summaryrefslogtreecommitdiff
path: root/tools/perf/scripts/python
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/scripts/python')
0 files changed, 0 insertions, 0 deletions
-rw-r--r--Documentation/DocBook/80211.tmpl5
-rw-r--r--Documentation/DocBook/kernel-hacking.tmpl2
-rw-r--r--Documentation/DocBook/v4l/io.xml2
-rw-r--r--Documentation/DocBook/writing-an-alsa-driver.tmpl10
-rw-r--r--Documentation/RCU/NMI-RCU.txt4
-rw-r--r--Documentation/SubmitChecklist4
-rw-r--r--Documentation/arm/Booting5
-rw-r--r--Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt42
-rw-r--r--Documentation/arm/Samsung-S3C24XX/Overview.txt7
-rw-r--r--Documentation/arm/kernel_user_helpers.txt267
-rw-r--r--Documentation/blackfin/bfin-spi-notes.txt2
-rw-r--r--Documentation/block/queue-sysfs.txt10
-rw-r--r--Documentation/blockdev/README.DAC9602
-rw-r--r--Documentation/blockdev/ramdisk.txt8
-rw-r--r--Documentation/cgroups/cpuacct.txt2
-rw-r--r--Documentation/cgroups/cpusets.txt2
-rw-r--r--Documentation/cgroups/memory.txt85
-rw-r--r--Documentation/cpu-freq/cpu-drivers.txt2
-rw-r--r--Documentation/development-process/4.Coding2
-rw-r--r--Documentation/devicetree/bindings/arm/pmu.txt21
-rw-r--r--Documentation/devicetree/bindings/arm/primecell.txt21
-rw-r--r--Documentation/devicetree/bindings/arm/sirf.txt3
-rw-r--r--Documentation/devicetree/bindings/arm/xilinx.txt7
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl-sec2.txt (renamed from Documentation/devicetree/bindings/powerpc/fsl/sec.txt)2
-rw-r--r--Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt22
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio.txt46
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio_nvidia.txt8
-rw-r--r--[-rwxr-xr-x]Documentation/devicetree/bindings/net/can/fsl-flexcan.txt0
-rw-r--r--Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt5
-rw-r--r--Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt22
-rw-r--r--Documentation/devicetree/bindings/spi/spi_nvidia.txt5
-rw-r--r--Documentation/devicetree/bindings/tty/serial/of-serial.txt36
-rw-r--r--Documentation/driver-model/device.txt2
-rw-r--r--Documentation/driver-model/overview.txt52
-rw-r--r--Documentation/fb/modedb.txt21
-rw-r--r--Documentation/feature-removal-schedule.txt80
-rw-r--r--Documentation/filesystems/Locking34
-rw-r--r--Documentation/filesystems/debugfs.txt4
-rw-r--r--Documentation/filesystems/ext3.txt13
-rw-r--r--Documentation/filesystems/ext4.txt23
-rw-r--r--Documentation/filesystems/nfs/Exporting9
-rw-r--r--Documentation/filesystems/nfs/nfs41-server.txt33
-rw-r--r--Documentation/filesystems/nfs/nfsroot.txt2
-rw-r--r--Documentation/filesystems/porting28
-rw-r--r--Documentation/filesystems/squashfs.txt4
-rw-r--r--Documentation/filesystems/ubifs.txt28
-rw-r--r--Documentation/filesystems/vfs.txt30
-rw-r--r--Documentation/hwmon/it873
-rw-r--r--Documentation/hwmon/lm783
-rw-r--r--Documentation/hwmon/sch563631
-rw-r--r--Documentation/i2o/ioctl2
-rw-r--r--Documentation/ioctl/ioctl-number.txt1
-rw-r--r--Documentation/isdn/README.HiSax2
-rw-r--r--Documentation/ja_JP/SubmitChecklist2
-rw-r--r--Documentation/ja_JP/SubmittingPatches258
-rw-r--r--Documentation/kbuild/makefiles.txt38
-rw-r--r--Documentation/kernel-parameters.txt22
-rw-r--r--Documentation/magic-number.txt2
-rw-r--r--Documentation/mca.txt4
-rw-r--r--Documentation/mmc/00-INDEX2
-rw-r--r--Documentation/mmc/mmc-async-req.txt87
-rw-r--r--Documentation/networking/ifenslave.c18
-rw-r--r--Documentation/networking/ip-sysctl.txt29
-rw-r--r--Documentation/networking/netdev-features.txt154
-rw-r--r--Documentation/networking/nfc.txt128
-rw-r--r--Documentation/networking/stmmac.txt200
-rw-r--r--Documentation/power/devices.txt14
-rw-r--r--Documentation/power/opp.txt2
-rw-r--r--Documentation/power/runtime_pm.txt229
-rw-r--r--Documentation/rbtree.txt23
-rw-r--r--Documentation/s390/TAPE122
-rw-r--r--Documentation/scheduler/sched-arch.txt2
-rw-r--r--Documentation/scsi/BusLogic.txt2
-rw-r--r--Documentation/serial/computone.txt2
-rw-r--r--Documentation/sound/alsa/HD-Audio-Controls.txt100
-rw-r--r--Documentation/spi/ep93xx_spi10
-rw-r--r--Documentation/spi/pxa2xx5
-rw-r--r--Documentation/sysctl/kernel.txt237
-rw-r--r--Documentation/trace/kprobetrace.txt9
-rw-r--r--Documentation/usb/ehci.txt2
-rw-r--r--Documentation/usb/gadget_hid.txt6
-rw-r--r--Documentation/vDSO/parse_vdso.c256
-rw-r--r--Documentation/vDSO/vdso_test.c111
-rw-r--r--Documentation/virtual/kvm/api.txt172
-rw-r--r--Documentation/virtual/kvm/mmu.txt18
-rw-r--r--Documentation/virtual/kvm/msr.txt34
-rw-r--r--Documentation/virtual/kvm/nested-vmx.txt251
-rw-r--r--Documentation/virtual/kvm/ppc-pv.txt8
-rw-r--r--Documentation/virtual/lguest/lguest.c47
-rw-r--r--Documentation/x86/entry_64.txt98
-rw-r--r--Documentation/zh_CN/SubmitChecklist2
-rw-r--r--Documentation/zh_CN/email-clients.txt210
-rw-r--r--Documentation/zh_CN/magic-number.txt2
-rw-r--r--MAINTAINERS238
-rw-r--r--Makefile1
-rw-r--r--arch/alpha/Kconfig1
-rw-r--r--arch/alpha/include/asm/8253pit.h3
-rw-r--r--arch/alpha/include/asm/atomic.h12
-rw-r--r--arch/alpha/include/asm/bitops.h3
-rw-r--r--arch/alpha/include/asm/floppy.h2
-rw-r--r--arch/alpha/include/asm/local.h2
-rw-r--r--arch/alpha/include/asm/ptrace.h1
-rw-r--r--arch/alpha/kernel/module.c34
-rw-r--r--arch/alpha/kernel/perf_event.c4
-rw-r--r--arch/alpha/kernel/process.c1
-rw-r--r--arch/alpha/kernel/smp.c2
-rw-r--r--arch/alpha/kernel/sys_ruffian.c1
-rw-r--r--arch/alpha/kernel/time.c3
-rw-r--r--arch/alpha/lib/dec_and_lock.c2
-rw-r--r--arch/arm/Kconfig104
-rw-r--r--arch/arm/Makefile7
-rw-r--r--arch/arm/boot/compressed/Makefile10
-rw-r--r--arch/arm/boot/compressed/head-shmobile.S12
-rw-r--r--arch/arm/boot/compressed/head.S3
-rw-r--r--arch/arm/boot/compressed/mmcif-sh7372.c2
-rw-r--r--arch/arm/boot/compressed/sdhi-sh7372.c95
-rw-r--r--arch/arm/boot/compressed/sdhi-shmobile.c449
-rw-r--r--arch/arm/boot/compressed/sdhi-shmobile.h11
-rw-r--r--arch/arm/boot/compressed/vmlinux.lds.in12
-rw-r--r--arch/arm/boot/dts/prima2-cb.dts416
-rw-r--r--arch/arm/boot/dts/zynq-ep107.dts52
-rw-r--r--arch/arm/common/dmabounce.c193
-rw-r--r--arch/arm/common/gic.c13
-rw-r--r--arch/arm/common/it8152.c16
-rw-r--r--arch/arm/common/sa1111.c60
-rw-r--r--arch/arm/common/scoop.c2
-rw-r--r--arch/arm/configs/cm_x300_defconfig18
-rw-r--r--arch/arm/configs/loki_defconfig120
-rw-r--r--arch/arm/configs/mmp2_defconfig9
-rw-r--r--arch/arm/configs/mx51_defconfig3
-rw-r--r--arch/arm/configs/mxs_defconfig4
-rw-r--r--arch/arm/configs/u8500_defconfig32
-rw-r--r--arch/arm/include/asm/assembler.h9
-rw-r--r--arch/arm/include/asm/atomic.h10
-rw-r--r--arch/arm/include/asm/bitops.h9
-rw-r--r--arch/arm/include/asm/clkdev.h5
-rw-r--r--arch/arm/include/asm/dma-mapping.h88
-rw-r--r--arch/arm/include/asm/dma.h11
-rw-r--r--arch/arm/include/asm/entry-macro-multi.S14
-rw-r--r--arch/arm/include/asm/hardware/gic.h6
-rw-r--r--arch/arm/include/asm/hardware/scoop.h1
-rw-r--r--arch/arm/include/asm/hwcap.h36
-rw-r--r--arch/arm/include/asm/i8253.h15
-rw-r--r--arch/arm/include/asm/irq.h1
-rw-r--r--arch/arm/include/asm/kprobes.h28
-rw-r--r--arch/arm/include/asm/mach/arch.h4
-rw-r--r--arch/arm/include/asm/memory.h12
-rw-r--r--arch/arm/include/asm/pci.h12
-rw-r--r--arch/arm/include/asm/perf_event.h2
-rw-r--r--arch/arm/include/asm/pmu.h2
-rw-r--r--arch/arm/include/asm/proc-fns.h14
-rw-r--r--arch/arm/include/asm/ptrace.h11
-rw-r--r--arch/arm/include/asm/scatterlist.h4
-rw-r--r--arch/arm/include/asm/setup.h8
-rw-r--r--arch/arm/include/asm/suspend.h22
-rw-r--r--arch/arm/include/asm/tcm.h2
-rw-r--r--arch/arm/include/asm/tlbflush.h58
-rw-r--r--arch/arm/include/asm/traps.h3
-rw-r--r--arch/arm/include/asm/vga.h5
-rw-r--r--arch/arm/kernel/Makefile7
-rw-r--r--arch/arm/kernel/asm-offsets.c3
-rw-r--r--arch/arm/kernel/entry-armv.S523
-rw-r--r--arch/arm/kernel/entry-header.S31
-rw-r--r--arch/arm/kernel/head-nommu.S8
-rw-r--r--arch/arm/kernel/head.S8
-rw-r--r--arch/arm/kernel/hw_breakpoint.c12
-rw-r--r--arch/arm/kernel/irq.c70
-rw-r--r--arch/arm/kernel/kprobes-arm.c999
-rw-r--r--arch/arm/kernel/kprobes-common.c577
-rw-r--r--arch/arm/kernel/kprobes-decode.c1670
-rw-r--r--arch/arm/kernel/kprobes-thumb.c1462
-rw-r--r--arch/arm/kernel/kprobes.c222
-rw-r--r--arch/arm/kernel/kprobes.h420
-rw-r--r--arch/arm/kernel/module.c29
-rw-r--r--arch/arm/kernel/perf_event.c10
-rw-r--r--arch/arm/kernel/perf_event_v6.c30
-rw-r--r--arch/arm/kernel/perf_event_v7.c374
-rw-r--r--arch/arm/kernel/perf_event_xscale.c18
-rw-r--r--arch/arm/kernel/pmu.c87
-rw-r--r--arch/arm/kernel/ptrace.c33
-rw-r--r--arch/arm/kernel/setup.c109
-rw-r--r--arch/arm/kernel/sleep.S84
-rw-r--r--arch/arm/kernel/smp.c13
-rw-r--r--arch/arm/kernel/smp_scu.c2
-rw-r--r--arch/arm/kernel/swp_emulate.c2
-rw-r--r--arch/arm/kernel/tcm.c68
-rw-r--r--arch/arm/kernel/traps.c19
-rw-r--r--arch/arm/kernel/vmlinux.lds.S126
-rw-r--r--arch/arm/lib/ecard.S1
-rw-r--r--arch/arm/lib/io-readsw-armv3.S1
-rw-r--r--arch/arm/lib/io-writesw-armv3.S1
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c2
-rw-r--r--arch/arm/mach-at91/board-snapper9260.c2
-rw-r--r--arch/arm/mach-at91/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-at91/pm.c2
-rw-r--r--arch/arm/mach-bcmring/dma.c4
-rw-r--r--arch/arm/mach-bcmring/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-bcmring/include/mach/entry-macro.S4
-rw-r--r--arch/arm/mach-bcmring/include/mach/hardware.h2
-rw-r--r--arch/arm/mach-cns3xxx/cns3420vb.c3
-rw-r--r--arch/arm/mach-cns3xxx/core.c43
-rw-r--r--arch/arm/mach-cns3xxx/core.h6
-rw-r--r--arch/arm/mach-cns3xxx/include/mach/hardware.h22
-rw-r--r--arch/arm/mach-cns3xxx/include/mach/pm.h2
-rw-r--r--arch/arm/mach-cns3xxx/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-cns3xxx/pcie.c3
-rw-r--r--arch/arm/mach-cns3xxx/pm.c2
-rw-r--r--arch/arm/mach-davinci/board-da830-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c8
-rw-r--r--arch/arm/mach-davinci/board-dm355-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-dm355-leopard.c1
-rw-r--r--arch/arm/mach-davinci/board-dm365-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-dm644x-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-dm646x-evm.c19
-rw-r--r--arch/arm/mach-davinci/board-mityomapl138.c2
-rw-r--r--arch/arm/mach-davinci/board-neuros-osd2.c1
-rw-r--r--arch/arm/mach-davinci/board-omapl138-hawk.c1
-rw-r--r--arch/arm/mach-davinci/board-sffsdr.c1
-rw-r--r--arch/arm/mach-davinci/board-tnetv107x-evm.c1
-rw-r--r--arch/arm/mach-davinci/clock.c46
-rw-r--r--arch/arm/mach-davinci/clock.h3
-rw-r--r--arch/arm/mach-davinci/da850.c10
-rw-r--r--arch/arm/mach-davinci/devices-da8xx.c126
-rw-r--r--arch/arm/mach-davinci/dm646x.c5
-rw-r--r--arch/arm/mach-davinci/include/mach/clkdev.h15
-rw-r--r--arch/arm/mach-davinci/include/mach/da8xx.h2
-rw-r--r--arch/arm/mach-davinci/include/mach/dm646x.h2
-rw-r--r--arch/arm/mach-davinci/include/mach/entry-macro.S3
-rw-r--r--arch/arm/mach-davinci/include/mach/memory.h7
-rw-r--r--arch/arm/mach-davinci/include/mach/psc.h151
-rw-r--r--arch/arm/mach-davinci/pm.c1
-rw-r--r--arch/arm/mach-davinci/psc.c14
-rw-r--r--arch/arm/mach-dove/common.c2
-rw-r--r--arch/arm/mach-dove/include/mach/hardware.h7
-rw-r--r--arch/arm/mach-dove/pcie.c3
-rw-r--r--arch/arm/mach-ep93xx/Makefile4
-rw-r--r--arch/arm/mach-ep93xx/core.c33
-rw-r--r--arch/arm/mach-ep93xx/dma-m2p.c411
-rw-r--r--arch/arm/mach-ep93xx/dma.c108
-rw-r--r--arch/arm/mach-ep93xx/include/mach/clkdev.h11
-rw-r--r--arch/arm/mach-ep93xx/include/mach/dma.h190
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h1
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h2
-rw-r--r--arch/arm/mach-ep93xx/include/mach/hardware.h2
-rw-r--r--arch/arm/mach-ep93xx/simone.c4
-rw-r--r--arch/arm/mach-ep93xx/snappercl15.c4
-rw-r--r--arch/arm/mach-exynos4/Kconfig34
-rw-r--r--arch/arm/mach-exynos4/Makefile12
-rw-r--r--arch/arm/mach-exynos4/clock.c238
-rw-r--r--arch/arm/mach-exynos4/cpu.c39
-rw-r--r--arch/arm/mach-exynos4/dev-audio.c2
-rw-r--r--arch/arm/mach-exynos4/dev-dwmci.c82
-rw-r--r--arch/arm/mach-exynos4/hotplug.c13
-rw-r--r--arch/arm/mach-exynos4/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-exynos4/include/mach/dwmci.h20
-rw-r--r--arch/arm/mach-exynos4/include/mach/entry-macro.S11
-rw-r--r--arch/arm/mach-exynos4/include/mach/irqs.h196
-rw-r--r--arch/arm/mach-exynos4/include/mach/map.h19
-rw-r--r--arch/arm/mach-exynos4/include/mach/pm-core.h10
-rw-r--r--arch/arm/mach-exynos4/include/mach/pmu.h25
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-audss.h18
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-clock.h12
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-pmu.h1
-rw-r--r--arch/arm/mach-exynos4/localtimer.c26
-rw-r--r--arch/arm/mach-exynos4/mach-nuri.c753
-rw-r--r--arch/arm/mach-exynos4/mach-smdkc210.c86
-rw-r--r--arch/arm/mach-exynos4/mach-smdkv310.c19
-rw-r--r--arch/arm/mach-exynos4/mach-universal_c210.c121
-rw-r--r--arch/arm/mach-exynos4/mct.c2
-rw-r--r--arch/arm/mach-exynos4/platsmp.c65
-rw-r--r--arch/arm/mach-exynos4/pm.c275
-rw-r--r--arch/arm/mach-exynos4/pmu.c175
-rw-r--r--arch/arm/mach-exynos4/setup-fimd0.c43
-rw-r--r--arch/arm/mach-exynos4/sleep.S22
-rw-r--r--arch/arm/mach-exynos4/time.c301
-rw-r--r--arch/arm/mach-footbridge/Kconfig1
-rw-r--r--arch/arm/mach-footbridge/dc21285.c3
-rw-r--r--arch/arm/mach-footbridge/include/mach/hardware.h5
-rw-r--r--arch/arm/mach-footbridge/isa-timer.c59
-rw-r--r--arch/arm/mach-h720x/h7201-eval.c1
-rw-r--r--arch/arm/mach-h720x/h7202-eval.c1
-rw-r--r--arch/arm/mach-h720x/include/mach/entry-macro.S3
-rw-r--r--arch/arm/mach-h720x/include/mach/memory.h7
-rw-r--r--arch/arm/mach-imx/Kconfig6
-rw-r--r--arch/arm/mach-imx/clock-imx25.c7
-rw-r--r--arch/arm/mach-imx/dma-v1.c26
-rw-r--r--arch/arm/mach-imx/eukrea_mbimx27-baseboard.c23
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c15
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c13
-rw-r--r--arch/arm/mach-imx/mach-apf9328.c9
-rw-r--r--arch/arm/mach-imx/mach-armadillo5x0.c2
-rw-r--r--arch/arm/mach-imx/mach-bug.c2
-rw-r--r--arch/arm/mach-imx/mach-cpuimx27.c2
-rw-r--r--arch/arm/mach-imx/mach-cpuimx35.c2
-rw-r--r--arch/arm/mach-imx/mach-eukrea_cpuimx25.c2
-rw-r--r--arch/arm/mach-imx/mach-imx27_visstrim_m10.c4
-rw-r--r--arch/arm/mach-imx/mach-imx27ipcam.c2
-rw-r--r--arch/arm/mach-imx/mach-imx27lite.c2
-rw-r--r--arch/arm/mach-imx/mach-kzm_arm11_01.c2
-rw-r--r--arch/arm/mach-imx/mach-mx1ads.c2
-rw-r--r--arch/arm/mach-imx/mach-mx21ads.c2
-rw-r--r--arch/arm/mach-imx/mach-mx25_3ds.c2
-rw-r--r--arch/arm/mach-imx/mach-mx27_3ds.c139
-rw-r--r--arch/arm/mach-imx/mach-mx27ads.c2
-rw-r--r--arch/arm/mach-imx/mach-mx31_3ds.c13
-rw-r--r--arch/arm/mach-imx/mach-mx31ads.c2
-rw-r--r--arch/arm/mach-imx/mach-mx31lilly.c2
-rw-r--r--arch/arm/mach-imx/mach-mx31lite.c2
-rw-r--r--arch/arm/mach-imx/mach-mx31moboard.c16
-rw-r--r--arch/arm/mach-imx/mach-mx35_3ds.c4
-rw-r--r--arch/arm/mach-imx/mach-mxt_td60.c2
-rw-r--r--arch/arm/mach-imx/mach-pca100.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm037.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm038.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c2
-rw-r--r--arch/arm/mach-imx/mach-qong.c2
-rw-r--r--arch/arm/mach-imx/mach-scb9328.c19
-rw-r--r--arch/arm/mach-imx/mach-vpr200.c2
-rw-r--r--arch/arm/mach-imx/mm-imx1.c21
-rw-r--r--arch/arm/mach-imx/mm-imx21.c24
-rw-r--r--arch/arm/mach-imx/mm-imx25.c42
-rw-r--r--arch/arm/mach-imx/mm-imx27.c25
-rw-r--r--arch/arm/mach-imx/mm-imx31.c42
-rw-r--r--arch/arm/mach-imx/mm-imx35.c63
-rw-r--r--arch/arm/mach-imx/mx31lite-db.c15
-rw-r--r--arch/arm/mach-integrator/include/mach/bits.h61
-rw-r--r--arch/arm/mach-integrator/include/mach/hardware.h7
-rw-r--r--arch/arm/mach-integrator/pci_v3.c5
-rw-r--r--arch/arm/mach-iop13xx/include/mach/hardware.h7
-rw-r--r--arch/arm/mach-iop13xx/pci.c5
-rw-r--r--arch/arm/mach-iop13xx/setup.c1
-rw-r--r--arch/arm/mach-iop32x/include/mach/hardware.h3
-rw-r--r--arch/arm/mach-iop33x/include/mach/hardware.h3
-rw-r--r--arch/arm/mach-ixp2000/include/mach/hardware.h8
-rw-r--r--arch/arm/mach-ixp2000/pci.c5
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/hardware.h4
-rw-r--r--arch/arm/mach-ixp23xx/pci.c5
-rw-r--r--arch/arm/mach-ixp4xx/avila-setup.c6
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c17
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/fsg-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/gateway7001-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/goramo_mlr.c3
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/hardware.h5
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/memory.h4
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c12
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/vulcan-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-setup.c3
-rw-r--r--arch/arm/mach-kirkwood/include/mach/hardware.h7
-rw-r--r--arch/arm/mach-kirkwood/pcie.c3
-rw-r--r--arch/arm/mach-ks8695/include/mach/hardware.h9
-rw-r--r--arch/arm/mach-ks8695/pci.c3
-rw-r--r--arch/arm/mach-loki/Kconfig13
-rw-r--r--arch/arm/mach-loki/Makefile3
-rw-r--r--arch/arm/mach-loki/addr-map.c122
-rw-r--r--arch/arm/mach-loki/common.c162
-rw-r--r--arch/arm/mach-loki/common.h37
-rw-r--r--arch/arm/mach-loki/include/mach/bridge-regs.h28
-rw-r--r--arch/arm/mach-loki/include/mach/debug-macro.S19
-rw-r--r--arch/arm/mach-loki/include/mach/entry-macro.S30
-rw-r--r--arch/arm/mach-loki/include/mach/hardware.h15
-rw-r--r--arch/arm/mach-loki/include/mach/io.h26
-rw-r--r--arch/arm/mach-loki/include/mach/irqs.h58
-rw-r--r--arch/arm/mach-loki/include/mach/loki.h83
-rw-r--r--arch/arm/mach-loki/include/mach/memory.h10
-rw-r--r--arch/arm/mach-loki/include/mach/system.h36
-rw-r--r--arch/arm/mach-loki/include/mach/timex.h11
-rw-r--r--arch/arm/mach-loki/include/mach/uncompress.h47
-rw-r--r--arch/arm/mach-loki/include/mach/vmalloc.h5
-rw-r--r--arch/arm/mach-loki/irq.c22
-rw-r--r--arch/arm/mach-loki/lb88rc8480-setup.c99
-rw-r--r--arch/arm/mach-lpc32xx/clock.c2
-rw-r--r--arch/arm/mach-lpc32xx/common.c42
-rw-r--r--arch/arm/mach-lpc32xx/common.h2
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/clkdev.h25
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/entry-macro.S4
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-mmp/Kconfig7
-rw-r--r--arch/arm/mach-mmp/Makefile1
-rw-r--r--arch/arm/mach-mmp/brownstone.c10
-rw-r--r--arch/arm/mach-mmp/clock.c15
-rw-r--r--arch/arm/mach-mmp/clock.h1
-rw-r--r--arch/arm/mach-mmp/gplugd.c189
-rw-r--r--arch/arm/mach-mmp/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-mmp/include/mach/mfp-gplugd.h52
-rw-r--r--arch/arm/mach-mmp/include/mach/mfp-pxa168.h19
-rw-r--r--arch/arm/mach-mmp/include/mach/mmp2.h2
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa168.h8
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-apmu.h1
-rw-r--r--arch/arm/mach-mmp/jasper.c2
-rw-r--r--arch/arm/mach-mmp/mmp2.c16
-rw-r--r--arch/arm/mach-mmp/pxa168.c6
-rw-r--r--arch/arm/mach-mmp/ttc_dkb.c31
-rw-r--r--arch/arm/mach-msm/Kconfig19
-rw-r--r--arch/arm/mach-msm/Makefile2
-rw-r--r--arch/arm/mach-msm/platsmp.c19
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/hardware.h7
-rw-r--r--arch/arm/mach-mv78xx0/pcie.c11
-rw-r--r--arch/arm/mach-mx5/Kconfig18
-rw-r--r--arch/arm/mach-mx5/Makefile2
-rw-r--r--arch/arm/mach-mx5/board-cpuimx51.c14
-rw-r--r--arch/arm/mach-mx5/board-cpuimx51sd.c2
-rw-r--r--arch/arm/mach-mx5/board-mx50_rdp.c2
-rw-r--r--arch/arm/mach-mx5/board-mx51_3ds.c5
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c58
-rw-r--r--arch/arm/mach-mx5/board-mx51_efikamx.c17
-rw-r--r--arch/arm/mach-mx5/board-mx51_efikasb.c18
-rw-r--r--arch/arm/mach-mx5/board-mx53_ard.c254
-rw-r--r--arch/arm/mach-mx5/board-mx53_evk.c19
-rw-r--r--arch/arm/mach-mx5/board-mx53_loco.c37
-rw-r--r--arch/arm/mach-mx5/board-mx53_smd.c2
-rw-r--r--arch/arm/mach-mx5/clock-mx51-mx53.c33
-rw-r--r--arch/arm/mach-mx5/crm_regs.h2
-rw-r--r--arch/arm/mach-mx5/devices-imx53.h8
-rw-r--r--arch/arm/mach-mx5/devices.c64
-rw-r--r--arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c24
-rw-r--r--arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c19
-rw-r--r--arch/arm/mach-mx5/mm-mx50.c22
-rw-r--r--arch/arm/mach-mx5/mm.c71
-rw-r--r--arch/arm/mach-mx5/pm-imx5.c73
-rw-r--r--arch/arm/mach-mxs/Kconfig3
-rw-r--r--arch/arm/mach-mxs/Makefile2
-rw-r--r--arch/arm/mach-mxs/devices.c11
-rw-r--r--arch/arm/mach-mxs/devices/Makefile1
-rw-r--r--arch/arm/mach-mxs/devices/platform-auart.c1
-rw-r--r--arch/arm/mach-mxs/devices/platform-dma.c1
-rw-r--r--arch/arm/mach-mxs/devices/platform-fec.c1
-rw-r--r--arch/arm/mach-mxs/devices/platform-gpio-mxs.c53
-rw-r--r--arch/arm/mach-mxs/devices/platform-mxsfb.c1
-rw-r--r--arch/arm/mach-mxs/gpio.c331
-rw-r--r--arch/arm/mach-mxs/gpio.h34
-rw-r--r--arch/arm/mach-mxs/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-mxs/include/mach/devices-common.h2
-rw-r--r--arch/arm/mach-mxs/include/mach/dma.h2
-rw-r--r--arch/arm/mach-mxs/mach-mx28evk.c22
-rw-r--r--arch/arm/mach-mxs/mach-tx28.c19
-rw-r--r--arch/arm/mach-mxs/mm-mx23.c1
-rw-r--r--arch/arm/mach-mxs/mm-mx28.c1
-rw-r--r--arch/arm/mach-nomadik/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-nuc93x/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-nuc93x/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c4
-rw-r--r--arch/arm/mach-omap1/board-fsample.c4
-rw-r--r--arch/arm/mach-omap1/board-generic.c4
-rw-r--r--arch/arm/mach-omap1/board-h2.c4
-rw-r--r--arch/arm/mach-omap1/board-h3.c4
-rw-r--r--arch/arm/mach-omap1/board-htcherald.c4
-rw-r--r--arch/arm/mach-omap1/board-innovator.c4
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c4
-rw-r--r--arch/arm/mach-omap1/board-osk.c4
-rw-r--r--arch/arm/mach-omap1/board-palmte.c4
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c4
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c4
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c4
-rw-r--r--arch/arm/mach-omap1/board-sx1.c4
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c4
-rw-r--r--arch/arm/mach-omap1/gpio15xx.c22
-rw-r--r--arch/arm/mach-omap1/gpio16xx.c28
-rw-r--r--arch/arm/mach-omap1/gpio7xx.c27
-rw-r--r--arch/arm/mach-omap1/include/mach/clkdev.h5
-rw-r--r--arch/arm/mach-omap1/irq.c2
-rw-r--r--arch/arm/mach-omap1/mcbsp.c4
-rw-r--r--arch/arm/mach-omap1/pm.c2
-rw-r--r--arch/arm/mach-omap1/pm_bus.c14
-rw-r--r--arch/arm/mach-omap1/time.c6
-rw-r--r--arch/arm/mach-omap1/timer32k.c4
-rw-r--r--arch/arm/mach-omap2/Kconfig6
-rw-r--r--arch/arm/mach-omap2/Makefile20
-rw-r--r--arch/arm/mach-omap2/board-2430sdp.c4
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c93
-rw-r--r--arch/arm/mach-omap2/board-3630sdp.c4
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c341
-rw-r--r--arch/arm/mach-omap2/board-am3517crane.c4
-rw-r--r--arch/arm/mach-omap2/board-am3517evm.c4
-rw-r--r--arch/arm/mach-omap2/board-apollon.c4
-rw-r--r--arch/arm/mach-omap2/board-cm-t35.c176
-rw-r--r--arch/arm/mach-omap2/board-cm-t3517.c5
-rw-r--r--arch/arm/mach-omap2/board-devkit8000.c64
-rw-r--r--arch/arm/mach-omap2/board-flash.c4
-rw-r--r--arch/arm/mach-omap2/board-generic.c4
-rw-r--r--arch/arm/mach-omap2/board-h4.c4
-rw-r--r--arch/arm/mach-omap2/board-igep0020.c79
-rw-r--r--arch/arm/mach-omap2/board-ldp.c29
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c12
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c167
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c111
-rw-r--r--arch/arm/mach-omap2/board-omap3logic.c19
-rw-r--r--arch/arm/mach-omap2/board-omap3pandora.c119
-rw-r--r--arch/arm/mach-omap2/board-omap3stalker.c99
-rw-r--r--arch/arm/mach-omap2/board-omap3touchbook.c97
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c161
-rw-r--r--arch/arm/mach-omap2/board-overo.c84
-rw-r--r--arch/arm/mach-omap2/board-rm680.c12
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c194
-rw-r--r--arch/arm/mach-omap2/board-rx51.c4
-rw-r--r--arch/arm/mach-omap2/board-ti8168evm.c9
-rw-r--r--arch/arm/mach-omap2/board-zoom-debugboard.c9
-rw-r--r--arch/arm/mach-omap2/board-zoom-peripherals.c128
-rw-r--r--arch/arm/mach-omap2/board-zoom.c8
-rw-r--r--arch/arm/mach-omap2/clock.c28
-rw-r--r--arch/arm/mach-omap2/clock.h3
-rw-r--r--arch/arm/mach-omap2/clock2420_data.c22
-rw-r--r--arch/arm/mach-omap2/clock2430_data.c32
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c44
-rw-r--r--arch/arm/mach-omap2/clock44xx.h7
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c490
-rw-r--r--arch/arm/mach-omap2/clockdomain.c210
-rw-r--r--arch/arm/mach-omap2/clockdomain.h11
-rw-r--r--arch/arm/mach-omap2/clockdomain2xxx_3xxx.c6
-rw-r--r--arch/arm/mach-omap2/clockdomain44xx.c13
-rw-r--r--arch/arm/mach-omap2/clockdomains44xx_data.c124
-rw-r--r--arch/arm/mach-omap2/cm-regbits-44xx.h659
-rw-r--r--arch/arm/mach-omap2/cm1_44xx.h64
-rw-r--r--arch/arm/mach-omap2/cm2_44xx.h73
-rw-r--r--arch/arm/mach-omap2/cm44xx.h8
-rw-r--r--arch/arm/mach-omap2/cminst44xx.c150
-rw-r--r--arch/arm/mach-omap2/cminst44xx.h10
-rw-r--r--arch/arm/mach-omap2/common-board-devices.c27
-rw-r--r--arch/arm/mach-omap2/common-board-devices.h26
-rw-r--r--arch/arm/mach-omap2/control.c7
-rw-r--r--arch/arm/mach-omap2/control.h6
-rw-r--r--arch/arm/mach-omap2/devices.c3
-rw-r--r--arch/arm/mach-omap2/gpio.c34
-rw-r--r--arch/arm/mach-omap2/gpmc-nand.c10
-rw-r--r--arch/arm/mach-omap2/hsmmc.c7
-rw-r--r--arch/arm/mach-omap2/i2c.c68
-rw-r--r--arch/arm/mach-omap2/id.c53
-rw-r--r--arch/arm/mach-omap2/include/mach/clkdev.h5
-rw-r--r--arch/arm/mach-omap2/include/mach/entry-macro.S3
-rw-r--r--arch/arm/mach-omap2/io.c17
-rw-r--r--arch/arm/mach-omap2/iommu2.c4
-rw-r--r--arch/arm/mach-omap2/irq.c32
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c2
-rw-r--r--arch/arm/mach-omap2/omap-smp.c8
-rw-r--r--arch/arm/mach-omap2/omap4-common.c10
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c404
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c841
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c917
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c173
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c322
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c130
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c150
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c672
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c959
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_data.c20
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_data.h93
-rw-r--r--arch/arm/mach-omap2/pm-debug.c372
-rw-r--r--arch/arm/mach-omap2/pm.c6
-rw-r--r--arch/arm/mach-omap2/pm.h38
-rw-r--r--arch/arm/mach-omap2/pm24xx.c6
-rw-r--r--arch/arm/mach-omap2/pm34xx.c86
-rw-r--r--arch/arm/mach-omap2/powerdomains44xx_data.c27
-rw-r--r--arch/arm/mach-omap2/prcm.c2
-rw-r--r--arch/arm/mach-omap2/prcm_mpu44xx.h69
-rw-r--r--arch/arm/mach-omap2/prm-regbits-44xx.h8
-rw-r--r--arch/arm/mach-omap2/prm44xx.c145
-rw-r--r--arch/arm/mach-omap2/prm44xx.h44
-rw-r--r--arch/arm/mach-omap2/prminst44xx.c112
-rw-r--r--arch/arm/mach-omap2/prminst44xx.h12
-rw-r--r--arch/arm/mach-omap2/serial.c1
-rw-r--r--arch/arm/mach-omap2/sleep34xx.S518
-rw-r--r--arch/arm/mach-omap2/smartreflex.c38
-rw-r--r--arch/arm/mach-omap2/timer-gp.c266
-rw-r--r--arch/arm/mach-omap2/timer-gp.h16
-rw-r--r--arch/arm/mach-omap2/timer.c342
-rw-r--r--arch/arm/mach-omap2/twl-common.c304
-rw-r--r--arch/arm/mach-omap2/twl-common.h59
-rw-r--r--arch/arm/mach-omap2/usb-musb.c10
-rw-r--r--arch/arm/mach-orion5x/include/mach/hardware.h7
-rw-r--r--arch/arm/mach-orion5x/mpp.c2
-rw-r--r--arch/arm/mach-orion5x/pci.c2
-rw-r--r--arch/arm/mach-pnx4008/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-pnx4008/include/mach/entry-macro.S5
-rw-r--r--arch/arm/mach-prima2/Makefile7
-rw-r--r--arch/arm/mach-prima2/Makefile.boot3
-rw-r--r--arch/arm/mach-prima2/clock.c509
-rw-r--r--arch/arm/mach-prima2/common.h26
-rw-r--r--arch/arm/mach-prima2/include/mach/clkdev.h15
-rw-r--r--arch/arm/mach-prima2/include/mach/debug-macro.S29
-rw-r--r--arch/arm/mach-prima2/include/mach/entry-macro.S29
-rw-r--r--arch/arm/mach-prima2/include/mach/hardware.h15
-rw-r--r--arch/arm/mach-prima2/include/mach/io.h16
-rw-r--r--arch/arm/mach-prima2/include/mach/irqs.h17
-rw-r--r--arch/arm/mach-prima2/include/mach/map.h16
-rw-r--r--arch/arm/mach-prima2/include/mach/memory.h21
-rw-r--r--arch/arm/mach-prima2/include/mach/system.h29
-rw-r--r--arch/arm/mach-prima2/include/mach/timex.h14
-rw-r--r--arch/arm/mach-prima2/include/mach/uart.h23
-rw-r--r--arch/arm/mach-prima2/include/mach/uncompress.h40
-rw-r--r--arch/arm/mach-prima2/include/mach/vmalloc.h16
-rw-r--r--arch/arm/mach-prima2/irq.c71
-rw-r--r--arch/arm/mach-prima2/l2x0.c59
-rw-r--r--arch/arm/mach-prima2/lluart.c25
-rw-r--r--arch/arm/mach-prima2/prima2.c41
-rw-r--r--arch/arm/mach-prima2/rstc.c69
-rw-r--r--arch/arm/mach-prima2/timer.c217
-rw-r--r--arch/arm/mach-pxa/balloon3.c1
-rw-r--r--arch/arm/mach-pxa/capc7117.c1
-rw-r--r--arch/arm/mach-pxa/clock.c15
-rw-r--r--arch/arm/mach-pxa/clock.h1
-rw-r--r--arch/arm/mach-pxa/cm-x2xx-pci.c3
-rw-r--r--arch/arm/mach-pxa/cm-x2xx.c8
-rw-r--r--arch/arm/mach-pxa/cm-x300.c59
-rw-r--r--arch/arm/mach-pxa/colibri-pxa270.c2
-rw-r--r--arch/arm/mach-pxa/colibri-pxa300.c1
-rw-r--r--arch/arm/mach-pxa/colibri-pxa320.c4
-rw-r--r--arch/arm/mach-pxa/corgi.c3
-rw-r--r--arch/arm/mach-pxa/csb726.c4
-rw-r--r--arch/arm/mach-pxa/em-x270.c2
-rw-r--r--arch/arm/mach-pxa/eseries.c6
-rw-r--r--arch/arm/mach-pxa/ezx.c6
-rw-r--r--arch/arm/mach-pxa/generic.h13
-rw-r--r--arch/arm/mach-pxa/gumstix.c1
-rw-r--r--arch/arm/mach-pxa/h5000.c2
-rw-r--r--arch/arm/mach-pxa/himalaya.c4
-rw-r--r--arch/arm/mach-pxa/hx4700.c71
-rw-r--r--arch/arm/mach-pxa/icontrol.c1
-rw-r--r--arch/arm/mach-pxa/idp.c1
-rw-r--r--arch/arm/mach-pxa/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-pxa/include/mach/corgi.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/hardware.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/irqs.h12
-rw-r--r--arch/arm/mach-pxa/include/mach/magician.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/memory.h4
-rw-r--r--arch/arm/mach-pxa/include/mach/pm.h4
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa25x.h9
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa27x-udc.h4
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa27x.h5
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa300.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa320.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa3xx.h14
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa930.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/regs-intc.h30
-rw-r--r--arch/arm/mach-pxa/irq.c36
-rw-r--r--arch/arm/mach-pxa/littleton.c1
-rw-r--r--arch/arm/mach-pxa/lpd270.c1
-rw-r--r--arch/arm/mach-pxa/lubbock.c1
-rw-r--r--arch/arm/mach-pxa/magician.c58
-rw-r--r--arch/arm/mach-pxa/mainstone.c1
-rw-r--r--arch/arm/mach-pxa/mioa701.c71
-rw-r--r--arch/arm/mach-pxa/mp900.c1
-rw-r--r--arch/arm/mach-pxa/palmld.c1
-rw-r--r--arch/arm/mach-pxa/palmt5.c1
-rw-r--r--arch/arm/mach-pxa/palmtc.c4
-rw-r--r--arch/arm/mach-pxa/palmte2.c3
-rw-r--r--arch/arm/mach-pxa/palmtreo.c2
-rw-r--r--arch/arm/mach-pxa/palmtx.c1
-rw-r--r--arch/arm/mach-pxa/palmz72.c2
-rw-r--r--arch/arm/mach-pxa/pcm027.c1
-rw-r--r--arch/arm/mach-pxa/pm.c1
-rw-r--r--arch/arm/mach-pxa/poodle.c1
-rw-r--r--arch/arm/mach-pxa/pxa25x.c3
-rw-r--r--arch/arm/mach-pxa/pxa27x.c11
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c19
-rw-r--r--arch/arm/mach-pxa/pxa95x.c1
-rw-r--r--arch/arm/mach-pxa/raumfeld.c8
-rw-r--r--arch/arm/mach-pxa/saar.c1
-rw-r--r--arch/arm/mach-pxa/saarb.c3
-rw-r--r--arch/arm/mach-pxa/sleep.S55
-rw-r--r--arch/arm/mach-pxa/spitz.c3
-rw-r--r--arch/arm/mach-pxa/stargate2.c2
-rw-r--r--arch/arm/mach-pxa/tavorevb.c1
-rw-r--r--arch/arm/mach-pxa/tavorevb3.c1
-rw-r--r--arch/arm/mach-pxa/tosa.c1
-rw-r--r--arch/arm/mach-pxa/trizeps4.c2
-rw-r--r--arch/arm/mach-pxa/viper.c1
-rw-r--r--arch/arm/mach-pxa/vpac270.c1
-rw-r--r--arch/arm/mach-pxa/xcep.c4
-rw-r--r--arch/arm/mach-pxa/z2.c18
-rw-r--r--arch/arm/mach-pxa/zeus.c7
-rw-r--r--arch/arm/mach-pxa/zylonite.c3
-rw-r--r--arch/arm/mach-realview/Kconfig1
-rw-r--r--arch/arm/mach-realview/include/mach/memory.h4
-rw-r--r--arch/arm/mach-realview/platsmp.c8
-rw-r--r--arch/arm/mach-realview/realview_eb.c3
-rw-r--r--arch/arm/mach-realview/realview_pb1176.c3
-rw-r--r--arch/arm/mach-realview/realview_pb11mp.c3
-rw-r--r--arch/arm/mach-realview/realview_pba8.c3
-rw-r--r--arch/arm/mach-realview/realview_pbx.c3
-rw-r--r--arch/arm/mach-s3c2400/Kconfig7
-rw-r--r--arch/arm/mach-s3c2400/Makefile15
-rw-r--r--arch/arm/mach-s3c2400/gpio.c42
-rw-r--r--arch/arm/mach-s3c2400/include/mach/map.h66
-rw-r--r--arch/arm/mach-s3c2410/h1940-bluetooth.c1
-rw-r--r--arch/arm/mach-s3c2410/include/mach/gpio-fns.h6
-rw-r--r--arch/arm/mach-s3c2410/include/mach/pm-core.h3
-rw-r--r--arch/arm/mach-s3c2410/include/mach/regs-gpio.h241
-rw-r--r--arch/arm/mach-s3c2410/include/mach/regs-mem.h28
-rw-r--r--arch/arm/mach-s3c2410/include/mach/spi-gpio.h28
-rw-r--r--arch/arm/mach-s3c2410/mach-qt2410.c34
-rw-r--r--arch/arm/mach-s3c2412/Kconfig2
-rw-r--r--arch/arm/mach-s3c2412/clock.c36
-rw-r--r--arch/arm/mach-s3c2412/mach-jive.c41
-rw-r--r--arch/arm/mach-s3c2412/pm.c6
-rw-r--r--arch/arm/mach-s3c2416/clock.c10
-rw-r--r--arch/arm/mach-s3c2416/pm.c6
-rw-r--r--arch/arm/mach-s3c2440/clock.c5
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c1
-rw-r--r--arch/arm/mach-s3c2440/s3c2442.c2
-rw-r--r--arch/arm/mach-s3c2440/s3c244x-clock.c2
-rw-r--r--arch/arm/mach-s3c2443/clock.c16
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/debug-macro.S27
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/io.h18
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/irqs.h117
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/map.h86
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/memory.h21
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/regs-clock.h88
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/regs-irq.h25
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/system.h25
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/tick.h15
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/timex.h18
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/vmalloc.h17
-rw-r--r--arch/arm/mach-s3c64xx/Kconfig24
-rw-r--r--arch/arm/mach-s3c64xx/Makefile5
-rw-r--r--arch/arm/mach-s3c64xx/clock.c86
-rw-r--r--arch/arm/mach-s3c64xx/dev-onenand1.c10
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/irqs.h5
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/pm-core.h19
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/regs-fb.h21
-rw-r--r--arch/arm/mach-s3c64xx/irq.c12
-rw-r--r--arch/arm/mach-s3c64xx/mach-anw6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c774
-rw-r--r--arch/arm/mach-s3c64xx/mach-hmt.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-mini6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-ncp.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-real6410.c2
-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-smdk6410.c43
-rw-r--r--arch/arm/mach-s3c64xx/pm.c2
-rw-r--r--arch/arm/mach-s3c64xx/setup-fb-24bpp.c1
-rw-r--r--arch/arm/mach-s3c64xx/sleep.S23
-rw-r--r--arch/arm/mach-s5p64x0/Kconfig2
-rw-r--r--arch/arm/mach-s5p64x0/Makefile2
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6440.c74
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6450.c68
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-gpio.h10
-rw-r--r--arch/arm/mach-s5p64x0/irq-eint.c152
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6440.c54
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6450.c54
-rw-r--r--arch/arm/mach-s5pc100/Kconfig1
-rw-r--r--arch/arm/mach-s5pc100/clock.c200
-rw-r--r--arch/arm/mach-s5pc100/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-s5pc100/include/mach/regs-fb.h105
-rw-r--r--arch/arm/mach-s5pc100/mach-smdkc100.c57
-rw-r--r--arch/arm/mach-s5pc100/setup-fb-24bpp.c1
-rw-r--r--arch/arm/mach-s5pv210/Kconfig2
-rw-r--r--arch/arm/mach-s5pv210/Makefile1
-rw-r--r--arch/arm/mach-s5pv210/clock.c174
-rw-r--r--arch/arm/mach-s5pv210/cpu.c2
-rw-r--r--arch/arm/mach-s5pv210/dev-audio.c2
-rw-r--r--arch/arm/mach-s5pv210/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-s5pv210/include/mach/map.h3
-rw-r--r--arch/arm/mach-s5pv210/include/mach/pm-core.h3
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-audss.h18
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-fb.h21
-rw-r--r--arch/arm/mach-s5pv210/mach-aquila.c2
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c12
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c57
-rw-r--r--arch/arm/mach-s5pv210/pm.c2
-rw-r--r--arch/arm/mach-s5pv210/setup-fb-24bpp.c1
-rw-r--r--arch/arm/mach-s5pv210/sleep.S21
-rw-r--r--arch/arm/mach-sa1100/assabet.c3
-rw-r--r--arch/arm/mach-sa1100/badge4.c3
-rw-r--r--arch/arm/mach-sa1100/include/mach/hardware.h8
-rw-r--r--arch/arm/mach-sa1100/include/mach/memory.h4
-rw-r--r--arch/arm/mach-sa1100/jornada720.c3
-rw-r--r--arch/arm/mach-sa1100/pci-nanoengine.c3
-rw-r--r--arch/arm/mach-sa1100/pm.c7
-rw-r--r--arch/arm/mach-sa1100/sleep.S19
-rw-r--r--arch/arm/mach-shark/core.c1
-rw-r--r--arch/arm/mach-shark/include/mach/entry-macro.S10
-rw-r--r--arch/arm/mach-shark/include/mach/hardware.h6
-rw-r--r--arch/arm/mach-shark/include/mach/memory.h2
-rw-r--r--arch/arm/mach-shark/pci.c12
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c7
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c5
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c1
-rw-r--r--arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h21
-rw-r--r--arch/arm/mach-shmobile/include/mach/sdhi.h16
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h29
-rw-r--r--arch/arm/mach-shmobile/platsmp.c5
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c160
-rw-r--r--arch/arm/mach-shmobile/pm_runtime.c22
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c11
-rw-r--r--arch/arm/mach-spear3xx/include/mach/clkdev.h19
-rw-r--r--arch/arm/mach-spear6xx/include/mach/clkdev.h19
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/board-harmony.c22
-rw-r--r--arch/arm/mach-tegra/board-paz00-pinmux.c10
-rw-r--r--arch/arm/mach-tegra/board-paz00.c31
-rw-r--r--arch/arm/mach-tegra/board-paz00.h10
-rw-r--r--arch/arm/mach-tegra/board-seaboard.c28
-rw-r--r--arch/arm/mach-tegra/board-trimslice-pinmux.c9
-rw-r--r--arch/arm/mach-tegra/board-trimslice.c56
-rw-r--r--arch/arm/mach-tegra/board-trimslice.h3
-rw-r--r--arch/arm/mach-tegra/clock.c7
-rw-r--r--arch/arm/mach-tegra/devices.c53
-rw-r--r--arch/arm/mach-tegra/include/mach/barriers.h30
-rw-r--r--arch/arm/mach-tegra/include/mach/system.h1
-rw-r--r--arch/arm/mach-tegra/io.c1
-rw-r--r--arch/arm/mach-tegra/pcie.c2
-rw-r--r--arch/arm/mach-tegra/platsmp.c11
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c4
-rw-r--r--arch/arm/mach-u300/core.c2
-rw-r--r--arch/arm/mach-u300/spi.c4
-rw-r--r--arch/arm/mach-u300/timer.c33
-rw-r--r--arch/arm/mach-ux500/Kconfig15
-rw-r--r--arch/arm/mach-ux500/board-mop500-pins.c43
-rw-r--r--arch/arm/mach-ux500/board-mop500-regulators.c11
-rw-r--r--arch/arm/mach-ux500/board-mop500-sdi.c61
-rw-r--r--arch/arm/mach-ux500/board-mop500-u8500uib.c24
-rw-r--r--arch/arm/mach-ux500/board-mop500-uib.c2
-rw-r--r--arch/arm/mach-ux500/board-mop500.c154
-rw-r--r--arch/arm/mach-ux500/board-mop500.h5
-rw-r--r--arch/arm/mach-ux500/board-u5500.c84
-rw-r--r--arch/arm/mach-ux500/clock.c79
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c1
-rw-r--r--arch/arm/mach-ux500/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-ux500/include/mach/uncompress.h3
-rw-r--r--arch/arm/mach-ux500/platsmp.c8
-rw-r--r--arch/arm/mach-ux500/usb.c1
-rw-r--r--arch/arm/mach-versatile/include/mach/hardware.h6
-rw-r--r--arch/arm/mach-versatile/pci.c3
-rw-r--r--arch/arm/mach-vexpress/ct-ca9x4.c4
-rw-r--r--arch/arm/mach-w90x900/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-zynq/Makefile6
-rw-r--r--arch/arm/mach-zynq/Makefile.boot (renamed from arch/arm/mach-loki/Makefile.boot)0
-rw-r--r--arch/arm/mach-zynq/board_dt.c0
-rw-r--r--arch/arm/mach-zynq/common.c118
-rw-r--r--arch/arm/mach-zynq/common.h (renamed from arch/arm/mach-tegra/include/mach/hardware.h)20
-rw-r--r--arch/arm/mach-zynq/include/mach/clkdev.h32
-rw-r--r--arch/arm/mach-zynq/include/mach/debug-macro.S36
-rw-r--r--arch/arm/mach-zynq/include/mach/entry-macro.S30
-rw-r--r--arch/arm/mach-zynq/include/mach/hardware.h18
-rw-r--r--arch/arm/mach-zynq/include/mach/io.h33
-rw-r--r--arch/arm/mach-zynq/include/mach/irqs.h21
-rw-r--r--arch/arm/mach-zynq/include/mach/memory.h22
-rw-r--r--arch/arm/mach-zynq/include/mach/system.h (renamed from arch/arm/mach-tegra/include/mach/clkdev.h)22
-rw-r--r--arch/arm/mach-zynq/include/mach/timex.h23
-rw-r--r--arch/arm/mach-zynq/include/mach/uart.h25
-rw-r--r--arch/arm/mach-zynq/include/mach/uncompress.h51
-rw-r--r--arch/arm/mach-zynq/include/mach/vmalloc.h20
-rw-r--r--arch/arm/mach-zynq/include/mach/zynq_soc.h48
-rw-r--r--arch/arm/mach-zynq/timer.c298
-rw-r--r--arch/arm/mm/Kconfig3
-rw-r--r--arch/arm/mm/abort-ev4.S17
-rw-r--r--arch/arm/mm/abort-ev4t.S17
-rw-r--r--arch/arm/mm/abort-ev5t.S19
-rw-r--r--arch/arm/mm/abort-ev5tj.S25
-rw-r--r--arch/arm/mm/abort-ev6.S25
-rw-r--r--arch/arm/mm/abort-ev7.S25
-rw-r--r--arch/arm/mm/abort-lv4t.S141
-rw-r--r--arch/arm/mm/abort-macro.S34
-rw-r--r--arch/arm/mm/abort-nommu.S10
-rw-r--r--arch/arm/mm/alignment.c3
-rw-r--r--arch/arm/mm/cache-fa.S15
-rw-r--r--arch/arm/mm/cache-v3.S15
-rw-r--r--arch/arm/mm/cache-v4.S15
-rw-r--r--arch/arm/mm/cache-v4wb.S15
-rw-r--r--arch/arm/mm/cache-v4wt.S15
-rw-r--r--arch/arm/mm/cache-v6.S15
-rw-r--r--arch/arm/mm/cache-v7.S15
-rw-r--r--arch/arm/mm/copypage-v6.c1
-rw-r--r--arch/arm/mm/dma-mapping.c35
-rw-r--r--arch/arm/mm/fault.c12
-rw-r--r--arch/arm/mm/init.c47
-rw-r--r--arch/arm/mm/iomap.c12
-rw-r--r--arch/arm/mm/mm.h6
-rw-r--r--arch/arm/mm/pabort-legacy.S10
-rw-r--r--arch/arm/mm/pabort-v6.S10
-rw-r--r--arch/arm/mm/pabort-v7.S11
-rw-r--r--arch/arm/mm/proc-arm1020.S45
-rw-r--r--arch/arm/mm/proc-arm1020e.S52
-rw-r--r--arch/arm/mm/proc-arm1022.S52
-rw-r--r--arch/arm/mm/proc-arm1026.S53
-rw-r--r--arch/arm/mm/proc-arm6_7.S256
-rw-r--r--arch/arm/mm/proc-arm720.S85
-rw-r--r--arch/arm/mm/proc-arm740.S42
-rw-r--r--arch/arm/mm/proc-arm7tdmi.S216
-rw-r--r--arch/arm/mm/proc-arm920.S56
-rw-r--r--arch/arm/mm/proc-arm922.S53
-rw-r--r--arch/arm/mm/proc-arm925.S88
-rw-r--r--arch/arm/mm/proc-arm926.S54
-rw-r--r--arch/arm/mm/proc-arm940.S51
-rw-r--r--arch/arm/mm/proc-arm946.S53
-rw-r--r--arch/arm/mm/proc-arm9tdmi.S78
-rw-r--r--arch/arm/mm/proc-fa526.S38
-rw-r--r--arch/arm/mm/proc-feroceon.S202
-rw-r--r--arch/arm/mm/proc-macros.S68
-rw-r--r--arch/arm/mm/proc-mohawk.S61
-rw-r--r--arch/arm/mm/proc-sa110.S39
-rw-r--r--arch/arm/mm/proc-sa1100.S91
-rw-r--r--arch/arm/mm/proc-v6.S42
-rw-r--r--arch/arm/mm/proc-v7.S139
-rw-r--r--arch/arm/mm/proc-xsc3.S94
-rw-r--r--arch/arm/mm/proc-xscale.S510
-rw-r--r--arch/arm/mm/tlb-fa.S12
-rw-r--r--arch/arm/mm/tlb-v3.S8
-rw-r--r--arch/arm/mm/tlb-v4.S8
-rw-r--r--arch/arm/mm/tlb-v4wb.S8
-rw-r--r--arch/arm/mm/tlb-v4wbi.S8
-rw-r--r--arch/arm/mm/tlb-v6.S12
-rw-r--r--arch/arm/mm/tlb-v7.S15
-rw-r--r--arch/arm/plat-iop/pci.c3
-rw-r--r--arch/arm/plat-mxc/Makefile2
-rw-r--r--arch/arm/plat-mxc/avic.c12
-rw-r--r--arch/arm/plat-mxc/devices.c25
-rw-r--r--arch/arm/plat-mxc/devices/Makefile1
-rw-r--r--arch/arm/plat-mxc/devices/platform-fec.c1
-rw-r--r--arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c1
-rw-r--r--arch/arm/plat-mxc/devices/platform-gpio-mxc.c32
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-dma.c204
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-fb.c1
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-i2c.c3
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-keypad.c5
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-ssi.c12
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-uart.c2
-rw-r--r--arch/arm/plat-mxc/devices/platform-ipu-core.c1
-rw-r--r--arch/arm/plat-mxc/devices/platform-mxc-ehci.c1
-rw-r--r--arch/arm/plat-mxc/devices/platform-mxc-mmc.c1
-rw-r--r--arch/arm/plat-mxc/devices/platform-spi_imx.c12
-rw-r--r--arch/arm/plat-mxc/gpio.c361
-rw-r--r--arch/arm/plat-mxc/include/mach/clkdev.h7
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h12
-rw-r--r--arch/arm/plat-mxc/include/mach/debug-macro.S10
-rw-r--r--arch/arm/plat-mxc/include/mach/devices-common.h8
-rw-r--r--arch/arm/plat-mxc/include/mach/entry-macro.S4
-rw-r--r--arch/arm/plat-mxc/include/mach/gpio.h27
-rw-r--r--arch/arm/plat-mxc/include/mach/hardware.h28
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx25.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx53.h128
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-v1.h4
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-v3.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux.h26
-rw-r--r--arch/arm/plat-mxc/include/mach/irqs.h21
-rw-r--r--arch/arm/plat-mxc/include/mach/mx53.h54
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc.h8
-rw-r--r--arch/arm/plat-mxc/include/mach/sdma.h6
-rw-r--r--arch/arm/plat-mxc/include/mach/timex.h13
-rw-r--r--arch/arm/plat-mxc/include/mach/uncompress.h1
-rw-r--r--arch/arm/plat-mxc/iomux-v1.c34
-rw-r--r--arch/arm/plat-mxc/irq-common.c13
-rw-r--r--arch/arm/plat-mxc/pwm.c8
-rw-r--r--arch/arm/plat-mxc/tzic.c99
-rw-r--r--arch/arm/plat-nomadik/include/plat/ste_dma40.h1
-rw-r--r--arch/arm/plat-omap/Kconfig3
-rw-r--r--arch/arm/plat-omap/clock.c51
-rw-r--r--arch/arm/plat-omap/counter_32k.c123
-rw-r--r--arch/arm/plat-omap/dmtimer.c213
-rw-r--r--arch/arm/plat-omap/include/plat/clkdev.h13
-rw-r--r--arch/arm/plat-omap/include/plat/clkdev_omap.h1
-rw-r--r--arch/arm/plat-omap/include/plat/clock.h4
-rw-r--r--arch/arm/plat-omap/include/plat/common.h6
-rw-r--r--arch/arm/plat-omap/include/plat/cpu.h35
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h251
-rw-r--r--arch/arm/plat-omap/include/plat/gpio.h20
-rw-r--r--arch/arm/plat-omap/include/plat/i2c.h6
-rw-r--r--arch/arm/plat-omap/include/plat/irqs.h18
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h74
-rw-r--r--arch/arm/plat-omap/include/plat/nand.h6
-rw-r--r--arch/arm/plat-omap/include/plat/omap-pm.h8
-rw-r--r--arch/arm/plat-omap/include/plat/omap4-keypad.h3
-rw-r--r--arch/arm/plat-omap/include/plat/omap_device.h9
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h35
-rw-r--r--arch/arm/plat-omap/include/plat/uncompress.h1
-rw-r--r--arch/arm/plat-omap/iovmm.c6
-rw-r--r--arch/arm/plat-omap/mcbsp.c604
-rw-r--r--arch/arm/plat-omap/omap_device.c147
-rw-r--r--arch/arm/plat-omap/sram.c15
-rw-r--r--arch/arm/plat-pxa/include/plat/sdhci.h35
-rw-r--r--arch/arm/plat-s3c24xx/Kconfig2
-rw-r--r--arch/arm/plat-s3c24xx/clock-dclk.c4
-rw-r--r--arch/arm/plat-s3c24xx/cpu.c15
-rw-r--r--arch/arm/plat-s3c24xx/devs.c38
-rw-r--r--arch/arm/plat-s3c24xx/include/mach/clkdev.h7
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/regs-iis.h9
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/regs-spi.h1
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/s3c2400.h31
-rw-r--r--arch/arm/plat-s3c24xx/s3c2410-clock.c21
-rw-r--r--arch/arm/plat-s3c24xx/s3c2443-clock.c39
-rw-r--r--arch/arm/plat-s3c24xx/sleep.S25
-rw-r--r--arch/arm/plat-s5p/Kconfig11
-rw-r--r--arch/arm/plat-s5p/Makefile3
-rw-r--r--arch/arm/plat-s5p/clock.c35
-rw-r--r--arch/arm/plat-s5p/dev-fimd0.c67
-rw-r--r--arch/arm/plat-s5p/dev-mfc.c123
-rw-r--r--arch/arm/plat-s5p/include/plat/map-s5p.h5
-rw-r--r--arch/arm/plat-s5p/include/plat/mfc.h27
-rw-r--r--arch/arm/plat-s5p/include/plat/s5p-clock.h5
-rw-r--r--arch/arm/plat-s5p/s5p-time.c29
-rw-r--r--arch/arm/plat-s5p/sysmmu.c6
-rw-r--r--arch/arm/plat-samsung/Kconfig6
-rw-r--r--arch/arm/plat-samsung/Makefile1
-rw-r--r--arch/arm/plat-samsung/adc.c84
-rw-r--r--arch/arm/plat-samsung/clock.c105
-rw-r--r--arch/arm/plat-samsung/dev-asocdma.c10
-rw-r--r--arch/arm/plat-samsung/dev-backlight.c149
-rw-r--r--arch/arm/plat-samsung/dev-fb.c14
-rw-r--r--arch/arm/plat-samsung/dev-hwmon.c14
-rw-r--r--arch/arm/plat-samsung/dev-i2c0.c14
-rw-r--r--arch/arm/plat-samsung/dev-i2c1.c24
-rw-r--r--arch/arm/plat-samsung/dev-i2c2.c24
-rw-r--r--arch/arm/plat-samsung/dev-i2c3.c24
-rw-r--r--arch/arm/plat-samsung/dev-i2c4.c24
-rw-r--r--arch/arm/plat-samsung/dev-i2c5.c24
-rw-r--r--arch/arm/plat-samsung/dev-i2c6.c24
-rw-r--r--arch/arm/plat-samsung/dev-i2c7.c24
-rw-r--r--arch/arm/plat-samsung/dev-nand.c9
-rw-r--r--arch/arm/plat-samsung/dev-ts.c14
-rw-r--r--arch/arm/plat-samsung/dev-usb.c9
-rw-r--r--arch/arm/plat-samsung/include/plat/audio.h1
-rw-r--r--arch/arm/plat-samsung/include/plat/backlight.h26
-rw-r--r--arch/arm/plat-samsung/include/plat/clock.h3
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h6
-rw-r--r--arch/arm/plat-samsung/include/plat/fb-core.h15
-rw-r--r--arch/arm/plat-samsung/include/plat/fb.h15
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/iic.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/pm.h5
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-adc.h1
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-serial.h8
-rw-r--r--arch/arm/plat-samsung/irq-uart.c7
-rw-r--r--arch/arm/plat-samsung/pm-check.c2
-rw-r--r--arch/arm/plat-samsung/pm.c13
-rw-r--r--arch/arm/plat-samsung/pwm-clock.c10
-rw-r--r--arch/arm/plat-samsung/time.c2
-rw-r--r--arch/arm/plat-spear/clock.c7
-rw-r--r--arch/arm/plat-spear/include/plat/clkdev.h20
-rw-r--r--arch/arm/plat-tcc/include/mach/clkdev.h7
-rw-r--r--arch/arm/vfp/vfphw.S63
-rw-r--r--arch/arm/vfp/vfpmodule.c133
-rw-r--r--arch/avr32/include/asm/atomic.h60
-rw-r--r--arch/avr32/include/asm/delay.h27
-rw-r--r--arch/avr32/include/asm/ptrace.h2
-rw-r--r--arch/avr32/kernel/module.c20
-rw-r--r--arch/avr32/kernel/setup.c10
-rw-r--r--arch/avr32/mach-at32ap/extint.c2
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c2
-rw-r--r--arch/avr32/mach-at32ap/intc.c2
-rw-r--r--arch/avr32/mach-at32ap/pio.c2
-rw-r--r--arch/blackfin/Kconfig10
-rw-r--r--arch/blackfin/configs/BF561-EZKIT_defconfig8
-rw-r--r--arch/blackfin/include/asm/Kbuild43
-rw-r--r--arch/blackfin/include/asm/atomic.h21
-rw-r--r--arch/blackfin/include/asm/auxvec.h1
-rw-r--r--arch/blackfin/include/asm/bitsperlong.h1
-rw-r--r--arch/blackfin/include/asm/blackfin.h6
-rw-r--r--arch/blackfin/include/asm/bugs.h1
-rw-r--r--arch/blackfin/include/asm/cputime.h1
-rw-r--r--arch/blackfin/include/asm/current.h1
-rw-r--r--arch/blackfin/include/asm/device.h1
-rw-r--r--arch/blackfin/include/asm/div64.h1
-rw-r--r--arch/blackfin/include/asm/dma.h2
-rw-r--r--arch/blackfin/include/asm/dpmc.h27
-rw-r--r--arch/blackfin/include/asm/emergency-restart.h1
-rw-r--r--arch/blackfin/include/asm/errno.h1
-rw-r--r--arch/blackfin/include/asm/fb.h1
-rw-r--r--arch/blackfin/include/asm/futex.h1
-rw-r--r--arch/blackfin/include/asm/gpio.h64
-rw-r--r--arch/blackfin/include/asm/gptimers.h19
-rw-r--r--arch/blackfin/include/asm/hw_irq.h1
-rw-r--r--arch/blackfin/include/asm/ioctl.h1
-rw-r--r--arch/blackfin/include/asm/ipcbuf.h1
-rw-r--r--arch/blackfin/include/asm/ipipe.h2
-rw-r--r--arch/blackfin/include/asm/irq_regs.h1
-rw-r--r--arch/blackfin/include/asm/irqflags.h42
-rw-r--r--arch/blackfin/include/asm/kdebug.h1
-rw-r--r--arch/blackfin/include/asm/kmap_types.h1
-rw-r--r--arch/blackfin/include/asm/local.h1
-rw-r--r--arch/blackfin/include/asm/local64.h1
-rw-r--r--arch/blackfin/include/asm/mman.h1
-rw-r--r--arch/blackfin/include/asm/module.h8
-rw-r--r--arch/blackfin/include/asm/msgbuf.h1
-rw-r--r--arch/blackfin/include/asm/mutex.h77
-rw-r--r--arch/blackfin/include/asm/page.h8
-rw-r--r--arch/blackfin/include/asm/param.h1
-rw-r--r--arch/blackfin/include/asm/pda.h10
-rw-r--r--arch/blackfin/include/asm/percpu.h1
-rw-r--r--arch/blackfin/include/asm/pgalloc.h1
-rw-r--r--arch/blackfin/include/asm/ptrace.h1
-rw-r--r--arch/blackfin/include/asm/resource.h1
-rw-r--r--arch/blackfin/include/asm/scatterlist.h6
-rw-r--r--arch/blackfin/include/asm/sections.h8
-rw-r--r--arch/blackfin/include/asm/sembuf.h1
-rw-r--r--arch/blackfin/include/asm/serial.h1
-rw-r--r--arch/blackfin/include/asm/setup.h1
-rw-r--r--arch/blackfin/include/asm/shmbuf.h1
-rw-r--r--arch/blackfin/include/asm/shmparam.h1
-rw-r--r--arch/blackfin/include/asm/sigcontext.h8
-rw-r--r--arch/blackfin/include/asm/socket.h1
-rw-r--r--arch/blackfin/include/asm/sockios.h1
-rw-r--r--arch/blackfin/include/asm/spinlock.h10
-rw-r--r--arch/blackfin/include/asm/statfs.h1
-rw-r--r--arch/blackfin/include/asm/termbits.h1
-rw-r--r--arch/blackfin/include/asm/termios.h1
-rw-r--r--arch/blackfin/include/asm/topology.h1
-rw-r--r--arch/blackfin/include/asm/types.h1
-rw-r--r--arch/blackfin/include/asm/ucontext.h1
-rw-r--r--arch/blackfin/include/asm/unaligned.h1
-rw-r--r--arch/blackfin/include/asm/user.h1
-rw-r--r--arch/blackfin/include/asm/xor.h1
-rw-r--r--arch/blackfin/kernel/Makefile1
-rw-r--r--arch/blackfin/kernel/asm-offsets.c10
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c26
-rw-r--r--arch/blackfin/kernel/debug-mmrs.c109
-rw-r--r--arch/blackfin/kernel/ftrace.c2
-rw-r--r--arch/blackfin/kernel/gptimers.c93
-rw-r--r--arch/blackfin/kernel/ipipe.c2
-rw-r--r--arch/blackfin/kernel/module.c21
-rw-r--r--arch/blackfin/kernel/nmi.c2
-rw-r--r--arch/blackfin/kernel/process.c1
-rw-r--r--arch/blackfin/kernel/pwm.c100
-rw-r--r--arch/blackfin/kernel/reboot.c4
-rw-r--r--arch/blackfin/kernel/setup.c16
-rw-r--r--arch/blackfin/kernel/time.c4
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S1
-rw-r--r--arch/blackfin/mach-bf518/Kconfig78
-rw-r--r--arch/blackfin/mach-bf518/boards/ezbrd.c59
-rw-r--r--arch/blackfin/mach-bf518/boards/tcm-bf518.c47
-rw-r--r--arch/blackfin/mach-bf518/include/mach/anomaly.h24
-rw-r--r--arch/blackfin/mach-bf518/include/mach/portmux.h54
-rw-r--r--arch/blackfin/mach-bf527/boards/ad7160eval.c19
-rw-r--r--arch/blackfin/mach-bf527/boards/cm_bf527.c55
-rw-r--r--arch/blackfin/mach-bf527/boards/ezbrd.c62
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c98
-rw-r--r--arch/blackfin/mach-bf527/boards/tll6527m.c70
-rw-r--r--arch/blackfin/mach-bf527/include/mach/anomaly.h34
-rw-r--r--arch/blackfin/mach-bf533/boards/H8606.c28
-rw-r--r--arch/blackfin/mach-bf533/boards/blackstamp.c10
-rw-r--r--arch/blackfin/mach-bf533/boards/cm_bf533.c29
-rw-r--r--arch/blackfin/mach-bf533/boards/ezkit.c36
-rw-r--r--arch/blackfin/mach-bf533/boards/ip0x.c1
-rw-r--r--arch/blackfin/mach-bf533/boards/stamp.c78
-rw-r--r--arch/blackfin/mach-bf533/include/mach/anomaly.h19
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537e.c51
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537u.c63
-rw-r--r--arch/blackfin/mach-bf537/boards/dnp5370.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/minotaur.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/pnav10.c38
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c176
-rw-r--r--arch/blackfin/mach-bf537/boards/tcm_bf537.c51
-rw-r--r--arch/blackfin/mach-bf537/include/mach/anomaly.h34
-rw-r--r--arch/blackfin/mach-bf538/boards/ezkit.c25
-rw-r--r--arch/blackfin/mach-bf538/ext-gpio.c37
-rw-r--r--arch/blackfin/mach-bf538/include/mach/anomaly.h38
-rw-r--r--arch/blackfin/mach-bf538/include/mach/gpio.h3
-rw-r--r--arch/blackfin/mach-bf548/boards/cm_bf548.c15
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c32
-rw-r--r--arch/blackfin/mach-bf548/include/mach/anomaly.h220
-rw-r--r--arch/blackfin/mach-bf548/include/mach/gpio.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/irq.h2
-rw-r--r--arch/blackfin/mach-bf561/boards/acvilon.c9
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c58
-rw-r--r--arch/blackfin/mach-bf561/boards/ezkit.c41
-rw-r--r--arch/blackfin/mach-bf561/include/mach/anomaly.h132
-rw-r--r--arch/blackfin/mach-bf561/include/mach/gpio.h6
-rw-r--r--arch/blackfin/mach-bf561/secondary.S152
-rw-r--r--arch/blackfin/mach-common/dpmc_modes.S1016
-rw-r--r--arch/blackfin/mach-common/head.S36
-rw-r--r--arch/blackfin/mach-common/ints-priority.c41
-rw-r--r--arch/blackfin/mach-common/smp.c19
-rw-r--r--arch/cris/arch-v32/drivers/cryptocop.c2
-rw-r--r--arch/cris/arch-v32/kernel/smp.c2
-rw-r--r--arch/cris/arch-v32/mach-a3/pinmux.c10
-rw-r--r--arch/cris/include/arch-v10/arch/processor.h1
-rw-r--r--arch/cris/include/arch-v10/arch/ptrace.h1
-rw-r--r--arch/cris/include/arch-v32/arch/processor.h1
-rw-r--r--arch/cris/include/arch-v32/arch/ptrace.h1
-rw-r--r--arch/cris/include/asm/atomic.h6
-rw-r--r--arch/cris/include/asm/bitops.h5
-rw-r--r--arch/cris/kernel/module.c43
-rw-r--r--arch/cris/kernel/process.c2
-rw-r--r--arch/frv/include/asm/atomic.h6
-rw-r--r--arch/frv/include/asm/bitops.h3
-rw-r--r--arch/frv/include/asm/hardirq.h2
-rw-r--r--arch/frv/include/asm/processor.h1
-rw-r--r--arch/frv/include/asm/ptrace.h1
-rw-r--r--arch/frv/kernel/irq.c2
-rw-r--r--arch/frv/kernel/module.c57
-rw-r--r--arch/frv/kernel/process.c5
-rw-r--r--arch/h8300/Kconfig.cpu4
-rw-r--r--arch/h8300/include/asm/atomic.h6
-rw-r--r--arch/h8300/include/asm/posix_types.h2
-rw-r--r--arch/h8300/include/asm/processor.h2
-rw-r--r--arch/h8300/include/asm/ptrace.h1
-rw-r--r--arch/h8300/kernel/module.c45
-rw-r--r--arch/h8300/kernel/setup.c2
-rw-r--r--arch/ia64/Kconfig27
-rw-r--r--arch/ia64/include/asm/atomic.h6
-rw-r--r--arch/ia64/include/asm/bitops.h3
-rw-r--r--arch/ia64/include/asm/clocksource.h10
-rw-r--r--arch/ia64/include/asm/paravirt.h4
-rw-r--r--arch/ia64/include/asm/processor.h2
-rw-r--r--arch/ia64/include/asm/ptrace.h1
-rw-r--r--arch/ia64/include/asm/sn/tioce.h2
-rw-r--r--arch/ia64/include/asm/spinlock.h2
-rw-r--r--arch/ia64/kernel/cyclone.c2
-rw-r--r--arch/ia64/kernel/module.c16
-rw-r--r--arch/ia64/kernel/paravirt.c2
-rw-r--r--arch/ia64/kernel/smp.c2
-rw-r--r--arch/ia64/kernel/smpboot.c2
-rw-r--r--arch/ia64/kernel/time.c2
-rw-r--r--arch/ia64/kernel/uncached.c2
-rw-r--r--arch/ia64/kvm/Kconfig1
-rw-r--r--arch/ia64/sn/kernel/irq.c14
-rw-r--r--arch/ia64/sn/kernel/sn2/timer.c2
-rw-r--r--arch/m32r/Kconfig12
-rw-r--r--arch/m32r/include/asm/atomic.h10
-rw-r--r--arch/m32r/include/asm/delay.h27
-rw-r--r--arch/m32r/include/asm/mmu_context.h2
-rw-r--r--arch/m32r/include/asm/processor.h1
-rw-r--r--arch/m32r/include/asm/ptrace.h2
-rw-r--r--arch/m32r/include/asm/spinlock.h2
-rw-r--r--arch/m32r/kernel/module.c38
-rw-r--r--arch/m32r/kernel/smp.c2
-rw-r--r--arch/m32r/kernel/traps.c2
-rw-r--r--arch/m68k/Kconfig4
-rw-r--r--arch/m68k/Kconfig.nommu3
-rw-r--r--arch/m68k/Makefile_no2
-rw-r--r--arch/m68k/emu/nfeth.c2
-rw-r--r--arch/m68k/include/asm/atomic.h13
-rw-r--r--arch/m68k/include/asm/bitops.h531
-rw-r--r--arch/m68k/include/asm/bitops_mm.h501
-rw-r--r--arch/m68k/include/asm/bitops_no.h333
-rw-r--r--arch/m68k/include/asm/delay.h97
-rw-r--r--arch/m68k/include/asm/delay_mm.h57
-rw-r--r--arch/m68k/include/asm/delay_no.h76
-rw-r--r--arch/m68k/include/asm/entry_no.h12
-rw-r--r--arch/m68k/include/asm/hardirq.h35
-rw-r--r--arch/m68k/include/asm/hardirq_mm.h16
-rw-r--r--arch/m68k/include/asm/hardirq_no.h19
-rw-r--r--arch/m68k/include/asm/irq.h11
-rw-r--r--arch/m68k/include/asm/machdep.h1
-rw-r--r--arch/m68k/include/asm/module.h31
-rw-r--r--arch/m68k/include/asm/posix_types.h2
-rw-r--r--arch/m68k/include/asm/processor.h4
-rw-r--r--arch/m68k/include/asm/ptrace.h1
-rw-r--r--arch/m68k/include/asm/signal.h15
-rw-r--r--arch/m68k/include/asm/system.h194
-rw-r--r--arch/m68k/include/asm/system_mm.h193
-rw-r--r--arch/m68k/include/asm/system_no.h153
-rw-r--r--arch/m68k/include/asm/traps.h1
-rw-r--r--arch/m68k/kernel/irq.c10
-rw-r--r--arch/m68k/kernel/module.c130
-rw-r--r--arch/m68k/kernel/module_mm.c155
-rw-r--r--arch/m68k/kernel/module_no.c126
-rw-r--r--arch/m68k/kernel/process_mm.c2
-rw-r--r--arch/m68k/kernel/process_no.c2
-rw-r--r--arch/m68k/kernel/traps_no.c4
-rw-r--r--arch/m68k/lib/Makefile2
-rw-r--r--arch/m68k/lib/delay.c21
-rw-r--r--arch/m68k/mm/init_no.c11
-rw-r--r--arch/m68k/platform/5206/config.c6
-rw-r--r--arch/m68k/platform/5206e/Makefile18
-rw-r--r--arch/m68k/platform/5206e/config.c127
-rw-r--r--arch/m68k/platform/5206e/gpio.c49
-rw-r--r--arch/m68k/platform/5272/intc.c2
-rw-r--r--arch/m68k/platform/68328/entry.S15
-rw-r--r--arch/m68k/platform/68328/ints.c10
-rw-r--r--arch/m68k/platform/68360/entry.S15
-rw-r--r--arch/m68k/platform/68360/ints.c11
-rw-r--r--arch/m68k/platform/coldfire/entry.S24
-rw-r--r--arch/m68k/platform/coldfire/intc-2.c2
-rw-r--r--arch/m68k/platform/coldfire/intc-simr.c2
-rw-r--r--arch/m68k/platform/coldfire/intc.c1
-rw-r--r--arch/m68k/platform/coldfire/vectors.c10
-rw-r--r--arch/microblaze/include/asm/mmu_context_mm.h2
-rw-r--r--arch/microblaze/include/asm/pci-bridge.h77
-rw-r--r--arch/microblaze/include/asm/pci.h3
-rw-r--r--arch/microblaze/include/asm/prom.h17
-rw-r--r--arch/microblaze/include/asm/ptrace.h2
-rw-r--r--arch/microblaze/kernel/module.c35
-rw-r--r--arch/microblaze/pci/Makefile2
-rw-r--r--arch/microblaze/pci/pci-common.c114
-rw-r--r--arch/microblaze/pci/pci_32.c432
-rw-r--r--arch/mips/Kbuild.platforms1
-rw-r--r--arch/mips/Kconfig20
-rw-r--r--arch/mips/Makefile12
-rw-r--r--arch/mips/ar7/clock.c2
-rw-r--r--arch/mips/ar7/platform.c2
-rw-r--r--arch/mips/ar7/prom.c2
-rw-r--r--arch/mips/bcm47xx/setup.c2
-rw-r--r--arch/mips/cobalt/time.c2
-rw-r--r--arch/mips/include/asm/atomic.h17
-rw-r--r--arch/mips/include/asm/fixmap.h10
-rw-r--r--arch/mips/include/asm/floppy.h2
-rw-r--r--arch/mips/include/asm/gt64120.h2
-rw-r--r--arch/mips/include/asm/hw_irq.h2
-rw-r--r--arch/mips/include/asm/i8253.h24
-rw-r--r--arch/mips/include/asm/irq.h1
-rw-r--r--arch/mips/include/asm/local.h2
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h1
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/spaces.h17
-rw-r--r--arch/mips/include/asm/mach-generic/dma-coherence.h1
-rw-r--r--arch/mips/include/asm/mach-generic/spaces.h4
-rw-r--r--arch/mips/include/asm/mach-ip27/dma-coherence.h1
-rw-r--r--arch/mips/include/asm/mach-jazz/dma-coherence.h1
-rw-r--r--arch/mips/include/asm/mach-jz4740/gpio.h5
-rw-r--r--arch/mips/include/asm/mach-loongson/dma-coherence.h1
-rw-r--r--arch/mips/include/asm/mach-malta/cpu-feature-overrides.h2
-rw-r--r--arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h2
-rw-r--r--arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h59
-rw-r--r--arch/mips/include/asm/mach-powertv/dma-coherence.h1
-rw-r--r--arch/mips/include/asm/mach-tx39xx/spaces.h17
-rw-r--r--arch/mips/include/asm/mach-tx49xx/spaces.h17
-rw-r--r--arch/mips/include/asm/pgtable.h1
-rw-r--r--arch/mips/include/asm/smp-ops.h43
-rw-r--r--arch/mips/include/asm/smp.h2
-rw-r--r--arch/mips/include/asm/smtc.h1
-rw-r--r--arch/mips/include/asm/stacktrace.h4
-rw-r--r--arch/mips/include/asm/uasm.h2
-rw-r--r--arch/mips/include/asm/unistd.h21
-rw-r--r--arch/mips/jazz/irq.c2
-rw-r--r--arch/mips/kernel/cpu-probe.c1
-rw-r--r--arch/mips/kernel/i8253.c102
-rw-r--r--arch/mips/kernel/irq.c2
-rw-r--r--arch/mips/kernel/irq_cpu.c14
-rw-r--r--arch/mips/kernel/mips-mt.c2
-rw-r--r--arch/mips/kernel/module.c20
-rw-r--r--arch/mips/kernel/perf_event.c4
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c28
-rw-r--r--arch/mips/kernel/process.c20
-rw-r--r--arch/mips/kernel/rtlx.c2
-rw-r--r--arch/mips/kernel/scall32-o32.S1
-rw-r--r--arch/mips/kernel/scall64-64.S1
-rw-r--r--arch/mips/kernel/scall64-n32.S1
-rw-r--r--arch/mips/kernel/scall64-o32.S1
-rw-r--r--arch/mips/kernel/smp-cmp.c2
-rw-r--r--arch/mips/kernel/smp-mt.c2
-rw-r--r--arch/mips/kernel/smp.c2
-rw-r--r--arch/mips/kernel/smtc-proc.c2
-rw-r--r--arch/mips/kernel/smtc.c2
-rw-r--r--arch/mips/kernel/sync-r4k.c2
-rw-r--r--arch/mips/kernel/traps.c8
-rw-r--r--arch/mips/kernel/unaligned.c5
-rw-r--r--arch/mips/kernel/vpe.c2
-rw-r--r--arch/mips/lantiq/clk.c13
-rw-r--r--arch/mips/lantiq/devices.c2
-rw-r--r--arch/mips/lantiq/xway/devices.c2
-rw-r--r--arch/mips/loongson/lemote-2f/ec_kb3310b.c2
-rw-r--r--arch/mips/math-emu/cp1emu.c3
-rw-r--r--arch/mips/mipssim/sim_setup.c18
-rw-r--r--arch/mips/mipssim/sim_smtc.c2
-rw-r--r--arch/mips/mm/c-r4k.c4
-rw-r--r--arch/mips/mm/dma-default.c114
-rw-r--r--arch/mips/mm/fault.c8
-rw-r--r--arch/mips/mm/init.c8
-rw-r--r--arch/mips/mm/mmap.c193
-rw-r--r--arch/mips/mm/pgtable-32.c2
-rw-r--r--arch/mips/mm/pgtable-64.c2
-rw-r--r--arch/mips/mm/tlbex.c292
-rw-r--r--arch/mips/mti-malta/malta-init.c14
-rw-r--r--arch/mips/mti-malta/malta-smtc.c2
-rw-r--r--arch/mips/mti-malta/malta-time.c2
-rw-r--r--arch/mips/netlogic/Platform11
-rw-r--r--arch/mips/netlogic/xlr/irq.c2
-rw-r--r--arch/mips/netlogic/xlr/smp.c13
-rw-r--r--arch/mips/nxp/pnx8550/common/setup.c2
-rw-r--r--arch/mips/oprofile/Makefile2
-rw-r--r--arch/mips/oprofile/backtrace.c175
-rw-r--r--arch/mips/oprofile/common.c1
-rw-r--r--arch/mips/oprofile/op_impl.h2
-rw-r--r--arch/mips/pci/ops-nile4.c1
-rw-r--r--arch/mips/pci/pci-rc32434.c2
-rw-r--r--arch/mips/pci/pci-vr41xx.c2
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_setup.c8
-rw-r--r--arch/mips/pnx8550/common/setup.c2
-rw-r--r--arch/mips/powertv/asic/asic_devices.c10
-rw-r--r--arch/mips/rb532/devices.c24
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-nmi.c2
-rw-r--r--arch/mips/sibyte/sb1250/irq.c8
-rw-r--r--arch/mips/sni/time.c2
-rw-r--r--arch/mn10300/include/asm/atomic.h7
-rw-r--r--arch/mn10300/include/asm/bitops.h7
-rw-r--r--arch/mn10300/include/asm/mmu_context.h2
-rw-r--r--arch/mn10300/include/asm/processor.h1
-rw-r--r--arch/mn10300/include/asm/ptrace.h1
-rw-r--r--arch/mn10300/include/asm/spinlock.h2
-rw-r--r--arch/mn10300/include/asm/system.h2
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog.c2
-rw-r--r--arch/mn10300/kernel/module.c61
-rw-r--r--arch/mn10300/kernel/traps.c2
-rw-r--r--arch/mn10300/mm/misalignment.c2
-rw-r--r--arch/mn10300/proc-mn2ws0050/proc-init.c2
-rw-r--r--arch/openrisc/Kconfig207
-rw-r--r--arch/openrisc/Makefile55
-rw-r--r--arch/openrisc/README.openrisc99
-rw-r--r--arch/openrisc/TODO.openrisc16
-rw-r--r--arch/openrisc/boot/Makefile15
-rw-r--r--arch/openrisc/boot/dts/or1ksim.dts50
-rw-r--r--arch/openrisc/configs/or1ksim_defconfig65
-rw-r--r--arch/openrisc/include/asm/Kbuild64
-rw-r--r--arch/openrisc/include/asm/asm-offsets.h1
-rw-r--r--arch/openrisc/include/asm/bitops.h59
-rw-r--r--arch/openrisc/include/asm/bitops/__ffs.h33
-rw-r--r--arch/openrisc/include/asm/bitops/__fls.h33
-rw-r--r--arch/openrisc/include/asm/bitops/ffs.h32
-rw-r--r--arch/openrisc/include/asm/bitops/fls.h33
-rw-r--r--arch/openrisc/include/asm/byteorder.h1
-rw-r--r--arch/openrisc/include/asm/cache.h29
-rw-r--r--arch/openrisc/include/asm/cpuinfo.h34
-rw-r--r--arch/openrisc/include/asm/delay.h24
-rw-r--r--arch/openrisc/include/asm/dma-mapping.h134
-rw-r--r--arch/openrisc/include/asm/elf.h108
-rw-r--r--arch/openrisc/include/asm/fixmap.h87
-rw-r--r--arch/openrisc/include/asm/gpio.h65
-rw-r--r--arch/openrisc/include/asm/io.h51
-rw-r--r--arch/openrisc/include/asm/irq.h27
-rw-r--r--arch/openrisc/include/asm/irqflags.h29
-rw-r--r--arch/openrisc/include/asm/linkage.h25
-rw-r--r--arch/openrisc/include/asm/memblock.h24
-rw-r--r--arch/openrisc/include/asm/mmu.h26
-rw-r--r--arch/openrisc/include/asm/mmu_context.h43
-rw-r--r--arch/openrisc/include/asm/mutex.h27
-rw-r--r--arch/openrisc/include/asm/page.h110
-rw-r--r--arch/openrisc/include/asm/param.h26
-rw-r--r--arch/openrisc/include/asm/pgalloc.h102
-rw-r--r--arch/openrisc/include/asm/pgtable.h463
-rw-r--r--arch/openrisc/include/asm/processor.h113
-rw-r--r--arch/openrisc/include/asm/prom.h77
-rw-r--r--arch/openrisc/include/asm/ptrace.h131
-rw-r--r--arch/openrisc/include/asm/serial.h36
-rw-r--r--arch/openrisc/include/asm/sigcontext.h38
-rw-r--r--arch/openrisc/include/asm/spinlock.h24
-rw-r--r--arch/openrisc/include/asm/spr.h42
-rw-r--r--arch/openrisc/include/asm/spr_defs.h604
-rw-r--r--arch/openrisc/include/asm/syscall.h77
-rw-r--r--arch/openrisc/include/asm/syscalls.h27
-rw-r--r--arch/openrisc/include/asm/system.h35
-rw-r--r--arch/openrisc/include/asm/thread_info.h134
-rw-r--r--arch/openrisc/include/asm/timex.h36
-rw-r--r--arch/openrisc/include/asm/tlb.h34
-rw-r--r--arch/openrisc/include/asm/tlbflush.h55
-rw-r--r--arch/openrisc/include/asm/uaccess.h355
-rw-r--r--arch/openrisc/include/asm/unaligned.h51
-rw-r--r--arch/openrisc/include/asm/unistd.h31
-rw-r--r--arch/openrisc/kernel/Makefile14
-rw-r--r--arch/openrisc/kernel/asm-offsets.c70
-rw-r--r--arch/openrisc/kernel/dma.c191
-rw-r--r--arch/openrisc/kernel/entry.S1128
-rw-r--r--arch/openrisc/kernel/head.S1607
-rw-r--r--arch/openrisc/kernel/idle.c77
-rw-r--r--arch/openrisc/kernel/init_task.c41
-rw-r--r--arch/openrisc/kernel/irq.c172
-rw-r--r--arch/openrisc/kernel/module.c72
-rw-r--r--arch/openrisc/kernel/or32_ksyms.c46
-rw-r--r--arch/openrisc/kernel/process.c311
-rw-r--r--arch/openrisc/kernel/prom.c108
-rw-r--r--arch/openrisc/kernel/ptrace.c211
-rw-r--r--arch/openrisc/kernel/setup.c381
-rw-r--r--arch/openrisc/kernel/signal.c396
-rw-r--r--arch/openrisc/kernel/sys_call_table.c28
-rw-r--r--arch/openrisc/kernel/sys_or32.c57
-rw-r--r--arch/openrisc/kernel/time.c181
-rw-r--r--arch/openrisc/kernel/traps.c366
-rw-r--r--arch/openrisc/kernel/vmlinux.h12
-rw-r--r--arch/openrisc/kernel/vmlinux.lds.S115
-rw-r--r--arch/openrisc/lib/Makefile5
-rw-r--r--arch/openrisc/lib/delay.c60
-rw-r--r--arch/openrisc/lib/string.S204
-rw-r--r--arch/openrisc/mm/Makefile5
-rw-r--r--arch/openrisc/mm/fault.c338
-rw-r--r--arch/openrisc/mm/init.c283
-rw-r--r--arch/openrisc/mm/ioremap.c137
-rw-r--r--arch/openrisc/mm/tlb.c193
-rw-r--r--arch/parisc/include/asm/atomic.h16
-rw-r--r--arch/parisc/include/asm/bitops.h11
-rw-r--r--arch/parisc/include/asm/dma-mapping.h2
-rw-r--r--arch/parisc/include/asm/mmu_context.h2
-rw-r--r--arch/parisc/include/asm/ptrace.h1
-rw-r--r--arch/parisc/kernel/module.c12
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c2
-rw-r--r--arch/parisc/kernel/smp.c2
-rw-r--r--arch/parisc/kernel/traps.c2
-rw-r--r--arch/parisc/lib/bitops.c2
-rw-r--r--arch/parisc/math-emu/decode_exc.c2
-rw-r--r--arch/powerpc/Kconfig4
-rw-r--r--arch/powerpc/Kconfig.debug15
-rw-r--r--arch/powerpc/Makefile5
-rw-r--r--arch/powerpc/boot/dts/canyonlands.dts5
-rw-r--r--arch/powerpc/boot/dts/glacier.dts8
-rw-r--r--arch/powerpc/boot/dts/mpc8568mds.dts2
-rw-r--r--arch/powerpc/boot/dts/p1010rdb.dts280
-rw-r--r--arch/powerpc/boot/dts/p1010si.dtsi376
-rw-r--r--arch/powerpc/boot/dts/p1022ds.dts2
-rw-r--r--arch/powerpc/boot/dts/p1023rds.dts546
-rw-r--r--arch/powerpc/boot/dts/p2040rdb.dts166
-rw-r--r--arch/powerpc/boot/dts/p2040si.dtsi623
-rw-r--r--arch/powerpc/boot/dts/p3041ds.dts214
-rw-r--r--arch/powerpc/boot/dts/p3041si.dtsi660
-rw-r--r--arch/powerpc/boot/dts/p4080ds.dts533
-rw-r--r--arch/powerpc/boot/dts/p4080si.dtsi661
-rw-r--r--arch/powerpc/boot/dts/p5020ds.dts215
-rw-r--r--arch/powerpc/boot/dts/p5020si.dtsi652
-rw-r--r--arch/powerpc/boot/dts/sequoia.dts12
-rw-r--r--arch/powerpc/boot/dts/socrates.dts2
-rw-r--r--arch/powerpc/boot/dts/taishan.dts4
-rw-r--r--arch/powerpc/boot/dts/tqm8540.dts42
-rw-r--r--arch/powerpc/boot/dts/tqm8548-bigflash.dts2
-rw-r--r--arch/powerpc/boot/dts/tqm8548.dts2
-rw-r--r--arch/powerpc/boot/dts/tqm8560.dts2
-rw-r--r--arch/powerpc/boot/dts/xpedite5200.dts2
-rw-r--r--arch/powerpc/boot/dts/xpedite5200_xmon.dts2
-rw-r--r--arch/powerpc/boot/treeboot-iss4xx.c23
-rw-r--r--arch/powerpc/configs/44x/iss476-smp_defconfig6
-rw-r--r--arch/powerpc/configs/85xx/p1023rds_defconfig173
-rw-r--r--arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig5
-rw-r--r--arch/powerpc/configs/corenet32_smp_defconfig187
-rw-r--r--arch/powerpc/configs/corenet64_smp_defconfig (renamed from arch/powerpc/configs/e55xx_smp_defconfig)0
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig12
-rw-r--r--arch/powerpc/configs/mpc85xx_smp_defconfig10
-rw-r--r--arch/powerpc/configs/ppc64_defconfig16
-rw-r--r--arch/powerpc/configs/pseries_defconfig3
-rw-r--r--arch/powerpc/include/asm/8253pit.h3
-rw-r--r--arch/powerpc/include/asm/atomic.h19
-rw-r--r--arch/powerpc/include/asm/bitops.h5
-rw-r--r--arch/powerpc/include/asm/cputable.h14
-rw-r--r--arch/powerpc/include/asm/dbell.h2
-rw-r--r--arch/powerpc/include/asm/ehv_pic.h40
-rw-r--r--arch/powerpc/include/asm/elf.h4
-rw-r--r--arch/powerpc/include/asm/emulated_ops.h6
-rw-r--r--arch/powerpc/include/asm/epapr_hcalls.h502
-rw-r--r--arch/powerpc/include/asm/exception-64e.h52
-rw-r--r--arch/powerpc/include/asm/exception-64s.h136
-rw-r--r--arch/powerpc/include/asm/fsl_hcalls.h655
-rw-r--r--arch/powerpc/include/asm/hvcall.h5
-rw-r--r--arch/powerpc/include/asm/hvsi.h94
-rw-r--r--arch/powerpc/include/asm/hw_breakpoint.h2
-rw-r--r--arch/powerpc/include/asm/irq.h4
-rw-r--r--arch/powerpc/include/asm/jump_label.h47
-rw-r--r--arch/powerpc/include/asm/kvm.h15
-rw-r--r--arch/powerpc/include/asm/kvm_asm.h4
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h196
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h4
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_asm.h41
-rw-r--r--arch/powerpc/include/asm/kvm_booke.h4
-rw-r--r--arch/powerpc/include/asm/kvm_e500.h30
-rw-r--r--arch/powerpc/include/asm/kvm_host.h169
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h41
-rw-r--r--arch/powerpc/include/asm/local.h2
-rw-r--r--arch/powerpc/include/asm/macio.h2
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h10
-rw-r--r--arch/powerpc/include/asm/mmu.h12
-rw-r--r--arch/powerpc/include/asm/pSeries_reconfig.h2
-rw-r--r--arch/powerpc/include/asm/paca.h10
-rw-r--r--arch/powerpc/include/asm/pci-bridge.h79
-rw-r--r--arch/powerpc/include/asm/pci.h5
-rw-r--r--arch/powerpc/include/asm/pgtable-ppc64.h3
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h40
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h28
-rw-r--r--arch/powerpc/include/asm/processor.h5
-rw-r--r--arch/powerpc/include/asm/prom.h16
-rw-r--r--arch/powerpc/include/asm/reg.h29
-rw-r--r--arch/powerpc/include/asm/reg_booke.h1
-rw-r--r--arch/powerpc/include/asm/setup.h4
-rw-r--r--arch/powerpc/include/asm/smp.h3
-rw-r--r--arch/powerpc/include/asm/smu.h2
-rw-r--r--arch/powerpc/include/asm/system.h1
-rw-r--r--arch/powerpc/include/asm/udbg.h1
-rw-r--r--arch/powerpc/kernel/Makefile1
-rw-r--r--arch/powerpc/kernel/asm-offsets.c193
-rw-r--r--arch/powerpc/kernel/cpu_setup_power7.S22
-rw-r--r--arch/powerpc/kernel/cpu_setup_ppc970.S26
-rw-r--r--arch/powerpc/kernel/crash.c6
-rw-r--r--arch/powerpc/kernel/dma.c4
-rw-r--r--arch/powerpc/kernel/e500-pmu.c5
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S22
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S228
-rw-r--r--arch/powerpc/kernel/head_44x.S42
-rw-r--r--arch/powerpc/kernel/head_64.S2
-rw-r--r--arch/powerpc/kernel/head_booke.h42
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S57
-rw-r--r--arch/powerpc/kernel/idle_e500.S12
-rw-r--r--arch/powerpc/kernel/idle_power7.S2
-rw-r--r--arch/powerpc/kernel/irq.c50
-rw-r--r--arch/powerpc/kernel/jump_label.c23
-rw-r--r--arch/powerpc/kernel/machine_kexec.c4
-rw-r--r--arch/powerpc/kernel/misc_64.S4
-rw-r--r--arch/powerpc/kernel/module.c18
-rw-r--r--arch/powerpc/kernel/module_32.c11
-rw-r--r--arch/powerpc/kernel/module_64.c10
-rw-r--r--arch/powerpc/kernel/mpc7450-pmu.c7
-rw-r--r--arch/powerpc/kernel/of_platform.c2
-rw-r--r--arch/powerpc/kernel/paca.c2
-rw-r--r--arch/powerpc/kernel/pci-common.c53
-rw-r--r--arch/powerpc/kernel/pci_32.c171
-rw-r--r--arch/powerpc/kernel/pci_64.c4
-rw-r--r--arch/powerpc/kernel/pci_dn.c47
-rw-r--r--arch/powerpc/kernel/pci_of_scan.c9
-rw-r--r--arch/powerpc/kernel/perf_event.c8
-rw-r--r--arch/powerpc/kernel/perf_event_fsl_emb.c6
-rw-r--r--arch/powerpc/kernel/power4-pmu.c7
-rw-r--r--arch/powerpc/kernel/power5+-pmu.c7
-rw-r--r--arch/powerpc/kernel/power5-pmu.c7
-rw-r--r--arch/powerpc/kernel/power6-pmu.c7
-rw-r--r--arch/powerpc/kernel/power7-pmu.c7
-rw-r--r--arch/powerpc/kernel/ppc970-pmu.c7
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c2
-rw-r--r--arch/powerpc/kernel/process.c8
-rw-r--r--arch/powerpc/kernel/prom.c16
-rw-r--r--arch/powerpc/kernel/ptrace.c4
-rw-r--r--arch/powerpc/kernel/rtas.c3
-rw-r--r--arch/powerpc/kernel/rtas_flash.c1
-rw-r--r--arch/powerpc/kernel/rtas_pci.c2
-rw-r--r--arch/powerpc/kernel/rtasd.c2
-rw-r--r--arch/powerpc/kernel/setup-common.c30
-rw-r--r--arch/powerpc/kernel/setup_32.c4
-rw-r--r--arch/powerpc/kernel/setup_64.c9
-rw-r--r--arch/powerpc/kernel/smp-tbsync.c2
-rw-r--r--arch/powerpc/kernel/smp.c33
-rw-r--r--arch/powerpc/kernel/time.c2
-rw-r--r--arch/powerpc/kernel/traps.c5
-rw-r--r--arch/powerpc/kernel/udbg.c5
-rw-r--r--arch/powerpc/kvm/44x_tlb.c4
-rw-r--r--arch/powerpc/kvm/Kconfig35
-rw-r--r--arch/powerpc/kvm/Makefile27
-rw-r--r--arch/powerpc/kvm/book3s.c1007
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu.c54
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c180
-rw-r--r--arch/powerpc/kvm/book3s_64_vio_hv.c73
-rw-r--r--arch/powerpc/kvm/book3s_exports.c9
-rw-r--r--arch/powerpc/kvm/book3s_hv.c1269
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c155
-rw-r--r--arch/powerpc/kvm/book3s_hv_interrupts.S166
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c370
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S1345
-rw-r--r--arch/powerpc/kvm/book3s_interrupts.S21
-rw-r--r--arch/powerpc/kvm/book3s_mmu_hpte.c71
-rw-r--r--arch/powerpc/kvm/book3s_pr.c1029
-rw-r--r--arch/powerpc/kvm/book3s_rmhandlers.S102
-rw-r--r--arch/powerpc/kvm/book3s_segment.S117
-rw-r--r--arch/powerpc/kvm/booke.c132
-rw-r--r--arch/powerpc/kvm/booke.h23
-rw-r--r--arch/powerpc/kvm/booke_interrupts.S66
-rw-r--r--arch/powerpc/kvm/e500.c7
-rw-r--r--arch/powerpc/kvm/e500_emulate.c4
-rw-r--r--arch/powerpc/kvm/e500_tlb.c800
-rw-r--r--arch/powerpc/kvm/e500_tlb.h13
-rw-r--r--arch/powerpc/kvm/powerpc.c78
-rw-r--r--arch/powerpc/kvm/timing.c9
-rw-r--r--arch/powerpc/kvm/trace.h4
-rw-r--r--arch/powerpc/mm/44x_mmu.c13
-rw-r--r--arch/powerpc/mm/fault.c6
-rw-r--r--arch/powerpc/mm/hash_native_64.c6
-rw-r--r--arch/powerpc/mm/init_32.c32
-rw-r--r--arch/powerpc/mm/init_64.c16
-rw-r--r--arch/powerpc/mm/mem.c35
-rw-r--r--arch/powerpc/mm/tlb_hash32.c4
-rw-r--r--arch/powerpc/mm/tlb_low_64e.S206
-rw-r--r--arch/powerpc/mm/tlb_nohash.c64
-rw-r--r--arch/powerpc/net/Makefile4
-rw-r--r--arch/powerpc/net/bpf_jit.h227
-rw-r--r--arch/powerpc/net/bpf_jit_64.S138
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c694
-rw-r--r--arch/powerpc/platforms/40x/ep405.c2
-rw-r--r--arch/powerpc/platforms/40x/ppc40x_simple.c2
-rw-r--r--arch/powerpc/platforms/40x/walnut.c2
-rw-r--r--arch/powerpc/platforms/44x/canyonlands.c2
-rw-r--r--arch/powerpc/platforms/44x/ebony.c2
-rw-r--r--arch/powerpc/platforms/44x/ppc44x_simple.c2
-rw-r--r--arch/powerpc/platforms/44x/sam440ep.c2
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig8
-rw-r--r--arch/powerpc/platforms/52xx/Makefile1
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c10
-rw-r--r--arch/powerpc/platforms/82xx/pq2.c2
-rw-r--r--arch/powerpc/platforms/83xx/km83xx.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c4
-rw-r--r--arch/powerpc/platforms/83xx/sbc834x.c2
-rw-r--r--arch/powerpc/platforms/83xx/usb.c2
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig31
-rw-r--r--arch/powerpc/platforms/85xx/Makefile3
-rw-r--r--arch/powerpc/platforms/85xx/corenet_ds.c41
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c3
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_rdb.c5
-rw-r--r--arch/powerpc/platforms/85xx/p1010rdb.c122
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c18
-rw-r--r--arch/powerpc/platforms/85xx/p1023_rds.c162
-rw-r--r--arch/powerpc/platforms/85xx/p2040_rdb.c88
-rw-r--r--arch/powerpc/platforms/85xx/p3041_ds.c28
-rw-r--r--arch/powerpc/platforms/85xx/p4080_ds.c38
-rw-r--r--arch/powerpc/platforms/85xx/p5020_ds.c32
-rw-r--r--arch/powerpc/platforms/85xx/sbc8548.c2
-rw-r--r--arch/powerpc/platforms/85xx/sbc8560.c2
-rw-r--r--arch/powerpc/platforms/85xx/smp.c30
-rw-r--r--arch/powerpc/platforms/85xx/xes_mpc85xx.c2
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c107
-rw-r--r--arch/powerpc/platforms/Kconfig6
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype2
-rw-r--r--arch/powerpc/platforms/amigaone/Kconfig2
-rw-r--r--arch/powerpc/platforms/cell/celleb_scc_epci.c8
-rw-r--r--arch/powerpc/platforms/cell/celleb_scc_pciex.c2
-rw-r--r--arch/powerpc/platforms/cell/cpufreq_spudemand.c2
-rw-r--r--arch/powerpc/platforms/cell/smp.c2
-rw-r--r--arch/powerpc/platforms/cell/spu_manage.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c11
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c29
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h2
-rw-r--r--arch/powerpc/platforms/cell/spufs/syscalls.c22
-rw-r--r--arch/powerpc/platforms/chrp/Kconfig1
-rw-r--r--arch/powerpc/platforms/chrp/pci.c4
-rw-r--r--arch/powerpc/platforms/chrp/smp.c2
-rw-r--r--arch/powerpc/platforms/iseries/exception.S2
-rw-r--r--arch/powerpc/platforms/iseries/exception.h4
-rw-r--r--arch/powerpc/platforms/iseries/smp.c4
-rw-r--r--arch/powerpc/platforms/maple/setup.c41
-rw-r--r--arch/powerpc/platforms/pasemi/dma_lib.c2
-rw-r--r--arch/powerpc/platforms/powermac/backlight.c2
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c4
-rw-r--r--arch/powerpc/platforms/powermac/pci.c15
-rw-r--r--arch/powerpc/platforms/powermac/setup.c3
-rw-r--r--arch/powerpc/platforms/powermac/smp.c4
-rw-r--r--arch/powerpc/platforms/powermac/time.c2
-rw-r--r--arch/powerpc/platforms/prep/Kconfig1
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig1
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c10
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c2
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c10
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c16
-rw-r--r--arch/powerpc/platforms/pseries/hvconsole.c2
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c191
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h3
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c28
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
-rw-r--r--arch/powerpc/platforms/pseries/smp.c5
-rw-r--r--arch/powerpc/platforms/wsp/smp.c2
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/axonram.c2
-rw-r--r--arch/powerpc/sysdev/cpm1.c2
-rw-r--r--arch/powerpc/sysdev/cpm_common.c2
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c2
-rw-r--r--arch/powerpc/sysdev/ehv_pic.c302
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c2
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c99
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c2
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c29
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h3
-rw-r--r--arch/powerpc/sysdev/grackle.c2
-rw-r--r--arch/powerpc/sysdev/ipic.c2
-rw-r--r--arch/powerpc/sysdev/mmio_nvram.c2
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c2
-rw-r--r--arch/powerpc/sysdev/mpic.c38
-rw-r--r--arch/powerpc/sysdev/mv64x60_udbg.c4
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c165
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.c2
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_io.c2
-rw-r--r--arch/powerpc/sysdev/tsi108_dev.c2
-rw-r--r--arch/powerpc/sysdev/xics/icp-native.c11
-rw-r--r--arch/s390/boot/compressed/head31.S4
-rw-r--r--arch/s390/boot/compressed/head64.S4
-rw-r--r--arch/s390/crypto/sha256_s390.c66
-rw-r--r--arch/s390/include/asm/atomic.h7
-rw-r--r--arch/s390/include/asm/bitops.h5
-rw-r--r--arch/s390/include/asm/irqflags.h16
-rw-r--r--arch/s390/include/asm/kvm_host.h12
-rw-r--r--arch/s390/include/asm/linkage.h5
-rw-r--r--arch/s390/include/asm/lowcore.h2
-rw-r--r--arch/s390/include/asm/mmu.h4
-rw-r--r--arch/s390/include/asm/pgalloc.h7
-rw-r--r--arch/s390/include/asm/pgtable.h42
-rw-r--r--arch/s390/include/asm/processor.h1
-rw-r--r--arch/s390/include/asm/ptrace.h1
-rw-r--r--arch/s390/include/asm/thread_info.h2
-rw-r--r--arch/s390/include/asm/tlbflush.h2
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/base.S25
-rw-r--r--arch/s390/kernel/compat_wrapper.S836
-rw-r--r--arch/s390/kernel/dis.c2
-rw-r--r--arch/s390/kernel/entry.S32
-rw-r--r--arch/s390/kernel/entry.h7
-rw-r--r--arch/s390/kernel/entry64.S111
-rw-r--r--arch/s390/kernel/head.S7
-rw-r--r--arch/s390/kernel/head31.S13
-rw-r--r--arch/s390/kernel/head64.S13
-rw-r--r--arch/s390/kernel/irq.c83
-rw-r--r--arch/s390/kernel/mcount.S16
-rw-r--r--arch/s390/kernel/mcount64.S16
-rw-r--r--arch/s390/kernel/module.c20
-rw-r--r--arch/s390/kernel/reipl.S5
-rw-r--r--arch/s390/kernel/reipl64.S5
-rw-r--r--arch/s390/kernel/relocate_kernel.S6
-rw-r--r--arch/s390/kernel/relocate_kernel64.S6
-rw-r--r--arch/s390/kernel/s390_ksyms.c4
-rw-r--r--arch/s390/kernel/sclp.S5
-rw-r--r--arch/s390/kernel/smp.c3
-rw-r--r--arch/s390/kernel/switch_cpu.S8
-rw-r--r--arch/s390/kernel/switch_cpu64.S8
-rw-r--r--arch/s390/kernel/swsusp_asm64.S8
-rw-r--r--arch/s390/kernel/traps.c38
-rw-r--r--arch/s390/kvm/Kconfig1
-rw-r--r--arch/s390/kvm/Makefile2
-rw-r--r--arch/s390/kvm/gaccess.h243
-rw-r--r--arch/s390/kvm/intercept.c35
-rw-r--r--arch/s390/kvm/interrupt.c4
-rw-r--r--arch/s390/kvm/kvm-s390.c48
-rw-r--r--arch/s390/kvm/kvm-s390.h28
-rw-r--r--arch/s390/kvm/priv.c49
-rw-r--r--arch/s390/kvm/sie64a.S98
-rw-r--r--arch/s390/kvm/sigp.c6
-rw-r--r--arch/s390/lib/qrnnd.S5
-rw-r--r--arch/s390/mm/fault.c24
-rw-r--r--arch/s390/mm/hugetlbpage.c2
-rw-r--r--arch/s390/mm/pgtable.c421
-rw-r--r--arch/s390/mm/vmem.c8
-rw-r--r--arch/s390/oprofile/init.c2
-rw-r--r--arch/score/kernel/module.c29
-rw-r--r--arch/sh/Kconfig16
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c2
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c4
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c2
-rw-r--r--arch/sh/boards/mach-migor/setup.c2
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c4
-rw-r--r--arch/sh/include/asm/atomic.h12
-rw-r--r--arch/sh/include/asm/delay.h27
-rw-r--r--arch/sh/include/asm/hw_irq.h2
-rw-r--r--arch/sh/include/asm/ptrace.h2
-rw-r--r--arch/sh/include/asm/smp.h2
-rw-r--r--arch/sh/kernel/cpu/sh4/perf_event.c15
-rw-r--r--arch/sh/kernel/cpu/sh4a/perf_event.c15
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm_runtime.c6
-rw-r--r--arch/sh/kernel/idle.c2
-rw-r--r--arch/sh/kernel/io_trapped.c8
-rw-r--r--arch/sh/kernel/machine_kexec.c2
-rw-r--r--arch/sh/kernel/module.c35
-rw-r--r--arch/sh/kernel/ptrace_32.c5
-rw-r--r--arch/sh/kernel/smp.c2
-rw-r--r--arch/sh/kernel/traps_32.c2
-rw-r--r--arch/sh/kernel/traps_64.c10
-rw-r--r--arch/sh/kernel/unwinder.c2
-rw-r--r--arch/sh/math-emu/math.c2
-rw-r--r--arch/sh/mm/fault_32.c6
-rw-r--r--arch/sh/mm/tlbflush_64.c6
-rw-r--r--arch/sparc/Kconfig5
-rw-r--r--arch/sparc/include/asm/atomic_32.h4
-rw-r--r--arch/sparc/include/asm/atomic_64.h6
-rw-r--r--arch/sparc/include/asm/bitops_64.h5
-rw-r--r--arch/sparc/include/asm/elf_64.h2
-rw-r--r--arch/sparc/include/asm/pci_32.h3
-rw-r--r--arch/sparc/include/asm/pci_64.h3
-rw-r--r--arch/sparc/include/asm/pgalloc_64.h76
-rw-r--r--arch/sparc/include/asm/pgtable_64.h15
-rw-r--r--arch/sparc/include/asm/prom.h2
-rw-r--r--arch/sparc/include/asm/ptrace.h2
-rw-r--r--arch/sparc/include/asm/smp_32.h2
-rw-r--r--arch/sparc/include/asm/smp_64.h2
-rw-r--r--arch/sparc/kernel/ioport.c12
-rw-r--r--arch/sparc/kernel/irq_64.c2
-rw-r--r--arch/sparc/kernel/leon_smp.c2
-rw-r--r--arch/sparc/kernel/module.c28
-rw-r--r--arch/sparc/kernel/pci.c14
-rw-r--r--arch/sparc/kernel/pcic.c8
-rw-r--r--arch/sparc/kernel/perf_event.c46
-rw-r--r--arch/sparc/kernel/smp_32.c2
-rw-r--r--arch/sparc/kernel/smp_64.c2
-rw-r--r--arch/sparc/kernel/unaligned_32.c4
-rw-r--r--arch/sparc/kernel/unaligned_64.c12
-rw-r--r--arch/sparc/kernel/visemul.c2
-rw-r--r--arch/sparc/lib/atomic32.c2
-rw-r--r--arch/sparc/math-emu/math_32.c2
-rw-r--r--arch/sparc/math-emu/math_64.c2
-rw-r--r--arch/sparc/mm/Makefile2
-rw-r--r--arch/sparc/mm/fault_32.c8
-rw-r--r--arch/sparc/mm/fault_64.c8
-rw-r--r--arch/sparc/mm/gup.c181
-rw-r--r--arch/sparc/mm/tsb.c11
-rw-r--r--arch/tile/configs/tilegx_defconfig1
-rw-r--r--arch/tile/include/asm/atomic.h14
-rw-r--r--arch/tile/include/asm/atomic_32.h14
-rw-r--r--arch/tile/include/asm/atomic_64.h6
-rw-r--r--arch/tile/include/asm/bitops_32.h2
-rw-r--r--arch/tile/include/asm/bitops_64.h7
-rw-r--r--arch/tile/include/asm/ptrace.h2
-rw-r--r--arch/tile/include/asm/spinlock_32.h2
-rw-r--r--arch/tile/kernel/intvec_32.S2
-rw-r--r--arch/tile/kernel/module.c31
-rw-r--r--arch/tile/kernel/setup.c3
-rw-r--r--arch/tile/kvm/Kconfig1
-rw-r--r--arch/tile/lib/atomic_32.c2
-rw-r--r--arch/tile/lib/atomic_asm_32.S2
-rw-r--r--arch/um/Kconfig.x862
-rw-r--r--arch/um/drivers/chan_kern.c3
-rw-r--r--arch/um/drivers/cow_user.c6
-rw-r--r--arch/um/drivers/harddog_user.c2
-rw-r--r--arch/um/drivers/line.c3
-rw-r--r--arch/um/drivers/net_kern.c12
-rw-r--r--arch/um/drivers/net_user.c5
-rw-r--r--arch/um/drivers/slip_user.c3
-rw-r--r--arch/um/include/asm/delay.h10
-rw-r--r--arch/um/include/asm/ptrace-generic.h2
-rw-r--r--arch/um/kernel/exec.c1
-rw-r--r--arch/um/kernel/reboot.c3
-rw-r--r--arch/um/os-Linux/Makefile4
-rw-r--r--arch/um/os-Linux/elf_aux.c7
-rw-r--r--arch/um/os-Linux/helper.c4
-rw-r--r--arch/um/os-Linux/main.c4
-rw-r--r--arch/um/os-Linux/mem.c6
-rw-r--r--arch/um/os-Linux/user_syms.c5
-rw-r--r--arch/um/sys-i386/Makefile5
-rw-r--r--arch/um/sys-i386/asm/elf.h2
-rw-r--r--arch/um/sys-i386/delay.c59
-rw-r--r--arch/um/sys-i386/mem.c62
-rw-r--r--arch/um/sys-i386/signal.c2
-rw-r--r--arch/um/sys-x86_64/Makefile6
-rw-r--r--arch/um/sys-x86_64/asm/elf.h10
-rw-r--r--arch/um/sys-x86_64/delay.c54
-rw-r--r--arch/um/sys-x86_64/mem.c32
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/vm-flags.h26
-rw-r--r--arch/um/sys-x86_64/vdso/Makefile90
-rw-r--r--arch/um/sys-x86_64/vdso/checkundef.sh10
-rw-r--r--arch/um/sys-x86_64/vdso/um_vdso.c71
-rw-r--r--arch/um/sys-x86_64/vdso/vdso-layout.lds.S64
-rw-r--r--arch/um/sys-x86_64/vdso/vdso-note.S12
-rw-r--r--arch/um/sys-x86_64/vdso/vdso.S10
-rw-r--r--arch/um/sys-x86_64/vdso/vdso.lds.S32
-rw-r--r--arch/um/sys-x86_64/vdso/vma.c74
-rw-r--r--arch/unicore32/kernel/module.c35
-rw-r--r--arch/x86/Kconfig160
-rw-r--r--arch/x86/Kconfig.cpu3
-rw-r--r--arch/x86/boot/Makefile9
-rw-r--r--arch/x86/boot/tools/build.c33
-rw-r--r--arch/x86/crypto/ghash-clmulni-intel_glue.c2
-rw-r--r--arch/x86/ia32/ia32_signal.c22
-rw-r--r--arch/x86/ia32/ia32entry.S10
-rw-r--r--arch/x86/ia32/sys_ia32.c2
-rw-r--r--arch/x86/include/asm/alternative-asm.h4
-rw-r--r--arch/x86/include/asm/alternative.h8
-rw-r--r--arch/x86/include/asm/apb_timer.h23
-rw-r--r--arch/x86/include/asm/apic.h2
-rw-r--r--arch/x86/include/asm/asm.h5
-rw-r--r--arch/x86/include/asm/atomic.h10
-rw-r--r--arch/x86/include/asm/atomic64_32.h2
-rw-r--r--arch/x86/include/asm/atomic64_64.h2
-rw-r--r--arch/x86/include/asm/bitops.h5
-rw-r--r--arch/x86/include/asm/calling.h130
-rw-r--r--arch/x86/include/asm/clocksource.h18
-rw-r--r--arch/x86/include/asm/cmpxchg_32.h48
-rw-r--r--arch/x86/include/asm/cmpxchg_64.h45
-rw-r--r--arch/x86/include/asm/cpufeature.h10
-rw-r--r--arch/x86/include/asm/delay.h25
-rw-r--r--arch/x86/include/asm/entry_arch.h4
-rw-r--r--arch/x86/include/asm/fixmap.h1
-rw-r--r--arch/x86/include/asm/frame.h11
-rw-r--r--arch/x86/include/asm/hw_irq.h3
-rw-r--r--arch/x86/include/asm/i8253.h20
-rw-r--r--arch/x86/include/asm/irq_vectors.h11
-rw-r--r--arch/x86/include/asm/irqflags.h11
-rw-r--r--arch/x86/include/asm/kdebug.h1
-rw-r--r--arch/x86/include/asm/kvm_emulate.h52
-rw-r--r--arch/x86/include/asm/kvm_host.h46
-rw-r--r--arch/x86/include/asm/kvm_para.h20
-rw-r--r--arch/x86/include/asm/lguest_hcall.h1
-rw-r--r--arch/x86/include/asm/local.h2
-rw-r--r--arch/x86/include/asm/mce.h21
-rw-r--r--arch/x86/include/asm/mmu_context.h2
-rw-r--r--arch/x86/include/asm/mmzone_32.h6
-rw-r--r--arch/x86/include/asm/msr-index.h15
-rw-r--r--arch/x86/include/asm/olpc.h51
-rw-r--r--arch/x86/include/asm/paravirt.h9
-rw-r--r--arch/x86/include/asm/paravirt_types.h1
-rw-r--r--arch/x86/include/asm/percpu.h11
-rw-r--r--arch/x86/include/asm/perf_event.h5
-rw-r--r--arch/x86/include/asm/perf_event_p4.h33
-rw-r--r--arch/x86/include/asm/pgtable_types.h6
-rw-r--r--arch/x86/include/asm/processor-flags.h1
-rw-r--r--arch/x86/include/asm/prom.h13
-rw-r--r--arch/x86/include/asm/rwlock.h43
-rw-r--r--arch/x86/include/asm/segment.h2
-rw-r--r--arch/x86/include/asm/smpboot_hooks.h8
-rw-r--r--arch/x86/include/asm/spinlock.h39
-rw-r--r--arch/x86/include/asm/spinlock_types.h6
-rw-r--r--arch/x86/include/asm/thread_info.h2
-rw-r--r--arch/x86/include/asm/time.h6
-rw-r--r--arch/x86/include/asm/traps.h4
-rw-r--r--arch/x86/include/asm/tsc.h4
-rw-r--r--arch/x86/include/asm/uaccess.h3
-rw-r--r--arch/x86/include/asm/uv/uv_bau.h59
-rw-r--r--arch/x86/include/asm/uv/uv_mmrs.h2889
-rw-r--r--arch/x86/include/asm/vgtod.h3
-rw-r--r--arch/x86/include/asm/vmx.h43
-rw-r--r--arch/x86/include/asm/vsyscall.h4
-rw-r--r--arch/x86/include/asm/vvar.h24
-rw-r--r--arch/x86/include/asm/xen/hypercall.h22
-rw-r--r--arch/x86/include/asm/xen/pci.h5
-rw-r--r--arch/x86/include/asm/xen/trace_types.h18
-rw-r--r--arch/x86/kernel/Makefile9
-rw-r--r--arch/x86/kernel/alternative.c23
-rw-r--r--arch/x86/kernel/amd_gart_64.c2
-rw-r--r--arch/x86/kernel/apb_timer.c410
-rw-r--r--arch/x86/kernel/apic/apic.c29
-rw-r--r--arch/x86/kernel/apic/es7000_32.c2
-rw-r--r--arch/x86/kernel/apic/io_apic.c91
-rw-r--r--arch/x86/kernel/apm_32.c8
-rw-r--r--arch/x86/kernel/asm-offsets_32.c1
-rw-r--r--arch/x86/kernel/cpu/bugs.c4
-rw-r--r--arch/x86/kernel/cpu/common.c2
-rw-r--r--arch/x86/kernel/cpu/hypervisor.c4
-rw-r--r--arch/x86/kernel/cpu/intel.c18
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-severity.c152
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c288
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c10
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c182
-rw-r--r--arch/x86/kernel/cpu/perf_event.c168
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c14
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c385
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c4
-rw-r--r--arch/x86/kernel/cpu/perf_event_p4.c119
-rw-r--r--arch/x86/kernel/devicetree.c60
-rw-r--r--arch/x86/kernel/dumpstack_64.c37
-rw-r--r--arch/x86/kernel/entry_64.S84
-rw-r--r--arch/x86/kernel/hpet.c14
-rw-r--r--arch/x86/kernel/i387.c2
-rw-r--r--arch/x86/kernel/i8253.c99
-rw-r--r--arch/x86/kernel/i8259.c2
-rw-r--r--arch/x86/kernel/irqinit.c5
-rw-r--r--arch/x86/kernel/kgdb.c4
-rw-r--r--arch/x86/kernel/kvm.c72
-rw-r--r--arch/x86/kernel/kvmclock.c2
-rw-r--r--arch/x86/kernel/microcode_amd.c21
-rw-r--r--arch/x86/kernel/module.c37
-rw-r--r--arch/x86/kernel/paravirt.c9
-rw-r--r--arch/x86/kernel/pci-calgary_64.c2
-rw-r--r--arch/x86/kernel/probe_roms.c2
-rw-r--r--arch/x86/kernel/ptrace.c5
-rw-r--r--arch/x86/kernel/quirks.c5
-rw-r--r--arch/x86/kernel/relocate_kernel_32.S2
-rw-r--r--arch/x86/kernel/relocate_kernel_64.S2
-rw-r--r--arch/x86/kernel/signal.c56
-rw-r--r--arch/x86/kernel/smpboot.c2
-rw-r--r--arch/x86/kernel/stacktrace.c2
-rw-r--r--arch/x86/kernel/tboot.c1
-rw-r--r--arch/x86/kernel/time.c2
-rw-r--r--arch/x86/kernel/traps.c8
-rw-r--r--arch/x86/kernel/tsc.c26
-rw-r--r--arch/x86/kernel/vmlinux.lds.S49
-rw-r--r--arch/x86/kernel/vread_tsc_64.c36
-rw-r--r--arch/x86/kernel/vsyscall_64.c310
-rw-r--r--arch/x86/kernel/vsyscall_emu_64.S27
-rw-r--r--arch/x86/kvm/Kconfig2
-rw-r--r--arch/x86/kvm/emulate.c1749
-rw-r--r--arch/x86/kvm/lapic.c2
-rw-r--r--arch/x86/kvm/mmu.c1227
-rw-r--r--arch/x86/kvm/mmu.h25
-rw-r--r--arch/x86/kvm/mmu_audit.c12
-rw-r--r--arch/x86/kvm/mmutrace.h48
-rw-r--r--arch/x86/kvm/paging_tmpl.h258
-rw-r--r--arch/x86/kvm/svm.c6
-rw-r--r--arch/x86/kvm/timer.c2
-rw-r--r--arch/x86/kvm/trace.h31
-rw-r--r--arch/x86/kvm/vmx.c2784
-rw-r--r--arch/x86/kvm/x86.c374
-rw-r--r--arch/x86/kvm/x86.h44
-rw-r--r--arch/x86/lguest/boot.c36
-rw-r--r--arch/x86/lguest/i386_head.S35
-rw-r--r--arch/x86/lib/Makefile9
-rw-r--r--arch/x86/lib/atomic64_32.c2
-rw-r--r--arch/x86/lib/copy_page_64.S9
-rw-r--r--arch/x86/lib/memmove_64.S11
-rw-r--r--arch/x86/lib/rwlock.S44
-rw-r--r--arch/x86/lib/rwlock_64.S38
-rw-r--r--arch/x86/lib/rwsem.S (renamed from arch/x86/lib/rwsem_64.S)75
-rw-r--r--arch/x86/lib/semaphore_32.S124
-rw-r--r--arch/x86/lib/thunk_64.S45
-rw-r--r--arch/x86/lib/usercopy.c43
-rw-r--r--arch/x86/mm/fault.c6
-rw-r--r--arch/x86/mm/kmemcheck/error.c2
-rw-r--r--arch/x86/mm/mmio-mod.c2
-rw-r--r--arch/x86/mm/numa.c15
-rw-r--r--arch/x86/mm/numa_32.c6
-rw-r--r--arch/x86/mm/pageattr-test.c3
-rw-r--r--arch/x86/oprofile/backtrace.c21
-rw-r--r--arch/x86/pci/mmconfig-shared.c3
-rw-r--r--arch/x86/pci/xen.c371
-rw-r--r--arch/x86/platform/efi/efi.c90
-rw-r--r--arch/x86/platform/olpc/Makefile5
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-pm.c215
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-rtc.c81
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-sci.c614
-rw-r--r--arch/x86/platform/olpc/olpc-xo1.c146
-rw-r--r--arch/x86/platform/olpc/olpc-xo15-sci.c168
-rw-r--r--arch/x86/platform/olpc/olpc.c95
-rw-r--r--arch/x86/platform/olpc/olpc_dt.c103
-rw-r--r--arch/x86/platform/olpc/xo1-wakeup.S124
-rw-r--r--arch/x86/platform/uv/tlb_uv.c69
-rw-r--r--arch/x86/vdso/Makefile1
-rw-r--r--arch/x86/vdso/vclock_gettime.c103
-rw-r--r--arch/x86/vdso/vdso.S15
-rw-r--r--arch/x86/vdso/vma.c58
-rw-r--r--arch/x86/xen/Makefile4
-rw-r--r--arch/x86/xen/enlighten.c24
-rw-r--r--arch/x86/xen/mmu.c139
-rw-r--r--arch/x86/xen/multicalls.c169
-rw-r--r--arch/x86/xen/multicalls.h6
-rw-r--r--arch/x86/xen/platform-pci-unplug.c2
-rw-r--r--arch/x86/xen/trace.c61
-rw-r--r--arch/x86/xen/vga.c67
-rw-r--r--arch/x86/xen/xen-ops.h11
-rw-r--r--arch/xtensa/Kconfig13
-rw-r--r--arch/xtensa/include/asm/atomic.h10
-rw-r--r--arch/xtensa/include/asm/bitops.h14
-rw-r--r--arch/xtensa/include/asm/posix_types.h2
-rw-r--r--arch/xtensa/include/asm/ptrace.h1
-rw-r--r--arch/xtensa/include/asm/uaccess.h4
-rw-r--r--arch/xtensa/kernel/module.c43
-rw-r--r--arch/xtensa/kernel/process.c2
-rw-r--r--arch/xtensa/kernel/ptrace.c3
-rw-r--r--arch/xtensa/variants/s6000/include/variant/dmac.h2
-rw-r--r--block/blk-core.c40
-rw-r--r--block/blk-exec.c7
-rw-r--r--block/blk-ioc.c40
-rw-r--r--block/blk-lib.c5
-rw-r--r--block/blk-softirq.c11
-rw-r--r--block/blk-sysfs.c13
-rw-r--r--block/blk-throttle.c8
-rw-r--r--block/bsg.c18
-rw-r--r--block/cfq-iosched.c152
-rw-r--r--block/compat_ioctl.c14
-rw-r--r--block/deadline-iosched.c4
-rw-r--r--block/elevator.c7
-rw-r--r--block/genhd.c38
-rw-r--r--crypto/Kconfig6
-rw-r--r--crypto/af_alg.c2
-rw-r--r--crypto/algif_hash.c4
-rw-r--r--crypto/arc4.c15
-rw-r--r--crypto/async_tx/raid6test.c1
-rw-r--r--crypto/crc32c.c10
-rw-r--r--crypto/gf128mul.c4
-rw-r--r--crypto/proc.c2
-rw-r--r--crypto/rng.c2
-rw-r--r--crypto/sha1_generic.c11
-rw-r--r--crypto/testmgr.h293
-rw-r--r--drivers/Kconfig8
-rw-r--r--drivers/Makefile5
-rw-r--r--drivers/acpi/ac.c2
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/sbs.c2
-rw-r--r--drivers/acpi/video.c7
-rw-r--r--drivers/ata/Kconfig1
-rw-r--r--drivers/ata/acard-ahci.c27
-rw-r--r--drivers/ata/ahci.c122
-rw-r--r--drivers/ata/ahci.h1
-rw-r--r--drivers/ata/ata_generic.c5
-rw-r--r--drivers/ata/ata_piix.c44
-rw-r--r--drivers/ata/libahci.c152
-rw-r--r--drivers/ata/libata-acpi.c66
-rw-r--r--drivers/ata/libata-core.c400
-rw-r--r--drivers/ata/libata-eh.c154
-rw-r--r--drivers/ata/libata-pmp.c123
-rw-r--r--drivers/ata/libata-scsi.c22
-rw-r--r--drivers/ata/libata-sff.c53
-rw-r--r--drivers/ata/pata_acpi.c8
-rw-r--r--drivers/ata/pata_ali.c8
-rw-r--r--drivers/ata/pata_amd.c8
-rw-r--r--drivers/ata/pata_artop.c5
-rw-r--r--drivers/ata/pata_atp867x.c13
-rw-r--r--drivers/ata/pata_bf54x.c4
-rw-r--r--drivers/ata/pata_cs5520.c3
-rw-r--r--drivers/ata/pata_efar.c5
-rw-r--r--drivers/ata/pata_hpt3x3.c4
-rw-r--r--drivers/ata/pata_icside.c4
-rw-r--r--drivers/ata/pata_it8213.c5
-rw-r--r--drivers/ata/pata_it821x.c16
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c4
-rw-r--r--drivers/ata/pata_legacy.c2
-rw-r--r--drivers/ata/pata_macio.c10
-rw-r--r--drivers/ata/pata_mpiix.c4
-rw-r--r--drivers/ata/pata_netcell.c5
-rw-r--r--drivers/ata/pata_ns87410.c2
-rw-r--r--drivers/ata/pata_ns87415.c5
-rw-r--r--drivers/ata/pata_octeon_cf.c8
-rw-r--r--drivers/ata/pata_oldpiix.c5
-rw-r--r--drivers/ata/pata_opti.c4
-rw-r--r--drivers/ata/pata_optidma.c4
-rw-r--r--drivers/ata/pata_pcmcia.c5
-rw-r--r--drivers/ata/pata_pdc2027x.c6
-rw-r--r--drivers/ata/pata_platform.c2
-rw-r--r--drivers/ata/pata_radisys.c5
-rw-r--r--drivers/ata/pata_rdc.c5
-rw-r--r--drivers/ata/pata_rz1000.c4
-rw-r--r--drivers/ata/pata_samsung_cf.c2
-rw-r--r--drivers/ata/pata_scc.c8
-rw-r--r--drivers/ata/pata_sch.c5
-rw-r--r--drivers/ata/pata_sil680.c4
-rw-r--r--drivers/ata/pata_sis.c5
-rw-r--r--drivers/ata/pata_sl82c105.c6
-rw-r--r--drivers/ata/pata_triflex.c4
-rw-r--r--drivers/ata/pata_via.c8
-rw-r--r--drivers/ata/pdc_adma.c10
-rw-r--r--drivers/ata/sata_dwc_460ex.c24
-rw-r--r--drivers/ata/sata_fsl.c43
-rw-r--r--drivers/ata/sata_inic162x.c31
-rw-r--r--drivers/ata/sata_mv.c94
-rw-r--r--drivers/ata/sata_nv.c79
-rw-r--r--drivers/ata/sata_promise.c6
-rw-r--r--drivers/ata/sata_qstor.c13
-rw-r--r--drivers/ata/sata_sil.c21
-rw-r--r--drivers/ata/sata_sil24.c43
-rw-r--r--drivers/ata/sata_sis.c26
-rw-r--r--drivers/ata/sata_svw.c4
-rw-r--r--drivers/ata/sata_sx4.c4
-rw-r--r--drivers/ata/sata_uli.c4
-rw-r--r--drivers/ata/sata_via.c42
-rw-r--r--drivers/ata/sata_vsc.c9
-rw-r--r--drivers/atm/ambassador.c13
-rw-r--r--drivers/atm/ambassador.h4
-rw-r--r--drivers/atm/atmtcp.c2
-rw-r--r--drivers/atm/eni.c2
-rw-r--r--drivers/atm/eni.h3
-rw-r--r--drivers/atm/firestream.c3
-rw-r--r--drivers/atm/fore200e.c2
-rw-r--r--drivers/atm/horizon.c3
-rw-r--r--drivers/atm/idt77252.c3
-rw-r--r--drivers/atm/iphase.c3
-rw-r--r--drivers/atm/lanai.c9
-rw-r--r--drivers/atm/nicstar.c2
-rw-r--r--drivers/atm/suni.c2
-rw-r--r--drivers/atm/uPD98402.c2
-rw-r--r--drivers/atm/zatm.c3
-rw-r--r--drivers/base/Kconfig66
-rw-r--r--drivers/base/Makefile2
-rw-r--r--drivers/base/devtmpfs.c338
-rw-r--r--drivers/base/memory.c2
-rw-r--r--drivers/base/platform.c21
-rw-r--r--drivers/base/power/Makefile1
-rw-r--r--drivers/base/power/clock_ops.c234
-rw-r--r--drivers/base/power/domain.c1273
-rw-r--r--drivers/base/power/generic_ops.c98
-rw-r--r--drivers/base/power/main.c65
-rw-r--r--drivers/base/power/opp.c19
-rw-r--r--drivers/base/power/runtime.c89
-rw-r--r--drivers/base/power/sysfs.c8
-rw-r--r--drivers/base/power/trace.c2
-rw-r--r--drivers/base/regmap/Kconfig13
-rw-r--r--drivers/base/regmap/Makefile3
-rw-r--r--drivers/base/regmap/regmap-i2c.c115
-rw-r--r--drivers/base/regmap/regmap-spi.c72
-rw-r--r--drivers/base/regmap/regmap.c455
-rw-r--r--drivers/bcma/Kconfig11
-rw-r--r--drivers/bcma/Makefile3
-rw-r--r--drivers/bcma/bcma_private.h11
-rw-r--r--drivers/bcma/core.c75
-rw-r--r--drivers/bcma/driver_chipcommon.c16
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c8
-rw-r--r--drivers/bcma/driver_pci.c66
-rw-r--r--drivers/bcma/driver_pci_host.c14
-rw-r--r--drivers/bcma/host_pci.c53
-rw-r--r--drivers/bcma/main.c14
-rw-r--r--drivers/bcma/sprom.c171
-rw-r--r--drivers/block/cciss.h2
-rw-r--r--drivers/block/cciss_scsi.c2
-rw-r--r--drivers/block/hd.c2
-rw-r--r--drivers/block/pktcdvd.c2
-rw-r--r--drivers/block/rbd.c46
-rw-r--r--drivers/block/xen-blkback/blkback.c37
-rw-r--r--drivers/block/xen-blkback/xenbus.c2
-rw-r--r--drivers/block/xsysace.c98
-rw-r--r--drivers/bluetooth/ath3k.c5
-rw-r--r--drivers/bluetooth/btusb.c12
-rw-r--r--drivers/char/apm-emulation.c2
-rw-r--r--drivers/char/bsr.c2
-rw-r--r--drivers/char/generic_nvram.c4
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hw_random/Kconfig12
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/core.c2
-rw-r--r--drivers/char/hw_random/nomadik-rng.c3
-rw-r--r--drivers/char/hw_random/omap-rng.c6
-rw-r--r--drivers/char/hw_random/ppc4xx-rng.c156
-rw-r--r--drivers/char/hw_random/timeriomem-rng.c3
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c2
-rw-r--r--drivers/char/mspec.c2
-rw-r--r--drivers/char/nvram.c2
-rw-r--r--drivers/char/ps3flash.c13
-rw-r--r--drivers/char/ramoops.c92
-rw-r--r--drivers/char/random.c15
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c2
-rw-r--r--drivers/clk/Kconfig3
-rw-r--r--drivers/clocksource/Kconfig12
-rw-r--r--drivers/clocksource/Makefile3
-rw-r--r--drivers/clocksource/dw_apb_timer.c401
-rw-r--r--drivers/clocksource/i8253.c114
-rw-r--r--drivers/connector/cn_proc.c37
-rw-r--r--drivers/cpufreq/Kconfig10
-rw-r--r--drivers/cpufreq/Kconfig.arm32
-rw-r--r--drivers/cpufreq/Kconfig.powerpc7
-rw-r--r--drivers/cpufreq/Makefile12
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c2
-rw-r--r--drivers/cpufreq/cpufreq.c20
-rw-r--r--drivers/cpufreq/exynos4210-cpufreq.c (renamed from arch/arm/mach-exynos4/cpufreq.c)9
-rw-r--r--drivers/cpufreq/maple-cpufreq.c309
-rw-r--r--drivers/cpufreq/s3c64xx-cpufreq.c (renamed from arch/arm/mach-s3c64xx/cpufreq.c)11
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c (renamed from arch/arm/mach-s5pv210/cpufreq.c)210
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c5
-rw-r--r--drivers/crypto/caam/caamalg.c1832
-rw-r--r--drivers/crypto/caam/compat.h1
-rw-r--r--drivers/crypto/caam/ctrl.c30
-rw-r--r--drivers/crypto/caam/desc_constr.h58
-rw-r--r--drivers/crypto/omap-sham.c180
-rw-r--r--drivers/crypto/talitos.c47
-rw-r--r--drivers/dma/Kconfig7
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/coh901318.c1
-rw-r--r--drivers/dma/dmaengine.c1
-rw-r--r--drivers/dma/dmatest.c1
-rw-r--r--drivers/dma/ep93xx_dma.c1355
-rw-r--r--drivers/dma/imx-dma.c3
-rw-r--r--drivers/dma/imx-sdma.c6
-rw-r--r--drivers/dma/ipu/ipu_idmac.c1
-rw-r--r--drivers/dma/mv_xor.c5
-rw-r--r--drivers/dma/ste_dma40.c1
-rw-r--r--drivers/edac/cell_edac.c2
-rw-r--r--drivers/edac/edac_stub.c2
-rw-r--r--drivers/edac/mpc85xx_edac.c16
-rw-r--r--drivers/eisa/pci_eisa.c4
-rw-r--r--drivers/firewire/core-card.c2
-rw-r--r--drivers/firewire/core-cdev.c20
-rw-r--r--drivers/firewire/core-device.c2
-rw-r--r--drivers/firewire/core-topology.c2
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/net.c11
-rw-r--r--drivers/firewire/nosy.c2
-rw-r--r--drivers/firewire/ohci.c42
-rw-r--r--drivers/firmware/google/gsmi.c19
-rw-r--r--drivers/firmware/iscsi_ibft.c14
-rw-r--r--drivers/firmware/sigma.c3
-rw-r--r--drivers/gpio/Kconfig66
-rw-r--r--drivers/gpio/Makefile87
-rw-r--r--drivers/gpio/gpio-74x164.c (renamed from drivers/gpio/74x164.c)33
-rw-r--r--drivers/gpio/gpio-ab8500.c (renamed from drivers/gpio/ab8500-gpio.c)1
-rw-r--r--drivers/gpio/gpio-adp5520.c (renamed from drivers/gpio/adp5520-gpio.c)0
-rw-r--r--drivers/gpio/gpio-adp5588.c (renamed from drivers/gpio/adp5588-gpio.c)0
-rw-r--r--drivers/gpio/gpio-bt8xx.c (renamed from drivers/gpio/bt8xxgpio.c)2
-rw-r--r--drivers/gpio/gpio-cs5535.c (renamed from drivers/gpio/cs5535-gpio.c)0
-rw-r--r--drivers/gpio/gpio-da9052.c277
-rw-r--r--drivers/gpio/gpio-ep93xx.c (renamed from arch/arm/mach-ep93xx/gpio.c)245
-rw-r--r--drivers/gpio/gpio-exynos4.c5
-rw-r--r--drivers/gpio/gpio-generic.c (renamed from drivers/gpio/basic_mmio_gpio.c)6
-rw-r--r--drivers/gpio/gpio-it8761e.c (renamed from drivers/gpio/it8761e_gpio.c)2
-rw-r--r--drivers/gpio/gpio-janz-ttl.c (renamed from drivers/gpio/janz-ttl.c)0
-rw-r--r--drivers/gpio/gpio-langwell.c (renamed from drivers/gpio/langwell_gpio.c)4
-rw-r--r--drivers/gpio/gpio-max7300.c (renamed from drivers/gpio/max7300.c)2
-rw-r--r--drivers/gpio/gpio-max7301.c (renamed from drivers/gpio/max7301.c)2
-rw-r--r--drivers/gpio/gpio-max730x.c (renamed from drivers/gpio/max730x.c)2
-rw-r--r--drivers/gpio/gpio-max732x.c (renamed from drivers/gpio/max732x.c)2
-rw-r--r--drivers/gpio/gpio-mc33880.c (renamed from drivers/gpio/mc33880.c)2
-rw-r--r--drivers/gpio/gpio-mcp23s08.c (renamed from drivers/gpio/mcp23s08.c)291
-rw-r--r--drivers/gpio/gpio-ml-ioh.c (renamed from drivers/gpio/ml_ioh_gpio.c)2
-rw-r--r--drivers/gpio/gpio-mpc5200.c (renamed from arch/powerpc/platforms/52xx/mpc52xx_gpio.c)12
-rw-r--r--drivers/gpio/gpio-mxc.c460
-rw-r--r--drivers/gpio/gpio-mxs.c289
-rw-r--r--drivers/gpio/gpio-omap.c723
-rw-r--r--drivers/gpio/gpio-pca953x.c (renamed from drivers/gpio/pca953x.c)105
-rw-r--r--drivers/gpio/gpio-pcf857x.c (renamed from drivers/gpio/pcf857x.c)2
-rw-r--r--drivers/gpio/gpio-pch.c (renamed from drivers/gpio/pch_gpio.c)0
-rw-r--r--drivers/gpio/gpio-pl061.c (renamed from drivers/gpio/pl061.c)4
-rw-r--r--drivers/gpio/gpio-plat-samsung.c3
-rw-r--r--drivers/gpio/gpio-rdc321x.c (renamed from drivers/gpio/rdc321x-gpio.c)0
-rw-r--r--drivers/gpio/gpio-s5pc100.c5
-rw-r--r--drivers/gpio/gpio-s5pv210.c5
-rw-r--r--drivers/gpio/gpio-sch.c (renamed from drivers/gpio/sch_gpio.c)2
-rw-r--r--drivers/gpio/gpio-stmpe.c (renamed from drivers/gpio/stmpe-gpio.c)0
-rw-r--r--drivers/gpio/gpio-sx150x.c (renamed from drivers/gpio/sx150x.c)0
-rw-r--r--drivers/gpio/gpio-tc3589x.c (renamed from drivers/gpio/tc3589x-gpio.c)0
-rw-r--r--drivers/gpio/gpio-tegra.c (renamed from arch/arm/mach-tegra/gpio.c)10
-rw-r--r--drivers/gpio/gpio-timberdale.c (renamed from drivers/gpio/timbgpio.c)2
-rw-r--r--drivers/gpio/gpio-tps65910.c (renamed from drivers/gpio/tps65910-gpio.c)2
-rw-r--r--drivers/gpio/gpio-twl4030.c (renamed from drivers/gpio/twl4030-gpio.c)2
-rw-r--r--drivers/gpio/gpio-u300.c13
-rw-r--r--drivers/gpio/gpio-ucb1400.c (renamed from drivers/gpio/ucb1400_gpio.c)0
-rw-r--r--drivers/gpio/gpio-vr41xx.c (renamed from drivers/gpio/vr41xx_giu.c)2
-rw-r--r--drivers/gpio/gpio-vx855.c (renamed from drivers/gpio/vx855_gpio.c)0
-rw-r--r--drivers/gpio/gpio-wm831x.c (renamed from drivers/gpio/wm831x-gpio.c)2
-rw-r--r--drivers/gpio/gpio-wm8350.c (renamed from drivers/gpio/wm8350-gpiolib.c)2
-rw-r--r--drivers/gpio/gpio-wm8994.c (renamed from drivers/gpio/wm8994-gpio.c)2
-rw-r--r--drivers/gpio/gpio-xilinx.c (renamed from drivers/gpio/xilinx_gpio.c)0
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c5
-rw-r--r--drivers/gpu/drm/drm_edid.c4
-rw-r--r--drivers/gpu/drm/drm_gem.c47
-rw-r--r--drivers/gpu/drm/drm_modes.c87
-rw-r--r--drivers/gpu/drm/drm_platform.c5
-rw-r--r--drivers/gpu/drm/drm_scatter.c10
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c41
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c69
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h46
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c191
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c39
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c13
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h6
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c8
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c142
-rw-r--r--drivers/gpu/drm/i915/intel_display.c699
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c17
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h9
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c8
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c15
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c6
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c6
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c46
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c50
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c232
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_channel.c167
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c34
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h78
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fb.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c15
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c31
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c148
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c119
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_notifier.c20
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c98
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sgdma.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c114
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_temp.c15
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.c21
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h2
-rw-r--r--drivers/gpu/drm/nouveau/nv04_crtc.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv04_graph.c22
-rw-r--r--drivers/gpu/drm/nouveau/nv04_instmem.c28
-rw-r--r--drivers/gpu/drm/nouveau/nv10_graph.c15
-rw-r--r--drivers/gpu/drm/nouveau/nv20_graph.c13
-rw-r--r--drivers/gpu/drm/nouveau/nv40_graph.c112
-rw-r--r--drivers/gpu/drm/nouveau/nv40_mpeg.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c6
-rw-r--r--drivers/gpu/drm/nouveau/nv50_evo.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_graph.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_instmem.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv50_mpeg.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vram.c41
-rw-r--r--drivers/gpu/drm/nouveau/nv84_crypt.c2
-rw-r--r--drivers/gpu/drm/nouveau/nva3_copy.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_copy.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fb.c68
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fbcon.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fifo.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.c270
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.fuc400
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.h24
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grctx.c239
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grgpc.fuc474
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h483
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grhub.fuc808
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h838
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_instmem.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vm.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vram.c14
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c5
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c22
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c7
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c57
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h2
-rw-r--r--drivers/gpu/drm/radeon/ni.c1
-rw-r--r--drivers/gpu/drm/radeon/r600.c15
-rw-r--r--drivers/gpu/drm/radeon/r600_cp.c23
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon.h27
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_clocks.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c42
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c15
-rw-r--r--drivers/gpu/drm/radeon/radeon_mem.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_reg.h2
-rw-r--r--drivers/gpu/drm/radeon/reg_srcs/cayman2
-rw-r--r--drivers/gpu/drm/radeon/reg_srcs/evergreen3
-rw-r--r--drivers/gpu/drm/radeon/reg_srcs/r6001
-rw-r--r--drivers/gpu/drm/radeon/rs600.c2
-rw-r--r--drivers/gpu/drm/radeon/rv770.c1
-rw-r--r--drivers/gpu/drm/sis/sis_drv.h4
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_lock.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_object.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc.c18
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c8
-rw-r--r--drivers/gpu/vga/vgaarb.c3
-rw-r--r--drivers/hid/Kconfig44
-rw-r--r--drivers/hid/Makefile3
-rw-r--r--drivers/hid/hid-axff.c1
-rw-r--r--drivers/hid/hid-core.c13
-rw-r--r--drivers/hid/hid-emsff.c7
-rw-r--r--drivers/hid/hid-holtekff.c240
-rw-r--r--drivers/hid/hid-ids.h15
-rw-r--r--drivers/hid/hid-lg.c74
-rw-r--r--drivers/hid/hid-microsoft.c28
-rw-r--r--drivers/hid/hid-multitouch.c4
-rw-r--r--drivers/hid/hid-prodikeys.c17
-rw-r--r--drivers/hid/hid-roccat-arvo.c21
-rw-r--r--drivers/hid/hid-roccat-arvo.h13
-rw-r--r--drivers/hid/hid-roccat-common.c20
-rw-r--r--drivers/hid/hid-roccat-common.h4
-rw-r--r--drivers/hid/hid-roccat-kone.c56
-rw-r--r--drivers/hid/hid-roccat-kone.h2
-rw-r--r--drivers/hid/hid-roccat-koneplus.c49
-rw-r--r--drivers/hid/hid-roccat-koneplus.h23
-rw-r--r--drivers/hid/hid-roccat-kovaplus.c25
-rw-r--r--drivers/hid/hid-roccat-kovaplus.h9
-rw-r--r--drivers/hid/hid-roccat-pyra.c25
-rw-r--r--drivers/hid/hid-roccat-pyra.h9
-rw-r--r--drivers/hid/hid-sony.c35
-rw-r--r--drivers/hid/hid-speedlink.c89
-rw-r--r--drivers/hid/hid-uclogic.c195
-rw-r--r--drivers/hid/hid-wiimote.c489
-rw-r--r--drivers/hid/usbhid/hid-core.c2
-rw-r--r--drivers/hwmon/Kconfig21
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/gl520sm.c2
-rw-r--r--drivers/hwmon/hwmon-vid.c42
-rw-r--r--drivers/hwmon/it87.c29
-rw-r--r--drivers/hwmon/lm78.c305
-rw-r--r--drivers/hwmon/max1111.c27
-rw-r--r--drivers/hwmon/sch5627.c334
-rw-r--r--drivers/hwmon/sch5636.c539
-rw-r--r--drivers/hwmon/sch56xx-common.c340
-rw-r--r--drivers/hwmon/sch56xx-common.h24
-rw-r--r--drivers/hwmon/sht15.c4
-rw-r--r--drivers/hwmon/via-cputemp.c44
-rw-r--r--drivers/i2c/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c61
-rw-r--r--drivers/i2c/busses/i2c-cpm.c7
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c41
-rw-r--r--drivers/i2c/busses/i2c-highlander.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c4
-rw-r--r--drivers/i2c/busses/i2c-pxa.c7
-rw-r--r--drivers/i2c/busses/i2c-s6000.c5
-rw-r--r--drivers/i2c/busses/i2c-tegra.c17
-rw-r--r--drivers/i2c/i2c-core.c5
-rw-r--r--drivers/ide/palm_bk3710.c2
-rw-r--r--drivers/ide/tx4939ide.c4
-rw-r--r--drivers/ieee802154/Makefile2
-rw-r--r--drivers/ieee802154/fakehard.c2
-rw-r--r--drivers/infiniband/core/addr.c7
-rw-r--r--drivers/infiniband/core/cache.c3
-rw-r--r--drivers/infiniband/core/cma.c84
-rw-r--r--drivers/infiniband/core/device.c6
-rw-r--r--drivers/infiniband/core/netlink.c2
-rw-r--r--drivers/infiniband/hw/amso1100/c2.c1
-rw-r--r--drivers/infiniband/hw/amso1100/c2_provider.c9
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c12
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c8
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c42
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c2
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c8
-rw-r--r--drivers/infiniband/hw/cxgb4/resource.c9
-rw-r--r--drivers/infiniband/hw/ehca/ehca_tools.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c11
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c198
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c68
-rw-r--r--drivers/infiniband/hw/mlx4/main.c21
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c276
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h93
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c43
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c175
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c101
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c43
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c35
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c77
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c49
-rw-r--r--drivers/infiniband/hw/mthca/mthca_reset.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c33
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c4
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c19
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h4
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c50
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c11
-rw-r--r--drivers/infiniband/hw/qib/qib.h3
-rw-r--r--drivers/infiniband/hw/qib/qib_file_ops.c16
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c26
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c72
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.c78
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.h143
-rw-r--r--drivers/infiniband/hw/qib/qib_pcie.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_sysfs.c14
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c41
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c20
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h1
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c4
-rw-r--r--drivers/input/gameport/gameport.c2
-rw-r--r--drivers/input/joystick/analog.c2
-rw-r--r--drivers/input/misc/Kconfig13
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/pcspkr.c9
-rw-r--r--drivers/input/misc/twl4030-vibra.c12
-rw-r--r--drivers/input/misc/twl6040-vibra.c423
-rw-r--r--drivers/input/serio/libps2.c2
-rw-r--r--drivers/input/serio/sa1111ps2.c6
-rw-r--r--drivers/iommu/Kconfig110
-rw-r--r--drivers/iommu/Makefile5
-rw-r--r--drivers/iommu/amd_iommu.c (renamed from arch/x86/kernel/amd_iommu.c)314
-rw-r--r--drivers/iommu/amd_iommu_init.c (renamed from arch/x86/kernel/amd_iommu_init.c)8
-rw-r--r--drivers/iommu/amd_iommu_proto.h (renamed from arch/x86/include/asm/amd_iommu_proto.h)2
-rw-r--r--drivers/iommu/amd_iommu_types.h (renamed from arch/x86/include/asm/amd_iommu_types.h)9
-rw-r--r--drivers/iommu/dmar.c (renamed from drivers/pci/dmar.c)0
-rw-r--r--drivers/iommu/intel-iommu.c (renamed from drivers/pci/intel-iommu.c)1
-rw-r--r--drivers/iommu/intr_remapping.c (renamed from drivers/pci/intr_remapping.c)1
-rw-r--r--drivers/iommu/intr_remapping.h (renamed from drivers/pci/intr_remapping.h)0
-rw-r--r--drivers/iommu/iommu.c (renamed from drivers/base/iommu.c)0
-rw-r--r--drivers/iommu/iova.c (renamed from drivers/pci/iova.c)0
-rw-r--r--drivers/iommu/msm_iommu.c (renamed from arch/arm/mach-msm/iommu.c)0
-rw-r--r--drivers/iommu/msm_iommu_dev.c (renamed from arch/arm/mach-msm/iommu_dev.c)0
-rw-r--r--drivers/isdn/gigaset/gigaset.h2
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c1
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c1
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c1
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNinfineon.c1
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c1
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c1
-rw-r--r--drivers/isdn/hardware/mISDN/speedfax.c1
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c1
-rw-r--r--drivers/isdn/hisax/hisax.h1
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.c1
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c2
-rw-r--r--drivers/isdn/i4l/isdn_net.c5
-rw-r--r--drivers/leds/Kconfig20
-rw-r--r--drivers/leds/leds-gpio.c6
-rw-r--r--drivers/leds/leds-lm3530.c67
-rw-r--r--drivers/leds/leds-lp5521.c4
-rw-r--r--drivers/leds/leds-sunfire.c12
-rw-r--r--drivers/lguest/core.c2
-rw-r--r--drivers/lguest/interrupts_and_traps.c10
-rw-r--r--drivers/lguest/lg.h2
-rw-r--r--drivers/lguest/lguest_device.c37
-rw-r--r--drivers/lguest/lguest_user.c17
-rw-r--r--drivers/lguest/page_tables.c282
-rw-r--r--drivers/lguest/x86/core.c107
-rw-r--r--drivers/macintosh/nvram.c4
-rw-r--r--drivers/md/dm-crypt.c2
-rw-r--r--drivers/md/dm-kcopyd.c2
-rw-r--r--drivers/md/dm-mpath.c2
-rw-r--r--drivers/md/dm-queue-length.c2
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/linear.c8
-rw-r--r--drivers/md/md.c26
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h1
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_ca.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_common.h1
-rw-r--r--drivers/media/dvb/mantis/mantis_evm.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_hif.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_ioc.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_pcmcia.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_uart.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_vp1034.c1
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c1
-rw-r--r--drivers/media/rc/ite-cir.c1
-rw-r--r--drivers/media/video/davinci/vpif.c2
-rw-r--r--drivers/media/video/hdpvr/hdpvr-core.c2
-rw-r--r--drivers/media/video/m5mols/m5mols_capture.c1
-rw-r--r--drivers/media/video/omap/omap_vout.c2
-rw-r--r--drivers/media/video/omap24xxcam.c5
-rw-r--r--drivers/media/video/tlg2300/pd-dvb.c2
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c2
-rw-r--r--drivers/media/video/uvc/uvc_queue.c2
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c2
-rw-r--r--drivers/media/video/uvc/uvc_video.c2
-rw-r--r--drivers/media/video/videobuf2-memops.c1
-rw-r--r--drivers/message/i2o/i2o_scsi.c2
-rw-r--r--drivers/message/i2o/iop.c8
-rw-r--r--drivers/mfd/Kconfig8
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/tc6387xb.c2
-rw-r--r--drivers/mfd/twl-core.c13
-rw-r--r--drivers/mfd/twl4030-audio.c277
-rw-r--r--drivers/mfd/twl4030-codec.c277
-rw-r--r--drivers/mfd/twl6040-core.c620
-rw-r--r--drivers/mfd/twl6040-irq.c191
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/misc/atmel-ssc.c2
-rw-r--r--drivers/misc/atmel_pwm.c2
-rw-r--r--drivers/misc/eeprom/Kconfig25
-rw-r--r--drivers/misc/eeprom/Makefile2
-rw-r--r--drivers/misc/eeprom/digsy_mtc_eeprom.c85
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c410
-rw-r--r--drivers/misc/fsa9480.c557
-rw-r--r--drivers/misc/pch_phub.c9
-rw-r--r--drivers/misc/phantom.c2
-rw-r--r--drivers/misc/pti.c105
-rw-r--r--drivers/misc/vmw_balloon.c31
-rw-r--r--drivers/mmc/card/block.c681
-rw-r--r--drivers/mmc/card/mmc_test.c498
-rw-r--r--drivers/mmc/card/queue.c217
-rw-r--r--drivers/mmc/card/queue.h33
-rw-r--r--drivers/mmc/core/core.c198
-rw-r--r--drivers/mmc/core/sd.c68
-rw-r--r--drivers/mmc/core/sdio_bus.c8
-rw-r--r--drivers/mmc/host/Kconfig84
-rw-r--r--drivers/mmc/host/Makefile25
-rw-r--r--drivers/mmc/host/at91_mci.c3
-rw-r--r--drivers/mmc/host/at91_mci.h (renamed from arch/arm/mach-at91/include/mach/at91_mci.h)2
-rw-r--r--drivers/mmc/host/atmel-mci.c63
-rw-r--r--drivers/mmc/host/dw_mmc.c448
-rw-r--r--drivers/mmc/host/dw_mmc.h17
-rw-r--r--drivers/mmc/host/mmci.c157
-rw-r--r--drivers/mmc/host/mmci.h8
-rw-r--r--drivers/mmc/host/mxcmmc.c8
-rw-r--r--drivers/mmc/host/mxs-mmc.c30
-rw-r--r--drivers/mmc/host/omap_hsmmc.c671
-rw-r--r--drivers/mmc/host/sdhci-cns3xxx.c44
-rw-r--r--drivers/mmc/host/sdhci-dove.c43
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c125
-rw-r--r--drivers/mmc/host/sdhci-of-core.c253
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c86
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c67
-rw-r--r--drivers/mmc/host/sdhci-of.h42
-rw-r--r--drivers/mmc/host/sdhci-pci.c54
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c216
-rw-r--r--drivers/mmc/host/sdhci-pltfm.h90
-rw-r--r--drivers/mmc/host/sdhci-pxa.c303
-rw-r--r--drivers/mmc/host/sdhci-pxav2.c244
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c289
-rw-r--r--drivers/mmc/host/sdhci-s3c.c6
-rw-r--r--drivers/mmc/host/sdhci-tegra.c117
-rw-r--r--drivers/mmc/host/sdhci.c34
-rw-r--r--drivers/mmc/host/sh_mmcif.c27
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c36
-rw-r--r--drivers/mmc/host/tmio_mmc.h54
-rw-r--r--drivers/mmc/host/tmio_mmc_dma.c8
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c205
-rw-r--r--drivers/mmc/host/vub300.c4
-rw-r--r--drivers/mtd/devices/sst25l.c4
-rw-r--r--drivers/mtd/maps/bfin-async-flash.c2
-rw-r--r--drivers/mtd/maps/ixp2000.c11
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c2
-rw-r--r--drivers/mtd/mtdchar.c2
-rw-r--r--drivers/mtd/nand/atmel_nand.c5
-rw-r--r--drivers/mtd/nand/bcm_umi_nand.c2
-rw-r--r--drivers/mtd/nand/mpc5121_nfc.c2
-rw-r--r--drivers/mtd/ubi/build.c28
-rw-r--r--drivers/mtd/ubi/cdev.c10
-rw-r--r--drivers/mtd/ubi/debug.c269
-rw-r--r--drivers/mtd/ubi/debug.h113
-rw-r--r--drivers/mtd/ubi/io.c20
-rw-r--r--drivers/mtd/ubi/scan.c2
-rw-r--r--drivers/mtd/ubi/ubi.h8
-rw-r--r--drivers/mtd/ubi/vmt.c2
-rw-r--r--drivers/mtd/ubi/vtbl.c18
-rw-r--r--drivers/mtd/ubi/wl.c42
-rw-r--r--drivers/net/3c503.c1
-rw-r--r--drivers/net/7990.c9
-rw-r--r--drivers/net/8139cp.c84
-rw-r--r--drivers/net/8139too.c1
-rw-r--r--drivers/net/8390.h1
-rw-r--r--drivers/net/Kconfig43
-rw-r--r--drivers/net/Makefile3
-rw-r--r--drivers/net/a2065.c356
-rw-r--r--drivers/net/ac3200.c1
-rw-r--r--drivers/net/acenic.c66
-rw-r--r--drivers/net/acenic.h8
-rw-r--r--drivers/net/amd8111e.c37
-rw-r--r--drivers/net/amd8111e.h3
-rw-r--r--drivers/net/apne.c1
-rw-r--r--drivers/net/appletalk/ltpc.c8
-rw-r--r--drivers/net/arcnet/arc-rimi.c1
-rw-r--r--drivers/net/arcnet/com20020-isa.c1
-rw-r--r--drivers/net/arcnet/com20020-pci.c1
-rw-r--r--drivers/net/arcnet/com20020.c1
-rw-r--r--drivers/net/arcnet/com90io.c1
-rw-r--r--drivers/net/arcnet/com90xx.c1
-rw-r--r--drivers/net/ariadne.c1267
-rw-r--r--drivers/net/arm/am79c961a.c14
-rw-r--r--drivers/net/arm/at91_ether.c1
-rw-r--r--drivers/net/arm/ep93xx_eth.c1
-rw-r--r--drivers/net/arm/ks8695net.c2
-rw-r--r--drivers/net/atl1c/atl1c.h3
-rw-r--r--drivers/net/atl1c/atl1c_main.c74
-rw-r--r--drivers/net/atl1e/atl1e.h3
-rw-r--r--drivers/net/atl1e/atl1e_main.c84
-rw-r--r--drivers/net/atlx/atl1.c23
-rw-r--r--drivers/net/atlx/atl1.h1
-rw-r--r--drivers/net/atlx/atl2.c83
-rw-r--r--drivers/net/atlx/atl2.h5
-rw-r--r--drivers/net/atlx/atlx.c57
-rw-r--r--drivers/net/b44.c23
-rw-r--r--drivers/net/bcm63xx_enet.c9
-rw-r--r--drivers/net/benet/be.h16
-rw-r--r--drivers/net/benet/be_cmds.c142
-rw-r--r--drivers/net/benet/be_cmds.h29
-rw-r--r--drivers/net/benet/be_ethtool.c55
-rw-r--r--drivers/net/benet/be_main.c430
-rw-r--r--drivers/net/bmac.c9
-rw-r--r--drivers/net/bna/bfa_cee.c63
-rw-r--r--drivers/net/bna/bfa_cee.h3
-rw-r--r--drivers/net/bna/bfa_cs.h (renamed from drivers/net/bna/bfa_sm.h)78
-rw-r--r--drivers/net/bna/bfa_defs.h5
-rw-r--r--drivers/net/bna/bfa_defs_mfg_comm.h20
-rw-r--r--drivers/net/bna/bfa_defs_status.h134
-rw-r--r--drivers/net/bna/bfa_ioc.c157
-rw-r--r--drivers/net/bna/bfa_ioc.h51
-rw-r--r--drivers/net/bna/bfa_wc.h69
-rw-r--r--drivers/net/bna/bfi.h20
-rw-r--r--drivers/net/bna/bna.h18
-rw-r--r--drivers/net/bna/bna_ctrl.c45
-rw-r--r--drivers/net/bna/bna_hw.h92
-rw-r--r--drivers/net/bna/bna_txrx.c44
-rw-r--r--drivers/net/bna/bna_types.h58
-rw-r--r--drivers/net/bna/bnad.c128
-rw-r--r--drivers/net/bna/bnad.h30
-rw-r--r--drivers/net/bna/bnad_ethtool.c2
-rw-r--r--drivers/net/bna/cna.h5
-rw-r--r--drivers/net/bnx2.c97
-rw-r--r--drivers/net/bnx2.h15
-rw-r--r--drivers/net/bnx2x/Makefile2
-rw-r--r--drivers/net/bnx2x/bnx2x.h1105
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.c1497
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.h675
-rw-r--r--drivers/net/bnx2x/bnx2x_dcb.c880
-rw-r--r--drivers/net/bnx2x/bnx2x_dcb.h30
-rw-r--r--drivers/net/bnx2x/bnx2x_dump.h1721
-rw-r--r--drivers/net/bnx2x/bnx2x_ethtool.c698
-rw-r--r--drivers/net/bnx2x/bnx2x_fw_defs.h519
-rw-r--r--drivers/net/bnx2x/bnx2x_hsi.h5399
-rw-r--r--drivers/net/bnx2x/bnx2x_init.h409
-rw-r--r--drivers/net/bnx2x/bnx2x_init_ops.h194
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c6355
-rw-r--r--drivers/net/bnx2x/bnx2x_link.h183
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c6225
-rw-r--r--drivers/net/bnx2x/bnx2x_reg.h957
-rw-r--r--drivers/net/bnx2x/bnx2x_sp.c5692
-rw-r--r--drivers/net/bnx2x/bnx2x_sp.h1297
-rw-r--r--drivers/net/bnx2x/bnx2x_stats.c908
-rw-r--r--drivers/net/bnx2x/bnx2x_stats.h228
-rw-r--r--drivers/net/bonding/bond_3ad.c53
-rw-r--r--drivers/net/bonding/bond_3ad.h8
-rw-r--r--drivers/net/bonding/bond_alb.c4
-rw-r--r--drivers/net/bonding/bond_ipv6.c8
-rw-r--r--drivers/net/bonding/bond_main.c127
-rw-r--r--drivers/net/bonding/bond_procfs.c1
-rw-r--r--drivers/net/bonding/bond_sysfs.c34
-rw-r--r--drivers/net/bonding/bonding.h8
-rw-r--r--drivers/net/bsd_comp.c2
-rw-r--r--drivers/net/caif/Kconfig9
-rw-r--r--drivers/net/caif/Makefile3
-rw-r--r--drivers/net/caif/caif_hsi.c1219
-rw-r--r--drivers/net/caif/caif_serial.c2
-rw-r--r--drivers/net/caif/caif_shm_u5500.c1
-rw-r--r--drivers/net/caif/caif_shmcore.c2
-rw-r--r--drivers/net/caif/caif_spi.c1
-rw-r--r--drivers/net/caif/caif_spi_slave.c1
-rw-r--r--drivers/net/can/Kconfig8
-rw-r--r--drivers/net/can/at91_can.c366
-rw-r--r--drivers/net/can/bfin_can.c137
-rw-r--r--drivers/net/can/c_can/c_can.c2
-rw-r--r--drivers/net/can/c_can/c_can_platform.c2
-rw-r--r--drivers/net/can/dev.c2
-rw-r--r--drivers/net/can/janz-ican3.c1
-rw-r--r--drivers/net/can/sja1000/sja1000.h1
-rw-r--r--drivers/net/can/sja1000/sja1000_of_platform.c1
-rw-r--r--drivers/net/can/slcan.c63
-rw-r--r--drivers/net/can/softing/softing_fw.c1
-rw-r--r--drivers/net/can/softing/softing_main.c4
-rw-r--r--drivers/net/cassini.c3
-rw-r--r--drivers/net/chelsio/common.h2
-rw-r--r--drivers/net/chelsio/cxgb2.c39
-rw-r--r--drivers/net/chelsio/sge.c18
-rw-r--r--drivers/net/chelsio/sge.h2
-rw-r--r--drivers/net/cnic.c412
-rw-r--r--drivers/net/cnic.h52
-rw-r--r--drivers/net/cnic_defs.h5288
-rw-r--r--drivers/net/cnic_if.h15
-rw-r--r--drivers/net/cpmac.c3
-rw-r--r--drivers/net/cxgb3/adapter.h2
-rw-r--r--drivers/net/cxgb3/common.h1
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c51
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c21
-rw-r--r--drivers/net/cxgb3/l2t.h2
-rw-r--r--drivers/net/cxgb3/sge.c35
-rw-r--r--drivers/net/cxgb3/t3_hw.c11
-rw-r--r--drivers/net/cxgb3/t3cdev.h2
-rw-r--r--drivers/net/cxgb4/cxgb4.h1
-rw-r--r--drivers/net/cxgb4/cxgb4_main.c2
-rw-r--r--drivers/net/cxgb4/cxgb4_uld.h2
-rw-r--r--drivers/net/cxgb4/l2t.h2
-rw-r--r--drivers/net/cxgb4vf/adapter.h2
-rw-r--r--drivers/net/cxgb4vf/cxgb4vf_main.c68
-rw-r--r--drivers/net/cxgb4vf/sge.c34
-rw-r--r--drivers/net/cxgb4vf/t4vf_hw.c1
-rw-r--r--drivers/net/davinci_cpdma.c2
-rw-r--r--drivers/net/davinci_emac.c13
-rw-r--r--drivers/net/declance.c47
-rw-r--r--drivers/net/depca.c31
-rw-r--r--drivers/net/dl2k.c4
-rw-r--r--drivers/net/dm9000.c27
-rw-r--r--drivers/net/dnet.c3
-rw-r--r--drivers/net/e100.c2
-rw-r--r--drivers/net/e1000/e1000.h2
-rw-r--r--drivers/net/e1000/e1000_ethtool.c69
-rw-r--r--drivers/net/e1000/e1000_hw.c7
-rw-r--r--drivers/net/e1000/e1000_main.c203
-rw-r--r--drivers/net/e1000e/82571.c5
-rw-r--r--drivers/net/e1000e/e1000.h51
-rw-r--r--drivers/net/e1000e/es2lan.c8
-rw-r--r--drivers/net/e1000e/ethtool.c1
-rw-r--r--drivers/net/e1000e/hw.h21
-rw-r--r--drivers/net/e1000e/ich8lan.c191
-rw-r--r--drivers/net/e1000e/lib.c4
-rw-r--r--drivers/net/e1000e/netdev.c171
-rw-r--r--drivers/net/e1000e/phy.c352
-rw-r--r--drivers/net/e2100.c1
-rw-r--r--drivers/net/eexpress.c2
-rw-r--r--drivers/net/ehea/ehea.h1
-rw-r--r--drivers/net/ehea/ehea_main.c54
-rw-r--r--drivers/net/ehea/ehea_qmr.c2
-rw-r--r--drivers/net/enic/enic.h4
-rw-r--r--drivers/net/enic/enic_dev.c11
-rw-r--r--drivers/net/enic/enic_dev.h1
-rw-r--r--drivers/net/enic/enic_main.c153
-rw-r--r--drivers/net/enic/enic_res.c30
-rw-r--r--drivers/net/enic/vnic_cq.c2
-rw-r--r--drivers/net/enic/vnic_cq.h1
-rw-r--r--drivers/net/enic/vnic_dev.c60
-rw-r--r--drivers/net/enic/vnic_dev.h5
-rw-r--r--drivers/net/enic/vnic_devcmd.h19
-rw-r--r--drivers/net/enic/vnic_enet.h11
-rw-r--r--drivers/net/enic/vnic_intr.c7
-rw-r--r--drivers/net/enic/vnic_intr.h6
-rw-r--r--drivers/net/epic100.c4
-rw-r--r--drivers/net/es3210.c1
-rw-r--r--drivers/net/ethoc.c5
-rw-r--r--drivers/net/ewrk3.c39
-rw-r--r--drivers/net/fealnx.c4
-rw-r--r--drivers/net/fec.c9
-rw-r--r--drivers/net/fec_mpc52xx.c13
-rw-r--r--drivers/net/forcedeth.c68
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c2
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c4
-rw-r--r--drivers/net/fs_enet/mii-fec.c2
-rw-r--r--drivers/net/ftgmac100.c1365
-rw-r--r--drivers/net/ftgmac100.h246
-rw-r--r--drivers/net/gianfar.c182
-rw-r--r--drivers/net/gianfar.h57
-rw-r--r--drivers/net/gianfar_ethtool.c958
-rw-r--r--drivers/net/gianfar_ptp.c2
-rw-r--r--drivers/net/greth.c2
-rw-r--r--drivers/net/hamachi.c4
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c1
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c1
-rw-r--r--drivers/net/hamradio/dmascc.c2
-rw-r--r--drivers/net/hp-plus.c1
-rw-r--r--drivers/net/hp.c1
-rw-r--r--drivers/net/hp100.c18
-rw-r--r--drivers/net/ibm_newemac/core.c2
-rw-r--r--drivers/net/ibmveth.c3
-rw-r--r--drivers/net/ifb.c57
-rw-r--r--drivers/net/igb/Makefile2
-rw-r--r--drivers/net/igb/e1000_82575.c22
-rw-r--r--drivers/net/igb/e1000_82575.h4
-rw-r--r--drivers/net/igb/e1000_defines.h17
-rw-r--r--drivers/net/igb/e1000_hw.h2
-rw-r--r--drivers/net/igb/e1000_mac.c5
-rw-r--r--drivers/net/igb/e1000_mac.h2
-rw-r--r--drivers/net/igb/e1000_mbx.c2
-rw-r--r--drivers/net/igb/e1000_mbx.h2
-rw-r--r--drivers/net/igb/e1000_nvm.c2
-rw-r--r--drivers/net/igb/e1000_nvm.h2
-rw-r--r--drivers/net/igb/e1000_phy.c2
-rw-r--r--drivers/net/igb/e1000_phy.h2
-rw-r--r--drivers/net/igb/e1000_regs.h2
-rw-r--r--drivers/net/igb/igb.h6
-rw-r--r--drivers/net/igb/igb_ethtool.c102
-rw-r--r--drivers/net/igb/igb_main.c127
-rw-r--r--drivers/net/igbvf/igbvf.h4
-rw-r--r--drivers/net/igbvf/netdev.c46
-rw-r--r--drivers/net/ioc3-eth.c9
-rw-r--r--drivers/net/ipg.c1
-rw-r--r--drivers/net/irda/ali-ircc.c1
-rw-r--r--drivers/net/irda/donauboe.c1
-rw-r--r--drivers/net/irda/nsc-ircc.c1
-rw-r--r--drivers/net/irda/pxaficp_ir.c2
-rw-r--r--drivers/net/irda/sir_dev.c1
-rw-r--r--drivers/net/irda/smsc-ircc2.c3
-rw-r--r--drivers/net/irda/toim3232-sir.c2
-rw-r--r--drivers/net/irda/via-ircc.c1
-rw-r--r--drivers/net/irda/via-ircc.h2
-rw-r--r--drivers/net/irda/vlsi_ir.c1
-rw-r--r--drivers/net/irda/w83977af_ir.c1
-rw-r--r--drivers/net/iseries_veth.c14
-rw-r--r--drivers/net/ixgbe/ixgbe.h102
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c43
-rw-r--r--drivers/net/ixgbe/ixgbe_82599.c645
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c244
-rw-r--r--drivers/net/ixgbe/ixgbe_common.h5
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.c10
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.h7
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82598.c43
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82598.h3
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82599.c119
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82599.h14
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c129
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c589
-rw-r--r--drivers/net/ixgbe/ixgbe_fcoe.c279
-rw-r--r--drivers/net/ixgbe/ixgbe_fcoe.h12
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c1354
-rw-r--r--drivers/net/ixgbe/ixgbe_sriov.c16
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h99
-rw-r--r--drivers/net/ixgbe/ixgbe_x540.c2
-rw-r--r--drivers/net/ixgbevf/ixgbevf.h8
-rw-r--r--drivers/net/ixgbevf/ixgbevf_main.c88
-rw-r--r--drivers/net/ixp2000/ixpdev.c1
-rw-r--r--drivers/net/jme.c73
-rw-r--r--drivers/net/jme.h7
-rw-r--r--drivers/net/korina.c7
-rw-r--r--drivers/net/ks8842.c1
-rw-r--r--drivers/net/ks8851.c1
-rw-r--r--drivers/net/ks8851_mll.c4
-rw-r--r--drivers/net/ksz884x.c3
-rw-r--r--drivers/net/lib8390.c290
-rw-r--r--drivers/net/ll_temac_main.c7
-rw-r--r--drivers/net/lne390.c1
-rw-r--r--drivers/net/macb.c5
-rw-r--r--drivers/net/mace.c1
-rw-r--r--drivers/net/macmace.c2
-rw-r--r--drivers/net/macvlan.c27
-rw-r--r--drivers/net/macvtap.c134
-rw-r--r--drivers/net/mipsnet.c1
-rw-r--r--drivers/net/mlx4/en_ethtool.c9
-rw-r--r--drivers/net/mlx4/en_main.c3
-rw-r--r--drivers/net/mlx4/en_netdev.c54
-rw-r--r--drivers/net/mlx4/en_port.c29
-rw-r--r--drivers/net/mlx4/en_rx.c26
-rw-r--r--drivers/net/mlx4/en_selftest.c3
-rw-r--r--drivers/net/mlx4/en_tx.c5
-rw-r--r--drivers/net/mlx4/fw.c39
-rw-r--r--drivers/net/mlx4/fw.h8
-rw-r--r--drivers/net/mlx4/main.c62
-rw-r--r--drivers/net/mlx4/mcg.c17
-rw-r--r--drivers/net/mlx4/mlx4.h5
-rw-r--r--drivers/net/mlx4/mlx4_en.h6
-rw-r--r--drivers/net/mlx4/port.c8
-rw-r--r--drivers/net/mlx4/reset.c2
-rw-r--r--drivers/net/mv643xx_eth.c10
-rw-r--r--drivers/net/myri10ge/myri10ge.c268
-rw-r--r--drivers/net/myri10ge/myri10ge_mcp_gen_header.h2
-rw-r--r--drivers/net/myri_sbus.c1187
-rw-r--r--drivers/net/myri_sbus.h311
-rw-r--r--drivers/net/natsemi.c4
-rw-r--r--drivers/net/netx-eth.c1
-rw-r--r--drivers/net/netxen/netxen_nic.h5
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c16
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c6
-rw-r--r--drivers/net/netxen/netxen_nic_init.c74
-rw-r--r--drivers/net/netxen/netxen_nic_main.c13
-rw-r--r--drivers/net/niu.c39
-rw-r--r--drivers/net/ns83820.c34
-rw-r--r--drivers/net/octeon/octeon_mgmt.c1
-rw-r--r--drivers/net/pcnet32.c9
-rw-r--r--drivers/net/phy/icplus.c6
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/plip.c6
-rw-r--r--drivers/net/ppp_async.c1
-rw-r--r--drivers/net/ppp_generic.c2
-rw-r--r--drivers/net/ppp_synctty.c1
-rw-r--r--drivers/net/pptp.c1
-rw-r--r--drivers/net/ps3_gelic_net.c44
-rw-r--r--drivers/net/ps3_gelic_net.h1
-rw-r--r--drivers/net/pxa168_eth.c7
-rw-r--r--drivers/net/qla3xxx.c5
-rw-r--r--drivers/net/qlcnic/qlcnic.h46
-rw-r--r--drivers/net/qlcnic/qlcnic_ctx.c37
-rw-r--r--drivers/net/qlcnic/qlcnic_ethtool.c163
-rw-r--r--drivers/net/qlcnic/qlcnic_hw.c74
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c133
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c78
-rw-r--r--drivers/net/qlge/qlge.h4
-rw-r--r--drivers/net/qlge/qlge_ethtool.c2
-rw-r--r--drivers/net/qlge/qlge_main.c166
-rw-r--r--drivers/net/r6040.c3
-rw-r--r--drivers/net/r8169.c637
-rw-r--r--drivers/net/rionet.c2
-rw-r--r--drivers/net/s2io.c90
-rw-r--r--drivers/net/s2io.h5
-rw-r--r--drivers/net/sb1250-mac.c2
-rw-r--r--drivers/net/sc92031.c1
-rw-r--r--drivers/net/sfc/Kconfig7
-rw-r--r--drivers/net/sfc/efx.c60
-rw-r--r--drivers/net/sfc/enum.h3
-rw-r--r--drivers/net/sfc/ethtool.c27
-rw-r--r--drivers/net/sfc/falcon.c51
-rw-r--r--drivers/net/sfc/filter.c47
-rw-r--r--drivers/net/sfc/net_driver.h12
-rw-r--r--drivers/net/sfc/nic.c1
-rw-r--r--drivers/net/sfc/siena.c49
-rw-r--r--drivers/net/sgiseeq.c1
-rw-r--r--drivers/net/sh_eth.c12
-rw-r--r--drivers/net/sis190.c1
-rw-r--r--drivers/net/sis900.c4
-rw-r--r--drivers/net/skge.c103
-rw-r--r--drivers/net/skge.h1
-rw-r--r--drivers/net/sky2.c165
-rw-r--r--drivers/net/sky2.h16
-rw-r--r--drivers/net/slhc.c2
-rw-r--r--drivers/net/slip.c35
-rw-r--r--drivers/net/slip.h1
-rw-r--r--drivers/net/smc-mca.c1
-rw-r--r--drivers/net/smc-ultra.c1
-rw-r--r--drivers/net/smc911x.c5
-rw-r--r--drivers/net/smc9194.c5
-rw-r--r--drivers/net/smc91x.c5
-rw-r--r--drivers/net/smsc911x.c2
-rw-r--r--drivers/net/smsc9420.c3
-rw-r--r--drivers/net/spider_net.c5
-rw-r--r--drivers/net/starfire.c90
-rw-r--r--drivers/net/stmmac/dwmac1000_core.c1
-rw-r--r--drivers/net/stmmac/dwmac1000_dma.c1
-rw-r--r--drivers/net/stmmac/dwmac100_core.c1
-rw-r--r--drivers/net/stmmac/dwmac100_dma.c1
-rw-r--r--drivers/net/stmmac/stmmac.h11
-rw-r--r--drivers/net/stmmac/stmmac_ethtool.c2
-rw-r--r--drivers/net/stmmac/stmmac_main.c192
-rw-r--r--drivers/net/stmmac/stmmac_mdio.c84
-rw-r--r--drivers/net/sunbmac.c8
-rw-r--r--drivers/net/sungem.c901
-rw-r--r--drivers/net/sungem.h25
-rw-r--r--drivers/net/sunhme.c16
-rw-r--r--drivers/net/sunlance.c8
-rw-r--r--drivers/net/sunqe.c7
-rw-r--r--drivers/net/tehuti.c37
-rw-r--r--drivers/net/tehuti.h1
-rw-r--r--drivers/net/tg3.c788
-rw-r--r--drivers/net/tg3.h30
-rw-r--r--drivers/net/tlan.c2
-rw-r--r--drivers/net/tokenring/3c359.c6
-rw-r--r--drivers/net/tokenring/ibmtr.c3
-rw-r--r--drivers/net/tokenring/madgemc.c2
-rw-r--r--drivers/net/tsi108_eth.c1
-rw-r--r--drivers/net/tulip/de2104x.c1
-rw-r--r--drivers/net/tulip/de4x5.c12
-rw-r--r--drivers/net/tulip/pnic.c1
-rw-r--r--drivers/net/tulip/tulip_core.c1
-rw-r--r--drivers/net/tun.c32
-rw-r--r--drivers/net/typhoon.c2
-rw-r--r--drivers/net/ucc_geth.c7
-rw-r--r--drivers/net/usb/asix.c4
-rw-r--r--drivers/net/usb/cdc-phonet.c1
-rw-r--r--drivers/net/usb/cdc_ncm.c1
-rw-r--r--drivers/net/usb/ipheth.c15
-rw-r--r--drivers/net/usb/kalmia.c12
-rw-r--r--drivers/net/veth.c73
-rw-r--r--drivers/net/via-velocity.c50
-rw-r--r--drivers/net/via-velocity.h2
-rw-r--r--drivers/net/virtio_net.c79
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c120
-rw-r--r--drivers/net/vmxnet3/vmxnet3_ethtool.c53
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h8
-rw-r--r--drivers/net/vxge/vxge-config.c57
-rw-r--r--drivers/net/vxge/vxge-config.h2
-rw-r--r--drivers/net/vxge/vxge-main.c159
-rw-r--r--drivers/net/vxge/vxge-main.h53
-rw-r--r--drivers/net/vxge/vxge-traffic.c6
-rw-r--r--drivers/net/wan/c101.c30
-rw-r--r--drivers/net/wan/cosa.c226
-rw-r--r--drivers/net/wan/cycx_drv.c81
-rw-r--r--drivers/net/wan/cycx_main.c32
-rw-r--r--drivers/net/wan/cycx_x25.c177
-rw-r--r--drivers/net/wan/dlci.c22
-rw-r--r--drivers/net/wan/dscc4.c81
-rw-r--r--drivers/net/wan/farsync.c8
-rw-r--r--drivers/net/wan/hd64570.c8
-rw-r--r--drivers/net/wan/hd64572.c8
-rw-r--r--drivers/net/wan/hdlc.c16
-rw-r--r--drivers/net/wan/hdlc_cisco.c21
-rw-r--r--drivers/net/wan/hdlc_fr.c96
-rw-r--r--drivers/net/wan/hdlc_ppp.c9
-rw-r--r--drivers/net/wan/hdlc_x25.c12
-rw-r--r--drivers/net/wan/hostess_sv11.c11
-rw-r--r--drivers/net/wan/ixp4xx_hss.c28
-rw-r--r--drivers/net/wan/lapbether.c18
-rw-r--r--drivers/net/wan/lmc/lmc_var.h2
-rw-r--r--drivers/net/wan/n2.c42
-rw-r--r--drivers/net/wan/pc300_drv.c4
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/pc300too.c36
-rw-r--r--drivers/net/wan/pci200syn.c29
-rw-r--r--drivers/net/wan/sbni.c72
-rw-r--r--drivers/net/wan/sdla.c52
-rw-r--r--drivers/net/wan/sealevel.c11
-rw-r--r--drivers/net/wan/wanxl.c93
-rw-r--r--drivers/net/wan/x25_asy.c47
-rw-r--r--drivers/net/wan/z85230.c34
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h2
-rw-r--r--drivers/net/wireless/adm8211.c1
-rw-r--r--drivers/net/wireless/ath/ath.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c50
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.c89
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h438
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c55
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c1201
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h206
-rw-r--r--drivers/net/wireless/ath/ath5k/caps.c49
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c423
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h21
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c20
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c50
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h12
-rw-r--r--drivers/net/wireless/ath/ath5k/initvals.c16
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c74
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c263
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c52
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c40
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c133
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c9
-rw-r--r--drivers/net/wireless/ath/ath5k/reg.h89
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c93
-rw-r--r--drivers/net/wireless/ath/ath5k/rfbuffer.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/rfgain.h8
-rw-r--r--drivers/net/wireless/ath/ath5k/rfkill.c65
-rw-r--r--drivers/net/wireless/ath/ath5k/sysfs.c42
-rw-r--r--drivers/net/wireless/ath/ath5k/trace.h21
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c39
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c51
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c182
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c131
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c41
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h1147
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h1080
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h18
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c30
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c81
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_debug.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c218
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c39
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c179
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c56
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c200
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h44
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c350
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h13
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.h4
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h19
-rw-r--r--drivers/net/wireless/ath/carl9170/fwdesc.h21
-rw-r--r--drivers/net/wireless/ath/carl9170/hw.h56
-rw-r--r--drivers/net/wireless/ath/carl9170/led.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c129
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c21
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c12
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c290
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h6
-rw-r--r--drivers/net/wireless/ath/carl9170/wlan.h25
-rw-r--r--drivers/net/wireless/ath/key.c7
-rw-r--r--drivers/net/wireless/atmel.c1
-rw-r--r--drivers/net/wireless/b43/Kconfig32
-rw-r--r--drivers/net/wireless/b43/Makefile5
-rw-r--r--drivers/net/wireless/b43/b43.h63
-rw-r--r--drivers/net/wireless/b43/bus.c253
-rw-r--r--drivers/net/wireless/b43/bus.h70
-rw-r--r--drivers/net/wireless/b43/debugfs.c2
-rw-r--r--drivers/net/wireless/b43/dma.c77
-rw-r--r--drivers/net/wireless/b43/dma.h4
-rw-r--r--drivers/net/wireless/b43/leds.c17
-rw-r--r--drivers/net/wireless/b43/lo.c8
-rw-r--r--drivers/net/wireless/b43/main.c680
-rw-r--r--drivers/net/wireless/b43/main.h4
-rw-r--r--drivers/net/wireless/b43/pcmcia.c2
-rw-r--r--drivers/net/wireless/b43/phy_a.c23
-rw-r--r--drivers/net/wireless/b43/phy_common.c22
-rw-r--r--drivers/net/wireless/b43/phy_common.h6
-rw-r--r--drivers/net/wireless/b43/phy_g.c94
-rw-r--r--drivers/net/wireless/b43/phy_ht.c413
-rw-r--r--drivers/net/wireless/b43/phy_ht.h46
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c52
-rw-r--r--drivers/net/wireless/b43/phy_lcn.h14
-rw-r--r--drivers/net/wireless/b43/phy_lp.c137
-rw-r--r--drivers/net/wireless/b43/phy_n.c122
-rw-r--r--drivers/net/wireless/b43/pio.c12
-rw-r--r--drivers/net/wireless/b43/radio_2055.c2
-rw-r--r--drivers/net/wireless/b43/radio_2055.h5
-rw-r--r--drivers/net/wireless/b43/radio_2056.h5
-rw-r--r--drivers/net/wireless/b43/radio_2059.c174
-rw-r--r--drivers/net/wireless/b43/radio_2059.h54
-rw-r--r--drivers/net/wireless/b43/rfkill.c11
-rw-r--r--drivers/net/wireless/b43/sdio.c12
-rw-r--r--drivers/net/wireless/b43/sysfs.c6
-rw-r--r--drivers/net/wireless/b43/tables.c2
-rw-r--r--drivers/net/wireless/b43/tables_lpphy.c17
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c2
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h8
-rw-r--r--drivers/net/wireless/b43/tables_phy_ht.c750
-rw-r--r--drivers/net/wireless/b43/tables_phy_ht.h22
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.c34
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.h6
-rw-r--r--drivers/net/wireless/b43/wa.c26
-rw-r--r--drivers/net/wireless/b43/xmit.c7
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h4
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/dma.c19
-rw-r--r--drivers/net/wireless/b43legacy/dma.h2
-rw-r--r--drivers/net/wireless/b43legacy/ilt.c2
-rw-r--r--drivers/net/wireless/b43legacy/leds.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c12
-rw-r--r--drivers/net/wireless/b43legacy/main.h2
-rw-r--r--drivers/net/wireless/b43legacy/phy.c2
-rw-r--r--drivers/net/wireless/b43legacy/phy.h2
-rw-r--r--drivers/net/wireless/b43legacy/pio.c2
-rw-r--r--drivers/net/wireless/b43legacy/radio.c2
-rw-r--r--drivers/net/wireless/b43legacy/radio.h2
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c2
-rw-r--r--drivers/net/wireless/b43legacy/sysfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h1
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.h1
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_rx.c4
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_wx.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945.c4
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-lib.c79
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-rs.c3
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-rx.c78
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-tx.c3
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965.c10
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-commands.h11
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.c91
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.h17
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-debugfs.c192
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-dev.h61
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-devtrace.c3
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-devtrace.h60
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-eeprom.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-helpers.h9
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-rx.c21
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-scan.c92
-rw-r--r--drivers/net/wireless/iwlegacy/iwl3945-base.c301
-rw-r--r--drivers/net/wireless/iwlegacy/iwl4965-base.c465
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-2000.c117
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c78
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c115
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c74
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c328
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hw.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ict.c306
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c774
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c38
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c235
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c394
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.c38
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c614
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c224
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c2038
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h87
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-bus.h139
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h222
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c166
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h194
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c94
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h181
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c42
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c291
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-pci.c569
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h93
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c296
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c194
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h251
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h82
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c979
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c (renamed from drivers/net/wireless/iwlwifi/iwl-tx.c)727
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c1172
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h225
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c2
-rw-r--r--drivers/net/wireless/libertas/cfg.c1
-rw-r--r--drivers/net/wireless/libertas/cmd.c47
-rw-r--r--drivers/net/wireless/libertas/cmd.h2
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c7
-rw-r--r--drivers/net/wireless/libertas/debugfs.c1
-rw-r--r--drivers/net/wireless/libertas/dev.h2
-rw-r--r--drivers/net/wireless/libertas/ethtool.c1
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c34
-rw-r--r--drivers/net/wireless/libertas/if_spi.c8
-rw-r--r--drivers/net/wireless/libertas/main.c15
-rw-r--r--drivers/net/wireless/libertas/mesh.c973
-rw-r--r--drivers/net/wireless/libertas/mesh.h31
-rw-r--r--drivers/net/wireless/libertas/rx.c1
-rw-r--r--drivers/net/wireless/libertas/tx.c3
-rw-r--r--drivers/net/wireless/libertas_tf/cmd.c1
-rw-r--r--drivers/net/wireless/libertas_tf/main.c3
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c464
-rw-r--r--drivers/net/wireless/mac80211_hwsim.h133
-rw-r--r--drivers/net/wireless/mwifiex/11n.c33
-rw-r--r--drivers/net/wireless/mwifiex/11n.h14
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c54
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c5
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.h5
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c56
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c28
-rw-r--r--drivers/net/wireless/mwifiex/debugfs.c35
-rw-r--r--drivers/net/wireless/mwifiex/decl.h4
-rw-r--r--drivers/net/wireless/mwifiex/fw.h11
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h1
-rw-r--r--drivers/net/wireless/mwifiex/join.c23
-rw-r--r--drivers/net/wireless/mwifiex/main.c36
-rw-r--r--drivers/net/wireless/mwifiex/main.h30
-rw-r--r--drivers/net/wireless/mwifiex/scan.c6
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c94
-rw-r--r--drivers/net/wireless/mwifiex/sdio.h6
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c113
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c50
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c14
-rw-r--r--drivers/net/wireless/mwifiex/sta_rx.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_tx.c13
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c2
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c32
-rw-r--r--drivers/net/wireless/mwl8k.c7
-rw-r--r--drivers/net/wireless/orinoco/airport.c9
-rw-r--r--drivers/net/wireless/orinoco/cfg.c6
-rw-r--r--drivers/net/wireless/orinoco/fw.c7
-rw-r--r--drivers/net/wireless/orinoco/fw.h2
-rw-r--r--drivers/net/wireless/orinoco/hermes.c40
-rw-r--r--drivers/net/wireless/orinoco/hermes.h37
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.c8
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.h12
-rw-r--r--drivers/net/wireless/orinoco/hw.c48
-rw-r--r--drivers/net/wireless/orinoco/hw.h2
-rw-r--r--drivers/net/wireless/orinoco/main.c48
-rw-r--r--drivers/net/wireless/orinoco/mic.c8
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h16
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c6
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c3
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c6
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c23
-rw-r--r--drivers/net/wireless/orinoco/spectrum_cs.c10
-rw-r--r--drivers/net/wireless/orinoco/wext.c14
-rw-r--r--drivers/net/wireless/p54/p54pci.h1
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c1
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h1
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c1
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig9
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h16
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c378
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c90
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c13
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c113
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c1
-rw-r--r--drivers/net/wireless/rtlwifi/Kconfig15
-rw-r--r--drivers/net/wireless/rtlwifi/Makefile1
-rw-r--r--drivers/net/wireless/rtlwifi/base.c26
-rw-r--r--drivers/net/wireless/rtlwifi/cam.c8
-rw-r--r--drivers/net/wireless/rtlwifi/core.c18
-rw-r--r--drivers/net/wireless/rtlwifi/core.h2
-rw-r--r--drivers/net/wireless/rtlwifi/debug.h5
-rw-r--r--drivers/net/wireless/rtlwifi/efuse.c14
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c249
-rw-r--r--drivers/net/wireless/rtlwifi/pci.h12
-rw-r--r--drivers/net/wireless/rtlwifi/ps.c97
-rw-r--r--drivers/net/wireless/rtlwifi/ps.h3
-rw-r--r--drivers/net/wireless/rtlwifi/rc.c2
-rw-r--r--drivers/net/wireless/rtlwifi/regd.c18
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c7
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c12
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.c23
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/led.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/phy.c14
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/reg.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/rf.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.c12
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.c77
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/led.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.c22
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/phy.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/rf.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/trx.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/Makefile14
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/def.h269
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/dm.c1355
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/dm.h212
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/fw.c790
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/fw.h155
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/hw.c2329
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/hw.h66
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/led.c159
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/led.h38
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/phy.c3831
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/phy.h178
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/reg.h1313
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/rf.c628
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/rf.h44
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/sw.c423
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/sw.h37
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/table.c1690
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/table.h57
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/trx.c959
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/trx.h756
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/dm.c7
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/fw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.c38
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/led.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/phy.c27
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/reg.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/rf.c6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/sw.c6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c12
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c12
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h10
-rw-r--r--drivers/net/wireless/wl1251/sdio.c1
-rw-r--r--drivers/net/wireless/wl1251/spi.c1
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig2
-rw-r--r--drivers/net/wireless/wl12xx/acx.c61
-rw-r--r--drivers/net/wireless/wl12xx/acx.h20
-rw-r--r--drivers/net/wireless/wl12xx/boot.c40
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c109
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h62
-rw-r--r--drivers/net/wireless/wl12xx/conf.h65
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c153
-rw-r--r--drivers/net/wireless/wl12xx/event.c101
-rw-r--r--drivers/net/wireless/wl12xx/event.h29
-rw-r--r--drivers/net/wireless/wl12xx/ini.h3
-rw-r--r--drivers/net/wireless/wl12xx/init.c27
-rw-r--r--drivers/net/wireless/wl12xx/io.c7
-rw-r--r--drivers/net/wireless/wl12xx/io.h15
-rw-r--r--drivers/net/wireless/wl12xx/main.c793
-rw-r--r--drivers/net/wireless/wl12xx/ps.c21
-rw-r--r--drivers/net/wireless/wl12xx/rx.c39
-rw-r--r--drivers/net/wireless/wl12xx/rx.h12
-rw-r--r--drivers/net/wireless/wl12xx/scan.c90
-rw-r--r--drivers/net/wireless/wl12xx/scan.h18
-rw-r--r--drivers/net/wireless/wl12xx/sdio.c83
-rw-r--r--drivers/net/wireless/wl12xx/spi.c16
-rw-r--r--drivers/net/wireless/wl12xx/testmode.c2
-rw-r--r--drivers/net/wireless/wl12xx/tx.c176
-rw-r--r--drivers/net/wireless/wl12xx/tx.h28
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h63
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_def.h6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c118
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c129
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h5
-rw-r--r--drivers/net/xen-netback/netback.c1
-rw-r--r--drivers/net/xen-netfront.c69
-rw-r--r--drivers/net/xilinx_emaclite.c14
-rw-r--r--drivers/net/yellowfin.c6
-rw-r--r--drivers/net/znet.c2
-rw-r--r--drivers/net/zorro8390.c673
-rw-r--r--drivers/nfc/Kconfig24
-rw-r--r--drivers/nfc/Makefile3
-rw-r--r--drivers/nfc/pn533.c1632
-rw-r--r--drivers/of/Kconfig8
-rw-r--r--drivers/of/Makefile1
-rw-r--r--drivers/of/address.c18
-rw-r--r--drivers/of/base.c65
-rw-r--r--drivers/of/gpio.c11
-rw-r--r--drivers/of/of_pci.c113
-rw-r--r--drivers/of/of_pci_irq.c92
-rw-r--r--drivers/of/platform.c200
-rw-r--r--drivers/oprofile/oprofile_perf.c4
-rw-r--r--drivers/oprofile/oprofile_stats.h2
-rw-r--r--drivers/parport/parport_ax88796.c2
-rw-r--r--drivers/parport/parport_pc.c54
-rw-r--r--drivers/parport/parport_serial.c229
-rw-r--r--drivers/pci/Makefile7
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c2
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c2
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c21
-rw-r--r--drivers/pci/of.c61
-rw-r--r--drivers/pci/pci-driver.c18
-rw-r--r--drivers/pci/pci-label.c2
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/aspm.c2
-rw-r--r--drivers/pci/probe.c7
-rw-r--r--drivers/pci/quirks.c23
-rw-r--r--drivers/pci/xen-pcifront.c2
-rw-r--r--drivers/pcmcia/at91_cf.c7
-rw-r--r--drivers/pcmcia/electra_cf.c4
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c3
-rw-r--r--drivers/pcmcia/pxa2xx_trizeps4.c4
-rw-r--r--drivers/pcmcia/rsrc_iodyn.c6
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c6
-rw-r--r--drivers/platform/x86/asus-wmi.c2
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c62
-rw-r--r--drivers/pnp/pnpbios/rsparser.c12
-rw-r--r--drivers/power/ds2782_battery.c4
-rw-r--r--drivers/regulator/Kconfig1
-rw-r--r--drivers/regulator/tps65023-regulator.c97
-rw-r--r--drivers/rtc/Kconfig20
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/class.c65
-rw-r--r--drivers/rtc/interface.c55
-rw-r--r--drivers/rtc/rtc-at32ap700x.c2
-rw-r--r--drivers/rtc/rtc-cmos.c6
-rw-r--r--drivers/rtc/rtc-ds1286.c2
-rw-r--r--drivers/rtc/rtc-ds1511.c2
-rw-r--r--drivers/rtc/rtc-ds1742.c2
-rw-r--r--drivers/rtc/rtc-m48t35.c2
-rw-r--r--drivers/rtc/rtc-m48t59.c2
-rw-r--r--drivers/rtc/rtc-mpc5121.c81
-rw-r--r--drivers/rtc/rtc-mrst.c5
-rw-r--r--drivers/rtc/rtc-pm8xxx.c550
-rw-r--r--drivers/rtc/rtc-puv3.c5
-rw-r--r--drivers/rtc/rtc-s3c.c32
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c153
-rw-r--r--drivers/rtc/rtc-tegra.c2
-rw-r--r--drivers/rtc/rtc-twl.c2
-rw-r--r--drivers/rtc/rtc-vt8500.c6
-rw-r--r--drivers/s390/block/dasd.c576
-rw-r--r--drivers/s390/block/dasd_eer.c2
-rw-r--r--drivers/s390/block/dasd_int.h57
-rw-r--r--drivers/s390/block/dasd_ioctl.c38
-rw-r--r--drivers/s390/block/dasd_proc.c106
-rw-r--r--drivers/s390/char/Kconfig3
-rw-r--r--drivers/s390/char/sclp_quiesce.c2
-rw-r--r--drivers/s390/char/vmlogrdr.c2
-rw-r--r--drivers/s390/char/vmwatchdog.c4
-rw-r--r--drivers/s390/cio/css.c8
-rw-r--r--drivers/s390/cio/device.h2
-rw-r--r--drivers/s390/cio/qdio_main.c2
-rw-r--r--drivers/s390/cio/qdio_thinint.c17
-rw-r--r--drivers/s390/crypto/ap_bus.c98
-rw-r--r--drivers/s390/crypto/ap_bus.h22
-rw-r--r--drivers/s390/crypto/zcrypt_api.c2
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c2
-rw-r--r--drivers/s390/crypto/zcrypt_mono.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c2
-rw-r--r--drivers/s390/net/ctcm_mpc.h1
-rw-r--r--drivers/s390/net/fsm.h2
-rw-r--r--drivers/s390/net/qeth_core.h2
-rw-r--r--drivers/s390/net/qeth_core_main.c1
-rw-r--r--drivers/s390/net/qeth_l3_main.c125
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c2
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/scsi/aha152x.c17
-rw-r--r--drivers/scsi/atari_NCR5380.c6
-rw-r--r--drivers/scsi/atari_scsi.c1
-rw-r--r--drivers/scsi/be2iscsi/be_main.c199
-rw-r--r--drivers/scsi/bfa/Makefile2
-rw-r--r--drivers/scsi/bfa/bfa.h144
-rw-r--r--drivers/scsi/bfa/bfa_core.c878
-rw-r--r--drivers/scsi/bfa/bfa_defs.h583
-rw-r--r--drivers/scsi/bfa/bfa_defs_fcs.h27
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h170
-rw-r--r--drivers/scsi/bfa/bfa_fc.h11
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c49
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h16
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c478
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h89
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c153
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h31
-rw-r--r--drivers/scsi/bfa/bfa_fcs_fcpim.c10
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c329
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c121
-rw-r--r--drivers/scsi/bfa/bfa_hw_cb.c94
-rw-r--r--drivers/scsi/bfa/bfa_hw_ct.c89
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c2992
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h609
-rw-r--r--drivers/scsi/bfa/bfa_ioc_cb.c69
-rw-r--r--drivers/scsi/bfa/bfa_ioc_ct.c516
-rw-r--r--drivers/scsi/bfa/bfa_modules.h27
-rw-r--r--drivers/scsi/bfa/bfa_port.c428
-rw-r--r--drivers/scsi/bfa/bfa_port.h62
-rw-r--r--drivers/scsi/bfa/bfa_svc.c1136
-rw-r--r--drivers/scsi/bfa/bfa_svc.h151
-rw-r--r--drivers/scsi/bfa/bfad.c295
-rw-r--r--drivers/scsi/bfa/bfad_attr.c53
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c2163
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h509
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c14
-rw-r--r--drivers/scsi/bfa/bfad_drv.h26
-rw-r--r--drivers/scsi/bfa/bfad_im.c32
-rw-r--r--drivers/scsi/bfa/bfad_im.h3
-rw-r--r--drivers/scsi/bfa/bfi.h637
-rw-r--r--drivers/scsi/bfa/bfi_cbreg.h305
-rw-r--r--drivers/scsi/bfa/bfi_ctreg.h636
-rw-r--r--drivers/scsi/bfa/bfi_ms.h159
-rw-r--r--drivers/scsi/bfa/bfi_reg.h450
-rw-r--r--drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h1162
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h18
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_constants.h139
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_els.c7
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c43
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c466
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c25
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c24
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h4
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_hsi.h14
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h35
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c207
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c174
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c38
-rw-r--r--drivers/scsi/bnx2i/bnx2i_sysfs.c2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c6
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c2
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c4
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c2
-rw-r--r--drivers/scsi/dpt/dpti_i2o.h2
-rw-r--r--drivers/scsi/fcoe/fcoe.c174
-rw-r--r--drivers/scsi/fnic/fnic.h2
-rw-r--r--drivers/scsi/fnic/fnic_main.c21
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c2
-rw-r--r--drivers/scsi/hpsa.c2
-rw-r--r--drivers/scsi/iscsi_boot_sysfs.c31
-rw-r--r--drivers/scsi/iscsi_tcp.c61
-rw-r--r--drivers/scsi/libfc/fc_exch.c26
-rw-r--r--drivers/scsi/libfc/fc_lport.c2
-rw-r--r--drivers/scsi/libfc/fc_rport.c28
-rw-r--r--drivers/scsi/libiscsi.c14
-rw-r--r--drivers/scsi/libiscsi_tcp.c14
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h8
-rw-r--r--drivers/scsi/mac_scsi.c14
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h12
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h74
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h6
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h4
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c84
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h77
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c12
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_debug.h2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c279
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c24
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c4
-rw-r--r--drivers/scsi/scsi_devinfo.c2
-rw-r--r--drivers/scsi/scsi_lib.c2
-rw-r--r--drivers/scsi/scsi_pm.c8
-rw-r--r--drivers/scsi/ses.c6
-rw-r--r--drivers/scsi/sr.c46
-rw-r--r--drivers/scsi/sr.h7
-rw-r--r--drivers/scsi/sun3_NCR5380.c98
-rw-r--r--drivers/scsi/sun3_scsi.c11
-rw-r--r--drivers/scsi/sun3_scsi_vme.c11
-rw-r--r--drivers/sh/clk/core.c7
-rw-r--r--drivers/spi/Kconfig48
-rw-r--r--drivers/spi/Makefile111
-rw-r--r--drivers/spi/atmel_spi.h167
-rw-r--r--drivers/spi/spi-altera.c (renamed from drivers/spi/spi_altera.c)0
-rw-r--r--drivers/spi/spi-ath79.c (renamed from drivers/spi/ath79_spi.c)2
-rw-r--r--drivers/spi/spi-atmel.c (renamed from drivers/spi/atmel_spi.c)155
-rw-r--r--drivers/spi/spi-au1550.c (renamed from drivers/spi/au1550_spi.c)2
-rw-r--r--drivers/spi/spi-bfin-sport.c (renamed from drivers/spi/spi_bfin_sport.c)0
-rw-r--r--drivers/spi/spi-bfin5xx.c (renamed from drivers/spi/spi_bfin5xx.c)218
-rw-r--r--drivers/spi/spi-bitbang-txrx.h (renamed from drivers/spi/spi_bitbang_txrx.h)0
-rw-r--r--drivers/spi/spi-bitbang.c (renamed from drivers/spi/spi_bitbang.c)8
-rw-r--r--drivers/spi/spi-butterfly.c (renamed from drivers/spi/spi_butterfly.c)4
-rw-r--r--drivers/spi/spi-coldfire-qspi.c (renamed from drivers/spi/coldfire_qspi.c)0
-rw-r--r--drivers/spi/spi-davinci.c (renamed from drivers/spi/davinci_spi.c)0
-rw-r--r--drivers/spi/spi-dw-mid.c (renamed from drivers/spi/dw_spi_mid.c)4
-rw-r--r--drivers/spi/spi-dw-mmio.c (renamed from drivers/spi/dw_spi_mmio.c)4
-rw-r--r--drivers/spi/spi-dw-pci.c (renamed from drivers/spi/dw_spi_pci.c)4
-rw-r--r--drivers/spi/spi-dw.c (renamed from drivers/spi/dw_spi.c)8
-rw-r--r--drivers/spi/spi-dw.h (renamed from drivers/spi/dw_spi.h)1
-rw-r--r--drivers/spi/spi-ep93xx.c (renamed from drivers/spi/ep93xx_spi.c)303
-rw-r--r--drivers/spi/spi-fsl-espi.c (renamed from drivers/spi/spi_fsl_espi.c)2
-rw-r--r--drivers/spi/spi-fsl-lib.c (renamed from drivers/spi/spi_fsl_lib.c)2
-rw-r--r--drivers/spi/spi-fsl-lib.h (renamed from drivers/spi/spi_fsl_lib.h)0
-rw-r--r--drivers/spi/spi-fsl-spi.c (renamed from drivers/spi/spi_fsl_spi.c)30
-rw-r--r--drivers/spi/spi-gpio.c (renamed from drivers/spi/spi_gpio.c)6
-rw-r--r--drivers/spi/spi-imx.c (renamed from drivers/spi/spi_imx.c)466
-rw-r--r--drivers/spi/spi-lm70llp.c (renamed from drivers/spi/spi_lm70llp.c)4
-rw-r--r--drivers/spi/spi-mpc512x-psc.c (renamed from drivers/spi/mpc512x_psc_spi.c)0
-rw-r--r--drivers/spi/spi-mpc52xx-psc.c (renamed from drivers/spi/mpc52xx_psc_spi.c)0
-rw-r--r--drivers/spi/spi-mpc52xx.c (renamed from drivers/spi/mpc52xx_spi.c)0
-rw-r--r--drivers/spi/spi-nuc900.c (renamed from drivers/spi/spi_nuc900.c)5
-rw-r--r--drivers/spi/spi-oc-tiny.c (renamed from drivers/spi/spi_oc_tiny.c)0
-rw-r--r--drivers/spi/spi-omap-100k.c (renamed from drivers/spi/omap_spi_100k.c)0
-rw-r--r--drivers/spi/spi-omap-uwire.c (renamed from drivers/spi/omap_uwire.c)2
-rw-r--r--drivers/spi/spi-omap2-mcspi.c (renamed from drivers/spi/omap2_mcspi.c)10
-rw-r--r--drivers/spi/spi-orion.c (renamed from drivers/spi/orion_spi.c)8
-rw-r--r--drivers/spi/spi-pl022.c (renamed from drivers/spi/amba-pl022.c)111
-rw-r--r--drivers/spi/spi-ppc4xx.c (renamed from drivers/spi/spi_ppc4xx.c)2
-rw-r--r--drivers/spi/spi-pxa2xx-pci.c (renamed from drivers/spi/pxa2xx_spi_pci.c)0
-rw-r--r--drivers/spi/spi-pxa2xx.c (renamed from drivers/spi/pxa2xx_spi.c)0
-rw-r--r--drivers/spi/spi-s3c24xx-fiq.S (renamed from drivers/spi/spi_s3c24xx_fiq.S)2
-rw-r--r--drivers/spi/spi-s3c24xx-fiq.h (renamed from drivers/spi/spi_s3c24xx_fiq.h)0
-rw-r--r--drivers/spi/spi-s3c24xx.c (renamed from drivers/spi/spi_s3c24xx.c)5
-rw-r--r--drivers/spi/spi-s3c64xx.c (renamed from drivers/spi/spi_s3c64xx.c)3
-rw-r--r--drivers/spi/spi-sh-msiof.c (renamed from drivers/spi/spi_sh_msiof.c)0
-rw-r--r--drivers/spi/spi-sh-sci.c (renamed from drivers/spi/spi_sh_sci.c)2
-rw-r--r--drivers/spi/spi-sh.c (renamed from drivers/spi/spi_sh.c)0
-rw-r--r--drivers/spi/spi-stmp.c (renamed from drivers/spi/spi_stmp.c)0
-rw-r--r--drivers/spi/spi-tegra.c (renamed from drivers/spi/spi_tegra.c)20
-rw-r--r--drivers/spi/spi-ti-ssp.c (renamed from drivers/spi/ti-ssp-spi.c)0
-rw-r--r--drivers/spi/spi-tle62x0.c (renamed from drivers/spi/tle62x0.c)2
-rw-r--r--drivers/spi/spi-topcliff-pch.c (renamed from drivers/spi/spi_topcliff_pch.c)1158
-rw-r--r--drivers/spi/spi-txx9.c (renamed from drivers/spi/spi_txx9.c)2
-rw-r--r--drivers/spi/spi-xilinx.c (renamed from drivers/spi/xilinx_spi.c)0
-rw-r--r--drivers/spi/spi.c2
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c201
-rw-r--r--drivers/spi/spidev.c2
-rw-r--r--drivers/ssb/b43_pci_bridge.c2
-rw-r--r--drivers/ssb/driver_chipcommon.c2
-rw-r--r--drivers/ssb/driver_chipcommon_pmu.c6
-rw-r--r--drivers/ssb/driver_extif.c2
-rw-r--r--drivers/ssb/driver_gige.c15
-rw-r--r--drivers/ssb/driver_mipscore.c2
-rw-r--r--drivers/ssb/driver_pcicore.c12
-rw-r--r--drivers/ssb/embedded.c2
-rw-r--r--drivers/ssb/main.c40
-rw-r--r--drivers/ssb/pci.c11
-rw-r--r--drivers/ssb/pcihost_wrapper.c8
-rw-r--r--drivers/ssb/pcmcia.c2
-rw-r--r--drivers/ssb/scan.c5
-rw-r--r--drivers/ssb/sdio.c2
-rw-r--r--drivers/ssb/sprom.c2
-rw-r--r--drivers/staging/Kconfig10
-rw-r--r--drivers/staging/Makefile5
-rw-r--r--drivers/staging/altera-stapl/Kconfig2
-rw-r--r--drivers/staging/altera-stapl/Makefile2
-rw-r--r--drivers/staging/altera-stapl/altera.c33
-rw-r--r--drivers/staging/ath6kl/TODO2
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_drv.c56
-rw-r--r--drivers/staging/ath6kl/os/linux/cfg80211.c211
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ar6000_drv.h20
-rw-r--r--drivers/staging/ath6kl/os/linux/include/cfg80211.h11
-rw-r--r--drivers/staging/ath6kl/os/linux/include/config_linux.h2
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h2
-rw-r--r--drivers/staging/ath6kl/os/linux/include/osapi_linux.h1
-rw-r--r--drivers/staging/ath6kl/wmi/wmi.c6
-rw-r--r--drivers/staging/bcm/Debug.h2
-rw-r--r--drivers/staging/bcm/InterfaceRx.c4
-rw-r--r--drivers/staging/bcm/Macros.h4
-rw-r--r--drivers/staging/bcm/Misc.c10
-rw-r--r--drivers/staging/bcm/PHSModule.c24
-rw-r--r--drivers/staging/bcm/PHSModule.h2
-rw-r--r--drivers/staging/bcm/headers.h8
-rw-r--r--drivers/staging/bcm/sort.c77
-rw-r--r--drivers/staging/brcm80211/Makefile4
-rw-r--r--drivers/staging/brcm80211/README65
-rw-r--r--drivers/staging/brcm80211/TODO12
-rw-r--r--drivers/staging/brcm80211/brcmfmac/Makefile27
-rw-r--r--drivers/staging/brcm80211/brcmfmac/README2
-rw-r--r--drivers/staging/brcm80211/brcmfmac/aiutils.c1
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmcdc.h98
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmchip.h9
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdbus.h113
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh.c631
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c386
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c925
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h134
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c235
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd.h970
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_bus.h76
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_cdc.c348
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_common.c1606
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c158
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_dbg.h105
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_linux.c2238
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c25
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_proto.h63
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_sdio.c4746
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhdioctl.h100
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dngl_stats.h32
-rw-r--r--drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h75
-rw-r--r--drivers/staging/brcm80211/brcmfmac/hndrte_cons.h62
-rw-r--r--drivers/staging/brcm80211/brcmfmac/msgtrace.h61
-rw-r--r--drivers/staging/brcm80211/brcmfmac/sdio_host.h347
-rw-r--r--drivers/staging/brcm80211/brcmfmac/sdioh.h63
-rw-r--r--drivers/staging/brcm80211/brcmfmac/sdiovar.h38
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c2480
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h208
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_iw.c3693
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_iw.h142
-rw-r--r--drivers/staging/brcm80211/brcmsmac/Makefile45
-rw-r--r--drivers/staging/brcm80211/brcmsmac/aiutils.c717
-rw-r--r--drivers/staging/brcm80211/brcmsmac/aiutils.h230
-rw-r--r--drivers/staging/brcm80211/brcmsmac/alloc.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_alloc.c)153
-rw-r--r--drivers/staging/brcm80211/brcmsmac/alloc.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_alloc.h)5
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ampdu.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c)410
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ampdu.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_types.h)31
-rw-r--r--drivers/staging/brcm80211/brcmsmac/antsel.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_antsel.c)113
-rw-r--r--drivers/staging/brcm80211/brcmsmac/antsel.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_antsel.h)16
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bcmotp.c936
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bcmsrom.c714
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bmac.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_bmac.c)1112
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bmac.h174
-rw-r--r--drivers/staging/brcm80211/brcmsmac/channel.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_channel.c)594
-rw-r--r--drivers/staging/brcm80211/brcmsmac/channel.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_channel.h)82
-rw-r--r--drivers/staging/brcm80211/brcmsmac/d11.h160
-rw-r--r--drivers/staging/brcm80211/brcmsmac/dma.c (renamed from drivers/staging/brcm80211/brcmsmac/hnddma.c)563
-rw-r--r--drivers/staging/brcm80211/brcmsmac/dma.h (renamed from drivers/staging/brcm80211/include/hnddma.h)146
-rw-r--r--drivers/staging/brcm80211/brcmsmac/mac80211_if.c (renamed from drivers/staging/brcm80211/brcmsmac/wl_mac80211.c)823
-rw-r--r--drivers/staging/brcm80211/brcmsmac/mac80211_if.h (renamed from drivers/staging/brcm80211/brcmsmac/wl_mac80211.h)75
-rw-r--r--drivers/staging/brcm80211/brcmsmac/main.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_main.c)4123
-rw-r--r--drivers/staging/brcm80211/brcmsmac/main.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_main.h)794
-rw-r--r--drivers/staging/brcm80211/brcmsmac/nicpci.c672
-rw-r--r--drivers/staging/brcm80211/brcmsmac/nicpci.h85
-rw-r--r--drivers/staging/brcm80211/brcmsmac/nvram.c215
-rw-r--r--drivers/staging/brcm80211/brcmsmac/otp.c544
-rw-r--r--drivers/staging/brcm80211/brcmsmac/otp.h (renamed from drivers/staging/brcm80211/include/bcmotp.h)13
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c)718
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h294
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_int.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h)467
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c)584
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h)12
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_n.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c)1031
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.c)4
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.h)8
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_radio.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h)6
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_version.h36
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phyreg_n.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h)14
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c)53
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h)35
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c)53
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h)21
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h256
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy_shim.c218
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy_shim.h164
-rw-r--r--drivers/staging/brcm80211/brcmsmac/pmu.c474
-rw-r--r--drivers/staging/brcm80211/brcmsmac/pmu.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_pmu.h)44
-rw-r--r--drivers/staging/brcm80211/brcmsmac/pub.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_pub.h)427
-rw-r--r--drivers/staging/brcm80211/brcmsmac/rate.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_rate.c)207
-rw-r--r--drivers/staging/brcm80211/brcmsmac/rate.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_rate.h)116
-rw-r--r--drivers/staging/brcm80211/brcmsmac/scb.h (renamed from drivers/staging/brcm80211/brcmsmac/wlc_scb.h)31
-rw-r--r--drivers/staging/brcm80211/brcmsmac/srom.c (renamed from drivers/staging/brcm80211/brcmsmac/bcmsrom_tbl.h)890
-rw-r--r--drivers/staging/brcm80211/brcmsmac/srom.h (renamed from drivers/staging/brcm80211/include/bcmsrom.h)12
-rw-r--r--drivers/staging/brcm80211/brcmsmac/stf.c (renamed from drivers/staging/brcm80211/brcmsmac/wlc_stf.c)204
-rw-r--r--drivers/staging/brcm80211/brcmsmac/stf.h42
-rw-r--r--drivers/staging/brcm80211/brcmsmac/types.h398
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ucode_loader.c (renamed from drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c)80
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ucode_loader.h (renamed from drivers/staging/brcm80211/brcmsmac/wl_ucode.h)15
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wl_dbg.h92
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wl_export.h47
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h29
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_bmac.h178
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h135
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_cfg.h280
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_key.h140
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c243
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h112
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_pmu.c1929
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_stf.h38
-rw-r--r--drivers/staging/brcm80211/brcmutil/Makefile (renamed from drivers/staging/brcm80211/util/Makefile)6
-rw-r--r--drivers/staging/brcm80211/brcmutil/utils.c (renamed from drivers/staging/brcm80211/util/bcmutils.c)153
-rw-r--r--drivers/staging/brcm80211/brcmutil/wifi.c (renamed from drivers/staging/brcm80211/util/bcmwifi.c)20
-rw-r--r--drivers/staging/brcm80211/include/aidmp.h374
-rw-r--r--drivers/staging/brcm80211/include/bcmdefs.h150
-rw-r--r--drivers/staging/brcm80211/include/bcmdevs.h124
-rw-r--r--drivers/staging/brcm80211/include/bcmnvram.h153
-rw-r--r--drivers/staging/brcm80211/include/bcmsdh.h205
-rw-r--r--drivers/staging/brcm80211/include/bcmsdpcm.h208
-rw-r--r--drivers/staging/brcm80211/include/bcmsrom_fmt.h367
-rw-r--r--drivers/staging/brcm80211/include/bcmutils.h500
-rw-r--r--drivers/staging/brcm80211/include/brcm_hw_ids.h59
-rw-r--r--drivers/staging/brcm80211/include/brcmu_utils.h301
-rw-r--r--drivers/staging/brcm80211/include/brcmu_wifi.h (renamed from drivers/staging/brcm80211/include/bcmwifi.h)126
-rw-r--r--drivers/staging/brcm80211/include/chipcommon.h281
-rw-r--r--drivers/staging/brcm80211/include/defs.h112
-rw-r--r--drivers/staging/brcm80211/include/hndsoc.h199
-rw-r--r--drivers/staging/brcm80211/include/nicpci.h79
-rw-r--r--drivers/staging/brcm80211/include/pci_core.h122
-rw-r--r--drivers/staging/brcm80211/include/pcicfg.h50
-rw-r--r--drivers/staging/brcm80211/include/pcie_core.h299
-rw-r--r--drivers/staging/brcm80211/include/proto/802.11.h200
-rw-r--r--drivers/staging/brcm80211/include/proto/bcmeth.h44
-rw-r--r--drivers/staging/brcm80211/include/proto/bcmevent.h207
-rw-r--r--drivers/staging/brcm80211/include/sbchipc.h1588
-rw-r--r--drivers/staging/brcm80211/include/sbconfig.h272
-rw-r--r--drivers/staging/brcm80211/include/sbhnddma.h315
-rw-r--r--drivers/staging/brcm80211/include/sbsdio.h152
-rw-r--r--drivers/staging/brcm80211/include/sbsdpcmdev.h281
-rw-r--r--drivers/staging/brcm80211/include/sdio.h552
-rw-r--r--drivers/staging/brcm80211/include/soc.h95
-rw-r--r--drivers/staging/brcm80211/include/wlioctl.h1365
-rw-r--r--drivers/staging/comedi/Kconfig10
-rw-r--r--drivers/staging/comedi/comedi.h6
-rw-r--r--drivers/staging/comedi/comedi_fops.c18
-rw-r--r--drivers/staging/comedi/comedidev.h3
-rw-r--r--drivers/staging/comedi/drivers.c4
-rw-r--r--drivers/staging/comedi/drivers/Makefile1
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c2
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c1
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c2
-rw-r--r--drivers/staging/comedi/drivers/das1800.c28
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c1
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c462
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c37
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c1
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c1
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c1
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c22
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c45
-rw-r--r--drivers/staging/comedi/drivers/unioxx5.c46
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c7
-rw-r--r--drivers/staging/cs5535_gpio/Kconfig11
-rw-r--r--drivers/staging/cs5535_gpio/Makefile1
-rw-r--r--drivers/staging/cs5535_gpio/TODO6
-rw-r--r--drivers/staging/cs5535_gpio/cs5535_gpio.c260
-rw-r--r--drivers/staging/cxd2099/cxd2099.c1
-rw-r--r--drivers/staging/cxt1e1/sbecom_inline_linux.h1
-rw-r--r--drivers/staging/dt3155v4l/Kconfig10
-rw-r--r--drivers/staging/dt3155v4l/dt3155v4l.c486
-rw-r--r--drivers/staging/dt3155v4l/dt3155v4l.h22
-rw-r--r--drivers/staging/easycap/Kconfig32
-rw-r--r--drivers/staging/easycap/Makefile4
-rw-r--r--drivers/staging/easycap/README28
-rw-r--r--drivers/staging/easycap/easycap.h46
-rw-r--r--drivers/staging/easycap/easycap_ioctl.c17
-rw-r--r--drivers/staging/easycap/easycap_main.c156
-rw-r--r--drivers/staging/easycap/easycap_settings.c2
-rw-r--r--drivers/staging/easycap/easycap_sound.c35
-rw-r--r--drivers/staging/easycap/easycap_sound_oss.c954
-rw-r--r--drivers/staging/echo/echo.c11
-rw-r--r--drivers/staging/et131x/et1310_address_map.h323
-rw-r--r--drivers/staging/et131x/et1310_mac.c265
-rw-r--r--drivers/staging/et131x/et1310_phy.c33
-rw-r--r--drivers/staging/et131x/et1310_phy.h169
-rw-r--r--drivers/staging/et131x/et1310_pm.c4
-rw-r--r--drivers/staging/et131x/et1310_rx.c214
-rw-r--r--drivers/staging/et131x/et1310_tx.c12
-rw-r--r--drivers/staging/et131x/et131x.h4
-rw-r--r--drivers/staging/et131x/et131x_adapter.h21
-rw-r--r--drivers/staging/et131x/et131x_defs.h1
-rw-r--r--drivers/staging/et131x/et131x_initpci.c34
-rw-r--r--drivers/staging/et131x/et131x_isr.c20
-rw-r--r--drivers/staging/et131x/et131x_netdev.c140
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf14
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.h480
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c190
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h66
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c561
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c224
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c26
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_hw.c9
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h32
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_usb.h413
-rw-r--r--drivers/staging/ft1000/ft1000.h252
-rw-r--r--drivers/staging/generic_serial/Kconfig45
-rw-r--r--drivers/staging/generic_serial/Makefile6
-rw-r--r--drivers/staging/generic_serial/TODO6
-rw-r--r--drivers/staging/generic_serial/generic_serial.c844
-rw-r--r--drivers/staging/generic_serial/rio/Makefile12
-rw-r--r--drivers/staging/generic_serial/rio/board.h132
-rw-r--r--drivers/staging/generic_serial/rio/cirrus.h210
-rw-r--r--drivers/staging/generic_serial/rio/cmdblk.h53
-rw-r--r--drivers/staging/generic_serial/rio/cmdpkt.h177
-rw-r--r--drivers/staging/generic_serial/rio/daemon.h307
-rw-r--r--drivers/staging/generic_serial/rio/errors.h98
-rw-r--r--drivers/staging/generic_serial/rio/func.h143
-rw-r--r--drivers/staging/generic_serial/rio/host.h123
-rw-r--r--drivers/staging/generic_serial/rio/link.h96
-rw-r--r--drivers/staging/generic_serial/rio/linux_compat.h77
-rw-r--r--drivers/staging/generic_serial/rio/map.h98
-rw-r--r--drivers/staging/generic_serial/rio/param.h55
-rw-r--r--drivers/staging/generic_serial/rio/parmmap.h81
-rw-r--r--drivers/staging/generic_serial/rio/pci.h72
-rw-r--r--drivers/staging/generic_serial/rio/phb.h142
-rw-r--r--drivers/staging/generic_serial/rio/pkt.h77
-rw-r--r--drivers/staging/generic_serial/rio/port.h179
-rw-r--r--drivers/staging/generic_serial/rio/protsts.h110
-rw-r--r--drivers/staging/generic_serial/rio/rio.h208
-rw-r--r--drivers/staging/generic_serial/rio/rio_linux.c1204
-rw-r--r--drivers/staging/generic_serial/rio/rio_linux.h197
-rw-r--r--drivers/staging/generic_serial/rio/rioboard.h275
-rw-r--r--drivers/staging/generic_serial/rio/rioboot.c1113
-rw-r--r--drivers/staging/generic_serial/rio/riocmd.c939
-rw-r--r--drivers/staging/generic_serial/rio/rioctrl.c1504
-rw-r--r--drivers/staging/generic_serial/rio/riodrvr.h138
-rw-r--r--drivers/staging/generic_serial/rio/rioinfo.h92
-rw-r--r--drivers/staging/generic_serial/rio/rioinit.c421
-rw-r--r--drivers/staging/generic_serial/rio/riointr.c645
-rw-r--r--drivers/staging/generic_serial/rio/rioioctl.h57
-rw-r--r--drivers/staging/generic_serial/rio/rioparam.c663
-rw-r--r--drivers/staging/generic_serial/rio/rioroute.c1039
-rw-r--r--drivers/staging/generic_serial/rio/riospace.h154
-rw-r--r--drivers/staging/generic_serial/rio/riotable.c941
-rw-r--r--drivers/staging/generic_serial/rio/riotty.c654
-rw-r--r--drivers/staging/generic_serial/rio/route.h101
-rw-r--r--drivers/staging/generic_serial/rio/rup.h69
-rw-r--r--drivers/staging/generic_serial/rio/unixrup.h51
-rw-r--r--drivers/staging/generic_serial/ser_a2232.c831
-rw-r--r--drivers/staging/generic_serial/ser_a2232.h202
-rw-r--r--drivers/staging/generic_serial/ser_a2232fw.ax529
-rw-r--r--drivers/staging/generic_serial/ser_a2232fw.h306
-rw-r--r--drivers/staging/generic_serial/sx.c2894
-rw-r--r--drivers/staging/generic_serial/sx.h201
-rw-r--r--drivers/staging/generic_serial/sxboards.h206
-rw-r--r--drivers/staging/generic_serial/sxwindow.h393
-rw-r--r--drivers/staging/generic_serial/vme_scc.c1145
-rw-r--r--drivers/staging/gma500/Kconfig27
-rw-r--r--drivers/staging/gma500/Makefile48
-rw-r--r--drivers/staging/gma500/TODO29
-rw-r--r--drivers/staging/gma500/accel_2d.c (renamed from drivers/staging/gma500/psb_2d.c)298
-rw-r--r--drivers/staging/gma500/backlight.c49
-rw-r--r--drivers/staging/gma500/cdv_device.c351
-rw-r--r--drivers/staging/gma500/cdv_device.h36
-rw-r--r--drivers/staging/gma500/cdv_intel_crt.c326
-rw-r--r--drivers/staging/gma500/cdv_intel_display.c1508
-rw-r--r--drivers/staging/gma500/cdv_intel_hdmi.c376
-rw-r--r--drivers/staging/gma500/cdv_intel_lvds.c721
-rw-r--r--drivers/staging/gma500/displays/hdmi.h33
-rw-r--r--drivers/staging/gma500/displays/pyr_cmd.h34
-rw-r--r--drivers/staging/gma500/displays/pyr_vid.h34
-rw-r--r--drivers/staging/gma500/displays/tmd_cmd.h34
-rw-r--r--drivers/staging/gma500/displays/tmd_vid.h34
-rw-r--r--drivers/staging/gma500/displays/tpo_cmd.h35
-rw-r--r--drivers/staging/gma500/displays/tpo_vid.h33
-rw-r--r--drivers/staging/gma500/framebuffer.c (renamed from drivers/staging/gma500/psb_fb.c)530
-rw-r--r--drivers/staging/gma500/framebuffer.h (renamed from drivers/staging/gma500/psb_fb.h)11
-rw-r--r--drivers/staging/gma500/gem.c (renamed from drivers/staging/gma500/psb_gem.c)165
-rw-r--r--drivers/staging/gma500/gem_glue.c110
-rw-r--r--drivers/staging/gma500/gem_glue.h4
-rw-r--r--drivers/staging/gma500/gtt.c (renamed from drivers/staging/gma500/psb_gtt.c)247
-rw-r--r--drivers/staging/gma500/gtt.h (renamed from drivers/staging/gma500/psb_gtt.h)14
-rw-r--r--drivers/staging/gma500/intel_bios.c (renamed from drivers/staging/gma500/psb_intel_bios.c)25
-rw-r--r--drivers/staging/gma500/intel_bios.h (renamed from drivers/staging/gma500/psb_intel_bios.h)0
-rw-r--r--drivers/staging/gma500/intel_i2c.c (renamed from drivers/staging/gma500/psb_intel_i2c.c)0
-rw-r--r--drivers/staging/gma500/intel_opregion.c (renamed from drivers/staging/gma500/psb_intel_opregion.c)28
-rw-r--r--drivers/staging/gma500/mdfld_device.c714
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi.c760
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi.h176
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi_dpu.c778
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi_dpu.h154
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dpi.c800
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dpi.h78
-rw-r--r--drivers/staging/gma500/mdfld_dsi_output.c1011
-rw-r--r--drivers/staging/gma500/mdfld_dsi_output.h138
-rw-r--r--drivers/staging/gma500/mdfld_dsi_pkg_sender.c1484
-rw-r--r--drivers/staging/gma500/mdfld_dsi_pkg_sender.h184
-rw-r--r--drivers/staging/gma500/mdfld_intel_display.c1402
-rw-r--r--drivers/staging/gma500/mdfld_msic.h31
-rw-r--r--drivers/staging/gma500/mdfld_output.c170
-rw-r--r--drivers/staging/gma500/mdfld_output.h41
-rw-r--r--drivers/staging/gma500/mdfld_pyr_cmd.c558
-rw-r--r--drivers/staging/gma500/mdfld_tmd_vid.c206
-rw-r--r--drivers/staging/gma500/mdfld_tpo_cmd.c509
-rw-r--r--drivers/staging/gma500/mdfld_tpo_vid.c140
-rw-r--r--drivers/staging/gma500/medfield.h270
-rw-r--r--drivers/staging/gma500/mid_bios.c269
-rw-r--r--drivers/staging/gma500/mid_bios.h21
-rw-r--r--drivers/staging/gma500/mmu.c (renamed from drivers/staging/gma500/psb_mmu.c)0
-rw-r--r--drivers/staging/gma500/mrst.h73
-rw-r--r--drivers/staging/gma500/mrst_crtc.c31
-rw-r--r--drivers/staging/gma500/mrst_device.c634
-rw-r--r--drivers/staging/gma500/mrst_hdmi.c852
-rw-r--r--drivers/staging/gma500/mrst_hdmi_i2c.c327
-rw-r--r--drivers/staging/gma500/mrst_lvds.c92
-rw-r--r--drivers/staging/gma500/power.c (renamed from drivers/staging/gma500/psb_powermgmt.c)237
-rw-r--r--drivers/staging/gma500/power.h (renamed from drivers/staging/gma500/psb_powermgmt.h)6
-rw-r--r--drivers/staging/gma500/psb_bl.c227
-rw-r--r--drivers/staging/gma500/psb_device.c353
-rw-r--r--drivers/staging/gma500/psb_drm.h152
-rw-r--r--drivers/staging/gma500/psb_drv.c456
-rw-r--r--drivers/staging/gma500/psb_drv.h494
-rw-r--r--drivers/staging/gma500/psb_intel_display.c173
-rw-r--r--drivers/staging/gma500/psb_intel_display.h3
-rw-r--r--drivers/staging/gma500/psb_intel_drv.h24
-rw-r--r--drivers/staging/gma500/psb_intel_lvds.c148
-rw-r--r--drivers/staging/gma500/psb_intel_reg.h1144
-rw-r--r--drivers/staging/gma500/psb_intel_sdvo.c35
-rw-r--r--drivers/staging/gma500/psb_intel_sdvo_regs.h14
-rw-r--r--drivers/staging/gma500/psb_irq.c99
-rw-r--r--drivers/staging/gma500/psb_irq.h8
-rw-r--r--drivers/staging/gma500/psb_lid.c6
-rw-r--r--drivers/staging/gma500/psb_reg.h842
-rw-r--r--drivers/staging/hv/blkvsc_drv.c42
-rw-r--r--drivers/staging/hv/channel.c113
-rw-r--r--drivers/staging/hv/channel_mgmt.c8
-rw-r--r--drivers/staging/hv/connection.c52
-rw-r--r--drivers/staging/hv/hv.c4
-rw-r--r--drivers/staging/hv/hv_mouse.c2
-rw-r--r--drivers/staging/hv/hv_timesource.c1
-rw-r--r--drivers/staging/hv/hyperv.h86
-rw-r--r--drivers/staging/hv/hyperv_net.h14
-rw-r--r--drivers/staging/hv/hyperv_vmbus.h2
-rw-r--r--drivers/staging/hv/netvsc.c173
-rw-r--r--drivers/staging/hv/netvsc_drv.c60
-rw-r--r--drivers/staging/hv/ring_buffer.c6
-rw-r--r--drivers/staging/hv/rndis_filter.c59
-rw-r--r--drivers/staging/hv/storvsc.c8
-rw-r--r--drivers/staging/hv/storvsc_drv.c88
-rw-r--r--drivers/staging/hv/tools/hv_kvp_daemon.c1
-rw-r--r--drivers/staging/hv/vmbus_drv.c136
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-light8
-rw-r--r--drivers/staging/iio/accel/adis16201.h12
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c133
-rw-r--r--drivers/staging/iio/accel/adis16201_ring.c8
-rw-r--r--drivers/staging/iio/accel/adis16201_trigger.c11
-rw-r--r--drivers/staging/iio/accel/adis16203.h12
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c85
-rw-r--r--drivers/staging/iio/accel/adis16203_ring.c8
-rw-r--r--drivers/staging/iio/accel/adis16203_trigger.c17
-rw-r--r--drivers/staging/iio/accel/adis16204.h12
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c84
-rw-r--r--drivers/staging/iio/accel/adis16204_ring.c8
-rw-r--r--drivers/staging/iio/accel/adis16204_trigger.c11
-rw-r--r--drivers/staging/iio/accel/adis16209.h12
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c82
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c8
-rw-r--r--drivers/staging/iio/accel/adis16209_trigger.c17
-rw-r--r--drivers/staging/iio/accel/adis16220.h14
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c105
-rw-r--r--drivers/staging/iio/accel/adis16240.h14
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c82
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c8
-rw-r--r--drivers/staging/iio/accel/adis16240_trigger.c17
-rw-r--r--drivers/staging/iio/accel/kxsd9.c102
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c2
-rw-r--r--drivers/staging/iio/accel/sca3000.h1
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c100
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c14
-rw-r--r--drivers/staging/iio/adc/Kconfig14
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/ad7150.c91
-rw-r--r--drivers/staging/iio/adc/ad7152.c73
-rw-r--r--drivers/staging/iio/adc/ad7291.c86
-rw-r--r--drivers/staging/iio/adc/ad7314.c48
-rw-r--r--drivers/staging/iio/adc/ad7476.h5
-rw-r--r--drivers/staging/iio/adc/ad7476_core.c84
-rw-r--r--drivers/staging/iio/adc/ad7476_ring.c10
-rw-r--r--drivers/staging/iio/adc/ad7745.c79
-rw-r--r--drivers/staging/iio/adc/ad7793.c987
-rw-r--r--drivers/staging/iio/adc/ad7793.h107
-rw-r--r--drivers/staging/iio/adc/ad7816.c74
-rw-r--r--drivers/staging/iio/adc/ad7887_core.c3
-rw-r--r--drivers/staging/iio/adc/ad7887_ring.c6
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c13
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c4
-rw-r--r--drivers/staging/iio/adc/adt7310.c94
-rw-r--r--drivers/staging/iio/adc/adt7410.c86
-rw-r--r--drivers/staging/iio/adc/adt75.c123
-rw-r--r--drivers/staging/iio/adc/max1363_core.c20
-rw-r--r--drivers/staging/iio/addac/adt7316.c224
-rw-r--r--drivers/staging/iio/dac/Kconfig11
-rw-r--r--drivers/staging/iio/dac/Makefile1
-rw-r--r--drivers/staging/iio/dac/ad5446.c82
-rw-r--r--drivers/staging/iio/dac/ad5446.h2
-rw-r--r--drivers/staging/iio/dac/ad5504.c89
-rw-r--r--drivers/staging/iio/dac/ad5504.h2
-rw-r--r--drivers/staging/iio/dac/ad5624r.h1
-rw-r--r--drivers/staging/iio/dac/ad5624r_spi.c84
-rw-r--r--drivers/staging/iio/dac/ad5686.c497
-rw-r--r--drivers/staging/iio/dac/ad5791.c112
-rw-r--r--drivers/staging/iio/dac/ad5791.h2
-rw-r--r--drivers/staging/iio/dac/max517.c40
-rw-r--r--drivers/staging/iio/dds/ad5930.c37
-rw-r--r--drivers/staging/iio/dds/ad9832.c69
-rw-r--r--drivers/staging/iio/dds/ad9832.h2
-rw-r--r--drivers/staging/iio/dds/ad9834.c81
-rw-r--r--drivers/staging/iio/dds/ad9834.h2
-rw-r--r--drivers/staging/iio/dds/ad9850.c37
-rw-r--r--drivers/staging/iio/dds/ad9852.c38
-rw-r--r--drivers/staging/iio/dds/ad9910.c36
-rw-r--r--drivers/staging/iio/dds/ad9951.c36
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c59
-rw-r--r--drivers/staging/iio/gyro/adis16080_core.c48
-rw-r--r--drivers/staging/iio/gyro/adis16130_core.c50
-rw-r--r--drivers/staging/iio/gyro/adis16260.h18
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c100
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c9
-rw-r--r--drivers/staging/iio/gyro/adis16260_trigger.c15
-rw-r--r--drivers/staging/iio/gyro/adxrs450.h13
-rw-r--r--drivers/staging/iio/gyro/adxrs450_core.c71
-rw-r--r--drivers/staging/iio/iio.h16
-rw-r--r--drivers/staging/iio/imu/adis16400.h3
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c50
-rw-r--r--drivers/staging/iio/industrialio-core.c47
-rw-r--r--drivers/staging/iio/industrialio-trigger.c20
-rw-r--r--drivers/staging/iio/kfifo_buf.c2
-rw-r--r--drivers/staging/iio/light/Kconfig2
-rw-r--r--drivers/staging/iio/light/isl29018.c197
-rw-r--r--drivers/staging/iio/light/tsl2563.c125
-rw-r--r--drivers/staging/iio/magnetometer/ak8975.c91
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c50
-rw-r--r--drivers/staging/iio/meter/ade7753.c83
-rw-r--r--drivers/staging/iio/meter/ade7753.h10
-rw-r--r--drivers/staging/iio/meter/ade7754.c80
-rw-r--r--drivers/staging/iio/meter/ade7754.h12
-rw-r--r--drivers/staging/iio/meter/ade7759.c80
-rw-r--r--drivers/staging/iio/meter/ade7759.h12
-rw-r--r--drivers/staging/iio/meter/ade7854-i2c.c39
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c40
-rw-r--r--drivers/staging/iio/meter/ade7854.c76
-rw-r--r--drivers/staging/iio/meter/ade7854.h36
-rw-r--r--drivers/staging/iio/resolver/Kconfig27
-rw-r--r--drivers/staging/iio/resolver/ad2s120x.c196
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c856
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.h17
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c48
-rw-r--r--drivers/staging/iio/trigger.h52
-rw-r--r--drivers/staging/iio/trigger/iio-trig-gpio.c2
-rw-r--r--drivers/staging/intel_sst/intel_sst.c5
-rw-r--r--drivers/staging/intel_sst/intel_sst_app_interface.c4
-rw-r--r--drivers/staging/intel_sst/intel_sst_common.h2
-rw-r--r--drivers/staging/intel_sst/intel_sst_drv_interface.c10
-rw-r--r--drivers/staging/intel_sst/intelmid_v2_control.c2
-rw-r--r--drivers/staging/keucr/Kconfig6
-rw-r--r--drivers/staging/keucr/Makefile2
-rw-r--r--drivers/staging/keucr/init.c71
-rw-r--r--drivers/staging/keucr/init.h773
-rw-r--r--drivers/staging/keucr/ms.c1034
-rw-r--r--drivers/staging/keucr/ms.h401
-rw-r--r--drivers/staging/keucr/msscsi.c344
-rw-r--r--drivers/staging/keucr/transport.c4
-rw-r--r--drivers/staging/keucr/transport.h46
-rw-r--r--drivers/staging/keucr/usb.c5
-rw-r--r--drivers/staging/keucr/usb.h3
-rw-r--r--drivers/staging/lirc/lirc_bt829.c4
-rw-r--r--drivers/staging/lirc/lirc_parallel.c6
-rw-r--r--drivers/staging/lirc/lirc_ttusbir.c1
-rw-r--r--drivers/staging/lirc/lirc_zilog.c2
-rw-r--r--drivers/staging/mei/init.c149
-rw-r--r--drivers/staging/mei/interface.c9
-rw-r--r--drivers/staging/mei/interrupt.c47
-rw-r--r--drivers/staging/mei/iorw.c32
-rw-r--r--drivers/staging/mei/main.c39
-rw-r--r--drivers/staging/mei/mei_dev.h123
-rw-r--r--drivers/staging/mei/wd.c18
-rw-r--r--drivers/staging/msm/Kconfig124
-rw-r--r--drivers/staging/msm/Makefile88
-rw-r--r--drivers/staging/msm/TODO3
-rw-r--r--drivers/staging/msm/ebi2_l2f.c569
-rw-r--r--drivers/staging/msm/ebi2_lcd.c250
-rw-r--r--drivers/staging/msm/ebi2_tmd20.c1122
-rw-r--r--drivers/staging/msm/hdmi_sii9022.c248
-rw-r--r--drivers/staging/msm/lcdc.c239
-rw-r--r--drivers/staging/msm/lcdc_external.c54
-rw-r--r--drivers/staging/msm/lcdc_gordon.c446
-rw-r--r--drivers/staging/msm/lcdc_panel.c88
-rw-r--r--drivers/staging/msm/lcdc_prism.c64
-rw-r--r--drivers/staging/msm/lcdc_sharp_wvga_pt.c290
-rw-r--r--drivers/staging/msm/lcdc_st15.c237
-rw-r--r--drivers/staging/msm/lcdc_toshiba_wvga_pt.c374
-rw-r--r--drivers/staging/msm/logo.c98
-rw-r--r--drivers/staging/msm/mddi.c375
-rw-r--r--drivers/staging/msm/mddi_ext.c320
-rw-r--r--drivers/staging/msm/mddi_ext_lcd.c91
-rw-r--r--drivers/staging/msm/mddi_prism.c114
-rw-r--r--drivers/staging/msm/mddi_sharp.c892
-rw-r--r--drivers/staging/msm/mddi_toshiba.c1741
-rw-r--r--drivers/staging/msm/mddi_toshiba.h36
-rw-r--r--drivers/staging/msm/mddi_toshiba_vga.c136
-rw-r--r--drivers/staging/msm/mddi_toshiba_wvga_pt.c64
-rw-r--r--drivers/staging/msm/mddihost.c377
-rw-r--r--drivers/staging/msm/mddihost.h207
-rw-r--r--drivers/staging/msm/mddihost_e.c63
-rw-r--r--drivers/staging/msm/mddihosti.c2239
-rw-r--r--drivers/staging/msm/mddihosti.h531
-rw-r--r--drivers/staging/msm/mdp.c1113
-rw-r--r--drivers/staging/msm/mdp.h679
-rw-r--r--drivers/staging/msm/mdp4.h336
-rw-r--r--drivers/staging/msm/mdp4_debugfs.c175
-rw-r--r--drivers/staging/msm/mdp4_overlay.c1259
-rw-r--r--drivers/staging/msm/mdp4_overlay_lcdc.c313
-rw-r--r--drivers/staging/msm/mdp4_overlay_mddi.c254
-rw-r--r--drivers/staging/msm/mdp4_util.c1686
-rw-r--r--drivers/staging/msm/mdp_cursor.c104
-rw-r--r--drivers/staging/msm/mdp_dma.c561
-rw-r--r--drivers/staging/msm/mdp_dma_lcdc.c379
-rw-r--r--drivers/staging/msm/mdp_dma_s.c139
-rw-r--r--drivers/staging/msm/mdp_dma_tv.c142
-rw-r--r--drivers/staging/msm/mdp_hw_init.c720
-rw-r--r--drivers/staging/msm/mdp_ppp.c1502
-rw-r--r--drivers/staging/msm/mdp_ppp_dq.c347
-rw-r--r--drivers/staging/msm/mdp_ppp_dq.h69
-rw-r--r--drivers/staging/msm/mdp_ppp_v20.c2486
-rw-r--r--drivers/staging/msm/mdp_ppp_v31.c828
-rw-r--r--drivers/staging/msm/mdp_vsync.c389
-rw-r--r--drivers/staging/msm/memory.c214
-rw-r--r--drivers/staging/msm/memory_ll.h61
-rw-r--r--drivers/staging/msm/msm_fb.c2354
-rw-r--r--drivers/staging/msm/msm_fb.h158
-rw-r--r--drivers/staging/msm/msm_fb_bl.c79
-rw-r--r--drivers/staging/msm/msm_fb_def.h181
-rw-r--r--drivers/staging/msm/msm_fb_panel.c136
-rw-r--r--drivers/staging/msm/msm_fb_panel.h129
-rw-r--r--drivers/staging/msm/msm_mdp.h245
-rw-r--r--drivers/staging/msm/staging-devices.c312
-rw-r--r--drivers/staging/msm/tv_ntsc.c163
-rw-r--r--drivers/staging/msm/tv_pal.c213
-rw-r--r--drivers/staging/msm/tvenc.c296
-rw-r--r--drivers/staging/msm/tvenc.h101
-rw-r--r--drivers/staging/nvec/nvec.c1
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c27
-rw-r--r--drivers/staging/octeon/ethernet-rgmii.c33
-rw-r--r--drivers/staging/octeon/ethernet-rx.c26
-rw-r--r--drivers/staging/octeon/ethernet-sgmii.c14
-rw-r--r--drivers/staging/octeon/ethernet-tx.c13
-rw-r--r--drivers/staging/octeon/ethernet-util.h4
-rw-r--r--drivers/staging/octeon/ethernet-xaui.c22
-rw-r--r--drivers/staging/panel/panel.c1
-rw-r--r--drivers/staging/pohmelfs/crypto.c1
-rw-r--r--drivers/staging/pohmelfs/dir.c2
-rw-r--r--drivers/staging/pohmelfs/inode.c11
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211.h2
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_module.c1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c9
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c2
-rw-r--r--drivers/staging/rtl8187se/r8180.h1
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c3
-rw-r--r--drivers/staging/rtl8192e/dot11d.h23
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211.h2
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c1
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c1
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c1
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c1
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_module.c3
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c1
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c3
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c3
-rw-r--r--drivers/staging/rtl8192e/r8192E.h2
-rw-r--r--drivers/staging/rtl8192e/r8192E_core.c14
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_module.c3
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c1
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c7
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c2
-rw-r--r--drivers/staging/rtl8192u/r8192U.h1
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c10
-rw-r--r--drivers/staging/rtl8712/drv_types.h1
-rw-r--r--drivers/staging/rtl8712/ieee80211.h31
-rw-r--r--drivers/staging/rtl8712/osdep_service.h7
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h2
-rw-r--r--drivers/staging/rtl8712/wifi.h7
-rw-r--r--drivers/staging/rts_pstor/ms.c3
-rw-r--r--drivers/staging/rts_pstor/rtsx.h1
-rw-r--r--drivers/staging/rts_pstor/rtsx_chip.c6
-rw-r--r--drivers/staging/rts_pstor/sd.c64
-rw-r--r--drivers/staging/rts_pstor/sd.h5
-rw-r--r--drivers/staging/sep/sep_driver.c7
-rw-r--r--drivers/staging/sep/sep_driver_config.h2
-rw-r--r--drivers/staging/solo6x10/solo6x10.h2
-rw-r--r--drivers/staging/speakup/main.c1
-rw-r--r--drivers/staging/speakup/speakup.h1
-rw-r--r--drivers/staging/speakup/speakup_soft.c9
-rw-r--r--drivers/staging/spectra/lld_nand.c18
-rw-r--r--drivers/staging/ste_rmi4/Makefile1
-rw-r--r--drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c32
-rw-r--r--drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c43
-rw-r--r--drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h2
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/host_os.h3
-rw-r--r--drivers/staging/tm6000/tm6000-alsa.c8
-rw-r--r--drivers/staging/tm6000/tm6000-cards.c7
-rw-r--r--drivers/staging/tm6000/tm6000-dvb.c10
-rw-r--r--drivers/staging/tm6000/tm6000-i2c.c2
-rw-r--r--drivers/staging/tm6000/tm6000-input.c3
-rw-r--r--drivers/staging/tm6000/tm6000-video.c43
-rw-r--r--drivers/staging/tm6000/tm6000.h3
-rw-r--r--drivers/staging/tty/Kconfig87
-rw-r--r--drivers/staging/tty/Makefile7
-rw-r--r--drivers/staging/tty/TODO6
-rw-r--r--drivers/staging/tty/cd1865.h263
-rw-r--r--drivers/staging/tty/digi1.h100
-rw-r--r--drivers/staging/tty/digiFep1.h136
-rw-r--r--drivers/staging/tty/digiPCI.h42
-rw-r--r--drivers/staging/tty/epca.c2784
-rw-r--r--drivers/staging/tty/epca.h158
-rw-r--r--drivers/staging/tty/epcaconfig.h7
-rw-r--r--drivers/staging/tty/ip2/Makefile8
-rw-r--r--drivers/staging/tty/ip2/i2cmd.c210
-rw-r--r--drivers/staging/tty/ip2/i2cmd.h630
-rw-r--r--drivers/staging/tty/ip2/i2ellis.c1403
-rw-r--r--drivers/staging/tty/ip2/i2ellis.h566
-rw-r--r--drivers/staging/tty/ip2/i2hw.h652
-rw-r--r--drivers/staging/tty/ip2/i2lib.c2214
-rw-r--r--drivers/staging/tty/ip2/i2lib.h351
-rw-r--r--drivers/staging/tty/ip2/i2pack.h364
-rw-r--r--drivers/staging/tty/ip2/ip2.h107
-rw-r--r--drivers/staging/tty/ip2/ip2ioctl.h35
-rw-r--r--drivers/staging/tty/ip2/ip2main.c3234
-rw-r--r--drivers/staging/tty/ip2/ip2trace.h42
-rw-r--r--drivers/staging/tty/ip2/ip2types.h57
-rw-r--r--drivers/staging/tty/istallion.c4507
-rw-r--r--drivers/staging/tty/riscom8.c1560
-rw-r--r--drivers/staging/tty/riscom8.h91
-rw-r--r--drivers/staging/tty/riscom8_reg.h254
-rw-r--r--drivers/staging/tty/serial167.c2489
-rw-r--r--drivers/staging/tty/specialix.c2368
-rw-r--r--drivers/staging/tty/specialix_io8.h140
-rw-r--r--drivers/staging/tty/stallion.c4651
-rw-r--r--drivers/staging/usbip/README1
-rw-r--r--drivers/staging/usbip/stub.h4
-rw-r--r--drivers/staging/usbip/stub_dev.c55
-rw-r--r--drivers/staging/usbip/stub_main.c193
-rw-r--r--drivers/staging/usbip/stub_rx.c6
-rw-r--r--drivers/staging/usbip/stub_tx.c15
-rw-r--r--drivers/staging/usbip/usbip_common.c35
-rw-r--r--drivers/staging/usbip/usbip_common.h238
-rw-r--r--drivers/staging/usbip/userspace/AUTHORS1
-rw-r--r--drivers/staging/usbip/userspace/Makefile.am9
-rw-r--r--drivers/staging/usbip/userspace/README298
-rwxr-xr-xdrivers/staging/usbip/userspace/cleanup.sh10
-rw-r--r--drivers/staging/usbip/userspace/configure.ac26
-rw-r--r--drivers/staging/usbip/userspace/libsrc/Makefile.am8
-rw-r--r--drivers/staging/usbip/userspace/libsrc/stub_driver.c391
-rw-r--r--drivers/staging/usbip/userspace/libsrc/stub_driver.h36
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip.h19
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_common.c28
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_common.h138
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c401
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h48
-rw-r--r--drivers/staging/usbip/userspace/libsrc/vhci_driver.c167
-rw-r--r--drivers/staging/usbip/userspace/libsrc/vhci_driver.h32
-rw-r--r--drivers/staging/usbip/userspace/src/Makefile.am17
-rw-r--r--drivers/staging/usbip/userspace/src/bind-driver.c643
-rw-r--r--drivers/staging/usbip/userspace/src/usbip.c817
-rw-r--r--drivers/staging/usbip/userspace/src/usbip.h39
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_attach.c228
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_bind.c277
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_detach.c103
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_list.c303
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_network.c198
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_network.h94
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_unbind.c186
-rw-r--r--drivers/staging/usbip/userspace/src/usbipd.c705
-rw-r--r--drivers/staging/usbip/userspace/src/utils.c283
-rw-r--r--drivers/staging/usbip/userspace/src/utils.h56
-rw-r--r--drivers/staging/usbip/userspace/usb.ids13209
-rw-r--r--drivers/staging/usbip/vhci.h11
-rw-r--r--drivers/staging/usbip/vhci_hcd.c59
-rw-r--r--drivers/staging/usbip/vhci_rx.c2
-rw-r--r--drivers/staging/usbip/vhci_sysfs.c6
-rw-r--r--drivers/staging/vme/boards/vme_vmivme7805.c4
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c19
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c2
-rw-r--r--drivers/staging/vme/devices/vme_user.c53
-rw-r--r--drivers/staging/vme/devices/vme_user.h6
-rw-r--r--drivers/staging/vme/vme.h2
-rw-r--r--drivers/staging/westbridge/Kconfig53
-rw-r--r--drivers/staging/westbridge/TODO7
-rw-r--r--drivers/staging/westbridge/astoria/Kconfig9
-rw-r--r--drivers/staging/westbridge/astoria/Makefile11
-rw-r--r--drivers/staging/westbridge/astoria/api/Makefile14
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyasdma.c1107
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyasintr.c143
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c358
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c1264
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyasmisc.c3488
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyasmtp.c1136
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyasstorage.c4125
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyasusb.c3740
-rw-r--r--drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c2441
-rw-r--r--drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h55
-rw-r--r--drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h319
-rw-r--r--drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h558
-rw-r--r--drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h72
-rw-r--r--drivers/staging/westbridge/astoria/block/Kconfig9
-rw-r--r--drivers/staging/westbridge/astoria/block/Makefile11
-rw-r--r--drivers/staging/westbridge/astoria/block/cyasblkdev_block.c1631
-rw-r--r--drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c417
-rw-r--r--drivers/staging/westbridge/astoria/block/cyasblkdev_queue.h64
-rw-r--r--drivers/staging/westbridge/astoria/device/Kconfig9
-rw-r--r--drivers/staging/westbridge/astoria/device/Makefile23
-rw-r--r--drivers/staging/westbridge/astoria/device/cyasdevice.c409
-rw-r--r--drivers/staging/westbridge/astoria/gadget/Kconfig9
-rw-r--r--drivers/staging/westbridge/astoria/gadget/Makefile11
-rw-r--r--drivers/staging/westbridge/astoria/gadget/cyasgadget.c2177
-rw-r--r--drivers/staging/westbridge/astoria/gadget/cyasgadget.h193
-rw-r--r--drivers/staging/westbridge/astoria/gadget/cyasgadget_ioctl.h99
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyanerr.h418
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmedia.h59
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmisc.h614
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyanregs.h180
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyansdkversion.h30
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyanstorage.h419
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyantioch.h35
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyantypes.h31
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyanusb.h619
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_end.h11
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_start.h11
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyascast.h35
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h1057
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h375
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h1094
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyashal.h108
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyashalcb.h44
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h800
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h104
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslep2pep.h36
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslowlevel.h366
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmedia.h54
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h1549
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc_dep.h53
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmtp.h646
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h3838
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasregs.h201
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h2759
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage_dep.h309
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyastoria.h36
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyastsdkversion.h30
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyastypes.h71
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h1862
-rw-r--r--drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb_dep.h224
-rw-r--r--drivers/staging/winbond/mds_s.h2
-rw-r--r--drivers/staging/winbond/phy_calibration.c462
-rw-r--r--drivers/staging/winbond/wb35reg_s.h2
-rw-r--r--drivers/staging/wlags49_h2/wl_internal.h8
-rw-r--r--drivers/staging/wlags49_h2/wl_version.h1
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c4
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c1
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c1
-rw-r--r--drivers/staging/xgifb/vb_ext.c1
-rw-r--r--drivers/staging/xgifb/vb_init.c1
-rw-r--r--drivers/staging/xgifb/vb_setmode.c1
-rw-r--r--drivers/staging/zcache/tmem.c100
-rw-r--r--drivers/staging/zcache/tmem.h23
-rw-r--r--drivers/staging/zcache/zcache.c517
-rw-r--r--drivers/staging/zram/zram_drv.c457
-rw-r--r--drivers/staging/zram/zram_drv.h9
-rw-r--r--drivers/target/loopback/Kconfig6
-rw-r--r--drivers/target/loopback/tcm_loop.c207
-rw-r--r--drivers/target/loopback/tcm_loop.h6
-rw-r--r--drivers/target/target_core_alua.c426
-rw-r--r--drivers/target/target_core_cdb.c457
-rw-r--r--drivers/target/target_core_configfs.c667
-rw-r--r--drivers/target/target_core_device.c819
-rw-r--r--drivers/target/target_core_fabric_configfs.c122
-rw-r--r--drivers/target/target_core_fabric_lib.c27
-rw-r--r--drivers/target/target_core_file.c149
-rw-r--r--drivers/target/target_core_file.h4
-rw-r--r--drivers/target/target_core_hba.c37
-rw-r--r--drivers/target/target_core_iblock.c199
-rw-r--r--drivers/target/target_core_iblock.h9
-rw-r--r--drivers/target/target_core_pr.c862
-rw-r--r--drivers/target/target_core_pr.h2
-rw-r--r--drivers/target/target_core_pscsi.c316
-rw-r--r--drivers/target/target_core_pscsi.h4
-rw-r--r--drivers/target/target_core_rd.c483
-rw-r--r--drivers/target/target_core_rd.h4
-rw-r--r--drivers/target/target_core_scdb.c20
-rw-r--r--drivers/target/target_core_scdb.h10
-rw-r--r--drivers/target/target_core_stat.c112
-rw-r--r--drivers/target/target_core_tmr.c185
-rw-r--r--drivers/target/target_core_tpg.c206
-rw-r--r--drivers/target/target_core_transport.c3626
-rw-r--r--drivers/target/target_core_ua.c62
-rw-r--r--drivers/target/tcm_fc/Makefile17
-rw-r--r--drivers/target/tcm_fc/tcm_fc.h25
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c141
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c48
-rw-r--r--drivers/target/tcm_fc/tfc_io.c131
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c20
-rw-r--r--drivers/tty/bfin_jtag_comm.c2
-rw-r--r--drivers/tty/hvc/Kconfig5
-rw-r--r--drivers/tty/hvc/Makefile3
-rw-r--r--drivers/tty/hvc/hvc_console.c70
-rw-r--r--drivers/tty/hvc/hvc_console.h4
-rw-r--r--drivers/tty/hvc/hvc_vio.c408
-rw-r--r--drivers/tty/hvc/hvsi.c129
-rw-r--r--drivers/tty/hvc/hvsi_lib.c426
-rw-r--r--drivers/tty/moxa.c5
-rw-r--r--drivers/tty/mxser.c4
-rw-r--r--drivers/tty/n_gsm.c401
-rw-r--r--drivers/tty/n_tty.c2
-rw-r--r--drivers/tty/rocket.c2
-rw-r--r--drivers/tty/serial/8250.c4
-rw-r--r--drivers/tty/serial/8250_pci.c185
-rw-r--r--drivers/tty/serial/Kconfig17
-rw-r--r--drivers/tty/serial/Makefile2
-rw-r--r--drivers/tty/serial/bfin_5xx.c5
-rw-r--r--drivers/tty/serial/dz.c2
-rw-r--r--drivers/tty/serial/ifx6x60.c1
-rw-r--r--drivers/tty/serial/imx.c5
-rw-r--r--drivers/tty/serial/m32r_sio.c2
-rw-r--r--drivers/tty/serial/of_serial.c43
-rw-r--r--drivers/tty/serial/omap-serial.c6
-rw-r--r--drivers/tty/serial/pch_uart.c11
-rw-r--r--drivers/tty/serial/pxa.c2
-rw-r--r--drivers/tty/serial/s3c2400.c105
-rw-r--r--drivers/tty/serial/s3c2410.c2
-rw-r--r--drivers/tty/serial/s3c2412.c2
-rw-r--r--drivers/tty/serial/s3c2440.c2
-rw-r--r--drivers/tty/serial/s3c24a0.c117
-rw-r--r--drivers/tty/serial/s3c6400.c2
-rw-r--r--drivers/tty/serial/s5pv210.c11
-rw-r--r--drivers/tty/serial/samsung.c36
-rw-r--r--drivers/tty/serial/samsung.h19
-rw-r--r--drivers/tty/serial/sb1250-duart.c2
-rw-r--r--drivers/tty/serial/sunsu.c2
-rw-r--r--drivers/tty/serial/vt8500_serial.c3
-rw-r--r--drivers/tty/serial/zs.c2
-rw-r--r--drivers/tty/tty_io.c4
-rw-r--r--drivers/uio/uio_pdrv.c2
-rw-r--r--drivers/uio/uio_pdrv_genirq.c45
-rw-r--r--drivers/usb/atm/ueagle-atm.c38
-rw-r--r--drivers/usb/atm/usbatm.c4
-rw-r--r--drivers/usb/class/usblp.c7
-rw-r--r--drivers/usb/core/hcd.c17
-rw-r--r--drivers/usb/gadget/Kconfig313
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/amd5536udc.c18
-rw-r--r--drivers/usb/gadget/at91_udc.c20
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c28
-rw-r--r--drivers/usb/gadget/audio.c1
-rw-r--r--drivers/usb/gadget/cdc2.c1
-rw-r--r--drivers/usb/gadget/ci13xxx_msm.c1
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c62
-rw-r--r--drivers/usb/gadget/composite.c363
-rw-r--r--drivers/usb/gadget/config.c25
-rw-r--r--drivers/usb/gadget/dbgp.c10
-rw-r--r--drivers/usb/gadget/dummy_hcd.c1162
-rw-r--r--drivers/usb/gadget/epautoconf.c132
-rw-r--r--drivers/usb/gadget/ether.c1
-rw-r--r--drivers/usb/gadget/f_acm.c50
-rw-r--r--drivers/usb/gadget/f_audio.c7
-rw-r--r--drivers/usb/gadget/f_ecm.c152
-rw-r--r--drivers/usb/gadget/f_eem.c90
-rw-r--r--drivers/usb/gadget/f_fs.c3
-rw-r--r--drivers/usb/gadget/f_hid.c22
-rw-r--r--drivers/usb/gadget/f_loopback.c72
-rw-r--r--drivers/usb/gadget/f_mass_storage.c33
-rw-r--r--drivers/usb/gadget/f_ncm.c58
-rw-r--r--drivers/usb/gadget/f_obex.c32
-rw-r--r--drivers/usb/gadget/f_phonet.c18
-rw-r--r--drivers/usb/gadget/f_rndis.c153
-rw-r--r--drivers/usb/gadget/f_serial.c32
-rw-r--r--drivers/usb/gadget/f_sourcesink.c71
-rw-r--r--drivers/usb/gadget/f_subset.c95
-rw-r--r--drivers/usb/gadget/f_uvc.c8
-rw-r--r--drivers/usb/gadget/file_storage.c15
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c20
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c26
-rw-r--r--drivers/usb/gadget/fusb300_udc.c111
-rw-r--r--drivers/usb/gadget/g_ffs.c1
-rw-r--r--drivers/usb/gadget/gadget_chips.h178
-rw-r--r--drivers/usb/gadget/gmidi.c9
-rw-r--r--drivers/usb/gadget/goku_udc.c19
-rw-r--r--drivers/usb/gadget/hid.c1
-rw-r--r--drivers/usb/gadget/imx_udc.c20
-rw-r--r--drivers/usb/gadget/inode.c11
-rw-r--r--drivers/usb/gadget/langwell_udc.c32
-rw-r--r--drivers/usb/gadget/m66592-udc.c62
-rw-r--r--drivers/usb/gadget/m66592-udc.h40
-rw-r--r--drivers/usb/gadget/mass_storage.c1
-rw-r--r--drivers/usb/gadget/multi.c1
-rw-r--r--drivers/usb/gadget/mv_udc_core.c21
-rw-r--r--drivers/usb/gadget/ncm.c1
-rw-r--r--drivers/usb/gadget/net2272.c2752
-rw-r--r--drivers/usb/gadget/net2272.h601
-rw-r--r--drivers/usb/gadget/net2280.c74
-rw-r--r--drivers/usb/gadget/nokia.c1
-rw-r--r--drivers/usb/gadget/omap_udc.c22
-rw-r--r--drivers/usb/gadget/pch_udc.c16
-rw-r--r--drivers/usb/gadget/printer.c45
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c19
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c23
-rw-r--r--drivers/usb/gadget/pxa27x_udc.h4
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c71
-rw-r--r--drivers/usb/gadget/r8a66597-udc.h2
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c19
-rw-r--r--drivers/usb/gadget/s3c-hsudc.c17
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c60
-rw-r--r--drivers/usb/gadget/serial.c1
-rw-r--r--drivers/usb/gadget/storage_common.c2
-rw-r--r--drivers/usb/gadget/u_ether.c24
-rw-r--r--drivers/usb/gadget/u_ether.h4
-rw-r--r--drivers/usb/gadget/u_serial.c4
-rw-r--r--drivers/usb/gadget/u_serial.h2
-rw-r--r--drivers/usb/gadget/udc-core.c484
-rw-r--r--drivers/usb/gadget/uvc_queue.c2
-rw-r--r--drivers/usb/gadget/webcam.c1
-rw-r--r--drivers/usb/gadget/zero.c1
-rw-r--r--drivers/usb/host/ehci-ath79.c2
-rw-r--r--drivers/usb/host/ehci-cns3xxx.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c2
-rw-r--r--drivers/usb/host/ehci-grlib.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c21
-rw-r--r--drivers/usb/host/ehci-hub.c78
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c2
-rw-r--r--drivers/usb/host/ehci-msm.c20
-rw-r--r--drivers/usb/host/ehci-octeon.c2
-rw-r--r--drivers/usb/host/ehci-pmcmsp.c10
-rw-r--r--drivers/usb/host/ehci-ppc-of.c2
-rw-r--r--drivers/usb/host/ehci-q.c85
-rw-r--r--drivers/usb/host/ehci-s5p.c95
-rw-r--r--drivers/usb/host/ehci-sched.c17
-rw-r--r--drivers/usb/host/ehci-sysfs.c190
-rw-r--r--drivers/usb/host/ehci-w90x900.c2
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/ehci.h6
-rw-r--r--drivers/usb/host/fhci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-ath79.c4
-rw-r--r--drivers/usb/host/ohci-cns3xxx.c2
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/ohci-octeon.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-sa1111.c2
-rw-r--r--drivers/usb/host/ohci-sh.c2
-rw-r--r--drivers/usb/host/ohci-sm501.c11
-rw-r--r--drivers/usb/host/ohci-ssb.c2
-rw-r--r--drivers/usb/host/ohci-tmio.c6
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c2
-rw-r--r--drivers/usb/host/pci-quirks.c56
-rw-r--r--drivers/usb/host/r8a66597-hcd.c6
-rw-r--r--drivers/usb/host/r8a66597.h38
-rw-r--r--drivers/usb/host/uhci-grlib.c2
-rw-r--r--drivers/usb/host/whci/init.c2
-rw-r--r--drivers/usb/host/xhci-dbg.c22
-rw-r--r--drivers/usb/host/xhci-mem.c26
-rw-r--r--drivers/usb/host/xhci-ring.c42
-rw-r--r--drivers/usb/host/xhci.c10
-rw-r--r--drivers/usb/host/xhci.h7
-rw-r--r--drivers/usb/image/microtek.c2
-rw-r--r--drivers/usb/misc/appledisplay.c2
-rw-r--r--drivers/usb/misc/ftdi-elan.c28
-rw-r--r--drivers/usb/mon/mon_text.c9
-rw-r--r--drivers/usb/musb/Kconfig75
-rw-r--r--drivers/usb/musb/Makefile4
-rw-r--r--drivers/usb/musb/am35x.c4
-rw-r--r--drivers/usb/musb/blackfin.h2
-rw-r--r--drivers/usb/musb/da8xx.c12
-rw-r--r--drivers/usb/musb/davinci.c5
-rw-r--r--drivers/usb/musb/musb_core.c135
-rw-r--r--drivers/usb/musb/musb_core.h70
-rw-r--r--drivers/usb/musb/musb_gadget.c102
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c4
-rw-r--r--drivers/usb/musb/musb_host.h4
-rw-r--r--drivers/usb/musb/musb_virthub.c6
-rw-r--r--drivers/usb/musb/omap2430.c15
-rw-r--r--drivers/usb/musb/tusb6010.c26
-rw-r--r--drivers/usb/otg/isp1301_omap.c4
-rw-r--r--drivers/usb/otg/otg_fsm.c1
-rw-r--r--drivers/usb/otg/twl4030-usb.c2
-rw-r--r--drivers/usb/otg/twl6030-usb.c30
-rw-r--r--drivers/usb/renesas_usbhs/Kconfig13
-rw-r--r--drivers/usb/renesas_usbhs/Makefile2
-rw-r--r--drivers/usb/renesas_usbhs/common.c34
-rw-r--r--drivers/usb/renesas_usbhs/common.h44
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c1016
-rw-r--r--drivers/usb/renesas_usbhs/fifo.h104
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c840
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c298
-rw-r--r--drivers/usb/renesas_usbhs/pipe.h47
-rw-r--r--drivers/usb/serial/garmin_gps.c2
-rw-r--r--drivers/usb/serial/pl2303.c27
-rw-r--r--drivers/usb/serial/pl2303.h4
-rw-r--r--drivers/usb/storage/Kconfig8
-rw-r--r--drivers/usb/storage/ene_ub6250.c1639
-rw-r--r--drivers/usb/storage/realtek_cr.c490
-rw-r--r--drivers/usb/wusbcore/cbaf.c4
-rw-r--r--drivers/usb/wusbcore/wa-rpipe.c2
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c7
-rw-r--r--drivers/uwb/uwbd.c2
-rw-r--r--drivers/uwb/whc-rc.c2
-rw-r--r--drivers/vhost/net.c91
-rw-r--r--drivers/vhost/test.c5
-rw-r--r--drivers/vhost/vhost.c213
-rw-r--r--drivers/vhost/vhost.h34
-rw-r--r--drivers/video/atmel_lcdfb.c4
-rw-r--r--drivers/video/aty/atyfb_base.c7
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/backlight/Kconfig8
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/adp8860_bl.c3
-rw-r--r--drivers/video/backlight/ams369fg06.c646
-rw-r--r--drivers/video/backlight/ld9040.c17
-rw-r--r--drivers/video/backlight/s6e63m0.c11
-rw-r--r--drivers/video/cobalt_lcdfb.c2
-rw-r--r--drivers/video/controlfb.c4
-rw-r--r--drivers/video/ep93xx-fb.c4
-rw-r--r--drivers/video/fb_defio.c11
-rw-r--r--drivers/video/i810/i810.h2
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c4
-rw-r--r--drivers/video/msm/mdp.c3
-rw-r--r--drivers/video/msm/msm_fb.c7
-rw-r--r--drivers/video/nuc900fb.c2
-rw-r--r--drivers/video/platinumfb.c5
-rw-r--r--drivers/video/pxa168fb.c2
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c2
-rw-r--r--drivers/video/udlfb.c1
-rw-r--r--drivers/video/vermilion/vermilion.h2
-rw-r--r--drivers/video/via/viafbdev.c4
-rw-r--r--drivers/virt/Kconfig32
-rw-r--r--drivers/virt/Makefile5
-rw-r--r--drivers/virt/fsl_hypervisor.c938
-rw-r--r--drivers/virtio/Kconfig3
-rw-r--r--drivers/w1/masters/matrox_w1.c2
-rw-r--r--drivers/w1/slaves/w1_therm.c9
-rw-r--r--drivers/w1/w1.c2
-rw-r--r--drivers/w1/w1_family.h3
-rw-r--r--drivers/watchdog/intel_scu_watchdog.c2
-rw-r--r--drivers/watchdog/sbc7240_wdt.c2
-rw-r--r--drivers/xen/Kconfig76
-rw-r--r--drivers/xen/Makefile4
-rw-r--r--drivers/xen/balloon.c139
-rw-r--r--drivers/xen/events.c7
-rw-r--r--drivers/xen/tmem.c170
-rw-r--r--drivers/xen/xen-balloon.c2
-rw-r--r--drivers/xen/xen-pciback/Makefile7
-rw-r--r--drivers/xen/xen-pciback/conf_space.c438
-rw-r--r--drivers/xen/xen-pciback/conf_space.h126
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability.c207
-rw-r--r--drivers/xen/xen-pciback/conf_space_header.c386
-rw-r--r--drivers/xen/xen-pciback/conf_space_quirks.c140
-rw-r--r--drivers/xen/xen-pciback/conf_space_quirks.h33
-rw-r--r--drivers/xen/xen-pciback/passthrough.c194
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c1376
-rw-r--r--drivers/xen/xen-pciback/pciback.h183
-rw-r--r--drivers/xen/xen-pciback/pciback_ops.c384
-rw-r--r--drivers/xen/xen-pciback/vpci.c259
-rw-r--r--drivers/xen/xen-pciback/xenbus.c749
-rw-r--r--drivers/xen/xen-selfballoon.c485
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c44
-rw-r--r--drivers/xen/xenbus/xenbus_probe.h2
-rw-r--r--drivers/xen/xenbus/xenbus_probe_backend.c9
-rw-r--r--drivers/xen/xenbus/xenbus_probe_frontend.c6
-rw-r--r--fs/9p/acl.c69
-rw-r--r--fs/9p/acl.h10
-rw-r--r--fs/9p/cache.c20
-rw-r--r--fs/9p/cache.h9
-rw-r--r--fs/9p/v9fs.c45
-rw-r--r--fs/9p/v9fs.h29
-rw-r--r--fs/9p/v9fs_vfs.h3
-rw-r--r--fs/9p/vfs_file.c22
-rw-r--r--fs/9p/vfs_inode.c124
-rw-r--r--fs/9p/vfs_inode_dotl.c84
-rw-r--r--fs/Makefile1
-rw-r--r--fs/affs/affs.h2
-rw-r--r--fs/affs/file.c8
-rw-r--r--fs/afs/afs_vl.h2
-rw-r--r--fs/afs/internal.h4
-rw-r--r--fs/afs/security.c6
-rw-r--r--fs/afs/write.c18
-rw-r--r--fs/anon_inodes.c4
-rw-r--r--fs/attr.c6
-rw-r--r--fs/bad_inode.c5
-rw-r--r--fs/binfmt_elf.c3
-rw-r--r--fs/binfmt_elf_fdpic.c3
-rw-r--r--fs/binfmt_misc.c3
-rw-r--r--fs/block_dev.c56
-rw-r--r--fs/btrfs/acl.c64
-rw-r--r--fs/btrfs/ctree.h11
-rw-r--r--fs/btrfs/delayed-inode.h2
-rw-r--r--fs/btrfs/disk-io.c15
-rw-r--r--fs/btrfs/extent_io.c2
-rw-r--r--fs/btrfs/file.c169
-rw-r--r--fs/btrfs/inode.c29
-rw-r--r--fs/btrfs/ioctl.c16
-rw-r--r--fs/cachefiles/bind.c2
-rw-r--r--fs/ceph/caps.c6
-rw-r--r--fs/ceph/debugfs.c2
-rw-r--r--fs/ceph/dir.c137
-rw-r--r--fs/ceph/export.c24
-rw-r--r--fs/ceph/file.c83
-rw-r--r--fs/ceph/inode.c54
-rw-r--r--fs/ceph/ioctl.c15
-rw-r--r--fs/ceph/ioctl.h1
-rw-r--r--fs/ceph/mds_client.c56
-rw-r--r--fs/ceph/mds_client.h3
-rw-r--r--fs/ceph/snap.c25
-rw-r--r--fs/ceph/super.c7
-rw-r--r--fs/ceph/super.h25
-rw-r--r--fs/ceph/xattr.c8
-rw-r--r--fs/cifs/cifsencrypt.c110
-rw-r--r--fs/cifs/cifsfs.c11
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/connect.c5
-rw-r--r--fs/cifs/dir.c21
-rw-r--r--fs/cifs/file.c18
-rw-r--r--fs/cifs/link.c8
-rw-r--r--fs/cifs/readdir.c429
-rw-r--r--fs/cifs/smbencrypt.c8
-rw-r--r--fs/coda/coda_int.h2
-rw-r--r--fs/coda/coda_linux.h2
-rw-r--r--fs/coda/dir.c9
-rw-r--r--fs/coda/file.c8
-rw-r--r--fs/coda/pioctl.c4
-rw-r--r--fs/compat.c246
-rw-r--r--fs/compat_ioctl.c5
-rw-r--r--fs/dcache.c273
-rw-r--r--fs/direct-io.c90
-rw-r--r--fs/dlm/ast.c265
-rw-r--r--fs/dlm/ast.h15
-rw-r--r--fs/dlm/config.c75
-rw-r--r--fs/dlm/config.h2
-rw-r--r--fs/dlm/dlm_internal.h29
-rw-r--r--fs/dlm/lock.c225
-rw-r--r--fs/dlm/lockspace.c177
-rw-r--r--fs/dlm/lowcomms.c9
-rw-r--r--fs/dlm/memory.c22
-rw-r--r--fs/dlm/memory.h2
-rw-r--r--fs/dlm/plock.c10
-rw-r--r--fs/dlm/recoverd.c12
-rw-r--r--fs/dlm/user.c12
-rw-r--r--fs/ecryptfs/file.c7
-rw-r--r--fs/ecryptfs/inode.c37
-rw-r--r--fs/ecryptfs/keystore.c2
-rw-r--r--fs/efs/namei.c7
-rw-r--r--fs/eventpoll.c2
-rw-r--r--fs/exec.c101
-rw-r--r--fs/exofs/file.c10
-rw-r--r--fs/exofs/namei.c7
-rw-r--r--fs/ext2/acl.c63
-rw-r--r--fs/ext2/acl.h4
-rw-r--r--fs/ext2/ext2.h3
-rw-r--r--fs/ext2/file.c6
-rw-r--r--fs/ext2/inode.c6
-rw-r--r--fs/ext2/namei.c18
-rw-r--r--fs/ext2/xattr.c10
-rw-r--r--fs/ext3/acl.c94
-rw-r--r--fs/ext3/acl.h4
-rw-r--r--fs/ext3/balloc.c38
-rw-r--r--fs/ext3/file.c3
-rw-r--r--fs/ext3/fsync.c27
-rw-r--r--fs/ext3/ialloc.c4
-rw-r--r--fs/ext3/inode.c201
-rw-r--r--fs/ext3/ioctl.c4
-rw-r--r--fs/ext3/namei.c25
-rw-r--r--fs/ext3/super.c15
-rw-r--r--fs/ext3/xattr.c12
-rw-r--r--fs/ext4/acl.c95
-rw-r--r--fs/ext4/acl.h4
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/ext4/file.c23
-rw-r--r--fs/ext4/fsync.c38
-rw-r--r--fs/ext4/inode.c129
-rw-r--r--fs/ext4/namei.c18
-rw-r--r--fs/fat/fat.h4
-rw-r--r--fs/fat/file.c8
-rw-r--r--fs/fat/inode.c10
-rw-r--r--fs/fat/namei_msdos.c29
-rw-r--r--fs/fat/namei_vfat.c6
-rw-r--r--fs/file_table.c2
-rw-r--r--fs/fs-writeback.c389
-rw-r--r--fs/fuse/dir.c28
-rw-r--r--fs/fuse/file.c47
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/generic_acl.c62
-rw-r--r--fs/gfs2/acl.c75
-rw-r--r--fs/gfs2/acl.h2
-rw-r--r--fs/gfs2/bmap.c14
-rw-r--r--fs/gfs2/dir.c221
-rw-r--r--fs/gfs2/dir.h1
-rw-r--r--fs/gfs2/file.c23
-rw-r--r--fs/gfs2/glock.c39
-rw-r--r--fs/gfs2/glock.h6
-rw-r--r--fs/gfs2/glops.c7
-rw-r--r--fs/gfs2/incore.h3
-rw-r--r--fs/gfs2/inode.c35
-rw-r--r--fs/gfs2/inode.h2
-rw-r--r--fs/gfs2/main.c3
-rw-r--r--fs/gfs2/ops_fstype.c1
-rw-r--r--fs/gfs2/rgrp.c52
-rw-r--r--fs/gfs2/rgrp.h4
-rw-r--r--fs/gfs2/super.c2
-rw-r--r--fs/hfs/inode.c15
-rw-r--r--fs/hfsplus/brec.c4
-rw-r--r--fs/hfsplus/catalog.c14
-rw-r--r--fs/hfsplus/dir.c8
-rw-r--r--fs/hfsplus/extents.c50
-rw-r--r--fs/hfsplus/hfsplus_fs.h21
-rw-r--r--fs/hfsplus/inode.c28
-rw-r--r--fs/hfsplus/part_tbl.c32
-rw-r--r--fs/hfsplus/super.c43
-rw-r--r--fs/hfsplus/unicode.c35
-rw-r--r--fs/hfsplus/wrapper.c92
-rw-r--r--fs/hostfs/hostfs_kern.c21
-rw-r--r--fs/hpfs/dir.c4
-rw-r--r--fs/hpfs/file.c7
-rw-r--r--fs/hpfs/hpfs_fn.h2
-rw-r--r--fs/hpfs/namei.c2
-rw-r--r--fs/hppfs/hppfs.c5
-rw-r--r--fs/hugetlbfs/inode.c3
-rw-r--r--fs/inode.c173
-rw-r--r--fs/internal.h6
-rw-r--r--fs/isofs/dir.c3
-rw-r--r--fs/isofs/inode.c1
-rw-r--r--fs/isofs/isofs.h1
-rw-r--r--fs/isofs/namei.c13
-rw-r--r--fs/isofs/rock.c3
-rw-r--r--fs/jbd/checkpoint.c37
-rw-r--r--fs/jbd/commit.c57
-rw-r--r--fs/jbd/journal.c99
-rw-r--r--fs/jbd/transaction.c83
-rw-r--r--fs/jffs2/acl.c49
-rw-r--r--fs/jffs2/acl.h6
-rw-r--r--fs/jffs2/dir.c11
-rw-r--r--fs/jffs2/file.c11
-rw-r--r--fs/jffs2/fs.c4
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/readinode.c2
-rw-r--r--fs/jffs2/symlink.c2
-rw-r--r--fs/jfs/acl.c75
-rw-r--r--fs/jfs/file.c13
-rw-r--r--fs/jfs/inode.c4
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/jfs/jfs_inode.h2
-rw-r--r--fs/jfs/namei.c51
-rw-r--r--fs/libfs.c26
-rw-r--r--fs/lockd/svclock.c8
-rw-r--r--fs/locks.c75
-rw-r--r--fs/logfs/dir.c4
-rw-r--r--fs/logfs/file.c11
-rw-r--r--fs/logfs/logfs.h2
-rw-r--r--fs/minix/inode.c3
-rw-r--r--fs/namei.c516
-rw-r--r--fs/namespace.c25
-rw-r--r--fs/ncpfs/file.c4
-rw-r--r--fs/nfs/cache_lib.c9
-rw-r--r--fs/nfs/cache_lib.h2
-rw-r--r--fs/nfs/dir.c87
-rw-r--r--fs/nfs/direct.c6
-rw-r--r--fs/nfs/file.c18
-rw-r--r--fs/nfs/idmap.c7
-rw-r--r--fs/nfs/inode.c20
-rw-r--r--fs/nfs/nfs3acl.c10
-rw-r--r--fs/nfs/nfs4_fs.h10
-rw-r--r--fs/nfs/nfs4proc.c70
-rw-r--r--fs/nfs/nfs4state.c12
-rw-r--r--fs/nfs/pagelist.c4
-rw-r--r--fs/nfs/read.c8
-rw-r--r--fs/nfs/super.c16
-rw-r--r--fs/nfs/write.c25
-rw-r--r--fs/nfsctl.c100
-rw-r--r--fs/nfsd/Kconfig12
-rw-r--r--fs/nfsd/cache.h2
-rw-r--r--fs/nfsd/export.c418
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfs4proc.c58
-rw-r--r--fs/nfsd/nfs4recover.c52
-rw-r--r--fs/nfsd/nfs4state.c265
-rw-r--r--fs/nfsd/nfs4xdr.c144
-rw-r--r--fs/nfsd/nfscache.c3
-rw-r--r--fs/nfsd/nfsctl.c343
-rw-r--r--fs/nfsd/nfssvc.c33
-rw-r--r--fs/nfsd/state.h1
-rw-r--r--fs/nfsd/xdr4.h30
-rw-r--r--fs/nilfs2/file.c12
-rw-r--r--fs/nilfs2/inode.c10
-rw-r--r--fs/nilfs2/namei.c7
-rw-r--r--fs/nilfs2/nilfs.h4
-rw-r--r--fs/notify/group.c2
-rw-r--r--fs/notify/inode_mark.c2
-rw-r--r--fs/notify/mark.c2
-rw-r--r--fs/notify/notification.c2
-rw-r--r--fs/notify/vfsmount_mark.c2
-rw-r--r--fs/ntfs/dir.c10
-rw-r--r--fs/ntfs/file.c13
-rw-r--r--fs/ntfs/inode.c10
-rw-r--r--fs/ntfs/inode.h2
-rw-r--r--fs/ocfs2/acl.c77
-rw-r--r--fs/ocfs2/acl.h2
-rw-r--r--fs/ocfs2/aops.c10
-rw-r--r--fs/ocfs2/file.c41
-rw-r--r--fs/ocfs2/file.h2
-rw-r--r--fs/ocfs2/move_extents.c1
-rw-r--r--fs/ocfs2/namei.c1
-rw-r--r--fs/ocfs2/refcounttree.c49
-rw-r--r--fs/omfs/dir.c2
-rw-r--r--fs/open.c80
-rw-r--r--fs/partitions/check.c12
-rw-r--r--fs/pipe.c4
-rw-r--r--fs/posix_acl.c50
-rw-r--r--fs/proc/array.c2
-rw-r--r--fs/proc/base.c31
-rw-r--r--fs/proc/inode.c2
-rw-r--r--fs/proc/meminfo.c2
-rw-r--r--fs/proc/proc_sysctl.c4
-rw-r--r--fs/read_write.c48
-rw-r--r--fs/reiserfs/bitmap.c8
-rw-r--r--fs/reiserfs/dir.c13
-rw-r--r--fs/reiserfs/file.c10
-rw-r--r--fs/reiserfs/inode.c13
-rw-r--r--fs/reiserfs/journal.c13
-rw-r--r--fs/reiserfs/namei.c4
-rw-r--r--fs/reiserfs/resize.c6
-rw-r--r--fs/reiserfs/super.c1
-rw-r--r--fs/reiserfs/xattr.c36
-rw-r--r--fs/reiserfs/xattr_acl.c71
-rw-r--r--fs/splice.c4
-rw-r--r--fs/squashfs/Kconfig14
-rw-r--r--fs/squashfs/Makefile3
-rw-r--r--fs/squashfs/decompressor.c6
-rw-r--r--fs/squashfs/decompressor.h4
-rw-r--r--fs/squashfs/namei.c10
-rw-r--r--fs/squashfs/squashfs.h3
-rw-r--r--fs/super.c180
-rw-r--r--fs/sync.c25
-rw-r--r--fs/sysfs/inode.c6
-rw-r--r--fs/sysfs/sysfs.h2
-rw-r--r--fs/ubifs/commit.c8
-rw-r--r--fs/ubifs/debug.c762
-rw-r--r--fs/ubifs/debug.h241
-rw-r--r--fs/ubifs/dir.c16
-rw-r--r--fs/ubifs/file.c23
-rw-r--r--fs/ubifs/io.c168
-rw-r--r--fs/ubifs/log.c6
-rw-r--r--fs/ubifs/lprops.c8
-rw-r--r--fs/ubifs/lpt.c37
-rw-r--r--fs/ubifs/lpt_commit.c40
-rw-r--r--fs/ubifs/misc.h103
-rw-r--r--fs/ubifs/orphan.c2
-rw-r--r--fs/ubifs/recovery.c43
-rw-r--r--fs/ubifs/replay.c3
-rw-r--r--fs/ubifs/sb.c6
-rw-r--r--fs/ubifs/scan.c4
-rw-r--r--fs/ubifs/super.c6
-rw-r--r--fs/ubifs/tnc.c26
-rw-r--r--fs/ubifs/tnc_commit.c145
-rw-r--r--fs/ubifs/ubifs.h23
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/ufs/namei.c2
-rw-r--r--fs/xfs/Makefile2
-rw-r--r--fs/xfs/linux-2.6/xfs_acl.c82
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c23
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c79
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h64
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c18
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c447
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h7
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c55
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c81
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h13
-rw-r--r--fs/xfs/linux-2.6/xfs_trace.h62
-rw-r--r--fs/xfs/quota/xfs_dquot.c48
-rw-r--r--fs/xfs/quota/xfs_dquot.h6
-rw-r--r--fs/xfs/quota/xfs_qm.c49
-rw-r--r--fs/xfs/quota/xfs_qm.h6
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c355
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c15
-rw-r--r--fs/xfs/xfs.h1
-rw-r--r--fs/xfs/xfs_acl.h2
-rw-r--r--fs/xfs/xfs_alloc.c14
-rw-r--r--fs/xfs/xfs_alloc_btree.c84
-rw-r--r--fs/xfs/xfs_arch.h136
-rw-r--r--fs/xfs/xfs_attr.c41
-rw-r--r--fs/xfs/xfs_attr_leaf.c60
-rw-r--r--fs/xfs/xfs_bmap.c48
-rw-r--r--fs/xfs/xfs_bmap_btree.c106
-rw-r--r--fs/xfs/xfs_btree.c29
-rw-r--r--fs/xfs/xfs_btree.h38
-rw-r--r--fs/xfs/xfs_btree_trace.c249
-rw-r--r--fs/xfs/xfs_btree_trace.h99
-rw-r--r--fs/xfs/xfs_buf_item.c75
-rw-r--r--fs/xfs/xfs_da_btree.c272
-rw-r--r--fs/xfs/xfs_da_btree.h13
-rw-r--r--fs/xfs/xfs_dir2.c156
-rw-r--r--fs/xfs/xfs_dir2.h54
-rw-r--r--fs/xfs/xfs_dir2_block.c253
-rw-r--r--fs/xfs/xfs_dir2_block.h92
-rw-r--r--fs/xfs/xfs_dir2_data.c327
-rw-r--r--fs/xfs/xfs_dir2_data.h184
-rw-r--r--fs/xfs/xfs_dir2_format.h597
-rw-r--r--fs/xfs/xfs_dir2_leaf.c417
-rw-r--r--fs/xfs/xfs_dir2_leaf.h253
-rw-r--r--fs/xfs/xfs_dir2_node.c203
-rw-r--r--fs/xfs/xfs_dir2_node.h100
-rw-r--r--fs/xfs/xfs_dir2_priv.h135
-rw-r--r--fs/xfs/xfs_dir2_sf.c338
-rw-r--r--fs/xfs/xfs_dir2_sf.h171
-rw-r--r--fs/xfs/xfs_filestream.c14
-rw-r--r--fs/xfs/xfs_fs.h5
-rw-r--r--fs/xfs/xfs_ialloc.c14
-rw-r--r--fs/xfs/xfs_ialloc_btree.c75
-rw-r--r--fs/xfs/xfs_iget.c1
-rw-r--r--fs/xfs/xfs_inode.c553
-rw-r--r--fs/xfs/xfs_inode.h27
-rw-r--r--fs/xfs/xfs_inode_item.c17
-rw-r--r--fs/xfs/xfs_inum.h11
-rw-r--r--fs/xfs/xfs_log.c64
-rw-r--r--fs/xfs/xfs_log_recover.c42
-rw-r--r--fs/xfs/xfs_mount.c73
-rw-r--r--fs/xfs/xfs_mount.h2
-rw-r--r--fs/xfs/xfs_rename.c4
-rw-r--r--fs/xfs/xfs_trans.c27
-rw-r--r--fs/xfs/xfs_trans_ail.c214
-rw-r--r--fs/xfs/xfs_trans_buf.c118
-rw-r--r--fs/xfs/xfs_trans_inode.c9
-rw-r--r--fs/xfs/xfs_trans_priv.h14
-rw-r--r--fs/xfs/xfs_vnodeops.c489
-rw-r--r--fs/xfs/xfs_vnodeops.h3
-rw-r--r--include/acpi/platform/aclinux.h2
-rw-r--r--include/acpi/video.h2
-rw-r--r--include/asm-generic/atomic.h59
-rw-r--r--include/asm-generic/bitops/ext2-atomic-setbit.h11
-rw-r--r--include/asm-generic/bitops/ext2-atomic.h4
-rw-r--r--include/asm-generic/delay.h37
-rw-r--r--include/asm-generic/io.h9
-rw-r--r--include/asm-generic/iomap.h12
-rw-r--r--include/asm-generic/local.h2
-rw-r--r--include/asm-generic/local64.h2
-rw-r--r--include/asm-generic/pci-bridge.h62
-rw-r--r--include/asm-generic/system.h2
-rw-r--r--include/crypto/if_alg.h1
-rw-r--r--include/drm/drmP.h11
-rw-r--r--include/drm/radeon_drm.h1
-rw-r--r--include/drm/ttm/ttm_bo_api.h3
-rw-r--r--include/drm/ttm/ttm_bo_driver.h6
-rw-r--r--include/drm/ttm/ttm_lock.h2
-rw-r--r--include/drm/ttm/ttm_memory.h2
-rw-r--r--include/drm/ttm/ttm_object.h4
-rw-r--r--include/drm/ttm/ttm_page_alloc.h2
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/aio.h2
-rw-r--r--include/linux/amd-iommu.h (renamed from arch/x86/include/asm/amd_iommu.h)0
-rw-r--r--include/linux/anon_inodes.h2
-rw-r--r--include/linux/arcdevice.h1
-rw-r--r--include/linux/ath9k_platform.h2
-rw-r--r--include/linux/atmdev.h2
-rw-r--r--include/linux/atomic.h54
-rw-r--r--include/linux/audit.h7
-rw-r--r--include/linux/backing-dev.h10
-rw-r--r--include/linux/bcma/bcma.h47
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h12
-rw-r--r--include/linux/bcma/bcma_driver_pci.h2
-rw-r--r--include/linux/bcma/bcma_regs.h27
-rw-r--r--include/linux/binfmts.h1
-rw-r--r--include/linux/bit_spinlock.h4
-rw-r--r--include/linux/bitmap.h1
-rw-r--r--include/linux/blkdev.h27
-rw-r--r--include/linux/buffer_head.h2
-rw-r--r--include/linux/ceph/libceph.h2
-rw-r--r--include/linux/ceph/messenger.h1
-rw-r--r--include/linux/cgroup.h1
-rw-r--r--include/linux/clocksource.h15
-rw-r--r--include/linux/cn_proc.h13
-rw-r--r--include/linux/compat.h9
-rw-r--r--include/linux/configfs.h2
-rw-r--r--include/linux/connector.h2
-rw-r--r--include/linux/cordic.h48
-rw-r--r--include/linux/cpu.h33
-rw-r--r--include/linux/cpufreq.h5
-rw-r--r--include/linux/cpumask.h14
-rw-r--r--include/linux/crc8.h101
-rw-r--r--include/linux/cred.h3
-rw-r--r--include/linux/crypto.h2
-rw-r--r--include/linux/cs5535.h60
-rw-r--r--include/linux/ctype.h9
-rw-r--r--include/linux/dcache.h10
-rw-r--r--include/linux/dcbnl.h25
-rw-r--r--include/linux/dccp.h1
-rw-r--r--include/linux/debug_locks.h2
-rw-r--r--include/linux/device.h6
-rw-r--r--include/linux/dio.h2
-rw-r--r--include/linux/dma-direction.h13
-rw-r--r--include/linux/dma-mapping.h31
-rw-r--r--include/linux/dmaengine.h4
-rw-r--r--include/linux/dw_apb_timer.h56
-rw-r--r--include/linux/edac.h2
-rw-r--r--include/linux/eeprom_93xx46.h18
-rw-r--r--include/linux/efi.h34
-rw-r--r--include/linux/elevator.h2
-rw-r--r--include/linux/etherdevice.h2
-rw-r--r--include/linux/ethtool.h35
-rw-r--r--include/linux/ext2_fs.h1
-rw-r--r--include/linux/ext3_fs.h9
-rw-r--r--include/linux/fault-inject.h21
-rw-r--r--include/linux/fb.h3
-rw-r--r--include/linux/fd.h22
-rw-r--r--include/linux/fdtable.h3
-rw-r--r--include/linux/filter.h2
-rw-r--r--include/linux/firewire-cdev.h78
-rw-r--r--include/linux/firewire.h2
-rw-r--r--include/linux/fs.h121
-rw-r--r--include/linux/fsl_hypervisor.h241
-rw-r--r--include/linux/fsnotify_backend.h2
-rw-r--r--include/linux/ftrace.h7
-rw-r--r--include/linux/ftrace_event.h5
-rw-r--r--include/linux/generic_acl.h1
-rw-r--r--include/linux/genhd.h2
-rw-r--r--include/linux/gsmmux.h11
-rw-r--r--include/linux/hardirq.h4
-rw-r--r--include/linux/hid.h3
-rw-r--r--include/linux/hugetlb.h3
-rw-r--r--include/linux/hw_breakpoint.h10
-rw-r--r--include/linux/hw_random.h2
-rw-r--r--include/linux/i2c-omap.h27
-rw-r--r--include/linux/i2c/twl.h25
-rw-r--r--include/linux/i8253.h29
-rw-r--r--include/linux/ieee80211.h55
-rw-r--r--include/linux/if_ether.h5
-rw-r--r--include/linux/if_packet.h6
-rw-r--r--include/linux/if_vlan.h91
-rw-r--r--include/linux/inet_lro.h19
-rw-r--r--include/linux/init_task.h1
-rw-r--r--include/linux/interrupt.h2
-rw-r--r--include/linux/iocontext.h14
-rw-r--r--include/linux/iommu.h2
-rw-r--r--include/linux/ioport.h30
-rw-r--r--include/linux/ipc_namespace.h7
-rw-r--r--include/linux/irq.h5
-rw-r--r--include/linux/iscsi_boot_sysfs.h16
-rw-r--r--include/linux/jbd.h1
-rw-r--r--include/linux/journal-head.h2
-rw-r--r--include/linux/jump_label.h2
-rw-r--r--include/linux/kdb.h2
-rw-r--r--include/linux/kernel.h48
-rw-r--r--include/linux/key.h2
-rw-r--r--include/linux/kgdb.h2
-rw-r--r--include/linux/kobject.h2
-rw-r--r--include/linux/kvm.h20
-rw-r--r--include/linux/kvm_host.h8
-rw-r--r--include/linux/led-lm3530.h5
-rw-r--r--include/linux/lguest.h2
-rw-r--r--include/linux/libata.h68
-rw-r--r--include/linux/memcontrol.h26
-rw-r--r--include/linux/memory_hotplug.h11
-rw-r--r--include/linux/mfd/pm8xxx/rtc.h (renamed from arch/arm/mach-msm/include/mach/clkdev.h)20
-rw-r--r--include/linux/mfd/tmio.h8
-rw-r--r--include/linux/mfd/tps65910.h2
-rw-r--r--include/linux/mfd/twl4030-audio.h (renamed from include/linux/mfd/twl4030-codec.h)16
-rw-r--r--include/linux/mfd/twl6040.h228
-rw-r--r--include/linux/mii.h2
-rw-r--r--include/linux/mlx4/cmd.h3
-rw-r--r--include/linux/mlx4/device.h62
-rw-r--r--include/linux/mlx4/qp.h8
-rw-r--r--include/linux/mm.h59
-rw-r--r--include/linux/mman.h2
-rw-r--r--include/linux/mmc/boot.h6
-rw-r--r--include/linux/mmc/card.h2
-rw-r--r--include/linux/mmc/core.h9
-rw-r--r--include/linux/mmc/dw_mmc.h28
-rw-r--r--include/linux/mmc/host.h26
-rw-r--r--include/linux/mmc/ioctl.h2
-rw-r--r--include/linux/mmc/mmc.h17
-rw-r--r--include/linux/mmc/pm.h2
-rw-r--r--include/linux/mmc/sd.h7
-rw-r--r--include/linux/mmc/sdhci-pltfm.h35
-rw-r--r--include/linux/mmc/sdhci-spear.h6
-rw-r--r--include/linux/mmc/sdhci.h6
-rw-r--r--include/linux/mmc/sdio.h7
-rw-r--r--include/linux/mmc/sdio_func.h7
-rw-r--r--include/linux/mmc/sdio_ids.h6
-rw-r--r--include/linux/mmc/sh_mmcif.h6
-rw-r--r--include/linux/mmc/sh_mobile_sdhi.h6
-rw-r--r--include/linux/mmc/tmio.h8
-rw-r--r--include/linux/mmzone.h8
-rw-r--r--include/linux/mnt_namespace.h1
-rw-r--r--include/linux/module.h24
-rw-r--r--include/linux/moduleloader.h7
-rw-r--r--include/linux/mount.h2
-rw-r--r--include/linux/mtd/ubi.h14
-rw-r--r--include/linux/mutex.h4
-rw-r--r--include/linux/namei.h5
-rw-r--r--include/linux/netdevice.h93
-rw-r--r--include/linux/netfilter/ipset/ip_set.h50
-rw-r--r--include/linux/netfilter/ipset/ip_set_ahash.h154
-rw-r--r--include/linux/netfilter/ipset/ip_set_hash.h4
-rw-r--r--include/linux/netfilter/ipset/ip_set_timeout.h5
-rw-r--r--include/linux/netfilter/ipset/pfxlen.h11
-rw-r--r--include/linux/netfilter/nfnetlink.h3
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h1
-rw-r--r--include/linux/netfilter/xt_set.h15
-rw-r--r--include/linux/netlink.h8
-rw-r--r--include/linux/netpoll.h2
-rw-r--r--include/linux/nfc.h126
-rw-r--r--include/linux/nfs_fs.h6
-rw-r--r--include/linux/nfs_fs_sb.h2
-rw-r--r--include/linux/nfsd/export.h2
-rw-r--r--include/linux/nl80211.h77
-rw-r--r--include/linux/nodemask.h13
-rw-r--r--include/linux/notifier.h82
-rw-r--r--include/linux/nsproxy.h1
-rw-r--r--include/linux/of.h29
-rw-r--r--include/linux/of_address.h5
-rw-r--r--include/linux/of_gpio.h42
-rw-r--r--include/linux/of_pci.h5
-rw-r--r--include/linux/of_platform.h40
-rw-r--r--include/linux/oom.h4
-rw-r--r--include/linux/opp.h8
-rw-r--r--include/linux/oprofile.h2
-rw-r--r--include/linux/page-flags.h4
-rw-r--r--include/linux/pagemap.h16
-rw-r--r--include/linux/pci.h41
-rw-r--r--include/linux/pci_ids.h14
-rw-r--r--include/linux/perf_event.h83
-rw-r--r--include/linux/phy.h2
-rw-r--r--include/linux/platform_data/fsa9480.h27
-rw-r--r--include/linux/platform_data/pxa_sdhci.h60
-rw-r--r--include/linux/platform_device.h1
-rw-r--r--include/linux/plist.h55
-rw-r--r--include/linux/pm.h10
-rw-r--r--include/linux/pm_domain.h108
-rw-r--r--include/linux/pm_runtime.h38
-rw-r--r--include/linux/pnp.h2
-rw-r--r--include/linux/poison.h6
-rw-r--r--include/linux/posix_acl.h5
-rw-r--r--include/linux/preempt.h26
-rw-r--r--include/linux/proc_fs.h2
-rw-r--r--include/linux/pti.h3
-rw-r--r--include/linux/ptrace.h104
-rw-r--r--include/linux/quota.h10
-rw-r--r--include/linux/ramoops.h2
-rw-r--r--include/linux/random.h1
-rw-r--r--include/linux/rculist.h2
-rw-r--r--include/linux/rcupdate.h12
-rw-r--r--include/linux/reboot.h5
-rw-r--r--include/linux/regmap.h82
-rw-r--r--include/linux/reiserfs_acl.h6
-rw-r--r--include/linux/reiserfs_fs.h2
-rw-r--r--include/linux/reiserfs_xattr.h2
-rw-r--r--include/linux/ring_buffer.h2
-rw-r--r--include/linux/rtmutex.h4
-rw-r--r--include/linux/rtnetlink.h5
-rw-r--r--include/linux/rwsem.h12
-rw-r--r--include/linux/sched.h55
-rw-r--r--include/linux/seccomp.h10
-rw-r--r--include/linux/security.h9
-rw-r--r--include/linux/sem.h2
-rw-r--r--include/linux/seq_file.h1
-rw-r--r--include/linux/shm.h4
-rw-r--r--include/linux/shrinker.h42
-rw-r--r--include/linux/skbuff.h75
-rw-r--r--include/linux/slab.h20
-rw-r--r--include/linux/slab_def.h52
-rw-r--r--include/linux/slob_def.h10
-rw-r--r--include/linux/slub_def.h23
-rw-r--r--include/linux/socket.h4
-rw-r--r--include/linux/sonet.h2
-rw-r--r--include/linux/spi/74x164.h2
-rw-r--r--include/linux/spi/mcp23s08.h9
-rw-r--r--include/linux/spinlock.h2
-rw-r--r--include/linux/splice.h2
-rw-r--r--include/linux/ssb/ssb.h4
-rw-r--r--include/linux/ssb/ssb_driver_chipcommon.h2
-rw-r--r--include/linux/stacktrace.h4
-rw-r--r--include/linux/stmmac.h25
-rw-r--r--include/linux/stop_machine.h16
-rw-r--r--include/linux/sunrpc/auth.h2
-rw-r--r--include/linux/sunrpc/cache.h11
-rw-r--r--include/linux/sunrpc/svc.h1
-rw-r--r--include/linux/sunrpc/timer.h2
-rw-r--r--include/linux/suspend.h16
-rw-r--r--include/linux/swap.h19
-rw-r--r--include/linux/sysfs.h2
-rw-r--r--include/linux/tc_ematch/tc_em_meta.h2
-rw-r--r--include/linux/tcp.h1
-rw-r--r--include/linux/tracehook.h385
-rw-r--r--include/linux/tty.h37
-rw-r--r--include/linux/usb/composite.h32
-rw-r--r--include/linux/usb/gadget.h88
-rw-r--r--include/linux/usb/m66592.h2
-rw-r--r--include/linux/usb/r8a66597.h8
-rw-r--r--include/linux/usb/renesas_usbhs.h17
-rw-r--r--include/linux/virtio_net.h1
-rw-r--r--include/linux/vmstat.h2
-rw-r--r--include/linux/vt.h7
-rw-r--r--include/linux/vt_kern.h2
-rw-r--r--include/linux/workqueue.h20
-rw-r--r--include/linux/writeback.h55
-rw-r--r--include/linux/zorro.h2
-rw-r--r--include/net/9p/9p.h193
-rw-r--r--include/net/9p/client.h12
-rw-r--r--include/net/9p/transport.h2
-rw-r--r--include/net/act_api.h6
-rw-r--r--include/net/arp.h31
-rw-r--r--include/net/ax25.h2
-rw-r--r--include/net/bluetooth/bluetooth.h27
-rw-r--r--include/net/bluetooth/hci.h77
-rw-r--r--include/net/bluetooth/hci_core.h96
-rw-r--r--include/net/bluetooth/l2cap.h140
-rw-r--r--include/net/bluetooth/mgmt.h12
-rw-r--r--include/net/bluetooth/rfcomm.h9
-rw-r--r--include/net/bluetooth/smp.h47
-rw-r--r--include/net/caif/caif_hsi.h145
-rw-r--r--include/net/cfg80211.h71
-rw-r--r--include/net/cipso_ipv4.h2
-rw-r--r--include/net/dcbnl.h11
-rw-r--r--include/net/dst.h41
-rw-r--r--include/net/dst_ops.h1
-rw-r--r--include/net/flow.h2
-rw-r--r--include/net/genetlink.h32
-rw-r--r--include/net/inet_hashtables.h2
-rw-r--r--include/net/inet_timewait_sock.h2
-rw-r--r--include/net/inetpeer.h41
-rw-r--r--include/net/ip.h10
-rw-r--r--include/net/ip6_fib.h1
-rw-r--r--include/net/ip_vs.h36
-rw-r--r--include/net/ipv6.h12
-rw-r--r--include/net/lib80211.h2
-rw-r--r--include/net/llc.h2
-rw-r--r--include/net/mac80211.h321
-rw-r--r--include/net/neighbour.h36
-rw-r--r--include/net/net_namespace.h3
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netlabel.h2
-rw-r--r--include/net/netlink.h24
-rw-r--r--include/net/netns/conntrack.h2
-rw-r--r--include/net/nfc.h156
-rw-r--r--include/net/pkt_sched.h4
-rw-r--r--include/net/rtnetlink.h7
-rw-r--r--include/net/sch_generic.h12
-rw-r--r--include/net/sctp/sctp.h15
-rw-r--r--include/net/sctp/structs.h19
-rw-r--r--include/net/sctp/user.h1
-rw-r--r--include/net/snmp.h86
-rw-r--r--include/net/sock.h5
-rw-r--r--include/net/tcp.h11
-rw-r--r--include/net/wimax.h1
-rw-r--r--include/pcmcia/ds.h2
-rw-r--r--include/rdma/ib_pma.h156
-rw-r--r--include/rdma/ib_sa.h2
-rw-r--r--include/rdma/ib_verbs.h5
-rw-r--r--include/rxrpc/types.h2
-rw-r--r--include/scsi/iscsi_proto.h18
-rw-r--r--include/scsi/libfc.h8
-rw-r--r--include/scsi/libiscsi.h2
-rw-r--r--include/scsi/osd_initiator.h2
-rw-r--r--include/scsi/scsi.h2
-rw-r--r--include/scsi/scsi_device.h2
-rw-r--r--include/sound/rawmidi.h4
-rw-r--r--include/sound/soc-dai.h4
-rw-r--r--include/sound/soc-dapm.h7
-rw-r--r--include/sound/soc.h59
-rw-r--r--include/sound/soundfont.h2
-rw-r--r--include/target/target_core_base.h228
-rw-r--r--include/target/target_core_device.h6
-rw-r--r--include/target/target_core_fabric_ops.h9
-rw-r--r--include/target/target_core_transport.h43
-rw-r--r--include/trace/events/asoc.h45
-rw-r--r--include/trace/events/btrfs.h6
-rw-r--r--include/trace/events/ext3.h864
-rw-r--r--include/trace/events/ext4.h6
-rw-r--r--include/trace/events/jbd.h203
-rw-r--r--include/trace/events/sock.h68
-rw-r--r--include/trace/events/udp.h32
-rw-r--r--include/trace/events/vmscan.h77
-rw-r--r--include/trace/events/writeback.h183
-rw-r--r--include/trace/events/xen.h504
-rw-r--r--include/xen/balloon.h14
-rw-r--r--include/xen/events.h2
-rw-r--r--include/xen/hvc-console.h4
-rw-r--r--include/xen/interface/xen.h39
-rw-r--r--include/xen/tmem.h5
-rw-r--r--include/xen/xenbus.h2
-rw-r--r--init/Kconfig13
-rw-r--r--init/calibrate.c11
-rw-r--r--ipc/ipc_sysctl.c36
-rw-r--r--ipc/mqueue.c125
-rw-r--r--ipc/sem.c23
-rw-r--r--ipc/shm.c101
-rw-r--r--ipc/util.c16
-rw-r--r--kernel/Kconfig.preempt3
-rw-r--r--kernel/Makefile5
-rw-r--r--kernel/async.c12
-rw-r--r--kernel/audit.c31
-rw-r--r--kernel/audit_tree.c8
-rw-r--r--kernel/auditsc.c2
-rw-r--r--kernel/cgroup.c13
-rw-r--r--kernel/compat.c1
-rw-r--r--kernel/configs.c4
-rw-r--r--kernel/cpuset.c10
-rw-r--r--kernel/debug/debug_core.c2
-rw-r--r--kernel/delayacct.c2
-rw-r--r--kernel/events/Makefile2
-rw-r--r--kernel/events/core.c938
-rw-r--r--kernel/events/hw_breakpoint.c10
-rw-r--r--kernel/events/internal.h96
-rw-r--r--kernel/events/ring_buffer.c380
-rw-r--r--kernel/exit.c94
-rw-r--r--kernel/fork.c124
-rw-r--r--kernel/futex.c6
-rw-r--r--kernel/gcov/Kconfig2
-rw-r--r--kernel/irq/devres.c2
-rw-r--r--kernel/kexec.c2
-rw-r--r--kernel/kprobes.c33
-rw-r--r--kernel/lockdep.c33
-rw-r--r--kernel/module.c80
-rw-r--r--kernel/notifier.c31
-rw-r--r--kernel/nsproxy.c4
-rw-r--r--kernel/panic.c2
-rw-r--r--kernel/params.c18
-rw-r--r--kernel/pid.c1
-rw-r--r--kernel/pm_qos_params.c6
-rw-r--r--kernel/power/Kconfig12
-rw-r--r--kernel/power/main.c5
-rw-r--r--kernel/power/suspend.c20
-rw-r--r--kernel/printk.c24
-rw-r--r--kernel/ptrace.c197
-rw-r--r--kernel/rcupdate.c2
-rw-r--r--kernel/rcutorture.c4
-rw-r--r--kernel/rcutree_trace.c2
-rw-r--r--kernel/rtmutex.c2
-rw-r--r--kernel/rwsem.c18
-rw-r--r--kernel/sched.c214
-rw-r--r--kernel/sched_autogroup.h1
-rw-r--r--kernel/sched_fair.c72
-rw-r--r--kernel/sched_features.h4
-rw-r--r--kernel/sched_rt.c26
-rw-r--r--kernel/signal.c425
-rw-r--r--kernel/stacktrace.c12
-rw-r--r--kernel/stop_machine.c80
-rw-r--r--kernel/sys.c32
-rw-r--r--kernel/sysctl.c11
-rw-r--r--kernel/taskstats.c2
-rw-r--r--kernel/time/timekeeping.c28
-rw-r--r--kernel/trace/ftrace.c157
-rw-r--r--kernel/trace/ring_buffer.c66
-rw-r--r--kernel/trace/ring_buffer_benchmark.c2
-rw-r--r--kernel/trace/trace.c326
-rw-r--r--kernel/trace/trace.h63
-rw-r--r--kernel/trace/trace_entries.h3
-rw-r--r--kernel/trace/trace_events.c139
-rw-r--r--kernel/trace/trace_events_filter.c6
-rw-r--r--kernel/trace/trace_functions.c3
-rw-r--r--kernel/trace/trace_functions_graph.c225
-rw-r--r--kernel/trace/trace_irqsoff.c4
-rw-r--r--kernel/trace/trace_kprobe.c324
-rw-r--r--kernel/trace/trace_mmiotrace.c2
-rw-r--r--kernel/trace/trace_output.c11
-rw-r--r--kernel/trace/trace_sched_wakeup.c4
-rw-r--r--kernel/trace/trace_stack.c13
-rw-r--r--kernel/watchdog.c8
-rw-r--r--kernel/workqueue.c81
-rw-r--r--lib/Kconfig14
-rw-r--r--lib/Kconfig.debug13
-rw-r--r--lib/Makefile3
-rw-r--r--lib/atomic64.c2
-rw-r--r--lib/atomic64_test.c2
-rw-r--r--lib/bitmap.c2
-rw-r--r--lib/checksum.c13
-rw-r--r--lib/cordic.c101
-rw-r--r--lib/cpumask.c4
-rw-r--r--lib/crc32.c2
-rw-r--r--lib/crc8.c86
-rw-r--r--lib/dec_and_lock.c2
-rw-r--r--lib/devres.c2
-rw-r--r--lib/fault-inject.c144
-rw-r--r--lib/iomap.c4
-rw-r--r--lib/kstrtox.c5
-rw-r--r--lib/lcm.c1
-rw-r--r--lib/plist.c7
-rw-r--r--lib/vsprintf.c26
-rw-r--r--lib/xz/xz_private.h2
-rw-r--r--mm/Kconfig2
-rw-r--r--mm/backing-dev.c85
-rw-r--r--mm/dmapool.c2
-rw-r--r--mm/failslab.c31
-rw-r--r--mm/filemap.c23
-rw-r--r--mm/huge_memory.c6
-rw-r--r--mm/hugetlb.c41
-rw-r--r--mm/init-mm.c2
-rw-r--r--mm/kmemleak.c2
-rw-r--r--mm/madvise.c2
-rw-r--r--mm/memblock.c8
-rw-r--r--mm/memcontrol.c573
-rw-r--r--mm/memory.c125
-rw-r--r--mm/memory_hotplug.c68
-rw-r--r--mm/mempolicy.c16
-rw-r--r--mm/mmap.c34
-rw-r--r--mm/nommu.c37
-rw-r--r--mm/oom_kill.c5
-rw-r--r--mm/page-writeback.c291
-rw-r--r--mm/page_alloc.c163
-rw-r--r--mm/page_cgroup.c10
-rw-r--r--mm/pagewalk.c49
-rw-r--r--mm/rmap.c11
-rw-r--r--mm/shmem.c558
-rw-r--r--mm/slab.c17
-rw-r--r--mm/slob.c8
-rw-r--r--mm/slub.c107
-rw-r--r--mm/sparse.c2
-rw-r--r--mm/swapfile.c29
-rw-r--r--mm/thrash.c17
-rw-r--r--mm/truncate.c146
-rw-r--r--mm/vmalloc.c20
-rw-r--r--mm/vmscan.c150
-rw-r--r--net/8021q/vlan.c19
-rw-r--r--net/8021q/vlan.h31
-rw-r--r--net/8021q/vlan_core.c46
-rw-r--r--net/8021q/vlan_dev.c7
-rw-r--r--net/8021q/vlanproc.c6
-rw-r--r--net/9p/client.c155
-rw-r--r--net/9p/mod.c4
-rw-r--r--net/9p/protocol.c44
-rw-r--r--net/9p/trans_virtio.c4
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/TUNABLE50
-rw-r--r--net/appletalk/aarp.c138
-rw-r--r--net/appletalk/ddp.c380
-rw-r--r--net/atm/atm_misc.c2
-rw-r--r--net/atm/clip.c24
-rw-r--r--net/atm/common.c2
-rw-r--r--net/atm/lec.c2
-rw-r--r--net/atm/mpc.c2
-rw-r--r--net/atm/pppoatm.c1
-rw-r--r--net/atm/proc.c2
-rw-r--r--net/batman-adv/Kconfig1
-rw-r--r--net/batman-adv/aggregation.c73
-rw-r--r--net/batman-adv/aggregation.h13
-rw-r--r--net/batman-adv/bat_debugfs.c11
-rw-r--r--net/batman-adv/bat_sysfs.c102
-rw-r--r--net/batman-adv/bat_sysfs.h2
-rw-r--r--net/batman-adv/bitarray.c12
-rw-r--r--net/batman-adv/bitarray.h10
-rw-r--r--net/batman-adv/gateway_client.c268
-rw-r--r--net/batman-adv/gateway_client.h3
-rw-r--r--net/batman-adv/gateway_common.c25
-rw-r--r--net/batman-adv/hard-interface.c46
-rw-r--r--net/batman-adv/hard-interface.h20
-rw-r--r--net/batman-adv/hash.c7
-rw-r--r--net/batman-adv/hash.h6
-rw-r--r--net/batman-adv/icmp_socket.c4
-rw-r--r--net/batman-adv/main.c31
-rw-r--r--net/batman-adv/main.h85
-rw-r--r--net/batman-adv/originator.c36
-rw-r--r--net/batman-adv/originator.h18
-rw-r--r--net/batman-adv/packet.h142
-rw-r--r--net/batman-adv/ring_buffer.c4
-rw-r--r--net/batman-adv/ring_buffer.h2
-rw-r--r--net/batman-adv/routing.c376
-rw-r--r--net/batman-adv/routing.h15
-rw-r--r--net/batman-adv/send.c147
-rw-r--r--net/batman-adv/send.h14
-rw-r--r--net/batman-adv/soft-interface.c66
-rw-r--r--net/batman-adv/soft-interface.h5
-rw-r--r--net/batman-adv/translation-table.c1566
-rw-r--r--net/batman-adv/translation-table.h49
-rw-r--r--net/batman-adv/types.h74
-rw-r--r--net/batman-adv/unicast.c33
-rw-r--r--net/batman-adv/unicast.h8
-rw-r--r--net/batman-adv/vis.c104
-rw-r--r--net/bluetooth/Kconfig9
-rw-r--r--net/bluetooth/Makefile2
-rw-r--r--net/bluetooth/cmtp/capi.c3
-rw-r--r--net/bluetooth/hci_conn.c79
-rw-r--r--net/bluetooth/hci_core.c264
-rw-r--r--net/bluetooth/hci_event.c289
-rw-r--r--net/bluetooth/hci_sock.c70
-rw-r--r--net/bluetooth/l2cap_core.c1052
-rw-r--r--net/bluetooth/l2cap_sock.c442
-rw-r--r--net/bluetooth/lib.c23
-rw-r--r--net/bluetooth/mgmt.c281
-rw-r--r--net/bluetooth/rfcomm/sock.c6
-rw-r--r--net/bluetooth/sco.c4
-rw-r--r--net/bluetooth/smp.c702
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/bridge/br_if.c2
-rw-r--r--net/bridge/br_netfilter.c16
-rw-r--r--net/bridge/br_netlink.c17
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/bridge/br_private_stp.h3
-rw-r--r--net/bridge/br_stp.c31
-rw-r--r--net/bridge/br_stp_bpdu.c15
-rw-r--r--net/bridge/br_stp_if.c3
-rw-r--r--net/bridge/br_stp_timer.c1
-rw-r--r--net/bridge/netfilter/ebt_ulog.c1
-rw-r--r--net/caif/caif_dev.c1
-rw-r--r--net/caif/chnl_net.c2
-rw-r--r--net/can/af_can.c5
-rw-r--r--net/can/bcm.c1
-rw-r--r--net/ceph/crypto.c2
-rw-r--r--net/ceph/messenger.c12
-rw-r--r--net/ceph/osd_client.c6
-rw-r--r--net/core/dev.c26
-rw-r--r--net/core/dst.c17
-rw-r--r--net/core/ethtool.c313
-rw-r--r--net/core/fib_rules.c6
-rw-r--r--net/core/flow.c2
-rw-r--r--net/core/link_watch.c2
-rw-r--r--net/core/neighbour.c191
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/core/net-traces.c2
-rw-r--r--net/core/net_namespace.c1
-rw-r--r--net/core/netpoll.c13
-rw-r--r--net/core/rtnetlink.c64
-rw-r--r--net/core/skbuff.c84
-rw-r--r--net/core/sock.c11
-rw-r--r--net/core/timestamping.c2
-rw-r--r--net/dcb/dcbnl.c677
-rw-r--r--net/dccp/ccid.c4
-rw-r--r--net/dccp/ccids/ccid2.c109
-rw-r--r--net/dccp/ccids/ccid2.h25
-rw-r--r--net/dccp/input.c61
-rw-r--r--net/dccp/output.c14
-rw-r--r--net/decnet/af_decnet.c697
-rw-r--r--net/decnet/dn_dev.c78
-rw-r--r--net/decnet/dn_fib.c83
-rw-r--r--net/decnet/dn_neigh.c44
-rw-r--r--net/decnet/dn_nsp_in.c182
-rw-r--r--net/decnet/dn_route.c143
-rw-r--r--net/decnet/dn_table.c25
-rw-r--r--net/decnet/dn_timer.c2
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c18
-rw-r--r--net/decnet/sysctl_net_decnet.c17
-rw-r--r--net/dsa/mv88e6131.c8
-rw-r--r--net/econet/af_econet.c172
-rw-r--r--net/ethernet/eth.c3
-rw-r--r--net/ieee802154/af_ieee802154.c2
-rw-r--r--net/ieee802154/dgram.c2
-rw-r--r--net/ieee802154/nl-phy.c31
-rw-r--r--net/ipv4/af_inet.c52
-rw-r--r--net/ipv4/arp.c41
-rw-r--r--net/ipv4/cipso_ipv4.c2
-rw-r--r--net/ipv4/devinet.c6
-rw-r--r--net/ipv4/fib_frontend.c6
-rw-r--r--net/ipv4/fib_trie.c12
-rw-r--r--net/ipv4/gre.c22
-rw-r--r--net/ipv4/icmp.c14
-rw-r--r--net/ipv4/inet_diag.c2
-rw-r--r--net/ipv4/inet_lro.c74
-rw-r--r--net/ipv4/inetpeer.c293
-rw-r--r--net/ipv4/ip_fragment.c5
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_input.c4
-rw-r--r--net/ipv4/ip_output.c16
-rw-r--r--net/ipv4/ipconfig.c75
-rw-r--r--net/ipv4/ipmr.c5
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c26
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c210
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c2
-rw-r--r--net/ipv4/raw.c38
-rw-r--r--net/ipv4/route.c96
-rw-r--r--net/ipv4/syncookies.c1
-rw-r--r--net/ipv4/sysctl_net_ipv4.c14
-rw-r--r--net/ipv4/tcp_input.c46
-rw-r--r--net/ipv4/tcp_ipv4.c11
-rw-r--r--net/ipv4/tcp_minisocks.c6
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv6/addrconf.c55
-rw-r--r--net/ipv6/addrlabel.c9
-rw-r--r--net/ipv6/ip6_fib.c5
-rw-r--r--net/ipv6/ip6_output.c58
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/ip6mr.c3
-rw-r--r--net/ipv6/ndisc.c16
-rw-r--r--net/ipv6/raw.c145
-rw-r--r--net/ipv6/route.c85
-rw-r--r--net/ipv6/sit.c4
-rw-r--r--net/ipv6/syncookies.c1
-rw-r--r--net/ipv6/tcp_ipv6.c5
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/irda/af_irda.c4
-rw-r--r--net/irda/ircomm/ircomm_tty_attach.c2
-rw-r--r--net/irda/irda_device.c2
-rw-r--r--net/irda/iriap.c8
-rw-r--r--net/irda/irlan/irlan_client.c10
-rw-r--r--net/irda/irlan/irlan_common.c10
-rw-r--r--net/irda/irlan/irlan_eth.c2
-rw-r--r--net/irda/irlan/irlan_provider.c10
-rw-r--r--net/irda/irqueue.c4
-rw-r--r--net/irda/irttp.c18
-rw-r--r--net/iucv/iucv.c9
-rw-r--r--net/key/af_key.c20
-rw-r--r--net/l2tp/l2tp_core.c2
-rw-r--r--net/l2tp/l2tp_ip.c19
-rw-r--r--net/l2tp/l2tp_ppp.c2
-rw-r--r--net/lapb/lapb_iface.c30
-rw-r--r--net/lapb/lapb_in.c881
-rw-r--r--net/mac80211/aes_ccm.c37
-rw-r--r--net/mac80211/aes_ccm.h2
-rw-r--r--net/mac80211/aes_cmac.c10
-rw-r--r--net/mac80211/aes_cmac.h2
-rw-r--r--net/mac80211/agg-rx.c29
-rw-r--r--net/mac80211/cfg.c66
-rw-r--r--net/mac80211/debugfs_key.c13
-rw-r--r--net/mac80211/driver-ops.h59
-rw-r--r--net/mac80211/driver-trace.h144
-rw-r--r--net/mac80211/ht.c6
-rw-r--r--net/mac80211/ieee80211_i.h41
-rw-r--r--net/mac80211/iface.c7
-rw-r--r--net/mac80211/key.c173
-rw-r--r--net/mac80211/key.h32
-rw-r--r--net/mac80211/mesh_hwmp.c20
-rw-r--r--net/mac80211/mesh_pathtbl.c4
-rw-r--r--net/mac80211/mlme.c137
-rw-r--r--net/mac80211/pm.c54
-rw-r--r--net/mac80211/rc80211_minstrel.c9
-rw-r--r--net/mac80211/rc80211_minstrel.h12
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c7
-rw-r--r--net/mac80211/rx.c38
-rw-r--r--net/mac80211/scan.c45
-rw-r--r--net/mac80211/sta_info.c4
-rw-r--r--net/mac80211/sta_info.h6
-rw-r--r--net/mac80211/tkip.c115
-rw-r--r--net/mac80211/tkip.h8
-rw-r--r--net/mac80211/tx.c17
-rw-r--r--net/mac80211/util.c151
-rw-r--r--net/mac80211/wme.c3
-rw-r--r--net/mac80211/wme.h5
-rw-r--r--net/mac80211/work.c28
-rw-r--r--net/mac80211/wpa.c94
-rw-r--r--net/netfilter/ipset/Kconfig10
-rw-r--r--net/netfilter/ipset/Makefile1
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ip.c35
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c38
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_port.c31
-rw-r--r--net/netfilter/ipset/ip_set_core.c166
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c49
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c69
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c73
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c137
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c88
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c786
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c119
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c106
-rw-r--r--net/netfilter/ipset/pfxlen.c23
-rw-r--r--net/netfilter/ipvs/ip_vs_app.c14
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c78
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c28
-rw-r--r--net/netfilter/ipvs/ip_vs_est.c13
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c52
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c13
-rw-r--r--net/netfilter/nf_conntrack_netlink.c4
-rw-r--r--net/netfilter/nfnetlink.c40
-rw-r--r--net/netfilter/nfnetlink_log.c2
-rw-r--r--net/netfilter/nfnetlink_queue.c172
-rw-r--r--net/netfilter/xt_AUDIT.c5
-rw-r--r--net/netfilter/xt_CT.c11
-rw-r--r--net/netfilter/xt_HL.c64
-rw-r--r--net/netfilter/xt_RATEEST.c8
-rw-r--r--net/netfilter/xt_hl.c32
-rw-r--r--net/netfilter/xt_set.c153
-rw-r--r--net/netlabel/netlabel_cipso_v4.c2
-rw-r--r--net/netlabel/netlabel_domainhash.c3
-rw-r--r--net/netlabel/netlabel_kapi.c2
-rw-r--r--net/netlabel/netlabel_mgmt.c2
-rw-r--r--net/netlabel/netlabel_mgmt.h2
-rw-r--r--net/netlabel/netlabel_unlabeled.c15
-rw-r--r--net/netlink/af_netlink.c20
-rw-r--r--net/netlink/genetlink.c2
-rw-r--r--net/netrom/nr_route.c22
-rw-r--r--net/nfc/Kconfig16
-rw-r--r--net/nfc/Makefile7
-rw-r--r--net/nfc/af_nfc.c98
-rw-r--r--net/nfc/core.c468
-rw-r--r--net/nfc/netlink.c537
-rw-r--r--net/nfc/nfc.h117
-rw-r--r--net/nfc/rawsock.c354
-rw-r--r--net/packet/af_packet.c438
-rw-r--r--net/phonet/pn_netlink.c13
-rw-r--r--net/rds/bind.c4
-rw-r--r--net/rds/ib.h1
-rw-r--r--net/rds/ib_cm.c6
-rw-r--r--net/rds/ib_send.c4
-rw-r--r--net/rds/iw.h1
-rw-r--r--net/rds/iw_cm.c9
-rw-r--r--net/rds/iw_rdma.c9
-rw-r--r--net/rds/iw_send.c4
-rw-r--r--net/rds/page.c1
-rw-r--r--net/rds/send.c7
-rw-r--r--net/rds/tcp_stats.c2
-rw-r--r--net/rose/rose_link.c7
-rw-r--r--net/rose/rose_route.c5
-rw-r--r--net/sched/act_api.c11
-rw-r--r--net/sched/act_csum.c2
-rw-r--r--net/sched/act_gact.c3
-rw-r--r--net/sched/act_ipt.c2
-rw-r--r--net/sched/act_mirred.c2
-rw-r--r--net/sched/act_nat.c2
-rw-r--r--net/sched/act_pedit.c2
-rw-r--r--net/sched/act_police.c2
-rw-r--r--net/sched/act_simple.c3
-rw-r--r--net/sched/act_skbedit.c2
-rw-r--r--net/sched/cls_api.c12
-rw-r--r--net/sched/cls_basic.c2
-rw-r--r--net/sched/cls_cgroup.c2
-rw-r--r--net/sched/cls_flow.c6
-rw-r--r--net/sched/cls_fw.c2
-rw-r--r--net/sched/cls_route.c2
-rw-r--r--net/sched/cls_rsvp.h4
-rw-r--r--net/sched/cls_tcindex.c2
-rw-r--r--net/sched/cls_u32.c2
-rw-r--r--net/sched/em_meta.c7
-rw-r--r--net/sched/sch_api.c18
-rw-r--r--net/sched/sch_atm.c1
-rw-r--r--net/sched/sch_choke.c2
-rw-r--r--net/sched/sch_generic.c10
-rw-r--r--net/sched/sch_netem.c1
-rw-r--r--net/sched/sch_sfq.c2
-rw-r--r--net/sched/sch_teql.c4
-rw-r--r--net/sctp/associola.c6
-rw-r--r--net/sctp/bind_addr.c17
-rw-r--r--net/sctp/input.c3
-rw-r--r--net/sctp/ipv6.c2
-rw-r--r--net/sctp/outqueue.c13
-rw-r--r--net/sctp/protocol.c152
-rw-r--r--net/sctp/sm_make_chunk.c55
-rw-r--r--net/sctp/sm_sideeffect.c2
-rw-r--r--net/sctp/sm_statefuns.c51
-rw-r--r--net/sctp/socket.c200
-rw-r--r--net/sctp/sysctl.c7
-rw-r--r--net/socket.c2
-rw-r--r--net/sunrpc/auth.c2
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c46
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c7
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c32
-rw-r--r--net/sunrpc/clnt.c36
-rw-r--r--net/sunrpc/rpc_pipe.c14
-rw-r--r--net/sunrpc/svc_xprt.c11
-rw-r--r--net/sunrpc/svcauth_unix.c79
-rw-r--r--net/sunrpc/svcsock.c2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c1
-rw-r--r--net/sunrpc/xprtrdma/verbs.c1
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h2
-rw-r--r--net/tipc/bcast.c6
-rw-r--r--net/tipc/bearer.c1
-rw-r--r--net/tipc/bearer.h2
-rw-r--r--net/tipc/core.h8
-rw-r--r--net/tipc/link.c6
-rw-r--r--net/tipc/msg.c6
-rw-r--r--net/tipc/msg.h34
-rw-r--r--net/tipc/name_distr.c6
-rw-r--r--net/tipc/name_table.c289
-rw-r--r--net/tipc/name_table.h14
-rw-r--r--net/tipc/port.c284
-rw-r--r--net/tipc/socket.c3
-rw-r--r--net/unix/af_unix.c38
-rw-r--r--net/wireless/core.c7
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/mlme.c15
-rw-r--r--net/wireless/nl80211.c341
-rw-r--r--net/wireless/nl80211.h4
-rw-r--r--net/wireless/scan.c11
-rw-r--r--net/wireless/util.c38
-rw-r--r--net/x25/af_x25.c471
-rw-r--r--net/x25/x25_dev.c44
-rw-r--r--net/x25/x25_in.c118
-rw-r--r--net/x25/x25_link.c87
-rw-r--r--net/x25/x25_subr.c78
-rw-r--r--net/xfrm/xfrm_policy.c9
-rw-r--r--net/xfrm/xfrm_user.c3
-rw-r--r--samples/hw_breakpoint/data_breakpoint.c4
-rw-r--r--scripts/Kbuild.include4
-rw-r--r--scripts/Makefile.lib40
-rw-r--r--scripts/Makefile.modpost2
-rw-r--r--scripts/bootgraph.pl2
-rwxr-xr-xscripts/checkpatch.pl656
-rw-r--r--scripts/docproc.c17
-rw-r--r--scripts/dtc/Makefile28
-rw-r--r--scripts/dtc/dtc-lexer.lex.c_shipped59
-rw-r--r--scripts/dtc/dtc-parser.tab.c_shipped116
-rw-r--r--scripts/dtc/dtc-parser.tab.h_shipped11
-rw-r--r--scripts/gcc-goto.sh2
-rw-r--r--scripts/genksyms/.gitignore7
-rw-r--r--scripts/genksyms/Makefile48
-rw-r--r--scripts/genksyms/genksyms.c2
-rw-r--r--scripts/genksyms/keywords.gperf3
-rw-r--r--scripts/genksyms/keywords.hash.c_shipped (renamed from scripts/genksyms/keywords.c_shipped)96
-rw-r--r--scripts/genksyms/lex.l4
-rw-r--r--scripts/genksyms/lex.lex.c_shipped (renamed from scripts/genksyms/lex.c_shipped)359
-rw-r--r--scripts/genksyms/parse.tab.c_shipped (renamed from scripts/genksyms/parse.c_shipped)198
-rw-r--r--scripts/genksyms/parse.tab.h_shipped (renamed from scripts/genksyms/parse.h_shipped)7
-rwxr-xr-xscripts/get_maintainer.pl9
-rw-r--r--scripts/headers_install.pl1
-rw-r--r--scripts/kconfig/.gitignore2
-rw-r--r--scripts/kconfig/Makefile34
-rw-r--r--scripts/kconfig/lkc.h2
-rw-r--r--scripts/kconfig/zconf.gperf2
-rw-r--r--scripts/kconfig/zconf.hash.c_shipped273
-rw-r--r--scripts/kconfig/zconf.l8
-rw-r--r--scripts/kconfig/zconf.lex.c_shipped (renamed from scripts/kconfig/lex.zconf.c_shipped)26
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped68
-rw-r--r--scripts/kconfig/zconf.y18
-rw-r--r--scripts/mkmakefile9
-rw-r--r--scripts/mod/modpost.c29
-rw-r--r--scripts/package/Makefile8
-rw-r--r--security/apparmor/domain.c2
-rw-r--r--security/apparmor/lib.c1
-rw-r--r--security/capability.c2
-rw-r--r--security/device_cgroup.c10
-rw-r--r--security/integrity/ima/ima_main.c2
-rw-r--r--security/keys/keyring.c1
-rw-r--r--security/security.c9
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/hooks.c9
-rw-r--r--security/selinux/netnode.c20
-rw-r--r--security/selinux/netport.c20
-rw-r--r--security/selinux/selinuxfs.c1
-rw-r--r--security/selinux/xfrm.c2
-rw-r--r--security/smack/smack_lsm.c5
-rw-r--r--security/tomoyo/realpath.c2
-rw-r--r--sound/aoa/soundbus/i2sbus/core.c9
-rw-r--r--sound/atmel/abdac.c2
-rw-r--r--sound/atmel/ac97c.c2
-rw-r--r--sound/core/info.c2
-rw-r--r--sound/core/rawmidi.c45
-rw-r--r--sound/drivers/pcsp/pcsp.h8
-rw-r--r--sound/firewire/speakers.c2
-rw-r--r--sound/isa/msnd/msnd.h2
-rw-r--r--sound/pci/ad1889.c4
-rw-r--r--sound/pci/ali5451/ali5451.c4
-rw-r--r--sound/pci/als300.c4
-rw-r--r--sound/pci/als4000.c2
-rw-r--r--sound/pci/asihpi/asihpi.c81
-rw-r--r--sound/pci/asihpi/hpi.h24
-rw-r--r--sound/pci/asihpi/hpi6000.c11
-rw-r--r--sound/pci/asihpi/hpi6205.c52
-rw-r--r--sound/pci/asihpi/hpi6205.h25
-rw-r--r--sound/pci/asihpi/hpi_internal.h155
-rw-r--r--sound/pci/asihpi/hpicmn.c17
-rw-r--r--sound/pci/asihpi/hpidspcd.c136
-rw-r--r--sound/pci/asihpi/hpidspcd.h72
-rw-r--r--sound/pci/asihpi/hpifunc.c86
-rw-r--r--sound/pci/asihpi/hpimsginit.c4
-rw-r--r--sound/pci/asihpi/hpimsgx.c6
-rw-r--r--sound/pci/asihpi/hpioctl.c10
-rw-r--r--sound/pci/asihpi/hpios.c8
-rw-r--r--sound/pci/asihpi/hpios.h1
-rw-r--r--sound/pci/atiixp.c4
-rw-r--r--sound/pci/atiixp_modem.c4
-rw-r--r--sound/pci/au88x0/au88x0.c4
-rw-r--r--sound/pci/aw2/aw2-alsa.c4
-rw-r--r--sound/pci/azt3328.c4
-rw-r--r--sound/pci/bt87x.c4
-rw-r--r--sound/pci/ca0106/ca0106_main.c4
-rw-r--r--sound/pci/cmipci.c4
-rw-r--r--sound/pci/cs4281.c4
-rw-r--r--sound/pci/cs46xx/cs46xx.c2
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c2
-rw-r--r--sound/pci/cs5530.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c4
-rw-r--r--sound/pci/ctxfi/ct20k2reg.h1
-rw-r--r--sound/pci/ctxfi/ctatc.c107
-rw-r--r--sound/pci/ctxfi/ctatc.h8
-rw-r--r--sound/pci/ctxfi/ctdaio.c23
-rw-r--r--sound/pci/ctxfi/ctdaio.h1
-rw-r--r--sound/pci/ctxfi/cthardware.h14
-rw-r--r--sound/pci/ctxfi/cthw20k1.c15
-rw-r--r--sound/pci/ctxfi/cthw20k2.c337
-rw-r--r--sound/pci/ctxfi/ctmixer.c145
-rw-r--r--sound/pci/ctxfi/xfi.c6
-rw-r--r--sound/pci/echoaudio/darla20.c2
-rw-r--r--sound/pci/echoaudio/darla24.c2
-rw-r--r--sound/pci/echoaudio/echo3g.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c6
-rw-r--r--sound/pci/echoaudio/gina20.c2
-rw-r--r--sound/pci/echoaudio/gina24.c2
-rw-r--r--sound/pci/echoaudio/indigo.c2
-rw-r--r--sound/pci/echoaudio/indigodj.c2
-rw-r--r--sound/pci/echoaudio/indigodjx.c2
-rw-r--r--sound/pci/echoaudio/indigoio.c2
-rw-r--r--sound/pci/echoaudio/indigoiox.c2
-rw-r--r--sound/pci/echoaudio/layla20.c2
-rw-r--r--sound/pci/echoaudio/layla24.c2
-rw-r--r--sound/pci/echoaudio/mia.c2
-rw-r--r--sound/pci/echoaudio/mona.c2
-rw-r--r--sound/pci/emu10k1/emu10k1.c2
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c2
-rw-r--r--sound/pci/emu10k1/emu10k1x.c4
-rw-r--r--sound/pci/ens1370.c4
-rw-r--r--sound/pci/es1938.c6
-rw-r--r--sound/pci/es1968.c68
-rw-r--r--sound/pci/fm801.c4
-rw-r--r--sound/pci/hda/Kconfig39
-rw-r--r--sound/pci/hda/Makefile4
-rw-r--r--sound/pci/hda/alc260_quirks.c1272
-rw-r--r--sound/pci/hda/alc262_quirks.c1353
-rw-r--r--sound/pci/hda/alc268_quirks.c636
-rw-r--r--sound/pci/hda/alc269_quirks.c681
-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.c1898
-rw-r--r--sound/pci/hda/alc882_quirks.c3755
-rw-r--r--sound/pci/hda/alc_quirks.c467
-rw-r--r--sound/pci/hda/hda_codec.c363
-rw-r--r--sound/pci/hda/hda_codec.h30
-rw-r--r--sound/pci/hda/hda_eld.c46
-rw-r--r--sound/pci/hda/hda_intel.c80
-rw-r--r--sound/pci/hda/hda_local.h10
-rw-r--r--sound/pci/hda/hda_proc.c2
-rw-r--r--sound/pci/hda/patch_analog.c7
-rw-r--r--sound/pci/hda/patch_ca0110.c3
-rw-r--r--sound/pci/hda/patch_ca0132.c1097
-rw-r--r--sound/pci/hda/patch_cirrus.c19
-rw-r--r--sound/pci/hda/patch_cmedia.c17
-rw-r--r--sound/pci/hda/patch_conexant.c71
-rw-r--r--sound/pci/hda/patch_hdmi.c704
-rw-r--r--sound/pci/hda/patch_realtek.c18190
-rw-r--r--sound/pci/hda/patch_sigmatel.c31
-rw-r--r--sound/pci/hda/patch_via.c6095
-rw-r--r--sound/pci/ice1712/ice1712.c6
-rw-r--r--sound/pci/ice1712/ice1724.c4
-rw-r--r--sound/pci/intel8x0.c12
-rw-r--r--sound/pci/intel8x0m.c6
-rw-r--r--sound/pci/korg1212/korg1212.c4
-rw-r--r--sound/pci/lola/lola.c4
-rw-r--r--sound/pci/lola/lola.h2
-rw-r--r--sound/pci/lola/lola_mixer.c130
-rw-r--r--sound/pci/lx6464es/lx6464es.c25
-rw-r--r--sound/pci/lx6464es/lx6464es.h4
-rw-r--r--sound/pci/lx6464es/lx_core.c14
-rw-r--r--sound/pci/lx6464es/lx_core.h2
-rw-r--r--sound/pci/maestro3.c75
-rw-r--r--sound/pci/mixart/mixart.c4
-rw-r--r--sound/pci/nm256/nm256.c4
-rw-r--r--sound/pci/oxygen/oxygen.c2
-rw-r--r--sound/pci/oxygen/oxygen_lib.c2
-rw-r--r--sound/pci/oxygen/oxygen_pcm.c6
-rw-r--r--sound/pci/oxygen/virtuoso.c2
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c5
-rw-r--r--sound/pci/pcxhr/pcxhr.c4
-rw-r--r--sound/pci/riptide/riptide.c6
-rw-r--r--sound/pci/rme32.c4
-rw-r--r--sound/pci/rme96.c4
-rw-r--r--sound/pci/rme9652/hdsp.c4
-rw-r--r--sound/pci/rme9652/hdspm.c4
-rw-r--r--sound/pci/rme9652/rme9652.c4
-rw-r--r--sound/pci/sis7019.c6
-rw-r--r--sound/pci/sonicvibes.c4
-rw-r--r--sound/pci/trident/trident.c2
-rw-r--r--sound/pci/trident/trident_main.c2
-rw-r--r--sound/pci/via82xx.c4
-rw-r--r--sound/pci/via82xx_modem.c4
-rw-r--r--sound/pci/vx222/vx222.c4
-rw-r--r--sound/pci/ymfpci/ymfpci.c2
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c2
-rw-r--r--sound/pcmcia/vx/vxpocket.c2
-rw-r--r--sound/ppc/pmac.c9
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/atmel/atmel-pcm.c8
-rw-r--r--sound/soc/atmel/atmel-pcm.h2
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c6
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c1
-rw-r--r--sound/soc/au1x/dbdma2.c7
-rw-r--r--sound/soc/blackfin/Kconfig27
-rw-r--r--sound/soc/blackfin/Makefile4
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c6
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c12
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c6
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1701.c139
-rw-r--r--sound/soc/blackfin/bfin-eval-adav80x.c173
-rw-r--r--sound/soc/codecs/Kconfig25
-rw-r--r--sound/soc/codecs/Makefile10
-rw-r--r--sound/soc/codecs/ad1836.c313
-rw-r--r--sound/soc/codecs/ad1836.h44
-rw-r--r--sound/soc/codecs/adau1701.c549
-rw-r--r--sound/soc/codecs/adau1701.h17
-rw-r--r--sound/soc/codecs/adav80x.c951
-rw-r--r--sound/soc/codecs/adav80x.h35
-rw-r--r--sound/soc/codecs/ak4641.c2
-rw-r--r--sound/soc/codecs/cs4270.c5
-rw-r--r--sound/soc/codecs/max98088.c2
-rw-r--r--sound/soc/codecs/max98095.c10
-rw-r--r--sound/soc/codecs/sta32x.c917
-rw-r--r--sound/soc/codecs/sta32x.h210
-rw-r--r--sound/soc/codecs/tlv320aic3x.c34
-rw-r--r--sound/soc/codecs/twl4030.c22
-rw-r--r--sound/soc/codecs/twl6040.c737
-rw-r--r--sound/soc/codecs/twl6040.h119
-rw-r--r--sound/soc/codecs/wm8782.c80
-rw-r--r--sound/soc/codecs/wm8900.c1
-rw-r--r--sound/soc/codecs/wm8904.c1
-rw-r--r--sound/soc/codecs/wm8915.c156
-rw-r--r--sound/soc/codecs/wm8940.c7
-rw-r--r--sound/soc/codecs/wm8962.c132
-rw-r--r--sound/soc/codecs/wm8983.c1203
-rw-r--r--sound/soc/codecs/wm8983.h1029
-rw-r--r--sound/soc/codecs/wm8993.c3
-rw-r--r--sound/soc/codecs/wm8994.c148
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/codecs/wm9081.c2
-rw-r--r--sound/soc/codecs/wm_hubs.c54
-rw-r--r--sound/soc/codecs/wm_hubs.h10
-rw-r--r--sound/soc/davinci/davinci-pcm.c154
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c4
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c8
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c147
-rw-r--r--sound/soc/ep93xx/snappercl15.c4
-rw-r--r--sound/soc/fsl/fsl_dma.c8
-rw-r--r--sound/soc/fsl/fsl_ssi.c9
-rw-r--r--sound/soc/fsl/mpc5200_dma.c9
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c10
-rw-r--r--sound/soc/fsl/p1022_ds.c10
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c4
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c8
-rw-r--r--sound/soc/imx/imx-ssi.c7
-rw-r--r--sound/soc/imx/imx-ssi.h3
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c6
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c6
-rw-r--r--sound/soc/mid-x86/sst_platform.c5
-rw-r--r--sound/soc/nuc900/nuc900-ac97.c2
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c7
-rw-r--r--sound/soc/omap/Kconfig11
-rw-r--r--sound/soc/omap/Makefile4
-rw-r--r--sound/soc/omap/ams-delta.c5
-rw-r--r--sound/soc/omap/omap-hdmi.c158
-rw-r--r--sound/soc/omap/omap-hdmi.h36
-rw-r--r--sound/soc/omap/omap-pcm.c6
-rw-r--r--sound/soc/omap/omap4-hdmi-card.c129
-rw-r--r--sound/soc/omap/sdp3430.c2
-rw-r--r--sound/soc/omap/sdp4430.c52
-rw-r--r--sound/soc/omap/zoom2.c2
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c5
-rw-r--r--sound/soc/s6000/s6000-pcm.c7
-rw-r--r--sound/soc/samsung/Kconfig16
-rw-r--r--sound/soc/samsung/Makefile4
-rw-r--r--sound/soc/samsung/dma.c6
-rw-r--r--sound/soc/samsung/i2s-regs.h143
-rw-r--r--sound/soc/samsung/i2s.c104
-rw-r--r--sound/soc/samsung/smdk_wm8994.c5
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c176
-rw-r--r--sound/soc/samsung/speyside.c61
-rw-r--r--sound/soc/samsung/speyside_wm8962.c264
-rw-r--r--sound/soc/sh/dma-sh7760.c6
-rw-r--r--sound/soc/sh/fsi.c582
-rw-r--r--sound/soc/sh/siu_pcm.c5
-rw-r--r--sound/soc/soc-cache.c692
-rw-r--r--sound/soc/soc-core.c821
-rw-r--r--sound/soc/soc-dapm.c275
-rw-r--r--sound/soc/soc-io.c396
-rw-r--r--sound/soc/soc-pcm.c639
-rw-r--r--sound/soc/tegra/Kconfig9
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra_i2s.c4
-rw-r--r--sound/soc/tegra/tegra_pcm.c6
-rw-r--r--sound/soc/tegra/tegra_spdif.c371
-rw-r--r--sound/soc/tegra/tegra_spdif.h473
-rw-r--r--sound/soc/tegra/tegra_wm8903.c2
-rw-r--r--sound/soc/txx9/txx9aclc.c5
-rw-r--r--sound/sparc/dbri.c2
-rw-r--r--sound/usb/card.c16
-rw-r--r--sound/usb/endpoint.c2
-rw-r--r--sound/usb/misc/ua101.c2
-rw-r--r--sound/usb/quirks-table.h30
-rw-r--r--sound/usb/quirks.c159
-rw-r--r--tools/perf/Documentation/perf-annotate.txt6
-rw-r--r--tools/perf/Documentation/perf-probe.txt6
-rw-r--r--tools/perf/Documentation/perf-report.txt21
-rw-r--r--tools/perf/Documentation/perf-script.txt18
-rw-r--r--tools/perf/Makefile7
-rw-r--r--tools/perf/builtin-annotate.c15
-rw-r--r--tools/perf/builtin-probe.c3
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-report.c57
-rw-r--r--tools/perf/builtin-script.c121
-rw-r--r--tools/perf/builtin-stat.c20
-rw-r--r--tools/perf/builtin-test.c249
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/util/callchain.h6
-rw-r--r--tools/perf/util/dwarf-aux.c663
-rw-r--r--tools/perf/util/dwarf-aux.h100
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/header.c5
-rw-r--r--tools/perf/util/hist.c6
-rw-r--r--tools/perf/util/parse-events.c39
-rw-r--r--tools/perf/util/parse-events.h6
-rw-r--r--tools/perf/util/probe-event.c165
-rw-r--r--tools/perf/util/probe-event.h1
-rw-r--r--tools/perf/util/probe-finder.c752
-rw-r--r--tools/perf/util/probe-finder.h43
-rw-r--r--tools/perf/util/python.c17
-rw-r--r--tools/perf/util/session.c132
-rw-r--r--tools/perf/util/session.h9
-rw-r--r--tools/perf/util/sort.c223
-rw-r--r--tools/perf/util/sort.h14
-rw-r--r--tools/perf/util/string.c19
-rw-r--r--tools/perf/util/trace-event-info.c120
-rw-r--r--tools/perf/util/util.h1
-rwxr-xr-xtools/testing/ktest/ktest.pl970
-rw-r--r--tools/testing/ktest/sample.conf142
-rw-r--r--virt/kvm/assigned-dev.c2
-rw-r--r--virt/kvm/iommu.c18
-rw-r--r--virt/kvm/kvm_main.c110
6544 files changed, 338792 insertions, 334727 deletions
diff --git a/.gitignore b/.gitignore
index 9dacde0a4b2d..57af07cf7e68 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,11 @@ modules.builtin
/Module.symvers
#
+# Debian directory (make deb-pkg)
+#
+/debian/
+
+#
# git files that we don't want to ignore even it they are dot-files
#
!.gitignore
diff --git a/.mailmap b/.mailmap
index 353ad5607156..a4806f0de852 100644
--- a/.mailmap
+++ b/.mailmap
@@ -73,8 +73,7 @@ Linas Vepstas <linas@austin.ibm.com>
Mark Brown <broonie@sirena.org.uk>
Matthieu CASTET <castet.matthieu@free.fr>
Mayuresh Janorkar <mayur@ti.com>
-Michael Buesch <mb@bu3sch.de>
-Michael Buesch <mbuesch@freenet.de>
+Michael Buesch <m@bues.ch>
Michel Dänzer <michel@tungstengraphics.com>
Mitesh shah <mshah@teja.com>
Morten Welinder <terra@gnome.org>
diff --git a/Documentation/ABI/obsolete/proc-pid-oom_adj b/Documentation/ABI/obsolete/proc-pid-oom_adj
index cf63f264ce0f..9a3cb88ade47 100644
--- a/Documentation/ABI/obsolete/proc-pid-oom_adj
+++ b/Documentation/ABI/obsolete/proc-pid-oom_adj
@@ -14,7 +14,7 @@ Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's
A much more powerful interface, /proc/<pid>/oom_score_adj, was
introduced with the oom killer rewrite that allows users to increase or
- decrease the badness() score linearly. This interface will replace
+ decrease the badness score linearly. This interface will replace
/proc/<pid>/oom_adj.
A warning will be emitted to the kernel log if an application uses this
diff --git a/Documentation/ABI/stable/firewire-cdev b/Documentation/ABI/stable/firewire-cdev
new file mode 100644
index 000000000000..16d030827368
--- /dev/null
+++ b/Documentation/ABI/stable/firewire-cdev
@@ -0,0 +1,103 @@
+What: /dev/fw[0-9]+
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ The character device files /dev/fw* are the interface between
+ firewire-core and IEEE 1394 device drivers implemented in
+ userspace. The ioctl(2)- and read(2)-based ABI is defined and
+ documented in <linux/firewire-cdev.h>.
+
+ This ABI offers most of the features which firewire-core also
+ exposes to kernelspace IEEE 1394 drivers.
+
+ Each /dev/fw* is associated with one IEEE 1394 node, which can
+ be remote or local nodes. Operations on a /dev/fw* file have
+ different scope:
+ - The 1394 node which is associated with the file:
+ - Asynchronous request transmission
+ - Get the Configuration ROM
+ - Query node ID
+ - Query maximum speed of the path between this node
+ and local node
+ - The 1394 bus (i.e. "card") to which the node is attached to:
+ - Isochronous stream transmission and reception
+ - Asynchronous stream transmission and reception
+ - Asynchronous broadcast request transmission
+ - PHY packet transmission and reception
+ - Allocate, reallocate, deallocate isochronous
+ resources (channels, bandwidth) at the bus's IRM
+ - Query node IDs of local node, root node, IRM, bus
+ manager
+ - Query cycle time
+ - Bus reset initiation, bus reset event reception
+ - All 1394 buses:
+ - Allocation of IEEE 1212 address ranges on the local
+ link layers, reception of inbound requests to such
+ an address range, asynchronous response transmission
+ to inbound requests
+ - Addition of descriptors or directories to the local
+ nodes' Configuration ROM
+
+ Due to the different scope of operations and in order to let
+ userland implement different access permission models, some
+ operations are restricted to /dev/fw* files that are associated
+ with a local node:
+ - Addition of descriptors or directories to the local
+ nodes' Configuration ROM
+ - PHY packet transmission and reception
+
+ A /dev/fw* file remains associated with one particular node
+ during its entire life time. Bus topology changes, and hence
+ node ID changes, are tracked by firewire-core. ABI users do not
+ need to be aware of topology.
+
+ The following file operations are supported:
+
+ open(2)
+ Currently the only useful flags are O_RDWR.
+
+ ioctl(2)
+ Initiate various actions. Some take immediate effect, others
+ are performed asynchronously while or after the ioctl returns.
+ See the inline documentation in <linux/firewire-cdev.h> for
+ descriptions of all ioctls.
+
+ poll(2), select(2), epoll_wait(2) etc.
+ Watch for events to become available to be read.
+
+ read(2)
+ Receive various events. There are solicited events like
+ outbound asynchronous transaction completion or isochronous
+ buffer completion, and unsolicited events such as bus resets,
+ request reception, or PHY packet reception. Always use a read
+ buffer which is large enough to receive the largest event that
+ could ever arrive. See <linux/firewire-cdev.h> for descriptions
+ of all event types and for which ioctls affect reception of
+ events.
+
+ mmap(2)
+ Allocate a DMA buffer for isochronous reception or transmission
+ and map it into the process address space. The arguments should
+ be used as follows: addr = NULL, length = the desired buffer
+ size, i.e. number of packets times size of largest packet,
+ prot = at least PROT_READ for reception and at least PROT_WRITE
+ for transmission, flags = MAP_SHARED, fd = the handle to the
+ /dev/fw*, offset = 0.
+
+ Isochronous reception works in packet-per-buffer fashion except
+ for multichannel reception which works in buffer-fill mode.
+
+ munmap(2)
+ Unmap the isochronous I/O buffer from the process address space.
+
+ close(2)
+ Besides stopping and freeing I/O contexts that were associated
+ with the file descriptor, back out any changes to the local
+ nodes' Configuration ROM. Deallocate isochronous channels and
+ bandwidth at the IRM that were marked for kernel-assisted
+ re- and deallocation.
+
+Users: libraw1394
+ libdc1394
+ tools like jujuutils, fwhack, ...
diff --git a/Documentation/ABI/stable/sysfs-bus-firewire b/Documentation/ABI/stable/sysfs-bus-firewire
new file mode 100644
index 000000000000..3d484e5dc846
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-bus-firewire
@@ -0,0 +1,122 @@
+What: /sys/bus/firewire/devices/fw[0-9]+/
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ IEEE 1394 node device attributes.
+ Read-only. Mutable during the node device's lifetime.
+ See IEEE 1212 for semantic definitions.
+
+ config_rom
+ Contents of the Configuration ROM register.
+ Binary attribute; an array of host-endian u32.
+
+ guid
+ The node's EUI-64 in the bus information block of
+ Configuration ROM.
+ Hexadecimal string representation of an u64.
+
+
+What: /sys/bus/firewire/devices/fw[0-9]+/units
+Date: June 2009
+KernelVersion: 2.6.31
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ IEEE 1394 node device attribute.
+ Read-only. Mutable during the node device's lifetime.
+ See IEEE 1212 for semantic definitions.
+
+ units
+ Summary of all units present in an IEEE 1394 node.
+ Contains space-separated tuples of specifier_id and
+ version of each unit present in the node. Specifier_id
+ and version are hexadecimal string representations of
+ u24 of the respective unit directory entries.
+ Specifier_id and version within each tuple are separated
+ by a colon.
+
+Users: udev rules to set ownership and access permissions or ACLs of
+ /dev/fw[0-9]+ character device files
+
+
+What: /sys/bus/firewire/devices/fw[0-9]+[.][0-9]+/
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ IEEE 1394 unit device attributes.
+ Read-only. Immutable during the unit device's lifetime.
+ See IEEE 1212 for semantic definitions.
+
+ modalias
+ Same as MODALIAS in the uevent at device creation.
+
+ rom_index
+ Offset of the unit directory within the parent device's
+ (node device's) Configuration ROM, in quadlets.
+ Decimal string representation.
+
+
+What: /sys/bus/firewire/devices/*/
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ Attributes common to IEEE 1394 node devices and unit devices.
+ Read-only. Mutable during the node device's lifetime.
+ Immutable during the unit device's lifetime.
+ See IEEE 1212 for semantic definitions.
+
+ These attributes are only created if the root directory of an
+ IEEE 1394 node or the unit directory of an IEEE 1394 unit
+ actually contains according entries.
+
+ hardware_version
+ Hexadecimal string representation of an u24.
+
+ hardware_version_name
+ Contents of a respective textual descriptor leaf.
+
+ model
+ Hexadecimal string representation of an u24.
+
+ model_name
+ Contents of a respective textual descriptor leaf.
+
+ specifier_id
+ Hexadecimal string representation of an u24.
+ Mandatory in unit directories according to IEEE 1212.
+
+ vendor
+ Hexadecimal string representation of an u24.
+ Mandatory in the root directory according to IEEE 1212.
+
+ vendor_name
+ Contents of a respective textual descriptor leaf.
+
+ version
+ Hexadecimal string representation of an u24.
+ Mandatory in unit directories according to IEEE 1212.
+
+
+What: /sys/bus/firewire/drivers/sbp2/fw*/host*/target*/*:*:*:*/ieee1394_id
+ formerly
+ /sys/bus/ieee1394/drivers/sbp2/fw*/host*/target*/*:*:*:*/ieee1394_id
+Date: Feb 2004
+KernelVersion: 2.6.4
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ SCSI target port identifier and logical unit identifier of a
+ logical unit of an SBP-2 target. The identifiers are specified
+ in SAM-2...SAM-4 annex A. They are persistent and world-wide
+ unique properties the SBP-2 attached target.
+
+ Read-only attribute, immutable during the target's lifetime.
+ Format, as exposed by firewire-sbp2 since 2.6.22, May 2007:
+ Colon-separated hexadecimal string representations of
+ u64 EUI-64 : u24 directory_ID : u16 LUN
+ without 0x prefixes, without whitespace. The former sbp2 driver
+ (removed in 2.6.37 after being superseded by firewire-sbp2) used
+ a somewhat shorter format which was not as close to SAM.
+
+Users: udev rules to create /dev/disk/by-id/ symlinks
diff --git a/Documentation/ABI/stable/vdso b/Documentation/ABI/stable/vdso
new file mode 100644
index 000000000000..8a1cbb594497
--- /dev/null
+++ b/Documentation/ABI/stable/vdso
@@ -0,0 +1,27 @@
+On some architectures, when the kernel loads any userspace program it
+maps an ELF DSO into that program's address space. This DSO is called
+the vDSO and it often contains useful and highly-optimized alternatives
+to real syscalls.
+
+These functions are called just like ordinary C function according to
+your platform's ABI. Call them from a sensible context. (For example,
+if you set CS on x86 to something strange, the vDSO functions are
+within their rights to crash.) In addition, if you pass a bad
+pointer to a vDSO function, you might get SIGSEGV instead of -EFAULT.
+
+To find the DSO, parse the auxiliary vector passed to the program's
+entry point. The AT_SYSINFO_EHDR entry will point to the vDSO.
+
+The vDSO uses symbol versioning; whenever you request a symbol from the
+vDSO, specify the version you are expecting.
+
+Programs that dynamically link to glibc will use the vDSO automatically.
+Otherwise, you can use the reference parser in Documentation/vDSO/parse_vdso.c.
+
+Unless otherwise noted, the set of symbols with any given version and the
+ABI of those symbols is considered stable. It may vary across architectures,
+though.
+
+(As of this writing, this ABI documentation as been confirmed for x86_64.
+ The maintainers of the other vDSO-using architectures should confirm
+ that it is correct for their architecture.) \ No newline at end of file
diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480 b/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480
new file mode 100644
index 000000000000..9de269bb0ae5
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480
@@ -0,0 +1,21 @@
+What: /sys/bus/i2c/devices/.../device
+Date: February 2011
+Contact: Minkyu Kang <mk7.kang@samsung.com>
+Description:
+ show what device is attached
+ NONE - no device
+ USB - USB device is attached
+ UART - UART is attached
+ CHARGER - Charger is attaced
+ JIG - JIG is attached
+
+What: /sys/bus/i2c/devices/.../switch
+Date: February 2011
+Contact: Minkyu Kang <mk7.kang@samsung.com>
+Description:
+ show or set the state of manual switch
+ VAUDIO - switch to VAUDIO path
+ UART - switch to UART path
+ AUDIO - switch to AUDIO path
+ DHOST - switch to DHOST path
+ AUTO - switch automatically by device
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
index c1b53b8bc2ae..65e6e5dd67e8 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
@@ -92,6 +92,14 @@ Description: The mouse has a tracking- and a distance-control-unit. These
This file is writeonly.
Users: http://roccat.sourceforge.net
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/talk
+Date: May 2011
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: Used to active some easy* functions of the mouse from outside.
+ The data has to be 16 bytes long.
+ This file is writeonly.
+Users: http://roccat.sourceforge.net
+
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
Date: October 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-wiimote b/Documentation/ABI/testing/sysfs-driver-hid-wiimote
new file mode 100644
index 000000000000..5d5a16ea57c6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-wiimote
@@ -0,0 +1,10 @@
+What: /sys/bus/hid/drivers/wiimote/<dev>/led1
+What: /sys/bus/hid/drivers/wiimote/<dev>/led2
+What: /sys/bus/hid/drivers/wiimote/<dev>/led3
+What: /sys/bus/hid/drivers/wiimote/<dev>/led4
+Date: July 2011
+KernelVersion: 3.1
+Contact: David Herrmann <dh.herrmann@googlemail.com>
+Description: Make it possible to set/get current led state. Reading from it
+ returns 0 if led is off and 1 if it is on. Writing 0 to it
+ disables the led, writing 1 enables it.
diff --git a/Documentation/ABI/testing/sysfs-module b/Documentation/ABI/testing/sysfs-module
index cfcec3bffc0a..9489ea8e294c 100644
--- a/Documentation/ABI/testing/sysfs-module
+++ b/Documentation/ABI/testing/sysfs-module
@@ -10,3 +10,26 @@ KernelVersion: 2.6.35
Contact: masa-korg@dsn.okisemi.com
Description: Write/read Option ROM data.
+
+What: /sys/module/ehci_hcd/drivers/.../uframe_periodic_max
+Date: July 2011
+KernelVersion: 3.1
+Contact: Kirill Smelkov <kirr@mns.spb.ru>
+Description: Maximum time allowed for periodic transfers per microframe (μs)
+
+ [ USB 2.0 sets maximum allowed time for periodic transfers per
+ microframe to be 80%, that is 100 microseconds out of 125
+ microseconds (full microframe).
+
+ However there are cases, when 80% max isochronous bandwidth is
+ too limiting. For example two video streams could require 110
+ microseconds of isochronous bandwidth per microframe to work
+ together. ]
+
+ Through this setting it is possible to raise the limit so that
+ the host controller would allow allocating more than 100
+ microseconds of periodic bandwidth per microframe.
+
+ Beware, non-standard modes are usually not thoroughly tested by
+ hardware designers, and the hardware can malfunction when this
+ setting differ from default 100.
diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
index d568bc235bc0..a0b6250add79 100644
--- a/Documentation/DMA-API-HOWTO.txt
+++ b/Documentation/DMA-API-HOWTO.txt
@@ -613,13 +613,13 @@ to use the dma_sync_*() interfaces.
pass_to_upper_layers(cp->rx_buf);
make_and_setup_new_rx_buf(cp);
} else {
- /* Just sync the buffer and give it back
- * to the card.
+ /* CPU should not write to
+ * DMA_FROM_DEVICE-mapped area,
+ * so dma_sync_single_for_device() is
+ * not needed here. It would be required
+ * for DMA_BIDIRECTIONAL mapping if
+ * the memory was modified.
*/
- dma_sync_single_for_device(&cp->dev,
- cp->rx_dma,
- cp->rx_len,
- DMA_FROM_DEVICE);
give_rx_buf_to_card(cp);
}
}
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 8906648f962b..445289cd0e65 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -402,8 +402,9 @@
!Finclude/net/mac80211.h set_key_cmd
!Finclude/net/mac80211.h ieee80211_key_conf
!Finclude/net/mac80211.h ieee80211_key_flags
-!Finclude/net/mac80211.h ieee80211_tkip_key_type
-!Finclude/net/mac80211.h ieee80211_get_tkip_key
+!Finclude/net/mac80211.h ieee80211_get_tkip_p1k
+!Finclude/net/mac80211.h ieee80211_get_tkip_p1k_iv
+!Finclude/net/mac80211.h ieee80211_get_tkip_p2k
!Finclude/net/mac80211.h ieee80211_key_removed
</chapter>
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 7b3f49363413..07a9c48de5a2 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -409,7 +409,7 @@ cond_resched(); /* Will sleep */
<para>
You should always compile your kernel
- <symbol>CONFIG_DEBUG_SPINLOCK_SLEEP</symbol> on, and it will warn
+ <symbol>CONFIG_DEBUG_ATOMIC_SLEEP</symbol> on, and it will warn
you if you break these rules. If you <emphasis>do</emphasis> break
the rules, you will eventually lock up your box.
</para>
diff --git a/Documentation/DocBook/v4l/io.xml b/Documentation/DocBook/v4l/io.xml
index 227e7ac45a06..c57d1ec6291c 100644
--- a/Documentation/DocBook/v4l/io.xml
+++ b/Documentation/DocBook/v4l/io.xml
@@ -210,7 +210,7 @@ for (i = 0; i &lt; reqbuf.count; i++)
<programlisting>
&v4l2-requestbuffers; reqbuf;
/* Our current format uses 3 planes per buffer */
-#define FMT_NUM_PLANES = 3;
+#define FMT_NUM_PLANES = 3
struct {
void *start[FMT_NUM_PLANES];
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
index 58ced2346e67..598c22f3b3ac 100644
--- a/Documentation/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -1164,7 +1164,7 @@
}
chip->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_mychip_interrupt,
- IRQF_SHARED, "My Chip", chip)) {
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1197,7 +1197,7 @@
/* pci_driver definition */
static struct pci_driver driver = {
- .name = "My Own Chip",
+ .name = KBUILD_MODNAME,
.id_table = snd_mychip_ids,
.probe = snd_mychip_probe,
.remove = __devexit_p(snd_mychip_remove),
@@ -1340,7 +1340,7 @@
<programlisting>
<![CDATA[
if (request_irq(pci->irq, snd_mychip_interrupt,
- IRQF_SHARED, "My Chip", chip)) {
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1616,7 +1616,7 @@
<programlisting>
<![CDATA[
static struct pci_driver driver = {
- .name = "My Own Chip",
+ .name = KBUILD_MODNAME,
.id_table = snd_mychip_ids,
.probe = snd_mychip_probe,
.remove = __devexit_p(snd_mychip_remove),
@@ -5816,7 +5816,7 @@ struct _snd_pcm_runtime {
<programlisting>
<![CDATA[
static struct pci_driver driver = {
- .name = "My Chip",
+ .name = KBUILD_MODNAME,
.id_table = snd_my_ids,
.probe = snd_my_probe,
.remove = __devexit_p(snd_my_remove),
diff --git a/Documentation/RCU/NMI-RCU.txt b/Documentation/RCU/NMI-RCU.txt
index a8536cb88091..bf82851a0e57 100644
--- a/Documentation/RCU/NMI-RCU.txt
+++ b/Documentation/RCU/NMI-RCU.txt
@@ -5,8 +5,8 @@ Although RCU is usually used to protect read-mostly data structures,
it is possible to use RCU to provide dynamic non-maskable interrupt
handlers, as well as dynamic irq handlers. This document describes
how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer
-work in "arch/i386/oprofile/nmi_timer_int.c" and in
-"arch/i386/kernel/traps.c".
+work in "arch/x86/oprofile/nmi_timer_int.c" and in
+"arch/x86/kernel/traps.c".
The relevant pieces of code are listed below, each followed by a
brief explanation.
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index da0382daa395..dc0e33210d7e 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -53,8 +53,8 @@ kernel patches.
12: Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
- CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP all simultaneously
- enabled.
+ CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_PROVE_RCU
+ and CONFIG_DEBUG_OBJECTS_RCU_HEAD all simultaneously enabled.
13: Has been build- and runtime tested with and without CONFIG_SMP and
CONFIG_PREEMPT.
diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting
index 4e686a2ed91e..a341d87d276e 100644
--- a/Documentation/arm/Booting
+++ b/Documentation/arm/Booting
@@ -164,3 +164,8 @@ In either case, the following conditions must be met:
- The boot loader is expected to call the kernel image by jumping
directly to the first instruction of the kernel image.
+ On CPUs supporting the ARM instruction set, the entry must be
+ made in ARM state, even for a Thumb-2 kernel.
+
+ On CPUs supporting only the Thumb instruction set such as
+ Cortex-M class CPUs, the entry must be made in Thumb state.
diff --git a/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt b/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt
new file mode 100644
index 000000000000..441959846e1a
--- /dev/null
+++ b/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt
@@ -0,0 +1,42 @@
+ROM-able zImage boot from eSD
+-----------------------------
+
+An ROM-able zImage compiled with ZBOOT_ROM_SDHI may be written to eSD and
+SuperH Mobile ARM will to boot directly from the SDHI hardware block.
+
+This is achieved by the mask ROM loading the first portion of the image into
+MERAM and then jumping to it. This portion contains loader code which
+copies the entire image to SDRAM and jumps to it. From there the zImage
+boot code proceeds as normal, uncompressing the image into its final
+location and then jumping to it.
+
+This code has been tested on an mackerel board using the developer 1A eSD
+boot mode which is configured using the following jumper settings.
+
+ 8 7 6 5 4 3 2 1
+ x|x|x|x| |x|x|
+S4 -+-+-+-+-+-+-+-
+ | | | |x| | |x on
+
+The eSD card needs to be present in SDHI slot 1 (CN7).
+As such S1 and S33 also need to be configured as per
+the notes in arch/arm/mach-shmobile/board-mackerel.c.
+
+A partial zImage must be written to physical partition #1 (boot)
+of the eSD at sector 0 in vrl4 format. A utility vrl4 is supplied to
+accomplish this.
+
+e.g.
+ vrl4 < zImage | dd of=/dev/sdX bs=512 count=17
+
+A full copy of _the same_ zImage should be written to physical partition #1
+(boot) of the eSD at sector 0. This should _not_ be in vrl4 format.
+
+ vrl4 < zImage | dd of=/dev/sdX bs=512
+
+Note: The commands above assume that the physical partition has been
+switched. No such facility currently exists in the Linux Kernel.
+
+Physical partitions are described in the eSD specification. At the time of
+writing they are not the same as partitions that are typically configured
+using fdisk and visible through /proc/partitions
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index c12bfc1a00c9..359587b2367b 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -8,10 +8,13 @@ Introduction
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
- S3C2412, S3C2413, S3C2416 S3C2440, S3C2442, S3C2443 and S3C2450 devices
+ S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443 and S3C2450 devices
are supported.
- Support for the S3C2400 and S3C24A0 series are in progress.
+ Support for the S3C2400 and S3C24A0 series was never completed and the
+ corresponding code has been removed after a while. If someone wishes to
+ revive this effort, partial support can be retrieved from earlier Linux
+ versions.
The S3C2416 and S3C2450 devices are very similar and S3C2450 support is
included under the arch/arm/mach-s3c2416 directory. Note, whilst core
diff --git a/Documentation/arm/kernel_user_helpers.txt b/Documentation/arm/kernel_user_helpers.txt
new file mode 100644
index 000000000000..a17df9f91d16
--- /dev/null
+++ b/Documentation/arm/kernel_user_helpers.txt
@@ -0,0 +1,267 @@
+Kernel-provided User Helpers
+============================
+
+These are segment of kernel provided user code reachable from user space
+at a fixed address in kernel memory. This is used to provide user space
+with some operations which require kernel help because of unimplemented
+native feature and/or instructions in many ARM CPUs. The idea is for this
+code to be executed directly in user mode for best efficiency but which is
+too intimate with the kernel counter part to be left to user libraries.
+In fact this code might even differ from one CPU to another depending on
+the available instruction set, or whether it is a SMP systems. In other
+words, the kernel reserves the right to change this code as needed without
+warning. Only the entry points and their results as documented here are
+guaranteed to be stable.
+
+This is different from (but doesn't preclude) a full blown VDSO
+implementation, however a VDSO would prevent some assembly tricks with
+constants that allows for efficient branching to those code segments. And
+since those code segments only use a few cycles before returning to user
+code, the overhead of a VDSO indirect far call would add a measurable
+overhead to such minimalistic operations.
+
+User space is expected to bypass those helpers and implement those things
+inline (either in the code emitted directly by the compiler, or part of
+the implementation of a library call) when optimizing for a recent enough
+processor that has the necessary native support, but only if resulting
+binaries are already to be incompatible with earlier ARM processors due to
+useage of similar native instructions for other things. In other words
+don't make binaries unable to run on earlier processors just for the sake
+of not using these kernel helpers if your compiled code is not going to
+use new instructions for other purpose.
+
+New helpers may be added over time, so an older kernel may be missing some
+helpers present in a newer kernel. For this reason, programs must check
+the value of __kuser_helper_version (see below) before assuming that it is
+safe to call any particular helper. This check should ideally be
+performed only once at process startup time, and execution aborted early
+if the required helpers are not provided by the kernel version that
+process is running on.
+
+kuser_helper_version
+--------------------
+
+Location: 0xffff0ffc
+
+Reference declaration:
+
+ extern int32_t __kuser_helper_version;
+
+Definition:
+
+ This field contains the number of helpers being implemented by the
+ running kernel. User space may read this to determine the availability
+ of a particular helper.
+
+Usage example:
+
+#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
+
+void check_kuser_version(void)
+{
+ if (__kuser_helper_version < 2) {
+ fprintf(stderr, "can't do atomic operations, kernel too old\n");
+ abort();
+ }
+}
+
+Notes:
+
+ User space may assume that the value of this field never changes
+ during the lifetime of any single process. This means that this
+ field can be read once during the initialisation of a library or
+ startup phase of a program.
+
+kuser_get_tls
+-------------
+
+Location: 0xffff0fe0
+
+Reference prototype:
+
+ void * __kuser_get_tls(void);
+
+Input:
+
+ lr = return address
+
+Output:
+
+ r0 = TLS value
+
+Clobbered registers:
+
+ none
+
+Definition:
+
+ Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
+
+Usage example:
+
+typedef void * (__kuser_get_tls_t)(void);
+#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
+
+void foo()
+{
+ void *tls = __kuser_get_tls();
+ printf("TLS = %p\n", tls);
+}
+
+Notes:
+
+ - Valid only if __kuser_helper_version >= 1 (from kernel version 2.6.12).
+
+kuser_cmpxchg
+-------------
+
+Location: 0xffff0fc0
+
+Reference prototype:
+
+ int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
+
+Input:
+
+ r0 = oldval
+ r1 = newval
+ r2 = ptr
+ lr = return address
+
+Output:
+
+ r0 = success code (zero or non-zero)
+ C flag = set if r0 == 0, clear if r0 != 0
+
+Clobbered registers:
+
+ r3, ip, flags
+
+Definition:
+
+ Atomically store newval in *ptr only if *ptr is equal to oldval.
+ Return zero if *ptr was changed or non-zero if no exchange happened.
+ The C flag is also set if *ptr was changed to allow for assembly
+ optimization in the calling code.
+
+Usage example:
+
+typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
+
+int atomic_add(volatile int *ptr, int val)
+{
+ int old, new;
+
+ do {
+ old = *ptr;
+ new = old + val;
+ } while(__kuser_cmpxchg(old, new, ptr));
+
+ return new;
+}
+
+Notes:
+
+ - This routine already includes memory barriers as needed.
+
+ - Valid only if __kuser_helper_version >= 2 (from kernel version 2.6.12).
+
+kuser_memory_barrier
+--------------------
+
+Location: 0xffff0fa0
+
+Reference prototype:
+
+ void __kuser_memory_barrier(void);
+
+Input:
+
+ lr = return address
+
+Output:
+
+ none
+
+Clobbered registers:
+
+ none
+
+Definition:
+
+ Apply any needed memory barrier to preserve consistency with data modified
+ manually and __kuser_cmpxchg usage.
+
+Usage example:
+
+typedef void (__kuser_dmb_t)(void);
+#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
+
+Notes:
+
+ - Valid only if __kuser_helper_version >= 3 (from kernel version 2.6.15).
+
+kuser_cmpxchg64
+---------------
+
+Location: 0xffff0f60
+
+Reference prototype:
+
+ int __kuser_cmpxchg64(const int64_t *oldval,
+ const int64_t *newval,
+ volatile int64_t *ptr);
+
+Input:
+
+ r0 = pointer to oldval
+ r1 = pointer to newval
+ r2 = pointer to target value
+ lr = return address
+
+Output:
+
+ r0 = success code (zero or non-zero)
+ C flag = set if r0 == 0, clear if r0 != 0
+
+Clobbered registers:
+
+ r3, lr, flags
+
+Definition:
+
+ Atomically store the 64-bit value pointed by *newval in *ptr only if *ptr
+ is equal to the 64-bit value pointed by *oldval. Return zero if *ptr was
+ changed or non-zero if no exchange happened.
+
+ The C flag is also set if *ptr was changed to allow for assembly
+ optimization in the calling code.
+
+Usage example:
+
+typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
+ const int64_t *newval,
+ volatile int64_t *ptr);
+#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
+
+int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
+{
+ int64_t old, new;
+
+ do {
+ old = *ptr;
+ new = old + val;
+ } while(__kuser_cmpxchg64(&old, &new, ptr));
+
+ return new;
+}
+
+Notes:
+
+ - This routine already includes memory barriers as needed.
+
+ - Due to the length of this sequence, this spans 2 conventional kuser
+ "slots", therefore 0xffff0f80 is not used as a valid entry point.
+
+ - Valid only if __kuser_helper_version >= 5 (from kernel version 3.1).
diff --git a/Documentation/blackfin/bfin-spi-notes.txt b/Documentation/blackfin/bfin-spi-notes.txt
index 556fa877f2e8..eae6eaf2a09d 100644
--- a/Documentation/blackfin/bfin-spi-notes.txt
+++ b/Documentation/blackfin/bfin-spi-notes.txt
@@ -9,6 +9,8 @@ the entire SPI transfer. - And not just bits_per_word duration.
In most cases you can utilize SPI MODE_3 instead of MODE_0 to work-around this
behavior. If your SPI slave device in question requires SPI MODE_0 or MODE_2
timing, you can utilize the GPIO controlled SPI Slave Select option instead.
+In this case, you should use GPIO based CS for all of your slaves and not just
+the ones using mode 0 or 2 in order to guarantee correct CS toggling behavior.
You can even use the same pin whose peripheral role is a SSEL,
but use it as a GPIO instead.
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt
index f65274081c8d..d8147b336c35 100644
--- a/Documentation/block/queue-sysfs.txt
+++ b/Documentation/block/queue-sysfs.txt
@@ -45,9 +45,13 @@ device.
rq_affinity (RW)
----------------
-If this option is enabled, the block layer will migrate request completions
-to the CPU that originally submitted the request. For some workloads
-this provides a significant reduction in CPU cycles due to caching effects.
+If this option is '1', the block layer will migrate request completions to the
+cpu "group" that originally submitted the request. For some workloads this
+provides a significant reduction in CPU cycles due to caching effects.
+
+For storage configurations that need to maximize distribution of completion
+processing setting this option to '2' forces the completion to run on the
+requesting cpu (bypassing the "group" aggregation logic).
scheduler (RW)
--------------
diff --git a/Documentation/blockdev/README.DAC960 b/Documentation/blockdev/README.DAC960
index 0e8f618ab534..bd85fb9dc6e5 100644
--- a/Documentation/blockdev/README.DAC960
+++ b/Documentation/blockdev/README.DAC960
@@ -214,7 +214,7 @@ replacing "/usr/src" with wherever you keep your Linux kernel source tree:
make config
make bzImage (or zImage)
-Then install "arch/i386/boot/bzImage" or "arch/i386/boot/zImage" as your
+Then install "arch/x86/boot/bzImage" or "arch/x86/boot/zImage" as your
standard kernel, run lilo if appropriate, and reboot.
To create the necessary devices in /dev, the "make_rd" script included in
diff --git a/Documentation/blockdev/ramdisk.txt b/Documentation/blockdev/ramdisk.txt
index 6c820baa19a6..fa72e97dd669 100644
--- a/Documentation/blockdev/ramdisk.txt
+++ b/Documentation/blockdev/ramdisk.txt
@@ -64,9 +64,9 @@ the RAM disk dynamically grows as data is being written into it, a size field
is not required. Bits 11 to 13 are not currently used and may as well be zero.
These numbers are no magical secrets, as seen below:
-./arch/i386/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK 0x07FF
-./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG 0x8000
-./arch/i386/kernel/setup.c:#define RAMDISK_LOAD_FLAG 0x4000
+./arch/x86/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK 0x07FF
+./arch/x86/kernel/setup.c:#define RAMDISK_PROMPT_FLAG 0x8000
+./arch/x86/kernel/setup.c:#define RAMDISK_LOAD_FLAG 0x4000
Consider a typical two floppy disk setup, where you will have the
kernel on disk one, and have already put a RAM disk image onto disk #2.
@@ -85,7 +85,7 @@ The command line equivalent is: "prompt_ramdisk=1"
Putting that together gives 2^15 + 2^14 + 0 = 49152 for an rdev word.
So to create disk one of the set, you would do:
- /usr/src/linux# cat arch/i386/boot/zImage > /dev/fd0
+ /usr/src/linux# cat arch/x86/boot/zImage > /dev/fd0
/usr/src/linux# rdev /dev/fd0 /dev/fd0
/usr/src/linux# rdev -r /dev/fd0 49152
diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt
index 9ad85df4b983..9d73cc0cadb9 100644
--- a/Documentation/cgroups/cpuacct.txt
+++ b/Documentation/cgroups/cpuacct.txt
@@ -23,7 +23,7 @@ New accounting groups can be created under the parent group /sys/fs/cgroup.
# cd /sys/fs/cgroup
# mkdir g1
-# echo $$ > g1
+# echo $$ > g1/tasks
The above steps create a new group g1 and move the current shell
process (bash) into it. CPU time consumed by this bash and its children
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
index 5b0d78e55ccc..5c51ed406d1d 100644
--- a/Documentation/cgroups/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
@@ -180,7 +180,7 @@ files describing that cpuset:
- cpuset.sched_load_balance flag: if set, load balance within CPUs on that cpuset
- cpuset.sched_relax_domain_level: the searching range when migrating tasks
-In addition, the root cpuset only has the following file:
+In addition, only the root cpuset has the following file:
- cpuset.memory_pressure_enabled flag: compute memory_pressure?
New cpusets are created using the mkdir system call or shell
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 06eb6d957c83..6f3c598971fc 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -380,7 +380,7 @@ will be charged as a new owner of it.
5.2 stat file
-memory.stat file includes following statistics
+5.2.1 memory.stat file includes following statistics
# per-memory cgroup local status
cache - # of bytes of page cache memory.
@@ -438,6 +438,89 @@ Note:
file_mapped is accounted only when the memory cgroup is owner of page
cache.)
+5.2.2 memory.vmscan_stat
+
+memory.vmscan_stat includes statistics information for memory scanning and
+freeing, reclaiming. The statistics shows memory scanning information since
+memory cgroup creation and can be reset to 0 by writing 0 as
+
+ #echo 0 > ../memory.vmscan_stat
+
+This file contains following statistics.
+
+[param]_[file_or_anon]_pages_by_[reason]_[under_heararchy]
+[param]_elapsed_ns_by_[reason]_[under_hierarchy]
+
+For example,
+
+ scanned_file_pages_by_limit indicates the number of scanned
+ file pages at vmscan.
+
+Now, 3 parameters are supported
+
+ scanned - the number of pages scanned by vmscan
+ rotated - the number of pages activated at vmscan
+ freed - the number of pages freed by vmscan
+
+If "rotated" is high against scanned/freed, the memcg seems busy.
+
+Now, 2 reason are supported
+
+ limit - the memory cgroup's limit
+ system - global memory pressure + softlimit
+ (global memory pressure not under softlimit is not handled now)
+
+When under_hierarchy is added in the tail, the number indicates the
+total memcg scan of its children and itself.
+
+elapsed_ns is a elapsed time in nanosecond. This may include sleep time
+and not indicates CPU usage. So, please take this as just showing
+latency.
+
+Here is an example.
+
+# cat /cgroup/memory/A/memory.vmscan_stat
+scanned_pages_by_limit 9471864
+scanned_anon_pages_by_limit 6640629
+scanned_file_pages_by_limit 2831235
+rotated_pages_by_limit 4243974
+rotated_anon_pages_by_limit 3971968
+rotated_file_pages_by_limit 272006
+freed_pages_by_limit 2318492
+freed_anon_pages_by_limit 962052
+freed_file_pages_by_limit 1356440
+elapsed_ns_by_limit 351386416101
+scanned_pages_by_system 0
+scanned_anon_pages_by_system 0
+scanned_file_pages_by_system 0
+rotated_pages_by_system 0
+rotated_anon_pages_by_system 0
+rotated_file_pages_by_system 0
+freed_pages_by_system 0
+freed_anon_pages_by_system 0
+freed_file_pages_by_system 0
+elapsed_ns_by_system 0
+scanned_pages_by_limit_under_hierarchy 9471864
+scanned_anon_pages_by_limit_under_hierarchy 6640629
+scanned_file_pages_by_limit_under_hierarchy 2831235
+rotated_pages_by_limit_under_hierarchy 4243974
+rotated_anon_pages_by_limit_under_hierarchy 3971968
+rotated_file_pages_by_limit_under_hierarchy 272006
+freed_pages_by_limit_under_hierarchy 2318492
+freed_anon_pages_by_limit_under_hierarchy 962052
+freed_file_pages_by_limit_under_hierarchy 1356440
+elapsed_ns_by_limit_under_hierarchy 351386416101
+scanned_pages_by_system_under_hierarchy 0
+scanned_anon_pages_by_system_under_hierarchy 0
+scanned_file_pages_by_system_under_hierarchy 0
+rotated_pages_by_system_under_hierarchy 0
+rotated_anon_pages_by_system_under_hierarchy 0
+rotated_file_pages_by_system_under_hierarchy 0
+freed_pages_by_system_under_hierarchy 0
+freed_anon_pages_by_system_under_hierarchy 0
+freed_file_pages_by_system_under_hierarchy 0
+elapsed_ns_by_system_under_hierarchy 0
+
5.3 swappiness
Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
index 6c30e930c122..c436096351f8 100644
--- a/Documentation/cpu-freq/cpu-drivers.txt
+++ b/Documentation/cpu-freq/cpu-drivers.txt
@@ -168,7 +168,7 @@ in-chipset dynamic frequency switching to policy->min, the upper limit
to policy->max, and -if supported- select a performance-oriented
setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a
powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check
-the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c
+the reference implementation in drivers/cpufreq/longrun.c
diff --git a/Documentation/development-process/4.Coding b/Documentation/development-process/4.Coding
index f3f1a469443c..83f5f5b365a3 100644
--- a/Documentation/development-process/4.Coding
+++ b/Documentation/development-process/4.Coding
@@ -244,7 +244,7 @@ testing purposes. In particular, you should turn on:
- DEBUG_SLAB can find a variety of memory allocation and use errors; it
should be used on most development kernels.
- - DEBUG_SPINLOCK, DEBUG_SPINLOCK_SLEEP, and DEBUG_MUTEXES will find a
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, and DEBUG_MUTEXES will find a
number of common locking errors.
There are quite a few other debugging options, some of which will be
diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt
new file mode 100644
index 000000000000..1c044eb320cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/pmu.txt
@@ -0,0 +1,21 @@
+* ARM Performance Monitor Units
+
+ARM cores often have a PMU for counting cpu and cache events like cache misses
+and hits. The interface to the PMU is part of the ARM ARM. The ARM PMU
+representation in the device tree should be done as under:-
+
+Required properties:
+
+- compatible : should be one of
+ "arm,cortex-a9-pmu"
+ "arm,cortex-a8-pmu"
+ "arm,arm1176-pmu"
+ "arm,arm1136-pmu"
+- interrupts : 1 combined interrupt or 1 per core.
+
+Example:
+
+pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupts = <100 101>;
+};
diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt
new file mode 100644
index 000000000000..1d5d7a870ec7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/primecell.txt
@@ -0,0 +1,21 @@
+* ARM Primecell Peripherals
+
+ARM, Ltd. Primecell peripherals have a standard id register that can be used to
+identify the peripheral type, vendor, and revision. This value can be used for
+driver matching.
+
+Required properties:
+
+- compatible : should be a specific value for peripheral and "arm,primecell"
+
+Optional properties:
+
+- arm,primecell-periphid : Value to override the h/w value with
+
+Example:
+
+serial@fff36000 {
+ compatible = "arm,pl011", "arm,primecell";
+ arm,primecell-periphid = <0x00341011>;
+};
+
diff --git a/Documentation/devicetree/bindings/arm/sirf.txt b/Documentation/devicetree/bindings/arm/sirf.txt
new file mode 100644
index 000000000000..6b07f65b32de
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/sirf.txt
@@ -0,0 +1,3 @@
+prima2 "cb" evalutation board
+Required root node properties:
+ - compatible = "sirf,prima2-cb", "sirf,prima2";
diff --git a/Documentation/devicetree/bindings/arm/xilinx.txt b/Documentation/devicetree/bindings/arm/xilinx.txt
new file mode 100644
index 000000000000..6f1ed830b4f7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/xilinx.txt
@@ -0,0 +1,7 @@
+Xilinx Zynq EP107 Emulation Platform board
+
+This board is an emulation platform for the Zynq product which is
+based on an ARM Cortex A9 processor.
+
+Required root node properties:
+ - compatible = "xlnx,zynq-ep107";
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/sec.txt b/Documentation/devicetree/bindings/crypto/fsl-sec2.txt
index 2b6f2d45c45a..38988ef1336b 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/sec.txt
+++ b/Documentation/devicetree/bindings/crypto/fsl-sec2.txt
@@ -1,4 +1,4 @@
-Freescale SoC SEC Security Engines
+Freescale SoC SEC Security Engines versions 2.x-3.x
Required properties:
diff --git a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt
new file mode 100644
index 000000000000..4363ae4b3c14
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt
@@ -0,0 +1,22 @@
+* Freescale i.MX/MXC GPIO controller
+
+Required properties:
+- compatible : Should be "fsl,<soc>-gpio"
+- reg : Address and length of the register set for the device
+- interrupts : Should be the port interrupt shared by all 32 pins, if
+ one number. If two numbers, the first one is the interrupt shared
+ by low 16 pins and the second one is for high 16 pins.
+- gpio-controller : Marks the device node as a gpio controller.
+- #gpio-cells : Should be two. The first cell is the pin number and
+ the second cell is used to specify optional parameters (currently
+ unused).
+
+Example:
+
+gpio0: gpio@73f84000 {
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f84000 0x4000>;
+ interrupts = <50 51>;
+ gpio-controller;
+ #gpio-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index edaa84d288a1..4e16ba4feab0 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -4,17 +4,45 @@ Specifying GPIO information for devices
1) gpios property
-----------------
-Nodes that makes use of GPIOs should define them using `gpios' property,
-format of which is: <&gpio-controller1-phandle gpio1-specifier
- &gpio-controller2-phandle gpio2-specifier
- 0 /* holes are permitted, means no GPIO 3 */
- &gpio-controller4-phandle gpio4-specifier
- ...>;
+Nodes that makes use of GPIOs should specify them using one or more
+properties, each containing a 'gpio-list':
-Note that gpio-specifier length is controller dependent.
+ gpio-list ::= <single-gpio> [gpio-list]
+ single-gpio ::= <gpio-phandle> <gpio-specifier>
+ gpio-phandle : phandle to gpio controller node
+ gpio-specifier : Array of #gpio-cells specifying specific gpio
+ (controller specific)
+
+GPIO properties should be named "[<name>-]gpios". Exact
+meaning of each gpios property must be documented in the device tree
+binding for each device.
+
+For example, the following could be used to describe gpios pins to use
+as chip select lines; with chip selects 0, 1 and 3 populated, and chip
+select 2 left empty:
+
+ gpio1: gpio1 {
+ gpio-controller
+ #gpio-cells = <2>;
+ };
+ gpio2: gpio2 {
+ gpio-controller
+ #gpio-cells = <1>;
+ };
+ [...]
+ chipsel-gpios = <&gpio1 12 0>,
+ <&gpio1 13 0>,
+ <0>, /* holes are permitted, means no GPIO 2 */
+ <&gpio2 2>;
+
+Note that gpio-specifier length is controller dependent. In the
+above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
+only uses one.
gpio-specifier may encode: bank, pin position inside the bank,
whether pin is open-drain and whether pin is logically inverted.
+Exact meaning of each specifier cell is controller specific, and must
+be documented in the device tree binding for the device.
Example of the node using GPIOs:
@@ -28,8 +56,8 @@ and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
2) gpio-controller nodes
------------------------
-Every GPIO controller node must have #gpio-cells property defined,
-this information will be used to translate gpio-specifiers.
+Every GPIO controller node must both an empty "gpio-controller"
+property, and have #gpio-cells contain the size of the gpio-specifier.
Example of two SOC GPIO banks defined as gpio-controller nodes:
diff --git a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt
new file mode 100644
index 000000000000..eb4b530d64e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt
@@ -0,0 +1,8 @@
+NVIDIA Tegra 2 GPIO controller
+
+Required properties:
+- compatible : "nvidia,tegra20-gpio"
+- #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.
diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
index 1a729f089866..1a729f089866 100755..100644
--- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
+++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
diff --git a/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt b/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt
new file mode 100644
index 000000000000..a2891ceb6344
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt
@@ -0,0 +1,5 @@
+OLPC XO-1 RTC
+~~~~~~~~~~~~~
+
+Required properties:
+ - compatible : "olpc,xo1-rtc"
diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
new file mode 100644
index 000000000000..9841057d112b
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
@@ -0,0 +1,22 @@
+* Freescale (Enhanced) Configurable Serial Peripheral Interface
+ (CSPI/eCSPI) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<soc>-cspi" or "fsl,<soc>-ecspi"
+- reg : Offset and length of the register set for the device
+- interrupts : Should contain CSPI/eCSPI interrupt
+- fsl,spi-num-chipselects : Contains the number of the chipselect
+- cs-gpios : Specifies the gpio pins to be used for chipselects.
+
+Example:
+
+ecspi@70010000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-ecspi";
+ reg = <0x70010000 0x4000>;
+ interrupts = <36>;
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
+ <&gpio3 25 0>; /* GPIO4_25 */
+};
diff --git a/Documentation/devicetree/bindings/spi/spi_nvidia.txt b/Documentation/devicetree/bindings/spi/spi_nvidia.txt
new file mode 100644
index 000000000000..6b9e51896693
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi_nvidia.txt
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 SPI device
+
+Required properties:
+- compatible : should be "nvidia,tegra20-spi".
+- gpios : should specify GPIOs used for chipselect.
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
new file mode 100644
index 000000000000..b8b27b0aca10
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -0,0 +1,36 @@
+* UART (Universal Asynchronous Receiver/Transmitter)
+
+Required properties:
+- compatible : one of:
+ - "ns8250"
+ - "ns16450"
+ - "ns16550a"
+ - "ns16550"
+ - "ns16750"
+ - "ns16850"
+ - "nvidia,tegra20-uart"
+ - "ibm,qpace-nwp-serial"
+ - "serial" if the port type is unknown.
+- 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:
+- current-speed : the current active speed of the UART.
+- reg-offset : offset to apply to the mapbase from the start of the registers.
+- reg-shift : quantity to shift the register offsets by.
+- reg-io-width : the size (in bytes) of the IO accesses that should be
+ performed on the device. There are some systems that require 32-bit
+ accesses to the UART (e.g. TI davinci).
+- used-by-rtas : set to indicate that the port is in use by the OpenFirmware
+ RTAS and should not be registered.
+
+Example:
+
+ uart@80230000 {
+ compatible = "ns8250";
+ reg = <0x80230000 0x100>;
+ clock-frequency = <3686400>;
+ interrupts = <10>;
+ reg-shift = <2>;
+ };
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
index b2ff42685bcb..bdefe728a737 100644
--- a/Documentation/driver-model/device.txt
+++ b/Documentation/driver-model/device.txt
@@ -104,4 +104,4 @@ Then in the module init function is would do:
And assuming 'dev' is the struct device passed into the probe hook, the driver
probe function would do something like:
- create_device(&mydriver_class, dev, chrdev, &private_data, "my_name");
+ device_create(&mydriver_class, dev, chrdev, &private_data, "my_name");
diff --git a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt
index 07236ed968da..6a8f9a8075d8 100644
--- a/Documentation/driver-model/overview.txt
+++ b/Documentation/driver-model/overview.txt
@@ -30,7 +30,7 @@ management, and hot plug. In particular, the model dictated by Intel and
Microsoft (namely ACPI) ensures that almost every device on almost any bus
on an x86-compatible system can work within this paradigm. Of course,
not every bus is able to support all such operations, although most
-buses support a most of those operations.
+buses support most of those operations.
Downstream Access
@@ -46,25 +46,29 @@ struct pci_dev now looks like this:
struct pci_dev {
...
- struct device dev;
+ struct device dev; /* Generic device interface */
+ ...
};
-Note first that it is statically allocated. This means only one allocation on
-device discovery. Note also that it is at the _end_ of struct pci_dev. This is
-to make people think about what they're doing when switching between the bus
-driver and the global driver; and to prevent against mindless casts between
-the two.
+Note first that the struct device dev within the struct pci_dev is
+statically allocated. This means only one allocation on device discovery.
+
+Note also that that struct device dev is not necessarily defined at the
+front of the pci_dev structure. This is to make people think about what
+they're doing when switching between the bus driver and the global driver,
+and to discourage meaningless and incorrect casts between the two.
The PCI bus layer freely accesses the fields of struct device. It knows about
the structure of struct pci_dev, and it should know the structure of struct
device. Individual PCI device drivers that have been converted to the current
driver model generally do not and should not touch the fields of struct device,
-unless there is a strong compelling reason to do so.
+unless there is a compelling reason to do so.
-This abstraction is prevention of unnecessary pain during transitional phases.
-If the name of the field changes or is removed, then every downstream driver
-will break. On the other hand, if only the bus layer (and not the device
-layer) accesses struct device, it is only that layer that needs to change.
+The above abstraction prevents unnecessary pain during transitional phases.
+If it were not done this way, then when a field was renamed or removed, every
+downstream driver would break. On the other hand, if only the bus layer
+(and not the device layer) accesses the struct device, it is only the bus
+layer that needs to change.
User Interface
@@ -73,15 +77,27 @@ User Interface
By virtue of having a complete hierarchical view of all the devices in the
system, exporting a complete hierarchical view to userspace becomes relatively
easy. This has been accomplished by implementing a special purpose virtual
-file system named sysfs. It is hence possible for the user to mount the
-whole sysfs filesystem anywhere in userspace.
+file system named sysfs.
+
+Almost all mainstream Linux distros mount this filesystem automatically; you
+can see some variation of the following in the output of the "mount" command:
+
+$ mount
+...
+none on /sys type sysfs (rw,noexec,nosuid,nodev)
+...
+$
+
+The auto-mounting of sysfs is typically accomplished by an entry similar to
+the following in the /etc/fstab file:
+
+none /sys sysfs defaults 0 0
-This can be done permanently by providing the following entry into the
-/etc/fstab (under the provision that the mount point does exist, of course):
+or something similar in the /lib/init/fstab file on Debian-based systems:
-none /sys sysfs defaults 0 0
+none /sys sysfs nodev,noexec,nosuid 0 0
-Or by hand on the command line:
+If sysfs is not automatically mounted, you can always do it manually with:
# mount -t sysfs sysfs /sys
diff --git a/Documentation/fb/modedb.txt b/Documentation/fb/modedb.txt
index ec4dee75a354..16aa08453911 100644
--- a/Documentation/fb/modedb.txt
+++ b/Documentation/fb/modedb.txt
@@ -20,7 +20,7 @@ in a video= option, fbmem considers that to be a global video mode option.
Valid mode specifiers (mode_option argument):
- <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
+ <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
<name>[-<bpp>][@<refresh>]
with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
@@ -36,6 +36,21 @@ pixels and 1.8% of yres).
Sample usage: 1024x768M@60m - CVT timing with margins
+DRM drivers also add options to enable or disable outputs:
+
+'e' will force the display to be enabled, i.e. it will override the detection
+if a display is connected. 'D' will force the display to be enabled and use
+digital output. This is useful for outputs that have both analog and digital
+signals (e.g. HDMI and DVI-I). For other outputs it behaves like 'e'. If 'd'
+is specified the output is disabled.
+
+You can additionally specify which output the options matches to.
+To force the VGA output to be enabled and drive a specific mode say:
+ video=VGA-1:1280x1024@60me
+
+Specifying the option multiple times for different ports is possible, e.g.:
+ video=LVDS-1:d video=HDMI-1:D
+
***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
What is the VESA(TM) Coordinated Video Timings (CVT)?
@@ -132,5 +147,5 @@ There may be more modes.
tridentfb - Trident (Cyber)blade chipset frame buffer
vt8623fb - VIA 8623 frame buffer
-BTW, only a few drivers use this at the moment. Others are to follow
-(feel free to send patches).
+BTW, only a few fb drivers use this at the moment. Others are to follow
+(feel free to send patches). The DRM drivers also support this.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index b1c921c27519..dfd6a9f4a583 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -184,7 +184,7 @@ Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's
A much more powerful interface, /proc/<pid>/oom_score_adj, was
introduced with the oom killer rewrite that allows users to increase or
- decrease the badness() score linearly. This interface will replace
+ decrease the badness score linearly. This interface will replace
/proc/<pid>/oom_adj.
A warning will be emitted to the kernel log if an application uses this
@@ -193,20 +193,6 @@ Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's
---------------------------
-What: CS5535/CS5536 obsolete GPIO driver
-When: June 2011
-Files: drivers/staging/cs5535_gpio/*
-Check: drivers/staging/cs5535_gpio/cs5535_gpio.c
-Why: A newer driver replaces this; it is drivers/gpio/cs5535-gpio.c, and
- integrates with the Linux GPIO subsystem. The old driver has been
- moved to staging, and will be removed altogether around 2.6.40.
- Please test the new driver, and ensure that the functionality you
- need and any bugfixes from the old driver are available in the new
- one.
-Who: Andres Salomon <dilinger@queued.net>
-
---------------------------
-
What: remove EXPORT_SYMBOL(kernel_thread)
When: August 2006
Files: arch/*/kernel/*_ksyms.c
@@ -294,7 +280,7 @@ When: The schedule was July 2008, but it was decided that we are going to keep t
Why: The support code for the old firmware hurts code readability/maintainability
and slightly hurts runtime performance. Bugfixes for the old firmware
are not provided by Broadcom anymore.
-Who: Michael Buesch <mb@bu3sch.de>
+Who: Michael Buesch <m@bues.ch>
---------------------------
@@ -430,7 +416,7 @@ Who: Avi Kivity <avi@redhat.com>
----------------------------
What: iwlwifi 50XX module parameters
-When: 2.6.40
+When: 3.0
Why: The "..50" modules parameters were used to configure 5000 series and
up devices; different set of module parameters also available for 4965
with same functionalities. Consolidate both set into single place
@@ -441,7 +427,7 @@ Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
----------------------------
What: iwl4965 alias support
-When: 2.6.40
+When: 3.0
Why: Internal alias support has been present in module-init-tools for some
time, the MODULE_ALIAS("iwl4965") boilerplate aliases can be removed
with no impact.
@@ -474,15 +460,8 @@ Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
----------------------------
-What: DMA_xxBIT_MASK macros
-When: Jun 2011
-Why: DMA_xxBIT_MASK macros were replaced with DMA_BIT_MASK() macros.
-Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-
-----------------------------
-
What: iwlwifi disable_hw_scan module parameters
-When: 2.6.40
+When: 3.0
Why: Hareware scan is the prefer method for iwlwifi devices for
scanning operation. Remove software scan support for all the
iwlwifi devices.
@@ -491,26 +470,6 @@ Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
----------------------------
-What: access to nfsd auth cache through sys_nfsservctl or '.' files
- in the 'nfsd' filesystem.
-When: 2.6.40
-Why: This is a legacy interface which have been replaced by a more
- dynamic cache. Continuing to maintain this interface is an
- unnecessary burden.
-Who: NeilBrown <neilb@suse.de>
-
-----------------------------
-
-What: cancel_rearming_delayed_work[queue]()
-When: 2.6.39
-
-Why: The functions have been superceded by cancel_delayed_work_sync()
- quite some time ago. The conversion is trivial and there is no
- in-kernel user left.
-Who: Tejun Heo <tj@kernel.org>
-
-----------------------------
-
What: Legacy, non-standard chassis intrusion detection interface.
When: June 2011
Why: The adm9240, w83792d and w83793 hardware monitoring drivers have
@@ -528,22 +487,6 @@ Files: net/netfilter/xt_connlimit.c
----------------------------
-What: noswapaccount kernel command line parameter
-When: 2.6.40
-Why: The original implementation of memsw feature enabled by
- CONFIG_CGROUP_MEM_RES_CTLR_SWAP could be disabled by the noswapaccount
- kernel parameter (introduced in 2.6.29-rc1). Later on, this decision
- turned out to be not ideal because we cannot have the feature compiled
- in and disabled by default and let only interested to enable it
- (e.g. general distribution kernels might need it). Therefore we have
- added swapaccount[=0|1] parameter (introduced in 2.6.37) which provides
- the both possibilities. If we remove noswapaccount we will have
- less command line parameters with the same functionality and we
- can also cleanup the parameter handling a bit ().
-Who: Michal Hocko <mhocko@suse.cz>
-
-----------------------------
-
What: ipt_addrtype match include file
When: 2012
Why: superseded by xt_addrtype
@@ -562,7 +505,7 @@ Who: Jean Delvare <khali@linux-fr.org>
----------------------------
What: Support for UVCIOC_CTRL_ADD in the uvcvideo driver
-When: 2.6.42
+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>
@@ -570,7 +513,7 @@ Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----------------------------
What: Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
-When: 2.6.42
+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>
@@ -578,7 +521,7 @@ Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----------------------------
What: Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
-When: 2.6.42
+When: 3.2
Why: Superseded by the UVCIOC_CTRL_QUERY ioctl.
Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -605,3 +548,10 @@ Why: Just opening a V4L device should not change the state of the hardware
Who: Hans Verkuil <hans.verkuil@cisco.com>
----------------------------
+
+What: g_file_storage driver
+When: 3.8
+Why: This driver has been superseded by g_mass_storage.
+Who: Alan Stern <stern@rowland.harvard.edu>
+
+----------------------------
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 57d827d6071d..653380793a6c 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -52,7 +52,7 @@ ata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, unsigned int);
- int (*check_acl)(struct inode *, int, unsigned int);
+ int (*get_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -80,7 +80,7 @@ put_link: no
truncate: yes (see below)
setattr: yes
permission: no (may not block if called in rcu-walk mode)
-check_acl: no
+get_acl: no
getattr: no
setxattr: yes
getxattr: no
@@ -338,21 +338,21 @@ fl_release_private: maybe no
----------------------- lock_manager_operations ---------------------------
prototypes:
- int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
- void (*fl_notify)(struct file_lock *); /* unblock callback */
- int (*fl_grant)(struct file_lock *, struct file_lock *, int);
- void (*fl_release_private)(struct file_lock *);
- void (*fl_break)(struct file_lock *); /* break_lease callback */
- int (*fl_change)(struct file_lock **, int);
+ int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
+ void (*lm_notify)(struct file_lock *); /* unblock callback */
+ int (*lm_grant)(struct file_lock *, struct file_lock *, int);
+ void (*lm_release_private)(struct file_lock *);
+ void (*lm_break)(struct file_lock *); /* break_lease callback */
+ int (*lm_change)(struct file_lock **, int);
locking rules:
file_lock_lock may block
-fl_compare_owner: yes no
-fl_notify: yes no
-fl_grant: no no
-fl_release_private: maybe no
-fl_break: yes no
-fl_change yes no
+lm_compare_owner: yes no
+lm_notify: yes no
+lm_grant: no no
+lm_release_private: maybe no
+lm_break: yes no
+lm_change yes no
--------------------------- buffer_head -----------------------------------
prototypes:
@@ -412,7 +412,7 @@ prototypes:
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
- int (*fsync) (struct file *, int datasync);
+ int (*fsync) (struct file *, loff_t start, loff_t end, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
@@ -438,9 +438,7 @@ prototypes:
locking rules:
All may block except for ->setlease.
- No VFS locks held on entry except for ->fsync and ->setlease.
-
-->fsync() has i_mutex on inode.
+ No VFS locks held on entry except for ->setlease.
->setlease has the file_list_lock held and must not sleep.
diff --git a/Documentation/filesystems/debugfs.txt b/Documentation/filesystems/debugfs.txt
index ed52af60c2d8..742cc06e138f 100644
--- a/Documentation/filesystems/debugfs.txt
+++ b/Documentation/filesystems/debugfs.txt
@@ -73,8 +73,8 @@ the following functions can be used instead:
struct dentry *parent, u16 *value);
struct dentry *debugfs_create_x32(const char *name, mode_t mode,
struct dentry *parent, u32 *value);
-
-Note that there is no debugfs_create_x64().
+ struct dentry *debugfs_create_x64(const char *name, mode_t mode,
+ struct dentry *parent, u64 *value);
These functions are useful as long as the developer knows the size of the
value to be exported. Some types can have different widths on different
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 272f80d5f966..22f3a0eda1d2 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -147,15 +147,6 @@ grpjquota=<file> during journal replay. They replace the above
package for more details
(http://sourceforge.net/projects/linuxquota).
-bh (*) ext3 associates buffer heads to data pages to
-nobh (a) cache disk block mapping information
- (b) link pages into transaction to provide
- ordering guarantees.
- "bh" option forces use of buffer heads.
- "nobh" option tries to avoid associating buffer
- heads (supported only for "writeback" mode).
-
-
Specification
=============
Ext3 shares all disk implementation with the ext2 filesystem, and adds
@@ -227,5 +218,5 @@ kernel source: <file:fs/ext3/>
programs: http://e2fsprogs.sourceforge.net/
http://ext2resize.sourceforge.net
-useful links: http://www.ibm.com/developerworks/library/l-fs7.html
- http://www.ibm.com/developerworks/library/l-fs8.html
+useful links: http://www.ibm.com/developerworks/library/l-fs7/index.html
+ http://www.ibm.com/developerworks/library/l-fs8/index.html
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index 3ae9bc94352a..232a575a0c48 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -68,12 +68,12 @@ Note: More extensive information for getting started with ext4 can be
'-o barriers=[0|1]' mount option for both ext3 and ext4 filesystems
for a fair comparison. When tuning ext3 for best benchmark numbers,
it is often worthwhile to try changing the data journaling mode; '-o
- data=writeback,nobh' can be faster for some workloads. (Note
- however that running mounted with data=writeback can potentially
- leave stale data exposed in recently written files in case of an
- unclean shutdown, which could be a security exposure in some
- situations.) Configuring the filesystem with a large journal can
- also be helpful for metadata-intensive workloads.
+ data=writeback' can be faster for some workloads. (Note however that
+ running mounted with data=writeback can potentially leave stale data
+ exposed in recently written files in case of an unclean shutdown,
+ which could be a security exposure in some situations.) Configuring
+ the filesystem with a large journal can also be helpful for
+ metadata-intensive workloads.
2. Features
===========
@@ -272,14 +272,6 @@ grpjquota=<file> during journal replay. They replace the above
package for more details
(http://sourceforge.net/projects/linuxquota).
-bh (*) ext4 associates buffer heads to data pages to
-nobh (a) cache disk block mapping information
- (b) link pages into transaction to provide
- ordering guarantees.
- "bh" option forces use of buffer heads.
- "nobh" option tries to avoid associating buffer
- heads (supported only for "writeback" mode).
-
stripe=n Number of filesystem blocks that mballoc will try
to use for allocation size and alignment. For RAID5/6
systems this should be the number of data
@@ -393,8 +385,7 @@ dioread_nolock locking. If the dioread_nolock option is specified
write and convert the extent to initialized after IO
completes. This approach allows ext4 code to avoid
using inode mutex, which improves scalability on high
- speed storages. However this does not work with nobh
- option and the mount will fail. Nor does it work with
+ speed storages. However this does not work with
data journaling and dioread_nolock option will be
ignored with kernel warning. Note that dioread_nolock
code path is only used for extent-based files.
diff --git a/Documentation/filesystems/nfs/Exporting b/Documentation/filesystems/nfs/Exporting
index 87019d2b5981..09994c247289 100644
--- a/Documentation/filesystems/nfs/Exporting
+++ b/Documentation/filesystems/nfs/Exporting
@@ -92,7 +92,14 @@ For a filesystem to be exportable it must:
1/ provide the filehandle fragment routines described below.
2/ make sure that d_splice_alias is used rather than d_add
when ->lookup finds an inode for a given parent and name.
- Typically the ->lookup routine will end with a:
+
+ If inode is NULL, d_splice_alias(inode, dentry) is eqivalent to
+
+ d_add(dentry, inode), NULL
+
+ Similarly, d_splice_alias(ERR_PTR(err), dentry) = ERR_PTR(err)
+
+ Typically the ->lookup routine will simply end with a:
return d_splice_alias(inode, dentry);
}
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
index 04884914a1c8..092fad92a3f0 100644
--- a/Documentation/filesystems/nfs/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -39,27 +39,17 @@ interoperability problems with future clients. Known issues:
from a linux client are possible, but we aren't really
conformant with the spec (for example, we don't use kerberos
on the backchannel correctly).
- - no trunking support: no clients currently take advantage of
- trunking, but this is a mandatory feature, and its use is
- recommended to clients in a number of places. (E.g. to ensure
- timely renewal in case an existing connection's retry timeouts
- have gotten too long; see section 8.3 of the RFC.)
- Therefore, lack of this feature may cause future clients to
- fail.
- Incomplete backchannel support: incomplete backchannel gss
support and no support for BACKCHANNEL_CTL mean that
callbacks (hence delegations and layouts) may not be
available and clients confused by the incomplete
implementation may fail.
- - Server reboot recovery is unsupported; if the server reboots,
- clients may fail.
- We do not support SSV, which provides security for shared
client-server state (thus preventing unauthorized tampering
with locks and opens, for example). It is mandatory for
servers to support this, though no clients use it yet.
- Mandatory operations which we do not support, such as
- DESTROY_CLIENTID, FREE_STATEID, SECINFO_NO_NAME, and
- TEST_STATEID, are not currently used by clients, but will be
+ DESTROY_CLIENTID, are not currently used by clients, but will be
(and the spec recommends their uses in common cases), and
clients should not be expected to know how to recover from the
case where they are not supported. This will eventually cause
@@ -69,8 +59,9 @@ In addition, some limitations are inherited from the current NFSv4
implementation:
- Incomplete delegation enforcement: if a file is renamed or
- unlinked, a client holding a delegation may continue to
- indefinitely allow opens of the file under the old name.
+ unlinked by a local process, a client holding a delegation may
+ continue to indefinitely allow opens of the file under the old
+ name.
The table below, taken from the NFSv4.1 document, lists
the operations that are mandatory to implement (REQ), optional
@@ -99,7 +90,7 @@ Operations
+----------------------+------------+--------------+----------------+
| ACCESS | REQ | | Section 18.1 |
NS | BACKCHANNEL_CTL | REQ | | Section 18.33 |
-NS | BIND_CONN_TO_SESSION | REQ | | Section 18.34 |
+I | BIND_CONN_TO_SESSION | REQ | | Section 18.34 |
| CLOSE | REQ | | Section 18.2 |
| COMMIT | REQ | | Section 18.3 |
| CREATE | REQ | | Section 18.4 |
@@ -111,7 +102,7 @@ NS*| DELEGPURGE | OPT | FDELG (REQ) | Section 18.5 |
NS | DESTROY_CLIENTID | REQ | | Section 18.50 |
I | DESTROY_SESSION | REQ | | Section 18.37 |
I | EXCHANGE_ID | REQ | | Section 18.35 |
-NS | FREE_STATEID | REQ | | Section 18.38 |
+I | FREE_STATEID | REQ | | Section 18.38 |
| GETATTR | REQ | | Section 18.7 |
P | GETDEVICEINFO | OPT | pNFS (REQ) | Section 18.40 |
P | GETDEVICELIST | OPT | pNFS (OPT) | Section 18.41 |
@@ -145,14 +136,14 @@ NS*| OPENATTR | OPT | | Section 18.17 |
| RESTOREFH | REQ | | Section 18.27 |
| SAVEFH | REQ | | Section 18.28 |
| SECINFO | REQ | | Section 18.29 |
-NS | SECINFO_NO_NAME | REC | pNFS files | Section 18.45, |
+I | SECINFO_NO_NAME | REC | pNFS files | Section 18.45, |
| | | layout (REQ) | Section 13.12 |
I | SEQUENCE | REQ | | Section 18.46 |
| SETATTR | REQ | | Section 18.30 |
| SETCLIENTID | MNI | | N/A |
| SETCLIENTID_CONFIRM | MNI | | N/A |
NS | SET_SSV | REQ | | Section 18.47 |
-NS | TEST_STATEID | REQ | | Section 18.48 |
+I | TEST_STATEID | REQ | | Section 18.48 |
| VERIFY | REQ | | Section 18.31 |
NS*| WANT_DELEGATION | OPT | FDELG (OPT) | Section 18.49 |
| WRITE | REQ | | Section 18.32 |
@@ -206,12 +197,6 @@ CREATE_SESSION:
SEQUENCE:
* no support for dynamic slot table renegotiation (optional)
-nfsv4.1 COMPOUND rules:
-The following cases aren't supported yet:
-* Enforcing of NFS4ERR_NOT_ONLY_OP for: BIND_CONN_TO_SESSION, CREATE_SESSION,
- DESTROY_CLIENTID, DESTROY_SESSION, EXCHANGE_ID.
-* DESTROY_SESSION MUST be the final operation in the COMPOUND request.
-
Nonstandard compound limitations:
* No support for a sessions fore channel RPC compound that requires both a
ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
@@ -219,3 +204,5 @@ Nonstandard compound limitations:
negotiation.
* No more than one IO operation (read, write, readdir) allowed per
compound.
+
+See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
index 90c71c6f0d00..ffdd9d866ad7 100644
--- a/Documentation/filesystems/nfs/nfsroot.txt
+++ b/Documentation/filesystems/nfs/nfsroot.txt
@@ -226,7 +226,7 @@ They depend on various facilities being available:
cdrecord.
e.g.
- cdrecord dev=ATAPI:1,0,0 arch/i386/boot/image.iso
+ cdrecord dev=ATAPI:1,0,0 arch/x86/boot/image.iso
For more information on isolinux, including how to create bootdisks
for prebuilt kernels, see http://syslinux.zytor.com/
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index 6e29954851a2..b4a3d765ff9a 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -400,10 +400,32 @@ a file off.
--
[mandatory]
-
---
-[mandatory]
->get_sb() is gone. Switch to use of ->mount(). Typically it's just
a matter of switching from calling get_sb_... to mount_... and changing the
function type. If you were doing it manually, just switch from setting ->mnt_root
to some pointer to returning that pointer. On errors return ERR_PTR(...).
+
+--
+[mandatory]
+ ->permission() and generic_permission()have lost flags
+argument; instead of passing IPERM_FLAG_RCU we add MAY_NOT_BLOCK into mask.
+ generic_permission() has also lost the check_acl argument; ACL checking
+has been taken to VFS and filesystems need to provide a non-NULL ->i_op->get_acl
+to read an ACL from disk.
+
+--
+[mandatory]
+ If you implement your own ->llseek() you must handle SEEK_HOLE and
+SEEK_DATA. You can hanle this by returning -EINVAL, but it would be nicer to
+support it in some way. The generic handler assumes that the entire file is
+data and there is a virtual hole at the end of the file. So if the provided
+offset is less than i_size and SEEK_DATA is specified, return the same offset.
+If the above is true for the offset and you are given SEEK_HOLE, return the end
+of the file. If the offset is i_size or greater return -ENXIO in either case.
+
+[mandatory]
+ If you have your own ->fsync() you must make sure to call
+filemap_write_and_wait_range() so that all dirty pages are synced out properly.
+You must also keep in mind that ->fsync() is not called with i_mutex held
+anymore, so if you require i_mutex locking you must make sure to take it and
+release it yourself.
diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt
index d4d41465a0b1..7db3ebda5a4c 100644
--- a/Documentation/filesystems/squashfs.txt
+++ b/Documentation/filesystems/squashfs.txt
@@ -2,7 +2,7 @@ SQUASHFS 4.0 FILESYSTEM
=======================
Squashfs is a compressed read-only filesystem for Linux.
-It uses zlib/lzo compression to compress files, inodes and directories.
+It uses zlib/lzo/xz compression to compress files, inodes and directories.
Inodes in the system are very small and all blocks are packed to minimise
data overhead. Block sizes greater than 4K are supported up to a maximum
of 1Mbytes (default block size 128K).
@@ -55,6 +55,8 @@ create populated squashfs filesystems. This and other squashfs utilities
can be obtained from http://www.squashfs.org. Usage instructions can be
obtained from this site also.
+The squashfs-tools development tree is now located on kernel.org
+ git://git.kernel.org/pub/scm/fs/squashfs/squashfs-tools.git
3. SQUASHFS FILESYSTEM DESIGN
-----------------------------
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
index 8e4fab639d9c..a0a61d2f389f 100644
--- a/Documentation/filesystems/ubifs.txt
+++ b/Documentation/filesystems/ubifs.txt
@@ -111,34 +111,6 @@ The following is an example of the kernel boot arguments to attach mtd0
to UBI and mount volume "rootfs":
ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
-
-Module Parameters for Debugging
-===============================
-
-When UBIFS has been compiled with debugging enabled, there are 2 module
-parameters that are available to control aspects of testing and debugging.
-
-debug_chks Selects extra checks that UBIFS can do while running:
-
- Check Flag value
-
- General checks 1
- Check Tree Node Cache (TNC) 2
- Check indexing tree size 4
- Check orphan area 8
- Check old indexing tree 16
- Check LEB properties (lprops) 32
- Check leaf nodes and inodes 64
-
-debug_tsts Selects a mode of testing, as follows:
-
- Test mode Flag value
-
- Failure mode for recovery testing 4
-
-For example, set debug_chks to 3 to enable general and TNC checks.
-
-
References
==========
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 88b9f5519af9..52d8fb81cfff 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -229,6 +229,8 @@ struct super_operations {
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+ int (*nr_cached_objects)(struct super_block *);
+ void (*free_cached_objects)(struct super_block *, int);
};
All methods are called without any locks being held, unless otherwise
@@ -301,6 +303,26 @@ or bottom half).
quota_write: called by the VFS to write to filesystem quota file.
+ nr_cached_objects: called by the sb cache shrinking function for the
+ filesystem to return the number of freeable cached objects it contains.
+ Optional.
+
+ free_cache_objects: called by the sb cache shrinking function for the
+ filesystem to scan the number of objects indicated to try to free them.
+ Optional, but any filesystem implementing this method needs to also
+ implement ->nr_cached_objects for it to be called correctly.
+
+ We can't do anything with any errors that the filesystem might
+ encountered, hence the void return type. This will never be called if
+ the VM is trying to reclaim under GFP_NOFS conditions, hence this
+ method does not need to handle that situation itself.
+
+ Implementations must include conditional reschedule calls inside any
+ scanning loop that is done. This allows the VFS to determine
+ appropriate scan batch sizes without having to worry about whether
+ implementations will cause holdoff problems due to large scan batch
+ sizes.
+
Whoever sets up the inode is responsible for filling in the "i_op" field. This
is a pointer to a "struct inode_operations" which describes the methods that
can be performed on individual inodes.
@@ -333,8 +355,8 @@ struct inode_operations {
void * (*follow_link) (struct dentry *, struct nameidata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int, unsigned int);
- int (*check_acl)(struct inode *, int, unsigned int);
+ int (*permission) (struct inode *, int);
+ int (*get_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -423,7 +445,7 @@ otherwise noted.
permission: called by the VFS to check for access rights on a POSIX-like
filesystem.
- May be called in rcu-walk mode (flags & IPERM_FLAG_RCU). If in rcu-walk
+ May be called in rcu-walk mode (mask & MAY_NOT_BLOCK). If in rcu-walk
mode, the filesystem must check the permission without blocking or
storing to the inode.
@@ -755,7 +777,7 @@ struct file_operations {
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
- int (*fsync) (struct file *, int datasync);
+ int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 38425f0f2645..6f496a586732 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -76,7 +76,8 @@ IT8718F, IT8720F, IT8721F, IT8726F, IT8758E and SiS950 chips.
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
joysticks and other miscellaneous stuff. For hardware monitoring, they
include an 'environment controller' with 3 temperature sensors, 3 fan
-rotation speed sensors, 8 voltage sensors, and associated alarms.
+rotation speed sensors, 8 voltage sensors, associated alarms, and chassis
+intrusion detection.
The IT8712F and IT8716F additionally feature VID inputs, used to report
the Vcore voltage of the processor. The early IT8712F have 5 VID pins,
diff --git a/Documentation/hwmon/lm78 b/Documentation/hwmon/lm78
index 60932e26abaa..2bdc881a0c12 100644
--- a/Documentation/hwmon/lm78
+++ b/Documentation/hwmon/lm78
@@ -13,7 +13,8 @@ Supported chips:
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
-Author: Frodo Looijaard <frodol@dds.nl>
+Authors: Frodo Looijaard <frodol@dds.nl>
+ Jean Delvare <khali@linux-fr.org>
Description
-----------
diff --git a/Documentation/hwmon/sch5636 b/Documentation/hwmon/sch5636
new file mode 100644
index 000000000000..f83bd1c260f0
--- /dev/null
+++ b/Documentation/hwmon/sch5636
@@ -0,0 +1,31 @@
+Kernel driver sch5636
+=====================
+
+Supported chips:
+ * SMSC SCH5636
+ Prefix: 'sch5636'
+ Addresses scanned: none, address read from Super I/O config space
+
+Author: Hans de Goede <hdegoede@redhat.com>
+
+
+Description
+-----------
+
+SMSC SCH5636 Super I/O chips include an embedded microcontroller for
+hardware monitoring solutions, allowing motherboard manufacturers to create
+their own custom hwmon solution based upon the SCH5636.
+
+Currently the sch5636 driver only supports the Fujitsu Theseus SCH5636 based
+hwmon solution. The sch5636 driver runs a sanity check on loading to ensure
+it is dealing with a Fujitsu Theseus and not with another custom SCH5636 based
+hwmon solution.
+
+The Fujitsu Theseus can monitor up to 5 voltages, 8 fans and 16
+temperatures. Note that the driver detects how many fan headers /
+temperature sensors are actually implemented on the motherboard, so you will
+likely see fewer temperature and fan inputs.
+
+An application note describing the Theseus' registers, as well as an
+application note describing the protocol for communicating with the
+microcontroller is available upon request. Please mail me if you want a copy.
diff --git a/Documentation/i2o/ioctl b/Documentation/i2o/ioctl
index 1e77fac4e120..22ca53a67e23 100644
--- a/Documentation/i2o/ioctl
+++ b/Documentation/i2o/ioctl
@@ -110,7 +110,7 @@ V. Getting Logical Configuration Table
ENOBUFS Buffer not large enough. If this occurs, the required
buffer length is written into *(lct->reslen)
-VI. Settting Parameters
+VI. Setting Parameters
SYNOPSIS
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 3a46e360496d..72ba8d51dbc1 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -301,6 +301,7 @@ Code Seq#(hex) Include File Comments
<mailto:rusty@rustcorp.com.au>
0xAE all linux/kvm.h Kernel-based Virtual Machine
<mailto:kvm@vger.kernel.org>
+0xAF 00-1F linux/fsl_hypervisor.h Freescale hypervisor
0xB0 all RATIO devices in development:
<mailto:vgo@ratio.de>
0xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax
index 99e87a61897d..b1a573cf4472 100644
--- a/Documentation/isdn/README.HiSax
+++ b/Documentation/isdn/README.HiSax
@@ -506,7 +506,7 @@ to e.g. the Internet:
<ISDN subsystem - ISDN support -- HiSax>
make clean; make zImage; make modules; make modules_install
2. Install the new kernel
- cp /usr/src/linux/arch/i386/boot/zImage /etc/kernel/linux.isdn
+ cp /usr/src/linux/arch/x86/boot/zImage /etc/kernel/linux.isdn
vi /etc/lilo.conf
<add new kernel in the bootable image section>
lilo
diff --git a/Documentation/ja_JP/SubmitChecklist b/Documentation/ja_JP/SubmitChecklist
index 2df4576f1173..cb5507b1ac81 100644
--- a/Documentation/ja_JP/SubmitChecklist
+++ b/Documentation/ja_JP/SubmitChecklist
@@ -68,7 +68,7 @@ Linux カーãƒãƒ«ãƒ‘ãƒƒãƒæŠ•ç¨¿è€…å‘ã‘ãƒã‚§ãƒƒã‚¯ãƒªã‚¹ãƒˆ
12: CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, CONFIG_DEBUG_SLAB,
CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK,
- CONFIG_DEBUG_SPINLOCK_SLEEP ã“れら全ã¦ã‚’åŒæ™‚ã«æœ‰åйã«ã—ã¦å‹•作確èªã‚’
+ CONFIG_DEBUG_ATOMIC_SLEEP ã“れら全ã¦ã‚’åŒæ™‚ã«æœ‰åйã«ã—ã¦å‹•作確èªã‚’
行ã£ã¦ãã ã•ã„。
13: CONFIG_SMP, CONFIG_PREEMPT を有効ã«ã—ãŸå ´åˆã¨ç„¡åйã«ã—ãŸå ´åˆã®ä¸¡æ–¹ã§
diff --git a/Documentation/ja_JP/SubmittingPatches b/Documentation/ja_JP/SubmittingPatches
index f107c834d242..97f78dd0c085 100644
--- a/Documentation/ja_JP/SubmittingPatches
+++ b/Documentation/ja_JP/SubmittingPatches
@@ -11,16 +11,18 @@ for non English (read: Japanese) speakers and is not intended as a
fork. So if you have any comments or updates of this file, please try
to update the original English file first.
-Last Updated: 2007/10/24
+Last Updated: 2011/06/09
+
==================================
ã“れã¯ã€
-linux-2.6.23/Documentation/SubmittingPatches ã®å’Œè¨³
+linux-2.6.39/Documentation/SubmittingPatches ã®å’Œè¨³
ã§ã™ã€‚
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日: 2007/10/17
+翻訳日: 2011/06/09
翻訳者: Keiichi Kii <k-keiichi at bx dot jp dot nec dot com>
校正者: Masanari Kobayashi ã•ã‚“ <zap03216 at nifty dot ne dot jp>
Matsukura ã•ã‚“ <nbh--mats at nifty dot com>
+ Takeshi Hamasaki ã•ã‚“ <hmatrjp at users dot sourceforge dot jp>
==================================
Linux カーãƒãƒ«ã«å¤‰æ›´ã‚’加ãˆã‚‹ãŸã‚ã® Howto
@@ -97,7 +99,7 @@ Quilt:
http://savannah.nongnu.org/projects/quilt
Andrew Morton's patch scripts:
-http://userweb.kernel.org/~akpm/stuff/tpp.txt
+http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz
ã“ã®ãƒªãƒ³ã‚¯ã®å…ˆã®ã‚¹ã‚¯ãƒªãƒ—トã®ä»£ã‚りã¨ã—ã¦ã€quilt ãŒãƒ‘ッãƒãƒžãƒã‚¸ãƒ¡ãƒ³ãƒˆ
ツールã¨ã—ã¦æŽ¨å¥¨ã•れã¦ã„ã¾ã™(上ã®ãƒªãƒ³ã‚¯ã‚’見ã¦ãã ã•ã„)。
@@ -109,9 +111,25 @@ http://userweb.kernel.org/~akpm/stuff/tpp.txt
「ドライãƒãƒ¼ X ã«å¯¾ã™ã‚‹ãƒã‚°ãƒ•ィックスã€ã‚ã‚‹ã„ã¯ã€Œã“ã®ãƒ‘ッãƒã¯ã‚µãƒ–シス
テム X ã«å¯¾ã™ã‚‹æ›´æ–°ã‚’å«ã‚“ã§ã„ã¾ã™ã€‚ã©ã†ã‹å–り入れã¦ãã ã•ã„。ã€ãªã©ã§ã™ã€‚
+パッãƒã®èª¬æ˜Žã‚’ Linux カーãƒãƒ«ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ãƒžãƒã‚¸ãƒ¡ãƒ³ãƒˆã‚·ã‚¹ãƒ†ãƒ ã€Œ git ã€ã®
+コミットログã¨ã—ã¦ç°¡å˜ã«å¼•用ã§ãã‚‹å½¢ã§æ›¸ã‘ã°ã€ãƒ¡ãƒ³ãƒ†ãƒŠã‹ã‚‰æ„Ÿè¬ã•れるã§ã—ょã†ã€‚
+以下㮠#15 を見ã¦ãã ã•ã„。
+
説明ãŒé•·ããªã‚Šã ã—ãŸã®ã§ã‚れã°ã€ãŠãらããれã¯ãƒ‘ッãƒã‚’分ã‘ã‚‹å¿…è¦ãŒã‚ã‚‹
ã¨ã„ã†å…†å€™ã§ã™ã€‚次㮠#3 を見ã¦ãã ã•ã„。
+パッãƒ(シリーズ)ã‚’(å†)投稿ã™ã‚‹æ™‚ã€å分ãªãƒ‘ッãƒã®èª¬æ˜Žã¨ãã®ãƒ‘ッãƒãŒå¿…è¦ãªç†ç”±ã‚’
+パッãƒã«å«ã‚ã¦ãã ã•ã„。ãŸã ã€Œã“れã¯ãƒ‘ッãƒ(シリーズ)ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ Nã€ã¨ã ã‘
+書ã‹ãªã„ã§ãã ã•ã„。ãã—ã¦ã€ãƒ‘ッãƒã‚’マージã™ã‚‹äººã«ãƒ‘ッãƒã®èª¬æ˜Žã‚’探ã•ã›ãれを
+パッãƒã«è¿½è¨˜ã•ã›ã‚‹ãŸã‚ã€éŽåŽ»ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒ‘ッãƒã‚„ãã®ãƒ‘ッãƒã® URL ã‚’å‚ç…§ã™ã‚‹
+手間をã‹ã‘ã•ã›ãªã„ã§ãã ã•ã„。
+ã¤ã¾ã‚Šã€ãƒ‘ッãƒã‚·ãƒªãƒ¼ã‚ºã¨ãã®èª¬æ˜Žã¯ä¸€ç·’ã«ã‚ã‚‹ã¹ãã§ã™ã€‚ã“れã¯ãƒ‘ッãƒã‚’マージã™ã‚‹
+人ã€ãƒ¬ãƒ“ューã™ã‚‹äººã€ã©ã¡ã‚‰ã®ãŸã‚ã«ã‚‚ãªã‚Šã¾ã™ã€‚レビューã™ã‚‹äººã®ä¸­ã«ã¯ã€ãŠãらã
+éŽåŽ»ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒ‘ッãƒã‚’å—ã‘å–ã£ã¦ã‚‚ã„ãªã„人ãŒã„ã¾ã™ã€‚
+
+登録済ã¿ã®ãƒã‚°ã‚¨ãƒ³ãƒˆãƒªã‚’修正ã™ã‚‹ãƒ‘ッãƒã§ã‚れã°ã€ãã®ãƒã‚°ã‚¨ãƒ³ãƒˆãƒªã‚’示ã™ãƒã‚° ID
+ã‚„ URL を明記ã—ã¦ãã ã•ã„。
+
3) パッãƒã®åˆ†å‰²
æ„味ã®ã‚ã‚‹ã²ã¨ã¾ã¨ã¾ã‚Šã”ã¨ã«å¤‰æ›´ã‚’個々ã®ãƒ‘ッãƒãƒ•ァイルã«åˆ†ã‘ã¦ãã ã•ã„。
@@ -141,7 +159,7 @@ http://userweb.kernel.org/~akpm/stuff/tpp.txt
æ‹’å¦ã•れるã§ã—ょã†ã€‚
ã‚ãªãŸã¯ãƒ‘ッãƒã‚’投稿ã™ã‚‹å‰ã«æœ€ä½Žé™ãƒ‘ッãƒã‚¹ã‚¿ã‚¤ãƒ«ãƒã‚§ãƒƒã‚«ãƒ¼
-( scripts/patchcheck.pl )を利用ã—ã¦ãƒ‘ッãƒã‚’ãƒã‚§ãƒƒã‚¯ã™ã¹ãã§ã™ã€‚
+( scripts/checkpatch.pl )を利用ã—ã¦ãƒ‘ッãƒã‚’ãƒã‚§ãƒƒã‚¯ã™ã¹ãã§ã™ã€‚
ã‚‚ã—パッãƒã«é•åãŒã®ã“ã£ã¦ã„ã‚‹ãªã‚‰ã°ã€ãれらã®å…¨ã¦ã«ã¤ã„ã¦ã‚ãªãŸã¯æ­£å½“ãª
ç†ç”±ã‚’示ã›ã‚‹ã‚ˆã†ã«ã—ã¦ãŠãå¿…è¦ãŒã‚りã¾ã™ã€‚
@@ -192,13 +210,13 @@ VGER.KERNEL.ORG ã§ãƒ›ã‚¹ãƒ†ã‚£ãƒ³ã‚°ã•れã¦ã„るメーリングリストã®ä
情報ãŒãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãƒšãƒ¼ã‚¸ã®ä¸­ã«å…¥ã£ã¦ãるよã†ã«ã€å¤‰æ›´ãŒèµ·ããŸã¨ã„ã†
通知をé€ã£ã¦ãã ã•ã„。
-ãŸã¨ãˆã€ãƒ¡ãƒ³ãƒ†ãƒŠãŒ #4 ã§å応ãŒãªã‹ã£ãŸã¨ã—ã¦ã‚‚ã€ãƒ¡ãƒ³ãƒ†ãƒŠã®ã‚³ãƒ¼ãƒ‰ã«å¤‰æ›´ã‚’
+ãŸã¨ãˆã€ãƒ¡ãƒ³ãƒ†ãƒŠãŒ #5 ã§å応ãŒãªã‹ã£ãŸã¨ã—ã¦ã‚‚ã€ãƒ¡ãƒ³ãƒ†ãƒŠã®ã‚³ãƒ¼ãƒ‰ã«å¤‰æ›´ã‚’
加ãˆãŸã¨ãã«ã¯ã€ã„ã¤ã‚‚メンテナ㫠CC ã™ã‚‹ã®ã‚’忘れãªã„よã†ã«ã—ã¦ãã ã•ã„。
-å°ã•ãªãƒ‘ッãƒã§ã‚れã°ã€Adrian Bunk ãŒç®¡ç†ã—ã¦ã„ã‚‹ Trivial Patch Monkey
-(ã¡ã‚‡ã£ã¨ã—ãŸãƒ‘ッãƒã‚’集ã‚ã¦ã„ã‚‹)<trivial@kernel.org>ã« CC ã—ã¦ã‚‚ã„ã„
-ã§ã™ã€‚ã¡ã‚‡ã£ã¨ã—ãŸãƒ‘ッãƒã¨ã¯ä»¥ä¸‹ã®ãƒ«ãƒ¼ãƒ«ã®ã©ã‚Œã‹1ã¤ã‚’満ãŸã—ã¦ã„ãªã‘
-れã°ãªã‚Šã¾ã›ã‚“。
+å°ã•ãªãƒ‘ッãƒã§ã‚れã°ã€Trivial Patch Monkey(ã¡ã‚‡ã£ã¨ã—ãŸãƒ‘ッãƒã‚’集ã‚ã¦ã„ã‚‹)
+<trivial@kernel.org>ã« CC ã—ã¦ã‚‚ã„ã„ã§ã™ã€‚ãã®ç¾ç®¡ç†è€…ã«ã¤ã„ã¦ã¯ MAINTAINERS
+ファイルを見ã¦ãã ã•ã„。ã¡ã‚‡ã£ã¨ã—ãŸãƒ‘ッãƒã¨ã¯ä»¥ä¸‹ã®ãƒ«ãƒ¼ãƒ«ã®ã©ã‚Œã‹1ã¤ã‚’満ãŸã—ã¦
+ã„ãªã‘れã°ãªã‚Šã¾ã›ã‚“。
・ドキュメントã®ã‚¹ãƒšãƒ«ãƒŸã‚¹ã®ä¿®æ­£
・grep(1) コマンドã«ã‚ˆã‚‹æ¤œç´¢ã‚’困難ã«ã—ã¦ã„るスペルã®ä¿®æ­£
・コンパイル時ã®è­¦å‘Šã®ä¿®æ­£(ç„¡é§„ãªè­¦å‘ŠãŒæ•£ä¹±ã™ã‚‹ã“ã¨ã¯å¥½ã¾ã—ããªã„ãŸ
@@ -210,7 +228,6 @@ VGER.KERNEL.ORG ã§ãƒ›ã‚¹ãƒ†ã‚£ãƒ³ã‚°ã•れã¦ã„るメーリングリストã®ä
ãƒ»ç§»æ¤æ€§ã®ãªã„コードã‹ã‚‰ç§»æ¤æ€§ã®ã‚るコードã¸ã®ç½®ãæ›ãˆ(å°ã•ã„範囲ã§
ã‚れã°ã‚¢ãƒ¼ã‚­ãƒ†ã‚¯ãƒãƒ£ç‰¹æœ‰ã®ã“ã¨ã§ã‚‚ä»–ã®äººãŒã‚³ãƒ”ーã§ãã¾ã™)
・作者やメンテナã«ã‚ˆã‚‹ä¿®æ­£(ã™ãªã‚ã¡ patch monkey ã®å†è»¢é€ãƒ¢ãƒ¼ãƒ‰)
-EMAIL: <trivial@kernel.org>
7) MIME やリンクや圧縮ファイルや添付ファイルã§ã¯ãªãプレインテキストã®ã¿
@@ -233,26 +250,15 @@ MIME å½¢å¼ã®æ·»ä»˜ãƒ•ァイル㯠Linus ã«æ‰‹é–“ã‚’å–らã›ã‚‹ã“ã¨ã«ãªã‚
例外:ãŠä½¿ã„ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒãƒ‘ッãƒã‚’ã‚ã¡ã‚ƒãã¡ã‚ƒã«ã™ã‚‹ã®ã§
ã‚れã°ã€èª°ã‹ãŒ MIME å½¢å¼ã®ãƒ‘ッãƒã‚’å†é€ã™ã‚‹ã‚ˆã†æ±‚ã‚ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。
-警告: Mozilla ã®ã‚ˆã†ãªç‰¹å®šã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯é›»å­ãƒ¡ãƒ¼ãƒ«ã®
-ヘッダã«ä»¥ä¸‹ã®ã‚‚ã®ã‚’付加ã—ã¦é€ã‚Šã¾ã™ã€‚
----- message header ----
-Content-Type: text/plain; charset=us-ascii; format=flowed
----- message header ----
-å•題ã¯ã€ã€Œ format=flowed ã€ãŒä»˜ã„ãŸé›»å­ãƒ¡ãƒ¼ãƒ«ã‚’特定ã®å—ä¿¡å´ã®é›»å­ãƒ¡ãƒ¼ãƒ«
-クライアントãŒã‚¿ãƒ–をスペースã«ç½®ãæ›ãˆã‚‹ã¨ã„ã†ã‚ˆã†ãªå¤‰æ›´ã‚’ã™ã‚‹ã“ã¨ã§ã™ã€‚
-ã—ãŸãŒã£ã¦é€ã‚‰ã‚Œã¦ããŸãƒ‘ッãƒã¯å£Šã‚Œã¦ã„るよã†ã«è¦‹ãˆã‚‹ã§ã—ょã†ã€‚
-
-ã“れを修正ã™ã‚‹ã«ã¯ã€mozilla ã® defaults/pref/mailnews.js ファイルを
-以下ã®ã‚ˆã†ã«ä¿®æ­£ã—ã¾ã™ã€‚
-pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
-pref("mailnews.display.disable_format_flowed_support", true);
+余計ãªå¤‰æ›´ã‚’加ãˆãšã«ã‚ãªãŸã®ãƒ‘ッãƒã‚’é€ä¿¡ã™ã‚‹ãŸã‚ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®è¨­å®š
+ã®ãƒ’ントã«ã¤ã„ã¦ã¯ Documentation/email-clients.txt ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
8) é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µã‚¤ã‚º
パッãƒã‚’ Linus ã¸é€ã‚‹ã¨ãã¯å¸¸ã« #7 ã®æ‰‹é †ã«å¾“ã£ã¦ãã ã•ã„。
大ããªãƒ‘ッãƒã¯ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã‚„メンテナã«ã¨ã£ã¦ä¸è¦ªåˆ‡ã§ã™ã€‚パッãƒãŒ
-未圧縮㧠40KB ã‚’è¶…ãˆã‚‹ã‚ˆã†ã§ã‚ã‚‹ãªã‚‰ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ã‚¢ã‚¯ã‚»ã‚¹å¯èƒ½ãª
+未圧縮㧠300KB ã‚’è¶…ãˆã‚‹ã‚ˆã†ã§ã‚ã‚‹ãªã‚‰ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ã‚¢ã‚¯ã‚»ã‚¹å¯èƒ½ãª
サーãƒã«ä¿å­˜ã—ã€ä¿å­˜å ´æ‰€ã‚’示㙠URL ã‚’ä¼ãˆã‚‹ã»ã†ãŒé©åˆ‡ã§ã™ã€‚
9) カーãƒãƒ«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®æ˜Žè¨˜
@@ -324,7 +330,7 @@ Linus ã‚„ LKML ã¸ã®å¤§é‡ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã®ãŸã‚ã«ã€ã‚µãƒ–ジェクトã
(c) 本寄与ã¯(a)ã€(b)ã€(c)を証明ã™ã‚‹ç¬¬3者ã‹ã‚‰ç§ã¸ç›´æŽ¥æä¾›ã•れãŸ
ã‚‚ã®ã§ã‚りã€ç§ã¯ãれã«å¤‰æ›´ã‚’加ãˆã¦ã„ãªã„。
- (d) ç§ã¯ã“ã®ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆã¨æœ¬å¯„与ãŒå…¬ã®ã‚‚ã®ã§ã‚ã‚‹ã“ã¨ã«ç†è§£åŠã³åŒæ„ã™
+ (d) ç§ã¯ã“ã®ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆã¨æœ¬å¯„与ãŒå…¬ã®ã‚‚ã®ã§ã‚ã‚‹ã“ã¨ã«ç†è§£åŠã³åŒæ„ã™
ã‚‹ã€‚åŒæ™‚ã«ã€é–¢ä¸Žã—ãŸè¨˜éŒ²(投稿ã®éš›ã®å…¨ã¦ã®å€‹äººæƒ…報㨠sign-off ã‚’
å«ã‚€)ãŒç„¡æœŸé™ã«ä¿å…¨ã•れるã“ã¨ã¨ã€å½“該プロジェクトåˆã¯é–¢é€£ã™ã‚‹
ã‚ªãƒ¼ãƒ—ãƒ³ã‚½ãƒ¼ã‚¹ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã«æ²¿ã£ãŸå½¢ã§å†é…布ã•れるã“ã¨ã«ç†è§£åŠã³
@@ -340,7 +346,51 @@ Linus ã‚„ LKML ã¸ã®å¤§é‡ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã®ãŸã‚ã«ã€ã‚µãƒ–ジェクトã
無視ã•れã¾ã™ãŒã€ã‚ãªãŸã¯ãã®ã‚¿ã‚°ã‚’ç¤¾å†…ã®æ‰‹ç¶šãã«åˆ©ç”¨ã—ãŸã‚Šã€sign-off ã«ç‰¹åˆ¥
ãªæƒ…報を示ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-13) ã„㤠Acked-by: を使ã†ã®ã‹
+ã‚ãªãŸãŒã‚µãƒ–システムã¾ãŸã¯ãƒ–ランãƒã®ãƒ¡ãƒ³ãƒ†ãƒŠã§ã‚れã°ã€å—ã‘å–ã£ãŸãƒ‘ッãƒã‚’自身ã®
+ツリーã«ãƒžãƒ¼ã‚¸ã™ã‚‹ãŸã‚ã«ã€ã‚ãšã‹ã«å¤‰æ›´ãŒå¿…è¦ã¨ãªã‚‹å ´åˆãŒã‚りã¾ã™ã€‚ãªãœãªã‚‰
+ã‚ãªãŸã®ãƒ„リーã®ä¸­ã®ã‚³ãƒ¼ãƒ‰ã¨æŠ•稿者ã®ãƒ„リーã®ä¸­ã®ã‚³ãƒ¼ãƒ‰ã¯åŒä¸€ã§ã¯ãªã„ãŸã‚ã§ã™ã€‚
+ã‚‚ã—ã€ã‚ãªãŸãŒå޳坆ã«ä¸Šè¨˜ãƒ«ãƒ¼ãƒ«(c)ã«ã“ã ã‚ã‚‹ã®ã§ã‚れã°ã€æŠ•稿者ã«å†åº¦å·®åˆ†ã‚’
+ã¨ã‚‹ã‚ˆã†ä¾é ¼ã™ã¹ãã§ã™ã€‚ã—ã‹ã—ã€ã“ã‚Œã¯æ™‚é–“ã¨ã‚¨ãƒãƒ«ã‚®ãƒ¼ã‚’éžç”Ÿç”£çš„ã«æµªè²»ã™ã‚‹
+ã“ã¨ã«ãªã‚Šã¾ã™ã€‚ルール(b)ã¯ã‚ãªãŸã«ã‚³ãƒ¼ãƒ‰ã‚’修正ã™ã‚‹æ¨©åˆ©ã‚’与ãˆã¦ãれã¾ã™ã€‚
+ã—ã‹ã—ã€æŠ•ç¨¿è€…ã®ã‚³ãƒ¼ãƒ‰ã‚’修正ã—ã€ãã®ä¿®æ­£ã«ã‚ˆã‚‹ãƒã‚°ã‚’æŠ•ç¨¿è€…ã«æŠ¼ã—付ã‘ã¦ã—ã¾ã†
+ã“ã¨ã¯ã¨ã¦ã‚‚失礼ãªã“ã¨ã§ã™ã€‚ã“ã®å•題を解決ã™ã‚‹ãŸã‚ã«ã€æœ«å°¾ã®æŠ•稿者ã®
+Signed-off-by ã¨ã‚ãªãŸãŒãã®æœ«å°¾ã«è¿½åŠ ã™ã‚‹ Signed-off-by ã®é–“ã«ã€ä¿®æ­£ã‚’
+加ãˆãŸã“ã¨ã‚’示ã™1行を追加ã™ã‚‹ã“ã¨ãŒæŽ¨å¥¨ã•れã¦ã„ã¾ã™ã€‚
+(ãã®1è¡Œã®æ›¸ãæ–¹ã«)決ã¾ã‚Šã¯ã‚りã¾ã›ã‚“ãŒã€å¤§æ‹¬å¼§ã®ä¸­ã«é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚„æ°å
+ã¨ä¿®æ­£å†…容を記載ã™ã‚‹ã‚„り方ã¯ç›®ã«ã¤ãã‚„ã™ãã€æœ€çµ‚段階ã§ã®å¤‰æ›´ã®è²¬ä»»ãŒã‚ãªãŸã«
+ã‚ã‚‹ã“ã¨ã‚’明確ã«ã™ã‚‹ã®ã«ååˆ†ãªæ–¹æ³•ã®ã‚ˆã†ã§ã™ã€‚例ãˆã°ã€
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+ [lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+ Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+ã‚ãªãŸãŒå®‰å®šç‰ˆã®ãƒ–ランãƒã‚’管ç†ã—ã¦ãŠã‚Šã€ä½œæˆè€…ã®ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã€å¤‰æ›´ã®è¿½è·¡ã€
+修正ã®ãƒžãƒ¼ã‚¸ã€ã¨åŒæ™‚ã«è‹¦æƒ…ã‹ã‚‰ã®æŠ•稿者ã®ä¿è­·ã‚’行ã„ãŸã„å ´åˆã€ã“ã®æ…£ç¿’ã¯ç‰¹ã«
+有用ã¨ãªã‚Šã¾ã™ã€‚ã„ã‹ãªã‚‹äº‹æƒ…ãŒã‚ã£ã¦ã‚‚ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã«å‡ºã¦ãる作æˆè€…ã®
+アイデンティティ情報(From ヘッダ)ã¯å¤‰æ›´ã§ããªã„ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。
+
+ãƒãƒƒã‚¯ãƒãƒ¼ãƒˆã™ã‚‹äººã®ãŸã‚ã®ç‰¹åˆ¥ãªæ³¨æ„事項。追跡を容易ã«è¡Œã†ãŸã‚ã«ã€ã‚³ãƒŸãƒƒãƒˆ
+メッセージã®ãƒˆãƒƒãƒ—(サブジェクト行ã®ã™ã後)ã«ãƒ‘ッãƒã®èµ·æºã‚’ç¤ºã™æƒ…報を記述ã™ã‚‹
+ã“ã¨ã¯ä¸€èˆ¬çš„ã§æœ‰ç”¨ãªæ…£ç¿’ã§ã™ã€‚例ãˆã°ã€ã“れ㯠2.6-stable ツリーã§ã®ä¸€ä¾‹ã§ã™ã€‚
+
+ Date: Tue May 13 19:10:30 2008 +0000
+
+ SCSI: libiscsi regression in 2.6.25: fix nop timer handling
+
+ commit 4cf1043593db6a337f10e006c23c69e5fc93e722 upstream
+
+ãã—ã¦ã€ã“れ㯠2.4 ツリーã§ã®ä¸€ä¾‹ã§ã™ã€‚
+
+ Date: Tue May 13 22:12:27 2008 +0200
+
+ wireless, airo: waitbusy() won't delay
+
+ [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+ã©ã‚“ãªå½¢å¼ã§ã‚れã€ã“ã®æƒ…å ±ã¯ã‚ãªãŸã®ãƒ„リーを追跡ã™ã‚‹äººã‚„ã‚ãªãŸã®ãƒ„リーã®ãƒã‚°ã‚’
+解決ã—よã†ã¨ã—ã¦ã„る人ã«ã¨ã£ã¦ä¾¡å€¤ã®ã‚る支æ´ã¨ãªã‚Šã¾ã™ã€‚
+
+13) ã„㤠Acked-by: 㨠Cc: を使ã†ã®ã‹
「 Signed-off-by: ã€ã‚¿ã‚°ã¯ãã®ç½²å者ãŒãƒ‘ッãƒã®é–‹ç™ºã«é–¢ã‚ã£ã¦ã„ãŸã“ã¨ã‚„パッãƒ
ã®ä¼æ’­ãƒ‘スã«ã„ãŸã“ã¨ã‚’示ã—ã¦ã„ã¾ã™ã€‚
@@ -354,7 +404,7 @@ Linus ã‚„ LKML ã¸ã®å¤§é‡ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã®ãŸã‚ã«ã€ã‚µãƒ–ジェクトã
Acked-by: 㯠Signed-off-by: ã®ã‚ˆã†ã«å…¬å¼ãªã‚¿ã‚°ã§ã¯ã‚りã¾ã›ã‚“。ãれã¯ãƒ¡ãƒ³ãƒ†ãƒŠãŒ
å°‘ãªãã¨ã‚‚パッãƒã‚’レビューã—ã€åŒæ„を示ã—ã¦ã„ã‚‹ã¨ã„ã†è¨˜éŒ²ã§ã™ã€‚ãã®ã‚ˆã†ãª
-ã“ã¨ã‹ã‚‰ãƒ‘ッãƒã®çµ±åˆè€…ãŒãƒ¡ãƒ³ãƒ†ãƒŠã®ã€Œã†ã‚“ã€è‰¯ã„ã¨æ€ã†ã‚ˆã€ã¨ã„ã†ç™ºè¨€ã‚’
+ã“ã¨ã‹ã‚‰ãƒ‘ッãƒã‚’マージã™ã‚‹äººãŒãƒ¡ãƒ³ãƒ†ãƒŠã®ã€Œã†ã‚“ã€è‰¯ã„ã¨æ€ã†ã‚ˆã€ã¨ã„ã†ç™ºè¨€ã‚’
Acked-by: ã¸ç½®ãæ›ãˆã‚‹ã“ã¨ãŒã‚りã¾ã™ã€‚
Acked-by: ãŒå¿…ãšã—もパッãƒå…¨ä½“ã®æ‰¿èªã‚’示ã—ã¦ã„ã‚‹ã‚ã‘ã§ã¯ã‚りã¾ã›ã‚“。例ãˆã°ã€
@@ -364,7 +414,62 @@ Acked-by: ãŒå¿…ãšã—もパッãƒå…¨ä½“ã®æ‰¿èªã‚’示ã—ã¦ã„ã‚‹ã‚ã‘ã§ã¯ã
ã“ã®ç‚¹ã¯ã€ã”自分ã§åˆ¤æ–­ã—ã¦ãã ã•ã„。(ãã® Acked-by: ãŒ)ç–‘ã‚ã—ã„å ´åˆã¯ã€
メーリングリストアーカイブã®ä¸­ã®å¤§å…ƒã®è­°è«–ã‚’å‚ç…§ã™ã¹ãã§ã™ã€‚
-14) 標準的ãªãƒ‘ッãƒã®ãƒ•ォーマット
+パッãƒã«ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹æ©Ÿä¼šã‚’æŒã£ã¦ã„ãŸãŒã€ãã®æ™‚ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ãªã‹ã£ãŸäººãŒã„れã°ã€
+ãã®äººã‚’指ã™ã€ŒCc:ã€ã‚¿ã‚°ã‚’ä»»æ„ã§è¿½åŠ ã—ã¦ã‚‚ã‹ã¾ã„ã¾ã›ã‚“。ã“ã‚Œã¯æŒ‡å®šã•れãŸäººã‹ã‚‰ã®
+明確ãªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ãªã—ã«ä»˜ä¸Žã§ãる唯一ã®ã‚¿ã‚°ã§ã™ã€‚
+ã“ã®ã‚¿ã‚°ã¯ãƒ‘ッãƒã«é–¢å¿ƒãŒã‚ã‚‹ã¨æ€ã‚れる人é”ãŒãã®ãƒ‘ッãƒã®è­°è«–ã«å«ã¾ã‚Œã¦ã„ãŸã“ã¨
+を明文化ã—ã¾ã™ã€‚
+
+14) Reported-by 㨠Tested-by: 㨠Reviewed-by: ã®åˆ©ç”¨
+
+ä»–ã®èª°ã‹ã«ã‚ˆã£ã¦å ±å‘Šã•れãŸå•題を修正ã™ã‚‹ãƒ‘ッãƒã§ã‚れã°ã€å•題報告者ã¨ã„ã†å¯„与を
+クレジットã™ã‚‹ãŸã‚ã«ã€Reported-by: タグを追加ã™ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。
+ã“ã¾ã‚ã«ãƒã‚°å ±å‘Šè€…をクレジットã—ã¦ã„ãã“ã¨ã§ã€ã†ã¾ãã„ã‘ã°ãã®äººãŸã¡ãŒå°†æ¥å†ã³
+コミュニティã®åŠ›ã¨ãªã£ã¦ãれるã§ã—ょã†ã€‚
+ãŸã ã—ã€å ±å‘Šè€…ã®è¨±å¯ç„¡ãã“ã®ã‚¿ã‚°ã‚’追加ã—ãªã„よã†ã«æ³¨æ„ã—ã¦ãã ã•ã„。特ã«ã€
+å•題ãŒå…¬ã®å ´ã§å ±å‘Šã•れã¦ã„ãªã‹ã£ãŸã®ã§ã‚れã°ã€‚
+
+Tested-by: ã‚¿ã‚°ã¯ã‚¿ã‚°ã§æŒ‡å®šã•れãŸäººã«ã‚ˆã£ã¦(ã‚る環境下ã§)パッãƒã®ãƒ†ã‚¹ãƒˆã«æˆåŠŸ
+ã—ã¦ã„ã‚‹ã“ã¨ã‚’示ã—ã¾ã™ã€‚ã“ã®ã‚¿ã‚°ã¯ãƒ¡ãƒ³ãƒ†ãƒŠã«ãƒ†ã‚¹ãƒˆãŒå®Ÿæ–½æ¸ˆã¿ã§ã‚ã‚‹ã“ã¨ã‚’
+知らã›ã€å°†æ¥ã®é–¢é€£ãƒ‘ッãƒã®ãƒ†ã‚¹ãƒˆå”力者を見ã¤ã‘る方法をæä¾›ã—ã€ãƒ†ã‚¹ãƒˆå®Ÿæ–½è€…ã«
+対ã™ã‚‹ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã‚’ä¿è¨¼ã—ã¾ã™ã€‚
+
+Reviewed-by: ã‚¿ã‚°ã¯ã€ãれã¨ã¯ç•°ãªã‚Šã€ä¸‹è¨˜ã®ãƒ¬ãƒ“ューア宣言ã®ä¸‹ã«ãƒ¬ãƒ“ューã•れã€
+å—ã‘入れå¯èƒ½ã¨ã¿ãªã•れãŸãƒ‘ッãƒã§ã‚ã‚‹ã“ã¨ã‚’示ã—ã¾ã™ã€‚
+
+ レビューアã«ã‚ˆã‚‹ç›£ç£å®£è¨€
+
+ ç§ã¯ Reviewed-by: ã‚¿ã‚°ã‚’æç¤ºã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€ä»¥ä¸‹ã®ã“ã¨ã‚’明言ã™ã‚‹ã€‚
+
+ (a) ç§ã¯ãƒ¡ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³ã‚«ãƒ¼ãƒãƒ«ã¸ã®çµ±åˆã«å‘ã‘ã€ãã®å¦¥å½“性åŠã³ã€Œå³å¿œæ€§
+ (訳注)ã€ã‚’検証ã—ã€æŠ€è¡“çš„å´é¢ã‹ã‚‰ãƒ‘ッãƒã‚’レビュー済ã¿ã§ã‚る。
+
+ 訳注:
+ 「å³å¿œæ€§ã€ã®åŽŸæ–‡ã¯ "readiness"。
+ パッãƒãŒå分ãªå“質をæŒã£ã¦ãŠã‚Šã€ãƒ¡ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³ã‚«ãƒ¼ãƒãƒ«ã¸ã®çµ±åˆã‚’å³åº§ã«
+ 行ã†ã“ã¨ãŒã§ãる状態ã§ã‚ã‚‹ã‹ã©ã†ã‹ã‚’ "readiness" ã¨ã„ã†å˜èªžã§è¡¨ç¾
+ ã—ã¦ã„る。
+
+ (b) パッãƒã«é–¢ã™ã‚‹ã‚らゆるå•é¡Œã€æ‡¸å¿µã€ã‚ã‚‹ã„ã¯ã€ç–‘å•ã¯æŠ•ç¨¿è€…ã¸ä¼é”済ã¿
+ ã§ã‚る。ç§ã¯ãれらã®ã‚³ãƒ¡ãƒ³ãƒˆã«å¯¾ã™ã‚‹æŠ•稿者ã®è¿”ç­”ã«æº€è¶³ã—ã¦ã„る。
+
+ (c) 投稿ã«ä¼´ã„改良ã•れるコードãŒã‚る一方ã§ã€ç¾æ™‚点ã§ã€ç§ã¯(1)ãれãŒ
+ カーãƒãƒ«ã«ã¨ã£ã¦ä¾¡å€¤ã®ã‚る変更ã§ã‚ã‚‹ã“ã¨ã€ãã—ã¦ã€(2)çµ±åˆã«éš›ã—ã¦
+ è­°è«–ã«ãªã‚Šå¾—るよã†ãªå•題ã¯ãªã„ã‚‚ã®ã¨ç¢ºä¿¡ã—ã¦ã„る。
+
+ (d) ç§ã¯ãƒ‘ッãƒã‚’レビューã—é©åˆ‡ã§ã‚ã‚‹ã¨ç¢ºä¿¡ã—ã¦ã„る一方ã§ã€ã‚らゆる
+ 状æ³ã«ãŠã„ã¦ãã®å®£è¨€ã—ãŸç›®çš„ã‚„æ©Ÿèƒ½ãŒæ­£ã—ã実ç¾ã™ã‚‹ã“ã¨ã«é–¢ã—ã¦ã€
+ ã„ã‹ãªã‚‹ä¿è¨¼ã‚‚ã—ãªã„(特ã«ã©ã“ã‹ã§æ˜Žç¤ºã—ãªã„é™ã‚Š)。
+
+Reviewd-by ã‚¿ã‚°ã¯ãã®ãƒ‘ッãƒãŒã‚«ãƒ¼ãƒãƒ«ã«å¯¾ã—ã¦é©åˆ‡ãªä¿®æ­£ã§ã‚ã£ã¦ã€æ·±åˆ»ãªæŠ€è¡“çš„
+å•題を残ã—ã¦ã„ãªã„ã¨ã„ã†æ„見ã®å®£è¨€ã§ã™ã€‚興味ã®ã‚るレビューアã¯èª°ã§ã‚‚(レビュー
+作業を終ãˆãŸã‚‰)パッãƒã«å¯¾ã—㦠Reviewed-by ã‚¿ã‚°ã‚’æç¤ºã§ãã¾ã™ã€‚ã“ã®ã‚¿ã‚°ã¯
+レビューアã®å¯„与をクレジットã™ã‚‹åƒãã€ãƒ¬ãƒ“ューã®é€²æ—ã®åº¦åˆã„をメンテナã«
+知らã›ã‚‹åƒãã‚’æŒã¡ã¾ã™ã€‚ãã®ãƒ‘ッãƒã®é ˜åŸŸã«è©³ã—ãã€ãã—ã¦ã€ã—ã£ã‹ã‚Šã¨ã—ãŸ
+レビューを実施ã—ãŸãƒ¬ãƒ“ューアã«ã‚ˆã£ã¦æä¾›ã•れる時ã€Reviewed-by: ã‚¿ã‚°ãŒã‚ãªãŸã®
+パッãƒã‚’カーãƒãƒ«ã«ãƒžãƒ¼ã‚¸ã™ã‚‹å¯èƒ½æ€§ã‚’高ã‚ã‚‹ã§ã—ょã†ã€‚
+
+15) 標準的ãªãƒ‘ッãƒã®ãƒ•ォーマット
標準的ãªãƒ‘ッãƒã®ã‚µãƒ–ジェクトã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šã§ã™ã€‚
@@ -396,18 +501,37 @@ Acked-by: ãŒå¿…ãšã—もパッãƒå…¨ä½“ã®æ‰¿èªã‚’示ã—ã¦ã„ã‚‹ã‚ã‘ã§ã¯ã
é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µãƒ–ジェクト内ã®ã‚µãƒ–システム表記ã¯ã€ãƒ‘ッãƒãŒé©ç”¨ã•れる
分野ã¾ãŸã¯ã‚µãƒ–システムを識別ã§ãるよã†ã«ã™ã¹ãã§ã™ã€‚
-é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µãƒ–ジェクトã®ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ã¯ãã®ãƒ‘ッãƒã®æ¦‚è¦ã‚’正確
-ã«è¡¨ç¾ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。「概è¦ã®è¨€ã„回ã—ã€ã‚’ファイルåã«ã—ã¦ã¯ã„
-ã‘ã¾ã›ã‚“。一連ã®ãƒ‘ッãƒä¸­ã§ãれãžã‚Œã®ãƒ‘ッãƒã¯åŒã˜ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ã‚’
-使ã£ã¦ã¯ã„ã‘ã¾ã›ã‚“(「一連ã®ãƒ‘ッãƒã€ã¨ã¯é †åºä»˜ã‘られãŸé–¢é€£ã®ã‚る複数ã®
+é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µãƒ–ジェクトã®ã€Œsummary phraseã€ã¯ãã®ãƒ‘ッãƒã®æ¦‚è¦ã‚’正確
+ã«è¡¨ç¾ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。「summary phraseã€ã‚’ファイルåã«ã—ã¦ã¯ã„
+ã‘ã¾ã›ã‚“。パッãƒã‚·ãƒªãƒ¼ã‚ºä¸­ã§ãれãžã‚Œã®ãƒ‘ッãƒã¯åŒã˜ã€Œsummary phraseã€ã‚’
+使ã£ã¦ã¯ã„ã‘ã¾ã›ã‚“(「パッãƒã‚·ãƒªãƒ¼ã‚ºã€ã¨ã¯é †åºä»˜ã‘られãŸé–¢é€£ã®ã‚る複数ã®
パッãƒç¾¤ã§ã™)。
-ã‚ãªãŸã®é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ãŒãã®ãƒ‘ッãƒã«ã¨ã£ã¦ä¸–界ã§å”¯
-一ã®è­˜åˆ¥å­ã«ãªã‚‹ã‚ˆã†ã«å¿ƒãŒã‘ã¦ãã ã•ã„。「概è¦ã®è¨€ã„回ã—ã€ã¯ git ã®
-ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã®ä¸­ã¸ãšã£ã¨ä¼æ’­ã—ã¦ã„ãã¾ã™ã€‚「概è¦ã®è¨€ã„回ã—ã€ã¯ã€é–‹
-発者ãŒå¾Œã§ãƒ‘ッãƒã‚’å‚ç…§ã™ã‚‹ãŸã‚ã«è­°è«–ã®ä¸­ã§åˆ©ç”¨ã™ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。
-人々ã¯ãã®ãƒ‘ッãƒã«é–¢é€£ã—ãŸè­°è«–を読むãŸã‚ã«ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ã‚’使ã£ã¦
-google ã§æ¤œç´¢ã—ãŸãŒã‚‹ã§ã—ょã†ã€‚
+ã‚ãªãŸã®é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã€Œsummary phraseã€ãŒãã®ãƒ‘ッãƒã«ã¨ã£ã¦ä¸–界ã§å”¯ä¸€ã®è­˜åˆ¥å­ã«
+ãªã‚‹ã‚ˆã†ã«å¿ƒãŒã‘ã¦ãã ã•ã„。「summary phraseã€ã¯ git ã®ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã®ä¸­ã¸
+ãšã£ã¨ä¼æ’­ã—ã¦ã„ãã¾ã™ã€‚「summary phraseã€ã¯ã€é–‹ç™ºè€…ãŒå¾Œã§ãƒ‘ッãƒã‚’å‚ç…§ã™ã‚‹
+ãŸã‚ã«è­°è«–ã®ä¸­ã§åˆ©ç”¨ã™ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。
+人々ã¯ãã®ãƒ‘ッãƒã«é–¢é€£ã—ãŸè­°è«–を読むãŸã‚ã«ã€Œsummary phraseã€ã‚’使ã£ã¦ google ã§
+検索ã—ãŸãŒã‚‹ã§ã—ょã†ã€‚ãれã¯ã¾ãŸ2ã€3ヶ月ã‚ã¨ã§ã€äººã€…ãŒã€Œgitkã€ã‚„
+「git log --onelineã€ã®ã‚ˆã†ãªãƒ„ールを使用ã—ã¦ä½•åƒã‚‚ã®ãƒ‘ッãƒã«ç›®ã‚’é€šã™æ™‚ã€
+唯一目ã«ã¨ã¾ã‚‹æƒ…å ±ã¨ãªã‚‹ã§ã—ょã†ã€‚
+
+ã“れらã®ç†ç”±ã®ãŸã‚ã€ã€Œsummary phraseã€ã¯ãªãœãƒ‘ッãƒãŒå¿…è¦ã§ã‚ã‚‹ã‹ã€ãƒ‘ッãƒãŒä½•ã‚’
+変更ã™ã‚‹ã‹ã®2ã¤ã®æƒ…報をã›ã„ãœã„70〜75文字ã§è¡¨ç¾ã—ã¦ã„ãªã‘れã°ãªã‚Šã¾ã›ã‚“。
+「summary phraseã€ã¯ç°¡æ½”ã§ã‚り説明的ã§ã‚る表ç¾ã‚’目指ã—ã¤ã¤ã€ã†ã¾ã
+ã¾ã¨ã‚られã¦ã„る概è¦ã¨ãªã‚‹ã¹ãã§ã™ã€‚
+
+「summary phraseã€ã¯ã€ŒSubject: [PATCH tag] <summary phrase>ã€ã®ã‚ˆã†ã«ã€
+大括弧ã§é–‰ã˜ã‚‰ã‚ŒãŸã‚¿ã‚°ã‚’接頭辞ã¨ã—ã¦ä»˜åŠ ã—ã¦ã‚‚ã‹ã¾ã„ã¾ã›ã‚“。ã“ã®ã‚¿ã‚°ã¯
+「summary phraseã€ã®ä¸€éƒ¨ã¨ã¯è€ƒãˆã¾ã›ã‚“ãŒã€ãƒ‘ッãƒã‚’ã©ã®ã‚ˆã†ã«å–り扱ã†ã¹ãã‹ã‚’
+表ç¾ã—ã¾ã™ã€‚
+一般的ã«ã¯ã€Œv1, v2, v3ã€ã®ã‚ˆã†ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を表ã™ã‚¿ã‚°(éŽåŽ»ã®ãƒ‘ッãƒã«å¯¾ã™ã‚‹
+ã‚³ãƒ¡ãƒ³ãƒˆã‚’åæ˜ ã™ã‚‹ãŸã‚ã«è¤‡æ•°ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒ‘ッãƒãŒæŠ•稿ã•れã¦ã„ã‚‹ã®ã§ã‚れã°)ã€
+「RFCã€ã®ã‚ˆã†ãªã‚³ãƒ¡ãƒ³ãƒˆã‚’è¦æ±‚ã™ã‚‹ã‚¿ã‚°ãŒæŒ™ã’られã¾ã™ã€‚パッãƒã‚·ãƒªãƒ¼ã‚ºã¨ã—ã¦4ã¤ã®
+パッãƒãŒã‚れã°ã€å€‹ã€…ã®ãƒ‘ッãƒã«ã€Œ1/4, 2/4, 3/4, 4/4ã€ã®ã‚ˆã†ã«ç•ªå·ã‚’付ã‘ã¦ã‚‚
+ã‹ã¾ã„ã¾ã›ã‚“。ã“れã¯é–‹ç™ºè€…ãŒãƒ‘ッãƒã‚’é©ç”¨ã™ã‚‹é †ç•ªã‚’ç¢ºå®Ÿã«æŠŠæ¡ã™ã‚‹ãŸã‚ã§ã™ã€‚
+ãã—ã¦ã€é–‹ç™ºè€…ãŒãƒ‘ッãƒã‚·ãƒªãƒ¼ã‚ºã®ä¸­ã®ã™ã¹ã¦ã®ãƒ‘ッãƒã‚’もらã•ãšãƒ¬ãƒ“ュー或ã„ã¯
+é©ç”¨ã™ã‚‹ã®ã‚’ä¿è¨¼ã™ã‚‹ãŸã‚ã§ã™ã€‚
サブジェクトã®ä¾‹ã‚’二ã¤
@@ -426,7 +550,12 @@ google ã§æ¤œç´¢ã—ãŸãŒã‚‹ã§ã—ょã†ã€‚
説明本体ã¯ç„¡æœŸé™ã®ã‚½ãƒ¼ã‚¹ã®ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã«ã‚³ãƒŸãƒƒãƒˆã•れã¾ã™ã€‚ãªã®ã§ã€èª¬æ˜Ž
本体ã¯ãã®ãƒ‘ッãƒã«è‡³ã£ãŸè­°è«–ã®è©³ç´°ã‚’忘れã¦ã„ã‚‹ã‚ã‚‹ç¨‹åº¦ã®æŠ€é‡ã‚’æŒã£ã¦ã„る人
-ãŒãã®è©³ç´°ã‚’æ€ã„出ã™ã“ã¨ãŒã§ãã‚‹ã‚‚ã®ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。
+ãŒãã®è©³ç´°ã‚’æ€ã„出ã™ã“ã¨ãŒã§ãã‚‹ã‚‚ã®ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。パッãƒãŒå¯¾å‡¦ã™ã‚‹
+障害ã®ç—‡çж(カーãƒãƒ«ãƒ­ã‚°ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚„ oops メッセージ等)を記載ã™ã‚‹ã“ã¨ã¯å•題ã«
+対処å¯èƒ½ãªãƒ‘ッãƒã‚’求ã‚ã¦ã‚³ãƒŸãƒƒãƒˆãƒ­ã‚°ã‚’検索ã™ã‚‹äººã€…ã«ã¨ã£ã¦ç‰¹ã«æœ‰ç”¨ã§ã™ã€‚
+パッãƒãŒã‚³ãƒ³ãƒ‘イルå•題を解決ã™ã‚‹ã®ã§ã‚れã°ã€ãã®ãƒ‘ッãƒã‚’探ã—ã¦ã„る人ãŒè¦‹ã¤ã‘ã‚‹
+ã“ã¨ãŒã§ãる情報ã ã‘ã§å分ã§ã‚りã€ã‚³ãƒ³ãƒ‘イル時ã®å…¨ã¦ã®ã‚¨ãƒ©ãƒ¼ã‚’å«ã‚ã‚‹å¿…è¦ã¯
+ã‚りã¾ã›ã‚“。「summary phraseã€ã¨åŒæ§˜ã«ã€ç°¡æ½”ã§ã‚り説明的ã§ã‚ã‚‹ã“ã¨ãŒé‡è¦ã§ã™ã€‚
「 --- ã€ãƒžãƒ¼ã‚«ãƒ¼è¡Œã¯ãƒ‘ッãƒå‡¦ç†ãƒ„ールã«å¯¾ã—ã¦ã€ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®çµ‚端
部分をèªè­˜ã•ã›ã‚‹ã¨ã„ã†é‡è¦ãªå½¹ç›®ã‚’æžœãŸã—ã¾ã™ã€‚
@@ -436,14 +565,46 @@ google ã§æ¤œç´¢ã—ãŸãŒã‚‹ã§ã—ょã†ã€‚
追加ã•れ何行消ã•れãŸã‹ã‚’示ã™ã‚‚ã®ã§ã™ã€‚diffstat コマンドã¯ç‰¹ã«å¤§ããªãƒ‘ッãƒã«
ãŠã„ã¦å½¹ç«‹ã¡ã¾ã™ã€‚ãã®æ™‚点ã§ã ã‘åˆã¯ãƒ¡ãƒ³ãƒ†ãƒŠã«ã¨ã£ã¦ã®ã¿é–¢ä¿‚ã®ã‚るコメント
ã¯ç„¡æœŸé™ã«ä¿å­˜ã•れるãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã«ã¨ã£ã¦é©åˆ‡ã§ã¯ã‚りã¾ã›ã‚“。ãã®ãŸã‚ã€ã“ã®
-よã†ãªã‚³ãƒ¡ãƒ³ãƒˆã‚‚マーカー行ã®å¾Œã«æ›¸ã‹ã‚Œã‚‹ã¹ãã§ã™ã€‚ファイルåã¯ã‚«ãƒ¼ãƒãƒ«ã‚½ãƒ¼
-スツリーã®ãƒˆãƒƒãƒ—ディレクトリã‹ã‚‰ã®è¡¨è¨˜ã§ãƒªã‚¹ãƒˆã•れるãŸã‚ã€æ¨ªæ–¹å‘ã®ã‚¹ãƒšãƒ¼ã‚¹
-ã‚’ã¨ã‚ŠéŽãŽãªã„よã†ã«ã€diffstat コマンドã«ã‚ªãƒ—ション「 -p 1 -w 70 ã€ã‚’指定ã—
-ã¦ãã ã•ã„(インデントをå«ã‚ã¦ã¡ã‚‡ã†ã©80列ã«åˆã†ã§ã—ょã†)。
+よã†ãªã‚³ãƒ¡ãƒ³ãƒˆã‚‚マーカー行ã®å¾Œã«æ›¸ã‹ã‚Œã‚‹ã¹ãã§ã™ã€‚
+ã“ã®ã‚ˆã†ãªã‚³ãƒ¡ãƒ³ãƒˆã®è‰¯ã„例ã¨ã—ã¦ã€v1 㨠v2 ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³é–“ã§ä½•ãŒå¤‰æ›´ã•れãŸã‹ã‚’
+表ã™ã€Œãƒ‘ッãƒã®å¤‰æ›´å±¥æ­´ã€ãŒæŒ™ã’られã¾ã™ã€‚
+
+「 --- ã€ãƒžãƒ¼ã‚«ãƒ¼è¡Œã®å¾Œã« diffstat コマンドã®çµæžœã‚’å«ã‚ã‚‹ã®ã§ã‚れã°ã€ãƒ•ァイル
+åã¯ã‚«ãƒ¼ãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã®ãƒˆãƒƒãƒ—ディレクトリã‹ã‚‰ã®è¡¨è¨˜ã§åˆ—記ã•れるãŸã‚ã€æ¨ªæ–¹å‘
+ã®ã‚¹ãƒšãƒ¼ã‚¹ã‚’ã¨ã‚ŠéŽãŽãªã„よã†ã«ã€diffstat コマンドã«ã‚ªãƒ—ション「 -p 1 -w 70 ã€
+を指定ã—ã¦ãã ã•ã„(インデントをå«ã‚ã¦ã¡ã‚‡ã†ã©80列ã«åˆã†ã§ã—ょã†)。
é©åˆ‡ãªãƒ‘ッãƒã®ãƒ•ォーマットã®è©³ç´°ã«ã¤ã„ã¦ã¯ã‚»ã‚¯ã‚·ãƒ§ãƒ³3ã®å‚考文献をå‚ç…§ã—ã¦
ãã ã•ã„。
+16) 「git pullã€è¦æ±‚ã®é€ã‚Šæ–¹(Linus ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‹ã‚‰)
+
+é–“é•ã£ãŸãƒ–ランãƒã‹ã‚‰å¼•ã£å¼µã‚‹ã®ã‚’防ããŸã‚ã«ã€git リãƒã‚¸ãƒˆãƒªã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨
+ブランãƒåã‚’åŒã˜è¡Œã«1行ã§è¨˜è¼‰ã—ã¦ãã ã•ã„。ãã†ã™ã‚‹ã“ã¨ã§ã€3回ã®é€£ç¶šã‚¯ãƒªãƒƒã‚¯
+ã§å…¨ã¦é¸æŠžã§ãã¾ã™ã€‚
+
+æ­£ã—ã„å½¢å¼ã¯ä¸‹è¨˜ã®é€šã‚Šã§ã™ã€‚
+
+ "Please pull from
+
+ git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+ to get these changes:"
+
+ãã®çµæžœã€ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’自分自身ã§ã‚¿ã‚¤ãƒ”ングã—ã¦é–“é•ãˆã‚‹ã“ã¨ã¯ãªããªã‚Šã¾ã™(実際ã«ã€
+何度ã‹é–“é•ã£ãŸãƒ–ランãƒã‹ã‚‰å¼•ã£å¼µã£ã¦ãã¦ã—ã¾ã„ã€ãã®æ™‚ã« diffstat ã®çµæžœã‚’
+検証ã—ã¦é–“é•ã£ã¦ã„ã‚‹ã“ã¨ã«æ°—ã¥ã„ãŸã“ã¨ãŒã‚りã¾ã™ã€‚ã©ã“ã‹ã‚‰ä½•を引ã£å¼µã‚‹ã¹ãã‹ã‚’
+「探ã—ãŸã‚Šã€ã€æ­£ã—ã„ブランãƒåã‹ã©ã†ã‹ã‚’é‡ã­ã¦ãƒã‚§ãƒƒã‚¯ã—ãŸã‚Šã™ã‚‹å¿…è¦ãŒ
+ãªããªã‚Œã°ã‚ˆã‚Šå¿«é©ã«ãªã‚‹ã§ã—ょã†)。
+
+diffstat ã®çµæžœã‚’生æˆã™ã‚‹ãŸã‚ã«ã€Œ git diff -M --stat --summary ã€ã‚’使ã£ã¦
+ãã ã•ã„。-M オプションã¯ãƒ•ァイルåã®å¤‰æ›´ã‚’検知ã§ãã€--summary オプションã¯
+æ–°è¦ãƒ•ァイルã€å‰Šé™¤ã•れãŸãƒ•ァイルã€åå‰ãŒå¤‰æ›´ã•れãŸãƒ•ã‚¡ã‚¤ãƒ«ã®æ¦‚è¦ã‚’生æˆã—ã¾ã™ã€‚
+
+-M オプション(ファイルåã®å¤‰æ›´æ¤œçŸ¥)を指定ã™ã‚‹ã¨ã€diffstat ã®çµæžœã¯ã‹ãªã‚Š
+ç•°ãªã£ã¦ãã¾ã™ã€‚git ã¯å¤§è¦æ¨¡ãªå¤‰æ›´(追加ã¨å‰Šé™¤ã®ãƒšã‚¢)をファイルåã®å¤‰æ›´ã¨
+判断ã™ã‚‹ãŸã‚ã§ã™ã€‚
+
------------------------------------
セクション2 - ヒントã¨TIPSã¨å°æŠ€
------------------------------------
@@ -459,7 +620,7 @@ google ã§æ¤œç´¢ã—ãŸãŒã‚‹ã§ã—ょã†ã€‚
も逸脱ã—ã¦ã„ã‚‹ã¨ã€ãƒ¬ãƒ“ューやコメントãªã—ã«å—ã‘å–ã£ã¦ã‚‚らãˆãªã„ã‹ã‚‚ã—
れã¾ã›ã‚“。
-唯一ã®ç‰¹ç­†ã™ã¹ã例外ã¯ã€ã‚³ãƒ¼ãƒ‰ã‚’ã‚るファイルã‹ã‚‰åˆ¥ã®ãƒ•ァイルã«ç§»å‹•
+特筆ã™ã¹ã例外ã¯ã€ã‚³ãƒ¼ãƒ‰ã‚’ã‚るファイルã‹ã‚‰åˆ¥ã®ãƒ•ァイルã«ç§»å‹•
ã™ã‚‹ã¨ãã§ã™ã€‚ã“ã®å ´åˆã€ã‚³ãƒ¼ãƒ‰ã‚’移動ã™ã‚‹ãƒ‘ッãƒã§ã¯ã€ç§»å‹•ã•れるコード
ã«é–¢ã—ã¦ç§»å‹•以外ã®å¤‰æ›´ã‚’一切加ãˆã‚‹ã¹ãã§ã¯ã‚りã¾ã›ã‚“。ã“れã«ã‚ˆã‚Šã€
コードã®ç§»å‹•ã¨ã‚ãªãŸãŒè¡Œã£ãŸã‚³ãƒ¼ãƒ‰ã®ä¿®æ­£ã‚’明確ã«åŒºåˆ¥ã§ãるよã†ã«ãª
@@ -553,4 +714,11 @@ Kernel Documentation/CodingStyle:
Linus Torvalds's mail on the canonical patch format:
<http://lkml.org/lkml/2005/4/7/183>
+
+Andi Kleen, "On submitting kernel patches"
+ Some strategies to get difficult or controversial changes in.
+ http://halobates.de/on-submitting-patches.pdf
+
--
+
+
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 47435e56c5da..f47cdefb4d1e 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -441,7 +441,7 @@ more details, with real examples.
specified if first option are not supported.
Example:
- #arch/i386/kernel/Makefile
+ #arch/x86/kernel/Makefile
vsyscall-flags += $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
In the above example, vsyscall-flags will be assigned the option
@@ -460,7 +460,7 @@ more details, with real examples.
supported to use an optional second option.
Example:
- #arch/i386/Makefile
+ #arch/x86/Makefile
cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
In the above example, cflags-y will be assigned the option
@@ -522,7 +522,7 @@ more details, with real examples.
even though the option was accepted by gcc.
Example:
- #arch/i386/Makefile
+ #arch/x86/Makefile
cflags-y += $(shell \
if [ $(call cc-version) -ge 0300 ] ; then \
echo "-mregparm=3"; fi ;)
@@ -802,7 +802,7 @@ but in the architecture makefiles where the kbuild infrastructure
is not sufficient this sometimes needs to be explicit.
Example:
- #arch/i386/boot/Makefile
+ #arch/x86/boot/Makefile
subdir- := compressed/
The above assignment instructs kbuild to descend down in the
@@ -812,12 +812,12 @@ To support the clean infrastructure in the Makefiles that builds the
final bootimage there is an optional target named archclean:
Example:
- #arch/i386/Makefile
+ #arch/x86/Makefile
archclean:
- $(Q)$(MAKE) $(clean)=arch/i386/boot
+ $(Q)$(MAKE) $(clean)=arch/x86/boot
-When "make clean" is executed, make will descend down in arch/i386/boot,
-and clean as usual. The Makefile located in arch/i386/boot/ may use
+When "make clean" is executed, make will descend down in arch/x86/boot,
+and clean as usual. The Makefile located in arch/x86/boot/ may use
the subdir- trick to descend further down.
Note 1: arch/$(ARCH)/Makefile cannot use "subdir-", because that file is
@@ -882,7 +882,7 @@ When kbuild executes, the following steps are followed (roughly):
LDFLAGS_vmlinux uses the LDFLAGS_$@ support.
Example:
- #arch/i386/Makefile
+ #arch/x86/Makefile
LDFLAGS_vmlinux := -e stext
OBJCOPYFLAGS objcopy flags
@@ -920,14 +920,14 @@ When kbuild executes, the following steps are followed (roughly):
Often, the KBUILD_CFLAGS variable depends on the configuration.
Example:
- #arch/i386/Makefile
+ #arch/x86/Makefile
cflags-$(CONFIG_M386) += -march=i386
KBUILD_CFLAGS += $(cflags-y)
Many arch Makefiles dynamically run the target C compiler to
probe supported options:
- #arch/i386/Makefile
+ #arch/x86/Makefile
...
cflags-$(CONFIG_MPENTIUMII) += $(call cc-option,\
@@ -1038,8 +1038,8 @@ When kbuild executes, the following steps are followed (roughly):
into the arch/$(ARCH)/boot/Makefile.
Example:
- #arch/i386/Makefile
- boot := arch/i386/boot
+ #arch/x86/Makefile
+ boot := arch/x86/boot
bzImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
@@ -1051,7 +1051,7 @@ When kbuild executes, the following steps are followed (roughly):
To support this, $(archhelp) must be defined.
Example:
- #arch/i386/Makefile
+ #arch/x86/Makefile
define archhelp
echo '* bzImage - Image (arch/$(ARCH)/boot/bzImage)'
endif
@@ -1065,7 +1065,7 @@ When kbuild executes, the following steps are followed (roughly):
from vmlinux.
Example:
- #arch/i386/Makefile
+ #arch/x86/Makefile
all: bzImage
When "make" is executed without arguments, bzImage will be built.
@@ -1083,7 +1083,7 @@ When kbuild executes, the following steps are followed (roughly):
2) kbuild knows what files to delete during "make clean"
Example:
- #arch/i386/kernel/Makefile
+ #arch/x86/kernel/Makefile
extra-y := head.o init_task.o
In this example, extra-y is used to list object files that
@@ -1133,7 +1133,7 @@ When kbuild executes, the following steps are followed (roughly):
Compress target. Use maximum compression to compress target.
Example:
- #arch/i386/boot/Makefile
+ #arch/x86/boot/Makefile
LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext
@@ -1193,7 +1193,7 @@ When kbuild executes, the following steps are followed (roughly):
When updating the $(obj)/bzImage target, the line
- BUILD arch/i386/boot/bzImage
+ BUILD arch/x86/boot/bzImage
will be displayed with "make KBUILD_VERBOSE=0".
@@ -1207,7 +1207,7 @@ When kbuild executes, the following steps are followed (roughly):
kbuild knows .lds files and includes a rule *lds.S -> *lds.
Example:
- #arch/i386/kernel/Makefile
+ #arch/x86/kernel/Makefile
always := vmlinux.lds
#Makefile
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index aa47be71df4c..4ca93898fbd3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1159,10 +1159,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
for all guests.
Default is 1 (enabled) if in 64bit or 32bit-PAE mode
- kvm-intel.bypass_guest_pf=
- [KVM,Intel] Disables bypassing of guest page faults
- on Intel chips. Default is 1 (enabled)
-
kvm-intel.ept= [KVM,Intel] Disable extended page tables
(virtualized MMU) support on capable Intel chips.
Default is 1 (enabled)
@@ -1737,6 +1733,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
no-kvmapf [X86,KVM] Disable paravirtualized asynchronous page
fault handling.
+ no-steal-acc [X86,KVM] Disable paravirtualized steal time accounting.
+ steal time is computed, but won't influence scheduler
+ behaviour
+
nolapic [X86-32,APIC] Do not enable or use the local APIC.
nolapic_timer [X86-32,APIC] Do not use the local APIC timer.
@@ -1846,7 +1846,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
See Documentation/sound/oss/oss-parameters.txt
panic= [KNL] Kernel behaviour on panic: delay <timeout>
- seconds before rebooting
+ timeout > 0: seconds before rebooting
+ timeout = 0: wait forever
+ timeout < 0: reboot immediately
Format: <timeout>
parkbd.port= [HW] Parallel port number the keyboard adapter is
@@ -2526,6 +2528,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
<port#>,<js1>,<js2>,<js3>,<js4>,<js5>,<js6>,<js7>
See also Documentation/input/joystick-parport.txt
+ udbg-immortal [PPC] When debugging early kernel crashes that
+ happen after console_init() and before a proper
+ console driver takes over, this boot options might
+ help "seeing" what's going on.
+
uhash_entries= [KNL,NET]
Set number of hash buckets for UDP/UDP-Lite connections
@@ -2540,6 +2547,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
unknown_nmi_panic
[X86] Cause panic on unknown NMI.
+ usbcore.authorized_default=
+ [USB] Default USB device authorization:
+ (default -1 = authorized except for wireless USB,
+ 0 = not authorized, 1 = authorized)
+
usbcore.autosuspend=
[USB] The autosuspend time delay (in seconds) used
for newly-detected USB devices (default 2). This
diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
index 4b12abcb2ad3..abf481f780ec 100644
--- a/Documentation/magic-number.txt
+++ b/Documentation/magic-number.txt
@@ -66,7 +66,7 @@ MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h
RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h
SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h
HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c
-APM_BIOS_MAGIC 0x4101 apm_user arch/i386/kernel/apm.c
+APM_BIOS_MAGIC 0x4101 apm_user arch/x86/kernel/apm_32.c
CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h
DB_MAGIC 0x4442 fc_info drivers/net/iph5526_novram.c
DL_MAGIC 0x444d fc_info drivers/net/iph5526_novram.c
diff --git a/Documentation/mca.txt b/Documentation/mca.txt
index 510375d4209a..dfd130c2207d 100644
--- a/Documentation/mca.txt
+++ b/Documentation/mca.txt
@@ -11,7 +11,7 @@ Adapter Detection
The ideal MCA adapter detection is done through the use of the
Programmable Option Select registers. Generic functions for doing
-this have been added in include/linux/mca.h and arch/i386/kernel/mca.c.
+this have been added in include/linux/mca.h and arch/x86/kernel/mca_32.c.
Everything needed to detect adapters and read (and write) configuration
information is there. A number of MCA-specific drivers already use
this. The typical probe code looks like the following:
@@ -81,7 +81,7 @@ more people use shared IRQs on PCI machines.
In general, an interrupt must be acknowledged not only at the ICU (which
is done automagically by the kernel), but at the device level. In
particular, IRQ 0 must be reset after a timer interrupt (now done in
-arch/i386/kernel/time.c) or the first timer interrupt hangs the system.
+arch/x86/kernel/time.c) or the first timer interrupt hangs the system.
There were also problems with the 1.3.x floppy drivers, but that seems
to have been fixed.
diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX
index 93dd7a714075..a9ba6720ffdf 100644
--- a/Documentation/mmc/00-INDEX
+++ b/Documentation/mmc/00-INDEX
@@ -4,3 +4,5 @@ mmc-dev-attrs.txt
- info on SD and MMC device attributes
mmc-dev-parts.txt
- info on SD and MMC device partitions
+mmc-async-req.txt
+ - info on mmc asynchronous requests
diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt
new file mode 100644
index 000000000000..ae1907b10e4a
--- /dev/null
+++ b/Documentation/mmc/mmc-async-req.txt
@@ -0,0 +1,87 @@
+Rationale
+=========
+
+How significant is the cache maintenance overhead?
+It depends. Fast eMMC and multiple cache levels with speculative cache
+pre-fetch makes the cache overhead relatively significant. If the DMA
+preparations for the next request are done in parallel with the current
+transfer, the DMA preparation overhead would not affect the MMC performance.
+The intention of non-blocking (asynchronous) MMC requests is to minimize the
+time between when an MMC request ends and another MMC request begins.
+Using mmc_wait_for_req(), the MMC controller is idle while dma_map_sg and
+dma_unmap_sg are processing. Using non-blocking MMC requests makes it
+possible to prepare the caches for next job in parallel with an active
+MMC request.
+
+MMC block driver
+================
+
+The mmc_blk_issue_rw_rq() in the MMC block driver is made non-blocking.
+The increase in throughput is proportional to the time it takes to
+prepare (major part of preparations are dma_map_sg() and dma_unmap_sg())
+a request and how fast the memory is. The faster the MMC/SD is the
+more significant the prepare request time becomes. Roughly the expected
+performance gain is 5% for large writes and 10% on large reads on a L2 cache
+platform. In power save mode, when clocks run on a lower frequency, the DMA
+preparation may cost even more. As long as these slower preparations are run
+in parallel with the transfer performance won't be affected.
+
+Details on measurements from IOZone and mmc_test
+================================================
+
+https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req
+
+MMC core API extension
+======================
+
+There is one new public function mmc_start_req().
+It starts a new MMC command request for a host. The function isn't
+truly non-blocking. If there is an ongoing async request it waits
+for completion of that request and starts the new one and returns. It
+doesn't wait for the new request to complete. If there is no ongoing
+request it starts the new request and returns immediately.
+
+MMC host extensions
+===================
+
+There are two optional members in the mmc_host_ops -- pre_req() and
+post_req() -- that the host driver may implement in order to move work
+to before and after the actual mmc_host_ops.request() function is called.
+In the DMA case pre_req() may do dma_map_sg() and prepare the DMA
+descriptor, and post_req() runs the dma_unmap_sg().
+
+Optimize for the first request
+==============================
+
+The first request in a series of requests can't be prepared in parallel
+with the previous transfer, since there is no previous request.
+The argument is_first_req in pre_req() indicates that there is no previous
+request. The host driver may optimize for this scenario to minimize
+the performance loss. A way to optimize for this is to split the current
+request in two chunks, prepare the first chunk and start the request,
+and finally prepare the second chunk and start the transfer.
+
+Pseudocode to handle is_first_req scenario with minimal prepare overhead:
+
+if (is_first_req && req->size > threshold)
+ /* start MMC transfer for the complete transfer size */
+ mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE);
+
+ /*
+ * Begin to prepare DMA while cmd is being processed by MMC.
+ * The first chunk of the request should take the same time
+ * to prepare as the "MMC process command time".
+ * If prepare time exceeds MMC cmd time
+ * the transfer is delayed, guesstimate max 4k as first chunk size.
+ */
+ prepare_1st_chunk_for_dma(req);
+ /* flush pending desc to the DMAC (dmaengine.h) */
+ dma_issue_pending(req->dma_desc);
+
+ prepare_2nd_chunk_for_dma(req);
+ /*
+ * The second issue_pending should be called before MMC runs out
+ * of the first chunk. If the MMC runs out of the first data chunk
+ * before this call, the transfer is delayed.
+ */
+ dma_issue_pending(req->dma_desc);
diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
index 2bac9618c345..65968fbf1e49 100644
--- a/Documentation/networking/ifenslave.c
+++ b/Documentation/networking/ifenslave.c
@@ -260,7 +260,7 @@ int main(int argc, char *argv[])
case 'V': opt_V++; exclusive++; break;
case '?':
- fprintf(stderr, usage_msg);
+ fprintf(stderr, "%s", usage_msg);
res = 2;
goto out;
}
@@ -268,13 +268,13 @@ int main(int argc, char *argv[])
/* options check */
if (exclusive > 1) {
- fprintf(stderr, usage_msg);
+ fprintf(stderr, "%s", usage_msg);
res = 2;
goto out;
}
if (opt_v || opt_V) {
- printf(version);
+ printf("%s", version);
if (opt_V) {
res = 0;
goto out;
@@ -282,14 +282,14 @@ int main(int argc, char *argv[])
}
if (opt_u) {
- printf(usage_msg);
+ printf("%s", usage_msg);
res = 0;
goto out;
}
if (opt_h) {
- printf(usage_msg);
- printf(help_msg);
+ printf("%s", usage_msg);
+ printf("%s", help_msg);
res = 0;
goto out;
}
@@ -309,7 +309,7 @@ int main(int argc, char *argv[])
goto out;
} else {
/* Just show usage */
- fprintf(stderr, usage_msg);
+ fprintf(stderr, "%s", usage_msg);
res = 2;
goto out;
}
@@ -320,7 +320,7 @@ int main(int argc, char *argv[])
master_ifname = *spp++;
if (master_ifname == NULL) {
- fprintf(stderr, usage_msg);
+ fprintf(stderr, "%s", usage_msg);
res = 2;
goto out;
}
@@ -339,7 +339,7 @@ int main(int argc, char *argv[])
if (slave_ifname == NULL) {
if (opt_d || opt_c) {
- fprintf(stderr, usage_msg);
+ fprintf(stderr, "%s", usage_msg);
res = 2;
goto out;
}
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index bfe924217f24..db2a4067013c 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -106,16 +106,6 @@ inet_peer_maxttl - INTEGER
when the number of entries in the pool is very small).
Measured in seconds.
-inet_peer_gc_mintime - INTEGER
- Minimum interval between garbage collection passes. This interval is
- in effect under high memory pressure on the pool.
- Measured in seconds.
-
-inet_peer_gc_maxtime - INTEGER
- Minimum interval between garbage collection passes. This interval is
- in effect under low (or absent) memory pressure on the pool.
- Measured in seconds.
-
TCP variables:
somaxconn - INTEGER
@@ -394,7 +384,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
min: Minimal size of receive buffer used by TCP sockets.
It is guaranteed to each TCP socket, even under moderate memory
pressure.
- Default: 8K
+ Default: 1 page
default: initial size of receive buffer used by TCP sockets.
This value overrides net.core.rmem_default used by other protocols.
@@ -483,7 +473,7 @@ tcp_window_scaling - BOOLEAN
tcp_wmem - vector of 3 INTEGERs: min, default, max
min: Amount of memory reserved for send buffers for TCP sockets.
Each TCP socket has rights to use it due to fact of its birth.
- Default: 4K
+ Default: 1 page
default: initial size of send buffer used by TCP sockets. This
value overrides net.core.wmem_default used by other protocols.
@@ -553,13 +543,13 @@ udp_rmem_min - INTEGER
Minimal size of receive buffer used by UDP sockets in moderation.
Each UDP socket is able to use the size for receiving data, even if
total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
- Default: 4096
+ Default: 1 page
udp_wmem_min - INTEGER
Minimal size of send buffer used by UDP sockets in moderation.
Each UDP socket is able to use the size for sending data, even if
total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
- Default: 4096
+ Default: 1 page
CIPSOv4 Variables:
@@ -1465,10 +1455,17 @@ sctp_mem - vector of 3 INTEGERs: min, pressure, max
Default is calculated at boot time from amount of available memory.
sctp_rmem - vector of 3 INTEGERs: min, default, max
- See tcp_rmem for a description.
+ Only the first value ("min") is used, "default" and "max" are
+ ignored.
+
+ min: Minimal size of receive buffer used by SCTP socket.
+ It is guaranteed to each SCTP socket (but not association) even
+ under moderate memory pressure.
+
+ Default: 1 page
sctp_wmem - vector of 3 INTEGERs: min, default, max
- See tcp_wmem for a description.
+ Currently this tunable has no effect.
addr_scope_policy - INTEGER
Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00
diff --git a/Documentation/networking/netdev-features.txt b/Documentation/networking/netdev-features.txt
new file mode 100644
index 000000000000..4b1c0dcef84c
--- /dev/null
+++ b/Documentation/networking/netdev-features.txt
@@ -0,0 +1,154 @@
+Netdev features mess and how to get out from it alive
+=====================================================
+
+Author:
+ Michał Mirosław <mirq-linux@rere.qmqm.pl>
+
+
+
+ Part I: Feature sets
+======================
+
+Long gone are the days when a network card would just take and give packets
+verbatim. Today's devices add multiple features and bugs (read: offloads)
+that relieve an OS of various tasks like generating and checking checksums,
+splitting packets, classifying them. Those capabilities and their state
+are commonly referred to as netdev features in Linux kernel world.
+
+There are currently three sets of features relevant to the driver, and
+one used internally by network core:
+
+ 1. netdev->hw_features set contains features whose state may possibly
+ be changed (enabled or disabled) for a particular device by user's
+ request. This set should be initialized in ndo_init callback and not
+ changed later.
+
+ 2. netdev->features set contains features which are currently enabled
+ for a device. This should be changed only by network core or in
+ error paths of ndo_set_features callback.
+
+ 3. netdev->vlan_features set contains features whose state is inherited
+ by child VLAN devices (limits netdev->features set). This is currently
+ used for all VLAN devices whether tags are stripped or inserted in
+ hardware or software.
+
+ 4. netdev->wanted_features set contains feature set requested by user.
+ This set is filtered by ndo_fix_features callback whenever it or
+ some device-specific conditions change. This set is internal to
+ networking core and should not be referenced in drivers.
+
+
+
+ Part II: Controlling enabled features
+=======================================
+
+When current feature set (netdev->features) is to be changed, new set
+is calculated and filtered by calling ndo_fix_features callback
+and netdev_fix_features(). If the resulting set differs from current
+set, it is passed to ndo_set_features callback and (if the callback
+returns success) replaces value stored in netdev->features.
+NETDEV_FEAT_CHANGE notification is issued after that whenever current
+set might have changed.
+
+The following events trigger recalculation:
+ 1. device's registration, after ndo_init returned success
+ 2. user requested changes in features state
+ 3. netdev_update_features() is called
+
+ndo_*_features callbacks are called with rtnl_lock held. Missing callbacks
+are treated as always returning success.
+
+A driver that wants to trigger recalculation must do so by calling
+netdev_update_features() while holding rtnl_lock. This should not be done
+from ndo_*_features callbacks. netdev->features should not be modified by
+driver except by means of ndo_fix_features callback.
+
+
+
+ Part III: Implementation hints
+================================
+
+ * ndo_fix_features:
+
+All dependencies between features should be resolved here. The resulting
+set can be reduced further by networking core imposed limitations (as coded
+in netdev_fix_features()). For this reason it is safer to disable a feature
+when its dependencies are not met instead of forcing the dependency on.
+
+This callback should not modify hardware nor driver state (should be
+stateless). It can be called multiple times between successive
+ndo_set_features calls.
+
+Callback must not alter features contained in NETIF_F_SOFT_FEATURES or
+NETIF_F_NEVER_CHANGE sets. The exception is NETIF_F_VLAN_CHALLENGED but
+care must be taken as the change won't affect already configured VLANs.
+
+ * ndo_set_features:
+
+Hardware should be reconfigured to match passed feature set. The set
+should not be altered unless some error condition happens that can't
+be reliably detected in ndo_fix_features. In this case, the callback
+should update netdev->features to match resulting hardware state.
+Errors returned are not (and cannot be) propagated anywhere except dmesg.
+(Note: successful return is zero, >0 means silent error.)
+
+
+
+ Part IV: Features
+===================
+
+For current list of features, see include/linux/netdev_features.h.
+This section describes semantics of some of them.
+
+ * Transmit checksumming
+
+For complete description, see comments near the top of include/linux/skbuff.h.
+
+Note: NETIF_F_HW_CSUM is a superset of NETIF_F_IP_CSUM + NETIF_F_IPV6_CSUM.
+It means that device can fill TCP/UDP-like checksum anywhere in the packets
+whatever headers there might be.
+
+ * Transmit TCP segmentation offload
+
+NETIF_F_TSO_ECN means that hardware can properly split packets with CWR bit
+set, be it TCPv4 (when NETIF_F_TSO is enabled) or TCPv6 (NETIF_F_TSO6).
+
+ * Transmit DMA from high memory
+
+On platforms where this is relevant, NETIF_F_HIGHDMA signals that
+ndo_start_xmit can handle skbs with frags in high memory.
+
+ * Transmit scatter-gather
+
+Those features say that ndo_start_xmit can handle fragmented skbs:
+NETIF_F_SG --- paged skbs (skb_shinfo()->frags), NETIF_F_FRAGLIST ---
+chained skbs (skb->next/prev list).
+
+ * Software features
+
+Features contained in NETIF_F_SOFT_FEATURES are features of networking
+stack. Driver should not change behaviour based on them.
+
+ * LLTX driver (deprecated for hardware drivers)
+
+NETIF_F_LLTX should be set in drivers that implement their own locking in
+transmit path or don't need locking at all (e.g. software tunnels).
+In ndo_start_xmit, it is recommended to use a try_lock and return
+NETDEV_TX_LOCKED when the spin lock fails. The locking should also properly
+protect against other callbacks (the rules you need to find out).
+
+Don't use it for new drivers.
+
+ * netns-local device
+
+NETIF_F_NETNS_LOCAL is set for devices that are not allowed to move between
+network namespaces (e.g. loopback).
+
+Don't use it in drivers.
+
+ * VLAN challenged
+
+NETIF_F_VLAN_CHALLENGED should be set for devices which can't cope with VLAN
+headers. Some drivers set this because the cards can't handle the bigger MTU.
+[FIXME: Those cases could be fixed in VLAN code by allowing only reduced-MTU
+VLANs. This may be not useful, though.]
diff --git a/Documentation/networking/nfc.txt b/Documentation/networking/nfc.txt
new file mode 100644
index 000000000000..b24c29bdae27
--- /dev/null
+++ b/Documentation/networking/nfc.txt
@@ -0,0 +1,128 @@
+Linux NFC subsystem
+===================
+
+The Near Field Communication (NFC) subsystem is required to standardize the
+NFC device drivers development and to create an unified userspace interface.
+
+This document covers the architecture overview, the device driver interface
+description and the userspace interface description.
+
+Architecture overview
+---------------------
+
+The NFC subsystem is responsible for:
+ - NFC adapters management;
+ - Polling for targets;
+ - Low-level data exchange;
+
+The subsystem is divided in some parts. The 'core' is responsible for
+providing the device driver interface. On the other side, it is also
+responsible for providing an interface to control operations and low-level
+data exchange.
+
+The control operations are available to userspace via generic netlink.
+
+The low-level data exchange interface is provided by the new socket family
+PF_NFC. The NFC_SOCKPROTO_RAW performs raw communication with NFC targets.
+
+
+ +--------------------------------------+
+ | USER SPACE |
+ +--------------------------------------+
+ ^ ^
+ | low-level | control
+ | data exchange | operations
+ | |
+ | v
+ | +-----------+
+ | AF_NFC | netlink |
+ | socket +-----------+
+ | raw ^
+ | |
+ v v
+ +---------+ +-----------+
+ | rawsock | <--------> | core |
+ +---------+ +-----------+
+ ^
+ |
+ v
+ +-----------+
+ | driver |
+ +-----------+
+
+Device Driver Interface
+-----------------------
+
+When registering on the NFC subsystem, the device driver must inform the core
+of the set of supported NFC protocols and the set of ops callbacks. The ops
+callbacks that must be implemented are the following:
+
+* start_poll - setup the device to poll for targets
+* stop_poll - stop on progress polling operation
+* activate_target - select and initialize one of the targets found
+* deactivate_target - deselect and deinitialize the selected target
+* data_exchange - send data and receive the response (transceive operation)
+
+Userspace interface
+--------------------
+
+The userspace interface is divided in control operations and low-level data
+exchange operation.
+
+CONTROL OPERATIONS:
+
+Generic netlink is used to implement the interface to the control operations.
+The operations are composed by commands and events, all listed below:
+
+* NFC_CMD_GET_DEVICE - get specific device info or dump the device list
+* NFC_CMD_START_POLL - setup a specific device to polling for targets
+* NFC_CMD_STOP_POLL - stop the polling operation in a specific device
+* NFC_CMD_GET_TARGET - dump the list of targets found by a specific device
+
+* NFC_EVENT_DEVICE_ADDED - reports an NFC device addition
+* NFC_EVENT_DEVICE_REMOVED - reports an NFC device removal
+* NFC_EVENT_TARGETS_FOUND - reports START_POLL results when 1 or more targets
+are found
+
+The user must call START_POLL to poll for NFC targets, passing the desired NFC
+protocols through NFC_ATTR_PROTOCOLS attribute. The device remains in polling
+state until it finds any target. However, the user can stop the polling
+operation by calling STOP_POLL command. In this case, it will be checked if
+the requester of STOP_POLL is the same of START_POLL.
+
+If the polling operation finds one or more targets, the event TARGETS_FOUND is
+sent (including the device id). The user must call GET_TARGET to get the list of
+all targets found by such device. Each reply message has target attributes with
+relevant information such as the supported NFC protocols.
+
+All polling operations requested through one netlink socket are stopped when
+it's closed.
+
+LOW-LEVEL DATA EXCHANGE:
+
+The userspace must use PF_NFC sockets to perform any data communication with
+targets. All NFC sockets use AF_NFC:
+
+struct sockaddr_nfc {
+ sa_family_t sa_family;
+ __u32 dev_idx;
+ __u32 target_idx;
+ __u32 nfc_protocol;
+};
+
+To establish a connection with one target, the user must create an
+NFC_SOCKPROTO_RAW socket and call the 'connect' syscall with the sockaddr_nfc
+struct correctly filled. All information comes from NFC_EVENT_TARGETS_FOUND
+netlink event. As a target can support more than one NFC protocol, the user
+must inform which protocol it wants to use.
+
+Internally, 'connect' will result in an activate_target call to the driver.
+When the socket is closed, the target is deactivated.
+
+The data format exchanged through the sockets is NFC protocol dependent. For
+instance, when communicating with MIFARE tags, the data exchanged are MIFARE
+commands and their responses.
+
+The first received package is the response to the first sent package and so
+on. In order to allow valid "empty" responses, every data received has a NULL
+header of 1 byte.
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 80a7a3454902..57a24108b845 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -7,7 +7,7 @@ This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers
(Synopsys IP blocks); it has been fully tested on STLinux platforms.
Currently this network device driver is for all STM embedded MAC/GMAC
-(7xxx SoCs). Other platforms start using it i.e. ARM SPEAr.
+(i.e. 7xxx/5xxx SoCs) and it's known working on other platforms i.e. ARM SPEAr.
DWC Ether MAC 10/100/1000 Universal version 3.41a and DWC Ether MAC 10/100
Universal version 4.0 have been used for developing the first code
@@ -71,7 +71,7 @@ Several performance tests on STM platforms showed this optimisation allows to sp
the CPU while having the maximum throughput.
4.4) WOL
-Wake up on Lan feature through Magic Frame is only supported for the GMAC
+Wake up on Lan feature through Magic and Unicast frames are supported for the GMAC
core.
4.5) DMA descriptors
@@ -91,11 +91,15 @@ LRO is not supported.
The driver is compatible with PAL to work with PHY and GPHY devices.
4.9) Platform information
-Several information came from the platform; please refer to the
-driver's Header file in include/linux directory.
+Several driver's information can be passed through the platform
+These are included in the include/linux/stmmac.h header file
+and detailed below as well:
-struct plat_stmmacenet_data {
+ struct plat_stmmacenet_data {
int bus_id;
+ int phy_addr;
+ int interface;
+ struct stmmac_mdio_bus_data *mdio_bus_data;
int pbl;
int clk_csr;
int has_gmac;
@@ -103,67 +107,135 @@ struct plat_stmmacenet_data {
int tx_coe;
int bugged_jumbo;
int pmt;
- void (*fix_mac_speed)(void *priv, unsigned int speed);
- void (*bus_setup)(unsigned long ioaddr);
-#ifdef CONFIG_STM_DRIVERS
- struct stm_pad_config *pad_config;
-#endif
- void *bsp_priv;
-};
+ int force_sf_dma_mode;
+ void (*fix_mac_speed)(void *priv, unsigned int speed);
+ void (*bus_setup)(void __iomem *ioaddr);
+ int (*init)(struct platform_device *pdev);
+ void (*exit)(struct platform_device *pdev);
+ void *bsp_priv;
+ };
Where:
-- pbl (Programmable Burst Length) is maximum number of
- beats to be transferred in one DMA transaction.
- GMAC also enables the 4xPBL by default.
-- fix_mac_speed and bus_setup are used to configure internal target
- registers (on STM platforms);
-- has_gmac: GMAC core is on board (get it at run-time in the next step);
-- bus_id: bus identifier.
-- tx_coe: core is able to perform the tx csum in HW.
-- enh_desc: if sets the MAC will use the enhanced descriptor structure.
-- clk_csr: CSR Clock range selection.
-- bugged_jumbo: some HWs are not able to perform the csum in HW for
- over-sized frames due to limited buffer sizes. Setting this
- flag the csum will be done in SW on JUMBO frames.
-
-struct plat_stmmacphy_data {
- int bus_id;
- int phy_addr;
- unsigned int phy_mask;
- int interface;
- int (*phy_reset)(void *priv);
- void *priv;
-};
+ o bus_id: bus identifier.
+ o phy_addr: the physical address can be passed from the platform.
+ If it is set to -1 the driver will automatically
+ detect it at run-time by probing all the 32 addresses.
+ o interface: PHY device's interface.
+ o mdio_bus_data: specific platform fields for the MDIO bus.
+ o pbl: the Programmable Burst Length is maximum number of beats to
+ be transferred in one DMA transaction.
+ GMAC also enables the 4xPBL by default.
+ o clk_csr: CSR Clock range selection.
+ o has_gmac: uses the GMAC core.
+ o enh_desc: if sets the MAC will use the enhanced descriptor structure.
+ o tx_coe: core is able to perform the tx csum in HW.
+ o bugged_jumbo: some HWs are not able to perform the csum in HW for
+ over-sized frames due to limited buffer sizes.
+ Setting this flag the csum will be done in SW on
+ JUMBO frames.
+ o pmt: core has the embedded power module (optional).
+ o force_sf_dma_mode: force DMA to use the Store and Forward mode
+ instead of the Threshold.
+ o fix_mac_speed: this callback is used for modifying some syscfg registers
+ (on ST SoCs) according to the link speed negotiated by the
+ physical layer .
+ o bus_setup: perform HW setup of the bus. For example, on some ST platforms
+ this field is used to configure the AMBA bridge to generate more
+ efficient STBus traffic.
+ o init/exit: callbacks used for calling a custom initialisation;
+ this is sometime necessary on some platforms (e.g. ST boxes)
+ where the HW needs to have set some PIO lines or system cfg
+ registers.
+ o custom_cfg: this is a custom configuration that can be passed while
+ initialising the resources.
+
+The we have:
+
+ struct stmmac_mdio_bus_data {
+ int bus_id;
+ int (*phy_reset)(void *priv);
+ unsigned int phy_mask;
+ int *irqs;
+ int probed_phy_irq;
+ };
Where:
-- bus_id: bus identifier;
-- phy_addr: physical address used for the attached phy device;
- set it to -1 to get it at run-time;
-- interface: physical MII interface mode;
-- phy_reset: hook to reset HW function.
-
-SOURCES:
-- Kconfig
-- Makefile
-- stmmac_main.c: main network device driver;
-- stmmac_mdio.c: mdio functions;
-- stmmac_ethtool.c: ethtool support;
-- stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
- Only tested on ST40 platforms based.
-- stmmac.h: private driver structure;
-- common.h: common definitions and VFTs;
-- descs.h: descriptor structure definitions;
-- dwmac1000_core.c: GMAC core functions;
-- dwmac1000_dma.c: dma functions for the GMAC chip;
-- dwmac1000.h: specific header file for the GMAC;
-- dwmac100_core: MAC 100 core and dma code;
-- dwmac100_dma.c: dma funtions for the MAC chip;
-- dwmac1000.h: specific header file for the MAC;
-- dwmac_lib.c: generic DMA functions shared among chips
-- enh_desc.c: functions for handling enhanced descriptors
-- norm_desc.c: functions for handling normal descriptors
-
-TODO:
-- XGMAC controller is not supported.
-- Review the timer optimisation code to use an embedded device that seems to be
+ o bus_id: bus identifier;
+ o phy_reset: hook to reset the phy device attached to the bus.
+ o phy_mask: phy mask passed when register the MDIO bus within the driver.
+ o irqs: list of IRQs, one per PHY.
+ o probed_phy_irq: if irqs is NULL, use this for probed PHY.
+
+Below an example how the structures above are using on ST platforms.
+
+ static struct plat_stmmacenet_data stxYYY_ethernet_platform_data = {
+ .pbl = 32,
+ .has_gmac = 0,
+ .enh_desc = 0,
+ .fix_mac_speed = stxYYY_ethernet_fix_mac_speed,
+ |
+ |-> to write an internal syscfg
+ | on this platform when the
+ | link speed changes from 10 to
+ | 100 and viceversa
+ .init = &stmmac_claim_resource,
+ |
+ |-> On ST SoC this calls own "PAD"
+ | manager framework to claim
+ | all the resources necessary
+ | (GPIO ...). The .custom_cfg field
+ | is used to pass a custom config.
+};
+
+Below the usage of the stmmac_mdio_bus_data: on this SoC, in fact,
+there are two MAC cores: one MAC is for MDIO Bus/PHY emulation
+with fixed_link support.
+
+static struct stmmac_mdio_bus_data stmmac1_mdio_bus = {
+ .bus_id = 1,
+ |
+ |-> phy device on the bus_id 1
+ .phy_reset = phy_reset;
+ |
+ |-> function to provide the phy_reset on this board
+ .phy_mask = 0,
+};
+
+static struct fixed_phy_status stmmac0_fixed_phy_status = {
+ .link = 1,
+ .speed = 100,
+ .duplex = 1,
+};
+
+During the board's device_init we can configure the first
+MAC for fixed_link by calling:
+ fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status));)
+and the second one, with a real PHY device attached to the bus,
+by using the stmmac_mdio_bus_data structure (to provide the id, the
+reset procedure etc).
+
+4.10) List of source files:
+ o Kconfig
+ o Makefile
+ o stmmac_main.c: main network device driver;
+ o stmmac_mdio.c: mdio functions;
+ o stmmac_ethtool.c: ethtool support;
+ o stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
+ Only tested on ST40 platforms based.
+ o stmmac.h: private driver structure;
+ o common.h: common definitions and VFTs;
+ o descs.h: descriptor structure definitions;
+ o dwmac1000_core.c: GMAC core functions;
+ o dwmac1000_dma.c: dma functions for the GMAC chip;
+ o dwmac1000.h: specific header file for the GMAC;
+ o dwmac100_core: MAC 100 core and dma code;
+ o dwmac100_dma.c: dma funtions for the MAC chip;
+ o dwmac1000.h: specific header file for the MAC;
+ o dwmac_lib.c: generic DMA functions shared among chips
+ o enh_desc.c: functions for handling enhanced descriptors
+ o norm_desc.c: functions for handling normal descriptors
+
+5) 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/power/devices.txt b/Documentation/power/devices.txt
index 64565aac6e40..3384d5996be2 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -506,8 +506,8 @@ routines. Nevertheless, different callback pointers are used in case there is a
situation where it actually matters.
-Device Power Domains
---------------------
+Device Power Management Domains
+-------------------------------
Sometimes devices share reference clocks or other power resources. In those
cases it generally is not possible to put devices into low-power states
individually. Instead, a set of devices sharing a power resource can be put
@@ -516,8 +516,8 @@ power resource. Of course, they also need to be put into the full-power state
together, by turning the shared power resource on. A set of devices with this
property is often referred to as a power domain.
-Support for power domains is provided through the pwr_domain field of struct
-device. This field is a pointer to an object of type struct dev_power_domain,
+Support for power domains is provided through the pm_domain field of struct
+device. This field is a pointer to an object of type struct dev_pm_domain,
defined in include/linux/pm.h, providing a set of power management callbacks
analogous to the subsystem-level and device driver callbacks that are executed
for the given device during all power transitions, instead of the respective
@@ -604,7 +604,7 @@ state temporarily, for example so that its system wakeup capability can be
disabled. This all depends on the hardware and the design of the subsystem and
device driver in question.
-During system-wide resume from a sleep state it's best to put devices into the
-full-power state, as explained in Documentation/power/runtime_pm.txt. Refer to
-that document for more information regarding this particular issue as well as
+During system-wide resume from a sleep state it's easiest to put devices into
+the full-power state, as explained in Documentation/power/runtime_pm.txt. Refer
+to that document for more information regarding this particular issue as well as
for information on the device runtime power management framework in general.
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
index 5ae70a12c1e2..3035d00757ad 100644
--- a/Documentation/power/opp.txt
+++ b/Documentation/power/opp.txt
@@ -321,6 +321,8 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
addition to CONFIG_PM as power management feature is required to
dynamically scale voltage and frequency in a system.
+opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table
+
7. Data Structures
==================
Typically an SoC contains multiple voltage domains which are variable. Each
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index b24875b1ced5..14dd3c6ad97e 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -1,39 +1,39 @@
-Run-time Power Management Framework for I/O Devices
+Runtime Power Management Framework for I/O Devices
(C) 2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
(C) 2010 Alan Stern <stern@rowland.harvard.edu>
1. Introduction
-Support for run-time power management (run-time PM) of I/O devices is provided
+Support for runtime power management (runtime PM) of I/O devices is provided
at the power management core (PM core) level by means of:
* The power management workqueue pm_wq in which bus types and device drivers can
put their PM-related work items. It is strongly recommended that pm_wq be
- used for queuing all work items related to run-time PM, because this allows
+ used for queuing all work items related to runtime PM, because this allows
them to be synchronized with system-wide power transitions (suspend to RAM,
hibernation and resume from system sleep states). pm_wq is declared in
include/linux/pm_runtime.h and defined in kernel/power/main.c.
-* A number of run-time PM fields in the 'power' member of 'struct device' (which
+* A number of runtime PM fields in the 'power' member of 'struct device' (which
is of the type 'struct dev_pm_info', defined in include/linux/pm.h) that can
- be used for synchronizing run-time PM operations with one another.
+ be used for synchronizing runtime PM operations with one another.
-* Three device run-time PM callbacks in 'struct dev_pm_ops' (defined in
+* Three device runtime PM callbacks in 'struct dev_pm_ops' (defined in
include/linux/pm.h).
* A set of helper functions defined in drivers/base/power/runtime.c that can be
- used for carrying out run-time PM operations in such a way that the
+ used for carrying out runtime PM operations in such a way that the
synchronization between them is taken care of by the PM core. Bus types and
device drivers are encouraged to use these functions.
-The run-time PM callbacks present in 'struct dev_pm_ops', the device run-time PM
+The runtime PM callbacks present in 'struct dev_pm_ops', the device runtime PM
fields of 'struct dev_pm_info' and the core helper functions provided for
-run-time PM are described below.
+runtime PM are described below.
-2. Device Run-time PM Callbacks
+2. Device Runtime PM Callbacks
-There are three device run-time PM callbacks defined in 'struct dev_pm_ops':
+There are three device runtime PM callbacks defined in 'struct dev_pm_ops':
struct dev_pm_ops {
...
@@ -72,11 +72,11 @@ knows what to do to handle the device).
not mean that the device has been put into a low power state. It is
supposed to mean, however, that the device will not process data and will
not communicate with the CPU(s) and RAM until the subsystem-level resume
- callback is executed for it. The run-time PM status of a device after
+ callback is executed for it. The runtime PM status of a device after
successful execution of the subsystem-level suspend callback is 'suspended'.
* If the subsystem-level suspend callback returns -EBUSY or -EAGAIN,
- the device's run-time PM status is 'active', which means that the device
+ the device's runtime PM status is 'active', which means that the device
_must_ be fully operational afterwards.
* If the subsystem-level suspend callback returns an error code different
@@ -104,7 +104,7 @@ the device).
* Once the subsystem-level resume callback has completed successfully, the PM
core regards the device as fully operational, which means that the device
- _must_ be able to complete I/O operations as needed. The run-time PM status
+ _must_ be able to complete I/O operations as needed. The runtime PM status
of the device is then 'active'.
* If the subsystem-level resume callback returns an error code, the PM core
@@ -130,7 +130,7 @@ device in that case. The value returned by this callback is ignored by the PM
core.
The helper functions provided by the PM core, described in Section 4, guarantee
-that the following constraints are met with respect to the bus type's run-time
+that the following constraints are met with respect to the bus type's runtime
PM callbacks:
(1) The callbacks are mutually exclusive (e.g. it is forbidden to execute
@@ -142,7 +142,7 @@ PM callbacks:
(2) ->runtime_idle() and ->runtime_suspend() can only be executed for 'active'
devices (i.e. the PM core will only execute ->runtime_idle() or
- ->runtime_suspend() for the devices the run-time PM status of which is
+ ->runtime_suspend() for the devices the runtime PM status of which is
'active').
(3) ->runtime_idle() and ->runtime_suspend() can only be executed for a device
@@ -151,7 +151,7 @@ PM callbacks:
flag of which is set.
(4) ->runtime_resume() can only be executed for 'suspended' devices (i.e. the
- PM core will only execute ->runtime_resume() for the devices the run-time
+ PM core will only execute ->runtime_resume() for the devices the runtime
PM status of which is 'suspended').
Additionally, the helper functions provided by the PM core obey the following
@@ -171,9 +171,9 @@ rules:
scheduled requests to execute the other callbacks for the same device,
except for scheduled autosuspends.
-3. Run-time PM Device Fields
+3. Runtime PM Device Fields
-The following device run-time PM fields are present in 'struct dev_pm_info', as
+The following device runtime PM fields are present in 'struct dev_pm_info', as
defined in include/linux/pm.h:
struct timer_list suspend_timer;
@@ -205,7 +205,7 @@ defined in include/linux/pm.h:
unsigned int disable_depth;
- used for disabling the helper funcions (they work normally if this is
- equal to zero); the initial value of it is 1 (i.e. run-time PM is
+ equal to zero); the initial value of it is 1 (i.e. runtime PM is
initially disabled for all devices)
unsigned int runtime_error;
@@ -229,10 +229,10 @@ defined in include/linux/pm.h:
suspend to complete; means "start a resume as soon as you've suspended"
unsigned int run_wake;
- - set if the device is capable of generating run-time wake-up events
+ - set if the device is capable of generating runtime wake-up events
enum rpm_status runtime_status;
- - the run-time PM status of the device; this field's initial value is
+ - the runtime PM status of the device; this field's initial value is
RPM_SUSPENDED, which means that each device is initially regarded by the
PM core as 'suspended', regardless of its real hardware status
@@ -243,7 +243,7 @@ defined in include/linux/pm.h:
and pm_runtime_forbid() helper functions
unsigned int no_callbacks;
- - indicates that the device does not use the run-time PM callbacks (see
+ - indicates that the device does not use the runtime PM callbacks (see
Section 8); it may be modified only by the pm_runtime_no_callbacks()
helper function
@@ -270,16 +270,16 @@ defined in include/linux/pm.h:
All of the above fields are members of the 'power' member of 'struct device'.
-4. Run-time PM Device Helper Functions
+4. Runtime PM Device Helper Functions
-The following run-time PM helper functions are defined in
+The following runtime PM helper functions are defined in
drivers/base/power/runtime.c and include/linux/pm_runtime.h:
void pm_runtime_init(struct device *dev);
- - initialize the device run-time PM fields in 'struct dev_pm_info'
+ - initialize the device runtime PM fields in 'struct dev_pm_info'
void pm_runtime_remove(struct device *dev);
- - make sure that the run-time PM of the device will be disabled after
+ - make sure that the runtime PM of the device will be disabled after
removing the device from device hierarchy
int pm_runtime_idle(struct device *dev);
@@ -289,9 +289,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
int pm_runtime_suspend(struct device *dev);
- execute the subsystem-level suspend callback for the device; returns 0 on
- success, 1 if the device's run-time PM status was already 'suspended', or
+ success, 1 if the device's runtime PM status was already 'suspended', or
error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
- to suspend the device again in future
+ to suspend the device again in future and -EACCES means that
+ 'power.disable_depth' is different from 0
int pm_runtime_autosuspend(struct device *dev);
- same as pm_runtime_suspend() except that the autosuspend delay is taken
@@ -301,10 +302,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
int pm_runtime_resume(struct device *dev);
- execute the subsystem-level resume callback for the device; returns 0 on
- success, 1 if the device's run-time PM status was already 'active' or
+ success, 1 if the device's runtime PM status was already 'active' or
error code on failure, where -EAGAIN means it may be safe to attempt to
resume the device again in future, but 'power.runtime_error' should be
- checked additionally
+ checked additionally, and -EACCES means that 'power.disable_depth' is
+ different from 0
int pm_request_idle(struct device *dev);
- submit a request to execute the subsystem-level idle callback for the
@@ -321,7 +323,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
device in future, where 'delay' is the time to wait before queuing up a
suspend work item in pm_wq, in milliseconds (if 'delay' is zero, the work
item is queued up immediately); returns 0 on success, 1 if the device's PM
- run-time status was already 'suspended', or error code if the request
+ runtime status was already 'suspended', or error code if the request
hasn't been scheduled (or queued up if 'delay' is 0); if the execution of
->runtime_suspend() is already scheduled and not yet expired, the new
value of 'delay' will be used as the time to wait
@@ -329,7 +331,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
int pm_request_resume(struct device *dev);
- submit a request to execute the subsystem-level resume callback for the
device (the request is represented by a work item in pm_wq); returns 0 on
- success, 1 if the device's run-time PM status was already 'active', or
+ success, 1 if the device's runtime PM status was already 'active', or
error code if the request hasn't been queued up
void pm_runtime_get_noresume(struct device *dev);
@@ -367,22 +369,32 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
pm_runtime_autosuspend(dev) and return its result
void pm_runtime_enable(struct device *dev);
- - enable the run-time PM helper functions to run the device bus type's
- run-time PM callbacks described in Section 2
+ - decrement the device's 'power.disable_depth' field; if that field is equal
+ to zero, the runtime PM helper functions can execute subsystem-level
+ callbacks described in Section 2 for the device
int pm_runtime_disable(struct device *dev);
- - prevent the run-time PM helper functions from running subsystem-level
- run-time PM callbacks for the device, make sure that all of the pending
- run-time PM operations on the device are either completed or canceled;
+ - increment the device's 'power.disable_depth' field (if the value of that
+ field was previously zero, this prevents subsystem-level runtime PM
+ callbacks from being run for the device), make sure that all of the pending
+ runtime PM operations on the device are either completed or canceled;
returns 1 if there was a resume request pending and it was necessary to
execute the subsystem-level resume callback for the device to satisfy that
request, otherwise 0 is returned
+ int pm_runtime_barrier(struct device *dev);
+ - check if there's a resume request pending for the device and resume it
+ (synchronously) in that case, cancel any other pending runtime PM requests
+ regarding it and wait for all runtime PM operations on it in progress to
+ complete; returns 1 if there was a resume request pending and it was
+ necessary to execute the subsystem-level resume callback for the device to
+ satisfy that request, otherwise 0 is returned
+
void pm_suspend_ignore_children(struct device *dev, bool enable);
- set/unset the power.ignore_children flag of the device
int pm_runtime_set_active(struct device *dev);
- - clear the device's 'power.runtime_error' flag, set the device's run-time
+ - clear the device's 'power.runtime_error' flag, set the device's runtime
PM status to 'active' and update its parent's counter of 'active'
children as appropriate (it is only valid to use this function if
'power.runtime_error' is set or 'power.disable_depth' is greater than
@@ -390,7 +402,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
which is not active and the 'power.ignore_children' flag of which is unset
void pm_runtime_set_suspended(struct device *dev);
- - clear the device's 'power.runtime_error' flag, set the device's run-time
+ - clear the device's 'power.runtime_error' flag, set the device's runtime
PM status to 'suspended' and update its parent's counter of 'active'
children as appropriate (it is only valid to use this function if
'power.runtime_error' is set or 'power.disable_depth' is greater than
@@ -400,6 +412,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
- return true if the device's runtime PM status is 'suspended' and its
'power.disable_depth' field is equal to zero, or false otherwise
+ bool pm_runtime_status_suspended(struct device *dev);
+ - return true if the device's runtime PM status is 'suspended'
+
void pm_runtime_allow(struct device *dev);
- set the power.runtime_auto flag for the device and decrease its usage
counter (used by the /sys/devices/.../power/control interface to
@@ -411,7 +426,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
effectively prevent the device from being power managed at run time)
void pm_runtime_no_callbacks(struct device *dev);
- - set the power.no_callbacks flag for the device and remove the run-time
+ - set the power.no_callbacks flag for the device and remove the runtime
PM attributes from /sys/devices/.../power (or prevent them from being
added when the device is registered)
@@ -431,7 +446,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
- set the power.autosuspend_delay value to 'delay' (expressed in
- milliseconds); if 'delay' is negative then run-time suspends are
+ milliseconds); if 'delay' is negative then runtime suspends are
prevented
unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
@@ -470,35 +485,35 @@ pm_runtime_resume()
pm_runtime_get_sync()
pm_runtime_put_sync_suspend()
-5. Run-time PM Initialization, Device Probing and Removal
+5. Runtime PM Initialization, Device Probing and Removal
-Initially, the run-time PM is disabled for all devices, which means that the
-majority of the run-time PM helper funtions described in Section 4 will return
+Initially, the runtime PM is disabled for all devices, which means that the
+majority of the runtime PM helper funtions described in Section 4 will return
-EAGAIN until pm_runtime_enable() is called for the device.
-In addition to that, the initial run-time PM status of all devices is
+In addition to that, the initial runtime PM status of all devices is
'suspended', but it need not reflect the actual physical state of the device.
Thus, if the device is initially active (i.e. it is able to process I/O), its
-run-time PM status must be changed to 'active', with the help of
+runtime PM status must be changed to 'active', with the help of
pm_runtime_set_active(), before pm_runtime_enable() is called for the device.
-However, if the device has a parent and the parent's run-time PM is enabled,
+However, if the device has a parent and the parent's runtime PM is enabled,
calling pm_runtime_set_active() for the device will affect the parent, unless
the parent's 'power.ignore_children' flag is set. Namely, in that case the
parent won't be able to suspend at run time, using the PM core's helper
functions, as long as the child's status is 'active', even if the child's
-run-time PM is still disabled (i.e. pm_runtime_enable() hasn't been called for
+runtime PM is still disabled (i.e. pm_runtime_enable() hasn't been called for
the child yet or pm_runtime_disable() has been called for it). For this reason,
once pm_runtime_set_active() has been called for the device, pm_runtime_enable()
-should be called for it too as soon as reasonably possible or its run-time PM
+should be called for it too as soon as reasonably possible or its runtime PM
status should be changed back to 'suspended' with the help of
pm_runtime_set_suspended().
-If the default initial run-time PM status of the device (i.e. 'suspended')
+If the default initial runtime PM status of the device (i.e. 'suspended')
reflects the actual state of the device, its bus type's or its driver's
->probe() callback will likely need to wake it up using one of the PM core's
helper functions described in Section 4. In that case, pm_runtime_resume()
-should be used. Of course, for this purpose the device's run-time PM has to be
+should be used. Of course, for this purpose the device's runtime PM has to be
enabled earlier by calling pm_runtime_enable().
If the device bus type's or driver's ->probe() callback runs
@@ -529,33 +544,33 @@ The user space can effectively disallow the driver of the device to power manage
it at run time by changing the value of its /sys/devices/.../power/control
attribute to "on", which causes pm_runtime_forbid() to be called. In principle,
this mechanism may also be used by the driver to effectively turn off the
-run-time power management of the device until the user space turns it on.
-Namely, during the initialization the driver can make sure that the run-time PM
+runtime power management of the device until the user space turns it on.
+Namely, during the initialization the driver can make sure that the runtime PM
status of the device is 'active' and call pm_runtime_forbid(). It should be
noted, however, that if the user space has already intentionally changed the
value of /sys/devices/.../power/control to "auto" to allow the driver to power
manage the device at run time, the driver may confuse it by using
pm_runtime_forbid() this way.
-6. Run-time PM and System Sleep
+6. Runtime PM and System Sleep
-Run-time PM and system sleep (i.e., system suspend and hibernation, also known
+Runtime PM and system sleep (i.e., system suspend and hibernation, also known
as suspend-to-RAM and suspend-to-disk) interact with each other in a couple of
ways. If a device is active when a system sleep starts, everything is
straightforward. But what should happen if the device is already suspended?
-The device may have different wake-up settings for run-time PM and system sleep.
-For example, remote wake-up may be enabled for run-time suspend but disallowed
+The device may have different wake-up settings for runtime PM and system sleep.
+For example, remote wake-up may be enabled for runtime suspend but disallowed
for system sleep (device_may_wakeup(dev) returns 'false'). When this happens,
the subsystem-level system suspend callback is responsible for changing the
device's wake-up setting (it may leave that to the device driver's system
suspend routine). It may be necessary to resume the device and suspend it again
in order to do so. The same is true if the driver uses different power levels
-or other settings for run-time suspend and system sleep.
+or other settings for runtime suspend and system sleep.
-During system resume, devices generally should be brought back to full power,
-even if they were suspended before the system sleep began. There are several
-reasons for this, including:
+During system resume, the simplest approach is to bring all devices back to full
+power, even if they had been suspended before the system suspend began. There
+are several reasons for this, including:
* The device might need to switch power levels, wake-up settings, etc.
@@ -570,18 +585,50 @@ reasons for this, including:
* The device might need to be reset.
* Even though the device was suspended, if its usage counter was > 0 then most
- likely it would need a run-time resume in the near future anyway.
-
- * Always going back to full power is simplest.
+ likely it would need a runtime resume in the near future anyway.
-If the device was suspended before the sleep began, then its run-time PM status
-will have to be updated to reflect the actual post-system sleep status. The way
-to do this is:
+If the device had been suspended before the system suspend began and it's
+brought back to full power during resume, then its runtime PM status will have
+to be updated to reflect the actual post-system sleep status. The way to do
+this is:
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
+The PM core always increments the runtime usage counter before calling the
+->suspend() callback and decrements it after calling the ->resume() callback.
+Hence disabling runtime PM temporarily like this will not cause any runtime
+suspend attempts to be permanently lost. If the usage count goes to zero
+following the return of the ->resume() callback, the ->runtime_idle() callback
+will be invoked as usual.
+
+On some systems, however, system sleep is not entered through a global firmware
+or hardware operation. Instead, all hardware components are put into low-power
+states directly by the kernel in a coordinated way. Then, the system sleep
+state effectively follows from the states the hardware components end up in
+and the system is woken up from that state by a hardware interrupt or a similar
+mechanism entirely under the kernel's control. As a result, the kernel never
+gives control away and the states of all devices during resume are precisely
+known to it. If that is the case and none of the situations listed above takes
+place (in particular, if the system is not waking up from hibernation), it may
+be more efficient to leave the devices that had been suspended before the system
+suspend began in the suspended state.
+
+The PM core does its best to reduce the probability of race conditions between
+the runtime PM and system suspend/resume (and hibernation) callbacks by carrying
+out the following operations:
+
+ * During system suspend it calls pm_runtime_get_noresume() and
+ pm_runtime_barrier() for every device right before executing the
+ subsystem-level .suspend() callback for it. In addition to that it calls
+ pm_runtime_disable() for every device right after executing the
+ subsystem-level .suspend() callback for it.
+
+ * During system resume it calls pm_runtime_enable() and pm_runtime_put_sync()
+ for every device right before and right after executing the subsystem-level
+ .resume() callback for it, respectively.
+
7. Generic subsystem callbacks
Subsystems may wish to conserve code space by using the set of generic power
@@ -606,40 +653,68 @@ driver/base/power/generic_ops.c:
callback provided by its driver and return its result, or return 0 if not
defined
+ int pm_generic_suspend_noirq(struct device *dev);
+ - if pm_runtime_suspended(dev) returns "false", invoke the ->suspend_noirq()
+ callback provided by the device's driver and return its result, or return
+ 0 if not defined
+
int pm_generic_resume(struct device *dev);
- invoke the ->resume() callback provided by the driver of this device and,
if successful, change the device's runtime PM status to 'active'
+ int pm_generic_resume_noirq(struct device *dev);
+ - invoke the ->resume_noirq() callback provided by the driver of this device
+
int pm_generic_freeze(struct device *dev);
- if the device has not been suspended at run time, invoke the ->freeze()
callback provided by its driver and return its result, or return 0 if not
defined
+ int pm_generic_freeze_noirq(struct device *dev);
+ - if pm_runtime_suspended(dev) returns "false", invoke the ->freeze_noirq()
+ callback provided by the device's driver and return its result, or return
+ 0 if not defined
+
int pm_generic_thaw(struct device *dev);
- if the device has not been suspended at run time, invoke the ->thaw()
callback provided by its driver and return its result, or return 0 if not
defined
+ int pm_generic_thaw_noirq(struct device *dev);
+ - if pm_runtime_suspended(dev) returns "false", invoke the ->thaw_noirq()
+ callback provided by the device's driver and return its result, or return
+ 0 if not defined
+
int pm_generic_poweroff(struct device *dev);
- if the device has not been suspended at run time, invoke the ->poweroff()
callback provided by its driver and return its result, or return 0 if not
defined
+ int pm_generic_poweroff_noirq(struct device *dev);
+ - if pm_runtime_suspended(dev) returns "false", run the ->poweroff_noirq()
+ callback provided by the device's driver and return its result, or return
+ 0 if not defined
+
int pm_generic_restore(struct device *dev);
- invoke the ->restore() callback provided by the driver of this device and,
if successful, change the device's runtime PM status to 'active'
+ int pm_generic_restore_noirq(struct device *dev);
+ - invoke the ->restore_noirq() callback provided by the device's driver
+
These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(),
-->runtime_resume(), ->suspend(), ->resume(), ->freeze(), ->thaw(), ->poweroff(),
-or ->restore() callback pointers in the subsystem-level dev_pm_ops structures.
+->runtime_resume(), ->suspend(), ->suspend_noirq(), ->resume(),
+->resume_noirq(), ->freeze(), ->freeze_noirq(), ->thaw(), ->thaw_noirq(),
+->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() callback
+pointers in the subsystem-level dev_pm_ops structures.
If a subsystem wishes to use all of them at the same time, it can simply assign
the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its
dev_pm_ops structure pointer.
Device drivers that wish to use the same function as a system suspend, freeze,
-poweroff and run-time suspend callback, and similarly for system resume, thaw,
-restore, and run-time resume, can achieve this with the help of the
+poweroff and runtime suspend callback, and similarly for system resume, thaw,
+restore, and runtime resume, can achieve this with the help of the
UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
last argument to NULL).
@@ -649,7 +724,7 @@ Some "devices" are only logical sub-devices of their parent and cannot be
power-managed on their own. (The prototype example is a USB interface. Entire
USB devices can go into low-power mode or send wake-up requests, but neither is
possible for individual interfaces.) The drivers for these devices have no
-need of run-time PM callbacks; if the callbacks did exist, ->runtime_suspend()
+need of runtime PM callbacks; if the callbacks did exist, ->runtime_suspend()
and ->runtime_resume() would always return 0 without doing anything else and
->runtime_idle() would always call pm_runtime_suspend().
@@ -657,7 +732,7 @@ Subsystems can tell the PM core about these devices by calling
pm_runtime_no_callbacks(). This should be done after the device structure is
initialized and before it is registered (although after device registration is
also okay). The routine will set the device's power.no_callbacks flag and
-prevent the non-debugging run-time PM sysfs attributes from being created.
+prevent the non-debugging runtime PM sysfs attributes from being created.
When power.no_callbacks is set, the PM core will not invoke the
->runtime_idle(), ->runtime_suspend(), or ->runtime_resume() callbacks.
@@ -665,7 +740,7 @@ Instead it will assume that suspends and resumes always succeed and that idle
devices should be suspended.
As a consequence, the PM core will never directly inform the device's subsystem
-or driver about run-time power changes. Instead, the driver for the device's
+or driver about runtime power changes. Instead, the driver for the device's
parent must take responsibility for telling the device's driver when the
parent's power state changes.
@@ -676,13 +751,13 @@ A device should be put in a low-power state only when there's some reason to
think it will remain in that state for a substantial time. A common heuristic
says that a device which hasn't been used for a while is liable to remain
unused; following this advice, drivers should not allow devices to be suspended
-at run-time until they have been inactive for some minimum period. Even when
+at runtime until they have been inactive for some minimum period. Even when
the heuristic ends up being non-optimal, it will still prevent devices from
"bouncing" too rapidly between low-power and full-power states.
The term "autosuspend" is an historical remnant. It doesn't mean that the
device is automatically suspended (the subsystem or driver still has to call
-the appropriate PM routines); rather it means that run-time suspends will
+the appropriate PM routines); rather it means that runtime suspends will
automatically be delayed until the desired period of inactivity has elapsed.
Inactivity is determined based on the power.last_busy field. Drivers should
diff --git a/Documentation/rbtree.txt b/Documentation/rbtree.txt
index 19f8278c3854..8d32d85a5234 100644
--- a/Documentation/rbtree.txt
+++ b/Documentation/rbtree.txt
@@ -196,15 +196,20 @@ Support for Augmented rbtrees
Augmented rbtree is an rbtree with "some" additional data stored in each node.
This data can be used to augment some new functionality to rbtree.
Augmented rbtree is an optional feature built on top of basic rbtree
-infrastructure. rbtree user who wants this feature will have an augment
-callback function in rb_root initialized.
-
-This callback function will be called from rbtree core routines whenever
-a node has a change in one or both of its children. It is the responsibility
-of the callback function to recalculate the additional data that is in the
-rb node using new children information. Note that if this new additional
-data affects the parent node's additional data, then callback function has
-to handle it and do the recursive updates.
+infrastructure. An rbtree user who wants this feature will have to call the
+augmentation functions with the user provided augmentation callback
+when inserting and erasing nodes.
+
+On insertion, the user must call rb_augment_insert() once the new node is in
+place. This will cause the augmentation function callback to be called for
+each node between the new node and the root which has been affected by the
+insertion.
+
+When erasing a node, the user must call rb_augment_erase_begin() first to
+retrieve the deepest node on the rebalance path. Then, after erasing the
+original node, the user must call rb_augment_erase_end() with the deepest
+node found earlier. This will cause the augmentation function to be called
+for each affected node between the deepest node and the root.
Interval tree is an example of augmented rb tree. Reference -
diff --git a/Documentation/s390/TAPE b/Documentation/s390/TAPE
deleted file mode 100644
index c639aa5603ff..000000000000
--- a/Documentation/s390/TAPE
+++ /dev/null
@@ -1,122 +0,0 @@
-Channel attached Tape device driver
-
------------------------------WARNING-----------------------------------------
-This driver is considered to be EXPERIMENTAL. Do NOT use it in
-production environments. Feel free to test it and report problems back to us.
------------------------------------------------------------------------------
-
-The LINUX for zSeries tape device driver manages channel attached tape drives
-which are compatible to IBM 3480 or IBM 3490 magnetic tape subsystems. This
-includes various models of these devices (for example the 3490E).
-
-
-Tape driver features
-
-The device driver supports a maximum of 128 tape devices.
-No official LINUX device major number is assigned to the zSeries tape device
-driver. It allocates major numbers dynamically and reports them on system
-startup.
-Typically it will get major number 254 for both the character device front-end
-and the block device front-end.
-
-The tape device driver needs no kernel parameters. All supported devices
-present are detected on driver initialization at system startup or module load.
-The devices detected are ordered by their subchannel numbers. The device with
-the lowest subchannel number becomes device 0, the next one will be device 1
-and so on.
-
-
-Tape character device front-end
-
-The usual way to read or write to the tape device is through the character
-device front-end. The zSeries tape device driver provides two character devices
-for each physical device -- the first of these will rewind automatically when
-it is closed, the second will not rewind automatically.
-
-The character device nodes are named /dev/rtibm0 (rewinding) and /dev/ntibm0
-(non-rewinding) for the first device, /dev/rtibm1 and /dev/ntibm1 for the
-second, and so on.
-
-The character device front-end can be used as any other LINUX tape device. You
-can write to it and read from it using LINUX facilities such as GNU tar. The
-tool mt can be used to perform control operations, such as rewinding the tape
-or skipping a file.
-
-Most LINUX tape software should work with either tape character device.
-
-
-Tape block device front-end
-
-The tape device may also be accessed as a block device in read-only mode.
-This could be used for software installation in the same way as it is used with
-other operation systems on the zSeries platform (and most LINUX
-distributions are shipped on compact disk using ISO9660 filesystems).
-
-One block device node is provided for each physical device. These are named
-/dev/btibm0 for the first device, /dev/btibm1 for the second and so on.
-You should only use the ISO9660 filesystem on LINUX for zSeries tapes because
-the physical tape devices cannot perform fast seeks and the ISO9660 system is
-optimized for this situation.
-
-
-Tape block device example
-
-In this example a tape with an ISO9660 filesystem is created using the first
-tape device. ISO9660 filesystem support must be built into your system kernel
-for this.
-The mt command is used to issue tape commands and the mkisofs command to
-create an ISO9660 filesystem:
-
-- create a LINUX directory (somedir) with the contents of the filesystem
- mkdir somedir
- cp contents somedir
-
-- insert a tape
-
-- ensure the tape is at the beginning
- mt -f /dev/ntibm0 rewind
-
-- set the blocksize of the character driver. The blocksize 2048 bytes
- is commonly used on ISO9660 CD-Roms
- mt -f /dev/ntibm0 setblk 2048
-
-- write the filesystem to the character device driver
- mkisofs -o /dev/ntibm0 somedir
-
-- rewind the tape again
- mt -f /dev/ntibm0 rewind
-
-- Now you can mount your new filesystem as a block device:
- mount -t iso9660 -o ro,block=2048 /dev/btibm0 /mnt
-
-TODO List
-
- - Driver has to be stabilized still
-
-BUGS
-
-This driver is considered BETA, which means some weaknesses may still
-be in it.
-If an error occurs which cannot be handled by the code you will get a
-sense-data dump.In that case please do the following:
-
-1. set the tape driver debug level to maximum:
- echo 6 >/proc/s390dbf/tape/level
-
-2. re-perform the actions which produced the bug. (Hopefully the bug will
- reappear.)
-
-3. get a snapshot from the debug-feature:
- cat /proc/s390dbf/tape/hex_ascii >somefile
-
-4. Now put the snapshot together with a detailed description of the situation
- that led to the bug:
- - Which tool did you use?
- - Which hardware do you have?
- - Was your tape unit online?
- - Is it a shared tape unit?
-
-5. Send an email with your bug report to:
- mailto:Linux390@de.ibm.com
-
-
diff --git a/Documentation/scheduler/sched-arch.txt b/Documentation/scheduler/sched-arch.txt
index d43dbcbd163b..28aa1075e291 100644
--- a/Documentation/scheduler/sched-arch.txt
+++ b/Documentation/scheduler/sched-arch.txt
@@ -66,7 +66,7 @@ Your cpu_idle routines need to obey the following rules:
barrier issued (followed by a test of need_resched with
interrupts disabled, as explained in 3).
-arch/i386/kernel/process.c has examples of both polling and
+arch/x86/kernel/process.c has examples of both polling and
sleeping idle functions.
diff --git a/Documentation/scsi/BusLogic.txt b/Documentation/scsi/BusLogic.txt
index d7fbc9488b98..48e982cd6fe7 100644
--- a/Documentation/scsi/BusLogic.txt
+++ b/Documentation/scsi/BusLogic.txt
@@ -553,7 +553,7 @@ replacing "/usr/src" with wherever you keep your Linux kernel source tree:
make config
make zImage
-Then install "arch/i386/boot/zImage" as your standard kernel, run lilo if
+Then install "arch/x86/boot/zImage" as your standard kernel, run lilo if
appropriate, and reboot.
diff --git a/Documentation/serial/computone.txt b/Documentation/serial/computone.txt
index c57ea4781e5d..60a6f657c37d 100644
--- a/Documentation/serial/computone.txt
+++ b/Documentation/serial/computone.txt
@@ -87,7 +87,7 @@ c) Set address on ISA cards then:
edit /usr/src/linux/drivers/char/ip2.c
(Optional - may be specified on kernel command line now)
d) Run "make zImage" or whatever target you prefer.
-e) mv /usr/src/linux/arch/i386/boot/zImage to /boot.
+e) mv /usr/src/linux/arch/x86/boot/zImage to /boot.
f) Add new config for this kernel into /etc/lilo.conf, run "lilo"
or copy to a floppy disk and boot from that floppy disk.
g) Reboot using this kernel
diff --git a/Documentation/sound/alsa/HD-Audio-Controls.txt b/Documentation/sound/alsa/HD-Audio-Controls.txt
new file mode 100644
index 000000000000..1482035243e6
--- /dev/null
+++ b/Documentation/sound/alsa/HD-Audio-Controls.txt
@@ -0,0 +1,100 @@
+This file explains the codec-specific mixer controls.
+
+Realtek 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", "6ch",
+ and "8ch". According to the configuration, this also controls the
+ jack-retasking of multi-I/O jacks.
+
+* Auto-Mute Mode
+ This is an enum control to change the auto-mute behavior of the
+ headphone and line-out jacks. If built-in speakers and headphone
+ and/or line-out jacks are available on a machine, this controls
+ appears.
+ When there are only either headphones or line-out jacks, it gives
+ "Disabled" and "Enabled" state. When enabled, the speaker is muted
+ automatically when a jack is plugged.
+
+ When both headphone and line-out jacks are present, it gives
+ "Disabled", "Speaker Only" and "Line-Out+Speaker". When
+ speaker-only is chosen, plugging into a headphone or a line-out jack
+ mutes the speakers, but not line-outs. When line-out+speaker is
+ selected, plugging to a headphone jack mutes both speakers and
+ line-outs.
+
+
+IDT/Sigmatel codecs
+-------------------
+
+* Analog Loopback
+ This control enables/disables the analog-loopback circuit. This
+ appears only when "loopback" is set to true in a codec hint
+ (see HD-Audio.txt). Note that on some codecs the analog-loopback
+ and the normal PCM playback are exclusive, i.e. when this is on, you
+ won't hear any PCM stream.
+
+* Swap Center/LFE
+ Swaps the center and LFE channel order. Normally, the left
+ corresponds to the center and the right to the LFE. When this is
+ ON, the left to the LFE and the right to the center.
+
+* Headphone as Line Out
+ When this control is ON, treat the headphone jacks as line-out
+ jacks. That is, the headphone won't auto-mute the other line-outs,
+ and no HP-amp is set to the pins.
+
+* Mic Jack Mode, Line Jack Mode, etc
+ These enum controls the direction and the bias of the input jack
+ pins. Depending on the jack type, it can set as "Mic In" and "Line
+ In", for determining the input bias, or it can be set to "Line Out"
+ when the pin is a multi-I/O jack for surround channels.
+
+
+VIA codecs
+----------
+
+* Smart 5.1
+ An enum control to re-task the multi-I/O jacks for surround outputs.
+ When it's ON, the corresponding input jacks (usually a line-in and a
+ mic-in) are switched as the surround and the CLFE output 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. In the case the headphone DAC is shared with a
+ side or a CLFE-channel DAC, the DAC is switched to the headphone
+ automatically.
+
+* Loopback Mixing
+ An enum control to determine whether the analog-loopback route is
+ enabled or not. When it's enabled, the analog-loopback is mixed to
+ the front-channel. Also, the same route is used for the headphone
+ and speaker outputs. As a side-effect, when this mode is set, the
+ individual volume controls will be no longer available for
+ headphones and speakers because there is only one DAC connected to a
+ mixer widget.
+
+* Dynamic Power-Control
+ This control determines whether the dynamic power-control per jack
+ detection is enabled or not. When enabled, the widgets power state
+ (D0/D3) are changed dynamically depending on the jack plugging
+ state for saving power consumptions. However, if your system
+ doesn't provide a proper jack-detection, this won't work; in such a
+ case, turn this control OFF.
+
+* Jack Detect
+ This control is provided only for VT1708 codec which gives no proper
+ unsolicited event per jack plug. When this is on, the driver polls
+ the jack detection so that the headphone auto-mute can work, while
+ turning this off would reduce the power consumption.
+
+
+Conexant codecs
+---------------
+
+* Auto-Mute Mode
+ See Reatek codecs.
diff --git a/Documentation/spi/ep93xx_spi b/Documentation/spi/ep93xx_spi
index 6325f5b48635..d8eb01c15db1 100644
--- a/Documentation/spi/ep93xx_spi
+++ b/Documentation/spi/ep93xx_spi
@@ -88,6 +88,16 @@ static void __init ts72xx_init_machine(void)
ARRAY_SIZE(ts72xx_spi_devices));
}
+The driver can use DMA for the transfers also. In this case ts72xx_spi_info
+becomes:
+
+static struct ep93xx_spi_info ts72xx_spi_info = {
+ .num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
+ .use_dma = true;
+};
+
+Note that CONFIG_EP93XX_DMA should be enabled as well.
+
Thanks to
=========
Martin Guy, H. Hartley Sweeten and others who helped me during development of
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
index 493dada57372..00511e08db78 100644
--- a/Documentation/spi/pxa2xx
+++ b/Documentation/spi/pxa2xx
@@ -22,15 +22,11 @@ Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
found in include/linux/spi/pxa2xx_spi.h:
struct pxa2xx_spi_master {
- enum pxa_ssp_type ssp_type;
u32 clock_enable;
u16 num_chipselect;
u8 enable_dma;
};
-The "pxa2xx_spi_master.ssp_type" field must have a value between 1 and 3 and
-informs the driver which features a particular SSP supports.
-
The "pxa2xx_spi_master.clock_enable" field is used to enable/disable the
corresponding SSP peripheral block in the "Clock Enable Register (CKEN"). See
the "PXA2xx Developer Manual" section "Clocks and Power Management".
@@ -61,7 +57,6 @@ static struct resource pxa_spi_nssp_resources[] = {
};
static struct pxa2xx_spi_master pxa_nssp_master_info = {
- .ssp_type = PXA25x_NSSP, /* Type of SSP */
.clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */
.num_chipselect = 1, /* Matches the number of chips attached to NSSP */
.enable_dma = 1, /* Enables NSSP DMA */
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 5e7cb39ad195..704e474a93df 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -17,23 +17,21 @@ before actually making adjustments.
Currently, these files might (depending on your configuration)
show up in /proc/sys/kernel:
-- acpi_video_flags
+
- acct
+- acpi_video_flags
+- auto_msgmni
- bootloader_type [ X86 only ]
- bootloader_version [ X86 only ]
- callhome [ S390 only ]
-- auto_msgmni
- core_pattern
- core_pipe_limit
- core_uses_pid
- ctrl-alt-del
-- dentry-state
- dmesg_restrict
- domainname
- hostname
- hotplug
-- java-appletviewer [ binfmt_java, obsolete ]
-- java-interpreter [ binfmt_java, obsolete ]
- kptr_restrict
- kstack_depth_to_print [ X86 only ]
- l2cr [ PPC only ]
@@ -48,10 +46,14 @@ show up in /proc/sys/kernel:
- overflowgid
- overflowuid
- panic
+- panic_on_oops
+- panic_on_unrecovered_nmi
- pid_max
- powersave-nap [ PPC only ]
-- panic_on_unrecovered_nmi
- printk
+- printk_delay
+- printk_ratelimit
+- printk_ratelimit_burst
- randomize_va_space
- real-root-dev ==> Documentation/initrd.txt
- reboot-cmd [ SPARC only ]
@@ -59,9 +61,11 @@ show up in /proc/sys/kernel:
- rtsig-nr
- sem
- sg-big-buff [ generic SCSI device (sg) ]
+- shm_rmid_forced
- shmall
- shmmax [ sysv ipc ]
- shmmni
+- softlockup_thresh
- stop-a [ SPARC only ]
- sysrq ==> Documentation/sysrq.txt
- tainted
@@ -71,15 +75,6 @@ show up in /proc/sys/kernel:
==============================================================
-acpi_video_flags:
-
-flags
-
-See Doc*/kernel/power/video.txt, it allows mode of video boot to be
-set during run time.
-
-==============================================================
-
acct:
highwater lowwater frequency
@@ -97,6 +92,25 @@ valid for 30 seconds.
==============================================================
+acpi_video_flags:
+
+flags
+
+See Doc*/kernel/power/video.txt, it allows mode of video boot to be
+set during run time.
+
+==============================================================
+
+auto_msgmni:
+
+Enables/Disables automatic recomputing of msgmni upon memory add/remove
+or upon ipc namespace creation/removal (see the msgmni description
+above). Echoing "1" into this file enables msgmni automatic recomputing.
+Echoing "0" turns it off. auto_msgmni default value is 1.
+
+
+==============================================================
+
bootloader_type:
x86 bootloader identification
@@ -172,22 +186,24 @@ core_pattern is used to specify a core dumpfile pattern name.
core_pipe_limit:
-This sysctl is only applicable when core_pattern is configured to pipe core
-files to a user space helper (when the first character of core_pattern is a '|',
-see above). When collecting cores via a pipe to an application, it is
-occasionally useful for the collecting application to gather data about the
-crashing process from its /proc/pid directory. In order to do this safely, the
-kernel must wait for the collecting process to exit, so as not to remove the
-crashing processes proc files prematurely. This in turn creates the possibility
-that a misbehaving userspace collecting process can block the reaping of a
-crashed process simply by never exiting. This sysctl defends against that. It
-defines how many concurrent crashing processes may be piped to user space
-applications in parallel. If this value is exceeded, then those crashing
-processes above that value are noted via the kernel log and their cores are
-skipped. 0 is a special value, indicating that unlimited processes may be
-captured in parallel, but that no waiting will take place (i.e. the collecting
-process is not guaranteed access to /proc/<crashing pid>/). This value defaults
-to 0.
+This sysctl is only applicable when core_pattern is configured to pipe
+core files to a user space helper (when the first character of
+core_pattern is a '|', see above). When collecting cores via a pipe
+to an application, it is occasionally useful for the collecting
+application to gather data about the crashing process from its
+/proc/pid directory. In order to do this safely, the kernel must wait
+for the collecting process to exit, so as not to remove the crashing
+processes proc files prematurely. This in turn creates the
+possibility that a misbehaving userspace collecting process can block
+the reaping of a crashed process simply by never exiting. This sysctl
+defends against that. It defines how many concurrent crashing
+processes may be piped to user space applications in parallel. If
+this value is exceeded, then those crashing processes above that value
+are noted via the kernel log and their cores are skipped. 0 is a
+special value, indicating that unlimited processes may be captured in
+parallel, but that no waiting will take place (i.e. the collecting
+process is not guaranteed access to /proc/<crashing pid>/). This
+value defaults to 0.
==============================================================
@@ -218,14 +234,14 @@ to decide what to do with it.
dmesg_restrict:
-This toggle indicates whether unprivileged users are prevented from using
-dmesg(8) to view messages from the kernel's log buffer. When
-dmesg_restrict is set to (0) there are no restrictions. When
+This toggle indicates whether unprivileged users are prevented
+from using dmesg(8) to view messages from the kernel's log buffer.
+When dmesg_restrict is set to (0) there are no restrictions. When
dmesg_restrict is set set to (1), users must have CAP_SYSLOG to use
dmesg(8).
-The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the default
-value of dmesg_restrict.
+The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the
+default value of dmesg_restrict.
==============================================================
@@ -256,13 +272,6 @@ Default value is "/sbin/hotplug".
==============================================================
-l2cr: (PPC only)
-
-This flag controls the L2 cache of G3 processor boards. If
-0, the cache is disabled. Enabled if nonzero.
-
-==============================================================
-
kptr_restrict:
This toggle indicates whether restrictions are placed on
@@ -283,6 +292,13 @@ kernel stack.
==============================================================
+l2cr: (PPC only)
+
+This flag controls the L2 cache of G3 processor boards. If
+0, the cache is disabled. Enabled if nonzero.
+
+==============================================================
+
modules_disabled:
A toggle value indicating if modules are allowed to be loaded
@@ -293,6 +309,21 @@ to false.
==============================================================
+nmi_watchdog:
+
+Enables/Disables the NMI watchdog on x86 systems. When the value is
+non-zero the NMI watchdog is enabled and will continuously test all
+online cpus to determine whether or not they are still functioning
+properly. Currently, passing "nmi_watchdog=" parameter at boot time is
+required for this function to work.
+
+If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel
+parameter), the NMI watchdog shares registers with oprofile. By
+disabling the NMI watchdog, oprofile may have more registers to
+utilize.
+
+==============================================================
+
osrelease, ostype & version:
# cat osrelease
@@ -312,10 +343,10 @@ The only way to tune these values is to rebuild the kernel :-)
overflowgid & overflowuid:
-if your architecture did not always support 32-bit UIDs (i.e. arm, i386,
-m68k, sh, and sparc32), a fixed UID and GID will be returned to
-applications that use the old 16-bit UID/GID system calls, if the actual
-UID or GID would exceed 65535.
+if your architecture did not always support 32-bit UIDs (i.e. arm,
+i386, m68k, sh, and sparc32), a fixed UID and GID will be returned to
+applications that use the old 16-bit UID/GID system calls, if the
+actual UID or GID would exceed 65535.
These sysctls allow you to change the value of the fixed UID and GID.
The default is 65534.
@@ -324,9 +355,22 @@ The default is 65534.
panic:
-The value in this file represents the number of seconds the
-kernel waits before rebooting on a panic. When you use the
-software watchdog, the recommended setting is 60.
+The value in this file represents the number of seconds the kernel
+waits before rebooting on a panic. When you use the software watchdog,
+the recommended setting is 60.
+
+==============================================================
+
+panic_on_unrecovered_nmi:
+
+The default Linux behaviour on an NMI of either memory or unknown is
+to continue operation. For many environments such as scientific
+computing it is preferable that the box is taken out and the error
+dealt with than an uncorrected parity/ECC error get propagated.
+
+A small number of systems do generate NMI's for bizarre random reasons
+such as power management so the default is off. That sysctl works like
+the existing panic controls already in that directory.
==============================================================
@@ -376,6 +420,14 @@ the different loglevels.
==============================================================
+printk_delay:
+
+Delay each printk message in printk_delay milliseconds
+
+Value from 0 - 10000 is allowed.
+
+==============================================================
+
printk_ratelimit:
Some warning messages are rate limited. printk_ratelimit specifies
@@ -395,15 +447,7 @@ send before ratelimiting kicks in.
==============================================================
-printk_delay:
-
-Delay each printk message in printk_delay milliseconds
-
-Value from 0 - 10000 is allowed.
-
-==============================================================
-
-randomize-va-space:
+randomize_va_space:
This option can be used to select the type of process address
space randomization that is used in the system, for architectures
@@ -466,15 +510,36 @@ are doing anyway :)
==============================================================
-shmmax:
+shmmax:
This value can be used to query and set the run time limit
on the maximum shared memory segment size that can be created.
-Shared memory segments up to 1Gb are now supported in the
+Shared memory segments up to 1Gb are now supported in the
kernel. This value defaults to SHMMAX.
==============================================================
+shm_rmid_forced:
+
+Linux lets you set resource limits, including how much memory one
+process can consume, via setrlimit(2). Unfortunately, shared memory
+segments are allowed to exist without association with any process, and
+thus might not be counted against any resource limits. If enabled,
+shared memory segments are automatically destroyed when their attach
+count becomes zero after a detach or a process termination. It will
+also destroy segments that were created, but never attached to, on exit
+from the process. The only use left for IPC_RMID is to immediately
+destroy an unattached segment. Of course, this breaks the way things are
+defined, so some applications might stop working. Note that this
+feature will do you no good unless you also configure your resource
+limits (in particular, RLIMIT_AS and RLIMIT_NPROC). Most systems don't
+need this.
+
+Note that if you change this from 0 to 1, already created segments
+without users and with a dead originative process will be destroyed.
+
+==============================================================
+
softlockup_thresh:
This value can be used to lower the softlockup tolerance threshold. The
@@ -484,7 +549,7 @@ tunable to zero will disable the softlockup detection altogether.
==============================================================
-tainted:
+tainted:
Non-zero if the kernel has been tainted. Numeric values, which
can be ORed together:
@@ -509,49 +574,11 @@ can be ORed together:
==============================================================
-auto_msgmni:
-
-Enables/Disables automatic recomputing of msgmni upon memory add/remove or
-upon ipc namespace creation/removal (see the msgmni description above).
-Echoing "1" into this file enables msgmni automatic recomputing.
-Echoing "0" turns it off.
-auto_msgmni default value is 1.
-
-==============================================================
-
-nmi_watchdog:
-
-Enables/Disables the NMI watchdog on x86 systems. When the value is non-zero
-the NMI watchdog is enabled and will continuously test all online cpus to
-determine whether or not they are still functioning properly. Currently,
-passing "nmi_watchdog=" parameter at boot time is required for this function
-to work.
-
-If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel parameter), the
-NMI watchdog shares registers with oprofile. By disabling the NMI watchdog,
-oprofile may have more registers to utilize.
-
-==============================================================
-
unknown_nmi_panic:
-The value in this file affects behavior of handling NMI. When the value is
-non-zero, unknown NMI is trapped and then panic occurs. At that time, kernel
-debugging information is displayed on console.
-
-NMI switch that most IA32 servers have fires unknown NMI up, for example.
-If a system hangs up, try pressing the NMI switch.
-
-==============================================================
-
-panic_on_unrecovered_nmi:
-
-The default Linux behaviour on an NMI of either memory or unknown is to continue
-operation. For many environments such as scientific computing it is preferable
-that the box is taken out and the error dealt with than an uncorrected
-parity/ECC error get propogated.
-
-A small number of systems do generate NMI's for bizarre random reasons such as
-power management so the default is off. That sysctl works like the existing
-panic controls already in that directory.
+The value in this file affects behavior of handling NMI. When the
+value is non-zero, unknown NMI is trapped and then panic occurs. At
+that time, kernel debugging information is displayed on console.
+NMI switch that most IA32 servers have fires unknown NMI up, for
+example. If a system hangs up, try pressing the NMI switch.
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index c83bd6b4e6e8..d0d0bb9e3e25 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -22,14 +22,15 @@ current_tracer. Instead of that, add probe points via
Synopsis of kprobe_events
-------------------------
- p[:[GRP/]EVENT] SYMBOL[+offs]|MEMADDR [FETCHARGS] : Set a probe
- r[:[GRP/]EVENT] SYMBOL[+0] [FETCHARGS] : Set a return probe
+ p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe
+ r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe
-:[GRP/]EVENT : Clear a probe
GRP : Group name. If omitted, use "kprobes" for it.
EVENT : Event name. If omitted, the event name is generated
- based on SYMBOL+offs or MEMADDR.
- SYMBOL[+offs] : Symbol+offset where the probe is inserted.
+ based on SYM+offs or MEMADDR.
+ MOD : Module name which has given SYM.
+ SYM[+offs] : Symbol+offset where the probe is inserted.
MEMADDR : Address where the probe is inserted.
FETCHARGS : Arguments. Each probe can have up to 128 args.
diff --git a/Documentation/usb/ehci.txt b/Documentation/usb/ehci.txt
index 9dcafa7d930d..160bd6c3ab7b 100644
--- a/Documentation/usb/ehci.txt
+++ b/Documentation/usb/ehci.txt
@@ -210,3 +210,5 @@ TBD: Interrupt and ISO transfer performance issues. Those periodic
transfers are fully scheduled, so the main issue is likely to be how
to trigger "high bandwidth" modes.
+TBD: More than standard 80% periodic bandwidth allocation is possible
+through sysfs uframe_periodic_max parameter. Describe that.
diff --git a/Documentation/usb/gadget_hid.txt b/Documentation/usb/gadget_hid.txt
index f4a51f567427..12696c2e43fb 100644
--- a/Documentation/usb/gadget_hid.txt
+++ b/Documentation/usb/gadget_hid.txt
@@ -81,8 +81,8 @@ Send and receive HID reports
to do this.
hid_gadget_test is a small interactive program to test the HID
- gadget driver. To use, point it at a hidg device and set the
- device type (keyboard / mouse / joystick) - E.G.:
+ gadget driver. To use, point it at a hidg device and set the
+ device type (keyboard / mouse / joystick) - E.G.:
# hid_gadget_test /dev/hidg0 keyboard
@@ -97,7 +97,7 @@ Send and receive HID reports
HID gadget.
Another interesting example is the caps lock test. Type
- -–caps-lock and hit return. A report is then sent by the
+ --caps-lock and hit return. A report is then sent by the
gadget and you should receive the host answer, corresponding
to the caps lock LED status.
diff --git a/Documentation/vDSO/parse_vdso.c b/Documentation/vDSO/parse_vdso.c
new file mode 100644
index 000000000000..85870208edcf
--- /dev/null
+++ b/Documentation/vDSO/parse_vdso.c
@@ -0,0 +1,256 @@
+/*
+ * parse_vdso.c: Linux reference vDSO parser
+ * Written by Andrew Lutomirski, 2011.
+ *
+ * This code is meant to be linked in to various programs that run on Linux.
+ * As such, it is available with as few restrictions as possible. This file
+ * is licensed under the Creative Commons Zero License, version 1.0,
+ * available at http://creativecommons.org/publicdomain/zero/1.0/legalcode
+ *
+ * The vDSO is a regular ELF DSO that the kernel maps into user space when
+ * it starts a program. It works equally well in statically and dynamically
+ * linked binaries.
+ *
+ * This code is tested on x86_64. In principle it should work on any 64-bit
+ * architecture that has a vDSO.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <elf.h>
+
+/*
+ * To use this vDSO parser, first call one of the vdso_init_* functions.
+ * If you've already parsed auxv, then pass the value of AT_SYSINFO_EHDR
+ * to vdso_init_from_sysinfo_ehdr. Otherwise pass auxv to vdso_init_from_auxv.
+ * Then call vdso_sym for each symbol you want. For example, to look up
+ * gettimeofday on x86_64, use:
+ *
+ * <some pointer> = vdso_sym("LINUX_2.6", "gettimeofday");
+ * or
+ * <some pointer> = vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
+ *
+ * vdso_sym will return 0 if the symbol doesn't exist or if the init function
+ * failed or was not called. vdso_sym is a little slow, so its return value
+ * should be cached.
+ *
+ * vdso_sym is threadsafe; the init functions are not.
+ *
+ * These are the prototypes:
+ */
+extern void vdso_init_from_auxv(void *auxv);
+extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
+extern void *vdso_sym(const char *version, const char *name);
+
+
+/* And here's the code. */
+
+#ifndef __x86_64__
+# error Not yet ported to non-x86_64 architectures
+#endif
+
+static struct vdso_info
+{
+ bool valid;
+
+ /* Load information */
+ uintptr_t load_addr;
+ uintptr_t load_offset; /* load_addr - recorded vaddr */
+
+ /* Symbol table */
+ Elf64_Sym *symtab;
+ const char *symstrings;
+ Elf64_Word *bucket, *chain;
+ Elf64_Word nbucket, nchain;
+
+ /* Version table */
+ Elf64_Versym *versym;
+ Elf64_Verdef *verdef;
+} vdso_info;
+
+/* Straight from the ELF specification. */
+static unsigned long elf_hash(const unsigned char *name)
+{
+ unsigned long h = 0, g;
+ while (*name)
+ {
+ h = (h << 4) + *name++;
+ if (g = h & 0xf0000000)
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ return h;
+}
+
+void vdso_init_from_sysinfo_ehdr(uintptr_t base)
+{
+ size_t i;
+ bool found_vaddr = false;
+
+ vdso_info.valid = false;
+
+ vdso_info.load_addr = base;
+
+ Elf64_Ehdr *hdr = (Elf64_Ehdr*)base;
+ Elf64_Phdr *pt = (Elf64_Phdr*)(vdso_info.load_addr + hdr->e_phoff);
+ Elf64_Dyn *dyn = 0;
+
+ /*
+ * We need two things from the segment table: the load offset
+ * and the dynamic table.
+ */
+ for (i = 0; i < hdr->e_phnum; i++)
+ {
+ if (pt[i].p_type == PT_LOAD && !found_vaddr) {
+ found_vaddr = true;
+ vdso_info.load_offset = base
+ + (uintptr_t)pt[i].p_offset
+ - (uintptr_t)pt[i].p_vaddr;
+ } else if (pt[i].p_type == PT_DYNAMIC) {
+ dyn = (Elf64_Dyn*)(base + pt[i].p_offset);
+ }
+ }
+
+ if (!found_vaddr || !dyn)
+ return; /* Failed */
+
+ /*
+ * Fish out the useful bits of the dynamic table.
+ */
+ Elf64_Word *hash = 0;
+ vdso_info.symstrings = 0;
+ vdso_info.symtab = 0;
+ vdso_info.versym = 0;
+ vdso_info.verdef = 0;
+ for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
+ switch (dyn[i].d_tag) {
+ case DT_STRTAB:
+ vdso_info.symstrings = (const char *)
+ ((uintptr_t)dyn[i].d_un.d_ptr
+ + vdso_info.load_offset);
+ break;
+ case DT_SYMTAB:
+ vdso_info.symtab = (Elf64_Sym *)
+ ((uintptr_t)dyn[i].d_un.d_ptr
+ + vdso_info.load_offset);
+ break;
+ case DT_HASH:
+ hash = (Elf64_Word *)
+ ((uintptr_t)dyn[i].d_un.d_ptr
+ + vdso_info.load_offset);
+ break;
+ case DT_VERSYM:
+ vdso_info.versym = (Elf64_Versym *)
+ ((uintptr_t)dyn[i].d_un.d_ptr
+ + vdso_info.load_offset);
+ break;
+ case DT_VERDEF:
+ vdso_info.verdef = (Elf64_Verdef *)
+ ((uintptr_t)dyn[i].d_un.d_ptr
+ + vdso_info.load_offset);
+ break;
+ }
+ }
+ if (!vdso_info.symstrings || !vdso_info.symtab || !hash)
+ return; /* Failed */
+
+ if (!vdso_info.verdef)
+ vdso_info.versym = 0;
+
+ /* Parse the hash table header. */
+ vdso_info.nbucket = hash[0];
+ vdso_info.nchain = hash[1];
+ vdso_info.bucket = &hash[2];
+ vdso_info.chain = &hash[vdso_info.nbucket + 2];
+
+ /* That's all we need. */
+ vdso_info.valid = true;
+}
+
+static bool vdso_match_version(Elf64_Versym ver,
+ const char *name, Elf64_Word hash)
+{
+ /*
+ * This is a helper function to check if the version indexed by
+ * ver matches name (which hashes to hash).
+ *
+ * The version definition table is a mess, and I don't know how
+ * to do this in better than linear time without allocating memory
+ * to build an index. I also don't know why the table has
+ * variable size entries in the first place.
+ *
+ * For added fun, I can't find a comprehensible specification of how
+ * to parse all the weird flags in the table.
+ *
+ * So I just parse the whole table every time.
+ */
+
+ /* First step: find the version definition */
+ ver &= 0x7fff; /* Apparently bit 15 means "hidden" */
+ Elf64_Verdef *def = vdso_info.verdef;
+ while(true) {
+ if ((def->vd_flags & VER_FLG_BASE) == 0
+ && (def->vd_ndx & 0x7fff) == ver)
+ break;
+
+ if (def->vd_next == 0)
+ return false; /* No definition. */
+
+ def = (Elf64_Verdef *)((char *)def + def->vd_next);
+ }
+
+ /* Now figure out whether it matches. */
+ Elf64_Verdaux *aux = (Elf64_Verdaux*)((char *)def + def->vd_aux);
+ return def->vd_hash == hash
+ && !strcmp(name, vdso_info.symstrings + aux->vda_name);
+}
+
+void *vdso_sym(const char *version, const char *name)
+{
+ unsigned long ver_hash;
+ if (!vdso_info.valid)
+ return 0;
+
+ ver_hash = elf_hash(version);
+ Elf64_Word chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
+
+ for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
+ Elf64_Sym *sym = &vdso_info.symtab[chain];
+
+ /* Check for a defined global or weak function w/ right name. */
+ if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
+ continue;
+ if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
+ ELF64_ST_BIND(sym->st_info) != STB_WEAK)
+ continue;
+ if (sym->st_shndx == SHN_UNDEF)
+ continue;
+ if (strcmp(name, vdso_info.symstrings + sym->st_name))
+ continue;
+
+ /* Check symbol version. */
+ if (vdso_info.versym
+ && !vdso_match_version(vdso_info.versym[chain],
+ version, ver_hash))
+ continue;
+
+ return (void *)(vdso_info.load_offset + sym->st_value);
+ }
+
+ return 0;
+}
+
+void vdso_init_from_auxv(void *auxv)
+{
+ Elf64_auxv_t *elf_auxv = auxv;
+ for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++)
+ {
+ if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
+ vdso_init_from_sysinfo_ehdr(elf_auxv[i].a_un.a_val);
+ return;
+ }
+ }
+
+ vdso_info.valid = false;
+}
diff --git a/Documentation/vDSO/vdso_test.c b/Documentation/vDSO/vdso_test.c
new file mode 100644
index 000000000000..fff633432dff
--- /dev/null
+++ b/Documentation/vDSO/vdso_test.c
@@ -0,0 +1,111 @@
+/*
+ * vdso_test.c: Sample code to test parse_vdso.c on x86_64
+ * Copyright (c) 2011 Andy Lutomirski
+ * Subject to the GNU General Public License, version 2
+ *
+ * You can amuse yourself by compiling with:
+ * gcc -std=gnu99 -nostdlib
+ * -Os -fno-asynchronous-unwind-tables -flto
+ * vdso_test.c parse_vdso.c -o vdso_test
+ * to generate a small binary with no dependencies at all.
+ */
+
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdint.h>
+
+extern void *vdso_sym(const char *version, const char *name);
+extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
+extern void vdso_init_from_auxv(void *auxv);
+
+/* We need a libc functions... */
+int strcmp(const char *a, const char *b)
+{
+ /* This implementation is buggy: it never returns -1. */
+ while (*a || *b) {
+ if (*a != *b)
+ return 1;
+ if (*a == 0 || *b == 0)
+ return 1;
+ a++;
+ b++;
+ }
+
+ return 0;
+}
+
+/* ...and two syscalls. This is x86_64-specific. */
+static inline long linux_write(int fd, const void *data, size_t len)
+{
+
+ long ret;
+ asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write),
+ "D" (fd), "S" (data), "d" (len) :
+ "cc", "memory", "rcx",
+ "r8", "r9", "r10", "r11" );
+ return ret;
+}
+
+static inline void linux_exit(int code)
+{
+ asm volatile ("syscall" : : "a" (__NR_exit), "D" (code));
+}
+
+void to_base10(char *lastdig, uint64_t n)
+{
+ while (n) {
+ *lastdig = (n % 10) + '0';
+ n /= 10;
+ lastdig--;
+ }
+}
+
+__attribute__((externally_visible)) void c_main(void **stack)
+{
+ /* Parse the stack */
+ long argc = (long)*stack;
+ stack += argc + 2;
+
+ /* Now we're pointing at the environment. Skip it. */
+ while(*stack)
+ stack++;
+ stack++;
+
+ /* Now we're pointing at auxv. Initialize the vDSO parser. */
+ vdso_init_from_auxv((void *)stack);
+
+ /* Find gettimeofday. */
+ typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
+ gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
+
+ if (!gtod)
+ linux_exit(1);
+
+ struct timeval tv;
+ long ret = gtod(&tv, 0);
+
+ if (ret == 0) {
+ char buf[] = "The time is .000000\n";
+ to_base10(buf + 31, tv.tv_sec);
+ to_base10(buf + 38, tv.tv_usec);
+ linux_write(1, buf, sizeof(buf) - 1);
+ } else {
+ linux_exit(ret);
+ }
+
+ linux_exit(0);
+}
+
+/*
+ * This is the real entry point. It passes the initial stack into
+ * the C entry point.
+ */
+asm (
+ ".text\n"
+ ".global _start\n"
+ ".type _start,@function\n"
+ "_start:\n\t"
+ "mov %rsp,%rdi\n\t"
+ "jmp c_main"
+ );
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 42542eb802ca..b0e4b9cd6a66 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -180,6 +180,19 @@ KVM_CHECK_EXTENSION ioctl() to determine the value for max_vcpus at run-time.
If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
cpus max.
+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.
+
4.8 KVM_GET_DIRTY_LOG (vm ioctl)
Capability: basic
@@ -1143,15 +1156,10 @@ Assigns an IRQ to a passed-through device.
struct kvm_assigned_irq {
__u32 assigned_dev_id;
- __u32 host_irq;
+ __u32 host_irq; /* ignored (legacy field) */
__u32 guest_irq;
__u32 flags;
union {
- struct {
- __u32 addr_lo;
- __u32 addr_hi;
- __u32 data;
- } guest_msi;
__u32 reserved[12];
};
};
@@ -1239,8 +1247,10 @@ Type: vm ioctl
Parameters: struct kvm_assigned_msix_nr (in)
Returns: 0 on success, -1 on error
-Set the number of MSI-X interrupts for an assigned device. This service can
-only be called once in the lifetime of an assigned device.
+Set the number of MSI-X interrupts for an assigned device. The number is
+reset again by terminating the MSI-X assignment of the device via
+KVM_DEASSIGN_DEV_IRQ. Calling this service more than once at any earlier
+point will fail.
struct kvm_assigned_msix_nr {
__u32 assigned_dev_id;
@@ -1291,6 +1301,135 @@ Returns the tsc frequency of the guest. The unit of the return value is
KHz. If the host has unstable tsc this ioctl returns -EIO instead as an
error.
+4.56 KVM_GET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (out)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+ char regs[KVM_APIC_REG_SIZE];
+};
+
+Reads the Local APIC registers and copies them into the input argument. The
+data format and layout are the same as documented in the architecture manual.
+
+4.57 KVM_SET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (in)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+ char regs[KVM_APIC_REG_SIZE];
+};
+
+Copies the input argument into the the Local APIC registers. The data format
+and layout are the same as documented in the architecture manual.
+
+4.58 KVM_IOEVENTFD
+
+Capability: KVM_CAP_IOEVENTFD
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_ioeventfd (in)
+Returns: 0 on success, !0 on error
+
+This ioctl attaches or detaches an ioeventfd to a legal pio/mmio address
+within the guest. A guest write in the registered address will signal the
+provided event instead of triggering an exit.
+
+struct kvm_ioeventfd {
+ __u64 datamatch;
+ __u64 addr; /* legal pio/mmio address */
+ __u32 len; /* 1, 2, 4, or 8 bytes */
+ __s32 fd;
+ __u32 flags;
+ __u8 pad[36];
+};
+
+The following flags are defined:
+
+#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
+#define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
+#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
+
+If datamatch flag is set, the event will be signaled only if the written value
+to the registered address is equal to datamatch in struct kvm_ioeventfd.
+
+4.62 KVM_CREATE_SPAPR_TCE
+
+Capability: KVM_CAP_SPAPR_TCE
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_create_spapr_tce (in)
+Returns: file descriptor for manipulating the created TCE table
+
+This creates a virtual TCE (translation control entry) table, which
+is an IOMMU for PAPR-style virtual I/O. It is used to translate
+logical addresses used in virtual I/O into guest physical addresses,
+and provides a scatter/gather capability for PAPR virtual I/O.
+
+/* for KVM_CAP_SPAPR_TCE */
+struct kvm_create_spapr_tce {
+ __u64 liobn;
+ __u32 window_size;
+};
+
+The liobn field gives the logical IO bus number for which to create a
+TCE table. The window_size field specifies the size of the DMA window
+which this TCE table will translate - the table will contain one 64
+bit TCE entry for every 4kiB of the DMA window.
+
+When the guest issues an H_PUT_TCE hcall on a liobn for which a TCE
+table has been created using this ioctl(), the kernel will handle it
+in real mode, updating the TCE table. H_PUT_TCE calls for other
+liobns will cause a vm exit and must be handled by userspace.
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the created TCE table into userspace. This lets userspace read
+the entries written by kernel-handled H_PUT_TCE calls, and also lets
+userspace update the TCE table directly which is useful in some
+circumstances.
+
+4.63 KVM_ALLOCATE_RMA
+
+Capability: KVM_CAP_PPC_RMA
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_allocate_rma (out)
+Returns: file descriptor for mapping the allocated RMA
+
+This allocates a Real Mode Area (RMA) from the pool allocated at boot
+time by the kernel. An RMA is a physically-contiguous, aligned region
+of memory used on older POWER processors to provide the memory which
+will be accessed by real-mode (MMU off) accesses in a KVM guest.
+POWER processors support a set of sizes for the RMA that usually
+includes 64MB, 128MB, 256MB and some larger powers of two.
+
+/* for KVM_ALLOCATE_RMA */
+struct kvm_allocate_rma {
+ __u64 rma_size;
+};
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the allocated RMA into userspace. The mapped area can then be
+passed to the KVM_SET_USER_MEMORY_REGION ioctl to establish it as the
+RMA for a virtual machine. The size of the RMA in bytes (which is
+fixed at host kernel boot time) is returned in the rma_size field of
+the argument structure.
+
+The KVM_CAP_PPC_RMA capability is 1 or 2 if the KVM_ALLOCATE_RMA ioctl
+is supported; 2 if the processor requires all virtual machines to have
+an RMA, or 1 if the processor can use an RMA but doesn't require it,
+because it supports the Virtual RMA (VRMA) facility.
+
5. The kvm_run structure
Application code obtains a pointer to the kvm_run structure by
@@ -1473,6 +1612,23 @@ Userspace can now handle the hypercall and when it's done modify the gprs as
necessary. Upon guest entry all guest GPRs will then be replaced by the values
in this struct.
+ /* KVM_EXIT_PAPR_HCALL */
+ struct {
+ __u64 nr;
+ __u64 ret;
+ __u64 args[9];
+ } papr_hcall;
+
+This is used on 64-bit PowerPC when emulating a pSeries partition,
+e.g. with the 'pseries' machine type in qemu. It occurs when the
+guest does a hypercall using the 'sc 1' instruction. The 'nr' field
+contains the hypercall number (from the guest R3), and 'args' contains
+the arguments (from the guest R4 - R12). Userspace should put the
+return code in 'ret' and any extra returned values in args[].
+The possible hypercalls are defined in the Power Architecture Platform
+Requirements (PAPR) document available from www.power.org (free
+developer registration required to access it).
+
/* Fix the size of the union. */
char padding[256];
};
diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt
index f46aa58389ca..5dc972c09b55 100644
--- a/Documentation/virtual/kvm/mmu.txt
+++ b/Documentation/virtual/kvm/mmu.txt
@@ -165,6 +165,10 @@ Shadow pages contain the following information:
Contains the value of efer.nxe for which the page is valid.
role.cr0_wp:
Contains the value of cr0.wp for which the page is valid.
+ role.smep_andnot_wp:
+ Contains the value of cr4.smep && !cr0.wp for which the page is valid
+ (pages for which this is true are different from other pages; see the
+ treatment of cr0.wp=0 below).
gfn:
Either the guest page table containing the translations shadowed by this
page, or the base page frame for linear translations. See role.direct.
@@ -317,6 +321,20 @@ on fault type:
(user write faults generate a #PF)
+In the first case there is an additional complication if CR4.SMEP is
+enabled: since we've turned the page into a kernel page, the kernel may now
+execute it. We handle this by also setting spte.nx. If we get a user
+fetch or read fault, we'll change spte.u=1 and spte.nx=gpte.nx back.
+
+To prevent an spte that was converted into a kernel page with cr0.wp=0
+from being written by the kernel after cr0.wp has changed to 1, we make
+the value of cr0.wp part of the page role. This means that an spte created
+with one value of cr0.wp cannot be used when cr0.wp has a different value -
+it will simply be missed by the shadow page lookup code. A similar issue
+exists when an spte created with cr0.wp=0 and cr4.smep=0 is used after
+changing cr4.smep to 1. To avoid this, the value of !cr0.wp && cr4.smep
+is also made a part of the page role.
+
Large pages
===========
diff --git a/Documentation/virtual/kvm/msr.txt b/Documentation/virtual/kvm/msr.txt
index d079aed27e03..50317809113d 100644
--- a/Documentation/virtual/kvm/msr.txt
+++ b/Documentation/virtual/kvm/msr.txt
@@ -185,3 +185,37 @@ MSR_KVM_ASYNC_PF_EN: 0x4b564d02
Currently type 2 APF will be always delivered on the same vcpu as
type 1 was, but guest should not rely on that.
+
+MSR_KVM_STEAL_TIME: 0x4b564d03
+
+ data: 64-byte alignment physical address of a memory area which must be
+ in guest RAM, plus an enable bit in bit 0. This memory is expected to
+ hold a copy of the following structure:
+
+ struct kvm_steal_time {
+ __u64 steal;
+ __u32 version;
+ __u32 flags;
+ __u32 pad[12];
+ }
+
+ whose data will be filled in by the hypervisor periodically. Only one
+ write, or registration, is needed for each VCPU. The interval between
+ updates of this structure is arbitrary and implementation-dependent.
+ The hypervisor may update this structure at any time it sees fit until
+ anything with bit0 == 0 is written to it. Guest is required to make sure
+ this structure is initialized to zero.
+
+ Fields have the following meanings:
+
+ version: a sequence counter. In other words, guest has to check
+ this field before and after grabbing time information and make
+ sure they are both equal and even. An odd version indicates an
+ in-progress update.
+
+ flags: At this point, always zero. May be used to indicate
+ changes in this structure in the future.
+
+ steal: the amount of time in which this vCPU did not run, in
+ nanoseconds. Time during which the vcpu is idle, will not be
+ reported as steal time.
diff --git a/Documentation/virtual/kvm/nested-vmx.txt b/Documentation/virtual/kvm/nested-vmx.txt
new file mode 100644
index 000000000000..8ed937de1163
--- /dev/null
+++ b/Documentation/virtual/kvm/nested-vmx.txt
@@ -0,0 +1,251 @@
+Nested VMX
+==========
+
+Overview
+---------
+
+On Intel processors, KVM uses Intel's VMX (Virtual-Machine eXtensions)
+to easily and efficiently run guest operating systems. Normally, these guests
+*cannot* themselves be hypervisors running their own guests, because in VMX,
+guests cannot use VMX instructions.
+
+The "Nested VMX" feature adds this missing capability - of running guest
+hypervisors (which use VMX) with their own nested guests. It does so by
+allowing a guest to use VMX instructions, and correctly and efficiently
+emulating them using the single level of VMX available in the hardware.
+
+We describe in much greater detail the theory behind the nested VMX feature,
+its implementation and its performance characteristics, in the OSDI 2010 paper
+"The Turtles Project: Design and Implementation of Nested Virtualization",
+available at:
+
+ http://www.usenix.org/events/osdi10/tech/full_papers/Ben-Yehuda.pdf
+
+
+Terminology
+-----------
+
+Single-level virtualization has two levels - the host (KVM) and the guests.
+In nested virtualization, we have three levels: The host (KVM), which we call
+L0, the guest hypervisor, which we call L1, and its nested guest, which we
+call L2.
+
+
+Known limitations
+-----------------
+
+The current code supports running Linux guests under KVM guests.
+Only 64-bit guest hypervisors are supported.
+
+Additional patches for running Windows under guest KVM, and Linux under
+guest VMware server, and support for nested EPT, are currently running in
+the lab, and will be sent as follow-on patchsets.
+
+
+Running nested VMX
+------------------
+
+The nested VMX feature is disabled by default. It can be enabled by giving
+the "nested=1" option to the kvm-intel module.
+
+No modifications are required to user space (qemu). However, qemu's default
+emulated CPU type (qemu64) does not list the "VMX" CPU feature, so it must be
+explicitly enabled, by giving qemu one of the following options:
+
+ -cpu host (emulated CPU has all features of the real CPU)
+
+ -cpu qemu64,+vmx (add just the vmx feature to a named CPU type)
+
+
+ABIs
+----
+
+Nested VMX aims to present a standard and (eventually) fully-functional VMX
+implementation for the a guest hypervisor to use. As such, the official
+specification of the ABI that it provides is Intel's VMX specification,
+namely volume 3B of their "Intel 64 and IA-32 Architectures Software
+Developer's Manual". Not all of VMX's features are currently fully supported,
+but the goal is to eventually support them all, starting with the VMX features
+which are used in practice by popular hypervisors (KVM and others).
+
+As a VMX implementation, nested VMX presents a VMCS structure to L1.
+As mandated by the spec, other than the two fields revision_id and abort,
+this structure is *opaque* to its user, who is not supposed to know or care
+about its internal structure. Rather, the structure is accessed through the
+VMREAD and VMWRITE instructions.
+Still, for debugging purposes, KVM developers might be interested to know the
+internals of this structure; This is struct vmcs12 from arch/x86/kvm/vmx.c.
+
+The name "vmcs12" refers to the VMCS that L1 builds for L2. In the code we
+also have "vmcs01", the VMCS that L0 built for L1, and "vmcs02" is the VMCS
+which L0 builds to actually run L2 - how this is done is explained in the
+aforementioned paper.
+
+For convenience, we repeat the content of struct vmcs12 here. If the internals
+of this structure changes, this can break live migration across KVM versions.
+VMCS12_REVISION (from vmx.c) should be changed if struct vmcs12 or its inner
+struct shadow_vmcs is ever changed.
+
+ typedef u64 natural_width;
+ struct __packed vmcs12 {
+ /* According to the Intel spec, a VMCS region must start with
+ * these two user-visible fields */
+ u32 revision_id;
+ u32 abort;
+
+ u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+ u32 padding[7]; /* room for future expansion */
+
+ u64 io_bitmap_a;
+ u64 io_bitmap_b;
+ u64 msr_bitmap;
+ u64 vm_exit_msr_store_addr;
+ u64 vm_exit_msr_load_addr;
+ u64 vm_entry_msr_load_addr;
+ u64 tsc_offset;
+ u64 virtual_apic_page_addr;
+ u64 apic_access_addr;
+ u64 ept_pointer;
+ u64 guest_physical_address;
+ u64 vmcs_link_pointer;
+ u64 guest_ia32_debugctl;
+ u64 guest_ia32_pat;
+ u64 guest_ia32_efer;
+ u64 guest_pdptr0;
+ u64 guest_pdptr1;
+ u64 guest_pdptr2;
+ u64 guest_pdptr3;
+ u64 host_ia32_pat;
+ u64 host_ia32_efer;
+ u64 padding64[8]; /* room for future expansion */
+ natural_width cr0_guest_host_mask;
+ natural_width cr4_guest_host_mask;
+ natural_width cr0_read_shadow;
+ natural_width cr4_read_shadow;
+ natural_width cr3_target_value0;
+ natural_width cr3_target_value1;
+ natural_width cr3_target_value2;
+ natural_width cr3_target_value3;
+ natural_width exit_qualification;
+ natural_width guest_linear_address;
+ natural_width guest_cr0;
+ natural_width guest_cr3;
+ natural_width guest_cr4;
+ natural_width guest_es_base;
+ natural_width guest_cs_base;
+ natural_width guest_ss_base;
+ natural_width guest_ds_base;
+ natural_width guest_fs_base;
+ natural_width guest_gs_base;
+ natural_width guest_ldtr_base;
+ natural_width guest_tr_base;
+ natural_width guest_gdtr_base;
+ natural_width guest_idtr_base;
+ natural_width guest_dr7;
+ natural_width guest_rsp;
+ natural_width guest_rip;
+ natural_width guest_rflags;
+ natural_width guest_pending_dbg_exceptions;
+ natural_width guest_sysenter_esp;
+ natural_width guest_sysenter_eip;
+ natural_width host_cr0;
+ natural_width host_cr3;
+ natural_width host_cr4;
+ natural_width host_fs_base;
+ natural_width host_gs_base;
+ natural_width host_tr_base;
+ natural_width host_gdtr_base;
+ natural_width host_idtr_base;
+ natural_width host_ia32_sysenter_esp;
+ natural_width host_ia32_sysenter_eip;
+ natural_width host_rsp;
+ natural_width host_rip;
+ natural_width paddingl[8]; /* room for future expansion */
+ u32 pin_based_vm_exec_control;
+ u32 cpu_based_vm_exec_control;
+ u32 exception_bitmap;
+ u32 page_fault_error_code_mask;
+ u32 page_fault_error_code_match;
+ u32 cr3_target_count;
+ u32 vm_exit_controls;
+ u32 vm_exit_msr_store_count;
+ u32 vm_exit_msr_load_count;
+ u32 vm_entry_controls;
+ u32 vm_entry_msr_load_count;
+ u32 vm_entry_intr_info_field;
+ u32 vm_entry_exception_error_code;
+ u32 vm_entry_instruction_len;
+ u32 tpr_threshold;
+ u32 secondary_vm_exec_control;
+ u32 vm_instruction_error;
+ u32 vm_exit_reason;
+ u32 vm_exit_intr_info;
+ u32 vm_exit_intr_error_code;
+ u32 idt_vectoring_info_field;
+ u32 idt_vectoring_error_code;
+ u32 vm_exit_instruction_len;
+ u32 vmx_instruction_info;
+ u32 guest_es_limit;
+ u32 guest_cs_limit;
+ u32 guest_ss_limit;
+ u32 guest_ds_limit;
+ u32 guest_fs_limit;
+ u32 guest_gs_limit;
+ u32 guest_ldtr_limit;
+ u32 guest_tr_limit;
+ u32 guest_gdtr_limit;
+ u32 guest_idtr_limit;
+ u32 guest_es_ar_bytes;
+ u32 guest_cs_ar_bytes;
+ u32 guest_ss_ar_bytes;
+ u32 guest_ds_ar_bytes;
+ u32 guest_fs_ar_bytes;
+ u32 guest_gs_ar_bytes;
+ u32 guest_ldtr_ar_bytes;
+ u32 guest_tr_ar_bytes;
+ u32 guest_interruptibility_info;
+ u32 guest_activity_state;
+ u32 guest_sysenter_cs;
+ u32 host_ia32_sysenter_cs;
+ u32 padding32[8]; /* room for future expansion */
+ u16 virtual_processor_id;
+ u16 guest_es_selector;
+ u16 guest_cs_selector;
+ u16 guest_ss_selector;
+ u16 guest_ds_selector;
+ u16 guest_fs_selector;
+ u16 guest_gs_selector;
+ u16 guest_ldtr_selector;
+ u16 guest_tr_selector;
+ u16 host_es_selector;
+ u16 host_cs_selector;
+ u16 host_ss_selector;
+ u16 host_ds_selector;
+ u16 host_fs_selector;
+ u16 host_gs_selector;
+ u16 host_tr_selector;
+ };
+
+
+Authors
+-------
+
+These patches were written by:
+ Abel Gordon, abelg <at> il.ibm.com
+ Nadav Har'El, nyh <at> il.ibm.com
+ Orit Wasserman, oritw <at> il.ibm.com
+ Ben-Ami Yassor, benami <at> il.ibm.com
+ Muli Ben-Yehuda, muli <at> il.ibm.com
+
+With contributions by:
+ Anthony Liguori, aliguori <at> us.ibm.com
+ Mike Day, mdday <at> us.ibm.com
+ Michael Factor, factor <at> il.ibm.com
+ Zvi Dubitzky, dubi <at> il.ibm.com
+
+And valuable reviews by:
+ Avi Kivity, avi <at> redhat.com
+ Gleb Natapov, gleb <at> redhat.com
+ Marcelo Tosatti, mtosatti <at> redhat.com
+ Kevin Tian, kevin.tian <at> intel.com
+ and others.
diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virtual/kvm/ppc-pv.txt
index 3ab969c59046..2b7ce190cde4 100644
--- a/Documentation/virtual/kvm/ppc-pv.txt
+++ b/Documentation/virtual/kvm/ppc-pv.txt
@@ -68,9 +68,11 @@ page that contains parts of supervisor visible register state. The guest can
map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
With this hypercall issued the guest always gets the magic page mapped at the
-desired location in effective and physical address space. For now, we always
-map the page to -4096. This way we can access it using absolute load and store
-functions. The following instruction reads the first field of the magic page:
+desired location. The first parameter indicates the effective address when the
+MMU is enabled. The second parameter indicates the address in real mode, if
+applicable to the target. For now, we always map the page to -4096. This way we
+can access it using absolute load and store functions. The following
+instruction reads the first field of the magic page:
ld rX, -4096(0)
diff --git a/Documentation/virtual/lguest/lguest.c b/Documentation/virtual/lguest/lguest.c
index cd9d6af61d07..043bd7df3139 100644
--- a/Documentation/virtual/lguest/lguest.c
+++ b/Documentation/virtual/lguest/lguest.c
@@ -51,7 +51,7 @@
#include <asm/bootparam.h>
#include "../../../include/linux/lguest_launcher.h"
/*L:110
- * We can ignore the 42 include files we need for this program, but I do want
+ * We can ignore the 43 include files we need for this program, but I do want
* to draw attention to the use of kernel-style types.
*
* As Linus said, "C is a Spartan language, and so should your naming be." I
@@ -65,7 +65,6 @@ typedef uint16_t u16;
typedef uint8_t u8;
/*:*/
-#define PAGE_PRESENT 0x7 /* Present, RW, Execute */
#define BRIDGE_PFX "bridge:"
#ifndef SIOCBRADDIF
#define SIOCBRADDIF 0x89a2 /* add interface to bridge */
@@ -861,8 +860,10 @@ static void console_output(struct virtqueue *vq)
/* writev can return a partial write, so we loop here. */
while (!iov_empty(iov, out)) {
int len = writev(STDOUT_FILENO, iov, out);
- if (len <= 0)
- err(1, "Write to stdout gave %i", len);
+ if (len <= 0) {
+ warn("Write to stdout gave %i (%d)", len, errno);
+ break;
+ }
iov_consume(iov, out, len);
}
@@ -898,7 +899,7 @@ static void net_output(struct virtqueue *vq)
* same format: what a coincidence!
*/
if (writev(net_info->tunfd, iov, out) < 0)
- errx(1, "Write to tun failed?");
+ warnx("Write to tun failed (%d)?", errno);
/*
* Done with that one; wait_for_vq_desc() will send the interrupt if
@@ -955,7 +956,7 @@ static void net_input(struct virtqueue *vq)
*/
len = readv(net_info->tunfd, iov, in);
if (len <= 0)
- err(1, "Failed to read from tun.");
+ warn("Failed to read from tun (%d).", errno);
/*
* Mark that packet buffer as used, but don't interrupt here. We want
@@ -1093,9 +1094,10 @@ static void update_device_status(struct device *dev)
warnx("Device %s configuration FAILED", dev->name);
if (dev->running)
reset_device(dev);
- } else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
- if (!dev->running)
- start_device(dev);
+ } else {
+ if (dev->running)
+ err(1, "Device %s features finalized twice", dev->name);
+ start_device(dev);
}
}
@@ -1120,25 +1122,11 @@ static void handle_output(unsigned long addr)
return;
}
- /*
- * Devices *can* be used before status is set to DRIVER_OK.
- * The original plan was that they would never do this: they
- * would always finish setting up their status bits before
- * actually touching the virtqueues. In practice, we allowed
- * them to, and they do (eg. the disk probes for partition
- * tables as part of initialization).
- *
- * If we see this, we start the device: once it's running, we
- * expect the device to catch all the notifications.
- */
+ /* Devices should not be used before features are finalized. */
for (vq = i->vq; vq; vq = vq->next) {
if (addr != vq->config.pfn*getpagesize())
continue;
- if (i->running)
- errx(1, "Notification on running %s", i->name);
- /* This just calls create_thread() for each virtqueue */
- start_device(i);
- return;
+ errx(1, "Notification on %s before setup!", i->name);
}
}
@@ -1370,7 +1358,7 @@ static void setup_console(void)
* --sharenet=<name> option which opens or creates a named pipe. This can be
* used to send packets to another guest in a 1:1 manner.
*
- * More sopisticated is to use one of the tools developed for project like UML
+ * More sophisticated is to use one of the tools developed for project like UML
* to do networking.
*
* Faster is to do virtio bonding in kernel. Doing this 1:1 would be
@@ -1380,7 +1368,7 @@ static void setup_console(void)
* multiple inter-guest channels behind one interface, although it would
* require some manner of hotplugging new virtio channels.
*
- * Finally, we could implement a virtio network switch in the kernel.
+ * Finally, we could use a virtio network switch in the kernel, ie. vhost.
:*/
static u32 str2ip(const char *ipaddr)
@@ -2017,10 +2005,7 @@ int main(int argc, char *argv[])
/* Tell the entry path not to try to reload segment registers. */
boot->hdr.loadflags |= KEEP_SEGMENTS;
- /*
- * We tell the kernel to initialize the Guest: this returns the open
- * /dev/lguest file descriptor.
- */
+ /* We tell the kernel to initialize the Guest. */
tell_kernel(start);
/* Ensure that we terminate if a device-servicing child dies. */
diff --git a/Documentation/x86/entry_64.txt b/Documentation/x86/entry_64.txt
new file mode 100644
index 000000000000..7869f14d055c
--- /dev/null
+++ b/Documentation/x86/entry_64.txt
@@ -0,0 +1,98 @@
+This file documents some of the kernel entries in
+arch/x86/kernel/entry_64.S. A lot of this explanation is adapted from
+an email from Ingo Molnar:
+
+http://lkml.kernel.org/r/<20110529191055.GC9835%40elte.hu>
+
+The x86 architecture has quite a few different ways to jump into
+kernel code. Most of these entry points are registered in
+arch/x86/kernel/traps.c and implemented in arch/x86/kernel/entry_64.S
+and arch/x86/ia32/ia32entry.S.
+
+The IDT vector assignments are listed in arch/x86/include/irq_vectors.h.
+
+Some of these entries are:
+
+ - system_call: syscall instruction from 64-bit code.
+
+ - ia32_syscall: int 0x80 from 32-bit or 64-bit code; compat syscall
+ either way.
+
+ - ia32_syscall, ia32_sysenter: syscall and sysenter from 32-bit
+ code
+
+ - interrupt: An array of entries. Every IDT vector that doesn't
+ explicitly point somewhere else gets set to the corresponding
+ value in interrupts. These point to a whole array of
+ 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.
+
+ - Architecturally-defined exceptions like divide_error.
+
+There are a few complexities here. The different x86-64 entries
+have different calling conventions. The syscall and sysenter
+instructions have their own peculiar calling conventions. Some of
+the IDT entries push an error code onto the stack; others don't.
+IDT entries using the IST alternative stack mechanism need their own
+magic to get the stack frames right. (You can find some
+documentation in the AMD APM, Volume 2, Chapter 8 and the Intel SDM,
+Volume 3, Chapter 6.)
+
+Dealing with the swapgs instruction is especially tricky. Swapgs
+toggles whether gs is the kernel gs or the user gs. The swapgs
+instruction is rather fragile: it must nest perfectly and only in
+single depth, it should only be used if entering from user mode to
+kernel mode and then when returning to user-space, and precisely
+so. If we mess that up even slightly, we crash.
+
+So when we have a secondary entry, already in kernel mode, we *must
+not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's
+not switched/swapped yet.
+
+Now, there's a secondary complication: there's a cheap way to test
+which mode the CPU is in and an expensive way.
+
+The cheap way is to pick this info off the entry frame on the kernel
+stack, from the CS of the ptregs area of the kernel stack:
+
+ xorl %ebx,%ebx
+ testl $3,CS+8(%rsp)
+ je error_kernelspace
+ SWAPGS
+
+The expensive (paranoid) way is to read back the MSR_GS_BASE value
+(which is what SWAPGS modifies):
+
+ movl $1,%ebx
+ movl $MSR_GS_BASE,%ecx
+ rdmsr
+ testl %edx,%edx
+ js 1f /* negative -> in kernel */
+ SWAPGS
+ xorl %ebx,%ebx
+1: ret
+
+and the whole paranoid non-paranoid macro complexity is about whether
+to suffer that RDMSR cost.
+
+If we are at an interrupt or user-trap/gate-alike boundary then we can
+use the faster check: the stack will be a reliable indicator of
+whether SWAPGS was already done: if we see that we are a secondary
+entry interrupting kernel mode execution, then we know that the GS
+base has already been switched. If it says that we interrupted
+user-space execution then we must do the SWAPGS.
+
+But if we are in an NMI/MCE/DEBUG/whatever super-atomic entry context,
+which might have triggered right after a normal entry wrote CS to the
+stack but before we executed SWAPGS, then the only safe way to check
+for GS is the slower method: the RDMSR.
+
+So we try only to mark those entry methods 'paranoid' that absolutely
+need the more expensive check for the GS base - and we generate all
+'normal' entry points with the regular (faster) entry macros.
diff --git a/Documentation/zh_CN/SubmitChecklist b/Documentation/zh_CN/SubmitChecklist
index 951415bbab0c..4c741d6bc048 100644
--- a/Documentation/zh_CN/SubmitChecklist
+++ b/Documentation/zh_CN/SubmitChecklist
@@ -67,7 +67,7 @@ LinuxÄÚºËÌá½»Çåµ¥
12£ºÒѾ­Í¨¹ýCONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
- CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP²âÊÔ£¬²¢ÇÒͬʱ¶¼
+ CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP²âÊÔ£¬²¢ÇÒͬʱ¶¼
ʹÄÜ¡£
13£ºÒѾ­¶¼¹¹½¨²¢ÇÒʹÓûòÕß²»Ê¹Óà CONFIG_SMP ºÍ CONFIG_PREEMPT²âÊÔÖ´ÐÐʱ¼ä¡£
diff --git a/Documentation/zh_CN/email-clients.txt b/Documentation/zh_CN/email-clients.txt
index 5d65e323d060..b9a1a3e6c78d 100644
--- a/Documentation/zh_CN/email-clients.txt
+++ b/Documentation/zh_CN/email-clients.txt
@@ -1,4 +1,4 @@
-锘?Chinese translated version of Documentation/email-clients.txt
+Chinese translated version of Documentation/email-clients.txt
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -8,203 +8,203 @@ or if there is a problem with the translation.
Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
---------------------------------------------------------------------
-Documentation/email-clients.txt ???涓????缈�?
+Documentation/email-clients.txt 的中文翻译
-æ¿¡??????å® ??ç’烘????å­˜?版???????????瀹癸??璇风?å­˜?ヨ??绯诲?????妗g??ç¼å­˜?よ?????æ¿¡????æµ£?浣跨?ㄨ?辨??
-浜ゆ???????ä¼´?剧??ç’‡?é”›?æ¶”????浠ュ??æ¶“???????ç¼å­˜?よ??å§¹???┿??æ¿¡???????缈æ˜????å­˜?é¢???????舵?????缈?
-ç’‡?瀛???ã„©??棰?é”›?璇疯??绯讳腑??????ç¼å­˜?よ?????
+如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
+äº¤æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
+译存在问题,请è”系中文版维护者。
-æ¶“???????ç¼å­˜?よ??é”›? ç’æƒ§??濞? Harry Wei <harryxiyou@gmail.com>
-æ¶“???????缈æ˜?????é”›? ç’æƒ§??濞? Harry Wei <harryxiyou@gmail.com>
-涓?????????¤?????锛? Yinglin Luan <synmyth@gmail.com>
+中文版维护者: è´¾å¨å¨ Harry Wei <harryxiyou@gmail.com>
+中文版翻译者: è´¾å¨å¨ Harry Wei <harryxiyou@gmail.com>
+中文版校译者: Yinglin Luan <synmyth@gmail.com>
Xiaochen Wang <wangxiaochen0@gmail.com>
yaxinsn <yaxinsn@163.com>
-浠ヤ??涓烘?f??
+以下为正文
---------------------------------------------------------------------
-Linux???浠跺?㈡?风?????缃?淇℃??
+Linux邮件客户端é…置信æ¯
======================================================================
-?????????缃?
+普通é…ç½®
----------------------------------------------------------------------
-Linux?????歌ˉ涓???????æ©????浠惰?????浜ょ??é”›????濂芥??ç›ãƒ¤??æµ£?æ¶“æ´ª??浠朵????????宓?????????????浜?ç¼å­˜?よ??
-??ユ?堕??浠讹??浣???????浠�????瀹规?煎??�璇ユ??"text/plain"?????惰??锛????浠朵????????涓?璧???????锛?
-???涓鸿??æµ¼?浣胯ˉ涓????寮???ã„©?ã„¥????ㄨ??ç’鸿??绋?æ¶“???????寰???ä¼´?俱??
+Linuxå†…æ ¸è¡¥ä¸æ˜¯é€šè¿‡é‚®ä»¶è¢«æäº¤çš„,最好把补ä¸ä½œä¸ºé‚®ä»¶ä½“的内嵌文本。有些维护者
+接收附件,但是附件的内容格å¼åº”该是"text/plain"。然而,附件一般是ä¸èµžæˆçš„,
+因为这会使补ä¸çš„引用部分在评论过程中å˜çš„很困难。
-??ㄦ?ュ?????Linux?????歌ˉ涓???????æµ è·º?㈡?风????ã„¥?????ç›ãƒ¤????è·º??璇ュ??浜?????????????æ¿®???舵?????渚?æ¿¡?é”›?
-æµ ?æµ ?æ¶“???芥?ç‘°?????????????ã‚…?惰〃绗???????绌烘?ç¡·???????虫????ㄦ??æ¶“?ç›????寮?æ¾¶å­˜?????ç¼?ç俱??
+用æ¥å‘é€Linux内核补ä¸çš„邮件客户端在å‘é€è¡¥ä¸æ—¶åº”该处于文本的原始状æ€ã€‚例如,
+他们ä¸èƒ½æ”¹å˜æˆ–者删除制表符或者空格,甚至是在æ¯ä¸€è¡Œçš„开头或者结尾。
-æ¶“?ç‘•????æ©?"format=flowed"妯″????????ç›ãƒ¤?????æ©???蜂??寮?璧蜂?????棰????浠ュ?????瀹崇?????ç›????
+ä¸è¦é€šè¿‡"format=flowed"模å¼å‘é€è¡¥ä¸ã€‚这样会引起ä¸å¯é¢„æœŸä»¥åŠæœ‰å®³çš„æ–­è¡Œã€‚
-æ¶“?ç‘•?ç’â•€????????æµ è·º?㈡?风??æ©?ç›??????ㄦ?㈣?????æ©???蜂??æµ¼???æ‘??æµ£????ç›ãƒ¤?????
+ä¸è¦è®©ä½ çš„邮件客户端进行自动æ¢è¡Œã€‚这样也会破å你的补ä¸ã€‚
-???æµ è·º?㈡?风??æ¶“???芥?ç‘°???????????瀛?ç»—????缂??????ç‘°?????ç‘•??????????ç›ãƒ¤???????芥??ASCII??????UTF-8缂??????ç‘°??é”›?
-æ¿¡????æµ£?浣跨??UTF-8缂??????ç‘°???????????浠讹????d??æµ£?ç?æµ¼???åž®??æ¶“?浜??????è—‰????????瀛?ç»—???????棰????
+邮件客户端ä¸èƒ½æ”¹å˜æ–‡æœ¬çš„å­—ç¬¦é›†ç¼–ç æ–¹å¼ã€‚è¦å‘é€çš„è¡¥ä¸åªèƒ½æ˜¯ASCII或者UTF-8ç¼–ç æ–¹å¼ï¼Œ
+如果你使用UTF-8ç¼–ç æ–¹å¼å‘é€é‚®ä»¶ï¼Œé‚£ä¹ˆä½ å°†ä¼šé¿å…一些å¯èƒ½å‘生的字符集问题。
-???浠跺?㈡?风??�璇ュ舰???骞朵??淇???? References: ?????? In-Reply-To: ???棰?锛???d??
-???浠惰??棰?çå˜??æµ¼?æ¶“???????
+邮件客户端应该形æˆå¹¶ä¸”ä¿æŒ References: 或者 In-Reply-To: 标题,那么
+邮件è¯é¢˜å°±ä¸ä¼šä¸­æ–­ã€‚
-æ¾¶???å‰??甯?(?????????ç’寸??甯?)???甯é•????界?ㄤ??ç›ãƒ¤??é”›????æ¶“å“„?惰〃绗?æµ¼?æž????涓虹┖??笺??浣跨??xclipboard, xclip
-??????xcutselæ¶”?ç’稿??浠ワ??æµ£???????濂芥??ç’‡?æ¶“?æ¶“?????????åž®??浣跨?ã„¥????å‰??甯????
+å¤åˆ¶ç²˜å¸–(或者剪贴粘帖)通常ä¸èƒ½ç”¨äºŽè¡¥ä¸ï¼Œå› ä¸ºåˆ¶è¡¨ç¬¦ä¼šè½¬æ¢ä¸ºç©ºæ ¼ã€‚使用xclipboard, xclip
+或者xcutsel也许å¯ä»¥ï¼Œä½†æ˜¯æœ€å¥½æµ‹è¯•一下或者é¿å…使用å¤åˆ¶ç²˜å¸–。
-æ¶“?ç‘•???ㄤ娇???PGP/GPG缃æ’????????浠朵腑??????ç›ãƒ¤?????æ©???蜂??浣垮??寰?æ¾¶???????æ¶“???借?诲??????????ㄤ??æµ£????ç›ãƒ¤?????
-锛?�涓????棰?�璇ユ?????浠ヤ慨澶????锛?
+ä¸è¦åœ¨ä½¿ç”¨PGP/GPGç½²å的邮件中包å«è¡¥ä¸ã€‚这样会使得很多脚本ä¸èƒ½è¯»å–和适用于你的补ä¸ã€‚
+(这个问题应该是å¯ä»¥ä¿®å¤çš„)
-??ã„§???????æ??æµ è·º??ç›ã„¥?????ç›ãƒ¤??æ¶”????é”›?ç¼????宸åž?????æ¶“?æ¶“?ç›ãƒ¤?????æ¶“?æ¶“???????涓绘??é”›?æ·‡?瀛???ユ?è·º?扮??
-???浠讹??ç?ç›ãƒ¤?????'patch'??戒护???æ¶“?é”›?æ¿¡??????????浜?é”›????ç¼??????æ??æµ è·º??ç›ã„¥????????
+在给内核邮件列表å‘é€è¡¥ä¸ä¹‹å‰ï¼Œç»™è‡ªå·±å‘é€ä¸€ä¸ªè¡¥ä¸æ˜¯ä¸ªä¸é”™çš„主æ„,ä¿å­˜æŽ¥æ”¶åˆ°çš„
+邮件,将补ä¸ç”¨'patch'命令打上,如果æˆåŠŸäº†ï¼Œå†ç»™å†…核邮件列表å‘é€ã€‚
-涓?浜????浠跺?㈡?风?????绀?
+一些邮件客户端æç¤º
----------------------------------------------------------------------
-æ©????ç¼???è½°??浜?ç’‡?ç¼????MUA???缃????绀猴?????浠ョ?ㄤ??ç¼?Linux?????稿?????ç›ãƒ¤?????æ©?浜?骞朵???????虫??
-?????????�浠跺?????缃???�????
+这里给出一些详细的MUAé…ç½®æç¤ºï¼Œå¯ä»¥ç”¨äºŽç»™Linux内核å‘é€è¡¥ä¸ã€‚è¿™äº›å¹¶ä¸æ„味是
+所有的软件包é…置总结。
-璇存??锛?
-TUI = 浠ユ?????涓哄?虹???????ㄦ?锋?ュ??
-GUI = ??惧舰?????㈢?ㄦ?锋?ュ??
+说明:
+TUI = 以文本为基础的用户接å£
+GUI = 图形界é¢ç”¨æˆ·æŽ¥å£
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Alpine (TUI)
-???缃????椤癸??
-???"Sending Preferences"??ã„¥??é”›?
+é…置选项:
+在"Sending Preferences"部分:
-- "Do Not Send Flowed Text"蹇?椤诲?????
-- "Strip Whitespace Before Sending"蹇?椤诲?抽??
+- "Do Not Send Flowed Text"必须开å¯
+- "Strip Whitespace Before Sending"必须关闭
-褰???????浠舵?讹????????�璇ユ?惧?ㄨˉ涓?浼???虹?扮????版?癸????跺?????涓?CTRL-R�??????锛?浣挎??瀹????
-ç›ãƒ¤?????æµ è·º????ュ?ä¼´??浠朵腑???
+当写邮件时,光标应该放在补ä¸ä¼šå‡ºçŽ°çš„åœ°æ–¹ï¼Œç„¶åŽæŒ‰ä¸‹CTRL-R组åˆé”®ï¼Œä½¿æŒ‡å®šçš„
+è¡¥ä¸æ–‡ä»¶åµŒå…¥åˆ°é‚®ä»¶ä¸­ã€‚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Evolution (GUI)
-æ¶“?浜?寮????????????????浣跨?ã„¥????????ç›ãƒ¤??
+一些开å‘者æˆåŠŸçš„ä½¿ç”¨å®ƒå‘é€è¡¥ä¸
-褰??????╅??浠堕??椤癸??Preformat
- 浠?Format->Heading->Preformatted (Ctrl-7)??????宸ュ?锋??
+当选择邮件选项:Preformat
+ 从Format->Heading->Preformatted (Ctrl-7)或者工具æ 
-??跺??浣跨??锛?
- Insert->Text File... (Alt-n x)?????ヨˉ涓????浠躲??
+ç„¶åŽä½¿ç”¨ï¼š
+ Insert->Text File... (Alt-n x)æ’å…¥è¡¥ä¸æ–‡ä»¶ã€‚
-浣?�???浠?"diff -Nru old.c new.c | xclip"锛???????Preformat锛???跺??浣跨?ㄤ腑??撮??��绮?甯????
+你还å¯ä»¥"diff -Nru old.c new.c | xclip",选择Preformat,然åŽä½¿ç”¨ä¸­é—´é”®è¿›è¡Œç²˜å¸–。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Kmail (GUI)
-æ¶“?浜?寮????????????????浣跨?ã„¥????????ç›ãƒ¤?????
+一些开å‘者æˆåŠŸçš„ä½¿ç”¨å®ƒå‘é€è¡¥ä¸ã€‚
-榛?ç’よ?剧疆涓?æ¶“?HTML??ç…Ž??????????????é”›?æ¶“?ç‘•??????ã„¥?????
+默认设置ä¸ä¸ºHTMLæ ¼å¼æ˜¯åˆé€‚的;ä¸è¦å¯ç”¨å®ƒã€‚
-褰?æ¶”????æ¶“?ç????æµ å‰????è·º??é”›???ã„©??椤逛?????æ¶“?ç‘•??????â•„????ㄦ?㈣????????æ¶“????缂虹?ç‘°æ°¨???æµ£???ã„©??浠朵腑æˆ???ョ??浠讳????????
-??戒??æµ¼?çš??????ㄦ?㈣??é”›????å§ã‚„??蹇?椤诲?ã„¥?????ç›ãƒ¤??æ¶”?????????ㄦ?㈣????????ç» ?????????è§„??ç辨???????ㄨ????ㄦ?㈣????ヤ功??????浠讹??
-??跺?????瀹?淇?瀛?涓鸿??绋裤??涓????浣???ㄨ??绋夸腑???娆℃??寮?瀹?锛?瀹?宸茬????ㄩ?ㄨ????ㄦ?㈣??浜?锛???d??浣???????浠惰?界?舵病???
-?????╄????ㄦ?㈣??锛?浣????�涓?浼?澶�诲凡???????????ㄦ?㈣?????
+当书写一å°é‚®ä»¶çš„æ—¶å€™ï¼Œåœ¨é€‰é¡¹ä¸‹é¢ä¸è¦é€‰æ‹©è‡ªåЍæ¢è¡Œã€‚唯一的缺点就是你在邮件中输入的任何文本
+都ä¸ä¼šè¢«è‡ªåЍæ¢è¡Œï¼Œå› æ­¤ä½ å¿…须在å‘é€è¡¥ä¸ä¹‹å‰æ‰‹åЍæ¢è¡Œã€‚最简å•的方法就是å¯ç”¨è‡ªåЍæ¢è¡Œæ¥ä¹¦å†™é‚®ä»¶ï¼Œ
+ç„¶åŽæŠŠå®ƒä¿å­˜ä¸ºè‰ç¨¿ã€‚一旦你在è‰ç¨¿ä¸­å†æ¬¡æ‰“开它,它已ç»å…¨éƒ¨è‡ªåЍæ¢è¡Œäº†ï¼Œé‚£ä¹ˆä½ çš„邮件虽然没有
+选择自动æ¢è¡Œï¼Œä½†æ˜¯è¿˜ä¸ä¼šå¤±åŽ»å·²æœ‰çš„è‡ªåŠ¨æ¢è¡Œã€‚
-??ã„©??æµ å‰??æ´????é”›??????ヨˉ涓?æ¶”????é”›???å¥??甯哥?ã„§??ç›ãƒ¤??瀹????ç»—?é”›?æ¶“?æ¶“?æ©?瀛????(---)???
+在邮件的底部,æ’入补ä¸ä¹‹å‰ï¼Œæ”¾ä¸Šå¸¸ç”¨çš„è¡¥ä¸å®šç•Œç¬¦ï¼šä¸‰ä¸ªè¿žå­—å·(---)。
-??è·º?????"Message"????????$??é”›??????â•‚????ユ??浠讹????ョ????????æµ£????ç›ãƒ¤?????浠躲??æ©????æ¶“?æ¶“?棰?æ¾¶???????椤癸??æµ£????æµ ?
-???�瀹????缃?浣???????浠跺缓绔?宸ュ?锋????????锛?�???浠ュ甫涓?"insert file"??炬?????
+ç„¶åŽåœ¨"Message"èœå•æ¡ç›®ï¼Œé€‰æ‹©æ’入文件,接ç€é€‰å–ä½ çš„è¡¥ä¸æ–‡ä»¶ã€‚还有一个é¢å¤–的选项,你å¯ä»¥
+通过它é…置你的邮件建立工具æ èœå•,还å¯ä»¥å¸¦ä¸Š"insert file"图标。
-æµ£????浠ュ????ã„¥?ä¼´??æ©?GPG???ç’ä¼´??浠讹??æµ£???????宓?ç›ãƒ¤?????濂戒??ç‘•?浣跨??GPG???ç’æ¿??æµ ????æµ£?æ¶“å“„??宓??????????绛惧??ç›ãƒ¤??é”›?
-褰?浠?GPG涓???????7浣?缂??????朵??浣夸??浠?????????�?澶???????
+ä½ å¯ä»¥å®‰å…¨åœ°é€šè¿‡GPGæ ‡è®°é™„ä»¶ï¼Œä½†æ˜¯å†…åµŒè¡¥ä¸æœ€å¥½ä¸è¦ä½¿ç”¨GPG标记它们。作为内嵌文本的签å‘è¡¥ä¸ï¼Œ
+当从GPG中æå–7ä½ç¼–ç æ—¶ä¼šä½¿ä»–们å˜çš„æ›´åР夿‚。
-æ¿¡????æµ£????ç‘•?浠ラ??æµ å‰??褰㈠????????ç›ãƒ¤??é”›???d??çåž?抽????ç‘°?婚??浠讹????è·º?????æ¶“?çž???Ñ??ç»????"Suggest automatic
-display"é”›?æ©???å³°??宓????浠舵?æ‘?è§„??ç’â•„?æ˜???????般??
+如果你éžè¦ä»¥é™„件的形å¼å‘é€è¡¥ä¸ï¼Œé‚£ä¹ˆå°±å³é”®ç‚¹å‡»é™„件,然åŽé€‰ä¸­å±žæ€§ï¼Œçªå‡º"Suggest automatic
+display",这样内嵌附件更容易让读者看到。
-褰?æµ£?ç‘•?æ·‡?瀛?ç?ç‘•?????????????宓???????ç›ãƒ¤??é”›?æµ£????浠ヤ??娑???????ç›ã„§????奸????â•?????ç›ãƒ¤????????浠讹????è·º????冲?婚?????
-"save as"???æµ£????浠ヤ娇??ㄤ??æ¶“?娌℃????å­˜?圭????????ç›ãƒ¤????????浠讹??æ¿¡????瀹????浠ユ?g‘???褰㈠??ç¼???????褰?æµ£?å§ï½‡????ã„¥??
-???宸辩??�??d??涓?瀵????锛???f?舵病??????椤瑰??浠ヤ??瀛????浠?--宸茬?????涓?涓?�??风??bug�姹???ュ?�?kmail???bugzilla
-骞朵??甯????æ©?ç?æµ¼?çš?æ¾¶??????????浠舵??浠ュ?????瀵规??æ¶“???ㄦ?å³°??璇诲???????????çš?æ·‡?瀛????é”›????浠ュ?????æµ£???虫?????æµ è·º????è·º?æ¿?朵????版?癸??
-浣?涓?寰?涓????浠?浠????????????逛负�????????翠?????璇汇??
+当你è¦ä¿å­˜å°†è¦å‘é€çš„内嵌文本补ä¸ï¼Œä½ å¯ä»¥ä»Žæ¶ˆæ¯åˆ—表窗格选择包å«è¡¥ä¸çš„邮件,然åŽå³å‡»é€‰æ‹©
+"save as"。你å¯ä»¥ä½¿ç”¨ä¸€ä¸ªæ²¡æœ‰æ›´æ”¹çš„包å«è¡¥ä¸çš„邮件,如果它是以正确的形å¼ç»„æˆã€‚当你正真在它
+自己的窗å£ä¹‹ä¸‹å¯Ÿçœ‹ï¼Œé‚£æ—¶æ²¡æœ‰é€‰é¡¹å¯ä»¥ä¿å­˜é‚®ä»¶--å·²ç»æœ‰ä¸€ä¸ªè¿™æ ·çš„bug被汇报到了kmailçš„bugzilla
+并且希望这将会被处ç†ã€‚邮件是以åªé’ˆå¯¹æŸä¸ªç”¨æˆ·å¯è¯»å†™çš„æƒé™è¢«ä¿å­˜çš„,所以如果你想把邮件å¤åˆ¶åˆ°å…¶ä»–地方,
+ä½ ä¸å¾—ä¸æŠŠä»–ä»¬çš„æƒé™æ”¹ä¸ºç»„或者整体å¯è¯»ã€‚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Lotus Notes (GUI)
-涓?瑕?浣跨?ㄥ?????
+ä¸è¦ä½¿ç”¨å®ƒã€‚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mutt (TUI)
-寰?澶?Linux寮????浜哄??浣跨??mutt瀹㈡?风??锛????浠ヨ?????瀹????瀹?宸ヤ????????甯告??浜????
+很多Linuxå¼€å‘人员使用muttå®¢æˆ·ç«¯ï¼Œæ‰€ä»¥è¯æ˜Žå®ƒè‚¯å®šå·¥ä½œçš„éžå¸¸æ¼‚亮。
-Mutt涓????甯?缂?�???锛????浠ヤ??绠′??浣跨?ㄤ??涔?缂?�??ㄩ?戒??�璇ュ甫????????ㄦ??�???澶у????扮??�??ㄩ?藉甫???
-涓?涓?"insert file"???椤癸??瀹????浠ラ??�涓???瑰?????浠跺??瀹圭????瑰???????ユ??浠躲??
+Muttä¸è‡ªå¸¦ç¼–辑器,所以ä¸ç®¡ä½ ä½¿ç”¨ä»€ä¹ˆç¼–辑器都ä¸åº”该带有自动断行。大多数编辑器都带有
+一个"insert file"选项,它å¯ä»¥é€šè¿‡ä¸æ”¹å˜æ–‡ä»¶å†…å®¹çš„æ–¹å¼æ’入文件。
-'vim'浣?涓?mutt???缂?�???锛?
+'vim'作为mutt的编辑器:
set editor="vi"
- 濡????浣跨??xclip锛???�ヤ互涓???戒护
+ 如果使用xclip,敲入以下命令
:set paste
- ???涓????涔??????????shift-insert??????浣跨??
+ æŒ‰ä¸­é”®ä¹‹å‰æˆ–者shift-insert或者使用
:r filename
-æ¿¡??????å® ?????ç›ãƒ¤??æµ£?æ¶“å“„??宓??????????
-(a)ttach宸ヤ?????寰?濂斤??涓?甯????"set paste"???
+å¦‚æžœæƒ³è¦æŠŠè¡¥ä¸ä½œä¸ºå†…嵌文本。
+(a)ttach工作的很好,ä¸å¸¦æœ‰"set paste"。
-???缃????椤癸??
-瀹?æ´?璇ヤ互榛?ç’よ?剧疆???褰㈠??宸ヤ?????
-??惰??é”›????"send_charset"ç’剧疆涓?"us-ascii::utf-8"æ¶”????æ¶“?æ¶“?æ¶“???????涓绘?????
+é…置选项:
+它应该以默认设置的形å¼å·¥ä½œã€‚
+然而,把"send_charset"设置为"us-ascii::utf-8"也是一个ä¸é”™çš„主æ„。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Pine (TUI)
-Pine�??绘??涓?浜?绌烘?煎????????棰?锛?浣????�浜???�ㄥ??璇ラ?借??淇?澶?浜????
+Pine过去有一些空格删å‡é—®é¢˜ï¼Œä½†æ˜¯è¿™äº›çŽ°åœ¨åº”è¯¥éƒ½è¢«ä¿®å¤äº†ã€‚
-æ¿¡???????浠ワ??璇蜂娇???alpine(pine???ç¼Ñ„?胯??)
+如果å¯ä»¥ï¼Œè¯·ä½¿ç”¨alpine(pine的继承者)
-???缃????椤癸??
-- ???�????????????瑕?娑???ゆ??绋???????
-- "no-strip-whitespace-before-send"???椤逛????????瑕???????
+é…置选项:
+- æœ€è¿‘çš„ç‰ˆæœ¬éœ€è¦æ¶ˆé™¤æµç¨‹æ–‡æœ¬
+- "no-strip-whitespace-before-send"选项也是需è¦çš„。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sylpheed (GUI)
-- ???宓??????????浠ュ??濂界??宸ヤ??锛???????浣跨?ㄩ??浠讹?????
-- ???ç’é•娇??ã„¥????ã„§??缂?æˆ???ã„£??
-- 瀵逛?????褰?�澶???堕??甯告?????
-- 濡???????�non-SSL�??ワ?????娉?浣跨??TLS SMTP?????????
-- ??ㄧ?????�??d腑???涓?涓?寰??????ㄧ??ruler bar???
-- ç¼???æ¿?????æ¶“?娣诲????æ¿??çå˜??æµ¼?å§ï½‡â€˜???浜?瑙f?剧ãš??????
+- 内嵌文本å¯ä»¥å¾ˆå¥½çš„工作(或者使用附件)。
+- å…许使用外部的编辑器。
+- 对于目录较多时éžå¸¸æ…¢ã€‚
+- 如果通过non-SSL连接,无法使用TLS SMTP授æƒã€‚
+- 在组æˆçª—å£ä¸­æœ‰ä¸€ä¸ªå¾ˆæœ‰ç”¨çš„ruler bar。
+- ç»™åœ°å€æœ¬ä¸­æ·»åŠ åœ°å€å°±ä¸ä¼šæ­£ç¡®çš„了解显示å。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thunderbird (GUI)
-榛?ç’ゆ????å…¸??é”›?thunderbird寰?瀹规??????????????é”›?æµ£????æ©????æ¶“?浜???è§„?????浠ュ己??è·º?????寰???æ‘ソ???
+默认情况下,thunderbird很容易æŸå文本,但是还有一些方法å¯ä»¥å¼ºåˆ¶å®ƒå˜å¾—更好。
-- ??ㄧ?ㄦ?峰????疯?剧疆???锛?�??????瀵诲??锛?涓?瑕???????"Compose messages in HTML format"???
+- 在用户å¸å·è®¾ç½®é‡Œï¼Œç»„æˆå’Œå¯»å€ï¼Œä¸è¦é€‰æ‹©"Compose messages in HTML format"。
-- 缂?æˆ?æµ£????Thunderbird???缃?ç’剧疆??ヤ娇瀹?æ¶“?ç‘•????ç›?浣跨??é”›?user_pref("mailnews.wraplength", 0);
+- 编辑你的Thunderbirdé…置设置æ¥ä½¿å®ƒä¸è¦æ‹†è¡Œä½¿ç”¨ï¼šuser_pref("mailnews.wraplength", 0);
-- 缂?æˆ?æµ£????Thunderbird???缃?ç’剧疆锛?浣垮??æ¶“?ç‘•?浣跨??"format=flowed"??ç…Ž??é”›?user_pref("mailnews.
+- 编辑你的Thunderbirdé…置设置,使它ä¸è¦ä½¿ç”¨"format=flowed"æ ¼å¼ï¼šuser_pref("mailnews.
send_plaintext_flowed", false);
-- æµ£????ç‘•?æµ£?Thunderbird???æ¶“æ´ª???????ç…Ž????ç‘°??é”›?
- æ¿¡????榛?ç’ゆ????å…¸??æµ£?æ¶”??????????HTML??ç…Ž??é”›???d?????寰???俱??æµ ?æµ ?æµ ????棰???????æ¶“????妗?æ¶“???????"Preformat"??ç…Ž?????
- æ¿¡????榛?ç’ゆ????å…¸??æµ£?æ¶”??????????????????ç…Ž??é”›?æµ£?æ¶“?寰????瀹???逛负HTML??ç…Ž??é”›?æµ ?æµ ?æµ£?æ¶“è½°??娆℃?Ñ…??é”›???ヤ功?????扮??娑????é”›?
- ??è·º??寮哄?朵娇瀹??????版???????ç…Ž??é”›???????瀹?çå˜?????ç›????ç‘•?瀹???æ¿??é”›???ã„¥??淇$????炬??æ¶“?浣跨??shift?????ヤ娇瀹????æ¶“?HTML
- ??煎??锛???跺?????棰???????涓????妗?涓???????"Preformat"??煎?????
+- 你需è¦ä½¿Thunderbirdå˜ä¸ºé¢„å…ˆæ ¼å¼æ–¹å¼ï¼š
+ 如果默认情况下你书写的是HTMLæ ¼å¼ï¼Œé‚£ä¸æ˜¯å¾ˆéš¾ã€‚仅仅从标题æ çš„下拉框中选择"Preformat"æ ¼å¼ã€‚
+ 如果默认情况下你书写的是文本格å¼ï¼Œä½ ä¸å¾—把它改为HTMLæ ¼å¼ï¼ˆä»…仅作为一次性的)æ¥ä¹¦å†™æ–°çš„æ¶ˆæ¯ï¼Œ
+ ç„¶åŽå¼ºåˆ¶ä½¿å®ƒå›žåˆ°æ–‡æœ¬æ ¼å¼ï¼Œå¦åˆ™å®ƒå°±ä¼šæ‹†è¡Œã€‚è¦å®žçŽ°å®ƒï¼Œåœ¨å†™ä¿¡çš„å›¾æ ‡ä¸Šä½¿ç”¨shifté”®æ¥ä½¿å®ƒå˜ä¸ºHTML
+ æ ¼å¼ï¼Œç„¶åŽæ ‡é¢˜æ çš„下拉框中选择"Preformat"æ ¼å¼ã€‚
-- ???ç’é•娇??ã„¥????ã„§??缂?æˆ????é”›?
- ???瀵?Thunderbird???ç›ãƒ¤?????ç» ?????????è§„??ç辨??浣跨?ㄤ??æ¶“?"external editor"??â•??é”›???è·º??浣跨?ㄤ????????娆㈢??
- $EDITOR??ヨ?诲???????????骞惰ˉ涓???版?????æ¶“????ç‘•?瀹???æ¿??é”›????浠ヤ??æžè—‰è‹Ÿæ¶“?瀹?ç‘?æ©?æ¶“???â•??é”›???è·º??娣诲??æ¶“?æ¶“?浣跨?ã„¥?????
- ??????View->Toolbars->Customize...??????褰?æµ£?æ¶”????淇℃???????è·º??æµ ?æµ ???ç‘°?诲??çåž??浠ヤ?????
+- å…许使用外部的编辑器:
+ 针对Thunderbirdæ‰“è¡¥ä¸æœ€ç®€å•的方法就是使用一个"external editor"扩展,然åŽä½¿ç”¨ä½ æœ€å–œæ¬¢çš„
+ $EDITORæ¥è¯»å–或者åˆå¹¶è¡¥ä¸åˆ°æ–‡æœ¬ä¸­ã€‚è¦å®žçŽ°å®ƒï¼Œå¯ä»¥ä¸‹è½½å¹¶ä¸”å®‰è£…è¿™ä¸ªæ‰©å±•ï¼Œç„¶åŽæ·»åŠ ä¸€ä¸ªä½¿ç”¨å®ƒçš„
+ 按键View->Toolbars->Customize...最åŽå½“你书写信æ¯çš„æ—¶å€™ä»…仅点击它就å¯ä»¥äº†ã€‚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TkRat (GUI)
-???浠ヤ娇??ㄥ?????浣跨??"Insert file..."??????澶???ㄧ??缂?�??ㄣ??
+å¯ä»¥ä½¿ç”¨å®ƒã€‚使用"Insert file..."或者外部的编辑器。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Gmail (Web GUI)
-æ¶“?ç‘•?浣跨?ã„¥????????ç›ãƒ¤?????
+ä¸è¦ä½¿ç”¨å®ƒå‘é€è¡¥ä¸ã€‚
-Gmail缃?椤�㈡?风???????ㄥ?版????惰〃绗?�???涓虹┖??笺??
+Gmail网页客户端自动地把制表符转æ¢ä¸ºç©ºæ ¼ã€‚
-??界?跺?惰〃绗?�???涓虹┖??奸??棰????浠ヨ??澶???ㄧ??�??ㄨВ??筹???????跺??�浼?浣跨?ㄥ??�??㈣?????姣?�??????涓?78涓?瀛?绗????
+虽然制表符转æ¢ä¸ºç©ºæ ¼é—®é¢˜å¯ä»¥è¢«å¤–éƒ¨ç¼–è¾‘å™¨è§£å†³ï¼ŒåŒæ—¶å®ƒè¿˜ä¼šä½¿ç”¨å›žè½¦æ¢è¡ŒæŠŠæ¯è¡Œæ‹†åˆ†ä¸º78个字符。
-???涓?涓????棰????Gmail�浼????浠讳??涓????ASCII???瀛?绗????淇℃????逛负base64缂???????瀹????涓?瑗垮????????娆ф床浜虹?????瀛????
+å¦ä¸€ä¸ªé—®é¢˜æ˜¯Gmailè¿˜ä¼šæŠŠä»»ä½•ä¸æ˜¯ASCIIçš„å­—ç¬¦çš„ä¿¡æ¯æ”¹ä¸ºbase64ç¼–ç ã€‚它把东西å˜çš„åƒæ¬§æ´²äººçš„å字。
###
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt
index 4c4ce853577b..c278f412dc65 100644
--- a/Documentation/zh_CN/magic-number.txt
+++ b/Documentation/zh_CN/magic-number.txt
@@ -66,7 +66,7 @@ MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h
RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h
SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h
HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c
-APM_BIOS_MAGIC 0x4101 apm_user arch/i386/kernel/apm.c
+APM_BIOS_MAGIC 0x4101 apm_user arch/x86/kernel/apm_32.c
CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h
DB_MAGIC 0x4442 fc_info drivers/net/iph5526_novram.c
DL_MAGIC 0x444d fc_info drivers/net/iph5526_novram.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 187282da9213..7b2e9e85e427 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1,4 +1,5 @@
+
List of maintainers and how to submit kernel changes
Please try to follow the guidelines below. This will make things
@@ -533,6 +534,8 @@ L: device-drivers-devel@blackfin.uclinux.org
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://wiki.analog.com/
S: Supported
+F: sound/soc/codecs/adau*
+F: sound/soc/codecs/adav*
F: sound/soc/codecs/ad1*
F: sound/soc/codecs/ssm*
@@ -693,7 +696,7 @@ T: git git://git.infradead.org/users/cbou/linux-cns3xxx.git
ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
M: Hartley Sweeten <hsweeten@visionengravers.com>
-M: Ryan Mallon <ryan@bluewatersys.com>
+M: Ryan Mallon <rmallon@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-ep93xx/
@@ -731,6 +734,12 @@ T: git git://git.berlios.de/gemini-board
S: Maintained
F: arch/arm/mach-gemini/
+ARM/CSR SIRFPRIMA2 MACHINE SUPPORT
+M: Barry Song <baohua.song@csr.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-prima2/
+
ARM/EBSA110 MACHINE SUPPORT
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1543,13 +1552,20 @@ F: drivers/net/tg3.*
BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
M: Brett Rudley <brudley@broadcom.com>
M: Henry Ptasinski <henryp@broadcom.com>
-M: Dowan Kim <dowan@broadcom.com>
M: Roland Vossen <rvossen@broadcom.com>
M: Arend van Spriel <arend@broadcom.com>
+M: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+M: Kan Yan <kanyan@broadcom.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/staging/brcm80211/
+BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
+M: Bhanu Prakash Gollapudi <bprakash@broadcom.com>
+L: linux-scsi@vger.kernel.org
+S: Supported
+F: drivers/scsi/bnx2fc/
+
BROCADE BFA FC SCSI DRIVER
M: Jing Huang <huangj@brocade.com>
L: linux-scsi@vger.kernel.org
@@ -1579,7 +1595,7 @@ F: Documentation/sound/alsa/Bt87x.txt
F: sound/pci/bt87x.c
BT8XXGPIO DRIVER
-M: Michael Buesch <mb@bu3sch.de>
+M: Michael Buesch <m@bues.ch>
W: http://bu3sch.de/btgpio.php
S: Maintained
F: drivers/gpio/bt8xxgpio.c
@@ -1772,7 +1788,8 @@ F: include/linux/clk.h
CISCO FCOE HBA DRIVER
M: Abhijeet Joglekar <abjoglek@cisco.com>
-M: Joe Eykholt <jeykholt@cisco.com>
+M: Venkata Siva Vijayendra Bhamidipati <vbhamidi@cisco.com>
+M: Brian Uchino <buchino@cisco.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/fnic/
@@ -3002,7 +3019,7 @@ F: kernel/hrtimer.c
F: kernel/time/clockevents.c
F: kernel/time/tick*.*
F: kernel/time/timer_*.c
-F: include/linux/clockevents.h
+F: include/linux/clockchips.h
F: include/linux/hrtimer.h
HIGH-SPEED SCC DRIVER FOR AX.25
@@ -3425,10 +3442,9 @@ S: Maintained
F: drivers/net/ipg.*
IPATH DRIVER
-M: Ralph Campbell <infinipath@qlogic.com>
+M: Mike Marciniszyn <infinipath@qlogic.com>
L: linux-rdma@vger.kernel.org
-T: git git://git.qlogic.com/ipath-linux-2.6
-S: Supported
+S: Maintained
F: drivers/infiniband/hw/ipath/
IPMI SUBSYSTEM
@@ -3886,7 +3902,7 @@ F: arch/powerpc/platforms/512x/
F: arch/powerpc/platforms/52xx/
LINUX FOR POWERPC EMBEDDED PPC4XX
-M: Josh Boyer <jwboyer@linux.vnet.ibm.com>
+M: Josh Boyer <jwboyer@gmail.com>
M: Matt Porter <mporter@kernel.crashing.org>
W: http://www.penguinppc.org/
L: linuxppc-dev@lists.ozlabs.org
@@ -3918,6 +3934,7 @@ W: http://www.penguinppc.org/
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
F: arch/powerpc/platforms/83xx/
+F: arch/powerpc/platforms/85xx/
LINUX FOR POWERPC PA SEMI PWRFICIENT
M: Olof Johansson <olof@lixom.net>
@@ -3951,6 +3968,13 @@ L: lm-sensors@lm-sensors.org
S: Maintained
F: drivers/hwmon/lm73.c
+LM78 HARDWARE MONITOR DRIVER
+M: Jean Delvare <khali@linux-fr.org>
+L: lm-sensors@lm-sensors.org
+S: Maintained
+F: Documentation/hwmon/lm78
+F: drivers/hwmon/lm78.c
+
LM83 HARDWARE MONITOR DRIVER
M: Jean Delvare <khali@linux-fr.org>
L: lm-sensors@lm-sensors.org
@@ -4097,6 +4121,12 @@ S: Maintained
F: drivers/net/mv643xx_eth.*
F: include/linux/mv643xx.h
+MARVELL MWIFIEX WIRELESS DRIVER
+M: Bing Zhao <bzhao@marvell.com>
+L: linux-wireless@vger.kernel.org
+S: Maintained
+F: drivers/net/wireless/mwifiex/
+
MARVELL MWL8K WIRELESS DRIVER
M: Lennert Buytenhek <buytenh@wantstofly.org>
L: linux-wireless@vger.kernel.org
@@ -4193,9 +4223,10 @@ F: drivers/usb/image/microtek.*
MIPS
M: Ralf Baechle <ralf@linux-mips.org>
-W: http://www.linux-mips.org/
L: linux-mips@linux-mips.org
+W: http://www.linux-mips.org/
T: git git://git.linux-mips.org/pub/scm/linux.git
+Q: http://patchwork.linux-mips.org/project/linux-mips/list/
S: Supported
F: Documentation/mips/
F: arch/mips/
@@ -4289,8 +4320,8 @@ S: Maintained
F: drivers/usb/musb/
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
+M: Jon Mason <mason@myri.com>
M: Andrew Gallatin <gallatin@myri.com>
-M: Brice Goglin <brice@myri.com>
L: netdev@vger.kernel.org
W: http://www.myri.com/scs/download-Myri10GE.html
S: Supported
@@ -4584,9 +4615,8 @@ S: Maintained
F: drivers/mmc/host/omap.c
OMAP HS MMC SUPPORT
-M: Madhusudhan Chikkature <madhu.cr@ti.com>
L: linux-omap@vger.kernel.org
-S: Maintained
+S: Orphan
F: drivers/mmc/host/omap_hsmmc.c
OMAP RANDOM NUMBER GENERATOR SUPPORT
@@ -4680,6 +4710,14 @@ F: drivers/of
F: include/linux/of*.h
K: of_get_property
+OPENRISC ARCHITECTURE
+M: Jonas Bonn <jonas@southpole.se>
+W: http://openrisc.net
+L: linux@lists.openrisc.net
+S: Maintained
+T: git git://openrisc.net/~jonas/linux
+F: arch/openrisc
+
OPL4 DRIVER
M: Clemens Ladisch <clemens@ladisch.de>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -5152,6 +5190,12 @@ M: Robert Jarzmik <robert.jarzmik@free.fr>
L: rtc-linux@googlegroups.com
S: Maintained
+QIB DRIVER
+M: Mike Marciniszyn <infinipath@qlogic.com>
+L: linux-rdma@vger.kernel.org
+S: Supported
+F: drivers/infiniband/hw/qib/
+
QLOGIC QLA1280 SCSI DRIVER
M: Michael Reed <mdr@sgi.com>
L: linux-scsi@vger.kernel.org
@@ -5313,6 +5357,13 @@ L: reiserfs-devel@vger.kernel.org
S: Supported
F: fs/reiserfs/
+REGISTER MAP ABSTRACTION
+M: Mark Brown <broonie@opensource.wolfsonmicro.com>
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git
+S: Supported
+F: drivers/base/regmap/
+F: include/linux/regmap.h
+
RFKILL
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-wireless@vger.kernel.org
@@ -5875,7 +5926,7 @@ S: Maintained
F: drivers/net/sonic.*
SONICS SILICON BACKPLANE DRIVER (SSB)
-M: Michael Buesch <mb@bu3sch.de>
+M: Michael Buesch <m@bues.ch>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/ssb/
@@ -6049,6 +6100,145 @@ L: devel@driverdev.osuosl.org
S: Maintained
F: drivers/staging/
+STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
+M: Henk de Groot <pe1dnn@amsat.org>
+S: Odd Fixes
+F: drivers/staging/wlags49_h2/
+F: drivers/staging/wlags49_h25/
+
+STAGING - ASUS OLED
+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>
+S: Odd Fixes
+F: drivers/staging/comedi/
+
+STAGING - CRYSTAL HD VIDEO DECODER
+M: Naren Sankar <nsankar@broadcom.com>
+M: Jarod Wilson <jarod@wilsonet.com>
+M: Scott Davilla <davilla@4pi.com>
+M: Manu Abraham <abraham.manu@gmail.com>
+S: Odd Fixes
+F: drivers/staging/crystalhd/
+
+STAGING - CYPRESS WESTBRIDGE SUPPORT
+M: David Cross <david.cross@cypress.com>
+S: Odd Fixes
+F: drivers/staging/westbridge/
+
+STAGING - ECHO CANCELLER
+M: Steve Underwood <steveu@coppice.org>
+M: David Rowe <david@rowetel.com>
+S: Odd Fixes
+F: drivers/staging/echo/
+
+STAGING - FLARION FT1000 DRIVERS
+M: Marek Belisko <marek.belisko@gmail.com>
+S: Odd Fixes
+F: drivers/staging/ft1000/
+
+STAGING - FRONTIER TRANZPORT AND ALPHATRACK
+M: David Täht <d@teklibre.com>
+S: Odd Fixes
+F: drivers/staging/frontier/
+
+STAGING - HYPER-V (MICROSOFT)
+M: Hank Janssen <hjanssen@microsoft.com>
+M: Haiyang Zhang <haiyangz@microsoft.com>
+S: Odd Fixes
+F: drivers/staging/hv/
+
+STAGING - INDUSTRIAL IO
+M: Jonathan Cameron <jic23@cam.ac.uk>
+L: linux-iio@vger.kernel.org
+S: Odd Fixes
+F: drivers/staging/iio/
+
+STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
+M: Jarod Wilson <jarod@wilsonet.com>
+W: http://www.lirc.org/
+S: Odd Fixes
+F: drivers/staging/lirc/
+
+STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
+M: Andres Salomon <dilinger@queued.net>
+M: Chris Ball <cjb@laptop.org>
+M: Jon Nettleton <jon.nettleton@gmail.com>
+W: http://wiki.laptop.org/go/DCON
+S: Odd Fixes
+F: drivers/staging/olpc_dcon/
+
+STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER
+M: Willy Tarreau <willy@meta-x.org>
+S: Odd Fixes
+F: drivers/staging/panel/
+
+STAGING - REALTEK RTL8712U DRIVERS
+M: Larry Finger <Larry.Finger@lwfinger.net>
+M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
+S: Odd Fixes
+F: drivers/staging/rtl8712/
+
+STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
+M: Teddy Wang <teddy.wang@siliconmotion.com.cn>
+S: Odd Fixes
+F: drivers/staging/sm7xx/
+
+STAGING - SOFTLOGIC 6x10 MPEG CODEC
+M: Ben Collins <bcollins@bluecherry.net>
+S: Odd Fixes
+F: drivers/staging/solo6x10/
+
+STAGING - SPEAKUP CONSOLE SPEECH DRIVER
+M: William Hubbs <w.d.hubbs@gmail.com>
+M: Chris Brannon <chris@the-brannons.com>
+M: Kirk Reiser <kirk@braille.uwo.ca>
+M: Samuel Thibault <samuel.thibault@ens-lyon.org>
+L: speakup@braille.uwo.ca
+W: http://www.linux-speakup.org/
+S: Odd Fixes
+F: drivers/staging/speakup/
+
+STAGING - TI DSP BRIDGE DRIVERS
+M: Omar Ramirez Luna <omar.ramirez@ti.com>
+S: Odd Fixes
+F: drivers/staging/tidspbridge/
+
+STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS
+L: linux-media@vger.kernel.org
+S: Odd Fixes
+F: drivers/staging/tm6000/
+
+STAGING - USB ENE SM/MS CARD READER DRIVER
+M: Al Cho <acho@novell.com>
+S: Odd Fixes
+F: drivers/staging/keucr/
+
+STAGING - VIA VT665X DRIVERS
+M: Forest Bond <forest@alittletooquiet.net>
+S: Odd Fixes
+F: drivers/staging/vt665?/
+
+STAGING - WINBOND IS89C35 WLAN USB DRIVER
+M: Pavel Machek <pavel@ucw.cz>
+S: Odd Fixes
+F: drivers/staging/winbond/
+
+STAGING - XGI Z7,Z9,Z11 PCI DISPLAY DRIVER
+M: Arnaud Patard <apatard@mandriva.com>
+S: Odd Fixes
+F: drivers/staging/xgifb/
+
STARFIRE/DURALAN NETWORK DRIVER
M: Ion Badulescu <ionut@badula.org>
S: Odd Fixes
@@ -6242,9 +6432,14 @@ F: drivers/char/toshiba.c
F: include/linux/toshiba.h
TMIO MMC DRIVER
+M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
M: Ian Molton <ian@mnementh.co.uk>
+L: linux-mmc@vger.kernel.org
S: Maintained
-F: drivers/mmc/host/tmio_mmc.*
+F: drivers/mmc/host/tmio_mmc*
+F: drivers/mmc/host/sh_mobile_sdhi.c
+F: include/linux/mmc/tmio.h
+F: include/linux/mmc/sh_mobile_sdhi.h
TMPFS (SHMEM FILESYSTEM)
M: Hugh Dickins <hughd@google.com>
@@ -6321,7 +6516,7 @@ F: drivers/scsi/u14-34f.c
UBI FILE SYSTEM (UBIFS)
M: Artem Bityutskiy <dedekind1@gmail.com>
-M: Adrian Hunter <adrian.hunter@nokia.com>
+M: Adrian Hunter <adrian.hunter@intel.com>
L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubifs-2.6.git
W: http://www.linux-mtd.infradead.org/doc/ubifs.html
@@ -6546,13 +6741,6 @@ W: http://pegasus2.sourceforge.net/
S: Maintained
F: drivers/net/usb/rtl8150.c
-USB SE401 DRIVER
-L: linux-usb@vger.kernel.org
-W: http://www.chello.nl/~j.vreeken/se401/
-S: Orphan
-F: Documentation/video4linux/se401.txt
-F: drivers/staging/se401/
-
USB SERIAL BELKIN F5U103 DRIVER
M: William Greathouse <wgreathouse@smva.com>
L: linux-usb@vger.kernel.org
@@ -6938,9 +7126,9 @@ S: Maintained
F: drivers/input/misc/wistron_btns.c
WL1251 WIRELESS DRIVER
-M: Kalle Valo <kvalo@adurom.com>
+M: Luciano Coelho <coelho@ti.com>
L: linux-wireless@vger.kernel.org
-W: http://wireless.kernel.org
+W: http://wireless.kernel.org/en/users/Drivers/wl1251
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
F: drivers/net/wireless/wl1251/*
diff --git a/Makefile b/Makefile
index 6a5bdad524af..d0189560613c 100644
--- a/Makefile
+++ b/Makefile
@@ -1290,6 +1290,7 @@ help:
@echo ' make O=dir [targets] Locate all output files in "dir", including .config'
@echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)'
@echo ' make C=2 [targets] Force check of all c source with $$CHECK'
+ @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections'
@echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where'
@echo ' 1: warnings which may be relevant and do not occur too often'
@echo ' 2: warnings which occur quite often but may still be relevant'
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 60219bf94198..ca2da8da6e9c 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -6,6 +6,7 @@ config ALPHA
select HAVE_OPROFILE
select HAVE_SYSCALL_WRAPPERS
select HAVE_IRQ_WORK
+ select HAVE_PCSPKR_PLATFORM
select HAVE_PERF_EVENTS
select HAVE_DMA_ATTRS
select HAVE_GENERIC_HARDIRQS
diff --git a/arch/alpha/include/asm/8253pit.h b/arch/alpha/include/asm/8253pit.h
deleted file mode 100644
index a71c9c1455a7..000000000000
--- a/arch/alpha/include/asm/8253pit.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * 8253/8254 Programmable Interval Timer
- */
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index e756d04b6cd5..640f909ddd41 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -176,15 +176,15 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -196,10 +196,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
/**
* atomic64_add_unless - add unless the number is a given value
@@ -208,7 +207,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
{
@@ -256,5 +255,4 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
#define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb()
-#include <asm-generic/atomic-long.h>
#endif /* _ALPHA_ATOMIC_H */
diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h
index 85b815215776..a19ba5efea4c 100644
--- a/arch/alpha/include/asm/bitops.h
+++ b/arch/alpha/include/asm/bitops.h
@@ -456,8 +456,7 @@ sched_find_first_bit(const unsigned long b[2])
#include <asm-generic/bitops/le.h>
-#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* __KERNEL__ */
diff --git a/arch/alpha/include/asm/floppy.h b/arch/alpha/include/asm/floppy.h
index 0be50413b2b5..46cefbd50e73 100644
--- a/arch/alpha/include/asm/floppy.h
+++ b/arch/alpha/include/asm/floppy.h
@@ -27,7 +27,7 @@
#define fd_cacheflush(addr,size) /* nothing */
#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt,\
IRQF_DISABLED, "floppy", NULL)
-#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL)
#ifdef CONFIG_PCI
diff --git a/arch/alpha/include/asm/local.h b/arch/alpha/include/asm/local.h
index b9e3e3318371..9c94b8456043 100644
--- a/arch/alpha/include/asm/local.h
+++ b/arch/alpha/include/asm/local.h
@@ -2,7 +2,7 @@
#define _ALPHA_LOCAL_H
#include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
typedef struct
{
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h
index 65cf3e28e2f4..fd698a174f26 100644
--- a/arch/alpha/include/asm/ptrace.h
+++ b/arch/alpha/include/asm/ptrace.h
@@ -72,7 +72,6 @@ struct switch_stack {
#define user_mode(regs) (((regs)->ps & 8) != 0)
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
#define task_pt_regs(task) \
((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1)
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
index ebc3c894b5a2..2fd00b7077e4 100644
--- a/arch/alpha/kernel/module.c
+++ b/arch/alpha/kernel/module.c
@@ -29,20 +29,6 @@
#define DEBUGP(fmt...)
#endif
-void *
-module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc(size);
-}
-
-void
-module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
/* Allocate the GOT at the end of the core sections. */
struct got_entry {
@@ -156,14 +142,6 @@ module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
}
int
-apply_relocate(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
- unsigned int relsec, struct module *me)
-{
- printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
- return -ENOEXEC;
-}
-
-int
apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
unsigned int symindex, unsigned int relsec,
struct module *me)
@@ -302,15 +280,3 @@ apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
return 0;
}
-
-int
-module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void
-module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 90561c45e7d8..8143cd7cdbfb 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -17,7 +17,7 @@
#include <linux/init.h>
#include <asm/hwrpb.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/irq_regs.h>
#include <asm/pal.h>
@@ -847,7 +847,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
data.period = event->hw.last_period;
if (alpha_perf_event_set_period(event, hwc, idx)) {
- if (perf_event_overflow(event, 1, &data, regs)) {
+ if (perf_event_overflow(event, &data, regs)) {
/* Interrupts coming too quickly; "throttle" the
* counter, i.e., disable it for a little while.
*/
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 838eac128409..89bbe5b41145 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -200,7 +200,6 @@ show_regs(struct pt_regs *regs)
void
start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
- set_fs(USER_DS);
regs->pc = pc;
regs->ps = 8;
wrusp(sp);
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index d739703608fc..4087a569b43b 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -31,7 +31,7 @@
#include <asm/hwrpb.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 8de1046fe91e..f33648e4e8cf 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -26,7 +26,6 @@
#include <asm/pgtable.h>
#include <asm/core_cia.h>
#include <asm/tlbflush.h>
-#include <asm/8253pit.h>
#include "proto.h"
#include "irq_impl.h"
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 818e74ed45dc..e336694ca042 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -46,7 +46,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
-#include <asm/8253pit.h>
#include <asm/rtc.h>
#include <linux/mc146818rtc.h>
@@ -91,7 +90,7 @@ DEFINE_PER_CPU(u8, irq_work_pending);
#define test_irq_work_pending() __get_cpu_var(irq_work_pending)
#define clear_irq_work_pending() __get_cpu_var(irq_work_pending) = 0
-void set_irq_work_pending(void)
+void arch_irq_work_raise(void)
{
set_irq_work_pending_flag();
}
diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c
index 0f5520d2f45f..f9f5fe830e9f 100644
--- a/arch/alpha/lib/dec_and_lock.c
+++ b/arch/alpha/lib/dec_and_lock.c
@@ -6,7 +6,7 @@
*/
#include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
asm (".text \n\
.global _atomic_dec_and_lock \n\
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9adc278a22ab..09ebf0ba64fa 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -10,7 +10,7 @@ config ARM
select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
select HAVE_ARCH_KGDB
- select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
+ select HAVE_KPROBES if !XIP_KERNEL
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
@@ -37,6 +37,9 @@ config ARM
Europe. There is an ARM Linux project with a web page at
<http://www.arm.linux.org.uk/>.
+config ARM_HAS_SG_CHAIN
+ bool
+
config HAVE_PWM
bool
@@ -239,6 +242,7 @@ config ARCH_INTEGRATOR
select ARM_AMBA
select ARCH_HAS_CPUFREQ
select CLKDEV_LOOKUP
+ select HAVE_MACH_CLKDEV
select ICST
select GENERIC_CLOCKEVENTS
select PLAT_VERSATILE
@@ -250,6 +254,7 @@ config ARCH_REALVIEW
bool "ARM Ltd. RealView family"
select ARM_AMBA
select CLKDEV_LOOKUP
+ select HAVE_MACH_CLKDEV
select ICST
select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -265,6 +270,7 @@ config ARCH_VERSATILE
select ARM_AMBA
select ARM_VIC
select CLKDEV_LOOKUP
+ select HAVE_MACH_CLKDEV
select ICST
select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -281,6 +287,7 @@ config ARCH_VEXPRESS
select ARM_AMBA
select ARM_TIMER_SP804
select CLKDEV_LOOKUP
+ select HAVE_MACH_CLKDEV
select GENERIC_CLOCKEVENTS
select HAVE_CLK
select HAVE_PATA_PLATFORM
@@ -321,7 +328,7 @@ config ARCH_CLPS711X
config ARCH_CNS3XXX
bool "Cavium Networks CNS3XXX family"
- select CPU_V6
+ select CPU_V6K
select GENERIC_CLOCKEVENTS
select ARM_GIC
select MIGHT_HAVE_PCI
@@ -337,6 +344,19 @@ config ARCH_GEMINI
help
Support for the Cortina Systems Gemini family SoCs
+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
+ select GENERIC_IRQ_CHIP
+ select USE_OF
+ select ZONE_DMA
+ help
+ Support for CSR SiRFSoC ARM Cortex A9 Platform
+
config ARCH_EBSA110
bool "EBSA-110"
select CPU_SA110
@@ -376,6 +396,7 @@ config ARCH_MXC
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
select CLKSRC_MMIO
+ select GENERIC_IRQ_CHIP
select HAVE_SCHED_CLOCK
help
Support for Freescale MXC/iMX-based family of processors
@@ -490,14 +511,6 @@ config ARCH_KIRKWOOD
Support for the following Marvell Kirkwood series SoCs:
88F6180, 88F6192 and 88F6281.
-config ARCH_LOKI
- bool "Marvell Loki (88RC8480)"
- select CPU_FEROCEON
- select GENERIC_CLOCKEVENTS
- select PLAT_ORION
- help
- Support for the Marvell Loki (88RC8480) SoC.
-
config ARCH_LPC32XX
bool "NXP LPC32XX"
select CLKSRC_MMIO
@@ -591,7 +604,6 @@ config ARCH_TEGRA
select GENERIC_GPIO
select HAVE_CLK
select HAVE_SCHED_CLOCK
- select ARCH_HAS_BARRIERS if CACHE_L2X0
select ARCH_HAS_CPUFREQ
help
This enables support for NVIDIA Tegra based systems (Tegra APX,
@@ -618,6 +630,8 @@ config ARCH_PXA
select TICK_ONESHOT
select PLAT_PXA
select SPARSE_IRQ
+ select AUTO_ZRELADDR
+ select MULTI_IRQ_HANDLER
help
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
@@ -638,10 +652,12 @@ config ARCH_SHMOBILE
bool "Renesas SH-Mobile / R-Mobile"
select HAVE_CLK
select CLKDEV_LOOKUP
+ select HAVE_MACH_CLKDEV
select GENERIC_CLOCKEVENTS
select NO_IOPORT
select SPARSE_IRQ
select MULTI_IRQ_HANDLER
+ select PM_GENERIC_DOMAINS if PM
help
Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
@@ -682,6 +698,7 @@ config ARCH_S3C2410
select GENERIC_GPIO
select ARCH_HAS_CPUFREQ
select HAVE_CLK
+ select CLKDEV_LOOKUP
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_I2C if I2C
help
@@ -699,6 +716,7 @@ config ARCH_S3C64XX
select CPU_V6
select ARM_VIC
select HAVE_CLK
+ select CLKDEV_LOOKUP
select NO_IOPORT
select ARCH_USES_GETTIMEOFFSET
select ARCH_HAS_CPUFREQ
@@ -723,6 +741,8 @@ config ARCH_S5P64X0
select CPU_V6
select GENERIC_GPIO
select HAVE_CLK
+ select CLKDEV_LOOKUP
+ select CLKSRC_MMIO
select HAVE_S3C2410_WATCHDOG if WATCHDOG
select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK
@@ -736,6 +756,7 @@ config ARCH_S5PC100
bool "Samsung S5PC100"
select GENERIC_GPIO
select HAVE_CLK
+ select CLKDEV_LOOKUP
select CPU_V7
select ARM_L1_CACHE_SHIFT_6
select ARCH_USES_GETTIMEOFFSET
@@ -749,8 +770,11 @@ config ARCH_S5PV210
bool "Samsung S5PV210/S5PC110"
select CPU_V7
select ARCH_SPARSEMEM_ENABLE
+ select ARCH_HAS_HOLES_MEMORYMODEL
select GENERIC_GPIO
select HAVE_CLK
+ select CLKDEV_LOOKUP
+ select CLKSRC_MMIO
select ARM_L1_CACHE_SHIFT_6
select ARCH_HAS_CPUFREQ
select GENERIC_CLOCKEVENTS
@@ -765,8 +789,10 @@ config ARCH_EXYNOS4
bool "Samsung EXYNOS4"
select CPU_V7
select ARCH_SPARSEMEM_ENABLE
+ select ARCH_HAS_HOLES_MEMORYMODEL
select GENERIC_GPIO
select HAVE_CLK
+ select CLKDEV_LOOKUP
select ARCH_HAS_CPUFREQ
select GENERIC_CLOCKEVENTS
select HAVE_S3C_RTC if RTC_CLASS
@@ -808,6 +834,7 @@ config ARCH_U300
select ARM_VIC
select GENERIC_CLOCKEVENTS
select CLKDEV_LOOKUP
+ select HAVE_MACH_CLKDEV
select GENERIC_GPIO
help
Support for ST-Ericsson U300 series mobile platforms.
@@ -852,6 +879,7 @@ config ARCH_OMAP
select HAVE_CLK
select ARCH_REQUIRE_GPIOLIB
select ARCH_HAS_CPUFREQ
+ select CLKSRC_MMIO
select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK
select ARCH_HAS_HOLES_MEMORYMODEL
@@ -879,6 +907,19 @@ config ARCH_VT8500
select HAVE_PWM
help
Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
+
+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
+ select ARM_AMBA
+ select ICST
+ select USE_OF
+ help
+ Support for Xilinx Zynq ARM Cortex A9 Platform
endchoice
#
@@ -924,8 +965,6 @@ source "arch/arm/mach-kirkwood/Kconfig"
source "arch/arm/mach-ks8695/Kconfig"
-source "arch/arm/mach-loki/Kconfig"
-
source "arch/arm/mach-lpc32xx/Kconfig"
source "arch/arm/mach-msm/Kconfig"
@@ -969,7 +1008,6 @@ source "arch/arm/plat-spear/Kconfig"
source "arch/arm/plat-tcc/Kconfig"
if ARCH_S3C2410
-source "arch/arm/mach-s3c2400/Kconfig"
source "arch/arm/mach-s3c2410/Kconfig"
source "arch/arm/mach-s3c2412/Kconfig"
source "arch/arm/mach-s3c2416/Kconfig"
@@ -1346,7 +1384,6 @@ config SMP_ON_UP
config HAVE_ARM_SCU
bool
- depends on SMP
help
This option enables support for the ARM system coherency unit
@@ -1715,17 +1752,34 @@ config ZBOOT_ROM
Say Y here if you intend to execute your compressed kernel image
(zImage) directly from ROM or flash. If unsure, say N.
+choice
+ prompt "Include SD/MMC loader in zImage (EXPERIMENTAL)"
+ depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL
+ default ZBOOT_ROM_NONE
+ help
+ Include experimental SD/MMC loading code in the ROM-able zImage.
+ With this enabled it is possible to write the the ROM-able zImage
+ kernel image to an MMC or SD card and boot the kernel straight
+ from the reset vector. At reset the processor Mask ROM will load
+ the first part of the the ROM-able zImage which in turn loads the
+ rest the kernel image to RAM.
+
+config ZBOOT_ROM_NONE
+ bool "No SD/MMC loader in zImage (EXPERIMENTAL)"
+ help
+ Do not load image from SD or MMC
+
config ZBOOT_ROM_MMCIF
bool "Include MMCIF loader in zImage (EXPERIMENTAL)"
- depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL
help
- Say Y here to include experimental MMCIF loading code in the
- ROM-able zImage. With this enabled it is possible to write the
- the ROM-able zImage kernel image to an MMC card and boot the
- kernel straight from the reset vector. At reset the processor
- Mask ROM will load the first part of the the ROM-able zImage
- which in turn loads the rest the kernel image to RAM using the
- MMCIF hardware block.
+ Load image from MMCIF hardware block.
+
+config ZBOOT_ROM_SH_MOBILE_SDHI
+ bool "Include SuperH Mobile SDHI loader in zImage (EXPERIMENTAL)"
+ help
+ Load image from SDHI hardware block
+
+endchoice
config CMDLINE
string "Default kernel command string"
@@ -1875,10 +1929,6 @@ config CPU_FREQ_PXA
default y
select CPU_FREQ_DEFAULT_GOV_USERSPACE
-config CPU_FREQ_S3C64XX
- bool "CPUfreq support for Samsung S3C64XX CPUs"
- depends on CPU_FREQ && CPU_S3C6410
-
config CPU_FREQ_S3C
bool
help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index f5b2b390c8f2..3a4a04b33d0f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -150,7 +150,6 @@ machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_KIRKWOOD) := kirkwood
machine-$(CONFIG_ARCH_KS8695) := ks8695
-machine-$(CONFIG_ARCH_LOKI) := loki
machine-$(CONFIG_ARCH_LPC32XX) := lpc32xx
machine-$(CONFIG_ARCH_MMP) := mmp
machine-$(CONFIG_ARCH_MSM) := msm
@@ -169,11 +168,11 @@ machine-$(CONFIG_ARCH_OMAP3) := omap2
machine-$(CONFIG_ARCH_OMAP4) := omap2
machine-$(CONFIG_ARCH_ORION5X) := orion5x
machine-$(CONFIG_ARCH_PNX4008) := pnx4008
+machine-$(CONFIG_ARCH_PRIMA2) := prima2
machine-$(CONFIG_ARCH_PXA) := pxa
machine-$(CONFIG_ARCH_REALVIEW) := realview
machine-$(CONFIG_ARCH_RPC) := rpc
-machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
-machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0
+machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2412 s3c2416 s3c2440 s3c2443
machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx
machine-$(CONFIG_ARCH_S5P64X0) := s5p64x0
machine-$(CONFIG_ARCH_S5PC100) := s5pc100
@@ -196,6 +195,7 @@ machine-$(CONFIG_MACH_SPEAR300) := spear3xx
machine-$(CONFIG_MACH_SPEAR310) := spear3xx
machine-$(CONFIG_MACH_SPEAR320) := spear3xx
machine-$(CONFIG_MACH_SPEAR600) := spear6xx
+machine-$(CONFIG_ARCH_ZYNQ) := zynq
# Platform directory name. This list is sorted alphanumerically
# by CONFIG_* macro name.
@@ -203,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC) := mxc
plat-$(CONFIG_ARCH_OMAP) := omap
plat-$(CONFIG_ARCH_S3C64XX) := samsung
plat-$(CONFIG_ARCH_TCC_926) := tcc
+plat-$(CONFIG_ARCH_ZYNQ) := versatile
plat-$(CONFIG_PLAT_IOP) := iop
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
plat-$(CONFIG_PLAT_ORION) := orion
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 23aad0722303..0c74a6fab952 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -6,13 +6,19 @@
OBJS =
-# Ensure that mmcif loader code appears early in the image
+# Ensure that MMCIF loader code appears early in the image
# to minimise that number of bocks that have to be read in
# order to load it.
ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y)
-ifeq ($(CONFIG_ARCH_SH7372),y)
OBJS += mmcif-sh7372.o
endif
+
+# Ensure that SDHI loader code appears early in the image
+# to minimise that number of bocks that have to be read in
+# order to load it.
+ifeq ($(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI),y)
+OBJS += sdhi-shmobile.o
+OBJS += sdhi-sh7372.o
endif
AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
index c943d2e7da9d..fe3719b516fd 100644
--- a/arch/arm/boot/compressed/head-shmobile.S
+++ b/arch/arm/boot/compressed/head-shmobile.S
@@ -25,14 +25,14 @@
/* load board-specific initialization code */
#include <mach/zboot.h>
-#ifdef CONFIG_ZBOOT_ROM_MMCIF
- /* Load image from MMC */
- adr sp, __tmp_stack + 128
+#if defined(CONFIG_ZBOOT_ROM_MMCIF) || defined(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI)
+ /* Load image from MMC/SD */
+ adr sp, __tmp_stack + 256
ldr r0, __image_start
ldr r1, __image_end
subs r1, r1, r0
ldr r0, __load_base
- bl mmcif_loader
+ bl mmc_loader
/* Jump to loaded code */
ldr r0, __loaded
@@ -51,9 +51,9 @@ __loaded:
.long __continue
.align
__tmp_stack:
- .space 128
+ .space 256
__continue:
-#endif /* CONFIG_ZBOOT_ROM_MMCIF */
+#endif /* CONFIG_ZBOOT_ROM_MMC || CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI */
b 1f
__atags:@ tag #1
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 940b20178107..e95a5989602a 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -353,7 +353,8 @@ not_relocated: mov r0, #0
mov r0, #0 @ must be zero
mov r1, r7 @ restore architecture number
mov r2, r8 @ restore atags pointer
- mov pc, r4 @ call kernel
+ ARM( mov pc, r4 ) @ call kernel
+ THUMB( bx r4 ) @ entry point is always ARM
.align 2
.type LC0, #object
diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c
index 7453c8337b83..b6f61d9a5a1b 100644
--- a/arch/arm/boot/compressed/mmcif-sh7372.c
+++ b/arch/arm/boot/compressed/mmcif-sh7372.c
@@ -40,7 +40,7 @@
* to an MMC card
* # dd if=vrl4.out of=/dev/sdx bs=512 seek=1
*/
-asmlinkage void mmcif_loader(unsigned char *buf, unsigned long len)
+asmlinkage void mmc_loader(unsigned char *buf, unsigned long len)
{
mmc_init_progress();
mmc_update_progress(MMC_PROGRESS_ENTER);
diff --git a/arch/arm/boot/compressed/sdhi-sh7372.c b/arch/arm/boot/compressed/sdhi-sh7372.c
new file mode 100644
index 000000000000..d403a8b24d7f
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-sh7372.c
@@ -0,0 +1,95 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Kuninori Morimoto
+ * Copyright (C) 2010 Simon Horman
+ *
+ * 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.
+ *
+ * Parts inspired by u-boot
+ */
+
+#include <linux/io.h>
+#include <mach/mmc.h>
+#include <linux/mmc/boot.h>
+#include <linux/mmc/tmio.h>
+
+#include "sdhi-shmobile.h"
+
+#define PORT179CR 0xe60520b3
+#define PORT180CR 0xe60520b4
+#define PORT181CR 0xe60520b5
+#define PORT182CR 0xe60520b6
+#define PORT183CR 0xe60520b7
+#define PORT184CR 0xe60520b8
+
+#define SMSTPCR3 0xe615013c
+
+#define CR_INPUT_ENABLE 0x10
+#define CR_FUNCTION1 0x01
+
+#define SDHI1_BASE (void __iomem *)0xe6860000
+#define SDHI_BASE SDHI1_BASE
+
+/* SuperH Mobile SDHI loader
+ *
+ * loads the zImage from an SD card starting from block 0
+ * on physical partition 1
+ *
+ * The image must be start with a vrl4 header and
+ * the zImage must start at offset 512 of the image. That is,
+ * at block 1 (=byte 512) of physical partition 1
+ *
+ * Use the following line to write the vrl4 formated zImage
+ * to an SD card
+ * # dd if=vrl4.out of=/dev/sdx bs=512
+ */
+asmlinkage void mmc_loader(unsigned short *buf, unsigned long len)
+{
+ int high_capacity;
+
+ mmc_init_progress();
+
+ mmc_update_progress(MMC_PROGRESS_ENTER);
+ /* Initialise SDHI1 */
+ /* PORT184CR: GPIO_FN_SDHICMD1 Control */
+ __raw_writeb(CR_FUNCTION1, PORT184CR);
+ /* PORT179CR: GPIO_FN_SDHICLK1 Control */
+ __raw_writeb(CR_INPUT_ENABLE|CR_FUNCTION1, PORT179CR);
+ /* PORT181CR: GPIO_FN_SDHID1_3 Control */
+ __raw_writeb(CR_FUNCTION1, PORT183CR);
+ /* PORT182CR: GPIO_FN_SDHID1_2 Control */
+ __raw_writeb(CR_FUNCTION1, PORT182CR);
+ /* PORT183CR: GPIO_FN_SDHID1_1 Control */
+ __raw_writeb(CR_FUNCTION1, PORT181CR);
+ /* PORT180CR: GPIO_FN_SDHID1_0 Control */
+ __raw_writeb(CR_FUNCTION1, PORT180CR);
+
+ /* Enable clock to SDHI1 hardware block */
+ __raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 13), SMSTPCR3);
+
+ /* setup SDHI hardware */
+ mmc_update_progress(MMC_PROGRESS_INIT);
+ high_capacity = sdhi_boot_init(SDHI_BASE);
+ if (high_capacity < 0)
+ goto err;
+
+ mmc_update_progress(MMC_PROGRESS_LOAD);
+ /* load kernel */
+ if (sdhi_boot_do_read(SDHI_BASE, high_capacity,
+ 0, /* Kernel is at block 1 */
+ (len + TMIO_BBS - 1) / TMIO_BBS, buf))
+ goto err;
+
+ /* Disable clock to SDHI1 hardware block */
+ __raw_writel(__raw_readl(SMSTPCR3) & (1 << 13), SMSTPCR3);
+
+ mmc_update_progress(MMC_PROGRESS_DONE);
+
+ return;
+err:
+ for(;;);
+}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.c b/arch/arm/boot/compressed/sdhi-shmobile.c
new file mode 100644
index 000000000000..bd3d46980955
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-shmobile.c
@@ -0,0 +1,449 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Kuninori Morimoto
+ * Copyright (C) 2010 Simon Horman
+ *
+ * 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.
+ *
+ * Parts inspired by u-boot
+ */
+
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/tmio.h>
+#include <mach/sdhi.h>
+
+#define OCR_FASTBOOT (1<<29)
+#define OCR_HCS (1<<30)
+#define OCR_BUSY (1<<31)
+
+#define RESP_CMD12 0x00000030
+
+static inline u16 sd_ctrl_read16(void __iomem *base, int addr)
+{
+ return __raw_readw(base + addr);
+}
+
+static inline u32 sd_ctrl_read32(void __iomem *base, int addr)
+{
+ return __raw_readw(base + addr) |
+ __raw_readw(base + addr + 2) << 16;
+}
+
+static inline void sd_ctrl_write16(void __iomem *base, int addr, u16 val)
+{
+ __raw_writew(val, base + addr);
+}
+
+static inline void sd_ctrl_write32(void __iomem *base, int addr, u32 val)
+{
+ __raw_writew(val, base + addr);
+ __raw_writew(val >> 16, base + addr + 2);
+}
+
+#define ALL_ERROR (TMIO_STAT_CMD_IDX_ERR | TMIO_STAT_CRCFAIL | \
+ TMIO_STAT_STOPBIT_ERR | TMIO_STAT_DATATIMEOUT | \
+ TMIO_STAT_RXOVERFLOW | TMIO_STAT_TXUNDERRUN | \
+ TMIO_STAT_CMDTIMEOUT | TMIO_STAT_ILL_ACCESS | \
+ TMIO_STAT_ILL_FUNC)
+
+static int sdhi_intr(void __iomem *base)
+{
+ unsigned long state = sd_ctrl_read32(base, CTL_STATUS);
+
+ if (state & ALL_ERROR) {
+ sd_ctrl_write32(base, CTL_STATUS, ~ALL_ERROR);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ ALL_ERROR |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return -EINVAL;
+ }
+ if (state & TMIO_STAT_CMDRESPEND) {
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ TMIO_STAT_CMDRESPEND |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return 0;
+ }
+ if (state & TMIO_STAT_RXRDY) {
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_RXRDY);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ TMIO_STAT_RXRDY | TMIO_STAT_TXUNDERRUN |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return 0;
+ }
+ if (state & TMIO_STAT_DATAEND) {
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_DATAEND);
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ TMIO_STAT_DATAEND |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ return 0;
+ }
+
+ return -EAGAIN;
+}
+
+static int sdhi_boot_wait_resp_end(void __iomem *base)
+{
+ int err = -EAGAIN, timeout = 10000000;
+
+ while (timeout--) {
+ err = sdhi_intr(base);
+ if (err != -EAGAIN)
+ break;
+ udelay(1);
+ }
+
+ return err;
+}
+
+/* SDHI_CLK_CTRL */
+#define CLK_MMC_ENABLE (1 << 8)
+#define CLK_MMC_INIT (1 << 6) /* clk / 256 */
+
+static void sdhi_boot_mmc_clk_stop(void __iomem *base)
+{
+ sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, 0x0000);
+ msleep(10);
+ sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, ~CLK_MMC_ENABLE &
+ sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
+ msleep(10);
+}
+
+static void sdhi_boot_mmc_clk_start(void __iomem *base)
+{
+ sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, CLK_MMC_ENABLE |
+ sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
+ msleep(10);
+ sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, CLK_MMC_ENABLE);
+ msleep(10);
+}
+
+static void sdhi_boot_reset(void __iomem *base)
+{
+ sd_ctrl_write16(base, CTL_RESET_SD, 0x0000);
+ msleep(10);
+ sd_ctrl_write16(base, CTL_RESET_SD, 0x0001);
+ msleep(10);
+}
+
+/* Set MMC clock / power.
+ * Note: This controller uses a simple divider scheme therefore it cannot
+ * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
+ * MMC wont run that fast, it has to be clocked at 12MHz which is the next
+ * slowest setting.
+ */
+static int sdhi_boot_mmc_set_ios(void __iomem *base, struct mmc_ios *ios)
+{
+ if (sd_ctrl_read32(base, CTL_STATUS) & TMIO_STAT_CMD_BUSY)
+ return -EBUSY;
+
+ if (ios->clock)
+ sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL,
+ ios->clock | CLK_MMC_ENABLE);
+
+ /* Power sequence - OFF -> ON -> UP */
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF: /* power down SD bus */
+ sdhi_boot_mmc_clk_stop(base);
+ break;
+ case MMC_POWER_ON: /* power up SD bus */
+ break;
+ case MMC_POWER_UP: /* start bus clock */
+ sdhi_boot_mmc_clk_start(base);
+ break;
+ }
+
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_1:
+ sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x80e0);
+ break;
+ case MMC_BUS_WIDTH_4:
+ sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x00e0);
+ break;
+ }
+
+ /* Let things settle. delay taken from winCE driver */
+ udelay(140);
+
+ return 0;
+}
+
+/* These are the bitmasks the tmio chip requires to implement the MMC response
+ * types. Note that R1 and R6 are the same in this scheme. */
+#define RESP_NONE 0x0300
+#define RESP_R1 0x0400
+#define RESP_R1B 0x0500
+#define RESP_R2 0x0600
+#define RESP_R3 0x0700
+#define DATA_PRESENT 0x0800
+#define TRANSFER_READ 0x1000
+
+static int sdhi_boot_request(void __iomem *base, struct mmc_command *cmd)
+{
+ int err, c = cmd->opcode;
+
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_NONE: c |= RESP_NONE; break;
+ case MMC_RSP_R1: c |= RESP_R1; break;
+ case MMC_RSP_R1B: c |= RESP_R1B; break;
+ case MMC_RSP_R2: c |= RESP_R2; break;
+ case MMC_RSP_R3: c |= RESP_R3; break;
+ default:
+ return -EINVAL;
+ }
+
+ /* No interrupts so this may not be cleared */
+ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
+
+ sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND |
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ sd_ctrl_write32(base, CTL_ARG_REG, cmd->arg);
+ sd_ctrl_write16(base, CTL_SD_CMD, c);
+
+
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ ~(TMIO_STAT_CMDRESPEND | ALL_ERROR) &
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+
+ err = sdhi_boot_wait_resp_end(base);
+ if (err)
+ return err;
+
+ cmd->resp[0] = sd_ctrl_read32(base, CTL_RESPONSE);
+
+ return 0;
+}
+
+static int sdhi_boot_do_read_single(void __iomem *base, int high_capacity,
+ unsigned long block, unsigned short *buf)
+{
+ int err, i;
+
+ /* CMD17 - Read */
+ {
+ struct mmc_command cmd;
+
+ cmd.opcode = MMC_READ_SINGLE_BLOCK | \
+ TRANSFER_READ | DATA_PRESENT;
+ if (high_capacity)
+ cmd.arg = block;
+ else
+ cmd.arg = block * TMIO_BBS;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ sd_ctrl_write32(base, CTL_IRQ_MASK,
+ ~(TMIO_STAT_DATAEND | TMIO_STAT_RXRDY |
+ TMIO_STAT_TXUNDERRUN) &
+ sd_ctrl_read32(base, CTL_IRQ_MASK));
+ err = sdhi_boot_wait_resp_end(base);
+ if (err)
+ return err;
+
+ sd_ctrl_write16(base, CTL_SD_XFER_LEN, TMIO_BBS);
+ for (i = 0; i < TMIO_BBS / sizeof(*buf); i++)
+ *buf++ = sd_ctrl_read16(base, RESP_CMD12);
+
+ err = sdhi_boot_wait_resp_end(base);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+int sdhi_boot_do_read(void __iomem *base, int high_capacity,
+ unsigned long offset, unsigned short count,
+ unsigned short *buf)
+{
+ unsigned long i;
+ int err = 0;
+
+ for (i = 0; i < count; i++) {
+ err = sdhi_boot_do_read_single(base, high_capacity, offset + i,
+ buf + (i * TMIO_BBS /
+ sizeof(*buf)));
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+#define VOLTAGES (MMC_VDD_32_33 | MMC_VDD_33_34)
+
+int sdhi_boot_init(void __iomem *base)
+{
+ bool sd_v2 = false, sd_v1_0 = false;
+ unsigned short cid;
+ int err, high_capacity = 0;
+
+ sdhi_boot_mmc_clk_stop(base);
+ sdhi_boot_reset(base);
+
+ /* mmc0: clock 400000Hz busmode 1 powermode 2 cs 0 Vdd 21 width 0 timing 0 */
+ {
+ struct mmc_ios ios;
+ ios.power_mode = MMC_POWER_ON;
+ ios.bus_width = MMC_BUS_WIDTH_1;
+ ios.clock = CLK_MMC_INIT;
+ err = sdhi_boot_mmc_set_ios(base, &ios);
+ if (err)
+ return err;
+ }
+
+ /* CMD0 */
+ {
+ struct mmc_command cmd;
+ msleep(1);
+ cmd.opcode = MMC_GO_IDLE_STATE;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_NONE;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ msleep(2);
+ }
+
+ /* CMD8 - Test for SD version 2 */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = SD_SEND_IF_COND;
+ cmd.arg = (VOLTAGES != 0) << 8 | 0xaa;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd); /* Ignore error */
+ if ((cmd.resp[0] & 0xff) == 0xaa)
+ sd_v2 = true;
+ }
+
+ /* CMD55 - Get OCR (SD) */
+ {
+ int timeout = 1000;
+ struct mmc_command cmd;
+
+ cmd.arg = 0;
+
+ do {
+ cmd.opcode = MMC_APP_CMD;
+ cmd.flags = MMC_RSP_R1;
+ cmd.arg = 0;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ break;
+
+ cmd.opcode = SD_APP_OP_COND;
+ cmd.flags = MMC_RSP_R3;
+ cmd.arg = (VOLTAGES & 0xff8000);
+ if (sd_v2)
+ cmd.arg |= OCR_HCS;
+ cmd.arg |= OCR_FASTBOOT;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ break;
+
+ msleep(1);
+ } while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
+
+ if (!err && timeout) {
+ if (!sd_v2)
+ sd_v1_0 = true;
+ high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
+ }
+ }
+
+ /* CMD1 - Get OCR (MMC) */
+ if (!sd_v2 && !sd_v1_0) {
+ int timeout = 1000;
+ struct mmc_command cmd;
+
+ do {
+ cmd.opcode = MMC_SEND_OP_COND;
+ cmd.arg = VOLTAGES | OCR_HCS;
+ cmd.flags = MMC_RSP_R3;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+
+ msleep(1);
+ } while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
+
+ if (!timeout)
+ return -EAGAIN;
+
+ high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
+ }
+
+ /* CMD2 - Get CID */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_ALL_SEND_CID;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R2;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ /* CMD3
+ * MMC: Set the relative address
+ * SD: Get the relative address
+ * Also puts the card into the standby state
+ */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SET_RELATIVE_ADDR;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ cid = cmd.resp[0] >> 16;
+ }
+
+ /* CMD9 - Get CSD */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SEND_CSD;
+ cmd.arg = cid << 16;
+ cmd.flags = MMC_RSP_R2;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ /* CMD7 - Select the card */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SELECT_CARD;
+ //cmd.arg = rca << 16;
+ cmd.arg = cid << 16;
+ //cmd.flags = MMC_RSP_R1B;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ /* CMD16 - Set the block size */
+ {
+ struct mmc_command cmd;
+ cmd.opcode = MMC_SET_BLOCKLEN;
+ cmd.arg = TMIO_BBS;
+ cmd.flags = MMC_RSP_R1;
+ err = sdhi_boot_request(base, &cmd);
+ if (err)
+ return err;
+ }
+
+ return high_capacity;
+}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.h b/arch/arm/boot/compressed/sdhi-shmobile.h
new file mode 100644
index 000000000000..92eaa09f985e
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-shmobile.h
@@ -0,0 +1,11 @@
+#ifndef SDHI_MOBILE_H
+#define SDHI_MOBILE_H
+
+#include <linux/compiler.h>
+
+int sdhi_boot_do_read(void __iomem *base, int high_capacity,
+ unsigned long offset, unsigned short count,
+ unsigned short *buf);
+int sdhi_boot_init(void __iomem *base);
+
+#endif
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index ea80abe78844..4e728834a1b9 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -33,20 +33,24 @@ SECTIONS
*(.text.*)
*(.fixup)
*(.gnu.warning)
+ *(.glue_7t)
+ *(.glue_7)
+ }
+ .rodata : {
*(.rodata)
*(.rodata.*)
- *(.glue_7)
- *(.glue_7t)
+ }
+ .piggydata : {
*(.piggydata)
- . = ALIGN(4);
}
+ . = ALIGN(4);
_etext = .;
+ .got.plt : { *(.got.plt) }
_got_start = .;
.got : { *(.got) }
_got_end = .;
- .got.plt : { *(.got.plt) }
_edata = .;
. = BSS_START;
diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
new file mode 100644
index 000000000000..6fecc88065b2
--- /dev/null
+++ b/arch/arm/boot/dts/prima2-cb.dts
@@ -0,0 +1,416 @@
+/dts-v1/;
+/ {
+ model = "SiRF Prima2 eVB";
+ compatible = "sirf,prima2-cb", "sirf,prima2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ memory {
+ reg = <0x00000000 0x20000000>;
+ };
+
+ chosen {
+ bootargs = "mem=512M real_root=/dev/mmcblk0p2 console=ttyS0 panel=1 bootsplash=true bpp=16 androidboot.console=ttyS1";
+ linux,stdout-path = &uart1;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ reg = <0x0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <32768>;
+ i-cache-size = <32768>;
+ /* from bootloader */
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
+ axi {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x40000000 0x40000000 0x80000000>;
+
+ l2-cache-controller@80040000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x80040000 0x1000>;
+ interrupts = <59>;
+ };
+
+ intc: interrupt-controller@80020000 {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "sirf,prima2-intc";
+ reg = <0x80020000 0x1000>;
+ };
+
+ sys-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x88000000 0x88000000 0x40000>;
+
+ clock-controller@88000000 {
+ compatible = "sirf,prima2-clkc";
+ reg = <0x88000000 0x1000>;
+ interrupts = <3>;
+ };
+
+ reset-controller@88010000 {
+ compatible = "sirf,prima2-rstc";
+ reg = <0x88010000 0x1000>;
+ };
+ };
+
+ mem-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x90000000 0x90000000 0x10000>;
+
+ memory-controller@90000000 {
+ compatible = "sirf,prima2-memc";
+ reg = <0x90000000 0x10000>;
+ interrupts = <27>;
+ };
+ };
+
+ disp-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x90010000 0x90010000 0x30000>;
+
+ display@90010000 {
+ compatible = "sirf,prima2-lcd";
+ reg = <0x90010000 0x20000>;
+ interrupts = <30>;
+ };
+
+ vpp@90020000 {
+ compatible = "sirf,prima2-vpp";
+ reg = <0x90020000 0x10000>;
+ interrupts = <31>;
+ };
+ };
+
+ graphics-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x98000000 0x98000000 0x8000000>;
+
+ graphics@98000000 {
+ compatible = "powervr,sgx531";
+ reg = <0x98000000 0x8000000>;
+ interrupts = <6>;
+ };
+ };
+
+ multimedia-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xa0000000 0xa0000000 0x8000000>;
+
+ multimedia@a0000000 {
+ compatible = "sirf,prima2-video-codec";
+ reg = <0xa0000000 0x8000000>;
+ interrupts = <5>;
+ };
+ };
+
+ dsp-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xa8000000 0xa8000000 0x2000000>;
+
+ dspif@a8000000 {
+ compatible = "sirf,prima2-dspif";
+ reg = <0xa8000000 0x10000>;
+ interrupts = <9>;
+ };
+
+ gps@a8010000 {
+ compatible = "sirf,prima2-gps";
+ reg = <0xa8010000 0x10000>;
+ interrupts = <7>;
+ };
+
+ dsp@a9000000 {
+ compatible = "sirf,prima2-dsp";
+ reg = <0xa9000000 0x1000000>;
+ interrupts = <8>;
+ };
+ };
+
+ peri-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xb0000000 0xb0000000 0x180000>;
+
+ timer@b0020000 {
+ compatible = "sirf,prima2-tick";
+ reg = <0xb0020000 0x1000>;
+ interrupts = <0>;
+ };
+
+ nand@b0030000 {
+ compatible = "sirf,prima2-nand";
+ reg = <0xb0030000 0x10000>;
+ interrupts = <41>;
+ };
+
+ audio@b0040000 {
+ compatible = "sirf,prima2-audio";
+ reg = <0xb0040000 0x10000>;
+ interrupts = <35>;
+ };
+
+ uart0: uart@b0050000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-uart";
+ reg = <0xb0050000 0x10000>;
+ interrupts = <17>;
+ };
+
+ uart1: uart@b0060000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-uart";
+ reg = <0xb0060000 0x10000>;
+ interrupts = <18>;
+ };
+
+ uart2: uart@b0070000 {
+ cell-index = <2>;
+ compatible = "sirf,prima2-uart";
+ reg = <0xb0070000 0x10000>;
+ interrupts = <19>;
+ };
+
+ usp0: usp@b0080000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-usp";
+ reg = <0xb0080000 0x10000>;
+ interrupts = <20>;
+ };
+
+ usp1: usp@b0090000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-usp";
+ reg = <0xb0090000 0x10000>;
+ interrupts = <21>;
+ };
+
+ usp2: usp@b00a0000 {
+ cell-index = <2>;
+ compatible = "sirf,prima2-usp";
+ reg = <0xb00a0000 0x10000>;
+ interrupts = <22>;
+ };
+
+ dmac0: dma-controller@b00b0000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-dmac";
+ reg = <0xb00b0000 0x10000>;
+ interrupts = <12>;
+ };
+
+ dmac1: dma-controller@b0160000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-dmac";
+ reg = <0xb0160000 0x10000>;
+ interrupts = <13>;
+ };
+
+ vip@b00C0000 {
+ compatible = "sirf,prima2-vip";
+ reg = <0xb00C0000 0x10000>;
+ };
+
+ spi0: spi@b00d0000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-spi";
+ reg = <0xb00d0000 0x10000>;
+ interrupts = <15>;
+ };
+
+ spi1: spi@b0170000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-spi";
+ reg = <0xb0170000 0x10000>;
+ interrupts = <16>;
+ };
+
+ i2c0: i2c@b00e0000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-i2c";
+ reg = <0xb00e0000 0x10000>;
+ interrupts = <24>;
+ };
+
+ i2c1: i2c@b00f0000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-i2c";
+ reg = <0xb00f0000 0x10000>;
+ interrupts = <25>;
+ };
+
+ tsc@b0110000 {
+ compatible = "sirf,prima2-tsc";
+ reg = <0xb0110000 0x10000>;
+ interrupts = <33>;
+ };
+
+ gpio: gpio-controller@b0120000 {
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ compatible = "sirf,prima2-gpio";
+ reg = <0xb0120000 0x10000>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pwm@b0130000 {
+ compatible = "sirf,prima2-pwm";
+ reg = <0xb0130000 0x10000>;
+ };
+
+ efusesys@b0140000 {
+ compatible = "sirf,prima2-efuse";
+ reg = <0xb0140000 0x10000>;
+ };
+
+ pulsec@b0150000 {
+ compatible = "sirf,prima2-pulsec";
+ reg = <0xb0150000 0x10000>;
+ interrupts = <48>;
+ };
+
+ pci-iobg {
+ compatible = "sirf,prima2-pciiobg", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x56000000 0x56000000 0x1b00000>;
+
+ sd0: sdhci@56000000 {
+ cell-index = <0>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56000000 0x100000>;
+ interrupts = <38>;
+ };
+
+ sd1: sdhci@56100000 {
+ cell-index = <1>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56100000 0x100000>;
+ interrupts = <38>;
+ };
+
+ sd2: sdhci@56200000 {
+ cell-index = <2>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56200000 0x100000>;
+ interrupts = <23>;
+ };
+
+ sd3: sdhci@56300000 {
+ cell-index = <3>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56300000 0x100000>;
+ interrupts = <23>;
+ };
+
+ sd4: sdhci@56400000 {
+ cell-index = <4>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56400000 0x100000>;
+ interrupts = <39>;
+ };
+
+ sd5: sdhci@56500000 {
+ cell-index = <5>;
+ compatible = "sirf,prima2-sdhc";
+ reg = <0x56500000 0x100000>;
+ interrupts = <39>;
+ };
+
+ pci-copy@57900000 {
+ compatible = "sirf,prima2-pcicp";
+ reg = <0x57900000 0x100000>;
+ interrupts = <40>;
+ };
+
+ rom-interface@57a00000 {
+ compatible = "sirf,prima2-romif";
+ reg = <0x57a00000 0x100000>;
+ };
+ };
+ };
+
+ rtc-iobg {
+ compatible = "sirf,prima2-rtciobg", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x80030000 0x10000>;
+
+ gpsrtc@1000 {
+ compatible = "sirf,prima2-gpsrtc";
+ reg = <0x1000 0x1000>;
+ interrupts = <55 56 57>;
+ };
+
+ sysrtc@2000 {
+ compatible = "sirf,prima2-sysrtc";
+ reg = <0x2000 0x1000>;
+ interrupts = <52 53 54>;
+ };
+
+ pwrc@3000 {
+ compatible = "sirf,prima2-pwrc";
+ reg = <0x3000 0x1000>;
+ interrupts = <32>;
+ };
+ };
+
+ uus-iobg {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xb8000000 0xb8000000 0x40000>;
+
+ usb0: usb@b00e0000 {
+ compatible = "chipidea,ci13611a-prima2";
+ reg = <0xb8000000 0x10000>;
+ interrupts = <10>;
+ };
+
+ usb1: usb@b00f0000 {
+ compatible = "chipidea,ci13611a-prima2";
+ reg = <0xb8010000 0x10000>;
+ interrupts = <11>;
+ };
+
+ sata@b00f0000 {
+ compatible = "synopsys,dwc-ahsata";
+ reg = <0xb8020000 0x10000>;
+ interrupts = <37>;
+ };
+
+ security@b00f0000 {
+ compatible = "sirf,prima2-security";
+ reg = <0xb8030000 0x10000>;
+ interrupts = <42>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
new file mode 100644
index 000000000000..37ca192fb193
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-ep107.dts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/ {
+ model = "Xilinx Zynq EP107";
+ compatible = "xlnx,zynq-ep107";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
+ linux,stdout-path = &uart0;
+ };
+
+ amba {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ intc: interrupt-controller@f8f01000 {
+ interrupt-controller;
+ compatible = "arm,gic";
+ reg = <0xF8F01000 0x1000>;
+ #interrupt-cells = <2>;
+ };
+
+ uart0: uart@e0000000 {
+ compatible = "xlnx,xuartps";
+ reg = <0xE0000000 0x1000>;
+ interrupts = <59 0>;
+ clock = <50000000>;
+ };
+ };
+};
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 841df7d21c2f..595ecd290ebf 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -79,6 +79,8 @@ struct dmabounce_device_info {
struct dmabounce_pool large;
rwlock_t lock;
+
+ int (*needs_bounce)(struct device *, dma_addr_t, size_t);
};
#ifdef STATS
@@ -210,114 +212,91 @@ static struct safe_buffer *find_safe_buffer_dev(struct device *dev,
if (!dev || !dev->archdata.dmabounce)
return NULL;
if (dma_mapping_error(dev, dma_addr)) {
- if (dev)
- dev_err(dev, "Trying to %s invalid mapping\n", where);
- else
- pr_err("unknown device: Trying to %s invalid mapping\n", where);
+ dev_err(dev, "Trying to %s invalid mapping\n", where);
return NULL;
}
return find_safe_buffer(dev->archdata.dmabounce, dma_addr);
}
-static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction dir)
+static int needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
- struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
- dma_addr_t dma_addr;
- int needs_bounce = 0;
-
- if (device_info)
- DO_STATS ( device_info->map_op_count++ );
-
- dma_addr = virt_to_dma(dev, ptr);
+ if (!dev || !dev->archdata.dmabounce)
+ return 0;
if (dev->dma_mask) {
- unsigned long mask = *dev->dma_mask;
- unsigned long limit;
+ unsigned long limit, mask = *dev->dma_mask;
limit = (mask + 1) & ~mask;
if (limit && size > limit) {
dev_err(dev, "DMA mapping too big (requested %#x "
"mask %#Lx)\n", size, *dev->dma_mask);
- return ~0;
+ return -E2BIG;
}
- /*
- * Figure out if we need to bounce from the DMA mask.
- */
- needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
+ /* Figure out if we need to bounce from the DMA mask. */
+ if ((dma_addr | (dma_addr + size - 1)) & ~mask)
+ return 1;
}
- if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
- struct safe_buffer *buf;
+ return !!dev->archdata.dmabounce->needs_bounce(dev, dma_addr, size);
+}
- buf = alloc_safe_buffer(device_info, ptr, size, dir);
- if (buf == 0) {
- dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
- __func__, ptr);
- return ~0;
- }
+static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction dir)
+{
+ struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+ struct safe_buffer *buf;
- dev_dbg(dev,
- "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
- __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
- buf->safe, buf->safe_dma_addr);
+ if (device_info)
+ DO_STATS ( device_info->map_op_count++ );
- if ((dir == DMA_TO_DEVICE) ||
- (dir == DMA_BIDIRECTIONAL)) {
- dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
- __func__, ptr, buf->safe, size);
- memcpy(buf->safe, ptr, size);
- }
- ptr = buf->safe;
+ buf = alloc_safe_buffer(device_info, ptr, size, dir);
+ if (buf == NULL) {
+ dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
+ __func__, ptr);
+ return ~0;
+ }
- dma_addr = buf->safe_dma_addr;
- } else {
- /*
- * We don't need to sync the DMA buffer since
- * it was allocated via the coherent allocators.
- */
- __dma_single_cpu_to_dev(ptr, size, dir);
+ dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
+ __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
+ buf->safe, buf->safe_dma_addr);
+
+ if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) {
+ dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
+ __func__, ptr, buf->safe, size);
+ memcpy(buf->safe, ptr, size);
}
- return dma_addr;
+ return buf->safe_dma_addr;
}
-static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
+static inline void unmap_single(struct device *dev, struct safe_buffer *buf,
size_t size, enum dma_data_direction dir)
{
- struct safe_buffer *buf = find_safe_buffer_dev(dev, dma_addr, "unmap");
-
- if (buf) {
- BUG_ON(buf->size != size);
- BUG_ON(buf->direction != dir);
+ BUG_ON(buf->size != size);
+ BUG_ON(buf->direction != dir);
- dev_dbg(dev,
- "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
- __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
- buf->safe, buf->safe_dma_addr);
+ dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
+ __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
+ buf->safe, buf->safe_dma_addr);
- DO_STATS(dev->archdata.dmabounce->bounce_count++);
+ DO_STATS(dev->archdata.dmabounce->bounce_count++);
- if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
- void *ptr = buf->ptr;
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+ void *ptr = buf->ptr;
- dev_dbg(dev,
- "%s: copy back safe %p to unsafe %p size %d\n",
- __func__, buf->safe, ptr, size);
- memcpy(ptr, buf->safe, size);
+ dev_dbg(dev, "%s: copy back safe %p to unsafe %p size %d\n",
+ __func__, buf->safe, ptr, size);
+ memcpy(ptr, buf->safe, size);
- /*
- * Since we may have written to a page cache page,
- * we need to ensure that the data will be coherent
- * with user mappings.
- */
- __cpuc_flush_dcache_area(ptr, size);
- }
- free_safe_buffer(dev->archdata.dmabounce, buf);
- } else {
- __dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir);
+ /*
+ * Since we may have written to a page cache page,
+ * we need to ensure that the data will be coherent
+ * with user mappings.
+ */
+ __cpuc_flush_dcache_area(ptr, size);
}
+ free_safe_buffer(dev->archdata.dmabounce, buf);
}
/* ************************************************** */
@@ -328,45 +307,28 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
* substitute the safe buffer for the unsafe one.
* (basically move the buffer from an unsafe area to a safe one)
*/
-dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction dir)
-{
- dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- __func__, ptr, size, dir);
-
- BUG_ON(!valid_dma_direction(dir));
-
- return map_single(dev, ptr, size, dir);
-}
-EXPORT_SYMBOL(__dma_map_single);
-
-/*
- * see if a mapped address was really a "safe" buffer and if so, copy
- * the data from the safe buffer back to the unsafe buffer and free up
- * the safe buffer. (basically return things back to the way they
- * should be)
- */
-void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction dir)
-{
- dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- __func__, (void *) dma_addr, size, dir);
-
- unmap_single(dev, dma_addr, size, dir);
-}
-EXPORT_SYMBOL(__dma_unmap_single);
-
dma_addr_t __dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir)
{
+ dma_addr_t dma_addr;
+ int ret;
+
dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
__func__, page, offset, size, dir);
- BUG_ON(!valid_dma_direction(dir));
+ dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
+
+ ret = needs_bounce(dev, dma_addr, size);
+ if (ret < 0)
+ return ~0;
+
+ if (ret == 0) {
+ __dma_page_cpu_to_dev(page, offset, size, dir);
+ return dma_addr;
+ }
if (PageHighMem(page)) {
- dev_err(dev, "DMA buffer bouncing of HIGHMEM pages "
- "is not supported\n");
+ dev_err(dev, "DMA buffer bouncing of HIGHMEM pages is not supported\n");
return ~0;
}
@@ -383,10 +345,19 @@ EXPORT_SYMBOL(__dma_map_page);
void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
- dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- __func__, (void *) dma_addr, size, dir);
+ struct safe_buffer *buf;
+
+ dev_dbg(dev, "%s(dma=%#x,size=%d,dir=%x)\n",
+ __func__, dma_addr, size, dir);
+
+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
+ if (!buf) {
+ __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, dma_addr)),
+ dma_addr & ~PAGE_MASK, size, dir);
+ return;
+ }
- unmap_single(dev, dma_addr, size, dir);
+ unmap_single(dev, buf, size, dir);
}
EXPORT_SYMBOL(__dma_unmap_page);
@@ -461,7 +432,8 @@ static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
}
int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
- unsigned long large_buffer_size)
+ unsigned long large_buffer_size,
+ int (*needs_bounce_fn)(struct device *, dma_addr_t, size_t))
{
struct dmabounce_device_info *device_info;
int ret;
@@ -497,6 +469,7 @@ int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
device_info->dev = dev;
INIT_LIST_HEAD(&device_info->safe_buffers);
rwlock_init(&device_info->lock);
+ device_info->needs_bounce = needs_bounce_fn;
#ifdef STATS
device_info->total_allocs = 0;
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 4ddd0a6ac7ff..3227ca952a12 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -38,12 +38,6 @@ static DEFINE_SPINLOCK(irq_controller_lock);
/* Address of GIC 0 CPU interface */
void __iomem *gic_cpu_base_addr __read_mostly;
-struct gic_chip_data {
- unsigned int irq_offset;
- void __iomem *dist_base;
- void __iomem *cpu_base;
-};
-
/*
* Supported arch specific GIC irq extension.
* Default make them NULL.
@@ -179,22 +173,21 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
{
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
unsigned int shift = (d->irq % 4) * 8;
- unsigned int cpu = cpumask_first(mask_val);
+ unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
u32 val, mask, bit;
- if (cpu >= 8)
+ if (cpu >= 8 || cpu >= nr_cpu_ids)
return -EINVAL;
mask = 0xff << shift;
bit = 1 << (cpu + shift);
spin_lock(&irq_controller_lock);
- d->node = cpu;
val = readl_relaxed(reg) & ~mask;
writel_relaxed(val | bit, reg);
spin_unlock(&irq_controller_lock);
- return 0;
+ return IRQ_SET_MASK_OK;
}
#endif
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index 7a21927c52e1..14ad62e16dd1 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -243,6 +243,12 @@ static struct resource it8152_mem = {
* ITE8152 chip can address up to 64MByte, so all the devices
* connected to ITE8152 (PCI and USB) should have limited DMA window
*/
+static int it8152_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+ dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
+ __func__, dma_addr, size);
+ return (dma_addr + size - PHYS_OFFSET) >= SZ_64M;
+}
/*
* Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all
@@ -254,7 +260,7 @@ static int it8152_pci_platform_notify(struct device *dev)
if (dev->dma_mask)
*dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
- dmabounce_register_dev(dev, 2048, 4096);
+ dmabounce_register_dev(dev, 2048, 4096, it8152_needs_bounce);
}
return 0;
}
@@ -267,14 +273,6 @@ static int it8152_pci_platform_notify_remove(struct device *dev)
return 0;
}
-int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
- dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
- __func__, dma_addr, size);
- return (dev->bus == &pci_bus_type) &&
- ((dma_addr + size - PHYS_OFFSET) >= SZ_64M);
-}
-
int dma_set_coherent_mask(struct device *dev, u64 mask)
{
if (mask >= PHYS_OFFSET + SZ_64M - 1)
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 9c49a46a2b7a..0569de6acfba 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -579,7 +579,36 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2];
}
+#endif
+#ifdef CONFIG_DMABOUNCE
+/*
+ * According to the "Intel StrongARM SA-1111 Microprocessor Companion
+ * Chip Specification Update" (June 2000), erratum #7, there is a
+ * significant bug in the SA1111 SDRAM shared memory controller. If
+ * an access to a region of memory above 1MB relative to the bank base,
+ * it is important that address bit 10 _NOT_ be asserted. Depending
+ * on the configuration of the RAM, bit 10 may correspond to one
+ * of several different (processor-relative) address bits.
+ *
+ * This routine only identifies whether or not a given DMA address
+ * is susceptible to the bug.
+ *
+ * This should only get called for sa1111_device types due to the
+ * way we configure our device dma_masks.
+ */
+static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
+{
+ /*
+ * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
+ * User's Guide" mentions that jumpers R51 and R52 control the
+ * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
+ * SDRAM bank 1 on Neponset). The default configuration selects
+ * Assabet, so any address in bank 1 is necessarily invalid.
+ */
+ return (machine_is_assabet() || machine_is_pfs168()) &&
+ (addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
+}
#endif
static void sa1111_dev_release(struct device *_dev)
@@ -644,7 +673,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
dev->dev.dma_mask = &dev->dma_mask;
if (dev->dma_mask != 0xffffffffUL) {
- ret = dmabounce_register_dev(&dev->dev, 1024, 4096);
+ ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
+ sa1111_needs_bounce);
if (ret) {
dev_err(&dev->dev, "SA1111: Failed to register"
" with dmabounce\n");
@@ -818,34 +848,6 @@ static void __sa1111_remove(struct sa1111 *sachip)
kfree(sachip);
}
-/*
- * According to the "Intel StrongARM SA-1111 Microprocessor Companion
- * Chip Specification Update" (June 2000), erratum #7, there is a
- * significant bug in the SA1111 SDRAM shared memory controller. If
- * an access to a region of memory above 1MB relative to the bank base,
- * it is important that address bit 10 _NOT_ be asserted. Depending
- * on the configuration of the RAM, bit 10 may correspond to one
- * of several different (processor-relative) address bits.
- *
- * This routine only identifies whether or not a given DMA address
- * is susceptible to the bug.
- *
- * This should only get called for sa1111_device types due to the
- * way we configure our device dma_masks.
- */
-int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
-{
- /*
- * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
- * User's Guide" mentions that jumpers R51 and R52 control the
- * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
- * SDRAM bank 1 on Neponset). The default configuration selects
- * Assabet, so any address in bank 1 is necessarily invalid.
- */
- return ((machine_is_assabet() || machine_is_pfs168()) &&
- (addr >= 0xc8000000 || (addr + size) >= 0xc8000000));
-}
-
struct sa1111_save_data {
unsigned int skcr;
unsigned int skpcr;
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index c11af1e4bad3..a07b0e763a80 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -193,7 +193,7 @@ static int __devinit scoop_probe(struct platform_device *pdev)
spin_lock_init(&devptr->scoop_lock);
inf = pdev->dev.platform_data;
- devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
+ devptr->base = ioremap(mem->start, resource_size(mem));
if (!devptr->base) {
ret = -ENOMEM;
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 921e56a7572c..f4b767256f95 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=18
-CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_MODULES=y
@@ -13,6 +12,7 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_PXA=y
+CONFIG_GPIO_PCA953X=y
CONFIG_MACH_CM_X300=y
CONFIG_NO_HZ=y
CONFIG_AEABI=y
@@ -23,7 +23,6 @@ CONFIG_CMDLINE="root=/dev/mtdblock5 rootfstype=ubifs console=ttyS2,38400"
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
CONFIG_APM_EMULATION=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -40,8 +39,8 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
@@ -60,7 +59,6 @@ CONFIG_MTD_NAND_PXA3xx=y
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_NETDEVICES=y
@@ -81,16 +79,15 @@ CONFIG_TOUCHSCREEN_WM97XX=m
# CONFIG_TOUCHSCREEN_WM9705 is not set
# CONFIG_TOUCHSCREEN_WM9713 is not set
# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_PXA=y
CONFIG_SERIAL_PXA_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
CONFIG_I2C_PXA=y
CONFIG_SPI=y
CONFIG_SPI_GPIO=y
CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_PCA953X=y
# CONFIG_HWMON is not set
CONFIG_PMIC_DA903X=y
CONFIG_REGULATOR=y
@@ -102,7 +99,6 @@ CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_TDO24M=y
# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_BACKLIGHT_DA903X=m
-# CONFIG_VGA_CONSOLE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_FONTS=y
@@ -131,7 +127,6 @@ CONFIG_HID_GREENASIA=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
-CONFIG_HID_WACOM=m
CONFIG_HID_ZEROPLUS=y
CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
@@ -152,7 +147,6 @@ CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_TMPFS=y
@@ -164,7 +158,6 @@ CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
-CONFIG_SMB_FS=m
CONFIG_CIFS=m
CONFIG_CIFS_WEAK_PW_HASH=y
CONFIG_PARTITION_ADVANCED=y
@@ -172,9 +165,7 @@ CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHED_DEBUG is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_FTRACE is not set
CONFIG_DEBUG_USER=y
@@ -182,7 +173,6 @@ CONFIG_DEBUG_LL=y
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_ARC4=m
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/arm/configs/loki_defconfig b/arch/arm/configs/loki_defconfig
deleted file mode 100644
index 1ba752b2dc6d..000000000000
--- a/arch/arm/configs/loki_defconfig
+++ /dev/null
@@ -1,120 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_LOKI=y
-CONFIG_MACH_LB88RC8480=y
-# CONFIG_CPU_FEROCEON_OLD_ID is not set
-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_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_FTL=y
-CONFIG_NFTL=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_CFI_I4=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
-CONFIG_MTD_NAND_ORION=y
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_ATA=y
-CONFIG_SATA_MV=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MV643XX_ETH=y
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_LEGACY_PTY_COUNT=16
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MV64XXX=y
-CONFIG_SPI=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_PRINTER=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_NEW_LEDS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_XFS_FS=y
-CONFIG_INOTIFY=y
-CONFIG_ISO9660_FS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_LDM_PARTITION=y
-CONFIG_LDM_DEBUG=y
-CONFIG_SUN_PARTITION=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index 47ad3b1a4fee..5a584520db2f 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -8,6 +8,7 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_MMP=y
+CONFIG_MACH_BROWNSTONE=y
CONFIG_MACH_FLINT=y
CONFIG_MACH_MARVELL_JASPER=y
CONFIG_HIGH_RES_TIMERS=y
@@ -63,10 +64,16 @@ CONFIG_BACKLIGHT_MAX8925=y
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX8925=y
+CONFIG_MMC=y
# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_JFFS2_FS=y
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
@@ -81,7 +88,7 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_INFO=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DYNAMIC_DEBUG=y
+# CONFIG_DYNAMIC_DEBUG is not set
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
index 0ace16cba9b5..88c5802a2351 100644
--- a/arch/arm/configs/mx51_defconfig
+++ b/arch/arm/configs/mx51_defconfig
@@ -106,6 +106,7 @@ CONFIG_GPIO_SYSFS=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
@@ -145,7 +146,7 @@ CONFIG_ROOT_NFS=y
CONFIG_NLS_DEFAULT="cp437"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=y
CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 2bf224310fb4..db2cb7d180dc 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -22,6 +22,8 @@ CONFIG_BLK_DEV_INTEGRITY=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_MXS=y
+CONFIG_MACH_MX23EVK=y
+CONFIG_MACH_MX28EVK=y
CONFIG_MACH_STMP378X_DEVB=y
CONFIG_MACH_TX28=y
# CONFIG_ARM_THUMB is not set
@@ -89,7 +91,7 @@ CONFIG_DISPLAY_SUPPORT=m
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_MXS=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=m
CONFIG_DMADEVICES=y
CONFIG_MXS_DMA=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index a5cce242a775..97d31a4663da 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -11,12 +11,12 @@ CONFIG_ARCH_U8500=y
CONFIG_UX500_SOC_DB5500=y
CONFIG_UX500_SOC_DB8500=y
CONFIG_MACH_U8500=y
+CONFIG_MACH_SNOWBALL=y
CONFIG_MACH_U5500=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
-CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
@@ -25,8 +25,13 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NETFILTER=y
CONFIG_PHONET=y
-CONFIG_PHONET_PIPECTRLR=y
# CONFIG_WIRELESS is not set
CONFIG_CAIF=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -35,6 +40,13 @@ CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_MISC_DEVICES=y
CONFIG_AB8500_PWM=y
CONFIG_SENSORS_BH1780=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set
@@ -49,9 +61,9 @@ CONFIG_INPUT_MISC=y
CONFIG_INPUT_AB8500_PONKEY=y
# CONFIG_SERIO is not set
CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_NOMADIK=y
CONFIG_I2C=y
@@ -64,14 +76,19 @@ CONFIG_GPIO_TC3589X=y
CONFIG_MFD_STMPE=y
CONFIG_MFD_TC3589X=y
CONFIG_AB8500_CORE=y
-CONFIG_REGULATOR=y
CONFIG_REGULATOR_AB8500=y
# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_USB_GADGET=y
+CONFIG_AB8500_USB=y
CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_ARMMMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_LM3530=y
CONFIG_LEDS_LP5521=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AB8500=y
@@ -79,7 +96,6 @@ CONFIG_RTC_DRV_PL031=y
CONFIG_DMADEVICES=y
CONFIG_STE_DMA40=y
CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
@@ -91,6 +107,8 @@ CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_CONFIGFS_FS=m
# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_MAGIC_SYSRQ=y
@@ -99,7 +117,5 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_FTRACE is not set
CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 65c3f2474f5e..29035e86a59d 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -293,4 +293,13 @@
.macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort
.endm
+
+/* Utility macro for declaring string literals */
+ .macro string name:req, string
+ .type \name , #object
+\name:
+ .asciz "\string"
+ .size \name , . - \name
+ .endm
+
#endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index 7e79503ab89b..86976d034382 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -208,16 +208,15 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
c = old;
- return c != u;
+ return c;
}
-#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)
@@ -460,9 +459,6 @@ static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)
-#else /* !CONFIG_GENERIC_ATOMIC64 */
-#include <asm-generic/atomic64.h>
-#endif
-#include <asm-generic/atomic-long.h>
+#endif /* !CONFIG_GENERIC_ATOMIC64 */
#endif
#endif
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index b4892a06442c..f7419ef9c8f9 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -26,8 +26,8 @@
#include <linux/compiler.h>
#include <asm/system.h>
-#define smp_mb__before_clear_bit() mb()
-#define smp_mb__after_clear_bit() mb()
+#define smp_mb__before_clear_bit() smp_mb()
+#define smp_mb__after_clear_bit() smp_mb()
/*
* These functions are the basis of our bit ops.
@@ -310,10 +310,7 @@ static inline int find_next_bit_le(const void *p, int size, int offset)
/*
* Ext2 is defined to use little-endian byte ordering.
*/
-#define ext2_set_bit_atomic(lock, nr, p) \
- test_and_set_bit_le(nr, p)
-#define ext2_clear_bit_atomic(lock, nr, p) \
- test_and_clear_bit_le(nr, p)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* __KERNEL__ */
diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h
index 765d33222369..80751c15c300 100644
--- a/arch/arm/include/asm/clkdev.h
+++ b/arch/arm/include/asm/clkdev.h
@@ -14,7 +14,12 @@
#include <linux/slab.h>
+#ifdef CONFIG_HAVE_MACH_CLKDEV
#include <mach/clkdev.h>
+#else
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+#endif
static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
{
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 4fff837363ed..7a21d0bf7134 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -115,39 +115,8 @@ static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
___dma_page_dev_to_cpu(page, off, size, dir);
}
-/*
- * Return whether the given device DMA address mask can be supported
- * properly. For example, if your device can only drive the low 24-bits
- * during bus mastering, then you would pass 0x00ffffff as the mask
- * to this function.
- *
- * FIXME: This should really be a platform specific issue - we should
- * return false if GFP_DMA allocations may not satisfy the supplied 'mask'.
- */
-static inline int dma_supported(struct device *dev, u64 mask)
-{
- if (mask < ISA_DMA_THRESHOLD)
- return 0;
- return 1;
-}
-
-static inline int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-#ifdef CONFIG_DMABOUNCE
- if (dev->archdata.dmabounce) {
- if (dma_mask >= ISA_DMA_THRESHOLD)
- return 0;
- else
- return -EIO;
- }
-#endif
- if (!dev->dma_mask || !dma_supported(dev, dma_mask))
- return -EIO;
-
- *dev->dma_mask = dma_mask;
-
- return 0;
-}
+extern int dma_supported(struct device *, u64);
+extern int dma_set_mask(struct device *, u64);
/*
* DMA errors are defined by all-bits-set in the DMA address.
@@ -256,14 +225,14 @@ int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
* @dev: valid struct device pointer
* @small_buf_size: size of buffers to use with small buffer pool
* @large_buf_size: size of buffers to use with large buffer pool (can be 0)
+ * @needs_bounce_fn: called to determine whether buffer needs bouncing
*
* This function should be called by low-level platform code to register
* a device as requireing DMA buffer bouncing. The function will allocate
* appropriate DMA pools for the device.
- *
*/
extern int dmabounce_register_dev(struct device *, unsigned long,
- unsigned long);
+ unsigned long, int (*)(struct device *, dma_addr_t, size_t));
/**
* dmabounce_unregister_dev
@@ -277,31 +246,9 @@ extern int dmabounce_register_dev(struct device *, unsigned long,
*/
extern void dmabounce_unregister_dev(struct device *);
-/**
- * dma_needs_bounce
- *
- * @dev: valid struct device pointer
- * @dma_handle: dma_handle of unbounced buffer
- * @size: size of region being mapped
- *
- * Platforms that utilize the dmabounce mechanism must implement
- * this function.
- *
- * The dmabounce routines call this function whenever a dma-mapping
- * is requested to determine whether a given buffer needs to be bounced
- * or not. The function must return 0 if the buffer is OK for
- * DMA access and 1 if the buffer needs to be bounced.
- *
- */
-extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
-
/*
* The DMA API, implemented by dmabounce.c. See below for descriptions.
*/
-extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
- enum dma_data_direction);
-extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
- enum dma_data_direction);
extern dma_addr_t __dma_map_page(struct device *, struct page *,
unsigned long, size_t, enum dma_data_direction);
extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
@@ -328,13 +275,6 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
}
-static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
- size_t size, enum dma_data_direction dir)
-{
- __dma_single_cpu_to_dev(cpu_addr, size, dir);
- return virt_to_dma(dev, cpu_addr);
-}
-
static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir)
{
@@ -342,12 +282,6 @@ static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
return pfn_to_dma(dev, page_to_pfn(page)) + offset;
}
-static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
-{
- __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
-}
-
static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir)
{
@@ -373,14 +307,18 @@ static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
size_t size, enum dma_data_direction dir)
{
+ unsigned long offset;
+ struct page *page;
dma_addr_t addr;
+ BUG_ON(!virt_addr_valid(cpu_addr));
+ BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
BUG_ON(!valid_dma_direction(dir));
- addr = __dma_map_single(dev, cpu_addr, size, dir);
- debug_dma_map_page(dev, virt_to_page(cpu_addr),
- (unsigned long)cpu_addr & ~PAGE_MASK, size,
- dir, addr, true);
+ page = virt_to_page(cpu_addr);
+ offset = (unsigned long)cpu_addr & ~PAGE_MASK;
+ addr = __dma_map_page(dev, page, offset, size, dir);
+ debug_dma_map_page(dev, page, offset, size, dir, addr, true);
return addr;
}
@@ -430,7 +368,7 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir)
{
debug_dma_unmap_page(dev, handle, size, dir, true);
- __dma_unmap_single(dev, handle, size, dir);
+ __dma_unmap_page(dev, handle, size, dir);
}
/**
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index 42005542932b..628670e9d7c9 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -1,15 +1,16 @@
#ifndef __ASM_ARM_DMA_H
#define __ASM_ARM_DMA_H
-#include <asm/memory.h>
-
/*
* This is the maximum virtual address which can be DMA'd from.
*/
-#ifndef ARM_DMA_ZONE_SIZE
-#define MAX_DMA_ADDRESS 0xffffffff
+#ifndef CONFIG_ZONE_DMA
+#define MAX_DMA_ADDRESS 0xffffffffUL
#else
-#define MAX_DMA_ADDRESS (PAGE_OFFSET + ARM_DMA_ZONE_SIZE)
+#define MAX_DMA_ADDRESS ({ \
+ extern unsigned long arm_dma_zone_size; \
+ arm_dma_zone_size ? \
+ (PAGE_OFFSET + arm_dma_zone_size) : 0xffffffffUL; })
#endif
#ifdef CONFIG_ISA_DMA_API
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index 2da8547de6d6..2f1e2098dfe7 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -4,8 +4,8 @@
* Interrupt handling. Preserves r7, r8, r9
*/
.macro arch_irq_handler_default
- get_irqnr_preamble r5, lr
-1: get_irqnr_and_base r0, r6, r5, lr
+ get_irqnr_preamble r6, lr
+1: get_irqnr_and_base r0, r2, r6, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@@ -17,17 +17,17 @@
/*
* XXX
*
- * this macro assumes that irqstat (r6) and base (r5) are
+ * this macro assumes that irqstat (r2) and base (r6) are
* preserved from get_irqnr_and_base above
*/
- ALT_SMP(test_for_ipi r0, r6, r5, lr)
+ ALT_SMP(test_for_ipi r0, r2, r6, lr)
ALT_UP_B(9997f)
movne r1, sp
adrne lr, BSYM(1b)
bne do_IPI
#ifdef CONFIG_LOCAL_TIMERS
- test_for_ltirq r0, r6, r5, lr
+ test_for_ltirq r0, r2, r6, lr
movne r0, sp
adrne lr, BSYM(1b)
bne do_local_timer
@@ -40,7 +40,7 @@
.align 5
.global \symbol_name
\symbol_name:
- mov r4, lr
+ mov r8, lr
arch_irq_handler_default
- mov pc, r4
+ mov pc, r8
.endm
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 0691f9dcc500..435d3f86c708 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -41,6 +41,12 @@ 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;
+};
#endif
#endif
diff --git a/arch/arm/include/asm/hardware/scoop.h b/arch/arm/include/asm/hardware/scoop.h
index ebb3ceaa8fac..58cdf5d84122 100644
--- a/arch/arm/include/asm/hardware/scoop.h
+++ b/arch/arm/include/asm/hardware/scoop.h
@@ -61,7 +61,6 @@ struct scoop_pcmcia_dev {
struct scoop_pcmcia_config {
struct scoop_pcmcia_dev *devs;
int num_devs;
- void (*pcmcia_init)(void);
void (*power_ctrl)(struct device *scoop, unsigned short cpr, int nr);
};
diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h
index c1062c317103..c93a22a8b924 100644
--- a/arch/arm/include/asm/hwcap.h
+++ b/arch/arm/include/asm/hwcap.h
@@ -4,22 +4,26 @@
/*
* HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
*/
-#define HWCAP_SWP 1
-#define HWCAP_HALF 2
-#define HWCAP_THUMB 4
-#define HWCAP_26BIT 8 /* Play it safe */
-#define HWCAP_FAST_MULT 16
-#define HWCAP_FPA 32
-#define HWCAP_VFP 64
-#define HWCAP_EDSP 128
-#define HWCAP_JAVA 256
-#define HWCAP_IWMMXT 512
-#define HWCAP_CRUNCH 1024
-#define HWCAP_THUMBEE 2048
-#define HWCAP_NEON 4096
-#define HWCAP_VFPv3 8192
-#define HWCAP_VFPv3D16 16384
-#define HWCAP_TLS 32768
+#define HWCAP_SWP (1 << 0)
+#define HWCAP_HALF (1 << 1)
+#define HWCAP_THUMB (1 << 2)
+#define HWCAP_26BIT (1 << 3) /* Play it safe */
+#define HWCAP_FAST_MULT (1 << 4)
+#define HWCAP_FPA (1 << 5)
+#define HWCAP_VFP (1 << 6)
+#define HWCAP_EDSP (1 << 7)
+#define HWCAP_JAVA (1 << 8)
+#define HWCAP_IWMMXT (1 << 9)
+#define HWCAP_CRUNCH (1 << 10)
+#define HWCAP_THUMBEE (1 << 11)
+#define HWCAP_NEON (1 << 12)
+#define HWCAP_VFPv3 (1 << 13)
+#define HWCAP_VFPv3D16 (1 << 14)
+#define HWCAP_TLS (1 << 15)
+#define HWCAP_VFPv4 (1 << 16)
+#define HWCAP_IDIVA (1 << 17)
+#define HWCAP_IDIVT (1 << 18)
+#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
/*
diff --git a/arch/arm/include/asm/i8253.h b/arch/arm/include/asm/i8253.h
deleted file mode 100644
index 70656b69d5ce..000000000000
--- a/arch/arm/include/asm/i8253.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASMARM_I8253_H
-#define __ASMARM_I8253_H
-
-/* i8253A PIT registers */
-#define PIT_MODE 0x43
-#define PIT_CH0 0x40
-
-#define PIT_LATCH ((PIT_TICK_RATE + HZ / 2) / HZ)
-
-extern raw_spinlock_t i8253_lock;
-
-#define outb_pit outb_p
-#define inb_pit inb_p
-
-#endif
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 2721a5814cb9..5a526afb5f18 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -23,6 +23,7 @@ struct pt_regs;
extern void migrate_irqs(void);
extern void asm_do_IRQ(unsigned int, struct pt_regs *);
+void handle_IRQ(unsigned int, struct pt_regs *);
void init_IRQ(void);
#endif
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index e46bdd0097eb..feec86768f9c 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -24,12 +24,6 @@
#define MAX_INSN_SIZE 2
#define MAX_STACK_SIZE 64 /* 32 would probably be OK */
-/*
- * This undefined instruction must be unique and
- * reserved solely for kprobes' use.
- */
-#define KPROBE_BREAKPOINT_INSTRUCTION 0xe7f001f8
-
#define regs_return_value(regs) ((regs)->ARM_r0)
#define flush_insn_slot(p) do { } while (0)
#define kretprobe_blacklist_size 0
@@ -38,14 +32,17 @@ typedef u32 kprobe_opcode_t;
struct kprobe;
typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
-
typedef unsigned long (kprobe_check_cc)(unsigned long);
+typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *);
+typedef void (kprobe_insn_fn_t)(void);
/* Architecture specific copy of original instruction. */
struct arch_specific_insn {
- kprobe_opcode_t *insn;
- kprobe_insn_handler_t *insn_handler;
- kprobe_check_cc *insn_check_cc;
+ kprobe_opcode_t *insn;
+ kprobe_insn_handler_t *insn_handler;
+ kprobe_check_cc *insn_check_cc;
+ kprobe_insn_singlestep_t *insn_singlestep;
+ kprobe_insn_fn_t *insn_fn;
};
struct prev_kprobe {
@@ -62,20 +59,9 @@ struct kprobe_ctlblk {
};
void arch_remove_kprobe(struct kprobe *);
-void kretprobe_trampoline(void);
-
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
-enum kprobe_insn {
- INSN_REJECTED,
- INSN_GOOD,
- INSN_GOOD_NO_SLOT
-};
-
-enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
- struct arch_specific_insn *);
-void __init arm_kprobe_decode_init(void);
#endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 946f4d778f71..3281fb4b12e3 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -23,6 +23,10 @@ struct machine_desc {
unsigned int nr_irqs; /* number of IRQs */
+#ifdef CONFIG_ZONE_DMA
+ unsigned long dma_zone_size; /* size of DMA-able area */
+#endif
+
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index af44a8fb3480..b8de516e600e 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -204,18 +204,6 @@ static inline unsigned long __phys_to_virt(unsigned long x)
#endif
/*
- * The DMA mask corresponding to the maximum bus address allocatable
- * using GFP_DMA. The default here places no restriction on DMA
- * allocations. This must be the smallest DMA mask in the system,
- * so a successful GFP_DMA allocation will always satisfy this.
- */
-#ifndef ARM_DMA_ZONE_SIZE
-#define ISA_DMA_THRESHOLD (0xffffffffULL)
-#else
-#define ISA_DMA_THRESHOLD (PHYS_OFFSET + ARM_DMA_ZONE_SIZE - 1)
-#endif
-
-/*
* PFNs are used to describe any physical page; this means
* PFN 0 == physical address 0.
*
diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h
index 92e2a833693d..2b1f245db0c6 100644
--- a/arch/arm/include/asm/pci.h
+++ b/arch/arm/include/asm/pci.h
@@ -3,9 +3,19 @@
#ifdef __KERNEL__
#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci-bridge.h>
#include <asm/mach/pci.h> /* for pci_sys_data */
-#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
+
+extern unsigned long pcibios_min_io;
+#define PCIBIOS_MIN_IO pcibios_min_io
+extern unsigned long pcibios_min_mem;
+#define PCIBIOS_MIN_MEM pcibios_min_mem
+
+static inline int pcibios_assign_all_busses(void)
+{
+ return pci_has_flag(PCI_REASSIGN_ALL_RSRC);
+}
#ifdef CONFIG_PCI_DOMAINS
static inline int pci_domain_nr(struct pci_bus *bus)
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index c4aa4e8c6af9..0f8e3827a89b 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -24,6 +24,8 @@ enum arm_perf_pmu_ids {
ARM_PERF_PMU_ID_V6MP,
ARM_PERF_PMU_ID_CA8,
ARM_PERF_PMU_ID_CA9,
+ ARM_PERF_PMU_ID_CA5,
+ ARM_PERF_PMU_ID_CA15,
ARM_NUM_PMU_IDS,
};
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 7544ce6b481a..67c70a31a1be 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -52,7 +52,7 @@ reserve_pmu(enum arm_pmu_type device);
* a cookie.
*/
extern int
-release_pmu(struct platform_device *pdev);
+release_pmu(enum arm_pmu_type type);
/**
* init_pmu() - Initialise the PMU.
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 8ec535e11fd7..633d1cb84d87 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -82,13 +82,13 @@ 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));
#else
-#define cpu_proc_init() processor._proc_init()
-#define cpu_proc_fin() processor._proc_fin()
-#define cpu_reset(addr) processor.reset(addr)
-#define cpu_do_idle() processor._do_idle()
-#define cpu_dcache_clean_area(addr,sz) processor.dcache_clean_area(addr,sz)
-#define cpu_set_pte_ext(ptep,pte,ext) processor.set_pte_ext(ptep,pte,ext)
-#define cpu_do_switch_mm(pgd,mm) processor.switch_mm(pgd,mm)
+#define cpu_proc_init processor._proc_init
+#define cpu_proc_fin processor._proc_fin
+#define cpu_reset processor.reset
+#define cpu_do_idle processor._do_idle
+#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
#endif
extern void cpu_resume(void);
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 312d10877bd7..96187ff58c24 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -69,8 +69,9 @@
#define PSR_c 0x000000ff /* Control */
/*
- * ARMv7 groups of APSR bits
+ * ARMv7 groups of PSR bits
*/
+#define APSR_MASK 0xf80f0000 /* N, Z, C, V, Q and GE flags */
#define PSR_ISET_MASK 0x01000010 /* ISA state (J, T) mask */
#define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
#define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */
@@ -200,6 +201,14 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define PREDICATE_ALWAYS 0xe0000000
/*
+ * True if instr is a 32-bit thumb instruction. This works if instr
+ * is the first or only half-word of a thumb instruction. It also works
+ * when instr holds all 32-bits of a wide thumb instruction if stored
+ * in the form (first_half<<16)|(second_half)
+ */
+#define is_wide_instruction(instr) ((unsigned)(instr) >= 0xe800)
+
+/*
* kprobe-based event tracer support
*/
#include <linux/stddef.h>
diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h
index 2f87870d9347..cefdb8f898a1 100644
--- a/arch/arm/include/asm/scatterlist.h
+++ b/arch/arm/include/asm/scatterlist.h
@@ -1,6 +1,10 @@
#ifndef _ASMARM_SCATTERLIST_H
#define _ASMARM_SCATTERLIST_H
+#ifdef CONFIG_ARM_HAS_SG_CHAIN
+#define ARCH_HAS_SG_CHAIN
+#endif
+
#include <asm/memory.h>
#include <asm/types.h>
#include <asm-generic/scatterlist.h>
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index ee2ad8ae07af..915696dd9c7c 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -187,12 +187,16 @@ struct tagtable {
#define __tag __used __attribute__((__section__(".taglist.init")))
#define __tagtable(tag, fn) \
-static struct tagtable __tagtable_##fn __tag = { tag, fn }
+static const struct tagtable __tagtable_##fn __tag = { tag, fn }
/*
* Memory map description
*/
-#define NR_BANKS 8
+#ifdef CONFIG_ARCH_EP93XX
+# define NR_BANKS 16
+#else
+# define NR_BANKS 8
+#endif
struct membank {
phys_addr_t start;
diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h
new file mode 100644
index 000000000000..b0e4e1a02318
--- /dev/null
+++ b/arch/arm/include/asm/suspend.h
@@ -0,0 +1,22 @@
+#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;
+}
+
+#endif
diff --git a/arch/arm/include/asm/tcm.h b/arch/arm/include/asm/tcm.h
index 5929ef5d927a..8578d726ad78 100644
--- a/arch/arm/include/asm/tcm.h
+++ b/arch/arm/include/asm/tcm.h
@@ -27,5 +27,7 @@
void *tcm_alloc(size_t len);
void tcm_free(void *addr, size_t len);
+bool tcm_dtcm_present(void);
+bool tcm_itcm_present(void);
#endif
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index d2005de383b8..8077145698ff 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -34,16 +34,12 @@
#define TLB_V6_D_ASID (1 << 17)
#define TLB_V6_I_ASID (1 << 18)
-#define TLB_BTB (1 << 28)
-
/* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */
#define TLB_V7_UIS_PAGE (1 << 19)
#define TLB_V7_UIS_FULL (1 << 20)
#define TLB_V7_UIS_ASID (1 << 21)
-/* Inner Shareable BTB operation (ARMv7 MP extensions) */
-#define TLB_V7_IS_BTB (1 << 22)
-
+#define TLB_BARRIER (1 << 28)
#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */
#define TLB_DCLEAN (1 << 30)
#define TLB_WB (1 << 31)
@@ -58,7 +54,7 @@
* v4wb - ARMv4 with write buffer without I TLB flush entry instruction
* v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
* fr - Feroceon (v4wbi with non-outer-cacheable page table walks)
- * fa - Faraday (v4 with write buffer with UTLB and branch target buffer (BTB))
+ * fa - Faraday (v4 with write buffer with UTLB)
* v6wbi - ARMv6 with write buffer with I TLB flush entry instruction
* v7wbi - identical to v6wbi
*/
@@ -99,7 +95,7 @@
# define v4_always_flags (-1UL)
#endif
-#define fa_tlb_flags (TLB_WB | TLB_BTB | TLB_DCLEAN | \
+#define fa_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
TLB_V4_U_FULL | TLB_V4_U_PAGE)
#ifdef CONFIG_CPU_TLB_FA
@@ -166,7 +162,7 @@
# define v4wb_always_flags (-1UL)
#endif
-#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
TLB_V6_I_FULL | TLB_V6_D_FULL | \
TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
TLB_V6_I_ASID | TLB_V6_D_ASID)
@@ -184,9 +180,9 @@
# define v6wbi_always_flags (-1UL)
#endif
-#define v7wbi_tlb_flags_smp (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
+#define v7wbi_tlb_flags_smp (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
-#define v7wbi_tlb_flags_up (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v7wbi_tlb_flags_up (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
#ifdef CONFIG_CPU_TLB_V7
@@ -341,15 +337,7 @@ static inline void local_flush_tlb_all(void)
if (tlb_flag(TLB_V7_UIS_FULL))
asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
- if (tlb_flag(TLB_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
- dsb();
- isb();
- }
- if (tlb_flag(TLB_V7_IS_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ if (tlb_flag(TLB_BARRIER)) {
dsb();
isb();
}
@@ -389,17 +377,8 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");
#endif
- if (tlb_flag(TLB_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
- dsb();
- }
- if (tlb_flag(TLB_V7_IS_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ if (tlb_flag(TLB_BARRIER))
dsb();
- isb();
- }
}
static inline void
@@ -439,17 +418,8 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
#endif
- if (tlb_flag(TLB_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
- dsb();
- }
- if (tlb_flag(TLB_V7_IS_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ if (tlb_flag(TLB_BARRIER))
dsb();
- isb();
- }
}
static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -482,15 +452,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
if (tlb_flag(TLB_V7_UIS_PAGE))
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
- if (tlb_flag(TLB_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
- dsb();
- isb();
- }
- if (tlb_flag(TLB_V7_IS_BTB)) {
- /* flush the branch target cache */
- asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ if (tlb_flag(TLB_BARRIER)) {
dsb();
isb();
}
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index f90756dc16dc..5b29a6673625 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -3,6 +3,9 @@
#include <linux/list.h>
+struct pt_regs;
+struct task_struct;
+
struct undef_hook {
struct list_head node;
u32 instr_mask;
diff --git a/arch/arm/include/asm/vga.h b/arch/arm/include/asm/vga.h
index 250a4dd00630..91f40217bfa5 100644
--- a/arch/arm/include/asm/vga.h
+++ b/arch/arm/include/asm/vga.h
@@ -2,9 +2,10 @@
#define ASMARM_VGA_H
#include <linux/io.h>
-#include <mach/hardware.h>
-#define VGA_MAP_MEM(x,s) (PCIMEM_BASE + (x))
+extern unsigned long vga_base;
+
+#define VGA_MAP_MEM(x,s) (vga_base + (x))
#define vga_readb(x) (*((volatile unsigned char *)x))
#define vga_writeb(x,y) (*((volatile unsigned char *)y) = (x))
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a5b31af5c2b8..f7887dc53c1f 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -37,7 +37,12 @@ obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
+obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o
+ifdef CONFIG_THUMB2_KERNEL
+obj-$(CONFIG_KPROBES) += kprobes-thumb.o
+else
+obj-$(CONFIG_KPROBES) += kprobes-arm.o
+endif
obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 927522cfc12e..16baba2e4369 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -59,6 +59,9 @@ int main(void)
DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
+#ifdef CONFIG_SMP
+ DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu));
+#endif
#ifdef CONFIG_ARM_THUMBEE
DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state));
#endif
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 90c62cd51ca9..a87cbf889ff4 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -29,21 +29,53 @@
#include <asm/entry-macro-multi.S>
/*
- * Interrupt handling. Preserves r7, r8, r9
+ * Interrupt handling.
*/
.macro irq_handler
#ifdef CONFIG_MULTI_IRQ_HANDLER
- ldr r5, =handle_arch_irq
+ ldr r1, =handle_arch_irq
mov r0, sp
- ldr r5, [r5]
+ ldr r1, [r1]
adr lr, BSYM(9997f)
- teq r5, #0
- movne pc, r5
+ teq r1, #0
+ movne pc, r1
#endif
arch_irq_handler_default
9997:
.endm
+ .macro pabt_helper
+ @ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5
+#ifdef MULTI_PABORT
+ ldr ip, .LCprocfns
+ mov lr, pc
+ ldr pc, [ip, #PROCESSOR_PABT_FUNC]
+#else
+ bl CPU_PABORT_HANDLER
+#endif
+ .endm
+
+ .macro dabt_helper
+
+ @
+ @ Call the processor-specific abort handler:
+ @
+ @ r2 - pt_regs
+ @ r4 - aborted context pc
+ @ r5 - aborted context psr
+ @
+ @ The abort handler must return the aborted address in r0, and
+ @ the fault status register in r1. r9 must be preserved.
+ @
+#ifdef MULTI_DABORT
+ ldr ip, .LCprocfns
+ mov lr, pc
+ ldr pc, [ip, #PROCESSOR_DABT_FUNC]
+#else
+ bl CPU_DABORT_HANDLER
+#endif
+ .endm
+
#ifdef CONFIG_KPROBES
.section .kprobes.text,"ax",%progbits
#else
@@ -126,106 +158,74 @@ ENDPROC(__und_invalid)
SPFIX( subeq sp, sp, #4 )
stmia sp, {r1 - r12}
- ldmia r0, {r1 - r3}
- add r5, sp, #S_SP - 4 @ here for interlock avoidance
- mov r4, #-1 @ "" "" "" ""
- add r0, sp, #(S_FRAME_SIZE + \stack_hole - 4)
- SPFIX( addeq r0, r0, #4 )
- str r1, [sp, #-4]! @ save the "real" r0 copied
+ ldmia r0, {r3 - r5}
+ add r7, sp, #S_SP - 4 @ here for interlock avoidance
+ mov r6, #-1 @ "" "" "" ""
+ add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+ SPFIX( addeq r2, r2, #4 )
+ str r3, [sp, #-4]! @ save the "real" r0 copied
@ from the exception stack
- mov r1, lr
+ mov r3, lr
@
@ We are now ready to fill in the remaining blanks on the stack:
@
- @ r0 - sp_svc
- @ r1 - lr_svc
- @ r2 - lr_<exception>, already fixed up for correct return/restart
- @ r3 - spsr_<exception>
- @ r4 - orig_r0 (see pt_regs definition in ptrace.h)
+ @ r2 - sp_svc
+ @ r3 - lr_svc
+ @ r4 - lr_<exception>, already fixed up for correct return/restart
+ @ r5 - spsr_<exception>
+ @ r6 - orig_r0 (see pt_regs definition in ptrace.h)
@
- stmia r5, {r0 - r4}
+ stmia r7, {r2 - r6}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+ bl trace_hardirqs_off
+#endif
.endm
.align 5
__dabt_svc:
svc_entry
-
- @
- @ get ready to re-enable interrupts if appropriate
- @
- mrs r9, cpsr
- tst r3, #PSR_I_BIT
- biceq r9, r9, #PSR_I_BIT
-
- @
- @ Call the processor-specific abort handler:
- @
- @ r2 - aborted context pc
- @ r3 - aborted context cpsr
- @
- @ The abort handler must return the aborted address in r0, and
- @ the fault status register in r1. r9 must be preserved.
- @
-#ifdef MULTI_DABORT
- ldr r4, .LCprocfns
- mov lr, pc
- ldr pc, [r4, #PROCESSOR_DABT_FUNC]
-#else
- bl CPU_DABORT_HANDLER
-#endif
-
- @
- @ set desired IRQ state, then call main handler
- @
- debug_entry r1
- msr cpsr_c, r9
mov r2, sp
- bl do_DataAbort
+ dabt_helper
@
@ IRQs off again before pulling preserved data off the stack
@
disable_irq_notrace
- @
- @ restore SPSR and restart the instruction
- @
- ldr r2, [sp, #S_PSR]
- svc_exit r2 @ return from exception
+#ifdef CONFIG_TRACE_IRQFLAGS
+ tst r5, #PSR_I_BIT
+ bleq trace_hardirqs_on
+ tst r5, #PSR_I_BIT
+ blne trace_hardirqs_off
+#endif
+ svc_exit r5 @ return from exception
UNWIND(.fnend )
ENDPROC(__dabt_svc)
.align 5
__irq_svc:
svc_entry
+ irq_handler
-#ifdef CONFIG_TRACE_IRQFLAGS
- bl trace_hardirqs_off
-#endif
#ifdef CONFIG_PREEMPT
get_thread_info tsk
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
- add r7, r8, #1 @ increment it
- str r7, [tsk, #TI_PREEMPT]
-#endif
-
- irq_handler
-#ifdef CONFIG_PREEMPT
- str r8, [tsk, #TI_PREEMPT] @ restore preempt count
ldr r0, [tsk, #TI_FLAGS] @ get flags
teq r8, #0 @ if preempt count != 0
movne r0, #0 @ force flags to 0
tst r0, #_TIF_NEED_RESCHED
blne svc_preempt
#endif
- ldr r4, [sp, #S_PSR] @ irqs are already disabled
+
#ifdef CONFIG_TRACE_IRQFLAGS
- tst r4, #PSR_I_BIT
- bleq trace_hardirqs_on
+ @ The parent context IRQs must have been enabled to get here in
+ @ the first place, so there's no point checking the PSR I bit.
+ bl trace_hardirqs_on
#endif
- svc_exit r4 @ return from exception
+ svc_exit r5 @ return from exception
UNWIND(.fnend )
ENDPROC(__irq_svc)
@@ -251,7 +251,6 @@ __und_svc:
#else
svc_entry
#endif
-
@
@ call emulation code, which returns using r9 if it has emulated
@ the instruction, or the more conventional lr if we are to treat
@@ -260,15 +259,16 @@ __und_svc:
@ r0 - instruction
@
#ifndef CONFIG_THUMB2_KERNEL
- ldr r0, [r2, #-4]
+ ldr r0, [r4, #-4]
#else
- ldrh r0, [r2, #-2] @ Thumb instruction at LR - 2
+ ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2
and r9, r0, #0xf800
cmp r9, #0xe800 @ 32-bit instruction if xx >= 0
- ldrhhs r9, [r2] @ bottom 16 bits
+ ldrhhs r9, [r4] @ bottom 16 bits
orrhs r0, r9, r0, lsl #16
#endif
adr r9, BSYM(1f)
+ mov r2, r4
bl call_fpe
mov r0, sp @ struct pt_regs *regs
@@ -282,45 +282,35 @@ __und_svc:
@
@ restore SPSR and restart the instruction
@
- ldr r2, [sp, #S_PSR] @ Get SVC cpsr
- svc_exit r2 @ return from exception
+ ldr r5, [sp, #S_PSR] @ Get SVC cpsr
+#ifdef CONFIG_TRACE_IRQFLAGS
+ tst r5, #PSR_I_BIT
+ bleq trace_hardirqs_on
+ tst r5, #PSR_I_BIT
+ blne trace_hardirqs_off
+#endif
+ svc_exit r5 @ return from exception
UNWIND(.fnend )
ENDPROC(__und_svc)
.align 5
__pabt_svc:
svc_entry
-
- @
- @ re-enable interrupts if appropriate
- @
- mrs r9, cpsr
- tst r3, #PSR_I_BIT
- biceq r9, r9, #PSR_I_BIT
-
- mov r0, r2 @ pass address of aborted instruction.
-#ifdef MULTI_PABORT
- ldr r4, .LCprocfns
- mov lr, pc
- ldr pc, [r4, #PROCESSOR_PABT_FUNC]
-#else
- bl CPU_PABORT_HANDLER
-#endif
- debug_entry r1
- msr cpsr_c, r9 @ Maybe enable interrupts
mov r2, sp @ regs
- bl do_PrefetchAbort @ call abort handler
+ pabt_helper
@
@ IRQs off again before pulling preserved data off the stack
@
disable_irq_notrace
- @
- @ restore SPSR and restart the instruction
- @
- ldr r2, [sp, #S_PSR]
- svc_exit r2 @ return from exception
+#ifdef CONFIG_TRACE_IRQFLAGS
+ tst r5, #PSR_I_BIT
+ bleq trace_hardirqs_on
+ tst r5, #PSR_I_BIT
+ blne trace_hardirqs_off
+#endif
+ svc_exit r5 @ return from exception
UNWIND(.fnend )
ENDPROC(__pabt_svc)
@@ -351,23 +341,23 @@ ENDPROC(__pabt_svc)
ARM( stmib sp, {r1 - r12} )
THUMB( stmia sp, {r0 - r12} )
- ldmia r0, {r1 - r3}
+ ldmia r0, {r3 - r5}
add r0, sp, #S_PC @ here for interlock avoidance
- mov r4, #-1 @ "" "" "" ""
+ mov r6, #-1 @ "" "" "" ""
- str r1, [sp] @ save the "real" r0 copied
+ str r3, [sp] @ save the "real" r0 copied
@ from the exception stack
@
@ We are now ready to fill in the remaining blanks on the stack:
@
- @ r2 - lr_<exception>, already fixed up for correct return/restart
- @ r3 - spsr_<exception>
- @ r4 - orig_r0 (see pt_regs definition in ptrace.h)
+ @ r4 - lr_<exception>, already fixed up for correct return/restart
+ @ r5 - spsr_<exception>
+ @ r6 - orig_r0 (see pt_regs definition in ptrace.h)
@
@ Also, separately save sp_usr and lr_usr
@
- stmia r0, {r2 - r4}
+ stmia r0, {r4 - r6}
ARM( stmdb r0, {sp, lr}^ )
THUMB( store_user_sp_lr r0, r1, S_SP - S_PC )
@@ -380,10 +370,14 @@ ENDPROC(__pabt_svc)
@ Clear FP to mark the first stack frame
@
zero_fp
+
+#ifdef CONFIG_IRQSOFF_TRACER
+ bl trace_hardirqs_off
+#endif
.endm
.macro kuser_cmpxchg_check
-#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
#ifndef CONFIG_MMU
#warning "NPTL on non MMU needs fixing"
#else
@@ -391,8 +385,8 @@ ENDPROC(__pabt_svc)
@ if it was interrupted in a critical region. Here we
@ perform a quick test inline since it should be false
@ 99.9999% of the time. The rest is done out of line.
- cmp r2, #TASK_SIZE
- blhs kuser_cmpxchg_fixup
+ cmp r4, #TASK_SIZE
+ blhs kuser_cmpxchg64_fixup
#endif
#endif
.endm
@@ -401,32 +395,9 @@ ENDPROC(__pabt_svc)
__dabt_usr:
usr_entry
kuser_cmpxchg_check
-
- @
- @ Call the processor-specific abort handler:
- @
- @ r2 - aborted context pc
- @ r3 - aborted context cpsr
- @
- @ The abort handler must return the aborted address in r0, and
- @ the fault status register in r1.
- @
-#ifdef MULTI_DABORT
- ldr r4, .LCprocfns
- mov lr, pc
- ldr pc, [r4, #PROCESSOR_DABT_FUNC]
-#else
- bl CPU_DABORT_HANDLER
-#endif
-
- @
- @ IRQs on, then call the main handler
- @
- debug_entry r1
- enable_irq
mov r2, sp
- adr lr, BSYM(ret_from_exception)
- b do_DataAbort
+ dabt_helper
+ b ret_from_exception
UNWIND(.fnend )
ENDPROC(__dabt_usr)
@@ -434,28 +405,8 @@ ENDPROC(__dabt_usr)
__irq_usr:
usr_entry
kuser_cmpxchg_check
-
-#ifdef CONFIG_IRQSOFF_TRACER
- bl trace_hardirqs_off
-#endif
-
- get_thread_info tsk
-#ifdef CONFIG_PREEMPT
- ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
- add r7, r8, #1 @ increment it
- str r7, [tsk, #TI_PREEMPT]
-#endif
-
irq_handler
-#ifdef CONFIG_PREEMPT
- ldr r0, [tsk, #TI_PREEMPT]
- str r8, [tsk, #TI_PREEMPT]
- teq r0, r7
- ARM( strne r0, [r0, -r0] )
- THUMB( movne r0, #0 )
- THUMB( strne r0, [r0] )
-#endif
-
+ get_thread_info tsk
mov why, #0
b ret_to_user_from_irq
UNWIND(.fnend )
@@ -467,6 +418,9 @@ ENDPROC(__irq_usr)
__und_usr:
usr_entry
+ mov r2, r4
+ mov r3, r5
+
@
@ fall through to the emulation code, which returns using r9 if
@ it has emulated the instruction, or the more conventional lr
@@ -682,19 +636,8 @@ ENDPROC(__und_usr_unknown)
.align 5
__pabt_usr:
usr_entry
-
- mov r0, r2 @ pass address of aborted instruction.
-#ifdef MULTI_PABORT
- ldr r4, .LCprocfns
- mov lr, pc
- ldr pc, [r4, #PROCESSOR_PABT_FUNC]
-#else
- bl CPU_PABORT_HANDLER
-#endif
- debug_entry r1
- enable_irq @ Enable interrupts
mov r2, sp @ regs
- bl do_PrefetchAbort @ call abort handler
+ pabt_helper
UNWIND(.fnend )
/* fall through */
/*
@@ -758,31 +701,12 @@ ENDPROC(__switch_to)
/*
* User helpers.
*
- * These are segment of kernel provided user code reachable from user space
- * at a fixed address in kernel memory. This is used to provide user space
- * with some operations which require kernel help because of unimplemented
- * native feature and/or instructions in many ARM CPUs. The idea is for
- * this code to be executed directly in user mode for best efficiency but
- * which is too intimate with the kernel counter part to be left to user
- * libraries. In fact this code might even differ from one CPU to another
- * depending on the available instruction set and restrictions like on
- * SMP systems. In other words, the kernel reserves the right to change
- * this code as needed without warning. Only the entry points and their
- * results are guaranteed to be stable.
- *
* Each segment is 32-byte aligned and will be moved to the top of the high
* vector page. New segments (if ever needed) must be added in front of
* existing ones. This mechanism should be used only for things that are
* really small and justified, and not be abused freely.
*
- * User space is expected to implement those things inline when optimizing
- * for a processor that has the necessary native support, but only if such
- * resulting binaries are already to be incompatible with earlier ARM
- * processors due to the use of unsupported instructions other than what
- * is provided here. In other words don't make binaries unable to run on
- * earlier processors just for the sake of not using these kernel helpers
- * if your compiled code is not going to use the new instructions for other
- * purpose.
+ * See Documentation/arm/kernel_user_helpers.txt for formal definitions.
*/
THUMB( .arm )
@@ -799,96 +723,103 @@ ENDPROC(__switch_to)
__kuser_helper_start:
/*
- * Reference prototype:
- *
- * void __kernel_memory_barrier(void)
- *
- * Input:
- *
- * lr = return address
- *
- * Output:
- *
- * none
- *
- * Clobbered:
- *
- * none
- *
- * Definition and user space usage example:
- *
- * typedef void (__kernel_dmb_t)(void);
- * #define __kernel_dmb (*(__kernel_dmb_t *)0xffff0fa0)
- *
- * Apply any needed memory barrier to preserve consistency with data modified
- * manually and __kuser_cmpxchg usage.
- *
- * This could be used as follows:
- *
- * #define __kernel_dmb() \
- * asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \
- * : : : "r0", "lr","cc" )
+ * Due to the length of some sequences, __kuser_cmpxchg64 spans 2 regular
+ * kuser "slots", therefore 0xffff0f80 is not used as a valid entry point.
*/
-__kuser_memory_barrier: @ 0xffff0fa0
+__kuser_cmpxchg64: @ 0xffff0f60
+
+#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+
+ /*
+ * Poor you. No fast solution possible...
+ * The kernel itself must perform the operation.
+ * A special ghost syscall is used for that (see traps.c).
+ */
+ stmfd sp!, {r7, lr}
+ ldr r7, 1f @ it's 20 bits
+ swi __ARM_NR_cmpxchg64
+ ldmfd sp!, {r7, pc}
+1: .word __ARM_NR_cmpxchg64
+
+#elif defined(CONFIG_CPU_32v6K)
+
+ stmfd sp!, {r4, r5, r6, r7}
+ ldrd r4, r5, [r0] @ load old val
+ ldrd r6, r7, [r1] @ load new val
+ smp_dmb arm
+1: ldrexd r0, r1, [r2] @ load current val
+ eors r3, r0, r4 @ compare with oldval (1)
+ eoreqs r3, r1, r5 @ compare with oldval (2)
+ strexdeq r3, r6, r7, [r2] @ store newval if eq
+ teqeq r3, #1 @ success?
+ beq 1b @ if no then retry
smp_dmb arm
+ rsbs r0, r3, #0 @ set returned val and C flag
+ ldmfd sp!, {r4, r5, r6, r7}
+ bx lr
+
+#elif !defined(CONFIG_SMP)
+
+#ifdef CONFIG_MMU
+
+ /*
+ * The only thing that can break atomicity in this cmpxchg64
+ * implementation is either an IRQ or a data abort exception
+ * causing another process/thread to be scheduled in the middle of
+ * the critical sequence. The same strategy as for cmpxchg is used.
+ */
+ stmfd sp!, {r4, r5, r6, lr}
+ ldmia r0, {r4, r5} @ load old val
+ ldmia r1, {r6, lr} @ load new val
+1: ldmia r2, {r0, r1} @ load current val
+ eors r3, r0, r4 @ compare with oldval (1)
+ eoreqs r3, r1, r5 @ compare with oldval (2)
+2: stmeqia r2, {r6, lr} @ store newval if eq
+ rsbs r0, r3, #0 @ set return val and C flag
+ ldmfd sp!, {r4, r5, r6, pc}
+
+ .text
+kuser_cmpxchg64_fixup:
+ @ Called from kuser_cmpxchg_fixup.
+ @ r4 = address of interrupted insn (must be preserved).
+ @ sp = saved regs. r7 and r8 are clobbered.
+ @ 1b = first critical insn, 2b = last critical insn.
+ @ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b.
+ mov r7, #0xffff0fff
+ sub r7, r7, #(0xffff0fff - (0xffff0f60 + (1b - __kuser_cmpxchg64)))
+ subs r8, r4, r7
+ rsbcss r8, r8, #(2b - 1b)
+ strcs r7, [sp, #S_PC]
+#if __LINUX_ARM_ARCH__ < 6
+ bcc kuser_cmpxchg32_fixup
+#endif
+ mov pc, lr
+ .previous
+
+#else
+#warning "NPTL on non MMU needs fixing"
+ mov r0, #-1
+ adds r0, r0, #0
usr_ret lr
+#endif
+
+#else
+#error "incoherent kernel configuration"
+#endif
+
+ /* pad to next slot */
+ .rept (16 - (. - __kuser_cmpxchg64)/4)
+ .word 0
+ .endr
.align 5
-/*
- * Reference prototype:
- *
- * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
- *
- * Input:
- *
- * r0 = oldval
- * r1 = newval
- * r2 = ptr
- * lr = return address
- *
- * Output:
- *
- * r0 = returned value (zero or non-zero)
- * C flag = set if r0 == 0, clear if r0 != 0
- *
- * Clobbered:
- *
- * r3, ip, flags
- *
- * Definition and user space usage example:
- *
- * typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
- * #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
- *
- * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
- * Return zero if *ptr was changed or non-zero if no exchange happened.
- * The C flag is also set if *ptr was changed to allow for assembly
- * optimization in the calling code.
- *
- * Notes:
- *
- * - This routine already includes memory barriers as needed.
- *
- * For example, a user space atomic_add implementation could look like this:
- *
- * #define atomic_add(ptr, val) \
- * ({ register unsigned int *__ptr asm("r2") = (ptr); \
- * register unsigned int __result asm("r1"); \
- * asm volatile ( \
- * "1: @ atomic_add\n\t" \
- * "ldr r0, [r2]\n\t" \
- * "mov r3, #0xffff0fff\n\t" \
- * "add lr, pc, #4\n\t" \
- * "add r1, r0, %2\n\t" \
- * "add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
- * "bcc 1b" \
- * : "=&r" (__result) \
- * : "r" (__ptr), "rIL" (val) \
- * : "r0","r3","ip","lr","cc","memory" ); \
- * __result; })
- */
+__kuser_memory_barrier: @ 0xffff0fa0
+ smp_dmb arm
+ usr_ret lr
+
+ .align 5
__kuser_cmpxchg: @ 0xffff0fc0
@@ -925,15 +856,15 @@ __kuser_cmpxchg: @ 0xffff0fc0
usr_ret lr
.text
-kuser_cmpxchg_fixup:
+kuser_cmpxchg32_fixup:
@ Called from kuser_cmpxchg_check macro.
- @ r2 = address of interrupted insn (must be preserved).
+ @ r4 = address of interrupted insn (must be preserved).
@ sp = saved regs. r7 and r8 are clobbered.
@ 1b = first critical insn, 2b = last critical insn.
- @ If r2 >= 1b and r2 <= 2b then saved pc_usr is set to 1b.
+ @ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b.
mov r7, #0xffff0fff
sub r7, r7, #(0xffff0fff - (0xffff0fc0 + (1b - __kuser_cmpxchg)))
- subs r8, r2, r7
+ subs r8, r4, r7
rsbcss r8, r8, #(2b - 1b)
strcs r7, [sp, #S_PC]
mov pc, lr
@@ -963,39 +894,6 @@ kuser_cmpxchg_fixup:
.align 5
-/*
- * Reference prototype:
- *
- * int __kernel_get_tls(void)
- *
- * Input:
- *
- * lr = return address
- *
- * Output:
- *
- * r0 = TLS value
- *
- * Clobbered:
- *
- * none
- *
- * Definition and user space usage example:
- *
- * typedef int (__kernel_get_tls_t)(void);
- * #define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0)
- *
- * Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
- *
- * This could be used as follows:
- *
- * #define __kernel_get_tls() \
- * ({ register unsigned int __val asm("r0"); \
- * asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \
- * : "=r" (__val) : : "lr","cc" ); \
- * __val; })
- */
-
__kuser_get_tls: @ 0xffff0fe0
ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init
usr_ret lr
@@ -1004,19 +902,6 @@ __kuser_get_tls: @ 0xffff0fe0
.word 0 @ 0xffff0ff0 software TLS value, then
.endr @ pad up to __kuser_helper_version
-/*
- * Reference declaration:
- *
- * extern unsigned int __kernel_helper_version;
- *
- * Definition and user space usage example:
- *
- * #define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
- *
- * User space may read this to determine the curent number of helpers
- * available.
- */
-
__kuser_helper_version: @ 0xffff0ffc
.word ((__kuser_helper_end - __kuser_helper_start) >> 5)
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 051166c2a932..9a8531eadd3d 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -121,15 +121,13 @@
.endm
#else /* CONFIG_THUMB2_KERNEL */
.macro svc_exit, rpsr
+ ldr lr, [sp, #S_SP] @ top of the stack
+ ldrd r0, r1, [sp, #S_LR] @ calling lr and pc
clrex @ clear the exclusive monitor
- ldr r0, [sp, #S_SP] @ top of the stack
- ldr r1, [sp, #S_PC] @ return address
- tst r0, #4 @ orig stack 8-byte aligned?
- stmdb r0, {r1, \rpsr} @ rfe context
+ stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context
ldmia sp, {r0 - r12}
- ldr lr, [sp, #S_LR]
- addeq sp, sp, #S_FRAME_SIZE - 8 @ aligned
- addne sp, sp, #S_FRAME_SIZE - 4 @ not aligned
+ mov sp, lr
+ ldr lr, [sp], #4
rfeia sp!
.endm
@@ -165,25 +163,6 @@
.endm
#endif /* !CONFIG_THUMB2_KERNEL */
- @
- @ Debug exceptions are taken as prefetch or data aborts.
- @ We must disable preemption during the handler so that
- @ we can access the debug registers safely.
- @
- .macro debug_entry, fsr
-#if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT)
- ldr r4, =0x40f @ mask out fsr.fs
- and r5, r4, \fsr
- cmp r5, #2 @ debug exception
- bne 1f
- get_thread_info r10
- ldr r6, [r10, #TI_PREEMPT] @ get preempt count
- add r11, r6, #1 @ increment it
- str r11, [r10, #TI_PREEMPT]
-1:
-#endif
- .endm
-
/*
* These are the registers used in the syscall handler, and allow us to
* have in theory up to 7 arguments to a function - r0 to r6.
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 6b1e0ad9ec3b..d46f25968bec 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -32,8 +32,16 @@
* numbers for r1.
*
*/
+ .arm
+
__HEAD
ENTRY(stext)
+
+ THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM.
+ THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
+ THUMB( .thumb ) @ switch to Thumb now.
+ THUMB(1: )
+
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
@ and irqs disabled
#ifndef CONFIG_CPU_CP15
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 278c1b0ebb2e..742b6108a001 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -71,8 +71,16 @@
* crap here - that's what the boot loader (or in extreme, well justified
* circumstances, zImage) is for.
*/
+ .arm
+
__HEAD
ENTRY(stext)
+
+ THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM.
+ THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
+ THUMB( .thumb ) @ switch to Thumb now.
+ THUMB(1: )
+
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
@ and irqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 87acc25d7a3e..a927ca1f5566 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -796,7 +796,7 @@ unlock:
/*
* Called from either the Data Abort Handler [watchpoint] or the
- * Prefetch Abort Handler [breakpoint] with preemption disabled.
+ * Prefetch Abort Handler [breakpoint] with interrupts disabled.
*/
static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
struct pt_regs *regs)
@@ -804,8 +804,10 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
int ret = 0;
u32 dscr;
- /* We must be called with preemption disabled. */
- WARN_ON(preemptible());
+ preempt_disable();
+
+ if (interrupts_enabled(regs))
+ local_irq_enable();
/* We only handle watchpoints and hardware breakpoints. */
ARM_DBG_READ(c1, 0, dscr);
@@ -824,10 +826,6 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
ret = 1; /* Unhandled fault. */
}
- /*
- * Re-enable preemption after it was disabled in the
- * low-level exception handling code.
- */
preempt_enable();
return ret;
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 83bbad03fcc6..de3dcab8610b 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -67,12 +67,12 @@ int arch_show_interrupts(struct seq_file *p, int prec)
}
/*
- * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
- * come via this function. Instead, they should provide their
- * own 'handler'
+ * handle_IRQ handles all hardware IRQ's. Decoded IRQs should
+ * not come via this function. Instead, they should provide their
+ * own 'handler'. Used by platform code implementing C-based 1st
+ * level decoding.
*/
-asmlinkage void __exception_irq_entry
-asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+void handle_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
@@ -97,6 +97,15 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
set_irq_regs(old_regs);
}
+/*
+ * asm_do_IRQ is the interface to be used from assembly code.
+ */
+asmlinkage void __exception_irq_entry
+asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+ handle_IRQ(irq, regs);
+}
+
void set_irq_flags(unsigned int irq, unsigned int iflags)
{
unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
@@ -131,54 +140,63 @@ int __init arch_probe_nr_irqs(void)
#ifdef CONFIG_HOTPLUG_CPU
-static bool migrate_one_irq(struct irq_data *d)
+static bool migrate_one_irq(struct irq_desc *desc)
{
- unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask);
+ struct irq_data *d = irq_desc_get_irq_data(desc);
+ const struct cpumask *affinity = d->affinity;
+ struct irq_chip *c;
bool ret = false;
- if (cpu >= nr_cpu_ids) {
- cpu = cpumask_any(cpu_online_mask);
+ /*
+ * If this is a per-CPU interrupt, or the affinity does not
+ * include this CPU, then we have nothing to do.
+ */
+ if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
+ return false;
+
+ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+ affinity = cpu_online_mask;
ret = true;
}
- pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu);
-
- d->chip->irq_set_affinity(d, cpumask_of(cpu), true);
+ c = irq_data_get_irq_chip(d);
+ if (c->irq_set_affinity)
+ c->irq_set_affinity(d, affinity, true);
+ else
+ pr_debug("IRQ%u: unable to set affinity\n", d->irq);
return ret;
}
/*
- * The CPU has been marked offline. Migrate IRQs off this CPU. If
- * the affinity settings do not allow other CPUs, force them onto any
+ * The current CPU has been marked offline. Migrate IRQs off this CPU.
+ * If the affinity settings do not allow other CPUs, force them onto any
* available CPU.
+ *
+ * Note: we must iterate over all IRQs, whether they have an attached
+ * action structure or not, as we need to get chained interrupts too.
*/
void migrate_irqs(void)
{
- unsigned int i, cpu = smp_processor_id();
+ unsigned int i;
struct irq_desc *desc;
unsigned long flags;
local_irq_save(flags);
for_each_irq_desc(i, desc) {
- struct irq_data *d = &desc->irq_data;
bool affinity_broken = false;
- raw_spin_lock(&desc->lock);
- do {
- if (desc->action == NULL)
- break;
-
- if (d->node != cpu)
- break;
+ if (!desc)
+ continue;
- affinity_broken = migrate_one_irq(d);
- } while (0);
+ raw_spin_lock(&desc->lock);
+ affinity_broken = migrate_one_irq(desc);
raw_spin_unlock(&desc->lock);
if (affinity_broken && printk_ratelimit())
- pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu);
+ pr_warning("IRQ%u no longer affine to CPU%u\n", i,
+ smp_processor_id());
}
local_irq_restore(flags);
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
new file mode 100644
index 000000000000..79203ee1d039
--- /dev/null
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -0,0 +1,999 @@
+/*
+ * arch/arm/kernel/kprobes-decode.c
+ *
+ * Copyright (C) 2006, 2007 Motorola 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.
+ */
+
+/*
+ * We do not have hardware single-stepping on ARM, This
+ * effort is further complicated by the ARM not having a
+ * "next PC" register. Instructions that change the PC
+ * can't be safely single-stepped in a MP environment, so
+ * we have a lot of work to do:
+ *
+ * In the prepare phase:
+ * *) If it is an instruction that does anything
+ * with the CPU mode, we reject it for a kprobe.
+ * (This is out of laziness rather than need. The
+ * instructions could be simulated.)
+ *
+ * *) Otherwise, decode the instruction rewriting its
+ * registers to take fixed, ordered registers and
+ * setting a handler for it to run the instruction.
+ *
+ * In the execution phase by an instruction's handler:
+ *
+ * *) If the PC is written to by the instruction, the
+ * instruction must be fully simulated in software.
+ *
+ * *) Otherwise, a modified form of the instruction is
+ * directly executed. Its handler calls the
+ * instruction in insn[0]. In insn[1] is a
+ * "mov pc, lr" to return.
+ *
+ * Before calling, load up the reordered registers
+ * from the original instruction's registers. If one
+ * of the original input registers is the PC, compute
+ * and adjust the appropriate input register.
+ *
+ * After call completes, copy the output registers to
+ * the original instruction's original registers.
+ *
+ * We don't use a real breakpoint instruction since that
+ * would have us in the kernel go from SVC mode to SVC
+ * mode losing the link register. Instead we use an
+ * undefined instruction. To simplify processing, the
+ * undefined instruction used for kprobes must be reserved
+ * exclusively for kprobes use.
+ *
+ * TODO: ifdef out some instruction decoding based on architecture.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+
+#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
+
+#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
+
+#if __LINUX_ARM_ARCH__ >= 6
+#define BLX(reg) "blx "reg" \n\t"
+#else
+#define BLX(reg) "mov lr, pc \n\t" \
+ "mov pc, "reg" \n\t"
+#endif
+
+/*
+ * To avoid the complications of mimicing single-stepping on a
+ * processor without a Next-PC or a single-step mode, and to
+ * avoid having to deal with the side-effects of boosting, we
+ * simulate or emulate (almost) all ARM instructions.
+ *
+ * "Simulation" is where the instruction's behavior is duplicated in
+ * C code. "Emulation" is where the original instruction is rewritten
+ * and executed, often by altering its registers.
+ *
+ * By having all behavior of the kprobe'd instruction completed before
+ * returning from the kprobe_handler(), all locks (scheduler and
+ * interrupt) can safely be released. There is no need for secondary
+ * breakpoints, no race with MP or preemptable kernels, nor having to
+ * clean up resources counts at a later time impacting overall system
+ * performance. By rewriting the instruction, only the minimum registers
+ * need to be loaded and saved back optimizing performance.
+ *
+ * Calling the insnslot_*_rwflags version of a function doesn't hurt
+ * anything even when the CPSR flags aren't updated by the
+ * instruction. It's just a little slower in return for saving
+ * a little space by not having a duplicate function that doesn't
+ * update the flags. (The same optimization can be said for
+ * instructions that do or don't perform register writeback)
+ * Also, instructions can either read the flags, only write the
+ * flags, or read and write the flags. To save combinations
+ * rather than for sheer performance, flag functions just assume
+ * read and write of flags.
+ */
+
+static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ long iaddr = (long)p->addr;
+ int disp = branch_displacement(insn);
+
+ if (insn & (1 << 24))
+ regs->ARM_lr = iaddr + 4;
+
+ regs->ARM_pc = iaddr + 8 + disp;
+}
+
+static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ long iaddr = (long)p->addr;
+ int disp = branch_displacement(insn);
+
+ regs->ARM_lr = iaddr + 4;
+ regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
+ regs->ARM_cpsr |= PSR_T_BIT;
+}
+
+static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rm = insn & 0xf;
+ long rmv = regs->uregs[rm];
+
+ if (insn & (1 << 5))
+ regs->ARM_lr = (long)p->addr + 4;
+
+ regs->ARM_pc = rmv & ~0x1;
+ regs->ARM_cpsr &= ~PSR_T_BIT;
+ if (rmv & 0x1)
+ regs->ARM_cpsr |= PSR_T_BIT;
+}
+
+static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 12) & 0xf;
+ unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+ regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
+static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->uregs[12] = regs->uregs[13];
+}
+
+static void __kprobes
+emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = (unsigned long)p->addr + 8;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0") = regs->uregs[rt];
+ register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rtv), "=r" (rt2v), "=r" (rnv)
+ : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
+ [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rt] = rtv;
+ regs->uregs[rt+1] = rt2v;
+ if (is_writeback(insn))
+ regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_ldr(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = (unsigned long)p->addr + 8;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0");
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rtv), "=r" (rnv)
+ : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rt == 15)
+ load_write_pc(rtv, regs);
+ else
+ regs->uregs[rt] = rtv;
+
+ if (is_writeback(insn))
+ regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_str(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long rtpc = (unsigned long)p->addr + str_pc_offset;
+ unsigned long rnpc = (unsigned long)p->addr + 8;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
+ : regs->uregs[rt];
+ register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rnv)
+ : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (is_writeback(insn))
+ regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = (unsigned long)p->addr + 8;
+ int rd = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+ int rs = (insn >> 8) & 0xf;
+
+ register unsigned long rdv asm("r0") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+ register unsigned long rmv asm("r3") = (rm == 15) ? pc
+ : regs->uregs[rm];
+ register unsigned long rsv asm("r1") = regs->uregs[rs];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rd == 15)
+ alu_write_pc(rdv, regs);
+ else
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdv asm("r0") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 16) & 0xf;
+ int rn = (insn >> 12) & 0xf;
+ int rm = insn & 0xf;
+ int rs = (insn >> 8) & 0xf;
+
+ register unsigned long rdv asm("r2") = regs->uregs[rd];
+ register unsigned long rnv asm("r0") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+ register unsigned long rsv asm("r1") = regs->uregs[rs];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 12) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdv asm("r0") = regs->uregs[rd];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ BLX("%[fn]")
+ : "=r" (rdv)
+ : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rdlo = (insn >> 12) & 0xf;
+ int rdhi = (insn >> 16) & 0xf;
+ int rn = insn & 0xf;
+ int rm = (insn >> 8) & 0xf;
+
+ register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
+ register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
+ register unsigned long rnv asm("r3") = regs->uregs[rn];
+ register unsigned long rmv asm("r1") = regs->uregs[rm];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ BLX("%[fn]")
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
+ : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
+ "2" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rdlo] = rdlov;
+ regs->uregs[rdhi] = rdhiv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+/*
+ * For the instruction masking and comparisons in all the "space_*"
+ * functions below, Do _not_ rearrange the order of tests unless
+ * you're very, very sure of what you are doing. For the sake of
+ * efficiency, the masks for some tests sometimes assume other test
+ * have been done prior to them so the number of patterns to test
+ * for an instruction set can be as broad as possible to reduce the
+ * number of tests needed.
+ */
+
+static const union decode_item arm_1111_table[] = {
+ /* Unconditional instructions */
+
+ /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */
+ /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */
+ /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */
+ /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop),
+
+ /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */
+ /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */
+ /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */
+ /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop),
+
+ /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1),
+
+ /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
+ /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
+ /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+
+ /* Coprocessor instructions... */
+ /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */
+ /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+ /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+ /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+ /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+ /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
+ /* Miscellaneous instructions */
+
+ /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
+ DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs,
+ REGS(0, NOPC, 0, 0, 0)),
+
+ /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx),
+
+ /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
+ DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx,
+ REGS(0, 0, 0, 0, NOPC)),
+
+ /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
+ /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
+ /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
+ /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
+ DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
+ /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
+ /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
+ /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
+ /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
+ /* Halfword multiply and multiply-accumulate */
+
+ /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
+ DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
+ DECODE_OR (0x0ff000b0, 0x012000a0),
+ /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
+ DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+ /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
+ DECODE_OR (0x0ff00090, 0x01000080),
+ /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
+ DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0000_____1001_table[] = {
+ /* Multiply and multiply-accumulate */
+
+ /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
+ /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+ /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
+ /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_OR (0x0fe000f0, 0x00200090),
+ /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_OR (0x0ff000f0, 0x00400090),
+ /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */
+ /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */
+ /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */
+ /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */
+ /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */
+ /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
+ /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
+ /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_____1001_table[] = {
+ /* Synchronization primitives */
+
+ /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
+ DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_000x_____1xx1_table[] = {
+ /* Extra load/store instructions */
+
+ /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */
+ /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */
+ /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */
+ /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */
+ /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_REJECT (0x0f200090, 0x00200090),
+
+ /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */
+ DECODE_REJECT (0x0e10e0d0, 0x0000e0d0),
+
+ /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */
+ /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd,
+ REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
+
+ /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */
+ /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd,
+ REGS(NOPCWB, NOPCX, 0, 0, 0)),
+
+ /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str,
+ REGS(NOPCWB, NOPC, 0, 0, NOPC)),
+
+ /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
+ /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
+ /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr,
+ REGS(NOPCWB, NOPC, 0, 0, NOPC)),
+
+ /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str,
+ REGS(NOPCWB, NOPC, 0, 0, 0)),
+
+ /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
+ /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
+ /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr,
+ REGS(NOPCWB, NOPC, 0, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_000x_table[] = {
+ /* Data-processing (register) */
+
+ /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_REJECT (0x0e10f000, 0x0010f000),
+
+ /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */
+ DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp),
+
+ /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
+ /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
+ /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
+ /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, 0, 0, 0, ANY)),
+
+ /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
+ /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(0, ANY, 0, 0, ANY)),
+
+ /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
+ /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */
+ /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */
+ /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */
+ /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */
+ /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */
+ /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */
+ /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
+ /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
+ /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
+ DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, ANY, 0, 0, ANY)),
+
+ /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
+ /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
+ /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
+ /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
+ DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, 0, NOPC, 0, ANY)),
+
+ /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
+ /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
+ DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(0, ANY, NOPC, 0, ANY)),
+
+ /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
+ /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */
+ /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */
+ /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */
+ /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */
+ /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */
+ /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */
+ /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
+ /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
+ /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
+ DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, ANY, NOPC, 0, ANY)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_001x_table[] = {
+ /* Data-processing (immediate) */
+
+ /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
+ /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, 0)),
+
+ /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
+ DECODE_OR (0x0fff00ff, 0x03200001),
+ /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
+ DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none),
+ /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
+ /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
+ /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
+ DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop),
+ /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */
+ /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
+ /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0fb00000, 0x03200000),
+
+ /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_REJECT (0x0e10f000, 0x0210f000),
+
+ /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */
+ /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */
+ /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, 0, 0, 0, 0)),
+
+ /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */
+ /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(0, ANY, 0, 0, 0)),
+
+ /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */
+ /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */
+ /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */
+ /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */
+ /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */
+ /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */
+ /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */
+ /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */
+ /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */
+ /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags,
+ REGS(ANY, ANY, 0, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0110_____xxx1_table[] = {
+ /* Media instructions */
+
+ /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */
+ /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */
+ DECODE_OR(0x0fa00030, 0x06a00010),
+ /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */
+ /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */
+ DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
+ /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
+ /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
+ /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
+ DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */
+ DECODE_REJECT (0x0fb00010, 0x06000010),
+ /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */
+ DECODE_REJECT (0x0f8000f0, 0x060000b0),
+ /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */
+ DECODE_REJECT (0x0f8000f0, 0x060000d0),
+ /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */
+ /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */
+ /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */
+ /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */
+ /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */
+ /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */
+ /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */
+ /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */
+ /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */
+ /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */
+ /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */
+ /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */
+ /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */
+ /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */
+ /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */
+ /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */
+ /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */
+ /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */
+ /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */
+ /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */
+ /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */
+ /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */
+ /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */
+ /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */
+ /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */
+ /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */
+ /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */
+ /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */
+ /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */
+ /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */
+ /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */
+ /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */
+ /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */
+ /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */
+ /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */
+ /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */
+ /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */
+ DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+ /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */
+ /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */
+ DECODE_REJECT (0x0fb000f0, 0x06900070),
+
+ /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */
+ /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */
+ /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */
+ /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */
+ /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */
+ /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */
+ DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */
+ /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */
+ /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */
+ /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */
+ /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */
+ /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */
+ DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc,
+ REGS(NOPCX, NOPC, 0, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_0111_____xxx1_table[] = {
+ /* Media instructions */
+
+ /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
+ DECODE_REJECT (0x0ff000f0, 0x07f000f0),
+
+ /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
+ /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
+ DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */
+ /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */
+ DECODE_OR (0x0ff0f090, 0x0700f010),
+ /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */
+ DECODE_OR (0x0ff0f0d0, 0x0750f010),
+ /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
+ DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+ /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */
+ /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */
+ DECODE_OR (0x0ff00090, 0x07000010),
+ /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */
+ DECODE_OR (0x0ff000d0, 0x07500010),
+ /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
+
+ /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */
+ DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+ /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */
+ /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */
+ DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPC)),
+
+ /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */
+ DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, 0)),
+
+ /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */
+ DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc,
+ REGS(0, NOPC, 0, 0, NOPCX)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_01xx_table[] = {
+ /* Load/store word and unsigned byte */
+
+ /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0c40f000, 0x0440f000),
+
+ /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
+ /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0d200000, 0x04200000),
+
+ /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */
+ /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str,
+ REGS(NOPCWB, ANY, 0, 0, 0)),
+
+ /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr,
+ REGS(NOPCWB, ANY, 0, 0, 0)),
+
+ /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */
+ /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str,
+ REGS(NOPCWB, ANY, 0, 0, NOPC)),
+
+ /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr,
+ REGS(NOPCWB, ANY, 0, 0, NOPC)),
+
+ DECODE_END
+};
+
+static const union decode_item arm_cccc_100x_table[] = {
+ /* Block data transfer instructions */
+
+ /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+ /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm),
+
+ /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */
+ /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
+ DECODE_END
+};
+
+const union decode_item kprobe_decode_arm_table[] = {
+ /*
+ * Unconditional instructions
+ * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table),
+
+ /*
+ * Miscellaneous instructions
+ * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx
+ */
+ DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table),
+
+ /*
+ * Halfword multiply and multiply-accumulate
+ * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx
+ */
+ DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table),
+
+ /*
+ * Multiply and multiply-accumulate
+ * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx
+ */
+ DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table),
+
+ /*
+ * Synchronization primitives
+ * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx
+ */
+ DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table),
+
+ /*
+ * Extra load/store instructions
+ * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx
+ */
+ DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table),
+
+ /*
+ * Data-processing (register)
+ * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx
+ * Data-processing (register-shifted register)
+ * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx
+ */
+ DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table),
+
+ /*
+ * Data-processing (immediate)
+ * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table),
+
+ /*
+ * Media instructions
+ * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx
+ */
+ DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table),
+ DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table),
+
+ /*
+ * Load/store word and unsigned byte
+ * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table),
+
+ /*
+ * Block data transfer instructions
+ * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table),
+
+ /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
+ /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl),
+
+ /*
+ * Supervisor Call, and coprocessor instructions
+ */
+
+ /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */
+ /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+ /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+ /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+ /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+ /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+ /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0x0c000000, 0x0c000000),
+
+ DECODE_END
+};
+
+static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 4;
+ p->ainsn.insn_handler(p, regs);
+}
+
+/* Return:
+ * INSN_REJECTED If instruction is one not allowed to kprobe,
+ * INSN_GOOD If instruction is supported and uses instruction slot,
+ * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
+ *
+ * For instructions we don't want to kprobe (INSN_REJECTED return result):
+ * These are generally ones that modify the processor state making
+ * them "hard" to simulate such as switches processor modes or
+ * make accesses in alternate modes. Any of these could be simulated
+ * if the work was put into it, but low return considering they
+ * should also be very rare.
+ */
+enum kprobe_insn __kprobes
+arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = arm_singlestep;
+ asi->insn_check_cc = kprobe_condition_checks[insn>>28];
+ return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false);
+}
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
new file mode 100644
index 000000000000..a5394fb4e4e0
--- /dev/null
+++ b/arch/arm/kernel/kprobes-common.c
@@ -0,0 +1,577 @@
+/*
+ * arch/arm/kernel/kprobes-common.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
+ * Copyright (C) 2006, 2007 Motorola 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/kprobes.h>
+
+#include "kprobes.h"
+
+
+#ifndef find_str_pc_offset
+
+/*
+ * For STR and STM instructions, an ARM core may choose to use either
+ * a +8 or a +12 displacement from the current instruction's address.
+ * Whichever value is chosen for a given core, it must be the same for
+ * both instructions and may not change. This function measures it.
+ */
+
+int str_pc_offset;
+
+void __init find_str_pc_offset(void)
+{
+ int addr, scratch, ret;
+
+ __asm__ (
+ "sub %[ret], pc, #4 \n\t"
+ "str pc, %[addr] \n\t"
+ "ldr %[scr], %[addr] \n\t"
+ "sub %[ret], %[scr], %[ret] \n\t"
+ : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
+
+ str_pc_offset = ret;
+}
+
+#endif /* !find_str_pc_offset */
+
+
+#ifndef test_load_write_pc_interworking
+
+bool load_write_pc_interworks;
+
+void __init test_load_write_pc_interworking(void)
+{
+ int arch = cpu_architecture();
+ BUG_ON(arch == CPU_ARCH_UNKNOWN);
+ load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
+}
+
+#endif /* !test_load_write_pc_interworking */
+
+
+#ifndef test_alu_write_pc_interworking
+
+bool alu_write_pc_interworks;
+
+void __init test_alu_write_pc_interworking(void)
+{
+ int arch = cpu_architecture();
+ BUG_ON(arch == CPU_ARCH_UNKNOWN);
+ alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
+}
+
+#endif /* !test_alu_write_pc_interworking */
+
+
+void __init arm_kprobe_decode_init(void)
+{
+ find_str_pc_offset();
+ test_load_write_pc_interworking();
+ test_alu_write_pc_interworking();
+}
+
+
+static unsigned long __kprobes __check_eq(unsigned long cpsr)
+{
+ return cpsr & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_ne(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_cs(unsigned long cpsr)
+{
+ return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_cc(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_mi(unsigned long cpsr)
+{
+ return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_pl(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_vs(unsigned long cpsr)
+{
+ return cpsr & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_vc(unsigned long cpsr)
+{
+ return (~cpsr) & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_hi(unsigned long cpsr)
+{
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ls(unsigned long cpsr)
+{
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ge(unsigned long cpsr)
+{
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_lt(unsigned long cpsr)
+{
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_gt(unsigned long cpsr)
+{
+ unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return (~temp) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_le(unsigned long cpsr)
+{
+ unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return temp & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_al(unsigned long cpsr)
+{
+ return true;
+}
+
+kprobe_check_cc * const kprobe_condition_checks[16] = {
+ &__check_eq, &__check_ne, &__check_cs, &__check_cc,
+ &__check_mi, &__check_pl, &__check_vs, &__check_vc,
+ &__check_hi, &__check_ls, &__check_ge, &__check_lt,
+ &__check_gt, &__check_le, &__check_al, &__check_al
+};
+
+
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
+{
+}
+
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
+{
+ p->ainsn.insn_fn();
+}
+
+static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rn = (insn >> 16) & 0xf;
+ int lbit = insn & (1 << 20);
+ int wbit = insn & (1 << 21);
+ int ubit = insn & (1 << 23);
+ int pbit = insn & (1 << 24);
+ long *addr = (long *)regs->uregs[rn];
+ int reg_bit_vector;
+ int reg_count;
+
+ reg_count = 0;
+ reg_bit_vector = insn & 0xffff;
+ while (reg_bit_vector) {
+ reg_bit_vector &= (reg_bit_vector - 1);
+ ++reg_count;
+ }
+
+ if (!ubit)
+ addr -= reg_count;
+ addr += (!pbit == !ubit);
+
+ reg_bit_vector = insn & 0xffff;
+ while (reg_bit_vector) {
+ int reg = __ffs(reg_bit_vector);
+ reg_bit_vector &= (reg_bit_vector - 1);
+ if (lbit)
+ regs->uregs[reg] = *addr++;
+ else
+ *addr++ = regs->uregs[reg];
+ }
+
+ if (wbit) {
+ if (!ubit)
+ addr -= reg_count;
+ addr -= (!pbit == !ubit);
+ regs->uregs[rn] = (long)addr;
+ }
+}
+
+static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc = (long)p->addr + str_pc_offset;
+ simulate_ldm1stm1(p, regs);
+ regs->ARM_pc = (long)p->addr + 4;
+}
+
+static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+ simulate_ldm1stm1(p, regs);
+ load_write_pc(regs->ARM_pc, regs);
+}
+
+static void __kprobes
+emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ register void *rregs asm("r1") = regs;
+ register void *rfn asm("lr") = p->ainsn.insn_fn;
+
+ __asm__ __volatile__ (
+ "stmdb sp!, {%[regs], r11} \n\t"
+ "ldmia %[regs], {r0-r12} \n\t"
+#if __LINUX_ARM_ARCH__ >= 6
+ "blx %[fn] \n\t"
+#else
+ "str %[fn], [sp, #-4]! \n\t"
+ "adr lr, 1f \n\t"
+ "ldr pc, [sp], #4 \n\t"
+ "1: \n\t"
+#endif
+ "ldr lr, [sp], #4 \n\t" /* lr = regs */
+ "stmia lr, {r0-r12} \n\t"
+ "ldr r11, [sp], #4 \n\t"
+ : [regs] "=r" (rregs), [fn] "=r" (rfn)
+ : "0" (rregs), "1" (rfn)
+ : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r12", "memory", "cc"
+ );
+}
+
+static void __kprobes
+emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
+}
+
+static void __kprobes
+emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
+{
+ emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
+ load_write_pc(regs->ARM_pc, regs);
+}
+
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ kprobe_insn_handler_t *handler = 0;
+ unsigned reglist = insn & 0xffff;
+ int is_ldm = insn & 0x100000;
+ int rn = (insn >> 16) & 0xf;
+
+ if (rn <= 12 && (reglist & 0xe000) == 0) {
+ /* Instruction only uses registers in the range R0..R12 */
+ handler = emulate_generic_r0_12_noflags;
+
+ } else if (rn >= 2 && (reglist & 0x8003) == 0) {
+ /* Instruction only uses registers in the range R2..R14 */
+ rn -= 2;
+ reglist >>= 2;
+ handler = emulate_generic_r2_14_noflags;
+
+ } else if (rn >= 3 && (reglist & 0x0007) == 0) {
+ /* Instruction only uses registers in the range R3..R15 */
+ if (is_ldm && (reglist & 0x8000)) {
+ rn -= 3;
+ reglist >>= 3;
+ handler = emulate_ldm_r3_15;
+ }
+ }
+
+ if (handler) {
+ /* We can emulate the instruction in (possibly) modified form */
+ asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist;
+ asi->insn_handler = handler;
+ return INSN_GOOD;
+ }
+
+ /* Fallback to slower simulation... */
+ if (reglist & 0x8000)
+ handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
+ else
+ handler = simulate_ldm1stm1;
+ asi->insn_handler = handler;
+ return INSN_GOOD_NO_SLOT;
+}
+
+
+/*
+ * Prepare an instruction slot to receive an instruction for emulating.
+ * This is done by placing a subroutine return after the location where the
+ * instruction will be placed. We also modify ARM instructions to be
+ * unconditional as the condition code will already be checked before any
+ * emulation handler is called.
+ */
+static kprobe_opcode_t __kprobes
+prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ if (thumb) {
+ u16 *thumb_insn = (u16 *)asi->insn;
+ thumb_insn[1] = 0x4770; /* Thumb bx lr */
+ thumb_insn[2] = 0x4770; /* Thumb bx lr */
+ return insn;
+ }
+ asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
+#else
+ asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
+#endif
+ /* Make an ARM instruction unconditional */
+ if (insn < 0xe0000000)
+ insn = (insn | 0xe0000000) & ~0x10000000;
+ return insn;
+}
+
+/*
+ * Write a (probably modified) instruction into the slot previously prepared by
+ * prepare_emulated_insn
+ */
+static void __kprobes
+set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ if (thumb) {
+ u16 *ip = (u16 *)asi->insn;
+ if (is_wide_instruction(insn))
+ *ip++ = insn >> 16;
+ *ip++ = insn;
+ return;
+ }
+#endif
+ asi->insn[0] = insn;
+}
+
+/*
+ * When we modify the register numbers encoded in an instruction to be emulated,
+ * the new values come from this define. For ARM and 32-bit Thumb instructions
+ * this gives...
+ *
+ * bit position 16 12 8 4 0
+ * ---------------+---+---+---+---+---+
+ * register r2 r0 r1 -- r3
+ */
+#define INSN_NEW_BITS 0x00020103
+
+/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
+#define INSN_SAMEAS16_BITS 0x22222222
+
+/*
+ * Validate and modify each of the registers encoded in an instruction.
+ *
+ * Each nibble in regs contains a value from enum decode_reg_type. For each
+ * non-zero value, the corresponding nibble in pinsn is validated and modified
+ * according to the type.
+ */
+static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs)
+{
+ kprobe_opcode_t insn = *pinsn;
+ kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
+
+ for (; regs != 0; regs >>= 4, mask <<= 4) {
+
+ kprobe_opcode_t new_bits = INSN_NEW_BITS;
+
+ switch (regs & 0xf) {
+
+ case REG_TYPE_NONE:
+ /* Nibble not a register, skip to next */
+ continue;
+
+ case REG_TYPE_ANY:
+ /* Any register is allowed */
+ break;
+
+ case REG_TYPE_SAMEAS16:
+ /* Replace register with same as at bit position 16 */
+ new_bits = INSN_SAMEAS16_BITS;
+ break;
+
+ case REG_TYPE_SP:
+ /* Only allow SP (R13) */
+ if ((insn ^ 0xdddddddd) & mask)
+ goto reject;
+ break;
+
+ case REG_TYPE_PC:
+ /* Only allow PC (R15) */
+ if ((insn ^ 0xffffffff) & mask)
+ goto reject;
+ break;
+
+ case REG_TYPE_NOSP:
+ /* Reject SP (R13) */
+ if (((insn ^ 0xdddddddd) & mask) == 0)
+ goto reject;
+ break;
+
+ case REG_TYPE_NOSPPC:
+ case REG_TYPE_NOSPPCX:
+ /* Reject SP and PC (R13 and R15) */
+ if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
+ goto reject;
+ break;
+
+ case REG_TYPE_NOPCWB:
+ if (!is_writeback(insn))
+ break; /* No writeback, so any register is OK */
+ /* fall through... */
+ case REG_TYPE_NOPC:
+ case REG_TYPE_NOPCX:
+ /* Reject PC (R15) */
+ if (((insn ^ 0xffffffff) & mask) == 0)
+ goto reject;
+ break;
+ }
+
+ /* Replace value of nibble with new register number... */
+ insn &= ~mask;
+ insn |= new_bits & mask;
+ }
+
+ *pinsn = insn;
+ return true;
+
+reject:
+ return false;
+}
+
+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)
+};
+
+/*
+ * kprobe_decode_insn operates on data tables in order to decode an ARM
+ * architecture instruction onto which a kprobe has been placed.
+ *
+ * These instruction decoding tables are a concatenation of entries each
+ * of which consist of one of the following structs:
+ *
+ * decode_table
+ * decode_custom
+ * decode_simulate
+ * decode_emulate
+ * decode_or
+ * decode_reject
+ *
+ * Each of these starts with a struct decode_header which has the following
+ * fields:
+ *
+ * type_regs
+ * mask
+ * value
+ *
+ * The least significant DECODE_TYPE_BITS of type_regs contains a value
+ * from enum decode_type, this indicates which of the decode_* structs
+ * the entry contains. The value DECODE_TYPE_END indicates the end of the
+ * table.
+ *
+ * When the table is parsed, each entry is checked in turn to see if it
+ * matches the instruction to be decoded using the test:
+ *
+ * (insn & mask) == value
+ *
+ * If no match is found before the end of the table is reached then decoding
+ * fails with INSN_REJECTED.
+ *
+ * When a match is found, decode_regs() is called to validate and modify each
+ * of the registers encoded in the instruction; the data it uses to do this
+ * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
+ * to fail with INSN_REJECTED.
+ *
+ * Once the instruction has passed the above tests, further processing
+ * depends on the type of the table entry's decode struct.
+ *
+ */
+int __kprobes
+kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *table, bool thumb)
+{
+ const struct decode_header *h = (struct decode_header *)table;
+ const struct decode_header *next;
+ bool matched = false;
+
+ insn = prepare_emulated_insn(insn, asi, thumb);
+
+ for (;; h = next) {
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+ u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
+
+ if (type == DECODE_TYPE_END)
+ return INSN_REJECTED;
+
+ next = (struct decode_header *)
+ ((uintptr_t)h + decode_struct_sizes[type]);
+
+ if (!matched && (insn & h->mask.bits) != h->value.bits)
+ continue;
+
+ if (!decode_regs(&insn, regs))
+ return INSN_REJECTED;
+
+ switch (type) {
+
+ case DECODE_TYPE_TABLE: {
+ struct decode_table *d = (struct decode_table *)h;
+ next = (struct decode_header *)d->table.table;
+ break;
+ }
+
+ case DECODE_TYPE_CUSTOM: {
+ struct decode_custom *d = (struct decode_custom *)h;
+ return (*d->decoder.decoder)(insn, asi);
+ }
+
+ case DECODE_TYPE_SIMULATE: {
+ struct decode_simulate *d = (struct decode_simulate *)h;
+ asi->insn_handler = d->handler.handler;
+ return INSN_GOOD_NO_SLOT;
+ }
+
+ case DECODE_TYPE_EMULATE: {
+ struct decode_emulate *d = (struct decode_emulate *)h;
+ asi->insn_handler = d->handler.handler;
+ set_emulated_insn(insn, asi, thumb);
+ return INSN_GOOD;
+ }
+
+ case DECODE_TYPE_OR:
+ matched = true;
+ break;
+
+ case DECODE_TYPE_REJECT:
+ default:
+ return INSN_REJECTED;
+ }
+ }
+ }
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
deleted file mode 100644
index 15eeff6aea0e..000000000000
--- a/arch/arm/kernel/kprobes-decode.c
+++ /dev/null
@@ -1,1670 +0,0 @@
-/*
- * arch/arm/kernel/kprobes-decode.c
- *
- * Copyright (C) 2006, 2007 Motorola 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.
- */
-
-/*
- * We do not have hardware single-stepping on ARM, This
- * effort is further complicated by the ARM not having a
- * "next PC" register. Instructions that change the PC
- * can't be safely single-stepped in a MP environment, so
- * we have a lot of work to do:
- *
- * In the prepare phase:
- * *) If it is an instruction that does anything
- * with the CPU mode, we reject it for a kprobe.
- * (This is out of laziness rather than need. The
- * instructions could be simulated.)
- *
- * *) Otherwise, decode the instruction rewriting its
- * registers to take fixed, ordered registers and
- * setting a handler for it to run the instruction.
- *
- * In the execution phase by an instruction's handler:
- *
- * *) If the PC is written to by the instruction, the
- * instruction must be fully simulated in software.
- *
- * *) Otherwise, a modified form of the instruction is
- * directly executed. Its handler calls the
- * instruction in insn[0]. In insn[1] is a
- * "mov pc, lr" to return.
- *
- * Before calling, load up the reordered registers
- * from the original instruction's registers. If one
- * of the original input registers is the PC, compute
- * and adjust the appropriate input register.
- *
- * After call completes, copy the output registers to
- * the original instruction's original registers.
- *
- * We don't use a real breakpoint instruction since that
- * would have us in the kernel go from SVC mode to SVC
- * mode losing the link register. Instead we use an
- * undefined instruction. To simplify processing, the
- * undefined instruction used for kprobes must be reserved
- * exclusively for kprobes use.
- *
- * TODO: ifdef out some instruction decoding based on architecture.
- */
-
-#include <linux/kernel.h>
-#include <linux/kprobes.h>
-
-#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
-
-#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
-
-#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
-
-/*
- * Test if load/store instructions writeback the address register.
- * if P (bit 24) == 0 or W (bit 21) == 1
- */
-#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
-
-#define PSR_fs (PSR_f|PSR_s)
-
-#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */
-
-typedef long (insn_0arg_fn_t)(void);
-typedef long (insn_1arg_fn_t)(long);
-typedef long (insn_2arg_fn_t)(long, long);
-typedef long (insn_3arg_fn_t)(long, long, long);
-typedef long (insn_4arg_fn_t)(long, long, long, long);
-typedef long long (insn_llret_0arg_fn_t)(void);
-typedef long long (insn_llret_3arg_fn_t)(long, long, long);
-typedef long long (insn_llret_4arg_fn_t)(long, long, long, long);
-
-union reg_pair {
- long long dr;
-#ifdef __LITTLE_ENDIAN
- struct { long r0, r1; };
-#else
- struct { long r1, r0; };
-#endif
-};
-
-/*
- * For STR and STM instructions, an ARM core may choose to use either
- * a +8 or a +12 displacement from the current instruction's address.
- * Whichever value is chosen for a given core, it must be the same for
- * both instructions and may not change. This function measures it.
- */
-
-static int str_pc_offset;
-
-static void __init find_str_pc_offset(void)
-{
- int addr, scratch, ret;
-
- __asm__ (
- "sub %[ret], pc, #4 \n\t"
- "str pc, %[addr] \n\t"
- "ldr %[scr], %[addr] \n\t"
- "sub %[ret], %[scr], %[ret] \n\t"
- : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
-
- str_pc_offset = ret;
-}
-
-/*
- * The insnslot_?arg_r[w]flags() functions below are to keep the
- * msr -> *fn -> mrs instruction sequences indivisible so that
- * the state of the CPSR flags aren't inadvertently modified
- * just before or just after the call.
- */
-
-static inline long __kprobes
-insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn)
-{
- register long ret asm("r0");
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- : "=r" (ret)
- : [cpsr] "r" (cpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- return ret;
-}
-
-static inline long long __kprobes
-insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn)
-{
- register long ret0 asm("r0");
- register long ret1 asm("r1");
- union reg_pair fnr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- : "=r" (ret0), "=r" (ret1)
- : [cpsr] "r" (cpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- fnr.r0 = ret0;
- fnr.r1 = ret1;
- return fnr.dr;
-}
-
-static inline long __kprobes
-insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long ret asm("r0");
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- : "=r" (ret)
- : "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- return ret;
-}
-
-static inline long __kprobes
-insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long ret asm("r0");
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- : "=r" (ret)
- : "0" (rr0), "r" (rr1),
- [cpsr] "r" (cpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- return ret;
-}
-
-static inline long __kprobes
-insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long rr2 asm("r2") = r2;
- register long ret asm("r0");
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- : "=r" (ret)
- : "0" (rr0), "r" (rr1), "r" (rr2),
- [cpsr] "r" (cpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- return ret;
-}
-
-static inline long long __kprobes
-insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr,
- insn_llret_3arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long rr2 asm("r2") = r2;
- register long ret0 asm("r0");
- register long ret1 asm("r1");
- union reg_pair fnr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- : "=r" (ret0), "=r" (ret1)
- : "0" (rr0), "r" (rr1), "r" (rr2),
- [cpsr] "r" (cpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- fnr.r0 = ret0;
- fnr.r1 = ret1;
- return fnr.dr;
-}
-
-static inline long __kprobes
-insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr,
- insn_4arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long rr2 asm("r2") = r2;
- register long rr3 asm("r3") = r3;
- register long ret asm("r0");
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- : "=r" (ret)
- : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
- [cpsr] "r" (cpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- return ret;
-}
-
-static inline long __kprobes
-insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long ret asm("r0");
- long oldcpsr = *cpsr;
- long newcpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[oldcpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- "mrs %[newcpsr], cpsr \n\t"
- : "=r" (ret), [newcpsr] "=r" (newcpsr)
- : "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
- return ret;
-}
-
-static inline long __kprobes
-insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long ret asm("r0");
- long oldcpsr = *cpsr;
- long newcpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[oldcpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- "mrs %[newcpsr], cpsr \n\t"
- : "=r" (ret), [newcpsr] "=r" (newcpsr)
- : "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
- return ret;
-}
-
-static inline long __kprobes
-insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr,
- insn_3arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long rr2 asm("r2") = r2;
- register long ret asm("r0");
- long oldcpsr = *cpsr;
- long newcpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[oldcpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- "mrs %[newcpsr], cpsr \n\t"
- : "=r" (ret), [newcpsr] "=r" (newcpsr)
- : "0" (rr0), "r" (rr1), "r" (rr2),
- [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
- return ret;
-}
-
-static inline long __kprobes
-insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
- insn_4arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long rr2 asm("r2") = r2;
- register long rr3 asm("r3") = r3;
- register long ret asm("r0");
- long oldcpsr = *cpsr;
- long newcpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[oldcpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- "mrs %[newcpsr], cpsr \n\t"
- : "=r" (ret), [newcpsr] "=r" (newcpsr)
- : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
- [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
- return ret;
-}
-
-static inline long long __kprobes
-insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
- insn_llret_4arg_fn_t *fn)
-{
- register long rr0 asm("r0") = r0;
- register long rr1 asm("r1") = r1;
- register long rr2 asm("r2") = r2;
- register long rr3 asm("r3") = r3;
- register long ret0 asm("r0");
- register long ret1 asm("r1");
- long oldcpsr = *cpsr;
- long newcpsr;
- union reg_pair fnr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[oldcpsr] \n\t"
- "mov lr, pc \n\t"
- "mov pc, %[fn] \n\t"
- "mrs %[newcpsr], cpsr \n\t"
- : "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr)
- : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
- [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
- : "lr", "cc"
- );
- *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
- fnr.r0 = ret0;
- fnr.r1 = ret1;
- return fnr.dr;
-}
-
-/*
- * To avoid the complications of mimicing single-stepping on a
- * processor without a Next-PC or a single-step mode, and to
- * avoid having to deal with the side-effects of boosting, we
- * simulate or emulate (almost) all ARM instructions.
- *
- * "Simulation" is where the instruction's behavior is duplicated in
- * C code. "Emulation" is where the original instruction is rewritten
- * and executed, often by altering its registers.
- *
- * By having all behavior of the kprobe'd instruction completed before
- * returning from the kprobe_handler(), all locks (scheduler and
- * interrupt) can safely be released. There is no need for secondary
- * breakpoints, no race with MP or preemptable kernels, nor having to
- * clean up resources counts at a later time impacting overall system
- * performance. By rewriting the instruction, only the minimum registers
- * need to be loaded and saved back optimizing performance.
- *
- * Calling the insnslot_*_rwflags version of a function doesn't hurt
- * anything even when the CPSR flags aren't updated by the
- * instruction. It's just a little slower in return for saving
- * a little space by not having a duplicate function that doesn't
- * update the flags. (The same optimization can be said for
- * instructions that do or don't perform register writeback)
- * Also, instructions can either read the flags, only write the
- * flags, or read and write the flags. To save combinations
- * rather than for sheer performance, flag functions just assume
- * read and write of flags.
- */
-
-static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- long iaddr = (long)p->addr;
- int disp = branch_displacement(insn);
-
- if (insn & (1 << 24))
- regs->ARM_lr = iaddr + 4;
-
- regs->ARM_pc = iaddr + 8 + disp;
-}
-
-static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- long iaddr = (long)p->addr;
- int disp = branch_displacement(insn);
-
- regs->ARM_lr = iaddr + 4;
- regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
- regs->ARM_cpsr |= PSR_T_BIT;
-}
-
-static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rm = insn & 0xf;
- long rmv = regs->uregs[rm];
-
- if (insn & (1 << 5))
- regs->ARM_lr = (long)p->addr + 4;
-
- regs->ARM_pc = rmv & ~0x1;
- regs->ARM_cpsr &= ~PSR_T_BIT;
- if (rmv & 0x1)
- regs->ARM_cpsr |= PSR_T_BIT;
-}
-
-static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- unsigned long mask = 0xf8ff03df; /* Mask out execution state */
- regs->uregs[rd] = regs->ARM_cpsr & mask;
-}
-
-static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rn = (insn >> 16) & 0xf;
- int lbit = insn & (1 << 20);
- int wbit = insn & (1 << 21);
- int ubit = insn & (1 << 23);
- int pbit = insn & (1 << 24);
- long *addr = (long *)regs->uregs[rn];
- int reg_bit_vector;
- int reg_count;
-
- reg_count = 0;
- reg_bit_vector = insn & 0xffff;
- while (reg_bit_vector) {
- reg_bit_vector &= (reg_bit_vector - 1);
- ++reg_count;
- }
-
- if (!ubit)
- addr -= reg_count;
- addr += (!pbit == !ubit);
-
- reg_bit_vector = insn & 0xffff;
- while (reg_bit_vector) {
- int reg = __ffs(reg_bit_vector);
- reg_bit_vector &= (reg_bit_vector - 1);
- if (lbit)
- regs->uregs[reg] = *addr++;
- else
- *addr++ = regs->uregs[reg];
- }
-
- if (wbit) {
- if (!ubit)
- addr -= reg_count;
- addr -= (!pbit == !ubit);
- regs->uregs[rn] = (long)addr;
- }
-}
-
-static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_pc = (long)p->addr + str_pc_offset;
- simulate_ldm1stm1(p, regs);
- regs->ARM_pc = (long)p->addr + 4;
-}
-
-static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
-{
- regs->uregs[12] = regs->uregs[13];
-}
-
-static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
-{
- insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- long ppc = (long)p->addr + 8;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf; /* rm may be invalid, don't care. */
- long rmv = (rm == 15) ? ppc : regs->uregs[rm];
- long rnv = (rn == 15) ? ppc : regs->uregs[rn];
-
- /* Not following the C calling convention here, so need asm(). */
- __asm__ __volatile__ (
- "ldr r0, %[rn] \n\t"
- "ldr r1, %[rm] \n\t"
- "msr cpsr_fs, %[cpsr]\n\t"
- "mov lr, pc \n\t"
- "mov pc, %[i_fn] \n\t"
- "str r0, %[rn] \n\t" /* in case of writeback */
- "str r2, %[rd0] \n\t"
- "str r3, %[rd1] \n\t"
- : [rn] "+m" (rnv),
- [rd0] "=m" (regs->uregs[rd]),
- [rd1] "=m" (regs->uregs[rd+1])
- : [rm] "m" (rmv),
- [cpsr] "r" (regs->ARM_cpsr),
- [i_fn] "r" (i_fn)
- : "r0", "r1", "r2", "r3", "lr", "cc"
- );
- if (is_writeback(insn))
- regs->uregs[rn] = rnv;
-}
-
-static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
-{
- insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- long ppc = (long)p->addr + 8;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
- long rnv = (rn == 15) ? ppc : regs->uregs[rn];
- /* rm/rmv may be invalid, don't care. */
- long rmv = (rm == 15) ? ppc : regs->uregs[rm];
- long rnv_wb;
-
- rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
- regs->uregs[rd+1],
- regs->ARM_cpsr, i_fn);
- if (is_writeback(insn))
- regs->uregs[rn] = rnv_wb;
-}
-
-static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
-{
- insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- long ppc = (long)p->addr + 8;
- union reg_pair fnr;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
- long rdv;
- long rnv = (rn == 15) ? ppc : regs->uregs[rn];
- long rmv = (rm == 15) ? ppc : regs->uregs[rm];
- long cpsr = regs->ARM_cpsr;
-
- fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
- if (rn != 15)
- regs->uregs[rn] = fnr.r0; /* Save Rn in case of writeback. */
- rdv = fnr.r1;
-
- if (rd == 15) {
-#if __LINUX_ARM_ARCH__ >= 5
- cpsr &= ~PSR_T_BIT;
- if (rdv & 0x1)
- cpsr |= PSR_T_BIT;
- regs->ARM_cpsr = cpsr;
- rdv &= ~0x1;
-#else
- rdv &= ~0x2;
-#endif
- }
- regs->uregs[rd] = rdv;
-}
-
-static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
-{
- insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- long iaddr = (long)p->addr;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
- long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
- long rnv = (rn == 15) ? iaddr + 8 : regs->uregs[rn];
- long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */
- long rnv_wb;
-
- rnv_wb = insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
- if (rn != 15)
- regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */
-}
-
-static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
-{
- insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rm = insn & 0xf;
- long rmv = regs->uregs[rm];
-
- /* Writes Q flag */
- regs->uregs[rd] = insnslot_1arg_rwflags(rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)
-{
- insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
- long rnv = regs->uregs[rn];
- long rmv = regs->uregs[rm];
-
- /* Reads GE bits */
- regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
-{
- insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
-
- insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)
-{
-}
-
-static void __kprobes
-emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)
-{
- insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- long rdv = regs->uregs[rd];
-
- regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)
-{
- insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rn = insn & 0xf;
- long rdv = regs->uregs[rd];
- long rnv = regs->uregs[rn];
-
- regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
-{
- insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rm = insn & 0xf;
- long rmv = regs->uregs[rm];
-
- regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
- long rnv = regs->uregs[rn];
- long rmv = regs->uregs[rm];
-
- regs->uregs[rd] =
- insnslot_2arg_rwflags(rnv, rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 16) & 0xf;
- int rn = (insn >> 12) & 0xf;
- int rs = (insn >> 8) & 0xf;
- int rm = insn & 0xf;
- long rnv = regs->uregs[rn];
- long rsv = regs->uregs[rs];
- long rmv = regs->uregs[rm];
-
- regs->uregs[rd] =
- insnslot_3arg_rwflags(rnv, rsv, rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 16) & 0xf;
- int rs = (insn >> 8) & 0xf;
- int rm = insn & 0xf;
- long rsv = regs->uregs[rs];
- long rmv = regs->uregs[rm];
-
- regs->uregs[rd] =
- insnslot_2arg_rwflags(rsv, rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- union reg_pair fnr;
- int rdhi = (insn >> 16) & 0xf;
- int rdlo = (insn >> 12) & 0xf;
- int rs = (insn >> 8) & 0xf;
- int rm = insn & 0xf;
- long rsv = regs->uregs[rs];
- long rmv = regs->uregs[rm];
-
- fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],
- regs->uregs[rdlo], rsv, rmv,
- &regs->ARM_cpsr, i_fn);
- regs->uregs[rdhi] = fnr.r0;
- regs->uregs[rdlo] = fnr.r1;
-}
-
-static void __kprobes
-emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
-
- regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
-
- regs->uregs[rd] = insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)
-{
- insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- int rn = (insn >> 16) & 0xf;
- long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
-
- insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- long ppc = (long)p->addr + 8;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */
- int rs = (insn >> 8) & 0xf; /* invalid, don't care. */
- int rm = insn & 0xf;
- long rnv = (rn == 15) ? ppc : regs->uregs[rn];
- long rmv = (rm == 15) ? ppc : regs->uregs[rm];
- long rsv = regs->uregs[rs];
-
- regs->uregs[rd] =
- insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- long ppc = (long)p->addr + 8;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */
- int rs = (insn >> 8) & 0xf; /* invalid, don't care. */
- int rm = insn & 0xf;
- long rnv = (rn == 15) ? ppc : regs->uregs[rn];
- long rmv = (rm == 15) ? ppc : regs->uregs[rm];
- long rsv = regs->uregs[rs];
-
- regs->uregs[rd] =
- insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)
-{
- insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
- kprobe_opcode_t insn = p->opcode;
- long ppc = (long)p->addr + 8;
- int rn = (insn >> 16) & 0xf;
- int rs = (insn >> 8) & 0xf; /* rs/rsv may be invalid, don't care. */
- int rm = insn & 0xf;
- long rnv = (rn == 15) ? ppc : regs->uregs[rn];
- long rmv = (rm == 15) ? ppc : regs->uregs[rm];
- long rsv = regs->uregs[rs];
-
- insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))
- : (~insn & (1 << 22));
-
- if (is_writeback(insn) && is_r15(insn, 16))
- return INSN_REJECTED; /* Writeback to PC */
-
- insn &= 0xfff00fff;
- insn |= 0x00001000; /* Rn = r0, Rd = r1 */
- if (not_imm) {
- insn &= ~0xf;
- insn |= 2; /* Rm = r2 */
- }
- asi->insn[0] = insn;
- asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr : emulate_str;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
-
- insn &= 0xffff0fff; /* Rd = r0 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rd12_modify;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,
- struct arch_specific_insn *asi)
-{
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
-
- insn &= 0xffff0ff0; /* Rd = r0 */
- insn |= 0x00000001; /* Rn = r1 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rd12rn0_modify;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
-
- insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rd12rm0;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
- struct arch_specific_insn *asi)
-{
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
-
- insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */
- insn |= 0x00000001; /* Rm = r1 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rd12rn16rm0_rwflags;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
- struct arch_specific_insn *asi)
-{
- if (is_r15(insn, 16))
- return INSN_REJECTED; /* Rd is PC */
-
- insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */
- insn |= 0x00000001; /* Rm = r1 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rd16rs8rm0_rwflags;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
- struct arch_specific_insn *asi)
-{
- if (is_r15(insn, 16))
- return INSN_REJECTED; /* Rd is PC */
-
- insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */
- insn |= 0x00000102; /* Rs = r1, Rm = r2 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
- struct arch_specific_insn *asi)
-{
- if (is_r15(insn, 16) || is_r15(insn, 12))
- return INSN_REJECTED; /* RdHi or RdLo is PC */
-
- insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */
- insn |= 0x00001203; /* Rs = r2, Rm = r3 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;
- return INSN_GOOD;
-}
-
-/*
- * For the instruction masking and comparisons in all the "space_*"
- * functions below, Do _not_ rearrange the order of tests unless
- * you're very, very sure of what you are doing. For the sake of
- * efficiency, the masks for some tests sometimes assume other test
- * have been done prior to them so the number of patterns to test
- * for an instruction set can be as broad as possible to reduce the
- * number of tests needed.
- */
-
-static enum kprobe_insn __kprobes
-space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */
- /* PLDI : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */
- /* PLDW : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */
- /* PLD : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */
- if ((insn & 0xfe300000) == 0xf4100000) {
- asi->insn_handler = emulate_nop;
- return INSN_GOOD_NO_SLOT;
- }
-
- /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
- if ((insn & 0xfe000000) == 0xfa000000) {
- asi->insn_handler = simulate_blx1;
- return INSN_GOOD_NO_SLOT;
- }
-
- /* CPS : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
- /* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
-
- /* SRS : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
- /* RFE : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
-
- /* Coprocessor instructions... */
- /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
- /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
- /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
- /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
- /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
- /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
- /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-
- return INSN_REJECTED;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
- if ((insn & 0x0f900010) == 0x01000000) {
-
- /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
- if ((insn & 0x0ff000f0) == 0x01000000) {
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
- asi->insn_handler = simulate_mrs;
- return INSN_GOOD_NO_SLOT;
- }
-
- /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
- if ((insn & 0x0ff00090) == 0x01400080)
- return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
- asi);
-
- /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
- /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
- if ((insn & 0x0ff000b0) == 0x012000a0 ||
- (insn & 0x0ff00090) == 0x01600080)
- return prep_emulate_rd16rs8rm0_wflags(insn, asi);
-
- /* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
- /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
- if ((insn & 0x0ff00090) == 0x01000080 ||
- (insn & 0x0ff000b0) == 0x01200080)
- return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-
- /* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
- /* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
- /* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
-
- /* Other instruction encodings aren't yet defined */
- return INSN_REJECTED;
- }
-
- /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
- else if ((insn & 0x0f900090) == 0x01000010) {
-
- /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
- /* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
- if ((insn & 0x0ff000d0) == 0x01200010) {
- if ((insn & 0x0ff000ff) == 0x0120003f)
- return INSN_REJECTED; /* BLX pc */
- asi->insn_handler = simulate_blx2bx;
- return INSN_GOOD_NO_SLOT;
- }
-
- /* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
- if ((insn & 0x0ff000f0) == 0x01600010)
- return prep_emulate_rd12rm0(insn, asi);
-
- /* QADD : cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx :Q */
- /* QSUB : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
- /* QDADD : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
- /* QDSUB : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
- if ((insn & 0x0f9000f0) == 0x01000050)
- return prep_emulate_rd12rn16rm0_wflags(insn, asi);
-
- /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
- /* SMC : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
-
- /* Other instruction encodings aren't yet defined */
- return INSN_REJECTED;
- }
-
- /* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
- else if ((insn & 0x0f0000f0) == 0x00000090) {
-
- /* MUL : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx : */
- /* MULS : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
- /* MLA : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx : */
- /* MLAS : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
- /* UMAAL : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx : */
- /* undef : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx : */
- /* MLS : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx : */
- /* undef : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx : */
- /* UMULL : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx : */
- /* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
- /* UMLAL : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx : */
- /* UMLALS : cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx :cc */
- /* SMULL : cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx : */
- /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
- /* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */
- /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
- if ((insn & 0x00d00000) == 0x00500000)
- return INSN_REJECTED;
- else if ((insn & 0x00e00000) == 0x00000000)
- return prep_emulate_rd16rs8rm0_wflags(insn, asi);
- else if ((insn & 0x00a00000) == 0x00200000)
- return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
- else
- return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
- asi);
- }
-
- /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
- else if ((insn & 0x0e000090) == 0x00000090) {
-
- /* SWP : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
- /* SWPB : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
- /* ??? : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
- /* ??? : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
- /* ??? : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
- /* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
- /* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
- /* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
- /* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
- /* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
- /* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
- /* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
- /* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */
-
- /* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
- /* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
- /* LDRH : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
- /* STRH : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
- /* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
- /* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
- if ((insn & 0x0f0000f0) == 0x01000090) {
- if ((insn & 0x0fb000f0) == 0x01000090) {
- /* SWP/SWPB */
- return prep_emulate_rd12rn16rm0_wflags(insn,
- asi);
- } else {
- /* STREX/LDREX variants and unallocaed space */
- return INSN_REJECTED;
- }
-
- } else if ((insn & 0x0e1000d0) == 0x00000d0) {
- /* STRD/LDRD */
- if ((insn & 0x0000e000) == 0x0000e000)
- return INSN_REJECTED; /* Rd is LR or PC */
- if (is_writeback(insn) && is_r15(insn, 16))
- return INSN_REJECTED; /* Writeback to PC */
-
- insn &= 0xfff00fff;
- insn |= 0x00002000; /* Rn = r0, Rd = r2 */
- if (!(insn & (1 << 22))) {
- /* Register index */
- insn &= ~0xf;
- insn |= 1; /* Rm = r1 */
- }
- asi->insn[0] = insn;
- asi->insn_handler =
- (insn & (1 << 5)) ? emulate_strd : emulate_ldrd;
- return INSN_GOOD;
- }
-
- /* LDRH/STRH/LDRSB/LDRSH */
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
- return prep_emulate_ldr_str(insn, asi);
- }
-
- /* cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx */
-
- /*
- * ALU op with S bit and Rd == 15 :
- * cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
- */
- if ((insn & 0x0e10f000) == 0x0010f000)
- return INSN_REJECTED;
-
- /*
- * "mov ip, sp" is the most common kprobe'd instruction by far.
- * Check and optimize for it explicitly.
- */
- if (insn == 0xe1a0c00d) {
- asi->insn_handler = simulate_mov_ipsp;
- return INSN_GOOD_NO_SLOT;
- }
-
- /*
- * Data processing: Immediate-shift / Register-shift
- * ALU op : cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx
- * CPY : cccc 0001 1010 xxxx xxxx 0000 0000 xxxx
- * MOV : cccc 0001 101x xxxx xxxx xxxx xxxx xxxx
- * *S (bit 20) updates condition codes
- * ADC/SBC/RSC reads the C flag
- */
- insn &= 0xfff00ff0; /* Rn = r0, Rd = r0 */
- insn |= 0x00000001; /* Rm = r1 */
- if (insn & 0x010) {
- insn &= 0xfffff0ff; /* register shift */
- insn |= 0x00000200; /* Rs = r2 */
- }
- asi->insn[0] = insn;
-
- if ((insn & 0x0f900000) == 0x01100000) {
- /*
- * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
- * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
- * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
- * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
- */
- asi->insn_handler = emulate_alu_tests;
- } else {
- /* ALU ops which write to Rd */
- asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */
- emulate_alu_rwflags : emulate_alu_rflags;
- }
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* MOVW : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
- /* MOVT : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
- if ((insn & 0x0fb00000) == 0x03000000)
- return prep_emulate_rd12_modify(insn, asi);
-
- /* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
- if ((insn & 0x0fff0000) == 0x03200000) {
- unsigned op2 = insn & 0x000000ff;
- if (op2 == 0x01 || op2 == 0x04) {
- /* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
- /* SEV : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_none;
- return INSN_GOOD;
- } else if (op2 <= 0x03) {
- /* NOP : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
- /* WFE : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
- /* WFI : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
- /*
- * We make WFE and WFI true NOPs to avoid stalls due
- * to missing events whilst processing the probe.
- */
- asi->insn_handler = emulate_nop;
- return INSN_GOOD_NO_SLOT;
- }
- /* For DBG and unallocated hints it's safest to reject them */
- return INSN_REJECTED;
- }
-
- /*
- * MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
- * ALU op with S bit and Rd == 15 :
- * cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
- */
- if ((insn & 0x0fb00000) == 0x03200000 || /* MSR */
- (insn & 0x0e10f000) == 0x0210f000) /* ALU s-bit, R15 */
- return INSN_REJECTED;
-
- /*
- * Data processing: 32-bit Immediate
- * ALU op : cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
- * MOV : cccc 0011 101x xxxx xxxx xxxx xxxx xxxx
- * *S (bit 20) updates condition codes
- * ADC/SBC/RSC reads the C flag
- */
- insn &= 0xfff00fff; /* Rn = r0 and Rd = r0 */
- asi->insn[0] = insn;
-
- if ((insn & 0x0f900000) == 0x03100000) {
- /*
- * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx
- * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx
- * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx
- * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx
- */
- asi->insn_handler = emulate_alu_tests_imm;
- } else {
- /* ALU ops which write to Rd */
- asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */
- emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
- }
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
- if ((insn & 0x0ff000f0) == 0x068000b0) {
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
- insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */
- insn |= 0x00000001; /* Rm = r1 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_sel;
- return INSN_GOOD;
- }
-
- /* SSAT : cccc 0110 101x xxxx xxxx xxxx xx01 xxxx :Q */
- /* USAT : cccc 0110 111x xxxx xxxx xxxx xx01 xxxx :Q */
- /* SSAT16 : cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx :Q */
- /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
- if ((insn & 0x0fa00030) == 0x06a00010 ||
- (insn & 0x0fb000f0) == 0x06a00030) {
- if (is_r15(insn, 12))
- return INSN_REJECTED; /* Rd is PC */
- insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_sat;
- return INSN_GOOD;
- }
-
- /* REV : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
- /* REV16 : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
- /* RBIT : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
- /* REVSH : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
- if ((insn & 0x0ff00070) == 0x06b00030 ||
- (insn & 0x0ff00070) == 0x06f00030)
- return prep_emulate_rd12rm0(insn, asi);
-
- /* ??? : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx : */
- /* SADD16 : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
- /* SADDSUBX : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
- /* SSUBADDX : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
- /* SSUB16 : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
- /* SADD8 : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
- /* ??? : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx : */
- /* ??? : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx : */
- /* SSUB8 : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
- /* QADD16 : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx : */
- /* QADDSUBX : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx : */
- /* QSUBADDX : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx : */
- /* QSUB16 : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx : */
- /* QADD8 : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx : */
- /* ??? : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx : */
- /* ??? : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx : */
- /* QSUB8 : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx : */
- /* SHADD16 : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx : */
- /* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx : */
- /* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx : */
- /* SHSUB16 : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx : */
- /* SHADD8 : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx : */
- /* ??? : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx : */
- /* ??? : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx : */
- /* SHSUB8 : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx : */
- /* ??? : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx : */
- /* UADD16 : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
- /* UADDSUBX : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
- /* USUBADDX : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
- /* USUB16 : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
- /* UADD8 : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
- /* ??? : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx : */
- /* ??? : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx : */
- /* USUB8 : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
- /* UQADD16 : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx : */
- /* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx : */
- /* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx : */
- /* UQSUB16 : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx : */
- /* UQADD8 : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx : */
- /* ??? : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx : */
- /* ??? : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx : */
- /* UQSUB8 : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx : */
- /* UHADD16 : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx : */
- /* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx : */
- /* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx : */
- /* UHSUB16 : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx : */
- /* UHADD8 : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx : */
- /* ??? : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx : */
- /* ??? : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx : */
- /* UHSUB8 : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx : */
- if ((insn & 0x0f800010) == 0x06000010) {
- if ((insn & 0x00300000) == 0x00000000 ||
- (insn & 0x000000e0) == 0x000000a0 ||
- (insn & 0x000000e0) == 0x000000c0)
- return INSN_REJECTED; /* Unallocated space */
- return prep_emulate_rd12rn16rm0_wflags(insn, asi);
- }
-
- /* PKHBT : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx : */
- /* PKHTB : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx : */
- if ((insn & 0x0ff00030) == 0x06800010)
- return prep_emulate_rd12rn16rm0_wflags(insn, asi);
-
- /* SXTAB16 : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx : */
- /* SXTB16 : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx : */
- /* ??? : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx : */
- /* SXTAB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */
- /* SXTB : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx : */
- /* SXTAH : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx : */
- /* SXTH : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx : */
- /* UXTAB16 : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx : */
- /* UXTB16 : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx : */
- /* ??? : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx : */
- /* UXTAB : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx : */
- /* UXTB : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx : */
- /* UXTAH : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx : */
- /* UXTH : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx : */
- if ((insn & 0x0f8000f0) == 0x06800070) {
- if ((insn & 0x00300000) == 0x00100000)
- return INSN_REJECTED; /* Unallocated space */
-
- if ((insn & 0x000f0000) == 0x000f0000)
- return prep_emulate_rd12rm0(insn, asi);
- else
- return prep_emulate_rd12rn16rm0_wflags(insn, asi);
- }
-
- /* Other instruction encodings aren't yet defined */
- return INSN_REJECTED;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* Undef : cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
- if ((insn & 0x0ff000f0) == 0x03f000f0)
- return INSN_REJECTED;
-
- /* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
- /* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
- if ((insn & 0x0ff00090) == 0x07400010)
- return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
-
- /* SMLAD : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
- /* SMUAD : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
- /* SMLSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
- /* SMUSD : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx : */
- /* SMMLA : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx : */
- /* SMMUL : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx : */
- /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx : */
- /* USAD8 : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx : */
- if ((insn & 0x0ff00090) == 0x07000010 ||
- (insn & 0x0ff000d0) == 0x07500010 ||
- (insn & 0x0ff000f0) == 0x07800010) {
-
- if ((insn & 0x0000f000) == 0x0000f000)
- return prep_emulate_rd16rs8rm0_wflags(insn, asi);
- else
- return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
- }
-
- /* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */
- if ((insn & 0x0ff000d0) == 0x075000d0)
- return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-
- /* SBFX : cccc 0111 101x xxxx xxxx xxxx x101 xxxx : */
- /* UBFX : cccc 0111 111x xxxx xxxx xxxx x101 xxxx : */
- if ((insn & 0x0fa00070) == 0x07a00050)
- return prep_emulate_rd12rm0(insn, asi);
-
- /* BFI : cccc 0111 110x xxxx xxxx xxxx x001 xxxx : */
- /* BFC : cccc 0111 110x xxxx xxxx xxxx x001 1111 : */
- if ((insn & 0x0fe00070) == 0x07c00010) {
-
- if ((insn & 0x0000000f) == 0x0000000f)
- return prep_emulate_rd12_modify(insn, asi);
- else
- return prep_emulate_rd12rn0_modify(insn, asi);
- }
-
- return INSN_REJECTED;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* LDR : cccc 01xx x0x1 xxxx xxxx xxxx xxxx xxxx */
- /* LDRB : cccc 01xx x1x1 xxxx xxxx xxxx xxxx xxxx */
- /* LDRBT : cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
- /* LDRT : cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
- /* STR : cccc 01xx x0x0 xxxx xxxx xxxx xxxx xxxx */
- /* STRB : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
- /* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
- /* STRT : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
-
- if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12))
- return INSN_REJECTED; /* LDRB into PC */
-
- return prep_emulate_ldr_str(insn, asi);
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* LDM(2) : cccc 100x x101 xxxx 0xxx xxxx xxxx xxxx */
- /* LDM(3) : cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
- if ((insn & 0x0e708000) == 0x85000000 ||
- (insn & 0x0e508000) == 0x85010000)
- return INSN_REJECTED;
-
- /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
- /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
- asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
- simulate_stm1_pc : simulate_ldm1stm1;
- return INSN_GOOD_NO_SLOT;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* B : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
- /* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
- asi->insn_handler = simulate_bbl;
- return INSN_GOOD_NO_SLOT;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /* Coprocessor instructions... */
- /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
- /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
- /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
- /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
- /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
- /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
- /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-
- /* SVC : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
-
- return INSN_REJECTED;
-}
-
-static unsigned long __kprobes __check_eq(unsigned long cpsr)
-{
- return cpsr & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_ne(unsigned long cpsr)
-{
- return (~cpsr) & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_cs(unsigned long cpsr)
-{
- return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_cc(unsigned long cpsr)
-{
- return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_mi(unsigned long cpsr)
-{
- return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_pl(unsigned long cpsr)
-{
- return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_vs(unsigned long cpsr)
-{
- return cpsr & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_vc(unsigned long cpsr)
-{
- return (~cpsr) & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_hi(unsigned long cpsr)
-{
- cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
- return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ls(unsigned long cpsr)
-{
- cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
- return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ge(unsigned long cpsr)
-{
- cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_lt(unsigned long cpsr)
-{
- cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_gt(unsigned long cpsr)
-{
- unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
- return (~temp) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_le(unsigned long cpsr)
-{
- unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
- return temp & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_al(unsigned long cpsr)
-{
- return true;
-}
-
-static kprobe_check_cc * const condition_checks[16] = {
- &__check_eq, &__check_ne, &__check_cs, &__check_cc,
- &__check_mi, &__check_pl, &__check_vs, &__check_vc,
- &__check_hi, &__check_ls, &__check_ge, &__check_lt,
- &__check_gt, &__check_le, &__check_al, &__check_al
-};
-
-/* Return:
- * INSN_REJECTED If instruction is one not allowed to kprobe,
- * INSN_GOOD If instruction is supported and uses instruction slot,
- * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
- *
- * For instructions we don't want to kprobe (INSN_REJECTED return result):
- * These are generally ones that modify the processor state making
- * them "hard" to simulate such as switches processor modes or
- * make accesses in alternate modes. Any of these could be simulated
- * if the work was put into it, but low return considering they
- * should also be very rare.
- */
-enum kprobe_insn __kprobes
-arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- asi->insn_check_cc = condition_checks[insn>>28];
- asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
-
- if ((insn & 0xf0000000) == 0xf0000000)
-
- return space_1111(insn, asi);
-
- else if ((insn & 0x0e000000) == 0x00000000)
-
- return space_cccc_000x(insn, asi);
-
- else if ((insn & 0x0e000000) == 0x02000000)
-
- return space_cccc_001x(insn, asi);
-
- else if ((insn & 0x0f000010) == 0x06000010)
-
- return space_cccc_0110__1(insn, asi);
-
- else if ((insn & 0x0f000010) == 0x07000010)
-
- return space_cccc_0111__1(insn, asi);
-
- else if ((insn & 0x0c000000) == 0x04000000)
-
- return space_cccc_01xx(insn, asi);
-
- else if ((insn & 0x0e000000) == 0x08000000)
-
- return space_cccc_100x(insn, asi);
-
- else if ((insn & 0x0e000000) == 0x0a000000)
-
- return space_cccc_101x(insn, asi);
-
- return space_cccc_11xx(insn, asi);
-}
-
-void __init arm_kprobe_decode_init(void)
-{
- find_str_pc_offset();
-}
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
new file mode 100644
index 000000000000..902ca59e8b11
--- /dev/null
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -0,0 +1,1462 @@
+/*
+ * arch/arm/kernel/kprobes-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/kprobes.h>
+
+#include "kprobes.h"
+
+
+/*
+ * True if current instruction is in an IT block.
+ */
+#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
+
+/*
+ * Return the condition code to check for the currently executing instruction.
+ * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
+ * in_it_block returns true.
+ */
+#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
+
+/*
+ * Return the PC value for a probe in thumb code.
+ * This is the address of the probed instruction plus 4.
+ * We subtract one because the address will have bit zero set to indicate
+ * a pointer to thumb code.
+ */
+static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
+{
+ return (unsigned long)p->addr - 1 + 4;
+}
+
+static void __kprobes
+t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
+ unsigned long rmv = regs->uregs[rm];
+ unsigned int halfwords;
+
+ if (insn & 0x10) /* TBH */
+ halfwords = ((u16 *)rnv)[rmv];
+ else /* TBB */
+ halfwords = ((u8 *)rnv)[rmv];
+
+ regs->ARM_pc = pc + 2 * halfwords;
+}
+
+static void __kprobes
+t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 8) & 0xf;
+ unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+ regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
+static void __kprobes
+t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+
+ long offset = insn & 0x7ff; /* imm11 */
+ offset += (insn & 0x003f0000) >> 5; /* imm6 */
+ offset += (insn & 0x00002000) << 4; /* J1 */
+ offset += (insn & 0x00000800) << 7; /* J2 */
+ offset -= (insn & 0x04000000) >> 7; /* Apply sign bit */
+
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ int cc = (insn >> 22) & 0xf;
+ asi->insn_check_cc = kprobe_condition_checks[cc];
+ asi->insn_handler = t32_simulate_cond_branch;
+ return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+
+ long offset = insn & 0x7ff; /* imm11 */
+ offset += (insn & 0x03ff0000) >> 5; /* imm10 */
+ offset += (insn & 0x00002000) << 9; /* J1 */
+ offset += (insn & 0x00000800) << 10; /* J2 */
+ if (insn & 0x04000000)
+ offset -= 0x00800000; /* Apply sign bit */
+ else
+ offset ^= 0x00600000; /* Invert J1 and J2 */
+
+ if (insn & (1 << 14)) {
+ /* BL or BLX */
+ regs->ARM_lr = (unsigned long)p->addr + 4;
+ if (!(insn & (1 << 12))) {
+ /* BLX so switch to ARM mode */
+ regs->ARM_cpsr &= ~PSR_T_BIT;
+ pc &= ~3;
+ }
+ }
+
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static void __kprobes
+t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long addr = thumb_probe_pc(p) & ~3;
+ int rt = (insn >> 12) & 0xf;
+ unsigned long rtv;
+
+ long offset = insn & 0xfff;
+ if (insn & 0x00800000)
+ addr += offset;
+ else
+ addr -= offset;
+
+ if (insn & 0x00400000) {
+ /* LDR */
+ rtv = *(unsigned long *)addr;
+ if (rt == 15) {
+ bx_write_pc(rtv, regs);
+ return;
+ }
+ } else if (insn & 0x00200000) {
+ /* LDRH */
+ if (insn & 0x01000000)
+ rtv = *(s16 *)addr;
+ else
+ rtv = *(u16 *)addr;
+ } else {
+ /* LDRB */
+ if (insn & 0x01000000)
+ rtv = *(s8 *)addr;
+ else
+ rtv = *(u8 *)addr;
+ }
+
+ regs->uregs[rt] = rtv;
+}
+
+static enum kprobe_insn __kprobes
+t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
+
+ /* Fixup modified instruction to have halfwords in correct order...*/
+ insn = asi->insn[0];
+ ((u16 *)asi->insn)[0] = insn >> 16;
+ ((u16 *)asi->insn)[1] = insn & 0xffff;
+
+ return ret;
+}
+
+static void __kprobes
+t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p) & ~3;
+ int rt1 = (insn >> 12) & 0xf;
+ int rt2 = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+
+ register unsigned long rt1v asm("r0") = regs->uregs[rt1];
+ register unsigned long rt2v asm("r1") = regs->uregs[rt2];
+ register unsigned long rnv asm("r2") = (rn == 15) ? pc
+ : regs->uregs[rn];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
+ : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rn != 15)
+ regs->uregs[rn] = rnv; /* Writeback base register */
+ regs->uregs[rt1] = rt1v;
+ regs->uregs[rt2] = rt2v;
+}
+
+static void __kprobes
+t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rt = (insn >> 12) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rtv asm("r0") = regs->uregs[rt];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rtv), "=r" (rnv)
+ : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rn] = rnv; /* Writeback base register */
+ if (rt == 15) /* Can't be true for a STR as they aren't allowed */
+ bx_write_pc(rtv, regs);
+ else
+ regs->uregs[rt] = rtv;
+}
+
+static void __kprobes
+t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdv asm("r1") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ "blx %[fn] \n\t"
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdv), [cpsr] "=r" (cpsr)
+ : "0" (rdv), "r" (rnv), "r" (rmv),
+ "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rd = (insn >> 8) & 0xf;
+
+ register unsigned long rdv asm("r1") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = pc & ~3;
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rdv)
+ : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+
+ register unsigned long rdv asm("r1") = regs->uregs[rd];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rdv)
+ : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rdlo = (insn >> 12) & 0xf;
+ int rdhi = (insn >> 8) & 0xf;
+ int rn = (insn >> 16) & 0xf;
+ int rm = insn & 0xf;
+
+ register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
+ register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
+ register unsigned long rnv asm("r2") = regs->uregs[rn];
+ register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ "blx %[fn]"
+ : "=r" (rdlov), "=r" (rdhiv)
+ : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
+ [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ regs->uregs[rdlo] = rdlov;
+ regs->uregs[rdhi] = rdhiv;
+}
+
+/* These emulation encodings are functionally equivalent... */
+#define t32_emulate_rd8rn16rm0ra12_noflags \
+ t32_emulate_rdlo12rdhi8rn16rm0_noflags
+
+static const union decode_item t32_table_1110_100x_x0xx[] = {
+ /* Load/store multiple instructions */
+
+ /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe4f0000, 0xe80f0000),
+
+ /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */
+ /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffc00000, 0xe8000000),
+ /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */
+ /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffc00000, 0xe9800000),
+
+ /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe508000, 0xe8008000),
+ /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe50c000, 0xe810c000),
+ /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe402000, 0xe8002000),
+
+ /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
+ /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1110_100x_x1xx[] = {
+ /* Load/store dual, load/store exclusive, table branch */
+
+ /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_OR (0xff600000, 0xe8600000),
+ /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
+ REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
+
+ /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */
+ /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch,
+ REGS(NOSP, 0, 0, 0, NOSPPC)),
+
+ /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
+ /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
+ /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
+ /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */
+ /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */
+ /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */
+ /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */
+ /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1110_101x[] = {
+ /* Data-processing (shifted register) */
+
+ /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */
+ /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, 0, 0, NOSPPC)),
+
+ /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */
+ DECODE_OR (0xfff00f00, 0xeb100f00),
+ /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOPC, 0, 0, 0, NOSPPC)),
+
+ /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */
+ /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+ /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */
+ /* ??? 1110 1010 111x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffa00000, 0xeaa00000),
+ /* ??? 1110 1011 001x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffe00000, 0xeb200000),
+ /* ??? 1110 1011 100x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffe00000, 0xeb800000),
+ /* ??? 1110 1011 111x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xffe00000, 0xebe00000),
+
+ /* ADD/SUB SP, SP, Rm, LSL #0..3 */
+ /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */
+ DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(SP, 0, SP, 0, NOSPPC)),
+
+ /* ADD/SUB SP, SP, Rm, shift */
+ /* 1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */
+ DECODE_REJECT (0xff4f0f00, 0xeb0d0d00),
+
+ /* ADD/SUB Rd, SP, Rm, shift */
+ /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(SP, 0, NOPC, 0, NOSPPC)),
+
+ /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */
+ /* BIC 1110 1010 001x xxxx xxxx xxxx xxxx xxxx */
+ /* ORR 1110 1010 010x xxxx xxxx xxxx xxxx xxxx */
+ /* ORN 1110 1010 011x xxxx xxxx xxxx xxxx xxxx */
+ /* EOR 1110 1010 100x xxxx xxxx xxxx xxxx xxxx */
+ /* PKH 1110 1010 110x xxxx xxxx xxxx xxxx xxxx */
+ /* ADD 1110 1011 000x xxxx xxxx xxxx xxxx xxxx */
+ /* ADC 1110 1011 010x xxxx xxxx xxxx xxxx xxxx */
+ /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */
+ /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */
+ /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_0x0x___0[] = {
+ /* Data-processing (modified immediate) */
+
+ /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */
+ /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, 0, 0, 0)),
+
+ /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */
+ DECODE_OR (0xfbf08f00, 0xf1100f00),
+ /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */
+ DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOPC, 0, 0, 0, 0)),
+
+ /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */
+ /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf0a00000),
+ /* ??? 1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */
+ /* ??? 1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbc08000, 0xf0c00000),
+ /* ??? 1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf1200000),
+ /* ??? 1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf1800000),
+ /* ??? 1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfbe08000, 0xf1e00000),
+
+ /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */
+ /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(SP, 0, NOPC, 0, 0)),
+
+ /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */
+ /* BIC 1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */
+ /* ORR 1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */
+ /* ORN 1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */
+ /* EOR 1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */
+ /* ADD 1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */
+ /* ADC 1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */
+ /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */
+ /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */
+ /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_0x1x___0[] = {
+ /* Data-processing (plain binary immediate) */
+
+ /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */
+ DECODE_OR (0xfbff8000, 0xf20f0000),
+ /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags,
+ REGS(PC, 0, NOSPPC, 0, 0)),
+
+ /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */
+ DECODE_OR (0xfbff8f00, 0xf20d0d00),
+ /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */
+ DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags,
+ REGS(SP, 0, SP, 0, 0)),
+
+ /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_OR (0xfbf08000, 0xf2000000),
+ /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags,
+ REGS(NOPCX, 0, NOSPPC, 0, 0)),
+
+ /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */
+ /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */
+ /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */
+ /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */
+ /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+ /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */
+ /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+ /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags,
+ REGS(NOSPPCX, 0, NOSPPC, 0, 0)),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_0xxx___1[] = {
+ /* Branches and miscellaneous control */
+
+ /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */
+ DECODE_OR (0xfff0d7ff, 0xf3a08001),
+ /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */
+ DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none),
+ /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */
+ /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */
+ /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */
+ DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
+
+ /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */
+ DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs,
+ REGS(0, 0, NOSPPC, 0, 0)),
+
+ /*
+ * Unsupported instructions
+ * 1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx
+ *
+ * MSR 1111 0011 100x xxxx 10x0 xxxx xxxx xxxx
+ * DBG hint 1111 0011 1010 xxxx 10x0 x000 1111 xxxx
+ * Unallocated hints 1111 0011 1010 xxxx 10x0 x000 xxxx xxxx
+ * CPS 1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx
+ * CLREX/DSB/DMB/ISB 1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx
+ * BXJ 1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx
+ * SUBS PC,LR,#<imm8> 1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx
+ * MRS Rd, SPSR 1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx
+ * SMC 1111 0111 1111 xxxx 1000 xxxx xxxx xxxx
+ * UNDEFINED 1111 0111 1111 xxxx 1010 xxxx xxxx xxxx
+ * ??? 1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx
+ */
+ DECODE_REJECT (0xfb80d000, 0xf3808000),
+
+ /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */
+ DECODE_CUSTOM (0xf800d000, 0xf0008000, t32_decode_cond_branch),
+
+ /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */
+ DECODE_OR (0xf800d001, 0xf000c000),
+ /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */
+ /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xf8009000, 0xf0009000, t32_simulate_branch),
+
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
+ /* Memory hints */
+
+ /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */
+ /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */
+ DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, kprobe_simulate_nop),
+
+ /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_OR (0xffd0f000, 0xf890f000),
+ /* PLD{W} (immediate) 1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */
+ DECODE_OR (0xffd0ff00, 0xf810fc00),
+ /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_OR (0xfff0f000, 0xf990f000),
+ /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */
+ DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop,
+ REGS(NOPCX, 0, 0, 0, 0)),
+
+ /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */
+ DECODE_OR (0xffd0ffc0, 0xf810f000),
+ /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */
+ DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop,
+ REGS(NOPCX, 0, 0, 0, NOSPPC)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_100x[] = {
+ /* Store/Load single data item */
+
+ /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfe600000, 0xf8600000),
+
+ /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xfff00000, 0xf9500000),
+
+ /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */
+ DECODE_REJECT (0xfe800d00, 0xf8000800),
+
+ /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */
+ /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */
+ /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */
+ /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */
+ DECODE_REJECT (0xfe800f00, 0xf8000e00),
+
+ /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */
+ DECODE_REJECT (0xff1f0000, 0xf80f0000),
+
+ /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */
+ DECODE_REJECT (0xff10f000, 0xf800f000),
+
+ /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
+ DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal,
+ REGS(PC, ANY, 0, 0, 0)),
+
+ /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */
+ DECODE_OR (0xffe00800, 0xf8400800),
+ /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
+ /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr,
+ REGS(NOPCX, ANY, 0, 0, 0)),
+
+ /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
+ /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
+ DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr,
+ REGS(NOPCX, ANY, 0, 0, NOSPPC)),
+
+ /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
+ /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
+ /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
+ /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
+ REGS(PC, NOSPPCX, 0, 0, 0)),
+
+ /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
+ /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */
+ /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */
+ DECODE_OR (0xfec00800, 0xf8000800),
+ /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */
+ /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
+ /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
+ DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr,
+ REGS(NOPCX, NOSPPCX, 0, 0, 0)),
+
+ /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
+ /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
+ /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */
+ /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
+ /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
+ /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
+ DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr,
+ REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_1010___1111[] = {
+ /* Data-processing (register) */
+
+ /* ??? 1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */
+ DECODE_REJECT (0xffe0f080, 0xfa60f080),
+
+ /* SXTH 1111 1010 0000 1111 1111 xxxx 1xxx xxxx */
+ /* UXTH 1111 1010 0001 1111 1111 xxxx 1xxx xxxx */
+ /* SXTB16 1111 1010 0010 1111 1111 xxxx 1xxx xxxx */
+ /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */
+ /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */
+ /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */
+ DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+
+ /* ??? 1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */
+ DECODE_REJECT (0xff80f0b0, 0xfa80f030),
+ /* ??? 1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */
+ DECODE_REJECT (0xffb0f080, 0xfab0f000),
+
+ /* SADD16 1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */
+ /* SASX 1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */
+ /* SSAX 1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */
+ /* SSUB16 1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */
+ /* SADD8 1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */
+ /* SSUB8 1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */
+
+ /* QADD16 1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */
+ /* QASX 1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */
+ /* QSAX 1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */
+ /* QSUB16 1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */
+ /* QADD8 1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */
+ /* QSUB8 1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */
+
+ /* SHADD16 1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */
+ /* SHASX 1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */
+ /* SHSAX 1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */
+ /* SHSUB16 1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */
+ /* SHADD8 1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */
+ /* SHSUB8 1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */
+
+ /* UADD16 1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */
+ /* UASX 1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */
+ /* USAX 1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */
+ /* USUB16 1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */
+ /* UADD8 1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */
+ /* USUB8 1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */
+
+ /* UQADD16 1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */
+ /* UQASX 1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */
+ /* UQSAX 1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */
+ /* UQSUB16 1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */
+ /* UQADD8 1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */
+ /* UQSUB8 1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */
+
+ /* UHADD16 1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */
+ /* UHASX 1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */
+ /* UHSAX 1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */
+ /* UHSUB16 1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */
+ /* UHADD8 1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */
+ /* UHSUB8 1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */
+ DECODE_OR (0xff80f080, 0xfa80f000),
+
+ /* SXTAH 1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */
+ /* UXTAH 1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */
+ /* SXTAB16 1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */
+ /* UXTAB16 1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */
+ /* SXTAB 1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */
+ /* UXTAB 1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */
+ DECODE_OR (0xff80f080, 0xfa00f080),
+
+ /* QADD 1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */
+ /* QDADD 1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */
+ /* QSUB 1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */
+ /* QDSUB 1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */
+ DECODE_OR (0xfff0f0c0, 0xfa80f080),
+
+ /* SEL 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+ DECODE_OR (0xfff0f0f0, 0xfaa0f080),
+
+ /* LSL 1111 1010 000x xxxx 1111 xxxx 0000 xxxx */
+ /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */
+ /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */
+ /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+ /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+ DECODE_OR (0xfff0f0f0, 0xfab0f080),
+
+ /* REV 1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */
+ /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */
+ /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */
+ /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */
+ DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_1011_0[] = {
+ /* Multiply, multiply accumulate, and absolute difference */
+
+ /* ??? 1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */
+ DECODE_REJECT (0xfff0f0f0, 0xfb00f010),
+ /* ??? 1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */
+ DECODE_REJECT (0xfff0f0f0, 0xfb70f010),
+
+ /* SMULxy 1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */
+ DECODE_OR (0xfff0f0c0, 0xfb10f000),
+ /* MUL 1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */
+ /* SMUAD{X} 1111 1011 0010 xxxx 1111 xxxx 000x xxxx */
+ /* SMULWy 1111 1011 0011 xxxx 1111 xxxx 000x xxxx */
+ /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */
+ /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */
+ /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags,
+ REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+ /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */
+ DECODE_REJECT (0xfff000f0, 0xfb700010),
+
+ /* SMLAxy 1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */
+ DECODE_OR (0xfff000c0, 0xfb100000),
+ /* MLA 1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */
+ /* MLS 1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */
+ /* SMLAD{X} 1111 1011 0010 xxxx xxxx xxxx 000x xxxx */
+ /* SMLAWy 1111 1011 0011 xxxx xxxx xxxx 000x xxxx */
+ /* SMLSD{X} 1111 1011 0100 xxxx xxxx xxxx 000x xxxx */
+ /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */
+ /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */
+ /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags,
+ REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)),
+
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+static const union decode_item t32_table_1111_1011_1[] = {
+ /* Long multiply, long multiply accumulate, and divide */
+
+ /* UMAAL 1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */
+ DECODE_OR (0xfff000f0, 0xfbe00060),
+ /* SMLALxy 1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */
+ DECODE_OR (0xfff000c0, 0xfbc00080),
+ /* SMLALD{X} 1111 1011 1100 xxxx xxxx xxxx 110x xxxx */
+ /* SMLSLD{X} 1111 1011 1101 xxxx xxxx xxxx 110x xxxx */
+ DECODE_OR (0xffe000e0, 0xfbc000c0),
+ /* SMULL 1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */
+ /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */
+ /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */
+ /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */
+ DECODE_EMULATEX (0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags,
+ REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)),
+
+ /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */
+ /* UDIV 1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */
+ /* Other unallocated instructions... */
+ DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb32_table[] = {
+
+ /*
+ * Load/store multiple instructions
+ * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
+
+ /*
+ * Load/store dual, load/store exclusive, table branch
+ * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
+
+ /*
+ * Data-processing (shifted register)
+ * 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe000000, 0xea000000, t32_table_1110_101x),
+
+ /*
+ * Coprocessor instructions
+ * 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_REJECT (0xfc000000, 0xec000000),
+
+ /*
+ * Data-processing (modified immediate)
+ * 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfa008000, 0xf0000000, t32_table_1111_0x0x___0),
+
+ /*
+ * Data-processing (plain binary immediate)
+ * 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfa008000, 0xf2000000, t32_table_1111_0x1x___0),
+
+ /*
+ * Branches and miscellaneous control
+ * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
+
+ /*
+ * Advanced SIMD element or structure load/store instructions
+ * 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_REJECT (0xff100000, 0xf9000000),
+
+ /*
+ * Memory hints
+ * 1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
+
+ /*
+ * Store single data item
+ * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx
+ * Load single data items
+ * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x),
+
+ /*
+ * Data-processing (register)
+ * 1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
+
+ /*
+ * Multiply, multiply accumulate, and absolute difference
+ * 1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xff800000, 0xfb000000, t32_table_1111_1011_0),
+
+ /*
+ * Long multiply, long multiply accumulate, and divide
+ * 1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xff800000, 0xfb800000, t32_table_1111_1011_1),
+
+ /*
+ * Coprocessor instructions
+ * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+ */
+ DECODE_END
+};
+
+static void __kprobes
+t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rm = (insn >> 3) & 0xf;
+ unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+ if (insn & (1 << 7)) /* BLX ? */
+ regs->ARM_lr = (unsigned long)p->addr + 2;
+
+ bx_write_pc(rmv, regs);
+}
+
+static void __kprobes
+t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
+ long index = insn & 0xff;
+ int rt = (insn >> 8) & 0x7;
+ regs->uregs[rt] = base[index];
+}
+
+static void __kprobes
+t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long* base = (unsigned long *)regs->ARM_sp;
+ long index = insn & 0xff;
+ int rt = (insn >> 8) & 0x7;
+ if (insn & 0x800) /* LDR */
+ regs->uregs[rt] = base[index];
+ else /* STR */
+ base[index] = regs->uregs[rt];
+}
+
+static void __kprobes
+t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long base = (insn & 0x800) ? regs->ARM_sp
+ : (thumb_probe_pc(p) & ~3);
+ long offset = insn & 0xff;
+ int rt = (insn >> 8) & 0x7;
+ regs->uregs[rt] = base + offset * 4;
+}
+
+static void __kprobes
+t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ long imm = insn & 0x7f;
+ if (insn & 0x80) /* SUB */
+ regs->ARM_sp -= imm * 4;
+ else /* ADD */
+ regs->ARM_sp += imm * 4;
+}
+
+static void __kprobes
+t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rn = insn & 0x7;
+ kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
+ if (nonzero & 0x800) {
+ long i = insn & 0x200;
+ long imm5 = insn & 0xf8;
+ unsigned long pc = thumb_probe_pc(p);
+ regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
+ }
+}
+
+static void __kprobes
+t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
+{
+ /*
+ * The 8 IT state bits are split into two parts in CPSR:
+ * ITSTATE<1:0> are in CPSR<26:25>
+ * ITSTATE<7:2> are in CPSR<15:10>
+ * The new IT state is in the lower byte of insn.
+ */
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long cpsr = regs->ARM_cpsr;
+ cpsr &= ~PSR_IT_MASK;
+ cpsr |= (insn & 0xfc) << 8;
+ cpsr |= (insn & 0x03) << 25;
+ regs->ARM_cpsr = cpsr;
+}
+
+static void __kprobes
+t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 2;
+ t16_simulate_it(p, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = t16_singlestep_it;
+ return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ long offset = insn & 0x7f;
+ offset -= insn & 0x80; /* Apply sign bit */
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ int cc = (insn >> 8) & 0xf;
+ asi->insn_check_cc = kprobe_condition_checks[cc];
+ asi->insn_handler = t16_simulate_cond_branch;
+ return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ long offset = insn & 0x3ff;
+ offset -= insn & 0x400; /* Apply sign bit */
+ regs->ARM_pc = pc + (offset * 2);
+}
+
+static unsigned long __kprobes
+t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long oldcpsr = regs->ARM_cpsr;
+ unsigned long newcpsr;
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[oldcpsr] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "stmia %[regs], {r0-r7} \n\t"
+ "mrs %[newcpsr], cpsr \n\t"
+ : [newcpsr] "=r" (newcpsr)
+ : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
+ [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "lr", "memory", "cc"
+ );
+
+ return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
+}
+
+static void __kprobes
+t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_cpsr = t16_emulate_loregs(p, regs);
+}
+
+static void __kprobes
+t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long cpsr = t16_emulate_loregs(p, regs);
+ if (!in_it_block(cpsr))
+ regs->ARM_cpsr = cpsr;
+}
+
+static void __kprobes
+t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ unsigned long pc = thumb_probe_pc(p);
+ int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
+ int rm = (insn >> 3) & 0xf;
+
+ register unsigned long rdnv asm("r1");
+ register unsigned long rmv asm("r0");
+ unsigned long cpsr = regs->ARM_cpsr;
+
+ rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
+ rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+ __asm__ __volatile__ (
+ "msr cpsr_fs, %[cpsr] \n\t"
+ "blx %[fn] \n\t"
+ "mrs %[cpsr], cpsr \n\t"
+ : "=r" (rdnv), [cpsr] "=r" (cpsr)
+ : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "lr", "memory", "cc"
+ );
+
+ if (rdn == 15)
+ rdnv &= ~1;
+
+ regs->uregs[rdn] = rdnv;
+ regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ insn &= ~0x00ff;
+ insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
+ ((u16 *)asi->insn)[0] = insn;
+ asi->insn_handler = t16_emulate_hiregs;
+ return INSN_GOOD;
+}
+
+static void __kprobes
+t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
+{
+ __asm__ __volatile__ (
+ "ldr r9, [%[regs], #13*4] \n\t"
+ "ldr r8, [%[regs], #14*4] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "str r9, [%[regs], #13*4] \n\t"
+ :
+ : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+ "lr", "memory", "cc"
+ );
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ /*
+ * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
+ * and call it with R9=SP and LR in the register list represented
+ * by R8.
+ */
+ ((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */
+ ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
+ asi->insn_handler = t16_emulate_push;
+ return INSN_GOOD;
+}
+
+static void __kprobes
+t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+ __asm__ __volatile__ (
+ "ldr r9, [%[regs], #13*4] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "stmia %[regs], {r0-r7} \n\t"
+ "str r9, [%[regs], #13*4] \n\t"
+ :
+ : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+ "lr", "memory", "cc"
+ );
+}
+
+static void __kprobes
+t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
+{
+ register unsigned long pc asm("r8");
+
+ __asm__ __volatile__ (
+ "ldr r9, [%[regs], #13*4] \n\t"
+ "ldmia %[regs], {r0-r7} \n\t"
+ "blx %[fn] \n\t"
+ "stmia %[regs], {r0-r7} \n\t"
+ "str r9, [%[regs], #13*4] \n\t"
+ : "=r" (pc)
+ : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+ "lr", "memory", "cc"
+ );
+
+ bx_write_pc(pc, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ /*
+ * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
+ * and call it with R9=SP and PC in the register list represented
+ * by R8.
+ */
+ ((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */
+ ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
+ asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
+ : t16_emulate_pop_nopc;
+ return INSN_GOOD;
+}
+
+static const union decode_item t16_table_1011[] = {
+ /* Miscellaneous 16-bit instructions */
+
+ /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */
+ /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */
+ DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm),
+
+ /* CBZ 1011 00x1 xxxx xxxx */
+ /* CBNZ 1011 10x1 xxxx xxxx */
+ DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz),
+
+ /* SXTH 1011 0010 00xx xxxx */
+ /* SXTB 1011 0010 01xx xxxx */
+ /* UXTH 1011 0010 10xx xxxx */
+ /* UXTB 1011 0010 11xx xxxx */
+ /* REV 1011 1010 00xx xxxx */
+ /* REV16 1011 1010 01xx xxxx */
+ /* ??? 1011 1010 10xx xxxx */
+ /* REVSH 1011 1010 11xx xxxx */
+ DECODE_REJECT (0xffc0, 0xba80),
+ DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags),
+
+ /* PUSH 1011 010x xxxx xxxx */
+ DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push),
+ /* POP 1011 110x xxxx xxxx */
+ DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop),
+
+ /*
+ * If-Then, and hints
+ * 1011 1111 xxxx xxxx
+ */
+
+ /* YIELD 1011 1111 0001 0000 */
+ DECODE_OR (0xffff, 0xbf10),
+ /* SEV 1011 1111 0100 0000 */
+ DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none),
+ /* NOP 1011 1111 0000 0000 */
+ /* WFE 1011 1111 0010 0000 */
+ /* WFI 1011 1111 0011 0000 */
+ DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop),
+ /* Unassigned hints 1011 1111 xxxx 0000 */
+ DECODE_REJECT (0xff0f, 0xbf00),
+ /* IT 1011 1111 xxxx xxxx */
+ DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it),
+
+ /* SETEND 1011 0110 010x xxxx */
+ /* CPS 1011 0110 011x xxxx */
+ /* BKPT 1011 1110 xxxx xxxx */
+ /* And unallocated instructions... */
+ DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb16_table[] = {
+
+ /*
+ * Shift (immediate), add, subtract, move, and compare
+ * 00xx xxxx xxxx xxxx
+ */
+
+ /* CMP (immediate) 0010 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags),
+
+ /* ADD (register) 0001 100x xxxx xxxx */
+ /* SUB (register) 0001 101x xxxx xxxx */
+ /* LSL (immediate) 0000 0xxx xxxx xxxx */
+ /* LSR (immediate) 0000 1xxx xxxx xxxx */
+ /* ASR (immediate) 0001 0xxx xxxx xxxx */
+ /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */
+ /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */
+ /* MOV (immediate) 0010 0xxx xxxx xxxx */
+ /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */
+ /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags),
+
+ /*
+ * 16-bit Thumb data-processing instructions
+ * 0100 00xx xxxx xxxx
+ */
+
+ /* TST (register) 0100 0010 00xx xxxx */
+ DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags),
+ /* CMP (register) 0100 0010 10xx xxxx */
+ /* CMN (register) 0100 0010 11xx xxxx */
+ DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags),
+ /* AND (register) 0100 0000 00xx xxxx */
+ /* EOR (register) 0100 0000 01xx xxxx */
+ /* LSL (register) 0100 0000 10xx xxxx */
+ /* LSR (register) 0100 0000 11xx xxxx */
+ /* ASR (register) 0100 0001 00xx xxxx */
+ /* ADC (register) 0100 0001 01xx xxxx */
+ /* SBC (register) 0100 0001 10xx xxxx */
+ /* ROR (register) 0100 0001 11xx xxxx */
+ /* RSB (immediate) 0100 0010 01xx xxxx */
+ /* ORR (register) 0100 0011 00xx xxxx */
+ /* MUL 0100 0011 00xx xxxx */
+ /* BIC (register) 0100 0011 10xx xxxx */
+ /* MVN (register) 0100 0011 10xx xxxx */
+ DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
+
+ /*
+ * Special data instructions and branch and exchange
+ * 0100 01xx xxxx xxxx
+ */
+
+ /* BLX pc 0100 0111 1111 1xxx */
+ DECODE_REJECT (0xfff8, 0x47f8),
+
+ /* BX (register) 0100 0111 0xxx xxxx */
+ /* BLX (register) 0100 0111 1xxx xxxx */
+ DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
+
+ /* ADD pc, pc 0100 0100 1111 1111 */
+ DECODE_REJECT (0xffff, 0x44ff),
+
+ /* ADD (register) 0100 0100 xxxx xxxx */
+ /* CMP (register) 0100 0101 xxxx xxxx */
+ /* MOV (register) 0100 0110 xxxx xxxx */
+ DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs),
+
+ /*
+ * Load from Literal Pool
+ * LDR (literal) 0100 1xxx xxxx xxxx
+ */
+ DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal),
+
+ /*
+ * 16-bit Thumb Load/store instructions
+ * 0101 xxxx xxxx xxxx
+ * 011x xxxx xxxx xxxx
+ * 100x xxxx xxxx xxxx
+ */
+
+ /* STR (register) 0101 000x xxxx xxxx */
+ /* STRH (register) 0101 001x xxxx xxxx */
+ /* STRB (register) 0101 010x xxxx xxxx */
+ /* LDRSB (register) 0101 011x xxxx xxxx */
+ /* LDR (register) 0101 100x xxxx xxxx */
+ /* LDRH (register) 0101 101x xxxx xxxx */
+ /* LDRB (register) 0101 110x xxxx xxxx */
+ /* LDRSH (register) 0101 111x xxxx xxxx */
+ /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */
+ /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */
+ /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */
+ /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags),
+ /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */
+ /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags),
+ /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */
+ /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */
+ DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
+
+ /*
+ * Generate PC-/SP-relative address
+ * ADR (literal) 1010 0xxx xxxx xxxx
+ * ADD (SP plus immediate) 1010 1xxx xxxx xxxx
+ */
+ DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr),
+
+ /*
+ * Miscellaneous 16-bit instructions
+ * 1011 xxxx xxxx xxxx
+ */
+ DECODE_TABLE (0xf000, 0xb000, t16_table_1011),
+
+ /* STM 1100 0xxx xxxx xxxx */
+ /* LDM 1100 1xxx xxxx xxxx */
+ DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags),
+
+ /*
+ * Conditional branch, and Supervisor Call
+ */
+
+ /* Permanently UNDEFINED 1101 1110 xxxx xxxx */
+ /* SVC 1101 1111 xxxx xxxx */
+ DECODE_REJECT (0xfe00, 0xde00),
+
+ /* Conditional branch 1101 xxxx xxxx xxxx */
+ DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch),
+
+ /*
+ * Unconditional branch
+ * B 1110 0xxx xxxx xxxx
+ */
+ DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch),
+
+ DECODE_END
+};
+
+static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
+{
+ if (unlikely(in_it_block(cpsr)))
+ return kprobe_condition_checks[current_cond(cpsr)](cpsr);
+ return true;
+}
+
+static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 2;
+ p->ainsn.insn_handler(p, regs);
+ regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
+static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->ARM_pc += 4;
+ p->ainsn.insn_handler(p, regs);
+ regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
+enum kprobe_insn __kprobes
+thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = thumb16_singlestep;
+ asi->insn_check_cc = thumb_check_cc;
+ return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
+}
+
+enum kprobe_insn __kprobes
+thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+ asi->insn_singlestep = thumb32_singlestep;
+ asi->insn_check_cc = thumb_check_cc;
+ return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true);
+}
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 1656c87501c0..129c1163248b 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -28,14 +28,16 @@
#include <asm/traps.h>
#include <asm/cacheflush.h>
+#include "kprobes.h"
+
#define MIN_STACK_SIZE(addr) \
min((unsigned long)MAX_STACK_SIZE, \
(unsigned long)current_thread_info() + THREAD_START_SP - (addr))
-#define flush_insns(addr, cnt) \
+#define flush_insns(addr, size) \
flush_icache_range((unsigned long)(addr), \
(unsigned long)(addr) + \
- sizeof(kprobe_opcode_t) * (cnt))
+ (size))
/* Used as a marker in ARM_pc to note when we're in a jprobe. */
#define JPROBE_MAGIC_ADDR 0xffffffff
@@ -49,16 +51,35 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
kprobe_opcode_t insn;
kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
unsigned long addr = (unsigned long)p->addr;
+ bool thumb;
+ kprobe_decode_insn_t *decode_insn;
int is;
- if (addr & 0x3 || in_exception_text(addr))
+ if (in_exception_text(addr))
return -EINVAL;
+#ifdef CONFIG_THUMB2_KERNEL
+ thumb = true;
+ addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
+ insn = ((u16 *)addr)[0];
+ if (is_wide_instruction(insn)) {
+ insn <<= 16;
+ insn |= ((u16 *)addr)[1];
+ decode_insn = thumb32_kprobe_decode_insn;
+ } else
+ decode_insn = thumb16_kprobe_decode_insn;
+#else /* !CONFIG_THUMB2_KERNEL */
+ thumb = false;
+ if (addr & 0x3)
+ return -EINVAL;
insn = *p->addr;
+ decode_insn = arm_kprobe_decode_insn;
+#endif
+
p->opcode = insn;
p->ainsn.insn = tmp_insn;
- switch (arm_kprobe_decode_insn(insn, &p->ainsn)) {
+ switch ((*decode_insn)(insn, &p->ainsn)) {
case INSN_REJECTED: /* not supported */
return -EINVAL;
@@ -68,7 +89,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return -ENOMEM;
for (is = 0; is < MAX_INSN_SIZE; ++is)
p->ainsn.insn[is] = tmp_insn[is];
- flush_insns(p->ainsn.insn, MAX_INSN_SIZE);
+ flush_insns(p->ainsn.insn,
+ sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE);
+ p->ainsn.insn_fn = (kprobe_insn_fn_t *)
+ ((uintptr_t)p->ainsn.insn | thumb);
break;
case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */
@@ -79,24 +103,88 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return 0;
}
+#ifdef CONFIG_THUMB2_KERNEL
+
+/*
+ * For a 32-bit Thumb breakpoint spanning two memory words we need to take
+ * special precautions to insert the breakpoint atomically, especially on SMP
+ * systems. This is achieved by calling this arming function using stop_machine.
+ */
+static int __kprobes set_t32_breakpoint(void *addr)
+{
+ ((u16 *)addr)[0] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION >> 16;
+ ((u16 *)addr)[1] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION & 0xffff;
+ flush_insns(addr, 2*sizeof(u16));
+ return 0;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+ uintptr_t addr = (uintptr_t)p->addr & ~1; /* Remove any Thumb flag */
+
+ if (!is_wide_instruction(p->opcode)) {
+ *(u16 *)addr = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
+ flush_insns(addr, sizeof(u16));
+ } else if (addr & 2) {
+ /* A 32-bit instruction spanning two words needs special care */
+ stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map);
+ } else {
+ /* Word aligned 32-bit instruction can be written atomically */
+ u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
+#ifndef __ARMEB__ /* Swap halfwords for little-endian */
+ bkp = (bkp >> 16) | (bkp << 16);
+#endif
+ *(u32 *)addr = bkp;
+ flush_insns(addr, sizeof(u32));
+ }
+}
+
+#else /* !CONFIG_THUMB2_KERNEL */
+
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
- *p->addr = KPROBE_BREAKPOINT_INSTRUCTION;
- flush_insns(p->addr, 1);
+ kprobe_opcode_t insn = p->opcode;
+ kprobe_opcode_t brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
+ if (insn >= 0xe0000000)
+ brkp |= 0xe0000000; /* Unconditional instruction */
+ else
+ brkp |= insn & 0xf0000000; /* Copy condition from insn */
+ *p->addr = brkp;
+ flush_insns(p->addr, sizeof(p->addr[0]));
}
+#endif /* !CONFIG_THUMB2_KERNEL */
+
/*
* The actual disarming is done here on each CPU and synchronized using
* stop_machine. This synchronization is necessary on SMP to avoid removing
* a probe between the moment the 'Undefined Instruction' exception is raised
* and the moment the exception handler reads the faulting instruction from
- * memory.
+ * memory. It is also needed to atomically set the two half-words of a 32-bit
+ * Thumb breakpoint.
*/
int __kprobes __arch_disarm_kprobe(void *p)
{
struct kprobe *kp = p;
+#ifdef CONFIG_THUMB2_KERNEL
+ u16 *addr = (u16 *)((uintptr_t)kp->addr & ~1);
+ kprobe_opcode_t insn = kp->opcode;
+ unsigned int len;
+
+ if (is_wide_instruction(insn)) {
+ ((u16 *)addr)[0] = insn>>16;
+ ((u16 *)addr)[1] = insn;
+ len = 2*sizeof(u16);
+ } else {
+ ((u16 *)addr)[0] = insn;
+ len = sizeof(u16);
+ }
+ flush_insns(addr, len);
+
+#else /* !CONFIG_THUMB2_KERNEL */
*kp->addr = kp->opcode;
- flush_insns(kp->addr, 1);
+ flush_insns(kp->addr, sizeof(kp->addr[0]));
+#endif
return 0;
}
@@ -130,12 +218,24 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
__get_cpu_var(current_kprobe) = p;
}
-static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
- struct kprobe_ctlblk *kcb)
+static void __kprobes
+singlestep_skip(struct kprobe *p, struct pt_regs *regs)
{
+#ifdef CONFIG_THUMB2_KERNEL
+ regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+ if (is_wide_instruction(p->opcode))
+ regs->ARM_pc += 4;
+ else
+ regs->ARM_pc += 2;
+#else
regs->ARM_pc += 4;
- if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
- p->ainsn.insn_handler(p, regs);
+#endif
+}
+
+static inline void __kprobes
+singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
+{
+ p->ainsn.insn_singlestep(p, regs);
}
/*
@@ -149,11 +249,23 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p, *cur;
struct kprobe_ctlblk *kcb;
- kprobe_opcode_t *addr = (kprobe_opcode_t *)regs->ARM_pc;
kcb = get_kprobe_ctlblk();
cur = kprobe_running();
- p = get_kprobe(addr);
+
+#ifdef CONFIG_THUMB2_KERNEL
+ /*
+ * First look for a probe which was registered using an address with
+ * bit 0 set, this is the usual situation for pointers to Thumb code.
+ * If not found, fallback to looking for one with bit 0 clear.
+ */
+ p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1));
+ if (!p)
+ p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
+
+#else /* ! CONFIG_THUMB2_KERNEL */
+ p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
+#endif
if (p) {
if (cur) {
@@ -173,7 +285,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
/* impossible cases */
BUG();
}
- } else {
+ } else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) {
+ /* Probe hit and conditional execution check ok. */
set_current_kprobe(p);
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
@@ -193,6 +306,13 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
}
reset_current_kprobe();
}
+ } else {
+ /*
+ * Probe hit but conditional execution check failed,
+ * so just skip the instruction and continue as if
+ * nothing had happened.
+ */
+ singlestep_skip(p, regs);
}
} else if (cur) {
/* We probably hit a jprobe. Call its break handler. */
@@ -300,7 +420,11 @@ void __naked __kprobes kretprobe_trampoline(void)
"bl trampoline_handler \n\t"
"mov lr, r0 \n\t"
"ldmia sp!, {r0 - r11} \n\t"
+#ifdef CONFIG_THUMB2_KERNEL
+ "bx lr \n\t"
+#else
"mov pc, lr \n\t"
+#endif
: : : "memory");
}
@@ -378,11 +502,22 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
struct jprobe *jp = container_of(p, struct jprobe, kp);
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
long sp_addr = regs->ARM_sp;
+ long cpsr;
kcb->jprobe_saved_regs = *regs;
memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr));
regs->ARM_pc = (long)jp->entry;
- regs->ARM_cpsr |= PSR_I_BIT;
+
+ cpsr = regs->ARM_cpsr | PSR_I_BIT;
+#ifdef CONFIG_THUMB2_KERNEL
+ /* Set correct Thumb state in cpsr */
+ if (regs->ARM_pc & 1)
+ cpsr |= PSR_T_BIT;
+ else
+ cpsr &= ~PSR_T_BIT;
+#endif
+ regs->ARM_cpsr = cpsr;
+
preempt_disable();
return 1;
}
@@ -404,7 +539,12 @@ void __kprobes jprobe_return(void)
* This is to prevent any simulated instruction from writing
* over the regs when they are accessing the stack.
*/
+#ifdef CONFIG_THUMB2_KERNEL
+ "sub r0, %0, %1 \n\t"
+ "mov sp, r0 \n\t"
+#else
"sub sp, %0, %1 \n\t"
+#endif
"ldr r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t"
"str %0, [sp, %2] \n\t"
"str r0, [sp, %3] \n\t"
@@ -415,15 +555,28 @@ void __kprobes jprobe_return(void)
* Return to the context saved by setjmp_pre_handler
* and restored by longjmp_break_handler.
*/
+#ifdef CONFIG_THUMB2_KERNEL
+ "ldr lr, [sp, %2] \n\t" /* lr = saved sp */
+ "ldrd r0, r1, [sp, %5] \n\t" /* r0,r1 = saved lr,pc */
+ "ldr r2, [sp, %4] \n\t" /* r2 = saved psr */
+ "stmdb lr!, {r0, r1, r2} \n\t" /* push saved lr and */
+ /* rfe context */
+ "ldmia sp, {r0 - r12} \n\t"
+ "mov sp, lr \n\t"
+ "ldr lr, [sp], #4 \n\t"
+ "rfeia sp! \n\t"
+#else
"ldr r0, [sp, %4] \n\t"
"msr cpsr_cxsf, r0 \n\t"
"ldmia sp, {r0 - pc} \n\t"
+#endif
:
: "r" (kcb->jprobe_saved_regs.ARM_sp),
"I" (sizeof(struct pt_regs) * 2),
"J" (offsetof(struct pt_regs, ARM_sp)),
"J" (offsetof(struct pt_regs, ARM_pc)),
- "J" (offsetof(struct pt_regs, ARM_cpsr))
+ "J" (offsetof(struct pt_regs, ARM_cpsr)),
+ "J" (offsetof(struct pt_regs, ARM_lr))
: "memory", "cc");
}
@@ -460,17 +613,44 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
return 0;
}
-static struct undef_hook kprobes_break_hook = {
+#ifdef CONFIG_THUMB2_KERNEL
+
+static struct undef_hook kprobes_thumb16_break_hook = {
+ .instr_mask = 0xffff,
+ .instr_val = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION,
+ .cpsr_mask = MODE_MASK,
+ .cpsr_val = SVC_MODE,
+ .fn = kprobe_trap_handler,
+};
+
+static struct undef_hook kprobes_thumb32_break_hook = {
.instr_mask = 0xffffffff,
- .instr_val = KPROBE_BREAKPOINT_INSTRUCTION,
+ .instr_val = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION,
.cpsr_mask = MODE_MASK,
.cpsr_val = SVC_MODE,
.fn = kprobe_trap_handler,
};
+#else /* !CONFIG_THUMB2_KERNEL */
+
+static struct undef_hook kprobes_arm_break_hook = {
+ .instr_mask = 0x0fffffff,
+ .instr_val = KPROBE_ARM_BREAKPOINT_INSTRUCTION,
+ .cpsr_mask = MODE_MASK,
+ .cpsr_val = SVC_MODE,
+ .fn = kprobe_trap_handler,
+};
+
+#endif /* !CONFIG_THUMB2_KERNEL */
+
int __init arch_init_kprobes()
{
arm_kprobe_decode_init();
- register_undef_hook(&kprobes_break_hook);
+#ifdef CONFIG_THUMB2_KERNEL
+ register_undef_hook(&kprobes_thumb16_break_hook);
+ register_undef_hook(&kprobes_thumb32_break_hook);
+#else
+ register_undef_hook(&kprobes_arm_break_hook);
+#endif
return 0;
}
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
new file mode 100644
index 000000000000..a6aeda0a6c7f
--- /dev/null
+++ b/arch/arm/kernel/kprobes.h
@@ -0,0 +1,420 @@
+/*
+ * arch/arm/kernel/kprobes.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * Some contents moved here from arch/arm/include/asm/kprobes.h which is
+ * Copyright (C) 2006, 2007 Motorola 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.
+ */
+
+#ifndef _ARM_KERNEL_KPROBES_H
+#define _ARM_KERNEL_KPROBES_H
+
+/*
+ * These undefined instructions must be unique and
+ * reserved solely for kprobes' use.
+ */
+#define KPROBE_ARM_BREAKPOINT_INSTRUCTION 0x07f001f8
+#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18
+#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
+
+
+enum kprobe_insn {
+ INSN_REJECTED,
+ INSN_GOOD,
+ INSN_GOOD_NO_SLOT
+};
+
+typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
+ struct arch_specific_insn *);
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
+ struct arch_specific_insn *);
+enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
+ struct arch_specific_insn *);
+
+#else /* !CONFIG_THUMB2_KERNEL */
+
+enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
+ struct arch_specific_insn *);
+#endif
+
+void __init arm_kprobe_decode_init(void);
+
+extern kprobe_check_cc * const kprobe_condition_checks[16];
+
+
+#if __LINUX_ARM_ARCH__ >= 7
+
+/* str_pc_offset is architecturally defined from ARMv7 onwards */
+#define str_pc_offset 8
+#define find_str_pc_offset()
+
+#else /* __LINUX_ARM_ARCH__ < 7 */
+
+/* We need a run-time check to determine str_pc_offset */
+extern int str_pc_offset;
+void __init find_str_pc_offset(void);
+
+#endif
+
+
+/*
+ * Update ITSTATE after normal execution of an IT block instruction.
+ *
+ * The 8 IT state bits are split into two parts in CPSR:
+ * ITSTATE<1:0> are in CPSR<26:25>
+ * ITSTATE<7:2> are in CPSR<15:10>
+ */
+static inline unsigned long it_advance(unsigned long cpsr)
+ {
+ if ((cpsr & 0x06000400) == 0) {
+ /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
+ cpsr &= ~PSR_IT_MASK;
+ } else {
+ /* We need to shift left ITSTATE<4:0> */
+ const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */
+ unsigned long it = cpsr & mask;
+ it <<= 1;
+ it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */
+ it &= mask;
+ cpsr &= ~mask;
+ cpsr |= it;
+ }
+ return cpsr;
+}
+
+static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
+{
+ long cpsr = regs->ARM_cpsr;
+ if (pcv & 0x1) {
+ cpsr |= PSR_T_BIT;
+ pcv &= ~0x1;
+ } else {
+ cpsr &= ~PSR_T_BIT;
+ pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */
+ }
+ regs->ARM_cpsr = cpsr;
+ regs->ARM_pc = pcv;
+}
+
+
+#if __LINUX_ARM_ARCH__ >= 6
+
+/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */
+#define load_write_pc_interworks true
+#define test_load_write_pc_interworking()
+
+#else /* __LINUX_ARM_ARCH__ < 6 */
+
+/* We need run-time testing to determine if load_write_pc() should interwork. */
+extern bool load_write_pc_interworks;
+void __init test_load_write_pc_interworking(void);
+
+#endif
+
+static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
+{
+ if (load_write_pc_interworks)
+ bx_write_pc(pcv, regs);
+ else
+ regs->ARM_pc = pcv;
+}
+
+
+#if __LINUX_ARM_ARCH__ >= 7
+
+#define alu_write_pc_interworks true
+#define test_alu_write_pc_interworking()
+
+#elif __LINUX_ARM_ARCH__ <= 5
+
+/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */
+#define alu_write_pc_interworks false
+#define test_alu_write_pc_interworking()
+
+#else /* __LINUX_ARM_ARCH__ == 6 */
+
+/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */
+extern bool alu_write_pc_interworks;
+void __init test_alu_write_pc_interworking(void);
+
+#endif /* __LINUX_ARM_ARCH__ == 6 */
+
+static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
+{
+ if (alu_write_pc_interworks)
+ bx_write_pc(pcv, regs);
+ else
+ regs->ARM_pc = pcv;
+}
+
+
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
+
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
+
+/*
+ * Test if load/store instructions writeback the address register.
+ * if P (bit 24) == 0 or W (bit 21) == 1
+ */
+#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
+
+/*
+ * The following definitions and macros are used to build instruction
+ * decoding tables for use by kprobe_decode_insn.
+ *
+ * These tables are a concatenation of entries each of which consist of one of
+ * the decode_* structs. All of the fields in every type of decode structure
+ * are of the union type decode_item, therefore the entire decode table can be
+ * viewed as an array of these and declared like:
+ *
+ * static const union decode_item table_name[] = {};
+ *
+ * In order to construct each entry in the table, macros are used to
+ * initialise a number of sequential decode_item values in a layout which
+ * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct
+ * decode_simulate by initialising four decode_item objects like this...
+ *
+ * {.bits = _type},
+ * {.bits = _mask},
+ * {.bits = _value},
+ * {.handler = _handler},
+ *
+ * Initialising a specified member of the union means that the compiler
+ * will produce a warning if the argument is of an incorrect type.
+ *
+ * Below is a list of each of the macros used to initialise entries and a
+ * description of the action performed when that entry is matched to an
+ * instruction. A match is found when (instruction & mask) == value.
+ *
+ * DECODE_TABLE(mask, value, table)
+ * Instruction decoding jumps to parsing the new sub-table 'table'.
+ *
+ * DECODE_CUSTOM(mask, value, decoder)
+ * The custom function 'decoder' is called to the complete decoding
+ * of an instruction.
+ *
+ * DECODE_SIMULATE(mask, value, handler)
+ * Set the probes instruction handler to 'handler', this will be used
+ * to simulate the instruction when the probe is hit. Decoding returns
+ * with INSN_GOOD_NO_SLOT.
+ *
+ * DECODE_EMULATE(mask, value, handler)
+ * Set the probes instruction handler to 'handler', this will be used
+ * to emulate the instruction when the probe is hit. The modified
+ * instruction (see below) is placed in the probes instruction slot so it
+ * may be called by the emulation code. Decoding returns with INSN_GOOD.
+ *
+ * DECODE_REJECT(mask, value)
+ * Instruction decoding fails with INSN_REJECTED
+ *
+ * DECODE_OR(mask, value)
+ * This allows the mask/value test of multiple table entries to be
+ * logically ORed. Once an 'or' entry is matched the decoding action to
+ * be performed is that of the next entry which isn't an 'or'. E.g.
+ *
+ * DECODE_OR (mask1, value1)
+ * DECODE_OR (mask2, value2)
+ * DECODE_SIMULATE (mask3, value3, simulation_handler)
+ *
+ * This means that if any of the three mask/value pairs match the
+ * instruction being decoded, then 'simulation_handler' will be used
+ * for it.
+ *
+ * Both the SIMULATE and EMULATE macros have a second form which take an
+ * additional 'regs' argument.
+ *
+ * DECODE_SIMULATEX(mask, value, handler, regs)
+ * DECODE_EMULATEX (mask, value, handler, regs)
+ *
+ * These are used to specify what kind of CPU register is encoded in each of the
+ * least significant 5 nibbles of the instruction being decoded. The regs value
+ * is specified using the REGS macro, this takes any of the REG_TYPE_* values
+ * from enum decode_reg_type as arguments; only the '*' part of the name is
+ * given. E.g.
+ *
+ * REGS(0, ANY, NOPC, 0, ANY)
+ *
+ * This indicates an instruction is encoded like:
+ *
+ * bits 19..16 ignore
+ * bits 15..12 any register allowed here
+ * bits 11.. 8 any register except PC allowed here
+ * bits 7.. 4 ignore
+ * bits 3.. 0 any register allowed here
+ *
+ * This register specification is checked after a decode table entry is found to
+ * match an instruction (through the mask/value test). Any invalid register then
+ * found in the instruction will cause decoding to fail with INSN_REJECTED. In
+ * the above example this would happen if bits 11..8 of the instruction were
+ * 1111, indicating R15 or PC.
+ *
+ * As well as checking for legal combinations of registers, this data is also
+ * used to modify the registers encoded in the instructions so that an
+ * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.)
+ *
+ * Here is a real example which matches ARM instructions of the form
+ * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>"
+ *
+ * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+ * REGS(ANY, ANY, NOPC, 0, ANY)),
+ * ^ ^ ^ ^
+ * Rn Rd Rs Rm
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because
+ * Rs == R15
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the
+ * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into
+ * the kprobes instruction slot. This can then be called later by the handler
+ * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction.
+ */
+
+enum decode_type {
+ DECODE_TYPE_END,
+ DECODE_TYPE_TABLE,
+ DECODE_TYPE_CUSTOM,
+ DECODE_TYPE_SIMULATE,
+ DECODE_TYPE_EMULATE,
+ DECODE_TYPE_OR,
+ DECODE_TYPE_REJECT,
+ NUM_DECODE_TYPES /* Must be last enum */
+};
+
+#define DECODE_TYPE_BITS 4
+#define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1)
+
+enum decode_reg_type {
+ REG_TYPE_NONE = 0, /* Not a register, ignore */
+ REG_TYPE_ANY, /* Any register allowed */
+ REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */
+ REG_TYPE_SP, /* Register must be SP */
+ REG_TYPE_PC, /* Register must be PC */
+ REG_TYPE_NOSP, /* Register must not be SP */
+ REG_TYPE_NOSPPC, /* Register must not be SP or PC */
+ REG_TYPE_NOPC, /* Register must not be PC */
+ REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */
+
+ /* The following types are used when the encoding for PC indicates
+ * another instruction form. This distiction only matters for test
+ * case coverage checks.
+ */
+ REG_TYPE_NOPCX, /* Register must not be PC */
+ REG_TYPE_NOSPPCX, /* Register must not be SP or PC */
+
+ /* Alias to allow '0' arg to be used in REGS macro. */
+ REG_TYPE_0 = REG_TYPE_NONE
+};
+
+#define REGS(r16, r12, r8, r4, r0) \
+ ((REG_TYPE_##r16) << 16) + \
+ ((REG_TYPE_##r12) << 12) + \
+ ((REG_TYPE_##r8) << 8) + \
+ ((REG_TYPE_##r4) << 4) + \
+ (REG_TYPE_##r0)
+
+union decode_item {
+ u32 bits;
+ const union decode_item *table;
+ kprobe_insn_handler_t *handler;
+ kprobe_decode_insn_t *decoder;
+};
+
+
+#define DECODE_END \
+ {.bits = DECODE_TYPE_END}
+
+
+struct decode_header {
+ union decode_item type_regs;
+ union decode_item mask;
+ union decode_item value;
+};
+
+#define DECODE_HEADER(_type, _mask, _value, _regs) \
+ {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \
+ {.bits = (_mask)}, \
+ {.bits = (_value)}
+
+
+struct decode_table {
+ struct decode_header header;
+ union decode_item table;
+};
+
+#define DECODE_TABLE(_mask, _value, _table) \
+ DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \
+ {.table = (_table)}
+
+
+struct decode_custom {
+ struct decode_header header;
+ union decode_item decoder;
+};
+
+#define DECODE_CUSTOM(_mask, _value, _decoder) \
+ DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
+ {.decoder = (_decoder)}
+
+
+struct decode_simulate {
+ struct decode_header header;
+ union decode_item handler;
+};
+
+#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \
+ DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \
+ {.handler = (_handler)}
+
+#define DECODE_SIMULATE(_mask, _value, _handler) \
+ DECODE_SIMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_emulate {
+ struct decode_header header;
+ union decode_item handler;
+};
+
+#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \
+ DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \
+ {.handler = (_handler)}
+
+#define DECODE_EMULATE(_mask, _value, _handler) \
+ DECODE_EMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_or {
+ struct decode_header header;
+};
+
+#define DECODE_OR(_mask, _value) \
+ DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
+
+
+struct decode_reject {
+ struct decode_header header;
+};
+
+#define DECODE_REJECT(_mask, _value) \
+ DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
+
+
+int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *table, bool thumb16);
+
+
+#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 016d6a0830a3..05b377616fd5 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -43,25 +43,7 @@ void *module_alloc(unsigned long size)
GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
__builtin_return_address(0));
}
-#else /* CONFIG_MMU */
-void *module_alloc(unsigned long size)
-{
- return size == 0 ? NULL : vmalloc(size);
-}
-#endif /* !CONFIG_MMU */
-
-void module_free(struct module *module, void *region)
-{
- vfree(region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
+#endif
int
apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
@@ -265,15 +247,6 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
return 0;
}
-int
-apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec, struct module *module)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
- module->name);
- return -ENOEXEC;
-}
-
struct mod_unwind_map {
const Elf_Shdr *unw_sec;
const Elf_Shdr *txt_sec;
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 2b5b1421596c..53c9c2610cbc 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -435,7 +435,7 @@ armpmu_reserve_hardware(void)
if (irq >= 0)
free_irq(irq, NULL);
}
- release_pmu(pmu_device);
+ release_pmu(ARM_PMU_DEVICE_CPU);
pmu_device = NULL;
}
@@ -454,7 +454,7 @@ armpmu_release_hardware(void)
}
armpmu->stop();
- release_pmu(pmu_device);
+ release_pmu(ARM_PMU_DEVICE_CPU);
pmu_device = NULL;
}
@@ -662,6 +662,12 @@ init_hw_perf_events(void)
case 0xC090: /* Cortex-A9 */
armpmu = armv7_a9_pmu_init();
break;
+ case 0xC050: /* Cortex-A5 */
+ armpmu = armv7_a5_pmu_init();
+ break;
+ case 0xC0F0: /* Cortex-A15 */
+ armpmu = armv7_a15_pmu_init();
+ break;
}
/* Intel CPUs [xscale]. */
} else if (0x69 == implementor) {
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index f1e8dd94afe8..dd7f3b9f4cb3 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -173,6 +173,20 @@ static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
enum armv6mpcore_perf_types {
@@ -310,6 +324,20 @@ static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
static inline unsigned long
@@ -479,7 +507,7 @@ armv6pmu_handle_irq(int irq_num,
if (!armpmu_event_set_period(event, hwc, idx))
continue;
- if (perf_event_overflow(event, 0, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
armpmu->disable(hwc, idx);
}
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 4960686afb58..4c851834f68e 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -17,17 +17,23 @@
*/
#ifdef CONFIG_CPU_V7
-/* Common ARMv7 event types */
+/*
+ * Common ARMv7 event types
+ *
+ * Note: An implementation may not be able to count all of these events
+ * but the encodings are considered to be `reserved' in the case that
+ * they are not available.
+ */
enum armv7_perf_types {
ARMV7_PERFCTR_PMNC_SW_INCR = 0x00,
ARMV7_PERFCTR_IFETCH_MISS = 0x01,
ARMV7_PERFCTR_ITLB_MISS = 0x02,
- ARMV7_PERFCTR_DCACHE_REFILL = 0x03,
- ARMV7_PERFCTR_DCACHE_ACCESS = 0x04,
+ ARMV7_PERFCTR_DCACHE_REFILL = 0x03, /* L1 */
+ ARMV7_PERFCTR_DCACHE_ACCESS = 0x04, /* L1 */
ARMV7_PERFCTR_DTLB_REFILL = 0x05,
ARMV7_PERFCTR_DREAD = 0x06,
ARMV7_PERFCTR_DWRITE = 0x07,
-
+ ARMV7_PERFCTR_INSTR_EXECUTED = 0x08,
ARMV7_PERFCTR_EXC_TAKEN = 0x09,
ARMV7_PERFCTR_EXC_EXECUTED = 0x0A,
ARMV7_PERFCTR_CID_WRITE = 0x0B,
@@ -39,21 +45,30 @@ enum armv7_perf_types {
*/
ARMV7_PERFCTR_PC_WRITE = 0x0C,
ARMV7_PERFCTR_PC_IMM_BRANCH = 0x0D,
+ ARMV7_PERFCTR_PC_PROC_RETURN = 0x0E,
ARMV7_PERFCTR_UNALIGNED_ACCESS = 0x0F,
+
+ /* These events are defined by the PMUv2 supplement (ARM DDI 0457A). */
ARMV7_PERFCTR_PC_BRANCH_MIS_PRED = 0x10,
ARMV7_PERFCTR_CLOCK_CYCLES = 0x11,
-
- ARMV7_PERFCTR_PC_BRANCH_MIS_USED = 0x12,
+ ARMV7_PERFCTR_PC_BRANCH_PRED = 0x12,
+ ARMV7_PERFCTR_MEM_ACCESS = 0x13,
+ ARMV7_PERFCTR_L1_ICACHE_ACCESS = 0x14,
+ ARMV7_PERFCTR_L1_DCACHE_WB = 0x15,
+ ARMV7_PERFCTR_L2_DCACHE_ACCESS = 0x16,
+ ARMV7_PERFCTR_L2_DCACHE_REFILL = 0x17,
+ ARMV7_PERFCTR_L2_DCACHE_WB = 0x18,
+ ARMV7_PERFCTR_BUS_ACCESS = 0x19,
+ ARMV7_PERFCTR_MEMORY_ERROR = 0x1A,
+ ARMV7_PERFCTR_INSTR_SPEC = 0x1B,
+ ARMV7_PERFCTR_TTBR_WRITE = 0x1C,
+ ARMV7_PERFCTR_BUS_CYCLES = 0x1D,
ARMV7_PERFCTR_CPU_CYCLES = 0xFF
};
/* ARMv7 Cortex-A8 specific event types */
enum armv7_a8_perf_types {
- ARMV7_PERFCTR_INSTR_EXECUTED = 0x08,
-
- ARMV7_PERFCTR_PC_PROC_RETURN = 0x0E,
-
ARMV7_PERFCTR_WRITE_BUFFER_FULL = 0x40,
ARMV7_PERFCTR_L2_STORE_MERGED = 0x41,
ARMV7_PERFCTR_L2_STORE_BUFF = 0x42,
@@ -138,6 +153,39 @@ enum armv7_a9_perf_types {
ARMV7_PERFCTR_PLE_RQST_PROG = 0xA5
};
+/* ARMv7 Cortex-A5 specific event types */
+enum armv7_a5_perf_types {
+ ARMV7_PERFCTR_IRQ_TAKEN = 0x86,
+ ARMV7_PERFCTR_FIQ_TAKEN = 0x87,
+
+ ARMV7_PERFCTR_EXT_MEM_RQST = 0xc0,
+ ARMV7_PERFCTR_NC_EXT_MEM_RQST = 0xc1,
+ ARMV7_PERFCTR_PREFETCH_LINEFILL = 0xc2,
+ ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP = 0xc3,
+ ARMV7_PERFCTR_ENTER_READ_ALLOC = 0xc4,
+ ARMV7_PERFCTR_READ_ALLOC = 0xc5,
+
+ ARMV7_PERFCTR_STALL_SB_FULL = 0xc9,
+};
+
+/* ARMv7 Cortex-A15 specific event types */
+enum armv7_a15_perf_types {
+ ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS = 0x40,
+ ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS = 0x41,
+ ARMV7_PERFCTR_L1_DCACHE_READ_REFILL = 0x42,
+ ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL = 0x43,
+
+ ARMV7_PERFCTR_L1_DTLB_READ_REFILL = 0x4C,
+ ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL = 0x4D,
+
+ ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS = 0x50,
+ ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS = 0x51,
+ ARMV7_PERFCTR_L2_DCACHE_READ_REFILL = 0x52,
+ ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL = 0x53,
+
+ ARMV7_PERFCTR_SPEC_PC_WRITE = 0x76,
+};
+
/*
* Cortex-A8 HW events mapping
*
@@ -207,11 +255,6 @@ static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
},
},
[C(DTLB)] = {
- /*
- * Only ITLB misses and DTLB refills are supported.
- * If users want the DTLB refills misses a raw counter
- * must be used.
- */
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
[C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
@@ -255,6 +298,20 @@ static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
/*
@@ -323,11 +380,6 @@ static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
},
},
[C(DTLB)] = {
- /*
- * Only ITLB misses and DTLB refills are supported.
- * If users want the DTLB refills misses a raw counter
- * must be used.
- */
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
[C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
@@ -371,6 +423,256 @@ static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+};
+
+/*
+ * Cortex-A5 HW events mapping
+ */
+static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ /*
+ * The prefetch counters don't differentiate between the I
+ * side and the D side.
+ */
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+};
+
+/*
+ * Cortex-A15 HW events mapping
+ */
+static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_SPEC_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES,
+};
+
+static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DCACHE_READ_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(L1I)] = {
+ /*
+ * Not all performance counters differentiate between read
+ * and write accesses/misses so we're not always strictly
+ * correct, but it's the best we can do. Writes and reads get
+ * combined in these cases.
+ */
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L2_DCACHE_READ_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DTLB_READ_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
/*
@@ -787,7 +1089,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
if (!armpmu_event_set_period(event, hwc, idx))
continue;
- if (perf_event_overflow(event, 0, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
armpmu->disable(hwc, idx);
}
@@ -905,6 +1207,26 @@ static const struct arm_pmu *__init armv7_a9_pmu_init(void)
armv7pmu.num_events = armv7_read_num_pmnc_events();
return &armv7pmu;
}
+
+static const 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.num_events = armv7_read_num_pmnc_events();
+ return &armv7pmu;
+}
+
+static const 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.num_events = armv7_read_num_pmnc_events();
+ return &armv7pmu;
+}
#else
static const struct arm_pmu *__init armv7_a8_pmu_init(void)
{
@@ -915,4 +1237,14 @@ static const struct arm_pmu *__init armv7_a9_pmu_init(void)
{
return NULL;
}
+
+static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+{
+ return NULL;
+}
+
+static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+{
+ return NULL;
+}
#endif /* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 39affbe4fdb2..3c4397491d08 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -144,6 +144,20 @@ static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
#define XSCALE_PMU_ENABLE 0x001
@@ -251,7 +265,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
if (!armpmu_event_set_period(event, hwc, idx))
continue;
- if (perf_event_overflow(event, 0, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
armpmu->disable(hwc, idx);
}
@@ -583,7 +597,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
if (!armpmu_event_set_period(event, hwc, idx))
continue;
- if (perf_event_overflow(event, 0, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
armpmu->disable(hwc, idx);
}
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
index 2c79eec19262..2b70709376c3 100644
--- a/arch/arm/kernel/pmu.c
+++ b/arch/arm/kernel/pmu.c
@@ -17,6 +17,7 @@
#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>
@@ -25,36 +26,88 @@ static volatile long pmu_lock;
static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES];
-static int __devinit pmu_device_probe(struct platform_device *pdev)
+static int __devinit pmu_register(struct platform_device *pdev,
+ enum arm_pmu_type type)
{
-
- if (pdev->id < 0 || pdev->id >= ARM_NUM_PMU_DEVICES) {
+ if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {
pr_warning("received registration request for unknown "
- "device %d\n", pdev->id);
+ "device %d\n", type);
return -EINVAL;
}
- if (pmu_devices[pdev->id])
- pr_warning("registering new PMU device type %d overwrites "
- "previous registration!\n", pdev->id);
- else
- pr_info("registered new PMU device of type %d\n",
- pdev->id);
+ if (pmu_devices[type]) {
+ pr_warning("rejecting duplicate registration of PMU device "
+ "type %d.", type);
+ return -ENOSPC;
+ }
- pmu_devices[pdev->id] = pdev;
+ pr_info("registered new PMU device of type %d\n", type);
+ pmu_devices[type] = pdev;
return 0;
}
-static struct platform_driver pmu_driver = {
+#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 = pmu_device_probe,
+ .probe = armpmu_device_probe,
+ .id_table = armpmu_plat_device_ids,
};
static int __init register_pmu_driver(void)
{
- return platform_driver_register(&pmu_driver);
+ return platform_driver_register(&armpmu_driver);
}
device_initcall(register_pmu_driver);
@@ -77,11 +130,11 @@ reserve_pmu(enum arm_pmu_type device)
EXPORT_SYMBOL_GPL(reserve_pmu);
int
-release_pmu(struct platform_device *pdev)
+release_pmu(enum arm_pmu_type device)
{
- if (WARN_ON(pdev != pmu_devices[pdev->id]))
+ if (WARN_ON(!pmu_devices[device]))
return -EINVAL;
- clear_bit_unlock(pdev->id, &pmu_lock);
+ clear_bit_unlock(device, &pmu_lock);
return 0;
}
EXPORT_SYMBOL_GPL(release_pmu);
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 97260060bf26..2491f3b406bc 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -228,34 +228,12 @@ static struct undef_hook thumb_break_hook = {
.fn = break_trap,
};
-static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
-{
- unsigned int instr2;
- void __user *pc;
-
- /* Check the second half of the instruction. */
- pc = (void __user *)(instruction_pointer(regs) + 2);
-
- if (processor_mode(regs) == SVC_MODE) {
- instr2 = *(u16 *) pc;
- } else {
- get_user(instr2, (u16 __user *)pc);
- }
-
- if (instr2 == 0xa000) {
- ptrace_break(current, regs);
- return 0;
- } else {
- return 1;
- }
-}
-
static struct undef_hook thumb2_break_hook = {
- .instr_mask = 0xffff,
- .instr_val = 0xf7f0,
+ .instr_mask = 0xffffffff,
+ .instr_val = 0xf7f0a000,
.cpsr_mask = PSR_T_BIT,
.cpsr_val = PSR_T_BIT,
- .fn = thumb2_break_trap,
+ .fn = break_trap,
};
static int __init ptrace_break_init(void)
@@ -396,7 +374,7 @@ static long ptrace_hbp_idx_to_num(int idx)
/*
* Handle hitting a HW-breakpoint.
*/
-static void ptrace_hbptriggered(struct perf_event *bp, int unused,
+static void ptrace_hbptriggered(struct perf_event *bp,
struct perf_sample_data *data,
struct pt_regs *regs)
{
@@ -479,7 +457,8 @@ static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
attr.bp_type = type;
attr.disabled = 1;
- return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, tsk);
+ return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL,
+ tsk);
}
static int ptrace_gethbpregs(struct task_struct *tsk, long num,
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index acbb447ac6b5..70bca649e925 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -343,54 +343,6 @@ static void __init feat_v6_fixup(void)
elf_hwcap &= ~HWCAP_TLS;
}
-static void __init setup_processor(void)
-{
- struct proc_info_list *list;
-
- /*
- * locate processor in the list of supported processor
- * types. The linker builds this table for us from the
- * entries in arch/arm/mm/proc-*.S
- */
- list = lookup_processor_type(read_cpuid_id());
- if (!list) {
- printk("CPU configuration botched (ID %08x), unable "
- "to continue.\n", read_cpuid_id());
- while (1);
- }
-
- cpu_name = list->cpu_name;
-
-#ifdef MULTI_CPU
- processor = *list->proc;
-#endif
-#ifdef MULTI_TLB
- cpu_tlb = *list->tlb;
-#endif
-#ifdef MULTI_USER
- cpu_user = *list->user;
-#endif
-#ifdef MULTI_CACHE
- cpu_cache = *list->cache;
-#endif
-
- printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
- cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
- proc_arch[cpu_architecture()], cr_alignment);
-
- sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
- sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
- elf_hwcap = list->elf_hwcap;
-#ifndef CONFIG_ARM_THUMB
- elf_hwcap &= ~HWCAP_THUMB;
-#endif
-
- feat_v6_fixup();
-
- cacheid_init();
- cpu_proc_init();
-}
-
/*
* cpu_init - initialise one CPU.
*
@@ -406,6 +358,8 @@ void cpu_init(void)
BUG();
}
+ cpu_proc_init();
+
/*
* Define the placement constraint for the inline asm directive below.
* In Thumb-2, msr with an immediate value is not allowed.
@@ -442,6 +396,54 @@ void cpu_init(void)
: "r14");
}
+static void __init setup_processor(void)
+{
+ struct proc_info_list *list;
+
+ /*
+ * locate processor in the list of supported processor
+ * types. The linker builds this table for us from the
+ * entries in arch/arm/mm/proc-*.S
+ */
+ list = lookup_processor_type(read_cpuid_id());
+ if (!list) {
+ printk("CPU configuration botched (ID %08x), unable "
+ "to continue.\n", read_cpuid_id());
+ while (1);
+ }
+
+ cpu_name = list->cpu_name;
+
+#ifdef MULTI_CPU
+ processor = *list->proc;
+#endif
+#ifdef MULTI_TLB
+ cpu_tlb = *list->tlb;
+#endif
+#ifdef MULTI_USER
+ cpu_user = *list->user;
+#endif
+#ifdef MULTI_CACHE
+ cpu_cache = *list->cache;
+#endif
+
+ printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
+ cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
+ proc_arch[cpu_architecture()], cr_alignment);
+
+ sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
+ sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
+ elf_hwcap = list->elf_hwcap;
+#ifndef CONFIG_ARM_THUMB
+ elf_hwcap &= ~HWCAP_THUMB;
+#endif
+
+ feat_v6_fixup();
+
+ cacheid_init();
+ cpu_init();
+}
+
void __init dump_machine_table(void)
{
struct machine_desc *p;
@@ -915,9 +917,14 @@ void __init setup_arch(char **cmdline_p)
#endif
reserve_crashkernel();
- cpu_init();
tcm_init();
+#ifdef CONFIG_ZONE_DMA
+ if (mdesc->dma_zone_size) {
+ extern unsigned long arm_dma_zone_size;
+ arm_dma_zone_size = mdesc->dma_zone_size;
+ }
+#endif
#ifdef CONFIG_MULTI_IRQ_HANDLER
handle_arch_irq = mdesc->handle_irq;
#endif
@@ -979,6 +986,10 @@ static const char *hwcap_str[] = {
"neon",
"vfpv3",
"vfpv3d16",
+ "tls",
+ "vfpv4",
+ "idiva",
+ "idivt",
NULL
};
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 6398ead9d1c0..dc902f2c6845 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -10,64 +10,61 @@
/*
* Save CPU state for a suspend
* r1 = v:p offset
- * r3 = virtual return function
- * Note: sp is decremented to allocate space for CPU state on stack
- * r0-r3,r9,r10,lr corrupted
+ * r2 = suspend function arg0
+ * r3 = suspend function
*/
-ENTRY(cpu_suspend)
- mov r9, lr
+ENTRY(__cpu_suspend)
+ stmfd sp!, {r4 - r11, lr}
#ifdef MULTI_CPU
ldr r10, =processor
- mov r2, sp @ current virtual SP
- ldr r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
+ ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
ldr ip, [r10, #CPU_DO_RESUME] @ virtual resume function
- sub sp, sp, r0 @ allocate CPU state on stack
- mov r0, sp @ save pointer
+#else
+ ldr r5, =cpu_suspend_size
+ ldr ip, =cpu_do_resume
+#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, r2, r3, ip} @ save v:p, virt SP, retfn, phys resume fn
- ldr r3, =sleep_save_sp
- add r2, sp, r1 @ convert SP 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
#ifdef CONFIG_SMP
ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
ALT_UP(mov lr, #0)
and lr, lr, #15
- str r2, [r3, lr, lsl #2] @ save phys SP
+ str r6, [r5, lr, lsl #2] @ save phys SP
#else
- str r2, [r3] @ save phys SP
+ str r6, [r5] @ save phys SP
#endif
+#ifdef MULTI_CPU
mov lr, pc
ldr pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
#else
- mov r2, sp @ current virtual SP
- ldr r0, =cpu_suspend_size
- sub sp, sp, r0 @ allocate CPU state on stack
- mov r0, sp @ save pointer
- stmfd sp!, {r1, r2, r3} @ save v:p, virt SP, return fn
- ldr r3, =sleep_save_sp
- add r2, sp, r1 @ convert SP to phys
-#ifdef CONFIG_SMP
- ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
- ALT_UP(mov lr, #0)
- and lr, lr, #15
- str r2, [r3, lr, lsl #2] @ save phys SP
-#else
- str r2, [r3] @ save phys SP
-#endif
bl cpu_do_suspend
#endif
@ flush data cache
#ifdef MULTI_CACHE
ldr r10, =cpu_cache
- mov lr, r9
+ mov lr, pc
ldr pc, [r10, #CACHE_FLUSH_KERN_ALL]
#else
- mov lr, r9
- b __cpuc_flush_kern_all
+ bl __cpuc_flush_kern_all
#endif
-ENDPROC(cpu_suspend)
+ 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
+ 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)
@@ -97,7 +94,9 @@ ENDPROC(cpu_resume_turn_mmu_on)
cpu_resume_after_mmu:
str r5, [r2, r4, lsl #2] @ restore old mapping
mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
- mov pc, lr
+ bl cpu_init @ restore the und/abt/irq banked regs
+ mov r0, #0 @ return zero on success
+ ldmfd sp!, {r4 - r11, pc}
ENDPROC(cpu_resume_after_mmu)
/*
@@ -120,20 +119,11 @@ 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
-#ifdef MULTI_CPU
- @ load v:p, stack, return fn, resume fn
- ARM( ldmia r0!, {r1, sp, lr, pc} )
-THUMB( ldmia r0!, {r1, r2, r3, r4} )
+ @ load v:p, stack, resume fn
+ ARM( ldmia r0!, {r1, sp, pc} )
+THUMB( ldmia r0!, {r1, r2, r3} )
THUMB( mov sp, r2 )
-THUMB( mov lr, r3 )
-THUMB( bx r4 )
-#else
- @ load v:p, stack, return fn
- ARM( ldmia r0!, {r1, sp, lr} )
-THUMB( ldmia r0!, {r1, r2, lr} )
-THUMB( mov sp, r2 )
- b cpu_do_resume
-#endif
+THUMB( bx r3 )
ENDPROC(cpu_resume)
sleep_save_sp:
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e7f92a4321f3..d88ff0230e82 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -27,7 +27,7 @@
#include <linux/clockchips.h>
#include <linux/completion.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/cputype.h>
@@ -365,8 +365,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
*/
if (max_cpus > ncores)
max_cpus = ncores;
-
- if (max_cpus > 1) {
+ if (ncores > 1 && max_cpus) {
/*
* Enable the local timer or broadcast device for the
* boot CPU, but only if we have more than one CPU.
@@ -374,6 +373,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
percpu_timer_setup();
/*
+ * Initialise the present map, which describes the set of CPUs
+ * actually populated at the present time. A platform should
+ * re-initialize the map in platform_smp_prepare_cpus() if
+ * present != possible (e.g. physical hotplug).
+ */
+ init_cpu_present(&cpu_possible_map);
+
+ /*
* Initialise the SCU if there are more than one CPU
* and let them know where to start.
*/
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index a1e757c3439b..79ed5e7f204a 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -20,6 +20,7 @@
#define SCU_INVALIDATE 0x0c
#define SCU_FPGA_REVISION 0x10
+#ifdef CONFIG_SMP
/*
* Get the number of CPU cores from the SCU configuration
*/
@@ -50,6 +51,7 @@ void __init scu_enable(void __iomem *scu_base)
*/
flush_cache_all();
}
+#endif
/*
* Set the executing CPUs power mode as defined. This will be in
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 40ee7e5045e4..5f452f8fde05 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -183,7 +183,7 @@ static int swp_handler(struct pt_regs *regs, unsigned int instr)
unsigned int address, destreg, data, type;
unsigned int res = 0;
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->ARM_pc);
if (current->pid != previous_pid) {
pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c
index f5cf660eefcc..30e302d33e0a 100644
--- a/arch/arm/kernel/tcm.c
+++ b/arch/arm/kernel/tcm.c
@@ -19,6 +19,8 @@
#include "tcm.h"
static struct gen_pool *tcm_pool;
+static bool dtcm_present;
+static bool itcm_present;
/* TCM section definitions from the linker */
extern char __itcm_start, __sitcm_text, __eitcm_text;
@@ -90,6 +92,18 @@ void tcm_free(void *addr, size_t len)
}
EXPORT_SYMBOL(tcm_free);
+bool tcm_dtcm_present(void)
+{
+ return dtcm_present;
+}
+EXPORT_SYMBOL(tcm_dtcm_present);
+
+bool tcm_itcm_present(void)
+{
+ return itcm_present;
+}
+EXPORT_SYMBOL(tcm_itcm_present);
+
static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
u32 *offset)
{
@@ -134,6 +148,10 @@ static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
(tcm_region & 1) ? "" : "not ");
}
+ /* Not much fun you can do with a size 0 bank */
+ if (tcm_size == 0)
+ return 0;
+
/* Force move the TCM bank to where we want it, enable */
tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1;
@@ -165,12 +183,20 @@ void __init tcm_init(void)
u32 tcm_status = read_cpuid_tcmstatus();
u8 dtcm_banks = (tcm_status >> 16) & 0x03;
u8 itcm_banks = (tcm_status & 0x03);
+ size_t dtcm_code_sz = &__edtcm_data - &__sdtcm_data;
+ size_t itcm_code_sz = &__eitcm_text - &__sitcm_text;
char *start;
char *end;
char *ram;
int ret;
int i;
+ /* Values greater than 2 for D/ITCM banks are "reserved" */
+ if (dtcm_banks > 2)
+ dtcm_banks = 0;
+ if (itcm_banks > 2)
+ itcm_banks = 0;
+
/* Setup DTCM if present */
if (dtcm_banks > 0) {
for (i = 0; i < dtcm_banks; i++) {
@@ -178,6 +204,13 @@ void __init tcm_init(void)
if (ret)
return;
}
+ /* This means you compiled more code than fits into DTCM */
+ if (dtcm_code_sz > (dtcm_end - DTCM_OFFSET)) {
+ pr_info("CPU DTCM: %u bytes of code compiled to "
+ "DTCM but only %lu bytes of DTCM present\n",
+ dtcm_code_sz, (dtcm_end - DTCM_OFFSET));
+ goto no_dtcm;
+ }
dtcm_res.end = dtcm_end - 1;
request_resource(&iomem_resource, &dtcm_res);
dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET;
@@ -186,12 +219,16 @@ void __init tcm_init(void)
start = &__sdtcm_data;
end = &__edtcm_data;
ram = &__dtcm_start;
- /* This means you compiled more code than fits into DTCM */
- BUG_ON((end - start) > (dtcm_end - DTCM_OFFSET));
- memcpy(start, ram, (end-start));
- pr_debug("CPU DTCM: copied data from %p - %p\n", start, end);
+ memcpy(start, ram, dtcm_code_sz);
+ pr_debug("CPU DTCM: copied data from %p - %p\n",
+ start, end);
+ dtcm_present = true;
+ } else if (dtcm_code_sz) {
+ pr_info("CPU DTCM: %u bytes of code compiled to DTCM but no "
+ "DTCM banks present in CPU\n", dtcm_code_sz);
}
+no_dtcm:
/* Setup ITCM if present */
if (itcm_banks > 0) {
for (i = 0; i < itcm_banks; i++) {
@@ -199,6 +236,13 @@ void __init tcm_init(void)
if (ret)
return;
}
+ /* This means you compiled more code than fits into ITCM */
+ if (itcm_code_sz > (itcm_end - ITCM_OFFSET)) {
+ pr_info("CPU ITCM: %u bytes of code compiled to "
+ "ITCM but only %lu bytes of ITCM present\n",
+ itcm_code_sz, (itcm_end - ITCM_OFFSET));
+ return;
+ }
itcm_res.end = itcm_end - 1;
request_resource(&iomem_resource, &itcm_res);
itcm_iomap[0].length = itcm_end - ITCM_OFFSET;
@@ -207,10 +251,13 @@ void __init tcm_init(void)
start = &__sitcm_text;
end = &__eitcm_text;
ram = &__itcm_start;
- /* This means you compiled more code than fits into ITCM */
- BUG_ON((end - start) > (itcm_end - ITCM_OFFSET));
- memcpy(start, ram, (end-start));
- pr_debug("CPU ITCM: copied code from %p - %p\n", start, end);
+ memcpy(start, ram, itcm_code_sz);
+ pr_debug("CPU ITCM: copied code from %p - %p\n",
+ start, end);
+ itcm_present = true;
+ } else if (itcm_code_sz) {
+ pr_info("CPU ITCM: %u bytes of code compiled to ITCM but no "
+ "ITCM banks present in CPU\n", itcm_code_sz);
}
}
@@ -221,7 +268,6 @@ void __init tcm_init(void)
*/
static int __init setup_tcm_pool(void)
{
- u32 tcm_status = read_cpuid_tcmstatus();
u32 dtcm_pool_start = (u32) &__edtcm_data;
u32 itcm_pool_start = (u32) &__eitcm_text;
int ret;
@@ -236,7 +282,7 @@ static int __init setup_tcm_pool(void)
pr_debug("Setting up TCM memory pool\n");
/* Add the rest of DTCM to the TCM pool */
- if (tcm_status & (0x03 << 16)) {
+ if (dtcm_present) {
if (dtcm_pool_start < dtcm_end) {
ret = gen_pool_add(tcm_pool, dtcm_pool_start,
dtcm_end - dtcm_pool_start, -1);
@@ -253,7 +299,7 @@ static int __init setup_tcm_pool(void)
}
/* Add the rest of ITCM to the TCM pool */
- if (tcm_status & 0x03) {
+ if (itcm_present) {
if (itcm_pool_start < itcm_end) {
ret = gen_pool_add(tcm_pool, itcm_pool_start,
itcm_end - itcm_pool_start, -1);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6807cb1e76dd..bc9f9da782cb 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -25,7 +25,7 @@
#include <linux/init.h>
#include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/system.h>
#include <asm/unistd.h>
@@ -355,9 +355,24 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
pc = (void __user *)instruction_pointer(regs);
if (processor_mode(regs) == SVC_MODE) {
- instr = *(u32 *) pc;
+#ifdef CONFIG_THUMB2_KERNEL
+ if (thumb_mode(regs)) {
+ instr = ((u16 *)pc)[0];
+ if (is_wide_instruction(instr)) {
+ instr <<= 16;
+ instr |= ((u16 *)pc)[1];
+ }
+ } else
+#endif
+ instr = *(u32 *) pc;
} else if (thumb_mode(regs)) {
get_user(instr, (u16 __user *)pc);
+ if (is_wide_instruction(instr)) {
+ unsigned int instr2;
+ get_user(instr2, (u16 __user *)pc+1);
+ instr <<= 16;
+ instr |= instr2;
+ }
} else {
get_user(instr, (u32 __user *)pc);
}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index e5287f21badc..bf977f8514f6 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -38,57 +38,6 @@ jiffies = jiffies_64 + 4;
SECTIONS
{
-#ifdef CONFIG_XIP_KERNEL
- . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
-#else
- . = PAGE_OFFSET + TEXT_OFFSET;
-#endif
-
- .init : { /* Init code and data */
- _stext = .;
- _sinittext = .;
- HEAD_TEXT
- INIT_TEXT
- ARM_EXIT_KEEP(EXIT_TEXT)
- _einittext = .;
- ARM_CPU_DISCARD(PROC_INFO)
- __arch_info_begin = .;
- *(.arch.info.init)
- __arch_info_end = .;
- __tagtable_begin = .;
- *(.taglist.init)
- __tagtable_end = .;
-#ifdef CONFIG_SMP_ON_UP
- __smpalt_begin = .;
- *(.alt.smp.init)
- __smpalt_end = .;
-#endif
-
- __pv_table_begin = .;
- *(.pv_table)
- __pv_table_end = .;
-
- INIT_SETUP(16)
-
- INIT_CALLS
- CON_INITCALL
- SECURITY_INITCALL
- INIT_RAM_FS
-
-#ifndef CONFIG_XIP_KERNEL
- __init_begin = _stext;
- INIT_DATA
- ARM_EXIT_KEEP(EXIT_DATA)
-#endif
- }
-
- PERCPU_SECTION(32)
-
-#ifndef CONFIG_XIP_KERNEL
- . = ALIGN(PAGE_SIZE);
- __init_end = .;
-#endif
-
/*
* unwind exit sections must be discarded before the rest of the
* unwind sections get included.
@@ -106,10 +55,22 @@ SECTIONS
*(.fixup)
*(__ex_table)
#endif
+#ifndef CONFIG_SMP_ON_UP
+ *(.alt.smp.init)
+#endif
}
+#ifdef CONFIG_XIP_KERNEL
+ . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
+#else
+ . = PAGE_OFFSET + TEXT_OFFSET;
+#endif
+ .head.text : {
+ _text = .;
+ HEAD_TEXT
+ }
.text : { /* Real text segment */
- _text = .; /* Text and read-only data */
+ _stext = .; /* Text and read-only data */
__exception_text_start = .;
*(.exception.text)
__exception_text_end = .;
@@ -122,8 +83,6 @@ SECTIONS
*(.fixup)
#endif
*(.gnu.warning)
- *(.rodata)
- *(.rodata.*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
@@ -152,10 +111,63 @@ SECTIONS
_etext = .; /* End of text and rodata section */
+#ifndef CONFIG_XIP_KERNEL
+ . = ALIGN(PAGE_SIZE);
+ __init_begin = .;
+#endif
+
+ INIT_TEXT_SECTION(8)
+ .exit.text : {
+ ARM_EXIT_KEEP(EXIT_TEXT)
+ }
+ .init.proc.info : {
+ ARM_CPU_DISCARD(PROC_INFO)
+ }
+ .init.arch.info : {
+ __arch_info_begin = .;
+ *(.arch.info.init)
+ __arch_info_end = .;
+ }
+ .init.tagtable : {
+ __tagtable_begin = .;
+ *(.taglist.init)
+ __tagtable_end = .;
+ }
+#ifdef CONFIG_SMP_ON_UP
+ .init.smpalt : {
+ __smpalt_begin = .;
+ *(.alt.smp.init)
+ __smpalt_end = .;
+ }
+#endif
+ .init.pv_table : {
+ __pv_table_begin = .;
+ *(.pv_table)
+ __pv_table_end = .;
+ }
+ .init.data : {
+#ifndef CONFIG_XIP_KERNEL
+ INIT_DATA
+#endif
+ INIT_SETUP(16)
+ INIT_CALLS
+ CON_INITCALL
+ SECURITY_INITCALL
+ INIT_RAM_FS
+ }
+#ifndef CONFIG_XIP_KERNEL
+ .exit.data : {
+ ARM_EXIT_KEEP(EXIT_DATA)
+ }
+#endif
+
+ PERCPU_SECTION(32)
+
#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
. = PAGE_OFFSET + TEXT_OFFSET;
#else
+ __init_end = .;
. = ALIGN(THREAD_SIZE);
__data_loc = .;
#endif
@@ -270,12 +282,6 @@ SECTIONS
/* Default discards */
DISCARDS
-
-#ifndef CONFIG_SMP_ON_UP
- /DISCARD/ : {
- *(.alt.smp.init)
- }
-#endif
}
/*
diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S
index 8678eb2b7a60..e6057fa851bb 100644
--- a/arch/arm/lib/ecard.S
+++ b/arch/arm/lib/ecard.S
@@ -12,7 +12,6 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <mach/hardware.h>
#define CPSR2SPSR(rt) \
mrs rt, cpsr; \
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
index 9aaf7c72065d..88487c8c4f23 100644
--- a/arch/arm/lib/io-readsw-armv3.S
+++ b/arch/arm/lib/io-readsw-armv3.S
@@ -9,7 +9,6 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <mach/hardware.h>
.Linsw_bad_alignment:
adr r0, .Linsw_bad_align_msg
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
index cd34503e424d..49b800419e32 100644
--- a/arch/arm/lib/io-writesw-armv3.S
+++ b/arch/arm/lib/io-writesw-armv3.S
@@ -9,7 +9,6 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <mach/hardware.h>
.Loutsw_bad_alignment:
adr r0, .Loutsw_bad_align_msg
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 5004bf0a05f2..0f917928eeb7 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -525,7 +525,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
if (ARRAY_SIZE(lcdc_resources) > 2) {
void __iomem *fb;
struct resource *fb_res = &lcdc_resources[2];
- size_t fb_len = fb_res->end - fb_res->start + 1;
+ size_t fb_len = resource_size(fb_res);
fb = ioremap(fb_res->start, fb_len);
if (fb) {
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 3eb0a1153cc8..6010ce16b3cf 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Bluewater System Ltd
*
* Author: Andre Renaud <andre@bluewatersys.com>
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
*
* This 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/arch/arm/mach-at91/include/mach/clkdev.h b/arch/arm/mach-at91/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-at91/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index ea53f4d9b283..4159eca78945 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -20,7 +20,7 @@
#include <linux/io.h>
#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c
index d87ad30dda35..0ca00050666a 100644
--- a/arch/arm/mach-bcmring/dma.c
+++ b/arch/arm/mach-bcmring/dma.c
@@ -34,7 +34,7 @@
#include <linux/mm.h>
#include <linux/pfn.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <mach/dma.h>
/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
@@ -835,7 +835,7 @@ int dma_init(void)
/* Create /proc/dma/channels and /proc/dma/devices */
- gDmaDir = create_proc_entry("dma", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+ gDmaDir = proc_mkdir("dma", NULL);
if (gDmaDir == NULL) {
printk(KERN_ERR "Unable to create /proc/dma\n");
diff --git a/arch/arm/mach-bcmring/include/mach/clkdev.h b/arch/arm/mach-bcmring/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-bcmring/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-bcmring/include/mach/entry-macro.S b/arch/arm/mach-bcmring/include/mach/entry-macro.S
index 7d393ca010ac..94c950d783ba 100644
--- a/arch/arm/mach-bcmring/include/mach/entry-macro.S
+++ b/arch/arm/mach-bcmring/include/mach/entry-macro.S
@@ -80,7 +80,3 @@
.macro arch_ret_to_user, tmp1, tmp2
.endm
-
- .macro irq_prio_table
- .endm
-
diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h
index 8bf3564fba50..ed78aabb8e9f 100644
--- a/arch/arm/mach-bcmring/include/mach/hardware.h
+++ b/arch/arm/mach-bcmring/include/mach/hardware.h
@@ -36,8 +36,6 @@
#define RAM_SIZE (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
#define RAM_BASE PAGE_OFFSET
-#define pcibios_assign_all_busses() 1
-
/* Macros to make managing spinlocks a bit more controlled in terms of naming. */
/* See reg_gpio.h, reg_irq.h, arch.c, gpio.c for example usage. */
#if defined(__KERNEL__)
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 08e5c8759502..3e7d1496cb47 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -29,7 +29,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
-#include <mach/hardware.h>
#include <mach/cns3xxx.h>
#include <mach/irqs.h>
#include "core.h"
@@ -170,6 +169,8 @@ static struct platform_device *cns3420_pdevs[] __initdata = {
static void __init cns3420_init(void)
{
+ cns3xxx_l2x0_init();
+
platform_add_devices(cns3420_pdevs, ARRAY_SIZE(cns3420_pdevs));
cns3xxx_ahci_init();
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index da30078a80c1..941a308e1253 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -16,6 +16,7 @@
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
#include <mach/cns3xxx.h>
#include "core.h"
@@ -244,3 +245,45 @@ static void __init cns3xxx_timer_init(void)
struct sys_timer cns3xxx_timer = {
.init = cns3xxx_timer_init,
};
+
+#ifdef CONFIG_CACHE_L2X0
+
+void __init cns3xxx_l2x0_init(void)
+{
+ void __iomem *base = ioremap(CNS3XXX_L2C_BASE, SZ_4K);
+ u32 val;
+
+ if (WARN_ON(!base))
+ return;
+
+ /*
+ * Tag RAM Control register
+ *
+ * bit[10:8] - 1 cycle of write accesses latency
+ * bit[6:4] - 1 cycle of read accesses latency
+ * bit[3:0] - 1 cycle of setup latency
+ *
+ * 1 cycle of latency for setup, read and write accesses
+ */
+ val = readl(base + L2X0_TAG_LATENCY_CTRL);
+ val &= 0xfffff888;
+ writel(val, base + L2X0_TAG_LATENCY_CTRL);
+
+ /*
+ * Data RAM Control register
+ *
+ * bit[10:8] - 1 cycles of write accesses latency
+ * bit[6:4] - 1 cycles of read accesses latency
+ * bit[3:0] - 1 cycle of setup latency
+ *
+ * 1 cycle of latency for setup, read and write accesses
+ */
+ val = readl(base + L2X0_DATA_LATENCY_CTRL);
+ val &= 0xfffff888;
+ writel(val, base + L2X0_DATA_LATENCY_CTRL);
+
+ /* 32 KiB, 8-way, parity disable */
+ l2x0_init(base, 0x00540000, 0xfe000fff);
+}
+
+#endif /* CONFIG_CACHE_L2X0 */
diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h
index ffeb3a8b73ba..fcd225343c61 100644
--- a/arch/arm/mach-cns3xxx/core.h
+++ b/arch/arm/mach-cns3xxx/core.h
@@ -13,6 +13,12 @@
extern struct sys_timer cns3xxx_timer;
+#ifdef CONFIG_CACHE_L2X0
+void __init cns3xxx_l2x0_init(void);
+#else
+static inline void cns3xxx_l2x0_init(void) {}
+#endif /* CONFIG_CACHE_L2X0 */
+
void __init cns3xxx_map_io(void);
void __init cns3xxx_init_irq(void);
void cns3xxx_power_off(void);
diff --git a/arch/arm/mach-cns3xxx/include/mach/hardware.h b/arch/arm/mach-cns3xxx/include/mach/hardware.h
deleted file mode 100644
index 57e09836f9d7..000000000000
--- a/arch/arm/mach-cns3xxx/include/mach/hardware.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * This file contains the hardware definitions of the Cavium Networks boards.
- *
- * 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_HARDWARE_H
-#define __MACH_HARDWARE_H
-
-#include <asm/sizes.h>
-
-/* macro to get at IO space when running virtually */
-#define PCIBIOS_MIN_IO 0x00000000
-#define PCIBIOS_MIN_MEM 0x00000000
-#define pcibios_assign_all_busses() 1
-
-#endif
diff --git a/arch/arm/mach-cns3xxx/include/mach/pm.h b/arch/arm/mach-cns3xxx/include/mach/pm.h
index 6eae7f764d1d..c2588cc991d1 100644
--- a/arch/arm/mach-cns3xxx/include/mach/pm.h
+++ b/arch/arm/mach-cns3xxx/include/mach/pm.h
@@ -11,7 +11,7 @@
#ifndef __CNS3XXX_PM_H
#define __CNS3XXX_PM_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
void cns3xxx_pwr_clk_en(unsigned int block);
void cns3xxx_pwr_clk_dis(unsigned int block);
diff --git a/arch/arm/mach-cns3xxx/include/mach/vmalloc.h b/arch/arm/mach-cns3xxx/include/mach/vmalloc.h
index 4d381ec05278..1dd231d2f772 100644
--- a/arch/arm/mach-cns3xxx/include/mach/vmalloc.h
+++ b/arch/arm/mach-cns3xxx/include/mach/vmalloc.h
@@ -8,4 +8,4 @@
* published by the Free Software Foundation.
*/
-#define VMALLOC_END 0xd8000000
+#define VMALLOC_END 0xd8000000UL
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 78defd71a829..a4ec080908b8 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -369,6 +369,9 @@ static int __init cns3xxx_pcie_init(void)
{
int i;
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0;
+
hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, 0,
"imprecise external abort");
diff --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c
index 5e579552aa54..0c04678615ce 100644
--- a/arch/arm/mach-cns3xxx/pm.c
+++ b/arch/arm/mach-cns3xxx/pm.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <mach/system.h>
#include <mach/cns3xxx.h>
#include <mach/pm.h>
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 8bc3701aa05c..84fd78684868 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -681,4 +681,5 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
.init_irq = cp_intc_init,
.timer = &davinci_timer,
.init_machine = da830_evm_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index a7b41bf505f1..bd5394537c88 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1117,6 +1117,8 @@ static __init int da850_evm_init_cpufreq(void)
static __init int da850_evm_init_cpufreq(void) { return 0; }
#endif
+#define DA850EVM_SATA_REFCLKPN_RATE (100 * 1000 * 1000)
+
static __init void da850_evm_init(void)
{
int ret;
@@ -1237,6 +1239,11 @@ static __init void da850_evm_init(void)
if (ret)
pr_warning("da850_evm_init: spi 1 registration failed: %d\n",
ret);
+
+ ret = da850_register_sata(DA850EVM_SATA_REFCLKPN_RATE);
+ if (ret)
+ pr_warning("da850_evm_init: sata registration failed: %d\n",
+ ret);
}
#ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -1261,4 +1268,5 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
.init_irq = cp_intc_init,
.timer = &davinci_timer,
.init_machine = da850_evm_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 6e7cad13352c..241a6bd67408 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -356,4 +356,5 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = dm355_evm_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 543f9911b281..bee284ca7fd6 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -275,4 +275,5 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = dm355_leopard_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 09a87e61ffcf..9818f214d4f0 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -617,5 +617,6 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = dm365_evm_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 556bbd468db3..95607a191e03 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -717,4 +717,5 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = davinci_evm_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index f6ac9ba74878..993a3146fd35 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -719,9 +719,15 @@ static void __init cdce_clk_init(void)
}
}
+#define DM6467T_EVM_REF_FREQ 33000000
+
static void __init davinci_map_io(void)
{
dm646x_init();
+
+ if (machine_is_davinci_dm6467tevm())
+ davinci_set_refclk_rate(DM6467T_EVM_REF_FREQ);
+
cdce_clk_init();
}
@@ -785,23 +791,13 @@ static __init void evm_init(void)
soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID;
}
-#define DM646X_EVM_REF_FREQ 27000000
-#define DM6467T_EVM_REF_FREQ 33000000
-
-void __init dm646x_board_setup_refclk(struct clk *clk)
-{
- if (machine_is_davinci_dm6467tevm())
- clk->rate = DM6467T_EVM_REF_FREQ;
- else
- clk->rate = DM646X_EVM_REF_FREQ;
-}
-
MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
.boot_params = (0x80000100),
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = evm_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
@@ -810,5 +806,6 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = evm_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 606a6f27ed6c..c278226627ad 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -20,6 +20,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
+#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/common.h>
@@ -570,4 +571,5 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
.init_irq = cp_intc_init,
.timer = &davinci_timer,
.init_machine = mityomapl138_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 3e7be2de96de..d60a80028ba3 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -277,4 +277,5 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = davinci_ntosd2_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 67c38d0ecd10..237332a11421 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -343,4 +343,5 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
.init_irq = cp_intc_init,
.timer = &davinci_timer,
.init_machine = omapl138_hawk_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 61ac96d8f00d..5f4385c0a089 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -156,4 +156,5 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = davinci_sffsdr_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index 1a656e882262..782892065682 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -282,4 +282,5 @@ MACHINE_START(TNETV107X, "TNETV107X EVM")
.init_irq = cp_intc_init,
.timer = &davinci_timer,
.init_machine = tnetv107x_evm_board_init,
+ .dma_zone_size = SZ_128M,
MACHINE_END
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index e4e3af179f02..00861139101d 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -44,7 +44,7 @@ static void __clk_enable(struct clk *clk)
__clk_enable(clk->parent);
if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc,
- PSC_STATE_ENABLE);
+ true, clk->flags);
}
static void __clk_disable(struct clk *clk)
@@ -54,8 +54,7 @@ static void __clk_disable(struct clk *clk)
if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) &&
(clk->flags & CLK_PSC))
davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc,
- (clk->flags & PSC_SWRSTDISABLE) ?
- PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE);
+ false, clk->flags);
if (clk->parent)
__clk_disable(clk->parent);
}
@@ -239,8 +238,7 @@ static int __init clk_disable_unused(void)
pr_debug("Clocks: disable unused %s\n", ck->name);
davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
- (ck->flags & PSC_SWRSTDISABLE) ?
- PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE);
+ false, ck->flags);
}
spin_unlock_irq(&clockfw_lock);
@@ -368,6 +366,12 @@ static unsigned long clk_leafclk_recalc(struct clk *clk)
return clk->parent->rate;
}
+int davinci_simple_set_rate(struct clk *clk, unsigned long rate)
+{
+ clk->rate = rate;
+ return 0;
+}
+
static unsigned long clk_pllclk_recalc(struct clk *clk)
{
u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
@@ -506,6 +510,38 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
}
EXPORT_SYMBOL(davinci_set_pllrate);
+/**
+ * davinci_set_refclk_rate() - Set the reference clock rate
+ * @rate: The new rate.
+ *
+ * Sets the reference clock rate to a given value. This will most likely
+ * result in the entire clock tree getting updated.
+ *
+ * This is used to support boards which use a reference clock different
+ * than that used by default in <soc>.c file. The reference clock rate
+ * should be updated early in the boot process; ideally soon after the
+ * clock tree has been initialized once with the default reference clock
+ * rate (davinci_common_init()).
+ *
+ * Returns 0 on success, error otherwise.
+ */
+int davinci_set_refclk_rate(unsigned long rate)
+{
+ struct clk *refclk;
+
+ refclk = clk_get(NULL, "ref");
+ if (IS_ERR(refclk)) {
+ pr_err("%s: failed to get reference clock.\n", __func__);
+ return PTR_ERR(refclk);
+ }
+
+ clk_set_rate(refclk, rate);
+
+ clk_put(refclk);
+
+ return 0;
+}
+
int __init davinci_clk_init(struct clk_lookup *clocks)
{
struct clk_lookup *c;
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index 0dd22031ec62..a705f367a84d 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -111,6 +111,7 @@ struct clk {
#define CLK_PLL BIT(4) /* PLL-derived clock */
#define PRE_PLL BIT(5) /* source is before PLL mult/div */
#define PSC_SWRSTDISABLE BIT(6) /* Disable state is SwRstDisable */
+#define PSC_FORCE BIT(7) /* Force module state transtition */
#define CLK(dev, con, ck) \
{ \
@@ -123,6 +124,8 @@ int davinci_clk_init(struct clk_lookup *clocks);
int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
unsigned int mult, unsigned int postdiv);
int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
+int davinci_set_refclk_rate(unsigned long rate);
+int davinci_simple_set_rate(struct clk *clk, unsigned long rate);
extern struct platform_device davinci_wdt_device;
extern void davinci_watchdog_reset(struct platform_device *);
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 133aac405853..935dbed5c541 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -58,6 +58,7 @@ static struct pll_data pll0_data = {
static struct clk ref_clk = {
.name = "ref_clk",
.rate = DA850_REF_FREQ,
+ .set_rate = davinci_simple_set_rate,
};
static struct clk pll0_clk = {
@@ -373,6 +374,14 @@ static struct clk spi1_clk = {
.flags = DA850_CLK_ASYNC3,
};
+static struct clk sata_clk = {
+ .name = "sata",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA850_LPSC1_SATA,
+ .gpsc = 1,
+ .flags = PSC_FORCE,
+};
+
static struct clk_lookup da850_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll0", &pll0_clk),
@@ -419,6 +428,7 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "usb20", &usb20_clk),
CLK("spi_davinci.0", NULL, &spi0_clk),
CLK("spi_davinci.1", NULL, &spi1_clk),
+ CLK("ahci", NULL, &sata_clk),
CLK(NULL, NULL, NULL),
};
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index fc4e98ea7543..2f7e719636f1 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -14,6 +14,8 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
+#include <linux/ahci_platform.h>
+#include <linux/clk.h>
#include <mach/cputype.h>
#include <mach/common.h>
@@ -33,6 +35,7 @@
#define DA8XX_SPI0_BASE 0x01c41000
#define DA830_SPI1_BASE 0x01e12000
#define DA8XX_LCD_CNTRL_BASE 0x01e13000
+#define DA850_SATA_BASE 0x01e18000
#define DA850_MMCSD1_BASE 0x01e1b000
#define DA8XX_EMAC_CPPI_PORT_BASE 0x01e20000
#define DA8XX_EMAC_CPGMACSS_BASE 0x01e22000
@@ -842,3 +845,126 @@ int __init da8xx_register_spi(int instance, struct spi_board_info *info,
return platform_device_register(&da8xx_spi_device[instance]);
}
+
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+
+static struct resource da850_sata_resources[] = {
+ {
+ .start = DA850_SATA_BASE,
+ .end = DA850_SATA_BASE + 0x1fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_DA850_SATAINT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* SATA PHY Control Register offset from AHCI base */
+#define SATA_P0PHYCR_REG 0x178
+
+#define SATA_PHY_MPY(x) ((x) << 0)
+#define SATA_PHY_LOS(x) ((x) << 6)
+#define SATA_PHY_RXCDR(x) ((x) << 10)
+#define SATA_PHY_RXEQ(x) ((x) << 13)
+#define SATA_PHY_TXSWING(x) ((x) << 19)
+#define SATA_PHY_ENPLL(x) ((x) << 31)
+
+static struct clk *da850_sata_clk;
+static unsigned long da850_sata_refclkpn;
+
+/* Supported DA850 SATA crystal frequencies */
+#define KHZ_TO_HZ(freq) ((freq) * 1000)
+static unsigned long da850_sata_xtal[] = {
+ KHZ_TO_HZ(300000),
+ KHZ_TO_HZ(250000),
+ 0, /* Reserved */
+ KHZ_TO_HZ(187500),
+ KHZ_TO_HZ(150000),
+ KHZ_TO_HZ(125000),
+ KHZ_TO_HZ(120000),
+ KHZ_TO_HZ(100000),
+ KHZ_TO_HZ(75000),
+ KHZ_TO_HZ(60000),
+};
+
+static int da850_sata_init(struct device *dev, void __iomem *addr)
+{
+ int i, ret;
+ unsigned int val;
+
+ da850_sata_clk = clk_get(dev, NULL);
+ if (IS_ERR(da850_sata_clk))
+ return PTR_ERR(da850_sata_clk);
+
+ ret = clk_enable(da850_sata_clk);
+ if (ret)
+ goto err0;
+
+ /* Enable SATA clock receiver */
+ val = __raw_readl(DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
+ val &= ~BIT(0);
+ __raw_writel(val, DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
+
+ /* Get the multiplier needed for 1.5GHz PLL output */
+ for (i = 0; i < ARRAY_SIZE(da850_sata_xtal); i++)
+ if (da850_sata_xtal[i] == da850_sata_refclkpn)
+ break;
+
+ if (i == ARRAY_SIZE(da850_sata_xtal)) {
+ ret = -EINVAL;
+ goto err1;
+ }
+
+ val = SATA_PHY_MPY(i + 1) |
+ SATA_PHY_LOS(1) |
+ SATA_PHY_RXCDR(4) |
+ SATA_PHY_RXEQ(1) |
+ SATA_PHY_TXSWING(3) |
+ SATA_PHY_ENPLL(1);
+
+ __raw_writel(val, addr + SATA_P0PHYCR_REG);
+
+ return 0;
+
+err1:
+ clk_disable(da850_sata_clk);
+err0:
+ clk_put(da850_sata_clk);
+ return ret;
+}
+
+static void da850_sata_exit(struct device *dev)
+{
+ clk_disable(da850_sata_clk);
+ clk_put(da850_sata_clk);
+}
+
+static struct ahci_platform_data da850_sata_pdata = {
+ .init = da850_sata_init,
+ .exit = da850_sata_exit,
+};
+
+static u64 da850_sata_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device da850_sata_device = {
+ .name = "ahci",
+ .id = -1,
+ .dev = {
+ .platform_data = &da850_sata_pdata,
+ .dma_mask = &da850_sata_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(da850_sata_resources),
+ .resource = da850_sata_resources,
+};
+
+int __init da850_register_sata(unsigned long refclkpn)
+{
+ da850_sata_refclkpn = refclkpn;
+ if (!da850_sata_refclkpn)
+ return -EINVAL;
+
+ return platform_device_register(&da850_sata_device);
+}
+#endif
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 1e0f809644bb..1802e711a2b8 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -8,6 +8,7 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/serial_8250.h>
@@ -42,6 +43,7 @@
/*
* Device specific clocks
*/
+#define DM646X_REF_FREQ 27000000
#define DM646X_AUX_FREQ 24000000
static struct pll_data pll1_data = {
@@ -56,6 +58,8 @@ static struct pll_data pll2_data = {
static struct clk ref_clk = {
.name = "ref_clk",
+ .rate = DM646X_REF_FREQ,
+ .set_rate = davinci_simple_set_rate,
};
static struct clk aux_clkin = {
@@ -901,7 +905,6 @@ int __init dm646x_init_edma(struct edma_rsv_info *rsv)
void __init dm646x_init(void)
{
- dm646x_board_setup_refclk(&ref_clk);
davinci_common_init(&davinci_soc_info_dm646x);
}
diff --git a/arch/arm/mach-davinci/include/mach/clkdev.h b/arch/arm/mach-davinci/include/mach/clkdev.h
deleted file mode 100644
index 14a504887189..000000000000
--- a/arch/arm/mach-davinci/include/mach/clkdev.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-struct clk;
-
-static inline int __clk_get(struct clk *clk)
-{
- return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index ad64da713fc8..eaca7d8b9d68 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -57,6 +57,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_SYSCFG1_BASE (IO_PHYS + 0x22C000)
#define DA8XX_SYSCFG1_VIRT(x) (da8xx_syscfg1_base + (x))
#define DA8XX_DEEPSLEEP_REG 0x8
+#define DA8XX_PWRDN_REG 0x18
#define DA8XX_PSC0_BASE 0x01c10000
#define DA8XX_PLL0_BASE 0x01c11000
@@ -89,6 +90,7 @@ int da850_register_cpufreq(char *async_clk);
int da8xx_register_cpuidle(void);
void __iomem * __init da8xx_get_mem_ctlr(void);
int da850_register_pm(struct platform_device *pdev);
+int __init da850_register_sata(unsigned long refclkpn);
extern struct platform_device da8xx_serial_device;
extern struct emac_platform_data da8xx_emac_pdata;
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
index 7a27f3f13913..2a00fe5ac253 100644
--- a/arch/arm/mach-davinci/include/mach/dm646x.h
+++ b/arch/arm/mach-davinci/include/mach/dm646x.h
@@ -15,7 +15,6 @@
#include <mach/asp.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
-#include <linux/clk.h>
#include <linux/davinci_emac.h>
#define DM646X_EMAC_BASE (0x01C80000)
@@ -31,7 +30,6 @@
void __init dm646x_init(void);
void __init dm646x_init_mcasp0(struct snd_platform_data *pdata);
void __init dm646x_init_mcasp1(struct snd_platform_data *pdata);
-void __init dm646x_board_setup_refclk(struct clk *clk);
int __init dm646x_init_edma(struct edma_rsv_info *rsv);
void dm646x_video_init(void);
diff --git a/arch/arm/mach-davinci/include/mach/entry-macro.S b/arch/arm/mach-davinci/include/mach/entry-macro.S
index fbdebc7cb409..e14c0dc0e12c 100644
--- a/arch/arm/mach-davinci/include/mach/entry-macro.S
+++ b/arch/arm/mach-davinci/include/mach/entry-macro.S
@@ -46,6 +46,3 @@
#endif
1002:
.endm
-
- .macro irq_prio_table
- .endm
diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h
index 491249ef209c..78731944a70c 100644
--- a/arch/arm/mach-davinci/include/mach/memory.h
+++ b/arch/arm/mach-davinci/include/mach/memory.h
@@ -41,11 +41,4 @@
*/
#define CONSISTENT_DMA_SIZE (14<<20)
-/*
- * Restrict DMA-able region to workaround silicon bug. The bug
- * restricts buffers available for DMA to video hardware to be
- * below 128M
- */
-#define ARM_DMA_ZONE_SIZE SZ_128M
-
#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index a47e6f29206e..47fd0bc3d3e7 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -30,47 +30,47 @@
#define DAVINCI_PWR_SLEEP_CNTRL_BASE 0x01C41000
/* Power and Sleep Controller (PSC) Domains */
-#define DAVINCI_GPSC_ARMDOMAIN 0
-#define DAVINCI_GPSC_DSPDOMAIN 1
+#define DAVINCI_GPSC_ARMDOMAIN 0
+#define DAVINCI_GPSC_DSPDOMAIN 1
-#define DAVINCI_LPSC_VPSSMSTR 0
-#define DAVINCI_LPSC_VPSSSLV 1
-#define DAVINCI_LPSC_TPCC 2
-#define DAVINCI_LPSC_TPTC0 3
-#define DAVINCI_LPSC_TPTC1 4
-#define DAVINCI_LPSC_EMAC 5
-#define DAVINCI_LPSC_EMAC_WRAPPER 6
-#define DAVINCI_LPSC_USB 9
-#define DAVINCI_LPSC_ATA 10
-#define DAVINCI_LPSC_VLYNQ 11
-#define DAVINCI_LPSC_UHPI 12
-#define DAVINCI_LPSC_DDR_EMIF 13
-#define DAVINCI_LPSC_AEMIF 14
-#define DAVINCI_LPSC_MMC_SD 15
-#define DAVINCI_LPSC_McBSP 17
-#define DAVINCI_LPSC_I2C 18
-#define DAVINCI_LPSC_UART0 19
-#define DAVINCI_LPSC_UART1 20
-#define DAVINCI_LPSC_UART2 21
-#define DAVINCI_LPSC_SPI 22
-#define DAVINCI_LPSC_PWM0 23
-#define DAVINCI_LPSC_PWM1 24
-#define DAVINCI_LPSC_PWM2 25
-#define DAVINCI_LPSC_GPIO 26
-#define DAVINCI_LPSC_TIMER0 27
-#define DAVINCI_LPSC_TIMER1 28
-#define DAVINCI_LPSC_TIMER2 29
-#define DAVINCI_LPSC_SYSTEM_SUBSYS 30
-#define DAVINCI_LPSC_ARM 31
-#define DAVINCI_LPSC_SCR2 32
-#define DAVINCI_LPSC_SCR3 33
-#define DAVINCI_LPSC_SCR4 34
-#define DAVINCI_LPSC_CROSSBAR 35
-#define DAVINCI_LPSC_CFG27 36
-#define DAVINCI_LPSC_CFG3 37
-#define DAVINCI_LPSC_CFG5 38
-#define DAVINCI_LPSC_GEM 39
-#define DAVINCI_LPSC_IMCOP 40
+#define DAVINCI_LPSC_VPSSMSTR 0
+#define DAVINCI_LPSC_VPSSSLV 1
+#define DAVINCI_LPSC_TPCC 2
+#define DAVINCI_LPSC_TPTC0 3
+#define DAVINCI_LPSC_TPTC1 4
+#define DAVINCI_LPSC_EMAC 5
+#define DAVINCI_LPSC_EMAC_WRAPPER 6
+#define DAVINCI_LPSC_USB 9
+#define DAVINCI_LPSC_ATA 10
+#define DAVINCI_LPSC_VLYNQ 11
+#define DAVINCI_LPSC_UHPI 12
+#define DAVINCI_LPSC_DDR_EMIF 13
+#define DAVINCI_LPSC_AEMIF 14
+#define DAVINCI_LPSC_MMC_SD 15
+#define DAVINCI_LPSC_McBSP 17
+#define DAVINCI_LPSC_I2C 18
+#define DAVINCI_LPSC_UART0 19
+#define DAVINCI_LPSC_UART1 20
+#define DAVINCI_LPSC_UART2 21
+#define DAVINCI_LPSC_SPI 22
+#define DAVINCI_LPSC_PWM0 23
+#define DAVINCI_LPSC_PWM1 24
+#define DAVINCI_LPSC_PWM2 25
+#define DAVINCI_LPSC_GPIO 26
+#define DAVINCI_LPSC_TIMER0 27
+#define DAVINCI_LPSC_TIMER1 28
+#define DAVINCI_LPSC_TIMER2 29
+#define DAVINCI_LPSC_SYSTEM_SUBSYS 30
+#define DAVINCI_LPSC_ARM 31
+#define DAVINCI_LPSC_SCR2 32
+#define DAVINCI_LPSC_SCR3 33
+#define DAVINCI_LPSC_SCR4 34
+#define DAVINCI_LPSC_CROSSBAR 35
+#define DAVINCI_LPSC_CFG27 36
+#define DAVINCI_LPSC_CFG3 37
+#define DAVINCI_LPSC_CFG5 38
+#define DAVINCI_LPSC_GEM 39
+#define DAVINCI_LPSC_IMCOP 40
#define DM355_LPSC_TIMER3 5
#define DM355_LPSC_SPI1 6
@@ -102,39 +102,39 @@
/*
* LPSC Assignments
*/
-#define DM646X_LPSC_ARM 0
-#define DM646X_LPSC_C64X_CPU 1
-#define DM646X_LPSC_HDVICP0 2
-#define DM646X_LPSC_HDVICP1 3
-#define DM646X_LPSC_TPCC 4
-#define DM646X_LPSC_TPTC0 5
-#define DM646X_LPSC_TPTC1 6
-#define DM646X_LPSC_TPTC2 7
-#define DM646X_LPSC_TPTC3 8
-#define DM646X_LPSC_PCI 13
-#define DM646X_LPSC_EMAC 14
-#define DM646X_LPSC_VDCE 15
-#define DM646X_LPSC_VPSSMSTR 16
-#define DM646X_LPSC_VPSSSLV 17
-#define DM646X_LPSC_TSIF0 18
-#define DM646X_LPSC_TSIF1 19
-#define DM646X_LPSC_DDR_EMIF 20
-#define DM646X_LPSC_AEMIF 21
-#define DM646X_LPSC_McASP0 22
-#define DM646X_LPSC_McASP1 23
-#define DM646X_LPSC_CRGEN0 24
-#define DM646X_LPSC_CRGEN1 25
-#define DM646X_LPSC_UART0 26
-#define DM646X_LPSC_UART1 27
-#define DM646X_LPSC_UART2 28
-#define DM646X_LPSC_PWM0 29
-#define DM646X_LPSC_PWM1 30
-#define DM646X_LPSC_I2C 31
-#define DM646X_LPSC_SPI 32
-#define DM646X_LPSC_GPIO 33
-#define DM646X_LPSC_TIMER0 34
-#define DM646X_LPSC_TIMER1 35
-#define DM646X_LPSC_ARM_INTC 45
+#define DM646X_LPSC_ARM 0
+#define DM646X_LPSC_C64X_CPU 1
+#define DM646X_LPSC_HDVICP0 2
+#define DM646X_LPSC_HDVICP1 3
+#define DM646X_LPSC_TPCC 4
+#define DM646X_LPSC_TPTC0 5
+#define DM646X_LPSC_TPTC1 6
+#define DM646X_LPSC_TPTC2 7
+#define DM646X_LPSC_TPTC3 8
+#define DM646X_LPSC_PCI 13
+#define DM646X_LPSC_EMAC 14
+#define DM646X_LPSC_VDCE 15
+#define DM646X_LPSC_VPSSMSTR 16
+#define DM646X_LPSC_VPSSSLV 17
+#define DM646X_LPSC_TSIF0 18
+#define DM646X_LPSC_TSIF1 19
+#define DM646X_LPSC_DDR_EMIF 20
+#define DM646X_LPSC_AEMIF 21
+#define DM646X_LPSC_McASP0 22
+#define DM646X_LPSC_McASP1 23
+#define DM646X_LPSC_CRGEN0 24
+#define DM646X_LPSC_CRGEN1 25
+#define DM646X_LPSC_UART0 26
+#define DM646X_LPSC_UART1 27
+#define DM646X_LPSC_UART2 28
+#define DM646X_LPSC_PWM0 29
+#define DM646X_LPSC_PWM1 30
+#define DM646X_LPSC_I2C 31
+#define DM646X_LPSC_SPI 32
+#define DM646X_LPSC_GPIO 33
+#define DM646X_LPSC_TIMER0 34
+#define DM646X_LPSC_TIMER1 35
+#define DM646X_LPSC_ARM_INTC 45
/* PSC0 defines */
#define DA8XX_LPSC0_TPCC 0
@@ -243,13 +243,14 @@
#define PSC_STATE_DISABLE 2
#define PSC_STATE_ENABLE 3
-#define MDSTAT_STATE_MASK 0x1f
+#define MDSTAT_STATE_MASK 0x1f
+#define MDCTL_FORCE BIT(31)
#ifndef __ASSEMBLER__
extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
- unsigned int id, u32 next_state);
+ unsigned int id, bool enable, u32 flags);
#endif
diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c
index 1bd73a04be20..04c49f7543ef 100644
--- a/arch/arm/mach-davinci/pm.c
+++ b/arch/arm/mach-davinci/pm.c
@@ -17,6 +17,7 @@
#include <asm/cacheflush.h>
#include <asm/delay.h>
+#include <asm/io.h>
#include <mach/da8xx.h>
#include <mach/sram.h>
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index a41580400701..1fb6bdff38c1 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,6 +25,8 @@
#include <mach/cputype.h>
#include <mach/psc.h>
+#include "clock.h"
+
/* Return nonzero iff the domain's clock is active */
int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
{
@@ -48,11 +50,12 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
/* Enable or disable a PSC domain */
void davinci_psc_config(unsigned int domain, unsigned int ctlr,
- unsigned int id, u32 next_state)
+ unsigned int id, bool enable, u32 flags)
{
u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
void __iomem *psc_base;
struct davinci_soc_info *soc_info = &davinci_soc_info;
+ u32 next_state = PSC_STATE_ENABLE;
if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
@@ -62,9 +65,18 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,
psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
+ if (!enable) {
+ if (flags & PSC_SWRSTDISABLE)
+ next_state = PSC_STATE_SWRSTDISABLE;
+ else
+ next_state = PSC_STATE_DISABLE;
+ }
+
mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
mdctl &= ~MDSTAT_STATE_MASK;
mdctl |= next_state;
+ if (flags & PSC_FORCE)
+ mdctl |= MDCTL_FORCE;
__raw_writel(mdctl, psc_base + MDCTL + 4 * id);
pdstat = __raw_readl(psc_base + PDSTAT);
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 5ed51b84c1b2..83dce859886d 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -13,11 +13,9 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
-#include <linux/serial_8250.h>
#include <linux/clk.h>
#include <linux/mbus.h>
#include <linux/ata_platform.h>
-#include <linux/serial_8250.h>
#include <linux/gpio.h>
#include <asm/page.h>
#include <asm/setup.h>
diff --git a/arch/arm/mach-dove/include/mach/hardware.h b/arch/arm/mach-dove/include/mach/hardware.h
index 32b0826e7873..f1368b9a8ece 100644
--- a/arch/arm/mach-dove/include/mach/hardware.h
+++ b/arch/arm/mach-dove/include/mach/hardware.h
@@ -11,13 +11,6 @@
#include "dove.h"
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x1000
-#define PCIBIOS_MIN_MEM 0x01000000
-#define PCIMEM_BASE DOVE_PCIE0_MEM_PHYS_BASE
-
-
/* Macros below are required for compatibility with PXA AC'97 driver. */
#define __REG(x) (*((volatile u32 *)((x) - DOVE_SB_REGS_PHYS_BASE + \
DOVE_SB_REGS_VIRT_BASE)))
diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c
index 502d1ca2f4b7..c2f1c4767f21 100644
--- a/arch/arm/mach-dove/pcie.c
+++ b/arch/arm/mach-dove/pcie.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/mbus.h>
+#include <video/vga.h>
#include <asm/mach/pci.h>
#include <asm/mach/arch.h>
#include <asm/setup.h>
@@ -228,6 +229,8 @@ static void __init add_pcie_port(int index, unsigned long base)
void __init dove_pcie_init(int init_port0, int init_port1)
{
+ vga_base = DOVE_PCIE0_MEM_PHYS_BASE;
+
if (init_port0)
add_pcie_port(0, DOVE_PCIE0_VIRT_BASE);
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 33ee2c863d18..3cedcf2d39e5 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -1,11 +1,13 @@
#
# Makefile for the linux kernel.
#
-obj-y := core.o clock.o dma-m2p.o gpio.o
+obj-y := core.o clock.o
obj-m :=
obj-n :=
obj- :=
+obj-$(CONFIG_EP93XX_DMA) += dma.o
+
obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o
obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6659a0d137a3..c60f081e930b 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -174,14 +174,10 @@ struct sys_timer ep93xx_timer = {
/*************************************************************************
* EP93xx IRQ handling
*************************************************************************/
-extern void ep93xx_gpio_init_irq(void);
-
void __init ep93xx_init_irq(void)
{
vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
-
- ep93xx_gpio_init_irq();
}
@@ -241,6 +237,24 @@ unsigned int ep93xx_chip_revision(void)
}
/*************************************************************************
+ * EP93xx GPIO
+ *************************************************************************/
+static struct resource ep93xx_gpio_resource[] = {
+ {
+ .start = EP93XX_GPIO_PHYS_BASE,
+ .end = EP93XX_GPIO_PHYS_BASE + 0xcc - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ep93xx_gpio_device = {
+ .name = "gpio-ep93xx",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ep93xx_gpio_resource),
+ .resource = ep93xx_gpio_resource,
+};
+
+/*************************************************************************
* EP93xx peripheral handling
*************************************************************************/
#define EP93XX_UART_MCR_OFFSET (0x0100)
@@ -492,11 +506,15 @@ static struct resource ep93xx_spi_resources[] = {
},
};
+static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32);
+
static struct platform_device ep93xx_spi_device = {
.name = "ep93xx-spi",
.id = 0,
.dev = {
- .platform_data = &ep93xx_spi_master_data,
+ .platform_data = &ep93xx_spi_master_data,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &ep93xx_spi_dma_mask,
},
.num_resources = ARRAY_SIZE(ep93xx_spi_resources),
.resource = ep93xx_spi_resources,
@@ -870,14 +888,13 @@ void __init ep93xx_register_ac97(void)
platform_device_register(&ep93xx_pcm_device);
}
-extern void ep93xx_gpio_init(void);
-
void __init ep93xx_init_devices(void)
{
/* Disallow access to MaverickCrunch initially */
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
- ep93xx_gpio_init();
+ /* Get the GPIO working early, other devices need it */
+ platform_device_register(&ep93xx_gpio_device);
amba_device_register(&uart1_device, &iomem_resource);
amba_device_register(&uart2_device, &iomem_resource);
diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c
deleted file mode 100644
index a696d354b1f8..000000000000
--- a/arch/arm/mach-ep93xx/dma-m2p.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/dma-m2p.c
- * M2P DMA handling for Cirrus EP93xx chips.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- * Copyright (C) 2006 Applied Data Systems
- *
- * Copyright (C) 2009 Ryan Mallon <ryan@bluewatersys.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.
- */
-
-/*
- * On the EP93xx chip the following peripherals my be allocated to the 10
- * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
- *
- * I2S contains 3 Tx and 3 Rx DMA Channels
- * AAC contains 3 Tx and 3 Rx DMA Channels
- * UART1 contains 1 Tx and 1 Rx DMA Channels
- * UART2 contains 1 Tx and 1 Rx DMA Channels
- * UART3 contains 1 Tx and 1 Rx DMA Channels
- * IrDA contains 1 Tx and 1 Rx DMA Channels
- *
- * SSP and IDE use the Memory to Memory (M2M) channels and are not covered
- * with this implementation.
- */
-
-#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#include <mach/dma.h>
-#include <mach/hardware.h>
-
-#define M2P_CONTROL 0x00
-#define M2P_CONTROL_STALL_IRQ_EN (1 << 0)
-#define M2P_CONTROL_NFB_IRQ_EN (1 << 1)
-#define M2P_CONTROL_ERROR_IRQ_EN (1 << 3)
-#define M2P_CONTROL_ENABLE (1 << 4)
-#define M2P_INTERRUPT 0x04
-#define M2P_INTERRUPT_STALL (1 << 0)
-#define M2P_INTERRUPT_NFB (1 << 1)
-#define M2P_INTERRUPT_ERROR (1 << 3)
-#define M2P_PPALLOC 0x08
-#define M2P_STATUS 0x0c
-#define M2P_REMAIN 0x14
-#define M2P_MAXCNT0 0x20
-#define M2P_BASE0 0x24
-#define M2P_MAXCNT1 0x30
-#define M2P_BASE1 0x34
-
-#define STATE_IDLE 0 /* Channel is inactive. */
-#define STATE_STALL 1 /* Channel is active, no buffers pending. */
-#define STATE_ON 2 /* Channel is active, one buffer pending. */
-#define STATE_NEXT 3 /* Channel is active, two buffers pending. */
-
-struct m2p_channel {
- char *name;
- void __iomem *base;
- int irq;
-
- struct clk *clk;
- spinlock_t lock;
-
- void *client;
- unsigned next_slot:1;
- struct ep93xx_dma_buffer *buffer_xfer;
- struct ep93xx_dma_buffer *buffer_next;
- struct list_head buffers_pending;
-};
-
-static struct m2p_channel m2p_rx[] = {
- {"m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1},
- {"m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3},
- {"m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5},
- {"m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7},
- {"m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9},
- {NULL},
-};
-
-static struct m2p_channel m2p_tx[] = {
- {"m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0},
- {"m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2},
- {"m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4},
- {"m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6},
- {"m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8},
- {NULL},
-};
-
-static void feed_buf(struct m2p_channel *ch, struct ep93xx_dma_buffer *buf)
-{
- if (ch->next_slot == 0) {
- writel(buf->size, ch->base + M2P_MAXCNT0);
- writel(buf->bus_addr, ch->base + M2P_BASE0);
- } else {
- writel(buf->size, ch->base + M2P_MAXCNT1);
- writel(buf->bus_addr, ch->base + M2P_BASE1);
- }
- ch->next_slot ^= 1;
-}
-
-static void choose_buffer_xfer(struct m2p_channel *ch)
-{
- struct ep93xx_dma_buffer *buf;
-
- ch->buffer_xfer = NULL;
- if (!list_empty(&ch->buffers_pending)) {
- buf = list_entry(ch->buffers_pending.next,
- struct ep93xx_dma_buffer, list);
- list_del(&buf->list);
- feed_buf(ch, buf);
- ch->buffer_xfer = buf;
- }
-}
-
-static void choose_buffer_next(struct m2p_channel *ch)
-{
- struct ep93xx_dma_buffer *buf;
-
- ch->buffer_next = NULL;
- if (!list_empty(&ch->buffers_pending)) {
- buf = list_entry(ch->buffers_pending.next,
- struct ep93xx_dma_buffer, list);
- list_del(&buf->list);
- feed_buf(ch, buf);
- ch->buffer_next = buf;
- }
-}
-
-static inline void m2p_set_control(struct m2p_channel *ch, u32 v)
-{
- /*
- * The control register must be read immediately after being written so
- * that the internal state machine is correctly updated. See the ep93xx
- * users' guide for details.
- */
- writel(v, ch->base + M2P_CONTROL);
- readl(ch->base + M2P_CONTROL);
-}
-
-static inline int m2p_channel_state(struct m2p_channel *ch)
-{
- return (readl(ch->base + M2P_STATUS) >> 4) & 0x3;
-}
-
-static irqreturn_t m2p_irq(int irq, void *dev_id)
-{
- struct m2p_channel *ch = dev_id;
- struct ep93xx_dma_m2p_client *cl;
- u32 irq_status, v;
- int error = 0;
-
- cl = ch->client;
-
- spin_lock(&ch->lock);
- irq_status = readl(ch->base + M2P_INTERRUPT);
-
- if (irq_status & M2P_INTERRUPT_ERROR) {
- writel(M2P_INTERRUPT_ERROR, ch->base + M2P_INTERRUPT);
- error = 1;
- }
-
- if ((irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) == 0) {
- spin_unlock(&ch->lock);
- return IRQ_NONE;
- }
-
- switch (m2p_channel_state(ch)) {
- case STATE_IDLE:
- pr_crit("dma interrupt without a dma buffer\n");
- BUG();
- break;
-
- case STATE_STALL:
- cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
- if (ch->buffer_next != NULL) {
- cl->buffer_finished(cl->cookie, ch->buffer_next,
- 0, error);
- }
- choose_buffer_xfer(ch);
- choose_buffer_next(ch);
- if (ch->buffer_xfer != NULL)
- cl->buffer_started(cl->cookie, ch->buffer_xfer);
- break;
-
- case STATE_ON:
- cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
- ch->buffer_xfer = ch->buffer_next;
- choose_buffer_next(ch);
- cl->buffer_started(cl->cookie, ch->buffer_xfer);
- break;
-
- case STATE_NEXT:
- pr_crit("dma interrupt while next\n");
- BUG();
- break;
- }
-
- v = readl(ch->base + M2P_CONTROL) & ~(M2P_CONTROL_STALL_IRQ_EN |
- M2P_CONTROL_NFB_IRQ_EN);
- if (ch->buffer_xfer != NULL)
- v |= M2P_CONTROL_STALL_IRQ_EN;
- if (ch->buffer_next != NULL)
- v |= M2P_CONTROL_NFB_IRQ_EN;
- m2p_set_control(ch, v);
-
- spin_unlock(&ch->lock);
- return IRQ_HANDLED;
-}
-
-static struct m2p_channel *find_free_channel(struct ep93xx_dma_m2p_client *cl)
-{
- struct m2p_channel *ch;
- int i;
-
- if (cl->flags & EP93XX_DMA_M2P_RX)
- ch = m2p_rx;
- else
- ch = m2p_tx;
-
- for (i = 0; ch[i].base; i++) {
- struct ep93xx_dma_m2p_client *client;
-
- client = ch[i].client;
- if (client != NULL) {
- int port;
-
- port = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
- if (port == (client->flags &
- EP93XX_DMA_M2P_PORT_MASK)) {
- pr_warning("DMA channel already used by %s\n",
- cl->name ? : "unknown client");
- return ERR_PTR(-EBUSY);
- }
- }
- }
-
- for (i = 0; ch[i].base; i++) {
- if (ch[i].client == NULL)
- return ch + i;
- }
-
- pr_warning("No free DMA channel for %s\n",
- cl->name ? : "unknown client");
- return ERR_PTR(-ENODEV);
-}
-
-static void channel_enable(struct m2p_channel *ch)
-{
- struct ep93xx_dma_m2p_client *cl = ch->client;
- u32 v;
-
- clk_enable(ch->clk);
-
- v = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
- writel(v, ch->base + M2P_PPALLOC);
-
- v = cl->flags & EP93XX_DMA_M2P_ERROR_MASK;
- v |= M2P_CONTROL_ENABLE | M2P_CONTROL_ERROR_IRQ_EN;
- m2p_set_control(ch, v);
-}
-
-static void channel_disable(struct m2p_channel *ch)
-{
- u32 v;
-
- v = readl(ch->base + M2P_CONTROL);
- v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
- m2p_set_control(ch, v);
-
- while (m2p_channel_state(ch) >= STATE_ON)
- cpu_relax();
-
- m2p_set_control(ch, 0x0);
-
- while (m2p_channel_state(ch) == STATE_STALL)
- cpu_relax();
-
- clk_disable(ch->clk);
-}
-
-int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *cl)
-{
- struct m2p_channel *ch;
- int err;
-
- ch = find_free_channel(cl);
- if (IS_ERR(ch))
- return PTR_ERR(ch);
-
- err = request_irq(ch->irq, m2p_irq, 0, cl->name ? : "dma-m2p", ch);
- if (err)
- return err;
-
- ch->client = cl;
- ch->next_slot = 0;
- ch->buffer_xfer = NULL;
- ch->buffer_next = NULL;
- INIT_LIST_HEAD(&ch->buffers_pending);
-
- cl->channel = ch;
-
- channel_enable(ch);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_register);
-
-void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *cl)
-{
- struct m2p_channel *ch = cl->channel;
-
- channel_disable(ch);
- free_irq(ch->irq, ch);
- ch->client = NULL;
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_unregister);
-
-void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *cl,
- struct ep93xx_dma_buffer *buf)
-{
- struct m2p_channel *ch = cl->channel;
- unsigned long flags;
- u32 v;
-
- spin_lock_irqsave(&ch->lock, flags);
- v = readl(ch->base + M2P_CONTROL);
- if (ch->buffer_xfer == NULL) {
- ch->buffer_xfer = buf;
- feed_buf(ch, buf);
- cl->buffer_started(cl->cookie, buf);
-
- v |= M2P_CONTROL_STALL_IRQ_EN;
- m2p_set_control(ch, v);
-
- } else if (ch->buffer_next == NULL) {
- ch->buffer_next = buf;
- feed_buf(ch, buf);
-
- v |= M2P_CONTROL_NFB_IRQ_EN;
- m2p_set_control(ch, v);
- } else {
- list_add_tail(&buf->list, &ch->buffers_pending);
- }
- spin_unlock_irqrestore(&ch->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit);
-
-void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *cl,
- struct ep93xx_dma_buffer *buf)
-{
- struct m2p_channel *ch = cl->channel;
-
- list_add_tail(&buf->list, &ch->buffers_pending);
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit_recursive);
-
-void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *cl)
-{
- struct m2p_channel *ch = cl->channel;
-
- channel_disable(ch);
- ch->next_slot = 0;
- ch->buffer_xfer = NULL;
- ch->buffer_next = NULL;
- INIT_LIST_HEAD(&ch->buffers_pending);
- channel_enable(ch);
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_flush);
-
-static int init_channel(struct m2p_channel *ch)
-{
- ch->clk = clk_get(NULL, ch->name);
- if (IS_ERR(ch->clk))
- return PTR_ERR(ch->clk);
-
- spin_lock_init(&ch->lock);
- ch->client = NULL;
-
- return 0;
-}
-
-static int __init ep93xx_dma_m2p_init(void)
-{
- int i;
- int ret;
-
- for (i = 0; m2p_rx[i].base; i++) {
- ret = init_channel(m2p_rx + i);
- if (ret)
- return ret;
- }
-
- for (i = 0; m2p_tx[i].base; i++) {
- ret = init_channel(m2p_tx + i);
- if (ret)
- return ret;
- }
-
- pr_info("M2P DMA subsystem initialized\n");
- return 0;
-}
-arch_initcall(ep93xx_dma_m2p_init);
diff --git a/arch/arm/mach-ep93xx/dma.c b/arch/arm/mach-ep93xx/dma.c
new file mode 100644
index 000000000000..5a2570881255
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma.c
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ep93xx/dma.c
+ *
+ * Platform support code for the EP93xx dmaengine driver.
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * This work is based on the original dma-m2p implementation with
+ * following copyrights:
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ * Copyright (C) 2009 Ryan Mallon <rmallon@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/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+#define DMA_CHANNEL(_name, _base, _irq) \
+ { .name = (_name), .base = (_base), .irq = (_irq) }
+
+/*
+ * DMA M2P channels.
+ *
+ * On the EP93xx chip the following peripherals my be allocated to the 10
+ * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
+ *
+ * I2S contains 3 Tx and 3 Rx DMA Channels
+ * AAC contains 3 Tx and 3 Rx DMA Channels
+ * UART1 contains 1 Tx and 1 Rx DMA Channels
+ * UART2 contains 1 Tx and 1 Rx DMA Channels
+ * UART3 contains 1 Tx and 1 Rx DMA Channels
+ * IrDA contains 1 Tx and 1 Rx DMA Channels
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
+ DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
+ DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
+ DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
+ DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
+ DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
+ DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
+ DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
+ DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
+ DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
+ DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
+ .channels = ep93xx_dma_m2p_channels,
+ .num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels),
+};
+
+static struct platform_device ep93xx_dma_m2p_device = {
+ .name = "ep93xx-dma-m2p",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_dma_m2p_data,
+ },
+};
+
+/*
+ * DMA M2M channels.
+ *
+ * There are 2 M2M channels which support memcpy/memset and in addition simple
+ * hardware requests from/to SSP and IDE. We do not implement an external
+ * hardware requests.
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
+ DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
+ DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
+ .channels = ep93xx_dma_m2m_channels,
+ .num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels),
+};
+
+static struct platform_device ep93xx_dma_m2m_device = {
+ .name = "ep93xx-dma-m2m",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_dma_m2m_data,
+ },
+};
+
+static int __init ep93xx_dma_init(void)
+{
+ platform_device_register(&ep93xx_dma_m2p_device);
+ platform_device_register(&ep93xx_dma_m2m_device);
+ return 0;
+}
+arch_initcall(ep93xx_dma_init);
diff --git a/arch/arm/mach-ep93xx/include/mach/clkdev.h b/arch/arm/mach-ep93xx/include/mach/clkdev.h
deleted file mode 100644
index 50cb991eadeb..000000000000
--- a/arch/arm/mach-ep93xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/clkdev.h
- */
-
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
index 5e31b2b25da9..46d4d876e6fb 100644
--- a/arch/arm/mach-ep93xx/include/mach/dma.h
+++ b/arch/arm/mach-ep93xx/include/mach/dma.h
@@ -1,149 +1,93 @@
-/**
- * DOC: EP93xx DMA M2P memory to peripheral and peripheral to memory engine
- *
- * The EP93xx DMA M2P subsystem handles DMA transfers between memory and
- * peripherals. DMA M2P channels are available for audio, UARTs and IrDA.
- * See chapter 10 of the EP93xx users guide for full details on the DMA M2P
- * engine.
- *
- * See sound/soc/ep93xx/ep93xx-pcm.c for an example use of the DMA M2P code.
- *
- */
-
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
-#include <linux/list.h>
#include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
-/**
- * struct ep93xx_dma_buffer - Information about a buffer to be transferred
- * using the DMA M2P engine
+/*
+ * M2P channels.
*
- * @list: Entry in DMA buffer list
- * @bus_addr: Physical address of the buffer
- * @size: Size of the buffer in bytes
+ * Note that these values are also directly used for setting the PPALLOC
+ * register.
*/
-struct ep93xx_dma_buffer {
- struct list_head list;
- u32 bus_addr;
- u16 size;
-};
+#define EP93XX_DMA_I2S1 0
+#define EP93XX_DMA_I2S2 1
+#define EP93XX_DMA_AAC1 2
+#define EP93XX_DMA_AAC2 3
+#define EP93XX_DMA_AAC3 4
+#define EP93XX_DMA_I2S3 5
+#define EP93XX_DMA_UART1 6
+#define EP93XX_DMA_UART2 7
+#define EP93XX_DMA_UART3 8
+#define EP93XX_DMA_IRDA 9
+/* M2M channels */
+#define EP93XX_DMA_SSP 10
+#define EP93XX_DMA_IDE 11
/**
- * struct ep93xx_dma_m2p_client - Information about a DMA M2P client
- *
- * @name: Unique name for this client
- * @flags: Client flags
- * @cookie: User data to pass to callback functions
- * @buffer_started: Non NULL function to call when a transfer is started.
- * The arguments are the user data cookie and the DMA
- * buffer which is starting.
- * @buffer_finished: Non NULL function to call when a transfer is completed.
- * The arguments are the user data cookie, the DMA buffer
- * which has completed, and a boolean flag indicating if
- * the transfer had an error.
+ * struct ep93xx_dma_data - configuration data for the EP93xx dmaengine
+ * @port: peripheral which is requesting the channel
+ * @direction: TX/RX channel
+ * @name: optional name for the channel, this is displayed in /proc/interrupts
+ *
+ * This information is passed as private channel parameter in a filter
+ * function. Note that this is only needed for slave/cyclic channels. For
+ * memcpy channels %NULL data should be passed.
*/
-struct ep93xx_dma_m2p_client {
- char *name;
- u8 flags;
- void *cookie;
- void (*buffer_started)(void *cookie,
- struct ep93xx_dma_buffer *buf);
- void (*buffer_finished)(void *cookie,
- struct ep93xx_dma_buffer *buf,
- int bytes, int error);
-
- /* private: Internal use only */
- void *channel;
+struct ep93xx_dma_data {
+ int port;
+ enum dma_data_direction direction;
+ const char *name;
};
-/* DMA M2P ports */
-#define EP93XX_DMA_M2P_PORT_I2S1 0x00
-#define EP93XX_DMA_M2P_PORT_I2S2 0x01
-#define EP93XX_DMA_M2P_PORT_AAC1 0x02
-#define EP93XX_DMA_M2P_PORT_AAC2 0x03
-#define EP93XX_DMA_M2P_PORT_AAC3 0x04
-#define EP93XX_DMA_M2P_PORT_I2S3 0x05
-#define EP93XX_DMA_M2P_PORT_UART1 0x06
-#define EP93XX_DMA_M2P_PORT_UART2 0x07
-#define EP93XX_DMA_M2P_PORT_UART3 0x08
-#define EP93XX_DMA_M2P_PORT_IRDA 0x09
-#define EP93XX_DMA_M2P_PORT_MASK 0x0f
-
-/* DMA M2P client flags */
-#define EP93XX_DMA_M2P_TX 0x00 /* Memory to peripheral */
-#define EP93XX_DMA_M2P_RX 0x10 /* Peripheral to memory */
-
-/*
- * DMA M2P client error handling flags. See the EP93xx users guide
- * documentation on the DMA M2P CONTROL register for more details
- */
-#define EP93XX_DMA_M2P_ABORT_ON_ERROR 0x20 /* Abort on peripheral error */
-#define EP93XX_DMA_M2P_IGNORE_ERROR 0x40 /* Ignore peripheral errors */
-#define EP93XX_DMA_M2P_ERROR_MASK 0x60 /* Mask of error bits */
-
/**
- * ep93xx_dma_m2p_client_register - Register a client with the DMA M2P
- * subsystem
- *
- * @m2p: Client information to register
- * returns 0 on success
- *
- * The DMA M2P subsystem allocates a channel and an interrupt line for the DMA
- * client
+ * struct ep93xx_dma_chan_data - platform specific data for a DMA channel
+ * @name: name of the channel, used for getting the right clock for the channel
+ * @base: mapped registers
+ * @irq: interrupt number used by this channel
*/
-int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *m2p);
+struct ep93xx_dma_chan_data {
+ const char *name;
+ void __iomem *base;
+ int irq;
+};
/**
- * ep93xx_dma_m2p_client_unregister - Unregister a client from the DMA M2P
- * subsystem
- *
- * @m2p: Client to unregister
+ * struct ep93xx_dma_platform_data - platform data for the dmaengine driver
+ * @channels: array of channels which are passed to the driver
+ * @num_channels: number of channels in the array
*
- * Any transfers currently in progress will be completed in hardware, but
- * ignored in software.
+ * This structure is passed to the DMA engine driver via platform data. For
+ * M2P channels, contract is that even channels are for TX and odd for RX.
+ * There is no requirement for the M2M channels.
*/
-void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *m2p);
+struct ep93xx_dma_platform_data {
+ struct ep93xx_dma_chan_data *channels;
+ size_t num_channels;
+};
-/**
- * ep93xx_dma_m2p_submit - Submit a DMA M2P transfer
- *
- * @m2p: DMA Client to submit the transfer on
- * @buf: DMA Buffer to submit
- *
- * If the current or next transfer positions are free on the M2P client then
- * the transfer is started immediately. If not, the transfer is added to the
- * list of pending transfers. This function must not be called from the
- * buffer_finished callback for an M2P channel.
- *
- */
-void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *m2p,
- struct ep93xx_dma_buffer *buf);
+static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan)
+{
+ return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p");
+}
/**
- * ep93xx_dma_m2p_submit_recursive - Put a DMA transfer on the pending list
- * for an M2P channel
+ * ep93xx_dma_chan_direction - returns direction the channel can be used
+ * @chan: channel
*
- * @m2p: DMA Client to submit the transfer on
- * @buf: DMA Buffer to submit
- *
- * This function must only be called from the buffer_finished callback for an
- * M2P channel. It is commonly used to add the next transfer in a chained list
- * of DMA transfers.
+ * This function can be used in filter functions to find out whether the
+ * channel supports given DMA direction. Only M2P channels have such
+ * limitation, for M2M channels the direction is configurable.
*/
-void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
- struct ep93xx_dma_buffer *buf);
+static inline enum dma_data_direction
+ep93xx_dma_chan_direction(struct dma_chan *chan)
+{
+ if (!ep93xx_dma_chan_is_m2p(chan))
+ return DMA_NONE;
-/**
- * ep93xx_dma_m2p_flush - Flush all pending transfers on a DMA M2P client
- *
- * @m2p: DMA client to flush transfers on
- *
- * Any transfers currently in progress will be completed in hardware, but
- * ignored in software.
- *
- */
-void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
+ /* even channels are for TX, odd for RX */
+ return (chan->chan_id % 2 == 0) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+}
#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 9ac4d1055097..c4a7b84ef06d 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -98,6 +98,7 @@
#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
+#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000)
#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
index 0a37961b3453..9bb63ac13f04 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
@@ -7,9 +7,11 @@ struct spi_device;
* struct ep93xx_spi_info - EP93xx specific SPI descriptor
* @num_chipselect: number of chip selects on this board, must be
* at least one
+ * @use_dma: use DMA for the transfers
*/
struct ep93xx_spi_info {
int num_chipselect;
+ bool use_dma;
};
/**
diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h
index 5a3ce024b593..4df842897eae 100644
--- a/arch/arm/mach-ep93xx/include/mach/hardware.h
+++ b/arch/arm/mach-ep93xx/include/mach/hardware.h
@@ -8,8 +8,6 @@
#include <mach/ep93xx-regs.h>
#include <mach/platform.h>
-#define pcibios_assign_all_busses() 0
-
/*
* The EP93xx has two external crystal oscillators. To generate the
* required high-frequency clocks, the processor uses two phase-locked-
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index d96dc1c5da20..8392e95d7cea 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -2,7 +2,7 @@
* arch/arm/mach-ep93xx/simone.c
* Simplemachines Sim.One support.
*
- * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
+ * Copyright (C) 2010 Ryan Mallon
*
* Based on the 2.6.24.7 support:
* Copyright (C) 2009 Simplemachines
@@ -65,7 +65,7 @@ static void __init simone_init_machine(void)
}
MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
-/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
+/* Maintainer: Ryan Mallon */
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index ac601fe2b448..2e9c614757e4 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -3,7 +3,7 @@
* Bluewater Systems Snapper CL15 system module
*
* Copyright (C) 2009 Bluewater Systems Ltd
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
*
* NAND code adapted from driver by:
* Andre Renaud <andre@bluewatersys.com>
@@ -162,7 +162,7 @@ static void __init snappercl15_init_machine(void)
}
MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
- /* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
+ /* Maintainer: Ryan Mallon */
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc31c4b2..0c77ab99fa16 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -16,7 +16,8 @@ config CPU_EXYNOS4210
Enable EXYNOS4210 CPU support
config EXYNOS4_MCT
- bool "Kernel timer support by MCT"
+ bool
+ default y
help
Use MCT (Multi Core Timer) as kernel timers
@@ -25,6 +26,11 @@ config EXYNOS4_DEV_AHCI
help
Compile in platform device definitions for AHCI
+config EXYNOS4_SETUP_FIMD0
+ bool
+ help
+ Common setup code for FIMD0.
+
config EXYNOS4_DEV_PD
bool
help
@@ -35,6 +41,11 @@ config EXYNOS4_DEV_SYSMMU
help
Common setup code for SYSTEM MMU in EXYNOS4
+config EXYNOS4_DEV_DWMCI
+ bool
+ help
+ Compile in platform device definitions for DWMCI
+
config EXYNOS4_SETUP_I2C1
bool
help
@@ -103,6 +114,7 @@ menu "EXYNOS4 Machines"
config MACH_SMDKC210
bool "SMDKC210"
select CPU_EXYNOS4210
+ select S5P_DEV_FIMD0
select S3C_DEV_RTC
select S3C_DEV_WDT
select S3C_DEV_I2C1
@@ -110,8 +122,11 @@ config MACH_SMDKC210
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
help
@@ -120,6 +135,7 @@ config MACH_SMDKC210
config MACH_SMDKV310
bool "SMDKV310"
select CPU_EXYNOS4210
+ select S5P_DEV_FIMD0
select S3C_DEV_RTC
select S3C_DEV_WDT
select S3C_DEV_I2C1
@@ -127,9 +143,13 @@ config MACH_SMDKV310
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
+ select SAMSUNG_DEV_BACKLIGHT
+ select EXYNOS4_DEV_AHCI
select SAMSUNG_DEV_KEYPAD
select EXYNOS4_DEV_PD
+ select SAMSUNG_DEV_PWM
select EXYNOS4_DEV_SYSMMU
+ select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_KEYPAD
select EXYNOS4_SETUP_SDHCI
@@ -153,13 +173,22 @@ config MACH_ARMLEX4210
config MACH_UNIVERSAL_C210
bool "Mobile UNIVERSAL_C210 Board"
select CPU_EXYNOS4210
+ select S5P_GPIO_INT
+ select S5P_DEV_FIMC0
+ select S5P_DEV_FIMC1
+ select S5P_DEV_FIMC2
+ select S5P_DEV_FIMC3
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
select S3C_DEV_I2C1
+ select S3C_DEV_I2C3
select S3C_DEV_I2C5
+ select S5P_DEV_MFC
select S5P_DEV_ONENAND
+ select EXYNOS4_DEV_PD
select EXYNOS4_SETUP_I2C1
+ select EXYNOS4_SETUP_I2C3
select EXYNOS4_SETUP_I2C5
select EXYNOS4_SETUP_SDHCI
help
@@ -176,13 +205,16 @@ config MACH_NURI
select S3C_DEV_I2C1
select S3C_DEV_I2C3
select S3C_DEV_I2C5
+ select S5P_DEV_MFC
select S5P_DEV_USB_EHCI
+ select EXYNOS4_DEV_PD
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C3
select EXYNOS4_SETUP_I2C5
select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_USB_PHY
select SAMSUNG_DEV_PWM
+ select SAMSUNG_DEV_ADC
help
Machine support for Samsung Mobile NURI Board.
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index 60fe5ecf3599..b7fe1d7b0b1f 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -13,19 +13,13 @@ 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
+obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o irq-eint.o dma.o pmu.o
obj-$(CONFIG_PM) += pm.o sleep.o
-obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
-ifeq ($(CONFIG_EXYNOS4_MCT),y)
-obj-y += mct.o
-else
-obj-y += time.o
-obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
-endif
+obj-$(CONFIG_EXYNOS4_MCT) += mct.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
@@ -43,8 +37,10 @@ obj-y += dev-audio.o
obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
+obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C2) += setup-i2c2.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C3) += setup-i2c3.o
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 871f9d508fde..851dea018578 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -27,24 +27,20 @@
static struct clk clk_sclk_hdmi27m = {
.name = "sclk_hdmi27m",
- .id = -1,
.rate = 27000000,
};
static struct clk clk_sclk_hdmiphy = {
.name = "sclk_hdmiphy",
- .id = -1,
};
static struct clk clk_sclk_usbphy0 = {
.name = "sclk_usbphy0",
- .id = -1,
.rate = 27000000,
};
static struct clk clk_sclk_usbphy1 = {
.name = "sclk_usbphy1",
- .id = -1,
};
static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
@@ -132,7 +128,6 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
- .id = -1,
},
.sources = &clk_src_apll,
.reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
@@ -141,7 +136,6 @@ static struct clksrc_clk clk_mout_apll = {
static struct clksrc_clk clk_sclk_apll = {
.clk = {
.name = "sclk_apll",
- .id = -1,
.parent = &clk_mout_apll.clk,
},
.reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
@@ -150,7 +144,6 @@ static struct clksrc_clk clk_sclk_apll = {
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
- .id = -1,
},
.sources = &clk_src_epll,
.reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
@@ -159,7 +152,6 @@ static struct clksrc_clk clk_mout_epll = {
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
- .id = -1,
},
.sources = &clk_src_mpll,
.reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
@@ -178,7 +170,6 @@ static struct clksrc_sources clkset_moutcore = {
static struct clksrc_clk clk_moutcore = {
.clk = {
.name = "moutcore",
- .id = -1,
},
.sources = &clkset_moutcore,
.reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
@@ -187,7 +178,6 @@ static struct clksrc_clk clk_moutcore = {
static struct clksrc_clk clk_coreclk = {
.clk = {
.name = "core_clk",
- .id = -1,
.parent = &clk_moutcore.clk,
},
.reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
@@ -196,7 +186,6 @@ static struct clksrc_clk clk_coreclk = {
static struct clksrc_clk clk_armclk = {
.clk = {
.name = "armclk",
- .id = -1,
.parent = &clk_coreclk.clk,
},
};
@@ -204,7 +193,6 @@ static struct clksrc_clk clk_armclk = {
static struct clksrc_clk clk_aclk_corem0 = {
.clk = {
.name = "aclk_corem0",
- .id = -1,
.parent = &clk_coreclk.clk,
},
.reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
@@ -213,7 +201,6 @@ static struct clksrc_clk clk_aclk_corem0 = {
static struct clksrc_clk clk_aclk_cores = {
.clk = {
.name = "aclk_cores",
- .id = -1,
.parent = &clk_coreclk.clk,
},
.reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
@@ -222,7 +209,6 @@ static struct clksrc_clk clk_aclk_cores = {
static struct clksrc_clk clk_aclk_corem1 = {
.clk = {
.name = "aclk_corem1",
- .id = -1,
.parent = &clk_coreclk.clk,
},
.reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
@@ -231,7 +217,6 @@ static struct clksrc_clk clk_aclk_corem1 = {
static struct clksrc_clk clk_periphclk = {
.clk = {
.name = "periphclk",
- .id = -1,
.parent = &clk_coreclk.clk,
},
.reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
@@ -252,7 +237,6 @@ static struct clksrc_sources clkset_mout_corebus = {
static struct clksrc_clk clk_mout_corebus = {
.clk = {
.name = "mout_corebus",
- .id = -1,
},
.sources = &clkset_mout_corebus,
.reg_src = { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
@@ -261,7 +245,6 @@ static struct clksrc_clk clk_mout_corebus = {
static struct clksrc_clk clk_sclk_dmc = {
.clk = {
.name = "sclk_dmc",
- .id = -1,
.parent = &clk_mout_corebus.clk,
},
.reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
@@ -270,7 +253,6 @@ static struct clksrc_clk clk_sclk_dmc = {
static struct clksrc_clk clk_aclk_cored = {
.clk = {
.name = "aclk_cored",
- .id = -1,
.parent = &clk_sclk_dmc.clk,
},
.reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
@@ -279,7 +261,6 @@ static struct clksrc_clk clk_aclk_cored = {
static struct clksrc_clk clk_aclk_corep = {
.clk = {
.name = "aclk_corep",
- .id = -1,
.parent = &clk_aclk_cored.clk,
},
.reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
@@ -288,7 +269,6 @@ static struct clksrc_clk clk_aclk_corep = {
static struct clksrc_clk clk_aclk_acp = {
.clk = {
.name = "aclk_acp",
- .id = -1,
.parent = &clk_mout_corebus.clk,
},
.reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
@@ -297,7 +277,6 @@ static struct clksrc_clk clk_aclk_acp = {
static struct clksrc_clk clk_pclk_acp = {
.clk = {
.name = "pclk_acp",
- .id = -1,
.parent = &clk_aclk_acp.clk,
},
.reg_div = { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
@@ -318,7 +297,6 @@ static struct clksrc_sources clkset_aclk = {
static struct clksrc_clk clk_aclk_200 = {
.clk = {
.name = "aclk_200",
- .id = -1,
},
.sources = &clkset_aclk,
.reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
@@ -328,7 +306,6 @@ static struct clksrc_clk clk_aclk_200 = {
static struct clksrc_clk clk_aclk_100 = {
.clk = {
.name = "aclk_100",
- .id = -1,
},
.sources = &clkset_aclk,
.reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
@@ -338,7 +315,6 @@ static struct clksrc_clk clk_aclk_100 = {
static struct clksrc_clk clk_aclk_160 = {
.clk = {
.name = "aclk_160",
- .id = -1,
},
.sources = &clkset_aclk,
.reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
@@ -348,7 +324,6 @@ static struct clksrc_clk clk_aclk_160 = {
static struct clksrc_clk clk_aclk_133 = {
.clk = {
.name = "aclk_133",
- .id = -1,
},
.sources = &clkset_aclk,
.reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
@@ -368,7 +343,6 @@ static struct clksrc_sources clkset_vpllsrc = {
static struct clksrc_clk clk_vpllsrc = {
.clk = {
.name = "vpll_src",
- .id = -1,
.enable = exynos4_clksrc_mask_top_ctrl,
.ctrlbit = (1 << 0),
},
@@ -389,7 +363,6 @@ static struct clksrc_sources clkset_sclk_vpll = {
static struct clksrc_clk clk_sclk_vpll = {
.clk = {
.name = "sclk_vpll",
- .id = -1,
},
.sources = &clkset_sclk_vpll,
.reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
@@ -398,161 +371,151 @@ static struct clksrc_clk clk_sclk_vpll = {
static struct clk init_clocks_off[] = {
{
.name = "timers",
- .id = -1,
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1<<24),
}, {
.name = "csis",
- .id = 0,
+ .devname = "s5p-mipi-csis.0",
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "csis",
- .id = 1,
+ .devname = "s5p-mipi-csis.1",
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "fimc",
- .id = 0,
+ .devname = "exynos4-fimc.0",
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "fimc",
- .id = 1,
+ .devname = "exynos4-fimc.1",
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "fimc",
- .id = 2,
+ .devname = "exynos4-fimc.2",
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "fimc",
- .id = 3,
+ .devname = "exynos4-fimc.3",
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "fimd",
- .id = 0,
+ .devname = "exynos4-fb.0",
.enable = exynos4_clk_ip_lcd0_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "fimd",
- .id = 1,
+ .devname = "exynos4-fb.1",
.enable = exynos4_clk_ip_lcd1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "sataphy",
- .id = -1,
.parent = &clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "hsmmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "hsmmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "hsmmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "hsmmc",
- .id = 3,
+ .devname = "s3c-sdhci.3",
.parent = &clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 8),
}, {
- .name = "hsmmc",
- .id = 4,
+ .name = "dwmmc",
.parent = &clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "sata",
- .id = -1,
.parent = &clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 10),
}, {
.name = "pdma",
- .id = 0,
+ .devname = "s3c-pl330.0",
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "pdma",
- .id = 1,
+ .devname = "s3c-pl330.1",
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "adc",
- .id = -1,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 15),
}, {
.name = "keypad",
- .id = -1,
.enable = exynos4_clk_ip_perir_ctrl,
.ctrlbit = (1 << 16),
}, {
.name = "rtc",
- .id = -1,
.enable = exynos4_clk_ip_perir_ctrl,
.ctrlbit = (1 << 15),
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_perir_ctrl,
.ctrlbit = (1 << 14),
}, {
.name = "usbhost",
- .id = -1,
.enable = exynos4_clk_ip_fsys_ctrl ,
.ctrlbit = (1 << 12),
}, {
.name = "otg",
- .id = -1,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 13),
}, {
.name = "spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 16),
}, {
.name = "spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 17),
}, {
.name = "spi",
- .id = 2,
+ .devname = "s3c64xx-spi.2",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 18),
}, {
.name = "iis",
- .id = 0,
+ .devname = "samsung-i2s.0",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 19),
}, {
.name = "iis",
- .id = 1,
+ .devname = "samsung-i2s.1",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 20),
}, {
.name = "iis",
- .id = 2,
+ .devname = "samsung-i2s.2",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 21),
}, {
@@ -562,125 +525,115 @@ static struct clk init_clocks_off[] = {
.ctrlbit = (1 << 27),
}, {
.name = "fimg2d",
- .id = -1,
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 0),
}, {
+ .name = "mfc",
+ .devname = "s5p-mfc",
+ .enable = exynos4_clk_ip_mfc_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
.name = "i2c",
- .id = 0,
+ .devname = "s3c2440-i2c.0",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "i2c",
- .id = 1,
+ .devname = "s3c2440-i2c.1",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "i2c",
- .id = 2,
+ .devname = "s3c2440-i2c.2",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "i2c",
- .id = 3,
+ .devname = "s3c2440-i2c.3",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "i2c",
- .id = 4,
+ .devname = "s3c2440-i2c.4",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 10),
}, {
.name = "i2c",
- .id = 5,
+ .devname = "s3c2440-i2c.5",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 11),
}, {
.name = "i2c",
- .id = 6,
+ .devname = "s3c2440-i2c.6",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "i2c",
- .id = 7,
+ .devname = "s3c2440-i2c.7",
.parent = &clk_aclk_100.clk,
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 13),
}, {
.name = "SYSMMU_MDMA",
- .id = -1,
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "SYSMMU_FIMC0",
- .id = -1,
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "SYSMMU_FIMC1",
- .id = -1,
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "SYSMMU_FIMC2",
- .id = -1,
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "SYSMMU_FIMC3",
- .id = -1,
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 10),
}, {
.name = "SYSMMU_JPEG",
- .id = -1,
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 11),
}, {
.name = "SYSMMU_FIMD0",
- .id = -1,
.enable = exynos4_clk_ip_lcd0_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_FIMD1",
- .id = -1,
.enable = exynos4_clk_ip_lcd1_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_PCIe",
- .id = -1,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 18),
}, {
.name = "SYSMMU_G2D",
- .id = -1,
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "SYSMMU_ROTATOR",
- .id = -1,
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_TV",
- .id = -1,
.enable = exynos4_clk_ip_tv_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_MFC_L",
- .id = -1,
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "SYSMMU_MFC_R",
- .id = -1,
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 2),
}
@@ -689,32 +642,32 @@ static struct clk init_clocks_off[] = {
static struct clk init_clocks[] = {
{
.name = "uart",
- .id = 0,
+ .devname = "s5pv210-uart.0",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "uart",
- .id = 1,
+ .devname = "s5pv210-uart.1",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "uart",
- .id = 2,
+ .devname = "s5pv210-uart.2",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "uart",
- .id = 3,
+ .devname = "s5pv210-uart.3",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "uart",
- .id = 4,
+ .devname = "s5pv210-uart.4",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "uart",
- .id = 5,
+ .devname = "s5pv210-uart.5",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 5),
}
@@ -750,7 +703,6 @@ static struct clksrc_sources clkset_mout_g2d0 = {
static struct clksrc_clk clk_mout_g2d0 = {
.clk = {
.name = "mout_g2d0",
- .id = -1,
},
.sources = &clkset_mout_g2d0,
.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
@@ -769,7 +721,6 @@ static struct clksrc_sources clkset_mout_g2d1 = {
static struct clksrc_clk clk_mout_g2d1 = {
.clk = {
.name = "mout_g2d1",
- .id = -1,
},
.sources = &clkset_mout_g2d1,
.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
@@ -785,10 +736,55 @@ static struct clksrc_sources clkset_mout_g2d = {
.nr_sources = ARRAY_SIZE(clkset_mout_g2d_list),
};
+static struct clk *clkset_mout_mfc0_list[] = {
+ [0] = &clk_mout_mpll.clk,
+ [1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc0 = {
+ .sources = clkset_mout_mfc0_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_mfc0_list),
+};
+
+static struct clksrc_clk clk_mout_mfc0 = {
+ .clk = {
+ .name = "mout_mfc0",
+ },
+ .sources = &clkset_mout_mfc0,
+ .reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc1_list[] = {
+ [0] = &clk_mout_epll.clk,
+ [1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc1 = {
+ .sources = clkset_mout_mfc1_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_mfc1_list),
+};
+
+static struct clksrc_clk clk_mout_mfc1 = {
+ .clk = {
+ .name = "mout_mfc1",
+ },
+ .sources = &clkset_mout_mfc1,
+ .reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc_list[] = {
+ [0] = &clk_mout_mfc0.clk,
+ [1] = &clk_mout_mfc1.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc = {
+ .sources = clkset_mout_mfc_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_mfc_list),
+};
+
static struct clksrc_clk clk_dout_mmc0 = {
.clk = {
.name = "dout_mmc0",
- .id = -1,
},
.sources = &clkset_group,
.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
@@ -798,7 +794,6 @@ static struct clksrc_clk clk_dout_mmc0 = {
static struct clksrc_clk clk_dout_mmc1 = {
.clk = {
.name = "dout_mmc1",
- .id = -1,
},
.sources = &clkset_group,
.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
@@ -808,7 +803,6 @@ static struct clksrc_clk clk_dout_mmc1 = {
static struct clksrc_clk clk_dout_mmc2 = {
.clk = {
.name = "dout_mmc2",
- .id = -1,
},
.sources = &clkset_group,
.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
@@ -818,7 +812,6 @@ static struct clksrc_clk clk_dout_mmc2 = {
static struct clksrc_clk clk_dout_mmc3 = {
.clk = {
.name = "dout_mmc3",
- .id = -1,
},
.sources = &clkset_group,
.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
@@ -828,7 +821,6 @@ static struct clksrc_clk clk_dout_mmc3 = {
static struct clksrc_clk clk_dout_mmc4 = {
.clk = {
.name = "dout_mmc4",
- .id = -1,
},
.sources = &clkset_group,
.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
@@ -839,7 +831,7 @@ static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "uclk1",
- .id = 0,
+ .devname = "s5pv210-uart.0",
.enable = exynos4_clksrc_mask_peril0_ctrl,
.ctrlbit = (1 << 0),
},
@@ -849,7 +841,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = 1,
+ .devname = "s5pv210-uart.1",
.enable = exynos4_clksrc_mask_peril0_ctrl,
.ctrlbit = (1 << 4),
},
@@ -859,7 +851,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = 2,
+ .devname = "s5pv210-uart.2",
.enable = exynos4_clksrc_mask_peril0_ctrl,
.ctrlbit = (1 << 8),
},
@@ -869,7 +861,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = 3,
+ .devname = "s5pv210-uart.3",
.enable = exynos4_clksrc_mask_peril0_ctrl,
.ctrlbit = (1 << 12),
},
@@ -879,7 +871,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_pwm",
- .id = -1,
.enable = exynos4_clksrc_mask_peril0_ctrl,
.ctrlbit = (1 << 24),
},
@@ -889,7 +880,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_csis",
- .id = 0,
+ .devname = "s5p-mipi-csis.0",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 24),
},
@@ -899,7 +890,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_csis",
- .id = 1,
+ .devname = "s5p-mipi-csis.1",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 28),
},
@@ -909,7 +900,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_cam",
- .id = 0,
+ .devname = "exynos4-fimc.0",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 16),
},
@@ -919,7 +910,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_cam",
- .id = 1,
+ .devname = "exynos4-fimc.1",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 20),
},
@@ -929,7 +920,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 0,
+ .devname = "exynos4-fimc.0",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 0),
},
@@ -939,7 +930,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 1,
+ .devname = "exynos4-fimc.1",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 4),
},
@@ -949,7 +940,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 2,
+ .devname = "exynos4-fimc.2",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 8),
},
@@ -959,7 +950,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 3,
+ .devname = "exynos4-fimc.3",
.enable = exynos4_clksrc_mask_cam_ctrl,
.ctrlbit = (1 << 12),
},
@@ -969,7 +960,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimd",
- .id = 0,
+ .devname = "exynos4-fb.0",
.enable = exynos4_clksrc_mask_lcd0_ctrl,
.ctrlbit = (1 << 0),
},
@@ -979,7 +970,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimd",
- .id = 1,
+ .devname = "exynos4-fb.1",
.enable = exynos4_clksrc_mask_lcd1_ctrl,
.ctrlbit = (1 << 0),
},
@@ -989,7 +980,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_sata",
- .id = -1,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 24),
},
@@ -999,7 +989,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.enable = exynos4_clksrc_mask_peril1_ctrl,
.ctrlbit = (1 << 16),
},
@@ -1009,7 +999,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.enable = exynos4_clksrc_mask_peril1_ctrl,
.ctrlbit = (1 << 20),
},
@@ -1019,7 +1009,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 2,
+ .devname = "s3c64xx-spi.2",
.enable = exynos4_clksrc_mask_peril1_ctrl,
.ctrlbit = (1 << 24),
},
@@ -1029,15 +1019,22 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimg2d",
- .id = -1,
},
.sources = &clkset_mout_g2d,
.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
}, {
.clk = {
+ .name = "sclk_mfc",
+ .devname = "s5p-mfc",
+ },
+ .sources = &clkset_mout_mfc,
+ .reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
.name = "sclk_mmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_dout_mmc0.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 0),
@@ -1046,7 +1043,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_dout_mmc1.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 4),
@@ -1055,7 +1052,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_dout_mmc2.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 8),
@@ -1064,7 +1061,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 3,
+ .devname = "s3c-sdhci.3",
.parent = &clk_dout_mmc3.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 12),
@@ -1072,8 +1069,7 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
}, {
.clk = {
- .name = "sclk_mmc",
- .id = 4,
+ .name = "sclk_dwmmc",
.parent = &clk_dout_mmc4.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 16),
@@ -1112,6 +1108,8 @@ static struct clksrc_clk *sysclks[] = {
&clk_dout_mmc2,
&clk_dout_mmc3,
&clk_dout_mmc4,
+ &clk_mout_mfc0,
+ &clk_mout_mfc1,
};
static int xtal_rate;
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index bfd621460abf..2d8a40c9e6e5 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -16,12 +16,16 @@
#include <asm/proc-fns.h>
#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
#include <plat/cpu.h>
#include <plat/clock.h>
+#include <plat/devs.h>
#include <plat/exynos4.h>
+#include <plat/adc-core.h>
#include <plat/sdhci.h>
#include <plat/devs.h>
+#include <plat/fb-core.h>
#include <plat/fimc-core.h>
#include <plat/iic-core.h>
@@ -103,7 +107,17 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
.length = SZ_4K,
.type = MT_DEVICE,
- }
+ }, {
+ .virtual = (unsigned long)S5P_VA_GIC_CPU,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
+ .length = SZ_64K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_GIC_DIST,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
+ .length = SZ_64K,
+ .type = MT_DEVICE,
+ },
};
static void exynos4_idle(void)
@@ -129,6 +143,8 @@ void __init exynos4_map_io(void)
exynos4_default_sdhci2();
exynos4_default_sdhci3();
+ s3c_adc_setname("samsung-adc-v3");
+
s3c_fimc_setname(0, "exynos4-fimc");
s3c_fimc_setname(1, "exynos4-fimc");
s3c_fimc_setname(2, "exynos4-fimc");
@@ -138,6 +154,8 @@ void __init exynos4_map_io(void)
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
s3c_i2c2_setname("s3c2440-i2c");
+
+ s5p_fb_setname(0, "exynos4-fb");
}
void __init exynos4_init_clocks(int xtal)
@@ -150,22 +168,23 @@ void __init exynos4_init_clocks(int xtal)
exynos4_setup_clocks();
}
+static void exynos4_gic_irq_eoi(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());
+}
+
void __init exynos4_init_irq(void)
{
int irq;
- gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+ gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+ gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
- /*
- * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
- * connected to the interrupt combiner. These irqs
- * should be initialized to support cascade interrupt.
- */
- if ((irq >= 40) && !(irq == 51) && !(irq == 53))
- continue;
-
combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
COMBINER_IRQ(irq, 0));
combiner_cascade_irq(irq, IRQ_SPI(irq));
diff --git a/arch/arm/mach-exynos4/dev-audio.c b/arch/arm/mach-exynos4/dev-audio.c
index 983069a53239..5a9f9c2e53bf 100644
--- a/arch/arm/mach-exynos4/dev-audio.c
+++ b/arch/arm/mach-exynos4/dev-audio.c
@@ -21,6 +21,7 @@
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
+#include <mach/regs-audss.h>
static const char *rclksrc[] = {
[0] = "busclk",
@@ -55,6 +56,7 @@ static struct s3c_audio_pdata i2sv5_pdata = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
| QUIRK_NEED_RSTCLR,
.src_clk = rclksrc,
+ .idma_addr = EXYNOS4_AUDSS_INT_MEM,
},
},
};
diff --git a/arch/arm/mach-exynos4/dev-dwmci.c b/arch/arm/mach-exynos4/dev-dwmci.c
new file mode 100644
index 000000000000..b025db4bf602
--- /dev/null
+++ b/arch/arm/mach-exynos4/dev-dwmci.c
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/arm/mach-exynos4/dev-dwmci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Platform device for Synopsys DesignWare Mobile Storage IP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/dw_mmc.h>
+
+#include <plat/devs.h>
+
+#include <mach/map.h>
+
+static int exynos4_dwmci_get_bus_wd(u32 slot_id)
+{
+ return 4;
+}
+
+static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
+{
+ return 0;
+}
+
+static struct resource exynos4_dwmci_resource[] = {
+ [0] = {
+ .start = EXYNOS4_PA_DWMCI,
+ .end = EXYNOS4_PA_DWMCI + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_DWMCI,
+ .end = IRQ_DWMCI,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct dw_mci_board exynos4_dwci_pdata = {
+ .num_slots = 1,
+ .quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+ .bus_hz = 80 * 1000 * 1000,
+ .detect_delay_ms = 200,
+ .init = exynos4_dwmci_init,
+ .get_bus_wd = exynos4_dwmci_get_bus_wd,
+};
+
+static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_dwmci = {
+ .name = "dw_mmc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(exynos4_dwmci_resource),
+ .resource = exynos4_dwmci_resource,
+ .dev = {
+ .dma_mask = &exynos4_dwmci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &exynos4_dwci_pdata,
+ },
+};
+
+void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
+{
+ struct dw_mci_board *npd;
+
+ npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
+ &exynos4_device_dwmci);
+
+ if (!npd->init)
+ npd->init = exynos4_dwmci_init;
+ if (!npd->get_bus_wd)
+ npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
+}
diff --git a/arch/arm/mach-exynos4/hotplug.c b/arch/arm/mach-exynos4/hotplug.c
index 2b5909e2ccd3..7490789784c9 100644
--- a/arch/arm/mach-exynos4/hotplug.c
+++ b/arch/arm/mach-exynos4/hotplug.c
@@ -13,9 +13,12 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
+#include <linux/io.h>
#include <asm/cacheflush.h>
+#include <mach/regs-pmu.h>
+
extern volatile int pen_release;
static inline void cpu_enter_lowpower(void)
@@ -58,12 +61,12 @@ static inline void cpu_leave_lowpower(void)
static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
{
- /*
- * there is no power-control hardware on this platform, so all
- * we can do is put the core into WFI; this is safe as the calling
- * code will have already disabled interrupts
- */
for (;;) {
+
+ /* make cpu1 to be turned off at next WFI command */
+ if (cpu == 1)
+ __raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
+
/*
* here's the WFI
*/
diff --git a/arch/arm/mach-exynos4/include/mach/clkdev.h b/arch/arm/mach-exynos4/include/mach/clkdev.h
new file mode 100644
index 000000000000..7dffa83d23ff
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-exynos4/include/mach/dwmci.h b/arch/arm/mach-exynos4/include/mach/dwmci.h
new file mode 100644
index 000000000000..7ce657459cc0
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/dwmci.h
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Synopsys DesignWare Mobile Storage for EXYNOS4210
+ *
+ * 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_ARM_ARCH_DWMCI_H
+#define __ASM_ARM_ARCH_DWMCI_H __FILE__
+
+#include <linux/mmc/dw_mmc.h>
+
+extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
+
+#endif /* __ASM_ARM_ARCH_DWMCI_H */
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index d8f38c2e5654..d7a1e281ce7a 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -10,6 +10,7 @@
*/
#include <mach/hardware.h>
+#include <mach/map.h>
#include <asm/hardware/gic.h>
.macro disable_fiq
@@ -18,6 +19,10 @@
.macro get_irqnr_preamble, base, tmp
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
.endm
.macro arch_ret_to_user, tmp1, tmp2
@@ -75,10 +80,4 @@
/* 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/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 5d037301d21a..934d2a493982 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -19,40 +19,105 @@
#define IRQ_PPI(x) S5P_IRQ(x+16)
-#define IRQ_LOCALTIMER IRQ_PPI(13)
-
/* SPI: Shared Peripheral Interrupt */
#define IRQ_SPI(x) S5P_IRQ(x+32)
-#define IRQ_MCT1 IRQ_SPI(35)
-
-#define IRQ_EINT0 IRQ_SPI(40)
-#define IRQ_EINT1 IRQ_SPI(41)
-#define IRQ_EINT2 IRQ_SPI(42)
-#define IRQ_EINT3 IRQ_SPI(43)
-#define IRQ_USB_HSOTG IRQ_SPI(44)
-#define IRQ_USB_HOST IRQ_SPI(45)
-#define IRQ_MODEM_IF IRQ_SPI(46)
-#define IRQ_ROTATOR IRQ_SPI(47)
-#define IRQ_JPEG IRQ_SPI(48)
-#define IRQ_2D IRQ_SPI(49)
-#define IRQ_PCIE IRQ_SPI(50)
-#define IRQ_MCT0 IRQ_SPI(51)
-#define IRQ_MFC IRQ_SPI(52)
-#define IRQ_AUDIO_SS IRQ_SPI(54)
-#define IRQ_AC97 IRQ_SPI(55)
-#define IRQ_SPDIF IRQ_SPI(56)
-#define IRQ_KEYPAD IRQ_SPI(57)
-#define IRQ_INTFEEDCTRL_SSS IRQ_SPI(58)
-#define IRQ_SLIMBUS IRQ_SPI(59)
-#define IRQ_PMU IRQ_SPI(60)
-#define IRQ_TSI IRQ_SPI(61)
-#define IRQ_SATA IRQ_SPI(62)
-#define IRQ_GPS IRQ_SPI(63)
+#define IRQ_EINT0 IRQ_SPI(16)
+#define IRQ_EINT1 IRQ_SPI(17)
+#define IRQ_EINT2 IRQ_SPI(18)
+#define IRQ_EINT3 IRQ_SPI(19)
+#define IRQ_EINT4 IRQ_SPI(20)
+#define IRQ_EINT5 IRQ_SPI(21)
+#define IRQ_EINT6 IRQ_SPI(22)
+#define IRQ_EINT7 IRQ_SPI(23)
+#define IRQ_EINT8 IRQ_SPI(24)
+#define IRQ_EINT9 IRQ_SPI(25)
+#define IRQ_EINT10 IRQ_SPI(26)
+#define IRQ_EINT11 IRQ_SPI(27)
+#define IRQ_EINT12 IRQ_SPI(28)
+#define IRQ_EINT13 IRQ_SPI(29)
+#define IRQ_EINT14 IRQ_SPI(30)
+#define IRQ_EINT15 IRQ_SPI(31)
+#define IRQ_EINT16_31 IRQ_SPI(32)
+
+#define IRQ_PDMA0 IRQ_SPI(35)
+#define IRQ_PDMA1 IRQ_SPI(36)
+#define IRQ_TIMER0_VIC IRQ_SPI(37)
+#define IRQ_TIMER1_VIC IRQ_SPI(38)
+#define IRQ_TIMER2_VIC IRQ_SPI(39)
+#define IRQ_TIMER3_VIC IRQ_SPI(40)
+#define IRQ_TIMER4_VIC IRQ_SPI(41)
+#define IRQ_MCT_L0 IRQ_SPI(42)
+#define IRQ_WDT IRQ_SPI(43)
+#define IRQ_RTC_ALARM IRQ_SPI(44)
+#define IRQ_RTC_TIC IRQ_SPI(45)
+#define IRQ_GPIO_XB IRQ_SPI(46)
+#define IRQ_GPIO_XA IRQ_SPI(47)
+#define IRQ_MCT_L1 IRQ_SPI(48)
+
+#define IRQ_UART0 IRQ_SPI(52)
+#define IRQ_UART1 IRQ_SPI(53)
+#define IRQ_UART2 IRQ_SPI(54)
+#define IRQ_UART3 IRQ_SPI(55)
+#define IRQ_UART4 IRQ_SPI(56)
+#define IRQ_MCT_G0 IRQ_SPI(57)
+#define IRQ_IIC IRQ_SPI(58)
+#define IRQ_IIC1 IRQ_SPI(59)
+#define IRQ_IIC2 IRQ_SPI(60)
+#define IRQ_IIC3 IRQ_SPI(61)
+#define IRQ_IIC4 IRQ_SPI(62)
+#define IRQ_IIC5 IRQ_SPI(63)
+#define IRQ_IIC6 IRQ_SPI(64)
+#define IRQ_IIC7 IRQ_SPI(65)
+
+#define IRQ_USB_HOST IRQ_SPI(70)
+#define IRQ_USB_HSOTG IRQ_SPI(71)
+#define IRQ_MODEM_IF IRQ_SPI(72)
+#define IRQ_HSMMC0 IRQ_SPI(73)
+#define IRQ_HSMMC1 IRQ_SPI(74)
+#define IRQ_HSMMC2 IRQ_SPI(75)
+#define IRQ_HSMMC3 IRQ_SPI(76)
+#define IRQ_DWMCI IRQ_SPI(77)
+
+#define IRQ_MIPICSI0 IRQ_SPI(78)
+
+#define IRQ_MIPICSI1 IRQ_SPI(80)
+
+#define IRQ_ONENAND_AUDI IRQ_SPI(82)
+#define IRQ_ROTATOR IRQ_SPI(83)
+#define IRQ_FIMC0 IRQ_SPI(84)
+#define IRQ_FIMC1 IRQ_SPI(85)
+#define IRQ_FIMC2 IRQ_SPI(86)
+#define IRQ_FIMC3 IRQ_SPI(87)
+#define IRQ_JPEG IRQ_SPI(88)
+#define IRQ_2D IRQ_SPI(89)
+#define IRQ_PCIE IRQ_SPI(90)
+
+#define IRQ_MFC IRQ_SPI(94)
+
+#define IRQ_AUDIO_SS IRQ_SPI(96)
+#define IRQ_I2S0 IRQ_SPI(97)
+#define IRQ_I2S1 IRQ_SPI(98)
+#define IRQ_I2S2 IRQ_SPI(99)
+#define IRQ_AC97 IRQ_SPI(100)
+
+#define IRQ_SPDIF IRQ_SPI(104)
+#define IRQ_ADC0 IRQ_SPI(105)
+#define IRQ_PEN0 IRQ_SPI(106)
+#define IRQ_ADC1 IRQ_SPI(107)
+#define IRQ_PEN1 IRQ_SPI(108)
+#define IRQ_KEYPAD IRQ_SPI(109)
+#define IRQ_PMU IRQ_SPI(110)
+#define IRQ_GPS IRQ_SPI(111)
+#define IRQ_INTFEEDCTRL_SSS IRQ_SPI(112)
+#define IRQ_SLIMBUS IRQ_SPI(113)
+
+#define IRQ_TSI IRQ_SPI(115)
+#define IRQ_SATA IRQ_SPI(116)
#define MAX_IRQ_IN_COMBINER 8
-#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
#define IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0)
@@ -73,75 +138,14 @@
#define IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6)
#define IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7)
-#define IRQ_PDMA0 COMBINER_IRQ(21, 0)
-#define IRQ_PDMA1 COMBINER_IRQ(21, 1)
-
-#define IRQ_TIMER0_VIC COMBINER_IRQ(22, 0)
-#define IRQ_TIMER1_VIC COMBINER_IRQ(22, 1)
-#define IRQ_TIMER2_VIC COMBINER_IRQ(22, 2)
-#define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3)
-#define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4)
-
-#define IRQ_RTC_ALARM COMBINER_IRQ(23, 0)
-#define IRQ_RTC_TIC COMBINER_IRQ(23, 1)
-
-#define IRQ_GPIO_XB COMBINER_IRQ(24, 0)
-#define IRQ_GPIO_XA COMBINER_IRQ(24, 1)
-
-#define IRQ_UART0 COMBINER_IRQ(26, 0)
-#define IRQ_UART1 COMBINER_IRQ(26, 1)
-#define IRQ_UART2 COMBINER_IRQ(26, 2)
-#define IRQ_UART3 COMBINER_IRQ(26, 3)
-#define IRQ_UART4 COMBINER_IRQ(26, 4)
-
-#define IRQ_IIC COMBINER_IRQ(27, 0)
-#define IRQ_IIC1 COMBINER_IRQ(27, 1)
-#define IRQ_IIC2 COMBINER_IRQ(27, 2)
-#define IRQ_IIC3 COMBINER_IRQ(27, 3)
-#define IRQ_IIC4 COMBINER_IRQ(27, 4)
-#define IRQ_IIC5 COMBINER_IRQ(27, 5)
-#define IRQ_IIC6 COMBINER_IRQ(27, 6)
-#define IRQ_IIC7 COMBINER_IRQ(27, 7)
-
-#define IRQ_HSMMC0 COMBINER_IRQ(29, 0)
-#define IRQ_HSMMC1 COMBINER_IRQ(29, 1)
-#define IRQ_HSMMC2 COMBINER_IRQ(29, 2)
-#define IRQ_HSMMC3 COMBINER_IRQ(29, 3)
-
-#define IRQ_MIPI_CSIS0 COMBINER_IRQ(30, 0)
-#define IRQ_MIPI_CSIS1 COMBINER_IRQ(30, 1)
-
-#define IRQ_FIMC0 COMBINER_IRQ(32, 0)
-#define IRQ_FIMC1 COMBINER_IRQ(32, 1)
-#define IRQ_FIMC2 COMBINER_IRQ(33, 0)
-#define IRQ_FIMC3 COMBINER_IRQ(33, 1)
-
-#define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0)
-
-#define IRQ_MCT_L1 COMBINER_IRQ(35, 3)
-
-#define IRQ_EINT4 COMBINER_IRQ(37, 0)
-#define IRQ_EINT5 COMBINER_IRQ(37, 1)
-#define IRQ_EINT6 COMBINER_IRQ(37, 2)
-#define IRQ_EINT7 COMBINER_IRQ(37, 3)
-#define IRQ_EINT8 COMBINER_IRQ(38, 0)
-
-#define IRQ_EINT9 COMBINER_IRQ(38, 1)
-#define IRQ_EINT10 COMBINER_IRQ(38, 2)
-#define IRQ_EINT11 COMBINER_IRQ(38, 3)
-#define IRQ_EINT12 COMBINER_IRQ(38, 4)
-#define IRQ_EINT13 COMBINER_IRQ(38, 5)
-#define IRQ_EINT14 COMBINER_IRQ(38, 6)
-#define IRQ_EINT15 COMBINER_IRQ(38, 7)
-
-#define IRQ_EINT16_31 COMBINER_IRQ(39, 0)
-
-#define IRQ_MCT_L0 COMBINER_IRQ(51, 0)
+#define IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0)
+#define IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1)
+#define IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2)
-#define IRQ_WDT COMBINER_IRQ(53, 0)
-#define IRQ_MCT_G0 COMBINER_IRQ(53, 4)
+#define MAX_COMBINER_NR 16
-#define MAX_COMBINER_NR 54
+#define IRQ_ADC IRQ_ADC0
+#define IRQ_TC IRQ_PEN0
#define S5P_IRQ_EINT_BASE COMBINER_IRQ(MAX_COMBINER_NR, 0)
@@ -155,6 +159,6 @@
#define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_GPIO_END)
+#define NR_IRQS (IRQ_GPIO_END + 64)
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 0009e77a05fc..d32296dc65e2 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -57,12 +57,14 @@
#define EXYNOS4_PA_DMC0 0x10400000
-#define EXYNOS4_PA_COMBINER 0x10448000
+#define EXYNOS4_PA_COMBINER 0x10440000
+
+#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_GIC_CPU 0x10500100
#define EXYNOS4_PA_TWD 0x10500600
-#define EXYNOS4_PA_GIC_DIST 0x10501000
#define EXYNOS4_PA_L2CC 0x10502000
#define EXYNOS4_PA_MDMA 0x10810000
@@ -93,7 +95,10 @@
#define EXYNOS4_PA_MIPI_CSIS0 0x11880000
#define EXYNOS4_PA_MIPI_CSIS1 0x11890000
+#define EXYNOS4_PA_FIMD0 0x11C00000
+
#define EXYNOS4_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000))
+#define EXYNOS4_PA_DWMCI 0x12550000
#define EXYNOS4_PA_SATA 0x12560000
#define EXYNOS4_PA_SATAPHY 0x125D0000
@@ -103,11 +108,15 @@
#define EXYNOS4_PA_EHCI 0x12580000
#define EXYNOS4_PA_HSPHY 0x125B0000
+#define EXYNOS4_PA_MFC 0x13400000
#define EXYNOS4_PA_UART 0x13800000
#define EXYNOS4_PA_IIC(x) (0x13860000 + ((x) * 0x10000))
+#define EXYNOS4_PA_ADC 0x13910000
+#define EXYNOS4_PA_ADC1 0x13911000
+
#define EXYNOS4_PA_AC97 0x139A0000
#define EXYNOS4_PA_SPDIF 0x139B0000
@@ -130,6 +139,8 @@
#define S3C_PA_IIC5 EXYNOS4_PA_IIC(5)
#define S3C_PA_IIC6 EXYNOS4_PA_IIC(6)
#define S3C_PA_IIC7 EXYNOS4_PA_IIC(7)
+#define SAMSUNG_PA_ADC EXYNOS4_PA_ADC
+#define SAMSUNG_PA_ADC1 EXYNOS4_PA_ADC1
#define S3C_PA_RTC EXYNOS4_PA_RTC
#define S3C_PA_WDT EXYNOS4_PA_WATCHDOG
@@ -140,10 +151,12 @@
#define S5P_PA_FIMC3 EXYNOS4_PA_FIMC3
#define S5P_PA_MIPI_CSIS0 EXYNOS4_PA_MIPI_CSIS0
#define S5P_PA_MIPI_CSIS1 EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_FIMD0 EXYNOS4_PA_FIMD0
#define S5P_PA_ONENAND EXYNOS4_PA_ONENAND
#define S5P_PA_ONENAND_DMA EXYNOS4_PA_ONENAND_DMA
#define S5P_PA_SDRAM EXYNOS4_PA_SDRAM
#define S5P_PA_SROMC EXYNOS4_PA_SROMC
+#define S5P_PA_MFC EXYNOS4_PA_MFC
#define S5P_PA_SYSCON EXYNOS4_PA_SYSCON
#define S5P_PA_TIMER EXYNOS4_PA_TIMER
#define S5P_PA_EHCI EXYNOS4_PA_EHCI
diff --git a/arch/arm/mach-exynos4/include/mach/pm-core.h b/arch/arm/mach-exynos4/include/mach/pm-core.h
index f26e46bc06ca..1df3b81f96e8 100644
--- a/arch/arm/mach-exynos4/include/mach/pm-core.h
+++ b/arch/arm/mach-exynos4/include/mach/pm-core.h
@@ -47,3 +47,13 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
{
/* nothing here yet */
}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+ /* nothing here yet */
+}
+
+static inline void s3c_pm_saved_gpios(void)
+{
+ /* nothing here yet */
+}
diff --git a/arch/arm/mach-exynos4/include/mach/pmu.h b/arch/arm/mach-exynos4/include/mach/pmu.h
new file mode 100644
index 000000000000..a952904b010e
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/pmu.h
@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pmu.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4210 - PMU(Power Management Unit) 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_PMU_H
+#define __ASM_ARCH_PMU_H __FILE__
+
+enum sys_powerdown {
+ SYS_AFTR,
+ SYS_LPA,
+ SYS_SLEEP,
+ NUM_SYS_POWERDOWN,
+};
+
+extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
+
+#endif /* __ASM_ARCH_PMU_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-audss.h b/arch/arm/mach-exynos4/include/mach/regs-audss.h
new file mode 100644
index 000000000000..ca5a8b64218a
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-audss.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-exynos4/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.com
+ *
+ * Exynos4 Audio SubSystem clock register 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define EXYNOS4_AUDSS_INT_MEM (0x03000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h
index 6e311c1157f5..d493fdb422ff 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h
@@ -25,6 +25,9 @@
#define S5P_CLKDIV_STAT_RIGHTBUS S5P_CLKREG(0x08600)
#define S5P_CLKGATE_IP_RIGHTBUS S5P_CLKREG(0x08800)
+#define S5P_EPLL_LOCK S5P_CLKREG(0x0C010)
+#define S5P_VPLL_LOCK S5P_CLKREG(0x0C020)
+
#define S5P_EPLL_CON0 S5P_CLKREG(0x0C110)
#define S5P_EPLL_CON1 S5P_CLKREG(0x0C114)
#define S5P_VPLL_CON0 S5P_CLKREG(0x0C120)
@@ -33,7 +36,9 @@
#define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210)
#define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214)
#define S5P_CLKSRC_CAM S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_TV S5P_CLKREG(0x0C224)
#define S5P_CLKSRC_MFC S5P_CLKREG(0x0C228)
+#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)
@@ -61,6 +66,7 @@
#define S5P_CLKDIV_PERIL3 S5P_CLKREG(0x0C55C)
#define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x0C560)
#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)
@@ -120,6 +126,12 @@
#define S5P_APLL_VAL_1000 ((250 << 16) | (6 << 8) | 1)
#define S5P_APLL_VAL_800 ((200 << 16) | (6 << 8) | 1)
+#define S5P_EPLLCON0_ENABLE_SHIFT (31)
+#define S5P_EPLLCON0_LOCKED_SHIFT (29)
+
+#define S5P_VPLLCON0_ENABLE_SHIFT (31)
+#define S5P_VPLLCON0_LOCKED_SHIFT (29)
+
#define S5P_CLKSRC_CPU_MUXCORE_SHIFT (16)
#define S5P_CLKMUX_STATCPU_MUXCORE_MASK (0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
index a9643371f8e7..fa49bbb8e7b0 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
@@ -158,6 +158,7 @@
#define S5P_PMU_GPS_CONF S5P_PMUREG(0x3CE0)
#define S5P_PMU_SATA_PHY_CONTROL_EN 0x1
+#define S5P_CORE_LOCAL_PWR_EN 0x3
#define S5P_INT_LOCAL_PWR_EN 0x7
#define S5P_CHECK_SLEEP 0x00000BAD
diff --git a/arch/arm/mach-exynos4/localtimer.c b/arch/arm/mach-exynos4/localtimer.c
deleted file mode 100644
index 6bf3d0ab9627..000000000000
--- a/arch/arm/mach-exynos4/localtimer.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-exynos4/localtimer.c
- *
- * Cloned from linux/arch/arm/mach-realview/localtimer.c
- *
- * Copyright (C) 2002 ARM Ltd.
- * 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/clockchips.h>
-
-#include <asm/irq.h>
-#include <asm/localtimer.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
- evt->irq = IRQ_LOCALTIMER;
- twd_timer_setup(evt);
- return 0;
-}
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index 642702bb5b12..43be71b799cb 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -13,10 +13,15 @@
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/i2c-gpio.h>
#include <linux/gpio_keys.h>
#include <linux/gpio.h>
+#include <linux/power/max8903_charger.h>
+#include <linux/power/max17042_battery.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
#include <linux/mmc/host.h>
#include <linux/fb.h>
#include <linux/pwm_backlight.h>
@@ -26,6 +31,7 @@
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
+#include <plat/adc.h>
#include <plat/regs-serial.h>
#include <plat/exynos4.h>
#include <plat/cpu.h>
@@ -35,6 +41,8 @@
#include <plat/clock.h>
#include <plat/gpio-cfg.h>
#include <plat/iic.h>
+#include <plat/mfc.h>
+#include <plat/pd.h>
#include <mach/map.h>
@@ -54,6 +62,7 @@
enum fixed_regulator_id {
FIXED_REG_ID_MMC = 0,
+ FIXED_REG_ID_MAX8903,
};
static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
@@ -344,10 +353,730 @@ static void __init nuri_tsp_init(void)
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
}
+static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
+ REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
+ REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
+ REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
+ REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
+ REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
+ REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
+ REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
+ REGULATOR_SUPPLY("vcc", "platform-lcd"), /* U804 LVDS */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
+ REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
+ REGULATOR_SUPPLY("inmotor", "max8997-haptic"),
+};
+static struct regulator_consumer_supply __initdata max8997_ldo15_[] = {
+ REGULATOR_SUPPLY("avdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo16_[] = {
+ REGULATOR_SUPPLY("d_sensor", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo18_[] = {
+ REGULATOR_SUPPLY("vdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
+ REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
+ REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
+ REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck4_[] = {
+ REGULATOR_SUPPLY("core", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck6_[] = {
+ REGULATOR_SUPPLY("dig_28", "0-001f"), /* pin "7" of HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout1_[] = {
+ REGULATOR_SUPPLY("usb_vbus", NULL), /* CPU's USB OTG */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout2_[] = {
+ REGULATOR_SUPPLY("usb_vbus", "modemctl"), /* VBUS of Modem */
+};
+
+static struct regulator_consumer_supply __initdata max8997_charger_[] = {
+ REGULATOR_SUPPLY("vinchg1", "charger-manager.0"),
+};
+static struct regulator_consumer_supply __initdata max8997_chg_toff_[] = {
+ REGULATOR_SUPPLY("vinchg_stop", NULL), /* for jack interrupt handlers */
+};
+
+static struct regulator_consumer_supply __initdata max8997_32khz_ap_[] = {
+ REGULATOR_SUPPLY("gps_clk", "bcm4751"),
+ REGULATOR_SUPPLY("bt_clk", "bcm4330-b1"),
+ REGULATOR_SUPPLY("wifi_clk", "bcm433-b1"),
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+ .constraints = {
+ .name = "VADC_3.3V_C210",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo1_),
+ .consumer_supplies = max8997_ldo1_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+ .constraints = {
+ .name = "VALIVE_1.1V_C210",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+ .constraints = {
+ .name = "VUSB_1.1V_C210",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo3_),
+ .consumer_supplies = max8997_ldo3_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+ .constraints = {
+ .name = "VMIPI_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo4_),
+ .consumer_supplies = max8997_ldo4_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo5_data = {
+ .constraints = {
+ .name = "VHSIC_1.2V_C210",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo5_),
+ .consumer_supplies = max8997_ldo5_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+ .constraints = {
+ .name = "VCC_1.8V_PDA",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+ .constraints = {
+ .name = "CAM_ISP_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo7_),
+ .consumer_supplies = max8997_ldo7_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+ .constraints = {
+ .name = "VUSB/VDAC_3.3V_C210",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo8_),
+ .consumer_supplies = max8997_ldo8_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+ .constraints = {
+ .name = "VCC_2.8V_PDA",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+ .constraints = {
+ .name = "VPLL_1.1V_C210",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+ .constraints = {
+ .name = "LVDS_VDD3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .boot_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo11_),
+ .consumer_supplies = max8997_ldo11_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo12_data = {
+ .constraints = {
+ .name = "VT_CAM_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo12_),
+ .consumer_supplies = max8997_ldo12_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo13_data = {
+ .constraints = {
+ .name = "VTF_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo13_),
+ .consumer_supplies = max8997_ldo13_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+ .constraints = {
+ .name = "VCC_3.0V_MOTOR",
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo14_),
+ .consumer_supplies = max8997_ldo14_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo15_data = {
+ .constraints = {
+ .name = "VTOUCH_ADVV2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo15_),
+ .consumer_supplies = max8997_ldo15_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo16_data = {
+ .constraints = {
+ .name = "CAM_SENSOR_IO_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo16_),
+ .consumer_supplies = max8997_ldo16_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo18_data = {
+ .constraints = {
+ .name = "VTOUCH_VDD2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_ldo18_),
+ .consumer_supplies = max8997_ldo18_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+ .constraints = {
+ .name = "VDDQ_M1M2_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+ .constraints = {
+ .name = "VARM_1.2V_C210",
+ .min_uV = 900000,
+ .max_uV = 1350000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_buck1_),
+ .consumer_supplies = max8997_buck1_,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+ .constraints = {
+ .name = "VINT_1.1V_C210",
+ .min_uV = 900000,
+ .max_uV = 1100000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_buck2_),
+ .consumer_supplies = max8997_buck2_,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+ .constraints = {
+ .name = "VG3D_1.1V_C210",
+ .min_uV = 900000,
+ .max_uV = 1100000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_buck3_),
+ .consumer_supplies = max8997_buck3_,
+};
+
+static struct regulator_init_data __initdata max8997_buck4_data = {
+ .constraints = {
+ .name = "CAM_ISP_CORE_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_buck4_),
+ .consumer_supplies = max8997_buck4_,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+ .constraints = {
+ .name = "VMEM_1.2V_C210",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_buck6_data = {
+ .constraints = {
+ .name = "CAM_AF_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_buck6_),
+ .consumer_supplies = max8997_buck6_,
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+ .constraints = {
+ .name = "VCC_SUB_2.0V",
+ .min_uV = 2000000,
+ .max_uV = 2000000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_32khz_ap_data = {
+ .constraints = {
+ .name = "32KHz AP",
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_32khz_ap_),
+ .consumer_supplies = max8997_32khz_ap_,
+};
+
+static struct regulator_init_data __initdata max8997_32khz_cp_data = {
+ .constraints = {
+ .name = "32KHz CP",
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_vichg_data = {
+ .constraints = {
+ .name = "VICHG",
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data __initdata max8997_esafeout1_data = {
+ .constraints = {
+ .name = "SAFEOUT1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_esafeout1_),
+ .consumer_supplies = max8997_esafeout1_,
+};
+
+static struct regulator_init_data __initdata max8997_esafeout2_data = {
+ .constraints = {
+ .name = "SAFEOUT2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_esafeout2_),
+ .consumer_supplies = max8997_esafeout2_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_cv_data = {
+ .constraints = {
+ .name = "CHARGER_CV",
+ .min_uV = 4200000,
+ .max_uV = 4200000,
+ .apply_uV = 1,
+ },
+};
+
+static struct regulator_init_data __initdata max8997_charger_data = {
+ .constraints = {
+ .name = "CHARGER",
+ .min_uA = 200000,
+ .max_uA = 950000,
+ .boot_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+ REGULATOR_CHANGE_CURRENT,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_charger_),
+ .consumer_supplies = max8997_charger_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_topoff_data = {
+ .constraints = {
+ .name = "CHARGER TOPOFF",
+ .min_uA = 50000,
+ .max_uA = 200000,
+ .valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(max8997_chg_toff_),
+ .consumer_supplies = max8997_chg_toff_,
+};
+
+static struct max8997_regulator_data __initdata nuri_max8997_regulators[] = {
+ { MAX8997_LDO1, &max8997_ldo1_data },
+ { MAX8997_LDO2, &max8997_ldo2_data },
+ { MAX8997_LDO3, &max8997_ldo3_data },
+ { MAX8997_LDO4, &max8997_ldo4_data },
+ { MAX8997_LDO5, &max8997_ldo5_data },
+ { MAX8997_LDO6, &max8997_ldo6_data },
+ { MAX8997_LDO7, &max8997_ldo7_data },
+ { MAX8997_LDO8, &max8997_ldo8_data },
+ { MAX8997_LDO9, &max8997_ldo9_data },
+ { MAX8997_LDO10, &max8997_ldo10_data },
+ { MAX8997_LDO11, &max8997_ldo11_data },
+ { MAX8997_LDO12, &max8997_ldo12_data },
+ { MAX8997_LDO13, &max8997_ldo13_data },
+ { MAX8997_LDO14, &max8997_ldo14_data },
+ { MAX8997_LDO15, &max8997_ldo15_data },
+ { MAX8997_LDO16, &max8997_ldo16_data },
+
+ { MAX8997_LDO18, &max8997_ldo18_data },
+ { MAX8997_LDO21, &max8997_ldo21_data },
+
+ { MAX8997_BUCK1, &max8997_buck1_data },
+ { MAX8997_BUCK2, &max8997_buck2_data },
+ { MAX8997_BUCK3, &max8997_buck3_data },
+ { MAX8997_BUCK4, &max8997_buck4_data },
+ { MAX8997_BUCK5, &max8997_buck5_data },
+ { MAX8997_BUCK6, &max8997_buck6_data },
+ { MAX8997_BUCK7, &max8997_buck7_data },
+
+ { MAX8997_EN32KHZ_AP, &max8997_32khz_ap_data },
+ { MAX8997_EN32KHZ_CP, &max8997_32khz_cp_data },
+
+ { MAX8997_ENVICHG, &max8997_vichg_data },
+ { MAX8997_ESAFEOUT1, &max8997_esafeout1_data },
+ { MAX8997_ESAFEOUT2, &max8997_esafeout2_data },
+ { MAX8997_CHARGER_CV, &max8997_charger_cv_data },
+ { MAX8997_CHARGER, &max8997_charger_data },
+ { MAX8997_CHARGER_TOPOFF, &max8997_charger_topoff_data },
+};
+
+static struct max8997_platform_data __initdata nuri_max8997_pdata = {
+ .wakeup = 1,
+
+ .num_regulators = ARRAY_SIZE(nuri_max8997_regulators),
+ .regulators = nuri_max8997_regulators,
+
+ .buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
+ .buck2_gpiodvs = true,
+
+ .buck1_voltage[0] = 1350000, /* 1.35V */
+ .buck1_voltage[1] = 1300000, /* 1.3V */
+ .buck1_voltage[2] = 1250000, /* 1.25V */
+ .buck1_voltage[3] = 1200000, /* 1.2V */
+ .buck1_voltage[4] = 1150000, /* 1.15V */
+ .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] = 1200000, /* 1.2V */
+ .buck5_voltage[1] = 1200000, /* 1.2V */
+ .buck5_voltage[2] = 1200000, /* 1.2V */
+ .buck5_voltage[3] = 1200000, /* 1.2V */
+ .buck5_voltage[4] = 1200000, /* 1.2V */
+ .buck5_voltage[5] = 1200000, /* 1.2V */
+ .buck5_voltage[6] = 1200000, /* 1.2V */
+ .buck5_voltage[7] = 1200000, /* 1.2V */
+};
+
/* GPIO I2C 5 (PMIC) */
+enum { I2C5_MAX8997 };
static struct i2c_board_info i2c5_devs[] __initdata = {
- /* max8997, To be updated */
+ [I2C5_MAX8997] = {
+ I2C_BOARD_INFO("max8997", 0xCC >> 1),
+ .platform_data = &nuri_max8997_pdata,
+ },
+};
+
+static struct max17042_platform_data nuri_battery_platform_data = {
+};
+
+/* GPIO I2C 9 (Fuel Gauge) */
+static struct i2c_gpio_platform_data i2c9_gpio_data = {
+ .sda_pin = EXYNOS4_GPY4(0), /* XM0ADDR_8 */
+ .scl_pin = EXYNOS4_GPY4(1), /* XM0ADDR_9 */
+};
+static struct platform_device i2c9_gpio = {
+ .name = "i2c-gpio",
+ .id = 9,
+ .dev = {
+ .platform_data = &i2c9_gpio_data,
+ },
};
+enum { I2C9_MAX17042};
+static struct i2c_board_info i2c9_devs[] __initdata = {
+ [I2C9_MAX17042] = {
+ I2C_BOARD_INFO("max17042", 0x36),
+ .platform_data = &nuri_battery_platform_data,
+ },
+};
+
+/* MAX8903 Secondary Charger */
+static struct regulator_consumer_supply supplies_max8903[] = {
+ REGULATOR_SUPPLY("vinchg2", "charger-manager.0"),
+};
+
+static struct regulator_init_data max8903_charger_en_data = {
+ .constraints = {
+ .name = "VOUT_CHARGER",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(supplies_max8903),
+ .consumer_supplies = supplies_max8903,
+};
+
+static struct fixed_voltage_config max8903_charger_en = {
+ .supply_name = "VOUT_CHARGER",
+ .microvolts = 5000000, /* Assume 5VDC */
+ .gpio = EXYNOS4_GPY4(5), /* TA_EN negaged */
+ .enable_high = 0, /* Enable = Low */
+ .enabled_at_boot = 1,
+ .init_data = &max8903_charger_en_data,
+};
+
+static struct platform_device max8903_fixed_reg_dev = {
+ .name = "reg-fixed-voltage",
+ .id = FIXED_REG_ID_MAX8903,
+ .dev = { .platform_data = &max8903_charger_en },
+};
+
+static struct max8903_pdata nuri_max8903 = {
+ /*
+ * cen: don't control with the driver, let it be
+ * controlled by regulator above
+ */
+ .dok = EXYNOS4_GPX1(4), /* TA_nCONNECTED */
+ /* uok, usus: not connected */
+ .chg = EXYNOS4_GPE2(0), /* TA_nCHG */
+ /* flt: vcc_1.8V_pda */
+ .dcm = EXYNOS4_GPL0(1), /* CURR_ADJ */
+
+ .dc_valid = true,
+ .usb_valid = false, /* USB is not wired to MAX8903 */
+};
+
+static struct platform_device nuri_max8903_device = {
+ .name = "max8903-charger",
+ .dev = {
+ .platform_data = &nuri_max8903,
+ },
+};
+
+static struct device *nuri_cm_devices[] = {
+ &s3c_device_i2c5.dev,
+ &s3c_device_adc.dev,
+ NULL, /* Reserved for UART */
+ NULL,
+};
+
+static void __init nuri_power_init(void)
+{
+ int gpio;
+ int irq_base = IRQ_GPIO_END + 1;
+ int ta_en = 0;
+
+ nuri_max8997_pdata.irq_base = irq_base;
+ irq_base += MAX8997_IRQ_NR;
+
+ gpio = EXYNOS4_GPX0(7);
+ gpio_request(gpio, "AP_PMIC_IRQ");
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+ gpio = EXYNOS4_GPX2(3);
+ gpio_request(gpio, "FUEL_ALERT");
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+ gpio = nuri_max8903.dok;
+ gpio_request(gpio, "TA_nCONNECTED");
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ ta_en = gpio_get_value(gpio) ? 0 : 1;
+
+ gpio = nuri_max8903.chg;
+ gpio_request(gpio, "TA_nCHG");
+ gpio_direction_input(gpio);
+
+ gpio = nuri_max8903.dcm;
+ gpio_request(gpio, "CURR_ADJ");
+ gpio_direction_output(gpio, ta_en);
+}
/* USB EHCI */
static struct s5p_ehci_platdata nuri_ehci_pdata;
@@ -361,6 +1090,7 @@ static void __init nuri_ehci_init(void)
static struct platform_device *nuri_devices[] __initdata = {
/* Samsung Platform Devices */
+ &s3c_device_i2c5, /* PMIC should initialize first */
&emmc_fixed_voltage,
&s3c_device_hsmmc0,
&s3c_device_hsmmc2,
@@ -369,11 +1099,20 @@ static struct platform_device *nuri_devices[] __initdata = {
&s3c_device_timer[0],
&s5p_device_ehci,
&s3c_device_i2c3,
+ &i2c9_gpio,
+ &s3c_device_adc,
+ &s3c_device_rtc,
+ &s5p_device_mfc,
+ &s5p_device_mfc_l,
+ &s5p_device_mfc_r,
+ &exynos4_device_pd[PD_MFC],
/* NURI Devices */
&nuri_gpio_keys,
&nuri_lcd_device,
&nuri_backlight_device,
+ &max8903_fixed_reg_dev,
+ &nuri_max8903_device,
};
static void __init nuri_map_io(void)
@@ -383,21 +1122,32 @@ static void __init nuri_map_io(void)
s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
}
+static void __init nuri_reserve(void)
+{
+ s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
static void __init nuri_machine_init(void)
{
nuri_sdhci_init();
nuri_tsp_init();
+ nuri_power_init();
i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
s3c_i2c3_set_platdata(&i2c3_data);
i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+ s3c_i2c5_set_platdata(NULL);
+ i2c5_devs[I2C5_MAX8997].irq = gpio_to_irq(EXYNOS4_GPX0(7));
i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+ i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
+ i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
nuri_ehci_init();
clk_xusbxti.rate = 24000000;
/* Last */
platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
+ s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
}
MACHINE_START(NURI, "NURI")
@@ -407,4 +1157,5 @@ MACHINE_START(NURI, "NURI")
.map_io = nuri_map_io,
.init_machine = nuri_machine_init,
.timer = &exynos4_timer,
+ .reserve = &nuri_reserve,
MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkc210.c b/arch/arm/mach-exynos4/mach-smdkc210.c
index e645f7a955f0..a7c65e05c1eb 100644
--- a/arch/arm/mach-exynos4/mach-smdkc210.c
+++ b/arch/arm/mach-exynos4/mach-smdkc210.c
@@ -9,24 +9,33 @@
*/
#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>
@@ -111,6 +120,67 @@ static struct s3c_sdhci_platdata smdkc210_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 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),
@@ -165,6 +235,8 @@ static struct platform_device *smdkc210_devices[] __initdata = {
&exynos4_device_pd[PD_GPS],
&exynos4_device_sysmmu,
&samsung_asoc_dma,
+ &s5p_device_fimd0,
+ &smdkc210_lcd_lte480wv,
&smdkc210_smsc911x,
};
@@ -191,6 +263,17 @@ static void __init smdkc210_smsc911x_init(void)
(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);
@@ -210,6 +293,9 @@ static void __init smdkc210_machine_init(void)
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));
}
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index edd814110da8..ea4149556860 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/pwm_backlight.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -29,6 +30,8 @@
#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>
@@ -181,9 +184,12 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&exynos4_device_pd[PD_CAM],
&exynos4_device_pd[PD_TV],
&exynos4_device_pd[PD_GPS],
+ &exynos4_device_spdif,
&exynos4_device_sysmmu,
&samsung_asoc_dma,
+ &samsung_asoc_idma,
&smdkv310_smsc911x,
+ &exynos4_device_ahci,
};
static void __init smdkv310_smsc911x_init(void)
@@ -209,6 +215,17 @@ static void __init smdkv310_smsc911x_init(void)
(0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
}
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkv310_bl_gpio_info = {
+ .no = EXYNOS4_GPD0(1),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkv310_bl_data = {
+ .pwm_id = 1,
+ .pwm_period_ns = 1000,
+};
+
static void __init smdkv310_map_io(void)
{
s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -230,6 +247,8 @@ static void __init smdkv310_machine_init(void)
samsung_keypad_set_platdata(&smdkv310_keypad_data);
+ samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+
platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
}
diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
index 97d329fff2cf..0e280d12301e 100644
--- a/arch/arm/mach-exynos4/mach-universal_c210.c
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -18,6 +18,9 @@
#include <linux/regulator/fixed.h>
#include <linux/regulator/max8952.h>
#include <linux/mmc/host.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/mcs.h>
+#include <linux/i2c/atmel_mxt_ts.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -27,7 +30,10 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+#include <plat/mfc.h>
#include <plat/sdhci.h>
+#include <plat/pd.h>
#include <mach/map.h>
@@ -477,6 +483,96 @@ static struct i2c_board_info i2c5_devs[] __initdata = {
},
};
+/* I2C3 (TSP) */
+static struct mxt_platform_data qt602240_platform_data = {
+ .x_line = 19,
+ .y_line = 11,
+ .x_size = 800,
+ .y_size = 480,
+ .blen = 0x11,
+ .threshold = 0x28,
+ .voltage = 2800000, /* 2.8V */
+ .orient = MXT_DIAGONAL,
+};
+
+static struct i2c_board_info i2c3_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("qt602240_ts", 0x4a),
+ .platform_data = &qt602240_platform_data,
+ },
+};
+
+static void __init universal_tsp_init(void)
+{
+ int gpio;
+
+ /* TSP_LDO_ON: XMDMADDR_11 */
+ gpio = EXYNOS4_GPE2(3);
+ gpio_request(gpio, "TSP_LDO_ON");
+ gpio_direction_output(gpio, 1);
+ gpio_export(gpio, 0);
+
+ /* TSP_INT: XMDMADDR_7 */
+ gpio = EXYNOS4_GPE1(7);
+ gpio_request(gpio, "TSP_INT");
+
+ s5p_register_gpio_interrupt(gpio);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ i2c3_devs[0].irq = gpio_to_irq(gpio);
+}
+
+
+/* GPIO I2C 12 (3 Touchkey) */
+static uint32_t touchkey_keymap[] = {
+ /* MCS_KEY_MAP(value, keycode) */
+ MCS_KEY_MAP(0, KEY_MENU), /* KEY_SEND */
+ MCS_KEY_MAP(1, KEY_BACK), /* KEY_END */
+};
+
+static struct mcs_platform_data touchkey_data = {
+ .keymap = touchkey_keymap,
+ .keymap_size = ARRAY_SIZE(touchkey_keymap),
+ .key_maxval = 2,
+};
+
+/* GPIO I2C 3_TOUCH 2.8V */
+#define I2C_GPIO_BUS_12 12
+static struct i2c_gpio_platform_data i2c_gpio12_data = {
+ .sda_pin = EXYNOS4_GPE4(0), /* XMDMDATA_8 */
+ .scl_pin = EXYNOS4_GPE4(1), /* XMDMDATA_9 */
+};
+
+static struct platform_device i2c_gpio12 = {
+ .name = "i2c-gpio",
+ .id = I2C_GPIO_BUS_12,
+ .dev = {
+ .platform_data = &i2c_gpio12_data,
+ },
+};
+
+static struct i2c_board_info i2c_gpio12_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("mcs5080_touchkey", 0x20),
+ .platform_data = &touchkey_data,
+ },
+};
+
+static void __init universal_touchkey_init(void)
+{
+ int gpio;
+
+ gpio = EXYNOS4_GPE3(7); /* XMDMDATA_7 */
+ gpio_request(gpio, "3_TOUCH_INT");
+ s5p_register_gpio_interrupt(gpio);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+ i2c_gpio12_devs[0].irq = gpio_to_irq(gpio);
+
+ gpio = EXYNOS4_GPE3(3); /* XMDMDATA_3 */
+ gpio_request(gpio, "3_TOUCH_EN");
+ gpio_direction_output(gpio, 1);
+}
+
/* GPIO KEYS */
static struct gpio_keys_button universal_gpio_keys_tables[] = {
{
@@ -608,15 +704,25 @@ static struct i2c_board_info i2c1_devs[] __initdata = {
static struct platform_device *universal_devices[] __initdata = {
/* Samsung Platform Devices */
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
+ &s5p_device_fimc3,
&mmc0_fixed_voltage,
&s3c_device_hsmmc0,
&s3c_device_hsmmc2,
&s3c_device_hsmmc3,
+ &s3c_device_i2c3,
&s3c_device_i2c5,
/* Universal Devices */
+ &i2c_gpio12,
&universal_gpio_keys,
&s5p_device_onenand,
+ &s5p_device_mfc,
+ &s5p_device_mfc_l,
+ &s5p_device_mfc_r,
+ &exynos4_device_pd[PD_MFC],
};
static void __init universal_map_io(void)
@@ -626,6 +732,11 @@ static void __init universal_map_io(void)
s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
}
+static void __init universal_reserve(void)
+{
+ s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
static void __init universal_machine_init(void)
{
universal_sdhci_init();
@@ -633,11 +744,20 @@ static void __init universal_machine_init(void)
i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+ universal_tsp_init();
+ s3c_i2c3_set_platdata(NULL);
+ i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+
s3c_i2c5_set_platdata(NULL);
i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+ universal_touchkey_init();
+ i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
+ ARRAY_SIZE(i2c_gpio12_devs));
+
/* Last */
platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+ s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
}
MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
@@ -647,4 +767,5 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
.map_io = universal_map_io,
.init_machine = universal_machine_init,
.timer = &exynos4_timer,
+ .reserve = &universal_reserve,
MACHINE_END
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index 14ac10b7ec02..1ae059b7ad7b 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -383,8 +383,8 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
} else {
mct_tick1_event_irq.dev_id = &mct_tick[cpu];
- irq_set_affinity(IRQ_MCT1, cpumask_of(1));
setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+ irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
}
}
diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c
index c5e65a02be8d..7c2282c6ba81 100644
--- a/arch/arm/mach-exynos4/platsmp.c
+++ b/arch/arm/mach-exynos4/platsmp.c
@@ -28,9 +28,12 @@
#include <mach/hardware.h>
#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
extern void exynos4_secondary_startup(void);
+#define CPU1_BOOT_REG S5P_VA_SYSRAM
+
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
@@ -58,6 +61,31 @@ static void __iomem *scu_base_addr(void)
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());
+ void __iomem *cpu_base = S5P_VA_GIC_CPU +
+ (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+ int i;
+
+ /*
+ * Deal with the banked PPI and SGI interrupts - disable all
+ * PPI interrupts, ensure all SGI interrupts are enabled.
+ */
+ __raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
+ __raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+
+ /*
+ * Set priority on PPI and SGI interrupts
+ */
+ for (i = 0; i < 32; i += 4)
+ __raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+
+ __raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
+ __raw_writel(1, cpu_base + GIC_CPU_CTRL);
+}
+
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
@@ -65,7 +93,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_secondary_init(0);
+ exynos4_gic_secondary_init();
/*
* let the primary processor know we're out of the
@@ -100,16 +128,41 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
*/
write_pen_release(cpu);
+ if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
+ __raw_writel(S5P_CORE_LOCAL_PWR_EN,
+ S5P_ARM_CORE1_CONFIGURATION);
+
+ timeout = 10;
+
+ /* wait max 10 ms until cpu1 is on */
+ while ((__raw_readl(S5P_ARM_CORE1_STATUS)
+ & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
+ if (timeout-- == 0)
+ break;
+
+ mdelay(1);
+ }
+
+ if (timeout == 0) {
+ printk(KERN_ERR "cpu1 power enable failed");
+ spin_unlock(&boot_lock);
+ return -ETIMEDOUT;
+ }
+ }
/*
* Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register,
* and branch to the address found there.
*/
- gic_raise_softirq(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
smp_rmb();
+
+ __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+ CPU1_BOOT_REG);
+ gic_raise_softirq(cpumask_of(cpu), 1);
+
if (pen_release == -1)
break;
@@ -154,14 +207,6 @@ void __init smp_init_cpus(void)
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- /*
- * Initialise the present map, which describes the set of CPUs
- * actually populated at the present time.
- */
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
scu_enable(scu_base_addr());
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index 8755ca8dd48d..bc6ca9482de1 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -18,92 +18,23 @@
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
#include <plat/cpu.h>
#include <plat/pm.h>
+#include <plat/pll.h>
+#include <plat/regs-srom.h>
#include <mach/regs-irq.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-pmu.h>
#include <mach/pm-core.h>
-
-static struct sleep_save exynos4_sleep[] = {
- { .reg = S5P_ARM_CORE0_LOWPWR , .val = 0x2, },
- { .reg = S5P_DIS_IRQ_CORE0 , .val = 0x0, },
- { .reg = S5P_DIS_IRQ_CENTRAL0 , .val = 0x0, },
- { .reg = S5P_ARM_CORE1_LOWPWR , .val = 0x2, },
- { .reg = S5P_DIS_IRQ_CORE1 , .val = 0x0, },
- { .reg = S5P_DIS_IRQ_CENTRAL1 , .val = 0x0, },
- { .reg = S5P_ARM_COMMON_LOWPWR , .val = 0x2, },
- { .reg = S5P_L2_0_LOWPWR , .val = 0x3, },
- { .reg = S5P_L2_1_LOWPWR , .val = 0x3, },
- { .reg = S5P_CMU_ACLKSTOP_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_SCLKSTOP_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_LOWPWR , .val = 0x0, },
- { .reg = S5P_APLL_SYSCLK_LOWPWR , .val = 0x0, },
- { .reg = S5P_MPLL_SYSCLK_LOWPWR , .val = 0x0, },
- { .reg = S5P_VPLL_SYSCLK_LOWPWR , .val = 0x0, },
- { .reg = S5P_EPLL_SYSCLK_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_TV_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_CAM_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_TV_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_MFC_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_G3D_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_LCD0_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_LCD1_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_MAUDIO_LOWPWR , .val = 0x0, },
- { .reg = S5P_CMU_RESET_GPS_LOWPWR , .val = 0x0, },
- { .reg = S5P_TOP_BUS_LOWPWR , .val = 0x0, },
- { .reg = S5P_TOP_RETENTION_LOWPWR , .val = 0x1, },
- { .reg = S5P_TOP_PWR_LOWPWR , .val = 0x3, },
- { .reg = S5P_LOGIC_RESET_LOWPWR , .val = 0x0, },
- { .reg = S5P_ONENAND_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_MODIMIF_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_G2D_ACP_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_USBOTG_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_HSMMC_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_CSSYS_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_SECSS_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_PCIE_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_SATA_MEM_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_DRAM_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_GPIO_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_UART_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_MMCA_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_MMCB_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_EBIA_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_EBIB_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR , .val = 0x0, },
- { .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR , .val = 0x0, },
- { .reg = S5P_XUSBXTI_LOWPWR , .val = 0x0, },
- { .reg = S5P_XXTI_LOWPWR , .val = 0x0, },
- { .reg = S5P_EXT_REGULATOR_LOWPWR , .val = 0x0, },
- { .reg = S5P_GPIO_MODE_LOWPWR , .val = 0x0, },
- { .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR , .val = 0x0, },
- { .reg = S5P_CAM_LOWPWR , .val = 0x0, },
- { .reg = S5P_TV_LOWPWR , .val = 0x0, },
- { .reg = S5P_MFC_LOWPWR , .val = 0x0, },
- { .reg = S5P_G3D_LOWPWR , .val = 0x0, },
- { .reg = S5P_LCD0_LOWPWR , .val = 0x0, },
- { .reg = S5P_LCD1_LOWPWR , .val = 0x0, },
- { .reg = S5P_MAUDIO_LOWPWR , .val = 0x0, },
- { .reg = S5P_GPS_LOWPWR , .val = 0x0, },
- { .reg = S5P_GPS_ALIVE_LOWPWR , .val = 0x0, },
-};
+#include <mach/pmu.h>
static struct sleep_save exynos4_set_clksrc[] = {
{ .reg = S5P_CLKSRC_MASK_TOP , .val = 0x00000001, },
@@ -118,20 +49,28 @@ static struct sleep_save exynos4_set_clksrc[] = {
{ .reg = S5P_CLKSRC_MASK_DMC , .val = 0x00010000, },
};
+static struct sleep_save exynos4_epll_save[] = {
+ SAVE_ITEM(S5P_EPLL_CON0),
+ SAVE_ITEM(S5P_EPLL_CON1),
+};
+
+static struct sleep_save exynos4_vpll_save[] = {
+ SAVE_ITEM(S5P_VPLL_CON0),
+ SAVE_ITEM(S5P_VPLL_CON1),
+};
+
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_EPLL_CON0),
- SAVE_ITEM(S5P_EPLL_CON1),
- SAVE_ITEM(S5P_VPLL_CON0),
- SAVE_ITEM(S5P_VPLL_CON1),
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),
@@ -158,6 +97,7 @@ static struct sleep_save exynos4_core_save[] = {
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),
@@ -166,6 +106,7 @@ static struct sleep_save exynos4_core_save[] = {
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),
@@ -186,8 +127,10 @@ static struct sleep_save exynos4_core_save[] = {
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),
@@ -270,6 +213,13 @@ static struct sleep_save exynos4_core_save[] = {
SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
+
+ /* SROM side */
+ SAVE_ITEM(S5P_SROM_BW),
+ SAVE_ITEM(S5P_SROM_BC0),
+ SAVE_ITEM(S5P_SROM_BC1),
+ SAVE_ITEM(S5P_SROM_BC2),
+ SAVE_ITEM(S5P_SROM_BC3),
};
static struct sleep_save exynos4_l2cc_save[] = {
@@ -280,37 +230,11 @@ static struct sleep_save exynos4_l2cc_save[] = {
SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
};
-void exynos4_cpu_suspend(void)
-{
- unsigned long tmp;
- unsigned long mask = 0xFFFFFFFF;
-
- /* Setting Central Sequence Register for power down mode */
-
- tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
- tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
- __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-
- /* Setting Central Sequence option Register */
-
- tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
- tmp &= ~(S5P_USE_MASK);
- tmp |= S5P_USE_STANDBY_WFI0;
- __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
-
- /* Clear all interrupt pending to avoid early wakeup */
-
- __raw_writel(mask, (S5P_VA_GIC_DIST + 0x280));
- __raw_writel(mask, (S5P_VA_GIC_DIST + 0x284));
- __raw_writel(mask, (S5P_VA_GIC_DIST + 0x288));
-
- /* Disable all interrupt */
-
- __raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000));
- __raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000));
- __raw_writel(mask, (S5P_VA_GIC_DIST + 0x184));
- __raw_writel(mask, (S5P_VA_GIC_DIST + 0x188));
+/* For Cortex-A9 Diagnostic and Power control register */
+static unsigned int save_arm_register[2];
+static int exynos4_cpu_suspend(unsigned long arg)
+{
outer_flush_all();
/* issue the standby signal into the pm unit. */
@@ -326,12 +250,14 @@ static void exynos4_pm_prepare(void)
s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+ s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
+ s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
tmp = __raw_readl(S5P_INFORM1);
/* Set value of power down register for sleep mode */
- s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep));
+ exynos4_sys_powerdown_conf(SYS_SLEEP);
__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
/* ensure at least INFORM0 has the resume address */
@@ -373,12 +299,80 @@ void exynos4_scu_enable(void __iomem *scu_base)
flush_cache_all();
}
+static unsigned long pll_base_rate;
+
+static void exynos4_restore_pll(void)
+{
+ unsigned long pll_con, locktime, lockcnt;
+ unsigned long pll_in_rate;
+ unsigned int p_div, epll_wait = 0, vpll_wait = 0;
+
+ if (pll_base_rate == 0)
+ return;
+
+ pll_in_rate = pll_base_rate;
+
+ /* EPLL */
+ pll_con = exynos4_epll_save[0].val;
+
+ if (pll_con & (1 << 31)) {
+ pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
+ p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
+
+ pll_in_rate /= 1000000;
+
+ locktime = (3000 / pll_in_rate) * p_div;
+ lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+ __raw_writel(lockcnt, S5P_EPLL_LOCK);
+
+ s3c_pm_do_restore_core(exynos4_epll_save,
+ ARRAY_SIZE(exynos4_epll_save));
+ epll_wait = 1;
+ }
+
+ pll_in_rate = pll_base_rate;
+
+ /* VPLL */
+ pll_con = exynos4_vpll_save[0].val;
+
+ if (pll_con & (1 << 31)) {
+ pll_in_rate /= 1000000;
+ /* 750us */
+ locktime = 750;
+ lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+ __raw_writel(lockcnt, S5P_VPLL_LOCK);
+
+ s3c_pm_do_restore_core(exynos4_vpll_save,
+ ARRAY_SIZE(exynos4_vpll_save));
+ vpll_wait = 1;
+ }
+
+ /* Wait PLL locking */
+
+ do {
+ if (epll_wait) {
+ pll_con = __raw_readl(S5P_EPLL_CON0);
+ if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
+ epll_wait = 0;
+ }
+
+ if (vpll_wait) {
+ pll_con = __raw_readl(S5P_VPLL_CON0);
+ if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
+ vpll_wait = 0;
+ }
+ } while (epll_wait || vpll_wait);
+}
+
static struct sysdev_driver exynos4_pm_driver = {
.add = exynos4_pm_add,
};
static __init int exynos4_pm_drvinit(void)
{
+ struct clk *pll_base;
unsigned int tmp;
s3c_pm_init();
@@ -389,12 +383,69 @@ static __init int exynos4_pm_drvinit(void)
tmp |= ((0xFF << 8) | (0x1F << 1));
__raw_writel(tmp, S5P_WAKEUP_MASK);
+ pll_base = clk_get(NULL, "xtal");
+
+ if (!IS_ERR(pll_base)) {
+ pll_base_rate = clk_get_rate(pll_base);
+ clk_put(pll_base);
+ }
+
return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
}
arch_initcall(exynos4_pm_drvinit);
+static int exynos4_pm_suspend(void)
+{
+ unsigned long tmp;
+
+ /* Setting Central Sequence Register for power down mode */
+
+ tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+ __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+ /* Save Power control register */
+ asm ("mrc p15, 0, %0, c15, c0, 0"
+ : "=r" (tmp) : : "cc");
+ save_arm_register[0] = tmp;
+
+ /* Save Diagnostic register */
+ asm ("mrc p15, 0, %0, c15, c0, 1"
+ : "=r" (tmp) : : "cc");
+ save_arm_register[1] = tmp;
+
+ return 0;
+}
+
static void exynos4_pm_resume(void)
{
+ unsigned long tmp;
+
+ /*
+ * If PMU failed while entering sleep mode, WFI will be
+ * ignored by PMU and then exiting cpu_do_idle().
+ * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+ * in this situation.
+ */
+ tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+ tmp |= S5P_CENTRAL_LOWPWR_CFG;
+ __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+ /* No need to perform below restore code */
+ goto early_wakeup;
+ }
+ /* Restore Power control register */
+ tmp = save_arm_register[0];
+ asm volatile ("mcr p15, 0, %0, c15, c0, 0"
+ : : "r" (tmp)
+ : "cc");
+
+ /* Restore Diagnostic register */
+ tmp = save_arm_register[1];
+ asm volatile ("mcr p15, 0, %0, c15, c0, 1"
+ : : "r" (tmp)
+ : "cc");
+
/* For release retention */
__raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
@@ -407,6 +458,8 @@ static void exynos4_pm_resume(void)
s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+ exynos4_restore_pll();
+
exynos4_scu_enable(S5P_VA_SCU);
#ifdef CONFIG_CACHE_L2X0
@@ -415,9 +468,13 @@ static void exynos4_pm_resume(void)
/* enable L2X0*/
writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
#endif
+
+early_wakeup:
+ return;
}
static struct syscore_ops exynos4_pm_syscore_ops = {
+ .suspend = exynos4_pm_suspend,
.resume = exynos4_pm_resume,
};
diff --git a/arch/arm/mach-exynos4/pmu.c b/arch/arm/mach-exynos4/pmu.c
new file mode 100644
index 000000000000..7ea9eb2a20d2
--- /dev/null
+++ b/arch/arm/mach-exynos4/pmu.c
@@ -0,0 +1,175 @@
+/* linux/arch/arm/mach-exynos4/pmu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4210 - CPU PMU(Power Management Unit) 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/io.h>
+#include <linux/kernel.h>
+
+#include <mach/regs-clock.h>
+#include <mach/pmu.h>
+
+static void __iomem *sys_powerdown_reg[] = {
+ S5P_ARM_CORE0_LOWPWR,
+ S5P_DIS_IRQ_CORE0,
+ S5P_DIS_IRQ_CENTRAL0,
+ S5P_ARM_CORE1_LOWPWR,
+ S5P_DIS_IRQ_CORE1,
+ S5P_DIS_IRQ_CENTRAL1,
+ S5P_ARM_COMMON_LOWPWR,
+ S5P_L2_0_LOWPWR,
+ S5P_L2_1_LOWPWR,
+ S5P_CMU_ACLKSTOP_LOWPWR,
+ S5P_CMU_SCLKSTOP_LOWPWR,
+ S5P_CMU_RESET_LOWPWR,
+ S5P_APLL_SYSCLK_LOWPWR,
+ S5P_MPLL_SYSCLK_LOWPWR,
+ S5P_VPLL_SYSCLK_LOWPWR,
+ S5P_EPLL_SYSCLK_LOWPWR,
+ S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,
+ S5P_CMU_RESET_GPSALIVE_LOWPWR,
+ S5P_CMU_CLKSTOP_CAM_LOWPWR,
+ S5P_CMU_CLKSTOP_TV_LOWPWR,
+ S5P_CMU_CLKSTOP_MFC_LOWPWR,
+ S5P_CMU_CLKSTOP_G3D_LOWPWR,
+ S5P_CMU_CLKSTOP_LCD0_LOWPWR,
+ S5P_CMU_CLKSTOP_LCD1_LOWPWR,
+ S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,
+ S5P_CMU_CLKSTOP_GPS_LOWPWR,
+ S5P_CMU_RESET_CAM_LOWPWR,
+ S5P_CMU_RESET_TV_LOWPWR,
+ S5P_CMU_RESET_MFC_LOWPWR,
+ S5P_CMU_RESET_G3D_LOWPWR,
+ S5P_CMU_RESET_LCD0_LOWPWR,
+ S5P_CMU_RESET_LCD1_LOWPWR,
+ S5P_CMU_RESET_MAUDIO_LOWPWR,
+ S5P_CMU_RESET_GPS_LOWPWR,
+ S5P_TOP_BUS_LOWPWR,
+ S5P_TOP_RETENTION_LOWPWR,
+ S5P_TOP_PWR_LOWPWR,
+ S5P_LOGIC_RESET_LOWPWR,
+ S5P_ONENAND_MEM_LOWPWR,
+ S5P_MODIMIF_MEM_LOWPWR,
+ S5P_G2D_ACP_MEM_LOWPWR,
+ S5P_USBOTG_MEM_LOWPWR,
+ S5P_HSMMC_MEM_LOWPWR,
+ S5P_CSSYS_MEM_LOWPWR,
+ S5P_SECSS_MEM_LOWPWR,
+ S5P_PCIE_MEM_LOWPWR,
+ S5P_SATA_MEM_LOWPWR,
+ S5P_PAD_RETENTION_DRAM_LOWPWR,
+ S5P_PAD_RETENTION_MAUDIO_LOWPWR,
+ S5P_PAD_RETENTION_GPIO_LOWPWR,
+ S5P_PAD_RETENTION_UART_LOWPWR,
+ S5P_PAD_RETENTION_MMCA_LOWPWR,
+ S5P_PAD_RETENTION_MMCB_LOWPWR,
+ S5P_PAD_RETENTION_EBIA_LOWPWR,
+ S5P_PAD_RETENTION_EBIB_LOWPWR,
+ S5P_PAD_RETENTION_ISOLATION_LOWPWR,
+ S5P_PAD_RETENTION_ALV_SEL_LOWPWR,
+ S5P_XUSBXTI_LOWPWR,
+ S5P_XXTI_LOWPWR,
+ S5P_EXT_REGULATOR_LOWPWR,
+ S5P_GPIO_MODE_LOWPWR,
+ S5P_GPIO_MODE_MAUDIO_LOWPWR,
+ S5P_CAM_LOWPWR,
+ S5P_TV_LOWPWR,
+ S5P_MFC_LOWPWR,
+ S5P_G3D_LOWPWR,
+ S5P_LCD0_LOWPWR,
+ S5P_LCD1_LOWPWR,
+ S5P_MAUDIO_LOWPWR,
+ S5P_GPS_LOWPWR,
+ S5P_GPS_ALIVE_LOWPWR,
+};
+
+static const unsigned int sys_powerdown_val[][NUM_SYS_POWERDOWN] = {
+ /* { AFTR, LPA, SLEEP }*/
+ { 0, 0, 2 }, /* ARM_CORE0 */
+ { 0, 0, 0 }, /* ARM_DIS_IRQ_CORE0 */
+ { 0, 0, 0 }, /* ARM_DIS_IRQ_CENTRAL0 */
+ { 0, 0, 2 }, /* ARM_CORE1 */
+ { 0, 0, 0 }, /* ARM_DIS_IRQ_CORE1 */
+ { 0, 0, 0 }, /* ARM_DIS_IRQ_CENTRAL1 */
+ { 0, 0, 2 }, /* ARM_COMMON */
+ { 2, 2, 3 }, /* ARM_CPU_L2_0 */
+ { 2, 2, 3 }, /* ARM_CPU_L2_1 */
+ { 1, 0, 0 }, /* CMU_ACLKSTOP */
+ { 1, 0, 0 }, /* CMU_SCLKSTOP */
+ { 1, 1, 0 }, /* CMU_RESET */
+ { 1, 0, 0 }, /* APLL_SYSCLK */
+ { 1, 0, 0 }, /* MPLL_SYSCLK */
+ { 1, 0, 0 }, /* VPLL_SYSCLK */
+ { 1, 1, 0 }, /* EPLL_SYSCLK */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_GPS_ALIVE */
+ { 1, 1, 0 }, /* CMU_RESET_GPS_ALIVE */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_CAM */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_TV */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_MFC */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_G3D */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_LCD0 */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_LCD1 */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_MAUDIO */
+ { 1, 1, 0 }, /* CMU_CLKSTOP_GPS */
+ { 1, 1, 0 }, /* CMU_RESET_CAM */
+ { 1, 1, 0 }, /* CMU_RESET_TV */
+ { 1, 1, 0 }, /* CMU_RESET_MFC */
+ { 1, 1, 0 }, /* CMU_RESET_G3D */
+ { 1, 1, 0 }, /* CMU_RESET_LCD0 */
+ { 1, 1, 0 }, /* CMU_RESET_LCD1 */
+ { 1, 1, 0 }, /* CMU_RESET_MAUDIO */
+ { 1, 1, 0 }, /* CMU_RESET_GPS */
+ { 3, 0, 0 }, /* TOP_BUS */
+ { 1, 0, 1 }, /* TOP_RETENTION */
+ { 3, 0, 3 }, /* TOP_PWR */
+ { 1, 1, 0 }, /* LOGIC_RESET */
+ { 3, 0, 0 }, /* ONENAND_MEM */
+ { 3, 0, 0 }, /* MODIMIF_MEM */
+ { 3, 0, 0 }, /* G2D_ACP_MEM */
+ { 3, 0, 0 }, /* USBOTG_MEM */
+ { 3, 0, 0 }, /* HSMMC_MEM */
+ { 3, 0, 0 }, /* CSSYS_MEM */
+ { 3, 0, 0 }, /* SECSS_MEM */
+ { 3, 0, 0 }, /* PCIE_MEM */
+ { 3, 0, 0 }, /* SATA_MEM */
+ { 1, 0, 0 }, /* PAD_RETENTION_DRAM */
+ { 1, 1, 0 }, /* PAD_RETENTION_MAUDIO */
+ { 1, 0, 0 }, /* PAD_RETENTION_GPIO */
+ { 1, 0, 0 }, /* PAD_RETENTION_UART */
+ { 1, 0, 0 }, /* PAD_RETENTION_MMCA */
+ { 1, 0, 0 }, /* PAD_RETENTION_MMCB */
+ { 1, 0, 0 }, /* PAD_RETENTION_EBIA */
+ { 1, 0, 0 }, /* PAD_RETENTION_EBIB */
+ { 1, 0, 0 }, /* PAD_RETENTION_ISOLATION */
+ { 1, 0, 0 }, /* PAD_RETENTION_ALV_SEL */
+ { 1, 1, 0 }, /* XUSBXTI */
+ { 1, 1, 0 }, /* XXTI */
+ { 1, 1, 0 }, /* EXT_REGULATOR */
+ { 1, 0, 0 }, /* GPIO_MODE */
+ { 1, 1, 0 }, /* GPIO_MODE_MAUDIO */
+ { 7, 0, 0 }, /* CAM */
+ { 7, 0, 0 }, /* TV */
+ { 7, 0, 0 }, /* MFC */
+ { 7, 0, 0 }, /* G3D */
+ { 7, 0, 0 }, /* LCD0 */
+ { 7, 0, 0 }, /* LCD1 */
+ { 7, 7, 0 }, /* MAUDIO */
+ { 7, 0, 0 }, /* GPS */
+ { 7, 0, 0 }, /* GPS_ALIVE */
+};
+
+void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
+{
+ unsigned int count = ARRAY_SIZE(sys_powerdown_reg);
+
+ for (; count > 0; count--)
+ __raw_writel(sys_powerdown_val[count - 1][mode],
+ sys_powerdown_reg[count - 1]);
+}
diff --git a/arch/arm/mach-exynos4/setup-fimd0.c b/arch/arm/mach-exynos4/setup-fimd0.c
new file mode 100644
index 000000000000..07a6dbeecdd0
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-fimd0.c
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-exynos4/setup-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Base Exynos4 FIMD 0 configuration
+ *
+ * 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/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
+
+#include <mach/map.h>
+
+void exynos4_fimd0_gpio_setup_24bpp(void)
+{
+ unsigned int reg;
+
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
+
+ /*
+ * Set DISPLAY_CONTROL register for Display path selection.
+ *
+ * DISPLAY_CONTROL[1:0]
+ * ---------------------
+ * 00 | MIE
+ * 01 | MDINE
+ * 10 | FIMD : selected
+ * 11 | FIMD
+ */
+ reg = __raw_readl(S3C_VA_SYS + 0x0210);
+ reg |= (1 << 1);
+ __raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
diff --git a/arch/arm/mach-exynos4/sleep.S b/arch/arm/mach-exynos4/sleep.S
index 6b62425417a6..0984078f1eba 100644
--- a/arch/arm/mach-exynos4/sleep.S
+++ b/arch/arm/mach-exynos4/sleep.S
@@ -33,28 +33,6 @@
.text
/*
- * s3c_cpu_save
- *
- * entry:
- * r1 = v:p offset
- */
-
-ENTRY(s3c_cpu_save)
-
- stmfd sp!, { r3 - r12, lr }
- ldr r3, =resume_with_mmu
- bl cpu_suspend
-
- ldr r0, =pm_cpu_sleep
- ldr r0, [ r0 ]
- mov pc, r0
-
-resume_with_mmu:
- ldmfd sp!, { r3 - r12, pc }
-
- .ltorg
-
- /*
* sleep magic, to allow the bootloader to check for an valid
* image to resume to. Must be the first word before the
* s3c_cpu_resume entry.
diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c
deleted file mode 100644
index ebb8f38d5405..000000000000
--- a/arch/arm/mach-exynos4/time.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* linux/arch/arm/mach-exynos4/time.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4 (and compatible) HRT support
- * PWM 2/4 is used for this feature
- *
- * 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/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-
-#include <asm/smp_twd.h>
-
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <asm/mach/time.h>
-
-static unsigned long clock_count_per_tick;
-
-static struct clk *tin2;
-static struct clk *tin4;
-static struct clk *tdiv2;
-static struct clk *tdiv4;
-static struct clk *timerclk;
-
-static void exynos4_pwm_stop(unsigned int pwm_id)
-{
- unsigned long tcon;
-
- tcon = __raw_readl(S3C2410_TCON);
-
- switch (pwm_id) {
- case 2:
- tcon &= ~S3C2410_TCON_T2START;
- break;
- case 4:
- tcon &= ~S3C2410_TCON_T4START;
- break;
- default:
- break;
- }
- __raw_writel(tcon, S3C2410_TCON);
-}
-
-static void exynos4_pwm_init(unsigned int pwm_id, unsigned long tcnt)
-{
- unsigned long tcon;
-
- tcon = __raw_readl(S3C2410_TCON);
-
- /* timers reload after counting zero, so reduce the count by 1 */
- tcnt--;
-
- /* ensure timer is stopped... */
- switch (pwm_id) {
- case 2:
- tcon &= ~(0xf<<12);
- tcon |= S3C2410_TCON_T2MANUALUPD;
-
- __raw_writel(tcnt, S3C2410_TCNTB(2));
- __raw_writel(tcnt, S3C2410_TCMPB(2));
- __raw_writel(tcon, S3C2410_TCON);
-
- break;
- case 4:
- tcon &= ~(7<<20);
- tcon |= S3C2410_TCON_T4MANUALUPD;
-
- __raw_writel(tcnt, S3C2410_TCNTB(4));
- __raw_writel(tcnt, S3C2410_TCMPB(4));
- __raw_writel(tcon, S3C2410_TCON);
-
- break;
- default:
- break;
- }
-}
-
-static inline void exynos4_pwm_start(unsigned int pwm_id, bool periodic)
-{
- unsigned long tcon;
-
- tcon = __raw_readl(S3C2410_TCON);
-
- switch (pwm_id) {
- case 2:
- tcon |= S3C2410_TCON_T2START;
- tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
- if (periodic)
- tcon |= S3C2410_TCON_T2RELOAD;
- else
- tcon &= ~S3C2410_TCON_T2RELOAD;
- break;
- case 4:
- tcon |= S3C2410_TCON_T4START;
- tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
- if (periodic)
- tcon |= S3C2410_TCON_T4RELOAD;
- else
- tcon &= ~S3C2410_TCON_T4RELOAD;
- break;
- default:
- break;
- }
- __raw_writel(tcon, S3C2410_TCON);
-}
-
-static int exynos4_pwm_set_next_event(unsigned long cycles,
- struct clock_event_device *evt)
-{
- exynos4_pwm_init(2, cycles);
- exynos4_pwm_start(2, 0);
- return 0;
-}
-
-static void exynos4_pwm_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- exynos4_pwm_stop(2);
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- exynos4_pwm_init(2, clock_count_per_tick);
- exynos4_pwm_start(2, 1);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- break;
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
-}
-
-static struct clock_event_device pwm_event_device = {
- .name = "pwm_timer2",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .rating = 200,
- .shift = 32,
- .set_next_event = exynos4_pwm_set_next_event,
- .set_mode = exynos4_pwm_set_mode,
-};
-
-irqreturn_t exynos4_clock_event_isr(int irq, void *dev_id)
-{
- struct clock_event_device *evt = &pwm_event_device;
-
- evt->event_handler(evt);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction exynos4_clock_event_irq = {
- .name = "pwm_timer2_irq",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = exynos4_clock_event_isr,
-};
-
-static void __init exynos4_clockevent_init(void)
-{
- unsigned long pclk;
- unsigned long clock_rate;
- struct clk *tscaler;
-
- pclk = clk_get_rate(timerclk);
-
- /* configure clock tick */
-
- tscaler = clk_get_parent(tdiv2);
-
- clk_set_rate(tscaler, pclk / 2);
- clk_set_rate(tdiv2, pclk / 2);
- clk_set_parent(tin2, tdiv2);
-
- clock_rate = clk_get_rate(tin2);
-
- clock_count_per_tick = clock_rate / HZ;
-
- pwm_event_device.mult =
- div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
- pwm_event_device.max_delta_ns =
- clockevent_delta2ns(-1, &pwm_event_device);
- pwm_event_device.min_delta_ns =
- clockevent_delta2ns(1, &pwm_event_device);
-
- pwm_event_device.cpumask = cpumask_of(0);
- clockevents_register_device(&pwm_event_device);
-
- setup_irq(IRQ_TIMER2, &exynos4_clock_event_irq);
-}
-
-static cycle_t exynos4_pwm4_read(struct clocksource *cs)
-{
- return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
-}
-
-#ifdef CONFIG_PM
-static void exynos4_pwm4_resume(struct clocksource *cs)
-{
- unsigned long pclk;
-
- pclk = clk_get_rate(timerclk);
-
- clk_set_rate(tdiv4, pclk / 2);
- clk_set_parent(tin4, tdiv4);
-
- exynos4_pwm_init(4, ~0);
- exynos4_pwm_start(4, 1);
-}
-#endif
-
-struct clocksource pwm_clocksource = {
- .name = "pwm_timer4",
- .rating = 250,
- .read = exynos4_pwm4_read,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS ,
-#ifdef CONFIG_PM
- .resume = exynos4_pwm4_resume,
-#endif
-};
-
-static void __init exynos4_clocksource_init(void)
-{
- unsigned long pclk;
- unsigned long clock_rate;
-
- pclk = clk_get_rate(timerclk);
-
- clk_set_rate(tdiv4, pclk / 2);
- clk_set_parent(tin4, tdiv4);
-
- clock_rate = clk_get_rate(tin4);
-
- exynos4_pwm_init(4, ~0);
- exynos4_pwm_start(4, 1);
-
- if (clocksource_register_hz(&pwm_clocksource, clock_rate))
- panic("%s: can't register clocksource\n", pwm_clocksource.name);
-}
-
-static void __init exynos4_timer_resources(void)
-{
- struct platform_device tmpdev;
-
- tmpdev.dev.bus = &platform_bus_type;
-
- timerclk = clk_get(NULL, "timers");
- if (IS_ERR(timerclk))
- panic("failed to get timers clock for system timer");
-
- clk_enable(timerclk);
-
- tmpdev.id = 2;
- tin2 = clk_get(&tmpdev.dev, "pwm-tin");
- if (IS_ERR(tin2))
- panic("failed to get pwm-tin2 clock for system timer");
-
- tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
- if (IS_ERR(tdiv2))
- panic("failed to get pwm-tdiv2 clock for system timer");
- clk_enable(tin2);
-
- tmpdev.id = 4;
- tin4 = clk_get(&tmpdev.dev, "pwm-tin");
- if (IS_ERR(tin4))
- panic("failed to get pwm-tin4 clock for system timer");
-
- tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
- if (IS_ERR(tdiv4))
- panic("failed to get pwm-tdiv4 clock for system timer");
-
- clk_enable(tin4);
-}
-
-static void __init exynos4_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
- twd_base = S5P_VA_TWD;
-#endif
-
- exynos4_timer_resources();
- exynos4_clockevent_init();
- exynos4_clocksource_init();
-}
-
-struct sys_timer exynos4_timer = {
- .init = exynos4_timer_init,
-};
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
index 46adca068f2c..dc26fff22cf0 100644
--- a/arch/arm/mach-footbridge/Kconfig
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -5,6 +5,7 @@ menu "Footbridge Implementations"
config ARCH_CATS
bool "CATS"
select CLKSRC_I8253
+ select CLKEVT_I8253
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 3ffa54841ec5..1331fff51ae2 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -295,6 +295,9 @@ void __init dc21285_preinit(void)
unsigned int mem_size, mem_mask;
int cfn_mode;
+ pcibios_min_mem = 0x81000000;
+ vga_base = PCIMEM_BASE;
+
mem_size = (unsigned int)high_memory - PAGE_OFFSET;
for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
if (mem_mask >= mem_size)
diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h
index b6fdf23ecf6c..15d54981674c 100644
--- a/arch/arm/mach-footbridge/include/mach/hardware.h
+++ b/arch/arm/mach-footbridge/include/mach/hardware.h
@@ -100,9 +100,4 @@ extern unsigned int nw_gpio_read(void);
extern void nw_cpld_modify(unsigned int mask, unsigned int set);
#endif
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x1000
-#define PCIBIOS_MIN_MEM 0x81000000
-
#endif
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index 7020f1a3feca..c40bb415f4b5 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -5,64 +5,18 @@
* Copyright (C) 1998 Phil Blundell
*/
#include <linux/clockchips.h>
-#include <linux/clocksource.h>
+#include <linux/i8253.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/timex.h>
#include <asm/irq.h>
-#include <asm/i8253.h>
#include <asm/mach/time.h>
#include "common.h"
-DEFINE_RAW_SPINLOCK(i8253_lock);
-
-static void pit_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- unsigned long flags;
-
- raw_local_irq_save(flags);
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- outb_p(0x34, PIT_MODE);
- outb_p(PIT_LATCH & 0xff, PIT_CH0);
- outb_p(PIT_LATCH >> 8, PIT_CH0);
- break;
-
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_UNUSED:
- outb_p(0x30, PIT_MODE);
- outb_p(0, PIT_CH0);
- outb_p(0, PIT_CH0);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
- local_irq_restore(flags);
-}
-
-static int pit_set_next_event(unsigned long delta,
- struct clock_event_device *evt)
-{
- return 0;
-}
-
-static struct clock_event_device pit_ce = {
- .name = "pit",
- .features = CLOCK_EVT_FEAT_PERIODIC,
- .set_mode = pit_set_mode,
- .set_next_event = pit_set_next_event,
- .shift = 32,
-};
-
static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *ce = dev_id;
@@ -74,20 +28,15 @@ static struct irqaction pit_timer_irq = {
.name = "pit",
.handler = pit_timer_interrupt,
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .dev_id = &pit_ce,
+ .dev_id = &i8253_clockevent,
};
static void __init isa_timer_init(void)
{
- pit_ce.cpumask = cpumask_of(smp_processor_id());
- pit_ce.mult = div_sc(PIT_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);
- pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce);
- pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce);
-
clocksource_i8253_init();
- setup_irq(pit_ce.irq, &pit_timer_irq);
- clockevents_register_device(&pit_ce);
+ setup_irq(i8253_clockevent.irq, &pit_timer_irq);
+ clockevent_i8253_init(false);
}
struct sys_timer isa_timer = {
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index 629454d71c8d..65f1bea958e5 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -33,4 +33,5 @@ MACHINE_START(H7201, "Hynix GMS30C7201")
.map_io = h720x_map_io,
.init_irq = h720x_init_irq,
.timer = &h7201_timer,
+ .dma_zone_size = SZ_256M,
MACHINE_END
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index e9f46b696354..884584a09752 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -76,4 +76,5 @@ MACHINE_START(H7202, "Hynix HMS30C7202")
.init_irq = h7202_init_irq,
.timer = &h7202_timer,
.init_machine = init_eval_h7202,
+ .dma_zone_size = SZ_256M,
MACHINE_END
diff --git a/arch/arm/mach-h720x/include/mach/entry-macro.S b/arch/arm/mach-h720x/include/mach/entry-macro.S
index 6d3b917c4a18..c3948e5ba4a0 100644
--- a/arch/arm/mach-h720x/include/mach/entry-macro.S
+++ b/arch/arm/mach-h720x/include/mach/entry-macro.S
@@ -57,9 +57,6 @@
tst \irqstat, #1 @ bit 0 should be set
.endm
- .macro irq_prio_table
- .endm
-
#else
#error hynix processor selection missmatch
#endif
diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h
index b0b3baec9acf..96dcf50c51d3 100644
--- a/arch/arm/mach-h720x/include/mach/memory.h
+++ b/arch/arm/mach-h720x/include/mach/memory.h
@@ -8,11 +8,4 @@
#define __ASM_ARCH_MEMORY_H
#define PLAT_PHYS_OFFSET UL(0x40000000)
-/*
- * This is the maximum DMA address that can be DMAd to.
- * There should not be more than (0xd0000000 - 0xc0000000)
- * bytes of RAM.
- */
-#define ARM_DMA_ZONE_SIZE SZ_256M
-
#endif
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 59c97a331136..0519dd7f034b 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -167,6 +167,7 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
bool "Eukrea MBIMXSD development board"
select IMX_HAVE_PLATFORM_GPIO_KEYS
select IMX_HAVE_PLATFORM_IMX_SSI
+ select LEDS_GPIO_REGISTER
help
This adds board specific devices that can be found on Eukrea's
MBIMXSD evaluation board.
@@ -265,6 +266,7 @@ config MACH_EUKREA_MBIMX27_BASEBOARD
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_MXC_MMC
select IMX_HAVE_PLATFORM_SPI_IMX
+ select LEDS_GPIO_REGISTER
help
This adds board specific devices that can be found on Eukrea's
MBIMX27 evaluation board.
@@ -276,6 +278,7 @@ config MACH_MX27_3DS
select SOC_IMX27
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_FB
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_KEYPAD
select IMX_HAVE_PLATFORM_IMX_UART
@@ -403,6 +406,7 @@ config MACH_MX31LITE
select IMX_HAVE_PLATFORM_MXC_NAND
select IMX_HAVE_PLATFORM_MXC_RTC
select IMX_HAVE_PLATFORM_SPI_IMX
+ select LEDS_GPIO_REGISTER
help
Include support for MX31 LITEKIT platform. This includes specific
configurations for the board and its peripherals.
@@ -471,6 +475,7 @@ config MACH_MX31MOBOARD
select IMX_HAVE_PLATFORM_MXC_EHCI
select IMX_HAVE_PLATFORM_MXC_MMC
select IMX_HAVE_PLATFORM_SPI_IMX
+ select LEDS_GPIO_REGISTER
select MXC_ULPI if USB_ULPI
help
Include support for mx31moboard platform. This includes specific
@@ -577,6 +582,7 @@ config MACH_EUKREA_MBIMXSD35_BASEBOARD
select IMX_HAVE_PLATFORM_GPIO_KEYS
select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IPU_CORE
+ select LEDS_GPIO_REGISTER
help
This adds board specific devices that can be found on Eukrea's
MBIMXSD evaluation board.
diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c
index a65838fc061c..af1c580b06bc 100644
--- a/arch/arm/mach-imx/clock-imx25.c
+++ b/arch/arm/mach-imx/clock-imx25.c
@@ -282,9 +282,10 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
- _REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
- _REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
- _REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
+ /* i.mx25 has the i.mx35 type cspi */
+ _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
+ _REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
+ _REGISTER_CLOCK("imx35-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
index 236f1495efad..42afc29a7da8 100644
--- a/arch/arm/mach-imx/dma-v1.c
+++ b/arch/arm/mach-imx/dma-v1.c
@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/scatterlist.h>
@@ -475,7 +476,6 @@ void imx_dma_enable(int channel)
imx_dmav1_writel(imx_dmav1_readl(DMA_CCR(channel)) | CCR_CEN |
CCR_ACRPT, DMA_CCR(channel));
-#ifdef CONFIG_ARCH_MX2
if ((cpu_is_mx21() || cpu_is_mx27()) &&
imxdma->sg && imx_dma_hw_chain(imxdma)) {
imxdma->sg = sg_next(imxdma->sg);
@@ -487,7 +487,6 @@ void imx_dma_enable(int channel)
DMA_CCR(channel));
}
}
-#endif
imxdma->in_use = 1;
local_irq_restore(flags);
@@ -518,7 +517,6 @@ void imx_dma_disable(int channel)
}
EXPORT_SYMBOL(imx_dma_disable);
-#ifdef CONFIG_ARCH_MX2
static void imx_dma_watchdog(unsigned long chno)
{
struct imx_dma_channel *imxdma = &imx_dma_channels[chno];
@@ -530,7 +528,6 @@ static void imx_dma_watchdog(unsigned long chno)
if (imxdma->err_handler)
imxdma->err_handler(chno, imxdma->data, IMX_DMA_ERR_TIMEOUT);
}
-#endif
static irqreturn_t dma_err_handler(int irq, void *dev_id)
{
@@ -654,10 +651,8 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
{
int i, disr;
-#ifdef CONFIG_ARCH_MX2
if (cpu_is_mx21() || cpu_is_mx27())
dma_err_handler(irq, dev_id);
-#endif
disr = imx_dmav1_readl(DMA_DISR);
@@ -703,7 +698,6 @@ int imx_dma_request(int channel, const char *name)
imxdma->name = name;
local_irq_restore(flags); /* request_irq() can block */
-#ifdef CONFIG_ARCH_MX2
if (cpu_is_mx21() || cpu_is_mx27()) {
ret = request_irq(MX2x_INT_DMACH0 + channel,
dma_irq_handler, 0, "DMA", NULL);
@@ -717,7 +711,6 @@ int imx_dma_request(int channel, const char *name)
imxdma->watchdog.function = &imx_dma_watchdog;
imxdma->watchdog.data = channel;
}
-#endif
return ret;
}
@@ -744,10 +737,8 @@ void imx_dma_free(int channel)
imx_dma_disable(channel);
imxdma->name = NULL;
-#ifdef CONFIG_ARCH_MX2
if (cpu_is_mx21() || cpu_is_mx27())
free_irq(MX2x_INT_DMACH0 + channel, NULL);
-#endif
local_irq_restore(flags);
}
@@ -803,21 +794,13 @@ static int __init imx_dma_init(void)
int ret = 0;
int i;
-#ifdef CONFIG_ARCH_MX1
if (cpu_is_mx1())
imx_dmav1_baseaddr = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
- else
-#endif
-#ifdef CONFIG_MACH_MX21
- if (cpu_is_mx21())
+ else if (cpu_is_mx21())
imx_dmav1_baseaddr = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
- else
-#endif
-#ifdef CONFIG_MACH_MX27
- if (cpu_is_mx27())
+ else if (cpu_is_mx27())
imx_dmav1_baseaddr = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
else
-#endif
return 0;
dma_clk = clk_get(NULL, "dma");
@@ -828,7 +811,6 @@ static int __init imx_dma_init(void)
/* reset DMA module */
imx_dmav1_writel(DCR_DRST, DMA_DCR);
-#ifdef CONFIG_ARCH_MX1
if (cpu_is_mx1()) {
ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", NULL);
if (ret) {
@@ -843,7 +825,7 @@ static int __init imx_dma_init(void)
return ret;
}
}
-#endif
+
/* enable DMA module */
imx_dmav1_writel(DCR_DEN, DMA_DCR);
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 5911281da5f5..5db3e1463af7 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -112,7 +112,7 @@ eukrea_mbimx27_keymap_data __initconst = {
.keymap_size = ARRAY_SIZE(eukrea_mbimx27_keymap),
};
-static struct gpio_led gpio_leds[] = {
+static const struct gpio_led eukrea_mbimx27_gpio_leds[] __initconst = {
{
.name = "led1",
.default_trigger = "heartbeat",
@@ -127,17 +127,10 @@ static struct gpio_led gpio_leds[] = {
},
};
-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 const struct gpio_led_platform_data
+ eukrea_mbimx27_gpio_led_info __initconst = {
+ .leds = eukrea_mbimx27_gpio_leds,
+ .num_leds = ARRAY_SIZE(eukrea_mbimx27_gpio_leds),
};
static struct imx_fb_videomode eukrea_mbimx27_modes[] = {
@@ -293,10 +286,6 @@ static struct i2c_board_info eukrea_mbimx27_i2c_devices[] = {
},
};
-static struct platform_device *platform_devices[] __initdata = {
- &leds_gpio,
-};
-
static const struct imxmmc_platform_data sdhc_pdata __initconst = {
.dat3_card_detect = 1,
};
@@ -377,5 +366,5 @@ void __init eukrea_mbimx27_baseboard_init(void)
imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data);
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ gpio_led_register_device(-1, &eukrea_mbimx27_gpio_led_info);
}
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index f9ef04acdab1..01ebcb31e482 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -173,7 +173,7 @@ static struct platform_device eukrea_mbimxsd_lcd_powerdev = {
.dev.platform_data = &eukrea_mbimxsd_lcd_power_data,
};
-static struct gpio_led eukrea_mbimxsd_leds[] = {
+static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
{
.name = "led1",
.default_trigger = "heartbeat",
@@ -182,19 +182,12 @@ static struct gpio_led eukrea_mbimxsd_leds[] = {
},
};
-static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+static const struct gpio_led_platform_data
+ eukrea_mbimxsd_led_info __initconst = {
.leds = eukrea_mbimxsd_leds,
.num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds),
};
-static struct platform_device eukrea_mbimxsd_leds_gpio = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &eukrea_mbimxsd_led_info,
- },
-};
-
static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
{
.gpio = GPIO_SWITCH1,
@@ -212,7 +205,6 @@ static const struct gpio_keys_platform_data
};
static struct platform_device *platform_devices[] __initdata = {
- &eukrea_mbimxsd_leds_gpio,
&eukrea_mbimxsd_lcd_powerdev,
};
@@ -287,5 +279,6 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
}
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 4909ea05855a..558eb526ba56 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -193,19 +193,12 @@ static struct gpio_led eukrea_mbimxsd_leds[] = {
},
};
-static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+static const struct gpio_led_platform_data
+ eukrea_mbimxsd_led_info __initconst = {
.leds = eukrea_mbimxsd_leds,
.num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds),
};
-static struct platform_device eukrea_mbimxsd_leds_gpio = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &eukrea_mbimxsd_led_info,
- },
-};
-
static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
{
.gpio = GPIO_SWITCH1,
@@ -223,7 +216,6 @@ static const struct gpio_keys_platform_data
};
static struct platform_device *platform_devices[] __initdata = {
- &eukrea_mbimxsd_leds_gpio,
&eukrea_mbimxsd_lcd_powerdev,
};
@@ -299,5 +291,6 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
}
diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c
index 15e45c84e371..a404c89485ca 100644
--- a/arch/arm/mach-imx/mach-apf9328.c
+++ b/arch/arm/mach-imx/mach-apf9328.c
@@ -99,11 +99,6 @@ static struct platform_device dm9000x_device = {
}
};
-/* --- SERIAL RESSOURCE --- */
-static const struct imxuart_platform_data uart0_pdata __initconst = {
- .flags = 0,
-};
-
static const struct imxuart_platform_data uart1_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@@ -115,11 +110,13 @@ static struct platform_device *devices[] __initdata = {
static void __init apf9328_init(void)
{
+ imx1_soc_init();
+
mxc_gpio_setup_multiple_pins(apf9328_pins,
ARRAY_SIZE(apf9328_pins),
"APF9328");
- imx1_add_imx_uart0(&uart0_pdata);
+ imx1_add_imx_uart0(NULL);
imx1_add_imx_uart1(&uart1_pdata);
platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index ffb40ff619b1..ede2710f8b76 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -490,6 +490,8 @@ static struct platform_device *devices[] __initdata = {
*/
static void __init armadillo5x0_init(void)
{
+ imx31_soc_init();
+
mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");
diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c
index 42e4f078a19c..f49470553bdf 100644
--- a/arch/arm/mach-imx/mach-bug.c
+++ b/arch/arm/mach-imx/mach-bug.c
@@ -42,6 +42,8 @@ static const unsigned int bug_pins[] __initconst = {
static void __init bug_board_init(void)
{
+ imx31_soc_init();
+
mxc_iomux_setup_multiple_pins(bug_pins,
ARRAY_SIZE(bug_pins), "uart-4");
imx31_add_imx_uart4(&uart_pdata);
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 46a2e41d43d2..87887ac5806b 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -250,6 +250,8 @@ __setup("otg_mode=", eukrea_cpuimx27_otg_mode);
static void __init eukrea_cpuimx27_init(void)
{
+ imx27_soc_init();
+
mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins,
ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27");
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 3f8ef825fa6f..f39a478ba1a6 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -156,6 +156,8 @@ __setup("otg_mode=", eukrea_cpuimx35_otg_mode);
*/
static void __init eukrea_cpuimx35_init(void)
{
+ imx35_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
ARRAY_SIZE(eukrea_cpuimx35_pads));
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index 148cff2819b9..da36da52969d 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -125,6 +125,8 @@ __setup("otg_mode=", eukrea_cpuimx25_otg_mode);
static void __init eukrea_cpuimx25_init(void)
{
+ imx25_soc_init();
+
if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads,
ARRAY_SIZE(eukrea_cpuimx25_pads)))
printk(KERN_ERR "error setting cpuimx25 pads !\n");
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 7ae43b1ec517..6707de0ab716 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -34,7 +34,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>
-#include <mach/iomux.h>
+#include <mach/iomux-mx27.h>
#include "devices-imx27.h"
@@ -231,6 +231,8 @@ static void __init visstrim_m10_board_init(void)
{
int ret;
+ imx27_soc_init();
+
ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,
ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");
if (ret)
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
index 9be6cd6fbf8c..272f793e9247 100644
--- a/arch/arm/mach-imx/mach-imx27ipcam.c
+++ b/arch/arm/mach-imx/mach-imx27ipcam.c
@@ -50,6 +50,8 @@ static const int mx27ipcam_pins[] __initconst = {
static void __init mx27ipcam_init(void)
{
+ imx27_soc_init();
+
mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),
"mx27ipcam");
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index 841140516ede..d81a769fe895 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -59,6 +59,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
static void __init mx27lite_init(void)
{
+ imx27_soc_init();
+
mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
"imx27lite");
imx27_add_imx_uart0(&uart_pdata);
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index 1ecae20cf4e3..e472a1d88058 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -223,6 +223,8 @@ static int kzm_pins[] __initdata = {
*/
static void __init kzm_board_init(void)
{
+ imx31_soc_init();
+
mxc_iomux_setup_multiple_pins(kzm_pins,
ARRAY_SIZE(kzm_pins), "kzm");
kzm_init_ext_uart();
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 38ec5cbbda9b..5cd8bee46960 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -115,6 +115,8 @@ static struct i2c_board_info mx1ads_i2c_devices[] = {
*/
static void __init mx1ads_init(void)
{
+ imx1_soc_init();
+
mxc_gpio_setup_multiple_pins(mx1ads_pins,
ARRAY_SIZE(mx1ads_pins), "mx1ads");
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 74ac88978ddd..d389ecf9b5a8 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -279,6 +279,8 @@ static struct platform_device *platform_devices[] __initdata = {
static void __init mx21ads_board_init(void)
{
+ imx21_soc_init();
+
mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins),
"mx21ads");
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 58ea3fdf0911..01534bb61305 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -219,6 +219,8 @@ static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
static void __init mx25pdk_init(void)
{
+ imx25_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
ARRAY_SIZE(mx25pdk_pads));
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 6e1accf93f81..6fa6934ab150 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -29,6 +29,7 @@
#include <linux/mfd/mc13783.h>
#include <linux/spi/spi.h>
#include <linux/regulator/machine.h>
+#include <linux/spi/l4f00242t03.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -42,10 +43,15 @@
#include "devices-imx27.h"
-#define SD1_EN_GPIO (GPIO_PORTB + 25)
-#define OTG_PHY_RESET_GPIO (GPIO_PORTB + 23)
-#define SPI2_SS0 (GPIO_PORTD + 21)
-#define EXPIO_PARENT_INT (MXC_INTERNAL_IRQS + GPIO_PORTC + 28)
+#define SD1_EN_GPIO IMX_GPIO_NR(2, 25)
+#define OTG_PHY_RESET_GPIO IMX_GPIO_NR(2, 23)
+#define SPI2_SS0 IMX_GPIO_NR(4, 21)
+#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(3, 28))
+#define PMIC_INT IMX_GPIO_NR(3, 14)
+#define SPI1_SS0 IMX_GPIO_NR(4, 28)
+#define SD1_CD IMX_GPIO_NR(2, 26)
+#define LCD_RESET IMX_GPIO_NR(1, 3)
+#define LCD_ENABLE IMX_GPIO_NR(1, 31)
static const int mx27pdk_pins[] __initconst = {
/* UART1 */
@@ -94,13 +100,47 @@ static const int mx27pdk_pins[] __initconst = {
PE2_PF_USBOTG_DIR,
PE24_PF_USBOTG_CLK,
PE25_PF_USBOTG_DATA7,
+ /* CSPI1 */
+ PD31_PF_CSPI1_MOSI,
+ PD30_PF_CSPI1_MISO,
+ PD29_PF_CSPI1_SCLK,
+ PD25_PF_CSPI1_RDY,
+ SPI1_SS0 | GPIO_GPIO | GPIO_OUT,
/* CSPI2 */
PD22_PF_CSPI2_SCLK,
PD23_PF_CSPI2_MISO,
PD24_PF_CSPI2_MOSI,
+ SPI2_SS0 | GPIO_GPIO | GPIO_OUT,
/* I2C1 */
PD17_PF_I2C_DATA,
PD18_PF_I2C_CLK,
+ /* PMIC INT */
+ PMIC_INT | GPIO_GPIO | GPIO_IN,
+ /* LCD */
+ PA5_PF_LSCLK,
+ PA6_PF_LD0,
+ PA7_PF_LD1,
+ PA8_PF_LD2,
+ PA9_PF_LD3,
+ PA10_PF_LD4,
+ PA11_PF_LD5,
+ PA12_PF_LD6,
+ PA13_PF_LD7,
+ PA14_PF_LD8,
+ PA15_PF_LD9,
+ PA16_PF_LD10,
+ PA17_PF_LD11,
+ PA18_PF_LD12,
+ PA19_PF_LD13,
+ PA20_PF_LD14,
+ PA21_PF_LD15,
+ PA22_PF_LD16,
+ PA23_PF_LD17,
+ PA28_PF_HSYNC,
+ PA29_PF_VSYNC,
+ PA30_PF_CONTRAST,
+ LCD_ENABLE | GPIO_GPIO | GPIO_OUT,
+ LCD_RESET | GPIO_GPIO | GPIO_OUT,
};
static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -131,13 +171,13 @@ static const struct matrix_keymap_data mx27_3ds_keymap_data __initconst = {
static int mx27_3ds_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
void *data)
{
- return request_irq(IRQ_GPIOB(26), detect_irq, IRQF_TRIGGER_FALLING |
- IRQF_TRIGGER_RISING, "sdhc1-card-detect", data);
+ return request_irq(gpio_to_irq(SD1_CD), detect_irq,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "sdhc1-card-detect", data);
}
static void mx27_3ds_sdhc1_exit(struct device *dev, void *data)
{
- free_irq(IRQ_GPIOB(26), data);
+ free_irq(gpio_to_irq(SD1_CD), data);
}
static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
@@ -193,6 +233,13 @@ static int __init mx27_3ds_otg_mode(char *options)
__setup("otg_mode=", mx27_3ds_otg_mode);
/* Regulators */
+static struct regulator_init_data gpo_init = {
+ .constraints = {
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
static struct regulator_consumer_supply vmmc1_consumers[] = {
REGULATOR_SUPPLY("lcd_2v8", NULL),
};
@@ -201,7 +248,9 @@ static struct regulator_init_data vmmc1_init = {
.constraints = {
.min_uV = 2800000,
.max_uV = 2800000,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(vmmc1_consumers),
.consumer_supplies = vmmc1_consumers,
@@ -228,6 +277,12 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
}, {
.id = MC13783_REG_VGEN,
.init_data = &vgen_init,
+ }, {
+ .id = MC13783_REG_GPO1, /* Turn on 1.8V */
+ .init_data = &gpo_init,
+ }, {
+ .id = MC13783_REG_GPO3, /* Turn on 3.3V */
+ .init_data = &gpo_init,
},
};
@@ -238,15 +293,63 @@ static struct mc13xxx_platform_data mc13783_pdata = {
.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
},
- .flags = MC13783_USE_REGULATOR,
+ .flags = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN |
+ MC13783_USE_RTC,
};
/* SPI */
-static int spi2_internal_chipselect[] = {SPI2_SS0};
+static int spi1_chipselect[] = {SPI1_SS0};
+
+static const struct spi_imx_master spi1_pdata __initconst = {
+ .chipselect = spi1_chipselect,
+ .num_chipselect = ARRAY_SIZE(spi1_chipselect),
+};
+
+static int spi2_chipselect[] = {SPI2_SS0};
static const struct spi_imx_master spi2_pdata __initconst = {
- .chipselect = spi2_internal_chipselect,
- .num_chipselect = ARRAY_SIZE(spi2_internal_chipselect),
+ .chipselect = spi2_chipselect,
+ .num_chipselect = ARRAY_SIZE(spi2_chipselect),
+};
+
+static struct imx_fb_videomode mx27_3ds_modes[] = {
+ { /* 480x640 @ 60 Hz */
+ .mode = {
+ .name = "Epson-VGA",
+ .refresh = 60,
+ .xres = 480,
+ .yres = 640,
+ .pixclock = 41701,
+ .left_margin = 20,
+ .right_margin = 41,
+ .upper_margin = 10,
+ .lower_margin = 5,
+ .hsync_len = 20,
+ .vsync_len = 10,
+ .sync = FB_SYNC_OE_ACT_HIGH |
+ FB_SYNC_CLK_INVERT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ },
+ .bpp = 16,
+ .pcr = 0xFAC08B82,
+ },
+};
+
+static const struct imx_fb_platform_data mx27_3ds_fb_data __initconst = {
+ .mode = mx27_3ds_modes,
+ .num_modes = ARRAY_SIZE(mx27_3ds_modes),
+ .pwmr = 0x00A903FF,
+ .lscr1 = 0x00120300,
+ .dmacr = 0x00020010,
+};
+
+/* LCD */
+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 = {
@@ -256,8 +359,14 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
.bus_num = 1,
.chip_select = 0, /* SS0 */
.platform_data = &mc13783_pdata,
- .irq = IRQ_GPIOC(14),
+ .irq = gpio_to_irq(PMIC_INT),
.mode = SPI_CS_HIGH,
+ }, {
+ .modalias = "l4f00242t03",
+ .max_speed_hz = 5000000,
+ .bus_num = 0,
+ .chip_select = 0, /* SS0 */
+ .platform_data = &mx27_3ds_lcd_pdata,
},
};
@@ -267,6 +376,8 @@ static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
static void __init mx27pdk_init(void)
{
+ imx27_soc_init();
+
mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
"mx27pdk");
mx27_3ds_sdhc1_enable_level_translator();
@@ -289,12 +400,14 @@ static void __init mx27pdk_init(void)
imx27_add_fsl_usb2_udc(&otg_device_pdata);
imx27_add_spi_imx1(&spi2_pdata);
+ imx27_add_spi_imx0(&spi1_pdata);
spi_register_board_info(mx27_3ds_spi_devs,
ARRAY_SIZE(mx27_3ds_spi_devs));
if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
+ imx27_add_imx_fb(&mx27_3ds_fb_data);
}
static void __init mx27pdk_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 1db79506f5e4..fc26ed71b9ed 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -288,6 +288,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
static void __init mx27ads_board_init(void)
{
+ imx27_soc_init();
+
mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins),
"mx27ads");
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 9b982449cb52..c20be7530927 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -13,6 +13,7 @@
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/clk.h>
@@ -53,11 +54,8 @@ static int mx31_3ds_pins[] = {
MX31_PIN_RXD1__RXD1,
IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
/*SPI0*/
- MX31_PIN_CSPI1_SCLK__SCLK,
- MX31_PIN_CSPI1_MOSI__MOSI,
- MX31_PIN_CSPI1_MISO__MISO,
- MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
- MX31_PIN_CSPI1_SS2__SS2, /* CS for LCD */
+ IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_ALT1),
+ IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_ALT1),
/* SPI 1 */
MX31_PIN_CSPI2_SCLK__SCLK,
MX31_PIN_CSPI2_MOSI__MOSI,
@@ -689,6 +687,11 @@ static void __init mx31_3ds_init(void)
{
int ret;
+ imx31_soc_init();
+
+ /* Configure SPI1 IOMUX */
+ mxc_iomux_set_gpr(MUX_PGP_CSPI_BB, true);
+
mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
"mx31_3ds");
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c
index f4dee0254634..0ce49478a479 100644
--- a/arch/arm/mach-imx/mach-mx31ads.c
+++ b/arch/arm/mach-imx/mach-mx31ads.c
@@ -516,6 +516,8 @@ static void __init mx31ads_init_irq(void)
static void __init mx31ads_init(void)
{
+ imx31_soc_init();
+
mxc_init_extuart();
mxc_init_imx_uart();
mxc_init_i2c();
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index 410e676ae087..750368ddf0f9 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -243,6 +243,8 @@ core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
static void __init mx31lilly_board_init(void)
{
+ imx31_soc_init();
+
switch (mx31lilly_baseboard) {
case MX31LILLY_NOBOARD:
break;
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index ac9b4cad320e..4b47fd9fdd89 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -230,6 +230,8 @@ static void __init mx31lite_init(void)
{
int ret;
+ imx31_soc_init();
+
switch (mx31lite_baseboard) {
case MX31LITE_NOBOARD:
break;
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index eaa51e49ca95..b358383120e7 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -425,7 +425,7 @@ static int __init moboard_usbh2_init(void)
return 0;
}
-static struct gpio_led mx31moboard_leds[] = {
+static const struct gpio_led mx31moboard_leds[] __initconst = {
{
.name = "coreboard-led-0:red:running",
.default_trigger = "heartbeat",
@@ -442,26 +442,17 @@ static struct gpio_led mx31moboard_leds[] = {
},
};
-static struct gpio_led_platform_data mx31moboard_led_pdata = {
+static const struct gpio_led_platform_data mx31moboard_led_pdata __initconst = {
.num_leds = ARRAY_SIZE(mx31moboard_leds),
.leds = mx31moboard_leds,
};
-static struct platform_device mx31moboard_leds_device = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &mx31moboard_led_pdata,
- },
-};
-
static const struct ipu_platform_data mx3_ipu_data __initconst = {
.irq_base = MXC_IPU_IRQ_START,
};
static struct platform_device *devices[] __initdata = {
&mx31moboard_flash,
- &mx31moboard_leds_device,
};
static struct mx3_camera_pdata camera_pdata __initdata = {
@@ -507,10 +498,13 @@ core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
*/
static void __init mx31moboard_init(void)
{
+ imx31_soc_init();
+
mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
"moboard");
platform_add_devices(devices, ARRAY_SIZE(devices));
+ gpio_led_register_device(-1, &mx31moboard_led_pdata);
imx31_add_imx_uart0(&uart0_pdata);
imx31_add_imx_uart4(&uart4_pdata);
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index 882880ac1bbc..b3b9bd8ac2a3 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -43,7 +43,7 @@
#include "devices-imx35.h"
-#define EXPIO_PARENT_INT (MXC_INTERNAL_IRQS + GPIO_PORTA + 1)
+#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 1))
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
@@ -179,6 +179,8 @@ static const struct imxi2c_platform_data mx35_3ds_i2c0_data __initconst = {
*/
static void __init mx35_3ds_init(void)
{
+ imx35_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
imx35_add_fec(NULL);
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index 2774541511e7..c85876fed663 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -233,6 +233,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
static void __init mxt_td60_board_init(void)
{
+ imx27_soc_init();
+
mxc_gpio_setup_multiple_pins(mxt_td60_pins, ARRAY_SIZE(mxt_td60_pins),
"MXT_TD60");
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index bbddc5a11c43..71083aa16038 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -357,6 +357,8 @@ static void __init pca100_init(void)
{
int ret;
+ imx27_soc_init();
+
/* SSI unit */
mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index 89c213b81295..f45b7cd72c8a 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -576,6 +576,8 @@ static void __init pcm037_init(void)
{
int ret;
+ imx31_soc_init();
+
mxc_iomux_set_gpr(MUX_PGP_UH2, 1);
mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 853bb871c7ed..2d6a64bbac44 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -295,6 +295,8 @@ static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
static void __init pcm038_init(void)
{
+ imx27_soc_init();
+
mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),
"PCM038");
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 026441628dfa..163cc318cafb 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -356,6 +356,8 @@ static struct esdhc_platform_data sd1_pdata = {
*/
static void __init pcm043_init(void)
{
+ imx35_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
mxc_audmux_v2_configure_port(3,
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index c16328715939..3626f486498a 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -244,6 +244,8 @@ static void __init qong_init_fpga(void)
*/
static void __init qong_init(void)
{
+ imx31_soc_init();
+
mxc_init_imx_uart();
qong_init_nor_mtd();
qong_init_fpga();
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index dcaee043628e..db2d60470e15 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -101,21 +101,7 @@ static const int mxc_uart1_pins[] = {
PC12_PF_UART1_RXD,
};
-static int uart1_mxc_init(struct platform_device *pdev)
-{
- return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
- ARRAY_SIZE(mxc_uart1_pins), "UART1");
-}
-
-static void uart1_mxc_exit(struct platform_device *pdev)
-{
- mxc_gpio_release_multiple_pins(mxc_uart1_pins,
- ARRAY_SIZE(mxc_uart1_pins));
-}
-
static const struct imxuart_platform_data uart_pdata __initconst = {
- .init = uart1_mxc_init,
- .exit = uart1_mxc_exit,
.flags = IMXUART_HAVE_RTSCTS,
};
@@ -129,6 +115,11 @@ static struct platform_device *devices[] __initdata = {
*/
static void __init scb9328_init(void)
{
+ imx1_soc_init();
+
+ mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
+ ARRAY_SIZE(mxc_uart1_pins), "UART1");
+
imx1_add_imx_uart0(&uart_pdata);
printk(KERN_INFO"Scb9328: Adding devices\n");
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index d74e3473d236..7d8e012a6335 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -267,6 +267,8 @@ static struct platform_device *devices[] __initdata = {
*/
static void __init vpr200_board_init(void)
{
+ imx35_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
imx35_add_fec(NULL);
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 2e482ba5a0e7..2bded591d5c2 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -23,7 +23,6 @@
#include <mach/common.h>
#include <mach/hardware.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>
@@ -44,15 +43,19 @@ void __init imx1_init_early(void)
MX1_NUM_GPIO_PORT);
}
-static struct mxc_gpio_port imx1_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
-};
-
void __init mx1_init_irq(void)
{
mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR));
- mxc_gpio_init(imx1_gpio_ports, ARRAY_SIZE(imx1_gpio_ports));
+}
+
+void __init imx1_soc_init(void)
+{
+ mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256,
+ MX1_GPIO_INT_PORTA, 0);
+ mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256,
+ MX1_GPIO_INT_PORTB, 0);
+ mxc_register_gpio("imx1-gpio", 2, MX1_GPIO3_BASE_ADDR, SZ_256,
+ MX1_GPIO_INT_PORTC, 0);
+ mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256,
+ MX1_GPIO_INT_PORTD, 0);
}
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index 7a0c500ac2c8..3f05dfebacc9 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -22,9 +22,9 @@
#include <linux/init.h>
#include <mach/hardware.h>
#include <mach/common.h>
+#include <mach/devices-common.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>
@@ -70,17 +70,19 @@ void __init imx21_init_early(void)
MX21_NUM_GPIO_PORT);
}
-static struct mxc_gpio_port imx21_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
- DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
- DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
- DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
- DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
- DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
-};
-
void __init mx21_init_irq(void)
{
mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
- mxc_gpio_init(imx21_gpio_ports, ARRAY_SIZE(imx21_gpio_ports));
+}
+
+void __init imx21_soc_init(void)
+{
+ mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 1, MX21_GPIO2_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 2, MX21_GPIO3_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 3, MX21_GPIO4_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 4, MX21_GPIO5_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+
+ imx_add_imx_dma();
}
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index 02f7b5c7fa8e..8bf029164652 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -24,10 +24,10 @@
#include <asm/mach/map.h>
#include <mach/common.h>
+#include <mach/devices-common.h>
#include <mach/hardware.h>
#include <mach/mx25.h>
#include <mach/iomux-v3.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
/*
@@ -57,16 +57,40 @@ void __init imx25_init_early(void)
mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
}
-static struct mxc_gpio_port imx25_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
-};
-
void __init mx25_init_irq(void)
{
mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
- mxc_gpio_init(imx25_gpio_ports, ARRAY_SIZE(imx25_gpio_ports));
}
+static struct sdma_script_start_addrs imx25_sdma_script __initdata = {
+ .ap_2_ap_addr = 729,
+ .uart_2_mcu_addr = 904,
+ .per_2_app_addr = 1255,
+ .mcu_2_app_addr = 834,
+ .uartsh_2_mcu_addr = 1120,
+ .per_2_shp_addr = 1329,
+ .mcu_2_shp_addr = 1048,
+ .ata_2_mcu_addr = 1560,
+ .mcu_2_ata_addr = 1479,
+ .app_2_per_addr = 1189,
+ .app_2_mcu_addr = 770,
+ .shp_2_per_addr = 1407,
+ .shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx25_sdma_pdata __initdata = {
+ .sdma_version = 2,
+ .fw_name = "sdma-imx25.bin",
+ .script_addrs = &imx25_sdma_script,
+};
+
+void __init imx25_soc_init(void)
+{
+ /* i.mx25 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
+ mxc_register_gpio("imx31-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
+ mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
+ mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
+
+ imx_add_imx_sdma(MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
+}
diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index a6761a39f08c..96dd1f5ea7bd 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -22,9 +22,9 @@
#include <linux/init.h>
#include <mach/hardware.h>
#include <mach/common.h>
+#include <mach/devices-common.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>
@@ -70,17 +70,20 @@ void __init imx27_init_early(void)
MX27_NUM_GPIO_PORT);
}
-static struct mxc_gpio_port imx27_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
- DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
- DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
- DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
- DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
- DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
-};
-
void __init mx27_init_irq(void)
{
mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
- mxc_gpio_init(imx27_gpio_ports, ARRAY_SIZE(imx27_gpio_ports));
+}
+
+void __init imx27_soc_init(void)
+{
+ /* i.mx27 has the i.mx21 type gpio */
+ mxc_register_gpio("imx21-gpio", 0, MX27_GPIO1_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 1, MX27_GPIO2_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 2, MX27_GPIO3_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 3, MX27_GPIO4_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 4, MX27_GPIO5_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+ mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+
+ imx_add_imx_dma();
}
diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c
index 86b9b45864d2..61bff38cb955 100644
--- a/arch/arm/mach-imx/mm-imx31.c
+++ b/arch/arm/mach-imx/mm-imx31.c
@@ -24,9 +24,9 @@
#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/gpio.h>
#include <mach/irqs.h>
static struct map_desc mx31_io_desc[] __initdata = {
@@ -53,14 +53,40 @@ void __init imx31_init_early(void)
mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
}
-static struct mxc_gpio_port imx31_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
- DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
- DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
-};
-
void __init mx31_init_irq(void)
{
mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
- mxc_gpio_init(imx31_gpio_ports, ARRAY_SIZE(imx31_gpio_ports));
+}
+
+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 = {
+ .sdma_version = 1,
+ .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(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
index c880e6d1ae55..98769ae34377 100644
--- a/arch/arm/mach-imx/mm-imx35.c
+++ b/arch/arm/mach-imx/mm-imx35.c
@@ -25,9 +25,9 @@
#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/gpio.h>
#include <mach/irqs.h>
static struct map_desc mx35_io_desc[] __initdata = {
@@ -50,14 +50,61 @@ void __init imx35_init_early(void)
mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
}
-static struct mxc_gpio_port imx35_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
- DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
- DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
-};
-
void __init mx35_init_irq(void)
{
mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
- mxc_gpio_init(imx35_gpio_ports, ARRAY_SIZE(imx35_gpio_ports));
+}
+
+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 = {
+ .sdma_version = 2,
+ .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(MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
}
diff --git a/arch/arm/mach-imx/mx31lite-db.c b/arch/arm/mach-imx/mx31lite-db.c
index 5aa053edc17c..bf0fb87946ba 100644
--- a/arch/arm/mach-imx/mx31lite-db.c
+++ b/arch/arm/mach-imx/mx31lite-db.c
@@ -161,7 +161,7 @@ static const struct spi_imx_master spi0_pdata __initconst = {
/* GPIO LEDs */
-static struct gpio_led litekit_leds[] = {
+static const struct gpio_led litekit_leds[] __initconst = {
{
.name = "GPIO0",
.gpio = IOMUX_TO_GPIO(MX31_PIN_COMPARE),
@@ -176,19 +176,12 @@ static struct gpio_led litekit_leds[] = {
}
};
-static struct gpio_led_platform_data litekit_led_platform_data = {
+static const struct gpio_led_platform_data
+ litekit_led_platform_data __initconst = {
.leds = litekit_leds,
.num_leds = ARRAY_SIZE(litekit_leds),
};
-static struct platform_device litekit_led_device = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &litekit_led_platform_data,
- },
-};
-
void __init mx31lite_db_init(void)
{
mxc_iomux_setup_multiple_pins(litekit_db_board_pins,
@@ -197,7 +190,7 @@ void __init mx31lite_db_init(void)
imx31_add_imx_uart0(&uart_pdata);
imx31_add_mxc_mmc(0, &mmc_pdata);
imx31_add_spi_imx0(&spi0_pdata);
- platform_device_register(&litekit_led_device);
+ gpio_led_register_device(-1, &litekit_led_platform_data);
imx31_add_imx2_wdt(NULL);
imx31_add_mxc_rtc(NULL);
}
diff --git a/arch/arm/mach-integrator/include/mach/bits.h b/arch/arm/mach-integrator/include/mach/bits.h
deleted file mode 100644
index 09b024e0496a..000000000000
--- a/arch/arm/mach-integrator/include/mach/bits.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * 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
- */
-/* Bit field definitions
- * Copyright (C) ARM Limited 1998. All rights reserved.
- */
-
-#ifndef __bits_h
-#define __bits_h 1
-
-#define BIT0 0x00000001
-#define BIT1 0x00000002
-#define BIT2 0x00000004
-#define BIT3 0x00000008
-#define BIT4 0x00000010
-#define BIT5 0x00000020
-#define BIT6 0x00000040
-#define BIT7 0x00000080
-#define BIT8 0x00000100
-#define BIT9 0x00000200
-#define BIT10 0x00000400
-#define BIT11 0x00000800
-#define BIT12 0x00001000
-#define BIT13 0x00002000
-#define BIT14 0x00004000
-#define BIT15 0x00008000
-#define BIT16 0x00010000
-#define BIT17 0x00020000
-#define BIT18 0x00040000
-#define BIT19 0x00080000
-#define BIT20 0x00100000
-#define BIT21 0x00200000
-#define BIT22 0x00400000
-#define BIT23 0x00800000
-#define BIT24 0x01000000
-#define BIT25 0x02000000
-#define BIT26 0x04000000
-#define BIT27 0x08000000
-#define BIT28 0x10000000
-#define BIT29 0x20000000
-#define BIT30 0x40000000
-#define BIT31 0x80000000
-
-#endif
-
-/* END */
diff --git a/arch/arm/mach-integrator/include/mach/hardware.h b/arch/arm/mach-integrator/include/mach/hardware.h
index 57f51ba11251..65fed7c0eb84 100644
--- a/arch/arm/mach-integrator/include/mach/hardware.h
+++ b/arch/arm/mach-integrator/include/mach/hardware.h
@@ -32,13 +32,6 @@
#define IO_SIZE 0x0B000000 // How much?
#define IO_START INTEGRATOR_HDR_BASE // PA of IO
-#define PCIMEM_BASE PCI_MEMORY_VADDR
-
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x6000
-#define PCIBIOS_MIN_MEM 0x00100000
-
/* macro to get at IO space when running virtually */
#ifdef CONFIG_MMU
#define IO_ADDRESS(x) (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE)
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 6467d99fa2ee..dd56bfb351e3 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -27,6 +27,7 @@
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <video/vga.h>
#include <mach/hardware.h>
#include <mach/platform.h>
@@ -502,6 +503,10 @@ void __init pci_v3_preinit(void)
unsigned int temp;
int ret;
+ pcibios_min_io = 0x6000;
+ pcibios_min_mem = 0x00100000;
+ vga_base = PCI_MEMORY_VADDR;
+
/*
* Hook in our fault handler for PCI errors
*/
diff --git a/arch/arm/mach-iop13xx/include/mach/hardware.h b/arch/arm/mach-iop13xx/include/mach/hardware.h
index 8e1d56289846..786fa266fab3 100644
--- a/arch/arm/mach-iop13xx/include/mach/hardware.h
+++ b/arch/arm/mach-iop13xx/include/mach/hardware.h
@@ -2,18 +2,11 @@
#define __ASM_ARCH_HARDWARE_H
#include <asm/types.h>
-#define pcibios_assign_all_busses() 1
-
#ifndef __ASSEMBLY__
-extern unsigned long iop13xx_pcibios_min_io;
-extern unsigned long iop13xx_pcibios_min_mem;
extern u16 iop13xx_dev_id(void);
extern void iop13xx_set_atu_mmr_bases(void);
#endif
-#define PCIBIOS_MIN_IO (iop13xx_pcibios_min_io)
-#define PCIBIOS_MIN_MEM (iop13xx_pcibios_min_mem)
-
/*
* Generic chipset bits
*
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
index ba3dae352a2d..0690b1d7fd3e 100644
--- a/arch/arm/mach-iop13xx/pci.c
+++ b/arch/arm/mach-iop13xx/pci.c
@@ -39,8 +39,6 @@ u32 iop13xx_atue_mem_base;
u32 iop13xx_atux_mem_base;
size_t iop13xx_atue_mem_size;
size_t iop13xx_atux_mem_size;
-unsigned long iop13xx_pcibios_min_io = 0;
-unsigned long iop13xx_pcibios_min_mem = 0;
EXPORT_SYMBOL(iop13xx_atue_mem_base);
EXPORT_SYMBOL(iop13xx_atux_mem_base);
@@ -971,7 +969,8 @@ void __init iop13xx_pci_init(void)
__raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR);
/* Setup the Min Address for PCI memory... */
- iop13xx_pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
+ pcibios_min_io = 0;
+ pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
/* if Linux is given control of an ATU
* clear out its prior configuration,
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index 5c147fb66a01..a5b989728b9e 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -17,6 +17,7 @@
*
*/
+#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
#include <linux/io.h>
#ifdef CONFIG_MTD_PHYSMAP
diff --git a/arch/arm/mach-iop32x/include/mach/hardware.h b/arch/arm/mach-iop32x/include/mach/hardware.h
index d559c4e6095a..48cb1b20ba91 100644
--- a/arch/arm/mach-iop32x/include/mach/hardware.h
+++ b/arch/arm/mach-iop32x/include/mach/hardware.h
@@ -18,9 +18,6 @@
* but when we read them, we convert them to virtual addresses. See
* arch/arm/plat-iop/pci.c.
*/
-#define pcibios_assign_all_busses() 1
-#define PCIBIOS_MIN_IO 0x00000000
-#define PCIBIOS_MIN_MEM 0x00000000
#ifndef __ASSEMBLY__
void iop32x_init_irq(void);
diff --git a/arch/arm/mach-iop33x/include/mach/hardware.h b/arch/arm/mach-iop33x/include/mach/hardware.h
index 8c10e430655e..839285315e4e 100644
--- a/arch/arm/mach-iop33x/include/mach/hardware.h
+++ b/arch/arm/mach-iop33x/include/mach/hardware.h
@@ -18,9 +18,6 @@
* but when we read them, we convert them to virtual addresses. See
* arch/arm/mach-iop3xx/iop3xx-pci.c
*/
-#define pcibios_assign_all_busses() 1
-#define PCIBIOS_MIN_IO 0x00000000
-#define PCIBIOS_MIN_MEM 0x00000000
#ifndef __ASSEMBLY__
void iop33x_init_irq(void);
diff --git a/arch/arm/mach-ixp2000/include/mach/hardware.h b/arch/arm/mach-ixp2000/include/mach/hardware.h
index f033de4e7493..cdaf1db84003 100644
--- a/arch/arm/mach-ixp2000/include/mach/hardware.h
+++ b/arch/arm/mach-ixp2000/include/mach/hardware.h
@@ -19,16 +19,8 @@
#ifndef __ASM_ARCH_HARDWARE_H__
#define __ASM_ARCH_HARDWARE_H__
-/*
- * This needs to be platform-specific?
- */
-#define PCIBIOS_MIN_IO 0x00000000
-#define PCIBIOS_MIN_MEM 0x00000000
-
#include "ixp2000-regs.h" /* Chipset Registers */
-#define pcibios_assign_all_busses() 0
-
/*
* Platform helper functions
*/
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
index f797c5f538b0..f5098b306fd3 100644
--- a/arch/arm/mach-ixp2000/pci.c
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -196,6 +196,11 @@ clear_master_aborts(void)
void __init
ixp2000_pci_preinit(void)
{
+ pci_set_flags(0);
+
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0;
+
#ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
/*
* Configure the PCI unit to properly byteswap I/O transactions,
diff --git a/arch/arm/mach-ixp23xx/include/mach/hardware.h b/arch/arm/mach-ixp23xx/include/mach/hardware.h
index 57b508bfe280..60e55fa10238 100644
--- a/arch/arm/mach-ixp23xx/include/mach/hardware.h
+++ b/arch/arm/mach-ixp23xx/include/mach/hardware.h
@@ -15,13 +15,9 @@
#define __ASM_ARCH_HARDWARE_H
/* PCI IO info */
-#define PCIBIOS_MIN_IO 0x00000000
-#define PCIBIOS_MIN_MEM 0xe0000000
#include "ixp23xx.h"
-#define pcibios_assign_all_busses() 0
-
/*
* Platform helper functions
*/
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index 563819a83292..e6be5711c700 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -227,6 +227,11 @@ static void __init ixp23xx_pci_common_init(void)
void __init ixp23xx_pci_preinit(void)
{
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0xe0000000;
+
+ pci_set_flags(0);
+
ixp23xx_pci_common_init();
hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS, 0,
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
index 73745ff102d5..ee19c1d383aa 100644
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -169,6 +169,9 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = avila_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
/*
@@ -184,6 +187,9 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = avila_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index e9a589395723..2131832ee6ba 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -316,6 +316,11 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r
}
+static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+ return (dma_addr + size) >= SZ_64M;
+}
+
/*
* Setup DMA mask to 64MB on PCI devices. Ignore all other devices.
*/
@@ -324,7 +329,7 @@ static int ixp4xx_pci_platform_notify(struct device *dev)
if(dev->bus == &pci_bus_type) {
*dev->dma_mask = SZ_64M - 1;
dev->coherent_dma_mask = SZ_64M - 1;
- dmabounce_register_dev(dev, 2048, 4096);
+ dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
}
return 0;
}
@@ -337,15 +342,15 @@ static int ixp4xx_pci_platform_notify_remove(struct device *dev)
return 0;
}
-int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
- return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);
-}
-
void __init ixp4xx_pci_preinit(void)
{
unsigned long cpuid = read_cpuid_id();
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+ pcibios_min_mem = 0x10000000; /* 1 GB of indirect PCI MMIO space */
+#else
+ pcibios_min_mem = 0x48000000; /* 64 MB of PCI MMIO space */
+#endif
/*
* Determine which PCI read method to use.
* Rev 0 IXP425 requires workaround.
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 355e3de38733..e24564b5d935 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -114,6 +114,9 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = coyote_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index d398229cfaa5..03e54515e8b3 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -284,4 +284,7 @@ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
.init_irq = ixp4xx_init_irq,
.timer = &dsmg600_timer,
.init_machine = dsmg600_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index 727ee39ce11c..23a8b3614568 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -275,5 +275,8 @@ MACHINE_START(FSG, "Freecom FSG-3")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = fsg_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
index 9dc0b4eaa65a..d4f851bdd9a4 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -101,5 +101,8 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = gateway7001_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index 3e8c0e33b59c..5f00ad224fe0 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -501,4 +501,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = gmlr_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 77abead36227..3790dffd3c30 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -169,6 +169,9 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = gtwx5715_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/include/mach/hardware.h b/arch/arm/mach-ixp4xx/include/mach/hardware.h
index 8138371c406e..c30e7e923a73 100644
--- a/arch/arm/mach-ixp4xx/include/mach/hardware.h
+++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h
@@ -17,19 +17,14 @@
#ifndef __ASM_ARCH_HARDWARE_H__
#define __ASM_ARCH_HARDWARE_H__
-#define PCIBIOS_MIN_IO 0x00001000
#ifdef CONFIG_IXP4XX_INDIRECT_PCI
-#define PCIBIOS_MIN_MEM 0x10000000 /* 1 GB of indirect PCI MMIO space */
#define PCIBIOS_MAX_MEM 0x4FFFFFFF
#else
-#define PCIBIOS_MIN_MEM 0x48000000 /* 64 MB of PCI MMIO space */
#define PCIBIOS_MAX_MEM 0x4BFFFFFF
#endif
#define ARCH_HAS_DMA_SET_COHERENT_MASK
-#define pcibios_assign_all_busses() 1
-
/* Register locations and bits */
#include "ixp4xx-regs.h"
diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h
index 34e79404671a..4caf1761f1e2 100644
--- a/arch/arm/mach-ixp4xx/include/mach/memory.h
+++ b/arch/arm/mach-ixp4xx/include/mach/memory.h
@@ -14,8 +14,4 @@
*/
#define PLAT_PHYS_OFFSET UL(0x00000000)
-#ifdef CONFIG_PCI
-#define ARM_DMA_ZONE_SIZE SZ_64M
-#endif
-
#endif
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index dca4f7f9f4f7..6a2927956bf6 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -258,6 +258,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = ixdp425_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
@@ -269,6 +272,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = ixdp425_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
@@ -280,6 +286,9 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = ixdp425_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
@@ -291,5 +300,8 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = ixdp425_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index f18fee748878..afb51879d9a4 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -319,4 +319,7 @@ MACHINE_START(NAS100D, "Iomega NAS 100d")
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.init_machine = nas100d_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index f79b62eb7614..69e40f2cf092 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -305,4 +305,7 @@ MACHINE_START(NSLU2, "Linksys NSLU2")
.init_irq = ixp4xx_init_irq,
.timer = &nslu2_timer,
.init_machine = nslu2_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c
index 4e72cfdd3c46..045336c833af 100644
--- a/arch/arm/mach-ixp4xx/vulcan-setup.c
+++ b/arch/arm/mach-ixp4xx/vulcan-setup.c
@@ -241,4 +241,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = vulcan_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
index 5d148c7bc4fb..40b9fad800b8 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -102,5 +102,8 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
.init_machine = wg302v2_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/hardware.h b/arch/arm/mach-kirkwood/include/mach/hardware.h
index cde85283f7d3..742b74f43e41 100644
--- a/arch/arm/mach-kirkwood/include/mach/hardware.h
+++ b/arch/arm/mach-kirkwood/include/mach/hardware.h
@@ -11,11 +11,4 @@
#include "kirkwood.h"
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x00001000
-#define PCIBIOS_MIN_MEM 0x01000000
-#define PCIMEM_BASE KIRKWOOD_PCIE_MEM_PHYS_BASE /* mem base for VGA */
-
-
#endif
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index ca294ff6d5be..bfeb9c900cec 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -12,6 +12,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/mbus.h>
+#include <video/vga.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <plat/pcie.h>
@@ -271,6 +272,8 @@ static void __init add_pcie_port(int index, unsigned long base)
void __init kirkwood_pcie_init(unsigned int portmask)
{
+ vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
+
if (portmask & KW_PCIE0)
add_pcie_port(0, PCIE_VIRT_BASE);
diff --git a/arch/arm/mach-ks8695/include/mach/hardware.h b/arch/arm/mach-ks8695/include/mach/hardware.h
index e0f911d9e021..5e0c388143da 100644
--- a/arch/arm/mach-ks8695/include/mach/hardware.h
+++ b/arch/arm/mach-ks8695/include/mach/hardware.h
@@ -42,13 +42,4 @@
#define KS8695_PCIIO_PA 0x80000000
#define KS8695_PCIIO_SIZE SZ_64K
-
-/*
- * PCI support
- */
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0
-#define PCIBIOS_MIN_MEM 0
-
#endif
diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c
index 5fcd082a17f9..c7c9a188d105 100644
--- a/arch/arm/mach-ks8695/pci.c
+++ b/arch/arm/mach-ks8695/pci.c
@@ -317,6 +317,9 @@ void __init ks8695_init_pci(struct ks8695_pci_cfg *cfg)
return;
}
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0;
+
printk(KERN_INFO "PCI: Initialising\n");
ks8695_show_pciregs();
diff --git a/arch/arm/mach-loki/Kconfig b/arch/arm/mach-loki/Kconfig
deleted file mode 100644
index 0045bdd761ca..000000000000
--- a/arch/arm/mach-loki/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-if ARCH_LOKI
-
-menu "Marvell Loki (88RC8480) Implementations"
-
-config MACH_LB88RC8480
- bool "Marvell LB88RC8480 Development Board"
- help
- Say 'Y' here if you want your kernel to support the
- Marvell LB88RC8480 Development Board.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-loki/Makefile b/arch/arm/mach-loki/Makefile
deleted file mode 100644
index d43233ee590f..000000000000
--- a/arch/arm/mach-loki/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-y += common.o addr-map.o irq.o
-
-obj-$(CONFIG_MACH_LB88RC8480) += lb88rc8480-setup.o
diff --git a/arch/arm/mach-loki/addr-map.c b/arch/arm/mach-loki/addr-map.c
deleted file mode 100644
index b9537c97beba..000000000000
--- a/arch/arm/mach-loki/addr-map.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * arch/arm/mach-loki/addr-map.c
- *
- * Address map functions for Marvell Loki (88RC8480) SoCs
- *
- * 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/init.h>
-#include <linux/mbus.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include "common.h"
-
-/*
- * Generic Address Decode Windows bit settings
- */
-#define TARGET_DDR 0
-#define TARGET_DEV_BUS 1
-#define TARGET_PCIE0 3
-#define TARGET_PCIE1 4
-#define ATTR_DEV_BOOT 0x0f
-#define ATTR_DEV_CS2 0x1b
-#define ATTR_DEV_CS1 0x1d
-#define ATTR_DEV_CS0 0x1e
-#define ATTR_PCIE_IO 0x51
-#define ATTR_PCIE_MEM 0x59
-
-/*
- * Helpers to get DDR bank info
- */
-#define DDR_SIZE_CS(n) DDR_REG(0x1500 + ((n) << 3))
-#define DDR_BASE_CS(n) DDR_REG(0x1504 + ((n) << 3))
-
-/*
- * CPU Address Decode Windows registers
- */
-#define BRIDGE_REG(x) (BRIDGE_VIRT_BASE | (x))
-#define CPU_WIN_CTRL(n) BRIDGE_REG(0x000 | ((n) << 4))
-#define CPU_WIN_BASE(n) BRIDGE_REG(0x004 | ((n) << 4))
-#define CPU_WIN_REMAP_LO(n) BRIDGE_REG(0x008 | ((n) << 4))
-#define CPU_WIN_REMAP_HI(n) BRIDGE_REG(0x00c | ((n) << 4))
-
-
-struct mbus_dram_target_info loki_mbus_dram_info;
-
-static void __init setup_cpu_win(int win, u32 base, u32 size,
- u8 target, u8 attr, int remap)
-{
- u32 ctrl;
-
- base &= 0xffff0000;
- ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (1 << 5) | target;
-
- writel(base, CPU_WIN_BASE(win));
- writel(ctrl, CPU_WIN_CTRL(win));
- if (win < 2) {
- if (remap < 0)
- remap = base;
-
- writel(remap & 0xffff0000, CPU_WIN_REMAP_LO(win));
- writel(0, CPU_WIN_REMAP_HI(win));
- }
-}
-
-void __init loki_setup_cpu_mbus(void)
-{
- int i;
- int cs;
-
- /*
- * First, disable and clear windows.
- */
- for (i = 0; i < 8; i++) {
- writel(0, CPU_WIN_BASE(i));
- writel(0, CPU_WIN_CTRL(i));
- if (i < 2) {
- writel(0, CPU_WIN_REMAP_LO(i));
- writel(0, CPU_WIN_REMAP_HI(i));
- }
- }
-
- /*
- * Setup windows for PCIe IO+MEM space.
- */
- setup_cpu_win(2, LOKI_PCIE0_MEM_PHYS_BASE, LOKI_PCIE0_MEM_SIZE,
- TARGET_PCIE0, ATTR_PCIE_MEM, -1);
- setup_cpu_win(3, LOKI_PCIE1_MEM_PHYS_BASE, LOKI_PCIE1_MEM_SIZE,
- TARGET_PCIE1, ATTR_PCIE_MEM, -1);
-
- /*
- * Setup MBUS dram target info.
- */
- loki_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
-
- for (i = 0, cs = 0; i < 4; i++) {
- u32 base = readl(DDR_BASE_CS(i));
- u32 size = readl(DDR_SIZE_CS(i));
-
- /*
- * Chip select enabled?
- */
- if (size & 1) {
- struct mbus_dram_window *w;
-
- w = &loki_mbus_dram_info.cs[cs++];
- w->cs_index = i;
- w->mbus_attr = 0xf & ~(1 << i);
- w->base = base & 0xffff0000;
- w->size = (size | 0x0000ffff) + 1;
- }
- }
- loki_mbus_dram_info.num_cs = cs;
-}
-
-void __init loki_setup_dev_boot_win(u32 base, u32 size)
-{
- setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
-}
diff --git a/arch/arm/mach-loki/common.c b/arch/arm/mach-loki/common.c
deleted file mode 100644
index 5f02664db812..000000000000
--- a/arch/arm/mach-loki/common.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * arch/arm/mach-loki/common.c
- *
- * Core functions for Marvell Loki (88RC8480) SoCs
- *
- * 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/mbus.h>
-#include <linux/dma-mapping.h>
-#include <asm/page.h>
-#include <asm/timex.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include <mach/bridge-regs.h>
-#include <mach/loki.h>
-#include <plat/orion_nand.h>
-#include <plat/time.h>
-#include <plat/common.h>
-#include "common.h"
-
-/*****************************************************************************
- * I/O Address Mapping
- ****************************************************************************/
-static struct map_desc loki_io_desc[] __initdata = {
- {
- .virtual = LOKI_REGS_VIRT_BASE,
- .pfn = __phys_to_pfn(LOKI_REGS_PHYS_BASE),
- .length = LOKI_REGS_SIZE,
- .type = MT_DEVICE,
- },
-};
-
-void __init loki_map_io(void)
-{
- iotable_init(loki_io_desc, ARRAY_SIZE(loki_io_desc));
-}
-
-
-/*****************************************************************************
- * GE00
- ****************************************************************************/
-void __init loki_ge0_init(struct mv643xx_eth_platform_data *eth_data)
-{
- writel(0x00079220, GE0_VIRT_BASE + 0x20b0);
-
- orion_ge00_init(eth_data, &loki_mbus_dram_info,
- GE0_PHYS_BASE, IRQ_LOKI_GBE_A_INT,
- 0, LOKI_TCLK);
-}
-
-
-/*****************************************************************************
- * GE01
- ****************************************************************************/
-void __init loki_ge1_init(struct mv643xx_eth_platform_data *eth_data)
-{
- writel(0x00079220, GE1_VIRT_BASE + 0x20b0);
-
- orion_ge01_init(eth_data, &loki_mbus_dram_info,
- GE1_PHYS_BASE, IRQ_LOKI_GBE_B_INT,
- 0, LOKI_TCLK);
-}
-
-
-/*****************************************************************************
- * SAS/SATA
- ****************************************************************************/
-static struct resource loki_sas_resources[] = {
- {
- .name = "mvsas0 mem",
- .start = SAS0_PHYS_BASE,
- .end = SAS0_PHYS_BASE + 0x01ff,
- .flags = IORESOURCE_MEM,
- }, {
- .name = "mvsas0 irq",
- .start = IRQ_LOKI_SAS_A,
- .end = IRQ_LOKI_SAS_A,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "mvsas1 mem",
- .start = SAS1_PHYS_BASE,
- .end = SAS1_PHYS_BASE + 0x01ff,
- .flags = IORESOURCE_MEM,
- }, {
- .name = "mvsas1 irq",
- .start = IRQ_LOKI_SAS_B,
- .end = IRQ_LOKI_SAS_B,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device loki_sas = {
- .name = "mvsas",
- .id = 0,
- .dev = {
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
- .num_resources = ARRAY_SIZE(loki_sas_resources),
- .resource = loki_sas_resources,
-};
-
-void __init loki_sas_init(void)
-{
- writel(0x8300f707, DDR_REG(0x1424));
- platform_device_register(&loki_sas);
-}
-
-
-/*****************************************************************************
- * UART0
- ****************************************************************************/
-void __init loki_uart0_init(void)
-{
- orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
- IRQ_LOKI_UART0, LOKI_TCLK);
-}
-
-/*****************************************************************************
- * UART1
- ****************************************************************************/
-void __init loki_uart1_init(void)
-{
- orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
- IRQ_LOKI_UART1, LOKI_TCLK);
-}
-
-
-/*****************************************************************************
- * Time handling
- ****************************************************************************/
-void __init loki_init_early(void)
-{
- orion_time_set_base(TIMER_VIRT_BASE);
-}
-
-static void loki_timer_init(void)
-{
- orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
- IRQ_LOKI_BRIDGE, LOKI_TCLK);
-}
-
-struct sys_timer loki_timer = {
- .init = loki_timer_init,
-};
-
-
-/*****************************************************************************
- * General
- ****************************************************************************/
-void __init loki_init(void)
-{
- printk(KERN_INFO "Loki ID: 88RC8480. TCLK=%d.\n", LOKI_TCLK);
-
- loki_setup_cpu_mbus();
-}
diff --git a/arch/arm/mach-loki/common.h b/arch/arm/mach-loki/common.h
deleted file mode 100644
index a315dcf8887c..000000000000
--- a/arch/arm/mach-loki/common.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * arch/arm/mach-loki/common.h
- *
- * Core functions for Marvell Loki (88RC8480) SoCs
- *
- * 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 __ARCH_LOKI_COMMON_H
-#define __ARCH_LOKI_COMMON_H
-
-struct mv643xx_eth_platform_data;
-
-/*
- * Basic Loki init functions used early by machine-setup.
- */
-void loki_map_io(void);
-void loki_init(void);
-void loki_init_early(void);
-void loki_init_irq(void);
-
-extern struct mbus_dram_target_info loki_mbus_dram_info;
-void loki_setup_cpu_mbus(void);
-void loki_setup_dev_boot_win(u32 base, u32 size);
-
-void loki_ge0_init(struct mv643xx_eth_platform_data *eth_data);
-void loki_ge1_init(struct mv643xx_eth_platform_data *eth_data);
-void loki_sas_init(void);
-void loki_uart0_init(void);
-void loki_uart1_init(void);
-
-extern struct sys_timer loki_timer;
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/bridge-regs.h b/arch/arm/mach-loki/include/mach/bridge-regs.h
deleted file mode 100644
index fd87732097cd..000000000000
--- a/arch/arm/mach-loki/include/mach/bridge-regs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/bridge-regs.h
- *
- * 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_BRIDGE_REGS_H
-#define __ASM_ARCH_BRIDGE_REGS_H
-
-#include <mach/loki.h>
-
-#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108)
-#define SOFT_RESET_OUT_EN 0x00000004
-
-#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c)
-#define SOFT_RESET 0x00000001
-
-#define BRIDGE_INT_TIMER1_CLR 0x0004
-
-#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200)
-#define IRQ_CAUSE_OFF 0x0000
-#define IRQ_MASK_OFF 0x0004
-
-#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300)
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/debug-macro.S b/arch/arm/mach-loki/include/mach/debug-macro.S
deleted file mode 100644
index cc90d99ac76c..000000000000
--- a/arch/arm/mach-loki/include/mach/debug-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/debug-macro.S
- *
- * 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/loki.h>
-
- .macro addruart, rp, rv
- ldr \rp, =LOKI_REGS_PHYS_BASE
- ldr \rv, =LOKI_REGS_VIRT_BASE
- orr \rp, \rp, #0x00012000
- orr \rv, \rv, #0x00012000
- .endm
-
-#define UART_SHIFT 2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-loki/include/mach/entry-macro.S b/arch/arm/mach-loki/include/mach/entry-macro.S
deleted file mode 100644
index bc917ed3a62d..000000000000
--- a/arch/arm/mach-loki/include/mach/entry-macro.S
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Marvell Loki (88RC8480) 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/bridge-regs.h>
-
- .macro disable_fiq
- .endm
-
- .macro arch_ret_to_user, tmp1, tmp2
- .endm
-
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =IRQ_VIRT_BASE
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqstat, [\base, #IRQ_CAUSE_OFF]
- ldr \tmp, [\base, #IRQ_MASK_OFF]
- mov \irqnr, #0
- ands \irqstat, \irqstat, \tmp
- clzne \irqnr, \irqstat
- rsbne \irqnr, \irqnr, #31
- .endm
diff --git a/arch/arm/mach-loki/include/mach/hardware.h b/arch/arm/mach-loki/include/mach/hardware.h
deleted file mode 100644
index d7bfc8f17729..000000000000
--- a/arch/arm/mach-loki/include/mach/hardware.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/hardware.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_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include "loki.h"
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/io.h b/arch/arm/mach-loki/include/mach/io.h
deleted file mode 100644
index a373cd582c84..000000000000
--- a/arch/arm/mach-loki/include/mach/io.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/io.h
- *
- * 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_IO_H
-#define __ASM_ARCH_IO_H
-
-#include "loki.h"
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-static inline void __iomem *__io(unsigned long addr)
-{
- return (void __iomem *)((addr - LOKI_PCIE0_IO_PHYS_BASE)
- + LOKI_PCIE0_IO_VIRT_BASE);
-}
-
-#define __io(a) __io(a)
-#define __mem_pci(a) (a)
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/irqs.h b/arch/arm/mach-loki/include/mach/irqs.h
deleted file mode 100644
index 9fbd3326867b..000000000000
--- a/arch/arm/mach-loki/include/mach/irqs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/irqs.h
- *
- * IRQ definitions for Marvell Loki (88RC8480) SoCs
- *
- * 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_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#include "loki.h" /* need GPIO_MAX */
-
-/*
- * Interrupt Controller
- */
-#define IRQ_LOKI_PCIE_A_CPU_DRBL 0
-#define IRQ_LOKI_CPU_PCIE_A_DRBL 1
-#define IRQ_LOKI_PCIE_B_CPU_DRBL 2
-#define IRQ_LOKI_CPU_PCIE_B_DRBL 3
-#define IRQ_LOKI_COM_A_ERR 6
-#define IRQ_LOKI_COM_A_IN 7
-#define IRQ_LOKI_COM_A_OUT 8
-#define IRQ_LOKI_COM_B_ERR 9
-#define IRQ_LOKI_COM_B_IN 10
-#define IRQ_LOKI_COM_B_OUT 11
-#define IRQ_LOKI_DMA_A 12
-#define IRQ_LOKI_DMA_B 13
-#define IRQ_LOKI_SAS_A 14
-#define IRQ_LOKI_SAS_B 15
-#define IRQ_LOKI_DDR 16
-#define IRQ_LOKI_XOR 17
-#define IRQ_LOKI_BRIDGE 18
-#define IRQ_LOKI_PCIE_A_ERR 20
-#define IRQ_LOKI_PCIE_A_INT 21
-#define IRQ_LOKI_PCIE_B_ERR 22
-#define IRQ_LOKI_PCIE_B_INT 23
-#define IRQ_LOKI_GBE_A_INT 24
-#define IRQ_LOKI_GBE_B_INT 25
-#define IRQ_LOKI_DEV_ERR 26
-#define IRQ_LOKI_UART0 27
-#define IRQ_LOKI_UART1 28
-#define IRQ_LOKI_TWSI 29
-#define IRQ_LOKI_GPIO_23_0 30
-#define IRQ_LOKI_GPIO_25_24 31
-
-/*
- * Loki General Purpose Pins
- */
-#define IRQ_LOKI_GPIO_START 32
-#define NR_GPIO_IRQS GPIO_MAX
-
-#define NR_IRQS (IRQ_LOKI_GPIO_START + NR_GPIO_IRQS)
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/loki.h b/arch/arm/mach-loki/include/mach/loki.h
deleted file mode 100644
index bfca7c265f43..000000000000
--- a/arch/arm/mach-loki/include/mach/loki.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/loki.h
- *
- * Generic definitions for Marvell Loki (88RC8480) SoC flavors
- *
- * 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_LOKI_H
-#define __ASM_ARCH_LOKI_H
-
-/*
- * Marvell Loki (88RC8480) address maps.
- *
- * phys
- * d0000000 on-chip peripheral registers
- * e0000000 PCIe 0 Memory space
- * e8000000 PCIe 1 Memory space
- * f0000000 PCIe 0 I/O space
- * f0100000 PCIe 1 I/O space
- *
- * virt phys size
- * fed00000 d0000000 1M on-chip peripheral registers
- * fee00000 f0000000 64K PCIe 0 I/O space
- * fef00000 f0100000 64K PCIe 1 I/O space
- */
-
-#define LOKI_REGS_PHYS_BASE 0xd0000000
-#define LOKI_REGS_VIRT_BASE 0xfed00000
-#define LOKI_REGS_SIZE SZ_1M
-
-#define LOKI_PCIE0_IO_PHYS_BASE 0xf0000000
-#define LOKI_PCIE0_IO_VIRT_BASE 0xfee00000
-#define LOKI_PCIE0_IO_BUS_BASE 0x00000000
-#define LOKI_PCIE0_IO_SIZE SZ_64K
-
-#define LOKI_PCIE1_IO_PHYS_BASE 0xf0100000
-#define LOKI_PCIE1_IO_VIRT_BASE 0xfef00000
-#define LOKI_PCIE1_IO_BUS_BASE 0x00000000
-#define LOKI_PCIE1_IO_SIZE SZ_64K
-
-#define LOKI_PCIE0_MEM_PHYS_BASE 0xe0000000
-#define LOKI_PCIE0_MEM_SIZE SZ_128M
-
-#define LOKI_PCIE1_MEM_PHYS_BASE 0xe8000000
-#define LOKI_PCIE1_MEM_SIZE SZ_128M
-
-/*
- * Register Map
- */
-#define DEV_BUS_PHYS_BASE (LOKI_REGS_PHYS_BASE | 0x10000)
-#define DEV_BUS_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0x10000)
-#define UART0_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x2000)
-#define UART0_VIRT_BASE (DEV_BUS_VIRT_BASE | 0x2000)
-#define UART1_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x2100)
-#define UART1_VIRT_BASE (DEV_BUS_VIRT_BASE | 0x2100)
-
-#define BRIDGE_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0x20000)
-
-#define PCIE0_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0x30000)
-
-#define PCIE1_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0x40000)
-
-#define SAS0_PHYS_BASE (LOKI_REGS_PHYS_BASE | 0x80000)
-
-#define SAS1_PHYS_BASE (LOKI_REGS_PHYS_BASE | 0x90000)
-
-#define GE0_PHYS_BASE (LOKI_REGS_PHYS_BASE | 0xa0000)
-#define GE0_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0xa0000)
-
-#define GE1_PHYS_BASE (LOKI_REGS_PHYS_BASE | 0xb0000)
-#define GE1_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0xb0000)
-
-#define DDR_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0xf0000)
-#define DDR_REG(x) (DDR_VIRT_BASE | (x))
-
-
-#define GPIO_MAX 8
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/memory.h b/arch/arm/mach-loki/include/mach/memory.h
deleted file mode 100644
index 66366657a875..000000000000
--- a/arch/arm/mach-loki/include/mach/memory.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-loki/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-loki/include/mach/system.h b/arch/arm/mach-loki/include/mach/system.h
deleted file mode 100644
index 71895199a534..000000000000
--- a/arch/arm/mach-loki/include/mach/system.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/system.h
- *
- * 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_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-#include <mach/bridge-regs.h>
-
-static inline void arch_idle(void)
-{
- cpu_do_idle();
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
- /*
- * Enable soft reset to assert RSTOUTn.
- */
- writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
-
- /*
- * Assert soft reset.
- */
- writel(SOFT_RESET, SYSTEM_SOFT_RESET);
-
- while (1)
- ;
-}
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/timex.h b/arch/arm/mach-loki/include/mach/timex.h
deleted file mode 100644
index 9df210915297..000000000000
--- a/arch/arm/mach-loki/include/mach/timex.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/timex.h
- *
- * 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.
- */
-
-#define CLOCK_TICK_RATE (100 * HZ)
-
-#define LOKI_TCLK 180000000
diff --git a/arch/arm/mach-loki/include/mach/uncompress.h b/arch/arm/mach-loki/include/mach/uncompress.h
deleted file mode 100644
index 90b2a7e65da3..000000000000
--- a/arch/arm/mach-loki/include/mach/uncompress.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/uncompress.h
- *
- * 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/serial_reg.h>
-#include <mach/loki.h>
-
-#define SERIAL_BASE ((unsigned char *)UART0_PHYS_BASE)
-
-static void putc(const char c)
-{
- unsigned char *base = SERIAL_BASE;
- int i;
-
- for (i = 0; i < 0x1000; i++) {
- if (base[UART_LSR << 2] & UART_LSR_THRE)
- break;
- barrier();
- }
-
- base[UART_TX << 2] = c;
-}
-
-static void flush(void)
-{
- unsigned char *base = SERIAL_BASE;
- unsigned char mask;
- int i;
-
- mask = UART_LSR_TEMT | UART_LSR_THRE;
-
- for (i = 0; i < 0x1000; i++) {
- if ((base[UART_LSR << 2] & mask) == mask)
- break;
- barrier();
- }
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-loki/include/mach/vmalloc.h b/arch/arm/mach-loki/include/mach/vmalloc.h
deleted file mode 100644
index 5dcbd865443f..000000000000
--- a/arch/arm/mach-loki/include/mach/vmalloc.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/vmalloc.h
- */
-
-#define VMALLOC_END 0xfe800000UL
diff --git a/arch/arm/mach-loki/irq.c b/arch/arm/mach-loki/irq.c
deleted file mode 100644
index 76b211bfcca2..000000000000
--- a/arch/arm/mach-loki/irq.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-loki/irq.c
- *
- * Marvell Loki (88RC8480) IRQ handling.
- *
- * 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/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <mach/bridge-regs.h>
-#include <plat/irq.h>
-#include "common.h"
-
-void __init loki_init_irq(void)
-{
- orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_OFF));
-}
diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c
deleted file mode 100644
index 35eae4e6abb2..000000000000
--- a/arch/arm/mach-loki/lb88rc8480-setup.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * arch/arm/mach-loki/lb88rc8480-setup.c
- *
- * Marvell LB88RC8480 Development Board Setup
- *
- * 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
-#include <linux/timer.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/loki.h>
-#include "common.h"
-
-#define LB88RC8480_FLASH_BOOT_CS_BASE 0xf8000000
-#define LB88RC8480_FLASH_BOOT_CS_SIZE SZ_128M
-
-#define LB88RC8480_NOR_BOOT_BASE 0xff000000
-#define LB88RC8480_NOR_BOOT_SIZE SZ_16M
-
-static struct mtd_partition lb88rc8480_boot_flash_parts[] = {
- {
- .name = "kernel",
- .offset = 0,
- .size = SZ_2M,
- }, {
- .name = "root-fs",
- .offset = SZ_2M,
- .size = (SZ_8M + SZ_4M + SZ_1M),
- }, {
- .name = "u-boot",
- .offset = (SZ_8M + SZ_4M + SZ_2M + SZ_1M),
- .size = SZ_1M,
- },
-};
-
-static struct physmap_flash_data lb88rc8480_boot_flash_data = {
- .parts = lb88rc8480_boot_flash_parts,
- .nr_parts = ARRAY_SIZE(lb88rc8480_boot_flash_parts),
- .width = 1, /* 8 bit bus width */
-};
-
-static struct resource lb88rc8480_boot_flash_resource = {
- .flags = IORESOURCE_MEM,
- .start = LB88RC8480_NOR_BOOT_BASE,
- .end = LB88RC8480_NOR_BOOT_BASE + LB88RC8480_NOR_BOOT_SIZE - 1,
-};
-
-static struct platform_device lb88rc8480_boot_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &lb88rc8480_boot_flash_data,
- },
- .num_resources = 1,
- .resource = &lb88rc8480_boot_flash_resource,
-};
-
-static struct mv643xx_eth_platform_data lb88rc8480_ge0_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(1),
- .mac_addr = { 0x00, 0x50, 0x43, 0x11, 0x22, 0x33 },
-};
-
-static void __init lb88rc8480_init(void)
-{
- /*
- * Basic setup. Needs to be called early.
- */
- loki_init();
-
- loki_ge0_init(&lb88rc8480_ge0_data);
- loki_sas_init();
- loki_uart0_init();
- loki_uart1_init();
-
- loki_setup_dev_boot_win(LB88RC8480_FLASH_BOOT_CS_BASE,
- LB88RC8480_FLASH_BOOT_CS_SIZE);
- platform_device_register(&lb88rc8480_boot_flash);
-}
-
-MACHINE_START(LB88RC8480, "Marvell LB88RC8480 Development Board")
- /* Maintainer: Ke Wei <kewei@marvell.com> */
- .boot_params = 0x00000100,
- .init_machine = lb88rc8480_init,
- .map_io = loki_map_io,
- .init_early = loki_init_early,
- .init_irq = loki_init_irq,
- .timer = &loki_timer,
-MACHINE_END
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
index da0e6498110a..1e027514096d 100644
--- a/arch/arm/mach-lpc32xx/clock.c
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -1077,7 +1077,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
_REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0)
_REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1)
- _REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc)
+ _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc)
_REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc)
_REGISTER_CLOCK("lpc-net.0", NULL, clk_net)
_REGISTER_CLOCK("dev:clcd", NULL, clk_lcd)
diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c
index ee24dc28e93e..205b2dbb565b 100644
--- a/arch/arm/mach-lpc32xx/common.c
+++ b/arch/arm/mach-lpc32xx/common.c
@@ -95,6 +95,48 @@ struct platform_device lpc32xx_i2c2_device = {
},
};
+/* TSC (Touch Screen Controller) */
+
+static struct resource lpc32xx_tsc_resources[] = {
+ {
+ .start = LPC32XX_ADC_BASE,
+ .end = LPC32XX_ADC_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_LPC32XX_TS_IRQ,
+ .end = IRQ_LPC32XX_TS_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device lpc32xx_tsc_device = {
+ .name = "ts-lpc32xx",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(lpc32xx_tsc_resources),
+ .resource = lpc32xx_tsc_resources,
+};
+
+/* RTC */
+
+static struct resource lpc32xx_rtc_resources[] = {
+ {
+ .start = LPC32XX_RTC_BASE,
+ .end = LPC32XX_RTC_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },{
+ .start = IRQ_LPC32XX_RTC,
+ .end = IRQ_LPC32XX_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device lpc32xx_rtc_device = {
+ .name = "rtc-lpc32xx",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(lpc32xx_rtc_resources),
+ .resource = lpc32xx_rtc_resources,
+};
+
/*
* Returns the unique ID for the device
*/
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
index f82211fd80c1..5583f52662bd 100644
--- a/arch/arm/mach-lpc32xx/common.h
+++ b/arch/arm/mach-lpc32xx/common.h
@@ -28,6 +28,8 @@ extern struct platform_device lpc32xx_watchdog_device;
extern struct platform_device lpc32xx_i2c0_device;
extern struct platform_device lpc32xx_i2c1_device;
extern struct platform_device lpc32xx_i2c2_device;
+extern struct platform_device lpc32xx_tsc_device;
+extern struct platform_device lpc32xx_rtc_device;
/*
* Other arch specific structures and functions
diff --git a/arch/arm/mach-lpc32xx/include/mach/clkdev.h b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
deleted file mode 100644
index 9bf0637e29ce..000000000000
--- a/arch/arm/mach-lpc32xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/clkdev.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_CLKDEV_H
-#define __ASM_ARCH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
index 870227c96602..b725f6c93975 100644
--- a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
+++ b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
@@ -41,7 +41,3 @@
rsb \irqnr, \irqnr, #31
teq \irqstat, #0
.endm
-
- .macro irq_prio_table
- .endm
-
diff --git a/arch/arm/mach-lpc32xx/include/mach/vmalloc.h b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
index d1d936c7236d..720fa43a60bf 100644
--- a/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
+++ b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
@@ -19,6 +19,6 @@
#ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H
-#define VMALLOC_END 0xF0000000
+#define VMALLOC_END 0xF0000000UL
#endif
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 67793a690272..56ef5f6c8116 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -77,6 +77,13 @@ config MACH_TETON_BGA
Say 'Y' here if you want to support the Marvell PXA168-based
Teton BGA Development Board.
+config MACH_SHEEVAD
+ bool "Marvell's PXA168 GuruPlug Display (gplugD) Board"
+ select CPU_PXA168
+ help
+ Say 'Y' here if you want to support the Marvell PXA168-based
+ GuruPlug Display (gplugD) Board
+
endmenu
config CPU_PXA168
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 5c68382141af..b0ac942327aa 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -19,3 +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
diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
index 7bb78fd5a2a6..c79162a50f28 100644
--- a/arch/arm/mach-mmp/brownstone.c
+++ b/arch/arm/mach-mmp/brownstone.c
@@ -177,9 +177,16 @@ static struct i2c_board_info brownstone_twsi1_info[] = {
};
static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
- .max_speed = 25000000,
+ .clk_delay_cycles = 0x1f,
};
+static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc2 = {
+ .clk_delay_cycles = 0x1f,
+ .flags = PXA_FLAG_CARD_PERMANENT
+ | PXA_FLAG_SD_8_BIT_CAPABLE_SLOT,
+};
+
+
static void __init brownstone_init(void)
{
mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
@@ -189,6 +196,7 @@ static void __init brownstone_init(void)
mmp2_add_uart(3);
mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
+ mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */
/* enable 5v regulator */
platform_device_register(&brownstone_v_5vp_device);
diff --git a/arch/arm/mach-mmp/clock.c b/arch/arm/mach-mmp/clock.c
index 886e05648f08..7c6f95f29142 100644
--- a/arch/arm/mach-mmp/clock.c
+++ b/arch/arm/mach-mmp/clock.c
@@ -88,3 +88,18 @@ unsigned long clk_get_rate(struct clk *clk)
return rate;
}
EXPORT_SYMBOL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (clk->ops->setrate) {
+ spin_lock_irqsave(&clocks_lock, flags);
+ ret = clk->ops->setrate(clk, rate);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h
index 9b027d7491f5..3143e994e672 100644
--- a/arch/arm/mach-mmp/clock.h
+++ b/arch/arm/mach-mmp/clock.h
@@ -12,6 +12,7 @@ struct clkops {
void (*enable)(struct clk *);
void (*disable)(struct clk *);
unsigned long (*getrate)(struct clk *);
+ int (*setrate)(struct clk *, unsigned long);
};
struct clk {
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
new file mode 100644
index 000000000000..c070c24255f4
--- /dev/null
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -0,0 +1,189 @@
+/*
+ * linux/arch/arm/mach-mmp/gplugd.c
+ *
+ * Support for the Marvell PXA168-based GuruPlug Display (gplugD) 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
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/gpio.h>
+#include <mach/pxa168.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/mfp-gplugd.h>
+
+#include "common.h"
+
+static unsigned long gplugd_pin_config[] __initdata = {
+ /* UART3 */
+ GPIO8_UART3_SOUT,
+ GPIO9_UART3_SIN,
+ GPI1O_UART3_CTS,
+ GPI11_UART3_RTS,
+
+ /* MMC2 */
+ GPIO28_MMC2_CMD,
+ GPIO29_MMC2_CLK,
+ GPIO30_MMC2_DAT0,
+ GPIO31_MMC2_DAT1,
+ GPIO32_MMC2_DAT2,
+ GPIO33_MMC2_DAT3,
+
+ /* LCD & HDMI clock selection GPIO: 0: 74.176MHz, 1: 74.25 MHz */
+ GPIO35_GPIO,
+ GPIO36_GPIO, /* CEC Interrupt */
+
+ /* MMC1 */
+ GPIO43_MMC1_CLK,
+ GPIO49_MMC1_CMD,
+ GPIO41_MMC1_DAT0,
+ GPIO40_MMC1_DAT1,
+ GPIO52_MMC1_DAT2,
+ GPIO51_MMC1_DAT3,
+ GPIO53_MMC1_CD,
+
+ /* LCD */
+ GPIO56_LCD_FCLK_RD,
+ GPIO57_LCD_LCLK_A0,
+ GPIO58_LCD_PCLK_WR,
+ GPIO59_LCD_DENA_BIAS,
+ GPIO60_LCD_DD0,
+ GPIO61_LCD_DD1,
+ GPIO62_LCD_DD2,
+ GPIO63_LCD_DD3,
+ GPIO64_LCD_DD4,
+ GPIO65_LCD_DD5,
+ GPIO66_LCD_DD6,
+ GPIO67_LCD_DD7,
+ GPIO68_LCD_DD8,
+ GPIO69_LCD_DD9,
+ GPIO70_LCD_DD10,
+ GPIO71_LCD_DD11,
+ GPIO72_LCD_DD12,
+ GPIO73_LCD_DD13,
+ GPIO74_LCD_DD14,
+ GPIO75_LCD_DD15,
+ GPIO76_LCD_DD16,
+ GPIO77_LCD_DD17,
+ GPIO78_LCD_DD18,
+ GPIO79_LCD_DD19,
+ GPIO80_LCD_DD20,
+ GPIO81_LCD_DD21,
+ GPIO82_LCD_DD22,
+ GPIO83_LCD_DD23,
+
+ /* GPIO */
+ GPIO84_GPIO,
+ GPIO85_GPIO,
+
+ /* Fast-Ethernet*/
+ GPIO86_TX_CLK,
+ GPIO87_TX_EN,
+ GPIO88_TX_DQ3,
+ GPIO89_TX_DQ2,
+ GPIO90_TX_DQ1,
+ GPIO91_TX_DQ0,
+ GPIO92_MII_CRS,
+ GPIO93_MII_COL,
+ GPIO94_RX_CLK,
+ GPIO95_RX_ER,
+ GPIO96_RX_DQ3,
+ GPIO97_RX_DQ2,
+ GPIO98_RX_DQ1,
+ GPIO99_RX_DQ0,
+ GPIO100_MII_MDC,
+ GPIO101_MII_MDIO,
+ GPIO103_RX_DV,
+ GPIO104_GPIO, /* Reset PHY */
+
+ /* RTC interrupt */
+ GPIO102_GPIO,
+
+ /* I2C */
+ GPIO105_CI2C_SDA,
+ GPIO106_CI2C_SCL,
+
+ /* Select JTAG */
+ GPIO109_GPIO,
+
+ /* I2S */
+ GPIO114_I2S_FRM,
+ GPIO115_I2S_BCLK,
+ GPIO116_I2S_TXD
+};
+
+static struct i2c_board_info gplugd_i2c_board_info[] = {
+ {
+ .type = "isl1208",
+ .addr = 0x6F,
+ }
+};
+
+/* Bring PHY out of reset by setting GPIO 104 */
+static int gplugd_eth_init(void)
+{
+ if (unlikely(gpio_request(104, "ETH_RESET_N"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 104 to bring Ethernet "
+ "PHY out of reset\n");
+ return -EIO;
+ }
+
+ gpio_direction_output(104, 1);
+ gpio_free(104);
+ return 0;
+}
+
+struct pxa168_eth_platform_data gplugd_eth_platform_data = {
+ .port_number = 0,
+ .phy_addr = 0,
+ .speed = 0, /* Autonagotiation */
+ .init = gplugd_eth_init,
+};
+
+static void __init select_disp_freq(void)
+{
+ /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */
+ if (unlikely(gpio_request(35, "DISP_FREQ_SEL"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 35 to select display "
+ "frequency\n");
+ } else {
+ gpio_direction_output(35, 1);
+ gpio_free(104);
+ }
+
+ if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 85 to select display "
+ "frequency\n");
+ } else {
+ gpio_direction_output(85, 0);
+ gpio_free(104);
+ }
+}
+
+static void __init gplugd_init(void)
+{
+ mfp_config(ARRAY_AND_SIZE(gplugd_pin_config));
+
+ select_disp_freq();
+
+ /* on-chip devices */
+ pxa168_add_uart(3);
+ pxa168_add_ssp(0);
+ pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
+
+ pxa168_add_eth(&gplugd_eth_platform_data);
+}
+
+MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform")
+ .map_io = mmp_map_io,
+ .nr_irqs = IRQ_BOARD_START,
+ .init_irq = pxa168_init_irq,
+ .timer = &pxa168_timer,
+ .init_machine = gplugd_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/clkdev.h b/arch/arm/mach-mmp/include/mach/clkdev.h
deleted file mode 100644
index 2fb354e54e0d..000000000000
--- a/arch/arm/mach-mmp/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif /* __ASM_MACH_CLKDEV_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
new file mode 100644
index 000000000000..b8cf38d85600
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
+ *
+ * MFP definitions used in gplugD
+ *
+ * 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_MFP_GPLUGD_H
+#define __MACH_MFP_GPLUGD_H
+
+#include <plat/mfp.h>
+#include <mach/mfp.h>
+
+/* UART3 */
+#define GPIO8_UART3_SOUT MFP_CFG(GPIO8, AF2)
+#define GPIO9_UART3_SIN MFP_CFG(GPIO9, AF2)
+#define GPI1O_UART3_CTS MFP_CFG(GPIO10, AF2)
+#define GPI11_UART3_RTS MFP_CFG(GPIO11, AF2)
+
+/* MMC2 */
+#define GPIO28_MMC2_CMD MFP_CFG_DRV(GPIO28, AF6, FAST)
+#define GPIO29_MMC2_CLK MFP_CFG_DRV(GPIO29, AF6, FAST)
+#define GPIO30_MMC2_DAT0 MFP_CFG_DRV(GPIO30, AF6, FAST)
+#define GPIO31_MMC2_DAT1 MFP_CFG_DRV(GPIO31, AF6, FAST)
+#define GPIO32_MMC2_DAT2 MFP_CFG_DRV(GPIO32, AF6, FAST)
+#define GPIO33_MMC2_DAT3 MFP_CFG_DRV(GPIO33, AF6, FAST)
+
+/* I2S */
+#undef GPIO114_I2S_FRM
+#undef GPIO115_I2S_BCLK
+
+#define GPIO114_I2S_FRM MFP_CFG_DRV(GPIO114, AF1, FAST)
+#define GPIO115_I2S_BCLK MFP_CFG_DRV(GPIO115, AF1, FAST)
+#define GPIO116_I2S_TXD MFP_CFG_DRV(GPIO116, AF1, FAST)
+
+/* MMC4 */
+#define GPIO125_MMC4_DAT3 MFP_CFG_DRV(GPIO125, AF7, FAST)
+#define GPIO126_MMC4_DAT2 MFP_CFG_DRV(GPIO126, AF7, FAST)
+#define GPIO127_MMC4_DAT1 MFP_CFG_DRV(GPIO127, AF7, FAST)
+#define GPIO0_2_MMC4_DAT0 MFP_CFG_DRV(GPIO0_2, AF7, FAST)
+#define GPIO1_2_MMC4_CMD MFP_CFG_DRV(GPIO1_2, AF7, FAST)
+#define GPIO2_2_MMC4_CLK MFP_CFG_DRV(GPIO2_2, AF7, FAST)
+
+/* OTG GPIO */
+#define GPIO_USB_OTG_PEN 18
+#define GPIO_USB_OIDIR 20
+
+/* Other GPIOs are 35, 84, 85 */
+#endif /* __MACH_MFP_GPLUGD_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index 713be155a44d..8c782328b21c 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -305,4 +305,23 @@
#define GPIO112_KP_MKOUT6 MFP_CFG(GPIO112, AF7)
#define GPIO121_KP_MKIN4 MFP_CFG(GPIO121, AF7)
+/* Fast Ethernet */
+#define GPIO86_TX_CLK MFP_CFG(GPIO86, AF5)
+#define GPIO87_TX_EN MFP_CFG(GPIO87, AF5)
+#define GPIO88_TX_DQ3 MFP_CFG(GPIO88, AF5)
+#define GPIO89_TX_DQ2 MFP_CFG(GPIO89, AF5)
+#define GPIO90_TX_DQ1 MFP_CFG(GPIO90, AF5)
+#define GPIO91_TX_DQ0 MFP_CFG(GPIO91, AF5)
+#define GPIO92_MII_CRS MFP_CFG(GPIO92, AF5)
+#define GPIO93_MII_COL MFP_CFG(GPIO93, AF5)
+#define GPIO94_RX_CLK MFP_CFG(GPIO94, AF5)
+#define GPIO95_RX_ER MFP_CFG(GPIO95, AF5)
+#define GPIO96_RX_DQ3 MFP_CFG(GPIO96, AF5)
+#define GPIO97_RX_DQ2 MFP_CFG(GPIO97, AF5)
+#define GPIO98_RX_DQ1 MFP_CFG(GPIO98, AF5)
+#define GPIO99_RX_DQ0 MFP_CFG(GPIO99, AF5)
+#define GPIO100_MII_MDC MFP_CFG(GPIO100, AF5)
+#define GPIO101_MII_MDIO MFP_CFG(GPIO101, AF5)
+#define GPIO103_RX_DV MFP_CFG(GPIO103, AF5)
+
#endif /* __ASM_MACH_MFP_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h
index 2cbf6df09b82..de7b88826ad7 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -1,7 +1,7 @@
#ifndef __ASM_MACH_MMP2_H
#define __ASM_MACH_MMP2_H
-#include <plat/sdhci.h>
+#include <linux/platform_data/pxa_sdhci.h>
struct sys_timer;
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index a52b3d2f325c..7f005843a707 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -14,9 +14,11 @@ extern void pxa168_clear_keypad_wakeup(void);
#include <video/pxa168fb.h>
#include <plat/pxa27x_keypad.h>
#include <mach/cputype.h>
+#include <linux/pxa168_eth.h>
extern struct pxa_device_desc pxa168_device_uart1;
extern struct pxa_device_desc pxa168_device_uart2;
+extern struct pxa_device_desc pxa168_device_uart3;
extern struct pxa_device_desc pxa168_device_twsi0;
extern struct pxa_device_desc pxa168_device_twsi1;
extern struct pxa_device_desc pxa168_device_pwm1;
@@ -31,6 +33,7 @@ extern struct pxa_device_desc pxa168_device_ssp5;
extern struct pxa_device_desc pxa168_device_nand;
extern struct pxa_device_desc pxa168_device_fb;
extern struct pxa_device_desc pxa168_device_keypad;
+extern struct pxa_device_desc pxa168_device_eth;
static inline int pxa168_add_uart(int id)
{
@@ -39,6 +42,7 @@ static inline int pxa168_add_uart(int id)
switch (id) {
case 1: d = &pxa168_device_uart1; break;
case 2: d = &pxa168_device_uart2; break;
+ case 3: d = &pxa168_device_uart3; break;
}
if (d == NULL)
@@ -117,4 +121,8 @@ static inline int pxa168_add_keypad(struct pxa27x_keypad_platform_data *data)
return pxa_register_device(&pxa168_device_keypad, data, sizeof(*data));
}
+static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data)
+{
+ return pxa_register_device(&pxa168_device_eth, data, sizeof(*data));
+}
#endif /* __ASM_MACH_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
index f7011ef70bf5..8447ac63e28f 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -29,6 +29,7 @@
#define APMU_BUS APMU_REG(0x06c)
#define APMU_SDH2 APMU_REG(0x0e8)
#define APMU_SDH3 APMU_REG(0x0ec)
+#define APMU_ETH APMU_REG(0x0fc)
#define APMU_FNCLK_EN (1 << 4)
#define APMU_AXICLK_EN (1 << 3)
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index 24172a0aad59..5d6421d63254 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -154,7 +154,7 @@ static struct i2c_board_info jasper_twsi1_info[] = {
};
static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
- .max_speed = 25000000,
+ .clk_delay_cycles = 0x1f,
};
static void __init jasper_init(void)
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 8e6c3ac7f7c1..079c18861d5c 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -168,10 +168,10 @@ static struct clk_lookup mmp2_clkregs[] = {
INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
- INIT_CLKREG(&clk_sdh0, "sdhci-pxa.0", "PXA-SDHCLK"),
- INIT_CLKREG(&clk_sdh1, "sdhci-pxa.1", "PXA-SDHCLK"),
- INIT_CLKREG(&clk_sdh2, "sdhci-pxa.2", "PXA-SDHCLK"),
- INIT_CLKREG(&clk_sdh3, "sdhci-pxa.3", "PXA-SDHCLK"),
+ INIT_CLKREG(&clk_sdh0, "sdhci-pxav3.0", "PXA-SDHCLK"),
+ INIT_CLKREG(&clk_sdh1, "sdhci-pxav3.1", "PXA-SDHCLK"),
+ INIT_CLKREG(&clk_sdh2, "sdhci-pxav3.2", "PXA-SDHCLK"),
+ INIT_CLKREG(&clk_sdh3, "sdhci-pxav3.3", "PXA-SDHCLK"),
};
static int __init mmp2_init(void)
@@ -222,8 +222,8 @@ MMP2_DEVICE(twsi4, "pxa2xx-i2c", 3, TWSI4, 0xd4033000, 0x70);
MMP2_DEVICE(twsi5, "pxa2xx-i2c", 4, TWSI5, 0xd4033800, 0x70);
MMP2_DEVICE(twsi6, "pxa2xx-i2c", 5, TWSI6, 0xd4034000, 0x70);
MMP2_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x100, 28, 29);
-MMP2_DEVICE(sdh0, "sdhci-pxa", 0, MMC, 0xd4280000, 0x120);
-MMP2_DEVICE(sdh1, "sdhci-pxa", 1, MMC2, 0xd4280800, 0x120);
-MMP2_DEVICE(sdh2, "sdhci-pxa", 2, MMC3, 0xd4281000, 0x120);
-MMP2_DEVICE(sdh3, "sdhci-pxa", 3, MMC4, 0xd4281800, 0x120);
+MMP2_DEVICE(sdh0, "sdhci-pxav3", 0, MMC, 0xd4280000, 0x120);
+MMP2_DEVICE(sdh1, "sdhci-pxav3", 1, MMC2, 0xd4280800, 0x120);
+MMP2_DEVICE(sdh2, "sdhci-pxav3", 2, MMC3, 0xd4281000, 0x120);
+MMP2_DEVICE(sdh3, "sdhci-pxav3", 3, MMC4, 0xd4281800, 0x120);
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index ab9f999106c7..0156f535dae7 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -66,6 +66,7 @@ void __init pxa168_init_irq(void)
/* APB peripheral clocks */
static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
+static APBC_CLK(uart3, PXA168_UART3, 1, 14745600);
static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
@@ -81,11 +82,13 @@ 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);
/* device and clock bindings */
static struct clk_lookup pxa168_clkregs[] = {
INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+ INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
@@ -100,6 +103,7 @@ static struct clk_lookup pxa168_clkregs[] = {
INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
+ INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
};
static int __init pxa168_init(void)
@@ -149,6 +153,7 @@ void pxa168_clear_keypad_wakeup(void)
/* on-chip devices */
PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
+PXA168_DEVICE(uart3, "pxa2xx-uart", 2, UART3, 0xd4026000, 0x30, 23, 24);
PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
@@ -163,3 +168,4 @@ PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59);
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);
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index e411039ea59e..6bd37a27e5fc 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -15,6 +15,8 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/onenand.h>
#include <linux/interrupt.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -25,7 +27,17 @@
#include "common.h"
-#define TTCDKB_NR_IRQS (IRQ_BOARD_START + 24)
+#define TTCDKB_GPIO_EXT0(x) (NR_BUILTIN_GPIO + ((x < 0) ? 0 : \
+ ((x < 16) ? x : 15)))
+#define TTCDKB_GPIO_EXT1(x) (NR_BUILTIN_GPIO + 16 + ((x < 0) ? 0 : \
+ ((x < 16) ? x : 15)))
+
+/*
+ * 16 board interrupts -- MAX7312 GPIO expander
+ * 16 board interrupts -- PCA9575 GPIO expander
+ * 24 board interrupts -- 88PM860x PMIC
+ */
+#define TTCDKB_NR_IRQS (IRQ_BOARD_START + 16 + 16 + 24)
static unsigned long ttc_dkb_pin_config[] __initdata = {
/* UART2 */
@@ -113,6 +125,22 @@ static struct platform_device *ttc_dkb_devices[] = {
&ttc_dkb_device_onenand,
};
+static struct pca953x_platform_data max7312_data[] = {
+ {
+ .gpio_base = TTCDKB_GPIO_EXT0(0),
+ .irq_base = IRQ_BOARD_START,
+ },
+};
+
+static struct i2c_board_info ttc_dkb_i2c_info[] = {
+ {
+ .type = "max7312",
+ .addr = 0x23,
+ .irq = IRQ_GPIO(80),
+ .platform_data = &max7312_data,
+ },
+};
+
static void __init ttc_dkb_init(void)
{
mfp_config(ARRAY_AND_SIZE(ttc_dkb_pin_config));
@@ -121,6 +149,7 @@ static void __init ttc_dkb_init(void)
pxa910_add_uart(1);
/* off-chip devices */
+ pxa910_add_twsi(0, NULL, ARRAY_AND_SIZE(ttc_dkb_i2c_info));
platform_add_devices(ARRAY_AND_SIZE(ttc_dkb_devices));
}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 1516896e8d17..888e92502e15 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -148,22 +148,6 @@ config MACH_MSM8960_RUMI3
endmenu
-config MSM_IOMMU
- bool "MSM IOMMU Support"
- depends on ARCH_MSM8X60 || ARCH_MSM8960
- select IOMMU_API
- default n
- help
- Support for the IOMMUs found on certain Qualcomm SOCs.
- These IOMMUs allow virtualization of the address space used by most
- cores within the multimedia subsystem.
-
- If unsure, say N here.
-
-config IOMMU_PGTABLES_L2
- def_bool y
- depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
-
config MSM_DEBUG_UART
int
default 1 if MSM_DEBUG_UART1
@@ -205,9 +189,6 @@ config MSM_GPIOMUX
config MSM_V2_TLMM
bool
-config IOMMU_API
- bool
-
config MSM_SCM
bool
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 9519fd28a025..b70658c5ae00 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -3,7 +3,7 @@ obj-y += clock.o
obj-$(CONFIG_DEBUG_FS) += clock-debug.o
obj-$(CONFIG_MSM_VIC) += irq-vic.o
-obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o
+obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o
obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
obj-$(CONFIG_ARCH_MSM7X30) += dma.o
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 2034098cf015..1a1af9e56250 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -18,6 +18,7 @@
#include <asm/hardware/gic.h>
#include <asm/cacheflush.h>
+#include <asm/cputype.h>
#include <asm/mach-types.h>
#include <mach/msm_iomap.h>
@@ -40,6 +41,12 @@ volatile int pen_release = -1;
static DEFINE_SPINLOCK(boot_lock);
+static inline int get_core_count(void)
+{
+ /* 1 + the PART[1:0] field of MIDR */
+ return ((read_cpuid_id() >> 4) & 3) + 1;
+}
+
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/* Configure edge-triggered PPIs */
@@ -147,9 +154,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
*/
void __init smp_init_cpus(void)
{
- unsigned int i;
+ unsigned int i, ncores = get_core_count();
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
set_smp_cross_call(gic_raise_softirq);
@@ -157,12 +164,4 @@ void __init smp_init_cpus(void)
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- /*
- * Initialise the present map, which describes the set of CPUs
- * actually populated at the present time.
- */
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
}
diff --git a/arch/arm/mach-mv78xx0/include/mach/hardware.h b/arch/arm/mach-mv78xx0/include/mach/hardware.h
index 5d887557e123..67cab0a08e07 100644
--- a/arch/arm/mach-mv78xx0/include/mach/hardware.h
+++ b/arch/arm/mach-mv78xx0/include/mach/hardware.h
@@ -11,11 +11,4 @@
#include "mv78xx0.h"
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x00001000
-#define PCIBIOS_MIN_MEM 0x01000000
-#define PCIMEM_BASE MV78XX0_PCIE_MEM_PHYS_BASE /* mem base for VGA */
-
-
#endif
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index a560439dcc3c..d6336afe9948 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/mbus.h>
+#include <video/vga.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <plat/pcie.h>
@@ -129,12 +130,12 @@ static void __init mv78xx0_pcie_preinit(void)
struct pcie_port *pp = pcie_port + i;
mv78xx0_setup_pcie_io_win(win++, pp->res[0].start,
- pp->res[0].end - pp->res[0].start + 1,
- pp->maj, pp->min);
+ resource_size(&pp->res[0]),
+ pp->maj, pp->min);
mv78xx0_setup_pcie_mem_win(win++, pp->res[1].start,
- pp->res[1].end - pp->res[1].start + 1,
- pp->maj, pp->min);
+ resource_size(&pp->res[1]),
+ pp->maj, pp->min);
}
}
@@ -297,6 +298,8 @@ static void __init add_pcie_port(int maj, int min, unsigned long base)
void __init mv78xx0_pcie_init(int init_port0, int init_port1)
{
+ vga_base = MV78XX0_PCIE_MEM_PHYS_BASE;
+
if (init_port0) {
add_pcie_port(0, 0, PCIE00_VIRT_BASE);
if (!orion_pcie_x4_mode((void __iomem *)PCIE00_VIRT_BASE)) {
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 799fbc40e53c..b4e7c58bbb38 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -109,6 +109,7 @@ config MACH_EUKREA_MBIMX51_BASEBOARD
bool
select IMX_HAVE_PLATFORM_IMX_KEYPAD
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select LEDS_GPIO_REGISTER
help
This adds board specific devices that can be found on Eukrea's
MBIMX51 evaluation board.
@@ -135,6 +136,7 @@ config MACH_EUKREA_MBIMXSD51_BASEBOARD
prompt "Eukrea MBIMXSD development board"
bool
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select LEDS_GPIO_REGISTER
help
This adds board specific devices that can be found on Eukrea's
MBIMXSD evaluation board.
@@ -151,6 +153,7 @@ config MX51_EFIKA_COMMON
config MACH_MX51_EFIKAMX
bool "Support MX51 Genesi Efika MX nettop"
+ select LEDS_GPIO_REGISTER
select MX51_EFIKA_COMMON
help
Include support for Genesi Efika MX nettop. This includes specific
@@ -158,6 +161,7 @@ config MACH_MX51_EFIKAMX
config MACH_MX51_EFIKASB
bool "Support MX51 Genesi Efika Smartbook"
+ select LEDS_GPIO_REGISTER
select MX51_EFIKA_COMMON
help
Include support for Genesi Efika Smartbook. This includes specific
@@ -176,6 +180,7 @@ config MACH_MX53_EVK
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
select IMX_HAVE_PLATFORM_SPI_IMX
+ select LEDS_GPIO_REGISTER
help
Include support for MX53 EVK platform. This includes specific
configurations for the board and its peripherals.
@@ -199,10 +204,23 @@ config MACH_MX53_LOCO
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
select IMX_HAVE_PLATFORM_GPIO_KEYS
+ select LEDS_GPIO_REGISTER
help
Include support for MX53 LOCO platform. This includes specific
configurations for the board and its peripherals.
+config MACH_MX53_ARD
+ bool "Support MX53 ARD platforms"
+ select SOC_IMX53
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_GPIO_KEYS
+ help
+ 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 0b9338cec516..383e7cd3fbcb 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -6,12 +6,14 @@
obj-y := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
+obj-$(CONFIG_PM) += pm-imx5.o
obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o
obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o
obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o
+obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o
obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index 4efa02ee1639..7c893fa70266 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -43,10 +43,6 @@
#define CPUIMX51_QUARTB_GPIO IMX_GPIO_NR(3, 25)
#define CPUIMX51_QUARTC_GPIO IMX_GPIO_NR(3, 26)
#define CPUIMX51_QUARTD_GPIO IMX_GPIO_NR(3, 27)
-#define CPUIMX51_QUARTA_IRQ (MXC_INTERNAL_IRQS + CPUIMX51_QUARTA_GPIO)
-#define CPUIMX51_QUARTB_IRQ (MXC_INTERNAL_IRQS + CPUIMX51_QUARTB_GPIO)
-#define CPUIMX51_QUARTC_IRQ (MXC_INTERNAL_IRQS + CPUIMX51_QUARTC_GPIO)
-#define CPUIMX51_QUARTD_IRQ (MXC_INTERNAL_IRQS + CPUIMX51_QUARTD_GPIO)
#define CPUIMX51_QUART_XTAL 14745600
#define CPUIMX51_QUART_REGSHIFT 17
@@ -61,7 +57,7 @@
static struct plat_serial8250_port serial_platform_data[] = {
{
.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
- .irq = CPUIMX51_QUARTA_IRQ,
+ .irq = gpio_to_irq(CPUIMX51_QUARTA_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -69,7 +65,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 = CPUIMX51_QUARTB_IRQ,
+ .irq = gpio_to_irq(CPUIMX51_QUARTB_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -77,7 +73,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 = CPUIMX51_QUARTC_IRQ,
+ .irq = gpio_to_irq(CPUIMX51_QUARTC_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -85,7 +81,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 = CPUIMX51_QUARTD_IRQ,
+ .irq = irq_to_gpio(CPUIMX51_QUARTD_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -245,6 +241,8 @@ __setup("otg_mode=", eukrea_cpuimx51_otg_mode);
*/
static void __init eukrea_cpuimx51_init(void)
{
+ imx51_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
ARRAY_SIZE(eukrea_cpuimx51_pads));
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
index 5ef25a596143..ff096d587299 100644
--- a/arch/arm/mach-mx5/board-cpuimx51sd.c
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -264,6 +264,8 @@ static struct platform_device *platform_devices[] __initdata = {
static void __init eukrea_cpuimx51sd_init(void)
{
+ imx51_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
ARRAY_SIZE(eukrea_cpuimx51sd_pads));
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
index 11210e1ae42a..7de25c6712eb 100644
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -192,6 +192,8 @@ static const struct imxi2c_platform_data i2c_data __initconst = {
*/
static void __init mx50_rdp_board_init(void)
{
+ imx50_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
ARRAY_SIZE(mx50_rdp_pads));
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index 63dfbeafbc1e..07a38154da21 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -13,6 +13,7 @@
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -26,7 +27,7 @@
#include "devices-imx51.h"
#include "devices.h"
-#define EXPIO_PARENT_INT (MXC_INTERNAL_IRQS + GPIO_PORTA + 6)
+#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 6))
#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28)
static iomux_v3_cfg_t mx51_3ds_pads[] = {
@@ -135,6 +136,8 @@ static struct spi_board_info mx51_3ds_spi_nor_device[] = {
*/
static void __init mx51_3ds_init(void)
{
+ imx51_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
ARRAY_SIZE(mx51_3ds_pads));
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index c7b3fabf50f9..15c600026aee 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -36,11 +36,15 @@
#define BABBAGE_USB_HUB_RESET IMX_GPIO_NR(1, 7)
#define BABBAGE_USBH1_STP IMX_GPIO_NR(1, 27)
-#define BABBAGE_PHY_RESET IMX_GPIO_NR(2, 5)
+#define BABBAGE_USB_PHY_RESET IMX_GPIO_NR(2, 5)
#define BABBAGE_FEC_PHY_RESET IMX_GPIO_NR(2, 14)
#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21)
#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
+#define BABBAGE_SD1_CD IMX_GPIO_NR(1, 0)
+#define BABBAGE_SD1_WP IMX_GPIO_NR(1, 1)
+#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6)
+#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5)
/* USB_CTRL_1 */
#define MX51_USB_CTRL_1_OFFSET 0x10
@@ -110,6 +114,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
/* USB HUB reset line*/
MX51_PAD_GPIO1_7__GPIO1_7,
+ /* USB PHY reset line */
+ MX51_PAD_EIM_D21__GPIO2_5,
+
/* FEC */
MX51_PAD_EIM_EB2__FEC_MDIO,
MX51_PAD_EIM_EB3__FEC_RDATA1,
@@ -139,6 +146,8 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
MX51_PAD_SD1_DATA1__SD1_DATA1,
MX51_PAD_SD1_DATA2__SD1_DATA2,
MX51_PAD_SD1_DATA3__SD1_DATA3,
+ MX51_PAD_GPIO1_0__GPIO1_0,
+ MX51_PAD_GPIO1_1__GPIO1_1,
/* SD 2 */
MX51_PAD_SD2_CMD__SD2_CMD,
@@ -147,6 +156,8 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
MX51_PAD_SD2_DATA1__SD2_DATA1,
MX51_PAD_SD2_DATA2__SD2_DATA2,
MX51_PAD_SD2_DATA3__SD2_DATA3,
+ MX51_PAD_GPIO1_6__GPIO1_6,
+ MX51_PAD_GPIO1_5__GPIO1_5,
/* eCSPI1 */
MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
@@ -169,34 +180,31 @@ static struct imxi2c_platform_data babbage_hsi2c_data = {
.bitrate = 400000,
};
+static struct gpio mx51_babbage_usbh1_gpios[] = {
+ { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
+ { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
+};
+
static int gpio_usbh1_active(void)
{
iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
- iomux_v3_cfg_t phyreset_gpio = MX51_PAD_EIM_D21__GPIO2_5;
int ret;
/* Set USBH1_STP to GPIO and toggle it */
mxc_iomux_v3_setup_pad(usbh1stp_gpio);
- ret = gpio_request(BABBAGE_USBH1_STP, "usbh1_stp");
+ ret = gpio_request_array(mx51_babbage_usbh1_gpios,
+ ARRAY_SIZE(mx51_babbage_usbh1_gpios));
if (ret) {
- pr_debug("failed to get MX51_PAD_USBH1_STP__GPIO_1_27: %d\n", ret);
+ pr_debug("failed to get USBH1 pins: %d\n", ret);
return ret;
}
- gpio_direction_output(BABBAGE_USBH1_STP, 0);
- gpio_set_value(BABBAGE_USBH1_STP, 1);
- msleep(100);
- gpio_free(BABBAGE_USBH1_STP);
-
- /* De-assert USB PHY RESETB */
- mxc_iomux_v3_setup_pad(phyreset_gpio);
- ret = gpio_request(BABBAGE_PHY_RESET, "phy_reset");
- if (ret) {
- pr_debug("failed to get MX51_PAD_EIM_D21__GPIO_2_5: %d\n", ret);
- return ret;
- }
- gpio_direction_output(BABBAGE_PHY_RESET, 1);
+ msleep(100);
+ gpio_set_value(BABBAGE_USBH1_STP, 1);
+ gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
+ gpio_free_array(mx51_babbage_usbh1_gpios,
+ ARRAY_SIZE(mx51_babbage_usbh1_gpios));
return 0;
}
@@ -331,6 +339,16 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
.num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
};
+static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
+ .cd_gpio = BABBAGE_SD1_CD,
+ .wp_gpio = BABBAGE_SD1_WP,
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
+ .cd_gpio = BABBAGE_SD2_CD,
+ .wp_gpio = BABBAGE_SD2_WP,
+};
+
/*
* Board specific initialization.
*/
@@ -340,6 +358,8 @@ static void __init mx51_babbage_init(void)
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);
+ imx51_soc_init();
+
#if defined(CONFIG_CPU_FREQ_IMX)
get_cpu_op = mx51_get_cpu_op;
#endif
@@ -374,8 +394,8 @@ static void __init mx51_babbage_init(void)
mxc_iomux_v3_setup_pad(usbh1stp);
babbage_usbhub_reset();
- imx51_add_sdhci_esdhc_imx(0, NULL);
- imx51_add_sdhci_esdhc_imx(1, NULL);
+ imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
+ imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
spi_register_board_info(mx51_babbage_spi_board_info,
ARRAY_SIZE(mx51_babbage_spi_board_info));
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
index 6e362315291b..f70700dc0ec1 100644
--- a/arch/arm/mach-mx5/board-mx51_efikamx.c
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -139,7 +139,7 @@ static void __init mx51_efikamx_board_id(void)
}
}
-static struct gpio_led mx51_efikamx_leds[] = {
+static struct gpio_led mx51_efikamx_leds[] __initdata = {
{
.name = "efikamx:green",
.default_trigger = "default-on",
@@ -157,19 +157,12 @@ static struct gpio_led mx51_efikamx_leds[] = {
},
};
-static struct gpio_led_platform_data mx51_efikamx_leds_data = {
+static const struct gpio_led_platform_data
+ mx51_efikamx_leds_data __initconst = {
.leds = mx51_efikamx_leds,
.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
};
-static struct platform_device mx51_efikamx_leds_device = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &mx51_efikamx_leds_data,
- },
-};
-
static struct gpio_keys_button mx51_efikamx_powerkey[] = {
{
.code = KEY_POWER,
@@ -236,6 +229,8 @@ late_initcall(mx51_efikamx_power_init);
static void __init mx51_efikamx_init(void)
{
+ imx51_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
ARRAY_SIZE(mx51efikamx_pads));
efika_board_common_init();
@@ -248,7 +243,7 @@ static void __init mx51_efikamx_init(void)
mx51_efikamx_leds[2].default_trigger = "mmc1";
}
- platform_device_register(&mx51_efikamx_leds_device);
+ gpio_led_register_device(-1, &mx51_efikamx_leds_data);
imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
if (system_rev == 0x11) {
diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c
index 474fc6e4c6df..2e4d9d32a87c 100644
--- a/arch/arm/mach-mx5/board-mx51_efikasb.c
+++ b/arch/arm/mach-mx5/board-mx51_efikasb.c
@@ -132,7 +132,7 @@ static void __init mx51_efikasb_usb(void)
mxc_register_device(&mxc_usbh2_device, &usbh2_config);
}
-static struct gpio_led mx51_efikasb_leds[] = {
+static const struct gpio_led mx51_efikasb_leds[] __initconst = {
{
.name = "efikasb:green",
.default_trigger = "default-on",
@@ -146,19 +146,12 @@ static struct gpio_led mx51_efikasb_leds[] = {
},
};
-static struct gpio_led_platform_data mx51_efikasb_leds_data = {
+static const struct gpio_led_platform_data
+ mx51_efikasb_leds_data __initconst = {
.leds = mx51_efikasb_leds,
.num_leds = ARRAY_SIZE(mx51_efikasb_leds),
};
-static struct platform_device mx51_efikasb_leds_device = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &mx51_efikasb_leds_data,
- },
-};
-
static struct gpio_keys_button mx51_efikasb_keys[] = {
{
.code = KEY_POWER,
@@ -248,6 +241,8 @@ static void __init mx51_efikasb_board_id(void)
static void __init efikasb_board_init(void)
{
+ imx51_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
ARRAY_SIZE(mx51efikasb_pads));
efika_board_common_init();
@@ -256,9 +251,8 @@ static void __init efikasb_board_init(void)
mx51_efikasb_usb();
imx51_add_sdhci_esdhc_imx(1, NULL);
- platform_device_register(&mx51_efikasb_leds_device);
+ gpio_led_register_device(-1, &mx51_efikasb_leds_data);
imx_add_gpio_keys(&mx51_efikasb_keys_data);
-
}
static void __init mx51_efikasb_timer_init(void)
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
new file mode 100644
index 000000000000..76a67c4a2a0b
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx53_ard.c
@@ -0,0 +1,254 @@
+/*
+ * 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/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "crm_regs.h"
+#include "devices-imx53.h"
+
+#define ARD_ETHERNET_INT_B IMX_GPIO_NR(2, 31)
+#define ARD_SD1_CD IMX_GPIO_NR(1, 1)
+#define ARD_SD1_WP IMX_GPIO_NR(1, 9)
+#define ARD_I2CPORTEXP_B IMX_GPIO_NR(2, 3)
+#define ARD_VOLUMEDOWN IMX_GPIO_NR(4, 0)
+#define ARD_HOME IMX_GPIO_NR(5, 10)
+#define ARD_BACK IMX_GPIO_NR(5, 11)
+#define ARD_PROG IMX_GPIO_NR(5, 12)
+#define ARD_VOLUMEUP IMX_GPIO_NR(5, 13)
+
+static iomux_v3_cfg_t mx53_ard_pads[] = {
+ /* UART1 */
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+ /* WEIM for CS1 */
+ MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
+ MX53_PAD_EIM_D16__EMI_WEIM_D_16,
+ MX53_PAD_EIM_D17__EMI_WEIM_D_17,
+ MX53_PAD_EIM_D18__EMI_WEIM_D_18,
+ MX53_PAD_EIM_D19__EMI_WEIM_D_19,
+ MX53_PAD_EIM_D20__EMI_WEIM_D_20,
+ MX53_PAD_EIM_D21__EMI_WEIM_D_21,
+ MX53_PAD_EIM_D22__EMI_WEIM_D_22,
+ MX53_PAD_EIM_D23__EMI_WEIM_D_23,
+ MX53_PAD_EIM_D24__EMI_WEIM_D_24,
+ MX53_PAD_EIM_D25__EMI_WEIM_D_25,
+ MX53_PAD_EIM_D26__EMI_WEIM_D_26,
+ MX53_PAD_EIM_D27__EMI_WEIM_D_27,
+ MX53_PAD_EIM_D28__EMI_WEIM_D_28,
+ MX53_PAD_EIM_D29__EMI_WEIM_D_29,
+ MX53_PAD_EIM_D30__EMI_WEIM_D_30,
+ MX53_PAD_EIM_D31__EMI_WEIM_D_31,
+ MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
+ MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
+ MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
+ MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
+ MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
+ MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
+ MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
+ MX53_PAD_EIM_OE__EMI_WEIM_OE,
+ MX53_PAD_EIM_RW__EMI_WEIM_RW,
+ MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
+ /* SDHC1 */
+ MX53_PAD_SD1_CMD__ESDHC1_CMD,
+ MX53_PAD_SD1_CLK__ESDHC1_CLK,
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+ MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
+ MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
+ MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
+ MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
+ MX53_PAD_GPIO_1__GPIO1_1,
+ MX53_PAD_GPIO_9__GPIO1_9,
+ /* I2C2 */
+ MX53_PAD_EIM_EB2__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+ /* I2C3 */
+ MX53_PAD_GPIO_3__I2C3_SCL,
+ MX53_PAD_GPIO_16__I2C3_SDA,
+ /* GPIO */
+ MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */
+ MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */
+ MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */
+ MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */
+ MX53_PAD_GPIO_10__GPIO4_0, /* vol down */
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+ GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
+ GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
+ GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
+ GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data ard_button_data __initconst = {
+ .buttons = ard_buttons,
+ .nbuttons = ARRAY_SIZE(ard_buttons),
+};
+
+static struct resource ard_smsc911x_resources[] = {
+ {
+ .start = MX53_CS1_64MB_BASE_ADDR,
+ .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = gpio_to_irq(ARD_ETHERNET_INT_B),
+ .end = gpio_to_irq(ARD_ETHERNET_INT_B),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+ .name = "smsc911x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+ .resource = ard_smsc911x_resources,
+ .dev = {
+ .platform_data = &ard_smsc911x_config,
+ },
+};
+
+static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
+ .cd_gpio = ARD_SD1_CD,
+ .wp_gpio = ARD_SD1_WP,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c2_data = {
+ .bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c3_data = {
+ .bitrate = 400000,
+};
+
+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);
+
+ gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+ gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+}
+
+/* Config CS1 settings for ethernet controller */
+static int weim_cs_config(void)
+{
+ u32 reg;
+ void __iomem *weim_base, *iomuxc_base;
+
+ weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
+ if (!weim_base)
+ return -ENOMEM;
+
+ iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
+ if (!iomuxc_base)
+ return -ENOMEM;
+
+ /* CS1 timings for LAN9220 */
+ writel(0x20001, (weim_base + 0x18));
+ writel(0x0, (weim_base + 0x1C));
+ writel(0x16000202, (weim_base + 0x20));
+ writel(0x00000002, (weim_base + 0x24));
+ writel(0x16002082, (weim_base + 0x28));
+ writel(0x00000000, (weim_base + 0x2C));
+ writel(0x00000000, (weim_base + 0x90));
+
+ /* specify 64 MB on CS1 and CS0 on GPR1 */
+ reg = readl(iomuxc_base + 0x4);
+ reg &= ~0x3F;
+ reg |= 0x1B;
+ writel(reg, (iomuxc_base + 0x4));
+
+ iounmap(iomuxc_base);
+ iounmap(weim_base);
+
+ return 0;
+}
+
+static struct platform_device *devices[] __initdata = {
+ &ard_smsc_lan9220_device,
+};
+
+static void __init mx53_ard_board_init(void)
+{
+ imx53_soc_init();
+ imx53_add_imx_uart(0, NULL);
+
+ mx53_ard_io_init();
+ weim_cs_config();
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
+ imx53_add_imx2_wdt(0, NULL);
+ 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);
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+ mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_ard_timer = {
+ .init = mx53_ard_timer_init,
+};
+
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_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 f87d571882c6..1b417b06b736 100644
--- a/arch/arm/mach-mx5/board-mx53_evk.c
+++ b/arch/arm/mach-mx5/board-mx53_evk.c
@@ -35,6 +35,7 @@
#define MX53_EVK_FEC_PHY_RST IMX_GPIO_NR(7, 6)
#define EVK_ECSPI1_CS0 IMX_GPIO_NR(2, 30)
#define EVK_ECSPI1_CS1 IMX_GPIO_NR(3, 19)
+#define MX53EVK_LED IMX_GPIO_NR(7, 7)
#include "crm_regs.h"
#include "devices-imx53.h"
@@ -58,12 +59,27 @@ static iomux_v3_cfg_t mx53_evk_pads[] = {
/* ecspi chip select lines */
MX53_PAD_EIM_EB2__GPIO2_30,
MX53_PAD_EIM_D19__GPIO3_19,
+ /* LED */
+ MX53_PAD_PATA_DA_1__GPIO7_7,
};
static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
+static const struct gpio_led mx53evk_leds[] __initconst = {
+ {
+ .name = "green",
+ .default_trigger = "heartbeat",
+ .gpio = MX53EVK_LED,
+ },
+};
+
+static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
+ .leds = mx53evk_leds,
+ .num_leds = ARRAY_SIZE(mx53evk_leds),
+};
+
static inline void mx53_evk_init_uart(void)
{
imx53_add_imx_uart(0, NULL);
@@ -117,6 +133,8 @@ static const struct spi_imx_master mx53_evk_spi_data __initconst = {
static void __init mx53_evk_board_init(void)
{
+ imx53_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
ARRAY_SIZE(mx53_evk_pads));
mx53_evk_init_uart();
@@ -133,6 +151,7 @@ static void __init mx53_evk_board_init(void)
ARRAY_SIZE(mx53_evk_spi_board_info));
imx53_add_ecspi(0, &mx53_evk_spi_data);
imx53_add_imx2_wdt(0, NULL);
+ gpio_led_register_device(-1, &mx53evk_leds_data);
}
static void __init mx53_evk_timer_init(void)
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 1b947e8c9c0c..54be525e2bd7 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -38,6 +38,10 @@
#define MX53_LOCO_UI1 IMX_GPIO_NR(2, 14)
#define MX53_LOCO_UI2 IMX_GPIO_NR(2, 15)
#define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6)
+#define LOCO_LED IMX_GPIO_NR(7, 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)
static iomux_v3_cfg_t mx53_loco_pads[] = {
/* FEC */
@@ -70,6 +74,8 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+ /* SD1_CD */
+ MX53_PAD_EIM_DA13__GPIO3_13,
/* SD3 */
MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
@@ -163,7 +169,7 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
MX53_PAD_GPIO_7__SPDIF_PLOCK,
MX53_PAD_GPIO_17__SPDIF_OUT1,
/* GPIO */
- MX53_PAD_PATA_DA_1__GPIO7_7,
+ MX53_PAD_PATA_DA_1__GPIO7_7, /* LED */
MX53_PAD_PATA_DA_2__GPIO7_8,
MX53_PAD_PATA_DATA5__GPIO2_5,
MX53_PAD_PATA_DATA6__GPIO2_6,
@@ -202,6 +208,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
.nbuttons = ARRAY_SIZE(loco_buttons),
};
+static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
+ .cd_gpio = LOCO_SD1_CD,
+};
+
+static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
+ .cd_gpio = LOCO_SD3_CD,
+ .wp_gpio = LOCO_SD3_WP,
+};
+
static inline void mx53_loco_fec_reset(void)
{
int ret;
@@ -225,8 +240,23 @@ static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
.bitrate = 100000,
};
+static const struct gpio_led mx53loco_leds[] __initconst = {
+ {
+ .name = "green",
+ .default_trigger = "heartbeat",
+ .gpio = LOCO_LED,
+ },
+};
+
+static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
+ .leds = mx53loco_leds,
+ .num_leds = ARRAY_SIZE(mx53loco_leds),
+};
+
static void __init mx53_loco_board_init(void)
{
+ imx53_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
ARRAY_SIZE(mx53_loco_pads));
imx53_add_imx_uart(0, NULL);
@@ -235,9 +265,10 @@ static void __init mx53_loco_board_init(void)
imx53_add_imx2_wdt(0, NULL);
imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
- imx53_add_sdhci_esdhc_imx(0, NULL);
- imx53_add_sdhci_esdhc_imx(2, NULL);
+ 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);
}
static void __init mx53_loco_timer_init(void)
diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c
index 817c08938f55..bc02894eafef 100644
--- a/arch/arm/mach-mx5/board-mx53_smd.c
+++ b/arch/arm/mach-mx5/board-mx53_smd.c
@@ -113,6 +113,8 @@ static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
static void __init mx53_smd_board_init(void)
{
+ imx53_soc_init();
+
mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
ARRAY_SIZE(mx53_smd_pads));
mx53_smd_init_uart();
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 6b89c1bf4eb2..23cd809fa8b8 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -1254,12 +1254,20 @@ DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
NULL, NULL, &ipg_clk, &aips_tz1_clk);
DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
NULL, NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
+ NULL, NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
+ NULL, NULL, &ipg_clk, &spba_clk);
DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
NULL, NULL, &uart_root_clk, &uart1_ipg_clk);
DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
NULL, NULL, &uart_root_clk, &uart2_ipg_clk);
DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
NULL, NULL, &uart_root_clk, &uart3_ipg_clk);
+DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart4_ipg_clk);
+DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart5_ipg_clk);
/* GPT */
DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
@@ -1274,11 +1282,13 @@ DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
/* I2C */
DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
+ NULL, NULL, &ipg_perclk, NULL);
DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
+ NULL, NULL, &ipg_perclk, NULL);
DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+ NULL, NULL, &ipg_perclk, NULL);
/* FEC */
DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
@@ -1442,7 +1452,8 @@ static struct clk_lookup mx51_lookups[] = {
_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
- _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+ /* i.mx51 has the i.mx35 type cspi */
+ _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
@@ -1462,20 +1473,30 @@ static struct clk_lookup mx53_lookups[] = {
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+ _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+ _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
- _REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
- _REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
- _REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
+ /* i.mx53 has the i.mx51 type ecspi */
+ _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+ _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+ /* i.mx53 has the i.mx25 type cspi */
+ _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+ _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+ _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+ _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+ _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+ _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
};
static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
index 87c0c58f27a7..5e11ba7daee2 100644
--- a/arch/arm/mach-mx5/crm_regs.h
+++ b/arch/arm/mach-mx5/crm_regs.h
@@ -114,6 +114,8 @@
#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78)
#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C)
#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7 (MX51_CCM_BASE + 0x84)
+
#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84)
/* Define the bits in register CCR */
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
index 48f4c8cc42f5..c27fe8bb4762 100644
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -32,3 +32,11 @@ extern const struct imx_spi_imx_data imx53_ecspi_data[];
extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
#define imx53_add_imx2_wdt(id, pdata) \
imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
+
+extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
+#define imx53_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
+
+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)
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 153ada53e575..371ca8c8414c 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -12,7 +12,6 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/imx-uart.h>
#include <mach/irqs.h>
@@ -119,66 +118,3 @@ struct platform_device mxc_usbh2_device = {
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
-
-static struct mxc_gpio_port mxc_gpio_ports[] = {
- {
- .chip.label = "gpio-0",
- .base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO1_LOW,
- .irq_high = MX51_MXC_INT_GPIO1_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START
- },
- {
- .chip.label = "gpio-1",
- .base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO2_LOW,
- .irq_high = MX51_MXC_INT_GPIO2_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
- },
- {
- .chip.label = "gpio-2",
- .base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO3_LOW,
- .irq_high = MX51_MXC_INT_GPIO3_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
- },
- {
- .chip.label = "gpio-3",
- .base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO4_LOW,
- .irq_high = MX51_MXC_INT_GPIO4_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
- },
- {
- .chip.label = "gpio-4",
- .base = MX53_IO_ADDRESS(MX53_GPIO5_BASE_ADDR),
- .irq = MX53_INT_GPIO5_LOW,
- .irq_high = MX53_INT_GPIO5_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4
- },
- {
- .chip.label = "gpio-5",
- .base = MX53_IO_ADDRESS(MX53_GPIO6_BASE_ADDR),
- .irq = MX53_INT_GPIO6_LOW,
- .irq_high = MX53_INT_GPIO6_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5
- },
- {
- .chip.label = "gpio-6",
- .base = MX53_IO_ADDRESS(MX53_GPIO7_BASE_ADDR),
- .irq = MX53_INT_GPIO7_LOW,
- .irq_high = MX53_INT_GPIO7_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6
- },
-};
-
-int __init imx51_register_gpios(void)
-{
- return mxc_gpio_init(mxc_gpio_ports, 4);
-}
-
-int __init imx53_register_gpios(void)
-{
- return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
-}
-
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
index 97292d20f1f3..bbf4564bd050 100644
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
@@ -31,13 +31,12 @@
#include "devices.h"
#define MBIMX51_TSC2007_GPIO IMX_GPIO_NR(3, 30)
-#define MBIMX51_TSC2007_IRQ (MXC_INTERNAL_IRQS + MBIMX51_TSC2007_GPIO)
#define MBIMX51_LED0 IMX_GPIO_NR(3, 5)
#define MBIMX51_LED1 IMX_GPIO_NR(3, 6)
#define MBIMX51_LED2 IMX_GPIO_NR(3, 7)
#define MBIMX51_LED3 IMX_GPIO_NR(3, 8)
-static struct gpio_led mbimx51_leds[] = {
+static const struct gpio_led mbimx51_leds[] __initconst = {
{
.name = "led0",
.default_trigger = "heartbeat",
@@ -64,23 +63,11 @@ static struct gpio_led mbimx51_leds[] = {
},
};
-static struct gpio_led_platform_data mbimx51_leds_info = {
+static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
.leds = mbimx51_leds,
.num_leds = ARRAY_SIZE(mbimx51_leds),
};
-static struct platform_device mbimx51_leds_gpio = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &mbimx51_leds_info,
- },
-};
-
-static struct platform_device *devices[] __initdata = {
- &mbimx51_leds_gpio,
-};
-
static iomux_v3_cfg_t mbimx51_pads[] = {
/* UART2 */
MX51_PAD_UART2_RXD__UART2_RXD,
@@ -173,7 +160,7 @@ struct tsc2007_platform_data tsc2007_data = {
static struct i2c_board_info mbimx51_i2c_devices[] = {
{
I2C_BOARD_INFO("tsc2007", 0x49),
- .irq = MBIMX51_TSC2007_IRQ,
+ .irq = gpio_to_irq(MBIMX51_TSC2007_GPIO),
.platform_data = &tsc2007_data,
}, {
I2C_BOARD_INFO("tlv320aic23", 0x1a),
@@ -204,13 +191,14 @@ void __init eukrea_mbimx51_baseboard_init(void)
gpio_direction_output(MBIMX51_LED3, 1);
gpio_free(MBIMX51_LED3);
- platform_add_devices(devices, ARRAY_SIZE(devices));
+ gpio_led_register_device(-1, &mbimx51_leds_info);
imx51_add_imx_keypad(&mbimx51_map_data);
gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
gpio_direction_input(MBIMX51_TSC2007_GPIO);
- irq_set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
+ irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
+ IRQF_TRIGGER_FALLING);
i2c_register_board_info(1, mbimx51_i2c_devices,
ARRAY_SIZE(mbimx51_i2c_devices));
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
index 31c871ec46a6..261923997643 100644
--- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
@@ -74,7 +74,7 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
#define GPIO_LED1 IMX_GPIO_NR(3, 30)
#define GPIO_SWITCH1 IMX_GPIO_NR(3, 31)
-static struct gpio_led eukrea_mbimxsd_leds[] = {
+static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
{
.name = "led1",
.default_trigger = "heartbeat",
@@ -83,19 +83,12 @@ static struct gpio_led eukrea_mbimxsd_leds[] = {
},
};
-static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+static const struct gpio_led_platform_data
+ eukrea_mbimxsd_led_info __initconst = {
.leds = eukrea_mbimxsd_leds,
.num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds),
};
-static struct platform_device eukrea_mbimxsd_leds_gpio = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &eukrea_mbimxsd_led_info,
- },
-};
-
static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
{
.gpio = GPIO_SWITCH1,
@@ -112,10 +105,6 @@ static const struct gpio_keys_platform_data
.nbuttons = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
};
-static struct platform_device *platform_devices[] __initdata = {
- &eukrea_mbimxsd_leds_gpio,
-};
-
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@@ -154,6 +143,6 @@ void __init eukrea_mbimxsd51_baseboard_init(void)
i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
}
diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c
index b9c363b514a9..77e374c726fa 100644
--- a/arch/arm/mach-mx5/mm-mx50.c
+++ b/arch/arm/mach-mx5/mm-mx50.c
@@ -26,7 +26,6 @@
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-v3.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
/*
@@ -56,17 +55,18 @@ void __init imx50_init_early(void)
mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
}
-static struct mxc_gpio_port imx50_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-};
-
void __init mx50_init_irq(void)
{
tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
- mxc_gpio_init(imx50_gpio_ports, ARRAY_SIZE(imx50_gpio_ports));
+}
+
+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 ff557301b42b..ef8aec9319b6 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -18,6 +18,7 @@
#include <mach/hardware.h>
#include <mach/common.h>
+#include <mach/devices-common.h>
#include <mach/iomux-v3.h>
/*
@@ -69,8 +70,6 @@ void __init imx53_init_early(void)
mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
}
-int imx51_register_gpios(void);
-
void __init mx51_init_irq(void)
{
unsigned long tzic_addr;
@@ -86,11 +85,8 @@ void __init mx51_init_irq(void)
panic("unable to map TZIC interrupt controller\n");
tzic_init_irq(tzic_virt);
- imx51_register_gpios();
}
-int imx53_register_gpios(void);
-
void __init mx53_init_irq(void)
{
unsigned long tzic_addr;
@@ -103,5 +99,68 @@ void __init mx53_init_irq(void)
panic("unable to map TZIC interrupt controller\n");
tzic_init_irq(tzic_virt);
- imx53_register_gpios();
+}
+
+static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
+ .ap_2_ap_addr = 642,
+ .uart_2_mcu_addr = 817,
+ .mcu_2_app_addr = 747,
+ .mcu_2_shp_addr = 961,
+ .ata_2_mcu_addr = 1473,
+ .mcu_2_ata_addr = 1392,
+ .app_2_per_addr = 1033,
+ .app_2_mcu_addr = 683,
+ .shp_2_per_addr = 1251,
+ .shp_2_mcu_addr = 892,
+};
+
+static struct sdma_platform_data imx51_sdma_pdata __initdata = {
+ .sdma_version = 2,
+ .fw_name = "sdma-imx51.bin",
+ .script_addrs = &imx51_sdma_script,
+};
+
+static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
+ .ap_2_ap_addr = 642,
+ .app_2_mcu_addr = 683,
+ .mcu_2_app_addr = 747,
+ .uart_2_mcu_addr = 817,
+ .shp_2_mcu_addr = 891,
+ .mcu_2_shp_addr = 960,
+ .uartsh_2_mcu_addr = 1032,
+ .spdif_2_mcu_addr = 1100,
+ .mcu_2_spdif_addr = 1134,
+ .firi_2_mcu_addr = 1193,
+ .mcu_2_firi_addr = 1290,
+};
+
+static struct sdma_platform_data imx53_sdma_pdata __initdata = {
+ .sdma_version = 2,
+ .fw_name = "sdma-imx53.bin",
+ .script_addrs = &imx53_sdma_script,
+};
+
+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);
+
+ imx_add_imx_sdma(MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+}
+
+void __init imx53_soc_init(void)
+{
+ /* i.mx53 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
+ mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
+ mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
+ mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
+ mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
+ mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
+ mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+
+ imx_add_imx_sdma(MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
}
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
new file mode 100644
index 000000000000..e4529af0da72
--- /dev/null
+++ b/arch/arm/mach-mx5/pm-imx5.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 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
+ */
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <mach/system.h>
+#include "crm_regs.h"
+
+static struct clk *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);
+ break;
+ case PM_SUSPEND_STANDBY:
+ mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (state == PM_SUSPEND_MEM) {
+ local_flush_tlb_all();
+ flush_cache_all();
+
+ /*clear the EMPGC0/1 bits */
+ __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+ }
+ cpu_do_idle();
+ clk_disable(gpc_dvfs_clk);
+
+ return 0;
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+ return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+static const struct platform_suspend_ops mx5_suspend_ops = {
+ .valid = mx5_pm_valid,
+ .enter = mx5_suspend_enter,
+};
+
+static int __init mx5_pm_init(void)
+{
+ if (gpc_dvfs_clk == NULL)
+ gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+ if (!IS_ERR(gpc_dvfs_clk)) {
+ if (cpu_is_mx51())
+ suspend_set_ops(&mx5_suspend_ops);
+ } else
+ return -EPERM;
+
+ return 0;
+}
+device_initcall(mx5_pm_init);
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index f114960622e0..4cd0231ee539 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -41,6 +41,7 @@ config MACH_MX23EVK
config MACH_MX28EVK
bool "Support MX28EVK Platform"
select SOC_IMX28
+ select LEDS_GPIO_REGISTER
select MXS_HAVE_AMBA_DUART
select MXS_HAVE_PLATFORM_AUART
select MXS_HAVE_PLATFORM_FEC
@@ -55,10 +56,12 @@ config MACH_MX28EVK
config MODULE_TX28
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_MXS_I2C
+ select MXS_HAVE_PLATFORM_MXS_MMC
select MXS_HAVE_PLATFORM_MXS_PWM
config MACH_TX28
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 58e892376bf2..6c38262a3aaa 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,5 +1,5 @@
# Common support
-obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
+obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o
obj-$(CONFIG_MXS_OCOTP) += ocotp.o
obj-$(CONFIG_PM) += pm.o
diff --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c
index cfdb6b284702..fe3e847930c9 100644
--- a/arch/arm/mach-mxs/devices.c
+++ b/arch/arm/mach-mxs/devices.c
@@ -88,3 +88,14 @@ int __init mxs_add_amba_device(const struct amba_device *dev)
return amba_device_register(adev, &iomem_resource);
}
+
+struct device mxs_apbh_bus = {
+ .init_name = "mxs_apbh",
+ .parent = &platform_bus,
+};
+
+static int __init mxs_device_init(void)
+{
+ return device_register(&mxs_apbh_bus);
+}
+core_initcall(mxs_device_init);
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index 324f2824d38d..351915c683ff 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
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
diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c
index 796606cce0ce..27608f5d2ac8 100644
--- a/arch/arm/mach-mxs/devices/platform-auart.c
+++ b/arch/arm/mach-mxs/devices/platform-auart.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <asm/sizes.h>
#include <mach/mx23.h>
#include <mach/mx28.h>
diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c
index 295c4424d5d9..6a0202b1016c 100644
--- a/arch/arm/mach-mxs/devices/platform-dma.c
+++ b/arch/arm/mach-mxs/devices/platform-dma.c
@@ -6,6 +6,7 @@
* Free Software Foundation.
*/
#include <linux/compiler.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-mxs/devices/platform-fec.c b/arch/arm/mach-mxs/devices/platform-fec.c
index 9859cf283335..ae96a4fd8f14 100644
--- a/arch/arm/mach-mxs/devices/platform-fec.c
+++ b/arch/arm/mach-mxs/devices/platform-fec.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <asm/sizes.h>
#include <mach/mx28.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
new file mode 100644
index 000000000000..ed0885e414e0
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
@@ -0,0 +1,53 @@
+/*
+ * 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>
+
+struct platform_device *__init mxs_add_gpio(
+ int id, resource_size_t iobase, int irq)
+{
+ struct resource res[] = {
+ {
+ .start = iobase,
+ .end = iobase + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = irq,
+ .end = irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return platform_device_register_resndata(&mxs_apbh_bus,
+ "gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0);
+}
+
+static int __init mxs_add_mxs_gpio(void)
+{
+ if (cpu_is_mx23()) {
+ mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0);
+ mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1);
+ mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2);
+ }
+
+ if (cpu_is_mx28()) {
+ mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0);
+ mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1);
+ mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2);
+ mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3);
+ mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4);
+ }
+
+ return 0;
+}
+postcore_initcall(mxs_add_mxs_gpio);
diff --git a/arch/arm/mach-mxs/devices/platform-mxsfb.c b/arch/arm/mach-mxs/devices/platform-mxsfb.c
index bf72c9b8dbdd..5a75b7180f74 100644
--- a/arch/arm/mach-mxs/devices/platform-mxsfb.c
+++ b/arch/arm/mach-mxs/devices/platform-mxsfb.c
@@ -5,6 +5,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <asm/sizes.h>
#include <mach/mx23.h>
#include <mach/mx28.h>
diff --git a/arch/arm/mach-mxs/gpio.c b/arch/arm/mach-mxs/gpio.c
deleted file mode 100644
index 2c950fef71a8..000000000000
--- a/arch/arm/mach-mxs/gpio.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-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.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <asm-generic/bug.h>
-
-#include "gpio.h"
-
-static struct mxs_gpio_port *mxs_gpio_ports;
-static int gpio_table_size;
-
-#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
-#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
-#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
-#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
-#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
-#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
-#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
-#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
-
-#define GPIO_INT_FALL_EDGE 0x0
-#define GPIO_INT_LOW_LEV 0x1
-#define GPIO_INT_RISE_EDGE 0x2
-#define GPIO_INT_HIGH_LEV 0x3
-#define GPIO_INT_LEV_MASK (1 << 0)
-#define GPIO_INT_POL_MASK (1 << 1)
-
-/* Note: This driver assumes 32 GPIOs are handled in one register */
-
-static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)
-{
- __mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id));
-}
-
-static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
- int enable)
-{
- if (enable) {
- __mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id));
- __mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id));
- } else {
- __mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id));
- }
-}
-
-static void mxs_gpio_ack_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f);
-}
-
-static void mxs_gpio_mask_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0);
-}
-
-static void mxs_gpio_unmask_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1);
-}
-
-static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
-
-static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
-{
- u32 gpio = irq_to_gpio(d->irq);
- u32 pin_mask = 1 << (gpio & 31);
- struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
- void __iomem *pin_addr;
- int edge;
-
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- edge = GPIO_INT_RISE_EDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- edge = GPIO_INT_FALL_EDGE;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- edge = GPIO_INT_LOW_LEV;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- edge = GPIO_INT_HIGH_LEV;
- break;
- default:
- return -EINVAL;
- }
-
- /* set level or edge */
- pin_addr = port->base + PINCTRL_IRQLEV(port->id);
- if (edge & GPIO_INT_LEV_MASK)
- __mxs_setl(pin_mask, pin_addr);
- else
- __mxs_clrl(pin_mask, pin_addr);
-
- /* set polarity */
- pin_addr = port->base + PINCTRL_IRQPOL(port->id);
- if (edge & GPIO_INT_POL_MASK)
- __mxs_setl(pin_mask, pin_addr);
- else
- __mxs_clrl(pin_mask, pin_addr);
-
- clear_gpio_irqstatus(port, gpio & 0x1f);
-
- return 0;
-}
-
-/* MXS has one interrupt *per* gpio port */
-static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
- u32 irq_stat;
- struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq);
- u32 gpio_irq_no_base = port->virtual_irq_start;
-
- desc->irq_data.chip->irq_ack(&desc->irq_data);
-
- irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) &
- __raw_readl(port->base + PINCTRL_IRQEN(port->id));
-
- while (irq_stat != 0) {
- int irqoffset = fls(irq_stat) - 1;
- generic_handle_irq(gpio_irq_no_base + irqoffset);
- irq_stat &= ~(1 << irqoffset);
- }
-}
-
-/*
- * Set interrupt number "irq" in the GPIO as a wake-up source.
- * While system is running, all registered GPIO interrupts need to have
- * wake-up enabled. When system is suspended, only selected GPIO interrupts
- * need to have wake-up enabled.
- * @param irq interrupt source number
- * @param enable enable as wake-up if equal to non-zero
- * @return This function returns 0 on success.
- */
-static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
-{
- u32 gpio = irq_to_gpio(d->irq);
- u32 gpio_idx = gpio & 0x1f;
- struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
-
- if (enable) {
- if (port->irq_high && (gpio_idx >= 16))
- enable_irq_wake(port->irq_high);
- else
- enable_irq_wake(port->irq);
- } else {
- if (port->irq_high && (gpio_idx >= 16))
- disable_irq_wake(port->irq_high);
- else
- disable_irq_wake(port->irq);
- }
-
- return 0;
-}
-
-static struct irq_chip gpio_irq_chip = {
- .name = "mxs gpio",
- .irq_ack = mxs_gpio_ack_irq,
- .irq_mask = mxs_gpio_mask_irq,
- .irq_unmask = mxs_gpio_unmask_irq,
- .irq_set_type = mxs_gpio_set_irq_type,
- .irq_set_wake = mxs_gpio_set_wake_irq,
-};
-
-static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
- int dir)
-{
- struct mxs_gpio_port *port =
- container_of(chip, struct mxs_gpio_port, chip);
- void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id);
-
- if (dir)
- __mxs_setl(1 << offset, pin_addr);
- else
- __mxs_clrl(1 << offset, pin_addr);
-}
-
-static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct mxs_gpio_port *port =
- container_of(chip, struct mxs_gpio_port, chip);
-
- return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1;
-}
-
-static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct mxs_gpio_port *port =
- container_of(chip, struct mxs_gpio_port, chip);
- void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id);
-
- if (value)
- __mxs_setl(1 << offset, pin_addr);
- else
- __mxs_clrl(1 << offset, pin_addr);
-}
-
-static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct mxs_gpio_port *port =
- container_of(chip, struct mxs_gpio_port, chip);
-
- return port->virtual_irq_start + offset;
-}
-
-static int mxs_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- mxs_set_gpio_direction(chip, offset, 0);
- return 0;
-}
-
-static int mxs_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- mxs_gpio_set(chip, offset, value);
- mxs_set_gpio_direction(chip, offset, 1);
- return 0;
-}
-
-int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
-{
- int i, j;
-
- /* save for local usage */
- mxs_gpio_ports = port;
- gpio_table_size = cnt;
-
- pr_info("MXS GPIO hardware\n");
-
- for (i = 0; i < cnt; i++) {
- /* disable the interrupt and clear the status */
- __raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i));
- __raw_writel(0, port[i].base + PINCTRL_IRQEN(i));
-
- /* clear address has to be used to clear IRQSTAT bits */
- __mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i));
-
- for (j = port[i].virtual_irq_start;
- j < port[i].virtual_irq_start + 32; j++) {
- irq_set_chip_and_handler(j, &gpio_irq_chip,
- handle_level_irq);
- set_irq_flags(j, IRQF_VALID);
- }
-
- /* setup one handler for each entry */
- irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler);
- irq_set_handler_data(port[i].irq, &port[i]);
-
- /* register gpio chip */
- port[i].chip.direction_input = mxs_gpio_direction_input;
- port[i].chip.direction_output = mxs_gpio_direction_output;
- port[i].chip.get = mxs_gpio_get;
- port[i].chip.set = mxs_gpio_set;
- port[i].chip.to_irq = mxs_gpio_to_irq;
- port[i].chip.base = i * 32;
- port[i].chip.ngpio = 32;
-
- /* its a serious configuration bug when it fails */
- BUG_ON(gpiochip_add(&port[i].chip) < 0);
- }
-
- return 0;
-}
-
-#define MX23_GPIO_BASE MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR)
-#define MX28_GPIO_BASE MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR)
-
-#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id) \
- { \
- .chip.label = "gpio-" #_id, \
- .id = _id, \
- .irq = _irq, \
- .base = _base, \
- .virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32, \
- }
-
-#ifdef CONFIG_SOC_IMX23
-static struct mxs_gpio_port mx23_gpio_ports[] = {
- DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0),
- DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1),
- DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2),
-};
-
-int __init mx23_register_gpios(void)
-{
- return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports));
-}
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-static struct mxs_gpio_port mx28_gpio_ports[] = {
- DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0),
- DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1),
- DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2),
- DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3),
- DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4),
-};
-
-int __init mx28_register_gpios(void)
-{
- return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports));
-}
-#endif
diff --git a/arch/arm/mach-mxs/gpio.h b/arch/arm/mach-mxs/gpio.h
deleted file mode 100644
index 005bb06630b1..000000000000
--- a/arch/arm/mach-mxs/gpio.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 __MXS_GPIO_H__
-#define __MXS_GPIO_H__
-
-struct mxs_gpio_port {
- void __iomem *base;
- int id;
- int irq;
- int irq_high;
- int virtual_irq_start;
- struct gpio_chip chip;
-};
-
-int mxs_gpio_init(struct mxs_gpio_port*, int);
-
-#endif /* __MXS_GPIO_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/clkdev.h b/arch/arm/mach-mxs/include/mach/clkdev.h
deleted file mode 100644
index 3a8f2e3a6309..000000000000
--- a/arch/arm/mach-mxs/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_MXS_CLKDEV_H__
-#define __MACH_MXS_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 7a37469ed5bf..812d7a813a78 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -11,6 +11,8 @@
#include <linux/init.h>
#include <linux/amba/bus.h>
+extern struct device mxs_apbh_bus;
+
struct platform_device *mxs_add_platform_device_dmamask(
const char *name, int id,
const struct resource *res, unsigned int num_resources,
diff --git a/arch/arm/mach-mxs/include/mach/dma.h b/arch/arm/mach-mxs/include/mach/dma.h
index 7f4aeeaba8df..203d7c4a3e11 100644
--- a/arch/arm/mach-mxs/include/mach/dma.h
+++ b/arch/arm/mach-mxs/include/mach/dma.h
@@ -9,6 +9,8 @@
#ifndef __MACH_MXS_DMA_H__
#define __MACH_MXS_DMA_H__
+#include <linux/dmaengine.h>
+
struct mxs_dma_data {
int chan_irq;
};
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index eacdc6b0e70a..eaaf6ff28990 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -15,6 +15,7 @@
#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>
@@ -26,10 +27,10 @@
#include <mach/iomux-mx28.h>
#include "devices-mx28.h"
-#include "gpio.h"
#define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13)
#define MX28EVK_FEC_PHY_POWER MXS_GPIO_NR(2, 15)
+#define MX28EVK_GPIO_LED MXS_GPIO_NR(3, 5)
#define MX28EVK_BL_ENABLE MXS_GPIO_NR(3, 18)
#define MX28EVK_LCD_ENABLE MXS_GPIO_NR(3, 30)
#define MX28EVK_FEC_PHY_RESET MXS_GPIO_NR(4, 13)
@@ -179,6 +180,23 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
/* slot power enable */
MX28_PAD_PWM4__GPIO_3_29 |
(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+ /* led */
+ MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led mx28evk_leds[] __initconst = {
+ {
+ .name = "GPIO-LED",
+ .default_trigger = "heartbeat",
+ .gpio = MX28EVK_GPIO_LED,
+ },
+};
+
+static const struct gpio_led_platform_data mx28evk_led_data __initconst = {
+ .leds = mx28evk_leds,
+ .num_leds = ARRAY_SIZE(mx28evk_leds),
};
/* fec */
@@ -386,6 +404,8 @@ static void __init mx28evk_init(void)
if (ret)
pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+
+ gpio_led_register_device(0, &mx28evk_led_data);
}
static void __init mx28evk_timer_init(void)
diff --git a/arch/arm/mach-mxs/mach-tx28.c b/arch/arm/mach-mxs/mach-tx28.c
index b65e3719cbc4..515a423f82cd 100644
--- a/arch/arm/mach-mxs/mach-tx28.c
+++ b/arch/arm/mach-mxs/mach-tx28.c
@@ -101,14 +101,6 @@ static const iomux_cfg_t tx28_stk5v3_pads[] __initconst = {
(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 |
@@ -117,7 +109,7 @@ static const iomux_cfg_t tx28_stk5v3_pads[] __initconst = {
(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
};
-static struct gpio_led tx28_stk5v3_leds[] = {
+static const struct gpio_led tx28_stk5v3_leds[] __initconst = {
{
.name = "GPIO-LED",
.default_trigger = "heartbeat",
@@ -147,6 +139,11 @@ static struct i2c_board_info tx28_stk5v3_i2c_boardinfo[] __initdata = {
},
};
+static struct mxs_mmc_platform_data tx28_mmc0_pdata __initdata = {
+ .wp_gpio = -EINVAL,
+ .flags = SLOTF_4_BIT_CAPABLE,
+};
+
static void __init tx28_stk5v3_init(void)
{
mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
@@ -159,11 +156,11 @@ static void __init tx28_stk5v3_init(void)
/* spi via ssp will be added when available */
spi_register_board_info(tx28_spi_board_info,
ARRAY_SIZE(tx28_spi_board_info));
- mxs_add_platform_device("leds-gpio", 0, NULL, 0,
- &tx28_stk5v3_led_data, sizeof(tx28_stk5v3_led_data));
+ gpio_led_register_device(0, &tx28_stk5v3_led_data);
mx28_add_mxs_i2c(0);
i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
+ mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
}
static void __init tx28_timer_init(void)
diff --git a/arch/arm/mach-mxs/mm-mx23.c b/arch/arm/mach-mxs/mm-mx23.c
index 5148cd64a6b7..1b2345ac1a87 100644
--- a/arch/arm/mach-mxs/mm-mx23.c
+++ b/arch/arm/mach-mxs/mm-mx23.c
@@ -41,5 +41,4 @@ void __init mx23_map_io(void)
void __init mx23_init_irq(void)
{
icoll_init_irq();
- mx23_register_gpios();
}
diff --git a/arch/arm/mach-mxs/mm-mx28.c b/arch/arm/mach-mxs/mm-mx28.c
index 7e4cea32ebc6..b6e18ddb92c0 100644
--- a/arch/arm/mach-mxs/mm-mx28.c
+++ b/arch/arm/mach-mxs/mm-mx28.c
@@ -41,5 +41,4 @@ void __init mx28_map_io(void)
void __init mx28_init_irq(void)
{
icoll_init_irq();
- mx28_register_gpios();
}
diff --git a/arch/arm/mach-nomadik/include/mach/clkdev.h b/arch/arm/mach-nomadik/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-nomadik/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/clkdev.h b/arch/arm/mach-nuc93x/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/vmalloc.h b/arch/arm/mach-nuc93x/include/mach/vmalloc.h
index 98a21b81dec0..7d11a5f07696 100644
--- a/arch/arm/mach-nuc93x/include/mach/vmalloc.h
+++ b/arch/arm/mach-nuc93x/include/mach/vmalloc.h
@@ -18,6 +18,6 @@
#ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H
-#define VMALLOC_END (0xE0000000)
+#define VMALLOC_END 0xE0000000UL
#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index f49ce85d2448..312ea6b0409d 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -138,7 +138,7 @@ void ams_delta_latch2_write(u16 mask, u16 value)
static void __init ams_delta_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static struct map_desc ams_delta_io_desc[] __initdata = {
@@ -391,7 +391,7 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
.reserve = omap_reserve,
.init_irq = ams_delta_init_irq,
.init_machine = ams_delta_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
EXPORT_SYMBOL(ams_delta_latch1_write);
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 87f173d93557..a6b1bea50371 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -329,7 +329,7 @@ static void __init omap_fsample_init(void)
static void __init omap_fsample_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
/* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -394,5 +394,5 @@ MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
.reserve = omap_reserve,
.init_irq = omap_fsample_init_irq,
.init_machine = omap_fsample_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 23f4ab9e2651..04fc356c40fa 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -31,7 +31,7 @@
static void __init omap_generic_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
/* assume no Mini-AB port */
@@ -99,5 +99,5 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
.reserve = omap_reserve,
.init_irq = omap_generic_init_irq,
.init_machine = omap_generic_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index ba3bd09c4754..cb7fb1aa3dca 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -376,7 +376,7 @@ static struct i2c_board_info __initdata h2_i2c_board_info[] = {
static void __init h2_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static struct omap_usb_config h2_usb_config __initdata = {
@@ -466,5 +466,5 @@ MACHINE_START(OMAP_H2, "TI-H2")
.reserve = omap_reserve,
.init_irq = h2_init_irq,
.init_machine = h2_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index ac48677672ee..31f34875ffad 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -439,7 +439,7 @@ static void __init h3_init(void)
static void __init h3_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static void __init h3_map_io(void)
@@ -454,5 +454,5 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
.reserve = omap_reserve,
.init_irq = h3_init_irq,
.init_machine = h3_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index ba05a51f9408..36e06ea7ec65 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -605,7 +605,7 @@ static void __init htcherald_init_irq(void)
{
printk(KERN_INFO "htcherald_init_irq.\n");
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
MACHINE_START(HERALD, "HTC Herald")
@@ -616,5 +616,5 @@ MACHINE_START(HERALD, "HTC Herald")
.reserve = omap_reserve,
.init_irq = htcherald_init_irq,
.init_machine = htcherald_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 2d9b8cbd7a14..0b1ba462d388 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -292,7 +292,7 @@ static void __init innovator_init_smc91x(void)
static void __init innovator_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
#ifdef CONFIG_ARCH_OMAP15XX
@@ -464,5 +464,5 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
.reserve = omap_reserve,
.init_irq = innovator_init_irq,
.init_machine = innovator_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index cfd084926146..5469ce247ffe 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -51,7 +51,7 @@ static void __init omap_nokia770_init_irq(void)
omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static const unsigned int nokia770_keymap[] = {
@@ -269,5 +269,5 @@ MACHINE_START(NOKIA770, "Nokia 770")
.reserve = omap_reserve,
.init_irq = omap_nokia770_init_irq,
.init_machine = omap_nokia770_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e68dfde1918e..b08a21380772 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -282,7 +282,7 @@ static void __init osk_init_cf(void)
static void __init osk_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static struct omap_usb_config osk_usb_config __initdata = {
@@ -588,5 +588,5 @@ MACHINE_START(OMAP_OSK, "TI-OSK")
.reserve = omap_reserve,
.init_irq = osk_init_irq,
.init_machine = osk_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index c9d38f47845f..459cb6bfed55 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -62,7 +62,7 @@
static void __init omap_palmte_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static const unsigned int palmte_keymap[] = {
@@ -280,5 +280,5 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
.reserve = omap_reserve,
.init_irq = omap_palmte_init_irq,
.init_machine = omap_palmte_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index f04f2d36e7d3..b214f45f646c 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -266,7 +266,7 @@ static struct spi_board_info __initdata palmtt_boardinfo[] = {
static void __init omap_palmtt_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static struct omap_usb_config palmtt_usb_config __initdata = {
@@ -326,5 +326,5 @@ MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
.reserve = omap_reserve,
.init_irq = omap_palmtt_init_irq,
.init_machine = omap_palmtt_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 45f01d2c3a7a..9b0ea48d35fd 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -61,7 +61,7 @@ static void __init
omap_palmz71_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static const unsigned int palmz71_keymap[] = {
@@ -346,5 +346,5 @@ MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
.reserve = omap_reserve,
.init_irq = omap_palmz71_init_irq,
.init_machine = omap_palmz71_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 3c8ee8489458..67acd4142639 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -297,7 +297,7 @@ static void __init omap_perseus2_init(void)
static void __init omap_perseus2_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ 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 = {
@@ -355,5 +355,5 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
.reserve = omap_reserve,
.init_irq = omap_perseus2_init_irq,
.init_machine = omap_perseus2_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 0ad781db4e66..9c3b7c52d9cf 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -411,7 +411,7 @@ static void __init omap_sx1_init(void)
static void __init omap_sx1_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
/*----------------------------------------*/
@@ -426,5 +426,5 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1")
.reserve = omap_reserve,
.init_irq = omap_sx1_init_irq,
.init_machine = omap_sx1_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 65d24204937a..036edc0ee9b6 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -162,7 +162,7 @@ static struct omap_board_config_kernel voiceblue_config[] = {
static void __init voiceblue_init_irq(void)
{
omap1_init_common_hw();
- omap_init_irq();
+ omap1_init_irq();
}
static void __init voiceblue_map_io(void)
@@ -306,5 +306,5 @@ MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
.reserve = omap_reserve,
.init_irq = voiceblue_init_irq,
.init_machine = voiceblue_init,
- .timer = &omap_timer,
+ .timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
index 364137c2042c..399da4ce017b 100644
--- a/arch/arm/mach-omap1/gpio15xx.c
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -34,11 +34,22 @@ static struct __initdata resource omap15xx_mpu_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap15xx_mpuio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP_MPUIO_IO_CNTL,
+ .datain = OMAP_MPUIO_INPUT_LATCH,
+ .dataout = OMAP_MPUIO_OUTPUT,
+ .irqstatus = OMAP_MPUIO_GPIO_INT,
+ .irqenable = OMAP_MPUIO_GPIO_MASKIT,
+ .irqenable_inv = true,
+};
+
static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
.bank_type = METHOD_MPUIO,
.bank_width = 16,
.bank_stride = 1,
+ .regs = &omap15xx_mpuio_regs,
};
static struct platform_device omap15xx_mpu_gpio = {
@@ -64,10 +75,21 @@ static struct __initdata resource omap15xx_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap15xx_gpio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP1510_GPIO_DIR_CONTROL,
+ .datain = OMAP1510_GPIO_DATA_INPUT,
+ .dataout = OMAP1510_GPIO_DATA_OUTPUT,
+ .irqstatus = OMAP1510_GPIO_INT_STATUS,
+ .irqenable = OMAP1510_GPIO_INT_MASK,
+ .irqenable_inv = true,
+};
+
static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
.virtual_irq_start = IH_GPIO_BASE,
.bank_type = METHOD_GPIO_1510,
.bank_width = 16,
+ .regs = &omap15xx_gpio_regs,
};
static struct platform_device omap15xx_gpio = {
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
index 293a246e2824..0f399bd0e70e 100644
--- a/arch/arm/mach-omap1/gpio16xx.c
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -37,11 +37,22 @@ static struct __initdata resource omap16xx_mpu_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap16xx_mpuio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP_MPUIO_IO_CNTL,
+ .datain = OMAP_MPUIO_INPUT_LATCH,
+ .dataout = OMAP_MPUIO_OUTPUT,
+ .irqstatus = OMAP_MPUIO_GPIO_INT,
+ .irqenable = OMAP_MPUIO_GPIO_MASKIT,
+ .irqenable_inv = true,
+};
+
static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
.bank_type = METHOD_MPUIO,
.bank_width = 16,
.bank_stride = 1,
+ .regs = &omap16xx_mpuio_regs,
};
static struct platform_device omap16xx_mpu_gpio = {
@@ -67,10 +78,24 @@ static struct __initdata resource omap16xx_gpio1_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap16xx_gpio_regs = {
+ .revision = OMAP1610_GPIO_REVISION,
+ .direction = OMAP1610_GPIO_DIRECTION,
+ .set_dataout = OMAP1610_GPIO_SET_DATAOUT,
+ .clr_dataout = OMAP1610_GPIO_CLEAR_DATAOUT,
+ .datain = OMAP1610_GPIO_DATAIN,
+ .dataout = OMAP1610_GPIO_DATAOUT,
+ .irqstatus = OMAP1610_GPIO_IRQSTATUS1,
+ .irqenable = OMAP1610_GPIO_IRQENABLE1,
+ .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1,
+ .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1,
+};
+
static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
.virtual_irq_start = IH_GPIO_BASE,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio1 = {
@@ -100,6 +125,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = {
.virtual_irq_start = IH_GPIO_BASE + 16,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio2 = {
@@ -129,6 +155,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = {
.virtual_irq_start = IH_GPIO_BASE + 32,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio3 = {
@@ -158,6 +185,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = {
.virtual_irq_start = IH_GPIO_BASE + 48,
.bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio4 = {
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
index c6ad248d63a6..5ab63eab0ff5 100644
--- a/arch/arm/mach-omap1/gpio7xx.c
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -39,11 +39,22 @@ static struct __initdata resource omap7xx_mpu_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap7xx_mpuio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP_MPUIO_IO_CNTL / 2,
+ .datain = OMAP_MPUIO_INPUT_LATCH / 2,
+ .dataout = OMAP_MPUIO_OUTPUT / 2,
+ .irqstatus = OMAP_MPUIO_GPIO_INT / 2,
+ .irqenable = OMAP_MPUIO_GPIO_MASKIT / 2,
+ .irqenable_inv = true,
+};
+
static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
.bank_type = METHOD_MPUIO,
.bank_width = 32,
.bank_stride = 2,
+ .regs = &omap7xx_mpuio_regs,
};
static struct platform_device omap7xx_mpu_gpio = {
@@ -69,10 +80,21 @@ static struct __initdata resource omap7xx_gpio1_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap7xx_gpio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP7XX_GPIO_DIR_CONTROL,
+ .datain = OMAP7XX_GPIO_DATA_INPUT,
+ .dataout = OMAP7XX_GPIO_DATA_OUTPUT,
+ .irqstatus = OMAP7XX_GPIO_INT_STATUS,
+ .irqenable = OMAP7XX_GPIO_INT_MASK,
+ .irqenable_inv = true,
+};
+
static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
.virtual_irq_start = IH_GPIO_BASE,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio1 = {
@@ -102,6 +124,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = {
.virtual_irq_start = IH_GPIO_BASE + 32,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio2 = {
@@ -131,6 +154,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = {
.virtual_irq_start = IH_GPIO_BASE + 64,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio3 = {
@@ -160,6 +184,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = {
.virtual_irq_start = IH_GPIO_BASE + 96,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio4 = {
@@ -189,6 +214,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = {
.virtual_irq_start = IH_GPIO_BASE + 128,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio5 = {
@@ -218,6 +244,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = {
.virtual_irq_start = IH_GPIO_BASE + 160,
.bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio6 = {
diff --git a/arch/arm/mach-omap1/include/mach/clkdev.h b/arch/arm/mach-omap1/include/mach/clkdev.h
deleted file mode 100644
index ea8640e4603e..000000000000
--- a/arch/arm/mach-omap1/include/mach/clkdev.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap1/include/mach/clkdev.h
- */
-
-#include <plat/clkdev.h>
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 5d3da7a63af3..e2b9c901ab67 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -175,7 +175,7 @@ static struct irq_chip omap_irq_chip = {
.irq_set_wake = omap_wake_irq,
};
-void __init omap_init_irq(void)
+void __init omap1_init_irq(void)
{
int i, j;
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index d9af9811dedd..ab7395d84bc8 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -38,7 +38,7 @@ static void omap1_mcbsp_request(unsigned int id)
* On 1510, 1610 and 1710, McBSP1 and McBSP3
* are DSP public peripherals.
*/
- if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
+ if (id == 0 || id == 2) {
if (dsp_use++ == 0) {
api_clk = clk_get(NULL, "api_ck");
dsp_clk = clk_get(NULL, "dsp_ck");
@@ -59,7 +59,7 @@ static void omap1_mcbsp_request(unsigned int id)
static void omap1_mcbsp_free(unsigned int id)
{
- if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
+ if (id == 0 || id == 2) {
if (--dsp_use == 0) {
if (!IS_ERR(api_clk)) {
clk_disable(api_clk);
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 98ba9784aa15..495b3987d461 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -44,7 +44,7 @@
#include <linux/io.h>
#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
index 334fb8871bc3..943072d5a1d5 100644
--- a/arch/arm/mach-omap1/pm_bus.c
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -32,7 +32,7 @@ static int omap1_pm_runtime_suspend(struct device *dev)
if (ret)
return ret;
- ret = pm_runtime_clk_suspend(dev);
+ ret = pm_clk_suspend(dev);
if (ret) {
pm_generic_runtime_resume(dev);
return ret;
@@ -45,24 +45,24 @@ static int omap1_pm_runtime_resume(struct device *dev)
{
dev_dbg(dev, "%s\n", __func__);
- pm_runtime_clk_resume(dev);
+ pm_clk_resume(dev);
return pm_generic_runtime_resume(dev);
}
-static struct dev_power_domain default_power_domain = {
+static struct dev_pm_domain default_pm_domain = {
.ops = {
.runtime_suspend = omap1_pm_runtime_suspend,
.runtime_resume = omap1_pm_runtime_resume,
USE_PLATFORM_PM_SLEEP_OPS
},
};
-#define OMAP1_PWR_DOMAIN (&default_power_domain)
+#define OMAP1_PM_DOMAIN (&default_pm_domain)
#else
-#define OMAP1_PWR_DOMAIN NULL
+#define OMAP1_PM_DOMAIN NULL
#endif /* CONFIG_PM_RUNTIME */
static struct pm_clk_notifier_block platform_bus_notifier = {
- .pwr_domain = OMAP1_PWR_DOMAIN,
+ .pm_domain = OMAP1_PM_DOMAIN,
.con_ids = { "ick", "fck", NULL, },
};
@@ -71,7 +71,7 @@ static int __init omap1_pm_runtime_init(void)
if (!cpu_class_is_omap1())
return -ENODEV;
- pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+ pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
return 0;
}
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 03e1e1062ad4..a1837771e031 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -297,7 +297,7 @@ static inline int omap_32k_timer_usable(void)
* Timer initialization
* ---------------------------------------------------------------------------
*/
-static void __init omap_timer_init(void)
+static void __init omap1_timer_init(void)
{
if (omap_32k_timer_usable()) {
preferred_sched_clock_init(1);
@@ -307,6 +307,6 @@ static void __init omap_timer_init(void)
}
}
-struct sys_timer omap_timer = {
- .init = omap_timer_init,
+struct sys_timer omap1_timer = {
+ .init = omap1_timer_init,
};
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 13d7b8f145bd..96604a50c4fe 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -183,10 +183,6 @@ static __init void omap_init_32k_timer(void)
bool __init omap_32k_timer_init(void)
{
omap_init_clocksource_32k();
-
-#ifdef CONFIG_OMAP_DM_TIMER
- omap_dm_timer_init();
-#endif
omap_init_32k_timer();
return true;
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 19d5891c48e3..4ae6257b39a4 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -266,9 +266,10 @@ config MACH_OMAP_ZOOM3
select REGULATOR_FIXED_VOLTAGE
config MACH_CM_T35
- bool "CompuLab CM-T35 module"
+ bool "CompuLab CM-T35/CM-T3730 modules"
depends on ARCH_OMAP3
default y
+ select MACH_CM_T3730
select OMAP_PACKAGE_CUS
config MACH_CM_T3517
@@ -277,6 +278,9 @@ config MACH_CM_T3517
default y
select OMAP_PACKAGE_CBB
+config MACH_CM_T3730
+ bool
+
config MACH_IGEP0020
bool "IGEP v2 board"
depends on ARCH_OMAP3
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b14807794401..f34336560437 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,7 +3,7 @@
#
# Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
common.o gpio.o dma.o wd_timer.o
omap-2-3-common = irq.o sdrc.o
@@ -145,9 +145,19 @@ obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o
obj-$(CONFIG_SOC_OMAP2430) += opp2430_data.o
# hwmod data
-obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2420_data.o
-obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2430_data.o
-obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_3xxx_data.o
+obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_ipblock_data.o \
+ omap_hwmod_2xxx_3xxx_ipblock_data.o \
+ omap_hwmod_2xxx_interconnect_data.o \
+ omap_hwmod_2xxx_3xxx_interconnect_data.o \
+ omap_hwmod_2420_data.o
+obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2xxx_ipblock_data.o \
+ omap_hwmod_2xxx_3xxx_ipblock_data.o \
+ omap_hwmod_2xxx_interconnect_data.o \
+ omap_hwmod_2xxx_3xxx_interconnect_data.o \
+ omap_hwmod_2430_data.o
+obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_2xxx_3xxx_ipblock_data.o \
+ omap_hwmod_2xxx_3xxx_interconnect_data.o \
+ omap_hwmod_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4) += omap_hwmod_44xx_data.o
# EMU peripherals
@@ -269,4 +279,4 @@ obj-$(CONFIG_ARCH_OMAP4) += hwspinlock.o
disp-$(CONFIG_OMAP2_DSS) := display.o
obj-y += $(disp-m) $(disp-y)
-obj-y += common-board-devices.o
+obj-y += common-board-devices.o twl-common.o
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 5de6eac0a725..2028464cf5b9 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -260,7 +260,7 @@ MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
.reserve = omap_reserve,
.map_io = omap_2430sdp_map_io,
.init_early = omap_2430sdp_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap2_init_irq,
.init_machine = omap_2430sdp_init,
- .timer = &omap_timer,
+ .timer = &omap2_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 5dac974be625..bd600cfb7f80 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -231,22 +231,6 @@ static void __init omap_3430sdp_init_early(void)
omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
}
-static int sdp3430_batt_table[] = {
-/* 0 C*/
-30800, 29500, 28300, 27100,
-26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
-17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
-11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
-8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
-5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
-4040, 3910, 3790, 3670, 3550
-};
-
-static struct twl4030_bci_platform_data sdp3430_bci_data = {
- .battery_tmp_tbl = sdp3430_batt_table,
- .tblsize = ARRAY_SIZE(sdp3430_batt_table),
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -292,14 +276,6 @@ static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
.setup = sdp3430_twl_gpio_setup,
};
-static struct twl4030_usb_data sdp3430_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_madc_platform_data sdp3430_madc_data = {
- .irq_line = 1,
-};
-
/* regulator consumer mappings */
/* ads7846 on SPI */
@@ -307,16 +283,6 @@ static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = {
REGULATOR_SUPPLY("vcc", "spi1.0"),
};
-static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = {
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
- REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = {
REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
@@ -433,54 +399,10 @@ static struct regulator_init_data sdp3430_vsim = {
.consumer_supplies = sdp3430_vsim_supplies,
};
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data sdp3430_vdac = {
- .constraints = {
- .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(sdp3430_vdda_dac_supplies),
- .consumer_supplies = sdp3430_vdda_dac_supplies,
-};
-
-static struct regulator_init_data sdp3430_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(sdp3430_vpll2_supplies),
- .consumer_supplies = sdp3430_vpll2_supplies,
-};
-
-static struct twl4030_codec_audio_data sdp3430_audio;
-
-static struct twl4030_codec_data sdp3430_codec = {
- .audio_mclk = 26000000,
- .audio = &sdp3430_audio,
-};
-
static struct twl4030_platform_data sdp3430_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
- .bci = &sdp3430_bci_data,
.gpio = &sdp3430_gpio_data,
- .madc = &sdp3430_madc_data,
.keypad = &sdp3430_kp_data,
- .usb = &sdp3430_usb_data,
- .codec = &sdp3430_codec,
.vaux1 = &sdp3430_vaux1,
.vaux2 = &sdp3430_vaux2,
@@ -489,14 +411,21 @@ static struct twl4030_platform_data sdp3430_twldata = {
.vmmc1 = &sdp3430_vmmc1,
.vmmc2 = &sdp3430_vmmc2,
.vsim = &sdp3430_vsim,
- .vdac = &sdp3430_vdac,
- .vpll2 = &sdp3430_vpll2,
};
static int __init omap3430_i2c_init(void)
{
/* i2c1 for PMIC only */
+ omap3_pmic_get_config(&sdp3430_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI |
+ TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+ sdp3430_twldata.vdac->constraints.apply_uV = true;
+ sdp3430_twldata.vpll2->constraints.apply_uV = true;
+ sdp3430_twldata.vpll2->constraints.name = "VDVI";
+
omap3_pmic_init("twl4030", &sdp3430_twldata);
+
/* i2c2 on camera connector (for sensor control) and optional isp1301 */
omap_register_i2c_bus(2, 400, NULL, 0);
/* i2c3 on display connector (for DVI, tfp410) */
@@ -804,7 +733,7 @@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap_3430sdp_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap_3430sdp_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index a5933cc15caa..e4f37b57a0c4 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -219,7 +219,7 @@ MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap_sdp_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap_sdp_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 63de2d396e2d..c7cef44c75d4 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -22,6 +22,7 @@
#include <linux/i2c/twl.h>
#include <linux/gpio_keys.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <linux/leds.h>
#include <linux/leds_pwm.h>
@@ -37,10 +38,10 @@
#include <plat/mmc.h>
#include <plat/omap4-keypad.h>
#include <video/omapdss.h>
+#include <linux/wl12xx.h>
#include "mux.h"
#include "hsmmc.h"
-#include "timer-gp.h"
#include "control.h"
#include "common-board-devices.h"
@@ -52,6 +53,9 @@
#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define GPIO_WIFI_PMENA 54
+#define GPIO_WIFI_IRQ 53
+
static const int sdp4430_keymap[] = {
KEY(0, 0, KEY_E),
KEY(0, 1, KEY_R),
@@ -125,6 +129,64 @@ static const int sdp4430_keymap[] = {
KEY(7, 6, KEY_OK),
KEY(7, 7, KEY_DOWN),
};
+static struct omap_device_pad keypad_pads[] __initdata = {
+ { .name = "kpd_col1.kpd_col1",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "kpd_col1.kpd_col1",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "kpd_col2.kpd_col2",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "kpd_col3.kpd_col3",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "kpd_col4.kpd_col4",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "kpd_col5.kpd_col5",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "gpmc_a23.kpd_col7",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "gpmc_a22.kpd_col6",
+ .enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+ },
+ { .name = "kpd_row0.kpd_row0",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+ { .name = "kpd_row1.kpd_row1",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+ { .name = "kpd_row2.kpd_row2",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+ { .name = "kpd_row3.kpd_row3",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+ { .name = "kpd_row4.kpd_row4",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+ { .name = "kpd_row5.kpd_row5",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+ { .name = "gpmc_a18.kpd_row6",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+ { .name = "gpmc_a19.kpd_row7",
+ .enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+ OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+ },
+};
static struct matrix_keymap_data sdp4430_keymap_data = {
.keymap = sdp4430_keymap,
@@ -136,6 +198,13 @@ static struct omap4_keypad_platform_data sdp4430_keypad_data = {
.rows = 8,
.cols = 8,
};
+
+static struct omap_board_data keypad_data = {
+ .id = 1,
+ .pads = keypad_pads,
+ .pads_cnt = ARRAY_SIZE(keypad_pads),
+};
+
static struct gpio_led sdp4430_gpio_leds[] = {
{
.name = "omap4:green:debug0",
@@ -276,11 +345,40 @@ static struct platform_device sdp4430_lcd_device = {
.id = -1,
};
+static struct regulator_consumer_supply sdp4430_vbat_supply[] = {
+ REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),
+ REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"),
+};
+
+static struct regulator_init_data sdp4430_vbat_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sdp4430_vbat_supply),
+ .consumer_supplies = sdp4430_vbat_supply,
+};
+
+static struct fixed_voltage_config sdp4430_vbat_pdata = {
+ .supply_name = "VBAT",
+ .microvolts = 3750000,
+ .init_data = &sdp4430_vbat_data,
+ .gpio = -EINVAL,
+};
+
+static struct platform_device sdp4430_vbat = {
+ .name = "reg-fixed-voltage",
+ .id = -1,
+ .dev = {
+ .platform_data = &sdp4430_vbat_pdata,
+ },
+};
+
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 = {
@@ -295,9 +393,6 @@ static void __init omap_4430sdp_init_early(void)
{
omap2_init_common_infrastructure();
omap2_init_common_devices(NULL, NULL);
-#ifdef CONFIG_OMAP_32K_TIMER
- omap2_gp_clockevent_set_gptimer(1);
-#endif
}
static struct omap_musb_board_data musb_board_data = {
@@ -306,14 +401,6 @@ static struct omap_musb_board_data musb_board_data = {
.power = 100,
};
-static struct twl4030_usb_data omap4_usbphy_data = {
- .phy_init = omap4430_phy_init,
- .phy_exit = omap4430_phy_exit,
- .phy_power = omap4430_phy_power,
- .phy_set_clock = omap4430_phy_set_clk,
- .phy_suspend = omap4430_phy_suspend,
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 2,
@@ -327,21 +414,52 @@ static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .gpio_cd = -EINVAL,
.gpio_wp = -EINVAL,
},
+ {
+ .mmc = 5,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+ .gpio_cd = -EINVAL,
+ .gpio_wp = -EINVAL,
+ .ocr_mask = MMC_VDD_165_195,
+ .nonremovable = true,
+ },
{} /* Terminator */
};
static struct regulator_consumer_supply sdp4430_vaux_supply[] = {
- {
- .supply = "vmmc",
- .dev_name = "omap_hsmmc.1",
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
+
+static struct regulator_consumer_supply omap4_sdp4430_vmmc5_supply = {
+ .supply = "vmmc",
+ .dev_name = "omap_hsmmc.4",
+};
+
+static struct regulator_init_data sdp4430_vmmc5 = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &omap4_sdp4430_vmmc5_supply,
};
-static struct regulator_consumer_supply sdp4430_vmmc_supply[] = {
- {
- .supply = "vmmc",
- .dev_name = "omap_hsmmc.0",
+
+static struct fixed_voltage_config sdp4430_vwlan = {
+ .supply_name = "vwl1271",
+ .microvolts = 1800000, /* 1.8V */
+ .gpio = GPIO_WIFI_PMENA,
+ .startup_delay = 70000, /* 70msec */
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &sdp4430_vmmc5,
+};
+
+static struct platform_device omap_vwlan_device = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &sdp4430_vwlan,
},
};
@@ -399,65 +517,10 @@ static struct regulator_init_data sdp4430_vaux1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
+ .num_consumer_supplies = ARRAY_SIZE(sdp4430_vaux_supply),
.consumer_supplies = sdp4430_vaux_supply,
};
-static struct regulator_init_data sdp4430_vaux2 = {
- .constraints = {
- .min_uV = 1200000,
- .max_uV = 2800000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data sdp4430_vaux3 = {
- .constraints = {
- .min_uV = 1000000,
- .max_uV = 3000000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-/* VMMC1 for MMC1 card */
-static struct regulator_init_data sdp4430_vmmc = {
- .constraints = {
- .min_uV = 1200000,
- .max_uV = 3000000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = sdp4430_vmmc_supply,
-};
-
-static struct regulator_init_data sdp4430_vpp = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 2500000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
static struct regulator_init_data sdp4430_vusim = {
.constraints = {
.min_uV = 1200000,
@@ -471,74 +534,36 @@ static struct regulator_init_data sdp4430_vusim = {
},
};
-static struct regulator_init_data sdp4430_vana = {
- .constraints = {
- .min_uV = 2100000,
- .max_uV = 2100000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data sdp4430_vcxio = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
+static struct twl4030_codec_data twl6040_codec = {
+ /* single-step ramp for headset and handsfree */
+ .hs_left_step = 0x0f,
+ .hs_right_step = 0x0f,
+ .hf_left_step = 0x1d,
+ .hf_right_step = 0x1d,
};
-static struct regulator_init_data sdp4430_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
+static struct twl4030_vibra_data twl6040_vibra = {
+ .vibldrv_res = 8,
+ .vibrdrv_res = 3,
+ .viblmotor_res = 10,
+ .vibrmotor_res = 10,
+ .vddvibl_uV = 0, /* fixed volt supply - VBAT */
+ .vddvibr_uV = 0, /* fixed volt supply - VBAT */
};
-static struct regulator_init_data sdp4430_vusb = {
- .constraints = {
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data sdp4430_clk32kg = {
- .constraints = {
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
+static struct twl4030_audio_data twl6040_audio = {
+ .codec = &twl6040_codec,
+ .vibra = &twl6040_vibra,
+ .audpwron_gpio = 127,
+ .naudint_irq = OMAP44XX_IRQ_SYS_2N,
+ .irq_base = TWL6040_CODEC_IRQ_BASE,
};
static struct twl4030_platform_data sdp4430_twldata = {
- .irq_base = TWL6030_IRQ_BASE,
- .irq_end = TWL6030_IRQ_END,
-
+ .audio = &twl6040_audio,
/* Regulators */
- .vmmc = &sdp4430_vmmc,
- .vpp = &sdp4430_vpp,
.vusim = &sdp4430_vusim,
- .vana = &sdp4430_vana,
- .vcxio = &sdp4430_vcxio,
- .vdac = &sdp4430_vdac,
- .vusb = &sdp4430_vusb,
.vaux1 = &sdp4430_vaux1,
- .vaux2 = &sdp4430_vaux2,
- .vaux3 = &sdp4430_vaux3,
- .clk32kg = &sdp4430_clk32kg,
- .usb = &omap4_usbphy_data
};
static struct i2c_board_info __initdata sdp4430_i2c_3_boardinfo[] = {
@@ -556,6 +581,16 @@ static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = {
};
static int __init omap4_i2c_init(void)
{
+ omap4_pmic_get_config(&sdp4430_twldata, TWL_COMMON_PDATA_USB,
+ TWL_COMMON_REGULATOR_VDAC |
+ TWL_COMMON_REGULATOR_VAUX2 |
+ TWL_COMMON_REGULATOR_VAUX3 |
+ TWL_COMMON_REGULATOR_VMMC |
+ TWL_COMMON_REGULATOR_VPP |
+ TWL_COMMON_REGULATOR_VANA |
+ TWL_COMMON_REGULATOR_VCXIO |
+ TWL_COMMON_REGULATOR_VUSB |
+ TWL_COMMON_REGULATOR_CLK32KG);
omap4_pmic_init("twl6030", &sdp4430_twldata);
omap_register_i2c_bus(2, 400, NULL, 0);
omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
@@ -723,6 +758,41 @@ static inline void board_serial_init(void)
}
#endif
+static void omap4_sdp4430_wifi_mux_init(void)
+{
+ omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |
+ OMAP_PIN_OFF_WAKEUPENABLE);
+ omap_mux_init_gpio(GPIO_WIFI_PMENA, OMAP_PIN_OUTPUT);
+
+ omap_mux_init_signal("sdmmc5_cmd.sdmmc5_cmd",
+ OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_clk.sdmmc5_clk",
+ OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_dat0.sdmmc5_dat0",
+ OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_dat1.sdmmc5_dat1",
+ OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_dat2.sdmmc5_dat2",
+ OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_dat3.sdmmc5_dat3",
+ OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+
+}
+
+static struct wl12xx_platform_data omap4_sdp4430_wlan_data __initdata = {
+ .irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ),
+ .board_ref_clock = WL12XX_REFCLOCK_26,
+ .board_tcxo_clock = WL12XX_TCXOCLOCK_26,
+};
+
+static void omap4_sdp4430_wifi_init(void)
+{
+ omap4_sdp4430_wifi_mux_init();
+ if (wl12xx_set_platform_data(&omap4_sdp4430_wlan_data))
+ pr_err("Error setting wl12xx data\n");
+ platform_device_register(&omap_vwlan_device);
+}
+
static void __init omap_4430sdp_init(void)
{
int status;
@@ -739,6 +809,7 @@ static void __init omap_4430sdp_init(void)
omap_sfh7741prox_init();
platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
board_serial_init();
+ omap4_sdp4430_wifi_init();
omap4_twl6030_hsmmc_init(mmc);
usb_musb_init(&musb_board_data);
@@ -752,7 +823,7 @@ static void __init omap_4430sdp_init(void)
ARRAY_SIZE(sdp4430_spi_board_info));
}
- status = omap4_keyboard_init(&sdp4430_keypad_data);
+ status = omap4_keyboard_init(&sdp4430_keypad_data, &keypad_data);
if (status)
pr_err("Keypad initialization failed: %d\n", status);
@@ -773,5 +844,5 @@ MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
.init_early = omap_4430sdp_init_early,
.init_irq = gic_init_irq,
.init_machine = omap_4430sdp_init,
- .timer = &omap_timer,
+ .timer = &omap4_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 5e438a77cd72..5f2b55ff04ff 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -104,7 +104,7 @@ MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = am3517_crane_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = am3517_crane_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 63af4171c043..f3006c304150 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -494,7 +494,7 @@ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = am3517_evm_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = am3517_evm_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index b124bdfb4239..70211703ff9f 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -354,7 +354,7 @@ MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
.reserve = omap_reserve,
.map_io = omap_apollon_map_io,
.init_early = omap_apollon_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap2_init_irq,
.init_machine = omap_apollon_init,
- .timer = &omap_timer,
+ .timer = &omap2_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 77456dec93ea..3af8aab435b5 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -1,8 +1,9 @@
/*
- * board-cm-t35.c (CompuLab CM-T35 module)
+ * CompuLab CM-T35/CM-T3730 modules support
*
- * Copyright (C) 2009 CompuLab, Ltd.
- * Author: Mike Rapoport <mike@compulab.co.il>
+ * Copyright (C) 2009-2011 CompuLab, Ltd.
+ * Authors: Mike Rapoport <mike@compulab.co.il>
+ * Igor Grinberg <grinberg@compulab.co.il>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -13,11 +14,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
*/
#include <linux/kernel.h>
@@ -149,12 +145,12 @@ static struct mtd_partition cm_t35_nand_partitions[] = {
},
{
.name = "linux",
- .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x2A0000 */
.size = 32 * NAND_BLOCK_SIZE,
},
{
.name = "rootfs",
- .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x6A0000 */
.size = MTDPART_SIZ_FULL,
},
};
@@ -162,9 +158,7 @@ static struct mtd_partition cm_t35_nand_partitions[] = {
static struct omap_nand_platform_data cm_t35_nand_data = {
.parts = cm_t35_nand_partitions,
.nr_parts = ARRAY_SIZE(cm_t35_nand_partitions),
- .dma_channel = -1, /* disable DMA in OMAP NAND driver */
.cs = 0,
-
};
static void __init cm_t35_init_nand(void)
@@ -337,19 +331,17 @@ static void __init cm_t35_init_display(void)
}
}
-static struct regulator_consumer_supply cm_t35_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply cm_t35_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply cm_t35_vsim_supply = {
- .supply = "vmmc_aux",
+static struct regulator_consumer_supply cm_t35_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply cm_t35_vdac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_consumer_supply cm_t35_vdvi_supply =
- REGULATOR_SUPPLY("vdvi", "omapdss");
+static struct regulator_consumer_supply cm_t35_vdvi_supply[] = {
+ REGULATOR_SUPPLY("vdvi", "omapdss"),
+};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
static struct regulator_init_data cm_t35_vmmc1 = {
@@ -362,8 +354,8 @@ static struct regulator_init_data cm_t35_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &cm_t35_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(cm_t35_vmmc1_supply),
+ .consumer_supplies = cm_t35_vmmc1_supply,
};
/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -377,41 +369,8 @@ static struct regulator_init_data cm_t35_vsim = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &cm_t35_vsim_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data cm_t35_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &cm_t35_vdac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data cm_t35_vpll2 = {
- .constraints = {
- .name = "VDVI",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &cm_t35_vdvi_supply,
-};
-
-static struct twl4030_usb_data cm_t35_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
+ .num_consumer_supplies = ARRAY_SIZE(cm_t35_vsim_supply),
+ .consumer_supplies = cm_t35_vsim_supply,
};
static uint32_t cm_t35_keymap[] = {
@@ -470,9 +429,9 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
if (gpio_request_one(wlan_rst, GPIOF_OUT_INIT_HIGH, "WLAN RST") == 0) {
gpio_export(wlan_rst, 0);
udelay(10);
- gpio_set_value(wlan_rst, 0);
+ gpio_set_value_cansleep(wlan_rst, 0);
udelay(10);
- gpio_set_value(wlan_rst, 1);
+ gpio_set_value_cansleep(wlan_rst, 1);
} else {
pr_err("CM-T35: could not obtain gpio for WiFi reset\n");
}
@@ -481,10 +440,6 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
- /* link regulators to MMC adapters */
- cm_t35_vmmc1_supply.dev = mmc[0].dev;
- cm_t35_vsim_supply.dev = mmc[0].dev;
-
return 0;
}
@@ -496,21 +451,23 @@ static struct twl4030_gpio_platform_data cm_t35_gpio_data = {
};
static struct twl4030_platform_data cm_t35_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
.keypad = &cm_t35_kp_data,
- .usb = &cm_t35_usb_data,
.gpio = &cm_t35_gpio_data,
.vmmc1 = &cm_t35_vmmc1,
.vsim = &cm_t35_vsim,
- .vdac = &cm_t35_vdac,
- .vpll2 = &cm_t35_vpll2,
};
static void __init cm_t35_init_i2c(void)
{
+ omap3_pmic_get_config(&cm_t35_twldata, TWL_COMMON_PDATA_USB,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ cm_t35_twldata.vpll2->constraints.name = "VDVI";
+ cm_t35_twldata.vpll2->num_consumer_supplies =
+ ARRAY_SIZE(cm_t35_vdvi_supply);
+ cm_t35_twldata.vpll2->consumer_supplies = cm_t35_vdvi_supply;
+
omap3_pmic_init("tps65930", &cm_t35_twldata);
}
@@ -578,17 +535,11 @@ static struct omap_board_mux board_mux[] __initdata = {
OMAP3_MUX(UART1_TX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(UART1_RX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
- /* DSS */
+ /* common DSS */
OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_ACBIAS, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
@@ -601,12 +552,6 @@ static struct omap_board_mux board_mux[] __initdata = {
OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA20, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
- OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
/* display controls */
OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -619,19 +564,53 @@ static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
+
+static void __init cm_t3x_common_dss_mux_init(int mux_mode)
+{
+ omap_mux_init_signal("dss_data18", mux_mode);
+ omap_mux_init_signal("dss_data19", mux_mode);
+ omap_mux_init_signal("dss_data20", mux_mode);
+ omap_mux_init_signal("dss_data21", mux_mode);
+ omap_mux_init_signal("dss_data22", mux_mode);
+ omap_mux_init_signal("dss_data23", mux_mode);
+}
+
+static void __init cm_t35_init_mux(void)
+{
+ omap_mux_init_signal("gpio_70", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpio_71", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpio_72", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpio_73", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpio_74", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpio_75", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+ cm_t3x_common_dss_mux_init(OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+}
+
+static void __init cm_t3730_init_mux(void)
+{
+ omap_mux_init_signal("sys_boot0", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("sys_boot1", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("sys_boot3", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("sys_boot4", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("sys_boot5", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("sys_boot6", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+ cm_t3x_common_dss_mux_init(OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+}
+#else
+static inline void cm_t35_init_mux(void) {}
+static inline void cm_t3730_init_mux(void) {}
#endif
static struct omap_board_config_kernel cm_t35_config[] __initdata = {
};
-static void __init cm_t35_init(void)
+static void __init cm_t3x_common_init(void)
{
omap_board_config = cm_t35_config;
omap_board_config_size = ARRAY_SIZE(cm_t35_config);
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
omap_serial_init();
cm_t35_init_i2c();
- cm_t35_init_nand();
omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
cm_t35_init_ethernet();
cm_t35_init_led();
@@ -641,12 +620,35 @@ static void __init cm_t35_init(void)
usbhs_init(&usbhs_bdata);
}
+static void __init cm_t35_init(void)
+{
+ cm_t3x_common_init();
+ cm_t35_init_mux();
+ cm_t35_init_nand();
+}
+
+static void __init cm_t3730_init(void)
+{
+ cm_t3x_common_init();
+ cm_t3730_init_mux();
+}
+
MACHINE_START(CM_T35, "Compulab CM-T35")
.boot_params = 0x80000100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = cm_t35_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = cm_t35_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
+MACHINE_END
+
+MACHINE_START(CM_T3730, "Compulab CM-T3730")
+ .boot_params = 0x80000100,
+ .reserve = omap_reserve,
+ .map_io = omap3_map_io,
+ .init_early = cm_t35_init_early,
+ .init_irq = omap3_init_irq,
+ .init_machine = cm_t3730_init,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index c3a9fd35034a..05c72f4c1b57 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -236,7 +236,6 @@ static struct mtd_partition cm_t3517_nand_partitions[] = {
static struct omap_nand_platform_data cm_t3517_nand_data = {
.parts = cm_t3517_nand_partitions,
.nr_parts = ARRAY_SIZE(cm_t3517_nand_partitions),
- .dma_channel = -1, /* disable DMA in OMAP NAND driver */
.cs = 0,
};
@@ -304,7 +303,7 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = cm_t3517_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = cm_t3517_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 34956ec83296..b6002ec31c6a 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,7 +58,6 @@
#include "mux.h"
#include "hsmmc.h"
-#include "timer-gp.h"
#include "common-board-devices.h"
#define OMAP_DM9000_GPIO_IRQ 25
@@ -130,13 +129,14 @@ static void devkit8000_panel_disable_dvi(struct omap_dss_device *dssdev)
gpio_set_value_cansleep(dssdev->reset_gpio, 0);
}
-static struct regulator_consumer_supply devkit8000_vmmc1_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
-
+static struct regulator_consumer_supply devkit8000_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
/* ads7846 on SPI */
-static struct regulator_consumer_supply devkit8000_vio_supply =
- REGULATOR_SUPPLY("vcc", "spi2.0");
+static struct regulator_consumer_supply devkit8000_vio_supply[] = {
+ REGULATOR_SUPPLY("vcc", "spi2.0"),
+};
static struct panel_generic_dpi_data lcd_panel = {
.name = "generic",
@@ -186,9 +186,6 @@ static struct omap_dss_board_info devkit8000_dss_data = {
.default_device = &devkit8000_lcd_device,
};
-static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
static uint32_t board_keymap[] = {
KEY(0, 0, KEY_1),
KEY(1, 0, KEY_2),
@@ -284,22 +281,8 @@ static struct regulator_init_data devkit8000_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &devkit8000_vmmc1_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data devkit8000_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &devkit8000_vdda_dac_supply,
+ .num_consumer_supplies = ARRAY_SIZE(devkit8000_vmmc1_supply),
+ .consumer_supplies = devkit8000_vmmc1_supply,
};
/* VPLL1 for digital video outputs */
@@ -327,31 +310,14 @@ static struct regulator_init_data devkit8000_vio = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &devkit8000_vio_supply,
-};
-
-static struct twl4030_usb_data devkit8000_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data devkit8000_audio_data;
-
-static struct twl4030_codec_data devkit8000_codec_data = {
- .audio_mclk = 26000000,
- .audio = &devkit8000_audio_data,
+ .num_consumer_supplies = ARRAY_SIZE(devkit8000_vio_supply),
+ .consumer_supplies = devkit8000_vio_supply,
};
static struct twl4030_platform_data devkit8000_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
- .usb = &devkit8000_usb_data,
.gpio = &devkit8000_gpio_data,
- .codec = &devkit8000_codec_data,
.vmmc1 = &devkit8000_vmmc1,
- .vdac = &devkit8000_vdac,
.vpll1 = &devkit8000_vpll1,
.vio = &devkit8000_vio,
.keypad = &devkit8000_kp_data,
@@ -359,6 +325,9 @@ static struct twl4030_platform_data devkit8000_twldata = {
static int __init devkit8000_i2c_init(void)
{
+ omap3_pmic_get_config(&devkit8000_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC);
omap3_pmic_init("tps65930", &devkit8000_twldata);
/* Bus 3 is attached to the DVI port where devices like the pico DLP
* projector don't work reliably with 400kHz */
@@ -438,10 +407,7 @@ static void __init devkit8000_init_early(void)
static void __init devkit8000_init_irq(void)
{
- omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
- omap2_gp_clockevent_set_gptimer(12);
-#endif
+ omap3_init_irq();
}
#define OMAP_DM9000_BASE 0x2c000000
@@ -707,5 +673,5 @@ MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
.init_early = devkit8000_init_early,
.init_irq = devkit8000_init_irq,
.init_machine = devkit8000_init,
- .timer = &omap_timer,
+ .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 729892fdcf2e..aa1b0cbe19d2 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -132,11 +132,7 @@ static struct gpmc_timings nand_timings = {
};
static struct omap_nand_platform_data board_nand_data = {
- .nand_setup = NULL,
.gpmc_t = &nand_timings,
- .dma_channel = -1, /* disable DMA in OMAP NAND driver */
- .dev_ready = NULL,
- .devsize = 0, /* '0' for 8-bit, '1' for 16-bit device */
};
void
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 73e3c31e8508..54db41a84a9b 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -70,7 +70,7 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
.reserve = omap_reserve,
.map_io = omap_generic_map_io,
.init_early = omap_generic_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap2_init_irq,
.init_machine = omap_generic_init,
- .timer = &omap_timer,
+ .timer = &omap2_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index bac7933b8cbb..45de2b319ec9 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -298,7 +298,7 @@ static void __init omap_h4_init_early(void)
static void __init omap_h4_init_irq(void)
{
- omap_init_irq();
+ omap2_init_irq();
}
static struct at24_platform_data m24c01 = {
@@ -388,5 +388,5 @@ MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
.init_early = omap_h4_init_early,
.init_irq = omap_h4_init_irq,
.init_machine = omap_h4_init,
- .timer = &omap_timer,
+ .timer = &omap2_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 0c1bfca3f731..35be778caf1b 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -222,8 +222,9 @@ static inline void __init igep2_init_smsc911x(void)
static inline void __init igep2_init_smsc911x(void) { }
#endif
-static struct regulator_consumer_supply igep_vmmc1_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
+static struct regulator_consumer_supply igep_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
static struct regulator_init_data igep_vmmc1 = {
@@ -236,12 +237,13 @@ static struct regulator_init_data igep_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &igep_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(igep_vmmc1_supply),
+ .consumer_supplies = igep_vmmc1_supply,
};
-static struct regulator_consumer_supply igep_vio_supply =
- REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
+static struct regulator_consumer_supply igep_vio_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1"),
+};
static struct regulator_init_data igep_vio = {
.constraints = {
@@ -254,20 +256,21 @@ static struct regulator_init_data igep_vio = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &igep_vio_supply,
+ .num_consumer_supplies = ARRAY_SIZE(igep_vio_supply),
+ .consumer_supplies = igep_vio_supply,
};
-static struct regulator_consumer_supply igep_vmmc2_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply igep_vmmc2_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
static struct regulator_init_data igep_vmmc2 = {
.constraints = {
.valid_modes_mask = REGULATOR_MODE_NORMAL,
.always_on = 1,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &igep_vmmc2_supply,
+ .num_consumer_supplies = ARRAY_SIZE(igep_vmmc2_supply),
+ .consumer_supplies = igep_vmmc2_supply,
};
static struct fixed_voltage_config igep_vwlan = {
@@ -440,10 +443,6 @@ static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = {
.setup = igep_twl_gpio_setup,
};
-static struct twl4030_usb_data igep_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
static int igep2_enable_dvi(struct omap_dss_device *dssdev)
{
gpio_direction_output(IGEP2_GPIO_DVI_PUP, 1);
@@ -480,26 +479,6 @@ static struct omap_dss_board_info igep2_dss_data = {
.default_device = &igep2_dvi_device,
};
-static struct regulator_consumer_supply igep2_vpll2_supplies[] = {
- REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_init_data igep2_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(igep2_vpll2_supplies),
- .consumer_supplies = igep2_vpll2_supplies,
-};
-
static void __init igep2_display_init(void)
{
int err = gpio_request_one(IGEP2_GPIO_DVI_PUP, GPIOF_OUT_INIT_HIGH,
@@ -519,13 +498,6 @@ static void __init igep_init_early(void)
m65kxxxxam_sdrc_params);
}
-static struct twl4030_codec_audio_data igep2_audio_data;
-
-static struct twl4030_codec_data igep2_codec_data = {
- .audio_mclk = 26000000,
- .audio = &igep2_audio_data,
-};
-
static int igep2_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT),
@@ -558,11 +530,7 @@ static struct twl4030_keypad_data igep2_keypad_pdata = {
};
static struct twl4030_platform_data igep_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
- .usb = &igep_usb_data,
.gpio = &igep_twl4030_gpio_pdata,
.vmmc1 = &igep_vmmc1,
.vio = &igep_vio,
@@ -578,6 +546,8 @@ static void __init igep_i2c_init(void)
{
int ret;
+ omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_USB, 0);
+
if (machine_is_igep0020()) {
/*
* Bus 3 is attached to the DVI port where devices like the
@@ -588,9 +558,12 @@ static void __init igep_i2c_init(void)
if (ret)
pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret);
- igep_twldata.codec = &igep2_codec_data;
igep_twldata.keypad = &igep2_keypad_pdata;
- igep_twldata.vpll2 = &igep2_vpll2;
+ /* Get common pmic data */
+ omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VPLL2);
+ igep_twldata.vpll2->constraints.apply_uV = true;
+ igep_twldata.vpll2->constraints.name = "VDVI";
}
omap3_pmic_init("twl4030", &igep_twldata);
@@ -703,9 +676,9 @@ MACHINE_START(IGEP0020, "IGEP v2 board")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = igep_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = igep_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
MACHINE_START(IGEP0030, "IGEP OMAP3 module")
@@ -713,7 +686,7 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = igep_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = igep_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index f7d6038075f0..218764c9377e 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -199,22 +199,14 @@ static void __init omap_ldp_init_early(void)
omap2_init_common_devices(NULL, NULL);
}
-static struct twl4030_usb_data ldp_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
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,
};
-static struct twl4030_madc_platform_data ldp_madc_data = {
- .irq_line = 1,
-};
-
-static struct regulator_consumer_supply ldp_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -228,8 +220,8 @@ static struct regulator_init_data ldp_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &ldp_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(ldp_vmmc1_supply),
+ .consumer_supplies = ldp_vmmc1_supply,
};
/* ads7846 on SPI */
@@ -253,12 +245,7 @@ static struct regulator_init_data ldp_vaux1 = {
};
static struct twl4030_platform_data ldp_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
- .madc = &ldp_madc_data,
- .usb = &ldp_usb_data,
.vmmc1 = &ldp_vmmc1,
.vaux1 = &ldp_vaux1,
.gpio = &ldp_gpio_data,
@@ -267,6 +254,8 @@ static struct twl4030_platform_data ldp_twldata = {
static int __init omap_i2c_init(void)
{
+ omap3_pmic_get_config(&ldp_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC, 0);
omap3_pmic_init("twl4030", &ldp_twldata);
omap_register_i2c_bus(2, 400, NULL, 0);
omap_register_i2c_bus(3, 400, NULL, 0);
@@ -341,8 +330,6 @@ static void __init omap_ldp_init(void)
ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
omap2_hsmmc_init(mmc);
- /* link regulators to MMC adapters */
- ldp_vmmc1_supply.dev = mmc[0].dev;
}
MACHINE_START(OMAP_LDP, "OMAP LDP board")
@@ -350,7 +337,7 @@ MACHINE_START(OMAP_LDP, "OMAP LDP board")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap_ldp_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap_ldp_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 8d74318ed495..e11f0c5d608a 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -699,9 +699,9 @@ MACHINE_START(NOKIA_N800, "Nokia N800")
.reserve = omap_reserve,
.map_io = n8x0_map_io,
.init_early = n8x0_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap2_init_irq,
.init_machine = n8x0_init_machine,
- .timer = &omap_timer,
+ .timer = &omap2_timer,
MACHINE_END
MACHINE_START(NOKIA_N810, "Nokia N810")
@@ -709,9 +709,9 @@ MACHINE_START(NOKIA_N810, "Nokia N810")
.reserve = omap_reserve,
.map_io = n8x0_map_io,
.init_early = n8x0_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap2_init_irq,
.init_machine = n8x0_init_machine,
- .timer = &omap_timer,
+ .timer = &omap2_timer,
MACHINE_END
MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
@@ -719,7 +719,7 @@ MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
.reserve = omap_reserve,
.map_io = n8x0_map_io,
.init_early = n8x0_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap2_init_irq,
.init_machine = n8x0_init_machine,
- .timer = &omap_timer,
+ .timer = &omap2_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7f21d24bd437..32f5f895568a 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -50,7 +50,6 @@
#include "mux.h"
#include "hsmmc.h"
-#include "timer-gp.h"
#include "pm.h"
#include "common-board-devices.h"
@@ -61,7 +60,8 @@
* AXBX = GPIO173, GPIO172, GPIO171: 1 1 1
* C1_3 = GPIO173, GPIO172, GPIO171: 1 1 0
* C4 = GPIO173, GPIO172, GPIO171: 1 0 1
- * XM = GPIO173, GPIO172, GPIO171: 0 0 0
+ * XMA/XMB = GPIO173, GPIO172, GPIO171: 0 0 0
+ * XMC = GPIO173, GPIO172, GPIO171: 0 1 0
*/
enum {
OMAP3BEAGLE_BOARD_UNKN = 0,
@@ -69,14 +69,26 @@ enum {
OMAP3BEAGLE_BOARD_C1_3,
OMAP3BEAGLE_BOARD_C4,
OMAP3BEAGLE_BOARD_XM,
+ OMAP3BEAGLE_BOARD_XMC,
};
static u8 omap3_beagle_version;
-static u8 omap3_beagle_get_rev(void)
-{
- return omap3_beagle_version;
-}
+/*
+ * Board-specific configuration
+ * Defaults to BeagleBoard-xMC
+ */
+static struct {
+ int mmc1_gpio_wp;
+ int usb_pwr_level;
+ int reset_gpio;
+ int usr_button_gpio;
+} beagle_config = {
+ .mmc1_gpio_wp = -EINVAL,
+ .usb_pwr_level = GPIOF_OUT_INIT_LOW,
+ .reset_gpio = 129,
+ .usr_button_gpio = 4,
+};
static struct gpio omap3_beagle_rev_gpios[] __initdata = {
{ 171, GPIOF_IN, "rev_id_0" },
@@ -111,18 +123,32 @@ static void __init omap3_beagle_init_rev(void)
case 7:
printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+ beagle_config.mmc1_gpio_wp = 29;
+ beagle_config.reset_gpio = 170;
+ beagle_config.usr_button_gpio = 7;
break;
case 6:
printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+ beagle_config.mmc1_gpio_wp = 23;
+ beagle_config.reset_gpio = 170;
+ beagle_config.usr_button_gpio = 7;
break;
case 5:
printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+ beagle_config.mmc1_gpio_wp = 23;
+ beagle_config.reset_gpio = 170;
+ beagle_config.usr_button_gpio = 7;
break;
case 0:
- printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM Ax/Bx\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+ beagle_config.usb_pwr_level = GPIOF_OUT_INIT_HIGH;
+ break;
+ case 2:
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
break;
default:
printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
@@ -210,14 +236,6 @@ static struct omap_dss_board_info beagle_dss_data = {
.default_device = &beagle_dvi_device,
};
-static struct regulator_consumer_supply beagle_vdac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_consumer_supply beagle_vdvi_supplies[] = {
- REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
static void __init beagle_display_init(void)
{
int r;
@@ -234,17 +252,17 @@ static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
- .gpio_wp = 29,
+ .gpio_wp = -EINVAL,
},
{} /* Terminator */
};
-static struct regulator_consumer_supply beagle_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply beagle_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply beagle_vsim_supply = {
- .supply = "vmmc_aux",
+static struct regulator_consumer_supply beagle_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
};
static struct gpio_led gpio_leds[];
@@ -252,33 +270,22 @@ static struct gpio_led gpio_leds[];
static int beagle_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
- int r, usb_pwr_level;
-
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
- mmc[0].gpio_wp = -EINVAL;
- } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
- (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
- omap_mux_init_gpio(23, OMAP_PIN_INPUT);
- mmc[0].gpio_wp = 23;
- } else {
- omap_mux_init_gpio(29, OMAP_PIN_INPUT);
- }
+ int r;
+
+ if (beagle_config.mmc1_gpio_wp != -EINVAL)
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+ mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
- /* link regulators to MMC adapters */
- beagle_vmmc1_supply.dev = mmc[0].dev;
- beagle_vsim_supply.dev = mmc[0].dev;
-
/*
* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
* high / others active low)
* DVI reset GPIO is different between beagle revisions
*/
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
- usb_pwr_level = GPIOF_OUT_INIT_HIGH;
- beagle_dvi_device.reset_gpio = 129;
+ /* Valid for all -xM revisions */
+ if (cpu_is_omap3630()) {
/*
* gpio + 1 on Xm controls the TFP410's enable line (active low)
* gpio + 2 control varies depending on the board rev as below:
@@ -296,8 +303,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
pr_err("%s: unable to configure DVI_LDO_EN\n",
__func__);
} else {
- usb_pwr_level = GPIOF_OUT_INIT_LOW;
- beagle_dvi_device.reset_gpio = 170;
/*
* REVISIT: need ehci-omap hooks for external VBUS
* power switch and overcurrent detect
@@ -305,8 +310,10 @@ static int beagle_twl_gpio_setup(struct device *dev,
if (gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC"))
pr_err("%s: unable to configure EHCI_nOC\n", __func__);
}
+ beagle_dvi_device.reset_gpio = beagle_config.reset_gpio;
- gpio_request_one(gpio + TWL4030_GPIO_MAX, usb_pwr_level, "nEN_USB_PWR");
+ gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level,
+ "nEN_USB_PWR");
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -336,8 +343,8 @@ static struct regulator_init_data beagle_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(beagle_vmmc1_supply),
+ .consumer_supplies = beagle_vmmc1_supply,
};
/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -351,62 +358,15 @@ static struct regulator_init_data beagle_vsim = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vsim_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data beagle_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vdac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data beagle_vpll2 = {
- .constraints = {
- .name = "VDVI",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(beagle_vdvi_supplies),
- .consumer_supplies = beagle_vdvi_supplies,
-};
-
-static struct twl4030_usb_data beagle_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data beagle_audio_data;
-
-static struct twl4030_codec_data beagle_codec_data = {
- .audio_mclk = 26000000,
- .audio = &beagle_audio_data,
+ .num_consumer_supplies = ARRAY_SIZE(beagle_vsim_supply),
+ .consumer_supplies = beagle_vsim_supply,
};
static struct twl4030_platform_data beagle_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
- .usb = &beagle_usb_data,
.gpio = &beagle_gpio_data,
- .codec = &beagle_codec_data,
.vmmc1 = &beagle_vmmc1,
.vsim = &beagle_vsim,
- .vdac = &beagle_vdac,
- .vpll2 = &beagle_vpll2,
};
static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
@@ -417,6 +377,12 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
static int __init omap3_beagle_i2c_init(void)
{
+ omap3_pmic_get_config(&beagle_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ beagle_twldata.vpll2->constraints.name = "VDVI";
+
omap3_pmic_init("twl4030", &beagle_twldata);
/* Bus 3 is attached to the DVI port where devices like the pico DLP
* projector don't work reliably with 400kHz */
@@ -458,7 +424,8 @@ static struct platform_device leds_gpio = {
static struct gpio_keys_button gpio_buttons[] = {
{
.code = BTN_EXTRA,
- .gpio = 7,
+ /* Dynamically assigned depending on board */
+ .gpio = -EINVAL,
.desc = "user",
.wakeup = 1,
},
@@ -486,10 +453,7 @@ static void __init omap3_beagle_init_early(void)
static void __init omap3_beagle_init_irq(void)
{
- omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
- omap2_gp_clockevent_set_gptimer(12);
-#endif
+ omap3_init_irq();
}
static struct platform_device *omap3_beagle_devices[] __initdata = {
@@ -525,8 +489,8 @@ static void __init beagle_opp_init(void)
return;
}
- /* Custom OPP enabled for XM */
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+ /* Custom OPP enabled for all xM versions */
+ if (cpu_is_omap3630()) {
struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
struct omap_hwmod *dh = omap_hwmod_lookup("iva");
struct device *dev;
@@ -566,6 +530,9 @@ static void __init omap3_beagle_init(void)
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap3_beagle_init_rev();
omap3_beagle_i2c_init();
+
+ gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
+
platform_add_devices(omap3_beagle_devices,
ARRAY_SIZE(omap3_beagle_devices));
omap_display_init(&beagle_dss_data);
@@ -599,5 +566,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
.init_early = omap3_beagle_init_early,
.init_irq = omap3_beagle_init_irq,
.init_machine = omap3_beagle_init,
- .timer = &omap_timer,
+ .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 b4d43464a303..c452b3f3331a 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -273,12 +273,12 @@ static struct omap_dss_board_info omap3_evm_dss_data = {
.default_device = &omap3_evm_lcd_device,
};
-static struct regulator_consumer_supply omap3evm_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply omap3evm_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply omap3evm_vsim_supply = {
- .supply = "vmmc_aux",
+static struct regulator_consumer_supply omap3evm_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -292,8 +292,8 @@ static struct regulator_init_data omap3evm_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap3evm_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap3evm_vmmc1_supply),
+ .consumer_supplies = omap3evm_vmmc1_supply,
};
/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -307,8 +307,8 @@ static struct regulator_init_data omap3evm_vsim = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap3evm_vsim_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap3evm_vsim_supply),
+ .consumer_supplies = omap3evm_vsim_supply,
};
static struct omap2_hsmmc_info mmc[] = {
@@ -365,10 +365,6 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
- /* link regulators to MMC adapters */
- omap3evm_vmmc1_supply.dev = mmc[0].dev;
- omap3evm_vsim_supply.dev = mmc[0].dev;
-
/*
* Most GPIOs are for USB OTG. Some are mostly sent to
* the P2 connector; notably LEDA for the LCD backlight.
@@ -400,10 +396,6 @@ static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
.setup = omap3evm_twl_gpio_setup,
};
-static struct twl4030_usb_data omap3evm_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
static uint32_t board_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_DOWN),
@@ -438,58 +430,10 @@ static struct twl4030_keypad_data omap3evm_kp_data = {
.rep = 1,
};
-static struct twl4030_madc_platform_data omap3evm_madc_data = {
- .irq_line = 1,
-};
-
-static struct twl4030_codec_audio_data omap3evm_audio_data;
-
-static struct twl4030_codec_data omap3evm_codec_data = {
- .audio_mclk = 26000000,
- .audio = &omap3evm_audio_data,
-};
-
-static struct regulator_consumer_supply omap3_evm_vdda_dac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data omap3_evm_vdac = {
- .constraints = {
- .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 = 1,
- .consumer_supplies = &omap3_evm_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_evm_vpll2_supplies[] = {
- REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_init_data omap3_evm_vpll2 = {
- .constraints = {
- .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(omap3_evm_vpll2_supplies),
- .consumer_supplies = omap3_evm_vpll2_supplies,
-};
-
/* ads7846 on SPI */
-static struct regulator_consumer_supply omap3evm_vio_supply =
- REGULATOR_SUPPLY("vcc", "spi1.0");
+static struct regulator_consumer_supply omap3evm_vio_supply[] = {
+ REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
/* VIO for ads7846 */
static struct regulator_init_data omap3evm_vio = {
@@ -502,8 +446,8 @@ static struct regulator_init_data omap3evm_vio = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap3evm_vio_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap3evm_vio_supply),
+ .consumer_supplies = omap3evm_vio_supply,
};
#ifdef CONFIG_WL12XX_PLATFORM_DATA
@@ -511,16 +455,17 @@ static struct regulator_init_data omap3evm_vio = {
#define OMAP3EVM_WLAN_PMENA_GPIO (150)
#define OMAP3EVM_WLAN_IRQ_GPIO (149)
-static struct regulator_consumer_supply omap3evm_vmmc2_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply omap3evm_vmmc2_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
/* VMMC2 for driving the WL12xx module */
static struct regulator_init_data omap3evm_vmmc2 = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap3evm_vmmc2_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap3evm_vmmc2_supply),
+ .consumer_supplies = omap3evm_vmmc2_supply,
};
static struct fixed_voltage_config omap3evm_vwlan = {
@@ -548,17 +493,9 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
#endif
static struct twl4030_platform_data omap3evm_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
.keypad = &omap3evm_kp_data,
- .madc = &omap3evm_madc_data,
- .usb = &omap3evm_usb_data,
.gpio = &omap3evm_gpio_data,
- .codec = &omap3evm_codec_data,
- .vdac = &omap3_evm_vdac,
- .vpll2 = &omap3_evm_vpll2,
.vio = &omap3evm_vio,
.vmmc1 = &omap3evm_vmmc1,
.vsim = &omap3evm_vsim,
@@ -566,6 +503,14 @@ static struct twl4030_platform_data omap3evm_twldata = {
static int __init omap3_evm_i2c_init(void)
{
+ omap3_pmic_get_config(&omap3evm_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+ TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ omap3evm_twldata.vdac->constraints.apply_uV = true;
+ omap3evm_twldata.vpll2->constraints.apply_uV = true;
+
omap3_pmic_init("twl4030", &omap3evm_twldata);
omap_register_i2c_bus(2, 400, NULL, 0);
omap_register_i2c_bus(3, 400, NULL, 0);
@@ -740,7 +685,7 @@ MACHINE_START(OMAP3EVM, "OMAP3 EVM")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap3_evm_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap3_evm_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 60d9be49dbab..703aeb5b8fd4 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -35,7 +35,6 @@
#include "mux.h"
#include "hsmmc.h"
-#include "timer-gp.h"
#include "control.h"
#include "common-board-devices.h"
@@ -55,8 +54,8 @@
#define OMAP3_TORPEDO_MMC_GPIO_CD 127
#define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ 129
-static struct regulator_consumer_supply omap3logic_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -71,8 +70,8 @@ static struct regulator_init_data omap3logic_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap3logic_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap3logic_vmmc1_supply),
+ .consumer_supplies = omap3logic_vmmc1_supply,
};
static struct twl4030_gpio_platform_data omap3logic_gpio_data = {
@@ -130,8 +129,6 @@ static void __init board_mmc_init(void)
}
omap2_hsmmc_init(board_mmc_info);
- /* link regulators to MMC adapters */
- omap3logic_vmmc1_supply.dev = board_mmc_info[0].dev;
}
static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
@@ -215,16 +212,16 @@ MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.init_early = omap3logic_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap3logic_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.init_early = omap3logic_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap3logic_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 23f71d40883e..080d7bd6795e 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -320,17 +320,17 @@ static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
.setup = omap3pandora_twl_gpio_setup,
};
-static struct regulator_consumer_supply pandora_vmmc1_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
-
-static struct regulator_consumer_supply pandora_vmmc2_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply pandora_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
-static struct regulator_consumer_supply pandora_vmmc3_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2");
+static struct regulator_consumer_supply pandora_vmmc2_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1")
+};
-static struct regulator_consumer_supply pandora_vdda_dac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
+static struct regulator_consumer_supply pandora_vmmc3_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"),
+};
static struct regulator_consumer_supply pandora_vdds_supplies[] = {
REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
@@ -338,11 +338,13 @@ static struct regulator_consumer_supply pandora_vdds_supplies[] = {
REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
};
-static struct regulator_consumer_supply pandora_vcc_lcd_supply =
- REGULATOR_SUPPLY("vcc", "display0");
+static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
+ REGULATOR_SUPPLY("vcc", "display0"),
+};
-static struct regulator_consumer_supply pandora_usb_phy_supply =
- REGULATOR_SUPPLY("hsusb0", "ehci-omap.0");
+static struct regulator_consumer_supply pandora_usb_phy_supply[] = {
+ REGULATOR_SUPPLY("hsusb0", "ehci-omap.0"),
+};
/* ads7846 on SPI and 2 nub controllers on I2C */
static struct regulator_consumer_supply pandora_vaux4_supplies[] = {
@@ -351,8 +353,9 @@ static struct regulator_consumer_supply pandora_vaux4_supplies[] = {
REGULATOR_SUPPLY("vcc", "3-0067"),
};
-static struct regulator_consumer_supply pandora_adac_supply =
- REGULATOR_SUPPLY("vcc", "soc-audio");
+static struct regulator_consumer_supply pandora_adac_supply[] = {
+ REGULATOR_SUPPLY("vcc", "soc-audio"),
+};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
static struct regulator_init_data pandora_vmmc1 = {
@@ -365,8 +368,8 @@ static struct regulator_init_data pandora_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &pandora_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(pandora_vmmc1_supply),
+ .consumer_supplies = pandora_vmmc1_supply,
};
/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
@@ -380,38 +383,8 @@ static struct regulator_init_data pandora_vmmc2 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &pandora_vmmc2_supply,
-};
-
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data pandora_vdac = {
- .constraints = {
- .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 = 1,
- .consumer_supplies = &pandora_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data pandora_vpll2 = {
- .constraints = {
- .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(pandora_vdds_supplies),
- .consumer_supplies = pandora_vdds_supplies,
+ .num_consumer_supplies = ARRAY_SIZE(pandora_vmmc2_supply),
+ .consumer_supplies = pandora_vmmc2_supply,
};
/* VAUX1 for LCD */
@@ -425,8 +398,8 @@ static struct regulator_init_data pandora_vaux1 = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &pandora_vcc_lcd_supply,
+ .num_consumer_supplies = ARRAY_SIZE(pandora_vcc_lcd_supply),
+ .consumer_supplies = pandora_vcc_lcd_supply,
};
/* VAUX2 for USB host PHY */
@@ -440,8 +413,8 @@ static struct regulator_init_data pandora_vaux2 = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &pandora_usb_phy_supply,
+ .num_consumer_supplies = ARRAY_SIZE(pandora_usb_phy_supply),
+ .consumer_supplies = pandora_usb_phy_supply,
};
/* VAUX4 for ads7846 and nubs */
@@ -470,8 +443,8 @@ static struct regulator_init_data pandora_vsim = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &pandora_adac_supply,
+ .num_consumer_supplies = ARRAY_SIZE(pandora_adac_supply),
+ .consumer_supplies = pandora_adac_supply,
};
/* Fixed regulator internal to Wifi module */
@@ -479,8 +452,8 @@ static struct regulator_init_data pandora_vmmc3 = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &pandora_vmmc3_supply,
+ .num_consumer_supplies = ARRAY_SIZE(pandora_vmmc3_supply),
+ .consumer_supplies = pandora_vmmc3_supply,
};
static struct fixed_voltage_config pandora_vwlan = {
@@ -501,29 +474,12 @@ static struct platform_device pandora_vwlan_device = {
},
};
-static struct twl4030_usb_data omap3pandora_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data omap3pandora_audio_data;
-
-static struct twl4030_codec_data omap3pandora_codec_data = {
- .audio_mclk = 26000000,
- .audio = &omap3pandora_audio_data,
-};
-
static struct twl4030_bci_platform_data pandora_bci_data;
static struct twl4030_platform_data omap3pandora_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
.gpio = &omap3pandora_gpio_data,
- .usb = &omap3pandora_usb_data,
- .codec = &omap3pandora_codec_data,
.vmmc1 = &pandora_vmmc1,
.vmmc2 = &pandora_vmmc2,
- .vdac = &pandora_vdac,
- .vpll2 = &pandora_vpll2,
.vaux1 = &pandora_vaux1,
.vaux2 = &pandora_vaux2,
.vaux4 = &pandora_vaux4,
@@ -541,6 +497,17 @@ static struct i2c_board_info __initdata omap3pandora_i2c3_boardinfo[] = {
static int __init omap3pandora_i2c_init(void)
{
+ omap3_pmic_get_config(&omap3pandora_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ omap3pandora_twldata.vdac->constraints.apply_uV = true;
+
+ omap3pandora_twldata.vpll2->constraints.apply_uV = true;
+ omap3pandora_twldata.vpll2->num_consumer_supplies =
+ ARRAY_SIZE(pandora_vdds_supplies);
+ omap3pandora_twldata.vpll2->consumer_supplies = pandora_vdds_supplies;
+
omap3_pmic_init("tps65950", &omap3pandora_twldata);
/* i2c2 pins are not connected */
omap_register_i2c_bus(3, 100, omap3pandora_i2c3_boardinfo,
@@ -643,7 +610,7 @@ MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap3pandora_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap3pandora_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 0c108a212ea2..8e104980ea26 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -52,7 +52,6 @@
#include "sdram-micron-mt46h32m32lf-6.h"
#include "mux.h"
#include "hsmmc.h"
-#include "timer-gp.h"
#include "common-board-devices.h"
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
@@ -206,12 +205,12 @@ static struct omap_dss_board_info omap3_stalker_dss_data = {
.default_device = &omap3_stalker_dvi_device,
};
-static struct regulator_consumer_supply omap3stalker_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply omap3stalker_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply omap3stalker_vsim_supply = {
- .supply = "vmmc_aux",
+static struct regulator_consumer_supply omap3stalker_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -224,8 +223,8 @@ static struct regulator_init_data omap3stalker_vmmc1 = {
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap3stalker_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap3stalker_vmmc1_supply),
+ .consumer_supplies = omap3stalker_vmmc1_supply,
};
/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -238,8 +237,8 @@ static struct regulator_init_data omap3stalker_vsim = {
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap3stalker_vsim_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap3stalker_vsim_supply),
+ .consumer_supplies = omap3stalker_vsim_supply,
};
static struct omap2_hsmmc_info mmc[] = {
@@ -321,10 +320,6 @@ omap3stalker_twl_gpio_setup(struct device *dev,
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
- /* link regulators to MMC adapters */
- omap3stalker_vmmc1_supply.dev = mmc[0].dev;
- omap3stalker_vsim_supply.dev = mmc[0].dev;
-
/*
* Most GPIOs are for USB OTG. Some are mostly sent to
* the P2 connector; notably LEDA for the LCD backlight.
@@ -354,10 +349,6 @@ static struct twl4030_gpio_platform_data omap3stalker_gpio_data = {
.setup = omap3stalker_twl_gpio_setup,
};
-static struct twl4030_usb_data omap3stalker_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
static uint32_t board_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_DOWN),
@@ -392,68 +383,10 @@ static struct twl4030_keypad_data omap3stalker_kp_data = {
.rep = 1,
};
-static struct twl4030_madc_platform_data omap3stalker_madc_data = {
- .irq_line = 1,
-};
-
-static struct twl4030_codec_audio_data omap3stalker_audio_data;
-
-static struct twl4030_codec_data omap3stalker_codec_data = {
- .audio_mclk = 26000000,
- .audio = &omap3stalker_audio_data,
-};
-
-static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data omap3_stalker_vdac = {
- .constraints = {
- .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 = 1,
- .consumer_supplies = &omap3_stalker_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_stalker_vpll2_supplies[] = {
- REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_init_data omap3_stalker_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(omap3_stalker_vpll2_supplies),
- .consumer_supplies = omap3_stalker_vpll2_supplies,
-};
-
static struct twl4030_platform_data omap3stalker_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
.keypad = &omap3stalker_kp_data,
- .madc = &omap3stalker_madc_data,
- .usb = &omap3stalker_usb_data,
.gpio = &omap3stalker_gpio_data,
- .codec = &omap3stalker_codec_data,
- .vdac = &omap3_stalker_vdac,
- .vpll2 = &omap3_stalker_vpll2,
.vmmc1 = &omap3stalker_vmmc1,
.vsim = &omap3stalker_vsim,
};
@@ -474,6 +407,15 @@ static struct i2c_board_info __initdata omap3stalker_i2c_boardinfo3[] = {
static int __init omap3_stalker_i2c_init(void)
{
+ omap3_pmic_get_config(&omap3stalker_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+ TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ omap3stalker_twldata.vdac->constraints.apply_uV = true;
+ omap3stalker_twldata.vpll2->constraints.apply_uV = true;
+ omap3stalker_twldata.vpll2->constraints.name = "VDVI";
+
omap3_pmic_init("twl4030", &omap3stalker_twldata);
omap_register_i2c_bus(2, 400, NULL, 0);
omap_register_i2c_bus(3, 400, omap3stalker_i2c_boardinfo3,
@@ -494,10 +436,7 @@ static void __init omap3_stalker_init_early(void)
static void __init omap3_stalker_init_irq(void)
{
- omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
- omap2_gp_clockevent_set_gptimer(12);
-#endif
+ omap3_init_irq();
}
static struct platform_device *omap3_stalker_devices[] __initdata = {
@@ -560,5 +499,5 @@ MACHINE_START(SBC3530, "OMAP3 STALKER")
.init_early = omap3_stalker_init_early,
.init_irq = omap3_stalker_init_irq,
.init_machine = omap3_stalker_init,
- .timer = &omap_timer,
+ .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 5f649faf7377..852ea0464057 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -51,7 +51,6 @@
#include "mux.h"
#include "hsmmc.h"
-#include "timer-gp.h"
#include "common-board-devices.h"
#include <asm/setup.h>
@@ -114,12 +113,12 @@ static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = {
.ctrl_name = "internal",
};
-static struct regulator_consumer_supply touchbook_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply touchbook_vsim_supply = {
- .supply = "vmmc_aux",
+static struct regulator_consumer_supply touchbook_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
};
static struct gpio_led gpio_leds[];
@@ -137,10 +136,6 @@ static int touchbook_twl_gpio_setup(struct device *dev,
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
- /* link regulators to MMC adapters */
- touchbook_vmmc1_supply.dev = mmc[0].dev;
- touchbook_vsim_supply.dev = mmc[0].dev;
-
/* REVISIT: need ehci-omap hooks for external VBUS
* power switch and overcurrent detect
*/
@@ -167,14 +162,18 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = {
.setup = touchbook_twl_gpio_setup,
};
-static struct regulator_consumer_supply touchbook_vdac_supply = {
+static struct regulator_consumer_supply touchbook_vdac_supply[] = {
+{
.supply = "vdac",
.dev = &omap3_touchbook_lcd_device.dev,
+},
};
-static struct regulator_consumer_supply touchbook_vdvi_supply = {
+static struct regulator_consumer_supply touchbook_vdvi_supply[] = {
+{
.supply = "vdvi",
.dev = &omap3_touchbook_lcd_device.dev,
+},
};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -188,8 +187,8 @@ static struct regulator_init_data touchbook_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &touchbook_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(touchbook_vmmc1_supply),
+ .consumer_supplies = touchbook_vmmc1_supply,
};
/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -203,62 +202,15 @@ static struct regulator_init_data touchbook_vsim = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &touchbook_vsim_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data touchbook_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &touchbook_vdac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data touchbook_vpll2 = {
- .constraints = {
- .name = "VDVI",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &touchbook_vdvi_supply,
-};
-
-static struct twl4030_usb_data touchbook_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data touchbook_audio_data;
-
-static struct twl4030_codec_data touchbook_codec_data = {
- .audio_mclk = 26000000,
- .audio = &touchbook_audio_data,
+ .num_consumer_supplies = ARRAY_SIZE(touchbook_vsim_supply),
+ .consumer_supplies = touchbook_vsim_supply,
};
static struct twl4030_platform_data touchbook_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
- .usb = &touchbook_usb_data,
.gpio = &touchbook_gpio_data,
- .codec = &touchbook_codec_data,
.vmmc1 = &touchbook_vmmc1,
.vsim = &touchbook_vsim,
- .vdac = &touchbook_vdac,
- .vpll2 = &touchbook_vpll2,
};
static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
@@ -270,8 +222,20 @@ static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
static int __init omap3_touchbook_i2c_init(void)
{
/* Standard TouchBook bus */
- omap3_pmic_init("twl4030", &touchbook_twldata);
+ omap3_pmic_get_config(&touchbook_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ touchbook_twldata.vdac->num_consumer_supplies =
+ ARRAY_SIZE(touchbook_vdac_supply);
+ touchbook_twldata.vdac->consumer_supplies = touchbook_vdac_supply;
+ touchbook_twldata.vpll2->constraints.name = "VDVI";
+ touchbook_twldata.vpll2->num_consumer_supplies =
+ ARRAY_SIZE(touchbook_vdvi_supply);
+ touchbook_twldata.vpll2->consumer_supplies = touchbook_vdvi_supply;
+
+ omap3_pmic_init("twl4030", &touchbook_twldata);
/* Additional TouchBook bus */
omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo,
ARRAY_SIZE(touchBook_i2c_boardinfo));
@@ -371,10 +335,7 @@ static void __init omap3_touchbook_init_early(void)
static void __init omap3_touchbook_init_irq(void)
{
- omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
- omap2_gp_clockevent_set_gptimer(12);
-#endif
+ omap3_init_irq();
}
static struct platform_device *omap3_touchbook_devices[] __initdata = {
@@ -449,5 +410,5 @@ MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
.init_early = omap3_touchbook_init_early,
.init_irq = omap3_touchbook_init_irq,
.init_machine = omap3_touchbook_init,
- .timer = &omap_timer,
+ .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 0cfe2005cb50..9aaa96057666 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -41,7 +41,6 @@
#include <plat/usb.h>
#include <plat/mmc.h>
#include <video/omap-panel-generic-dpi.h>
-#include "timer-gp.h"
#include "hsmmc.h"
#include "control.h"
@@ -155,14 +154,6 @@ static struct omap_musb_board_data musb_board_data = {
.power = 100,
};
-static struct twl4030_usb_data omap4_usbphy_data = {
- .phy_init = omap4430_phy_init,
- .phy_exit = omap4430_phy_exit,
- .phy_power = omap4430_phy_power,
- .phy_set_clock = omap4430_phy_set_clk,
- .phy_suspend = omap4430_phy_suspend,
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -182,24 +173,16 @@ static struct omap2_hsmmc_info mmc[] = {
{} /* Terminator */
};
-static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
- {
- .supply = "vmmc",
- .dev_name = "omap_hsmmc.0",
- },
-};
-
-static struct regulator_consumer_supply omap4_panda_vmmc5_supply = {
- .supply = "vmmc",
- .dev_name = "omap_hsmmc.4",
+static struct regulator_consumer_supply omap4_panda_vmmc5_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.4"),
};
static struct regulator_init_data panda_vmmc5 = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap4_panda_vmmc5_supply,
+ .num_consumer_supplies = ARRAY_SIZE(omap4_panda_vmmc5_supply),
+ .consumer_supplies = omap4_panda_vmmc5_supply,
};
static struct fixed_voltage_config panda_vwlan = {
@@ -274,128 +257,8 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
return 0;
}
-static struct regulator_init_data omap4_panda_vaux2 = {
- .constraints = {
- .min_uV = 1200000,
- .max_uV = 2800000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vaux3 = {
- .constraints = {
- .min_uV = 1000000,
- .max_uV = 3000000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-/* VMMC1 for MMC1 card */
-static struct regulator_init_data omap4_panda_vmmc = {
- .constraints = {
- .min_uV = 1200000,
- .max_uV = 3000000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = omap4_panda_vmmc_supply,
-};
-
-static struct regulator_init_data omap4_panda_vpp = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 2500000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vana = {
- .constraints = {
- .min_uV = 2100000,
- .max_uV = 2100000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vcxio = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vusb = {
- .constraints = {
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_clk32kg = {
- .constraints = {
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct twl4030_platform_data omap4_panda_twldata = {
- .irq_base = TWL6030_IRQ_BASE,
- .irq_end = TWL6030_IRQ_END,
-
- /* Regulators */
- .vmmc = &omap4_panda_vmmc,
- .vpp = &omap4_panda_vpp,
- .vana = &omap4_panda_vana,
- .vcxio = &omap4_panda_vcxio,
- .vdac = &omap4_panda_vdac,
- .vusb = &omap4_panda_vusb,
- .vaux2 = &omap4_panda_vaux2,
- .vaux3 = &omap4_panda_vaux3,
- .clk32kg = &omap4_panda_clk32kg,
- .usb = &omap4_usbphy_data,
-};
+/* Panda board uses the common PMIC configuration */
+static struct twl4030_platform_data omap4_panda_twldata;
/*
* Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
@@ -409,6 +272,16 @@ static struct i2c_board_info __initdata panda_i2c_eeprom[] = {
static int __init omap4_panda_i2c_init(void)
{
+ omap4_pmic_get_config(&omap4_panda_twldata, TWL_COMMON_PDATA_USB,
+ TWL_COMMON_REGULATOR_VDAC |
+ TWL_COMMON_REGULATOR_VAUX2 |
+ TWL_COMMON_REGULATOR_VAUX3 |
+ TWL_COMMON_REGULATOR_VMMC |
+ TWL_COMMON_REGULATOR_VPP |
+ TWL_COMMON_REGULATOR_VANA |
+ TWL_COMMON_REGULATOR_VCXIO |
+ TWL_COMMON_REGULATOR_VUSB |
+ TWL_COMMON_REGULATOR_CLK32KG);
omap4_pmic_init("twl6030", &omap4_panda_twldata);
omap_register_i2c_bus(2, 400, NULL, 0);
/*
@@ -716,5 +589,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
.init_early = omap4_panda_init_early,
.init_irq = gic_init_irq,
.init_machine = omap4_panda_init,
- .timer = &omap_timer,
+ .timer = &omap4_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 175e1ab2b04d..f949a9954d76 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -74,15 +74,16 @@
defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
/* fixed regulator for ads7846 */
-static struct regulator_consumer_supply ads7846_supply =
- REGULATOR_SUPPLY("vcc", "spi1.0");
+static struct regulator_consumer_supply ads7846_supply[] = {
+ REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
static struct regulator_init_data vads7846_regulator = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &ads7846_supply,
+ .num_consumer_supplies = ARRAY_SIZE(ads7846_supply),
+ .consumer_supplies = ads7846_supply,
};
static struct fixed_voltage_config vads7846 = {
@@ -264,14 +265,6 @@ static struct omap_dss_board_info overo_dss_data = {
.default_device = &overo_dvi_device,
};
-static struct regulator_consumer_supply overo_vdda_dac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_consumer_supply overo_vdds_dsi_supply[] = {
- REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
static struct mtd_partition overo_nand_partitions[] = {
{
.name = "xloader",
@@ -319,8 +312,8 @@ static struct omap2_hsmmc_info mmc[] = {
{} /* Terminator */
};
-static struct regulator_consumer_supply overo_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply overo_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
@@ -415,8 +408,6 @@ static int overo_twl_gpio_setup(struct device *dev,
{
omap2_hsmmc_init(mmc);
- overo_vmmc1_supply.dev = mmc[0].dev;
-
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -433,10 +424,6 @@ static struct twl4030_gpio_platform_data overo_gpio_data = {
.setup = overo_twl_gpio_setup,
};
-static struct twl4030_usb_data overo_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
static struct regulator_init_data overo_vmmc1 = {
.constraints = {
.min_uV = 1850000,
@@ -447,59 +434,23 @@ static struct regulator_init_data overo_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &overo_vmmc1_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data overo_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &overo_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data overo_vpll2 = {
- .constraints = {
- .name = "VDVI",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(overo_vdds_dsi_supply),
- .consumer_supplies = overo_vdds_dsi_supply,
-};
-
-static struct twl4030_codec_audio_data overo_audio_data;
-
-static struct twl4030_codec_data overo_codec_data = {
- .audio_mclk = 26000000,
- .audio = &overo_audio_data,
+ .num_consumer_supplies = ARRAY_SIZE(overo_vmmc1_supply),
+ .consumer_supplies = overo_vmmc1_supply,
};
static struct twl4030_platform_data overo_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
.gpio = &overo_gpio_data,
- .usb = &overo_usb_data,
- .codec = &overo_codec_data,
.vmmc1 = &overo_vmmc1,
- .vdac = &overo_vdac,
- .vpll2 = &overo_vpll2,
};
static int __init overo_i2c_init(void)
{
+ omap3_pmic_get_config(&overo_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ overo_twldata.vpll2->constraints.name = "VDVI";
+
omap3_pmic_init("tps65950", &overo_twldata);
/* i2c2 pins are used for gpio */
omap_register_i2c_bus(3, 400, NULL, 0);
@@ -568,7 +519,6 @@ static void __init overo_init(void)
usb_musb_init(NULL);
usbhs_init(&usbhs_bdata);
overo_spi_init();
- overo_ads7846_init();
overo_init_smsc911x();
overo_display_init();
overo_init_led();
@@ -615,7 +565,7 @@ MACHINE_START(OVERO, "Gumstix Overo")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = overo_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = overo_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 42d10b12da3c..7dfed24ee12e 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -79,20 +79,14 @@ static struct twl4030_gpio_platform_data rm680_gpio_data = {
.pulldowns = BIT(1) | BIT(2) | BIT(8) | BIT(15),
};
-static struct twl4030_usb_data rm680_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
static struct twl4030_platform_data rm680_twl_data = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
.gpio = &rm680_gpio_data,
- .usb = &rm680_usb_data,
/* add rest of the children here */
};
static void __init rm680_i2c_init(void)
{
+ omap3_pmic_get_config(&rm680_twl_data, TWL_COMMON_PDATA_USB, 0);
omap_pmic_init(1, 2900, "twl5031", INT_34XX_SYS_NIRQ, &rm680_twl_data);
omap_register_i2c_bus(2, 400, NULL, 0);
omap_register_i2c_bus(3, 400, NULL, 0);
@@ -163,7 +157,7 @@ MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
.reserve = omap_reserve,
.map_io = rm680_map_io,
.init_early = rm680_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = rm680_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 88bd6f7705f0..cc503aa89c5e 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -39,6 +39,7 @@
#include <sound/tpa6130a2-plat.h>
#include <media/radio-si4713.h>
#include <media/si4713.h>
+#include <linux/leds-lp5523.h>
#include <../drivers/staging/iio/light/tsl2563.h>
@@ -53,6 +54,7 @@
#define RX51_WL1251_IRQ_GPIO 42
#define RX51_FMTX_RESET_GPIO 163
#define RX51_FMTX_IRQ 53
+#define RX51_LP5523_CHIP_EN_GPIO 41
#define RX51_USB_TRANSCEIVER_RST_GPIO 67
@@ -71,6 +73,64 @@ static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
};
#endif
+#if defined(CONFIG_LEDS_LP5523) || defined(CONFIG_LEDS_LP5523_MODULE)
+static struct lp5523_led_config rx51_lp5523_led_config[] = {
+ {
+ .chan_nr = 0,
+ .led_current = 50,
+ }, {
+ .chan_nr = 1,
+ .led_current = 50,
+ }, {
+ .chan_nr = 2,
+ .led_current = 50,
+ }, {
+ .chan_nr = 3,
+ .led_current = 50,
+ }, {
+ .chan_nr = 4,
+ .led_current = 50,
+ }, {
+ .chan_nr = 5,
+ .led_current = 50,
+ }, {
+ .chan_nr = 6,
+ .led_current = 50,
+ }, {
+ .chan_nr = 7,
+ .led_current = 50,
+ }, {
+ .chan_nr = 8,
+ .led_current = 50,
+ }
+};
+
+static int rx51_lp5523_setup(void)
+{
+ return gpio_request_one(RX51_LP5523_CHIP_EN_GPIO, GPIOF_DIR_OUT,
+ "lp5523_enable");
+}
+
+static void rx51_lp5523_release(void)
+{
+ gpio_free(RX51_LP5523_CHIP_EN_GPIO);
+}
+
+static void rx51_lp5523_enable(bool state)
+{
+ gpio_set_value(RX51_LP5523_CHIP_EN_GPIO, !!state);
+}
+
+static struct lp5523_platform_data rx51_lp5523_platform_data = {
+ .led_config = rx51_lp5523_led_config,
+ .num_channels = ARRAY_SIZE(rx51_lp5523_led_config),
+ .clock_mode = LP5523_CLOCK_AUTO,
+ .setup_resources = rx51_lp5523_setup,
+ .release_resources = rx51_lp5523_release,
+ .enable = rx51_lp5523_enable,
+};
+#endif
+
static struct omap2_mcspi_device_config wl1251_mcspi_config = {
.turbo_mode = 0,
.single_channel = 1,
@@ -288,10 +348,6 @@ static struct twl4030_keypad_data rx51_kp_data = {
.rep = 1,
};
-static struct twl4030_madc_platform_data rx51_madc_data = {
- .irq_line = 1,
-};
-
/* Enable input logic and pull all lines up when eMMC is on. */
static struct omap_board_mux rx51_mmc2_on_mux[] = {
OMAP3_MUX(SDMMC2_CMD, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
@@ -358,14 +414,17 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
{} /* Terminator */
};
-static struct regulator_consumer_supply rx51_vmmc1_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
+static struct regulator_consumer_supply rx51_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
-static struct regulator_consumer_supply rx51_vaux3_supply =
- REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply rx51_vaux3_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
-static struct regulator_consumer_supply rx51_vsim_supply =
- REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
+static struct regulator_consumer_supply rx51_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1"),
+};
static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
/* tlv320aic3x analog supplies */
@@ -395,10 +454,6 @@ static struct regulator_consumer_supply rx51_vaux1_consumers[] = {
REGULATOR_SUPPLY("vdd", "2-0063"),
};
-static struct regulator_consumer_supply rx51_vdac_supply[] = {
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
-};
-
static struct regulator_init_data rx51_vaux1 = {
.constraints = {
.name = "V28",
@@ -452,8 +507,8 @@ static struct regulator_init_data rx51_vaux3_mmc = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &rx51_vaux3_supply,
+ .num_consumer_supplies = ARRAY_SIZE(rx51_vaux3_supply),
+ .consumer_supplies = rx51_vaux3_supply,
};
static struct regulator_init_data rx51_vaux4 = {
@@ -479,8 +534,8 @@ static struct regulator_init_data rx51_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &rx51_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(rx51_vmmc1_supply),
+ .consumer_supplies = rx51_vmmc1_supply,
};
static struct regulator_init_data rx51_vmmc2 = {
@@ -500,24 +555,35 @@ static struct regulator_init_data rx51_vmmc2 = {
.consumer_supplies = rx51_vmmc2_supplies,
};
-static struct regulator_init_data rx51_vsim = {
+static struct regulator_init_data rx51_vpll1 = {
.constraints = {
- .name = "VMMC2_IO_18",
+ .name = "VPLL",
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = true,
+ .always_on = true,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE,
+ },
+};
+
+static struct regulator_init_data rx51_vpll2 = {
+ .constraints = {
+ .name = "VSDI_CSI",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = true,
+ .always_on = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &rx51_vsim_supply,
};
-static struct regulator_init_data rx51_vdac = {
+static struct regulator_init_data rx51_vsim = {
.constraints = {
- .name = "VDAC",
+ .name = "VMMC2_IO_18",
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = true,
@@ -526,8 +592,8 @@ static struct regulator_init_data rx51_vdac = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = rx51_vdac_supply,
+ .num_consumer_supplies = ARRAY_SIZE(rx51_vsim_supply),
+ .consumer_supplies = rx51_vsim_supply,
};
static struct regulator_init_data rx51_vio = {
@@ -544,6 +610,43 @@ static struct regulator_init_data rx51_vio = {
.consumer_supplies = rx51_vio_supplies,
};
+static struct regulator_init_data rx51_vintana1 = {
+ .constraints = {
+ .name = "VINTANA1",
+ .min_uV = 1500000,
+ .max_uV = 1500000,
+ .always_on = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE,
+ },
+};
+
+static struct regulator_init_data rx51_vintana2 = {
+ .constraints = {
+ .name = "VINTANA2",
+ .min_uV = 2750000,
+ .max_uV = 2750000,
+ .apply_uV = true,
+ .always_on = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE,
+ },
+};
+
+static struct regulator_init_data rx51_vintdig = {
+ .constraints = {
+ .name = "VINTDIG",
+ .min_uV = 1500000,
+ .max_uV = 1500000,
+ .always_on = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE,
+ },
+};
+
static struct si4713_platform_data rx51_si4713_i2c_data __initdata_or_module = {
.gpio_reset = RX51_FMTX_RESET_GPIO,
};
@@ -600,10 +703,6 @@ static struct twl4030_gpio_platform_data rx51_gpio_data = {
.setup = rx51_twlgpio_setup,
};
-static struct twl4030_usb_data rx51_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
static struct twl4030_ins sleep_on_seq[] __initdata = {
/*
* Turn off everything
@@ -765,33 +864,32 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
.resource_config = twl4030_rconfig,
};
-struct twl4030_codec_vibra_data rx51_vibra_data __initdata = {
+struct twl4030_vibra_data rx51_vibra_data __initdata = {
.coexist = 0,
};
-struct twl4030_codec_data rx51_codec_data __initdata = {
+struct twl4030_audio_data rx51_audio_data __initdata = {
.audio_mclk = 26000000,
.vibra = &rx51_vibra_data,
};
static struct twl4030_platform_data rx51_twldata __initdata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
.gpio = &rx51_gpio_data,
.keypad = &rx51_kp_data,
- .madc = &rx51_madc_data,
- .usb = &rx51_usb_data,
.power = &rx51_t2scripts_data,
- .codec = &rx51_codec_data,
+ .audio = &rx51_audio_data,
.vaux1 = &rx51_vaux1,
.vaux2 = &rx51_vaux2,
.vaux4 = &rx51_vaux4,
.vmmc1 = &rx51_vmmc1,
+ .vpll1 = &rx51_vpll1,
+ .vpll2 = &rx51_vpll2,
.vsim = &rx51_vsim,
- .vdac = &rx51_vdac,
+ .vintana1 = &rx51_vintana1,
+ .vintana2 = &rx51_vintana2,
+ .vintdig = &rx51_vintdig,
.vio = &rx51_vio,
};
@@ -830,6 +928,12 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
.platform_data = &rx51_tsl2563_platform_data,
},
#endif
+#if defined(CONFIG_LEDS_LP5523) || defined(CONFIG_LEDS_LP5523_MODULE)
+ {
+ I2C_BOARD_INFO("lp5523", 0x32),
+ .platform_data = &rx51_lp5523_platform_data,
+ },
+#endif
{
I2C_BOARD_INFO("tpa6130a2", 0x60),
.platform_data = &rx51_tpa6130a2_data,
@@ -847,6 +951,13 @@ static int __init rx51_i2c_init(void)
rx51_twldata.vaux3 = &rx51_vaux3_cam;
}
rx51_twldata.vmmc2 = &rx51_vmmc2;
+ omap3_pmic_get_config(&rx51_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC,
+ TWL_COMMON_REGULATOR_VDAC);
+
+ rx51_twldata.vdac->constraints.apply_uV = true;
+ rx51_twldata.vdac->constraints.name = "VDAC";
+
omap_pmic_init(1, 2200, "twl5030", INT_34XX_SYS_NIRQ, &rx51_twldata);
omap_register_i2c_bus(2, 100, rx51_peripherals_i2c_board_info_2,
ARRAY_SIZE(rx51_peripherals_i2c_board_info_2));
@@ -973,6 +1084,7 @@ error:
void __init rx51_peripherals_init(void)
{
rx51_i2c_init();
+ regulator_has_full_constraints();
gpmc_onenand_init(board_onenand_data);
board_smc91x_init();
rx51_add_gpio_keys();
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index fec4cac8fa0a..5ea142f9bc97 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -160,7 +160,7 @@ MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
.reserve = rx51_reserve,
.map_io = rx51_map_io,
.init_early = rx51_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = rx51_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index 09fa7bfff8d6..a85d5b0b11da 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -33,11 +33,6 @@ static void __init ti8168_init_early(void)
omap2_init_common_devices(NULL, NULL);
}
-static void __init ti8168_evm_init_irq(void)
-{
- omap_init_irq();
-}
-
static void __init ti8168_evm_init(void)
{
omap_serial_init();
@@ -56,7 +51,7 @@ MACHINE_START(TI8168EVM, "ti8168evm")
.boot_params = 0x80000100,
.map_io = ti8168_evm_map_io,
.init_early = ti8168_init_early,
- .init_irq = ti8168_evm_init_irq,
- .timer = &omap_timer,
+ .init_irq = ti816x_init_irq,
+ .timer = &omap3_timer,
.init_machine = ti8168_evm_init,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index 6402e781c458..369c2eb7715b 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -23,6 +23,7 @@
#define ZOOM_SMSC911X_GPIO 158
#define ZOOM_QUADUART_CS 3
#define ZOOM_QUADUART_GPIO 102
+#define ZOOM_QUADUART_RST_GPIO 152
#define QUART_CLK 1843200
#define DEBUG_BASE 0x08000000
#define ZOOM_ETHR_START DEBUG_BASE
@@ -67,6 +68,14 @@ static inline void __init zoom_init_quaduart(void)
unsigned long cs_mem_base;
int quart_gpio = 0;
+ if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
+ GPIOF_OUT_INIT_LOW,
+ "TL16CP754C GPIO") < 0) {
+ pr_err("Failed to request GPIO%d for TL16CP754C\n",
+ ZOOM_QUADUART_RST_GPIO);
+ return;
+ }
+
quart_cs = ZOOM_QUADUART_CS;
if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 118c6f53c5eb..6d0aa4fcb7c3 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -105,21 +105,20 @@ static struct twl4030_keypad_data zoom_kp_twl4030_data = {
.rep = 1,
};
-static struct regulator_consumer_supply zoom_vmmc1_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply zoom_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply zoom_vsim_supply = {
- .supply = "vmmc_aux",
+static struct regulator_consumer_supply zoom_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
};
-static struct regulator_consumer_supply zoom_vmmc2_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply zoom_vmmc2_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
};
-static struct regulator_consumer_supply zoom_vmmc3_supply = {
- .supply = "vmmc",
- .dev_name = "omap_hsmmc.2",
+static struct regulator_consumer_supply zoom_vmmc3_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"),
};
/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
@@ -133,8 +132,8 @@ static struct regulator_init_data zoom_vmmc1 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &zoom_vmmc1_supply,
+ .num_consumer_supplies = ARRAY_SIZE(zoom_vmmc1_supply),
+ .consumer_supplies = zoom_vmmc1_supply,
};
/* VMMC2 for MMC2 card */
@@ -148,8 +147,8 @@ static struct regulator_init_data zoom_vmmc2 = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &zoom_vmmc2_supply,
+ .num_consumer_supplies = ARRAY_SIZE(zoom_vmmc2_supply),
+ .consumer_supplies = zoom_vmmc2_supply,
};
/* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */
@@ -163,16 +162,16 @@ static struct regulator_init_data zoom_vsim = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &zoom_vsim_supply,
+ .num_consumer_supplies = ARRAY_SIZE(zoom_vsim_supply),
+ .consumer_supplies = zoom_vsim_supply,
};
static struct regulator_init_data zoom_vmmc3 = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &zoom_vmmc3_supply,
+ .num_consumer_supplies = ARRAY_SIZE(zoom_vmmc3_supply),
+ .consumer_supplies = zoom_vmmc3_supply,
};
static struct fixed_voltage_config zoom_vwlan = {
@@ -227,40 +226,6 @@ static struct omap2_hsmmc_info mmc[] = {
{} /* Terminator */
};
-static struct regulator_consumer_supply zoom_vpll2_supplies[] = {
- REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_consumer_supply zoom_vdda_dac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_init_data zoom_vpll2 = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(zoom_vpll2_supplies),
- .consumer_supplies = zoom_vpll2_supplies,
-};
-
-static struct regulator_init_data zoom_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &zoom_vdda_dac_supply,
-};
-
static int zoom_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
@@ -270,13 +235,6 @@ static int zoom_twl_gpio_setup(struct device *dev,
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
- /* link regulators to MMC adapters ... we "know" the
- * regulators will be set up only *after* we return.
- */
- zoom_vmmc1_supply.dev = mmc[0].dev;
- zoom_vsim_supply.dev = mmc[0].dev;
- zoom_vmmc2_supply.dev = mmc[1].dev;
-
ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
"lcd enable");
if (ret)
@@ -292,26 +250,6 @@ static void zoom2_set_hs_extmute(int mute)
gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
}
-static int zoom_batt_table[] = {
-/* 0 C*/
-30800, 29500, 28300, 27100,
-26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
-17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
-11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
-8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
-5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
-4040, 3910, 3790, 3670, 3550
-};
-
-static struct twl4030_bci_platform_data zoom_bci_data = {
- .battery_tmp_tbl = zoom_batt_table,
- .tblsize = ARRAY_SIZE(zoom_batt_table),
-};
-
-static struct twl4030_usb_data zoom_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
static struct twl4030_gpio_platform_data zoom_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
@@ -319,41 +257,29 @@ static struct twl4030_gpio_platform_data zoom_gpio_data = {
.setup = zoom_twl_gpio_setup,
};
-static struct twl4030_madc_platform_data zoom_madc_data = {
- .irq_line = 1,
-};
-
-static struct twl4030_codec_audio_data zoom_audio_data;
-
-static struct twl4030_codec_data zoom_codec_data = {
- .audio_mclk = 26000000,
- .audio = &zoom_audio_data,
-};
-
static struct twl4030_platform_data zoom_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
/* platform_data for children goes here */
- .bci = &zoom_bci_data,
- .madc = &zoom_madc_data,
- .usb = &zoom_usb_data,
.gpio = &zoom_gpio_data,
.keypad = &zoom_kp_twl4030_data,
- .codec = &zoom_codec_data,
.vmmc1 = &zoom_vmmc1,
.vmmc2 = &zoom_vmmc2,
.vsim = &zoom_vsim,
- .vpll2 = &zoom_vpll2,
- .vdac = &zoom_vdac,
};
static int __init omap_i2c_init(void)
{
+ omap3_pmic_get_config(&zoom_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI |
+ TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
if (machine_is_omap_zoom2()) {
- zoom_audio_data.ramp_delay_value = 3; /* 161 ms */
- zoom_audio_data.hs_extmute = 1;
- zoom_audio_data.set_hs_extmute = zoom2_set_hs_extmute;
+ struct twl4030_codec_data *codec_data;
+ codec_data = zoom_twldata.audio->codec;
+
+ codec_data->ramp_delay_value = 3; /* 161 ms */
+ codec_data->hs_extmute = 1;
+ codec_data->set_hs_extmute = zoom2_set_hs_extmute;
}
omap_pmic_init(1, 2400, "twl5030", INT_34XX_SYS_NIRQ, &zoom_twldata);
omap_register_i2c_bus(2, 400, NULL, 0);
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 4b133d75c935..8a98c3c303fc 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -137,9 +137,9 @@ MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap_zoom_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap_zoom_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
@@ -147,7 +147,7 @@ MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap_zoom_init_early,
- .init_irq = omap_init_irq,
+ .init_irq = omap3_init_irq,
.init_machine = omap_zoom_init,
- .timer = &omap_timer,
+ .timer = &omap3_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180299e4a838..1f3481f8d695 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -38,6 +38,14 @@
u8 cpu_mask;
/*
+ * clkdm_control: if true, then when a clock is enabled in the
+ * hardware, its clockdomain will first be enabled; and when a clock
+ * is disabled in the hardware, its clockdomain will be disabled
+ * afterwards.
+ */
+static bool clkdm_control = true;
+
+/*
* OMAP2+ specific clock functions
*/
@@ -100,6 +108,19 @@ void omap2_init_clk_clkdm(struct clk *clk)
}
/**
+ * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
+ *
+ * Prevent the OMAP clock code from calling into the clockdomain code
+ * when a hardware clock in that clockdomain is enabled or disabled.
+ * Intended to be called at init time from omap*_clk_init(). No
+ * return value.
+ */
+void __init omap2_clk_disable_clkdm_control(void)
+{
+ clkdm_control = false;
+}
+
+/**
* omap2_clk_dflt_find_companion - find companion clock to @clk
* @clk: struct clk * to find the companion clock of
* @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
@@ -268,7 +289,7 @@ void omap2_clk_disable(struct clk *clk)
clk->ops->disable(clk);
}
- if (clk->clkdm)
+ if (clkdm_control && clk->clkdm)
clkdm_clk_disable(clk->clkdm, clk);
if (clk->parent)
@@ -308,7 +329,7 @@ int omap2_clk_enable(struct clk *clk)
}
}
- if (clk->clkdm) {
+ if (clkdm_control && clk->clkdm) {
ret = clkdm_clk_enable(clk->clkdm, clk);
if (ret) {
WARN(1, "clock: %s: could not enable clockdomain %s: "
@@ -330,7 +351,7 @@ int omap2_clk_enable(struct clk *clk)
return 0;
oce_err3:
- if (clk->clkdm)
+ if (clkdm_control && clk->clkdm)
clkdm_clk_disable(clk->clkdm, clk);
oce_err2:
if (clk->parent)
@@ -453,6 +474,7 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
if (IS_ERR_VALUE(r)) {
WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
mpurate_ck->name, mpurate, r);
+ clk_put(mpurate_ck);
return -EINVAL;
}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index e10ff2b54844..48ac568881bd 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -16,6 +16,8 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK_H
+#include <linux/kernel.h>
+
#include <plat/clock.h>
/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
@@ -72,6 +74,7 @@ void omap2_clk_disable_unused(struct clk *clk);
#endif
void omap2_init_clk_clkdm(struct clk *clk);
+void __init omap2_clk_disable_clkdm_control(void);
/* clkt_clksel.c public functions */
u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 2926d028b6e9..debc040872f1 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1805,9 +1805,9 @@ static struct omap_clk omap2420_clks[] = {
CLK(NULL, "gfx_ick", &gfx_ick, CK_242X),
/* DSS domain clocks */
CLK("omapdss_dss", "ick", &dss_ick, CK_242X),
- CLK("omapdss_dss", "fck", &dss1_fck, CK_242X),
- CLK("omapdss_dss", "sys_clk", &dss2_fck, CK_242X),
- CLK("omapdss_dss", "tv_clk", &dss_54m_fck, CK_242X),
+ CLK(NULL, "dss1_fck", &dss1_fck, CK_242X),
+ CLK(NULL, "dss2_fck", &dss2_fck, CK_242X),
+ CLK(NULL, "dss_54m_fck", &dss_54m_fck, CK_242X),
/* L3 domain clocks */
CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X),
CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X),
@@ -1844,13 +1844,13 @@ static struct omap_clk omap2420_clks[] = {
CLK(NULL, "gpt12_ick", &gpt12_ick, CK_242X),
CLK(NULL, "gpt12_fck", &gpt12_fck, CK_242X),
CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_242X),
- CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_242X),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_242X),
CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_242X),
- CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_242X),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_242X),
CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_242X),
- CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_242X),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_242X),
CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_242X),
- CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_242X),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_242X),
CLK(NULL, "uart1_ick", &uart1_ick, CK_242X),
CLK(NULL, "uart1_fck", &uart1_fck, CK_242X),
CLK(NULL, "uart2_ick", &uart2_ick, CK_242X),
@@ -1860,7 +1860,7 @@ static struct omap_clk omap2420_clks[] = {
CLK(NULL, "gpios_ick", &gpios_ick, CK_242X),
CLK(NULL, "gpios_fck", &gpios_fck, CK_242X),
CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_242X),
- CLK("omap_wdt", "fck", &mpu_wdt_fck, CK_242X),
+ CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_242X),
CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_242X),
CLK(NULL, "wdt1_ick", &wdt1_ick, CK_242X),
CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_242X),
@@ -1880,11 +1880,11 @@ static struct omap_clk omap2420_clks[] = {
CLK(NULL, "eac_ick", &eac_ick, CK_242X),
CLK(NULL, "eac_fck", &eac_fck, CK_242X),
CLK("omap_hdq.0", "ick", &hdq_ick, CK_242X),
- CLK("omap_hdq.1", "fck", &hdq_fck, CK_242X),
+ CLK("omap_hdq.0", "fck", &hdq_fck, CK_242X),
CLK("omap_i2c.1", "ick", &i2c1_ick, CK_242X),
- CLK("omap_i2c.1", "fck", &i2c1_fck, CK_242X),
+ CLK(NULL, "i2c1_fck", &i2c1_fck, CK_242X),
CLK("omap_i2c.2", "ick", &i2c2_ick, CK_242X),
- CLK("omap_i2c.2", "fck", &i2c2_fck, CK_242X),
+ CLK(NULL, "i2c2_fck", &i2c2_fck, CK_242X),
CLK(NULL, "gpmc_fck", &gpmc_fck, CK_242X),
CLK(NULL, "sdma_fck", &sdma_fck, CK_242X),
CLK(NULL, "sdma_ick", &sdma_ick, CK_242X),
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 0c79d39e3021..96a942e42db1 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1895,9 +1895,9 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
/* DSS domain clocks */
CLK("omapdss_dss", "ick", &dss_ick, CK_243X),
- CLK("omapdss_dss", "fck", &dss1_fck, CK_243X),
- CLK("omapdss_dss", "sys_clk", &dss2_fck, CK_243X),
- CLK("omapdss_dss", "tv_clk", &dss_54m_fck, CK_243X),
+ CLK(NULL, "dss1_fck", &dss1_fck, CK_243X),
+ CLK(NULL, "dss2_fck", &dss2_fck, CK_243X),
+ CLK(NULL, "dss_54m_fck", &dss_54m_fck, CK_243X),
/* L3 domain clocks */
CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X),
CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X),
@@ -1934,21 +1934,21 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X),
CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X),
CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_243X),
- CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_243X),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_243X),
CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_243X),
- CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_243X),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_243X),
CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_243X),
- CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_243X),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_243X),
CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_243X),
- CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_243X),
+ CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_243X),
CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_243X),
- CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_243X),
+ CLK(NULL, "mcbsp5_fck", &mcbsp5_fck, CK_243X),
CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_243X),
- CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_243X),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_243X),
CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_243X),
- CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_243X),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_243X),
CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_243X),
- CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_243X),
+ CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_243X),
CLK(NULL, "uart1_ick", &uart1_ick, CK_243X),
CLK(NULL, "uart1_fck", &uart1_fck, CK_243X),
CLK(NULL, "uart2_ick", &uart2_ick, CK_243X),
@@ -1958,7 +1958,7 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "gpios_ick", &gpios_ick, CK_243X),
CLK(NULL, "gpios_fck", &gpios_fck, CK_243X),
CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_243X),
- CLK("omap_wdt", "fck", &mpu_wdt_fck, CK_243X),
+ CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_243X),
CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_243X),
CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X),
CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X),
@@ -1975,9 +1975,9 @@ static struct omap_clk omap2430_clks[] = {
CLK("omap_hdq.0", "ick", &hdq_ick, CK_243X),
CLK("omap_hdq.1", "fck", &hdq_fck, CK_243X),
CLK("omap_i2c.1", "ick", &i2c1_ick, CK_243X),
- CLK("omap_i2c.1", "fck", &i2chs1_fck, CK_243X),
+ CLK(NULL, "i2chs1_fck", &i2chs1_fck, CK_243X),
CLK("omap_i2c.2", "ick", &i2c2_ick, CK_243X),
- CLK("omap_i2c.2", "fck", &i2chs2_fck, CK_243X),
+ CLK(NULL, "i2chs2_fck", &i2chs2_fck, CK_243X),
CLK(NULL, "gpmc_fck", &gpmc_fck, CK_243X),
CLK(NULL, "sdma_fck", &sdma_fck, CK_243X),
CLK(NULL, "sdma_ick", &sdma_ick, CK_243X),
@@ -1990,9 +1990,9 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "usb_fck", &usb_fck, CK_243X),
CLK("musb-omap2430", "ick", &usbhs_ick, CK_243X),
CLK("omap_hsmmc.0", "ick", &mmchs1_ick, CK_243X),
- CLK("omap_hsmmc.0", "fck", &mmchs1_fck, CK_243X),
+ CLK(NULL, "mmchs1_fck", &mmchs1_fck, CK_243X),
CLK("omap_hsmmc.1", "ick", &mmchs2_ick, CK_243X),
- CLK("omap_hsmmc.1", "fck", &mmchs2_fck, CK_243X),
+ CLK(NULL, "mmchs2_fck", &mmchs2_fck, CK_243X),
CLK(NULL, "gpio5_ick", &gpio5_ick, CK_243X),
CLK(NULL, "gpio5_fck", &gpio5_fck, CK_243X),
CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X),
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 75b119bd9cda..ffd55b1c4396 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3289,25 +3289,25 @@ static struct omap_clk omap3xxx_clks[] = {
CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX),
CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX),
CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
- CLK("omap_hsmmc.2", "fck", &mmchs3_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("omap_hsmmc.1", "fck", &mmchs2_fck, CK_3XXX),
+ CLK(NULL, "mmchs3_fck", &mmchs3_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "mmchs2_fck", &mmchs2_fck, CK_3XXX),
CLK(NULL, "mspro_fck", &mspro_fck, CK_34XX | CK_36XX),
- CLK("omap_hsmmc.0", "fck", &mmchs1_fck, CK_3XXX),
- CLK("omap_i2c.3", "fck", &i2c3_fck, CK_3XXX),
- CLK("omap_i2c.2", "fck", &i2c2_fck, CK_3XXX),
- CLK("omap_i2c.1", "fck", &i2c1_fck, CK_3XXX),
- CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_3XXX),
- CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_3XXX),
+ CLK(NULL, "mmchs1_fck", &mmchs1_fck, CK_3XXX),
+ CLK(NULL, "i2c3_fck", &i2c3_fck, CK_3XXX),
+ CLK(NULL, "i2c2_fck", &i2c2_fck, CK_3XXX),
+ CLK(NULL, "i2c1_fck", &i2c1_fck, CK_3XXX),
+ CLK(NULL, "mcbsp5_fck", &mcbsp5_fck, CK_3XXX),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_3XXX),
CLK(NULL, "core_48m_fck", &core_48m_fck, CK_3XXX),
- CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_3XXX),
- CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_3XXX),
- CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_3XXX),
- CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_3XXX),
+ CLK(NULL, "mcspi4_fck", &mcspi4_fck, CK_3XXX),
+ CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_3XXX),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_3XXX),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_3XXX),
CLK(NULL, "uart2_fck", &uart2_fck, CK_3XXX),
CLK(NULL, "uart1_fck", &uart1_fck, CK_3XXX),
CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1),
CLK(NULL, "core_12m_fck", &core_12m_fck, CK_3XXX),
- CLK("omap_hdq.0", "fck", &hdq_fck, CK_3XXX),
+ CLK("omap_hdq.0", "fck", &hdq_fck, CK_3XXX),
CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1, CK_3430ES1),
CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2, CK_3430ES2PLUS | CK_36XX),
CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1, CK_3430ES1),
@@ -3356,11 +3356,11 @@ static struct omap_clk omap3xxx_clks[] = {
CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX),
CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX),
CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX),
- CLK("omapdss_dss", "fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
- CLK("omapdss_dss", "fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("omapdss_dss", "tv_clk", &dss_tv_fck, CK_3XXX),
- CLK("omapdss_dss", "video_clk", &dss_96m_fck, CK_3XXX),
- CLK("omapdss_dss", "sys_clk", &dss2_alwon_fck, CK_3XXX),
+ CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
+ CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "dss_tv_fck", &dss_tv_fck, CK_3XXX),
+ CLK(NULL, "dss_96m_fck", &dss_96m_fck, CK_3XXX),
+ CLK(NULL, "dss2_alwon_fck", &dss2_alwon_fck, CK_3XXX),
CLK("omapdss_dss", "ick", &dss_ick_3430es1, CK_3430ES1),
CLK("omapdss_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX),
@@ -3385,7 +3385,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_3XXX),
- CLK("omap_wdt", "fck", &wdt2_fck, CK_3XXX),
+ CLK(NULL, "wdt2_fck", &wdt2_fck, CK_3XXX),
CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_34XX | CK_36XX),
CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2PLUS | CK_36XX),
CLK("omap_wdt", "ick", &wdt2_ick, CK_3XXX),
@@ -3436,9 +3436,9 @@ static struct omap_clk omap3xxx_clks[] = {
CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_3XXX),
CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_3XXX),
CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_3XXX),
- CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_3XXX),
- CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_3XXX),
- CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_3XXX),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_3XXX),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_3XXX),
+ CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_3XXX),
CLK("etb", "emu_src_ck", &emu_src_ck, CK_3XXX),
CLK(NULL, "pclk_fck", &pclk_fck, CK_3XXX),
CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_3XXX),
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h
index 6be1095936db..7ceb870e7ab8 100644
--- a/arch/arm/mach-omap2/clock44xx.h
+++ b/arch/arm/mach-omap2/clock44xx.h
@@ -8,13 +8,6 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
-/*
- * XXX Missing values for the OMAP4 DPLL_USB
- * XXX Missing min_multiplier values for all OMAP4 DPLLs
- */
-#define OMAP4430_MAX_DPLL_MULT 2047
-#define OMAP4430_MAX_DPLL_DIV 128
-
int omap4xxx_clk_init(void);
#endif
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 8c965671b4d4..2af0e3f00ce1 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -53,9 +53,9 @@ static struct clk extalt_clkin_ck = {
static struct clk pad_clks_ck = {
.name = "pad_clks_ck",
.rate = 12000000,
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_CLKSEL_ABE,
- .enable_bit = OMAP4430_PAD_CLKS_GATE_SHIFT,
+ .ops = &clkops_omap2_dflt,
+ .enable_reg = OMAP4430_CM_CLKSEL_ABE,
+ .enable_bit = OMAP4430_PAD_CLKS_GATE_SHIFT,
};
static struct clk pad_slimbus_core_clks_ck = {
@@ -73,9 +73,9 @@ static struct clk secure_32k_clk_src_ck = {
static struct clk slimbus_clk = {
.name = "slimbus_clk",
.rate = 12000000,
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_CLKSEL_ABE,
- .enable_bit = OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
+ .ops = &clkops_omap2_dflt,
+ .enable_reg = OMAP4430_CM_CLKSEL_ABE,
+ .enable_bit = OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
};
static struct clk sys_32k_ck = {
@@ -258,8 +258,8 @@ static struct dpll_data dpll_abe_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = OMAP4430_MAX_DPLL_MULT,
- .max_divider = OMAP4430_MAX_DPLL_DIV,
+ .max_multiplier = 2047,
+ .max_divider = 128,
.min_divider = 1,
};
@@ -278,10 +278,10 @@ static struct clk dpll_abe_ck = {
static struct clk dpll_abe_x2_ck = {
.name = "dpll_abe_x2_ck",
.parent = &dpll_abe_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
.flags = CLOCK_CLKOUTX2,
.ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap3_clkoutx2_recalc,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
};
static const struct clksel_rate div31_1to31_rates[] = {
@@ -434,8 +434,8 @@ static struct dpll_data dpll_core_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = OMAP4430_MAX_DPLL_MULT,
- .max_divider = OMAP4430_MAX_DPLL_DIV,
+ .max_multiplier = 2047,
+ .max_divider = 128,
.min_divider = 1,
};
@@ -622,11 +622,11 @@ static struct clk dpll_core_m3x2_ck = {
.clksel_reg = OMAP4430_CM_DIV_M3_DPLL_CORE,
.clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
.ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DIV_M3_DPLL_CORE,
- .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
+ .enable_reg = OMAP4430_CM_DIV_M3_DPLL_CORE,
+ .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
};
static struct clk dpll_core_m7x2_ck = {
@@ -672,8 +672,8 @@ static struct dpll_data dpll_iva_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = OMAP4430_MAX_DPLL_MULT,
- .max_divider = OMAP4430_MAX_DPLL_DIV,
+ .max_multiplier = 2047,
+ .max_divider = 128,
.min_divider = 1,
};
@@ -740,8 +740,8 @@ static struct dpll_data dpll_mpu_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = OMAP4430_MAX_DPLL_MULT,
- .max_divider = OMAP4430_MAX_DPLL_DIV,
+ .max_multiplier = 2047,
+ .max_divider = 128,
.min_divider = 1,
};
@@ -813,8 +813,8 @@ static struct dpll_data dpll_per_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = OMAP4430_MAX_DPLL_MULT,
- .max_divider = OMAP4430_MAX_DPLL_DIV,
+ .max_multiplier = 2047,
+ .max_divider = 128,
.min_divider = 1,
};
@@ -850,10 +850,10 @@ static struct clk dpll_per_m2_ck = {
static struct clk dpll_per_x2_ck = {
.name = "dpll_per_x2_ck",
.parent = &dpll_per_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
.flags = CLOCK_CLKOUTX2,
.ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap3_clkoutx2_recalc,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
};
static const struct clksel dpll_per_m2x2_div[] = {
@@ -880,11 +880,11 @@ static struct clk dpll_per_m3x2_ck = {
.clksel_reg = OMAP4430_CM_DIV_M3_DPLL_PER,
.clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
.ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DIV_M3_DPLL_PER,
- .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
.set_rate = &omap2_clksel_set_rate,
+ .enable_reg = OMAP4430_CM_DIV_M3_DPLL_PER,
+ .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
};
static struct clk dpll_per_m4x2_ck = {
@@ -935,63 +935,6 @@ static struct clk dpll_per_m7x2_ck = {
.set_rate = &omap2_clksel_set_rate,
};
-/* DPLL_UNIPRO */
-static struct dpll_data dpll_unipro_dd = {
- .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_UNIPRO,
- .clk_bypass = &sys_clkin_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = OMAP4430_CM_CLKMODE_DPLL_UNIPRO,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO,
- .idlest_reg = OMAP4430_CM_IDLEST_DPLL_UNIPRO,
- .mult_mask = OMAP4430_DPLL_MULT_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_MASK,
- .enable_mask = OMAP4430_DPLL_EN_MASK,
- .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
- .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .sddiv_mask = OMAP4430_DPLL_SD_DIV_MASK,
- .max_multiplier = OMAP4430_MAX_DPLL_MULT,
- .max_divider = OMAP4430_MAX_DPLL_DIV,
- .min_divider = 1,
-};
-
-
-static struct clk dpll_unipro_ck = {
- .name = "dpll_unipro_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_unipro_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-static struct clk dpll_unipro_x2_ck = {
- .name = "dpll_unipro_x2_ck",
- .parent = &dpll_unipro_ck,
- .flags = CLOCK_CLKOUTX2,
- .ops = &clkops_null,
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_unipro_m2x2_div[] = {
- { .parent = &dpll_unipro_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_unipro_m2x2_ck = {
- .name = "dpll_unipro_m2x2_ck",
- .parent = &dpll_unipro_x2_ck,
- .clksel = dpll_unipro_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
static struct clk usb_hs_clk_div_ck = {
.name = "usb_hs_clk_div_ck",
.parent = &dpll_abe_m3x2_ck,
@@ -1015,8 +958,9 @@ static struct dpll_data dpll_usb_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = OMAP4430_MAX_DPLL_MULT,
- .max_divider = OMAP4430_MAX_DPLL_DIV,
+ .sddiv_mask = OMAP4430_DPLL_SD_DIV_MASK,
+ .max_multiplier = 4095,
+ .max_divider = 256,
.min_divider = 1,
};
@@ -1035,8 +979,8 @@ static struct clk dpll_usb_ck = {
static struct clk dpll_usb_clkdcoldo_ck = {
.name = "dpll_usb_clkdcoldo_ck",
.parent = &dpll_usb_ck,
- .ops = &clkops_omap4_dpllmx_ops,
.clksel_reg = OMAP4430_CM_CLKDCOLDO_DPLL_USB,
+ .ops = &clkops_omap4_dpllmx_ops,
.recalc = &followparent_recalc,
};
@@ -1169,19 +1113,6 @@ static struct clk func_96m_fclk = {
.set_rate = &omap2_clksel_set_rate,
};
-static const struct clksel hsmmc6_fclk_sel[] = {
- { .parent = &func_64m_fclk, .rates = div_1_0_rates },
- { .parent = &func_96m_fclk, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk hsmmc6_fclk = {
- .name = "hsmmc6_fclk",
- .parent = &func_64m_fclk,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
static const struct clksel_rate div2_1to8_rates[] = {
{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
{ .div = 8, .val = 1, .flags = RATE_IN_4430 },
@@ -1264,6 +1195,21 @@ static struct clk l4_wkup_clk_mux_ck = {
.recalc = &omap2_clksel_recalc,
};
+static struct clk ocp_abe_iclk = {
+ .name = "ocp_abe_iclk",
+ .parent = &aess_fclk,
+ .ops = &clkops_null,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk per_abe_24m_fclk = {
+ .name = "per_abe_24m_fclk",
+ .parent = &dpll_abe_m2_ck,
+ .ops = &clkops_null,
+ .fixed_div = 4,
+ .recalc = &omap_fixed_divisor_recalc,
+};
+
static const struct clksel per_abe_nc_fclk_div[] = {
{ .parent = &dpll_abe_m2_ck, .rates = div2_1to2_rates },
{ .parent = NULL },
@@ -1281,41 +1227,6 @@ static struct clk per_abe_nc_fclk = {
.set_rate = &omap2_clksel_set_rate,
};
-static const struct clksel mcasp2_fclk_sel[] = {
- { .parent = &func_96m_fclk, .rates = div_1_0_rates },
- { .parent = &per_abe_nc_fclk, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk mcasp2_fclk = {
- .name = "mcasp2_fclk",
- .parent = &func_96m_fclk,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcasp3_fclk = {
- .name = "mcasp3_fclk",
- .parent = &func_96m_fclk,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk ocp_abe_iclk = {
- .name = "ocp_abe_iclk",
- .parent = &aess_fclk,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk per_abe_24m_fclk = {
- .name = "per_abe_24m_fclk",
- .parent = &dpll_abe_m2_ck,
- .ops = &clkops_null,
- .fixed_div = 4,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
static const struct clksel pmd_stm_clock_mux_sel[] = {
{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
{ .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
@@ -1486,6 +1397,40 @@ static struct clk dss_dss_clk = {
.recalc = &followparent_recalc,
};
+static const struct clksel_rate div3_8to32_rates[] = {
+ { .div = 8, .val = 0, .flags = RATE_IN_44XX },
+ { .div = 16, .val = 1, .flags = RATE_IN_44XX },
+ { .div = 32, .val = 2, .flags = RATE_IN_44XX },
+ { .div = 0 },
+};
+
+static const struct clksel div_ts_div[] = {
+ { .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates },
+ { .parent = NULL },
+};
+
+static struct clk div_ts_ck = {
+ .name = "div_ts_ck",
+ .parent = &l4_wkup_clk_mux_ck,
+ .clksel = div_ts_div,
+ .clksel_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_24_25_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk bandgap_ts_fclk = {
+ .name = "bandgap_ts_fclk",
+ .ops = &clkops_omap2_dflt,
+ .enable_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ .enable_bit = OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
+ .clkdm_name = "l4_wkup_clkdm",
+ .parent = &div_ts_ck,
+ .recalc = &followparent_recalc,
+};
+
static struct clk dss_48mhz_clk = {
.name = "dss_48mhz_clk",
.ops = &clkops_omap2_dflt,
@@ -1694,6 +1639,7 @@ static struct clk gpmc_ick = {
.ops = &clkops_omap2_dflt,
.enable_reg = OMAP4430_CM_L3_2_GPMC_CLKCTRL,
.enable_bit = OMAP4430_MODULEMODE_HWCTRL,
+ .flags = ENABLE_ON_INIT,
.clkdm_name = "l3_2_clkdm",
.parent = &l3_div_ck,
.recalc = &followparent_recalc,
@@ -1846,8 +1792,8 @@ static struct clk l3_instr_ick = {
.ops = &clkops_omap2_dflt,
.enable_reg = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
.enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l3_instr_clkdm",
.flags = ENABLE_ON_INIT,
+ .clkdm_name = "l3_instr_clkdm",
.parent = &l3_div_ck,
.recalc = &followparent_recalc,
};
@@ -1857,8 +1803,8 @@ static struct clk l3_main_3_ick = {
.ops = &clkops_omap2_dflt,
.enable_reg = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
.enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l3_instr_clkdm",
.flags = ENABLE_ON_INIT,
+ .clkdm_name = "l3_instr_clkdm",
.parent = &l3_div_ck,
.recalc = &followparent_recalc,
};
@@ -1995,10 +1941,16 @@ static struct clk mcbsp3_fck = {
.clkdm_name = "abe_clkdm",
};
+static const struct clksel mcbsp4_sync_mux_sel[] = {
+ { .parent = &func_96m_fclk, .rates = div_1_0_rates },
+ { .parent = &per_abe_nc_fclk, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
static struct clk mcbsp4_sync_mux_ck = {
.name = "mcbsp4_sync_mux_ck",
.parent = &func_96m_fclk,
- .clksel = mcasp2_fclk_sel,
+ .clksel = mcbsp4_sync_mux_sel,
.init = &omap2_init_clksel_parent,
.clksel_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
.clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
@@ -2077,11 +2029,17 @@ static struct clk mcspi4_fck = {
.recalc = &followparent_recalc,
};
+static const struct clksel hsmmc1_fclk_sel[] = {
+ { .parent = &func_64m_fclk, .rates = div_1_0_rates },
+ { .parent = &func_96m_fclk, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
/* Merged hsmmc1_fclk into mmc1 */
static struct clk mmc1_fck = {
.name = "mmc1_fck",
.parent = &func_64m_fclk,
- .clksel = hsmmc6_fclk_sel,
+ .clksel = hsmmc1_fclk_sel,
.init = &omap2_init_clksel_parent,
.clksel_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
.clksel_mask = OMAP4430_CLKSEL_MASK,
@@ -2096,7 +2054,7 @@ static struct clk mmc1_fck = {
static struct clk mmc2_fck = {
.name = "mmc2_fck",
.parent = &func_64m_fclk,
- .clksel = hsmmc6_fclk_sel,
+ .clksel = hsmmc1_fclk_sel,
.init = &omap2_init_clksel_parent,
.clksel_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
.clksel_mask = OMAP4430_CLKSEL_MASK,
@@ -2162,8 +2120,8 @@ static struct clk ocp_wp_noc_ick = {
.ops = &clkops_omap2_dflt,
.enable_reg = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
.enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l3_instr_clkdm",
.flags = ENABLE_ON_INIT,
+ .clkdm_name = "l3_instr_clkdm",
.parent = &l3_div_ck,
.recalc = &followparent_recalc,
};
@@ -2850,19 +2808,39 @@ static struct clk trace_clk_div_ck = {
/* SCRM aux clk nodes */
-static const struct clksel auxclk_sel[] = {
+static const struct clksel auxclk_src_sel[] = {
{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
{ .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
{ .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
{ .parent = NULL },
};
-static struct clk auxclk0_ck = {
- .name = "auxclk0_ck",
+static const struct clksel_rate div16_1to16_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_4430 },
+ { .div = 2, .val = 1, .flags = RATE_IN_4430 },
+ { .div = 3, .val = 2, .flags = RATE_IN_4430 },
+ { .div = 4, .val = 3, .flags = RATE_IN_4430 },
+ { .div = 5, .val = 4, .flags = RATE_IN_4430 },
+ { .div = 6, .val = 5, .flags = RATE_IN_4430 },
+ { .div = 7, .val = 6, .flags = RATE_IN_4430 },
+ { .div = 8, .val = 7, .flags = RATE_IN_4430 },
+ { .div = 9, .val = 8, .flags = RATE_IN_4430 },
+ { .div = 10, .val = 9, .flags = RATE_IN_4430 },
+ { .div = 11, .val = 10, .flags = RATE_IN_4430 },
+ { .div = 12, .val = 11, .flags = RATE_IN_4430 },
+ { .div = 13, .val = 12, .flags = RATE_IN_4430 },
+ { .div = 14, .val = 13, .flags = RATE_IN_4430 },
+ { .div = 15, .val = 14, .flags = RATE_IN_4430 },
+ { .div = 16, .val = 15, .flags = RATE_IN_4430 },
+ { .div = 0 },
+};
+
+static struct clk auxclk0_src_ck = {
+ .name = "auxclk0_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK0,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2870,12 +2848,29 @@ static struct clk auxclk0_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk1_ck = {
- .name = "auxclk1_ck",
+static const struct clksel auxclk0_sel[] = {
+ { .parent = &auxclk0_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk0_ck = {
+ .name = "auxclk0_ck",
+ .parent = &auxclk0_src_ck,
+ .clksel = auxclk0_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK0,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk1_src_ck = {
+ .name = "auxclk1_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK1,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2883,24 +2878,59 @@ static struct clk auxclk1_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk2_ck = {
- .name = "auxclk2_ck",
+static const struct clksel auxclk1_sel[] = {
+ { .parent = &auxclk1_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk1_ck = {
+ .name = "auxclk1_ck",
+ .parent = &auxclk1_src_ck,
+ .clksel = auxclk1_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK1,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk2_src_ck = {
+ .name = "auxclk2_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK2,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
.enable_reg = OMAP4_SCRM_AUXCLK2,
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk3_ck = {
- .name = "auxclk3_ck",
+
+static const struct clksel auxclk2_sel[] = {
+ { .parent = &auxclk2_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk2_ck = {
+ .name = "auxclk2_ck",
+ .parent = &auxclk2_src_ck,
+ .clksel = auxclk2_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK2,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk3_src_ck = {
+ .name = "auxclk3_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK3,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2908,12 +2938,29 @@ static struct clk auxclk3_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk4_ck = {
- .name = "auxclk4_ck",
+static const struct clksel auxclk3_sel[] = {
+ { .parent = &auxclk3_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk3_ck = {
+ .name = "auxclk3_ck",
+ .parent = &auxclk3_src_ck,
+ .clksel = auxclk3_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK3,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk4_src_ck = {
+ .name = "auxclk4_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK4,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2921,12 +2968,29 @@ static struct clk auxclk4_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
-static struct clk auxclk5_ck = {
- .name = "auxclk5_ck",
+static const struct clksel auxclk4_sel[] = {
+ { .parent = &auxclk4_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk4_ck = {
+ .name = "auxclk4_ck",
+ .parent = &auxclk4_src_ck,
+ .clksel = auxclk4_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK4,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk5_src_ck = {
+ .name = "auxclk5_src_ck",
.parent = &sys_clkin_ck,
.init = &omap2_init_clksel_parent,
.ops = &clkops_omap2_dflt,
- .clksel = auxclk_sel,
+ .clksel = auxclk_src_sel,
.clksel_reg = OMAP4_SCRM_AUXCLK5,
.clksel_mask = OMAP4_SRCSELECT_MASK,
.recalc = &omap2_clksel_recalc,
@@ -2934,6 +2998,23 @@ static struct clk auxclk5_ck = {
.enable_bit = OMAP4_ENABLE_SHIFT,
};
+static const struct clksel auxclk5_sel[] = {
+ { .parent = &auxclk5_src_ck, .rates = div16_1to16_rates },
+ { .parent = NULL },
+};
+
+static struct clk auxclk5_ck = {
+ .name = "auxclk5_ck",
+ .parent = &auxclk5_src_ck,
+ .clksel = auxclk5_sel,
+ .clksel_reg = OMAP4_SCRM_AUXCLK5,
+ .clksel_mask = OMAP4_CLKDIV_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+ .set_rate = &omap2_clksel_set_rate,
+};
+
static const struct clksel auxclkreq_sel[] = {
{ .parent = &auxclk0_ck, .rates = div_1_0_rates },
{ .parent = &auxclk1_ck, .rates = div_1_1_rates },
@@ -3077,9 +3158,6 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, CK_443X),
CLK(NULL, "dpll_per_m6x2_ck", &dpll_per_m6x2_ck, CK_443X),
CLK(NULL, "dpll_per_m7x2_ck", &dpll_per_m7x2_ck, CK_443X),
- CLK(NULL, "dpll_unipro_ck", &dpll_unipro_ck, CK_443X),
- CLK(NULL, "dpll_unipro_x2_ck", &dpll_unipro_x2_ck, CK_443X),
- CLK(NULL, "dpll_unipro_m2x2_ck", &dpll_unipro_m2x2_ck, CK_443X),
CLK(NULL, "usb_hs_clk_div_ck", &usb_hs_clk_div_ck, CK_443X),
CLK(NULL, "dpll_usb_ck", &dpll_usb_ck, CK_443X),
CLK(NULL, "dpll_usb_clkdcoldo_ck", &dpll_usb_clkdcoldo_ck, CK_443X),
@@ -3092,17 +3170,14 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "func_48mc_fclk", &func_48mc_fclk, CK_443X),
CLK(NULL, "func_64m_fclk", &func_64m_fclk, CK_443X),
CLK(NULL, "func_96m_fclk", &func_96m_fclk, CK_443X),
- CLK(NULL, "hsmmc6_fclk", &hsmmc6_fclk, CK_443X),
CLK(NULL, "init_60m_fclk", &init_60m_fclk, CK_443X),
CLK(NULL, "l3_div_ck", &l3_div_ck, CK_443X),
CLK(NULL, "l4_div_ck", &l4_div_ck, CK_443X),
CLK(NULL, "lp_clk_div_ck", &lp_clk_div_ck, CK_443X),
CLK(NULL, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, CK_443X),
- CLK(NULL, "per_abe_nc_fclk", &per_abe_nc_fclk, CK_443X),
- CLK(NULL, "mcasp2_fclk", &mcasp2_fclk, CK_443X),
- CLK(NULL, "mcasp3_fclk", &mcasp3_fclk, CK_443X),
CLK(NULL, "ocp_abe_iclk", &ocp_abe_iclk, CK_443X),
CLK(NULL, "per_abe_24m_fclk", &per_abe_24m_fclk, CK_443X),
+ CLK(NULL, "per_abe_nc_fclk", &per_abe_nc_fclk, CK_443X),
CLK(NULL, "pmd_stm_clock_mux_ck", &pmd_stm_clock_mux_ck, CK_443X),
CLK(NULL, "pmd_trace_clk_mux_ck", &pmd_trace_clk_mux_ck, CK_443X),
CLK(NULL, "syc_clk_div_ck", &syc_clk_div_ck, CK_443X),
@@ -3110,14 +3185,16 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "aes2_fck", &aes2_fck, CK_443X),
CLK(NULL, "aess_fck", &aess_fck, CK_443X),
CLK(NULL, "bandgap_fclk", &bandgap_fclk, CK_443X),
+ CLK(NULL, "bandgap_ts_fclk", &bandgap_ts_fclk, CK_446X),
CLK(NULL, "des3des_fck", &des3des_fck, CK_443X),
+ CLK(NULL, "div_ts_ck", &div_ts_ck, CK_446X),
CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X),
CLK(NULL, "dmic_fck", &dmic_fck, CK_443X),
CLK(NULL, "dsp_fck", &dsp_fck, CK_443X),
- CLK("omapdss_dss", "sys_clk", &dss_sys_clk, CK_443X),
- CLK("omapdss_dss", "tv_clk", &dss_tv_clk, CK_443X),
- CLK("omapdss_dss", "video_clk", &dss_48mhz_clk, CK_443X),
- CLK("omapdss_dss", "fck", &dss_dss_clk, CK_443X),
+ CLK(NULL, "dss_sys_clk", &dss_sys_clk, CK_443X),
+ CLK(NULL, "dss_tv_clk", &dss_tv_clk, CK_443X),
+ CLK(NULL, "dss_48mhz_clk", &dss_48mhz_clk, CK_443X),
+ CLK(NULL, "dss_dss_clk", &dss_dss_clk, CK_443X),
CLK("omapdss_dss", "ick", &dss_fck, CK_443X),
CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X),
CLK(NULL, "emif1_fck", &emif1_fck, CK_443X),
@@ -3138,12 +3215,12 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "gpio6_ick", &gpio6_ick, CK_443X),
CLK(NULL, "gpmc_ick", &gpmc_ick, CK_443X),
CLK(NULL, "gpu_fck", &gpu_fck, CK_443X),
- CLK("omap2_hdq.0", "fck", &hdq1w_fck, CK_443X),
+ CLK(NULL, "hdq1w_fck", &hdq1w_fck, CK_443X),
CLK(NULL, "hsi_fck", &hsi_fck, CK_443X),
- CLK("omap_i2c.1", "fck", &i2c1_fck, CK_443X),
- CLK("omap_i2c.2", "fck", &i2c2_fck, CK_443X),
- CLK("omap_i2c.3", "fck", &i2c3_fck, CK_443X),
- CLK("omap_i2c.4", "fck", &i2c4_fck, CK_443X),
+ CLK(NULL, "i2c1_fck", &i2c1_fck, CK_443X),
+ CLK(NULL, "i2c2_fck", &i2c2_fck, CK_443X),
+ CLK(NULL, "i2c3_fck", &i2c3_fck, CK_443X),
+ CLK(NULL, "i2c4_fck", &i2c4_fck, CK_443X),
CLK(NULL, "ipu_fck", &ipu_fck, CK_443X),
CLK(NULL, "iss_ctrlclk", &iss_ctrlclk, CK_443X),
CLK(NULL, "iss_fck", &iss_fck, CK_443X),
@@ -3154,23 +3231,23 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "mcasp_sync_mux_ck", &mcasp_sync_mux_ck, CK_443X),
CLK(NULL, "mcasp_fck", &mcasp_fck, CK_443X),
CLK(NULL, "mcbsp1_sync_mux_ck", &mcbsp1_sync_mux_ck, CK_443X),
- CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_443X),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_443X),
CLK(NULL, "mcbsp2_sync_mux_ck", &mcbsp2_sync_mux_ck, CK_443X),
- CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_443X),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_443X),
CLK(NULL, "mcbsp3_sync_mux_ck", &mcbsp3_sync_mux_ck, CK_443X),
- CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_443X),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_443X),
CLK(NULL, "mcbsp4_sync_mux_ck", &mcbsp4_sync_mux_ck, CK_443X),
- CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_443X),
+ CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_443X),
CLK(NULL, "mcpdm_fck", &mcpdm_fck, CK_443X),
- CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_443X),
- CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_443X),
- CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_443X),
- CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_443X),
- CLK("omap_hsmmc.0", "fck", &mmc1_fck, CK_443X),
- CLK("omap_hsmmc.1", "fck", &mmc2_fck, CK_443X),
- CLK("omap_hsmmc.2", "fck", &mmc3_fck, CK_443X),
- CLK("omap_hsmmc.3", "fck", &mmc4_fck, CK_443X),
- CLK("omap_hsmmc.4", "fck", &mmc5_fck, CK_443X),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_443X),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_443X),
+ CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_443X),
+ CLK(NULL, "mcspi4_fck", &mcspi4_fck, CK_443X),
+ CLK(NULL, "mmc1_fck", &mmc1_fck, CK_443X),
+ CLK(NULL, "mmc2_fck", &mmc2_fck, CK_443X),
+ CLK(NULL, "mmc3_fck", &mmc3_fck, CK_443X),
+ CLK(NULL, "mmc4_fck", &mmc4_fck, CK_443X),
+ CLK(NULL, "mmc5_fck", &mmc5_fck, CK_443X),
CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_443X),
CLK(NULL, "ocp2scp_usb_phy_ick", &ocp2scp_usb_phy_ick, CK_443X),
CLK(NULL, "ocp_wp_noc_ick", &ocp_wp_noc_ick, CK_443X),
@@ -3204,7 +3281,6 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "uart2_fck", &uart2_fck, CK_443X),
CLK(NULL, "uart3_fck", &uart3_fck, CK_443X),
CLK(NULL, "uart4_fck", &uart4_fck, CK_443X),
- CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X),
CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X),
CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X),
CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X),
@@ -3216,9 +3292,7 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X),
CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X),
CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X),
- CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X),
CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X),
- CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X),
CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X),
CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X),
CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X),
@@ -3226,17 +3300,32 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "usb_tll_hs_usb_ch2_clk", &usb_tll_hs_usb_ch2_clk, CK_443X),
CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X),
CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X),
- CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X),
CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
- CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X),
CLK(NULL, "usim_ck", &usim_ck, CK_443X),
CLK(NULL, "usim_fclk", &usim_fclk, CK_443X),
CLK(NULL, "usim_fck", &usim_fck, CK_443X),
- CLK("omap_wdt", "fck", &wd_timer2_fck, CK_443X),
- CLK(NULL, "mailboxes_ick", &dummy_ck, CK_443X),
+ CLK(NULL, "wd_timer2_fck", &wd_timer2_fck, CK_443X),
CLK(NULL, "wd_timer3_fck", &wd_timer3_fck, CK_443X),
CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck, CK_443X),
CLK(NULL, "trace_clk_div_ck", &trace_clk_div_ck, CK_443X),
+ CLK(NULL, "auxclk0_src_ck", &auxclk0_src_ck, CK_443X),
+ CLK(NULL, "auxclk0_ck", &auxclk0_ck, CK_443X),
+ CLK(NULL, "auxclkreq0_ck", &auxclkreq0_ck, CK_443X),
+ CLK(NULL, "auxclk1_src_ck", &auxclk1_src_ck, CK_443X),
+ CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_443X),
+ CLK(NULL, "auxclkreq1_ck", &auxclkreq1_ck, CK_443X),
+ CLK(NULL, "auxclk2_src_ck", &auxclk2_src_ck, CK_443X),
+ CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_443X),
+ CLK(NULL, "auxclkreq2_ck", &auxclkreq2_ck, CK_443X),
+ CLK(NULL, "auxclk3_src_ck", &auxclk3_src_ck, CK_443X),
+ CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_443X),
+ CLK(NULL, "auxclkreq3_ck", &auxclkreq3_ck, CK_443X),
+ CLK(NULL, "auxclk4_src_ck", &auxclk4_src_ck, CK_443X),
+ CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_443X),
+ CLK(NULL, "auxclkreq4_ck", &auxclkreq4_ck, CK_443X),
+ CLK(NULL, "auxclk5_src_ck", &auxclk5_src_ck, CK_443X),
+ CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X),
+ CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_443X),
CLK(NULL, "gpmc_ck", &dummy_ck, CK_443X),
CLK(NULL, "gpt1_ick", &dummy_ck, CK_443X),
CLK(NULL, "gpt2_ick", &dummy_ck, CK_443X),
@@ -3253,6 +3342,7 @@ static struct omap_clk omap44xx_clks[] = {
CLK("omap_i2c.2", "ick", &dummy_ck, CK_443X),
CLK("omap_i2c.3", "ick", &dummy_ck, CK_443X),
CLK("omap_i2c.4", "ick", &dummy_ck, CK_443X),
+ CLK(NULL, "mailboxes_ick", &dummy_ck, CK_443X),
CLK("omap_hsmmc.0", "ick", &dummy_ck, CK_443X),
CLK("omap_hsmmc.1", "ick", &dummy_ck, CK_443X),
CLK("omap_hsmmc.2", "ick", &dummy_ck, CK_443X),
@@ -3270,19 +3360,9 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "uart2_ick", &dummy_ck, CK_443X),
CLK(NULL, "uart3_ick", &dummy_ck, CK_443X),
CLK(NULL, "uart4_ick", &dummy_ck, CK_443X),
+ CLK("usbhs-omap.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(NULL, "auxclk0_ck", &auxclk0_ck, CK_443X),
- CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_443X),
- CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_443X),
- CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_443X),
- CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_443X),
- CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X),
- CLK(NULL, "auxclkreq0_ck", &auxclkreq0_ck, CK_443X),
- CLK(NULL, "auxclkreq1_ck", &auxclkreq1_ck, CK_443X),
- CLK(NULL, "auxclkreq2_ck", &auxclkreq2_ck, CK_443X),
- CLK(NULL, "auxclkreq3_ck", &auxclkreq3_ck, CK_443X),
- CLK(NULL, "auxclkreq4_ck", &auxclkreq4_ck, CK_443X),
- CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_443X),
};
int __init omap4xxx_clk_init(void)
@@ -3293,9 +3373,13 @@ int __init omap4xxx_clk_init(void)
if (cpu_is_omap44xx()) {
cpu_mask = RATE_IN_4430;
cpu_clkflg = CK_443X;
+ } else if (cpu_is_omap446x()) {
+ cpu_mask = RATE_IN_4460;
+ cpu_clkflg = CK_446X;
}
clk_init(&omap2_clk_functions);
+ omap2_clk_disable_clkdm_control();
for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
c++)
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 6cb6c03293df..ab7db083f97f 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -1,8 +1,8 @@
/*
* OMAP2/3/4 clockdomain framework functions
*
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Nokia Corporation
*
* Written by Paul Walmsley and Jouni Högander
* Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
@@ -92,6 +92,8 @@ static int _clkdm_register(struct clockdomain *clkdm)
pwrdm_add_clkdm(pwrdm, clkdm);
+ spin_lock_init(&clkdm->lock);
+
pr_debug("clockdomain: registered %s\n", clkdm->name);
return 0;
@@ -690,6 +692,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
*/
int clkdm_sleep(struct clockdomain *clkdm)
{
+ int ret;
+ unsigned long flags;
+
if (!clkdm)
return -EINVAL;
@@ -704,7 +709,11 @@ int clkdm_sleep(struct clockdomain *clkdm)
pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
- return arch_clkdm->clkdm_sleep(clkdm);
+ spin_lock_irqsave(&clkdm->lock, flags);
+ clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
+ ret = arch_clkdm->clkdm_sleep(clkdm);
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+ return ret;
}
/**
@@ -718,6 +727,9 @@ int clkdm_sleep(struct clockdomain *clkdm)
*/
int clkdm_wakeup(struct clockdomain *clkdm)
{
+ int ret;
+ unsigned long flags;
+
if (!clkdm)
return -EINVAL;
@@ -732,7 +744,11 @@ int clkdm_wakeup(struct clockdomain *clkdm)
pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
- return arch_clkdm->clkdm_wakeup(clkdm);
+ spin_lock_irqsave(&clkdm->lock, flags);
+ clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
+ ret = arch_clkdm->clkdm_wakeup(clkdm);
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+ return ret;
}
/**
@@ -747,6 +763,8 @@ int clkdm_wakeup(struct clockdomain *clkdm)
*/
void clkdm_allow_idle(struct clockdomain *clkdm)
{
+ unsigned long flags;
+
if (!clkdm)
return;
@@ -762,8 +780,11 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
clkdm->name);
+ spin_lock_irqsave(&clkdm->lock, flags);
+ clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
arch_clkdm->clkdm_allow_idle(clkdm);
pwrdm_clkdm_state_switch(clkdm);
+ spin_unlock_irqrestore(&clkdm->lock, flags);
}
/**
@@ -777,6 +798,8 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
*/
void clkdm_deny_idle(struct clockdomain *clkdm)
{
+ unsigned long flags;
+
if (!clkdm)
return;
@@ -792,11 +815,90 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
clkdm->name);
+ spin_lock_irqsave(&clkdm->lock, flags);
+ clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
arch_clkdm->clkdm_deny_idle(clkdm);
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+}
+
+/**
+ * clkdm_in_hwsup - is clockdomain @clkdm have hardware-supervised idle enabled?
+ * @clkdm: struct clockdomain *
+ *
+ * Returns true if clockdomain @clkdm currently has
+ * hardware-supervised idle enabled, or false if it does not or if
+ * @clkdm is NULL. It is only valid to call this function after
+ * clkdm_init() has been called. This function does not actually read
+ * bits from the hardware; it instead tests an in-memory flag that is
+ * changed whenever the clockdomain code changes the auto-idle mode.
+ */
+bool clkdm_in_hwsup(struct clockdomain *clkdm)
+{
+ bool ret;
+ unsigned long flags;
+
+ if (!clkdm)
+ return false;
+
+ spin_lock_irqsave(&clkdm->lock, flags);
+ ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false;
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+
+ return ret;
+}
+
+/* Clockdomain-to-clock/hwmod framework interface code */
+
+static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
+{
+ unsigned long flags;
+
+ if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+ return -EINVAL;
+
+ /*
+ * For arch's with no autodeps, clkcm_clk_enable
+ * should be called for every clock instance or hwmod that is
+ * enabled, so the clkdm can be force woken up.
+ */
+ if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
+ return 0;
+
+ spin_lock_irqsave(&clkdm->lock, flags);
+ arch_clkdm->clkdm_clk_enable(clkdm);
+ pwrdm_wait_transition(clkdm->pwrdm.ptr);
+ pwrdm_clkdm_state_switch(clkdm);
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+
+ pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
+
+ return 0;
}
+static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
+{
+ unsigned long flags;
+
+ if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+ return -EINVAL;
+
+ if (atomic_read(&clkdm->usecount) == 0) {
+ WARN_ON(1); /* underflow */
+ return -ERANGE;
+ }
+
+ if (atomic_dec_return(&clkdm->usecount) > 0)
+ return 0;
+
+ spin_lock_irqsave(&clkdm->lock, flags);
+ arch_clkdm->clkdm_clk_disable(clkdm);
+ pwrdm_clkdm_state_switch(clkdm);
+ spin_unlock_irqrestore(&clkdm->lock, flags);
-/* Clockdomain-to-clock framework interface code */
+ pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
+
+ return 0;
+}
/**
* clkdm_clk_enable - add an enabled downstream clock to this clkdm
@@ -819,25 +921,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
* downstream clocks for debugging purposes?
*/
- if (!clkdm || !clk)
+ if (!clk)
return -EINVAL;
- if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
- return -EINVAL;
-
- if (atomic_inc_return(&clkdm->usecount) > 1)
- return 0;
-
- /* Clockdomain now has one enabled downstream clock */
-
- pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
- clk->name);
-
- arch_clkdm->clkdm_clk_enable(clkdm);
- pwrdm_wait_transition(clkdm->pwrdm.ptr);
- pwrdm_clkdm_state_switch(clkdm);
-
- return 0;
+ return _clkdm_clk_hwmod_enable(clkdm);
}
/**
@@ -850,9 +937,8 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
* clockdomain usecount goes to 0, put the clockdomain to sleep
* (software-supervised mode) or remove the clkdm autodependencies
* (hardware-supervised mode). Returns -EINVAL if passed null
- * pointers; -ERANGE if the @clkdm usecount underflows and debugging
- * is enabled; or returns 0 upon success or if the clockdomain is in
- * hwsup idle mode.
+ * pointers; -ERANGE if the @clkdm usecount underflows; or returns 0
+ * upon success or if the clockdomain is in hwsup idle mode.
*/
int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
{
@@ -861,30 +947,72 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
* downstream clocks for debugging purposes?
*/
- if (!clkdm || !clk)
+ if (!clk)
return -EINVAL;
- if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+ return _clkdm_clk_hwmod_disable(clkdm);
+}
+
+/**
+ * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the enabled downstream hwmod
+ *
+ * Increment the usecount of the clockdomain @clkdm and ensure that it
+ * is awake before @oh is enabled. Intended to be called by
+ * module_enable() code.
+ * If the clockdomain is in software-supervised idle mode, force the
+ * clockdomain to wake. If the clockdomain is in hardware-supervised idle
+ * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the
+ * clockdomain can be read from/written to by on-chip processors.
+ * Returns -EINVAL if passed null pointers;
+ * returns 0 upon success or if the clockdomain is in hwsup idle mode.
+ */
+int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+ /* The clkdm attribute does not exist yet prior OMAP4 */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ return 0;
+
+ /*
+ * XXX Rewrite this code to maintain a list of enabled
+ * downstream hwmods for debugging purposes?
+ */
+
+ if (!oh)
return -EINVAL;
-#ifdef DEBUG
- if (atomic_read(&clkdm->usecount) == 0) {
- WARN_ON(1); /* underflow */
- return -ERANGE;
- }
-#endif
+ return _clkdm_clk_hwmod_enable(clkdm);
+}
- if (atomic_dec_return(&clkdm->usecount) > 0)
+/**
+ * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the disabled downstream hwmod
+ *
+ * Decrement the usecount of this clockdomain @clkdm when @oh is
+ * disabled. Intended to be called by module_disable() code.
+ * If the clockdomain usecount goes to 0, put the clockdomain to sleep
+ * (software-supervised mode) or remove the clkdm autodependencies
+ * (hardware-supervised mode).
+ * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount
+ * underflows; or returns 0 upon success or if the clockdomain is in hwsup
+ * idle mode.
+ */
+int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+ /* The clkdm attribute does not exist yet prior OMAP4 */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
return 0;
- /* All downstream clocks of this clockdomain are now disabled */
-
- pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
- clk->name);
+ /*
+ * XXX Rewrite this code to maintain a list of enabled
+ * downstream hwmods for debugging purposes?
+ */
- arch_clkdm->clkdm_clk_disable(clkdm);
- pwrdm_clkdm_state_switch(clkdm);
+ if (!oh)
+ return -EINVAL;
- return 0;
+ return _clkdm_clk_hwmod_disable(clkdm);
}
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 5823584d9cd7..1e50c88b8a07 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -17,9 +17,11 @@
#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
#include <linux/init.h>
+#include <linux/spinlock.h>
#include "powerdomain.h"
#include <plat/clock.h>
+#include <plat/omap_hwmod.h>
#include <plat/cpu.h>
/*
@@ -82,6 +84,9 @@ struct clkdm_dep {
const struct omap_chip_id omap_chip;
};
+/* Possible flags for struct clockdomain._flags */
+#define _CLKDM_FLAG_HWSUP_ENABLED BIT(0)
+
/**
* struct clockdomain - OMAP clockdomain
* @name: clockdomain name
@@ -89,6 +94,7 @@ struct clkdm_dep {
* @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
* @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
* @flags: Clockdomain capability flags
+ * @_flags: Flags for use only by internal clockdomain code
* @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
* @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers
* @cm_inst: (OMAP4 only) CM instance register offset
@@ -113,6 +119,7 @@ struct clockdomain {
} pwrdm;
const u16 clktrctrl_mask;
const u8 flags;
+ u8 _flags;
const u8 dep_bit;
const u8 prcm_partition;
const s16 cm_inst;
@@ -122,6 +129,7 @@ struct clockdomain {
const struct omap_chip_id omap_chip;
atomic_t usecount;
struct list_head node;
+ spinlock_t lock;
};
/**
@@ -177,12 +185,15 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
void clkdm_allow_idle(struct clockdomain *clkdm);
void clkdm_deny_idle(struct clockdomain *clkdm);
+bool clkdm_in_hwsup(struct clockdomain *clkdm);
int clkdm_wakeup(struct clockdomain *clkdm);
int clkdm_sleep(struct clockdomain *clkdm);
int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
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 omap3xxx_clockdomains_init(void);
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
index 48d0db7e6069..f740edb111f4 100644
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -183,7 +183,8 @@ static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
_clkdm_add_autodeps(clkdm);
_enable_hwsup(clkdm);
} else {
- clkdm_wakeup(clkdm);
+ if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+ omap2_clkdm_wakeup(clkdm);
}
return 0;
@@ -205,7 +206,8 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
_clkdm_del_autodeps(clkdm);
_enable_hwsup(clkdm);
} else {
- clkdm_sleep(clkdm);
+ if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+ omap2_clkdm_sleep(clkdm);
}
return 0;
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index a1a4ecd26544..b43706aa08bd 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -95,13 +95,8 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
{
- bool hwsup = false;
-
- hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
- clkdm->cm_inst, clkdm->clkdm_offs);
-
- if (!hwsup)
- clkdm_wakeup(clkdm);
+ if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+ return omap4_clkdm_wakeup(clkdm);
return 0;
}
@@ -113,8 +108,8 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
clkdm->cm_inst, clkdm->clkdm_offs);
- if (!hwsup)
- clkdm_sleep(clkdm);
+ if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+ omap4_clkdm_sleep(clkdm);
return 0;
}
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index a607ec196e8b..dccc651fa0d0 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -1,11 +1,12 @@
/*
* OMAP4 Clock domains framework
*
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Nokia Corporation
*
* Abhijit Pagare (abhijitpagare@ti.com)
* Benoit Cousson (b-cousson@ti.com)
+ * Paul Walmsley (paul@pwsan.com)
*
* This file is automatically generated from the OMAP hardware databases.
* We respectfully ask that any modifications to this file be coordinated
@@ -32,7 +33,7 @@
/* Static Dependencies for OMAP4 Clock Domains */
-static struct clkdm_dep ducati_wkup_sleep_deps[] = {
+static struct clkdm_dep d2d_wkup_sleep_deps[] = {
{
.clkdm_name = "abe_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
@@ -50,103 +51,103 @@ static struct clkdm_dep ducati_wkup_sleep_deps[] = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_dss_clkdm",
+ .clkdm_name = "l3_emif_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_emif_clkdm",
+ .clkdm_name = "l3_init_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_gfx_clkdm",
+ .clkdm_name = "l4_cfg_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_init_clkdm",
+ .clkdm_name = "l4_per_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
+ { NULL },
+};
+
+static struct clkdm_dep ducati_wkup_sleep_deps[] = {
{
- .clkdm_name = "l4_cfg_clkdm",
+ .clkdm_name = "abe_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l4_per_clkdm",
+ .clkdm_name = "ivahd_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l4_secure_clkdm",
+ .clkdm_name = "l3_1_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l4_wkup_clkdm",
+ .clkdm_name = "l3_2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "tesla_clkdm",
+ .clkdm_name = "l3_dss_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
- { NULL },
-};
-
-static struct clkdm_dep iss_wkup_sleep_deps[] = {
{
- .clkdm_name = "ivahd_clkdm",
+ .clkdm_name = "l3_emif_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_1_clkdm",
+ .clkdm_name = "l3_gfx_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_emif_clkdm",
+ .clkdm_name = "l3_init_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
- { NULL },
-};
-
-static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
{
- .clkdm_name = "l3_1_clkdm",
+ .clkdm_name = "l4_cfg_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_emif_clkdm",
+ .clkdm_name = "l4_per_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
- { NULL },
-};
-
-static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = {
{
- .clkdm_name = "abe_clkdm",
+ .clkdm_name = "l4_secure_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "ivahd_clkdm",
+ .clkdm_name = "l4_wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_1_clkdm",
+ .clkdm_name = "tesla_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
+ { NULL },
+};
+
+static struct clkdm_dep iss_wkup_sleep_deps[] = {
{
- .clkdm_name = "l3_2_clkdm",
+ .clkdm_name = "ivahd_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_emif_clkdm",
+ .clkdm_name = "l3_1_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l3_init_clkdm",
+ .clkdm_name = "l3_emif_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
+ { NULL },
+};
+
+static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
{
- .clkdm_name = "l4_cfg_clkdm",
+ .clkdm_name = "l3_1_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{
- .clkdm_name = "l4_per_clkdm",
+ .clkdm_name = "l3_emif_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
},
{ NULL },
@@ -280,7 +281,7 @@ static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
{ NULL },
};
-static struct clkdm_dep mpuss_wkup_sleep_deps[] = {
+static struct clkdm_dep mpu_wkup_sleep_deps[] = {
{
.clkdm_name = "abe_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
@@ -497,14 +498,14 @@ static struct clockdomain l3_init_44xx_clkdm = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
-static struct clockdomain mpuss_44xx_clkdm = {
- .name = "mpuss_clkdm",
- .pwrdm = { .name = "mpu_pwrdm" },
- .prcm_partition = OMAP4430_CM1_PARTITION,
- .cm_inst = OMAP4430_CM1_MPU_INST,
- .clkdm_offs = OMAP4430_CM1_MPU_MPU_CDOFFS,
- .wkdep_srcs = mpuss_wkup_sleep_deps,
- .sleepdep_srcs = mpuss_wkup_sleep_deps,
+static struct clockdomain d2d_44xx_clkdm = {
+ .name = "d2d_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_D2D_CDOFFS,
+ .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),
};
@@ -563,6 +564,18 @@ static struct clockdomain ducati_44xx_clkdm = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
+static struct clockdomain mpu_44xx_clkdm = {
+ .name = "mpuss_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .prcm_partition = OMAP4430_CM1_PARTITION,
+ .cm_inst = OMAP4430_CM1_MPU_INST,
+ .clkdm_offs = OMAP4430_CM1_MPU_MPU_CDOFFS,
+ .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 = {
.name = "l3_2_clkdm",
.pwrdm = { .name = "core_pwrdm" },
@@ -585,18 +598,6 @@ static struct clockdomain l3_1_44xx_clkdm = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
-static struct clockdomain l3_d2d_44xx_clkdm = {
- .name = "l3_d2d_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .prcm_partition = OMAP4430_CM2_PARTITION,
- .cm_inst = OMAP4430_CM2_CORE_INST,
- .clkdm_offs = OMAP4430_CM2_CORE_D2D_CDOFFS,
- .wkdep_srcs = l3_d2d_wkup_sleep_deps,
- .sleepdep_srcs = l3_d2d_wkup_sleep_deps,
- .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
static struct clockdomain iss_44xx_clkdm = {
.name = "iss_clkdm",
.pwrdm = { .name = "cam_pwrdm" },
@@ -655,6 +656,7 @@ static struct clockdomain l3_dma_44xx_clkdm = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
+/* As clockdomains are added or removed above, this list must also be changed */
static struct clockdomain *clockdomains_omap44xx[] __initdata = {
&l4_cefuse_44xx_clkdm,
&l4_cfg_44xx_clkdm,
@@ -666,21 +668,21 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = {
&abe_44xx_clkdm,
&l3_instr_44xx_clkdm,
&l3_init_44xx_clkdm,
- &mpuss_44xx_clkdm,
+ &d2d_44xx_clkdm,
&mpu0_44xx_clkdm,
&mpu1_44xx_clkdm,
&l3_emif_44xx_clkdm,
&l4_ao_44xx_clkdm,
&ducati_44xx_clkdm,
+ &mpu_44xx_clkdm,
&l3_2_44xx_clkdm,
&l3_1_44xx_clkdm,
- &l3_d2d_44xx_clkdm,
&iss_44xx_clkdm,
&l3_dss_44xx_clkdm,
&l4_wkup_44xx_clkdm,
&emu_sys_44xx_clkdm,
&l3_dma_44xx_clkdm,
- NULL,
+ NULL
};
void __init omap44xx_clockdomains_init(void)
diff --git a/arch/arm/mach-omap2/cm-regbits-44xx.h b/arch/arm/mach-omap2/cm-regbits-44xx.h
index 9d47a05b17b4..65597a745638 100644
--- a/arch/arm/mach-omap2/cm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-44xx.h
@@ -22,22 +22,18 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H
#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H
-/*
- * Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP,
- * CM_TESLA_DYNAMICDEP
- */
+/* Used by CM_L3_1_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
#define OMAP4430_ABE_DYNDEP_SHIFT 3
#define OMAP4430_ABE_DYNDEP_MASK (1 << 3)
/*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_ABE_STATDEP_SHIFT 3
#define OMAP4430_ABE_STATDEP_MASK (1 << 3)
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
#define OMAP4430_ALWONCORE_DYNDEP_SHIFT 16
#define OMAP4430_ALWONCORE_DYNDEP_MASK (1 << 16)
@@ -47,14 +43,13 @@
/*
* Used by CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
- * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_DDRPHY,
- * CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER,
- * CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
+ * CM_AUTOIDLE_DPLL_DDRPHY, CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU,
+ * CM_AUTOIDLE_DPLL_PER, CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
*/
#define OMAP4430_AUTO_DPLL_MODE_SHIFT 0
#define OMAP4430_AUTO_DPLL_MODE_MASK (0x7 << 0)
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
#define OMAP4430_CEFUSE_DYNDEP_SHIFT 17
#define OMAP4430_CEFUSE_DYNDEP_MASK (1 << 17)
@@ -82,15 +77,15 @@
#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK (1 << 8)
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_SHIFT 11
#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK (1 << 11)
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_SHIFT 12
#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK (1 << 12)
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_SHIFT 13
#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK (1 << 13)
@@ -106,35 +101,39 @@
#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT 9
#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK (1 << 9)
+/* Used by CM_L4CFG_CLKSTCTRL */
+#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_SHIFT 9
+#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_MASK (1 << 9)
+
/* Used by CM_CEFUSE_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT 9
#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK (1 << 9)
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_DLL_CLK_SHIFT 9
#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK (1 << 9)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_SHIFT 9
#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK (1 << 9)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_SHIFT 10
#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK (1 << 10)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_SHIFT 11
#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK (1 << 11)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_SHIFT 12
#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK (1 << 12)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_SHIFT 13
#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK (1 << 13)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_SHIFT 14
#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK (1 << 14)
@@ -158,7 +157,7 @@
#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_SHIFT 10
#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK (1 << 10)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_SHIFT 15
#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK (1 << 15)
@@ -170,55 +169,55 @@
#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_SHIFT 11
#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK (1 << 11)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_SHIFT 20
#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK (1 << 20)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_SHIFT 26
#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK (1 << 26)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_SHIFT 21
#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK (1 << 21)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_SHIFT 27
#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK (1 << 27)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_SHIFT 13
#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK (1 << 13)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_SHIFT 12
#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK (1 << 12)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_SHIFT 28
#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK (1 << 28)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_SHIFT 29
#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK (1 << 29)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_SHIFT 11
#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK (1 << 11)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_SHIFT 16
#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK (1 << 16)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_SHIFT 17
#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK (1 << 17)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_SHIFT 18
#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK (1 << 18)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_SHIFT 19
#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK (1 << 19)
@@ -234,11 +233,11 @@
#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_SHIFT 10
#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_MASK (1 << 10)
-/* Used by CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE */
+/* Used by CM_L3_1_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_L3_1_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK (1 << 8)
-/* Used by CM_L3_2_CLKSTCTRL, CM_L3_2_CLKSTCTRL_RESTORE */
+/* Used by CM_L3_2_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_L3_2_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK (1 << 8)
@@ -254,7 +253,7 @@
#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK (1 << 8)
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK (1 << 8)
@@ -262,7 +261,7 @@
#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK (1 << 8)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK (1 << 8)
@@ -282,7 +281,7 @@
#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK (1 << 8)
-/* Used by CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE */
+/* Used by CM_L4CFG_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK (1 << 8)
@@ -290,11 +289,11 @@
#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_SHIFT 9
#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK (1 << 9)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_SHIFT 9
#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK (1 << 9)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK (1 << 8)
@@ -306,7 +305,7 @@
#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_SHIFT 12
#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK (1 << 12)
-/* Used by CM_MPU_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE */
+/* Used by CM_MPU_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK (1 << 8)
@@ -314,43 +313,43 @@
#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_SHIFT 9
#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK (1 << 9)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_SHIFT 16
#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK (1 << 16)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_SHIFT 17
#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK (1 << 17)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_SHIFT 18
#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK (1 << 18)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_SHIFT 19
#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK (1 << 19)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_SHIFT 25
#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK (1 << 25)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_SHIFT 20
#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK (1 << 20)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_SHIFT 21
#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK (1 << 21)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_SHIFT 22
#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK (1 << 22)
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_SHIFT 24
#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK (1 << 24)
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_SHIFT 10
#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK (1 << 10)
@@ -378,27 +377,27 @@
#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_SHIFT 8
#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK (1 << 8)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_SHIFT 22
#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK (1 << 22)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_SHIFT 23
#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK (1 << 23)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_SHIFT 24
#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK (1 << 24)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_SHIFT 10
#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_MASK (1 << 10)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_SHIFT 14
#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_MASK (1 << 14)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_SHIFT 15
#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK (1 << 15)
@@ -406,11 +405,11 @@
#define OMAP4430_CLKACTIVITY_USIM_GFCLK_SHIFT 10
#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK (1 << 10)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_SHIFT 30
#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK (1 << 30)
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_SHIFT 25
#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK (1 << 25)
@@ -418,6 +417,10 @@
#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT 11
#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK (1 << 11)
+/* Used by CM_WKUP_CLKSTCTRL */
+#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_SHIFT 13
+#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_MASK (1 << 13)
+
/*
* Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
* CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
@@ -432,7 +435,7 @@
/*
* Renamed from CLKSEL Used by CM_ABE_DSS_SYS_CLKSEL, CM_ABE_PLL_REF_CLKSEL,
- * CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ
+ * CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ, CM_L4_WKUP_CLKSEL
*/
#define OMAP4430_CLKSEL_0_0_SHIFT 0
#define OMAP4430_CLKSEL_0_0_MASK (1 << 0)
@@ -449,18 +452,19 @@
#define OMAP4430_CLKSEL_60M_SHIFT 24
#define OMAP4430_CLKSEL_60M_MASK (1 << 24)
+/* Used by CM_MPU_MPU_CLKCTRL */
+#define OMAP4460_CLKSEL_ABE_DIV_MODE_SHIFT 25
+#define OMAP4460_CLKSEL_ABE_DIV_MODE_MASK (1 << 25)
+
/* Used by CM1_ABE_AESS_CLKCTRL */
#define OMAP4430_CLKSEL_AESS_FCLK_SHIFT 24
#define OMAP4430_CLKSEL_AESS_FCLK_MASK (1 << 24)
-/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
+/* Used by CM_CLKSEL_CORE */
#define OMAP4430_CLKSEL_CORE_SHIFT 0
#define OMAP4430_CLKSEL_CORE_MASK (1 << 0)
-/*
- * Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
- * CM_SHADOW_FREQ_CONFIG2
- */
+/* Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2 */
#define OMAP4430_CLKSEL_CORE_1_1_SHIFT 1
#define OMAP4430_CLKSEL_CORE_1_1_MASK (1 << 1)
@@ -468,6 +472,10 @@
#define OMAP4430_CLKSEL_DIV_SHIFT 24
#define OMAP4430_CLKSEL_DIV_MASK (1 << 24)
+/* Used by CM_MPU_MPU_CLKCTRL */
+#define OMAP4460_CLKSEL_EMIF_DIV_MODE_SHIFT 24
+#define OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK (1 << 24)
+
/* Used by CM_CAM_FDIF_CLKCTRL */
#define OMAP4430_CLKSEL_FCLK_SHIFT 24
#define OMAP4430_CLKSEL_FCLK_MASK (0x3 << 24)
@@ -484,18 +492,15 @@
#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_SHIFT 26
#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK (0x3 << 26)
-/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
+/* Used by CM_CLKSEL_CORE */
#define OMAP4430_CLKSEL_L3_SHIFT 4
#define OMAP4430_CLKSEL_L3_MASK (1 << 4)
-/*
- * Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
- * CM_SHADOW_FREQ_CONFIG2
- */
+/* Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2 */
#define OMAP4430_CLKSEL_L3_SHADOW_SHIFT 2
#define OMAP4430_CLKSEL_L3_SHADOW_MASK (1 << 2)
-/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
+/* Used by CM_CLKSEL_CORE */
#define OMAP4430_CLKSEL_L4_SHIFT 8
#define OMAP4430_CLKSEL_L4_MASK (1 << 8)
@@ -526,11 +531,11 @@
#define OMAP4430_CLKSEL_SOURCE_24_24_SHIFT 24
#define OMAP4430_CLKSEL_SOURCE_24_24_MASK (1 << 24)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_CLKSEL_UTMI_P1_SHIFT 24
#define OMAP4430_CLKSEL_UTMI_P1_MASK (1 << 24)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_CLKSEL_UTMI_P2_SHIFT 25
#define OMAP4430_CLKSEL_UTMI_P2_MASK (1 << 25)
@@ -538,13 +543,10 @@
* Used by CM1_ABE_CLKSTCTRL, CM_ALWON_CLKSTCTRL, CM_CAM_CLKSTCTRL,
* CM_CEFUSE_CLKSTCTRL, CM_D2D_CLKSTCTRL, CM_DSS_CLKSTCTRL,
* CM_DUCATI_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_IVAHD_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3INSTR_CLKSTCTRL,
- * CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE, CM_L3_2_CLKSTCTRL,
- * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE,
- * CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE, CM_L4SEC_CLKSTCTRL,
- * CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE, CM_MPU_CLKSTCTRL,
- * CM_MPU_CLKSTCTRL_RESTORE, CM_SDMA_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
- * CM_WKUP_CLKSTCTRL
+ * CM_L3INIT_CLKSTCTRL, CM_L3INSTR_CLKSTCTRL, CM_L3_1_CLKSTCTRL,
+ * CM_L3_2_CLKSTCTRL, CM_L4CFG_CLKSTCTRL, CM_L4PER_CLKSTCTRL,
+ * CM_L4SEC_CLKSTCTRL, CM_MEMIF_CLKSTCTRL, CM_MPU_CLKSTCTRL, CM_SDMA_CLKSTCTRL,
+ * CM_TESLA_CLKSTCTRL, CM_WKUP_CLKSTCTRL
*/
#define OMAP4430_CLKTRCTRL_SHIFT 0
#define OMAP4430_CLKTRCTRL_MASK (0x3 << 0)
@@ -561,10 +563,7 @@
#define OMAP4430_CUSTOM_SHIFT 6
#define OMAP4430_CUSTOM_MASK (0x3 << 6)
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
#define OMAP4430_D2D_DYNDEP_SHIFT 18
#define OMAP4430_D2D_DYNDEP_MASK (1 << 18)
@@ -572,33 +571,43 @@
#define OMAP4430_D2D_STATDEP_SHIFT 18
#define OMAP4430_D2D_STATDEP_MASK (1 << 18)
+/* Used by CM_CLKSEL_DPLL_MPU */
+#define OMAP4460_DCC_COUNT_MAX_SHIFT 24
+#define OMAP4460_DCC_COUNT_MAX_MASK (0xff << 24)
+
+/* Used by CM_CLKSEL_DPLL_MPU */
+#define OMAP4460_DCC_EN_SHIFT 22
+#define OMAP4460_DCC_EN_MASK (1 << 22)
+
/*
* Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
- * CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE, CM_SSC_DELTAMSTEP_DPLL_DDRPHY,
- * CM_SSC_DELTAMSTEP_DPLL_IVA, CM_SSC_DELTAMSTEP_DPLL_MPU,
- * CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
- * CM_SSC_DELTAMSTEP_DPLL_USB
+ * CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA,
+ * CM_SSC_DELTAMSTEP_DPLL_MPU, CM_SSC_DELTAMSTEP_DPLL_PER,
+ * CM_SSC_DELTAMSTEP_DPLL_UNIPRO, CM_SSC_DELTAMSTEP_DPLL_USB
*/
#define OMAP4430_DELTAMSTEP_SHIFT 0
#define OMAP4430_DELTAMSTEP_MASK (0xfffff << 0)
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
-#define OMAP4430_DLL_OVERRIDE_SHIFT 2
-#define OMAP4430_DLL_OVERRIDE_MASK (1 << 2)
+/* Renamed from DELTAMSTEP Used by CM_SSC_DELTAMSTEP_DPLL_USB */
+#define OMAP4460_DELTAMSTEP_0_20_SHIFT 0
+#define OMAP4460_DELTAMSTEP_0_20_MASK (0x1fffff << 0)
-/* Renamed from DLL_OVERRIDE Used by CM_DLL_CTRL */
-#define OMAP4430_DLL_OVERRIDE_0_0_SHIFT 0
-#define OMAP4430_DLL_OVERRIDE_0_0_MASK (1 << 0)
+/* Used by CM_DLL_CTRL */
+#define OMAP4430_DLL_OVERRIDE_SHIFT 0
+#define OMAP4430_DLL_OVERRIDE_MASK (1 << 0)
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Renamed from DLL_OVERRIDE Used by CM_SHADOW_FREQ_CONFIG1 */
+#define OMAP4430_DLL_OVERRIDE_2_2_SHIFT 2
+#define OMAP4430_DLL_OVERRIDE_2_2_MASK (1 << 2)
+
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
#define OMAP4430_DLL_RESET_SHIFT 3
#define OMAP4430_DLL_RESET_MASK (1 << 3)
/*
- * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
- * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_USB
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDRPHY,
+ * CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER,
+ * CM_CLKSEL_DPLL_UNIPRO, CM_CLKSEL_DPLL_USB
*/
#define OMAP4430_DPLL_BYP_CLKSEL_SHIFT 23
#define OMAP4430_DPLL_BYP_CLKSEL_MASK (1 << 23)
@@ -607,28 +616,19 @@
#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT 8
#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK (1 << 8)
-/* Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_CORE_RESTORE */
+/* Used by CM_CLKSEL_DPLL_CORE */
#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_SHIFT 20
#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK (1 << 20)
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
#define OMAP4430_DPLL_CLKOUTHIF_DIV_SHIFT 0
#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK (0x1f << 0)
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_SHIFT 5
#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK (1 << 5)
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT 8
#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK (1 << 8)
@@ -637,9 +637,8 @@
#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK (1 << 10)
/*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
*/
#define OMAP4430_DPLL_CLKOUT_DIV_SHIFT 0
#define OMAP4430_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
@@ -649,9 +648,8 @@
#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK (0x7f << 0)
/*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
*/
#define OMAP4430_DPLL_CLKOUT_DIVCHACK_SHIFT 5
#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK (1 << 5)
@@ -661,29 +659,28 @@
#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK (1 << 7)
/*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
*/
#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT 8
#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK (1 << 8)
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
#define OMAP4430_DPLL_CORE_DPLL_EN_SHIFT 8
#define OMAP4430_DPLL_CORE_DPLL_EN_MASK (0x7 << 8)
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
#define OMAP4430_DPLL_CORE_M2_DIV_SHIFT 11
#define OMAP4430_DPLL_CORE_M2_DIV_MASK (0x1f << 11)
-/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG2 */
#define OMAP4430_DPLL_CORE_M5_DIV_SHIFT 3
#define OMAP4430_DPLL_CORE_M5_DIV_MASK (0x1f << 3)
/*
- * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
- * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDRPHY,
+ * CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER,
+ * CM_CLKSEL_DPLL_UNIPRO
*/
#define OMAP4430_DPLL_DIV_SHIFT 0
#define OMAP4430_DPLL_DIV_MASK (0x7f << 0)
@@ -693,9 +690,8 @@
#define OMAP4430_DPLL_DIV_0_7_MASK (0xff << 0)
/*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
*/
#define OMAP4430_DPLL_DRIFTGUARD_EN_SHIFT 8
#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK (1 << 8)
@@ -705,26 +701,25 @@
#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK (1 << 3)
/*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
*/
#define OMAP4430_DPLL_EN_SHIFT 0
#define OMAP4430_DPLL_EN_MASK (0x7 << 0)
/*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO
*/
#define OMAP4430_DPLL_LPMODE_EN_SHIFT 10
#define OMAP4430_DPLL_LPMODE_EN_MASK (1 << 10)
/*
- * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
- * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDRPHY,
+ * CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER,
+ * CM_CLKSEL_DPLL_UNIPRO
*/
#define OMAP4430_DPLL_MULT_SHIFT 8
#define OMAP4430_DPLL_MULT_MASK (0x7ff << 8)
@@ -734,9 +729,9 @@
#define OMAP4430_DPLL_MULT_USB_MASK (0xfff << 8)
/*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO
*/
#define OMAP4430_DPLL_REGM4XEN_SHIFT 11
#define OMAP4430_DPLL_REGM4XEN_MASK (1 << 11)
@@ -746,55 +741,46 @@
#define OMAP4430_DPLL_SD_DIV_MASK (0xff << 24)
/*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
*/
#define OMAP4430_DPLL_SSC_ACK_SHIFT 13
#define OMAP4430_DPLL_SSC_ACK_MASK (1 << 13)
/*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
*/
#define OMAP4430_DPLL_SSC_DOWNSPREAD_SHIFT 14
#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK (1 << 14)
/*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
*/
#define OMAP4430_DPLL_SSC_EN_SHIFT 12
#define OMAP4430_DPLL_SSC_EN_MASK (1 << 12)
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
#define OMAP4430_DSS_DYNDEP_SHIFT 8
#define OMAP4430_DSS_DYNDEP_MASK (1 << 8)
-/*
- * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE
- */
+/* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP */
#define OMAP4430_DSS_STATDEP_SHIFT 8
#define OMAP4430_DSS_STATDEP_MASK (1 << 8)
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_2_DYNAMICDEP */
#define OMAP4430_DUCATI_DYNDEP_SHIFT 0
#define OMAP4430_DUCATI_DYNDEP_MASK (1 << 0)
-/* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE */
+/* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP */
#define OMAP4430_DUCATI_STATDEP_SHIFT 0
#define OMAP4430_DUCATI_STATDEP_MASK (1 << 0)
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
#define OMAP4430_FREQ_UPDATE_SHIFT 0
#define OMAP4430_FREQ_UPDATE_MASK (1 << 0)
@@ -802,7 +788,7 @@
#define OMAP4430_FUNC_SHIFT 16
#define OMAP4430_FUNC_MASK (0xfff << 16)
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_2_DYNAMICDEP */
#define OMAP4430_GFX_DYNDEP_SHIFT 10
#define OMAP4430_GFX_DYNDEP_MASK (1 << 10)
@@ -810,119 +796,95 @@
#define OMAP4430_GFX_STATDEP_SHIFT 10
#define OMAP4430_GFX_STATDEP_MASK (1 << 10)
-/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG2 */
#define OMAP4430_GPMC_FREQ_UPDATE_SHIFT 0
#define OMAP4430_GPMC_FREQ_UPDATE_MASK (1 << 0)
/*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_SHIFT 0
#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK (0x1f << 0)
/*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT 5
#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK (1 << 5)
/*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT 8
#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK (1 << 8)
/*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_SHIFT 12
#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK (1 << 12)
/*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_SHIFT 0
#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK (0x1f << 0)
/*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT 5
#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK (1 << 5)
/*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT 8
#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK (1 << 8)
/*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
*/
#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_SHIFT 12
#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK (1 << 12)
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_SHIFT 0
#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK (0x1f << 0)
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT 5
#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK (1 << 5)
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT 8
#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK (1 << 8)
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_SHIFT 12
#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK (1 << 12)
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_SHIFT 0
#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK (0x1f << 0)
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_SHIFT 5
#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK (1 << 5)
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_SHIFT 8
#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK (1 << 8)
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_SHIFT 12
#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK (1 << 12)
@@ -934,8 +896,7 @@
* CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
* CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
* CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
- * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
* CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
* CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
* CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
@@ -944,30 +905,24 @@
* CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
* CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
* CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL,
* CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
* CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
* CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
* CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
* CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
* CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
- * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
- * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
- * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
- * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
- * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
- * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
- * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL,
+ * CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL,
+ * CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL,
+ * CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL,
+ * CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL,
+ * CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL,
+ * CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL,
+ * CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
* CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
* CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
* CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
@@ -983,166 +938,148 @@
#define OMAP4430_IDLEST_SHIFT 16
#define OMAP4430_IDLEST_MASK (0x3 << 16)
-/*
- * Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
- * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE
- */
+/* Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
#define OMAP4430_ISS_DYNDEP_SHIFT 9
#define OMAP4430_ISS_DYNDEP_MASK (1 << 9)
/*
* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_TESLA_STATICDEP
*/
#define OMAP4430_ISS_STATDEP_SHIFT 9
#define OMAP4430_ISS_STATDEP_MASK (1 << 9)
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_TESLA_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
#define OMAP4430_IVAHD_DYNDEP_SHIFT 2
#define OMAP4430_IVAHD_DYNDEP_MASK (1 << 2)
/*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_IVAHD_STATDEP_SHIFT 2
#define OMAP4430_IVAHD_STATDEP_MASK (1 << 2)
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
#define OMAP4430_L3INIT_DYNDEP_SHIFT 7
#define OMAP4430_L3INIT_DYNDEP_MASK (1 << 7)
/*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_L3INIT_STATDEP_SHIFT 7
#define OMAP4430_L3INIT_STATDEP_MASK (1 << 7)
/*
* Used by CM_DSS_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
- * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * CM_L4CFG_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
*/
#define OMAP4430_L3_1_DYNDEP_SHIFT 5
#define OMAP4430_L3_1_DYNDEP_MASK (1 << 5)
/*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
* CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_L3_1_STATDEP_SHIFT 5
#define OMAP4430_L3_1_STATDEP_MASK (1 << 5)
/*
- * Used by CM_CAM_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE,
- * CM_DUCATI_DYNAMICDEP, CM_EMU_DYNAMICDEP, CM_GFX_DYNAMICDEP,
- * CM_IVAHD_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_1_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
+ * Used by CM_CAM_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
+ * CM_EMU_DYNAMICDEP, CM_GFX_DYNAMICDEP, CM_IVAHD_DYNAMICDEP,
+ * CM_L3INIT_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
+ * CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
*/
#define OMAP4430_L3_2_DYNDEP_SHIFT 6
#define OMAP4430_L3_2_DYNDEP_MASK (1 << 6)
/*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
* CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_L3_2_STATDEP_SHIFT 6
#define OMAP4430_L3_2_STATDEP_MASK (1 << 6)
-/* Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_1_DYNAMICDEP */
#define OMAP4430_L4CFG_DYNDEP_SHIFT 12
#define OMAP4430_L4CFG_DYNDEP_MASK (1 << 12)
/*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_L4CFG_STATDEP_SHIFT 12
#define OMAP4430_L4CFG_STATDEP_MASK (1 << 12)
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_2_DYNAMICDEP */
#define OMAP4430_L4PER_DYNDEP_SHIFT 13
#define OMAP4430_L4PER_DYNDEP_MASK (1 << 13)
/*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_L4SEC_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_L4PER_STATDEP_SHIFT 13
#define OMAP4430_L4PER_STATDEP_MASK (1 << 13)
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
- * CM_L4PER_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
#define OMAP4430_L4SEC_DYNDEP_SHIFT 14
#define OMAP4430_L4SEC_DYNDEP_MASK (1 << 14)
/*
* Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE
+ * CM_SDMA_STATICDEP
*/
#define OMAP4430_L4SEC_STATDEP_SHIFT 14
#define OMAP4430_L4SEC_STATDEP_MASK (1 << 14)
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
#define OMAP4430_L4WKUP_DYNDEP_SHIFT 15
#define OMAP4430_L4WKUP_DYNDEP_MASK (1 << 15)
/*
* Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_L4WKUP_STATDEP_SHIFT 15
#define OMAP4430_L4WKUP_STATDEP_MASK (1 << 15)
/*
- * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_L3_1_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
+ * CM_MPU_DYNAMICDEP
*/
#define OMAP4430_MEMIF_DYNDEP_SHIFT 4
#define OMAP4430_MEMIF_DYNDEP_MASK (1 << 4)
/*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
* CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
*/
#define OMAP4430_MEMIF_STATDEP_SHIFT 4
#define OMAP4430_MEMIF_STATDEP_MASK (1 << 4)
/*
* Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
- * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
- * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB
+ * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
+ * CM_SSC_MODFREQDIV_DPLL_MPU, CM_SSC_MODFREQDIV_DPLL_PER,
+ * CM_SSC_MODFREQDIV_DPLL_UNIPRO, CM_SSC_MODFREQDIV_DPLL_USB
*/
#define OMAP4430_MODFREQDIV_EXPONENT_SHIFT 8
#define OMAP4430_MODFREQDIV_EXPONENT_MASK (0x7 << 8)
/*
* Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
- * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
- * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB
+ * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
+ * CM_SSC_MODFREQDIV_DPLL_MPU, CM_SSC_MODFREQDIV_DPLL_PER,
+ * CM_SSC_MODFREQDIV_DPLL_UNIPRO, CM_SSC_MODFREQDIV_DPLL_USB
*/
#define OMAP4430_MODFREQDIV_MANTISSA_SHIFT 0
#define OMAP4430_MODFREQDIV_MANTISSA_MASK (0x7f << 0)
@@ -1155,8 +1092,7 @@
* CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
* CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
* CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
- * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
* CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
* CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
* CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
@@ -1165,30 +1101,24 @@
* CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
* CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
* CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL,
* CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
* CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
* CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
* CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
* CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
* CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
- * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
- * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
- * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
- * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
- * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
- * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
- * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL,
+ * CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL,
+ * CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL,
+ * CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL,
+ * CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL,
+ * CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL,
+ * CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL,
+ * CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
* CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
* CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
* CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
@@ -1204,6 +1134,10 @@
#define OMAP4430_MODULEMODE_SHIFT 0
#define OMAP4430_MODULEMODE_MASK (0x3 << 0)
+/* Used by CM_L4CFG_DYNAMICDEP */
+#define OMAP4460_MPU_DYNDEP_SHIFT 19
+#define OMAP4460_MPU_DYNDEP_MASK (1 << 19)
+
/* Used by CM_DSS_DSS_CLKCTRL */
#define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT 9
#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK (1 << 9)
@@ -1221,11 +1155,9 @@
#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK (1 << 8)
/*
- * Used by CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE, CM_WKUP_GPIO1_CLKCTRL
+ * Used by CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL,
+ * CM_WKUP_GPIO1_CLKCTRL
*/
#define OMAP4430_OPTFCLKEN_DBCLK_SHIFT 8
#define OMAP4430_OPTFCLKEN_DBCLK_MASK (1 << 8)
@@ -1254,23 +1186,23 @@
#define OMAP4430_OPTFCLKEN_FCLK2_SHIFT 10
#define OMAP4430_OPTFCLKEN_FCLK2_MASK (1 << 10)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT 15
#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK (1 << 15)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT 13
#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK (1 << 13)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT 14
#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK (1 << 14)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT 11
#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK (1 << 11)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT 12
#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK (1 << 12)
@@ -1298,6 +1230,10 @@
#define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT 10
#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK (1 << 10)
+/* Used by CM_WKUP_BANDGAP_CLKCTRL */
+#define OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT 8
+#define OMAP4460_OPTFCLKEN_TS_FCLK_MASK (1 << 8)
+
/* Used by CM_DSS_DSS_CLKCTRL */
#define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT 11
#define OMAP4430_OPTFCLKEN_TV_CLK_MASK (1 << 11)
@@ -1306,27 +1242,27 @@
#define OMAP4430_OPTFCLKEN_TXPHYCLK_SHIFT 8
#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK (1 << 8)
-/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_TLL_CLKCTRL */
#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT 8
#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK (1 << 8)
-/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_TLL_CLKCTRL */
#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT 9
#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK (1 << 9)
-/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_TLL_CLKCTRL */
#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT 10
#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK (1 << 10)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT 8
#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK (1 << 8)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT 9
#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK (1 << 9)
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT 10
#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK (1 << 10)
@@ -1374,7 +1310,7 @@
#define OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT 22
#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK (0x3 << 22)
-/* Used by CM_DYN_DEP_PRESCAL, CM_DYN_DEP_PRESCAL_RESTORE */
+/* Used by CM_DYN_DEP_PRESCAL */
#define OMAP4430_PRESCAL_SHIFT 0
#define OMAP4430_PRESCAL_MASK (0x3f << 0)
@@ -1382,10 +1318,7 @@
#define OMAP4430_R_RTL_SHIFT 11
#define OMAP4430_R_RTL_MASK (0x1f << 11)
-/*
- * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
- */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL */
#define OMAP4430_SAR_MODE_SHIFT 4
#define OMAP4430_SAR_MODE_MASK (1 << 4)
@@ -1397,7 +1330,7 @@
#define OMAP4430_SCHEME_SHIFT 30
#define OMAP4430_SCHEME_MASK (0x3 << 30)
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
#define OMAP4430_SDMA_DYNDEP_SHIFT 11
#define OMAP4430_SDMA_DYNDEP_MASK (1 << 11)
@@ -1417,10 +1350,10 @@
* CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
* CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
* CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_XHPI_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL,
- * CM_SDMA_SDMA_CLKCTRL, CM_TESLA_TESLA_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL
*/
#define OMAP4430_STBYST_SHIFT 18
#define OMAP4430_STBYST_MASK (1 << 18)
@@ -1438,17 +1371,13 @@
#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK (1 << 9)
/*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
*/
#define OMAP4430_ST_DPLL_CLKOUT_SHIFT 9
#define OMAP4430_ST_DPLL_CLKOUT_MASK (1 << 9)
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
#define OMAP4430_ST_DPLL_CLKOUTHIF_SHIFT 9
#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK (1 << 9)
@@ -1457,30 +1386,24 @@
#define OMAP4430_ST_DPLL_CLKOUTX2_MASK (1 << 11)
/*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
*/
#define OMAP4430_ST_HSDIVIDER_CLKOUT1_SHIFT 9
#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK (1 << 9)
/*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
*/
#define OMAP4430_ST_HSDIVIDER_CLKOUT2_SHIFT 9
#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK (1 << 9)
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
#define OMAP4430_ST_HSDIVIDER_CLKOUT3_SHIFT 9
#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK (1 << 9)
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
#define OMAP4430_ST_HSDIVIDER_CLKOUT4_SHIFT 9
#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK (1 << 9)
@@ -1496,7 +1419,7 @@
#define OMAP4430_SYS_CLKSEL_SHIFT 0
#define OMAP4430_SYS_CLKSEL_MASK (0x7 << 0)
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
#define OMAP4430_TESLA_DYNDEP_SHIFT 1
#define OMAP4430_TESLA_DYNDEP_MASK (1 << 1)
@@ -1505,11 +1428,9 @@
#define OMAP4430_TESLA_STATDEP_MASK (1 << 1)
/*
- * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_DUCATI_DYNAMICDEP,
- * CM_EMU_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE,
- * CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
- * CM_L4PER_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP, CM_EMU_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
*/
#define OMAP4430_WINDOWSIZE_SHIFT 24
#define OMAP4430_WINDOWSIZE_MASK (0xf << 24)
diff --git a/arch/arm/mach-omap2/cm1_44xx.h b/arch/arm/mach-omap2/cm1_44xx.h
index e2d7a56b2ad6..1bc00dc4876c 100644
--- a/arch/arm/mach-omap2/cm1_44xx.h
+++ b/arch/arm/mach-omap2/cm1_44xx.h
@@ -1,7 +1,7 @@
/*
* OMAP44xx CM1 instance offset macros
*
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
* Copyright (C) 2009-2010 Nokia Corporation
*
* Paul Walmsley (paul@pwsan.com)
@@ -41,9 +41,9 @@
#define OMAP4430_CM1_INSTR_INST 0x0f00
/* CM1 clockdomain register offsets (from instance start) */
-#define OMAP4430_CM1_ABE_ABE_CDOFFS 0x0000
-#define OMAP4430_CM1_MPU_MPU_CDOFFS 0x0000
-#define OMAP4430_CM1_TESLA_TESLA_CDOFFS 0x0000
+#define OMAP4430_CM1_MPU_MPU_CDOFFS 0x0000
+#define OMAP4430_CM1_TESLA_TESLA_CDOFFS 0x0000
+#define OMAP4430_CM1_ABE_ABE_CDOFFS 0x0000
/* CM1 */
@@ -82,8 +82,8 @@
#define OMAP4430_CM_DIV_M7_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0044)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_OFFSET 0x0048
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0048)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_OFFSET 0x004c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x004c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_OFFSET 0x004c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x004c)
#define OMAP4_CM_EMU_OVERRIDE_DPLL_CORE_OFFSET 0x0050
#define OMAP4430_CM_EMU_OVERRIDE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0050)
#define OMAP4_CM_CLKMODE_DPLL_MPU_OFFSET 0x0060
@@ -98,8 +98,8 @@
#define OMAP4430_CM_DIV_M2_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0070)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_MPU_OFFSET 0x0088
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0088)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_MPU_OFFSET 0x008c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x008c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_MPU_OFFSET 0x008c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x008c)
#define OMAP4_CM_BYPCLK_DPLL_MPU_OFFSET 0x009c
#define OMAP4430_CM_BYPCLK_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x009c)
#define OMAP4_CM_CLKMODE_DPLL_IVA_OFFSET 0x00a0
@@ -116,8 +116,8 @@
#define OMAP4430_CM_DIV_M5_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00bc)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_IVA_OFFSET 0x00c8
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00c8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_IVA_OFFSET 0x00cc
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00cc)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_IVA_OFFSET 0x00cc
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00cc)
#define OMAP4_CM_BYPCLK_DPLL_IVA_OFFSET 0x00dc
#define OMAP4430_CM_BYPCLK_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00dc)
#define OMAP4_CM_CLKMODE_DPLL_ABE_OFFSET 0x00e0
@@ -134,8 +134,8 @@
#define OMAP4430_CM_DIV_M3_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00f4)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_ABE_OFFSET 0x0108
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0108)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_ABE_OFFSET 0x010c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x010c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_ABE_OFFSET 0x010c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x010c)
#define OMAP4_CM_CLKMODE_DPLL_DDRPHY_OFFSET 0x0120
#define OMAP4430_CM_CLKMODE_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0120)
#define OMAP4_CM_IDLEST_DPLL_DDRPHY_OFFSET 0x0124
@@ -154,8 +154,8 @@
#define OMAP4430_CM_DIV_M6_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0140)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_DDRPHY_OFFSET 0x0148
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0148)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_DDRPHY_OFFSET 0x014c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x014c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_DDRPHY_OFFSET 0x014c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x014c)
#define OMAP4_CM_SHADOW_FREQ_CONFIG1_OFFSET 0x0160
#define OMAP4430_CM_SHADOW_FREQ_CONFIG1 OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0160)
#define OMAP4_CM_SHADOW_FREQ_CONFIG2_OFFSET 0x0164
@@ -217,42 +217,6 @@
#define OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET 0x0088
#define OMAP4430_CM1_ABE_WDT3_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0088)
-/* CM1.RESTORE_CM1 register offsets */
-#define OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET 0x0000
-#define OMAP4430_CM_CLKSEL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0000)
-#define OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET 0x0004
-#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0004)
-#define OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET 0x0008
-#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0008)
-#define OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET 0x000c
-#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x000c)
-#define OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET 0x0010
-#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0010)
-#define OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET 0x0014
-#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0014)
-#define OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET 0x0018
-#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0018)
-#define OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET 0x001c
-#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x001c)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET 0x0020
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0020)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE_OFFSET 0x0024
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0024)
-#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET 0x0028
-#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0028)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET 0x002c
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x002c)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET 0x0030
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0030)
-#define OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET 0x0034
-#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0034)
-#define OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET 0x0038
-#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0038)
-#define OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET 0x003c
-#define OMAP4430_CM_CM1_PROFILING_CLKCTRL_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x003c)
-#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET 0x0040
-#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0040)
-
/* Function prototypes */
extern u32 omap4_cm1_read_inst_reg(s16 inst, u16 idx);
extern void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 idx);
diff --git a/arch/arm/mach-omap2/cm2_44xx.h b/arch/arm/mach-omap2/cm2_44xx.h
index aa4745044065..b9de72da1a8e 100644
--- a/arch/arm/mach-omap2/cm2_44xx.h
+++ b/arch/arm/mach-omap2/cm2_44xx.h
@@ -1,7 +1,7 @@
/*
* OMAP44xx CM2 instance offset macros
*
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
* Copyright (C) 2009-2010 Nokia Corporation
*
* Paul Walmsley (paul@pwsan.com)
@@ -40,9 +40,9 @@
#define OMAP4430_CM2_CAM_INST 0x1000
#define OMAP4430_CM2_DSS_INST 0x1100
#define OMAP4430_CM2_GFX_INST 0x1200
-#define OMAP4430_CM2_L3INIT_INST 0x1300
+#define OMAP4430_CM2_L3INIT_INST 0x1300
#define OMAP4430_CM2_L4PER_INST 0x1400
-#define OMAP4430_CM2_CEFUSE_INST 0x1600
+#define OMAP4430_CM2_CEFUSE_INST 0x1600
#define OMAP4430_CM2_RESTORE_INST 0x1e00
#define OMAP4430_CM2_INSTR_INST 0x1f00
@@ -65,7 +65,6 @@
#define OMAP4430_CM2_L4PER_L4SEC_CDOFFS 0x0180
#define OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS 0x0000
-
/* CM2 */
/* CM2.OCP_SOCKET_CM2 register offsets */
@@ -121,8 +120,8 @@
#define OMAP4430_CM_DIV_M7_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0064)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_PER_OFFSET 0x0068
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0068)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_PER_OFFSET 0x006c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x006c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET 0x006c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x006c)
#define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET 0x0080
#define OMAP4430_CM_CLKMODE_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0080)
#define OMAP4_CM_IDLEST_DPLL_USB_OFFSET 0x0084
@@ -135,8 +134,8 @@
#define OMAP4430_CM_DIV_M2_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0090)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_USB_OFFSET 0x00a8
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00a8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_USB_OFFSET 0x00ac
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ac)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_USB_OFFSET 0x00ac
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ac)
#define OMAP4_CM_CLKDCOLDO_DPLL_USB_OFFSET 0x00b4
#define OMAP4430_CM_CLKDCOLDO_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00b4)
#define OMAP4_CM_CLKMODE_DPLL_UNIPRO_OFFSET 0x00c0
@@ -151,8 +150,8 @@
#define OMAP4430_CM_DIV_M2_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00d0)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_UNIPRO_OFFSET 0x00e8
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00e8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_UNIPRO_OFFSET 0x00ec
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ec)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_UNIPRO_OFFSET 0x00ec
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ec)
/* CM2.ALWAYS_ON_CM2 register offsets */
#define OMAP4_CM_ALWON_CLKSTCTRL_OFFSET 0x0000
@@ -227,8 +226,8 @@
#define OMAP4430_CM_D2D_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0508)
#define OMAP4_CM_D2D_SAD2D_CLKCTRL_OFFSET 0x0520
#define OMAP4430_CM_D2D_SAD2D_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0520)
-#define OMAP4_CM_D2D_INSTEM_ICR_CLKCTRL_OFFSET 0x0528
-#define OMAP4430_CM_D2D_INSTEM_ICR_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0528)
+#define OMAP4_CM_D2D_MODEM_ICR_CLKCTRL_OFFSET 0x0528
+#define OMAP4430_CM_D2D_MODEM_ICR_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0528)
#define OMAP4_CM_D2D_SAD2D_FW_CLKCTRL_OFFSET 0x0530
#define OMAP4430_CM_D2D_SAD2D_FW_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0530)
#define OMAP4_CM_L4CFG_CLKSTCTRL_OFFSET 0x0600
@@ -450,56 +449,6 @@
#define OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET 0x0020
#define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_INST, 0x0020)
-/* CM2.RESTORE_CM2 register offsets */
-#define OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET 0x0000
-#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0000)
-#define OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET 0x0004
-#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0004)
-#define OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET 0x0008
-#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0008)
-#define OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET 0x000c
-#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x000c)
-#define OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET 0x0010
-#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0010)
-#define OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET 0x0014
-#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0014)
-#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET 0x0018
-#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0018)
-#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET 0x001c
-#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x001c)
-#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET 0x0020
-#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0020)
-#define OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET 0x0024
-#define OMAP4430_CM_CM2_PROFILING_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0024)
-#define OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET 0x0028
-#define OMAP4430_CM_D2D_STATICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0028)
-#define OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET 0x002c
-#define OMAP4430_CM_L3_1_DYNAMICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x002c)
-#define OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET 0x0030
-#define OMAP4430_CM_L3_2_DYNAMICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0030)
-#define OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET 0x0034
-#define OMAP4430_CM_D2D_DYNAMICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0034)
-#define OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET 0x0038
-#define OMAP4430_CM_L4CFG_DYNAMICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0038)
-#define OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET 0x003c
-#define OMAP4430_CM_L4PER_DYNAMICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x003c)
-#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_RESTORE_OFFSET 0x0040
-#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0040)
-#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_RESTORE_OFFSET 0x0044
-#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0044)
-#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_RESTORE_OFFSET 0x0048
-#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0048)
-#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_RESTORE_OFFSET 0x004c
-#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x004c)
-#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_RESTORE_OFFSET 0x0050
-#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0050)
-#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET 0x0054
-#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0054)
-#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET 0x0058
-#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0058)
-#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET 0x005c
-#define OMAP4430_CM_SDMA_STATICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x005c)
-
/* Function prototypes */
extern u32 omap4_cm2_read_inst_reg(s16 inst, u16 idx);
extern void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 idx);
diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 0b87ec82b41c..3380beeace6e 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -1,7 +1,7 @@
/*
* OMAP4 Clock Management (CM) definitions
*
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
* Copyright (C) 2007-2009 Nokia Corporation
*
* Written by Paul Walmsley
@@ -23,10 +23,4 @@
#define OMAP4_CM_CLKSTCTRL 0x0000
#define OMAP4_CM_STATICDEP 0x0004
-/* Function prototypes */
-# ifndef __ASSEMBLER__
-
-extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
-
-# endif
#endif
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index a482bfa0a954..eb2a472bbf46 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -2,6 +2,7 @@
* OMAP4 CM instance functions
*
* Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -32,6 +33,22 @@
#include "prm44xx.h"
#include "prcm_mpu44xx.h"
+/*
+ * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
+ *
+ * 0x0 func: Module is fully functional, including OCP
+ * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep
+ * abortion
+ * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if
+ * using separate functional clock
+ * 0x3 disabled: Module is disabled and cannot be accessed
+ *
+ */
+#define CLKCTRL_IDLEST_FUNCTIONAL 0x0
+#define CLKCTRL_IDLEST_INTRANSITION 0x1
+#define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
+#define CLKCTRL_IDLEST_DISABLED 0x3
+
static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
[OMAP4430_INVALID_PRCM_PARTITION] = 0,
[OMAP4430_PRM_PARTITION] = OMAP4430_PRM_BASE,
@@ -41,6 +58,48 @@ static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
[OMAP4430_PRCM_MPU_PARTITION] = OMAP4430_PRCM_MPU_BASE,
};
+/* Private functions */
+
+/**
+ * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to
+ * bit 0.
+ */
+static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+ u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+ v &= OMAP4430_IDLEST_MASK;
+ v >>= OMAP4430_IDLEST_SHIFT;
+ return v;
+}
+
+/**
+ * _is_module_ready - can module registers be accessed without causing an abort?
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either
+ * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise.
+ */
+static bool _is_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+ u32 v;
+
+ v = _clkctrl_idlest(part, inst, cdoffs, clkctrl_offs);
+
+ return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
+ v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
+}
+
+/* Public functions */
+
/* Read a register in a CM instance */
u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx)
{
@@ -200,36 +259,93 @@ void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs)
*/
/**
- * omap4_cm_wait_module_ready - wait for a module to be in 'func' state
- * @clkctrl_reg: CLKCTRL module address
+ * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
*
* Wait for the module IDLEST to be functional. If the idle state is in any
* the non functional state (trans, idle or disabled), module and thus the
* sysconfig cannot be accessed and will probably lead to an "imprecise
* external abort"
+ */
+int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs,
+ u16 clkctrl_offs)
+{
+ int i = 0;
+
+ if (!clkctrl_offs)
+ return 0;
+
+ omap_test_timeout(_is_module_ready(part, inst, cdoffs, clkctrl_offs),
+ MAX_MODULE_READY_TIME, i);
+
+ return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/**
+ * omap4_cminst_wait_module_idle - wait for a module to be in 'disabled'
+ * state
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
*
- * Module idle state:
- * 0x0 func: Module is fully functional, including OCP
- * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep
- * abortion
- * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if
- * using separate functional clock
- * 0x3 disabled: Module is disabled and cannot be accessed
- *
+ * Wait for the module IDLEST to be disabled. Some PRCM transition,
+ * like reset assertion or parent clock de-activation must wait the
+ * module to be fully disabled.
*/
-int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
+int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
{
int i = 0;
- if (!clkctrl_reg)
+ if (!clkctrl_offs)
return 0;
- omap_test_timeout((
- ((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
- (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
- OMAP4430_IDLEST_SHIFT) == 0x2)),
- MAX_MODULE_READY_TIME, i);
+ omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) ==
+ CLKCTRL_IDLEST_DISABLED),
+ MAX_MODULE_READY_TIME, i);
return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
}
+/**
+ * omap4_cminst_module_enable - Enable the modulemode inside CLKCTRL
+ * @mode: Module mode (SW or HW)
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
+ u16 clkctrl_offs)
+{
+ u32 v;
+
+ v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+ v &= ~OMAP4430_MODULEMODE_MASK;
+ v |= mode << OMAP4430_MODULEMODE_SHIFT;
+ omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
+}
+
+/**
+ * omap4_cminst_module_disable - Disable the module inside CLKCTRL
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+ u16 clkctrl_offs)
+{
+ u32 v;
+
+ v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+ v &= ~OMAP4430_MODULEMODE_MASK;
+ omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
+}
diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
index 2b32c181a2ee..f2ea6453ade0 100644
--- a/arch/arm/mach-omap2/cminst44xx.h
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -17,6 +17,14 @@ extern void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs);
extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
+extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
+extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
+
+extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
+ u16 clkctrl_offs);
+extern void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+ u16 clkctrl_offs);
+
/*
* In an ideal world, we would not export these low-level functions,
* but this will probably take some time to fix properly
@@ -32,6 +40,4 @@ extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
u32 mask);
-extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
-
#endif
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 94ccf464677b..bcb0c5817167 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -20,36 +20,15 @@
*
*/
-#include <linux/i2c.h>
-#include <linux/i2c/twl.h>
-
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
-#include <plat/i2c.h>
#include <plat/mcspi.h>
#include <plat/nand.h>
#include "common-board-devices.h"
-static struct i2c_board_info __initdata pmic_i2c_board_info = {
- .addr = 0x48,
- .flags = I2C_CLIENT_WAKE,
-};
-
-void __init omap_pmic_init(int bus, u32 clkrate,
- const char *pmic_type, int pmic_irq,
- struct twl4030_platform_data *pmic_data)
-{
- strncpy(pmic_i2c_board_info.type, pmic_type,
- sizeof(pmic_i2c_board_info.type));
- pmic_i2c_board_info.irq = pmic_irq;
- pmic_i2c_board_info.platform_data = pmic_data;
-
- omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
-}
-
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
static struct omap2_mcspi_device_config ads7846_mcspi_config = {
@@ -115,9 +94,7 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
#endif
#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-static struct omap_nand_platform_data nand_data = {
- .dma_channel = -1, /* disable DMA in OMAP NAND driver */
-};
+static struct omap_nand_platform_data nand_data;
void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
int nr_parts)
@@ -148,7 +125,7 @@ void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
nand_data.cs = nandcs;
nand_data.parts = parts;
nand_data.nr_parts = nr_parts;
- nand_data.options = options;
+ nand_data.devsize = options;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (gpmc_nand_init(&nand_data) < 0)
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index 679719051df5..a0b4a42836ab 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -1,33 +1,11 @@
#ifndef __OMAP_COMMON_BOARD_DEVICES__
#define __OMAP_COMMON_BOARD_DEVICES__
+#include "twl-common.h"
+
#define NAND_BLOCK_SIZE SZ_128K
-struct twl4030_platform_data;
struct mtd_partition;
-
-void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
- struct twl4030_platform_data *pmic_data);
-
-static inline void omap2_pmic_init(const char *pmic_type,
- struct twl4030_platform_data *pmic_data)
-{
- omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data);
-}
-
-static inline void omap3_pmic_init(const char *pmic_type,
- struct twl4030_platform_data *pmic_data)
-{
- omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
-}
-
-static inline void omap4_pmic_init(const char *pmic_type,
- struct twl4030_platform_data *pmic_data)
-{
- /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
- omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
-}
-
struct ads7846_platform_data;
void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index da53ba3917ca..aab884fecc55 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -286,14 +286,15 @@ void omap3_save_scratchpad_contents(void)
scratchpad_contents.boot_config_ptr = 0x0;
if (cpu_is_omap3630())
scratchpad_contents.public_restore_ptr =
- virt_to_phys(get_omap3630_restore_pointer());
+ virt_to_phys(omap3_restore_3630);
else if (omap_rev() != OMAP3430_REV_ES3_0 &&
omap_rev() != OMAP3430_REV_ES3_1)
scratchpad_contents.public_restore_ptr =
- virt_to_phys(get_restore_pointer());
+ virt_to_phys(omap3_restore);
else
scratchpad_contents.public_restore_ptr =
- virt_to_phys(get_es3_restore_pointer());
+ virt_to_phys(omap3_restore_es3);
+
if (omap_type() == OMAP2_DEVICE_TYPE_GP)
scratchpad_contents.secure_ram_restore_ptr = 0x0;
else
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index a016c8b59e00..d4ef75d5a382 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -386,9 +386,9 @@ extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
extern void omap3_save_scratchpad_contents(void);
extern void omap3_clear_scratchpad_contents(void);
-extern u32 *get_restore_pointer(void);
-extern u32 *get_es3_restore_pointer(void);
-extern u32 *get_omap3630_restore_pointer(void);
+extern void omap3_restore(void);
+extern void omap3_restore_es3(void);
+extern void omap3_restore_3630(void);
extern u32 omap3_arm_context[128];
extern void omap3_control_save_context(void);
extern void omap3_control_restore_context(void);
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 5b8ca680ed93..1077ad663f93 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -230,7 +230,7 @@ struct omap_device_pm_latency omap_keyboard_latency[] = {
};
int __init omap4_keyboard_init(struct omap4_keypad_platform_data
- *sdp4430_keypad_data)
+ *sdp4430_keypad_data, struct omap_board_data *bdata)
{
struct omap_device *od;
struct omap_hwmod *oh;
@@ -257,6 +257,7 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
name, oh->name);
return PTR_ERR(od);
}
+ oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
return 0;
}
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 9529842ae054..2765cdc3152d 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -61,13 +61,45 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
pdata->dbck_flag = dev_attr->dbck_flag;
pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);
+ pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("gpio%d: Memory allocation failed\n", id);
+ return -ENOMEM;
+ }
+
switch (oh->class->rev) {
case 0:
case 1:
pdata->bank_type = METHOD_GPIO_24XX;
+ pdata->regs->revision = OMAP24XX_GPIO_REVISION;
+ pdata->regs->direction = OMAP24XX_GPIO_OE;
+ pdata->regs->datain = OMAP24XX_GPIO_DATAIN;
+ pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT;
+ pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT;
+ pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT;
+ pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1;
+ pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2;
+ pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1;
+ pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1;
+ pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1;
+ pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL;
+ pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN;
break;
case 2:
pdata->bank_type = METHOD_GPIO_44XX;
+ pdata->regs->revision = OMAP4_GPIO_REVISION;
+ pdata->regs->direction = OMAP4_GPIO_OE;
+ pdata->regs->datain = OMAP4_GPIO_DATAIN;
+ pdata->regs->dataout = OMAP4_GPIO_DATAOUT;
+ pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT;
+ pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT;
+ pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0;
+ pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1;
+ pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0;
+ pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0;
+ pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0;
+ pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME;
+ pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE;
break;
default:
WARN(1, "Invalid gpio bank_type\n");
@@ -87,6 +119,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
return PTR_ERR(od);
}
+ omap_device_disable_idle_on_suspend(od);
+
gpio_bank_count++;
return 0;
}
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index c1791d08ae56..8ad210bda9a9 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -20,8 +20,6 @@
#include <plat/board.h>
#include <plat/gpmc.h>
-static struct omap_nand_platform_data *gpmc_nand_data;
-
static struct resource gpmc_nand_resource = {
.flags = IORESOURCE_MEM,
};
@@ -33,7 +31,7 @@ static struct platform_device gpmc_nand_device = {
.resource = &gpmc_nand_resource,
};
-static int omap2_nand_gpmc_retime(void)
+static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
{
struct gpmc_timings t;
int err;
@@ -83,13 +81,11 @@ static int omap2_nand_gpmc_retime(void)
return 0;
}
-int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
+int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
{
int err = 0;
struct device *dev = &gpmc_nand_device.dev;
- gpmc_nand_data = _nand_data;
- gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime;
gpmc_nand_device.dev.platform_data = gpmc_nand_data;
err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -100,7 +96,7 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
}
/* Set timings in GPMC */
- err = omap2_nand_gpmc_retime();
+ err = omap2_nand_gpmc_retime(gpmc_nand_data);
if (err < 0) {
dev_err(dev, "Unable to set gpmc timings: %d\n", err);
return err;
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 66868c5d5a29..a9b45c76e1d3 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <mach/hardware.h>
#include <plat/mmc.h>
#include <plat/omap-pm.h>
@@ -213,12 +214,10 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on,
static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
int controller_nr)
{
- if ((mmc_controller->slots[0].switch_pin > 0) && \
- (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
+ if (gpio_is_valid(mmc_controller->slots[0].switch_pin))
omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
OMAP_PIN_INPUT_PULLUP);
- if ((mmc_controller->slots[0].gpio_wp > 0) && \
- (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
+ if (gpio_is_valid(mmc_controller->slots[0].gpio_wp))
omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
OMAP_PIN_INPUT_PULLUP);
if (cpu_is_omap34xx()) {
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index 79c478c4cb1c..ace99944e96f 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -21,9 +21,19 @@
#include <plat/cpu.h>
#include <plat/i2c.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
#include "mux.h"
+/* In register I2C_CON, Bit 15 is the I2C enable bit */
+#define I2C_EN BIT(15)
+#define OMAP2_I2C_CON_OFFSET 0x24
+#define OMAP4_I2C_CON_OFFSET 0xA4
+
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT 10000
+
void __init omap2_i2c_mux_pins(int bus_id)
{
char mux_name[sizeof("i2c2_scl.i2c2_scl")];
@@ -37,3 +47,61 @@ void __init omap2_i2c_mux_pins(int bus_id)
sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id);
omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
}
+
+/**
+ * omap_i2c_reset - reset the omap i2c module.
+ * @oh: struct omap_hwmod *
+ *
+ * The i2c moudle in omap2, omap3 had a special sequence to reset. The
+ * sequence is:
+ * - Disable the I2C.
+ * - Write to SOFTRESET bit.
+ * - Enable the I2C.
+ * - Poll on the RESETDONE bit.
+ * The sequence is implemented in below function. This is called for 2420,
+ * 2430 and omap3.
+ */
+int omap_i2c_reset(struct omap_hwmod *oh)
+{
+ u32 v;
+ u16 i2c_con;
+ int c = 0;
+
+ if (oh->class->rev == OMAP_I2C_IP_VERSION_2) {
+ i2c_con = OMAP4_I2C_CON_OFFSET;
+ } else if (oh->class->rev == OMAP_I2C_IP_VERSION_1) {
+ i2c_con = OMAP2_I2C_CON_OFFSET;
+ } else {
+ WARN(1, "Cannot reset I2C block %s: unsupported revision\n",
+ oh->name);
+ return -EINVAL;
+ }
+
+ /* Disable I2C */
+ v = omap_hwmod_read(oh, i2c_con);
+ v &= ~I2C_EN;
+ omap_hwmod_write(v, oh, i2c_con);
+
+ /* Write to the SOFTRESET bit */
+ omap_hwmod_softreset(oh);
+
+ /* Enable I2C */
+ v = omap_hwmod_read(oh, i2c_con);
+ v |= I2C_EN;
+ omap_hwmod_write(v, oh, i2c_con);
+
+ /* Poll on RESETDONE bit */
+ omap_test_timeout((omap_hwmod_read(oh,
+ oh->class->sysc->syss_offs)
+ & SYSS_RESETDONE_MASK),
+ MAX_MODULE_SOFTRESET_WAIT, c);
+
+ if (c == MAX_MODULE_SOFTRESET_WAIT)
+ pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+ __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+ else
+ pr_debug("%s: %s: softreset in %d usec\n", __func__,
+ oh->name, c);
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 2537090aa33a..37efb8696927 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -31,7 +31,7 @@
static struct omap_chip_id omap_chip;
static unsigned int omap_revision;
-u32 omap3_features;
+u32 omap_features;
unsigned int omap_rev(void)
{
@@ -183,14 +183,14 @@ static void __init omap24xx_check_revision(void)
#define OMAP3_CHECK_FEATURE(status,feat) \
if (((status & OMAP3_ ##feat## _MASK) \
>> OMAP3_ ##feat## _SHIFT) != FEAT_ ##feat## _NONE) { \
- omap3_features |= OMAP3_HAS_ ##feat; \
+ omap_features |= OMAP3_HAS_ ##feat; \
}
static void __init omap3_check_features(void)
{
u32 status;
- omap3_features = 0;
+ omap_features = 0;
status = omap_ctrl_readl(OMAP3_CONTROL_OMAP_STATUS);
@@ -200,11 +200,11 @@ static void __init omap3_check_features(void)
OMAP3_CHECK_FEATURE(status, NEON);
OMAP3_CHECK_FEATURE(status, ISP);
if (cpu_is_omap3630())
- omap3_features |= OMAP3_HAS_192MHZ_CLK;
+ omap_features |= OMAP3_HAS_192MHZ_CLK;
if (!cpu_is_omap3505() && !cpu_is_omap3517())
- omap3_features |= OMAP3_HAS_IO_WAKEUP;
+ omap_features |= OMAP3_HAS_IO_WAKEUP;
- omap3_features |= OMAP3_HAS_SDRC;
+ omap_features |= OMAP3_HAS_SDRC;
/*
* TODO: Get additional info (where applicable)
@@ -212,9 +212,34 @@ static void __init omap3_check_features(void)
*/
}
+static void __init omap4_check_features(void)
+{
+ u32 si_type;
+
+ if (cpu_is_omap443x())
+ omap_features |= OMAP4_HAS_MPU_1GHZ;
+
+
+ if (cpu_is_omap446x()) {
+ si_type =
+ read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1);
+ switch ((si_type & (3 << 16)) >> 16) {
+ case 2:
+ /* High performance device */
+ omap_features |= OMAP4_HAS_MPU_1_5GHZ;
+ break;
+ case 1:
+ default:
+ /* Standard device */
+ omap_features |= OMAP4_HAS_MPU_1_2GHZ;
+ break;
+ }
+ }
+}
+
static void __init ti816x_check_features(void)
{
- omap3_features = OMAP3_HAS_NEON;
+ omap_features = OMAP3_HAS_NEON;
}
static void __init omap3_check_revision(void)
@@ -344,10 +369,10 @@ static void __init omap4_check_revision(void)
rev = (idcode >> 28) & 0xf;
/*
- * Few initial ES2.0 samples IDCODE is same as ES1.0
+ * Few initial 4430 ES2.0 samples IDCODE is same as ES1.0
* Use ARM register to detect the correct ES version
*/
- if (!rev) {
+ if (!rev && (hawkeye != 0xb94e)) {
idcode = read_cpuid(CPUID_ID);
rev = (idcode & 0xf) - 1;
}
@@ -377,6 +402,15 @@ static void __init omap4_check_revision(void)
omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
}
break;
+ case 0xb94e:
+ switch (rev) {
+ 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;
@@ -518,6 +552,7 @@ void __init omap2_check_revision(void)
return;
} else if (cpu_is_omap44xx()) {
omap4_check_revision();
+ omap4_check_features();
return;
} else {
pr_err("OMAP revision unknown, please fix!\n");
diff --git a/arch/arm/mach-omap2/include/mach/clkdev.h b/arch/arm/mach-omap2/include/mach/clkdev.h
deleted file mode 100644
index 53b027441c56..000000000000
--- a/arch/arm/mach-omap2/include/mach/clkdev.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/clkdev.h
- */
-
-#include <plat/clkdev.h>
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index a48690b90990..ceb8b7e593d7 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -165,6 +165,3 @@
#endif
#endif /* MULTI_OMAP2 */
-
- .macro irq_prio_table
- .endm
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 441e79d043a7..2ce1ce6fb4db 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -333,23 +333,9 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
}
+/* See irq.c, omap4-common.c and entry-macro.S */
void __iomem *omap_irq_base;
-/*
- * Initialize asm_irq_base for entry-macro.S
- */
-static inline void omap_irq_base_init(void)
-{
- if (cpu_is_omap24xx())
- omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE);
- else if (cpu_is_omap34xx())
- omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE);
- else if (cpu_is_omap44xx())
- omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE);
- else
- pr_err("Could not initialize omap_irq_base\n");
-}
-
void __init omap2_init_common_infrastructure(void)
{
u8 postsetup_state;
@@ -422,7 +408,6 @@ void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
_omap2_init_reprogram_sdrc();
}
- omap_irq_base_init();
}
/*
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index adb083e41acd..f286012783c6 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -225,8 +225,8 @@ static u32 omap2_get_pte_attr(struct iotlb_entry *e)
attr = e->mixed << 5;
attr |= e->endian;
attr |= e->elsz >> 3;
- attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6);
-
+ attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) ||
+ (e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6);
return attr;
}
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3af2b7a1045e..3a12f7586a4c 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -141,25 +141,20 @@ omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
-void __init omap_init_irq(void)
+static void __init omap_init_irq(u32 base, int nr_irqs)
{
unsigned long nr_of_irqs = 0;
unsigned int nr_banks = 0;
int i, j;
+ omap_irq_base = ioremap(base, SZ_4K);
+ if (WARN_ON(!omap_irq_base))
+ return;
+
for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
- unsigned long base = 0;
struct omap_irq_bank *bank = irq_banks + i;
- if (cpu_is_omap24xx())
- base = OMAP24XX_IC_BASE;
- else if (cpu_is_omap34xx())
- base = OMAP34XX_IC_BASE;
-
- BUG_ON(!base);
-
- if (cpu_is_ti816x())
- bank->nr_irqs = 128;
+ bank->nr_irqs = nr_irqs;
/* Static mapping, never released */
bank->base_reg = ioremap(base, SZ_4K);
@@ -181,6 +176,21 @@ void __init omap_init_irq(void)
nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");
}
+void __init omap2_init_irq(void)
+{
+ omap_init_irq(OMAP24XX_IC_BASE, 96);
+}
+
+void __init omap3_init_irq(void)
+{
+ omap_init_irq(OMAP34XX_IC_BASE, 96);
+}
+
+void __init ti816x_init_irq(void)
+{
+ omap_init_irq(OMAP34XX_IC_BASE, 128);
+}
+
#ifdef CONFIG_ARCH_OMAP3
static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index 3fc5dc7233da..e61feadcda4e 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -67,7 +67,7 @@ static struct iommu_device omap4_devices[] = {
.pdata = {
.name = "ducati",
.nr_tlb_entries = 32,
- .clk_name = "ducati_ick",
+ .clk_name = "ipu_fck",
.da_start = 0x0,
.da_end = 0xFFFFF000,
},
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index ecfe93c4b585..ce65e9329c7b 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -125,14 +125,6 @@ void __init smp_init_cpus(void)
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- /*
- * Initialise the present map, which describes the set of CPUs
- * actually populated at the present time.
- */
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
/*
* Initialise the SCU and wake up the secondary core using
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 9ef8c29dd817..35ac3e5f6e94 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -19,6 +19,8 @@
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
+#include <plat/irqs.h>
+
#include <mach/hardware.h>
#include <mach/omap4-common.h>
@@ -31,17 +33,15 @@ void __iomem *gic_dist_base_addr;
void __init gic_init_irq(void)
{
- void __iomem *gic_cpu_base;
-
/* Static mapping, never released */
gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
BUG_ON(!gic_dist_base_addr);
/* Static mapping, never released */
- gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
- BUG_ON(!gic_cpu_base);
+ omap_irq_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
+ BUG_ON(!omap_irq_base);
- gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
+ gic_init(0, 29, gic_dist_base_addr, omap_irq_base);
}
#ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 293fa6cd50e1..84cc0bdda3ae 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2,6 +2,7 @@
* omap_hwmod implementation for OMAP2/3/4
*
* Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
*
* Paul Walmsley, Benoît Cousson, Kevin Hilman
*
@@ -145,9 +146,10 @@
#include <plat/prcm.h>
#include "cm2xxx_3xxx.h"
-#include "cm44xx.h"
+#include "cminst44xx.h"
#include "prm2xxx_3xxx.h"
#include "prm44xx.h"
+#include "prminst44xx.h"
#include "mux.h"
/* Maximum microseconds to wait for OMAP module to softreset */
@@ -387,11 +389,10 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
*/
static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
{
- u32 wakeup_mask;
-
if (!oh->class->sysc ||
!((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
- (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
+ (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
+ (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
return -EINVAL;
if (!oh->class->sysc->sysc_fields) {
@@ -399,12 +400,13 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
return -EINVAL;
}
- wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
-
- *v |= wakeup_mask;
+ if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
+ *v |= 0x1 << oh->class->sysc->sysc_fields->enwkup_shift;
if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
/* XXX test pwrdm_get_wken for this hwmod's subsystem */
@@ -422,11 +424,10 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
*/
static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
{
- u32 wakeup_mask;
-
if (!oh->class->sysc ||
!((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
- (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
+ (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
+ (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
return -EINVAL;
if (!oh->class->sysc->sysc_fields) {
@@ -434,12 +435,13 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
return -EINVAL;
}
- wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
-
- *v &= ~wakeup_mask;
+ if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
+ *v &= ~(0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
/* XXX test pwrdm_get_wken for this hwmod's subsystem */
@@ -678,6 +680,125 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
}
/**
+ * _enable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Enables the PRCM module mode related to the hwmod @oh.
+ * No return value.
+ */
+static void _enable_module(struct omap_hwmod *oh)
+{
+ /* The module mode does not exist prior OMAP4 */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ return;
+
+ if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+ return;
+
+ pr_debug("omap_hwmod: %s: _enable_module: %d\n",
+ oh->name, oh->prcm.omap4.modulemode);
+
+ omap4_cminst_module_enable(oh->prcm.omap4.modulemode,
+ oh->clkdm->prcm_partition,
+ oh->clkdm->cm_inst,
+ oh->clkdm->clkdm_offs,
+ oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
+ * _disable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Disable the PRCM module mode related to the hwmod @oh.
+ * No return value.
+ */
+static void _disable_module(struct omap_hwmod *oh)
+{
+ /* The module mode does not exist prior OMAP4 */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ return;
+
+ if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+ return;
+
+ pr_debug("omap_hwmod: %s: _disable_module\n", oh->name);
+
+ omap4_cminst_module_disable(oh->clkdm->prcm_partition,
+ oh->clkdm->cm_inst,
+ oh->clkdm->clkdm_offs,
+ oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
+ * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
+ * @oh: struct omap_hwmod *oh
+ *
+ * Count and return the number of MPU IRQs associated with the hwmod
+ * @oh. Used to allocate struct resource data. Returns 0 if @oh is
+ * NULL.
+ */
+static int _count_mpu_irqs(struct omap_hwmod *oh)
+{
+ struct omap_hwmod_irq_info *ohii;
+ int i = 0;
+
+ if (!oh || !oh->mpu_irqs)
+ return 0;
+
+ do {
+ ohii = &oh->mpu_irqs[i++];
+ } while (ohii->irq != -1);
+
+ return i;
+}
+
+/**
+ * _count_sdma_reqs - count the number of SDMA request lines associated with @oh
+ * @oh: struct omap_hwmod *oh
+ *
+ * Count and return the number of SDMA request lines associated with
+ * the hwmod @oh. Used to allocate struct resource data. Returns 0
+ * if @oh is NULL.
+ */
+static int _count_sdma_reqs(struct omap_hwmod *oh)
+{
+ struct omap_hwmod_dma_info *ohdi;
+ int i = 0;
+
+ if (!oh || !oh->sdma_reqs)
+ return 0;
+
+ do {
+ ohdi = &oh->sdma_reqs[i++];
+ } while (ohdi->dma_req != -1);
+
+ return i;
+}
+
+/**
+ * _count_ocp_if_addr_spaces - count the number of address space entries for @oh
+ * @oh: struct omap_hwmod *oh
+ *
+ * Count and return the number of address space ranges associated with
+ * the hwmod @oh. Used to allocate struct resource data. Returns 0
+ * if @oh is NULL.
+ */
+static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os)
+{
+ struct omap_hwmod_addr_space *mem;
+ int i = 0;
+
+ if (!os || !os->addr)
+ return 0;
+
+ do {
+ mem = &os->addr[i++];
+ } while (mem->pa_start != mem->pa_end);
+
+ return i;
+}
+
+/**
* _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
* @oh: struct omap_hwmod *
*
@@ -722,8 +843,7 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
{
struct omap_hwmod_ocp_if *os;
struct omap_hwmod_addr_space *mem;
- int i;
- int found = 0;
+ int i = 0, found = 0;
void __iomem *va_start;
if (!oh || oh->slaves_cnt == 0)
@@ -731,12 +851,14 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
os = oh->slaves[index];
- for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) {
- if (mem->flags & ADDR_TYPE_RT) {
+ if (!os->addr)
+ return NULL;
+
+ do {
+ mem = &os->addr[i++];
+ if (mem->flags & ADDR_TYPE_RT)
found = 1;
- break;
- }
- }
+ } while (!found && mem->pa_start != mem->pa_end);
if (found) {
va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
@@ -781,8 +903,16 @@ static void _enable_sysc(struct omap_hwmod *oh)
}
if (sf & SYSC_HAS_MIDLEMODE) {
- idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
- HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
+ if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+ idlemode = HWMOD_IDLEMODE_NO;
+ } else {
+ if (sf & SYSC_HAS_ENAWAKEUP)
+ _enable_wakeup(oh, &v);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+ else
+ idlemode = HWMOD_IDLEMODE_SMART;
+ }
_set_master_standbymode(oh, idlemode, &v);
}
@@ -840,8 +970,16 @@ static void _idle_sysc(struct omap_hwmod *oh)
}
if (sf & SYSC_HAS_MIDLEMODE) {
- idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
- HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART;
+ if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+ idlemode = HWMOD_IDLEMODE_FORCE;
+ } else {
+ if (sf & SYSC_HAS_ENAWAKEUP)
+ _enable_wakeup(oh, &v);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+ else
+ idlemode = HWMOD_IDLEMODE_SMART;
+ }
_set_master_standbymode(oh, idlemode, &v);
}
@@ -903,9 +1041,40 @@ static struct omap_hwmod *_lookup(const char *name)
return oh;
}
+/**
+ * _init_clkdm - look up a clockdomain name, store pointer in omap_hwmod
+ * @oh: struct omap_hwmod *
+ *
+ * Convert a clockdomain name stored in a struct omap_hwmod into a
+ * clockdomain pointer, and save it into the struct omap_hwmod.
+ * return -EINVAL if clkdm_name does not exist or if the lookup failed.
+ */
+static int _init_clkdm(struct omap_hwmod *oh)
+{
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ return 0;
+
+ if (!oh->clkdm_name) {
+ pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name);
+ return -EINVAL;
+ }
+
+ oh->clkdm = clkdm_lookup(oh->clkdm_name);
+ if (!oh->clkdm) {
+ pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n",
+ oh->name, oh->clkdm_name);
+ return -EINVAL;
+ }
+
+ pr_debug("omap_hwmod: %s: associated to clkdm %s\n",
+ oh->name, oh->clkdm_name);
+
+ return 0;
+}
/**
- * _init_clocks - clk_get() all clocks associated with this hwmod
+ * _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as
+ * well the clockdomain.
* @oh: struct omap_hwmod *
* @data: not used; pass NULL
*
@@ -925,9 +1094,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
ret |= _init_main_clk(oh);
ret |= _init_interface_clks(oh);
ret |= _init_opt_clks(oh);
+ ret |= _init_clkdm(oh);
if (!ret)
oh->_state = _HWMOD_STATE_CLKS_INITED;
+ else
+ pr_warning("omap_hwmod: %s: cannot _init_clocks\n", oh->name);
return ret;
}
@@ -939,7 +1111,7 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
* Wait for a module @oh to leave slave idle. Returns 0 if the module
* does not have an IDLEST bit or if the module successfully leaves
* slave idle; otherwise, pass along the return value of the
- * appropriate *_cm_wait_module_ready() function.
+ * appropriate *_cm*_wait_module_ready() function.
*/
static int _wait_target_ready(struct omap_hwmod *oh)
{
@@ -966,7 +1138,13 @@ static int _wait_target_ready(struct omap_hwmod *oh)
oh->prcm.omap2.idlest_reg_id,
oh->prcm.omap2.idlest_idle_bit);
} else if (cpu_is_omap44xx()) {
- ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);
+ if (!oh->clkdm)
+ return -EINVAL;
+
+ ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition,
+ oh->clkdm->cm_inst,
+ oh->clkdm->clkdm_offs,
+ oh->prcm.omap4.clkctrl_offs);
} else {
BUG();
};
@@ -975,6 +1153,36 @@ static int _wait_target_ready(struct omap_hwmod *oh)
}
/**
+ * _wait_target_disable - wait for a module to be disabled
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to enter slave idle. Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully enters
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_idle() function.
+ */
+static int _wait_target_disable(struct omap_hwmod *oh)
+{
+ /* TODO: For now just handle OMAP4+ */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ return 0;
+
+ if (!oh)
+ return -EINVAL;
+
+ if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+ return 0;
+
+ if (oh->flags & HWMOD_NO_IDLEST)
+ return 0;
+
+ return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
+ oh->clkdm->cm_inst,
+ oh->clkdm->clkdm_offs,
+ oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
* _lookup_hardreset - fill register bit info for this hwmod/reset line
* @oh: struct omap_hwmod *
* @name: name of the reset line in the context of this hwmod
@@ -1030,8 +1238,10 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
ohri.rst_shift);
else if (cpu_is_omap44xx())
- return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
- ohri.rst_shift);
+ return omap4_prminst_assert_hardreset(ohri.rst_shift,
+ oh->clkdm->pwrdm.ptr->prcm_partition,
+ oh->clkdm->pwrdm.ptr->prcm_offs,
+ oh->prcm.omap4.rstctrl_offs);
else
return -EINVAL;
}
@@ -1066,8 +1276,10 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
if (ohri.st_shift)
pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
oh->name, name);
- ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
- ohri.rst_shift);
+ ret = omap4_prminst_deassert_hardreset(ohri.rst_shift,
+ oh->clkdm->pwrdm.ptr->prcm_partition,
+ oh->clkdm->pwrdm.ptr->prcm_offs,
+ oh->prcm.omap4.rstctrl_offs);
} else {
return -EINVAL;
}
@@ -1102,8 +1314,10 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
ohri.st_shift);
} else if (cpu_is_omap44xx()) {
- return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
- ohri.rst_shift);
+ return omap4_prminst_is_hardreset_asserted(ohri.rst_shift,
+ oh->clkdm->pwrdm.ptr->prcm_partition,
+ oh->clkdm->pwrdm.ptr->prcm_offs,
+ oh->prcm.omap4.rstctrl_offs);
} else {
return -EINVAL;
}
@@ -1223,6 +1437,9 @@ static int _reset(struct omap_hwmod *oh)
static int _enable(struct omap_hwmod *oh)
{
int r;
+ int hwsup = 0;
+
+ pr_debug("omap_hwmod: %s: enabling\n", oh->name);
if (oh->_state != _HWMOD_STATE_INITIALIZED &&
oh->_state != _HWMOD_STATE_IDLE &&
@@ -1232,11 +1449,10 @@ static int _enable(struct omap_hwmod *oh)
return -EINVAL;
}
- pr_debug("omap_hwmod: %s: enabling\n", oh->name);
/*
* If an IP contains only one HW reset line, then de-assert it in order
- * to allow to enable the clocks. Otherwise the PRCM will return
+ * to allow the module state transition. Otherwise the PRCM will return
* Intransition status, and the init will failed.
*/
if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
@@ -1250,10 +1466,34 @@ static int _enable(struct omap_hwmod *oh)
omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
_add_initiator_dep(oh, mpu_oh);
+
+ if (oh->clkdm) {
+ /*
+ * A clockdomain must be in SW_SUP before enabling
+ * completely the module. The clockdomain can be set
+ * in HW_AUTO only when the module become ready.
+ */
+ hwsup = clkdm_in_hwsup(oh->clkdm);
+ r = clkdm_hwmod_enable(oh->clkdm, oh);
+ if (r) {
+ WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
+ oh->name, oh->clkdm->name, r);
+ return r;
+ }
+ }
+
_enable_clocks(oh);
+ _enable_module(oh);
r = _wait_target_ready(oh);
if (!r) {
+ /*
+ * Set the clockdomain to HW_AUTO only if the target is ready,
+ * assuming that the previous state was HW_AUTO
+ */
+ if (oh->clkdm && hwsup)
+ clkdm_allow_idle(oh->clkdm);
+
oh->_state = _HWMOD_STATE_ENABLED;
/* Access the sysconfig only if the target is ready */
@@ -1266,6 +1506,9 @@ static int _enable(struct omap_hwmod *oh)
_disable_clocks(oh);
pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
oh->name, r);
+
+ if (oh->clkdm)
+ clkdm_hwmod_disable(oh->clkdm, oh);
}
return r;
@@ -1281,18 +1524,33 @@ static int _enable(struct omap_hwmod *oh)
*/
static int _idle(struct omap_hwmod *oh)
{
+ int ret;
+
+ pr_debug("omap_hwmod: %s: idling\n", oh->name);
+
if (oh->_state != _HWMOD_STATE_ENABLED) {
WARN(1, "omap_hwmod: %s: idle state can only be entered from "
"enabled state\n", oh->name);
return -EINVAL;
}
- pr_debug("omap_hwmod: %s: idling\n", oh->name);
-
if (oh->class->sysc)
_idle_sysc(oh);
_del_initiator_dep(oh, mpu_oh);
+ _disable_module(oh);
+ ret = _wait_target_disable(oh);
+ if (ret)
+ pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+ oh->name);
+ /*
+ * The module must be in idle mode before disabling any parents
+ * clocks. Otherwise, the parent clock might be disabled before
+ * the module transition is done, and thus will prevent the
+ * transition to complete properly.
+ */
_disable_clocks(oh);
+ if (oh->clkdm)
+ clkdm_hwmod_disable(oh->clkdm, oh);
/* Mux pins for device idle if populated */
if (oh->mux && oh->mux->pads_dynamic)
@@ -1374,24 +1632,34 @@ static int _shutdown(struct omap_hwmod *oh)
}
}
- if (oh->class->sysc)
+ if (oh->class->sysc) {
+ if (oh->_state == _HWMOD_STATE_IDLE)
+ _enable(oh);
_shutdown_sysc(oh);
-
- /*
- * If an IP contains only one HW reset line, then assert it
- * before disabling the clocks and shutting down the IP.
- */
- if (oh->rst_lines_cnt == 1)
- _assert_hardreset(oh, oh->rst_lines[0].name);
+ }
/* clocks and deps are already disabled in idle */
if (oh->_state == _HWMOD_STATE_ENABLED) {
_del_initiator_dep(oh, mpu_oh);
/* XXX what about the other system initiators here? dma, dsp */
+ _disable_module(oh);
+ ret = _wait_target_disable(oh);
+ if (ret)
+ pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+ oh->name);
_disable_clocks(oh);
+ if (oh->clkdm)
+ clkdm_hwmod_disable(oh->clkdm, oh);
}
/* XXX Should this code also force-disable the optional clocks? */
+ /*
+ * If an IP contains only one HW reset line, then assert it
+ * after disabling the clocks and before shutting down the IP.
+ */
+ if (oh->rst_lines_cnt == 1)
+ _assert_hardreset(oh, oh->rst_lines[0].name);
+
/* Mux pins to safe mode or use populated off mode values */
if (oh->mux)
omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
@@ -1562,6 +1830,33 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
}
/**
+ * omap_hwmod_softreset - reset a module via SYSCONFIG.SOFTRESET bit
+ * @oh: struct omap_hwmod *
+ *
+ * This is a public function exposed to drivers. Some drivers may need to do
+ * some settings before and after resetting the device. Those drivers after
+ * doing the necessary settings could use this function to start a reset by
+ * setting the SYSCONFIG.SOFTRESET bit.
+ */
+int omap_hwmod_softreset(struct omap_hwmod *oh)
+{
+ u32 v;
+ int ret;
+
+ if (!oh || !(oh->_sysc_cache))
+ return -EINVAL;
+
+ v = oh->_sysc_cache;
+ ret = _set_softreset(oh, &v);
+ if (ret)
+ goto error;
+ _write_sysconfig(v, oh);
+
+error:
+ return ret;
+}
+
+/**
* omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
* @oh: struct omap_hwmod *
* @idlemode: SIDLEMODE field bits (shifted to bit 0)
@@ -1685,9 +1980,6 @@ static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
return 0;
oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
- if (!oh->_mpu_rt_va)
- pr_warning("omap_hwmod: %s found no _mpu_rt_va for %s\n",
- __func__, oh->name);
return 0;
}
@@ -1939,10 +2231,10 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
{
int ret, i;
- ret = oh->mpu_irqs_cnt + oh->sdma_reqs_cnt;
+ ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
for (i = 0; i < oh->slaves_cnt; i++)
- ret += oh->slaves[i]->addr_cnt;
+ ret += _count_ocp_if_addr_spaces(oh->slaves[i]);
return ret;
}
@@ -1959,12 +2251,13 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
*/
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
{
- int i, j;
+ int i, j, mpu_irqs_cnt, sdma_reqs_cnt;
int r = 0;
/* For each IRQ, DMA, memory area, fill in array.*/
- for (i = 0; i < oh->mpu_irqs_cnt; i++) {
+ mpu_irqs_cnt = _count_mpu_irqs(oh);
+ for (i = 0; i < mpu_irqs_cnt; i++) {
(res + r)->name = (oh->mpu_irqs + i)->name;
(res + r)->start = (oh->mpu_irqs + i)->irq;
(res + r)->end = (oh->mpu_irqs + i)->irq;
@@ -1972,7 +2265,8 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
r++;
}
- for (i = 0; i < oh->sdma_reqs_cnt; i++) {
+ sdma_reqs_cnt = _count_sdma_reqs(oh);
+ for (i = 0; i < sdma_reqs_cnt; i++) {
(res + r)->name = (oh->sdma_reqs + i)->name;
(res + r)->start = (oh->sdma_reqs + i)->dma_req;
(res + r)->end = (oh->sdma_reqs + i)->dma_req;
@@ -1982,10 +2276,12 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
for (i = 0; i < oh->slaves_cnt; i++) {
struct omap_hwmod_ocp_if *os;
+ int addr_cnt;
os = oh->slaves[i];
+ addr_cnt = _count_ocp_if_addr_spaces(os);
- for (j = 0; j < os->addr_cnt; j++) {
+ for (j = 0; j < addr_cnt; j++) {
(res + r)->name = (os->addr + j)->name;
(res + r)->start = (os->addr + j)->pa_start;
(res + r)->end = (os->addr + j)->pa_end;
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index c4d0ae87d62a..a015c69068f6 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1,7 +1,7 @@
/*
* omap_hwmod_2420_data.c - hardware modules present on the OMAP2420 chips
*
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -114,38 +114,20 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod;
static struct omap_hwmod omap2420_mcbsp2_hwmod;
/* l4 core -> mcspi1 interface */
-static struct omap_hwmod_addr_space omap2420_mcspi1_addr_space[] = {
- {
- .pa_start = 0x48098000,
- .pa_end = 0x480980ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi1 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_mcspi1_hwmod,
.clk = "mcspi1_ick",
- .addr = omap2420_mcspi1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_mcspi1_addr_space),
+ .addr = omap2_mcspi1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l4 core -> mcspi2 interface */
-static struct omap_hwmod_addr_space omap2420_mcspi2_addr_space[] = {
- {
- .pa_start = 0x4809a000,
- .pa_end = 0x4809a0ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi2 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_mcspi2_hwmod,
.clk = "mcspi2_ick",
- .addr = omap2420_mcspi2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_mcspi2_addr_space),
+ .addr = omap2_mcspi2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -157,95 +139,47 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
};
/* L4 CORE -> UART1 interface */
-static struct omap_hwmod_addr_space omap2420_uart1_addr_space[] = {
- {
- .pa_start = OMAP2_UART1_BASE,
- .pa_end = OMAP2_UART1_BASE + SZ_8K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_uart1_hwmod,
.clk = "uart1_ick",
- .addr = omap2420_uart1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_uart1_addr_space),
+ .addr = omap2xxx_uart1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* L4 CORE -> UART2 interface */
-static struct omap_hwmod_addr_space omap2420_uart2_addr_space[] = {
- {
- .pa_start = OMAP2_UART2_BASE,
- .pa_end = OMAP2_UART2_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_uart2_hwmod,
.clk = "uart2_ick",
- .addr = omap2420_uart2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_uart2_addr_space),
+ .addr = omap2xxx_uart2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* L4 PER -> UART3 interface */
-static struct omap_hwmod_addr_space omap2420_uart3_addr_space[] = {
- {
- .pa_start = OMAP2_UART3_BASE,
- .pa_end = OMAP2_UART3_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_uart3_hwmod,
.clk = "uart3_ick",
- .addr = omap2420_uart3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_uart3_addr_space),
+ .addr = omap2xxx_uart3_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* I2C IP block address space length (in bytes) */
-#define OMAP2_I2C_AS_LEN 128
-
/* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_addr_space omap2420_i2c1_addr_space[] = {
- {
- .pa_start = 0x48070000,
- .pa_end = 0x48070000 + OMAP2_I2C_AS_LEN - 1,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2420_l4_core__i2c1 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_i2c1_hwmod,
.clk = "i2c1_ick",
- .addr = omap2420_i2c1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_i2c1_addr_space),
+ .addr = omap2_i2c1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_addr_space omap2420_i2c2_addr_space[] = {
- {
- .pa_start = 0x48072000,
- .pa_end = 0x48072000 + OMAP2_I2C_AS_LEN - 1,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2420_l4_core__i2c2 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_i2c2_hwmod,
.clk = "i2c2_ick",
- .addr = omap2420_i2c2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_i2c2_addr_space),
+ .addr = omap2_i2c2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -340,29 +274,8 @@ static struct omap_hwmod omap2420_iva_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
-/* Timer Common */
-static struct omap_hwmod_class_sysconfig omap2420_timer_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_timer_hwmod_class = {
- .name = "timer",
- .sysc = &omap2420_timer_sysc,
- .rev = OMAP_TIMER_IP_VERSION_1,
-};
-
/* timer1 */
static struct omap_hwmod omap2420_timer1_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer1_mpu_irqs[] = {
- { .irq = 37, },
-};
static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
{
@@ -370,6 +283,7 @@ static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
.pa_end = 0x48028000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> timer1 */
@@ -378,7 +292,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__timer1 = {
.slave = &omap2420_timer1_hwmod,
.clk = "gpt1_ick",
.addr = omap2420_timer1_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -390,8 +303,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer1_slaves[] = {
/* timer1 hwmod */
static struct omap_hwmod omap2420_timer1_hwmod = {
.name = "timer1",
- .mpu_irqs = omap2420_timer1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer1_mpu_irqs),
+ .mpu_irqs = omap2_timer1_mpu_irqs,
.main_clk = "gpt1_fck",
.prcm = {
.omap2 = {
@@ -404,31 +316,19 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
},
.slaves = omap2420_timer1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer1_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer2 */
static struct omap_hwmod omap2420_timer2_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer2_mpu_irqs[] = {
- { .irq = 38, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer2_addrs[] = {
- {
- .pa_start = 0x4802a000,
- .pa_end = 0x4802a000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer2 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer2 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer2_hwmod,
.clk = "gpt2_ick",
- .addr = omap2420_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer2_addrs),
+ .addr = omap2xxx_timer2_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -440,8 +340,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer2_slaves[] = {
/* timer2 hwmod */
static struct omap_hwmod omap2420_timer2_hwmod = {
.name = "timer2",
- .mpu_irqs = omap2420_timer2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer2_mpu_irqs),
+ .mpu_irqs = omap2_timer2_mpu_irqs,
.main_clk = "gpt2_fck",
.prcm = {
.omap2 = {
@@ -454,31 +353,19 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
},
.slaves = omap2420_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer2_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer3 */
static struct omap_hwmod omap2420_timer3_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer3_mpu_irqs[] = {
- { .irq = 39, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer3_addrs[] = {
- {
- .pa_start = 0x48078000,
- .pa_end = 0x48078000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer3 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer3 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer3_hwmod,
.clk = "gpt3_ick",
- .addr = omap2420_timer3_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer3_addrs),
+ .addr = omap2xxx_timer3_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -490,8 +377,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer3_slaves[] = {
/* timer3 hwmod */
static struct omap_hwmod omap2420_timer3_hwmod = {
.name = "timer3",
- .mpu_irqs = omap2420_timer3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer3_mpu_irqs),
+ .mpu_irqs = omap2_timer3_mpu_irqs,
.main_clk = "gpt3_fck",
.prcm = {
.omap2 = {
@@ -504,31 +390,19 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
},
.slaves = omap2420_timer3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer3_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer4 */
static struct omap_hwmod omap2420_timer4_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer4_mpu_irqs[] = {
- { .irq = 40, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer4_addrs[] = {
- {
- .pa_start = 0x4807a000,
- .pa_end = 0x4807a000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer4 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer4 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer4_hwmod,
.clk = "gpt4_ick",
- .addr = omap2420_timer4_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer4_addrs),
+ .addr = omap2xxx_timer4_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -540,8 +414,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer4_slaves[] = {
/* timer4 hwmod */
static struct omap_hwmod omap2420_timer4_hwmod = {
.name = "timer4",
- .mpu_irqs = omap2420_timer4_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer4_mpu_irqs),
+ .mpu_irqs = omap2_timer4_mpu_irqs,
.main_clk = "gpt4_fck",
.prcm = {
.omap2 = {
@@ -554,31 +427,19 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
},
.slaves = omap2420_timer4_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer4_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer5 */
static struct omap_hwmod omap2420_timer5_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer5_mpu_irqs[] = {
- { .irq = 41, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer5_addrs[] = {
- {
- .pa_start = 0x4807c000,
- .pa_end = 0x4807c000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer5 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer5 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer5_hwmod,
.clk = "gpt5_ick",
- .addr = omap2420_timer5_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer5_addrs),
+ .addr = omap2xxx_timer5_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -590,8 +451,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer5_slaves[] = {
/* timer5 hwmod */
static struct omap_hwmod omap2420_timer5_hwmod = {
.name = "timer5",
- .mpu_irqs = omap2420_timer5_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer5_mpu_irqs),
+ .mpu_irqs = omap2_timer5_mpu_irqs,
.main_clk = "gpt5_fck",
.prcm = {
.omap2 = {
@@ -604,32 +464,20 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
},
.slaves = omap2420_timer5_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer5_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer6 */
static struct omap_hwmod omap2420_timer6_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer6_mpu_irqs[] = {
- { .irq = 42, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer6_addrs[] = {
- {
- .pa_start = 0x4807e000,
- .pa_end = 0x4807e000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer6 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer6 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer6_hwmod,
.clk = "gpt6_ick",
- .addr = omap2420_timer6_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer6_addrs),
+ .addr = omap2xxx_timer6_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -641,8 +489,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer6_slaves[] = {
/* timer6 hwmod */
static struct omap_hwmod omap2420_timer6_hwmod = {
.name = "timer6",
- .mpu_irqs = omap2420_timer6_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer6_mpu_irqs),
+ .mpu_irqs = omap2_timer6_mpu_irqs,
.main_clk = "gpt6_fck",
.prcm = {
.omap2 = {
@@ -655,31 +502,19 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
},
.slaves = omap2420_timer6_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer6_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer7 */
static struct omap_hwmod omap2420_timer7_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer7_mpu_irqs[] = {
- { .irq = 43, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer7_addrs[] = {
- {
- .pa_start = 0x48080000,
- .pa_end = 0x48080000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer7 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer7 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer7_hwmod,
.clk = "gpt7_ick",
- .addr = omap2420_timer7_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer7_addrs),
+ .addr = omap2xxx_timer7_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -691,8 +526,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer7_slaves[] = {
/* timer7 hwmod */
static struct omap_hwmod omap2420_timer7_hwmod = {
.name = "timer7",
- .mpu_irqs = omap2420_timer7_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer7_mpu_irqs),
+ .mpu_irqs = omap2_timer7_mpu_irqs,
.main_clk = "gpt7_fck",
.prcm = {
.omap2 = {
@@ -705,31 +539,19 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
},
.slaves = omap2420_timer7_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer7_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer8 */
static struct omap_hwmod omap2420_timer8_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer8_mpu_irqs[] = {
- { .irq = 44, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer8_addrs[] = {
- {
- .pa_start = 0x48082000,
- .pa_end = 0x48082000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer8 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer8 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer8_hwmod,
.clk = "gpt8_ick",
- .addr = omap2420_timer8_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer8_addrs),
+ .addr = omap2xxx_timer8_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -741,8 +563,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer8_slaves[] = {
/* timer8 hwmod */
static struct omap_hwmod omap2420_timer8_hwmod = {
.name = "timer8",
- .mpu_irqs = omap2420_timer8_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer8_mpu_irqs),
+ .mpu_irqs = omap2_timer8_mpu_irqs,
.main_clk = "gpt8_fck",
.prcm = {
.omap2 = {
@@ -755,31 +576,19 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
},
.slaves = omap2420_timer8_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer8_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer9 */
static struct omap_hwmod omap2420_timer9_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer9_mpu_irqs[] = {
- { .irq = 45, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer9_addrs[] = {
- {
- .pa_start = 0x48084000,
- .pa_end = 0x48084000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer9 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer9 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer9_hwmod,
.clk = "gpt9_ick",
- .addr = omap2420_timer9_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer9_addrs),
+ .addr = omap2xxx_timer9_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -791,8 +600,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer9_slaves[] = {
/* timer9 hwmod */
static struct omap_hwmod omap2420_timer9_hwmod = {
.name = "timer9",
- .mpu_irqs = omap2420_timer9_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer9_mpu_irqs),
+ .mpu_irqs = omap2_timer9_mpu_irqs,
.main_clk = "gpt9_fck",
.prcm = {
.omap2 = {
@@ -805,31 +613,19 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
},
.slaves = omap2420_timer9_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer9_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer10 */
static struct omap_hwmod omap2420_timer10_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer10_mpu_irqs[] = {
- { .irq = 46, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer10_addrs[] = {
- {
- .pa_start = 0x48086000,
- .pa_end = 0x48086000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer10 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer10 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer10_hwmod,
.clk = "gpt10_ick",
- .addr = omap2420_timer10_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer10_addrs),
+ .addr = omap2_timer10_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -841,8 +637,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer10_slaves[] = {
/* timer10 hwmod */
static struct omap_hwmod omap2420_timer10_hwmod = {
.name = "timer10",
- .mpu_irqs = omap2420_timer10_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer10_mpu_irqs),
+ .mpu_irqs = omap2_timer10_mpu_irqs,
.main_clk = "gpt10_fck",
.prcm = {
.omap2 = {
@@ -855,31 +650,19 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
},
.slaves = omap2420_timer10_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer10_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer11 */
static struct omap_hwmod omap2420_timer11_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer11_mpu_irqs[] = {
- { .irq = 47, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer11_addrs[] = {
- {
- .pa_start = 0x48088000,
- .pa_end = 0x48088000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer11 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer11 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer11_hwmod,
.clk = "gpt11_ick",
- .addr = omap2420_timer11_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer11_addrs),
+ .addr = omap2_timer11_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -891,8 +674,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer11_slaves[] = {
/* timer11 hwmod */
static struct omap_hwmod omap2420_timer11_hwmod = {
.name = "timer11",
- .mpu_irqs = omap2420_timer11_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer11_mpu_irqs),
+ .mpu_irqs = omap2_timer11_mpu_irqs,
.main_clk = "gpt11_fck",
.prcm = {
.omap2 = {
@@ -905,31 +687,19 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
},
.slaves = omap2420_timer11_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer11_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer12 */
static struct omap_hwmod omap2420_timer12_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer12_mpu_irqs[] = {
- { .irq = 48, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer12_addrs[] = {
- {
- .pa_start = 0x4808a000,
- .pa_end = 0x4808a000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer12 */
static struct omap_hwmod_ocp_if omap2420_l4_core__timer12 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_timer12_hwmod,
.clk = "gpt12_ick",
- .addr = omap2420_timer12_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_timer12_addrs),
+ .addr = omap2xxx_timer12_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -941,8 +711,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer12_slaves[] = {
/* timer12 hwmod */
static struct omap_hwmod omap2420_timer12_hwmod = {
.name = "timer12",
- .mpu_irqs = omap2420_timer12_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_timer12_mpu_irqs),
+ .mpu_irqs = omap2xxx_timer12_mpu_irqs,
.main_clk = "gpt12_fck",
.prcm = {
.omap2 = {
@@ -955,7 +724,7 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
},
.slaves = omap2420_timer12_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer12_slaves),
- .class = &omap2420_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
@@ -966,6 +735,7 @@ static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
.pa_end = 0x4802207f,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
@@ -973,31 +743,9 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
.slave = &omap2420_wd_timer2_hwmod,
.clk = "mpu_wdt_ick",
.addr = omap2420_wd_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_wd_timer2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/*
- * 'wd_timer' class
- * 32-bit watchdog upward counter that generates a pulse on the reset pin on
- * overflow condition
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = {
- .name = "wd_timer",
- .sysc = &omap2420_wd_timer_sysc,
- .pre_shutdown = &omap2_wd_timer_disable
-};
-
/* wd_timer2 */
static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
&omap2420_l4_wkup__wd_timer2,
@@ -1005,7 +753,7 @@ static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
static struct omap_hwmod omap2420_wd_timer2_hwmod = {
.name = "wd_timer2",
- .class = &omap2420_wd_timer_hwmod_class,
+ .class = &omap2xxx_wd_timer_hwmod_class,
.main_clk = "mpu_wdt_fck",
.prcm = {
.omap2 = {
@@ -1021,45 +769,16 @@ static struct omap_hwmod omap2420_wd_timer2_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
-/* UART */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
- .rev_offs = 0x50,
- .sysc_offs = 0x54,
- .syss_offs = 0x58,
- .sysc_flags = (SYSC_HAS_SIDLEMODE |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
- .name = "uart",
- .sysc = &uart_sysc,
-};
-
/* UART1 */
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
- { .irq = INT_24XX_UART1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
-};
-
static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
&omap2_l4_core__uart1,
};
static struct omap_hwmod omap2420_uart1_hwmod = {
.name = "uart1",
- .mpu_irqs = uart1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs),
- .sdma_reqs = uart1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart1_sdma_reqs),
+ .mpu_irqs = omap2_uart1_mpu_irqs,
+ .sdma_reqs = omap2_uart1_sdma_reqs,
.main_clk = "uart1_fck",
.prcm = {
.omap2 = {
@@ -1072,31 +791,20 @@ static struct omap_hwmod omap2420_uart1_hwmod = {
},
.slaves = omap2420_uart1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_uart1_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* UART2 */
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
- { .irq = INT_24XX_UART2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
-};
-
static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
&omap2_l4_core__uart2,
};
static struct omap_hwmod omap2420_uart2_hwmod = {
.name = "uart2",
- .mpu_irqs = uart2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs),
- .sdma_reqs = uart2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart2_sdma_reqs),
+ .mpu_irqs = omap2_uart2_mpu_irqs,
+ .sdma_reqs = omap2_uart2_sdma_reqs,
.main_clk = "uart2_fck",
.prcm = {
.omap2 = {
@@ -1109,31 +817,20 @@ static struct omap_hwmod omap2420_uart2_hwmod = {
},
.slaves = omap2420_uart2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_uart2_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* UART3 */
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
- { .irq = INT_24XX_UART3_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
-};
-
static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
&omap2_l4_core__uart3,
};
static struct omap_hwmod omap2420_uart3_hwmod = {
.name = "uart3",
- .mpu_irqs = uart3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs),
- .sdma_reqs = uart3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart3_sdma_reqs),
+ .mpu_irqs = omap2_uart3_mpu_irqs,
+ .sdma_reqs = omap2_uart3_sdma_reqs,
.main_clk = "uart3_fck",
.prcm = {
.omap2 = {
@@ -1146,53 +843,22 @@ static struct omap_hwmod omap2420_uart3_hwmod = {
},
.slaves = omap2420_uart3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_uart3_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
-/*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_dss_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_dss_hwmod_class = {
- .name = "dss",
- .sysc = &omap2420_dss_sysc,
-};
-
-static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = {
- { .name = "dispc", .dma_req = 5 },
-};
-
/* dss */
/* dss master ports */
static struct omap_hwmod_ocp_if *omap2420_dss_masters[] = {
&omap2420_dss__l3,
};
-static struct omap_hwmod_addr_space omap2420_dss_addrs[] = {
- {
- .pa_start = 0x48050000,
- .pa_end = 0x480503FF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss */
static struct omap_hwmod_ocp_if omap2420_l4_core__dss = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_dss_core_hwmod,
.clk = "dss_ick",
- .addr = omap2420_dss_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_dss_addrs),
+ .addr = omap2_dss_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
@@ -1214,10 +880,9 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
static struct omap_hwmod omap2420_dss_core_hwmod = {
.name = "dss_core",
- .class = &omap2420_dss_hwmod_class,
+ .class = &omap2_dss_hwmod_class,
.main_clk = "dss1_fck", /* instead of dss_fck */
- .sdma_reqs = omap2420_dss_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2420_dss_sdma_chs),
+ .sdma_reqs = omap2xxx_dss_sdma_chs,
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -1237,46 +902,12 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_dispc_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_dispc_hwmod_class = {
- .name = "dispc",
- .sysc = &omap2420_dispc_sysc,
-};
-
-static struct omap_hwmod_irq_info omap2420_dispc_irqs[] = {
- { .irq = 25 },
-};
-
-static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = {
- {
- .pa_start = 0x48050400,
- .pa_end = 0x480507FF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_dispc */
static struct omap_hwmod_ocp_if omap2420_l4_core__dss_dispc = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_dss_dispc_hwmod,
.clk = "dss_ick",
- .addr = omap2420_dss_dispc_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_dss_dispc_addrs),
+ .addr = omap2_dss_dispc_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION,
@@ -1293,9 +924,8 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
static struct omap_hwmod omap2420_dss_dispc_hwmod = {
.name = "dss_dispc",
- .class = &omap2420_dispc_hwmod_class,
- .mpu_irqs = omap2420_dispc_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dispc_irqs),
+ .class = &omap2_dispc_hwmod_class,
+ .mpu_irqs = omap2_dispc_irqs,
.main_clk = "dss1_fck",
.prcm = {
.omap2 = {
@@ -1312,41 +942,12 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_rfbi_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_rfbi_hwmod_class = {
- .name = "rfbi",
- .sysc = &omap2420_rfbi_sysc,
-};
-
-static struct omap_hwmod_addr_space omap2420_dss_rfbi_addrs[] = {
- {
- .pa_start = 0x48050800,
- .pa_end = 0x48050BFF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_rfbi */
static struct omap_hwmod_ocp_if omap2420_l4_core__dss_rfbi = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_dss_rfbi_hwmod,
.clk = "dss_ick",
- .addr = omap2420_dss_rfbi_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_dss_rfbi_addrs),
+ .addr = omap2_dss_rfbi_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
@@ -1363,7 +964,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
.name = "dss_rfbi",
- .class = &omap2420_rfbi_hwmod_class,
+ .class = &omap2_rfbi_hwmod_class,
.main_clk = "dss1_fck",
.prcm = {
.omap2 = {
@@ -1378,31 +979,12 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'venc' class
- * video encoder
- */
-
-static struct omap_hwmod_class omap2420_venc_hwmod_class = {
- .name = "venc",
-};
-
-/* dss_venc */
-static struct omap_hwmod_addr_space omap2420_dss_venc_addrs[] = {
- {
- .pa_start = 0x48050C00,
- .pa_end = 0x48050FFF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_venc */
static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_dss_venc_hwmod,
.clk = "dss_54m_fck",
- .addr = omap2420_dss_venc_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_dss_venc_addrs),
+ .addr = omap2_dss_venc_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP2420_L4_CORE_FW_DSS_VENC_REGION,
@@ -1420,7 +1002,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
static struct omap_hwmod omap2420_dss_venc_hwmod = {
.name = "dss_venc",
- .class = &omap2420_venc_hwmod_class,
+ .class = &omap2_venc_hwmod_class,
.main_clk = "dss1_fck",
.prcm = {
.omap2 = {
@@ -1447,20 +1029,18 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
static struct omap_hwmod_class i2c_class = {
.name = "i2c",
.sysc = &i2c_sysc,
+ .rev = OMAP_I2C_IP_VERSION_1,
+ .reset = &omap_i2c_reset,
};
-static struct omap_i2c_dev_attr i2c_dev_attr;
-
-/* I2C1 */
-
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
- { .irq = INT_24XX_I2C1_IRQ, },
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+ .flags = OMAP_I2C_FLAG_NO_FIFO |
+ OMAP_I2C_FLAG_SIMPLE_CLOCK |
+ OMAP_I2C_FLAG_16BIT_DATA_REG |
+ OMAP_I2C_FLAG_BUS_SHIFT_2,
};
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
- { .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
-};
+/* I2C1 */
static struct omap_hwmod_ocp_if *omap2420_i2c1_slaves[] = {
&omap2420_l4_core__i2c1,
@@ -1468,10 +1048,8 @@ static struct omap_hwmod_ocp_if *omap2420_i2c1_slaves[] = {
static struct omap_hwmod omap2420_i2c1_hwmod = {
.name = "i2c1",
- .mpu_irqs = i2c1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(i2c1_mpu_irqs),
- .sdma_reqs = i2c1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(i2c1_sdma_reqs),
+ .mpu_irqs = omap2_i2c1_mpu_irqs,
+ .sdma_reqs = omap2_i2c1_sdma_reqs,
.main_clk = "i2c1_fck",
.prcm = {
.omap2 = {
@@ -1492,25 +1070,14 @@ static struct omap_hwmod omap2420_i2c1_hwmod = {
/* I2C2 */
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
- { .irq = INT_24XX_I2C2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
- { .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
-};
-
static struct omap_hwmod_ocp_if *omap2420_i2c2_slaves[] = {
&omap2420_l4_core__i2c2,
};
static struct omap_hwmod omap2420_i2c2_hwmod = {
.name = "i2c2",
- .mpu_irqs = i2c2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(i2c2_mpu_irqs),
- .sdma_reqs = i2c2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(i2c2_sdma_reqs),
+ .mpu_irqs = omap2_i2c2_mpu_irqs,
+ .sdma_reqs = omap2_i2c2_sdma_reqs,
.main_clk = "i2c2_fck",
.prcm = {
.omap2 = {
@@ -1536,6 +1103,7 @@ static struct omap_hwmod_addr_space omap2420_gpio1_addr_space[] = {
.pa_end = 0x480181ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio1 = {
@@ -1543,7 +1111,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio1 = {
.slave = &omap2420_gpio1_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_gpio1_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1554,6 +1121,7 @@ static struct omap_hwmod_addr_space omap2420_gpio2_addr_space[] = {
.pa_end = 0x4801a1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio2 = {
@@ -1561,7 +1129,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio2 = {
.slave = &omap2420_gpio2_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_gpio2_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1572,6 +1139,7 @@ static struct omap_hwmod_addr_space omap2420_gpio3_addr_space[] = {
.pa_end = 0x4801c1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio3 = {
@@ -1579,7 +1147,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio3 = {
.slave = &omap2420_gpio3_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_gpio3_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1590,6 +1157,7 @@ static struct omap_hwmod_addr_space omap2420_gpio4_addr_space[] = {
.pa_end = 0x4801e1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio4 = {
@@ -1597,7 +1165,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio4 = {
.slave = &omap2420_gpio4_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio4_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2420_gpio4_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1607,32 +1174,7 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
.dbck_flag = false,
};
-static struct omap_hwmod_class_sysconfig omap242x_gpio_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
- SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-/*
- * 'gpio' class
- * general purpose io module
- */
-static struct omap_hwmod_class omap242x_gpio_hwmod_class = {
- .name = "gpio",
- .sysc = &omap242x_gpio_sysc,
- .rev = 0,
-};
-
/* gpio1 */
-static struct omap_hwmod_irq_info omap242x_gpio1_irqs[] = {
- { .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
-};
-
static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
&omap2420_l4_wkup__gpio1,
};
@@ -1640,8 +1182,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
static struct omap_hwmod omap2420_gpio1_hwmod = {
.name = "gpio1",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap242x_gpio1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap242x_gpio1_irqs),
+ .mpu_irqs = omap2_gpio1_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1654,16 +1195,12 @@ static struct omap_hwmod omap2420_gpio1_hwmod = {
},
.slaves = omap2420_gpio1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_gpio1_slaves),
- .class = &omap242x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* gpio2 */
-static struct omap_hwmod_irq_info omap242x_gpio2_irqs[] = {
- { .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
-};
-
static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
&omap2420_l4_wkup__gpio2,
};
@@ -1671,8 +1208,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
static struct omap_hwmod omap2420_gpio2_hwmod = {
.name = "gpio2",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap242x_gpio2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap242x_gpio2_irqs),
+ .mpu_irqs = omap2_gpio2_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1685,16 +1221,12 @@ static struct omap_hwmod omap2420_gpio2_hwmod = {
},
.slaves = omap2420_gpio2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_gpio2_slaves),
- .class = &omap242x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* gpio3 */
-static struct omap_hwmod_irq_info omap242x_gpio3_irqs[] = {
- { .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
-};
-
static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
&omap2420_l4_wkup__gpio3,
};
@@ -1702,8 +1234,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
static struct omap_hwmod omap2420_gpio3_hwmod = {
.name = "gpio3",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap242x_gpio3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap242x_gpio3_irqs),
+ .mpu_irqs = omap2_gpio3_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1716,16 +1247,12 @@ static struct omap_hwmod omap2420_gpio3_hwmod = {
},
.slaves = omap2420_gpio3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_gpio3_slaves),
- .class = &omap242x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* gpio4 */
-static struct omap_hwmod_irq_info omap242x_gpio4_irqs[] = {
- { .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
-};
-
static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
&omap2420_l4_wkup__gpio4,
};
@@ -1733,8 +1260,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
static struct omap_hwmod omap2420_gpio4_hwmod = {
.name = "gpio4",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap242x_gpio4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap242x_gpio4_irqs),
+ .mpu_irqs = omap2_gpio4_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1747,28 +1273,11 @@ static struct omap_hwmod omap2420_gpio4_hwmod = {
},
.slaves = omap2420_gpio4_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_gpio4_slaves),
- .class = &omap242x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
-/* system dma */
-static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x002c,
- .syss_offs = 0x0028,
- .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
- SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_dma_hwmod_class = {
- .name = "dma",
- .sysc = &omap2420_dma_sysc,
-};
-
/* dma attributes */
static struct omap_dma_dev_attr dma_dev_attr = {
.dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
@@ -1776,21 +1285,6 @@ static struct omap_dma_dev_attr dma_dev_attr = {
.lch_count = 32,
};
-static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
- { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
- { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
- { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
- { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
-};
-
-static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
- {
- .pa_start = 0x48056000,
- .pa_end = 0x48056fff,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* dma_system -> L3 */
static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = {
.master = &omap2420_dma_system_hwmod,
@@ -1809,8 +1303,7 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_dma_system_hwmod,
.clk = "sdma_ick",
- .addr = omap2420_dma_system_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_dma_system_addrs),
+ .addr = omap2_dma_system_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1821,9 +1314,8 @@ static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = {
static struct omap_hwmod omap2420_dma_system_hwmod = {
.name = "dma",
- .class = &omap2420_dma_hwmod_class,
- .mpu_irqs = omap2420_dma_system_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dma_system_irqs),
+ .class = &omap2xxx_dma_hwmod_class,
+ .mpu_irqs = omap2_dma_system_irqs,
.main_clk = "core_l3_ck",
.slaves = omap2420_dma_system_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_dma_system_slaves),
@@ -1834,48 +1326,19 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'mailbox' class
- * mailbox module allowing communication between the on-chip processors
- * using a queued mailbox-interrupt mechanism.
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_mailbox_sysc = {
- .rev_offs = 0x000,
- .sysc_offs = 0x010,
- .syss_offs = 0x014,
- .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_mailbox_hwmod_class = {
- .name = "mailbox",
- .sysc = &omap2420_mailbox_sysc,
-};
-
/* mailbox */
static struct omap_hwmod omap2420_mailbox_hwmod;
static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
{ .name = "dsp", .irq = 26 },
{ .name = "iva", .irq = 34 },
-};
-
-static struct omap_hwmod_addr_space omap2420_mailbox_addrs[] = {
- {
- .pa_start = 0x48094000,
- .pa_end = 0x480941ff,
- .flags = ADDR_TYPE_RT,
- },
+ { .irq = -1 }
};
/* l4_core -> mailbox */
static struct omap_hwmod_ocp_if omap2420_l4_core__mailbox = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_mailbox_hwmod,
- .addr = omap2420_mailbox_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_mailbox_addrs),
+ .addr = omap2_mailbox_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1886,9 +1349,8 @@ static struct omap_hwmod_ocp_if *omap2420_mailbox_slaves[] = {
static struct omap_hwmod omap2420_mailbox_hwmod = {
.name = "mailbox",
- .class = &omap2420_mailbox_hwmod_class,
+ .class = &omap2xxx_mailbox_hwmod_class,
.mpu_irqs = omap2420_mailbox_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_mailbox_irqs),
.main_clk = "mailboxes_ick",
.prcm = {
.omap2 = {
@@ -1904,45 +1366,7 @@ static struct omap_hwmod omap2420_mailbox_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
-/*
- * 'mcspi' class
- * multichannel serial port interface (mcspi) / master/slave synchronous serial
- * bus
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_mcspi_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_mcspi_class = {
- .name = "mcspi",
- .sysc = &omap2420_mcspi_sysc,
- .rev = OMAP2_MCSPI_REV,
-};
-
/* mcspi1 */
-static struct omap_hwmod_irq_info omap2420_mcspi1_mpu_irqs[] = {
- { .irq = 65 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcspi1_sdma_reqs[] = {
- { .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
- { .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
- { .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
- { .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
- { .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
- { .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
- { .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
- { .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
-};
-
static struct omap_hwmod_ocp_if *omap2420_mcspi1_slaves[] = {
&omap2420_l4_core__mcspi1,
};
@@ -1953,10 +1377,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
static struct omap_hwmod omap2420_mcspi1_hwmod = {
.name = "mcspi1_hwmod",
- .mpu_irqs = omap2420_mcspi1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_mcspi1_mpu_irqs),
- .sdma_reqs = omap2420_mcspi1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2420_mcspi1_sdma_reqs),
+ .mpu_irqs = omap2_mcspi1_mpu_irqs,
+ .sdma_reqs = omap2_mcspi1_sdma_reqs,
.main_clk = "mcspi1_fck",
.prcm = {
.omap2 = {
@@ -1969,23 +1391,12 @@ static struct omap_hwmod omap2420_mcspi1_hwmod = {
},
.slaves = omap2420_mcspi1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_mcspi1_slaves),
- .class = &omap2420_mcspi_class,
- .dev_attr = &omap_mcspi1_dev_attr,
+ .class = &omap2xxx_mcspi_class,
+ .dev_attr = &omap_mcspi1_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* mcspi2 */
-static struct omap_hwmod_irq_info omap2420_mcspi2_mpu_irqs[] = {
- { .irq = 66 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcspi2_sdma_reqs[] = {
- { .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
- { .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
- { .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
- { .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
-};
-
static struct omap_hwmod_ocp_if *omap2420_mcspi2_slaves[] = {
&omap2420_l4_core__mcspi2,
};
@@ -1996,10 +1407,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
static struct omap_hwmod omap2420_mcspi2_hwmod = {
.name = "mcspi2_hwmod",
- .mpu_irqs = omap2420_mcspi2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_mcspi2_mpu_irqs),
- .sdma_reqs = omap2420_mcspi2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2420_mcspi2_sdma_reqs),
+ .mpu_irqs = omap2_mcspi2_mpu_irqs,
+ .sdma_reqs = omap2_mcspi2_sdma_reqs,
.main_clk = "mcspi2_fck",
.prcm = {
.omap2 = {
@@ -2012,8 +1421,8 @@ static struct omap_hwmod omap2420_mcspi2_hwmod = {
},
.slaves = omap2420_mcspi2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_mcspi2_slaves),
- .class = &omap2420_mcspi_class,
- .dev_attr = &omap_mcspi2_dev_attr,
+ .class = &omap2xxx_mcspi_class,
+ .dev_attr = &omap_mcspi2_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
@@ -2030,20 +1439,7 @@ static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = {
static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
{ .name = "tx", .irq = 59 },
{ .name = "rx", .irq = 60 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcbsp1_sdma_chs[] = {
- { .name = "rx", .dma_req = 32 },
- { .name = "tx", .dma_req = 31 },
-};
-
-static struct omap_hwmod_addr_space omap2420_mcbsp1_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x48074000,
- .pa_end = 0x480740ff,
- .flags = ADDR_TYPE_RT
- },
+ { .irq = -1 }
};
/* l4_core -> mcbsp1 */
@@ -2051,8 +1447,7 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp1 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_mcbsp1_hwmod,
.clk = "mcbsp1_ick",
- .addr = omap2420_mcbsp1_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_mcbsp1_addrs),
+ .addr = omap2_mcbsp1_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2065,9 +1460,7 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
.name = "mcbsp1",
.class = &omap2420_mcbsp_hwmod_class,
.mpu_irqs = omap2420_mcbsp1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_mcbsp1_irqs),
- .sdma_reqs = omap2420_mcbsp1_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2420_mcbsp1_sdma_chs),
+ .sdma_reqs = omap2_mcbsp1_sdma_reqs,
.main_clk = "mcbsp1_fck",
.prcm = {
.omap2 = {
@@ -2087,20 +1480,7 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
static struct omap_hwmod_irq_info omap2420_mcbsp2_irqs[] = {
{ .name = "tx", .irq = 62 },
{ .name = "rx", .irq = 63 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcbsp2_sdma_chs[] = {
- { .name = "rx", .dma_req = 34 },
- { .name = "tx", .dma_req = 33 },
-};
-
-static struct omap_hwmod_addr_space omap2420_mcbsp2_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x48076000,
- .pa_end = 0x480760ff,
- .flags = ADDR_TYPE_RT
- },
+ { .irq = -1 }
};
/* l4_core -> mcbsp2 */
@@ -2108,8 +1488,7 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
.master = &omap2420_l4_core_hwmod,
.slave = &omap2420_mcbsp2_hwmod,
.clk = "mcbsp2_ick",
- .addr = omap2420_mcbsp2_addrs,
- .addr_cnt = ARRAY_SIZE(omap2420_mcbsp2_addrs),
+ .addr = omap2xxx_mcbsp2_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2122,9 +1501,7 @@ static struct omap_hwmod omap2420_mcbsp2_hwmod = {
.name = "mcbsp2",
.class = &omap2420_mcbsp_hwmod_class,
.mpu_irqs = omap2420_mcbsp2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2420_mcbsp2_irqs),
- .sdma_reqs = omap2420_mcbsp2_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2420_mcbsp2_sdma_chs),
+ .sdma_reqs = omap2_mcbsp2_sdma_reqs,
.main_clk = "mcbsp2_fck",
.prcm = {
.omap2 = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 9682dd519f8d..16743c7d6e8e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1,7 +1,7 @@
/*
* omap_hwmod_2430_data.c - hardware modules present on the OMAP2430 chips
*
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -131,42 +131,21 @@ static struct omap_hwmod_ocp_if omap2430_usbhsotg__l3 = {
.user = OCP_USER_MPU,
};
-/* I2C IP block address space length (in bytes) */
-#define OMAP2_I2C_AS_LEN 128
-
/* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_addr_space omap2430_i2c1_addr_space[] = {
- {
- .pa_start = 0x48070000,
- .pa_end = 0x48070000 + OMAP2_I2C_AS_LEN - 1,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2430_l4_core__i2c1 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_i2c1_hwmod,
.clk = "i2c1_ick",
- .addr = omap2430_i2c1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_i2c1_addr_space),
+ .addr = omap2_i2c1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_addr_space omap2430_i2c2_addr_space[] = {
- {
- .pa_start = 0x48072000,
- .pa_end = 0x48072000 + OMAP2_I2C_AS_LEN - 1,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2430_l4_core__i2c2 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_i2c2_hwmod,
.clk = "i2c2_ick",
- .addr = omap2430_i2c2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_i2c2_addr_space),
+ .addr = omap2_i2c2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -178,56 +157,29 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
};
/* L4 CORE -> UART1 interface */
-static struct omap_hwmod_addr_space omap2430_uart1_addr_space[] = {
- {
- .pa_start = OMAP2_UART1_BASE,
- .pa_end = OMAP2_UART1_BASE + SZ_8K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_uart1_hwmod,
.clk = "uart1_ick",
- .addr = omap2430_uart1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_uart1_addr_space),
+ .addr = omap2xxx_uart1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* L4 CORE -> UART2 interface */
-static struct omap_hwmod_addr_space omap2430_uart2_addr_space[] = {
- {
- .pa_start = OMAP2_UART2_BASE,
- .pa_end = OMAP2_UART2_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_uart2_hwmod,
.clk = "uart2_ick",
- .addr = omap2430_uart2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_uart2_addr_space),
+ .addr = omap2xxx_uart2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* L4 PER -> UART3 interface */
-static struct omap_hwmod_addr_space omap2430_uart3_addr_space[] = {
- {
- .pa_start = OMAP2_UART3_BASE,
- .pa_end = OMAP2_UART3_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_uart3_hwmod,
.clk = "uart3_ick",
- .addr = omap2430_uart3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_uart3_addr_space),
+ .addr = omap2xxx_uart3_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -248,7 +200,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__usbhsotg = {
.slave = &omap2430_usbhsotg_hwmod,
.clk = "usb_l4_ick",
.addr = omap2430_usbhsotg_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_usbhsotg_addrs),
.user = OCP_USER_MPU,
};
@@ -261,38 +212,20 @@ static struct omap_hwmod_ocp_if *omap2430_usbhsotg_slaves[] = {
};
/* L4 CORE -> MMC1 interface */
-static struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
- {
- .pa_start = 0x4809c000,
- .pa_end = 0x4809c1ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2430_l4_core__mmc1 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mmc1_hwmod,
.clk = "mmchs1_ick",
.addr = omap2430_mmc1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_mmc1_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* L4 CORE -> MMC2 interface */
-static struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
- {
- .pa_start = 0x480b4000,
- .pa_end = 0x480b41ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2430_l4_core__mmc2 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mmc2_hwmod,
- .addr = omap2430_mmc2_addr_space,
.clk = "mmchs2_ick",
- .addr_cnt = ARRAY_SIZE(omap2430_mmc2_addr_space),
+ .addr = omap2430_mmc2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -333,56 +266,29 @@ static struct omap_hwmod_ocp_if *omap2430_l4_wkup_masters[] = {
};
/* l4 core -> mcspi1 interface */
-static struct omap_hwmod_addr_space omap2430_mcspi1_addr_space[] = {
- {
- .pa_start = 0x48098000,
- .pa_end = 0x480980ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi1 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mcspi1_hwmod,
.clk = "mcspi1_ick",
- .addr = omap2430_mcspi1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_mcspi1_addr_space),
+ .addr = omap2_mcspi1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l4 core -> mcspi2 interface */
-static struct omap_hwmod_addr_space omap2430_mcspi2_addr_space[] = {
- {
- .pa_start = 0x4809a000,
- .pa_end = 0x4809a0ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi2 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mcspi2_hwmod,
.clk = "mcspi2_ick",
- .addr = omap2430_mcspi2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_mcspi2_addr_space),
+ .addr = omap2_mcspi2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l4 core -> mcspi3 interface */
-static struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
- {
- .pa_start = 0x480b8000,
- .pa_end = 0x480b80ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi3 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mcspi3_hwmod,
.clk = "mcspi3_ick",
.addr = omap2430_mcspi3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_mcspi3_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -441,29 +347,8 @@ static struct omap_hwmod omap2430_iva_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
-/* Timer Common */
-static struct omap_hwmod_class_sysconfig omap2430_timer_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_timer_hwmod_class = {
- .name = "timer",
- .sysc = &omap2430_timer_sysc,
- .rev = OMAP_TIMER_IP_VERSION_1,
-};
-
/* timer1 */
static struct omap_hwmod omap2430_timer1_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer1_mpu_irqs[] = {
- { .irq = 37, },
-};
static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
{
@@ -471,6 +356,7 @@ static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
.pa_end = 0x49018000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> timer1 */
@@ -479,7 +365,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__timer1 = {
.slave = &omap2430_timer1_hwmod,
.clk = "gpt1_ick",
.addr = omap2430_timer1_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -491,8 +376,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer1_slaves[] = {
/* timer1 hwmod */
static struct omap_hwmod omap2430_timer1_hwmod = {
.name = "timer1",
- .mpu_irqs = omap2430_timer1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer1_mpu_irqs),
+ .mpu_irqs = omap2_timer1_mpu_irqs,
.main_clk = "gpt1_fck",
.prcm = {
.omap2 = {
@@ -505,31 +389,19 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
},
.slaves = omap2430_timer1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer1_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer2 */
static struct omap_hwmod omap2430_timer2_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer2_mpu_irqs[] = {
- { .irq = 38, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer2_addrs[] = {
- {
- .pa_start = 0x4802a000,
- .pa_end = 0x4802a000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer2 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer2 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer2_hwmod,
.clk = "gpt2_ick",
- .addr = omap2430_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer2_addrs),
+ .addr = omap2xxx_timer2_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -541,8 +413,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer2_slaves[] = {
/* timer2 hwmod */
static struct omap_hwmod omap2430_timer2_hwmod = {
.name = "timer2",
- .mpu_irqs = omap2430_timer2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer2_mpu_irqs),
+ .mpu_irqs = omap2_timer2_mpu_irqs,
.main_clk = "gpt2_fck",
.prcm = {
.omap2 = {
@@ -555,31 +426,19 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
},
.slaves = omap2430_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer2_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer3 */
static struct omap_hwmod omap2430_timer3_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer3_mpu_irqs[] = {
- { .irq = 39, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer3_addrs[] = {
- {
- .pa_start = 0x48078000,
- .pa_end = 0x48078000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer3 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer3 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer3_hwmod,
.clk = "gpt3_ick",
- .addr = omap2430_timer3_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer3_addrs),
+ .addr = omap2xxx_timer3_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -591,8 +450,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer3_slaves[] = {
/* timer3 hwmod */
static struct omap_hwmod omap2430_timer3_hwmod = {
.name = "timer3",
- .mpu_irqs = omap2430_timer3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer3_mpu_irqs),
+ .mpu_irqs = omap2_timer3_mpu_irqs,
.main_clk = "gpt3_fck",
.prcm = {
.omap2 = {
@@ -605,31 +463,19 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
},
.slaves = omap2430_timer3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer3_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer4 */
static struct omap_hwmod omap2430_timer4_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer4_mpu_irqs[] = {
- { .irq = 40, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer4_addrs[] = {
- {
- .pa_start = 0x4807a000,
- .pa_end = 0x4807a000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer4 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer4 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer4_hwmod,
.clk = "gpt4_ick",
- .addr = omap2430_timer4_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer4_addrs),
+ .addr = omap2xxx_timer4_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -641,8 +487,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer4_slaves[] = {
/* timer4 hwmod */
static struct omap_hwmod omap2430_timer4_hwmod = {
.name = "timer4",
- .mpu_irqs = omap2430_timer4_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer4_mpu_irqs),
+ .mpu_irqs = omap2_timer4_mpu_irqs,
.main_clk = "gpt4_fck",
.prcm = {
.omap2 = {
@@ -655,31 +500,19 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
},
.slaves = omap2430_timer4_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer4_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer5 */
static struct omap_hwmod omap2430_timer5_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer5_mpu_irqs[] = {
- { .irq = 41, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer5_addrs[] = {
- {
- .pa_start = 0x4807c000,
- .pa_end = 0x4807c000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer5 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer5 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer5_hwmod,
.clk = "gpt5_ick",
- .addr = omap2430_timer5_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer5_addrs),
+ .addr = omap2xxx_timer5_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -691,8 +524,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer5_slaves[] = {
/* timer5 hwmod */
static struct omap_hwmod omap2430_timer5_hwmod = {
.name = "timer5",
- .mpu_irqs = omap2430_timer5_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer5_mpu_irqs),
+ .mpu_irqs = omap2_timer5_mpu_irqs,
.main_clk = "gpt5_fck",
.prcm = {
.omap2 = {
@@ -705,31 +537,19 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
},
.slaves = omap2430_timer5_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer5_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer6 */
static struct omap_hwmod omap2430_timer6_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer6_mpu_irqs[] = {
- { .irq = 42, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer6_addrs[] = {
- {
- .pa_start = 0x4807e000,
- .pa_end = 0x4807e000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer6 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer6 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer6_hwmod,
.clk = "gpt6_ick",
- .addr = omap2430_timer6_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer6_addrs),
+ .addr = omap2xxx_timer6_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -741,8 +561,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer6_slaves[] = {
/* timer6 hwmod */
static struct omap_hwmod omap2430_timer6_hwmod = {
.name = "timer6",
- .mpu_irqs = omap2430_timer6_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer6_mpu_irqs),
+ .mpu_irqs = omap2_timer6_mpu_irqs,
.main_clk = "gpt6_fck",
.prcm = {
.omap2 = {
@@ -755,31 +574,19 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
},
.slaves = omap2430_timer6_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer6_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer7 */
static struct omap_hwmod omap2430_timer7_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer7_mpu_irqs[] = {
- { .irq = 43, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer7_addrs[] = {
- {
- .pa_start = 0x48080000,
- .pa_end = 0x48080000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer7 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer7 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer7_hwmod,
.clk = "gpt7_ick",
- .addr = omap2430_timer7_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer7_addrs),
+ .addr = omap2xxx_timer7_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -791,8 +598,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer7_slaves[] = {
/* timer7 hwmod */
static struct omap_hwmod omap2430_timer7_hwmod = {
.name = "timer7",
- .mpu_irqs = omap2430_timer7_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer7_mpu_irqs),
+ .mpu_irqs = omap2_timer7_mpu_irqs,
.main_clk = "gpt7_fck",
.prcm = {
.omap2 = {
@@ -805,31 +611,19 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
},
.slaves = omap2430_timer7_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer7_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer8 */
static struct omap_hwmod omap2430_timer8_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer8_mpu_irqs[] = {
- { .irq = 44, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer8_addrs[] = {
- {
- .pa_start = 0x48082000,
- .pa_end = 0x48082000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer8 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer8 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer8_hwmod,
.clk = "gpt8_ick",
- .addr = omap2430_timer8_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer8_addrs),
+ .addr = omap2xxx_timer8_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -841,8 +635,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer8_slaves[] = {
/* timer8 hwmod */
static struct omap_hwmod omap2430_timer8_hwmod = {
.name = "timer8",
- .mpu_irqs = omap2430_timer8_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer8_mpu_irqs),
+ .mpu_irqs = omap2_timer8_mpu_irqs,
.main_clk = "gpt8_fck",
.prcm = {
.omap2 = {
@@ -855,31 +648,19 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
},
.slaves = omap2430_timer8_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer8_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer9 */
static struct omap_hwmod omap2430_timer9_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer9_mpu_irqs[] = {
- { .irq = 45, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer9_addrs[] = {
- {
- .pa_start = 0x48084000,
- .pa_end = 0x48084000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer9 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer9 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer9_hwmod,
.clk = "gpt9_ick",
- .addr = omap2430_timer9_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer9_addrs),
+ .addr = omap2xxx_timer9_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -891,8 +672,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer9_slaves[] = {
/* timer9 hwmod */
static struct omap_hwmod omap2430_timer9_hwmod = {
.name = "timer9",
- .mpu_irqs = omap2430_timer9_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer9_mpu_irqs),
+ .mpu_irqs = omap2_timer9_mpu_irqs,
.main_clk = "gpt9_fck",
.prcm = {
.omap2 = {
@@ -905,31 +685,19 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
},
.slaves = omap2430_timer9_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer9_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer10 */
static struct omap_hwmod omap2430_timer10_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer10_mpu_irqs[] = {
- { .irq = 46, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer10_addrs[] = {
- {
- .pa_start = 0x48086000,
- .pa_end = 0x48086000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer10 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer10 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer10_hwmod,
.clk = "gpt10_ick",
- .addr = omap2430_timer10_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer10_addrs),
+ .addr = omap2_timer10_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -941,8 +709,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer10_slaves[] = {
/* timer10 hwmod */
static struct omap_hwmod omap2430_timer10_hwmod = {
.name = "timer10",
- .mpu_irqs = omap2430_timer10_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer10_mpu_irqs),
+ .mpu_irqs = omap2_timer10_mpu_irqs,
.main_clk = "gpt10_fck",
.prcm = {
.omap2 = {
@@ -955,31 +722,19 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
},
.slaves = omap2430_timer10_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer10_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer11 */
static struct omap_hwmod omap2430_timer11_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer11_mpu_irqs[] = {
- { .irq = 47, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer11_addrs[] = {
- {
- .pa_start = 0x48088000,
- .pa_end = 0x48088000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer11 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer11 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer11_hwmod,
.clk = "gpt11_ick",
- .addr = omap2430_timer11_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer11_addrs),
+ .addr = omap2_timer11_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -991,8 +746,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer11_slaves[] = {
/* timer11 hwmod */
static struct omap_hwmod omap2430_timer11_hwmod = {
.name = "timer11",
- .mpu_irqs = omap2430_timer11_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer11_mpu_irqs),
+ .mpu_irqs = omap2_timer11_mpu_irqs,
.main_clk = "gpt11_fck",
.prcm = {
.omap2 = {
@@ -1005,31 +759,19 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
},
.slaves = omap2430_timer11_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer11_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer12 */
static struct omap_hwmod omap2430_timer12_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer12_mpu_irqs[] = {
- { .irq = 48, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer12_addrs[] = {
- {
- .pa_start = 0x4808a000,
- .pa_end = 0x4808a000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer12 */
static struct omap_hwmod_ocp_if omap2430_l4_core__timer12 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_timer12_hwmod,
.clk = "gpt12_ick",
- .addr = omap2430_timer12_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_timer12_addrs),
+ .addr = omap2xxx_timer12_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1041,8 +783,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer12_slaves[] = {
/* timer12 hwmod */
static struct omap_hwmod omap2430_timer12_hwmod = {
.name = "timer12",
- .mpu_irqs = omap2430_timer12_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_timer12_mpu_irqs),
+ .mpu_irqs = omap2xxx_timer12_mpu_irqs,
.main_clk = "gpt12_fck",
.prcm = {
.omap2 = {
@@ -1055,7 +796,7 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
},
.slaves = omap2430_timer12_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer12_slaves),
- .class = &omap2430_timer_hwmod_class,
+ .class = &omap2xxx_timer_hwmod_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
@@ -1066,6 +807,7 @@ static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
.pa_end = 0x4901607f,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
@@ -1073,31 +815,9 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
.slave = &omap2430_wd_timer2_hwmod,
.clk = "mpu_wdt_ick",
.addr = omap2430_wd_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_wd_timer2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/*
- * 'wd_timer' class
- * 32-bit watchdog upward counter that generates a pulse on the reset pin on
- * overflow condition
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
- .rev_offs = 0x0,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
- .name = "wd_timer",
- .sysc = &omap2430_wd_timer_sysc,
- .pre_shutdown = &omap2_wd_timer_disable
-};
-
/* wd_timer2 */
static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
&omap2430_l4_wkup__wd_timer2,
@@ -1105,7 +825,7 @@ static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
static struct omap_hwmod omap2430_wd_timer2_hwmod = {
.name = "wd_timer2",
- .class = &omap2430_wd_timer_hwmod_class,
+ .class = &omap2xxx_wd_timer_hwmod_class,
.main_clk = "mpu_wdt_fck",
.prcm = {
.omap2 = {
@@ -1121,45 +841,16 @@ static struct omap_hwmod omap2430_wd_timer2_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
-/* UART */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
- .rev_offs = 0x50,
- .sysc_offs = 0x54,
- .syss_offs = 0x58,
- .sysc_flags = (SYSC_HAS_SIDLEMODE |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
- .name = "uart",
- .sysc = &uart_sysc,
-};
-
/* UART1 */
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
- { .irq = INT_24XX_UART1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
-};
-
static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
&omap2_l4_core__uart1,
};
static struct omap_hwmod omap2430_uart1_hwmod = {
.name = "uart1",
- .mpu_irqs = uart1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs),
- .sdma_reqs = uart1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart1_sdma_reqs),
+ .mpu_irqs = omap2_uart1_mpu_irqs,
+ .sdma_reqs = omap2_uart1_sdma_reqs,
.main_clk = "uart1_fck",
.prcm = {
.omap2 = {
@@ -1172,31 +863,20 @@ static struct omap_hwmod omap2430_uart1_hwmod = {
},
.slaves = omap2430_uart1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_uart1_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* UART2 */
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
- { .irq = INT_24XX_UART2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
-};
-
static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
&omap2_l4_core__uart2,
};
static struct omap_hwmod omap2430_uart2_hwmod = {
.name = "uart2",
- .mpu_irqs = uart2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs),
- .sdma_reqs = uart2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart2_sdma_reqs),
+ .mpu_irqs = omap2_uart2_mpu_irqs,
+ .sdma_reqs = omap2_uart2_sdma_reqs,
.main_clk = "uart2_fck",
.prcm = {
.omap2 = {
@@ -1209,31 +889,20 @@ static struct omap_hwmod omap2430_uart2_hwmod = {
},
.slaves = omap2430_uart2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_uart2_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* UART3 */
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
- { .irq = INT_24XX_UART3_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
-};
-
static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
&omap2_l4_core__uart3,
};
static struct omap_hwmod omap2430_uart3_hwmod = {
.name = "uart3",
- .mpu_irqs = uart3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs),
- .sdma_reqs = uart3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart3_sdma_reqs),
+ .mpu_irqs = omap2_uart3_mpu_irqs,
+ .sdma_reqs = omap2_uart3_sdma_reqs,
.main_clk = "uart3_fck",
.prcm = {
.omap2 = {
@@ -1246,53 +915,22 @@ static struct omap_hwmod omap2430_uart3_hwmod = {
},
.slaves = omap2430_uart3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_uart3_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
-/*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_dss_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_dss_hwmod_class = {
- .name = "dss",
- .sysc = &omap2430_dss_sysc,
-};
-
-static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = {
- { .name = "dispc", .dma_req = 5 },
-};
-
/* dss */
/* dss master ports */
static struct omap_hwmod_ocp_if *omap2430_dss_masters[] = {
&omap2430_dss__l3,
};
-static struct omap_hwmod_addr_space omap2430_dss_addrs[] = {
- {
- .pa_start = 0x48050000,
- .pa_end = 0x480503FF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss */
static struct omap_hwmod_ocp_if omap2430_l4_core__dss = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_dss_core_hwmod,
.clk = "dss_ick",
- .addr = omap2430_dss_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_dss_addrs),
+ .addr = omap2_dss_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1308,10 +946,9 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
static struct omap_hwmod omap2430_dss_core_hwmod = {
.name = "dss_core",
- .class = &omap2430_dss_hwmod_class,
+ .class = &omap2_dss_hwmod_class,
.main_clk = "dss1_fck", /* instead of dss_fck */
- .sdma_reqs = omap2430_dss_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_dss_sdma_chs),
+ .sdma_reqs = omap2xxx_dss_sdma_chs,
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -1331,46 +968,12 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_dispc_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_dispc_hwmod_class = {
- .name = "dispc",
- .sysc = &omap2430_dispc_sysc,
-};
-
-static struct omap_hwmod_irq_info omap2430_dispc_irqs[] = {
- { .irq = 25 },
-};
-
-static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = {
- {
- .pa_start = 0x48050400,
- .pa_end = 0x480507FF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_dispc */
static struct omap_hwmod_ocp_if omap2430_l4_core__dss_dispc = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_dss_dispc_hwmod,
.clk = "dss_ick",
- .addr = omap2430_dss_dispc_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_dss_dispc_addrs),
+ .addr = omap2_dss_dispc_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1381,9 +984,8 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
static struct omap_hwmod omap2430_dss_dispc_hwmod = {
.name = "dss_dispc",
- .class = &omap2430_dispc_hwmod_class,
- .mpu_irqs = omap2430_dispc_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dispc_irqs),
+ .class = &omap2_dispc_hwmod_class,
+ .mpu_irqs = omap2_dispc_irqs,
.main_clk = "dss1_fck",
.prcm = {
.omap2 = {
@@ -1400,41 +1002,12 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_rfbi_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_rfbi_hwmod_class = {
- .name = "rfbi",
- .sysc = &omap2430_rfbi_sysc,
-};
-
-static struct omap_hwmod_addr_space omap2430_dss_rfbi_addrs[] = {
- {
- .pa_start = 0x48050800,
- .pa_end = 0x48050BFF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_rfbi */
static struct omap_hwmod_ocp_if omap2430_l4_core__dss_rfbi = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_dss_rfbi_hwmod,
.clk = "dss_ick",
- .addr = omap2430_dss_rfbi_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_dss_rfbi_addrs),
+ .addr = omap2_dss_rfbi_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1445,7 +1018,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
.name = "dss_rfbi",
- .class = &omap2430_rfbi_hwmod_class,
+ .class = &omap2_rfbi_hwmod_class,
.main_clk = "dss1_fck",
.prcm = {
.omap2 = {
@@ -1460,31 +1033,12 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'venc' class
- * video encoder
- */
-
-static struct omap_hwmod_class omap2430_venc_hwmod_class = {
- .name = "venc",
-};
-
-/* dss_venc */
-static struct omap_hwmod_addr_space omap2430_dss_venc_addrs[] = {
- {
- .pa_start = 0x48050C00,
- .pa_end = 0x48050FFF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_venc */
static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_dss_venc_hwmod,
.clk = "dss_54m_fck",
- .addr = omap2430_dss_venc_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_dss_venc_addrs),
+ .addr = omap2_dss_venc_addrs,
.flags = OCPIF_SWSUP_IDLE,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1496,7 +1050,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
static struct omap_hwmod omap2430_dss_venc_hwmod = {
.name = "dss_venc",
- .class = &omap2430_venc_hwmod_class,
+ .class = &omap2_venc_hwmod_class,
.main_clk = "dss1_fck",
.prcm = {
.omap2 = {
@@ -1524,33 +1078,28 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
static struct omap_hwmod_class i2c_class = {
.name = "i2c",
.sysc = &i2c_sysc,
+ .rev = OMAP_I2C_IP_VERSION_1,
+ .reset = &omap_i2c_reset,
};
static struct omap_i2c_dev_attr i2c_dev_attr = {
.fifo_depth = 8, /* bytes */
+ .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+ OMAP_I2C_FLAG_BUS_SHIFT_2 |
+ OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
};
/* I2C1 */
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
- { .irq = INT_24XX_I2C1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
- { .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
-};
-
static struct omap_hwmod_ocp_if *omap2430_i2c1_slaves[] = {
&omap2430_l4_core__i2c1,
};
static struct omap_hwmod omap2430_i2c1_hwmod = {
.name = "i2c1",
- .mpu_irqs = i2c1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(i2c1_mpu_irqs),
- .sdma_reqs = i2c1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(i2c1_sdma_reqs),
+ .flags = HWMOD_16BIT_REG,
+ .mpu_irqs = omap2_i2c1_mpu_irqs,
+ .sdma_reqs = omap2_i2c1_sdma_reqs,
.main_clk = "i2chs1_fck",
.prcm = {
.omap2 = {
@@ -1578,25 +1127,15 @@ static struct omap_hwmod omap2430_i2c1_hwmod = {
/* I2C2 */
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
- { .irq = INT_24XX_I2C2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
- { .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
-};
-
static struct omap_hwmod_ocp_if *omap2430_i2c2_slaves[] = {
&omap2430_l4_core__i2c2,
};
static struct omap_hwmod omap2430_i2c2_hwmod = {
.name = "i2c2",
- .mpu_irqs = i2c2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(i2c2_mpu_irqs),
- .sdma_reqs = i2c2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(i2c2_sdma_reqs),
+ .flags = HWMOD_16BIT_REG,
+ .mpu_irqs = omap2_i2c2_mpu_irqs,
+ .sdma_reqs = omap2_i2c2_sdma_reqs,
.main_clk = "i2chs2_fck",
.prcm = {
.omap2 = {
@@ -1621,6 +1160,7 @@ static struct omap_hwmod_addr_space omap2430_gpio1_addr_space[] = {
.pa_end = 0x4900C1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
@@ -1628,7 +1168,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
.slave = &omap2430_gpio1_hwmod,
.clk = "gpios_ick",
.addr = omap2430_gpio1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_gpio1_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1639,6 +1178,7 @@ static struct omap_hwmod_addr_space omap2430_gpio2_addr_space[] = {
.pa_end = 0x4900E1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
@@ -1646,7 +1186,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
.slave = &omap2430_gpio2_hwmod,
.clk = "gpios_ick",
.addr = omap2430_gpio2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_gpio2_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1657,6 +1196,7 @@ static struct omap_hwmod_addr_space omap2430_gpio3_addr_space[] = {
.pa_end = 0x490101ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
@@ -1664,7 +1204,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
.slave = &omap2430_gpio3_hwmod,
.clk = "gpios_ick",
.addr = omap2430_gpio3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_gpio3_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1675,6 +1214,7 @@ static struct omap_hwmod_addr_space omap2430_gpio4_addr_space[] = {
.pa_end = 0x490121ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
@@ -1682,7 +1222,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
.slave = &omap2430_gpio4_hwmod,
.clk = "gpios_ick",
.addr = omap2430_gpio4_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_gpio4_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1693,6 +1232,7 @@ static struct omap_hwmod_addr_space omap2430_gpio5_addr_space[] = {
.pa_end = 0x480B61ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
@@ -1700,7 +1240,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
.slave = &omap2430_gpio5_hwmod,
.clk = "gpio5_ick",
.addr = omap2430_gpio5_addr_space,
- .addr_cnt = ARRAY_SIZE(omap2430_gpio5_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1710,32 +1249,7 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
.dbck_flag = false,
};
-static struct omap_hwmod_class_sysconfig omap243x_gpio_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
- SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-/*
- * 'gpio' class
- * general purpose io module
- */
-static struct omap_hwmod_class omap243x_gpio_hwmod_class = {
- .name = "gpio",
- .sysc = &omap243x_gpio_sysc,
- .rev = 0,
-};
-
/* gpio1 */
-static struct omap_hwmod_irq_info omap243x_gpio1_irqs[] = {
- { .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
-};
-
static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
&omap2430_l4_wkup__gpio1,
};
@@ -1743,8 +1257,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
static struct omap_hwmod omap2430_gpio1_hwmod = {
.name = "gpio1",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap243x_gpio1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap243x_gpio1_irqs),
+ .mpu_irqs = omap2_gpio1_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1757,16 +1270,12 @@ static struct omap_hwmod omap2430_gpio1_hwmod = {
},
.slaves = omap2430_gpio1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_gpio1_slaves),
- .class = &omap243x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* gpio2 */
-static struct omap_hwmod_irq_info omap243x_gpio2_irqs[] = {
- { .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
-};
-
static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
&omap2430_l4_wkup__gpio2,
};
@@ -1774,8 +1283,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
static struct omap_hwmod omap2430_gpio2_hwmod = {
.name = "gpio2",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap243x_gpio2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap243x_gpio2_irqs),
+ .mpu_irqs = omap2_gpio2_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1788,16 +1296,12 @@ static struct omap_hwmod omap2430_gpio2_hwmod = {
},
.slaves = omap2430_gpio2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_gpio2_slaves),
- .class = &omap243x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* gpio3 */
-static struct omap_hwmod_irq_info omap243x_gpio3_irqs[] = {
- { .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
-};
-
static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
&omap2430_l4_wkup__gpio3,
};
@@ -1805,8 +1309,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
static struct omap_hwmod omap2430_gpio3_hwmod = {
.name = "gpio3",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap243x_gpio3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap243x_gpio3_irqs),
+ .mpu_irqs = omap2_gpio3_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1819,16 +1322,12 @@ static struct omap_hwmod omap2430_gpio3_hwmod = {
},
.slaves = omap2430_gpio3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_gpio3_slaves),
- .class = &omap243x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* gpio4 */
-static struct omap_hwmod_irq_info omap243x_gpio4_irqs[] = {
- { .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
-};
-
static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
&omap2430_l4_wkup__gpio4,
};
@@ -1836,8 +1335,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
static struct omap_hwmod omap2430_gpio4_hwmod = {
.name = "gpio4",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap243x_gpio4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap243x_gpio4_irqs),
+ .mpu_irqs = omap2_gpio4_irqs,
.main_clk = "gpios_fck",
.prcm = {
.omap2 = {
@@ -1850,7 +1348,7 @@ static struct omap_hwmod omap2430_gpio4_hwmod = {
},
.slaves = omap2430_gpio4_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_gpio4_slaves),
- .class = &omap243x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
@@ -1858,6 +1356,7 @@ static struct omap_hwmod omap2430_gpio4_hwmod = {
/* gpio5 */
static struct omap_hwmod_irq_info omap243x_gpio5_irqs[] = {
{ .irq = 33 }, /* INT_24XX_GPIO_BANK5 */
+ { .irq = -1 }
};
static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
@@ -1868,7 +1367,6 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
.name = "gpio5",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap243x_gpio5_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap243x_gpio5_irqs),
.main_clk = "gpio5_fck",
.prcm = {
.omap2 = {
@@ -1881,28 +1379,11 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
},
.slaves = omap2430_gpio5_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_gpio5_slaves),
- .class = &omap243x_gpio_hwmod_class,
+ .class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
-/* dma_system */
-static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x002c,
- .syss_offs = 0x0028,
- .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
- SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_dma_hwmod_class = {
- .name = "dma",
- .sysc = &omap2430_dma_sysc,
-};
-
/* dma attributes */
static struct omap_dma_dev_attr dma_dev_attr = {
.dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
@@ -1910,21 +1391,6 @@ static struct omap_dma_dev_attr dma_dev_attr = {
.lch_count = 32,
};
-static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
- { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
- { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
- { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
- { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
-};
-
-static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
- {
- .pa_start = 0x48056000,
- .pa_end = 0x48056fff,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* dma_system -> L3 */
static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
.master = &omap2430_dma_system_hwmod,
@@ -1943,8 +1409,7 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_dma_system_hwmod,
.clk = "sdma_ick",
- .addr = omap2430_dma_system_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_dma_system_addrs),
+ .addr = omap2_dma_system_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1955,9 +1420,8 @@ static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
static struct omap_hwmod omap2430_dma_system_hwmod = {
.name = "dma",
- .class = &omap2430_dma_hwmod_class,
- .mpu_irqs = omap2430_dma_system_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dma_system_irqs),
+ .class = &omap2xxx_dma_hwmod_class,
+ .mpu_irqs = omap2_dma_system_irqs,
.main_clk = "core_l3_ck",
.slaves = omap2430_dma_system_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_dma_system_slaves),
@@ -1968,47 +1432,18 @@ static struct omap_hwmod omap2430_dma_system_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'mailbox' class
- * mailbox module allowing communication between the on-chip processors
- * using a queued mailbox-interrupt mechanism.
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_mailbox_sysc = {
- .rev_offs = 0x000,
- .sysc_offs = 0x010,
- .syss_offs = 0x014,
- .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_mailbox_hwmod_class = {
- .name = "mailbox",
- .sysc = &omap2430_mailbox_sysc,
-};
-
/* mailbox */
static struct omap_hwmod omap2430_mailbox_hwmod;
static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
{ .irq = 26 },
-};
-
-static struct omap_hwmod_addr_space omap2430_mailbox_addrs[] = {
- {
- .pa_start = 0x48094000,
- .pa_end = 0x480941ff,
- .flags = ADDR_TYPE_RT,
- },
+ { .irq = -1 }
};
/* l4_core -> mailbox */
static struct omap_hwmod_ocp_if omap2430_l4_core__mailbox = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mailbox_hwmod,
- .addr = omap2430_mailbox_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_mailbox_addrs),
+ .addr = omap2_mailbox_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2019,9 +1454,8 @@ static struct omap_hwmod_ocp_if *omap2430_mailbox_slaves[] = {
static struct omap_hwmod omap2430_mailbox_hwmod = {
.name = "mailbox",
- .class = &omap2430_mailbox_hwmod_class,
+ .class = &omap2xxx_mailbox_hwmod_class,
.mpu_irqs = omap2430_mailbox_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mailbox_irqs),
.main_clk = "mailboxes_ick",
.prcm = {
.omap2 = {
@@ -2037,45 +1471,7 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
-/*
- * 'mcspi' class
- * multichannel serial port interface (mcspi) / master/slave synchronous serial
- * bus
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_mcspi_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_mcspi_class = {
- .name = "mcspi",
- .sysc = &omap2430_mcspi_sysc,
- .rev = OMAP2_MCSPI_REV,
-};
-
/* mcspi1 */
-static struct omap_hwmod_irq_info omap2430_mcspi1_mpu_irqs[] = {
- { .irq = 65 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcspi1_sdma_reqs[] = {
- { .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
- { .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
- { .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
- { .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
- { .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
- { .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
- { .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
- { .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
-};
-
static struct omap_hwmod_ocp_if *omap2430_mcspi1_slaves[] = {
&omap2430_l4_core__mcspi1,
};
@@ -2086,10 +1482,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
static struct omap_hwmod omap2430_mcspi1_hwmod = {
.name = "mcspi1_hwmod",
- .mpu_irqs = omap2430_mcspi1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcspi1_mpu_irqs),
- .sdma_reqs = omap2430_mcspi1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcspi1_sdma_reqs),
+ .mpu_irqs = omap2_mcspi1_mpu_irqs,
+ .sdma_reqs = omap2_mcspi1_sdma_reqs,
.main_clk = "mcspi1_fck",
.prcm = {
.omap2 = {
@@ -2102,23 +1496,12 @@ static struct omap_hwmod omap2430_mcspi1_hwmod = {
},
.slaves = omap2430_mcspi1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcspi1_slaves),
- .class = &omap2430_mcspi_class,
- .dev_attr = &omap_mcspi1_dev_attr,
+ .class = &omap2xxx_mcspi_class,
+ .dev_attr = &omap_mcspi1_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcspi2 */
-static struct omap_hwmod_irq_info omap2430_mcspi2_mpu_irqs[] = {
- { .irq = 66 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcspi2_sdma_reqs[] = {
- { .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
- { .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
- { .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
- { .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
-};
-
static struct omap_hwmod_ocp_if *omap2430_mcspi2_slaves[] = {
&omap2430_l4_core__mcspi2,
};
@@ -2129,10 +1512,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
static struct omap_hwmod omap2430_mcspi2_hwmod = {
.name = "mcspi2_hwmod",
- .mpu_irqs = omap2430_mcspi2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcspi2_mpu_irqs),
- .sdma_reqs = omap2430_mcspi2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcspi2_sdma_reqs),
+ .mpu_irqs = omap2_mcspi2_mpu_irqs,
+ .sdma_reqs = omap2_mcspi2_sdma_reqs,
.main_clk = "mcspi2_fck",
.prcm = {
.omap2 = {
@@ -2145,14 +1526,15 @@ static struct omap_hwmod omap2430_mcspi2_hwmod = {
},
.slaves = omap2430_mcspi2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcspi2_slaves),
- .class = &omap2430_mcspi_class,
- .dev_attr = &omap_mcspi2_dev_attr,
+ .class = &omap2xxx_mcspi_class,
+ .dev_attr = &omap_mcspi2_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcspi3 */
static struct omap_hwmod_irq_info omap2430_mcspi3_mpu_irqs[] = {
{ .irq = 91 },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
@@ -2160,6 +1542,7 @@ static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
{ .name = "rx0", .dma_req = 16 }, /* DMA_SPI3_RX0 */
{ .name = "tx1", .dma_req = 23 }, /* DMA_SPI3_TX1 */
{ .name = "rx1", .dma_req = 24 }, /* DMA_SPI3_RX1 */
+ { .dma_req = -1 }
};
static struct omap_hwmod_ocp_if *omap2430_mcspi3_slaves[] = {
@@ -2173,9 +1556,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
static struct omap_hwmod omap2430_mcspi3_hwmod = {
.name = "mcspi3_hwmod",
.mpu_irqs = omap2430_mcspi3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcspi3_mpu_irqs),
.sdma_reqs = omap2430_mcspi3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcspi3_sdma_reqs),
.main_clk = "mcspi3_fck",
.prcm = {
.omap2 = {
@@ -2188,8 +1569,8 @@ static struct omap_hwmod omap2430_mcspi3_hwmod = {
},
.slaves = omap2430_mcspi3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcspi3_slaves),
- .class = &omap2430_mcspi_class,
- .dev_attr = &omap_mcspi3_dev_attr,
+ .class = &omap2xxx_mcspi_class,
+ .dev_attr = &omap_mcspi3_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
@@ -2218,12 +1599,12 @@ static struct omap_hwmod_irq_info omap2430_usbhsotg_mpu_irqs[] = {
{ .name = "mc", .irq = 92 },
{ .name = "dma", .irq = 93 },
+ { .irq = -1 }
};
static struct omap_hwmod omap2430_usbhsotg_hwmod = {
.name = "usb_otg_hs",
.mpu_irqs = omap2430_usbhsotg_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_usbhsotg_mpu_irqs),
.main_clk = "usbhs_ick",
.prcm = {
.omap2 = {
@@ -2273,20 +1654,7 @@ static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = {
{ .name = "rx", .irq = 60 },
{ .name = "ovr", .irq = 61 },
{ .name = "common", .irq = 64 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcbsp1_sdma_chs[] = {
- { .name = "rx", .dma_req = 32 },
- { .name = "tx", .dma_req = 31 },
-};
-
-static struct omap_hwmod_addr_space omap2430_mcbsp1_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x48074000,
- .pa_end = 0x480740ff,
- .flags = ADDR_TYPE_RT
- },
+ { .irq = -1 }
};
/* l4_core -> mcbsp1 */
@@ -2294,8 +1662,7 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp1 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mcbsp1_hwmod,
.clk = "mcbsp1_ick",
- .addr = omap2430_mcbsp1_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_mcbsp1_addrs),
+ .addr = omap2_mcbsp1_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2308,9 +1675,7 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = {
.name = "mcbsp1",
.class = &omap2430_mcbsp_hwmod_class,
.mpu_irqs = omap2430_mcbsp1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcbsp1_irqs),
- .sdma_reqs = omap2430_mcbsp1_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcbsp1_sdma_chs),
+ .sdma_reqs = omap2_mcbsp1_sdma_reqs,
.main_clk = "mcbsp1_fck",
.prcm = {
.omap2 = {
@@ -2331,20 +1696,7 @@ static struct omap_hwmod_irq_info omap2430_mcbsp2_irqs[] = {
{ .name = "tx", .irq = 62 },
{ .name = "rx", .irq = 63 },
{ .name = "common", .irq = 16 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcbsp2_sdma_chs[] = {
- { .name = "rx", .dma_req = 34 },
- { .name = "tx", .dma_req = 33 },
-};
-
-static struct omap_hwmod_addr_space omap2430_mcbsp2_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x48076000,
- .pa_end = 0x480760ff,
- .flags = ADDR_TYPE_RT
- },
+ { .irq = -1 }
};
/* l4_core -> mcbsp2 */
@@ -2352,8 +1704,7 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp2 = {
.master = &omap2430_l4_core_hwmod,
.slave = &omap2430_mcbsp2_hwmod,
.clk = "mcbsp2_ick",
- .addr = omap2430_mcbsp2_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_mcbsp2_addrs),
+ .addr = omap2xxx_mcbsp2_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2366,9 +1717,7 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = {
.name = "mcbsp2",
.class = &omap2430_mcbsp_hwmod_class,
.mpu_irqs = omap2430_mcbsp2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcbsp2_irqs),
- .sdma_reqs = omap2430_mcbsp2_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcbsp2_sdma_chs),
+ .sdma_reqs = omap2_mcbsp2_sdma_reqs,
.main_clk = "mcbsp2_fck",
.prcm = {
.omap2 = {
@@ -2389,11 +1738,7 @@ static struct omap_hwmod_irq_info omap2430_mcbsp3_irqs[] = {
{ .name = "tx", .irq = 89 },
{ .name = "rx", .irq = 90 },
{ .name = "common", .irq = 17 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcbsp3_sdma_chs[] = {
- { .name = "rx", .dma_req = 18 },
- { .name = "tx", .dma_req = 17 },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
@@ -2403,6 +1748,7 @@ static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
.pa_end = 0x4808C0ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> mcbsp3 */
@@ -2411,7 +1757,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp3 = {
.slave = &omap2430_mcbsp3_hwmod,
.clk = "mcbsp3_ick",
.addr = omap2430_mcbsp3_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_mcbsp3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2424,9 +1769,7 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = {
.name = "mcbsp3",
.class = &omap2430_mcbsp_hwmod_class,
.mpu_irqs = omap2430_mcbsp3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcbsp3_irqs),
- .sdma_reqs = omap2430_mcbsp3_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcbsp3_sdma_chs),
+ .sdma_reqs = omap2_mcbsp3_sdma_reqs,
.main_clk = "mcbsp3_fck",
.prcm = {
.omap2 = {
@@ -2447,11 +1790,13 @@ static struct omap_hwmod_irq_info omap2430_mcbsp4_irqs[] = {
{ .name = "tx", .irq = 54 },
{ .name = "rx", .irq = 55 },
{ .name = "common", .irq = 18 },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap2430_mcbsp4_sdma_chs[] = {
{ .name = "rx", .dma_req = 20 },
{ .name = "tx", .dma_req = 19 },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
@@ -2461,6 +1806,7 @@ static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
.pa_end = 0x4808E0ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> mcbsp4 */
@@ -2469,7 +1815,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp4 = {
.slave = &omap2430_mcbsp4_hwmod,
.clk = "mcbsp4_ick",
.addr = omap2430_mcbsp4_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_mcbsp4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2482,9 +1827,7 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = {
.name = "mcbsp4",
.class = &omap2430_mcbsp_hwmod_class,
.mpu_irqs = omap2430_mcbsp4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcbsp4_irqs),
.sdma_reqs = omap2430_mcbsp4_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcbsp4_sdma_chs),
.main_clk = "mcbsp4_fck",
.prcm = {
.omap2 = {
@@ -2505,11 +1848,13 @@ static struct omap_hwmod_irq_info omap2430_mcbsp5_irqs[] = {
{ .name = "tx", .irq = 81 },
{ .name = "rx", .irq = 82 },
{ .name = "common", .irq = 19 },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap2430_mcbsp5_sdma_chs[] = {
{ .name = "rx", .dma_req = 22 },
{ .name = "tx", .dma_req = 21 },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
@@ -2519,6 +1864,7 @@ static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
.pa_end = 0x480960ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> mcbsp5 */
@@ -2527,7 +1873,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
.slave = &omap2430_mcbsp5_hwmod,
.clk = "mcbsp5_ick",
.addr = omap2430_mcbsp5_addrs,
- .addr_cnt = ARRAY_SIZE(omap2430_mcbsp5_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2540,9 +1885,7 @@ static struct omap_hwmod omap2430_mcbsp5_hwmod = {
.name = "mcbsp5",
.class = &omap2430_mcbsp_hwmod_class,
.mpu_irqs = omap2430_mcbsp5_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mcbsp5_irqs),
.sdma_reqs = omap2430_mcbsp5_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mcbsp5_sdma_chs),
.main_clk = "mcbsp5_fck",
.prcm = {
.omap2 = {
@@ -2580,11 +1923,13 @@ static struct omap_hwmod_class omap2430_mmc_class = {
static struct omap_hwmod_irq_info omap2430_mmc1_mpu_irqs[] = {
{ .irq = 83 },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap2430_mmc1_sdma_reqs[] = {
{ .name = "tx", .dma_req = 61 }, /* DMA_MMC1_TX */
{ .name = "rx", .dma_req = 62 }, /* DMA_MMC1_RX */
+ { .dma_req = -1 }
};
static struct omap_hwmod_opt_clk omap2430_mmc1_opt_clks[] = {
@@ -2603,9 +1948,7 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
.name = "mmc1",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap2430_mmc1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mmc1_mpu_irqs),
.sdma_reqs = omap2430_mmc1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mmc1_sdma_reqs),
.opt_clks = omap2430_mmc1_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(omap2430_mmc1_opt_clks),
.main_clk = "mmchs1_fck",
@@ -2629,11 +1972,13 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
static struct omap_hwmod_irq_info omap2430_mmc2_mpu_irqs[] = {
{ .irq = 86 },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap2430_mmc2_sdma_reqs[] = {
{ .name = "tx", .dma_req = 47 }, /* DMA_MMC2_TX */
{ .name = "rx", .dma_req = 48 }, /* DMA_MMC2_RX */
+ { .dma_req = -1 }
};
static struct omap_hwmod_opt_clk omap2430_mmc2_opt_clks[] = {
@@ -2648,9 +1993,7 @@ static struct omap_hwmod omap2430_mmc2_hwmod = {
.name = "mmc2",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap2430_mmc2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap2430_mmc2_mpu_irqs),
.sdma_reqs = omap2430_mmc2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap2430_mmc2_sdma_reqs),
.opt_clks = omap2430_mmc2_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(omap2430_mmc2_opt_clks),
.main_clk = "mmchs2_fck",
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
new file mode 100644
index 000000000000..04637fabadd2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
@@ -0,0 +1,173 @@
+/*
+ * omap_hwmod_2xxx_3xxx_interconnect_data.c - common interconnect data, OMAP2/3
+ *
+ * Copyright (C) 2009-2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX handle crossbar/shared link difference for L3?
+ * XXX these should be marked initdata for multi-OMAP kernels
+ */
+#include <asm/sizes.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+
+#include "omap_hwmod_common_data.h"
+
+struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
+ {
+ .pa_start = 0x4809c000,
+ .pa_end = 0x4809c1ff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
+ {
+ .pa_start = 0x480b4000,
+ .pa_end = 0x480b41ff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_i2c1_addr_space[] = {
+ {
+ .pa_start = 0x48070000,
+ .pa_end = 0x48070000 + SZ_128 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_i2c2_addr_space[] = {
+ {
+ .pa_start = 0x48072000,
+ .pa_end = 0x48072000 + SZ_128 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_addrs[] = {
+ {
+ .pa_start = 0x48050000,
+ .pa_end = 0x48050000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_dispc_addrs[] = {
+ {
+ .pa_start = 0x48050400,
+ .pa_end = 0x48050400 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_rfbi_addrs[] = {
+ {
+ .pa_start = 0x48050800,
+ .pa_end = 0x48050800 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dss_venc_addrs[] = {
+ {
+ .pa_start = 0x48050C00,
+ .pa_end = 0x48050C00 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_timer10_addrs[] = {
+ {
+ .pa_start = 0x48086000,
+ .pa_end = 0x48086000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_timer11_addrs[] = {
+ {
+ .pa_start = 0x48088000,
+ .pa_end = 0x48088000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer12_addrs[] = {
+ {
+ .pa_start = 0x4808a000,
+ .pa_end = 0x4808a000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mcspi1_addr_space[] = {
+ {
+ .pa_start = 0x48098000,
+ .pa_end = 0x48098000 + SZ_256 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mcspi2_addr_space[] = {
+ {
+ .pa_start = 0x4809a000,
+ .pa_end = 0x4809a000 + SZ_256 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
+ {
+ .pa_start = 0x480b8000,
+ .pa_end = 0x480b8000 + SZ_256 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_dma_system_addrs[] = {
+ {
+ .pa_start = 0x48056000,
+ .pa_end = 0x48056000 + SZ_4K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mailbox_addrs[] = {
+ {
+ .pa_start = 0x48094000,
+ .pa_end = 0x48094000 + SZ_512 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2_mcbsp1_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x48074000,
+ .pa_end = 0x480740ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
new file mode 100644
index 000000000000..c451729d289a
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -0,0 +1,322 @@
+/*
+ * omap_hwmod_2xxx_3xxx_ipblock_data.c - common IP block data for OMAP2/3
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+#include <plat/dma.h>
+
+#include <mach/irqs.h>
+
+#include "omap_hwmod_common_data.h"
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig omap2_uart_sysc = {
+ .rev_offs = 0x50,
+ .sysc_offs = 0x54,
+ .syss_offs = 0x58,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_uart_class = {
+ .name = "uart",
+ .sysc = &omap2_uart_sysc,
+};
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dss_hwmod_class = {
+ .name = "dss",
+ .sysc = &omap2_dss_sysc,
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dispc_hwmod_class = {
+ .name = "dispc",
+ .sysc = &omap2_dispc_sysc,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_rfbi_hwmod_class = {
+ .name = "rfbi",
+ .sysc = &omap2_rfbi_sysc,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+struct omap_hwmod_class omap2_venc_hwmod_class = {
+ .name = "venc",
+};
+
+
+/* Common DMA request line data */
+struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[] = {
+ { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+ { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_uart2_sdma_reqs[] = {
+ { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+ { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_uart3_sdma_reqs[] = {
+ { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+ { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_i2c1_sdma_reqs[] = {
+ { .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+ { .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_i2c2_sdma_reqs[] = {
+ { .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+ { .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcspi1_sdma_reqs[] = {
+ { .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
+ { .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
+ { .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
+ { .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
+ { .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
+ { .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
+ { .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
+ { .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcspi2_sdma_reqs[] = {
+ { .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
+ { .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
+ { .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
+ { .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp1_sdma_reqs[] = {
+ { .name = "rx", .dma_req = 32 },
+ { .name = "tx", .dma_req = 31 },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp2_sdma_reqs[] = {
+ { .name = "rx", .dma_req = 34 },
+ { .name = "tx", .dma_req = 33 },
+ { .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp3_sdma_reqs[] = {
+ { .name = "rx", .dma_req = 18 },
+ { .name = "tx", .dma_req = 17 },
+ { .dma_req = -1 }
+};
+
+/* Other IP block data */
+
+
+/*
+ * omap_hwmod class data
+ */
+
+struct omap_hwmod_class l3_hwmod_class = {
+ .name = "l3"
+};
+
+struct omap_hwmod_class l4_hwmod_class = {
+ .name = "l4"
+};
+
+struct omap_hwmod_class mpu_hwmod_class = {
+ .name = "mpu"
+};
+
+struct omap_hwmod_class iva_hwmod_class = {
+ .name = "iva"
+};
+
+/* Common MPU IRQ line data */
+
+struct omap_hwmod_irq_info omap2_timer1_mpu_irqs[] = {
+ { .irq = 37, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer2_mpu_irqs[] = {
+ { .irq = 38, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer3_mpu_irqs[] = {
+ { .irq = 39, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer4_mpu_irqs[] = {
+ { .irq = 40, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer5_mpu_irqs[] = {
+ { .irq = 41, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer6_mpu_irqs[] = {
+ { .irq = 42, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer7_mpu_irqs[] = {
+ { .irq = 43, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer8_mpu_irqs[] = {
+ { .irq = 44, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer9_mpu_irqs[] = {
+ { .irq = 45, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer10_mpu_irqs[] = {
+ { .irq = 46, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer11_mpu_irqs[] = {
+ { .irq = 47, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart1_mpu_irqs[] = {
+ { .irq = INT_24XX_UART1_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart2_mpu_irqs[] = {
+ { .irq = INT_24XX_UART2_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[] = {
+ { .irq = INT_24XX_UART3_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_dispc_irqs[] = {
+ { .irq = 25 },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[] = {
+ { .irq = INT_24XX_I2C1_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[] = {
+ { .irq = INT_24XX_I2C2_IRQ, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio1_irqs[] = {
+ { .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio2_irqs[] = {
+ { .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio3_irqs[] = {
+ { .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio4_irqs[] = {
+ { .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_dma_system_irqs[] = {
+ { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+ { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+ { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+ { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[] = {
+ { .irq = 65 },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[] = {
+ { .irq = 66 },
+ { .irq = -1 }
+};
+
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
new file mode 100644
index 000000000000..4f3547c2a49e
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -0,0 +1,130 @@
+/*
+ * omap_hwmod_2xxx_interconnect_data.c - common interconnect data for OMAP2xxx
+ *
+ * Copyright (C) 2009-2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX handle crossbar/shared link difference for L3?
+ * XXX these should be marked initdata for multi-OMAP kernels
+ */
+#include <asm/sizes.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+
+#include "omap_hwmod_common_data.h"
+
+struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[] = {
+ {
+ .pa_start = OMAP2_UART1_BASE,
+ .pa_end = OMAP2_UART1_BASE + SZ_8K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[] = {
+ {
+ .pa_start = OMAP2_UART2_BASE,
+ .pa_end = OMAP2_UART2_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[] = {
+ {
+ .pa_start = OMAP2_UART3_BASE,
+ .pa_end = OMAP2_UART3_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer2_addrs[] = {
+ {
+ .pa_start = 0x4802a000,
+ .pa_end = 0x4802a000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer3_addrs[] = {
+ {
+ .pa_start = 0x48078000,
+ .pa_end = 0x48078000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer4_addrs[] = {
+ {
+ .pa_start = 0x4807a000,
+ .pa_end = 0x4807a000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer5_addrs[] = {
+ {
+ .pa_start = 0x4807c000,
+ .pa_end = 0x4807c000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer6_addrs[] = {
+ {
+ .pa_start = 0x4807e000,
+ .pa_end = 0x4807e000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer7_addrs[] = {
+ {
+ .pa_start = 0x48080000,
+ .pa_end = 0x48080000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer8_addrs[] = {
+ {
+ .pa_start = 0x48082000,
+ .pa_end = 0x48082000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer9_addrs[] = {
+ {
+ .pa_start = 0x48084000,
+ .pa_end = 0x48084000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x48076000,
+ .pa_end = 0x480760ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
new file mode 100644
index 000000000000..177dee20faef
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -0,0 +1,150 @@
+/*
+ * omap_hwmod_2xxx_ipblock_data.c - common IP block data for OMAP2xxx
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+#include <plat/mcspi.h>
+
+#include <mach/irqs.h>
+
+#include "omap_hwmod_common_data.h"
+#include "wd_timer.h"
+
+struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[] = {
+ { .irq = 48, },
+ { .irq = -1 }
+};
+
+struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
+ { .name = "dispc", .dma_req = 5 },
+ { .dma_req = -1 }
+};
+/* OMAP2xxx Timer Common */
+static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_timer_hwmod_class = {
+ .name = "timer",
+ .sysc = &omap2xxx_timer_sysc,
+ .rev = OMAP_TIMER_IP_VERSION_1,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_wd_timer_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class = {
+ .name = "wd_timer",
+ .sysc = &omap2xxx_wd_timer_sysc,
+ .pre_shutdown = &omap2_wd_timer_disable
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+static struct omap_hwmod_class_sysconfig omap2xxx_gpio_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_gpio_hwmod_class = {
+ .name = "gpio",
+ .sysc = &omap2xxx_gpio_sysc,
+ .rev = 0,
+};
+
+/* system dma */
+static struct omap_hwmod_class_sysconfig omap2xxx_dma_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x002c,
+ .syss_offs = 0x0028,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_dma_hwmod_class = {
+ .name = "dma",
+ .sysc = &omap2xxx_dma_sysc,
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_mailbox_sysc = {
+ .rev_offs = 0x000,
+ .sysc_offs = 0x010,
+ .syss_offs = 0x014,
+ .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_mailbox_hwmod_class = {
+ .name = "mailbox",
+ .sysc = &omap2xxx_mailbox_sysc,
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_mcspi_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_mcspi_class = {
+ .name = "mcspi",
+ .sysc = &omap2xxx_mcspi_sysc,
+ .rev = OMAP2_MCSPI_REV,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 909a84de6682..25bf43b5a4ec 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1,7 +1,7 @@
/*
* omap_hwmod_3xxx_data.c - hardware modules present on the OMAP3xxx chips
*
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -103,6 +103,7 @@ static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_per = {
static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
{ .irq = INT_34XX_L3_DBG_IRQ },
{ .irq = INT_34XX_L3_APP_IRQ },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
@@ -111,6 +112,7 @@ static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
.pa_end = 0x6800ffff,
.flags = ADDR_TYPE_RT,
},
+ { }
};
/* MPU -> L3 interface */
@@ -118,7 +120,6 @@ static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
.master = &omap3xxx_mpu_hwmod,
.slave = &omap3xxx_l3_main_hwmod,
.addr = omap3xxx_l3_main_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_l3_main_addrs),
.user = OCP_USER_MPU,
};
@@ -150,8 +151,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
static struct omap_hwmod omap3xxx_l3_main_hwmod = {
.name = "l3_main",
.class = &l3_hwmod_class,
- .mpu_irqs = omap3xxx_l3_main_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_l3_main_irqs),
+ .mpu_irqs = omap3xxx_l3_main_irqs,
.masters = omap3xxx_l3_main_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_l3_main_masters),
.slaves = omap3xxx_l3_main_slaves,
@@ -190,39 +190,21 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
};
/* L4 CORE -> MMC1 interface */
-static struct omap_hwmod_addr_space omap3xxx_mmc1_addr_space[] = {
- {
- .pa_start = 0x4809c000,
- .pa_end = 0x4809c1ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc1 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_mmc1_hwmod,
.clk = "mmchs1_ick",
- .addr = omap3xxx_mmc1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mmc1_addr_space),
+ .addr = omap2430_mmc1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
.flags = OMAP_FIREWALL_L4
};
/* L4 CORE -> MMC2 interface */
-static struct omap_hwmod_addr_space omap3xxx_mmc2_addr_space[] = {
- {
- .pa_start = 0x480b4000,
- .pa_end = 0x480b41ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc2 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_mmc2_hwmod,
.clk = "mmchs2_ick",
- .addr = omap3xxx_mmc2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mmc2_addr_space),
+ .addr = omap2430_mmc2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
.flags = OMAP_FIREWALL_L4
};
@@ -234,6 +216,7 @@ static struct omap_hwmod_addr_space omap3xxx_mmc3_addr_space[] = {
.pa_end = 0x480ad1ff,
.flags = ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
@@ -241,7 +224,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
.slave = &omap3xxx_mmc3_hwmod,
.clk = "mmchs3_ick",
.addr = omap3xxx_mmc3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mmc3_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
.flags = OMAP_FIREWALL_L4
};
@@ -253,6 +235,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
.pa_end = OMAP3_UART1_BASE + SZ_8K - 1,
.flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
@@ -260,7 +243,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
.slave = &omap3xxx_uart1_hwmod,
.clk = "uart1_ick",
.addr = omap3xxx_uart1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_uart1_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -271,6 +253,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
.pa_end = OMAP3_UART2_BASE + SZ_1K - 1,
.flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
@@ -278,7 +261,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
.slave = &omap3xxx_uart2_hwmod,
.clk = "uart2_ick",
.addr = omap3xxx_uart2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_uart2_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -289,6 +271,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
.pa_end = OMAP3_UART3_BASE + SZ_1K - 1,
.flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
@@ -296,7 +279,6 @@ static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
.slave = &omap3xxx_uart3_hwmod,
.clk = "uart3_ick",
.addr = omap3xxx_uart3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_uart3_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -307,6 +289,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart4_addr_space[] = {
.pa_end = OMAP3_UART4_BASE + SZ_1K - 1,
.flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
@@ -314,28 +297,15 @@ static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
.slave = &omap3xxx_uart4_hwmod,
.clk = "uart4_ick",
.addr = omap3xxx_uart4_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_uart4_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* I2C IP block address space length (in bytes) */
-#define OMAP2_I2C_AS_LEN 128
-
/* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_addr_space omap3xxx_i2c1_addr_space[] = {
- {
- .pa_start = 0x48070000,
- .pa_end = 0x48070000 + OMAP2_I2C_AS_LEN - 1,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_i2c1_hwmod,
.clk = "i2c1_ick",
- .addr = omap3xxx_i2c1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_i2c1_addr_space),
+ .addr = omap2_i2c1_addr_space,
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_I2C1_REGION,
@@ -347,20 +317,11 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
};
/* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_addr_space omap3xxx_i2c2_addr_space[] = {
- {
- .pa_start = 0x48072000,
- .pa_end = 0x48072000 + OMAP2_I2C_AS_LEN - 1,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_i2c2_hwmod,
.clk = "i2c2_ick",
- .addr = omap3xxx_i2c2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_i2c2_addr_space),
+ .addr = omap2_i2c2_addr_space,
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_I2C2_REGION,
@@ -375,9 +336,10 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
static struct omap_hwmod_addr_space omap3xxx_i2c3_addr_space[] = {
{
.pa_start = 0x48060000,
- .pa_end = 0x48060000 + OMAP2_I2C_AS_LEN - 1,
+ .pa_end = 0x48060000 + SZ_128 - 1,
.flags = ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
@@ -385,7 +347,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
.slave = &omap3xxx_i2c3_hwmod,
.clk = "i2c3_ick",
.addr = omap3xxx_i2c3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3xxx_i2c3_addr_space),
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_I2C3_REGION,
@@ -403,6 +364,7 @@ static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
.pa_end = OMAP34XX_SR1_BASE + SZ_1K - 1,
.flags = ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
@@ -410,7 +372,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
.slave = &omap34xx_sr1_hwmod,
.clk = "sr_l4_ick",
.addr = omap3_sr1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3_sr1_addr_space),
.user = OCP_USER_MPU,
};
@@ -421,6 +382,7 @@ static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
.pa_end = OMAP34XX_SR2_BASE + SZ_1K - 1,
.flags = ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
@@ -428,7 +390,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
.slave = &omap34xx_sr2_hwmod,
.clk = "sr_l4_ick",
.addr = omap3_sr2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap3_sr2_addr_space),
.user = OCP_USER_MPU,
};
@@ -442,6 +403,7 @@ static struct omap_hwmod_addr_space omap3xxx_usbhsotg_addrs[] = {
.pa_end = OMAP34XX_HSUSB_OTG_BASE + SZ_4K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> usbhsotg */
@@ -450,7 +412,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
.slave = &omap3xxx_usbhsotg_hwmod,
.clk = "l4_ick",
.addr = omap3xxx_usbhsotg_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_usbhsotg_addrs),
.user = OCP_USER_MPU,
};
@@ -468,6 +429,7 @@ static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
.pa_end = AM35XX_IPSS_USBOTGSS_BASE + SZ_4K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> usbhsotg */
@@ -476,7 +438,6 @@ static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
.slave = &am35xx_usbhsotg_hwmod,
.clk = "l4_ick",
.addr = am35xx_usbhsotg_addrs,
- .addr_cnt = ARRAY_SIZE(am35xx_usbhsotg_addrs),
.user = OCP_USER_MPU,
};
@@ -611,9 +572,6 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
/* timer1 */
static struct omap_hwmod omap3xxx_timer1_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer1_mpu_irqs[] = {
- { .irq = 37, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
{
@@ -621,6 +579,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
.pa_end = 0x48318000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> timer1 */
@@ -629,7 +588,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__timer1 = {
.slave = &omap3xxx_timer1_hwmod,
.clk = "gpt1_ick",
.addr = omap3xxx_timer1_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -641,8 +599,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer1_slaves[] = {
/* timer1 hwmod */
static struct omap_hwmod omap3xxx_timer1_hwmod = {
.name = "timer1",
- .mpu_irqs = omap3xxx_timer1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer1_mpu_irqs),
+ .mpu_irqs = omap2_timer1_mpu_irqs,
.main_clk = "gpt1_fck",
.prcm = {
.omap2 = {
@@ -661,9 +618,6 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
/* timer2 */
static struct omap_hwmod omap3xxx_timer2_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer2_mpu_irqs[] = {
- { .irq = 38, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
{
@@ -671,6 +625,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
.pa_end = 0x49032000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer2 */
@@ -679,7 +634,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer2 = {
.slave = &omap3xxx_timer2_hwmod,
.clk = "gpt2_ick",
.addr = omap3xxx_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -691,8 +645,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer2_slaves[] = {
/* timer2 hwmod */
static struct omap_hwmod omap3xxx_timer2_hwmod = {
.name = "timer2",
- .mpu_irqs = omap3xxx_timer2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer2_mpu_irqs),
+ .mpu_irqs = omap2_timer2_mpu_irqs,
.main_clk = "gpt2_fck",
.prcm = {
.omap2 = {
@@ -711,9 +664,6 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
/* timer3 */
static struct omap_hwmod omap3xxx_timer3_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer3_mpu_irqs[] = {
- { .irq = 39, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
{
@@ -721,6 +671,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
.pa_end = 0x49034000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer3 */
@@ -729,7 +680,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer3 = {
.slave = &omap3xxx_timer3_hwmod,
.clk = "gpt3_ick",
.addr = omap3xxx_timer3_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -741,8 +691,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer3_slaves[] = {
/* timer3 hwmod */
static struct omap_hwmod omap3xxx_timer3_hwmod = {
.name = "timer3",
- .mpu_irqs = omap3xxx_timer3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer3_mpu_irqs),
+ .mpu_irqs = omap2_timer3_mpu_irqs,
.main_clk = "gpt3_fck",
.prcm = {
.omap2 = {
@@ -761,9 +710,6 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
/* timer4 */
static struct omap_hwmod omap3xxx_timer4_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer4_mpu_irqs[] = {
- { .irq = 40, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
{
@@ -771,6 +717,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
.pa_end = 0x49036000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer4 */
@@ -779,7 +726,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer4 = {
.slave = &omap3xxx_timer4_hwmod,
.clk = "gpt4_ick",
.addr = omap3xxx_timer4_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -791,8 +737,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer4_slaves[] = {
/* timer4 hwmod */
static struct omap_hwmod omap3xxx_timer4_hwmod = {
.name = "timer4",
- .mpu_irqs = omap3xxx_timer4_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer4_mpu_irqs),
+ .mpu_irqs = omap2_timer4_mpu_irqs,
.main_clk = "gpt4_fck",
.prcm = {
.omap2 = {
@@ -811,9 +756,6 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
/* timer5 */
static struct omap_hwmod omap3xxx_timer5_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer5_mpu_irqs[] = {
- { .irq = 41, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
{
@@ -821,6 +763,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
.pa_end = 0x49038000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer5 */
@@ -829,7 +772,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer5 = {
.slave = &omap3xxx_timer5_hwmod,
.clk = "gpt5_ick",
.addr = omap3xxx_timer5_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer5_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -841,8 +783,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer5_slaves[] = {
/* timer5 hwmod */
static struct omap_hwmod omap3xxx_timer5_hwmod = {
.name = "timer5",
- .mpu_irqs = omap3xxx_timer5_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer5_mpu_irqs),
+ .mpu_irqs = omap2_timer5_mpu_irqs,
.main_clk = "gpt5_fck",
.prcm = {
.omap2 = {
@@ -861,9 +802,6 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
/* timer6 */
static struct omap_hwmod omap3xxx_timer6_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer6_mpu_irqs[] = {
- { .irq = 42, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
{
@@ -871,6 +809,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
.pa_end = 0x4903A000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer6 */
@@ -879,7 +818,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer6 = {
.slave = &omap3xxx_timer6_hwmod,
.clk = "gpt6_ick",
.addr = omap3xxx_timer6_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer6_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -891,8 +829,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer6_slaves[] = {
/* timer6 hwmod */
static struct omap_hwmod omap3xxx_timer6_hwmod = {
.name = "timer6",
- .mpu_irqs = omap3xxx_timer6_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer6_mpu_irqs),
+ .mpu_irqs = omap2_timer6_mpu_irqs,
.main_clk = "gpt6_fck",
.prcm = {
.omap2 = {
@@ -911,9 +848,6 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
/* timer7 */
static struct omap_hwmod omap3xxx_timer7_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer7_mpu_irqs[] = {
- { .irq = 43, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
{
@@ -921,6 +855,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
.pa_end = 0x4903C000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer7 */
@@ -929,7 +864,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer7 = {
.slave = &omap3xxx_timer7_hwmod,
.clk = "gpt7_ick",
.addr = omap3xxx_timer7_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer7_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -941,8 +875,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer7_slaves[] = {
/* timer7 hwmod */
static struct omap_hwmod omap3xxx_timer7_hwmod = {
.name = "timer7",
- .mpu_irqs = omap3xxx_timer7_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer7_mpu_irqs),
+ .mpu_irqs = omap2_timer7_mpu_irqs,
.main_clk = "gpt7_fck",
.prcm = {
.omap2 = {
@@ -961,9 +894,6 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
/* timer8 */
static struct omap_hwmod omap3xxx_timer8_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer8_mpu_irqs[] = {
- { .irq = 44, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
{
@@ -971,6 +901,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
.pa_end = 0x4903E000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer8 */
@@ -979,7 +910,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer8 = {
.slave = &omap3xxx_timer8_hwmod,
.clk = "gpt8_ick",
.addr = omap3xxx_timer8_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer8_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -991,8 +921,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer8_slaves[] = {
/* timer8 hwmod */
static struct omap_hwmod omap3xxx_timer8_hwmod = {
.name = "timer8",
- .mpu_irqs = omap3xxx_timer8_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer8_mpu_irqs),
+ .mpu_irqs = omap2_timer8_mpu_irqs,
.main_clk = "gpt8_fck",
.prcm = {
.omap2 = {
@@ -1011,9 +940,6 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
/* timer9 */
static struct omap_hwmod omap3xxx_timer9_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer9_mpu_irqs[] = {
- { .irq = 45, },
-};
static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
{
@@ -1021,6 +947,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
.pa_end = 0x49040000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer9 */
@@ -1029,7 +956,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer9 = {
.slave = &omap3xxx_timer9_hwmod,
.clk = "gpt9_ick",
.addr = omap3xxx_timer9_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer9_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1041,8 +967,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer9_slaves[] = {
/* timer9 hwmod */
static struct omap_hwmod omap3xxx_timer9_hwmod = {
.name = "timer9",
- .mpu_irqs = omap3xxx_timer9_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer9_mpu_irqs),
+ .mpu_irqs = omap2_timer9_mpu_irqs,
.main_clk = "gpt9_fck",
.prcm = {
.omap2 = {
@@ -1061,25 +986,13 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
/* timer10 */
static struct omap_hwmod omap3xxx_timer10_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer10_mpu_irqs[] = {
- { .irq = 46, },
-};
-
-static struct omap_hwmod_addr_space omap3xxx_timer10_addrs[] = {
- {
- .pa_start = 0x48086000,
- .pa_end = 0x48086000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer10 */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer10 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_timer10_hwmod,
.clk = "gpt10_ick",
- .addr = omap3xxx_timer10_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer10_addrs),
+ .addr = omap2_timer10_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1091,8 +1004,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer10_slaves[] = {
/* timer10 hwmod */
static struct omap_hwmod omap3xxx_timer10_hwmod = {
.name = "timer10",
- .mpu_irqs = omap3xxx_timer10_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer10_mpu_irqs),
+ .mpu_irqs = omap2_timer10_mpu_irqs,
.main_clk = "gpt10_fck",
.prcm = {
.omap2 = {
@@ -1111,25 +1023,13 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
/* timer11 */
static struct omap_hwmod omap3xxx_timer11_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer11_mpu_irqs[] = {
- { .irq = 47, },
-};
-
-static struct omap_hwmod_addr_space omap3xxx_timer11_addrs[] = {
- {
- .pa_start = 0x48088000,
- .pa_end = 0x48088000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
-};
/* l4_core -> timer11 */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer11 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_timer11_hwmod,
.clk = "gpt11_ick",
- .addr = omap3xxx_timer11_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer11_addrs),
+ .addr = omap2_timer11_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1141,8 +1041,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer11_slaves[] = {
/* timer11 hwmod */
static struct omap_hwmod omap3xxx_timer11_hwmod = {
.name = "timer11",
- .mpu_irqs = omap3xxx_timer11_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer11_mpu_irqs),
+ .mpu_irqs = omap2_timer11_mpu_irqs,
.main_clk = "gpt11_fck",
.prcm = {
.omap2 = {
@@ -1163,6 +1062,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
static struct omap_hwmod omap3xxx_timer12_hwmod;
static struct omap_hwmod_irq_info omap3xxx_timer12_mpu_irqs[] = {
{ .irq = 95, },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
@@ -1171,6 +1071,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
.pa_end = 0x48304000 + SZ_1K - 1,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> timer12 */
@@ -1179,7 +1080,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer12 = {
.slave = &omap3xxx_timer12_hwmod,
.clk = "gpt12_ick",
.addr = omap3xxx_timer12_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_timer12_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1192,7 +1092,6 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer12_slaves[] = {
static struct omap_hwmod omap3xxx_timer12_hwmod = {
.name = "timer12",
.mpu_irqs = omap3xxx_timer12_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_timer12_mpu_irqs),
.main_clk = "gpt12_fck",
.prcm = {
.omap2 = {
@@ -1216,6 +1115,7 @@ static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
.pa_end = 0x4831407f,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
@@ -1223,7 +1123,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
.slave = &omap3xxx_wd_timer2_hwmod,
.clk = "wdt2_ick",
.addr = omap3xxx_wd_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_wd_timer2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1291,45 +1190,16 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
.flags = HWMOD_SWSUP_SIDLE,
};
-/* UART common */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
- .rev_offs = 0x50,
- .sysc_offs = 0x54,
- .syss_offs = 0x58,
- .sysc_flags = (SYSC_HAS_SIDLEMODE |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
- .name = "uart",
- .sysc = &uart_sysc,
-};
-
/* UART1 */
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
- { .irq = INT_24XX_UART1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
-};
-
static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
&omap3_l4_core__uart1,
};
static struct omap_hwmod omap3xxx_uart1_hwmod = {
.name = "uart1",
- .mpu_irqs = uart1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs),
- .sdma_reqs = uart1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart1_sdma_reqs),
+ .mpu_irqs = omap2_uart1_mpu_irqs,
+ .sdma_reqs = omap2_uart1_sdma_reqs,
.main_clk = "uart1_fck",
.prcm = {
.omap2 = {
@@ -1342,31 +1212,20 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
},
.slaves = omap3xxx_uart1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart1_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* UART2 */
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
- { .irq = INT_24XX_UART2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
-};
-
static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
&omap3_l4_core__uart2,
};
static struct omap_hwmod omap3xxx_uart2_hwmod = {
.name = "uart2",
- .mpu_irqs = uart2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs),
- .sdma_reqs = uart2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart2_sdma_reqs),
+ .mpu_irqs = omap2_uart2_mpu_irqs,
+ .sdma_reqs = omap2_uart2_sdma_reqs,
.main_clk = "uart2_fck",
.prcm = {
.omap2 = {
@@ -1379,31 +1238,20 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
},
.slaves = omap3xxx_uart2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart2_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* UART3 */
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
- { .irq = INT_24XX_UART3_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
- { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
-};
-
static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
&omap3_l4_per__uart3,
};
static struct omap_hwmod omap3xxx_uart3_hwmod = {
.name = "uart3",
- .mpu_irqs = uart3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs),
- .sdma_reqs = uart3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart3_sdma_reqs),
+ .mpu_irqs = omap2_uart3_mpu_irqs,
+ .sdma_reqs = omap2_uart3_sdma_reqs,
.main_clk = "uart3_fck",
.prcm = {
.omap2 = {
@@ -1416,7 +1264,7 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
},
.slaves = omap3xxx_uart3_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart3_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@@ -1424,11 +1272,13 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
{ .irq = INT_36XX_UART4_IRQ, },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
{ .name = "rx", .dma_req = OMAP36XX_DMA_UART4_RX, },
{ .name = "tx", .dma_req = OMAP36XX_DMA_UART4_TX, },
+ { .dma_req = -1 }
};
static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
@@ -1438,9 +1288,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
static struct omap_hwmod omap3xxx_uart4_hwmod = {
.name = "uart4",
.mpu_irqs = uart4_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(uart4_mpu_irqs),
.sdma_reqs = uart4_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(uart4_sdma_reqs),
.main_clk = "uart4_fck",
.prcm = {
.omap2 = {
@@ -1453,36 +1301,21 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = {
},
.slaves = omap3xxx_uart4_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart4_slaves),
- .class = &uart_class,
+ .class = &omap2_uart_class,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
};
static struct omap_hwmod_class i2c_class = {
- .name = "i2c",
- .sysc = &i2c_sysc,
-};
-
-/*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap3xxx_dss_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap3xxx_dss_hwmod_class = {
- .name = "dss",
- .sysc = &omap3xxx_dss_sysc,
+ .name = "i2c",
+ .sysc = &i2c_sysc,
+ .rev = OMAP_I2C_IP_VERSION_1,
+ .reset = &omap_i2c_reset,
};
static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
{ .name = "dispc", .dma_req = 5 },
{ .name = "dsi1", .dma_req = 74 },
+ { .dma_req = -1 }
};
/* dss */
@@ -1491,21 +1324,12 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_masters[] = {
&omap3xxx_dss__l3,
};
-static struct omap_hwmod_addr_space omap3xxx_dss_addrs[] = {
- {
- .pa_start = 0x48050000,
- .pa_end = 0x480503FF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss */
static struct omap_hwmod_ocp_if omap3430es1_l4_core__dss = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3430es1_dss_core_hwmod,
.clk = "dss_ick",
- .addr = omap3xxx_dss_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_dss_addrs),
+ .addr = omap2_dss_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION,
@@ -1520,8 +1344,7 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_dss_core_hwmod,
.clk = "dss_ick",
- .addr = omap3xxx_dss_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_dss_addrs),
+ .addr = omap2_dss_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_DSS_CORE_REGION,
@@ -1549,11 +1372,9 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
static struct omap_hwmod omap3430es1_dss_core_hwmod = {
.name = "dss_core",
- .class = &omap3xxx_dss_hwmod_class,
+ .class = &omap2_dss_hwmod_class,
.main_clk = "dss1_alwon_fck", /* instead of dss_fck */
.sdma_reqs = omap3xxx_dss_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs),
-
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -1575,11 +1396,9 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
static struct omap_hwmod omap3xxx_dss_core_hwmod = {
.name = "dss_core",
- .class = &omap3xxx_dss_hwmod_class,
+ .class = &omap2_dss_hwmod_class,
.main_clk = "dss1_alwon_fck", /* instead of dss_fck */
.sdma_reqs = omap3xxx_dss_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs),
-
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -1600,47 +1419,12 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1),
};
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap3xxx_dispc_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
- SYSC_HAS_MIDLEMODE | SYSC_HAS_ENAWAKEUP |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = {
- .name = "dispc",
- .sysc = &omap3xxx_dispc_sysc,
-};
-
-static struct omap_hwmod_irq_info omap3xxx_dispc_irqs[] = {
- { .irq = 25 },
-};
-
-static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = {
- {
- .pa_start = 0x48050400,
- .pa_end = 0x480507FF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_dispc */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_dss_dispc_hwmod,
.clk = "dss_ick",
- .addr = omap3xxx_dss_dispc_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_addrs),
+ .addr = omap2_dss_dispc_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_DSS_DISPC_REGION,
@@ -1658,9 +1442,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
.name = "dss_dispc",
- .class = &omap3xxx_dispc_hwmod_class,
- .mpu_irqs = omap3xxx_dispc_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dispc_irqs),
+ .class = &omap2_dispc_hwmod_class,
+ .mpu_irqs = omap2_dispc_irqs,
.main_clk = "dss1_alwon_fck",
.prcm = {
.omap2 = {
@@ -1688,6 +1471,7 @@ static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
{ .irq = 25 },
+ { .irq = -1 }
};
/* dss_dsi1 */
@@ -1697,6 +1481,7 @@ static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
.pa_end = 0x4804FFFF,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> dss_dsi1 */
@@ -1704,7 +1489,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_dss_dsi1_hwmod,
.addr = omap3xxx_dss_dsi1_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_addrs),
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_DSS_DSI_REGION,
@@ -1724,7 +1508,6 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
.name = "dss_dsi1",
.class = &omap3xxx_dsi_hwmod_class,
.mpu_irqs = omap3xxx_dsi1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dsi1_irqs),
.main_clk = "dss1_alwon_fck",
.prcm = {
.omap2 = {
@@ -1741,41 +1524,12 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap3xxx_rfbi_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap3xxx_rfbi_hwmod_class = {
- .name = "rfbi",
- .sysc = &omap3xxx_rfbi_sysc,
-};
-
-static struct omap_hwmod_addr_space omap3xxx_dss_rfbi_addrs[] = {
- {
- .pa_start = 0x48050800,
- .pa_end = 0x48050BFF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_rfbi */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_dss_rfbi_hwmod,
.clk = "dss_ick",
- .addr = omap3xxx_dss_rfbi_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_addrs),
+ .addr = omap2_dss_rfbi_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_DSS_RFBI_REGION,
@@ -1793,7 +1547,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
.name = "dss_rfbi",
- .class = &omap3xxx_rfbi_hwmod_class,
+ .class = &omap2_rfbi_hwmod_class,
.main_clk = "dss1_alwon_fck",
.prcm = {
.omap2 = {
@@ -1810,31 +1564,12 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/*
- * 'venc' class
- * video encoder
- */
-
-static struct omap_hwmod_class omap3xxx_venc_hwmod_class = {
- .name = "venc",
-};
-
-/* dss_venc */
-static struct omap_hwmod_addr_space omap3xxx_dss_venc_addrs[] = {
- {
- .pa_start = 0x48050C00,
- .pa_end = 0x48050FFF,
- .flags = ADDR_TYPE_RT
- },
-};
-
/* l4_core -> dss_venc */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_dss_venc_hwmod,
.clk = "dss_tv_fck",
- .addr = omap3xxx_dss_venc_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_dss_venc_addrs),
+ .addr = omap2_dss_venc_addrs,
.fw = {
.omap2 = {
.l4_fw_region = OMAP3_L4_CORE_FW_DSS_VENC_REGION,
@@ -1853,7 +1588,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
.name = "dss_venc",
- .class = &omap3xxx_venc_hwmod_class,
+ .class = &omap2_venc_hwmod_class,
.main_clk = "dss1_alwon_fck",
.prcm = {
.omap2 = {
@@ -1874,15 +1609,9 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
static struct omap_i2c_dev_attr i2c1_dev_attr = {
.fifo_depth = 8, /* bytes */
-};
-
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
- { .irq = INT_24XX_I2C1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
- { .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+ .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+ OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+ OMAP_I2C_FLAG_BUS_SHIFT_2,
};
static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
@@ -1891,10 +1620,9 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
static struct omap_hwmod omap3xxx_i2c1_hwmod = {
.name = "i2c1",
- .mpu_irqs = i2c1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(i2c1_mpu_irqs),
- .sdma_reqs = i2c1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(i2c1_sdma_reqs),
+ .flags = HWMOD_16BIT_REG,
+ .mpu_irqs = omap2_i2c1_mpu_irqs,
+ .sdma_reqs = omap2_i2c1_sdma_reqs,
.main_clk = "i2c1_fck",
.prcm = {
.omap2 = {
@@ -1916,15 +1644,9 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
static struct omap_i2c_dev_attr i2c2_dev_attr = {
.fifo_depth = 8, /* bytes */
-};
-
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
- { .irq = INT_24XX_I2C2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
- { .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
- { .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+ .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+ OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+ OMAP_I2C_FLAG_BUS_SHIFT_2,
};
static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
@@ -1933,10 +1655,9 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
static struct omap_hwmod omap3xxx_i2c2_hwmod = {
.name = "i2c2",
- .mpu_irqs = i2c2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(i2c2_mpu_irqs),
- .sdma_reqs = i2c2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(i2c2_sdma_reqs),
+ .flags = HWMOD_16BIT_REG,
+ .mpu_irqs = omap2_i2c2_mpu_irqs,
+ .sdma_reqs = omap2_i2c2_sdma_reqs,
.main_clk = "i2c2_fck",
.prcm = {
.omap2 = {
@@ -1958,15 +1679,20 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
static struct omap_i2c_dev_attr i2c3_dev_attr = {
.fifo_depth = 64, /* bytes */
+ .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+ OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+ OMAP_I2C_FLAG_BUS_SHIFT_2,
};
static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
{ .irq = INT_34XX_I2C3_IRQ, },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
{ .name = "tx", .dma_req = OMAP34XX_DMA_I2C3_TX },
{ .name = "rx", .dma_req = OMAP34XX_DMA_I2C3_RX },
+ { .dma_req = -1 }
};
static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
@@ -1975,10 +1701,9 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
static struct omap_hwmod omap3xxx_i2c3_hwmod = {
.name = "i2c3",
+ .flags = HWMOD_16BIT_REG,
.mpu_irqs = i2c3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(i2c3_mpu_irqs),
.sdma_reqs = i2c3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(i2c3_sdma_reqs),
.main_clk = "i2c3_fck",
.prcm = {
.omap2 = {
@@ -2003,13 +1728,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
.pa_end = 0x483101ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
.master = &omap3xxx_l4_wkup_hwmod,
.slave = &omap3xxx_gpio1_hwmod,
.addr = omap3xxx_gpio1_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_gpio1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2020,13 +1745,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
.pa_end = 0x490501ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
.master = &omap3xxx_l4_per_hwmod,
.slave = &omap3xxx_gpio2_hwmod,
.addr = omap3xxx_gpio2_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_gpio2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2037,13 +1762,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
.pa_end = 0x490521ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
.master = &omap3xxx_l4_per_hwmod,
.slave = &omap3xxx_gpio3_hwmod,
.addr = omap3xxx_gpio3_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_gpio3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2054,13 +1779,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
.pa_end = 0x490541ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
.master = &omap3xxx_l4_per_hwmod,
.slave = &omap3xxx_gpio4_hwmod,
.addr = omap3xxx_gpio4_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_gpio4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2071,13 +1796,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
.pa_end = 0x490561ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
.master = &omap3xxx_l4_per_hwmod,
.slave = &omap3xxx_gpio5_hwmod,
.addr = omap3xxx_gpio5_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_gpio5_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2088,13 +1813,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
.pa_end = 0x490581ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
.master = &omap3xxx_l4_per_hwmod,
.slave = &omap3xxx_gpio6_hwmod,
.addr = omap3xxx_gpio6_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_gpio6_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2127,10 +1852,6 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
};
/* gpio1 */
-static struct omap_hwmod_irq_info omap3xxx_gpio1_irqs[] = {
- { .irq = 29 }, /* INT_34XX_GPIO_BANK1 */
-};
-
static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio1_dbck", },
};
@@ -2142,8 +1863,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
static struct omap_hwmod omap3xxx_gpio1_hwmod = {
.name = "gpio1",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap3xxx_gpio1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_gpio1_irqs),
+ .mpu_irqs = omap2_gpio1_irqs,
.main_clk = "gpio1_ick",
.opt_clks = gpio1_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks),
@@ -2164,10 +1884,6 @@ static struct omap_hwmod omap3xxx_gpio1_hwmod = {
};
/* gpio2 */
-static struct omap_hwmod_irq_info omap3xxx_gpio2_irqs[] = {
- { .irq = 30 }, /* INT_34XX_GPIO_BANK2 */
-};
-
static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio2_dbck", },
};
@@ -2179,8 +1895,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
static struct omap_hwmod omap3xxx_gpio2_hwmod = {
.name = "gpio2",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap3xxx_gpio2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_gpio2_irqs),
+ .mpu_irqs = omap2_gpio2_irqs,
.main_clk = "gpio2_ick",
.opt_clks = gpio2_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks),
@@ -2201,10 +1916,6 @@ static struct omap_hwmod omap3xxx_gpio2_hwmod = {
};
/* gpio3 */
-static struct omap_hwmod_irq_info omap3xxx_gpio3_irqs[] = {
- { .irq = 31 }, /* INT_34XX_GPIO_BANK3 */
-};
-
static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio3_dbck", },
};
@@ -2216,8 +1927,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
static struct omap_hwmod omap3xxx_gpio3_hwmod = {
.name = "gpio3",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap3xxx_gpio3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_gpio3_irqs),
+ .mpu_irqs = omap2_gpio3_irqs,
.main_clk = "gpio3_ick",
.opt_clks = gpio3_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio3_opt_clks),
@@ -2238,10 +1948,6 @@ static struct omap_hwmod omap3xxx_gpio3_hwmod = {
};
/* gpio4 */
-static struct omap_hwmod_irq_info omap3xxx_gpio4_irqs[] = {
- { .irq = 32 }, /* INT_34XX_GPIO_BANK4 */
-};
-
static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio4_dbck", },
};
@@ -2253,8 +1959,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
static struct omap_hwmod omap3xxx_gpio4_hwmod = {
.name = "gpio4",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap3xxx_gpio4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_gpio4_irqs),
+ .mpu_irqs = omap2_gpio4_irqs,
.main_clk = "gpio4_ick",
.opt_clks = gpio4_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio4_opt_clks),
@@ -2277,6 +1982,7 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod = {
/* gpio5 */
static struct omap_hwmod_irq_info omap3xxx_gpio5_irqs[] = {
{ .irq = 33 }, /* INT_34XX_GPIO_BANK5 */
+ { .irq = -1 }
};
static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
@@ -2291,7 +1997,6 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
.name = "gpio5",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap3xxx_gpio5_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_gpio5_irqs),
.main_clk = "gpio5_ick",
.opt_clks = gpio5_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio5_opt_clks),
@@ -2314,6 +2019,7 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
/* gpio6 */
static struct omap_hwmod_irq_info omap3xxx_gpio6_irqs[] = {
{ .irq = 34 }, /* INT_34XX_GPIO_BANK6 */
+ { .irq = -1 }
};
static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
@@ -2328,7 +2034,6 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {
.name = "gpio6",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap3xxx_gpio6_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_gpio6_irqs),
.main_clk = "gpio6_ick",
.opt_clks = gpio6_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio6_opt_clks),
@@ -2382,19 +2087,13 @@ static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
};
/* dma_system */
-static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
- { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
- { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
- { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
- { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
-};
-
static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
{
.pa_start = 0x48056000,
.pa_end = 0x48056fff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* dma_system master ports */
@@ -2408,7 +2107,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
.slave = &omap3xxx_dma_system_hwmod,
.clk = "core_l4_ick",
.addr = omap3xxx_dma_system_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_dma_system_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2420,8 +2118,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
static struct omap_hwmod omap3xxx_dma_system_hwmod = {
.name = "dma",
.class = &omap3xxx_dma_hwmod_class,
- .mpu_irqs = omap3xxx_dma_system_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dma_system_irqs),
+ .mpu_irqs = omap2_dma_system_irqs,
.main_clk = "core_l3_ick",
.prcm = {
.omap2 = {
@@ -2466,11 +2163,7 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
{ .name = "irq", .irq = 16 },
{ .name = "tx", .irq = 59 },
{ .name = "rx", .irq = 60 },
-};
-
-static struct omap_hwmod_dma_info omap3xxx_mcbsp1_sdma_chs[] = {
- { .name = "rx", .dma_req = 32 },
- { .name = "tx", .dma_req = 31 },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
@@ -2480,6 +2173,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
.pa_end = 0x480740ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> mcbsp1 */
@@ -2488,7 +2182,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp1 = {
.slave = &omap3xxx_mcbsp1_hwmod,
.clk = "mcbsp1_ick",
.addr = omap3xxx_mcbsp1_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mcbsp1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2501,9 +2194,7 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
.name = "mcbsp1",
.class = &omap3xxx_mcbsp_hwmod_class,
.mpu_irqs = omap3xxx_mcbsp1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp1_irqs),
- .sdma_reqs = omap3xxx_mcbsp1_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp1_sdma_chs),
+ .sdma_reqs = omap2_mcbsp1_sdma_reqs,
.main_clk = "mcbsp1_fck",
.prcm = {
.omap2 = {
@@ -2524,11 +2215,7 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp2_irqs[] = {
{ .name = "irq", .irq = 17 },
{ .name = "tx", .irq = 62 },
{ .name = "rx", .irq = 63 },
-};
-
-static struct omap_hwmod_dma_info omap3xxx_mcbsp2_sdma_chs[] = {
- { .name = "rx", .dma_req = 34 },
- { .name = "tx", .dma_req = 33 },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
@@ -2538,6 +2225,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
.pa_end = 0x490220ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcbsp2 */
@@ -2546,7 +2234,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2 = {
.slave = &omap3xxx_mcbsp2_hwmod,
.clk = "mcbsp2_ick",
.addr = omap3xxx_mcbsp2_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2563,9 +2250,7 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
.name = "mcbsp2",
.class = &omap3xxx_mcbsp_hwmod_class,
.mpu_irqs = omap3xxx_mcbsp2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_irqs),
- .sdma_reqs = omap3xxx_mcbsp2_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_sdma_chs),
+ .sdma_reqs = omap2_mcbsp2_sdma_reqs,
.main_clk = "mcbsp2_fck",
.prcm = {
.omap2 = {
@@ -2587,11 +2272,7 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp3_irqs[] = {
{ .name = "irq", .irq = 22 },
{ .name = "tx", .irq = 89 },
{ .name = "rx", .irq = 90 },
-};
-
-static struct omap_hwmod_dma_info omap3xxx_mcbsp3_sdma_chs[] = {
- { .name = "rx", .dma_req = 18 },
- { .name = "tx", .dma_req = 17 },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
@@ -2601,6 +2282,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
.pa_end = 0x490240ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcbsp3 */
@@ -2609,7 +2291,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3 = {
.slave = &omap3xxx_mcbsp3_hwmod,
.clk = "mcbsp3_ick",
.addr = omap3xxx_mcbsp3_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2626,9 +2307,7 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
.name = "mcbsp3",
.class = &omap3xxx_mcbsp_hwmod_class,
.mpu_irqs = omap3xxx_mcbsp3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_irqs),
- .sdma_reqs = omap3xxx_mcbsp3_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_sdma_chs),
+ .sdma_reqs = omap2_mcbsp3_sdma_reqs,
.main_clk = "mcbsp3_fck",
.prcm = {
.omap2 = {
@@ -2650,11 +2329,13 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp4_irqs[] = {
{ .name = "irq", .irq = 23 },
{ .name = "tx", .irq = 54 },
{ .name = "rx", .irq = 55 },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap3xxx_mcbsp4_sdma_chs[] = {
{ .name = "rx", .dma_req = 20 },
{ .name = "tx", .dma_req = 19 },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
@@ -2664,6 +2345,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
.pa_end = 0x490260ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcbsp4 */
@@ -2672,7 +2354,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp4 = {
.slave = &omap3xxx_mcbsp4_hwmod,
.clk = "mcbsp4_ick",
.addr = omap3xxx_mcbsp4_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mcbsp4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2685,9 +2366,7 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
.name = "mcbsp4",
.class = &omap3xxx_mcbsp_hwmod_class,
.mpu_irqs = omap3xxx_mcbsp4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp4_irqs),
.sdma_reqs = omap3xxx_mcbsp4_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp4_sdma_chs),
.main_clk = "mcbsp4_fck",
.prcm = {
.omap2 = {
@@ -2708,11 +2387,13 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp5_irqs[] = {
{ .name = "irq", .irq = 27 },
{ .name = "tx", .irq = 81 },
{ .name = "rx", .irq = 82 },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap3xxx_mcbsp5_sdma_chs[] = {
{ .name = "rx", .dma_req = 22 },
{ .name = "tx", .dma_req = 21 },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
@@ -2722,6 +2403,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
.pa_end = 0x480960ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_core -> mcbsp5 */
@@ -2730,7 +2412,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp5 = {
.slave = &omap3xxx_mcbsp5_hwmod,
.clk = "mcbsp5_ick",
.addr = omap3xxx_mcbsp5_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mcbsp5_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2743,9 +2424,7 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
.name = "mcbsp5",
.class = &omap3xxx_mcbsp_hwmod_class,
.mpu_irqs = omap3xxx_mcbsp5_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp5_irqs),
.sdma_reqs = omap3xxx_mcbsp5_sdma_chs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp5_sdma_chs),
.main_clk = "mcbsp5_fck",
.prcm = {
.omap2 = {
@@ -2776,6 +2455,7 @@ static struct omap_hwmod_class omap3xxx_mcbsp_sidetone_hwmod_class = {
/* mcbsp2_sidetone */
static struct omap_hwmod_irq_info omap3xxx_mcbsp2_sidetone_irqs[] = {
{ .name = "irq", .irq = 4 },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
@@ -2785,6 +2465,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
.pa_end = 0x490280ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcbsp2_sidetone */
@@ -2793,7 +2474,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2_sidetone = {
.slave = &omap3xxx_mcbsp2_sidetone_hwmod,
.clk = "mcbsp2_ick",
.addr = omap3xxx_mcbsp2_sidetone_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_addrs),
.user = OCP_USER_MPU,
};
@@ -2806,7 +2486,6 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
.name = "mcbsp2_sidetone",
.class = &omap3xxx_mcbsp_sidetone_hwmod_class,
.mpu_irqs = omap3xxx_mcbsp2_sidetone_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_irqs),
.main_clk = "mcbsp2_fck",
.prcm = {
.omap2 = {
@@ -2825,6 +2504,7 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
/* mcbsp3_sidetone */
static struct omap_hwmod_irq_info omap3xxx_mcbsp3_sidetone_irqs[] = {
{ .name = "irq", .irq = 5 },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
@@ -2834,6 +2514,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
.pa_end = 0x4902A0ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcbsp3_sidetone */
@@ -2842,7 +2523,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3_sidetone = {
.slave = &omap3xxx_mcbsp3_sidetone_hwmod,
.clk = "mcbsp3_ick",
.addr = omap3xxx_mcbsp3_sidetone_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_addrs),
.user = OCP_USER_MPU,
};
@@ -2855,7 +2535,6 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
.name = "mcbsp3_sidetone",
.class = &omap3xxx_mcbsp_sidetone_hwmod_class,
.mpu_irqs = omap3xxx_mcbsp3_sidetone_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_irqs),
.main_clk = "mcbsp3_fck",
.prcm = {
.omap2 = {
@@ -3025,6 +2704,7 @@ static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = {
static struct omap_hwmod omap3xxx_mailbox_hwmod;
static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
{ .irq = 26 },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
@@ -3033,6 +2713,7 @@ static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
.pa_end = 0x480941ff,
.flags = ADDR_TYPE_RT,
},
+ { }
};
/* l4_core -> mailbox */
@@ -3040,7 +2721,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mailbox = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap3xxx_mailbox_hwmod,
.addr = omap3xxx_mailbox_addrs,
- .addr_cnt = ARRAY_SIZE(omap3xxx_mailbox_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3053,7 +2733,6 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
.name = "mailbox",
.class = &omap3xxx_mailbox_hwmod_class,
.mpu_irqs = omap3xxx_mailbox_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_mailbox_irqs),
.main_clk = "mailboxes_ick",
.prcm = {
.omap2 = {
@@ -3070,56 +2749,29 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
};
/* l4 core -> mcspi1 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi1_addr_space[] = {
- {
- .pa_start = 0x48098000,
- .pa_end = 0x480980ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi1 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap34xx_mcspi1,
.clk = "mcspi1_ick",
- .addr = omap34xx_mcspi1_addr_space,
- .addr_cnt = ARRAY_SIZE(omap34xx_mcspi1_addr_space),
+ .addr = omap2_mcspi1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l4 core -> mcspi2 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi2_addr_space[] = {
- {
- .pa_start = 0x4809a000,
- .pa_end = 0x4809a0ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi2 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap34xx_mcspi2,
.clk = "mcspi2_ick",
- .addr = omap34xx_mcspi2_addr_space,
- .addr_cnt = ARRAY_SIZE(omap34xx_mcspi2_addr_space),
+ .addr = omap2_mcspi2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l4 core -> mcspi3 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi3_addr_space[] = {
- {
- .pa_start = 0x480b8000,
- .pa_end = 0x480b80ff,
- .flags = ADDR_TYPE_RT,
- },
-};
-
static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi3 = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &omap34xx_mcspi3,
.clk = "mcspi3_ick",
- .addr = omap34xx_mcspi3_addr_space,
- .addr_cnt = ARRAY_SIZE(omap34xx_mcspi3_addr_space),
+ .addr = omap2430_mcspi3_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3130,6 +2782,7 @@ static struct omap_hwmod_addr_space omap34xx_mcspi4_addr_space[] = {
.pa_end = 0x480ba0ff,
.flags = ADDR_TYPE_RT,
},
+ { }
};
static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
@@ -3137,7 +2790,6 @@ static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
.slave = &omap34xx_mcspi4,
.clk = "mcspi4_ick",
.addr = omap34xx_mcspi4_addr_space,
- .addr_cnt = ARRAY_SIZE(omap34xx_mcspi4_addr_space),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3165,21 +2817,6 @@ static struct omap_hwmod_class omap34xx_mcspi_class = {
};
/* mcspi1 */
-static struct omap_hwmod_irq_info omap34xx_mcspi1_mpu_irqs[] = {
- { .name = "irq", .irq = 65 },
-};
-
-static struct omap_hwmod_dma_info omap34xx_mcspi1_sdma_reqs[] = {
- { .name = "tx0", .dma_req = 35 },
- { .name = "rx0", .dma_req = 36 },
- { .name = "tx1", .dma_req = 37 },
- { .name = "rx1", .dma_req = 38 },
- { .name = "tx2", .dma_req = 39 },
- { .name = "rx2", .dma_req = 40 },
- { .name = "tx3", .dma_req = 41 },
- { .name = "rx3", .dma_req = 42 },
-};
-
static struct omap_hwmod_ocp_if *omap34xx_mcspi1_slaves[] = {
&omap34xx_l4_core__mcspi1,
};
@@ -3190,10 +2827,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
static struct omap_hwmod omap34xx_mcspi1 = {
.name = "mcspi1",
- .mpu_irqs = omap34xx_mcspi1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_mcspi1_mpu_irqs),
- .sdma_reqs = omap34xx_mcspi1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap34xx_mcspi1_sdma_reqs),
+ .mpu_irqs = omap2_mcspi1_mpu_irqs,
+ .sdma_reqs = omap2_mcspi1_sdma_reqs,
.main_clk = "mcspi1_fck",
.prcm = {
.omap2 = {
@@ -3212,17 +2847,6 @@ static struct omap_hwmod omap34xx_mcspi1 = {
};
/* mcspi2 */
-static struct omap_hwmod_irq_info omap34xx_mcspi2_mpu_irqs[] = {
- { .name = "irq", .irq = 66 },
-};
-
-static struct omap_hwmod_dma_info omap34xx_mcspi2_sdma_reqs[] = {
- { .name = "tx0", .dma_req = 43 },
- { .name = "rx0", .dma_req = 44 },
- { .name = "tx1", .dma_req = 45 },
- { .name = "rx1", .dma_req = 46 },
-};
-
static struct omap_hwmod_ocp_if *omap34xx_mcspi2_slaves[] = {
&omap34xx_l4_core__mcspi2,
};
@@ -3233,10 +2857,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
static struct omap_hwmod omap34xx_mcspi2 = {
.name = "mcspi2",
- .mpu_irqs = omap34xx_mcspi2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_mcspi2_mpu_irqs),
- .sdma_reqs = omap34xx_mcspi2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap34xx_mcspi2_sdma_reqs),
+ .mpu_irqs = omap2_mcspi2_mpu_irqs,
+ .sdma_reqs = omap2_mcspi2_sdma_reqs,
.main_clk = "mcspi2_fck",
.prcm = {
.omap2 = {
@@ -3257,6 +2879,7 @@ static struct omap_hwmod omap34xx_mcspi2 = {
/* mcspi3 */
static struct omap_hwmod_irq_info omap34xx_mcspi3_mpu_irqs[] = {
{ .name = "irq", .irq = 91 }, /* 91 */
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
@@ -3264,6 +2887,7 @@ static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
{ .name = "rx0", .dma_req = 16 },
{ .name = "tx1", .dma_req = 23 },
{ .name = "rx1", .dma_req = 24 },
+ { .dma_req = -1 }
};
static struct omap_hwmod_ocp_if *omap34xx_mcspi3_slaves[] = {
@@ -3277,9 +2901,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
static struct omap_hwmod omap34xx_mcspi3 = {
.name = "mcspi3",
.mpu_irqs = omap34xx_mcspi3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_mcspi3_mpu_irqs),
.sdma_reqs = omap34xx_mcspi3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap34xx_mcspi3_sdma_reqs),
.main_clk = "mcspi3_fck",
.prcm = {
.omap2 = {
@@ -3300,11 +2922,13 @@ static struct omap_hwmod omap34xx_mcspi3 = {
/* SPI4 */
static struct omap_hwmod_irq_info omap34xx_mcspi4_mpu_irqs[] = {
{ .name = "irq", .irq = INT_34XX_SPI4_IRQ }, /* 48 */
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap34xx_mcspi4_sdma_reqs[] = {
{ .name = "tx0", .dma_req = 70 }, /* DMA_SPI4_TX0 */
{ .name = "rx0", .dma_req = 71 }, /* DMA_SPI4_RX0 */
+ { .dma_req = -1 }
};
static struct omap_hwmod_ocp_if *omap34xx_mcspi4_slaves[] = {
@@ -3318,9 +2942,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
static struct omap_hwmod omap34xx_mcspi4 = {
.name = "mcspi4",
.mpu_irqs = omap34xx_mcspi4_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_mcspi4_mpu_irqs),
.sdma_reqs = omap34xx_mcspi4_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap34xx_mcspi4_sdma_reqs),
.main_clk = "mcspi4_fck",
.prcm = {
.omap2 = {
@@ -3362,12 +2984,12 @@ static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
{ .name = "mc", .irq = 92 },
{ .name = "dma", .irq = 93 },
+ { .irq = -1 }
};
static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
.name = "usb_otg_hs",
.mpu_irqs = omap3xxx_usbhsotg_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_usbhsotg_mpu_irqs),
.main_clk = "hsotgusb_ick",
.prcm = {
.omap2 = {
@@ -3399,6 +3021,7 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
{ .name = "mc", .irq = 71 },
+ { .irq = -1 }
};
static struct omap_hwmod_class am35xx_usbotg_class = {
@@ -3409,7 +3032,6 @@ static struct omap_hwmod_class am35xx_usbotg_class = {
static struct omap_hwmod am35xx_usbhsotg_hwmod = {
.name = "am35x_otg_hs",
.mpu_irqs = am35xx_usbhsotg_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(am35xx_usbhsotg_mpu_irqs),
.main_clk = NULL,
.prcm = {
.omap2 = {
@@ -3445,11 +3067,13 @@ static struct omap_hwmod_class omap34xx_mmc_class = {
static struct omap_hwmod_irq_info omap34xx_mmc1_mpu_irqs[] = {
{ .irq = 83, },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap34xx_mmc1_sdma_reqs[] = {
{ .name = "tx", .dma_req = 61, },
{ .name = "rx", .dma_req = 62, },
+ { .dma_req = -1 }
};
static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = {
@@ -3467,9 +3091,7 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
static struct omap_hwmod omap3xxx_mmc1_hwmod = {
.name = "mmc1",
.mpu_irqs = omap34xx_mmc1_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_mmc1_mpu_irqs),
.sdma_reqs = omap34xx_mmc1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap34xx_mmc1_sdma_reqs),
.opt_clks = omap34xx_mmc1_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc1_opt_clks),
.main_clk = "mmchs1_fck",
@@ -3493,11 +3115,13 @@ static struct omap_hwmod omap3xxx_mmc1_hwmod = {
static struct omap_hwmod_irq_info omap34xx_mmc2_mpu_irqs[] = {
{ .irq = INT_24XX_MMC2_IRQ, },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap34xx_mmc2_sdma_reqs[] = {
{ .name = "tx", .dma_req = 47, },
{ .name = "rx", .dma_req = 48, },
+ { .dma_req = -1 }
};
static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = {
@@ -3511,9 +3135,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
static struct omap_hwmod omap3xxx_mmc2_hwmod = {
.name = "mmc2",
.mpu_irqs = omap34xx_mmc2_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_mmc2_mpu_irqs),
.sdma_reqs = omap34xx_mmc2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap34xx_mmc2_sdma_reqs),
.opt_clks = omap34xx_mmc2_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc2_opt_clks),
.main_clk = "mmchs2_fck",
@@ -3536,11 +3158,13 @@ static struct omap_hwmod omap3xxx_mmc2_hwmod = {
static struct omap_hwmod_irq_info omap34xx_mmc3_mpu_irqs[] = {
{ .irq = 94, },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap34xx_mmc3_sdma_reqs[] = {
{ .name = "tx", .dma_req = 77, },
{ .name = "rx", .dma_req = 78, },
+ { .dma_req = -1 }
};
static struct omap_hwmod_opt_clk omap34xx_mmc3_opt_clks[] = {
@@ -3554,9 +3178,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc3_slaves[] = {
static struct omap_hwmod omap3xxx_mmc3_hwmod = {
.name = "mmc3",
.mpu_irqs = omap34xx_mmc3_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_mmc3_mpu_irqs),
.sdma_reqs = omap34xx_mmc3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap34xx_mmc3_sdma_reqs),
.opt_clks = omap34xx_mmc3_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc3_opt_clks),
.main_clk = "mmchs3_fck",
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index e1c69ffe0f69..6201422c0606 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -22,11 +22,13 @@
#include <plat/omap_hwmod.h>
#include <plat/cpu.h>
+#include <plat/i2c.h>
#include <plat/gpio.h>
#include <plat/dma.h>
#include <plat/mcspi.h>
#include <plat/mcbsp.h>
#include <plat/mmc.h>
+#include <plat/i2c.h>
#include "omap_hwmod_common_data.h"
@@ -80,7 +82,12 @@ static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
.name = "dmm",
};
-/* dmm interface data */
+/* dmm */
+static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
+ { .irq = 113 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
/* l3_main_1 -> dmm */
static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
.master = &omap44xx_l3_main_1_hwmod,
@@ -95,6 +102,7 @@ static struct omap_hwmod_addr_space omap44xx_dmm_addrs[] = {
.pa_end = 0x4e0007ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* mpu -> dmm */
@@ -103,7 +111,6 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
.slave = &omap44xx_dmm_hwmod,
.clk = "l3_div_ck",
.addr = omap44xx_dmm_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dmm_addrs),
.user = OCP_USER_MPU,
};
@@ -113,17 +120,19 @@ static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
&omap44xx_mpu__dmm,
};
-static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
- { .irq = 113 + OMAP44XX_IRQ_GIC_START },
-};
-
static struct omap_hwmod omap44xx_dmm_hwmod = {
.name = "dmm",
.class = &omap44xx_dmm_hwmod_class,
+ .clkdm_name = "l3_emif_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_MEMIF_DMM_CONTEXT_OFFSET,
+ },
+ },
.slaves = omap44xx_dmm_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dmm_slaves),
.mpu_irqs = omap44xx_dmm_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dmm_irqs),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
@@ -135,7 +144,7 @@ static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
.name = "emif_fw",
};
-/* emif_fw interface data */
+/* emif_fw */
/* dmm -> emif_fw */
static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
.master = &omap44xx_dmm_hwmod,
@@ -150,6 +159,7 @@ static struct omap_hwmod_addr_space omap44xx_emif_fw_addrs[] = {
.pa_end = 0x4a20c0ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> emif_fw */
@@ -158,7 +168,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
.slave = &omap44xx_emif_fw_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_emif_fw_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_emif_fw_addrs),
.user = OCP_USER_MPU,
};
@@ -171,6 +180,13 @@ static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
static struct omap_hwmod omap44xx_emif_fw_hwmod = {
.name = "emif_fw",
.class = &omap44xx_emif_fw_hwmod_class,
+ .clkdm_name = "l3_emif_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_MEMIF_EMIF_FW_CONTEXT_OFFSET,
+ },
+ },
.slaves = omap44xx_emif_fw_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_emif_fw_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -184,7 +200,7 @@ static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
.name = "l3",
};
-/* l3_instr interface data */
+/* l3_instr */
/* iva -> l3_instr */
static struct omap_hwmod_ocp_if omap44xx_iva__l3_instr = {
.master = &omap44xx_iva_hwmod,
@@ -210,12 +226,26 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
static struct omap_hwmod omap44xx_l3_instr_hwmod = {
.name = "l3_instr",
.class = &omap44xx_l3_hwmod_class,
+ .clkdm_name = "l3_instr_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INSTR_L3_INSTR_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
.slaves = omap44xx_l3_instr_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l3_instr_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
-/* l3_main_1 interface data */
+/* l3_main_1 */
+static struct omap_hwmod_irq_info omap44xx_l3_main_1_irqs[] = {
+ { .name = "dbg_err", .irq = 9 + OMAP44XX_IRQ_GIC_START },
+ { .name = "app_err", .irq = 10 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
/* dsp -> l3_main_1 */
static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = {
.master = &omap44xx_dsp_hwmod,
@@ -264,18 +294,13 @@ static struct omap_hwmod_ocp_if omap44xx_mmc2__l3_main_1 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* L3 target configuration and error log registers */
-static struct omap_hwmod_irq_info omap44xx_l3_targ_irqs[] = {
- { .irq = 9 + OMAP44XX_IRQ_GIC_START },
- { .irq = 10 + OMAP44XX_IRQ_GIC_START },
-};
-
static struct omap_hwmod_addr_space omap44xx_l3_main_1_addrs[] = {
{
.pa_start = 0x44000000,
.pa_end = 0x44000fff,
- .flags = ADDR_TYPE_RT,
+ .flags = ADDR_TYPE_RT
},
+ { }
};
/* mpu -> l3_main_1 */
@@ -284,8 +309,7 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
.slave = &omap44xx_l3_main_1_hwmod,
.clk = "l3_div_ck",
.addr = omap44xx_l3_main_1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_l3_main_1_addrs),
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .user = OCP_USER_MPU,
};
/* l3_main_1 slave ports */
@@ -302,14 +326,20 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
.name = "l3_main_1",
.class = &omap44xx_l3_hwmod_class,
- .mpu_irqs = omap44xx_l3_targ_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_l3_targ_irqs),
+ .clkdm_name = "l3_1_clkdm",
+ .mpu_irqs = omap44xx_l3_main_1_irqs,
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3_1_L3_1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET,
+ },
+ },
.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 interface data */
+/* l3_main_2 */
/* dma_system -> l3_main_2 */
static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
.master = &omap44xx_dma_system_hwmod,
@@ -354,8 +384,9 @@ static struct omap_hwmod_addr_space omap44xx_l3_main_2_addrs[] = {
{
.pa_start = 0x44800000,
.pa_end = 0x44801fff,
- .flags = ADDR_TYPE_RT,
+ .flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_1 -> l3_main_2 */
@@ -364,8 +395,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
.slave = &omap44xx_l3_main_2_hwmod,
.clk = "l3_div_ck",
.addr = omap44xx_l3_main_2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_l3_main_2_addrs),
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .user = OCP_USER_MPU,
};
/* l4_cfg -> l3_main_2 */
@@ -399,18 +429,26 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
.name = "l3_main_2",
.class = &omap44xx_l3_hwmod_class,
+ .clkdm_name = "l3_2_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3_2_L3_2_CONTEXT_OFFSET,
+ },
+ },
.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 interface data */
+/* l3_main_3 */
static struct omap_hwmod_addr_space omap44xx_l3_main_3_addrs[] = {
{
.pa_start = 0x45000000,
.pa_end = 0x45000fff,
- .flags = ADDR_TYPE_RT,
+ .flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_1 -> l3_main_3 */
@@ -419,8 +457,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
.slave = &omap44xx_l3_main_3_hwmod,
.clk = "l3_div_ck",
.addr = omap44xx_l3_main_3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_l3_main_3_addrs),
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .user = OCP_USER_MPU,
};
/* l3_main_2 -> l3_main_3 */
@@ -449,6 +486,14 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
.name = "l3_main_3",
.class = &omap44xx_l3_hwmod_class,
+ .clkdm_name = "l3_instr_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INSTR_L3_3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
.slaves = omap44xx_l3_main_3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_3_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -462,7 +507,7 @@ static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
.name = "l4",
};
-/* l4_abe interface data */
+/* l4_abe */
/* aess -> l4_abe */
static struct omap_hwmod_ocp_if omap44xx_aess__l4_abe = {
.master = &omap44xx_aess_hwmod,
@@ -506,12 +551,18 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
static struct omap_hwmod omap44xx_l4_abe_hwmod = {
.name = "l4_abe",
.class = &omap44xx_l4_hwmod_class,
+ .clkdm_name = "abe_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET,
+ },
+ },
.slaves = omap44xx_l4_abe_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_abe_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
-/* l4_cfg interface data */
+/* l4_cfg */
/* l3_main_1 -> l4_cfg */
static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
.master = &omap44xx_l3_main_1_hwmod,
@@ -528,12 +579,19 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
.name = "l4_cfg",
.class = &omap44xx_l4_hwmod_class,
+ .clkdm_name = "l4_cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4CFG_L4_CFG_CONTEXT_OFFSET,
+ },
+ },
.slaves = omap44xx_l4_cfg_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_cfg_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
-/* l4_per interface data */
+/* l4_per */
/* l3_main_2 -> l4_per */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
.master = &omap44xx_l3_main_2_hwmod,
@@ -550,12 +608,19 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
static struct omap_hwmod omap44xx_l4_per_hwmod = {
.name = "l4_per",
.class = &omap44xx_l4_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_L4_PER_CONTEXT_OFFSET,
+ },
+ },
.slaves = omap44xx_l4_per_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_per_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
-/* l4_wkup interface data */
+/* l4_wkup */
/* l4_cfg -> l4_wkup */
static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
.master = &omap44xx_l4_cfg_hwmod,
@@ -572,6 +637,13 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
.name = "l4_wkup",
.class = &omap44xx_l4_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_WKUP_L4WKUP_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_WKUP_L4WKUP_CONTEXT_OFFSET,
+ },
+ },
.slaves = omap44xx_l4_wkup_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_wkup_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -585,7 +657,7 @@ static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
.name = "mpu_bus",
};
-/* mpu_private interface data */
+/* mpu_private */
/* mpu -> mpu_private */
static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
.master = &omap44xx_mpu_hwmod,
@@ -602,6 +674,7 @@ static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
static struct omap_hwmod omap44xx_mpu_private_hwmod = {
.name = "mpu_private",
.class = &omap44xx_mpu_bus_hwmod_class,
+ .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),
@@ -633,7 +706,9 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
* gpmc
* gpu
* hdq1w
- * hsi
+ * mcasp
+ * mpu_c0
+ * mpu_c1
* ocmc_ram
* ocp2scp_usb_phy
* ocp_wp_noc
@@ -660,7 +735,8 @@ static struct omap_hwmod_class_sysconfig omap44xx_aess_sysc = {
.sysc_offs = 0x0010,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART |
+ MSTANDBY_SMART_WKUP),
.sysc_fields = &omap_hwmod_sysc_type2,
};
@@ -672,6 +748,7 @@ static struct omap_hwmod_class omap44xx_aess_hwmod_class = {
/* aess */
static struct omap_hwmod_irq_info omap44xx_aess_irqs[] = {
{ .irq = 99 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_aess_sdma_reqs[] = {
@@ -683,6 +760,7 @@ static struct omap_hwmod_dma_info omap44xx_aess_sdma_reqs[] = {
{ .name = "fifo5", .dma_req = 105 + OMAP44XX_DMA_REQ_START },
{ .name = "fifo6", .dma_req = 106 + OMAP44XX_DMA_REQ_START },
{ .name = "fifo7", .dma_req = 107 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
/* aess master ports */
@@ -696,6 +774,7 @@ static struct omap_hwmod_addr_space omap44xx_aess_addrs[] = {
.pa_end = 0x401f13ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> aess */
@@ -704,7 +783,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess = {
.slave = &omap44xx_aess_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_aess_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_aess_addrs),
.user = OCP_USER_MPU,
};
@@ -714,6 +792,7 @@ static struct omap_hwmod_addr_space omap44xx_aess_dma_addrs[] = {
.pa_end = 0x490f13ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> aess (dma) */
@@ -722,7 +801,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess_dma = {
.slave = &omap44xx_aess_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_aess_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_aess_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -735,14 +813,15 @@ static struct omap_hwmod_ocp_if *omap44xx_aess_slaves[] = {
static struct omap_hwmod omap44xx_aess_hwmod = {
.name = "aess",
.class = &omap44xx_aess_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_aess_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_aess_irqs),
.sdma_reqs = omap44xx_aess_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_aess_sdma_reqs),
.main_clk = "aess_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_aess_slaves,
@@ -769,9 +848,10 @@ static struct omap_hwmod_opt_clk bandgap_opt_clks[] = {
static struct omap_hwmod omap44xx_bandgap_hwmod = {
.name = "bandgap",
.class = &omap44xx_bandgap_hwmod_class,
- .prcm = {
+ .clkdm_name = "l4_wkup_clkdm",
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_WKUP_BANDGAP_CLKCTRL_OFFSET,
},
},
.opt_clks = bandgap_opt_clks,
@@ -806,6 +886,7 @@ static struct omap_hwmod_addr_space omap44xx_counter_32k_addrs[] = {
.pa_end = 0x4a30401f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> counter_32k */
@@ -814,7 +895,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__counter_32k = {
.slave = &omap44xx_counter_32k_hwmod,
.clk = "l4_wkup_clk_mux_ck",
.addr = omap44xx_counter_32k_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_counter_32k_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -826,11 +906,13 @@ static struct omap_hwmod_ocp_if *omap44xx_counter_32k_slaves[] = {
static struct omap_hwmod omap44xx_counter_32k_hwmod = {
.name = "counter_32k",
.class = &omap44xx_counter_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
.flags = HWMOD_SWSUP_SIDLE,
.main_clk = "sys_32k_ck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_WKUP_SYNCTIMER_CONTEXT_OFFSET,
},
},
.slaves = omap44xx_counter_32k_slaves,
@@ -875,6 +957,7 @@ static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = {
{ .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START },
{ .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START },
{ .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
/* dma_system master ports */
@@ -888,6 +971,7 @@ static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
.pa_end = 0x4a056fff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> dma_system */
@@ -896,7 +980,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = {
.slave = &omap44xx_dma_system_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dma_system_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dma_system_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -908,12 +991,13 @@ static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = {
static struct omap_hwmod omap44xx_dma_system_hwmod = {
.name = "dma_system",
.class = &omap44xx_dma_hwmod_class,
+ .clkdm_name = "l3_dma_clkdm",
.mpu_irqs = omap44xx_dma_system_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dma_system_irqs),
.main_clk = "l3_div_ck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_SDMA_SDMA_CONTEXT_OFFSET,
},
},
.dev_attr = &dma_dev_attr,
@@ -948,10 +1032,12 @@ static struct omap_hwmod_class omap44xx_dmic_hwmod_class = {
static struct omap_hwmod omap44xx_dmic_hwmod;
static struct omap_hwmod_irq_info omap44xx_dmic_irqs[] = {
{ .irq = 114 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
{ .dma_req = 66 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
@@ -960,6 +1046,7 @@ static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
.pa_end = 0x4012e07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> dmic */
@@ -968,7 +1055,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
.slave = &omap44xx_dmic_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_dmic_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dmic_addrs),
.user = OCP_USER_MPU,
};
@@ -978,6 +1064,7 @@ static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
.pa_end = 0x4902e07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> dmic (dma) */
@@ -986,7 +1073,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic_dma = {
.slave = &omap44xx_dmic_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_dmic_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dmic_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -999,14 +1085,15 @@ static struct omap_hwmod_ocp_if *omap44xx_dmic_slaves[] = {
static struct omap_hwmod omap44xx_dmic_hwmod = {
.name = "dmic",
.class = &omap44xx_dmic_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_dmic_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dmic_irqs),
.sdma_reqs = omap44xx_dmic_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dmic_sdma_reqs),
.main_clk = "dmic_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_DMIC_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_dmic_slaves,
@@ -1026,6 +1113,7 @@ static struct omap_hwmod_class omap44xx_dsp_hwmod_class = {
/* dsp */
static struct omap_hwmod_irq_info omap44xx_dsp_irqs[] = {
{ .irq = 28 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_rst_info omap44xx_dsp_resets[] = {
@@ -1067,12 +1155,13 @@ static struct omap_hwmod_ocp_if *omap44xx_dsp_slaves[] = {
static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
.name = "dsp_c0",
.class = &omap44xx_dsp_hwmod_class,
+ .clkdm_name = "tesla_clkdm",
.flags = HWMOD_INIT_NO_RESET,
.rst_lines = omap44xx_dsp_c0_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_dsp_c0_resets),
.prcm = {
.omap4 = {
- .rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+ .rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
},
},
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1081,15 +1170,17 @@ static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
static struct omap_hwmod omap44xx_dsp_hwmod = {
.name = "dsp",
.class = &omap44xx_dsp_hwmod_class,
+ .clkdm_name = "tesla_clkdm",
.mpu_irqs = omap44xx_dsp_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dsp_irqs),
.rst_lines = omap44xx_dsp_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_dsp_resets),
.main_clk = "dsp_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
- .rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+ .clkctrl_offs = OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET,
+ .rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
+ .context_offs = OMAP4_RM_TESLA_TESLA_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.slaves = omap44xx_dsp_slaves,
@@ -1127,15 +1218,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
.pa_end = 0x5800007f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> dss */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_dss_hwmod,
- .clk = "l3_div_ck",
+ .clk = "dss_fck",
.addr = omap44xx_dss_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -1145,6 +1236,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_addrs[] = {
.pa_end = 0x4804007f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> dss */
@@ -1153,7 +1245,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = {
.slave = &omap44xx_dss_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dss_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_addrs),
.user = OCP_USER_MPU,
};
@@ -1173,10 +1264,12 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
static struct omap_hwmod omap44xx_dss_hwmod = {
.name = "dss_core",
.class = &omap44xx_dss_hwmod_class,
- .main_clk = "dss_fck",
+ .clkdm_name = "l3_dss_clkdm",
+ .main_clk = "dss_dss_clk",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
.opt_clks = dss_opt_clks,
@@ -1215,10 +1308,12 @@ static struct omap_hwmod_class omap44xx_dispc_hwmod_class = {
static struct omap_hwmod omap44xx_dss_dispc_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_dispc_irqs[] = {
{ .irq = 25 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_dss_dispc_sdma_reqs[] = {
{ .dma_req = 5 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
@@ -1227,15 +1322,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
.pa_end = 0x58001fff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> dss_dispc */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_dss_dispc_hwmod,
- .clk = "l3_div_ck",
+ .clk = "dss_fck",
.addr = omap44xx_dss_dispc_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -1245,6 +1340,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
.pa_end = 0x48041fff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> dss_dispc */
@@ -1253,7 +1349,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
.slave = &omap44xx_dss_dispc_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dss_dispc_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_dispc_addrs),
.user = OCP_USER_MPU,
};
@@ -1263,19 +1358,27 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
&omap44xx_l4_per__dss_dispc,
};
+static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = {
+ { .role = "sys_clk", .clk = "dss_sys_clk" },
+ { .role = "tv_clk", .clk = "dss_tv_clk" },
+ { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
.name = "dss_dispc",
.class = &omap44xx_dispc_hwmod_class,
+ .clkdm_name = "l3_dss_clkdm",
.mpu_irqs = omap44xx_dss_dispc_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_irqs),
.sdma_reqs = omap44xx_dss_dispc_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
- .main_clk = "dss_fck",
+ .main_clk = "dss_dss_clk",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
+ .opt_clks = dss_dispc_opt_clks,
+ .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),
@@ -1306,10 +1409,12 @@ static struct omap_hwmod_class omap44xx_dsi_hwmod_class = {
static struct omap_hwmod omap44xx_dss_dsi1_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_dsi1_irqs[] = {
{ .irq = 53 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_dss_dsi1_sdma_reqs[] = {
{ .dma_req = 74 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
@@ -1318,15 +1423,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
.pa_end = 0x580041ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> dss_dsi1 */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_dss_dsi1_hwmod,
- .clk = "l3_div_ck",
+ .clk = "dss_fck",
.addr = omap44xx_dss_dsi1_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -1336,6 +1441,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_addrs[] = {
.pa_end = 0x480441ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> dss_dsi1 */
@@ -1344,7 +1450,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = {
.slave = &omap44xx_dss_dsi1_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dss_dsi1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_addrs),
.user = OCP_USER_MPU,
};
@@ -1354,19 +1459,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
&omap44xx_l4_per__dss_dsi1,
};
+static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
+ { .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
.name = "dss_dsi1",
.class = &omap44xx_dsi_hwmod_class,
+ .clkdm_name = "l3_dss_clkdm",
.mpu_irqs = omap44xx_dss_dsi1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
.sdma_reqs = omap44xx_dss_dsi1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
- .main_clk = "dss_fck",
+ .main_clk = "dss_dss_clk",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
+ .opt_clks = dss_dsi1_opt_clks,
+ .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),
@@ -1376,10 +1487,12 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
static struct omap_hwmod omap44xx_dss_dsi2_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_dsi2_irqs[] = {
{ .irq = 84 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_dss_dsi2_sdma_reqs[] = {
{ .dma_req = 83 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
@@ -1388,15 +1501,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
.pa_end = 0x580051ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> dss_dsi2 */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_dss_dsi2_hwmod,
- .clk = "l3_div_ck",
+ .clk = "dss_fck",
.addr = omap44xx_dss_dsi2_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -1406,6 +1519,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_addrs[] = {
.pa_end = 0x480451ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> dss_dsi2 */
@@ -1414,7 +1528,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = {
.slave = &omap44xx_dss_dsi2_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dss_dsi2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_addrs),
.user = OCP_USER_MPU,
};
@@ -1424,19 +1537,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = {
&omap44xx_l4_per__dss_dsi2,
};
+static struct omap_hwmod_opt_clk dss_dsi2_opt_clks[] = {
+ { .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
.name = "dss_dsi2",
.class = &omap44xx_dsi_hwmod_class,
+ .clkdm_name = "l3_dss_clkdm",
.mpu_irqs = omap44xx_dss_dsi2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
.sdma_reqs = omap44xx_dss_dsi2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
- .main_clk = "dss_fck",
+ .main_clk = "dss_dss_clk",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
+ .opt_clks = dss_dsi2_opt_clks,
+ .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),
@@ -1466,10 +1585,12 @@ static struct omap_hwmod_class omap44xx_hdmi_hwmod_class = {
static struct omap_hwmod omap44xx_dss_hdmi_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_hdmi_irqs[] = {
{ .irq = 101 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = {
{ .dma_req = 75 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
@@ -1478,15 +1599,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
.pa_end = 0x58006fff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> dss_hdmi */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_dss_hdmi_hwmod,
- .clk = "l3_div_ck",
+ .clk = "dss_fck",
.addr = omap44xx_dss_hdmi_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -1496,6 +1617,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_addrs[] = {
.pa_end = 0x48046fff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> dss_hdmi */
@@ -1504,7 +1626,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = {
.slave = &omap44xx_dss_hdmi_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dss_hdmi_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_addrs),
.user = OCP_USER_MPU,
};
@@ -1514,19 +1635,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
&omap44xx_l4_per__dss_hdmi,
};
+static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = {
+ { .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
.name = "dss_hdmi",
.class = &omap44xx_hdmi_hwmod_class,
+ .clkdm_name = "l3_dss_clkdm",
.mpu_irqs = omap44xx_dss_hdmi_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
.sdma_reqs = omap44xx_dss_hdmi_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
- .main_clk = "dss_fck",
+ .main_clk = "dss_dss_clk",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
+ .opt_clks = dss_hdmi_opt_clks,
+ .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),
@@ -1556,6 +1683,7 @@ static struct omap_hwmod_class omap44xx_rfbi_hwmod_class = {
static struct omap_hwmod omap44xx_dss_rfbi_hwmod;
static struct omap_hwmod_dma_info omap44xx_dss_rfbi_sdma_reqs[] = {
{ .dma_req = 13 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
@@ -1564,15 +1692,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
.pa_end = 0x580020ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> dss_rfbi */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_dss_rfbi_hwmod,
- .clk = "l3_div_ck",
+ .clk = "dss_fck",
.addr = omap44xx_dss_rfbi_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -1582,6 +1710,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_addrs[] = {
.pa_end = 0x480420ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> dss_rfbi */
@@ -1590,7 +1719,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = {
.slave = &omap44xx_dss_rfbi_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dss_rfbi_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_addrs),
.user = OCP_USER_MPU,
};
@@ -1600,17 +1728,24 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
&omap44xx_l4_per__dss_rfbi,
};
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+ { .role = "ick", .clk = "dss_fck" },
+};
+
static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
.name = "dss_rfbi",
.class = &omap44xx_rfbi_hwmod_class,
+ .clkdm_name = "l3_dss_clkdm",
.sdma_reqs = omap44xx_dss_rfbi_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
- .main_clk = "dss_fck",
+ .main_clk = "dss_dss_clk",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
+ .opt_clks = dss_rfbi_opt_clks,
+ .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),
@@ -1633,15 +1768,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
.pa_end = 0x580030ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> dss_venc */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_dss_venc_hwmod,
- .clk = "l3_div_ck",
+ .clk = "dss_fck",
.addr = omap44xx_dss_venc_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -1651,6 +1786,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_addrs[] = {
.pa_end = 0x480430ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> dss_venc */
@@ -1659,7 +1795,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = {
.slave = &omap44xx_dss_venc_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_dss_venc_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_dss_venc_addrs),
.user = OCP_USER_MPU,
};
@@ -1672,10 +1807,12 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
static struct omap_hwmod omap44xx_dss_venc_hwmod = {
.name = "dss_venc",
.class = &omap44xx_venc_hwmod_class,
- .main_clk = "dss_fck",
+ .clkdm_name = "l3_dss_clkdm",
+ .main_clk = "dss_dss_clk",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
.slaves = omap44xx_dss_venc_slaves,
@@ -1716,6 +1853,7 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
static struct omap_hwmod omap44xx_gpio1_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio1_irqs[] = {
{ .irq = 29 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
@@ -1724,6 +1862,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
.pa_end = 0x4a3101ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> gpio1 */
@@ -1732,7 +1871,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
.slave = &omap44xx_gpio1_hwmod,
.clk = "l4_wkup_clk_mux_ck",
.addr = omap44xx_gpio1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_gpio1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1748,12 +1886,14 @@ static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
static struct omap_hwmod omap44xx_gpio1_hwmod = {
.name = "gpio1",
.class = &omap44xx_gpio_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
.mpu_irqs = omap44xx_gpio1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio1_irqs),
.main_clk = "gpio1_ick",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_WKUP_GPIO1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.opt_clks = gpio1_opt_clks,
@@ -1768,6 +1908,7 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = {
static struct omap_hwmod omap44xx_gpio2_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio2_irqs[] = {
{ .irq = 30 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
@@ -1776,6 +1917,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
.pa_end = 0x480551ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> gpio2 */
@@ -1784,7 +1926,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
.slave = &omap44xx_gpio2_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_gpio2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_gpio2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1800,13 +1941,15 @@ static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
static struct omap_hwmod omap44xx_gpio2_hwmod = {
.name = "gpio2",
.class = &omap44xx_gpio_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap44xx_gpio2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio2_irqs),
.main_clk = "gpio2_ick",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_GPIO2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.opt_clks = gpio2_opt_clks,
@@ -1821,6 +1964,7 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
static struct omap_hwmod omap44xx_gpio3_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio3_irqs[] = {
{ .irq = 31 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
@@ -1829,6 +1973,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
.pa_end = 0x480571ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> gpio3 */
@@ -1837,7 +1982,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
.slave = &omap44xx_gpio3_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_gpio3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_gpio3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1853,13 +1997,15 @@ static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
static struct omap_hwmod omap44xx_gpio3_hwmod = {
.name = "gpio3",
.class = &omap44xx_gpio_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap44xx_gpio3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio3_irqs),
.main_clk = "gpio3_ick",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_GPIO3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.opt_clks = gpio3_opt_clks,
@@ -1874,6 +2020,7 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
static struct omap_hwmod omap44xx_gpio4_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio4_irqs[] = {
{ .irq = 32 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
@@ -1882,6 +2029,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
.pa_end = 0x480591ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> gpio4 */
@@ -1890,7 +2038,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
.slave = &omap44xx_gpio4_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_gpio4_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_gpio4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1906,13 +2053,15 @@ static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
static struct omap_hwmod omap44xx_gpio4_hwmod = {
.name = "gpio4",
.class = &omap44xx_gpio_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap44xx_gpio4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio4_irqs),
.main_clk = "gpio4_ick",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_GPIO4_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.opt_clks = gpio4_opt_clks,
@@ -1927,6 +2076,7 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
static struct omap_hwmod omap44xx_gpio5_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio5_irqs[] = {
{ .irq = 33 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
@@ -1935,6 +2085,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
.pa_end = 0x4805b1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> gpio5 */
@@ -1943,7 +2094,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
.slave = &omap44xx_gpio5_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_gpio5_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_gpio5_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -1959,13 +2109,15 @@ static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
static struct omap_hwmod omap44xx_gpio5_hwmod = {
.name = "gpio5",
.class = &omap44xx_gpio_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap44xx_gpio5_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio5_irqs),
.main_clk = "gpio5_ick",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_GPIO5_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.opt_clks = gpio5_opt_clks,
@@ -1980,6 +2132,7 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
static struct omap_hwmod omap44xx_gpio6_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio6_irqs[] = {
{ .irq = 34 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
@@ -1988,6 +2141,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
.pa_end = 0x4805d1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> gpio6 */
@@ -1996,7 +2150,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
.slave = &omap44xx_gpio6_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_gpio6_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_gpio6_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2012,13 +2165,15 @@ static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
static struct omap_hwmod omap44xx_gpio6_hwmod = {
.name = "gpio6",
.class = &omap44xx_gpio_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.mpu_irqs = omap44xx_gpio6_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio6_irqs),
.main_clk = "gpio6_ick",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_GPIO6_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.opt_clks = gpio6_opt_clks,
@@ -2044,7 +2199,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_hsi_sysc = {
SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
- MSTANDBY_SMART),
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
.sysc_fields = &omap_hwmod_sysc_type1,
};
@@ -2058,6 +2213,7 @@ static struct omap_hwmod_irq_info omap44xx_hsi_irqs[] = {
{ .name = "mpu_p1", .irq = 67 + OMAP44XX_IRQ_GIC_START },
{ .name = "mpu_p2", .irq = 68 + OMAP44XX_IRQ_GIC_START },
{ .name = "mpu_dma", .irq = 71 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
/* hsi master ports */
@@ -2071,6 +2227,7 @@ static struct omap_hwmod_addr_space omap44xx_hsi_addrs[] = {
.pa_end = 0x4a05bfff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> hsi */
@@ -2079,7 +2236,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__hsi = {
.slave = &omap44xx_hsi_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_hsi_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_hsi_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2091,12 +2247,14 @@ static struct omap_hwmod_ocp_if *omap44xx_hsi_slaves[] = {
static struct omap_hwmod omap44xx_hsi_hwmod = {
.name = "hsi",
.class = &omap44xx_hsi_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
.mpu_irqs = omap44xx_hsi_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_hsi_irqs),
.main_clk = "hsi_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L3INIT_HSI_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_HSI_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.slaves = omap44xx_hsi_slaves,
@@ -2125,17 +2283,25 @@ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
.name = "i2c",
.sysc = &omap44xx_i2c_sysc,
+ .rev = OMAP_I2C_IP_VERSION_2,
+ .reset = &omap_i2c_reset,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+ .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
};
/* i2c1 */
static struct omap_hwmod omap44xx_i2c1_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c1_irqs[] = {
{ .irq = 56 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_i2c1_sdma_reqs[] = {
{ .name = "tx", .dma_req = 26 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 27 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
@@ -2144,6 +2310,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
.pa_end = 0x480700ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> i2c1 */
@@ -2152,7 +2319,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
.slave = &omap44xx_i2c1_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_i2c1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_i2c1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2164,19 +2330,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = {
static struct omap_hwmod omap44xx_i2c1_hwmod = {
.name = "i2c1",
.class = &omap44xx_i2c_hwmod_class,
- .flags = HWMOD_INIT_NO_RESET,
+ .clkdm_name = "l4_per_clkdm",
+ .flags = HWMOD_16BIT_REG,
.mpu_irqs = omap44xx_i2c1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c1_irqs),
.sdma_reqs = omap44xx_i2c1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_i2c1_sdma_reqs),
.main_clk = "i2c1_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_I2C1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_i2c1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c1_slaves),
+ .dev_attr = &i2c_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
@@ -2184,11 +2352,13 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = {
static struct omap_hwmod omap44xx_i2c2_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c2_irqs[] = {
{ .irq = 57 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_i2c2_sdma_reqs[] = {
{ .name = "tx", .dma_req = 28 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 29 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
@@ -2197,6 +2367,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
.pa_end = 0x480720ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> i2c2 */
@@ -2205,7 +2376,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
.slave = &omap44xx_i2c2_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_i2c2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_i2c2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2217,19 +2387,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = {
static struct omap_hwmod omap44xx_i2c2_hwmod = {
.name = "i2c2",
.class = &omap44xx_i2c_hwmod_class,
- .flags = HWMOD_INIT_NO_RESET,
+ .clkdm_name = "l4_per_clkdm",
+ .flags = HWMOD_16BIT_REG,
.mpu_irqs = omap44xx_i2c2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c2_irqs),
.sdma_reqs = omap44xx_i2c2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_i2c2_sdma_reqs),
.main_clk = "i2c2_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_I2C2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_i2c2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c2_slaves),
+ .dev_attr = &i2c_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
@@ -2237,11 +2409,13 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = {
static struct omap_hwmod omap44xx_i2c3_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c3_irqs[] = {
{ .irq = 61 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_i2c3_sdma_reqs[] = {
{ .name = "tx", .dma_req = 24 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 25 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
@@ -2250,6 +2424,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
.pa_end = 0x480600ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> i2c3 */
@@ -2258,7 +2433,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
.slave = &omap44xx_i2c3_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_i2c3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_i2c3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2270,19 +2444,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = {
static struct omap_hwmod omap44xx_i2c3_hwmod = {
.name = "i2c3",
.class = &omap44xx_i2c_hwmod_class,
- .flags = HWMOD_INIT_NO_RESET,
+ .clkdm_name = "l4_per_clkdm",
+ .flags = HWMOD_16BIT_REG,
.mpu_irqs = omap44xx_i2c3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c3_irqs),
.sdma_reqs = omap44xx_i2c3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_i2c3_sdma_reqs),
.main_clk = "i2c3_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_I2C3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_i2c3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c3_slaves),
+ .dev_attr = &i2c_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
@@ -2290,11 +2466,13 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = {
static struct omap_hwmod omap44xx_i2c4_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c4_irqs[] = {
{ .irq = 62 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_i2c4_sdma_reqs[] = {
{ .name = "tx", .dma_req = 123 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 124 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
@@ -2303,6 +2481,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
.pa_end = 0x483500ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> i2c4 */
@@ -2311,7 +2490,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
.slave = &omap44xx_i2c4_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_i2c4_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_i2c4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2323,19 +2501,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = {
static struct omap_hwmod omap44xx_i2c4_hwmod = {
.name = "i2c4",
.class = &omap44xx_i2c_hwmod_class,
- .flags = HWMOD_INIT_NO_RESET,
+ .clkdm_name = "l4_per_clkdm",
+ .flags = HWMOD_16BIT_REG,
.mpu_irqs = omap44xx_i2c4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c4_irqs),
.sdma_reqs = omap44xx_i2c4_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_i2c4_sdma_reqs),
.main_clk = "i2c4_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_I2C4_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_i2c4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c4_slaves),
+ .dev_attr = &i2c_dev_attr,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
@@ -2351,6 +2531,7 @@ static struct omap_hwmod_class omap44xx_ipu_hwmod_class = {
/* ipu */
static struct omap_hwmod_irq_info omap44xx_ipu_irqs[] = {
{ .irq = 100 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_rst_info omap44xx_ipu_c0_resets[] = {
@@ -2387,12 +2568,13 @@ static struct omap_hwmod_ocp_if *omap44xx_ipu_slaves[] = {
static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
.name = "ipu_c0",
.class = &omap44xx_ipu_hwmod_class,
+ .clkdm_name = "ducati_clkdm",
.flags = HWMOD_INIT_NO_RESET,
.rst_lines = omap44xx_ipu_c0_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_ipu_c0_resets),
- .prcm = {
+ .prcm = {
.omap4 = {
- .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+ .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
},
},
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2402,12 +2584,13 @@ static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
.name = "ipu_c1",
.class = &omap44xx_ipu_hwmod_class,
+ .clkdm_name = "ducati_clkdm",
.flags = HWMOD_INIT_NO_RESET,
.rst_lines = omap44xx_ipu_c1_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_ipu_c1_resets),
- .prcm = {
+ .prcm = {
.omap4 = {
- .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+ .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
},
},
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2416,15 +2599,17 @@ static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
static struct omap_hwmod omap44xx_ipu_hwmod = {
.name = "ipu",
.class = &omap44xx_ipu_hwmod_class,
+ .clkdm_name = "ducati_clkdm",
.mpu_irqs = omap44xx_ipu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_ipu_irqs),
.rst_lines = omap44xx_ipu_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_ipu_resets),
.main_clk = "ipu_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
- .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+ .clkctrl_offs = OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET,
+ .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DUCATI_DUCATI_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.slaves = omap44xx_ipu_slaves,
@@ -2446,7 +2631,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = {
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
- MSTANDBY_SMART),
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
.sysc_fields = &omap_hwmod_sysc_type2,
};
@@ -2458,6 +2643,7 @@ static struct omap_hwmod_class omap44xx_iss_hwmod_class = {
/* iss */
static struct omap_hwmod_irq_info omap44xx_iss_irqs[] = {
{ .irq = 24 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_iss_sdma_reqs[] = {
@@ -2465,6 +2651,7 @@ static struct omap_hwmod_dma_info omap44xx_iss_sdma_reqs[] = {
{ .name = "2", .dma_req = 9 + OMAP44XX_DMA_REQ_START },
{ .name = "3", .dma_req = 11 + OMAP44XX_DMA_REQ_START },
{ .name = "4", .dma_req = 12 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
/* iss master ports */
@@ -2478,6 +2665,7 @@ static struct omap_hwmod_addr_space omap44xx_iss_addrs[] = {
.pa_end = 0x520000ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> iss */
@@ -2486,7 +2674,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
.slave = &omap44xx_iss_hwmod,
.clk = "l3_div_ck",
.addr = omap44xx_iss_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_iss_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2502,14 +2689,15 @@ static struct omap_hwmod_opt_clk iss_opt_clks[] = {
static struct omap_hwmod omap44xx_iss_hwmod = {
.name = "iss",
.class = &omap44xx_iss_hwmod_class,
+ .clkdm_name = "iss_clkdm",
.mpu_irqs = omap44xx_iss_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_iss_irqs),
.sdma_reqs = omap44xx_iss_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_iss_sdma_reqs),
.main_clk = "iss_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_CAM_ISS_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_CAM_ISS_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.opt_clks = iss_opt_clks,
@@ -2535,6 +2723,7 @@ static struct omap_hwmod_irq_info omap44xx_iva_irqs[] = {
{ .name = "sync_1", .irq = 103 + OMAP44XX_IRQ_GIC_START },
{ .name = "sync_0", .irq = 104 + OMAP44XX_IRQ_GIC_START },
{ .name = "mailbox_0", .irq = 107 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_rst_info omap44xx_iva_resets[] = {
@@ -2561,6 +2750,7 @@ static struct omap_hwmod_addr_space omap44xx_iva_addrs[] = {
.pa_end = 0x5a07ffff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l3_main_2 -> iva */
@@ -2569,7 +2759,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
.slave = &omap44xx_iva_hwmod,
.clk = "l3_div_ck",
.addr = omap44xx_iva_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_iva_addrs),
.user = OCP_USER_MPU,
};
@@ -2583,12 +2772,13 @@ static struct omap_hwmod_ocp_if *omap44xx_iva_slaves[] = {
static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
.name = "iva_seq0",
.class = &omap44xx_iva_hwmod_class,
+ .clkdm_name = "ivahd_clkdm",
.flags = HWMOD_INIT_NO_RESET,
.rst_lines = omap44xx_iva_seq0_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_iva_seq0_resets),
.prcm = {
.omap4 = {
- .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+ .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
},
},
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2598,12 +2788,13 @@ static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
.name = "iva_seq1",
.class = &omap44xx_iva_hwmod_class,
+ .clkdm_name = "ivahd_clkdm",
.flags = HWMOD_INIT_NO_RESET,
.rst_lines = omap44xx_iva_seq1_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_iva_seq1_resets),
.prcm = {
.omap4 = {
- .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+ .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
},
},
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2612,15 +2803,17 @@ static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
static struct omap_hwmod omap44xx_iva_hwmod = {
.name = "iva",
.class = &omap44xx_iva_hwmod_class,
+ .clkdm_name = "ivahd_clkdm",
.mpu_irqs = omap44xx_iva_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_iva_irqs),
.rst_lines = omap44xx_iva_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_iva_resets),
.main_clk = "iva_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
- .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+ .clkctrl_offs = OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET,
+ .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
+ .context_offs = OMAP4_RM_IVAHD_IVAHD_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.slaves = omap44xx_iva_slaves,
@@ -2656,6 +2849,7 @@ static struct omap_hwmod_class omap44xx_kbd_hwmod_class = {
static struct omap_hwmod omap44xx_kbd_hwmod;
static struct omap_hwmod_irq_info omap44xx_kbd_irqs[] = {
{ .irq = 120 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
@@ -2664,6 +2858,7 @@ static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
.pa_end = 0x4a31c07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> kbd */
@@ -2672,7 +2867,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__kbd = {
.slave = &omap44xx_kbd_hwmod,
.clk = "l4_wkup_clk_mux_ck",
.addr = omap44xx_kbd_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_kbd_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2684,12 +2878,14 @@ static struct omap_hwmod_ocp_if *omap44xx_kbd_slaves[] = {
static struct omap_hwmod omap44xx_kbd_hwmod = {
.name = "kbd",
.class = &omap44xx_kbd_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
.mpu_irqs = omap44xx_kbd_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_kbd_irqs),
.main_clk = "kbd_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_WKUP_KEYBOARD_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_WKUP_KEYBOARD_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_kbd_slaves,
@@ -2721,6 +2917,7 @@ static struct omap_hwmod_class omap44xx_mailbox_hwmod_class = {
static struct omap_hwmod omap44xx_mailbox_hwmod;
static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = {
{ .irq = 26 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
@@ -2729,6 +2926,7 @@ static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
.pa_end = 0x4a0f41ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> mailbox */
@@ -2737,7 +2935,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
.slave = &omap44xx_mailbox_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mailbox_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mailbox_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -2749,11 +2946,12 @@ static struct omap_hwmod_ocp_if *omap44xx_mailbox_slaves[] = {
static struct omap_hwmod omap44xx_mailbox_hwmod = {
.name = "mailbox",
.class = &omap44xx_mailbox_hwmod_class,
+ .clkdm_name = "l4_cfg_clkdm",
.mpu_irqs = omap44xx_mailbox_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mailbox_irqs),
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4CFG_MAILBOX_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET,
},
},
.slaves = omap44xx_mailbox_slaves,
@@ -2784,11 +2982,13 @@ static struct omap_hwmod_class omap44xx_mcbsp_hwmod_class = {
static struct omap_hwmod omap44xx_mcbsp1_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp1_irqs[] = {
{ .irq = 17 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcbsp1_sdma_reqs[] = {
{ .name = "tx", .dma_req = 32 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 33 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
@@ -2798,6 +2998,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
.pa_end = 0x401220ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcbsp1 */
@@ -2806,7 +3007,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1 = {
.slave = &omap44xx_mcbsp1_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcbsp1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcbsp1_addrs),
.user = OCP_USER_MPU,
};
@@ -2817,6 +3017,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp1_dma_addrs[] = {
.pa_end = 0x490220ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcbsp1 (dma) */
@@ -2825,7 +3026,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1_dma = {
.slave = &omap44xx_mcbsp1_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcbsp1_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcbsp1_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -2838,14 +3038,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = {
static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
.name = "mcbsp1",
.class = &omap44xx_mcbsp_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_mcbsp1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcbsp1_irqs),
.sdma_reqs = omap44xx_mcbsp1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcbsp1_sdma_reqs),
.main_clk = "mcbsp1_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_MCBSP1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mcbsp1_slaves,
@@ -2857,11 +3058,13 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
static struct omap_hwmod omap44xx_mcbsp2_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp2_irqs[] = {
{ .irq = 22 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcbsp2_sdma_reqs[] = {
{ .name = "tx", .dma_req = 16 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 17 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
@@ -2871,6 +3074,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
.pa_end = 0x401240ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcbsp2 */
@@ -2879,7 +3083,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2 = {
.slave = &omap44xx_mcbsp2_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcbsp2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcbsp2_addrs),
.user = OCP_USER_MPU,
};
@@ -2890,6 +3093,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp2_dma_addrs[] = {
.pa_end = 0x490240ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcbsp2 (dma) */
@@ -2898,7 +3102,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2_dma = {
.slave = &omap44xx_mcbsp2_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcbsp2_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcbsp2_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -2911,14 +3114,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = {
static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
.name = "mcbsp2",
.class = &omap44xx_mcbsp_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_mcbsp2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcbsp2_irqs),
.sdma_reqs = omap44xx_mcbsp2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcbsp2_sdma_reqs),
.main_clk = "mcbsp2_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_MCBSP2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mcbsp2_slaves,
@@ -2930,11 +3134,13 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
static struct omap_hwmod omap44xx_mcbsp3_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp3_irqs[] = {
{ .irq = 23 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcbsp3_sdma_reqs[] = {
{ .name = "tx", .dma_req = 18 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 19 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
@@ -2944,6 +3150,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
.pa_end = 0x401260ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcbsp3 */
@@ -2952,7 +3159,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3 = {
.slave = &omap44xx_mcbsp3_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcbsp3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcbsp3_addrs),
.user = OCP_USER_MPU,
};
@@ -2963,6 +3169,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp3_dma_addrs[] = {
.pa_end = 0x490260ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcbsp3 (dma) */
@@ -2971,7 +3178,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3_dma = {
.slave = &omap44xx_mcbsp3_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcbsp3_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcbsp3_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -2984,14 +3190,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = {
static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
.name = "mcbsp3",
.class = &omap44xx_mcbsp_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_mcbsp3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcbsp3_irqs),
.sdma_reqs = omap44xx_mcbsp3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcbsp3_sdma_reqs),
.main_clk = "mcbsp3_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_MCBSP3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mcbsp3_slaves,
@@ -3003,11 +3210,13 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
static struct omap_hwmod omap44xx_mcbsp4_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp4_irqs[] = {
{ .irq = 16 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcbsp4_sdma_reqs[] = {
{ .name = "tx", .dma_req = 30 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 31 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
@@ -3016,6 +3225,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
.pa_end = 0x480960ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcbsp4 */
@@ -3024,7 +3234,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = {
.slave = &omap44xx_mcbsp4_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mcbsp4_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcbsp4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3036,14 +3245,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = {
static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
.name = "mcbsp4",
.class = &omap44xx_mcbsp_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mcbsp4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcbsp4_irqs),
.sdma_reqs = omap44xx_mcbsp4_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcbsp4_sdma_reqs),
.main_clk = "mcbsp4_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MCBSP4_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mcbsp4_slaves,
@@ -3076,11 +3286,13 @@ static struct omap_hwmod_class omap44xx_mcpdm_hwmod_class = {
static struct omap_hwmod omap44xx_mcpdm_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcpdm_irqs[] = {
{ .irq = 112 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcpdm_sdma_reqs[] = {
{ .name = "up_link", .dma_req = 64 + OMAP44XX_DMA_REQ_START },
{ .name = "dn_link", .dma_req = 65 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
@@ -3089,6 +3301,7 @@ static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
.pa_end = 0x4013207f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcpdm */
@@ -3097,7 +3310,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
.slave = &omap44xx_mcpdm_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcpdm_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcpdm_addrs),
.user = OCP_USER_MPU,
};
@@ -3107,6 +3319,7 @@ static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = {
.pa_end = 0x4903207f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> mcpdm (dma) */
@@ -3115,7 +3328,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm_dma = {
.slave = &omap44xx_mcpdm_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_mcpdm_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcpdm_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -3128,14 +3340,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcpdm_slaves[] = {
static struct omap_hwmod omap44xx_mcpdm_hwmod = {
.name = "mcpdm",
.class = &omap44xx_mcpdm_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_mcpdm_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcpdm_irqs),
.sdma_reqs = omap44xx_mcpdm_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcpdm_sdma_reqs),
.main_clk = "mcpdm_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_PDM_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mcpdm_slaves,
@@ -3169,6 +3382,7 @@ static struct omap_hwmod_class omap44xx_mcspi_hwmod_class = {
static struct omap_hwmod omap44xx_mcspi1_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi1_irqs[] = {
{ .irq = 65 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcspi1_sdma_reqs[] = {
@@ -3180,6 +3394,7 @@ static struct omap_hwmod_dma_info omap44xx_mcspi1_sdma_reqs[] = {
{ .name = "rx2", .dma_req = 39 + OMAP44XX_DMA_REQ_START },
{ .name = "tx3", .dma_req = 40 + OMAP44XX_DMA_REQ_START },
{ .name = "rx3", .dma_req = 41 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
@@ -3188,6 +3403,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
.pa_end = 0x480981ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcspi1 */
@@ -3196,7 +3412,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi1 = {
.slave = &omap44xx_mcspi1_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mcspi1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcspi1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3213,14 +3428,15 @@ static struct omap2_mcspi_dev_attr mcspi1_dev_attr = {
static struct omap_hwmod omap44xx_mcspi1_hwmod = {
.name = "mcspi1",
.class = &omap44xx_mcspi_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mcspi1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcspi1_irqs),
.sdma_reqs = omap44xx_mcspi1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcspi1_sdma_reqs),
.main_clk = "mcspi1_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MCSPI1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.dev_attr = &mcspi1_dev_attr,
@@ -3233,6 +3449,7 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = {
static struct omap_hwmod omap44xx_mcspi2_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi2_irqs[] = {
{ .irq = 66 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcspi2_sdma_reqs[] = {
@@ -3240,6 +3457,7 @@ static struct omap_hwmod_dma_info omap44xx_mcspi2_sdma_reqs[] = {
{ .name = "rx0", .dma_req = 43 + OMAP44XX_DMA_REQ_START },
{ .name = "tx1", .dma_req = 44 + OMAP44XX_DMA_REQ_START },
{ .name = "rx1", .dma_req = 45 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
@@ -3248,6 +3466,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
.pa_end = 0x4809a1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcspi2 */
@@ -3256,7 +3475,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi2 = {
.slave = &omap44xx_mcspi2_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mcspi2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcspi2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3273,14 +3491,15 @@ static struct omap2_mcspi_dev_attr mcspi2_dev_attr = {
static struct omap_hwmod omap44xx_mcspi2_hwmod = {
.name = "mcspi2",
.class = &omap44xx_mcspi_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mcspi2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcspi2_irqs),
.sdma_reqs = omap44xx_mcspi2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcspi2_sdma_reqs),
.main_clk = "mcspi2_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MCSPI2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.dev_attr = &mcspi2_dev_attr,
@@ -3293,6 +3512,7 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = {
static struct omap_hwmod omap44xx_mcspi3_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi3_irqs[] = {
{ .irq = 91 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcspi3_sdma_reqs[] = {
@@ -3300,6 +3520,7 @@ static struct omap_hwmod_dma_info omap44xx_mcspi3_sdma_reqs[] = {
{ .name = "rx0", .dma_req = 15 + OMAP44XX_DMA_REQ_START },
{ .name = "tx1", .dma_req = 22 + OMAP44XX_DMA_REQ_START },
{ .name = "rx1", .dma_req = 23 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
@@ -3308,6 +3529,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
.pa_end = 0x480b81ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcspi3 */
@@ -3316,7 +3538,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi3 = {
.slave = &omap44xx_mcspi3_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mcspi3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcspi3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3333,14 +3554,15 @@ static struct omap2_mcspi_dev_attr mcspi3_dev_attr = {
static struct omap_hwmod omap44xx_mcspi3_hwmod = {
.name = "mcspi3",
.class = &omap44xx_mcspi_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mcspi3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcspi3_irqs),
.sdma_reqs = omap44xx_mcspi3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcspi3_sdma_reqs),
.main_clk = "mcspi3_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MCSPI3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.dev_attr = &mcspi3_dev_attr,
@@ -3353,11 +3575,13 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = {
static struct omap_hwmod omap44xx_mcspi4_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi4_irqs[] = {
{ .irq = 48 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mcspi4_sdma_reqs[] = {
{ .name = "tx0", .dma_req = 69 + OMAP44XX_DMA_REQ_START },
{ .name = "rx0", .dma_req = 70 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
@@ -3366,6 +3590,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
.pa_end = 0x480ba1ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mcspi4 */
@@ -3374,7 +3599,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi4 = {
.slave = &omap44xx_mcspi4_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mcspi4_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mcspi4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3391,14 +3615,15 @@ static struct omap2_mcspi_dev_attr mcspi4_dev_attr = {
static struct omap_hwmod omap44xx_mcspi4_hwmod = {
.name = "mcspi4",
.class = &omap44xx_mcspi_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mcspi4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcspi4_irqs),
.sdma_reqs = omap44xx_mcspi4_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcspi4_sdma_reqs),
.main_clk = "mcspi4_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MCSPI4_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.dev_attr = &mcspi4_dev_attr,
@@ -3420,7 +3645,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_mmc_sysc = {
SYSC_HAS_SOFTRESET),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
- MSTANDBY_SMART),
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
.sysc_fields = &omap_hwmod_sysc_type2,
};
@@ -3430,14 +3655,15 @@ static struct omap_hwmod_class omap44xx_mmc_hwmod_class = {
};
/* mmc1 */
-
static struct omap_hwmod_irq_info omap44xx_mmc1_irqs[] = {
{ .irq = 83 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mmc1_sdma_reqs[] = {
{ .name = "tx", .dma_req = 60 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 61 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
/* mmc1 master ports */
@@ -3451,6 +3677,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc1_addrs[] = {
.pa_end = 0x4809c3ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mmc1 */
@@ -3459,7 +3686,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc1 = {
.slave = &omap44xx_mmc1_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mmc1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mmc1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3476,14 +3702,15 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
static struct omap_hwmod omap44xx_mmc1_hwmod = {
.name = "mmc1",
.class = &omap44xx_mmc_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
.mpu_irqs = omap44xx_mmc1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mmc1_irqs),
.sdma_reqs = omap44xx_mmc1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mmc1_sdma_reqs),
.main_clk = "mmc1_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_MMC1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.dev_attr = &mmc1_dev_attr,
@@ -3497,11 +3724,13 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
/* mmc2 */
static struct omap_hwmod_irq_info omap44xx_mmc2_irqs[] = {
{ .irq = 86 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mmc2_sdma_reqs[] = {
{ .name = "tx", .dma_req = 46 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 47 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
/* mmc2 master ports */
@@ -3515,6 +3744,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc2_addrs[] = {
.pa_end = 0x480b43ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mmc2 */
@@ -3523,7 +3753,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc2 = {
.slave = &omap44xx_mmc2_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mmc2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mmc2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3535,14 +3764,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc2_slaves[] = {
static struct omap_hwmod omap44xx_mmc2_hwmod = {
.name = "mmc2",
.class = &omap44xx_mmc_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
.mpu_irqs = omap44xx_mmc2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mmc2_irqs),
.sdma_reqs = omap44xx_mmc2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mmc2_sdma_reqs),
.main_clk = "mmc2_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_MMC2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mmc2_slaves,
@@ -3556,11 +3786,13 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
static struct omap_hwmod omap44xx_mmc3_hwmod;
static struct omap_hwmod_irq_info omap44xx_mmc3_irqs[] = {
{ .irq = 94 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mmc3_sdma_reqs[] = {
{ .name = "tx", .dma_req = 76 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 77 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
@@ -3569,6 +3801,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
.pa_end = 0x480ad3ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mmc3 */
@@ -3577,7 +3810,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc3 = {
.slave = &omap44xx_mmc3_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mmc3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mmc3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3589,14 +3821,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc3_slaves[] = {
static struct omap_hwmod omap44xx_mmc3_hwmod = {
.name = "mmc3",
.class = &omap44xx_mmc_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mmc3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mmc3_irqs),
.sdma_reqs = omap44xx_mmc3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mmc3_sdma_reqs),
.main_clk = "mmc3_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MMCSD3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mmc3_slaves,
@@ -3608,11 +3841,13 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
static struct omap_hwmod omap44xx_mmc4_hwmod;
static struct omap_hwmod_irq_info omap44xx_mmc4_irqs[] = {
{ .irq = 96 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mmc4_sdma_reqs[] = {
{ .name = "tx", .dma_req = 56 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 57 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
@@ -3621,6 +3856,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
.pa_end = 0x480d13ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mmc4 */
@@ -3629,7 +3865,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc4 = {
.slave = &omap44xx_mmc4_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mmc4_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mmc4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3641,14 +3876,16 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc4_slaves[] = {
static struct omap_hwmod omap44xx_mmc4_hwmod = {
.name = "mmc4",
.class = &omap44xx_mmc_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mmc4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mmc4_irqs),
+
.sdma_reqs = omap44xx_mmc4_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mmc4_sdma_reqs),
.main_clk = "mmc4_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MMCSD4_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mmc4_slaves,
@@ -3660,11 +3897,13 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
static struct omap_hwmod omap44xx_mmc5_hwmod;
static struct omap_hwmod_irq_info omap44xx_mmc5_irqs[] = {
{ .irq = 59 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_mmc5_sdma_reqs[] = {
{ .name = "tx", .dma_req = 58 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 59 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
@@ -3673,6 +3912,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
.pa_end = 0x480d53ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> mmc5 */
@@ -3681,7 +3921,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc5 = {
.slave = &omap44xx_mmc5_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_mmc5_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_mmc5_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3693,14 +3932,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc5_slaves[] = {
static struct omap_hwmod omap44xx_mmc5_hwmod = {
.name = "mmc5",
.class = &omap44xx_mmc_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mmc5_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mmc5_irqs),
.sdma_reqs = omap44xx_mmc5_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mmc5_sdma_reqs),
.main_clk = "mmc5_fck",
- .prcm = {
+ .prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_MMCSD5_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_mmc5_slaves,
@@ -3722,6 +3962,7 @@ static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
{ .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
{ .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
{ .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
/* mpu master ports */
@@ -3734,13 +3975,14 @@ static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
static struct omap_hwmod omap44xx_mpu_hwmod = {
.name = "mpu",
.class = &omap44xx_mpu_hwmod_class,
- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+ .clkdm_name = "mpuss_clkdm",
+ .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
.mpu_irqs = omap44xx_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mpu_irqs),
.main_clk = "dpll_mpu_m2_ck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
},
},
.masters = omap44xx_mpu_masters,
@@ -3778,6 +4020,7 @@ static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = {
static struct omap_hwmod omap44xx_smartreflex_core_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = {
{ .irq = 19 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
@@ -3786,6 +4029,7 @@ static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
.pa_end = 0x4a0dd03f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> smartreflex_core */
@@ -3794,7 +4038,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = {
.slave = &omap44xx_smartreflex_core_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_smartreflex_core_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3806,13 +4049,16 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
.name = "smartreflex_core",
.class = &omap44xx_smartreflex_hwmod_class,
+ .clkdm_name = "l4_ao_clkdm",
.mpu_irqs = omap44xx_smartreflex_core_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_irqs),
+
.main_clk = "smartreflex_core_fck",
.vdd_name = "core",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ALWON_SR_CORE_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_smartreflex_core_slaves,
@@ -3824,6 +4070,7 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
static struct omap_hwmod omap44xx_smartreflex_iva_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = {
{ .irq = 102 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
@@ -3832,6 +4079,7 @@ static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
.pa_end = 0x4a0db03f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> smartreflex_iva */
@@ -3840,7 +4088,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = {
.slave = &omap44xx_smartreflex_iva_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_smartreflex_iva_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3852,13 +4099,15 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
.name = "smartreflex_iva",
.class = &omap44xx_smartreflex_hwmod_class,
+ .clkdm_name = "l4_ao_clkdm",
.mpu_irqs = omap44xx_smartreflex_iva_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_irqs),
.main_clk = "smartreflex_iva_fck",
.vdd_name = "iva",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ALWON_SR_IVA_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_smartreflex_iva_slaves,
@@ -3870,6 +4119,7 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = {
{ .irq = 18 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
@@ -3878,6 +4128,7 @@ static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
.pa_end = 0x4a0d903f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> smartreflex_mpu */
@@ -3886,7 +4137,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = {
.slave = &omap44xx_smartreflex_mpu_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_smartreflex_mpu_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3898,13 +4148,15 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
.name = "smartreflex_mpu",
.class = &omap44xx_smartreflex_hwmod_class,
+ .clkdm_name = "l4_ao_clkdm",
.mpu_irqs = omap44xx_smartreflex_mpu_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_irqs),
.main_clk = "smartreflex_mpu_fck",
.vdd_name = "mpu",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ALWON_SR_MPU_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_smartreflex_mpu_slaves,
@@ -3943,6 +4195,7 @@ static struct omap_hwmod_addr_space omap44xx_spinlock_addrs[] = {
.pa_end = 0x4a0f6fff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> spinlock */
@@ -3951,7 +4204,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__spinlock = {
.slave = &omap44xx_spinlock_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_spinlock_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_spinlock_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -3963,9 +4215,11 @@ static struct omap_hwmod_ocp_if *omap44xx_spinlock_slaves[] = {
static struct omap_hwmod omap44xx_spinlock_hwmod = {
.name = "spinlock",
.class = &omap44xx_spinlock_hwmod_class,
+ .clkdm_name = "l4_cfg_clkdm",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4CFG_HW_SEM_CONTEXT_OFFSET,
},
},
.slaves = omap44xx_spinlock_slaves,
@@ -4015,6 +4269,7 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
static struct omap_hwmod omap44xx_timer1_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
{ .irq = 37 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
@@ -4023,6 +4278,7 @@ static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
.pa_end = 0x4a31807f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> timer1 */
@@ -4031,7 +4287,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__timer1 = {
.slave = &omap44xx_timer1_hwmod,
.clk = "l4_wkup_clk_mux_ck",
.addr = omap44xx_timer1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4043,12 +4298,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer1_slaves[] = {
static struct omap_hwmod omap44xx_timer1_hwmod = {
.name = "timer1",
.class = &omap44xx_timer_1ms_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
.mpu_irqs = omap44xx_timer1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer1_irqs),
.main_clk = "timer1_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_WKUP_TIMER1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_WKUP_TIMER1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer1_slaves,
@@ -4060,6 +4317,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
static struct omap_hwmod omap44xx_timer2_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer2_irqs[] = {
{ .irq = 38 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
@@ -4068,6 +4326,7 @@ static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
.pa_end = 0x4803207f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer2 */
@@ -4076,7 +4335,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer2 = {
.slave = &omap44xx_timer2_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4088,12 +4346,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer2_slaves[] = {
static struct omap_hwmod omap44xx_timer2_hwmod = {
.name = "timer2",
.class = &omap44xx_timer_1ms_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_timer2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer2_irqs),
.main_clk = "timer2_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_DMTIMER2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer2_slaves,
@@ -4105,6 +4365,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
static struct omap_hwmod omap44xx_timer3_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer3_irqs[] = {
{ .irq = 39 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
@@ -4113,6 +4374,7 @@ static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
.pa_end = 0x4803407f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer3 */
@@ -4121,7 +4383,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer3 = {
.slave = &omap44xx_timer3_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_timer3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4133,12 +4394,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer3_slaves[] = {
static struct omap_hwmod omap44xx_timer3_hwmod = {
.name = "timer3",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_timer3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer3_irqs),
.main_clk = "timer3_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_DMTIMER3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer3_slaves,
@@ -4150,6 +4413,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
static struct omap_hwmod omap44xx_timer4_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer4_irqs[] = {
{ .irq = 40 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
@@ -4158,6 +4422,7 @@ static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
.pa_end = 0x4803607f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer4 */
@@ -4166,7 +4431,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer4 = {
.slave = &omap44xx_timer4_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_timer4_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4178,12 +4442,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer4_slaves[] = {
static struct omap_hwmod omap44xx_timer4_hwmod = {
.name = "timer4",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_timer4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer4_irqs),
.main_clk = "timer4_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_DMTIMER4_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer4_slaves,
@@ -4195,6 +4461,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
static struct omap_hwmod omap44xx_timer5_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer5_irqs[] = {
{ .irq = 41 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
@@ -4203,6 +4470,7 @@ static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
.pa_end = 0x4013807f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer5 */
@@ -4211,7 +4479,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5 = {
.slave = &omap44xx_timer5_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer5_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer5_addrs),
.user = OCP_USER_MPU,
};
@@ -4221,6 +4488,7 @@ static struct omap_hwmod_addr_space omap44xx_timer5_dma_addrs[] = {
.pa_end = 0x4903807f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer5 (dma) */
@@ -4229,7 +4497,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5_dma = {
.slave = &omap44xx_timer5_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer5_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer5_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -4242,12 +4509,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer5_slaves[] = {
static struct omap_hwmod omap44xx_timer5_hwmod = {
.name = "timer5",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_timer5_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer5_irqs),
.main_clk = "timer5_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_TIMER5_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer5_slaves,
@@ -4259,6 +4528,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
static struct omap_hwmod omap44xx_timer6_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer6_irqs[] = {
{ .irq = 42 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
@@ -4267,6 +4537,7 @@ static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
.pa_end = 0x4013a07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer6 */
@@ -4275,7 +4546,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6 = {
.slave = &omap44xx_timer6_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer6_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer6_addrs),
.user = OCP_USER_MPU,
};
@@ -4285,6 +4555,7 @@ static struct omap_hwmod_addr_space omap44xx_timer6_dma_addrs[] = {
.pa_end = 0x4903a07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer6 (dma) */
@@ -4293,7 +4564,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6_dma = {
.slave = &omap44xx_timer6_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer6_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer6_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -4306,12 +4576,15 @@ static struct omap_hwmod_ocp_if *omap44xx_timer6_slaves[] = {
static struct omap_hwmod omap44xx_timer6_hwmod = {
.name = "timer6",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_timer6_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer6_irqs),
+
.main_clk = "timer6_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_TIMER6_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer6_slaves,
@@ -4323,6 +4596,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
static struct omap_hwmod omap44xx_timer7_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer7_irqs[] = {
{ .irq = 43 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
@@ -4331,6 +4605,7 @@ static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
.pa_end = 0x4013c07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer7 */
@@ -4339,7 +4614,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7 = {
.slave = &omap44xx_timer7_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer7_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer7_addrs),
.user = OCP_USER_MPU,
};
@@ -4349,6 +4623,7 @@ static struct omap_hwmod_addr_space omap44xx_timer7_dma_addrs[] = {
.pa_end = 0x4903c07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer7 (dma) */
@@ -4357,7 +4632,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7_dma = {
.slave = &omap44xx_timer7_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer7_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer7_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -4370,12 +4644,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer7_slaves[] = {
static struct omap_hwmod omap44xx_timer7_hwmod = {
.name = "timer7",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_timer7_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer7_irqs),
.main_clk = "timer7_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_TIMER7_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer7_slaves,
@@ -4387,6 +4663,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
static struct omap_hwmod omap44xx_timer8_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer8_irqs[] = {
{ .irq = 44 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
@@ -4395,6 +4672,7 @@ static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
.pa_end = 0x4013e07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer8 */
@@ -4403,7 +4681,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8 = {
.slave = &omap44xx_timer8_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer8_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer8_addrs),
.user = OCP_USER_MPU,
};
@@ -4413,6 +4690,7 @@ static struct omap_hwmod_addr_space omap44xx_timer8_dma_addrs[] = {
.pa_end = 0x4903e07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> timer8 (dma) */
@@ -4421,7 +4699,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8_dma = {
.slave = &omap44xx_timer8_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_timer8_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer8_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -4434,12 +4711,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer8_slaves[] = {
static struct omap_hwmod omap44xx_timer8_hwmod = {
.name = "timer8",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_timer8_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer8_irqs),
.main_clk = "timer8_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_TIMER8_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer8_slaves,
@@ -4451,6 +4730,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
static struct omap_hwmod omap44xx_timer9_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer9_irqs[] = {
{ .irq = 45 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
@@ -4459,6 +4739,7 @@ static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
.pa_end = 0x4803e07f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer9 */
@@ -4467,7 +4748,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer9 = {
.slave = &omap44xx_timer9_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_timer9_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer9_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4479,12 +4759,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer9_slaves[] = {
static struct omap_hwmod omap44xx_timer9_hwmod = {
.name = "timer9",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_timer9_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer9_irqs),
.main_clk = "timer9_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_DMTIMER9_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer9_slaves,
@@ -4496,6 +4778,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
static struct omap_hwmod omap44xx_timer10_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer10_irqs[] = {
{ .irq = 46 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
@@ -4504,6 +4787,7 @@ static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
.pa_end = 0x4808607f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer10 */
@@ -4512,7 +4796,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer10 = {
.slave = &omap44xx_timer10_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_timer10_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer10_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4524,12 +4807,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer10_slaves[] = {
static struct omap_hwmod omap44xx_timer10_hwmod = {
.name = "timer10",
.class = &omap44xx_timer_1ms_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_timer10_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer10_irqs),
.main_clk = "timer10_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_DMTIMER10_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer10_slaves,
@@ -4541,6 +4826,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
static struct omap_hwmod omap44xx_timer11_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer11_irqs[] = {
{ .irq = 47 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
@@ -4549,6 +4835,7 @@ static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
.pa_end = 0x4808807f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> timer11 */
@@ -4557,7 +4844,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer11 = {
.slave = &omap44xx_timer11_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_timer11_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_timer11_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4569,12 +4855,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer11_slaves[] = {
static struct omap_hwmod omap44xx_timer11_hwmod = {
.name = "timer11",
.class = &omap44xx_timer_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_timer11_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_timer11_irqs),
.main_clk = "timer11_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_DMTIMER11_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_timer11_slaves,
@@ -4608,11 +4896,13 @@ static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
static struct omap_hwmod omap44xx_uart1_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart1_irqs[] = {
{ .irq = 72 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_uart1_sdma_reqs[] = {
{ .name = "tx", .dma_req = 48 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 49 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
@@ -4621,6 +4911,7 @@ static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
.pa_end = 0x4806a0ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> uart1 */
@@ -4629,7 +4920,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
.slave = &omap44xx_uart1_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_uart1_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_uart1_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4641,14 +4931,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
static struct omap_hwmod omap44xx_uart1_hwmod = {
.name = "uart1",
.class = &omap44xx_uart_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_uart1_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart1_irqs),
.sdma_reqs = omap44xx_uart1_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart1_sdma_reqs),
.main_clk = "uart1_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_UART1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_uart1_slaves,
@@ -4660,11 +4951,13 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
static struct omap_hwmod omap44xx_uart2_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart2_irqs[] = {
{ .irq = 73 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_uart2_sdma_reqs[] = {
{ .name = "tx", .dma_req = 50 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 51 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
@@ -4673,6 +4966,7 @@ static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
.pa_end = 0x4806c0ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> uart2 */
@@ -4681,7 +4975,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
.slave = &omap44xx_uart2_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_uart2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_uart2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4693,14 +4986,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
static struct omap_hwmod omap44xx_uart2_hwmod = {
.name = "uart2",
.class = &omap44xx_uart_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_uart2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart2_irqs),
.sdma_reqs = omap44xx_uart2_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart2_sdma_reqs),
.main_clk = "uart2_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_UART2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_uart2_slaves,
@@ -4712,11 +5006,13 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
static struct omap_hwmod omap44xx_uart3_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart3_irqs[] = {
{ .irq = 74 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_uart3_sdma_reqs[] = {
{ .name = "tx", .dma_req = 52 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 53 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
@@ -4725,6 +5021,7 @@ static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
.pa_end = 0x480200ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> uart3 */
@@ -4733,7 +5030,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
.slave = &omap44xx_uart3_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_uart3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_uart3_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4745,15 +5041,16 @@ static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
static struct omap_hwmod omap44xx_uart3_hwmod = {
.name = "uart3",
.class = &omap44xx_uart_hwmod_class,
- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+ .clkdm_name = "l4_per_clkdm",
+ .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
.mpu_irqs = omap44xx_uart3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart3_irqs),
.sdma_reqs = omap44xx_uart3_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart3_sdma_reqs),
.main_clk = "uart3_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_UART3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_uart3_slaves,
@@ -4765,11 +5062,13 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
static struct omap_hwmod omap44xx_uart4_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart4_irqs[] = {
{ .irq = 70 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_dma_info omap44xx_uart4_sdma_reqs[] = {
{ .name = "tx", .dma_req = 54 + OMAP44XX_DMA_REQ_START },
{ .name = "rx", .dma_req = 55 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
};
static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
@@ -4778,6 +5077,7 @@ static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
.pa_end = 0x4806e0ff,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_per -> uart4 */
@@ -4786,7 +5086,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
.slave = &omap44xx_uart4_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_uart4_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_uart4_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4798,14 +5097,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
static struct omap_hwmod omap44xx_uart4_hwmod = {
.name = "uart4",
.class = &omap44xx_uart_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_uart4_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart4_irqs),
.sdma_reqs = omap44xx_uart4_sdma_reqs,
- .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart4_sdma_reqs),
.main_clk = "uart4_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_UART4_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_uart4_slaves,
@@ -4832,14 +5132,15 @@ static struct omap_hwmod_class_sysconfig omap44xx_usb_otg_hs_sysc = {
};
static struct omap_hwmod_class omap44xx_usb_otg_hs_hwmod_class = {
- .name = "usb_otg_hs",
- .sysc = &omap44xx_usb_otg_hs_sysc,
+ .name = "usb_otg_hs",
+ .sysc = &omap44xx_usb_otg_hs_sysc,
};
/* usb_otg_hs */
static struct omap_hwmod_irq_info omap44xx_usb_otg_hs_irqs[] = {
{ .name = "mc", .irq = 92 + OMAP44XX_IRQ_GIC_START },
{ .name = "dma", .irq = 93 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
/* usb_otg_hs master ports */
@@ -4853,6 +5154,7 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
.pa_end = 0x4a0ab003,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_cfg -> usb_otg_hs */
@@ -4861,7 +5163,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_otg_hs = {
.slave = &omap44xx_usb_otg_hs_hwmod,
.clk = "l4_div_ck",
.addr = omap44xx_usb_otg_hs_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4877,17 +5178,19 @@ static struct omap_hwmod_opt_clk usb_otg_hs_opt_clks[] = {
static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
.name = "usb_otg_hs",
.class = &omap44xx_usb_otg_hs_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
.flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
.mpu_irqs = omap44xx_usb_otg_hs_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_irqs),
.main_clk = "usb_otg_hs_ick",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_USB_OTG_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
},
},
.opt_clks = usb_otg_hs_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(usb_otg_hs_opt_clks),
+ .opt_clks_cnt = ARRAY_SIZE(usb_otg_hs_opt_clks),
.slaves = omap44xx_usb_otg_hs_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
.masters = omap44xx_usb_otg_hs_masters,
@@ -4922,6 +5225,7 @@ static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
static struct omap_hwmod omap44xx_wd_timer2_hwmod;
static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
{ .irq = 80 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
@@ -4930,6 +5234,7 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
.pa_end = 0x4a31407f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_wkup -> wd_timer2 */
@@ -4938,7 +5243,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
.slave = &omap44xx_wd_timer2_hwmod,
.clk = "l4_wkup_clk_mux_ck",
.addr = omap44xx_wd_timer2_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_wd_timer2_addrs),
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
@@ -4950,12 +5254,14 @@ static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
.name = "wd_timer2",
.class = &omap44xx_wd_timer_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
.mpu_irqs = omap44xx_wd_timer2_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_wd_timer2_irqs),
.main_clk = "wd_timer2_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM_WKUP_WDT2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_WKUP_WDT2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_wd_timer2_slaves,
@@ -4967,6 +5273,7 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
static struct omap_hwmod omap44xx_wd_timer3_hwmod;
static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
{ .irq = 36 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
@@ -4975,6 +5282,7 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
.pa_end = 0x4013007f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> wd_timer3 */
@@ -4983,7 +5291,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
.slave = &omap44xx_wd_timer3_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_wd_timer3_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_wd_timer3_addrs),
.user = OCP_USER_MPU,
};
@@ -4993,6 +5300,7 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
.pa_end = 0x4903007f,
.flags = ADDR_TYPE_RT
},
+ { }
};
/* l4_abe -> wd_timer3 (dma) */
@@ -5001,7 +5309,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
.slave = &omap44xx_wd_timer3_hwmod,
.clk = "ocp_abe_iclk",
.addr = omap44xx_wd_timer3_dma_addrs,
- .addr_cnt = ARRAY_SIZE(omap44xx_wd_timer3_dma_addrs),
.user = OCP_USER_SDMA,
};
@@ -5014,12 +5321,14 @@ static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
.name = "wd_timer3",
.class = &omap44xx_wd_timer_hwmod_class,
+ .clkdm_name = "abe_clkdm",
.mpu_irqs = omap44xx_wd_timer3_irqs,
- .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_wd_timer3_irqs),
.main_clk = "wd_timer3_fck",
.prcm = {
.omap4 = {
- .clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+ .clkctrl_offs = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_WDT3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
.slaves = omap44xx_wd_timer3_slaves,
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c
index 08a134243ecb..de832ebc93a9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c
@@ -49,23 +49,3 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = {
.srst_shift = SYSC_TYPE2_SOFTRESET_SHIFT,
};
-
-/*
- * omap_hwmod class data
- */
-
-struct omap_hwmod_class l3_hwmod_class = {
- .name = "l3"
-};
-
-struct omap_hwmod_class l4_hwmod_class = {
- .name = "l4"
-};
-
-struct omap_hwmod_class mpu_hwmod_class = {
- .name = "mpu"
-};
-
-struct omap_hwmod_class iva_hwmod_class = {
- .name = "iva"
-};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index c34e98bf1242..39a7c37f4587 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -1,10 +1,10 @@
/*
* omap_hwmod_common_data.h - OMAP hwmod common macros and declarations
*
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010-2011 Nokia Corporation
* Paul Walmsley
*
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
* Benoît Cousson
*
* This program is free software; you can redistribute it and/or modify
@@ -16,10 +16,99 @@
#include <plat/omap_hwmod.h>
+/* Common address space across OMAP2xxx */
+extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[];
+extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[];
+extern struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[];
+extern struct omap_hwmod_addr_space omap2xxx_timer2_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer3_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer4_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer5_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer6_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer7_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer8_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer9_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer12_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[];
+
+/* Common address space across OMAP2xxx/3xxx */
+extern struct omap_hwmod_addr_space omap2_i2c1_addr_space[];
+extern struct omap_hwmod_addr_space omap2_i2c2_addr_space[];
+extern struct omap_hwmod_addr_space omap2_dss_addrs[];
+extern struct omap_hwmod_addr_space omap2_dss_dispc_addrs[];
+extern struct omap_hwmod_addr_space omap2_dss_rfbi_addrs[];
+extern struct omap_hwmod_addr_space omap2_dss_venc_addrs[];
+extern struct omap_hwmod_addr_space omap2_timer10_addrs[];
+extern struct omap_hwmod_addr_space omap2_timer11_addrs[];
+extern struct omap_hwmod_addr_space omap2430_mmc1_addr_space[];
+extern struct omap_hwmod_addr_space omap2430_mmc2_addr_space[];
+extern struct omap_hwmod_addr_space omap2_mcspi1_addr_space[];
+extern struct omap_hwmod_addr_space omap2_mcspi2_addr_space[];
+extern struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[];
+extern struct omap_hwmod_addr_space omap2_dma_system_addrs[];
+extern struct omap_hwmod_addr_space omap2_mailbox_addrs[];
+extern struct omap_hwmod_addr_space omap2_mcbsp1_addrs[];
+
+/* Common IP block data across OMAP2xxx */
+extern struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[];
+extern struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[];
+
+/* Common IP block data */
+extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_uart2_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_uart3_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_i2c1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_i2c2_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcspi1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcspi2_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcbsp1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcbsp2_sdma_reqs[];
+
+/* Common IP block data on OMAP2430/OMAP3 */
+extern struct omap_hwmod_dma_info omap2_mcbsp3_sdma_reqs[];
+
+/* Common IP block data across OMAP2/3 */
+extern struct omap_hwmod_irq_info omap2_timer1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer2_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer3_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer4_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer5_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer6_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer7_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer8_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer9_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer10_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer11_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_uart1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_uart2_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_dispc_irqs[];
+extern struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio1_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio2_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio3_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio4_irqs[];
+extern struct omap_hwmod_irq_info omap2_dma_system_irqs[];
+extern struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[];
+
/* OMAP hwmod classes - forward declarations */
extern struct omap_hwmod_class l3_hwmod_class;
extern struct omap_hwmod_class l4_hwmod_class;
extern struct omap_hwmod_class mpu_hwmod_class;
extern struct omap_hwmod_class iva_hwmod_class;
+extern struct omap_hwmod_class omap2_uart_class;
+extern struct omap_hwmod_class omap2_dss_hwmod_class;
+extern struct omap_hwmod_class omap2_dispc_hwmod_class;
+extern struct omap_hwmod_class omap2_rfbi_hwmod_class;
+extern struct omap_hwmod_class omap2_venc_hwmod_class;
+
+extern struct omap_hwmod_class omap2xxx_timer_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_gpio_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_dma_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_mcspi_class;
#endif
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index e01da45c0537..4411163e012d 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -38,155 +38,12 @@
#include "prm2xxx_3xxx.h"
#include "pm.h"
-int omap2_pm_debug;
u32 enable_off_mode;
-u32 sleep_while_idle;
-u32 wakeup_timer_seconds;
-u32 wakeup_timer_milliseconds;
-
-#define DUMP_PRM_MOD_REG(mod, reg) \
- regs[reg_count].name = #mod "." #reg; \
- regs[reg_count++].val = omap2_prm_read_mod_reg(mod, reg)
-#define DUMP_CM_MOD_REG(mod, reg) \
- regs[reg_count].name = #mod "." #reg; \
- regs[reg_count++].val = omap2_cm_read_mod_reg(mod, reg)
-#define DUMP_PRM_REG(reg) \
- regs[reg_count].name = #reg; \
- regs[reg_count++].val = __raw_readl(reg)
-#define DUMP_CM_REG(reg) \
- regs[reg_count].name = #reg; \
- regs[reg_count++].val = __raw_readl(reg)
-#define DUMP_INTC_REG(reg, off) \
- regs[reg_count].name = #reg; \
- regs[reg_count++].val = \
- __raw_readl(OMAP2_L4_IO_ADDRESS(0x480fe000 + (off)))
-
-void omap2_pm_dump(int mode, int resume, unsigned int us)
-{
- struct reg {
- const char *name;
- u32 val;
- } regs[32];
- int reg_count = 0, i;
- const char *s1 = NULL, *s2 = NULL;
-
- if (!resume) {
-#if 0
- /* MPU */
- DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
- DUMP_CM_MOD_REG(MPU_MOD, OMAP2_CM_CLKSTCTRL);
- DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTCTRL);
- DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTST);
- DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
-#endif
-#if 0
- /* INTC */
- DUMP_INTC_REG(INTC_MIR0, 0x0084);
- DUMP_INTC_REG(INTC_MIR1, 0x00a4);
- DUMP_INTC_REG(INTC_MIR2, 0x00c4);
-#endif
-#if 0
- DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
- if (cpu_is_omap24xx()) {
- DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
- DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
- OMAP2_PRCM_CLKEMUL_CTRL_OFFSET);
- DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
- OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
- }
- DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
- DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
- DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
- DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
- DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
- DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
- DUMP_PRM_MOD_REG(CORE_MOD, OMAP2_PM_PWSTST);
-#endif
-#if 0
- /* DSP */
- if (cpu_is_omap24xx()) {
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_CM_CLKSTCTRL);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTCTRL);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTST);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTCTRL);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTST);
- }
-#endif
- } else {
- DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
- if (cpu_is_omap24xx())
- DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
- DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
- DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
-#if 1
- DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
- DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
- DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
-#endif
- }
-
- switch (mode) {
- case 0:
- s1 = "full";
- s2 = "retention";
- break;
- case 1:
- s1 = "MPU";
- s2 = "retention";
- break;
- case 2:
- s1 = "MPU";
- s2 = "idle";
- break;
- }
-
- if (!resume)
-#ifdef CONFIG_NO_HZ
- printk(KERN_INFO
- "--- Going to %s %s (next timer after %u ms)\n", s1, s2,
- jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
- jiffies));
-#else
- printk(KERN_INFO "--- Going to %s %s\n", s1, s2);
-#endif
- else
- printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n",
- us / 1000, us % 1000);
-
- for (i = 0; i < reg_count; i++)
- printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
-}
-
-void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
- u32 tick_rate, cycles;
-
- if (!seconds && !milliseconds)
- return;
-
- tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
- cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
- omap_dm_timer_stop(gptimer_wakeup);
- omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
- pr_info("PM: Resume timer in %u.%03u secs"
- " (%d ticks at %d ticks/sec.)\n",
- seconds, milliseconds, cycles, tick_rate);
-}
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-static void pm_dbg_regset_store(u32 *ptr);
-
-static struct dentry *pm_dbg_dir;
-
static int pm_dbg_init_done;
static int pm_dbg_init(void);
@@ -196,160 +53,6 @@ enum {
DEBUG_FILE_TIMERS,
};
-struct pm_module_def {
- char name[8]; /* Name of the module */
- short type; /* CM or PRM */
- unsigned short offset;
- int low; /* First register address on this module */
- int high; /* Last register address on this module */
-};
-
-#define MOD_CM 0
-#define MOD_PRM 1
-
-static const struct pm_module_def *pm_dbg_reg_modules;
-static const struct pm_module_def omap3_pm_reg_modules[] = {
- { "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c },
- { "OCP", MOD_CM, OCP_MOD, 0, 0x10 },
- { "MPU", MOD_CM, MPU_MOD, 4, 0x4c },
- { "CORE", MOD_CM, CORE_MOD, 0, 0x4c },
- { "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c },
- { "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 },
- { "CCR", MOD_CM, PLL_MOD, 0, 0x70 },
- { "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c },
- { "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c },
- { "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c },
- { "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 },
- { "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 },
- { "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c },
-
- { "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc },
- { "OCP", MOD_PRM, OCP_MOD, 4, 0x1c },
- { "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 },
- { "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 },
- { "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 },
- { "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 },
- { "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 },
- { "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 },
- { "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 },
- { "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 },
- { "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 },
- { "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 },
- { "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 },
- { "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 },
- { "", 0, 0, 0, 0 },
-};
-
-#define PM_DBG_MAX_REG_SETS 4
-
-static void *pm_dbg_reg_set[PM_DBG_MAX_REG_SETS];
-
-static int pm_dbg_get_regset_size(void)
-{
- static int regset_size;
-
- if (regset_size == 0) {
- int i = 0;
-
- while (pm_dbg_reg_modules[i].name[0] != 0) {
- regset_size += pm_dbg_reg_modules[i].high +
- 4 - pm_dbg_reg_modules[i].low;
- i++;
- }
- }
- return regset_size;
-}
-
-static int pm_dbg_show_regs(struct seq_file *s, void *unused)
-{
- int i, j;
- unsigned long val;
- int reg_set = (int)s->private;
- u32 *ptr;
- void *store = NULL;
- int regs;
- int linefeed;
-
- if (reg_set == 0) {
- store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
- ptr = store;
- pm_dbg_regset_store(ptr);
- } else {
- ptr = pm_dbg_reg_set[reg_set - 1];
- }
-
- i = 0;
-
- while (pm_dbg_reg_modules[i].name[0] != 0) {
- regs = 0;
- linefeed = 0;
- if (pm_dbg_reg_modules[i].type == MOD_CM)
- seq_printf(s, "MOD: CM_%s (%08x)\n",
- pm_dbg_reg_modules[i].name,
- (u32)(OMAP3430_CM_BASE +
- pm_dbg_reg_modules[i].offset));
- else
- seq_printf(s, "MOD: PRM_%s (%08x)\n",
- pm_dbg_reg_modules[i].name,
- (u32)(OMAP3430_PRM_BASE +
- pm_dbg_reg_modules[i].offset));
-
- for (j = pm_dbg_reg_modules[i].low;
- j <= pm_dbg_reg_modules[i].high; j += 4) {
- val = *(ptr++);
- if (val != 0) {
- regs++;
- if (linefeed) {
- seq_printf(s, "\n");
- linefeed = 0;
- }
- seq_printf(s, " %02x => %08lx", j, val);
- if (regs % 4 == 0)
- linefeed = 1;
- }
- }
- seq_printf(s, "\n");
- i++;
- }
-
- if (store != NULL)
- kfree(store);
-
- return 0;
-}
-
-static void pm_dbg_regset_store(u32 *ptr)
-{
- int i, j;
- u32 val;
-
- i = 0;
-
- while (pm_dbg_reg_modules[i].name[0] != 0) {
- for (j = pm_dbg_reg_modules[i].low;
- j <= pm_dbg_reg_modules[i].high; j += 4) {
- if (pm_dbg_reg_modules[i].type == MOD_CM)
- val = omap2_cm_read_mod_reg(
- pm_dbg_reg_modules[i].offset, j);
- else
- val = omap2_prm_read_mod_reg(
- pm_dbg_reg_modules[i].offset, j);
- *(ptr++) = val;
- }
- i++;
- }
-}
-
-int pm_dbg_regset_save(int reg_set)
-{
- if (pm_dbg_reg_set[reg_set-1] == NULL)
- return -EINVAL;
-
- pm_dbg_regset_store(pm_dbg_reg_set[reg_set-1]);
-
- return 0;
-}
-
static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
"OFF",
"RET",
@@ -469,11 +172,6 @@ static int pm_dbg_open(struct inode *inode, struct file *file)
};
}
-static int pm_dbg_reg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pm_dbg_show_regs, inode->i_private);
-}
-
static const struct file_operations debug_fops = {
.open = pm_dbg_open,
.read = seq_read,
@@ -481,40 +179,6 @@ static const struct file_operations debug_fops = {
.release = single_release,
};
-static const struct file_operations debug_reg_fops = {
- .open = pm_dbg_reg_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-int pm_dbg_regset_init(int reg_set)
-{
- char name[2];
-
- if (!pm_dbg_init_done)
- pm_dbg_init();
-
- if (reg_set < 1 || reg_set > PM_DBG_MAX_REG_SETS ||
- pm_dbg_reg_set[reg_set-1] != NULL)
- return -EINVAL;
-
- pm_dbg_reg_set[reg_set-1] =
- kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
-
- if (pm_dbg_reg_set[reg_set-1] == NULL)
- return -ENOMEM;
-
- if (pm_dbg_dir != NULL) {
- sprintf(name, "%d", reg_set);
-
- (void) debugfs_create_file(name, S_IRUGO,
- pm_dbg_dir, (void *)reg_set, &debug_reg_fops);
- }
-
- return 0;
-}
-
static int pwrdm_suspend_get(void *data, u64 *val)
{
int ret = -EINVAL;
@@ -576,9 +240,6 @@ static int option_set(void *data, u64 val)
{
u32 *option = data;
- if (option == &wakeup_timer_milliseconds && val >= 1000)
- return -EINVAL;
-
*option = val;
if (option == &enable_off_mode) {
@@ -595,22 +256,13 @@ static int option_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
-static int pm_dbg_init(void)
+static int __init pm_dbg_init(void)
{
- int i;
struct dentry *d;
- char name[2];
if (pm_dbg_init_done)
return 0;
- if (cpu_is_omap34xx())
- pm_dbg_reg_modules = omap3_pm_reg_modules;
- else {
- printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
- return -ENODEV;
- }
-
d = debugfs_create_dir("pm_debug", NULL);
if (IS_ERR(d))
return PTR_ERR(d);
@@ -622,30 +274,8 @@ static int pm_dbg_init(void)
pwrdm_for_each(pwrdms_setup, (void *)d);
- pm_dbg_dir = debugfs_create_dir("registers", d);
- if (IS_ERR(pm_dbg_dir))
- return PTR_ERR(pm_dbg_dir);
-
- (void) debugfs_create_file("current", S_IRUGO,
- pm_dbg_dir, (void *)0, &debug_reg_fops);
-
- for (i = 0; i < PM_DBG_MAX_REG_SETS; i++)
- if (pm_dbg_reg_set[i] != NULL) {
- sprintf(name, "%d", i+1);
- (void) debugfs_create_file(name, S_IRUGO,
- pm_dbg_dir, (void *)(i+1), &debug_reg_fops);
-
- }
-
(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
&enable_off_mode, &pm_dbg_option_fops);
- (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUSR, d,
- &sleep_while_idle, &pm_dbg_option_fops);
- (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d,
- &wakeup_timer_seconds, &pm_dbg_option_fops);
- (void) debugfs_create_file("wakeup_timer_milliseconds",
- S_IRUGO | S_IWUSR, d, &wakeup_timer_milliseconds,
- &pm_dbg_option_fops);
pm_dbg_init_done = 1;
return 0;
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 49486f522dca..3feb35911a32 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -106,8 +106,9 @@ static void omap2_init_processor_devices(void)
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
{
u32 cur_state;
- int sleep_switch = 0;
+ int sleep_switch = -1;
int ret = 0;
+ int hwsup = 0;
if (pwrdm == NULL || IS_ERR(pwrdm))
return -EINVAL;
@@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
sleep_switch = LOWPOWERSTATE_SWITCH;
} else {
+ hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
pwrdm_wait_transition(pwrdm);
sleep_switch = FORCEWAKEUP_SWITCH;
@@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
switch (sleep_switch) {
case FORCEWAKEUP_SWITCH:
- if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
+ if (hwsup)
clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
else
clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce77352..4e166add2f35 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -60,46 +60,40 @@ inline void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
-extern u32 wakeup_timer_seconds;
-extern u32 wakeup_timer_milliseconds;
-extern struct omap_dm_timer *gptimer_wakeup;
-
#ifdef CONFIG_PM_DEBUG
-extern void omap2_pm_dump(int mode, int resume, unsigned int us);
-extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
-extern int omap2_pm_debug;
extern u32 enable_off_mode;
-extern u32 sleep_while_idle;
#else
-#define omap2_pm_dump(mode, resume, us) do {} while (0);
-#define omap2_pm_wakeup_on_timer(seconds, milliseconds) do {} while (0);
-#define omap2_pm_debug 0
#define enable_off_mode 0
-#define sleep_while_idle 0
#endif
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
-extern int pm_dbg_regset_save(int reg_set);
-extern int pm_dbg_regset_init(int reg_set);
#else
#define pm_dbg_update_time(pwrdm, prev) do {} while (0);
-#define pm_dbg_regset_save(reg_set) do {} while (0);
-#define pm_dbg_regset_init(reg_set) do {} while (0);
#endif /* CONFIG_PM_DEBUG */
+/* 24xx */
extern void omap24xx_idle_loop_suspend(void);
+extern unsigned int omap24xx_idle_loop_suspend_sz;
extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
-extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
-extern int save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
+extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap24xx_idle_loop_suspend_sz;
+/* 3xxx */
+extern void omap34xx_cpu_suspend(int save_state);
+
+/* omap3_do_wfi function pointer and size, for copy to SRAM */
+extern void omap3_do_wfi(void);
+extern unsigned int omap3_do_wfi_sz;
+/* ... and its pointer from SRAM after copy */
+extern void (*omap3_do_wfi_sram)(void);
+
+/* save_secure_ram_context function pointer and size, for copy to SRAM */
+extern int save_secure_ram_context(u32 *addr);
extern unsigned int save_secure_ram_context_sz;
-extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap34xx_cpu_suspend_sz;
+
+extern void omap3_save_scratchpad_contents(void);
#define PM_RTA_ERRATUM_i608 (1 << 0)
#define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1)
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index df3ded6fe194..bf089e743ed9 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -53,6 +53,8 @@
#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)
@@ -123,7 +125,6 @@ static void omap2_enter_full_retention(void)
omap2_gpio_prepare_for_idle(0);
if (omap2_pm_debug) {
- omap2_pm_dump(0, 0, 0);
getnstimeofday(&ts_preidle);
}
@@ -160,7 +161,6 @@ no_sleep:
getnstimeofday(&ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
- omap2_pm_dump(0, 1, tmp);
}
omap2_gpio_resume_after_idle();
@@ -247,7 +247,6 @@ static void omap2_enter_mpu_retention(void)
}
if (omap2_pm_debug) {
- omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
getnstimeofday(&ts_preidle);
}
@@ -259,7 +258,6 @@ static void omap2_enter_mpu_retention(void)
getnstimeofday(&ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
- omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
}
}
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c155c9d1c82c..7255d9bce868 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -31,6 +31,8 @@
#include <linux/console.h>
#include <trace/events/power.h>
+#include <asm/suspend.h>
+
#include <plat/sram.h>
#include "clockdomain.h"
#include "powerdomain.h"
@@ -40,8 +42,6 @@
#include <plat/gpmc.h>
#include <plat/dma.h>
-#include <asm/tlbflush.h>
-
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
#include "prm-regbits-34xx.h"
@@ -64,11 +64,6 @@ static inline bool is_suspending(void)
}
#endif
-/* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET 0xc4
-#define OMAP343X_TABLE_VALUE_OFFSET 0xc0
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET 0xc8
-
/* pm34xx errata defined in pm.h */
u16 pm34xx_errata;
@@ -83,9 +78,8 @@ struct power_state {
static LIST_HEAD(pwrst_list);
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
-
static int (*_omap_save_secure_sram)(u32 *addr);
+void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -312,28 +306,25 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
return IRQ_HANDLED;
}
-/* Function to restore the table entry that was modified for enabling MMU */
-static void restore_table_entry(void)
+static void omap34xx_save_context(u32 *save)
{
- void __iomem *scratchpad_address;
- u32 previous_value, control_reg_value;
- u32 *address;
+ u32 val;
- scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
+ /* Read Auxiliary Control Register */
+ asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
- /* Get address of entry that was modified */
- address = (u32 *)__raw_readl(scratchpad_address +
- OMAP343X_TABLE_ADDRESS_OFFSET);
- /* Get the previous value which needs to be restored */
- previous_value = __raw_readl(scratchpad_address +
- OMAP343X_TABLE_VALUE_OFFSET);
- address = __va(address);
- *address = previous_value;
- flush_tlb_all();
- control_reg_value = __raw_readl(scratchpad_address
- + OMAP343X_CONTROL_REG_VALUE_OFFSET);
- /* This will enable caches and prediction */
- set_cr(control_reg_value);
+ /* Read L2 AUX ctrl register */
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+}
+
+static int omap34xx_do_sram_idle(unsigned long save_state)
+{
+ omap34xx_cpu_suspend(save_state);
+ return 0;
}
void omap_sram_idle(void)
@@ -352,9 +343,6 @@ void omap_sram_idle(void)
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
- if (!_omap_sram_idle)
- return;
-
pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
pwrdm_clear_all_prev_pwrst(neon_pwrdm);
pwrdm_clear_all_prev_pwrst(core_pwrdm);
@@ -432,12 +420,16 @@ void omap_sram_idle(void)
sdrc_pwr = sdrc_read_reg(SDRC_POWER);
/*
- * omap3_arm_context is the location where ARM registers
- * get saved. The restore path then reads from this
- * location and restores them back.
+ * omap3_arm_context is the location where some ARM context
+ * get saved. The rest is placed on the stack, and restored
+ * from there before resuming.
*/
- _omap_sram_idle(omap3_arm_context, save_state);
- cpu_init();
+ if (save_state)
+ omap34xx_save_context(omap3_arm_context);
+ if (save_state == 1 || save_state == 3)
+ cpu_suspend(save_state, omap34xx_do_sram_idle);
+ else
+ omap34xx_do_sram_idle(save_state);
/* Restore normal SDRC POWER settings */
if (omap_rev() >= OMAP3430_REV_ES3_0 &&
@@ -445,10 +437,6 @@ void omap_sram_idle(void)
core_next_state == PWRDM_POWER_OFF)
sdrc_write_reg(sdrc_pwr, SDRC_POWER);
- /* Restore table entry modified during MMU restoration */
- if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
- restore_table_entry();
-
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
@@ -497,8 +485,6 @@ console_still_active:
int omap3_can_sleep(void)
{
- if (!sleep_while_idle)
- return 0;
if (!omap_uart_can_sleep())
return 0;
return 1;
@@ -534,10 +520,6 @@ static int omap3_pm_suspend(void)
struct power_state *pwrst;
int state, ret = 0;
- if (wakeup_timer_seconds || wakeup_timer_milliseconds)
- omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
- wakeup_timer_milliseconds);
-
/* Read current next_pwrsts */
list_for_each_entry(pwrst, &pwrst_list, node)
pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
@@ -852,10 +834,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
return 0;
}
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
void omap_push_sram_idle(void)
{
- _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
- omap34xx_cpu_suspend_sz);
+ omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
+
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
save_secure_ram_context_sz);
@@ -920,7 +909,6 @@ static int __init omap3_pm_init(void)
per_clkdm = clkdm_lookup("per_clkdm");
core_clkdm = clkdm_lookup("core_clkdm");
- omap_push_sram_idle();
#ifdef CONFIG_SUSPEND
suspend_set_ops(&omap_pm_ops);
#endif /* CONFIG_SUSPEND */
diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
index c4222c7036a5..247e79495115 100644
--- a/arch/arm/mach-omap2/powerdomains44xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP4 Power domains framework
*
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
* Copyright (C) 2009-2011 Nokia Corporation
*
* Abhijit Pagare (abhijitpagare@ti.com)
@@ -41,19 +41,19 @@ static struct powerdomain core_44xx_pwrdm = {
.banks = 5,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF, /* core_nret_bank */
- [1] = PWRSTS_OFF_RET, /* core_ocmram */
+ [1] = PWRSTS_RET, /* core_ocmram */
[2] = PWRSTS_RET, /* core_other_bank */
[3] = PWRSTS_OFF_RET, /* ducati_l2ram */
[4] = PWRSTS_OFF_RET, /* ducati_unicache */
},
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* core_nret_bank */
- [1] = PWRSTS_OFF_RET, /* core_ocmram */
+ [1] = PWRSTS_ON, /* core_ocmram */
[2] = PWRSTS_ON, /* core_other_bank */
[3] = PWRSTS_ON, /* ducati_l2ram */
[4] = PWRSTS_ON, /* ducati_unicache */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* gfx_44xx_pwrdm: 3D accelerator power domain */
@@ -70,7 +70,7 @@ static struct powerdomain gfx_44xx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* gfx_mem */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* abe_44xx_pwrdm: Audio back end power domain */
@@ -90,7 +90,7 @@ static struct powerdomain abe_44xx_pwrdm = {
[0] = PWRSTS_ON, /* aessmem */
[1] = PWRSTS_ON, /* periphmem */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* dss_44xx_pwrdm: Display subsystem power domain */
@@ -108,7 +108,7 @@ static struct powerdomain dss_44xx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* dss_mem */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* tesla_44xx_pwrdm: Tesla processor power domain */
@@ -130,7 +130,7 @@ static struct powerdomain tesla_44xx_pwrdm = {
[1] = PWRSTS_ON, /* tesla_l1 */
[2] = PWRSTS_ON, /* tesla_l2 */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* wkup_44xx_pwrdm: Wake-up power domain */
@@ -205,7 +205,7 @@ static struct powerdomain mpu_44xx_pwrdm = {
.prcm_offs = OMAP4430_PRM_MPU_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
- .pwrsts = PWRSTS_OFF_RET_ON,
+ .pwrsts = PWRSTS_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 3,
.pwrsts_mem_ret = {
@@ -241,7 +241,7 @@ static struct powerdomain ivahd_44xx_pwrdm = {
[2] = PWRSTS_ON, /* tcm1_mem */
[3] = PWRSTS_ON, /* tcm2_mem */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* cam_44xx_pwrdm: Camera subsystem power domain */
@@ -258,7 +258,7 @@ static struct powerdomain cam_44xx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* cam_mem */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* l3init_44xx_pwrdm: L3 initators pheripherals power domain */
@@ -276,7 +276,7 @@ static struct powerdomain l3init_44xx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* l3init_bank1 */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/* l4per_44xx_pwrdm: Target peripherals power domain */
@@ -296,7 +296,7 @@ static struct powerdomain l4per_44xx_pwrdm = {
[0] = PWRSTS_ON, /* nonretained_bank */
[1] = PWRSTS_ON, /* retained_bank */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/*
@@ -318,6 +318,7 @@ static struct powerdomain cefuse_44xx_pwrdm = {
.prcm_partition = OMAP4430_PRM_PARTITION,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
/*
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 6be14389e4f3..2e40a5cf0163 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -70,7 +70,7 @@ static void omap_prcm_arch_reset(char mode, const char *cmd)
prcm_offs = OMAP3430_GR_MOD;
omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
} else if (cpu_is_omap44xx()) {
- omap4_prm_global_warm_sw_reset(); /* never returns */
+ omap4_prminst_global_warm_sw_reset(); /* never returns */
} else {
WARN_ON(1);
}
diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h
index d22d1b43bccd..8a6e250f04b5 100644
--- a/arch/arm/mach-omap2/prcm_mpu44xx.h
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.h
@@ -31,7 +31,6 @@
OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE + (inst) + (reg))
/* PRCM_MPU instances */
-
#define OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST 0x0000
#define OMAP4430_PRCM_MPU_DEVICE_PRM_INST 0x0200
#define OMAP4430_PRCM_MPU_CPU0_INST 0x0400
@@ -52,46 +51,46 @@
*/
/* PRCM_MPU.OCP_SOCKET_PRCM register offsets */
-#define OMAP4_REVISION_PRCM_OFFSET 0x0000
-#define OMAP4430_REVISION_PRCM OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST, 0x0000)
+#define OMAP4_REVISION_PRCM_OFFSET 0x0000
+#define OMAP4430_REVISION_PRCM OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST, 0x0000)
/* PRCM_MPU.DEVICE_PRM register offsets */
-#define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET 0x0000
-#define OMAP4430_PRCM_MPU_PRM_RSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0000)
-#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET 0x0004
-#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0004)
+#define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET 0x0000
+#define OMAP4430_PRCM_MPU_PRM_RSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0000)
+#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET 0x0004
+#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0004)
/* PRCM_MPU.CPU0 register offsets */
-#define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET 0x0000
-#define OMAP4430_PM_CPU0_PWRSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0000)
-#define OMAP4_PM_CPU0_PWRSTST_OFFSET 0x0004
-#define OMAP4430_PM_CPU0_PWRSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0004)
-#define OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET 0x0008
-#define OMAP4430_RM_CPU0_CPU0_CONTEXT OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0008)
-#define OMAP4_RM_CPU0_CPU0_RSTCTRL_OFFSET 0x000c
-#define OMAP4430_RM_CPU0_CPU0_RSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x000c)
-#define OMAP4_RM_CPU0_CPU0_RSTST_OFFSET 0x0010
-#define OMAP4430_RM_CPU0_CPU0_RSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0010)
-#define OMAP4_CM_CPU0_CPU0_CLKCTRL_OFFSET 0x0014
-#define OMAP4430_CM_CPU0_CPU0_CLKCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0014)
-#define OMAP4_CM_CPU0_CLKSTCTRL_OFFSET 0x0018
-#define OMAP4430_CM_CPU0_CLKSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0018)
+#define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET 0x0000
+#define OMAP4430_PM_CPU0_PWRSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0000)
+#define OMAP4_PM_CPU0_PWRSTST_OFFSET 0x0004
+#define OMAP4430_PM_CPU0_PWRSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0004)
+#define OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET 0x0008
+#define OMAP4430_RM_CPU0_CPU0_CONTEXT OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0008)
+#define OMAP4_RM_CPU0_CPU0_RSTCTRL_OFFSET 0x000c
+#define OMAP4430_RM_CPU0_CPU0_RSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x000c)
+#define OMAP4_RM_CPU0_CPU0_RSTST_OFFSET 0x0010
+#define OMAP4430_RM_CPU0_CPU0_RSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0010)
+#define OMAP4_CM_CPU0_CPU0_CLKCTRL_OFFSET 0x0014
+#define OMAP4430_CM_CPU0_CPU0_CLKCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0014)
+#define OMAP4_CM_CPU0_CLKSTCTRL_OFFSET 0x0018
+#define OMAP4430_CM_CPU0_CLKSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0018)
/* PRCM_MPU.CPU1 register offsets */
-#define OMAP4_PM_CPU1_PWRSTCTRL_OFFSET 0x0000
-#define OMAP4430_PM_CPU1_PWRSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0000)
-#define OMAP4_PM_CPU1_PWRSTST_OFFSET 0x0004
-#define OMAP4430_PM_CPU1_PWRSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0004)
-#define OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET 0x0008
-#define OMAP4430_RM_CPU1_CPU1_CONTEXT OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0008)
-#define OMAP4_RM_CPU1_CPU1_RSTCTRL_OFFSET 0x000c
-#define OMAP4430_RM_CPU1_CPU1_RSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x000c)
-#define OMAP4_RM_CPU1_CPU1_RSTST_OFFSET 0x0010
-#define OMAP4430_RM_CPU1_CPU1_RSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0010)
-#define OMAP4_CM_CPU1_CPU1_CLKCTRL_OFFSET 0x0014
-#define OMAP4430_CM_CPU1_CPU1_CLKCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0014)
-#define OMAP4_CM_CPU1_CLKSTCTRL_OFFSET 0x0018
-#define OMAP4430_CM_CPU1_CLKSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0018)
+#define OMAP4_PM_CPU1_PWRSTCTRL_OFFSET 0x0000
+#define OMAP4430_PM_CPU1_PWRSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0000)
+#define OMAP4_PM_CPU1_PWRSTST_OFFSET 0x0004
+#define OMAP4430_PM_CPU1_PWRSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0004)
+#define OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET 0x0008
+#define OMAP4430_RM_CPU1_CPU1_CONTEXT OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0008)
+#define OMAP4_RM_CPU1_CPU1_RSTCTRL_OFFSET 0x000c
+#define OMAP4430_RM_CPU1_CPU1_RSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x000c)
+#define OMAP4_RM_CPU1_CPU1_RSTST_OFFSET 0x0010
+#define OMAP4430_RM_CPU1_CPU1_RSTST OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0010)
+#define OMAP4_CM_CPU1_CPU1_CLKCTRL_OFFSET 0x0014
+#define OMAP4430_CM_CPU1_CPU1_CLKCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0014)
+#define OMAP4_CM_CPU1_CLKSTCTRL_OFFSET 0x0018
+#define OMAP4430_CM_CPU1_CLKSTCTRL OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0018)
/* Function prototypes */
# ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h
index 6d2776f6fc08..3cb247bebdaa 100644
--- a/arch/arm/mach-omap2/prm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-44xx.h
@@ -283,6 +283,14 @@
#define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT 10
#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK (0x3 << 10)
+/* Used by PRM_DEVICE_OFF_CTRL */
+#define OMAP4460_EMIF1_OFFWKUP_DISABLE_SHIFT 8
+#define OMAP4460_EMIF1_OFFWKUP_DISABLE_MASK (1 << 8)
+
+/* Used by PRM_DEVICE_OFF_CTRL */
+#define OMAP4460_EMIF2_OFFWKUP_DISABLE_SHIFT 9
+#define OMAP4460_EMIF2_OFFWKUP_DISABLE_MASK (1 << 9)
+
/* Used by RM_MPU_RSTST */
#define OMAP4430_EMULATION_RST_SHIFT 0
#define OMAP4430_EMULATION_RST_MASK (1 << 0)
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index a2a04bfa9628..00165558fc4d 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -1,7 +1,7 @@
/*
* OMAP4 PRM module functions
*
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
* Benoît Cousson
* Paul Walmsley
@@ -24,12 +24,6 @@
#include "prm44xx.h"
#include "prm-regbits-44xx.h"
-/*
- * Address offset (in bytes) between the reset control and the reset
- * status registers: 4 bytes on OMAP4
- */
-#define OMAP4_RST_CTRL_ST_OFFSET 4
-
/* PRM low-level functions */
/* Read a register in a CM/PRM instance in the PRM module */
@@ -56,140 +50,3 @@ u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
return v;
}
-
-/* Read a PRM register, AND it, and shift the result down to bit 0 */
-/* XXX deprecated */
-u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
-{
- u32 v;
-
- v = __raw_readl(reg);
- v &= mask;
- v >>= __ffs(mask);
-
- return v;
-}
-
-/* Read-modify-write a register in a PRM module. Caller must lock */
-/* XXX deprecated */
-u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
-{
- u32 v;
-
- v = __raw_readl(reg);
- v &= ~mask;
- v |= bits;
- __raw_writel(v, reg);
-
- return v;
-}
-
-u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 reg)
-{
- return omap4_prm_rmw_inst_reg_bits(bits, bits, inst, reg);
-}
-
-u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 reg)
-{
- return omap4_prm_rmw_inst_reg_bits(bits, 0x0, inst, reg);
-}
-
-/**
- * omap4_prm_is_hardreset_asserted - read the HW reset line state of
- * submodules contained in the hwmod module
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to check
- *
- * Returns 1 if the (sub)module hardreset line is currently asserted,
- * 0 if the (sub)module hardreset line is not currently asserted, or
- * -EINVAL upon parameter error.
- */
-int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
-{
- if (!cpu_is_omap44xx() || !rstctrl_reg)
- return -EINVAL;
-
- return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
-}
-
-/**
- * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to assert
- *
- * Some IPs like dsp, ipu or iva contain processors that require an HW
- * reset line to be asserted / deasserted in order to fully enable the
- * IP. These modules may have multiple hard-reset lines that reset
- * different 'submodules' inside the IP block. This function will
- * place the submodule into reset. Returns 0 upon success or -EINVAL
- * upon an argument error.
- */
-int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
-{
- u32 mask;
-
- if (!cpu_is_omap44xx() || !rstctrl_reg)
- return -EINVAL;
-
- mask = 1 << shift;
- omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
-
- return 0;
-}
-
-/**
- * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to deassert
- *
- * Some IPs like dsp, ipu or iva contain processors that require an HW
- * reset line to be asserted / deasserted in order to fully enable the
- * IP. These modules may have multiple hard-reset lines that reset
- * different 'submodules' inside the IP block. This function will
- * take the submodule out of reset and wait until the PRCM indicates
- * that the reset has completed before returning. Returns 0 upon success or
- * -EINVAL upon an argument error, -EEXIST if the submodule was already out
- * of reset, or -EBUSY if the submodule did not exit reset promptly.
- */
-int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
-{
- u32 mask;
- void __iomem *rstst_reg;
- int c;
-
- if (!cpu_is_omap44xx() || !rstctrl_reg)
- return -EINVAL;
-
- rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
-
- mask = 1 << shift;
-
- /* Check the current status to avoid de-asserting the line twice */
- if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
- return -EEXIST;
-
- /* Clear the reset status by writing 1 to the status bit */
- omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
- /* de-assert the reset control line */
- omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
- /* wait the status to be set */
- omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
- MAX_MODULE_HARDRESET_WAIT, c);
-
- return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
-}
-
-void omap4_prm_global_warm_sw_reset(void)
-{
- u32 v;
-
- v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
- OMAP4_RM_RSTCTRL);
- v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
- omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
- OMAP4_RM_RSTCTRL);
-
- /* OCP barrier */
- v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
- OMAP4_RM_RSTCTRL);
-}
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 67a0d3feb3f6..7dfa379b625d 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -31,7 +31,7 @@
#define OMAP4430_PRM_BASE 0x4a306000
#define OMAP44XX_PRM_REGADDR(inst, reg) \
- OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE + (inst) + (reg))
+ OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE + (inst) + (reg))
/* PRM instances */
@@ -46,30 +46,18 @@
#define OMAP4430_PRM_CAM_INST 0x1000
#define OMAP4430_PRM_DSS_INST 0x1100
#define OMAP4430_PRM_GFX_INST 0x1200
-#define OMAP4430_PRM_L3INIT_INST 0x1300
+#define OMAP4430_PRM_L3INIT_INST 0x1300
#define OMAP4430_PRM_L4PER_INST 0x1400
-#define OMAP4430_PRM_CEFUSE_INST 0x1600
+#define OMAP4430_PRM_CEFUSE_INST 0x1600
#define OMAP4430_PRM_WKUP_INST 0x1700
#define OMAP4430_PRM_WKUP_CM_INST 0x1800
#define OMAP4430_PRM_EMU_INST 0x1900
-#define OMAP4430_PRM_EMU_CM_INST 0x1a00
-#define OMAP4430_PRM_DEVICE_INST 0x1b00
+#define OMAP4430_PRM_EMU_CM_INST 0x1a00
+#define OMAP4430_PRM_DEVICE_INST 0x1b00
#define OMAP4430_PRM_INSTR_INST 0x1f00
/* PRM clockdomain register offsets (from instance start) */
-#define OMAP4430_PRM_MPU_MPU_CDOFFS 0x0000
-#define OMAP4430_PRM_TESLA_TESLA_CDOFFS 0x0000
-#define OMAP4430_PRM_ABE_ABE_CDOFFS 0x0000
-#define OMAP4430_PRM_CORE_CORE_CDOFFS 0x0000
-#define OMAP4430_PRM_IVAHD_IVAHD_CDOFFS 0x0000
-#define OMAP4430_PRM_CAM_CAM_CDOFFS 0x0000
-#define OMAP4430_PRM_DSS_DSS_CDOFFS 0x0000
-#define OMAP4430_PRM_GFX_GFX_CDOFFS 0x0000
-#define OMAP4430_PRM_L3INIT_L3INIT_CDOFFS 0x0000
-#define OMAP4430_PRM_L4PER_L4PER_CDOFFS 0x0000
-#define OMAP4430_PRM_CEFUSE_CEFUSE_CDOFFS 0x0000
#define OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS 0x0000
-#define OMAP4430_PRM_EMU_EMU_CDOFFS 0x0000
#define OMAP4430_PRM_EMU_CM_EMU_CDOFFS 0x0000
/* OMAP4 specific register offsets */
@@ -247,8 +235,8 @@
#define OMAP4430_RM_MEMIF_DLL_H_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0464)
#define OMAP4_RM_D2D_SAD2D_CONTEXT_OFFSET 0x0524
#define OMAP4430_RM_D2D_SAD2D_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0524)
-#define OMAP4_RM_D2D_INSTEM_ICR_CONTEXT_OFFSET 0x052c
-#define OMAP4430_RM_D2D_INSTEM_ICR_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x052c)
+#define OMAP4_RM_D2D_MODEM_ICR_CONTEXT_OFFSET 0x052c
+#define OMAP4430_RM_D2D_MODEM_ICR_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x052c)
#define OMAP4_RM_D2D_SAD2D_FW_CONTEXT_OFFSET 0x0534
#define OMAP4430_RM_D2D_SAD2D_FW_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0534)
#define OMAP4_RM_L4CFG_L4_CFG_CONTEXT_OFFSET 0x0624
@@ -713,8 +701,8 @@
#define OMAP4430_PRM_VC_VAL_BYPASS OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a0)
#define OMAP4_PRM_VC_CFG_CHANNEL_OFFSET 0x00a4
#define OMAP4430_PRM_VC_CFG_CHANNEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a4)
-#define OMAP4_PRM_VC_CFG_I2C_INSTE_OFFSET 0x00a8
-#define OMAP4430_PRM_VC_CFG_I2C_INSTE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a8)
+#define OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET 0x00a8
+#define OMAP4430_PRM_VC_CFG_I2C_MODE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a8)
#define OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET 0x00ac
#define OMAP4430_PRM_VC_CFG_I2C_CLK OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00ac)
#define OMAP4_PRM_SRAM_COUNT_OFFSET 0x00b0
@@ -751,8 +739,8 @@
#define OMAP4430_PRM_PHASE2A_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00ec)
#define OMAP4_PRM_PHASE2B_CNDP_OFFSET 0x00f0
#define OMAP4430_PRM_PHASE2B_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f0)
-#define OMAP4_PRM_INSTEM_IF_CTRL_OFFSET 0x00f4
-#define OMAP4430_PRM_INSTEM_IF_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f4)
+#define OMAP4_PRM_MODEM_IF_CTRL_OFFSET 0x00f4
+#define OMAP4430_PRM_MODEM_IF_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f4)
#define OMAP4_PRM_VC_ERRST_OFFSET 0x00f8
#define OMAP4430_PRM_VC_ERRST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f8)
@@ -762,16 +750,6 @@
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);
-extern u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
-extern u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
-
-extern int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
-extern int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-extern int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-
-extern void omap4_prm_global_warm_sw_reset(void);
# endif
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
index a30324297278..3a7bab16edd5 100644
--- a/arch/arm/mach-omap2/prminst44xx.c
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -2,6 +2,7 @@
* OMAP4 PRM instance functions
*
* Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -53,7 +54,7 @@ void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
/* Read-modify-write a register in PRM. Caller must lock */
u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
- s16 idx)
+ u16 idx)
{
u32 v;
@@ -64,3 +65,112 @@ u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
return v;
}
+
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET 4
+
+/**
+ * omap4_prminst_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
+ u16 rstctrl_offs)
+{
+ u32 v;
+
+ v = omap4_prminst_read_inst_reg(part, inst, rstctrl_offs);
+ v &= 1 << shift;
+ v >>= shift;
+
+ return v;
+}
+
+/**
+ * omap4_prminst_assert_hardreset - assert the HW reset line of a submodule
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP. These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block. This function will
+ * place the submodule into reset. Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
+ u16 rstctrl_offs)
+{
+ u32 mask = 1 << shift;
+
+ omap4_prminst_rmw_inst_reg_bits(mask, mask, part, inst, rstctrl_offs);
+
+ return 0;
+}
+
+/**
+ * omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and
+ * wait
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP. These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block. This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning. Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
+ u16 rstctrl_offs)
+{
+ int c;
+ u32 mask = 1 << shift;
+ u16 rstst_offs = rstctrl_offs + OMAP4_RST_CTRL_ST_OFFSET;
+
+ /* Check the current status to avoid de-asserting the line twice */
+ if (omap4_prminst_is_hardreset_asserted(shift, part, inst,
+ rstctrl_offs) == 0)
+ return -EEXIST;
+
+ /* Clear the reset status by writing 1 to the status bit */
+ omap4_prminst_rmw_inst_reg_bits(0xffffffff, mask, part, inst,
+ rstst_offs);
+ /* de-assert the reset control line */
+ omap4_prminst_rmw_inst_reg_bits(mask, 0, part, inst, rstctrl_offs);
+ /* wait the status to be set */
+ omap_test_timeout(omap4_prminst_is_hardreset_asserted(shift, part, inst,
+ rstst_offs),
+ MAX_MODULE_HARDRESET_WAIT, c);
+
+ return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
+
+void omap4_prminst_global_warm_sw_reset(void)
+{
+ u32 v;
+
+ v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_RSTCTRL_OFFSET);
+ v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
+ omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_RSTCTRL_OFFSET);
+
+ /* OCP barrier */
+ v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_RSTCTRL_OFFSET);
+}
diff --git a/arch/arm/mach-omap2/prminst44xx.h b/arch/arm/mach-omap2/prminst44xx.h
index 02dd66ddda8b..46f2efb36596 100644
--- a/arch/arm/mach-omap2/prminst44xx.h
+++ b/arch/arm/mach-omap2/prminst44xx.h
@@ -2,6 +2,7 @@
* OMAP4 Power/Reset Management (PRM) function prototypes
*
* Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -18,8 +19,15 @@
extern u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx);
extern void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
extern u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
- s16 inst, s16 idx);
+ s16 inst, u16 idx);
-extern void omap4_prm_global_warm_sw_reset(void);
+extern void omap4_prminst_global_warm_sw_reset(void);
+
+extern int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
+ u16 rstctrl_offs);
+extern int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
+ u16 rstctrl_offs);
+extern int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
+ u16 rstctrl_offs);
#endif
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 1ac361b7b8cb..466fc722fa0f 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -805,6 +805,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
name, oh->name);
+ omap_device_disable_idle_on_suspend(od);
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
uart->irq = oh->mpu_irqs[0].irq;
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 63f10669571a..f2ea1bd1c691 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -74,46 +74,6 @@
* API functions
*/
-/*
- * The "get_*restore_pointer" functions are used to provide a
- * physical restore address where the ROM code jumps while waking
- * up from MPU OFF/OSWR state.
- * The restore pointer is stored into the scratchpad.
- */
-
- .text
-/* Function call to get the restore pointer for resume from OFF */
-ENTRY(get_restore_pointer)
- stmfd sp!, {lr} @ save registers on stack
- adr r0, restore
- ldmfd sp!, {pc} @ restore regs and return
-ENDPROC(get_restore_pointer)
- .align
-ENTRY(get_restore_pointer_sz)
- .word . - get_restore_pointer
-
- .text
-/* Function call to get the restore pointer for 3630 resume from OFF */
-ENTRY(get_omap3630_restore_pointer)
- stmfd sp!, {lr} @ save registers on stack
- adr r0, restore_3630
- ldmfd sp!, {pc} @ restore regs and return
-ENDPROC(get_omap3630_restore_pointer)
- .align
-ENTRY(get_omap3630_restore_pointer_sz)
- .word . - get_omap3630_restore_pointer
-
- .text
-/* Function call to get the restore pointer for ES3 to resume from OFF */
-ENTRY(get_es3_restore_pointer)
- stmfd sp!, {lr} @ save registers on stack
- adr r0, restore_es3
- ldmfd sp!, {pc} @ restore regs and return
-ENDPROC(get_es3_restore_pointer)
- .align
-ENTRY(get_es3_restore_pointer_sz)
- .word . - get_es3_restore_pointer
-
.text
/*
* L2 cache needs to be toggled for stable OFF mode functionality on 3630.
@@ -133,7 +93,7 @@ ENDPROC(enable_omap3630_toggle_l2_on_restore)
/* Function to call rom code to save secure ram context */
.align 3
ENTRY(save_secure_ram_context)
- stmfd sp!, {r1-r12, lr} @ save registers on stack
+ stmfd sp!, {r4 - r11, lr} @ save registers on stack
adr r3, api_params @ r3 points to parameters
str r0, [r3,#0x4] @ r0 has sdram address
ldr r12, high_mask
@@ -152,7 +112,7 @@ ENTRY(save_secure_ram_context)
nop
nop
nop
- ldmfd sp!, {r1-r12, pc}
+ ldmfd sp!, {r4 - r11, pc}
.align
sram_phy_addr_mask:
.word SRAM_BASE_P
@@ -179,69 +139,38 @@ ENTRY(save_secure_ram_context_sz)
*
*
* Notes:
- * - this code gets copied to internal SRAM at boot and after wake-up
- * from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - only the minimum set of functions gets copied to internal SRAM at boot
+ * and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
+ * pointers in SDRAM or SRAM are called depending on the desired low power
+ * target state.
* - when the OMAP wakes up it continues at different execution points
* depending on the low power mode (non-OFF vs OFF modes),
* cf. 'Resume path for xxx mode' comments.
*/
.align 3
ENTRY(omap34xx_cpu_suspend)
- stmfd sp!, {r0-r12, lr} @ save registers on stack
+ stmfd sp!, {r4 - r11, lr} @ save registers on stack
/*
- * r0 contains CPU context save/restore pointer in sdram
- * r1 contains information about saving context:
+ * r0 contains information about saving context:
* 0 - No context lost
* 1 - Only L1 and logic lost
* 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
* 3 - Both L1 and L2 lost and logic lost
*/
- /* Directly jump to WFI is the context save is not required */
- cmp r1, #0x0
- beq omap3_do_wfi
+ /*
+ * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
+ * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
+ */
+ ldr r4, omap3_do_wfi_sram_addr
+ ldr r5, [r4]
+ cmp r0, #0x0 @ If no context save required,
+ bxeq r5 @ jump to the WFI code in SRAM
+
/* Otherwise fall through to the save context code */
save_context_wfi:
- mov r8, r0 @ Store SDRAM address in r8
- mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
- mov r4, #0x1 @ Number of parameters for restore call
- stmia r8!, {r4-r5} @ Push parameters for restore call
- mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
- stmia r8!, {r4-r5} @ Push parameters for restore call
-
- /* Check what that target sleep state is from r1 */
- cmp r1, #0x2 @ Only L2 lost, no need to save context
- beq clean_caches
-
-l1_logic_lost:
- 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}
-
-clean_caches:
/*
* jump out to kernel flush routine
* - reuse that code is better
@@ -284,7 +213,32 @@ clean_caches:
THUMB( nop )
.arm
-omap3_do_wfi:
+ b omap3_do_wfi
+
+/*
+ * Local variables
+ */
+omap3_do_wfi_sram_addr:
+ .word omap3_do_wfi_sram
+kernel_flush:
+ .word v7_flush_dcache_all
+
+/* ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
+
+/*
+ * Do WFI instruction
+ * Includes the resume path for non-OFF modes
+ *
+ * This code gets copied to internal SRAM and is accessible
+ * from both SDRAM and SRAM:
+ * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
+ * - executed from SDRAM for OFF mode (omap3_do_wfi).
+ */
+ .align 3
+ENTRY(omap3_do_wfi)
ldr r4, sdrc_power @ read the SDRC_POWER register
ldr r5, [r4] @ read the contents of SDRC_POWER
orr r5, r5, #0x40 @ enable self refresh on idle req
@@ -316,8 +270,86 @@ omap3_do_wfi:
nop
nop
nop
- bl wait_sdrc_ok
+/*
+ * This function implements the erratum ID i581 WA:
+ * SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
+
+/* Make sure SDRC accesses are ok */
+wait_sdrc_ok:
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+ ldr r4, cm_idlest_ckgen
+wait_dpll3_lock:
+ ldr r5, [r4]
+ tst r5, #1
+ beq wait_dpll3_lock
+
+ ldr r4, cm_idlest1_core
+wait_sdrc_ready:
+ ldr r5, [r4]
+ tst r5, #0x2
+ bne wait_sdrc_ready
+ /* allow DLL powerdown upon hw idle req */
+ ldr r4, sdrc_power
+ ldr r5, [r4]
+ bic r5, r5, #0x40
+ str r5, [r4]
+
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
+is_dll_in_lock_mode:
+ /* Is dll in lock mode? */
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ tst r5, #0x4
+ bne exit_nonoff_modes @ Return if locked
+ /* wait till dll locks */
+ adr r7, kick_counter
+wait_dll_lock_timed:
+ ldr r4, wait_dll_lock_counter
+ add r4, r4, #1
+ str r4, [r7, #wait_dll_lock_counter - kick_counter]
+ ldr r4, sdrc_dlla_status
+ /* Wait 20uS for lock */
+ mov r6, #8
+wait_dll_lock:
+ subs r6, r6, #0x1
+ beq kick_dll
+ ldr r5, [r4]
+ and r5, r5, #0x4
+ cmp r5, #0x4
+ bne wait_dll_lock
+ b exit_nonoff_modes @ Return when locked
+
+ /* disable/reenable DLL if not locked */
+kick_dll:
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ mov r6, r5
+ bic r6, #(1<<3) @ disable dll
+ str r6, [r4]
+ dsb
+ orr r6, r6, #(1<<3) @ enable dll
+ str r6, [r4]
+ dsb
+ ldr r4, kick_counter
+ add r4, r4, #1
+ str r4, [r7] @ kick_counter
+ b wait_dll_lock_timed
+
+exit_nonoff_modes:
+ /* Re-enable C-bit if needed */
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
@@ -329,7 +361,32 @@ omap3_do_wfi:
* == Exit point from non-OFF modes ==
* ===================================
*/
- ldmfd sp!, {r0-r12, pc} @ restore regs and return
+ ldmfd sp!, {r4 - r11, pc} @ restore regs and return
+
+/*
+ * Local variables
+ */
+sdrc_power:
+ .word SDRC_POWER_V
+cm_idlest1_core:
+ .word CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+ .word CM_IDLEST_CKGEN_V
+sdrc_dlla_status:
+ .word SDRC_DLLA_STATUS_V
+sdrc_dlla_ctrl:
+ .word SDRC_DLLA_CTRL_V
+ /*
+ * When exporting to userspace while the counters are in SRAM,
+ * these 2 words need to be at the end to facilitate retrival!
+ */
+kick_counter:
+ .word 0
+wait_dll_lock_counter:
+ .word 0
+
+ENTRY(omap3_do_wfi_sz)
+ .word . - omap3_do_wfi
/*
@@ -346,13 +403,17 @@ omap3_do_wfi:
* restore_es3: applies to 34xx >= ES3.0
* restore_3630: applies to 36xx
* restore: common code for 3xxx
+ *
+ * Note: when back from CORE and MPU OFF mode we are running
+ * from SDRAM, without MMU, without the caches and prediction.
+ * Also the SRAM content has been cleared.
*/
-restore_es3:
+ENTRY(omap3_restore_es3)
ldr r5, pm_prepwstst_core_p
ldr r4, [r5]
and r4, r4, #0x3
cmp r4, #0x0 @ Check if previous power state of CORE is OFF
- bne restore
+ bne omap3_restore @ Fall through to OMAP3 common code
adr r0, es3_sdrc_fix
ldr r1, sram_base
ldr r2, es3_sdrc_fix_sz
@@ -364,35 +425,32 @@ copy_to_sram:
bne copy_to_sram
ldr r1, sram_base
blx r1
- b restore
+ b omap3_restore @ Fall through to OMAP3 common code
+ENDPROC(omap3_restore_es3)
-restore_3630:
+ENTRY(omap3_restore_3630)
ldr r1, pm_prepwstst_core_p
ldr r2, [r1]
and r2, r2, #0x3
cmp r2, #0x0 @ Check if previous power state of CORE is OFF
- bne restore
+ bne omap3_restore @ Fall through to OMAP3 common code
/* Disable RTA before giving control */
ldr r1, control_mem_rta
mov r2, #OMAP36XX_RTA_DISABLE
str r2, [r1]
+ENDPROC(omap3_restore_3630)
/* Fall through to common code for the remaining logic */
-restore:
+ENTRY(omap3_restore)
/*
- * Check what was the reason for mpu reset and store the reason in r9:
- * 0 - No context lost
- * 1 - Only L1 and logic lost
- * 2 - Only L2 lost - In this case, we wont be here
- * 3 - Both L1 and L2 lost
+ * Read the pwstctrl register to check the reason for mpu reset.
+ * This tells us what was lost.
*/
ldr r1, pm_pwstctrl_mpu
ldr r2, [r1]
and r2, r2, #0x3
cmp r2, #0x0 @ Check if target power state was OFF or RET
- moveq r9, #0x3 @ MPU OFF => L1 and L2 lost
- movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation
bne logic_l1_restore
ldr r0, l2dis_3630
@@ -471,115 +529,39 @@ logic_l1_restore:
orr r1, r1, #2 @ re-enable L2 cache
mcr p15, 0, r1, c1, c0, 1
skipl2reen:
- mov r1, #0
- /*
- * Invalidate all instruction caches to PoU
- * and flush branch target cache
- */
- mcr p15, 0, r1, c7, c5, 0
- ldr r4, scratchpad_base
- ldr r3, [r4,#0xBC]
- adds r3, r3, #16
-
- 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
-
- /* Enabling 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
-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 r1, table_entry
- /* r1 has the value to be written to table entry*/
- add r1, r1, r4
- /* Getting the address of table entry to modify */
- lsr r4, #18
- /* r2 has the location which needs to be modified */
- add r2, r4
- /* Storing previous entry of location being modified */
- ldr r5, scratchpad_base
- ldr r4, [r2]
- str r4, [r5, #0xC0]
- /* Modify the table entry */
- str r1, [r2]
- /*
- * Storing address of entry being modified
- * - will be restored after enabling MMU
- */
- ldr r5, scratchpad_base
- str r2, [r5, #0xC4]
-
- 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}
- /* Store previous value of control register in scratchpad */
- str r4, [r5, #0xC8]
- ldr r2, cache_pred_disable_mask
- and r4, r2
- mcr p15, 0, r4, c1, c0, 0
- dsb
- isb
- ldr r0, =restoremmu_on
- bx r0
+ /* Now branch to the common CPU resume function */
+ b cpu_resume
+ENDPROC(omap3_restore)
+
+ .ltorg
/*
- * ==============================
- * == Exit point from OFF mode ==
- * ==============================
+ * Local variables
*/
-restoremmu_on:
- ldmfd sp!, {r0-r12, pc} @ restore regs and return
-
+pm_prepwstst_core_p:
+ .word PM_PREPWSTST_CORE_P
+pm_pwstctrl_mpu:
+ .word PM_PWSTCTRL_MPU_P
+scratchpad_base:
+ .word SCRATCHPAD_BASE_P
+sram_base:
+ .word SRAM_BASE_P + 0x8000
+control_stat:
+ .word CONTROL_STAT
+control_mem_rta:
+ .word CONTROL_MEM_RTA_CTRL
+l2dis_3630:
+ .word 0
/*
* Internal functions
*/
-/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+/*
+ * This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0
+ * Copied to and run from SRAM in order to reconfigure the SDRC parameters.
+ */
.text
.align 3
ENTRY(es3_sdrc_fix)
@@ -609,6 +591,9 @@ ENTRY(es3_sdrc_fix)
str r5, [r4] @ kick off refreshes
bx lr
+/*
+ * Local variables
+ */
.align
sdrc_syscfg:
.word SDRC_SYSCONFIG_P
@@ -627,128 +612,3 @@ sdrc_manual_1:
ENDPROC(es3_sdrc_fix)
ENTRY(es3_sdrc_fix_sz)
.word . - es3_sdrc_fix
-
-/*
- * This function implements the erratum ID i581 WA:
- * SDRC state restore before accessing the SDRAM
- *
- * Only used at return from non-OFF mode. For OFF
- * mode the ROM code configures the SDRC and
- * the DPLL before calling the restore code directly
- * from DDR.
- */
-
-/* Make sure SDRC accesses are ok */
-wait_sdrc_ok:
-
-/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
- ldr r4, cm_idlest_ckgen
-wait_dpll3_lock:
- ldr r5, [r4]
- tst r5, #1
- beq wait_dpll3_lock
-
- ldr r4, cm_idlest1_core
-wait_sdrc_ready:
- ldr r5, [r4]
- tst r5, #0x2
- bne wait_sdrc_ready
- /* allow DLL powerdown upon hw idle req */
- ldr r4, sdrc_power
- ldr r5, [r4]
- bic r5, r5, #0x40
- str r5, [r4]
-
-/*
- * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
- * base instead.
- * Be careful not to clobber r7 when maintaing this code.
- */
-
-is_dll_in_lock_mode:
- /* Is dll in lock mode? */
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- tst r5, #0x4
- bxne lr @ Return if locked
- /* wait till dll locks */
- adr r7, kick_counter
-wait_dll_lock_timed:
- ldr r4, wait_dll_lock_counter
- add r4, r4, #1
- str r4, [r7, #wait_dll_lock_counter - kick_counter]
- ldr r4, sdrc_dlla_status
- /* Wait 20uS for lock */
- mov r6, #8
-wait_dll_lock:
- subs r6, r6, #0x1
- beq kick_dll
- ldr r5, [r4]
- and r5, r5, #0x4
- cmp r5, #0x4
- bne wait_dll_lock
- bx lr @ Return when locked
-
- /* disable/reenable DLL if not locked */
-kick_dll:
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- mov r6, r5
- bic r6, #(1<<3) @ disable dll
- str r6, [r4]
- dsb
- orr r6, r6, #(1<<3) @ enable dll
- str r6, [r4]
- dsb
- ldr r4, kick_counter
- add r4, r4, #1
- str r4, [r7] @ kick_counter
- b wait_dll_lock_timed
-
- .align
-cm_idlest1_core:
- .word CM_IDLEST1_CORE_V
-cm_idlest_ckgen:
- .word CM_IDLEST_CKGEN_V
-sdrc_dlla_status:
- .word SDRC_DLLA_STATUS_V
-sdrc_dlla_ctrl:
- .word SDRC_DLLA_CTRL_V
-pm_prepwstst_core_p:
- .word PM_PREPWSTST_CORE_P
-pm_pwstctrl_mpu:
- .word PM_PWSTCTRL_MPU_P
-scratchpad_base:
- .word SCRATCHPAD_BASE_P
-sram_base:
- .word SRAM_BASE_P + 0x8000
-sdrc_power:
- .word SDRC_POWER_V
-ttbrbit_mask:
- .word 0xFFFFC000
-table_index_mask:
- .word 0xFFF00000
-table_entry:
- .word 0x00000C02
-cache_pred_disable_mask:
- .word 0xFFFFE7FB
-control_stat:
- .word CONTROL_STAT
-control_mem_rta:
- .word CONTROL_MEM_RTA_CTRL
-kernel_flush:
- .word v7_flush_dcache_all
-l2dis_3630:
- .word 0
- /*
- * When exporting to userspace while the counters are in SRAM,
- * these 2 words need to be at the end to facilitate retrival!
- */
-kick_counter:
- .word 0
-wait_dll_lock_counter:
- .word 0
-ENDPROC(omap34xx_cpu_suspend)
-
-ENTRY(omap34xx_cpu_suspend_sz)
- .word . - omap34xx_cpu_suspend
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index fb7dc52394a8..2ce2fb7664bc 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -143,7 +143,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
sr_write_reg(sr_info, IRQSTATUS, status);
}
- if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
+ if (sr_class->notify)
sr_class->notify(sr_info->voltdm, status);
return IRQ_HANDLED;
@@ -258,9 +258,7 @@ static int sr_late_init(struct omap_sr *sr_info)
struct resource *mem;
int ret = 0;
- if (sr_class->class_type == SR_CLASS2 &&
- sr_class->notify_flags && sr_info->irq) {
-
+ if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
if (name == NULL) {
ret = -ENOMEM;
@@ -270,6 +268,7 @@ static int sr_late_init(struct omap_sr *sr_info)
0, name, (void *)sr_info);
if (ret)
goto error;
+ disable_irq(sr_info->irq);
}
if (pdata && pdata->enable_on_init)
@@ -278,16 +277,16 @@ static int sr_late_init(struct omap_sr *sr_info)
return ret;
error:
- iounmap(sr_info->base);
- mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
- list_del(&sr_info->node);
- dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
- "interrupt handler. Smartreflex will"
- "not function as desired\n", __func__);
- kfree(name);
- kfree(sr_info);
- return ret;
+ iounmap(sr_info->base);
+ mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+ list_del(&sr_info->node);
+ dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
+ "interrupt handler. Smartreflex will"
+ "not function as desired\n", __func__);
+ kfree(name);
+ kfree(sr_info);
+ return ret;
}
static void sr_v1_disable(struct omap_sr *sr)
@@ -808,10 +807,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)
return -EINVAL;
}
- if (!val)
- sr_stop_vddautocomp(sr_info);
- else
- sr_start_vddautocomp(sr_info);
+ /* control enable/disable only if there is a delta in value */
+ if (sr_info->autocomp_active != val) {
+ if (!val)
+ sr_stop_vddautocomp(sr_info);
+ else
+ sr_start_vddautocomp(sr_info);
+ }
return 0;
}
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
deleted file mode 100644
index 3b9cf85f4bb9..000000000000
--- a/arch/arm/mach-omap2/timer-gp.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/timer-gp.c
- *
- * OMAP2 GP timer support.
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Update to use new clocksource/clockevent layers
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
- * Copyright (C) 2007 MontaVista Software, Inc.
- *
- * Original driver:
- * Copyright (C) 2005 Nokia Corporation
- * Author: Paul Mundt <paul.mundt@nokia.com>
- * Juha Yrjölä <juha.yrjola@nokia.com>
- * OMAP Dual-mode timer framework support by Timo Teras
- *
- * Some parts based off of TI's 24xx code:
- *
- * Copyright (C) 2004-2009 Texas Instruments, Inc.
- *
- * Roughly modelled after the OMAP1 MPU timer code.
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-
-#include <asm/mach/time.h>
-#include <plat/dmtimer.h>
-#include <asm/localtimer.h>
-#include <asm/sched_clock.h>
-#include <plat/common.h>
-#include <plat/omap_hwmod.h>
-
-#include "timer-gp.h"
-
-
-/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
-#define MAX_GPTIMER_ID 12
-
-static struct omap_dm_timer *gptimer;
-static struct clock_event_device clockevent_gpt;
-static u8 __initdata gptimer_id = 1;
-static u8 __initdata inited;
-struct omap_dm_timer *gptimer_wakeup;
-
-static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
-{
- struct omap_dm_timer *gpt = (struct omap_dm_timer *)dev_id;
- struct clock_event_device *evt = &clockevent_gpt;
-
- omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_OVERFLOW);
-
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static struct irqaction omap2_gp_timer_irq = {
- .name = "gp timer",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = omap2_gp_timer_interrupt,
-};
-
-static int omap2_gp_timer_set_next_event(unsigned long cycles,
- struct clock_event_device *evt)
-{
- omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles);
-
- return 0;
-}
-
-static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- u32 period;
-
- omap_dm_timer_stop(gptimer);
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
- period -= 1;
- omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- break;
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
-}
-
-static struct clock_event_device clockevent_gpt = {
- .name = "gp timer",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .shift = 32,
- .set_next_event = omap2_gp_timer_set_next_event,
- .set_mode = omap2_gp_timer_set_mode,
-};
-
-/**
- * omap2_gp_clockevent_set_gptimer - set which GPTIMER is used for clockevents
- * @id: GPTIMER to use (1..MAX_GPTIMER_ID)
- *
- * Define the GPTIMER that the system should use for the tick timer.
- * Meant to be called from board-*.c files in the event that GPTIMER1, the
- * default, is unsuitable. Returns -EINVAL on error or 0 on success.
- */
-int __init omap2_gp_clockevent_set_gptimer(u8 id)
-{
- if (id < 1 || id > MAX_GPTIMER_ID)
- return -EINVAL;
-
- BUG_ON(inited);
-
- gptimer_id = id;
-
- return 0;
-}
-
-static void __init omap2_gp_clockevent_init(void)
-{
- u32 tick_rate;
- int src;
- char clockevent_hwmod_name[8]; /* 8 = sizeof("timerXX0") */
-
- inited = 1;
-
- sprintf(clockevent_hwmod_name, "timer%d", gptimer_id);
- omap_hwmod_setup_one(clockevent_hwmod_name);
-
- gptimer = omap_dm_timer_request_specific(gptimer_id);
- BUG_ON(gptimer == NULL);
- gptimer_wakeup = gptimer;
-
-#if defined(CONFIG_OMAP_32K_TIMER)
- src = OMAP_TIMER_SRC_32_KHZ;
-#else
- src = OMAP_TIMER_SRC_SYS_CLK;
- WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the "
- "secure 32KiHz clock source\n");
-#endif
-
- if (gptimer_id != 12)
- WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)),
- "timer-gp: omap_dm_timer_set_source() failed\n");
-
- tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
-
- pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n",
- gptimer_id, tick_rate);
-
- omap2_gp_timer_irq.dev_id = (void *)gptimer;
- setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
- omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
-
- clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC,
- clockevent_gpt.shift);
- clockevent_gpt.max_delta_ns =
- clockevent_delta2ns(0xffffffff, &clockevent_gpt);
- clockevent_gpt.min_delta_ns =
- clockevent_delta2ns(3, &clockevent_gpt);
- /* Timer internal resynch latency. */
-
- clockevent_gpt.cpumask = cpumask_of(0);
- clockevents_register_device(&clockevent_gpt);
-}
-
-/* Clocksource code */
-
-#ifdef CONFIG_OMAP_32K_TIMER
-/*
- * When 32k-timer is enabled, don't use GPTimer for clocksource
- * instead, just leave default clocksource which uses the 32k
- * sync counter. See clocksource setup in plat-omap/counter_32k.c
- */
-
-static void __init omap2_gp_clocksource_init(void)
-{
- omap_init_clocksource_32k();
-}
-
-#else
-/*
- * clocksource
- */
-static DEFINE_CLOCK_DATA(cd);
-static struct omap_dm_timer *gpt_clocksource;
-static cycle_t clocksource_read_cycles(struct clocksource *cs)
-{
- return (cycle_t)omap_dm_timer_read_counter(gpt_clocksource);
-}
-
-static struct clocksource clocksource_gpt = {
- .name = "gp timer",
- .rating = 300,
- .read = clocksource_read_cycles,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static void notrace dmtimer_update_sched_clock(void)
-{
- u32 cyc;
-
- cyc = omap_dm_timer_read_counter(gpt_clocksource);
-
- update_sched_clock(&cd, cyc, (u32)~0);
-}
-
-/* Setup free-running counter for clocksource */
-static void __init omap2_gp_clocksource_init(void)
-{
- static struct omap_dm_timer *gpt;
- u32 tick_rate;
- static char err1[] __initdata = KERN_ERR
- "%s: failed to request dm-timer\n";
- static char err2[] __initdata = KERN_ERR
- "%s: can't register clocksource!\n";
-
- gpt = omap_dm_timer_request();
- if (!gpt)
- printk(err1, clocksource_gpt.name);
- gpt_clocksource = gpt;
-
- omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
- tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
-
- omap_dm_timer_set_load_start(gpt, 1, 0);
-
- init_sched_clock(&cd, dmtimer_update_sched_clock, 32, tick_rate);
-
- if (clocksource_register_hz(&clocksource_gpt, tick_rate))
- printk(err2, clocksource_gpt.name);
-}
-#endif
-
-static void __init omap2_gp_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
- if (cpu_is_omap44xx()) {
- twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
- BUG_ON(!twd_base);
- }
-#endif
- omap_dm_timer_init();
-
- omap2_gp_clockevent_init();
- omap2_gp_clocksource_init();
-}
-
-struct sys_timer omap_timer = {
- .init = omap2_gp_timer_init,
-};
diff --git a/arch/arm/mach-omap2/timer-gp.h b/arch/arm/mach-omap2/timer-gp.h
deleted file mode 100644
index 5c1072c6783b..000000000000
--- a/arch/arm/mach-omap2/timer-gp.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * OMAP2/3 GPTIMER support.headers
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
-
-extern int __init omap2_gp_clockevent_set_gptimer(u8 id);
-
-#endif
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
new file mode 100644
index 000000000000..e9640728239b
--- /dev/null
+++ b/arch/arm/mach-omap2/timer.c
@@ -0,0 +1,342 @@
+/*
+ * linux/arch/arm/mach-omap2/timer.c
+ *
+ * OMAP2 GP timer support.
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Update to use new clocksource/clockevent layers
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * Original driver:
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ * Juha Yrjölä <juha.yrjola@nokia.com>
+ * OMAP Dual-mode timer framework support by Timo Teras
+ *
+ * Some parts based off of TI's 24xx code:
+ *
+ * Copyright (C) 2004-2009 Texas Instruments, Inc.
+ *
+ * Roughly modelled after the OMAP1 MPU timer code.
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+
+#include <asm/mach/time.h>
+#include <plat/dmtimer.h>
+#include <asm/localtimer.h>
+#include <asm/sched_clock.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
+
+/* Parent clocks, eventually these will come from the clock framework */
+
+#define OMAP2_MPU_SOURCE "sys_ck"
+#define OMAP3_MPU_SOURCE OMAP2_MPU_SOURCE
+#define OMAP4_MPU_SOURCE "sys_clkin_ck"
+#define OMAP2_32K_SOURCE "func_32k_ck"
+#define OMAP3_32K_SOURCE "omap_32k_fck"
+#define OMAP4_32K_SOURCE "sys_32k_ck"
+
+#ifdef CONFIG_OMAP_32K_TIMER
+#define OMAP2_CLKEV_SOURCE OMAP2_32K_SOURCE
+#define OMAP3_CLKEV_SOURCE OMAP3_32K_SOURCE
+#define OMAP4_CLKEV_SOURCE OMAP4_32K_SOURCE
+#define OMAP3_SECURE_TIMER 12
+#else
+#define OMAP2_CLKEV_SOURCE OMAP2_MPU_SOURCE
+#define OMAP3_CLKEV_SOURCE OMAP3_MPU_SOURCE
+#define OMAP4_CLKEV_SOURCE OMAP4_MPU_SOURCE
+#define OMAP3_SECURE_TIMER 1
+#endif
+
+/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
+#define MAX_GPTIMER_ID 12
+
+u32 sys_timer_reserved;
+
+/* Clockevent code */
+
+static struct omap_dm_timer clkev;
+static struct clock_event_device clockevent_gpt;
+
+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);
+
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap2_gp_timer_irq = {
+ .name = "gp timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = omap2_gp_timer_interrupt,
+};
+
+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,
+ 0xffffffff - cycles, 1);
+
+ return 0;
+}
+
+static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ u32 period;
+
+ __omap_dm_timer_stop(clkev.io_base, 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,
+ 0xffffffff - period, 1);
+ __omap_dm_timer_load_start(clkev.io_base,
+ OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
+ 0xffffffff - period, 1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static struct clock_event_device clockevent_gpt = {
+ .name = "gp timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = omap2_gp_timer_set_next_event,
+ .set_mode = omap2_gp_timer_set_mode,
+};
+
+static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
+ int gptimer_id,
+ const char *fck_source)
+{
+ char name[10]; /* 10 = sizeof("gptXX_Xck0") */
+ struct omap_hwmod *oh;
+ size_t size;
+ int res = 0;
+
+ sprintf(name, "timer%d", gptimer_id);
+ omap_hwmod_setup_one(name);
+ oh = omap_hwmod_lookup(name);
+ if (!oh)
+ return -ENODEV;
+
+ timer->irq = oh->mpu_irqs[0].irq;
+ timer->phys_base = oh->slaves[0]->addr->pa_start;
+ size = oh->slaves[0]->addr->pa_end - timer->phys_base;
+
+ /* Static mapping, never released */
+ timer->io_base = ioremap(timer->phys_base, size);
+ if (!timer->io_base)
+ return -ENXIO;
+
+ /* After the dmtimer is using hwmod these clocks won't be needed */
+ sprintf(name, "gpt%d_fck", gptimer_id);
+ timer->fclk = clk_get(NULL, name);
+ if (IS_ERR(timer->fclk))
+ return -ENODEV;
+
+ sprintf(name, "gpt%d_ick", gptimer_id);
+ timer->iclk = clk_get(NULL, name);
+ if (IS_ERR(timer->iclk)) {
+ clk_put(timer->fclk);
+ return -ENODEV;
+ }
+
+ omap_hwmod_enable(oh);
+
+ sys_timer_reserved |= (1 << (gptimer_id - 1));
+
+ if (gptimer_id != 12) {
+ struct clk *src;
+
+ src = clk_get(NULL, fck_source);
+ if (IS_ERR(src)) {
+ res = -EINVAL;
+ } else {
+ res = __omap_dm_timer_set_source(timer->fclk, src);
+ if (IS_ERR_VALUE(res))
+ pr_warning("%s: timer%i cannot set source\n",
+ __func__, gptimer_id);
+ clk_put(src);
+ }
+ }
+ __omap_dm_timer_reset(timer->io_base, 1, 1);
+ timer->posted = 1;
+
+ timer->rate = clk_get_rate(timer->fclk);
+
+ timer->reserved = 1;
+
+ return res;
+}
+
+static void __init omap2_gp_clockevent_init(int gptimer_id,
+ const char *fck_source)
+{
+ int res;
+
+ res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
+ BUG_ON(res);
+
+ 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);
+
+ clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
+ clockevent_gpt.shift);
+ clockevent_gpt.max_delta_ns =
+ clockevent_delta2ns(0xffffffff, &clockevent_gpt);
+ clockevent_gpt.min_delta_ns =
+ clockevent_delta2ns(3, &clockevent_gpt);
+ /* Timer internal resynch latency. */
+
+ clockevent_gpt.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_gpt);
+
+ pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
+ gptimer_id, clkev.rate);
+}
+
+/* Clocksource code */
+
+#ifdef CONFIG_OMAP_32K_TIMER
+/*
+ * When 32k-timer is enabled, don't use GPTimer for clocksource
+ * instead, just leave default clocksource which uses the 32k
+ * sync counter. See clocksource setup in plat-omap/counter_32k.c
+ */
+
+static void __init omap2_gp_clocksource_init(int unused, const char *dummy)
+{
+ omap_init_clocksource_32k();
+}
+
+#else
+
+static struct omap_dm_timer clksrc;
+
+/*
+ * clocksource
+ */
+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);
+}
+
+static struct clocksource clocksource_gpt = {
+ .name = "gp timer",
+ .rating = 300,
+ .read = clocksource_read_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void notrace dmtimer_update_sched_clock(void)
+{
+ u32 cyc;
+
+ cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+
+ update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+unsigned long long notrace sched_clock(void)
+{
+ u32 cyc = 0;
+
+ if (clksrc.reserved)
+ cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+/* Setup free-running counter for clocksource */
+static void __init omap2_gp_clocksource_init(int gptimer_id,
+ const char *fck_source)
+{
+ int res;
+
+ res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
+ BUG_ON(res);
+
+ pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
+ gptimer_id, clksrc.rate);
+
+ __omap_dm_timer_load_start(clksrc.io_base, OMAP_TIMER_CTRL_ST, 0, 1);
+ init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
+
+ if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
+ pr_err("Could not register clocksource %s\n",
+ clocksource_gpt.name);
+}
+#endif
+
+#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \
+ clksrc_nr, clksrc_src) \
+static void __init omap##name##_timer_init(void) \
+{ \
+ omap2_gp_clockevent_init((clkev_nr), clkev_src); \
+ omap2_gp_clocksource_init((clksrc_nr), clksrc_src); \
+}
+
+#define OMAP_SYS_TIMER(name) \
+struct sys_timer omap##name##_timer = { \
+ .init = omap##name##_timer_init, \
+};
+
+#ifdef CONFIG_ARCH_OMAP2
+OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
+OMAP_SYS_TIMER(2)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER(3)
+OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
+ 2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER(3_secure)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static void __init omap4_timer_init(void)
+{
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
+ omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE);
+}
+OMAP_SYS_TIMER(4)
+#endif
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
new file mode 100644
index 000000000000..2543342dbccb
--- /dev/null
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -0,0 +1,304 @@
+/*
+ * twl-common.c
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc..
+ * Author: Peter Ujfalusi <peter.ujfalusi@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 in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You 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/i2c.h>
+#include <linux/i2c/twl.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+
+#include <plat/i2c.h>
+#include <plat/usb.h>
+
+#include "twl-common.h"
+
+static struct i2c_board_info __initdata pmic_i2c_board_info = {
+ .addr = 0x48,
+ .flags = I2C_CLIENT_WAKE,
+};
+
+void __init omap_pmic_init(int bus, u32 clkrate,
+ const char *pmic_type, int pmic_irq,
+ struct twl4030_platform_data *pmic_data)
+{
+ strncpy(pmic_i2c_board_info.type, pmic_type,
+ sizeof(pmic_i2c_board_info.type));
+ pmic_i2c_board_info.irq = pmic_irq;
+ pmic_i2c_board_info.platform_data = pmic_data;
+
+ omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
+}
+
+static struct twl4030_usb_data omap4_usb_pdata = {
+ .phy_init = omap4430_phy_init,
+ .phy_exit = omap4430_phy_exit,
+ .phy_power = omap4430_phy_power,
+ .phy_set_clock = omap4430_phy_set_clk,
+ .phy_suspend = omap4430_phy_suspend,
+};
+
+static struct twl4030_usb_data omap3_usb_pdata = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
+static int omap3_batt_table[] = {
+/* 0 C */
+30800, 29500, 28300, 27100,
+26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
+17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
+11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
+8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
+5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
+4040, 3910, 3790, 3670, 3550
+};
+
+static struct twl4030_bci_platform_data omap3_bci_pdata = {
+ .battery_tmp_tbl = omap3_batt_table,
+ .tblsize = ARRAY_SIZE(omap3_batt_table),
+};
+
+static struct twl4030_madc_platform_data omap3_madc_pdata = {
+ .irq_line = 1,
+};
+
+static struct twl4030_codec_data omap3_codec;
+
+static struct twl4030_audio_data omap3_audio_pdata = {
+ .audio_mclk = 26000000,
+ .codec = &omap3_codec,
+};
+
+static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = {
+ REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
+};
+
+static struct regulator_init_data omap3_vdac_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap3_vdda_dac_supplies),
+ .consumer_supplies = omap3_vdda_dac_supplies,
+};
+
+static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_init_data omap3_vpll2_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap3_vpll2_supplies),
+ .consumer_supplies = omap3_vpll2_supplies,
+};
+
+static struct regulator_init_data omap4_vdac_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vaux2_idata = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 2800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vaux3_idata = {
+ .constraints = {
+ .min_uV = 1000000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_consumer_supply omap4_vmmc_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
+
+/* VMMC1 for MMC1 card */
+static struct regulator_init_data omap4_vmmc_idata = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_vmmc_supply),
+ .consumer_supplies = omap4_vmmc_supply,
+};
+
+static struct regulator_init_data omap4_vpp_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 2500000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vana_idata = {
+ .constraints = {
+ .min_uV = 2100000,
+ .max_uV = 2100000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vcxio_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_vusb_idata = {
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data omap4_clk32kg_idata = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags)
+{
+ if (!pmic_data->irq_base)
+ pmic_data->irq_base = TWL6030_IRQ_BASE;
+ if (!pmic_data->irq_end)
+ pmic_data->irq_end = TWL6030_IRQ_END;
+
+ /* Common platform data configurations */
+ if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
+ pmic_data->usb = &omap4_usb_pdata;
+
+ /* Common regulator configurations */
+ if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+ pmic_data->vdac = &omap4_vdac_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VAUX2 && !pmic_data->vaux2)
+ pmic_data->vaux2 = &omap4_vaux2_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VAUX3 && !pmic_data->vaux3)
+ pmic_data->vaux3 = &omap4_vaux3_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VMMC && !pmic_data->vmmc)
+ pmic_data->vmmc = &omap4_vmmc_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VPP && !pmic_data->vpp)
+ pmic_data->vpp = &omap4_vpp_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VANA && !pmic_data->vana)
+ pmic_data->vana = &omap4_vana_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VCXIO && !pmic_data->vcxio)
+ pmic_data->vcxio = &omap4_vcxio_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VUSB && !pmic_data->vusb)
+ pmic_data->vusb = &omap4_vusb_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_CLK32KG &&
+ !pmic_data->clk32kg)
+ pmic_data->clk32kg = &omap4_clk32kg_idata;
+}
+
+void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags)
+{
+ if (!pmic_data->irq_base)
+ pmic_data->irq_base = TWL4030_IRQ_BASE;
+ if (!pmic_data->irq_end)
+ pmic_data->irq_end = TWL4030_IRQ_END;
+
+ /* Common platform data configurations */
+ if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
+ pmic_data->usb = &omap3_usb_pdata;
+
+ if (pdata_flags & TWL_COMMON_PDATA_BCI && !pmic_data->bci)
+ pmic_data->bci = &omap3_bci_pdata;
+
+ if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc)
+ pmic_data->madc = &omap3_madc_pdata;
+
+ if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
+ pmic_data->audio = &omap3_audio_pdata;
+
+ /* Common regulator configurations */
+ if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+ pmic_data->vdac = &omap3_vdac_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_VPLL2 && !pmic_data->vpll2)
+ pmic_data->vpll2 = &omap3_vpll2_idata;
+}
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
new file mode 100644
index 000000000000..5e83a5bd37fb
--- /dev/null
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -0,0 +1,59 @@
+#ifndef __OMAP_PMIC_COMMON__
+#define __OMAP_PMIC_COMMON__
+
+#define TWL_COMMON_PDATA_USB (1 << 0)
+#define TWL_COMMON_PDATA_BCI (1 << 1)
+#define TWL_COMMON_PDATA_MADC (1 << 2)
+#define TWL_COMMON_PDATA_AUDIO (1 << 3)
+
+/* Common LDO regulators for TWL4030/TWL6030 */
+#define TWL_COMMON_REGULATOR_VDAC (1 << 0)
+#define TWL_COMMON_REGULATOR_VAUX1 (1 << 1)
+#define TWL_COMMON_REGULATOR_VAUX2 (1 << 2)
+#define TWL_COMMON_REGULATOR_VAUX3 (1 << 3)
+
+/* TWL6030 LDO regulators */
+#define TWL_COMMON_REGULATOR_VMMC (1 << 4)
+#define TWL_COMMON_REGULATOR_VPP (1 << 5)
+#define TWL_COMMON_REGULATOR_VUSIM (1 << 6)
+#define TWL_COMMON_REGULATOR_VANA (1 << 7)
+#define TWL_COMMON_REGULATOR_VCXIO (1 << 8)
+#define TWL_COMMON_REGULATOR_VUSB (1 << 9)
+#define TWL_COMMON_REGULATOR_CLK32KG (1 << 10)
+
+/* TWL4030 LDO regulators */
+#define TWL_COMMON_REGULATOR_VPLL1 (1 << 4)
+#define TWL_COMMON_REGULATOR_VPLL2 (1 << 5)
+
+
+struct twl4030_platform_data;
+
+void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
+ struct twl4030_platform_data *pmic_data);
+
+static inline void omap2_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data)
+{
+ omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data);
+}
+
+static inline void omap3_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data)
+{
+ omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
+}
+
+static inline void omap4_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data)
+{
+ /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
+ omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
+}
+
+void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags);
+
+void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ u32 pdata_flags, u32 regulators_flags);
+
+#endif /* __OMAP_PMIC_COMMON__ */
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index c7ed540d868d..a65145b02a55 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -33,8 +33,6 @@
#include <plat/omap_device.h>
#include "mux.h"
-#if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
-
static struct musb_hdrc_config musb_config = {
.multipoint = 1,
.dyn_fifo = 1,
@@ -175,11 +173,3 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
if (cpu_is_omap44xx())
omap4430_phy_init(dev);
}
-
-#else
-void __init usb_musb_init(struct omap_musb_board_data *board_data)
-{
- if (cpu_is_omap44xx())
- omap4430_phy_init(NULL);
-}
-#endif /* CONFIG_USB_MUSB_SOC */
diff --git a/arch/arm/mach-orion5x/include/mach/hardware.h b/arch/arm/mach-orion5x/include/mach/hardware.h
index e51aaf4bf2b5..395735482473 100644
--- a/arch/arm/mach-orion5x/include/mach/hardware.h
+++ b/arch/arm/mach-orion5x/include/mach/hardware.h
@@ -11,11 +11,4 @@
#include "orion5x.h"
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x00001000
-#define PCIBIOS_MIN_MEM 0x01000000
-#define PCIMEM_BASE ORION5X_PCIE_MEM_PHYS_BASE
-
-
#endif
diff --git a/arch/arm/mach-orion5x/mpp.c b/arch/arm/mach-orion5x/mpp.c
index f12c41b98d46..b6ddd7a5db6a 100644
--- a/arch/arm/mach-orion5x/mpp.c
+++ b/arch/arm/mach-orion5x/mpp.c
@@ -24,7 +24,7 @@ static unsigned int __init orion5x_variant(void)
orion5x_pcie_id(&dev, &rev);
- if (dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0)
+ if (dev == MV88F5181_DEV_ID)
return MPP_F5181_MASK;
if (dev == MV88F5182_DEV_ID)
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index e8706f15a670..f64965d4f8e8 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -560,6 +560,8 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
{
int ret = 0;
+ vga_base = ORION5X_PCIE_MEM_PHYS_BASE;
+
if (nr == 0) {
orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
ret = pcie_setup(sys);
diff --git a/arch/arm/mach-pnx4008/include/mach/clkdev.h b/arch/arm/mach-pnx4008/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-pnx4008/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-pnx4008/include/mach/entry-macro.S b/arch/arm/mach-pnx4008/include/mach/entry-macro.S
index 8003037578ed..db7eeebf30d7 100644
--- a/arch/arm/mach-pnx4008/include/mach/entry-macro.S
+++ b/arch/arm/mach-pnx4008/include/mach/entry-macro.S
@@ -120,8 +120,3 @@
1003:
.endm
-
- .macro irq_prio_table
- .endm
-
-
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
new file mode 100644
index 000000000000..7af7fc05d565
--- /dev/null
+++ b/arch/arm/mach-prima2/Makefile
@@ -0,0 +1,7 @@
+obj-y := timer.o
+obj-y += irq.o
+obj-y += clock.o
+obj-y += rstc.o
+obj-y += prima2.o
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_CACHE_L2X0) += l2x0.o
diff --git a/arch/arm/mach-prima2/Makefile.boot b/arch/arm/mach-prima2/Makefile.boot
new file mode 100644
index 000000000000..d023db3ae4ff
--- /dev/null
+++ b/arch/arm/mach-prima2/Makefile.boot
@@ -0,0 +1,3 @@
+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
new file mode 100644
index 000000000000..f9a2aaf63f71
--- /dev/null
+++ b/arch/arm/mach-prima2/clock.c
@@ -0,0 +1,509 @@
+/*
+ * Clock tree for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+
+#define SIRFSOC_CLKC_CLK_EN0 0x0000
+#define SIRFSOC_CLKC_CLK_EN1 0x0004
+#define SIRFSOC_CLKC_REF_CFG 0x0014
+#define SIRFSOC_CLKC_CPU_CFG 0x0018
+#define SIRFSOC_CLKC_MEM_CFG 0x001c
+#define SIRFSOC_CLKC_SYS_CFG 0x0020
+#define SIRFSOC_CLKC_IO_CFG 0x0024
+#define SIRFSOC_CLKC_DSP_CFG 0x0028
+#define SIRFSOC_CLKC_GFX_CFG 0x002c
+#define SIRFSOC_CLKC_MM_CFG 0x0030
+#define SIRFSOC_LKC_LCD_CFG 0x0034
+#define SIRFSOC_CLKC_MMC_CFG 0x0038
+#define SIRFSOC_CLKC_PLL1_CFG0 0x0040
+#define SIRFSOC_CLKC_PLL2_CFG0 0x0044
+#define SIRFSOC_CLKC_PLL3_CFG0 0x0048
+#define SIRFSOC_CLKC_PLL1_CFG1 0x004c
+#define SIRFSOC_CLKC_PLL2_CFG1 0x0050
+#define SIRFSOC_CLKC_PLL3_CFG1 0x0054
+#define SIRFSOC_CLKC_PLL1_CFG2 0x0058
+#define SIRFSOC_CLKC_PLL2_CFG2 0x005c
+#define SIRFSOC_CLKC_PLL3_CFG2 0x0060
+
+#define SIRFSOC_CLOCK_VA_BASE SIRFSOC_VA(0x005000)
+
+#define KHZ 1000
+#define MHZ (KHZ * KHZ)
+
+struct clk_ops {
+ unsigned long (*get_rate)(struct clk *clk);
+ long (*round_rate)(struct clk *clk, unsigned long rate);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+ int (*enable)(struct clk *clk);
+ int (*disable)(struct clk *clk);
+ struct clk *(*get_parent)(struct clk *clk);
+ int (*set_parent)(struct clk *clk, struct clk *parent);
+};
+
+struct clk {
+ struct clk *parent; /* parent clk */
+ unsigned long rate; /* clock rate in Hz */
+ signed char usage; /* clock enable count */
+ signed char enable_bit; /* enable bit: 0 ~ 63 */
+ unsigned short regofs; /* register offset */
+ struct clk_ops *ops; /* clock operation */
+};
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+ return readl(SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+ writel(val, SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+/*
+ * osc_rtc - real time oscillator - 32.768KHz
+ * osc_sys - high speed oscillator - 26MHz
+ */
+
+static struct clk clk_rtc = {
+ .rate = 32768,
+};
+
+static struct clk clk_osc = {
+ .rate = 26 * MHZ,
+};
+
+/*
+ * std pll
+ */
+static unsigned long std_pll_get_rate(struct clk *clk)
+{
+ unsigned long fin = clk_get_rate(clk->parent);
+ u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
+ SIRFSOC_CLKC_PLL1_CFG0;
+
+ if (clkc_readl(regcfg2) & BIT(2)) {
+ /* pll bypass mode */
+ clk->rate = fin;
+ } else {
+ /* fout = fin * nf / nr / od */
+ u32 cfg0 = clkc_readl(clk->regofs);
+ u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
+ u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
+ u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
+ WARN_ON(fin % MHZ);
+ clk->rate = fin / MHZ * nf / nr / od * MHZ;
+ }
+
+ return clk->rate;
+}
+
+static int std_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long fin, nf, nr, od, reg;
+
+ /*
+ * fout = fin * nf / (nr * od);
+ * set od = 1, nr = fin/MHz, so fout = nf * MHz
+ */
+
+ nf = rate / MHZ;
+ if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
+ return -EINVAL;
+
+ fin = clk_get_rate(clk->parent);
+ BUG_ON(fin < MHZ);
+
+ nr = fin / MHZ;
+ BUG_ON((fin % MHZ) || nr > BIT(6));
+
+ od = 1;
+
+ reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
+ clkc_writel(reg, clk->regofs);
+
+ reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
+ clkc_writel((nf >> 1) - 1, reg);
+
+ reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
+ while (!(clkc_readl(reg) & BIT(6)))
+ cpu_relax();
+
+ clk->rate = 0; /* set to zero will force recalculation */
+ return 0;
+}
+
+static struct clk_ops std_pll_ops = {
+ .get_rate = std_pll_get_rate,
+ .set_rate = std_pll_set_rate,
+};
+
+static struct clk clk_pll1 = {
+ .parent = &clk_osc,
+ .regofs = SIRFSOC_CLKC_PLL1_CFG0,
+ .ops = &std_pll_ops,
+};
+
+static struct clk clk_pll2 = {
+ .parent = &clk_osc,
+ .regofs = SIRFSOC_CLKC_PLL2_CFG0,
+ .ops = &std_pll_ops,
+};
+
+static struct clk clk_pll3 = {
+ .parent = &clk_osc,
+ .regofs = SIRFSOC_CLKC_PLL3_CFG0,
+ .ops = &std_pll_ops,
+};
+
+/*
+ * clock domains - cpu, mem, sys/io
+ */
+
+static struct clk clk_mem;
+
+static struct clk *dmn_get_parent(struct clk *clk)
+{
+ struct clk *clks[] = {
+ &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+ };
+ u32 cfg = clkc_readl(clk->regofs);
+ WARN_ON((cfg & (BIT(3) - 1)) > 4);
+ return clks[cfg & (BIT(3) - 1)];
+}
+
+static int dmn_set_parent(struct clk *clk, struct clk *parent)
+{
+ const struct clk *clks[] = {
+ &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+ };
+ u32 cfg = clkc_readl(clk->regofs);
+ int i;
+ for (i = 0; i < ARRAY_SIZE(clks); i++) {
+ if (clks[i] == parent) {
+ cfg &= ~(BIT(3) - 1);
+ clkc_writel(cfg | i, clk->regofs);
+ /* BIT(3) - switching status: 1 - busy, 0 - done */
+ while (clkc_readl(clk->regofs) & BIT(3))
+ cpu_relax();
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static unsigned long dmn_get_rate(struct clk *clk)
+{
+ unsigned long fin = clk_get_rate(clk->parent);
+ u32 cfg = clkc_readl(clk->regofs);
+ if (cfg & BIT(24)) {
+ /* fcd bypass mode */
+ clk->rate = fin;
+ } else {
+ /*
+ * wait count: bit[19:16], hold count: bit[23:20]
+ */
+ u32 wait = (cfg >> 16) & (BIT(4) - 1);
+ u32 hold = (cfg >> 20) & (BIT(4) - 1);
+
+ clk->rate = fin / (wait + hold + 2);
+ }
+
+ return clk->rate;
+}
+
+static int dmn_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long fin;
+ unsigned ratio, wait, hold, reg;
+ unsigned bits = (clk == &clk_mem) ? 3 : 4;
+
+ fin = clk_get_rate(clk->parent);
+ ratio = fin / rate;
+
+ if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
+ return -EINVAL;
+
+ WARN_ON(fin % rate);
+
+ wait = (ratio >> 1) - 1;
+ hold = ratio - wait - 2;
+
+ reg = clkc_readl(clk->regofs);
+ reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
+ reg |= (wait << 16) | (hold << 20) | BIT(25);
+ clkc_writel(reg, clk->regofs);
+
+ /* waiting FCD been effective */
+ while (clkc_readl(clk->regofs) & BIT(25))
+ cpu_relax();
+
+ clk->rate = 0; /* set to zero will force recalculation */
+
+ return 0;
+}
+
+/*
+ * cpu clock has no FCD register in Prima2, can only change pll
+ */
+static int cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret1, ret2;
+ struct clk *cur_parent, *tmp_parent;
+
+ cur_parent = dmn_get_parent(clk);
+ BUG_ON(cur_parent == NULL || cur_parent->usage > 1);
+
+ /* switch to tmp pll before setting parent clock's rate */
+ tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1;
+ ret1 = dmn_set_parent(clk, tmp_parent);
+ BUG_ON(ret1);
+
+ ret2 = clk_set_rate(cur_parent, rate);
+
+ ret1 = dmn_set_parent(clk, cur_parent);
+
+ clk->rate = 0; /* set to zero will force recalculation */
+
+ return ret2 ? ret2 : ret1;
+}
+
+static struct clk_ops cpu_ops = {
+ .get_parent = dmn_get_parent,
+ .set_parent = dmn_set_parent,
+ .set_rate = cpu_set_rate,
+};
+
+static struct clk clk_cpu = {
+ .parent = &clk_pll1,
+ .regofs = SIRFSOC_CLKC_CPU_CFG,
+ .ops = &cpu_ops,
+};
+
+
+static struct clk_ops msi_ops = {
+ .set_rate = dmn_set_rate,
+ .get_rate = dmn_get_rate,
+ .set_parent = dmn_set_parent,
+ .get_parent = dmn_get_parent,
+};
+
+static struct clk clk_mem = {
+ .parent = &clk_pll2,
+ .regofs = SIRFSOC_CLKC_MEM_CFG,
+ .ops = &msi_ops,
+};
+
+static struct clk clk_sys = {
+ .parent = &clk_pll3,
+ .regofs = SIRFSOC_CLKC_SYS_CFG,
+ .ops = &msi_ops,
+};
+
+static struct clk clk_io = {
+ .parent = &clk_pll3,
+ .regofs = SIRFSOC_CLKC_IO_CFG,
+ .ops = &msi_ops,
+};
+
+/*
+ * on-chip clock sets
+ */
+static struct clk_lookup onchip_clks[] = {
+ {
+ .dev_id = "rtc",
+ .clk = &clk_rtc,
+ }, {
+ .dev_id = "osc",
+ .clk = &clk_osc,
+ }, {
+ .dev_id = "pll1",
+ .clk = &clk_pll1,
+ }, {
+ .dev_id = "pll2",
+ .clk = &clk_pll2,
+ }, {
+ .dev_id = "pll3",
+ .clk = &clk_pll3,
+ }, {
+ .dev_id = "cpu",
+ .clk = &clk_cpu,
+ }, {
+ .dev_id = "mem",
+ .clk = &clk_mem,
+ }, {
+ .dev_id = "sys",
+ .clk = &clk_sys,
+ }, {
+ .dev_id = "io",
+ .clk = &clk_io,
+ },
+};
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return -EINVAL;
+
+ if (clk->parent)
+ clk_enable(clk->parent);
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ if (!clk->usage++ && clk->ops && clk->ops->enable)
+ clk->ops->enable(clk);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return;
+
+ WARN_ON(!clk->usage);
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ if (--clk->usage == 0 && clk->ops && clk->ops->disable)
+ clk->ops->disable(clk);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ if (clk->parent)
+ clk_disable(clk->parent);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return 0;
+
+ if (clk->rate)
+ return clk->rate;
+
+ if (clk->ops && clk->ops->get_rate)
+ return clk->ops->get_rate(clk);
+
+ return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return 0;
+
+ if (clk->ops && clk->ops->round_rate)
+ return clk->ops->round_rate(clk, rate);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return -EINVAL;
+
+ if (!clk->ops || !clk->ops->set_rate)
+ return -EINVAL;
+
+ return clk->ops->set_rate(clk, rate);
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret;
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return -EINVAL;
+
+ if (!clk->ops || !clk->ops->set_parent)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ ret = clk->ops->set_parent(clk, parent);
+ if (!ret) {
+ parent->usage += clk->usage;
+ clk->parent->usage -= clk->usage;
+ BUG_ON(clk->parent->usage < 0);
+ clk->parent = parent;
+ }
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (unlikely(IS_ERR_OR_NULL(clk)))
+ return NULL;
+
+ if (!clk->ops || !clk->ops->get_parent)
+ return clk->parent;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ clk->parent = clk->ops->get_parent(clk);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+static void __init sirfsoc_clk_init(void)
+{
+ clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));
+}
+
+static struct of_device_id clkc_ids[] = {
+ { .compatible = "sirf,prima2-clkc" },
+};
+
+void __init sirfsoc_of_clk_init(void)
+{
+ struct device_node *np;
+ struct resource res;
+ struct map_desc sirfsoc_clkc_iodesc = {
+ .virtual = SIRFSOC_CLOCK_VA_BASE,
+ .type = MT_DEVICE,
+ };
+
+ np = of_find_matching_node(NULL, clkc_ids);
+ if (!np)
+ panic("unable to find compatible clkc node in dtb\n");
+
+ if (of_address_to_resource(np, 0, &res))
+ panic("unable to find clkc range in dtb");
+ of_node_put(np);
+
+ sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start);
+ sirfsoc_clkc_iodesc.length = 1 + res.end - res.start;
+
+ iotable_init(&sirfsoc_clkc_iodesc, 1);
+
+ sirfsoc_clk_init();
+}
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
new file mode 100644
index 000000000000..83e5d2128118
--- /dev/null
+++ b/arch/arm/mach-prima2/common.h
@@ -0,0 +1,26 @@
+/*
+ * This file contains common function prototypes to avoid externs in the c files.
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_COMMON_H__
+#define __MACH_PRIMA2_COMMON_H__
+
+#include <linux/init.h>
+#include <asm/mach/time.h>
+
+extern struct sys_timer sirfsoc_timer;
+
+extern void __init sirfsoc_of_irq_init(void);
+extern void __init sirfsoc_of_clk_init(void);
+
+#ifndef CONFIG_DEBUG_LL
+static inline void sirfsoc_map_lluart(void) {}
+#else
+extern void __init sirfsoc_map_lluart(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/clkdev.h b/arch/arm/mach-prima2/include/mach/clkdev.h
new file mode 100644
index 000000000000..66932518b1b7
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/clkdev.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/clkdev.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/debug-macro.S b/arch/arm/mach-prima2/include/mach/debug-macro.S
new file mode 100644
index 000000000000..bf75106333ff
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/debug-macro.S
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+ .macro addruart, rp, rv
+ ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical
+ ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
+ .endm
+
+ .macro busyuart,rd,rx
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
+ tst \rd, #SIRFSOC_UART1_TXFIFO_EMPTY
+ beq 1001b
+ .endm
+
diff --git a/arch/arm/mach-prima2/include/mach/entry-macro.S b/arch/arm/mach-prima2/include/mach/entry-macro.S
new file mode 100644
index 000000000000..1c8a50f102a7
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/entry-macro.S
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+
+#define SIRFSOC_INT_ID 0x38
+
+ .macro get_irqnr_preamble, base, tmp
+ ldr \base, =sirfsoc_intc_base
+ ldr \base, [\base]
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \irqnr, [\base, #SIRFSOC_INT_ID] @ Get the highest priority irq
+ cmp \irqnr, #0x40 @ the irq num can't be larger than 0x3f
+ movges \irqnr, #0
+ .endm
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
diff --git a/arch/arm/mach-prima2/include/mach/hardware.h b/arch/arm/mach-prima2/include/mach/hardware.h
new file mode 100644
index 000000000000..105b96964f25
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/hardware.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/hardware.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#include <asm/sizes.h>
+#include <mach/map.h>
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/io.h b/arch/arm/mach-prima2/include/mach/io.h
new file mode 100644
index 000000000000..6c31e9ec279e
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/io.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/mach-prima2/include/mach/io.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_IO_H
+#define __MACH_PRIMA2_IO_H
+
+#define IO_SPACE_LIMIT ((resource_size_t)0)
+
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
new file mode 100644
index 000000000000..bb354f952fd6
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/irqs.h
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-prima2/include/mach/irqs.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define SIRFSOC_INTENAL_IRQ_START 0
+#define SIRFSOC_INTENAL_IRQ_END 59
+
+#define NR_IRQS 220
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/map.h b/arch/arm/mach-prima2/include/mach/map.h
new file mode 100644
index 000000000000..66b1ae2e553f
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/map.h
@@ -0,0 +1,16 @@
+/*
+ * memory & I/O static mapping definitions for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_MAP_H__
+#define __MACH_PRIMA2_MAP_H__
+
+#include <mach/vmalloc.h>
+
+#define SIRFSOC_VA(x) (VMALLOC_END + ((x) & 0x00FFF000))
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/memory.h b/arch/arm/mach-prima2/include/mach/memory.h
new file mode 100644
index 000000000000..368cd5a0601a
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/memory.h
@@ -0,0 +1,21 @@
+/*
+ * 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/include/mach/system.h b/arch/arm/mach-prima2/include/mach/system.h
new file mode 100644
index 000000000000..0dbd257ad16d
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/system.h
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/system.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+#include <linux/bitops.h>
+#include <mach/hardware.h>
+
+#define SIRFSOC_SYS_RST_BIT BIT(31)
+
+extern void __iomem *sirfsoc_rstc_base;
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base);
+}
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/timex.h b/arch/arm/mach-prima2/include/mach/timex.h
new file mode 100644
index 000000000000..d6f98a75e562
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/timex.h
@@ -0,0 +1,14 @@
+/*
+ * arch/arm/mach-prima2/include/mach/timex.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+#define CLOCK_TICK_RATE 1000000
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h
new file mode 100644
index 000000000000..c98b4d5ac24a
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/uart.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uart.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_SIRFSOC_UART_H
+#define __MACH_PRIMA2_SIRFSOC_UART_H
+
+/* UART-1: used as serial debug port */
+#define SIRFSOC_UART1_PA_BASE 0xb0060000
+#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000)
+#define SIRFSOC_UART1_SIZE SZ_4K
+
+#define SIRFSOC_UART_TXFIFO_STATUS 0x0114
+#define SIRFSOC_UART_TXFIFO_DATA 0x0118
+
+#define SIRFSOC_UART1_TXFIFO_FULL (1 << 5)
+#define SIRFSOC_UART1_TXFIFO_EMPTY (1 << 6)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
new file mode 100644
index 000000000000..83125c6a30b3
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/uncompress.h
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uncompress.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+#define arch_decomp_wdog()
+
+static __inline__ void putc(char c)
+{
+ /*
+ * during kernel decompression, all mappings are flat:
+ * virt_addr == phys_addr
+ */
+ while (__raw_readl(SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
+ & SIRFSOC_UART1_TXFIFO_FULL)
+ barrier();
+
+ __raw_writel(c, SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
+}
+
+static inline void flush(void)
+{
+}
+
+#endif
+
diff --git a/arch/arm/mach-prima2/include/mach/vmalloc.h b/arch/arm/mach-prima2/include/mach/vmalloc.h
new file mode 100644
index 000000000000..c9f90fec78e3
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/ach-prima2/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_VMALLOC_H
+#define __MACH_VMALLOC_H
+
+#include <linux/const.h>
+
+#define VMALLOC_END _AC(0xFEC00000, UL)
+
+#endif
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
new file mode 100644
index 000000000000..c3404cbb6ff7
--- /dev/null
+++ b/arch/arm/mach-prima2/irq.c
@@ -0,0 +1,71 @@
+/*
+ * interrupt controller support 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/io.h>
+#include <linux/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SIRFSOC_INT_RISC_MASK0 0x0018
+#define SIRFSOC_INT_RISC_MASK1 0x001C
+#define SIRFSOC_INT_RISC_LEVEL0 0x0020
+#define SIRFSOC_INT_RISC_LEVEL1 0x0024
+
+void __iomem *sirfsoc_intc_base;
+
+static __init void
+sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq);
+ ct = gc->chip_types;
+
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
+}
+
+static __init void sirfsoc_irq_init(void)
+{
+ sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
+ sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32);
+
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+ writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+}
+
+static struct of_device_id intc_ids[] = {
+ { .compatible = "sirf,prima2-intc" },
+};
+
+void __init sirfsoc_of_irq_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, intc_ids);
+ if (!np)
+ panic("unable to find compatible intc node in dtb\n");
+
+ sirfsoc_intc_base = of_iomap(np, 0);
+ if (!sirfsoc_intc_base)
+ panic("unable to map intc cpu registers\n");
+
+ of_node_put(np);
+
+ sirfsoc_irq_init();
+}
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
new file mode 100644
index 000000000000..9cda2057bcfb
--- /dev/null
+++ b/arch/arm/mach-prima2/l2x0.c
@@ -0,0 +1,59 @@
+/*
+ * l2 cache initialization 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/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 int __init sirfsoc_of_l2x_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);
+ }
+ l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
+ 0x00000000);
+
+ return 0;
+}
+early_initcall(sirfsoc_of_l2x_init);
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
new file mode 100644
index 000000000000..a89f9b3c8cc5
--- /dev/null
+++ b/arch/arm/mach-prima2/lluart.c
@@ -0,0 +1,25 @@
+/*
+ * Static memory mapping for DEBUG_LL
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+#include <mach/uart.h>
+
+void __init sirfsoc_map_lluart(void)
+{
+ struct map_desc sirfsoc_lluart_map = {
+ .virtual = SIRFSOC_UART1_VA_BASE,
+ .pfn = __phys_to_pfn(SIRFSOC_UART1_PA_BASE),
+ .length = SIRFSOC_UART1_SIZE,
+ .type = MT_DEVICE,
+ };
+
+ iotable_init(&sirfsoc_lluart_map, 1);
+}
diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
new file mode 100644
index 000000000000..f57124bdd143
--- /dev/null
+++ b/arch/arm/mach-prima2/prima2.c
@@ -0,0 +1,41 @@
+/*
+ * Defines machines 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/kernel.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include "common.h"
+
+static struct of_device_id sirfsoc_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ {},
+};
+
+void __init sirfsoc_mach_init(void)
+{
+ of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL);
+}
+
+static const char *prima2cb_dt_match[] __initdata = {
+ "sirf,prima2-cb",
+ NULL
+};
+
+MACHINE_START(PRIMA2_EVB, "prima2cb")
+ /* Maintainer: Barry Song <baohua.song@csr.com> */
+ .boot_params = 0x00000100,
+ .init_early = sirfsoc_of_clk_init,
+ .map_io = sirfsoc_map_lluart,
+ .init_irq = sirfsoc_of_irq_init,
+ .timer = &sirfsoc_timer,
+ .init_machine = sirfsoc_mach_init,
+ .dt_compat = prima2cb_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c
new file mode 100644
index 000000000000..d074786e83d4
--- /dev/null
+++ b/arch/arm/mach-prima2/rstc.c
@@ -0,0 +1,69 @@
+/*
+ * reset controller 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/mutex.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __iomem *sirfsoc_rstc_base;
+static DEFINE_MUTEX(rstc_lock);
+
+static struct of_device_id rstc_ids[] = {
+ { .compatible = "sirf,prima2-rstc" },
+};
+
+static int __init sirfsoc_of_rstc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, rstc_ids);
+ if (!np)
+ panic("unable to find compatible rstc node in dtb\n");
+
+ sirfsoc_rstc_base = of_iomap(np, 0);
+ if (!sirfsoc_rstc_base)
+ panic("unable to map rstc cpu registers\n");
+
+ of_node_put(np);
+
+ return 0;
+}
+early_initcall(sirfsoc_of_rstc_init);
+
+int sirfsoc_reset_device(struct device *dev)
+{
+ const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL);
+ unsigned int reset_bit;
+
+ if (!prop)
+ return -ENODEV;
+
+ reset_bit = be32_to_cpup(prop);
+
+ mutex_lock(&rstc_lock);
+
+ /*
+ * Writing 1 to this bit resets corresponding block. Writing 0 to this
+ * bit de-asserts reset signal of the corresponding block.
+ * datasheet doesn't require explicit delay between the set and clear
+ * of reset bit. it could be shorter if tests pass.
+ */
+ writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
+ sirfsoc_rstc_base + (reset_bit / 32) * 4);
+ msleep(10);
+ writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
+ sirfsoc_rstc_base + (reset_bit / 32) * 4);
+
+ mutex_unlock(&rstc_lock);
+
+ return 0;
+}
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c
new file mode 100644
index 000000000000..44027f34a88a
--- /dev/null
+++ b/arch/arm/mach-prima2/timer.c
@@ -0,0 +1,217 @@
+/*
+ * System timer 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/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/map.h>
+#include <asm/mach/time.h>
+
+#define SIRFSOC_TIMER_COUNTER_LO 0x0000
+#define SIRFSOC_TIMER_COUNTER_HI 0x0004
+#define SIRFSOC_TIMER_MATCH_0 0x0008
+#define SIRFSOC_TIMER_MATCH_1 0x000C
+#define SIRFSOC_TIMER_MATCH_2 0x0010
+#define SIRFSOC_TIMER_MATCH_3 0x0014
+#define SIRFSOC_TIMER_MATCH_4 0x0018
+#define SIRFSOC_TIMER_MATCH_5 0x001C
+#define SIRFSOC_TIMER_STATUS 0x0020
+#define SIRFSOC_TIMER_INT_EN 0x0024
+#define SIRFSOC_TIMER_WATCHDOG_EN 0x0028
+#define SIRFSOC_TIMER_DIV 0x002C
+#define SIRFSOC_TIMER_LATCH 0x0030
+#define SIRFSOC_TIMER_LATCHED_LO 0x0034
+#define SIRFSOC_TIMER_LATCHED_HI 0x0038
+
+#define SIRFSOC_TIMER_WDT_INDEX 5
+
+#define SIRFSOC_TIMER_LATCH_BIT BIT(0)
+
+static void __iomem *sirfsoc_timer_base;
+static void __init sirfsoc_of_timer_map(void);
+
+/* timer0 interrupt handler */
+static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *ce = dev_id;
+
+ WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
+
+ /* clear timer0 interrupt */
+ writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+ ce->event_handler(ce);
+
+ return IRQ_HANDLED;
+}
+
+/* read 64-bit timer counter */
+static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+{
+ u64 cycles;
+
+ /* latch the 64-bit timer counter */
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+ cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
+ cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+ return cycles;
+}
+
+static int sirfsoc_timer_set_next_event(unsigned long delta,
+ struct clock_event_device *ce)
+{
+ unsigned long now, next;
+
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+ now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+ next = now + delta;
+ writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+ now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+ return next - now > delta ? -ETIME : 0;
+}
+
+static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *ce)
+{
+ u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ WARN_ON(1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static struct clock_event_device sirfsoc_clockevent = {
+ .name = "sirfsoc_clockevent",
+ .rating = 200,
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = sirfsoc_timer_set_mode,
+ .set_next_event = sirfsoc_timer_set_next_event,
+};
+
+static struct clocksource sirfsoc_clocksource = {
+ .name = "sirfsoc_clocksource",
+ .rating = 200,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .read = sirfsoc_timer_read,
+};
+
+static struct irqaction sirfsoc_timer_irq = {
+ .name = "sirfsoc_timer0",
+ .flags = IRQF_TIMER,
+ .irq = 0,
+ .handler = sirfsoc_timer_interrupt,
+ .dev_id = &sirfsoc_clockevent,
+};
+
+/* Overwrite weak default sched_clock with more precise one */
+unsigned long long notrace sched_clock(void)
+{
+ static int is_mapped = 0;
+
+ /*
+ * 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) {
+ sirfsoc_of_timer_map();
+ is_mapped = 1;
+ }
+
+ return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE);
+}
+
+static void __init sirfsoc_clockevent_init(void)
+{
+ clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
+
+ sirfsoc_clockevent.max_delta_ns =
+ clockevent_delta2ns(-2, &sirfsoc_clockevent);
+ sirfsoc_clockevent.min_delta_ns =
+ clockevent_delta2ns(2, &sirfsoc_clockevent);
+
+ sirfsoc_clockevent.cpumask = cpumask_of(0);
+ clockevents_register_device(&sirfsoc_clockevent);
+}
+
+/* initialize the kernel jiffy timer source */
+static void __init sirfsoc_timer_init(void)
+{
+ unsigned long rate;
+
+ /* timer's input clock is io clock */
+ struct clk *clk = clk_get_sys("io", NULL);
+
+ BUG_ON(IS_ERR(clk));
+
+ rate = clk_get_rate(clk);
+
+ BUG_ON(rate < CLOCK_TICK_RATE);
+ BUG_ON(rate % CLOCK_TICK_RATE);
+
+ writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
+ writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+ writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+ writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+ BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
+
+ BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
+
+ sirfsoc_clockevent_init();
+}
+
+static struct of_device_id timer_ids[] = {
+ { .compatible = "sirf,prima2-tick" },
+};
+
+static void __init sirfsoc_of_timer_map(void)
+{
+ struct device_node *np;
+ const unsigned int *intspec;
+
+ np = of_find_matching_node(NULL, timer_ids);
+ if (!np)
+ panic("unable to find compatible timer node in dtb\n");
+ sirfsoc_timer_base = of_iomap(np, 0);
+ if (!sirfsoc_timer_base)
+ panic("unable to map timer cpu registers\n");
+
+ /* Get the interrupts property */
+ intspec = of_get_property(np, "interrupts", NULL);
+ BUG_ON(!intspec);
+ sirfsoc_timer_irq.irq = be32_to_cpup(intspec);
+
+ of_node_put(np);
+}
+
+struct sys_timer sirfsoc_timer = {
+ .init = sirfsoc_timer_init,
+};
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 810a982a66f8..ef3e8b1e06c1 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -825,6 +825,7 @@ MACHINE_START(BALLOON3, "Balloon3")
.map_io = balloon3_map_io,
.nr_irqs = BALLOON3_NR_IRQS,
.init_irq = balloon3_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = balloon3_init,
.boot_params = PLAT_PHYS_OFFSET + 0x100,
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
index 4284513f396a..648b0ab2bf77 100644
--- a/arch/arm/mach-pxa/capc7117.c
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -151,6 +151,7 @@ MACHINE_START(CAPC7117,
.boot_params = 0xa0000100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = capc7117_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index d5152220ce94..4d466102a027 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -53,6 +53,21 @@ unsigned long clk_get_rate(struct clk *clk)
}
EXPORT_SYMBOL(clk_get_rate);
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (clk->ops->setrate) {
+ spin_lock_irqsave(&clocks_lock, flags);
+ ret = clk->ops->setrate(clk, rate);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
void clk_dummy_enable(struct clk *clk)
{
}
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index 1f2fb9c43f06..3a258b1bf1aa 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -5,6 +5,7 @@ struct clkops {
void (*enable)(struct clk *);
void (*disable)(struct clk *);
unsigned long (*getrate)(struct clk *);
+ int (*setrate)(struct clk *, unsigned long);
};
struct clk {
diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c
index 1afc0fb7d6d5..4eb7660a279d 100644
--- a/arch/arm/mach-pxa/cm-x2xx-pci.c
+++ b/arch/arm/mach-pxa/cm-x2xx-pci.c
@@ -125,6 +125,9 @@ static void cmx2xx_pci_preinit(void)
{
pr_info("Initializing CM-X2XX PCI subsystem\n");
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0;
+
__raw_writel(0x800, IT8152_PCI_CFG_ADDR);
if (__raw_readl(IT8152_PCI_CFG_DATA) == 0x81521283) {
pr_info("PCI Bridge found.\n");
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index a10996782476..13cf518bbbf8 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -21,7 +21,8 @@
#include <asm/mach-types.h>
#include <asm/mach/map.h>
-#include <mach/pxa2xx-regs.h>
+#include <mach/pxa25x.h>
+#include <mach/pxa27x.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
#include <mach/smemc.h>
@@ -516,6 +517,11 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX")
.map_io = cmx2xx_map_io,
.nr_irqs = CMX2XX_NR_IRQS,
.init_irq = cmx2xx_init_irq,
+ /* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = cmx2xx_init,
+#ifdef CONFIG_PCI
+ .dma_zone_size = SZ_64M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index b2248e76ec8b..b6a51340270b 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -12,6 +12,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/module.h>
#include <linux/kernel.h>
@@ -161,10 +162,10 @@ static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
GPIO99_GPIO, /* Ethernet IRQ */
/* RTC GPIOs */
- GPIO95_GPIO, /* RTC CS */
- GPIO96_GPIO, /* RTC WR */
- GPIO97_GPIO, /* RTC RD */
- GPIO98_GPIO, /* RTC IO */
+ GPIO95_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC CS */
+ GPIO96_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC WR */
+ GPIO97_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC RD */
+ GPIO98_GPIO, /* RTC IO */
/* Standard I2C */
GPIO21_I2C_SCL,
@@ -484,14 +485,13 @@ static int cm_x300_ulpi_phy_reset(void)
int err;
/* reset the PHY */
- err = gpio_request(GPIO_ULPI_PHY_RST, "ulpi reset");
+ err = gpio_request_one(GPIO_ULPI_PHY_RST, GPIOF_OUT_INIT_LOW,
+ "ulpi reset");
if (err) {
- pr_err("%s: failed to request ULPI reset GPIO: %d\n",
- __func__, err);
+ pr_err("failed to request ULPI reset GPIO: %d\n", err);
return err;
}
- gpio_direction_output(GPIO_ULPI_PHY_RST, 0);
msleep(10);
gpio_set_value(GPIO_ULPI_PHY_RST, 1);
msleep(10);
@@ -510,8 +510,7 @@ static inline int cm_x300_u2d_init(struct device *dev)
pout_clk = clk_get(NULL, "CLK_POUT");
if (IS_ERR(pout_clk)) {
err = PTR_ERR(pout_clk);
- pr_err("%s: failed to get CLK_POUT: %d\n",
- __func__, err);
+ pr_err("failed to get CLK_POUT: %d\n", err);
return err;
}
clk_enable(pout_clk);
@@ -768,39 +767,36 @@ static void __init cm_x300_init_da9030(void)
irq_set_irq_wake(IRQ_WAKEUP0, 1);
}
+/* wi2wi gpio setting for system_rev >= 130 */
+static struct gpio cm_x300_wi2wi_gpios[] __initdata = {
+ { 71, GPIOF_OUT_INIT_HIGH, "wlan en" },
+ { 70, GPIOF_OUT_INIT_HIGH, "bt reset" },
+};
+
static void __init cm_x300_init_wi2wi(void)
{
int bt_reset, wlan_en;
int err;
if (system_rev < 130) {
- wlan_en = 77;
- bt_reset = 78;
- } else {
- wlan_en = 71;
- bt_reset = 70;
+ cm_x300_wi2wi_gpios[0].gpio = 77; /* wlan en */
+ cm_x300_wi2wi_gpios[1].gpio = 78; /* bt reset */
}
/* Libertas and CSR reset */
- err = gpio_request(wlan_en, "wlan en");
+ err = gpio_request_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
if (err) {
- pr_err("CM-X300: failed to request wlan en gpio: %d\n", err);
- } else {
- gpio_direction_output(wlan_en, 1);
- gpio_free(wlan_en);
+ pr_err("failed to request wifi/bt gpios: %d\n", err);
+ return;
}
- err = gpio_request(bt_reset, "bt reset");
- if (err) {
- pr_err("CM-X300: failed to request bt reset gpio: %d\n", err);
- } else {
- gpio_direction_output(bt_reset, 1);
- udelay(10);
- gpio_set_value(bt_reset, 0);
- udelay(10);
- gpio_set_value(bt_reset, 1);
- gpio_free(bt_reset);
- }
+ udelay(10);
+ gpio_set_value(bt_reset, 0);
+ udelay(10);
+ gpio_set_value(bt_reset, 1);
+
+ gpio_free(wlan_en);
+ gpio_free(bt_reset);
}
/* MFP */
@@ -859,6 +855,7 @@ MACHINE_START(CM_X300, "CM-X300 module")
.boot_params = 0xa0000100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = cm_x300_init,
.fixup = cm_x300_fixup,
diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index 7545a48ed88b..870920934ecf 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -310,6 +310,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
.init_machine = colibri_pxa270_init,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
MACHINE_END
@@ -318,6 +319,7 @@ MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
.init_machine = colibri_pxa270_income_init,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index 66dd81cbc8a0..60a6781e7a8e 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -187,6 +187,7 @@ MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
.init_machine = colibri_pxa300_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index ff9ff5f4fc47..d2c6631915d4 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -23,8 +23,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa320.h>
+#include <mach/pxa320.h>
#include <mach/colibri.h>
#include <mach/pxafb.h>
#include <mach/ohci.h>
@@ -258,6 +257,7 @@ MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
.init_machine = colibri_pxa320_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 3a5507e31919..185a37cad254 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -722,6 +722,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
.fixup = fixup_corgi,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
@@ -732,6 +733,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
.fixup = fixup_corgi,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
@@ -742,6 +744,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
.fixup = fixup_corgi,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 0481c29a70e8..fe812eafb1f1 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -22,10 +22,9 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/csb726.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
#include <mach/mmc.h>
#include <mach/ohci.h>
-#include <mach/pxa2xx-regs.h>
#include <mach/audio.h>
#include <mach/smemc.h>
@@ -276,6 +275,7 @@ MACHINE_START(CSB726, "Cogent CSB726")
.boot_params = 0xa0000100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.init_machine = csb726_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index f8a6e9d79a3a..2e37ea52b372 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -1302,6 +1302,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270")
.boot_params = 0xa0000100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = em_x270_init,
MACHINE_END
@@ -1310,6 +1311,7 @@ MACHINE_START(EXEDA, "Compulab eXeda")
.boot_params = 0xa0000100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = em_x270_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index 2e3970fdde0b..b4599ec9d619 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -193,6 +193,7 @@ MACHINE_START(E330, "Toshiba e330")
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.fixup = eseries_fixup,
.init_machine = e330_init,
.timer = &pxa_timer,
@@ -242,6 +243,7 @@ MACHINE_START(E350, "Toshiba e350")
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.fixup = eseries_fixup,
.init_machine = e350_init,
.timer = &pxa_timer,
@@ -364,6 +366,7 @@ MACHINE_START(E400, "Toshiba e400")
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.fixup = eseries_fixup,
.init_machine = e400_init,
.timer = &pxa_timer,
@@ -552,6 +555,7 @@ MACHINE_START(E740, "Toshiba e740")
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.fixup = eseries_fixup,
.init_machine = e740_init,
.timer = &pxa_timer,
@@ -743,6 +747,7 @@ MACHINE_START(E750, "Toshiba e750")
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.fixup = eseries_fixup,
.init_machine = e750_init,
.timer = &pxa_timer,
@@ -947,6 +952,7 @@ MACHINE_START(E800, "Toshiba e800")
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.fixup = eseries_fixup,
.init_machine = e800_init,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index d88aed8fbe15..b73eadb9f5dc 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -801,6 +801,7 @@ MACHINE_START(EZX_A780, "Motorola EZX A780")
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = a780_init,
MACHINE_END
@@ -866,6 +867,7 @@ MACHINE_START(EZX_E680, "Motorola EZX E680")
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = e680_init,
MACHINE_END
@@ -931,6 +933,7 @@ MACHINE_START(EZX_A1200, "Motorola EZX A1200")
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = a1200_init,
MACHINE_END
@@ -1121,6 +1124,7 @@ MACHINE_START(EZX_A910, "Motorola EZX A910")
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = a910_init,
MACHINE_END
@@ -1186,6 +1190,7 @@ MACHINE_START(EZX_E6, "Motorola EZX E6")
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = e6_init,
MACHINE_END
@@ -1225,6 +1230,7 @@ MACHINE_START(EZX_E2, "Motorola EZX E2")
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = e2_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index e6c9344a95ae..92a2e85ab02c 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -13,21 +13,8 @@ struct irq_data;
struct sys_timer;
extern struct sys_timer pxa_timer;
-extern void __init pxa_init_irq(int irq_nr,
- int (*set_wake)(struct irq_data *,
- unsigned int));
-extern void __init pxa25x_init_irq(void);
-#ifdef CONFIG_CPU_PXA26x
-extern void __init pxa26x_init_irq(void);
-#endif
-extern void __init pxa27x_init_irq(void);
-extern void __init pxa3xx_init_irq(void);
-extern void __init pxa95x_init_irq(void);
extern void __init pxa_map_io(void);
-extern void __init pxa25x_map_io(void);
-extern void __init pxa27x_map_io(void);
-extern void __init pxa3xx_map_io(void);
extern unsigned int get_clk_frequency_khz(int info);
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index d65e4bde9b91..deaa111c91f9 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -236,6 +236,7 @@ MACHINE_START(GUMSTIX, "Gumstix")
.boot_params = 0xa0000100, /* match u-boot bi_boot_params */
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = gumstix_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index 657db469de1f..0a235128914d 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -28,6 +28,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/irq.h>
#include <mach/pxa25x.h>
#include <mach/h5000.h>
@@ -205,6 +206,7 @@ MACHINE_START(H5400, "HP iPAQ H5000")
.boot_params = 0xa0000100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = h5000_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
index e8603eba54bd..a997d0ab2872 100644
--- a/arch/arm/mach-pxa/himalaya.c
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -24,8 +24,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <mach/mfp-pxa25x.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
#include "generic.h"
@@ -162,6 +161,7 @@ MACHINE_START(HIMALAYA, "HTC Himalaya")
.boot_params = 0xa0000100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.init_machine = himalaya_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index f941a495a4a8..c748a473a2ff 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -135,42 +135,6 @@ static unsigned long hx4700_pin_config[] __initdata = {
GPIO66_GPIO, /* nSDIO_IRQ */
};
-#define HX4700_GPIO_IN(num, _desc) \
- { .gpio = (num), .dir = 0, .desc = (_desc) }
-#define HX4700_GPIO_OUT(num, _init, _desc) \
- { .gpio = (num), .dir = 1, .init = (_init), .desc = (_desc) }
-struct gpio_ress {
- unsigned gpio : 8;
- unsigned dir : 1;
- unsigned init : 1;
- char *desc;
-};
-
-static int hx4700_gpio_request(struct gpio_ress *gpios, int size)
-{
- int i, rc = 0;
- int gpio;
- int dir;
-
- for (i = 0; (!rc) && (i < size); i++) {
- gpio = gpios[i].gpio;
- dir = gpios[i].dir;
- rc = gpio_request(gpio, gpios[i].desc);
- if (rc) {
- pr_err("Error requesting GPIO %d(%s) : %d\n",
- gpio, gpios[i].desc, rc);
- continue;
- }
- if (dir)
- gpio_direction_output(gpio, gpios[i].init);
- else
- gpio_direction_input(gpio);
- }
- while ((rc) && (--i >= 0))
- gpio_free(gpios[i].gpio);
- return rc;
-}
-
/*
* IRDA
*/
@@ -829,26 +793,30 @@ static struct platform_device *devices[] __initdata = {
&pcmcia,
};
-static struct gpio_ress global_gpios[] = {
- HX4700_GPIO_IN(GPIO12_HX4700_ASIC3_IRQ, "ASIC3_IRQ"),
- HX4700_GPIO_IN(GPIO13_HX4700_W3220_IRQ, "W3220_IRQ"),
- HX4700_GPIO_IN(GPIO14_HX4700_nWLAN_IRQ, "WLAN_IRQ"),
- HX4700_GPIO_OUT(GPIO59_HX4700_LCD_PC1, 1, "LCD_PC1"),
- HX4700_GPIO_OUT(GPIO62_HX4700_LCD_nRESET, 1, "LCD_RESET"),
- HX4700_GPIO_OUT(GPIO70_HX4700_LCD_SLIN1, 1, "LCD_SLIN1"),
- HX4700_GPIO_OUT(GPIO84_HX4700_LCD_SQN, 1, "LCD_SQN"),
- HX4700_GPIO_OUT(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1, "LCD_LVDD"),
- HX4700_GPIO_OUT(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1, "LCD_AVDD"),
- HX4700_GPIO_OUT(GPIO32_HX4700_RS232_ON, 1, "RS232_ON"),
- HX4700_GPIO_OUT(GPIO71_HX4700_ASIC3_nRESET, 1, "ASIC3_nRESET"),
- HX4700_GPIO_OUT(GPIO82_HX4700_EUART_RESET, 1, "EUART_RESET"),
- HX4700_GPIO_OUT(GPIO105_HX4700_nIR_ON, 1, "nIR_EN"),
+static struct gpio global_gpios[] = {
+ { GPIO12_HX4700_ASIC3_IRQ, GPIOF_IN, "ASIC3_IRQ" },
+ { GPIO13_HX4700_W3220_IRQ, GPIOF_IN, "W3220_IRQ" },
+ { GPIO14_HX4700_nWLAN_IRQ, GPIOF_IN, "WLAN_IRQ" },
+ { GPIO59_HX4700_LCD_PC1, GPIOF_OUT_INIT_HIGH, "LCD_PC1" },
+ { GPIO62_HX4700_LCD_nRESET, GPIOF_OUT_INIT_HIGH, "LCD_RESET" },
+ { GPIO70_HX4700_LCD_SLIN1, GPIOF_OUT_INIT_HIGH, "LCD_SLIN1" },
+ { GPIO84_HX4700_LCD_SQN, GPIOF_OUT_INIT_HIGH, "LCD_SQN" },
+ { GPIO110_HX4700_LCD_LVDD_3V3_ON, GPIOF_OUT_INIT_HIGH, "LCD_LVDD" },
+ { GPIO111_HX4700_LCD_AVDD_3V3_ON, GPIOF_OUT_INIT_HIGH, "LCD_AVDD" },
+ { GPIO32_HX4700_RS232_ON, GPIOF_OUT_INIT_HIGH, "RS232_ON" },
+ { GPIO71_HX4700_ASIC3_nRESET, GPIOF_OUT_INIT_HIGH, "ASIC3_nRESET" },
+ { GPIO82_HX4700_EUART_RESET, GPIOF_OUT_INIT_HIGH, "EUART_RESET" },
+ { GPIO105_HX4700_nIR_ON, GPIOF_OUT_INIT_HIGH, "nIR_EN" },
};
static void __init hx4700_init(void)
{
+ int ret;
+
pxa2xx_mfp_config(ARRAY_AND_SIZE(hx4700_pin_config));
- hx4700_gpio_request(ARRAY_AND_SIZE(global_gpios));
+ ret = gpio_request_array(ARRAY_AND_SIZE(global_gpios));
+ if (ret)
+ pr_err ("hx4700: Failed to request GPIOs.\n");
pxa_set_ffuart_info(NULL);
pxa_set_btuart_info(NULL);
@@ -874,6 +842,7 @@ MACHINE_START(H4700, "HP iPAQ HX4700")
.map_io = pxa27x_map_io,
.nr_irqs = HX4700_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.init_machine = hx4700_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index 6cedc81da3bc..d427429f1f34 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -194,6 +194,7 @@ MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
.boot_params = 0xa0000100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = icontrol_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index f7fb64f11a7d..ddf20e5c376e 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -196,6 +196,7 @@ MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
/* Maintainer: Vibren Technologies */
.map_io = idp_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = idp_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/include/mach/clkdev.h b/arch/arm/mach-pxa/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-pxa/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/corgi.h b/arch/arm/mach-pxa/include/mach/corgi.h
index 0011055bc3f9..5dfd1195a5a7 100644
--- a/arch/arm/mach-pxa/include/mach/corgi.h
+++ b/arch/arm/mach-pxa/include/mach/corgi.h
@@ -34,7 +34,7 @@
#define CORGI_GPIO_LCDCON_CS (19) /* LCD Control Chip Select */
#define CORGI_GPIO_MAX1111_CS (20) /* MAX1111 Chip Select */
#define CORGI_GPIO_ADC_TEMP_ON (21) /* Select battery voltage or temperature */
-#define CORGI_GPIO_IR_ON (22) /* Enable IR Transciever */
+#define CORGI_GPIO_IR_ON (22) /* Enable IR Transceiver */
#define CORGI_GPIO_ADS7846_CS (24) /* ADS7846 Chip Select */
#define CORGI_GPIO_SD_PWR (33) /* MMC/SD Power */
#define CORGI_GPIO_CHRG_ON (38) /* Enable battery Charging */
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index 6957ba56025b..de63ca3016b4 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -337,9 +337,6 @@ extern unsigned long get_clock_tick_rate(void);
#endif
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
-#define PCIBIOS_MIN_IO 0
-#define PCIBIOS_MIN_MEM 0
-#define pcibios_assign_all_busses() 1
#define ARCH_HAS_DMA_SET_COHERENT_MASK
#endif
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 038402404e39..7cc5a781e99e 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -104,4 +104,16 @@
#define NR_IRQS (IRQ_BOARD_START)
+#ifndef __ASSEMBLY__
+struct irq_data;
+struct pt_regs;
+
+void pxa_mask_irq(struct irq_data *);
+void pxa_unmask_irq(struct irq_data *);
+void icip_handle_irq(struct pt_regs *);
+void ichp_handle_irq(struct pt_regs *);
+
+void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
+#endif
+
#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h
index 0a2efcf7947c..7cbfc5d3f9df 100644
--- a/arch/arm/mach-pxa/include/mach/magician.h
+++ b/arch/arm/mach-pxa/include/mach/magician.h
@@ -12,6 +12,7 @@
#ifndef _MAGICIAN_H_
#define _MAGICIAN_H_
+#include <linux/gpio.h>
#include <mach/irqs.h>
/*
@@ -77,7 +78,7 @@
* CPLD EGPIOs
*/
-#define MAGICIAN_EGPIO_BASE 0x80 /* GPIO_BOARD_START */
+#define MAGICIAN_EGPIO_BASE NR_BUILTIN_GPIO
#define MAGICIAN_EGPIO(reg,bit) \
(MAGICIAN_EGPIO_BASE + 8*reg + bit)
diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h
index 07734f37f8fd..d05a59727d66 100644
--- a/arch/arm/mach-pxa/include/mach/memory.h
+++ b/arch/arm/mach-pxa/include/mach/memory.h
@@ -17,8 +17,4 @@
*/
#define PLAT_PHYS_OFFSET UL(0xa0000000)
-#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
-#define ARM_DMA_ZONE_SIZE SZ_64M
-#endif
-
#endif
diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h
index f15afe012995..51558bcee999 100644
--- a/arch/arm/mach-pxa/include/mach/pm.h
+++ b/arch/arm/mach-pxa/include/mach/pm.h
@@ -22,8 +22,8 @@ struct pxa_cpu_pm_fns {
extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
/* sleep.S */
-extern void pxa25x_cpu_suspend(unsigned int, long);
-extern void pxa27x_cpu_suspend(unsigned int, long);
+extern int pxa25x_finish_suspend(unsigned long);
+extern int pxa27x_finish_suspend(unsigned long);
extern int pxa_pm_enter(suspend_state_t state);
extern int pxa_pm_prepare(void);
diff --git a/arch/arm/mach-pxa/include/mach/pxa25x.h b/arch/arm/mach-pxa/include/mach/pxa25x.h
index 508c3ba1f4d0..3ac0baac7350 100644
--- a/arch/arm/mach-pxa/include/mach/pxa25x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa25x.h
@@ -4,5 +4,14 @@
#include <mach/hardware.h>
#include <mach/pxa2xx-regs.h>
#include <mach/mfp-pxa25x.h>
+#include <mach/irqs.h>
+
+extern void __init pxa25x_map_io(void);
+extern void __init pxa25x_init_irq(void);
+#ifdef CONFIG_CPU_PXA26x
+extern void __init pxa26x_init_irq(void);
+#endif
+
+#define pxa25x_handle_irq icip_handle_irq
#endif /* __MACH_PXA25x_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x-udc.h b/arch/arm/mach-pxa/include/mach/pxa27x-udc.h
index ab1443f8bd89..4cf28f670706 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x-udc.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x-udc.h
@@ -56,9 +56,9 @@
#define UDCFNR __REG(0x40600014) /* UDC Frame Number Register */
#define UDCOTGICR __REG(0x40600018) /* UDC On-The-Go interrupt control */
#define UDCOTGICR_IESF (1 << 24) /* OTG SET_FEATURE command recvd */
-#define UDCOTGICR_IEXR (1 << 17) /* Extra Transciever Interrupt
+#define UDCOTGICR_IEXR (1 << 17) /* Extra Transceiver Interrupt
Rising Edge Interrupt Enable */
-#define UDCOTGICR_IEXF (1 << 16) /* Extra Transciever Interrupt
+#define UDCOTGICR_IEXF (1 << 16) /* Extra Transceiver Interrupt
Falling Edge Interrupt Enable */
#define UDCOTGICR_IEVV40R (1 << 9) /* OTG Vbus Valid 4.0V Rising Edge
Interrupt Enable */
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 0b702693f458..b9b1bdc4bacc 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -4,6 +4,7 @@
#include <mach/hardware.h>
#include <mach/pxa2xx-regs.h>
#include <mach/mfp-pxa27x.h>
+#include <mach/irqs.h>
#define ARB_CNTRL __REG(0x48000048) /* Arbiter Control Register */
@@ -17,6 +18,10 @@
#define ARB_CORE_PARK (1<<24) /* Be parked with core when idle */
#define ARB_LOCK_FLAG (1<<23) /* Only Locking masters gain access to the bus */
+extern void __init pxa27x_map_io(void);
+extern void __init pxa27x_init_irq(void);
extern int __init pxa27x_set_pwrmode(unsigned int mode);
+#define pxa27x_handle_irq ichp_handle_irq
+
#endif /* __MACH_PXA27x_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa300.h b/arch/arm/mach-pxa/include/mach/pxa300.h
index 2f33076c9e48..733b6412c3df 100644
--- a/arch/arm/mach-pxa/include/mach/pxa300.h
+++ b/arch/arm/mach-pxa/include/mach/pxa300.h
@@ -1,8 +1,7 @@
#ifndef __MACH_PXA300_H
#define __MACH_PXA300_H
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
#include <mach/mfp-pxa300.h>
#endif /* __MACH_PXA300_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa320.h b/arch/arm/mach-pxa/include/mach/pxa320.h
index cab78e903273..b6204e470d89 100644
--- a/arch/arm/mach-pxa/include/mach/pxa320.h
+++ b/arch/arm/mach-pxa/include/mach/pxa320.h
@@ -1,8 +1,7 @@
#ifndef __MACH_PXA320_H
#define __MACH_PXA320_H
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
#include <mach/mfp-pxa320.h>
#endif /* __MACH_PXA320_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx.h b/arch/arm/mach-pxa/include/mach/pxa3xx.h
new file mode 100644
index 000000000000..cd3e57f42688
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx.h
@@ -0,0 +1,14 @@
+#ifndef __MACH_PXA3XX_H
+#define __MACH_PXA3XX_H
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/irqs.h>
+
+extern void __init pxa3xx_map_io(void);
+extern void __init pxa3xx_init_irq(void);
+extern void __init pxa95x_init_irq(void);
+
+#define pxa3xx_handle_irq ichp_handle_irq
+
+#endif /* __MACH_PXA3XX_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa930.h b/arch/arm/mach-pxa/include/mach/pxa930.h
index d45f76a9b54d..190363b98d01 100644
--- a/arch/arm/mach-pxa/include/mach/pxa930.h
+++ b/arch/arm/mach-pxa/include/mach/pxa930.h
@@ -1,8 +1,7 @@
#ifndef __MACH_PXA930_H
#define __MACH_PXA930_H
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
#include <mach/mfp-pxa930.h>
#endif /* __MACH_PXA930_H */
diff --git a/arch/arm/mach-pxa/include/mach/regs-intc.h b/arch/arm/mach-pxa/include/mach/regs-intc.h
deleted file mode 100644
index 662288eb6f95..000000000000
--- a/arch/arm/mach-pxa/include/mach/regs-intc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef __ASM_MACH_REGS_INTC_H
-#define __ASM_MACH_REGS_INTC_H
-
-#include <mach/hardware.h>
-
-/*
- * Interrupt Controller
- */
-
-#define ICIP __REG(0x40D00000) /* Interrupt Controller IRQ Pending Register */
-#define ICMR __REG(0x40D00004) /* Interrupt Controller Mask Register */
-#define ICLR __REG(0x40D00008) /* Interrupt Controller Level Register */
-#define ICFP __REG(0x40D0000C) /* Interrupt Controller FIQ Pending Register */
-#define ICPR __REG(0x40D00010) /* Interrupt Controller Pending Register */
-#define ICCR __REG(0x40D00014) /* Interrupt Controller Control Register */
-#define ICHP __REG(0x40D00018) /* Interrupt Controller Highest Priority Register */
-
-#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */
-#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */
-#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */
-#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */
-#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */
-
-#define ICIP3 __REG(0x40D00130) /* Interrupt Controller IRQ Pending Register 3 */
-#define ICMR3 __REG(0x40D00134) /* Interrupt Controller Mask Register 3 */
-#define ICLR3 __REG(0x40D00138) /* Interrupt Controller Level Register 3 */
-#define ICFP3 __REG(0x40D0013C) /* Interrupt Controller FIQ Pending Register 3 */
-#define ICPR3 __REG(0x40D00140) /* Interrupt Controller Pending Register 3 */
-
-#endif /* __ASM_MACH_REGS_INTC_H */
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 32ed551bf9c5..b09e848eb6c6 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -37,6 +37,8 @@
#define IPR(i) (((i) < 32) ? (0x01c + ((i) << 2)) : \
((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) : \
(0x144 + (((i) - 64) << 2)))
+#define ICHP_VAL_IRQ (1 << 31)
+#define ICHP_IRQ(i) (((i) >> 16) & 0x7fff)
#define IPR_VALID (1 << 31)
#define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f)
@@ -64,7 +66,7 @@ static inline void __iomem *irq_base(int i)
return (void __iomem *)io_p2v(phys_base[i]);
}
-static void pxa_mask_irq(struct irq_data *d)
+void pxa_mask_irq(struct irq_data *d)
{
void __iomem *base = irq_data_get_irq_chip_data(d);
uint32_t icmr = __raw_readl(base + ICMR);
@@ -73,7 +75,7 @@ static void pxa_mask_irq(struct irq_data *d)
__raw_writel(icmr, base + ICMR);
}
-static void pxa_unmask_irq(struct irq_data *d)
+void pxa_unmask_irq(struct irq_data *d)
{
void __iomem *base = irq_data_get_irq_chip_data(d);
uint32_t icmr = __raw_readl(base + ICMR);
@@ -127,6 +129,36 @@ static struct irq_chip pxa_low_gpio_chip = {
.irq_set_type = pxa_set_low_gpio_type,
};
+asmlinkage void __exception_irq_entry icip_handle_irq(struct pt_regs *regs)
+{
+ uint32_t icip, icmr, mask;
+
+ do {
+ icip = __raw_readl(IRQ_BASE + ICIP);
+ icmr = __raw_readl(IRQ_BASE + ICMR);
+ mask = icip & icmr;
+
+ if (mask == 0)
+ break;
+
+ handle_IRQ(PXA_IRQ(fls(mask) - 1), regs);
+ } while (1);
+}
+
+asmlinkage void __exception_irq_entry ichp_handle_irq(struct pt_regs *regs)
+{
+ uint32_t ichp;
+
+ do {
+ __asm__ __volatile__("mrc p6, 0, %0, c5, c0, 0\n": "=r"(ichp));
+
+ if ((ichp & ICHP_VAL_IRQ) == 0)
+ break;
+
+ handle_IRQ(PXA_IRQ(ICHP_IRQ(ichp)), regs);
+ } while (1);
+}
+
static void __init pxa_init_low_gpio_irq(set_wake_t fn)
{
int irq;
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index e5e326d2cdc9..8f97e15e86e5 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -441,6 +441,7 @@ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleto
.map_io = pxa3xx_map_io,
.nr_irqs = LITTLETON_NR_IRQS,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = littleton_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 6cf8180bf5bd..c171d6ebee49 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -503,6 +503,7 @@ MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
.map_io = lpd270_map_io,
.nr_irqs = LPD270_NR_IRQS,
.init_irq = lpd270_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = lpd270_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index e10ddb827147..a8c696bfc132 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -553,6 +553,7 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
.map_io = lubbock_map_io,
.nr_irqs = LUBBOCK_NR_IRQS,
.init_irq = lubbock_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = lubbock_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index e1920572948a..5fe5bcd7c0a1 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -344,22 +344,14 @@ static struct pxafb_mach_info samsung_info = {
* Backlight
*/
+static struct gpio magician_bl_gpios[] = {
+ { EGPIO_MAGICIAN_BL_POWER, GPIOF_DIR_OUT, "Backlight power" },
+ { EGPIO_MAGICIAN_BL_POWER2, GPIOF_DIR_OUT, "Backlight power 2" },
+};
+
static int magician_backlight_init(struct device *dev)
{
- int ret;
-
- ret = gpio_request(EGPIO_MAGICIAN_BL_POWER, "BL_POWER");
- if (ret)
- goto err;
- ret = gpio_request(EGPIO_MAGICIAN_BL_POWER2, "BL_POWER2");
- if (ret)
- goto err2;
- return 0;
-
-err2:
- gpio_free(EGPIO_MAGICIAN_BL_POWER);
-err:
- return ret;
+ return gpio_request_array(ARRAY_AND_SIZE(magician_bl_gpios));
}
static int magician_backlight_notify(struct device *dev, int brightness)
@@ -376,8 +368,7 @@ static int magician_backlight_notify(struct device *dev, int brightness)
static void magician_backlight_exit(struct device *dev)
{
- gpio_free(EGPIO_MAGICIAN_BL_POWER);
- gpio_free(EGPIO_MAGICIAN_BL_POWER2);
+ gpio_free_array(ARRAY_AND_SIZE(magician_bl_gpios));
}
static struct platform_pwm_backlight_data backlight_data = {
@@ -712,16 +703,25 @@ static struct platform_device *devices[] __initdata = {
&leds_gpio,
};
+static struct gpio magician_global_gpios[] = {
+ { GPIO13_MAGICIAN_CPLD_IRQ, GPIOF_IN, "CPLD_IRQ" },
+ { GPIO107_MAGICIAN_DS1WM_IRQ, GPIOF_IN, "DS1WM_IRQ" },
+ { GPIO104_MAGICIAN_LCD_POWER_1, GPIOF_OUT_INIT_LOW, "LCD power 1" },
+ { GPIO105_MAGICIAN_LCD_POWER_2, GPIOF_OUT_INIT_LOW, "LCD power 2" },
+ { GPIO106_MAGICIAN_LCD_POWER_3, GPIOF_OUT_INIT_LOW, "LCD power 3" },
+ { GPIO83_MAGICIAN_nIR_EN, GPIOF_OUT_INIT_HIGH, "nIR_EN" },
+};
+
static void __init magician_init(void)
{
void __iomem *cpld;
int lcd_select;
int err;
- gpio_request(GPIO13_MAGICIAN_CPLD_IRQ, "CPLD_IRQ");
- gpio_request(GPIO107_MAGICIAN_DS1WM_IRQ, "DS1WM_IRQ");
-
pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
+ err = gpio_request_array(ARRAY_AND_SIZE(magician_global_gpios));
+ if (err)
+ pr_err("magician: Failed to request GPIOs: %d\n", err);
pxa_set_ffuart_info(NULL);
pxa_set_btuart_info(NULL);
@@ -729,11 +729,7 @@ static void __init magician_init(void)
platform_add_devices(ARRAY_AND_SIZE(devices));
- err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN");
- if (!err) {
- gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1);
- pxa_set_ficp_info(&magician_ficp_info);
- }
+ pxa_set_ficp_info(&magician_ficp_info);
pxa27x_set_i2c_power_info(NULL);
pxa_set_i2c_info(&i2c_info);
pxa_set_mci_info(&magician_mci_info);
@@ -747,16 +743,9 @@ static void __init magician_init(void)
system_rev = board_id & 0x7;
lcd_select = board_id & 0x8;
pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
- if (lcd_select && (system_rev < 3)) {
- gpio_request(GPIO75_MAGICIAN_SAMSUNG_POWER, "SAMSUNG_POWER");
- gpio_direction_output(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
- }
- gpio_request(GPIO104_MAGICIAN_LCD_POWER_1, "LCD_POWER_1");
- gpio_request(GPIO105_MAGICIAN_LCD_POWER_2, "LCD_POWER_2");
- gpio_request(GPIO106_MAGICIAN_LCD_POWER_3, "LCD_POWER_3");
- gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
- gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
- gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
+ if (lcd_select && (system_rev < 3))
+ gpio_request_one(GPIO75_MAGICIAN_SAMSUNG_POWER,
+ GPIOF_OUT_INIT_LOW, "SAMSUNG_POWER");
pxa_set_fb_info(NULL, lcd_select ? &samsung_info : &toppoly_info);
} else
pr_err("LCD detection: CPLD mapping failed\n");
@@ -768,6 +757,7 @@ MACHINE_START(MAGICIAN, "HTC Magician")
.map_io = pxa27x_map_io,
.nr_irqs = MAGICIAN_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.init_machine = magician_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 3479e2b3b511..4622eb78ef25 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -620,6 +620,7 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
.map_io = mainstone_map_io,
.nr_irqs = MAINSTONE_NR_IRQS,
.init_irq = mainstone_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = mainstone_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index e3470137c934..64810f908e5b 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -177,50 +177,6 @@ static unsigned long mioa701_pin_config[] = {
MFP_CFG_OUT(GPIO116, AF0, DRIVE_HIGH),
};
-#define MIO_GPIO_IN(num, _desc) \
- { .gpio = (num), .dir = 0, .desc = (_desc) }
-#define MIO_GPIO_OUT(num, _init, _desc) \
- { .gpio = (num), .dir = 1, .init = (_init), .desc = (_desc) }
-struct gpio_ress {
- unsigned gpio : 8;
- unsigned dir : 1;
- unsigned init : 1;
- char *desc;
-};
-
-static int mio_gpio_request(struct gpio_ress *gpios, int size)
-{
- int i, rc = 0;
- int gpio;
- int dir;
-
- for (i = 0; (!rc) && (i < size); i++) {
- gpio = gpios[i].gpio;
- dir = gpios[i].dir;
- rc = gpio_request(gpio, gpios[i].desc);
- if (rc) {
- printk(KERN_ERR "Error requesting GPIO %d(%s) : %d\n",
- gpio, gpios[i].desc, rc);
- continue;
- }
- if (dir)
- gpio_direction_output(gpio, gpios[i].init);
- else
- gpio_direction_input(gpio);
- }
- while ((rc) && (--i >= 0))
- gpio_free(gpios[i].gpio);
- return rc;
-}
-
-static void mio_gpio_free(struct gpio_ress *gpios, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- gpio_free(gpios[i].gpio);
-}
-
/* LCD Screen and Backlight */
static struct platform_pwm_backlight_data mioa701_backlight_data = {
.pwm_id = 0,
@@ -346,16 +302,16 @@ irqreturn_t gsm_on_irq(int irq, void *p)
return IRQ_HANDLED;
}
-struct gpio_ress gsm_gpios[] = {
- MIO_GPIO_IN(GPIO25_GSM_MOD_ON_STATE, "GSM state"),
- MIO_GPIO_IN(GPIO113_GSM_EVENT, "GSM event"),
+static struct gpio gsm_gpios[] = {
+ { GPIO25_GSM_MOD_ON_STATE, GPIOF_IN, "GSM state" },
+ { GPIO113_GSM_EVENT, GPIOF_IN, "GSM event" },
};
static int __init gsm_init(void)
{
int rc;
- rc = mio_gpio_request(ARRAY_AND_SIZE(gsm_gpios));
+ rc = gpio_request_array(ARRAY_AND_SIZE(gsm_gpios));
if (rc)
goto err_gpio;
rc = request_irq(gpio_to_irq(GPIO25_GSM_MOD_ON_STATE), gsm_on_irq,
@@ -369,7 +325,7 @@ static int __init gsm_init(void)
err_irq:
printk(KERN_ERR "Mioa701: Can't request GSM_ON irq\n");
- mio_gpio_free(ARRAY_AND_SIZE(gsm_gpios));
+ gpio_free_array(ARRAY_AND_SIZE(gsm_gpios));
err_gpio:
printk(KERN_ERR "Mioa701: gsm not available\n");
return rc;
@@ -378,7 +334,7 @@ err_gpio:
static void gsm_exit(void)
{
free_irq(gpio_to_irq(GPIO25_GSM_MOD_ON_STATE), NULL);
- mio_gpio_free(ARRAY_AND_SIZE(gsm_gpios));
+ gpio_free_array(ARRAY_AND_SIZE(gsm_gpios));
}
/*
@@ -749,14 +705,16 @@ static void mioa701_restart(char c, const char *cmd)
arm_machine_restart('s', cmd);
}
-static struct gpio_ress global_gpios[] = {
- MIO_GPIO_OUT(GPIO9_CHARGE_EN, 1, "Charger enable"),
- MIO_GPIO_OUT(GPIO18_POWEROFF, 0, "Power Off"),
- MIO_GPIO_OUT(GPIO87_LCD_POWER, 0, "LCD Power"),
+static struct gpio global_gpios[] = {
+ { GPIO9_CHARGE_EN, GPIOF_OUT_INIT_HIGH, "Charger enable" },
+ { GPIO18_POWEROFF, GPIOF_OUT_INIT_LOW, "Power Off" },
+ { GPIO87_LCD_POWER, GPIOF_OUT_INIT_LOW, "LCD Power" },
};
static void __init mioa701_machine_init(void)
{
+ int rc;
+
PSLR = 0xff100000; /* SYSDEL=125ms, PWRDEL=125ms, PSLR_SL_ROD=1 */
PCFR = PCFR_DC_EN | PCFR_GPR_EN | PCFR_OPDE;
RTTR = 32768 - 1; /* Reset crazy WinCE value */
@@ -766,7 +724,9 @@ static void __init mioa701_machine_init(void)
pxa_set_ffuart_info(NULL);
pxa_set_btuart_info(NULL);
pxa_set_stuart_info(NULL);
- mio_gpio_request(ARRAY_AND_SIZE(global_gpios));
+ rc = gpio_request_array(ARRAY_AND_SIZE(global_gpios));
+ if (rc)
+ pr_err("MioA701: Failed to request GPIOs: %d", rc);
bootstrap_init();
pxa_set_fb_info(NULL, &mioa701_pxafb_info);
pxa_set_mci_info(&mioa701_mci_info);
@@ -794,6 +754,7 @@ MACHINE_START(MIOA701, "MIO A701")
.boot_params = 0xa0000100,
.map_io = &pxa27x_map_io,
.init_irq = &pxa27x_init_irq,
+ .handle_irq = &pxa27x_handle_irq,
.init_machine = mioa701_machine_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index 59cce78aebd1..fb408861dbcf 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -96,6 +96,7 @@ MACHINE_START(NEC_MP900, "MobilePro900/C")
.timer = &pxa_timer,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.init_machine = mp900c_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 4061ecddee70..6b77365ed938 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -345,6 +345,7 @@ MACHINE_START(PALMLD, "Palm LifeDrive")
.boot_params = 0xa0000100,
.map_io = palmld_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = palmld_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index df4d7d009fbb..9bd3e47486fb 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -206,6 +206,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5")
.map_io = pxa27x_map_io,
.reserve = palmt5_reserve,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = palmt5_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index fb06bd047272..6ad4a6c7bc96 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -31,14 +31,13 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <mach/pxa25x.h>
#include <mach/audio.h>
#include <mach/palmtc.h>
#include <mach/mmc.h>
#include <mach/pxafb.h>
-#include <mach/mfp-pxa25x.h>
#include <mach/irda.h>
#include <mach/udc.h>
-#include <mach/pxa2xx-regs.h>
#include "generic.h"
#include "devices.h"
@@ -541,6 +540,7 @@ MACHINE_START(PALMTC, "Palm Tungsten|C")
.boot_params = 0xa0000100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = palmtc_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 726f5b98dcd3..664232f3e62c 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -31,11 +31,11 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <mach/pxa25x.h>
#include <mach/audio.h>
#include <mach/palmte2.h>
#include <mach/mmc.h>
#include <mach/pxafb.h>
-#include <mach/mfp-pxa25x.h>
#include <mach/irda.h>
#include <mach/udc.h>
#include <mach/palmasoc.h>
@@ -359,6 +359,7 @@ MACHINE_START(PALMTE2, "Palm Tungsten|E2")
.boot_params = 0xa0000100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = palmte2_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 20d1b18b1733..bb27d4b688d8 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -444,6 +444,7 @@ MACHINE_START(TREO680, "Palm Treo 680")
.map_io = pxa27x_map_io,
.reserve = treo_reserve,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = treo680_init,
MACHINE_END
@@ -453,6 +454,7 @@ MACHINE_START(CENTRO, "Palm Centro 685")
.map_io = pxa27x_map_io,
.reserve = treo_reserve,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = centro_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 595f002066cc..fc4285589c1f 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -367,6 +367,7 @@ MACHINE_START(PALMTX, "Palm T|X")
.boot_params = 0xa0000100,
.map_io = palmtx_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = palmtx_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 65f24f0b77e8..e61c1cc05519 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -33,6 +33,7 @@
#include <linux/i2c-gpio.h>
#include <asm/mach-types.h>
+#include <asm/suspend.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -401,6 +402,7 @@ MACHINE_START(PALMZ72, "Palm Zire72")
.boot_params = 0xa0000100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = palmz72_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 1fc8a66407ae..ffa65dfb8c6f 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -262,6 +262,7 @@ MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
.map_io = pcm027_map_io,
.nr_irqs = PCM027_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = pcm027_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 51e1583265b2..37178a8559b1 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -42,7 +42,6 @@ int pxa_pm_enter(suspend_state_t state)
/* *** go zzz *** */
pxa_cpu_pm_fns->enter(state);
- cpu_init();
if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) {
/* after sleeping, validate the checksum */
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 16d14fd79b4b..a113ea9ab4ab 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -468,6 +468,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
.map_io = pxa25x_map_io,
.nr_irqs = POODLE_NR_IRQS, /* 4 for LoCoMo */
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = poodle_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index fed363cec9c6..9c434d21a271 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -25,6 +25,7 @@
#include <linux/irq.h>
#include <asm/mach/map.h>
+#include <asm/suspend.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
@@ -244,7 +245,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
switch (state) {
case PM_SUSPEND_MEM:
- pxa25x_cpu_suspend(PWRMODE_SLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+ cpu_suspend(PWRMODE_SLEEP, pxa25x_finish_suspend);
break;
}
}
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 2fecbec58d88..9d2400b5f503 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -24,6 +24,7 @@
#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>
@@ -284,6 +285,11 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
void pxa27x_cpu_pm_enter(suspend_state_t state)
{
extern void pxa_cpu_standby(void);
+#ifndef CONFIG_IWMMXT
+ u64 acc0;
+
+ asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
+#endif
/* ensure voltage-change sequencer not initiated, which hangs */
PCFR &= ~PCFR_FVC;
@@ -299,7 +305,10 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
pxa_cpu_standby();
break;
case PM_SUSPEND_MEM:
- pxa27x_cpu_suspend(pwrmode, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+ cpu_suspend(pwrmode, pxa27x_finish_suspend);
+#ifndef CONFIG_IWMMXT
+ asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
+#endif
break;
}
}
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 8521d7d6f1da..b5cd9e5aba31 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -24,6 +24,7 @@
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach/map.h>
+#include <asm/suspend.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <mach/pxa3xx-regs.h>
@@ -31,7 +32,6 @@
#include <mach/ohci.h>
#include <mach/pm.h>
#include <mach/dma.h>
-#include <mach/regs-intc.h>
#include <mach/smemc.h>
#include "generic.h"
@@ -141,8 +141,13 @@ static void pxa3xx_cpu_pm_suspend(void)
{
volatile unsigned long *p = (volatile void *)0xc0000000;
unsigned long saved_data = *p;
+#ifndef CONFIG_IWMMXT
+ u64 acc0;
- extern void pxa3xx_cpu_suspend(long);
+ asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
+#endif
+
+ extern int pxa3xx_finish_suspend(unsigned long);
/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
@@ -162,11 +167,15 @@ static void pxa3xx_cpu_pm_suspend(void)
/* overwrite with the resume address */
*p = virt_to_phys(cpu_resume);
- pxa3xx_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
+ cpu_suspend(0, pxa3xx_finish_suspend);
*p = saved_data;
AD3ER = 0;
+
+#ifndef CONFIG_IWMMXT
+ asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
+#endif
}
static void pxa3xx_cpu_pm_enter(suspend_state_t state)
@@ -328,13 +337,13 @@ static void pxa_ack_ext_wakeup(struct irq_data *d)
static void pxa_mask_ext_wakeup(struct irq_data *d)
{
- ICMR2 &= ~(1 << ((d->irq - PXA_IRQ(0)) & 0x1f));
+ pxa_mask_irq(d);
PECR &= ~PECR_IE(d->irq - IRQ_WAKEUP0);
}
static void pxa_unmask_ext_wakeup(struct irq_data *d)
{
- ICMR2 |= 1 << ((d->irq - PXA_IRQ(0)) & 0x1f);
+ pxa_unmask_irq(d);
PECR |= PECR_IE(d->irq - IRQ_WAKEUP0);
}
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index ecc82a330fad..0ee166b61f81 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -27,7 +27,6 @@
#include <mach/reset.h>
#include <mach/pm.h>
#include <mach/dma.h>
-#include <mach/regs-intc.h>
#include "generic.h"
#include "devices.h"
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 2f37d43f51b6..bbcd90562ebe 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -46,10 +46,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa3xx.h>
-#include <mach/mfp-pxa300.h>
+#include <mach/pxa300.h>
#include <mach/ohci.h>
#include <mach/pxafb.h>
#include <mach/mmc.h>
@@ -1093,6 +1090,7 @@ MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
.init_machine = raumfeld_controller_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
MACHINE_END
#endif
@@ -1103,6 +1101,7 @@ MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
.init_machine = raumfeld_connector_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
MACHINE_END
#endif
@@ -1113,6 +1112,7 @@ MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
.init_machine = raumfeld_speaker_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
MACHINE_END
#endif
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index fee97a935122..df4356e8acae 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -599,6 +599,7 @@ MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
.boot_params = 0xa0000100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = saar_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
index 9322fe527c7f..ebd6379c4969 100644
--- a/arch/arm/mach-pxa/saarb.c
+++ b/arch/arm/mach-pxa/saarb.c
@@ -104,9 +104,10 @@ static void __init saarb_init(void)
MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
.boot_params = 0xa0000100,
- .map_io = pxa_map_io,
+ .map_io = pxa3xx_map_io,
.nr_irqs = SAARB_NR_IRQS,
.init_irq = pxa95x_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = saarb_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 6f5368899d84..1e544be9905d 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -24,20 +24,9 @@
#ifdef CONFIG_PXA3xx
/*
- * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
- *
- * r0 = v:p offset
+ * pxa3xx_finish_suspend() - forces CPU into sleep state (S2D3C4)
*/
-ENTRY(pxa3xx_cpu_suspend)
-
-#ifndef CONFIG_IWMMXT
- mra r2, r3, acc0
-#endif
- stmfd sp!, {r2 - r12, lr} @ save registers on stack
- mov r1, r0
- ldr r3, =pxa_cpu_resume @ resume function
- bl cpu_suspend
-
+ENTRY(pxa3xx_finish_suspend)
mov r0, #0x06 @ S2D3C4 mode
mcr p14, 0, r0, c7, c0, 0 @ enter sleep
@@ -46,28 +35,18 @@ ENTRY(pxa3xx_cpu_suspend)
#ifdef CONFIG_PXA27x
/*
- * pxa27x_cpu_suspend()
+ * pxa27x_finish_suspend()
*
* Forces CPU into sleep state.
*
* r0 = value for PWRMODE M field for desired sleep state
- * r1 = v:p offset
*/
-ENTRY(pxa27x_cpu_suspend)
-
-#ifndef CONFIG_IWMMXT
- mra r2, r3, acc0
-#endif
- stmfd sp!, {r2 - r12, lr} @ save registers on stack
- mov r4, r0 @ save sleep mode
- ldr r3, =pxa_cpu_resume @ resume function
- bl cpu_suspend
-
+ENTRY(pxa27x_finish_suspend)
@ Put the processor to sleep
@ (also workaround for sighting 28071)
@ prepare value for sleep mode
- mov r1, r4 @ sleep mode
+ mov r1, r0 @ sleep mode
@ prepare pointer to physical address 0 (virtual mapping in generic.c)
mov r2, #UNCACHED_PHYS_0
@@ -99,21 +78,16 @@ ENTRY(pxa27x_cpu_suspend)
#ifdef CONFIG_PXA25x
/*
- * pxa25x_cpu_suspend()
+ * pxa25x_finish_suspend()
*
* Forces CPU into sleep state.
*
* r0 = value for PWRMODE M field for desired sleep state
- * r1 = v:p offset
*/
-ENTRY(pxa25x_cpu_suspend)
- stmfd sp!, {r2 - r12, lr} @ save registers on stack
- mov r4, r0 @ save sleep mode
- ldr r3, =pxa_cpu_resume @ resume function
- bl cpu_suspend
+ENTRY(pxa25x_finish_suspend)
@ prepare value for sleep mode
- mov r1, r4 @ sleep mode
+ mov r1, r0 @ sleep mode
@ prepare pointer to physical address 0 (virtual mapping in generic.c)
mov r2, #UNCACHED_PHYS_0
@@ -195,16 +169,3 @@ pxa_cpu_do_suspend:
mcr p14, 0, r1, c7, c0, 0 @ PWRMODE
20: b 20b @ loop waiting for sleep
-
-/*
- * pxa_cpu_resume()
- *
- * entry point from bootloader into kernel during resume
- */
- .align 5
-pxa_cpu_resume:
- ldmfd sp!, {r2, r3}
-#ifndef CONFIG_IWMMXT
- mar acc0, r2, r3
-#endif
- ldmfd sp!, {r4 - r12, pc} @ return to caller
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 01c576963e94..438c7b5e451f 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -984,6 +984,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
.fixup = spitz_fixup,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.init_machine = spitz_init,
.timer = &pxa_timer,
MACHINE_END
@@ -994,6 +995,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
.fixup = spitz_fixup,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.init_machine = spitz_init,
.timer = &pxa_timer,
MACHINE_END
@@ -1004,6 +1006,7 @@ MACHINE_START(AKITA, "SHARP Akita")
.fixup = spitz_fixup,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.init_machine = spitz_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index cb5611daf5fe..3f8d0af9e2f7 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -1001,6 +1001,7 @@ static void __init stargate2_init(void)
MACHINE_START(INTELMOTE2, "IMOTE 2")
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = imote2_init,
.boot_params = 0xA0000100,
@@ -1012,6 +1013,7 @@ MACHINE_START(STARGATE2, "Stargate 2")
.map_io = pxa27x_map_io,
.nr_irqs = STARGATE_NR_IRQS,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = stargate2_init,
.boot_params = 0xA0000100,
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 53d4a472b699..32fb58e01b10 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -492,6 +492,7 @@ MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
.boot_params = 0xa0000100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = tavorevb_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
index 79f4422f12f4..fd5a8eae0a87 100644
--- a/arch/arm/mach-pxa/tavorevb3.c
+++ b/arch/arm/mach-pxa/tavorevb3.c
@@ -129,6 +129,7 @@ MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
.map_io = pxa3xx_map_io,
.nr_irqs = TAVOREVB3_NR_IRQS,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = evb3_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 5fa145778e7d..9f69a2682693 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -974,6 +974,7 @@ MACHINE_START(TOSA, "SHARP Tosa")
.map_io = pxa25x_map_io,
.nr_irqs = TOSA_NR_IRQS,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.init_machine = tosa_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 687417a93698..c0417508f39d 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -558,6 +558,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
MACHINE_END
@@ -567,5 +568,6 @@ MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 903218eab56d..d4a3dc74e84a 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -995,6 +995,7 @@ MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
.boot_params = 0xa0000100,
.map_io = viper_map_io,
.init_irq = viper_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
.init_machine = viper_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index 67bd41488bf8..5f8490ab07cb 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -719,6 +719,7 @@ MACHINE_START(VPAC270, "Voipac PXA270")
.boot_params = 0xa0000100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = vpac270_init
MACHINE_END
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index f55f8f2e0db3..acc600f5e72f 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -28,8 +28,7 @@
#include <asm/mach/map.h>
#include <mach/hardware.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
#include <mach/smemc.h>
#include "generic.h"
@@ -185,6 +184,7 @@ MACHINE_START(XCEP, "Iskratel XCEP")
.init_machine = xcep_init,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
+ .handle_irq = pxa25x_handle_irq,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index fbe9e02e2f9f..6c9275a20c91 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -40,6 +40,7 @@
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <plat/pxa27x_keypad.h>
+#include <mach/pm.h>
#include "generic.h"
#include "devices.h"
@@ -677,6 +678,20 @@ static void __init z2_pmic_init(void)
static inline void z2_pmic_init(void) {}
#endif
+#ifdef CONFIG_PM
+static void z2_power_off(void)
+{
+ /* We're using deep sleep as poweroff, so clear PSPR to ensure that
+ * bootloader will jump to its entry point in resume handler
+ */
+ PSPR = 0x0;
+ local_irq_disable();
+ pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+}
+#else
+#define z2_power_off NULL
+#endif
+
/******************************************************************************
* Machine init
******************************************************************************/
@@ -698,12 +713,15 @@ static void __init z2_init(void)
z2_leds_init();
z2_keys_init();
z2_pmic_init();
+
+ pm_power_off = z2_power_off;
}
MACHINE_START(ZIPIT2, "Zipit Z2")
.boot_params = 0xa0000100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = z2_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index 00363c7ac182..99c49bcd9f70 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -31,17 +31,17 @@
#include <linux/can/platform/mcp251x.h>
#include <asm/mach-types.h>
+#include <asm/suspend.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/pxa2xx-regs.h>
+#include <mach/pxa27x.h>
#include <mach/regs-uart.h>
#include <mach/ohci.h>
#include <mach/mmc.h>
#include <mach/pxa27x-udc.h>
#include <mach/udc.h>
#include <mach/pxafb.h>
-#include <mach/mfp-pxa27x.h>
#include <mach/pm.h>
#include <mach/audio.h>
#include <mach/arcom-pcmcia.h>
@@ -676,7 +676,7 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
static void zeus_power_off(void)
{
local_irq_disable();
- pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+ cpu_suspend(PWRMODE_DEEPSLEEP, pxa27x_finish_suspend);
}
#else
#define zeus_power_off NULL
@@ -908,6 +908,7 @@ MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
.map_io = zeus_map_io,
.nr_irqs = ZEUS_NR_IRQS,
.init_irq = zeus_init_irq,
+ .handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = zeus_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 5821185f77ab..15ec66b3471a 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -24,7 +24,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <mach/hardware.h>
+#include <mach/pxa3xx.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
#include <mach/zylonite.h>
@@ -426,6 +426,7 @@ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
.map_io = pxa3xx_map_io,
.nr_irqs = ZYLONITE_NR_IRQS,
.init_irq = pxa3xx_init_irq,
+ .handle_irq = pxa3xx_handle_irq,
.timer = &pxa_timer,
.init_machine = zylonite_init,
MACHINE_END
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index b9a9805e4828..dba6d0c1fc17 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -50,6 +50,7 @@ config MACH_REALVIEW_PB1176
bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
select CPU_V6
select ARM_GIC
+ select HAVE_TCM
help
Include support for the ARM(R) RealView(R) Platform Baseboard for
ARM1176JZF-S.
diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h
index 1759fa673eea..2022e092f0ca 100644
--- a/arch/arm/mach-realview/include/mach/memory.h
+++ b/arch/arm/mach-realview/include/mach/memory.h
@@ -29,10 +29,6 @@
#define PLAT_PHYS_OFFSET UL(0x00000000)
#endif
-#ifdef CONFIG_ZONE_DMA
-#define ARM_DMA_ZONE_SIZE SZ_256M
-#endif
-
#ifdef CONFIG_SPARSEMEM
/*
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 963bf0d8119a..4ae943bafa92 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -68,14 +68,6 @@ void __init smp_init_cpus(void)
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- /*
- * Initialise the present map, which describes the set of CPUs
- * actually populated at the present time.
- */
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
scu_enable(scu_base_addr());
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 10e75faba4c9..7a4e3b18cb3e 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -470,4 +470,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
.init_irq = gic_init_irq,
.timer = &realview_eb_timer,
.init_machine = realview_eb_init,
+#ifdef CONFIG_ZONE_DMA
+ .dma_zone_size = SZ_256M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index eab6070f66d0..ad5671acb66a 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -365,4 +365,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
.init_irq = gic_init_irq,
.timer = &realview_pb1176_timer,
.init_machine = realview_pb1176_init,
+#ifdef CONFIG_ZONE_DMA
+ .dma_zone_size = SZ_256M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index b2985fc7cd4e..b43644b3685e 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -367,4 +367,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
.init_irq = gic_init_irq,
.timer = &realview_pb11mp_timer,
.init_machine = realview_pb11mp_init,
+#ifdef CONFIG_ZONE_DMA
+ .dma_zone_size = SZ_256M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index fb6866558760..763e8f38c15d 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -317,4 +317,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
.init_irq = gic_init_irq,
.timer = &realview_pba8_timer,
.init_machine = realview_pba8_init,
+#ifdef CONFIG_ZONE_DMA
+ .dma_zone_size = SZ_256M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 92ace2cf2b2c..363b0ab56150 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -400,4 +400,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
.init_irq = gic_init_irq,
.timer = &realview_pbx_timer,
.init_machine = realview_pbx_init,
+#ifdef CONFIG_ZONE_DMA
+ .dma_zone_size = SZ_256M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-s3c2400/Kconfig b/arch/arm/mach-s3c2400/Kconfig
deleted file mode 100644
index fdd8f5e96faf..000000000000
--- a/arch/arm/mach-s3c2400/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2007 Simtec Electronics
-#
-# Licensed under GPLv2
-
-menu "S3C2400 Machines"
-
-endmenu
diff --git a/arch/arm/mach-s3c2400/Makefile b/arch/arm/mach-s3c2400/Makefile
deleted file mode 100644
index 7e23f4e13766..000000000000
--- a/arch/arm/mach-s3c2400/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# arch/arm/mach-s3c2400/Makefile
-#
-# Copyright 2007 Simtec Electronics
-#
-# Licensed under GPLv2
-
-obj-y :=
-obj-m :=
-obj-n :=
-obj- :=
-
-obj-$(CONFIG_CPU_S3C2400) += gpio.o
-
-# Machine support
-
diff --git a/arch/arm/mach-s3c2400/gpio.c b/arch/arm/mach-s3c2400/gpio.c
deleted file mode 100644
index 6c68e78f3595..000000000000
--- a/arch/arm/mach-s3c2400/gpio.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* linux/arch/arm/mach-s3c2400/gpio.c
- *
- * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
- *
- * S3C2400 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 <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-int s3c2400_gpio_getirq(unsigned int pin)
-{
- if (pin < S3C2410_GPE(0) || pin > S3C2400_GPE(7))
- return -EINVAL; /* not valid interrupts */
-
- return (pin - S3C2410_GPE(0)) + IRQ_EINT0;
-}
-
-EXPORT_SYMBOL(s3c2400_gpio_getirq);
diff --git a/arch/arm/mach-s3c2400/include/mach/map.h b/arch/arm/mach-s3c2400/include/mach/map.h
deleted file mode 100644
index 3fd889200e99..000000000000
--- a/arch/arm/mach-s3c2400/include/mach/map.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* arch/arm/mach-s3c2400/include/mach/map.h
- *
- * Copyright 2003-2007 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- * Ben Dooks <ben@simtec.co.uk>
- *
- * Copyright 2003, Lucas Correia Villa Real
- *
- * S3C2400 - 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.
-*/
-
-#define S3C2400_PA_MEMCTRL (0x14000000)
-#define S3C2400_PA_USBHOST (0x14200000)
-#define S3C2400_PA_IRQ (0x14400000)
-#define S3C2400_PA_DMA (0x14600000)
-#define S3C2400_PA_CLKPWR (0x14800000)
-#define S3C2400_PA_LCD (0x14A00000)
-#define S3C2400_PA_UART (0x15000000)
-#define S3C2400_PA_TIMER (0x15100000)
-#define S3C2400_PA_USBDEV (0x15200140)
-#define S3C2400_PA_WATCHDOG (0x15300000)
-#define S3C2400_PA_IIC (0x15400000)
-#define S3C2400_PA_IIS (0x15508000)
-#define S3C2400_PA_GPIO (0x15600000)
-#define S3C2400_PA_RTC (0x15700040)
-#define S3C2400_PA_ADC (0x15800000)
-#define S3C2400_PA_SPI (0x15900000)
-
-#define S3C2400_PA_MMC (0x15A00000)
-#define S3C2400_SZ_MMC SZ_1M
-
-/* physical addresses of all the chip-select areas */
-
-#define S3C2400_CS0 (0x00000000)
-#define S3C2400_CS1 (0x02000000)
-#define S3C2400_CS2 (0x04000000)
-#define S3C2400_CS3 (0x06000000)
-#define S3C2400_CS4 (0x08000000)
-#define S3C2400_CS5 (0x0A000000)
-#define S3C2400_CS6 (0x0C000000)
-#define S3C2400_CS7 (0x0E000000)
-
-#define S3C2400_SDRAM_PA (S3C2400_CS6)
-
-/* Use a single interface for common resources between S3C24XX cpus */
-
-#define S3C24XX_PA_IRQ S3C2400_PA_IRQ
-#define S3C24XX_PA_MEMCTRL S3C2400_PA_MEMCTRL
-#define S3C24XX_PA_USBHOST S3C2400_PA_USBHOST
-#define S3C24XX_PA_DMA S3C2400_PA_DMA
-#define S3C24XX_PA_CLKPWR S3C2400_PA_CLKPWR
-#define S3C24XX_PA_LCD S3C2400_PA_LCD
-#define S3C24XX_PA_UART S3C2400_PA_UART
-#define S3C24XX_PA_TIMER S3C2400_PA_TIMER
-#define S3C24XX_PA_USBDEV S3C2400_PA_USBDEV
-#define S3C24XX_PA_WATCHDOG S3C2400_PA_WATCHDOG
-#define S3C24XX_PA_IIC S3C2400_PA_IIC
-#define S3C24XX_PA_IIS S3C2400_PA_IIS
-#define S3C24XX_PA_GPIO S3C2400_PA_GPIO
-#define S3C24XX_PA_RTC S3C2400_PA_RTC
-#define S3C24XX_PA_ADC S3C2400_PA_ADC
-#define S3C24XX_PA_SPI S3C2400_PA_SPI
diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c
index 2c126bbca08d..a5eeb62ce1c2 100644
--- a/arch/arm/mach-s3c2410/h1940-bluetooth.c
+++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c
@@ -18,7 +18,6 @@
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/rfkill.h>
-#include <linux/leds.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
index f453c4f2cb8e..bab139201761 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
@@ -52,12 +52,6 @@ extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
extern int s3c2410_gpio_getirq(unsigned int pin);
-#ifdef CONFIG_CPU_S3C2400
-
-extern int s3c2400_gpio_getirq(unsigned int pin);
-
-#endif /* CONFIG_CPU_S3C2400 */
-
/* s3c2410_gpio_irqfilter
*
* set the irq filtering on the given pin
diff --git a/arch/arm/mach-s3c2410/include/mach/pm-core.h b/arch/arm/mach-s3c2410/include/mach/pm-core.h
index 70a83b209e25..45eea5210c87 100644
--- a/arch/arm/mach-s3c2410/include/mach/pm-core.h
+++ b/arch/arm/mach-s3c2410/include/mach/pm-core.h
@@ -62,3 +62,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
struct pm_uart_save *save)
{
}
+
+static inline void s3c_pm_restored_gpios(void) { }
+static inline void s3c_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
index a0a89d429296..cac1ad6b582c 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
@@ -16,11 +16,7 @@
#include <mach/gpio-nrs.h>
-#ifdef CONFIG_CPU_S3C2400
-#define S3C24XX_MISCCR S3C2400_MISCCR
-#else
#define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80)
-#endif /* CONFIG_CPU_S3C2400 */
/* general configuration options */
@@ -42,67 +38,33 @@
/* configure GPIO ports A..G */
/* port A - S3C2410: 22bits, zero in bit X makes pin X output
- * S3C2400: 18bits, zero in bit X makes pin X output
* 1 makes port special function, this is default
*/
#define S3C2410_GPACON S3C2410_GPIOREG(0x00)
#define S3C2410_GPADAT S3C2410_GPIOREG(0x04)
-#define S3C2400_GPACON S3C2410_GPIOREG(0x00)
-#define S3C2400_GPADAT S3C2410_GPIOREG(0x04)
-
#define S3C2410_GPA0_ADDR0 (1<<0)
-
#define S3C2410_GPA1_ADDR16 (1<<1)
-
#define S3C2410_GPA2_ADDR17 (1<<2)
-
#define S3C2410_GPA3_ADDR18 (1<<3)
-
#define S3C2410_GPA4_ADDR19 (1<<4)
-
#define S3C2410_GPA5_ADDR20 (1<<5)
-
#define S3C2410_GPA6_ADDR21 (1<<6)
-
#define S3C2410_GPA7_ADDR22 (1<<7)
-
#define S3C2410_GPA8_ADDR23 (1<<8)
-
#define S3C2410_GPA9_ADDR24 (1<<9)
-
#define S3C2410_GPA10_ADDR25 (1<<10)
-#define S3C2400_GPA10_SCKE (1<<10)
-
#define S3C2410_GPA11_ADDR26 (1<<11)
-#define S3C2400_GPA11_nCAS0 (1<<11)
-
#define S3C2410_GPA12_nGCS1 (1<<12)
-#define S3C2400_GPA12_nCAS1 (1<<12)
-
#define S3C2410_GPA13_nGCS2 (1<<13)
-#define S3C2400_GPA13_nGCS1 (1<<13)
-
#define S3C2410_GPA14_nGCS3 (1<<14)
-#define S3C2400_GPA14_nGCS2 (1<<14)
-
#define S3C2410_GPA15_nGCS4 (1<<15)
-#define S3C2400_GPA15_nGCS3 (1<<15)
-
#define S3C2410_GPA16_nGCS5 (1<<16)
-#define S3C2400_GPA16_nGCS4 (1<<16)
-
#define S3C2410_GPA17_CLE (1<<17)
-#define S3C2400_GPA17_nGCS5 (1<<17)
-
#define S3C2410_GPA18_ALE (1<<18)
-
#define S3C2410_GPA19_nFWE (1<<19)
-
#define S3C2410_GPA20_nFRE (1<<20)
-
#define S3C2410_GPA21_nRSTOUT (1<<21)
-
#define S3C2410_GPA22_nFCE (1<<22)
/* 0x08 and 0x0c are reserved on S3C2410 */
@@ -111,10 +73,6 @@
* GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
* 00 = input, 01 = output, 10=special function, 11=reserved
- * S3C2400:
- * GPB is 16 IO pins, each configured by 2 bits each in GPBCON.
- * 00 = input, 01 = output, 10=data, 11=special function
-
* bit 0,1 = pin 0, 2,3= pin 1...
*
* CPBUP = pull up resistor control, 1=disabled, 0=enabled
@@ -124,78 +82,35 @@
#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)
#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)
-#define S3C2400_GPBCON S3C2410_GPIOREG(0x08)
-#define S3C2400_GPBDAT S3C2410_GPIOREG(0x0C)
-#define S3C2400_GPBUP S3C2410_GPIOREG(0x10)
-
/* no i/o pin in port b can have value 3 (unless it is a s3c2443) ! */
#define S3C2410_GPB0_TOUT0 (0x02 << 0)
-#define S3C2400_GPB0_DATA16 (0x02 << 0)
#define S3C2410_GPB1_TOUT1 (0x02 << 2)
-#define S3C2400_GPB1_DATA17 (0x02 << 2)
#define S3C2410_GPB2_TOUT2 (0x02 << 4)
-#define S3C2400_GPB2_DATA18 (0x02 << 4)
-#define S3C2400_GPB2_TCLK1 (0x03 << 4)
#define S3C2410_GPB3_TOUT3 (0x02 << 6)
-#define S3C2400_GPB3_DATA19 (0x02 << 6)
-#define S3C2400_GPB3_TXD1 (0x03 << 6)
#define S3C2410_GPB4_TCLK0 (0x02 << 8)
-#define S3C2400_GPB4_DATA20 (0x02 << 8)
#define S3C2410_GPB4_MASK (0x03 << 8)
-#define S3C2400_GPB4_RXD1 (0x03 << 8)
-#define S3C2400_GPB4_MASK (0x03 << 8)
#define S3C2410_GPB5_nXBACK (0x02 << 10)
#define S3C2443_GPB5_XBACK (0x03 << 10)
-#define S3C2400_GPB5_DATA21 (0x02 << 10)
-#define S3C2400_GPB5_nCTS1 (0x03 << 10)
#define S3C2410_GPB6_nXBREQ (0x02 << 12)
#define S3C2443_GPB6_XBREQ (0x03 << 12)
-#define S3C2400_GPB6_DATA22 (0x02 << 12)
-#define S3C2400_GPB6_nRTS1 (0x03 << 12)
#define S3C2410_GPB7_nXDACK1 (0x02 << 14)
#define S3C2443_GPB7_XDACK1 (0x03 << 14)
-#define S3C2400_GPB7_DATA23 (0x02 << 14)
#define S3C2410_GPB8_nXDREQ1 (0x02 << 16)
-#define S3C2400_GPB8_DATA24 (0x02 << 16)
#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
#define S3C2443_GPB9_XDACK0 (0x03 << 18)
-#define S3C2400_GPB9_DATA25 (0x02 << 18)
-#define S3C2400_GPB9_I2SSDI (0x03 << 18)
#define S3C2410_GPB10_nXDRE0 (0x02 << 20)
#define S3C2443_GPB10_XDREQ0 (0x03 << 20)
-#define S3C2400_GPB10_DATA26 (0x02 << 20)
-#define S3C2400_GPB10_nSS (0x03 << 20)
-
-#define S3C2400_GPB11_INP (0x00 << 22)
-#define S3C2400_GPB11_OUTP (0x01 << 22)
-#define S3C2400_GPB11_DATA27 (0x02 << 22)
-
-#define S3C2400_GPB12_INP (0x00 << 24)
-#define S3C2400_GPB12_OUTP (0x01 << 24)
-#define S3C2400_GPB12_DATA28 (0x02 << 24)
-
-#define S3C2400_GPB13_INP (0x00 << 26)
-#define S3C2400_GPB13_OUTP (0x01 << 26)
-#define S3C2400_GPB13_DATA29 (0x02 << 26)
-
-#define S3C2400_GPB14_INP (0x00 << 28)
-#define S3C2400_GPB14_OUTP (0x01 << 28)
-#define S3C2400_GPB14_DATA30 (0x02 << 28)
-
-#define S3C2400_GPB15_INP (0x00 << 30)
-#define S3C2400_GPB15_OUTP (0x01 << 30)
-#define S3C2400_GPB15_DATA31 (0x02 << 30)
#define S3C2410_GPB_PUPDIS(x) (1<<(x))
@@ -208,59 +123,22 @@
#define S3C2410_GPCCON S3C2410_GPIOREG(0x20)
#define S3C2410_GPCDAT S3C2410_GPIOREG(0x24)
#define S3C2410_GPCUP S3C2410_GPIOREG(0x28)
-
-#define S3C2400_GPCCON S3C2410_GPIOREG(0x14)
-#define S3C2400_GPCDAT S3C2410_GPIOREG(0x18)
-#define S3C2400_GPCUP S3C2410_GPIOREG(0x1C)
-
#define S3C2410_GPC0_LEND (0x02 << 0)
-#define S3C2400_GPC0_VD0 (0x02 << 0)
-
#define S3C2410_GPC1_VCLK (0x02 << 2)
-#define S3C2400_GPC1_VD1 (0x02 << 2)
-
#define S3C2410_GPC2_VLINE (0x02 << 4)
-#define S3C2400_GPC2_VD2 (0x02 << 4)
-
#define S3C2410_GPC3_VFRAME (0x02 << 6)
-#define S3C2400_GPC3_VD3 (0x02 << 6)
-
#define S3C2410_GPC4_VM (0x02 << 8)
-#define S3C2400_GPC4_VD4 (0x02 << 8)
-
#define S3C2410_GPC5_LCDVF0 (0x02 << 10)
-#define S3C2400_GPC5_VD5 (0x02 << 10)
-
#define S3C2410_GPC6_LCDVF1 (0x02 << 12)
-#define S3C2400_GPC6_VD6 (0x02 << 12)
-
#define S3C2410_GPC7_LCDVF2 (0x02 << 14)
-#define S3C2400_GPC7_VD7 (0x02 << 14)
-
#define S3C2410_GPC8_VD0 (0x02 << 16)
-#define S3C2400_GPC8_VD8 (0x02 << 16)
-
#define S3C2410_GPC9_VD1 (0x02 << 18)
-#define S3C2400_GPC9_VD9 (0x02 << 18)
-
#define S3C2410_GPC10_VD2 (0x02 << 20)
-#define S3C2400_GPC10_VD10 (0x02 << 20)
-
#define S3C2410_GPC11_VD3 (0x02 << 22)
-#define S3C2400_GPC11_VD11 (0x02 << 22)
-
#define S3C2410_GPC12_VD4 (0x02 << 24)
-#define S3C2400_GPC12_VD12 (0x02 << 24)
-
#define S3C2410_GPC13_VD5 (0x02 << 26)
-#define S3C2400_GPC13_VD13 (0x02 << 26)
-
#define S3C2410_GPC14_VD6 (0x02 << 28)
-#define S3C2400_GPC14_VD14 (0x02 << 28)
-
#define S3C2410_GPC15_VD7 (0x02 << 30)
-#define S3C2400_GPC15_VD15 (0x02 << 30)
-
#define S3C2410_GPC_PUPDIS(x) (1<<(x))
/*
@@ -269,8 +147,6 @@
* almost identical setup to port b, but the special functions are mostly
* to do with the video system's data.
*
- * S3C2400: Port D consists of 11 GPIO/Special function
- *
* almost identical setup to port c
*/
@@ -278,46 +154,31 @@
#define S3C2410_GPDDAT S3C2410_GPIOREG(0x34)
#define S3C2410_GPDUP S3C2410_GPIOREG(0x38)
-#define S3C2400_GPDCON S3C2410_GPIOREG(0x20)
-#define S3C2400_GPDDAT S3C2410_GPIOREG(0x24)
-#define S3C2400_GPDUP S3C2410_GPIOREG(0x28)
-
#define S3C2410_GPD0_VD8 (0x02 << 0)
-#define S3C2400_GPD0_VFRAME (0x02 << 0)
#define S3C2442_GPD0_nSPICS1 (0x03 << 0)
#define S3C2410_GPD1_VD9 (0x02 << 2)
-#define S3C2400_GPD1_VM (0x02 << 2)
#define S3C2442_GPD1_SPICLK1 (0x03 << 2)
#define S3C2410_GPD2_VD10 (0x02 << 4)
-#define S3C2400_GPD2_VLINE (0x02 << 4)
#define S3C2410_GPD3_VD11 (0x02 << 6)
-#define S3C2400_GPD3_VCLK (0x02 << 6)
#define S3C2410_GPD4_VD12 (0x02 << 8)
-#define S3C2400_GPD4_LEND (0x02 << 8)
#define S3C2410_GPD5_VD13 (0x02 << 10)
-#define S3C2400_GPD5_TOUT0 (0x02 << 10)
#define S3C2410_GPD6_VD14 (0x02 << 12)
-#define S3C2400_GPD6_TOUT1 (0x02 << 12)
#define S3C2410_GPD7_VD15 (0x02 << 14)
-#define S3C2400_GPD7_TOUT2 (0x02 << 14)
#define S3C2410_GPD8_VD16 (0x02 << 16)
-#define S3C2400_GPD8_TOUT3 (0x02 << 16)
#define S3C2440_GPD8_SPIMISO1 (0x03 << 16)
#define S3C2410_GPD9_VD17 (0x02 << 18)
-#define S3C2400_GPD9_TCLK0 (0x02 << 18)
#define S3C2440_GPD9_SPIMOSI1 (0x03 << 18)
#define S3C2410_GPD10_VD18 (0x02 << 20)
-#define S3C2400_GPD10_nWAIT (0x02 << 20)
#define S3C2440_GPD10_SPICLK1 (0x03 << 20)
#define S3C2410_GPD11_VD19 (0x02 << 22)
@@ -340,9 +201,6 @@
* again, the same as port B, but dealing with I2S, SDI, and
* more miscellaneous functions
*
- * S3C2400:
- * Port E consists of 12 GPIO/Special function
- *
* GPIO / interrupt inputs
*/
@@ -350,74 +208,51 @@
#define S3C2410_GPEDAT S3C2410_GPIOREG(0x44)
#define S3C2410_GPEUP S3C2410_GPIOREG(0x48)
-#define S3C2400_GPECON S3C2410_GPIOREG(0x2C)
-#define S3C2400_GPEDAT S3C2410_GPIOREG(0x30)
-#define S3C2400_GPEUP S3C2410_GPIOREG(0x34)
-
#define S3C2410_GPE0_I2SLRCK (0x02 << 0)
#define S3C2443_GPE0_AC_nRESET (0x03 << 0)
-#define S3C2400_GPE0_EINT0 (0x02 << 0)
#define S3C2410_GPE0_MASK (0x03 << 0)
#define S3C2410_GPE1_I2SSCLK (0x02 << 2)
#define S3C2443_GPE1_AC_SYNC (0x03 << 2)
-#define S3C2400_GPE1_EINT1 (0x02 << 2)
-#define S3C2400_GPE1_nSS (0x03 << 2)
#define S3C2410_GPE1_MASK (0x03 << 2)
#define S3C2410_GPE2_CDCLK (0x02 << 4)
#define S3C2443_GPE2_AC_BITCLK (0x03 << 4)
-#define S3C2400_GPE2_EINT2 (0x02 << 4)
-#define S3C2400_GPE2_I2SSDI (0x03 << 4)
#define S3C2410_GPE3_I2SSDI (0x02 << 6)
#define S3C2443_GPE3_AC_SDI (0x03 << 6)
-#define S3C2400_GPE3_EINT3 (0x02 << 6)
-#define S3C2400_GPE3_nCTS1 (0x03 << 6)
#define S3C2410_GPE3_nSS0 (0x03 << 6)
#define S3C2410_GPE3_MASK (0x03 << 6)
#define S3C2410_GPE4_I2SSDO (0x02 << 8)
#define S3C2443_GPE4_AC_SDO (0x03 << 8)
-#define S3C2400_GPE4_EINT4 (0x02 << 8)
-#define S3C2400_GPE4_nRTS1 (0x03 << 8)
#define S3C2410_GPE4_I2SSDI (0x03 << 8)
#define S3C2410_GPE4_MASK (0x03 << 8)
#define S3C2410_GPE5_SDCLK (0x02 << 10)
#define S3C2443_GPE5_SD1_CLK (0x02 << 10)
-#define S3C2400_GPE5_EINT5 (0x02 << 10)
-#define S3C2400_GPE5_TCLK1 (0x03 << 10)
#define S3C2443_GPE5_AC_BITCLK (0x03 << 10)
#define S3C2410_GPE6_SDCMD (0x02 << 12)
#define S3C2443_GPE6_SD1_CMD (0x02 << 12)
#define S3C2443_GPE6_AC_SDI (0x03 << 12)
-#define S3C2400_GPE6_EINT6 (0x02 << 12)
#define S3C2410_GPE7_SDDAT0 (0x02 << 14)
#define S3C2443_GPE5_SD1_DAT0 (0x02 << 14)
#define S3C2443_GPE7_AC_SDO (0x03 << 14)
-#define S3C2400_GPE7_EINT7 (0x02 << 14)
#define S3C2410_GPE8_SDDAT1 (0x02 << 16)
#define S3C2443_GPE8_SD1_DAT1 (0x02 << 16)
#define S3C2443_GPE8_AC_SYNC (0x03 << 16)
-#define S3C2400_GPE8_nXDACK0 (0x02 << 16)
#define S3C2410_GPE9_SDDAT2 (0x02 << 18)
#define S3C2443_GPE9_SD1_DAT2 (0x02 << 18)
#define S3C2443_GPE9_AC_nRESET (0x03 << 18)
-#define S3C2400_GPE9_nXDACK1 (0x02 << 18)
-#define S3C2400_GPE9_nXBACK (0x03 << 18)
#define S3C2410_GPE10_SDDAT3 (0x02 << 20)
#define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
-#define S3C2400_GPE10_nXDREQ0 (0x02 << 20)
#define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
-#define S3C2400_GPE11_nXDREQ1 (0x02 << 22)
-#define S3C2400_GPE11_nXBREQ (0x03 << 22)
#define S3C2410_GPE12_SPIMOSI0 (0x02 << 24)
@@ -447,9 +282,6 @@
*
* pull up works like all other ports.
*
- * S3C2400:
- * Port F consists of 7 GPIO/Special function
- *
* GPIO/serial/misc pins
*/
@@ -457,37 +289,14 @@
#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)
#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)
-#define S3C2400_GPFCON S3C2410_GPIOREG(0x38)
-#define S3C2400_GPFDAT S3C2410_GPIOREG(0x3C)
-#define S3C2400_GPFUP S3C2410_GPIOREG(0x40)
-
#define S3C2410_GPF0_EINT0 (0x02 << 0)
-#define S3C2400_GPF0_RXD0 (0x02 << 0)
-
#define S3C2410_GPF1_EINT1 (0x02 << 2)
-#define S3C2400_GPF1_RXD1 (0x02 << 2)
-#define S3C2400_GPF1_IICSDA (0x03 << 2)
-
#define S3C2410_GPF2_EINT2 (0x02 << 4)
-#define S3C2400_GPF2_TXD0 (0x02 << 4)
-
#define S3C2410_GPF3_EINT3 (0x02 << 6)
-#define S3C2400_GPF3_TXD1 (0x02 << 6)
-#define S3C2400_GPF3_IICSCL (0x03 << 6)
-
#define S3C2410_GPF4_EINT4 (0x02 << 8)
-#define S3C2400_GPF4_nRTS0 (0x02 << 8)
-#define S3C2400_GPF4_nXBACK (0x03 << 8)
-
#define S3C2410_GPF5_EINT5 (0x02 << 10)
-#define S3C2400_GPF5_nCTS0 (0x02 << 10)
-#define S3C2400_GPF5_nXBREQ (0x03 << 10)
-
#define S3C2410_GPF6_EINT6 (0x02 << 12)
-#define S3C2400_GPF6_CLKOUT (0x02 << 12)
-
#define S3C2410_GPF7_EINT7 (0x02 << 14)
-
#define S3C2410_GPF_PUPDIS(x) (1<<(x))
/* S3C2410:
@@ -497,62 +306,38 @@
* 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
*
* pull up works like all other ports.
- *
- * S3C2400:
- * Port G consists of 10 GPIO/Special function
*/
#define S3C2410_GPGCON S3C2410_GPIOREG(0x60)
#define S3C2410_GPGDAT S3C2410_GPIOREG(0x64)
#define S3C2410_GPGUP S3C2410_GPIOREG(0x68)
-#define S3C2400_GPGCON S3C2410_GPIOREG(0x44)
-#define S3C2400_GPGDAT S3C2410_GPIOREG(0x48)
-#define S3C2400_GPGUP S3C2410_GPIOREG(0x4C)
-
#define S3C2410_GPG0_EINT8 (0x02 << 0)
-#define S3C2400_GPG0_I2SLRCK (0x02 << 0)
#define S3C2410_GPG1_EINT9 (0x02 << 2)
-#define S3C2400_GPG1_I2SSCLK (0x02 << 2)
#define S3C2410_GPG2_EINT10 (0x02 << 4)
#define S3C2410_GPG2_nSS0 (0x03 << 4)
-#define S3C2400_GPG2_CDCLK (0x02 << 4)
#define S3C2410_GPG3_EINT11 (0x02 << 6)
#define S3C2410_GPG3_nSS1 (0x03 << 6)
-#define S3C2400_GPG3_I2SSDO (0x02 << 6)
-#define S3C2400_GPG3_I2SSDI (0x03 << 6)
#define S3C2410_GPG4_EINT12 (0x02 << 8)
-#define S3C2400_GPG4_MMCCLK (0x02 << 8)
-#define S3C2400_GPG4_I2SSDI (0x03 << 8)
#define S3C2410_GPG4_LCDPWREN (0x03 << 8)
#define S3C2443_GPG4_LCDPWRDN (0x03 << 8)
#define S3C2410_GPG5_EINT13 (0x02 << 10)
-#define S3C2400_GPG5_MMCCMD (0x02 << 10)
-#define S3C2400_GPG5_IICSDA (0x03 << 10)
#define S3C2410_GPG5_SPIMISO1 (0x03 << 10) /* not s3c2443 */
#define S3C2410_GPG6_EINT14 (0x02 << 12)
-#define S3C2400_GPG6_MMCDAT (0x02 << 12)
-#define S3C2400_GPG6_IICSCL (0x03 << 12)
#define S3C2410_GPG6_SPIMOSI1 (0x03 << 12)
#define S3C2410_GPG7_EINT15 (0x02 << 14)
#define S3C2410_GPG7_SPICLK1 (0x03 << 14)
-#define S3C2400_GPG7_SPIMISO (0x02 << 14)
-#define S3C2400_GPG7_IICSDA (0x03 << 14)
#define S3C2410_GPG8_EINT16 (0x02 << 16)
-#define S3C2400_GPG8_SPIMOSI (0x02 << 16)
-#define S3C2400_GPG8_IICSCL (0x03 << 16)
#define S3C2410_GPG9_EINT17 (0x02 << 18)
-#define S3C2400_GPG9_SPICLK (0x02 << 18)
-#define S3C2400_GPG9_MMCCLK (0x03 << 18)
#define S3C2410_GPG10_EINT18 (0x02 << 20)
@@ -660,7 +445,6 @@
#define S3C2443_GPMUP S3C2410_GPIOREG(0x108)
/* miscellaneous control */
-#define S3C2400_MISCCR S3C2410_GPIOREG(0x54)
#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
@@ -674,14 +458,6 @@
#define S3C2410_MISCCR_SPUCR_LEN (0<<1)
#define S3C2410_MISCCR_SPUCR_LDIS (1<<1)
-#define S3C2400_MISCCR_SPUCR_LEN (0<<0)
-#define S3C2400_MISCCR_SPUCR_LDIS (1<<0)
-#define S3C2400_MISCCR_SPUCR_HEN (0<<1)
-#define S3C2400_MISCCR_SPUCR_HDIS (1<<1)
-
-#define S3C2400_MISCCR_HZ_STOPEN (0<<2)
-#define S3C2400_MISCCR_HZ_STOPPREV (1<<2)
-
#define S3C2410_MISCCR_USBDEV (0<<3)
#define S3C2410_MISCCR_USBHOST (1<<3)
@@ -728,7 +504,6 @@
*
* Samsung datasheet p9-25
*/
-#define S3C2400_EXTINT0 S3C2410_GPIOREG(0x58)
#define S3C2410_EXTINT0 S3C2410_GPIOREG(0x88)
#define S3C2410_EXTINT1 S3C2410_GPIOREG(0x8C)
#define S3C2410_EXTINT2 S3C2410_GPIOREG(0x90)
@@ -796,22 +571,6 @@
#define S3C2410_GSTATUS2_OFFRESET (1<<1)
#define S3C2410_GSTATUS2_PONRESET (1<<0)
-/* open drain control register */
-#define S3C2400_OPENCR S3C2410_GPIOREG(0x50)
-
-#define S3C2400_OPENCR_OPC_RXD1DIS (0<<0)
-#define S3C2400_OPENCR_OPC_RXD1EN (1<<0)
-#define S3C2400_OPENCR_OPC_TXD1DIS (0<<1)
-#define S3C2400_OPENCR_OPC_TXD1EN (1<<1)
-#define S3C2400_OPENCR_OPC_CMDDIS (0<<2)
-#define S3C2400_OPENCR_OPC_CMDEN (1<<2)
-#define S3C2400_OPENCR_OPC_DATDIS (0<<3)
-#define S3C2400_OPENCR_OPC_DATEN (1<<3)
-#define S3C2400_OPENCR_OPC_MISODIS (0<<4)
-#define S3C2400_OPENCR_OPC_MISOEN (1<<4)
-#define S3C2400_OPENCR_OPC_MOSIDIS (0<<5)
-#define S3C2400_OPENCR_OPC_MOSIEN (1<<5)
-
/* 2412/2413 sleep configuration registers */
#define S3C2412_GPBSLPCON S3C2410_GPIOREG(0x1C)
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-mem.h b/arch/arm/mach-s3c2410/include/mach/regs-mem.h
index 988a6863e54b..e0c67b0163d8 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-mem.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-mem.h
@@ -145,29 +145,8 @@
#define S3C2410_BANKCON_Tacs_SHIFT (13)
#define S3C2410_BANKCON_SRAM (0x0 << 15)
-#define S3C2400_BANKCON_EDODRAM (0x2 << 15)
#define S3C2410_BANKCON_SDRAM (0x3 << 15)
-/* next bits only for EDO DRAM in 6,7 */
-#define S3C2400_BANKCON_EDO_Trcd1 (0x00 << 4)
-#define S3C2400_BANKCON_EDO_Trcd2 (0x01 << 4)
-#define S3C2400_BANKCON_EDO_Trcd3 (0x02 << 4)
-#define S3C2400_BANKCON_EDO_Trcd4 (0x03 << 4)
-
-/* CAS pulse width */
-#define S3C2400_BANKCON_EDO_PULSE1 (0x00 << 3)
-#define S3C2400_BANKCON_EDO_PULSE2 (0x01 << 3)
-
-/* CAS pre-charge */
-#define S3C2400_BANKCON_EDO_TCP1 (0x00 << 2)
-#define S3C2400_BANKCON_EDO_TCP2 (0x01 << 2)
-
-/* control column address select */
-#define S3C2400_BANKCON_EDO_SCANb8 (0x00 << 0)
-#define S3C2400_BANKCON_EDO_SCANb9 (0x01 << 0)
-#define S3C2400_BANKCON_EDO_SCANb10 (0x02 << 0)
-#define S3C2400_BANKCON_EDO_SCANb11 (0x03 << 0)
-
/* next bits only for SDRAM in 6,7 */
#define S3C2410_BANKCON_Trcd2 (0x00 << 2)
#define S3C2410_BANKCON_Trcd3 (0x01 << 2)
@@ -194,12 +173,6 @@
#define S3C2410_REFRESH_TRP_3clk (1<<20)
#define S3C2410_REFRESH_TRP_4clk (2<<20)
-#define S3C2400_REFRESH_DRAM_TRP_MASK (3<<20)
-#define S3C2400_REFRESH_DRAM_TRP_1_5clk (0<<20)
-#define S3C2400_REFRESH_DRAM_TRP_2_5clk (1<<20)
-#define S3C2400_REFRESH_DRAM_TRP_3_5clk (2<<20)
-#define S3C2400_REFRESH_DRAM_TRP_4_5clk (3<<20)
-
#define S3C2410_REFRESH_TSRC_MASK (3<<18)
#define S3C2410_REFRESH_TSRC_4clk (0<<18)
#define S3C2410_REFRESH_TSRC_5clk (1<<18)
@@ -222,7 +195,6 @@
#define S3C2410_BANKSIZE_4M (0x5 << 0)
#define S3C2410_BANKSIZE_2M (0x4 << 0)
#define S3C2410_BANKSIZE_MASK (0x7 << 0)
-#define S3C2400_BANKSIZE_MASK (0x4 << 0)
#define S3C2410_BANKSIZE_SCLK_EN (1<<4)
#define S3C2410_BANKSIZE_SCKE_EN (1<<5)
#define S3C2410_BANKSIZE_BURST (1<<7)
diff --git a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
deleted file mode 100644
index dcef2287cb38..000000000000
--- a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/spi-gpio.h
- *
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - SPI Controller platform_device info
- *
- * 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_SPIGPIO_H
-#define __ASM_ARCH_SPIGPIO_H __FILE__
-
-struct s3c2410_spigpio_info {
- unsigned long pin_clk;
- unsigned long pin_mosi;
- unsigned long pin_miso;
-
- int num_chipselect;
- int bus_num;
-
- void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
-};
-
-
-#endif /* __ASM_ARCH_SPIGPIO_H */
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index e8f49feef28c..f44f77531b1e 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -32,7 +32,7 @@
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_gpio.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -53,8 +53,6 @@
#include <mach/fb.h>
#include <plat/nand.h>
#include <plat/udc.h>
-#include <mach/spi.h>
-#include <mach/spi-gpio.h>
#include <plat/iic.h>
#include <plat/common-smdk.h>
@@ -216,32 +214,16 @@ static struct platform_device qt2410_led = {
/* SPI */
-static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
-{
- switch (cs) {
- case BITBANG_CS_ACTIVE:
- gpio_set_value(S3C2410_GPB(5), 0);
- break;
- case BITBANG_CS_INACTIVE:
- gpio_set_value(S3C2410_GPB(5), 1);
- break;
- }
-}
-
-static struct s3c2410_spigpio_info spi_gpio_cfg = {
- .pin_clk = S3C2410_GPG(7),
- .pin_mosi = S3C2410_GPG(6),
- .pin_miso = S3C2410_GPG(5),
- .chip_select = &spi_gpio_cs,
+static struct spi_gpio_platform_data spi_gpio_cfg = {
+ .sck = S3C2410_GPG(7),
+ .mosi = S3C2410_GPG(6),
+ .miso = S3C2410_GPG(5),
};
-
static struct platform_device qt2410_spi = {
- .name = "s3c24xx-spi-gpio",
- .id = 1,
- .dev = {
- .platform_data = &spi_gpio_cfg,
- },
+ .name = "spi-gpio",
+ .id = 1,
+ .dev.platform_data = &spi_gpio_cfg,
};
/* Board devices */
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
index e82ab4aa7ab9..c2cf4e569989 100644
--- a/arch/arm/mach-s3c2412/Kconfig
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -15,7 +15,7 @@ config CPU_S3C2412
config CPU_S3C2412_ONLY
bool
- depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+ depends on ARCH_S3C2410 && !CPU_S3C2410 && \
!CPU_S3C2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
!CPU_S3C2443 && CPU_S3C2412
default y if CPU_S3C2412
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c
index 0c0505b025cb..140711db6c89 100644
--- a/arch/arm/mach-s3c2412/clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -95,12 +95,10 @@ static int s3c2412_upll_enable(struct clk *clk, int enable)
static struct clk clk_erefclk = {
.name = "erefclk",
- .id = -1,
};
static struct clk clk_urefclk = {
.name = "urefclk",
- .id = -1,
};
static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
@@ -122,7 +120,6 @@ static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
static struct clk clk_usysclk = {
.name = "usysclk",
- .id = -1,
.parent = &clk_xtal,
.ops = &(struct clk_ops) {
.set_parent = s3c2412_setparent_usysclk,
@@ -132,13 +129,11 @@ static struct clk clk_usysclk = {
static struct clk clk_mrefclk = {
.name = "mrefclk",
.parent = &clk_xtal,
- .id = -1,
};
static struct clk clk_mdivclk = {
.name = "mdivclk",
.parent = &clk_xtal,
- .id = -1,
};
static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
@@ -200,7 +195,6 @@ static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
static struct clk clk_usbsrc = {
.name = "usbsrc",
- .id = -1,
.ops = &(struct clk_ops) {
.get_rate = s3c2412_getrate_usbsrc,
.set_rate = s3c2412_setrate_usbsrc,
@@ -228,7 +222,6 @@ static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
static struct clk clk_msysclk = {
.name = "msysclk",
- .id = -1,
.ops = &(struct clk_ops) {
.set_parent = s3c2412_setparent_msysclk,
},
@@ -268,7 +261,6 @@ static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent)
static struct clk clk_armclk = {
.name = "armclk",
- .id = -1,
.parent = &clk_msysclk,
.ops = &(struct clk_ops) {
.set_parent = s3c2412_setparent_armclk,
@@ -344,7 +336,6 @@ static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
static struct clk clk_uart = {
.name = "uartclk",
- .id = -1,
.ops = &(struct clk_ops) {
.get_rate = s3c2412_getrate_uart,
.set_rate = s3c2412_setrate_uart,
@@ -397,7 +388,6 @@ static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
static struct clk clk_i2s = {
.name = "i2sclk",
- .id = -1,
.ops = &(struct clk_ops) {
.get_rate = s3c2412_getrate_i2s,
.set_rate = s3c2412_setrate_i2s,
@@ -449,7 +439,6 @@ static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
static struct clk clk_cam = {
.name = "camif-upll", /* same as 2440 name */
- .id = -1,
.ops = &(struct clk_ops) {
.get_rate = s3c2412_getrate_cam,
.set_rate = s3c2412_setrate_cam,
@@ -463,37 +452,31 @@ static struct clk clk_cam = {
static struct clk init_clocks_disable[] = {
{
.name = "nand",
- .id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_NAND,
}, {
.name = "sdi",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_SDI,
}, {
.name = "adc",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_ADC,
}, {
.name = "i2c",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_IIC,
}, {
.name = "iis",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_IIS,
}, {
.name = "spi",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_SPI,
@@ -503,96 +486,83 @@ static struct clk init_clocks_disable[] = {
static struct clk init_clocks[] = {
{
.name = "dma",
- .id = 0,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA0,
}, {
.name = "dma",
- .id = 1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA1,
}, {
.name = "dma",
- .id = 2,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA2,
}, {
.name = "dma",
- .id = 3,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA3,
}, {
.name = "lcd",
- .id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_LCDC,
}, {
.name = "gpio",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_GPIO,
}, {
.name = "usb-host",
- .id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USBH,
}, {
.name = "usb-device",
- .id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USBD,
}, {
.name = "timers",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_PWMT,
}, {
.name = "uart",
- .id = 0,
+ .devname = "s3c2412-uart.0",
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_UART0,
}, {
.name = "uart",
- .id = 1,
+ .devname = "s3c2412-uart.1",
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_UART1,
}, {
.name = "uart",
- .id = 2,
+ .devname = "s3c2412-uart.2",
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_UART2,
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_RTC,
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_p,
.ctrlbit = 0,
}, {
.name = "usb-bus-gadget",
- .id = -1,
.parent = &clk_usb_bus,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USB_DEV48,
}, {
.name = "usb-bus-host",
- .id = -1,
.parent = &clk_usb_bus,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USB_HOST48,
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 85dcaeb9e62f..5eeb47580b0c 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -25,6 +25,7 @@
#include <video/ili9320.h>
#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -38,7 +39,6 @@
#include <mach/regs-gpio.h>
#include <mach/regs-mem.h>
#include <mach/regs-lcd.h>
-#include <mach/spi-gpio.h>
#include <mach/fb.h>
#include <asm/mach-types.h>
@@ -389,45 +389,30 @@ static struct ili9320_platdata jive_lcm_config = {
/* LCD SPI support */
-static void jive_lcd_spi_chipselect(struct s3c2410_spigpio_info *spi, int cs)
-{
- gpio_set_value(S3C2410_GPB(7), cs ? 0 : 1);
-}
-
-static struct s3c2410_spigpio_info jive_lcd_spi = {
- .bus_num = 1,
- .pin_clk = S3C2410_GPG(8),
- .pin_mosi = S3C2410_GPB(8),
- .num_chipselect = 1,
- .chip_select = jive_lcd_spi_chipselect,
+static struct spi_gpio_platform_data jive_lcd_spi = {
+ .sck = S3C2410_GPG(8),
+ .mosi = S3C2410_GPB(8),
+ .miso = SPI_GPIO_NO_MISO,
};
static struct platform_device jive_device_lcdspi = {
- .name = "spi_s3c24xx_gpio",
+ .name = "spi-gpio",
.id = 1,
- .num_resources = 0,
.dev.platform_data = &jive_lcd_spi,
};
-/* WM8750 audio code SPI definition */
-static void jive_wm8750_chipselect(struct s3c2410_spigpio_info *spi, int cs)
-{
- gpio_set_value(S3C2410_GPH(10), cs ? 0 : 1);
-}
+/* WM8750 audio code SPI definition */
-static struct s3c2410_spigpio_info jive_wm8750_spi = {
- .bus_num = 2,
- .pin_clk = S3C2410_GPB(4),
- .pin_mosi = S3C2410_GPB(9),
- .num_chipselect = 1,
- .chip_select = jive_wm8750_chipselect,
+static struct spi_gpio_platform_data jive_wm8750_spi = {
+ .sck = S3C2410_GPB(4),
+ .mosi = S3C2410_GPB(9),
+ .miso = SPI_GPIO_NO_MISO,
};
static struct platform_device jive_device_wm8750 = {
- .name = "spi_s3c24xx_gpio",
+ .name = "spi-gpio",
.id = 2,
- .num_resources = 0,
.dev.platform_data = &jive_wm8750_spi,
};
@@ -441,12 +426,14 @@ static struct spi_board_info __initdata jive_spi_devs[] = {
.mode = SPI_MODE_3, /* CPOL=1, CPHA=1 */
.max_speed_hz = 100000,
.platform_data = &jive_lcm_config,
+ .controller_data = (void *)S3C2410_GPB(7),
}, {
.modalias = "WM8750",
.bus_num = 2,
.chip_select = 0,
.mode = SPI_MODE_0, /* CPOL=0, CPHA=0 */
.max_speed_hz = 100000,
+ .controller_data = (void *)S3C2410_GPH(10),
},
};
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
index 752b13a7b3db..f4077efa51fa 100644
--- a/arch/arm/mach-s3c2412/pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -37,12 +37,10 @@
extern void s3c2412_sleep_enter(void);
-static void s3c2412_cpu_suspend(void)
+static int s3c2412_cpu_suspend(unsigned long arg)
{
unsigned long tmp;
- flush_cache_all();
-
/* set our standby method to sleep */
tmp = __raw_readl(S3C2412_PWRCFG);
@@ -50,6 +48,8 @@ static void s3c2412_cpu_suspend(void)
__raw_writel(tmp, S3C2412_PWRCFG);
s3c2412_sleep_enter();
+
+ panic("sleep resumed to originator?");
}
static void s3c2412_pm_prepare(void)
diff --git a/arch/arm/mach-s3c2416/clock.c b/arch/arm/mach-s3c2416/clock.c
index 3b02d8506e25..21a5e81f0ab5 100644
--- a/arch/arm/mach-s3c2416/clock.c
+++ b/arch/arm/mach-s3c2416/clock.c
@@ -42,7 +42,7 @@ static struct clksrc_clk hsmmc_div[] = {
[0] = {
.clk = {
.name = "hsmmc-div",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_esysclk.clk,
},
.reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 },
@@ -50,7 +50,7 @@ static struct clksrc_clk hsmmc_div[] = {
[1] = {
.clk = {
.name = "hsmmc-div",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_esysclk.clk,
},
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
@@ -60,8 +60,8 @@ static struct clksrc_clk hsmmc_div[] = {
static struct clksrc_clk hsmmc_mux[] = {
[0] = {
.clk = {
- .id = 0,
.name = "hsmmc-if",
+ .devname = "s3c-sdhci.0",
.ctrlbit = (1 << 6),
.enable = s3c2443_clkcon_enable_s,
},
@@ -76,8 +76,8 @@ static struct clksrc_clk hsmmc_mux[] = {
},
[1] = {
.clk = {
- .id = 1,
.name = "hsmmc-if",
+ .devname = "s3c-sdhci.1",
.ctrlbit = (1 << 12),
.enable = s3c2443_clkcon_enable_s,
},
@@ -94,7 +94,7 @@ static struct clksrc_clk hsmmc_mux[] = {
static struct clk hsmmc0_clk = {
.name = "hsmmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2416_HCLKCON_HSMMC0,
diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c
index 41db2b21e213..9ec54f1d8e75 100644
--- a/arch/arm/mach-s3c2416/pm.c
+++ b/arch/arm/mach-s3c2416/pm.c
@@ -24,10 +24,8 @@
extern void s3c2412_sleep_enter(void);
-static void s3c2416_cpu_suspend(void)
+static int s3c2416_cpu_suspend(unsigned long arg)
{
- flush_cache_all();
-
/* enable wakeup sources regardless of battery state */
__raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG);
@@ -35,6 +33,8 @@ static void s3c2416_cpu_suspend(void)
__raw_writel(0x2BED, S3C2443_PWRMODE);
s3c2412_sleep_enter();
+
+ panic("sleep resumed to originator?");
}
static void s3c2416_pm_prepare(void)
diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c
index 3dc2426e2345..f9e6bdaf41d2 100644
--- a/arch/arm/mach-s3c2440/clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -36,7 +36,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <mach/regs-clock.h>
@@ -90,14 +90,12 @@ static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
static struct clk s3c2440_clk_cam = {
.name = "camif",
- .id = -1,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2440_CLKCON_CAMERA,
};
static struct clk s3c2440_clk_cam_upll = {
.name = "camif-upll",
- .id = -1,
.ops = &(struct clk_ops) {
.set_rate = s3c2440_camif_upll_setrate,
.round_rate = s3c2440_camif_upll_round,
@@ -106,7 +104,6 @@ static struct clk s3c2440_clk_cam_upll = {
static struct clk s3c2440_clk_ac97 = {
.name = "ac97",
- .id = -1,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2440_CLKCON_CAMERA,
};
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 716662008ce2..c10ddf4ed7f1 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -74,7 +74,6 @@
#include <mach/fb.h>
#include <mach/spi.h>
-#include <mach/spi-gpio.h>
#include <plat/usb-control.h>
#include <mach/regs-mem.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c
index 6224bad4d604..9ad99f8016a1 100644
--- a/arch/arm/mach-s3c2440/s3c2442.c
+++ b/arch/arm/mach-s3c2440/s3c2442.c
@@ -38,7 +38,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <mach/regs-clock.h>
diff --git a/arch/arm/mach-s3c2440/s3c244x-clock.c b/arch/arm/mach-s3c2440/s3c244x-clock.c
index f8d96130d1d1..7f5ea0a169a5 100644
--- a/arch/arm/mach-s3c2440/s3c244x-clock.c
+++ b/arch/arm/mach-s3c2440/s3c244x-clock.c
@@ -35,7 +35,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <mach/regs-clock.h>
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index f4ec6d5715c8..a1a7176675b9 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -59,7 +59,6 @@
static struct clk clk_i2s_ext = {
.name = "i2s-ext",
- .id = -1,
};
/* armdiv
@@ -139,7 +138,6 @@ static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
static struct clk clk_armdiv = {
.name = "armdiv",
- .id = -1,
.parent = &clk_msysclk.clk,
.ops = &(struct clk_ops) {
.round_rate = s3c2443_armclk_roundrate,
@@ -160,7 +158,6 @@ static struct clk *clk_arm_sources[] = {
static struct clksrc_clk clk_arm = {
.clk = {
.name = "armclk",
- .id = -1,
},
.sources = &(struct clksrc_sources) {
.sources = clk_arm_sources,
@@ -177,7 +174,6 @@ static struct clksrc_clk clk_arm = {
static struct clksrc_clk clk_hsspi = {
.clk = {
.name = "hsspi",
- .id = -1,
.parent = &clk_esysclk.clk,
.ctrlbit = S3C2443_SCLKCON_HSSPICLK,
.enable = s3c2443_clkcon_enable_s,
@@ -196,7 +192,7 @@ static struct clksrc_clk clk_hsspi = {
static struct clksrc_clk clk_hsmmc_div = {
.clk = {
.name = "hsmmc-div",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_esysclk.clk,
},
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
@@ -231,7 +227,7 @@ static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
static struct clk clk_hsmmc = {
.name = "hsmmc-if",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_hsmmc_div.clk,
.enable = s3c2443_enable_hsmmc,
.ops = &(struct clk_ops) {
@@ -248,7 +244,6 @@ static struct clk clk_hsmmc = {
static struct clksrc_clk clk_i2s_eplldiv = {
.clk = {
.name = "i2s-eplldiv",
- .id = -1,
.parent = &clk_esysclk.clk,
},
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
@@ -271,7 +266,6 @@ struct clk *clk_i2s_srclist[] = {
static struct clksrc_clk clk_i2s = {
.clk = {
.name = "i2s-if",
- .id = -1,
.ctrlbit = S3C2443_SCLKCON_I2SCLK,
.enable = s3c2443_clkcon_enable_s,
@@ -288,25 +282,23 @@ static struct clksrc_clk clk_i2s = {
static struct clk init_clocks_off[] = {
{
.name = "sdi",
- .id = -1,
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_SDI,
}, {
.name = "iis",
- .id = -1,
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_IIS,
}, {
.name = "spi",
- .id = 0,
+ .devname = "s3c2410-spi.0",
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_SPI0,
}, {
.name = "spi",
- .id = 1,
+ .devname = "s3c2410-spi.1",
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_SPI1,
diff --git a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
deleted file mode 100644
index 0c5a73805560..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/debug-macro.S
- *
- * 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.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-#include <plat/regs-serial.h>
-
- .macro addruart, rp, rv
- ldr \rp, = S3C24XX_PA_UART
- ldr \rv, = S3C24XX_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
- add \rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
- add \rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
-#endif
- .endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s3c24a0/include/mach/io.h b/arch/arm/mach-s3c24a0/include/mach/io.h
deleted file mode 100644
index 4326c30fabcb..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s3c24a0/include/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S3C24A0
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a) __typesafe_io(a)
-#define __mem_pci(a) (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
diff --git a/arch/arm/mach-s3c24a0/include/mach/irqs.h b/arch/arm/mach-s3c24a0/include/mach/irqs.h
deleted file mode 100644
index 83ce2a7a9dae..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/irqs.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/irqs.h
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- * Ben Dooks <ben@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_24A0_IRQS_H
-#define __ASM_ARCH_24A0_IRQS_H __FILE__
-
-#define IRQ_EINT0t2 S3C2410_IRQ(0) /* 16 */
-/* for generic entry-macro.S */
-#define IRQ_EINT0 IRQ_EINT0t2
-
-#define IRQ_EINT3t6 S3C2410_IRQ(1)
-#define IRQ_EINT7t10 S3C2410_IRQ(2)
-#define IRQ_EINT11t14 S3C2410_IRQ(3)
-#define IRQ_EINT15t18 S3C2410_IRQ(4) /* 20 */
-#define IRQ_TICK S3C2410_IRQ(5)
-#define IRQ_DCTQ S3C2410_IRQ(6)
-#define IRQ_MC S3C2410_IRQ(7)
-#define IRQ_ME S3C2410_IRQ(8) /* 24 */
-#define IRQ_KEYPAD S3C2410_IRQ(9)
-#define IRQ_TIMER0 S3C2410_IRQ(10)
-#define IRQ_TIMER1 S3C2410_IRQ(11)
-#define IRQ_TIMER2 S3C2410_IRQ(12)
-#define IRQ_TIMER3_4 S3C2410_IRQ(13)
-#define IRQ_OS_TIMER IRQ_TIMER3_4
-#define IRQ_LCD S3C2410_IRQ(14)
-#define IRQ_CAM_C S3C2410_IRQ(15)
-#define IRQ_WDT_BATFLT S3C2410_IRQ(16) /* 32 */
-#define IRQ_UART0 S3C2410_IRQ(17)
-#define IRQ_CAM_P S3C2410_IRQ(18)
-#define IRQ_MODEM S3C2410_IRQ(19)
-#define IRQ_DMA S3C2410_IRQ(20)
-#define IRQ_SDI S3C2410_IRQ(21)
-#define IRQ_SPI0 S3C2410_IRQ(22)
-#define IRQ_UART1 S3C2410_IRQ(23)
-#define IRQ_AC97_NFLASH S3C2410_IRQ(24) /* 40 */
-#define IRQ_USBD S3C2410_IRQ(25)
-#define IRQ_USBH S3C2410_IRQ(26)
-#define IRQ_IIC S3C2410_IRQ(27)
-#define IRQ_IRDA_MSTICK S3C2410_IRQ(28) /* 44 */
-#define IRQ_VLX_SPI1 S3C2410_IRQ(29)
-#define IRQ_RTC S3C2410_IRQ(30) /* 46 */
-#define IRQ_ADC_PEN S3C2410_IRQ(31)
-
-/* interrupts generated from the external interrupts sources */
-#define IRQ_EINT00 S3C2410_IRQ(32) /* 48 */
-#define IRQ_EINT1 S3C2410_IRQ(33)
-#define IRQ_EINT2 S3C2410_IRQ(34)
-#define IRQ_EINT3 S3C2410_IRQ(35)
-#define IRQ_EINT4 S3C2410_IRQ(36)
-#define IRQ_EINT5 S3C2410_IRQ(37)
-#define IRQ_EINT6 S3C2410_IRQ(38)
-#define IRQ_EINT7 S3C2410_IRQ(39)
-#define IRQ_EINT8 S3C2410_IRQ(40)
-#define IRQ_EINT9 S3C2410_IRQ(41)
-#define IRQ_EINT10 S3C2410_IRQ(42)
-#define IRQ_EINT11 S3C2410_IRQ(43)
-#define IRQ_EINT12 S3C2410_IRQ(44)
-#define IRQ_EINT13 S3C2410_IRQ(45)
-#define IRQ_EINT14 S3C2410_IRQ(46)
-#define IRQ_EINT15 S3C2410_IRQ(47)
-#define IRQ_EINT16 S3C2410_IRQ(48)
-#define IRQ_EINT17 S3C2410_IRQ(49)
-#define IRQ_EINT18 S3C2410_IRQ(50)
-
-#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT00)
-
-/* SUB IRQS */
-#define IRQ_S3CUART_RX0 S3C2410_IRQ(51) /* 67 */
-#define IRQ_S3CUART_TX0 S3C2410_IRQ(52)
-#define IRQ_S3CUART_ERR0 S3C2410_IRQ(53)
-
-#define IRQ_S3CUART_RX1 S3C2410_IRQ(54)
-#define IRQ_S3CUART_TX1 S3C2410_IRQ(55)
-#define IRQ_S3CUART_ERR1 S3C2410_IRQ(56)
-
-#define IRQ_S3CUART_RX2 (0x0)
-#define IRQ_S3CUART_TX2 (0x0)
-#define IRQ_S3CUART_ERR2 (0x0)
-
-
-#define IRQ_IRDA S3C2410_IRQ(57)
-#define IRQ_MSTICK S3C2410_IRQ(58)
-#define IRQ_RESERVED0 S3C2410_IRQ(59)
-#define IRQ_RESERVED1 S3C2410_IRQ(60)
-#define IRQ_RESERVED2 S3C2410_IRQ(61)
-#define IRQ_TIMER3 S3C2410_IRQ(62)
-#define IRQ_TIMER4 S3C2410_IRQ(63)
-#define IRQ_WDT S3C2410_IRQ(64)
-#define IRQ_BATFLT S3C2410_IRQ(65)
-#define IRQ_POST S3C2410_IRQ(66)
-#define IRQ_DISP_FIFO S3C2410_IRQ(67)
-#define IRQ_PENUP S3C2410_IRQ(68)
-#define IRQ_PENDN S3C2410_IRQ(69)
-#define IRQ_ADC S3C2410_IRQ(70)
-#define IRQ_DISP_FRAME S3C2410_IRQ(71)
-#define IRQ_NFLASH S3C2410_IRQ(72)
-#define IRQ_AC97 S3C2410_IRQ(73)
-#define IRQ_SPI1 S3C2410_IRQ(74)
-#define IRQ_VLX S3C2410_IRQ(75)
-#define IRQ_DMA0 S3C2410_IRQ(76)
-#define IRQ_DMA1 S3C2410_IRQ(77)
-#define IRQ_DMA2 S3C2410_IRQ(78)
-#define IRQ_DMA3 S3C2410_IRQ(79)
-
-#define IRQ_TC (0x0)
-
-#define NR_IRQS (IRQ_DMA3+1)
-
-#endif /* __ASM_ARCH_24A0_IRQS_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/map.h b/arch/arm/mach-s3c24a0/include/mach/map.h
deleted file mode 100644
index d88c8b24fe34..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/map.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/map.h
- *
- * Copyright 2003-2007 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24A0 - 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_ARCH_24A0_MAP_H
-#define __ASM_ARCH_24A0_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map.h>
-
-#define S3C24A0_PA_IO_BASE (0x40000000)
-#define S3C24A0_PA_CLKPWR (0x40000000)
-#define S3C24A0_PA_IRQ (0x40200000)
-#define S3C24A0_PA_DMA (0x40400000)
-#define S3C24A0_PA_MEMCTRL (0x40C00000)
-#define S3C24A0_PA_NAND (0x40C00000)
-#define S3C24A0_PA_SROM (0x40C20000)
-#define S3C24A0_PA_SDRAM (0x40C40000)
-#define S3C24A0_PA_BUSM (0x40CE0000)
-#define S3C24A0_PA_USBHOST (0x41000000)
-#define S3C24A0_PA_MODEMIF (0x41180000)
-#define S3C24A0_PA_IRDA (0x41800000)
-#define S3C24A0_PA_TIMER (0x44000000)
-#define S3C24A0_PA_WATCHDOG (0x44100000)
-#define S3C24A0_PA_RTC (0x44200000)
-#define S3C24A0_PA_UART (0x44400000)
-#define S3C24A0_PA_UART0 (S3C24A0_PA_UART)
-#define S3C24A0_PA_UART1 (S3C24A0_PA_UART + 0x4000)
-#define S3C24A0_PA_SPI (0x44500000)
-#define S3C24A0_PA_IIC (0x44600000)
-#define S3C24A0_PA_IIS (0x44700000)
-#define S3C24A0_PA_GPIO (0x44800000)
-#define S3C24A0_PA_KEYIF (0x44900000)
-#define S3C24A0_PA_USBDEV (0x44A00000)
-#define S3C24A0_PA_AC97 (0x45000000)
-#define S3C24A0_PA_ADC (0x45800000)
-#define S3C24A0_PA_SDI (0x46000000)
-#define S3C24A0_PA_MS (0x46100000)
-#define S3C24A0_PA_LCD (0x4A000000)
-#define S3C24A0_PA_VPOST (0x4A100000)
-
-/* physical addresses of all the chip-select areas */
-
-#define S3C24A0_CS0 (0x00000000)
-#define S3C24A0_CS1 (0x04000000)
-#define S3C24A0_CS2 (0x08000000)
-#define S3C24A0_CS3 (0x0C000000)
-#define S3C24A0_CS4 (0x10000000)
-#define S3C24A0_CS5 (0x40000000)
-
-#define S3C24A0_SDRAM_PA (S3C24A0_CS4)
-
-/* Use a single interface for common resources between S3C24XX cpus */
-
-#define S3C24XX_PA_IRQ S3C24A0_PA_IRQ
-#define S3C24XX_PA_MEMCTRL S3C24A0_PA_MEMCTRL
-#define S3C24XX_PA_USBHOST S3C24A0_PA_USBHOST
-#define S3C24XX_PA_DMA S3C24A0_PA_DMA
-#define S3C24XX_PA_CLKPWR S3C24A0_PA_CLKPWR
-#define S3C24XX_PA_LCD S3C24A0_PA_LCD
-#define S3C24XX_PA_UART S3C24A0_PA_UART
-#define S3C24XX_PA_TIMER S3C24A0_PA_TIMER
-#define S3C24XX_PA_USBDEV S3C24A0_PA_USBDEV
-#define S3C24XX_PA_WATCHDOG S3C24A0_PA_WATCHDOG
-#define S3C24XX_PA_IIS S3C24A0_PA_IIS
-#define S3C24XX_PA_GPIO S3C24A0_PA_GPIO
-#define S3C24XX_PA_RTC S3C24A0_PA_RTC
-#define S3C24XX_PA_ADC S3C24A0_PA_ADC
-#define S3C24XX_PA_SPI S3C24A0_PA_SPI
-#define S3C24XX_PA_SDI S3C24A0_PA_SDI
-#define S3C24XX_PA_NAND S3C24A0_PA_NAND
-
-#define S3C_PA_UART S3C24A0_PA_UART
-#define S3C_PA_IIC S3C24A0_PA_IIC
-#define S3C_PA_NAND S3C24XX_PA_NAND
-
-#endif /* __ASM_ARCH_24A0_MAP_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h
deleted file mode 100644
index 7d208a71b172..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/memory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/memory.h
- * from linux/include/asm-arm/arch-rpc/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_24A0_MEMORY_H
-#define __ASM_ARCH_24A0_MEMORY_H __FILE__
-
-#define PLAT_PHYS_OFFSET UL(0x10000000)
-
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt(x) __phys_to_virt(x)
-#define __pfn_to_bus(x) __pfn_to_phys(x)
-#define __bus_to_pfn(x) __phys_to_pfn(x)
-
-#endif
diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-clock.h b/arch/arm/mach-s3c24a0/include/mach/regs-clock.h
deleted file mode 100644
index be0af518b488..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/regs-clock.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/regs-clock.h
- *
- * Copyright (c) 2003-2006 Simtec Electronics <linux@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.
- *
- * S3C24A0 clock register definitions
-*/
-
-#ifndef __ASM_ARCH_24A0_REGS_CLOCK_H
-#define __ASM_ARCH_24A0_REGS_CLOCK_H __FILE__
-
-#define S3C24A0_MPLLCON S3C2410_CLKREG(0x10)
-#define S3C24A0_UPLLCON S3C2410_CLKREG(0x14)
-#define S3C24A0_CLKCON S3C2410_CLKREG(0x20)
-#define S3C24A0_CLKSRC S3C2410_CLKREG(0x24)
-#define S3C24A0_CLKDIVN S3C2410_CLKREG(0x28)
-
-/* CLKCON register bits */
-
-#define S3C24A0_CLKCON_VLX (1<<29)
-#define S3C24A0_CLKCON_VPOST (1<<28)
-#define S3C24A0_CLKCON_WDT (1<<27) /* reserved */
-#define S3C24A0_CLKCON_MPEGDCTQ (1<<26)
-#define S3C24A0_CLKCON_VPOSTIF (1<<25)
-#define S3C24A0_CLKCON_MPEG4IF (1<<24)
-#define S3C24A0_CLKCON_CAM_UPLL (1<<23)
-#define S3C24A0_CLKCON_LCDC (1<<22)
-#define S3C24A0_CLKCON_CAM_HCLK (1<<21)
-#define S3C24A0_CLKCON_MPEG4 (1<<20)
-#define S3C24A0_CLKCON_KEYPAD (1<<19)
-#define S3C24A0_CLKCON_ADC (1<<18)
-#define S3C24A0_CLKCON_SDI (1<<17)
-#define S3C24A0_CLKCON_MS (1<<16) /* memory stick */
-#define S3C24A0_CLKCON_USBD (1<<15)
-#define S3C24A0_CLKCON_GPIO (1<<14)
-#define S3C24A0_CLKCON_IIS (1<<13)
-#define S3C24A0_CLKCON_IIC (1<<12)
-#define S3C24A0_CLKCON_SPI (1<<11)
-#define S3C24A0_CLKCON_UART1 (1<<10)
-#define S3C24A0_CLKCON_UART0 (1<<9)
-#define S3C24A0_CLKCON_PWMT (1<<8)
-#define S3C24A0_CLKCON_USBH (1<<7)
-#define S3C24A0_CLKCON_AC97 (1<<6)
-#define S3C24A0_CLKCON_IrDA (1<<4)
-#define S3C24A0_CLKCON_IDLE (1<<2)
-#define S3C24A0_CLKCON_MON (1<<1)
-#define S3C24A0_CLKCON_STOP (1<<0)
-
-/* CLKSRC register bits */
-
-#define S3C24A0_CLKSRC_OSC (1<<8) /* CLKSRC */
-#define S3C24A0_CLKSRC_UPLL (1<<7)
-#define S3C24A0_CLKSRC_MPLL (1<<5)
-#define S3C24A0_CLKSRC_EXT (1<<4)
-
-/* Use a single interface with the common code, for s3c24xx */
-
-#define S3C2410_MPLLCON S3C24A0_MPLLCON
-#define S3C2410_UPLLCON S3C24A0_UPLLCON
-#define S3C2410_CLKCON S3C24A0_CLKCON
-#define S3C2410_CLKSLOW S3C24A0_CLKSRC
-#define S3C2410_CLKDIVN S3C24A0_CLKDIVN
-
-#define S3C2410_CLKCON_IDLE S3C24A0_CLKCON_IDLE
-#define S3C2410_CLKCON_POWER S3C24A0_CLKCON_STOP
-#define S3C2410_CLKCON_LCDC S3C24A0_CLKCON_LCDC
-#define S3C2410_CLKCON_USBH S3C24A0_CLKCON_USBH
-#define S3C2410_CLKCON_USBD S3C24A0_CLKCON_USBD
-#define S3C2410_CLKCON_PWMT S3C24A0_CLKCON_PWMT
-#define S3C2410_CLKCON_SDI S3C24A0_CLKCON_SDI
-#define S3C2410_CLKCON_UART0 S3C24A0_CLKCON_UART0
-#define S3C2410_CLKCON_UART1 S3C24A0_CLKCON_UART1
-#define S3C2410_CLKCON_GPIO S3C24A0_CLKCON_GPIO
-#define S3C2410_CLKCON_ADC S3C24A0_CLKCON_ADC
-#define S3C2410_CLKCON_IIC S3C24A0_CLKCON_IIC
-#define S3C2410_CLKCON_IIS S3C24A0_CLKCON_IIS
-#define S3C2410_CLKCON_SPI S3C24A0_CLKCON_SPI
-
-#define S3C2410_CLKSLOW_UCLK_OFF S3C24A0_CLKSRC_UPLL
-#define S3C2410_CLKSLOW_MPLL_OFF S3C24A0_CLKSRC_MPLL
-#define S3C2410_CLKSLOW_SLOW (0xFF)
-#define S3C2410_CLKSLOW_GET_SLOWVAL(x) (0x1)
-
-#endif /* __ASM_ARCH_24A0_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-irq.h b/arch/arm/mach-s3c24a0/include/mach/regs-irq.h
deleted file mode 100644
index 6086f6f189eb..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/regs-irq.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/regs-irq.h
- *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
- * http://www.simtec.co.uk/products/SWLINUX/
- *
- * 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_24A0_REGS_IRQ_H
-#define ___ASM_ARCH_24A0_REGS_IRQ_H __FILE__
-
-
-#define S3C2410_EINTMASK S3C2410_EINTREG(0x034)
-#define S3C2410_EINTPEND S3C2410_EINTREG(0X038)
-
-#define S3C24XX_EINTMASK S3C24XX_EINTREG(0x034)
-#define S3C24XX_EINTPEND S3C24XX_EINTREG(0X038)
-
-#endif /* __ASM_ARCH_24A0_REGS_IRQ_H */
-
-
-
diff --git a/arch/arm/mach-s3c24a0/include/mach/system.h b/arch/arm/mach-s3c24a0/include/mach/system.h
deleted file mode 100644
index bd1bd1957656..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/system.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/system.h
- *
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24A0 - System function defines and includes
- *
- * 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 <asm/io.h>
-
-#include <mach/map.h>
-
-static void arch_idle(void)
-{
- /* currently no specific idle support. */
-}
-
-void (*s3c24xx_reset_hook)(void);
-
-#include <asm/plat-s3c24xx/system-reset.h>
diff --git a/arch/arm/mach-s3c24a0/include/mach/tick.h b/arch/arm/mach-s3c24a0/include/mach/tick.h
deleted file mode 100644
index 9dea8ba6fb72..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/tick.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/tick.h
- *
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * S3C24A0 - timer tick support
- */
-
-#define SUBSRC_TIMER4 (1 << (IRQ_TIMER4 - IRQ_S3CUART_RX0))
-
-static inline int s3c24xx_ostimer_pending(void)
-{
- return __raw_readl(S3C2410_SUBSRCPND) & SUBSRC_TIMER4;
-}
diff --git a/arch/arm/mach-s3c24a0/include/mach/timex.h b/arch/arm/mach-s3c24a0/include/mach/timex.h
deleted file mode 100644
index 98573424a016..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/timex.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/timex.h
- *
- * Copyright (c) 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - time parameters
- *
- * 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_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h
deleted file mode 100644
index 6480b15277f3..000000000000
--- a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/include/asm-arm/arch-s3c24ao/vmalloc.h
- *
- * Copyright 2008 Simtec Electronics <linux@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.
- *
- * S3C24A0 vmalloc definition
-*/
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END 0xF6000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index e4177e22557b..f057b6ae4f90 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -142,6 +142,7 @@ config MACH_SMDK6410
select S3C_DEV_USB_HOST
select S3C_DEV_USB_HSOTG
select S3C_DEV_WDT
+ select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_PWM
select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -266,3 +267,26 @@ config MACH_SMARTQ7
select MACH_SMARTQ
help
Machine support for the SmartQ 7
+
+config MACH_WLF_CRAGG_6410
+ bool "Wolfson Cragganmore 6410"
+ select CPU_S3C6410
+ select S3C64XX_SETUP_SDHCI
+ select S3C64XX_SETUP_I2C1
+ select S3C64XX_SETUP_IDE
+ select S3C64XX_SETUP_FB_24BPP
+ select S3C64XX_SETUP_KEYPAD
+ select SAMSUNG_DEV_ADC
+ select SAMSUNG_DEV_KEYPAD
+ select S3C_DEV_USB_HOST
+ select S3C_DEV_USB_HSOTG
+ select S3C_DEV_HSMMC
+ select S3C_DEV_HSMMC1
+ select S3C_DEV_HSMMC2
+ select S3C_DEV_I2C1
+ select S3C_DEV_WDT
+ select S3C_DEV_RTC
+ select S3C64XX_DEV_SPI
+ select S3C24XX_GPIO_EXTRA128
+ help
+ Machine support for the Wolfson Cragganmore S3C6410 variant.
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 4657363f0674..61b4034a0c22 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -23,10 +23,6 @@ obj-$(CONFIG_CPU_S3C6410) += s3c6410.o
obj-y += irq.o
obj-y += irq-eint.o
-# CPU frequency scaling
-
-obj-$(CONFIG_CPU_FREQ_S3C64XX) += cpufreq.o
-
# DMA support
obj-$(CONFIG_S3C64XX_DMA) += dma.o
@@ -59,6 +55,7 @@ obj-$(CONFIG_MACH_HMT) += mach-hmt.o
obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o
obj-$(CONFIG_MACH_SMARTQ5) += mach-smartq5.o
obj-$(CONFIG_MACH_SMARTQ7) += mach-smartq7.o
+obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o
# device support
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index fdfc4d5e37a1..8cf39e33579e 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -39,7 +39,6 @@
static struct clk clk_ext_xtal_mux = {
.name = "ext_xtal",
- .id = -1,
};
#define clk_fin_apll clk_ext_xtal_mux
@@ -51,13 +50,11 @@ static struct clk clk_ext_xtal_mux = {
struct clk clk_h2 = {
.name = "hclk2",
- .id = -1,
.rate = 0,
};
struct clk clk_27m = {
.name = "clk_27m",
- .id = -1,
.rate = 27000000,
};
@@ -83,14 +80,12 @@ static int clk_48m_ctrl(struct clk *clk, int enable)
struct clk clk_48m = {
.name = "clk_48m",
- .id = -1,
.rate = 48000000,
.enable = clk_48m_ctrl,
};
struct clk clk_xusbxti = {
.name = "xusbxti",
- .id = -1,
.rate = 48000000,
};
@@ -130,109 +125,101 @@ int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
static struct clk init_clocks_off[] = {
{
.name = "nand",
- .id = -1,
.parent = &clk_h,
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_RTC,
}, {
.name = "adc",
- .id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_TSADC,
}, {
.name = "i2c",
- .id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_IIC,
}, {
.name = "i2c",
- .id = 1,
+ .devname = "s3c2440-i2c.1",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C6410_CLKCON_PCLK_I2C1,
}, {
.name = "iis",
- .id = 0,
+ .devname = "samsung-i2s.0",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_IIS0,
}, {
.name = "iis",
- .id = 1,
+ .devname = "samsung-i2s.1",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_IIS1,
}, {
#ifdef CONFIG_CPU_S3C6410
.name = "iis",
- .id = -1, /* There's only one IISv4 port */
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C6410_CLKCON_PCLK_IIS2,
}, {
#endif
.name = "keypad",
- .id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_KEYPAD,
}, {
.name = "spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_SPI0,
}, {
.name = "spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_SPI1,
}, {
.name = "spi_48m",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
}, {
.name = "spi_48m",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
}, {
.name = "48m",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_MMC0_48,
}, {
.name = "48m",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_MMC1_48,
}, {
.name = "48m",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
}, {
.name = "dma0",
- .id = -1,
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_DMA0,
}, {
.name = "dma1",
- .id = -1,
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_DMA1,
@@ -242,89 +229,81 @@ static struct clk init_clocks_off[] = {
static struct clk init_clocks[] = {
{
.name = "lcd",
- .id = -1,
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_LCD,
}, {
.name = "gpio",
- .id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_GPIO,
}, {
.name = "usb-host",
- .id = -1,
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_UHOST,
}, {
.name = "hsmmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC0,
}, {
.name = "hsmmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC1,
}, {
.name = "hsmmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC2,
}, {
.name = "otg",
- .id = -1,
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_USB,
}, {
.name = "timers",
- .id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_PWM,
}, {
.name = "uart",
- .id = 0,
+ .devname = "s3c6400-uart.0",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_UART0,
}, {
.name = "uart",
- .id = 1,
+ .devname = "s3c6400-uart.1",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_UART1,
}, {
.name = "uart",
- .id = 2,
+ .devname = "s3c6400-uart.2",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_UART2,
}, {
.name = "uart",
- .id = 3,
+ .devname = "s3c6400-uart.3",
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_UART3,
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_p,
.ctrlbit = S3C_CLKCON_PCLK_WDT,
}, {
.name = "ac97",
- .id = -1,
.parent = &clk_p,
.ctrlbit = S3C_CLKCON_PCLK_AC97,
}, {
.name = "cfcon",
- .id = -1,
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_IHOST,
@@ -334,7 +313,6 @@ static struct clk init_clocks[] = {
static struct clk clk_fout_apll = {
.name = "fout_apll",
- .id = -1,
};
static struct clk *clk_src_apll_list[] = {
@@ -350,7 +328,6 @@ static struct clksrc_sources clk_src_apll = {
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
- .id = -1,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 0, .size = 1 },
.sources = &clk_src_apll,
@@ -369,7 +346,6 @@ static struct clksrc_sources clk_src_epll = {
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
- .id = -1,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 2, .size = 1 },
.sources = &clk_src_epll,
@@ -388,7 +364,6 @@ static struct clksrc_sources clk_src_mpll = {
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
- .id = -1,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 1, .size = 1 },
.sources = &clk_src_mpll,
@@ -446,7 +421,6 @@ static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
static struct clk clk_arm = {
.name = "armclk",
- .id = -1,
.parent = &clk_mout_apll.clk,
.ops = &(struct clk_ops) {
.get_rate = s3c64xx_clk_arm_get_rate,
@@ -473,7 +447,6 @@ static struct clk_ops clk_dout_ops = {
static struct clk clk_dout_mpll = {
.name = "dout_mpll",
- .id = -1,
.parent = &clk_mout_mpll.clk,
.ops = &clk_dout_ops,
};
@@ -540,22 +513,18 @@ static struct clksrc_sources clkset_uhost = {
static struct clk clk_iis_cd0 = {
.name = "iis_cdclk0",
- .id = -1,
};
static struct clk clk_iis_cd1 = {
.name = "iis_cdclk1",
- .id = -1,
};
static struct clk clk_iisv4_cd = {
.name = "iis_cdclk_v4",
- .id = -1,
};
static struct clk clk_pcm_cd = {
.name = "pcm_cdclk",
- .id = -1,
};
static struct clk *clkset_audio0_list[] = {
@@ -610,7 +579,7 @@ static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "mmc_bus",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.ctrlbit = S3C_CLKCON_SCLK_MMC0,
.enable = s3c64xx_sclk_ctrl,
},
@@ -620,7 +589,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "mmc_bus",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.ctrlbit = S3C_CLKCON_SCLK_MMC1,
.enable = s3c64xx_sclk_ctrl,
},
@@ -630,7 +599,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "mmc_bus",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.ctrlbit = S3C_CLKCON_SCLK_MMC2,
.enable = s3c64xx_sclk_ctrl,
},
@@ -640,7 +609,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "usb-bus-host",
- .id = -1,
.ctrlbit = S3C_CLKCON_SCLK_UHOST,
.enable = s3c64xx_sclk_ctrl,
},
@@ -650,7 +618,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = -1,
.ctrlbit = S3C_CLKCON_SCLK_UART,
.enable = s3c64xx_sclk_ctrl,
},
@@ -661,7 +628,7 @@ static struct clksrc_clk clksrcs[] = {
/* Where does UCLK0 come from? */
.clk = {
.name = "spi-bus",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.ctrlbit = S3C_CLKCON_SCLK_SPI0,
.enable = s3c64xx_sclk_ctrl,
},
@@ -671,8 +638,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "spi-bus",
- .id = 1,
- .ctrlbit = S3C_CLKCON_SCLK_SPI1,
+ .devname = "s3c64xx-spi.1",
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
@@ -681,7 +647,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "audio-bus",
- .id = 0,
+ .devname = "samsung-i2s.0",
.ctrlbit = S3C_CLKCON_SCLK_AUDIO0,
.enable = s3c64xx_sclk_ctrl,
},
@@ -691,7 +657,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "audio-bus",
- .id = 1,
+ .devname = "samsung-i2s.1",
.ctrlbit = S3C_CLKCON_SCLK_AUDIO1,
.enable = s3c64xx_sclk_ctrl,
},
@@ -701,7 +667,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "audio-bus",
- .id = 2,
+ .devname = "samsung-i2s.2",
.ctrlbit = S3C6410_CLKCON_SCLK_AUDIO2,
.enable = s3c64xx_sclk_ctrl,
},
@@ -711,7 +677,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "irda-bus",
- .id = 0,
.ctrlbit = S3C_CLKCON_SCLK_IRDA,
.enable = s3c64xx_sclk_ctrl,
},
@@ -721,7 +686,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "camera",
- .id = -1,
.ctrlbit = S3C_CLKCON_SCLK_CAM,
.enable = s3c64xx_sclk_ctrl,
},
diff --git a/arch/arm/mach-s3c64xx/dev-onenand1.c b/arch/arm/mach-s3c64xx/dev-onenand1.c
index 92ffd5bac104..999f9e17a1e4 100644
--- a/arch/arm/mach-s3c64xx/dev-onenand1.c
+++ b/arch/arm/mach-s3c64xx/dev-onenand1.c
@@ -19,6 +19,8 @@
#include <mach/irqs.h>
#include <mach/map.h>
+#include <plat/devs.h>
+
static struct resource s3c64xx_onenand1_resources[] = {
[0] = {
.start = S3C64XX_PA_ONENAND1,
@@ -46,10 +48,6 @@ struct platform_device s3c64xx_device_onenand1 = {
void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
{
- struct onenand_platform_data *pd;
-
- pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
- if (!pd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- s3c64xx_device_onenand1.dev.platform_data = pd;
+ s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
+ &s3c64xx_device_onenand1);
}
diff --git a/arch/arm/mach-s3c64xx/include/mach/clkdev.h b/arch/arm/mach-s3c64xx/include/mach/clkdev.h
new file mode 100644
index 000000000000..7dffa83d23ff
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h
index 8e2df26cf14a..c026f67a80de 100644
--- a/arch/arm/mach-s3c64xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h
@@ -198,7 +198,9 @@
* interrupt controllers). */
#define IRQ_BOARD_START (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1)
-#ifdef CONFIG_SMDK6410_WM1190_EV1
+#ifdef CONFIG_MACH_WLF_CRAGG_6410
+#define IRQ_BOARD_NR 128
+#elif defined(CONFIG_SMDK6410_WM1190_EV1)
#define IRQ_BOARD_NR 64
#elif defined(CONFIG_SMDK6410_WM1192_EV1)
#define IRQ_BOARD_NR 64
@@ -215,6 +217,7 @@
/* Compatibility */
#define IRQ_ONENAND IRQ_ONENAND0
+#define IRQ_I2S0 IRQ_S3C6410_IIS
#endif /* __ASM_MACH_S3C64XX_IRQS_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/pm-core.h b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
index 1e9f20f0bb7b..38659bebe4b1 100644
--- a/arch/arm/mach-s3c64xx/include/mach/pm-core.h
+++ b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
@@ -53,7 +53,7 @@ static inline void s3c_pm_arch_show_resume_irqs(void)
* the IRQ wake controls depending on the CPU we are running on */
#define s3c_irqwake_eintallow ((1 << 28) - 1)
-#define s3c_irqwake_intallow (0)
+#define s3c_irqwake_intallow (~0)
static inline void s3c_pm_arch_update_uart(void __iomem *regs,
struct pm_uart_save *save)
@@ -96,3 +96,20 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
save->ucon = new_ucon;
}
}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+ /* ensure sleep mode has been cleared from the system */
+
+ __raw_writel(0, S3C64XX_SLPEN);
+}
+
+static inline void s3c_pm_saved_gpios(void)
+{
+ /* turn on the sleep mode and keep it there, as it seems that during
+ * suspend the xCON registers get re-set and thus you can end up with
+ * problems between going to sleep and resuming.
+ */
+
+ __raw_writel(S3C64XX_SLPEN_USE_xSLP, S3C64XX_SLPEN);
+}
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-fb.h b/arch/arm/mach-s3c64xx/include/mach/regs-fb.h
deleted file mode 100644
index a06ee0af9a4b..000000000000
--- a/arch/arm/mach-s3c64xx/include/mach/regs-fb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Copyright 2009 Samsung Electronics Co.
- *
- * Pawel Osciak <p.osciak@samsung.com>
- * Based on plat-s3c/include/plat/regs-fb.h by Ben Dooks <ben@simtec.co.uk>
- *
- * Framebuffer register definitions for Samsung S3C64xx.
- *
- * 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_MACH_REGS_FB_H
-#define __ASM_ARCH_MACH_REGS_FB_H __FILE__
-
-#include <plat/regs-fb-v4.h>
-
-#endif /* __ASM_ARCH_MACH_REGS_FB_H */
diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c
index 97660c8141ae..75d9a0e49193 100644
--- a/arch/arm/mach-s3c64xx/irq.c
+++ b/arch/arm/mach-s3c64xx/irq.c
@@ -48,14 +48,22 @@ static struct s3c_uart_irq uart_irqs[] = {
},
};
+/* 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))
+#define IRQ_VIC1_RESUME (1 << (IRQ_RTC_ALARM - IRQ_VIC1_BASE) | \
+ 1 << (IRQ_PENDN - IRQ_VIC1_BASE) | \
+ 1 << (IRQ_HSMMC0 - IRQ_VIC1_BASE) | \
+ 1 << (IRQ_HSMMC1 - IRQ_VIC1_BASE) | \
+ 1 << (IRQ_HSMMC2 - IRQ_VIC1_BASE))
void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
{
printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
/* initialise the pair of VICs */
- vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, 0);
- vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, 0);
+ vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
+ vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
/* add the timer sub-irqs */
s3c_init_vic_timer_irq(5, IRQ_TIMER0);
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index a53cf149476e..cb8864327ac4 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -35,7 +35,6 @@
#include <asm/mach/irq.h>
#include <mach/hardware.h>
-#include <mach/regs-fb.h>
#include <mach/map.h>
#include <asm/irq.h>
@@ -44,6 +43,7 @@
#include <plat/regs-serial.h>
#include <plat/iic.h>
#include <plat/fb.h>
+#include <plat/regs-fb-v4.h>
#include <mach/s3c6410.h>
#include <plat/clock.h>
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
new file mode 100644
index 000000000000..9026249233ad
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -0,0 +1,774 @@
+/* linux/arch/arm/mach-s3c64xx/mach-crag6410.c
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ * Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Copyright 2011 Simtec Electronics
+ * Ben Dooks <ben@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/pwm_backlight.h>
+#include <linux/dm9000.h>
+#include <linux/gpio_keys.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/spi/spi.h>
+
+#include <linux/i2c/pca953x.h>
+
+#include <video/platform_lcd.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <mach/s3c6410.h>
+#include <mach/regs-sys.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-modem.h>
+
+#include <mach/regs-gpio-memport.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fb.h>
+#include <plat/sdhci.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s3c64xx-spi.h>
+
+#include <plat/keypad.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/adc.h>
+#include <plat/iic.h>
+#include <plat/pm.h>
+
+#include <sound/wm8915.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#define BANFF_PMIC_IRQ_BASE IRQ_BOARD_START
+#define GLENFARCLAS_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
+
+#define PCA935X_GPIO_BASE GPIO_BOARD_START
+#define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
+#define GLENFARCLAS_PMIC_GPIO_BASE (GPIO_BOARD_START + 16)
+
+/* serial port setup */
+
+#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg crag6410_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [3] = {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+};
+
+static struct platform_pwm_backlight_data crag6410_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 1000,
+ .dft_brightness = 600,
+ .pwm_period_ns = 100000, /* about 1kHz */
+};
+
+static struct platform_device crag6410_backlight_device = {
+ .name = "pwm-backlight",
+ .id = -1,
+ .dev = {
+ .parent = &s3c_device_timer[0].dev,
+ .platform_data = &crag6410_backlight_data,
+ },
+};
+
+static void crag6410_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
+{
+ pr_debug("%s: setting power %d\n", __func__, power);
+
+ if (power) {
+ gpio_set_value(S3C64XX_GPB(0), 1);
+ msleep(1);
+ s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C_GPIO_SFN(2));
+ } else {
+ gpio_direction_output(S3C64XX_GPF(14), 0);
+ gpio_set_value(S3C64XX_GPB(0), 0);
+ }
+}
+
+static struct platform_device crag6410_lcd_powerdev = {
+ .name = "platform-lcd",
+ .id = -1,
+ .dev.parent = &s3c_device_fb.dev,
+ .dev.platform_data = &(struct plat_lcd_data) {
+ .set_power = crag6410_lcd_power_set,
+ },
+};
+
+/* 640x480 URT */
+static struct s3c_fb_pd_win crag6410_fb_win0 = {
+ /* this is to ensure we use win0 */
+ .win_mode = {
+ .left_margin = 150,
+ .right_margin = 80,
+ .upper_margin = 40,
+ .lower_margin = 5,
+ .hsync_len = 40,
+ .vsync_len = 5,
+ .xres = 640,
+ .yres = 480,
+ },
+ .max_bpp = 32,
+ .default_bpp = 16,
+ .virtual_y = 480 * 2,
+ .virtual_x = 640,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
+ .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
+ .win[0] = &crag6410_fb_win0,
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/* 2x6 keypad */
+
+static uint32_t crag6410_keymap[] __initdata = {
+ /* KEY(row, col, keycode) */
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_HOME),
+ KEY(0, 2, KEY_VOLUMEDOWN),
+ KEY(0, 3, KEY_HELP),
+ KEY(0, 4, KEY_MENU),
+ KEY(0, 5, KEY_MEDIA),
+ KEY(1, 0, 232),
+ KEY(1, 1, KEY_DOWN),
+ KEY(1, 2, KEY_LEFT),
+ KEY(1, 3, KEY_UP),
+ KEY(1, 4, KEY_RIGHT),
+ KEY(1, 5, KEY_CAMERA),
+};
+
+static struct matrix_keymap_data crag6410_keymap_data __initdata = {
+ .keymap = crag6410_keymap,
+ .keymap_size = ARRAY_SIZE(crag6410_keymap),
+};
+
+static struct samsung_keypad_platdata crag6410_keypad_data __initdata = {
+ .keymap_data = &crag6410_keymap_data,
+ .rows = 2,
+ .cols = 6,
+};
+
+static struct gpio_keys_button crag6410_gpio_keys[] = {
+ [0] = {
+ .code = KEY_SUSPEND,
+ .gpio = S3C64XX_GPL(10), /* EINT 18 */
+ .type = EV_KEY,
+ .wakeup = 1,
+ .active_low = 1,
+ },
+ [1] = {
+ .code = SW_FRONT_PROXIMITY,
+ .gpio = S3C64XX_GPN(11), /* EINT 11 */
+ .type = EV_SW,
+ },
+};
+
+static struct gpio_keys_platform_data crag6410_gpio_keydata = {
+ .buttons = crag6410_gpio_keys,
+ .nbuttons = ARRAY_SIZE(crag6410_gpio_keys),
+};
+
+static struct platform_device crag6410_gpio_keydev = {
+ .name = "gpio-keys",
+ .id = 0,
+ .dev.platform_data = &crag6410_gpio_keydata,
+};
+
+static struct resource crag6410_dm9k_resource[] = {
+ [0] = {
+ .start = S3C64XX_PA_XM0CSN5,
+ .end = S3C64XX_PA_XM0CSN5 + 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = S3C64XX_PA_XM0CSN5 + (1 << 8),
+ .end = S3C64XX_PA_XM0CSN5 + (1 << 8) + 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = S3C_EINT(17),
+ .end = S3C_EINT(17),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct dm9000_plat_data mini6410_dm9k_pdata = {
+ .flags = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device crag6410_dm9k_device = {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(crag6410_dm9k_resource),
+ .resource = crag6410_dm9k_resource,
+ .dev.platform_data = &mini6410_dm9k_pdata,
+};
+
+static struct resource crag6410_mmgpio_resource[] = {
+ [0] = {
+ .start = S3C64XX_PA_XM0CSN4 + 1,
+ .end = S3C64XX_PA_XM0CSN4 + 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device crag6410_mmgpio = {
+ .name = "basic-mmio-gpio",
+ .id = -1,
+ .resource = crag6410_mmgpio_resource,
+ .num_resources = ARRAY_SIZE(crag6410_mmgpio_resource),
+ .dev.platform_data = &(struct bgpio_pdata) {
+ .base = -1,
+ },
+};
+
+static struct platform_device speyside_device = {
+ .name = "speyside",
+ .id = -1,
+};
+
+static struct platform_device speyside_wm8962_device = {
+ .name = "speyside-wm8962",
+ .id = -1,
+};
+
+static struct regulator_consumer_supply wallvdd_consumers[] = {
+ REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
+ REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+};
+
+static struct regulator_init_data wallvdd_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wallvdd_consumers),
+ .consumer_supplies = wallvdd_consumers,
+};
+
+static struct fixed_voltage_config wallvdd_pdata = {
+ .supply_name = "WALLVDD",
+ .microvolts = 5000000,
+ .init_data = &wallvdd_data,
+ .gpio = -EINVAL,
+};
+
+static struct platform_device wallvdd_device = {
+ .name = "reg-fixed-voltage",
+ .id = -1,
+ .dev = {
+ .platform_data = &wallvdd_pdata,
+ },
+};
+
+static struct platform_device *crag6410_devices[] __initdata = {
+ &s3c_device_hsmmc0,
+ &s3c_device_hsmmc1,
+ &s3c_device_hsmmc2,
+ &s3c_device_i2c0,
+ &s3c_device_i2c1,
+ &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,
+ &samsung_asoc_dma,
+ &samsung_device_keypad,
+ &crag6410_gpio_keydev,
+ &crag6410_dm9k_device,
+ &s3c64xx_device_spi0,
+ &crag6410_mmgpio,
+ &crag6410_lcd_powerdev,
+ &crag6410_backlight_device,
+ &speyside_device,
+ &speyside_wm8962_device,
+ &wallvdd_device,
+};
+
+static struct pca953x_platform_data crag6410_pca_data = {
+ .gpio_base = PCA935X_GPIO_BASE,
+ .irq_base = 0,
+};
+
+static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
+ REGULATOR_SUPPLY("vddarm", NULL),
+};
+
+static struct regulator_init_data vddarm __initdata = {
+ .constraints = {
+ .name = "VDDARM",
+ .min_uV = 1000000,
+ .max_uV = 1300000,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
+ .consumer_supplies = vddarm_consumers,
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddint __initdata = {
+ .constraints = {
+ .name = "VDDINT",
+ .min_uV = 1000000,
+ .max_uV = 1200000,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+};
+
+static struct regulator_init_data vddmem __initdata = {
+ .constraints = {
+ .name = "VDDMEM",
+ .always_on = 1,
+ },
+};
+
+static struct regulator_init_data vddsys __initdata = {
+ .constraints = {
+ .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
+ .always_on = 1,
+ },
+};
+
+static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
+};
+
+static struct regulator_init_data vddmmc __initdata = {
+ .constraints = {
+ .name = "VDDMMC,UH",
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vddmmc_consumers),
+ .consumer_supplies = vddmmc_consumers,
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotgi __initdata = {
+ .constraints = {
+ .name = "VDDOTGi",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotg __initdata = {
+ .constraints = {
+ .name = "VDDOTG",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddhi __initdata = {
+ .constraints = {
+ .name = "VDDHI",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddadc __initdata = {
+ .constraints = {
+ .name = "VDDADC,VDDDAC",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddmem0 __initdata = {
+ .constraints = {
+ .name = "VDDMEM0",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddpll __initdata = {
+ .constraints = {
+ .name = "VDDPLL",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddlcd __initdata = {
+ .constraints = {
+ .name = "VDDLCD",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddalive __initdata = {
+ .constraints = {
+ .name = "VDDALIVE",
+ .always_on = 1,
+ },
+ .supply_regulator = "WALLVDD",
+};
+
+static struct wm831x_backup_pdata banff_backup_pdata __initdata = {
+ .charger_enable = 1,
+ .vlim = 2500, /* mV */
+ .ilim = 200, /* uA */
+};
+
+static struct wm831x_status_pdata banff_red_led __initdata = {
+ .name = "banff:red:",
+ .default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_status_pdata banff_green_led __initdata = {
+ .name = "banff:green:",
+ .default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_touch_pdata touch_pdata __initdata = {
+ .data_irq = S3C_EINT(26),
+ .pd_irq = S3C_EINT(27),
+};
+
+static struct wm831x_pdata crag_pmic_pdata __initdata = {
+ .wm831x_num = 1,
+ .irq_base = BANFF_PMIC_IRQ_BASE,
+ .gpio_base = GPIO_BOARD_START + 8,
+
+ .backup = &banff_backup_pdata,
+
+ .gpio_defaults = {
+ /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
+ [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
+ /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
+ [11] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x7,
+ },
+
+ .dcdc = {
+ &vddarm, /* DCDC1 */
+ &vddint, /* DCDC2 */
+ &vddmem, /* DCDC3 */
+ },
+
+ .ldo = {
+ &vddsys, /* LDO1 */
+ &vddmmc, /* LDO2 */
+ NULL, /* LDO3 */
+ &vddotgi, /* LDO4 */
+ &vddotg, /* LDO5 */
+ &vddhi, /* LDO6 */
+ &vddadc, /* LDO7 */
+ &vddmem0, /* LDO8 */
+ &vddpll, /* LDO9 */
+ &vddlcd, /* LDO10 */
+ &vddalive, /* LDO11 */
+ },
+
+ .status = {
+ &banff_green_led,
+ &banff_red_led,
+ },
+
+ .touch = &touch_pdata,
+};
+
+static struct i2c_board_info i2c_devs0[] __initdata = {
+ { I2C_BOARD_INFO("24c08", 0x50), },
+ { I2C_BOARD_INFO("tca6408", 0x20),
+ .platform_data = &crag6410_pca_data,
+ },
+ { I2C_BOARD_INFO("wm8312", 0x34),
+ .platform_data = &crag_pmic_pdata,
+ .irq = S3C_EINT(23),
+ },
+};
+
+static struct s3c2410_platform_i2c i2c0_pdata = {
+ .frequency = 400000,
+};
+
+static struct regulator_init_data pvdd_1v2 __initdata = {
+ .constraints = {
+ .name = "PVDD_1V2",
+ .always_on = 1,
+ },
+};
+
+static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+ REGULATOR_SUPPLY("PLLVDD", "1-001a"),
+ REGULATOR_SUPPLY("DBVDD", "1-001a"),
+ REGULATOR_SUPPLY("CPVDD", "1-001a"),
+ REGULATOR_SUPPLY("AVDD2", "1-001a"),
+ REGULATOR_SUPPLY("DCVDD", "1-001a"),
+ REGULATOR_SUPPLY("AVDD", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_1v8 __initdata = {
+ .constraints = {
+ .name = "PVDD_1V8",
+ .always_on = 1,
+ },
+
+ .consumer_supplies = pvdd_1v8_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
+};
+
+static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
+ REGULATOR_SUPPLY("MICVDD", "1-001a"),
+ REGULATOR_SUPPLY("AVDD1", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_3v3 __initdata = {
+ .constraints = {
+ .name = "PVDD_3V3",
+ .always_on = 1,
+ },
+
+ .consumer_supplies = pvdd_3v3_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
+};
+
+static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
+ .wm831x_num = 2,
+ .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
+ .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
+
+ .gpio_defaults = {
+ /* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
+ [0] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+ [1] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+ [2] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+ },
+
+ .dcdc = {
+ &pvdd_1v2, /* DCDC1 */
+ &pvdd_1v8, /* DCDC2 */
+ &pvdd_3v3, /* DCDC3 */
+ },
+
+ .disable_touch = true,
+};
+
+static struct wm8915_retune_mobile_config wm8915_retune[] = {
+ {
+ .name = "Sub LPF",
+ .rate = 48000,
+ .regs = {
+ 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+ 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+ 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+ },
+ },
+ {
+ .name = "Sub HPF",
+ .rate = 48000,
+ .regs = {
+ 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+ 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+ 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+ },
+ },
+};
+
+static struct wm8915_pdata wm8915_pdata __initdata = {
+ .ldo_ena = S3C64XX_GPN(7),
+ .gpio_base = CODEC_GPIO_BASE,
+ .micdet_def = 1,
+ .inl_mode = WM8915_DIFFERRENTIAL_1,
+ .inr_mode = WM8915_DIFFERRENTIAL_1,
+
+ .irq_flags = IRQF_TRIGGER_RISING,
+
+ .gpio_default = {
+ 0x8001, /* GPIO1 == ADCLRCLK1 */
+ 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
+ 0x0141, /* GPIO3 == HP_SEL */
+ 0x0002, /* GPIO4 == IRQ */
+ 0x020e, /* GPIO5 == CLKOUT */
+ },
+
+ .retune_mobile_cfgs = wm8915_retune,
+ .num_retune_mobile_cfgs = ARRAY_SIZE(wm8915_retune),
+};
+
+static struct wm8962_pdata wm8962_pdata __initdata = {
+ .gpio_init = {
+ 0,
+ WM8962_GPIO_FN_OPCLK,
+ WM8962_GPIO_FN_DMICCLK,
+ 0,
+ 0x8000 | WM8962_GPIO_FN_DMICDAT,
+ WM8962_GPIO_FN_IRQ, /* Open drain mode */
+ },
+ .irq_active_low = true,
+};
+
+static struct wm9081_pdata wm9081_pdata __initdata = {
+ .irq_high = false,
+ .irq_cmos = false,
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+ { I2C_BOARD_INFO("wm8311", 0x34),
+ .irq = S3C_EINT(0),
+ .platform_data = &glenfarclas_pmic_pdata },
+
+ { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
+ { I2C_BOARD_INFO("wm8915", 0x1a),
+ .platform_data = &wm8915_pdata,
+ .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+ },
+ { I2C_BOARD_INFO("wm9081", 0x6c),
+ .platform_data = &wm9081_pdata, },
+ { I2C_BOARD_INFO("wm8962", 0x1a),
+ .platform_data = &wm8962_pdata,
+ .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+ },
+};
+
+static void __init crag6410_map_io(void)
+{
+ s3c64xx_init_io(NULL, 0);
+ s3c24xx_init_clocks(12000000);
+ s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
+
+ /* LCD type and Bypass set by bootloader */
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
+ .max_width = 4,
+ .cd_type = S3C_SDHCI_CD_PERMANENT,
+};
+
+static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata = {
+ .max_width = 4,
+ .cd_type = S3C_SDHCI_CD_GPIO,
+ .ext_cd_gpio = S3C64XX_GPF(11),
+};
+
+static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
+{
+ /* Set all the necessary GPG pins to special-function 2 */
+ s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));
+
+ /* force card-detected for prototype 0 */
+ s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
+ .max_width = 4,
+ .cd_type = S3C_SDHCI_CD_INTERNAL,
+ .cfg_gpio = crag6410_cfg_sdhci0,
+};
+
+static void __init crag6410_machine_init(void)
+{
+ /* Open drain IRQs need pullups */
+ s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP);
+
+ gpio_request(S3C64XX_GPB(0), "LCD power");
+ gpio_direction_output(S3C64XX_GPB(0), 0);
+
+ gpio_request(S3C64XX_GPF(14), "LCD PWM");
+ gpio_direction_output(S3C64XX_GPF(14), 0); /* turn off */
+
+ gpio_request(S3C64XX_GPB(1), "SD power");
+ gpio_direction_output(S3C64XX_GPB(1), 0);
+
+ gpio_request(S3C64XX_GPF(10), "nRESETSEL");
+ gpio_direction_output(S3C64XX_GPF(10), 1);
+
+ s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
+ s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata);
+ s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);
+
+ s3c_i2c0_set_platdata(&i2c0_pdata);
+ s3c_i2c1_set_platdata(NULL);
+ s3c_fb_set_platdata(&crag6410_lcd_pdata);
+
+ i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
+ i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+ samsung_keypad_set_platdata(&crag6410_keypad_data);
+
+ platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
+
+ regulator_has_full_constraints();
+
+ s3c_pm_init();
+}
+
+MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
+ /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
+ .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .init_irq = s3c6410_init_irq,
+ .map_io = crag6410_map_io,
+ .init_machine = crag6410_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index b2639582caca..b3d93cc8dde0 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -27,7 +27,6 @@
#include <asm/mach/irq.h>
#include <mach/hardware.h>
-#include <mach/regs-fb.h>
#include <mach/map.h>
#include <asm/irq.h>
@@ -42,6 +41,7 @@
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
+#include <plat/regs-fb-v4.h>
#define UCON S3C2410_UCON_DEFAULT
#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 89f35e02e883..527f49bd1b57 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -29,7 +29,6 @@
#include <asm/mach/map.h>
#include <mach/map.h>
-#include <mach/regs-fb.h>
#include <mach/regs-gpio.h>
#include <mach/regs-modem.h>
#include <mach/regs-srom.h>
@@ -42,6 +41,7 @@
#include <plat/nand.h>
#include <plat/regs-serial.h>
#include <plat/ts.h>
+#include <plat/regs-fb-v4.h>
#include <video/platform_lcd.h>
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index c4986498cd12..01c6857c5b63 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -30,7 +30,6 @@
#include <asm/mach/irq.h>
#include <mach/hardware.h>
-#include <mach/regs-fb.h>
#include <mach/map.h>
#include <asm/irq.h>
@@ -44,6 +43,7 @@
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
+#include <plat/regs-fb-v4.h>
#define UCON S3C2410_UCON_DEFAULT
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 4957ab0a0d4a..95b04b1729e3 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -30,7 +30,6 @@
#include <asm/mach/map.h>
#include <mach/map.h>
-#include <mach/regs-fb.h>
#include <mach/regs-gpio.h>
#include <mach/regs-modem.h>
#include <mach/regs-srom.h>
@@ -43,6 +42,7 @@
#include <plat/nand.h>
#include <plat/regs-serial.h>
#include <plat/ts.h>
+#include <plat/regs-fb-v4.h>
#include <video/platform_lcd.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index 3a3e5acde523..342e8dfddf8b 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -21,7 +21,6 @@
#include <asm/mach/arch.h>
#include <mach/map.h>
-#include <mach/regs-fb.h>
#include <mach/regs-gpio.h>
#include <mach/s3c6410.h>
@@ -29,6 +28,7 @@
#include <plat/devs.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
#include "mach-smartq.h"
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index e65375877d53..57963977da8e 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -21,7 +21,6 @@
#include <asm/mach/arch.h>
#include <mach/map.h>
-#include <mach/regs-fb.h>
#include <mach/regs-gpio.h>
#include <mach/s3c6410.h>
@@ -29,6 +28,7 @@
#include <plat/devs.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
#include "mach-smartq.h"
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 2c0353a80906..ecbea92bf83b 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -48,7 +48,6 @@
#include <asm/mach/irq.h>
#include <mach/hardware.h>
-#include <mach/regs-fb.h>
#include <mach/map.h>
#include <asm/irq.h>
@@ -71,6 +70,8 @@
#include <plat/adc.h>
#include <plat/ts.h>
#include <plat/keypad.h>
+#include <plat/backlight.h>
+#include <plat/regs-fb-v4.h>
#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
@@ -209,17 +210,9 @@ static struct platform_device smdk6410_smsc911x = {
};
#ifdef CONFIG_REGULATOR
-static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] = {
- {
- /* WM8580 */
- .supply = "PVDD",
- .dev_name = "0-001b",
- },
- {
- /* WM8580 */
- .supply = "AVDD",
- .dev_name = "0-001b",
- },
+static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] __initdata = {
+ REGULATOR_SUPPLY("PVDD", "0-001b"),
+ REGULATOR_SUPPLY("AVDD", "0-001b"),
};
static struct regulator_init_data smdk6410_b_pwr_5v_data = {
@@ -337,16 +330,12 @@ static struct platform_device *smdk6410_devices[] __initdata = {
&s3c_device_rtc,
&s3c_device_ts,
&s3c_device_wdt,
- &s3c_device_timer[1],
- &smdk6410_backlight_device,
};
#ifdef CONFIG_REGULATOR
/* ARM core */
static struct regulator_consumer_supply smdk6410_vddarm_consumers[] = {
- {
- .supply = "vddarm",
- }
+ REGULATOR_SUPPLY("vddarm", NULL),
};
/* VDDARM, BUCK1 on J5 */
@@ -484,11 +473,7 @@ static struct regulator_init_data wm8350_dcdc3_data = {
/* USB, EXT, PCM, ADC/DAC, USB, MMC */
static struct regulator_consumer_supply wm8350_dcdc4_consumers[] = {
- {
- /* WM8580 */
- .supply = "DVDD",
- .dev_name = "0-001b",
- },
+ REGULATOR_SUPPLY("DVDD", "0-001b"),
};
static struct regulator_init_data wm8350_dcdc4_data = {
@@ -599,7 +584,7 @@ static struct regulator_init_data wm1192_dcdc3 = {
};
static struct regulator_consumer_supply wm1192_ldo1_consumers[] = {
- { .supply = "DVDD", .dev_name = "0-001b", }, /* WM8580 */
+ REGULATOR_SUPPLY("DVDD", "0-001b"), /* WM8580 */
};
static struct regulator_init_data wm1192_ldo1 = {
@@ -679,6 +664,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
.oversampling_shift = 2,
};
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
+ .no = S3C64XX_GPF(15),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk6410_bl_data = {
+ .pwm_id = 1,
+};
+
static void __init smdk6410_map_io(void)
{
u32 tmp;
@@ -740,6 +735,8 @@ static void __init smdk6410_machine_init(void)
s3c_ide_set_platdata(&smdk6410_ide_pdata);
+ samsung_bl_set(&smdk6410_bl_gpio_info, &smdk6410_bl_data);
+
platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
}
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
index bc1c470b7de6..8bad64370689 100644
--- a/arch/arm/mach-s3c64xx/pm.c
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -112,7 +112,7 @@ void s3c_pm_save_core(void)
* this.
*/
-static void s3c64xx_cpu_suspend(void)
+static int s3c64xx_cpu_suspend(unsigned long arg)
{
unsigned long tmp;
diff --git a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
index 8f3091182f9c..83d2afb79e9f 100644
--- a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
+++ b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
@@ -17,7 +17,6 @@
#include <linux/fb.h>
#include <linux/gpio.h>
-#include <mach/regs-fb.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S
index 1f87732b2320..34313f9c8792 100644
--- a/arch/arm/mach-s3c64xx/sleep.S
+++ b/arch/arm/mach-s3c64xx/sleep.S
@@ -25,29 +25,6 @@
.text
- /* s3c_cpu_save
- *
- * Save enough processor state to allow the restart of the pm.c
- * code after resume.
- *
- * entry:
- * r1 = v:p offset
- */
-
-ENTRY(s3c_cpu_save)
- stmfd sp!, { r4 - r12, lr }
- ldr r3, =resume_with_mmu
- bl cpu_suspend
-
- @@ call final suspend code
- ldr r0, =pm_cpu_sleep
- ldr pc, [r0]
-
- @@ return to the caller, after the MMU is turned on.
- @@ restore the last bits of the stack and return.
-resume_with_mmu:
- ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save
-
/* Sleep magic, the word before the resume entry point so that the
* bootloader can check for a resumeable image. */
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 017af4c4293c..65c7518dad7f 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -36,6 +36,7 @@ config MACH_SMDK6440
select S3C_DEV_WDT
select S3C64XX_DEV_SPI
select SAMSUNG_DEV_ADC
+ select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM
select SAMSUNG_DEV_TS
select S5P64X0_SETUP_I2C1
@@ -50,6 +51,7 @@ config MACH_SMDK6450
select S3C_DEV_WDT
select S3C64XX_DEV_SPI
select SAMSUNG_DEV_ADC
+ select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM
select SAMSUNG_DEV_TS
select S5P64X0_SETUP_I2C1
diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile
index ae6bf6feba89..5f6afdf067ed 100644
--- a/arch/arm/mach-s5p64x0/Makefile
+++ b/arch/arm/mach-s5p64x0/Makefile
@@ -13,7 +13,7 @@ obj- :=
# Core support for S5P64X0 system
obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o clock.o dma.o gpiolib.o
-obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o
+obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o irq-eint.o
obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o
obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index 9f12c2ebf416..0e9cd3092dd2 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -95,7 +95,6 @@ static struct clk_ops s5p6440_epll_ops = {
static struct clksrc_clk clk_hclk = {
.clk = {
.name = "clk_hclk",
- .id = -1,
.parent = &clk_armclk.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
@@ -104,7 +103,6 @@ static struct clksrc_clk clk_hclk = {
static struct clksrc_clk clk_pclk = {
.clk = {
.name = "clk_pclk",
- .id = -1,
.parent = &clk_hclk.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
@@ -112,7 +110,6 @@ static struct clksrc_clk clk_pclk = {
static struct clksrc_clk clk_hclk_low = {
.clk = {
.name = "clk_hclk_low",
- .id = -1,
},
.sources = &clkset_hclk_low,
.reg_src = { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 },
@@ -122,7 +119,6 @@ static struct clksrc_clk clk_hclk_low = {
static struct clksrc_clk clk_pclk_low = {
.clk = {
.name = "clk_pclk_low",
- .id = -1,
.parent = &clk_hclk_low.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
@@ -136,187 +132,167 @@ static struct clksrc_clk clk_pclk_low = {
static struct clk init_clocks_off[] = {
{
.name = "nand",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_mem_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "post",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 5)
}, {
.name = "2d",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "pdma",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "hsmmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 17),
}, {
.name = "hsmmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 18),
}, {
.name = "hsmmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 19),
}, {
.name = "otg",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 20)
}, {
.name = "irom",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 25),
}, {
.name = "lcd",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk1_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "hclk_fimgvg",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_hclk1_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "tsi",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "timers",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "pcm",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "adc",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "i2c",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 17),
}, {
.name = "spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 21),
}, {
.name = "spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 22),
}, {
.name = "gps",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 25),
}, {
.name = "iis",
- .id = 0,
+ .devname = "samsung-i2s.0",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 26),
}, {
.name = "dsim",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 28),
}, {
.name = "etm",
- .id = -1,
.parent = &clk_pclk.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 29),
}, {
.name = "dmc0",
- .id = -1,
.parent = &clk_pclk.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 30),
}, {
.name = "pclk_fimgvg",
- .id = -1,
.parent = &clk_pclk.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 31),
}, {
.name = "sclk_spi_48",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_48m,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 22),
}, {
.name = "sclk_spi_48",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_48m,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 23),
}, {
.name = "mmc_48m",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_48m,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 27),
}, {
.name = "mmc_48m",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_48m,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 28),
}, {
.name = "mmc_48m",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_48m,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 29),
@@ -329,43 +305,40 @@ static struct clk init_clocks_off[] = {
static struct clk init_clocks[] = {
{
.name = "intc",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "mem",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 21),
}, {
.name = "uart",
- .id = 0,
+ .devname = "s3c6400-uart.0",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "uart",
- .id = 1,
+ .devname = "s3c6400-uart.1",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "uart",
- .id = 2,
+ .devname = "s3c6400-uart.2",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "uart",
- .id = 3,
+ .devname = "s3c6400-uart.3",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "gpio",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 18),
@@ -374,12 +347,10 @@ static struct clk init_clocks[] = {
static struct clk clk_iis_cd_v40 = {
.name = "iis_cdclk_v40",
- .id = -1,
};
static struct clk clk_pcm_cd = {
.name = "pcm_cdclk",
- .id = -1,
};
static struct clk *clkset_group1_list[] = {
@@ -420,7 +391,7 @@ static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "sclk_mmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.ctrlbit = (1 << 24),
.enable = s5p64x0_sclk_ctrl,
},
@@ -430,7 +401,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.ctrlbit = (1 << 25),
.enable = s5p64x0_sclk_ctrl,
},
@@ -440,7 +411,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.ctrlbit = (1 << 26),
.enable = s5p64x0_sclk_ctrl,
},
@@ -450,7 +421,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = -1,
.ctrlbit = (1 << 5),
.enable = s5p64x0_sclk_ctrl,
},
@@ -460,7 +430,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 20),
.enable = s5p64x0_sclk_ctrl,
},
@@ -470,7 +440,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 21),
.enable = s5p64x0_sclk_ctrl,
},
@@ -480,7 +450,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_post",
- .id = -1,
.ctrlbit = (1 << 10),
.enable = s5p64x0_sclk_ctrl,
},
@@ -490,7 +459,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_dispcon",
- .id = -1,
.ctrlbit = (1 << 1),
.enable = s5p64x0_sclk1_ctrl,
},
@@ -500,7 +468,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimgvg",
- .id = -1,
.ctrlbit = (1 << 2),
.enable = s5p64x0_sclk1_ctrl,
},
@@ -510,7 +477,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_audio2",
- .id = -1,
.ctrlbit = (1 << 11),
.enable = s5p64x0_sclk_ctrl,
},
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index 4eec457ddccc..d9dc16cde109 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -36,7 +36,6 @@
static struct clksrc_clk clk_mout_dpll = {
.clk = {
.name = "mout_dpll",
- .id = -1,
},
.sources = &clk_src_dpll,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
@@ -96,7 +95,6 @@ static struct clk_ops s5p6450_epll_ops = {
static struct clksrc_clk clk_dout_epll = {
.clk = {
.name = "dout_epll",
- .id = -1,
.parent = &clk_mout_epll.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
@@ -105,7 +103,6 @@ static struct clksrc_clk clk_dout_epll = {
static struct clksrc_clk clk_mout_hclk_sel = {
.clk = {
.name = "mout_hclk_sel",
- .id = -1,
},
.sources = &clkset_hclk_low,
.reg_src = { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
@@ -124,7 +121,6 @@ static struct clksrc_sources clkset_hclk = {
static struct clksrc_clk clk_hclk = {
.clk = {
.name = "clk_hclk",
- .id = -1,
},
.sources = &clkset_hclk,
.reg_src = { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
@@ -134,7 +130,6 @@ static struct clksrc_clk clk_hclk = {
static struct clksrc_clk clk_pclk = {
.clk = {
.name = "clk_pclk",
- .id = -1,
.parent = &clk_hclk.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
@@ -142,7 +137,6 @@ static struct clksrc_clk clk_pclk = {
static struct clksrc_clk clk_dout_pwm_ratio0 = {
.clk = {
.name = "clk_dout_pwm_ratio0",
- .id = -1,
.parent = &clk_mout_hclk_sel.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
@@ -151,7 +145,6 @@ static struct clksrc_clk clk_dout_pwm_ratio0 = {
static struct clksrc_clk clk_pclk_to_wdt_pwm = {
.clk = {
.name = "clk_pclk_to_wdt_pwm",
- .id = -1,
.parent = &clk_dout_pwm_ratio0.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
@@ -160,7 +153,6 @@ static struct clksrc_clk clk_pclk_to_wdt_pwm = {
static struct clksrc_clk clk_hclk_low = {
.clk = {
.name = "clk_hclk_low",
- .id = -1,
},
.sources = &clkset_hclk_low,
.reg_src = { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
@@ -170,7 +162,6 @@ static struct clksrc_clk clk_hclk_low = {
static struct clksrc_clk clk_pclk_low = {
.clk = {
.name = "clk_pclk_low",
- .id = -1,
.parent = &clk_hclk_low.clk,
},
.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
@@ -184,109 +175,101 @@ static struct clksrc_clk clk_pclk_low = {
static struct clk init_clocks_off[] = {
{
.name = "usbhost",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "pdma",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "hsmmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 17),
}, {
.name = "hsmmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 18),
}, {
.name = "hsmmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 19),
}, {
.name = "usbotg",
- .id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 20),
}, {
.name = "lcd",
- .id = -1,
.parent = &clk_h,
.enable = s5p64x0_hclk1_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "adc",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "i2c",
- .id = 0,
+ .devname = "s3c2440-i2c.0",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 17),
}, {
.name = "spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 21),
}, {
.name = "spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 22),
}, {
.name = "iis",
- .id = 0,
+ .devname = "samsung-i2s.0",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 26),
}, {
.name = "iis",
- .id = 1,
+ .devname = "samsung-i2s.1",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 15),
}, {
.name = "iis",
- .id = 2,
+ .devname = "samsung-i2s.2",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 16),
}, {
.name = "i2c",
- .id = 1,
+ .devname = "s3c2440-i2c.1",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 27),
}, {
.name = "dmc0",
- .id = -1,
.parent = &clk_pclk.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 30),
@@ -299,49 +282,45 @@ static struct clk init_clocks_off[] = {
static struct clk init_clocks[] = {
{
.name = "intc",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "mem",
- .id = -1,
.parent = &clk_hclk.clk,
.enable = s5p64x0_hclk0_ctrl,
.ctrlbit = (1 << 21),
}, {
.name = "uart",
- .id = 0,
+ .devname = "s3c6400-uart.0",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "uart",
- .id = 1,
+ .devname = "s3c6400-uart.1",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "uart",
- .id = 2,
+ .devname = "s3c6400-uart.2",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "uart",
- .id = 3,
+ .devname = "s3c6400-uart.3",
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "timers",
- .id = -1,
.parent = &clk_pclk_to_wdt_pwm.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "gpio",
- .id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 18),
@@ -421,7 +400,6 @@ static struct clksrc_sources clkset_sclk_audio0 = {
static struct clksrc_clk clk_sclk_audio0 = {
.clk = {
.name = "audio-bus",
- .id = -1,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 8),
.parent = &clk_dout_epll.clk,
@@ -435,7 +413,7 @@ static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "sclk_mmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.ctrlbit = (1 << 24),
.enable = s5p64x0_sclk_ctrl,
},
@@ -445,7 +423,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.ctrlbit = (1 << 25),
.enable = s5p64x0_sclk_ctrl,
},
@@ -455,7 +433,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.ctrlbit = (1 << 26),
.enable = s5p64x0_sclk_ctrl,
},
@@ -465,7 +443,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = -1,
.ctrlbit = (1 << 5),
.enable = s5p64x0_sclk_ctrl,
},
@@ -475,7 +452,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 20),
.enable = s5p64x0_sclk_ctrl,
},
@@ -485,7 +462,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 21),
.enable = s5p64x0_sclk_ctrl,
},
@@ -495,7 +472,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = -1,
.ctrlbit = (1 << 10),
.enable = s5p64x0_sclk_ctrl,
},
@@ -505,7 +481,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "aclk_mali",
- .id = -1,
.ctrlbit = (1 << 2),
.enable = s5p64x0_sclk1_ctrl,
},
@@ -515,7 +490,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_2d",
- .id = -1,
.ctrlbit = (1 << 12),
.enable = s5p64x0_sclk_ctrl,
},
@@ -525,7 +499,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_usi",
- .id = -1,
.ctrlbit = (1 << 7),
.enable = s5p64x0_sclk_ctrl,
},
@@ -535,7 +508,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_camif",
- .id = -1,
.ctrlbit = (1 << 6),
.enable = s5p64x0_sclk_ctrl,
},
@@ -545,7 +517,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_dispcon",
- .id = -1,
.ctrlbit = (1 << 1),
.enable = s5p64x0_sclk1_ctrl,
},
@@ -555,7 +526,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_hsmmc44",
- .id = -1,
.ctrlbit = (1 << 30),
.enable = s5p64x0_sclk_ctrl,
},
diff --git a/arch/arm/mach-s5p64x0/include/mach/clkdev.h b/arch/arm/mach-s5p64x0/include/mach/clkdev.h
new file mode 100644
index 000000000000..7dffa83d23ff
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 513abffc7604..5837a36ece8d 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -85,6 +85,8 @@
#define IRQ_S3CUART_RX4 IRQ_S5P_UART_RX4
#define IRQ_S3CUART_RX5 IRQ_S5P_UART_RX5
+#define IRQ_I2S0 IRQ_I2SV40
+
/* S5P6450 EINT feature will be added */
/*
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
index 0953ef6b1c77..6ce254729f3b 100644
--- a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
@@ -34,4 +34,14 @@
#define S5P6450_GPQ_BASE (S5P_VA_GPIO + 0x0180)
#define S5P6450_GPS_BASE (S5P_VA_GPIO + 0x0300)
+/* External interrupt control registers for group0 */
+
+#define EINT0CON0_OFFSET (0x900)
+#define EINT0MASK_OFFSET (0x920)
+#define EINT0PEND_OFFSET (0x924)
+
+#define S5P64X0_EINT0CON0 (S5P_VA_GPIO + EINT0CON0_OFFSET)
+#define S5P64X0_EINT0MASK (S5P_VA_GPIO + EINT0MASK_OFFSET)
+#define S5P64X0_EINT0PEND (S5P_VA_GPIO + EINT0PEND_OFFSET)
+
#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c
new file mode 100644
index 000000000000..69ed4545112b
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/irq-eint.c
@@ -0,0 +1,152 @@
+/* arch/arm/mach-s5p64x0/irq-eint.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com/
+ *
+ * Based on linux/arch/arm/mach-s3c64xx/irq-eint.c
+ *
+ * S5P64X0 - Interrupt handling for External Interrupts.
+ *
+ * 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/gpio.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <plat/regs-irqtype.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+
+#define eint_offset(irq) ((irq) - IRQ_EINT(0))
+
+static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
+{
+ int offs = eint_offset(data->irq);
+ int shift;
+ u32 ctrl, mask;
+ u32 newvalue = 0;
+
+ if (offs > 15)
+ return -EINVAL;
+
+ switch (type) {
+ case IRQ_TYPE_NONE:
+ printk(KERN_WARNING "No edge setting!\n");
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ newvalue = S3C2410_EXTINT_RISEEDGE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ newvalue = S3C2410_EXTINT_FALLEDGE;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ newvalue = S3C2410_EXTINT_BOTHEDGE;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ newvalue = S3C2410_EXTINT_LOWLEV;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ newvalue = S3C2410_EXTINT_HILEV;
+ break;
+ default:
+ printk(KERN_ERR "No such irq type %d", type);
+ return -EINVAL;
+ }
+
+ shift = (offs / 2) * 4;
+ mask = 0x7 << shift;
+
+ ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask;
+ ctrl |= newvalue << shift;
+ __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))
+ s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
+ else
+ s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
+
+ return 0;
+}
+
+/*
+ * s5p64x0_irq_demux_eint
+ *
+ * This function demuxes the IRQ from the group0 external interrupts,
+ * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into
+ * the specific handlers s5p64x0_irq_demux_eintX_Y.
+ */
+static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end)
+{
+ u32 status = __raw_readl(S5P64X0_EINT0PEND);
+ u32 mask = __raw_readl(S5P64X0_EINT0MASK);
+ unsigned int irq;
+
+ status &= ~mask;
+ status >>= start;
+ status &= (1 << (end - start + 1)) - 1;
+
+ for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
+ if (status & 1)
+ generic_handle_irq(irq);
+ status >>= 1;
+ }
+}
+
+static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+ s5p64x0_irq_demux_eint(0, 3);
+}
+
+static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+{
+ s5p64x0_irq_demux_eint(4, 11);
+}
+
+static void s5p64x0_irq_demux_eint12_15(unsigned int irq,
+ struct irq_desc *desc)
+{
+ s5p64x0_irq_demux_eint(12, 15);
+}
+
+static int s5p64x0_alloc_gc(void)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE,
+ S5P_VA_GPIO, handle_level_irq);
+ if (!gc) {
+ printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0"
+ "external interrupts failed\n", __func__);
+ return -EINVAL;
+ }
+
+ ct = gc->chip_types;
+ ct->chip.irq_ack = irq_gc_ack;
+ ct->chip.irq_mask = irq_gc_mask_set_bit;
+ ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+ ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
+ ct->regs.ack = EINT0PEND_OFFSET;
+ ct->regs.mask = EINT0MASK_OFFSET;
+ irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+ return 0;
+}
+
+static int __init s5p64x0_init_irq_eint(void)
+{
+ int ret = s5p64x0_alloc_gc();
+ irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3);
+ irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11);
+ irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15);
+
+ return ret;
+}
+arch_initcall(s5p64x0_init_irq_eint);
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 2d559f10fd47..346f8dfa6f35 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -46,6 +46,7 @@
#include <plat/adc.h>
#include <plat/ts.h>
#include <plat/s5p-time.h>
+#include <plat/backlight.h>
#define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
S3C2410_UCON_RXILEVEL | \
@@ -91,45 +92,6 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
},
};
-static int smdk6440_backlight_init(struct device *dev)
-{
- int ret;
-
- ret = gpio_request(S5P6440_GPF(15), "Backlight");
- if (ret) {
- printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
- return ret;
- }
-
- /* Configure GPIO pin with S5P6440_GPF15_PWM_TOUT1 */
- s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_SFN(2));
-
- return 0;
-}
-
-static void smdk6440_backlight_exit(struct device *dev)
-{
- s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_OUTPUT);
- gpio_free(S5P6440_GPF(15));
-}
-
-static struct platform_pwm_backlight_data smdk6440_backlight_data = {
- .pwm_id = 1,
- .max_brightness = 255,
- .dft_brightness = 255,
- .pwm_period_ns = 78770,
- .init = smdk6440_backlight_init,
- .exit = smdk6440_backlight_exit,
-};
-
-static struct platform_device smdk6440_backlight_device = {
- .name = "pwm-backlight",
- .dev = {
- .parent = &s3c_device_timer[1].dev,
- .platform_data = &smdk6440_backlight_data,
- },
-};
-
static struct platform_device *smdk6440_devices[] __initdata = {
&s3c_device_adc,
&s3c_device_rtc,
@@ -139,8 +101,6 @@ static struct platform_device *smdk6440_devices[] __initdata = {
&s3c_device_wdt,
&samsung_asoc_dma,
&s5p6440_device_iis,
- &s3c_device_timer[1],
- &smdk6440_backlight_device,
};
static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -175,6 +135,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
.oversampling_shift = 2,
};
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
+ .no = S5P6440_GPF(15),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk6440_bl_data = {
+ .pwm_id = 1,
+};
+
static void __init smdk6440_map_io(void)
{
s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
@@ -194,6 +164,8 @@ static void __init smdk6440_machine_init(void)
i2c_register_board_info(1, smdk6440_i2c_devs1,
ARRAY_SIZE(smdk6440_i2c_devs1));
+ samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
+
platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
}
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index d19c4690ee97..33f2adf8f3fe 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -46,6 +46,7 @@
#include <plat/adc.h>
#include <plat/ts.h>
#include <plat/s5p-time.h>
+#include <plat/backlight.h>
#define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
S3C2410_UCON_RXILEVEL | \
@@ -109,45 +110,6 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
#endif
};
-static int smdk6450_backlight_init(struct device *dev)
-{
- int ret;
-
- ret = gpio_request(S5P6450_GPF(15), "Backlight");
- if (ret) {
- printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
- return ret;
- }
-
- /* Configure GPIO pin with S5P6450_GPF15_PWM_TOUT1 */
- s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_SFN(2));
-
- return 0;
-}
-
-static void smdk6450_backlight_exit(struct device *dev)
-{
- s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_OUTPUT);
- gpio_free(S5P6450_GPF(15));
-}
-
-static struct platform_pwm_backlight_data smdk6450_backlight_data = {
- .pwm_id = 1,
- .max_brightness = 255,
- .dft_brightness = 255,
- .pwm_period_ns = 78770,
- .init = smdk6450_backlight_init,
- .exit = smdk6450_backlight_exit,
-};
-
-static struct platform_device smdk6450_backlight_device = {
- .name = "pwm-backlight",
- .dev = {
- .parent = &s3c_device_timer[1].dev,
- .platform_data = &smdk6450_backlight_data,
- },
-};
-
static struct platform_device *smdk6450_devices[] __initdata = {
&s3c_device_adc,
&s3c_device_rtc,
@@ -157,8 +119,6 @@ static struct platform_device *smdk6450_devices[] __initdata = {
&s3c_device_wdt,
&samsung_asoc_dma,
&s5p6450_device_iis0,
- &s3c_device_timer[1],
- &smdk6450_backlight_device,
/* s5p6450_device_spi0 will be added */
};
@@ -194,6 +154,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
.oversampling_shift = 2,
};
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
+ .no = S5P6450_GPF(15),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk6450_bl_data = {
+ .pwm_id = 1,
+};
+
static void __init smdk6450_map_io(void)
{
s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
@@ -213,6 +183,8 @@ static void __init smdk6450_machine_init(void)
i2c_register_board_info(1, smdk6450_i2c_devs1,
ARRAY_SIZE(smdk6450_i2c_devs1));
+ samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
+
platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
}
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 608722ff4f28..e8a33c4b054c 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -56,6 +56,7 @@ config MACH_SMDKC100
select S3C_DEV_RTC
select S3C_DEV_WDT
select SAMSUNG_DEV_ADC
+ select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_IDE
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_PWM
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 0305e9b8282d..ff5cbb30de5b 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -31,7 +31,6 @@
static struct clk s5p_clk_otgphy = {
.name = "otg_phy",
- .id = -1,
};
static struct clk *clk_src_mout_href_list[] = {
@@ -47,7 +46,6 @@ static struct clksrc_sources clk_src_mout_href = {
static struct clksrc_clk clk_mout_href = {
.clk = {
.name = "mout_href",
- .id = -1,
},
.sources = &clk_src_mout_href,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
@@ -66,7 +64,6 @@ static struct clksrc_sources clk_src_mout_48m = {
static struct clksrc_clk clk_mout_48m = {
.clk = {
.name = "mout_48m",
- .id = -1,
},
.sources = &clk_src_mout_48m,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 1 },
@@ -75,7 +72,6 @@ static struct clksrc_clk clk_mout_48m = {
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
- .id = -1,
},
.sources = &clk_src_mpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
@@ -85,7 +81,6 @@ static struct clksrc_clk clk_mout_mpll = {
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
- .id = -1,
},
.sources = &clk_src_apll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
@@ -94,7 +89,6 @@ static struct clksrc_clk clk_mout_apll = {
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
- .id = -1,
},
.sources = &clk_src_epll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
@@ -112,7 +106,6 @@ static struct clksrc_sources clk_src_mout_hpll = {
static struct clksrc_clk clk_mout_hpll = {
.clk = {
.name = "mout_hpll",
- .id = -1,
},
.sources = &clk_src_mout_hpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
@@ -121,7 +114,6 @@ static struct clksrc_clk clk_mout_hpll = {
static struct clksrc_clk clk_div_apll = {
.clk = {
.name = "div_apll",
- .id = -1,
.parent = &clk_mout_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 1 },
@@ -130,7 +122,6 @@ static struct clksrc_clk clk_div_apll = {
static struct clksrc_clk clk_div_arm = {
.clk = {
.name = "div_arm",
- .id = -1,
.parent = &clk_div_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
@@ -139,7 +130,6 @@ static struct clksrc_clk clk_div_arm = {
static struct clksrc_clk clk_div_d0_bus = {
.clk = {
.name = "div_d0_bus",
- .id = -1,
.parent = &clk_div_arm.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
@@ -148,7 +138,6 @@ static struct clksrc_clk clk_div_d0_bus = {
static struct clksrc_clk clk_div_pclkd0 = {
.clk = {
.name = "div_pclkd0",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
@@ -157,7 +146,6 @@ static struct clksrc_clk clk_div_pclkd0 = {
static struct clksrc_clk clk_div_secss = {
.clk = {
.name = "div_secss",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 3 },
@@ -166,7 +154,6 @@ static struct clksrc_clk clk_div_secss = {
static struct clksrc_clk clk_div_apll2 = {
.clk = {
.name = "div_apll2",
- .id = -1,
.parent = &clk_mout_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 3 },
@@ -185,7 +172,6 @@ struct clksrc_sources clk_src_mout_am = {
static struct clksrc_clk clk_mout_am = {
.clk = {
.name = "mout_am",
- .id = -1,
},
.sources = &clk_src_mout_am,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
@@ -194,7 +180,6 @@ static struct clksrc_clk clk_mout_am = {
static struct clksrc_clk clk_div_d1_bus = {
.clk = {
.name = "div_d1_bus",
- .id = -1,
.parent = &clk_mout_am.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 3 },
@@ -203,7 +188,6 @@ static struct clksrc_clk clk_div_d1_bus = {
static struct clksrc_clk clk_div_mpll2 = {
.clk = {
.name = "div_mpll2",
- .id = -1,
.parent = &clk_mout_am.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 1 },
@@ -212,7 +196,6 @@ static struct clksrc_clk clk_div_mpll2 = {
static struct clksrc_clk clk_div_mpll = {
.clk = {
.name = "div_mpll",
- .id = -1,
.parent = &clk_mout_am.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 2 },
@@ -231,7 +214,6 @@ struct clksrc_sources clk_src_mout_onenand = {
static struct clksrc_clk clk_mout_onenand = {
.clk = {
.name = "mout_onenand",
- .id = -1,
},
.sources = &clk_src_mout_onenand,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
@@ -240,7 +222,6 @@ static struct clksrc_clk clk_mout_onenand = {
static struct clksrc_clk clk_div_onenand = {
.clk = {
.name = "div_onenand",
- .id = -1,
.parent = &clk_mout_onenand.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 2 },
@@ -249,7 +230,6 @@ static struct clksrc_clk clk_div_onenand = {
static struct clksrc_clk clk_div_pclkd1 = {
.clk = {
.name = "div_pclkd1",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 3 },
@@ -258,7 +238,6 @@ static struct clksrc_clk clk_div_pclkd1 = {
static struct clksrc_clk clk_div_cam = {
.clk = {
.name = "div_cam",
- .id = -1,
.parent = &clk_div_mpll2.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 24, .size = 5 },
@@ -267,7 +246,6 @@ static struct clksrc_clk clk_div_cam = {
static struct clksrc_clk clk_div_hdmi = {
.clk = {
.name = "div_hdmi",
- .id = -1,
.parent = &clk_mout_hpll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 },
@@ -399,367 +377,329 @@ static int s5pc100_sclk1_ctrl(struct clk *clk, int enable)
static struct clk init_clocks_off[] = {
{
.name = "cssys",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "secss",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "g2d",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "mdma",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "cfcon",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "nfcon",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "onenandc",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "sdm",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_2_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "seckey",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_2_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "hsmmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "hsmmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "hsmmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "modemif",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "otg",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "usbhost",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "pdma",
- .id = 1,
+ .devname = "s3c-pl330.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "pdma",
- .id = 0,
+ .devname = "s3c-pl330.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "lcd",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "rotator",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "fimc",
- .id = 0,
+ .devname = "s5p-fimc.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "fimc",
- .id = 1,
+ .devname = "s5p-fimc.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "fimc",
- .id = 2,
- .parent = &clk_div_d1_bus.clk,
+ .devname = "s5p-fimc.2",
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "jpeg",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "mipi-dsim",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "mipi-csis",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "g3d",
- .id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "tv",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "vp",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "mixer",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "hdmi",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "mfc",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "apc",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "iec",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "systimer",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "i2c",
- .id = 0,
+ .devname = "s3c2440-i2c.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "i2c",
- .id = 1,
+ .devname = "s3c2440-i2c.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "spi",
- .id = 2,
+ .devname = "s3c64xx-spi.2",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "irda",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "ccan",
- .id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 10),
}, {
.name = "ccan",
- .id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 11),
}, {
.name = "hsitx",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "hsirx",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 13),
}, {
.name = "iis",
- .id = 0,
+ .devname = "samsung-i2s.0",
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "iis",
- .id = 1,
+ .devname = "samsung-i2s.1",
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "iis",
- .id = 2,
+ .devname = "samsung-i2s.2",
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "ac97",
- .id = -1,
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "pcm",
- .id = 0,
+ .devname = "samsung-pcm.0",
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "pcm",
- .id = 1,
+ .devname = "samsung-pcm.1",
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "spdif",
- .id = -1,
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "adc",
- .id = -1,
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "keypad",
- .id = -1,
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "spi_48m",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "spi_48m",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "spi_48m",
- .id = 2,
+ .devname = "s3c64xx-spi.2",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "mmc_48m",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 15),
}, {
.name = "mmc_48m",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 16),
}, {
.name = "mmc_48m",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 17),
@@ -768,33 +708,27 @@ static struct clk init_clocks_off[] = {
static struct clk clk_vclk54m = {
.name = "vclk_54m",
- .id = -1,
.rate = 54000000,
};
static struct clk clk_i2scdclk0 = {
.name = "i2s_cdclk0",
- .id = -1,
};
static struct clk clk_i2scdclk1 = {
.name = "i2s_cdclk1",
- .id = -1,
};
static struct clk clk_i2scdclk2 = {
.name = "i2s_cdclk2",
- .id = -1,
};
static struct clk clk_pcmcdclk0 = {
.name = "pcm_cdclk0",
- .id = -1,
};
static struct clk clk_pcmcdclk1 = {
.name = "pcm_cdclk1",
- .id = -1,
};
static struct clk *clk_src_group1_list[] = {
@@ -836,7 +770,7 @@ struct clksrc_sources clk_src_group3 = {
static struct clksrc_clk clk_sclk_audio0 = {
.clk = {
.name = "sclk_audio",
- .id = 0,
+ .devname = "samsung-pcm.0",
.ctrlbit = (1 << 8),
.enable = s5pc100_sclk1_ctrl,
},
@@ -862,7 +796,7 @@ struct clksrc_sources clk_src_group4 = {
static struct clksrc_clk clk_sclk_audio1 = {
.clk = {
.name = "sclk_audio",
- .id = 1,
+ .devname = "samsung-pcm.1",
.ctrlbit = (1 << 9),
.enable = s5pc100_sclk1_ctrl,
},
@@ -887,7 +821,7 @@ struct clksrc_sources clk_src_group5 = {
static struct clksrc_clk clk_sclk_audio2 = {
.clk = {
.name = "sclk_audio",
- .id = 2,
+ .devname = "samsung-pcm.2",
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk1_ctrl,
},
@@ -976,48 +910,12 @@ struct clksrc_sources clk_src_sclk_spdif = {
.nr_sources = ARRAY_SIZE(clk_sclk_spdif_list),
};
-static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *pclk;
- int ret;
-
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
-
- ret = pclk->ops->set_rate(pclk, rate);
- clk_put(pclk);
-
- return ret;
-}
-
-static unsigned long s5pc100_spdif_get_rate(struct clk *clk)
-{
- struct clk *pclk;
- int rate;
-
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
-
- rate = pclk->ops->get_rate(clk);
- clk_put(pclk);
-
- return rate;
-}
-
-static struct clk_ops s5pc100_sclk_spdif_ops = {
- .set_rate = s5pc100_spdif_set_rate,
- .get_rate = s5pc100_spdif_get_rate,
-};
-
static struct clksrc_clk clk_sclk_spdif = {
.clk = {
.name = "sclk_spdif",
- .id = -1,
.ctrlbit = (1 << 11),
.enable = s5pc100_sclk1_ctrl,
- .ops = &s5pc100_sclk_spdif_ops,
+ .ops = &s5p_sclk_spdif_ops,
},
.sources = &clk_src_sclk_spdif,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 },
@@ -1027,7 +925,7 @@ static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "sclk_spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 4),
.enable = s5pc100_sclk0_ctrl,
@@ -1038,7 +936,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 5),
.enable = s5pc100_sclk0_ctrl,
@@ -1049,7 +947,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 2,
+ .devname = "s3c64xx-spi.2",
.ctrlbit = (1 << 6),
.enable = s5pc100_sclk0_ctrl,
@@ -1060,7 +958,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = -1,
.ctrlbit = (1 << 3),
.enable = s5pc100_sclk0_ctrl,
@@ -1071,7 +968,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mixer",
- .id = -1,
.ctrlbit = (1 << 6),
.enable = s5pc100_sclk0_ctrl,
@@ -1081,7 +977,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_lcd",
- .id = -1,
.ctrlbit = (1 << 0),
.enable = s5pc100_sclk1_ctrl,
@@ -1092,7 +987,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 0,
+ .devname = "s5p-fimc.0",
.ctrlbit = (1 << 1),
.enable = s5pc100_sclk1_ctrl,
@@ -1103,7 +998,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 1,
+ .devname = "s5p-fimc.1",
.ctrlbit = (1 << 2),
.enable = s5pc100_sclk1_ctrl,
@@ -1114,7 +1009,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 2,
+ .devname = "s5p-fimc.2",
.ctrlbit = (1 << 3),
.enable = s5pc100_sclk1_ctrl,
@@ -1125,7 +1020,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.ctrlbit = (1 << 12),
.enable = s5pc100_sclk1_ctrl,
@@ -1136,7 +1031,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.ctrlbit = (1 << 13),
.enable = s5pc100_sclk1_ctrl,
@@ -1147,7 +1042,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.ctrlbit = (1 << 14),
.enable = s5pc100_sclk1_ctrl,
@@ -1158,7 +1053,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_irda",
- .id = 2,
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk0_ctrl,
@@ -1169,7 +1063,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_irda",
- .id = -1,
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk0_ctrl,
@@ -1180,7 +1073,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_pwi",
- .id = -1,
.ctrlbit = (1 << 1),
.enable = s5pc100_sclk0_ctrl,
@@ -1191,7 +1083,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_uhost",
- .id = -1,
.ctrlbit = (1 << 11),
.enable = s5pc100_sclk0_ctrl,
@@ -1291,79 +1182,70 @@ void __init_or_cpufreq s5pc100_setup_clocks(void)
static struct clk init_clocks[] = {
{
.name = "tzic",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "intc",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "ebi",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "intmem",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "sromc",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "dmc",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "chipid",
- .id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "gpio",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "uart",
- .id = 0,
+ .devname = "s3c6400-uart.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "uart",
- .id = 1,
+ .devname = "s3c6400-uart.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "uart",
- .id = 2,
+ .devname = "s3c6400-uart.2",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "uart",
- .id = 3,
+ .devname = "s3c6400-uart.3",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "timers",
- .id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 6),
diff --git a/arch/arm/mach-s5pc100/include/mach/clkdev.h b/arch/arm/mach-s5pc100/include/mach/clkdev.h
new file mode 100644
index 000000000000..7dffa83d23ff
--- /dev/null
+++ b/arch/arm/mach-s5pc100/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-fb.h b/arch/arm/mach-s5pc100/include/mach/regs-fb.h
deleted file mode 100644
index 07aa4d6054fe..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/regs-fb.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/regs-fb.h
- *
- * Copyright 2009 Samsung Electronics Co.
- * Pawel Osciak <p.osciak@samsung.com>
- *
- * Framebuffer register definitions for Samsung S5PC100.
- *
- * 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_REGS_FB_H
-#define __ASM_ARCH_REGS_FB_H __FILE__
-
-#include <plat/regs-fb-v4.h>
-
-/* VP1 interface timing control */
-#define VP1CON0 (0x118)
-#define VP1_RATECON_EN (1 << 31)
-#define VP1_CLKRATE_MASK (0xff)
-
-#define VP1CON1 (0x11c)
-#define VP1_VTREGCON_EN (1 << 31)
-#define VP1_VBPD_MASK (0xfff)
-#define VP1_VBPD_SHIFT (16)
-
-
-#define WPALCON_H (0x19c)
-#define WPALCON_L (0x1a0)
-
-/* Palette control for WPAL0 and WPAL1 is the same as in S3C64xx, but
- * different for WPAL2-4
- */
-/* In WPALCON_L (aka WPALCON) */
-#define WPALCON_W1PAL_32BPP_A888 (0x7 << 3)
-#define WPALCON_W0PAL_32BPP_A888 (0x7 << 0)
-
-/* To set W2PAL-W4PAL consist of one bit from WPALCON_L and two from WPALCON_H,
- * e.g. W2PAL[2..0] is made of (WPALCON_H[10..9], WPALCON_L[6]).
- */
-#define WPALCON_L_WxPAL_L_MASK (0x1)
-#define WPALCON_L_W2PAL_L_SHIFT (6)
-#define WPALCON_L_W3PAL_L_SHIFT (7)
-#define WPALCON_L_W4PAL_L_SHIFT (8)
-
-#define WPALCON_L_WxPAL_H_MASK (0x3)
-#define WPALCON_H_W2PAL_H_SHIFT (9)
-#define WPALCON_H_W3PAL_H_SHIFT (13)
-#define WPALCON_H_W4PAL_H_SHIFT (17)
-
-/* Per-window alpha value registers */
-/* For window 0 8-bit alpha values are in VIDW0ALPHAx,
- * for windows 1-4 alpha values consist of two parts, the 4 low bits are
- * taken from VIDWxALPHAx and 4 high bits are from VIDOSDxC,
- * e.g. WIN1_ALPHA0_B[7..0] = (VIDOSD1C[3..0], VIDW1ALPHA0[3..0])
- */
-#define VIDWxALPHA0(_win) (0x200 + (_win * 8))
-#define VIDWxALPHA1(_win) (0x204 + (_win * 8))
-
-/* Only for window 0 in VIDW0ALPHAx. */
-#define VIDW0ALPHAx_R(_x) ((_x) << 16)
-#define VIDW0ALPHAx_R_MASK (0xff << 16)
-#define VIDW0ALPHAx_R_SHIFT (16)
-#define VIDW0ALPHAx_G(_x) ((_x) << 8)
-#define VIDW0ALPHAx_G_MASK (0xff << 8)
-#define VIDW0ALPHAx_G_SHIFT (8)
-#define VIDW0ALPHAx_B(_x) ((_x) << 0)
-#define VIDW0ALPHAx_B_MASK (0xff << 0)
-#define VIDW0ALPHAx_B_SHIFT (0)
-
-/* Low 4 bits of alpha0-1 for windows 1-4 */
-#define VIDW14ALPHAx_R_L(_x) ((_x) << 16)
-#define VIDW14ALPHAx_R_L_MASK (0xf << 16)
-#define VIDW14ALPHAx_R_L_SHIFT (16)
-#define VIDW14ALPHAx_G_L(_x) ((_x) << 8)
-#define VIDW14ALPHAx_G_L_MASK (0xf << 8)
-#define VIDW14ALPHAx_G_L_SHIFT (8)
-#define VIDW14ALPHAx_B_L(_x) ((_x) << 0)
-#define VIDW14ALPHAx_B_L_MASK (0xf << 0)
-#define VIDW14ALPHAx_B_L_SHIFT (0)
-
-
-/* Per-window blending equation control registers */
-#define BLENDEQx(_win) (0x244 + ((_win) * 4))
-#define BLENDEQ1 (0x244)
-#define BLENDEQ2 (0x248)
-#define BLENDEQ3 (0x24c)
-#define BLENDEQ4 (0x250)
-
-#define BLENDEQx_Q_FUNC(_x) ((_x) << 18)
-#define BLENDEQx_Q_FUNC_MASK (0xf << 18)
-#define BLENDEQx_P_FUNC(_x) ((_x) << 12)
-#define BLENDEQx_P_FUNC_MASK (0xf << 12)
-#define BLENDEQx_B_FUNC(_x) ((_x) << 6)
-#define BLENDEQx_B_FUNC_MASK (0xf << 6)
-#define BLENDEQx_A_FUNC(_x) ((_x) << 0)
-#define BLENDEQx_A_FUNC_MASK (0xf << 0)
-
-#define BLENDCON (0x260)
-#define BLENDCON_8BIT_ALPHA (1 << 0)
-
-
-#endif /* __ASM_ARCH_REGS_FB_H */
-
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 0525cb3ef406..227d8908aab6 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -29,7 +29,6 @@
#include <asm/mach/map.h>
#include <mach/map.h>
-#include <mach/regs-fb.h>
#include <mach/regs-gpio.h>
#include <video/platform_lcd.h>
@@ -51,6 +50,8 @@
#include <plat/keypad.h>
#include <plat/ts.h>
#include <plat/audio.h>
+#include <plat/backlight.h>
+#include <plat/regs-fb-v4.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -179,45 +180,6 @@ static struct samsung_keypad_platdata smdkc100_keypad_data __initdata = {
.cols = 8,
};
-static int smdkc100_backlight_init(struct device *dev)
-{
- int ret;
-
- ret = gpio_request(S5PC100_GPD(0), "Backlight");
- if (ret) {
- printk(KERN_ERR "failed to request GPF for PWM-OUT0\n");
- return ret;
- }
-
- /* Configure GPIO pin with S5PC100_GPD_TOUT_0 */
- s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_SFN(2));
-
- return 0;
-}
-
-static void smdkc100_backlight_exit(struct device *dev)
-{
- s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_OUTPUT);
- gpio_free(S5PC100_GPD(0));
-}
-
-static struct platform_pwm_backlight_data smdkc100_backlight_data = {
- .pwm_id = 0,
- .max_brightness = 255,
- .dft_brightness = 255,
- .pwm_period_ns = 78770,
- .init = smdkc100_backlight_init,
- .exit = smdkc100_backlight_exit,
-};
-
-static struct platform_device smdkc100_backlight_device = {
- .name = "pwm-backlight",
- .dev = {
- .parent = &s3c_device_timer[0].dev,
- .platform_data = &smdkc100_backlight_data,
- },
-};
-
static struct platform_device *smdkc100_devices[] __initdata = {
&s3c_device_adc,
&s3c_device_cfcon,
@@ -239,8 +201,6 @@ static struct platform_device *smdkc100_devices[] __initdata = {
&s5p_device_fimc1,
&s5p_device_fimc2,
&s5pc100_device_spdif,
- &s3c_device_timer[0],
- &smdkc100_backlight_device,
};
static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
@@ -249,6 +209,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
.oversampling_shift = 2,
};
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
+ .no = S5PC100_GPD(0),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkc100_bl_data = {
+ .pwm_id = 0,
+};
+
static void __init smdkc100_map_io(void)
{
s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -276,6 +246,9 @@ static void __init smdkc100_machine_init(void)
/* LCD init */
gpio_request(S5PC100_GPH0(6), "GPH0");
smdkc100_lcd_power_set(&smdkc100_lcd_power_data, 0);
+
+ samsung_bl_set(&smdkc100_bl_gpio_info, &smdkc100_bl_data);
+
platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices));
}
diff --git a/arch/arm/mach-s5pc100/setup-fb-24bpp.c b/arch/arm/mach-s5pc100/setup-fb-24bpp.c
index d31c0f3fe222..8978e4cf9ed5 100644
--- a/arch/arm/mach-s5pc100/setup-fb-24bpp.c
+++ b/arch/arm/mach-s5pc100/setup-fb-24bpp.c
@@ -15,7 +15,6 @@
#include <linux/fb.h>
#include <linux/gpio.h>
-#include <mach/regs-fb.h>
#include <mach/map.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 37b5a97594a5..69dd87cd8e22 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -90,6 +90,7 @@ config MACH_GONI
select S3C_DEV_HSMMC2
select S3C_DEV_I2C1
select S3C_DEV_I2C2
+ select S5P_DEV_MFC
select S3C_DEV_USB_HSOTG
select S5P_DEV_ONENAND
select SAMSUNG_DEV_KEYPAD
@@ -134,6 +135,7 @@ config MACH_SMDKV210
select S3C_DEV_RTC
select S3C_DEV_WDT
select SAMSUNG_DEV_ADC
+ select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_IDE
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_PWM
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 50907aca006c..599a3c0e8f6c 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -15,7 +15,6 @@ 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_CPU_FREQ) += cpufreq.o
# machine support
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index 2d599499cefe..52a8e607bcc2 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -36,7 +36,6 @@ static unsigned long xtal;
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
- .id = -1,
},
.sources = &clk_src_apll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
@@ -45,7 +44,6 @@ static struct clksrc_clk clk_mout_apll = {
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
- .id = -1,
},
.sources = &clk_src_epll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
@@ -54,7 +52,6 @@ static struct clksrc_clk clk_mout_epll = {
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
- .id = -1,
},
.sources = &clk_src_mpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
@@ -73,7 +70,6 @@ static struct clksrc_sources clkset_armclk = {
static struct clksrc_clk clk_armclk = {
.clk = {
.name = "armclk",
- .id = -1,
},
.sources = &clkset_armclk,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
@@ -83,7 +79,6 @@ static struct clksrc_clk clk_armclk = {
static struct clksrc_clk clk_hclk_msys = {
.clk = {
.name = "hclk_msys",
- .id = -1,
.parent = &clk_armclk.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
@@ -92,7 +87,6 @@ static struct clksrc_clk clk_hclk_msys = {
static struct clksrc_clk clk_pclk_msys = {
.clk = {
.name = "pclk_msys",
- .id = -1,
.parent = &clk_hclk_msys.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
@@ -101,7 +95,6 @@ static struct clksrc_clk clk_pclk_msys = {
static struct clksrc_clk clk_sclk_a2m = {
.clk = {
.name = "sclk_a2m",
- .id = -1,
.parent = &clk_mout_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
@@ -120,7 +113,6 @@ static struct clksrc_sources clkset_hclk_sys = {
static struct clksrc_clk clk_hclk_dsys = {
.clk = {
.name = "hclk_dsys",
- .id = -1,
},
.sources = &clkset_hclk_sys,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
@@ -130,7 +122,6 @@ static struct clksrc_clk clk_hclk_dsys = {
static struct clksrc_clk clk_pclk_dsys = {
.clk = {
.name = "pclk_dsys",
- .id = -1,
.parent = &clk_hclk_dsys.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
@@ -139,7 +130,6 @@ static struct clksrc_clk clk_pclk_dsys = {
static struct clksrc_clk clk_hclk_psys = {
.clk = {
.name = "hclk_psys",
- .id = -1,
},
.sources = &clkset_hclk_sys,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
@@ -149,7 +139,6 @@ static struct clksrc_clk clk_hclk_psys = {
static struct clksrc_clk clk_pclk_psys = {
.clk = {
.name = "pclk_psys",
- .id = -1,
.parent = &clk_hclk_psys.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
@@ -187,38 +176,31 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
static struct clk clk_sclk_hdmi27m = {
.name = "sclk_hdmi27m",
- .id = -1,
.rate = 27000000,
};
static struct clk clk_sclk_hdmiphy = {
.name = "sclk_hdmiphy",
- .id = -1,
};
static struct clk clk_sclk_usbphy0 = {
.name = "sclk_usbphy0",
- .id = -1,
};
static struct clk clk_sclk_usbphy1 = {
.name = "sclk_usbphy1",
- .id = -1,
};
static struct clk clk_pcmcdclk0 = {
.name = "pcmcdclk",
- .id = -1,
};
static struct clk clk_pcmcdclk1 = {
.name = "pcmcdclk",
- .id = -1,
};
static struct clk clk_pcmcdclk2 = {
.name = "pcmcdclk",
- .id = -1,
};
static struct clk *clkset_vpllsrc_list[] = {
@@ -234,7 +216,6 @@ static struct clksrc_sources clkset_vpllsrc = {
static struct clksrc_clk clk_vpllsrc = {
.clk = {
.name = "vpll_src",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 7),
},
@@ -255,7 +236,6 @@ static struct clksrc_sources clkset_sclk_vpll = {
static struct clksrc_clk clk_sclk_vpll = {
.clk = {
.name = "sclk_vpll",
- .id = -1,
},
.sources = &clkset_sclk_vpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
@@ -276,7 +256,6 @@ static struct clksrc_sources clkset_moutdmc0src = {
static struct clksrc_clk clk_mout_dmc0 = {
.clk = {
.name = "mout_dmc0",
- .id = -1,
},
.sources = &clkset_moutdmc0src,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
@@ -285,7 +264,6 @@ static struct clksrc_clk clk_mout_dmc0 = {
static struct clksrc_clk clk_sclk_dmc0 = {
.clk = {
.name = "sclk_dmc0",
- .id = -1,
.parent = &clk_mout_dmc0.clk,
},
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
@@ -312,181 +290,175 @@ static struct clk_ops clk_fout_apll_ops = {
static struct clk init_clocks_off[] = {
{
.name = "pdma",
- .id = 0,
+ .devname = "s3c-pl330.0",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "pdma",
- .id = 1,
+ .devname = "s3c-pl330.1",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "rot",
- .id = -1,
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1<<29),
}, {
.name = "fimc",
- .id = 0,
+ .devname = "s5pv210-fimc.0",
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 24),
}, {
.name = "fimc",
- .id = 1,
+ .devname = "s5pv210-fimc.1",
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 25),
}, {
.name = "fimc",
- .id = 2,
+ .devname = "s5pv210-fimc.2",
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 26),
}, {
+ .name = "mfc",
+ .devname = "s5p-mfc",
+ .parent = &clk_pclk_psys.clk,
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1 << 16),
+ }, {
.name = "otg",
- .id = -1,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<16),
}, {
.name = "usb-host",
- .id = -1,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<17),
}, {
.name = "lcd",
- .id = -1,
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<0),
}, {
.name = "cfcon",
- .id = 0,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<25),
}, {
.name = "hsmmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<16),
}, {
.name = "hsmmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<17),
}, {
.name = "hsmmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<18),
}, {
.name = "hsmmc",
- .id = 3,
+ .devname = "s3c-sdhci.3",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<19),
}, {
.name = "systimer",
- .id = -1,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<16),
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<22),
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<15),
}, {
.name = "i2c",
- .id = 0,
+ .devname = "s3c2440-i2c.0",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<7),
}, {
.name = "i2c",
- .id = 1,
+ .devname = "s3c2440-i2c.1",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 10),
}, {
.name = "i2c",
- .id = 2,
+ .devname = "s3c2440-i2c.2",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<9),
}, {
.name = "spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<12),
}, {
.name = "spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<13),
}, {
.name = "spi",
- .id = 2,
+ .devname = "s3c64xx-spi.2",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<14),
}, {
.name = "timers",
- .id = -1,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<23),
}, {
.name = "adc",
- .id = -1,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<24),
}, {
.name = "keypad",
- .id = -1,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<21),
}, {
.name = "iis",
- .id = 0,
+ .devname = "samsung-i2s.0",
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<4),
}, {
.name = "iis",
- .id = 1,
+ .devname = "samsung-i2s.1",
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "iis",
- .id = 2,
+ .devname = "samsung-i2s.2",
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "spdif",
- .id = -1,
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 0),
@@ -496,38 +468,36 @@ static struct clk init_clocks_off[] = {
static struct clk init_clocks[] = {
{
.name = "hclk_imem",
- .id = -1,
.parent = &clk_hclk_msys.clk,
.ctrlbit = (1 << 5),
.enable = s5pv210_clk_ip0_ctrl,
.ops = &clk_hclk_imem_ops,
}, {
.name = "uart",
- .id = 0,
+ .devname = "s5pv210-uart.0",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 17),
}, {
.name = "uart",
- .id = 1,
+ .devname = "s5pv210-uart.1",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 18),
}, {
.name = "uart",
- .id = 2,
+ .devname = "s5pv210-uart.2",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 19),
}, {
.name = "uart",
- .id = 3,
+ .devname = "s5pv210-uart.3",
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 20),
}, {
.name = "sromc",
- .id = -1,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1 << 26),
@@ -579,7 +549,6 @@ static struct clksrc_sources clkset_sclk_dac = {
static struct clksrc_clk clk_sclk_dac = {
.clk = {
.name = "sclk_dac",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 2),
},
@@ -590,7 +559,6 @@ static struct clksrc_clk clk_sclk_dac = {
static struct clksrc_clk clk_sclk_pixel = {
.clk = {
.name = "sclk_pixel",
- .id = -1,
.parent = &clk_sclk_vpll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
@@ -609,7 +577,6 @@ static struct clksrc_sources clkset_sclk_hdmi = {
static struct clksrc_clk clk_sclk_hdmi = {
.clk = {
.name = "sclk_hdmi",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 0),
},
@@ -647,7 +614,7 @@ static struct clksrc_sources clkset_sclk_audio0 = {
static struct clksrc_clk clk_sclk_audio0 = {
.clk = {
.name = "sclk_audio",
- .id = 0,
+ .devname = "soc-audio.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 24),
},
@@ -676,7 +643,7 @@ static struct clksrc_sources clkset_sclk_audio1 = {
static struct clksrc_clk clk_sclk_audio1 = {
.clk = {
.name = "sclk_audio",
- .id = 1,
+ .devname = "soc-audio.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 25),
},
@@ -705,7 +672,7 @@ static struct clksrc_sources clkset_sclk_audio2 = {
static struct clksrc_clk clk_sclk_audio2 = {
.clk = {
.name = "sclk_audio",
- .id = 2,
+ .devname = "soc-audio.2",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 26),
},
@@ -725,48 +692,12 @@ static struct clksrc_sources clkset_sclk_spdif = {
.nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list),
};
-static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *pclk;
- int ret;
-
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
-
- ret = pclk->ops->set_rate(pclk, rate);
- clk_put(pclk);
-
- return ret;
-}
-
-static unsigned long s5pv210_spdif_get_rate(struct clk *clk)
-{
- struct clk *pclk;
- int rate;
-
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
-
- rate = pclk->ops->get_rate(clk);
- clk_put(pclk);
-
- return rate;
-}
-
-static struct clk_ops s5pv210_sclk_spdif_ops = {
- .set_rate = s5pv210_spdif_set_rate,
- .get_rate = s5pv210_spdif_get_rate,
-};
-
static struct clksrc_clk clk_sclk_spdif = {
.clk = {
.name = "sclk_spdif",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 27),
- .ops = &s5pv210_sclk_spdif_ops,
+ .ops = &s5p_sclk_spdif_ops,
},
.sources = &clkset_sclk_spdif,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
@@ -793,7 +724,6 @@ static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "sclk_dmc",
- .id = -1,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
@@ -801,7 +731,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_onenand",
- .id = -1,
},
.sources = &clkset_sclk_onenand,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
@@ -809,7 +738,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = 0,
+ .devname = "s5pv210-uart.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 12),
},
@@ -819,7 +748,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = 1,
+ .devname = "s5pv210-uart.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 13),
},
@@ -829,7 +758,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = 2,
+ .devname = "s5pv210-uart.2",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 14),
},
@@ -839,7 +768,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "uclk1",
- .id = 3,
+ .devname = "s5pv210-uart.3",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 15),
},
@@ -849,7 +778,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mixer",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 1),
},
@@ -858,7 +786,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 0,
+ .devname = "s5pv210-fimc.0",
.enable = s5pv210_clk_mask1_ctrl,
.ctrlbit = (1 << 2),
},
@@ -868,7 +796,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 1,
+ .devname = "s5pv210-fimc.1",
.enable = s5pv210_clk_mask1_ctrl,
.ctrlbit = (1 << 3),
},
@@ -878,7 +806,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimc",
- .id = 2,
+ .devname = "s5pv210-fimc.2",
.enable = s5pv210_clk_mask1_ctrl,
.ctrlbit = (1 << 4),
},
@@ -888,7 +816,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_cam",
- .id = 0,
+ .devname = "s5pv210-fimc.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 3),
},
@@ -898,7 +826,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_cam",
- .id = 1,
+ .devname = "s5pv210-fimc.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 4),
},
@@ -908,7 +836,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_fimd",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 5),
},
@@ -918,7 +845,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 0,
+ .devname = "s3c-sdhci.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 8),
},
@@ -928,7 +855,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 1,
+ .devname = "s3c-sdhci.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 9),
},
@@ -938,7 +865,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 2,
+ .devname = "s3c-sdhci.2",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 10),
},
@@ -948,7 +875,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mmc",
- .id = 3,
+ .devname = "s3c-sdhci.3",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 11),
},
@@ -958,7 +885,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_mfc",
- .id = -1,
+ .devname = "s5p-mfc",
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 16),
},
@@ -968,7 +895,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_g2d",
- .id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 12),
},
@@ -978,7 +904,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_g3d",
- .id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 8),
},
@@ -988,7 +913,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_csis",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 6),
},
@@ -998,7 +922,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 0,
+ .devname = "s3c64xx-spi.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 16),
},
@@ -1008,7 +932,7 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_spi",
- .id = 1,
+ .devname = "s3c64xx-spi.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 17),
},
@@ -1018,7 +942,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_pwi",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 29),
},
@@ -1028,7 +951,6 @@ static struct clksrc_clk clksrcs[] = {
}, {
.clk = {
.name = "sclk_pwm",
- .id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 19),
},
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 61e6c24b90ac..79907ec78d43 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -126,7 +126,7 @@ void __init s5pv210_map_io(void)
s5pv210_default_sdhci2();
s5pv210_default_sdhci3();
- s3c_adc_setname("s3c64xx-adc");
+ s3c_adc_setname("samsung-adc-v3");
s3c_cfcon_setname("s5pv210-pata");
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 8d58f1926241..63f5d82004b5 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -18,6 +18,7 @@
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
+#include <mach/regs-audss.h>
static const char *rclksrc[] = {
[0] = "busclk",
@@ -52,6 +53,7 @@ static struct s3c_audio_pdata i2sv5_pdata = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
| QUIRK_NEED_RSTCLR,
.src_clk = rclksrc,
+ .idma_addr = S5PV210_AUDSS_INT_MEM,
},
},
};
diff --git a/arch/arm/mach-s5pv210/include/mach/clkdev.h b/arch/arm/mach-s5pv210/include/mach/clkdev.h
new file mode 100644
index 000000000000..7dffa83d23ff
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index 1dd58836fd4f..aac343c180b2 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -59,6 +59,8 @@
#define S5PV210_PA_CFCON 0xE8200000
+#define S5PV210_PA_MFC 0xF1700000
+
#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000))
#define S5PV210_PA_HSOTG 0xEC000000
@@ -107,6 +109,7 @@
#define S5P_PA_FIMC1 S5PV210_PA_FIMC1
#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
#define S5P_PA_MIPI_CSIS0 S5PV210_PA_MIPI_CSIS
+#define S5P_PA_MFC S5PV210_PA_MFC
#define S5P_PA_ONENAND S5PC110_PA_ONENAND
#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA
#define S5P_PA_SDRAM S5PV210_PA_SDRAM
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
index e8d394f8b057..3e22109e1b7b 100644
--- a/arch/arm/mach-s5pv210/include/mach/pm-core.h
+++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h
@@ -41,3 +41,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
{
/* nothing here yet */
}
+
+static inline void s3c_pm_restored_gpios(void) { }
+static inline void s3c_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-audss.h b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
new file mode 100644
index 000000000000..eacc1f790807
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s5pv210/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.com
+ *
+ * S5PV210 Audio SubSystem clock register 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define S5PV210_AUDSS_INT_MEM (0xC0000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-fb.h b/arch/arm/mach-s5pv210/include/mach/regs-fb.h
deleted file mode 100644
index 60d992989bdc..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/regs-fb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Dummy framebuffer to allow build for the moment.
- *
- * 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_MACH_REGS_FB_H
-#define __ASM_ARCH_MACH_REGS_FB_H __FILE__
-
-#include <plat/regs-fb-v4.h>
-
-static inline unsigned int s3c_fb_pal_reg(unsigned int window, int reg)
-{
- return 0x2400 + (window * 256 *4 ) + reg;
-}
-
-#endif /* __ASM_ARCH_MACH_REGS_FB_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 4e1d8ff5ae59..509627f25111 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -29,7 +29,6 @@
#include <mach/map.h>
#include <mach/regs-clock.h>
-#include <mach/regs-fb.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-serial.h>
@@ -40,6 +39,7 @@
#include <plat/fimc-core.h>
#include <plat/sdhci.h>
#include <plat/s5p-time.h>
+#include <plat/regs-fb-v4.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define AQUILA_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 31d5aa769753..85c2d51a0956 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -34,7 +34,6 @@
#include <mach/map.h>
#include <mach/regs-clock.h>
-#include <mach/regs-fb.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-serial.h>
@@ -47,6 +46,8 @@
#include <plat/sdhci.h>
#include <plat/clock.h>
#include <plat/s5p-time.h>
+#include <plat/mfc.h>
+#include <plat/regs-fb-v4.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -808,6 +809,9 @@ static struct platform_device *goni_devices[] __initdata = {
&goni_i2c_gpio5,
&mmc2_fixed_voltage,
&goni_device_gpiokeys,
+ &s5p_device_mfc,
+ &s5p_device_mfc_l,
+ &s5p_device_mfc_r,
&s3c_device_i2c0,
&s5p_device_fimc0,
&s5p_device_fimc1,
@@ -841,6 +845,11 @@ static void __init goni_map_io(void)
s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
}
+static void __init goni_reserve(void)
+{
+ s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
static void __init goni_machine_init(void)
{
/* Radio: call before I2C 1 registeration */
@@ -893,4 +902,5 @@ MACHINE_START(GONI, "GONI")
.map_io = goni_map_io,
.init_machine = goni_machine_init,
.timer = &s5p_timer,
+ .reserve = &goni_reserve,
MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index c6a9e86c2d5c..5e011fc6720d 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -29,7 +29,6 @@
#include <mach/map.h>
#include <mach/regs-clock.h>
-#include <mach/regs-fb.h>
#include <plat/regs-serial.h>
#include <plat/regs-srom.h>
@@ -45,6 +44,8 @@
#include <plat/pm.h>
#include <plat/fb.h>
#include <plat/s5p-time.h>
+#include <plat/backlight.h>
+#include <plat/regs-fb-v4.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -210,45 +211,6 @@ static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
.setup_gpio = s5pv210_fb_gpio_setup_24bpp,
};
-static int smdkv210_backlight_init(struct device *dev)
-{
- int ret;
-
- ret = gpio_request(S5PV210_GPD0(3), "Backlight");
- if (ret) {
- printk(KERN_ERR "failed to request GPD for PWM-OUT 3\n");
- return ret;
- }
-
- /* Configure GPIO pin with S5PV210_GPD_0_3_TOUT_3 */
- s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_SFN(2));
-
- return 0;
-}
-
-static void smdkv210_backlight_exit(struct device *dev)
-{
- s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_OUTPUT);
- gpio_free(S5PV210_GPD0(3));
-}
-
-static struct platform_pwm_backlight_data smdkv210_backlight_data = {
- .pwm_id = 3,
- .max_brightness = 255,
- .dft_brightness = 255,
- .pwm_period_ns = 78770,
- .init = smdkv210_backlight_init,
- .exit = smdkv210_backlight_exit,
-};
-
-static struct platform_device smdkv210_backlight_device = {
- .name = "pwm-backlight",
- .dev = {
- .parent = &s3c_device_timer[3].dev,
- .platform_data = &smdkv210_backlight_data,
- },
-};
-
static struct platform_device *smdkv210_devices[] __initdata = {
&s3c_device_adc,
&s3c_device_cfcon,
@@ -267,11 +229,10 @@ static struct platform_device *smdkv210_devices[] __initdata = {
&s5pv210_device_iis0,
&s5pv210_device_spdif,
&samsung_asoc_dma,
+ &samsung_asoc_idma,
&samsung_device_keypad,
&smdkv210_dm9000,
&smdkv210_lcd_lte480wv,
- &s3c_device_timer[3],
- &smdkv210_backlight_device,
};
static void __init smdkv210_dm9000_init(void)
@@ -310,6 +271,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
.oversampling_shift = 2,
};
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
+ .no = S5PV210_GPD0(3),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkv210_bl_data = {
+ .pwm_id = 3,
+};
+
static void __init smdkv210_map_io(void)
{
s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -341,6 +312,8 @@ static void __init smdkv210_machine_init(void)
s3c_fb_set_platdata(&smdkv210_lcd0_pdata);
+ samsung_bl_set(&smdkv210_bl_gpio_info, &smdkv210_bl_data);
+
platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
}
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
index 24febae3d4c0..309e388a8a83 100644
--- a/arch/arm/mach-s5pv210/pm.c
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -88,7 +88,7 @@ static struct sleep_save s5pv210_core_save[] = {
SAVE_ITEM(S3C2410_TCNTO(0)),
};
-void s5pv210_cpu_suspend(void)
+void s5pv210_cpu_suspend(unsigned long arg)
{
unsigned long tmp;
diff --git a/arch/arm/mach-s5pv210/setup-fb-24bpp.c b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
index e932ebfac56d..55103c8220b3 100644
--- a/arch/arm/mach-s5pv210/setup-fb-24bpp.c
+++ b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
@@ -15,7 +15,6 @@
#include <linux/fb.h>
#include <linux/gpio.h>
-#include <mach/regs-fb.h>
#include <mach/map.h>
#include <plat/fb.h>
#include <mach/regs-clock.h>
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
index a3d649466fb1..e3452ccd4b08 100644
--- a/arch/arm/mach-s5pv210/sleep.S
+++ b/arch/arm/mach-s5pv210/sleep.S
@@ -32,27 +32,6 @@
.text
- /* s3c_cpu_save
- *
- * entry:
- * r1 = v:p offset
- */
-
-ENTRY(s3c_cpu_save)
-
- stmfd sp!, { r3 - r12, lr }
- ldr r3, =resume_with_mmu
- bl cpu_suspend
-
- ldr r0, =pm_cpu_sleep
- ldr r0, [ r0 ]
- mov pc, r0
-
-resume_with_mmu:
- ldmfd sp!, { r3 - r12, pc }
-
- .ltorg
-
/* sleep magic, to allow the bootloader to check for an valid
* image to resume to. Must be the first word before the
* s3c_cpu_resume entry.
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 5778274a8260..26257df19b63 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -453,4 +453,7 @@ MACHINE_START(ASSABET, "Intel-Assabet")
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
.init_machine = assabet_init,
+#ifdef CONFIG_SA1111
+ .dma_zone_size = SZ_1M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index 4f19ff868b00..b4311b0a4395 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -306,4 +306,7 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
.map_io = badge4_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
+#ifdef CONFIG_SA1111
+ .dma_zone_size = SZ_1M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h
index 967ae7684390..99f5856d8de4 100644
--- a/arch/arm/mach-sa1100/include/mach/hardware.h
+++ b/arch/arm/mach-sa1100/include/mach/hardware.h
@@ -76,12 +76,4 @@ static inline unsigned long get_clock_tick_rate(void)
#include "SA-1101.h"
#endif
-#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
-#define PCIBIOS_MIN_IO 0
-#define PCIBIOS_MIN_MEM 0
-#define pcibios_assign_all_busses() 1
-#define HAVE_ARCH_PCI_SET_DMA_MASK 1
-#endif
-
-
#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h
index cff31ee246b7..12d376795abc 100644
--- a/arch/arm/mach-sa1100/include/mach/memory.h
+++ b/arch/arm/mach-sa1100/include/mach/memory.h
@@ -14,10 +14,6 @@
*/
#define PLAT_PHYS_OFFSET UL(0xc0000000)
-#ifdef CONFIG_SA1111
-#define ARM_DMA_ZONE_SIZE SZ_1M
-#endif
-
/*
* Because of the wide memory address space between physical RAM banks on the
* SA1100, it's much convenient to use Linux's SparseMEM support to implement
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 491ac9f20fb4..176c066aec7e 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -369,4 +369,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720")
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
.init_machine = jornada720_mach_init,
+#ifdef CONFIG_SA1111
+ .dma_zone_size = SZ_1M,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c
index fba7a913f12b..5fc074fe3eee 100644
--- a/arch/arm/mach-sa1100/pci-nanoengine.c
+++ b/arch/arm/mach-sa1100/pci-nanoengine.c
@@ -252,6 +252,9 @@ int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
{
int ret = 0;
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0;
+
if (nr == 0) {
sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
sys->io_offset = 0x400;
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index c4661aab22fb..bf85b8b259d5 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -29,10 +29,11 @@
#include <mach/hardware.h>
#include <asm/memory.h>
+#include <asm/suspend.h>
#include <asm/system.h>
#include <asm/mach/time.h>
-extern void sa1100_cpu_suspend(long);
+extern int sa1100_finish_suspend(unsigned long);
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
@@ -75,9 +76,7 @@ static int sa11x0_pm_enter(suspend_state_t state)
PSPR = virt_to_phys(cpu_resume);
/* go zzz */
- sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
-
- cpu_init();
+ cpu_suspend(0, sa1100_finish_suspend);
/*
* Ensure not to come back here if it wasn't intended
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S
index 04f2a618d4ef..e8223315b442 100644
--- a/arch/arm/mach-sa1100/sleep.S
+++ b/arch/arm/mach-sa1100/sleep.S
@@ -22,18 +22,13 @@
.text
/*
- * sa1100_cpu_suspend()
+ * sa1100_finish_suspend()
*
* Causes sa11x0 to enter sleep state
*
*/
-ENTRY(sa1100_cpu_suspend)
- stmfd sp!, {r4 - r12, lr} @ save registers on stack
- mov r1, r0
- ldr r3, =sa1100_cpu_resume @ return function
- bl cpu_suspend
-
+ENTRY(sa1100_finish_suspend)
@ disable clock switching
mcr p15, 0, r1, c15, c2, 2
@@ -139,13 +134,3 @@ sa1110_sdram_controller_fix:
str r13, [r12]
20: b 20b @ loop waiting for sleep
-
-/*
- * cpu_sa1100_resume()
- *
- * entry point from bootloader into kernel during resume
- */
- .align 5
-sa1100_cpu_resume:
- mcr p15, 0, r1, c15, c1, 2 @ enable clock switching
- ldmfd sp!, {r4 - r12, pc} @ return to caller
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 5cf7f94c1f31..ac2873c8014b 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -156,4 +156,5 @@ MACHINE_START(SHARK, "Shark")
.map_io = shark_map_io,
.init_irq = shark_init_irq,
.timer = &shark_timer,
+ .dma_zone_size = SZ_4M,
MACHINE_END
diff --git a/arch/arm/mach-shark/include/mach/entry-macro.S b/arch/arm/mach-shark/include/mach/entry-macro.S
index e2853c0a3333..0bb6cc626eb7 100644
--- a/arch/arm/mach-shark/include/mach/entry-macro.S
+++ b/arch/arm/mach-shark/include/mach/entry-macro.S
@@ -11,17 +11,17 @@
.endm
.macro get_irqnr_preamble, base, tmp
+ mov \base, #0xe0000000
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- mov r4, #0xe0000000
mov \irqstat, #0x0C
- strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */
- ldrb \irqnr, [r4, #0x20] @irq = inb(0x20) & 7
+ strb \irqstat, [\base, #0x20] @outb(0x0C, 0x20) /* Poll command */
+ ldrb \irqnr, [\base, #0x20] @irq = inb(0x20) & 7
and \irqstat, \irqnr, #0x80
teq \irqstat, #0
beq 43f
@@ -29,8 +29,8 @@
teq \irqnr, #2
bne 44f
43: mov \irqstat, #0x0C
- strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */
- ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8
+ strb \irqstat, [\base, #0xa0] @outb(0x0C, 0xA0) /* Poll command */
+ ldrb \irqnr, [\base, #0xa0] @irq = (inb(0xA0) & 7) + 8
and \irqstat, \irqnr, #0x80
teq \irqstat, #0
beq 44f
diff --git a/arch/arm/mach-shark/include/mach/hardware.h b/arch/arm/mach-shark/include/mach/hardware.h
index 94d84b27a0cb..663f952a8ab3 100644
--- a/arch/arm/mach-shark/include/mach/hardware.h
+++ b/arch/arm/mach-shark/include/mach/hardware.h
@@ -12,11 +12,5 @@
#define UNCACHEABLE_ADDR 0xdf010000
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x6000
-#define PCIBIOS_MIN_MEM 0x50000000
-#define PCIMEM_BASE 0xe8000000
-
#endif
diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h
index 4c0831f83b0c..1cf8d6962617 100644
--- a/arch/arm/mach-shark/include/mach/memory.h
+++ b/arch/arm/mach-shark/include/mach/memory.h
@@ -17,8 +17,6 @@
*/
#define PLAT_PHYS_OFFSET UL(0x08000000)
-#define ARM_DMA_ZONE_SIZE SZ_4M
-
/*
* Cache flushing area
*/
diff --git a/arch/arm/mach-shark/pci.c b/arch/arm/mach-shark/pci.c
index 89d175ce74d2..92d7227de0ac 100644
--- a/arch/arm/mach-shark/pci.c
+++ b/arch/arm/mach-shark/pci.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <video/vga.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
@@ -37,8 +38,15 @@ static struct hw_pci shark_pci __initdata = {
static int __init shark_pci_init(void)
{
- if (machine_is_shark())
- pci_common_init(&shark_pci);
+ if (!machine_is_shark())
+ return;
+
+ pcibios_min_io = 0x6000;
+ pcibios_min_mem = 0x50000000;
+ vga_base = 0xe8000000;
+
+ pci_common_init(&shark_pci);
+
return 0;
}
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 803bc6edfca4..837138e369bc 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -443,7 +443,7 @@ static struct platform_device usb1_host_device = {
.resource = usb1_host_resources,
};
-const static struct fb_videomode ap4evb_lcdc_modes[] = {
+static const struct fb_videomode ap4evb_lcdc_modes[] = {
{
#ifdef CONFIG_AP4EVB_QHD
.name = "R63302(QHD)",
@@ -1408,9 +1408,14 @@ static void __init ap4evb_init(void)
platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
+ sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc1_device);
+ sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
+ sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
+
hdmi_init_pm_clock();
fsi_init_pm_clock();
sh7372_pm_init();
+ pm_clk_add(&fsi_device.dev, "spu2");
}
static void __init ap4evb_timer_init(void)
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 3802f2afabef..5b36b6c5b448 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1582,8 +1582,13 @@ static void __init mackerel_init(void)
platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
+ 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_a4mp, &fsi_device);
+
hdmi_init_pm_clock();
sh7372_pm_init();
+ pm_clk_add(&fsi_device.dev, "spu2");
}
static void __init mackerel_timer_init(void)
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index c0800d83971e..91f5779abdd3 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -662,6 +662,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
+ CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
};
void __init sh7372_clock_init(void)
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h
new file mode 100644
index 000000000000..4a81b01f1e8f
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h
@@ -0,0 +1,21 @@
+#ifndef SDHI_SH7372_H
+#define SDHI_SH7372_H
+
+#define SDGENCNTA 0xfe40009c
+
+/* The countdown of SDGENCNTA is controlled by
+ * ZB3D2CLK which runs at 149.5MHz.
+ * That is 149.5ticks/us. Approximate this as 150ticks/us.
+ */
+static void udelay(int us)
+{
+ __raw_writel(us * 150, SDGENCNTA);
+ while(__raw_readl(SDGENCNTA)) ;
+}
+
+static void msleep(int ms)
+{
+ udelay(ms * 1000);
+}
+
+#endif
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi.h b/arch/arm/mach-shmobile/include/mach/sdhi.h
new file mode 100644
index 000000000000..0ec9e69f2c3b
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sdhi.h
@@ -0,0 +1,16 @@
+#ifndef SDHI_H
+#define SDHI_H
+
+/**************************************************
+ *
+ * CPU specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_ARCH_SH7372
+#include "mach/sdhi-sh7372.h"
+#else
+#error "unsupported CPU."
+#endif
+
+#endif /* SDHI_H */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index df20d7670172..ce595cee86cd 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -12,6 +12,7 @@
#define __ASM_SH7372_H__
#include <linux/sh_clk.h>
+#include <linux/pm_domain.h>
/*
* Pin Function Controller:
@@ -470,4 +471,32 @@ extern struct clk sh7372_fsibck_clk;
extern struct clk sh7372_fsidiva_clk;
extern struct clk sh7372_fsidivb_clk;
+struct platform_device;
+
+struct sh7372_pm_domain {
+ struct generic_pm_domain genpd;
+ unsigned int bit_shift;
+};
+
+static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
+{
+ return container_of(d, struct sh7372_pm_domain, genpd);
+}
+
+#ifdef CONFIG_PM
+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_a3rv;
+extern struct sh7372_pm_domain sh7372_a3ri;
+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);
+#else
+#define sh7372_init_pm_domain(pd) do { } while(0)
+#define sh7372_add_device_to_domain(pd, pdev) do { } while(0)
+#endif /* CONFIG_PM */
+
#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index f3888feb1c68..66f980625a33 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -64,10 +64,5 @@ void __init smp_init_cpus(void)
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
-
shmobile_smp_prepare_cpus();
}
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 8e4aadf14c9f..933fb411be0f 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -15,16 +15,176 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/tlbflush.h>
#include <mach/common.h>
+#include <mach/sh7372.h>
#define SMFRAM 0xe6a70000
#define SYSTBCR 0xe6150024
#define SBAR 0xe6180020
#define APARMBAREA 0xe6f10020
+#define SPDCR 0xe6180008
+#define SWUCR 0xe6180014
+#define PSTR 0xe6180080
+
+#define PSTR_RETRIES 100
+#define PSTR_DELAY_US 10
+
+#ifdef CONFIG_PM
+
+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 (__raw_readl(PSTR) & mask) {
+ unsigned int retry_count;
+
+ __raw_writel(mask, SPDCR);
+
+ for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
+ if (!(__raw_readl(SPDCR) & mask))
+ break;
+ cpu_relax();
+ }
+ }
+
+ pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
+ mask, __raw_readl(PSTR));
+
+ return 0;
+}
+
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+ struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
+ unsigned int mask = 1 << sh7372_pd->bit_shift;
+ unsigned int retry_count;
+ int ret = 0;
+
+ if (__raw_readl(PSTR) & mask)
+ goto out;
+
+ __raw_writel(mask, SWUCR);
+
+ for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
+ if (!(__raw_readl(SWUCR) & mask))
+ goto out;
+ if (retry_count > PSTR_RETRIES)
+ udelay(PSTR_DELAY_US);
+ else
+ cpu_relax();
+ }
+ if (__raw_readl(SWUCR) & mask)
+ ret = -EIO;
+
+ out:
+ pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
+ mask, __raw_readl(PSTR));
+
+ return ret;
+}
+
+static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
+{
+ int ret = pd_power_up(genpd);
+
+ /* force A4LC on after A3RV has been requested on */
+ pm_genpd_poweron(&sh7372_a4lc.genpd);
+
+ return ret;
+}
+
+static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
+{
+ 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;
+}
+
+static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
+{
+ /* only power down A4LC if A3RV is off */
+ if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
+ return pd_power_down(genpd);
+
+ return -EBUSY;
+}
+
+static bool pd_active_wakeup(struct device *dev)
+{
+ return true;
+}
+
+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);
+ genpd->stop_device = pm_clk_suspend;
+ genpd->start_device = pm_clk_resume;
+ 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_on(&sh7372_pd->genpd);
+}
+
+void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
+ struct platform_device *pdev)
+{
+ 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);
+}
+
+struct sh7372_pm_domain sh7372_a4lc = {
+ .bit_shift = 1,
+};
+
+struct sh7372_pm_domain sh7372_a4mp = {
+ .bit_shift = 2,
+};
+
+struct sh7372_pm_domain sh7372_d4 = {
+ .bit_shift = 3,
+};
+
+struct sh7372_pm_domain sh7372_a3rv = {
+ .bit_shift = 6,
+};
+
+struct sh7372_pm_domain sh7372_a3ri = {
+ .bit_shift = 8,
+};
+
+struct sh7372_pm_domain sh7372_a3sg = {
+ .bit_shift = 13,
+};
+
+#endif /* CONFIG_PM */
+
static void sh7372_enter_core_standby(void)
{
void __iomem *smfram = (void __iomem *)SMFRAM;
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
index 2d1b67a59e4a..6ec454e1e063 100644
--- a/arch/arm/mach-shmobile/pm_runtime.c
+++ b/arch/arm/mach-shmobile/pm_runtime.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/sh_clk.h>
@@ -28,31 +29,38 @@ static int default_platform_runtime_idle(struct device *dev)
return pm_runtime_suspend(dev);
}
-static struct dev_power_domain default_power_domain = {
+static struct dev_pm_domain default_pm_domain = {
.ops = {
- .runtime_suspend = pm_runtime_clk_suspend,
- .runtime_resume = pm_runtime_clk_resume,
+ .runtime_suspend = pm_clk_suspend,
+ .runtime_resume = pm_clk_resume,
.runtime_idle = default_platform_runtime_idle,
USE_PLATFORM_PM_SLEEP_OPS
},
};
-#define DEFAULT_PWR_DOMAIN_PTR (&default_power_domain)
+#define DEFAULT_PM_DOMAIN_PTR (&default_pm_domain)
#else
-#define DEFAULT_PWR_DOMAIN_PTR NULL
+#define DEFAULT_PM_DOMAIN_PTR NULL
#endif /* CONFIG_PM_RUNTIME */
static struct pm_clk_notifier_block platform_bus_notifier = {
- .pwr_domain = DEFAULT_PWR_DOMAIN_PTR,
+ .pm_domain = DEFAULT_PM_DOMAIN_PTR,
.con_ids = { NULL, },
};
static int __init sh_pm_runtime_init(void)
{
- pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+ pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
return 0;
}
core_initcall(sh_pm_runtime_init);
+
+static int __init sh_pm_runtime_late_init(void)
+{
+ pm_genpd_poweroff_unused();
+ return 0;
+}
+late_initcall(sh_pm_runtime_late_init);
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index cd807eea69e2..79f0413d8725 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -841,11 +841,22 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
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_a3rv);
+ sh7372_init_pm_domain(&sh7372_a3ri);
+ sh7372_init_pm_domain(&sh7372_a3sg);
+
platform_add_devices(sh7372_early_devices,
ARRAY_SIZE(sh7372_early_devices));
platform_add_devices(sh7372_late_devices,
ARRAY_SIZE(sh7372_late_devices));
+
+ 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);
}
void __init sh7372_add_early_devices(void)
diff --git a/arch/arm/mach-spear3xx/include/mach/clkdev.h b/arch/arm/mach-spear3xx/include/mach/clkdev.h
deleted file mode 100644
index a3d07339d9f1..000000000000
--- a/arch/arm/mach-spear3xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/clkdev.h
- *
- * Clock Dev framework definitions 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_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-#include <plat/clkdev.h>
-
-#endif /* __MACH_CLKDEV_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/clkdev.h b/arch/arm/mach-spear6xx/include/mach/clkdev.h
deleted file mode 100644
index 05676bf440d3..000000000000
--- a/arch/arm/mach-spear6xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/clkdev.h
- *
- * Clock Dev framework definitions for SPEAr6xx 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_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-#include <plat/clkdev.h>
-
-#endif /* __MACH_CLKDEV_H */
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 823c703e573c..ed58ef9019b5 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -4,7 +4,6 @@ obj-y += io.o
obj-y += irq.o
obj-y += clock.o
obj-y += timer.o
-obj-y += gpio.o
obj-y += pinmux.o
obj-y += powergate.o
obj-y += fuse.o
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 30e18bc60647..846cd7d69e3e 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -25,7 +25,6 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
#include <sound/wm8903.h>
@@ -83,22 +82,6 @@ static struct platform_device harmony_audio_device = {
},
};
-static struct tegra_i2c_platform_data harmony_i2c1_platform_data = {
- .bus_clk_rate = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_i2c2_platform_data = {
- .bus_clk_rate = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_i2c3_platform_data = {
- .bus_clk_rate = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_dvc_platform_data = {
- .bus_clk_rate = 400000,
-};
-
static struct wm8903_platform_data harmony_wm8903_pdata = {
.irq_active_low = 0,
.micdet_cfg = 0,
@@ -121,11 +104,6 @@ static struct i2c_board_info __initdata wm8903_board_info = {
static void __init harmony_i2c_init(void)
{
- tegra_i2c_device1.dev.platform_data = &harmony_i2c1_platform_data;
- tegra_i2c_device2.dev.platform_data = &harmony_i2c2_platform_data;
- tegra_i2c_device3.dev.platform_data = &harmony_i2c3_platform_data;
- tegra_i2c_device4.dev.platform_data = &harmony_dvc_platform_data;
-
platform_device_register(&tegra_i2c_device1);
platform_device_register(&tegra_i2c_device2);
platform_device_register(&tegra_i2c_device3);
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index 2643d1bd568b..bdd2627dd87b 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -141,12 +141,10 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
};
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_GPIO_SD4_CD, .enable = true },
- { .gpio = TEGRA_GPIO_SD4_WP, .enable = true },
- { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true },
+ { .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 },
};
void paz00_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 57e50a823eec..ea2f79c9879b 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -25,6 +25,7 @@
#include <linux/dma-mapping.h>
#include <linux/pda_power.h>
#include <linux/io.h>
+#include <linux/i2c.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -34,6 +35,7 @@
#include <mach/iomap.h>
#include <mach/irqs.h>
#include <mach/sdhci.h>
+#include <mach/gpio.h>
#include "board.h"
#include "board-paz00.h"
@@ -66,10 +68,22 @@ static struct platform_device debug_uart = {
static struct platform_device *paz00_devices[] __initdata = {
&debug_uart,
&tegra_sdhci_device1,
- &tegra_sdhci_device2,
&tegra_sdhci_device4,
};
+static void paz00_i2c_init(void)
+{
+ platform_device_register(&tegra_i2c_device1);
+ platform_device_register(&tegra_i2c_device2);
+ platform_device_register(&tegra_i2c_device4);
+}
+
+static void paz00_usb_init(void)
+{
+ platform_device_register(&tegra_ehci2_device);
+ platform_device_register(&tegra_ehci3_device);
+}
+
static void __init tegra_paz00_fixup(struct machine_desc *desc,
struct tag *tags, char **cmdline, struct meminfo *mi)
{
@@ -84,23 +98,16 @@ static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
{ NULL, NULL, 0, 0},
};
-
static struct tegra_sdhci_platform_data sdhci_pdata1 = {
.cd_gpio = TEGRA_GPIO_SD1_CD,
.wp_gpio = TEGRA_GPIO_SD1_WP,
.power_gpio = TEGRA_GPIO_SD1_POWER,
};
-static struct tegra_sdhci_platform_data sdhci_pdata2 = {
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
- .cd_gpio = TEGRA_GPIO_SD4_CD,
- .wp_gpio = TEGRA_GPIO_SD4_WP,
- .power_gpio = TEGRA_GPIO_SD4_POWER,
.is_8bit = 1,
};
@@ -111,13 +118,15 @@ static void __init tegra_paz00_init(void)
paz00_pinmux_init();
tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
- tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices));
+
+ paz00_i2c_init();
+ paz00_usb_init();
}
-MACHINE_START(PAZ00, "paz00")
+MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
.boot_params = 0x00000100,
.fixup = tegra_paz00_fixup,
.map_io = tegra_map_common_io,
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
index da193ca76d3b..d4ff39ddaeb3 100644
--- a/arch/arm/mach-tegra/board-paz00.h
+++ b/arch/arm/mach-tegra/board-paz00.h
@@ -17,12 +17,10 @@
#ifndef _MACH_TEGRA_BOARD_PAZ00_H
#define _MACH_TEGRA_BOARD_PAZ00_H
-#define TEGRA_GPIO_SD1_CD TEGRA_GPIO_PV5
-#define TEGRA_GPIO_SD1_WP TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PT3
-#define TEGRA_GPIO_SD4_CD TEGRA_GPIO_PH2
-#define TEGRA_GPIO_SD4_WP TEGRA_GPIO_PH3
-#define TEGRA_GPIO_SD4_POWER TEGRA_GPIO_PI6
+#define TEGRA_GPIO_SD1_CD TEGRA_GPIO_PV5
+#define TEGRA_GPIO_SD1_WP TEGRA_GPIO_PH1
+#define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PT3
+#define TEGRA_ULPI_RST TEGRA_GPIO_PV0
void paz00_pinmux_init(void);
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index a8d7ace9f958..56cbabf6aa68 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -19,7 +19,6 @@
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/io.h>
@@ -66,22 +65,6 @@ static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
{ NULL, NULL, 0, 0},
};
-static struct tegra_i2c_platform_data seaboard_i2c1_platform_data = {
- .bus_clk_rate = 400000.
-};
-
-static struct tegra_i2c_platform_data seaboard_i2c2_platform_data = {
- .bus_clk_rate = 400000,
-};
-
-static struct tegra_i2c_platform_data seaboard_i2c3_platform_data = {
- .bus_clk_rate = 400000,
-};
-
-static struct tegra_i2c_platform_data seaboard_dvc_platform_data = {
- .bus_clk_rate = 400000,
-};
-
static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
{
.code = SW_LID,
@@ -137,9 +120,9 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
static struct platform_device *seaboard_devices[] __initdata = {
&debug_uart,
&tegra_pmu_device,
- &tegra_sdhci_device1,
- &tegra_sdhci_device3,
&tegra_sdhci_device4,
+ &tegra_sdhci_device3,
+ &tegra_sdhci_device1,
&seaboard_gpio_keys_device,
};
@@ -159,12 +142,7 @@ static void __init seaboard_i2c_init(void)
i2c_register_board_info(0, &isl29018_device, 1);
- i2c_register_board_info(4, &adt7461_device, 1);
-
- tegra_i2c_device1.dev.platform_data = &seaboard_i2c1_platform_data;
- tegra_i2c_device2.dev.platform_data = &seaboard_i2c2_platform_data;
- tegra_i2c_device3.dev.platform_data = &seaboard_i2c3_platform_data;
- tegra_i2c_device4.dev.platform_data = &seaboard_dvc_platform_data;
+ i2c_register_board_info(3, &adt7461_device, 1);
platform_device_register(&tegra_i2c_device1);
platform_device_register(&tegra_i2c_device2);
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index 13534fa08abf..47c596cdbf32 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -29,13 +29,13 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, 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_DAP3, TEGRA_MUX_DAP3, 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_TRISTATE},
{TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -126,7 +126,7 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
@@ -145,6 +145,9 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
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 */
+
+ { .gpio = TRIMSLICE_GPIO_USB1_MODE, .enable = true }, /* USB1 mode */
+ { .gpio = TRIMSLICE_GPIO_USB2_RST, .enable = true }, /* USB2 PHY rst */
};
void __init trimslice_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index cda4cfd78e84..89a6d2adc1de 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -23,6 +23,8 @@
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -30,6 +32,7 @@
#include <mach/iomap.h>
#include <mach/sdhci.h>
+#include <mach/gpio.h>
#include "board.h"
#include "clock.h"
@@ -71,12 +74,58 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
.power_gpio = -1,
};
+static struct platform_device trimslice_audio_device = {
+ .name = "tegra-snd-trimslice",
+ .id = 0,
+};
+
static struct platform_device *trimslice_devices[] __initdata = {
&debug_uart,
&tegra_sdhci_device1,
&tegra_sdhci_device4,
+ &tegra_i2s_device1,
+ &tegra_das_device,
+ &tegra_pcm_device,
+ &trimslice_audio_device,
};
+static struct i2c_board_info trimslice_i2c3_board_info[] = {
+ {
+ I2C_BOARD_INFO("tlv320aic23", 0x1a),
+ },
+ {
+ I2C_BOARD_INFO("em3027", 0x56),
+ },
+};
+
+static void trimslice_i2c_init(void)
+{
+ platform_device_register(&tegra_i2c_device1);
+ platform_device_register(&tegra_i2c_device2);
+ platform_device_register(&tegra_i2c_device3);
+
+ i2c_register_board_info(2, trimslice_i2c3_board_info,
+ ARRAY_SIZE(trimslice_i2c3_board_info));
+}
+
+static void trimslice_usb_init(void)
+{
+ int err;
+
+ platform_device_register(&tegra_ehci3_device);
+
+ platform_device_register(&tegra_ehci2_device);
+
+ err = gpio_request_one(TRIMSLICE_GPIO_USB1_MODE, GPIOF_OUT_INIT_HIGH,
+ "usb1mode");
+ if (err) {
+ pr_err("TrimSlice: failed to obtain USB1 mode gpio: %d\n", err);
+ return;
+ }
+
+ platform_device_register(&tegra_ehci1_device);
+}
+
static void __init tegra_trimslice_fixup(struct machine_desc *desc,
struct tag *tags, char **cmdline, struct meminfo *mi)
{
@@ -90,6 +139,10 @@ static void __init tegra_trimslice_fixup(struct machine_desc *desc,
static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
/* name parent rate enabled */
{ "uarta", "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},
{ NULL, NULL, 0, 0},
};
@@ -112,6 +165,9 @@ static void __init tegra_trimslice_init(void)
tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
+
+ trimslice_i2c_init();
+ trimslice_usb_init();
}
MACHINE_START(TRIMSLICE, "trimslice")
diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h
index e8ef6291c6f1..7a7dee86b4da 100644
--- a/arch/arm/mach-tegra/board-trimslice.h
+++ b/arch/arm/mach-tegra/board-trimslice.h
@@ -20,6 +20,9 @@
#define TRIMSLICE_GPIO_SD4_CD TEGRA_GPIO_PP1 /* mmc4 cd */
#define TRIMSLICE_GPIO_SD4_WP TEGRA_GPIO_PP2 /* mmc4 wp */
+#define TRIMSLICE_GPIO_USB1_MODE TEGRA_GPIO_PV2 /* USB1 mode */
+#define TRIMSLICE_GPIO_USB2_RST TEGRA_GPIO_PV0 /* USB2 PHY reset */
+
void trimslice_pinmux_init(void);
#endif
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index e028320ab423..f8d41ffc0ca9 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -585,7 +585,7 @@ static const struct file_operations possible_parents_fops = {
static int clk_debugfs_register_one(struct clk *c)
{
- struct dentry *d, *child, *child_tmp;
+ struct dentry *d;
d = debugfs_create_dir(c->name, clk_debugfs_root);
if (!d)
@@ -614,10 +614,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;
err_out:
- d = c->dent;
- list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(c->dent);
+ debugfs_remove_recursive(c->dent);
return -ENOMEM;
}
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 1528f9daef1f..57e35d20c24c 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -22,10 +22,14 @@
#include <linux/dma-mapping.h>
#include <linux/fsl_devices.h>
#include <linux/serial_8250.h>
+#include <linux/i2c-tegra.h>
+#include <linux/platform_data/tegra_usb.h>
#include <asm/pmu.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dma.h>
+#include <mach/usb_phy.h>
+#include "gpio-names.h"
static struct resource i2c_resource1[] = {
[0] = {
@@ -79,13 +83,29 @@ static struct resource i2c_resource4[] = {
},
};
+static struct tegra_i2c_platform_data tegra_i2c1_platform_data = {
+ .bus_clk_rate = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_i2c2_platform_data = {
+ .bus_clk_rate = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_i2c3_platform_data = {
+ .bus_clk_rate = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_dvc_platform_data = {
+ .bus_clk_rate = 400000,
+};
+
struct platform_device tegra_i2c_device1 = {
.name = "tegra-i2c",
.id = 0,
.resource = i2c_resource1,
.num_resources = ARRAY_SIZE(i2c_resource1),
.dev = {
- .platform_data = 0,
+ .platform_data = &tegra_i2c1_platform_data,
},
};
@@ -95,7 +115,7 @@ struct platform_device tegra_i2c_device2 = {
.resource = i2c_resource2,
.num_resources = ARRAY_SIZE(i2c_resource2),
.dev = {
- .platform_data = 0,
+ .platform_data = &tegra_i2c2_platform_data,
},
};
@@ -105,7 +125,7 @@ struct platform_device tegra_i2c_device3 = {
.resource = i2c_resource3,
.num_resources = ARRAY_SIZE(i2c_resource3),
.dev = {
- .platform_data = 0,
+ .platform_data = &tegra_i2c3_platform_data,
},
};
@@ -115,7 +135,7 @@ struct platform_device tegra_i2c_device4 = {
.resource = i2c_resource4,
.num_resources = ARRAY_SIZE(i2c_resource4),
.dev = {
- .platform_data = 0,
+ .platform_data = &tegra_dvc_platform_data,
},
};
@@ -334,6 +354,28 @@ static struct resource tegra_usb3_resources[] = {
},
};
+static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+ /* All existing boards use GPIO PV0 for phy reset */
+ .reset_gpio = TEGRA_GPIO_PV0,
+ .clk = "cdev2",
+};
+
+static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
+ .operating_mode = TEGRA_USB_OTG,
+ .power_down_on_bus_suspend = 1,
+};
+
+static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
+ .phy_config = &tegra_ehci2_ulpi_phy_config,
+ .operating_mode = TEGRA_USB_HOST,
+ .power_down_on_bus_suspend = 1,
+};
+
+static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
+ .operating_mode = TEGRA_USB_HOST,
+ .power_down_on_bus_suspend = 1,
+};
+
static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
struct platform_device tegra_ehci1_device = {
@@ -342,6 +384,7 @@ struct platform_device tegra_ehci1_device = {
.dev = {
.dma_mask = &tegra_ehci_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &tegra_ehci1_pdata,
},
.resource = tegra_usb1_resources,
.num_resources = ARRAY_SIZE(tegra_usb1_resources),
@@ -353,6 +396,7 @@ struct platform_device tegra_ehci2_device = {
.dev = {
.dma_mask = &tegra_ehci_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &tegra_ehci2_pdata,
},
.resource = tegra_usb2_resources,
.num_resources = ARRAY_SIZE(tegra_usb2_resources),
@@ -364,6 +408,7 @@ struct platform_device tegra_ehci3_device = {
.dev = {
.dma_mask = &tegra_ehci_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &tegra_ehci3_pdata,
},
.resource = tegra_usb3_resources,
.num_resources = ARRAY_SIZE(tegra_usb3_resources),
diff --git a/arch/arm/mach-tegra/include/mach/barriers.h b/arch/arm/mach-tegra/include/mach/barriers.h
deleted file mode 100644
index 425b42e91ef6..000000000000
--- a/arch/arm/mach-tegra/include/mach/barriers.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * arch/arm/mach-realview/include/mach/barriers.h
- *
- * Copyright (C) 2010 ARM Ltd.
- * Written by Catalin Marinas <catalin.marinas@arm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __MACH_BARRIERS_H
-#define __MACH_BARRIERS_H
-
-#include <asm/outercache.h>
-
-#define rmb() dsb()
-#define wmb() do { dsb(); outer_sync(); } while (0)
-#define mb() wmb()
-
-#endif /* __MACH_BARRIERS_H */
diff --git a/arch/arm/mach-tegra/include/mach/system.h b/arch/arm/mach-tegra/include/mach/system.h
index d0183d876c3b..027c4215d313 100644
--- a/arch/arm/mach-tegra/include/mach/system.h
+++ b/arch/arm/mach-tegra/include/mach/system.h
@@ -21,7 +21,6 @@
#ifndef __MACH_TEGRA_SYSTEM_H
#define __MACH_TEGRA_SYSTEM_H
-#include <mach/hardware.h>
#include <mach/iomap.h>
extern void (*arch_reset)(char mode, const char *cmd);
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index 31848a9592f8..ea50fe28cf6a 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -24,7 +24,6 @@
#include <linux/mm.h>
#include <linux/io.h>
-#include <mach/hardware.h>
#include <asm/page.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 2941212b853c..031cd0a7d71d 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -912,6 +912,8 @@ int __init tegra_pcie_init(bool init_port0, bool init_port1)
if (!(init_port0 || init_port1))
return -ENODEV;
+ pcibios_min_mem = 0;
+
err = tegra_pcie_get_resources();
if (err)
return err;
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index b8ae3c978dee..0886cbccddee 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -21,7 +21,6 @@
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
-#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/smp_scu.h>
@@ -122,21 +121,13 @@ void __init smp_init_cpus(void)
}
for (i = 0; i < ncores; i++)
- cpu_set(i, cpu_possible_map);
+ set_cpu_possible(i, true);
set_smp_cross_call(gic_raise_softirq);
}
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- /*
- * Initialise the present map, which describes the set of CPUs
- * actually populated at the present time.
- */
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
scu_enable(scu_base);
}
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index bb618075fab6..0fe9b3ee2947 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -2182,8 +2182,8 @@ struct clk tegra_list_clks[] = {
PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */
PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */
PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */
- PERIPH_CLK("disp1", "tegradc.0", NULL, 27, 0x138, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */
- PERIPH_CLK("disp2", "tegradc.1", NULL, 26, 0x13c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */
+ PERIPH_CLK("disp1", "tegradc.0", NULL, 27, 0x138, 600000000, mux_pllp_plld_pllc_clkm, MUX), /* scales with voltage and process_id */
+ PERIPH_CLK("disp2", "tegradc.1", NULL, 26, 0x13c, 600000000, mux_pllp_plld_pllc_clkm, MUX), /* scales with voltage and process_id */
PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 513d6abec1f5..399c89f14dfb 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1791,7 +1791,7 @@ static void __init u300_assign_physmem(void)
0 == res->start) {
res->start = curr_start;
res->end += curr_start;
- curr_start += (res->end - res->start + 1);
+ curr_start += resource_size(res);
printk(KERN_INFO "core.c: Mapping RAM " \
"%#x-%#x to device %s:%s\n",
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index 5767208f1c1d..7b597e2b19e2 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -40,8 +40,8 @@ struct pl022_config_chip dummy_chip_info = {
.hierarchy = SSP_MASTER,
/* 0 = drive TX even as slave, 1 = do not drive TX as slave */
.slave_tx_disable = 0,
- .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
- .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
+ .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
+ .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
.ctrl_len = SSP_BITS_12,
.wait_state = SSP_MWIRE_WAIT_ZERO,
.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index 18d7fa0603c2..5f51bdeef0ef 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -27,9 +27,6 @@
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
-/* Be able to sleep for atleast 4 seconds (usually more) */
-#define APPTIMER_MIN_RANGE 4
-
/*
* APP side special timer registers
* This timer contains four timers which can fire an interrupt each.
@@ -309,11 +306,11 @@ static int u300_set_next_event(unsigned long cycles,
/* Use general purpose timer 1 as clock event */
static struct clock_event_device clockevent_u300_1mhz = {
- .name = "GPT1",
- .rating = 300, /* Reasonably fast and accurate clock event */
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = u300_set_next_event,
- .set_mode = u300_set_mode,
+ .name = "GPT1",
+ .rating = 300, /* Reasonably fast and accurate clock event */
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = u300_set_next_event,
+ .set_mode = u300_set_mode,
};
/* Clock event timer interrupt handler */
@@ -328,9 +325,9 @@ static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
}
static struct irqaction u300_timer_irq = {
- .name = "U300 Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = u300_timer_interrupt,
+ .name = "U300 Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = u300_timer_interrupt,
};
/*
@@ -413,16 +410,10 @@ static void __init u300_timer_init(void)
"GPT2", rate, 300, 32, clocksource_mmio_readl_up))
pr_err("timer: failed to initialize U300 clock source\n");
- clockevents_calc_mult_shift(&clockevent_u300_1mhz,
- rate, APPTIMER_MIN_RANGE);
- /* 32bit counter, so 32bits delta is max */
- clockevent_u300_1mhz.max_delta_ns =
- clockevent_delta2ns(0xffffffff, &clockevent_u300_1mhz);
- /* This timer is slow enough to set for 1 cycle == 1 MHz */
- clockevent_u300_1mhz.min_delta_ns =
- clockevent_delta2ns(1, &clockevent_u300_1mhz);
- clockevent_u300_1mhz.cpumask = cpumask_of(0);
- clockevents_register_device(&clockevent_u300_1mhz);
+ /* Configure and register the clockevent */
+ clockevents_config_and_register(&clockevent_u300_1mhz, rate,
+ 1, 0xffffffff);
+
/*
* TODO: init and register the rest of the timers too, they can be
* used by hrtimers!
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index f8b9392ee347..4210cb434dbc 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -20,7 +20,7 @@ config UX500_SOC_DB8500
endmenu
-menu "Ux500 target platform"
+menu "Ux500 target platform (boards)"
config MACH_U8500
bool "U8500 Development platform"
@@ -29,6 +29,19 @@ config MACH_U8500
help
Include support for the mop500 development platform.
+config MACH_HREFV60
+ bool "U85000 Development platform, HREFv60 version"
+ depends on UX500_SOC_DB8500
+ help
+ Include support for the HREFv60 new development platform.
+
+config MACH_SNOWBALL
+ bool "U8500 Snowball platform"
+ depends on UX500_SOC_DB8500
+ select MACH_U8500
+ help
+ Include support for the snowball development platform.
+
config MACH_U5500
bool "U5500 Development platform"
depends on UX500_SOC_DB5500
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index 70cdbd60596a..f26fd76f72b4 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -236,6 +236,46 @@ static pin_cfg_t mop500_pins_hrefv60[] = {
};
+static pin_cfg_t snowball_pins[] = {
+ /* SSP0, to AB8500 */
+ GPIO143_SSP0_CLK,
+ GPIO144_SSP0_FRM,
+ GPIO145_SSP0_RXD | PIN_PULL_DOWN,
+ GPIO146_SSP0_TXD,
+
+ /* MMC0: MicroSD card */
+ GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH,
+
+ /* MMC2: LAN */
+ GPIO86_SM_ADQ0,
+ GPIO87_SM_ADQ1,
+ GPIO88_SM_ADQ2,
+ GPIO89_SM_ADQ3,
+ GPIO90_SM_ADQ4,
+ GPIO91_SM_ADQ5,
+ GPIO92_SM_ADQ6,
+ GPIO93_SM_ADQ7,
+
+ GPIO94_SM_ADVn,
+ GPIO95_SM_CS0n,
+ GPIO96_SM_OEn,
+ GPIO97_SM_WEn,
+
+ GPIO128_SM_CKO,
+ GPIO130_SM_FBCLK,
+ GPIO131_SM_ADQ8,
+ GPIO132_SM_ADQ9,
+ GPIO133_SM_ADQ10,
+ GPIO134_SM_ADQ11,
+ GPIO135_SM_ADQ12,
+ GPIO136_SM_ADQ13,
+ GPIO137_SM_ADQ14,
+ GPIO138_SM_ADQ15,
+
+ /* RSTn_LAN */
+ GPIO141_GPIO | PIN_OUTPUT_HIGH,
+};
+
void __init mop500_pins_init(void)
{
nmk_config_pins(mop500_pins_common,
@@ -243,6 +283,9 @@ void __init mop500_pins_init(void)
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));
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 9ed0f90cfe23..2735d03996cf 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -77,7 +77,7 @@ static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
/* SoC core supply, no device */
REGULATOR_SUPPLY("v-intcore", NULL),
- /* USB Transciever */
+ /* USB Transceiver */
REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
};
@@ -272,7 +272,14 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
.max_uV = 2900000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
- .boot_on = 1, /* must be on for display */
+ .boot_on = 1, /* display is on at boot */
+ /*
+ * This voltage cannot be disabled right now because
+ * it is somehow affecting the external MMC
+ * functionality, though that typically will use
+ * AUX3.
+ */
+ .always_on = 1,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
.consumer_supplies = ab8500_vaux1_consumers,
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 7c6cb4fa47a9..d0cb9e5eb87c 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -32,13 +32,32 @@
#define MCI_DATA31DIREN (1 << 5)
#define MCI_FBCLKEN (1 << 7)
+/* GPIO pins used by the sdi0 level shifter */
+static int sdi0_en = -1;
+static int sdi0_vsel = -1;
+
static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
unsigned char power_mode)
{
- if (power_mode == MMC_POWER_UP)
- gpio_set_value_cansleep(GPIO_SDMMC_EN, 1);
- else if (power_mode == MMC_POWER_OFF)
- gpio_set_value_cansleep(GPIO_SDMMC_EN, 0);
+ switch (power_mode) {
+ case MMC_POWER_UP:
+ case MMC_POWER_ON:
+ /*
+ * Level shifter voltage should depend on vdd to when deciding
+ * on either 1.8V or 2.9V. Once the decision has been made the
+ * level shifter must be disabled and re-enabled with a changed
+ * select signal in order to switch the voltage. Since there is
+ * no framework support yet for indicating 1.8V in vdd, use the
+ * default 2.9V.
+ */
+ gpio_direction_output(sdi0_vsel, 0);
+ gpio_direction_output(sdi0_en, 1);
+ break;
+ case MMC_POWER_OFF:
+ gpio_direction_output(sdi0_vsel, 0);
+ gpio_direction_output(sdi0_en, 0);
+ break;
+ }
return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
MCI_DATA2DIREN | MCI_DATA31DIREN;
@@ -67,8 +86,10 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
static struct mmci_platform_data mop500_sdi0_data = {
.vdd_handler = mop500_sdi0_vdd_handler,
.ocr_mask = MMC_VDD_29_30,
- .f_max = 100000000,
- .capabilities = MMC_CAP_4_BIT_DATA,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_SD_HIGHSPEED |
+ MMC_CAP_MMC_HIGHSPEED,
.gpio_wp = -1,
#ifdef CONFIG_STE_DMA40
.dma_filter = stedma40_filter,
@@ -77,10 +98,6 @@ static struct mmci_platform_data mop500_sdi0_data = {
#endif
};
-/* GPIO pins used by the sdi0 level shifter */
-static int sdi0_en = -1;
-static int sdi0_vsel = -1;
-
static void sdi0_configure(void)
{
int ret;
@@ -140,7 +157,7 @@ static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
static struct mmci_platform_data mop500_sdi2_data = {
.ocr_mask = MMC_VDD_165_195,
- .f_max = 100000000,
+ .f_max = 50000000,
.capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
.gpio_cd = -1,
.gpio_wp = -1,
@@ -177,7 +194,7 @@ static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
static struct mmci_platform_data mop500_sdi4_data = {
.ocr_mask = MMC_VDD_29_30,
- .f_max = 100000000,
+ .f_max = 50000000,
.capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED,
.gpio_cd = -1,
@@ -199,17 +216,27 @@ 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;
- db8500_add_sdi2(&mop500_sdi2_data, periphid);
+ /* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
+ if (!machine_is_snowball())
+ db8500_add_sdi2(&mop500_sdi2_data, periphid);
/* On-board eMMC */
db8500_add_sdi4(&mop500_sdi4_data, periphid);
- 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;
+ 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
diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c
index d8a8734a0eba..8ce46c0fdfd5 100644
--- a/arch/arm/mach-ux500/board-mop500-u8500uib.c
+++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c
@@ -12,34 +12,14 @@
#include <linux/interrupt.h>
#include <linux/mfd/tc3589x.h>
#include <linux/input/matrix_keypad.h>
-#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
#include "board-mop500.h"
-/*
- * Synaptics RMI4 touchscreen interface on the U8500 UIB
- */
-
-/*
- * Descriptor structure.
- * Describes the number of i2c devices on the bus that speak RMI.
- */
-static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = {
- .irq_number = NOMADIK_GPIO_TO_IRQ(84),
- .irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
- .x_flip = false,
- .y_flip = true,
- .regulator_en = false,
-};
-
-static struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = {
- {
- I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
- .platform_data = &rmi4_i2c_dev_platformdata,
- },
+/* Dummy data that can be overridden by staging driver */
+struct i2c_board_info __initdata __weak mop500_i2c3_devices_u8500[] = {
};
/*
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
index 69cce41f602a..5af36aa56c08 100644
--- a/arch/arm/mach-ux500/board-mop500-uib.c
+++ b/arch/arm/mach-ux500/board-mop500-uib.c
@@ -25,7 +25,7 @@ struct uib {
void (*init)(void);
};
-static struct __initdata uib mop500_uibs[] = {
+static struct uib __initdata mop500_uibs[] = {
[STUIB] = {
.name = "ST-UIB",
.option = "stuib",
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 2a08c07dec6d..cd54abaccd96 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -26,9 +26,11 @@
#include <linux/mfd/ab8500/gpio.h>
#include <linux/leds-lp5521.h>
#include <linux/input.h>
+#include <linux/smsc911x.h>
#include <linux/gpio_keys.h>
#include <linux/delay.h>
+#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -47,6 +49,26 @@
#include "board-mop500.h"
#include "board-mop500-regulators.h"
+static struct gpio_led snowball_led_array[] = {
+ {
+ .name = "user_led",
+ .default_trigger = "none",
+ .gpio = 142,
+ },
+};
+
+static struct gpio_led_platform_data snowball_led_data = {
+ .leds = snowball_led_array,
+ .num_leds = ARRAY_SIZE(snowball_led_array),
+};
+
+static struct platform_device snowball_led_dev = {
+ .name = "leds-gpio",
+ .dev = {
+ .platform_data = &snowball_led_data,
+ },
+};
+
static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
.gpio_base = MOP500_AB8500_GPIO(0),
.irq_base = MOP500_AB8500_VIR_GPIO_IRQ_BASE,
@@ -69,6 +91,97 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
0x7A, 0x00, 0x00},
};
+static struct gpio_keys_button snowball_key_array[] = {
+ {
+ .gpio = 32,
+ .type = EV_KEY,
+ .code = KEY_1,
+ .desc = "userpb",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ {
+ .gpio = 151,
+ .type = EV_KEY,
+ .code = KEY_2,
+ .desc = "extkb1",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ {
+ .gpio = 152,
+ .type = EV_KEY,
+ .code = KEY_3,
+ .desc = "extkb2",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ {
+ .gpio = 161,
+ .type = EV_KEY,
+ .code = KEY_4,
+ .desc = "extkb3",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ {
+ .gpio = 162,
+ .type = EV_KEY,
+ .code = KEY_5,
+ .desc = "extkb4",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+};
+
+static struct gpio_keys_platform_data snowball_key_data = {
+ .buttons = snowball_key_array,
+ .nbuttons = ARRAY_SIZE(snowball_key_array),
+};
+
+static struct platform_device snowball_key_dev = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &snowball_key_data,
+ }
+};
+
+static struct smsc911x_platform_config snowball_sbnet_cfg = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+ .shift = 1,
+};
+
+static struct resource sbnet_res[] = {
+ {
+ .name = "smsc911x-memory",
+ .start = (0x5000 << 16),
+ .end = (0x5000 << 16) + 0xffff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = NOMADIK_GPIO_TO_IRQ(140),
+ .end = NOMADIK_GPIO_TO_IRQ(140),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ },
+};
+
+static struct platform_device snowball_sbnet_dev = {
+ .name = "smsc911x",
+ .num_resources = ARRAY_SIZE(sbnet_res),
+ .resource = sbnet_res,
+ .dev = {
+ .platform_data = &snowball_sbnet_cfg,
+ },
+};
+
static struct ab8500_platform_data ab8500_platdata = {
.irq_base = MOP500_AB8500_IRQ_BASE,
.regulator_reg_init = ab8500_regulator_reg_init,
@@ -295,8 +408,9 @@ static void mop500_prox_deactivate(struct device *dev)
}
/* add any platform devices here - TODO */
-static struct platform_device *platform_devs[] __initdata = {
+static struct platform_device *mop500_platform_devs[] __initdata = {
&mop500_gpio_keys_device,
+ &ab8500_device,
};
#ifdef CONFIG_STE_DMA40
@@ -478,6 +592,13 @@ static void __init mop500_uart_init(void)
db8500_add_uart2(&uart2_plat);
}
+static struct platform_device *snowball_platform_devs[] __initdata = {
+ &snowball_led_dev,
+ &snowball_key_dev,
+ &snowball_sbnet_dev,
+ &ab8500_device,
+};
+
static void __init mop500_init_machine(void)
{
int i2c0_devs;
@@ -487,24 +608,29 @@ static void __init mop500_init_machine(void)
* all these GPIO pins to the internal GPIO controller
* instead.
*/
- if (machine_is_hrefv60())
- mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
- else
- mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+ 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;
+ }
u8500_init_devices();
mop500_pins_init();
- platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+ 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));
mop500_i2c_init();
mop500_sdi_init();
mop500_spi_init();
mop500_uart_init();
- platform_device_register(&ab8500_device);
-
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
if (machine_is_hrefv60())
i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
@@ -512,6 +638,9 @@ static void __init mop500_init_machine(void)
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();
}
MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
@@ -531,3 +660,12 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
.timer = &ux500_timer,
.init_machine = mop500_init_machine,
MACHINE_END
+
+MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
+ .boot_params = 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,
+MACHINE_END
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index 03a31cc9b084..ee77a8970c33 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -7,6 +7,11 @@
#ifndef __BOARD_MOP500_H
#define __BOARD_MOP500_H
+/* snowball GPIO for MMC card */
+#define SNOWBALL_SDMMC_EN_GPIO 217
+#define SNOWBALL_SDMMC_1V8_3V_GPIO 228
+#define SNOWBALL_SDMMC_CD_GPIO 218
+
/* HREFv60-specific GPIO assignments, this board has no GPIO expander */
#define HREFV60_TOUCH_RST_GPIO 143
#define HREFV60_PROX_SENSE_GPIO 217
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 44fd3b5c33ec..e58f0f562426 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -10,16 +10,97 @@
#include <linux/amba/bus.h>
#include <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/i2c.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
+#include <plat/pincfg.h>
+#include <plat/i2c.h>
+
#include <mach/hardware.h>
#include <mach/devices.h>
#include <mach/setup.h>
+#include "pins-db5500.h"
#include "devices-db5500.h"
+#include <linux/led-lm3530.h>
+
+/*
+ * GPIO
+ */
+
+static pin_cfg_t u5500_pins[] = {
+ /* I2C */
+ GPIO218_I2C2_SCL | PIN_INPUT_PULLUP,
+ GPIO219_I2C2_SDA | PIN_INPUT_PULLUP,
+
+ /* DISPLAY_ENABLE */
+ GPIO226_GPIO | PIN_OUTPUT_LOW,
+
+ /* Backlight Enbale */
+ GPIO224_GPIO | PIN_OUTPUT_HIGH,
+};
+/*
+ * I2C
+ */
+
+#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
+static struct nmk_i2c_controller u5500_i2c##id##_data = { \
+ /* \
+ * slave data setup time, which is \
+ * 250 ns,100ns,10ns which is 14,6,2 \
+ * respectively for a 48 Mhz \
+ * i2c clock \
+ */ \
+ .slsu = _slsu, \
+ /* Tx FIFO threshold */ \
+ .tft = _tft, \
+ /* Rx FIFO threshold */ \
+ .rft = _rft, \
+ /* std. mode operation */ \
+ .clk_freq = clk, \
+ .sm = _sm, \
+}
+/*
+ * The board uses TODO <3> i2c controllers, initialize all of
+ * them with slave data setup time of 250 ns,
+ * Tx & Rx FIFO threshold values as 1 and standard
+ * mode of operation
+ */
+
+U5500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST);
+
+static struct lm3530_platform_data u5500_als_platform_data = {
+ .mode = LM3530_BL_MODE_MANUAL,
+ .als_input_mode = LM3530_INPUT_ALS1,
+ .max_current = LM3530_FS_CURR_26mA,
+ .pwm_pol_hi = true,
+ .als_avrg_time = LM3530_ALS_AVRG_TIME_512ms,
+ .brt_ramp_law = 1, /* Linear */
+ .brt_ramp_fall = LM3530_RAMP_TIME_8s,
+ .brt_ramp_rise = LM3530_RAMP_TIME_8s,
+ .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm,
+ .als2_resistor_sel = LM3530_ALS_IMPD_Z,
+ .als_vmin = 730, /* mV */
+ .als_vmax = 1020, /* mV */
+ .brt_val = 0x7F, /* Max brightness */
+};
+
+static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
+ {
+ /* Backlight */
+ I2C_BOARD_INFO("lm3530-led", 0x36),
+ .platform_data = &u5500_als_platform_data,
+ },
+};
+
+static void __init u5500_i2c_init(void)
+{
+ db5500_add_i2c2(&u5500_i2c2_data);
+ i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
+}
static void __init u5500_uart_init(void)
{
db5500_add_uart0(NULL);
@@ -30,7 +111,8 @@ static void __init u5500_uart_init(void)
static void __init u5500_init_machine(void)
{
u5500_init_devices();
-
+ nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins));
+ u5500_i2c_init();
u5500_sdi_init();
u5500_uart_init();
}
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index 32ce90840ee1..e832664d1bd9 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -14,6 +14,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
+#include <linux/cpufreq.h>
#include <plat/mtu.h>
#include <mach/hardware.h>
@@ -635,16 +636,13 @@ static const struct file_operations set_rate_fops = {
static struct dentry *clk_debugfs_register_dir(struct clk *c,
struct dentry *p_dentry)
{
- struct dentry *d, *clk_d, *child, *child_tmp;
- char s[255];
- char *p = s;
+ struct dentry *d, *clk_d;
+ const char *p = c->name;
- if (c->name == NULL)
- p += sprintf(p, "BUG");
- else
- p += sprintf(p, "%s", c->name);
+ if (!p)
+ p = "BUG";
- clk_d = debugfs_create_dir(s, p_dentry);
+ clk_d = debugfs_create_dir(p, p_dentry);
if (!clk_d)
return NULL;
@@ -666,24 +664,10 @@ static struct dentry *clk_debugfs_register_dir(struct clk *c,
return clk_d;
err_out:
- d = clk_d;
- list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(clk_d);
+ debugfs_remove_recursive(clk_d);
return NULL;
}
-static void clk_debugfs_remove_dir(struct dentry *cdentry)
-{
- struct dentry *d, *child, *child_tmp;
-
- d = cdentry;
- list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(cdentry);
- return ;
-}
-
static int clk_debugfs_register_one(struct clk *c)
{
struct clk *pa = c->parent_periph;
@@ -700,7 +684,7 @@ static int clk_debugfs_register_one(struct clk *c)
c->dent_bus = clk_debugfs_register_dir(c,
bpa->dent_bus ? bpa->dent_bus : bpa->dent);
if ((!c->dent_bus) && (c->dent)) {
- clk_debugfs_remove_dir(c->dent);
+ debugfs_remove_recursive(c->dent);
c->dent = NULL;
return -ENOMEM;
}
@@ -759,6 +743,51 @@ err_out:
late_initcall(clk_debugfs_init);
#endif /* defined(CONFIG_DEBUG_FS) */
+unsigned long clk_smp_twd_rate = 400000000;
+
+unsigned long clk_smp_twd_get_rate(struct clk *clk)
+{
+ return clk_smp_twd_rate;
+}
+
+static struct clk clk_smp_twd = {
+ .get_rate = clk_smp_twd_get_rate,
+ .name = "smp_twd",
+};
+
+static struct clk_lookup clk_smp_twd_lookup = {
+ .dev_id = "smp_twd",
+ .clk = &clk_smp_twd,
+};
+
+#ifdef CONFIG_CPU_FREQ
+
+static int clk_twd_cpufreq_transition(struct notifier_block *nb,
+ unsigned long state, void *data)
+{
+ struct cpufreq_freqs *f = data;
+
+ if (state == CPUFREQ_PRECHANGE) {
+ /* Save frequency in simple Hz */
+ clk_smp_twd_rate = f->new * 1000;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block clk_twd_cpufreq_nb = {
+ .notifier_call = clk_twd_cpufreq_transition,
+};
+
+static int clk_init_smp_twd_cpufreq(void)
+{
+ return cpufreq_register_notifier(&clk_twd_cpufreq_nb,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+late_initcall(clk_init_smp_twd_cpufreq);
+
+#endif
+
int __init clk_init(void)
{
if (cpu_is_u8500ed()) {
@@ -779,6 +808,8 @@ int __init clk_init(void)
else
clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
+ clkdev_add(&clk_smp_twd_lookup);
+
#ifdef CONFIG_DEBUG_FS
clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
if (cpu_is_u8500ed())
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index c01bc19e3c5e..22705d246fc7 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -44,6 +44,7 @@ static struct map_desc u5500_io_desc[] __initdata = {
__IO_DEV_DESC(U5500_GPIO3_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GPIO4_BASE, SZ_4K),
__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_PRCMU_TCDM_BASE, SZ_4K),
};
static struct resource db5500_pmu_resources[] = {
diff --git a/arch/arm/mach-ux500/include/mach/clkdev.h b/arch/arm/mach-ux500/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-ux500/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 088b550c40df..7dd08074c37b 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -54,7 +54,8 @@ static inline void arch_decomp_setup(void)
if (machine_is_u8500() ||
machine_is_svp8500v1() ||
machine_is_svp8500v2() ||
- machine_is_hrefv60())
+ machine_is_hrefv60() ||
+ machine_is_snowball())
ux500_uart_base = U8500_UART2_BASE;
else if (machine_is_u5500())
ux500_uart_base = U5500_UART0_BASE;
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 0c527fe2cebb..a33df5f4c27a 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -172,14 +172,6 @@ void __init smp_init_cpus(void)
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- /*
- * Initialise the present map, which describes the set of CPUs
- * actually populated at the present time.
- */
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
scu_enable(scu_base_addr());
wakeup_secondary();
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c
index 82e535953fd9..0a01cbdfe063 100644
--- a/arch/arm/mach-ux500/usb.c
+++ b/arch/arm/mach-ux500/usb.c
@@ -6,6 +6,7 @@
*/
#include <linux/platform_device.h>
#include <linux/usb/musb.h>
+#include <linux/dma-mapping.h>
#include <plat/ste_dma40.h>
#include <mach/hardware.h>
#include <mach/usb.h>
diff --git a/arch/arm/mach-versatile/include/mach/hardware.h b/arch/arm/mach-versatile/include/mach/hardware.h
index 6911e1f5f156..4d4973dd8fba 100644
--- a/arch/arm/mach-versatile/include/mach/hardware.h
+++ b/arch/arm/mach-versatile/include/mach/hardware.h
@@ -30,12 +30,6 @@
#define VERSATILE_PCI_VIRT_BASE (void __iomem *)0xe8000000ul
#define VERSATILE_PCI_CFG_VIRT_BASE (void __iomem *)0xe9000000ul
-/* CIK guesswork */
-#define PCIBIOS_MIN_IO 0x44000000
-#define PCIBIOS_MIN_MEM 0x50000000
-
-#define pcibios_assign_all_busses() 1
-
/* macro to get at IO space when running virtually */
#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index 13c7e5f90a82..7848a177b1f0 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -311,6 +311,9 @@ struct pci_bus * __init pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
void __init pci_versatile_preinit(void)
{
+ pcibios_min_io = 0x44000000;
+ pcibios_min_mem = 0x50000000;
+
__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28, PCI_IMAP0);
__raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28, PCI_IMAP1);
__raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28, PCI_IMAP2);
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 765a71ff7f3b..bfd32f52c2db 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -229,10 +229,6 @@ static void ct_ca9x4_init_cpu_map(void)
static void ct_ca9x4_smp_enable(unsigned int max_cpus)
{
- int i;
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
-
scu_enable(MMIO_P2V(A9_MPCORE_SCU));
}
#endif
diff --git a/arch/arm/mach-w90x900/include/mach/clkdev.h b/arch/arm/mach-w90x900/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/mach-w90x900/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
new file mode 100644
index 000000000000..c550c67aa893
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o timer.o board_dt.o
diff --git a/arch/arm/mach-loki/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
index 67039c3e0c48..67039c3e0c48 100644
--- a/arch/arm/mach-loki/Makefile.boot
+++ b/arch/arm/mach-zynq/Makefile.boot
diff --git a/arch/arm/mach-zynq/board_dt.c b/arch/arm/mach-zynq/board_dt.c
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/arch/arm/mach-zynq/board_dt.c
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
new file mode 100644
index 000000000000..73e93687b81a
--- /dev/null
+++ b/arch/arm/mach-zynq/common.c
@@ -0,0 +1,118 @@
+/*
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/zynq_soc.h>
+#include <mach/clkdev.h>
+#include "common.h"
+
+static struct of_device_id zynq_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ {}
+};
+
+/**
+ * xilinx_init_machine() - System specific initialization, intended to be
+ * called from board specific initialization.
+ */
+static void __init xilinx_init_machine(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * 64KB way size, 8-way associativity, parity disabled
+ */
+ l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
+#endif
+
+ of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+}
+
+/**
+ * xilinx_irq_init() - Interrupt controller initialization for the GIC.
+ */
+static void __init xilinx_irq_init(void)
+{
+ gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
+}
+
+/* The minimum devices needed to be mapped before the VM system is up and
+ * running include the GIC, UART and Timer Counter.
+ */
+
+static struct map_desc io_desc[] __initdata = {
+ {
+ .virtual = TTC0_VIRT,
+ .pfn = __phys_to_pfn(TTC0_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = SCU_PERIPH_VIRT,
+ .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = PL310_L2CC_VIRT,
+ .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+
+#ifdef CONFIG_DEBUG_LL
+ {
+ .virtual = UART0_VIRT,
+ .pfn = __phys_to_pfn(UART0_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+#endif
+
+};
+
+/**
+ * xilinx_map_io() - Create memory mappings needed for early I/O.
+ */
+static void __init xilinx_map_io(void)
+{
+ iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
+
+static const char *xilinx_dt_match[] = {
+ "xlnx,zynq-ep107",
+ NULL
+};
+
+MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+ .map_io = xilinx_map_io,
+ .init_irq = xilinx_irq_init,
+ .init_machine = xilinx_init_machine,
+ .timer = &xttcpss_sys_timer,
+ .dt_compat = xilinx_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/include/mach/hardware.h b/arch/arm/mach-zynq/common.h
index 56e43b3a5b97..a009644a1555 100644
--- a/arch/arm/mach-tegra/include/mach/hardware.h
+++ b/arch/arm/mach-zynq/common.h
@@ -1,11 +1,8 @@
/*
- * arch/arm/mach-tegra/include/mach/hardware.h
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
*
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@google.com>
- * Erik Gilling <konkers@google.com>
+ * 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
@@ -15,14 +12,13 @@
* but WITHOUT 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_HARDWARE_H
-#define __MACH_TEGRA_HARDWARE_H
+#ifndef __MACH_ZYNQ_COMMON_H__
+#define __MACH_ZYNQ_COMMON_H__
+
+#include <asm/mach/time.h>
-#define PCIBIOS_MIN_IO 0x1000
-#define PCIBIOS_MIN_MEM 0
-#define pcibios_assign_all_busses() 1
+extern struct sys_timer xttcpss_sys_timer;
#endif
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
new file mode 100644
index 000000000000..c6e73d81a459
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/clkdev.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-zynq/include/mach/clkdev.h
+ *
+ * Copyright (C) 2011 Xilinx, 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 __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#include <plat/clock.h>
+
+struct clk {
+ unsigned long rate;
+ const struct clk_ops *ops;
+ const struct icst_params *params;
+ void __iomem *vcoreg;
+};
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
new file mode 100644
index 000000000000..9f664d5eb81d
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/* arch/arm/mach-zynq/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+ .macro addruart, rp, rv
+ ldr \rp, =LL_UART_PADDR @ physical
+ ldr \rv, =LL_UART_VADDR @ virtual
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldr \rd, [\rx, #UART_SR_OFFSET] @ get status register
+ tst \rd, #UART_SR_TXFULL @
+ bne 1002b @ wait if FIFO is full
+ .endm
diff --git a/arch/arm/mach-zynq/include/mach/entry-macro.S b/arch/arm/mach-zynq/include/mach/entry-macro.S
new file mode 100644
index 000000000000..3cfc01b37461
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/entry-macro.S
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-zynq/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * based on arch/plat-mxc/include/mach/entry-macro.S
+ *
+ * Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 <mach/hardware.h>
+#include <asm/hardware/entry-macro-gic.S>
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
new file mode 100644
index 000000000000..d558d8a94be7
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-zynq/include/mach/hardware.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
new file mode 100644
index 000000000000..39d9885e0e9a
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/io.h
@@ -0,0 +1,33 @@
+/* arch/arm/mach-zynq/include/mach/io.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_IO_H__
+#define __MACH_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+
+#define IO_SPACE_LIMIT 0xffff
+
+/* IO address mapping macros, nothing special at this time but required */
+
+#ifdef __ASSEMBLER__
+#define IOMEM(x) (x)
+#else
+#define IOMEM(x) ((void __force __iomem *)(x))
+#endif
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
new file mode 100644
index 000000000000..5fb04fd3bac8
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/irqs.h
@@ -0,0 +1,21 @@
+/* arch/arm/mach-zynq/include/mach/irqs.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_GPIOS 118
+#define NR_IRQS (128 + ARCH_NR_GPIOS)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/memory.h b/arch/arm/mach-zynq/include/mach/memory.h
new file mode 100644
index 000000000000..35a92634dcc1
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/memory.h
@@ -0,0 +1,22 @@
+/* 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/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/system.h
index 66cd3f4fc896..1b84d705c675 100644
--- a/arch/arm/mach-tegra/include/mach/clkdev.h
+++ b/arch/arm/mach-zynq/include/mach/system.h
@@ -1,10 +1,6 @@
-/*
- * arch/arm/mach-tegra/include/mach/clkdev.h
+/* arch/arm/mach-zynq/include/mach/system.h
*
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@google.com>
+ * 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
@@ -14,21 +10,19 @@
* but WITHOUT 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_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-struct clk;
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
-static inline int __clk_get(struct clk *clk)
+static inline void arch_idle(void)
{
- return 1;
+ cpu_do_idle();
}
-static inline void __clk_put(struct clk *clk)
+static inline void arch_reset(char mode, const char *cmd)
{
+ /* Add architecture specific reset processing here */
}
#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
new file mode 100644
index 000000000000..6c0245e42a5e
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/timex.h
@@ -0,0 +1,23 @@
+/* arch/arm/mach-zynq/include/mach/timex.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+/* the following is needed for the system to build but will be removed
+ in the future, the value is not important but won't hurt
+*/
+#define CLOCK_TICK_RATE (100 * HZ)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
new file mode 100644
index 000000000000..5c47c97156f3
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uart.h
@@ -0,0 +1,25 @@
+/* arch/arm/mach-zynq/include/mach/uart.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_UART_H__
+#define __MACH_UART_H__
+
+#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
+#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
+#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
+
+#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
+#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
new file mode 100644
index 000000000000..af4e8447bfa3
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uncompress.h
@@ -0,0 +1,51 @@
+/* arch/arm/mach-zynq/include/mach/uncompress.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_UNCOMPRESS_H__
+#define __MACH_UNCOMPRESS_H__
+
+#include <linux/io.h>
+#include <asm/processor.h>
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+static inline void flush(void)
+{
+ /*
+ * Wait while the FIFO is not empty
+ */
+ while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+ UART_SR_TXEMPTY))
+ cpu_relax();
+}
+
+#define arch_decomp_wdog()
+
+static void putc(char ch)
+{
+ /*
+ * Wait for room in the FIFO, then write the char into the FIFO
+ */
+ while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+ UART_SR_TXFULL)
+ cpu_relax();
+
+ __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/vmalloc.h b/arch/arm/mach-zynq/include/mach/vmalloc.h
new file mode 100644
index 000000000000..2398eff1e8b8
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-zynq/include/mach/vmalloc.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_VMALLOC_H__
+#define __MACH_VMALLOC_H__
+
+#define VMALLOC_END 0xE0000000UL
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
new file mode 100644
index 000000000000..d0d3f8fb06dd
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/zynq_soc.h
@@ -0,0 +1,48 @@
+/* arch/arm/mach-zynq/include/mach/zynq_soc.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_XILINX_SOC_H__
+#define __MACH_XILINX_SOC_H__
+
+#define PERIPHERAL_CLOCK_RATE 2500000
+
+/* For now, all mappings are flat (physical = virtual)
+ */
+#define UART0_PHYS 0xE0000000
+#define UART0_VIRT UART0_PHYS
+
+#define TTC0_PHYS 0xF8001000
+#define TTC0_VIRT TTC0_PHYS
+
+#define PL310_L2CC_PHYS 0xF8F02000
+#define PL310_L2CC_VIRT PL310_L2CC_PHYS
+
+#define SCU_PERIPH_PHYS 0xF8F00000
+#define SCU_PERIPH_VIRT SCU_PERIPH_PHYS
+
+/* The following are intended for the devices that are mapped early */
+
+#define TTC0_BASE IOMEM(TTC0_VIRT)
+#define SCU_PERIPH_BASE IOMEM(SCU_PERIPH_VIRT)
+#define SCU_GIC_CPU_BASE (SCU_PERIPH_BASE + 0x100)
+#define SCU_GIC_DIST_BASE (SCU_PERIPH_BASE + 0x1000)
+#define PL310_L2CC_BASE IOMEM(PL310_L2CC_VIRT)
+
+/*
+ * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
+ */
+#define LL_UART_PADDR UART0_PHYS
+#define LL_UART_VADDR UART0_VIRT
+
+#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
new file mode 100644
index 000000000000..c2c96cc7d6e7
--- /dev/null
+++ b/arch/arm/mach-zynq/timer.c
@@ -0,0 +1,298 @@
+/*
+ * This file contains driver for the Xilinx PS Timer Counter IP.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * based on arch/mips/kernel/time.c timer driver
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+#include <mach/zynq_soc.h>
+#include "common.h"
+
+#define IRQ_TIMERCOUNTER0 42
+
+/*
+ * This driver configures the 2 16-bit count-up timers as follows:
+ *
+ * T1: Timer 1, clocksource for generic timekeeping
+ * T2: Timer 2, clockevent source for hrtimers
+ * T3: Timer 3, <unused>
+ *
+ * The input frequency to the timer module for emulation is 2.5MHz which is
+ * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
+ * the timers are clocked at 78.125KHz (12.8 us resolution).
+ *
+ * The input frequency to the timer module in silicon will be 200MHz. With the
+ * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
+ */
+#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
+#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
+
+#define XTTCPSS_TIMER_BASE TTC0_BASE
+#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
+/*
+ * Timer Register Offset Definitions of Timer 1, Increment base address by 4
+ * and use same offsets for Timer 2
+ */
+#define XTTCPSS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */
+#define XTTCPSS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */
+#define XTTCPSS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */
+#define XTTCPSS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */
+#define XTTCPSS_MATCH_1_OFFSET 0x30 /* Match 1 Value Reg, RW */
+#define XTTCPSS_MATCH_2_OFFSET 0x3C /* Match 2 Value Reg, RW */
+#define XTTCPSS_MATCH_3_OFFSET 0x48 /* Match 3 Value Reg, RW */
+#define XTTCPSS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */
+#define XTTCPSS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */
+
+#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
+
+/* Setup the timers to use pre-scaling */
+
+#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+
+/**
+ * struct xttcpss_timer - This definition defines local timer structure
+ *
+ * @base_addr: Base address of timer
+ **/
+struct xttcpss_timer {
+ void __iomem *base_addr;
+};
+
+static struct xttcpss_timer timers[2];
+static struct clock_event_device xttcpss_clockevent;
+
+/**
+ * xttcpss_set_interval - Set the timer interval value
+ *
+ * @timer: Pointer to the timer instance
+ * @cycles: Timer interval ticks
+ **/
+static void xttcpss_set_interval(struct xttcpss_timer *timer,
+ unsigned long cycles)
+{
+ u32 ctrl_reg;
+
+ /* Disable the counter, set the counter value and re-enable counter */
+ ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+ __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
+
+ /* Reset the counter (0x10) so that it starts from 0, one-shot
+ mode makes this needed for timing to be right. */
+ ctrl_reg |= 0x10;
+ ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+}
+
+/**
+ * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
+ *
+ * @irq: IRQ number of the Timer
+ * @dev_id: void pointer to the xttcpss_timer instance
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &xttcpss_clockevent;
+ struct xttcpss_timer *timer = dev_id;
+
+ /* Acknowledge the interrupt and call event handler */
+ __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
+ timer->base_addr + XTTCPSS_ISR_OFFSET);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction event_timer_irq = {
+ .name = "xttcpss clockevent",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = xttcpss_clock_event_interrupt,
+};
+
+/**
+ * xttcpss_timer_hardware_init - Initialize the timer hardware
+ *
+ * Initialize the hardware to start the clock source, get the clock
+ * event timer ready to use, and hook up the interrupt.
+ **/
+static void __init xttcpss_timer_hardware_init(void)
+{
+ /* Setup the clock source counter to be an incrementing counter
+ * with no interrupt and it rolls over at 0xFFFF. Pre-scale
+ it by 32 also. Let it start running now.
+ */
+ timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
+
+ __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_IER_OFFSET);
+ __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+
+ /* Setup the clock event timer to be an interval timer which
+ * is prescaled by 32 using the interval interrupt. Leave it
+ * disabled for now.
+ */
+
+ timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
+
+ __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_IER_OFFSET);
+
+ /* Setup IRQ the clock event timer */
+ event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
+ setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
+}
+
+/**
+ * __raw_readl_cycles - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t __raw_readl_cycles(struct clocksource *cs)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+
+ return (cycle_t)__raw_readl(timer->base_addr +
+ XTTCPSS_COUNT_VAL_OFFSET);
+}
+
+
+/*
+ * Instantiate and initialize the clock source structure
+ */
+static struct clocksource clocksource_xttcpss = {
+ .name = "xttcpss_timer1",
+ .rating = 200, /* Reasonable clock source */
+ .read = __raw_readl_cycles,
+ .mask = CLOCKSOURCE_MASK(16),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/**
+ * xttcpss_set_next_event - Sets the time interval for next event
+ *
+ * @cycles: Timer interval ticks
+ * @evt: Address of clock event instance
+ *
+ * returns: Always 0 - success
+ **/
+static int xttcpss_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+
+ xttcpss_set_interval(timer, cycles);
+ return 0;
+}
+
+/**
+ * xttcpss_set_mode - Sets the mode of timer
+ *
+ * @mode: Mode to be set
+ * @evt: Address of clock event instance
+ **/
+static void xttcpss_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ u32 ctrl_reg;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ xttcpss_set_interval(timer, TIMER_RATE / HZ);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ ctrl_reg = __raw_readl(timer->base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg,
+ timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ ctrl_reg = __raw_readl(timer->base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg,
+ timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ break;
+ }
+}
+
+/*
+ * Instantiate and initialize the clock event structure
+ */
+static struct clock_event_device xttcpss_clockevent = {
+ .name = "xttcpss_timer2",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = xttcpss_set_next_event,
+ .set_mode = xttcpss_set_mode,
+ .rating = 200,
+};
+
+/**
+ * xttcpss_timer_init - Initialize the timer
+ *
+ * Initializes the timer hardware and register the clock source and clock event
+ * timers with Linux kernal timer framework
+ **/
+static void __init xttcpss_timer_init(void)
+{
+ xttcpss_timer_hardware_init();
+ clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
+
+ /* Calculate the parameters to allow the clockevent to operate using
+ integer math
+ */
+ clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
+
+ xttcpss_clockevent.max_delta_ns =
+ clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
+ xttcpss_clockevent.min_delta_ns =
+ clockevent_delta2ns(1, &xttcpss_clockevent);
+
+ /* Indicate that clock event is on 1st CPU as SMP boot needs it */
+
+ xttcpss_clockevent.cpumask = cpumask_of(0);
+ clockevents_register_device(&xttcpss_clockevent);
+}
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+struct sys_timer xttcpss_sys_timer = {
+ .init = xttcpss_timer_init,
+};
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 0074b8dba793..88633fe01a5d 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -821,7 +821,8 @@ config CACHE_L2X0
depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
- ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
+ ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
+ ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX
default y
select OUTER_CACHE
select OUTER_CACHE_SYNC
diff --git a/arch/arm/mm/abort-ev4.S b/arch/arm/mm/abort-ev4.S
index 4f18f9e87bae..54473cd4aba9 100644
--- a/arch/arm/mm/abort-ev4.S
+++ b/arch/arm/mm/abort-ev4.S
@@ -3,14 +3,11 @@
/*
* Function: v4_early_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = address of abort
- * : r1 = FSR, bit 11 = write
- * : r2-r8 = corrupted
- * : r9 = preserved
- * : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current aborted instruction.
* Note: we read user space. This means we might cause a data
@@ -21,10 +18,8 @@
ENTRY(v4_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
- ldr r3, [r2] @ read aborted ARM instruction
+ ldr r3, [r4] @ read aborted ARM instruction
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
tst r3, #1 << 20 @ L = 1 -> write?
orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
-
-
+ b do_DataAbort
diff --git a/arch/arm/mm/abort-ev4t.S b/arch/arm/mm/abort-ev4t.S
index b6282548f922..9da704e7b86e 100644
--- a/arch/arm/mm/abort-ev4t.S
+++ b/arch/arm/mm/abort-ev4t.S
@@ -4,14 +4,11 @@
/*
* Function: v4t_early_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = address of abort
- * : r1 = FSR, bit 11 = write
- * : r2-r8 = corrupted
- * : r9 = preserved
- * : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current aborted instruction.
* Note: we read user space. This means we might cause a data
@@ -22,9 +19,9 @@
ENTRY(v4t_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
- do_thumb_abort
- ldreq r3, [r2] @ read aborted ARM instruction
+ do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+ ldreq r3, [r4] @ read aborted ARM instruction
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
tst r3, #1 << 20 @ check write
orreq r1, r1, #1 << 11
- mov pc, lr
+ b do_DataAbort
diff --git a/arch/arm/mm/abort-ev5t.S b/arch/arm/mm/abort-ev5t.S
index 02251b526c0d..a0908d4653a3 100644
--- a/arch/arm/mm/abort-ev5t.S
+++ b/arch/arm/mm/abort-ev5t.S
@@ -4,14 +4,11 @@
/*
* Function: v5t_early_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = address of abort
- * : r1 = FSR, bit 11 = write
- * : r2-r8 = corrupted
- * : r9 = preserved
- * : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current aborted instruction.
* Note: we read user space. This means we might cause a data
@@ -22,10 +19,10 @@
ENTRY(v5t_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
- do_thumb_abort
- ldreq r3, [r2] @ read aborted ARM instruction
+ do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+ ldreq r3, [r4] @ read aborted ARM instruction
bic r1, r1, #1 << 11 @ clear bits 11 of FSR
- do_ldrd_abort
+ do_ldrd_abort tmp=ip, insn=r3
tst r3, #1 << 20 @ check write
orreq r1, r1, #1 << 11
- mov pc, lr
+ b do_DataAbort
diff --git a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S
index bce68d601c8b..4006b7a61264 100644
--- a/arch/arm/mm/abort-ev5tj.S
+++ b/arch/arm/mm/abort-ev5tj.S
@@ -4,14 +4,11 @@
/*
* Function: v5tj_early_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = address of abort
- * : r1 = FSR, bit 11 = write
- * : r2-r8 = corrupted
- * : r9 = preserved
- * : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current aborted instruction.
* Note: we read user space. This means we might cause a data
@@ -23,13 +20,11 @@ ENTRY(v5tj_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
- tst r3, #PSR_J_BIT @ Java?
- movne pc, lr
- do_thumb_abort
- ldreq r3, [r2] @ read aborted ARM instruction
- do_ldrd_abort
+ tst r5, #PSR_J_BIT @ Java?
+ bne do_DataAbort
+ do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+ ldreq r3, [r4] @ read aborted ARM instruction
+ do_ldrd_abort tmp=ip, insn=r3
tst r3, #1 << 20 @ L = 0 -> write
orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
-
-
+ b do_DataAbort
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index 1478aa522144..ff1f7cc11f87 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -4,14 +4,11 @@
/*
* Function: v6_early_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = address of abort
- * : r1 = FSR, bit 11 = write
- * : r2-r8 = corrupted
- * : r9 = preserved
- * : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current aborted instruction.
* Note: we read user space. This means we might cause a data
@@ -33,16 +30,14 @@ ENTRY(v6_early_abort)
* The test below covers all the write situations, including Java bytecodes
*/
bic r1, r1, #1 << 11 @ clear bit 11 of FSR
- tst r3, #PSR_J_BIT @ Java?
- movne pc, lr
- do_thumb_abort
- ldreq r3, [r2] @ read aborted ARM instruction
+ tst r5, #PSR_J_BIT @ Java?
+ bne do_DataAbort
+ do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+ ldreq r3, [r4] @ read aborted ARM instruction
#ifdef CONFIG_CPU_ENDIAN_BE8
reveq r3, r3
#endif
- do_ldrd_abort
+ do_ldrd_abort tmp=ip, insn=r3
tst r3, #1 << 20 @ L = 0 -> write
orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
-
-
+ b do_DataAbort
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
index ec88b157d3bb..703375277ba6 100644
--- a/arch/arm/mm/abort-ev7.S
+++ b/arch/arm/mm/abort-ev7.S
@@ -3,14 +3,11 @@
/*
* Function: v7_early_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = address of abort
- * : r1 = FSR, bit 11 = write
- * : r2-r8 = corrupted
- * : r9 = preserved
- * : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current aborted instruction.
*/
@@ -37,18 +34,18 @@ ENTRY(v7_early_abort)
ldr r3, =0x40d @ On permission fault
and r3, r1, r3
cmp r3, #0x0d
- movne pc, lr
+ bne do_DataAbort
mcr p15, 0, r0, c7, c8, 0 @ Retranslate FAR
isb
- mrc p15, 0, r2, c7, c4, 0 @ Read the PAR
- and r3, r2, #0x7b @ On translation fault
+ mrc p15, 0, ip, c7, c4, 0 @ Read the PAR
+ and r3, ip, #0x7b @ On translation fault
cmp r3, #0x0b
- movne pc, lr
+ bne do_DataAbort
bic r1, r1, #0xf @ Fix up FSR FS[5:0]
- and r2, r2, #0x7e
- orr r1, r1, r2, LSR #1
+ and ip, ip, #0x7e
+ orr r1, r1, ip, LSR #1
#endif
- mov pc, lr
+ b do_DataAbort
ENDPROC(v7_early_abort)
diff --git a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S
index 9fb7b0e25ea1..f3982580c273 100644
--- a/arch/arm/mm/abort-lv4t.S
+++ b/arch/arm/mm/abort-lv4t.S
@@ -3,14 +3,11 @@
/*
* Function: v4t_late_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = address of abort
- * : r1 = FSR, bit 11 = write
- * : r2-r8 = corrupted
- * : r9 = preserved
- * : sp = pointer to registers
+ * Returns : r4-r5, r10-r11, r13 preserved
*
* Purpose : obtain information about current aborted instruction.
* Note: we read user space. This means we might cause a data
@@ -18,7 +15,7 @@
* picture. Unfortunately, this does happen. We live with it.
*/
ENTRY(v4t_late_abort)
- tst r3, #PSR_T_BIT @ check for thumb mode
+ tst r5, #PSR_T_BIT @ check for thumb mode
#ifdef CONFIG_CPU_CP15_MMU
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
@@ -28,7 +25,7 @@ ENTRY(v4t_late_abort)
mov r1, #0
#endif
bne .data_thumb_abort
- ldr r8, [r2] @ read arm instruction
+ ldr r8, [r4] @ read arm instruction
tst r8, #1 << 20 @ L = 1 -> write?
orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #15 << 24
@@ -47,86 +44,84 @@ ENTRY(v4t_late_abort)
/* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist>
/* a */ b .data_unknown
/* b */ b .data_unknown
-/* c */ mov pc, lr @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
-/* d */ mov pc, lr @ ldc rd, [rn, #m]
+/* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
+/* d */ b do_DataAbort @ ldc rd, [rn, #m]
/* e */ b .data_unknown
/* f */
.data_unknown: @ Part of jumptable
- mov r0, r2
+ mov r0, r4
mov r1, r8
- mov r2, sp
- bl baddataabort
- b ret_from_exception
+ b baddataabort
.data_arm_ldmstm:
tst r8, #1 << 21 @ check writeback bit
- moveq pc, lr @ no writeback -> no fixup
+ beq do_DataAbort @ no writeback -> no fixup
mov r7, #0x11
orr r7, r7, #0x1100
and r6, r8, r7
- and r2, r8, r7, lsl #1
- add r6, r6, r2, lsr #1
- and r2, r8, r7, lsl #2
- add r6, r6, r2, lsr #2
- and r2, r8, r7, lsl #3
- add r6, r6, r2, lsr #3
+ and r9, r8, r7, lsl #1
+ add r6, r6, r9, lsr #1
+ and r9, r8, r7, lsl #2
+ add r6, r6, r9, lsr #2
+ and r9, r8, r7, lsl #3
+ add r6, r6, r9, lsr #3
add r6, r6, r6, lsr #8
add r6, r6, r6, lsr #4
and r6, r6, #15 @ r6 = no. of registers to transfer.
- and r5, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ and r9, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
tst r8, #1 << 23 @ Check U bit
subne r7, r7, r6, lsl #2 @ Undo increment
addeq r7, r7, r6, lsl #2 @ Undo decrement
- str r7, [sp, r5, lsr #14] @ Put register 'Rn'
- mov pc, lr
+ str r7, [r2, r9, lsr #14] @ Put register 'Rn'
+ b do_DataAbort
.data_arm_lateldrhpre:
tst r8, #1 << 21 @ Check writeback bit
- moveq pc, lr @ No writeback -> no fixup
+ beq do_DataAbort @ No writeback -> no fixup
.data_arm_lateldrhpost:
- and r5, r8, #0x00f @ get Rm / low nibble of immediate value
+ and r9, r8, #0x00f @ get Rm / low nibble of immediate value
tst r8, #1 << 22 @ if (immediate offset)
andne r6, r8, #0xf00 @ { immediate high nibble
- orrne r6, r5, r6, lsr #4 @ combine nibbles } else
- ldreq r6, [sp, r5, lsl #2] @ { load Rm value }
+ orrne r6, r9, r6, lsr #4 @ combine nibbles } else
+ ldreq r6, [r2, r9, lsl #2] @ { load Rm value }
.data_arm_apply_r6_and_rn:
- and r5, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ and r9, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
tst r8, #1 << 23 @ Check U bit
subne r7, r7, r6 @ Undo incrmenet
addeq r7, r7, r6 @ Undo decrement
- str r7, [sp, r5, lsr #14] @ Put register 'Rn'
- mov pc, lr
+ str r7, [r2, r9, lsr #14] @ Put register 'Rn'
+ b do_DataAbort
.data_arm_lateldrpreconst:
tst r8, #1 << 21 @ check writeback bit
- moveq pc, lr @ no writeback -> no fixup
+ beq do_DataAbort @ no writeback -> no fixup
.data_arm_lateldrpostconst:
- movs r2, r8, lsl #20 @ Get offset
- moveq pc, lr @ zero -> no fixup
- and r5, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ movs r6, r8, lsl #20 @ Get offset
+ beq do_DataAbort @ zero -> no fixup
+ and r9, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
tst r8, #1 << 23 @ Check U bit
- subne r7, r7, r2, lsr #20 @ Undo increment
- addeq r7, r7, r2, lsr #20 @ Undo decrement
- str r7, [sp, r5, lsr #14] @ Put register 'Rn'
- mov pc, lr
+ subne r7, r7, r6, lsr #20 @ Undo increment
+ addeq r7, r7, r6, lsr #20 @ Undo decrement
+ str r7, [r2, r9, lsr #14] @ Put register 'Rn'
+ b do_DataAbort
.data_arm_lateldrprereg:
tst r8, #1 << 21 @ check writeback bit
- moveq pc, lr @ no writeback -> no fixup
+ beq do_DataAbort @ no writeback -> no fixup
.data_arm_lateldrpostreg:
and r7, r8, #15 @ Extract 'm' from instruction
- ldr r6, [sp, r7, lsl #2] @ Get register 'Rm'
- mov r5, r8, lsr #7 @ get shift count
- ands r5, r5, #31
+ ldr r6, [r2, r7, lsl #2] @ Get register 'Rm'
+ mov r9, r8, lsr #7 @ get shift count
+ ands r9, r9, #31
and r7, r8, #0x70 @ get shift type
orreq r7, r7, #8 @ shift count = 0
add pc, pc, r7
nop
- mov r6, r6, lsl r5 @ 0: LSL #!0
+ mov r6, r6, lsl r9 @ 0: LSL #!0
b .data_arm_apply_r6_and_rn
b .data_arm_apply_r6_and_rn @ 1: LSL #0
nop
@@ -134,7 +129,7 @@ ENTRY(v4t_late_abort)
nop
b .data_unknown @ 3: MUL?
nop
- mov r6, r6, lsr r5 @ 4: LSR #!0
+ mov r6, r6, lsr r9 @ 4: LSR #!0
b .data_arm_apply_r6_and_rn
mov r6, r6, lsr #32 @ 5: LSR #32
b .data_arm_apply_r6_and_rn
@@ -142,7 +137,7 @@ ENTRY(v4t_late_abort)
nop
b .data_unknown @ 7: MUL?
nop
- mov r6, r6, asr r5 @ 8: ASR #!0
+ mov r6, r6, asr r9 @ 8: ASR #!0
b .data_arm_apply_r6_and_rn
mov r6, r6, asr #32 @ 9: ASR #32
b .data_arm_apply_r6_and_rn
@@ -150,7 +145,7 @@ ENTRY(v4t_late_abort)
nop
b .data_unknown @ B: MUL?
nop
- mov r6, r6, ror r5 @ C: ROR #!0
+ mov r6, r6, ror r9 @ C: ROR #!0
b .data_arm_apply_r6_and_rn
mov r6, r6, rrx @ D: RRX
b .data_arm_apply_r6_and_rn
@@ -159,7 +154,7 @@ ENTRY(v4t_late_abort)
b .data_unknown @ F: MUL?
.data_thumb_abort:
- ldrh r8, [r2] @ read instruction
+ ldrh r8, [r4] @ read instruction
tst r8, #1 << 11 @ L = 1 -> write?
orreq r1, r1, #1 << 8 @ yes
and r7, r8, #15 << 12
@@ -172,10 +167,10 @@ ENTRY(v4t_late_abort)
/* 3 */ b .data_unknown
/* 4 */ b .data_unknown
/* 5 */ b .data_thumb_reg
-/* 6 */ mov pc, lr
-/* 7 */ mov pc, lr
-/* 8 */ mov pc, lr
-/* 9 */ mov pc, lr
+/* 6 */ b do_DataAbort
+/* 7 */ b do_DataAbort
+/* 8 */ b do_DataAbort
+/* 9 */ b do_DataAbort
/* A */ b .data_unknown
/* B */ b .data_thumb_pushpop
/* C */ b .data_thumb_ldmstm
@@ -185,41 +180,41 @@ ENTRY(v4t_late_abort)
.data_thumb_reg:
tst r8, #1 << 9
- moveq pc, lr
+ beq do_DataAbort
tst r8, #1 << 10 @ If 'S' (signed) bit is set
movne r1, #0 @ it must be a load instr
- mov pc, lr
+ b do_DataAbort
.data_thumb_pushpop:
tst r8, #1 << 10
beq .data_unknown
and r6, r8, #0x55 @ hweight8(r8) + R bit
- and r2, r8, #0xaa
- add r6, r6, r2, lsr #1
- and r2, r6, #0xcc
+ and r9, r8, #0xaa
+ add r6, r6, r9, lsr #1
+ and r9, r6, #0xcc
and r6, r6, #0x33
- add r6, r6, r2, lsr #2
+ add r6, r6, r9, lsr #2
movs r7, r8, lsr #9 @ C = r8 bit 8 (R bit)
adc r6, r6, r6, lsr #4 @ high + low nibble + R bit
and r6, r6, #15 @ number of regs to transfer
- ldr r7, [sp, #13 << 2]
+ ldr r7, [r2, #13 << 2]
tst r8, #1 << 11
addeq r7, r7, r6, lsl #2 @ increment SP if PUSH
subne r7, r7, r6, lsl #2 @ decrement SP if POP
- str r7, [sp, #13 << 2]
- mov pc, lr
+ str r7, [r2, #13 << 2]
+ b do_DataAbort
.data_thumb_ldmstm:
and r6, r8, #0x55 @ hweight8(r8)
- and r2, r8, #0xaa
- add r6, r6, r2, lsr #1
- and r2, r6, #0xcc
+ and r9, r8, #0xaa
+ add r6, r6, r9, lsr #1
+ and r9, r6, #0xcc
and r6, r6, #0x33
- add r6, r6, r2, lsr #2
+ add r6, r6, r9, lsr #2
add r6, r6, r6, lsr #4
- and r5, r8, #7 << 8
- ldr r7, [sp, r5, lsr #6]
+ and r9, r8, #7 << 8
+ ldr r7, [r2, r9, lsr #6]
and r6, r6, #15 @ number of regs to transfer
sub r7, r7, r6, lsl #2 @ always decrement
- str r7, [sp, r5, lsr #6]
- mov pc, lr
+ str r7, [r2, r9, lsr #6]
+ b do_DataAbort
diff --git a/arch/arm/mm/abort-macro.S b/arch/arm/mm/abort-macro.S
index d7cb1bfa51a4..52162d59407a 100644
--- a/arch/arm/mm/abort-macro.S
+++ b/arch/arm/mm/abort-macro.S
@@ -9,34 +9,32 @@
*
*/
- .macro do_thumb_abort
- tst r3, #PSR_T_BIT
+ .macro do_thumb_abort, fsr, pc, psr, tmp
+ tst \psr, #PSR_T_BIT
beq not_thumb
- ldrh r3, [r2] @ Read aborted Thumb instruction
- and r3, r3, # 0xfe00 @ Mask opcode field
- cmp r3, # 0x5600 @ Is it ldrsb?
- orreq r3, r3, #1 << 11 @ Set L-bit if yes
- tst r3, #1 << 11 @ L = 0 -> write
- orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
+ ldrh \tmp, [\pc] @ Read aborted Thumb instruction
+ and \tmp, \tmp, # 0xfe00 @ Mask opcode field
+ cmp \tmp, # 0x5600 @ Is it ldrsb?
+ orreq \tmp, \tmp, #1 << 11 @ Set L-bit if yes
+ tst \tmp, #1 << 11 @ L = 0 -> write
+ orreq \psr, \psr, #1 << 11 @ yes.
+ b do_DataAbort
not_thumb:
.endm
/*
- * We check for the following insturction encoding for LDRD.
+ * We check for the following instruction encoding for LDRD.
*
- * [27:25] == 0
+ * [27:25] == 000
* [7:4] == 1101
* [20] == 0
*/
- .macro do_ldrd_abort
- tst r3, #0x0e000000 @ [27:25] == 0
+ .macro do_ldrd_abort, tmp, insn
+ tst \insn, #0x0e100000 @ [27:25,20] == 0
bne not_ldrd
- and r2, r3, #0x000000f0 @ [7:4] == 1101
- cmp r2, #0x000000d0
- bne not_ldrd
- tst r3, #1 << 20 @ [20] == 0
- moveq pc, lr
+ and \tmp, \insn, #0x000000f0 @ [7:4] == 1101
+ cmp \tmp, #0x000000d0
+ beq do_DataAbort
not_ldrd:
.endm
diff --git a/arch/arm/mm/abort-nommu.S b/arch/arm/mm/abort-nommu.S
index 625e580945b5..119cb479c2ab 100644
--- a/arch/arm/mm/abort-nommu.S
+++ b/arch/arm/mm/abort-nommu.S
@@ -3,11 +3,11 @@
/*
* Function: nommu_early_abort
*
- * Params : r2 = address of aborted instruction
- * : r3 = saved SPSR
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
- * Returns : r0 = 0 (abort address)
- * : r1 = 0 (FSR)
+ * Returns : r4 - r11, r13 preserved
*
* Note: There is no FSR/FAR on !CPU_CP15_MMU cores.
* Just fill zero into the registers.
@@ -16,5 +16,5 @@
ENTRY(nommu_early_abort)
mov r0, #0 @ clear r0, r1 (no FSR/FAR)
mov r1, #0
- mov pc, lr
+ b do_DataAbort
ENDPROC(nommu_early_abort)
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 724ba3bce72c..be7c638b648b 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -727,6 +727,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
int isize = 4;
int thumb2_32b = 0;
+ if (interrupts_enabled(regs))
+ local_irq_enable();
+
instrptr = instruction_pointer(regs);
fs = get_fs();
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S
index 1fa6f71470de..072016371093 100644
--- a/arch/arm/mm/cache-fa.S
+++ b/arch/arm/mm/cache-fa.S
@@ -242,16 +242,5 @@ ENDPROC(fa_dma_unmap_area)
__INITDATA
- .type fa_cache_fns, #object
-ENTRY(fa_cache_fns)
- .long fa_flush_icache_all
- .long fa_flush_kern_cache_all
- .long fa_flush_user_cache_all
- .long fa_flush_user_cache_range
- .long fa_coherent_kern_range
- .long fa_coherent_user_range
- .long fa_flush_kern_dcache_area
- .long fa_dma_map_area
- .long fa_dma_unmap_area
- .long fa_dma_flush_range
- .size fa_cache_fns, . - fa_cache_fns
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions fa
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index 2e2bc406a18d..c2301f226100 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -129,16 +129,5 @@ ENDPROC(v3_dma_map_area)
__INITDATA
- .type v3_cache_fns, #object
-ENTRY(v3_cache_fns)
- .long v3_flush_icache_all
- .long v3_flush_kern_cache_all
- .long v3_flush_user_cache_all
- .long v3_flush_user_cache_range
- .long v3_coherent_kern_range
- .long v3_coherent_user_range
- .long v3_flush_kern_dcache_area
- .long v3_dma_map_area
- .long v3_dma_unmap_area
- .long v3_dma_flush_range
- .size v3_cache_fns, . - v3_cache_fns
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions v3
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index a8fefb523f19..fd9bb7addc8d 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -141,16 +141,5 @@ ENDPROC(v4_dma_map_area)
__INITDATA
- .type v4_cache_fns, #object
-ENTRY(v4_cache_fns)
- .long v4_flush_icache_all
- .long v4_flush_kern_cache_all
- .long v4_flush_user_cache_all
- .long v4_flush_user_cache_range
- .long v4_coherent_kern_range
- .long v4_coherent_user_range
- .long v4_flush_kern_dcache_area
- .long v4_dma_map_area
- .long v4_dma_unmap_area
- .long v4_dma_flush_range
- .size v4_cache_fns, . - v4_cache_fns
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions v4
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index f40c69656d8d..4f2c14151ccb 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -253,16 +253,5 @@ ENDPROC(v4wb_dma_unmap_area)
__INITDATA
- .type v4wb_cache_fns, #object
-ENTRY(v4wb_cache_fns)
- .long v4wb_flush_icache_all
- .long v4wb_flush_kern_cache_all
- .long v4wb_flush_user_cache_all
- .long v4wb_flush_user_cache_range
- .long v4wb_coherent_kern_range
- .long v4wb_coherent_user_range
- .long v4wb_flush_kern_dcache_area
- .long v4wb_dma_map_area
- .long v4wb_dma_unmap_area
- .long v4wb_dma_flush_range
- .size v4wb_cache_fns, . - v4wb_cache_fns
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions v4wb
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index a7b276dbda11..4d7b467631ce 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -197,16 +197,5 @@ ENDPROC(v4wt_dma_map_area)
__INITDATA
- .type v4wt_cache_fns, #object
-ENTRY(v4wt_cache_fns)
- .long v4wt_flush_icache_all
- .long v4wt_flush_kern_cache_all
- .long v4wt_flush_user_cache_all
- .long v4wt_flush_user_cache_range
- .long v4wt_coherent_kern_range
- .long v4wt_coherent_user_range
- .long v4wt_flush_kern_dcache_area
- .long v4wt_dma_map_area
- .long v4wt_dma_unmap_area
- .long v4wt_dma_flush_range
- .size v4wt_cache_fns, . - v4wt_cache_fns
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions v4wt
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 73b4a8b66a57..74c2e5a33a4d 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -330,16 +330,5 @@ ENDPROC(v6_dma_unmap_area)
__INITDATA
- .type v6_cache_fns, #object
-ENTRY(v6_cache_fns)
- .long v6_flush_icache_all
- .long v6_flush_kern_cache_all
- .long v6_flush_user_cache_all
- .long v6_flush_user_cache_range
- .long v6_coherent_kern_range
- .long v6_coherent_user_range
- .long v6_flush_kern_dcache_area
- .long v6_dma_map_area
- .long v6_dma_unmap_area
- .long v6_dma_flush_range
- .size v6_cache_fns, . - v6_cache_fns
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions v6
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index d32f02b61866..3b24bfa3b828 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -325,16 +325,5 @@ ENDPROC(v7_dma_unmap_area)
__INITDATA
- .type v7_cache_fns, #object
-ENTRY(v7_cache_fns)
- .long v7_flush_icache_all
- .long v7_flush_kern_cache_all
- .long v7_flush_user_cache_all
- .long v7_flush_user_cache_range
- .long v7_coherent_kern_range
- .long v7_coherent_user_range
- .long v7_flush_kern_dcache_area
- .long v7_dma_map_area
- .long v7_dma_unmap_area
- .long v7_dma_flush_range
- .size v7_cache_fns, . - v7_cache_fns
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions v7
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index bdba6c65c901..63cca0097130 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -41,7 +41,6 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
kfrom = kmap_atomic(from, KM_USER0);
kto = kmap_atomic(to, KM_USER1);
copy_page(kto, kfrom);
- __cpuc_flush_dcache_area(kto, PAGE_SIZE);
kunmap_atomic(kto, KM_USER1);
kunmap_atomic(kfrom, KM_USER0);
}
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 82a093cee09a..0a0a1e7c20d2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -25,9 +25,11 @@
#include <asm/tlbflush.h>
#include <asm/sizes.h>
+#include "mm.h"
+
static u64 get_coherent_dma_mask(struct device *dev)
{
- u64 mask = ISA_DMA_THRESHOLD;
+ u64 mask = (u64)arm_dma_limit;
if (dev) {
mask = dev->coherent_dma_mask;
@@ -41,10 +43,10 @@ static u64 get_coherent_dma_mask(struct device *dev)
return 0;
}
- if ((~mask) & ISA_DMA_THRESHOLD) {
+ if ((~mask) & (u64)arm_dma_limit) {
dev_warn(dev, "coherent DMA mask %#llx is smaller "
"than system GFP_DMA mask %#llx\n",
- mask, (unsigned long long)ISA_DMA_THRESHOLD);
+ mask, (u64)arm_dma_limit);
return 0;
}
}
@@ -657,6 +659,33 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
}
EXPORT_SYMBOL(dma_sync_sg_for_device);
+/*
+ * Return whether the given device DMA address mask can be supported
+ * properly. For example, if your device can only drive the low 24-bits
+ * during bus mastering, then you would pass 0x00ffffff as the mask
+ * to this function.
+ */
+int dma_supported(struct device *dev, u64 mask)
+{
+ if (mask < (u64)arm_dma_limit)
+ return 0;
+ return 1;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+ return -EIO;
+
+#ifndef CONFIG_DMABOUNCE
+ *dev->dma_mask = dma_mask;
+#endif
+
+ return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
#define PREALLOC_DMA_DEBUG_ENTRIES 4096
static int __init dma_debug_do_init(void)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index bc0e1d88fd3b..3b5ea68acbb8 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -94,7 +94,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
pud = pud_offset(pgd, addr);
if (PTRS_PER_PUD != 1)
- printk(", *pud=%08lx", pud_val(*pud));
+ printk(", *pud=%08llx", (long long)pud_val(*pud));
if (pud_none(*pud))
break;
@@ -285,6 +285,10 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
tsk = current;
mm = tsk->mm;
+ /* Enable interrupts if they were enabled in the parent context. */
+ if (interrupts_enabled(regs))
+ local_irq_enable();
+
/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -318,11 +322,11 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
fault = __do_page_fault(mm, addr, fsr, tsk);
up_read(&mm->mmap_sem);
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, addr);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
if (fault & VM_FAULT_MAJOR)
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, regs, addr);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, addr);
else if (fault & VM_FAULT_MINOR)
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, regs, addr);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, addr);
/*
* Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index c19571c40a21..2fee782077c1 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -212,6 +212,18 @@ static void __init arm_bootmem_init(unsigned long start_pfn,
}
#ifdef CONFIG_ZONE_DMA
+
+unsigned long arm_dma_zone_size __read_mostly;
+EXPORT_SYMBOL(arm_dma_zone_size);
+
+/*
+ * The DMA mask corresponding to the maximum bus address allocatable
+ * using GFP_DMA. The default here places no restriction on DMA
+ * allocations. This must be the smallest DMA mask in the system,
+ * so a successful GFP_DMA allocation will always satisfy this.
+ */
+u32 arm_dma_limit;
+
static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
unsigned long dma_size)
{
@@ -267,17 +279,17 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
#endif
}
-#ifdef ARM_DMA_ZONE_SIZE
-#ifndef CONFIG_ZONE_DMA
-#error ARM_DMA_ZONE_SIZE set but no DMA zone to limit allocations
-#endif
-
+#ifdef CONFIG_ZONE_DMA
/*
* Adjust the sizes according to any special requirements for
* this machine type.
*/
- arm_adjust_dma_zone(zone_size, zhole_size,
- ARM_DMA_ZONE_SIZE >> PAGE_SHIFT);
+ if (arm_dma_zone_size) {
+ arm_adjust_dma_zone(zone_size, zhole_size,
+ arm_dma_zone_size >> PAGE_SHIFT);
+ arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
+ } else
+ arm_dma_limit = 0xffffffff;
#endif
free_area_init_node(0, zone_size, min, zhole_size);
@@ -422,6 +434,17 @@ static inline int free_area(unsigned long pfn, unsigned long end, char *s)
return pages;
}
+/*
+ * Poison init memory with an undefined instruction (ARM) or a branch to an
+ * undefined instruction (Thumb).
+ */
+static inline void poison_init_mem(void *s, size_t count)
+{
+ u32 *p = (u32 *)s;
+ while ((count = count - 4))
+ *p++ = 0xe7fddef0;
+}
+
static inline void
free_memmap(unsigned long start_pfn, unsigned long end_pfn)
{
@@ -639,8 +662,8 @@ void __init mem_init(void)
" pkmap : 0x%08lx - 0x%08lx (%4ld MB)\n"
#endif
" modules : 0x%08lx - 0x%08lx (%4ld MB)\n"
- " .init : 0x%p" " - 0x%p" " (%4d kB)\n"
" .text : 0x%p" " - 0x%p" " (%4d kB)\n"
+ " .init : 0x%p" " - 0x%p" " (%4d kB)\n"
" .data : 0x%p" " - 0x%p" " (%4d kB)\n"
" .bss : 0x%p" " - 0x%p" " (%4d kB)\n",
@@ -662,8 +685,8 @@ void __init mem_init(void)
#endif
MLM(MODULES_VADDR, MODULES_END),
- MLK_ROUNDUP(__init_begin, __init_end),
MLK_ROUNDUP(_text, _etext),
+ MLK_ROUNDUP(__init_begin, __init_end),
MLK_ROUNDUP(_sdata, _edata),
MLK_ROUNDUP(__bss_start, __bss_stop));
@@ -704,11 +727,13 @@ void free_initmem(void)
#ifdef CONFIG_HAVE_TCM
extern char __tcm_start, __tcm_end;
+ poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start);
totalram_pages += free_area(__phys_to_pfn(__pa(&__tcm_start)),
__phys_to_pfn(__pa(&__tcm_end)),
"TCM link");
#endif
+ poison_init_mem(__init_begin, __init_end - __init_begin);
if (!machine_is_integrator() && !machine_is_cintegrator())
totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
__phys_to_pfn(__pa(__init_end)),
@@ -721,10 +746,12 @@ static int keep_initrd;
void free_initrd_mem(unsigned long start, unsigned long end)
{
- if (!keep_initrd)
+ if (!keep_initrd) {
+ poison_init_mem((void *)start, PAGE_ALIGN(end) - start);
totalram_pages += free_area(__phys_to_pfn(__pa(start)),
__phys_to_pfn(__pa(end)),
"initrd");
+ }
}
static int __init keepinitrd_setup(char *__unused)
diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c
index ffad039cbb73..430df1a5978d 100644
--- a/arch/arm/mm/iomap.c
+++ b/arch/arm/mm/iomap.c
@@ -9,6 +9,9 @@
#include <linux/ioport.h>
#include <linux/io.h>
+unsigned long vga_base;
+EXPORT_SYMBOL(vga_base);
+
#ifdef __io
void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
@@ -23,6 +26,15 @@ EXPORT_SYMBOL(ioport_unmap);
#endif
#ifdef CONFIG_PCI
+unsigned long pcibios_min_io = 0x1000;
+EXPORT_SYMBOL(pcibios_min_io);
+
+unsigned long pcibios_min_mem = 0x01000000;
+EXPORT_SYMBOL(pcibios_min_mem);
+
+unsigned int pci_flags = PCI_REASSIGN_ALL_RSRC;
+EXPORT_SYMBOL(pci_flags);
+
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
resource_size_t start = pci_resource_start(dev, bar);
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 5b3d7d543659..010566799c80 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -23,5 +23,11 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
#endif
+#ifdef CONFIG_ZONE_DMA
+extern u32 arm_dma_limit;
+#else
+#define arm_dma_limit ((u32)~0)
+#endif
+
void __init bootmem_init(void);
void arm_mm_memblock_reserve(void);
diff --git a/arch/arm/mm/pabort-legacy.S b/arch/arm/mm/pabort-legacy.S
index 87970eba88ea..8bbff025269a 100644
--- a/arch/arm/mm/pabort-legacy.S
+++ b/arch/arm/mm/pabort-legacy.S
@@ -4,16 +4,18 @@
/*
* Function: legacy_pabort
*
- * Params : r0 = address of aborted instruction
+ * Params : r2 = pt_regs
+ * : r4 = address of aborted instruction
+ * : r5 = psr for parent context
*
- * Returns : r0 = address of abort
- * : r1 = Simulated IFSR with section translation fault status
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current prefetch abort.
*/
.align 5
ENTRY(legacy_pabort)
+ mov r0, r4
mov r1, #5
- mov pc, lr
+ b do_PrefetchAbort
ENDPROC(legacy_pabort)
diff --git a/arch/arm/mm/pabort-v6.S b/arch/arm/mm/pabort-v6.S
index 06e3d1ef2115..9627646ce783 100644
--- a/arch/arm/mm/pabort-v6.S
+++ b/arch/arm/mm/pabort-v6.S
@@ -4,16 +4,18 @@
/*
* Function: v6_pabort
*
- * Params : r0 = address of aborted instruction
+ * Params : r2 = pt_regs
+ * : r4 = address of aborted instruction
+ * : r5 = psr for parent context
*
- * Returns : r0 = address of abort
- * : r1 = IFSR
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current prefetch abort.
*/
.align 5
ENTRY(v6_pabort)
+ mov r0, r4
mrc p15, 0, r1, c5, c0, 1 @ get IFSR
- mov pc, lr
+ b do_PrefetchAbort
ENDPROC(v6_pabort)
diff --git a/arch/arm/mm/pabort-v7.S b/arch/arm/mm/pabort-v7.S
index a8b3b300a18d..875761f44f3b 100644
--- a/arch/arm/mm/pabort-v7.S
+++ b/arch/arm/mm/pabort-v7.S
@@ -2,12 +2,13 @@
#include <asm/assembler.h>
/*
- * Function: v6_pabort
+ * Function: v7_pabort
*
- * Params : r0 = address of aborted instruction
+ * Params : r2 = pt_regs
+ * : r4 = address of aborted instruction
+ * : r5 = psr for parent context
*
- * Returns : r0 = address of abort
- * : r1 = IFSR
+ * Returns : r4 - r11, r13 preserved
*
* Purpose : obtain information about current prefetch abort.
*/
@@ -16,5 +17,5 @@
ENTRY(v7_pabort)
mrc p15, 0, r0, c6, c0, 2 @ get IFAR
mrc p15, 0, r1, c5, c0, 1 @ get IFSR
- mov pc, lr
+ b do_PrefetchAbort
ENDPROC(v7_pabort)
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 6c4e7fd6c8af..67469665d47a 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -364,17 +364,8 @@ ENTRY(arm1020_dma_unmap_area)
mov pc, lr
ENDPROC(arm1020_dma_unmap_area)
-ENTRY(arm1020_cache_fns)
- .long arm1020_flush_icache_all
- .long arm1020_flush_kern_cache_all
- .long arm1020_flush_user_cache_all
- .long arm1020_flush_user_cache_range
- .long arm1020_coherent_kern_range
- .long arm1020_coherent_user_range
- .long arm1020_flush_kern_dcache_area
- .long arm1020_dma_map_area
- .long arm1020_dma_unmap_area
- .long arm1020_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm1020
.align 5
ENTRY(cpu_arm1020_dcache_clean_area)
@@ -477,38 +468,14 @@ arm1020_crval:
crval clear=0x0000593f, mmuset=0x00003935, ucset=0x00001930
__INITDATA
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm1020, dabort=v4t_early_abort, pabort=legacy_pabort
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm1020_processor_functions, #object
-arm1020_processor_functions:
- .word v4t_early_abort
- .word legacy_pabort
- .word cpu_arm1020_proc_init
- .word cpu_arm1020_proc_fin
- .word cpu_arm1020_reset
- .word cpu_arm1020_do_idle
- .word cpu_arm1020_dcache_clean_area
- .word cpu_arm1020_switch_mm
- .word cpu_arm1020_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm1020_processor_functions, . - arm1020_processor_functions
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
+ string cpu_arch_name, "armv5t"
+ string cpu_elf_name, "v5"
.type cpu_arm1020_name, #object
cpu_arm1020_name:
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 4ce947c19623..4251421c0ed5 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -350,17 +350,8 @@ ENTRY(arm1020e_dma_unmap_area)
mov pc, lr
ENDPROC(arm1020e_dma_unmap_area)
-ENTRY(arm1020e_cache_fns)
- .long arm1020e_flush_icache_all
- .long arm1020e_flush_kern_cache_all
- .long arm1020e_flush_user_cache_all
- .long arm1020e_flush_user_cache_range
- .long arm1020e_coherent_kern_range
- .long arm1020e_coherent_user_range
- .long arm1020e_flush_kern_dcache_area
- .long arm1020e_dma_map_area
- .long arm1020e_dma_unmap_area
- .long arm1020e_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm1020e
.align 5
ENTRY(cpu_arm1020e_dcache_clean_area)
@@ -458,43 +449,14 @@ arm1020e_crval:
crval clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001930
__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm1020e_processor_functions, #object
-arm1020e_processor_functions:
- .word v4t_early_abort
- .word legacy_pabort
- .word cpu_arm1020e_proc_init
- .word cpu_arm1020e_proc_fin
- .word cpu_arm1020e_reset
- .word cpu_arm1020e_do_idle
- .word cpu_arm1020e_dcache_clean_area
- .word cpu_arm1020e_switch_mm
- .word cpu_arm1020e_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm1020e_processor_functions, . - arm1020e_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm1020e, dabort=v4t_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5te"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm1020e_name, #object
-cpu_arm1020e_name:
- .asciz "ARM1020E"
- .size cpu_arm1020e_name, . - cpu_arm1020e_name
+ string cpu_arch_name, "armv5te"
+ string cpu_elf_name, "v5"
+ string cpu_arm1020e_name, "ARM1020E"
.align
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index c8884c5413a2..d283cf3d06e3 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -339,17 +339,8 @@ ENTRY(arm1022_dma_unmap_area)
mov pc, lr
ENDPROC(arm1022_dma_unmap_area)
-ENTRY(arm1022_cache_fns)
- .long arm1022_flush_icache_all
- .long arm1022_flush_kern_cache_all
- .long arm1022_flush_user_cache_all
- .long arm1022_flush_user_cache_range
- .long arm1022_coherent_kern_range
- .long arm1022_coherent_user_range
- .long arm1022_flush_kern_dcache_area
- .long arm1022_dma_map_area
- .long arm1022_dma_unmap_area
- .long arm1022_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm1022
.align 5
ENTRY(cpu_arm1022_dcache_clean_area)
@@ -441,43 +432,14 @@ arm1022_crval:
crval clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001930
__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm1022_processor_functions, #object
-arm1022_processor_functions:
- .word v4t_early_abort
- .word legacy_pabort
- .word cpu_arm1022_proc_init
- .word cpu_arm1022_proc_fin
- .word cpu_arm1022_reset
- .word cpu_arm1022_do_idle
- .word cpu_arm1022_dcache_clean_area
- .word cpu_arm1022_switch_mm
- .word cpu_arm1022_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm1022_processor_functions, . - arm1022_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm1022, dabort=v4t_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5te"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm1022_name, #object
-cpu_arm1022_name:
- .asciz "ARM1022"
- .size cpu_arm1022_name, . - cpu_arm1022_name
+ string cpu_arch_name, "armv5te"
+ string cpu_elf_name, "v5"
+ string cpu_arm1022_name, "ARM1022"
.align
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 413684660aad..678a1ceafed2 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -333,17 +333,8 @@ ENTRY(arm1026_dma_unmap_area)
mov pc, lr
ENDPROC(arm1026_dma_unmap_area)
-ENTRY(arm1026_cache_fns)
- .long arm1026_flush_icache_all
- .long arm1026_flush_kern_cache_all
- .long arm1026_flush_user_cache_all
- .long arm1026_flush_user_cache_range
- .long arm1026_coherent_kern_range
- .long arm1026_coherent_user_range
- .long arm1026_flush_kern_dcache_area
- .long arm1026_dma_map_area
- .long arm1026_dma_unmap_area
- .long arm1026_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm1026
.align 5
ENTRY(cpu_arm1026_dcache_clean_area)
@@ -436,45 +427,15 @@ arm1026_crval:
crval clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001934
__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm1026_processor_functions, #object
-arm1026_processor_functions:
- .word v5t_early_abort
- .word legacy_pabort
- .word cpu_arm1026_proc_init
- .word cpu_arm1026_proc_fin
- .word cpu_arm1026_reset
- .word cpu_arm1026_do_idle
- .word cpu_arm1026_dcache_clean_area
- .word cpu_arm1026_switch_mm
- .word cpu_arm1026_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm1026_processor_functions, . - arm1026_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm1026, dabort=v5t_early_abort, pabort=legacy_pabort
.section .rodata
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5tej"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
+ string cpu_arch_name, "armv5tej"
+ string cpu_elf_name, "v5"
.align
-
- .type cpu_arm1026_name, #object
-cpu_arm1026_name:
- .asciz "ARM1026EJ-S"
- .size cpu_arm1026_name, . - cpu_arm1026_name
-
+ string cpu_arm1026_name, "ARM1026EJ-S"
.align
.section ".proc.info.init", #alloc, #execinstr
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 5f79dc4ce3fb..e5b974cddac3 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -29,19 +29,19 @@ ENTRY(cpu_arm7_dcache_clean_area)
/*
* Function: arm6_7_data_abort ()
*
- * Params : r2 = address of aborted instruction
- * : sp = pointer to registers
+ * Params : r2 = pt_regs
+ * : r4 = aborted context pc
+ * : r5 = aborted context psr
*
* Purpose : obtain information about current aborted instruction
*
- * Returns : r0 = address of abort
- * : r1 = FSR
+ * Returns : r4-r5, r10-r11, r13 preserved
*/
ENTRY(cpu_arm7_data_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
- ldr r8, [r2] @ read arm instruction
+ ldr r8, [r4] @ read arm instruction
tst r8, #1 << 20 @ L = 0 -> write?
orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #15 << 24
@@ -49,7 +49,7 @@ ENTRY(cpu_arm7_data_abort)
nop
/* 0 */ b .data_unknown
-/* 1 */ mov pc, lr @ swp
+/* 1 */ b do_DataAbort @ swp
/* 2 */ b .data_unknown
/* 3 */ b .data_unknown
/* 4 */ b .data_arm_lateldrpostconst @ ldr rd, [rn], #m
@@ -60,87 +60,85 @@ ENTRY(cpu_arm7_data_abort)
/* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist>
/* a */ b .data_unknown
/* b */ b .data_unknown
-/* c */ mov pc, lr @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
-/* d */ mov pc, lr @ ldc rd, [rn, #m]
+/* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
+/* d */ b do_DataAbort @ ldc rd, [rn, #m]
/* e */ b .data_unknown
/* f */
.data_unknown: @ Part of jumptable
- mov r0, r2
+ mov r0, r4
mov r1, r8
- mov r2, sp
- bl baddataabort
- b ret_from_exception
+ b baddataabort
ENTRY(cpu_arm6_data_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
- ldr r8, [r2] @ read arm instruction
+ ldr r8, [r4] @ read arm instruction
tst r8, #1 << 20 @ L = 0 -> write?
orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #14 << 24
teq r7, #8 << 24 @ was it ldm/stm
- movne pc, lr
+ bne do_DataAbort
.data_arm_ldmstm:
tst r8, #1 << 21 @ check writeback bit
- moveq pc, lr @ no writeback -> no fixup
+ beq do_DataAbort @ no writeback -> no fixup
mov r7, #0x11
orr r7, r7, #0x1100
and r6, r8, r7
- and r2, r8, r7, lsl #1
- add r6, r6, r2, lsr #1
- and r2, r8, r7, lsl #2
- add r6, r6, r2, lsr #2
- and r2, r8, r7, lsl #3
- add r6, r6, r2, lsr #3
+ and r9, r8, r7, lsl #1
+ add r6, r6, r9, lsr #1
+ and r9, r8, r7, lsl #2
+ add r6, r6, r9, lsr #2
+ and r9, r8, r7, lsl #3
+ add r6, r6, r9, lsr #3
add r6, r6, r6, lsr #8
add r6, r6, r6, lsr #4
and r6, r6, #15 @ r6 = no. of registers to transfer.
- and r5, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ and r9, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
tst r8, #1 << 23 @ Check U bit
subne r7, r7, r6, lsl #2 @ Undo increment
addeq r7, r7, r6, lsl #2 @ Undo decrement
- str r7, [sp, r5, lsr #14] @ Put register 'Rn'
- mov pc, lr
+ str r7, [r2, r9, lsr #14] @ Put register 'Rn'
+ b do_DataAbort
.data_arm_apply_r6_and_rn:
- and r5, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ and r9, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
tst r8, #1 << 23 @ Check U bit
subne r7, r7, r6 @ Undo incrmenet
addeq r7, r7, r6 @ Undo decrement
- str r7, [sp, r5, lsr #14] @ Put register 'Rn'
- mov pc, lr
+ str r7, [r2, r9, lsr #14] @ Put register 'Rn'
+ b do_DataAbort
.data_arm_lateldrpreconst:
tst r8, #1 << 21 @ check writeback bit
- moveq pc, lr @ no writeback -> no fixup
+ beq do_DataAbort @ no writeback -> no fixup
.data_arm_lateldrpostconst:
- movs r2, r8, lsl #20 @ Get offset
- moveq pc, lr @ zero -> no fixup
- and r5, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ movs r6, r8, lsl #20 @ Get offset
+ beq do_DataAbort @ zero -> no fixup
+ and r9, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
tst r8, #1 << 23 @ Check U bit
- subne r7, r7, r2, lsr #20 @ Undo increment
- addeq r7, r7, r2, lsr #20 @ Undo decrement
- str r7, [sp, r5, lsr #14] @ Put register 'Rn'
- mov pc, lr
+ subne r7, r7, r6, lsr #20 @ Undo increment
+ addeq r7, r7, r6, lsr #20 @ Undo decrement
+ str r7, [r2, r9, lsr #14] @ Put register 'Rn'
+ b do_DataAbort
.data_arm_lateldrprereg:
tst r8, #1 << 21 @ check writeback bit
- moveq pc, lr @ no writeback -> no fixup
+ beq do_DataAbort @ no writeback -> no fixup
.data_arm_lateldrpostreg:
and r7, r8, #15 @ Extract 'm' from instruction
- ldr r6, [sp, r7, lsl #2] @ Get register 'Rm'
- mov r5, r8, lsr #7 @ get shift count
- ands r5, r5, #31
+ ldr r6, [r2, r7, lsl #2] @ Get register 'Rm'
+ mov r9, r8, lsr #7 @ get shift count
+ ands r9, r9, #31
and r7, r8, #0x70 @ get shift type
orreq r7, r7, #8 @ shift count = 0
add pc, pc, r7
nop
- mov r6, r6, lsl r5 @ 0: LSL #!0
+ mov r6, r6, lsl r9 @ 0: LSL #!0
b .data_arm_apply_r6_and_rn
b .data_arm_apply_r6_and_rn @ 1: LSL #0
nop
@@ -148,7 +146,7 @@ ENTRY(cpu_arm6_data_abort)
nop
b .data_unknown @ 3: MUL?
nop
- mov r6, r6, lsr r5 @ 4: LSR #!0
+ mov r6, r6, lsr r9 @ 4: LSR #!0
b .data_arm_apply_r6_and_rn
mov r6, r6, lsr #32 @ 5: LSR #32
b .data_arm_apply_r6_and_rn
@@ -156,7 +154,7 @@ ENTRY(cpu_arm6_data_abort)
nop
b .data_unknown @ 7: MUL?
nop
- mov r6, r6, asr r5 @ 8: ASR #!0
+ mov r6, r6, asr r9 @ 8: ASR #!0
b .data_arm_apply_r6_and_rn
mov r6, r6, asr #32 @ 9: ASR #32
b .data_arm_apply_r6_and_rn
@@ -164,7 +162,7 @@ ENTRY(cpu_arm6_data_abort)
nop
b .data_unknown @ B: MUL?
nop
- mov r6, r6, ror r5 @ C: ROR #!0
+ mov r6, r6, ror r9 @ C: ROR #!0
b .data_arm_apply_r6_and_rn
mov r6, r6, rrx @ D: RRX
b .data_arm_apply_r6_and_rn
@@ -269,159 +267,57 @@ __arm7_setup: mov r0, #0
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm6_processor_functions, #object
-ENTRY(arm6_processor_functions)
- .word cpu_arm6_data_abort
- .word legacy_pabort
- .word cpu_arm6_proc_init
- .word cpu_arm6_proc_fin
- .word cpu_arm6_reset
- .word cpu_arm6_do_idle
- .word cpu_arm6_dcache_clean_area
- .word cpu_arm6_switch_mm
- .word cpu_arm6_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm6_processor_functions, . - arm6_processor_functions
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm7_processor_functions, #object
-ENTRY(arm7_processor_functions)
- .word cpu_arm7_data_abort
- .word legacy_pabort
- .word cpu_arm7_proc_init
- .word cpu_arm7_proc_fin
- .word cpu_arm7_reset
- .word cpu_arm7_do_idle
- .word cpu_arm7_dcache_clean_area
- .word cpu_arm7_switch_mm
- .word cpu_arm7_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm7_processor_functions, . - arm7_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm6, dabort=cpu_arm6_data_abort, pabort=legacy_pabort
+ define_processor_functions arm7, dabort=cpu_arm7_data_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name: .asciz "armv3"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name: .asciz "v3"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm6_name, #object
-cpu_arm6_name: .asciz "ARM6"
- .size cpu_arm6_name, . - cpu_arm6_name
-
- .type cpu_arm610_name, #object
-cpu_arm610_name:
- .asciz "ARM610"
- .size cpu_arm610_name, . - cpu_arm610_name
-
- .type cpu_arm7_name, #object
-cpu_arm7_name: .asciz "ARM7"
- .size cpu_arm7_name, . - cpu_arm7_name
-
- .type cpu_arm710_name, #object
-cpu_arm710_name:
- .asciz "ARM710"
- .size cpu_arm710_name, . - cpu_arm710_name
+ string cpu_arch_name, "armv3"
+ string cpu_elf_name, "v3"
+ string cpu_arm6_name, "ARM6"
+ string cpu_arm610_name, "ARM610"
+ string cpu_arm7_name, "ARM7"
+ string cpu_arm710_name, "ARM710"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __arm6_proc_info, #object
-__arm6_proc_info:
- .long 0x41560600
- .long 0xfffffff0
- .long 0x00000c1e
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __arm6_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_26BIT
- .long cpu_arm6_name
- .long arm6_processor_functions
- .long v3_tlb_fns
- .long v3_user_fns
- .long v3_cache_fns
- .size __arm6_proc_info, . - __arm6_proc_info
-
- .type __arm610_proc_info, #object
-__arm610_proc_info:
- .long 0x41560610
- .long 0xfffffff0
- .long 0x00000c1e
+.macro arm67_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, \
+ cpu_mm_mmu_flags:req, cpu_flush:req, cpu_proc_funcs:req
+ .type __\name\()_proc_info, #object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
+ .long \cpu_mm_mmu_flags
.long PMD_TYPE_SECT | \
PMD_BIT4 | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
- b __arm6_setup
+ b \cpu_flush
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_26BIT
- .long cpu_arm610_name
- .long arm6_processor_functions
+ .long \cpu_name
+ .long \cpu_proc_funcs
.long v3_tlb_fns
.long v3_user_fns
.long v3_cache_fns
- .size __arm610_proc_info, . - __arm610_proc_info
-
- .type __arm7_proc_info, #object
-__arm7_proc_info:
- .long 0x41007000
- .long 0xffffff00
- .long 0x00000c1e
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __arm7_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_26BIT
- .long cpu_arm7_name
- .long arm7_processor_functions
- .long v3_tlb_fns
- .long v3_user_fns
- .long v3_cache_fns
- .size __arm7_proc_info, . - __arm7_proc_info
-
- .type __arm710_proc_info, #object
-__arm710_proc_info:
- .long 0x41007100
- .long 0xfff8ff00
- .long PMD_TYPE_SECT | \
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
+
+ arm67_proc_info arm6, 0x41560600, 0xfffffff0, cpu_arm6_name, \
+ 0x00000c1e, __arm6_setup, arm6_processor_functions
+ arm67_proc_info arm610, 0x41560610, 0xfffffff0, cpu_arm610_name, \
+ 0x00000c1e, __arm6_setup, arm6_processor_functions
+ arm67_proc_info arm7, 0x41007000, 0xffffff00, cpu_arm7_name, \
+ 0x00000c1e, __arm7_setup, arm7_processor_functions
+ arm67_proc_info arm710, 0x41007100, 0xfff8ff00, cpu_arm710_name, \
+ PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
PMD_BIT4 | \
PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __arm7_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_26BIT
- .long cpu_arm710_name
- .long arm7_processor_functions
- .long v3_tlb_fns
- .long v3_user_fns
- .long v3_cache_fns
- .size __arm710_proc_info, . - __arm710_proc_info
+ PMD_SECT_AP_READ, \
+ __arm7_setup, arm7_processor_functions
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 7a06e5964f59..55f4e290665a 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -169,46 +169,15 @@ arm720_crval:
crval clear=0x00002f3f, mmuset=0x0000213d, ucset=0x00000130
__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm720_processor_functions, #object
-ENTRY(arm720_processor_functions)
- .word v4t_late_abort
- .word legacy_pabort
- .word cpu_arm720_proc_init
- .word cpu_arm720_proc_fin
- .word cpu_arm720_reset
- .word cpu_arm720_do_idle
- .word cpu_arm720_dcache_clean_area
- .word cpu_arm720_switch_mm
- .word cpu_arm720_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm720_processor_functions, . - arm720_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm720, dabort=v4t_late_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name: .asciz "armv4t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name: .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm710_name, #object
-cpu_arm710_name:
- .asciz "ARM710T"
- .size cpu_arm710_name, . - cpu_arm710_name
-
- .type cpu_arm720_name, #object
-cpu_arm720_name:
- .asciz "ARM720T"
- .size cpu_arm720_name, . - cpu_arm720_name
+ string cpu_arch_name, "armv4t"
+ string cpu_elf_name, "v4"
+ string cpu_arm710_name, "ARM710T"
+ string cpu_arm720_name, "ARM720T"
.align
@@ -218,10 +187,11 @@ cpu_arm720_name:
.section ".proc.info.init", #alloc, #execinstr
- .type __arm710_proc_info, #object
-__arm710_proc_info:
- .long 0x41807100 @ cpu_val
- .long 0xffffff00 @ cpu_mask
+.macro arm720_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cpu_flush:req
+ .type __\name\()_proc_info,#object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
.long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
@@ -232,38 +202,17 @@ __arm710_proc_info:
PMD_BIT4 | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
- b __arm710_setup @ cpu_flush
+ b \cpu_flush @ cpu_flush
.long cpu_arch_name @ arch_name
.long cpu_elf_name @ elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB @ elf_hwcap
- .long cpu_arm710_name @ name
+ .long \cpu_name
.long arm720_processor_functions
.long v4_tlb_fns
.long v4wt_user_fns
.long v4_cache_fns
- .size __arm710_proc_info, . - __arm710_proc_info
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
- .type __arm720_proc_info, #object
-__arm720_proc_info:
- .long 0x41807200 @ cpu_val
- .long 0xffffff00 @ cpu_mask
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __arm720_setup @ cpu_flush
- .long cpu_arch_name @ arch_name
- .long cpu_elf_name @ elf_name
- .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB @ elf_hwcap
- .long cpu_arm720_name @ name
- .long arm720_processor_functions
- .long v4_tlb_fns
- .long v4wt_user_fns
- .long v4_cache_fns
- .size __arm720_proc_info, . - __arm720_proc_info
+ arm720_proc_info arm710, 0x41807100, 0xffffff00, cpu_arm710_name, __arm710_setup
+ arm720_proc_info arm720, 0x41807200, 0xffffff00, cpu_arm720_name, __arm720_setup
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 6f9d12effee1..4506be3adda6 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -17,6 +17,8 @@
#include <asm/pgtable.h>
#include <asm/ptrace.h>
+#include "proc-macros.S"
+
.text
/*
* cpu_arm740_proc_init()
@@ -115,42 +117,14 @@ __arm740_setup:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm740_processor_functions, #object
-ENTRY(arm740_processor_functions)
- .word v4t_late_abort
- .word legacy_pabort
- .word cpu_arm740_proc_init
- .word cpu_arm740_proc_fin
- .word cpu_arm740_reset
- .word cpu_arm740_do_idle
- .word cpu_arm740_dcache_clean_area
- .word cpu_arm740_switch_mm
- .word 0 @ cpu_*_set_pte
- .word 0
- .word 0
- .word 0
- .size arm740_processor_functions, . - arm740_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm740, dabort=v4t_late_abort, pabort=legacy_pabort, nommu=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm740_name, #object
-cpu_arm740_name:
- .ascii "ARM740T"
- .size cpu_arm740_name, . - cpu_arm740_name
+ string cpu_arch_name, "armv4"
+ string cpu_elf_name, "v4"
+ string cpu_arm740_name, "ARM740T"
.align
@@ -170,5 +144,3 @@ __arm740_proc_info:
.long 0
.long v3_cache_fns @ cache model
.size __arm740_proc_info, . - __arm740_proc_info
-
-
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 537ffcb0646d..7e0e1fe4ed4d 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -17,6 +17,8 @@
#include <asm/pgtable.h>
#include <asm/ptrace.h>
+#include "proc-macros.S"
+
.text
/*
* cpu_arm7tdmi_proc_init()
@@ -55,197 +57,57 @@ __arm7tdmi_setup:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm7tdmi_processor_functions, #object
-ENTRY(arm7tdmi_processor_functions)
- .word v4t_late_abort
- .word legacy_pabort
- .word cpu_arm7tdmi_proc_init
- .word cpu_arm7tdmi_proc_fin
- .word cpu_arm7tdmi_reset
- .word cpu_arm7tdmi_do_idle
- .word cpu_arm7tdmi_dcache_clean_area
- .word cpu_arm7tdmi_switch_mm
- .word 0 @ cpu_*_set_pte
- .word 0
- .word 0
- .word 0
- .size arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm7tdmi, dabort=v4t_late_abort, pabort=legacy_pabort, nommu=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm7tdmi_name, #object
-cpu_arm7tdmi_name:
- .asciz "ARM7TDMI"
- .size cpu_arm7tdmi_name, . - cpu_arm7tdmi_name
-
- .type cpu_triscenda7_name, #object
-cpu_triscenda7_name:
- .asciz "Triscend-A7x"
- .size cpu_triscenda7_name, . - cpu_triscenda7_name
-
- .type cpu_at91_name, #object
-cpu_at91_name:
- .asciz "Atmel-AT91M40xxx"
- .size cpu_at91_name, . - cpu_at91_name
-
- .type cpu_s3c3410_name, #object
-cpu_s3c3410_name:
- .asciz "Samsung-S3C3410"
- .size cpu_s3c3410_name, . - cpu_s3c3410_name
-
- .type cpu_s3c44b0x_name, #object
-cpu_s3c44b0x_name:
- .asciz "Samsung-S3C44B0x"
- .size cpu_s3c44b0x_name, . - cpu_s3c44b0x_name
-
- .type cpu_s3c4510b, #object
-cpu_s3c4510b_name:
- .asciz "Samsung-S3C4510B"
- .size cpu_s3c4510b_name, . - cpu_s3c4510b_name
-
- .type cpu_s3c4530_name, #object
-cpu_s3c4530_name:
- .asciz "Samsung-S3C4530"
- .size cpu_s3c4530_name, . - cpu_s3c4530_name
-
- .type cpu_netarm_name, #object
-cpu_netarm_name:
- .asciz "NETARM"
- .size cpu_netarm_name, . - cpu_netarm_name
+ string cpu_arch_name, "armv4t"
+ string cpu_elf_name, "v4"
+ string cpu_arm7tdmi_name, "ARM7TDMI"
+ string cpu_triscenda7_name, "Triscend-A7x"
+ string cpu_at91_name, "Atmel-AT91M40xxx"
+ string cpu_s3c3410_name, "Samsung-S3C3410"
+ string cpu_s3c44b0x_name, "Samsung-S3C44B0x"
+ string cpu_s3c4510b_name, "Samsung-S3C4510B"
+ string cpu_s3c4530_name, "Samsung-S3C4530"
+ string cpu_netarm_name, "NETARM"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __arm7tdmi_proc_info, #object
-__arm7tdmi_proc_info:
- .long 0x41007700
- .long 0xfff8ff00
- .long 0
- .long 0
- b __arm7tdmi_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_26BIT
- .long cpu_arm7tdmi_name
- .long arm7tdmi_processor_functions
- .long 0
- .long 0
- .long v4_cache_fns
- .size __arm7tdmi_proc_info, . - __arm7tdmi_proc_info
-
- .type __triscenda7_proc_info, #object
-__triscenda7_proc_info:
- .long 0x0001d2ff
- .long 0x0001ffff
- .long 0
- .long 0
- b __arm7tdmi_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_triscenda7_name
- .long arm7tdmi_processor_functions
- .long 0
- .long 0
- .long v4_cache_fns
- .size __triscenda7_proc_info, . - __triscenda7_proc_info
-
- .type __at91_proc_info, #object
-__at91_proc_info:
- .long 0x14000040
- .long 0xfff000e0
- .long 0
- .long 0
- b __arm7tdmi_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_at91_name
- .long arm7tdmi_processor_functions
- .long 0
- .long 0
- .long v4_cache_fns
- .size __at91_proc_info, . - __at91_proc_info
-
- .type __s3c4510b_proc_info, #object
-__s3c4510b_proc_info:
- .long 0x36365000
- .long 0xfffff000
- .long 0
- .long 0
- b __arm7tdmi_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_s3c4510b_name
- .long arm7tdmi_processor_functions
- .long 0
- .long 0
- .long v4_cache_fns
- .size __s3c4510b_proc_info, . - __s3c4510b_proc_info
-
- .type __s3c4530_proc_info, #object
-__s3c4530_proc_info:
- .long 0x4c000000
- .long 0xfff000e0
- .long 0
- .long 0
- b __arm7tdmi_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_s3c4530_name
- .long arm7tdmi_processor_functions
- .long 0
- .long 0
- .long v4_cache_fns
- .size __s3c4530_proc_info, . - __s3c4530_proc_info
-
- .type __s3c3410_proc_info, #object
-__s3c3410_proc_info:
- .long 0x34100000
- .long 0xffff0000
- .long 0
- .long 0
- b __arm7tdmi_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_s3c3410_name
- .long arm7tdmi_processor_functions
- .long 0
- .long 0
- .long v4_cache_fns
- .size __s3c3410_proc_info, . - __s3c3410_proc_info
-
- .type __s3c44b0x_proc_info, #object
-__s3c44b0x_proc_info:
- .long 0x44b00000
- .long 0xffff0000
+.macro arm7tdmi_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, \
+ extra_hwcaps=0
+ .type __\name\()_proc_info, #object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
.long 0
.long 0
b __arm7tdmi_setup
.long cpu_arch_name
.long cpu_elf_name
- .long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_s3c44b0x_name
+ .long HWCAP_SWP | HWCAP_26BIT | ( \extra_hwcaps )
+ .long \cpu_name
.long arm7tdmi_processor_functions
.long 0
.long 0
.long v4_cache_fns
- .size __s3c44b0x_proc_info, . - __s3c44b0x_proc_info
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
+
+ arm7tdmi_proc_info arm7tdmi, 0x41007700, 0xfff8ff00, \
+ cpu_arm7tdmi_name
+ arm7tdmi_proc_info triscenda7, 0x0001d2ff, 0x0001ffff, \
+ cpu_triscenda7_name, extra_hwcaps=HWCAP_THUMB
+ arm7tdmi_proc_info at91, 0x14000040, 0xfff000e0, \
+ cpu_at91_name, extra_hwcaps=HWCAP_THUMB
+ arm7tdmi_proc_info s3c4510b, 0x36365000, 0xfffff000, \
+ cpu_s3c4510b_name, extra_hwcaps=HWCAP_THUMB
+ arm7tdmi_proc_info s3c4530, 0x4c000000, 0xfff000e0, \
+ cpu_s3c4530_name, extra_hwcaps=HWCAP_THUMB
+ arm7tdmi_proc_info s3c3410, 0x34100000, 0xffff0000, \
+ cpu_s3c3410_name, extra_hwcaps=HWCAP_THUMB
+ arm7tdmi_proc_info s3c44b0x, 0x44b00000, 0xffff0000, \
+ cpu_s3c44b0x_name, extra_hwcaps=HWCAP_THUMB
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index bf8a1d1cccb6..92bd102e3982 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -315,18 +315,8 @@ ENTRY(arm920_dma_unmap_area)
mov pc, lr
ENDPROC(arm920_dma_unmap_area)
-ENTRY(arm920_cache_fns)
- .long arm920_flush_icache_all
- .long arm920_flush_kern_cache_all
- .long arm920_flush_user_cache_all
- .long arm920_flush_user_cache_range
- .long arm920_coherent_kern_range
- .long arm920_coherent_user_range
- .long arm920_flush_kern_dcache_area
- .long arm920_dma_map_area
- .long arm920_dma_unmap_area
- .long arm920_dma_flush_range
-
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm920
#endif
@@ -416,9 +406,6 @@ ENTRY(cpu_arm920_do_resume)
PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
b cpu_resume_mmu
ENDPROC(cpu_arm920_do_resume)
-#else
-#define cpu_arm920_do_suspend 0
-#define cpu_arm920_do_resume 0
#endif
__CPUINIT
@@ -450,43 +437,14 @@ arm920_crval:
crval clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130
__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm920_processor_functions, #object
-arm920_processor_functions:
- .word v4t_early_abort
- .word legacy_pabort
- .word cpu_arm920_proc_init
- .word cpu_arm920_proc_fin
- .word cpu_arm920_reset
- .word cpu_arm920_do_idle
- .word cpu_arm920_dcache_clean_area
- .word cpu_arm920_switch_mm
- .word cpu_arm920_set_pte_ext
- .word cpu_arm920_suspend_size
- .word cpu_arm920_do_suspend
- .word cpu_arm920_do_resume
- .size arm920_processor_functions, . - arm920_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm920, dabort=v4t_early_abort, pabort=legacy_pabort, suspend=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm920_name, #object
-cpu_arm920_name:
- .asciz "ARM920T"
- .size cpu_arm920_name, . - cpu_arm920_name
+ string cpu_arch_name, "armv4t"
+ string cpu_elf_name, "v4"
+ string cpu_arm920_name, "ARM920T"
.align
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 95ba1fc56e4d..490e18833857 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -317,18 +317,8 @@ ENTRY(arm922_dma_unmap_area)
mov pc, lr
ENDPROC(arm922_dma_unmap_area)
-ENTRY(arm922_cache_fns)
- .long arm922_flush_icache_all
- .long arm922_flush_kern_cache_all
- .long arm922_flush_user_cache_all
- .long arm922_flush_user_cache_range
- .long arm922_coherent_kern_range
- .long arm922_coherent_user_range
- .long arm922_flush_kern_dcache_area
- .long arm922_dma_map_area
- .long arm922_dma_unmap_area
- .long arm922_dma_flush_range
-
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm922
#endif
@@ -420,43 +410,14 @@ arm922_crval:
crval clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130
__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm922_processor_functions, #object
-arm922_processor_functions:
- .word v4t_early_abort
- .word legacy_pabort
- .word cpu_arm922_proc_init
- .word cpu_arm922_proc_fin
- .word cpu_arm922_reset
- .word cpu_arm922_do_idle
- .word cpu_arm922_dcache_clean_area
- .word cpu_arm922_switch_mm
- .word cpu_arm922_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm922_processor_functions, . - arm922_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm922, dabort=v4t_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm922_name, #object
-cpu_arm922_name:
- .asciz "ARM922T"
- .size cpu_arm922_name, . - cpu_arm922_name
+ string cpu_arch_name, "armv4t"
+ string cpu_elf_name, "v4"
+ string cpu_arm922_name, "ARM922T"
.align
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 541e4774eea1..51d494be057e 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -372,17 +372,8 @@ ENTRY(arm925_dma_unmap_area)
mov pc, lr
ENDPROC(arm925_dma_unmap_area)
-ENTRY(arm925_cache_fns)
- .long arm925_flush_icache_all
- .long arm925_flush_kern_cache_all
- .long arm925_flush_user_cache_all
- .long arm925_flush_user_cache_range
- .long arm925_coherent_kern_range
- .long arm925_coherent_user_range
- .long arm925_flush_kern_dcache_area
- .long arm925_dma_map_area
- .long arm925_dma_unmap_area
- .long arm925_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm925
ENTRY(cpu_arm925_dcache_clean_area)
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -487,52 +478,24 @@ arm925_crval:
crval clear=0x00007f3f, mmuset=0x0000313d, ucset=0x00001130
__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm925_processor_functions, #object
-arm925_processor_functions:
- .word v4t_early_abort
- .word legacy_pabort
- .word cpu_arm925_proc_init
- .word cpu_arm925_proc_fin
- .word cpu_arm925_reset
- .word cpu_arm925_do_idle
- .word cpu_arm925_dcache_clean_area
- .word cpu_arm925_switch_mm
- .word cpu_arm925_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size arm925_processor_functions, . - arm925_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm925, dabort=v4t_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm925_name, #object
-cpu_arm925_name:
- .asciz "ARM925T"
- .size cpu_arm925_name, . - cpu_arm925_name
+ string cpu_arch_name, "armv4t"
+ string cpu_elf_name, "v4"
+ string cpu_arm925_name, "ARM925T"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __arm925_proc_info,#object
-__arm925_proc_info:
- .long 0x54029250
- .long 0xfffffff0
+.macro arm925_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache
+ .type __\name\()_proc_info,#object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
.long PMD_TYPE_SECT | \
PMD_BIT4 | \
PMD_SECT_AP_WRITE | \
@@ -550,27 +513,8 @@ __arm925_proc_info:
.long v4wbi_tlb_fns
.long v4wb_user_fns
.long arm925_cache_fns
- .size __arm925_proc_info, . - __arm925_proc_info
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
- .type __arm915_proc_info,#object
-__arm915_proc_info:
- .long 0x54029150
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __arm925_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
- .long cpu_arm925_name
- .long arm925_processor_functions
- .long v4wbi_tlb_fns
- .long v4wb_user_fns
- .long arm925_cache_fns
- .size __arm925_proc_info, . - __arm925_proc_info
+ arm925_proc_info arm925, 0x54029250, 0xfffffff0, cpu_arm925_name
+ arm925_proc_info arm915, 0x54029150, 0xfffffff0, cpu_arm925_name
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 0ed85d930c09..2bbcf053dffd 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -335,17 +335,8 @@ ENTRY(arm926_dma_unmap_area)
mov pc, lr
ENDPROC(arm926_dma_unmap_area)
-ENTRY(arm926_cache_fns)
- .long arm926_flush_icache_all
- .long arm926_flush_kern_cache_all
- .long arm926_flush_user_cache_all
- .long arm926_flush_user_cache_range
- .long arm926_coherent_kern_range
- .long arm926_coherent_user_range
- .long arm926_flush_kern_dcache_area
- .long arm926_dma_map_area
- .long arm926_dma_unmap_area
- .long arm926_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm926
ENTRY(cpu_arm926_dcache_clean_area)
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -430,9 +421,6 @@ ENTRY(cpu_arm926_do_resume)
PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
b cpu_resume_mmu
ENDPROC(cpu_arm926_do_resume)
-#else
-#define cpu_arm926_do_suspend 0
-#define cpu_arm926_do_resume 0
#endif
__CPUINIT
@@ -475,42 +463,14 @@ arm926_crval:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm926_processor_functions, #object
-arm926_processor_functions:
- .word v5tj_early_abort
- .word legacy_pabort
- .word cpu_arm926_proc_init
- .word cpu_arm926_proc_fin
- .word cpu_arm926_reset
- .word cpu_arm926_do_idle
- .word cpu_arm926_dcache_clean_area
- .word cpu_arm926_switch_mm
- .word cpu_arm926_set_pte_ext
- .word cpu_arm926_suspend_size
- .word cpu_arm926_do_suspend
- .word cpu_arm926_do_resume
- .size arm926_processor_functions, . - arm926_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm926, dabort=v5tj_early_abort, pabort=legacy_pabort, suspend=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5tej"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm926_name, #object
-cpu_arm926_name:
- .asciz "ARM926EJ-S"
- .size cpu_arm926_name, . - cpu_arm926_name
+ string cpu_arch_name, "armv5tej"
+ string cpu_elf_name, "v5"
+ string cpu_arm926_name, "ARM926EJ-S"
.align
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 26aea3f71c26..ac750d506153 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -264,17 +264,8 @@ ENTRY(arm940_dma_unmap_area)
mov pc, lr
ENDPROC(arm940_dma_unmap_area)
-ENTRY(arm940_cache_fns)
- .long arm940_flush_icache_all
- .long arm940_flush_kern_cache_all
- .long arm940_flush_user_cache_all
- .long arm940_flush_user_cache_range
- .long arm940_coherent_kern_range
- .long arm940_coherent_user_range
- .long arm940_flush_kern_dcache_area
- .long arm940_dma_map_area
- .long arm940_dma_unmap_area
- .long arm940_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm940
__CPUINIT
@@ -348,42 +339,14 @@ __arm940_setup:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm940_processor_functions, #object
-ENTRY(arm940_processor_functions)
- .word nommu_early_abort
- .word legacy_pabort
- .word cpu_arm940_proc_init
- .word cpu_arm940_proc_fin
- .word cpu_arm940_reset
- .word cpu_arm940_do_idle
- .word cpu_arm940_dcache_clean_area
- .word cpu_arm940_switch_mm
- .word 0 @ cpu_*_set_pte
- .word 0
- .word 0
- .word 0
- .size arm940_processor_functions, . - arm940_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm940, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
.section ".rodata"
-.type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm940_name, #object
-cpu_arm940_name:
- .ascii "ARM940T"
- .size cpu_arm940_name, . - cpu_arm940_name
+ string cpu_arch_name, "armv4t"
+ string cpu_elf_name, "v4"
+ string cpu_arm940_name, "ARM940T"
.align
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 8063345406fe..f8f7ea34bfc5 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -306,18 +306,8 @@ ENTRY(arm946_dma_unmap_area)
mov pc, lr
ENDPROC(arm946_dma_unmap_area)
-ENTRY(arm946_cache_fns)
- .long arm946_flush_icache_all
- .long arm946_flush_kern_cache_all
- .long arm946_flush_user_cache_all
- .long arm946_flush_user_cache_range
- .long arm946_coherent_kern_range
- .long arm946_coherent_user_range
- .long arm946_flush_kern_dcache_area
- .long arm946_dma_map_area
- .long arm946_dma_unmap_area
- .long arm946_dma_flush_range
-
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions arm946
ENTRY(cpu_arm946_dcache_clean_area)
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -403,43 +393,14 @@ __arm946_setup:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm946_processor_functions, #object
-ENTRY(arm946_processor_functions)
- .word nommu_early_abort
- .word legacy_pabort
- .word cpu_arm946_proc_init
- .word cpu_arm946_proc_fin
- .word cpu_arm946_reset
- .word cpu_arm946_do_idle
-
- .word cpu_arm946_dcache_clean_area
- .word cpu_arm946_switch_mm
- .word 0 @ cpu_*_set_pte
- .word 0
- .word 0
- .word 0
- .size arm946_processor_functions, . - arm946_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm946, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5te"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5t"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm946_name, #object
-cpu_arm946_name:
- .ascii "ARM946E-S"
- .size cpu_arm946_name, . - cpu_arm946_name
+ string cpu_arch_name, "armv5te"
+ string cpu_elf_name, "v5t"
+ string cpu_arm946_name, "ARM946E-S"
.align
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index 546b54da1005..2120f9e2af7f 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -17,6 +17,8 @@
#include <asm/pgtable.h>
#include <asm/ptrace.h>
+#include "proc-macros.S"
+
.text
/*
* cpu_arm9tdmi_proc_init()
@@ -55,82 +57,38 @@ __arm9tdmi_setup:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type arm9tdmi_processor_functions, #object
-ENTRY(arm9tdmi_processor_functions)
- .word nommu_early_abort
- .word legacy_pabort
- .word cpu_arm9tdmi_proc_init
- .word cpu_arm9tdmi_proc_fin
- .word cpu_arm9tdmi_reset
- .word cpu_arm9tdmi_do_idle
- .word cpu_arm9tdmi_dcache_clean_area
- .word cpu_arm9tdmi_switch_mm
- .word 0 @ cpu_*_set_pte
- .word 0
- .word 0
- .word 0
- .size arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions arm9tdmi, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_arm9tdmi_name, #object
-cpu_arm9tdmi_name:
- .asciz "ARM9TDMI"
- .size cpu_arm9tdmi_name, . - cpu_arm9tdmi_name
-
- .type cpu_p2001_name, #object
-cpu_p2001_name:
- .asciz "P2001"
- .size cpu_p2001_name, . - cpu_p2001_name
+ string cpu_arch_name, "armv4t"
+ string cpu_elf_name, "v4"
+ string cpu_arm9tdmi_name, "ARM9TDMI"
+ string cpu_p2001_name, "P2001"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __arm9tdmi_proc_info, #object
-__arm9tdmi_proc_info:
- .long 0x41009900
- .long 0xfff8ff00
+.macro arm9tdmi_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req
+ .type __\name\()_proc_info, #object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
.long 0
.long 0
b __arm9tdmi_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_arm9tdmi_name
+ .long \cpu_name
.long arm9tdmi_processor_functions
.long 0
.long 0
.long v4_cache_fns
- .size __arm9tdmi_proc_info, . - __arm9tdmi_proc_info
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
- .type __p2001_proc_info, #object
-__p2001_proc_info:
- .long 0x41029000
- .long 0xffffffff
- .long 0
- .long 0
- b __arm9tdmi_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
- .long cpu_p2001_name
- .long arm9tdmi_processor_functions
- .long 0
- .long 0
- .long v4_cache_fns
- .size __p2001_proc_info, . - __p2001_proc_info
+ arm9tdmi_proc_info arm9tdmi, 0x41009900, 0xfff8ff00, cpu_arm9tdmi_name
+ arm9tdmi_proc_info p2001, 0x41029000, 0xffffffff, cpu_p2001_name
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index fc2a4ae15cf4..4c7a5710472b 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -180,42 +180,14 @@ fa526_cr1_set:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type fa526_processor_functions, #object
-fa526_processor_functions:
- .word v4_early_abort
- .word legacy_pabort
- .word cpu_fa526_proc_init
- .word cpu_fa526_proc_fin
- .word cpu_fa526_reset
- .word cpu_fa526_do_idle
- .word cpu_fa526_dcache_clean_area
- .word cpu_fa526_switch_mm
- .word cpu_fa526_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size fa526_processor_functions, . - fa526_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions fa526, dabort=v4_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_fa526_name, #object
-cpu_fa526_name:
- .asciz "FA526"
- .size cpu_fa526_name, . - cpu_fa526_name
+ string cpu_arch_name, "armv4"
+ string cpu_elf_name, "v4"
+ string cpu_fa526_name, "FA526"
.align
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index d3883eed7a4a..8a6c2f78c1c3 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -411,29 +411,28 @@ ENTRY(feroceon_dma_unmap_area)
mov pc, lr
ENDPROC(feroceon_dma_unmap_area)
-ENTRY(feroceon_cache_fns)
- .long feroceon_flush_icache_all
- .long feroceon_flush_kern_cache_all
- .long feroceon_flush_user_cache_all
- .long feroceon_flush_user_cache_range
- .long feroceon_coherent_kern_range
- .long feroceon_coherent_user_range
- .long feroceon_flush_kern_dcache_area
- .long feroceon_dma_map_area
- .long feroceon_dma_unmap_area
- .long feroceon_dma_flush_range
-
-ENTRY(feroceon_range_cache_fns)
- .long feroceon_flush_icache_all
- .long feroceon_flush_kern_cache_all
- .long feroceon_flush_user_cache_all
- .long feroceon_flush_user_cache_range
- .long feroceon_coherent_kern_range
- .long feroceon_coherent_user_range
- .long feroceon_range_flush_kern_dcache_area
- .long feroceon_range_dma_map_area
- .long feroceon_dma_unmap_area
- .long feroceon_range_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions feroceon
+
+.macro range_alias basename
+ .globl feroceon_range_\basename
+ .type feroceon_range_\basename , %function
+ .equ feroceon_range_\basename , feroceon_\basename
+.endm
+
+/*
+ * Most of the cache functions are unchanged for this case.
+ * Export suitable alias symbols for the unchanged functions:
+ */
+ range_alias flush_icache_all
+ range_alias flush_user_cache_all
+ range_alias flush_kern_cache_all
+ range_alias flush_user_cache_range
+ range_alias coherent_kern_range
+ range_alias coherent_user_range
+ range_alias dma_unmap_area
+
+ define_cache_functions feroceon_range
.align 5
ENTRY(cpu_feroceon_dcache_clean_area)
@@ -539,93 +538,27 @@ feroceon_crval:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type feroceon_processor_functions, #object
-feroceon_processor_functions:
- .word v5t_early_abort
- .word legacy_pabort
- .word cpu_feroceon_proc_init
- .word cpu_feroceon_proc_fin
- .word cpu_feroceon_reset
- .word cpu_feroceon_do_idle
- .word cpu_feroceon_dcache_clean_area
- .word cpu_feroceon_switch_mm
- .word cpu_feroceon_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size feroceon_processor_functions, . - feroceon_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions feroceon, dabort=v5t_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5te"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_feroceon_name, #object
-cpu_feroceon_name:
- .asciz "Feroceon"
- .size cpu_feroceon_name, . - cpu_feroceon_name
-
- .type cpu_88fr531_name, #object
-cpu_88fr531_name:
- .asciz "Feroceon 88FR531-vd"
- .size cpu_88fr531_name, . - cpu_88fr531_name
-
- .type cpu_88fr571_name, #object
-cpu_88fr571_name:
- .asciz "Feroceon 88FR571-vd"
- .size cpu_88fr571_name, . - cpu_88fr571_name
-
- .type cpu_88fr131_name, #object
-cpu_88fr131_name:
- .asciz "Feroceon 88FR131"
- .size cpu_88fr131_name, . - cpu_88fr131_name
+ string cpu_arch_name, "armv5te"
+ string cpu_elf_name, "v5"
+ string cpu_feroceon_name, "Feroceon"
+ string cpu_88fr531_name, "Feroceon 88FR531-vd"
+ string cpu_88fr571_name, "Feroceon 88FR571-vd"
+ string cpu_88fr131_name, "Feroceon 88FR131"
.align
.section ".proc.info.init", #alloc, #execinstr
-#ifdef CONFIG_CPU_FEROCEON_OLD_ID
- .type __feroceon_old_id_proc_info,#object
-__feroceon_old_id_proc_info:
- .long 0x41009260
- .long 0xff00fff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __feroceon_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_feroceon_name
- .long feroceon_processor_functions
- .long v4wbi_tlb_fns
- .long feroceon_user_fns
- .long feroceon_cache_fns
- .size __feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info
-#endif
-
- .type __88fr531_proc_info,#object
-__88fr531_proc_info:
- .long 0x56055310
- .long 0xfffffff0
+.macro feroceon_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache:req
+ .type __\name\()_proc_info,#object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
.long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
@@ -640,59 +573,22 @@ __88fr531_proc_info:
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_88fr531_name
+ .long \cpu_name
.long feroceon_processor_functions
.long v4wbi_tlb_fns
.long feroceon_user_fns
- .long feroceon_cache_fns
- .size __88fr531_proc_info, . - __88fr531_proc_info
+ .long \cache
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
- .type __88fr571_proc_info,#object
-__88fr571_proc_info:
- .long 0x56155710
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __feroceon_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_88fr571_name
- .long feroceon_processor_functions
- .long v4wbi_tlb_fns
- .long feroceon_user_fns
- .long feroceon_range_cache_fns
- .size __88fr571_proc_info, . - __88fr571_proc_info
+#ifdef CONFIG_CPU_FEROCEON_OLD_ID
+ feroceon_proc_info feroceon_old_id, 0x41009260, 0xff00fff0, \
+ cpu_name=cpu_feroceon_name, cache=feroceon_cache_fns
+#endif
- .type __88fr131_proc_info,#object
-__88fr131_proc_info:
- .long 0x56251310
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __feroceon_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_88fr131_name
- .long feroceon_processor_functions
- .long v4wbi_tlb_fns
- .long feroceon_user_fns
- .long feroceon_range_cache_fns
- .size __88fr131_proc_info, . - __88fr131_proc_info
+ feroceon_proc_info 88fr531, 0x56055310, 0xfffffff0, cpu_88fr531_name, \
+ cache=feroceon_cache_fns
+ feroceon_proc_info 88fr571, 0x56155710, 0xfffffff0, cpu_88fr571_name, \
+ cache=feroceon_range_cache_fns
+ feroceon_proc_info 88fr131, 0x56251310, 0xfffffff0, cpu_88fr131_name, \
+ cache=feroceon_range_cache_fns
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 34261f9486b9..307a4def8d3a 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -254,3 +254,71 @@
mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
mcr p15, 0, ip, c7, c10, 4 @ data write barrier
.endm
+
+.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0
+ .type \name\()_processor_functions, #object
+ .align 2
+ENTRY(\name\()_processor_functions)
+ .word \dabort
+ .word \pabort
+ .word cpu_\name\()_proc_init
+ .word cpu_\name\()_proc_fin
+ .word cpu_\name\()_reset
+ .word cpu_\name\()_do_idle
+ .word cpu_\name\()_dcache_clean_area
+ .word cpu_\name\()_switch_mm
+
+ .if \nommu
+ .word 0
+ .else
+ .word cpu_\name\()_set_pte_ext
+ .endif
+
+ .if \suspend
+ .word cpu_\name\()_suspend_size
+#ifdef CONFIG_PM_SLEEP
+ .word cpu_\name\()_do_suspend
+ .word cpu_\name\()_do_resume
+#else
+ .word 0
+ .word 0
+#endif
+ .else
+ .word 0
+ .word 0
+ .word 0
+ .endif
+
+ .size \name\()_processor_functions, . - \name\()_processor_functions
+.endm
+
+.macro define_cache_functions name:req
+ .align 2
+ .type \name\()_cache_fns, #object
+ENTRY(\name\()_cache_fns)
+ .long \name\()_flush_icache_all
+ .long \name\()_flush_kern_cache_all
+ .long \name\()_flush_user_cache_all
+ .long \name\()_flush_user_cache_range
+ .long \name\()_coherent_kern_range
+ .long \name\()_coherent_user_range
+ .long \name\()_flush_kern_dcache_area
+ .long \name\()_dma_map_area
+ .long \name\()_dma_unmap_area
+ .long \name\()_dma_flush_range
+ .size \name\()_cache_fns, . - \name\()_cache_fns
+.endm
+
+.macro define_tlb_functions name:req, flags_up:req, flags_smp
+ .type \name\()_tlb_fns, #object
+ENTRY(\name\()_tlb_fns)
+ .long \name\()_flush_user_tlb_range
+ .long \name\()_flush_kern_tlb_range
+ .ifnb \flags_smp
+ ALT_SMP(.long \flags_smp )
+ ALT_UP(.long \flags_up )
+ .else
+ .long \flags_up
+ .endif
+ .size \name\()_tlb_fns, . - \name\()_tlb_fns
+.endm
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 9d4f2ae63370..db52b0fb14a0 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -93,6 +93,17 @@ ENTRY(cpu_mohawk_do_idle)
mov pc, lr
/*
+ * flush_icache_all()
+ *
+ * Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(mohawk_flush_icache_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
+ mov pc, lr
+ENDPROC(mohawk_flush_icache_all)
+
+/*
* flush_user_cache_all()
*
* Clean and invalidate all cache entries in a particular
@@ -288,16 +299,8 @@ ENTRY(mohawk_dma_unmap_area)
mov pc, lr
ENDPROC(mohawk_dma_unmap_area)
-ENTRY(mohawk_cache_fns)
- .long mohawk_flush_kern_cache_all
- .long mohawk_flush_user_cache_all
- .long mohawk_flush_user_cache_range
- .long mohawk_coherent_kern_range
- .long mohawk_coherent_user_range
- .long mohawk_flush_kern_dcache_area
- .long mohawk_dma_map_area
- .long mohawk_dma_unmap_area
- .long mohawk_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions mohawk
ENTRY(cpu_mohawk_dcache_clean_area)
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
@@ -373,42 +376,14 @@ mohawk_crval:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .type mohawk_processor_functions, #object
-mohawk_processor_functions:
- .word v5t_early_abort
- .word legacy_pabort
- .word cpu_mohawk_proc_init
- .word cpu_mohawk_proc_fin
- .word cpu_mohawk_reset
- .word cpu_mohawk_do_idle
- .word cpu_mohawk_dcache_clean_area
- .word cpu_mohawk_switch_mm
- .word cpu_mohawk_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size mohawk_processor_functions, . - mohawk_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions mohawk, dabort=v5t_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5te"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_mohawk_name, #object
-cpu_mohawk_name:
- .asciz "Marvell 88SV331x"
- .size cpu_mohawk_name, . - cpu_mohawk_name
+ string cpu_arch_name, "armv5te"
+ string cpu_elf_name, "v5"
+ string cpu_mohawk_name, "Marvell 88SV331x"
.align
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 46f09ed16b98..d50ada26edd6 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -187,43 +187,14 @@ sa110_crval:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
-
- .type sa110_processor_functions, #object
-ENTRY(sa110_processor_functions)
- .word v4_early_abort
- .word legacy_pabort
- .word cpu_sa110_proc_init
- .word cpu_sa110_proc_fin
- .word cpu_sa110_reset
- .word cpu_sa110_do_idle
- .word cpu_sa110_dcache_clean_area
- .word cpu_sa110_switch_mm
- .word cpu_sa110_set_pte_ext
- .word 0
- .word 0
- .word 0
- .size sa110_processor_functions, . - sa110_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions sa110, dabort=v4_early_abort, pabort=legacy_pabort
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_sa110_name, #object
-cpu_sa110_name:
- .asciz "StrongARM-110"
- .size cpu_sa110_name, . - cpu_sa110_name
+ string cpu_arch_name, "armv4"
+ string cpu_elf_name, "v4"
+ string cpu_sa110_name, "StrongARM-110"
.align
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 184a9c997e36..07219c2ae114 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -34,7 +34,7 @@
*/
#define DCACHELINESIZE 32
- __INIT
+ .section .text
/*
* cpu_sa1100_proc_init()
@@ -45,8 +45,6 @@ ENTRY(cpu_sa1100_proc_init)
mcr p15, 0, r0, c9, c0, 5 @ Allow read-buffer operations from userland
mov pc, lr
- .section .text
-
/*
* cpu_sa1100_proc_fin()
*
@@ -200,9 +198,6 @@ ENTRY(cpu_sa1100_do_resume)
PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
b cpu_resume_mmu
ENDPROC(cpu_sa1100_do_resume)
-#else
-#define cpu_sa1100_do_suspend 0
-#define cpu_sa1100_do_resume 0
#endif
__CPUINIT
@@ -236,59 +231,28 @@ sa1100_crval:
__INITDATA
/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
-
-/*
* SA1100 and SA1110 share the same function calls
*/
- .type sa1100_processor_functions, #object
-ENTRY(sa1100_processor_functions)
- .word v4_early_abort
- .word legacy_pabort
- .word cpu_sa1100_proc_init
- .word cpu_sa1100_proc_fin
- .word cpu_sa1100_reset
- .word cpu_sa1100_do_idle
- .word cpu_sa1100_dcache_clean_area
- .word cpu_sa1100_switch_mm
- .word cpu_sa1100_set_pte_ext
- .word cpu_sa1100_suspend_size
- .word cpu_sa1100_do_suspend
- .word cpu_sa1100_do_resume
- .size sa1100_processor_functions, . - sa1100_processor_functions
- .section ".rodata"
-
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv4"
- .size cpu_arch_name, . - cpu_arch_name
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions sa1100, dabort=v4_early_abort, pabort=legacy_pabort, suspend=1
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v4"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_sa1100_name, #object
-cpu_sa1100_name:
- .asciz "StrongARM-1100"
- .size cpu_sa1100_name, . - cpu_sa1100_name
+ .section ".rodata"
- .type cpu_sa1110_name, #object
-cpu_sa1110_name:
- .asciz "StrongARM-1110"
- .size cpu_sa1110_name, . - cpu_sa1110_name
+ string cpu_arch_name, "armv4"
+ string cpu_elf_name, "v4"
+ string cpu_sa1100_name, "StrongARM-1100"
+ string cpu_sa1110_name, "StrongARM-1110"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __sa1100_proc_info,#object
-__sa1100_proc_info:
- .long 0x4401a110
- .long 0xfffffff0
+.macro sa1100_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req
+ .type __\name\()_proc_info,#object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
.long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
@@ -301,32 +265,13 @@ __sa1100_proc_info:
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
- .long cpu_sa1100_name
+ .long \cpu_name
.long sa1100_processor_functions
.long v4wb_tlb_fns
.long v4_mc_user_fns
.long v4wb_cache_fns
- .size __sa1100_proc_info, . - __sa1100_proc_info
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
- .type __sa1110_proc_info,#object
-__sa1110_proc_info:
- .long 0x6901b110
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __sa1100_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
- .long cpu_sa1110_name
- .long sa1100_processor_functions
- .long v4wb_tlb_fns
- .long v4_mc_user_fns
- .long v4wb_cache_fns
- .size __sa1110_proc_info, . - __sa1110_proc_info
+ sa1100_proc_info sa1100, 0x4401a110, 0xfffffff0, cpu_sa1100_name
+ sa1100_proc_info sa1110, 0x6901b110, 0xfffffff0, cpu_sa1110_name
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 1d2b8451bf25..219138d2f158 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -56,6 +56,11 @@ ENTRY(cpu_v6_proc_fin)
*/
.align 5
ENTRY(cpu_v6_reset)
+ mrc p15, 0, r1, c1, c0, 0 @ ctrl register
+ bic r1, r1, #0x1 @ ...............m
+ mcr p15, 0, r1, c1, c0, 0 @ disable MMU
+ mov r1, #0
+ mcr p15, 0, r1, c7, c5, 4 @ ISB
mov pc, r0
/*
@@ -164,16 +169,9 @@ 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)
-#else
-#define cpu_v6_do_suspend 0
-#define cpu_v6_do_resume 0
#endif
-
- .type cpu_v6_name, #object
-cpu_v6_name:
- .asciz "ARMv6-compatible processor"
- .size cpu_v6_name, . - cpu_v6_name
+ string cpu_v6_name, "ARMv6-compatible processor"
.align
@@ -239,33 +237,13 @@ v6_crval:
__INITDATA
- .type v6_processor_functions, #object
-ENTRY(v6_processor_functions)
- .word v6_early_abort
- .word v6_pabort
- .word cpu_v6_proc_init
- .word cpu_v6_proc_fin
- .word cpu_v6_reset
- .word cpu_v6_do_idle
- .word cpu_v6_dcache_clean_area
- .word cpu_v6_switch_mm
- .word cpu_v6_set_pte_ext
- .word cpu_v6_suspend_size
- .word cpu_v6_do_suspend
- .word cpu_v6_do_resume
- .size v6_processor_functions, . - v6_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions v6, dabort=v6_early_abort, pabort=v6_pabort, suspend=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv6"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v6"
- .size cpu_elf_name, . - cpu_elf_name
+ string cpu_arch_name, "armv6"
+ string cpu_elf_name, "v6"
.align
.section ".proc.info.init", #alloc, #execinstr
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 089c0b5e454f..a30e78542ccf 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -58,9 +58,16 @@ ENDPROC(cpu_v7_proc_fin)
* to what would be the reset vector.
*
* - loc - location to jump to for soft reset
+ *
+ * This code must be executed using a flat identity mapping with
+ * caches disabled.
*/
.align 5
ENTRY(cpu_v7_reset)
+ mrc p15, 0, r1, c1, c0, 0 @ ctrl register
+ bic r1, r1, #0x1 @ ...............m
+ mcr p15, 0, r1, c1, c0, 0 @ disable MMU
+ isb
mov pc, r0
ENDPROC(cpu_v7_reset)
@@ -173,8 +180,7 @@ ENTRY(cpu_v7_set_pte_ext)
mov pc, lr
ENDPROC(cpu_v7_set_pte_ext)
-cpu_v7_name:
- .ascii "ARMv7 Processor"
+ string cpu_v7_name, "ARMv7 Processor"
.align
/*
@@ -257,9 +263,6 @@ 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)
-#else
-#define cpu_v7_do_suspend 0
-#define cpu_v7_do_resume 0
#endif
__CPUINIT
@@ -279,13 +282,20 @@ cpu_resume_l1_flags:
* It is assumed that:
* - cache type register is implemented
*/
+__v7_ca5mp_setup:
__v7_ca9mp_setup:
+ mov r10, #(1 << 0) @ TLB ops broadcasting
+ b 1f
+__v7_ca15mp_setup:
+ mov r10, #0
+1:
#ifdef CONFIG_SMP
ALT_SMP(mrc p15, 0, r0, c1, c0, 1)
ALT_UP(mov r0, #(1 << 6)) @ fake it for UP
tst r0, #(1 << 6) @ SMP/nAMP mode enabled?
- orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and
- mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting
+ orreq r0, r0, #(1 << 6) @ Enable SMP/nAMP mode
+ orreq r0, r0, r10 @ Enable CPU-specific SMP bits
+ mcreq p15, 0, r0, c1, c0, 1
#endif
__v7_setup:
adr r12, __v7_setup_stack @ the local stack
@@ -411,94 +421,75 @@ __v7_setup_stack:
__INITDATA
- .type v7_processor_functions, #object
-ENTRY(v7_processor_functions)
- .word v7_early_abort
- .word v7_pabort
- .word cpu_v7_proc_init
- .word cpu_v7_proc_fin
- .word cpu_v7_reset
- .word cpu_v7_do_idle
- .word cpu_v7_dcache_clean_area
- .word cpu_v7_switch_mm
- .word cpu_v7_set_pte_ext
- .word cpu_v7_suspend_size
- .word cpu_v7_do_suspend
- .word cpu_v7_do_resume
- .size v7_processor_functions, . - v7_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv7"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v7"
- .size cpu_elf_name, . - cpu_elf_name
+ string cpu_arch_name, "armv7"
+ string cpu_elf_name, "v7"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __v7_ca9mp_proc_info, #object
-__v7_ca9mp_proc_info:
- .long 0x410fc090 @ Required ID value
- .long 0xff0ffff0 @ Mask for ID
- ALT_SMP(.long \
- PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ | \
- PMD_FLAGS_SMP)
- ALT_UP(.long \
- PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ | \
- PMD_FLAGS_UP)
- .long PMD_TYPE_SECT | \
- PMD_SECT_XN | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- W(b) __v7_ca9mp_setup
+ /*
+ * Standard v7 proc info content
+ */
+.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0
+ ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
+ PMD_FLAGS_SMP | \mm_mmuflags)
+ ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
+ PMD_FLAGS_UP | \mm_mmuflags)
+ .long PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ | \io_mmuflags
+ W(b) \initfunc
.long cpu_arch_name
.long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \
+ HWCAP_EDSP | HWCAP_TLS | \hwcaps
.long cpu_v7_name
.long v7_processor_functions
.long v7wbi_tlb_fns
.long v6_user_fns
.long v7_cache_fns
+.endm
+
+ /*
+ * ARM Ltd. Cortex A5 processor.
+ */
+ .type __v7_ca5mp_proc_info, #object
+__v7_ca5mp_proc_info:
+ .long 0x410fc050
+ .long 0xff0ffff0
+ __v7_proc __v7_ca5mp_setup
+ .size __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info
+
+ /*
+ * ARM Ltd. Cortex A9 processor.
+ */
+ .type __v7_ca9mp_proc_info, #object
+__v7_ca9mp_proc_info:
+ .long 0x410fc090
+ .long 0xff0ffff0
+ __v7_proc __v7_ca9mp_setup
.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
/*
+ * ARM Ltd. Cortex A15 processor.
+ */
+ .type __v7_ca15mp_proc_info, #object
+__v7_ca15mp_proc_info:
+ .long 0x410fc0f0
+ .long 0xff0ffff0
+ __v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
+ .size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
+
+ /*
* Match any ARMv7 processor core.
*/
.type __v7_proc_info, #object
__v7_proc_info:
.long 0x000f0000 @ Required ID value
.long 0x000f0000 @ Mask for ID
- ALT_SMP(.long \
- PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ | \
- PMD_FLAGS_SMP)
- ALT_UP(.long \
- PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ | \
- PMD_FLAGS_UP)
- .long PMD_TYPE_SECT | \
- PMD_SECT_XN | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- W(b) __v7_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
- .long cpu_v7_name
- .long v7_processor_functions
- .long v7wbi_tlb_fns
- .long v6_user_fns
- .long v7_cache_fns
+ __v7_proc __v7_setup
.size __v7_proc_info, . - __v7_proc_info
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 596213699f37..28c72a2006a1 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -28,7 +28,6 @@
#include <linux/init.h>
#include <asm/assembler.h>
#include <asm/hwcap.h>
-#include <mach/hardware.h>
#include <asm/pgtable.h>
#include <asm/pgtable-hwdef.h>
#include <asm/page.h>
@@ -335,17 +334,8 @@ ENTRY(xsc3_dma_unmap_area)
mov pc, lr
ENDPROC(xsc3_dma_unmap_area)
-ENTRY(xsc3_cache_fns)
- .long xsc3_flush_icache_all
- .long xsc3_flush_kern_cache_all
- .long xsc3_flush_user_cache_all
- .long xsc3_flush_user_cache_range
- .long xsc3_coherent_kern_range
- .long xsc3_coherent_user_range
- .long xsc3_flush_kern_dcache_area
- .long xsc3_dma_map_area
- .long xsc3_dma_unmap_area
- .long xsc3_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions xsc3
ENTRY(cpu_xsc3_dcache_clean_area)
1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
@@ -454,9 +444,6 @@ ENTRY(cpu_xsc3_do_resume)
ldr r3, =0x542e @ section flags
b cpu_resume_mmu
ENDPROC(cpu_xsc3_do_resume)
-#else
-#define cpu_xsc3_do_suspend 0
-#define cpu_xsc3_do_resume 0
#endif
__CPUINIT
@@ -503,52 +490,24 @@ xsc3_crval:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
-
- .type xsc3_processor_functions, #object
-ENTRY(xsc3_processor_functions)
- .word v5t_early_abort
- .word legacy_pabort
- .word cpu_xsc3_proc_init
- .word cpu_xsc3_proc_fin
- .word cpu_xsc3_reset
- .word cpu_xsc3_do_idle
- .word cpu_xsc3_dcache_clean_area
- .word cpu_xsc3_switch_mm
- .word cpu_xsc3_set_pte_ext
- .word cpu_xsc3_suspend_size
- .word cpu_xsc3_do_suspend
- .word cpu_xsc3_do_resume
- .size xsc3_processor_functions, . - xsc3_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions xsc3, dabort=v5t_early_abort, pabort=legacy_pabort, suspend=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5te"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_xsc3_name, #object
-cpu_xsc3_name:
- .asciz "XScale-V3 based processor"
- .size cpu_xsc3_name, . - cpu_xsc3_name
+ string cpu_arch_name, "armv5te"
+ string cpu_elf_name, "v5"
+ string cpu_xsc3_name, "XScale-V3 based processor"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __xsc3_proc_info,#object
-__xsc3_proc_info:
- .long 0x69056000
- .long 0xffffe000
+.macro xsc3_proc_info name:req, cpu_val:req, cpu_mask:req
+ .type __\name\()_proc_info,#object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
.long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
@@ -566,29 +525,10 @@ __xsc3_proc_info:
.long v4wbi_tlb_fns
.long xsc3_mc_user_fns
.long xsc3_cache_fns
- .size __xsc3_proc_info, . - __xsc3_proc_info
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
-/* Note: PXA935 changed its implementor ID from Intel to Marvell */
+ xsc3_proc_info xsc3, 0x69056000, 0xffffe000
- .type __xsc3_pxa935_proc_info,#object
-__xsc3_pxa935_proc_info:
- .long 0x56056000
- .long 0xffffe000
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xsc3_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_xsc3_name
- .long xsc3_processor_functions
- .long v4wbi_tlb_fns
- .long xsc3_mc_user_fns
- .long xsc3_cache_fns
- .size __xsc3_pxa935_proc_info, . - __xsc3_pxa935_proc_info
+/* Note: PXA935 changed its implementor ID from Intel to Marvell */
+ xsc3_proc_info xsc3_pxa935, 0x56056000, 0xffffe000
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 42af97664c9d..fbc06e55b87a 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -390,12 +390,12 @@ ENDPROC(xscale_dma_map_area)
* - size - size of region
* - dir - DMA direction
*/
-ENTRY(xscale_dma_a0_map_area)
+ENTRY(xscale_80200_A0_A1_dma_map_area)
add r1, r1, r0
teq r2, #DMA_TO_DEVICE
beq xscale_dma_clean_range
b xscale_dma_flush_range
-ENDPROC(xscale_dma_a0_map_area)
+ENDPROC(xscale_80200_A0_A1_dma_map_area)
/*
* dma_unmap_area(start, size, dir)
@@ -407,17 +407,8 @@ ENTRY(xscale_dma_unmap_area)
mov pc, lr
ENDPROC(xscale_dma_unmap_area)
-ENTRY(xscale_cache_fns)
- .long xscale_flush_icache_all
- .long xscale_flush_kern_cache_all
- .long xscale_flush_user_cache_all
- .long xscale_flush_user_cache_range
- .long xscale_coherent_kern_range
- .long xscale_coherent_user_range
- .long xscale_flush_kern_dcache_area
- .long xscale_dma_map_area
- .long xscale_dma_unmap_area
- .long xscale_dma_flush_range
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions xscale
/*
* On stepping A0/A1 of the 80200, invalidating D-cache by line doesn't
@@ -432,16 +423,28 @@ ENTRY(xscale_cache_fns)
* revision January 22, 2003, available at:
* http://www.intel.com/design/iio/specupdt/273415.htm
*/
-ENTRY(xscale_80200_A0_A1_cache_fns)
- .long xscale_flush_kern_cache_all
- .long xscale_flush_user_cache_all
- .long xscale_flush_user_cache_range
- .long xscale_coherent_kern_range
- .long xscale_coherent_user_range
- .long xscale_flush_kern_dcache_area
- .long xscale_dma_a0_map_area
- .long xscale_dma_unmap_area
- .long xscale_dma_flush_range
+.macro a0_alias basename
+ .globl xscale_80200_A0_A1_\basename
+ .type xscale_80200_A0_A1_\basename , %function
+ .equ xscale_80200_A0_A1_\basename , xscale_\basename
+.endm
+
+/*
+ * Most of the cache functions are unchanged for these processor revisions.
+ * Export suitable alias symbols for the unchanged functions:
+ */
+ a0_alias flush_icache_all
+ a0_alias flush_user_cache_all
+ a0_alias flush_kern_cache_all
+ a0_alias flush_user_cache_range
+ a0_alias coherent_kern_range
+ a0_alias coherent_user_range
+ a0_alias flush_kern_dcache_area
+ a0_alias dma_flush_range
+ a0_alias dma_unmap_area
+
+ @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+ define_cache_functions xscale_80200_A0_A1
ENTRY(cpu_xscale_dcache_clean_area)
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
@@ -551,9 +554,6 @@ ENTRY(cpu_xscale_do_resume)
PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
b cpu_resume_mmu
ENDPROC(cpu_xscale_do_resume)
-#else
-#define cpu_xscale_do_suspend 0
-#define cpu_xscale_do_resume 0
#endif
__CPUINIT
@@ -587,432 +587,74 @@ xscale_crval:
__INITDATA
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
-
- .type xscale_processor_functions, #object
-ENTRY(xscale_processor_functions)
- .word v5t_early_abort
- .word legacy_pabort
- .word cpu_xscale_proc_init
- .word cpu_xscale_proc_fin
- .word cpu_xscale_reset
- .word cpu_xscale_do_idle
- .word cpu_xscale_dcache_clean_area
- .word cpu_xscale_switch_mm
- .word cpu_xscale_set_pte_ext
- .word cpu_xscale_suspend_size
- .word cpu_xscale_do_suspend
- .word cpu_xscale_do_resume
- .size xscale_processor_functions, . - xscale_processor_functions
+ @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+ define_processor_functions xscale, dabort=v5t_early_abort, pabort=legacy_pabort, suspend=1
.section ".rodata"
- .type cpu_arch_name, #object
-cpu_arch_name:
- .asciz "armv5te"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
-cpu_elf_name:
- .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
-
- .type cpu_80200_A0_A1_name, #object
-cpu_80200_A0_A1_name:
- .asciz "XScale-80200 A0/A1"
- .size cpu_80200_A0_A1_name, . - cpu_80200_A0_A1_name
-
- .type cpu_80200_name, #object
-cpu_80200_name:
- .asciz "XScale-80200"
- .size cpu_80200_name, . - cpu_80200_name
-
- .type cpu_80219_name, #object
-cpu_80219_name:
- .asciz "XScale-80219"
- .size cpu_80219_name, . - cpu_80219_name
-
- .type cpu_8032x_name, #object
-cpu_8032x_name:
- .asciz "XScale-IOP8032x Family"
- .size cpu_8032x_name, . - cpu_8032x_name
-
- .type cpu_8033x_name, #object
-cpu_8033x_name:
- .asciz "XScale-IOP8033x Family"
- .size cpu_8033x_name, . - cpu_8033x_name
-
- .type cpu_pxa250_name, #object
-cpu_pxa250_name:
- .asciz "XScale-PXA250"
- .size cpu_pxa250_name, . - cpu_pxa250_name
-
- .type cpu_pxa210_name, #object
-cpu_pxa210_name:
- .asciz "XScale-PXA210"
- .size cpu_pxa210_name, . - cpu_pxa210_name
-
- .type cpu_ixp42x_name, #object
-cpu_ixp42x_name:
- .asciz "XScale-IXP42x Family"
- .size cpu_ixp42x_name, . - cpu_ixp42x_name
-
- .type cpu_ixp43x_name, #object
-cpu_ixp43x_name:
- .asciz "XScale-IXP43x Family"
- .size cpu_ixp43x_name, . - cpu_ixp43x_name
-
- .type cpu_ixp46x_name, #object
-cpu_ixp46x_name:
- .asciz "XScale-IXP46x Family"
- .size cpu_ixp46x_name, . - cpu_ixp46x_name
-
- .type cpu_ixp2400_name, #object
-cpu_ixp2400_name:
- .asciz "XScale-IXP2400"
- .size cpu_ixp2400_name, . - cpu_ixp2400_name
-
- .type cpu_ixp2800_name, #object
-cpu_ixp2800_name:
- .asciz "XScale-IXP2800"
- .size cpu_ixp2800_name, . - cpu_ixp2800_name
-
- .type cpu_pxa255_name, #object
-cpu_pxa255_name:
- .asciz "XScale-PXA255"
- .size cpu_pxa255_name, . - cpu_pxa255_name
-
- .type cpu_pxa270_name, #object
-cpu_pxa270_name:
- .asciz "XScale-PXA270"
- .size cpu_pxa270_name, . - cpu_pxa270_name
+ string cpu_arch_name, "armv5te"
+ string cpu_elf_name, "v5"
+
+ string cpu_80200_A0_A1_name, "XScale-80200 A0/A1"
+ string cpu_80200_name, "XScale-80200"
+ string cpu_80219_name, "XScale-80219"
+ string cpu_8032x_name, "XScale-IOP8032x Family"
+ string cpu_8033x_name, "XScale-IOP8033x Family"
+ string cpu_pxa250_name, "XScale-PXA250"
+ string cpu_pxa210_name, "XScale-PXA210"
+ string cpu_ixp42x_name, "XScale-IXP42x Family"
+ string cpu_ixp43x_name, "XScale-IXP43x Family"
+ string cpu_ixp46x_name, "XScale-IXP46x Family"
+ string cpu_ixp2400_name, "XScale-IXP2400"
+ string cpu_ixp2800_name, "XScale-IXP2800"
+ string cpu_pxa255_name, "XScale-PXA255"
+ string cpu_pxa270_name, "XScale-PXA270"
.align
.section ".proc.info.init", #alloc, #execinstr
- .type __80200_A0_A1_proc_info,#object
-__80200_A0_A1_proc_info:
- .long 0x69052000
- .long 0xfffffffe
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_80200_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_80200_A0_A1_cache_fns
- .size __80200_A0_A1_proc_info, . - __80200_A0_A1_proc_info
-
- .type __80200_proc_info,#object
-__80200_proc_info:
- .long 0x69052000
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
+.macro xscale_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache
+ .type __\name\()_proc_info,#object
+__\name\()_proc_info:
+ .long \cpu_val
+ .long \cpu_mask
+ .long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
+ .long PMD_TYPE_SECT | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
b __xscale_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_80200_name
+ .long \cpu_name
.long xscale_processor_functions
.long v4wbi_tlb_fns
.long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __80200_proc_info, . - __80200_proc_info
-
- .type __80219_proc_info,#object
-__80219_proc_info:
- .long 0x69052e20
- .long 0xffffffe0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_80219_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __80219_proc_info, . - __80219_proc_info
-
- .type __8032x_proc_info,#object
-__8032x_proc_info:
- .long 0x69052420
- .long 0xfffff7e0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_8032x_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __8032x_proc_info, . - __8032x_proc_info
-
- .type __8033x_proc_info,#object
-__8033x_proc_info:
- .long 0x69054010
- .long 0xfffffd30
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_8033x_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __8033x_proc_info, . - __8033x_proc_info
-
- .type __pxa250_proc_info,#object
-__pxa250_proc_info:
- .long 0x69052100
- .long 0xfffff7f0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_pxa250_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __pxa250_proc_info, . - __pxa250_proc_info
-
- .type __pxa210_proc_info,#object
-__pxa210_proc_info:
- .long 0x69052120
- .long 0xfffff3f0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_pxa210_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __pxa210_proc_info, . - __pxa210_proc_info
-
- .type __ixp2400_proc_info, #object
-__ixp2400_proc_info:
- .long 0x69054190
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_ixp2400_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __ixp2400_proc_info, . - __ixp2400_proc_info
-
- .type __ixp2800_proc_info, #object
-__ixp2800_proc_info:
- .long 0x690541a0
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_ixp2800_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __ixp2800_proc_info, . - __ixp2800_proc_info
-
- .type __ixp42x_proc_info, #object
-__ixp42x_proc_info:
- .long 0x690541c0
- .long 0xffffffc0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_ixp42x_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __ixp42x_proc_info, . - __ixp42x_proc_info
-
- .type __ixp43x_proc_info, #object
-__ixp43x_proc_info:
- .long 0x69054040
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_ixp43x_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __ixp43x_proc_info, . - __ixp43x_proc_info
-
- .type __ixp46x_proc_info, #object
-__ixp46x_proc_info:
- .long 0x69054200
- .long 0xffffff00
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_ixp46x_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __ixp46x_proc_info, . - __ixp46x_proc_info
-
- .type __pxa255_proc_info,#object
-__pxa255_proc_info:
- .long 0x69052d00
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_pxa255_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __pxa255_proc_info, . - __pxa255_proc_info
-
- .type __pxa270_proc_info,#object
-__pxa270_proc_info:
- .long 0x69054110
- .long 0xfffffff0
- .long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b __xscale_setup
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_pxa270_name
- .long xscale_processor_functions
- .long v4wbi_tlb_fns
- .long xscale_mc_user_fns
- .long xscale_cache_fns
- .size __pxa270_proc_info, . - __pxa270_proc_info
-
+ .ifb \cache
+ .long xscale_cache_fns
+ .else
+ .long \cache
+ .endif
+ .size __\name\()_proc_info, . - __\name\()_proc_info
+.endm
+
+ xscale_proc_info 80200_A0_A1, 0x69052000, 0xfffffffe, cpu_80200_name, \
+ cache=xscale_80200_A0_A1_cache_fns
+ xscale_proc_info 80200, 0x69052000, 0xfffffff0, cpu_80200_name
+ xscale_proc_info 80219, 0x69052e20, 0xffffffe0, cpu_80219_name
+ xscale_proc_info 8032x, 0x69052420, 0xfffff7e0, cpu_8032x_name
+ xscale_proc_info 8033x, 0x69054010, 0xfffffd30, cpu_8033x_name
+ xscale_proc_info pxa250, 0x69052100, 0xfffff7f0, cpu_pxa250_name
+ xscale_proc_info pxa210, 0x69052120, 0xfffff3f0, cpu_pxa210_name
+ xscale_proc_info ixp2400, 0x69054190, 0xfffffff0, cpu_ixp2400_name
+ xscale_proc_info ixp2800, 0x690541a0, 0xfffffff0, cpu_ixp2800_name
+ xscale_proc_info ixp42x, 0x690541c0, 0xffffffc0, cpu_ixp42x_name
+ xscale_proc_info ixp43x, 0x69054040, 0xfffffff0, cpu_ixp43x_name
+ xscale_proc_info ixp46x, 0x69054200, 0xffffff00, cpu_ixp46x_name
+ xscale_proc_info pxa255, 0x69052d00, 0xfffffff0, cpu_pxa255_name
+ xscale_proc_info pxa270, 0x69054110, 0xfffffff0, cpu_pxa270_name
diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S
index 9694f1f6f485..d3ddcf9a76ca 100644
--- a/arch/arm/mm/tlb-fa.S
+++ b/arch/arm/mm/tlb-fa.S
@@ -46,7 +46,6 @@ ENTRY(fa_flush_user_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB
mcr p15, 0, r3, c7, c10, 4 @ data write barrier
mov pc, lr
@@ -60,16 +59,11 @@ ENTRY(fa_flush_kern_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB
mcr p15, 0, r3, c7, c10, 4 @ data write barrier
- mcr p15, 0, r3, c7, c5, 4 @ prefetch flush
+ mcr p15, 0, r3, c7, c5, 4 @ prefetch flush (isb)
mov pc, lr
__INITDATA
- .type fa_tlb_fns, #object
-ENTRY(fa_tlb_fns)
- .long fa_flush_user_tlb_range
- .long fa_flush_kern_tlb_range
- .long fa_tlb_flags
- .size fa_tlb_fns, . - fa_tlb_fns
+ /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+ define_tlb_functions fa, fa_tlb_flags
diff --git a/arch/arm/mm/tlb-v3.S b/arch/arm/mm/tlb-v3.S
index c10786ec8e0a..d253995ec4ca 100644
--- a/arch/arm/mm/tlb-v3.S
+++ b/arch/arm/mm/tlb-v3.S
@@ -44,9 +44,5 @@ ENTRY(v3_flush_kern_tlb_range)
__INITDATA
- .type v3_tlb_fns, #object
-ENTRY(v3_tlb_fns)
- .long v3_flush_user_tlb_range
- .long v3_flush_kern_tlb_range
- .long v3_tlb_flags
- .size v3_tlb_fns, . - v3_tlb_fns
+ /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+ define_tlb_functions v3, v3_tlb_flags
diff --git a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S
index d6c94457c2b9..17a025ade573 100644
--- a/arch/arm/mm/tlb-v4.S
+++ b/arch/arm/mm/tlb-v4.S
@@ -57,9 +57,5 @@ ENTRY(v4_flush_user_tlb_range)
__INITDATA
- .type v4_tlb_fns, #object
-ENTRY(v4_tlb_fns)
- .long v4_flush_user_tlb_range
- .long v4_flush_kern_tlb_range
- .long v4_tlb_flags
- .size v4_tlb_fns, . - v4_tlb_fns
+ /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+ define_tlb_functions v4, v4_tlb_flags
diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
index cb829ca7845d..c04598fa4d4a 100644
--- a/arch/arm/mm/tlb-v4wb.S
+++ b/arch/arm/mm/tlb-v4wb.S
@@ -69,9 +69,5 @@ ENTRY(v4wb_flush_kern_tlb_range)
__INITDATA
- .type v4wb_tlb_fns, #object
-ENTRY(v4wb_tlb_fns)
- .long v4wb_flush_user_tlb_range
- .long v4wb_flush_kern_tlb_range
- .long v4wb_tlb_flags
- .size v4wb_tlb_fns, . - v4wb_tlb_fns
+ /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+ define_tlb_functions v4wb, v4wb_tlb_flags
diff --git a/arch/arm/mm/tlb-v4wbi.S b/arch/arm/mm/tlb-v4wbi.S
index 60cfc4a25dd5..1f6062b6c1c1 100644
--- a/arch/arm/mm/tlb-v4wbi.S
+++ b/arch/arm/mm/tlb-v4wbi.S
@@ -60,9 +60,5 @@ ENTRY(v4wbi_flush_kern_tlb_range)
__INITDATA
- .type v4wbi_tlb_fns, #object
-ENTRY(v4wbi_tlb_fns)
- .long v4wbi_flush_user_tlb_range
- .long v4wbi_flush_kern_tlb_range
- .long v4wbi_tlb_flags
- .size v4wbi_tlb_fns, . - v4wbi_tlb_fns
+ /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+ define_tlb_functions v4wbi, v4wbi_tlb_flags
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index 73d7d89b04c4..eca07f550a0b 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -54,7 +54,6 @@ ENTRY(v6wbi_flush_user_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, ip, c7, c10, 4 @ data synchronization barrier
mov pc, lr
@@ -83,16 +82,11 @@ ENTRY(v6wbi_flush_kern_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, r2, c7, c10, 4 @ data synchronization barrier
- mcr p15, 0, r2, c7, c5, 4 @ prefetch flush
+ mcr p15, 0, r2, c7, c5, 4 @ prefetch flush (isb)
mov pc, lr
__INIT
- .type v6wbi_tlb_fns, #object
-ENTRY(v6wbi_tlb_fns)
- .long v6wbi_flush_user_tlb_range
- .long v6wbi_flush_kern_tlb_range
- .long v6wbi_tlb_flags
- .size v6wbi_tlb_fns, . - v6wbi_tlb_fns
+ /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+ define_tlb_functions v6wbi, v6wbi_tlb_flags
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index 53cd5b454673..845f461f8ec1 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -48,9 +48,6 @@ ENTRY(v7wbi_flush_user_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mov ip, #0
- ALT_SMP(mcr p15, 0, ip, c7, c1, 6) @ flush BTAC/BTB Inner Shareable
- ALT_UP(mcr p15, 0, ip, c7, c5, 6) @ flush BTAC/BTB
dsb
mov pc, lr
ENDPROC(v7wbi_flush_user_tlb_range)
@@ -75,9 +72,6 @@ ENTRY(v7wbi_flush_kern_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mov r2, #0
- ALT_SMP(mcr p15, 0, r2, c7, c1, 6) @ flush BTAC/BTB Inner Shareable
- ALT_UP(mcr p15, 0, r2, c7, c5, 6) @ flush BTAC/BTB
dsb
isb
mov pc, lr
@@ -85,10 +79,5 @@ ENDPROC(v7wbi_flush_kern_tlb_range)
__INIT
- .type v7wbi_tlb_fns, #object
-ENTRY(v7wbi_tlb_fns)
- .long v7wbi_flush_user_tlb_range
- .long v7wbi_flush_kern_tlb_range
- ALT_SMP(.long v7wbi_tlb_flags_smp)
- ALT_UP(.long v7wbi_tlb_flags_up)
- .size v7wbi_tlb_fns, . - v7wbi_tlb_fns
+ /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+ define_tlb_functions v7wbi, v7wbi_tlb_flags_up, flags_smp=v7wbi_tlb_flags_smp
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index 43f2b158237c..845549cbbb27 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/plat-iop/pci.c
@@ -374,6 +374,9 @@ void __init iop3xx_pci_preinit_cond(void)
void __init iop3xx_pci_preinit(void)
{
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0;
+
iop3xx_atu_disable();
iop3xx_atu_setup();
iop3xx_atu_debug();
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index a1387875a491..d53c35fe2ea7 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,7 +3,7 @@
#
# Common support
-obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o
+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_MXC_TZIC) += tzic.o
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 09e2bd0fcdca..55d2534ec727 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -46,6 +46,8 @@
#define AVIC_FIPNDH 0x60 /* fast int pending high */
#define AVIC_FIPNDL 0x64 /* fast int pending low */
+#define AVIC_NUM_IRQS 64
+
void __iomem *avic_base;
#ifdef CONFIG_MXC_IRQ_PRIOR
@@ -54,7 +56,7 @@ static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
unsigned int temp;
unsigned int mask = 0x0F << irq % 8 * 4;
- if (irq >= MXC_INTERNAL_IRQS)
+ if (irq >= AVIC_NUM_IRQS)
return -EINVAL;;
temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
@@ -72,14 +74,14 @@ static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
{
unsigned int irqt;
- if (irq >= MXC_INTERNAL_IRQS)
+ if (irq >= AVIC_NUM_IRQS)
return -EINVAL;
- if (irq < MXC_INTERNAL_IRQS / 2) {
+ if (irq < AVIC_NUM_IRQS / 2) {
irqt = __raw_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
} else {
- irq -= MXC_INTERNAL_IRQS / 2;
+ irq -= AVIC_NUM_IRQS / 2;
irqt = __raw_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
}
@@ -138,7 +140,7 @@ 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 < MXC_INTERNAL_IRQS; i++) {
+ 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);
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index eee1b6096a08..0d6ed31bdbf2 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -89,3 +89,28 @@ err:
return pdev;
}
+
+struct device mxc_aips_bus = {
+ .init_name = "mxc_aips",
+ .parent = &platform_bus,
+};
+
+struct device mxc_ahb_bus = {
+ .init_name = "mxc_ahb",
+ .parent = &platform_bus,
+};
+
+static int __init mxc_device_init(void)
+{
+ int ret;
+
+ ret = device_register(&mxc_aips_bus);
+ if (IS_ERR_VALUE(ret))
+ goto done;
+
+ ret = device_register(&mxc_ahb_bus);
+
+done:
+ return ret;
+}
+core_initcall(mxc_device_init);
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index ad2922acf480..b41bf972b54b 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
+obj-y += platform-gpio-mxc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
index ccc789e21daa..4fc6ffc2a13e 100644
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <asm/sizes.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
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 59c33f6e401c..23ce08e6ffd2 100644
--- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
+++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
new file mode 100644
index 000000000000..a7919a241032
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/devices-common.h>
+
+struct platform_device *__init mxc_register_gpio(char *name, int id,
+ resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
+{
+ struct resource res[] = {
+ {
+ .start = iobase,
+ .end = iobase + iosize - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = irq,
+ .end = irq,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = irq_high,
+ .end = irq_high,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return platform_device_register_resndata(&mxc_aips_bus,
+ name, id, res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
index b130f60ca6b7..2b0fdb23beb8 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-dma.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c
@@ -6,207 +6,29 @@
* 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/hardware.h>
#include <mach/devices-common.h>
-#include <mach/sdma.h>
-
-struct imx_imx_sdma_data {
- resource_size_t iobase;
- resource_size_t irq;
- struct sdma_platform_data pdata;
-};
-
-#define imx_imx_sdma_data_entry_single(soc, _sdma_version, _cpu_name, _to_version)\
- { \
- .iobase = soc ## _SDMA ## _BASE_ADDR, \
- .irq = soc ## _INT_SDMA, \
- .pdata = { \
- .sdma_version = _sdma_version, \
- .cpu_name = _cpu_name, \
- .to_version = _to_version, \
- }, \
- }
-
-#ifdef CONFIG_SOC_IMX25
-struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
- imx_imx_sdma_data_entry_single(MX25, 1, "imx25", 0);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-#ifdef CONFIG_SOC_IMX31
-struct imx_imx_sdma_data imx31_imx_sdma_data __initdata =
- imx_imx_sdma_data_entry_single(MX31, 1, "imx31", 0);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-struct imx_imx_sdma_data imx35_imx_sdma_data __initdata =
- imx_imx_sdma_data_entry_single(MX35, 2, "imx35", 0);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
- imx_imx_sdma_data_entry_single(MX51, 2, "imx51", 0);
-#endif /* ifdef CONFIG_SOC_IMX51 */
+struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
+{
+ return platform_device_register_resndata(&mxc_ahb_bus,
+ "imx-dma", -1, NULL, 0, NULL, 0);
+}
-static struct platform_device __init __maybe_unused *imx_add_imx_sdma(
- const struct imx_imx_sdma_data *data)
+struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+ resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
{
struct resource res[] = {
{
- .start = data->iobase,
- .end = data->iobase + SZ_4K - 1,
+ .start = iobase,
+ .end = iobase + SZ_16K - 1,
.flags = IORESOURCE_MEM,
}, {
- .start = data->irq,
- .end = data->irq,
+ .start = irq,
+ .end = irq,
.flags = IORESOURCE_IRQ,
},
};
- return imx_add_platform_device("imx-sdma", -1,
- res, ARRAY_SIZE(res),
- &data->pdata, sizeof(data->pdata));
-}
-
-static struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
-{
- return imx_add_platform_device("imx-dma", -1, NULL, 0, NULL, 0);
-}
-
-#ifdef CONFIG_ARCH_MX25
-static struct sdma_script_start_addrs addr_imx25_to1 = {
- .ap_2_ap_addr = 729,
- .uart_2_mcu_addr = 904,
- .per_2_app_addr = 1255,
- .mcu_2_app_addr = 834,
- .uartsh_2_mcu_addr = 1120,
- .per_2_shp_addr = 1329,
- .mcu_2_shp_addr = 1048,
- .ata_2_mcu_addr = 1560,
- .mcu_2_ata_addr = 1479,
- .app_2_per_addr = 1189,
- .app_2_mcu_addr = 770,
- .shp_2_per_addr = 1407,
- .shp_2_mcu_addr = 979,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX31
-static struct sdma_script_start_addrs addr_imx31_to1 = {
- .per_2_per_addr = 1677,
-};
-
-static struct sdma_script_start_addrs addr_imx31_to2 = {
- .ap_2_ap_addr = 423,
- .ap_2_bp_addr = 829,
- .bp_2_ap_addr = 1029,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX35
-static struct sdma_script_start_addrs addr_imx35_to1 = {
- .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 addr_imx35_to2 = {
- .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,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-static struct sdma_script_start_addrs addr_imx51 = {
- .ap_2_ap_addr = 642,
- .uart_2_mcu_addr = 817,
- .mcu_2_app_addr = 747,
- .mcu_2_shp_addr = 961,
- .ata_2_mcu_addr = 1473,
- .mcu_2_ata_addr = 1392,
- .app_2_per_addr = 1033,
- .app_2_mcu_addr = 683,
- .shp_2_per_addr = 1251,
- .shp_2_mcu_addr = 892,
-};
-#endif
-
-static int __init imxXX_add_imx_dma(void)
-{
- struct platform_device *ret;
-
-#if defined(CONFIG_SOC_IMX21) || defined(CONFIG_SOC_IMX27)
- if (cpu_is_mx21() || cpu_is_mx27())
- ret = imx_add_imx_dma();
- else
-#endif
-
-#if defined(CONFIG_SOC_IMX25)
- if (cpu_is_mx25()) {
- imx25_imx_sdma_data.pdata.script_addrs = &addr_imx25_to1;
- ret = imx_add_imx_sdma(&imx25_imx_sdma_data);
- } else
-#endif
-
-#if defined(CONFIG_SOC_IMX31)
- if (cpu_is_mx31()) {
- int to_version = mx31_revision() >> 4;
- imx31_imx_sdma_data.pdata.to_version = to_version;
- if (to_version == 1)
- imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to1;
- else
- imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to2;
- ret = imx_add_imx_sdma(&imx31_imx_sdma_data);
- } else
-#endif
-
-#if defined(CONFIG_SOC_IMX35)
- if (cpu_is_mx35()) {
- int to_version = mx35_revision() >> 4;
- imx35_imx_sdma_data.pdata.to_version = to_version;
- if (to_version == 1)
- imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to1;
- else
- imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to2;
- ret = imx_add_imx_sdma(&imx35_imx_sdma_data);
- } else
-#endif
-
-#if defined(CONFIG_SOC_IMX51)
- if (cpu_is_mx51()) {
- int to_version = mx51_revision() >> 4;
- imx51_imx_sdma_data.pdata.to_version = to_version;
- imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51;
- ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
- } else
-#endif
- ret = ERR_PTR(-ENODEV);
-
- if (IS_ERR(ret))
- return PTR_ERR(ret);
-
- return 0;
+ return platform_device_register_resndata(&mxc_ahb_bus, "imx-sdma",
+ -1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
}
-arch_initcall(imxXX_add_imx_dma);
diff --git a/arch/arm/plat-mxc/devices/platform-imx-fb.c b/arch/arm/plat-mxc/devices/platform-imx-fb.c
index 79a1cb18a5b0..2b0b5e0aa998 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-fb.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-fb.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index 2ab74f0da9a6..afe60f7244a8 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -94,8 +94,9 @@ const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
imx_imx_i2c_data_entry(MX53, _id, _hwid, SZ_4K)
imx53_imx_i2c_data_entry(0, 1),
imx53_imx_i2c_data_entry(1, 2),
+ imx53_imx_i2c_data_entry(2, 3),
};
-#endif /* ifdef CONFIG_SOC_IMX51 */
+#endif /* ifdef CONFIG_SOC_IMX53 */
struct platform_device *__init imx_add_imx_i2c(
const struct imx_imx_i2c_data *data,
diff --git a/arch/arm/plat-mxc/devices/platform-imx-keypad.c b/arch/arm/plat-mxc/devices/platform-imx-keypad.c
index 26366114b021..479c3e9f771f 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-keypad.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-keypad.c
@@ -46,6 +46,11 @@ const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
imx_imx_keypad_data_entry_single(MX51, SZ_16);
#endif /* ifdef CONFIG_SOC_IMX51 */
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_keypad_data imx53_imx_keypad_data __initconst =
+ imx_imx_keypad_data_entry_single(MX53, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
struct platform_device *__init imx_add_imx_keypad(
const struct imx_imx_keypad_data *data,
const struct matrix_keymap_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-ssi.c b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
index 2569c8d8a2ef..21c6f30e1017 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-ssi.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
@@ -69,13 +69,23 @@ const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
#ifdef CONFIG_SOC_IMX51
const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
#define imx51_imx_ssi_data_entry(_id, _hwid) \
- imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_4K)
+ imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_16K)
imx51_imx_ssi_data_entry(0, 1),
imx51_imx_ssi_data_entry(1, 2),
imx51_imx_ssi_data_entry(2, 3),
};
#endif /* ifdef CONFIG_SOC_IMX51 */
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_ssi_data imx53_imx_ssi_data[] __initconst = {
+#define imx53_imx_ssi_data_entry(_id, _hwid) \
+ imx_imx_ssi_data_entry(MX53, _id, _hwid, SZ_16K)
+ imx53_imx_ssi_data_entry(0, 1),
+ imx53_imx_ssi_data_entry(1, 2),
+ imx53_imx_ssi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
struct platform_device *__init imx_add_imx_ssi(
const struct imx_imx_ssi_data *data,
const struct imx_ssi_platform_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index 3c854c2cc6dd..cfce8c918b73 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -123,6 +123,8 @@ const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
imx53_imx_uart_data_entry(0, 1),
imx53_imx_uart_data_entry(1, 2),
imx53_imx_uart_data_entry(2, 3),
+ imx53_imx_uart_data_entry(3, 4),
+ imx53_imx_uart_data_entry(4, 5),
};
#endif /* ifdef CONFIG_SOC_IMX53 */
diff --git a/arch/arm/plat-mxc/devices/platform-ipu-core.c b/arch/arm/plat-mxc/devices/platform-ipu-core.c
index edf65034aea5..79d340ae0af1 100644
--- a/arch/arm/plat-mxc/devices/platform-ipu-core.c
+++ b/arch/arm/plat-mxc/devices/platform-ipu-core.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
index cc488f4b6204..e1763e03e7cb 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
index 90d762f6f93b..540d3a7d92df 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
index f97eb3615b2c..9bfae8bd5b8d 100644
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-spi_imx.c
@@ -40,9 +40,10 @@ const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
#endif
#ifdef CONFIG_SOC_IMX25
+/* i.mx25 has the i.mx35 type cspi */
const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
#define imx25_cspi_data_entry(_id, _hwid) \
- imx_spi_imx_data_entry(MX25, CSPI, "imx25-cspi", _id, _hwid, SZ_16K)
+ imx_spi_imx_data_entry(MX25, CSPI, "imx35-cspi", _id, _hwid, SZ_16K)
imx25_cspi_data_entry(0, 1),
imx25_cspi_data_entry(1, 2),
imx25_cspi_data_entry(2, 3),
@@ -79,8 +80,9 @@ const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
#endif /* ifdef CONFIG_SOC_IMX35 */
#ifdef CONFIG_SOC_IMX51
+/* i.mx51 has the i.mx35 type cspi */
const struct imx_spi_imx_data imx51_cspi_data __initconst =
- imx_spi_imx_data_entry_single(MX51, CSPI, "imx51-cspi", 2, , SZ_4K);
+ imx_spi_imx_data_entry_single(MX51, CSPI, "imx35-cspi", 2, , SZ_4K);
const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
#define imx51_ecspi_data_entry(_id, _hwid) \
@@ -91,12 +93,14 @@ const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
#endif /* ifdef CONFIG_SOC_IMX51 */
#ifdef CONFIG_SOC_IMX53
+/* i.mx53 has the i.mx35 type cspi */
const struct imx_spi_imx_data imx53_cspi_data __initconst =
- imx_spi_imx_data_entry_single(MX53, CSPI, "imx53-cspi", 0, , SZ_4K);
+ imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 0, , SZ_4K);
+/* i.mx53 has the i.mx51 type ecspi */
const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
#define imx53_ecspi_data_entry(_id, _hwid) \
- imx_spi_imx_data_entry(MX53, ECSPI, "imx53-ecspi", _id, _hwid, SZ_4K)
+ imx_spi_imx_data_entry(MX53, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
imx53_ecspi_data_entry(0, 1),
imx53_ecspi_data_entry(1, 2),
};
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
deleted file mode 100644
index 6cd6d7f686f6..000000000000
--- a/arch/arm/plat-mxc/gpio.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-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.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <mach/hardware.h>
-#include <asm-generic/bug.h>
-
-static struct mxc_gpio_port *mxc_gpio_ports;
-static int gpio_table_size;
-
-#define cpu_is_mx1_mx2() (cpu_is_mx1() || cpu_is_mx2())
-
-#define GPIO_DR (cpu_is_mx1_mx2() ? 0x1c : 0x00)
-#define GPIO_GDIR (cpu_is_mx1_mx2() ? 0x00 : 0x04)
-#define GPIO_PSR (cpu_is_mx1_mx2() ? 0x24 : 0x08)
-#define GPIO_ICR1 (cpu_is_mx1_mx2() ? 0x28 : 0x0C)
-#define GPIO_ICR2 (cpu_is_mx1_mx2() ? 0x2C : 0x10)
-#define GPIO_IMR (cpu_is_mx1_mx2() ? 0x30 : 0x14)
-#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18)
-
-#define GPIO_INT_LOW_LEV (cpu_is_mx1_mx2() ? 0x3 : 0x0)
-#define GPIO_INT_HIGH_LEV (cpu_is_mx1_mx2() ? 0x2 : 0x1)
-#define GPIO_INT_RISE_EDGE (cpu_is_mx1_mx2() ? 0x0 : 0x2)
-#define GPIO_INT_FALL_EDGE (cpu_is_mx1_mx2() ? 0x1 : 0x3)
-#define GPIO_INT_NONE 0x4
-
-/* Note: This driver assumes 32 GPIOs are handled in one register */
-
-static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index)
-{
- __raw_writel(1 << index, port->base + GPIO_ISR);
-}
-
-static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index,
- int enable)
-{
- u32 l;
-
- l = __raw_readl(port->base + GPIO_IMR);
- l = (l & (~(1 << index))) | (!!enable << index);
- __raw_writel(l, port->base + GPIO_IMR);
-}
-
-static void gpio_ack_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- _clear_gpio_irqstatus(&mxc_gpio_ports[gpio / 32], gpio & 0x1f);
-}
-
-static void gpio_mask_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 0);
-}
-
-static void gpio_unmask_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
-}
-
-static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
-
-static int gpio_set_irq_type(struct irq_data *d, u32 type)
-{
- u32 gpio = irq_to_gpio(d->irq);
- struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
- u32 bit, val;
- int edge;
- void __iomem *reg = port->base;
-
- port->both_edges &= ~(1 << (gpio & 31));
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- edge = GPIO_INT_RISE_EDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- edge = GPIO_INT_FALL_EDGE;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- val = mxc_gpio_get(&port->chip, gpio & 31);
- if (val) {
- edge = GPIO_INT_LOW_LEV;
- pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
- } else {
- edge = GPIO_INT_HIGH_LEV;
- pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
- }
- port->both_edges |= 1 << (gpio & 31);
- break;
- case IRQ_TYPE_LEVEL_LOW:
- edge = GPIO_INT_LOW_LEV;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- edge = GPIO_INT_HIGH_LEV;
- break;
- default:
- return -EINVAL;
- }
-
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
- val = __raw_readl(reg) & ~(0x3 << (bit << 1));
- __raw_writel(val | (edge << (bit << 1)), reg);
- _clear_gpio_irqstatus(port, gpio & 0x1f);
-
- return 0;
-}
-
-static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
-{
- void __iomem *reg = port->base;
- u32 bit, val;
- int edge;
-
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
- val = __raw_readl(reg);
- edge = (val >> (bit << 1)) & 3;
- val &= ~(0x3 << (bit << 1));
- if (edge == GPIO_INT_HIGH_LEV) {
- edge = GPIO_INT_LOW_LEV;
- pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
- } else if (edge == GPIO_INT_LOW_LEV) {
- edge = GPIO_INT_HIGH_LEV;
- pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
- } else {
- pr_err("mxc: invalid configuration for GPIO %d: %x\n",
- gpio, edge);
- return;
- }
- __raw_writel(val | (edge << (bit << 1)), reg);
-}
-
-/* handle 32 interrupts in one status register */
-static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
-{
- u32 gpio_irq_no_base = port->virtual_irq_start;
-
- while (irq_stat != 0) {
- int irqoffset = fls(irq_stat) - 1;
-
- if (port->both_edges & (1 << irqoffset))
- mxc_flip_edge(port, irqoffset);
-
- generic_handle_irq(gpio_irq_no_base + irqoffset);
-
- irq_stat &= ~(1 << irqoffset);
- }
-}
-
-/* MX1 and MX3 has one interrupt *per* gpio port */
-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);
-
- irq_stat = __raw_readl(port->base + GPIO_ISR) &
- __raw_readl(port->base + GPIO_IMR);
-
- mxc_gpio_irq_handler(port, irq_stat);
-}
-
-/* MX2 has one interrupt *for all* gpio ports */
-static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
- int i;
- u32 irq_msk, irq_stat;
- struct mxc_gpio_port *port = irq_get_handler_data(irq);
-
- /* walk through all interrupt status registers */
- for (i = 0; i < gpio_table_size; i++) {
- irq_msk = __raw_readl(port[i].base + GPIO_IMR);
- if (!irq_msk)
- continue;
-
- irq_stat = __raw_readl(port[i].base + GPIO_ISR) & irq_msk;
- if (irq_stat)
- mxc_gpio_irq_handler(&port[i], irq_stat);
- }
-}
-
-/*
- * Set interrupt number "irq" in the GPIO as a wake-up source.
- * While system is running, all registered GPIO interrupts need to have
- * wake-up enabled. When system is suspended, only selected GPIO interrupts
- * need to have wake-up enabled.
- * @param irq interrupt source number
- * @param enable enable as wake-up if equal to non-zero
- * @return This function returns 0 on success.
- */
-static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
-{
- u32 gpio = irq_to_gpio(d->irq);
- u32 gpio_idx = gpio & 0x1F;
- struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
-
- if (enable) {
- if (port->irq_high && (gpio_idx >= 16))
- enable_irq_wake(port->irq_high);
- else
- enable_irq_wake(port->irq);
- } else {
- if (port->irq_high && (gpio_idx >= 16))
- disable_irq_wake(port->irq_high);
- else
- disable_irq_wake(port->irq);
- }
-
- return 0;
-}
-
-static struct irq_chip gpio_irq_chip = {
- .name = "GPIO",
- .irq_ack = gpio_ack_irq,
- .irq_mask = gpio_mask_irq,
- .irq_unmask = gpio_unmask_irq,
- .irq_set_type = gpio_set_irq_type,
- .irq_set_wake = gpio_set_wake_irq,
-};
-
-static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
- int dir)
-{
- struct mxc_gpio_port *port =
- container_of(chip, struct mxc_gpio_port, chip);
- u32 l;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- l = __raw_readl(port->base + GPIO_GDIR);
- if (dir)
- l |= 1 << offset;
- else
- l &= ~(1 << offset);
- __raw_writel(l, port->base + GPIO_GDIR);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct mxc_gpio_port *port =
- container_of(chip, struct mxc_gpio_port, chip);
- void __iomem *reg = port->base + GPIO_DR;
- u32 l;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);
- __raw_writel(l, reg);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct mxc_gpio_port *port =
- container_of(chip, struct mxc_gpio_port, chip);
-
- return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1;
-}
-
-static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- _set_gpio_direction(chip, offset, 0);
- return 0;
-}
-
-static int mxc_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- mxc_gpio_set(chip, offset, value);
- _set_gpio_direction(chip, offset, 1);
- return 0;
-}
-
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
-{
- int i, j;
-
- /* save for local usage */
- mxc_gpio_ports = port;
- gpio_table_size = cnt;
-
- printk(KERN_INFO "MXC GPIO hardware\n");
-
- for (i = 0; i < cnt; i++) {
- /* disable the interrupt and clear the status */
- __raw_writel(0, port[i].base + GPIO_IMR);
- __raw_writel(~0, port[i].base + GPIO_ISR);
- for (j = port[i].virtual_irq_start;
- j < port[i].virtual_irq_start + 32; j++) {
- irq_set_lockdep_class(j, &gpio_lock_class);
- irq_set_chip_and_handler(j, &gpio_irq_chip,
- handle_level_irq);
- set_irq_flags(j, IRQF_VALID);
- }
-
- /* register gpio chip */
- port[i].chip.direction_input = mxc_gpio_direction_input;
- port[i].chip.direction_output = mxc_gpio_direction_output;
- port[i].chip.get = mxc_gpio_get;
- port[i].chip.set = mxc_gpio_set;
- port[i].chip.base = i * 32;
- port[i].chip.ngpio = 32;
-
- spin_lock_init(&port[i].lock);
-
- /* its a serious configuration bug when it fails */
- BUG_ON( gpiochip_add(&port[i].chip) < 0 );
-
- if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
- /* setup one handler for each entry */
- irq_set_chained_handler(port[i].irq,
- mx3_gpio_irq_handler);
- irq_set_handler_data(port[i].irq, &port[i]);
- if (port[i].irq_high) {
- /* setup handler for GPIO 16 to 31 */
- irq_set_chained_handler(port[i].irq_high,
- mx3_gpio_irq_handler);
- irq_set_handler_data(port[i].irq_high,
- &port[i]);
- }
- }
- }
-
- if (cpu_is_mx2()) {
- /* setup one handler for all GPIO interrupts */
- irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler);
- irq_set_handler_data(port[0].irq, port);
- }
-
- return 0;
-}
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/plat-mxc/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index da7991832af6..4e3d97890d69 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -43,6 +43,15 @@ extern void mx35_init_irq(void);
extern void mx50_init_irq(void);
extern void mx51_init_irq(void);
extern void mx53_init_irq(void);
+extern void imx1_soc_init(void);
+extern void imx21_soc_init(void);
+extern void imx25_soc_init(void);
+extern void imx27_soc_init(void);
+extern void imx31_soc_init(void);
+extern void imx35_soc_init(void);
+extern void imx50_soc_init(void);
+extern void imx51_soc_init(void);
+extern void imx53_soc_init(void);
extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
extern int mx1_clocks_init(unsigned long fref);
@@ -55,7 +64,8 @@ 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 mxc_register_gpios(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 *);
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 8e8d175e5077..91fc7cdb5dc9 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -12,32 +12,32 @@
*/
#include <mach/hardware.h>
-#ifdef CONFIG_ARCH_MX1
+#ifdef CONFIG_SOC_IMX1
#define UART_PADDR MX1_UART1_BASE_ADDR
#endif
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
#ifdef UART_PADDR
#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
#endif
#define UART_PADDR MX25_UART1_BASE_ADDR
#endif
-#ifdef CONFIG_ARCH_MX2
+#if defined(CONFIG_SOC_IMX21) || defined (CONFIG_SOC_IMX27)
#ifdef UART_PADDR
#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
#endif
#define UART_PADDR MX2x_UART1_BASE_ADDR
#endif
-#ifdef CONFIG_ARCH_MX3
+#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
#ifdef UART_PADDR
#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
#endif
#define UART_PADDR MX3x_UART1_BASE_ADDR
#endif
-#ifdef CONFIG_ARCH_MX5
+#ifdef CONFIG_SOC_IMX51
#ifdef UART_PADDR
#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
#endif
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index fa8477337f91..bf93820ab61c 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -9,6 +9,10 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/init.h>
+#include <mach/sdma.h>
+
+extern struct device mxc_aips_bus;
+extern struct device mxc_ahb_bus;
struct platform_device *imx_add_platform_device_dmamask(
const char *name, int id,
@@ -291,3 +295,7 @@ struct imx_spi_imx_data {
struct platform_device *__init imx_add_spi_imx(
const struct imx_spi_imx_data *data,
const struct spi_imx_master *pdata);
+
+struct platform_device *imx_add_imx_dma(void);
+struct platform_device *imx_add_imx_sdma(
+ resource_size_t iobase, int irq, struct sdma_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 2e49e71b1b98..066d464d322d 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -78,7 +78,3 @@
movs \irqnr, \irqnr
#endif
.endm
-
- @ irq priority table (not used)
- .macro irq_prio_table
- .endm
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index a2747f12813e..31c820c1b796 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -36,31 +36,4 @@
#define gpio_to_irq(gpio) (MXC_GPIO_IRQ_START + (gpio))
#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)
-struct mxc_gpio_port {
- void __iomem *base;
- int irq;
- int irq_high;
- int virtual_irq_start;
- struct gpio_chip chip;
- u32 both_edges;
- spinlock_t lock;
-};
-
-#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high) \
- { \
- .chip.label = "gpio-" #_id, \
- .irq = _irq, \
- .irq_high = _irq_high, \
- .base = soc ## _IO_ADDRESS( \
- soc ## _GPIO ## _hwid ## _BASE_ADDR), \
- .virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32, \
- }
-
-#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq) \
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
-#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid) \
- DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
-
-int mxc_gpio_init(struct mxc_gpio_port*, int);
-
#endif
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index 67d3e2bed065..a8bfd565dcad 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -97,35 +97,17 @@
#include <mach/mxc.h>
-#ifdef CONFIG_ARCH_MX5
#include <mach/mx50.h>
#include <mach/mx51.h>
#include <mach/mx53.h>
-#endif
-
-#ifdef CONFIG_ARCH_MX3
#include <mach/mx3x.h>
#include <mach/mx31.h>
#include <mach/mx35.h>
-#endif
-
-#ifdef CONFIG_ARCH_MX2
-# include <mach/mx2x.h>
-# ifdef CONFIG_MACH_MX21
-# include <mach/mx21.h>
-# endif
-# ifdef CONFIG_MACH_MX27
-# include <mach/mx27.h>
-# endif
-#endif
-
-#ifdef CONFIG_ARCH_MX1
-# include <mach/mx1.h>
-#endif
-
-#ifdef CONFIG_ARCH_MX25
-# include <mach/mx25.h>
-#endif
+#include <mach/mx2x.h>
+#include <mach/mx21.h>
+#include <mach/mx27.h>
+#include <mach/mx1.h>
+#include <mach/mx25.h>
#define imx_map_entry(soc, name, _type) { \
.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR), \
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx25.h b/arch/arm/plat-mxc/include/mach/iomux-mx25.h
index 2e5244de7ff5..bf64e1e594ed 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx25.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx25.h
@@ -457,7 +457,7 @@
#define MX25_PAD_GPIO_A__USBOTG_PWR IOMUX_PAD(0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PKE)
#define MX25_PAD_GPIO_B__GPIO_B IOMUX_PAD(0x3f4, 0x1f8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_B__CAN1_RX IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K)
+#define MX25_PAD_GPIO_B__CAN1_RX IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K_UP)
#define MX25_PAD_GPIO_B__USBOTG_OC IOMUX_PAD(0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PUS_100K_UP)
#define MX25_PAD_GPIO_C__GPIO_C IOMUX_PAD(0x3f8, 0x1fc, 0x10, 0, 0, NO_PAD_CTRL)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
index e95d9cb8aeb7..9440b9e00e89 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
@@ -39,10 +39,10 @@
#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, o, 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, 0x890, 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)
@@ -55,7 +55,7 @@
#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, 0x898, 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)
@@ -107,7 +107,7 @@
#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, 0x894, 1, 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)
@@ -377,7 +377,7 @@
#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, 0x878, 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)
@@ -393,7 +393,7 @@
#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, 0x890, 2, 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)
@@ -407,7 +407,7 @@
#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, 0x898, 2, 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)
@@ -428,7 +428,7 @@
#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, 0x88C, 1, 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)
@@ -442,7 +442,7 @@
#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, 0x894, 3, 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)
@@ -465,19 +465,19 @@
#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, 0x820, 1, 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, 0x824, 0, 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, 0x828, 0, 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)
@@ -485,7 +485,7 @@
#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, 0x874, 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)
@@ -500,7 +500,7 @@
#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, 0x814, 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)
@@ -510,7 +510,7 @@
#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, 0x884, 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)
@@ -525,7 +525,7 @@
#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, 0x888, 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)
@@ -541,7 +541,7 @@
#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, 0x880, 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)
@@ -557,10 +557,10 @@
#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, 0x87C, 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, 0x818, 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)
@@ -573,7 +573,7 @@
#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, 0x884, 2, 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)
@@ -697,7 +697,7 @@
#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, 17, 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)
@@ -859,7 +859,7 @@
#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, 0x878, 2, 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)
@@ -867,7 +867,7 @@
#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, 0x880, 2, 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)
@@ -877,7 +877,7 @@
#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, 0x87C, 2, 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)
@@ -889,7 +889,7 @@
#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, 0x874, 2, 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)
@@ -906,7 +906,7 @@
#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, 0x884, 4, 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)
@@ -915,7 +915,7 @@
#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, 0x888, 2, 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)
@@ -958,12 +958,12 @@
#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, 1, 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, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6 IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_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)
@@ -1161,13 +1161,13 @@
#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, 0x824, 2, 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, 0x880, 4, 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)
@@ -1214,27 +1214,27 @@
#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(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(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(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(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))
@@ -1272,14 +1272,14 @@
#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(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(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))
@@ -1565,56 +1565,56 @@
#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(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(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(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(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(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(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(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(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))
@@ -1657,7 +1657,7 @@
#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(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))
@@ -1665,7 +1665,7 @@
#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(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))
@@ -1682,7 +1682,7 @@
#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(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))
@@ -1690,14 +1690,14 @@
#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(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(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))
@@ -1705,7 +1705,7 @@
#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(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))
@@ -1713,7 +1713,7 @@
#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(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))
@@ -1721,7 +1721,7 @@
#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(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))
@@ -1729,7 +1729,7 @@
#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(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(NO_PAD_CTRL))
@@ -1737,7 +1737,7 @@
#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(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))
@@ -1745,7 +1745,7 @@
#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(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))
@@ -1753,7 +1753,7 @@
#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(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))
@@ -2061,13 +2061,13 @@
#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(NO_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(NO_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))
@@ -2339,7 +2339,7 @@
#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(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))
@@ -2347,7 +2347,7 @@
#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(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))
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h
index c07d30210c57..6fa8a707b9a0 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v1.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v1.h
@@ -85,9 +85,6 @@
#define GPIO_BOUT_0 (2 << GPIO_BOUT_SHIFT)
#define GPIO_BOUT_1 (3 << GPIO_BOUT_SHIFT)
-/* decode irq number to use with IMR(x), ISR(x) and friends */
-#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5)
-
#define IRQ_GPIOA(x) (MXC_GPIO_IRQ_START + x)
#define IRQ_GPIOB(x) (IRQ_GPIOA(32) + x)
#define IRQ_GPIOC(x) (IRQ_GPIOB(32) + x)
@@ -98,7 +95,6 @@
extern int mxc_gpio_mode(int gpio_mode);
extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
const char *label);
-extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
extern int __init imx_iomuxv1_init(void __iomem *base, int numports);
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
index 82620af1922f..ebbce33097a7 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
@@ -66,7 +66,6 @@ typedef u64 iomux_v3_cfg_t;
#define MUX_MODE_MASK ((iomux_v3_cfg_t)0x1f << MUX_MODE_SHIFT)
#define MUX_PAD_CTRL_SHIFT 41
#define MUX_PAD_CTRL_MASK ((iomux_v3_cfg_t)0x1ffff << MUX_PAD_CTRL_SHIFT)
-#define NO_PAD_CTRL ((iomux_v3_cfg_t)1 << (MUX_PAD_CTRL_SHIFT + 16))
#define MUX_SEL_INPUT_SHIFT 58
#define MUX_SEL_INPUT_MASK ((iomux_v3_cfg_t)0xf << MUX_SEL_INPUT_SHIFT)
@@ -85,6 +84,7 @@ typedef u64 iomux_v3_cfg_t;
* Use to set PAD control
*/
+#define NO_PAD_CTRL (1 << 16)
#define PAD_CTL_DVS (1 << 13)
#define PAD_CTL_HYS (1 << 8)
diff --git a/arch/arm/plat-mxc/include/mach/iomux.h b/arch/arm/plat-mxc/include/mach/iomux.h
deleted file mode 100644
index 3d226d7e7be2..000000000000
--- a/arch/arm/plat-mxc/include/mach/iomux.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Uwe Kleine-Koenig, Pengutronix
- *
- * 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_IOMUX_H__
-#define __MACH_IOMUX_H__
-
-/* This file will go away, please include mach/iomux-mx... directly */
-
-#ifdef CONFIG_ARCH_MX1
-#include <mach/iomux-mx1.h>
-#endif
-#ifdef CONFIG_ARCH_MX2
-#include <mach/iomux-mx2x.h>
-#ifdef CONFIG_MACH_MX21
-#include <mach/iomux-mx21.h>
-#endif
-#ifdef CONFIG_MACH_MX27
-#include <mach/iomux-mx27.h>
-#endif
-#endif
-
-#endif /* __MACH_IOMUX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 35c89bcdf758..00e812bbd81d 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -11,6 +11,8 @@
#ifndef __ASM_ARCH_MXC_IRQS_H__
#define __ASM_ARCH_MXC_IRQS_H__
+#include <asm-generic/gpio.h>
+
/*
* SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
*/
@@ -22,30 +24,13 @@
#define MXC_GPIO_IRQ_START MXC_INTERNAL_IRQS
-/* these are ordered by size to support multi-SoC kernels */
-#if defined CONFIG_SOC_IMX53
-#define MXC_GPIO_IRQS (32 * 7)
-#elif defined CONFIG_ARCH_MX2
-#define MXC_GPIO_IRQS (32 * 6)
-#elif defined CONFIG_SOC_IMX50
-#define MXC_GPIO_IRQS (32 * 6)
-#elif defined CONFIG_ARCH_MX1
-#define MXC_GPIO_IRQS (32 * 4)
-#elif defined CONFIG_ARCH_MX25
-#define MXC_GPIO_IRQS (32 * 4)
-#elif defined CONFIG_SOC_IMX51
-#define MXC_GPIO_IRQS (32 * 4)
-#elif defined CONFIG_ARCH_MX3
-#define MXC_GPIO_IRQS (32 * 3)
-#endif
-
/*
* The next 16 interrupts are for board specific purposes. Since
* the kernel can only run on one machine at a time, we can re-use
* these. If you need more, increase MXC_BOARD_IRQS, but keep it
* within sensible limits.
*/
-#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + MXC_GPIO_IRQS)
+#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + ARCH_NR_GPIOS)
#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
#define MXC_BOARD_IRQS 80
diff --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
index 9d2a1ef84de2..5e3c3236ebf3 100644
--- a/arch/arm/plat-mxc/include/mach/mx53.h
+++ b/arch/arm/plat-mxc/include/mach/mx53.h
@@ -145,14 +145,14 @@
/*
* Memory regions and CS
*/
-#define MX53_CSD0_BASE_ADDR 0x90000000
-#define MX53_CSD1_BASE_ADDR 0xA0000000
-#define MX53_CS0_BASE_ADDR 0xB0000000
-#define MX53_CS1_BASE_ADDR 0xB8000000
-#define MX53_CS2_BASE_ADDR 0xC0000000
-#define MX53_CS3_BASE_ADDR 0xC8000000
-#define MX53_CS4_BASE_ADDR 0xCC000000
-#define MX53_CS5_BASE_ADDR 0xCE000000
+#define MX53_CSD0_BASE_ADDR 0x70000000
+#define MX53_CSD1_BASE_ADDR 0xB0000000
+#define MX53_CS0_BASE_ADDR 0xF0000000
+#define MX53_CS1_32MB_BASE_ADDR 0xF2000000
+#define MX53_CS1_64MB_BASE_ADDR 0xF4000000
+#define MX53_CS2_64MB_BASE_ADDR 0xF4000000
+#define MX53_CS2_96MB_BASE_ADDR 0xF6000000
+#define MX53_CS3_BASE_ADDR 0xF6000000
#define MX53_IO_P2V(x) IMX_IO_P2V(x)
#define MX53_IO_ADDRESS(x) IOMEM(MX53_IO_P2V(x))
@@ -176,10 +176,10 @@
/*
* DMA request assignments
*/
-#define MX53_DMA_REQ_SSI3_TX1 47
-#define MX53_DMA_REQ_SSI3_RX1 46
-#define MX53_DMA_REQ_SSI3_TX2 45
-#define MX53_DMA_REQ_SSI3_RX2 44
+#define MX53_DMA_REQ_SSI3_TX0 47
+#define MX53_DMA_REQ_SSI3_RX0 46
+#define MX53_DMA_REQ_SSI3_TX1 45
+#define MX53_DMA_REQ_SSI3_RX1 44
#define MX53_DMA_REQ_UART3_TX 43
#define MX53_DMA_REQ_UART3_RX 42
#define MX53_DMA_REQ_ESAI_TX 41
@@ -194,14 +194,14 @@
#define MX53_DMA_REQ_ASRC_DMA1 32
#define MX53_DMA_REQ_EMI_WR 31
#define MX53_DMA_REQ_EMI_RD 30
-#define MX53_DMA_REQ_SSI1_TX1 29
-#define MX53_DMA_REQ_SSI1_RX1 28
-#define MX53_DMA_REQ_SSI1_TX2 27
-#define MX53_DMA_REQ_SSI1_RX2 26
-#define MX53_DMA_REQ_SSI2_TX1 25
-#define MX53_DMA_REQ_SSI2_RX1 24
-#define MX53_DMA_REQ_SSI2_TX2 23
-#define MX53_DMA_REQ_SSI2_RX2 22
+#define MX53_DMA_REQ_SSI1_TX0 29
+#define MX53_DMA_REQ_SSI1_RX0 28
+#define MX53_DMA_REQ_SSI1_TX1 27
+#define MX53_DMA_REQ_SSI1_RX1 26
+#define MX53_DMA_REQ_SSI2_TX0 25
+#define MX53_DMA_REQ_SSI2_RX0 24
+#define MX53_DMA_REQ_SSI2_TX1 23
+#define MX53_DMA_REQ_SSI2_RX1 22
#define MX53_DMA_REQ_I2C2_SDHC2 21
#define MX53_DMA_REQ_I2C1_SDHC1 20
#define MX53_DMA_REQ_UART1_TX 19
@@ -233,7 +233,7 @@
#define MX53_INT_ESDHC2 2
#define MX53_INT_ESDHC3 3
#define MX53_INT_ESDHC4 4
-#define MX53_INT_RESV5 5
+#define MX53_INT_DAP 5
#define MX53_INT_SDMA 6
#define MX53_INT_IOMUX 7
#define MX53_INT_NFC 8
@@ -241,7 +241,7 @@
#define MX53_INT_IPU_ERR 10
#define MX53_INT_IPU_SYN 11
#define MX53_INT_GPU 12
-#define MX53_INT_RESV13 13
+#define MX53_INT_UART4 13
#define MX53_INT_USB_H1 14
#define MX53_INT_EMI 15
#define MX53_INT_USB_H2 16
@@ -262,8 +262,8 @@
#define MX53_INT_UART1 31
#define MX53_INT_UART2 32
#define MX53_INT_UART3 33
-#define MX53_INT_RESV34 34
-#define MX53_INT_RESV35 35
+#define MX53_INT_RTC 34
+#define MX53_INT_PTP 35
#define MX53_INT_ECSPI1 36
#define MX53_INT_ECSPI2 37
#define MX53_INT_CSPI 38
@@ -293,8 +293,8 @@
#define MX53_INT_I2C1 62
#define MX53_INT_I2C2 63
#define MX53_INT_I2C3 64
-#define MX53_INT_RESV65 65
-#define MX53_INT_RESV66 66
+#define MX53_INT_MLB 65
+#define MX53_INT_ASRC 66
#define MX53_INT_SPDIF 67
#define MX53_INT_SIM_DAT 68
#define MX53_INT_IIM 69
@@ -314,7 +314,7 @@
#define MX53_INT_CAN2 83
#define MX53_INT_GPU2_IRQ 84
#define MX53_INT_GPU2_BUSY 85
-#define MX53_INT_RESV86 86
+#define MX53_INT_UART5 86
#define MX53_INT_FEC 87
#define MX53_INT_OWIRE 88
#define MX53_INT_CTI1_TG2 89
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 4ac53ce97c24..09879235a9f5 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -68,7 +68,7 @@
extern unsigned int __mxc_cpu_type;
#endif
-#ifdef CONFIG_ARCH_MX1
+#ifdef CONFIG_SOC_IMX1
# ifdef mxc_cpu_type
# undef mxc_cpu_type
# define mxc_cpu_type __mxc_cpu_type
@@ -80,7 +80,7 @@ extern unsigned int __mxc_cpu_type;
# define cpu_is_mx1() (0)
#endif
-#ifdef CONFIG_MACH_MX21
+#ifdef CONFIG_SOC_IMX21
# ifdef mxc_cpu_type
# undef mxc_cpu_type
# define mxc_cpu_type __mxc_cpu_type
@@ -92,7 +92,7 @@ extern unsigned int __mxc_cpu_type;
# define cpu_is_mx21() (0)
#endif
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
# ifdef mxc_cpu_type
# undef mxc_cpu_type
# define mxc_cpu_type __mxc_cpu_type
@@ -104,7 +104,7 @@ extern unsigned int __mxc_cpu_type;
# define cpu_is_mx25() (0)
#endif
-#ifdef CONFIG_MACH_MX27
+#ifdef CONFIG_SOC_IMX27
# ifdef mxc_cpu_type
# undef mxc_cpu_type
# define mxc_cpu_type __mxc_cpu_type
diff --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h
index 913e0432e40e..f495c87c113f 100644
--- a/arch/arm/plat-mxc/include/mach/sdma.h
+++ b/arch/arm/plat-mxc/include/mach/sdma.h
@@ -49,14 +49,12 @@ struct sdma_script_start_addrs {
* struct sdma_platform_data - platform specific data for SDMA engine
*
* @sdma_version The version of this SDMA engine
- * @cpu_name used to generate the firmware name
- * @to_version CPU Tape out version
+ * @fw_name The firmware name
* @script_addrs SDMA scripts addresses in SDMA ROM
*/
struct sdma_platform_data {
int sdma_version;
- char *cpu_name;
- int to_version;
+ char *fw_name;
struct sdma_script_start_addrs *script_addrs;
};
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
index d61d5c74817c..10343d1f87e1 100644
--- a/arch/arm/plat-mxc/include/mach/timex.h
+++ b/arch/arm/plat-mxc/include/mach/timex.h
@@ -16,16 +16,7 @@
#ifndef __ASM_ARCH_MXC_TIMEX_H__
#define __ASM_ARCH_MXC_TIMEX_H__
-#if defined CONFIG_ARCH_MX1
-#define CLOCK_TICK_RATE 16000000
-#elif defined CONFIG_ARCH_MX2
-#define CLOCK_TICK_RATE 13300000
-#elif defined CONFIG_ARCH_MX3
-#define CLOCK_TICK_RATE 16625000
-#elif defined CONFIG_ARCH_MX25
-#define CLOCK_TICK_RATE 16000000
-#elif defined CONFIG_ARCH_MX5
-#define CLOCK_TICK_RATE 8000000
-#endif
+/* Bogus value */
+#define CLOCK_TICK_RATE 12345678
#endif /* __ASM_ARCH_MXC_TIMEX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index d85e2d1c0324..88fd40452567 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -117,6 +117,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
case MACH_TYPE_MX53_EVK:
case MACH_TYPE_MX53_LOCO:
case MACH_TYPE_MX53_SMD:
+ case MACH_TYPE_MX53_ARD:
uart_base = MX53_UART1_BASE_ADDR;
break;
default:
diff --git a/arch/arm/plat-mxc/iomux-v1.c b/arch/arm/plat-mxc/iomux-v1.c
index 3238c10d4e02..1f73963bc13e 100644
--- a/arch/arm/plat-mxc/iomux-v1.c
+++ b/arch/arm/plat-mxc/iomux-v1.c
@@ -157,7 +157,7 @@ EXPORT_SYMBOL(mxc_gpio_mode);
static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
{
size_t i;
- int ret;
+ int ret = 0;
for (i = 0; i < count; ++i) {
ret = mxc_gpio_mode(list[i]);
@@ -172,45 +172,13 @@ static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
const char *label)
{
- size_t i;
int ret;
- for (i = 0; i < count; ++i) {
- unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-
- ret = gpio_request(gpio, label);
- if (ret)
- goto err_gpio_request;
- }
-
ret = imx_iomuxv1_setup_multiple(pin_list, count);
- if (ret)
- goto err_setup;
-
- return 0;
-
-err_setup:
- BUG_ON(i != count);
-
-err_gpio_request:
- mxc_gpio_release_multiple_pins(pin_list, i);
-
return ret;
}
EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins);
-void mxc_gpio_release_multiple_pins(const int *pin_list, int count)
-{
- size_t i;
-
- for (i = 0; i < count; ++i) {
- unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-
- gpio_free(gpio);
- }
-}
-EXPORT_SYMBOL(mxc_gpio_release_multiple_pins);
-
int __init imx_iomuxv1_init(void __iomem *base, int numports)
{
imx_iomuxv1_baseaddr = base;
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
index e1c6eff7258a..96953e2e4f11 100644
--- a/arch/arm/plat-mxc/irq-common.c
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -42,17 +42,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
{
- struct mxc_irq_chip *chip;
- struct irq_chip *base;
+ struct irq_chip_generic *gc;
+ int (*set_irq_fiq)(unsigned int, unsigned int);
int ret;
ret = -ENOSYS;
- base = irq_get_chip(irq);
- if (base) {
- chip = container_of(base, struct mxc_irq_chip, base);
- if (chip->set_irq_fiq)
- ret = chip->set_irq_fiq(irq, type);
+ gc = irq_get_chip_data(irq);
+ if (gc && gc->private) {
+ set_irq_fiq = gc->private;
+ ret = set_irq_fiq(irq, type);
}
return ret;
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
index 7a61ef8f471a..761c3c940a68 100644
--- a/arch/arm/plat-mxc/pwm.c
+++ b/arch/arm/plat-mxc/pwm.c
@@ -214,14 +214,14 @@ static int __devinit mxc_pwm_probe(struct platform_device *pdev)
goto err_free_clk;
}
- r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
+ r = request_mem_region(r->start, resource_size(r), pdev->name);
if (r == NULL) {
dev_err(&pdev->dev, "failed to request memory resource\n");
ret = -EBUSY;
goto err_free_clk;
}
- pwm->mmio_base = ioremap(r->start, r->end - r->start + 1);
+ pwm->mmio_base = ioremap(r->start, resource_size(r));
if (pwm->mmio_base == NULL) {
dev_err(&pdev->dev, "failed to ioremap() registers\n");
ret = -ENODEV;
@@ -236,7 +236,7 @@ static int __devinit mxc_pwm_probe(struct platform_device *pdev)
return 0;
err_free_mem:
- release_mem_region(r->start, r->end - r->start + 1);
+ release_mem_region(r->start, resource_size(r));
err_free_clk:
clk_put(pwm->clk);
err_free:
@@ -260,7 +260,7 @@ static int __devexit mxc_pwm_remove(struct platform_device *pdev)
iounmap(pwm->mmio_base);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, r->end - r->start + 1);
+ release_mem_region(r->start, resource_size(r));
clk_put(pwm->clk);
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index 57f9395f87ce..f257fccdc394 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -49,6 +49,8 @@
void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
+#define TZIC_NUM_IRQS 128
+
#ifdef CONFIG_FIQ
static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
{
@@ -66,78 +68,34 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
return 0;
}
+#else
+#define tzic_set_irq_fiq NULL
#endif
-/**
- * tzic_mask_irq() - Disable interrupt source "d" in the TZIC
- *
- * @param d interrupt source
- */
-static void tzic_mask_irq(struct irq_data *d)
-{
- int index, off;
-
- index = d->irq >> 5;
- off = d->irq & 0x1F;
- __raw_writel(1 << off, tzic_base + TZIC_ENCLEAR0(index));
-}
+static unsigned int *wakeup_intr[4];
-/**
- * tzic_unmask_irq() - Enable interrupt source "d" in the TZIC
- *
- * @param d interrupt source
- */
-static void tzic_unmask_irq(struct irq_data *d)
+static __init void tzic_init_gc(unsigned int irq_start)
{
- int index, off;
-
- index = d->irq >> 5;
- off = d->irq & 0x1F;
- __raw_writel(1 << off, tzic_base + TZIC_ENSET0(index));
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+ int idx = irq_start >> 5;
+
+ gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
+ handle_level_irq);
+ gc->private = tzic_set_irq_fiq;
+ gc->wake_enabled = IRQ_MSK(32);
+ wakeup_intr[idx] = &gc->wake_active;
+
+ ct = gc->chip_types;
+ ct->chip.irq_mask = irq_gc_mask_disable_reg;
+ ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+ ct->chip.irq_set_wake = irq_gc_set_wake;
+ ct->regs.disable = TZIC_ENCLEAR0(idx);
+ ct->regs.enable = TZIC_ENSET0(idx);
+
+ irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
}
-static unsigned int wakeup_intr[4];
-
-/**
- * tzic_set_wake_irq() - Set interrupt source "d" in the TZIC as a wake-up source.
- *
- * @param d interrupt source
- * @param enable enable as wake-up if equal to non-zero
- * disble as wake-up if equal to zero
- *
- * @return This function returns 0 on success.
- */
-static int tzic_set_wake_irq(struct irq_data *d, unsigned int enable)
-{
- unsigned int index, off;
-
- index = d->irq >> 5;
- off = d->irq & 0x1F;
-
- if (index > 3)
- return -EINVAL;
-
- if (enable)
- wakeup_intr[index] |= (1 << off);
- else
- wakeup_intr[index] &= ~(1 << off);
-
- return 0;
-}
-
-static struct mxc_irq_chip mxc_tzic_chip = {
- .base = {
- .name = "MXC_TZIC",
- .irq_ack = tzic_mask_irq,
- .irq_mask = tzic_mask_irq,
- .irq_unmask = tzic_unmask_irq,
- .irq_set_wake = tzic_set_wake_irq,
- },
-#ifdef CONFIG_FIQ
- .set_irq_fiq = tzic_set_irq_fiq,
-#endif
-};
-
/*
* This function initializes the TZIC hardware and disables all the
* interrupts. It registers the interrupt enable and disable functions
@@ -166,11 +124,8 @@ void __init tzic_init_irq(void __iomem *irqbase)
/* all IRQ no FIQ Warning :: No selection */
- for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
- irq_set_chip_and_handler(i, &mxc_tzic_chip.base,
- handle_level_irq);
- set_irq_flags(i, IRQF_VALID);
- }
+ for (i = 0; i < TZIC_NUM_IRQS; i += 32)
+ tzic_init_gc(i);
#ifdef CONFIG_FIQ
/* Initialize FIQ */
@@ -197,7 +152,7 @@ int tzic_enable_wake(int is_idle)
for (i = 0; i < 4; i++) {
v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) :
- wakeup_intr[i];
+ *wakeup_intr[i];
__raw_writel(v, tzic_base + TZIC_WAKEUP0(i));
}
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
index c44886062f8e..685c78716d95 100644
--- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h
+++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
@@ -10,6 +10,7 @@
#define STE_DMA40_H
#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 49a4c75243fc..6e6735f04ee3 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -211,9 +211,6 @@ choice
depends on ARCH_OMAP
default OMAP_PM_NOOP
-config OMAP_PM_NONE
- bool "No PM layer"
-
config OMAP_PM_NOOP
bool "No-op/debug PM layer"
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index c9122dd6ee8d..3ba4d11ca73e 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -475,18 +475,48 @@ int __init clk_init(struct clk_functions * custom_clocks)
/*
* debugfs support to trace clock tree hierarchy and attributes
*/
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
static struct dentry *clk_debugfs_root;
+static int clk_dbg_show_summary(struct seq_file *s, void *unused)
+{
+ struct clk *c;
+ struct clk *pa;
+
+ seq_printf(s, "%-30s %-30s %-10s %s\n",
+ "clock-name", "parent-name", "rate", "use-count");
+
+ list_for_each_entry(c, &clocks, node) {
+ pa = c->parent;
+ seq_printf(s, "%-30s %-30s %-10lu %d\n",
+ c->name, pa ? pa->name : "none", c->rate, c->usecount);
+ }
+
+ return 0;
+}
+
+static int clk_dbg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_dbg_show_summary, inode->i_private);
+}
+
+static const struct file_operations debug_clock_fops = {
+ .open = clk_dbg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int clk_debugfs_register_one(struct clk *c)
{
int err;
- struct dentry *d, *child, *child_tmp;
+ struct dentry *d;
struct clk *pa = c->parent;
- char s[255];
- char *p = s;
- p += sprintf(p, "%s", c->name);
- d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
+ d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
if (!d)
return -ENOMEM;
c->dent = d;
@@ -509,10 +539,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;
err_out:
- d = c->dent;
- list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(c->dent);
+ debugfs_remove_recursive(c->dent);
return err;
}
@@ -551,6 +578,12 @@ static int __init clk_debugfs_init(void)
if (err)
goto err_out;
}
+
+ d = debugfs_create_file("summary", S_IRUGO,
+ d, NULL, &debug_clock_fops);
+ if (!d)
+ return -ENOMEM;
+
return 0;
err_out:
debugfs_remove_recursive(clk_debugfs_root);
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index f7fed6080190..a6cbb712da51 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -18,6 +18,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sched.h>
+#include <linux/clocksource.h>
#include <asm/sched_clock.h>
@@ -26,87 +27,16 @@
#include <plat/clock.h>
-
/*
* 32KHz clocksource ... always available, on pretty most chips except
* OMAP 730 and 1510. Other timers could be used as clocksources, with
* higher resolution in free-running counter modes (e.g. 12 MHz xtal),
* but systems won't necessarily want to spend resources that way.
*/
+static void __iomem *timer_32k_base;
#define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410
-#include <linux/clocksource.h>
-
-/*
- * offset_32k holds the init time counter value. It is then subtracted
- * from every counter read to achieve a counter that counts time from the
- * kernel boot (needed for sched_clock()).
- */
-static u32 offset_32k __read_mostly;
-
-#ifdef CONFIG_ARCH_OMAP16XX
-static cycle_t notrace omap16xx_32k_read(struct clocksource *cs)
-{
- return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
-}
-#else
-#define omap16xx_32k_read NULL
-#endif
-
-#ifdef CONFIG_SOC_OMAP2420
-static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
-{
- return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2420_32k_read NULL
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
-static cycle_t notrace omap2430_32k_read(struct clocksource *cs)
-{
- return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2430_32k_read NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-static cycle_t notrace omap34xx_32k_read(struct clocksource *cs)
-{
- return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap34xx_32k_read NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static cycle_t notrace omap44xx_32k_read(struct clocksource *cs)
-{
- return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap44xx_32k_read NULL
-#endif
-
-/*
- * Kernel assumes that sched_clock can be called early but may not have
- * things ready yet.
- */
-static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs)
-{
- return 0;
-}
-
-static struct clocksource clocksource_32k = {
- .name = "32k_counter",
- .rating = 250,
- .read = omap_32k_read_dummy,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
/*
* Returns current time from boot in nsecs. It's OK for this to wrap
* around for now, as it's just a relative time stamp.
@@ -122,11 +52,11 @@ static DEFINE_CLOCK_DATA(cd);
static inline unsigned long long notrace _omap_32k_sched_clock(void)
{
- u32 cyc = clocksource_32k.read(&clocksource_32k);
+ u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
}
-#ifndef CONFIG_OMAP_MPU_TIMER
+#if defined(CONFIG_OMAP_32K_TIMER) && !defined(CONFIG_OMAP_MPU_TIMER)
unsigned long long notrace sched_clock(void)
{
return _omap_32k_sched_clock();
@@ -140,7 +70,7 @@ unsigned long long notrace omap_32k_sched_clock(void)
static void notrace omap_update_sched_clock(void)
{
- u32 cyc = clocksource_32k.read(&clocksource_32k);
+ u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
update_sched_clock(&cd, cyc, (u32)~0);
}
@@ -153,6 +83,7 @@ static void notrace omap_update_sched_clock(void)
*/
static struct timespec persistent_ts;
static cycles_t cycles, last_cycles;
+static unsigned int persistent_mult, persistent_shift;
void read_persistent_clock(struct timespec *ts)
{
unsigned long long nsecs;
@@ -160,11 +91,10 @@ void read_persistent_clock(struct timespec *ts)
struct timespec *tsp = &persistent_ts;
last_cycles = cycles;
- cycles = clocksource_32k.read(&clocksource_32k);
+ cycles = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
delta = cycles - last_cycles;
- nsecs = clocksource_cyc2ns(delta,
- clocksource_32k.mult, clocksource_32k.shift);
+ nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift);
timespec_add_ns(tsp, nsecs);
*ts = *tsp;
@@ -176,29 +106,46 @@ int __init omap_init_clocksource_32k(void)
"%s: can't register clocksource!\n";
if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
+ u32 pbase;
+ unsigned long size = SZ_4K;
+ void __iomem *base;
struct clk *sync_32k_ick;
- if (cpu_is_omap16xx())
- clocksource_32k.read = omap16xx_32k_read;
- else if (cpu_is_omap2420())
- clocksource_32k.read = omap2420_32k_read;
+ if (cpu_is_omap16xx()) {
+ pbase = OMAP16XX_TIMER_32K_SYNCHRONIZED;
+ size = SZ_1K;
+ } else if (cpu_is_omap2420())
+ pbase = OMAP2420_32KSYNCT_BASE + 0x10;
else if (cpu_is_omap2430())
- clocksource_32k.read = omap2430_32k_read;
+ pbase = OMAP2430_32KSYNCT_BASE + 0x10;
else if (cpu_is_omap34xx())
- clocksource_32k.read = omap34xx_32k_read;
+ pbase = OMAP3430_32KSYNCT_BASE + 0x10;
else if (cpu_is_omap44xx())
- clocksource_32k.read = omap44xx_32k_read;
+ pbase = OMAP4430_32KSYNCT_BASE + 0x10;
else
return -ENODEV;
+ /* For this to work we must have a static mapping in io.c for this area */
+ base = ioremap(pbase, size);
+ if (!base)
+ return -ENODEV;
+
sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
if (!IS_ERR(sync_32k_ick))
clk_enable(sync_32k_ick);
- offset_32k = clocksource_32k.read(&clocksource_32k);
+ timer_32k_base = base;
+
+ /*
+ * 120000 rough estimate from the calculations in
+ * __clocksource_updatefreq_scale.
+ */
+ clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
+ 32768, NSEC_PER_SEC, 120000);
- if (clocksource_register_hz(&clocksource_32k, 32768))
- printk(err, clocksource_32k.name);
+ if (clocksource_mmio_init(base, "32k_counter", 32768, 250, 32,
+ clocksource_mmio_readl_up))
+ printk(err, "32k_counter");
init_fixed_sched_clock(&cd, omap_update_sched_clock, 32,
32768, SC_MULT, SC_SHIFT);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index ee9f6ebba29b..75a847dd776a 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -41,127 +41,6 @@
#include <plat/dmtimer.h>
#include <mach/irqs.h>
-/* 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
-#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
-#define _OMAP_TIMER_CTRL_OFFSET 0x24
-#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
-#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
-#define OMAP_TIMER_CTRL_PT (1 << 12)
-#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
-#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
-#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
-#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
-#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
-#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
-#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* prescaler value shift */
-#define OMAP_TIMER_CTRL_POSTED (1 << 2)
-#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
-#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
-#define _OMAP_TIMER_COUNTER_OFFSET 0x28
-#define _OMAP_TIMER_LOAD_OFFSET 0x2c
-#define _OMAP_TIMER_TRIGGER_OFFSET 0x30
-#define _OMAP_TIMER_WRITE_PEND_OFFSET 0x34
-#define WP_NONE 0 /* no write pending bit */
-#define WP_TCLR (1 << 0)
-#define WP_TCRR (1 << 1)
-#define WP_TLDR (1 << 2)
-#define WP_TTGR (1 << 3)
-#define WP_TMAR (1 << 4)
-#define WP_TPIR (1 << 5)
-#define WP_TNIR (1 << 6)
-#define WP_TCVR (1 << 7)
-#define WP_TOCR (1 << 8)
-#define WP_TOWR (1 << 9)
-#define _OMAP_TIMER_MATCH_OFFSET 0x38
-#define _OMAP_TIMER_CAPTURE_OFFSET 0x3c
-#define _OMAP_TIMER_IF_CTRL_OFFSET 0x40
-#define _OMAP_TIMER_CAPTURE2_OFFSET 0x44 /* TCAR2, 34xx only */
-#define _OMAP_TIMER_TICK_POS_OFFSET 0x48 /* TPIR, 34xx only */
-#define _OMAP_TIMER_TICK_NEG_OFFSET 0x4c /* TNIR, 34xx only */
-#define _OMAP_TIMER_TICK_COUNT_OFFSET 0x50 /* TCVR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */
-
-/* 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))
-
-#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \
- | (WP_TCLR << WPSHIFT))
-
-#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \
- | (WP_TCRR << WPSHIFT))
-
-#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \
- | (WP_TLDR << WPSHIFT))
-
-#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \
- | (WP_TTGR << WPSHIFT))
-
-#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \
- | (WP_TMAR << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \
- | (WP_TPIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \
- | (WP_TNIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \
- | (WP_TCVR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_SET_REG \
- (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
- (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
-
-struct omap_dm_timer {
- unsigned long phys_base;
- int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
- struct clk *iclk, *fclk;
-#endif
- void __iomem *io_base;
- unsigned reserved:1;
- unsigned enabled:1;
- unsigned posted:1;
-};
-
static int dm_timer_count;
#ifdef CONFIG_ARCH_OMAP1
@@ -291,11 +170,7 @@ static spinlock_t dm_timer_lock;
*/
static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
{
- if (timer->posted)
- while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
- cpu_relax();
- return readl(timer->io_base + (reg & 0xff));
+ return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
}
/*
@@ -307,11 +182,7 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
u32 value)
{
- if (timer->posted)
- while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
- cpu_relax();
- writel(value, timer->io_base + (reg & 0xff));
+ __omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
}
static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
@@ -330,7 +201,7 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
static void omap_dm_timer_reset(struct omap_dm_timer *timer)
{
- u32 l;
+ int autoidle = 0, wakeup = 0;
if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
@@ -338,28 +209,21 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
}
omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
- l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
- l |= 0x02 << 3; /* Set to smart-idle mode */
- l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
-
- /* Enable autoidle on OMAP2 / OMAP3 */
- if (cpu_is_omap24xx() || cpu_is_omap34xx())
- l |= 0x1 << 0;
+ /* Enable autoidle on OMAP2+ */
+ if (cpu_class_is_omap2())
+ autoidle = 1;
/*
* Enable wake-up on OMAP2 CPUs.
*/
if (cpu_class_is_omap2())
- l |= 1 << 2;
- omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+ wakeup = 1;
- /* Match hardware reset default of posted mode */
- omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
- OMAP_TIMER_CTRL_POSTED);
+ __omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
timer->posted = 1;
}
-static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+void omap_dm_timer_prepare(struct omap_dm_timer *timer)
{
omap_dm_timer_enable(timer);
omap_dm_timer_reset(timer);
@@ -531,25 +395,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);
void omap_dm_timer_stop(struct omap_dm_timer *timer)
{
- u32 l;
+ unsigned long rate = 0;
- l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
- if (l & OMAP_TIMER_CTRL_ST) {
- l &= ~0x1;
- omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
#ifdef CONFIG_ARCH_OMAP2PLUS
- /* Readback to make sure write has completed */
- omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
- /*
- * Wait for functional clock period x 3.5 to make sure that
- * timer is stopped
- */
- udelay(3500000 / clk_get_rate(timer->fclk) + 1);
+ rate = clk_get_rate(timer->fclk);
#endif
- }
- /* Ack possibly pending interrupt */
- omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
- OMAP_TIMER_INT_OVERFLOW);
+
+ __omap_dm_timer_stop(timer->io_base, timer->posted, rate);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
@@ -572,22 +424,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
- int ret = -EINVAL;
-
if (source < 0 || source >= 3)
return -EINVAL;
- clk_disable(timer->fclk);
- ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
- clk_enable(timer->fclk);
-
- /*
- * When the functional clock disappears, too quick writes seem
- * to cause an abort. XXX Is this still necessary?
- */
- __delay(300000);
-
- return ret;
+ return __omap_dm_timer_set_source(timer->fclk,
+ dm_source_clocks[source]);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
@@ -625,8 +466,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
}
l |= OMAP_TIMER_CTRL_ST;
- omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
- omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+ __omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
@@ -679,8 +519,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
- omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
- omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
+ __omap_dm_timer_int_enable(timer->io_base, value);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
@@ -696,17 +535,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
- omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
+ __omap_dm_timer_write_status(timer->io_base, value);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
- unsigned int l;
-
- l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
-
- return l;
+ return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
@@ -737,7 +572,7 @@ int omap_dm_timers_active(void)
}
EXPORT_SYMBOL_GPL(omap_dm_timers_active);
-int __init omap_dm_timer_init(void)
+static int __init omap_dm_timer_init(void)
{
struct omap_dm_timer *timer;
int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */
@@ -790,8 +625,16 @@ int __init omap_dm_timer_init(void)
sprintf(clk_name, "gpt%d_fck", i + 1);
timer->fclk = clk_get(NULL, clk_name);
}
+
+ /* 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
}
return 0;
}
+
+arch_initcall(omap_dm_timer_init);
diff --git a/arch/arm/plat-omap/include/plat/clkdev.h b/arch/arm/plat-omap/include/plat/clkdev.h
deleted file mode 100644
index 730c49d1ebd8..000000000000
--- a/arch/arm/plat-omap/include/plat/clkdev.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-static inline int __clk_get(struct clk *clk)
-{
- return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h
index f1899a3e4174..387a9638991b 100644
--- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
+++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h
@@ -39,6 +39,7 @@ struct omap_clk {
#define CK_36XX (1 << 10) /* 36xx/37xx-specific clocks */
#define CK_443X (1 << 11)
#define CK_TI816X (1 << 12)
+#define CK_446X (1 << 13)
#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS)
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 006e599c6613..df4b9683f17f 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -58,10 +58,12 @@ struct clkops {
#define RATE_IN_36XX (1 << 4)
#define RATE_IN_4430 (1 << 5)
#define RATE_IN_TI816X (1 << 6)
+#define RATE_IN_4460 (1 << 7)
#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
#define RATE_IN_34XX (RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
#define RATE_IN_3XXX (RATE_IN_34XX | RATE_IN_36XX)
+#define RATE_IN_44XX (RATE_IN_4430 | RATE_IN_4460)
/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
#define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX)
@@ -152,7 +154,7 @@ struct dpll_data {
u16 max_multiplier;
u8 last_rounded_n;
u8 min_divider;
- u8 max_divider;
+ u16 max_divider;
u8 modes;
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
void __iomem *autoidle_reg;
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 5288130be96e..4564cc697d7f 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -34,7 +34,11 @@
struct sys_timer;
extern void omap_map_common_io(void);
-extern struct sys_timer omap_timer;
+extern struct sys_timer omap1_timer;
+extern struct sys_timer omap2_timer;
+extern struct sys_timer omap3_timer;
+extern struct sys_timer omap3_secure_timer;
+extern struct sys_timer omap4_timer;
extern bool omap_32k_timer_init(void);
extern int __init omap_init_clocksource_32k(void);
extern unsigned long long notrace omap_32k_sched_clock(void);
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 8198bb6cdb5e..67b3d75884cd 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -88,6 +88,7 @@ unsigned int omap_rev(void);
* cpu_is_omap243x(): True for OMAP2430
* cpu_is_omap343x(): True for OMAP3430
* cpu_is_omap443x(): True for OMAP4430
+ * cpu_is_omap446x(): True for OMAP4460
*/
#define GET_OMAP_CLASS (omap_rev() & 0xff)
@@ -123,6 +124,7 @@ IS_OMAP_SUBCLASS(243x, 0x243)
IS_OMAP_SUBCLASS(343x, 0x343)
IS_OMAP_SUBCLASS(363x, 0x363)
IS_OMAP_SUBCLASS(443x, 0x443)
+IS_OMAP_SUBCLASS(446x, 0x446)
IS_TI_SUBCLASS(816x, 0x816)
@@ -137,6 +139,7 @@ IS_TI_SUBCLASS(816x, 0x816)
#define cpu_is_ti816x() 0
#define cpu_is_omap44xx() 0
#define cpu_is_omap443x() 0
+#define cpu_is_omap446x() 0
#if defined(MULTI_OMAP1)
# if defined(CONFIG_ARCH_OMAP730)
@@ -361,8 +364,10 @@ IS_OMAP_TYPE(3517, 0x3517)
# if defined(CONFIG_ARCH_OMAP4)
# undef cpu_is_omap44xx
# undef cpu_is_omap443x
+# undef cpu_is_omap446x
# define cpu_is_omap44xx() is_omap44xx()
# define cpu_is_omap443x() is_omap443x()
+# define cpu_is_omap446x() is_omap446x()
# endif
/* Macros to detect if we have OMAP1 or OMAP2 */
@@ -410,6 +415,9 @@ IS_OMAP_TYPE(3517, 0x3517)
#define OMAP4430_REV_ES2_1 (OMAP443X_CLASS | (0x21 << 8))
#define OMAP4430_REV_ES2_2 (OMAP443X_CLASS | (0x22 << 8))
+#define OMAP446X_CLASS 0x44600044
+#define OMAP4460_REV_ES1_0 (OMAP446X_CLASS | (0x10 << 8))
+
/*
* omap_chip bits
*
@@ -439,13 +447,15 @@ IS_OMAP_TYPE(3517, 0x3517)
#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_OMAP4430ES2_2 | \
+ CHIP_IS_OMAP4460ES1_0)
/*
* "GE" here represents "greater than or equal to" in terms of ES
@@ -468,7 +478,7 @@ void omap2_check_revision(void);
/*
* Runtime detection of OMAP3 features
*/
-extern u32 omap3_features;
+extern u32 omap_features;
#define OMAP3_HAS_L2CACHE BIT(0)
#define OMAP3_HAS_IVA BIT(1)
@@ -478,11 +488,15 @@ extern u32 omap3_features;
#define OMAP3_HAS_192MHZ_CLK BIT(5)
#define OMAP3_HAS_IO_WAKEUP BIT(6)
#define OMAP3_HAS_SDRC BIT(7)
+#define OMAP4_HAS_MPU_1GHZ BIT(8)
+#define OMAP4_HAS_MPU_1_2GHZ BIT(9)
+#define OMAP4_HAS_MPU_1_5GHZ BIT(10)
+
#define OMAP3_HAS_FEATURE(feat,flag) \
static inline unsigned int omap3_has_ ##feat(void) \
{ \
- return (omap3_features & OMAP3_HAS_ ##flag); \
+ return omap_features & OMAP3_HAS_ ##flag; \
} \
OMAP3_HAS_FEATURE(l2cache, L2CACHE)
@@ -494,4 +508,19 @@ OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
OMAP3_HAS_FEATURE(sdrc, SDRC)
+/*
+ * Runtime detection of OMAP4 features
+ */
+extern u32 omap_features;
+
+#define OMAP4_HAS_FEATURE(feat, flag) \
+static inline unsigned int omap4_has_ ##feat(void) \
+{ \
+ return omap_features & OMAP4_HAS_ ##flag; \
+} \
+
+OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
+OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
+OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
+
#endif
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index d6c70d2f4030..eb5d16c60cd9 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -32,6 +32,10 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
#ifndef __ASM_ARCH_DMTIMER_H
#define __ASM_ARCH_DMTIMER_H
@@ -56,12 +60,8 @@
*/
#define OMAP_TIMER_IP_VERSION_1 0x1
struct omap_dm_timer;
-extern struct omap_dm_timer *gptimer_wakeup;
-extern struct sys_timer omap_timer;
struct clk;
-int omap_dm_timer_init(void);
-
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);
@@ -93,5 +93,248 @@ void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value
int omap_dm_timers_active(void);
+/*
+ * Do not use the defines below, they are not needed. They should be only
+ * 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
+#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
+#define _OMAP_TIMER_CTRL_OFFSET 0x24
+#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
+#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
+#define OMAP_TIMER_CTRL_PT (1 << 12)
+#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
+#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
+#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
+#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
+#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
+#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
+#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* prescaler value shift */
+#define OMAP_TIMER_CTRL_POSTED (1 << 2)
+#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
+#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
+#define _OMAP_TIMER_COUNTER_OFFSET 0x28
+#define _OMAP_TIMER_LOAD_OFFSET 0x2c
+#define _OMAP_TIMER_TRIGGER_OFFSET 0x30
+#define _OMAP_TIMER_WRITE_PEND_OFFSET 0x34
+#define WP_NONE 0 /* no write pending bit */
+#define WP_TCLR (1 << 0)
+#define WP_TCRR (1 << 1)
+#define WP_TLDR (1 << 2)
+#define WP_TTGR (1 << 3)
+#define WP_TMAR (1 << 4)
+#define WP_TPIR (1 << 5)
+#define WP_TNIR (1 << 6)
+#define WP_TCVR (1 << 7)
+#define WP_TOCR (1 << 8)
+#define WP_TOWR (1 << 9)
+#define _OMAP_TIMER_MATCH_OFFSET 0x38
+#define _OMAP_TIMER_CAPTURE_OFFSET 0x3c
+#define _OMAP_TIMER_IF_CTRL_OFFSET 0x40
+#define _OMAP_TIMER_CAPTURE2_OFFSET 0x44 /* TCAR2, 34xx only */
+#define _OMAP_TIMER_TICK_POS_OFFSET 0x48 /* TPIR, 34xx only */
+#define _OMAP_TIMER_TICK_NEG_OFFSET 0x4c /* TNIR, 34xx only */
+#define _OMAP_TIMER_TICK_COUNT_OFFSET 0x50 /* TCVR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */
+
+/* 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))
+
+#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \
+ | (WP_TCLR << WPSHIFT))
+
+#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \
+ | (WP_TCRR << WPSHIFT))
+
+#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \
+ | (WP_TLDR << WPSHIFT))
+
+#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \
+ | (WP_TTGR << WPSHIFT))
+
+#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \
+ | (WP_TMAR << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \
+ | (WP_TPIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \
+ | (WP_TNIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \
+ | (WP_TCVR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_SET_REG \
+ (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
+ (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
+
+struct omap_dm_timer {
+ unsigned long phys_base;
+ int irq;
+#ifdef CONFIG_ARCH_OMAP2PLUS
+ struct clk *iclk, *fclk;
+#endif
+ void __iomem *io_base;
+ unsigned long rate;
+ unsigned reserved:1;
+ unsigned enabled:1;
+ unsigned posted:1;
+};
+
+extern u32 sys_timer_reserved;
+void omap_dm_timer_prepare(struct omap_dm_timer *timer);
+
+static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
+ int posted)
+{
+ if (posted)
+ while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+ & (reg >> WPSHIFT))
+ cpu_relax();
+
+ return __raw_readl(base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
+ int posted)
+{
+ if (posted)
+ while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+ & (reg >> WPSHIFT))
+ cpu_relax();
+
+ __raw_writel(val, base + (reg & 0xff));
+}
+
+/* Assumes the source clock has been set by caller */
+static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
+ int wakeup)
+{
+ u32 l;
+
+ l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
+ l |= 0x02 << 3; /* Set to smart-idle mode */
+ l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
+
+ if (autoidle)
+ l |= 0x1 << 0;
+
+ if (wakeup)
+ l |= 1 << 2;
+
+ __omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
+
+ /* Match hardware reset default of posted mode */
+ __omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
+ OMAP_TIMER_CTRL_POSTED, 0);
+}
+
+static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
+ struct clk *parent)
+{
+ int ret;
+
+ clk_disable(timer_fck);
+ ret = clk_set_parent(timer_fck, parent);
+ clk_enable(timer_fck);
+
+ /*
+ * When the functional clock disappears, too quick writes seem
+ * to cause an abort. XXX Is this still necessary?
+ */
+ __delay(300000);
+
+ return ret;
+}
+
+static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
+ unsigned long rate)
+{
+ u32 l;
+
+ l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+ if (l & OMAP_TIMER_CTRL_ST) {
+ l &= ~0x1;
+ __omap_dm_timer_write(base, 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);
+ /*
+ * Wait for functional clock period x 3.5 to make sure that
+ * timer is stopped
+ */
+ udelay(3500000 / rate + 1);
+#endif
+ }
+
+ /* Ack possibly pending interrupt */
+ __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
+ OMAP_TIMER_INT_OVERFLOW, 0);
+}
+
+static inline void __omap_dm_timer_load_start(void __iomem *base, 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);
+}
+
+static inline void __omap_dm_timer_int_enable(void __iomem *base,
+ 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);
+}
+
+static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
+ int posted)
+{
+ return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
+}
+
+static inline void __omap_dm_timer_write_status(void __iomem *base,
+ unsigned int value)
+{
+ __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
+}
#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 ec97e00cb581..91e8de3db085 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -174,12 +174,32 @@ struct omap_gpio_dev_attr {
bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
};
+struct omap_gpio_reg_offs {
+ u16 revision;
+ u16 direction;
+ u16 datain;
+ u16 dataout;
+ u16 set_dataout;
+ u16 clr_dataout;
+ u16 irqstatus;
+ u16 irqstatus2;
+ u16 irqenable;
+ u16 set_irqenable;
+ u16 clr_irqenable;
+ u16 debounce;
+ u16 debounce_en;
+
+ bool irqenable_inv;
+};
+
struct omap_gpio_platform_data {
u16 virtual_irq_start;
int bank_type;
int bank_width; /* GPIO bank width */
int bank_stride; /* Only needed for omap1 MPUIO */
bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
+
+ struct omap_gpio_reg_offs *regs;
};
/* TODO: Analyze removing gpio_bank_count usage from driver code */
diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
index 878d632c4092..7c22b9e10dc3 100644
--- a/arch/arm/plat-omap/include/plat/i2c.h
+++ b/arch/arm/plat-omap/include/plat/i2c.h
@@ -22,6 +22,7 @@
#define __ASM__ARCH_OMAP_I2C_H
#include <linux/i2c.h>
+#include <linux/i2c-omap.h>
#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
@@ -46,10 +47,13 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
*/
struct omap_i2c_dev_attr {
u8 fifo_depth;
- u8 flags;
+ u32 flags;
};
void __init omap1_i2c_mux_pins(int bus_id);
void __init omap2_i2c_mux_pins(int bus_id);
+struct omap_hwmod;
+int omap_i2c_reset(struct omap_hwmod *oh);
+
#endif /* __ASM__ARCH_OMAP_I2C_H */
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 5a25098ea7ea..926d25c780f3 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -407,11 +407,19 @@
#endif
#define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS)
+#define TWL6040_CODEC_IRQ_BASE TWL6030_IRQ_END
+#ifdef CONFIG_TWL6040_CODEC
+#define TWL6040_CODEC_NR_IRQS 6
+#else
+#define TWL6040_CODEC_NR_IRQS 0
+#endif
+#define TWL6040_CODEC_IRQ_END (TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS)
+
/* Total number of interrupts depends on the enabled blocks above */
-#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END)
+#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END)
#define TWL_IRQ_END TWL4030_GPIO_IRQ_END
#else
-#define TWL_IRQ_END TWL6030_IRQ_END
+#define TWL_IRQ_END TWL6040_CODEC_IRQ_END
#endif
/* GPMC related */
@@ -428,7 +436,11 @@
#define INTCPS_NR_IRQS 96
#ifndef __ASSEMBLY__
-extern void omap_init_irq(void);
+extern void __iomem *omap_irq_base;
+void omap1_init_irq(void);
+void omap2_init_irq(void);
+void omap3_init_irq(void);
+void ti816x_init_irq(void);
extern int omap_irq_pending(void);
void omap_intc_save_context(void);
void omap_intc_restore_context(void);
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index f8f690ab2997..9882c657b2d4 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -24,7 +24,6 @@
#ifndef __ASM_ARCH_OMAP_MCBSP_H
#define __ASM_ARCH_OMAP_MCBSP_H
-#include <linux/completion.h>
#include <linux/spinlock.h>
#include <mach/hardware.h>
@@ -34,7 +33,7 @@
#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \
static struct platform_device omap_mcbsp##port_nr = { \
.name = "omap-mcbsp-dai", \
- .id = OMAP_MCBSP##port_nr, \
+ .id = port_nr - 1, \
}
#define MCBSP_CONFIG_TYPE2 0x2
@@ -333,18 +332,6 @@ struct omap_mcbsp_reg_cfg {
};
typedef enum {
- OMAP_MCBSP1 = 0,
- OMAP_MCBSP2,
- OMAP_MCBSP3,
- OMAP_MCBSP4,
- OMAP_MCBSP5
-} omap_mcbsp_id;
-
-typedef int __bitwise omap_mcbsp_io_type_t;
-#define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
-#define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
-
-typedef enum {
OMAP_MCBSP_WORD_8 = 0,
OMAP_MCBSP_WORD_12,
OMAP_MCBSP_WORD_16,
@@ -353,38 +340,6 @@ typedef enum {
OMAP_MCBSP_WORD_32,
} omap_mcbsp_word_length;
-typedef enum {
- OMAP_MCBSP_CLK_RISING = 0,
- OMAP_MCBSP_CLK_FALLING,
-} omap_mcbsp_clk_polarity;
-
-typedef enum {
- OMAP_MCBSP_FS_ACTIVE_HIGH = 0,
- OMAP_MCBSP_FS_ACTIVE_LOW,
-} omap_mcbsp_fs_polarity;
-
-typedef enum {
- OMAP_MCBSP_CLK_STP_MODE_NO_DELAY = 0,
- OMAP_MCBSP_CLK_STP_MODE_DELAY,
-} omap_mcbsp_clk_stp_mode;
-
-
-/******* SPI specific mode **********/
-typedef enum {
- OMAP_MCBSP_SPI_MASTER = 0,
- OMAP_MCBSP_SPI_SLAVE,
-} omap_mcbsp_spi_mode;
-
-struct omap_mcbsp_spi_cfg {
- omap_mcbsp_spi_mode spi_mode;
- omap_mcbsp_clk_polarity rx_clock_polarity;
- omap_mcbsp_clk_polarity tx_clock_polarity;
- omap_mcbsp_fs_polarity fsx_polarity;
- u8 clk_div;
- omap_mcbsp_clk_stp_mode clk_stp_mode;
- omap_mcbsp_word_length word_length;
-};
-
/* Platform specific configuration */
struct omap_mcbsp_ops {
void (*request)(unsigned int);
@@ -422,25 +377,13 @@ struct omap_mcbsp {
void __iomem *io_base;
u8 id;
u8 free;
- omap_mcbsp_word_length rx_word_length;
- omap_mcbsp_word_length tx_word_length;
- omap_mcbsp_io_type_t io_type; /* IRQ or poll */
- /* IRQ based TX/RX */
int rx_irq;
int tx_irq;
/* DMA stuff */
u8 dma_rx_sync;
- short dma_rx_lch;
u8 dma_tx_sync;
- short dma_tx_lch;
-
- /* Completion queues */
- struct completion tx_irq_completion;
- struct completion rx_irq_completion;
- struct completion tx_dma_completion;
- struct completion rx_dma_completion;
/* Protect the field .free, while checking if the mcbsp is in use */
spinlock_t lock;
@@ -499,24 +442,9 @@ 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);
void omap_mcbsp_stop(unsigned int id, int tx, int rx);
-void omap_mcbsp_xmit_word(unsigned int id, u32 word);
-u32 omap_mcbsp_recv_word(unsigned int id);
-
-int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
-int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
-int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
-int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
-
/* McBSP functional clock source changing function */
extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
-/* SPI specific API */
-void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
-
-/* Polled read/write functions */
-int omap_mcbsp_pollread(unsigned int id, u16 * buf);
-int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
-int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
/* McBSP signal muxing API */
void omap2_mcbsp1_mux_clkr_src(u8 mux);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index d86d1ecf0068..67fc5060183e 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -19,15 +19,11 @@ enum nand_io {
};
struct omap_nand_platform_data {
- unsigned int options;
int cs;
- int gpio_irq;
struct mtd_partition *parts;
struct gpmc_timings *gpmc_t;
int nr_parts;
- int (*nand_setup)(void);
- int (*dev_ready)(struct omap_nand_platform_data *);
- int dma_channel;
+ bool dev_ready;
int gpmc_irq;
enum nand_io xfer_type;
unsigned long phys_base;
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index c0a752053039..0840df813f4f 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -40,11 +40,7 @@
* framework starts. The "_if_" is to avoid name collisions with the
* PM idle-loop code.
*/
-#ifdef CONFIG_OMAP_PM_NONE
-#define omap_pm_if_early_init() 0
-#else
int __init omap_pm_if_early_init(void);
-#endif
/**
* omap_pm_if_init - OMAP PM init code called after clock fw init
@@ -52,11 +48,7 @@ int __init omap_pm_if_early_init(void);
* The main initialization code. OPP tables are passed in here. The
* "_if_" is to avoid name collisions with the PM idle-loop code.
*/
-#ifdef CONFIG_OMAP_PM_NONE
-#define omap_pm_if_init() 0
-#else
int __init omap_pm_if_init(void);
-#endif
/**
* omap_pm_if_exit - OMAP PM exit code
diff --git a/arch/arm/plat-omap/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h
index 2b1d9bc1eebb..9fe6c8783236 100644
--- a/arch/arm/plat-omap/include/plat/omap4-keypad.h
+++ b/arch/arm/plat-omap/include/plat/omap4-keypad.h
@@ -10,5 +10,6 @@ struct omap4_keypad_platform_data {
u8 cols;
};
-extern int omap4_keyboard_init(struct omap4_keypad_platform_data *);
+extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
+ struct omap_board_data *);
#endif
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349ff9fd8..ee405b36df4b 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -44,6 +44,10 @@ extern struct device omap_device_parent;
#define OMAP_DEVICE_STATE_IDLE 2
#define OMAP_DEVICE_STATE_SHUTDOWN 3
+/* omap_device.flags values */
+#define OMAP_DEVICE_SUSPENDED BIT(0)
+#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1)
+
/**
* struct omap_device - omap_device wrapper for platform_devices
* @pdev: platform_device
@@ -73,6 +77,7 @@ struct omap_device {
s8 pm_lat_level;
u8 hwmods_cnt;
u8 _state;
+ u8 flags;
};
/* Device driver interface (call via platform_data fn ptrs) */
@@ -117,6 +122,10 @@ 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
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1adea9c62984..0e329ca88a70 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -2,6 +2,7 @@
* omap_hwmod macros, structures
*
* Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
* Paul Walmsley
*
* Created in collaboration with (alphabetical order): Benoît Cousson,
@@ -77,9 +78,13 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
#define HWMOD_IDLEMODE_FORCE (1 << 0)
#define HWMOD_IDLEMODE_NO (1 << 1)
#define HWMOD_IDLEMODE_SMART (1 << 2)
-/* Slave idle mode flag only */
#define HWMOD_IDLEMODE_SMART_WKUP (1 << 3)
+/* modulemode control type (SW or HW) */
+#define MODULEMODE_HWCTRL 1
+#define MODULEMODE_SWCTRL 2
+
+
/**
* struct omap_hwmod_mux_info - hwmod specific mux configuration
* @pads: array of omap_device_pad entries
@@ -98,7 +103,7 @@ struct omap_hwmod_mux_info {
/**
* struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
* @name: name of the IRQ channel (module local name)
- * @irq_ch: IRQ channel ID
+ * @irq: IRQ channel ID (should be non-negative except -1 = terminator)
*
* @name should be something short, e.g., "tx" or "rx". It is for use
* by platform_get_resource_byname(). It is defined locally to the
@@ -106,13 +111,13 @@ struct omap_hwmod_mux_info {
*/
struct omap_hwmod_irq_info {
const char *name;
- u16 irq;
+ s16 irq;
};
/**
* struct omap_hwmod_dma_info - DMA channels used by the hwmod
* @name: name of the DMA channel (module local name)
- * @dma_req: DMA request ID
+ * @dma_req: DMA request ID (should be non-negative except -1 = terminator)
*
* @name should be something short, e.g., "tx" or "rx". It is for use
* by platform_get_resource_byname(). It is defined locally to the
@@ -120,7 +125,7 @@ struct omap_hwmod_irq_info {
*/
struct omap_hwmod_dma_info {
const char *name;
- u16 dma_req;
+ s16 dma_req;
};
/**
@@ -220,7 +225,6 @@ struct omap_hwmod_addr_space {
* @clk: interface clock: OMAP clock name
* @_clk: pointer to the interface struct clk (filled in at runtime)
* @fw: interface firewall data
- * @addr_cnt: ARRAY_SIZE(@addr)
* @width: OCP data width
* @user: initiators using this interface (see OCP_USER_* macros above)
* @flags: OCP interface flags (see OCPIF_* macros above)
@@ -239,7 +243,6 @@ struct omap_hwmod_ocp_if {
union {
struct omap_hwmod_omap2_firewall omap2;
} fw;
- u8 addr_cnt;
u8 width;
u8 user;
u8 flags;
@@ -258,6 +261,7 @@ struct omap_hwmod_ocp_if {
#define MSTANDBY_FORCE (HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT)
#define MSTANDBY_NO (HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT)
#define MSTANDBY_SMART (HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT)
+#define MSTANDBY_SMART_WKUP (HWMOD_IDLEMODE_SMART_WKUP << MASTER_STANDBY_SHIFT)
/* omap_hwmod_sysconfig.sysc_flags capability flags */
#define SYSC_HAS_AUTOIDLE (1 << 0)
@@ -362,9 +366,11 @@ struct omap_hwmod_omap2_prcm {
* @submodule_wkdep_bit: bit shift of the WKDEP range
*/
struct omap_hwmod_omap4_prcm {
- void __iomem *clkctrl_reg;
- void __iomem *rstctrl_reg;
+ u16 clkctrl_offs;
+ u16 rstctrl_offs;
+ u16 context_offs;
u8 submodule_wkdep_bit;
+ u8 modulemode;
};
@@ -468,8 +474,8 @@ struct omap_hwmod_class {
* @name: name of the hwmod
* @class: struct omap_hwmod_class * to the class of this hwmod
* @od: struct omap_device currently associated with this hwmod (internal use)
- * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
- * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
+ * @mpu_irqs: ptr to an array of MPU IRQs
+ * @sdma_reqs: ptr to an array of System DMA request IDs
* @prcm: PRCM data pertaining to this hwmod
* @main_clk: main clock: OMAP clock name
* @_clk: pointer to the main struct clk (filled in at runtime)
@@ -482,8 +488,6 @@ struct omap_hwmod_class {
* @_sysc_cache: internal-use hwmod flags
* @_mpu_rt_va: cached register target start address (internal use)
* @_mpu_port_index: cached MPU register target slave ID (internal use)
- * @mpu_irqs_cnt: number of @mpu_irqs
- * @sdma_reqs_cnt: number of @sdma_reqs
* @opt_clks_cnt: number of @opt_clks
* @master_cnt: number of @master entries
* @slaves_cnt: number of @slave entries
@@ -519,6 +523,8 @@ struct omap_hwmod {
const char *main_clk;
struct clk *_clk;
struct omap_hwmod_opt_clk *opt_clks;
+ char *clkdm_name;
+ struct clockdomain *clkdm;
char *vdd_name;
struct voltagedomain *voltdm;
struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
@@ -531,8 +537,6 @@ struct omap_hwmod {
u16 flags;
u8 _mpu_port_index;
u8 response_lat;
- u8 mpu_irqs_cnt;
- u8 sdma_reqs_cnt;
u8 rst_lines_cnt;
u8 opt_clks_cnt;
u8 masters_cnt;
@@ -572,6 +576,7 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
+int omap_hwmod_softreset(struct omap_hwmod *oh);
int omap_hwmod_count_resources(struct omap_hwmod *oh);
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index ac4b60d9aa29..a067484cc4a2 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -148,6 +148,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
/* omap3 based boards using UART3 */
DEBUG_LL_OMAP3(3, cm_t35);
DEBUG_LL_OMAP3(3, cm_t3517);
+ DEBUG_LL_OMAP3(3, cm_t3730);
DEBUG_LL_OMAP3(3, craneboard);
DEBUG_LL_OMAP3(3, devkit8000);
DEBUG_LL_OMAP3(3, igep0020);
diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index 83a37c54342f..c60737c49a32 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -72,7 +72,7 @@ static size_t sgtable_len(const struct sg_table *sgt)
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes;
- bytes = sg_dma_len(sg);
+ bytes = sg->length;
if (!iopgsz_ok(bytes)) {
pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
@@ -198,7 +198,7 @@ static void *vmap_sg(const struct sg_table *sgt)
int err;
pa = sg_phys(sg);
- bytes = sg_dma_len(sg);
+ bytes = sg->length;
BUG_ON(bytes != PAGE_SIZE);
@@ -476,7 +476,7 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
struct iotlb_entry e;
pa = sg_phys(sg);
- bytes = sg_dma_len(sg);
+ bytes = sg->length;
flags &= ~IOVMF_PGSZ_MASK;
pgsz = bytes_to_iopgsz(bytes);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 5587acf0eb2c..6c62af108710 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -16,8 +16,6 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <linux/wait.h>
-#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -25,7 +23,6 @@
#include <linux/io.h>
#include <linux/slab.h>
-#include <plat/dma.h>
#include <plat/mcbsp.h>
#include <plat/omap_device.h>
#include <linux/pm_runtime.h>
@@ -136,8 +133,6 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
irqst_spcr2);
/* Writing zero to XSYNC_ERR clears the IRQ */
MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2));
- } else {
- complete(&mcbsp_tx->tx_irq_completion);
}
return IRQ_HANDLED;
@@ -156,41 +151,11 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
irqst_spcr1);
/* Writing zero to RSYNC_ERR clears the IRQ */
MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
- } else {
- complete(&mcbsp_rx->rx_irq_completion);
}
return IRQ_HANDLED;
}
-static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
-{
- struct omap_mcbsp *mcbsp_dma_tx = data;
-
- dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n",
- MCBSP_READ(mcbsp_dma_tx, SPCR2));
-
- /* We can free the channels */
- omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
- mcbsp_dma_tx->dma_tx_lch = -1;
-
- complete(&mcbsp_dma_tx->tx_dma_completion);
-}
-
-static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
-{
- struct omap_mcbsp *mcbsp_dma_rx = data;
-
- dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n",
- MCBSP_READ(mcbsp_dma_rx, SPCR2));
-
- /* We can free the channels */
- omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
- mcbsp_dma_rx->dma_rx_lch = -1;
-
- complete(&mcbsp_dma_rx->rx_dma_completion);
-}
-
/*
* omap_mcbsp_config simply write a config to the
* appropriate McBSP.
@@ -758,37 +723,6 @@ static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
#endif
-/*
- * We can choose between IRQ based or polled IO.
- * This needs to be called before omap_mcbsp_request().
- */
-int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
-{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- spin_lock(&mcbsp->lock);
-
- if (!mcbsp->free) {
- dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
- mcbsp->id);
- spin_unlock(&mcbsp->lock);
- return -EINVAL;
- }
-
- mcbsp->io_type = io_type;
-
- spin_unlock(&mcbsp->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_set_io_type);
-
int omap_mcbsp_request(unsigned int id)
{
struct omap_mcbsp *mcbsp;
@@ -833,29 +767,24 @@ int omap_mcbsp_request(unsigned int id)
MCBSP_WRITE(mcbsp, SPCR1, 0);
MCBSP_WRITE(mcbsp, SPCR2, 0);
- if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
- /* We need to get IRQs here */
- init_completion(&mcbsp->tx_irq_completion);
- err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
- 0, "McBSP", (void *)mcbsp);
+ err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
+ 0, "McBSP", (void *)mcbsp);
+ if (err != 0) {
+ dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
+ "for McBSP%d\n", mcbsp->tx_irq,
+ mcbsp->id);
+ goto err_clk_disable;
+ }
+
+ if (mcbsp->rx_irq) {
+ err = request_irq(mcbsp->rx_irq,
+ omap_mcbsp_rx_irq_handler,
+ 0, "McBSP", (void *)mcbsp);
if (err != 0) {
- dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
- "for McBSP%d\n", mcbsp->tx_irq,
+ dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
+ "for McBSP%d\n", mcbsp->rx_irq,
mcbsp->id);
- goto err_clk_disable;
- }
-
- if (mcbsp->rx_irq) {
- init_completion(&mcbsp->rx_irq_completion);
- err = request_irq(mcbsp->rx_irq,
- omap_mcbsp_rx_irq_handler,
- 0, "McBSP", (void *)mcbsp);
- if (err != 0) {
- dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
- "for McBSP%d\n", mcbsp->rx_irq,
- mcbsp->id);
- goto err_free_irq;
- }
+ goto err_free_irq;
}
}
@@ -901,12 +830,9 @@ void omap_mcbsp_free(unsigned int id)
pm_runtime_put_sync(mcbsp->dev);
- if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
- /* Free IRQs */
- if (mcbsp->rx_irq)
- free_irq(mcbsp->rx_irq, (void *)mcbsp);
- free_irq(mcbsp->tx_irq, (void *)mcbsp);
- }
+ if (mcbsp->rx_irq)
+ free_irq(mcbsp->rx_irq, (void *)mcbsp);
+ free_irq(mcbsp->tx_irq, (void *)mcbsp);
reg_cache = mcbsp->reg_cache;
@@ -943,9 +869,6 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
if (cpu_is_omap34xx())
omap_st_start(mcbsp);
- mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
- mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
-
/* Only enable SRG, if McBSP is master */
w = MCBSP_READ_CACHE(mcbsp, PCR0);
if (w & (FSXM | FSRM | CLKXM | CLKRM))
@@ -1043,484 +966,32 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
}
EXPORT_SYMBOL(omap_mcbsp_stop);
-/* polled mcbsp i/o operations */
-int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
-{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
-
- MCBSP_WRITE(mcbsp, DXR1, buf);
- /* if frame sync error - clear the error */
- if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) {
- /* clear error */
- MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2));
- /* resend */
- return -1;
- } else {
- /* wait for transmit confirmation */
- int attemps = 0;
- while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
- if (attemps++ > 1000) {
- MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ_CACHE(mcbsp, SPCR2) &
- (~XRST));
- udelay(10);
- MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ_CACHE(mcbsp, SPCR2) |
- (XRST));
- udelay(10);
- dev_err(mcbsp->dev, "Could not write to"
- " McBSP%d Register\n", mcbsp->id);
- return -2;
- }
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_pollwrite);
-
-int omap_mcbsp_pollread(unsigned int id, u16 *buf)
-{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- /* if frame sync error - clear the error */
- if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) {
- /* clear error */
- MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1));
- /* resend */
- return -1;
- } else {
- /* wait for receive confirmation */
- int attemps = 0;
- while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) {
- if (attemps++ > 1000) {
- MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ_CACHE(mcbsp, SPCR1) &
- (~RRST));
- udelay(10);
- MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ_CACHE(mcbsp, SPCR1) |
- (RRST));
- udelay(10);
- dev_err(mcbsp->dev, "Could not read from"
- " McBSP%d Register\n", mcbsp->id);
- return -2;
- }
- }
- }
- *buf = MCBSP_READ(mcbsp, DRR1);
-
- return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_pollread);
-
-/*
- * IRQ based word transmission.
- */
-void omap_mcbsp_xmit_word(unsigned int id, u32 word)
-{
- struct omap_mcbsp *mcbsp;
- omap_mcbsp_word_length word_length;
-
- 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);
- word_length = mcbsp->tx_word_length;
-
- wait_for_completion(&mcbsp->tx_irq_completion);
-
- if (word_length > OMAP_MCBSP_WORD_16)
- MCBSP_WRITE(mcbsp, DXR2, word >> 16);
- MCBSP_WRITE(mcbsp, DXR1, word & 0xffff);
-}
-EXPORT_SYMBOL(omap_mcbsp_xmit_word);
-
-u32 omap_mcbsp_recv_word(unsigned int id)
-{
- struct omap_mcbsp *mcbsp;
- u16 word_lsb, word_msb = 0;
- omap_mcbsp_word_length word_length;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- word_length = mcbsp->rx_word_length;
-
- wait_for_completion(&mcbsp->rx_irq_completion);
-
- if (word_length > OMAP_MCBSP_WORD_16)
- word_msb = MCBSP_READ(mcbsp, DRR2);
- word_lsb = MCBSP_READ(mcbsp, DRR1);
-
- return (word_lsb | (word_msb << 16));
-}
-EXPORT_SYMBOL(omap_mcbsp_recv_word);
-
-int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
-{
- struct omap_mcbsp *mcbsp;
- omap_mcbsp_word_length tx_word_length;
- omap_mcbsp_word_length rx_word_length;
- u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
- tx_word_length = mcbsp->tx_word_length;
- rx_word_length = mcbsp->rx_word_length;
-
- if (tx_word_length != rx_word_length)
- return -EINVAL;
-
- /* First we wait for the transmitter to be ready */
- spcr2 = MCBSP_READ(mcbsp, SPCR2);
- while (!(spcr2 & XRDY)) {
- spcr2 = MCBSP_READ(mcbsp, SPCR2);
- if (attempts++ > 1000) {
- /* We must reset the transmitter */
- MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
- udelay(10);
- MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
- udelay(10);
- dev_err(mcbsp->dev, "McBSP%d transmitter not "
- "ready\n", mcbsp->id);
- return -EAGAIN;
- }
- }
-
- /* Now we can push the data */
- if (tx_word_length > OMAP_MCBSP_WORD_16)
- MCBSP_WRITE(mcbsp, DXR2, word >> 16);
- MCBSP_WRITE(mcbsp, DXR1, word & 0xffff);
-
- /* We wait for the receiver to be ready */
- spcr1 = MCBSP_READ(mcbsp, SPCR1);
- while (!(spcr1 & RRDY)) {
- spcr1 = MCBSP_READ(mcbsp, SPCR1);
- if (attempts++ > 1000) {
- /* We must reset the receiver */
- MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
- udelay(10);
- MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
- udelay(10);
- dev_err(mcbsp->dev, "McBSP%d receiver not "
- "ready\n", mcbsp->id);
- return -EAGAIN;
- }
- }
-
- /* Receiver is ready, let's read the dummy data */
- if (rx_word_length > OMAP_MCBSP_WORD_16)
- word_msb = MCBSP_READ(mcbsp, DRR2);
- word_lsb = MCBSP_READ(mcbsp, DRR1);
-
- return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
-
-int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
-{
- struct omap_mcbsp *mcbsp;
- u32 clock_word = 0;
- omap_mcbsp_word_length tx_word_length;
- omap_mcbsp_word_length rx_word_length;
- u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
-
- tx_word_length = mcbsp->tx_word_length;
- rx_word_length = mcbsp->rx_word_length;
-
- if (tx_word_length != rx_word_length)
- return -EINVAL;
-
- /* First we wait for the transmitter to be ready */
- spcr2 = MCBSP_READ(mcbsp, SPCR2);
- while (!(spcr2 & XRDY)) {
- spcr2 = MCBSP_READ(mcbsp, SPCR2);
- if (attempts++ > 1000) {
- /* We must reset the transmitter */
- MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
- udelay(10);
- MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
- udelay(10);
- dev_err(mcbsp->dev, "McBSP%d transmitter not "
- "ready\n", mcbsp->id);
- return -EAGAIN;
- }
- }
-
- /* We first need to enable the bus clock */
- if (tx_word_length > OMAP_MCBSP_WORD_16)
- MCBSP_WRITE(mcbsp, DXR2, clock_word >> 16);
- MCBSP_WRITE(mcbsp, DXR1, clock_word & 0xffff);
-
- /* We wait for the receiver to be ready */
- spcr1 = MCBSP_READ(mcbsp, SPCR1);
- while (!(spcr1 & RRDY)) {
- spcr1 = MCBSP_READ(mcbsp, SPCR1);
- if (attempts++ > 1000) {
- /* We must reset the receiver */
- MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
- udelay(10);
- MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
- udelay(10);
- dev_err(mcbsp->dev, "McBSP%d receiver not "
- "ready\n", mcbsp->id);
- return -EAGAIN;
- }
- }
-
- /* Receiver is ready, there is something for us */
- if (rx_word_length > OMAP_MCBSP_WORD_16)
- word_msb = MCBSP_READ(mcbsp, DRR2);
- word_lsb = MCBSP_READ(mcbsp, DRR1);
-
- word[0] = (word_lsb | (word_msb << 16));
-
- return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
-
/*
- * Simple DMA based buffer rx/tx routines.
- * Nothing fancy, just a single buffer tx/rx through DMA.
- * The DMA resources are released once the transfer is done.
- * For anything fancier, you should use your own customized DMA
- * routines and callbacks.
+ * The following functions are only required on an OMAP1-only build.
+ * mach-omap2/mcbsp.c contains the real functions
*/
-int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
- unsigned int length)
+#ifndef CONFIG_ARCH_OMAP2PLUS
+int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
{
- struct omap_mcbsp *mcbsp;
- int dma_tx_ch;
- int src_port = 0;
- int dest_port = 0;
- int sync_dev = 0;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX",
- omap_mcbsp_tx_dma_callback,
- mcbsp,
- &dma_tx_ch)) {
- dev_err(mcbsp->dev, " Unable to request DMA channel for "
- "McBSP%d TX. Trying IRQ based TX\n",
- mcbsp->id);
- return -EAGAIN;
- }
- mcbsp->dma_tx_lch = dma_tx_ch;
-
- dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id,
- dma_tx_ch);
-
- init_completion(&mcbsp->tx_dma_completion);
-
- if (cpu_class_is_omap1()) {
- src_port = OMAP_DMA_PORT_TIPB;
- dest_port = OMAP_DMA_PORT_EMIFF;
- }
- if (cpu_class_is_omap2())
- sync_dev = mcbsp->dma_tx_sync;
-
- omap_set_dma_transfer_params(mcbsp->dma_tx_lch,
- OMAP_DMA_DATA_TYPE_S16,
- length >> 1, 1,
- OMAP_DMA_SYNC_ELEMENT,
- sync_dev, 0);
-
- omap_set_dma_dest_params(mcbsp->dma_tx_lch,
- src_port,
- OMAP_DMA_AMODE_CONSTANT,
- mcbsp->phys_base + OMAP_MCBSP_REG_DXR1,
- 0, 0);
-
- omap_set_dma_src_params(mcbsp->dma_tx_lch,
- dest_port,
- OMAP_DMA_AMODE_POST_INC,
- buffer,
- 0, 0);
-
- omap_start_dma(mcbsp->dma_tx_lch);
- wait_for_completion(&mcbsp->tx_dma_completion);
-
- return 0;
+ WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+ __func__);
+ return -EINVAL;
}
-EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
-int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
- unsigned int length)
+void omap2_mcbsp1_mux_clkr_src(u8 mux)
{
- struct omap_mcbsp *mcbsp;
- int dma_rx_ch;
- int src_port = 0;
- int dest_port = 0;
- int sync_dev = 0;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX",
- omap_mcbsp_rx_dma_callback,
- mcbsp,
- &dma_rx_ch)) {
- dev_err(mcbsp->dev, "Unable to request DMA channel for "
- "McBSP%d RX. Trying IRQ based RX\n",
- mcbsp->id);
- return -EAGAIN;
- }
- mcbsp->dma_rx_lch = dma_rx_ch;
-
- dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id,
- dma_rx_ch);
-
- init_completion(&mcbsp->rx_dma_completion);
-
- if (cpu_class_is_omap1()) {
- src_port = OMAP_DMA_PORT_TIPB;
- dest_port = OMAP_DMA_PORT_EMIFF;
- }
- if (cpu_class_is_omap2())
- sync_dev = mcbsp->dma_rx_sync;
-
- omap_set_dma_transfer_params(mcbsp->dma_rx_lch,
- OMAP_DMA_DATA_TYPE_S16,
- length >> 1, 1,
- OMAP_DMA_SYNC_ELEMENT,
- sync_dev, 0);
-
- omap_set_dma_src_params(mcbsp->dma_rx_lch,
- src_port,
- OMAP_DMA_AMODE_CONSTANT,
- mcbsp->phys_base + OMAP_MCBSP_REG_DRR1,
- 0, 0);
-
- omap_set_dma_dest_params(mcbsp->dma_rx_lch,
- dest_port,
- OMAP_DMA_AMODE_POST_INC,
- buffer,
- 0, 0);
-
- omap_start_dma(mcbsp->dma_rx_lch);
- wait_for_completion(&mcbsp->rx_dma_completion);
-
- return 0;
+ WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+ __func__);
+ return;
}
-EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
-/*
- * SPI wrapper.
- * Since SPI setup is much simpler than the generic McBSP one,
- * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
- * Once this is done, you can call omap_mcbsp_start().
- */
-void omap_mcbsp_set_spi_mode(unsigned int id,
- const struct omap_mcbsp_spi_cfg *spi_cfg)
+void omap2_mcbsp1_mux_fsr_src(u8 mux)
{
- struct omap_mcbsp *mcbsp;
- struct omap_mcbsp_reg_cfg mcbsp_cfg;
-
- 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);
-
- memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
-
- /* SPI has only one frame */
- mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
- mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
-
- /* Clock stop mode */
- if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
- mcbsp_cfg.spcr1 |= (1 << 12);
- else
- mcbsp_cfg.spcr1 |= (3 << 11);
-
- /* Set clock parities */
- if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
- mcbsp_cfg.pcr0 |= CLKRP;
- else
- mcbsp_cfg.pcr0 &= ~CLKRP;
-
- if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
- mcbsp_cfg.pcr0 &= ~CLKXP;
- else
- mcbsp_cfg.pcr0 |= CLKXP;
-
- /* Set SCLKME to 0 and CLKSM to 1 */
- mcbsp_cfg.pcr0 &= ~SCLKME;
- mcbsp_cfg.srgr2 |= CLKSM;
-
- /* Set FSXP */
- if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
- mcbsp_cfg.pcr0 &= ~FSXP;
- else
- mcbsp_cfg.pcr0 |= FSXP;
-
- if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
- mcbsp_cfg.pcr0 |= CLKXM;
- mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div - 1);
- mcbsp_cfg.pcr0 |= FSXM;
- mcbsp_cfg.srgr2 &= ~FSGM;
- mcbsp_cfg.xcr2 |= XDATDLY(1);
- mcbsp_cfg.rcr2 |= RDATDLY(1);
- } else {
- mcbsp_cfg.pcr0 &= ~CLKXM;
- mcbsp_cfg.srgr1 |= CLKGDV(1);
- mcbsp_cfg.pcr0 &= ~FSXM;
- mcbsp_cfg.xcr2 &= ~XDATDLY(3);
- mcbsp_cfg.rcr2 &= ~RDATDLY(3);
- }
-
- mcbsp_cfg.xcr2 &= ~XPHASE;
- mcbsp_cfg.rcr2 &= ~RPHASE;
-
- omap_mcbsp_config(id, &mcbsp_cfg);
+ WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+ __func__);
+ return;
}
-EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
+#endif
#ifdef CONFIG_ARCH_OMAP3
#define max_thres(m) (mcbsp->pdata->buffer_size)
@@ -1833,8 +1304,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
spin_lock_init(&mcbsp->lock);
mcbsp->id = id + 1;
mcbsp->free = true;
- mcbsp->dma_tx_lch = -1;
- mcbsp->dma_rx_lch = -1;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
if (!res) {
@@ -1860,9 +1329,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
else
mcbsp->phys_dma_base = res->start;
- /* Default I/O is IRQ based */
- mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
-
mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 49fc0df0c21f..b6b409744954 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -236,61 +236,71 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
return 0;
}
-static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
+static void _add_clkdev(struct omap_device *od, const char *clk_alias,
+ const char *clk_name)
{
- return container_of(pdev, struct omap_device, pdev);
+ struct clk *r;
+ struct clk_lookup *l;
+
+ if (!clk_alias || !clk_name)
+ return;
+
+ pr_debug("omap_device: %s: Creating %s -> %s\n",
+ dev_name(&od->pdev.dev), clk_alias, clk_name);
+
+ 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);
+ 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);
+ return;
+ }
+
+ 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);
+ return;
+ }
+
+ clkdev_add(l);
}
/**
- * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
+ * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
+ * and main clock
* @od: struct omap_device *od
+ * @oh: struct omap_hwmod *oh
*
- * For every optional clock present per hwmod per omap_device, this function
- * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
- * if it does not exist already.
+ * For the main clock and every optional clock present per hwmod per
+ * omap_device, this function adds an entry in the clkdev table of the
+ * form <dev-id=dev_name, con-id=role> if it does not exist already.
*
* The function is called from inside omap_device_build_ss(), after
* omap_device_register.
*
* This allows drivers to get a pointer to its optional clocks based on its role
* by calling clk_get(<dev*>, <role>).
+ * In the case of the main clock, a "fck" alias is used.
*
* No return value.
*/
-static void _add_optional_clock_clkdev(struct omap_device *od,
- struct omap_hwmod *oh)
+static void _add_hwmod_clocks_clkdev(struct omap_device *od,
+ struct omap_hwmod *oh)
{
int i;
- for (i = 0; i < oh->opt_clks_cnt; i++) {
- struct omap_hwmod_opt_clk *oc;
- struct clk *r;
- struct clk_lookup *l;
+ _add_clkdev(od, "fck", oh->main_clk);
- oc = &oh->opt_clks[i];
-
- if (!oc->_clk)
- continue;
-
- r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
- if (!IS_ERR(r))
- continue; /* clkdev entry exists */
-
- r = omap_clk_get_by_name((char *)oc->clk);
- if (IS_ERR(r)) {
- pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
- dev_name(&od->pdev.dev), oc->clk);
- continue;
- }
-
- l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
- if (!l) {
- pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
- dev_name(&od->pdev.dev), oc->role);
- return;
- }
- clkdev_add(l);
- }
+ for (i = 0; i < oh->opt_clks_cnt; i++)
+ _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
}
@@ -316,7 +326,7 @@ u32 omap_device_get_context_loss_count(struct platform_device *pdev)
struct omap_device *od;
u32 ret = 0;
- od = _find_by_pdev(pdev);
+ od = to_omap_device(pdev);
if (od->hwmods_cnt)
ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
@@ -497,7 +507,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
for (i = 0; i < oh_cnt; i++) {
hwmods[i]->od = od;
- _add_optional_clock_clkdev(od, hwmods[i]);
+ _add_hwmod_clocks_clkdev(od, hwmods[i]);
}
if (ret)
@@ -537,6 +547,7 @@ int omap_early_device_register(struct omap_device *od)
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
static int _od_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -563,13 +574,55 @@ static int _od_runtime_resume(struct device *dev)
return pm_generic_runtime_resume(dev);
}
+#endif
+
+#ifdef CONFIG_SUSPEND
+static int _od_suspend_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct omap_device *od = to_omap_device(pdev);
+ int ret;
+
+ if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
+ return pm_generic_suspend_noirq(dev);
+
+ ret = pm_generic_suspend_noirq(dev);
+
+ if (!ret && !pm_runtime_status_suspended(dev)) {
+ if (pm_generic_runtime_suspend(dev) == 0) {
+ omap_device_idle(pdev);
+ od->flags |= OMAP_DEVICE_SUSPENDED;
+ }
+ }
+
+ return ret;
+}
+
+static int _od_resume_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct omap_device *od = to_omap_device(pdev);
+
+ if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
+ return pm_generic_resume_noirq(dev);
+
+ if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
+ !pm_runtime_status_suspended(dev)) {
+ od->flags &= ~OMAP_DEVICE_SUSPENDED;
+ omap_device_enable(pdev);
+ pm_generic_runtime_resume(dev);
+ }
+
+ return pm_generic_resume_noirq(dev);
+}
+#endif
-static struct dev_power_domain omap_device_power_domain = {
+static struct dev_pm_domain omap_device_pm_domain = {
.ops = {
- .runtime_suspend = _od_runtime_suspend,
- .runtime_idle = _od_runtime_idle,
- .runtime_resume = _od_runtime_resume,
+ SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
+ _od_runtime_idle)
USE_PLATFORM_PM_SLEEP_OPS
+ SET_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, _od_resume_noirq)
}
};
@@ -586,7 +639,7 @@ int omap_device_register(struct omap_device *od)
pr_debug("omap_device: %s: registering\n", od->pdev.name);
od->pdev.dev.parent = &omap_device_parent;
- od->pdev.dev.pwr_domain = &omap_device_power_domain;
+ od->pdev.dev.pm_domain = &omap_device_pm_domain;
return platform_device_register(&od->pdev);
}
@@ -611,7 +664,7 @@ int omap_device_enable(struct platform_device *pdev)
int ret;
struct omap_device *od;
- od = _find_by_pdev(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",
@@ -650,7 +703,7 @@ int omap_device_idle(struct platform_device *pdev)
int ret;
struct omap_device *od;
- od = _find_by_pdev(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",
@@ -681,7 +734,7 @@ int omap_device_shutdown(struct platform_device *pdev)
int ret, i;
struct omap_device *od;
- od = _find_by_pdev(pdev);
+ od = to_omap_device(pdev);
if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
od->_state != OMAP_DEVICE_STATE_IDLE) {
@@ -722,7 +775,7 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
int ret = -EINVAL;
struct omap_device *od;
- od = _find_by_pdev(pdev);
+ od = to_omap_device(pdev);
if (new_wakeup_lat_limit == od->dev_wakeup_lat)
return 0;
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 6af3d0b1f8d0..363c91e44efb 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -394,20 +394,15 @@ void omap3_sram_restore_context(void)
}
#endif /* CONFIG_PM */
-static int __init omap34xx_sram_init(void)
-{
- _omap3_sram_configure_core_dpll =
- omap_sram_push(omap3_sram_configure_core_dpll,
- omap3_sram_configure_core_dpll_sz);
- omap_push_sram_idle();
- return 0;
-}
-#else
+#endif /* CONFIG_ARCH_OMAP3 */
+
static inline int omap34xx_sram_init(void)
{
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+ omap3_sram_restore_context();
+#endif
return 0;
}
-#endif
int __init omap_sram_init(void)
{
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h b/arch/arm/plat-pxa/include/plat/sdhci.h
deleted file mode 100644
index 1ab332e37d7d..000000000000
--- a/arch/arm/plat-pxa/include/plat/sdhci.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
- *
- * Copyright 2010 Marvell
- * Zhangfei Gao <zhangfei.gao@marvell.com>
- *
- * PXA Platform - SDHCI platform data 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 __PLAT_PXA_SDHCI_H
-#define __PLAT_PXA_SDHCI_H
-
-/* pxa specific flag */
-/* Require clock free running */
-#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
-
-/* Board design supports 8-bit data on SD/SDIO BUS */
-#define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2)
-
-/*
- * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
- * @max_speed: the maximum speed supported
- * @quirks: quirks of specific device
- * @flags: flags for platform requirement
- */
-struct sdhci_pxa_platdata {
- unsigned int max_speed;
- unsigned int quirks;
- unsigned int flags;
-};
-
-#endif /* __PLAT_PXA_SDHCI_H */
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index d9c4096ebf45..8c5b3029b39f 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -4,7 +4,7 @@
config PLAT_S3C24XX
bool
- depends on ARCH_S3C2410 || ARCH_S3C24A0
+ depends on ARCH_S3C2410
default y
select NO_IOPORT
select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/arm/plat-s3c24xx/clock-dclk.c b/arch/arm/plat-s3c24xx/clock-dclk.c
index cf97caafe56b..f95d3268ae1f 100644
--- a/arch/arm/plat-s3c24xx/clock-dclk.c
+++ b/arch/arm/plat-s3c24xx/clock-dclk.c
@@ -169,7 +169,6 @@ static struct clk_ops dclk_ops = {
struct clk s3c24xx_dclk0 = {
.name = "dclk0",
- .id = -1,
.ctrlbit = S3C2410_DCLKCON_DCLK0EN,
.enable = s3c24xx_dclk_enable,
.ops = &dclk_ops,
@@ -177,7 +176,6 @@ struct clk s3c24xx_dclk0 = {
struct clk s3c24xx_dclk1 = {
.name = "dclk1",
- .id = -1,
.ctrlbit = S3C2410_DCLKCON_DCLK1EN,
.enable = s3c24xx_dclk_enable,
.ops = &dclk_ops,
@@ -189,12 +187,10 @@ static struct clk_ops clkout_ops = {
struct clk s3c24xx_clkout0 = {
.name = "clkout0",
- .id = -1,
.ops = &clkout_ops,
};
struct clk s3c24xx_clkout1 = {
.name = "clkout1",
- .id = -1,
.ops = &clkout_ops,
};
diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index 4a10c0f684b2..c1fc6c6fac72 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -46,7 +46,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/clock.h>
-#include <plat/s3c2400.h>
#include <plat/s3c2410.h>
#include <plat/s3c2412.h>
#include <plat/s3c2416.h>
@@ -55,7 +54,6 @@
/* table of supported CPUs */
-static const char name_s3c2400[] = "S3C2400";
static const char name_s3c2410[] = "S3C2410";
static const char name_s3c2412[] = "S3C2412";
static const char name_s3c2416[] = "S3C2416/S3C2450";
@@ -157,15 +155,6 @@ static struct cpu_table cpu_ids[] __initdata = {
.init = s3c2443_init,
.name = name_s3c2443,
},
- {
- .idcode = 0x0, /* S3C2400 doesn't have an idcode */
- .idmask = 0xffffffff,
- .map_io = s3c2400_map_io,
- .init_clocks = s3c2400_init_clocks,
- .init_uarts = s3c2400_init_uarts,
- .init = s3c2400_init,
- .name = name_s3c2400
- },
};
/* minimal IO mapping */
@@ -200,11 +189,7 @@ static unsigned long s3c24xx_read_idcode_v5(void)
static unsigned long s3c24xx_read_idcode_v4(void)
{
-#ifndef CONFIG_CPU_S3C2400
return __raw_readl(S3C2410_GSTATUS1);
-#else
- return 0UL;
-#endif
}
/* Hook for arm_pm_restart to ensure we execute the reset code
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 73667994518a..a76bf2df3333 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -150,9 +150,8 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
{
struct s3c2410fb_mach_info *npd;
- npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
+ npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
if (npd) {
- s3c_device_lcd.dev.platform_data = npd;
npd->displays = kmemdup(pd->displays,
sizeof(struct s3c2410fb_display) * npd->num_displays,
GFP_KERNEL);
@@ -188,12 +187,10 @@ struct platform_device s3c_device_ts = {
};
EXPORT_SYMBOL(s3c_device_ts);
-static struct s3c2410_ts_mach_info s3c2410ts_info;
-
void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
{
- memcpy(&s3c2410ts_info, hard_s3c2410ts_info, sizeof(struct s3c2410_ts_mach_info));
- s3c_device_ts.dev.platform_data = &s3c2410ts_info;
+ s3c_set_platdata(hard_s3c2410ts_info,
+ sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
}
/* USB Device (Gadget)*/
@@ -223,15 +220,7 @@ EXPORT_SYMBOL(s3c_device_usbgadget);
void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
{
- struct s3c2410_udc_mach_info *npd;
-
- npd = kmalloc(sizeof(*npd), GFP_KERNEL);
- if (npd) {
- memcpy(npd, pd, sizeof(*npd));
- s3c_device_usbgadget.dev.platform_data = npd;
- } else {
- printk(KERN_ERR "no memory for udc platform data\n");
- }
+ s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
}
/* USB High Speed 2.0 Device (Gadget) */
@@ -263,15 +252,7 @@ struct platform_device s3c_device_usb_hsudc = {
void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
{
- struct s3c24xx_hsudc_platdata *npd;
-
- npd = kmalloc(sizeof(*npd), GFP_KERNEL);
- if (npd) {
- memcpy(npd, pd, sizeof(*npd));
- s3c_device_usb_hsudc.dev.platform_data = npd;
- } else {
- printk(KERN_ERR "no memory for udc platform data\n");
- }
+ s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
}
/* IIS */
@@ -383,13 +364,8 @@ EXPORT_SYMBOL(s3c_device_sdi);
void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
{
- struct s3c24xx_mci_pdata *npd;
-
- npd = kmemdup(pdata, sizeof(struct s3c24xx_mci_pdata), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory to copy pdata", __func__);
-
- s3c_device_sdi.dev.platform_data = npd;
+ s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
+ &s3c_device_sdi);
}
diff --git a/arch/arm/plat-s3c24xx/include/mach/clkdev.h b/arch/arm/plat-s3c24xx/include/mach/clkdev.h
new file mode 100644
index 000000000000..7dffa83d23ff
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-iis.h b/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
index a6f1d5df13b4..cc44e0e931e9 100644
--- a/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
+++ b/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
@@ -64,14 +64,5 @@
#define S3C2410_IISFCON_RXMASK (0x3f)
#define S3C2410_IISFCON_RXSHIFT (0)
-#define S3C2400_IISFCON_TXDMA (1<<11)
-#define S3C2400_IISFCON_RXDMA (1<<10)
-#define S3C2400_IISFCON_TXENABLE (1<<9)
-#define S3C2400_IISFCON_RXENABLE (1<<8)
-#define S3C2400_IISFCON_TXMASK (0x07 << 4)
-#define S3C2400_IISFCON_TXSHIFT (4)
-#define S3C2400_IISFCON_RXMASK (0x07)
-#define S3C2400_IISFCON_RXSHIFT (0)
-
#define S3C2410_IISFIFO (0x10)
#endif /* __ASM_ARCH_REGS_IIS_H */
diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-spi.h b/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
index 2b35479ee35c..892e2f680fca 100644
--- a/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
+++ b/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
@@ -67,7 +67,6 @@
#define S3C2410_SPPIN_ENMUL (1<<2) /* Multi Master Error detect */
#define S3C2410_SPPIN_RESERVED (1<<1)
-#define S3C2400_SPPIN_nCS (1<<1) /* SPI Card Select */
#define S3C2410_SPPIN_KEEP (1<<0) /* Master Out keep */
#define S3C2410_SPPRE (0x0C)
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2400.h b/arch/arm/plat-s3c24xx/include/plat/s3c2400.h
deleted file mode 100644
index b3feaea5c70b..000000000000
--- a/arch/arm/plat-s3c24xx/include/plat/s3c2400.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
- *
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2400 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.
- *
- * Modifications:
- * 09-Fev-2006 LCVR First version, based on s3c2410.h
-*/
-
-#ifdef CONFIG_CPU_S3C2400
-
-extern int s3c2400_init(void);
-
-extern void s3c2400_map_io(void);
-
-extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2400_init_clocks(int xtal);
-
-#else
-#define s3c2400_init_clocks NULL
-#define s3c2400_init_uarts NULL
-#define s3c2400_map_io NULL
-#define s3c2400_init NULL
-#endif
diff --git a/arch/arm/plat-s3c24xx/s3c2410-clock.c b/arch/arm/plat-s3c24xx/s3c2410-clock.c
index 9ecc5d913679..def76aa3825a 100644
--- a/arch/arm/plat-s3c24xx/s3c2410-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2410-clock.c
@@ -90,37 +90,31 @@ static int s3c2410_upll_enable(struct clk *clk, int enable)
static struct clk init_clocks_off[] = {
{
.name = "nand",
- .id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_NAND,
}, {
.name = "sdi",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SDI,
}, {
.name = "adc",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_ADC,
}, {
.name = "i2c",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIC,
}, {
.name = "iis",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIS,
}, {
.name = "spi",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SPI,
@@ -130,70 +124,61 @@ static struct clk init_clocks_off[] = {
static struct clk init_clocks[] = {
{
.name = "lcd",
- .id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_LCDC,
}, {
.name = "gpio",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_GPIO,
}, {
.name = "usb-host",
- .id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBH,
}, {
.name = "usb-device",
- .id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBD,
}, {
.name = "timers",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_PWMT,
}, {
.name = "uart",
- .id = 0,
+ .devname = "s3c2410-uart.0",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART0,
}, {
.name = "uart",
- .id = 1,
+ .devname = "s3c2410-uart.1",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART1,
}, {
.name = "uart",
- .id = 2,
+ .devname = "s3c2410-uart.2",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART2,
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_RTC,
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_p,
.ctrlbit = 0,
}, {
.name = "usb-bus-host",
- .id = -1,
.parent = &clk_usb_bus,
}, {
.name = "usb-bus-gadget",
- .id = -1,
.parent = &clk_usb_bus,
},
};
diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c
index 82f2d4a39291..59552c0ea5fb 100644
--- a/arch/arm/plat-s3c24xx/s3c2443-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c
@@ -56,7 +56,6 @@ int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
struct clk clk_mpllref = {
.name = "mpllref",
.parent = &clk_xtal,
- .id = -1,
};
static struct clk *clk_epllref_sources[] = {
@@ -69,7 +68,6 @@ static struct clk *clk_epllref_sources[] = {
struct clksrc_clk clk_epllref = {
.clk = {
.name = "epllref",
- .id = -1,
},
.sources = &(struct clksrc_sources) {
.sources = clk_epllref_sources,
@@ -92,7 +90,6 @@ struct clksrc_clk clk_esysclk = {
.clk = {
.name = "esysclk",
.parent = &clk_epll,
- .id = -1,
},
.sources = &(struct clksrc_sources) {
.sources = clk_sysclk_sources,
@@ -115,7 +112,6 @@ static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
static struct clk clk_mdivclk = {
.name = "mdivclk",
.parent = &clk_mpllref,
- .id = -1,
.ops = &(struct clk_ops) {
.get_rate = s3c2443_getrate_mdivclk,
},
@@ -132,7 +128,6 @@ struct clksrc_clk clk_msysclk = {
.clk = {
.name = "msysclk",
.parent = &clk_xtal,
- .id = -1,
},
.sources = &(struct clksrc_sources) {
.sources = clk_msysclk_sources,
@@ -159,7 +154,6 @@ static unsigned long s3c2443_prediv_getrate(struct clk *clk)
static struct clk clk_prediv = {
.name = "prediv",
- .id = -1,
.parent = &clk_msysclk.clk,
.ops = &(struct clk_ops) {
.get_rate = s3c2443_prediv_getrate,
@@ -174,7 +168,6 @@ static struct clk clk_prediv = {
static struct clksrc_clk clk_usb_bus_host = {
.clk = {
.name = "usb-bus-host-parent",
- .id = -1,
.parent = &clk_esysclk.clk,
.ctrlbit = S3C2443_SCLKCON_USBHOST,
.enable = s3c2443_clkcon_enable_s,
@@ -189,7 +182,6 @@ static struct clksrc_clk clksrc_clks[] = {
/* ART baud-rate clock sourced from esysclk via a divisor */
.clk = {
.name = "uartclk",
- .id = -1,
.parent = &clk_esysclk.clk,
},
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
@@ -197,7 +189,6 @@ static struct clksrc_clk clksrc_clks[] = {
/* camera interface bus-clock, divided down from esysclk */
.clk = {
.name = "camif-upll", /* same as 2440 name */
- .id = -1,
.parent = &clk_esysclk.clk,
.ctrlbit = S3C2443_SCLKCON_CAMCLK,
.enable = s3c2443_clkcon_enable_s,
@@ -206,7 +197,6 @@ static struct clksrc_clk clksrc_clks[] = {
}, {
.clk = {
.name = "display-if",
- .id = -1,
.parent = &clk_esysclk.clk,
.ctrlbit = S3C2443_SCLKCON_DISPCLK,
.enable = s3c2443_clkcon_enable_s,
@@ -219,13 +209,11 @@ static struct clksrc_clk clksrc_clks[] = {
static struct clk init_clocks_off[] = {
{
.name = "adc",
- .id = -1,
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_ADC,
}, {
.name = "i2c",
- .id = -1,
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_IIC,
@@ -235,136 +223,117 @@ static struct clk init_clocks_off[] = {
static struct clk init_clocks[] = {
{
.name = "dma",
- .id = 0,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_DMA0,
}, {
.name = "dma",
- .id = 1,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_DMA1,
}, {
.name = "dma",
- .id = 2,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_DMA2,
}, {
.name = "dma",
- .id = 3,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_DMA3,
}, {
.name = "dma",
- .id = 4,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_DMA4,
}, {
.name = "dma",
- .id = 5,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_DMA5,
}, {
.name = "hsmmc",
- .id = 1,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_HSMMC,
}, {
.name = "gpio",
- .id = -1,
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_GPIO,
}, {
.name = "usb-host",
- .id = -1,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_USBH,
}, {
.name = "usb-device",
- .id = -1,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_USBD,
}, {
.name = "lcd",
- .id = -1,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_LCDC,
}, {
.name = "timers",
- .id = -1,
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_PWMT,
}, {
.name = "cfc",
- .id = -1,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_CFC,
}, {
.name = "ssmc",
- .id = -1,
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_SSMC,
}, {
.name = "uart",
- .id = 0,
+ .devname = "s3c2440-uart.0",
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_UART0,
}, {
.name = "uart",
- .id = 1,
+ .devname = "s3c2440-uart.1",
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_UART1,
}, {
.name = "uart",
- .id = 2,
+ .devname = "s3c2440-uart.2",
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_UART2,
}, {
.name = "uart",
- .id = 3,
+ .devname = "s3c2440-uart.3",
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_UART3,
}, {
.name = "rtc",
- .id = -1,
.parent = &clk_p,
.enable = s3c2443_clkcon_enable_p,
.ctrlbit = S3C2443_PCLKCON_RTC,
}, {
.name = "watchdog",
- .id = -1,
.parent = &clk_p,
.ctrlbit = S3C2443_PCLKCON_WDT,
}, {
.name = "ac97",
- .id = -1,
.parent = &clk_p,
.ctrlbit = S3C2443_PCLKCON_AC97,
}, {
.name = "nand",
- .id = -1,
.parent = &clk_h,
}, {
.name = "usb-bus-host",
- .id = -1,
.parent = &clk_usb_bus_host.clk,
}
};
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
index fd7032f84ae7..c56612569b40 100644
--- a/arch/arm/plat-s3c24xx/sleep.S
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -41,31 +41,6 @@
.text
- /* s3c_cpu_save
- *
- * entry:
- * r1 = v:p offset
- */
-
-ENTRY(s3c_cpu_save)
- stmfd sp!, { r4 - r12, lr }
- ldr r3, =resume_with_mmu
- bl cpu_suspend
-
- @@ jump to final code to send system to sleep
- ldr r0, =pm_cpu_sleep
- @@ldr pc, [ r0 ]
- ldr r0, [ r0 ]
- mov pc, r0
-
- @@ return to the caller, after having the MMU
- @@ turned on, this restores the last bits from the
- @@ stack
-resume_with_mmu:
- ldmfd sp!, { r4 - r12, pc }
-
- .ltorg
-
/* sleep magic, to allow the bootloader to check for an valid
* image to resume to. Must be the first word before the
* s3c_cpu_resume entry.
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index e98f5c5c7879..9843c954c042 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -39,6 +39,7 @@ config S5P_GPIO_INT
config S5P_HRT
bool
+ select SAMSUNG_DEV_PWM
help
Use the High Resolution timer support
@@ -70,6 +71,16 @@ config S5P_DEV_FIMC3
help
Compile in platform device definitions for FIMC controller 3
+config S5P_DEV_FIMD0
+ bool
+ help
+ Compile in platform device definitions for FIMD controller 0
+
+config S5P_DEV_MFC
+ bool
+ help
+ Compile in platform device definitions for MFC
+
config S5P_DEV_ONENAND
bool
help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index e234cc4d49a0..4b53e04eeca4 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -25,11 +25,12 @@ obj-$(CONFIG_PM) += irq-pm.o
obj-$(CONFIG_S5P_HRT) += s5p-time.o
# devices
-
+obj-$(CONFIG_S5P_DEV_MFC) += dev-mfc.o
obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o
+obj-$(CONFIG_S5P_DEV_FIMD0) += dev-fimd0.o
obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index 8d081d968c58..02af235298e2 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -168,6 +168,41 @@ unsigned long s5p_epll_get_rate(struct clk *clk)
return clk->rate;
}
+int s5p_spdif_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *pclk;
+ int ret;
+
+ pclk = clk_get_parent(clk);
+ if (IS_ERR(pclk))
+ return -EINVAL;
+
+ ret = pclk->ops->set_rate(pclk, rate);
+ clk_put(pclk);
+
+ return ret;
+}
+
+unsigned long s5p_spdif_get_rate(struct clk *clk)
+{
+ struct clk *pclk;
+ int rate;
+
+ pclk = clk_get_parent(clk);
+ if (IS_ERR(pclk))
+ return -EINVAL;
+
+ rate = pclk->ops->get_rate(clk);
+ clk_put(pclk);
+
+ return rate;
+}
+
+struct clk_ops s5p_sclk_spdif_ops = {
+ .set_rate = s5p_spdif_set_rate,
+ .get_rate = s5p_spdif_get_rate,
+};
+
static struct clk *s5p_clks[] __initdata = {
&clk_ext_xtal_mux,
&clk_48m,
diff --git a/arch/arm/plat-s5p/dev-fimd0.c b/arch/arm/plat-s5p/dev-fimd0.c
new file mode 100644
index 000000000000..f728bb5abcef
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimd0.c
@@ -0,0 +1,67 @@
+/* linux/arch/arm/plat-s5p/dev-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Core file for Samsung Display Controller (FIMD) driver
+ *
+ * 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/string.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/fb.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+static struct resource s5p_fimd0_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMD0,
+ .end = S5P_PA_FIMD0 + SZ_32K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMD0_VSYNC,
+ .end = IRQ_FIMD0_VSYNC,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_FIMD0_FIFO,
+ .end = IRQ_FIMD0_FIFO,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = IRQ_FIMD0_SYSTEM,
+ .end = IRQ_FIMD0_SYSTEM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 fimd0_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimd0 = {
+ .name = "s5p-fb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_fimd0_resource),
+ .resource = s5p_fimd0_resource,
+ .dev = {
+ .dma_mask = &fimd0_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+ s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+ &s5p_device_fimd0);
+}
diff --git a/arch/arm/plat-s5p/dev-mfc.c b/arch/arm/plat-s5p/dev-mfc.c
new file mode 100644
index 000000000000..94226a0010f7
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-mfc.c
@@ -0,0 +1,123 @@
+/* linux/arch/arm/plat-s5p/dev-mfc.c
+ *
+ * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd
+ *
+ * Base S5P MFC resource and device 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.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/memblock.h>
+#include <linux/ioport.h>
+
+#include <mach/map.h>
+#include <plat/devs.h>
+#include <plat/irqs.h>
+#include <plat/mfc.h>
+
+static struct resource s5p_mfc_resource[] = {
+ [0] = {
+ .start = S5P_PA_MFC,
+ .end = S5P_PA_MFC + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_MFC,
+ .end = IRQ_MFC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s5p_device_mfc = {
+ .name = "s5p-mfc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_mfc_resource),
+ .resource = s5p_mfc_resource,
+};
+
+/*
+ * MFC hardware has 2 memory interfaces which are modelled as two separate
+ * platform devices to let dma-mapping distinguish between them.
+ *
+ * MFC parent device (s5p_device_mfc) must be registered before memory
+ * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
+ */
+
+static u64 s5p_mfc_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_mfc_l = {
+ .name = "s5p-mfc-l",
+ .id = -1,
+ .dev = {
+ .parent = &s5p_device_mfc.dev,
+ .dma_mask = &s5p_mfc_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+struct platform_device s5p_device_mfc_r = {
+ .name = "s5p-mfc-r",
+ .id = -1,
+ .dev = {
+ .parent = &s5p_device_mfc.dev,
+ .dma_mask = &s5p_mfc_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+struct s5p_mfc_reserved_mem {
+ phys_addr_t base;
+ unsigned long size;
+ struct device *dev;
+};
+
+static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
+
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+ phys_addr_t lbase, unsigned int lsize)
+{
+ int i;
+
+ s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev;
+ s5p_mfc_mem[0].base = rbase;
+ s5p_mfc_mem[0].size = rsize;
+
+ s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev;
+ s5p_mfc_mem[1].base = lbase;
+ s5p_mfc_mem[1].size = lsize;
+
+ for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
+ struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
+ if (memblock_remove(area->base, area->size)) {
+ printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n",
+ area->size, (unsigned long) area->base);
+ area->base = 0;
+ }
+ }
+}
+
+static int __init s5p_mfc_memory_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
+ struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
+ if (!area->base)
+ continue;
+
+ if (dma_declare_coherent_memory(area->dev, area->base,
+ area->base, area->size,
+ DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
+ printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
+ area->size, (unsigned long) area->base);
+ }
+ return 0;
+}
+device_initcall(s5p_mfc_memory_init);
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
index d973d39666a3..36d3551173b2 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -35,9 +35,10 @@
#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000)
#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
#define S5P_VA_SCU S5P_VA_COREPERI(0x0)
-#define S5P_VA_GIC_CPU S5P_VA_COREPERI(0x100)
#define S5P_VA_TWD S5P_VA_COREPERI(0x600)
-#define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000)
+
+#define S5P_VA_GIC_CPU S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST S3C_ADDR(0x02820000)
#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000)
diff --git a/arch/arm/plat-s5p/include/plat/mfc.h b/arch/arm/plat-s5p/include/plat/mfc.h
new file mode 100644
index 000000000000..6697f8cb2949
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/mfc.h
@@ -0,0 +1,27 @@
+/*
+ * 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 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_S5P_MFC_H
+#define __PLAT_S5P_MFC_H
+
+/**
+ * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
+ * @rbase: base address for MFC 'right' memory interface
+ * @rsize: size of the memory reserved for MFC 'right' interface
+ * @lbase: base address for MFC 'left' memory interface
+ * @lsize: size of the memory reserved for MFC 'left' interface
+ *
+ * This function reserves system memory for both MFC device memory
+ * interfaces and registers it to respective struct device entries as
+ * coherent memory.
+ */
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+ phys_addr_t lbase, unsigned int lsize);
+
+#endif /* __PLAT_S5P_MFC_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
index 2b6dcff8ab2b..769b5bdfb046 100644
--- a/arch/arm/plat-s5p/include/plat/s5p-clock.h
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -47,4 +47,9 @@ extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
extern int s5p_epll_enable(struct clk *clk, int enable);
extern unsigned long s5p_epll_get_rate(struct clk *clk);
+/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
+extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
+extern unsigned long s5p_spdif_get_rate(struct clk *clk);
+
+extern struct clk_ops s5p_sclk_spdif_ops;
#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c
index 612934c48b0d..c833e7b57599 100644
--- a/arch/arm/plat-s5p/s5p-time.c
+++ b/arch/arm/plat-s5p/s5p-time.c
@@ -314,13 +314,6 @@ static void __iomem *s5p_timer_reg(void)
return S3C_TIMERREG(offset);
}
-static cycle_t s5p_timer_read(struct clocksource *cs)
-{
- void __iomem *reg = s5p_timer_reg();
-
- return (cycle_t) (reg ? ~__raw_readl(reg) : 0);
-}
-
/*
* Override the global weak sched_clock symbol with this
* local implementation which uses the clocksource to get some
@@ -350,14 +343,6 @@ static void notrace s5p_update_sched_clock(void)
update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
}
-struct clocksource time_clocksource = {
- .name = "s5p_clocksource_timer",
- .rating = 250,
- .read = s5p_timer_read,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
static void __init s5p_clocksource_init(void)
{
unsigned long pclk;
@@ -375,8 +360,9 @@ static void __init s5p_clocksource_init(void)
init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate);
- if (clocksource_register_hz(&time_clocksource, clock_rate))
- panic("%s: can't register clocksource\n", time_clocksource.name);
+ if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer",
+ clock_rate, 250, 32, clocksource_mmio_readl_down))
+ panic("s5p_clocksource_timer: can't register clocksource\n");
}
static void __init s5p_timer_resources(void)
@@ -384,6 +370,7 @@ static void __init s5p_timer_resources(void)
unsigned long event_id = timer_source.event_id;
unsigned long source_id = timer_source.source_id;
+ char devname[15];
timerclk = clk_get(NULL, "timers");
if (IS_ERR(timerclk))
@@ -391,6 +378,10 @@ static void __init s5p_timer_resources(void)
clk_enable(timerclk);
+ sprintf(devname, "s3c24xx-pwm.%lu", event_id);
+ s3c_device_timer[event_id].id = event_id;
+ s3c_device_timer[event_id].dev.init_name = devname;
+
tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
if (IS_ERR(tin_event))
panic("failed to get pwm-tin clock for event timer");
@@ -401,6 +392,10 @@ static void __init s5p_timer_resources(void)
clk_enable(tin_event);
+ sprintf(devname, "s3c24xx-pwm.%lu", source_id);
+ s3c_device_timer[source_id].id = source_id;
+ s3c_device_timer[source_id].dev.init_name = devname;
+
tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
if (IS_ERR(tin_source))
panic("failed to get pwm-tin clock for source timer");
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c
index 54f5eddc921d..e1cbc728c775 100644
--- a/arch/arm/plat-s5p/sysmmu.c
+++ b/arch/arm/plat-s5p/sysmmu.c
@@ -232,8 +232,8 @@ static int s5p_sysmmu_probe(struct platform_device *pdev)
goto err_res;
}
- mem = request_mem_region(res->start,
- ((res->end) - (res->start)) + 1, pdev->name);
+ mem = request_mem_region(res->start, resource_size(res),
+ pdev->name);
if (!mem) {
dev_err(dev, "Failed to request the memory region of %s.\n",
sysmmu_ips_name[i]);
@@ -241,7 +241,7 @@ static int s5p_sysmmu_probe(struct platform_device *pdev)
goto err_res;
}
- sysmmusfrs[i] = ioremap(res->start, res->end - res->start + 1);
+ sysmmusfrs[i] = ioremap(res->start, resource_size(res));
if (!sysmmusfrs[i]) {
dev_err(dev, "Failed to ioremap() for %s.\n",
sysmmu_ips_name[i]);
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 4d79519d19a4..b3e10659e4b8 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -280,6 +280,12 @@ config SAMSUNG_DEV_PWM
help
Compile in platform device definition for PWM Timer
+config SAMSUNG_DEV_BACKLIGHT
+ bool
+ depends on SAMSUNG_DEV_PWM
+ help
+ Compile in platform device definition LCD backlight with PWM Timer
+
config S3C24XX_PWM
bool "PWM device support"
select HAVE_PWM
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 53eb15b0a07d..853764ba8cc5 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_SAMSUNG_DEV_IDE) += dev-ide.o
obj-$(CONFIG_SAMSUNG_DEV_TS) += dev-ts.o
obj-$(CONFIG_SAMSUNG_DEV_KEYPAD) += dev-keypad.o
obj-$(CONFIG_SAMSUNG_DEV_PWM) += dev-pwm.o
+obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o
# DMA support
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2d67f2..ee8deef19481 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/regulator/consumer.h>
#include <plat/regs-adc.h>
#include <plat/adc.h>
@@ -39,8 +40,9 @@
*/
enum s3c_cpu_type {
- TYPE_S3C24XX,
- TYPE_S3C64XX
+ TYPE_ADCV1, /* S3C24XX */
+ TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
+ TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
};
struct s3c_adc_client {
@@ -71,6 +73,7 @@ struct adc_device {
unsigned int prescale;
int irq;
+ struct regulator *vdd;
};
static struct adc_device *adc_dev;
@@ -91,6 +94,7 @@ static inline void s3c_adc_select(struct adc_device *adc,
struct s3c_adc_client *client)
{
unsigned con = readl(adc->regs + S3C2410_ADCCON);
+ enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
client->select_cb(client, 1);
@@ -98,8 +102,12 @@ static inline void s3c_adc_select(struct adc_device *adc,
con &= ~S3C2410_ADCCON_STDBM;
con &= ~S3C2410_ADCCON_STARTMASK;
- if (!client->is_ts)
- con |= S3C2410_ADCCON_SELMUX(client->channel);
+ if (!client->is_ts) {
+ if (cpu == TYPE_ADCV3)
+ writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+ else
+ con |= S3C2410_ADCCON_SELMUX(client->channel);
+ }
writel(con, adc->regs + S3C2410_ADCCON);
}
@@ -285,8 +293,8 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
client->nr_samples--;
- if (cpu == TYPE_S3C64XX) {
- /* S3C64XX ADC resolution is 12-bit */
+ if (cpu != TYPE_ADCV1) {
+ /* S3C64XX/S5P ADC resolution is 12-bit */
data0 &= 0xfff;
data1 &= 0xfff;
} else {
@@ -312,7 +320,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
}
exit:
- if (cpu == TYPE_S3C64XX) {
+ if (cpu != TYPE_ADCV1) {
/* Clear ADC interrupt */
writel(0, adc->regs + S3C64XX_ADCCLRINT);
}
@@ -338,17 +346,24 @@ static int s3c_adc_probe(struct platform_device *pdev)
adc->pdev = pdev;
adc->prescale = S3C2410_ADCCON_PRSCVL(49);
+ adc->vdd = regulator_get(dev, "vdd");
+ if (IS_ERR(adc->vdd)) {
+ dev_err(dev, "operating without regulator \"vdd\" .\n");
+ ret = PTR_ERR(adc->vdd);
+ goto err_alloc;
+ }
+
adc->irq = platform_get_irq(pdev, 1);
if (adc->irq <= 0) {
dev_err(dev, "failed to get adc irq\n");
ret = -ENOENT;
- goto err_alloc;
+ goto err_reg;
}
ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
if (ret < 0) {
dev_err(dev, "failed to attach adc irq\n");
- goto err_alloc;
+ goto err_reg;
}
adc->clk = clk_get(dev, "adc");
@@ -372,10 +387,14 @@ static int s3c_adc_probe(struct platform_device *pdev)
goto err_clk;
}
+ ret = regulator_enable(adc->vdd);
+ if (ret)
+ goto err_ioremap;
+
clk_enable(adc->clk);
tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
- if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) {
+ if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1) {
/* Enable 12-bit ADC resolution */
tmp |= S3C64XX_ADCCON_RESSEL;
}
@@ -388,12 +407,15 @@ static int s3c_adc_probe(struct platform_device *pdev)
return 0;
+ err_ioremap:
+ iounmap(adc->regs);
err_clk:
clk_put(adc->clk);
err_irq:
free_irq(adc->irq, adc);
-
+ err_reg:
+ regulator_put(adc->vdd);
err_alloc:
kfree(adc);
return ret;
@@ -406,6 +428,8 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
iounmap(adc->regs);
free_irq(adc->irq, adc);
clk_disable(adc->clk);
+ regulator_disable(adc->vdd);
+ regulator_put(adc->vdd);
clk_put(adc->clk);
kfree(adc);
@@ -413,8 +437,10 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
+static int s3c_adc_suspend(struct device *dev)
{
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
struct adc_device *adc = platform_get_drvdata(pdev);
unsigned long flags;
u32 con;
@@ -428,19 +454,30 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
disable_irq(adc->irq);
spin_unlock_irqrestore(&adc->lock, flags);
clk_disable(adc->clk);
+ regulator_disable(adc->vdd);
return 0;
}
-static int s3c_adc_resume(struct platform_device *pdev)
+static int s3c_adc_resume(struct device *dev)
{
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
struct adc_device *adc = platform_get_drvdata(pdev);
+ int ret;
+ unsigned long tmp;
+ ret = regulator_enable(adc->vdd);
+ if (ret)
+ return ret;
clk_enable(adc->clk);
enable_irq(adc->irq);
- writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
- adc->regs + S3C2410_ADCCON);
+ tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+ /* Enable 12-bit ADC resolution */
+ if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1)
+ tmp |= S3C64XX_ADCCON_RESSEL;
+ writel(tmp, adc->regs + S3C2410_ADCCON);
return 0;
}
@@ -453,25 +490,32 @@ static int s3c_adc_resume(struct platform_device *pdev)
static struct platform_device_id s3c_adc_driver_ids[] = {
{
.name = "s3c24xx-adc",
- .driver_data = TYPE_S3C24XX,
+ .driver_data = TYPE_ADCV1,
}, {
.name = "s3c64xx-adc",
- .driver_data = TYPE_S3C64XX,
+ .driver_data = TYPE_ADCV2,
+ }, {
+ .name = "samsung-adc-v3",
+ .driver_data = TYPE_ADCV3,
},
{ }
};
MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
+static const struct dev_pm_ops adc_pm_ops = {
+ .suspend = s3c_adc_suspend,
+ .resume = s3c_adc_resume,
+};
+
static struct platform_driver s3c_adc_driver = {
.id_table = s3c_adc_driver_ids,
.driver = {
.name = "s3c-adc",
.owner = THIS_MODULE,
+ .pm = &adc_pm_ops,
},
.probe = s3c_adc_probe,
.remove = __devexit_p(s3c_adc_remove),
- .suspend = s3c_adc_suspend,
- .resume = s3c_adc_resume,
};
static int __init adc_init(void)
@@ -485,4 +529,4 @@ static int __init adc_init(void)
return ret;
}
-arch_initcall(adc_init);
+module_init(adc_init);
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 772892826ffc..302c42670bd1 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -71,74 +71,6 @@ static int clk_null_enable(struct clk *clk, int enable)
return 0;
}
-static int dev_is_s3c_uart(struct device *dev)
-{
- struct platform_device **pdev = s3c24xx_uart_devs;
- int i;
- for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++)
- if (*pdev && dev == &(*pdev)->dev)
- return 1;
- return 0;
-}
-
-/*
- * Serial drivers call get_clock() very early, before platform bus
- * has been set up, this requires a special check to let them get
- * a proper clock
- */
-
-static int dev_is_platform_device(struct device *dev)
-{
- return dev->bus == &platform_bus_type ||
- (dev->bus == NULL && dev_is_s3c_uart(dev));
-}
-
-/* Clock API calls */
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
- struct clk *p;
- struct clk *clk = ERR_PTR(-ENOENT);
- int idno;
-
- if (dev == NULL || !dev_is_platform_device(dev))
- idno = -1;
- else
- idno = to_platform_device(dev)->id;
-
- spin_lock(&clocks_lock);
-
- list_for_each_entry(p, &clocks, list) {
- if (p->id == idno &&
- strcmp(id, p->name) == 0 &&
- try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
-
- /* check for the case where a device was supplied, but the
- * clock that was being searched for is not device specific */
-
- if (IS_ERR(clk)) {
- list_for_each_entry(p, &clocks, list) {
- if (p->id == -1 && strcmp(id, p->name) == 0 &&
- try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
- }
-
- spin_unlock(&clocks_lock);
- return clk;
-}
-
-void clk_put(struct clk *clk)
-{
- module_put(clk->owner);
-}
-
int clk_enable(struct clk *clk)
{
if (IS_ERR(clk) || clk == NULL)
@@ -241,8 +173,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
return ret;
}
-EXPORT_SYMBOL(clk_get);
-EXPORT_SYMBOL(clk_put);
EXPORT_SYMBOL(clk_enable);
EXPORT_SYMBOL(clk_disable);
EXPORT_SYMBOL(clk_get_rate);
@@ -265,7 +195,6 @@ struct clk_ops clk_ops_def_setrate = {
struct clk clk_xtal = {
.name = "xtal",
- .id = -1,
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
@@ -273,30 +202,25 @@ struct clk clk_xtal = {
struct clk clk_ext = {
.name = "ext",
- .id = -1,
};
struct clk clk_epll = {
.name = "epll",
- .id = -1,
};
struct clk clk_mpll = {
.name = "mpll",
- .id = -1,
.ops = &clk_ops_def_setrate,
};
struct clk clk_upll = {
.name = "upll",
- .id = -1,
.parent = NULL,
.ctrlbit = 0,
};
struct clk clk_f = {
.name = "fclk",
- .id = -1,
.rate = 0,
.parent = &clk_mpll,
.ctrlbit = 0,
@@ -304,7 +228,6 @@ struct clk clk_f = {
struct clk clk_h = {
.name = "hclk",
- .id = -1,
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
@@ -313,7 +236,6 @@ struct clk clk_h = {
struct clk clk_p = {
.name = "pclk",
- .id = -1,
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
@@ -322,7 +244,6 @@ struct clk clk_p = {
struct clk clk_usb_bus = {
.name = "usb-bus",
- .id = -1,
.rate = 0,
.parent = &clk_upll,
};
@@ -330,7 +251,6 @@ struct clk clk_usb_bus = {
struct clk s3c24xx_uclk = {
.name = "uclk",
- .id = -1,
};
/* initialise the clock system */
@@ -346,14 +266,11 @@ int s3c24xx_register_clock(struct clk *clk)
if (clk->enable == NULL)
clk->enable = clk_null_enable;
- /* add to the list of available clocks */
-
- /* Quick check to see if this clock has already been registered. */
- BUG_ON(clk->list.prev != clk->list.next);
-
- spin_lock(&clocks_lock);
- list_add(&clk->list, &clocks);
- spin_unlock(&clocks_lock);
+ /* fill up the clk_lookup structure and register it*/
+ clk->lookup.dev_id = clk->devname;
+ clk->lookup.con_id = clk->name;
+ clk->lookup.clk = clk;
+ clkdev_add(&clk->lookup);
return 0;
}
@@ -458,15 +375,12 @@ static struct dentry *clk_debugfs_root;
static int clk_debugfs_register_one(struct clk *c)
{
int err;
- struct dentry *d, *child, *child_tmp;
+ struct dentry *d;
struct clk *pa = c->parent;
char s[255];
char *p = s;
- p += sprintf(p, "%s", c->name);
-
- if (c->id >= 0)
- sprintf(p, ":%d", c->id);
+ p += sprintf(p, "%s", c->devname);
d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
if (!d)
@@ -488,10 +402,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;
err_out:
- d = c->dent;
- list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(c->dent);
+ debugfs_remove_recursive(c->dent);
return err;
}
diff --git a/arch/arm/plat-samsung/dev-asocdma.c b/arch/arm/plat-samsung/dev-asocdma.c
index a068c4f42d56..97e35d3c064d 100644
--- a/arch/arm/plat-samsung/dev-asocdma.c
+++ b/arch/arm/plat-samsung/dev-asocdma.c
@@ -23,3 +23,13 @@ struct platform_device samsung_asoc_dma = {
}
};
EXPORT_SYMBOL(samsung_asoc_dma);
+
+struct platform_device samsung_asoc_idma = {
+ .name = "samsung-idma",
+ .id = -1,
+ .dev = {
+ .dma_mask = &audio_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+EXPORT_SYMBOL(samsung_asoc_idma);
diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c
new file mode 100644
index 000000000000..3cedd4c407af
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-backlight.c
@@ -0,0 +1,149 @@
+/* linux/arch/arm/plat-samsung/dev-backlight.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Common infrastructure for PWM Backlight for Samsung boards
+ *
+ * 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/platform_device.h>
+#include <linux/io.h>
+#include <linux/pwm_backlight.h>
+
+#include <plat/devs.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+
+static int samsung_bl_init(struct device *dev)
+{
+ int ret = 0;
+ struct platform_device *timer_dev =
+ container_of(dev->parent, struct platform_device, dev);
+ struct samsung_bl_gpio_info *bl_gpio_info =
+ timer_dev->dev.platform_data;
+
+ ret = gpio_request(bl_gpio_info->no, "Backlight");
+ if (ret) {
+ printk(KERN_ERR "failed to request GPIO for LCD Backlight\n");
+ return ret;
+ }
+
+ /* Configure GPIO pin with specific GPIO function for PWM timer */
+ s3c_gpio_cfgpin(bl_gpio_info->no, bl_gpio_info->func);
+
+ return 0;
+}
+
+static void samsung_bl_exit(struct device *dev)
+{
+ struct platform_device *timer_dev =
+ container_of(dev->parent, struct platform_device, dev);
+ struct samsung_bl_gpio_info *bl_gpio_info =
+ timer_dev->dev.platform_data;
+
+ s3c_gpio_cfgpin(bl_gpio_info->no, S3C_GPIO_OUTPUT);
+ gpio_free(bl_gpio_info->no);
+}
+
+/* Initialize few important fields of platform_pwm_backlight_data
+ * structure with default values. These fields can be overridden by
+ * board-specific values sent from machine file.
+ * For ease of operation, these fields are initialized with values
+ * used by most samsung boards.
+ * Users has the option of sending info about other parameters
+ * for their specific boards
+ */
+
+static struct platform_pwm_backlight_data samsung_dfl_bl_data __initdata = {
+ .max_brightness = 255,
+ .dft_brightness = 255,
+ .pwm_period_ns = 78770,
+ .init = samsung_bl_init,
+ .exit = samsung_bl_exit,
+};
+
+static struct platform_device samsung_dfl_bl_device __initdata = {
+ .name = "pwm-backlight",
+};
+
+/* samsung_bl_set - Set board specific data (if any) provided by user for
+ * PWM Backlight control and register specific PWM and backlight device.
+ * @gpio_info: structure containing GPIO info for PWM timer
+ * @bl_data: structure containing Backlight control data
+ */
+void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
+ struct platform_pwm_backlight_data *bl_data)
+{
+ int ret = 0;
+ struct platform_device *samsung_bl_device;
+ struct platform_pwm_backlight_data *samsung_bl_data;
+
+ samsung_bl_device = kmemdup(&samsung_dfl_bl_device,
+ sizeof(struct platform_device), GFP_KERNEL);
+ if (!samsung_bl_device) {
+ printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
+ return;
+ }
+
+ samsung_bl_data = s3c_set_platdata(&samsung_dfl_bl_data,
+ sizeof(struct platform_pwm_backlight_data), samsung_bl_device);
+ if (!samsung_bl_data) {
+ printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
+ goto err_data;
+ }
+
+ /* Copy board specific data provided by user */
+ samsung_bl_data->pwm_id = bl_data->pwm_id;
+ samsung_bl_device->dev.parent =
+ &s3c_device_timer[samsung_bl_data->pwm_id].dev;
+
+ if (bl_data->max_brightness)
+ samsung_bl_data->max_brightness = bl_data->max_brightness;
+ if (bl_data->dft_brightness)
+ samsung_bl_data->dft_brightness = bl_data->dft_brightness;
+ if (bl_data->lth_brightness)
+ samsung_bl_data->lth_brightness = bl_data->lth_brightness;
+ if (bl_data->pwm_period_ns)
+ samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
+ if (bl_data->init)
+ samsung_bl_data->init = bl_data->init;
+ if (bl_data->notify)
+ samsung_bl_data->notify = bl_data->notify;
+ if (bl_data->exit)
+ samsung_bl_data->exit = bl_data->exit;
+ if (bl_data->check_fb)
+ samsung_bl_data->check_fb = bl_data->check_fb;
+
+ /* Keep the GPIO info for future use */
+ s3c_device_timer[samsung_bl_data->pwm_id].dev.platform_data = gpio_info;
+
+ /* Register the specific PWM timer dev for Backlight control */
+ ret = platform_device_register(
+ &s3c_device_timer[samsung_bl_data->pwm_id]);
+ if (ret) {
+ printk(KERN_ERR "failed to register pwm timer for backlight: %d\n", ret);
+ goto err_plat_reg1;
+ }
+
+ /* Register the Backlight dev */
+ ret = platform_device_register(samsung_bl_device);
+ if (ret) {
+ printk(KERN_ERR "failed to register backlight device: %d\n", ret);
+ goto err_plat_reg2;
+ }
+
+ return;
+
+err_plat_reg2:
+ platform_device_unregister(&s3c_device_timer[samsung_bl_data->pwm_id]);
+err_plat_reg1:
+ kfree(samsung_bl_data);
+err_data:
+ kfree(samsung_bl_device);
+ return;
+}
diff --git a/arch/arm/plat-samsung/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c
index bf60204c6297..49a1362fd25b 100644
--- a/arch/arm/plat-samsung/dev-fb.c
+++ b/arch/arm/plat-samsung/dev-fb.c
@@ -58,16 +58,6 @@ struct platform_device s3c_device_fb = {
void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
{
- struct s3c_fb_platdata *npd;
-
- if (!pd) {
- printk(KERN_ERR "%s: no platform data\n", __func__);
- return;
- }
-
- npd = kmemdup(pd, sizeof(struct s3c_fb_platdata), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
- s3c_device_fb.dev.platform_data = npd;
+ s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+ &s3c_device_fb);
}
diff --git a/arch/arm/plat-samsung/dev-hwmon.c b/arch/arm/plat-samsung/dev-hwmon.c
index b3ffb9587250..c91a79ce8f39 100644
--- a/arch/arm/plat-samsung/dev-hwmon.c
+++ b/arch/arm/plat-samsung/dev-hwmon.c
@@ -27,16 +27,6 @@ struct platform_device s3c_device_hwmon = {
void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
{
- struct s3c_hwmon_pdata *npd;
-
- if (!pd) {
- printk(KERN_ERR "%s: no platform data\n", __func__);
- return;
- }
-
- npd = kmemdup(pd, sizeof(struct s3c_hwmon_pdata), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
- s3c_device_hwmon.dev.platform_data = npd;
+ s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
+ &s3c_device_hwmon);
}
diff --git a/arch/arm/plat-samsung/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c
index 3a601c16f03c..f8251f5098bd 100644
--- a/arch/arm/plat-samsung/dev-i2c0.c
+++ b/arch/arm/plat-samsung/dev-i2c0.c
@@ -48,7 +48,7 @@ struct platform_device s3c_device_i2c0 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data0 __initdata = {
+struct s3c2410_platform_i2c default_i2c_data __initdata = {
.flags = 0,
.slave_addr = 0x10,
.frequency = 100*1000,
@@ -60,13 +60,11 @@ void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
struct s3c2410_platform_i2c *npd;
if (!pd)
- pd = &default_i2c_data0;
+ pd = &default_i2c_data;
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c0_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c0);
- s3c_device_i2c0.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c0_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c
index 858ee2a0414c..3b7c7bec1cf9 100644
--- a/arch/arm/plat-samsung/dev-i2c1.c
+++ b/arch/arm/plat-samsung/dev-i2c1.c
@@ -44,26 +44,18 @@ struct platform_device s3c_device_i2c1 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data1 __initdata = {
- .flags = 0,
- .bus_num = 1,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
-};
-
void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
- pd = &default_i2c_data1;
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 1;
+ }
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c1_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c1);
- s3c_device_i2c1.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c1_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c
index ff4ba69b6830..07e9fd0b1b8b 100644
--- a/arch/arm/plat-samsung/dev-i2c2.c
+++ b/arch/arm/plat-samsung/dev-i2c2.c
@@ -45,26 +45,18 @@ struct platform_device s3c_device_i2c2 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data2 __initdata = {
- .flags = 0,
- .bus_num = 2,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
-};
-
void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
- pd = &default_i2c_data2;
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 2;
+ }
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c2_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c2);
- s3c_device_i2c2.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c2_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c
index 8586a10014b7..d48efa93c6e7 100644
--- a/arch/arm/plat-samsung/dev-i2c3.c
+++ b/arch/arm/plat-samsung/dev-i2c3.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c3 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data3 __initdata = {
- .flags = 0,
- .bus_num = 3,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
-};
-
void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
- pd = &default_i2c_data3;
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 3;
+ }
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c3_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c3);
- s3c_device_i2c3.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c3_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c
index df2159e2daa6..07e26444efe6 100644
--- a/arch/arm/plat-samsung/dev-i2c4.c
+++ b/arch/arm/plat-samsung/dev-i2c4.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c4 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data4 __initdata = {
- .flags = 0,
- .bus_num = 4,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
-};
-
void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
- pd = &default_i2c_data4;
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 4;
+ }
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c4_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c4);
- s3c_device_i2c4.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c4_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c
index 0499c2c3877b..f49655784563 100644
--- a/arch/arm/plat-samsung/dev-i2c5.c
+++ b/arch/arm/plat-samsung/dev-i2c5.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c5 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data5 __initdata = {
- .flags = 0,
- .bus_num = 5,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
-};
-
void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
- pd = &default_i2c_data5;
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 5;
+ }
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c5_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c5);
- s3c_device_i2c5.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c5_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c
index 4083108908a8..141d799944e2 100644
--- a/arch/arm/plat-samsung/dev-i2c6.c
+++ b/arch/arm/plat-samsung/dev-i2c6.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c6 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data6 __initdata = {
- .flags = 0,
- .bus_num = 6,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
-};
-
void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
- pd = &default_i2c_data6;
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 6;
+ }
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c6_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c6);
- s3c_device_i2c6.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c6_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c
index 1182451d7dce..9dddcd1665b5 100644
--- a/arch/arm/plat-samsung/dev-i2c7.c
+++ b/arch/arm/plat-samsung/dev-i2c7.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c7 = {
.resource = s3c_i2c_resource,
};
-static struct s3c2410_platform_i2c default_i2c_data7 __initdata = {
- .flags = 0,
- .bus_num = 7,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
-};
-
void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
- pd = &default_i2c_data7;
+ if (!pd) {
+ pd = &default_i2c_data;
+ pd->bus_num = 7;
+ }
- npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- else if (!npd->cfg_gpio)
- npd->cfg_gpio = s3c_i2c7_cfg_gpio;
+ npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+ &s3c_device_i2c7);
- s3c_device_i2c7.dev.platform_data = npd;
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_i2c7_cfg_gpio;
}
diff --git a/arch/arm/plat-samsung/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c
index 6927ae8fd118..b8e30ec6ac26 100644
--- a/arch/arm/plat-samsung/dev-nand.c
+++ b/arch/arm/plat-samsung/dev-nand.c
@@ -91,11 +91,10 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
* time then there is little chance the system is going to run.
*/
- npd = kmemdup(nand, sizeof(struct s3c2410_platform_nand), GFP_KERNEL);
- if (!npd) {
- printk(KERN_ERR "%s: failed copying platform data\n", __func__);
+ npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
+ &s3c_device_nand);
+ if (!npd)
return;
- }
/* now see if we need to copy any of the nand set data */
@@ -123,6 +122,4 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
to++;
}
}
-
- s3c_device_nand.dev.platform_data = npd;
}
diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c
index 3e4bd8147bf4..82543f0248ac 100644
--- a/arch/arm/plat-samsung/dev-ts.c
+++ b/arch/arm/plat-samsung/dev-ts.c
@@ -45,16 +45,6 @@ struct platform_device s3c_device_ts = {
void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
{
- struct s3c2410_ts_mach_info *npd;
-
- if (!pd) {
- printk(KERN_ERR "%s: no platform data\n", __func__);
- return;
- }
-
- npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
- s3c_device_ts.dev.platform_data = npd;
+ s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
+ &s3c_device_ts);
}
diff --git a/arch/arm/plat-samsung/dev-usb.c b/arch/arm/plat-samsung/dev-usb.c
index 0e0a3bf5c982..33fbaa967700 100644
--- a/arch/arm/plat-samsung/dev-usb.c
+++ b/arch/arm/plat-samsung/dev-usb.c
@@ -60,11 +60,6 @@ EXPORT_SYMBOL(s3c_device_ohci);
*/
void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
{
- struct s3c2410_hcd_info *npd;
-
- npd = kmemdup(info, sizeof(struct s3c2410_hcd_info), GFP_KERNEL);
- if (!npd)
- printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
- s3c_device_ohci.dev.platform_data = npd;
+ s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
+ &s3c_device_ohci);
}
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h
index a0826ed2f9fe..aa9875f77c40 100644
--- a/arch/arm/plat-samsung/include/plat/audio.h
+++ b/arch/arm/plat-samsung/include/plat/audio.h
@@ -44,6 +44,7 @@ struct samsung_i2s {
* Also corresponds to clocks of I2SMOD[10]
*/
const char **src_clk;
+ dma_addr_t idma_addr;
};
/**
diff --git a/arch/arm/plat-samsung/include/plat/backlight.h b/arch/arm/plat-samsung/include/plat/backlight.h
new file mode 100644
index 000000000000..51d8da846a62
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/backlight.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/plat-samsung/include/plat/backlight.h
+ *
+ * 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.
+ */
+
+#ifndef __ASM_PLAT_BACKLIGHT_H
+#define __ASM_PLAT_BACKLIGHT_H __FILE__
+
+/* samsung_bl_gpio_info - GPIO info for PWM Backlight control
+ * @no: GPIO number for PWM timer out
+ * @func: Special function of GPIO line for PWM timer
+ */
+struct samsung_bl_gpio_info {
+ int no;
+ int func;
+};
+
+extern void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
+ struct platform_pwm_backlight_data *bl_data);
+
+#endif /* __ASM_PLAT_BACKLIGHT_H */
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h
index 983c578b8276..87d5b38a86fb 100644
--- a/arch/arm/plat-samsung/include/plat/clock.h
+++ b/arch/arm/plat-samsung/include/plat/clock.h
@@ -10,6 +10,7 @@
*/
#include <linux/spinlock.h>
+#include <linux/clkdev.h>
struct clk;
@@ -40,6 +41,7 @@ struct clk {
struct module *owner;
struct clk *parent;
const char *name;
+ const char *devname;
int id;
int usage;
unsigned long rate;
@@ -47,6 +49,7 @@ struct clk {
struct clk_ops *ops;
int (*enable)(struct clk *, int enable);
+ struct clk_lookup lookup;
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
struct dentry *dent; /* For visible tree hierarchy */
#endif
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index e3b31c26ac3e..24ebb1e1de41 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -40,6 +40,7 @@ extern struct platform_device s3c64xx_device_spi0;
extern struct platform_device s3c64xx_device_spi1;
extern struct platform_device samsung_asoc_dma;
+extern struct platform_device samsung_asoc_idma;
extern struct platform_device s3c64xx_device_pcm0;
extern struct platform_device s3c64xx_device_pcm1;
@@ -49,6 +50,7 @@ extern struct platform_device s3c64xx_device_ac97;
extern struct platform_device s3c_device_ts;
extern struct platform_device s3c_device_fb;
+extern struct platform_device s5p_device_fimd0;
extern struct platform_device s3c_device_ohci;
extern struct platform_device s3c_device_lcd;
extern struct platform_device s3c_device_wdt;
@@ -112,6 +114,7 @@ extern struct platform_device exynos4_device_i2s2;
extern struct platform_device exynos4_device_spdif;
extern struct platform_device exynos4_device_pd[];
extern struct platform_device exynos4_device_ahci;
+extern struct platform_device exynos4_device_dwmci;
extern struct platform_device s5p6440_device_pcm;
extern struct platform_device s5p6440_device_iis;
@@ -136,6 +139,9 @@ extern struct platform_device s5p_device_fimc1;
extern struct platform_device s5p_device_fimc2;
extern struct platform_device s5p_device_fimc3;
+extern struct platform_device s5p_device_mfc;
+extern struct platform_device s5p_device_mfc_l;
+extern struct platform_device s5p_device_mfc_r;
extern struct platform_device s5p_device_mipi_csis0;
extern struct platform_device s5p_device_mipi_csis1;
diff --git a/arch/arm/plat-samsung/include/plat/fb-core.h b/arch/arm/plat-samsung/include/plat/fb-core.h
index bca383efcf6d..6abcbf139cee 100644
--- a/arch/arm/plat-samsung/include/plat/fb-core.h
+++ b/arch/arm/plat-samsung/include/plat/fb-core.h
@@ -26,4 +26,19 @@ static inline void s3c_fb_setname(char *name)
#endif
}
+/* Re-define device name depending on support. */
+static inline void s5p_fb_setname(int id, char *name)
+{
+ switch (id) {
+#ifdef CONFIG_S5P_DEV_FIMD0
+ case 0:
+ s5p_device_fimd0.name = name;
+ break;
+#endif
+ default:
+ printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
+ break;
+ }
+}
+
#endif /* __ASM_PLAT_FB_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index cb3ca3adc685..01f10e4d00c7 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -74,6 +74,14 @@ struct s3c_fb_platdata {
extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
/**
+ * s5p_fimd0_set_platdata() - Setup the FB device with platform data.
+ * @pd: The platform data to set. The data is copied from the passed structure
+ * so the machine data can mark the data __initdata so that any unused
+ * machines will end up dumping their data at runtime.
+ */
+extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
+
+/**
* s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface.
@@ -94,4 +102,11 @@ extern void s5pc100_fb_gpio_setup_24bpp(void);
*/
extern void s5pv210_fb_gpio_setup_24bpp(void);
+/**
+ * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
+ */
+extern void exynos4_fimd0_gpio_setup_24bpp(void);
+
#endif /* __PLAT_S3C_FB_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
index 3ad8386599c3..9a4e53d52967 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
@@ -140,7 +140,7 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
/* Pull-{up,down} resistor controls.
*
- * S3C2410,S3C2440,S3C24A0 = Pull-UP,
+ * S3C2410,S3C2440 = Pull-UP,
* S3C2412,S3C2413 = Pull-Down
* S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef]
* S3C2443 = Pull-Both [not same as S3C6400]
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
index 1543da8f85c1..56b0059439e1 100644
--- a/arch/arm/plat-samsung/include/plat/iic.h
+++ b/arch/arm/plat-samsung/include/plat/iic.h
@@ -71,4 +71,6 @@ extern void s3c_i2c5_cfg_gpio(struct platform_device *dev);
extern void s3c_i2c6_cfg_gpio(struct platform_device *dev);
extern void s3c_i2c7_cfg_gpio(struct platform_device *dev);
+extern struct s3c2410_platform_i2c default_i2c_data;
+
#endif /* __ASM_ARCH_IIC_H */
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 7fb6f6be8c81..f6749916d194 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -42,7 +42,7 @@ extern unsigned long s3c_irqwake_eintallow;
/* per-cpu sleep functions */
extern void (*pm_cpu_prep)(void);
-extern void (*pm_cpu_sleep)(void);
+extern int (*pm_cpu_sleep)(unsigned long);
/* Flags for PM Control */
@@ -52,10 +52,9 @@ extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
/* from sleep.S */
-extern int s3c_cpu_save(unsigned long *saveblk, long);
extern void s3c_cpu_resume(void);
-extern void s3c2410_cpu_suspend(void);
+extern int s3c2410_cpu_suspend(unsigned long);
/* sleep save info */
diff --git a/arch/arm/plat-samsung/include/plat/regs-adc.h b/arch/arm/plat-samsung/include/plat/regs-adc.h
index 7554c4fcddb9..035e8c38d69c 100644
--- a/arch/arm/plat-samsung/include/plat/regs-adc.h
+++ b/arch/arm/plat-samsung/include/plat/regs-adc.h
@@ -21,6 +21,7 @@
#define S3C2410_ADCDAT1 S3C2410_ADCREG(0x10)
#define S3C64XX_ADCUPDN S3C2410_ADCREG(0x14)
#define S3C64XX_ADCCLRINT S3C2410_ADCREG(0x18)
+#define S5P_ADCMUX S3C2410_ADCREG(0x1C)
#define S3C64XX_ADCCLRINTPNDNUP S3C2410_ADCREG(0x20)
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
index 116edfe120b9..bac36fa3becb 100644
--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
+++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
@@ -155,14 +155,6 @@
#define S3C2410_UFSTAT_RXMASK (15<<0)
#define S3C2410_UFSTAT_RXSHIFT (0)
-/* UFSTAT S3C24A0 */
-#define S3C24A0_UFSTAT_TXFULL (1 << 14)
-#define S3C24A0_UFSTAT_RXFULL (1 << 6)
-#define S3C24A0_UFSTAT_TXMASK (63 << 8)
-#define S3C24A0_UFSTAT_TXSHIFT (8)
-#define S3C24A0_UFSTAT_RXMASK (63)
-#define S3C24A0_UFSTAT_RXSHIFT (0)
-
/* UFSTAT S3C2443 same as S3C2440 */
#define S3C2440_UFSTAT_TXFULL (1<<14)
#define S3C2440_UFSTAT_RXFULL (1<<6)
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c
index 657405c481d0..3014c7226bd1 100644
--- a/arch/arm/plat-samsung/irq-uart.c
+++ b/arch/arm/plat-samsung/irq-uart.c
@@ -19,6 +19,8 @@
#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>
@@ -30,9 +32,12 @@
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))
@@ -41,6 +46,8 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
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)
diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c
index 6b733fafe7cd..3cbd62666b1e 100644
--- a/arch/arm/plat-samsung/pm-check.c
+++ b/arch/arm/plat-samsung/pm-check.c
@@ -72,7 +72,7 @@ static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
static u32 *s3c_pm_countram(struct resource *res, u32 *val)
{
- u32 size = (u32)(res->end - res->start)+1;
+ u32 size = (u32)resource_size(res);
size += CHECK_CHUNKSIZE-1;
size /= CHECK_CHUNKSIZE;
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index 5c0a440d6e16..ae6f99834cdd 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -20,6 +20,7 @@
#include <linux/io.h>
#include <asm/cacheflush.h>
+#include <asm/suspend.h>
#include <mach/hardware.h>
#include <mach/map.h>
@@ -231,7 +232,7 @@ static void __maybe_unused s3c_pm_show_resume_irqs(int start,
void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
+int (*pm_cpu_sleep)(unsigned long);
#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
@@ -268,6 +269,7 @@ static int s3c_pm_enter(suspend_state_t state)
/* save all necessary core registers not covered by the drivers */
s3c_pm_save_gpios();
+ s3c_pm_saved_gpios();
s3c_pm_save_uarts();
s3c_pm_save_core();
@@ -294,21 +296,18 @@ static int s3c_pm_enter(suspend_state_t state)
s3c_pm_arch_stop_clocks();
- /* s3c_cpu_save will also act as our return point from when
+ /* this will also act as our return point from when
* we resume as it saves its own register state and restores it
* during the resume. */
- s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
-
- /* restore the cpu state using the kernel's cpu init code. */
-
- cpu_init();
+ cpu_suspend(0, pm_cpu_sleep);
/* restore the system state */
s3c_pm_restore_core();
s3c_pm_restore_uarts();
s3c_pm_restore_gpios();
+ s3c_pm_restored_gpios();
s3c_pm_debug_init();
diff --git a/arch/arm/plat-samsung/pwm-clock.c b/arch/arm/plat-samsung/pwm-clock.c
index 46c9381e083b..f1bba88ed2f5 100644
--- a/arch/arm/plat-samsung/pwm-clock.c
+++ b/arch/arm/plat-samsung/pwm-clock.c
@@ -268,6 +268,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
[0] = {
.clk = {
.name = "pwm-tdiv",
+ .devname = "s3c24xx-pwm.0",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[0],
},
@@ -275,6 +276,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
[1] = {
.clk = {
.name = "pwm-tdiv",
+ .devname = "s3c24xx-pwm.1",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[0],
}
@@ -282,6 +284,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
[2] = {
.clk = {
.name = "pwm-tdiv",
+ .devname = "s3c24xx-pwm.2",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[1],
},
@@ -289,6 +292,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
[3] = {
.clk = {
.name = "pwm-tdiv",
+ .devname = "s3c24xx-pwm.3",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[1],
},
@@ -296,6 +300,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
[4] = {
.clk = {
.name = "pwm-tdiv",
+ .devname = "s3c24xx-pwm.4",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[1],
},
@@ -361,26 +366,31 @@ static struct clk_ops clk_tin_ops = {
static struct clk clk_tin[] = {
[0] = {
.name = "pwm-tin",
+ .devname = "s3c24xx-pwm.0",
.id = 0,
.ops = &clk_tin_ops,
},
[1] = {
.name = "pwm-tin",
+ .devname = "s3c24xx-pwm.1",
.id = 1,
.ops = &clk_tin_ops,
},
[2] = {
.name = "pwm-tin",
+ .devname = "s3c24xx-pwm.2",
.id = 2,
.ops = &clk_tin_ops,
},
[3] = {
.name = "pwm-tin",
+ .devname = "s3c24xx-pwm.3",
.id = 3,
.ops = &clk_tin_ops,
},
[4] = {
.name = "pwm-tin",
+ .devname = "s3c24xx-pwm.4",
.id = 4,
.ops = &clk_tin_ops,
},
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
index 2231d80ad817..e3bb806bbafe 100644
--- a/arch/arm/plat-samsung/time.c
+++ b/arch/arm/plat-samsung/time.c
@@ -259,6 +259,8 @@ static void __init s3c2410_timer_resources(void)
clk_enable(timerclk);
if (!use_tclk1_12()) {
+ tmpdev.id = 4;
+ tmpdev.dev.init_name = "s3c24xx-pwm.4";
tin = clk_get(&tmpdev.dev, "pwm-tin");
if (IS_ERR(tin))
panic("failed to get pwm-tin clock for system timer");
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index 6fa474cb398e..67dd00381ea6 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -916,7 +916,7 @@ static struct dentry *clk_debugfs_root;
static int clk_debugfs_register_one(struct clk *c)
{
int err;
- struct dentry *d, *child;
+ struct dentry *d;
struct clk *pa = c->pclk;
char s[255];
char *p = s;
@@ -951,10 +951,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;
err_out:
- d = c->dent;
- list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(c->dent);
+ debugfs_remove_recursive(c->dent);
return err;
}
diff --git a/arch/arm/plat-spear/include/plat/clkdev.h b/arch/arm/plat-spear/include/plat/clkdev.h
deleted file mode 100644
index a2d0112fcaf7..000000000000
--- a/arch/arm/plat-spear/include/plat/clkdev.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/clkdev.h
- *
- * Clock Dev framework definitions 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_CLKDEV_H
-#define __PLAT_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif /* __PLAT_CLKDEV_H */
diff --git a/arch/arm/plat-tcc/include/mach/clkdev.h b/arch/arm/plat-tcc/include/mach/clkdev.h
deleted file mode 100644
index 04b37a89801c..000000000000
--- a/arch/arm/plat-tcc/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 9897dcfc16d6..2d30c7f6edd3 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -77,27 +77,27 @@ ENTRY(vfp_support_entry)
bne look_for_VFP_exceptions @ VFP is already enabled
DBGSTR1 "enable %x", r10
- ldr r3, last_VFP_context_address
+ ldr r3, vfp_current_hw_state_address
orr r1, r1, #FPEXC_EN @ user FPEXC has the enable bit set
- ldr r4, [r3, r11, lsl #2] @ last_VFP_context pointer
+ ldr r4, [r3, r11, lsl #2] @ vfp_current_hw_state pointer
bic r5, r1, #FPEXC_EX @ make sure exceptions are disabled
- cmp r4, r10
- beq check_for_exception @ we are returning to the same
- @ process, so the registers are
- @ still there. In this case, we do
- @ not want to drop a pending exception.
+ cmp r4, r10 @ this thread owns the hw context?
+#ifndef CONFIG_SMP
+ @ For UP, checking that this thread owns the hw context is
+ @ sufficient to determine that the hardware state is valid.
+ beq vfp_hw_state_valid
+
+ @ On UP, we lazily save the VFP context. As a different
+ @ thread wants ownership of the VFP hardware, save the old
+ @ state if there was a previous (valid) owner.
VFPFMXR FPEXC, r5 @ enable VFP, disable any pending
@ exceptions, so we can get at the
@ rest of it
-#ifndef CONFIG_SMP
- @ Save out the current registers to the old thread state
- @ No need for SMP since this is not done lazily
-
DBGSTR1 "save old state %p", r4
- cmp r4, #0
- beq no_old_VFP_process
+ cmp r4, #0 @ if the vfp_current_hw_state is NULL
+ beq vfp_reload_hw @ then the hw state needs reloading
VFPFSTMIA r4, r5 @ save the working registers
VFPFMRX r5, FPSCR @ current status
#ifndef CONFIG_CPU_FEROCEON
@@ -110,13 +110,35 @@ ENTRY(vfp_support_entry)
1:
#endif
stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2
- @ and point r4 at the word at the
- @ start of the register dump
+vfp_reload_hw:
+
+#else
+ @ For SMP, if this thread does not own the hw context, then we
+ @ need to reload it. No need to save the old state as on SMP,
+ @ we always save the state when we switch away from a thread.
+ bne vfp_reload_hw
+
+ @ This thread has ownership of the current hardware context.
+ @ However, it may have been migrated to another CPU, in which
+ @ case the saved state is newer than the hardware context.
+ @ Check this by looking at the CPU number which the state was
+ @ last loaded onto.
+ ldr ip, [r10, #VFP_CPU]
+ teq ip, r11
+ beq vfp_hw_state_valid
+
+vfp_reload_hw:
+ @ We're loading this threads state into the VFP hardware. Update
+ @ the CPU number which contains the most up to date VFP context.
+ str r11, [r10, #VFP_CPU]
+
+ VFPFMXR FPEXC, r5 @ enable VFP, disable any pending
+ @ exceptions, so we can get at the
+ @ rest of it
#endif
-no_old_VFP_process:
DBGSTR1 "load state %p", r10
- str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer
+ str r10, [r3, r11, lsl #2] @ update the vfp_current_hw_state pointer
@ Load the saved state back into the VFP
VFPFLDMIA r10, r5 @ reload the working registers while
@ FPEXC is in a safe state
@@ -132,7 +154,8 @@ no_old_VFP_process:
#endif
VFPFMXR FPSCR, r5 @ restore status
-check_for_exception:
+@ The context stored in the VFP hardware is up to date with this thread
+vfp_hw_state_valid:
tst r1, #FPEXC_EX
bne process_exception @ might as well handle the pending
@ exception before retrying branch
@@ -207,8 +230,8 @@ ENTRY(vfp_save_state)
ENDPROC(vfp_save_state)
.align
-last_VFP_context_address:
- .word last_VFP_context
+vfp_current_hw_state_address:
+ .word vfp_current_hw_state
.macro tbl_branch, base, tmp, shift
#ifdef CONFIG_THUMB2_KERNEL
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index f25e7ec89416..79bcb4316930 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -33,7 +33,6 @@ void vfp_support_entry(void);
void vfp_null_entry(void);
void (*vfp_vector)(void) = vfp_null_entry;
-union vfp_state *last_VFP_context[NR_CPUS];
/*
* Dual-use variable.
@@ -43,6 +42,46 @@ union vfp_state *last_VFP_context[NR_CPUS];
unsigned int VFP_arch;
/*
+ * The pointer to the vfpstate structure of the thread which currently
+ * owns the context held in the VFP hardware, or NULL if the hardware
+ * context is invalid.
+ *
+ * For UP, this is sufficient to tell which thread owns the VFP context.
+ * However, for SMP, we also need to check the CPU number stored in the
+ * saved state too to catch migrations.
+ */
+union vfp_state *vfp_current_hw_state[NR_CPUS];
+
+/*
+ * Is 'thread's most up to date state stored in this CPUs hardware?
+ * Must be called from non-preemptible context.
+ */
+static bool vfp_state_in_hw(unsigned int cpu, struct thread_info *thread)
+{
+#ifdef CONFIG_SMP
+ if (thread->vfpstate.hard.cpu != cpu)
+ return false;
+#endif
+ return vfp_current_hw_state[cpu] == &thread->vfpstate;
+}
+
+/*
+ * 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.
+ */
+static void vfp_force_reload(unsigned int cpu, struct thread_info *thread)
+{
+ if (vfp_state_in_hw(cpu, thread)) {
+ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
+ vfp_current_hw_state[cpu] = NULL;
+ }
+#ifdef CONFIG_SMP
+ thread->vfpstate.hard.cpu = NR_CPUS;
+#endif
+}
+
+/*
* Per-thread VFP initialization.
*/
static void vfp_thread_flush(struct thread_info *thread)
@@ -50,21 +89,27 @@ static void vfp_thread_flush(struct thread_info *thread)
union vfp_state *vfp = &thread->vfpstate;
unsigned int cpu;
- memset(vfp, 0, sizeof(union vfp_state));
-
- vfp->hard.fpexc = FPEXC_EN;
- vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
-
/*
* Disable VFP to ensure we initialize it first. We must ensure
- * that the modification of last_VFP_context[] and hardware disable
- * are done for the same CPU and without preemption.
+ * that the modification of vfp_current_hw_state[] and hardware
+ * disable are done for the same CPU and without preemption.
+ *
+ * Do this first to ensure that preemption won't overwrite our
+ * state saving should access to the VFP be enabled at this point.
*/
cpu = get_cpu();
- if (last_VFP_context[cpu] == vfp)
- last_VFP_context[cpu] = NULL;
+ if (vfp_current_hw_state[cpu] == vfp)
+ vfp_current_hw_state[cpu] = NULL;
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
put_cpu();
+
+ memset(vfp, 0, sizeof(union vfp_state));
+
+ vfp->hard.fpexc = FPEXC_EN;
+ vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
+#ifdef CONFIG_SMP
+ vfp->hard.cpu = NR_CPUS;
+#endif
}
static void vfp_thread_exit(struct thread_info *thread)
@@ -73,8 +118,8 @@ static void vfp_thread_exit(struct thread_info *thread)
union vfp_state *vfp = &thread->vfpstate;
unsigned int cpu = get_cpu();
- if (last_VFP_context[cpu] == vfp)
- last_VFP_context[cpu] = NULL;
+ if (vfp_current_hw_state[cpu] == vfp)
+ vfp_current_hw_state[cpu] = NULL;
put_cpu();
}
@@ -84,6 +129,9 @@ static void vfp_thread_copy(struct thread_info *thread)
vfp_sync_hwstate(parent);
thread->vfpstate = parent->vfpstate;
+#ifdef CONFIG_SMP
+ thread->vfpstate.hard.cpu = NR_CPUS;
+#endif
}
/*
@@ -129,17 +177,8 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
* case the thread migrates to a different CPU. The
* restoring is done lazily.
*/
- if ((fpexc & FPEXC_EN) && last_VFP_context[cpu]) {
- vfp_save_state(last_VFP_context[cpu], fpexc);
- last_VFP_context[cpu]->hard.cpu = cpu;
- }
- /*
- * Thread migration, just force the reloading of the
- * state on the new CPU in case the VFP registers
- * contain stale data.
- */
- if (thread->vfpstate.hard.cpu != cpu)
- last_VFP_context[cpu] = NULL;
+ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu])
+ vfp_save_state(vfp_current_hw_state[cpu], fpexc);
#endif
/*
@@ -415,7 +454,7 @@ static int vfp_pm_suspend(void)
}
/* clear any information we had about last context state */
- memset(last_VFP_context, 0, sizeof(last_VFP_context));
+ memset(vfp_current_hw_state, 0, sizeof(vfp_current_hw_state));
return 0;
}
@@ -443,15 +482,15 @@ static void vfp_pm_init(void)
static inline void vfp_pm_init(void) { }
#endif /* CONFIG_PM */
+/*
+ * Ensure that the VFP state stored in 'thread->vfpstate' is up to date
+ * with the hardware state.
+ */
void vfp_sync_hwstate(struct thread_info *thread)
{
unsigned int cpu = get_cpu();
- /*
- * If the thread we're interested in is the current owner of the
- * hardware VFP state, then we need to save its state.
- */
- if (last_VFP_context[cpu] == &thread->vfpstate) {
+ if (vfp_state_in_hw(cpu, thread)) {
u32 fpexc = fmrx(FPEXC);
/*
@@ -465,36 +504,13 @@ void vfp_sync_hwstate(struct thread_info *thread)
put_cpu();
}
+/* Ensure that the thread reloads the hardware VFP state on the next use. */
void vfp_flush_hwstate(struct thread_info *thread)
{
unsigned int cpu = get_cpu();
- /*
- * If the thread we're interested in is the current owner of the
- * hardware VFP state, then we need to save its state.
- */
- if (last_VFP_context[cpu] == &thread->vfpstate) {
- u32 fpexc = fmrx(FPEXC);
+ vfp_force_reload(cpu, thread);
- fmxr(FPEXC, fpexc & ~FPEXC_EN);
-
- /*
- * Set the context to NULL to force a reload the next time
- * the thread uses the VFP.
- */
- last_VFP_context[cpu] = NULL;
- }
-
-#ifdef CONFIG_SMP
- /*
- * For SMP we still have to take care of the case where the thread
- * migrates to another CPU and then back to the original CPU on which
- * the last VFP user is still the same thread. Mark the thread VFP
- * state as belonging to a non-existent CPU so that the saved one will
- * be reloaded in the above case.
- */
- thread->vfpstate.hard.cpu = NR_CPUS;
-#endif
put_cpu();
}
@@ -513,8 +529,7 @@ static int vfp_hotplug(struct notifier_block *b, unsigned long action,
void *hcpu)
{
if (action == CPU_DYING || action == CPU_DYING_FROZEN) {
- unsigned int cpu = (long)hcpu;
- last_VFP_context[cpu] = NULL;
+ vfp_force_reload((long)hcpu, current_thread_info());
} else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
vfp_enable(NULL);
return NOTIFY_OK;
@@ -582,7 +597,6 @@ static int __init vfp_init(void)
elf_hwcap |= HWCAP_VFPv3D16;
}
#endif
-#ifdef CONFIG_NEON
/*
* Check for the presence of the Advanced SIMD
* load/store instructions, integer and single
@@ -590,10 +604,13 @@ static int __init vfp_init(void)
* for NEON if the hardware has the MVFR registers.
*/
if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
+#ifdef CONFIG_NEON
if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
elf_hwcap |= HWCAP_NEON;
- }
#endif
+ if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000)
+ elf_hwcap |= HWCAP_VFPv4;
+ }
}
return 0;
}
diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h
index bbce6a1c6bb6..e0ac2631c87e 100644
--- a/arch/avr32/include/asm/atomic.h
+++ b/arch/avr32/include/asm/atomic.h
@@ -78,70 +78,63 @@ static inline int atomic_add_return(int i, atomic_t *v)
/*
* atomic_sub_unless - sub unless the number is a given value
* @v: pointer of type atomic_t
- * @a: the amount to add to v...
+ * @a: the amount to subtract from v...
* @u: ...unless v is equal to u.
*
- * If the atomic value v is not equal to u, this function subtracts a
- * from v, and returns non zero. If v is equal to u then it returns
- * zero. This is done as an atomic operation.
+ * Atomically subtract @a from @v, so long as it was not @u.
+ * Returns the old value of @v.
*/
-static inline int atomic_sub_unless(atomic_t *v, int a, int u)
+static inline void atomic_sub_unless(atomic_t *v, int a, int u)
{
- int tmp, result = 0;
+ int tmp;
asm volatile(
"/* atomic_sub_unless */\n"
"1: ssrf 5\n"
- " ld.w %0, %3\n"
- " cp.w %0, %5\n"
+ " ld.w %0, %2\n"
+ " cp.w %0, %4\n"
" breq 1f\n"
- " sub %0, %4\n"
- " stcond %2, %0\n"
+ " sub %0, %3\n"
+ " stcond %1, %0\n"
" brne 1b\n"
- " mov %1, 1\n"
"1:"
- : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
- : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result)
+ : "=&r"(tmp), "=o"(v->counter)
+ : "m"(v->counter), "rKs21"(a), "rKs21"(u)
: "cc", "memory");
-
- return result;
}
/*
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
- * If the atomic value v is not equal to u, this function adds a to v,
- * and returns non zero. If v is equal to u then it returns zero. This
- * is done as an atomic operation.
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns the old value of @v.
*/
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
- int tmp, result;
+ int tmp, old = atomic_read(v);
if (__builtin_constant_p(a) && (a >= -1048575) && (a <= 1048576))
- result = atomic_sub_unless(v, -a, u);
+ atomic_sub_unless(v, -a, u);
else {
- result = 0;
asm volatile(
- "/* atomic_add_unless */\n"
+ "/* __atomic_add_unless */\n"
"1: ssrf 5\n"
- " ld.w %0, %3\n"
- " cp.w %0, %5\n"
+ " ld.w %0, %2\n"
+ " cp.w %0, %4\n"
" breq 1f\n"
- " add %0, %4\n"
- " stcond %2, %0\n"
+ " add %0, %3\n"
+ " stcond %1, %0\n"
" brne 1b\n"
- " mov %1, 1\n"
"1:"
- : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
- : "m"(v->counter), "r"(a), "ir"(u), "1"(result)
+ : "=&r"(tmp), "=o"(v->counter)
+ : "m"(v->counter), "r"(a), "ir"(u)
: "cc", "memory");
}
- return result;
+ return old;
}
/*
@@ -188,7 +181,6 @@ static inline int atomic_sub_if_positive(int i, atomic_t *v)
#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
#define atomic_add_negative(i, v) (atomic_add_return(i, v) < 0)
-#define atomic_inc_not_zero(v) atomic_add_unless(v, 1, 0)
#define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v)
#define smp_mb__before_atomic_dec() barrier()
@@ -196,6 +188,4 @@ static inline int atomic_sub_if_positive(int i, atomic_t *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
-
#endif /* __ASM_AVR32_ATOMIC_H */
diff --git a/arch/avr32/include/asm/delay.h b/arch/avr32/include/asm/delay.h
index a0ed9a9839a5..9670e127b7b2 100644
--- a/arch/avr32/include/asm/delay.h
+++ b/arch/avr32/include/asm/delay.h
@@ -1,26 +1 @@
-#ifndef __ASM_AVR32_DELAY_H
-#define __ASM_AVR32_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/avr32/lib/delay.c
- */
-
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
- __udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
- __ndelay(n))
-
-#endif /* __ASM_AVR32_DELAY_H */
+#include <asm-generic/delay.h>
diff --git a/arch/avr32/include/asm/ptrace.h b/arch/avr32/include/asm/ptrace.h
index e53dd0d900f5..c67a007f672a 100644
--- a/arch/avr32/include/asm/ptrace.h
+++ b/arch/avr32/include/asm/ptrace.h
@@ -132,8 +132,6 @@ struct pt_regs {
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs (struct pt_regs *);
-
static __inline__ int valid_user_regs(struct pt_regs *regs)
{
/*
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
index a727f54d64d6..596f7305d93f 100644
--- a/arch/avr32/kernel/module.c
+++ b/arch/avr32/kernel/module.c
@@ -19,13 +19,6 @@
#include <linux/moduleloader.h>
#include <linux/vmalloc.h>
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc(size);
-}
-
void module_free(struct module *mod, void *module_region)
{
vfree(mod->arch.syminfo);
@@ -299,15 +292,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
return ret;
}
-int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relindex,
- struct module *module)
-{
- printk(KERN_ERR "module %s: REL relocations are not supported\n",
- module->name);
- return -ENOEXEC;
-}
-
int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
struct module *module)
{
@@ -316,7 +300,3 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
return 0;
}
-
-void module_arch_cleanup(struct module *module)
-{
-}
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index bb0974cce4ac..b4247f478065 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -444,7 +444,7 @@ static unsigned long __init
find_bootmap_pfn(const struct resource *mem)
{
unsigned long bootmap_pages, bootmap_len;
- unsigned long node_pages = PFN_UP(mem->end - mem->start + 1);
+ unsigned long node_pages = PFN_UP(resource_size(mem));
unsigned long bootmap_start;
bootmap_pages = bootmem_bootmap_pages(node_pages);
@@ -541,10 +541,10 @@ static void __init setup_bootmem(void)
*/
if (res->start >= PFN_PHYS(first_pfn)
&& res->end < PFN_PHYS(max_pfn))
- reserve_bootmem_node(
- NODE_DATA(node), res->start,
- res->end - res->start + 1,
- BOOTMEM_DEFAULT);
+ reserve_bootmem_node(NODE_DATA(node),
+ res->start,
+ resource_size(res),
+ BOOTMEM_DEFAULT);
}
node_set_online(node);
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index fbc2aeaebddb..cfb298d66305 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -204,7 +204,7 @@ static int __init eic_probe(struct platform_device *pdev)
}
eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
- eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ eic->regs = ioremap(regs->start, resource_size(regs));
if (!eic->regs) {
dev_dbg(&pdev->dev, "failed to map regs\n");
goto err_ioremap;
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index f7672d3e86b8..f66245e6e63e 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -245,7 +245,7 @@ static int hsmc_probe(struct platform_device *pdev)
hsmc->pclk = pclk;
hsmc->mck = mck;
- hsmc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ hsmc->regs = ioremap(regs->start, resource_size(regs));
if (!hsmc->regs)
goto out_disable_clocks;
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index c9ac2f8e8f64..258682bc1278 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -107,7 +107,7 @@ void __init init_IRQ(void)
clk_enable(pclk);
- intc0.regs = ioremap(regs->start, regs->end - regs->start + 1);
+ intc0.regs = ioremap(regs->start, resource_size(regs));
if (!intc0.regs) {
printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n",
(unsigned long)regs->start);
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 2e0aa853a4bc..9b39dea6682f 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -461,7 +461,7 @@ void __init at32_init_pio(struct platform_device *pdev)
clk_enable(pio->clk);
pio->pdev = pdev;
- pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ pio->regs = ioremap(regs->start, resource_size(regs));
/* start with irqs disabled and acked */
pio_writel(pio, IDR, ~0UL);
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index d619b17c4413..c7476295de80 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -953,6 +953,16 @@ config BFIN_GPTIMERS
To compile this driver as a module, choose M here: the module
will be called gptimers.
+config HAVE_PWM
+ tristate "Enable PWM API support"
+ depends on BFIN_GPTIMERS
+ help
+ Enable support for the Pulse Width Modulation framework (as
+ found in linux/pwm.h).
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm.
+
choice
prompt "Uncached DMA region"
default DMA_UNCACHED_1M
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 1c0a82a10591..d7ff2aee3fbc 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -58,13 +58,13 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=m
+CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=m
-CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_RAM=y
CONFIG_MTD_ROM=m
-CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9e7c5379d3ff..7a075eaf6041 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -1,5 +1,48 @@
include include/asm-generic/Kbuild.asm
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += bugs.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 += futex.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ipcbuf.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 += mman.h
+generic-y += msgbuf.h
+generic-y += param.h
+generic-y += percpu.h
+generic-y += pgalloc.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sembuf.h
+generic-y += serial.h
+generic-y += setup.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.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 += user.h
+generic-y += xor.h
+
header-y += bfin_sport.h
header-y += cachectl.h
header-y += fixed_code.h
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index e48508957160..135225696fd2 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef __ARCH_BLACKFIN_ATOMIC__
#define __ARCH_BLACKFIN_ATOMIC__
@@ -76,11 +76,6 @@ static inline void atomic_set_mask(int mask, atomic_t *v)
__raw_atomic_set_asm(&v->counter, mask);
}
-static inline int atomic_test_mask(int mask, atomic_t *v)
-{
- return __raw_atomic_test_asm(&v->counter, mask);
-}
-
/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
@@ -94,15 +89,14 @@ static inline int atomic_test_mask(int mask, atomic_t *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) \
+#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 != (u); \
+ c; \
})
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
/*
* atomic_inc_and_test - increment and test
@@ -117,10 +111,7 @@ static inline int atomic_test_mask(int mask, atomic_t *v)
#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)
-#include <asm-generic/atomic-long.h>
#endif
-#include <asm-generic/atomic64.h>
-
#endif
diff --git a/arch/blackfin/include/asm/auxvec.h b/arch/blackfin/include/asm/auxvec.h
deleted file mode 100644
index 41fa68b71287..000000000000
--- a/arch/blackfin/include/asm/auxvec.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/auxvec.h>
diff --git a/arch/blackfin/include/asm/bitsperlong.h b/arch/blackfin/include/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0c13b2..000000000000
--- a/arch/blackfin/include/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/blackfin/include/asm/blackfin.h b/arch/blackfin/include/asm/blackfin.h
index eb7c1441d8f9..0928700b6bc4 100644
--- a/arch/blackfin/include/asm/blackfin.h
+++ b/arch/blackfin/include/asm/blackfin.h
@@ -1,9 +1,9 @@
/*
* Common header file for Blackfin family of processors.
*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
*/
#ifndef _BLACKFIN_H_
diff --git a/arch/blackfin/include/asm/bugs.h b/arch/blackfin/include/asm/bugs.h
deleted file mode 100644
index 61791e1ad9f5..000000000000
--- a/arch/blackfin/include/asm/bugs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bugs.h>
diff --git a/arch/blackfin/include/asm/cputime.h b/arch/blackfin/include/asm/cputime.h
deleted file mode 100644
index 6d68ad7e0ea3..000000000000
--- a/arch/blackfin/include/asm/cputime.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/cputime.h>
diff --git a/arch/blackfin/include/asm/current.h b/arch/blackfin/include/asm/current.h
deleted file mode 100644
index 4c51401b5537..000000000000
--- a/arch/blackfin/include/asm/current.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/current.h>
diff --git a/arch/blackfin/include/asm/device.h b/arch/blackfin/include/asm/device.h
deleted file mode 100644
index f0a4c256403b..000000000000
--- a/arch/blackfin/include/asm/device.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/device.h>
diff --git a/arch/blackfin/include/asm/div64.h b/arch/blackfin/include/asm/div64.h
deleted file mode 100644
index 6cd978cefb28..000000000000
--- a/arch/blackfin/include/asm/div64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h
index d9dbc1a53534..dac0c97242bb 100644
--- a/arch/blackfin/include/asm/dma.h
+++ b/arch/blackfin/include/asm/dma.h
@@ -10,7 +10,7 @@
#include <linux/interrupt.h>
#include <mach/dma.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/blackfin.h>
#include <asm/page.h>
#include <asm-generic/dma.h>
diff --git a/arch/blackfin/include/asm/dpmc.h b/arch/blackfin/include/asm/dpmc.h
index edf2a2ad5183..c4ec959dad78 100644
--- a/arch/blackfin/include/asm/dpmc.h
+++ b/arch/blackfin/include/asm/dpmc.h
@@ -117,7 +117,6 @@
#ifndef __ASSEMBLY__
void sleep_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
-void hibernate_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
void sleep_deeper(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
void do_hibernate(int wakeup);
void set_dram_srfs(void);
@@ -134,32 +133,6 @@ struct bfin_dpmc_platform_data {
unsigned short vr_settling_time; /* in us */
};
-#else
-
-#define PM_PUSH(x) \
- R0 = [P0 + (x - SRAM_BASE_ADDRESS)];\
- [--SP] = R0;\
-
-#define PM_POP(x) \
- R0 = [SP++];\
- [P0 + (x - SRAM_BASE_ADDRESS)] = R0;\
-
-#define PM_SYS_PUSH(x) \
- R0 = [P0 + (x - PLL_CTL)];\
- [--SP] = R0;\
-
-#define PM_SYS_POP(x) \
- R0 = [SP++];\
- [P0 + (x - PLL_CTL)] = R0;\
-
-#define PM_SYS_PUSH16(x) \
- R0 = w[P0 + (x - PLL_CTL)];\
- [--SP] = R0;\
-
-#define PM_SYS_POP16(x) \
- R0 = [SP++];\
- w[P0 + (x - PLL_CTL)] = R0;\
-
#endif
#endif /*_BLACKFIN_DPMC_H_*/
diff --git a/arch/blackfin/include/asm/emergency-restart.h b/arch/blackfin/include/asm/emergency-restart.h
deleted file mode 100644
index 3711bd9d50bd..000000000000
--- a/arch/blackfin/include/asm/emergency-restart.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/emergency-restart.h>
diff --git a/arch/blackfin/include/asm/errno.h b/arch/blackfin/include/asm/errno.h
deleted file mode 100644
index 4c82b503d92f..000000000000
--- a/arch/blackfin/include/asm/errno.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/errno.h>
diff --git a/arch/blackfin/include/asm/fb.h b/arch/blackfin/include/asm/fb.h
deleted file mode 100644
index 3a4988e8df45..000000000000
--- a/arch/blackfin/include/asm/fb.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fb.h>
diff --git a/arch/blackfin/include/asm/futex.h b/arch/blackfin/include/asm/futex.h
deleted file mode 100644
index 0b745828f42b..000000000000
--- a/arch/blackfin/include/asm/futex.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/futex.h>
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 1ef8417f5d27..5a25856381ff 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -16,58 +16,13 @@
#include <mach/gpio.h>
-#define GPIO_0 0
-#define GPIO_1 1
-#define GPIO_2 2
-#define GPIO_3 3
-#define GPIO_4 4
-#define GPIO_5 5
-#define GPIO_6 6
-#define GPIO_7 7
-#define GPIO_8 8
-#define GPIO_9 9
-#define GPIO_10 10
-#define GPIO_11 11
-#define GPIO_12 12
-#define GPIO_13 13
-#define GPIO_14 14
-#define GPIO_15 15
-#define GPIO_16 16
-#define GPIO_17 17
-#define GPIO_18 18
-#define GPIO_19 19
-#define GPIO_20 20
-#define GPIO_21 21
-#define GPIO_22 22
-#define GPIO_23 23
-#define GPIO_24 24
-#define GPIO_25 25
-#define GPIO_26 26
-#define GPIO_27 27
-#define GPIO_28 28
-#define GPIO_29 29
-#define GPIO_30 30
-#define GPIO_31 31
-#define GPIO_32 32
-#define GPIO_33 33
-#define GPIO_34 34
-#define GPIO_35 35
-#define GPIO_36 36
-#define GPIO_37 37
-#define GPIO_38 38
-#define GPIO_39 39
-#define GPIO_40 40
-#define GPIO_41 41
-#define GPIO_42 42
-#define GPIO_43 43
-#define GPIO_44 44
-#define GPIO_45 45
-#define GPIO_46 46
-#define GPIO_47 47
-
#define PERIPHERAL_USAGE 1
#define GPIO_USAGE 0
+#ifndef BFIN_GPIO_PINT
+# define BFIN_GPIO_PINT 0
+#endif
+
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
@@ -89,7 +44,7 @@
* MODIFICATION HISTORY :
**************************************************************/
-#ifndef CONFIG_BF54x
+#if !BFIN_GPIO_PINT
void set_gpio_dir(unsigned, unsigned short);
void set_gpio_inen(unsigned, unsigned short);
void set_gpio_polar(unsigned, unsigned short);
@@ -164,6 +119,10 @@ struct gpio_port_t {
#ifdef BFIN_SPECIAL_GPIO_BANKS
void bfin_special_gpio_free(unsigned gpio);
int bfin_special_gpio_request(unsigned gpio, const char *label);
+# ifdef CONFIG_PM
+void bfin_special_gpio_pm_hibernate_restore(void);
+void bfin_special_gpio_pm_hibernate_suspend(void);
+# endif
#endif
#ifdef CONFIG_PM
@@ -182,7 +141,7 @@ static inline void bfin_pm_standby_restore(void)
void bfin_gpio_pm_hibernate_restore(void);
void bfin_gpio_pm_hibernate_suspend(void);
-#ifndef CONFIG_BF54x
+# if !BFIN_GPIO_PINT
int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
struct gpio_port_s {
@@ -199,8 +158,9 @@ struct gpio_port_s {
unsigned short reserved;
unsigned short mux;
};
-#endif /*CONFIG_BF54x*/
+# endif
#endif /*CONFIG_PM*/
+
/***********************************************************
*
* FUNCTIONS: Blackfin GPIO Driver
diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h
index 38657dac1235..38bddcb190c8 100644
--- a/arch/blackfin/include/asm/gptimers.h
+++ b/arch/blackfin/include/asm/gptimers.h
@@ -193,6 +193,16 @@ uint16_t get_enabled_gptimers(void);
uint32_t get_gptimer_status(unsigned int group);
void set_gptimer_status(unsigned int group, uint32_t value);
+static inline void enable_gptimer(unsigned int timer_id)
+{
+ enable_gptimers(1 << timer_id);
+}
+
+static inline void disable_gptimer(unsigned int timer_id)
+{
+ disable_gptimers(1 << timer_id);
+}
+
/*
* All Blackfin system MMRs are padded to 32bits even if the register
* itself is only 16bits. So use a helper macro to streamline this.
@@ -209,6 +219,15 @@ struct bfin_gptimer_regs {
u32 width;
};
+/*
+ * bfin group timer registers layout
+ */
+struct bfin_gptimer_group_regs {
+ __BFP(enable);
+ __BFP(disable);
+ u32 status;
+};
+
#undef __BFP
#endif
diff --git a/arch/blackfin/include/asm/hw_irq.h b/arch/blackfin/include/asm/hw_irq.h
deleted file mode 100644
index 1f5ef7da0045..000000000000
--- a/arch/blackfin/include/asm/hw_irq.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hw_irq.h>
diff --git a/arch/blackfin/include/asm/ioctl.h b/arch/blackfin/include/asm/ioctl.h
deleted file mode 100644
index b279fe06dfe5..000000000000
--- a/arch/blackfin/include/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/blackfin/include/asm/ipcbuf.h b/arch/blackfin/include/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51cb6d0..000000000000
--- a/arch/blackfin/include/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
index 9e0cc0e2534f..17b5e92e3bc6 100644
--- a/arch/blackfin/include/asm/ipipe.h
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -32,7 +32,7 @@
#include <asm/ptrace.h>
#include <asm/irq.h>
#include <asm/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/traps.h>
#include <asm/bitsperlong.h>
diff --git a/arch/blackfin/include/asm/irq_regs.h b/arch/blackfin/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b70270..000000000000
--- a/arch/blackfin/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h
index b4bbb75a9e15..43eb4749de3d 100644
--- a/arch/blackfin/include/asm/irqflags.h
+++ b/arch/blackfin/include/asm/irqflags.h
@@ -18,12 +18,12 @@
extern unsigned long bfin_irq_flags;
#endif
-static inline void bfin_sti(unsigned long flags)
+static inline notrace void bfin_sti(unsigned long flags)
{
asm volatile("sti %0;" : : "d" (flags));
}
-static inline unsigned long bfin_cli(void)
+static inline notrace unsigned long bfin_cli(void)
{
unsigned long flags;
asm volatile("cli %0;" : "=d" (flags));
@@ -40,22 +40,22 @@ static inline unsigned long bfin_cli(void)
/*
* Hard, untraced CPU interrupt flag manipulation and access.
*/
-static inline void __hard_local_irq_disable(void)
+static inline notrace void __hard_local_irq_disable(void)
{
bfin_cli();
}
-static inline void __hard_local_irq_enable(void)
+static inline notrace void __hard_local_irq_enable(void)
{
bfin_sti(bfin_irq_flags);
}
-static inline unsigned long hard_local_save_flags(void)
+static inline notrace unsigned long hard_local_save_flags(void)
{
return bfin_read_IMASK();
}
-static inline unsigned long __hard_local_irq_save(void)
+static inline notrace unsigned long __hard_local_irq_save(void)
{
unsigned long flags;
flags = bfin_cli();
@@ -65,18 +65,18 @@ static inline unsigned long __hard_local_irq_save(void)
return flags;
}
-static inline int hard_irqs_disabled_flags(unsigned long flags)
+static inline notrace int hard_irqs_disabled_flags(unsigned long flags)
{
return (flags & ~0x3f) == 0;
}
-static inline int hard_irqs_disabled(void)
+static inline notrace int hard_irqs_disabled(void)
{
unsigned long flags = hard_local_save_flags();
return hard_irqs_disabled_flags(flags);
}
-static inline void __hard_local_irq_restore(unsigned long flags)
+static inline notrace void __hard_local_irq_restore(unsigned long flags)
{
if (!hard_irqs_disabled_flags(flags))
__hard_local_irq_enable();
@@ -113,31 +113,31 @@ void ipipe_check_context(struct ipipe_domain *ipd);
/*
* Interrupt pipe interface to linux/irqflags.h.
*/
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
{
__check_irqop_context();
__ipipe_stall_root();
barrier();
}
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
{
barrier();
__check_irqop_context();
__ipipe_unstall_root();
}
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
{
return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
}
-static inline int arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
{
return flags == bfin_no_irqs;
}
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
{
unsigned long flags;
@@ -148,13 +148,13 @@ static inline unsigned long arch_local_irq_save(void)
return flags;
}
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
{
__check_irqop_context();
__ipipe_restore_root(flags == bfin_no_irqs);
}
-static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
+static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
{
/*
* Merge virtual and real interrupt mask bits into a single
@@ -163,7 +163,7 @@ static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
return (real & ~(1 << 31)) | ((virt != 0) << 31);
}
-static inline int arch_demangle_irq_bits(unsigned long *x)
+static inline notrace int arch_demangle_irq_bits(unsigned long *x)
{
int virt = (*x & (1 << 31)) != 0;
*x &= ~(1L << 31);
@@ -174,7 +174,7 @@ static inline int arch_demangle_irq_bits(unsigned long *x)
* Interface to various arch routines that may be traced.
*/
#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
-static inline void hard_local_irq_disable(void)
+static inline notrace void hard_local_irq_disable(void)
{
if (!hard_irqs_disabled()) {
__hard_local_irq_disable();
@@ -182,7 +182,7 @@ static inline void hard_local_irq_disable(void)
}
}
-static inline void hard_local_irq_enable(void)
+static inline notrace void hard_local_irq_enable(void)
{
if (hard_irqs_disabled()) {
ipipe_trace_end(0x80000000);
@@ -190,7 +190,7 @@ static inline void hard_local_irq_enable(void)
}
}
-static inline unsigned long hard_local_irq_save(void)
+static inline notrace unsigned long hard_local_irq_save(void)
{
unsigned long flags = hard_local_save_flags();
if (!hard_irqs_disabled_flags(flags)) {
@@ -200,7 +200,7 @@ static inline unsigned long hard_local_irq_save(void)
return flags;
}
-static inline void hard_local_irq_restore(unsigned long flags)
+static inline notrace void hard_local_irq_restore(unsigned long flags)
{
if (!hard_irqs_disabled_flags(flags)) {
ipipe_trace_end(0x80000001);
diff --git a/arch/blackfin/include/asm/kdebug.h b/arch/blackfin/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b037665..000000000000
--- a/arch/blackfin/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/blackfin/include/asm/kmap_types.h b/arch/blackfin/include/asm/kmap_types.h
deleted file mode 100644
index 3575c64af42a..000000000000
--- a/arch/blackfin/include/asm/kmap_types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kmap_types.h>
diff --git a/arch/blackfin/include/asm/local.h b/arch/blackfin/include/asm/local.h
deleted file mode 100644
index c11c530f74d0..000000000000
--- a/arch/blackfin/include/asm/local.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/blackfin/include/asm/local64.h b/arch/blackfin/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/blackfin/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/blackfin/include/asm/mman.h b/arch/blackfin/include/asm/mman.h
deleted file mode 100644
index 8eebf89f5ab1..000000000000
--- a/arch/blackfin/include/asm/mman.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mman.h>
diff --git a/arch/blackfin/include/asm/module.h b/arch/blackfin/include/asm/module.h
index 4282b169ead9..ed5689b82c9f 100644
--- a/arch/blackfin/include/asm/module.h
+++ b/arch/blackfin/include/asm/module.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef _ASM_BFIN_MODULE_H
#define _ASM_BFIN_MODULE_H
diff --git a/arch/blackfin/include/asm/msgbuf.h b/arch/blackfin/include/asm/msgbuf.h
deleted file mode 100644
index 809134c644a6..000000000000
--- a/arch/blackfin/include/asm/msgbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/msgbuf.h>
diff --git a/arch/blackfin/include/asm/mutex.h b/arch/blackfin/include/asm/mutex.h
index f726e3a80ad0..ff6101aa2c71 100644
--- a/arch/blackfin/include/asm/mutex.h
+++ b/arch/blackfin/include/asm/mutex.h
@@ -1,76 +1 @@
-/*
- * 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)
- *
- * Copyright 2006-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
-
-#ifndef CONFIG_SMP
-#include <asm-generic/mutex.h>
-#else
-
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(atomic_dec_return(count) < 0))
- fail_fn(count);
- else
- smp_mb();
-}
-
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- if (unlikely(atomic_dec_return(count) < 0))
- return fail_fn(count);
- else {
- smp_mb();
- return 0;
- }
-}
-
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- smp_mb();
- if (unlikely(atomic_inc_return(count) <= 0))
- fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock() 1
-
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- /*
- * We have two variants here. The cmpxchg based one is the best one
- * because it never induce a false contention state. It is included
- * here because architectures using the inc/dec algorithms over the
- * xchg ones are much more likely to support cmpxchg natively.
- *
- * If not we fall back to the spinlock based variant - that is
- * just as efficient (and simpler) as a 'destructive' probing of
- * the mutex state would be.
- */
-#ifdef __HAVE_ARCH_CMPXCHG
- if (likely(atomic_cmpxchg(count, 1, 0) == 1)) {
- smp_mb();
- return 1;
- }
- return 0;
-#else
- return fail_fn(count);
-#endif
-}
-
-#endif
-
-#endif
+#include <asm-generic/mutex-dec.h>
diff --git a/arch/blackfin/include/asm/page.h b/arch/blackfin/include/asm/page.h
index d0ce975bcd48..7202404966f6 100644
--- a/arch/blackfin/include/asm/page.h
+++ b/arch/blackfin/include/asm/page.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef _BLACKFIN_PAGE_H
#define _BLACKFIN_PAGE_H
diff --git a/arch/blackfin/include/asm/param.h b/arch/blackfin/include/asm/param.h
deleted file mode 100644
index 965d45427975..000000000000
--- a/arch/blackfin/include/asm/param.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h
index d49bb261d9b7..28c2498c9c98 100644
--- a/arch/blackfin/include/asm/pda.h
+++ b/arch/blackfin/include/asm/pda.h
@@ -54,6 +54,16 @@ struct blackfin_pda { /* Per-processor Data Area */
#endif
};
+struct blackfin_initial_pda {
+ void *retx;
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+ void *dcplb_doublefault_addr;
+ void *icplb_doublefault_addr;
+ void *retx_doublefault;
+ unsigned seqstat_doublefault;
+#endif
+};
+
extern struct blackfin_pda cpu_pda[];
#endif /* __ASSEMBLY__ */
diff --git a/arch/blackfin/include/asm/percpu.h b/arch/blackfin/include/asm/percpu.h
deleted file mode 100644
index 06a959d67234..000000000000
--- a/arch/blackfin/include/asm/percpu.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/percpu.h>
diff --git a/arch/blackfin/include/asm/pgalloc.h b/arch/blackfin/include/asm/pgalloc.h
deleted file mode 100644
index f261cb7dda06..000000000000
--- a/arch/blackfin/include/asm/pgalloc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/pgalloc.h>
diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h
index 7854d4367c15..10d8641180f2 100644
--- a/arch/blackfin/include/asm/ptrace.h
+++ b/arch/blackfin/include/asm/ptrace.h
@@ -102,7 +102,6 @@ struct pt_regs {
/* user_mode returns true if only one bit is set in IPEND, other than the
master interrupt enable. */
#define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
-extern void show_regs(struct pt_regs *);
#define arch_has_single_step() (1)
/* common code demands this function */
diff --git a/arch/blackfin/include/asm/resource.h b/arch/blackfin/include/asm/resource.h
deleted file mode 100644
index 04bc4db8921b..000000000000
--- a/arch/blackfin/include/asm/resource.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/resource.h>
diff --git a/arch/blackfin/include/asm/scatterlist.h b/arch/blackfin/include/asm/scatterlist.h
deleted file mode 100644
index d177a1588958..000000000000
--- a/arch/blackfin/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _BLACKFIN_SCATTERLIST_H
-#define _BLACKFIN_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(_BLACKFIN_SCATTERLIST_H) */
diff --git a/arch/blackfin/include/asm/sections.h b/arch/blackfin/include/asm/sections.h
index 14a3e66d9167..fbd408475725 100644
--- a/arch/blackfin/include/asm/sections.h
+++ b/arch/blackfin/include/asm/sections.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef _BLACKFIN_SECTIONS_H
#define _BLACKFIN_SECTIONS_H
diff --git a/arch/blackfin/include/asm/sembuf.h b/arch/blackfin/include/asm/sembuf.h
deleted file mode 100644
index 7673b83cfef7..000000000000
--- a/arch/blackfin/include/asm/sembuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sembuf.h>
diff --git a/arch/blackfin/include/asm/serial.h b/arch/blackfin/include/asm/serial.h
deleted file mode 100644
index a0cb0caff152..000000000000
--- a/arch/blackfin/include/asm/serial.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/serial.h>
diff --git a/arch/blackfin/include/asm/setup.h b/arch/blackfin/include/asm/setup.h
deleted file mode 100644
index 552df83f1a49..000000000000
--- a/arch/blackfin/include/asm/setup.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/setup.h>
diff --git a/arch/blackfin/include/asm/shmbuf.h b/arch/blackfin/include/asm/shmbuf.h
deleted file mode 100644
index 83c05fc2de38..000000000000
--- a/arch/blackfin/include/asm/shmbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmbuf.h>
diff --git a/arch/blackfin/include/asm/shmparam.h b/arch/blackfin/include/asm/shmparam.h
deleted file mode 100644
index 93f30deb95d0..000000000000
--- a/arch/blackfin/include/asm/shmparam.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmparam.h>
diff --git a/arch/blackfin/include/asm/sigcontext.h b/arch/blackfin/include/asm/sigcontext.h
index ce4081a4d815..906bdc1f5fda 100644
--- a/arch/blackfin/include/asm/sigcontext.h
+++ b/arch/blackfin/include/asm/sigcontext.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef _ASM_BLACKFIN_SIGCONTEXT_H
#define _ASM_BLACKFIN_SIGCONTEXT_H
diff --git a/arch/blackfin/include/asm/socket.h b/arch/blackfin/include/asm/socket.h
deleted file mode 100644
index 6b71384b9d8b..000000000000
--- a/arch/blackfin/include/asm/socket.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/socket.h>
diff --git a/arch/blackfin/include/asm/sockios.h b/arch/blackfin/include/asm/sockios.h
deleted file mode 100644
index def6d4746ee7..000000000000
--- a/arch/blackfin/include/asm/sockios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sockios.h>
diff --git a/arch/blackfin/include/asm/spinlock.h b/arch/blackfin/include/asm/spinlock.h
index 1f286e71c21f..490c7caa02d9 100644
--- a/arch/blackfin/include/asm/spinlock.h
+++ b/arch/blackfin/include/asm/spinlock.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef __BFIN_SPINLOCK_H
#define __BFIN_SPINLOCK_H
@@ -11,7 +11,7 @@
# include <asm-generic/spinlock.h>
#else
-#include <asm/atomic.h>
+#include <linux/atomic.h>
asmlinkage int __raw_spin_is_locked_asm(volatile int *ptr);
asmlinkage void __raw_spin_lock_asm(volatile int *ptr);
diff --git a/arch/blackfin/include/asm/statfs.h b/arch/blackfin/include/asm/statfs.h
deleted file mode 100644
index 0b91fe198c20..000000000000
--- a/arch/blackfin/include/asm/statfs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/statfs.h>
diff --git a/arch/blackfin/include/asm/termbits.h b/arch/blackfin/include/asm/termbits.h
deleted file mode 100644
index 3935b106de79..000000000000
--- a/arch/blackfin/include/asm/termbits.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termbits.h>
diff --git a/arch/blackfin/include/asm/termios.h b/arch/blackfin/include/asm/termios.h
deleted file mode 100644
index 280d78a9d966..000000000000
--- a/arch/blackfin/include/asm/termios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termios.h>
diff --git a/arch/blackfin/include/asm/topology.h b/arch/blackfin/include/asm/topology.h
deleted file mode 100644
index 5428f333a02c..000000000000
--- a/arch/blackfin/include/asm/topology.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/topology.h>
diff --git a/arch/blackfin/include/asm/types.h b/arch/blackfin/include/asm/types.h
deleted file mode 100644
index b9e79bc580dd..000000000000
--- a/arch/blackfin/include/asm/types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/types.h>
diff --git a/arch/blackfin/include/asm/ucontext.h b/arch/blackfin/include/asm/ucontext.h
deleted file mode 100644
index 9bc07b9f30fb..000000000000
--- a/arch/blackfin/include/asm/ucontext.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ucontext.h>
diff --git a/arch/blackfin/include/asm/unaligned.h b/arch/blackfin/include/asm/unaligned.h
deleted file mode 100644
index 6cecbbb2111f..000000000000
--- a/arch/blackfin/include/asm/unaligned.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/unaligned.h>
diff --git a/arch/blackfin/include/asm/user.h b/arch/blackfin/include/asm/user.h
deleted file mode 100644
index 4792a60831e4..000000000000
--- a/arch/blackfin/include/asm/user.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/user.h>
diff --git a/arch/blackfin/include/asm/xor.h b/arch/blackfin/include/asm/xor.h
deleted file mode 100644
index c82eb12a5b18..000000000000
--- a/arch/blackfin/include/asm/xor.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/xor.h>
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index d550b24d9e9b..b7bdc42fe1a3 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
CFLAGS_REMOVE_ftrace.o = -pg
+obj-$(CONFIG_HAVE_PWM) += pwm.o
obj-$(CONFIG_IPIPE) += ipipe.o
obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
obj-$(CONFIG_CPLB_INFO) += cplbinfo.o
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index bd32c09b9349..17e35465a416 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -138,6 +138,16 @@ int main(void)
DEFINE(PDA_DF_SEQSTAT, offsetof(struct blackfin_pda, seqstat_doublefault));
DEFINE(PDA_DF_RETX, offsetof(struct blackfin_pda, retx_doublefault));
#endif
+
+ /* PDA initial management */
+ DEFINE(PDA_INIT_RETX, offsetof(struct blackfin_initial_pda, retx));
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+ DEFINE(PDA_INIT_DF_DCPLB, offsetof(struct blackfin_initial_pda, dcplb_doublefault_addr));
+ DEFINE(PDA_INIT_DF_ICPLB, offsetof(struct blackfin_initial_pda, icplb_doublefault_addr));
+ DEFINE(PDA_INIT_DF_SEQSTAT, offsetof(struct blackfin_initial_pda, seqstat_doublefault));
+ DEFINE(PDA_INIT_DF_RETX, offsetof(struct blackfin_initial_pda, retx_doublefault));
+#endif
+
#ifdef CONFIG_SMP
/* Inter-core lock (in L2 SRAM) */
DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index bcf8cf6fe412..02796b88443d 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -118,6 +118,9 @@ static struct str_ident {
#if defined(CONFIG_PM)
static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
+# ifdef BF538_FAMILY
+static unsigned short port_fer_saved[3];
+# endif
#endif
static void gpio_error(unsigned gpio)
@@ -604,6 +607,11 @@ void bfin_gpio_pm_hibernate_suspend(void)
{
int i, bank;
+#ifdef BF538_FAMILY
+ for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
+ port_fer_saved[i] = *port_fer[i];
+#endif
+
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
@@ -625,6 +633,10 @@ void bfin_gpio_pm_hibernate_suspend(void)
gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
}
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+ bfin_special_gpio_pm_hibernate_suspend();
+#endif
+
AWA_DUMMY_READ(maska);
}
@@ -632,6 +644,11 @@ void bfin_gpio_pm_hibernate_restore(void)
{
int i, bank;
+#ifdef BF538_FAMILY
+ for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
+ *port_fer[i] = port_fer_saved[i];
+#endif
+
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
@@ -653,6 +670,11 @@ void bfin_gpio_pm_hibernate_restore(void)
gpio_array[bank]->both = gpio_bank_saved[bank].both;
gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
}
+
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+ bfin_special_gpio_pm_hibernate_restore();
+#endif
+
AWA_DUMMY_READ(maska);
}
@@ -691,9 +713,9 @@ void bfin_gpio_pm_hibernate_restore(void)
gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
- gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
gpio_array[bank]->data_set = gpio_bank_saved[bank].data
- | gpio_bank_saved[bank].dir;
+ & gpio_bank_saved[bank].dir;
+ gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
}
}
#endif
diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c
index fce4807ceef9..92f664826281 100644
--- a/arch/blackfin/kernel/debug-mmrs.c
+++ b/arch/blackfin/kernel/debug-mmrs.c
@@ -27,7 +27,7 @@
#define PORT_MUX BFIN_PORT_MUX
#endif
-#define _d(name, bits, addr, perms) debugfs_create_x##bits(name, perms, parent, (u##bits *)addr)
+#define _d(name, bits, addr, perms) debugfs_create_x##bits(name, perms, parent, (u##bits *)(addr))
#define d(name, bits, addr) _d(name, bits, addr, S_IRUSR|S_IWUSR)
#define d_RO(name, bits, addr) _d(name, bits, addr, S_IRUSR)
#define d_WO(name, bits, addr) _d(name, bits, addr, S_IWUSR)
@@ -223,7 +223,8 @@ bfin_debug_mmrs_dma(struct dentry *parent, unsigned long base, int num, char mdm
__DMA(CURR_DESC_PTR, curr_desc_ptr);
__DMA(CURR_ADDR, curr_addr);
__DMA(IRQ_STATUS, irq_status);
- __DMA(PERIPHERAL_MAP, peripheral_map);
+ if (strcmp(pfx, "IMDMA") != 0)
+ __DMA(PERIPHERAL_MAP, peripheral_map);
__DMA(CURR_X_COUNT, curr_x_count);
__DMA(CURR_Y_COUNT, curr_y_count);
}
@@ -277,6 +278,32 @@ bfin_debug_mmrs_gptimer(struct dentry *parent, unsigned long base, int num)
}
#define GPTIMER(num) bfin_debug_mmrs_gptimer(parent, TIMER##num##_CONFIG, num)
+#define GPTIMER_GROUP_OFF(mmr) REGS_OFF(gptimer_group, mmr)
+#define __GPTIMER_GROUP(uname, lname) __REGS(gptimer_group, #uname, lname)
+static void __init __maybe_unused
+bfin_debug_mmrs_gptimer_group(struct dentry *parent, unsigned long base, int num)
+{
+ char buf[32], *_buf;
+
+ if (num == -1) {
+ _buf = buf + sprintf(buf, "TIMER_");
+ __GPTIMER_GROUP(ENABLE, enable);
+ __GPTIMER_GROUP(DISABLE, disable);
+ __GPTIMER_GROUP(STATUS, status);
+ } else {
+ /* These MMRs are a bit odd as the group # is a suffix */
+ _buf = buf + sprintf(buf, "TIMER_ENABLE%i", num);
+ d(buf, 16, base + GPTIMER_GROUP_OFF(enable));
+
+ _buf = buf + sprintf(buf, "TIMER_DISABLE%i", num);
+ d(buf, 16, base + GPTIMER_GROUP_OFF(disable));
+
+ _buf = buf + sprintf(buf, "TIMER_STATUS%i", num);
+ d(buf, 32, base + GPTIMER_GROUP_OFF(status));
+ }
+}
+#define GPTIMER_GROUP(mmr, num) bfin_debug_mmrs_gptimer_group(parent, mmr, num)
+
/*
* Handshake MDMA
*/
@@ -296,6 +323,29 @@ bfin_debug_mmrs_hmdma(struct dentry *parent, unsigned long base, int num)
#define HMDMA(num) bfin_debug_mmrs_hmdma(parent, HMDMA##num##_CONTROL, num)
/*
+ * Peripheral Interrupts (PINT/GPIO)
+ */
+#ifdef PINT0_MASK_SET
+#define __PINT(uname, lname) __REGS(pint, #uname, lname)
+static void __init __maybe_unused
+bfin_debug_mmrs_pint(struct dentry *parent, unsigned long base, int num)
+{
+ char buf[32], *_buf = REGS_STR_PFX(buf, PINT, num);
+ __PINT(MASK_SET, mask_set);
+ __PINT(MASK_CLEAR, mask_clear);
+ __PINT(REQUEST, request);
+ __PINT(ASSIGN, assign);
+ __PINT(EDGE_SET, edge_set);
+ __PINT(EDGE_CLEAR, edge_clear);
+ __PINT(INVERT_SET, invert_set);
+ __PINT(INVERT_CLEAR, invert_clear);
+ __PINT(PINSTATE, pinstate);
+ __PINT(LATCH, latch);
+}
+#define PINT(num) bfin_debug_mmrs_pint(parent, PINT##num##_MASK_SET, num)
+#endif
+
+/*
* Port/GPIO
*/
#define bfin_gpio_regs gpio_port_t
@@ -747,7 +797,7 @@ static int __init bfin_debug_mmrs_init(void)
#endif
parent = debugfs_create_dir("dmac", top);
-#ifdef DMA_TC_CNT
+#ifdef DMAC_TC_CNT
D16(DMAC_TC_CNT);
D16(DMAC_TC_PER);
#endif
@@ -1005,29 +1055,19 @@ static int __init bfin_debug_mmrs_init(void)
#endif
parent = debugfs_create_dir("gptimer", top);
-#ifdef TIMER_DISABLE
- D16(TIMER_DISABLE);
- D16(TIMER_ENABLE);
- D32(TIMER_STATUS);
+#ifdef TIMER_ENABLE
+ GPTIMER_GROUP(TIMER_ENABLE, -1);
#endif
-#ifdef TIMER_DISABLE0
- D16(TIMER_DISABLE0);
- D16(TIMER_ENABLE0);
- D32(TIMER_STATUS0);
+#ifdef TIMER_ENABLE0
+ GPTIMER_GROUP(TIMER_ENABLE0, 0);
#endif
-#ifdef TIMER_DISABLE1
- D16(TIMER_DISABLE1);
- D16(TIMER_ENABLE1);
- D32(TIMER_STATUS1);
+#ifdef TIMER_ENABLE1
+ GPTIMER_GROUP(TIMER_ENABLE1, 1);
#endif
/* XXX: Should convert BF561 MMR names */
#ifdef TMRS4_DISABLE
- D16(TMRS4_DISABLE);
- D16(TMRS4_ENABLE);
- D32(TMRS4_STATUS);
- D16(TMRS8_DISABLE);
- D16(TMRS8_ENABLE);
- D32(TMRS8_STATUS);
+ GPTIMER_GROUP(TMRS4_ENABLE, 0);
+ GPTIMER_GROUP(TMRS8_ENABLE, 1);
#endif
GPTIMER(0);
GPTIMER(1);
@@ -1253,6 +1293,14 @@ static int __init bfin_debug_mmrs_init(void)
D32(OTP_DATA3);
#endif
+#ifdef PINT0_MASK_SET
+ parent = debugfs_create_dir("pint", top);
+ PINT(0);
+ PINT(1);
+ PINT(2);
+ PINT(3);
+#endif
+
#ifdef PIXC_CTL
parent = debugfs_create_dir("pixc", top);
D16(PIXC_CTL);
@@ -1816,7 +1864,6 @@ static int __init bfin_debug_mmrs_init(void)
{
int num;
unsigned long base;
- char *_buf, buf[32];
base = PORTA_FER;
for (num = 0; num < 10; ++num) {
@@ -1824,24 +1871,6 @@ static int __init bfin_debug_mmrs_init(void)
base += sizeof(struct bfin_gpio_regs);
}
-#define __PINT(uname, lname) __REGS(pint, #uname, lname)
- parent = debugfs_create_dir("pint", top);
- base = PINT0_MASK_SET;
- for (num = 0; num < 4; ++num) {
- _buf = REGS_STR_PFX(buf, PINT, num);
- __PINT(MASK_SET, mask_set);
- __PINT(MASK_CLEAR, mask_clear);
- __PINT(IRQ, irq);
- __PINT(ASSIGN, assign);
- __PINT(EDGE_SET, edge_set);
- __PINT(EDGE_CLEAR, edge_clear);
- __PINT(INVERT_SET, invert_set);
- __PINT(INVERT_CLEAR, invert_clear);
- __PINT(PINSTATE, pinstate);
- __PINT(LATCH, latch);
- base += sizeof(struct bfin_pint_regs);
- }
-
}
#endif /* BF54x */
diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c
index 48808a12b427..9277905b82cf 100644
--- a/arch/blackfin/kernel/ftrace.c
+++ b/arch/blackfin/kernel/ftrace.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cacheflush.h>
#ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c
index 8b81dc04488a..06459f4bf43a 100644
--- a/arch/blackfin/kernel/gptimers.c
+++ b/arch/blackfin/kernel/gptimers.c
@@ -25,49 +25,33 @@
#define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
-typedef struct {
- uint16_t config;
- uint16_t __pad;
- uint32_t counter;
- uint32_t period;
- uint32_t width;
-} GPTIMER_timer_regs;
-
-typedef struct {
- uint16_t enable;
- uint16_t __pad0;
- uint16_t disable;
- uint16_t __pad1;
- uint32_t status;
-} GPTIMER_group_regs;
-
-static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
+static struct bfin_gptimer_regs * const timer_regs[MAX_BLACKFIN_GPTIMERS] =
{
- (GPTIMER_timer_regs *)TIMER0_CONFIG,
- (GPTIMER_timer_regs *)TIMER1_CONFIG,
- (GPTIMER_timer_regs *)TIMER2_CONFIG,
+ (void *)TIMER0_CONFIG,
+ (void *)TIMER1_CONFIG,
+ (void *)TIMER2_CONFIG,
#if (MAX_BLACKFIN_GPTIMERS > 3)
- (GPTIMER_timer_regs *)TIMER3_CONFIG,
- (GPTIMER_timer_regs *)TIMER4_CONFIG,
- (GPTIMER_timer_regs *)TIMER5_CONFIG,
- (GPTIMER_timer_regs *)TIMER6_CONFIG,
- (GPTIMER_timer_regs *)TIMER7_CONFIG,
+ (void *)TIMER3_CONFIG,
+ (void *)TIMER4_CONFIG,
+ (void *)TIMER5_CONFIG,
+ (void *)TIMER6_CONFIG,
+ (void *)TIMER7_CONFIG,
# if (MAX_BLACKFIN_GPTIMERS > 8)
- (GPTIMER_timer_regs *)TIMER8_CONFIG,
- (GPTIMER_timer_regs *)TIMER9_CONFIG,
- (GPTIMER_timer_regs *)TIMER10_CONFIG,
+ (void *)TIMER8_CONFIG,
+ (void *)TIMER9_CONFIG,
+ (void *)TIMER10_CONFIG,
# if (MAX_BLACKFIN_GPTIMERS > 11)
- (GPTIMER_timer_regs *)TIMER11_CONFIG,
+ (void *)TIMER11_CONFIG,
# endif
# endif
#endif
};
-static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] =
+static struct bfin_gptimer_group_regs * const group_regs[BFIN_TIMER_NUM_GROUP] =
{
- (GPTIMER_group_regs *)TIMER0_GROUP_REG,
+ (void *)TIMER0_GROUP_REG,
#if (MAX_BLACKFIN_GPTIMERS > 8)
- (GPTIMER_group_regs *)TIMER8_GROUP_REG,
+ (void *)TIMER8_GROUP_REG,
#endif
};
@@ -140,7 +124,7 @@ static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
void set_gptimer_pwidth(unsigned int timer_id, uint32_t value)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- timer_regs[timer_id]->width = value;
+ bfin_write(&timer_regs[timer_id]->width, value);
SSYNC();
}
EXPORT_SYMBOL(set_gptimer_pwidth);
@@ -148,14 +132,14 @@ EXPORT_SYMBOL(set_gptimer_pwidth);
uint32_t get_gptimer_pwidth(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- return timer_regs[timer_id]->width;
+ return bfin_read(&timer_regs[timer_id]->width);
}
EXPORT_SYMBOL(get_gptimer_pwidth);
void set_gptimer_period(unsigned int timer_id, uint32_t period)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- timer_regs[timer_id]->period = period;
+ bfin_write(&timer_regs[timer_id]->period, period);
SSYNC();
}
EXPORT_SYMBOL(set_gptimer_period);
@@ -163,71 +147,76 @@ EXPORT_SYMBOL(set_gptimer_period);
uint32_t get_gptimer_period(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- return timer_regs[timer_id]->period;
+ return bfin_read(&timer_regs[timer_id]->period);
}
EXPORT_SYMBOL(get_gptimer_period);
uint32_t get_gptimer_count(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- return timer_regs[timer_id]->counter;
+ return bfin_read(&timer_regs[timer_id]->counter);
}
EXPORT_SYMBOL(get_gptimer_count);
uint32_t get_gptimer_status(unsigned int group)
{
tassert(group < BFIN_TIMER_NUM_GROUP);
- return group_regs[group]->status;
+ return bfin_read(&group_regs[group]->status);
}
EXPORT_SYMBOL(get_gptimer_status);
void set_gptimer_status(unsigned int group, uint32_t value)
{
tassert(group < BFIN_TIMER_NUM_GROUP);
- group_regs[group]->status = value;
+ bfin_write(&group_regs[group]->status, value);
SSYNC();
}
EXPORT_SYMBOL(set_gptimer_status);
+static uint32_t read_gptimer_status(unsigned int timer_id)
+{
+ return bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status);
+}
+
int get_gptimer_intr(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]);
+ return !!(read_gptimer_status(timer_id) & timil_mask[timer_id]);
}
EXPORT_SYMBOL(get_gptimer_intr);
void clear_gptimer_intr(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id];
+ bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status, timil_mask[timer_id]);
}
EXPORT_SYMBOL(clear_gptimer_intr);
int get_gptimer_over(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]);
+ return !!(read_gptimer_status(timer_id) & tovf_mask[timer_id]);
}
EXPORT_SYMBOL(get_gptimer_over);
void clear_gptimer_over(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id];
+ bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status, tovf_mask[timer_id]);
}
EXPORT_SYMBOL(clear_gptimer_over);
int get_gptimer_run(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]);
+ return !!(read_gptimer_status(timer_id) & trun_mask[timer_id]);
}
EXPORT_SYMBOL(get_gptimer_run);
void set_gptimer_config(unsigned int timer_id, uint16_t config)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- timer_regs[timer_id]->config = config;
+ bfin_write(&timer_regs[timer_id]->config, config);
SSYNC();
}
EXPORT_SYMBOL(set_gptimer_config);
@@ -235,7 +224,7 @@ EXPORT_SYMBOL(set_gptimer_config);
uint16_t get_gptimer_config(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- return timer_regs[timer_id]->config;
+ return bfin_read(&timer_regs[timer_id]->config);
}
EXPORT_SYMBOL(get_gptimer_config);
@@ -244,7 +233,7 @@ void enable_gptimers(uint16_t mask)
int i;
tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
- group_regs[i]->enable = mask & 0xFF;
+ bfin_write(&group_regs[i]->enable, mask & 0xFF);
mask >>= 8;
}
SSYNC();
@@ -257,7 +246,7 @@ static void _disable_gptimers(uint16_t mask)
uint16_t m = mask;
tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
- group_regs[i]->disable = m & 0xFF;
+ bfin_write(&group_regs[i]->disable, m & 0xFF);
m >>= 8;
}
}
@@ -268,7 +257,7 @@ void disable_gptimers(uint16_t mask)
_disable_gptimers(mask);
for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
if (mask & (1 << i))
- group_regs[BFIN_TIMER_OCTET(i)]->status = trun_mask[i];
+ bfin_write(&group_regs[BFIN_TIMER_OCTET(i)]->status, trun_mask[i]);
SSYNC();
}
EXPORT_SYMBOL(disable_gptimers);
@@ -283,7 +272,7 @@ EXPORT_SYMBOL(disable_gptimers_sync);
void set_gptimer_pulse_hi(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- timer_regs[timer_id]->config |= TIMER_PULSE_HI;
+ bfin_write_or(&timer_regs[timer_id]->config, TIMER_PULSE_HI);
SSYNC();
}
EXPORT_SYMBOL(set_gptimer_pulse_hi);
@@ -291,7 +280,7 @@ EXPORT_SYMBOL(set_gptimer_pulse_hi);
void clear_gptimer_pulse_hi(unsigned int timer_id)
{
tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
- timer_regs[timer_id]->config &= ~TIMER_PULSE_HI;
+ bfin_write_and(&timer_regs[timer_id]->config, ~TIMER_PULSE_HI);
SSYNC();
}
EXPORT_SYMBOL(clear_gptimer_pulse_hi);
@@ -301,7 +290,7 @@ uint16_t get_enabled_gptimers(void)
int i;
uint16_t result = 0;
for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i)
- result |= (group_regs[i]->enable << (i << 3));
+ result |= (bfin_read(&group_regs[i]->enable) << (i << 3));
return result;
}
EXPORT_SYMBOL(get_enabled_gptimers);
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
index 486426f8a0d7..dbe11220cc53 100644
--- a/arch/blackfin/kernel/ipipe.c
+++ b/arch/blackfin/kernel/ipipe.c
@@ -32,7 +32,7 @@
#include <linux/unistd.h>
#include <linux/io.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq_handler.h>
DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index 35e350cad9d9..4489efc52883 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -16,19 +16,6 @@
#include <asm/cacheflush.h>
#include <asm/uaccess.h>
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc(size);
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
/* Transfer the section to the L1 memory */
int
module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
@@ -150,14 +137,6 @@ module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
return 0;
}
-int
-apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec, struct module *mod)
-{
- pr_err(".rel unsupported\n");
- return -ENOEXEC;
-}
-
/*************************************************************************/
/* FUNCTION : apply_relocate_add */
/* ABSTRACT : Blackfin specific relocation handling for the loadable */
diff --git a/arch/blackfin/kernel/nmi.c b/arch/blackfin/kernel/nmi.c
index 679d0db35256..9919d29287dc 100644
--- a/arch/blackfin/kernel/nmi.c
+++ b/arch/blackfin/kernel/nmi.c
@@ -18,7 +18,7 @@
#include <linux/smp.h>
#include <linux/timer.h>
#include <asm/blackfin.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/bfin_watchdog.h>
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 6a660fa921b5..6a80a9e9fc4a 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -140,7 +140,6 @@ EXPORT_SYMBOL(kernel_thread);
*/
void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
{
- set_fs(USER_DS);
regs->pc = new_ip;
if (current->mm)
regs->p5 = current->mm->start_data;
diff --git a/arch/blackfin/kernel/pwm.c b/arch/blackfin/kernel/pwm.c
new file mode 100644
index 000000000000..33f5942733bd
--- /dev/null
+++ b/arch/blackfin/kernel/pwm.c
@@ -0,0 +1,100 @@
+/*
+ * Blackfin Pulse Width Modulation (PWM) core
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#include <asm/gptimers.h>
+#include <asm/portmux.h>
+
+struct pwm_device {
+ unsigned id;
+ unsigned short pin;
+};
+
+static const unsigned short pwm_to_gptimer_per[] = {
+ P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5,
+ P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11,
+};
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+ struct pwm_device *pwm;
+ int ret;
+
+ /* XXX: pwm_id really should be unsigned */
+ if (pwm_id < 0)
+ return NULL;
+
+ pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
+ if (!pwm)
+ return pwm;
+
+ pwm->id = pwm_id;
+ if (pwm->id >= ARRAY_SIZE(pwm_to_gptimer_per))
+ goto err;
+
+ pwm->pin = pwm_to_gptimer_per[pwm->id];
+ ret = peripheral_request(pwm->pin, label);
+ if (ret)
+ goto err;
+
+ return pwm;
+ err:
+ kfree(pwm);
+ return NULL;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+ peripheral_free(pwm->pin);
+ kfree(pwm);
+}
+EXPORT_SYMBOL(pwm_free);
+
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+ unsigned long period, duty;
+ unsigned long long val;
+
+ if (duty_ns < 0 || duty_ns > period_ns)
+ return -EINVAL;
+
+ val = (unsigned long long)get_sclk() * period_ns;
+ do_div(val, NSEC_PER_SEC);
+ period = val;
+
+ val = (unsigned long long)period * duty_ns;
+ do_div(val, period_ns);
+ duty = period - val;
+
+ if (duty >= period)
+ duty = period - 1;
+
+ set_gptimer_config(pwm->id, TIMER_MODE_PWM | TIMER_PERIOD_CNT);
+ set_gptimer_pwidth(pwm->id, duty);
+ set_gptimer_period(pwm->id, period);
+
+ return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+ enable_gptimer(pwm->id);
+ return 0;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+ disable_gptimer(pwm->id);
+}
+EXPORT_SYMBOL(pwm_disable);
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
index 488bdc51aaa5..c4c0081b1996 100644
--- a/arch/blackfin/kernel/reboot.c
+++ b/arch/blackfin/kernel/reboot.c
@@ -54,7 +54,9 @@ static void bfin_reset(void)
/* The BF526 ROM will crash during reset */
#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
- bfin_read_SWRST();
+ /* Seems to be fixed with newer parts though ... */
+ if (__SILICON_REVISION__ < 1 && bfin_revid() < 1)
+ bfin_read_SWRST();
#endif
/* Wait for the SWRST write to complete. Cannot rely on SSYNC
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 536bd9d7e0cf..dfa2525a442d 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -54,8 +54,7 @@ EXPORT_SYMBOL(mtd_size);
#endif
char __initdata command_line[COMMAND_LINE_SIZE];
-void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat,
- *init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr;
+struct blackfin_initial_pda __initdata initial_pda;
/* boot memmap, for parsing "memmap=" */
#define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */
@@ -957,13 +956,16 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n");
#ifdef CONFIG_DEBUG_DOUBLEFAULT
/* We assume the crashing kernel, and the current symbol table match */
- printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n",
- (int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx);
- printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr);
- printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr);
+ printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF\n",
+ initial_pda.seqstat_doublefault & SEQSTAT_EXCAUSE,
+ initial_pda.retx_doublefault);
+ printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n",
+ initial_pda.dcplb_doublefault_addr);
+ printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n",
+ initial_pda.icplb_doublefault_addr);
#endif
printk(KERN_NOTICE " The instruction at %pF caused a double exception\n",
- init_retx);
+ initial_pda.retx);
} else if (_bfin_swrst & RESET_WDOG)
printk(KERN_INFO "Recovering from Watchdog event\n");
else if (_bfin_swrst & RESET_SOFTWARE)
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index 8d73724c0092..ceb2bf63dfe2 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -51,7 +51,7 @@ void __init setup_core_timer(void)
u32 tcount;
/* power up the timer, but don't enable it just yet */
- bfin_write_TCNTL(1);
+ bfin_write_TCNTL(TMPWR);
CSYNC();
/* the TSCALE prescaler counter */
@@ -64,7 +64,7 @@ void __init setup_core_timer(void)
/* now enable the timer */
CSYNC();
- bfin_write_TCNTL(7);
+ bfin_write_TCNTL(TAUTORLD | TMREN | TMPWR);
}
#endif
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 3ac5b66d14aa..ba35864b2b74 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -155,6 +155,7 @@ SECTIONS
SECURITY_INITCALL
INIT_RAM_FS
+ . = ALIGN(PAGE_SIZE);
___per_cpu_load = .;
PERCPU_INPUT(32)
diff --git a/arch/blackfin/mach-bf518/Kconfig b/arch/blackfin/mach-bf518/Kconfig
index 1d9f631a7f94..bde92a19970e 100644
--- a/arch/blackfin/mach-bf518/Kconfig
+++ b/arch/blackfin/mach-bf518/Kconfig
@@ -11,55 +11,75 @@ menu "BF518 Specific Configuration"
comment "Alternative Multiplexing Scheme"
choice
- prompt "SPORT0"
- default BF518_SPORT0_PORTG
+ prompt "PWM Channel Pins"
+ default BF518_PWM_ALL_PORTF
help
- Select PORT used for SPORT0. See Hardware Reference Manual
+ Select pins used for the PWM channels:
+ PWM_AH PWM_AL PWM_BH PWM_BL PWM_CH PWM_CL
-config BF518_SPORT0_PORTF
- bool "PORT F"
+ See the Hardware Reference Manual for more details.
+
+config BF518_PWM_ALL_PORTF
+ bool "PF1 - PF6"
help
- PORT F
+ PF{1,2,3,4,5,6} <-> PWM_{AH,AL,BH,BL,CH,CL}
-config BF518_SPORT0_PORTG
- bool "PORT G"
+config BF518_PWM_PORTF_PORTG
+ bool "PF11 - PF14 / PG1 - PG2"
help
- PORT G
+ PF{11,12,13,14} <-> PWM_{AH,AL,BH,BL}
+ PG{1,2} <-> PWM_{CH,CL}
+
endchoice
choice
- prompt "SPORT0 TSCLK Location"
- depends on BF518_SPORT0_PORTG
- default BF518_SPORT0_TSCLK_PG10
+ prompt "PWM Sync Pin"
+ default BF518_PWM_SYNC_PF7
help
- Select PIN used for SPORT0_TSCLK. See Hardware Reference Manual
+ Select the pin used for PWM_SYNC.
-config BF518_SPORT0_TSCLK_PG10
- bool "PORT PG10"
- help
- PORT PG10
+ See the Hardware Reference Manual for more details.
+
+config BF518_PWM_SYNC_PF7
+ bool "PF7"
+config BF518_PWM_SYNC_PF15
+ bool "PF15"
+endchoice
-config BF518_SPORT0_TSCLK_PG14
- bool "PORT PG14"
+choice
+ prompt "PWM Trip B Pin"
+ default BF518_PWM_TRIPB_PG10
help
- PORT PG14
+ Select the pin used for PWM_TRIPB.
+
+ See the Hardware Reference Manual for more details.
+
+config BF518_PWM_TRIPB_PG10
+ bool "PG10"
+config BF518_PWM_TRIPB_PG14
+ bool "PG14"
endchoice
choice
- prompt "UART1"
- default BF518_UART1_PORTF
+ prompt "PPI / Timer Pins"
+ default BF518_PPI_TMR_PG5
help
- Select PORT used for UART1. See Hardware Reference Manual
+ Select pins used for PPI/Timer:
+ PPICLK PPIFS1 PPIFS2
+ TMRCLK TMR0 TMR1
-config BF518_UART1_PORTF
- bool "PORT F"
+ See the Hardware Reference Manual for more details.
+
+config BF518_PPI_TMR_PG5
+ bool "PG5 - PG7"
help
- PORT F
+ PG{5,6,7} <-> {PPICLK/TMRCLK,TMR0/PPIFS1,TMR1/PPIFS2}
-config BF518_UART1_PORTG
- bool "PORT G"
+config BF518_PPI_TMR_PG12
+ bool "PG12 - PG14"
help
- PORT G
+ PG{12,13,14} <-> {PPICLK/TMRCLK,TMR0/PPIFS1,TMR1/PPIFS2}
+
endchoice
comment "Hysteresis/Schmitt Trigger Control"
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
index c0ccadcfa44e..d78fc2cc7d16 100644
--- a/arch/blackfin/mach-bf518/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -187,43 +187,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
-#if defined(CONFIG_NET_DSA_KSZ8893M) \
- || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
-/* SPI SWITCH CHIP */
-static struct bfin5xx_spi_chip spi_switch_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-#endif
-
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -239,21 +212,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
- && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -269,18 +227,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
#if defined(CONFIG_NET_DSA_KSZ8893M) \
|| defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
@@ -290,7 +236,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = 1,
.platform_data = NULL,
- .controller_data = &spi_switch_info,
.mode = SPI_MODE_3,
},
#endif
@@ -314,7 +259,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
@@ -324,7 +268,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 5,
- .controller_data = &spi_wm8731_chip_info,
.mode = SPI_MODE_0,
},
#endif
@@ -334,7 +277,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -343,7 +285,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &lq035q1_spi_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
diff --git a/arch/blackfin/mach-bf518/boards/tcm-bf518.c b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
index 50fc5c89e379..55c127908815 100644
--- a/arch/blackfin/mach-bf518/boards/tcm-bf518.c
+++ b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
@@ -138,32 +138,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -179,21 +163,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
- && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -209,18 +178,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
{
.modalias = "mmc_spi",
@@ -239,7 +196,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
@@ -249,7 +205,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 5,
- .controller_data = &spi_wm8731_chip_info,
.mode = SPI_MODE_0,
},
#endif
@@ -259,7 +214,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -268,7 +222,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &lq035q1_spi_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
diff --git a/arch/blackfin/mach-bf518/include/mach/anomaly.h b/arch/blackfin/mach-bf518/include/mach/anomaly.h
index d2f076fbbc9e..56383f7cbc07 100644
--- a/arch/blackfin/mach-bf518/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf518/include/mach/anomaly.h
@@ -11,10 +11,9 @@
*/
/* This file should be up to date with:
- * - Revision E, 01/26/2010; ADSP-BF512/BF514/BF516/BF518 Blackfin Processor Anomaly List
+ * - Revision F, 05/23/2011; ADSP-BF512/BF514/BF516/BF518 Blackfin Processor Anomaly List
*/
-/* We plan on not supporting 0.0 silicon, but 0.1 isn't out yet - sorry */
#if __SILICON_REVISION__ < 0
# error will not work on BF518 silicon version
#endif
@@ -77,19 +76,29 @@
/* False Hardware Error when RETI Points to Invalid Memory */
#define ANOMALY_05000461 (1)
/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
-#define ANOMALY_05000462 (1)
-/* PLL Latches Incorrect Settings During Reset */
-#define ANOMALY_05000469 (1)
+#define ANOMALY_05000462 (__SILICON_REVISION__ < 2)
/* Incorrect Default MSEL Value in PLL_CTL */
-#define ANOMALY_05000472 (1)
+#define ANOMALY_05000472 (__SILICON_REVISION__ < 2)
/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
#define ANOMALY_05000473 (1)
/* TESTSET Instruction Cannot Be Interrupted */
#define ANOMALY_05000477 (1)
/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
#define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL Latches Incorrect Settings During Reset */
+#define ANOMALY_05000482 (__SILICON_REVISION__ < 2)
+/* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */
+#define ANOMALY_05000485 (__SILICON_REVISION__ < 2)
+/* SPI Master Boot Can Fail Under Certain Conditions */
+#define ANOMALY_05000490 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
#define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* CNT_COMMAND Functionality Depends on CNT_IMASK Configuration */
+#define ANOMALY_05000498 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000099 (0)
@@ -157,6 +166,5 @@
#define ANOMALY_05000474 (0)
#define ANOMALY_05000475 (0)
#define ANOMALY_05000480 (0)
-#define ANOMALY_05000485 (0)
#endif
diff --git a/arch/blackfin/mach-bf518/include/mach/portmux.h b/arch/blackfin/mach-bf518/include/mach/portmux.h
index cd84a569b04e..b3b806f468da 100644
--- a/arch/blackfin/mach-bf518/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf518/include/mach/portmux.h
@@ -81,9 +81,15 @@
#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+#ifndef CONFIG_BF518_PPI_TMR_PG12
+#define P_PPI0_CLK (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
+#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#else
#define P_PPI0_CLK (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#endif
#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
/* SPI Port Mux */
@@ -139,9 +145,15 @@
#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(1))
/* Timer */
+#ifndef CONFIG_BF518_PPI_TMR_PG12
#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(2))
#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2))
+#else
+#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(2))
+#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(2))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(2))
+#endif
#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(2))
#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(2))
#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(2))
@@ -158,23 +170,33 @@
#define P_TWI0_SDA (P_DONTCARE)
/* PWM */
-#define P_PWM0_AH (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2))
-#define P_PWM0_AL (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2))
-#define P_PWM0_BH (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2))
-#define P_PWM0_BL (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2))
-#define P_PWM0_CH (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2))
-#define P_PWM0_CL (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2))
-#define P_PWM0_SYNC (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2))
-
-#define P_PWM1_AH (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(2))
-#define P_PWM1_AL (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2))
-#define P_PWM1_BH (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2))
-#define P_PWM1_BL (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2))
-#define P_PWM1_CH (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
-#define P_PWM1_CL (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
-#define P_PWM1_SYNC (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2))
-
+#ifndef CONFIG_BF518_PWM_PORTF_PORTG
+#define P_PWM_AH (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2))
+#define P_PWM_AL (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2))
+#define P_PWM_BH (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2))
+#define P_PWM_BL (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2))
+#define P_PWM_CH (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2))
+#define P_PWM_CL (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2))
+#else
+#define P_PWM_AH (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(2))
+#define P_PWM_AL (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2))
+#define P_PWM_BH (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2))
+#define P_PWM_BL (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2))
+#define P_PWM_CH (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
+#define P_PWM_CL (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
+#endif
+
+#ifndef CONFIG_BF518_PWM_SYNC_PF15
+#define P_PWM_SYNC (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2))
+#else
+#define P_PWM_SYNC (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2))
+#endif
+
+#ifndef CONFIG_BF518_PWM_TRIPB_PG14
+#define P_PWM_TRIPB (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(2))
+#else
#define P_PWM_TRIPB (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(2))
+#endif
/* RSI */
#define P_RSI_DATA0 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
index ccab4c689dc3..c04df43f6391 100644
--- a/arch/blackfin/mach-bf527/boards/ad7160eval.c
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -265,29 +265,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -328,7 +311,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -347,7 +329,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
};
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index c9d6dc88f0e6..6400341cc230 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -354,40 +354,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -403,21 +379,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
- && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -433,18 +394,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
@@ -452,7 +401,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -473,7 +421,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
@@ -483,7 +430,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 5,
- .controller_data = &spi_wm8731_chip_info,
.mode = SPI_MODE_0,
},
#endif
@@ -493,7 +439,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
};
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index b7101aa6e3aa..6dbb1b403763 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -253,32 +253,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (sst25wf040) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -311,35 +295,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
};
#endif
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
- && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -355,18 +310,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
{
.modalias = "mmc_spi",
@@ -385,7 +328,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
@@ -396,7 +338,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 5,
- .controller_data = &spi_ad7879_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -407,7 +348,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 5,
- .controller_data = &spi_wm8731_chip_info,
.mode = SPI_MODE_0,
},
#endif
@@ -417,7 +357,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -426,7 +365,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &lq035q1_spi_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index e67ac7720668..4e9dc9cf8241 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -409,6 +409,9 @@ static struct resource net2272_bfin_resources[] = {
.end = 0x20300000 + 0x100,
.flags = IORESOURCE_MEM,
}, {
+ .start = 1,
+ .flags = IORESOURCE_BUS,
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -448,40 +451,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -513,20 +492,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
};
#endif
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
@@ -574,9 +539,25 @@ static struct resource bfin_snd_resources[][4] = {
BFIN_SND_RES(0),
BFIN_SND_RES(1),
};
+#endif
-static struct platform_device bfin_pcm = {
- .name = "bfin-pcm-audio",
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s_pcm = {
+ .name = "bfin-i2s-pcm-audio",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm_pcm = {
+ .name = "bfin-tdm-pcm-audio",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+static struct platform_device bfin_ac97_pcm = {
+ .name = "bfin-ac97-pcm-audio",
.id = -1,
};
#endif
@@ -605,13 +586,6 @@ static struct platform_device bfin_tdm = {
};
#endif
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -627,18 +601,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
@@ -647,7 +609,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = 4,
.platform_data = "ad1836",
- .controller_data = &ad1836_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -670,7 +631,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
@@ -681,7 +641,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 3,
- .controller_data = &spi_ad7879_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -691,7 +650,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -700,7 +658,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 7,
- .controller_data = &lq035q1_spi_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -1276,9 +1233,16 @@ static struct platform_device *stamp_devices[] __initdata = {
&ezkit_flash_device,
#endif
-#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
- defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
- &bfin_pcm,
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+ &bfin_i2s_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+ &bfin_tdm_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+ &bfin_ac97_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
index 18d303dd5627..ec4bc7429c9f 100644
--- a/arch/blackfin/mach-bf527/boards/tll6527m.c
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -314,29 +314,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 0, /* use dma transfer with this chip*/
-/*
- * tll6527m V1.0 does not support native spi slave selects
- * hence DMA mode will not be useful since the ADC needs
- * CS to toggle for each sample and cs_change_per_word
- * seems to be removed from spi_bfin5xx.c
- */
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -359,21 +342,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
};
#endif
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) \
- || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
static struct platform_device bfin_i2s = {
.name = "bfin-i2s",
@@ -382,24 +350,7 @@ static struct platform_device bfin_i2s = {
};
#endif
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
#if defined(CONFIG_GPIO_MCP23S08) || defined(CONFIG_GPIO_MCP23S08_MODULE)
-static struct bfin5xx_spi_chip spi_mcp23s08_sys_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-
-static struct bfin5xx_spi_chip spi_mcp23s08_usr_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-
#include <linux/spi/mcp23s08.h>
static const struct mcp23s08_platform_data bfin_mcp23s08_sys_gpio_info = {
.chip[0].is_present = true,
@@ -429,22 +380,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC)
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc",
- /* Name of spi_driver for this device */
- .max_speed_hz = 10000000,
- /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = EXP_GPIO_SPISEL_BASE + 0x04 + MAX_CTRL_CS,
- /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- .mode = SPI_MODE_0,
- },
-#endif
-
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
{
.modalias = "mmc_spi",
@@ -470,7 +405,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
/* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = EXP_GPIO_SPISEL_BASE + 0x07 + MAX_CTRL_CS,
- .controller_data = &spi_ad7879_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -482,7 +416,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = EXP_GPIO_SPISEL_BASE + 0x03 + MAX_CTRL_CS,
.mode = SPI_CPHA | SPI_CPOL,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -491,7 +424,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000,
.bus_num = 0,
.chip_select = EXP_GPIO_SPISEL_BASE + 0x06 + MAX_CTRL_CS,
- .controller_data = &lq035q1_spi_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -502,7 +434,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = EXP_GPIO_SPISEL_BASE + 0x01 + MAX_CTRL_CS,
- .controller_data = &spi_mcp23s08_sys_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
{
@@ -511,7 +442,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = EXP_GPIO_SPISEL_BASE + 0x02 + MAX_CTRL_CS,
- .controller_data = &spi_mcp23s08_usr_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h
index e66a7e89cd3c..688470611e15 100644
--- a/arch/blackfin/mach-bf527/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h
@@ -11,8 +11,8 @@
*/
/* This file should be up to date with:
- * - Revision E, 03/15/2010; ADSP-BF526 Blackfin Processor Anomaly List
- * - Revision H, 04/29/2010; ADSP-BF527 Blackfin Processor Anomaly List
+ * - Revision F, 05/23/2011; ADSP-BF526 Blackfin Processor Anomaly List
+ * - Revision I, 05/23/2011; ADSP-BF527 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -57,7 +57,7 @@
/* Incorrect Access of OTP_STATUS During otp_write() Function */
#define ANOMALY_05000328 (_ANOMALY_BF527(< 2))
/* Host DMA Boot Modes Are Not Functional */
-#define ANOMALY_05000330 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000330 (_ANOMALY_BF527(< 2))
/* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
#define ANOMALY_05000337 (_ANOMALY_BF527(< 2))
/* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
@@ -135,7 +135,7 @@
/* Incorrect Default Internal Voltage Regulator Setting */
#define ANOMALY_05000410 (_ANOMALY_BF527(< 2))
/* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */
-#define ANOMALY_05000411 (_ANOMALY_BF526_BF527(< 1, < 2))
+#define ANOMALY_05000411 (_ANOMALY_BF526(< 1))
/* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */
#define ANOMALY_05000414 (_ANOMALY_BF526_BF527(< 1, < 2))
/* DEB2_URGENT Bit Not Functional */
@@ -181,11 +181,11 @@
/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
#define ANOMALY_05000443 (1)
/* The WURESET Bit in the SYSCR Register is not Functional */
-#define ANOMALY_05000445 (1)
-/* USB DMA Mode 1 Short Packet Data Corruption */
+#define ANOMALY_05000445 (_ANOMALY_BF527(>= 0))
+/* USB DMA Short Packet Data Corruption */
#define ANOMALY_05000450 (1)
/* BCODE_QUICKBOOT, BCODE_ALLBOOT, and BCODE_FULLBOOT Settings in SYSCR Register Not Functional */
-#define ANOMALY_05000451 (1)
+#define ANOMALY_05000451 (_ANOMALY_BF527(>= 0))
/* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
#define ANOMALY_05000452 (_ANOMALY_BF526_BF527(< 1, >= 0))
/* USB Receive Interrupt Is Not Generated in DMA Mode 1 */
@@ -198,19 +198,19 @@
#define ANOMALY_05000461 (1)
/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
#define ANOMALY_05000462 (1)
-/* USB Rx DMA hang */
+/* USB Rx DMA Hang */
#define ANOMALY_05000465 (1)
/* TxPktRdy Bit Not Set for Transmit Endpoint When Core and DMA Access USB Endpoint FIFOs Simultaneously */
#define ANOMALY_05000466 (1)
-/* Possible RX data corruption when control & data EP FIFOs are accessed via the core */
+/* Possible USB RX Data Corruption When Control & Data EP FIFOs are Accessed via the Core */
#define ANOMALY_05000467 (1)
/* PLL Latches Incorrect Settings During Reset */
#define ANOMALY_05000469 (1)
/* Incorrect Default MSEL Value in PLL_CTL */
#define ANOMALY_05000472 (_ANOMALY_BF526(>= 0))
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
#define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
#define ANOMALY_05000475 (1)
/* TESTSET Instruction Cannot Be Interrupted */
#define ANOMALY_05000477 (1)
@@ -219,11 +219,19 @@
/* Possible USB Data Corruption When Multiple Endpoints Are Accessed by the Core */
#define ANOMALY_05000483 (1)
/* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */
-#define ANOMALY_05000485 (_ANOMALY_BF526_BF527(< 2, < 3))
+#define ANOMALY_05000485 (_ANOMALY_BF526_BF527(< 2, >= 0))
/* The CODEC Zero-Cross Detect Feature is not Functional */
#define ANOMALY_05000487 (1)
-/* IFLUSH sucks at life */
+/* SPI Master Boot Can Fail Under Certain Conditions */
+#define ANOMALY_05000490 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
#define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* CNT_COMMAND Functionality Depends on CNT_IMASK Configuration */
+#define ANOMALY_05000498 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index d4bfcea56828..eb325ed6607e 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -159,22 +159,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
@@ -195,24 +179,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 4, /* actual baudrate is SCLK/(2xspeed_hz) */
- .bus_num = 1, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
.max_speed_hz = 16,
.bus_num = 1,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c
index 87b5af3693c1..b0ec825fb4ec 100644
--- a/arch/blackfin/mach-bf533/boards/blackstamp.c
+++ b/arch/blackfin/mach-bf533/boards/blackstamp.c
@@ -102,21 +102,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -151,7 +142,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 7,
- .controller_data = &spidev_chip_info,
},
#endif
};
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 4d5604eaa7c2..14f54a31e74c 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -59,29 +59,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-/* SPI ADC chip */
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -99,24 +82,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 2, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index b67b91d82242..ecd2801f050d 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -210,29 +210,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -250,24 +227,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -276,7 +241,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
};
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index a377d8afea03..fbee77fa9211 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -110,7 +110,6 @@ static struct platform_device dm9000_device2 = {
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0, /* if 1 - block!!! */
- .bits_per_word = 8,
};
#endif
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 43224ef00b8c..964a8e5f79b4 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -80,6 +80,9 @@ static struct resource net2272_bfin_resources[] = {
.end = 0x20300000 + 0x100,
.flags = IORESOURCE_MEM,
}, {
+ .start = 1,
+ .flags = IORESOURCE_BUS,
+ }, {
.start = IRQ_PF10,
.end = IRQ_PF10,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -172,29 +175,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -221,7 +201,6 @@ static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
.pio_interrupt = 0,
};
#endif
@@ -240,17 +219,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
@@ -258,7 +226,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = 4,
.platform_data = "ad1836", /* only includes chip name for the moment */
- .controller_data = &ad1836_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -269,7 +236,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -659,6 +625,41 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
};
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ int ret;
+
+ /* Set PF0 to 0, PF1 to 1 make /AMS3 work properly */
+ ret = gpio_request(GPIO_PF0, "net2272");
+ if (ret)
+ return ret;
+
+ ret = gpio_request(GPIO_PF1, "net2272");
+ if (ret) {
+ gpio_free(GPIO_PF0);
+ return ret;
+ }
+
+ ret = gpio_request(GPIO_PF11, "net2272");
+ if (ret) {
+ gpio_free(GPIO_PF0);
+ gpio_free(GPIO_PF1);
+ return ret;
+ }
+
+ gpio_direction_output(GPIO_PF0, 0);
+ gpio_direction_output(GPIO_PF1, 1);
+
+ /* Reset the USB chip */
+ gpio_direction_output(GPIO_PF11, 0);
+ mdelay(2);
+ gpio_set_value(GPIO_PF11, 1);
+#endif
+
+ return 0;
+}
+
static int __init stamp_init(void)
{
int ret;
@@ -685,6 +686,9 @@ static int __init stamp_init(void)
}
#endif
+ if (net2272_init())
+ pr_warning("unable to configure net2272; it probably won't work\n");
+
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
return 0;
}
diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h
index 72aa59440f82..03f2b40912a3 100644
--- a/arch/blackfin/mach-bf533/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h
@@ -11,7 +11,7 @@
*/
/* This file should be up to date with:
- * - Revision F, 05/25/2010; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
+ * - Revision G, 05/23/2011; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -152,7 +152,7 @@
#define ANOMALY_05000277 (__SILICON_REVISION__ < 6)
/* Disabling Peripherals with DMA Running May Cause DMA System Instability */
#define ANOMALY_05000278 (__SILICON_REVISION__ < 6)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
#define ANOMALY_05000281 (__SILICON_REVISION__ < 6)
/* Memory DMA Corruption with 32-Bit Data and Traffic Control */
#define ANOMALY_05000282 (__SILICON_REVISION__ < 6)
@@ -210,18 +210,25 @@
#define ANOMALY_05000462 (1)
/* Boot Failure When SDRAM Control Signals Toggle Coming Out Of Reset */
#define ANOMALY_05000471 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
#define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
#define ANOMALY_05000475 (1)
/* TESTSET Instruction Cannot Be Interrupted */
#define ANOMALY_05000477 (1)
/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
#define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
#define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
-/* These anomalies have been "phased" out of analog.com anomaly sheets and are
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
* here to show running on older silicon just isn't feasible.
*/
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index d582b810e7a7..44fd8409db10 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -61,29 +61,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -101,24 +84,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -766,6 +737,24 @@ static struct platform_device *cm_bf537e_devices[] __initdata = {
#endif
};
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ int ret;
+
+ ret = gpio_request(GPIO_PG14, "net2272");
+ if (ret)
+ return ret;
+
+ /* Reset USB Chip, PG14 */
+ gpio_direction_output(GPIO_PG14, 0);
+ mdelay(2);
+ gpio_set_value(GPIO_PG14, 1);
+#endif
+
+ return 0;
+}
+
static int __init cm_bf537e_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -777,6 +766,10 @@ static int __init cm_bf537e_init(void)
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
#endif
+
+ if (net2272_init())
+ pr_warning("unable to configure net2272; it probably won't work\n");
+
return 0;
}
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index cbb8098604c5..1b4ac5c64aae 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -62,29 +62,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -102,24 +85,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -731,6 +702,36 @@ static struct platform_device *cm_bf537u_devices[] __initdata = {
#endif
};
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ int ret;
+
+ ret = gpio_request(GPIO_PH15, driver_name);
+ if (ret)
+ return ret;
+
+ ret = gpio_request(GPIO_PH13, "net2272");
+ if (ret) {
+ gpio_free(GPIO_PH15);
+ return ret;
+ }
+
+ /* Set PH15 Low make /AMS2 work properly */
+ gpio_direction_output(GPIO_PH15, 0);
+
+ /* enable CLKBUF output */
+ bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
+
+ /* Reset the USB chip */
+ gpio_direction_output(GPIO_PH13, 0);
+ mdelay(2);
+ gpio_set_value(GPIO_PH13, 1);
+#endif
+
+ return 0;
+}
+
static int __init cm_bf537u_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -742,6 +743,10 @@ static int __init cm_bf537u_init(void)
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
#endif
+
+ if (net2272_init())
+ pr_warning("unable to configure net2272; it probably won't work\n");
+
return 0;
}
diff --git a/arch/blackfin/mach-bf537/boards/dnp5370.c b/arch/blackfin/mach-bf537/boards/dnp5370.c
index 6b4ff4605bff..8bc951de979d 100644
--- a/arch/blackfin/mach-bf537/boards/dnp5370.c
+++ b/arch/blackfin/mach-bf537/boards/dnp5370.c
@@ -130,7 +130,6 @@ static struct platform_device asmb_flash_device = {
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0, /* use no dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
@@ -161,7 +160,6 @@ static struct flash_platform_data bfin_spi_dataflash_data = {
static struct bfin5xx_spi_chip spi_dataflash_chip_info = {
.enable_dma = 0, /* use no dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index bfb3671a78da..c62f9dccd9f7 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -159,14 +159,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 9389f03e3b0a..3b8151d99b9a 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -184,40 +184,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -248,18 +224,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
@@ -267,7 +231,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -288,7 +251,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 5,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 76db1d483173..b52e6728f64f 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -367,6 +367,9 @@ static struct resource net2272_bfin_resources[] = {
.end = 0x20300000 + 0x100,
.flags = IORESOURCE_MEM,
}, {
+ .start = 1,
+ .flags = IORESOURCE_BUS,
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -533,49 +536,11 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD193X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD193X_MODULE)
-static struct bfin5xx_spi_chip ad1938_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) \
- || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
-static struct bfin5xx_spi_chip adav801_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
#include <linux/input/ad714x.h>
-static struct bfin5xx_spi_chip ad7147_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
static struct ad714x_slider_plat ad7147_spi_slider_plat[] = {
{
@@ -685,7 +650,6 @@ static struct ad714x_platform_data ad7142_i2c_platform_data = {
#if defined(CONFIG_AD2S90) || defined(CONFIG_AD2S90_MODULE)
static struct bfin5xx_spi_chip ad2s90_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 16,
};
#endif
@@ -697,7 +661,6 @@ static unsigned short ad2s120x_platform_data[] = {
static struct bfin5xx_spi_chip ad2s120x_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 16,
};
#endif
@@ -714,14 +677,12 @@ static unsigned short ad2s1210_platform_data[] = {
static struct bfin5xx_spi_chip ad2s1210_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_AD7314) || defined(CONFIG_AD7314_MODULE)
static struct bfin5xx_spi_chip ad7314_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 16,
};
#endif
@@ -735,7 +696,6 @@ static unsigned short ad7816_platform_data[] = {
static struct bfin5xx_spi_chip ad7816_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -749,7 +709,6 @@ static unsigned long adt7310_platform_data[3] = {
static struct bfin5xx_spi_chip adt7310_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -758,11 +717,6 @@ static unsigned short ad7298_platform_data[] = {
GPIO_PF7, /* busy_pin */
0,
};
-
-static struct bfin5xx_spi_chip ad7298_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
#endif
#if defined(CONFIG_ADT7316_SPI) || defined(CONFIG_ADT7316_SPI_MODULE)
@@ -773,7 +727,6 @@ static unsigned long adt7316_spi_data[2] = {
static struct bfin5xx_spi_chip adt7316_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -800,18 +753,12 @@ static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
.pio_interrupt = 0,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
#include <linux/spi/ad7877.h>
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -883,39 +830,13 @@ static const struct adxl34x_platform_data adxl34x_info = {
};
#endif
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
static struct bfin5xx_spi_chip enc28j60_spi_chip_info = {
.enable_dma = 1,
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_ADF702X) || defined(CONFIG_ADF702X_MODULE)
-static struct bfin5xx_spi_chip adf7021_spi_chip_info = {
- .bits_per_word = 16,
-};
-
#include <linux/spi/adf702x.h>
#define TXREG 0x0160A470
static const u32 adf7021_regs[] = {
@@ -959,10 +880,6 @@ static inline void adf702x_mac_init(void) {}
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
#include <linux/spi/ads7846.h>
-static struct bfin5xx_spi_chip ad7873_spi_chip_info = {
- .bits_per_word = 8,
-};
-
static int ads7873_get_pendown_state(void)
{
return gpio_get_value(GPIO_PF6);
@@ -1009,21 +926,12 @@ static struct flash_platform_data bfin_spi_dataflash_data = {
/* DataFlash chip */
static struct bfin5xx_spi_chip data_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
- .enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_AD7476) || defined(CONFIG_AD7476_MODULE)
static struct bfin5xx_spi_chip spi_ad7476_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
@@ -1053,17 +961,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_MODE_3,
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
- || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
@@ -1073,7 +970,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = 4,
.platform_data = "ad1836", /* only includes chip name for the moment */
- .controller_data = &ad1836_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -1084,7 +980,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 5,
- .controller_data = &ad1938_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -1095,7 +990,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &adav801_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -1109,7 +1003,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.chip_select = 5,
.mode = SPI_MODE_3,
.platform_data = &ad7147_spi_platform_data,
- .controller_data = &ad7147_spi_chip_info,
},
#endif
@@ -1188,7 +1081,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = 4, /* CS, change it for your board */
.platform_data = ad7298_platform_data,
- .controller_data = &ad7298_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -1225,7 +1117,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
@@ -1236,7 +1127,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spi_ad7879_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -1246,7 +1136,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -1255,7 +1144,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &lq035q1_spi_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -1278,7 +1166,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_adxl34x_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -1288,7 +1175,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 16000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = GPIO_PF10 + MAX_CTRL_CS, /* GPIO controlled SSEL */
- .controller_data = &adf7021_spi_chip_info,
.platform_data = &adf7021_platform_data,
.mode = SPI_MODE_0,
},
@@ -1300,7 +1186,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.irq = IRQ_PF6,
.chip_select = GPIO_PF10 + MAX_CTRL_CS, /* GPIO controlled SSEL */
- .controller_data = &ad7873_spi_chip_info,
.platform_data = &ad7873_pdata,
.mode = SPI_MODE_0,
},
@@ -2632,9 +2517,25 @@ static struct resource bfin_snd_resources[][4] = {
BFIN_SND_RES(0),
BFIN_SND_RES(1),
};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s_pcm = {
+ .name = "bfin-i2s-pcm-audio",
+ .id = -1,
+};
+#endif
-static struct platform_device bfin_pcm = {
- .name = "bfin-pcm-audio",
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm_pcm = {
+ .name = "bfin-tdm-pcm-audio",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+static struct platform_device bfin_ac97_pcm = {
+ .name = "bfin-ac97-pcm-audio",
.id = -1,
};
#endif
@@ -2869,10 +2770,16 @@ static struct platform_device *stamp_devices[] __initdata = {
&stamp_flash_device,
#endif
-#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
- defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \
- defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
- &bfin_pcm,
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+ &bfin_i2s_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+ &bfin_tdm_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+ &bfin_ac97_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
@@ -2916,6 +2823,24 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
};
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ int ret;
+
+ ret = gpio_request(GPIO_PF6, "net2272");
+ if (ret)
+ return ret;
+
+ /* Reset the USB chip */
+ gpio_direction_output(GPIO_PF6, 0);
+ mdelay(2);
+ gpio_set_value(GPIO_PF6, 1);
+#endif
+
+ return 0;
+}
+
static int __init stamp_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -2926,6 +2851,9 @@ static int __init stamp_init(void)
ARRAY_SIZE(bfin_i2c_board_info));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+ if (net2272_init())
+ pr_warning("unable to configure net2272; it probably won't work\n");
+
return 0;
}
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 164a7e02c022..9b7287abdfa1 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -62,29 +62,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
static struct bfin5xx_spi_chip mmc_spi_chip_info = {
.enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -102,24 +85,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -733,6 +704,24 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
#endif
};
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ int ret;
+
+ ret = gpio_request(GPIO_PG14, "net2272");
+ if (ret)
+ return ret;
+
+ /* Reset USB Chip, PG14 */
+ gpio_direction_output(GPIO_PG14, 0);
+ mdelay(2);
+ gpio_set_value(GPIO_PG14, 1);
+#endif
+
+ return 0;
+}
+
static int __init tcm_bf537_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -744,6 +733,10 @@ static int __init tcm_bf537_init(void)
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
#endif
+
+ if (net2272_init())
+ pr_warning("unable to configure net2272; it probably won't work\n");
+
return 0;
}
diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h
index 7f8e5a9f5db6..543cd3fb305e 100644
--- a/arch/blackfin/mach-bf537/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h
@@ -11,7 +11,7 @@
*/
/* This file should be up to date with:
- * - Revision E, 05/25/2010; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
+ * - Revision F, 05/23/2011; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -44,18 +44,12 @@
#define ANOMALY_05000119 (1)
/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
#define ANOMALY_05000122 (1)
-/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
-#define ANOMALY_05000157 (__SILICON_REVISION__ < 2)
/* PPI_DELAY Not Functional in PPI Modes with 0 Frame Syncs */
#define ANOMALY_05000180 (1)
-/* Instruction Cache Is Not Functional */
-#define ANOMALY_05000237 (__SILICON_REVISION__ < 2)
/* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
#define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
#define ANOMALY_05000245 (1)
-/* Buffered CLKIN Output Is Disabled by Default */
-#define ANOMALY_05000247 (1)
/* Incorrect Bit Shift of Data Word in Multichannel (TDM) Mode in Certain Conditions */
#define ANOMALY_05000250 (__SILICON_REVISION__ < 3)
/* EMAC TX DMA Error After an Early Frame Abort */
@@ -98,7 +92,7 @@
#define ANOMALY_05000278 (((ANOMALY_BF536 || ANOMALY_BF537) && __SILICON_REVISION__ < 3) || (ANOMALY_BF534 && __SILICON_REVISION__ < 2))
/* SPI Master Boot Mode Does Not Work Well with Atmel Data Flash Devices */
#define ANOMALY_05000280 (1)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
#define ANOMALY_05000281 (__SILICON_REVISION__ < 3)
/* Memory DMA Corruption with 32-Bit Data and Traffic Control */
#define ANOMALY_05000282 (__SILICON_REVISION__ < 3)
@@ -162,9 +156,9 @@
#define ANOMALY_05000461 (1)
/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
#define ANOMALY_05000462 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
#define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
#define ANOMALY_05000475 (1)
/* TESTSET Instruction Cannot Be Interrupted */
#define ANOMALY_05000477 (1)
@@ -172,8 +166,26 @@
#define ANOMALY_05000480 (__SILICON_REVISION__ < 3)
/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
#define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
#define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
+#define ANOMALY_05000157 (__SILICON_REVISION__ < 2)
+/* Instruction Cache Is Not Functional */
+#define ANOMALY_05000237 (__SILICON_REVISION__ < 2)
+/* Buffered CLKIN Output Is Disabled by Default */
+#define ANOMALY_05000247 (__SILICON_REVISION__ < 2)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
index e61424ef35eb..629f3c333415 100644
--- a/arch/blackfin/mach-bf538/boards/ezkit.c
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -502,7 +502,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
@@ -523,13 +522,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
};
#endif
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
#include <asm/bfin-lq035q1.h>
@@ -559,20 +551,6 @@ static struct platform_device bfin_lq035q1_device = {
};
#endif
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bf538_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -595,7 +573,6 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spi_ad7879_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -605,7 +582,6 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &lq035q1_spi_chip_info,
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
@@ -615,7 +591,6 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
};
diff --git a/arch/blackfin/mach-bf538/ext-gpio.c b/arch/blackfin/mach-bf538/ext-gpio.c
index 180b1252679f..471a9b184d5b 100644
--- a/arch/blackfin/mach-bf538/ext-gpio.c
+++ b/arch/blackfin/mach-bf538/ext-gpio.c
@@ -1,7 +1,7 @@
/*
* GPIOLIB interface for BF538/9 PORT C, D, and E GPIOs
*
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
@@ -121,3 +121,38 @@ static int __init bf538_extgpio_setup(void)
gpiochip_add(&bf538_porte_chip);
}
arch_initcall(bf538_extgpio_setup);
+
+#ifdef CONFIG_PM
+static struct {
+ u16 data, dir, inen;
+} gpio_bank_saved[3];
+
+static void __iomem * const port_bases[3] = {
+ (void *)PORTCIO,
+ (void *)PORTDIO,
+ (void *)PORTEIO,
+};
+
+void bfin_special_gpio_pm_hibernate_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
+ gpio_bank_saved[i].data = read_PORTIO(port_bases[i]);
+ gpio_bank_saved[i].inen = read_PORTIO_INEN(port_bases[i]);
+ gpio_bank_saved[i].dir = read_PORTIO_DIR(port_bases[i]);
+ }
+}
+
+void bfin_special_gpio_pm_hibernate_restore(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
+ write_PORTIO_INEN(port_bases[i], gpio_bank_saved[i].inen);
+ write_PORTIO_SET(port_bases[i],
+ gpio_bank_saved[i].data & gpio_bank_saved[i].dir);
+ write_PORTIO_DIR(port_bases[i], gpio_bank_saved[i].dir);
+ }
+}
+#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/anomaly.h b/arch/blackfin/mach-bf538/include/mach/anomaly.h
index 55e7d0712a94..b6ca99788710 100644
--- a/arch/blackfin/mach-bf538/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf538/include/mach/anomaly.h
@@ -11,8 +11,8 @@
*/
/* This file should be up to date with:
- * - Revision I, 05/25/2010; ADSP-BF538/BF538F Blackfin Processor Anomaly List
- * - Revision N, 05/25/2010; ADSP-BF539/BF539F Blackfin Processor Anomaly List
+ * - Revision J, 05/23/2011; ADSP-BF538/BF538F Blackfin Processor Anomaly List
+ * - Revision O, 05/23/2011; ADSP-BF539/BF539F Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -56,25 +56,21 @@
#define ANOMALY_05000229 (1)
/* PPI_FS3 Is Not Driven in 2 or 3 Internal Frame Sync Transmit Modes */
#define ANOMALY_05000233 (1)
-/* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
-#define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
#define ANOMALY_05000245 (1)
/* Maximum External Clock Speed for Timers */
#define ANOMALY_05000253 (1)
-/* DCPLB_FAULT_ADDR MMR Register May Be Corrupted */
-#define ANOMALY_05000261 (__SILICON_REVISION__ < 3)
/* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */
#define ANOMALY_05000270 (__SILICON_REVISION__ < 4)
/* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
-#define ANOMALY_05000272 (1)
+#define ANOMALY_05000272 (ANOMALY_BF538)
/* Writes to Synchronous SDRAM Memory May Be Lost */
#define ANOMALY_05000273 (__SILICON_REVISION__ < 4)
/* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
#define ANOMALY_05000277 (__SILICON_REVISION__ < 4)
/* Disabling Peripherals with DMA Running May Cause DMA System Instability */
#define ANOMALY_05000278 (__SILICON_REVISION__ < 4)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
#define ANOMALY_05000281 (__SILICON_REVISION__ < 4)
/* Memory DMA Corruption with 32-Bit Data and Traffic Control */
#define ANOMALY_05000282 (__SILICON_REVISION__ < 4)
@@ -102,8 +98,10 @@
#define ANOMALY_05000313 (__SILICON_REVISION__ < 4)
/* Killed System MMR Write Completes Erroneously on Next System MMR Access */
#define ANOMALY_05000315 (__SILICON_REVISION__ < 4)
+/* PFx Glitch on Write to PORTFIO or PORTFIO_TOGGLE */
+#define ANOMALY_05000317 (__SILICON_REVISION__ < 4) /* XXX: Same as 05000318 */
/* PFx Glitch on Write to FIO_FLAG_D or FIO_FLAG_T */
-#define ANOMALY_05000318 (ANOMALY_BF539 && __SILICON_REVISION__ < 4)
+#define ANOMALY_05000318 (__SILICON_REVISION__ < 4) /* XXX: Same as 05000317 */
/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
#define ANOMALY_05000355 (__SILICON_REVISION__ < 5)
/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
@@ -134,16 +132,32 @@
#define ANOMALY_05000461 (1)
/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
#define ANOMALY_05000462 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
#define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
#define ANOMALY_05000475 (1)
/* TESTSET Instruction Cannot Be Interrupted */
#define ANOMALY_05000477 (1)
/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
#define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
#define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
+#define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
+/* DCPLB_FAULT_ADDR MMR Register May Be Corrupted */
+#define ANOMALY_05000261 (__SILICON_REVISION__ < 3)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf538/include/mach/gpio.h b/arch/blackfin/mach-bf538/include/mach/gpio.h
index 8a5beeece996..3561c7d8935b 100644
--- a/arch/blackfin/mach-bf538/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf538/include/mach/gpio.h
@@ -8,7 +8,10 @@
#define _MACH_GPIO_H_
#define MAX_BLACKFIN_GPIOS 16
+#ifdef CONFIG_GPIOLIB
+/* We only use the special logic with GPIOLIB devices */
#define BFIN_SPECIAL_GPIO_BANKS 3
+#endif
#define GPIO_PF0 0 /* PF */
#define GPIO_PF1 1
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index d11502ac5623..212b9e0a08c8 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -861,16 +861,10 @@ static struct flash_platform_data bfin_spi_flash_data = {
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -886,13 +880,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bf54x_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -915,7 +902,6 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -924,7 +910,6 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
};
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 311bf9970fe7..cd9cbb68de69 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -1018,24 +1018,10 @@ static struct flash_platform_data bfin_spi_flash_data = {
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
};
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-
static const struct ad7877_platform_data bfin_ad7877_ts_info = {
.model = 7877,
.vref_delay_usecs = 50, /* internal, no capacitor */
@@ -1051,20 +1037,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
- .enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -1086,7 +1058,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 1,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
@@ -1097,7 +1068,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
- .controller_data = &spi_ad7877_chip_info,
},
#endif
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -1106,7 +1076,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
@@ -1117,7 +1086,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 1,
.chip_select = 2,
- .controller_data = &spi_adxl34x_chip_info,
.mode = SPI_MODE_3,
},
#endif
diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h
index 9e70785bdde3..ac96ee83b00e 100644
--- a/arch/blackfin/mach-bf548/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h
@@ -11,7 +11,7 @@
*/
/* This file should be up to date with:
- * - Revision J, 06/03/2010; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
+ * - Revision K, 05/23/2011; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -29,117 +29,37 @@
/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
#define ANOMALY_05000122 (1)
/* Data Corruption/Core Hang with L2/L3 Configured in Writeback Cache Mode */
-#define ANOMALY_05000220 (1)
+#define ANOMALY_05000220 (__SILICON_REVISION__ < 4)
/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
#define ANOMALY_05000245 (1)
/* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
#define ANOMALY_05000265 (1)
/* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
#define ANOMALY_05000272 (1)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
-#define ANOMALY_05000281 (__SILICON_REVISION__ < 1)
-/* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
-#define ANOMALY_05000304 (__SILICON_REVISION__ < 1)
/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
#define ANOMALY_05000310 (1)
-/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
-#define ANOMALY_05000312 (__SILICON_REVISION__ < 1)
-/* TWI Slave Boot Mode Is Not Functional */
-#define ANOMALY_05000324 (__SILICON_REVISION__ < 1)
/* FIFO Boot Mode Not Functional */
#define ANOMALY_05000325 (__SILICON_REVISION__ < 2)
-/* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */
-#define ANOMALY_05000327 (__SILICON_REVISION__ < 1)
-/* Incorrect Access of OTP_STATUS During otp_write() Function */
-#define ANOMALY_05000328 (__SILICON_REVISION__ < 1)
-/* Synchronous Burst Flash Boot Mode Is Not Functional */
-#define ANOMALY_05000329 (__SILICON_REVISION__ < 1)
-/* Host DMA Boot Modes Are Not Functional */
-#define ANOMALY_05000330 (__SILICON_REVISION__ < 1)
-/* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */
-#define ANOMALY_05000334 (__SILICON_REVISION__ < 1)
-/* Inadequate Rotary Debounce Logic Duration */
-#define ANOMALY_05000335 (__SILICON_REVISION__ < 1)
-/* Phantom Interrupt Occurs After First Configuration of Host DMA Port */
-#define ANOMALY_05000336 (__SILICON_REVISION__ < 1)
-/* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
-#define ANOMALY_05000337 (__SILICON_REVISION__ < 1)
-/* Slave-Mode SPI0 MISO Failure With CPHA = 0 */
-#define ANOMALY_05000338 (__SILICON_REVISION__ < 1)
-/* If Memory Reads Are Enabled on SDH or HOSTDP, Other DMAC1 Peripherals Cannot Read */
-#define ANOMALY_05000340 (__SILICON_REVISION__ < 1)
-/* Boot Host Wait (HWAIT) and Boot Host Wait Alternate (HWAITA) Signals Are Swapped */
-#define ANOMALY_05000344 (__SILICON_REVISION__ < 1)
-/* USB Calibration Value Is Not Initialized */
-#define ANOMALY_05000346 (__SILICON_REVISION__ < 1)
-/* USB Calibration Value to use */
-#define ANOMALY_05000346_value 0x5411
-/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
-#define ANOMALY_05000347 (__SILICON_REVISION__ < 1)
-/* Data Lost when Core Reads SDH Data FIFO */
-#define ANOMALY_05000349 (__SILICON_REVISION__ < 1)
-/* PLL Status Register Is Inaccurate */
-#define ANOMALY_05000351 (__SILICON_REVISION__ < 1)
/* bfrom_SysControl() Firmware Function Performs Improper System Reset */
/*
* Note: anomaly sheet says this is fixed with bf54x-0.2+, but testing
* shows that the fix itself does not cover all cases.
*/
#define ANOMALY_05000353 (1)
-/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
-#define ANOMALY_05000355 (__SILICON_REVISION__ < 1)
-/* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */
-#define ANOMALY_05000356 (__SILICON_REVISION__ < 1)
/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
#define ANOMALY_05000357 (1)
/* External Memory Read Access Hangs Core With PLL Bypass */
#define ANOMALY_05000360 (1)
/* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */
#define ANOMALY_05000365 (1)
-/* WURESET Bit In SYSCR Register Does Not Properly Indicate Hibernate Wake-Up */
-#define ANOMALY_05000367 (__SILICON_REVISION__ < 1)
/* Addressing Conflict between Boot ROM and Asynchronous Memory */
#define ANOMALY_05000369 (1)
-/* Default PLL MSEL and SSEL Settings Can Cause 400MHz Product To Violate Specifications */
-#define ANOMALY_05000370 (__SILICON_REVISION__ < 1)
/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
#define ANOMALY_05000371 (__SILICON_REVISION__ < 2)
-/* USB DP/DM Data Pins May Lose State When Entering Hibernate */
-#define ANOMALY_05000372 (__SILICON_REVISION__ < 1)
/* Security/Authentication Speedpath Causes Authentication To Fail To Initiate */
#define ANOMALY_05000378 (__SILICON_REVISION__ < 2)
/* 16-Bit NAND FLASH Boot Mode Is Not Functional */
#define ANOMALY_05000379 (1)
-/* 8-Bit NAND Flash Boot Mode Not Functional */
-#define ANOMALY_05000382 (__SILICON_REVISION__ < 1)
-/* Some ATAPI Modes Are Not Functional */
-#define ANOMALY_05000383 (1)
-/* Boot from OTP Memory Not Functional */
-#define ANOMALY_05000385 (__SILICON_REVISION__ < 1)
-/* bfrom_SysControl() Firmware Routine Not Functional */
-#define ANOMALY_05000386 (__SILICON_REVISION__ < 1)
-/* Programmable Preboot Settings Not Functional */
-#define ANOMALY_05000387 (__SILICON_REVISION__ < 1)
-/* CRC32 Checksum Support Not Functional */
-#define ANOMALY_05000388 (__SILICON_REVISION__ < 1)
-/* Reset Vector Must Not Be in SDRAM Memory Space */
-#define ANOMALY_05000389 (__SILICON_REVISION__ < 1)
-/* Changed Meaning of BCODE Field in SYSCR Register */
-#define ANOMALY_05000390 (__SILICON_REVISION__ < 1)
-/* Repeated Boot from Page-Mode or Burst-Mode Flash Memory May Fail */
-#define ANOMALY_05000391 (__SILICON_REVISION__ < 1)
-/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */
-#define ANOMALY_05000392 (__SILICON_REVISION__ < 1)
-/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */
-#define ANOMALY_05000393 (__SILICON_REVISION__ < 1)
-/* Log Buffer Not Functional */
-#define ANOMALY_05000394 (__SILICON_REVISION__ < 1)
-/* Hook Routine Not Functional */
-#define ANOMALY_05000395 (__SILICON_REVISION__ < 1)
-/* Header Indirect Bit Not Functional */
-#define ANOMALY_05000396 (__SILICON_REVISION__ < 1)
-/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */
-#define ANOMALY_05000397 (__SILICON_REVISION__ < 1)
/* Lockbox SESR Disallows Certain User Interrupts */
#define ANOMALY_05000404 (__SILICON_REVISION__ < 2)
/* Lockbox SESR Firmware Does Not Save/Restore Full Context */
@@ -161,7 +81,7 @@
/* Speculative Fetches Can Cause Undesired External FIFO Operations */
#define ANOMALY_05000416 (1)
/* Multichannel SPORT Channel Misalignment Under Specific Configuration */
-#define ANOMALY_05000425 (1)
+#define ANOMALY_05000425 (__SILICON_REVISION__ < 4)
/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
#define ANOMALY_05000426 (1)
/* CORE_EPPI_PRIO bit and SYS_EPPI_PRIO bit in the HMDMA1_CONTROL register are not functional */
@@ -174,8 +94,6 @@
#define ANOMALY_05000431 (__SILICON_REVISION__ < 3)
/* SW Breakpoints Ignored Upon Return From Lockbox Authentication */
#define ANOMALY_05000434 (1)
-/* OTP Write Accesses Not Supported */
-#define ANOMALY_05000442 (__SILICON_REVISION__ < 1)
/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
#define ANOMALY_05000443 (1)
/* CDMAPRIO and L2DMAPRIO Bits in the SYSCR Register Are Not Functional */
@@ -186,34 +104,32 @@
#define ANOMALY_05000448 (__SILICON_REVISION__ == 1)
/* Reduced Timing Margins on DDR Output Setup and Hold (tDS and tDH) */
#define ANOMALY_05000449 (__SILICON_REVISION__ == 1)
-/* USB DMA Mode 1 Short Packet Data Corruption */
+/* USB DMA Short Packet Data Corruption */
#define ANOMALY_05000450 (1)
-/* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
-#define ANOMALY_05000452 (__SILICON_REVISION__ < 1)
/* USB Receive Interrupt Is Not Generated in DMA Mode 1 */
#define ANOMALY_05000456 (1)
/* Host DMA Port Responds to Certain Bus Activity Without HOST_CE Assertion */
#define ANOMALY_05000457 (1)
/* USB DMA Mode 1 Failure When Multiple USB DMA Channels Are Concurrently Enabled */
-#define ANOMALY_05000460 (1)
+#define ANOMALY_05000460 (__SILICON_REVISION__ < 4)
/* False Hardware Error when RETI Points to Invalid Memory */
#define ANOMALY_05000461 (1)
/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
-#define ANOMALY_05000462 (1)
+#define ANOMALY_05000462 (__SILICON_REVISION__ < 4)
/* USB DMA RX Data Corruption */
-#define ANOMALY_05000463 (1)
+#define ANOMALY_05000463 (__SILICON_REVISION__ < 4)
/* USB TX DMA Hang */
-#define ANOMALY_05000464 (1)
-/* USB Rx DMA hang */
+#define ANOMALY_05000464 (__SILICON_REVISION__ < 4)
+/* USB Rx DMA Hang */
#define ANOMALY_05000465 (1)
/* TxPktRdy Bit Not Set for Transmit Endpoint When Core and DMA Access USB Endpoint FIFOs Simultaneously */
-#define ANOMALY_05000466 (1)
-/* Possible RX data corruption when control & data EP FIFOs are accessed via the core */
-#define ANOMALY_05000467 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+#define ANOMALY_05000466 (__SILICON_REVISION__ < 4)
+/* Possible USB RX Data Corruption When Control & Data EP FIFOs are Accessed via the Core */
+#define ANOMALY_05000467 (__SILICON_REVISION__ < 4)
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
#define ANOMALY_05000473 (1)
-/* Access to DDR-SDRAM causes system hang under certain PLL/VR settings */
-#define ANOMALY_05000474 (1)
+/* Access to DDR SDRAM Causes System Hang with Certain PLL Settings */
+#define ANOMALY_05000474 (__SILICON_REVISION__ < 4)
/* TESTSET Instruction Cannot Be Interrupted */
#define ANOMALY_05000477 (1)
/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
@@ -223,9 +139,111 @@
/* DDR Trim May Not Be Performed for Certain VLEV Values in OTP Page PBS00L */
#define ANOMALY_05000484 (__SILICON_REVISION__ < 3)
/* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */
-#define ANOMALY_05000485 (__SILICON_REVISION__ >= 2)
-/* IFLUSH sucks at life */
+#define ANOMALY_05000485 (__SILICON_REVISION__ > 1 && __SILICON_REVISION__ < 4)
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* SPI Master Boot Can Fail Under Certain Conditions */
+#define ANOMALY_05000490 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
#define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* CNT_COMMAND Functionality Depends on CNT_IMASK Configuration */
+#define ANOMALY_05000498 (1)
+/* Nand Flash Controller Hangs When the AMC Requests the Async Pins During the last 16 Bytes of a Page Write Operation. */
+#define ANOMALY_05000500 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+/* Async Memory Writes May Be Skipped When Using Odd Clock Ratios */
+#define ANOMALY_05000502 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* False Hardware Error when ISR Context Is Not Restored */
+#define ANOMALY_05000281 (__SILICON_REVISION__ < 1)
+/* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
+#define ANOMALY_05000304 (__SILICON_REVISION__ < 1)
+/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+#define ANOMALY_05000312 (__SILICON_REVISION__ < 1)
+/* TWI Slave Boot Mode Is Not Functional */
+#define ANOMALY_05000324 (__SILICON_REVISION__ < 1)
+/* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */
+#define ANOMALY_05000327 (__SILICON_REVISION__ < 1)
+/* Incorrect Access of OTP_STATUS During otp_write() Function */
+#define ANOMALY_05000328 (__SILICON_REVISION__ < 1)
+/* Synchronous Burst Flash Boot Mode Is Not Functional */
+#define ANOMALY_05000329 (__SILICON_REVISION__ < 1)
+/* Host DMA Boot Modes Are Not Functional */
+#define ANOMALY_05000330 (__SILICON_REVISION__ < 1)
+/* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */
+#define ANOMALY_05000334 (__SILICON_REVISION__ < 1)
+/* Inadequate Rotary Debounce Logic Duration */
+#define ANOMALY_05000335 (__SILICON_REVISION__ < 1)
+/* Phantom Interrupt Occurs After First Configuration of Host DMA Port */
+#define ANOMALY_05000336 (__SILICON_REVISION__ < 1)
+/* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
+#define ANOMALY_05000337 (__SILICON_REVISION__ < 1)
+/* Slave-Mode SPI0 MISO Failure With CPHA = 0 */
+#define ANOMALY_05000338 (__SILICON_REVISION__ < 1)
+/* If Memory Reads Are Enabled on SDH or HOSTDP, Other DMAC1 Peripherals Cannot Read */
+#define ANOMALY_05000340 (__SILICON_REVISION__ < 1)
+/* Boot Host Wait (HWAIT) and Boot Host Wait Alternate (HWAITA) Signals Are Swapped */
+#define ANOMALY_05000344 (__SILICON_REVISION__ < 1)
+/* USB Calibration Value Is Not Initialized */
+#define ANOMALY_05000346 (__SILICON_REVISION__ < 1)
+/* USB Calibration Value to use */
+#define ANOMALY_05000346_value 0x5411
+/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
+#define ANOMALY_05000347 (__SILICON_REVISION__ < 1)
+/* Data Lost when Core Reads SDH Data FIFO */
+#define ANOMALY_05000349 (__SILICON_REVISION__ < 1)
+/* PLL Status Register Is Inaccurate */
+#define ANOMALY_05000351 (__SILICON_REVISION__ < 1)
+/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
+#define ANOMALY_05000355 (__SILICON_REVISION__ < 1)
+/* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */
+#define ANOMALY_05000356 (__SILICON_REVISION__ < 1)
+/* WURESET Bit In SYSCR Register Does Not Properly Indicate Hibernate Wake-Up */
+#define ANOMALY_05000367 (__SILICON_REVISION__ < 1)
+/* Default PLL MSEL and SSEL Settings Can Cause 400MHz Product To Violate Specifications */
+#define ANOMALY_05000370 (__SILICON_REVISION__ < 1)
+/* USB DP/DM Data Pins May Lose State When Entering Hibernate */
+#define ANOMALY_05000372 (__SILICON_REVISION__ < 1)
+/* 8-Bit NAND Flash Boot Mode Not Functional */
+#define ANOMALY_05000382 (__SILICON_REVISION__ < 1)
+/* Boot from OTP Memory Not Functional */
+#define ANOMALY_05000385 (__SILICON_REVISION__ < 1)
+/* bfrom_SysControl() Firmware Routine Not Functional */
+#define ANOMALY_05000386 (__SILICON_REVISION__ < 1)
+/* Programmable Preboot Settings Not Functional */
+#define ANOMALY_05000387 (__SILICON_REVISION__ < 1)
+/* CRC32 Checksum Support Not Functional */
+#define ANOMALY_05000388 (__SILICON_REVISION__ < 1)
+/* Reset Vector Must Not Be in SDRAM Memory Space */
+#define ANOMALY_05000389 (__SILICON_REVISION__ < 1)
+/* Changed Meaning of BCODE Field in SYSCR Register */
+#define ANOMALY_05000390 (__SILICON_REVISION__ < 1)
+/* Repeated Boot from Page-Mode or Burst-Mode Flash Memory May Fail */
+#define ANOMALY_05000391 (__SILICON_REVISION__ < 1)
+/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000392 (__SILICON_REVISION__ < 1)
+/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000393 (__SILICON_REVISION__ < 1)
+/* Log Buffer Not Functional */
+#define ANOMALY_05000394 (__SILICON_REVISION__ < 1)
+/* Hook Routine Not Functional */
+#define ANOMALY_05000395 (__SILICON_REVISION__ < 1)
+/* Header Indirect Bit Not Functional */
+#define ANOMALY_05000396 (__SILICON_REVISION__ < 1)
+/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */
+#define ANOMALY_05000397 (__SILICON_REVISION__ < 1)
+/* OTP Write Accesses Not Supported */
+#define ANOMALY_05000442 (__SILICON_REVISION__ < 1)
+/* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
+#define ANOMALY_05000452 (__SILICON_REVISION__ < 1)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf548/include/mach/gpio.h b/arch/blackfin/mach-bf548/include/mach/gpio.h
index 7db433514e3f..35c8ced46158 100644
--- a/arch/blackfin/mach-bf548/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf548/include/mach/gpio.h
@@ -170,6 +170,8 @@
#define MAX_BLACKFIN_GPIOS 160
+#define BFIN_GPIO_PINT 1
+
#ifndef __ASSEMBLY__
struct gpio_port_t {
diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h
index 533b8095b540..10dc142c518d 100644
--- a/arch/blackfin/mach-bf548/include/mach/irq.h
+++ b/arch/blackfin/mach-bf548/include/mach/irq.h
@@ -438,7 +438,7 @@
struct bfin_pint_regs {
u32 mask_set;
u32 mask_clear;
- u32 irq;
+ u32 request;
u32 assign;
u32 edge_set;
u32 edge_clear;
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
index 9231a942892b..972e1347c6bc 100644
--- a/arch/blackfin/mach-bf561/boards/acvilon.c
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -364,14 +364,6 @@ static struct flash_platform_data bfin_spi_dataflash_data = {
/* DataFlash chip */
static struct bfin5xx_spi_chip data_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip */
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -420,7 +412,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 3,
- .controller_data = &spidev_chip_info,
},
#endif
#if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 87595cd38afe..e4f397d1d65b 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -60,29 +60,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
/* SPI flash chip (m25p64) */
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
- .bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
- .enable_dma = 1, /* use dma transfer with this chip*/
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
-static struct bfin5xx_spi_chip mmc_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
};
#endif
@@ -100,24 +77,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
- {
- .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
- .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0, /* Framework bus number */
- .chip_select = 1, /* Framework chip select. */
- .platform_data = NULL, /* No spi_driver specific config */
- .controller_data = &spi_adc_chip_info,
- },
-#endif
-
#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
.modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
- .controller_data = &ad1836_spi_chip_info,
},
#endif
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -126,7 +91,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &mmc_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -532,6 +496,24 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
#endif
};
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ int ret;
+
+ ret = gpio_request(GPIO_PF46, "net2272");
+ if (ret)
+ return ret;
+
+ /* Reset USB Chip, PF46 */
+ gpio_direction_output(GPIO_PF46, 0);
+ mdelay(2);
+ gpio_set_value(GPIO_PF46, 1);
+#endif
+
+ return 0;
+}
+
static int __init cm_bf561_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -543,6 +525,10 @@ static int __init cm_bf561_init(void)
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
#endif
+
+ if (net2272_init())
+ pr_warning("unable to configure net2272; it probably won't work\n");
+
return 0;
}
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 5067984a62e7..9490dc800ca5 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -108,6 +108,9 @@ static struct resource net2272_bfin_resources[] = {
.end = 0x2C000000 + 0x7F,
.flags = IORESOURCE_MEM,
}, {
+ .start = 1,
+ .flags = IORESOURCE_BUS,
+ }, {
.start = IRQ_PF10,
.end = IRQ_PF10,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
@@ -283,21 +286,6 @@ static struct platform_device ezkit_flash_device = {
};
#endif
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
- .enable_dma = 0,
- .bits_per_word = 8,
-};
-#endif
-
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
/* SPI (0) */
static struct resource bfin_spi0_resource[] = {
@@ -345,7 +333,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = 4,
.platform_data = "ad1836", /* only includes chip name for the moment */
- .controller_data = &ad1836_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -355,7 +342,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
- .controller_data = &spidev_chip_info,
},
#endif
};
@@ -516,6 +502,24 @@ static struct platform_device *ezkit_devices[] __initdata = {
#endif
};
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ int ret;
+
+ ret = gpio_request(GPIO_PF11, "net2272");
+ if (ret)
+ return ret;
+
+ /* Reset the USB chip */
+ gpio_direction_output(GPIO_PF11, 0);
+ mdelay(2);
+ gpio_set_value(GPIO_PF11, 1);
+#endif
+
+ return 0;
+}
+
static int __init ezkit_init(void)
{
int ret;
@@ -542,6 +546,9 @@ static int __init ezkit_init(void)
udelay(400);
#endif
+ if (net2272_init())
+ pr_warning("unable to configure net2272; it probably won't work\n");
+
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
return 0;
}
diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h
index 22b5ab773027..836baeed303a 100644
--- a/arch/blackfin/mach-bf561/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h
@@ -11,7 +11,7 @@
*/
/* This file should be up to date with:
- * - Revision R, 05/25/2010; ADSP-BF561 Blackfin Processor Anomaly List
+ * - Revision S, 05/23/2011; ADSP-BF561 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -26,62 +26,16 @@
#define ANOMALY_05000074 (1)
/* UART Line Status Register (UART_LSR) Bits Are Not Updated at the Same Time */
#define ANOMALY_05000099 (__SILICON_REVISION__ < 5)
-/* Trace Buffers May Contain Errors in Emulation Mode and/or Exception, NMI, Reset Handlers */
-#define ANOMALY_05000116 (__SILICON_REVISION__ < 3)
/* TESTSET Instructions Restricted to 32-Bit Aligned Memory Locations */
#define ANOMALY_05000120 (1)
/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
#define ANOMALY_05000122 (1)
-/* Erroneous Exception when Enabling Cache */
-#define ANOMALY_05000125 (__SILICON_REVISION__ < 3)
/* SIGNBITS Instruction Not Functional under Certain Conditions */
#define ANOMALY_05000127 (1)
-/* Two bits in the Watchpoint Status Register (WPSTAT) are swapped */
-#define ANOMALY_05000134 (__SILICON_REVISION__ < 3)
-/* Enable wires from the Data Watchpoint Address Control Register (WPDACTL) are swapped */
-#define ANOMALY_05000135 (__SILICON_REVISION__ < 3)
-/* Stall in multi-unit DMA operations */
-#define ANOMALY_05000136 (__SILICON_REVISION__ < 3)
-/* Allowing the SPORT RX FIFO to fill will cause an overflow */
-#define ANOMALY_05000140 (__SILICON_REVISION__ < 3)
-/* Infinite Stall may occur with a particular sequence of consecutive dual dag events */
-#define ANOMALY_05000141 (__SILICON_REVISION__ < 3)
-/* Interrupts may be lost when a programmable input flag is configured to be edge sensitive */
-#define ANOMALY_05000142 (__SILICON_REVISION__ < 3)
-/* DMA and TESTSET conflict when both are accessing external memory */
-#define ANOMALY_05000144 (__SILICON_REVISION__ < 3)
-/* In PWM_OUT mode, you must enable the PPI block to generate a waveform from PPI_CLK */
-#define ANOMALY_05000145 (__SILICON_REVISION__ < 3)
-/* MDMA may lose the first few words of a descriptor chain */
-#define ANOMALY_05000146 (__SILICON_REVISION__ < 3)
-/* Source MDMA descriptor may stop with a DMA Error near beginning of descriptor fetch */
-#define ANOMALY_05000147 (__SILICON_REVISION__ < 3)
/* IMDMA S1/D1 Channel May Stall */
#define ANOMALY_05000149 (1)
-/* DMA engine may lose data due to incorrect handshaking */
-#define ANOMALY_05000150 (__SILICON_REVISION__ < 3)
-/* DMA stalls when all three controllers read data from the same source */
-#define ANOMALY_05000151 (__SILICON_REVISION__ < 3)
-/* Execution stall when executing in L2 and doing external accesses */
-#define ANOMALY_05000152 (__SILICON_REVISION__ < 3)
-/* Frame Delay in SPORT Multichannel Mode */
-#define ANOMALY_05000153 (__SILICON_REVISION__ < 3)
-/* SPORT TFS signal stays active in multichannel mode outside of valid channels */
-#define ANOMALY_05000154 (__SILICON_REVISION__ < 3)
/* Timers in PWM-Out Mode with PPI GP Receive (Input) Mode with 0 Frame Syncs */
#define ANOMALY_05000156 (__SILICON_REVISION__ < 4)
-/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
-#define ANOMALY_05000157 (__SILICON_REVISION__ < 3)
-/* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1, or 1:1 */
-#define ANOMALY_05000159 (__SILICON_REVISION__ < 3)
-/* A read from external memory may return a wrong value with data cache enabled */
-#define ANOMALY_05000160 (__SILICON_REVISION__ < 3)
-/* Data Cache Fill data can be corrupted after/during Instruction DMA if certain core stalls exist */
-#define ANOMALY_05000161 (__SILICON_REVISION__ < 3)
-/* DMEM_CONTROL<12> is not set on Reset */
-#define ANOMALY_05000162 (__SILICON_REVISION__ < 3)
-/* SPORT Transmit Data Is Not Gated by External Frame Sync in Certain Conditions */
-#define ANOMALY_05000163 (__SILICON_REVISION__ < 3)
/* PPI Data Lengths between 8 and 16 Do Not Zero Out Upper Bits */
#define ANOMALY_05000166 (1)
/* Turning SPORTs on while External Frame Sync Is Active May Corrupt Data */
@@ -92,10 +46,6 @@
#define ANOMALY_05000169 (__SILICON_REVISION__ < 5)
/* Boot-ROM Modifies SICA_IWRx Wakeup Registers */
#define ANOMALY_05000171 (__SILICON_REVISION__ < 5)
-/* DSPID register values incorrect */
-#define ANOMALY_05000172 (__SILICON_REVISION__ < 3)
-/* DMA vs Core accesses to external memory */
-#define ANOMALY_05000173 (__SILICON_REVISION__ < 3)
/* Cache Fill Buffer Data lost */
#define ANOMALY_05000174 (__SILICON_REVISION__ < 5)
/* Overlapping Sequencer and Memory Stalls */
@@ -124,8 +74,6 @@
#define ANOMALY_05000189 (__SILICON_REVISION__ < 5)
/* PPI Not Functional at Core Voltage < 1Volt */
#define ANOMALY_05000190 (1)
-/* PPI does not invert the Driving PPICLK edge in Transmit Modes */
-#define ANOMALY_05000191 (__SILICON_REVISION__ < 3)
/* False I/O Pin Interrupts on Edge-Sensitive Inputs When Polarity Setting Is Changed */
#define ANOMALY_05000193 (__SILICON_REVISION__ < 5)
/* Restarting SPORT in Specific Modes May Cause Data Corruption */
@@ -217,10 +165,10 @@
/* Timing Requirements Change for External Frame Sync PPI Modes with Non-Zero PPI_DELAY */
#define ANOMALY_05000276 (__SILICON_REVISION__ < 5)
/* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
-#define ANOMALY_05000277 (__SILICON_REVISION__ < 3)
+#define ANOMALY_05000277 (__SILICON_REVISION__ < 5)
/* Disabling Peripherals with DMA Running May Cause DMA System Instability */
#define ANOMALY_05000278 (__SILICON_REVISION__ < 5)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
/* Temporarily walk around for bug 5423 till this issue is confirmed by
* official anomaly document. It looks 05000281 still exists on bf561
* v0.5.
@@ -274,8 +222,6 @@
#define ANOMALY_05000366 (1)
/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
#define ANOMALY_05000371 (1)
-/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
-#define ANOMALY_05000402 (__SILICON_REVISION__ == 4)
/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
#define ANOMALY_05000403 (1)
/* TESTSET Instruction Causes Data Corruption with Writeback Data Cache Enabled */
@@ -298,16 +244,82 @@
#define ANOMALY_05000462 (1)
/* Boot Failure When SDRAM Control Signals Toggle Coming Out Of Reset */
#define ANOMALY_05000471 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
#define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
#define ANOMALY_05000475 (1)
/* TESTSET Instruction Cannot Be Interrupted */
#define ANOMALY_05000477 (1)
/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
#define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
#define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* Trace Buffers May Contain Errors in Emulation Mode and/or Exception, NMI, Reset Handlers */
+#define ANOMALY_05000116 (__SILICON_REVISION__ < 3)
+/* Erroneous Exception when Enabling Cache */
+#define ANOMALY_05000125 (__SILICON_REVISION__ < 3)
+/* Two bits in the Watchpoint Status Register (WPSTAT) are swapped */
+#define ANOMALY_05000134 (__SILICON_REVISION__ < 3)
+/* Enable wires from the Data Watchpoint Address Control Register (WPDACTL) are swapped */
+#define ANOMALY_05000135 (__SILICON_REVISION__ < 3)
+/* Stall in multi-unit DMA operations */
+#define ANOMALY_05000136 (__SILICON_REVISION__ < 3)
+/* Allowing the SPORT RX FIFO to fill will cause an overflow */
+#define ANOMALY_05000140 (__SILICON_REVISION__ < 3)
+/* Infinite Stall may occur with a particular sequence of consecutive dual dag events */
+#define ANOMALY_05000141 (__SILICON_REVISION__ < 3)
+/* Interrupts may be lost when a programmable input flag is configured to be edge sensitive */
+#define ANOMALY_05000142 (__SILICON_REVISION__ < 3)
+/* DMA and TESTSET conflict when both are accessing external memory */
+#define ANOMALY_05000144 (__SILICON_REVISION__ < 3)
+/* In PWM_OUT mode, you must enable the PPI block to generate a waveform from PPI_CLK */
+#define ANOMALY_05000145 (__SILICON_REVISION__ < 3)
+/* MDMA may lose the first few words of a descriptor chain */
+#define ANOMALY_05000146 (__SILICON_REVISION__ < 3)
+/* Source MDMA descriptor may stop with a DMA Error near beginning of descriptor fetch */
+#define ANOMALY_05000147 (__SILICON_REVISION__ < 3)
+/* DMA engine may lose data due to incorrect handshaking */
+#define ANOMALY_05000150 (__SILICON_REVISION__ < 3)
+/* DMA stalls when all three controllers read data from the same source */
+#define ANOMALY_05000151 (__SILICON_REVISION__ < 3)
+/* Execution stall when executing in L2 and doing external accesses */
+#define ANOMALY_05000152 (__SILICON_REVISION__ < 3)
+/* Frame Delay in SPORT Multichannel Mode */
+#define ANOMALY_05000153 (__SILICON_REVISION__ < 3)
+/* SPORT TFS signal stays active in multichannel mode outside of valid channels */
+#define ANOMALY_05000154 (__SILICON_REVISION__ < 3)
+/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
+#define ANOMALY_05000157 (__SILICON_REVISION__ < 3)
+/* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1, or 1:1 */
+#define ANOMALY_05000159 (__SILICON_REVISION__ < 3)
+/* A read from external memory may return a wrong value with data cache enabled */
+#define ANOMALY_05000160 (__SILICON_REVISION__ < 3)
+/* Data Cache Fill data can be corrupted after/during Instruction DMA if certain core stalls exist */
+#define ANOMALY_05000161 (__SILICON_REVISION__ < 3)
+/* DMEM_CONTROL<12> is not set on Reset */
+#define ANOMALY_05000162 (__SILICON_REVISION__ < 3)
+/* SPORT Transmit Data Is Not Gated by External Frame Sync in Certain Conditions */
+#define ANOMALY_05000163 (__SILICON_REVISION__ < 3)
+/* DSPID register values incorrect */
+#define ANOMALY_05000172 (__SILICON_REVISION__ < 3)
+/* DMA vs Core accesses to external memory */
+#define ANOMALY_05000173 (__SILICON_REVISION__ < 3)
+/* PPI does not invert the Driving PPICLK edge in Transmit Modes */
+#define ANOMALY_05000191 (__SILICON_REVISION__ < 3)
+/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
+#define ANOMALY_05000402 (__SILICON_REVISION__ == 4)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000119 (0)
diff --git a/arch/blackfin/mach-bf561/include/mach/gpio.h b/arch/blackfin/mach-bf561/include/mach/gpio.h
index 57d5eab59faf..f9f8b2adf4ba 100644
--- a/arch/blackfin/mach-bf561/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf561/include/mach/gpio.h
@@ -58,9 +58,9 @@
#define GPIO_PF46 46
#define GPIO_PF47 47
-#define PORT_FIO0 GPIO_0
-#define PORT_FIO1 GPIO_16
-#define PORT_FIO2 GPIO_32
+#define PORT_FIO0 GPIO_PF0
+#define PORT_FIO1 GPIO_PF16
+#define PORT_FIO2 GPIO_PF32
#include <mach-common/ports-f.h>
diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S
index 4c462838f4e1..01e5408620ac 100644
--- a/arch/blackfin/mach-bf561/secondary.S
+++ b/arch/blackfin/mach-bf561/secondary.S
@@ -23,108 +23,78 @@
#define INITIAL_STACK (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
ENTRY(_coreb_trampoline_start)
- /* Set the SYSCFG register */
- R0 = 0x36;
- SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
- R0 = 0;
-
- /*Clear Out All the data and pointer Registers*/
- R1 = R0;
- R2 = R0;
- R3 = R0;
- R4 = R0;
- R5 = R0;
- R6 = R0;
- R7 = R0;
-
- P0 = R0;
- P1 = R0;
- P2 = R0;
- P3 = R0;
- P4 = R0;
- P5 = R0;
-
- LC0 = r0;
- LC1 = r0;
- L0 = r0;
- L1 = r0;
- L2 = r0;
- L3 = r0;
-
- /* Clear Out All the DAG Registers*/
- B0 = r0;
- B1 = r0;
- B2 = r0;
- B3 = r0;
-
- I0 = r0;
- I1 = r0;
- I2 = r0;
- I3 = r0;
-
- M0 = r0;
- M1 = r0;
- M2 = r0;
- M3 = r0;
+ /* Enable Cycle Counter and Nesting Of Interrupts */
+#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
+ R0 = SYSCFG_SNEN;
+#else
+ R0 = SYSCFG_SNEN | SYSCFG_CCEN;
+#endif
+ SYSCFG = R0;
- trace_buffer_init(p0,r0);
+ /* Optimization register tricks: keep a base value in the
+ * reserved P registers so we use the load/store with an
+ * offset syntax. R0 = [P5 + <constant>];
+ * P5 - core MMR base
+ * R6 - 0
+ */
+ r6 = 0;
+ p5.l = 0;
+ p5.h = hi(COREMMR_BASE);
- /* Turn off the icache */
- p0.l = LO(IMEM_CONTROL);
- p0.h = HI(IMEM_CONTROL);
- R1 = [p0];
- R0 = ~ENICPLB;
- R0 = R0 & R1;
+ /* Zero out registers required by Blackfin ABI */
- /* Disabling of CPLBs should be proceeded by a CSYNC */
+ /* Disable circular buffers */
+ L0 = r6;
+ L1 = r6;
+ L2 = r6;
+ L3 = r6;
+
+ /* Disable hardware loops in case we were started by 'go' */
+ LC0 = r6;
+ LC1 = r6;
+
+ /*
+ * Clear ITEST_COMMAND and DTEST_COMMAND registers,
+ * Leaving these as non-zero can confuse the emulator
+ */
+ [p5 + (DTEST_COMMAND - COREMMR_BASE)] = r6;
+ [p5 + (ITEST_COMMAND - COREMMR_BASE)] = r6;
CSYNC;
- [p0] = R0;
+
+ trace_buffer_init(p0,r0);
+
+ /* Turn off the icache */
+ r1 = [p5 + (IMEM_CONTROL - COREMMR_BASE)];
+ BITCLR (r1, ENICPLB_P);
+ [p5 + (IMEM_CONTROL - COREMMR_BASE)] = r1;
SSYNC;
/* Turn off the dcache */
- p0.l = LO(DMEM_CONTROL);
- p0.h = HI(DMEM_CONTROL);
- R1 = [p0];
- R0 = ~ENDCPLB;
- R0 = R0 & R1;
-
- /* Disabling of CPLBs should be proceeded by a CSYNC */
- CSYNC;
- [p0] = R0;
+ r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)];
+ BITCLR (r1, ENDCPLB_P);
+ [p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1;
SSYNC;
/* in case of double faults, save a few things */
- p0.l = _init_retx_coreb;
- p0.h = _init_retx_coreb;
- R0 = RETX;
- [P0] = R0;
-
+ p1.l = _initial_pda_coreb;
+ p1.h = _initial_pda_coreb;
+ r4 = RETX;
#ifdef CONFIG_DEBUG_DOUBLEFAULT
/* Only save these if we are storing them,
* This happens here, since L1 gets clobbered
* below
*/
GET_PDA(p0, r0);
- r7 = [p0 + PDA_DF_RETX];
- p1.l = _init_saved_retx_coreb;
- p1.h = _init_saved_retx_coreb;
- [p1] = r7;
-
- r7 = [p0 + PDA_DF_DCPLB];
- p1.l = _init_saved_dcplb_fault_addr_coreb;
- p1.h = _init_saved_dcplb_fault_addr_coreb;
- [p1] = r7;
-
- r7 = [p0 + PDA_DF_ICPLB];
- p1.l = _init_saved_icplb_fault_addr_coreb;
- p1.h = _init_saved_icplb_fault_addr_coreb;
- [p1] = r7;
-
- r7 = [p0 + PDA_DF_SEQSTAT];
- p1.l = _init_saved_seqstat_coreb;
- p1.h = _init_saved_seqstat_coreb;
- [p1] = r7;
+ r0 = [p0 + PDA_DF_RETX];
+ r1 = [p0 + PDA_DF_DCPLB];
+ r2 = [p0 + PDA_DF_ICPLB];
+ r3 = [p0 + PDA_DF_SEQSTAT];
+ [p1 + PDA_INIT_DF_RETX] = r0;
+ [p1 + PDA_INIT_DF_DCPLB] = r1;
+ [p1 + PDA_INIT_DF_ICPLB] = r2;
+ [p1 + PDA_INIT_DF_SEQSTAT] = r3;
#endif
+ [p1 + PDA_INIT_RETX] = r4;
/* Initialize stack pointer */
sp.l = lo(INITIAL_STACK);
@@ -138,19 +108,13 @@ ENTRY(_coreb_trampoline_start)
/* EVT15 = _real_start */
- p0.l = lo(EVT15);
- p0.h = hi(EVT15);
p1.l = _coreb_start;
p1.h = _coreb_start;
- [p0] = p1;
+ [p5 + (EVT15 - COREMMR_BASE)] = p1;
csync;
- p0.l = lo(IMASK);
- p0.h = hi(IMASK);
- p1.l = IMASK_IVG15;
- p1.h = 0x0;
- [p0] = p1;
- csync;
+ r0 = EVT_IVG15 (z);
+ sti r0;
raise 15;
p0.l = .LWAIT_HERE;
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index 9cfdd49a3127..1c534d298de4 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -12,8 +12,8 @@
.section .l1.text
ENTRY(_sleep_mode)
- [--SP] = ( R7:0, P5:0 );
- [--SP] = RETS;
+ [--SP] = (R7:4, P5:3);
+ [--SP] = RETS;
call _set_sic_iwr;
@@ -46,15 +46,25 @@ ENTRY(_sleep_mode)
call _test_pll_locked;
RETS = [SP++];
- ( R7:0, P5:0 ) = [SP++];
+ (R7:4, P5:3) = [SP++];
RTS;
ENDPROC(_sleep_mode)
+/*
+ * This func never returns as it puts the part into hibernate, and
+ * is only called from do_hibernate, so we don't bother saving or
+ * restoring any of the normal C runtime state. When we wake up,
+ * the entry point will be in do_hibernate and not here.
+ *
+ * We accept just one argument -- the value to write to VR_CTL.
+ */
ENTRY(_hibernate_mode)
- [--SP] = ( R7:0, P5:0 );
- [--SP] = RETS;
+ /* Save/setup the regs we need early for minor pipeline optimization */
+ R4 = R0;
+ P3.H = hi(VR_CTL);
+ P3.L = lo(VR_CTL);
- R3 = R0;
+ /* Disable all wakeup sources */
R0 = IWR_DISABLE_ALL;
R1 = IWR_DISABLE_ALL;
R2 = IWR_DISABLE_ALL;
@@ -62,10 +72,8 @@ ENTRY(_hibernate_mode)
call _set_dram_srfs;
SSYNC;
- P0.H = hi(VR_CTL);
- P0.L = lo(VR_CTL);
-
- W[P0] = R3.L;
+ /* Finally, we climb into our cave to hibernate */
+ W[P3] = R4.L;
CLI R2;
IDLE;
.Lforever:
@@ -73,8 +81,8 @@ ENTRY(_hibernate_mode)
ENDPROC(_hibernate_mode)
ENTRY(_sleep_deeper)
- [--SP] = ( R7:0, P5:0 );
- [--SP] = RETS;
+ [--SP] = (R7:4, P5:3);
+ [--SP] = RETS;
CLI R4;
@@ -167,7 +175,7 @@ ENTRY(_sleep_deeper)
STI R4;
RETS = [SP++];
- ( R7:0, P5:0 ) = [SP++];
+ (R7:4, P5:3) = [SP++];
RTS;
ENDPROC(_sleep_deeper)
@@ -188,21 +196,20 @@ ENTRY(_set_dram_srfs)
#else /* SDRAM */
P0.L = lo(EBIU_SDGCTL);
P0.H = hi(EBIU_SDGCTL);
+ P1.L = lo(EBIU_SDSTAT);
+ P1.H = hi(EBIU_SDSTAT);
+
R2 = [P0];
BITSET(R2, 24); /* SRFS enter self-refresh mode */
[P0] = R2;
SSYNC;
- P0.L = lo(EBIU_SDSTAT);
- P0.H = hi(EBIU_SDSTAT);
1:
- R2 = w[P0];
+ R2 = w[P1];
SSYNC;
cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
if !cc jump 1b;
- P0.L = lo(EBIU_SDGCTL);
- P0.H = hi(EBIU_SDGCTL);
R2 = [P0];
BITCLR(R2, 0); /* SCTLE disable CLKOUT */
[P0] = R2;
@@ -212,6 +219,7 @@ ENDPROC(_set_dram_srfs)
ENTRY(_unset_dram_srfs)
/* set the dram out of self refresh mode */
+
#if defined(EBIU_RSTCTL) /* DDR */
P0.H = hi(EBIU_RSTCTL);
P0.L = lo(EBIU_RSTCTL);
@@ -219,42 +227,39 @@ ENTRY(_unset_dram_srfs)
BITCLR(R2, 3); /* clear SRREQ bit */
[P0] = R2;
#elif defined(EBIU_SDGCTL) /* SDRAM */
-
- P0.L = lo(EBIU_SDGCTL); /* release CLKOUT from self-refresh */
+ /* release CLKOUT from self-refresh */
+ P0.L = lo(EBIU_SDGCTL);
P0.H = hi(EBIU_SDGCTL);
+
R2 = [P0];
BITSET(R2, 0); /* SCTLE enable CLKOUT */
[P0] = R2
SSYNC;
- P0.L = lo(EBIU_SDGCTL); /* release SDRAM from self-refresh */
- P0.H = hi(EBIU_SDGCTL);
+ /* release SDRAM from self-refresh */
R2 = [P0];
BITCLR(R2, 24); /* clear SRFS bit */
[P0] = R2
#endif
+
SSYNC;
RTS;
ENDPROC(_unset_dram_srfs)
ENTRY(_set_sic_iwr)
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \
- defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x)
- P0.H = hi(SIC_IWR0);
- P0.L = lo(SIC_IWR0);
- P1.H = hi(SIC_IWR1);
- P1.L = lo(SIC_IWR1);
- [P1] = R1;
-#if defined(CONFIG_BF54x)
- P1.H = hi(SIC_IWR2);
- P1.L = lo(SIC_IWR2);
- [P1] = R2;
-#endif
+#ifdef SIC_IWR0
+ P0.H = hi(SYSMMR_BASE);
+ P0.L = lo(SYSMMR_BASE);
+ [P0 + (SIC_IWR0 - SYSMMR_BASE)] = R0;
+ [P0 + (SIC_IWR1 - SYSMMR_BASE)] = R1;
+# ifdef SIC_IWR2
+ [P0 + (SIC_IWR2 - SYSMMR_BASE)] = R2;
+# endif
#else
P0.H = hi(SIC_IWR);
P0.L = lo(SIC_IWR);
-#endif
[P0] = R0;
+#endif
SSYNC;
RTS;
@@ -272,206 +277,55 @@ ENDPROC(_test_pll_locked)
.section .text
-ENTRY(_do_hibernate)
- [--SP] = ( R7:0, P5:0 );
- [--SP] = RETS;
- /* Save System MMRs */
- R2 = R0;
- P0.H = hi(PLL_CTL);
- P0.L = lo(PLL_CTL);
-
-#ifdef SIC_IMASK0
- PM_SYS_PUSH(SIC_IMASK0)
-#endif
-#ifdef SIC_IMASK1
- PM_SYS_PUSH(SIC_IMASK1)
-#endif
-#ifdef SIC_IMASK2
- PM_SYS_PUSH(SIC_IMASK2)
-#endif
-#ifdef SIC_IMASK
- PM_SYS_PUSH(SIC_IMASK)
-#endif
-#ifdef SIC_IAR0
- PM_SYS_PUSH(SIC_IAR0)
- PM_SYS_PUSH(SIC_IAR1)
- PM_SYS_PUSH(SIC_IAR2)
-#endif
-#ifdef SIC_IAR3
- PM_SYS_PUSH(SIC_IAR3)
-#endif
-#ifdef SIC_IAR4
- PM_SYS_PUSH(SIC_IAR4)
- PM_SYS_PUSH(SIC_IAR5)
- PM_SYS_PUSH(SIC_IAR6)
-#endif
-#ifdef SIC_IAR7
- PM_SYS_PUSH(SIC_IAR7)
-#endif
-#ifdef SIC_IAR8
- PM_SYS_PUSH(SIC_IAR8)
- PM_SYS_PUSH(SIC_IAR9)
- PM_SYS_PUSH(SIC_IAR10)
- PM_SYS_PUSH(SIC_IAR11)
-#endif
+#define PM_REG0 R7
+#define PM_REG1 R6
+#define PM_REG2 R5
+#define PM_REG3 R4
+#define PM_REG4 R3
+#define PM_REG5 R2
+#define PM_REG6 R1
+#define PM_REG7 R0
+#define PM_REG8 P5
+#define PM_REG9 P4
+#define PM_REG10 P3
+#define PM_REG11 P2
+#define PM_REG12 P1
+#define PM_REG13 P0
+
+#define PM_REGSET0 R7:7
+#define PM_REGSET1 R7:6
+#define PM_REGSET2 R7:5
+#define PM_REGSET3 R7:4
+#define PM_REGSET4 R7:3
+#define PM_REGSET5 R7:2
+#define PM_REGSET6 R7:1
+#define PM_REGSET7 R7:0
+#define PM_REGSET8 R7:0, P5:5
+#define PM_REGSET9 R7:0, P5:4
+#define PM_REGSET10 R7:0, P5:3
+#define PM_REGSET11 R7:0, P5:2
+#define PM_REGSET12 R7:0, P5:1
+#define PM_REGSET13 R7:0, P5:0
+
+#define _PM_PUSH(n, x, w, base) PM_REG##n = w[FP + ((x) - (base))];
+#define _PM_POP(n, x, w, base) w[FP + ((x) - (base))] = PM_REG##n;
+#define PM_PUSH_SYNC(n) [--sp] = (PM_REGSET##n);
+#define PM_POP_SYNC(n) (PM_REGSET##n) = [sp++];
+#define PM_PUSH(n, x) PM_REG##n = [FP++];
+#define PM_POP(n, x) [FP--] = PM_REG##n;
+#define PM_CORE_PUSH(n, x) _PM_PUSH(n, x, , COREMMR_BASE)
+#define PM_CORE_POP(n, x) _PM_POP(n, x, , COREMMR_BASE)
+#define PM_SYS_PUSH(n, x) _PM_PUSH(n, x, , SYSMMR_BASE)
+#define PM_SYS_POP(n, x) _PM_POP(n, x, , SYSMMR_BASE)
+#define PM_SYS_PUSH16(n, x) _PM_PUSH(n, x, w, SYSMMR_BASE)
+#define PM_SYS_POP16(n, x) _PM_POP(n, x, w, SYSMMR_BASE)
-#ifdef SIC_IWR
- PM_SYS_PUSH(SIC_IWR)
-#endif
-#ifdef SIC_IWR0
- PM_SYS_PUSH(SIC_IWR0)
-#endif
-#ifdef SIC_IWR1
- PM_SYS_PUSH(SIC_IWR1)
-#endif
-#ifdef SIC_IWR2
- PM_SYS_PUSH(SIC_IWR2)
-#endif
-
-#ifdef PINT0_ASSIGN
- PM_SYS_PUSH(PINT0_MASK_SET)
- PM_SYS_PUSH(PINT1_MASK_SET)
- PM_SYS_PUSH(PINT2_MASK_SET)
- PM_SYS_PUSH(PINT3_MASK_SET)
- PM_SYS_PUSH(PINT0_ASSIGN)
- PM_SYS_PUSH(PINT1_ASSIGN)
- PM_SYS_PUSH(PINT2_ASSIGN)
- PM_SYS_PUSH(PINT3_ASSIGN)
- PM_SYS_PUSH(PINT0_INVERT_SET)
- PM_SYS_PUSH(PINT1_INVERT_SET)
- PM_SYS_PUSH(PINT2_INVERT_SET)
- PM_SYS_PUSH(PINT3_INVERT_SET)
- PM_SYS_PUSH(PINT0_EDGE_SET)
- PM_SYS_PUSH(PINT1_EDGE_SET)
- PM_SYS_PUSH(PINT2_EDGE_SET)
- PM_SYS_PUSH(PINT3_EDGE_SET)
-#endif
-
- PM_SYS_PUSH(EBIU_AMBCTL0)
- PM_SYS_PUSH(EBIU_AMBCTL1)
- PM_SYS_PUSH16(EBIU_AMGCTL)
-
-#ifdef EBIU_FCTL
- PM_SYS_PUSH(EBIU_MBSCTL)
- PM_SYS_PUSH(EBIU_MODE)
- PM_SYS_PUSH(EBIU_FCTL)
-#endif
-
-#ifdef PORTCIO_FER
- PM_SYS_PUSH16(PORTCIO_DIR)
- PM_SYS_PUSH16(PORTCIO_INEN)
- PM_SYS_PUSH16(PORTCIO)
- PM_SYS_PUSH16(PORTCIO_FER)
- PM_SYS_PUSH16(PORTDIO_DIR)
- PM_SYS_PUSH16(PORTDIO_INEN)
- PM_SYS_PUSH16(PORTDIO)
- PM_SYS_PUSH16(PORTDIO_FER)
- PM_SYS_PUSH16(PORTEIO_DIR)
- PM_SYS_PUSH16(PORTEIO_INEN)
- PM_SYS_PUSH16(PORTEIO)
- PM_SYS_PUSH16(PORTEIO_FER)
-#endif
-
- PM_SYS_PUSH16(SYSCR)
-
- /* Save Core MMRs */
- P0.H = hi(SRAM_BASE_ADDRESS);
- P0.L = lo(SRAM_BASE_ADDRESS);
-
- PM_PUSH(DMEM_CONTROL)
- PM_PUSH(DCPLB_ADDR0)
- PM_PUSH(DCPLB_ADDR1)
- PM_PUSH(DCPLB_ADDR2)
- PM_PUSH(DCPLB_ADDR3)
- PM_PUSH(DCPLB_ADDR4)
- PM_PUSH(DCPLB_ADDR5)
- PM_PUSH(DCPLB_ADDR6)
- PM_PUSH(DCPLB_ADDR7)
- PM_PUSH(DCPLB_ADDR8)
- PM_PUSH(DCPLB_ADDR9)
- PM_PUSH(DCPLB_ADDR10)
- PM_PUSH(DCPLB_ADDR11)
- PM_PUSH(DCPLB_ADDR12)
- PM_PUSH(DCPLB_ADDR13)
- PM_PUSH(DCPLB_ADDR14)
- PM_PUSH(DCPLB_ADDR15)
- PM_PUSH(DCPLB_DATA0)
- PM_PUSH(DCPLB_DATA1)
- PM_PUSH(DCPLB_DATA2)
- PM_PUSH(DCPLB_DATA3)
- PM_PUSH(DCPLB_DATA4)
- PM_PUSH(DCPLB_DATA5)
- PM_PUSH(DCPLB_DATA6)
- PM_PUSH(DCPLB_DATA7)
- PM_PUSH(DCPLB_DATA8)
- PM_PUSH(DCPLB_DATA9)
- PM_PUSH(DCPLB_DATA10)
- PM_PUSH(DCPLB_DATA11)
- PM_PUSH(DCPLB_DATA12)
- PM_PUSH(DCPLB_DATA13)
- PM_PUSH(DCPLB_DATA14)
- PM_PUSH(DCPLB_DATA15)
- PM_PUSH(IMEM_CONTROL)
- PM_PUSH(ICPLB_ADDR0)
- PM_PUSH(ICPLB_ADDR1)
- PM_PUSH(ICPLB_ADDR2)
- PM_PUSH(ICPLB_ADDR3)
- PM_PUSH(ICPLB_ADDR4)
- PM_PUSH(ICPLB_ADDR5)
- PM_PUSH(ICPLB_ADDR6)
- PM_PUSH(ICPLB_ADDR7)
- PM_PUSH(ICPLB_ADDR8)
- PM_PUSH(ICPLB_ADDR9)
- PM_PUSH(ICPLB_ADDR10)
- PM_PUSH(ICPLB_ADDR11)
- PM_PUSH(ICPLB_ADDR12)
- PM_PUSH(ICPLB_ADDR13)
- PM_PUSH(ICPLB_ADDR14)
- PM_PUSH(ICPLB_ADDR15)
- PM_PUSH(ICPLB_DATA0)
- PM_PUSH(ICPLB_DATA1)
- PM_PUSH(ICPLB_DATA2)
- PM_PUSH(ICPLB_DATA3)
- PM_PUSH(ICPLB_DATA4)
- PM_PUSH(ICPLB_DATA5)
- PM_PUSH(ICPLB_DATA6)
- PM_PUSH(ICPLB_DATA7)
- PM_PUSH(ICPLB_DATA8)
- PM_PUSH(ICPLB_DATA9)
- PM_PUSH(ICPLB_DATA10)
- PM_PUSH(ICPLB_DATA11)
- PM_PUSH(ICPLB_DATA12)
- PM_PUSH(ICPLB_DATA13)
- PM_PUSH(ICPLB_DATA14)
- PM_PUSH(ICPLB_DATA15)
- PM_PUSH(EVT0)
- PM_PUSH(EVT1)
- PM_PUSH(EVT2)
- PM_PUSH(EVT3)
- PM_PUSH(EVT4)
- PM_PUSH(EVT5)
- PM_PUSH(EVT6)
- PM_PUSH(EVT7)
- PM_PUSH(EVT8)
- PM_PUSH(EVT9)
- PM_PUSH(EVT10)
- PM_PUSH(EVT11)
- PM_PUSH(EVT12)
- PM_PUSH(EVT13)
- PM_PUSH(EVT14)
- PM_PUSH(EVT15)
- PM_PUSH(IMASK)
- PM_PUSH(ILAT)
- PM_PUSH(IPRIO)
- PM_PUSH(TCNTL)
- PM_PUSH(TPERIOD)
- PM_PUSH(TSCALE)
- PM_PUSH(TCOUNT)
- PM_PUSH(TBUFCTL)
-
- /* Save Core Registers */
- [--sp] = SYSCFG;
- [--sp] = ( R7:0, P5:0 );
+ENTRY(_do_hibernate)
+ /*
+ * Save the core regs early so we can blow them away when
+ * saving/restoring MMR states
+ */
+ [--sp] = (R7:0, P5:0);
[--sp] = fp;
[--sp] = usp;
@@ -506,47 +360,497 @@ ENTRY(_do_hibernate)
[--sp] = LB0;
[--sp] = LB1;
+ /* We can't push RETI directly as that'll change IPEND[4] */
+ r7 = RETI;
+ [--sp] = RETS;
[--sp] = ASTAT;
[--sp] = CYCLES;
[--sp] = CYCLES2;
-
- [--sp] = RETS;
- r0 = RETI;
- [--sp] = r0;
+ [--sp] = SYSCFG;
[--sp] = RETX;
- [--sp] = RETN;
- [--sp] = RETE;
[--sp] = SEQSTAT;
+ [--sp] = r7;
+
+ /* Save first func arg in M3 */
+ M3 = R0;
+
+ /* Save system MMRs */
+ FP.H = hi(SYSMMR_BASE);
+ FP.L = lo(SYSMMR_BASE);
+
+#ifdef SIC_IMASK0
+ PM_SYS_PUSH(0, SIC_IMASK0)
+ PM_SYS_PUSH(1, SIC_IMASK1)
+# ifdef SIC_IMASK2
+ PM_SYS_PUSH(2, SIC_IMASK2)
+# endif
+#else
+ PM_SYS_PUSH(0, SIC_IMASK)
+#endif
+#ifdef SIC_IAR0
+ PM_SYS_PUSH(3, SIC_IAR0)
+ PM_SYS_PUSH(4, SIC_IAR1)
+ PM_SYS_PUSH(5, SIC_IAR2)
+#endif
+#ifdef SIC_IAR3
+ PM_SYS_PUSH(6, SIC_IAR3)
+#endif
+#ifdef SIC_IAR4
+ PM_SYS_PUSH(7, SIC_IAR4)
+ PM_SYS_PUSH(8, SIC_IAR5)
+ PM_SYS_PUSH(9, SIC_IAR6)
+#endif
+#ifdef SIC_IAR7
+ PM_SYS_PUSH(10, SIC_IAR7)
+#endif
+#ifdef SIC_IAR8
+ PM_SYS_PUSH(11, SIC_IAR8)
+ PM_SYS_PUSH(12, SIC_IAR9)
+ PM_SYS_PUSH(13, SIC_IAR10)
+#endif
+ PM_PUSH_SYNC(13)
+#ifdef SIC_IAR11
+ PM_SYS_PUSH(0, SIC_IAR11)
+#endif
+
+#ifdef SIC_IWR
+ PM_SYS_PUSH(1, SIC_IWR)
+#endif
+#ifdef SIC_IWR0
+ PM_SYS_PUSH(1, SIC_IWR0)
+#endif
+#ifdef SIC_IWR1
+ PM_SYS_PUSH(2, SIC_IWR1)
+#endif
+#ifdef SIC_IWR2
+ PM_SYS_PUSH(3, SIC_IWR2)
+#endif
+
+#ifdef PINT0_ASSIGN
+ PM_SYS_PUSH(4, PINT0_MASK_SET)
+ PM_SYS_PUSH(5, PINT1_MASK_SET)
+ PM_SYS_PUSH(6, PINT2_MASK_SET)
+ PM_SYS_PUSH(7, PINT3_MASK_SET)
+ PM_SYS_PUSH(8, PINT0_ASSIGN)
+ PM_SYS_PUSH(9, PINT1_ASSIGN)
+ PM_SYS_PUSH(10, PINT2_ASSIGN)
+ PM_SYS_PUSH(11, PINT3_ASSIGN)
+ PM_SYS_PUSH(12, PINT0_INVERT_SET)
+ PM_SYS_PUSH(13, PINT1_INVERT_SET)
+ PM_PUSH_SYNC(13)
+ PM_SYS_PUSH(0, PINT2_INVERT_SET)
+ PM_SYS_PUSH(1, PINT3_INVERT_SET)
+ PM_SYS_PUSH(2, PINT0_EDGE_SET)
+ PM_SYS_PUSH(3, PINT1_EDGE_SET)
+ PM_SYS_PUSH(4, PINT2_EDGE_SET)
+ PM_SYS_PUSH(5, PINT3_EDGE_SET)
+#endif
+
+ PM_SYS_PUSH16(6, SYSCR)
+
+ PM_SYS_PUSH16(7, EBIU_AMGCTL)
+ PM_SYS_PUSH(8, EBIU_AMBCTL0)
+ PM_SYS_PUSH(9, EBIU_AMBCTL1)
+#ifdef EBIU_FCTL
+ PM_SYS_PUSH(10, EBIU_MBSCTL)
+ PM_SYS_PUSH(11, EBIU_MODE)
+ PM_SYS_PUSH(12, EBIU_FCTL)
+ PM_PUSH_SYNC(12)
+#else
+ PM_PUSH_SYNC(9)
+#endif
+
+ /* Save Core MMRs */
+ I0.H = hi(COREMMR_BASE);
+ I0.L = lo(COREMMR_BASE);
+ I1 = I0;
+ I2 = I0;
+ I3 = I0;
+ B0 = I0;
+ B1 = I0;
+ B2 = I0;
+ B3 = I0;
+ I1.L = lo(DCPLB_ADDR0);
+ I2.L = lo(DCPLB_DATA0);
+ I3.L = lo(ICPLB_ADDR0);
+ B0.L = lo(ICPLB_DATA0);
+ B1.L = lo(EVT2);
+ B2.L = lo(IMASK);
+ B3.L = lo(TCNTL);
+
+ /* DCPLB Addr */
+ FP = I1;
+ PM_PUSH(0, DCPLB_ADDR0)
+ PM_PUSH(1, DCPLB_ADDR1)
+ PM_PUSH(2, DCPLB_ADDR2)
+ PM_PUSH(3, DCPLB_ADDR3)
+ PM_PUSH(4, DCPLB_ADDR4)
+ PM_PUSH(5, DCPLB_ADDR5)
+ PM_PUSH(6, DCPLB_ADDR6)
+ PM_PUSH(7, DCPLB_ADDR7)
+ PM_PUSH(8, DCPLB_ADDR8)
+ PM_PUSH(9, DCPLB_ADDR9)
+ PM_PUSH(10, DCPLB_ADDR10)
+ PM_PUSH(11, DCPLB_ADDR11)
+ PM_PUSH(12, DCPLB_ADDR12)
+ PM_PUSH(13, DCPLB_ADDR13)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, DCPLB_ADDR14)
+ PM_PUSH(1, DCPLB_ADDR15)
+
+ /* DCPLB Data */
+ FP = I2;
+ PM_PUSH(2, DCPLB_DATA0)
+ PM_PUSH(3, DCPLB_DATA1)
+ PM_PUSH(4, DCPLB_DATA2)
+ PM_PUSH(5, DCPLB_DATA3)
+ PM_PUSH(6, DCPLB_DATA4)
+ PM_PUSH(7, DCPLB_DATA5)
+ PM_PUSH(8, DCPLB_DATA6)
+ PM_PUSH(9, DCPLB_DATA7)
+ PM_PUSH(10, DCPLB_DATA8)
+ PM_PUSH(11, DCPLB_DATA9)
+ PM_PUSH(12, DCPLB_DATA10)
+ PM_PUSH(13, DCPLB_DATA11)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, DCPLB_DATA12)
+ PM_PUSH(1, DCPLB_DATA13)
+ PM_PUSH(2, DCPLB_DATA14)
+ PM_PUSH(3, DCPLB_DATA15)
+
+ /* ICPLB Addr */
+ FP = I3;
+ PM_PUSH(4, ICPLB_ADDR0)
+ PM_PUSH(5, ICPLB_ADDR1)
+ PM_PUSH(6, ICPLB_ADDR2)
+ PM_PUSH(7, ICPLB_ADDR3)
+ PM_PUSH(8, ICPLB_ADDR4)
+ PM_PUSH(9, ICPLB_ADDR5)
+ PM_PUSH(10, ICPLB_ADDR6)
+ PM_PUSH(11, ICPLB_ADDR7)
+ PM_PUSH(12, ICPLB_ADDR8)
+ PM_PUSH(13, ICPLB_ADDR9)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, ICPLB_ADDR10)
+ PM_PUSH(1, ICPLB_ADDR11)
+ PM_PUSH(2, ICPLB_ADDR12)
+ PM_PUSH(3, ICPLB_ADDR13)
+ PM_PUSH(4, ICPLB_ADDR14)
+ PM_PUSH(5, ICPLB_ADDR15)
+
+ /* ICPLB Data */
+ FP = B0;
+ PM_PUSH(6, ICPLB_DATA0)
+ PM_PUSH(7, ICPLB_DATA1)
+ PM_PUSH(8, ICPLB_DATA2)
+ PM_PUSH(9, ICPLB_DATA3)
+ PM_PUSH(10, ICPLB_DATA4)
+ PM_PUSH(11, ICPLB_DATA5)
+ PM_PUSH(12, ICPLB_DATA6)
+ PM_PUSH(13, ICPLB_DATA7)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, ICPLB_DATA8)
+ PM_PUSH(1, ICPLB_DATA9)
+ PM_PUSH(2, ICPLB_DATA10)
+ PM_PUSH(3, ICPLB_DATA11)
+ PM_PUSH(4, ICPLB_DATA12)
+ PM_PUSH(5, ICPLB_DATA13)
+ PM_PUSH(6, ICPLB_DATA14)
+ PM_PUSH(7, ICPLB_DATA15)
+
+ /* Event Vectors */
+ FP = B1;
+ PM_PUSH(8, EVT2)
+ PM_PUSH(9, EVT3)
+ FP += 4; /* EVT4 */
+ PM_PUSH(10, EVT5)
+ PM_PUSH(11, EVT6)
+ PM_PUSH(12, EVT7)
+ PM_PUSH(13, EVT8)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, EVT9)
+ PM_PUSH(1, EVT10)
+ PM_PUSH(2, EVT11)
+ PM_PUSH(3, EVT12)
+ PM_PUSH(4, EVT13)
+ PM_PUSH(5, EVT14)
+ PM_PUSH(6, EVT15)
+
+ /* CEC */
+ FP = B2;
+ PM_PUSH(7, IMASK)
+ FP += 4; /* IPEND */
+ PM_PUSH(8, ILAT)
+ PM_PUSH(9, IPRIO)
+
+ /* Core Timer */
+ FP = B3;
+ PM_PUSH(10, TCNTL)
+ PM_PUSH(11, TPERIOD)
+ PM_PUSH(12, TSCALE)
+ PM_PUSH(13, TCOUNT)
+ PM_PUSH_SYNC(13)
+
+ /* Misc non-contiguous registers */
+ FP = I0;
+ PM_CORE_PUSH(0, DMEM_CONTROL);
+ PM_CORE_PUSH(1, IMEM_CONTROL);
+ PM_CORE_PUSH(2, TBUFCTL);
+ PM_PUSH_SYNC(2)
+
+ /* Setup args to hibernate mode early for pipeline optimization */
+ R0 = M3;
+ P1.H = _hibernate_mode;
+ P1.L = _hibernate_mode;
/* Save Magic, return address and Stack Pointer */
- P0.H = 0;
- P0.L = 0;
- R0.H = 0xDEAD; /* Hibernate Magic */
- R0.L = 0xBEEF;
- [P0++] = R0; /* Store Hibernate Magic */
- R0.H = .Lpm_resume_here;
- R0.L = .Lpm_resume_here;
- [P0++] = R0; /* Save Return Address */
+ P0 = 0;
+ R1.H = 0xDEAD; /* Hibernate Magic */
+ R1.L = 0xBEEF;
+ R2.H = .Lpm_resume_here;
+ R2.L = .Lpm_resume_here;
+ [P0++] = R1; /* Store Hibernate Magic */
+ [P0++] = R2; /* Save Return Address */
[P0++] = SP; /* Save Stack Pointer */
- P0.H = _hibernate_mode;
- P0.L = _hibernate_mode;
- R0 = R2;
- call (P0); /* Goodbye */
+
+ /* Must use an indirect call as we need to jump to L1 */
+ call (P1); /* Goodbye */
.Lpm_resume_here:
+ /* Restore Core MMRs */
+ I0.H = hi(COREMMR_BASE);
+ I0.L = lo(COREMMR_BASE);
+ I1 = I0;
+ I2 = I0;
+ I3 = I0;
+ B0 = I0;
+ B1 = I0;
+ B2 = I0;
+ B3 = I0;
+ I1.L = lo(DCPLB_ADDR15);
+ I2.L = lo(DCPLB_DATA15);
+ I3.L = lo(ICPLB_ADDR15);
+ B0.L = lo(ICPLB_DATA15);
+ B1.L = lo(EVT15);
+ B2.L = lo(IPRIO);
+ B3.L = lo(TCOUNT);
+
+ /* Misc non-contiguous registers */
+ FP = I0;
+ PM_POP_SYNC(2)
+ PM_CORE_POP(2, TBUFCTL)
+ PM_CORE_POP(1, IMEM_CONTROL)
+ PM_CORE_POP(0, DMEM_CONTROL)
+
+ /* Core Timer */
+ PM_POP_SYNC(13)
+ FP = B3;
+ PM_POP(13, TCOUNT)
+ PM_POP(12, TSCALE)
+ PM_POP(11, TPERIOD)
+ PM_POP(10, TCNTL)
+
+ /* CEC */
+ FP = B2;
+ PM_POP(9, IPRIO)
+ PM_POP(8, ILAT)
+ FP += -4; /* IPEND */
+ PM_POP(7, IMASK)
+
+ /* Event Vectors */
+ FP = B1;
+ PM_POP(6, EVT15)
+ PM_POP(5, EVT14)
+ PM_POP(4, EVT13)
+ PM_POP(3, EVT12)
+ PM_POP(2, EVT11)
+ PM_POP(1, EVT10)
+ PM_POP(0, EVT9)
+ PM_POP_SYNC(13)
+ PM_POP(13, EVT8)
+ PM_POP(12, EVT7)
+ PM_POP(11, EVT6)
+ PM_POP(10, EVT5)
+ FP += -4; /* EVT4 */
+ PM_POP(9, EVT3)
+ PM_POP(8, EVT2)
+
+ /* ICPLB Data */
+ FP = B0;
+ PM_POP(7, ICPLB_DATA15)
+ PM_POP(6, ICPLB_DATA14)
+ PM_POP(5, ICPLB_DATA13)
+ PM_POP(4, ICPLB_DATA12)
+ PM_POP(3, ICPLB_DATA11)
+ PM_POP(2, ICPLB_DATA10)
+ PM_POP(1, ICPLB_DATA9)
+ PM_POP(0, ICPLB_DATA8)
+ PM_POP_SYNC(13)
+ PM_POP(13, ICPLB_DATA7)
+ PM_POP(12, ICPLB_DATA6)
+ PM_POP(11, ICPLB_DATA5)
+ PM_POP(10, ICPLB_DATA4)
+ PM_POP(9, ICPLB_DATA3)
+ PM_POP(8, ICPLB_DATA2)
+ PM_POP(7, ICPLB_DATA1)
+ PM_POP(6, ICPLB_DATA0)
+
+ /* ICPLB Addr */
+ FP = I3;
+ PM_POP(5, ICPLB_ADDR15)
+ PM_POP(4, ICPLB_ADDR14)
+ PM_POP(3, ICPLB_ADDR13)
+ PM_POP(2, ICPLB_ADDR12)
+ PM_POP(1, ICPLB_ADDR11)
+ PM_POP(0, ICPLB_ADDR10)
+ PM_POP_SYNC(13)
+ PM_POP(13, ICPLB_ADDR9)
+ PM_POP(12, ICPLB_ADDR8)
+ PM_POP(11, ICPLB_ADDR7)
+ PM_POP(10, ICPLB_ADDR6)
+ PM_POP(9, ICPLB_ADDR5)
+ PM_POP(8, ICPLB_ADDR4)
+ PM_POP(7, ICPLB_ADDR3)
+ PM_POP(6, ICPLB_ADDR2)
+ PM_POP(5, ICPLB_ADDR1)
+ PM_POP(4, ICPLB_ADDR0)
+
+ /* DCPLB Data */
+ FP = I2;
+ PM_POP(3, DCPLB_DATA15)
+ PM_POP(2, DCPLB_DATA14)
+ PM_POP(1, DCPLB_DATA13)
+ PM_POP(0, DCPLB_DATA12)
+ PM_POP_SYNC(13)
+ PM_POP(13, DCPLB_DATA11)
+ PM_POP(12, DCPLB_DATA10)
+ PM_POP(11, DCPLB_DATA9)
+ PM_POP(10, DCPLB_DATA8)
+ PM_POP(9, DCPLB_DATA7)
+ PM_POP(8, DCPLB_DATA6)
+ PM_POP(7, DCPLB_DATA5)
+ PM_POP(6, DCPLB_DATA4)
+ PM_POP(5, DCPLB_DATA3)
+ PM_POP(4, DCPLB_DATA2)
+ PM_POP(3, DCPLB_DATA1)
+ PM_POP(2, DCPLB_DATA0)
+
+ /* DCPLB Addr */
+ FP = I1;
+ PM_POP(1, DCPLB_ADDR15)
+ PM_POP(0, DCPLB_ADDR14)
+ PM_POP_SYNC(13)
+ PM_POP(13, DCPLB_ADDR13)
+ PM_POP(12, DCPLB_ADDR12)
+ PM_POP(11, DCPLB_ADDR11)
+ PM_POP(10, DCPLB_ADDR10)
+ PM_POP(9, DCPLB_ADDR9)
+ PM_POP(8, DCPLB_ADDR8)
+ PM_POP(7, DCPLB_ADDR7)
+ PM_POP(6, DCPLB_ADDR6)
+ PM_POP(5, DCPLB_ADDR5)
+ PM_POP(4, DCPLB_ADDR4)
+ PM_POP(3, DCPLB_ADDR3)
+ PM_POP(2, DCPLB_ADDR2)
+ PM_POP(1, DCPLB_ADDR1)
+ PM_POP(0, DCPLB_ADDR0)
+
+ /* Restore System MMRs */
+ FP.H = hi(SYSMMR_BASE);
+ FP.L = lo(SYSMMR_BASE);
+
+#ifdef EBIU_FCTL
+ PM_POP_SYNC(12)
+ PM_SYS_POP(12, EBIU_FCTL)
+ PM_SYS_POP(11, EBIU_MODE)
+ PM_SYS_POP(10, EBIU_MBSCTL)
+#else
+ PM_POP_SYNC(9)
+#endif
+ PM_SYS_POP(9, EBIU_AMBCTL1)
+ PM_SYS_POP(8, EBIU_AMBCTL0)
+ PM_SYS_POP16(7, EBIU_AMGCTL)
+
+ PM_SYS_POP16(6, SYSCR)
+
+#ifdef PINT0_ASSIGN
+ PM_SYS_POP(5, PINT3_EDGE_SET)
+ PM_SYS_POP(4, PINT2_EDGE_SET)
+ PM_SYS_POP(3, PINT1_EDGE_SET)
+ PM_SYS_POP(2, PINT0_EDGE_SET)
+ PM_SYS_POP(1, PINT3_INVERT_SET)
+ PM_SYS_POP(0, PINT2_INVERT_SET)
+ PM_POP_SYNC(13)
+ PM_SYS_POP(13, PINT1_INVERT_SET)
+ PM_SYS_POP(12, PINT0_INVERT_SET)
+ PM_SYS_POP(11, PINT3_ASSIGN)
+ PM_SYS_POP(10, PINT2_ASSIGN)
+ PM_SYS_POP(9, PINT1_ASSIGN)
+ PM_SYS_POP(8, PINT0_ASSIGN)
+ PM_SYS_POP(7, PINT3_MASK_SET)
+ PM_SYS_POP(6, PINT2_MASK_SET)
+ PM_SYS_POP(5, PINT1_MASK_SET)
+ PM_SYS_POP(4, PINT0_MASK_SET)
+#endif
+
+#ifdef SIC_IWR2
+ PM_SYS_POP(3, SIC_IWR2)
+#endif
+#ifdef SIC_IWR1
+ PM_SYS_POP(2, SIC_IWR1)
+#endif
+#ifdef SIC_IWR0
+ PM_SYS_POP(1, SIC_IWR0)
+#endif
+#ifdef SIC_IWR
+ PM_SYS_POP(1, SIC_IWR)
+#endif
+
+#ifdef SIC_IAR11
+ PM_SYS_POP(0, SIC_IAR11)
+#endif
+ PM_POP_SYNC(13)
+#ifdef SIC_IAR8
+ PM_SYS_POP(13, SIC_IAR10)
+ PM_SYS_POP(12, SIC_IAR9)
+ PM_SYS_POP(11, SIC_IAR8)
+#endif
+#ifdef SIC_IAR7
+ PM_SYS_POP(10, SIC_IAR7)
+#endif
+#ifdef SIC_IAR6
+ PM_SYS_POP(9, SIC_IAR6)
+ PM_SYS_POP(8, SIC_IAR5)
+ PM_SYS_POP(7, SIC_IAR4)
+#endif
+#ifdef SIC_IAR3
+ PM_SYS_POP(6, SIC_IAR3)
+#endif
+#ifdef SIC_IAR0
+ PM_SYS_POP(5, SIC_IAR2)
+ PM_SYS_POP(4, SIC_IAR1)
+ PM_SYS_POP(3, SIC_IAR0)
+#endif
+#ifdef SIC_IMASK0
+# ifdef SIC_IMASK2
+ PM_SYS_POP(2, SIC_IMASK2)
+# endif
+ PM_SYS_POP(1, SIC_IMASK1)
+ PM_SYS_POP(0, SIC_IMASK0)
+#else
+ PM_SYS_POP(0, SIC_IMASK)
+#endif
+
/* Restore Core Registers */
+ RETI = [sp++];
SEQSTAT = [sp++];
- RETE = [sp++];
- RETN = [sp++];
RETX = [sp++];
- r0 = [sp++];
- RETI = r0;
- RETS = [sp++];
-
+ SYSCFG = [sp++];
CYCLES2 = [sp++];
CYCLES = [sp++];
ASTAT = [sp++];
+ RETS = [sp++];
LB1 = [sp++];
LB0 = [sp++];
@@ -581,204 +885,10 @@ ENTRY(_do_hibernate)
usp = [sp++];
fp = [sp++];
-
- ( R7 : 0, P5 : 0) = [ SP ++ ];
- SYSCFG = [sp++];
-
- /* Restore Core MMRs */
-
- PM_POP(TBUFCTL)
- PM_POP(TCOUNT)
- PM_POP(TSCALE)
- PM_POP(TPERIOD)
- PM_POP(TCNTL)
- PM_POP(IPRIO)
- PM_POP(ILAT)
- PM_POP(IMASK)
- PM_POP(EVT15)
- PM_POP(EVT14)
- PM_POP(EVT13)
- PM_POP(EVT12)
- PM_POP(EVT11)
- PM_POP(EVT10)
- PM_POP(EVT9)
- PM_POP(EVT8)
- PM_POP(EVT7)
- PM_POP(EVT6)
- PM_POP(EVT5)
- PM_POP(EVT4)
- PM_POP(EVT3)
- PM_POP(EVT2)
- PM_POP(EVT1)
- PM_POP(EVT0)
- PM_POP(ICPLB_DATA15)
- PM_POP(ICPLB_DATA14)
- PM_POP(ICPLB_DATA13)
- PM_POP(ICPLB_DATA12)
- PM_POP(ICPLB_DATA11)
- PM_POP(ICPLB_DATA10)
- PM_POP(ICPLB_DATA9)
- PM_POP(ICPLB_DATA8)
- PM_POP(ICPLB_DATA7)
- PM_POP(ICPLB_DATA6)
- PM_POP(ICPLB_DATA5)
- PM_POP(ICPLB_DATA4)
- PM_POP(ICPLB_DATA3)
- PM_POP(ICPLB_DATA2)
- PM_POP(ICPLB_DATA1)
- PM_POP(ICPLB_DATA0)
- PM_POP(ICPLB_ADDR15)
- PM_POP(ICPLB_ADDR14)
- PM_POP(ICPLB_ADDR13)
- PM_POP(ICPLB_ADDR12)
- PM_POP(ICPLB_ADDR11)
- PM_POP(ICPLB_ADDR10)
- PM_POP(ICPLB_ADDR9)
- PM_POP(ICPLB_ADDR8)
- PM_POP(ICPLB_ADDR7)
- PM_POP(ICPLB_ADDR6)
- PM_POP(ICPLB_ADDR5)
- PM_POP(ICPLB_ADDR4)
- PM_POP(ICPLB_ADDR3)
- PM_POP(ICPLB_ADDR2)
- PM_POP(ICPLB_ADDR1)
- PM_POP(ICPLB_ADDR0)
- PM_POP(IMEM_CONTROL)
- PM_POP(DCPLB_DATA15)
- PM_POP(DCPLB_DATA14)
- PM_POP(DCPLB_DATA13)
- PM_POP(DCPLB_DATA12)
- PM_POP(DCPLB_DATA11)
- PM_POP(DCPLB_DATA10)
- PM_POP(DCPLB_DATA9)
- PM_POP(DCPLB_DATA8)
- PM_POP(DCPLB_DATA7)
- PM_POP(DCPLB_DATA6)
- PM_POP(DCPLB_DATA5)
- PM_POP(DCPLB_DATA4)
- PM_POP(DCPLB_DATA3)
- PM_POP(DCPLB_DATA2)
- PM_POP(DCPLB_DATA1)
- PM_POP(DCPLB_DATA0)
- PM_POP(DCPLB_ADDR15)
- PM_POP(DCPLB_ADDR14)
- PM_POP(DCPLB_ADDR13)
- PM_POP(DCPLB_ADDR12)
- PM_POP(DCPLB_ADDR11)
- PM_POP(DCPLB_ADDR10)
- PM_POP(DCPLB_ADDR9)
- PM_POP(DCPLB_ADDR8)
- PM_POP(DCPLB_ADDR7)
- PM_POP(DCPLB_ADDR6)
- PM_POP(DCPLB_ADDR5)
- PM_POP(DCPLB_ADDR4)
- PM_POP(DCPLB_ADDR3)
- PM_POP(DCPLB_ADDR2)
- PM_POP(DCPLB_ADDR1)
- PM_POP(DCPLB_ADDR0)
- PM_POP(DMEM_CONTROL)
-
- /* Restore System MMRs */
-
- P0.H = hi(PLL_CTL);
- P0.L = lo(PLL_CTL);
- PM_SYS_POP16(SYSCR)
-
-#ifdef PORTCIO_FER
- PM_SYS_POP16(PORTEIO_FER)
- PM_SYS_POP16(PORTEIO)
- PM_SYS_POP16(PORTEIO_INEN)
- PM_SYS_POP16(PORTEIO_DIR)
- PM_SYS_POP16(PORTDIO_FER)
- PM_SYS_POP16(PORTDIO)
- PM_SYS_POP16(PORTDIO_INEN)
- PM_SYS_POP16(PORTDIO_DIR)
- PM_SYS_POP16(PORTCIO_FER)
- PM_SYS_POP16(PORTCIO)
- PM_SYS_POP16(PORTCIO_INEN)
- PM_SYS_POP16(PORTCIO_DIR)
-#endif
-
-#ifdef EBIU_FCTL
- PM_SYS_POP(EBIU_FCTL)
- PM_SYS_POP(EBIU_MODE)
- PM_SYS_POP(EBIU_MBSCTL)
-#endif
- PM_SYS_POP16(EBIU_AMGCTL)
- PM_SYS_POP(EBIU_AMBCTL1)
- PM_SYS_POP(EBIU_AMBCTL0)
-
-#ifdef PINT0_ASSIGN
- PM_SYS_POP(PINT3_EDGE_SET)
- PM_SYS_POP(PINT2_EDGE_SET)
- PM_SYS_POP(PINT1_EDGE_SET)
- PM_SYS_POP(PINT0_EDGE_SET)
- PM_SYS_POP(PINT3_INVERT_SET)
- PM_SYS_POP(PINT2_INVERT_SET)
- PM_SYS_POP(PINT1_INVERT_SET)
- PM_SYS_POP(PINT0_INVERT_SET)
- PM_SYS_POP(PINT3_ASSIGN)
- PM_SYS_POP(PINT2_ASSIGN)
- PM_SYS_POP(PINT1_ASSIGN)
- PM_SYS_POP(PINT0_ASSIGN)
- PM_SYS_POP(PINT3_MASK_SET)
- PM_SYS_POP(PINT2_MASK_SET)
- PM_SYS_POP(PINT1_MASK_SET)
- PM_SYS_POP(PINT0_MASK_SET)
-#endif
-
-#ifdef SIC_IWR2
- PM_SYS_POP(SIC_IWR2)
-#endif
-#ifdef SIC_IWR1
- PM_SYS_POP(SIC_IWR1)
-#endif
-#ifdef SIC_IWR0
- PM_SYS_POP(SIC_IWR0)
-#endif
-#ifdef SIC_IWR
- PM_SYS_POP(SIC_IWR)
-#endif
-
-#ifdef SIC_IAR8
- PM_SYS_POP(SIC_IAR11)
- PM_SYS_POP(SIC_IAR10)
- PM_SYS_POP(SIC_IAR9)
- PM_SYS_POP(SIC_IAR8)
-#endif
-#ifdef SIC_IAR7
- PM_SYS_POP(SIC_IAR7)
-#endif
-#ifdef SIC_IAR6
- PM_SYS_POP(SIC_IAR6)
- PM_SYS_POP(SIC_IAR5)
- PM_SYS_POP(SIC_IAR4)
-#endif
-#ifdef SIC_IAR3
- PM_SYS_POP(SIC_IAR3)
-#endif
-#ifdef SIC_IAR0
- PM_SYS_POP(SIC_IAR2)
- PM_SYS_POP(SIC_IAR1)
- PM_SYS_POP(SIC_IAR0)
-#endif
-#ifdef SIC_IMASK
- PM_SYS_POP(SIC_IMASK)
-#endif
-#ifdef SIC_IMASK2
- PM_SYS_POP(SIC_IMASK2)
-#endif
-#ifdef SIC_IMASK1
- PM_SYS_POP(SIC_IMASK1)
-#endif
-#ifdef SIC_IMASK0
- PM_SYS_POP(SIC_IMASK0)
-#endif
+ (R7:0, P5:0) = [sp++];
[--sp] = RETI; /* Clear Global Interrupt Disable */
SP += 4;
- RETS = [SP++];
- ( R7:0, P5:0 ) = [SP++];
RTS;
ENDPROC(_do_hibernate)
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S
index 76de5724c1e3..8b4d98854403 100644
--- a/arch/blackfin/mach-common/head.S
+++ b/arch/blackfin/mach-common/head.S
@@ -85,37 +85,25 @@ ENTRY(__start)
SSYNC;
/* in case of double faults, save a few things */
- p0.l = _init_retx;
- p0.h = _init_retx;
- R0 = RETX;
- [P0] = R0;
-
+ p1.l = _initial_pda;
+ p1.h = _initial_pda;
+ r4 = RETX;
#ifdef CONFIG_DEBUG_DOUBLEFAULT
/* Only save these if we are storing them,
* This happens here, since L1 gets clobbered
* below
*/
GET_PDA(p0, r0);
- r5 = [p0 + PDA_DF_RETX];
- p1.l = _init_saved_retx;
- p1.h = _init_saved_retx;
- [p1] = r5;
-
- r5 = [p0 + PDA_DF_DCPLB];
- p1.l = _init_saved_dcplb_fault_addr;
- p1.h = _init_saved_dcplb_fault_addr;
- [p1] = r5;
-
- r5 = [p0 + PDA_DF_ICPLB];
- p1.l = _init_saved_icplb_fault_addr;
- p1.h = _init_saved_icplb_fault_addr;
- [p1] = r5;
-
- r5 = [p0 + PDA_DF_SEQSTAT];
- p1.l = _init_saved_seqstat;
- p1.h = _init_saved_seqstat;
- [p1] = r5;
+ r0 = [p0 + PDA_DF_RETX];
+ r1 = [p0 + PDA_DF_DCPLB];
+ r2 = [p0 + PDA_DF_ICPLB];
+ r3 = [p0 + PDA_DF_SEQSTAT];
+ [p1 + PDA_INIT_DF_RETX] = r0;
+ [p1 + PDA_INIT_DF_DCPLB] = r1;
+ [p1 + PDA_INIT_DF_ICPLB] = r2;
+ [p1 + PDA_INIT_DF_SEQSTAT] = r3;
#endif
+ [p1 + PDA_INIT_RETX] = r4;
/* Initialize stack pointer */
sp.l = _init_thread_union + THREAD_SIZE;
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 1177369f9922..332dace6af34 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -444,7 +444,7 @@ static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
extern void bfin_gpio_irq_prepare(unsigned gpio);
-#if !defined(CONFIG_BF54x)
+#if !BFIN_GPIO_PINT
static void bfin_gpio_ack_irq(struct irq_data *d)
{
@@ -633,7 +633,7 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
bfin_demux_gpio_block(irq);
}
-#else /* CONFIG_BF54x */
+#else
#define NR_PINT_SYS_IRQS 4
#define NR_PINT_BITS 32
@@ -647,24 +647,11 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
static unsigned char irq2pint_lut[NR_PINTS];
static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
-struct pin_int_t {
- unsigned int mask_set;
- unsigned int mask_clear;
- unsigned int request;
- unsigned int assign;
- unsigned int edge_set;
- unsigned int edge_clear;
- unsigned int invert_set;
- unsigned int invert_clear;
- unsigned int pinstate;
- unsigned int latch;
-};
-
-static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
- (struct pin_int_t *)PINT0_MASK_SET,
- (struct pin_int_t *)PINT1_MASK_SET,
- (struct pin_int_t *)PINT2_MASK_SET,
- (struct pin_int_t *)PINT3_MASK_SET,
+static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = {
+ (struct bfin_pint_regs *)PINT0_MASK_SET,
+ (struct bfin_pint_regs *)PINT1_MASK_SET,
+ (struct bfin_pint_regs *)PINT2_MASK_SET,
+ (struct bfin_pint_regs *)PINT3_MASK_SET,
};
inline unsigned int get_irq_base(u32 bank, u8 bmap)
@@ -981,7 +968,7 @@ int __init init_arch_irq(void)
local_irq_disable();
-#ifdef CONFIG_BF54x
+#if BFIN_GPIO_PINT
# ifdef CONFIG_PINTx_REASSIGN
pint[0]->assign = CONFIG_PINT0_ASSIGN;
pint[1]->assign = CONFIG_PINT1_ASSIGN;
@@ -999,16 +986,16 @@ int __init init_arch_irq(void)
irq_set_chip(irq, &bfin_internal_irqchip);
switch (irq) {
-#if defined(BF537_FAMILY)
- case IRQ_PH_INTA_MAC_RX:
- case IRQ_PF_INTA_PG_INTA:
-#elif defined(BF533_FAMILY)
- case IRQ_PROG_INTA:
-#elif defined(CONFIG_BF54x)
+#if BFIN_GPIO_PINT
case IRQ_PINT0:
case IRQ_PINT1:
case IRQ_PINT2:
case IRQ_PINT3:
+#elif defined(BF537_FAMILY)
+ case IRQ_PH_INTA_MAC_RX:
+ case IRQ_PF_INTA_PG_INTA:
+#elif defined(BF533_FAMILY)
+ case IRQ_PROG_INTA:
#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
case IRQ_PORTF_INTA:
case IRQ_PORTG_INTA:
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 35e7e1eb0188..107622aacf6b 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -23,7 +23,7 @@
#include <linux/seq_file.h>
#include <linux/irq.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/irq_handler.h>
#include <asm/mmu_context.h>
@@ -45,9 +45,7 @@ struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
unsigned long blackfin_iflush_l1_entry[NR_CPUS];
#endif
-void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
- *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
- *init_saved_dcplb_fault_addr_coreb;
+struct blackfin_initial_pda __cpuinitdata initial_pda_coreb;
#define BFIN_IPI_RESCHEDULE 0
#define BFIN_IPI_CALL_FUNC 1
@@ -369,13 +367,16 @@ void __cpuinit secondary_start_kernel(void)
if (_bfin_swrst & SWRST_DBL_FAULT_B) {
printk(KERN_EMERG "CoreB Recovering from DOUBLE FAULT event\n");
#ifdef CONFIG_DEBUG_DOUBLEFAULT
- printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n",
- (int)init_saved_seqstat_coreb & SEQSTAT_EXCAUSE, init_saved_retx_coreb);
- printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr_coreb);
- printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr_coreb);
+ printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF\n",
+ initial_pda_coreb.seqstat_doublefault & SEQSTAT_EXCAUSE,
+ initial_pda_coreb.retx_doublefault);
+ printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n",
+ initial_pda_coreb.dcplb_doublefault_addr);
+ printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n",
+ initial_pda_coreb.icplb_doublefault_addr);
#endif
printk(KERN_NOTICE " The instruction at %pF caused a double exception\n",
- init_retx_coreb);
+ initial_pda_coreb.retx);
}
/*
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index c03bc3bc30c2..642c6fed43d7 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -16,7 +16,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/list.h>
#include <linux/interrupt.h>
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index a0843a71aaee..0b99df72d2a4 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -7,7 +7,7 @@
#include <asm/mmu_context.h>
#include <hwregs/asm/mmu_defs_asm.h>
#include <hwregs/supp_reg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/err.h>
#include <linux/init.h>
diff --git a/arch/cris/arch-v32/mach-a3/pinmux.c b/arch/cris/arch-v32/mach-a3/pinmux.c
index 18648ef2d874..591f77526746 100644
--- a/arch/cris/arch-v32/mach-a3/pinmux.c
+++ b/arch/cris/arch-v32/mach-a3/pinmux.c
@@ -85,6 +85,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
int ret = -EINVAL;
char saved[sizeof pins];
unsigned long flags;
+ reg_pinmux_rw_hwprot hwprot;
+ reg_clkgen_rw_clk_ctrl clk_ctrl;
spin_lock_irqsave(&pinmux_lock, flags);
@@ -93,9 +95,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
- reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
- reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
- rw_clk_ctrl);
+ hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+ clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
switch (function) {
case pinmux_eth:
@@ -262,6 +263,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
int ret = -EINVAL;
char saved[sizeof pins];
unsigned long flags;
+ reg_pinmux_rw_hwprot hwprot;
spin_lock_irqsave(&pinmux_lock, flags);
@@ -270,7 +272,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
- reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+ hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
switch (function) {
case pinmux_eth:
diff --git a/arch/cris/include/arch-v10/arch/processor.h b/arch/cris/include/arch-v10/arch/processor.h
index cc692c7a0660..93feb2a487d8 100644
--- a/arch/cris/include/arch-v10/arch/processor.h
+++ b/arch/cris/include/arch-v10/arch/processor.h
@@ -53,7 +53,6 @@ struct thread_struct {
*/
#define start_thread(regs, ip, usp) do { \
- set_fs(USER_DS); \
regs->irp = ip; \
regs->dccr |= 1 << U_DCCR_BITNR; \
wrusp(usp); \
diff --git a/arch/cris/include/arch-v10/arch/ptrace.h b/arch/cris/include/arch-v10/arch/ptrace.h
index 2f464eab3a51..1a232739565e 100644
--- a/arch/cris/include/arch-v10/arch/ptrace.h
+++ b/arch/cris/include/arch-v10/arch/ptrace.h
@@ -112,7 +112,6 @@ struct switch_stack {
#define user_mode(regs) (((regs)->dccr & 0x100) != 0)
#define instruction_pointer(regs) ((regs)->irp)
#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
#endif /* __KERNEL__ */
diff --git a/arch/cris/include/arch-v32/arch/processor.h b/arch/cris/include/arch-v32/arch/processor.h
index f80b47790ca6..9603c907fbc4 100644
--- a/arch/cris/include/arch-v32/arch/processor.h
+++ b/arch/cris/include/arch-v32/arch/processor.h
@@ -47,7 +47,6 @@ struct thread_struct {
*/
#define start_thread(regs, ip, usp) \
do { \
- set_fs(USER_DS); \
regs->erp = ip; \
regs->ccs |= 1 << (U_CCS_BITNR + CCS_SHIFT); \
wrusp(usp); \
diff --git a/arch/cris/include/arch-v32/arch/ptrace.h b/arch/cris/include/arch-v32/arch/ptrace.h
index ffca8d0f2e17..19773d3bd4c4 100644
--- a/arch/cris/include/arch-v32/arch/ptrace.h
+++ b/arch/cris/include/arch-v32/arch/ptrace.h
@@ -111,7 +111,6 @@ struct switch_stack {
#define arch_has_single_step() (1)
#define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0)
#define instruction_pointer(regs) ((regs)->erp)
-extern void show_regs(struct pt_regs *);
#define profile_pc(regs) instruction_pointer(regs)
#endif /* __KERNEL__ */
diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h
index 88dc9b9c4ba0..bbf093814db2 100644
--- a/arch/cris/include/asm/atomic.h
+++ b/arch/cris/include/asm/atomic.h
@@ -138,7 +138,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;
@@ -148,9 +148,8 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
if (ret != u)
v->counter += a;
cris_atomic_restore(v, flags);
- return ret != u;
+ return ret;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
@@ -158,5 +157,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
#endif
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index 310e0de67aa6..a78a2d70cd8b 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -20,7 +20,7 @@
#include <arch/bitops.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/compiler.h>
/*
@@ -156,8 +156,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
#include <asm-generic/bitops/le.h>
-#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#include <asm-generic/bitops/sched.h>
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c
index bcd502f74cda..37400f5869e6 100644
--- a/arch/cris/kernel/module.c
+++ b/arch/cris/kernel/module.c
@@ -30,45 +30,19 @@
#endif
#ifdef CONFIG_ETRAX_KMALLOCED_MODULES
-#define MALLOC_MODULE(size) kmalloc(size, GFP_KERNEL)
-#define FREE_MODULE(region) kfree(region)
-#else
-#define MALLOC_MODULE(size) vmalloc_exec(size)
-#define FREE_MODULE(region) vfree(region)
-#endif
-
void *module_alloc(unsigned long size)
{
if (size == 0)
return NULL;
- return MALLOC_MODULE(size);
+ return kmalloc(size, GFP_KERNEL);
}
-
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
- FREE_MODULE(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
- return -ENOEXEC;
+ kfree(module_region);
}
+#endif
int apply_relocate_add(Elf32_Shdr *sechdrs,
const char *strtab,
@@ -108,14 +82,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
return 0;
}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index c99aeab7cef7..aa585e4e979e 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -12,7 +12,7 @@
* This file handles the architecture-dependent parts of process handling..
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h
index fae32c7fdcb6..0d8a7d661740 100644
--- a/arch/frv/include/asm/atomic.h
+++ b/arch/frv/include/asm/atomic.h
@@ -241,7 +241,7 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
#define atomic64_cmpxchg(v, old, new) (__cmpxchg_64(old, new, &(v)->counter))
#define atomic64_xchg(v, new) (__xchg_64(new, &(v)->counter))
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -253,10 +253,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-#include <asm-generic/atomic-long.h>
#endif /* _ASM_ATOMIC_H */
diff --git a/arch/frv/include/asm/bitops.h b/arch/frv/include/asm/bitops.h
index a1d00b0c6ed7..57bf85db893f 100644
--- a/arch/frv/include/asm/bitops.h
+++ b/arch/frv/include/asm/bitops.h
@@ -403,8 +403,7 @@ int __ilog2_u64(u64 n)
#include <asm-generic/bitops/le.h>
-#define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit ((nr) ^ 0x18, (addr))
-#define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr) ^ 0x18, (addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* __KERNEL__ */
diff --git a/arch/frv/include/asm/hardirq.h b/arch/frv/include/asm/hardirq.h
index 5fc8b6f5bc55..c62833d6ebbb 100644
--- a/arch/frv/include/asm/hardirq.h
+++ b/arch/frv/include/asm/hardirq.h
@@ -12,7 +12,7 @@
#ifndef __ASM_HARDIRQ_H
#define __ASM_HARDIRQ_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
extern atomic_t irq_err_count;
static inline void ack_bad_irq(int irq)
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index 4b789ab182b0..81c2e271d620 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -97,7 +97,6 @@ extern struct task_struct *__kernel_current_task;
*/
#define start_thread(_regs, _pc, _usp) \
do { \
- set_fs(USER_DS); /* reads from user space */ \
__frame = __kernel_frame0_ptr; \
__frame->pc = (_pc); \
__frame->psr &= ~PSR_S; \
diff --git a/arch/frv/include/asm/ptrace.h b/arch/frv/include/asm/ptrace.h
index 6bfad4cf1907..ef6635ca4ecb 100644
--- a/arch/frv/include/asm/ptrace.h
+++ b/arch/frv/include/asm/ptrace.h
@@ -78,7 +78,6 @@ register struct pt_regs *__frame asm("gr28");
#define user_stack_pointer(regs) ((regs)->sp)
extern unsigned long user_stack(const struct pt_regs *);
-extern void show_regs(struct pt_regs *);
#define profile_pc(regs) ((regs)->pc)
#define task_pt_regs(task) ((task)->thread.frame0)
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index a5f624a9f559..3facbc28cbbc 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -25,7 +25,7 @@
#include <linux/module.h>
#include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/system.h>
diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c
index 711763c8a6f3..9d9835f1fe2b 100644
--- a/arch/frv/kernel/module.c
+++ b/arch/frv/kernel/module.c
@@ -22,57 +22,6 @@
#define DEBUGP(fmt...)
#endif
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
-
- return vmalloc_exec(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
- return -ENOEXEC;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
- return -ENOEXEC;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
+/* TODO: At least one of apply_relocate or apply_relocate_add must be
+ * implemented in order to get working module support.
+ */
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 9d3597526467..3901df1213c0 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -143,10 +143,7 @@ void machine_power_off(void)
void flush_thread(void)
{
-#if 0 //ndef NO_FPU
- unsigned long zero = 0;
-#endif
- set_fs(USER_DS);
+ /* nothing */
}
inline unsigned long user_stack(const struct pt_regs *regs)
diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu
index d236ab4232ca..15c22286ae79 100644
--- a/arch/h8300/Kconfig.cpu
+++ b/arch/h8300/Kconfig.cpu
@@ -162,9 +162,7 @@ config H8300_TPU_CH
int "TPU channel"
depends on H8300_TPU
-config PREEMPT
- bool "Preemptible Kernel"
- default n
+source "kernel/Kconfig.preempt"
source "mm/Kconfig"
diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h
index 984221abb66d..f5a38c1f5489 100644
--- a/arch/h8300/include/asm/atomic.h
+++ b/arch/h8300/include/asm/atomic.h
@@ -104,7 +104,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;
@@ -114,9 +114,8 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
if (ret != u)
v->counter += a;
local_irq_restore(flags);
- return ret != u;
+ return ret;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
{
@@ -146,5 +145,4 @@ static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
#endif /* __ARCH_H8300_ATOMIC __ */
diff --git a/arch/h8300/include/asm/posix_types.h b/arch/h8300/include/asm/posix_types.h
index 5c553927fc53..6f833a16f694 100644
--- a/arch/h8300/include/asm/posix_types.h
+++ b/arch/h8300/include/asm/posix_types.h
@@ -50,7 +50,7 @@ typedef struct {
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
#undef __FD_ISSET
-#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define __FD_ISSET(d, set) (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
#undef __FD_ZERO
#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 69e8a34eb6d5..e834b6018897 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -81,7 +81,6 @@ struct thread_struct {
#if defined(__H8300H__)
#define start_thread(_regs, _pc, _usp) \
do { \
- set_fs(USER_DS); /* reads from user space */ \
(_regs)->pc = (_pc); \
(_regs)->ccr = 0x00; /* clear all flags */ \
(_regs)->er5 = current->mm->start_data; /* GOT base */ \
@@ -91,7 +90,6 @@ do { \
#if defined(__H8300S__)
#define start_thread(_regs, _pc, _usp) \
do { \
- set_fs(USER_DS); /* reads from user space */ \
(_regs)->pc = (_pc); \
(_regs)->ccr = 0x00; /* clear kernel flag */ \
(_regs)->exr = 0x78; /* enable all interrupts */ \
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h
index d866c0efba87..d09c440bdba7 100644
--- a/arch/h8300/include/asm/ptrace.h
+++ b/arch/h8300/include/asm/ptrace.h
@@ -60,7 +60,6 @@ struct pt_regs {
#define user_mode(regs) (!((regs)->ccr & PS_S))
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
#endif /* _H8300_PTRACE_H */
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
index db4953dc4e1b..1d526e05db19 100644
--- a/arch/h8300/kernel/module.c
+++ b/arch/h8300/kernel/module.c
@@ -11,40 +11,6 @@
#define DEBUGP(fmt...)
#endif
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
-
int apply_relocate_add(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
@@ -107,14 +73,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
me->name, rela[i].r_offset);
return -ENOEXEC;
}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
index 7fda657110eb..68d651081bd3 100644
--- a/arch/h8300/kernel/setup.c
+++ b/arch/h8300/kernel/setup.c
@@ -46,7 +46,7 @@
#include <asm/regs267x.h>
#endif
-#define STUBSIZE 0xc000;
+#define STUBSIZE 0xc000
unsigned long rom_length;
unsigned long memory_start;
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 38280ef4a2af..137b277f7e56 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -101,6 +101,9 @@ config GENERIC_IOMAP
bool
default y
+config ARCH_CLOCKSOURCE_DATA
+ def_bool y
+
config SCHED_OMIT_FRAME_POINTER
bool
default y
@@ -627,27 +630,6 @@ source "drivers/pci/hotplug/Kconfig"
source "drivers/pcmcia/Kconfig"
-config DMAR
- bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
- depends on IA64_GENERIC && ACPI && EXPERIMENTAL
- help
- DMA remapping (DMAR) devices support enables independent address
- translations for Direct Memory Access (DMA) from devices.
- These DMA remapping devices are reported via ACPI tables
- and include PCI device scope covered by these DMA
- remapping devices.
-
-config DMAR_DEFAULT_ON
- def_bool y
- prompt "Enable DMA Remapping Devices by default"
- depends on DMAR
- 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. It is
- recommended you say N here while the DMAR code remains
- experimental.
-
endmenu
endif
@@ -681,6 +663,3 @@ source "lib/Kconfig"
config IOMMU_HELPER
def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
-
-config IOMMU_API
- def_bool (DMAR)
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
index 446881439675..3fad89ee01cb 100644
--- a/arch/ia64/include/asm/atomic.h
+++ b/arch/ia64/include/asm/atomic.h
@@ -90,7 +90,7 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v)
(cmpxchg(&((v)->counter), old, new))
#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -102,10 +102,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
static __inline__ long atomic64_add_unless(atomic64_t *v, long a, long u)
{
@@ -216,5 +215,4 @@ atomic64_add_negative (__s64 i, atomic64_t *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
#endif /* _ASM_IA64_ATOMIC_H */
diff --git a/arch/ia64/include/asm/bitops.h b/arch/ia64/include/asm/bitops.h
index b76f7e009218..8e20bff39f79 100644
--- a/arch/ia64/include/asm/bitops.h
+++ b/arch/ia64/include/asm/bitops.h
@@ -458,8 +458,7 @@ static __inline__ unsigned long __arch_hweight64(unsigned long x)
#include <asm-generic/bitops/le.h>
-#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#include <asm-generic/bitops/sched.h>
diff --git a/arch/ia64/include/asm/clocksource.h b/arch/ia64/include/asm/clocksource.h
new file mode 100644
index 000000000000..5c8596e4cb02
--- /dev/null
+++ b/arch/ia64/include/asm/clocksource.h
@@ -0,0 +1,10 @@
+/* IA64-specific clocksource additions */
+
+#ifndef _ASM_IA64_CLOCKSOURCE_H
+#define _ASM_IA64_CLOCKSOURCE_H
+
+struct arch_clocksource_data {
+ void *fsys_mmio; /* used by fsyscall asm code */
+};
+
+#endif /* _ASM_IA64_CLOCKSOURCE_H */
diff --git a/arch/ia64/include/asm/paravirt.h b/arch/ia64/include/asm/paravirt.h
index 2eb0a981a09a..32551d304cd7 100644
--- a/arch/ia64/include/asm/paravirt.h
+++ b/arch/ia64/include/asm/paravirt.h
@@ -281,6 +281,10 @@ paravirt_init_missing_ticks_accounting(int cpu)
pv_time_ops.init_missing_ticks_accounting(cpu);
}
+struct jump_label_key;
+extern struct jump_label_key paravirt_steal_enabled;
+extern struct jump_label_key paravirt_steal_rq_enabled;
+
static inline int
paravirt_do_steal_accounting(unsigned long *new_itm)
{
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index 03afe7970748..d9f397fae03e 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -75,7 +75,7 @@
#include <asm/percpu.h>
#include <asm/rse.h>
#include <asm/unwind.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#ifdef CONFIG_NUMA
#include <asm/nodedata.h>
#endif
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h
index 7ae9c3f15a1c..f5cb27614e35 100644
--- a/arch/ia64/include/asm/ptrace.h
+++ b/arch/ia64/include/asm/ptrace.h
@@ -286,7 +286,6 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
struct task_struct; /* forward decl */
struct unw_frame_info; /* forward decl */
- extern void show_regs (struct pt_regs *);
extern void ia64_do_show_stack (struct unw_frame_info *, void *);
extern unsigned long ia64_get_user_rbs_end (struct task_struct *, struct pt_regs *,
unsigned long *);
diff --git a/arch/ia64/include/asm/sn/tioce.h b/arch/ia64/include/asm/sn/tioce.h
index 893468e1b41b..6eae8ada90f0 100644
--- a/arch/ia64/include/asm/sn/tioce.h
+++ b/arch/ia64/include/asm/sn/tioce.h
@@ -467,7 +467,7 @@ typedef volatile struct tioce {
#define CE_LSI_GB_CFG1_RXL0S_THS_SHFT 0
#define CE_LSI_GB_CFG1_RXL0S_THS_MASK (0xffULL << 0)
#define CE_LSI_GB_CFG1_RXL0S_SMP_SHFT 8
-#define CE_LSI_GB_CFG1_RXL0S_SMP_MASK (0xfULL << 8);
+#define CE_LSI_GB_CFG1_RXL0S_SMP_MASK (0xfULL << 8)
#define CE_LSI_GB_CFG1_RXL0S_ADJ_SHFT 12
#define CE_LSI_GB_CFG1_RXL0S_ADJ_MASK (0x7ULL << 12)
#define CE_LSI_GB_CFG1_RXL0S_FLT_SHFT 15
diff --git a/arch/ia64/include/asm/spinlock.h b/arch/ia64/include/asm/spinlock.h
index 1a91c9121d17..b77768d35f93 100644
--- a/arch/ia64/include/asm/spinlock.h
+++ b/arch/ia64/include/asm/spinlock.h
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/intrinsics.h>
#include <asm/system.h>
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index f64097b5118a..4826ff957a3d 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -115,7 +115,7 @@ int __init init_cyclone_clock(void)
}
/* initialize last tick */
cyclone_mc = cyclone_timer;
- clocksource_cyclone.fsys_mmio = cyclone_timer;
+ clocksource_cyclone.archdata.fsys_mmio = cyclone_timer;
clocksource_register_hz(&clocksource_cyclone, CYCLONE_TIMER_FREQ);
return 0;
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 1481b0a28ca0..24603be24c14 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -304,14 +304,6 @@ plt_target (struct plt_entry *plt)
#endif /* !USE_BRL */
-void *
-module_alloc (unsigned long size)
-{
- if (!size)
- return NULL;
- return vmalloc(size);
-}
-
void
module_free (struct module *mod, void *module_region)
{
@@ -853,14 +845,6 @@ apply_relocate_add (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symind
return 0;
}
-int
-apply_relocate (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
- unsigned int relsec, struct module *mod)
-{
- printk(KERN_ERR "module %s: REL relocs in section %u unsupported\n", mod->name, relsec);
- return -ENOEXEC;
-}
-
/*
* Modules contain a single unwind table which covers both the core and the init text
* sections but since the two are not contiguous, we need to split this table up such that
diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c
index a21d7bb9c69c..100868216c55 100644
--- a/arch/ia64/kernel/paravirt.c
+++ b/arch/ia64/kernel/paravirt.c
@@ -634,6 +634,8 @@ struct pv_irq_ops pv_irq_ops = {
* pv_time_ops
* time operations
*/
+struct jump_label_key paravirt_steal_enabled;
+struct jump_label_key paravirt_steal_rq_enabled;
static int
ia64_native_do_steal_accounting(unsigned long *new_itm)
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index be450a3e9871..0bd537b4ea6b 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -32,7 +32,7 @@
#include <linux/bitops.h>
#include <linux/kexec.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/current.h>
#include <asm/delay.h>
#include <asm/machvec.h>
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 14ec641003da..559097986672 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -40,7 +40,7 @@
#include <linux/percpu.h>
#include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cache.h>
#include <asm/current.h>
#include <asm/delay.h>
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 85118dfe9bb5..43920de425f1 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -468,7 +468,7 @@ void update_vsyscall(struct timespec *wall, struct timespec *wtm,
fsyscall_gtod_data.clk_mask = c->mask;
fsyscall_gtod_data.clk_mult = mult;
fsyscall_gtod_data.clk_shift = c->shift;
- fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio;
+ fsyscall_gtod_data.clk_fsys_mmio = c->archdata.fsys_mmio;
fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
/* copy kernel time structures */
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index c4696d217ce0..6a867dc45c05 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -25,7 +25,7 @@
#include <asm/pal.h>
#include <asm/system.h>
#include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/tlbflush.h>
#include <asm/sn/arch.h>
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index fa4d1e59deb0..9806e55f91be 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -49,6 +49,5 @@ config KVM_INTEL
extensions.
source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
endif # VIRTUALIZATION
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 81a1f4e6bcd8..485c42d97e83 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -112,8 +112,6 @@ static void sn_ack_irq(struct irq_data *data)
irq_move_irq(data);
}
-static void sn_irq_info_free(struct rcu_head *head);
-
struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
nasid_t nasid, int slice)
{
@@ -177,7 +175,7 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
spin_lock(&sn_irq_info_lock);
list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
spin_unlock(&sn_irq_info_lock);
- call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+ kfree_rcu(sn_irq_info, rcu);
finish_up:
@@ -338,14 +336,6 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
rcu_read_unlock();
}
-static void sn_irq_info_free(struct rcu_head *head)
-{
- struct sn_irq_info *sn_irq_info;
-
- sn_irq_info = container_of(head, struct sn_irq_info, rcu);
- kfree(sn_irq_info);
-}
-
void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
{
nasid_t nasid = sn_irq_info->irq_nasid;
@@ -399,7 +389,7 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)
spin_unlock(&sn_irq_info_lock);
if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
free_irq_vector(sn_irq_info->irq_irq);
- call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+ kfree_rcu(sn_irq_info, rcu);
pci_dev_put(pci_dev);
}
diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
index c34efda122e1..0f8844e49363 100644
--- a/arch/ia64/sn/kernel/sn2/timer.c
+++ b/arch/ia64/sn/kernel/sn2/timer.c
@@ -54,7 +54,7 @@ ia64_sn_udelay (unsigned long usecs)
void __init sn_timer_init(void)
{
- clocksource_sn2.fsys_mmio = RTC_COUNTER_ADDR;
+ clocksource_sn2.archdata.fsys_mmio = RTC_COUNTER_ADDR;
clocksource_register_hz(&clocksource_sn2, sn_rtc_cycles_per_second);
ia64_udelay = &ia64_sn_udelay;
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 85b44e858225..b92b9445255d 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -268,17 +268,7 @@ config SCHED_OMIT_FRAME_POINTER
bool
default y
-config PREEMPT
- bool "Preemptible Kernel"
- help
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- This allows applications to run more reliably even when the system is
- under load.
-
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
+source "kernel/Kconfig.preempt"
config SMP
bool "Symmetric multi-processing support"
diff --git a/arch/m32r/include/asm/atomic.h b/arch/m32r/include/asm/atomic.h
index d44a51e5271b..1e7f29fb21f2 100644
--- a/arch/m32r/include/asm/atomic.h
+++ b/arch/m32r/include/asm/atomic.h
@@ -239,15 +239,15 @@ static __inline__ int atomic_dec_return(atomic_t *v)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -259,10 +259,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *addr)
{
@@ -314,5 +313,4 @@ static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *addr)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
#endif /* _ASM_M32R_ATOMIC_H */
diff --git a/arch/m32r/include/asm/delay.h b/arch/m32r/include/asm/delay.h
index 9dd9e999ea69..9670e127b7b2 100644
--- a/arch/m32r/include/asm/delay.h
+++ b/arch/m32r/include/asm/delay.h
@@ -1,26 +1 @@
-#ifndef _ASM_M32R_DELAY_H
-#define _ASM_M32R_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/m32r/lib/delay.c
- */
-
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
- __udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
- __ndelay(n))
-
-#endif /* _ASM_M32R_DELAY_H */
+#include <asm-generic/delay.h>
diff --git a/arch/m32r/include/asm/mmu_context.h b/arch/m32r/include/asm/mmu_context.h
index a70a3df33635..a979a4198168 100644
--- a/arch/m32r/include/asm/mmu_context.h
+++ b/arch/m32r/include/asm/mmu_context.h
@@ -11,7 +11,7 @@
#ifndef __ASSEMBLY__
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/pgalloc.h>
#include <asm/mmu.h>
#include <asm/tlbflush.h>
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index 8397c249989b..e1f46d757460 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -106,7 +106,6 @@ struct thread_struct {
#define start_thread(regs, new_pc, new_spu) \
do { \
- set_fs(USER_DS); \
regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL; \
regs->bpc = new_pc; \
regs->spu = new_spu; \
diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h
index 840a1231edeb..527527584dd0 100644
--- a/arch/m32r/include/asm/ptrace.h
+++ b/arch/m32r/include/asm/ptrace.h
@@ -138,8 +138,6 @@ extern void init_debug_traps(struct task_struct *);
#define instruction_pointer(regs) ((regs)->bpc)
#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
-
extern void withdraw_debug_trap(struct pt_regs *regs);
#define task_pt_regs(task) \
diff --git a/arch/m32r/include/asm/spinlock.h b/arch/m32r/include/asm/spinlock.h
index 179a06489b10..b0ea2f26da3b 100644
--- a/arch/m32r/include/asm/spinlock.h
+++ b/arch/m32r/include/asm/spinlock.h
@@ -10,7 +10,7 @@
*/
#include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/page.h>
/*
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
index cb5f37d78d49..3071fe83ffc8 100644
--- a/arch/m32r/kernel/module.c
+++ b/arch/m32r/kernel/module.c
@@ -28,33 +28,6 @@
#define DEBUGP(fmt...)
#endif
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
-#ifdef CONFIG_MMU
- return vmalloc_exec(size);
-#else
- return vmalloc(size);
-#endif
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
#define COPY_UNALIGNED_WORD(sw, tw, align) \
{ \
void *__s = &(sw), *__t = &(tw); \
@@ -243,14 +216,3 @@ int apply_relocate(Elf32_Shdr *sechdrs,
return 0;
}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
index 092d40a6708e..ce7aea34fdf4 100644
--- a/arch/m32r/kernel/smp.c
+++ b/arch/m32r/kernel/smp.c
@@ -26,7 +26,7 @@
#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/m32r.h>
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
index fbd109031df3..ee6a9199561c 100644
--- a/arch/m32r/kernel/traps.c
+++ b/arch/m32r/kernel/traps.c
@@ -21,7 +21,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index d66e34c718d0..284cd3771eaa 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -41,6 +41,10 @@ config NO_DMA
config ZONE_DMA
bool
default y
+
+config CPU_HAS_NO_BITFIELDS
+ bool
+
config HZ
int
default 1000 if CLEOPATRA
diff --git a/arch/m68k/Kconfig.nommu b/arch/m68k/Kconfig.nommu
index b004dc1b1710..ff46383112a4 100644
--- a/arch/m68k/Kconfig.nommu
+++ b/arch/m68k/Kconfig.nommu
@@ -16,6 +16,7 @@ config GENERIC_CLOCKEVENTS
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
@@ -25,6 +26,7 @@ config M68000
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
@@ -34,6 +36,7 @@ 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
diff --git a/arch/m68k/Makefile_no b/arch/m68k/Makefile_no
index 81652ab893e1..844d3f172264 100644
--- a/arch/m68k/Makefile_no
+++ b/arch/m68k/Makefile_no
@@ -13,7 +13,7 @@ platform-$(CONFIG_M68EZ328) := 68EZ328
platform-$(CONFIG_M68VZ328) := 68VZ328
platform-$(CONFIG_M68360) := 68360
platform-$(CONFIG_M5206) := 5206
-platform-$(CONFIG_M5206e) := 5206e
+platform-$(CONFIG_M5206e) := 5206
platform-$(CONFIG_M520x) := 520x
platform-$(CONFIG_M523x) := 523x
platform-$(CONFIG_M5249) := 5249
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
index 8b6e201b2c20..c5748bb4ea71 100644
--- a/arch/m68k/emu/nfeth.c
+++ b/arch/m68k/emu/nfeth.c
@@ -16,6 +16,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <asm/natfeat.h>
#include <asm/virtconvert.h>
@@ -204,7 +205,6 @@ static struct net_device * __init nfeth_probe(int unit)
dev->irq = nfEtherIRQ;
dev->netdev_ops = &nfeth_netdev_ops;
- dev->flags |= NETIF_F_NO_CSUM;
memcpy(dev->dev_addr, mac, ETH_ALEN);
priv = netdev_priv(dev);
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
index 03ae3d14cd4a..65c6be6c8180 100644
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -169,21 +169,21 @@ static inline int atomic_add_negative(int i, atomic_t *v)
char c;
__asm__ __volatile__("addl %2,%1; smi %0"
: "=d" (c), "+m" (*v)
- : "id" (i));
+ : ASM_DI (i));
return c != 0;
}
static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
{
- __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
+ __asm__ __volatile__("andl %1,%0" : "+m" (*v) : ASM_DI (~(mask)));
}
static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
{
- __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
+ __asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask));
}
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -195,10 +195,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
@@ -206,6 +205,4 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
-#include <asm-generic/atomic64.h>
#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index ce163abddaba..c6baa913592a 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -1,5 +1,530 @@
-#ifdef __uClinux__
-#include "bitops_no.h"
+#ifndef _M68K_BITOPS_H
+#define _M68K_BITOPS_H
+/*
+ * Copyright 1992, Linus Torvalds.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <linux/compiler.h>
+
+/*
+ * Bit access functions vary across the ColdFire and 68k families.
+ * So we will break them out here, and then macro in the ones we want.
+ *
+ * ColdFire - supports standard bset/bclr/bchg with register operand only
+ * 68000 - supports standard bset/bclr/bchg with memory operand
+ * >= 68020 - also supports the bfset/bfclr/bfchg instructions
+ *
+ * Although it is possible to use only the bset/bclr/bchg with register
+ * operands on all platforms you end up with larger generated code.
+ * So we use the best form possible on a given platform.
+ */
+
+static inline void bset_reg_set_bit(int nr, volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+ __asm__ __volatile__ ("bset %1,(%0)"
+ :
+ : "a" (p), "di" (nr & 7)
+ : "memory");
+}
+
+static inline void bset_mem_set_bit(int nr, volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+ __asm__ __volatile__ ("bset %1,%0"
+ : "+m" (*p)
+ : "di" (nr & 7));
+}
+
+static inline void bfset_mem_set_bit(int nr, volatile unsigned long *vaddr)
+{
+ __asm__ __volatile__ ("bfset %1{%0:#1}"
+ :
+ : "d" (nr ^ 31), "o" (*vaddr)
+ : "memory");
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define set_bit(nr, vaddr) bset_reg_set_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define set_bit(nr, vaddr) bset_mem_set_bit(nr, vaddr)
+#else
+#define set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \
+ bset_mem_set_bit(nr, vaddr) : \
+ bfset_mem_set_bit(nr, vaddr))
+#endif
+
+#define __set_bit(nr, vaddr) set_bit(nr, vaddr)
+
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit() barrier()
+#define smp_mb__after_clear_bit() barrier()
+
+static inline void bclr_reg_clear_bit(int nr, volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+ __asm__ __volatile__ ("bclr %1,(%0)"
+ :
+ : "a" (p), "di" (nr & 7)
+ : "memory");
+}
+
+static inline void bclr_mem_clear_bit(int nr, volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+ __asm__ __volatile__ ("bclr %1,%0"
+ : "+m" (*p)
+ : "di" (nr & 7));
+}
+
+static inline void bfclr_mem_clear_bit(int nr, volatile unsigned long *vaddr)
+{
+ __asm__ __volatile__ ("bfclr %1{%0:#1}"
+ :
+ : "d" (nr ^ 31), "o" (*vaddr)
+ : "memory");
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define clear_bit(nr, vaddr) bclr_reg_clear_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define clear_bit(nr, vaddr) bclr_mem_clear_bit(nr, vaddr)
+#else
+#define clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \
+ bclr_mem_clear_bit(nr, vaddr) : \
+ bfclr_mem_clear_bit(nr, vaddr))
+#endif
+
+#define __clear_bit(nr, vaddr) clear_bit(nr, vaddr)
+
+
+static inline void bchg_reg_change_bit(int nr, volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+ __asm__ __volatile__ ("bchg %1,(%0)"
+ :
+ : "a" (p), "di" (nr & 7)
+ : "memory");
+}
+
+static inline void bchg_mem_change_bit(int nr, volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+ __asm__ __volatile__ ("bchg %1,%0"
+ : "+m" (*p)
+ : "di" (nr & 7));
+}
+
+static inline void bfchg_mem_change_bit(int nr, volatile unsigned long *vaddr)
+{
+ __asm__ __volatile__ ("bfchg %1{%0:#1}"
+ :
+ : "d" (nr ^ 31), "o" (*vaddr)
+ : "memory");
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define change_bit(nr, vaddr) bchg_reg_change_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define change_bit(nr, vaddr) bchg_mem_change_bit(nr, vaddr)
+#else
+#define change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \
+ bchg_mem_change_bit(nr, vaddr) : \
+ bfchg_mem_change_bit(nr, vaddr))
+#endif
+
+#define __change_bit(nr, vaddr) change_bit(nr, vaddr)
+
+
+static inline int test_bit(int nr, const unsigned long *vaddr)
+{
+ return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
+}
+
+
+static inline int bset_reg_test_and_set_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+ char retval;
+
+ __asm__ __volatile__ ("bset %2,(%1); sne %0"
+ : "=d" (retval)
+ : "a" (p), "di" (nr & 7)
+ : "memory");
+ return retval;
+}
+
+static inline int bset_mem_test_and_set_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+ char retval;
+
+ __asm__ __volatile__ ("bset %2,%1; sne %0"
+ : "=d" (retval), "+m" (*p)
+ : "di" (nr & 7));
+ return retval;
+}
+
+static inline int bfset_mem_test_and_set_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char retval;
+
+ __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
+ : "=d" (retval)
+ : "d" (nr ^ 31), "o" (*vaddr)
+ : "memory");
+ return retval;
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define test_and_set_bit(nr, vaddr) bset_reg_test_and_set_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define test_and_set_bit(nr, vaddr) bset_mem_test_and_set_bit(nr, vaddr)
+#else
+#define test_and_set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \
+ bset_mem_test_and_set_bit(nr, vaddr) : \
+ bfset_mem_test_and_set_bit(nr, vaddr))
+#endif
+
+#define __test_and_set_bit(nr, vaddr) test_and_set_bit(nr, vaddr)
+
+
+static inline int bclr_reg_test_and_clear_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+ char retval;
+
+ __asm__ __volatile__ ("bclr %2,(%1); sne %0"
+ : "=d" (retval)
+ : "a" (p), "di" (nr & 7)
+ : "memory");
+ return retval;
+}
+
+static inline int bclr_mem_test_and_clear_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+ char retval;
+
+ __asm__ __volatile__ ("bclr %2,%1; sne %0"
+ : "=d" (retval), "+m" (*p)
+ : "di" (nr & 7));
+ return retval;
+}
+
+static inline int bfclr_mem_test_and_clear_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char retval;
+
+ __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
+ : "=d" (retval)
+ : "d" (nr ^ 31), "o" (*vaddr)
+ : "memory");
+ return retval;
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define test_and_clear_bit(nr, vaddr) bclr_reg_test_and_clear_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define test_and_clear_bit(nr, vaddr) bclr_mem_test_and_clear_bit(nr, vaddr)
+#else
+#define test_and_clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \
+ bclr_mem_test_and_clear_bit(nr, vaddr) : \
+ bfclr_mem_test_and_clear_bit(nr, vaddr))
+#endif
+
+#define __test_and_clear_bit(nr, vaddr) test_and_clear_bit(nr, vaddr)
+
+
+static inline int bchg_reg_test_and_change_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+ char retval;
+
+ __asm__ __volatile__ ("bchg %2,(%1); sne %0"
+ : "=d" (retval)
+ : "a" (p), "di" (nr & 7)
+ : "memory");
+ return retval;
+}
+
+static inline int bchg_mem_test_and_change_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char *p = (char *)vaddr + (nr ^ 31) / 8;
+ char retval;
+
+ __asm__ __volatile__ ("bchg %2,%1; sne %0"
+ : "=d" (retval), "+m" (*p)
+ : "di" (nr & 7));
+ return retval;
+}
+
+static inline int bfchg_mem_test_and_change_bit(int nr,
+ volatile unsigned long *vaddr)
+{
+ char retval;
+
+ __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0"
+ : "=d" (retval)
+ : "d" (nr ^ 31), "o" (*vaddr)
+ : "memory");
+ return retval;
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define test_and_change_bit(nr, vaddr) bchg_reg_test_and_change_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define test_and_change_bit(nr, vaddr) bchg_mem_test_and_change_bit(nr, vaddr)
+#else
+#define test_and_change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \
+ bchg_mem_test_and_change_bit(nr, vaddr) : \
+ bfchg_mem_test_and_change_bit(nr, vaddr))
+#endif
+
+#define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr)
+
+
+/*
+ * The true 68020 and more advanced processors support the "bfffo"
+ * instruction for finding bits. ColdFire and simple 68000 parts
+ * (including CPU32) do not support this. They simply use the generic
+ * functions.
+ */
+#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ffz.h>
+#else
+
+static inline int find_first_zero_bit(const unsigned long *vaddr,
+ unsigned size)
+{
+ const unsigned long *p = vaddr;
+ int res = 32;
+ unsigned int words;
+ unsigned long num;
+
+ if (!size)
+ return 0;
+
+ words = (size + 31) >> 5;
+ while (!(num = ~*p++)) {
+ if (!--words)
+ goto out;
+ }
+
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+ : "=d" (res) : "d" (num & -num));
+ res ^= 31;
+out:
+ res += ((long)p - (long)vaddr - 4) * 8;
+ return res < size ? res : size;
+}
+#define find_first_zero_bit find_first_zero_bit
+
+static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
+ int offset)
+{
+ const unsigned long *p = vaddr + (offset >> 5);
+ int bit = offset & 31UL, res;
+
+ if (offset >= size)
+ return size;
+
+ if (bit) {
+ unsigned long num = ~*p++ & (~0UL << bit);
+ offset -= bit;
+
+ /* Look for zero in first longword */
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+ : "=d" (res) : "d" (num & -num));
+ if (res < 32) {
+ offset += res ^ 31;
+ return offset < size ? offset : size;
+ }
+ offset += 32;
+
+ if (offset >= size)
+ return size;
+ }
+ /* No zero yet, search remaining full bytes for a zero */
+ return offset + find_first_zero_bit(p, size - offset);
+}
+#define find_next_zero_bit find_next_zero_bit
+
+static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
+{
+ const unsigned long *p = vaddr;
+ int res = 32;
+ unsigned int words;
+ unsigned long num;
+
+ if (!size)
+ return 0;
+
+ words = (size + 31) >> 5;
+ while (!(num = *p++)) {
+ if (!--words)
+ goto out;
+ }
+
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+ : "=d" (res) : "d" (num & -num));
+ res ^= 31;
+out:
+ res += ((long)p - (long)vaddr - 4) * 8;
+ return res < size ? res : size;
+}
+#define find_first_bit find_first_bit
+
+static inline int find_next_bit(const unsigned long *vaddr, int size,
+ int offset)
+{
+ const unsigned long *p = vaddr + (offset >> 5);
+ int bit = offset & 31UL, res;
+
+ if (offset >= size)
+ return size;
+
+ if (bit) {
+ unsigned long num = *p++ & (~0UL << bit);
+ offset -= bit;
+
+ /* Look for one in first longword */
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+ : "=d" (res) : "d" (num & -num));
+ if (res < 32) {
+ offset += res ^ 31;
+ return offset < size ? offset : size;
+ }
+ offset += 32;
+
+ if (offset >= size)
+ return size;
+ }
+ /* No one yet, search remaining full bytes for a one */
+ return offset + find_first_bit(p, size - offset);
+}
+#define find_next_bit find_next_bit
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+ int res;
+
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+ : "=d" (res) : "d" (~word & -~word));
+ return res ^ 31;
+}
+
+#endif
+
+#ifdef __KERNEL__
+
+#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+
+/*
+ * The newer ColdFire family members support a "bitrev" instruction
+ * and we can use that to implement a fast ffs. Older Coldfire parts,
+ * and normal 68000 parts don't have anything special, so we use the
+ * generic functions for those.
+ */
+#if (defined(__mcfisaaplus__) || defined(__mcfisac__)) && \
+ !defined(CONFIG_M68000) && !defined(CONFIG_MCPU32)
+static inline int __ffs(int x)
+{
+ __asm__ __volatile__ ("bitrev %0; ff1 %0"
+ : "=d" (x)
+ : "0" (x));
+ return x;
+}
+
+static inline int ffs(int x)
+{
+ if (!x)
+ return 0;
+ return __ffs(x) + 1;
+}
+
+#else
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/__ffs.h>
+#endif
+
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+
#else
-#include "bitops_mm.h"
+
+/*
+ * ffs: find first bit set. 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 int ffs(int x)
+{
+ int cnt;
+
+ __asm__ ("bfffo %1{#0:#0},%0"
+ : "=d" (cnt)
+ : "dm" (x & -x));
+ return 32 - cnt;
+}
+#define __ffs(x) (ffs(x) - 1)
+
+/*
+ * fls: find last bit set.
+ */
+static inline int fls(int x)
+{
+ int cnt;
+
+ __asm__ ("bfffo %1{#0,#0},%0"
+ : "=d" (cnt)
+ : "dm" (x));
+ return 32 - cnt;
+}
+
+static inline int __fls(int x)
+{
+ return fls(x) - 1;
+}
+
#endif
+
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+#endif /* __KERNEL__ */
+
+#endif /* _M68K_BITOPS_H */
diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h
deleted file mode 100644
index 89cf5b814a4d..000000000000
--- a/arch/m68k/include/asm/bitops_mm.h
+++ /dev/null
@@ -1,501 +0,0 @@
-#ifndef _M68K_BITOPS_H
-#define _M68K_BITOPS_H
-/*
- * Copyright 1992, Linus Torvalds.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#include <linux/compiler.h>
-
-/*
- * Require 68020 or better.
- *
- * They use the standard big-endian m680x0 bit ordering.
- */
-
-#define test_and_set_bit(nr,vaddr) \
- (__builtin_constant_p(nr) ? \
- __constant_test_and_set_bit(nr, vaddr) : \
- __generic_test_and_set_bit(nr, vaddr))
-
-#define __test_and_set_bit(nr,vaddr) test_and_set_bit(nr,vaddr)
-
-static inline int __constant_test_and_set_bit(int nr, unsigned long *vaddr)
-{
- char *p = (char *)vaddr + (nr ^ 31) / 8;
- char retval;
-
- __asm__ __volatile__ ("bset %2,%1; sne %0"
- : "=d" (retval), "+m" (*p)
- : "di" (nr & 7));
-
- return retval;
-}
-
-static inline int __generic_test_and_set_bit(int nr, unsigned long *vaddr)
-{
- char retval;
-
- __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
- : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
-
- return retval;
-}
-
-#define set_bit(nr,vaddr) \
- (__builtin_constant_p(nr) ? \
- __constant_set_bit(nr, vaddr) : \
- __generic_set_bit(nr, vaddr))
-
-#define __set_bit(nr,vaddr) set_bit(nr,vaddr)
-
-static inline void __constant_set_bit(int nr, volatile unsigned long *vaddr)
-{
- char *p = (char *)vaddr + (nr ^ 31) / 8;
- __asm__ __volatile__ ("bset %1,%0"
- : "+m" (*p) : "di" (nr & 7));
-}
-
-static inline void __generic_set_bit(int nr, volatile unsigned long *vaddr)
-{
- __asm__ __volatile__ ("bfset %1{%0:#1}"
- : : "d" (nr^31), "o" (*vaddr) : "memory");
-}
-
-#define test_and_clear_bit(nr,vaddr) \
- (__builtin_constant_p(nr) ? \
- __constant_test_and_clear_bit(nr, vaddr) : \
- __generic_test_and_clear_bit(nr, vaddr))
-
-#define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr)
-
-static inline int __constant_test_and_clear_bit(int nr, unsigned long *vaddr)
-{
- char *p = (char *)vaddr + (nr ^ 31) / 8;
- char retval;
-
- __asm__ __volatile__ ("bclr %2,%1; sne %0"
- : "=d" (retval), "+m" (*p)
- : "di" (nr & 7));
-
- return retval;
-}
-
-static inline int __generic_test_and_clear_bit(int nr, unsigned long *vaddr)
-{
- char retval;
-
- __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
- : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
-
- return retval;
-}
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit() barrier()
-#define smp_mb__after_clear_bit() barrier()
-
-#define clear_bit(nr,vaddr) \
- (__builtin_constant_p(nr) ? \
- __constant_clear_bit(nr, vaddr) : \
- __generic_clear_bit(nr, vaddr))
-#define __clear_bit(nr,vaddr) clear_bit(nr,vaddr)
-
-static inline void __constant_clear_bit(int nr, volatile unsigned long *vaddr)
-{
- char *p = (char *)vaddr + (nr ^ 31) / 8;
- __asm__ __volatile__ ("bclr %1,%0"
- : "+m" (*p) : "di" (nr & 7));
-}
-
-static inline void __generic_clear_bit(int nr, volatile unsigned long *vaddr)
-{
- __asm__ __volatile__ ("bfclr %1{%0:#1}"
- : : "d" (nr^31), "o" (*vaddr) : "memory");
-}
-
-#define test_and_change_bit(nr,vaddr) \
- (__builtin_constant_p(nr) ? \
- __constant_test_and_change_bit(nr, vaddr) : \
- __generic_test_and_change_bit(nr, vaddr))
-
-#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr)
-#define __change_bit(nr,vaddr) change_bit(nr,vaddr)
-
-static inline int __constant_test_and_change_bit(int nr, unsigned long *vaddr)
-{
- char *p = (char *)vaddr + (nr ^ 31) / 8;
- char retval;
-
- __asm__ __volatile__ ("bchg %2,%1; sne %0"
- : "=d" (retval), "+m" (*p)
- : "di" (nr & 7));
-
- return retval;
-}
-
-static inline int __generic_test_and_change_bit(int nr, unsigned long *vaddr)
-{
- char retval;
-
- __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0"
- : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
-
- return retval;
-}
-
-#define change_bit(nr,vaddr) \
- (__builtin_constant_p(nr) ? \
- __constant_change_bit(nr, vaddr) : \
- __generic_change_bit(nr, vaddr))
-
-static inline void __constant_change_bit(int nr, unsigned long *vaddr)
-{
- char *p = (char *)vaddr + (nr ^ 31) / 8;
- __asm__ __volatile__ ("bchg %1,%0"
- : "+m" (*p) : "di" (nr & 7));
-}
-
-static inline void __generic_change_bit(int nr, unsigned long *vaddr)
-{
- __asm__ __volatile__ ("bfchg %1{%0:#1}"
- : : "d" (nr^31), "o" (*vaddr) : "memory");
-}
-
-static inline int test_bit(int nr, const unsigned long *vaddr)
-{
- return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
-}
-
-static inline int find_first_zero_bit(const unsigned long *vaddr,
- unsigned size)
-{
- const unsigned long *p = vaddr;
- int res = 32;
- unsigned int words;
- unsigned long num;
-
- if (!size)
- return 0;
-
- words = (size + 31) >> 5;
- while (!(num = ~*p++)) {
- if (!--words)
- goto out;
- }
-
- __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
- : "=d" (res) : "d" (num & -num));
- res ^= 31;
-out:
- res += ((long)p - (long)vaddr - 4) * 8;
- return res < size ? res : size;
-}
-#define find_first_zero_bit find_first_zero_bit
-
-static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
- int offset)
-{
- const unsigned long *p = vaddr + (offset >> 5);
- int bit = offset & 31UL, res;
-
- if (offset >= size)
- return size;
-
- if (bit) {
- unsigned long num = ~*p++ & (~0UL << bit);
- offset -= bit;
-
- /* Look for zero in first longword */
- __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
- : "=d" (res) : "d" (num & -num));
- if (res < 32) {
- offset += res ^ 31;
- return offset < size ? offset : size;
- }
- offset += 32;
-
- if (offset >= size)
- return size;
- }
- /* No zero yet, search remaining full bytes for a zero */
- return offset + find_first_zero_bit(p, size - offset);
-}
-#define find_next_zero_bit find_next_zero_bit
-
-static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
-{
- const unsigned long *p = vaddr;
- int res = 32;
- unsigned int words;
- unsigned long num;
-
- if (!size)
- return 0;
-
- words = (size + 31) >> 5;
- while (!(num = *p++)) {
- if (!--words)
- goto out;
- }
-
- __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
- : "=d" (res) : "d" (num & -num));
- res ^= 31;
-out:
- res += ((long)p - (long)vaddr - 4) * 8;
- return res < size ? res : size;
-}
-#define find_first_bit find_first_bit
-
-static inline int find_next_bit(const unsigned long *vaddr, int size,
- int offset)
-{
- const unsigned long *p = vaddr + (offset >> 5);
- int bit = offset & 31UL, res;
-
- if (offset >= size)
- return size;
-
- if (bit) {
- unsigned long num = *p++ & (~0UL << bit);
- offset -= bit;
-
- /* Look for one in first longword */
- __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
- : "=d" (res) : "d" (num & -num));
- if (res < 32) {
- offset += res ^ 31;
- return offset < size ? offset : size;
- }
- offset += 32;
-
- if (offset >= size)
- return size;
- }
- /* No one yet, search remaining full bytes for a one */
- return offset + find_first_bit(p, size - offset);
-}
-#define find_next_bit find_next_bit
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static inline unsigned long ffz(unsigned long word)
-{
- int res;
-
- __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
- : "=d" (res) : "d" (~word & -~word));
- return res ^ 31;
-}
-
-#ifdef __KERNEL__
-
-/*
- * ffs: find first bit set. 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 int ffs(int x)
-{
- int cnt;
-
- asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
-
- return 32 - cnt;
-}
-#define __ffs(x) (ffs(x) - 1)
-
-/*
- * fls: find last bit set.
- */
-
-static inline int fls(int x)
-{
- int cnt;
-
- asm ("bfffo %1{#0,#0},%0" : "=d" (cnt) : "dm" (x));
-
- return 32 - cnt;
-}
-
-static inline int __fls(int x)
-{
- return fls(x) - 1;
-}
-
-#include <asm-generic/bitops/fls64.h>
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-
-/* Bitmap functions for the little endian bitmap. */
-
-static inline void __set_bit_le(int nr, void *addr)
-{
- __set_bit(nr ^ 24, addr);
-}
-
-static inline void __clear_bit_le(int nr, void *addr)
-{
- __clear_bit(nr ^ 24, addr);
-}
-
-static inline int __test_and_set_bit_le(int nr, void *addr)
-{
- return __test_and_set_bit(nr ^ 24, addr);
-}
-
-static inline int test_and_set_bit_le(int nr, void *addr)
-{
- return test_and_set_bit(nr ^ 24, addr);
-}
-
-static inline int __test_and_clear_bit_le(int nr, void *addr)
-{
- return __test_and_clear_bit(nr ^ 24, addr);
-}
-
-static inline int test_and_clear_bit_le(int nr, void *addr)
-{
- return test_and_clear_bit(nr ^ 24, addr);
-}
-
-static inline int test_bit_le(int nr, const void *vaddr)
-{
- const unsigned char *p = vaddr;
- return (p[nr >> 3] & (1U << (nr & 7))) != 0;
-}
-
-static inline int find_first_zero_bit_le(const void *vaddr, unsigned size)
-{
- const unsigned long *p = vaddr, *addr = vaddr;
- int res = 0;
- unsigned int words;
-
- if (!size)
- return 0;
-
- words = (size >> 5) + ((size & 31) > 0);
- while (*p++ == ~0UL) {
- if (--words == 0)
- goto out;
- }
-
- --p;
- for (res = 0; res < 32; res++)
- if (!test_bit_le(res, p))
- break;
-out:
- res += (p - addr) * 32;
- return res < size ? res : size;
-}
-#define find_first_zero_bit_le find_first_zero_bit_le
-
-static inline unsigned long find_next_zero_bit_le(const void *addr,
- unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr;
- int bit = offset & 31UL, res;
-
- if (offset >= size)
- return size;
-
- p += offset >> 5;
-
- if (bit) {
- offset -= bit;
- /* Look for zero in first longword */
- for (res = bit; res < 32; res++)
- if (!test_bit_le(res, p)) {
- offset += res;
- return offset < size ? offset : size;
- }
- p++;
- offset += 32;
-
- if (offset >= size)
- return size;
- }
- /* No zero yet, search remaining full bytes for a zero */
- return offset + find_first_zero_bit_le(p, size - offset);
-}
-#define find_next_zero_bit_le find_next_zero_bit_le
-
-static inline int find_first_bit_le(const void *vaddr, unsigned size)
-{
- const unsigned long *p = vaddr, *addr = vaddr;
- int res = 0;
- unsigned int words;
-
- if (!size)
- return 0;
-
- words = (size >> 5) + ((size & 31) > 0);
- while (*p++ == 0UL) {
- if (--words == 0)
- goto out;
- }
-
- --p;
- for (res = 0; res < 32; res++)
- if (test_bit_le(res, p))
- break;
-out:
- res += (p - addr) * 32;
- return res < size ? res : size;
-}
-#define find_first_bit_le find_first_bit_le
-
-static inline unsigned long find_next_bit_le(const void *addr,
- unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr;
- int bit = offset & 31UL, res;
-
- if (offset >= size)
- return size;
-
- p += offset >> 5;
-
- if (bit) {
- offset -= bit;
- /* Look for one in first longword */
- for (res = bit; res < 32; res++)
- if (test_bit_le(res, p)) {
- offset += res;
- return offset < size ? offset : size;
- }
- p++;
- offset += 32;
-
- if (offset >= size)
- return size;
- }
- /* No set bit yet, search remaining full bytes for a set bit */
- return offset + find_first_bit_le(p, size - offset);
-}
-#define find_next_bit_le find_next_bit_le
-
-/* Bitmap functions for the ext2 filesystem. */
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit_le(nr, addr)
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit_le(nr, addr)
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_BITOPS_H */
diff --git a/arch/m68k/include/asm/bitops_no.h b/arch/m68k/include/asm/bitops_no.h
deleted file mode 100644
index 72e85acdd7bd..000000000000
--- a/arch/m68k/include/asm/bitops_no.h
+++ /dev/null
@@ -1,333 +0,0 @@
-#ifndef _M68KNOMMU_BITOPS_H
-#define _M68KNOMMU_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-#include <linux/compiler.h>
-#include <asm/byteorder.h> /* swab32 */
-
-#ifdef __KERNEL__
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#if defined (__mcfisaaplus__) || defined (__mcfisac__)
-static inline int ffs(unsigned int val)
-{
- if (!val)
- return 0;
-
- asm volatile(
- "bitrev %0\n\t"
- "ff1 %0\n\t"
- : "=d" (val)
- : "0" (val)
- );
- val++;
- return val;
-}
-
-static inline int __ffs(unsigned int val)
-{
- asm volatile(
- "bitrev %0\n\t"
- "ff1 %0\n\t"
- : "=d" (val)
- : "0" (val)
- );
- return val;
-}
-
-#else
-#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/__ffs.h>
-#endif
-
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ffz.h>
-
-static __inline__ void set_bit(int nr, volatile unsigned long * addr)
-{
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %0,%%a0; bset %1,(%%a0)"
- : "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "d" (nr)
- : "%a0", "cc");
-#else
- __asm__ __volatile__ ("bset %1,%0"
- : "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "di" (nr)
- : "cc");
-#endif
-}
-
-#define __set_bit(nr, addr) set_bit(nr, addr)
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit() barrier()
-#define smp_mb__after_clear_bit() barrier()
-
-static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
-{
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %0,%%a0; bclr %1,(%%a0)"
- : "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "d" (nr)
- : "%a0", "cc");
-#else
- __asm__ __volatile__ ("bclr %1,%0"
- : "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "di" (nr)
- : "cc");
-#endif
-}
-
-#define __clear_bit(nr, addr) clear_bit(nr, addr)
-
-static __inline__ void change_bit(int nr, volatile unsigned long * addr)
-{
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %0,%%a0; bchg %1,(%%a0)"
- : "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "d" (nr)
- : "%a0", "cc");
-#else
- __asm__ __volatile__ ("bchg %1,%0"
- : "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "di" (nr)
- : "cc");
-#endif
-}
-
-#define __change_bit(nr, addr) change_bit(nr, addr)
-
-static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
-{
- char retval;
-
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %1,%%a0; bset %2,(%%a0); sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "d" (nr)
- : "%a0");
-#else
- __asm__ __volatile__ ("bset %2,%1; sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "di" (nr)
- /* No clobber */);
-#endif
-
- return retval;
-}
-
-#define __test_and_set_bit(nr, addr) test_and_set_bit(nr, addr)
-
-static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
-{
- char retval;
-
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %1,%%a0; bclr %2,(%%a0); sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "d" (nr)
- : "%a0");
-#else
- __asm__ __volatile__ ("bclr %2,%1; sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "di" (nr)
- /* No clobber */);
-#endif
-
- return retval;
-}
-
-#define __test_and_clear_bit(nr, addr) test_and_clear_bit(nr, addr)
-
-static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
-{
- char retval;
-
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %1,%%a0\n\tbchg %2,(%%a0)\n\tsne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "d" (nr)
- : "%a0");
-#else
- __asm__ __volatile__ ("bchg %2,%1; sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
- : "di" (nr)
- /* No clobber */);
-#endif
-
- return retval;
-}
-
-#define __test_and_change_bit(nr, addr) test_and_change_bit(nr, addr)
-
-/*
- * This routine doesn't need to be atomic.
- */
-static __inline__ int __constant_test_bit(int nr, const volatile unsigned long * addr)
-{
- return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
-}
-
-static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
-{
- int * a = (int *) addr;
- int mask;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- return ((mask & *a) != 0);
-}
-
-#define test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- __constant_test_bit((nr),(addr)) : \
- __test_bit((nr),(addr)))
-
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-
-#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
-
-static inline void __set_bit_le(int nr, void *addr)
-{
- __set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline void __clear_bit_le(int nr, void *addr)
-{
- __clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline int __test_and_set_bit_le(int nr, volatile void *addr)
-{
- char retval;
-
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %1,%%a0; bset %2,(%%a0); sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
- : "d" (nr)
- : "%a0");
-#else
- __asm__ __volatile__ ("bset %2,%1; sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
- : "di" (nr)
- /* No clobber */);
-#endif
-
- return retval;
-}
-
-static inline int __test_and_clear_bit_le(int nr, volatile void *addr)
-{
- char retval;
-
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %1,%%a0; bclr %2,(%%a0); sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
- : "d" (nr)
- : "%a0");
-#else
- __asm__ __volatile__ ("bclr %2,%1; sne %0"
- : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
- : "di" (nr)
- /* No clobber */);
-#endif
-
- return retval;
-}
-
-#include <asm-generic/bitops/ext2-atomic.h>
-
-static inline int test_bit_le(int nr, const volatile void *addr)
-{
- char retval;
-
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__ ("lea %1,%%a0; btst %2,(%%a0); sne %0"
- : "=d" (retval)
- : "m" (((const volatile char *)addr)[nr >> 3]), "d" (nr)
- : "%a0");
-#else
- __asm__ __volatile__ ("btst %2,%1; sne %0"
- : "=d" (retval)
- : "m" (((const volatile char *)addr)[nr >> 3]), "di" (nr)
- /* No clobber */);
-#endif
-
- return retval;
-}
-
-#define find_first_zero_bit_le(addr, size) \
- find_next_zero_bit_le((addr), (size), 0)
-
-static inline unsigned long find_next_zero_bit_le(void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- /* We hold the little endian value in tmp, but then the
- * shift is illegal. So we could keep a big endian value
- * in tmp, like this:
- *
- * tmp = __swab32(*(p++));
- * tmp |= ~0UL >> (32-offset);
- *
- * but this would decrease performance, so we change the
- * shift:
- */
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- /* tmp is little endian, so we would have to swab the shift,
- * see above. But then we have to swab tmp below for ffz, so
- * we might as well do this here.
- */
- return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
- return result + ffz(__swab32(tmp));
-}
-#define find_next_zero_bit_le find_next_zero_bit_le
-
-extern unsigned long find_next_bit_le(const void *addr,
- unsigned long size, unsigned long offset);
-
-#endif /* __KERNEL__ */
-
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/__fls.h>
-#include <asm-generic/bitops/fls64.h>
-
-#endif /* _M68KNOMMU_BITOPS_H */
diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h
index d2598e3dd7b2..9c09becfd4c9 100644
--- a/arch/m68k/include/asm/delay.h
+++ b/arch/m68k/include/asm/delay.h
@@ -1,5 +1,96 @@
-#ifdef __uClinux__
-#include "delay_no.h"
+#ifndef _M68K_DELAY_H
+#define _M68K_DELAY_H
+
+#include <asm/param.h>
+
+/*
+ * Copyright (C) 1994 Hamish Macdonald
+ * Copyright (C) 2004 Greg Ungerer <gerg@uclinux.com>
+ *
+ * Delay routines, using a pre-computed "loops_per_jiffy" value.
+ */
+
+#if defined(CONFIG_COLDFIRE)
+/*
+ * The ColdFire runs the delay loop at significantly different speeds
+ * depending upon long word alignment or not. We'll pad it to
+ * long word alignment which is the faster version.
+ * The 0x4a8e is of course a 'tstl %fp' instruction. This is better
+ * than using a NOP (0x4e71) instruction because it executes in one
+ * cycle not three and doesn't allow for an arbitrary delay waiting
+ * for bus cycles to finish. Also fp/a6 isn't likely to cause a
+ * stall waiting for the register to become valid if such is added
+ * to the coldfire at some stage.
+ */
+#define DELAY_ALIGN ".balignw 4, 0x4a8e\n\t"
#else
-#include "delay_mm.h"
+/*
+ * No instruction alignment required for other m68k types.
+ */
+#define DELAY_ALIGN
#endif
+
+static inline void __delay(unsigned long loops)
+{
+ __asm__ __volatile__ (
+ DELAY_ALIGN
+ "1: subql #1,%0\n\t"
+ "jcc 1b"
+ : "=d" (loops)
+ : "0" (loops));
+}
+
+extern void __bad_udelay(void);
+
+
+#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)
+/*
+ * The simpler m68k and ColdFire processors do not have a 32*32->64
+ * multiply instruction. So we need to handle them a little differently.
+ * We use a bit of shifting and a single 32*32->32 multiply to get close.
+ * This is a macro so that the const version can factor out the first
+ * multiply and shift.
+ */
+#define HZSCALE (268435456 / (1000000 / HZ))
+
+#define __const_udelay(u) \
+ __delay(((((u) * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6)
+
+#else
+
+static inline void __xdelay(unsigned long xloops)
+{
+ unsigned long tmp;
+
+ __asm__ ("mulul %2,%0:%1"
+ : "=d" (xloops), "=d" (tmp)
+ : "d" (xloops), "1" (loops_per_jiffy));
+ __delay(xloops * HZ);
+}
+
+/*
+ * The definition of __const_udelay is specifically made a macro so that
+ * the const factor (4295 = 2**32 / 1000000) can be optimized out when
+ * the delay is a const.
+ */
+#define __const_udelay(n) (__xdelay((n) * 4295))
+
+#endif
+
+static inline void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs);
+}
+
+/*
+ * Use only for very small delays ( < 1 msec). Should probably use a
+ * lookup table, really, as the multiplications take much too long with
+ * short delays. This is a "reasonable" implementation, though (and the
+ * first constant multiplications gets optimized away if the delay is
+ * a constant)
+ */
+#define udelay(n) (__builtin_constant_p(n) ? \
+ ((n) > 20000 ? __bad_udelay() : __const_udelay(n)) : __udelay(n))
+
+
+#endif /* defined(_M68K_DELAY_H) */
diff --git a/arch/m68k/include/asm/delay_mm.h b/arch/m68k/include/asm/delay_mm.h
deleted file mode 100644
index 5ed92851bc6f..000000000000
--- a/arch/m68k/include/asm/delay_mm.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _M68K_DELAY_H
-#define _M68K_DELAY_H
-
-#include <asm/param.h>
-
-/*
- * Copyright (C) 1994 Hamish Macdonald
- *
- * Delay routines, using a pre-computed "loops_per_jiffy" value.
- */
-
-static inline void __delay(unsigned long loops)
-{
- __asm__ __volatile__ ("1: subql #1,%0; jcc 1b"
- : "=d" (loops) : "0" (loops));
-}
-
-extern void __bad_udelay(void);
-
-/*
- * Use only for very small delays ( < 1 msec). Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays. This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
- */
-static inline void __const_udelay(unsigned long xloops)
-{
- unsigned long tmp;
-
- __asm__ ("mulul %2,%0:%1"
- : "=d" (xloops), "=d" (tmp)
- : "d" (xloops), "1" (loops_per_jiffy));
- __delay(xloops * HZ);
-}
-
-static inline void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 4295); /* 2**32 / 1000000 */
-}
-
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 4295)) : \
- __udelay(n))
-
-static inline unsigned long muldiv(unsigned long a, unsigned long b,
- unsigned long c)
-{
- unsigned long tmp;
-
- __asm__ ("mulul %2,%0:%1; divul %3,%0:%1"
- : "=d" (tmp), "=d" (a)
- : "d" (b), "d" (c), "1" (a));
- return a;
-}
-
-#endif /* defined(_M68K_DELAY_H) */
diff --git a/arch/m68k/include/asm/delay_no.h b/arch/m68k/include/asm/delay_no.h
deleted file mode 100644
index c3a0edc90f21..000000000000
--- a/arch/m68k/include/asm/delay_no.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _M68KNOMMU_DELAY_H
-#define _M68KNOMMU_DELAY_H
-
-/*
- * Copyright (C) 1994 Hamish Macdonald
- * Copyright (C) 2004 Greg Ungerer <gerg@snapgear.com>
- */
-
-#include <asm/param.h>
-
-static inline void __delay(unsigned long loops)
-{
-#if defined(CONFIG_COLDFIRE)
- /* The coldfire runs this loop at significantly different speeds
- * depending upon long word alignment or not. We'll pad it to
- * long word alignment which is the faster version.
- * The 0x4a8e is of course a 'tstl %fp' instruction. This is better
- * than using a NOP (0x4e71) instruction because it executes in one
- * cycle not three and doesn't allow for an arbitrary delay waiting
- * for bus cycles to finish. Also fp/a6 isn't likely to cause a
- * stall waiting for the register to become valid if such is added
- * to the coldfire at some stage.
- */
- __asm__ __volatile__ ( ".balignw 4, 0x4a8e\n\t"
- "1: subql #1, %0\n\t"
- "jcc 1b"
- : "=d" (loops) : "0" (loops));
-#else
- __asm__ __volatile__ ( "1: subql #1, %0\n\t"
- "jcc 1b"
- : "=d" (loops) : "0" (loops));
-#endif
-}
-
-/*
- * Ideally we use a 32*32->64 multiply to calculate the number of
- * loop iterations, but the older standard 68k and ColdFire do not
- * have this instruction. So for them we have a clsoe approximation
- * loop using 32*32->32 multiplies only. This calculation based on
- * the ARM version of delay.
- *
- * We want to implement:
- *
- * loops = (usecs * 0x10c6 * HZ * loops_per_jiffy) / 2^32
- */
-
-#define HZSCALE (268435456 / (1000000/HZ))
-
-extern unsigned long loops_per_jiffy;
-
-static inline void _udelay(unsigned long usecs)
-{
-#if defined(CONFIG_M68328) || defined(CONFIG_M68EZ328) || \
- defined(CONFIG_M68VZ328) || defined(CONFIG_M68360) || \
- defined(CONFIG_COLDFIRE)
- __delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6);
-#else
- unsigned long tmp;
-
- usecs *= 4295; /* 2**32 / 1000000 */
- __asm__ ("mulul %2,%0:%1"
- : "=d" (usecs), "=d" (tmp)
- : "d" (usecs), "1" (loops_per_jiffy*HZ));
- __delay(usecs);
-#endif
-}
-
-/*
- * Moved the udelay() function into library code, no longer inlined.
- * I had to change the algorithm because we are overflowing now on
- * the faster ColdFire parts. The code is a little bigger, so it makes
- * sense to library it.
- */
-extern void udelay(unsigned long usecs);
-
-#endif /* defined(_M68KNOMMU_DELAY_H) */
diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h
index 627d69bacc58..68611e3dbb1d 100644
--- a/arch/m68k/include/asm/entry_no.h
+++ b/arch/m68k/include/asm/entry_no.h
@@ -96,11 +96,11 @@
.endm
.macro RDUSP
- movel sw_usp,%a2
+ movel sw_usp,%a3
.endm
.macro WRUSP
- movel %a0,sw_usp
+ movel %a3,sw_usp
.endm
#else /* !CONFIG_COLDFIRE_SW_A7 */
@@ -127,13 +127,13 @@
.endm
.macro RDUSP
- /*move %usp,%a2*/
- .word 0x4e6a
+ /*move %usp,%a3*/
+ .word 0x4e6b
.endm
.macro WRUSP
- /*move %a0,%usp*/
- .word 0x4e60
+ /*move %a3,%usp*/
+ .word 0x4e63
.endm
#endif /* !CONFIG_COLDFIRE_SW_A7 */
diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h
index 56d0d5db231c..870e5347155b 100644
--- a/arch/m68k/include/asm/hardirq.h
+++ b/arch/m68k/include/asm/hardirq.h
@@ -1,5 +1,34 @@
-#ifdef __uClinux__
-#include "hardirq_no.h"
+#ifndef __M68K_HARDIRQ_H
+#define __M68K_HARDIRQ_H
+
+#include <linux/threads.h>
+#include <linux/cache.h>
+#include <asm/irq.h>
+
+#define HARDIRQ_BITS 8
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+#ifdef CONFIG_MMU
+
+/* entry.S is sensitive to the offsets of these fields */
+typedef struct {
+ unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
#else
-#include "hardirq_mm.h"
+
+#include <asm-generic/hardirq.h>
+
+#endif /* !CONFIG_MMU */
+
#endif
diff --git a/arch/m68k/include/asm/hardirq_mm.h b/arch/m68k/include/asm/hardirq_mm.h
deleted file mode 100644
index 394ee946015c..000000000000
--- a/arch/m68k/include/asm/hardirq_mm.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __M68K_HARDIRQ_H
-#define __M68K_HARDIRQ_H
-
-#include <linux/threads.h>
-#include <linux/cache.h>
-
-/* entry.S is sensitive to the offsets of these fields */
-typedef struct {
- unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
-#define HARDIRQ_BITS 8
-
-#endif
diff --git a/arch/m68k/include/asm/hardirq_no.h b/arch/m68k/include/asm/hardirq_no.h
deleted file mode 100644
index b44b14be87d9..000000000000
--- a/arch/m68k/include/asm/hardirq_no.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __M68K_HARDIRQ_H
-#define __M68K_HARDIRQ_H
-
-#include <asm/irq.h>
-
-#define HARDIRQ_BITS 8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-#include <asm-generic/hardirq.h>
-
-#endif /* __M68K_HARDIRQ_H */
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index 907eff1edd2f..69ed0d74d532 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -33,15 +33,6 @@
#include <linux/spinlock_types.h>
/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-/*
* Interrupt source definitions
* General interrupt sources are the level 1-7.
* Adding an interrupt service routine for one of these sources
@@ -131,4 +122,6 @@ asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
#define irq_canonicalize(irq) (irq)
#endif /* CONFIG_MMU */
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+
#endif /* _M68K_IRQ_H_ */
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index 415d5484916c..789f3b2de0e9 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -40,6 +40,5 @@ extern unsigned long hw_timer_offset(void);
extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
extern void config_BSP(char *command, int len);
-extern void do_IRQ(int irq, struct pt_regs *fp);
#endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h
index 5f21e11071bd..edffe66b7f49 100644
--- a/arch/m68k/include/asm/module.h
+++ b/arch/m68k/include/asm/module.h
@@ -1,46 +1,41 @@
#ifndef _ASM_M68K_MODULE_H
#define _ASM_M68K_MODULE_H
-#ifdef CONFIG_MMU
+enum m68k_fixup_type {
+ m68k_fixup_memoffset,
+ m68k_fixup_vnode_shift,
+};
+
+struct m68k_fixup_info {
+ enum m68k_fixup_type type;
+ void *addr;
+};
struct mod_arch_specific {
struct m68k_fixup_info *fixup_start, *fixup_end;
};
+#ifdef CONFIG_MMU
+
#define MODULE_ARCH_INIT { \
.fixup_start = __start_fixup, \
.fixup_end = __stop_fixup, \
}
-enum m68k_fixup_type {
- m68k_fixup_memoffset,
- m68k_fixup_vnode_shift,
-};
-
-struct m68k_fixup_info {
- enum m68k_fixup_type type;
- void *addr;
-};
-
#define m68k_fixup(type, addr) \
" .section \".m68k_fixup\",\"aw\"\n" \
" .long " #type "," #addr "\n" \
" .previous\n"
+#endif /* CONFIG_MMU */
+
extern struct m68k_fixup_info __start_fixup[], __stop_fixup[];
struct module;
extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
struct m68k_fixup_info *end);
-#else
-
-struct mod_arch_specific {
-};
-
-#endif /* CONFIG_MMU */
-
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Ehdr Elf32_Ehdr
diff --git a/arch/m68k/include/asm/posix_types.h b/arch/m68k/include/asm/posix_types.h
index 63cdcc142d93..98d0970d9bad 100644
--- a/arch/m68k/include/asm/posix_types.h
+++ b/arch/m68k/include/asm/posix_types.h
@@ -51,7 +51,7 @@ typedef struct {
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
#undef __FD_ISSET
-#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define __FD_ISSET(d, set) (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
#undef __FD_ZERO
#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index f111b02b704f..d8ef53ac03f9 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -105,9 +105,6 @@ struct thread_struct {
static inline void start_thread(struct pt_regs * regs, unsigned long pc,
unsigned long usp)
{
- /* reads from user space */
- set_fs(USER_DS);
-
regs->pc = pc;
regs->sr &= ~0x2000;
wrusp(usp);
@@ -129,7 +126,6 @@ extern int handle_kernel_fault(struct pt_regs *regs);
#define start_thread(_regs, _pc, _usp) \
do { \
- set_fs(USER_DS); /* reads from user space */ \
(_regs)->pc = (_pc); \
((struct switch_stack *)(_regs))[-1].a6 = 0; \
reformat(_regs); \
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
index 6e6e3ac1d913..65322b17b6cf 100644
--- a/arch/m68k/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace.h
@@ -85,7 +85,6 @@ struct switch_stack {
#define user_mode(regs) (!((regs)->sr & PS_S))
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
#define arch_has_single_step() (1)
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
index 5bc09c787a11..60e88660169c 100644
--- a/arch/m68k/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal.h
@@ -150,7 +150,7 @@ typedef struct sigaltstack {
#ifdef __KERNEL__
#include <asm/sigcontext.h>
-#ifndef __uClinux__
+#ifndef CONFIG_CPU_HAS_NO_BITFIELDS
#define __HAVE_ARCH_SIG_BITOPS
static inline void sigaddset(sigset_t *set, int _sig)
@@ -199,15 +199,14 @@ static inline int sigfindinword(unsigned long word)
return word ^ 31;
}
-struct pt_regs;
-extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
+#endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */
-#else
-
-#undef __HAVE_ARCH_SIG_BITOPS
+#ifdef __uClinux__
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
+#else
+struct pt_regs;
+extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
#endif /* __uClinux__ */
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
#endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/system.h b/arch/m68k/include/asm/system.h
index ccea925ff4f5..47b01f4726bc 100644
--- a/arch/m68k/include/asm/system.h
+++ b/arch/m68k/include/asm/system.h
@@ -1,5 +1,193 @@
-#ifdef __uClinux__
-#include "system_no.h"
+#ifndef _M68K_SYSTEM_H
+#define _M68K_SYSTEM_H
+
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+#include <asm/segment.h>
+#include <asm/entry.h>
+
+#ifdef __KERNEL__
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing. This
+ * also clears the TS-flag if the task we switched to has used the
+ * math co-processor latest.
+ */
+/*
+ * switch_to() saves the extra registers, that are not saved
+ * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
+ * a0-a1. Some of these are used by schedule() and its predecessors
+ * and so we might get see unexpected behaviors when a task returns
+ * with unexpected register values.
+ *
+ * syscall stores these registers itself and none of them are used
+ * by syscall after the function in the syscall has been called.
+ *
+ * Beware that resume now expects *next to be in d1 and the offset of
+ * tss to be in a1. This saves a few instructions as we no longer have
+ * to push them onto the stack and read them back right after.
+ *
+ * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
+ *
+ * Changed 96/09/19 by Andreas Schwab
+ * pass prev in a0, next in a1
+ */
+asmlinkage void resume(void);
+#define switch_to(prev,next,last) do { \
+ register void *_prev __asm__ ("a0") = (prev); \
+ register void *_next __asm__ ("a1") = (next); \
+ register void *_last __asm__ ("d1"); \
+ __asm__ __volatile__("jbsr resume" \
+ : "=a" (_prev), "=a" (_next), "=d" (_last) \
+ : "0" (_prev), "1" (_next) \
+ : "d0", "d2", "d3", "d4", "d5"); \
+ (last) = _last; \
+} while (0)
+
+
+/*
+ * Force strict CPU ordering.
+ * Not really required on m68k...
+ */
+#define nop() do { asm volatile ("nop"); barrier(); } while (0)
+#define mb() barrier()
+#define rmb() barrier()
+#define wmb() barrier()
+#define read_barrier_depends() ((void)0)
+#define set_mb(var, value) ({ (var) = (value); wmb(); })
+
+#define smp_mb() barrier()
+#define smp_rmb() barrier()
+#define smp_wmb() barrier()
+#define smp_read_barrier_depends() ((void)0)
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+#ifndef CONFIG_RMW_INSNS
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+ unsigned long flags, tmp;
+
+ local_irq_save(flags);
+
+ switch (size) {
+ case 1:
+ tmp = *(u8 *)ptr;
+ *(u8 *)ptr = x;
+ x = tmp;
+ break;
+ case 2:
+ tmp = *(u16 *)ptr;
+ *(u16 *)ptr = x;
+ x = tmp;
+ break;
+ case 4:
+ tmp = *(u32 *)ptr;
+ *(u32 *)ptr = x;
+ x = tmp;
+ break;
+ default:
+ BUG();
+ }
+
+ local_irq_restore(flags);
+ return x;
+}
#else
-#include "system_mm.h"
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__
+ ("moveb %2,%0\n\t"
+ "1:\n\t"
+ "casb %0,%1,%2\n\t"
+ "jne 1b"
+ : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+ break;
+ case 2:
+ __asm__ __volatile__
+ ("movew %2,%0\n\t"
+ "1:\n\t"
+ "casw %0,%1,%2\n\t"
+ "jne 1b"
+ : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+ break;
+ case 4:
+ __asm__ __volatile__
+ ("movel %2,%0\n\t"
+ "1:\n\t"
+ "casl %0,%1,%2\n\t"
+ "jne 1b"
+ : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+ break;
+ }
+ return x;
+}
#endif
+
+#include <asm-generic/cmpxchg-local.h>
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+/*
+ * 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.
+ */
+#ifdef CONFIG_RMW_INSNS
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
+ unsigned long new, int size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__ ("casb %0,%2,%1"
+ : "=d" (old), "=m" (*(char *)p)
+ : "d" (new), "0" (old), "m" (*(char *)p));
+ break;
+ case 2:
+ __asm__ __volatile__ ("casw %0,%2,%1"
+ : "=d" (old), "=m" (*(short *)p)
+ : "d" (new), "0" (old), "m" (*(short *)p));
+ break;
+ case 4:
+ __asm__ __volatile__ ("casl %0,%2,%1"
+ : "=d" (old), "=m" (*(int *)p)
+ : "d" (new), "0" (old), "m" (*(int *)p));
+ break;
+ }
+ return old;
+}
+
+#define cmpxchg(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
+ (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
+ (unsigned long)(n), sizeof(*(ptr))))
+#else
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+ (unsigned long)(n), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif
+
+#define arch_align_stack(x) (x)
+
+#endif /* __KERNEL__ */
+
+#endif /* _M68K_SYSTEM_H */
diff --git a/arch/m68k/include/asm/system_mm.h b/arch/m68k/include/asm/system_mm.h
deleted file mode 100644
index 47b01f4726bc..000000000000
--- a/arch/m68k/include/asm/system_mm.h
+++ /dev/null
@@ -1,193 +0,0 @@
-#ifndef _M68K_SYSTEM_H
-#define _M68K_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-#include <asm/segment.h>
-#include <asm/entry.h>
-
-#ifdef __KERNEL__
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing. This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1
- */
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) do { \
- register void *_prev __asm__ ("a0") = (prev); \
- register void *_next __asm__ ("a1") = (next); \
- register void *_last __asm__ ("d1"); \
- __asm__ __volatile__("jbsr resume" \
- : "=a" (_prev), "=a" (_next), "=d" (_last) \
- : "0" (_prev), "1" (_next) \
- : "d0", "d2", "d3", "d4", "d5"); \
- (last) = _last; \
-} while (0)
-
-
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
-#define nop() do { asm volatile ("nop"); barrier(); } while (0)
-#define mb() barrier()
-#define rmb() barrier()
-#define wmb() barrier()
-#define read_barrier_depends() ((void)0)
-#define set_mb(var, value) ({ (var) = (value); wmb(); })
-
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() ((void)0)
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-#ifndef CONFIG_RMW_INSNS
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
- unsigned long flags, tmp;
-
- local_irq_save(flags);
-
- switch (size) {
- case 1:
- tmp = *(u8 *)ptr;
- *(u8 *)ptr = x;
- x = tmp;
- break;
- case 2:
- tmp = *(u16 *)ptr;
- *(u16 *)ptr = x;
- x = tmp;
- break;
- case 4:
- tmp = *(u32 *)ptr;
- *(u32 *)ptr = x;
- x = tmp;
- break;
- default:
- BUG();
- }
-
- local_irq_restore(flags);
- return x;
-}
-#else
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
- switch (size) {
- case 1:
- __asm__ __volatile__
- ("moveb %2,%0\n\t"
- "1:\n\t"
- "casb %0,%1,%2\n\t"
- "jne 1b"
- : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 2:
- __asm__ __volatile__
- ("movew %2,%0\n\t"
- "1:\n\t"
- "casw %0,%1,%2\n\t"
- "jne 1b"
- : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 4:
- __asm__ __volatile__
- ("movel %2,%0\n\t"
- "1:\n\t"
- "casl %0,%1,%2\n\t"
- "jne 1b"
- : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- }
- return x;
-}
-#endif
-
-#include <asm-generic/cmpxchg-local.h>
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-/*
- * 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.
- */
-#ifdef CONFIG_RMW_INSNS
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
- unsigned long new, int size)
-{
- switch (size) {
- case 1:
- __asm__ __volatile__ ("casb %0,%2,%1"
- : "=d" (old), "=m" (*(char *)p)
- : "d" (new), "0" (old), "m" (*(char *)p));
- break;
- case 2:
- __asm__ __volatile__ ("casw %0,%2,%1"
- : "=d" (old), "=m" (*(short *)p)
- : "d" (new), "0" (old), "m" (*(short *)p));
- break;
- case 4:
- __asm__ __volatile__ ("casl %0,%2,%1"
- : "=d" (old), "=m" (*(int *)p)
- : "d" (new), "0" (old), "m" (*(int *)p));
- break;
- }
- return old;
-}
-
-#define cmpxchg(ptr, o, n) \
- ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
- (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg_local(ptr, o, n) \
- ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
- (unsigned long)(n), sizeof(*(ptr))))
-#else
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n) \
- ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
- (unsigned long)(n), sizeof(*(ptr))))
-
-#include <asm-generic/cmpxchg.h>
-
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_SYSTEM_H */
diff --git a/arch/m68k/include/asm/system_no.h b/arch/m68k/include/asm/system_no.h
deleted file mode 100644
index 6fe9f93bc3ff..000000000000
--- a/arch/m68k/include/asm/system_no.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifndef _M68KNOMMU_SYSTEM_H
-#define _M68KNOMMU_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-#include <asm/segment.h>
-#include <asm/entry.h>
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing. This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1, offset of tss in d1, and whether
- * the mm structures are shared in d2 (to avoid atc flushing).
- */
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) \
-{ \
- void *_last; \
- __asm__ __volatile__( \
- "movel %1, %%a0\n\t" \
- "movel %2, %%a1\n\t" \
- "jbsr resume\n\t" \
- "movel %%d1, %0\n\t" \
- : "=d" (_last) \
- : "d" (prev), "d" (next) \
- : "cc", "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1"); \
- (last) = _last; \
-}
-
-#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
-
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
-#define nop() asm volatile ("nop"::)
-#define mb() asm volatile ("" : : :"memory")
-#define rmb() asm volatile ("" : : :"memory")
-#define wmb() asm volatile ("" : : :"memory")
-#define set_mb(var, value) ({ (var) = (value); wmb(); })
-
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while(0)
-
-#define read_barrier_depends() ((void)0)
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-#ifndef CONFIG_RMW_INSNS
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
- unsigned long tmp, flags;
-
- local_irq_save(flags);
-
- switch (size) {
- case 1:
- __asm__ __volatile__
- ("moveb %2,%0\n\t"
- "moveb %1,%2"
- : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 2:
- __asm__ __volatile__
- ("movew %2,%0\n\t"
- "movew %1,%2"
- : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 4:
- __asm__ __volatile__
- ("movel %2,%0\n\t"
- "movel %1,%2"
- : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- }
- local_irq_restore(flags);
- return tmp;
-}
-#else
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
- switch (size) {
- case 1:
- __asm__ __volatile__
- ("moveb %2,%0\n\t"
- "1:\n\t"
- "casb %0,%1,%2\n\t"
- "jne 1b"
- : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 2:
- __asm__ __volatile__
- ("movew %2,%0\n\t"
- "1:\n\t"
- "casw %0,%1,%2\n\t"
- "jne 1b"
- : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 4:
- __asm__ __volatile__
- ("movel %2,%0\n\t"
- "1:\n\t"
- "casl %0,%1,%2\n\t"
- "jne 1b"
- : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
- break;
- }
- return x;
-}
-#endif
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n) \
- ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
- (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#include <asm-generic/cmpxchg.h>
-
-#define arch_align_stack(x) (x)
-
-
-#endif /* _M68KNOMMU_SYSTEM_H */
diff --git a/arch/m68k/include/asm/traps.h b/arch/m68k/include/asm/traps.h
index 0bffb17d5db7..151068f64f44 100644
--- a/arch/m68k/include/asm/traps.h
+++ b/arch/m68k/include/asm/traps.h
@@ -22,7 +22,6 @@ extern e_vector vectors[];
asmlinkage void auto_inthandler(void);
asmlinkage void user_inthandler(void);
asmlinkage void bad_inthandler(void);
-extern void init_vectors(void);
#endif
diff --git a/arch/m68k/kernel/irq.c b/arch/m68k/kernel/irq.c
index 544b8717d499..c73988cfa90f 100644
--- a/arch/m68k/kernel/irq.c
+++ b/arch/m68k/kernel/irq.c
@@ -28,3 +28,13 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
set_irq_regs(oldregs);
}
+
+
+/* The number of spurious interrupts */
+atomic_t irq_err_count;
+
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+ seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+ return 0;
+}
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
index 7ea203ce6b1a..34849c4c6e3d 100644
--- a/arch/m68k/kernel/module.c
+++ b/arch/m68k/kernel/module.c
@@ -1,5 +1,129 @@
-#ifdef CONFIG_MMU
-#include "module_mm.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/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
#else
-#include "module_no.c"
+#define DEBUGP(fmt...)
+#endif
+
+#ifdef CONFIG_MODULES
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_68K_32:
+ /* We add the value into the location given */
+ *location += sym->st_value;
+ break;
+ case R_68K_PC32:
+ /* Add the value, subtract its postition */
+ *location += sym->st_value - (uint32_t)location;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+
+ DEBUGP("Applying relocate_add section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_68K_32:
+ /* We add the value into the location given */
+ *location = rel[i].r_addend + sym->st_value;
+ break;
+ case R_68K_PC32:
+ /* Add the value, subtract its postition */
+ *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *mod)
+{
+ module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
+ return 0;
+}
+
+#endif /* CONFIG_MODULES */
+
+void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+ struct m68k_fixup_info *end)
+{
+#ifdef CONFIG_MMU
+ struct m68k_fixup_info *fixup;
+
+ for (fixup = start; fixup < end; fixup++) {
+ switch (fixup->type) {
+ case m68k_fixup_memoffset:
+ *(u32 *)fixup->addr = m68k_memoffset;
+ break;
+ case m68k_fixup_vnode_shift:
+ *(u16 *)fixup->addr += m68k_virt_to_node_shift;
+ break;
+ }
+ }
#endif
+}
diff --git a/arch/m68k/kernel/module_mm.c b/arch/m68k/kernel/module_mm.c
deleted file mode 100644
index cd6bcb1c957e..000000000000
--- a/arch/m68k/kernel/module_mm.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-#ifdef CONFIG_MODULES
-
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- unsigned int i;
- Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
- Elf32_Sym *sym;
- uint32_t *location;
-
- DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
- /* This is where to make the change */
- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
- + rel[i].r_offset;
- /* This is the symbol it is referring to. Note that all
- undefined symbols have been resolved. */
- sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
- + ELF32_R_SYM(rel[i].r_info);
-
- switch (ELF32_R_TYPE(rel[i].r_info)) {
- case R_68K_32:
- /* We add the value into the location given */
- *location += sym->st_value;
- break;
- case R_68K_PC32:
- /* Add the value, subtract its postition */
- *location += sym->st_value - (uint32_t)location;
- break;
- default:
- printk(KERN_ERR "module %s: Unknown relocation: %u\n",
- me->name, ELF32_R_TYPE(rel[i].r_info));
- return -ENOEXEC;
- }
- }
- return 0;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- unsigned int i;
- Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
- Elf32_Sym *sym;
- uint32_t *location;
-
- DEBUGP("Applying relocate_add section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
- /* This is where to make the change */
- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
- + rel[i].r_offset;
- /* This is the symbol it is referring to. Note that all
- undefined symbols have been resolved. */
- sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
- + ELF32_R_SYM(rel[i].r_info);
-
- switch (ELF32_R_TYPE(rel[i].r_info)) {
- case R_68K_32:
- /* We add the value into the location given */
- *location = rel[i].r_addend + sym->st_value;
- break;
- case R_68K_PC32:
- /* Add the value, subtract its postition */
- *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
- break;
- default:
- printk(KERN_ERR "module %s: Unknown relocation: %u\n",
- me->name, ELF32_R_TYPE(rel[i].r_info));
- return -ENOEXEC;
- }
- }
- return 0;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *mod)
-{
- module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
-
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
-
-#endif /* CONFIG_MODULES */
-
-void module_fixup(struct module *mod, struct m68k_fixup_info *start,
- struct m68k_fixup_info *end)
-{
- struct m68k_fixup_info *fixup;
-
- for (fixup = start; fixup < end; fixup++) {
- switch (fixup->type) {
- case m68k_fixup_memoffset:
- *(u32 *)fixup->addr = m68k_memoffset;
- break;
- case m68k_fixup_vnode_shift:
- *(u16 *)fixup->addr += m68k_virt_to_node_shift;
- break;
- }
- }
-}
diff --git a/arch/m68k/kernel/module_no.c b/arch/m68k/kernel/module_no.c
deleted file mode 100644
index d11ffae7956a..000000000000
--- a/arch/m68k/kernel/module_no.c
+++ /dev/null
@@ -1,126 +0,0 @@
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- unsigned int i;
- Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
- Elf32_Sym *sym;
- uint32_t *location;
-
- DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
- /* This is where to make the change */
- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
- + rel[i].r_offset;
- /* This is the symbol it is referring to. Note that all
- undefined symbols have been resolved. */
- sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
- + ELF32_R_SYM(rel[i].r_info);
-
- switch (ELF32_R_TYPE(rel[i].r_info)) {
- case R_68K_32:
- /* We add the value into the location given */
- *location += sym->st_value;
- break;
- case R_68K_PC32:
- /* Add the value, subtract its postition */
- *location += sym->st_value - (uint32_t)location;
- break;
- default:
- printk(KERN_ERR "module %s: Unknown relocation: %u\n",
- me->name, ELF32_R_TYPE(rel[i].r_info));
- return -ENOEXEC;
- }
- }
- return 0;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- unsigned int i;
- Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
- Elf32_Sym *sym;
- uint32_t *location;
-
- DEBUGP("Applying relocate_add section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
- /* This is where to make the change */
- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
- + rel[i].r_offset;
- /* This is the symbol it is referring to. Note that all
- undefined symbols have been resolved. */
- sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
- + ELF32_R_SYM(rel[i].r_info);
-
- switch (ELF32_R_TYPE(rel[i].r_info)) {
- case R_68K_32:
- /* We add the value into the location given */
- *location = rel[i].r_addend + sym->st_value;
- break;
- case R_68K_PC32:
- /* Add the value, subtract its postition */
- *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
- break;
- default:
- printk(KERN_ERR "module %s: Unknown relocation: %u\n",
- me->name, ELF32_R_TYPE(rel[i].r_info));
- return -ENOEXEC;
- }
- }
- return 0;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c
index c2a1fc23dd75..1bc223aa07ec 100644
--- a/arch/m68k/kernel/process_mm.c
+++ b/arch/m68k/kernel/process_mm.c
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(kernel_thread);
void flush_thread(void)
{
unsigned long zero = 0;
- set_fs(USER_DS);
+
current->thread.fs = __USER_DS;
if (!FPU_IS_EMU)
asm volatile (".chip 68k/68881\n\t"
diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c
index 9b86ad11c68e..69c1803fcf1b 100644
--- a/arch/m68k/kernel/process_no.c
+++ b/arch/m68k/kernel/process_no.c
@@ -158,7 +158,7 @@ void flush_thread(void)
#ifdef CONFIG_FPU
unsigned long zero = 0;
#endif
- set_fs(USER_DS);
+
current->thread.fs = __USER_DS;
#ifdef CONFIG_FPU
if (!FPU_IS_EMU)
diff --git a/arch/m68k/kernel/traps_no.c b/arch/m68k/kernel/traps_no.c
index a768008dfd06..e67b8c806959 100644
--- a/arch/m68k/kernel/traps_no.c
+++ b/arch/m68k/kernel/traps_no.c
@@ -60,10 +60,6 @@ static char const * const vec_names[] = {
"MMU CONFIGURATION ERROR"
};
-void __init trap_init(void)
-{
-}
-
void die_if_kernel(char *str, struct pt_regs *fp, int nr)
{
if (!(fp->sr & PS_S))
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index df421e501436..1a1bd9067e90 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -9,6 +9,6 @@ lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
ifdef CONFIG_MMU
lib-y += string.o uaccess.o checksum_mm.o
else
-lib-y += mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o delay.o checksum_no.o
+lib-y += mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o checksum_no.o
endif
diff --git a/arch/m68k/lib/delay.c b/arch/m68k/lib/delay.c
deleted file mode 100644
index 5bd5472d38a0..000000000000
--- a/arch/m68k/lib/delay.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/m68knommu/lib/delay.c
- *
- * (C) Copyright 2004, Greg Ungerer <gerg@snapgear.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <asm/param.h>
-#include <asm/delay.h>
-
-EXPORT_SYMBOL(udelay);
-
-void udelay(unsigned long usecs)
-{
- _udelay(usecs);
-}
-
diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c
index 7cbd7bd1f8bc..50cd12cf28d9 100644
--- a/arch/m68k/mm/init_no.c
+++ b/arch/m68k/mm/init_no.c
@@ -42,7 +42,7 @@
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
-unsigned long empty_zero_page;
+void *empty_zero_page;
extern unsigned long memory_start;
extern unsigned long memory_end;
@@ -62,8 +62,8 @@ void __init paging_init(void)
unsigned long end_mem = memory_end & PAGE_MASK;
unsigned long zones_size[MAX_NR_ZONES] = {0, };
- empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
- memset((void *)empty_zero_page, 0, PAGE_SIZE);
+ empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
+ memset(empty_zero_page, 0, PAGE_SIZE);
/*
* Set up SFC/DFC registers (user data space).
@@ -120,7 +120,8 @@ void free_initrd_mem(unsigned long start, unsigned long end)
totalram_pages++;
pages++;
}
- printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024));
+ pr_notice("Freeing initrd memory: %luk freed\n",
+ pages * (PAGE_SIZE / 1024));
}
#endif
@@ -141,7 +142,7 @@ void free_initmem(void)
free_page(addr);
totalram_pages++;
}
- printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
+ 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))),
(int)(addr - PAGE_SIZE));
diff --git a/arch/m68k/platform/5206/config.c b/arch/m68k/platform/5206/config.c
index 9c335465e66d..6fa3f800277a 100644
--- a/arch/m68k/platform/5206/config.c
+++ b/arch/m68k/platform/5206/config.c
@@ -98,6 +98,12 @@ void m5206_cpu_reset(void)
void __init config_BSP(char *commandp, int size)
{
+#if defined(CONFIG_NETtel)
+ /* Copy command line from FLASH to local buffer... */
+ memcpy(commandp, (char *) 0xf0004000, size);
+ commandp[size-1] = 0;
+#endif /* CONFIG_NETtel */
+
mach_reset = m5206_cpu_reset;
m5206_timers_init();
m5206_uarts_init();
diff --git a/arch/m68k/platform/5206e/Makefile b/arch/m68k/platform/5206e/Makefile
deleted file mode 100644
index b5db05625cfa..000000000000
--- a/arch/m68k/platform/5206e/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff --git a/arch/m68k/platform/5206e/config.c b/arch/m68k/platform/5206e/config.c
deleted file mode 100644
index 942397984c66..000000000000
--- a/arch/m68k/platform/5206e/config.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/***************************************************************************/
-
-/*
- * linux/arch/m68knommu/platform/5206e/config.c
- *
- * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfdma.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5206e_uart_platform[] = {
- {
- .mapbase = MCF_MBAR + MCFUART_BASE1,
- .irq = 73,
- },
- {
- .mapbase = MCF_MBAR + MCFUART_BASE2,
- .irq = 74,
- },
- { },
-};
-
-static struct platform_device m5206e_uart = {
- .name = "mcfuart",
- .id = 0,
- .dev.platform_data = m5206e_uart_platform,
-};
-
-static struct platform_device *m5206e_devices[] __initdata = {
- &m5206e_uart,
-};
-
-/***************************************************************************/
-
-static void __init m5206e_uart_init_line(int line, int irq)
-{
- if (line == 0) {
- writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
- writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
- mcf_mapirq2imr(irq, MCFINTC_UART0);
- } else if (line == 1) {
- writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
- writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
- mcf_mapirq2imr(irq, MCFINTC_UART1);
- }
-}
-
-static void __init m5206e_uarts_init(void)
-{
- const int nrlines = ARRAY_SIZE(m5206e_uart_platform);
- int line;
-
- for (line = 0; (line < nrlines); line++)
- m5206e_uart_init_line(line, m5206e_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m5206e_timers_init(void)
-{
- /* Timer1 is always used as system timer */
- writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
- MCF_MBAR + MCFSIM_TIMER1ICR);
- mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
-
-#ifdef CONFIG_HIGHPROFILE
- /* Timer2 is to be used as a high speed profile timer */
- writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
- MCF_MBAR + MCFSIM_TIMER2ICR);
- mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
-#endif
-}
-
-/***************************************************************************/
-
-void m5206e_cpu_reset(void)
-{
- local_irq_disable();
- /* Set watchdog to soft reset, and enabled */
- __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
- for (;;)
- /* wait for watchdog to timeout */;
-}
-
-/***************************************************************************/
-
-void __init config_BSP(char *commandp, int size)
-{
-#if defined(CONFIG_NETtel)
- /* Copy command line from FLASH to local buffer... */
- memcpy(commandp, (char *) 0xf0004000, size);
- commandp[size-1] = 0;
-#endif /* CONFIG_NETtel */
-
- mach_reset = m5206e_cpu_reset;
- m5206e_timers_init();
- m5206e_uarts_init();
-
- /* Only support the external interrupts on their primary level */
- mcf_mapirq2imr(25, MCFINTC_EINT1);
- mcf_mapirq2imr(28, MCFINTC_EINT4);
- mcf_mapirq2imr(31, MCFINTC_EINT7);
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
- platform_add_devices(m5206e_devices, ARRAY_SIZE(m5206e_devices));
- return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff --git a/arch/m68k/platform/5206e/gpio.c b/arch/m68k/platform/5206e/gpio.c
deleted file mode 100644
index b9ab4a120f28..000000000000
--- a/arch/m68k/platform/5206e/gpio.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PP",
- .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,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFSIM_PADDR,
- .podr = (void __iomem *) MCFSIM_PADAT,
- .ppdr = (void __iomem *) MCFSIM_PADAT,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/5272/intc.c b/arch/m68k/platform/5272/intc.c
index 7e715dfe2819..7160e618b0a9 100644
--- a/arch/m68k/platform/5272/intc.c
+++ b/arch/m68k/platform/5272/intc.c
@@ -162,8 +162,6 @@ void __init init_IRQ(void)
{
int irq, edge;
- init_vectors();
-
/* Mask all interrupt sources */
writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S
index f68dce766c0a..293e1eba9acc 100644
--- a/arch/m68k/platform/68328/entry.S
+++ b/arch/m68k/platform/68328/entry.S
@@ -236,27 +236,26 @@ ret_from_interrupt:
* Handler for uninitialized and spurious interrupts.
*/
ENTRY(bad_interrupt)
- addql #1,num_spurious
+ addql #1,irq_err_count
rte
/*
* Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
+ * in a0, next (the new task) is in a1, so don't change these
* registers until their contents are no longer needed.
*/
ENTRY(resume)
movel %a0,%d1 /* save prev thread in d1 */
movew %sr,%a0@(TASK_THREAD+THREAD_SR) /* save sr */
- movel %usp,%a2 /* save usp */
- movel %a2,%a0@(TASK_THREAD+THREAD_USP)
-
SAVE_SWITCH_STACK
movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
+ movel %usp,%a3 /* save usp */
+ movel %a3,%a0@(TASK_THREAD+THREAD_USP)
+
+ movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */
+ movel %a3,%usp
movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
RESTORE_SWITCH_STACK
-
- movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
- movel %a0,%usp
movew %a1@(TASK_THREAD+THREAD_SR),%sr /* restore thread status reg */
rts
diff --git a/arch/m68k/platform/68328/ints.c b/arch/m68k/platform/68328/ints.c
index a90288cf7446..4bd456531f91 100644
--- a/arch/m68k/platform/68328/ints.c
+++ b/arch/m68k/platform/68328/ints.c
@@ -70,9 +70,6 @@ asmlinkage irqreturn_t inthandler7(void);
extern e_vector *_ramvec;
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
/* The 68k family did not have a good way to determine the source
* of interrupts until later in the family. The EC000 core does
* not provide the vector number on the stack, we vector everything
@@ -155,7 +152,7 @@ static struct irq_chip intc_irq_chip = {
* This function should be called during kernel startup to initialize
* the machine vector table.
*/
-void __init init_IRQ(void)
+void __init trap_init(void)
{
int i;
@@ -172,6 +169,11 @@ void __init init_IRQ(void)
_ramvec[69] = (e_vector) inthandler5;
_ramvec[70] = (e_vector) inthandler6;
_ramvec[71] = (e_vector) inthandler7;
+}
+
+void __init init_IRQ(void)
+{
+ int i;
IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S
index a07b14feed92..abbb89672ea0 100644
--- a/arch/m68k/platform/68360/entry.S
+++ b/arch/m68k/platform/68360/entry.S
@@ -157,27 +157,26 @@ ret_from_interrupt:
* Handler for uninitialized and spurious interrupts.
*/
bad_interrupt:
- addql #1,num_spurious
+ addql #1,irq_err_count
rte
/*
* Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
+ * in a0, next (the new task) is in a1, so don't change these
* registers until their contents are no longer needed.
*/
ENTRY(resume)
movel %a0,%d1 /* save prev thread in d1 */
movew %sr,%a0@(TASK_THREAD+THREAD_SR) /* save sr */
- movel %usp,%a2 /* save usp */
- movel %a2,%a0@(TASK_THREAD+THREAD_USP)
-
SAVE_SWITCH_STACK
movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
+ movel %usp,%a3 /* save usp */
+ movel %a3,%a0@(TASK_THREAD+THREAD_USP)
+
+ movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */
+ movel %a3,%usp
movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
RESTORE_SWITCH_STACK
-
- movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
- movel %a0,%usp
movew %a1@(TASK_THREAD+THREAD_SR),%sr /* restore thread status reg */
rts
diff --git a/arch/m68k/platform/68360/ints.c b/arch/m68k/platform/68360/ints.c
index 4af0f4e30f74..7b40202d9638 100644
--- a/arch/m68k/platform/68360/ints.c
+++ b/arch/m68k/platform/68360/ints.c
@@ -34,9 +34,6 @@ asmlinkage void inthandler(void);
extern void *_ramvec[];
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
static void intc_irq_unmask(struct irq_data *d)
{
pquicc->intr_cimr |= (1 << d->irq);
@@ -63,9 +60,8 @@ static struct irq_chip intc_irq_chip = {
* This function should be called during kernel startup to initialize
* the vector table.
*/
-void init_IRQ(void)
+void __init trap_init(void)
{
- int i;
int vba = (CPM_VECTOR_BASE<<4);
/* set up the vectors */
@@ -130,6 +126,11 @@ void init_IRQ(void)
/* turn off all CPM interrupts */
pquicc->intr_cimr = 0x00000000;
+}
+
+void init_IRQ(void)
+{
+ int i;
for (i = 0; (i < NR_IRQS); i++) {
irq_set_chip(i, &intc_irq_chip);
diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S
index 27c2b001161e..bd27242c2f43 100644
--- a/arch/m68k/platform/coldfire/entry.S
+++ b/arch/m68k/platform/coldfire/entry.S
@@ -182,21 +182,23 @@ ENTRY(inthandler)
/*
* Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
+ * in a0, next (the new task) is in a1, so don't change these
* registers until their contents are no longer needed.
- * This is always called in supervisor mode, so don't bother to save
- * and restore sr; user's process sr is actually in the stack.
*/
ENTRY(resume)
- movel %a0, %d1 /* get prev thread in d1 */
- RDUSP
- movel %a2,%a0@(TASK_THREAD+THREAD_USP)
-
+ movew %sr,%d1 /* save current status */
+ movew %d1,%a0@(TASK_THREAD+THREAD_SR)
+ movel %a0,%d1 /* get prev thread in d1 */
SAVE_SWITCH_STACK
movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
- movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
+ RDUSP /* movel %usp,%a3 */
+ movel %a3,%a0@(TASK_THREAD+THREAD_USP) /* save thread user stack */
+
+ movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore thread user stack */
+ WRUSP /* movel %a3,%usp */
+ movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new kernel stack */
+ movew %a1@(TASK_THREAD+THREAD_SR),%d7 /* restore new status */
+ movew %d7,%sr
RESTORE_SWITCH_STACK
-
- movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
- WRUSP
rts
+
diff --git a/arch/m68k/platform/coldfire/intc-2.c b/arch/m68k/platform/coldfire/intc-2.c
index 74b55cfbc3cb..995093357c59 100644
--- a/arch/m68k/platform/coldfire/intc-2.c
+++ b/arch/m68k/platform/coldfire/intc-2.c
@@ -194,8 +194,6 @@ void __init init_IRQ(void)
{
int irq;
- init_vectors();
-
/* Mask all interrupt sources */
__raw_writel(0x1, MCFICM_INTC0 + MCFINTC_IMRL);
#ifdef MCFICM_INTC1
diff --git a/arch/m68k/platform/coldfire/intc-simr.c b/arch/m68k/platform/coldfire/intc-simr.c
index d6a4d9d53e42..650d52e2927e 100644
--- a/arch/m68k/platform/coldfire/intc-simr.c
+++ b/arch/m68k/platform/coldfire/intc-simr.c
@@ -171,8 +171,6 @@ void __init init_IRQ(void)
{
int irq, eirq;
- init_vectors();
-
/* Mask all interrupt sources */
__raw_writeb(0xff, MCFINTC0_SIMR);
if (MCFINTC1_SIMR)
diff --git a/arch/m68k/platform/coldfire/intc.c b/arch/m68k/platform/coldfire/intc.c
index 0bbb414856eb..5c0c150b4067 100644
--- a/arch/m68k/platform/coldfire/intc.c
+++ b/arch/m68k/platform/coldfire/intc.c
@@ -139,7 +139,6 @@ void __init init_IRQ(void)
{
int irq;
- init_vectors();
mcf_maskimr(0xffffffff);
for (irq = 0; (irq < NR_IRQS); irq++) {
diff --git a/arch/m68k/platform/coldfire/vectors.c b/arch/m68k/platform/coldfire/vectors.c
index a21d3f870b7a..3a7cc524ecd3 100644
--- a/arch/m68k/platform/coldfire/vectors.c
+++ b/arch/m68k/platform/coldfire/vectors.c
@@ -35,21 +35,13 @@ asmlinkage void dbginterrupt_c(struct frame *fp)
extern e_vector *_ramvec;
-void set_evector(int vecnum, void (*handler)(void))
-{
- if (vecnum >= 0 && vecnum <= 255)
- _ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
/* Assembler routines */
asmlinkage void buserr(void);
asmlinkage void trap(void);
asmlinkage void system_call(void);
asmlinkage void inthandler(void);
-void __init init_vectors(void)
+void __init trap_init(void)
{
int i;
diff --git a/arch/microblaze/include/asm/mmu_context_mm.h b/arch/microblaze/include/asm/mmu_context_mm.h
index 3e5c254e8d1c..d68647746448 100644
--- a/arch/microblaze/include/asm/mmu_context_mm.h
+++ b/arch/microblaze/include/asm/mmu_context_mm.h
@@ -11,7 +11,7 @@
#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
#define _ASM_MICROBLAZE_MMU_CONTEXT_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/bitops.h>
#include <asm/mmu.h>
#include <asm-generic/mm_hooks.h>
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h
index 746df91e5796..32764cd077c6 100644
--- a/arch/microblaze/include/asm/pci-bridge.h
+++ b/arch/microblaze/include/asm/pci-bridge.h
@@ -10,31 +10,19 @@
#include <linux/pci.h>
#include <linux/list.h>
#include <linux/ioport.h>
+#include <asm-generic/pci-bridge.h>
struct device_node;
-enum {
- /* Force re-assigning all resources (ignore firmware
- * setup completely)
- */
- PCI_REASSIGN_ALL_RSRC = 0x00000001,
-
- /* Re-assign all bus numbers */
- PCI_REASSIGN_ALL_BUS = 0x00000002,
-
- /* Do not try to assign, just use existing setup */
- PCI_PROBE_ONLY = 0x00000004,
-
- /* Don't bother with ISA alignment unless the bridge has
- * ISA forwarding enabled
- */
- PCI_CAN_SKIP_ISA_ALIGN = 0x00000008,
-
- /* Enable domain numbers in /proc */
- PCI_ENABLE_PROC_DOMAINS = 0x00000010,
- /* ... except for domain 0 */
- PCI_COMPAT_DOMAIN_0 = 0x00000020,
-};
+#ifdef CONFIG_PCI
+extern struct list_head hose_list;
+extern int pcibios_vaddr_is_ioport(void __iomem *address);
+#else
+static inline int pcibios_vaddr_is_ioport(void __iomem *address)
+{
+ return 0;
+}
+#endif
/*
* Structure of a PCI controller (host bridge)
@@ -110,16 +98,6 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
return bus->sysdata;
}
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
- struct pci_controller *host;
-
- if (bus->self)
- return pci_device_to_OF_node(bus->self);
- host = pci_bus_to_host(bus);
- return host ? host->dn : NULL;
-}
-
static inline int isa_vaddr_is_ioport(void __iomem *address)
{
/* No specific ISA handling on ppc32 at this stage, it
@@ -164,40 +142,5 @@ extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
extern void pcibios_free_controller(struct pci_controller *phb);
extern void pcibios_setup_phb_resources(struct pci_controller *hose);
-#ifdef CONFIG_PCI
-extern unsigned int pci_flags;
-
-static inline void pci_set_flags(int flags)
-{
- pci_flags = flags;
-}
-
-static inline void pci_add_flags(int flags)
-{
- pci_flags |= flags;
-}
-
-static inline int pci_has_flag(int flag)
-{
- return pci_flags & flag;
-}
-
-extern struct list_head hose_list;
-
-extern int pcibios_vaddr_is_ioport(void __iomem *address);
-#else
-static inline int pcibios_vaddr_is_ioport(void __iomem *address)
-{
- return 0;
-}
-
-static inline void pci_set_flags(int flags) { }
-static inline void pci_add_flags(int flags) { }
-static inline int pci_has_flag(int flag)
-{
- return 0;
-}
-#endif /* CONFIG_PCI */
-
#endif /* __KERNEL__ */
#endif /* _ASM_MICROBLAZE_PCI_BRIDGE_H */
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index ba65cf472544..1dd9d6b1e275 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -40,8 +40,7 @@ struct pci_dev;
* Set this to 1 if you want the kernel to re-assign all PCI
* bus numbers (don't do that on ppc64 yet !)
*/
-#define pcibios_assign_all_busses() \
- (pci_has_flag(PCI_REASSIGN_ALL_BUS))
+#define pcibios_assign_all_busses() 0
static inline void pcibios_set_master(struct pci_dev *dev)
{
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 34c4e8b27805..20c5e8e5121b 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -21,7 +21,7 @@
#include <linux/types.h>
#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define HAVE_ARCH_DEVTREE_FIXUPS
@@ -33,21 +33,6 @@ enum early_consoles {
extern int of_early_console(void *version);
-#ifdef CONFIG_PCI
-/*
- * PCI <-> OF matching functions
- * (XXX should these be here?)
- */
-struct pci_bus;
-struct pci_dev;
-extern int pci_device_from_OF_node(struct device_node *node,
- u8 *bus, u8 *devfn);
-extern struct device_node *pci_busdev_to_OF_node(struct pci_bus *bus,
- int devfn);
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);
-extern void pci_create_OF_bus_map(void);
-#endif
-
/*
* OF address retreival & translation
*/
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
index d9b66304d5dd..816bee64b196 100644
--- a/arch/microblaze/include/asm/ptrace.h
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -61,8 +61,6 @@ struct pt_regs {
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
-void show_regs(struct pt_regs *);
-
#else /* __KERNEL__ */
/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c
index 0e73f6606547..142426f631bb 100644
--- a/arch/microblaze/kernel/module.c
+++ b/arch/microblaze/kernel/module.c
@@ -18,37 +18,6 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
-void *module_alloc(unsigned long size)
-{
- void *ret;
- ret = (size == 0) ? NULL : vmalloc(size);
- pr_debug("module_alloc (%08lx@%08lx)\n", size, (unsigned long int)ret);
- return ret;
-}
-
-void module_free(struct module *module, void *region)
-{
- pr_debug("module_free(%s,%08lx)\n", module->name,
- (unsigned long)region);
- vfree(region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec, struct module *module)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
- module->name);
- return -ENOEXEC;
-}
-
int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
unsigned int symindex, unsigned int relsec, struct module *module)
{
@@ -155,7 +124,3 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
flush_dcache();
return 0;
}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/microblaze/pci/Makefile b/arch/microblaze/pci/Makefile
index 9889cc2e1294..d1114fbd4780 100644
--- a/arch/microblaze/pci/Makefile
+++ b/arch/microblaze/pci/Makefile
@@ -2,5 +2,5 @@
# Makefile
#
-obj-$(CONFIG_PCI) += pci_32.o pci-common.o indirect_pci.o iomap.o
+obj-$(CONFIG_PCI) += pci-common.o indirect_pci.o iomap.o
obj-$(CONFIG_PCI_XILINX) += xilinx_pci.o
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 53599067d2f9..4cfae20f1067 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -50,6 +50,11 @@ unsigned int pci_flags;
static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
+unsigned long isa_io_base;
+unsigned long pci_dram_offset;
+static int pci_bus_count;
+
+
void set_pci_dma_ops(struct dma_map_ops *dma_ops)
{
pci_dma_ops = dma_ops;
@@ -89,7 +94,7 @@ void pcibios_free_controller(struct pci_controller *phb)
static resource_size_t pcibios_io_size(const struct pci_controller *hose)
{
- return hose->io_resource.end - hose->io_resource.start + 1;
+ return resource_size(&hose->io_resource);
}
int pcibios_vaddr_is_ioport(void __iomem *address)
@@ -1558,6 +1563,112 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
(unsigned long)hose->io_base_virt - _IO_BASE);
}
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+ struct pci_controller *hose = bus->sysdata;
+
+ return of_node_get(hose->dn);
+}
+
+static void __devinit pcibios_scan_phb(struct pci_controller *hose)
+{
+ struct pci_bus *bus;
+ struct device_node *node = hose->dn;
+ unsigned long io_offset;
+ struct resource *res = &hose->io_resource;
+
+ pr_debug("PCI: Scanning PHB %s\n",
+ node ? node->full_name : "<NO NAME>");
+
+ /* Create an empty bus for the toplevel */
+ bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
+ if (bus == NULL) {
+ printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
+ hose->global_number);
+ return;
+ }
+ bus->secondary = hose->first_busno;
+ hose->bus = bus;
+
+ /* Fixup IO space offset */
+ io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ res->start = (res->start + io_offset) & 0xffffffffu;
+ res->end = (res->end + io_offset) & 0xffffffffu;
+
+ /* Wire up PHB bus resources */
+ pcibios_setup_phb_resources(hose);
+
+ /* Scan children */
+ hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+}
+
+static int __init pcibios_init(void)
+{
+ struct pci_controller *hose, *tmp;
+ int next_busno = 0;
+
+ printk(KERN_INFO "PCI: Probing PCI hardware\n");
+
+ /* Scan all of the recorded PCI controllers. */
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+ hose->last_busno = 0xff;
+ pcibios_scan_phb(hose);
+ printk(KERN_INFO "calling pci_bus_add_devices()\n");
+ pci_bus_add_devices(hose->bus);
+ if (next_busno <= hose->last_busno)
+ next_busno = hose->last_busno + 1;
+ }
+ pci_bus_count = next_busno;
+
+ /* Call common code to handle resource allocation */
+ pcibios_resource_survey();
+
+ return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+static struct pci_controller *pci_bus_to_hose(int bus)
+{
+ struct pci_controller *hose, *tmp;
+
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ if (bus >= hose->first_busno && bus <= hose->last_busno)
+ return hose;
+ return NULL;
+}
+
+/* Provide information on locations of various I/O regions in physical
+ * memory. Do this on a per-card basis so that we choose the right
+ * root bridge.
+ * Note that the returned IO or memory base is a physical address
+ */
+
+long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
+{
+ struct pci_controller *hose;
+ long result = -EOPNOTSUPP;
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return -ENODEV;
+
+ switch (which) {
+ case IOBASE_BRIDGE_NUMBER:
+ return (long)hose->first_busno;
+ case IOBASE_MEMORY:
+ return (long)hose->pci_mem_offset;
+ case IOBASE_IO:
+ return (long)hose->io_base_phys;
+ case IOBASE_ISA_IO:
+ return (long)isa_io_base;
+ case IOBASE_ISA_MEM:
+ return (long)isa_mem_base;
+ }
+
+ return result;
+}
+
/*
* Null PCI config access functions, for the case when we can't
* find a hose.
@@ -1626,3 +1737,4 @@ int early_find_capability(struct pci_controller *hose, int bus, int devfn,
{
return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap);
}
+
diff --git a/arch/microblaze/pci/pci_32.c b/arch/microblaze/pci/pci_32.c
deleted file mode 100644
index 92728a6cfd80..000000000000
--- a/arch/microblaze/pci/pci_32.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Common pmac/prep/chrp pci routines. -- Cort
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/list.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#undef DEBUG
-
-unsigned long isa_io_base;
-unsigned long pci_dram_offset;
-int pcibios_assign_bus_offset = 1;
-
-static u8 *pci_to_OF_bus_map;
-
-/* By default, we don't re-assign bus numbers. We do this only on
- * some pmacs
- */
-static int pci_assign_all_buses;
-
-static int pci_bus_count;
-
-/*
- * Functions below are used on OpenFirmware machines.
- */
-static void
-make_one_node_map(struct device_node *node, u8 pci_bus)
-{
- const int *bus_range;
- int len;
-
- if (pci_bus >= pci_bus_count)
- return;
- bus_range = of_get_property(node, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, "
- "assuming it starts at 0\n", node->full_name);
- pci_to_OF_bus_map[pci_bus] = 0;
- } else
- pci_to_OF_bus_map[pci_bus] = bus_range[0];
-
- for_each_child_of_node(node, node) {
- struct pci_dev *dev;
- const unsigned int *class_code, *reg;
-
- class_code = of_get_property(node, "class-code", NULL);
- if (!class_code ||
- ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
- continue;
- reg = of_get_property(node, "reg", NULL);
- if (!reg)
- continue;
- dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff));
- if (!dev || !dev->subordinate) {
- pci_dev_put(dev);
- continue;
- }
- make_one_node_map(node, dev->subordinate->number);
- pci_dev_put(dev);
- }
-}
-
-void
-pcibios_make_OF_bus_map(void)
-{
- int i;
- struct pci_controller *hose, *tmp;
- struct property *map_prop;
- struct device_node *dn;
-
- pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
- if (!pci_to_OF_bus_map) {
- printk(KERN_ERR "Can't allocate OF bus map !\n");
- return;
- }
-
- /* We fill the bus map with invalid values, that helps
- * debugging.
- */
- for (i = 0; i < pci_bus_count; i++)
- pci_to_OF_bus_map[i] = 0xff;
-
- /* For each hose, we begin searching bridges */
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- struct device_node *node = hose->dn;
-
- if (!node)
- continue;
- make_one_node_map(node, hose->first_busno);
- }
- dn = of_find_node_by_path("/");
- map_prop = of_find_property(dn, "pci-OF-bus-map", NULL);
- if (map_prop) {
- BUG_ON(pci_bus_count > map_prop->length);
- memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
- }
- of_node_put(dn);
-#ifdef DEBUG
- printk(KERN_INFO "PCI->OF bus map:\n");
- for (i = 0; i < pci_bus_count; i++) {
- if (pci_to_OF_bus_map[i] == 0xff)
- continue;
- printk(KERN_INFO "%d -> %d\n", i, pci_to_OF_bus_map[i]);
- }
-#endif
-}
-
-typedef int (*pci_OF_scan_iterator)(struct device_node *node, void *data);
-
-static struct device_node *scan_OF_pci_childs(struct device_node *parent,
- pci_OF_scan_iterator filter, void *data)
-{
- struct device_node *node;
- struct device_node *sub_node;
-
- for_each_child_of_node(parent, node) {
- const unsigned int *class_code;
-
- if (filter(node, data)) {
- of_node_put(node);
- return node;
- }
-
- /* For PCI<->PCI bridges or CardBus bridges, we go down
- * Note: some OFs create a parent node "multifunc-device" as
- * a fake root for all functions of a multi-function device,
- * we go down them as well.
- */
- class_code = of_get_property(node, "class-code", NULL);
- if ((!class_code ||
- ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
- strcmp(node->name, "multifunc-device"))
- continue;
- sub_node = scan_OF_pci_childs(node, filter, data);
- if (sub_node) {
- of_node_put(node);
- return sub_node;
- }
- }
- return NULL;
-}
-
-static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
- unsigned int devfn)
-{
- struct device_node *np, *cnp;
- const u32 *reg;
- unsigned int psize;
-
- for_each_child_of_node(parent, np) {
- reg = of_get_property(np, "reg", &psize);
- if (reg && psize >= 4 && ((reg[0] >> 8) & 0xff) == devfn)
- return np;
-
- /* Note: some OFs create a parent node "multifunc-device" as
- * a fake root for all functions of a multi-function device,
- * we go down them as well. */
- if (!strcmp(np->name, "multifunc-device")) {
- cnp = scan_OF_for_pci_dev(np, devfn);
- if (cnp)
- return cnp;
- }
- }
- return NULL;
-}
-
-
-static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
-{
- struct device_node *parent, *np;
-
- /* Are we a root bus ? */
- if (bus->self == NULL || bus->parent == NULL) {
- struct pci_controller *hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return NULL;
- return of_node_get(hose->dn);
- }
-
- /* not a root bus, we need to get our parent */
- parent = scan_OF_for_pci_bus(bus->parent);
- if (parent == NULL)
- return NULL;
-
- /* now iterate for children for a match */
- np = scan_OF_for_pci_dev(parent, bus->self->devfn);
- of_node_put(parent);
-
- return np;
-}
-
-/*
- * Scans the OF tree for a device node matching a PCI device
- */
-struct device_node *
-pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
-{
- struct device_node *parent, *np;
-
- pr_debug("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
- parent = scan_OF_for_pci_bus(bus);
- if (parent == NULL)
- return NULL;
- pr_debug(" parent is %s\n", parent ? parent->full_name : "<NULL>");
- np = scan_OF_for_pci_dev(parent, devfn);
- of_node_put(parent);
- pr_debug(" result is %s\n", np ? np->full_name : "<NULL>");
-
- /* XXX most callers don't release the returned node
- * mostly because ppc64 doesn't increase the refcount,
- * we need to fix that.
- */
- return np;
-}
-EXPORT_SYMBOL(pci_busdev_to_OF_node);
-
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
-{
- return pci_busdev_to_OF_node(dev->bus, dev->devfn);
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
-static int
-find_OF_pci_device_filter(struct device_node *node, void *data)
-{
- return ((void *)node == data);
-}
-
-/*
- * Returns the PCI device matching a given OF node
- */
-int
-pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
-{
- const unsigned int *reg;
- struct pci_controller *hose;
- struct pci_dev *dev = NULL;
-
- /* Make sure it's really a PCI device */
- hose = pci_find_hose_for_OF_device(node);
- if (!hose || !hose->dn)
- return -ENODEV;
- if (!scan_OF_pci_childs(hose->dn,
- find_OF_pci_device_filter, (void *)node))
- return -ENODEV;
- reg = of_get_property(node, "reg", NULL);
- if (!reg)
- return -ENODEV;
- *bus = (reg[0] >> 16) & 0xff;
- *devfn = ((reg[0] >> 8) & 0xff);
-
- /* Ok, here we need some tweak. If we have already renumbered
- * all busses, we can't rely on the OF bus number any more.
- * the pci_to_OF_bus_map is not enough as several PCI busses
- * may match the same OF bus number.
- */
- if (!pci_to_OF_bus_map)
- return 0;
-
- for_each_pci_dev(dev)
- if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
- dev->devfn == *devfn) {
- *bus = dev->bus->number;
- pci_dev_put(dev);
- return 0;
- }
-
- return -ENODEV;
-}
-EXPORT_SYMBOL(pci_device_from_OF_node);
-
-/* We create the "pci-OF-bus-map" property now so it appears in the
- * /proc device tree
- */
-void __init
-pci_create_OF_bus_map(void)
-{
- struct property *of_prop;
- struct device_node *dn;
-
- of_prop = (struct property *) alloc_bootmem(sizeof(struct property) + \
- 256);
- if (!of_prop)
- return;
- dn = of_find_node_by_path("/");
- if (dn) {
- memset(of_prop, -1, sizeof(struct property) + 256);
- of_prop->name = "pci-OF-bus-map";
- of_prop->length = 256;
- of_prop->value = &of_prop[1];
- prom_add_property(dn, of_prop);
- of_node_put(dn);
- }
-}
-
-static void __devinit pcibios_scan_phb(struct pci_controller *hose)
-{
- struct pci_bus *bus;
- struct device_node *node = hose->dn;
- unsigned long io_offset;
- struct resource *res = &hose->io_resource;
-
- pr_debug("PCI: Scanning PHB %s\n",
- node ? node->full_name : "<NO NAME>");
-
- /* Create an empty bus for the toplevel */
- bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
- if (bus == NULL) {
- printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
- hose->global_number);
- return;
- }
- bus.dev->of_node = of_node_get(node);
- bus->secondary = hose->first_busno;
- hose->bus = bus;
-
- /* Fixup IO space offset */
- io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
- res->start = (res->start + io_offset) & 0xffffffffu;
- res->end = (res->end + io_offset) & 0xffffffffu;
-
- /* Wire up PHB bus resources */
- pcibios_setup_phb_resources(hose);
-
- /* Scan children */
- hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
-}
-
-static int __init pcibios_init(void)
-{
- struct pci_controller *hose, *tmp;
- int next_busno = 0;
-
- printk(KERN_INFO "PCI: Probing PCI hardware\n");
-
- if (pci_flags & PCI_REASSIGN_ALL_BUS) {
- printk(KERN_INFO "setting pci_asign_all_busses\n");
- pci_assign_all_buses = 1;
- }
-
- /* Scan all of the recorded PCI controllers. */
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- if (pci_assign_all_buses)
- hose->first_busno = next_busno;
- hose->last_busno = 0xff;
- pcibios_scan_phb(hose);
- printk(KERN_INFO "calling pci_bus_add_devices()\n");
- pci_bus_add_devices(hose->bus);
- if (pci_assign_all_buses || next_busno <= hose->last_busno)
- next_busno = hose->last_busno + \
- pcibios_assign_bus_offset;
- }
- pci_bus_count = next_busno;
-
- /* OpenFirmware based machines need a map of OF bus
- * numbers vs. kernel bus numbers since we may have to
- * remap them.
- */
- if (pci_assign_all_buses)
- pcibios_make_OF_bus_map();
-
- /* Call common code to handle resource allocation */
- pcibios_resource_survey();
-
- return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-static struct pci_controller*
-pci_bus_to_hose(int bus)
-{
- struct pci_controller *hose, *tmp;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
- if (bus >= hose->first_busno && bus <= hose->last_busno)
- return hose;
- return NULL;
-}
-
-/* Provide information on locations of various I/O regions in physical
- * memory. Do this on a per-card basis so that we choose the right
- * root bridge.
- * Note that the returned IO or memory base is a physical address
- */
-
-long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
-{
- struct pci_controller *hose;
- long result = -EOPNOTSUPP;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return -ENODEV;
-
- switch (which) {
- case IOBASE_BRIDGE_NUMBER:
- return (long)hose->first_busno;
- case IOBASE_MEMORY:
- return (long)hose->pci_mem_offset;
- case IOBASE_IO:
- return (long)hose->io_base_phys;
- case IOBASE_ISA_IO:
- return (long)isa_io_base;
- case IOBASE_ISA_MEM:
- return (long)isa_mem_base;
- }
-
- return result;
-}
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index aef6c917b45a..5ce8029f558b 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -16,6 +16,7 @@ platforms += lasat
platforms += loongson
platforms += mipssim
platforms += mti-malta
+platforms += netlogic
platforms += pmc-sierra
platforms += pnx833x
platforms += pnx8550
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 653da62d0682..177cdaf83564 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -185,6 +185,7 @@ config MACH_JAZZ
select CSRC_R4K
select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN
select GENERIC_ISA_DMA
+ select HAVE_PCSPKR_PLATFORM
select IRQ_CPU
select I8253
select I8259
@@ -266,6 +267,7 @@ config MIPS_MALTA
select CSRC_R4K
select DMA_NONCOHERENT
select GENERIC_ISA_DMA
+ select HAVE_PCSPKR_PLATFORM
select IRQ_CPU
select IRQ_GIC
select HW_HAS_PCI
@@ -640,6 +642,7 @@ config SNI_RM
select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN
select DMA_NONCOHERENT
select GENERIC_ISA_DMA
+ select HAVE_PCSPKR_PLATFORM
select HW_HAS_EISA
select HW_HAS_PCI
select IRQ_CPU
@@ -2388,6 +2391,7 @@ config MMU
config I8253
bool
select CLKSRC_I8253
+ select CLKEVT_I8253
select MIPS_EXTERNAL_TIMER
config ZONE_DMA32
@@ -2489,20 +2493,4 @@ source "security/Kconfig"
source "crypto/Kconfig"
-menuconfig VIRTUALIZATION
- bool "Virtualization"
- default n
- ---help---
- Say Y here to get to see options for using your Linux host to run other
- operating systems inside virtual machines (guests).
- This option alone does not add any kernel code.
-
- If you say N, all options in this submenu will be skipped and disabled.
-
-if VIRTUALIZATION
-
-source drivers/virtio/Kconfig
-
-endif # VIRTUALIZATION
-
source "lib/Kconfig"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 884819cd0607..53e3514ba10e 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -191,18 +191,6 @@ endif
#
include $(srctree)/arch/mips/Kbuild.platforms
-#
-# NETLOGIC SOC Common (common)
-#
-cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/mach-netlogic
-cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/netlogic
-
-#
-# NETLOGIC XLR/XLS SoC, Simulator and boards
-#
-core-$(CONFIG_NLM_XLR) += arch/mips/netlogic/xlr/
-load-$(CONFIG_NLM_XLR_BOARD) += 0xffffffff84000000
-
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
drivers-$(CONFIG_PCI) += arch/mips/pci/
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
index 2ca4ada1c291..2460f9d23f1b 100644
--- a/arch/mips/ar7/clock.c
+++ b/arch/mips/ar7/clock.c
@@ -443,7 +443,7 @@ struct clk *clk_get(struct device *dev, const char *id)
return &vbus_clk;
if (!strcmp(id, "cpu"))
return &cpu_clk;
- if (!strcmp(id, "dsp"));
+ if (!strcmp(id, "dsp"))
return &dsp_clk;
if (!strcmp(id, "vbus"))
return &vbus_clk;
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 7d2fab392327..33ffecf6a6d6 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -229,7 +229,7 @@ static struct resource cpmac_low_res[] = {
.name = "irq",
.flags = IORESOURCE_IRQ,
.start = 27,
- .end = 27,
+ .end = 27,
},
};
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
index 23818d299127..8088c6fdb83e 100644
--- a/arch/mips/ar7/prom.c
+++ b/arch/mips/ar7/prom.c
@@ -77,7 +77,7 @@ struct psp_env_chunk {
u16 csum;
u8 len;
char data[11];
-} __attribute__ ((packed));
+} __packed;
struct psp_var_map_entry {
u8 num;
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 73b529b57433..cfae81571ded 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2006 Michael Buesch <m@bues.ch>
* Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
* Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
*
diff --git a/arch/mips/cobalt/time.c b/arch/mips/cobalt/time.c
index 0162f9edc693..3bff3b820baf 100644
--- a/arch/mips/cobalt/time.c
+++ b/arch/mips/cobalt/time.c
@@ -17,10 +17,10 @@
* 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/i8253.h>
#include <linux/init.h>
#include <asm/gt64120.h>
-#include <asm/i8253.h>
#include <asm/time.h>
#define GT641XX_BASE_CLOCK 50000000 /* 50MHz */
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 4a02fe891ab6..1d93f81d57e7 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -303,15 +303,15 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
/**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -323,9 +323,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#define atomic_dec_return(v) atomic_sub_return(1, (v))
#define atomic_inc_return(v) atomic_add_return(1, (v))
@@ -680,7 +679,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
{
@@ -766,10 +765,6 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
*/
#define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
-#else /* !CONFIG_64BIT */
-
-#include <asm-generic/atomic64.h>
-
#endif /* CONFIG_64BIT */
/*
@@ -781,6 +776,4 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
#define smp_mb__before_atomic_inc() smp_mb__before_llsc()
#define smp_mb__after_atomic_inc() smp_llsc_mb()
-#include <asm-generic/atomic-long.h>
-
#endif /* _ASM_ATOMIC_H */
diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h
index 0b89b83e2055..98bcc98cf29b 100644
--- a/arch/mips/include/asm/fixmap.h
+++ b/arch/mips/include/asm/fixmap.h
@@ -14,6 +14,7 @@
#define _ASM_FIXMAP_H
#include <asm/page.h>
+#include <spaces.h>
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
#include <asm/kmap_types.h>
@@ -67,15 +68,6 @@ enum fixed_addresses {
* the start of the fixmap, and leave one page empty
* at the top of mem..
*/
-#ifdef CONFIG_BCM63XX
-#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000)
-#else
-#if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX)
-#define FIXADDR_TOP ((unsigned long)(long)(int)(0xff000000 - 0x20000))
-#else
-#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000)
-#endif
-#endif
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
diff --git a/arch/mips/include/asm/floppy.h b/arch/mips/include/asm/floppy.h
index c5c7c0e6064c..4456c9c47e21 100644
--- a/arch/mips/include/asm/floppy.h
+++ b/arch/mips/include/asm/floppy.h
@@ -29,7 +29,7 @@ static inline void fd_cacheflush(char * addr, long size)
#define FLOPPY0_TYPE fd_drive_type(0)
#define FLOPPY1_TYPE fd_drive_type(1)
-#define FDC1 fd_getfdaddr1();
+#define FDC1 fd_getfdaddr1()
#define N_FDC 1 /* do you *really* want a second controller? */
#define N_DRIVE 8
diff --git a/arch/mips/include/asm/gt64120.h b/arch/mips/include/asm/gt64120.h
index e64b41093c49..0aa44abc77fe 100644
--- a/arch/mips/include/asm/gt64120.h
+++ b/arch/mips/include/asm/gt64120.h
@@ -21,8 +21,6 @@
#ifndef _ASM_GT64120_H
#define _ASM_GT64120_H
-#include <linux/clocksource.h>
-
#include <asm/addrspace.h>
#include <asm/byteorder.h>
diff --git a/arch/mips/include/asm/hw_irq.h b/arch/mips/include/asm/hw_irq.h
index 77adda297ad9..9e8ef5994c9c 100644
--- a/arch/mips/include/asm/hw_irq.h
+++ b/arch/mips/include/asm/hw_irq.h
@@ -8,7 +8,7 @@
#ifndef __ASM_HW_IRQ_H
#define __ASM_HW_IRQ_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
extern atomic_t irq_err_count;
diff --git a/arch/mips/include/asm/i8253.h b/arch/mips/include/asm/i8253.h
deleted file mode 100644
index 9ad011366f73..000000000000
--- a/arch/mips/include/asm/i8253.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Machine specific IO port address definition for generic.
- * Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-#ifndef __ASM_I8253_H
-#define __ASM_I8253_H
-
-#include <linux/spinlock.h>
-
-/* i8253A PIT registers */
-#define PIT_MODE 0x43
-#define PIT_CH0 0x40
-#define PIT_CH2 0x42
-
-#define PIT_LATCH LATCH
-
-extern raw_spinlock_t i8253_lock;
-
-extern void setup_pit_timer(void);
-
-#define inb_pit inb_p
-#define outb_pit outb_p
-
-#endif /* __ASM_I8253_H */
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 0ec01294b063..2354c870a63a 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -18,7 +18,6 @@
static inline void irq_dispose_mapping(unsigned int virq)
{
- return;
}
#ifdef CONFIG_I8259
diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index fffc8307a80a..94fde8d0fac1 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -3,7 +3,7 @@
#include <linux/percpu.h>
#include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cmpxchg.h>
#include <asm/war.h>
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 85fd27509aac..0ed5230243c9 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -89,7 +89,6 @@
/* Interrupt Mask register */
#define PERF_IRQMASK_REG 0xc
-#define PERF_IRQSTAT_REG 0x10
/* Interrupt Status register */
#define PERF_IRQSTAT_REG 0x10
diff --git a/arch/mips/include/asm/mach-bcm63xx/spaces.h b/arch/mips/include/asm/mach-bcm63xx/spaces.h
new file mode 100644
index 000000000000..61e750fb4653
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/spaces.h
@@ -0,0 +1,17 @@
+/*
+ * 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 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_BCM63XX_SPACES_H
+#define _ASM_BCM63XX_SPACES_H
+
+#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_BCM63XX_SPACES_H */
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 8da98073e952..9c95177f7a7e 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -49,7 +49,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
static inline void plat_extra_sync_for_device(struct device *dev)
{
- return;
}
static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h
index c9fa4b14968d..d7a9efd3a5ce 100644
--- a/arch/mips/include/asm/mach-generic/spaces.h
+++ b/arch/mips/include/asm/mach-generic/spaces.h
@@ -82,4 +82,8 @@
#define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET)
#endif
+#ifndef FIXADDR_TOP
+#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000)
+#endif
+
#endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index 016d0989b141..06c441968e6e 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -60,7 +60,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
static inline void plat_extra_sync_for_device(struct device *dev)
{
- return;
}
static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index 302101b54acb..9fc1e9ad7038 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -50,7 +50,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
static inline void plat_extra_sync_for_device(struct device *dev)
{
- return;
}
static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-jz4740/gpio.h b/arch/mips/include/asm/mach-jz4740/gpio.h
index 7b74703745bb..1a6482ea0bb3 100644
--- a/arch/mips/include/asm/mach-jz4740/gpio.h
+++ b/arch/mips/include/asm/mach-jz4740/gpio.h
@@ -25,14 +25,13 @@ enum jz_gpio_function {
JZ_GPIO_FUNC3,
};
-
/*
Usually a driver for a SoC component has to request several gpio pins and
configure them as funcion pins.
jz_gpio_bulk_request can be used to ease this process.
Usually one would do something like:
- const static struct jz_gpio_bulk_request i2c_pins[] = {
+ static const struct jz_gpio_bulk_request i2c_pins[] = {
JZ_GPIO_BULK_PIN(I2C_SDA),
JZ_GPIO_BULK_PIN(I2C_SCK),
};
@@ -47,8 +46,8 @@ enum jz_gpio_function {
jz_gpio_bulk_free(i2c_pins, ARRAY_SIZE(i2c_pins));
-
*/
+
struct jz_gpio_bulk_request {
int gpio;
const char *name;
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 981c75f91a7d..e1433055fe98 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -55,7 +55,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
static inline void plat_extra_sync_for_device(struct device *dev)
{
- return;
}
static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
index 2848cea42bce..37e3583a9fdd 100644
--- a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
@@ -32,6 +32,7 @@
/* #define cpu_has_vtag_icache ? */
/* #define cpu_has_dc_aliases ? */
/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz 1
#define cpu_has_nofpuex 0
/* #define cpu_has_64bits ? */
/* #define cpu_has_64bit_zero_reg ? */
@@ -58,6 +59,7 @@
/* #define cpu_has_vtag_icache ? */
/* #define cpu_has_dc_aliases ? */
/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz 1
#define cpu_has_nofpuex 0
/* #define cpu_has_64bits ? */
/* #define cpu_has_64bit_zero_reg ? */
diff --git a/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
index 779b02205737..27aaaa5d925e 100644
--- a/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
@@ -31,6 +31,7 @@
/* #define cpu_has_vtag_icache ? */
/* #define cpu_has_dc_aliases ? */
/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz 1
#define cpu_has_nofpuex 0
/* #define cpu_has_64bits ? */
/* #define cpu_has_64bit_zero_reg ? */
@@ -56,6 +57,7 @@
/* #define cpu_has_vtag_icache ? */
/* #define cpu_has_dc_aliases ? */
/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz 1
#define cpu_has_nofpuex 0
/* #define cpu_has_64bits ? */
/* #define cpu_has_64bit_zero_reg ? */
diff --git a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
new file mode 100644
index 000000000000..f751e3ec56fb
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
+#define _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
+#define cpu_has_tlb 1
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 1
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 0
+#define cpu_has_counter 1
+#define cpu_has_watch 1
+#define cpu_has_divec 1
+#define cpu_has_vce 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_cache_cdex_s 0
+#define cpu_has_mcheck 1
+#define cpu_has_ejtag 1
+#define cpu_has_llsc 1
+#define cpu_has_mips16 0
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+#define cpu_has_vtag_icache 0
+#define cpu_has_dc_aliases 0
+#define cpu_has_ic_fills_f_dc 0
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 1
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+#define cpu_has_userlocal 0
+#define cpu_has_nofpuex 0
+#define cpu_has_64bits 0
+#define cpu_has_64bit_zero_reg 0
+#define cpu_has_vint 1
+#define cpu_has_veic 1
+#define cpu_has_inclusive_pcaches 0
+
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 32
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
index a8e72cf12142..62c094085947 100644
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -102,7 +102,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
static inline void plat_extra_sync_for_device(struct device *dev)
{
- return;
}
static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-tx39xx/spaces.h b/arch/mips/include/asm/mach-tx39xx/spaces.h
new file mode 100644
index 000000000000..151fe7a1cf1d
--- /dev/null
+++ b/arch/mips/include/asm/mach-tx39xx/spaces.h
@@ -0,0 +1,17 @@
+/*
+ * 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 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_TX39XX_SPACES_H
+#define _ASM_TX39XX_SPACES_H
+
+#define FIXADDR_TOP ((unsigned long)(long)(int)0xfefe0000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_TX39XX_SPACES_H */
diff --git a/arch/mips/include/asm/mach-tx49xx/spaces.h b/arch/mips/include/asm/mach-tx49xx/spaces.h
new file mode 100644
index 000000000000..0cb10a6f489e
--- /dev/null
+++ b/arch/mips/include/asm/mach-tx49xx/spaces.h
@@ -0,0 +1,17 @@
+/*
+ * 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 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_TX49XX_SPACES_H
+#define _ASM_TX49XX_SPACES_H
+
+#define FIXADDR_TOP ((unsigned long)(long)(int)0xfefe0000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_TX49XX_SPACES_H */
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 7e40f3778179..b2202a68cf0f 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -414,6 +414,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
* constraints placed on us by the cache architecture.
*/
#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
/*
* No page table caches to initialise
diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index 9e09af34c8a8..ef2a8041e78b 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -11,6 +11,8 @@
#ifndef __ASM_SMP_OPS_H
#define __ASM_SMP_OPS_H
+#include <linux/errno.h>
+
#ifdef CONFIG_SMP
#include <linux/cpumask.h>
@@ -56,8 +58,43 @@ static inline void register_smp_ops(struct plat_smp_ops *ops)
#endif /* !CONFIG_SMP */
-extern struct plat_smp_ops up_smp_ops;
-extern struct plat_smp_ops cmp_smp_ops;
-extern struct plat_smp_ops vsmp_smp_ops;
+static inline int register_up_smp_ops(void)
+{
+#ifdef CONFIG_SMP_UP
+ extern struct plat_smp_ops up_smp_ops;
+
+ register_smp_ops(&up_smp_ops);
+
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
+
+static inline int register_cmp_smp_ops(void)
+{
+#ifdef CONFIG_MIPS_CMP
+ extern struct plat_smp_ops cmp_smp_ops;
+
+ register_smp_ops(&cmp_smp_ops);
+
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
+
+static inline int register_vsmp_smp_ops(void)
+{
+#ifdef CONFIG_MIPS_MT_SMP
+ extern struct plat_smp_ops vsmp_smp_ops;
+
+ register_smp_ops(&vsmp_smp_ops);
+
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
#endif /* __ASM_SMP_OPS_H */
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index af42385245d5..d4fb4d852a6d 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -17,7 +17,7 @@
#include <linux/threads.h>
#include <linux/cpumask.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp-ops.h>
extern int smp_num_siblings;
diff --git a/arch/mips/include/asm/smtc.h b/arch/mips/include/asm/smtc.h
index ea60bf08dcb0..c9736fc06325 100644
--- a/arch/mips/include/asm/smtc.h
+++ b/arch/mips/include/asm/smtc.h
@@ -46,6 +46,7 @@ extern void smtc_prepare_cpus(int cpus);
extern void smtc_smp_finish(void);
extern void smtc_boot_secondary(int cpu, struct task_struct *t);
extern void smtc_cpus_done(void);
+extern void smtc_init_secondary(void);
/*
diff --git a/arch/mips/include/asm/stacktrace.h b/arch/mips/include/asm/stacktrace.h
index 0bf82818aa53..780ee2c2a2ac 100644
--- a/arch/mips/include/asm/stacktrace.h
+++ b/arch/mips/include/asm/stacktrace.h
@@ -7,6 +7,10 @@
extern int raw_show_trace;
extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
unsigned long pc, unsigned long *ra);
+extern unsigned long unwind_stack_by_address(unsigned long stack_page,
+ unsigned long *sp,
+ unsigned long pc,
+ unsigned long *ra);
#else
#define raw_show_trace 1
static inline unsigned long unwind_stack(struct task_struct *task,
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index dcbd4bb417ec..504d40aedfae 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -150,6 +150,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
# define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh)
# define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh)
# define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh)
+# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_dsrl_safe(buf, rs, rt, sh)
# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh)
# define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd)
# define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd)
@@ -165,6 +166,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
# define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh)
# define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh)
# define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
+# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh)
# define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd)
# define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd)
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 6fcfc480e9d0..ecea7871dec2 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -363,17 +363,18 @@
#define __NR_open_by_handle_at (__NR_Linux + 340)
#define __NR_clock_adjtime (__NR_Linux + 341)
#define __NR_syncfs (__NR_Linux + 342)
-#define __NR_setns (__NR_Linux + 343)
+#define __NR_sendmmsg (__NR_Linux + 343)
+#define __NR_setns (__NR_Linux + 344)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 343
+#define __NR_Linux_syscalls 344
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 343
+#define __NR_O32_Linux_syscalls 344
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -683,17 +684,18 @@
#define __NR_open_by_handle_at (__NR_Linux + 299)
#define __NR_clock_adjtime (__NR_Linux + 300)
#define __NR_syncfs (__NR_Linux + 301)
-#define __NR_setns (__NR_Linux + 302)
+#define __NR_sendmmsg (__NR_Linux + 302)
+#define __NR_setns (__NR_Linux + 303)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 302
+#define __NR_Linux_syscalls 303
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 302
+#define __NR_64_Linux_syscalls 303
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -1008,17 +1010,18 @@
#define __NR_open_by_handle_at (__NR_Linux + 304)
#define __NR_clock_adjtime (__NR_Linux + 305)
#define __NR_syncfs (__NR_Linux + 306)
-#define __NR_setns (__NR_Linux + 307)
+#define __NR_sendmmsg (__NR_Linux + 307)
+#define __NR_setns (__NR_Linux + 308)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 307
+#define __NR_Linux_syscalls 308
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 307
+#define __NR_N32_Linux_syscalls 308
#ifdef __KERNEL__
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index 260df4750949..ca9bd2069142 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -7,6 +7,7 @@
* Copyright (C) 1994 - 2001, 2003, 07 Ralf Baechle
*/
#include <linux/clockchips.h>
+#include <linux/i8253.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -15,7 +16,6 @@
#include <linux/irq.h>
#include <asm/irq_cpu.h>
-#include <asm/i8253.h>
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/jazz.h>
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index bb133d10b145..ebc0cd20b35d 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -71,7 +71,6 @@ void r4k_wait_irqoff(void)
local_irq_enable();
__asm__(" .globl __pastwait \n"
"__pastwait: \n");
- return;
}
/*
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 391221b6a6aa..be4ee7d63e04 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -3,96 +3,16 @@
*
*/
#include <linux/clockchips.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
+#include <linux/i8253.h>
#include <linux/module.h>
#include <linux/smp.h>
-#include <linux/spinlock.h>
#include <linux/irq.h>
-#include <asm/delay.h>
-#include <asm/i8253.h>
-#include <asm/io.h>
#include <asm/time.h>
-DEFINE_RAW_SPINLOCK(i8253_lock);
-EXPORT_SYMBOL(i8253_lock);
-
-/*
- * Initialize the PIT timer.
- *
- * This is also called after resume to bring the PIT into operation again.
- */
-static void init_pit_timer(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- raw_spin_lock(&i8253_lock);
-
- switch(mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- /* binary, mode 2, LSB/MSB, ch 0 */
- outb_p(0x34, PIT_MODE);
- outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
- outb(LATCH >> 8 , PIT_CH0); /* MSB */
- break;
-
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_UNUSED:
- if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
- evt->mode == CLOCK_EVT_MODE_ONESHOT) {
- outb_p(0x30, PIT_MODE);
- outb_p(0, PIT_CH0);
- outb_p(0, PIT_CH0);
- }
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* One shot setup */
- outb_p(0x38, PIT_MODE);
- break;
-
- case CLOCK_EVT_MODE_RESUME:
- /* Nothing to do here */
- break;
- }
- raw_spin_unlock(&i8253_lock);
-}
-
-/*
- * Program the next event in oneshot mode
- *
- * Delta is given in PIT ticks
- */
-static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
-{
- raw_spin_lock(&i8253_lock);
- outb_p(delta & 0xff , PIT_CH0); /* LSB */
- outb(delta >> 8 , PIT_CH0); /* MSB */
- raw_spin_unlock(&i8253_lock);
-
- return 0;
-}
-
-/*
- * On UP the PIT can serve all of the possible timer functions. On SMP systems
- * it can be solely used for the global tick.
- *
- * The profiling and update capabilites are switched off once the local apic is
- * registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
- * !using_apic_timer decisions in do_timer_interrupt_hook()
- */
-static struct clock_event_device pit_clockevent = {
- .name = "pit",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_mode = init_pit_timer,
- .set_next_event = pit_next_event,
- .irq = 0,
-};
-
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
- pit_clockevent.event_handler(&pit_clockevent);
+ i8253_clockevent.event_handler(&i8253_clockevent);
return IRQ_HANDLED;
}
@@ -103,25 +23,9 @@ static struct irqaction irq0 = {
.name = "timer"
};
-/*
- * Initialize the conversion factor and the min/max deltas of the clock event
- * structure and register the clock event source with the framework.
- */
void __init setup_pit_timer(void)
{
- struct clock_event_device *cd = &pit_clockevent;
- unsigned int cpu = smp_processor_id();
-
- /*
- * Start pit with the boot cpu mask and make it global after the
- * IO_APIC has been initialized.
- */
- cd->cpumask = cpumask_of(cpu);
- clockevent_set_clock(cd, CLOCK_TICK_RATE);
- cd->max_delta_ns = clockevent_delta2ns(0x7FFF, cd);
- cd->min_delta_ns = clockevent_delta2ns(0xF, cd);
- clockevents_register_device(cd);
-
+ clockevent_i8253_init(true);
setup_irq(0, &irq0);
}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 9b734d74ae8e..b53970d80991 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -23,7 +23,7 @@
#include <linux/kgdb.h>
#include <linux/ftrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 6e71b284f6c9..191eb52228c4 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -103,14 +103,12 @@ void __init mips_cpu_irq_init(void)
clear_c0_status(ST0_IM);
clear_c0_cause(CAUSEF_IP);
- /*
- * Only MT is using the software interrupts currently, so we just
- * leave them uninitialized for other processors.
- */
- if (cpu_has_mipsmt)
- for (i = irq_base; i < irq_base + 2; i++)
- irq_set_chip_and_handler(i, &mips_mt_cpu_irq_controller,
- handle_percpu_irq);
+ /* Software interrupts are used for MT/CMT IPI */
+ for (i = irq_base; i < irq_base + 2; i++)
+ irq_set_chip_and_handler(i, cpu_has_mipsmt ?
+ &mips_mt_cpu_irq_controller :
+ &mips_cpu_irq_controller,
+ handle_percpu_irq);
for (i = irq_base + 2; i < irq_base + 8; i++)
irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index b2259e7cd829..594ca69cb867 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -12,7 +12,7 @@
#include <asm/cpu.h>
#include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/hardirq.h>
#include <asm/mmu_context.h>
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index dd940b701963..4b930ac4aff2 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -45,30 +45,14 @@ static struct mips_hi16 *mips_hi16_list;
static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock);
+#ifdef MODULE_START
void *module_alloc(unsigned long size)
{
-#ifdef MODULE_START
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
GFP_KERNEL, PAGE_KERNEL, -1,
__builtin_return_address(0));
-#else
- if (size == 0)
- return NULL;
- return vmalloc(size);
-#endif
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
- char *secstrings, struct module *mod)
-{
- return 0;
}
+#endif
static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
{
diff --git a/arch/mips/kernel/perf_event.c b/arch/mips/kernel/perf_event.c
index a8244854d3dc..0aee944ac380 100644
--- a/arch/mips/kernel/perf_event.c
+++ b/arch/mips/kernel/perf_event.c
@@ -192,8 +192,6 @@ again:
local64_add(delta, &event->count);
local64_sub(delta, &hwc->period_left);
-
- return;
}
static void mipspmu_start(struct perf_event *event, int flags)
@@ -527,7 +525,7 @@ handle_associated_event(struct cpu_hw_events *cpuc,
if (!mipspmu_event_set_period(event, hwc, idx))
return;
- if (perf_event_overflow(event, 0, data, regs))
+ if (perf_event_overflow(event, data, regs))
mipspmu->disable_event(idx);
}
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 75266ff4cc33..e5ad09a9baf7 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -377,6 +377,20 @@ static const struct mips_perf_event mipsxxcore_cache_map
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
+[C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ },
+},
};
/* 74K core has completely different cache event map. */
@@ -480,6 +494,20 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
+[C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ },
+},
};
#ifdef CONFIG_MIPS_MT_SMP
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index d2112d3cf115..b30cb2573aaf 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -103,7 +103,6 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
__init_dsp();
regs->cp0_epc = pc;
regs->regs[29] = sp;
- current_thread_info()->addr_limit = USER_DS;
}
void exit_thread(void)
@@ -373,18 +372,18 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
#ifdef CONFIG_KALLSYMS
-/* used by show_backtrace() */
-unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
- unsigned long pc, unsigned long *ra)
+/* generic stack unwinding function */
+unsigned long notrace unwind_stack_by_address(unsigned long stack_page,
+ unsigned long *sp,
+ unsigned long pc,
+ unsigned long *ra)
{
- unsigned long stack_page;
struct mips_frame_info info;
unsigned long size, ofs;
int leaf;
extern void ret_from_irq(void);
extern void ret_from_exception(void);
- stack_page = (unsigned long)task_stack_page(task);
if (!stack_page)
return 0;
@@ -443,6 +442,15 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
*ra = 0;
return __kernel_text_address(pc) ? pc : 0;
}
+EXPORT_SYMBOL(unwind_stack_by_address);
+
+/* used by show_backtrace() */
+unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+ unsigned long pc, unsigned long *ra)
+{
+ unsigned long stack_page = (unsigned long)task_stack_page(task);
+ return unwind_stack_by_address(stack_page, sp, pc, ra);
+}
#endif
/*
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 557ef72472e0..7a80b7cda7cc 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -36,7 +36,7 @@
#include <asm/mipsmtregs.h>
#include <asm/mips_mt.h>
#include <asm/cacheflush.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/system.h>
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 99e656e425f3..e521420a45a5 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -589,6 +589,7 @@ einval: li v0, -ENOSYS
sys sys_open_by_handle_at 3 /* 4340 */
sys sys_clock_adjtime 2
sys sys_syncfs 1
+ sys sys_sendmmsg 4
sys sys_setns 2
.endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index fb0575f47f3d..85874d6a8a70 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -428,5 +428,6 @@ sys_call_table:
PTR sys_open_by_handle_at
PTR sys_clock_adjtime /* 5300 */
PTR sys_syncfs
+ PTR sys_sendmmsg
PTR sys_setns
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 4de0c5534e73..b85842fc87ae 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -428,5 +428,6 @@ EXPORT(sysn32_call_table)
PTR sys_open_by_handle_at
PTR compat_sys_clock_adjtime /* 6305 */
PTR sys_syncfs
+ PTR compat_sys_sendmmsg
PTR sys_setns
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 4a387de08bfa..46c4763edf21 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -546,5 +546,6 @@ sys_call_table:
PTR compat_sys_open_by_handle_at /* 4340 */
PTR compat_sys_clock_adjtime
PTR sys_syncfs
+ PTR compat_sys_sendmmsg
PTR sys_setns
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index cc81771b882c..fe3095160655 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/processor.h>
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 1ec56e635d04..ce9e286f0a74 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -24,7 +24,7 @@
#include <linux/compiler.h>
#include <linux/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/processor.h>
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 32a256101082..32c1e954cd37 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -34,7 +34,7 @@
#include <linux/err.h>
#include <linux/ftrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/r4k-timer.h>
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
index fe256559c997..928a5a61e1a6 100644
--- a/arch/mips/kernel/smtc-proc.c
+++ b/arch/mips/kernel/smtc-proc.c
@@ -10,7 +10,7 @@
#include <asm/cpu.h>
#include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/hardirq.h>
#include <asm/mmu_context.h>
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index cedac4633741..f0895e70e283 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -30,7 +30,7 @@
#include <asm/cpu.h>
#include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/hardirq.h>
#include <asm/hazards.h>
diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
index 05dd170a83f7..99f913c8d7a6 100644
--- a/arch/mips/kernel/sync-r4k.c
+++ b/arch/mips/kernel/sync-r4k.c
@@ -16,7 +16,7 @@
#include <linux/cpumask.h>
#include <asm/r4k-timer.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/barrier.h>
#include <asm/mipsregs.h>
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index e9b3af27d844..b7517e3abc85 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -578,12 +578,12 @@ static int simulate_llsc(struct pt_regs *regs, unsigned int opcode)
{
if ((opcode & OPCODE) == LL) {
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
- 1, 0, regs, 0);
+ 1, regs, 0);
return simulate_ll(regs, opcode);
}
if ((opcode & OPCODE) == SC) {
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
- 1, 0, regs, 0);
+ 1, regs, 0);
return simulate_sc(regs, opcode);
}
@@ -602,7 +602,7 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
int rd = (opcode & RD) >> 11;
int rt = (opcode & RT) >> 16;
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
- 1, 0, regs, 0);
+ 1, regs, 0);
switch (rd) {
case 0: /* CPU number */
regs->regs[rt] = smp_processor_id();
@@ -640,7 +640,7 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
{
if ((opcode & OPCODE) == SPEC0 && (opcode & FUNC) == SYNC) {
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
- 1, 0, regs, 0);
+ 1, regs, 0);
return 0;
}
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index cfea1adfa153..eb319b580353 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -111,8 +111,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
unsigned long value;
unsigned int res;
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
- 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
/*
* This load never faults.
@@ -517,7 +516,7 @@ asmlinkage void do_ade(struct pt_regs *regs)
mm_segment_t seg;
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
- 1, 0, regs, regs->cp0_badvaddr);
+ 1, regs, regs->cp0_badvaddr);
/*
* Did we catch a fault trying to load an instruction?
* Or are we running in MIPS16 mode?
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index dbb6b408f001..2cd50ad0d5c6 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -46,7 +46,7 @@
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/cacheflush.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cpu.h>
#include <asm/mips_mt.h>
#include <asm/processor.h>
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index 94560899d13e..7e9c0ffc11a5 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -100,6 +100,19 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);
+int clk_enable(struct clk *clk)
+{
+ /* not used */
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ /* not used */
+}
+EXPORT_SYMBOL(clk_disable);
+
static inline u32 ltq_get_counter_resolution(void)
{
u32 res;
diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
index 7b82c34cb169..44a36771c819 100644
--- a/arch/mips/lantiq/devices.c
+++ b/arch/mips/lantiq/devices.c
@@ -15,11 +15,9 @@
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
-#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/leds.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
index e09e789dfc27..d0e32ab2ea07 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -16,11 +16,9 @@
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
-#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/leds.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
index 64057244eec5..2b666d3a3947 100644
--- a/arch/mips/loongson/lemote-2f/ec_kb3310b.c
+++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
@@ -45,8 +45,6 @@ void ec_write(unsigned short addr, unsigned char val)
/* flush the write action */
inb(EC_IO_PORT_DATA);
spin_unlock_irqrestore(&index_access_lock, flags);
-
- return;
}
EXPORT_SYMBOL_GPL(ec_write);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index d32cb0503110..dbf2f93a5091 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -272,8 +272,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
}
emul:
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
- 1, 0, xcp, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0);
MIPS_FPU_EMU_INC_STATS(emulated);
switch (MIPSInst_OPCODE(ir)) {
case ldc1_op:{
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
index 55f22a3afe61..256e0cdaa499 100644
--- a/arch/mips/mipssim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -34,6 +34,7 @@
#include <asm/time.h>
#include <asm/mips-boards/sim.h>
#include <asm/mips-boards/simint.h>
+#include <asm/smp-ops.h>
static void __init serial_init(void);
@@ -59,18 +60,17 @@ void __init prom_init(void)
prom_meminit();
-#ifdef CONFIG_MIPS_MT_SMP
- if (cpu_has_mipsmt)
- register_smp_ops(&vsmp_smp_ops);
- else
- register_smp_ops(&up_smp_ops);
-#endif
+ if (cpu_has_mipsmt) {
+ if (!register_vsmp_smp_ops())
+ return;
+
#ifdef CONFIG_MIPS_MT_SMTC
- if (cpu_has_mipsmt)
register_smp_ops(&ssmtc_smp_ops);
- else
- register_smp_ops(&up_smp_ops);
+ return;
#endif
+ }
+
+ register_up_smp_ops();
}
static void __init serial_init(void)
diff --git a/arch/mips/mipssim/sim_smtc.c b/arch/mips/mipssim/sim_smtc.c
index 30df47258c2c..915063991f6e 100644
--- a/arch/mips/mipssim/sim_smtc.c
+++ b/arch/mips/mipssim/sim_smtc.c
@@ -24,7 +24,7 @@
#include <linux/interrupt.h>
#include <linux/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/smtc.h>
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index eeb642e4066e..b9aabb998a32 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -604,6 +604,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
r4k_blast_scache();
else
blast_scache_range(addr, addr + size);
+ __sync();
return;
}
@@ -620,6 +621,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
}
bc_wback_inv(addr, size);
+ __sync();
}
static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
@@ -647,6 +649,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
(addr + size - 1) & almask);
blast_inv_scache_range(addr, addr + size);
}
+ __sync();
return;
}
@@ -663,6 +666,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
}
bc_inv(addr, size);
+ __sync();
}
#endif /* CONFIG_DMA_NONCOHERENT */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 21ea14efb837..46084912e588 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -15,18 +15,18 @@
#include <linux/scatterlist.h>
#include <linux/string.h>
#include <linux/gfp.h>
+#include <linux/highmem.h>
#include <asm/cache.h>
#include <asm/io.h>
#include <dma-coherence.h>
-static inline unsigned long dma_addr_to_virt(struct device *dev,
+static inline struct page *dma_addr_to_page(struct device *dev,
dma_addr_t dma_addr)
{
- unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr);
-
- return (unsigned long)phys_to_virt(addr);
+ return pfn_to_page(
+ plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT);
}
/*
@@ -148,20 +148,20 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
free_pages(addr, get_order(size));
}
-static inline void __dma_sync(unsigned long addr, size_t size,
+static inline void __dma_sync_virtual(void *addr, size_t size,
enum dma_data_direction direction)
{
switch (direction) {
case DMA_TO_DEVICE:
- dma_cache_wback(addr, size);
+ dma_cache_wback((unsigned long)addr, size);
break;
case DMA_FROM_DEVICE:
- dma_cache_inv(addr, size);
+ dma_cache_inv((unsigned long)addr, size);
break;
case DMA_BIDIRECTIONAL:
- dma_cache_wback_inv(addr, size);
+ dma_cache_wback_inv((unsigned long)addr, size);
break;
default:
@@ -169,12 +169,49 @@ static inline void __dma_sync(unsigned long addr, size_t size,
}
}
+/*
+ * A single sg entry may refer to multiple physically contiguous
+ * pages. But we still need to process highmem pages individually.
+ * If highmem is not configured then the bulk of this loop gets
+ * optimized out.
+ */
+static inline void __dma_sync(struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ size_t left = size;
+
+ do {
+ size_t len = left;
+
+ if (PageHighMem(page)) {
+ void *addr;
+
+ if (offset + len > PAGE_SIZE) {
+ if (offset >= PAGE_SIZE) {
+ page += offset >> PAGE_SHIFT;
+ offset &= ~PAGE_MASK;
+ }
+ len = PAGE_SIZE - offset;
+ }
+
+ addr = kmap_atomic(page);
+ __dma_sync_virtual(addr + offset, len, direction);
+ kunmap_atomic(addr);
+ } else
+ __dma_sync_virtual(page_address(page) + offset,
+ size, direction);
+ offset = 0;
+ page++;
+ left -= len;
+ } while (left);
+}
+
static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
{
if (cpu_is_noncoherent_r10000(dev))
- __dma_sync(dma_addr_to_virt(dev, dma_addr), size,
- direction);
+ __dma_sync(dma_addr_to_page(dev, dma_addr),
+ dma_addr & ~PAGE_MASK, size, direction);
plat_unmap_dma_mem(dev, dma_addr, size, direction);
}
@@ -185,13 +222,11 @@ static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg,
int i;
for (i = 0; i < nents; i++, sg++) {
- unsigned long addr;
-
- addr = (unsigned long) sg_virt(sg);
- if (!plat_device_is_coherent(dev) && addr)
- __dma_sync(addr, sg->length, direction);
- sg->dma_address = plat_map_dma_mem(dev,
- (void *)addr, sg->length);
+ if (!plat_device_is_coherent(dev))
+ __dma_sync(sg_page(sg), sg->offset, sg->length,
+ direction);
+ sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) +
+ sg->offset;
}
return nents;
@@ -201,30 +236,23 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- unsigned long addr;
-
- addr = (unsigned long) page_address(page) + offset;
-
if (!plat_device_is_coherent(dev))
- __dma_sync(addr, size, direction);
+ __dma_sync(page, offset, size, direction);
- return plat_map_dma_mem(dev, (void *)addr, size);
+ return plat_map_dma_mem_page(dev, page) + offset;
}
static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
int nhwentries, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- unsigned long addr;
int i;
for (i = 0; i < nhwentries; i++, sg++) {
if (!plat_device_is_coherent(dev) &&
- direction != DMA_TO_DEVICE) {
- addr = (unsigned long) sg_virt(sg);
- if (addr)
- __dma_sync(addr, sg->length, direction);
- }
+ direction != DMA_TO_DEVICE)
+ __dma_sync(sg_page(sg), sg->offset, sg->length,
+ direction);
plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
}
}
@@ -232,24 +260,18 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
static void mips_dma_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
{
- if (cpu_is_noncoherent_r10000(dev)) {
- unsigned long addr;
-
- addr = dma_addr_to_virt(dev, dma_handle);
- __dma_sync(addr, size, direction);
- }
+ if (cpu_is_noncoherent_r10000(dev))
+ __dma_sync(dma_addr_to_page(dev, dma_handle),
+ dma_handle & ~PAGE_MASK, size, direction);
}
static void mips_dma_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
{
plat_extra_sync_for_device(dev);
- if (!plat_device_is_coherent(dev)) {
- unsigned long addr;
-
- addr = dma_addr_to_virt(dev, dma_handle);
- __dma_sync(addr, size, direction);
- }
+ if (!plat_device_is_coherent(dev))
+ __dma_sync(dma_addr_to_page(dev, dma_handle),
+ dma_handle & ~PAGE_MASK, size, direction);
}
static void mips_dma_sync_sg_for_cpu(struct device *dev,
@@ -260,8 +282,8 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev,
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nelems; i++, sg++) {
if (cpu_is_noncoherent_r10000(dev))
- __dma_sync((unsigned long)page_address(sg_page(sg)),
- sg->length, direction);
+ __dma_sync(sg_page(sg), sg->offset, sg->length,
+ direction);
}
}
@@ -273,8 +295,8 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nelems; i++, sg++) {
if (!plat_device_is_coherent(dev))
- __dma_sync((unsigned long)page_address(sg_page(sg)),
- sg->length, direction);
+ __dma_sync(sg_page(sg), sg->offset, sg->length,
+ direction);
}
}
@@ -295,7 +317,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev))
- __dma_sync((unsigned long)vaddr, size, direction);
+ __dma_sync_virtual(vaddr, size, direction);
}
EXPORT_SYMBOL(dma_cache_sync);
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 137ee76a0045..937cf3368164 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -145,7 +145,7 @@ good_area:
* the fault.
*/
fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@@ -154,12 +154,10 @@ good_area:
BUG();
}
if (fault & VM_FAULT_MAJOR) {
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
- 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
tsk->maj_flt++;
} else {
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
- 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
tsk->min_flt++;
}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 1aadeb42c5a5..b7ebc4fa89bc 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -277,11 +277,11 @@ void __init fixrange_init(unsigned long start, unsigned long end,
k = __pmd_offset(vaddr);
pgd = pgd_base + i;
- for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+ for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
pud = (pud_t *)pgd;
- for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+ for ( ; (j < PTRS_PER_PUD) && (vaddr < end); pud++, j++) {
pmd = (pmd_t *)pud;
- for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+ for (; (k < PTRS_PER_PMD) && (vaddr < end); pmd++, k++) {
if (pmd_none(*pmd)) {
pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
set_pmd(pmd, __pmd((unsigned long)pte));
@@ -368,7 +368,7 @@ void __init mem_init(void)
#ifdef CONFIG_DISCONTIGMEM
#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
#endif
- max_mapnr = highend_pfn;
+ max_mapnr = highend_pfn ? highend_pfn : max_low_pfn;
#else
max_mapnr = max_low_pfn;
#endif
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
index ae3c20a9556e..9ff5d0fac556 100644
--- a/arch/mips/mm/mmap.c
+++ b/arch/mips/mm/mmap.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/module.h>
+#include <linux/personality.h>
#include <linux/random.h>
#include <linux/sched.h>
@@ -17,21 +18,65 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
EXPORT_SYMBOL(shm_align_mask);
+/* gap between mmap and stack */
+#define MIN_GAP (128*1024*1024UL)
+#define MAX_GAP ((TASK_SIZE)/6*5)
+
+static int mmap_is_legacy(void)
+{
+ if (current->personality & ADDR_COMPAT_LAYOUT)
+ return 1;
+
+ if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
+ return 1;
+
+ return sysctl_legacy_va_layout;
+}
+
+static unsigned long mmap_base(unsigned long rnd)
+{
+ unsigned long gap = rlimit(RLIMIT_STACK);
+
+ if (gap < MIN_GAP)
+ gap = MIN_GAP;
+ else if (gap > MAX_GAP)
+ gap = MAX_GAP;
+
+ return PAGE_ALIGN(TASK_SIZE - gap - rnd);
+}
+
+static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
+ unsigned long pgoff)
+{
+ unsigned long base = addr & ~shm_align_mask;
+ unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
+
+ if (base + off <= addr)
+ return base + off;
+
+ return base - off;
+}
+
#define COLOUR_ALIGN(addr,pgoff) \
((((addr) + shm_align_mask) & ~shm_align_mask) + \
(((pgoff) << PAGE_SHIFT) & shm_align_mask))
-unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
+enum mmap_allocation_direction {UP, DOWN};
+
+static unsigned long arch_get_unmapped_area_foo(struct file *filp,
+ unsigned long addr0, unsigned long len, unsigned long pgoff,
+ unsigned long flags, enum mmap_allocation_direction dir)
{
- struct vm_area_struct * vmm;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ unsigned long addr = addr0;
int do_color_align;
- if (len > TASK_SIZE)
+ if (unlikely(len > TASK_SIZE))
return -ENOMEM;
if (flags & MAP_FIXED) {
- /* Even MAP_FIXED mappings must reside within TASK_SIZE. */
+ /* Even MAP_FIXED mappings must reside within TASK_SIZE */
if (TASK_SIZE - len < addr)
return -EINVAL;
@@ -48,34 +93,130 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
do_color_align = 0;
if (filp || (flags & MAP_SHARED))
do_color_align = 1;
+
+ /* requesting a specific address */
if (addr) {
if (do_color_align)
addr = COLOUR_ALIGN(addr, pgoff);
else
addr = PAGE_ALIGN(addr);
- vmm = find_vma(current->mm, addr);
+
+ vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
- (!vmm || addr + len <= vmm->vm_start))
+ (!vma || addr + len <= vma->vm_start))
return addr;
}
- addr = current->mm->mmap_base;
- if (do_color_align)
- addr = COLOUR_ALIGN(addr, pgoff);
- else
- addr = PAGE_ALIGN(addr);
- for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
- /* At this point: (!vmm || addr < vmm->vm_end). */
- if (TASK_SIZE - len < addr)
- return -ENOMEM;
- if (!vmm || addr + len <= vmm->vm_start)
- return addr;
- addr = vmm->vm_end;
+ if (dir == UP) {
+ addr = mm->mmap_base;
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ else
+ addr = PAGE_ALIGN(addr);
+
+ for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr)
+ return -ENOMEM;
+ if (!vma || addr + len <= vma->vm_start)
+ return addr;
+ addr = vma->vm_end;
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ }
+ } else {
+ /* check if free_area_cache is useful for us */
+ if (len <= mm->cached_hole_size) {
+ mm->cached_hole_size = 0;
+ mm->free_area_cache = mm->mmap_base;
+ }
+
+ /* either no address requested or can't fit in requested address hole */
+ addr = mm->free_area_cache;
+ if (do_color_align) {
+ unsigned long base =
+ COLOUR_ALIGN_DOWN(addr - len, pgoff);
+
+ addr = base + len;
+ }
+
+ /* make sure it can fit in the remaining address space */
+ if (likely(addr > len)) {
+ vma = find_vma(mm, addr - len);
+ if (!vma || addr <= vma->vm_start) {
+ /* remember the address as a hint for next time */
+ return mm->free_area_cache = addr-len;
+ }
+ }
+
+ if (unlikely(mm->mmap_base < len))
+ goto bottomup;
+
+ addr = mm->mmap_base-len;
if (do_color_align)
- addr = COLOUR_ALIGN(addr, pgoff);
+ addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+
+ do {
+ /*
+ * Lookup failure means no vma is above this address,
+ * else if new region fits below vma->vm_start,
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+ if (likely(!vma || addr+len <= vma->vm_start)) {
+ /* remember the address as a hint for next time */
+ return mm->free_area_cache = addr;
+ }
+
+ /* remember the largest hole we saw so far */
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+ addr = vma->vm_start-len;
+ if (do_color_align)
+ addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+ } while (likely(len < vma->vm_start));
+
+bottomup:
+ /*
+ * A failed mmap() very likely causes application failure,
+ * so fall back to the bottom-up function here. This scenario
+ * can happen with large stack limits and large mmap()
+ * allocations.
+ */
+ mm->cached_hole_size = ~0UL;
+ mm->free_area_cache = TASK_UNMAPPED_BASE;
+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+ /*
+ * Restore the topdown base:
+ */
+ mm->free_area_cache = mm->mmap_base;
+ mm->cached_hole_size = ~0UL;
+
+ return addr;
}
}
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ return arch_get_unmapped_area_foo(filp,
+ addr0, len, pgoff, flags, UP);
+}
+
+/*
+ * There is no need to export this but sched.h declares the function as
+ * extern so making it static here results in an error.
+ */
+unsigned long arch_get_unmapped_area_topdown(struct file *filp,
+ unsigned long addr0, unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ return arch_get_unmapped_area_foo(filp,
+ addr0, len, pgoff, flags, DOWN);
+}
+
void arch_pick_mmap_layout(struct mm_struct *mm)
{
unsigned long random_factor = 0UL;
@@ -89,9 +230,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
random_factor &= 0xffffffful;
}
- mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
- mm->get_unmapped_area = arch_get_unmapped_area;
- mm->unmap_area = arch_unmap_area;
+ if (mmap_is_legacy()) {
+ mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+ mm->mmap_base = mmap_base(random_factor);
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
}
static inline unsigned long brk_rnd(void)
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
index 575e4019227b..adc6911ba748 100644
--- a/arch/mips/mm/pgtable-32.c
+++ b/arch/mips/mm/pgtable-32.c
@@ -52,7 +52,7 @@ void __init pagetable_init(void)
* Fixed mappings:
*/
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
- fixrange_init(vaddr, 0, pgd_base);
+ fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
#ifdef CONFIG_HIGHMEM
/*
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
index 78eaa4f0b0ec..cda4e300eb0a 100644
--- a/arch/mips/mm/pgtable-64.c
+++ b/arch/mips/mm/pgtable-64.c
@@ -76,5 +76,5 @@ void __init pagetable_init(void)
* Fixed mappings:
*/
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
- fixrange_init(vaddr, 0, pgd_base);
+ fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 424ed4b92e6d..b6e1cff50667 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -42,6 +42,18 @@
extern void tlb_do_page_fault_0(void);
extern void tlb_do_page_fault_1(void);
+struct work_registers {
+ int r1;
+ int r2;
+ int r3;
+};
+
+struct tlb_reg_save {
+ unsigned long a;
+ unsigned long b;
+} ____cacheline_aligned_in_smp;
+
+static struct tlb_reg_save handler_reg_save[NR_CPUS];
static inline int r45k_bvahwbug(void)
{
@@ -248,6 +260,73 @@ static int scratch_reg __cpuinitdata;
static int pgd_reg __cpuinitdata;
enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch};
+static struct work_registers __cpuinit build_get_work_registers(u32 **p)
+{
+ struct work_registers r;
+
+ int smp_processor_id_reg;
+ int smp_processor_id_sel;
+ int smp_processor_id_shift;
+
+ if (scratch_reg > 0) {
+ /* Save in CPU local C0_KScratch? */
+ UASM_i_MTC0(p, 1, 31, scratch_reg);
+ r.r1 = K0;
+ r.r2 = K1;
+ r.r3 = 1;
+ return r;
+ }
+
+ if (num_possible_cpus() > 1) {
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+ smp_processor_id_shift = 51;
+ smp_processor_id_reg = 20; /* XContext */
+ smp_processor_id_sel = 0;
+#else
+# ifdef CONFIG_32BIT
+ smp_processor_id_shift = 25;
+ smp_processor_id_reg = 4; /* Context */
+ smp_processor_id_sel = 0;
+# endif
+# ifdef CONFIG_64BIT
+ smp_processor_id_shift = 26;
+ smp_processor_id_reg = 4; /* Context */
+ smp_processor_id_sel = 0;
+# endif
+#endif
+ /* Get smp_processor_id */
+ UASM_i_MFC0(p, K0, smp_processor_id_reg, smp_processor_id_sel);
+ UASM_i_SRL_SAFE(p, K0, K0, smp_processor_id_shift);
+
+ /* handler_reg_save index in K0 */
+ UASM_i_SLL(p, K0, K0, ilog2(sizeof(struct tlb_reg_save)));
+
+ UASM_i_LA(p, K1, (long)&handler_reg_save);
+ UASM_i_ADDU(p, K0, K0, K1);
+ } else {
+ UASM_i_LA(p, K0, (long)&handler_reg_save);
+ }
+ /* K0 now points to save area, save $1 and $2 */
+ UASM_i_SW(p, 1, offsetof(struct tlb_reg_save, a), K0);
+ UASM_i_SW(p, 2, offsetof(struct tlb_reg_save, b), K0);
+
+ r.r1 = K1;
+ r.r2 = 1;
+ r.r3 = 2;
+ return r;
+}
+
+static void __cpuinit build_restore_work_registers(u32 **p)
+{
+ if (scratch_reg > 0) {
+ UASM_i_MFC0(p, 1, 31, scratch_reg);
+ return;
+ }
+ /* K0 already points to save area, restore $1 and $2 */
+ UASM_i_LW(p, 1, offsetof(struct tlb_reg_save, a), K0);
+ UASM_i_LW(p, 2, offsetof(struct tlb_reg_save, b), K0);
+}
+
#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
/*
@@ -1160,9 +1239,6 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
memset(relocs, 0, sizeof(relocs));
memset(final_handler, 0, sizeof(final_handler));
- if (scratch_reg == 0)
- scratch_reg = allocate_kscratch();
-
if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) {
htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
scratch_reg);
@@ -1462,22 +1538,28 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
*/
static void __cpuinit
build_pte_present(u32 **p, struct uasm_reloc **r,
- unsigned int pte, unsigned int ptr, enum label_id lid)
+ int pte, int ptr, int scratch, enum label_id lid)
{
+ int t = scratch >= 0 ? scratch : pte;
+
if (kernel_uses_smartmips_rixi) {
if (use_bbit_insns()) {
uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
uasm_i_nop(p);
} else {
- uasm_i_andi(p, pte, pte, _PAGE_PRESENT);
- uasm_il_beqz(p, r, pte, lid);
- iPTE_LW(p, pte, ptr);
+ uasm_i_andi(p, t, pte, _PAGE_PRESENT);
+ uasm_il_beqz(p, r, t, lid);
+ if (pte == t)
+ /* You lose the SMP race :-(*/
+ iPTE_LW(p, pte, ptr);
}
} else {
- uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
- uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
- uasm_il_bnez(p, r, pte, lid);
- iPTE_LW(p, pte, ptr);
+ uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_READ);
+ uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_READ);
+ uasm_il_bnez(p, r, t, lid);
+ if (pte == t)
+ /* You lose the SMP race :-(*/
+ iPTE_LW(p, pte, ptr);
}
}
@@ -1497,19 +1579,19 @@ build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte,
*/
static void __cpuinit
build_pte_writable(u32 **p, struct uasm_reloc **r,
- unsigned int pte, unsigned int ptr, enum label_id lid)
+ unsigned int pte, unsigned int ptr, int scratch,
+ enum label_id lid)
{
- if (use_bbit_insns()) {
- uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
- uasm_i_nop(p);
- uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
- uasm_i_nop(p);
- } else {
- uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
- uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
- uasm_il_bnez(p, r, pte, lid);
+ int t = scratch >= 0 ? scratch : pte;
+
+ uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_WRITE);
+ uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_WRITE);
+ uasm_il_bnez(p, r, t, lid);
+ if (pte == t)
+ /* You lose the SMP race :-(*/
iPTE_LW(p, pte, ptr);
- }
+ else
+ uasm_i_nop(p);
}
/* Make PTE writable, update software status bits as well, then store
@@ -1531,15 +1613,19 @@ build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte,
*/
static void __cpuinit
build_pte_modifiable(u32 **p, struct uasm_reloc **r,
- unsigned int pte, unsigned int ptr, enum label_id lid)
+ unsigned int pte, unsigned int ptr, int scratch,
+ enum label_id lid)
{
if (use_bbit_insns()) {
uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
uasm_i_nop(p);
} else {
- uasm_i_andi(p, pte, pte, _PAGE_WRITE);
- uasm_il_beqz(p, r, pte, lid);
- iPTE_LW(p, pte, ptr);
+ int t = scratch >= 0 ? scratch : pte;
+ uasm_i_andi(p, t, pte, _PAGE_WRITE);
+ uasm_il_beqz(p, r, t, lid);
+ if (pte == t)
+ /* You lose the SMP race :-(*/
+ iPTE_LW(p, pte, ptr);
}
}
@@ -1619,7 +1705,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
memset(relocs, 0, sizeof(relocs));
build_r3000_tlbchange_handler_head(&p, K0, K1);
- build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+ build_pte_present(&p, &r, K0, K1, -1, label_nopage_tlbl);
uasm_i_nop(&p); /* load delay */
build_make_valid(&p, &r, K0, K1);
build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1649,7 +1735,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
memset(relocs, 0, sizeof(relocs));
build_r3000_tlbchange_handler_head(&p, K0, K1);
- build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+ build_pte_writable(&p, &r, K0, K1, -1, label_nopage_tlbs);
uasm_i_nop(&p); /* load delay */
build_make_write(&p, &r, K0, K1);
build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1673,13 +1759,14 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
u32 *p = handle_tlbm;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
+ struct work_registers wr;
memset(handle_tlbm, 0, sizeof(handle_tlbm));
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
build_r3000_tlbchange_handler_head(&p, K0, K1);
- build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+ build_pte_modifiable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbm);
uasm_i_nop(&p); /* load delay */
build_make_write(&p, &r, K0, K1);
build_r3000_pte_reload_tlbwi(&p, K0, K1);
@@ -1702,15 +1789,16 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
/*
* R4000 style TLB load/store/modify handlers.
*/
-static void __cpuinit
+static struct work_registers __cpuinit
build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
- struct uasm_reloc **r, unsigned int pte,
- unsigned int ptr)
+ struct uasm_reloc **r)
{
+ struct work_registers wr = build_get_work_registers(p);
+
#ifdef CONFIG_64BIT
- build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
+ build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
#else
- build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
+ build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */
#endif
#ifdef CONFIG_HUGETLB_PAGE
@@ -1719,21 +1807,22 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
* instead contains the tlb pte. Check the PAGE_HUGE bit and
* see if we need to jump to huge tlb processing.
*/
- build_is_huge_pte(p, r, pte, ptr, label_tlb_huge_update);
+ build_is_huge_pte(p, r, wr.r1, wr.r2, label_tlb_huge_update);
#endif
- UASM_i_MFC0(p, pte, C0_BADVADDR);
- UASM_i_LW(p, ptr, 0, ptr);
- UASM_i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
- uasm_i_andi(p, pte, pte, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
- UASM_i_ADDU(p, ptr, ptr, pte);
+ UASM_i_MFC0(p, wr.r1, C0_BADVADDR);
+ UASM_i_LW(p, wr.r2, 0, wr.r2);
+ UASM_i_SRL(p, wr.r1, wr.r1, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
+ uasm_i_andi(p, wr.r1, wr.r1, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
+ UASM_i_ADDU(p, wr.r2, wr.r2, wr.r1);
#ifdef CONFIG_SMP
uasm_l_smp_pgtable_change(l, *p);
#endif
- iPTE_LW(p, pte, ptr); /* get even pte */
+ iPTE_LW(p, wr.r1, wr.r2); /* get even pte */
if (!m4kc_tlbp_war())
build_tlb_probe_entry(p);
+ return wr;
}
static void __cpuinit
@@ -1746,6 +1835,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
build_update_entries(p, tmp, ptr);
build_tlb_write_entry(p, l, r, tlb_indexed);
uasm_l_leave(l, *p);
+ build_restore_work_registers(p);
uasm_i_eret(p); /* return from trap */
#ifdef CONFIG_64BIT
@@ -1758,6 +1848,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
u32 *p = handle_tlbl;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
+ struct work_registers wr;
memset(handle_tlbl, 0, sizeof(handle_tlbl));
memset(labels, 0, sizeof(labels));
@@ -1777,8 +1868,8 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
/* No need for uasm_i_nop */
}
- build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
- build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+ wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+ build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
if (m4kc_tlbp_war())
build_tlb_probe_entry(&p);
@@ -1788,44 +1879,43 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
* have triggered it. Skip the expensive test..
*/
if (use_bbit_insns()) {
- uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+ uasm_il_bbit0(&p, &r, wr.r1, ilog2(_PAGE_VALID),
label_tlbl_goaround1);
} else {
- uasm_i_andi(&p, K0, K0, _PAGE_VALID);
- uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1);
+ uasm_i_andi(&p, wr.r3, wr.r1, _PAGE_VALID);
+ uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround1);
}
uasm_i_nop(&p);
uasm_i_tlbr(&p);
/* Examine entrylo 0 or 1 based on ptr. */
if (use_bbit_insns()) {
- uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+ uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8);
} else {
- uasm_i_andi(&p, K0, K1, sizeof(pte_t));
- uasm_i_beqz(&p, K0, 8);
+ uasm_i_andi(&p, wr.r3, wr.r2, sizeof(pte_t));
+ uasm_i_beqz(&p, wr.r3, 8);
}
-
- UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
- UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
+ /* load it in the delay slot*/
+ UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO0);
+ /* load it if ptr is odd */
+ UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO1);
/*
- * If the entryLo (now in K0) is valid (bit 1), RI or
+ * If the entryLo (now in wr.r3) is valid (bit 1), RI or
* XI must have triggered it.
*/
if (use_bbit_insns()) {
- uasm_il_bbit1(&p, &r, K0, 1, label_nopage_tlbl);
- /* Reload the PTE value */
- iPTE_LW(&p, K0, K1);
+ uasm_il_bbit1(&p, &r, wr.r3, 1, label_nopage_tlbl);
+ uasm_i_nop(&p);
uasm_l_tlbl_goaround1(&l, p);
} else {
- uasm_i_andi(&p, K0, K0, 2);
- uasm_il_bnez(&p, &r, K0, label_nopage_tlbl);
- uasm_l_tlbl_goaround1(&l, p);
- /* Reload the PTE value */
- iPTE_LW(&p, K0, K1);
+ uasm_i_andi(&p, wr.r3, wr.r3, 2);
+ uasm_il_bnez(&p, &r, wr.r3, label_nopage_tlbl);
+ uasm_i_nop(&p);
}
+ uasm_l_tlbl_goaround1(&l, p);
}
- build_make_valid(&p, &r, K0, K1);
- build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+ build_make_valid(&p, &r, wr.r1, wr.r2);
+ build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
#ifdef CONFIG_HUGETLB_PAGE
/*
@@ -1833,8 +1923,8 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
* spots a huge page.
*/
uasm_l_tlb_huge_update(&l, p);
- iPTE_LW(&p, K0, K1);
- build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+ iPTE_LW(&p, wr.r1, wr.r2);
+ build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
build_tlb_probe_entry(&p);
if (kernel_uses_smartmips_rixi) {
@@ -1843,50 +1933,51 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
* have triggered it. Skip the expensive test..
*/
if (use_bbit_insns()) {
- uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+ uasm_il_bbit0(&p, &r, wr.r1, ilog2(_PAGE_VALID),
label_tlbl_goaround2);
} else {
- uasm_i_andi(&p, K0, K0, _PAGE_VALID);
- uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+ uasm_i_andi(&p, wr.r3, wr.r1, _PAGE_VALID);
+ uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround2);
}
uasm_i_nop(&p);
uasm_i_tlbr(&p);
/* Examine entrylo 0 or 1 based on ptr. */
if (use_bbit_insns()) {
- uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+ uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8);
} else {
- uasm_i_andi(&p, K0, K1, sizeof(pte_t));
- uasm_i_beqz(&p, K0, 8);
+ uasm_i_andi(&p, wr.r3, wr.r2, sizeof(pte_t));
+ uasm_i_beqz(&p, wr.r3, 8);
}
- UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
- UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
+ /* load it in the delay slot*/
+ UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO0);
+ /* load it if ptr is odd */
+ UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO1);
/*
- * If the entryLo (now in K0) is valid (bit 1), RI or
+ * If the entryLo (now in wr.r3) is valid (bit 1), RI or
* XI must have triggered it.
*/
if (use_bbit_insns()) {
- uasm_il_bbit0(&p, &r, K0, 1, label_tlbl_goaround2);
+ uasm_il_bbit0(&p, &r, wr.r3, 1, label_tlbl_goaround2);
} else {
- uasm_i_andi(&p, K0, K0, 2);
- uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+ uasm_i_andi(&p, wr.r3, wr.r3, 2);
+ uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround2);
}
- /* Reload the PTE value */
- iPTE_LW(&p, K0, K1);
/*
* We clobbered C0_PAGEMASK, restore it. On the other branch
* it is restored in build_huge_tlb_write_entry.
*/
- build_restore_pagemask(&p, &r, K0, label_nopage_tlbl, 0);
+ build_restore_pagemask(&p, &r, wr.r3, label_nopage_tlbl, 0);
uasm_l_tlbl_goaround2(&l, p);
}
- uasm_i_ori(&p, K0, K0, (_PAGE_ACCESSED | _PAGE_VALID));
- build_huge_handler_tail(&p, &r, &l, K0, K1);
+ uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID));
+ build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
#endif
uasm_l_nopage_tlbl(&l, p);
+ build_restore_work_registers(&p);
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
uasm_i_nop(&p);
@@ -1905,17 +1996,18 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
u32 *p = handle_tlbs;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
+ struct work_registers wr;
memset(handle_tlbs, 0, sizeof(handle_tlbs));
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
- build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
- build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+ wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+ build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
if (m4kc_tlbp_war())
build_tlb_probe_entry(&p);
- build_make_write(&p, &r, K0, K1);
- build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+ build_make_write(&p, &r, wr.r1, wr.r2);
+ build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
#ifdef CONFIG_HUGETLB_PAGE
/*
@@ -1923,15 +2015,16 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
* build_r4000_tlbchange_handler_head spots a huge page.
*/
uasm_l_tlb_huge_update(&l, p);
- iPTE_LW(&p, K0, K1);
- build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+ iPTE_LW(&p, wr.r1, wr.r2);
+ build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
build_tlb_probe_entry(&p);
- uasm_i_ori(&p, K0, K0,
+ uasm_i_ori(&p, wr.r1, wr.r1,
_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
- build_huge_handler_tail(&p, &r, &l, K0, K1);
+ build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
#endif
uasm_l_nopage_tlbs(&l, p);
+ build_restore_work_registers(&p);
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
uasm_i_nop(&p);
@@ -1950,18 +2043,19 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
u32 *p = handle_tlbm;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
+ struct work_registers wr;
memset(handle_tlbm, 0, sizeof(handle_tlbm));
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
- build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
- build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+ wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+ build_pte_modifiable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbm);
if (m4kc_tlbp_war())
build_tlb_probe_entry(&p);
/* Present and writable bits set, set accessed and dirty bits. */
- build_make_write(&p, &r, K0, K1);
- build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+ build_make_write(&p, &r, wr.r1, wr.r2);
+ build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
#ifdef CONFIG_HUGETLB_PAGE
/*
@@ -1969,15 +2063,16 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
* build_r4000_tlbchange_handler_head spots a huge page.
*/
uasm_l_tlb_huge_update(&l, p);
- iPTE_LW(&p, K0, K1);
- build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+ iPTE_LW(&p, wr.r1, wr.r2);
+ build_pte_modifiable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbm);
build_tlb_probe_entry(&p);
- uasm_i_ori(&p, K0, K0,
+ uasm_i_ori(&p, wr.r1, wr.r1,
_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
- build_huge_handler_tail(&p, &r, &l, K0, K1);
+ build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
#endif
uasm_l_nopage_tlbm(&l, p);
+ build_restore_work_registers(&p);
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
uasm_i_nop(&p);
@@ -2036,6 +2131,7 @@ void __cpuinit build_tlb_refill_handler(void)
default:
if (!run_once) {
+ scratch_reg = allocate_kscratch();
#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
build_r4000_setup_pgd();
#endif
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index 31180c321a1a..4b988b9a30d5 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -28,6 +28,7 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/cacheflush.h>
+#include <asm/smp-ops.h>
#include <asm/traps.h>
#include <asm/gcmpregs.h>
@@ -358,15 +359,14 @@ void __init prom_init(void)
#ifdef CONFIG_SERIAL_8250_CONSOLE
console_config();
#endif
-#ifdef CONFIG_MIPS_CMP
/* Early detection of CMP support */
if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))
- register_smp_ops(&cmp_smp_ops);
- else
-#endif
-#ifdef CONFIG_MIPS_MT_SMP
- register_smp_ops(&vsmp_smp_ops);
-#endif
+ if (!register_cmp_smp_ops())
+ return;
+
+ if (!register_vsmp_smp_ops())
+ return;
+
#ifdef CONFIG_MIPS_MT_SMTC
register_smp_ops(&msmtc_smp_ops);
#endif
diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c
index 49a38b09a488..1efc8c394486 100644
--- a/arch/mips/mti-malta/malta-smtc.c
+++ b/arch/mips/mti-malta/malta-smtc.c
@@ -152,7 +152,7 @@ int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
* runtime code can anyway deal with the null set
*/
printk(KERN_WARNING
- "IRQ affinity leaves no legal CPU for IRQ %d\n", irq);
+ "IRQ affinity leaves no legal CPU for IRQ %d\n", d->irq);
/* Do any generic SMTC IRQ affinity setup */
smtc_set_irq_affinity(d->irq, tmask);
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index 1620b83cd13e..f8ee945ee411 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -19,6 +19,7 @@
*/
#include <linux/types.h>
+#include <linux/i8253.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/sched.h>
@@ -31,7 +32,6 @@
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/hardirq.h>
-#include <asm/i8253.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <asm/cpu.h>
diff --git a/arch/mips/netlogic/Platform b/arch/mips/netlogic/Platform
new file mode 100644
index 000000000000..f87c1640abb5
--- /dev/null
+++ b/arch/mips/netlogic/Platform
@@ -0,0 +1,11 @@
+#
+# NETLOGIC includes
+#
+cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/mach-netlogic
+cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/netlogic
+
+#
+# NETLOGIC XLR/XLS SoC, Simulator and boards
+#
+core-$(CONFIG_NLM_XLR) += arch/mips/netlogic/xlr/
+load-$(CONFIG_NLM_XLR_BOARD) += 0xffffffff84000000
diff --git a/arch/mips/netlogic/xlr/irq.c b/arch/mips/netlogic/xlr/irq.c
index 1446d58e364c..521bb7377eb0 100644
--- a/arch/mips/netlogic/xlr/irq.c
+++ b/arch/mips/netlogic/xlr/irq.c
@@ -209,7 +209,7 @@ void __init init_xlr_irqs(void)
irq_set_chip_and_handler(i, &xlr_pic, handle_level_irq);
else
irq_set_chip_and_handler(i, &nlm_cpu_intr,
- handle_level_irq);
+ handle_percpu_irq);
}
#ifdef CONFIG_SMP
irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
diff --git a/arch/mips/netlogic/xlr/smp.c b/arch/mips/netlogic/xlr/smp.c
index b495a7f1433b..d842bce5c940 100644
--- a/arch/mips/netlogic/xlr/smp.c
+++ b/arch/mips/netlogic/xlr/smp.c
@@ -87,17 +87,7 @@ void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
/* IRQ_IPI_SMP_RESCHEDULE handler */
void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
{
- set_need_resched();
-}
-
-void nlm_common_ipi_handler(int irq, struct pt_regs *regs)
-{
- if (irq == IRQ_IPI_SMP_FUNCTION) {
- smp_call_function_interrupt();
- } else {
- /* Announce that we are for reschduling */
- set_need_resched();
- }
+ scheduler_ipi();
}
/*
@@ -122,6 +112,7 @@ void nlm_smp_finish(void)
#ifdef notyet
nlm_common_msgring_cpu_init();
#endif
+ local_irq_enable();
}
void nlm_cpus_done(void)
diff --git a/arch/mips/nxp/pnx8550/common/setup.c b/arch/mips/nxp/pnx8550/common/setup.c
index 64246c9c875c..71adac323323 100644
--- a/arch/mips/nxp/pnx8550/common/setup.c
+++ b/arch/mips/nxp/pnx8550/common/setup.c
@@ -140,6 +140,4 @@ void __init plat_mem_setup(void)
PNX8XXX_UART_LCR_8BIT;
ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
}
-
- return;
}
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
index 4b9d7044e26c..29f2f13eb31c 100644
--- a/arch/mips/oprofile/Makefile
+++ b/arch/mips/oprofile/Makefile
@@ -8,7 +8,7 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )
-oprofile-y := $(DRIVER_OBJS) common.o
+oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_CPU_MIPS32) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o
diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c
new file mode 100644
index 000000000000..6854ed5097d2
--- /dev/null
+++ b/arch/mips/oprofile/backtrace.c
@@ -0,0 +1,175 @@
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/stacktrace.h>
+#include <linux/stacktrace.h>
+#include <linux/kernel.h>
+#include <asm/sections.h>
+#include <asm/inst.h>
+
+struct stackframe {
+ unsigned long sp;
+ unsigned long pc;
+ unsigned long ra;
+};
+
+static inline int get_mem(unsigned long addr, unsigned long *result)
+{
+ unsigned long *address = (unsigned long *) addr;
+ if (!access_ok(VERIFY_READ, addr, sizeof(unsigned long)))
+ return -1;
+ if (__copy_from_user_inatomic(result, address, sizeof(unsigned long)))
+ return -3;
+ return 0;
+}
+
+/*
+ * These two instruction helpers were taken from process.c
+ */
+static inline int is_ra_save_ins(union mips_instruction *ip)
+{
+ /* sw / sd $ra, offset($sp) */
+ return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op)
+ && ip->i_format.rs == 29 && ip->i_format.rt == 31;
+}
+
+static inline int is_sp_move_ins(union mips_instruction *ip)
+{
+ /* addiu/daddiu sp,sp,-imm */
+ if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
+ return 0;
+ if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op)
+ return 1;
+ return 0;
+}
+
+/*
+ * Looks for specific instructions that mark the end of a function.
+ * This usually means we ran into the code area of the previous function.
+ */
+static inline int is_end_of_function_marker(union mips_instruction *ip)
+{
+ /* jr ra */
+ if (ip->r_format.func == jr_op && ip->r_format.rs == 31)
+ return 1;
+ /* lui gp */
+ if (ip->i_format.opcode == lui_op && ip->i_format.rt == 28)
+ return 1;
+ return 0;
+}
+
+/*
+ * TODO for userspace stack unwinding:
+ * - handle cases where the stack is adjusted inside a function
+ * (generally doesn't happen)
+ * - find optimal value for max_instr_check
+ * - try to find a way to handle leaf functions
+ */
+
+static inline int unwind_user_frame(struct stackframe *old_frame,
+ const unsigned int max_instr_check)
+{
+ struct stackframe new_frame = *old_frame;
+ off_t ra_offset = 0;
+ size_t stack_size = 0;
+ unsigned long addr;
+
+ if (old_frame->pc == 0 || old_frame->sp == 0 || old_frame->ra == 0)
+ return -9;
+
+ for (addr = new_frame.pc; (addr + max_instr_check > new_frame.pc)
+ && (!ra_offset || !stack_size); --addr) {
+ union mips_instruction ip;
+
+ if (get_mem(addr, (unsigned long *) &ip))
+ return -11;
+
+ if (is_sp_move_ins(&ip)) {
+ int stack_adjustment = ip.i_format.simmediate;
+ if (stack_adjustment > 0)
+ /* This marks the end of the previous function,
+ which means we overran. */
+ break;
+ stack_size = (unsigned) stack_adjustment;
+ } else if (is_ra_save_ins(&ip)) {
+ int ra_slot = ip.i_format.simmediate;
+ if (ra_slot < 0)
+ /* This shouldn't happen. */
+ break;
+ ra_offset = ra_slot;
+ } else if (is_end_of_function_marker(&ip))
+ break;
+ }
+
+ if (!ra_offset || !stack_size)
+ return -1;
+
+ if (ra_offset) {
+ new_frame.ra = old_frame->sp + ra_offset;
+ if (get_mem(new_frame.ra, &(new_frame.ra)))
+ return -13;
+ }
+
+ if (stack_size) {
+ new_frame.sp = old_frame->sp + stack_size;
+ if (get_mem(new_frame.sp, &(new_frame.sp)))
+ return -14;
+ }
+
+ if (new_frame.sp > old_frame->sp)
+ return -2;
+
+ new_frame.pc = old_frame->ra;
+ *old_frame = new_frame;
+
+ return 0;
+}
+
+static inline void do_user_backtrace(unsigned long low_addr,
+ struct stackframe *frame,
+ unsigned int depth)
+{
+ const unsigned int max_instr_check = 512;
+ const unsigned long high_addr = low_addr + THREAD_SIZE;
+
+ while (depth-- && !unwind_user_frame(frame, max_instr_check)) {
+ oprofile_add_trace(frame->ra);
+ if (frame->sp < low_addr || frame->sp > high_addr)
+ break;
+ }
+}
+
+#ifndef CONFIG_KALLSYMS
+static inline void do_kernel_backtrace(unsigned long low_addr,
+ struct stackframe *frame,
+ unsigned int depth) { }
+#else
+static inline void do_kernel_backtrace(unsigned long low_addr,
+ struct stackframe *frame,
+ unsigned int depth)
+{
+ while (depth-- && frame->pc) {
+ frame->pc = unwind_stack_by_address(low_addr,
+ &(frame->sp),
+ frame->pc,
+ &(frame->ra));
+ oprofile_add_trace(frame->ra);
+ }
+}
+#endif
+
+void notrace op_mips_backtrace(struct pt_regs *const regs, unsigned int depth)
+{
+ struct stackframe frame = { .sp = regs->regs[29],
+ .pc = regs->cp0_epc,
+ .ra = regs->regs[31] };
+ const int userspace = user_mode(regs);
+ const unsigned long low_addr = ALIGN(frame.sp, THREAD_SIZE);
+
+ if (userspace)
+ do_user_backtrace(low_addr, &frame, depth);
+ else
+ do_kernel_backtrace(low_addr, &frame, depth);
+}
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index f9eb1aba6345..d1f2d4c52d42 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -115,6 +115,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ops->start = op_mips_start;
ops->stop = op_mips_stop;
ops->cpu_type = lmodel->cpu_type;
+ ops->backtrace = op_mips_backtrace;
printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
lmodel->cpu_type);
diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h
index f04b54fb37d1..7c2da27ece04 100644
--- a/arch/mips/oprofile/op_impl.h
+++ b/arch/mips/oprofile/op_impl.h
@@ -36,4 +36,6 @@ struct op_mips_model {
unsigned char num_counters;
};
+void op_mips_backtrace(struct pt_regs * const regs, unsigned int depth);
+
#endif
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
index b7f0fb0210f4..99929cf88419 100644
--- a/arch/mips/pci/ops-nile4.c
+++ b/arch/mips/pci/ops-nile4.c
@@ -4,7 +4,6 @@
#include <asm/bootinfo.h>
#include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
#include <asm/nile4.h>
#define PCI_ACCESS_READ 0
diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c
index f31218e17d3c..764362ce5e40 100644
--- a/arch/mips/pci/pci-rc32434.c
+++ b/arch/mips/pci/pci-rc32434.c
@@ -215,7 +215,7 @@ static int __init rc32434_pci_init(void)
rc32434_pcibridge_init();
io_map_base = ioremap(rc32434_res_pci_io1.start,
- rc32434_res_pci_io1.end - rc32434_res_pci_io1.start + 1);
+ resource_size(&rcrc32434_res_pci_io1));
if (!io_map_base)
return -ENOMEM;
diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c
index 56525711f8b7..444b8d8004ad 100644
--- a/arch/mips/pci/pci-vr41xx.c
+++ b/arch/mips/pci/pci-vr41xx.c
@@ -305,7 +305,7 @@ static int __init vr41xx_pciu_init(void)
struct resource *res = vr41xx_pci_controller.io_resource;
master = setup->master_io;
io_map_base = ioremap(master->bus_base_address,
- res->end - res->start + 1);
+ resource_size(res));
if (!io_map_base)
return -EBUSY;
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
index 2413ea67877e..0abfbe04ffc9 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_setup.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
@@ -228,13 +228,11 @@ void __init prom_init(void)
*/
msp_serial_setup();
-#ifdef CONFIG_MIPS_MT_SMP
- register_smp_ops(&vsmp_smp_ops);
-#endif
-
+ if (register_vsmp_smp_ops()) {
#ifdef CONFIG_MIPS_MT_SMTC
- register_smp_ops(&msp_smtc_smp_ops);
+ register_smp_ops(&msp_smtc_smp_ops);
#endif
+ }
#ifdef CONFIG_PMCTWILED
/*
diff --git a/arch/mips/pnx8550/common/setup.c b/arch/mips/pnx8550/common/setup.c
index 43cb3945fdbf..fccd6b0c6d3f 100644
--- a/arch/mips/pnx8550/common/setup.c
+++ b/arch/mips/pnx8550/common/setup.c
@@ -139,6 +139,4 @@ void __init plat_mem_setup(void)
PNX8XXX_UART_LCR_8BIT;
ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
}
-
- return;
}
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
index e56fa61b3991..bce1872249ba 100644
--- a/arch/mips/powertv/asic/asic_devices.c
+++ b/arch/mips/powertv/asic/asic_devices.c
@@ -394,23 +394,21 @@ void __init platform_alloc_bootmem(void)
/* Loop through looking for resources that want a particular address */
for (i = 0; gp_resources[i].flags != 0; i++) {
- int size = gp_resources[i].end - gp_resources[i].start + 1;
+ int size = resource_size(&gp_resources[i]);
if ((gp_resources[i].start != 0) &&
((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
reserve_bootmem(dma_to_phys(gp_resources[i].start),
size, 0);
- total += gp_resources[i].end -
- gp_resources[i].start + 1;
+ total += resource_size(&gp_resources[i]);
pr_info("reserve resource %s at %08x (%u bytes)\n",
gp_resources[i].name, gp_resources[i].start,
- gp_resources[i].end -
- gp_resources[i].start + 1);
+ resource_size(&gp_resources[i]));
}
}
/* Loop through assigning addresses for those that are left */
for (i = 0; gp_resources[i].flags != 0; i++) {
- int size = gp_resources[i].end - gp_resources[i].start + 1;
+ int size = resource_size(&gp_resources[i]);
if ((gp_resources[i].start == 0) &&
((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
void *mem = alloc_bootmem_pages(size);
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 041fc1afc3f4..a969eb826634 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -251,28 +251,22 @@ static struct platform_device *rb532_devs[] = {
static void __init parse_mac_addr(char *macstr)
{
- int i, j;
- unsigned char result, value;
+ int i, h, l;
for (i = 0; i < 6; i++) {
- result = 0;
-
if (i != 5 && *(macstr + 2) != ':')
return;
- for (j = 0; j < 2; j++) {
- if (isxdigit(*macstr)
- && (value =
- isdigit(*macstr) ? *macstr -
- '0' : toupper(*macstr) - 'A' + 10) < 16) {
- result = result * 16 + value;
- macstr++;
- } else
- return;
- }
+ h = hex_to_bin(*macstr++);
+ if (h == -1)
+ return;
+
+ l = hex_to_bin(*macstr++);
+ if (l == -1)
+ return;
macstr++;
- korina_dev0_data.mac[i] = result;
+ korina_dev0_data.mac[i] = (h << 4) + l;
}
}
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index 1a94c9894188..607192449335 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -10,6 +10,7 @@
* Copyright (C) 2003, 06 Ralf Baechle (ralf@linux-mips.org)
*/
#include <linux/bcd.h>
+#include <linux/i8253.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kernel.h>
@@ -20,7 +21,6 @@
#include <asm/cpu.h>
#include <asm/mipsregs.h>
-#include <asm/i8253.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/time.h>
diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c
index bc4fa8dd67f3..005c29ed419a 100644
--- a/arch/mips/sgi-ip27/ip27-nmi.c
+++ b/arch/mips/sgi-ip27/ip27-nmi.c
@@ -3,7 +3,7 @@
#include <linux/nodemask.h>
#include <linux/spinlock.h>
#include <linux/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/sn/types.h>
#include <asm/sn/addrs.h>
#include <asm/sn/nmi.h>
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index be4460a5f6a8..76ee045e2ce4 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -123,6 +123,13 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
}
#endif
+static void disable_sb1250_irq(struct irq_data *d)
+{
+ unsigned int irq = d->irq;
+
+ sb1250_mask_irq(sb1250_irq_owner[irq], irq);
+}
+
static void enable_sb1250_irq(struct irq_data *d)
{
unsigned int irq = d->irq;
@@ -180,6 +187,7 @@ static struct irq_chip sb1250_irq_type = {
.name = "SB1250-IMR",
.irq_mask_ack = ack_sb1250_irq,
.irq_unmask = enable_sb1250_irq,
+ .irq_mask = disable_sb1250_irq,
#ifdef CONFIG_SMP
.irq_set_affinity = sb1250_set_affinity
#endif
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 0904d4d30cb3..ec0be14996a4 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -1,11 +1,11 @@
#include <linux/types.h>
+#include <linux/i8253.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/time.h>
#include <linux/clockchips.h>
-#include <asm/i8253.h>
#include <asm/sni.h>
#include <asm/time.h>
#include <asm-generic/rtc.h>
diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h
index 9d773a639513..b9a8f8461262 100644
--- a/arch/mn10300/include/asm/atomic.h
+++ b/arch/mn10300/include/asm/atomic.h
@@ -260,16 +260,15 @@ static inline void atomic_dec(atomic_t *v)
#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
-#define atomic_add_unless(v, a, u) \
+#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 != (u); \
+ c; \
})
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
/**
* atomic_clear_mask - Atomically clear bits in memory
@@ -344,8 +343,6 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *addr)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
-
#endif /* __KERNEL__ */
#endif /* CONFIG_SMP */
#endif /* _ASM_ATOMIC_H */
diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h
index 0939462967e3..596bb2706d81 100644
--- a/arch/mn10300/include/asm/bitops.h
+++ b/arch/mn10300/include/asm/bitops.h
@@ -227,12 +227,7 @@ int ffs(int x)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit((nr), (addr))
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit((nr), (addr))
-
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#include <asm-generic/bitops/le.h>
#endif /* __KERNEL__ */
diff --git a/arch/mn10300/include/asm/mmu_context.h b/arch/mn10300/include/asm/mmu_context.h
index c8f6c82672ad..c67c2b5365a6 100644
--- a/arch/mn10300/include/asm/mmu_context.h
+++ b/arch/mn10300/include/asm/mmu_context.h
@@ -22,7 +22,7 @@
#ifndef _ASM_MMU_CONTEXT_H
#define _ASM_MMU_CONTEXT_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm-generic/mm_hooks.h>
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h
index 4c1b5cc14c19..f7b3c9ab2cb5 100644
--- a/arch/mn10300/include/asm/processor.h
+++ b/arch/mn10300/include/asm/processor.h
@@ -127,7 +127,6 @@ static inline void start_thread(struct pt_regs *regs,
{
struct thread_info *ti = current_thread_info();
struct pt_regs *frame0;
- set_fs(USER_DS);
frame0 = thread_info_to_uregs(ti);
frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h
index b6961811d445..55b79ef10028 100644
--- a/arch/mn10300/include/asm/ptrace.h
+++ b/arch/mn10300/include/asm/ptrace.h
@@ -89,7 +89,6 @@ struct pt_regs {
#define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->sp)
-extern void show_regs(struct pt_regs *);
#define arch_has_single_step() (1)
diff --git a/arch/mn10300/include/asm/spinlock.h b/arch/mn10300/include/asm/spinlock.h
index 93429154e898..1ae580f38933 100644
--- a/arch/mn10300/include/asm/spinlock.h
+++ b/arch/mn10300/include/asm/spinlock.h
@@ -11,7 +11,7 @@
#ifndef _ASM_SPINLOCK_H
#define _ASM_SPINLOCK_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/rwlock.h>
#include <asm/page.h>
diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h
index 8ff3e5aaca41..94b4c5e1491b 100644
--- a/arch/mn10300/include/asm/system.h
+++ b/arch/mn10300/include/asm/system.h
@@ -19,7 +19,7 @@
#include <linux/kernel.h>
#include <linux/irqflags.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#if !defined(CONFIG_LAZY_SAVE_FPU)
struct fpu_state_struct;
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
index c5e12bfd9fcd..a45f0c7549a6 100644
--- a/arch/mn10300/kernel/mn10300-watchdog.c
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -19,7 +19,7 @@
#include <linux/nmi.h>
#include <asm/processor.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/intctl-regs.h>
#include <asm/rtc-regs.h>
#include <asm/div64.h>
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
index 196a111e2e29..216ad23c9570 100644
--- a/arch/mn10300/kernel/module.c
+++ b/arch/mn10300/kernel/module.c
@@ -32,36 +32,6 @@
#define DEBUGP(fmt, ...)
#endif
-/*
- * allocate storage for a module
- */
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc_exec(size);
-}
-
-/*
- * free memory returned from module_alloc()
- */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/*
- * allow the arch to fix up the section table
- * - we don't need anything special
- */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
static void reloc_put16(uint8_t *p, uint32_t val)
{
p[0] = val & 0xff;
@@ -81,20 +51,6 @@ static void reloc_put32(uint8_t *p, uint32_t val)
}
/*
- * apply a REL relocation
- */
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
-
-/*
* apply a RELA relocation
*/
int apply_relocate_add(Elf32_Shdr *sechdrs,
@@ -198,20 +154,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
}
return 0;
}
-
-/*
- * finish loading the module
- */
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-/*
- * finish clearing the module
- */
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index bd3e5e73826e..9220a75a7b43 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -30,7 +30,7 @@
#include <asm/system.h>
#include <linux/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
index eef989c1d0c1..f9bb8cb1c14a 100644
--- a/arch/mn10300/mm/misalignment.c
+++ b/arch/mn10300/mm/misalignment.c
@@ -26,7 +26,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/cpu-regs.h>
diff --git a/arch/mn10300/proc-mn2ws0050/proc-init.c b/arch/mn10300/proc-mn2ws0050/proc-init.c
index c58249b9525a..fe6e24906ffc 100644
--- a/arch/mn10300/proc-mn2ws0050/proc-init.c
+++ b/arch/mn10300/proc-mn2ws0050/proc-init.c
@@ -18,7 +18,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/busctl-regs.h>
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
new file mode 100644
index 000000000000..4558bafbd1a2
--- /dev/null
+++ b/arch/openrisc/Kconfig
@@ -0,0 +1,207 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/config-language.txt.
+#
+
+config OPENRISC
+ def_bool y
+ select OF
+ select OF_EARLY_FLATTREE
+ select HAVE_MEMBLOCK
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select HAVE_ARCH_TRACEHOOK
+ select HAVE_GENERIC_HARDIRQS
+ select GENERIC_IRQ_CHIP
+ select GENERIC_IRQ_PROBE
+ select GENERIC_IRQ_SHOW
+ select GENERIC_IOMAP
+
+config MMU
+ def_bool y
+
+config WISHBONE_BUS_BIG_ENDIAN
+ def_bool y
+
+config SYMBOL_PREFIX
+ string
+ default ""
+
+config HAVE_DMA_ATTRS
+ def_bool y
+
+config UID16
+ def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+ def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+ def_bool n
+
+config GENERIC_HWEIGHT
+ def_bool y
+
+config GENERIC_IOMAP
+ def_bool y
+
+config NO_IOPORT
+ def_bool y
+
+config GENERIC_GPIO
+ def_bool y
+
+config GENERIC_CLOCKEVENTS
+ def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+ def_bool y
+
+# For now, use generic checksum functions
+#These can be reimplemented in assembly later if so inclined
+config GENERIC_CSUM
+ def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+ def_bool y
+
+source "init/Kconfig"
+
+
+menu "Processor type and features"
+
+choice
+ prompt "Subarchitecture"
+ default OR1K_1200
+
+config OR1K_1200
+ bool "OR1200"
+ help
+ Generic OpenRISC 1200 architecture
+
+endchoice
+
+config OPENRISC_BUILTIN_DTB
+ string "Builtin DTB"
+ default ""
+
+menu "Class II Instructions"
+
+config OPENRISC_HAVE_INST_FF1
+ bool "Have instruction l.ff1"
+ default y
+ help
+ Select this if your implementation has the Class II instruction l.ff1
+
+config OPENRISC_HAVE_INST_FL1
+ bool "Have instruction l.fl1"
+ default y
+ help
+ Select this if your implementation has the Class II instruction l.fl1
+
+config OPENRISC_HAVE_INST_MUL
+ bool "Have instruction l.mul for hardware multiply"
+ default y
+ help
+ Select this if your implementation has a hardware multiply instruction
+
+config OPENRISC_HAVE_INST_DIV
+ bool "Have instruction l.div for hardware divide"
+ default y
+ help
+ Select this if your implementation has a hardware divide instruction
+endmenu
+
+
+source "kernel/time/Kconfig"
+source kernel/Kconfig.hz
+source kernel/Kconfig.preempt
+source "mm/Kconfig"
+
+config OPENRISC_NO_SPR_SR_DSX
+ bool "use SPR_SR_DSX software emulation" if OR1K_1200
+ default y
+ help
+ SPR_SR_DSX bit is status register bit indicating whether
+ the last exception has happened in delay slot.
+
+ OpenRISC architecture makes it optional to have it implemented
+ in hardware and the OR1200 does not have it.
+
+ Say N here if you know that your OpenRISC processor has
+ SPR_SR_DSX bit implemented. Say Y if you are unsure.
+
+config CMDLINE
+ string "Default kernel command string"
+ default ""
+ help
+ On some architectures there is currently no way for the boot loader
+ to pass arguments to the kernel. For these architectures, you should
+ supply some command-line options at build time by entering them
+ here.
+
+menu "Debugging options"
+
+config DEBUG_STACKOVERFLOW
+ bool "Check for kernel stack overflow"
+ default y
+ help
+ Make extra checks for space avaliable on stack in some
+ critical functions. This will cause kernel to run a bit slower,
+ but will catch most of kernel stack overruns and exit gracefuly.
+
+ Say Y if you are unsure.
+
+config JUMP_UPON_UNHANDLED_EXCEPTION
+ bool "Try to die gracefully"
+ default y
+ help
+ Now this puts kernel into infinite loop after first oops. Till
+ your kernel crashes this doesn't have any influence.
+
+ Say Y if you are unsure.
+
+config OPENRISC_EXCEPTION_DEBUG
+ bool "Print processor state at each exception"
+ default n
+ help
+ This option will make your kernel unusable for all but kernel
+ debugging.
+
+ Say N if you are unsure.
+
+config OPENRISC_ESR_EXCEPTION_BUG_CHECK
+ bool "Check for possible ESR exception bug"
+ default n
+ help
+ This option enables some checks that might expose some problems
+ in kernel.
+
+ Say N if you are unsure.
+
+endmenu
+
+endmenu
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile
new file mode 100644
index 000000000000..158ae4c0dc6c
--- /dev/null
+++ b/arch/openrisc/Makefile
@@ -0,0 +1,55 @@
+# BK Id: %F% %I% %G% %U% %#%
+#
+# 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 Linus Torvalds
+# Modifications for the OpenRISC architecture:
+# Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+# Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+#
+# Based on:
+# arch/i386/Makefile
+
+KBUILD_DEFCONFIG := or1ksim_defconfig
+
+LDFLAGS :=
+OBJCOPYFLAGS := -O binary -R .note -R .comment -S
+LDFLAGS_vmlinux :=
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+
+KBUILD_CFLAGS += -pipe -ffixed-r10
+
+ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y)
+ KBUILD_CFLAGS += $(call cc-option,-mhard-mul)
+else
+ KBUILD_CFLAGS += $(call cc-option,-msoft-mul)
+endif
+
+ifeq ($(CONFIG_OPENRISC_HAVE_INST_DIV),y)
+ KBUILD_CFLAGS += $(call cc-option,-mhard-div)
+else
+ KBUILD_CFLAGS += $(call cc-option,-msoft-div)
+endif
+
+head-y := arch/openrisc/kernel/head.o arch/openrisc/kernel/init_task.o
+
+core-y += arch/openrisc/lib/ \
+ arch/openrisc/kernel/ \
+ arch/openrisc/mm/
+libs-y += $(LIBGCC)
+
+ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
+BUILTIN_DTB := y
+else
+BUILTIN_DTB := n
+endif
+core-$(BUILTIN_DTB) += arch/openrisc/boot/
+
+all: vmlinux
diff --git a/arch/openrisc/README.openrisc b/arch/openrisc/README.openrisc
new file mode 100644
index 000000000000..c9f7edf2b9a2
--- /dev/null
+++ b/arch/openrisc/README.openrisc
@@ -0,0 +1,99 @@
+OpenRISC Linux
+==============
+
+This is a port of Linux to the OpenRISC class of microprocessors; the initial
+target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
+
+For information about OpenRISC processors and ongoing development:
+
+ website http://openrisc.net
+
+For more information about Linux on OpenRISC, please contact South Pole AB.
+
+ email: info@southpole.se
+
+ website: http://southpole.se
+ http://southpoleconsulting.com
+
+---------------------------------------------------------------------
+
+Build instructions for OpenRISC toolchain and Linux
+===================================================
+
+In order to build and run Linux for OpenRISC, you'll need at least a basic
+toolchain and, perhaps, the architectural simulator. Steps to get these bits
+in place are outlined here.
+
+1) The toolchain can be obtained from openrisc.net. Instructions for building
+a toolchain can be found at:
+
+http://openrisc.net/toolchain-build.html
+
+2) or1ksim (optional)
+
+or1ksim is the architectural simulator which will allow you to actually run
+your OpenRISC Linux kernel if you don't have an OpenRISC processor at hand.
+
+ git clone git://openrisc.net/jonas/or1ksim-svn
+
+ cd or1ksim
+ ./configure --prefix=$OPENRISC_PREFIX
+ make
+ make install
+
+3) Linux kernel
+
+Build the kernel as usual
+
+ make ARCH=openrisc defconfig
+ make ARCH=openrisc
+
+4) Run in architectural simulator
+
+Grab the or1ksim platform configuration file (from the or1ksim source) and
+together with your freshly built vmlinux, run your kernel with the following
+incantation:
+
+ sim -f arch/openrisc/or1ksim.cfg vmlinux
+
+---------------------------------------------------------------------
+
+Terminology
+===========
+
+In the code, the following particles are used on symbols to limit the scope
+to more or less specific processor implementations:
+
+openrisc: the OpenRISC class of processors
+or1k: the OpenRISC 1000 family of processors
+or1200: the OpenRISC 1200 processor
+
+---------------------------------------------------------------------
+
+History
+========
+
+18. 11. 2003 Matjaz Breskvar (phoenix@bsemi.com)
+ initial port of linux to OpenRISC/or32 architecture.
+ all the core stuff is implemented and seams usable.
+
+08. 12. 2003 Matjaz Breskvar (phoenix@bsemi.com)
+ complete change of TLB miss handling.
+ rewrite of exceptions handling.
+ fully functional sash-3.6 in default initrd.
+ a much improved version with changes all around.
+
+10. 04. 2004 Matjaz Breskvar (phoenix@bsemi.com)
+ alot of bugfixes all over.
+ ethernet support, functional http and telnet servers.
+ running many standard linux apps.
+
+26. 06. 2004 Matjaz Breskvar (phoenix@bsemi.com)
+ port to 2.6.x
+
+30. 11. 2004 Matjaz Breskvar (phoenix@bsemi.com)
+ lots of bugfixes and enhancments.
+ added opencores framebuffer driver.
+
+09. 10. 2010 Jonas Bonn (jonas@southpole.se)
+ major rewrite to bring up to par with upstream Linux 2.6.36
diff --git a/arch/openrisc/TODO.openrisc b/arch/openrisc/TODO.openrisc
new file mode 100644
index 000000000000..acfeef9c58e3
--- /dev/null
+++ b/arch/openrisc/TODO.openrisc
@@ -0,0 +1,16 @@
+The OpenRISC Linux port is fully functional and has been tracking upstream
+since 2.6.35. There are, however, remaining items to be completed within
+the coming months. Here's a list of known-to-be-less-than-stellar items
+that are due for investigation shortly, i.e. our TODO list:
+
+-- Implement the rest of the DMA API... dma_map_sg, etc.
+
+-- Consolidate usage of memblock and bootmem... move everything over to
+ memblock.
+
+-- Finish the renaming cleanup... there are references to or32 in the code
+ which was an older name for the architecture. The name we've settled on is
+ or1k and this change is slowly trickling through the stack. For the time
+ being, or32 is equivalent to or1k.
+
+-- Implement optimized version of memcpy and memset
diff --git a/arch/openrisc/boot/Makefile b/arch/openrisc/boot/Makefile
new file mode 100644
index 000000000000..98ca185097a5
--- /dev/null
+++ b/arch/openrisc/boot/Makefile
@@ -0,0 +1,15 @@
+
+
+ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_OPENRISC_BUILTIN_DTB)).dtb.o
+else
+BUILTIN_DTB :=
+endif
+obj-y += $(BUILTIN_DTB)
+
+clean-files := *.dtb.S
+
+#DTC_FLAGS ?= -p 1024
+
+$(obj)/%.dtb: $(src)/dts/%.dts
+ $(call cmd,dtc)
diff --git a/arch/openrisc/boot/dts/or1ksim.dts b/arch/openrisc/boot/dts/or1ksim.dts
new file mode 100644
index 000000000000..5d4f9027afaf
--- /dev/null
+++ b/arch/openrisc/boot/dts/or1ksim.dts
@@ -0,0 +1,50 @@
+/dts-v1/;
+/ {
+ compatible = "opencores,or1ksim";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&pic>;
+
+ chosen {
+ bootargs = "console=uart,mmio,0x90000000,115200";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x02000000>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ compatible = "opencores,or1200-rtlsvn481";
+ reg = <0>;
+ clock-frequency = <20000000>;
+ };
+ };
+
+ /*
+ * OR1K PIC is built into CPU and accessed via special purpose
+ * registers. It is not addressable and, hence, has no 'reg'
+ * property.
+ */
+ pic: pic {
+ compatible = "opencores,or1k-pic";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ serial0: serial@90000000 {
+ compatible = "opencores,uart16550-rtlsvn105", "ns16550a";
+ reg = <0x90000000 0x100>;
+ interrupts = <2>;
+ clock-frequency = <20000000>;
+ };
+
+ enet0: ethoc@92000000 {
+ compatible = "opencores,ethmac-rtlsvn338";
+ reg = <0x92000000 0x100>;
+ interrupts = <4>;
+ };
+};
diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig
new file mode 100644
index 000000000000..ea172bdfa36a
--- /dev/null
+++ b/arch/openrisc/configs/or1ksim_defconfig
@@ -0,0 +1,65 @@
+CONFIG_CROSS_COMPILE="or32-linux-"
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_GZIP is not set
+CONFIG_EXPERT=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_EPOLL is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_MODULES=y
+# CONFIG_BLOCK is not set
+CONFIG_OPENRISC_BUILTIN_DTB="or1ksim"
+CONFIG_NO_HZ=y
+CONFIG_HZ_100=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+# CONFIG_TCP_CONG_WESTWOOD is not set
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_PROC_DEVICETREE=y
+CONFIG_NETDEVICES=y
+CONFIG_MICREL_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_ETHOC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# 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_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
new file mode 100644
index 000000000000..11162e6c878f
--- /dev/null
+++ b/arch/openrisc/include/asm/Kbuild
@@ -0,0 +1,64 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += spr_defs.h
+
+generic-y += atomic.h
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cacheflush.h
+generic-y += checksum.h
+generic-y += cmpxchg.h
+generic-y += cmpxchg-local.h
+generic-y += cpumask.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += module.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 += rmap.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += setup.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += signal.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += stat.h
+generic-y += string.h
+generic-y += swab.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += user.h
diff --git a/arch/openrisc/include/asm/asm-offsets.h b/arch/openrisc/include/asm/asm-offsets.h
new file mode 100644
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/openrisc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
new file mode 100644
index 000000000000..a9e11efae14d
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops.h
@@ -0,0 +1,59 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_BITOPS_H
+#define __ASM_OPENRISC_BITOPS_H
+
+/*
+ * Where we haven't written assembly versions yet, we fall back to the
+ * generic implementations. Otherwise, we pull in our (hopefully)
+ * optimized versions.
+ */
+
+#include <linux/irqflags.h>
+#include <linux/compiler.h>
+
+/*
+ * clear_bit may not imply a memory barrier
+ */
+#ifndef smp_mb__before_clear_bit
+#define smp_mb__before_clear_bit() smp_mb()
+#define smp_mb__after_clear_bit() smp_mb()
+#endif
+
+#include <asm/bitops/__ffs.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm/bitops/fls.h>
+#include <asm/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <asm-generic/bitops/sched.h>
+#include <asm/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+
+#include <asm-generic/bitops/atomic.h>
+#include <asm-generic/bitops/non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __ASM_GENERIC_BITOPS_H */
diff --git a/arch/openrisc/include/asm/bitops/__ffs.h b/arch/openrisc/include/asm/bitops/__ffs.h
new file mode 100644
index 000000000000..6c8368a34059
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/__ffs.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC___FFS_H
+#define __ASM_OPENRISC___FFS_H
+
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
+
+static inline unsigned long __ffs(unsigned long x)
+{
+ int ret;
+
+ __asm__ ("l.ff1 %0,%1"
+ : "=r" (ret)
+ : "r" (x));
+
+ return ret-1;
+}
+
+#else
+#include <asm-generic/bitops/__ffs.h>
+#endif
+
+#endif /* __ASM_OPENRISC___FFS_H */
diff --git a/arch/openrisc/include/asm/bitops/__fls.h b/arch/openrisc/include/asm/bitops/__fls.h
new file mode 100644
index 000000000000..c4ecdb4c523b
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/__fls.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC___FLS_H
+#define __ASM_OPENRISC___FLS_H
+
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
+
+static inline unsigned long __fls(unsigned long x)
+{
+ int ret;
+
+ __asm__ ("l.fl1 %0,%1"
+ : "=r" (ret)
+ : "r" (x));
+
+ return ret-1;
+}
+
+#else
+#include <asm-generic/bitops/__fls.h>
+#endif
+
+#endif /* __ASM_OPENRISC___FLS_H */
diff --git a/arch/openrisc/include/asm/bitops/ffs.h b/arch/openrisc/include/asm/bitops/ffs.h
new file mode 100644
index 000000000000..9de46246ebc7
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/ffs.h
@@ -0,0 +1,32 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_FFS_H
+#define __ASM_OPENRISC_FFS_H
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
+
+static inline int ffs(int x)
+{
+ int ret;
+
+ __asm__ ("l.ff1 %0,%1"
+ : "=r" (ret)
+ : "r" (x));
+
+ return ret;
+}
+
+#else
+#include <asm-generic/bitops/ffs.h>
+#endif
+
+#endif /* __ASM_OPENRISC_FFS_H */
diff --git a/arch/openrisc/include/asm/bitops/fls.h b/arch/openrisc/include/asm/bitops/fls.h
new file mode 100644
index 000000000000..9efbf9ad86c4
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/fls.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_FLS_H
+#define __ASM_OPENRISC_FLS_H
+
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
+
+static inline int fls(int x)
+{
+ int ret;
+
+ __asm__ ("l.fl1 %0,%1"
+ : "=r" (ret)
+ : "r" (x));
+
+ return ret;
+}
+
+#else
+#include <asm-generic/bitops/fls.h>
+#endif
+
+#endif /* __ASM_OPENRISC_FLS_H */
diff --git a/arch/openrisc/include/asm/byteorder.h b/arch/openrisc/include/asm/byteorder.h
new file mode 100644
index 000000000000..60d14f7e14e2
--- /dev/null
+++ b/arch/openrisc/include/asm/byteorder.h
@@ -0,0 +1 @@
+#include <linux/byteorder/big_endian.h>
diff --git a/arch/openrisc/include/asm/cache.h b/arch/openrisc/include/asm/cache.h
new file mode 100644
index 000000000000..4ce7a01a252d
--- /dev/null
+++ b/arch/openrisc/include/asm/cache.h
@@ -0,0 +1,29 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_CACHE_H
+#define __ASM_OPENRISC_CACHE_H
+
+/* FIXME: How can we replace these with values from the CPU...
+ * they shouldn't be hard-coded!
+ */
+
+#define L1_CACHE_BYTES 16
+#define L1_CACHE_SHIFT 4
+
+#endif /* __ASM_OPENRISC_CACHE_H */
diff --git a/arch/openrisc/include/asm/cpuinfo.h b/arch/openrisc/include/asm/cpuinfo.h
new file mode 100644
index 000000000000..917318b6a970
--- /dev/null
+++ b/arch/openrisc/include/asm/cpuinfo.h
@@ -0,0 +1,34 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_CPUINFO_H
+#define __ASM_OPENRISC_CPUINFO_H
+
+struct cpuinfo {
+ u32 clock_frequency;
+
+ u32 icache_size;
+ u32 icache_block_size;
+
+ u32 dcache_size;
+ u32 dcache_block_size;
+};
+
+extern struct cpuinfo cpuinfo;
+
+#endif /* __ASM_OPENRISC_CPUINFO_H */
diff --git a/arch/openrisc/include/asm/delay.h b/arch/openrisc/include/asm/delay.h
new file mode 100644
index 000000000000..17f8bf5a5ac2
--- /dev/null
+++ b/arch/openrisc/include/asm/delay.h
@@ -0,0 +1,24 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_DELAY_H
+#define __ASM_OPENRISC_DELAY_H
+
+#include <asm-generic/delay.h>
+
+extern unsigned long loops_per_jiffy;
+
+#endif
diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h
new file mode 100644
index 000000000000..052f877b52a5
--- /dev/null
+++ b/arch/openrisc/include/asm/dma-mapping.h
@@ -0,0 +1,134 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_DMA_MAPPING_H
+#define __ASM_OPENRISC_DMA_MAPPING_H
+
+/*
+ * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * Documentation/DMA-API.txt for documentation.
+ *
+ * This file is written with the intention of eventually moving over
+ * to largely using asm-generic/dma-mapping-common.h in its place.
+ */
+
+#include <linux/dma-debug.h>
+#include <asm-generic/dma-coherent.h>
+#include <linux/kmemcheck.h>
+
+#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
+
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
+
+#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)
+
+void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag);
+void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle);
+dma_addr_t or1k_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+void or1k_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir);
+void or1k_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir);
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ void *memory;
+
+ memory = or1k_dma_alloc_coherent(dev, size, dma_handle, flag);
+
+ debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
+ return memory;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+ or1k_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+static inline dma_addr_t dma_map_single(struct device *dev, void *ptr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ dma_addr_t addr;
+
+ kmemcheck_mark_initialized(ptr, size);
+ BUG_ON(!valid_dma_direction(dir));
+ addr = or1k_map_page(dev, virt_to_page(ptr),
+ (unsigned long)ptr & ~PAGE_MASK, size,
+ dir, NULL);
+ debug_dma_map_page(dev, virt_to_page(ptr),
+ (unsigned long)ptr & ~PAGE_MASK, size,
+ dir, addr, true);
+ return addr;
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ BUG_ON(!valid_dma_direction(dir));
+ or1k_unmap_page(dev, addr, size, dir, NULL);
+ debug_dma_unmap_page(dev, addr, size, dir, true);
+}
+
+static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ BUG_ON(!valid_dma_direction(dir));
+ or1k_sync_single_for_cpu(dev, addr, size, dir);
+ debug_dma_sync_single_for_cpu(dev, addr, size, dir);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+ dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ BUG_ON(!valid_dma_direction(dir));
+ or1k_sync_single_for_device(dev, addr, size, dir);
+ debug_dma_sync_single_for_device(dev, addr, size, dir);
+}
+
+static inline int dma_supported(struct device *dev, u64 dma_mask)
+{
+ /* Support 32 bit DMA mask exclusively */
+ return dma_mask == 0xffffffffULL;
+}
+
+static inline int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+ return -EIO;
+
+ *dev->dma_mask = dma_mask;
+
+ return 0;
+}
+#endif /* __ASM_OPENRISC_DMA_MAPPING_H */
diff --git a/arch/openrisc/include/asm/elf.h b/arch/openrisc/include/asm/elf.h
new file mode 100644
index 000000000000..2ce603bbfdd3
--- /dev/null
+++ b/arch/openrisc/include/asm/elf.h
@@ -0,0 +1,108 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_ELF_H
+#define __ASM_OPENRISC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+
+/* The OR1K relocation types... not all relevant for module loader */
+#define R_OR32_NONE 0
+#define R_OR32_32 1
+#define R_OR32_16 2
+#define R_OR32_8 3
+#define R_OR32_CONST 4
+#define R_OR32_CONSTH 5
+#define R_OR32_JUMPTARG 6
+#define R_OR32_VTINHERIT 7
+#define R_OR32_VTENTRY 8
+
+typedef unsigned long elf_greg_t;
+
+/*
+ * Note that NGREG is defined to ELF_NGREG in include/linux/elfcore.h, and is
+ * thus exposed to user-space.
+ */
+#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* A placeholder; OR32 does not have fp support yes, so no fp regs for now. */
+typedef unsigned long elf_fpregset_t;
+
+/* This should be moved to include/linux/elf.h */
+#define EM_OR32 0x8472
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH EM_OR32
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2MSB
+
+#ifdef __KERNEL__
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+
+#define elf_check_arch(x) \
+ (((x)->e_machine == EM_OR32) || ((x)->e_machine == EM_OPENRISC))
+
+/* 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 (0x08000000)
+
+/*
+ * Enable dump using regset.
+ * This covers all of general/DSP/FPU regs.
+ */
+#define CORE_DUMP_USE_REGSET
+
+#define ELF_EXEC_PAGESIZE 8192
+
+extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt);
+#define ELF_CORE_COPY_REGS(dest, regs) dump_elf_thread(dest, regs);
+
+/* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This could be done in userspace,
+ but it's not easy, and we've already done it here. */
+
+#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.
+
+ For the moment, we have only optimizations for the Intel generations,
+ but that could change... */
+
+#define ELF_PLATFORM (NULL)
+
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h
new file mode 100644
index 000000000000..52733416c1f3
--- /dev/null
+++ b/arch/openrisc/include/asm/fixmap.h
@@ -0,0 +1,87 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_FIXMAP_H
+#define __ASM_OPENRISC_FIXMAP_H
+
+/* Why exactly do we need 2 empty pages between the top of the fixed
+ * addresses and the top of virtual memory? Something is using that
+ * memory space but not sure what right now... If you find it, leave
+ * a comment here.
+ */
+#define FIXADDR_TOP ((unsigned long) (-2*PAGE_SIZE))
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+
+/*
+ * On OpenRISC we use these special fixed_addresses for doing ioremap
+ * early in the boot process before memory initialization is complete.
+ * This is used, in particular, by the early serial console code.
+ *
+ * It's not really 'fixmap', per se, but fits loosely into the same
+ * paradigm.
+ */
+enum fixed_addresses {
+ /*
+ * FIX_IOREMAP entries are useful for mapping physical address
+ * space before ioremap() is useable, e.g. really early in boot
+ * before kmalloc() is working.
+ */
+#define FIX_N_IOREMAPS 32
+ FIX_IOREMAP_BEGIN,
+ FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
+ __end_of_fixed_addresses
+};
+
+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+/* FIXADDR_BOTTOM might be a better name here... */
+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+
+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without tranlation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static __always_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)
+ BUG();
+
+ 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);
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/gpio.h b/arch/openrisc/include/asm/gpio.h
new file mode 100644
index 000000000000..0b0d174f47cd
--- /dev/null
+++ b/arch/openrisc/include/asm/gpio.h
@@ -0,0 +1,65 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_GPIO_H
+#define __ASM_OPENRISC_GPIO_H
+
+#include <linux/errno.h>
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_GPIOLIB
+
+/*
+ * OpenRISC (or1k) does not have on-chip GPIO's so there is not really
+ * any standardized implementation that makes sense here. If passing
+ * through gpiolib becomes a bottleneck then it may make sense, on a
+ * case-by-case basis, to implement these inlined/rapid versions.
+ *
+ * Just call gpiolib.
+ */
+static inline int gpio_get_value(unsigned int gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+ __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+/*
+ * Not implemented, yet.
+ */
+static inline int gpio_to_irq(unsigned int gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+ return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+#endif /* __ASM_OPENRISC_GPIO_H */
diff --git a/arch/openrisc/include/asm/io.h b/arch/openrisc/include/asm/io.h
new file mode 100644
index 000000000000..07f5299d6c28
--- /dev/null
+++ b/arch/openrisc/include/asm/io.h
@@ -0,0 +1,51 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_IO_H
+#define __ASM_OPENRISC_IO_H
+
+/*
+ * PCI: can we really do 0 here if we have no port IO?
+ */
+#define IO_SPACE_LIMIT 0
+
+/* OpenRISC has no port IO */
+#define HAVE_ARCH_PIO_SIZE 1
+#define PIO_RESERVED 0X0UL
+#define PIO_OFFSET 0
+#define PIO_MASK 0
+
+#include <asm-generic/io.h>
+
+extern void __iomem *__ioremap(phys_addr_t offset, unsigned long size,
+ pgprot_t prot);
+
+static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
+{
+ return __ioremap(offset, size, PAGE_KERNEL);
+}
+
+/* #define _PAGE_CI 0x002 */
+static inline void __iomem *ioremap_nocache(phys_addr_t offset,
+ unsigned long size)
+{
+ return __ioremap(offset, size,
+ __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_CI));
+}
+
+extern void iounmap(void *addr);
+#endif
diff --git a/arch/openrisc/include/asm/irq.h b/arch/openrisc/include/asm/irq.h
new file mode 100644
index 000000000000..eb612b1865d2
--- /dev/null
+++ b/arch/openrisc/include/asm/irq.h
@@ -0,0 +1,27 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_IRQ_H__
+#define __ASM_OPENRISC_IRQ_H__
+
+#define NR_IRQS 32
+#include <asm-generic/irq.h>
+
+#define NO_IRQ (-1)
+
+#endif /* __ASM_OPENRISC_IRQ_H__ */
diff --git a/arch/openrisc/include/asm/irqflags.h b/arch/openrisc/include/asm/irqflags.h
new file mode 100644
index 000000000000..dc86c653d70b
--- /dev/null
+++ b/arch/openrisc/include/asm/irqflags.h
@@ -0,0 +1,29 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_IRQFLAGS_H
+#define ___ASM_OPENRISC_IRQFLAGS_H
+
+#include <asm/spr_defs.h>
+
+#define ARCH_IRQ_DISABLED 0x00
+#define ARCH_IRQ_ENABLED (SPR_SR_IEE|SPR_SR_TEE)
+
+#include <asm-generic/irqflags.h>
+
+#endif /* ___ASM_OPENRISC_IRQFLAGS_H */
diff --git a/arch/openrisc/include/asm/linkage.h b/arch/openrisc/include/asm/linkage.h
new file mode 100644
index 000000000000..e2638752091a
--- /dev/null
+++ b/arch/openrisc/include/asm/linkage.h
@@ -0,0 +1,25 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_LINKAGE_H
+#define __ASM_OPENRISC_LINKAGE_H
+
+#define __ALIGN .align 0
+#define __ALIGN_STR ".align 0"
+
+#endif /* __ASM_OPENRISC_LINKAGE_H */
diff --git a/arch/openrisc/include/asm/memblock.h b/arch/openrisc/include/asm/memblock.h
new file mode 100644
index 000000000000..bbe5a1c788cb
--- /dev/null
+++ b/arch/openrisc/include/asm/memblock.h
@@ -0,0 +1,24 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_MEMBLOCK_H
+#define __ASM_OPENRISC_MEMBLOCK_H
+
+/* empty */
+
+#endif /* __ASM_OPENRISC_MEMBLOCK_H */
diff --git a/arch/openrisc/include/asm/mmu.h b/arch/openrisc/include/asm/mmu.h
new file mode 100644
index 000000000000..d069bc2ddfa4
--- /dev/null
+++ b/arch/openrisc/include/asm/mmu.h
@@ -0,0 +1,26 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_MMU_H
+#define __ASM_OPENRISC_MMU_H
+
+#ifndef __ASSEMBLY__
+typedef unsigned long mm_context_t;
+#endif
+
+#endif
diff --git a/arch/openrisc/include/asm/mmu_context.h b/arch/openrisc/include/asm/mmu_context.h
new file mode 100644
index 000000000000..e94b814d2e3c
--- /dev/null
+++ b/arch/openrisc/include/asm/mmu_context.h
@@ -0,0 +1,43 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_MMU_CONTEXT_H
+#define __ASM_OPENRISC_MMU_CONTEXT_H
+
+#include <asm-generic/mm_hooks.h>
+
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void destroy_context(struct mm_struct *mm);
+extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk);
+
+#define deactivate_mm(tsk, mm) do { } while (0)
+
+#define activate_mm(prev, next) switch_mm((prev), (next), NULL)
+
+/* current active pgd - this is similar to other processors pgd
+ * registers like cr3 on the i386
+ */
+
+extern volatile pgd_t *current_pgd; /* defined in arch/openrisc/mm/fault.c */
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/mutex.h b/arch/openrisc/include/asm/mutex.h
new file mode 100644
index 000000000000..b85a0cfa9fc9
--- /dev/null
+++ b/arch/openrisc/include/asm/mutex.h
@@ -0,0 +1,27 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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.
+ */
+
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h
new file mode 100644
index 000000000000..b041b344b229
--- /dev/null
+++ b/arch/openrisc/include/asm/page.h
@@ -0,0 +1,110 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_PAGE_H
+#define __ASM_OPENRISC_PAGE_H
+
+
+/* PAGE_SHIFT determines the page size */
+
+#define PAGE_SHIFT 13
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#else
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#endif
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#define PAGE_OFFSET 0xc0000000
+#define KERNELBASE PAGE_OFFSET
+
+/* This is not necessarily the right place for this, but it's needed by
+ * drivers/of/fdt.c
+ */
+#include <asm/setup.h>
+
+#ifndef __ASSEMBLY__
+
+#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr) free_page(addr)
+
+#define clear_page(page) memset((page), 0, PAGE_SIZE)
+#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr, pg) clear_page(page)
+#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+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) })
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
+#endif /* !__ASSEMBLY__ */
+
+
+#ifndef __ASSEMBLY__
+
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
+
+#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
+
+#define virt_to_page(addr) \
+ (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
+#define page_to_virt(page) \
+ ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
+
+#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
+
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+
+#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
+ ((void *)(kaddr) < (void *)memory_end))
+
+#endif /* __ASSEMBLY__ */
+
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+
+#include <asm-generic/memory_model.h>
+#include <asm-generic/getorder.h>
+
+#endif /* __ASM_OPENRISC_PAGE_H */
diff --git a/arch/openrisc/include/asm/param.h b/arch/openrisc/include/asm/param.h
new file mode 100644
index 000000000000..c39a336610e2
--- /dev/null
+++ b/arch/openrisc/include/asm/param.h
@@ -0,0 +1,26 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_PARAM_H
+#define __ASM_OPENRISC_PARAM_H
+
+#define EXEC_PAGESIZE 8192
+
+#include <asm-generic/param.h>
+
+#endif /* __ASM_OPENRISC_PARAM_H */
diff --git a/arch/openrisc/include/asm/pgalloc.h b/arch/openrisc/include/asm/pgalloc.h
new file mode 100644
index 000000000000..05c39ecd2efd
--- /dev/null
+++ b/arch/openrisc/include/asm/pgalloc.h
@@ -0,0 +1,102 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_PGALLOC_H
+#define __ASM_OPENRISC_PGALLOC_H
+
+#include <asm/page.h>
+#include <linux/threads.h>
+#include <linux/mm.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+
+extern int mem_init_done;
+
+#define pmd_populate_kernel(mm, pmd, pte) \
+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+ struct page *pte)
+{
+ set_pmd(pmd, __pmd(_KERNPG_TABLE +
+ ((unsigned long)page_to_pfn(pte) <<
+ (unsigned long) PAGE_SHIFT)));
+}
+
+/*
+ * Allocate and free page tables.
+ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+ if (ret) {
+ memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+ memcpy(ret + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+
+ }
+ return ret;
+}
+
+#if 0
+/* FIXME: This seems to be the preferred style, but we are using
+ * current_pgd (from mm->pgd) to load kernel pages so we need it
+ * initialized. This needs to be looked into.
+ */
+extern inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ return (pgd_t *)get_zeroed_page(GFP_KERNEL);
+}
+#endif
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ free_page((unsigned long)pgd);
+}
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address);
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ unsigned long address)
+{
+ struct page *pte;
+ pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+ if (pte)
+ clear_page(page_address(pte));
+ return pte;
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+ free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+ __free_page(pte);
+}
+
+
+#define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#define check_pgt_cache() do { } while (0)
+
+#endif
diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h
new file mode 100644
index 000000000000..043505d7f684
--- /dev/null
+++ b/arch/openrisc/include/asm/pgtable.h
@@ -0,0 +1,463 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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.
+ */
+
+/* or32 pgtable.h - macros and functions to manipulate page tables
+ *
+ * Based on:
+ * include/asm-cris/pgtable.h
+ */
+
+#ifndef __ASM_OPENRISC_PGTABLE_H
+#define __ASM_OPENRISC_PGTABLE_H
+
+#include <asm-generic/pgtable-nopmd.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/mmu.h>
+#include <asm/fixmap.h>
+
+/*
+ * The Linux memory management assumes a three-level page table setup. On
+ * or32, we use that, but "fold" the mid level into the top-level page
+ * table. Since the MMU TLB is software loaded through an interrupt, it
+ * supports any page table structure, so we could have used a three-level
+ * setup, but for the amounts of memory we normally use, a two-level is
+ * probably more efficient.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the or32 page table tree.
+ */
+
+extern void paging_init(void);
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
+/*
+ * (pmds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+
+#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-2))
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: we use a two-level, so
+ * we don't really have any PMD directory physically.
+ * pointers are 4 bytes so we can use the page size and
+ * divide it by 4 (shift by 2).
+ */
+#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-2))
+
+#define PTRS_PER_PGD (1UL << (PAGE_SHIFT-2))
+
+/* calculate how many PGD entries a user-level program can use
+ * the first mappable virtual address is 0
+ * (TASK_SIZE is the maximum virtual address space)
+ */
+
+#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
+#define FIRST_USER_ADDRESS 0
+
+/*
+ * Kernels own virtual memory area.
+ */
+
+/*
+ * The size and location of the vmalloc area are chosen so that modules
+ * placed in this area aren't more than a 28-bit signed offset from any
+ * kernel functions that they may need. This greatly simplifies handling
+ * of the relocations for l.j and l.jal instructions as we don't need to
+ * introduce any trampolines for reaching "distant" code.
+ *
+ * 64 MB of vmalloc area is comparable to what's available on other arches.
+ */
+
+#define VMALLOC_START (PAGE_OFFSET-0x04000000)
+#define VMALLOC_END (PAGE_OFFSET)
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+/* Define some higher level generic page attributes.
+ *
+ * If you change _PAGE_CI definition be sure to change it in
+ * io.h for ioremap_nocache() too.
+ */
+
+/*
+ * An OR32 PTE looks like this:
+ *
+ * | 31 ... 10 | 9 | 8 ... 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * Phys pg.num L PP Index D A WOM WBC CI CC
+ *
+ * L : link
+ * PPI: Page protection index
+ * D : Dirty
+ * A : Accessed
+ * WOM: Weakly ordered memory
+ * WBC: Write-back cache
+ * CI : Cache inhibit
+ * CC : Cache coherent
+ *
+ * The protection bits below should correspond to the layout of the actual
+ * PTE as per above
+ */
+
+#define _PAGE_CC 0x001 /* software: pte contains a translation */
+#define _PAGE_CI 0x002 /* cache inhibit */
+#define _PAGE_WBC 0x004 /* write back cache */
+#define _PAGE_FILE 0x004 /* set: pagecache, unset: swap (when !PRESENT) */
+#define _PAGE_WOM 0x008 /* weakly ordered memory */
+
+#define _PAGE_A 0x010 /* accessed */
+#define _PAGE_D 0x020 /* dirty */
+#define _PAGE_URE 0x040 /* user read enable */
+#define _PAGE_UWE 0x080 /* user write enable */
+
+#define _PAGE_SRE 0x100 /* superuser read enable */
+#define _PAGE_SWE 0x200 /* superuser write enable */
+#define _PAGE_EXEC 0x400 /* software: page is executable */
+#define _PAGE_U_SHARED 0x800 /* software: page is shared in user space */
+
+/* 0x001 is cache coherency bit, which should always be set to
+ * 1 - for SMP (when we support it)
+ * 0 - otherwise
+ *
+ * we just reuse this bit in software for _PAGE_PRESENT and
+ * force it to 0 when loading it into TLB.
+ */
+#define _PAGE_PRESENT _PAGE_CC
+#define _PAGE_USER _PAGE_URE
+#define _PAGE_WRITE (_PAGE_UWE | _PAGE_SWE)
+#define _PAGE_DIRTY _PAGE_D
+#define _PAGE_ACCESSED _PAGE_A
+#define _PAGE_NO_CACHE _PAGE_CI
+#define _PAGE_SHARED _PAGE_U_SHARED
+#define _PAGE_READ (_PAGE_URE | _PAGE_SRE)
+
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
+#define _PAGE_ALL (_PAGE_PRESENT | _PAGE_ACCESSED)
+#define _KERNPG_TABLE \
+ (_PAGE_BASE | _PAGE_SRE | _PAGE_SWE | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define PAGE_NONE __pgprot(_PAGE_ALL)
+#define PAGE_READONLY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
+#define PAGE_READONLY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
+#define PAGE_SHARED \
+ __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
+ | _PAGE_SHARED)
+#define PAGE_SHARED_X \
+ __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
+ | _PAGE_SHARED | _PAGE_EXEC)
+#define PAGE_COPY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
+#define PAGE_COPY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
+
+#define PAGE_KERNEL \
+ __pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
+ | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
+#define PAGE_KERNEL_RO \
+ __pgprot(_PAGE_ALL | _PAGE_SRE \
+ | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
+#define PAGE_KERNEL_NOCACHE \
+ __pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
+ | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC | _PAGE_CI)
+
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY_X
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY_X
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY_X
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY_X
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY_X
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED_X
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY_X
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED_X
+
+/* zero page used for uninitialized stuff */
+extern unsigned long empty_zero_page[2048];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR (8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK (~(sizeof(void *)-1))
+
+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+/* 64-bit machines, beware! SRB. */
+#define SIZEOF_PTR_LOG2 2
+
+/* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+
+/* to set the page-dir */
+#define SET_PAGE_DIR(tsk, pgdir)
+
+#define pte_none(x) (!pte_val(x))
+#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(mm, addr, xp) do { pte_val(*(xp)) = 0; } while (0)
+
+#define pmd_none(x) (!pmd_val(x))
+#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK)) != _KERNPG_TABLE)
+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+#define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+
+static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+ pte_val(pte) &= ~(_PAGE_WRITE);
+ return pte;
+}
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+ pte_val(pte) &= ~(_PAGE_READ);
+ return pte;
+}
+
+static inline pte_t pte_exprotect(pte_t pte)
+{
+ pte_val(pte) &= ~(_PAGE_EXEC);
+ return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+ pte_val(pte) &= ~(_PAGE_DIRTY);
+ return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+ pte_val(pte) &= ~(_PAGE_ACCESSED);
+ return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_WRITE;
+ return pte;
+}
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_READ;
+ return pte;
+}
+
+static inline pte_t pte_mkexec(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_EXEC;
+ return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_DIRTY;
+ return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_ACCESSED;
+ return pte;
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+/* What actually goes as arguments to the various functions is less than
+ * obvious, but a rule of thumb is that struct page's goes as struct page *,
+ * really physical DRAM addresses are unsigned long's, and DRAM "virtual"
+ * addresses (the 0xc0xxxxxx's) goes as void *'s.
+ */
+
+static inline pte_t __mk_pte(void *page, pgprot_t pgprot)
+{
+ pte_t pte;
+ /* the PTE needs a physical address */
+ pte_val(pte) = __pa(page) | pgprot_val(pgprot);
+ return pte;
+}
+
+#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
+
+#define mk_pte_phys(physpage, pgprot) \
+({ \
+ pte_t __pte; \
+ \
+ pte_val(__pte) = (physpage) + pgprot_val(pgprot); \
+ __pte; \
+})
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+ return pte;
+}
+
+
+/*
+ * pte_val refers to a page in the 0x0xxxxxxx physical DRAM interval
+ * __pte_page(pte_val) refers to the "virtual" DRAM interval
+ * pte_pagenr refers to the page-number counted starting from the virtual
+ * DRAM start
+ */
+
+static inline unsigned long __pte_page(pte_t pte)
+{
+ /* the PTE contains a physical address */
+ return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
+}
+
+#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+/* permanent address of a page */
+
+#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pte_page(pte) (mem_map+pte_pagenr(pte))
+
+/*
+ * only the pte's themselves need to point to physical DRAM (see above)
+ * the pagetable links are purely handled within the kernel SW and thus
+ * don't need the __pa and __va transformations.
+ */
+static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
+{
+ pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep;
+}
+
+#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+/* to find an entry in a page-table-directory. */
+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+#define __pgd_offset(address) pgd_index(address)
+
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+#define __pmd_offset(address) \
+ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
+#define __pte_offset(address) \
+ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address) \
+ ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address))
+#define pte_offset_map(dir, address) \
+ ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+#define pte_offset_map_nested(dir, address) \
+ pte_offset_map(dir, address)
+
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
+#define pte_pfn(x) ((unsigned long)(((x).pte)) >> PAGE_SHIFT)
+#define pfn_pte(pfn, prot) __pte((((pfn) << PAGE_SHIFT)) | pgprot_val(prot))
+
+#define pte_ERROR(e) \
+ printk(KERN_ERR "%s:%d: bad pte %p(%08lx).\n", \
+ __FILE__, __LINE__, &(e), pte_val(e))
+#define pgd_ERROR(e) \
+ printk(KERN_ERR "%s:%d: bad pgd %p(%08lx).\n", \
+ __FILE__, __LINE__, &(e), pgd_val(e))
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
+
+/*
+ * or32 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ *
+ * Actually I am not sure on what this could be used for.
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+ unsigned long address, pte_t *pte)
+{
+}
+
+/* __PHX__ FIXME, SWAP, this probably doesn't work */
+
+/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
+/* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */
+
+#define __swp_type(x) (((x).val >> 5) & 0x7f)
+#define __swp_offset(x) ((x).val >> 12)
+#define __swp_entry(type, offset) \
+ ((swp_entry_t) { ((type) << 5) | ((offset) << 12) })
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+/* Encode and decode a nonlinear file mapping entry */
+
+#define PTE_FILE_MAX_BITS 26
+#define pte_to_pgoff(x) (pte_val(x) >> 6)
+#define pgoff_to_pte(x) __pte(((x) << 6) | _PAGE_FILE)
+
+#define kern_addr_valid(addr) (1)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#include <asm-generic/pgtable.h>
+
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init() do { } while (0)
+#define io_remap_page_range remap_page_range
+
+typedef pte_t *pte_addr_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_OPENRISC_PGTABLE_H */
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
new file mode 100644
index 000000000000..bb54c97b9783
--- /dev/null
+++ b/arch/openrisc/include/asm/processor.h
@@ -0,0 +1,113 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_PROCESSOR_H
+#define __ASM_OPENRISC_PROCESSOR_H
+
+#include <asm/spr_defs.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+
+#define STACK_TOP TASK_SIZE
+#define STACK_TOP_MAX STACK_TOP
+/* Kernel and user SR register setting */
+#define KERNEL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
+ | SPR_SR_DCE | SPR_SR_SM)
+#define USER_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
+ | SPR_SR_DCE | SPR_SR_IEE | SPR_SR_TEE)
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*
+ * User space process size. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ */
+
+#define TASK_SIZE (0x80000000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+struct thread_struct {
+};
+
+/*
+ * At user->kernel entry, the pt_regs struct is stacked on the top of the
+ * kernel-stack. This macro allows us to find those regs for a task.
+ * Notice that subsequent pt_regs stackings, like recursive interrupts
+ * occurring while we're in the kernel, won't affect this - only the first
+ * user->kernel transition registers are reached by this (i.e. not regs
+ * for running signal handler)
+ */
+#define user_regs(thread_info) (((struct pt_regs *)((unsigned long)(thread_info) + THREAD_SIZE - STACK_FRAME_OVERHEAD)) - 1)
+
+/*
+ * Dito but for the currently running task
+ */
+
+#define task_pt_regs(task) user_regs(task_thread_info(task))
+#define current_regs() user_regs(current_thread_info())
+
+extern inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
+#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
+
+#define INIT_THREAD { }
+
+
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc);
+#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp);
+
+
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
+void release_thread(struct task_struct *);
+unsigned long get_wchan(struct task_struct *p);
+
+/*
+ * Free current thread data structures etc..
+ */
+
+extern inline void exit_thread(void)
+{
+ /* Nothing needs to be done. */
+}
+
+/*
+ * Return saved PC of a blocked thread. For now, this is the "user" PC
+ */
+extern unsigned long thread_saved_pc(struct task_struct *t);
+
+#define init_stack (init_thread_union.stack)
+
+#define cpu_relax() do { } while (0)
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_OPENRISC_PROCESSOR_H */
diff --git a/arch/openrisc/include/asm/prom.h b/arch/openrisc/include/asm/prom.h
new file mode 100644
index 000000000000..e1f3fe26606c
--- /dev/null
+++ b/arch/openrisc/include/asm/prom.h
@@ -0,0 +1,77 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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/of.h> /* linux/of.h gets to determine #include ordering */
+
+#ifndef _ASM_OPENRISC_PROM_H
+#define _ASM_OPENRISC_PROM_H
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <asm/irq.h>
+#include <linux/atomic.h>
+#include <linux/of_irq.h>
+#include <linux/of_fdt.h>
+#include <linux/of_address.h>
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
+/* Other Prototypes */
+extern int early_uartlite_console(void);
+
+/* Parse the ibm,dma-window property of an OF node into the busno, phys and
+ * size parameters.
+ */
+void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
+ unsigned long *busno, unsigned long *phys, unsigned long *size);
+
+extern void kdump_move_device_tree(void);
+
+/* CPU OF node matching */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
+
+/* Get the MAC address */
+extern const void *of_get_mac_address(struct device_node *np);
+
+/**
+ * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * @pdev: the device whose interrupt is to be resolved
+ * @out_irq: structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+struct pci_dev;
+extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+
+/* This routine is here to provide compatibility with how powerpc
+ * handles IRQ mapping for OF device nodes. We precompute and permanently
+ * register them in the platform_device objects, whereas powerpc computes them
+ * on request.
+ */
+static inline void irq_dispose_mapping(unsigned int virq)
+{
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_OPENRISC_PROM_H */
diff --git a/arch/openrisc/include/asm/ptrace.h b/arch/openrisc/include/asm/ptrace.h
new file mode 100644
index 000000000000..054537c5f9c9
--- /dev/null
+++ b/arch/openrisc/include/asm/ptrace.h
@@ -0,0 +1,131 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_PTRACE_H
+#define __ASM_OPENRISC_PTRACE_H
+
+#include <asm/spr_defs.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * This is the layout of the regset returned by the GETREGSET ptrace call
+ */
+struct user_regs_struct {
+ /* GPR R0-R31... */
+ unsigned long gpr[32];
+ unsigned long pc;
+ unsigned long sr;
+ unsigned long pad1;
+ unsigned long pad2;
+};
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * Make kernel PTrace/register structures opaque to userspace... userspace can
+ * access thread state via the regset mechanism. This allows us a bit of
+ * flexibility in how we order the registers on the stack, permitting some
+ * optimizations like packing call-clobbered registers together so that
+ * they share a cacheline (not done yet, though... future optimization).
+ */
+
+#ifndef __ASSEMBLY__
+/*
+ * This struct describes how the registers are laid out on the kernel stack
+ * during a syscall or other kernel entry.
+ *
+ * This structure should always be cacheline aligned on the stack.
+ * FIXME: I don't think that's the case right now. The alignment is
+ * taken care of elsewhere... head.S, process.c, etc.
+ */
+
+struct pt_regs {
+ union {
+ struct {
+ /* Named registers */
+ long sr; /* Stored in place of r0 */
+ long sp; /* r1 */
+ };
+ struct {
+ /* Old style */
+ long offset[2];
+ long gprs[30];
+ };
+ struct {
+ /* New style */
+ long gpr[32];
+ };
+ };
+ long pc;
+ long orig_gpr11; /* For restarting system calls */
+ long syscallno; /* Syscall number (used by strace) */
+ long dummy; /* Cheap alignment fix */
+};
+#endif /* __ASSEMBLY__ */
+
+/* TODO: Rename this to REDZONE because that's what it is */
+#define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */
+
+#define instruction_pointer(regs) ((regs)->pc)
+#define user_mode(regs) (((regs)->sr & SPR_SR_SM) == 0)
+#define user_stack_pointer(regs) ((unsigned long)(regs)->sp)
+#define profile_pc(regs) instruction_pointer(regs)
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ */
+#define PT_SR 0
+#define PT_SP 4
+#define PT_GPR2 8
+#define PT_GPR3 12
+#define PT_GPR4 16
+#define PT_GPR5 20
+#define PT_GPR6 24
+#define PT_GPR7 28
+#define PT_GPR8 32
+#define PT_GPR9 36
+#define PT_GPR10 40
+#define PT_GPR11 44
+#define PT_GPR12 48
+#define PT_GPR13 52
+#define PT_GPR14 56
+#define PT_GPR15 60
+#define PT_GPR16 64
+#define PT_GPR17 68
+#define PT_GPR18 72
+#define PT_GPR19 76
+#define PT_GPR20 80
+#define PT_GPR21 84
+#define PT_GPR22 88
+#define PT_GPR23 92
+#define PT_GPR24 96
+#define PT_GPR25 100
+#define PT_GPR26 104
+#define PT_GPR27 108
+#define PT_GPR28 112
+#define PT_GPR29 116
+#define PT_GPR30 120
+#define PT_GPR31 124
+#define PT_PC 128
+#define PT_ORIG_GPR11 132
+#define PT_SYSCALLNO 136
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_OPENRISC_PTRACE_H */
diff --git a/arch/openrisc/include/asm/serial.h b/arch/openrisc/include/asm/serial.h
new file mode 100644
index 000000000000..270a45241639
--- /dev/null
+++ b/arch/openrisc/include/asm/serial.h
@@ -0,0 +1,36 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_SERIAL_H
+#define __ASM_OPENRISC_SERIAL_H
+
+#ifdef __KERNEL__
+
+#include <asm/cpuinfo.h>
+
+/* There's a generic version of this file, but it assumes a 1.8MHz UART clk...
+ * this, on the other hand, assumes the UART clock is tied to the system
+ * clock... 8250_early.c (early 8250 serial console) actually uses this, so
+ * it needs to be correct to get the early console working.
+ */
+
+#define BASE_BAUD (cpuinfo.clock_frequency/16)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_OPENRISC_SERIAL_H */
diff --git a/arch/openrisc/include/asm/sigcontext.h b/arch/openrisc/include/asm/sigcontext.h
new file mode 100644
index 000000000000..54a5c50132e3
--- /dev/null
+++ b/arch/openrisc/include/asm/sigcontext.h
@@ -0,0 +1,38 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_SIGCONTEXT_H
+#define __ASM_OPENRISC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+/* This struct is saved by setup_frame in signal.c, to keep the current
+ context while a signal handler is executed. It's restored by sys_sigreturn.
+
+ To keep things simple, we use pt_regs here even though normally you just
+ specify the list of regs to save. Then we can use copy_from_user on the
+ entire regs instead of a bunch of get_user's as well...
+*/
+
+struct sigcontext {
+ struct pt_regs regs; /* needs to be first */
+ unsigned long oldmask;
+ unsigned long usp; /* usp before stacking this gunk on it */
+};
+
+#endif /* __ASM_OPENRISC_SIGCONTEXT_H */
diff --git a/arch/openrisc/include/asm/spinlock.h b/arch/openrisc/include/asm/spinlock.h
new file mode 100644
index 000000000000..fd00a3a24123
--- /dev/null
+++ b/arch/openrisc/include/asm/spinlock.h
@@ -0,0 +1,24 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_SPINLOCK_H
+#define __ASM_OPENRISC_SPINLOCK_H
+
+#error "or32 doesn't do SMP yet"
+
+#endif
diff --git a/arch/openrisc/include/asm/spr.h b/arch/openrisc/include/asm/spr.h
new file mode 100644
index 000000000000..1cccb42dd477
--- /dev/null
+++ b/arch/openrisc/include/asm/spr.h
@@ -0,0 +1,42 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_SPR_H
+#define __ASM_OPENRISC_SPR_H
+
+#define mtspr(_spr, _val) __asm__ __volatile__ ( \
+ "l.mtspr r0,%1,%0" \
+ : : "K" (_spr), "r" (_val))
+#define mtspr_off(_spr, _off, _val) __asm__ __volatile__ ( \
+ "l.mtspr %0,%1,%2" \
+ : : "r" (_off), "r" (_val), "K" (_spr))
+
+static inline unsigned long mfspr(unsigned long add)
+{
+ unsigned long ret;
+ __asm__ __volatile__ ("l.mfspr %0,r0,%1" : "=r" (ret) : "K" (add));
+ return ret;
+}
+
+static inline unsigned long mfspr_off(unsigned long add, unsigned long offset)
+{
+ unsigned long ret;
+ __asm__ __volatile__ ("l.mfspr %0,%1,%2" : "=r" (ret)
+ : "r" (offset), "K" (add));
+ return ret;
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/spr_defs.h b/arch/openrisc/include/asm/spr_defs.h
new file mode 100644
index 000000000000..5dbc668865c4
--- /dev/null
+++ b/arch/openrisc/include/asm/spr_defs.h
@@ -0,0 +1,604 @@
+/*
+ * OpenRISC Linux
+ *
+ * SPR Definitions
+ *
+ * Copyright (C) 2000 Damjan Lampret
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2008, 2010 Embecosm Limited
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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 file is part of OpenRISC 1000 Architectural Simulator.
+ */
+
+#ifndef SPR_DEFS__H
+#define SPR_DEFS__H
+
+/* Definition of special-purpose registers (SPRs). */
+
+#define MAX_GRPS (32)
+#define MAX_SPRS_PER_GRP_BITS (11)
+#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS)
+#define MAX_SPRS (0x10000)
+
+/* Base addresses for the groups */
+#define SPRGROUP_SYS (0 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_DMMU (1 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_IMMU (2 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_DC (3 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_IC (4 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_MAC (5 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_D (6 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PC (7 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PM (8 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PIC (9 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_TT (10 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_FP (11 << MAX_SPRS_PER_GRP_BITS)
+
+/* System control and status group */
+#define SPR_VR (SPRGROUP_SYS + 0)
+#define SPR_UPR (SPRGROUP_SYS + 1)
+#define SPR_CPUCFGR (SPRGROUP_SYS + 2)
+#define SPR_DMMUCFGR (SPRGROUP_SYS + 3)
+#define SPR_IMMUCFGR (SPRGROUP_SYS + 4)
+#define SPR_DCCFGR (SPRGROUP_SYS + 5)
+#define SPR_ICCFGR (SPRGROUP_SYS + 6)
+#define SPR_DCFGR (SPRGROUP_SYS + 7)
+#define SPR_PCCFGR (SPRGROUP_SYS + 8)
+#define SPR_NPC (SPRGROUP_SYS + 16) /* CZ 21/06/01 */
+#define SPR_SR (SPRGROUP_SYS + 17) /* CZ 21/06/01 */
+#define SPR_PPC (SPRGROUP_SYS + 18) /* CZ 21/06/01 */
+#define SPR_FPCSR (SPRGROUP_SYS + 20) /* CZ 21/06/01 */
+#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) /* CZ 21/06/01 */
+#define SPR_EPCR_LAST (SPRGROUP_SYS + 47) /* CZ 21/06/01 */
+#define SPR_EEAR_BASE (SPRGROUP_SYS + 48)
+#define SPR_EEAR_LAST (SPRGROUP_SYS + 63)
+#define SPR_ESR_BASE (SPRGROUP_SYS + 64)
+#define SPR_ESR_LAST (SPRGROUP_SYS + 79)
+#define SPR_GPR_BASE (SPRGROUP_SYS + 1024)
+
+/* Data MMU group */
+#define SPR_DMMUCR (SPRGROUP_DMMU + 0)
+#define SPR_DTLBEIR (SPRGROUP_DMMU + 2)
+#define SPR_DTLBMR_BASE(WAY) (SPRGROUP_DMMU + 0x200 + (WAY) * 0x100)
+#define SPR_DTLBMR_LAST(WAY) (SPRGROUP_DMMU + 0x27f + (WAY) * 0x100)
+#define SPR_DTLBTR_BASE(WAY) (SPRGROUP_DMMU + 0x280 + (WAY) * 0x100)
+#define SPR_DTLBTR_LAST(WAY) (SPRGROUP_DMMU + 0x2ff + (WAY) * 0x100)
+
+/* Instruction MMU group */
+#define SPR_IMMUCR (SPRGROUP_IMMU + 0)
+#define SPR_ITLBEIR (SPRGROUP_IMMU + 2)
+#define SPR_ITLBMR_BASE(WAY) (SPRGROUP_IMMU + 0x200 + (WAY) * 0x100)
+#define SPR_ITLBMR_LAST(WAY) (SPRGROUP_IMMU + 0x27f + (WAY) * 0x100)
+#define SPR_ITLBTR_BASE(WAY) (SPRGROUP_IMMU + 0x280 + (WAY) * 0x100)
+#define SPR_ITLBTR_LAST(WAY) (SPRGROUP_IMMU + 0x2ff + (WAY) * 0x100)
+
+/* Data cache group */
+#define SPR_DCCR (SPRGROUP_DC + 0)
+#define SPR_DCBPR (SPRGROUP_DC + 1)
+#define SPR_DCBFR (SPRGROUP_DC + 2)
+#define SPR_DCBIR (SPRGROUP_DC + 3)
+#define SPR_DCBWR (SPRGROUP_DC + 4)
+#define SPR_DCBLR (SPRGROUP_DC + 5)
+#define SPR_DCR_BASE(WAY) (SPRGROUP_DC + 0x200 + (WAY) * 0x200)
+#define SPR_DCR_LAST(WAY) (SPRGROUP_DC + 0x3ff + (WAY) * 0x200)
+
+/* Instruction cache group */
+#define SPR_ICCR (SPRGROUP_IC + 0)
+#define SPR_ICBPR (SPRGROUP_IC + 1)
+#define SPR_ICBIR (SPRGROUP_IC + 2)
+#define SPR_ICBLR (SPRGROUP_IC + 3)
+#define SPR_ICR_BASE(WAY) (SPRGROUP_IC + 0x200 + (WAY) * 0x200)
+#define SPR_ICR_LAST(WAY) (SPRGROUP_IC + 0x3ff + (WAY) * 0x200)
+
+/* MAC group */
+#define SPR_MACLO (SPRGROUP_MAC + 1)
+#define SPR_MACHI (SPRGROUP_MAC + 2)
+
+/* Debug group */
+#define SPR_DVR(N) (SPRGROUP_D + (N))
+#define SPR_DCR(N) (SPRGROUP_D + 8 + (N))
+#define SPR_DMR1 (SPRGROUP_D + 16)
+#define SPR_DMR2 (SPRGROUP_D + 17)
+#define SPR_DWCR0 (SPRGROUP_D + 18)
+#define SPR_DWCR1 (SPRGROUP_D + 19)
+#define SPR_DSR (SPRGROUP_D + 20)
+#define SPR_DRR (SPRGROUP_D + 21)
+
+/* Performance counters group */
+#define SPR_PCCR(N) (SPRGROUP_PC + (N))
+#define SPR_PCMR(N) (SPRGROUP_PC + 8 + (N))
+
+/* Power management group */
+#define SPR_PMR (SPRGROUP_PM + 0)
+
+/* PIC group */
+#define SPR_PICMR (SPRGROUP_PIC + 0)
+#define SPR_PICPR (SPRGROUP_PIC + 1)
+#define SPR_PICSR (SPRGROUP_PIC + 2)
+
+/* Tick Timer group */
+#define SPR_TTMR (SPRGROUP_TT + 0)
+#define SPR_TTCR (SPRGROUP_TT + 1)
+
+/*
+ * Bit definitions for the Version Register
+ *
+ */
+#define SPR_VR_VER 0xff000000 /* Processor version */
+#define SPR_VR_CFG 0x00ff0000 /* Processor configuration */
+#define SPR_VR_RES 0x0000ffc0 /* Reserved */
+#define SPR_VR_REV 0x0000003f /* Processor revision */
+
+#define SPR_VR_VER_OFF 24
+#define SPR_VR_CFG_OFF 16
+#define SPR_VR_REV_OFF 0
+
+/*
+ * Bit definitions for the Unit Present Register
+ *
+ */
+#define SPR_UPR_UP 0x00000001 /* UPR present */
+#define SPR_UPR_DCP 0x00000002 /* Data cache present */
+#define SPR_UPR_ICP 0x00000004 /* Instruction cache present */
+#define SPR_UPR_DMP 0x00000008 /* Data MMU present */
+#define SPR_UPR_IMP 0x00000010 /* Instruction MMU present */
+#define SPR_UPR_MP 0x00000020 /* MAC present */
+#define SPR_UPR_DUP 0x00000040 /* Debug unit present */
+#define SPR_UPR_PCUP 0x00000080 /* Performance counters unit present */
+#define SPR_UPR_PMP 0x00000100 /* Power management present */
+#define SPR_UPR_PICP 0x00000200 /* PIC present */
+#define SPR_UPR_TTP 0x00000400 /* Tick timer present */
+#define SPR_UPR_RES 0x00fe0000 /* Reserved */
+#define SPR_UPR_CUP 0xff000000 /* Context units present */
+
+/*
+ * JPB: Bit definitions for the CPU configuration register
+ *
+ */
+#define SPR_CPUCFGR_NSGF 0x0000000f /* Number of shadow GPR files */
+#define SPR_CPUCFGR_CGF 0x00000010 /* Custom GPR file */
+#define SPR_CPUCFGR_OB32S 0x00000020 /* ORBIS32 supported */
+#define SPR_CPUCFGR_OB64S 0x00000040 /* ORBIS64 supported */
+#define SPR_CPUCFGR_OF32S 0x00000080 /* ORFPX32 supported */
+#define SPR_CPUCFGR_OF64S 0x00000100 /* ORFPX64 supported */
+#define SPR_CPUCFGR_OV64S 0x00000200 /* ORVDX64 supported */
+#define SPR_CPUCFGR_RES 0xfffffc00 /* Reserved */
+
+/*
+ * JPB: Bit definitions for the Debug configuration register and other
+ * constants.
+ *
+ */
+
+#define SPR_DCFGR_NDP 0x00000007 /* Number of matchpoints mask */
+#define SPR_DCFGR_NDP1 0x00000000 /* One matchpoint supported */
+#define SPR_DCFGR_NDP2 0x00000001 /* Two matchpoints supported */
+#define SPR_DCFGR_NDP3 0x00000002 /* Three matchpoints supported */
+#define SPR_DCFGR_NDP4 0x00000003 /* Four matchpoints supported */
+#define SPR_DCFGR_NDP5 0x00000004 /* Five matchpoints supported */
+#define SPR_DCFGR_NDP6 0x00000005 /* Six matchpoints supported */
+#define SPR_DCFGR_NDP7 0x00000006 /* Seven matchpoints supported */
+#define SPR_DCFGR_NDP8 0x00000007 /* Eight matchpoints supported */
+#define SPR_DCFGR_WPCI 0x00000008 /* Watchpoint counters implemented */
+
+#define MATCHPOINTS_TO_NDP(n) (1 == n ? SPR_DCFGR_NDP1 : \
+ 2 == n ? SPR_DCFGR_NDP2 : \
+ 3 == n ? SPR_DCFGR_NDP3 : \
+ 4 == n ? SPR_DCFGR_NDP4 : \
+ 5 == n ? SPR_DCFGR_NDP5 : \
+ 6 == n ? SPR_DCFGR_NDP6 : \
+ 7 == n ? SPR_DCFGR_NDP7 : SPR_DCFGR_NDP8)
+#define MAX_MATCHPOINTS 8
+#define MAX_WATCHPOINTS (MAX_MATCHPOINTS + 2)
+
+/*
+ * Bit definitions for the Supervision Register
+ *
+ */
+#define SPR_SR_SM 0x00000001 /* Supervisor Mode */
+#define SPR_SR_TEE 0x00000002 /* Tick timer Exception Enable */
+#define SPR_SR_IEE 0x00000004 /* Interrupt Exception Enable */
+#define SPR_SR_DCE 0x00000008 /* Data Cache Enable */
+#define SPR_SR_ICE 0x00000010 /* Instruction Cache Enable */
+#define SPR_SR_DME 0x00000020 /* Data MMU Enable */
+#define SPR_SR_IME 0x00000040 /* Instruction MMU Enable */
+#define SPR_SR_LEE 0x00000080 /* Little Endian Enable */
+#define SPR_SR_CE 0x00000100 /* CID Enable */
+#define SPR_SR_F 0x00000200 /* Condition Flag */
+#define SPR_SR_CY 0x00000400 /* Carry flag */
+#define SPR_SR_OV 0x00000800 /* Overflow flag */
+#define SPR_SR_OVE 0x00001000 /* Overflow flag Exception */
+#define SPR_SR_DSX 0x00002000 /* Delay Slot Exception */
+#define SPR_SR_EPH 0x00004000 /* Exception Prefix High */
+#define SPR_SR_FO 0x00008000 /* Fixed one */
+#define SPR_SR_SUMRA 0x00010000 /* Supervisor SPR read access */
+#define SPR_SR_RES 0x0ffe0000 /* Reserved */
+#define SPR_SR_CID 0xf0000000 /* Context ID */
+
+/*
+ * Bit definitions for the Data MMU Control Register
+ *
+ */
+#define SPR_DMMUCR_P2S 0x0000003e /* Level 2 Page Size */
+#define SPR_DMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
+#define SPR_DMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
+#define SPR_DMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
+
+/*
+ * Bit definitions for the Instruction MMU Control Register
+ *
+ */
+#define SPR_IMMUCR_P2S 0x0000003e /* Level 2 Page Size */
+#define SPR_IMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
+#define SPR_IMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
+#define SPR_IMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
+
+/*
+ * Bit definitions for the Data TLB Match Register
+ *
+ */
+#define SPR_DTLBMR_V 0x00000001 /* Valid */
+#define SPR_DTLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
+#define SPR_DTLBMR_CID 0x0000003c /* Context ID */
+#define SPR_DTLBMR_LRU 0x000000c0 /* Least Recently Used */
+#define SPR_DTLBMR_VPN 0xfffff000 /* Virtual Page Number */
+
+/*
+ * Bit definitions for the Data TLB Translate Register
+ *
+ */
+#define SPR_DTLBTR_CC 0x00000001 /* Cache Coherency */
+#define SPR_DTLBTR_CI 0x00000002 /* Cache Inhibit */
+#define SPR_DTLBTR_WBC 0x00000004 /* Write-Back Cache */
+#define SPR_DTLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
+#define SPR_DTLBTR_A 0x00000010 /* Accessed */
+#define SPR_DTLBTR_D 0x00000020 /* Dirty */
+#define SPR_DTLBTR_URE 0x00000040 /* User Read Enable */
+#define SPR_DTLBTR_UWE 0x00000080 /* User Write Enable */
+#define SPR_DTLBTR_SRE 0x00000100 /* Supervisor Read Enable */
+#define SPR_DTLBTR_SWE 0x00000200 /* Supervisor Write Enable */
+#define SPR_DTLBTR_PPN 0xfffff000 /* Physical Page Number */
+
+/*
+ * Bit definitions for the Instruction TLB Match Register
+ *
+ */
+#define SPR_ITLBMR_V 0x00000001 /* Valid */
+#define SPR_ITLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
+#define SPR_ITLBMR_CID 0x0000003c /* Context ID */
+#define SPR_ITLBMR_LRU 0x000000c0 /* Least Recently Used */
+#define SPR_ITLBMR_VPN 0xfffff000 /* Virtual Page Number */
+
+/*
+ * Bit definitions for the Instruction TLB Translate Register
+ *
+ */
+#define SPR_ITLBTR_CC 0x00000001 /* Cache Coherency */
+#define SPR_ITLBTR_CI 0x00000002 /* Cache Inhibit */
+#define SPR_ITLBTR_WBC 0x00000004 /* Write-Back Cache */
+#define SPR_ITLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
+#define SPR_ITLBTR_A 0x00000010 /* Accessed */
+#define SPR_ITLBTR_D 0x00000020 /* Dirty */
+#define SPR_ITLBTR_SXE 0x00000040 /* User Read Enable */
+#define SPR_ITLBTR_UXE 0x00000080 /* User Write Enable */
+#define SPR_ITLBTR_PPN 0xfffff000 /* Physical Page Number */
+
+/*
+ * Bit definitions for Data Cache Control register
+ *
+ */
+#define SPR_DCCR_EW 0x000000ff /* Enable ways */
+
+/*
+ * Bit definitions for Insn Cache Control register
+ *
+ */
+#define SPR_ICCR_EW 0x000000ff /* Enable ways */
+
+/*
+ * Bit definitions for Data Cache Configuration Register
+ *
+ */
+
+#define SPR_DCCFGR_NCW 0x00000007
+#define SPR_DCCFGR_NCS 0x00000078
+#define SPR_DCCFGR_CBS 0x00000080
+#define SPR_DCCFGR_CWS 0x00000100
+#define SPR_DCCFGR_CCRI 0x00000200
+#define SPR_DCCFGR_CBIRI 0x00000400
+#define SPR_DCCFGR_CBPRI 0x00000800
+#define SPR_DCCFGR_CBLRI 0x00001000
+#define SPR_DCCFGR_CBFRI 0x00002000
+#define SPR_DCCFGR_CBWBRI 0x00004000
+
+#define SPR_DCCFGR_NCW_OFF 0
+#define SPR_DCCFGR_NCS_OFF 3
+#define SPR_DCCFGR_CBS_OFF 7
+
+/*
+ * Bit definitions for Instruction Cache Configuration Register
+ *
+ */
+#define SPR_ICCFGR_NCW 0x00000007
+#define SPR_ICCFGR_NCS 0x00000078
+#define SPR_ICCFGR_CBS 0x00000080
+#define SPR_ICCFGR_CCRI 0x00000200
+#define SPR_ICCFGR_CBIRI 0x00000400
+#define SPR_ICCFGR_CBPRI 0x00000800
+#define SPR_ICCFGR_CBLRI 0x00001000
+
+#define SPR_ICCFGR_NCW_OFF 0
+#define SPR_ICCFGR_NCS_OFF 3
+#define SPR_ICCFGR_CBS_OFF 7
+
+/*
+ * Bit definitions for Data MMU Configuration Register
+ *
+ */
+
+#define SPR_DMMUCFGR_NTW 0x00000003
+#define SPR_DMMUCFGR_NTS 0x0000001C
+#define SPR_DMMUCFGR_NAE 0x000000E0
+#define SPR_DMMUCFGR_CRI 0x00000100
+#define SPR_DMMUCFGR_PRI 0x00000200
+#define SPR_DMMUCFGR_TEIRI 0x00000400
+#define SPR_DMMUCFGR_HTR 0x00000800
+
+#define SPR_DMMUCFGR_NTW_OFF 0
+#define SPR_DMMUCFGR_NTS_OFF 2
+
+/*
+ * Bit definitions for Instruction MMU Configuration Register
+ *
+ */
+
+#define SPR_IMMUCFGR_NTW 0x00000003
+#define SPR_IMMUCFGR_NTS 0x0000001C
+#define SPR_IMMUCFGR_NAE 0x000000E0
+#define SPR_IMMUCFGR_CRI 0x00000100
+#define SPR_IMMUCFGR_PRI 0x00000200
+#define SPR_IMMUCFGR_TEIRI 0x00000400
+#define SPR_IMMUCFGR_HTR 0x00000800
+
+#define SPR_IMMUCFGR_NTW_OFF 0
+#define SPR_IMMUCFGR_NTS_OFF 2
+
+/*
+ * Bit definitions for Debug Control registers
+ *
+ */
+#define SPR_DCR_DP 0x00000001 /* DVR/DCR present */
+#define SPR_DCR_CC 0x0000000e /* Compare condition */
+#define SPR_DCR_SC 0x00000010 /* Signed compare */
+#define SPR_DCR_CT 0x000000e0 /* Compare to */
+
+/* Bit results with SPR_DCR_CC mask */
+#define SPR_DCR_CC_MASKED 0x00000000
+#define SPR_DCR_CC_EQUAL 0x00000002
+#define SPR_DCR_CC_LESS 0x00000004
+#define SPR_DCR_CC_LESSE 0x00000006
+#define SPR_DCR_CC_GREAT 0x00000008
+#define SPR_DCR_CC_GREATE 0x0000000a
+#define SPR_DCR_CC_NEQUAL 0x0000000c
+
+/* Bit results with SPR_DCR_CT mask */
+#define SPR_DCR_CT_DISABLED 0x00000000
+#define SPR_DCR_CT_IFEA 0x00000020
+#define SPR_DCR_CT_LEA 0x00000040
+#define SPR_DCR_CT_SEA 0x00000060
+#define SPR_DCR_CT_LD 0x00000080
+#define SPR_DCR_CT_SD 0x000000a0
+#define SPR_DCR_CT_LSEA 0x000000c0
+#define SPR_DCR_CT_LSD 0x000000e0
+/* SPR_DCR_CT_LSD doesn't seem to be implemented anywhere in or1ksim. 2004-1-30 HP */
+
+/*
+ * Bit definitions for Debug Mode 1 register
+ *
+ */
+#define SPR_DMR1_CW 0x000fffff /* Chain register pair data */
+#define SPR_DMR1_CW0_AND 0x00000001
+#define SPR_DMR1_CW0_OR 0x00000002
+#define SPR_DMR1_CW0 (SPR_DMR1_CW0_AND | SPR_DMR1_CW0_OR)
+#define SPR_DMR1_CW1_AND 0x00000004
+#define SPR_DMR1_CW1_OR 0x00000008
+#define SPR_DMR1_CW1 (SPR_DMR1_CW1_AND | SPR_DMR1_CW1_OR)
+#define SPR_DMR1_CW2_AND 0x00000010
+#define SPR_DMR1_CW2_OR 0x00000020
+#define SPR_DMR1_CW2 (SPR_DMR1_CW2_AND | SPR_DMR1_CW2_OR)
+#define SPR_DMR1_CW3_AND 0x00000040
+#define SPR_DMR1_CW3_OR 0x00000080
+#define SPR_DMR1_CW3 (SPR_DMR1_CW3_AND | SPR_DMR1_CW3_OR)
+#define SPR_DMR1_CW4_AND 0x00000100
+#define SPR_DMR1_CW4_OR 0x00000200
+#define SPR_DMR1_CW4 (SPR_DMR1_CW4_AND | SPR_DMR1_CW4_OR)
+#define SPR_DMR1_CW5_AND 0x00000400
+#define SPR_DMR1_CW5_OR 0x00000800
+#define SPR_DMR1_CW5 (SPR_DMR1_CW5_AND | SPR_DMR1_CW5_OR)
+#define SPR_DMR1_CW6_AND 0x00001000
+#define SPR_DMR1_CW6_OR 0x00002000
+#define SPR_DMR1_CW6 (SPR_DMR1_CW6_AND | SPR_DMR1_CW6_OR)
+#define SPR_DMR1_CW7_AND 0x00004000
+#define SPR_DMR1_CW7_OR 0x00008000
+#define SPR_DMR1_CW7 (SPR_DMR1_CW7_AND | SPR_DMR1_CW7_OR)
+#define SPR_DMR1_CW8_AND 0x00010000
+#define SPR_DMR1_CW8_OR 0x00020000
+#define SPR_DMR1_CW8 (SPR_DMR1_CW8_AND | SPR_DMR1_CW8_OR)
+#define SPR_DMR1_CW9_AND 0x00040000
+#define SPR_DMR1_CW9_OR 0x00080000
+#define SPR_DMR1_CW9 (SPR_DMR1_CW9_AND | SPR_DMR1_CW9_OR)
+#define SPR_DMR1_RES1 0x00300000 /* Reserved */
+#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/
+#define SPR_DMR1_BT 0x00800000 /* Branch trace */
+#define SPR_DMR1_RES2 0xff000000 /* Reserved */
+
+/*
+ * Bit definitions for Debug Mode 2 register. AWTC and WGB corrected by JPB
+ *
+ */
+#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter 0 enable */
+#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter 0 enable */
+#define SPR_DMR2_AWTC 0x00000ffc /* Assign watchpoints to counters */
+#define SPR_DMR2_AWTC_OFF 2 /* Bit offset to AWTC field */
+#define SPR_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */
+#define SPR_DMR2_WGB_OFF 12 /* Bit offset to WGB field */
+#define SPR_DMR2_WBS 0xffc00000 /* JPB: Watchpoint status */
+#define SPR_DMR2_WBS_OFF 22 /* Bit offset to WBS field */
+
+/*
+ * Bit definitions for Debug watchpoint counter registers
+ *
+ */
+#define SPR_DWCR_COUNT 0x0000ffff /* Count */
+#define SPR_DWCR_MATCH 0xffff0000 /* Match */
+#define SPR_DWCR_MATCH_OFF 16 /* Match bit offset */
+
+/*
+ * Bit definitions for Debug stop register
+ *
+ */
+#define SPR_DSR_RSTE 0x00000001 /* Reset exception */
+#define SPR_DSR_BUSEE 0x00000002 /* Bus error exception */
+#define SPR_DSR_DPFE 0x00000004 /* Data Page Fault exception */
+#define SPR_DSR_IPFE 0x00000008 /* Insn Page Fault exception */
+#define SPR_DSR_TTE 0x00000010 /* Tick Timer exception */
+#define SPR_DSR_AE 0x00000020 /* Alignment exception */
+#define SPR_DSR_IIE 0x00000040 /* Illegal Instruction exception */
+#define SPR_DSR_IE 0x00000080 /* Interrupt exception */
+#define SPR_DSR_DME 0x00000100 /* DTLB miss exception */
+#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */
+#define SPR_DSR_RE 0x00000400 /* Range exception */
+#define SPR_DSR_SCE 0x00000800 /* System call exception */
+#define SPR_DSR_FPE 0x00001000 /* Floating Point Exception */
+#define SPR_DSR_TE 0x00002000 /* Trap exception */
+
+/*
+ * Bit definitions for Debug reason register
+ *
+ */
+#define SPR_DRR_RSTE 0x00000001 /* Reset exception */
+#define SPR_DRR_BUSEE 0x00000002 /* Bus error exception */
+#define SPR_DRR_DPFE 0x00000004 /* Data Page Fault exception */
+#define SPR_DRR_IPFE 0x00000008 /* Insn Page Fault exception */
+#define SPR_DRR_TTE 0x00000010 /* Tick Timer exception */
+#define SPR_DRR_AE 0x00000020 /* Alignment exception */
+#define SPR_DRR_IIE 0x00000040 /* Illegal Instruction exception */
+#define SPR_DRR_IE 0x00000080 /* Interrupt exception */
+#define SPR_DRR_DME 0x00000100 /* DTLB miss exception */
+#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */
+#define SPR_DRR_RE 0x00000400 /* Range exception */
+#define SPR_DRR_SCE 0x00000800 /* System call exception */
+#define SPR_DRR_FPE 0x00001000 /* Floating Point Exception */
+#define SPR_DRR_TE 0x00002000 /* Trap exception */
+
+/*
+ * Bit definitions for Performance counters mode registers
+ *
+ */
+#define SPR_PCMR_CP 0x00000001 /* Counter present */
+#define SPR_PCMR_UMRA 0x00000002 /* User mode read access */
+#define SPR_PCMR_CISM 0x00000004 /* Count in supervisor mode */
+#define SPR_PCMR_CIUM 0x00000008 /* Count in user mode */
+#define SPR_PCMR_LA 0x00000010 /* Load access event */
+#define SPR_PCMR_SA 0x00000020 /* Store access event */
+#define SPR_PCMR_IF 0x00000040 /* Instruction fetch event*/
+#define SPR_PCMR_DCM 0x00000080 /* Data cache miss event */
+#define SPR_PCMR_ICM 0x00000100 /* Insn cache miss event */
+#define SPR_PCMR_IFS 0x00000200 /* Insn fetch stall event */
+#define SPR_PCMR_LSUS 0x00000400 /* LSU stall event */
+#define SPR_PCMR_BS 0x00000800 /* Branch stall event */
+#define SPR_PCMR_DTLBM 0x00001000 /* DTLB miss event */
+#define SPR_PCMR_ITLBM 0x00002000 /* ITLB miss event */
+#define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */
+#define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */
+
+/*
+ * Bit definitions for the Power management register
+ *
+ */
+#define SPR_PMR_SDF 0x0000000f /* Slow down factor */
+#define SPR_PMR_DME 0x00000010 /* Doze mode enable */
+#define SPR_PMR_SME 0x00000020 /* Sleep mode enable */
+#define SPR_PMR_DCGE 0x00000040 /* Dynamic clock gating enable */
+#define SPR_PMR_SUME 0x00000080 /* Suspend mode enable */
+
+/*
+ * Bit definitions for PICMR
+ *
+ */
+#define SPR_PICMR_IUM 0xfffffffc /* Interrupt unmask */
+
+/*
+ * Bit definitions for PICPR
+ *
+ */
+#define SPR_PICPR_IPRIO 0xfffffffc /* Interrupt priority */
+
+/*
+ * Bit definitions for PICSR
+ *
+ */
+#define SPR_PICSR_IS 0xffffffff /* Interrupt status */
+
+/*
+ * Bit definitions for Tick Timer Control Register
+ *
+ */
+
+#define SPR_TTCR_CNT 0xffffffff /* Count, time period */
+#define SPR_TTMR_TP 0x0fffffff /* Time period */
+#define SPR_TTMR_IP 0x10000000 /* Interrupt Pending */
+#define SPR_TTMR_IE 0x20000000 /* Interrupt Enable */
+#define SPR_TTMR_DI 0x00000000 /* Disabled */
+#define SPR_TTMR_RT 0x40000000 /* Restart tick */
+#define SPR_TTMR_SR 0x80000000 /* Single run */
+#define SPR_TTMR_CR 0xc0000000 /* Continuous run */
+#define SPR_TTMR_M 0xc0000000 /* Tick mode */
+
+/*
+ * Bit definitions for the FP Control Status Register
+ *
+ */
+#define SPR_FPCSR_FPEE 0x00000001 /* Floating Point Exception Enable */
+#define SPR_FPCSR_RM 0x00000006 /* Rounding Mode */
+#define SPR_FPCSR_OVF 0x00000008 /* Overflow Flag */
+#define SPR_FPCSR_UNF 0x00000010 /* Underflow Flag */
+#define SPR_FPCSR_SNF 0x00000020 /* SNAN Flag */
+#define SPR_FPCSR_QNF 0x00000040 /* QNAN Flag */
+#define SPR_FPCSR_ZF 0x00000080 /* Zero Flag */
+#define SPR_FPCSR_IXF 0x00000100 /* Inexact Flag */
+#define SPR_FPCSR_IVF 0x00000200 /* Invalid Flag */
+#define SPR_FPCSR_INF 0x00000400 /* Infinity Flag */
+#define SPR_FPCSR_DZF 0x00000800 /* Divide By Zero Flag */
+#define SPR_FPCSR_ALLF (SPR_FPCSR_OVF | SPR_FPCSR_UNF | SPR_FPCSR_SNF | \
+ SPR_FPCSR_QNF | SPR_FPCSR_ZF | SPR_FPCSR_IXF | \
+ SPR_FPCSR_IVF | SPR_FPCSR_INF | SPR_FPCSR_DZF)
+
+#define FPCSR_RM_RN (0<<1)
+#define FPCSR_RM_RZ (1<<1)
+#define FPCSR_RM_RIP (2<<1)
+#define FPCSR_RM_RIN (3<<1)
+
+/*
+ * l.nop constants
+ *
+ */
+#define NOP_NOP 0x0000 /* Normal nop instruction */
+#define NOP_EXIT 0x0001 /* End of simulation */
+#define NOP_REPORT 0x0002 /* Simple report */
+/*#define NOP_PRINTF 0x0003 Simprintf instruction (obsolete)*/
+#define NOP_PUTC 0x0004 /* JPB: Simputc instruction */
+#define NOP_CNT_RESET 0x0005 /* Reset statistics counters */
+#define NOP_GET_TICKS 0x0006 /* JPB: Get # ticks running */
+#define NOP_GET_PS 0x0007 /* JPB: Get picosecs/cycle */
+#define NOP_REPORT_FIRST 0x0400 /* Report with number */
+#define NOP_REPORT_LAST 0x03ff /* Report with number */
+
+#endif /* SPR_DEFS__H */
diff --git a/arch/openrisc/include/asm/syscall.h b/arch/openrisc/include/asm/syscall.h
new file mode 100644
index 000000000000..9f0337055d26
--- /dev/null
+++ b/arch/openrisc/include/asm/syscall.h
@@ -0,0 +1,77 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_SYSCALL_H__
+#define __ASM_OPENRISC_SYSCALL_H__
+
+#include <linux/err.h>
+#include <linux/sched.h>
+
+static inline int
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+ return regs->syscallno ? regs->syscallno : -1;
+}
+
+static inline void
+syscall_rollback(struct task_struct *task, struct pt_regs *regs)
+{
+ regs->gpr[11] = regs->orig_gpr11;
+}
+
+static inline long
+syscall_get_error(struct task_struct *task, struct pt_regs *regs)
+{
+ return IS_ERR_VALUE(regs->gpr[11]) ? regs->gpr[11] : 0;
+}
+
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+ return regs->gpr[11];
+}
+
+static inline void
+syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
+ int error, long val)
+{
+ if (error)
+ regs->gpr[11] = -error;
+ else
+ regs->gpr[11] = val;
+}
+
+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->gpr[3 + i], n * sizeof(args[0]));
+}
+
+static inline void
+syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, const unsigned long *args)
+{
+ BUG_ON(i + n > 6);
+
+ memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h
new file mode 100644
index 000000000000..84a978af44d7
--- /dev/null
+++ b/arch/openrisc/include/asm/syscalls.h
@@ -0,0 +1,27 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_SYSCALLS_H
+#define __ASM_OPENRISC_SYSCALLS_H
+
+asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1,
+ unsigned long *v2);
+
+#include <asm-generic/syscalls.h>
+
+#endif /* __ASM_OPENRISC_SYSCALLS_H */
diff --git a/arch/openrisc/include/asm/system.h b/arch/openrisc/include/asm/system.h
new file mode 100644
index 000000000000..cf658882186b
--- /dev/null
+++ b/arch/openrisc/include/asm/system.h
@@ -0,0 +1,35 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_SYSTEM_H
+#define __ASM_OPENRISC_SYSTEM_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <asm/spr.h>
+#include <asm-generic/system.h>
+
+/* We probably need this definition, but the generic system.h provides it
+ * and it's not used on our arch anyway...
+ */
+/*#define nop() __asm__ __volatile__ ("l.nop"::)*/
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* __ASM_OPENRISC_SYSTEM_H */
diff --git a/arch/openrisc/include/asm/thread_info.h b/arch/openrisc/include/asm/thread_info.h
new file mode 100644
index 000000000000..07a8bc080ef2
--- /dev/null
+++ b/arch/openrisc/include/asm/thread_info.h
@@ -0,0 +1,134 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/processor.h>
+#endif
+
+
+/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
+ * normally, the stack is found by doing something like p + THREAD_SIZE
+ * in or32, a page is 8192 bytes, which seems like a sane size
+ */
+
+#define THREAD_SIZE_ORDER 0
+#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ * must also be changed
+ */
+#ifndef __ASSEMBLY__
+
+typedef unsigned long mm_segment_t;
+
+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 */
+ __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+
+ mm_segment_t addr_limit; /* thread address space:
+ 0-0x7FFFFFFF for user-thead
+ 0-0xFFFFFFFF for kernel-thread
+ */
+ struct restart_block restart_block;
+ __u8 supervisor_stack[0];
+
+ /* saved context data */
+ unsigned long ksp;
+};
+#endif
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#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, \
+ }, \
+ .ksp = 0, \
+}
+
+#define init_thread_info (init_thread_union.thread_info)
+
+/* how to get the thread information struct from C */
+register struct thread_info *current_thread_info_reg asm("r10");
+#define current_thread_info() (current_thread_info_reg)
+
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#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 singlestep on return to user
+ * mode
+ */
+#define TIF_SYSCALL_TRACEPOINT 8 /* for ftrace syscall instrumentation */
+#define TIF_RESTORE_SIGMASK 9
+#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling * TIF_NEED_RESCHED
+ */
+#define TIF_MEMDIE 17
+
+#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_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+
+
+/* Work to do when returning from interrupt/exception */
+/* For OpenRISC, this is anything in the LSW other than syscall trace */
+#define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP))
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/openrisc/include/asm/timex.h b/arch/openrisc/include/asm/timex.h
new file mode 100644
index 000000000000..9935cad1b9b9
--- /dev/null
+++ b/arch/openrisc/include/asm/timex.h
@@ -0,0 +1,36 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_TIMEX_H
+#define __ASM_OPENRISC_TIMEX_H
+
+#define get_cycles get_cycles
+
+#include <asm-generic/timex.h>
+#include <asm/spr.h>
+#include <asm/spr_defs.h>
+
+static inline cycles_t get_cycles(void)
+{
+ return mfspr(SPR_TTCR);
+}
+
+/* This isn't really used any more */
+#define CLOCK_TICK_RATE 1000
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+#endif
diff --git a/arch/openrisc/include/asm/tlb.h b/arch/openrisc/include/asm/tlb.h
new file mode 100644
index 000000000000..fa4376a4515d
--- /dev/null
+++ b/arch/openrisc/include/asm/tlb.h
@@ -0,0 +1,34 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_TLB_H__
+#define __ASM_OPENRISC_TLB_H__
+
+/*
+ * or32 doesn'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)
+
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+#include <linux/pagemap.h>
+#include <asm-generic/tlb.h>
+
+#endif /* __ASM_OPENRISC_TLB_H__ */
diff --git a/arch/openrisc/include/asm/tlbflush.h b/arch/openrisc/include/asm/tlbflush.h
new file mode 100644
index 000000000000..6a2accd6cb67
--- /dev/null
+++ b/arch/openrisc/include/asm/tlbflush.h
@@ -0,0 +1,55 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_TLBFLUSH_H
+#define __ASM_OPENRISC_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/current.h>
+#include <linux/sched.h>
+
+/*
+ * - flush_tlb() flushes the current mm struct TLBs
+ * - flush_tlb_all() flushes all processes TLBs
+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ * - flush_tlb_page(vma, vmaddr) flushes one page
+ * - flush_tlb_range(mm, start, end) flushes a range of pages
+ */
+
+void flush_tlb_all(void);
+void flush_tlb_mm(struct mm_struct *mm);
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
+void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end);
+
+static inline void flush_tlb(void)
+{
+ flush_tlb_mm(current->mm);
+}
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+ unsigned long end)
+{
+ flush_tlb_range(NULL, start, end);
+}
+
+#endif /* __ASM_OPENRISC_TLBFLUSH_H */
diff --git a/arch/openrisc/include/asm/uaccess.h b/arch/openrisc/include/asm/uaccess.h
new file mode 100644
index 000000000000..c310e45b538e
--- /dev/null
+++ b/arch/openrisc/include/asm/uaccess.h
@@ -0,0 +1,355 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_UACCESS_H
+#define __ASM_OPENRISC_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/errno.h>
+#include <linux/thread_info.h>
+#include <linux/prefetch.h>
+#include <linux/string.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not. If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+/* addr_limit is the maximum accessible address for the task. we misuse
+ * the KERNEL_DS and USER_DS values to both assign and compare the
+ * addr_limit values through the equally misnamed get/set_fs macros.
+ * (see above)
+ */
+
+#define KERNEL_DS (~0UL)
+#define get_ds() (KERNEL_DS)
+
+#define USER_DS (TASK_SIZE)
+#define get_fs() (current_thread_info()->addr_limit)
+#define set_fs(x) (current_thread_info()->addr_limit = (x))
+
+#define segment_eq(a, b) ((a) == (b))
+
+/* Ensure that the range from addr to addr+size is all within the process'
+ * address space
+ */
+#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size))
+
+/* Ensure that addr is below task's addr_limit */
+#define __addr_ok(addr) ((unsigned long) addr < get_fs())
+
+#define access_ok(type, addr, size) \
+ __range_ok((unsigned long)addr, (unsigned long)size)
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue. No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path. This means when everything is well,
+ * we don't even have to jump over them. Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry {
+ unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+extern void sort_exception_table(void);
+
+/*
+ * These are the main single-value transfer routines. They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the uglyness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ *
+ * As we use the same address space for kernel and user data on the
+ * PowerPC, we can just do these as direct assignments. (Of course, the
+ * exception handling means that it's no longer "just"...)
+ */
+#define get_user(x, ptr) \
+ __get_user_check((x), (ptr), sizeof(*(ptr)))
+#define put_user(x, ptr) \
+ __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+#define __get_user(x, ptr) \
+ __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+#define __put_user(x, ptr) \
+ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+extern long __put_user_bad(void);
+
+#define __put_user_nocheck(x, ptr, size) \
+({ \
+ long __pu_err; \
+ __put_user_size((x), (ptr), (size), __pu_err); \
+ __pu_err; \
+})
+
+#define __put_user_check(x, ptr, size) \
+({ \
+ long __pu_err = -EFAULT; \
+ __typeof__(*(ptr)) *__pu_addr = (ptr); \
+ if (access_ok(VERIFY_WRITE, __pu_addr, size)) \
+ __put_user_size((x), __pu_addr, (size), __pu_err); \
+ __pu_err; \
+})
+
+#define __put_user_size(x, ptr, size, retval) \
+do { \
+ retval = 0; \
+ switch (size) { \
+ case 1: __put_user_asm(x, ptr, retval, "l.sb"); break; \
+ case 2: __put_user_asm(x, ptr, retval, "l.sh"); break; \
+ case 4: __put_user_asm(x, ptr, retval, "l.sw"); break; \
+ case 8: __put_user_asm2(x, ptr, retval); break; \
+ default: __put_user_bad(); \
+ } \
+} while (0)
+
+struct __large_struct {
+ unsigned long buf[100];
+};
+#define __m(x) (*(struct __large_struct *)(x))
+
+/*
+ * We don't tell gcc that we are accessing memory, but this is OK
+ * because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ */
+#define __put_user_asm(x, addr, err, op) \
+ __asm__ __volatile__( \
+ "1: "op" 0(%2),%1\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: l.addi %0,r0,%3\n" \
+ " l.j 2b\n" \
+ " l.nop\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".previous" \
+ : "=r"(err) \
+ : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
+
+#define __put_user_asm2(x, addr, err) \
+ __asm__ __volatile__( \
+ "1: l.sw 0(%2),%1\n" \
+ "2: l.sw 4(%2),%H1\n" \
+ "3:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "4: l.addi %0,r0,%3\n" \
+ " l.j 3b\n" \
+ " l.nop\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,4b\n" \
+ " .long 2b,4b\n" \
+ ".previous" \
+ : "=r"(err) \
+ : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
+
+#define __get_user_nocheck(x, ptr, size) \
+({ \
+ long __gu_err, __gu_val; \
+ __get_user_size(__gu_val, (ptr), (size), __gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+#define __get_user_check(x, ptr, size) \
+({ \
+ long __gu_err = -EFAULT, __gu_val = 0; \
+ const __typeof__(*(ptr)) * __gu_addr = (ptr); \
+ if (access_ok(VERIFY_READ, __gu_addr, size)) \
+ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x, ptr, size, retval) \
+do { \
+ retval = 0; \
+ switch (size) { \
+ case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break; \
+ case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \
+ case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \
+ case 8: __get_user_asm2(x, ptr, retval); \
+ default: (x) = __get_user_bad(); \
+ } \
+} while (0)
+
+#define __get_user_asm(x, addr, err, op) \
+ __asm__ __volatile__( \
+ "1: "op" %1,0(%2)\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: l.addi %0,r0,%3\n" \
+ " l.addi %1,r0,0\n" \
+ " l.j 2b\n" \
+ " l.nop\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".previous" \
+ : "=r"(err), "=r"(x) \
+ : "r"(addr), "i"(-EFAULT), "0"(err))
+
+#define __get_user_asm2(x, addr, err) \
+ __asm__ __volatile__( \
+ "1: l.lwz %1,0(%2)\n" \
+ "2: l.lwz %H1,4(%2)\n" \
+ "3:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "4: l.addi %0,r0,%3\n" \
+ " l.addi %1,r0,0\n" \
+ " l.addi %H1,r0,0\n" \
+ " l.j 3b\n" \
+ " l.nop\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,4b\n" \
+ " .long 2b,4b\n" \
+ ".previous" \
+ : "=r"(err), "=&r"(x) \
+ : "r"(addr), "i"(-EFAULT), "0"(err))
+
+/* more complex routines */
+
+extern unsigned long __must_check
+__copy_tofrom_user(void *to, const void *from, unsigned long size);
+
+#define __copy_from_user(to, from, size) \
+ __copy_tofrom_user(to, from, size)
+#define __copy_to_user(to, from, size) \
+ __copy_tofrom_user(to, from, size)
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+static inline unsigned long
+copy_from_user(void *to, const void *from, unsigned long n)
+{
+ unsigned long over;
+
+ if (access_ok(VERIFY_READ, from, n))
+ return __copy_tofrom_user(to, from, n);
+ if ((unsigned long)from < TASK_SIZE) {
+ over = (unsigned long)from + n - TASK_SIZE;
+ return __copy_tofrom_user(to, from, n - over) + over;
+ }
+ return n;
+}
+
+static inline unsigned long
+copy_to_user(void *to, const void *from, unsigned long n)
+{
+ unsigned long over;
+
+ if (access_ok(VERIFY_WRITE, to, n))
+ return __copy_tofrom_user(to, from, n);
+ if ((unsigned long)to < TASK_SIZE) {
+ over = (unsigned long)to + n - TASK_SIZE;
+ return __copy_tofrom_user(to, from, n - over) + over;
+ }
+ return n;
+}
+
+extern unsigned long __clear_user(void *addr, unsigned long size);
+
+static inline __must_check unsigned long
+clear_user(void *addr, unsigned long size)
+{
+
+ if (access_ok(VERIFY_WRITE, addr, size))
+ return __clear_user(addr, size);
+ if ((unsigned long)addr < TASK_SIZE) {
+ unsigned long over = (unsigned long)addr + size - TASK_SIZE;
+ return __clear_user(addr, size - over) + over;
+ }
+ return size;
+}
+
+extern int __strncpy_from_user(char *dst, const char *src, long count);
+
+static inline long strncpy_from_user(char *dst, const char *src, long count)
+{
+ if (access_ok(VERIFY_READ, src, 1))
+ return __strncpy_from_user(dst, src, count);
+ return -EFAULT;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+
+extern int __strnlen_user(const char *str, long len, unsigned long top);
+
+/*
+ * Returns the length of the string at str (including the null byte),
+ * or 0 if we hit a page we can't access,
+ * or something > len if we didn't find a null byte.
+ *
+ * The `top' parameter to __strnlen_user is to make sure that
+ * we can never overflow from the user area into kernel space.
+ */
+static inline long strnlen_user(const char __user *str, long len)
+{
+ unsigned long top = (unsigned long)get_fs();
+ unsigned long res = 0;
+
+ if (__addr_ok(str))
+ res = __strnlen_user(str, len, top);
+
+ return res;
+}
+
+#define strlen_user(str) strnlen_user(str, TASK_SIZE-1)
+
+#endif /* __ASM_OPENRISC_UACCESS_H */
diff --git a/arch/openrisc/include/asm/unaligned.h b/arch/openrisc/include/asm/unaligned.h
new file mode 100644
index 000000000000..1141cbd6fd72
--- /dev/null
+++ b/arch/openrisc/include/asm/unaligned.h
@@ -0,0 +1,51 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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_OPENRISC_UNALIGNED_H
+#define __ASM_OPENRISC_UNALIGNED_H
+
+/*
+ * This is copied from the generic implementation and the C-struct
+ * variant replaced with the memmove variant. The GCC compiler
+ * for the OR32 arch optimizes too aggressively for the C-struct
+ * variant to work, so use the memmove variant instead.
+ *
+ * It may be worth considering implementing the unaligned access
+ * exception handler and allowing unaligned accesses (access_ok.h)...
+ * not sure if it would be much of a performance win without further
+ * investigation.
+ */
+#include <asm/byteorder.h>
+
+#if defined(__LITTLE_ENDIAN)
+# include <linux/unaligned/le_memmove.h>
+# include <linux/unaligned/be_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_le
+# define put_unaligned __put_unaligned_le
+#elif defined(__BIG_ENDIAN)
+# include <linux/unaligned/be_memmove.h>
+# include <linux/unaligned/le_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_be
+# define put_unaligned __put_unaligned_be
+#else
+# error need to define endianess
+#endif
+
+#endif /* __ASM_OPENRISC_UNALIGNED_H */
diff --git a/arch/openrisc/include/asm/unistd.h b/arch/openrisc/include/asm/unistd.h
new file mode 100644
index 000000000000..89af3ab5c2e9
--- /dev/null
+++ b/arch/openrisc/include/asm/unistd.h
@@ -0,0 +1,31 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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.
+ */
+
+#if !defined(__ASM_OPENRISC_UNISTD_H) || defined(__SYSCALL)
+#define __ASM_OPENRISC_UNISTD_H
+
+#define __ARCH_HAVE_MMU
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#define __NR_or1k_atomic __NR_arch_specific_syscall
+__SYSCALL(__NR_or1k_atomic, sys_or1k_atomic)
+
+#endif /* __ASM_OPENRISC_UNISTD_H */
diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile
new file mode 100644
index 000000000000..9a4c2706d795
--- /dev/null
+++ b/arch/openrisc/kernel/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux kernel.
+#
+
+extra-y := head.o vmlinux.lds init_task.o
+
+obj-y := setup.o idle.o or32_ksyms.o process.o dma.o \
+ traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \
+ sys_call_table.o
+
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_OF) += prom.o
+
+clean:
diff --git a/arch/openrisc/kernel/asm-offsets.c b/arch/openrisc/kernel/asm-offsets.c
new file mode 100644
index 000000000000..1a242a0d7583
--- /dev/null
+++ b/arch/openrisc/kernel/asm-offsets.c
@@ -0,0 +1,70 @@
+/*
+ * OpenRISC asm-offsets.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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 used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+ /* offsets into the task_struct */
+ DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+ DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+ DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+ DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+
+ /* offsets into thread_info */
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_KSP, offsetof(struct thread_info, ksp));
+
+ DEFINE(PT_SIZE, sizeof(struct pt_regs));
+
+ /* Interrupt register frame */
+ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
+ DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+
+ DEFINE(NUM_USER_SEGMENTS, TASK_SIZE >> 28);
+ return 0;
+}
diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c
new file mode 100644
index 000000000000..968d3ee477e3
--- /dev/null
+++ b/arch/openrisc/kernel/dma.c
@@ -0,0 +1,191 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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.
+ *
+ * DMA mapping callbacks...
+ * As alloc_coherent is the only DMA callback being used currently, that's
+ * the only thing implemented properly. The rest need looking into...
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+
+#include <asm/cpuinfo.h>
+#include <asm/spr_defs.h>
+#include <asm/tlbflush.h>
+
+static int page_set_nocache(pte_t *pte, unsigned long addr,
+ unsigned long next, struct mm_walk *walk)
+{
+ unsigned long cl;
+
+ pte_val(*pte) |= _PAGE_CI;
+
+ /*
+ * Flush the page out of the TLB so that the new page flags get
+ * picked up next time there's an access
+ */
+ flush_tlb_page(NULL, addr);
+
+ /* Flush page out of dcache */
+ for (cl = __pa(addr); cl < __pa(next); cl += cpuinfo.dcache_block_size)
+ mtspr(SPR_DCBFR, cl);
+
+ return 0;
+}
+
+static int page_clear_nocache(pte_t *pte, unsigned long addr,
+ unsigned long next, struct mm_walk *walk)
+{
+ pte_val(*pte) &= ~_PAGE_CI;
+
+ /*
+ * Flush the page out of the TLB so that the new page flags get
+ * picked up next time there's an access
+ */
+ flush_tlb_page(NULL, addr);
+
+ return 0;
+}
+
+/*
+ * Alloc "coherent" memory, which for OpenRISC means simply uncached.
+ *
+ * This function effectively just calls __get_free_pages, sets the
+ * cache-inhibit bit on those pages, and makes sure that the pages are
+ * flushed out of the cache before they are used.
+ *
+ */
+void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp)
+{
+ unsigned long va;
+ void *page;
+ struct mm_walk walk = {
+ .pte_entry = page_set_nocache,
+ .mm = &init_mm
+ };
+
+ page = alloc_pages_exact(size, gfp);
+ if (!page)
+ return NULL;
+
+ /* This gives us the real physical address of the first page. */
+ *dma_handle = __pa(page);
+
+ va = (unsigned long)page;
+
+ /*
+ * We need to iterate through the pages, clearing the dcache for
+ * them and setting the cache-inhibit bit.
+ */
+ if (walk_page_range(va, va + size, &walk)) {
+ free_pages_exact(page, size);
+ return NULL;
+ }
+
+ return (void *)va;
+}
+
+void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ unsigned long va = (unsigned long)vaddr;
+ struct mm_walk walk = {
+ .pte_entry = page_clear_nocache,
+ .mm = &init_mm
+ };
+
+ /* walk_page_range shouldn't be able to fail here */
+ WARN_ON(walk_page_range(va, va + size, &walk));
+
+ free_pages_exact(vaddr, size);
+}
+
+dma_addr_t or1k_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ unsigned long cl;
+ dma_addr_t addr = page_to_phys(page) + offset;
+
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ /* Flush the dcache for the requested range */
+ for (cl = addr; cl < addr + size;
+ cl += cpuinfo.dcache_block_size)
+ mtspr(SPR_DCBFR, cl);
+ break;
+ case DMA_FROM_DEVICE:
+ /* Invalidate the dcache for the requested range */
+ for (cl = addr; cl < addr + size;
+ cl += cpuinfo.dcache_block_size)
+ mtspr(SPR_DCBIR, cl);
+ break;
+ default:
+ /*
+ * NOTE: If dir == DMA_BIDIRECTIONAL then there's no need to
+ * flush nor invalidate the cache here as the area will need
+ * to be manually synced anyway.
+ */
+ break;
+ }
+
+ return addr;
+}
+
+void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ /* Nothing special to do here... */
+}
+
+void or1k_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ unsigned long cl;
+ dma_addr_t addr = dma_handle;
+
+ /* Invalidate the dcache for the requested range */
+ for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
+ mtspr(SPR_DCBIR, cl);
+}
+
+void or1k_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ unsigned long cl;
+ dma_addr_t addr = dma_handle;
+
+ /* Flush the dcache for the requested range */
+ for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
+ mtspr(SPR_DCBFR, cl);
+}
+
+/* Number of entries preallocated for DMA-API debugging */
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init dma_init(void)
+{
+ dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+
+ return 0;
+}
+
+fs_initcall(dma_init);
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
new file mode 100644
index 000000000000..d5f9c35a583f
--- /dev/null
+++ b/arch/openrisc/kernel/entry.S
@@ -0,0 +1,1128 @@
+/*
+ * OpenRISC entry.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/processor.h>
+#include <asm/unistd.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/spr_defs.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/asm-offsets.h>
+
+#define DISABLE_INTERRUPTS(t1,t2) \
+ l.mfspr t2,r0,SPR_SR ;\
+ l.movhi t1,hi(~(SPR_SR_IEE|SPR_SR_TEE)) ;\
+ l.ori t1,t1,lo(~(SPR_SR_IEE|SPR_SR_TEE)) ;\
+ l.and t2,t2,t1 ;\
+ l.mtspr r0,t2,SPR_SR
+
+#define ENABLE_INTERRUPTS(t1) \
+ l.mfspr t1,r0,SPR_SR ;\
+ l.ori t1,t1,lo(SPR_SR_IEE|SPR_SR_TEE) ;\
+ l.mtspr r0,t1,SPR_SR
+
+/* =========================================================[ macros ]=== */
+
+/*
+ * We need to disable interrupts at beginning of RESTORE_ALL
+ * since interrupt might come in after we've loaded EPC return address
+ * and overwrite EPC with address somewhere in RESTORE_ALL
+ * which is of course wrong!
+ */
+
+#define RESTORE_ALL \
+ DISABLE_INTERRUPTS(r3,r4) ;\
+ l.lwz r3,PT_PC(r1) ;\
+ l.mtspr r0,r3,SPR_EPCR_BASE ;\
+ l.lwz r3,PT_SR(r1) ;\
+ l.mtspr r0,r3,SPR_ESR_BASE ;\
+ l.lwz r2,PT_GPR2(r1) ;\
+ l.lwz r3,PT_GPR3(r1) ;\
+ l.lwz r4,PT_GPR4(r1) ;\
+ l.lwz r5,PT_GPR5(r1) ;\
+ l.lwz r6,PT_GPR6(r1) ;\
+ l.lwz r7,PT_GPR7(r1) ;\
+ l.lwz r8,PT_GPR8(r1) ;\
+ l.lwz r9,PT_GPR9(r1) ;\
+ l.lwz r10,PT_GPR10(r1) ;\
+ l.lwz r11,PT_GPR11(r1) ;\
+ l.lwz r12,PT_GPR12(r1) ;\
+ l.lwz r13,PT_GPR13(r1) ;\
+ l.lwz r14,PT_GPR14(r1) ;\
+ l.lwz r15,PT_GPR15(r1) ;\
+ l.lwz r16,PT_GPR16(r1) ;\
+ l.lwz r17,PT_GPR17(r1) ;\
+ l.lwz r18,PT_GPR18(r1) ;\
+ l.lwz r19,PT_GPR19(r1) ;\
+ l.lwz r20,PT_GPR20(r1) ;\
+ l.lwz r21,PT_GPR21(r1) ;\
+ l.lwz r22,PT_GPR22(r1) ;\
+ l.lwz r23,PT_GPR23(r1) ;\
+ l.lwz r24,PT_GPR24(r1) ;\
+ l.lwz r25,PT_GPR25(r1) ;\
+ l.lwz r26,PT_GPR26(r1) ;\
+ l.lwz r27,PT_GPR27(r1) ;\
+ l.lwz r28,PT_GPR28(r1) ;\
+ l.lwz r29,PT_GPR29(r1) ;\
+ l.lwz r30,PT_GPR30(r1) ;\
+ l.lwz r31,PT_GPR31(r1) ;\
+ l.lwz r1,PT_SP(r1) ;\
+ l.rfe
+
+
+#define EXCEPTION_ENTRY(handler) \
+ .global handler ;\
+handler: ;\
+ /* r1, EPCR, ESR a already saved */ ;\
+ l.sw PT_GPR2(r1),r2 ;\
+ l.sw PT_GPR3(r1),r3 ;\
+ l.sw PT_ORIG_GPR11(r1),r11 ;\
+ /* r4 already save */ ;\
+ l.sw PT_GPR5(r1),r5 ;\
+ l.sw PT_GPR6(r1),r6 ;\
+ l.sw PT_GPR7(r1),r7 ;\
+ l.sw PT_GPR8(r1),r8 ;\
+ l.sw PT_GPR9(r1),r9 ;\
+ /* r10 already saved */ ;\
+ l.sw PT_GPR11(r1),r11 ;\
+ /* r12 already saved */ ;\
+ l.sw PT_GPR13(r1),r13 ;\
+ l.sw PT_GPR14(r1),r14 ;\
+ l.sw PT_GPR15(r1),r15 ;\
+ l.sw PT_GPR16(r1),r16 ;\
+ l.sw PT_GPR17(r1),r17 ;\
+ l.sw PT_GPR18(r1),r18 ;\
+ l.sw PT_GPR19(r1),r19 ;\
+ l.sw PT_GPR20(r1),r20 ;\
+ l.sw PT_GPR21(r1),r21 ;\
+ l.sw PT_GPR22(r1),r22 ;\
+ l.sw PT_GPR23(r1),r23 ;\
+ l.sw PT_GPR24(r1),r24 ;\
+ l.sw PT_GPR25(r1),r25 ;\
+ l.sw PT_GPR26(r1),r26 ;\
+ l.sw PT_GPR27(r1),r27 ;\
+ l.sw PT_GPR28(r1),r28 ;\
+ l.sw PT_GPR29(r1),r29 ;\
+ /* r30 already save */ ;\
+/* l.sw PT_GPR30(r1),r30*/ ;\
+ l.sw PT_GPR31(r1),r31 ;\
+ l.sw PT_SYSCALLNO(r1),r0
+
+#define UNHANDLED_EXCEPTION(handler,vector) \
+ .global handler ;\
+handler: ;\
+ /* r1, EPCR, ESR already saved */ ;\
+ l.sw PT_GPR2(r1),r2 ;\
+ l.sw PT_GPR3(r1),r3 ;\
+ l.sw PT_ORIG_GPR11(r1),r11 ;\
+ l.sw PT_GPR5(r1),r5 ;\
+ l.sw PT_GPR6(r1),r6 ;\
+ l.sw PT_GPR7(r1),r7 ;\
+ l.sw PT_GPR8(r1),r8 ;\
+ l.sw PT_GPR9(r1),r9 ;\
+ /* r10 already saved */ ;\
+ l.sw PT_GPR11(r1),r11 ;\
+ /* r12 already saved */ ;\
+ l.sw PT_GPR13(r1),r13 ;\
+ l.sw PT_GPR14(r1),r14 ;\
+ l.sw PT_GPR15(r1),r15 ;\
+ l.sw PT_GPR16(r1),r16 ;\
+ l.sw PT_GPR17(r1),r17 ;\
+ l.sw PT_GPR18(r1),r18 ;\
+ l.sw PT_GPR19(r1),r19 ;\
+ l.sw PT_GPR20(r1),r20 ;\
+ l.sw PT_GPR21(r1),r21 ;\
+ l.sw PT_GPR22(r1),r22 ;\
+ l.sw PT_GPR23(r1),r23 ;\
+ l.sw PT_GPR24(r1),r24 ;\
+ l.sw PT_GPR25(r1),r25 ;\
+ l.sw PT_GPR26(r1),r26 ;\
+ l.sw PT_GPR27(r1),r27 ;\
+ l.sw PT_GPR28(r1),r28 ;\
+ l.sw PT_GPR29(r1),r29 ;\
+ /* r31 already saved */ ;\
+ l.sw PT_GPR30(r1),r30 ;\
+/* l.sw PT_GPR31(r1),r31 */ ;\
+ l.sw PT_SYSCALLNO(r1),r0 ;\
+ l.addi r3,r1,0 ;\
+ /* r4 is exception EA */ ;\
+ l.addi r5,r0,vector ;\
+ l.jal unhandled_exception ;\
+ l.nop ;\
+ l.j _ret_from_exception ;\
+ l.nop
+
+/*
+ * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR
+ * contain the same values as when exception we're handling
+ * occured. in fact they never do. if you need them use
+ * values saved on stack (for SPR_EPC, SPR_ESR) or content
+ * of r4 (for SPR_EEAR). for details look at EXCEPTION_HANDLE()
+ * in 'arch/or32/kernel/head.S'
+ */
+
+/* =====================================================[ exceptions] === */
+
+/* ---[ 0x100: RESET exception ]----------------------------------------- */
+
+EXCEPTION_ENTRY(_tng_kernel_start)
+ l.jal _start
+ l.andi r0,r0,0
+
+/* ---[ 0x200: BUS exception ]------------------------------------------- */
+
+EXCEPTION_ENTRY(_bus_fault_handler)
+ /* r4: EA of fault (set by EXCEPTION_HANDLE) */
+ l.jal do_bus_fault
+ l.addi r3,r1,0 /* pt_regs */
+
+ l.j _ret_from_exception
+ l.nop
+
+/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
+
+EXCEPTION_ENTRY(_data_page_fault_handler)
+ /* set up parameters for do_page_fault */
+ l.addi r3,r1,0 // pt_regs
+ /* r4 set be EXCEPTION_HANDLE */ // effective address of fault
+ l.ori r5,r0,0x300 // exception vector
+
+ /*
+ * __PHX__: TODO
+ *
+ * all this can be written much simpler. look at
+ * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part
+ */
+#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
+ l.lwz r6,PT_PC(r3) // address of an offending insn
+ l.lwz r6,0(r6) // instruction that caused pf
+
+ l.srli r6,r6,26 // check opcode for jump insn
+ l.sfeqi r6,0 // l.j
+ l.bf 8f
+ l.sfeqi r6,1 // l.jal
+ l.bf 8f
+ l.sfeqi r6,3 // l.bnf
+ l.bf 8f
+ l.sfeqi r6,4 // l.bf
+ l.bf 8f
+ l.sfeqi r6,0x11 // l.jr
+ l.bf 8f
+ l.sfeqi r6,0x12 // l.jalr
+ l.bf 8f
+
+ l.nop
+
+ l.j 9f
+ l.nop
+8:
+
+ l.lwz r6,PT_PC(r3) // address of an offending insn
+ l.addi r6,r6,4
+ l.lwz r6,0(r6) // instruction that caused pf
+ l.srli r6,r6,26 // get opcode
+9:
+
+#else
+
+ l.mfspr r6,r0,SPR_SR // SR
+// l.lwz r6,PT_SR(r3) // ESR
+ l.andi r6,r6,SPR_SR_DSX // check for delay slot exception
+ l.sfeqi r6,0x1 // exception happened in delay slot
+ l.bnf 7f
+ l.lwz r6,PT_PC(r3) // address of an offending insn
+
+ l.addi r6,r6,4 // offending insn is in delay slot
+7:
+ l.lwz r6,0(r6) // instruction that caused pf
+ l.srli r6,r6,26 // check opcode for write access
+#endif
+
+ l.sfgeui r6,0x34 // check opcode for write access
+ l.bnf 1f
+ l.sfleui r6,0x37
+ l.bnf 1f
+ l.ori r6,r0,0x1 // write access
+ l.j 2f
+ l.nop
+1: l.ori r6,r0,0x0 // !write access
+2:
+
+ /* call fault.c handler in or32/mm/fault.c */
+ l.jal do_page_fault
+ l.nop
+ l.j _ret_from_exception
+ l.nop
+
+/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
+
+EXCEPTION_ENTRY(_insn_page_fault_handler)
+ /* set up parameters for do_page_fault */
+ l.addi r3,r1,0 // pt_regs
+ /* r4 set be EXCEPTION_HANDLE */ // effective address of fault
+ l.ori r5,r0,0x400 // exception vector
+ l.ori r6,r0,0x0 // !write access
+
+ /* call fault.c handler in or32/mm/fault.c */
+ l.jal do_page_fault
+ l.nop
+ l.j _ret_from_exception
+ l.nop
+
+
+/* ---[ 0x500: Timer exception ]----------------------------------------- */
+
+EXCEPTION_ENTRY(_timer_handler)
+ l.jal timer_interrupt
+ l.addi r3,r1,0 /* pt_regs */
+
+ l.j _ret_from_intr
+ l.nop
+
+/* ---[ 0x600: Aligment exception ]-------------------------------------- */
+
+EXCEPTION_ENTRY(_alignment_handler)
+ /* r4: EA of fault (set by EXCEPTION_HANDLE) */
+ l.jal do_unaligned_access
+ l.addi r3,r1,0 /* pt_regs */
+
+ l.j _ret_from_exception
+ l.nop
+
+#if 0
+EXCEPTION_ENTRY(_aligment_handler)
+// l.mfspr r2,r0,SPR_EEAR_BASE /* Load the efective addres */
+ l.addi r2,r4,0
+// l.mfspr r5,r0,SPR_EPCR_BASE /* Load the insn address */
+ l.lwz r5,PT_PC(r1)
+
+ l.lwz r3,0(r5) /* Load insn */
+ l.srli r4,r3,26 /* Shift left to get the insn opcode */
+
+ l.sfeqi r4,0x00 /* Check if the load/store insn is in delay slot */
+ l.bf jmp
+ l.sfeqi r4,0x01
+ l.bf jmp
+ l.sfeqi r4,0x03
+ l.bf jmp
+ l.sfeqi r4,0x04
+ l.bf jmp
+ l.sfeqi r4,0x11
+ l.bf jr
+ l.sfeqi r4,0x12
+ l.bf jr
+ l.nop
+ l.j 1f
+ l.addi r5,r5,4 /* Increment PC to get return insn address */
+
+jmp:
+ l.slli r4,r3,6 /* Get the signed extended jump length */
+ l.srai r4,r4,4
+
+ l.lwz r3,4(r5) /* Load the real load/store insn */
+
+ l.add r5,r5,r4 /* Calculate jump target address */
+
+ l.j 1f
+ l.srli r4,r3,26 /* Shift left to get the insn opcode */
+
+jr:
+ l.slli r4,r3,9 /* Shift to get the reg nb */
+ l.andi r4,r4,0x7c
+
+ l.lwz r3,4(r5) /* Load the real load/store insn */
+
+ l.add r4,r4,r1 /* Load the jump register value from the stack */
+ l.lwz r5,0(r4)
+
+ l.srli r4,r3,26 /* Shift left to get the insn opcode */
+
+
+1:
+// l.mtspr r0,r5,SPR_EPCR_BASE
+ l.sw PT_PC(r1),r5
+
+ l.sfeqi r4,0x26
+ l.bf lhs
+ l.sfeqi r4,0x25
+ l.bf lhz
+ l.sfeqi r4,0x22
+ l.bf lws
+ l.sfeqi r4,0x21
+ l.bf lwz
+ l.sfeqi r4,0x37
+ l.bf sh
+ l.sfeqi r4,0x35
+ l.bf sw
+ l.nop
+
+1: l.j 1b /* I don't know what to do */
+ l.nop
+
+lhs: l.lbs r5,0(r2)
+ l.slli r5,r5,8
+ l.lbz r6,1(r2)
+ l.or r5,r5,r6
+ l.srli r4,r3,19
+ l.andi r4,r4,0x7c
+ l.add r4,r4,r1
+ l.j align_end
+ l.sw 0(r4),r5
+
+lhz: l.lbz r5,0(r2)
+ l.slli r5,r5,8
+ l.lbz r6,1(r2)
+ l.or r5,r5,r6
+ l.srli r4,r3,19
+ l.andi r4,r4,0x7c
+ l.add r4,r4,r1
+ l.j align_end
+ l.sw 0(r4),r5
+
+lws: l.lbs r5,0(r2)
+ l.slli r5,r5,24
+ l.lbz r6,1(r2)
+ l.slli r6,r6,16
+ l.or r5,r5,r6
+ l.lbz r6,2(r2)
+ l.slli r6,r6,8
+ l.or r5,r5,r6
+ l.lbz r6,3(r2)
+ l.or r5,r5,r6
+ l.srli r4,r3,19
+ l.andi r4,r4,0x7c
+ l.add r4,r4,r1
+ l.j align_end
+ l.sw 0(r4),r5
+
+lwz: l.lbz r5,0(r2)
+ l.slli r5,r5,24
+ l.lbz r6,1(r2)
+ l.slli r6,r6,16
+ l.or r5,r5,r6
+ l.lbz r6,2(r2)
+ l.slli r6,r6,8
+ l.or r5,r5,r6
+ l.lbz r6,3(r2)
+ l.or r5,r5,r6
+ l.srli r4,r3,19
+ l.andi r4,r4,0x7c
+ l.add r4,r4,r1
+ l.j align_end
+ l.sw 0(r4),r5
+
+sh:
+ l.srli r4,r3,9
+ l.andi r4,r4,0x7c
+ l.add r4,r4,r1
+ l.lwz r5,0(r4)
+ l.sb 1(r2),r5
+ l.srli r5,r5,8
+ l.j align_end
+ l.sb 0(r2),r5
+
+sw:
+ l.srli r4,r3,9
+ l.andi r4,r4,0x7c
+ l.add r4,r4,r1
+ l.lwz r5,0(r4)
+ l.sb 3(r2),r5
+ l.srli r5,r5,8
+ l.sb 2(r2),r5
+ l.srli r5,r5,8
+ l.sb 1(r2),r5
+ l.srli r5,r5,8
+ l.j align_end
+ l.sb 0(r2),r5
+
+align_end:
+ l.j _ret_from_intr
+ l.nop
+#endif
+
+/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
+
+EXCEPTION_ENTRY(_illegal_instruction_handler)
+ /* r4: EA of fault (set by EXCEPTION_HANDLE) */
+ l.jal do_illegal_instruction
+ l.addi r3,r1,0 /* pt_regs */
+
+ l.j _ret_from_exception
+ l.nop
+
+/* ---[ 0x800: External interrupt exception ]---------------------------- */
+
+EXCEPTION_ENTRY(_external_irq_handler)
+#ifdef CONFIG_OPENRISC_ESR_EXCEPTION_BUG_CHECK
+ l.lwz r4,PT_SR(r1) // were interrupts enabled ?
+ l.andi r4,r4,SPR_SR_IEE
+ l.sfeqi r4,0
+ l.bnf 1f // ext irq enabled, all ok.
+ l.nop
+
+ l.addi r1,r1,-0x8
+ l.movhi r3,hi(42f)
+ l.ori r3,r3,lo(42f)
+ l.sw 0x0(r1),r3
+ l.jal printk
+ l.sw 0x4(r1),r4
+ l.addi r1,r1,0x8
+
+ .section .rodata, "a"
+42:
+ .string "\n\rESR interrupt bug: in _external_irq_handler (ESR %x)\n\r"
+ .align 4
+ .previous
+
+ l.ori r4,r4,SPR_SR_IEE // fix the bug
+// l.sw PT_SR(r1),r4
+1:
+#endif
+ l.addi r3,r1,0
+ l.movhi r8,hi(do_IRQ)
+ l.ori r8,r8,lo(do_IRQ)
+ l.jalr r8
+ l.nop
+ l.j _ret_from_intr
+ l.nop
+
+/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
+
+
+/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
+
+
+/* ---[ 0xb00: Range exception ]----------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0xb00,0xb00)
+
+/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
+
+/*
+ * Syscalls are a special type of exception in that they are
+ * _explicitly_ invoked by userspace and can therefore be
+ * held to conform to the same ABI as normal functions with
+ * respect to whether registers are preserved across the call
+ * or not.
+ */
+
+/* Upon syscall entry we just save the callee-saved registers
+ * and not the call-clobbered ones.
+ */
+
+_string_syscall_return:
+ .string "syscall return %ld \n\r\0"
+ .align 4
+
+ENTRY(_sys_call_handler)
+ /* syscalls run with interrupts enabled */
+ ENABLE_INTERRUPTS(r29) // enable interrupts, r29 is temp
+
+ /* r1, EPCR, ESR a already saved */
+ l.sw PT_GPR2(r1),r2
+ /* r3-r8 must be saved because syscall restart relies
+ * on us being able to restart the syscall args... technically
+ * they should be clobbered, otherwise
+ */
+ l.sw PT_GPR3(r1),r3
+ /* r4 already saved */
+ /* r4 holds the EEAR address of the fault, load the original r4 */
+ l.lwz r4,PT_GPR4(r1)
+ l.sw PT_GPR5(r1),r5
+ l.sw PT_GPR6(r1),r6
+ l.sw PT_GPR7(r1),r7
+ l.sw PT_GPR8(r1),r8
+ l.sw PT_GPR9(r1),r9
+ /* r10 already saved */
+ l.sw PT_GPR11(r1),r11
+ l.sw PT_ORIG_GPR11(r1),r11
+ /* r12,r13 already saved */
+
+ /* r14-r28 (even) aren't touched by the syscall fast path below
+ * so we don't need to save them. However, the functions that return
+ * to userspace via a call to switch() DO need to save these because
+ * switch() effectively clobbers them... saving these registers for
+ * such functions is handled in their syscall wrappers (see fork, vfork,
+ * and clone, below).
+
+ /* r30 is the only register we clobber in the fast path */
+ /* r30 already saved */
+/* l.sw PT_GPR30(r1),r30 */
+ /* This is used by do_signal to determine whether to check for
+ * syscall restart or not */
+ l.sw PT_SYSCALLNO(r1),r11
+
+_syscall_check_trace_enter:
+ /* If TIF_SYSCALL_TRACE is set, then we want to do syscall tracing */
+ l.lwz r30,TI_FLAGS(r10)
+ l.andi r30,r30,_TIF_SYSCALL_TRACE
+ l.sfne r30,r0
+ l.bf _syscall_trace_enter
+ l.nop
+
+_syscall_check:
+ /* Ensure that the syscall number is reasonable */
+ l.sfgeui r11,__NR_syscalls
+ l.bf _syscall_badsys
+ l.nop
+
+_syscall_call:
+ l.movhi r29,hi(sys_call_table)
+ l.ori r29,r29,lo(sys_call_table)
+ l.slli r11,r11,2
+ l.add r29,r29,r11
+ l.lwz r29,0(r29)
+
+ l.jalr r29
+ l.nop
+
+_syscall_return:
+ /* All syscalls return here... just pay attention to ret_from_fork
+ * which does it in a round-about way.
+ */
+ l.sw PT_GPR11(r1),r11 // save return value
+
+#if 0
+_syscall_debug:
+ l.movhi r3,hi(_string_syscall_return)
+ l.ori r3,r3,lo(_string_syscall_return)
+ l.ori r27,r0,1
+ l.sw -4(r1),r27
+ l.sw -8(r1),r11
+ l.addi r1,r1,-8
+ l.movhi r27,hi(printk)
+ l.ori r27,r27,lo(printk)
+ l.jalr r27
+ l.nop
+ l.addi r1,r1,8
+#endif
+
+_syscall_check_trace_leave:
+ /* r30 is a callee-saved register so this should still hold the
+ * _TIF_SYSCALL_TRACE flag from _syscall_check_trace_enter above...
+ * _syscall_trace_leave expects syscall result to be in pt_regs->r11.
+ */
+ l.sfne r30,r0
+ l.bf _syscall_trace_leave
+ l.nop
+
+/* This is where the exception-return code begins... interrupts need to be
+ * disabled the rest of the way here because we can't afford to miss any
+ * interrupts that set NEED_RESCHED or SIGNALPENDING... really true? */
+
+_syscall_check_work:
+ /* Here we need to disable interrupts */
+ DISABLE_INTERRUPTS(r27,r29)
+ l.lwz r30,TI_FLAGS(r10)
+ l.andi r30,r30,_TIF_WORK_MASK
+ l.sfne r30,r0
+
+ l.bnf _syscall_resume_userspace
+ l.nop
+
+ /* Work pending follows a different return path, so we need to
+ * make sure that all the call-saved registers get into pt_regs
+ * before branching...
+ */
+ l.sw PT_GPR14(r1),r14
+ l.sw PT_GPR16(r1),r16
+ l.sw PT_GPR18(r1),r18
+ l.sw PT_GPR20(r1),r20
+ l.sw PT_GPR22(r1),r22
+ l.sw PT_GPR24(r1),r24
+ l.sw PT_GPR26(r1),r26
+ l.sw PT_GPR28(r1),r28
+
+ /* _work_pending needs to be called with interrupts disabled */
+ l.j _work_pending
+ l.nop
+
+_syscall_resume_userspace:
+// ENABLE_INTERRUPTS(r29)
+
+
+/* This is the hot path for returning to userspace from a syscall. If there's
+ * work to be done and the branch to _work_pending was taken above, then the
+ * return to userspace will be done via the normal exception return path...
+ * that path restores _all_ registers and will overwrite the "clobbered"
+ * registers with whatever garbage is in pt_regs -- that's OK because those
+ * registers are clobbered anyway and because the extra work is insignificant
+ * in the context of the extra work that _work_pending is doing.
+
+/* Once again, syscalls are special and only guarantee to preserve the
+ * same registers as a normal function call */
+
+/* The assumption here is that the registers r14-r28 (even) are untouched and
+ * don't need to be restored... be sure that that's really the case!
+ */
+
+/* This is still too much... we should only be restoring what we actually
+ * clobbered... we should even be using 'scratch' (odd) regs above so that
+ * we don't need to restore anything, hardly...
+ */
+
+ l.lwz r2,PT_GPR2(r1)
+
+ /* Restore args */
+ /* r3-r8 are technically clobbered, but syscall restart needs these
+ * to be restored...
+ */
+ l.lwz r3,PT_GPR3(r1)
+ l.lwz r4,PT_GPR4(r1)
+ l.lwz r5,PT_GPR5(r1)
+ l.lwz r6,PT_GPR6(r1)
+ l.lwz r7,PT_GPR7(r1)
+ l.lwz r8,PT_GPR8(r1)
+
+ l.lwz r9,PT_GPR9(r1)
+ l.lwz r10,PT_GPR10(r1)
+ l.lwz r11,PT_GPR11(r1)
+
+ /* r30 is the only register we clobber in the fast path */
+ l.lwz r30,PT_GPR30(r1)
+
+ /* Here we use r13-r19 (odd) as scratch regs */
+ l.lwz r13,PT_PC(r1)
+ l.lwz r15,PT_SR(r1)
+ l.lwz r1,PT_SP(r1)
+ /* Interrupts need to be disabled for setting EPCR and ESR
+ * so that another interrupt doesn't come in here and clobber
+ * them before we can use them for our l.rfe */
+ DISABLE_INTERRUPTS(r17,r19)
+ l.mtspr r0,r13,SPR_EPCR_BASE
+ l.mtspr r0,r15,SPR_ESR_BASE
+ l.rfe
+
+/* End of hot path!
+ * Keep the below tracing and error handling out of the hot path...
+*/
+
+_syscall_trace_enter:
+ /* Here we pass pt_regs to do_syscall_trace_enter. Make sure
+ * that function is really getting all the info it needs as
+ * pt_regs isn't a complete set of userspace regs, just the
+ * ones relevant to the syscall...
+ *
+ * Note use of delay slot for setting argument.
+ */
+ l.jal do_syscall_trace_enter
+ l.addi r3,r1,0
+
+ /* Restore arguments (not preserved across do_syscall_trace_enter)
+ * so that we can do the syscall for real and return to the syscall
+ * hot path.
+ */
+ l.lwz r11,PT_SYSCALLNO(r1)
+ l.lwz r3,PT_GPR3(r1)
+ l.lwz r4,PT_GPR4(r1)
+ l.lwz r5,PT_GPR5(r1)
+ l.lwz r6,PT_GPR6(r1)
+ l.lwz r7,PT_GPR7(r1)
+
+ l.j _syscall_check
+ l.lwz r8,PT_GPR8(r1)
+
+_syscall_trace_leave:
+ l.jal do_syscall_trace_leave
+ l.addi r3,r1,0
+
+ l.j _syscall_check_work
+ l.nop
+
+_syscall_badsys:
+ /* Here we effectively pretend to have executed an imaginary
+ * syscall that returns -ENOSYS and then return to the regular
+ * syscall hot path.
+ * Note that "return value" is set in the delay slot...
+ */
+ l.j _syscall_return
+ l.addi r11,r0,-ENOSYS
+
+/******* END SYSCALL HANDLING *******/
+
+/* ---[ 0xd00: Trap exception ]------------------------------------------ */
+
+UNHANDLED_EXCEPTION(_vector_0xd00,0xd00)
+
+/* ---[ 0xe00: Trap exception ]------------------------------------------ */
+
+EXCEPTION_ENTRY(_trap_handler)
+ /* r4: EA of fault (set by EXCEPTION_HANDLE) */
+ l.jal do_trap
+ l.addi r3,r1,0 /* pt_regs */
+
+ l.j _ret_from_exception
+ l.nop
+
+/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0xf00,0xf00)
+
+/* ---[ 0x1000: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1000,0x1000)
+
+/* ---[ 0x1100: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1100,0x1100)
+
+/* ---[ 0x1200: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1200,0x1200)
+
+/* ---[ 0x1300: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1300,0x1300)
+
+/* ---[ 0x1400: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1400,0x1400)
+
+/* ---[ 0x1500: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1500,0x1500)
+
+/* ---[ 0x1600: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1600,0x1600)
+
+/* ---[ 0x1700: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1700,0x1700)
+
+/* ---[ 0x1800: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1800,0x1800)
+
+/* ---[ 0x1900: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1900,0x1900)
+
+/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1a00,0x1a00)
+
+/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1b00,0x1b00)
+
+/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1c00,0x1c00)
+
+/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1d00,0x1d00)
+
+/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1e00,0x1e00)
+
+/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00)
+
+/* ========================================================[ return ] === */
+
+_work_pending:
+ /*
+ * if (current_thread_info->flags & _TIF_NEED_RESCHED)
+ * schedule();
+ */
+ l.lwz r5,TI_FLAGS(r10)
+ l.andi r3,r5,_TIF_NEED_RESCHED
+ l.sfnei r3,0
+ l.bnf _work_notifysig
+ l.nop
+ l.jal schedule
+ l.nop
+ l.j _resume_userspace
+ l.nop
+
+/* Handle pending signals and notify-resume requests.
+ * do_notify_resume must be passed the latest pushed pt_regs, not
+ * necessarily the "userspace" ones. Also, pt_regs->syscallno
+ * must be set so that the syscall restart functionality works.
+ */
+_work_notifysig:
+ l.jal do_notify_resume
+ l.ori r3,r1,0 /* pt_regs */
+
+_resume_userspace:
+ DISABLE_INTERRUPTS(r3,r4)
+ l.lwz r3,TI_FLAGS(r10)
+ l.andi r3,r3,_TIF_WORK_MASK
+ l.sfnei r3,0
+ l.bf _work_pending
+ l.nop
+
+_restore_all:
+ RESTORE_ALL
+ /* This returns to userspace code */
+
+
+ENTRY(_ret_from_intr)
+ENTRY(_ret_from_exception)
+ l.lwz r4,PT_SR(r1)
+ l.andi r3,r4,SPR_SR_SM
+ l.sfeqi r3,0
+ l.bnf _restore_all
+ l.nop
+ l.j _resume_userspace
+ l.nop
+
+ENTRY(ret_from_fork)
+ l.jal schedule_tail
+ l.nop
+
+ /* _syscall_returns expect r11 to contain return value */
+ l.lwz r11,PT_GPR11(r1)
+
+ /* The syscall fast path return expects call-saved registers
+ * r12-r28 to be untouched, so we restore them here as they
+ * will have been effectively clobbered when arriving here
+ * via the call to switch()
+ */
+ l.lwz r12,PT_GPR12(r1)
+ l.lwz r14,PT_GPR14(r1)
+ l.lwz r16,PT_GPR16(r1)
+ l.lwz r18,PT_GPR18(r1)
+ l.lwz r20,PT_GPR20(r1)
+ l.lwz r22,PT_GPR22(r1)
+ l.lwz r24,PT_GPR24(r1)
+ l.lwz r26,PT_GPR26(r1)
+ l.lwz r28,PT_GPR28(r1)
+
+ l.j _syscall_return
+ l.nop
+
+/* Since syscalls don't save call-clobbered registers, the args to
+ * kernel_thread_helper will need to be passed through callee-saved
+ * registers and copied to the parameter registers when the thread
+ * begins running.
+ *
+ * See arch/openrisc/kernel/process.c:
+ * The args are passed as follows:
+ * arg1 (r3) : passed in r20
+ * arg2 (r4) : passed in r22
+ */
+
+ENTRY(_kernel_thread_helper)
+ l.or r3,r20,r0
+ l.or r4,r22,r0
+ l.movhi r31,hi(kernel_thread_helper)
+ l.ori r31,r31,lo(kernel_thread_helper)
+ l.jr r31
+ l.nop
+
+
+/* ========================================================[ switch ] === */
+
+/*
+ * This routine switches between two different tasks. The process
+ * state of one is saved on its kernel stack. Then the state
+ * of the other is restored from its kernel stack. The memory
+ * management hardware is updated to the second process's state.
+ * Finally, we can return to the second process, via the 'return'.
+ *
+ * Note: there are two ways to get to the "going out" portion
+ * of this code; either by coming in via the entry (_switch)
+ * or via "fork" which must set up an environment equivalent
+ * to the "_switch" path. If you change this (or in particular, the
+ * SAVE_REGS macro), you'll have to change the fork code also.
+ */
+
+
+/* _switch MUST never lay on page boundry, cause it runs from
+ * effective addresses and beeing interrupted by iTLB miss would kill it.
+ * dTLB miss seams to never accour in the bad place since data accesses
+ * are from task structures which are always page aligned.
+ *
+ * The problem happens in RESTORE_ALL_NO_R11 where we first set the EPCR
+ * register, then load the previous register values and only at the end call
+ * the l.rfe instruction. If get TLB miss in beetwen the EPCR register gets
+ * garbled and we end up calling l.rfe with the wrong EPCR. (same probably
+ * holds for ESR)
+ *
+ * To avoid this problems it is sufficient to align _switch to
+ * some nice round number smaller than it's size...
+ */
+
+/* ABI rules apply here... we either enter _switch via schedule() or via
+ * an imaginary call to which we shall return at return_from_fork. Either
+ * way, we are a function call and only need to preserve the callee-saved
+ * registers when we return. As such, we don't need to save the registers
+ * on the stack that we won't be returning as they were...
+ */
+
+ .align 0x400
+ENTRY(_switch)
+ /* We don't store SR as _switch only gets called in a context where
+ * the SR will be the same going in and coming out... */
+
+ /* Set up new pt_regs struct for saving task state */
+ l.addi r1,r1,-(INT_FRAME_SIZE)
+
+ /* No need to store r1/PT_SP as it goes into KSP below */
+ l.sw PT_GPR2(r1),r2
+ l.sw PT_GPR9(r1),r9
+ /* This is wrong, r12 shouldn't be here... but GCC is broken for the time being
+ * and expects r12 to be callee-saved... */
+ l.sw PT_GPR12(r1),r12
+ l.sw PT_GPR14(r1),r14
+ l.sw PT_GPR16(r1),r16
+ l.sw PT_GPR18(r1),r18
+ l.sw PT_GPR20(r1),r20
+ l.sw PT_GPR22(r1),r22
+ l.sw PT_GPR24(r1),r24
+ l.sw PT_GPR26(r1),r26
+ l.sw PT_GPR28(r1),r28
+ l.sw PT_GPR30(r1),r30
+
+ l.addi r11,r10,0 /* Save old 'current' to 'last' return value*/
+
+ /* We use thread_info->ksp for storing the address of the above
+ * structure so that we can get back to it later... we don't want
+ * to lose the value of thread_info->ksp, though, so store it as
+ * pt_regs->sp so that we can easily restore it when we are made
+ * live again...
+ */
+
+ /* Save the old value of thread_info->ksp as pt_regs->sp */
+ l.lwz r29,TI_KSP(r10)
+ l.sw PT_SP(r1),r29
+
+ /* Swap kernel stack pointers */
+ l.sw TI_KSP(r10),r1 /* Save old stack pointer */
+ l.or r10,r4,r0 /* Set up new current_thread_info */
+ l.lwz r1,TI_KSP(r10) /* Load new stack pointer */
+
+ /* Restore the old value of thread_info->ksp */
+ l.lwz r29,PT_SP(r1)
+ l.sw TI_KSP(r10),r29
+
+ /* ...and restore the registers, except r11 because the return value
+ * has already been set above.
+ */
+ l.lwz r2,PT_GPR2(r1)
+ l.lwz r9,PT_GPR9(r1)
+ /* No need to restore r10 */
+ /* ...and do not restore r11 */
+
+ /* This is wrong, r12 shouldn't be here... but GCC is broken for the time being
+ * and expects r12 to be callee-saved... */
+ l.lwz r12,PT_GPR12(r1)
+ l.lwz r14,PT_GPR14(r1)
+ l.lwz r16,PT_GPR16(r1)
+ l.lwz r18,PT_GPR18(r1)
+ l.lwz r20,PT_GPR20(r1)
+ l.lwz r22,PT_GPR22(r1)
+ l.lwz r24,PT_GPR24(r1)
+ l.lwz r26,PT_GPR26(r1)
+ l.lwz r28,PT_GPR28(r1)
+ l.lwz r30,PT_GPR30(r1)
+
+ /* Unwind stack to pre-switch state */
+ l.addi r1,r1,(INT_FRAME_SIZE)
+
+ /* Return via the link-register back to where we 'came from', where that can be
+ * either schedule() or return_from_fork()... */
+ l.jr r9
+ l.nop
+
+/* ==================================================================== */
+
+/* These all use the delay slot for setting the argument register, so the
+ * jump is always happening after the l.addi instruction.
+ *
+ * These are all just wrappers that don't touch the link-register r9, so the
+ * return from the "real" syscall function will return back to the syscall
+ * code that did the l.jal that brought us here.
+ */
+
+/* fork requires that we save all the callee-saved registers because they
+ * are all effectively clobbered by the call to _switch. Here we store
+ * all the registers that aren't touched by the syscall fast path and thus
+ * weren't saved there.
+ */
+
+_fork_save_extra_regs_and_call:
+ l.sw PT_GPR14(r1),r14
+ l.sw PT_GPR16(r1),r16
+ l.sw PT_GPR18(r1),r18
+ l.sw PT_GPR20(r1),r20
+ l.sw PT_GPR22(r1),r22
+ l.sw PT_GPR24(r1),r24
+ l.sw PT_GPR26(r1),r26
+ l.jr r29
+ l.sw PT_GPR28(r1),r28
+
+ENTRY(sys_clone)
+ l.movhi r29,hi(_sys_clone)
+ l.ori r29,r29,lo(_sys_clone)
+ l.j _fork_save_extra_regs_and_call
+ l.addi r7,r1,0
+
+ENTRY(sys_fork)
+ l.movhi r29,hi(_sys_fork)
+ l.ori r29,r29,lo(_sys_fork)
+ l.j _fork_save_extra_regs_and_call
+ l.addi r3,r1,0
+
+ENTRY(sys_execve)
+ l.j _sys_execve
+ l.addi r6,r1,0
+
+ENTRY(sys_sigaltstack)
+ l.j _sys_sigaltstack
+ l.addi r5,r1,0
+
+ENTRY(sys_rt_sigreturn)
+ l.j _sys_rt_sigreturn
+ l.addi r3,r1,0
+
+/* This is a catch-all syscall for atomic instructions for the OpenRISC 1000.
+ * The functions takes a variable number of parameters depending on which
+ * particular flavour of atomic you want... parameter 1 is a flag identifying
+ * the atomic in question. Currently, this function implements the
+ * following variants:
+ *
+ * XCHG:
+ * @flag: 1
+ * @ptr1:
+ * @ptr2:
+ * Atomically exchange the values in pointers 1 and 2.
+ *
+ */
+
+ENTRY(sys_or1k_atomic)
+ /* FIXME: This ignores r3 and always does an XCHG */
+ DISABLE_INTERRUPTS(r17,r19)
+ l.lwz r30,0(r4)
+ l.lwz r28,0(r5)
+ l.sw 0(r4),r28
+ l.sw 0(r5),r30
+ ENABLE_INTERRUPTS(r17)
+ l.jr r9
+ l.or r11,r0,r0
+
+/* ============================================================[ EOF ]=== */
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S
new file mode 100644
index 000000000000..c75018d22644
--- /dev/null
+++ b/arch/openrisc/kernel/head.S
@@ -0,0 +1,1607 @@
+/*
+ * OpenRISC head.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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 <linux/threads.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+#include <asm/spr_defs.h>
+#include <asm/asm-offsets.h>
+
+#define tophys(rd,rs) \
+ l.movhi rd,hi(-KERNELBASE) ;\
+ l.add rd,rd,rs
+
+#define CLEAR_GPR(gpr) \
+ l.or gpr,r0,r0
+
+#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
+ l.movhi gpr,hi(symbol) ;\
+ l.ori gpr,gpr,lo(symbol)
+
+
+#define UART_BASE_ADD 0x90000000
+
+#define EXCEPTION_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
+#define SYSCALL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
+
+/* ============================================[ tmp store locations ]=== */
+
+/*
+ * emergency_print temporary stores
+ */
+#define EMERGENCY_PRINT_STORE_GPR4 l.sw 0x20(r0),r4
+#define EMERGENCY_PRINT_LOAD_GPR4 l.lwz r4,0x20(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR5 l.sw 0x24(r0),r5
+#define EMERGENCY_PRINT_LOAD_GPR5 l.lwz r5,0x24(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR6 l.sw 0x28(r0),r6
+#define EMERGENCY_PRINT_LOAD_GPR6 l.lwz r6,0x28(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR7 l.sw 0x2c(r0),r7
+#define EMERGENCY_PRINT_LOAD_GPR7 l.lwz r7,0x2c(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR8 l.sw 0x30(r0),r8
+#define EMERGENCY_PRINT_LOAD_GPR8 l.lwz r8,0x30(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR9 l.sw 0x34(r0),r9
+#define EMERGENCY_PRINT_LOAD_GPR9 l.lwz r9,0x34(r0)
+
+
+/*
+ * TLB miss handlers temorary stores
+ */
+#define EXCEPTION_STORE_GPR9 l.sw 0x10(r0),r9
+#define EXCEPTION_LOAD_GPR9 l.lwz r9,0x10(r0)
+
+#define EXCEPTION_STORE_GPR2 l.sw 0x64(r0),r2
+#define EXCEPTION_LOAD_GPR2 l.lwz r2,0x64(r0)
+
+#define EXCEPTION_STORE_GPR3 l.sw 0x68(r0),r3
+#define EXCEPTION_LOAD_GPR3 l.lwz r3,0x68(r0)
+
+#define EXCEPTION_STORE_GPR4 l.sw 0x6c(r0),r4
+#define EXCEPTION_LOAD_GPR4 l.lwz r4,0x6c(r0)
+
+#define EXCEPTION_STORE_GPR5 l.sw 0x70(r0),r5
+#define EXCEPTION_LOAD_GPR5 l.lwz r5,0x70(r0)
+
+#define EXCEPTION_STORE_GPR6 l.sw 0x74(r0),r6
+#define EXCEPTION_LOAD_GPR6 l.lwz r6,0x74(r0)
+
+
+/*
+ * EXCEPTION_HANDLE temporary stores
+ */
+
+#define EXCEPTION_T_STORE_GPR30 l.sw 0x78(r0),r30
+#define EXCEPTION_T_LOAD_GPR30(reg) l.lwz reg,0x78(r0)
+
+#define EXCEPTION_T_STORE_GPR10 l.sw 0x7c(r0),r10
+#define EXCEPTION_T_LOAD_GPR10(reg) l.lwz reg,0x7c(r0)
+
+#define EXCEPTION_T_STORE_SP l.sw 0x80(r0),r1
+#define EXCEPTION_T_LOAD_SP(reg) l.lwz reg,0x80(r0)
+
+/*
+ * For UNHANLDED_EXCEPTION
+ */
+
+#define EXCEPTION_T_STORE_GPR31 l.sw 0x84(r0),r31
+#define EXCEPTION_T_LOAD_GPR31(reg) l.lwz reg,0x84(r0)
+
+/* =========================================================[ macros ]=== */
+
+
+#define GET_CURRENT_PGD(reg,t1) \
+ LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
+ tophys (t1,reg) ;\
+ l.lwz reg,0(t1)
+
+
+/*
+ * DSCR: this is a common hook for handling exceptions. it will save
+ * the needed registers, set up stack and pointer to current
+ * then jump to the handler while enabling MMU
+ *
+ * PRMS: handler - a function to jump to. it has to save the
+ * remaining registers to kernel stack, call
+ * appropriate arch-independant exception handler
+ * and finaly jump to ret_from_except
+ *
+ * PREQ: unchanged state from the time exception happened
+ *
+ * POST: SAVED the following registers original value
+ * to the new created exception frame pointed to by r1
+ *
+ * r1 - ksp pointing to the new (exception) frame
+ * r4 - EEAR exception EA
+ * r10 - current pointing to current_thread_info struct
+ * r12 - syscall 0, since we didn't come from syscall
+ * r13 - temp it actually contains new SR, not needed anymore
+ * r31 - handler address of the handler we'll jump to
+ *
+ * handler has to save remaining registers to the exception
+ * ksp frame *before* tainting them!
+ *
+ * NOTE: this function is not reentrant per se. reentrancy is guaranteed
+ * by processor disabling all exceptions/interrupts when exception
+ * accours.
+ *
+ * OPTM: no need to make it so wasteful to extract ksp when in user mode
+ */
+
+#define EXCEPTION_HANDLE(handler) \
+ EXCEPTION_T_STORE_GPR30 ;\
+ l.mfspr r30,r0,SPR_ESR_BASE ;\
+ l.andi r30,r30,SPR_SR_SM ;\
+ l.sfeqi r30,0 ;\
+ EXCEPTION_T_STORE_GPR10 ;\
+ l.bnf 2f /* kernel_mode */ ;\
+ EXCEPTION_T_STORE_SP /* delay slot */ ;\
+1: /* user_mode: */ ;\
+ LOAD_SYMBOL_2_GPR(r1,current_thread_info_set) ;\
+ tophys (r30,r1) ;\
+ /* r10: current_thread_info */ ;\
+ l.lwz r10,0(r30) ;\
+ tophys (r30,r10) ;\
+ l.lwz r1,(TI_KSP)(r30) ;\
+ /* fall through */ ;\
+2: /* kernel_mode: */ ;\
+ /* create new stack frame, save only needed gprs */ ;\
+ /* r1: KSP, r10: current, r4: EEAR, r31: __pa(KSP) */ ;\
+ /* r12: temp, syscall indicator */ ;\
+ l.addi r1,r1,-(INT_FRAME_SIZE) ;\
+ /* r1 is KSP, r30 is __pa(KSP) */ ;\
+ tophys (r30,r1) ;\
+ l.sw PT_GPR12(r30),r12 ;\
+ l.mfspr r12,r0,SPR_EPCR_BASE ;\
+ l.sw PT_PC(r30),r12 ;\
+ l.mfspr r12,r0,SPR_ESR_BASE ;\
+ l.sw PT_SR(r30),r12 ;\
+ /* save r30 */ ;\
+ EXCEPTION_T_LOAD_GPR30(r12) ;\
+ l.sw PT_GPR30(r30),r12 ;\
+ /* save r10 as was prior to exception */ ;\
+ EXCEPTION_T_LOAD_GPR10(r12) ;\
+ l.sw PT_GPR10(r30),r12 ;\
+ /* save PT_SP as was prior to exception */ ;\
+ EXCEPTION_T_LOAD_SP(r12) ;\
+ l.sw PT_SP(r30),r12 ;\
+ /* save exception r4, set r4 = EA */ ;\
+ l.sw PT_GPR4(r30),r4 ;\
+ l.mfspr r4,r0,SPR_EEAR_BASE ;\
+ /* r12 == 1 if we come from syscall */ ;\
+ CLEAR_GPR(r12) ;\
+ /* ----- turn on MMU ----- */ ;\
+ l.ori r30,r0,(EXCEPTION_SR) ;\
+ l.mtspr r0,r30,SPR_ESR_BASE ;\
+ /* r30: EA address of handler */ ;\
+ LOAD_SYMBOL_2_GPR(r30,handler) ;\
+ l.mtspr r0,r30,SPR_EPCR_BASE ;\
+ l.rfe
+
+/*
+ * this doesn't work
+ *
+ *
+ * #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
+ * #define UNHANDLED_EXCEPTION(handler) \
+ * l.ori r3,r0,0x1 ;\
+ * l.mtspr r0,r3,SPR_SR ;\
+ * l.movhi r3,hi(0xf0000100) ;\
+ * l.ori r3,r3,lo(0xf0000100) ;\
+ * l.jr r3 ;\
+ * l.nop 1
+ *
+ * #endif
+ */
+
+/* DSCR: this is the same as EXCEPTION_HANDLE(), we are just
+ * a bit more carefull (if we have a PT_SP or current pointer
+ * corruption) and set them up from 'current_set'
+ *
+ */
+#define UNHANDLED_EXCEPTION(handler) \
+ EXCEPTION_T_STORE_GPR31 ;\
+ EXCEPTION_T_STORE_GPR10 ;\
+ EXCEPTION_T_STORE_SP ;\
+ /* temporary store r3, r9 into r1, r10 */ ;\
+ l.addi r1,r3,0x0 ;\
+ l.addi r10,r9,0x0 ;\
+ /* the string referenced by r3 must be low enough */ ;\
+ l.jal _emergency_print ;\
+ l.ori r3,r0,lo(_string_unhandled_exception) ;\
+ l.mfspr r3,r0,SPR_NPC ;\
+ l.jal _emergency_print_nr ;\
+ l.andi r3,r3,0x1f00 ;\
+ /* the string referenced by r3 must be low enough */ ;\
+ l.jal _emergency_print ;\
+ l.ori r3,r0,lo(_string_epc_prefix) ;\
+ l.jal _emergency_print_nr ;\
+ l.mfspr r3,r0,SPR_EPCR_BASE ;\
+ l.jal _emergency_print ;\
+ l.ori r3,r0,lo(_string_nl) ;\
+ /* end of printing */ ;\
+ l.addi r3,r1,0x0 ;\
+ l.addi r9,r10,0x0 ;\
+ /* extract current, ksp from current_set */ ;\
+ LOAD_SYMBOL_2_GPR(r1,_unhandled_stack_top) ;\
+ LOAD_SYMBOL_2_GPR(r10,init_thread_union) ;\
+ /* create new stack frame, save only needed gprs */ ;\
+ /* r1: KSP, r10: current, r31: __pa(KSP) */ ;\
+ /* r12: temp, syscall indicator, r13 temp */ ;\
+ l.addi r1,r1,-(INT_FRAME_SIZE) ;\
+ /* r1 is KSP, r31 is __pa(KSP) */ ;\
+ tophys (r31,r1) ;\
+ l.sw PT_GPR12(r31),r12 ;\
+ l.mfspr r12,r0,SPR_EPCR_BASE ;\
+ l.sw PT_PC(r31),r12 ;\
+ l.mfspr r12,r0,SPR_ESR_BASE ;\
+ l.sw PT_SR(r31),r12 ;\
+ /* save r31 */ ;\
+ EXCEPTION_T_LOAD_GPR31(r12) ;\
+ l.sw PT_GPR31(r31),r12 ;\
+ /* save r10 as was prior to exception */ ;\
+ EXCEPTION_T_LOAD_GPR10(r12) ;\
+ l.sw PT_GPR10(r31),r12 ;\
+ /* save PT_SP as was prior to exception */ ;\
+ EXCEPTION_T_LOAD_SP(r12) ;\
+ l.sw PT_SP(r31),r12 ;\
+ l.sw PT_GPR13(r31),r13 ;\
+ /* --> */ ;\
+ /* save exception r4, set r4 = EA */ ;\
+ l.sw PT_GPR4(r31),r4 ;\
+ l.mfspr r4,r0,SPR_EEAR_BASE ;\
+ /* r12 == 1 if we come from syscall */ ;\
+ CLEAR_GPR(r12) ;\
+ /* ----- play a MMU trick ----- */ ;\
+ l.ori r31,r0,(EXCEPTION_SR) ;\
+ l.mtspr r0,r31,SPR_ESR_BASE ;\
+ /* r31: EA address of handler */ ;\
+ LOAD_SYMBOL_2_GPR(r31,handler) ;\
+ l.mtspr r0,r31,SPR_EPCR_BASE ;\
+ l.rfe
+
+/* =====================================================[ exceptions] === */
+
+/* ---[ 0x100: RESET exception ]----------------------------------------- */
+ .org 0x100
+ /* Jump to .init code at _start which lives in the .head section
+ * and will be discarded after boot.
+ */
+ LOAD_SYMBOL_2_GPR(r4, _start)
+ tophys (r3,r4) /* MMU disabled */
+ l.jr r3
+ l.nop
+
+/* ---[ 0x200: BUS exception ]------------------------------------------- */
+ .org 0x200
+_dispatch_bus_fault:
+ EXCEPTION_HANDLE(_bus_fault_handler)
+
+/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
+ .org 0x300
+_dispatch_do_dpage_fault:
+// totaly disable timer interrupt
+// l.mtspr r0,r0,SPR_TTMR
+// DEBUG_TLB_PROBE(0x300)
+// EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x300)
+ EXCEPTION_HANDLE(_data_page_fault_handler)
+
+/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
+ .org 0x400
+_dispatch_do_ipage_fault:
+// totaly disable timer interrupt
+// l.mtspr r0,r0,SPR_TTMR
+// DEBUG_TLB_PROBE(0x400)
+// EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x400)
+ EXCEPTION_HANDLE(_insn_page_fault_handler)
+
+/* ---[ 0x500: Timer exception ]----------------------------------------- */
+ .org 0x500
+ EXCEPTION_HANDLE(_timer_handler)
+
+/* ---[ 0x600: Aligment exception ]-------------------------------------- */
+ .org 0x600
+ EXCEPTION_HANDLE(_alignment_handler)
+
+/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
+ .org 0x700
+ EXCEPTION_HANDLE(_illegal_instruction_handler)
+
+/* ---[ 0x800: External interrupt exception ]---------------------------- */
+ .org 0x800
+ EXCEPTION_HANDLE(_external_irq_handler)
+
+/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
+ .org 0x900
+ l.j boot_dtlb_miss_handler
+ l.nop
+
+/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
+ .org 0xa00
+ l.j boot_itlb_miss_handler
+ l.nop
+
+/* ---[ 0xb00: Range exception ]----------------------------------------- */
+ .org 0xb00
+ UNHANDLED_EXCEPTION(_vector_0xb00)
+
+/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
+ .org 0xc00
+ EXCEPTION_HANDLE(_sys_call_handler)
+
+/* ---[ 0xd00: Trap exception ]------------------------------------------ */
+ .org 0xd00
+ UNHANDLED_EXCEPTION(_vector_0xd00)
+
+/* ---[ 0xe00: Trap exception ]------------------------------------------ */
+ .org 0xe00
+// UNHANDLED_EXCEPTION(_vector_0xe00)
+ EXCEPTION_HANDLE(_trap_handler)
+
+/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
+ .org 0xf00
+ UNHANDLED_EXCEPTION(_vector_0xf00)
+
+/* ---[ 0x1000: Reserved exception ]------------------------------------- */
+ .org 0x1000
+ UNHANDLED_EXCEPTION(_vector_0x1000)
+
+/* ---[ 0x1100: Reserved exception ]------------------------------------- */
+ .org 0x1100
+ UNHANDLED_EXCEPTION(_vector_0x1100)
+
+/* ---[ 0x1200: Reserved exception ]------------------------------------- */
+ .org 0x1200
+ UNHANDLED_EXCEPTION(_vector_0x1200)
+
+/* ---[ 0x1300: Reserved exception ]------------------------------------- */
+ .org 0x1300
+ UNHANDLED_EXCEPTION(_vector_0x1300)
+
+/* ---[ 0x1400: Reserved exception ]------------------------------------- */
+ .org 0x1400
+ UNHANDLED_EXCEPTION(_vector_0x1400)
+
+/* ---[ 0x1500: Reserved exception ]------------------------------------- */
+ .org 0x1500
+ UNHANDLED_EXCEPTION(_vector_0x1500)
+
+/* ---[ 0x1600: Reserved exception ]------------------------------------- */
+ .org 0x1600
+ UNHANDLED_EXCEPTION(_vector_0x1600)
+
+/* ---[ 0x1700: Reserved exception ]------------------------------------- */
+ .org 0x1700
+ UNHANDLED_EXCEPTION(_vector_0x1700)
+
+/* ---[ 0x1800: Reserved exception ]------------------------------------- */
+ .org 0x1800
+ UNHANDLED_EXCEPTION(_vector_0x1800)
+
+/* ---[ 0x1900: Reserved exception ]------------------------------------- */
+ .org 0x1900
+ UNHANDLED_EXCEPTION(_vector_0x1900)
+
+/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
+ .org 0x1a00
+ UNHANDLED_EXCEPTION(_vector_0x1a00)
+
+/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
+ .org 0x1b00
+ UNHANDLED_EXCEPTION(_vector_0x1b00)
+
+/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
+ .org 0x1c00
+ UNHANDLED_EXCEPTION(_vector_0x1c00)
+
+/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
+ .org 0x1d00
+ UNHANDLED_EXCEPTION(_vector_0x1d00)
+
+/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
+ .org 0x1e00
+ UNHANDLED_EXCEPTION(_vector_0x1e00)
+
+/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
+ .org 0x1f00
+ UNHANDLED_EXCEPTION(_vector_0x1f00)
+
+ .org 0x2000
+/* ===================================================[ kernel start ]=== */
+
+/* .text*/
+
+/* This early stuff belongs in HEAD, but some of the functions below definitely
+ * don't... */
+
+ __HEAD
+ .global _start
+_start:
+ /*
+ * ensure a deterministic start
+ */
+
+ l.ori r3,r0,0x1
+ l.mtspr r0,r3,SPR_SR
+
+ CLEAR_GPR(r1)
+ CLEAR_GPR(r2)
+ CLEAR_GPR(r3)
+ CLEAR_GPR(r4)
+ CLEAR_GPR(r5)
+ CLEAR_GPR(r6)
+ CLEAR_GPR(r7)
+ CLEAR_GPR(r8)
+ CLEAR_GPR(r9)
+ CLEAR_GPR(r10)
+ CLEAR_GPR(r11)
+ CLEAR_GPR(r12)
+ CLEAR_GPR(r13)
+ CLEAR_GPR(r14)
+ CLEAR_GPR(r15)
+ CLEAR_GPR(r16)
+ CLEAR_GPR(r17)
+ CLEAR_GPR(r18)
+ CLEAR_GPR(r19)
+ CLEAR_GPR(r20)
+ CLEAR_GPR(r21)
+ CLEAR_GPR(r22)
+ CLEAR_GPR(r23)
+ CLEAR_GPR(r24)
+ CLEAR_GPR(r25)
+ CLEAR_GPR(r26)
+ CLEAR_GPR(r27)
+ CLEAR_GPR(r28)
+ CLEAR_GPR(r29)
+ CLEAR_GPR(r30)
+ CLEAR_GPR(r31)
+
+ /*
+ * set up initial ksp and current
+ */
+ LOAD_SYMBOL_2_GPR(r1,init_thread_union+0x2000) // setup kernel stack
+ LOAD_SYMBOL_2_GPR(r10,init_thread_union) // setup current
+ tophys (r31,r10)
+ l.sw TI_KSP(r31), r1
+
+ l.ori r4,r0,0x0
+
+
+ /*
+ * .data contains initialized data,
+ * .bss contains uninitialized data - clear it up
+ */
+clear_bss:
+ LOAD_SYMBOL_2_GPR(r24, __bss_start)
+ LOAD_SYMBOL_2_GPR(r26, _end)
+ tophys(r28,r24)
+ tophys(r30,r26)
+ CLEAR_GPR(r24)
+ CLEAR_GPR(r26)
+1:
+ l.sw (0)(r28),r0
+ l.sfltu r28,r30
+ l.bf 1b
+ l.addi r28,r28,4
+
+enable_ic:
+ l.jal _ic_enable
+ l.nop
+
+enable_dc:
+ l.jal _dc_enable
+ l.nop
+
+flush_tlb:
+ /*
+ * I N V A L I D A T E T L B e n t r i e s
+ */
+ LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
+ LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
+ l.addi r7,r0,128 /* Maximum number of sets */
+1:
+ l.mtspr r5,r0,0x0
+ l.mtspr r6,r0,0x0
+
+ l.addi r5,r5,1
+ l.addi r6,r6,1
+ l.sfeq r7,r0
+ l.bnf 1b
+ l.addi r7,r7,-1
+
+
+/* The MMU needs to be enabled before or32_early_setup is called */
+
+enable_mmu:
+ /*
+ * enable dmmu & immu
+ * SR[5] = 0, SR[6] = 0, 6th and 7th bit of SR set to 0
+ */
+ l.mfspr r30,r0,SPR_SR
+ l.movhi r28,hi(SPR_SR_DME | SPR_SR_IME)
+ l.ori r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
+ l.or r30,r30,r28
+ l.mtspr r0,r30,SPR_SR
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+
+ // reset the simulation counters
+ l.nop 5
+
+ LOAD_SYMBOL_2_GPR(r24, or32_early_setup)
+ l.jalr r24
+ l.nop
+
+clear_regs:
+ /*
+ * clear all GPRS to increase determinism
+ */
+ CLEAR_GPR(r2)
+ CLEAR_GPR(r3)
+ CLEAR_GPR(r4)
+ CLEAR_GPR(r5)
+ CLEAR_GPR(r6)
+ CLEAR_GPR(r7)
+ CLEAR_GPR(r8)
+ CLEAR_GPR(r9)
+ CLEAR_GPR(r11)
+ CLEAR_GPR(r12)
+ CLEAR_GPR(r13)
+ CLEAR_GPR(r14)
+ CLEAR_GPR(r15)
+ CLEAR_GPR(r16)
+ CLEAR_GPR(r17)
+ CLEAR_GPR(r18)
+ CLEAR_GPR(r19)
+ CLEAR_GPR(r20)
+ CLEAR_GPR(r21)
+ CLEAR_GPR(r22)
+ CLEAR_GPR(r23)
+ CLEAR_GPR(r24)
+ CLEAR_GPR(r25)
+ CLEAR_GPR(r26)
+ CLEAR_GPR(r27)
+ CLEAR_GPR(r28)
+ CLEAR_GPR(r29)
+ CLEAR_GPR(r30)
+ CLEAR_GPR(r31)
+
+jump_start_kernel:
+ /*
+ * jump to kernel entry (start_kernel)
+ */
+ LOAD_SYMBOL_2_GPR(r30, start_kernel)
+ l.jr r30
+ l.nop
+
+/* ========================================[ cache ]=== */
+
+ /* aligment here so we don't change memory offsets with
+ * memory controler defined
+ */
+ .align 0x2000
+
+_ic_enable:
+ /* Check if IC present and skip enabling otherwise */
+ l.mfspr r24,r0,SPR_UPR
+ l.andi r26,r24,SPR_UPR_ICP
+ l.sfeq r26,r0
+ l.bf 9f
+ l.nop
+
+ /* Disable IC */
+ l.mfspr r6,r0,SPR_SR
+ l.addi r5,r0,-1
+ l.xori r5,r5,SPR_SR_ICE
+ l.and r5,r6,r5
+ l.mtspr r0,r5,SPR_SR
+
+ /* Establish cache block size
+ If BS=0, 16;
+ If BS=1, 32;
+ r14 contain block size
+ */
+ l.mfspr r24,r0,SPR_ICCFGR
+ l.andi r26,r24,SPR_ICCFGR_CBS
+ l.srli r28,r26,7
+ l.ori r30,r0,16
+ l.sll r14,r30,r28
+
+ /* Establish number of cache sets
+ r16 contains number of cache sets
+ r28 contains log(# of cache sets)
+ */
+ l.andi r26,r24,SPR_ICCFGR_NCS
+ l.srli r28,r26,3
+ l.ori r30,r0,1
+ l.sll r16,r30,r28
+
+ /* Invalidate IC */
+ l.addi r6,r0,0
+ l.sll r5,r14,r28
+// l.mul r5,r14,r16
+// l.trap 1
+// l.addi r5,r0,IC_SIZE
+1:
+ l.mtspr r0,r6,SPR_ICBIR
+ l.sfne r6,r5
+ l.bf 1b
+ l.add r6,r6,r14
+ // l.addi r6,r6,IC_LINE
+
+ /* Enable IC */
+ l.mfspr r6,r0,SPR_SR
+ l.ori r6,r6,SPR_SR_ICE
+ l.mtspr r0,r6,SPR_SR
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+ l.nop
+9:
+ l.jr r9
+ l.nop
+
+_dc_enable:
+ /* Check if DC present and skip enabling otherwise */
+ l.mfspr r24,r0,SPR_UPR
+ l.andi r26,r24,SPR_UPR_DCP
+ l.sfeq r26,r0
+ l.bf 9f
+ l.nop
+
+ /* Disable DC */
+ l.mfspr r6,r0,SPR_SR
+ l.addi r5,r0,-1
+ l.xori r5,r5,SPR_SR_DCE
+ l.and r5,r6,r5
+ l.mtspr r0,r5,SPR_SR
+
+ /* Establish cache block size
+ If BS=0, 16;
+ If BS=1, 32;
+ r14 contain block size
+ */
+ l.mfspr r24,r0,SPR_DCCFGR
+ l.andi r26,r24,SPR_DCCFGR_CBS
+ l.srli r28,r26,7
+ l.ori r30,r0,16
+ l.sll r14,r30,r28
+
+ /* Establish number of cache sets
+ r16 contains number of cache sets
+ r28 contains log(# of cache sets)
+ */
+ l.andi r26,r24,SPR_DCCFGR_NCS
+ l.srli r28,r26,3
+ l.ori r30,r0,1
+ l.sll r16,r30,r28
+
+ /* Invalidate DC */
+ l.addi r6,r0,0
+ l.sll r5,r14,r28
+1:
+ l.mtspr r0,r6,SPR_DCBIR
+ l.sfne r6,r5
+ l.bf 1b
+ l.add r6,r6,r14
+
+ /* Enable DC */
+ l.mfspr r6,r0,SPR_SR
+ l.ori r6,r6,SPR_SR_DCE
+ l.mtspr r0,r6,SPR_SR
+9:
+ l.jr r9
+ l.nop
+
+/* ===============================================[ page table masks ]=== */
+
+/* bit 4 is used in hardware as write back cache bit. we never use this bit
+ * explicitly, so we can reuse it as _PAGE_FILE bit and mask it out when
+ * writing into hardware pte's
+ */
+
+#define DTLB_UP_CONVERT_MASK 0x3fa
+#define ITLB_UP_CONVERT_MASK 0x3a
+
+/* for SMP we'd have (this is a bit subtle, CC must be always set
+ * for SMP, but since we have _PAGE_PRESENT bit always defined
+ * we can just modify the mask)
+ */
+#define DTLB_SMP_CONVERT_MASK 0x3fb
+#define ITLB_SMP_CONVERT_MASK 0x3b
+
+/* ---[ boot dtlb miss handler ]----------------------------------------- */
+
+boot_dtlb_miss_handler:
+
+/* mask for DTLB_MR register: - (0) sets V (valid) bit,
+ * - (31-12) sets bits belonging to VPN (31-12)
+ */
+#define DTLB_MR_MASK 0xfffff001
+
+/* mask for DTLB_TR register: - (2) sets CI (cache inhibit) bit,
+ * - (4) sets A (access) bit,
+ * - (5) sets D (dirty) bit,
+ * - (8) sets SRE (superuser read) bit
+ * - (9) sets SWE (superuser write) bit
+ * - (31-12) sets bits belonging to VPN (31-12)
+ */
+#define DTLB_TR_MASK 0xfffff332
+
+/* These are for masking out the VPN/PPN value from the MR/TR registers...
+ * it's not the same as the PFN */
+#define VPN_MASK 0xfffff000
+#define PPN_MASK 0xfffff000
+
+
+ EXCEPTION_STORE_GPR6
+
+#if 0
+ l.mfspr r6,r0,SPR_ESR_BASE //
+ l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
+ l.sfeqi r6,0 // r6 == 0x1 --> SM
+ l.bf exit_with_no_dtranslation //
+ l.nop
+#endif
+
+ /* this could be optimized by moving storing of
+ * non r6 registers here, and jumping r6 restore
+ * if not in supervisor mode
+ */
+
+ EXCEPTION_STORE_GPR2
+ EXCEPTION_STORE_GPR3
+ EXCEPTION_STORE_GPR4
+ EXCEPTION_STORE_GPR5
+
+ l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
+
+immediate_translation:
+ CLEAR_GPR(r6)
+
+ l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
+
+ l.mfspr r6, r0, SPR_DMMUCFGR
+ l.andi r6, r6, SPR_DMMUCFGR_NTS
+ l.srli r6, r6, SPR_DMMUCFGR_NTS_OFF
+ l.ori r5, r0, 0x1
+ l.sll r5, r5, r6 // r5 = number DMMU sets
+ l.addi r6, r5, -1 // r6 = nsets mask
+ l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
+
+ l.or r6,r6,r4 // r6 <- r4
+ l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
+ l.movhi r5,hi(DTLB_MR_MASK) // r5 <- ffff:0000.x000
+ l.ori r5,r5,lo(DTLB_MR_MASK) // r5 <- ffff:1111.x001 - apply DTLB_MR_MASK
+ l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have DTLBMR entry
+ l.mtspr r2,r5,SPR_DTLBMR_BASE(0) // set DTLBMR
+
+ /* set up DTLB with no translation for EA <= 0xbfffffff */
+ LOAD_SYMBOL_2_GPR(r6,0xbfffffff)
+ l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xbfffffff >= EA)
+ l.bf 1f // goto out
+ l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
+
+ tophys(r3,r4) // r3 <- PA
+1:
+ l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
+ l.movhi r5,hi(DTLB_TR_MASK) // r5 <- ffff:0000.x000
+ l.ori r5,r5,lo(DTLB_TR_MASK) // r5 <- ffff:1111.x330 - apply DTLB_MR_MASK
+ l.and r5,r5,r3 // r5 <- PPN :PPN .x330 - we have DTLBTR entry
+ l.mtspr r2,r5,SPR_DTLBTR_BASE(0) // set DTLBTR
+
+ EXCEPTION_LOAD_GPR6
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR2
+
+ l.rfe // SR <- ESR, PC <- EPC
+
+exit_with_no_dtranslation:
+ /* EA out of memory or not in supervisor mode */
+ EXCEPTION_LOAD_GPR6
+ EXCEPTION_LOAD_GPR4
+ l.j _dispatch_bus_fault
+
+/* ---[ boot itlb miss handler ]----------------------------------------- */
+
+boot_itlb_miss_handler:
+
+/* mask for ITLB_MR register: - sets V (valid) bit,
+ * - sets bits belonging to VPN (15-12)
+ */
+#define ITLB_MR_MASK 0xfffff001
+
+/* mask for ITLB_TR register: - sets A (access) bit,
+ * - sets SXE (superuser execute) bit
+ * - sets bits belonging to VPN (15-12)
+ */
+#define ITLB_TR_MASK 0xfffff050
+
+/*
+#define VPN_MASK 0xffffe000
+#define PPN_MASK 0xffffe000
+*/
+
+
+
+ EXCEPTION_STORE_GPR2
+ EXCEPTION_STORE_GPR3
+ EXCEPTION_STORE_GPR4
+ EXCEPTION_STORE_GPR5
+ EXCEPTION_STORE_GPR6
+
+#if 0
+ l.mfspr r6,r0,SPR_ESR_BASE //
+ l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
+ l.sfeqi r6,0 // r6 == 0x1 --> SM
+ l.bf exit_with_no_itranslation
+ l.nop
+#endif
+
+
+ l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
+
+earlyearly:
+ CLEAR_GPR(r6)
+
+ l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
+
+ l.mfspr r6, r0, SPR_IMMUCFGR
+ l.andi r6, r6, SPR_IMMUCFGR_NTS
+ l.srli r6, r6, SPR_IMMUCFGR_NTS_OFF
+ l.ori r5, r0, 0x1
+ l.sll r5, r5, r6 // r5 = number IMMU sets from IMMUCFGR
+ l.addi r6, r5, -1 // r6 = nsets mask
+ l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
+
+ l.or r6,r6,r4 // r6 <- r4
+ l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
+ l.movhi r5,hi(ITLB_MR_MASK) // r5 <- ffff:0000.x000
+ l.ori r5,r5,lo(ITLB_MR_MASK) // r5 <- ffff:1111.x001 - apply ITLB_MR_MASK
+ l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have ITLBMR entry
+ l.mtspr r2,r5,SPR_ITLBMR_BASE(0) // set ITLBMR
+
+ /*
+ * set up ITLB with no translation for EA <= 0x0fffffff
+ *
+ * we need this for head.S mapping (EA = PA). if we move all functions
+ * which run with mmu enabled into entry.S, we might be able to eliminate this.
+ *
+ */
+ LOAD_SYMBOL_2_GPR(r6,0x0fffffff)
+ l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xb0ffffff >= EA)
+ l.bf 1f // goto out
+ l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
+
+ tophys(r3,r4) // r3 <- PA
+1:
+ l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
+ l.movhi r5,hi(ITLB_TR_MASK) // r5 <- ffff:0000.x000
+ l.ori r5,r5,lo(ITLB_TR_MASK) // r5 <- ffff:1111.x050 - apply ITLB_MR_MASK
+ l.and r5,r5,r3 // r5 <- PPN :PPN .x050 - we have ITLBTR entry
+ l.mtspr r2,r5,SPR_ITLBTR_BASE(0) // set ITLBTR
+
+ EXCEPTION_LOAD_GPR6
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR2
+
+ l.rfe // SR <- ESR, PC <- EPC
+
+exit_with_no_itranslation:
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR6
+ l.j _dispatch_bus_fault
+ l.nop
+
+/* ====================================================================== */
+/*
+ * Stuff below here shouldn't go into .head section... maybe this stuff
+ * can be moved to entry.S ???
+ */
+
+/* ==============================================[ DTLB miss handler ]=== */
+
+/*
+ * Comments:
+ * Exception handlers are entered with MMU off so the following handler
+ * needs to use physical addressing
+ *
+ */
+
+ .text
+ENTRY(dtlb_miss_handler)
+ EXCEPTION_STORE_GPR2
+ EXCEPTION_STORE_GPR3
+ EXCEPTION_STORE_GPR4
+ EXCEPTION_STORE_GPR5
+ EXCEPTION_STORE_GPR6
+ /*
+ * get EA of the miss
+ */
+ l.mfspr r2,r0,SPR_EEAR_BASE
+ /*
+ * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
+ */
+ GET_CURRENT_PGD(r3,r5) // r3 is current_pgd, r5 is temp
+ l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
+ l.slli r4,r4,0x2 // to get address << 2
+ l.add r5,r4,r3 // r4 is pgd_index(daddr)
+ /*
+ * if (pmd_none(*pmd))
+ * goto pmd_none:
+ */
+ tophys (r4,r5)
+ l.lwz r3,0x0(r4) // get *pmd value
+ l.sfne r3,r0
+ l.bnf d_pmd_none
+ l.andi r3,r3,~PAGE_MASK //0x1fff // ~PAGE_MASK
+ /*
+ * if (pmd_bad(*pmd))
+ * pmd_clear(pmd)
+ * goto pmd_bad:
+ */
+// l.sfeq r3,r0 // check *pmd value
+// l.bf d_pmd_good
+ l.addi r3,r0,0xffffe000 // PAGE_MASK
+// l.j d_pmd_bad
+// l.sw 0x0(r4),r0 // clear pmd
+d_pmd_good:
+ /*
+ * pte = *pte_offset(pmd, daddr);
+ */
+ l.lwz r4,0x0(r4) // get **pmd value
+ l.and r4,r4,r3 // & PAGE_MASK
+ l.srli r5,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
+ l.andi r3,r5,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
+ l.slli r3,r3,0x2 // to get address << 2
+ l.add r3,r3,r4
+ l.lwz r2,0x0(r3) // this is pte at last
+ /*
+ * if (!pte_present(pte))
+ */
+ l.andi r4,r2,0x1
+ l.sfne r4,r0 // is pte present
+ l.bnf d_pte_not_present
+ l.addi r3,r0,0xffffe3fa // PAGE_MASK | DTLB_UP_CONVERT_MASK
+ /*
+ * fill DTLB TR register
+ */
+ l.and r4,r2,r3 // apply the mask
+ // Determine number of DMMU sets
+ l.mfspr r6, r0, SPR_DMMUCFGR
+ l.andi r6, r6, SPR_DMMUCFGR_NTS
+ l.srli r6, r6, SPR_DMMUCFGR_NTS_OFF
+ l.ori r3, r0, 0x1
+ l.sll r3, r3, r6 // r3 = number DMMU sets DMMUCFGR
+ l.addi r6, r3, -1 // r6 = nsets mask
+ l.and r5, r5, r6 // calc offset: & (NUM_TLB_ENTRIES-1)
+ //NUM_TLB_ENTRIES
+ l.mtspr r5,r4,SPR_DTLBTR_BASE(0)
+ /*
+ * fill DTLB MR register
+ */
+ l.mfspr r2,r0,SPR_EEAR_BASE
+ l.addi r3,r0,0xffffe000 // PAGE_MASK
+ l.and r4,r2,r3 // apply PAGE_MASK to EA (__PHX__ do we really need this?)
+ l.ori r4,r4,0x1 // set hardware valid bit: DTBL_MR entry
+ l.mtspr r5,r4,SPR_DTLBMR_BASE(0)
+
+ EXCEPTION_LOAD_GPR2
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR6
+ l.rfe
+d_pmd_bad:
+ l.nop 1
+ EXCEPTION_LOAD_GPR2
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR6
+ l.rfe
+d_pmd_none:
+d_pte_not_present:
+ EXCEPTION_LOAD_GPR2
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR6
+ l.j _dispatch_do_dpage_fault
+ l.nop
+
+/* ==============================================[ ITLB miss handler ]=== */
+ENTRY(itlb_miss_handler)
+ EXCEPTION_STORE_GPR2
+ EXCEPTION_STORE_GPR3
+ EXCEPTION_STORE_GPR4
+ EXCEPTION_STORE_GPR5
+ EXCEPTION_STORE_GPR6
+ /*
+ * get EA of the miss
+ */
+ l.mfspr r2,r0,SPR_EEAR_BASE
+
+ /*
+ * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
+ *
+ */
+ GET_CURRENT_PGD(r3,r5) // r3 is current_pgd, r5 is temp
+ l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
+ l.slli r4,r4,0x2 // to get address << 2
+ l.add r5,r4,r3 // r4 is pgd_index(daddr)
+ /*
+ * if (pmd_none(*pmd))
+ * goto pmd_none:
+ */
+ tophys (r4,r5)
+ l.lwz r3,0x0(r4) // get *pmd value
+ l.sfne r3,r0
+ l.bnf i_pmd_none
+ l.andi r3,r3,0x1fff // ~PAGE_MASK
+ /*
+ * if (pmd_bad(*pmd))
+ * pmd_clear(pmd)
+ * goto pmd_bad:
+ */
+
+// l.sfeq r3,r0 // check *pmd value
+// l.bf i_pmd_good
+ l.addi r3,r0,0xffffe000 // PAGE_MASK
+// l.j i_pmd_bad
+// l.sw 0x0(r4),r0 // clear pmd
+
+i_pmd_good:
+ /*
+ * pte = *pte_offset(pmd, iaddr);
+ *
+ */
+ l.lwz r4,0x0(r4) // get **pmd value
+ l.and r4,r4,r3 // & PAGE_MASK
+ l.srli r5,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
+ l.andi r3,r5,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
+ l.slli r3,r3,0x2 // to get address << 2
+ l.add r3,r3,r4
+ l.lwz r2,0x0(r3) // this is pte at last
+ /*
+ * if (!pte_present(pte))
+ *
+ */
+ l.andi r4,r2,0x1
+ l.sfne r4,r0 // is pte present
+ l.bnf i_pte_not_present
+ l.addi r3,r0,0xffffe03a // PAGE_MASK | ITLB_UP_CONVERT_MASK
+ /*
+ * fill ITLB TR register
+ */
+ l.and r4,r2,r3 // apply the mask
+ l.andi r3,r2,0x7c0 // _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE | _PAGE_URE | _PAGE_UWE
+// l.andi r3,r2,0x400 // _PAGE_EXEC
+ l.sfeq r3,r0
+ l.bf itlb_tr_fill //_workaround
+ // Determine number of IMMU sets
+ l.mfspr r6, r0, SPR_IMMUCFGR
+ l.andi r6, r6, SPR_IMMUCFGR_NTS
+ l.srli r6, r6, SPR_IMMUCFGR_NTS_OFF
+ l.ori r3, r0, 0x1
+ l.sll r3, r3, r6 // r3 = number IMMU sets IMMUCFGR
+ l.addi r6, r3, -1 // r6 = nsets mask
+ l.and r5, r5, r6 // calc offset: & (NUM_TLB_ENTRIES-1)
+
+/*
+ * __PHX__ :: fixme
+ * we should not just blindly set executable flags,
+ * but it does help with ping. the clean way would be to find out
+ * (and fix it) why stack doesn't have execution permissions
+ */
+
+itlb_tr_fill_workaround:
+ l.ori r4,r4,0xc0 // | (SPR_ITLBTR_UXE | ITLBTR_SXE)
+itlb_tr_fill:
+ l.mtspr r5,r4,SPR_ITLBTR_BASE(0)
+ /*
+ * fill DTLB MR register
+ */
+ l.mfspr r2,r0,SPR_EEAR_BASE
+ l.addi r3,r0,0xffffe000 // PAGE_MASK
+ l.and r4,r2,r3 // apply PAGE_MASK to EA (__PHX__ do we really need this?)
+ l.ori r4,r4,0x1 // set hardware valid bit: DTBL_MR entry
+ l.mtspr r5,r4,SPR_ITLBMR_BASE(0)
+
+ EXCEPTION_LOAD_GPR2
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR6
+ l.rfe
+
+i_pmd_bad:
+ l.nop 1
+ EXCEPTION_LOAD_GPR2
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR6
+ l.rfe
+i_pmd_none:
+i_pte_not_present:
+ EXCEPTION_LOAD_GPR2
+ EXCEPTION_LOAD_GPR3
+ EXCEPTION_LOAD_GPR4
+ EXCEPTION_LOAD_GPR5
+ EXCEPTION_LOAD_GPR6
+ l.j _dispatch_do_ipage_fault
+ l.nop
+
+/* ==============================================[ boot tlb handlers ]=== */
+
+
+/* =================================================[ debugging aids ]=== */
+
+ .align 64
+_immu_trampoline:
+ .space 64
+_immu_trampoline_top:
+
+#define TRAMP_SLOT_0 (0x0)
+#define TRAMP_SLOT_1 (0x4)
+#define TRAMP_SLOT_2 (0x8)
+#define TRAMP_SLOT_3 (0xc)
+#define TRAMP_SLOT_4 (0x10)
+#define TRAMP_SLOT_5 (0x14)
+#define TRAMP_FRAME_SIZE (0x18)
+
+ENTRY(_immu_trampoline_workaround)
+ // r2 EEA
+ // r6 is physical EEA
+ tophys(r6,r2)
+
+ LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
+ tophys (r3,r5) // r3 is trampoline (physical)
+
+ LOAD_SYMBOL_2_GPR(r4,0x15000000)
+ l.sw TRAMP_SLOT_0(r3),r4
+ l.sw TRAMP_SLOT_1(r3),r4
+ l.sw TRAMP_SLOT_4(r3),r4
+ l.sw TRAMP_SLOT_5(r3),r4
+
+ // EPC = EEA - 0x4
+ l.lwz r4,0x0(r6) // load op @ EEA + 0x0 (fc address)
+ l.sw TRAMP_SLOT_3(r3),r4 // store it to _immu_trampoline_data
+ l.lwz r4,-0x4(r6) // load op @ EEA - 0x4 (f8 address)
+ l.sw TRAMP_SLOT_2(r3),r4 // store it to _immu_trampoline_data
+
+ l.srli r5,r4,26 // check opcode for write access
+ l.sfeqi r5,0 // l.j
+ l.bf 0f
+ l.sfeqi r5,0x11 // l.jr
+ l.bf 1f
+ l.sfeqi r5,1 // l.jal
+ l.bf 2f
+ l.sfeqi r5,0x12 // l.jalr
+ l.bf 3f
+ l.sfeqi r5,3 // l.bnf
+ l.bf 4f
+ l.sfeqi r5,4 // l.bf
+ l.bf 5f
+99:
+ l.nop
+ l.j 99b // should never happen
+ l.nop 1
+
+ // r2 is EEA
+ // r3 is trampoline address (physical)
+ // r4 is instruction
+ // r6 is physical(EEA)
+ //
+ // r5
+
+2: // l.jal
+
+ /* 19 20 aa aa l.movhi r9,0xaaaa
+ * a9 29 bb bb l.ori r9,0xbbbb
+ *
+ * where 0xaaaabbbb is EEA + 0x4 shifted right 2
+ */
+
+ l.addi r6,r2,0x4 // this is 0xaaaabbbb
+
+ // l.movhi r9,0xaaaa
+ l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
+ l.sh (TRAMP_SLOT_0+0x0)(r3),r5
+ l.srli r5,r6,16
+ l.sh (TRAMP_SLOT_0+0x2)(r3),r5
+
+ // l.ori r9,0xbbbb
+ l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
+ l.sh (TRAMP_SLOT_1+0x0)(r3),r5
+ l.andi r5,r6,0xffff
+ l.sh (TRAMP_SLOT_1+0x2)(r3),r5
+
+ /* falthrough, need to set up new jump offset */
+
+
+0: // l.j
+ l.slli r6,r4,6 // original offset shifted left 6 - 2
+// l.srli r6,r6,6 // original offset shifted right 2
+
+ l.slli r4,r2,4 // old jump position: EEA shifted left 4
+// l.srli r4,r4,6 // old jump position: shifted right 2
+
+ l.addi r5,r3,0xc // new jump position (physical)
+ l.slli r5,r5,4 // new jump position: shifted left 4
+
+ // calculate new jump offset
+ // new_off = old_off + (old_jump - new_jump)
+
+ l.sub r5,r4,r5 // old_jump - new_jump
+ l.add r5,r6,r5 // orig_off + (old_jump - new_jump)
+ l.srli r5,r5,6 // new offset shifted right 2
+
+ // r5 is new jump offset
+ // l.j has opcode 0x0...
+ l.sw TRAMP_SLOT_2(r3),r5 // write it back
+
+ l.j trampoline_out
+ l.nop
+
+/* ----------------------------- */
+
+3: // l.jalr
+
+ /* 19 20 aa aa l.movhi r9,0xaaaa
+ * a9 29 bb bb l.ori r9,0xbbbb
+ *
+ * where 0xaaaabbbb is EEA + 0x4 shifted right 2
+ */
+
+ l.addi r6,r2,0x4 // this is 0xaaaabbbb
+
+ // l.movhi r9,0xaaaa
+ l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
+ l.sh (TRAMP_SLOT_0+0x0)(r3),r5
+ l.srli r5,r6,16
+ l.sh (TRAMP_SLOT_0+0x2)(r3),r5
+
+ // l.ori r9,0xbbbb
+ l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
+ l.sh (TRAMP_SLOT_1+0x0)(r3),r5
+ l.andi r5,r6,0xffff
+ l.sh (TRAMP_SLOT_1+0x2)(r3),r5
+
+ l.lhz r5,(TRAMP_SLOT_2+0x0)(r3) // load hi part of jump instruction
+ l.andi r5,r5,0x3ff // clear out opcode part
+ l.ori r5,r5,0x4400 // opcode changed from l.jalr -> l.jr
+ l.sh (TRAMP_SLOT_2+0x0)(r3),r5 // write it back
+
+ /* falthrough */
+
+1: // l.jr
+ l.j trampoline_out
+ l.nop
+
+/* ----------------------------- */
+
+4: // l.bnf
+5: // l.bf
+ l.slli r6,r4,6 // original offset shifted left 6 - 2
+// l.srli r6,r6,6 // original offset shifted right 2
+
+ l.slli r4,r2,4 // old jump position: EEA shifted left 4
+// l.srli r4,r4,6 // old jump position: shifted right 2
+
+ l.addi r5,r3,0xc // new jump position (physical)
+ l.slli r5,r5,4 // new jump position: shifted left 4
+
+ // calculate new jump offset
+ // new_off = old_off + (old_jump - new_jump)
+
+ l.add r6,r6,r4 // (orig_off + old_jump)
+ l.sub r6,r6,r5 // (orig_off + old_jump) - new_jump
+ l.srli r6,r6,6 // new offset shifted right 2
+
+ // r6 is new jump offset
+ l.lwz r4,(TRAMP_SLOT_2+0x0)(r3) // load jump instruction
+ l.srli r4,r4,16
+ l.andi r4,r4,0xfc00 // get opcode part
+ l.slli r4,r4,16
+ l.or r6,r4,r6 // l.b(n)f new offset
+ l.sw TRAMP_SLOT_2(r3),r6 // write it back
+
+ /* we need to add l.j to EEA + 0x8 */
+ tophys (r4,r2) // may not be needed (due to shifts down_
+ l.addi r4,r4,(0x8 - 0x8) // jump target = r2 + 0x8 (compensate for 0x8)
+ // jump position = r5 + 0x8 (0x8 compensated)
+ l.sub r4,r4,r5 // jump offset = target - new_position + 0x8
+
+ l.slli r4,r4,4 // the amount of info in imediate of jump
+ l.srli r4,r4,6 // jump instruction with offset
+ l.sw TRAMP_SLOT_4(r3),r4 // write it to 4th slot
+
+ /* fallthrough */
+
+trampoline_out:
+ // set up new EPC to point to our trampoline code
+ LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
+ l.mtspr r0,r5,SPR_EPCR_BASE
+
+ // immu_trampoline is (4x) CACHE_LINE aligned
+ // and only 6 instructions long,
+ // so we need to invalidate only 2 lines
+
+ /* Establish cache block size
+ If BS=0, 16;
+ If BS=1, 32;
+ r14 contain block size
+ */
+ l.mfspr r21,r0,SPR_ICCFGR
+ l.andi r21,r21,SPR_ICCFGR_CBS
+ l.srli r21,r21,7
+ l.ori r23,r0,16
+ l.sll r14,r23,r21
+
+ l.mtspr r0,r5,SPR_ICBIR
+ l.add r5,r5,r14
+ l.mtspr r0,r5,SPR_ICBIR
+
+ l.jr r9
+ l.nop
+
+
+/*
+ * DSCR: prints a string referenced by r3.
+ *
+ * PRMS: r3 - address of the first character of null
+ * terminated string to be printed
+ *
+ * PREQ: UART at UART_BASE_ADD has to be initialized
+ *
+ * POST: caller should be aware that r3, r9 are changed
+ */
+ENTRY(_emergency_print)
+ EMERGENCY_PRINT_STORE_GPR4
+ EMERGENCY_PRINT_STORE_GPR5
+ EMERGENCY_PRINT_STORE_GPR6
+ EMERGENCY_PRINT_STORE_GPR7
+2:
+ l.lbz r7,0(r3)
+ l.sfeq r7,r0
+ l.bf 9f
+ l.nop
+
+// putc:
+ l.movhi r4,hi(UART_BASE_ADD)
+
+ l.addi r6,r0,0x20
+1: l.lbz r5,5(r4)
+ l.andi r5,r5,0x20
+ l.sfeq r5,r6
+ l.bnf 1b
+ l.nop
+
+ l.sb 0(r4),r7
+
+ l.addi r6,r0,0x60
+1: l.lbz r5,5(r4)
+ l.andi r5,r5,0x60
+ l.sfeq r5,r6
+ l.bnf 1b
+ l.nop
+
+ /* next character */
+ l.j 2b
+ l.addi r3,r3,0x1
+
+9:
+ EMERGENCY_PRINT_LOAD_GPR7
+ EMERGENCY_PRINT_LOAD_GPR6
+ EMERGENCY_PRINT_LOAD_GPR5
+ EMERGENCY_PRINT_LOAD_GPR4
+ l.jr r9
+ l.nop
+
+ENTRY(_emergency_print_nr)
+ EMERGENCY_PRINT_STORE_GPR4
+ EMERGENCY_PRINT_STORE_GPR5
+ EMERGENCY_PRINT_STORE_GPR6
+ EMERGENCY_PRINT_STORE_GPR7
+ EMERGENCY_PRINT_STORE_GPR8
+
+ l.addi r8,r0,32 // shift register
+
+1: /* remove leading zeros */
+ l.addi r8,r8,-0x4
+ l.srl r7,r3,r8
+ l.andi r7,r7,0xf
+
+ /* don't skip the last zero if number == 0x0 */
+ l.sfeqi r8,0x4
+ l.bf 2f
+ l.nop
+
+ l.sfeq r7,r0
+ l.bf 1b
+ l.nop
+
+2:
+ l.srl r7,r3,r8
+
+ l.andi r7,r7,0xf
+ l.sflts r8,r0
+ l.bf 9f
+
+ l.sfgtui r7,0x9
+ l.bnf 8f
+ l.nop
+ l.addi r7,r7,0x27
+
+8:
+ l.addi r7,r7,0x30
+// putc:
+ l.movhi r4,hi(UART_BASE_ADD)
+
+ l.addi r6,r0,0x20
+1: l.lbz r5,5(r4)
+ l.andi r5,r5,0x20
+ l.sfeq r5,r6
+ l.bnf 1b
+ l.nop
+
+ l.sb 0(r4),r7
+
+ l.addi r6,r0,0x60
+1: l.lbz r5,5(r4)
+ l.andi r5,r5,0x60
+ l.sfeq r5,r6
+ l.bnf 1b
+ l.nop
+
+ /* next character */
+ l.j 2b
+ l.addi r8,r8,-0x4
+
+9:
+ EMERGENCY_PRINT_LOAD_GPR8
+ EMERGENCY_PRINT_LOAD_GPR7
+ EMERGENCY_PRINT_LOAD_GPR6
+ EMERGENCY_PRINT_LOAD_GPR5
+ EMERGENCY_PRINT_LOAD_GPR4
+ l.jr r9
+ l.nop
+
+
+/*
+ * This should be used for debugging only.
+ * It messes up the Linux early serial output
+ * somehow, so use it sparingly and essentially
+ * only if you need to debug something that goes wrong
+ * before Linux gets the early serial going.
+ *
+ * Furthermore, you'll have to make sure you set the
+ * UART_DEVISOR correctly according to the system
+ * clock rate.
+ *
+ *
+ */
+
+
+
+#define SYS_CLK 20000000
+//#define SYS_CLK 1843200
+#define OR32_CONSOLE_BAUD 115200
+#define UART_DIVISOR SYS_CLK/(16*OR32_CONSOLE_BAUD)
+
+ENTRY(_early_uart_init)
+ l.movhi r3,hi(UART_BASE_ADD)
+
+ l.addi r4,r0,0x7
+ l.sb 0x2(r3),r4
+
+ l.addi r4,r0,0x0
+ l.sb 0x1(r3),r4
+
+ l.addi r4,r0,0x3
+ l.sb 0x3(r3),r4
+
+ l.lbz r5,3(r3)
+ l.ori r4,r5,0x80
+ l.sb 0x3(r3),r4
+ l.addi r4,r0,((UART_DIVISOR>>8) & 0x000000ff)
+ l.sb UART_DLM(r3),r4
+ l.addi r4,r0,((UART_DIVISOR) & 0x000000ff)
+ l.sb UART_DLL(r3),r4
+ l.sb 0x3(r3),r5
+
+ l.jr r9
+ l.nop
+
+_string_copying_linux:
+ .string "\n\n\n\n\n\rCopying Linux... \0"
+
+_string_ok_booting:
+ .string "Ok, booting the kernel.\n\r\0"
+
+_string_unhandled_exception:
+ .string "\n\rRunarunaround: Unhandled exception 0x\0"
+
+_string_epc_prefix:
+ .string ": EPC=0x\0"
+
+_string_nl:
+ .string "\n\r\0"
+
+ .global _string_esr_irq_bug
+_string_esr_irq_bug:
+ .string "\n\rESR external interrupt bug, for details look into entry.S\n\r\0"
+
+
+
+/* ========================================[ page aligned structures ]=== */
+
+/*
+ * .data section should be page aligned
+ * (look into arch/or32/kernel/vmlinux.lds)
+ */
+ .section .data,"aw"
+ .align 8192
+ .global empty_zero_page
+empty_zero_page:
+ .space 8192
+
+ .global swapper_pg_dir
+swapper_pg_dir:
+ .space 8192
+
+ .global _unhandled_stack
+_unhandled_stack:
+ .space 8192
+_unhandled_stack_top:
+
+/* ============================================================[ EOF ]=== */
diff --git a/arch/openrisc/kernel/idle.c b/arch/openrisc/kernel/idle.c
new file mode 100644
index 000000000000..d5bc5f813e89
--- /dev/null
+++ b/arch/openrisc/kernel/idle.c
@@ -0,0 +1,77 @@
+/*
+ * OpenRISC idle.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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.
+ *
+ * Idle daemon for or32. Idle daemon will handle any action
+ * that needs to be taken when the system becomes idle.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/tick.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+#include <asm/pgalloc.h>
+
+void (*powersave) (void) = NULL;
+
+static inline void pm_idle(void)
+{
+ barrier();
+}
+
+void cpu_idle(void)
+{
+ set_thread_flag(TIF_POLLING_NRFLAG);
+
+ /* endless idle loop with no priority at all */
+ while (1) {
+ tick_nohz_stop_sched_tick(1);
+
+ while (!need_resched()) {
+ check_pgt_cache();
+ rmb();
+
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+
+ local_irq_disable();
+ /* Don't trace irqs off for idle */
+ stop_critical_timings();
+ if (!need_resched() && powersave != NULL)
+ powersave();
+ start_critical_timings();
+ local_irq_enable();
+ set_thread_flag(TIF_POLLING_NRFLAG);
+ }
+
+ tick_nohz_restart_sched_tick();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
+}
diff --git a/arch/openrisc/kernel/init_task.c b/arch/openrisc/kernel/init_task.c
new file mode 100644
index 000000000000..45744a384927
--- /dev/null
+++ b/arch/openrisc/kernel/init_task.c
@@ -0,0 +1,41 @@
+/*
+ * OpenRISC init_task.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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_task.h>
+#include <linux/mqueue.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 THREAD_SIZE aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union __init_task_data = {
+ 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/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
new file mode 100644
index 000000000000..59b302338331
--- /dev/null
+++ b/arch/openrisc/kernel/irq.c
@@ -0,0 +1,172 @@
+/*
+ * OpenRISC irq.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/ptrace.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/ftrace.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/kernel_stat.h>
+
+#include <linux/irqflags.h>
+
+/* read interrupt enabled status */
+unsigned long arch_local_save_flags(void)
+{
+ return mfspr(SPR_SR) & (SPR_SR_IEE|SPR_SR_TEE);
+}
+EXPORT_SYMBOL(arch_local_save_flags);
+
+/* set interrupt enabled status */
+void arch_local_irq_restore(unsigned long flags)
+{
+ mtspr(SPR_SR, ((mfspr(SPR_SR) & ~(SPR_SR_IEE|SPR_SR_TEE)) | flags));
+}
+EXPORT_SYMBOL(arch_local_irq_restore);
+
+
+/* OR1K PIC implementation */
+
+/* We're a couple of cycles faster than the generic implementations with
+ * these 'fast' versions.
+ */
+
+static void or1k_pic_mask(struct irq_data *data)
+{
+ mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->irq));
+}
+
+static void or1k_pic_unmask(struct irq_data *data)
+{
+ mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->irq));
+}
+
+static void or1k_pic_ack(struct irq_data *data)
+{
+ /* EDGE-triggered interrupts need to be ack'ed in order to clear
+ * the latch.
+ * LEVER-triggered interrupts do not need to be ack'ed; however,
+ * ack'ing the interrupt has no ill-effect and is quicker than
+ * trying to figure out what type it is...
+ */
+
+ /* The OpenRISC 1000 spec says to write a 1 to the bit to ack the
+ * interrupt, but the OR1200 does this backwards and requires a 0
+ * to be written...
+ */
+
+#ifdef CONFIG_OR1K_1200
+ /* There are two oddities with the OR1200 PIC implementation:
+ * i) LEVEL-triggered interrupts are latched and need to be cleared
+ * ii) the interrupt latch is cleared by writing a 0 to the bit,
+ * as opposed to a 1 as mandated by the spec
+ */
+
+ mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
+#else
+ WARN(1, "Interrupt handling possibily broken\n");
+ mtspr(SPR_PICSR, (1UL << irq));
+#endif
+}
+
+static void or1k_pic_mask_ack(struct irq_data *data)
+{
+ /* Comments for pic_ack apply here, too */
+
+#ifdef CONFIG_OR1K_1200
+ mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
+#else
+ WARN(1, "Interrupt handling possibily broken\n");
+ mtspr(SPR_PICSR, (1UL << irq));
+#endif
+}
+
+static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
+{
+ /* There's nothing to do in the PIC configuration when changing
+ * flow type. Level and edge-triggered interrupts are both
+ * supported, but it's PIC-implementation specific which type
+ * is handled. */
+
+ return irq_setup_alt_chip(data, flow_type);
+}
+
+static inline int pic_get_irq(int first)
+{
+ int irq;
+
+ irq = ffs(mfspr(SPR_PICSR) >> first);
+
+ return irq ? irq + first - 1 : NO_IRQ;
+}
+
+static void __init or1k_irq_init(void)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ /* Disable all interrupts until explicitly requested */
+ mtspr(SPR_PICMR, (0UL));
+
+ gc = irq_alloc_generic_chip("or1k-PIC", 1, 0, 0, handle_level_irq);
+ ct = gc->chip_types;
+
+ ct->chip.irq_unmask = or1k_pic_unmask;
+ ct->chip.irq_mask = or1k_pic_mask;
+ ct->chip.irq_ack = or1k_pic_ack;
+ ct->chip.irq_mask_ack = or1k_pic_mask_ack;
+ ct->chip.irq_set_type = or1k_pic_set_type;
+
+ /* The OR1K PIC can handle both level and edge trigged
+ * interrupts in roughly the same manner
+ */
+#if 0
+ /* FIXME: chip.type??? */
+ ct->chip.type = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_MASK;
+#endif
+
+ irq_setup_generic_chip(gc, IRQ_MSK(NR_IRQS), 0,
+ IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+}
+
+void __init init_IRQ(void)
+{
+ or1k_irq_init();
+}
+
+void __irq_entry do_IRQ(struct pt_regs *regs)
+{
+ int irq = -1;
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
+ irq_enter();
+
+ while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
+ generic_handle_irq(irq);
+
+ irq_exit();
+ set_irq_regs(old_regs);
+}
+
+unsigned int irq_create_of_mapping(struct device_node *controller,
+ const u32 *intspec, unsigned int intsize)
+{
+ return intspec[0];
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/openrisc/kernel/module.c b/arch/openrisc/kernel/module.c
new file mode 100644
index 000000000000..10ff50f0202a
--- /dev/null
+++ b/arch/openrisc/kernel/module.c
@@ -0,0 +1,72 @@
+/*
+ * OpenRISC module.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/moduleloader.h>
+#include <linux/elf.h>
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+ uint32_t value;
+
+ pr_debug("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+ value = sym->st_value + rel[i].r_addend;
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_OR32_32:
+ *location = value;
+ break;
+ case R_OR32_CONST:
+ location = (uint16_t *)location + 1;
+ *((uint16_t *)location) = (uint16_t) (value);
+ break;
+ case R_OR32_CONSTH:
+ location = (uint16_t *)location + 1;
+ *((uint16_t *)location) = (uint16_t) (value >> 16);
+ break;
+ case R_OR32_JUMPTARG:
+ value -= (uint32_t)location;
+ value >>= 2;
+ value &= 0x03ffffff;
+ value |= *location & 0xfc000000;
+ *location = value;
+ break;
+ default:
+ pr_err("module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/arch/openrisc/kernel/or32_ksyms.c b/arch/openrisc/kernel/or32_ksyms.c
new file mode 100644
index 000000000000..83ccf7c0c58d
--- /dev/null
+++ b/arch/openrisc/kernel/or32_ksyms.c
@@ -0,0 +1,46 @@
+/*
+ * OpenRISC or32_ksyms.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/elfcore.h>
+#include <linux/sched.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/semaphore.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include <asm/io.h>
+#include <asm/hardirq.h>
+#include <asm/delay.h>
+#include <asm/pgalloc.h>
+
+#define DECLARE_EXPORT(name) extern void name(void); EXPORT_SYMBOL(name)
+
+/* compiler generated symbols */
+DECLARE_EXPORT(__udivsi3);
+DECLARE_EXPORT(__divsi3);
+DECLARE_EXPORT(__umodsi3);
+DECLARE_EXPORT(__modsi3);
+DECLARE_EXPORT(__muldi3);
+DECLARE_EXPORT(__ashrdi3);
+DECLARE_EXPORT(__ashldi3);
+DECLARE_EXPORT(__lshrdi3);
+
+EXPORT_SYMBOL(__copy_tofrom_user);
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
new file mode 100644
index 000000000000..e4209af879ec
--- /dev/null
+++ b/arch/openrisc/kernel/process.c
@@ -0,0 +1,311 @@
+/*
+ * OpenRISC process.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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 file handles the architecture-dependent parts of process handling...
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/elfcore.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+#include <linux/fs.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/spr_defs.h>
+
+#include <linux/smp.h>
+
+/*
+ * Pointer to Current thread info structure.
+ *
+ * Used at user space -> kernel transitions.
+ */
+struct thread_info *current_thread_info_set[NR_CPUS] = { &init_thread_info, };
+
+void machine_restart(void)
+{
+ printk(KERN_INFO "*** MACHINE RESTART ***\n");
+ __asm__("l.nop 1");
+}
+
+/*
+ * Similar to machine_power_off, but don't shut off power. Add code
+ * here to freeze the system for e.g. post-mortem debug purpose when
+ * possible. This halt has nothing to do with the idle halt.
+ */
+void machine_halt(void)
+{
+ printk(KERN_INFO "*** MACHINE HALT ***\n");
+ __asm__("l.nop 1");
+}
+
+/* If or when software power-off is implemented, add code here. */
+void machine_power_off(void)
+{
+ printk(KERN_INFO "*** MACHINE POWER OFF ***\n");
+ __asm__("l.nop 1");
+}
+
+void (*pm_power_off) (void) = machine_power_off;
+
+/*
+ * When a process does an "exec", machine state like FPU and debug
+ * registers need to be reset. This is a hook function for that.
+ * Currently we don't have any such state to reset, so this is empty.
+ */
+void flush_thread(void)
+{
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ extern void show_registers(struct pt_regs *regs);
+
+ /* __PHX__ cleanup this mess */
+ show_registers(regs);
+}
+
+unsigned long thread_saved_pc(struct task_struct *t)
+{
+ return (unsigned long)user_regs(t->stack)->pc;
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Copy the thread-specific (arch specific) info from the current
+ * process to the new one p
+ */
+extern asmlinkage void ret_from_fork(void);
+
+int
+copy_thread(unsigned long clone_flags, unsigned long usp,
+ unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs *childregs;
+ struct pt_regs *kregs;
+ unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+ struct thread_info *ti;
+ unsigned long top_of_kernel_stack;
+
+ top_of_kernel_stack = sp;
+
+ p->set_child_tid = p->clear_child_tid = NULL;
+
+ /* Copy registers */
+ /* redzone */
+ sp -= STACK_FRAME_OVERHEAD;
+ sp -= sizeof(struct pt_regs);
+ childregs = (struct pt_regs *)sp;
+
+ /* Copy parent registers */
+ *childregs = *regs;
+
+ if ((childregs->sr & SPR_SR_SM) == 1) {
+ /* for kernel thread, set `current_thread_info'
+ * and stackptr in new task
+ */
+ childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+ childregs->gpr[10] = (unsigned long)task_thread_info(p);
+ } else {
+ childregs->sp = usp;
+ }
+
+ childregs->gpr[11] = 0; /* Result from fork() */
+
+ /*
+ * The way this works is that at some point in the future
+ * some task will call _switch to switch to the new task.
+ * That will pop off the stack frame created below and start
+ * the new task running at ret_from_fork. The new task will
+ * do some house keeping and then return from the fork or clone
+ * system call, using the stack frame created above.
+ */
+ /* redzone */
+ sp -= STACK_FRAME_OVERHEAD;
+ sp -= sizeof(struct pt_regs);
+ kregs = (struct pt_regs *)sp;
+
+ ti = task_thread_info(p);
+ ti->ksp = sp;
+
+ /* kregs->sp must store the location of the 'pre-switch' kernel stack
+ * pointer... for a newly forked process, this is simply the top of
+ * the kernel stack.
+ */
+ kregs->sp = top_of_kernel_stack;
+ kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */
+ kregs->gpr[10] = (unsigned long)task_thread_info(p);
+ kregs->gpr[9] = (unsigned long)ret_from_fork;
+
+ return 0;
+}
+
+/*
+ * Set up a thread for executing a new program
+ */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
+{
+ unsigned long sr = regs->sr & ~SPR_SR_SM;
+
+ set_fs(USER_DS);
+ memset(regs->gpr, 0, sizeof(regs->gpr));
+
+ regs->pc = pc;
+ regs->sr = sr;
+ regs->sp = sp;
+
+/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/
+}
+
+/* Fill in the fpu structure for a core dump. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
+{
+ /* TODO */
+ return 0;
+}
+
+extern struct thread_info *_switch(struct thread_info *old_ti,
+ struct thread_info *new_ti);
+
+struct task_struct *__switch_to(struct task_struct *old,
+ struct task_struct *new)
+{
+ struct task_struct *last;
+ struct thread_info *new_ti, *old_ti;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* current_set is an array of saved current pointers
+ * (one for each cpu). we need them at user->kernel transition,
+ * while we save them at kernel->user transition
+ */
+ new_ti = new->stack;
+ old_ti = old->stack;
+
+ current_thread_info_set[smp_processor_id()] = new_ti;
+ last = (_switch(old_ti, new_ti))->task;
+
+ local_irq_restore(flags);
+
+ return last;
+}
+
+/*
+ * Write out registers in core dump format, as defined by the
+ * struct user_regs_struct
+ */
+void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs)
+{
+ dest[0] = 0; /* r0 */
+ memcpy(dest+1, regs->gpr+1, 31*sizeof(unsigned long));
+ dest[32] = regs->pc;
+ dest[33] = regs->sr;
+ dest[34] = 0;
+ dest[35] = 0;
+}
+
+extern void _kernel_thread_helper(void);
+
+void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg)
+{
+ do_exit(fn(arg));
+}
+
+/*
+ * Create a kernel thread.
+ */
+int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(regs));
+
+ regs.gpr[20] = (unsigned long)fn;
+ regs.gpr[22] = (unsigned long)arg;
+ regs.sr = mfspr(SPR_SR);
+ regs.pc = (unsigned long)_kernel_thread_helper;
+
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
+ 0, &regs, 0, NULL, NULL);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage long _sys_execve(const char __user *name,
+ const char __user * const __user *argv,
+ const char __user * const __user *envp,
+ struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname(name);
+ error = PTR_ERR(filename);
+
+ if (IS_ERR(filename))
+ goto out;
+
+ error = do_execve(filename, argv, envp, regs);
+ putname(filename);
+
+out:
+ return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ /* TODO */
+
+ return 0;
+}
+
+int kernel_execve(const char *filename, char *const argv[], char *const envp[])
+{
+ register long __res asm("r11") = __NR_execve;
+ register long __a asm("r3") = (long)(filename);
+ register long __b asm("r4") = (long)(argv);
+ register long __c asm("r5") = (long)(envp);
+ __asm__ volatile ("l.sys 1"
+ : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c)
+ : "0"(__res), "1"(__a), "2"(__b), "3"(__c)
+ : "r6", "r7", "r8", "r12", "r13", "r15",
+ "r17", "r19", "r21", "r23", "r25", "r27",
+ "r29", "r31");
+ __asm__ volatile ("l.nop");
+ return __res;
+}
diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c
new file mode 100644
index 000000000000..1bb58ba89afa
--- /dev/null
+++ b/arch/openrisc/kernel/prom.c
@@ -0,0 +1,108 @@
+/*
+ * OpenRISC prom.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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.
+ *
+ * Architecture specific procedures for creating, accessing and
+ * interpreting the device tree.
+ *
+ */
+
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/stringify.h>
+#include <linux/delay.h>
+#include <linux/initrd.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+#include <linux/debugfs.h>
+#include <linux/irq.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
+
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+
+extern char cmd_line[COMMAND_LINE_SIZE];
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+ size &= PAGE_MASK;
+ memblock_add(base, size);
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+ return __va(memblock_alloc(size, align));
+}
+
+void __init early_init_devtree(void *params)
+{
+ void *alloc;
+
+ /* Setup flat device-tree pointer */
+ initial_boot_params = params;
+
+
+ /* Retrieve various informations from the /chosen node of the
+ * device-tree, including the platform type, initrd location and
+ * size, TCE reserve, and more ...
+ */
+ of_scan_flat_dt(early_init_dt_scan_chosen, cmd_line);
+
+ /* Scan memory nodes and rebuild MEMBLOCKs */
+ memblock_init();
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+ of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+ /* Save command line for /proc/cmdline and then parse parameters */
+ strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
+
+ memblock_analyze();
+
+ /* We must copy the flattend device tree from init memory to regular
+ * memory because the device tree references the strings in it
+ * directly.
+ */
+
+ alloc = __va(memblock_alloc(initial_boot_params->totalsize, PAGE_SIZE));
+
+ memcpy(alloc, initial_boot_params, initial_boot_params->totalsize);
+
+ initial_boot_params = alloc;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+ unsigned long end)
+{
+ initrd_start = (unsigned long)__va(start);
+ initrd_end = (unsigned long)__va(end);
+ initrd_below_start_ok = 1;
+}
+#endif
diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c
new file mode 100644
index 000000000000..656b94beab89
--- /dev/null
+++ b/arch/openrisc/kernel/ptrace.c
@@ -0,0 +1,211 @@
+/*
+ * OpenRISC ptrace.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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 <stddef.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/audit.h>
+#include <linux/regset.h>
+#include <linux/tracehook.h>
+#include <linux/elf.h>
+
+#include <asm/thread_info.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+/*
+ * Copy the thread state to a regset that can be interpreted by userspace.
+ *
+ * It doesn't matter what our internal pt_regs structure looks like. The
+ * important thing is that we export a consistent view of the thread state
+ * to userspace. As such, we need to make sure that the regset remains
+ * ABI compatible as defined by the struct user_regs_struct:
+ *
+ * (Each item is a 32-bit word)
+ * r0 = 0 (exported for clarity)
+ * 31 GPRS r1-r31
+ * PC (Program counter)
+ * SR (Supervision register)
+ */
+static int genregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user * ubuf)
+{
+ const struct pt_regs *regs = task_pt_regs(target);
+ int ret;
+
+ /* r0 */
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 0, 4);
+
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ regs->gpr+1, 4, 4*32);
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &regs->pc, 4*32, 4*33);
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &regs->sr, 4*33, 4*34);
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 4*34, -1);
+
+ return ret;
+}
+
+/*
+ * Set the thread state from a regset passed in via ptrace
+ */
+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)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+ int ret;
+
+ /* ignore r0 */
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
+ /* r1 - r31 */
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ regs->gpr+1, 4, 4*32);
+ /* PC */
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &regs->pc, 4*32, 4*33);
+ /*
+ * Skip SR and padding... userspace isn't allowed to changes bits in
+ * the Supervision register
+ */
+ if (!ret)
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 4*33, -1);
+
+ return ret;
+}
+
+/*
+ * Define the register sets available on OpenRISC under Linux
+ */
+enum or1k_regset {
+ REGSET_GENERAL,
+};
+
+static const struct user_regset or1k_regsets[] = {
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .get = genregs_get,
+ .set = genregs_set,
+ },
+};
+
+static const struct user_regset_view user_or1k_native_view = {
+ .name = "or1k",
+ .e_machine = EM_OPENRISC,
+ .regsets = or1k_regsets,
+ .n = ARRAY_SIZE(or1k_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ return &user_or1k_native_view;
+}
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ pr_debug("ptrace_disable(): TODO\n");
+
+ user_disable_single_step(child);
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+}
+
+long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
+ unsigned long data)
+{
+ int ret;
+
+ switch (request) {
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
+{
+ long ret = 0;
+
+ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+ tracehook_report_syscall_entry(regs))
+ /*
+ * Tracing decided this syscall should not happen.
+ * We'll return a bogus call number to get an ENOSYS
+ * error, but leave the original number in <something>.
+ */
+ ret = -1L;
+
+ /* Are these regs right??? */
+ if (unlikely(current->audit_context))
+ audit_syscall_entry(audit_arch(), regs->syscallno,
+ regs->gpr[3], regs->gpr[4],
+ regs->gpr[5], regs->gpr[6]);
+
+ return ret ? : regs->syscallno;
+}
+
+asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
+{
+ int step;
+
+ if (unlikely(current->audit_context))
+ audit_syscall_exit(AUDITSC_RESULT(regs->gpr[11]),
+ regs->gpr[11]);
+
+ step = test_thread_flag(TIF_SINGLESTEP);
+ if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+ tracehook_report_syscall_exit(regs, step);
+}
diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
new file mode 100644
index 000000000000..1422f747f52b
--- /dev/null
+++ b/arch/openrisc/kernel/setup.c
@@ -0,0 +1,381 @@
+/*
+ * OpenRISC setup.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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 file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/initrd.h>
+#include <linux/of_fdt.h>
+#include <linux/of.h>
+#include <linux/memblock.h>
+#include <linux/device.h>
+#include <linux/of_platform.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/cpuinfo.h>
+#include <asm/delay.h>
+
+#include "vmlinux.h"
+
+char __initdata cmd_line[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+
+static unsigned long __init setup_memory(void)
+{
+ unsigned long bootmap_size;
+ unsigned long ram_start_pfn;
+ unsigned long free_ram_start_pfn;
+ unsigned long ram_end_pfn;
+ phys_addr_t memory_start, memory_end;
+ struct memblock_region *region;
+
+ memory_end = memory_start = 0;
+
+ /* Find main memory where is the kernel */
+ for_each_memblock(memory, region) {
+ memory_start = region->base;
+ memory_end = region->base + region->size;
+ printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
+ memory_start, memory_end);
+ }
+
+ if (!memory_end) {
+ panic("No memory!");
+ }
+
+ ram_start_pfn = PFN_UP(memory_start);
+ /* free_ram_start_pfn is first page after kernel */
+ free_ram_start_pfn = PFN_UP(__pa(&_end));
+ ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
+
+ max_pfn = ram_end_pfn;
+
+ /*
+ * initialize the boot-time allocator (with low memory only).
+ *
+ * This makes the memory from the end of the kernel to the end of
+ * RAM usable.
+ * init_bootmem sets the global values min_low_pfn, max_low_pfn.
+ */
+ bootmap_size = init_bootmem(free_ram_start_pfn,
+ ram_end_pfn - ram_start_pfn);
+ free_bootmem(PFN_PHYS(free_ram_start_pfn),
+ (ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
+ reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
+ BOOTMEM_DEFAULT);
+
+ for_each_memblock(reserved, region) {
+ printk(KERN_INFO "Reserved - 0x%08x-0x%08x\n",
+ (u32) region->base, (u32) region->size);
+ reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
+ }
+
+ return ram_end_pfn;
+}
+
+struct cpuinfo cpuinfo;
+
+static void print_cpuinfo(void)
+{
+ unsigned long upr = mfspr(SPR_UPR);
+ unsigned long vr = mfspr(SPR_VR);
+ unsigned int version;
+ unsigned int revision;
+
+ version = (vr & SPR_VR_VER) >> 24;
+ revision = (vr & SPR_VR_REV);
+
+ printk(KERN_INFO "CPU: OpenRISC-%x (revision %d) @%d MHz\n",
+ version, revision, cpuinfo.clock_frequency / 1000000);
+
+ if (!(upr & SPR_UPR_UP)) {
+ printk(KERN_INFO
+ "-- no UPR register... unable to detect configuration\n");
+ return;
+ }
+
+ if (upr & SPR_UPR_DCP)
+ printk(KERN_INFO
+ "-- dcache: %4d bytes total, %2d bytes/line, %d way(s)\n",
+ cpuinfo.dcache_size, cpuinfo.dcache_block_size, 1);
+ else
+ printk(KERN_INFO "-- dcache disabled\n");
+ if (upr & SPR_UPR_ICP)
+ printk(KERN_INFO
+ "-- icache: %4d bytes total, %2d bytes/line, %d way(s)\n",
+ cpuinfo.icache_size, cpuinfo.icache_block_size, 1);
+ else
+ printk(KERN_INFO "-- icache disabled\n");
+
+ if (upr & SPR_UPR_DMP)
+ printk(KERN_INFO "-- dmmu: %4d entries, %lu way(s)\n",
+ 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2),
+ 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW));
+ if (upr & SPR_UPR_IMP)
+ printk(KERN_INFO "-- immu: %4d entries, %lu way(s)\n",
+ 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2),
+ 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW));
+
+ printk(KERN_INFO "-- additional features:\n");
+ if (upr & SPR_UPR_DUP)
+ printk(KERN_INFO "-- debug unit\n");
+ if (upr & SPR_UPR_PCUP)
+ printk(KERN_INFO "-- performance counters\n");
+ if (upr & SPR_UPR_PMP)
+ printk(KERN_INFO "-- power management\n");
+ if (upr & SPR_UPR_PICP)
+ printk(KERN_INFO "-- PIC\n");
+ if (upr & SPR_UPR_TTP)
+ printk(KERN_INFO "-- timer\n");
+ if (upr & SPR_UPR_CUP)
+ printk(KERN_INFO "-- custom unit(s)\n");
+}
+
+void __init setup_cpuinfo(void)
+{
+ struct device_node *cpu;
+ unsigned long iccfgr, dccfgr;
+ unsigned long cache_set_size, cache_ways;
+
+ cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481");
+ if (!cpu)
+ panic("No compatible CPU found in device tree...\n");
+
+ iccfgr = mfspr(SPR_ICCFGR);
+ cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
+ cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
+ cpuinfo.icache_block_size = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> 7);
+ cpuinfo.icache_size =
+ cache_set_size * cache_ways * cpuinfo.icache_block_size;
+
+ dccfgr = mfspr(SPR_DCCFGR);
+ cache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
+ cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
+ cpuinfo.dcache_block_size = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> 7);
+ cpuinfo.dcache_size =
+ cache_set_size * cache_ways * cpuinfo.dcache_block_size;
+
+ if (of_property_read_u32(cpu, "clock-frequency",
+ &cpuinfo.clock_frequency)) {
+ printk(KERN_WARNING
+ "Device tree missing CPU 'clock-frequency' parameter."
+ "Assuming frequency 25MHZ"
+ "This is probably not what you want.");
+ }
+
+ of_node_put(cpu);
+
+ print_cpuinfo();
+}
+
+/**
+ * or32_early_setup
+ *
+ * Handles the pointer to the device tree that this kernel is to use
+ * for establishing the available platform devices.
+ *
+ * For now, this is limited to using the built-in device tree. In the future,
+ * it is intended that this function will take a pointer to the device tree
+ * that is potentially built-in, but potentially also passed in by the
+ * bootloader, or discovered by some equally clever means...
+ */
+
+void __init or32_early_setup(void)
+{
+
+ early_init_devtree(__dtb_start);
+
+ printk(KERN_INFO "Compiled-in FDT at 0x%p\n", __dtb_start);
+}
+
+static int __init openrisc_device_probe(void)
+{
+ of_platform_populate(NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+device_initcall(openrisc_device_probe);
+
+static inline unsigned long extract_value_bits(unsigned long reg,
+ short bit_nr, short width)
+{
+ return (reg >> bit_nr) & (0 << width);
+}
+
+static inline unsigned long extract_value(unsigned long reg, unsigned long mask)
+{
+ while (!(mask & 0x1)) {
+ reg = reg >> 1;
+ mask = mask >> 1;
+ }
+ return mask & reg;
+}
+
+void __init detect_unit_config(unsigned long upr, unsigned long mask,
+ char *text, void (*func) (void))
+{
+ if (text != NULL)
+ printk("%s", text);
+
+ if (upr & mask) {
+ if (func != NULL)
+ func();
+ else
+ printk("present\n");
+ } else
+ printk("not present\n");
+}
+
+/*
+ * calibrate_delay
+ *
+ * Lightweight calibrate_delay implementation that calculates loops_per_jiffy
+ * from the clock frequency passed in via the device tree
+ *
+ */
+
+void __cpuinit calibrate_delay(void)
+{
+ const int *val;
+ struct device_node *cpu = NULL;
+ cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481");
+ val = of_get_property(cpu, "clock-frequency", NULL);
+ if (!val)
+ panic("no cpu 'clock-frequency' parameter in device tree");
+ loops_per_jiffy = *val / HZ;
+ pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+ loops_per_jiffy / (500000 / HZ),
+ (loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long max_low_pfn;
+
+ unflatten_device_tree();
+
+ setup_cpuinfo();
+
+ /* process 1's initial memory region is the kernel code/data */
+ init_mm.start_code = (unsigned long)&_stext;
+ init_mm.end_code = (unsigned long)&_etext;
+ init_mm.end_data = (unsigned long)&_edata;
+ init_mm.brk = (unsigned long)&_end;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ initrd_start = (unsigned long)&__initrd_start;
+ initrd_end = (unsigned long)&__initrd_end;
+ if (initrd_start == initrd_end) {
+ initrd_start = 0;
+ initrd_end = 0;
+ }
+ initrd_below_start_ok = 1;
+#endif
+
+ /* setup bootmem allocator */
+ max_low_pfn = setup_memory();
+
+ /* paging_init() sets up the MMU and marks all pages as reserved */
+ paging_init();
+
+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+ if (!conswitchp)
+ conswitchp = &dummy_con;
+#endif
+
+ *cmdline_p = cmd_line;
+
+ printk(KERN_INFO "OpenRISC Linux -- http://openrisc.net\n");
+}
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ unsigned long vr;
+ int version, revision;
+
+ vr = mfspr(SPR_VR);
+ version = (vr & SPR_VR_VER) >> 24;
+ revision = vr & SPR_VR_REV;
+
+ return seq_printf(m,
+ "cpu\t\t: OpenRISC-%x\n"
+ "revision\t: %d\n"
+ "frequency\t: %ld\n"
+ "dcache size\t: %d bytes\n"
+ "dcache block size\t: %d bytes\n"
+ "icache size\t: %d bytes\n"
+ "icache block size\t: %d bytes\n"
+ "immu\t\t: %d entries, %lu ways\n"
+ "dmmu\t\t: %d entries, %lu ways\n"
+ "bogomips\t: %lu.%02lu\n",
+ version,
+ revision,
+ loops_per_jiffy * HZ,
+ cpuinfo.dcache_size,
+ cpuinfo.dcache_block_size,
+ cpuinfo.icache_size,
+ cpuinfo.icache_block_size,
+ 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2),
+ 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW),
+ 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2),
+ 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW),
+ (loops_per_jiffy * HZ) / 500000,
+ ((loops_per_jiffy * HZ) / 5000) % 100);
+}
+
+static void *c_start(struct seq_file *m, loff_t * pos)
+{
+ /* We only have one CPU... */
+ return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t * pos)
+{
+ ++*pos;
+ return NULL;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
new file mode 100644
index 000000000000..5f759c76834e
--- /dev/null
+++ b/arch/openrisc/kernel/signal.c
@@ -0,0 +1,396 @@
+/*
+ * OpenRISC signal.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/tracehook.h>
+
+#include <asm/processor.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage long
+_sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->sp);
+}
+
+struct rt_sigframe {
+ struct siginfo *pinfo;
+ void *puc;
+ struct siginfo info;
+ struct ucontext uc;
+ unsigned char retcode[16]; /* trampoline code */
+};
+
+static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+ unsigned int err = 0;
+ unsigned long old_usp;
+
+ /* Alwys make any pending restarted system call return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ /* restore the regs from &sc->regs (same as sc, since regs is first)
+ * (sc is already checked for VERIFY_READ since the sigframe was
+ * checked in sys_sigreturn previously)
+ */
+
+ if (__copy_from_user(regs, sc, sizeof(struct pt_regs)))
+ goto badframe;
+
+ /* make sure the SM-bit is cleared so user-mode cannot fool us */
+ regs->sr &= ~SPR_SR_SM;
+
+ /* restore the old USP as it was before we stacked the sc etc.
+ * (we cannot just pop the sigcontext since we aligned the sp and
+ * stuff after pushing it)
+ */
+
+ err |= __get_user(old_usp, &sc->usp);
+
+ regs->sp = old_usp;
+
+ /* TODO: the other ports use regs->orig_XX to disable syscall checks
+ * after this completes, but we don't use that mechanism. maybe we can
+ * use it now ?
+ */
+
+ return err;
+
+badframe:
+ return 1;
+}
+
+asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp;
+ sigset_t set;
+ stack_t st;
+
+ /*
+ * Since we stacked the signal on a dword boundary,
+ * then frame should be dword aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ if (((long)frame) & 3)
+ goto badframe;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs->sp);
+
+ return regs->gpr[11];
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+ unsigned long mask)
+{
+ int err = 0;
+ unsigned long usp = regs->sp;
+
+ /* copy the regs. they are first in sc so we can use sc directly */
+
+ err |= __copy_to_user(sc, regs, sizeof(struct pt_regs));
+
+ /* then some other stuff */
+
+ err |= __put_user(mask, &sc->oldmask);
+
+ err |= __put_user(usp, &sc->usp);
+
+ return err;
+}
+
+static inline unsigned long align_sigframe(unsigned long sp)
+{
+ return sp & ~3UL;
+}
+
+/*
+ * Work out where the signal frame should go. It's either on the user stack
+ * or the alternate stack.
+ */
+
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+ struct pt_regs *regs, size_t frame_size)
+{
+ unsigned long sp = regs->sp;
+ int onsigstack = on_sig_stack(sp);
+
+ /* redzone */
+ sp -= STACK_FRAME_OVERHEAD;
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
+ if (current->sas_ss_size)
+ sp = current->sas_ss_sp + current->sas_ss_size;
+ }
+
+ sp = align_sigframe(sp - frame_size);
+
+ /*
+ * If we are on the alternate signal stack and would overflow it, don't.
+ * Return an always-bogus address instead so we will die with SIGSEGV.
+ */
+ if (onsigstack && !likely(on_sig_stack(sp)))
+ return (void __user *)-1L;
+
+ return (void __user *)sp;
+}
+
+/* grab and setup a signal frame.
+ *
+ * basically we stack a lot of state info, and arrange for the
+ * user-mode program to return to the kernel using either a
+ * trampoline which performs the syscall sigreturn, or a provided
+ * user-mode trampoline.
+ */
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe *frame;
+ unsigned long return_ip;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->uc, &frame->puc);
+
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ err |= copy_siginfo_to_user(&frame->info, info);
+ if (err)
+ goto give_sigsegv;
+
+ /* Clear all the bits of the ucontext we don't use. */
+ err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(NULL, &frame->uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
+
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto give_sigsegv;
+
+ /* trampoline - the desired return ip is the retcode itself */
+ return_ip = (unsigned long)&frame->retcode;
+ /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
+ err |= __put_user(0xa960, (short *)(frame->retcode + 0));
+ err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
+ err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
+ err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
+
+ if (err)
+ goto give_sigsegv;
+
+ /* TODO what is the current->exec_domain stuff and invmap ? */
+
+ /* Set up registers for signal handler */
+ regs->pc = (unsigned long)ka->sa.sa_handler; /* what we enter NOW */
+ regs->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
+ regs->gpr[3] = (unsigned long)sig; /* arg 1: signo */
+ regs->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
+ regs->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
+
+ /* actually move the usp to reflect the stacked frame */
+ regs->sp = (unsigned long)frame;
+
+ return;
+
+give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+static inline void
+handle_signal(unsigned long sig,
+ siginfo_t *info, struct k_sigaction *ka,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ setup_rt_frame(sig, ka, info, oldset, regs);
+
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+
+ 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);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Also note that the regs structure given here as an argument, is the latest
+ * pushed pt_regs. It may or may not be the same as the first pushed registers
+ * when the initial usermode->kernelmode transition took place. Therefore
+ * we can use user_mode(regs) to see if we came directly from kernel or user
+ * mode below.
+ */
+
+void do_signal(struct pt_regs *regs)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+
+ /*
+ * We want the common case to go fast, which
+ * is why we may in certain cases get here from
+ * kernel mode. Just return without doing anything
+ * if so.
+ */
+ if (!user_mode(regs))
+ return;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+ /* If we are coming out of a syscall then we need
+ * to check if the syscall was interrupted and wants to be
+ * restarted after handling the signal. If so, the original
+ * syscall number is put back into r11 and the PC rewound to
+ * point at the l.sys instruction that resulted in the
+ * original syscall. Syscall results other than the four
+ * below mean that the syscall executed to completion and no
+ * restart is necessary.
+ */
+ if (regs->syscallno) {
+ int restart = 0;
+
+ switch (regs->gpr[11]) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ /* Restart if there is no signal handler */
+ restart = (signr <= 0);
+ break;
+ case -ERESTARTSYS:
+ /* Restart if there no signal handler or
+ * SA_RESTART flag is set */
+ restart = (signr <= 0 || (ka.sa.sa_flags & SA_RESTART));
+ break;
+ case -ERESTARTNOINTR:
+ /* Always restart */
+ restart = 1;
+ break;
+ }
+
+ if (restart) {
+ if (regs->gpr[11] == -ERESTART_RESTARTBLOCK)
+ regs->gpr[11] = __NR_restart_syscall;
+ else
+ regs->gpr[11] = regs->orig_gpr11;
+ regs->pc -= 4;
+ } else {
+ regs->gpr[11] = -EINTR;
+ }
+ }
+
+ if (signr <= 0) {
+ /* no signal to deliver so we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+
+ } else { /* signr > 0 */
+ sigset_t *oldset;
+
+ if (current_thread_info()->flags & _TIF_RESTORE_SIGMASK)
+ oldset = &current->saved_sigmask;
+ else
+ oldset = &current->blocked;
+
+ /* Whee! Actually deliver the signal. */
+ handle_signal(signr, &info, &ka, oldset, regs);
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+ tracehook_signal_handler(signr, &info, &ka, regs,
+ test_thread_flag(TIF_SINGLESTEP));
+ }
+
+ return;
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs)
+{
+ if (current_thread_info()->flags & _TIF_SIGPENDING)
+ do_signal(regs);
+
+ if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) {
+ clear_thread_flag(TIF_NOTIFY_RESUME);
+ tracehook_notify_resume(regs);
+ if (current->replacement_session_keyring)
+ key_replace_session_keyring();
+ }
+}
diff --git a/arch/openrisc/kernel/sys_call_table.c b/arch/openrisc/kernel/sys_call_table.c
new file mode 100644
index 000000000000..e1f8ce8c72a8
--- /dev/null
+++ b/arch/openrisc/kernel/sys_call_table.c
@@ -0,0 +1,28 @@
+/*
+ * OpenRISC sys_call_table.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff --git a/arch/openrisc/kernel/sys_or32.c b/arch/openrisc/kernel/sys_or32.c
new file mode 100644
index 000000000000..57060084c0cc
--- /dev/null
+++ b/arch/openrisc/kernel/sys_or32.c
@@ -0,0 +1,57 @@
+/*
+ * OpenRISC sys_or32.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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 file contains various random system calls that
+ * have a non-standard calling sequence on some platforms.
+ * Since we don't have to do any backwards compatibility, our
+ * versions are done in the most "normal" way possible.
+ */
+
+#include <linux/errno.h>
+#include <linux/syscalls.h>
+#include <linux/mm.h>
+
+#include <asm/syscalls.h>
+
+/* These are secondary entry points as the primary entry points are defined in
+ * entry.S where we add the 'regs' parameter value
+ */
+
+asmlinkage long _sys_clone(unsigned long clone_flags, unsigned long newsp,
+ int __user *parent_tid, int __user *child_tid,
+ struct pt_regs *regs)
+{
+ long ret;
+
+ /* FIXME: Is alignment necessary? */
+ /* newsp = ALIGN(newsp, 4); */
+
+ if (!newsp)
+ newsp = regs->sp;
+
+ ret = do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+
+ return ret;
+}
+
+asmlinkage int _sys_fork(struct pt_regs *regs)
+{
+#ifdef CONFIG_MMU
+ return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+#else
+ return -EINVAL;
+#endif
+}
diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c
new file mode 100644
index 000000000000..bd946ef1623d
--- /dev/null
+++ b/arch/openrisc/kernel/time.c
@@ -0,0 +1,181 @@
+/*
+ * OpenRISC time.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/time.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+#include <linux/ftrace.h>
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/cpuinfo.h>
+
+static int openrisc_timer_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ u32 c;
+
+ /* Read 32-bit counter value, add delta, mask off the low 28 bits.
+ * We're guaranteed delta won't be bigger than 28 bits because the
+ * generic timekeeping code ensures that for us.
+ */
+ c = mfspr(SPR_TTCR);
+ c += delta;
+ c &= SPR_TTMR_TP;
+
+ /* Set counter and enable interrupt.
+ * Keep timer in continuous mode always.
+ */
+ mtspr(SPR_TTMR, SPR_TTMR_CR | SPR_TTMR_IE | c);
+
+ return 0;
+}
+
+static void openrisc_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ pr_debug(KERN_INFO "%s: periodic\n", __func__);
+ BUG();
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ pr_debug(KERN_INFO "%s: oneshot\n", __func__);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ pr_debug(KERN_INFO "%s: unused\n", __func__);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ pr_debug(KERN_INFO "%s: shutdown\n", __func__);
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ pr_debug(KERN_INFO "%s: resume\n", __func__);
+ break;
+ }
+}
+
+/* This is the clock event device based on the OR1K tick timer.
+ * As the timer is being used as a continuous clock-source (required for HR
+ * timers) we cannot enable the PERIODIC feature. The tick timer can run using
+ * one-shot events, so no problem.
+ */
+
+static struct clock_event_device clockevent_openrisc_timer = {
+ .name = "openrisc_timer_clockevent",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 300,
+ .set_next_event = openrisc_timer_set_next_event,
+ .set_mode = openrisc_timer_set_mode,
+};
+
+static inline void timer_ack(void)
+{
+ /* Clear the IP bit and disable further interrupts */
+ /* This can be done very simply... we just need to keep the timer
+ running, so just maintain the CR bits while clearing the rest
+ of the register
+ */
+ mtspr(SPR_TTMR, SPR_TTMR_CR);
+}
+
+/*
+ * The timer interrupt is mostly handled in generic code nowadays... this
+ * function just acknowledges the interrupt and fires the event handler that
+ * has been set on the clockevent device by the generic time management code.
+ *
+ * This function needs to be called by the timer exception handler and that's
+ * all the exception handler needs to do.
+ */
+
+irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs)
+{
+ struct pt_regs *old_regs = set_irq_regs(regs);
+ struct clock_event_device *evt = &clockevent_openrisc_timer;
+
+ timer_ack();
+
+ /*
+ * update_process_times() expects us to have called irq_enter().
+ */
+ irq_enter();
+ evt->event_handler(evt);
+ irq_exit();
+
+ set_irq_regs(old_regs);
+
+ return IRQ_HANDLED;
+}
+
+static __init void openrisc_clockevent_init(void)
+{
+ clockevents_calc_mult_shift(&clockevent_openrisc_timer,
+ cpuinfo.clock_frequency, 4);
+
+ /* We only have 28 bits */
+ clockevent_openrisc_timer.max_delta_ns =
+ clockevent_delta2ns((u32) 0x0fffffff, &clockevent_openrisc_timer);
+ clockevent_openrisc_timer.min_delta_ns =
+ clockevent_delta2ns(1, &clockevent_openrisc_timer);
+ clockevent_openrisc_timer.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_openrisc_timer);
+}
+
+/**
+ * Clocksource: Based on OpenRISC timer/counter
+ *
+ * This sets up the OpenRISC Tick Timer as a clock source. The tick timer
+ * is 32 bits wide and runs at the CPU clock frequency.
+ */
+
+static cycle_t openrisc_timer_read(struct clocksource *cs)
+{
+ return (cycle_t) mfspr(SPR_TTCR);
+}
+
+static struct clocksource openrisc_timer = {
+ .name = "openrisc_timer",
+ .rating = 200,
+ .read = openrisc_timer_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init openrisc_timer_init(void)
+{
+ if (clocksource_register_hz(&openrisc_timer, cpuinfo.clock_frequency))
+ panic("failed to register clocksource");
+
+ /* Enable the incrementer: 'continuous' mode with interrupt disabled */
+ mtspr(SPR_TTMR, SPR_TTMR_CR);
+
+ return 0;
+}
+
+void __init time_init(void)
+{
+ u32 upr;
+
+ upr = mfspr(SPR_UPR);
+ if (!(upr & SPR_UPR_TTP))
+ panic("Linux not supported on devices without tick timer");
+
+ openrisc_timer_init();
+ openrisc_clockevent_init();
+}
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
new file mode 100644
index 000000000000..a4ec44a052b2
--- /dev/null
+++ b/arch/openrisc/kernel/traps.c
@@ -0,0 +1,366 @@
+/*
+ * OpenRISC traps.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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.
+ *
+ * Here we handle the break vectors not used by the system call
+ * mechanism, as well as some general stack/register dumping
+ * things.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kallsyms.h>
+#include <asm/uaccess.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+extern char _etext, _stext;
+
+int kstack_depth_to_print = 0x180;
+
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+ return p > (void *)tinfo && p < (void *)tinfo + THREAD_SIZE - 3;
+}
+
+void show_trace(struct task_struct *task, unsigned long *stack)
+{
+ struct thread_info *context;
+ unsigned long addr;
+
+ context = (struct thread_info *)
+ ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+
+ while (valid_stack_ptr(context, stack)) {
+ addr = *stack++;
+ if (__kernel_text_address(addr)) {
+ printk(" [<%08lx>]", addr);
+ print_symbol(" %s", addr);
+ printk("\n");
+ }
+ }
+ printk(" =======================\n");
+}
+
+/* displays a short stack trace */
+void show_stack(struct task_struct *task, unsigned long *esp)
+{
+ unsigned long addr, *stack;
+ int i;
+
+ if (esp == NULL)
+ esp = (unsigned long *)&esp;
+
+ stack = esp;
+
+ printk("Stack dump [0x%08lx]:\n", (unsigned long)esp);
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (kstack_end(stack))
+ break;
+ if (__get_user(addr, stack)) {
+ /* This message matches "failing address" marked
+ s390 in ksymoops, so lines containing it will
+ not be filtered out by ksymoops. */
+ printk("Failing address 0x%lx\n", (unsigned long)stack);
+ break;
+ }
+ stack++;
+
+ printk("sp + %02d: 0x%08lx\n", i * 4, addr);
+ }
+ printk("\n");
+
+ show_trace(task, esp);
+
+ return;
+}
+
+void show_trace_task(struct task_struct *tsk)
+{
+ /*
+ * TODO: SysRq-T trace dump...
+ */
+}
+
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+ unsigned long stack;
+
+ show_stack(current, &stack);
+}
+
+void show_registers(struct pt_regs *regs)
+{
+ int i;
+ int in_kernel = 1;
+ unsigned long esp;
+
+ esp = (unsigned long)(&regs->sp);
+ if (user_mode(regs))
+ in_kernel = 0;
+
+ printk("CPU #: %d\n"
+ " PC: %08lx SR: %08lx SP: %08lx\n",
+ smp_processor_id(), regs->pc, regs->sr, regs->sp);
+ printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
+ 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
+ printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
+ regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
+ printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
+ regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
+ printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
+ regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
+ printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
+ regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
+ printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
+ regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
+ printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
+ regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
+ printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
+ regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
+ printk(" RES: %08lx oGPR11: %08lx syscallno: %08lx\n",
+ regs->gpr[11], regs->orig_gpr11, regs->syscallno);
+
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
+ current->comm, current->pid, (unsigned long)current);
+ /*
+ * When in-kernel, we also print out the stack and code at the
+ * time of the fault..
+ */
+ if (in_kernel) {
+
+ printk("\nStack: ");
+ show_stack(NULL, (unsigned long *)esp);
+
+ printk("\nCode: ");
+ if (regs->pc < PAGE_OFFSET)
+ goto bad;
+
+ for (i = -24; i < 24; i++) {
+ unsigned char c;
+ if (__get_user(c, &((unsigned char *)regs->pc)[i])) {
+bad:
+ printk(" Bad PC value.");
+ break;
+ }
+
+ if (i == 0)
+ printk("(%02x) ", c);
+ else
+ printk("%02x ", c);
+ }
+ }
+ printk("\n");
+}
+
+void nommu_dump_state(struct pt_regs *regs,
+ unsigned long ea, unsigned long vector)
+{
+ int i;
+ unsigned long addr, stack = regs->sp;
+
+ printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector);
+
+ printk("CPU #: %d\n"
+ " PC: %08lx SR: %08lx SP: %08lx\n",
+ 0, regs->pc, regs->sr, regs->sp);
+ printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
+ 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
+ printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
+ regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
+ printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
+ regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
+ printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
+ regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
+ printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
+ regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
+ printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
+ regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
+ printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
+ regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
+ printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
+ regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
+ printk(" RES: %08lx oGPR11: %08lx syscallno: %08lx\n",
+ regs->gpr[11], regs->orig_gpr11, regs->syscallno);
+
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
+ ((struct task_struct *)(__pa(current)))->comm,
+ ((struct task_struct *)(__pa(current)))->pid,
+ (unsigned long)current);
+
+ printk("\nStack: ");
+ printk("Stack dump [0x%08lx]:\n", (unsigned long)stack);
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (((long)stack & (THREAD_SIZE - 1)) == 0)
+ break;
+ stack++;
+
+ printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4,
+ *((unsigned long *)(__pa(stack))));
+ }
+ printk("\n");
+
+ printk("Call Trace: ");
+ i = 1;
+ while (((long)stack & (THREAD_SIZE - 1)) != 0) {
+ addr = *((unsigned long *)__pa(stack));
+ stack++;
+
+ if (kernel_text_address(addr)) {
+ if (i && ((i % 6) == 0))
+ printk("\n ");
+ printk(" [<%08lx>]", addr);
+ i++;
+ }
+ }
+ printk("\n");
+
+ printk("\nCode: ");
+
+ for (i = -24; i < 24; i++) {
+ unsigned char c;
+ c = ((unsigned char *)(__pa(regs->pc)))[i];
+
+ if (i == 0)
+ printk("(%02x) ", c);
+ else
+ printk("%02x ", c);
+ }
+ printk("\n");
+}
+
+/* This is normally the 'Oops' routine */
+void die(const char *str, struct pt_regs *regs, long err)
+{
+
+ console_verbose();
+ printk("\n%s#: %04lx\n", str, err & 0xffff);
+ show_registers(regs);
+#ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
+ printk("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n");
+
+ /* shut down interrupts */
+ local_irq_disable();
+
+ __asm__ __volatile__("l.nop 1");
+ do {} while (1);
+#endif
+ do_exit(SIGSEGV);
+}
+
+/* This is normally the 'Oops' routine */
+void die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+ if (user_mode(regs))
+ return;
+
+ die(str, regs, err);
+}
+
+void unhandled_exception(struct pt_regs *regs, int ea, int vector)
+{
+ printk("Unable to handle exception at EA =0x%x, vector 0x%x",
+ ea, vector);
+ die("Oops", regs, 9);
+}
+
+void __init trap_init(void)
+{
+ /* Nothing needs to be done */
+}
+
+asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
+{
+ siginfo_t info;
+ memset(&info, 0, sizeof(info));
+ info.si_signo = SIGTRAP;
+ info.si_code = TRAP_TRACE;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGTRAP, &info, current);
+
+ regs->pc += 4;
+}
+
+asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
+{
+ siginfo_t info;
+
+ if (user_mode(regs)) {
+ /* Send a SIGSEGV */
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code has been set above */
+ info.si_addr = (void *)address;
+ force_sig_info(SIGSEGV, &info, current);
+ } else {
+ printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
+ show_registers(regs);
+ die("Die:", regs, address);
+ }
+
+}
+
+asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
+{
+ siginfo_t info;
+
+ if (user_mode(regs)) {
+ /* Send a SIGBUS */
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGBUS, &info, current);
+ } else { /* Kernel mode */
+ printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address);
+ show_registers(regs);
+ die("Die:", regs, address);
+ }
+}
+
+asmlinkage void do_illegal_instruction(struct pt_regs *regs,
+ unsigned long address)
+{
+ siginfo_t info;
+
+ if (user_mode(regs)) {
+ /* Send a SIGILL */
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGBUS, &info, current);
+ } else { /* Kernel mode */
+ printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n",
+ address);
+ show_registers(regs);
+ die("Die:", regs, address);
+ }
+}
diff --git a/arch/openrisc/kernel/vmlinux.h b/arch/openrisc/kernel/vmlinux.h
new file mode 100644
index 000000000000..ee842a2d3f36
--- /dev/null
+++ b/arch/openrisc/kernel/vmlinux.h
@@ -0,0 +1,12 @@
+#ifndef __OPENRISC_VMLINUX_H_
+#define __OPENRISC_VMLINUX_H_
+
+extern char _stext, _etext, _edata, _end;
+#ifdef CONFIG_BLK_DEV_INITRD
+extern char __initrd_start, __initrd_end;
+extern char __initramfs_start;
+#endif
+
+extern u32 __dtb_start[];
+
+#endif
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..2d69a853b742
--- /dev/null
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -0,0 +1,115 @@
+/*
+ * OpenRISC vmlinux.lds.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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.
+ *
+ * ld script for OpenRISC architecture
+ */
+
+/* TODO
+ * - clean up __offset & stuff
+ * - change all 8192 aligment to PAGE !!!
+ * - recheck if all aligments are really needed
+ */
+
+# define LOAD_OFFSET PAGE_OFFSET
+# define LOAD_BASE PAGE_OFFSET
+
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT("elf32-or32", "elf32-or32", "elf32-or32")
+jiffies = jiffies_64 + 4;
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = LOAD_BASE ;
+
+ /* _s_kernel_ro must be page aligned */
+ . = ALIGN(PAGE_SIZE);
+ _s_kernel_ro = .;
+
+ .text : AT(ADDR(.text) - LOAD_OFFSET)
+ {
+ _stext = .;
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ IRQENTRY_TEXT
+ *(.fixup)
+ *(.text.__*)
+ _etext = .;
+ }
+ /* TODO: Check if fixup and text.__* are really necessary
+ * fixup is definitely necessary
+ */
+
+ _sdata = .;
+
+ /* Page alignment required for RO_DATA_SECTION */
+ RO_DATA_SECTION(PAGE_SIZE)
+ _e_kernel_ro = .;
+
+ /* Whatever comes after _e_kernel_ro had better be page-aligend, too */
+
+ /* 32 here is cacheline size... recheck this */
+ RW_DATA_SECTION(32, PAGE_SIZE, PAGE_SIZE)
+
+ _edata = .;
+
+ EXCEPTION_TABLE(4)
+ NOTES
+
+ /* Init code and data */
+ . = ALIGN(PAGE_SIZE);
+ __init_begin = .;
+
+ HEAD_TEXT_SECTION
+
+ /* Page aligned */
+ INIT_TEXT_SECTION(PAGE_SIZE)
+
+ /* Align __setup_start on 16 byte boundary */
+ INIT_DATA_SECTION(16)
+
+ PERCPU_SECTION(L1_CACHE_BYTES)
+
+ __init_end = .;
+
+ . = ALIGN(PAGE_SIZE);
+ .initrd : AT(ADDR(.initrd) - LOAD_OFFSET)
+ {
+ __initrd_start = .;
+ *(.initrd)
+ __initrd_end = .;
+ FILL (0);
+ . = ALIGN (PAGE_SIZE);
+ }
+
+ __vmlinux_end = .; /* last address of the physical file */
+
+ BSS_SECTION(0, 0, 0x20)
+
+ _end = .;
+
+ /* Throw in the debugging sections */
+ STABS_DEBUG
+ DWARF_DEBUG
+
+ /* Sections to be discarded -- must be last */
+ DISCARDS
+}
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
new file mode 100644
index 000000000000..966f65dbc6f0
--- /dev/null
+++ b/arch/openrisc/lib/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for or32 specific library files..
+#
+
+obj-y = string.o delay.o
diff --git a/arch/openrisc/lib/delay.c b/arch/openrisc/lib/delay.c
new file mode 100644
index 000000000000..01d9740ae6f3
--- /dev/null
+++ b/arch/openrisc/lib/delay.c
@@ -0,0 +1,60 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * 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
+ *
+ * Precise Delay Loops
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/delay.h>
+#include <asm/timex.h>
+#include <asm/processor.h>
+
+int __devinit read_current_timer(unsigned long *timer_value)
+{
+ *timer_value = mfspr(SPR_TTCR);
+ return 0;
+}
+
+void __delay(unsigned long cycles)
+{
+ cycles_t target = get_cycles() + cycles;
+
+ while (get_cycles() < target)
+ cpu_relax();
+}
+EXPORT_SYMBOL(__delay);
+
+inline void __const_udelay(unsigned long xloops)
+{
+ unsigned long long loops;
+
+ loops = xloops * loops_per_jiffy * HZ;
+
+ __delay(loops >> 32);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+ __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/openrisc/lib/string.S b/arch/openrisc/lib/string.S
new file mode 100644
index 000000000000..465f04bc7deb
--- /dev/null
+++ b/arch/openrisc/lib/string.S
@@ -0,0 +1,204 @@
+/*
+ * OpenRISC string.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/errno.h>
+
+ /*
+ * this can be optimized by doing gcc inline assemlby with
+ * proper constraints (no need to save args registers...)
+ *
+ */
+
+
+/*
+ *
+ * int __copy_tofrom_user(void *to, const void *from, unsigned long size);
+ *
+ * NOTE: it returns number of bytes NOT copied !!!
+ *
+ */
+ .global __copy_tofrom_user
+__copy_tofrom_user:
+ l.addi r1,r1,-12
+ l.sw 0(r1),r6
+ l.sw 4(r1),r4
+ l.sw 8(r1),r3
+
+ l.addi r11,r5,0
+2: l.sfeq r11,r0
+ l.bf 1f
+ l.addi r11,r11,-1
+8: l.lbz r6,0(r4)
+9: l.sb 0(r3),r6
+ l.addi r3,r3,1
+ l.j 2b
+ l.addi r4,r4,1
+1:
+ l.addi r11,r11,1 // r11 holds the return value
+
+ l.lwz r6,0(r1)
+ l.lwz r4,4(r1)
+ l.lwz r3,8(r1)
+ l.jr r9
+ l.addi r1,r1,12
+
+ .section .fixup, "ax"
+99:
+ l.j 1b
+ l.nop
+ .previous
+
+ .section __ex_table, "a"
+ .long 8b, 99b // read fault
+ .long 9b, 99b // write fault
+ .previous
+
+/*
+ * unsigned long clear_user(void *addr, unsigned long size) ;
+ *
+ * NOTE: it returns number of bytes NOT cleared !!!
+ */
+ .global __clear_user
+__clear_user:
+ l.addi r1,r1,-8
+ l.sw 0(r1),r4
+ l.sw 4(r1),r3
+
+2: l.sfeq r4,r0
+ l.bf 1f
+ l.addi r4,r4,-1
+9: l.sb 0(r3),r0
+ l.j 2b
+ l.addi r3,r3,1
+
+1:
+ l.addi r11,r4,1
+
+ l.lwz r4,0(r1)
+ l.lwz r3,4(r1)
+ l.jr r9
+ l.addi r1,r1,8
+
+ .section .fixup, "ax"
+99:
+ l.j 1b
+ l.nop
+ .previous
+
+ .section __ex_table, "a"
+ .long 9b, 99b // write fault
+ .previous
+
+/*
+ * long strncpy_from_user(char *dst, const char *src, long count)
+ *
+ *
+ */
+ .global __strncpy_from_user
+__strncpy_from_user:
+ l.addi r1,r1,-16
+ l.sw 0(r1),r6
+ l.sw 4(r1),r5
+ l.sw 8(r1),r4
+ l.sw 12(r1),r3
+
+ l.addi r11,r5,0
+2: l.sfeq r5,r0
+ l.bf 1f
+ l.addi r5,r5,-1
+8: l.lbz r6,0(r4)
+ l.sfeq r6,r0
+ l.bf 1f
+9: l.sb 0(r3),r6
+ l.addi r3,r3,1
+ l.j 2b
+ l.addi r4,r4,1
+1:
+ l.lwz r6,0(r1)
+ l.addi r5,r5,1
+ l.sub r11,r11,r5 // r11 holds the return value
+
+ l.lwz r6,0(r1)
+ l.lwz r5,4(r1)
+ l.lwz r4,8(r1)
+ l.lwz r3,12(r1)
+ l.jr r9
+ l.addi r1,r1,16
+
+ .section .fixup, "ax"
+99:
+ l.movhi r11,hi(-EFAULT)
+ l.ori r11,r11,lo(-EFAULT)
+
+ l.lwz r6,0(r1)
+ l.lwz r5,4(r1)
+ l.lwz r4,8(r1)
+ l.lwz r3,12(r1)
+ l.jr r9
+ l.addi r1,r1,16
+ .previous
+
+ .section __ex_table, "a"
+ .long 8b, 99b // read fault
+ .previous
+
+/*
+ * extern int __strnlen_user(const char *str, long len, unsigned long top);
+ *
+ *
+ * RTRN: - length of a string including NUL termination character
+ * - on page fault 0
+ */
+
+ .global __strnlen_user
+__strnlen_user:
+ l.addi r1,r1,-8
+ l.sw 0(r1),r6
+ l.sw 4(r1),r3
+
+ l.addi r11,r0,0
+2: l.sfeq r11,r4
+ l.bf 1f
+ l.addi r11,r11,1
+8: l.lbz r6,0(r3)
+ l.sfeq r6,r0
+ l.bf 1f
+ l.sfgeu r3,r5 // are we over the top ?
+ l.bf 99f
+ l.j 2b
+ l.addi r3,r3,1
+
+1:
+ l.lwz r6,0(r1)
+ l.lwz r3,4(r1)
+ l.jr r9
+ l.addi r1,r1,8
+
+ .section .fixup, "ax"
+99:
+ l.addi r11,r0,0
+
+ l.lwz r6,0(r1)
+ l.lwz r3,4(r1)
+ l.jr r9
+ l.addi r1,r1,8
+ .previous
+
+ .section __ex_table, "a"
+ .long 8b, 99b // read fault
+ .previous
diff --git a/arch/openrisc/mm/Makefile b/arch/openrisc/mm/Makefile
new file mode 100644
index 000000000000..324ba2634529
--- /dev/null
+++ b/arch/openrisc/mm/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux openrisc-specific parts of the memory manager.
+#
+
+obj-y := fault.o tlb.o init.o ioremap.o
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
new file mode 100644
index 000000000000..a5dce82f864b
--- /dev/null
+++ b/arch/openrisc/mm/fault.c
@@ -0,0 +1,338 @@
+/*
+ * OpenRISC fault.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/mm.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+
+#define NUM_TLB_ENTRIES 64
+#define TLB_OFFSET(add) (((add) >> PAGE_SHIFT) & (NUM_TLB_ENTRIES-1))
+
+unsigned long pte_misses; /* updated by do_page_fault() */
+unsigned long pte_errors; /* updated by do_page_fault() */
+
+/* __PHX__ :: - check the vmalloc_fault in do_page_fault()
+ * - also look into include/asm-or32/mmu_context.h
+ */
+volatile pgd_t *current_pgd;
+
+extern void die(char *, struct pt_regs *, long);
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * If this routine detects a bad access, it returns 1, otherwise it
+ * returns 0.
+ */
+
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
+ unsigned long vector, int write_acc)
+{
+ struct task_struct *tsk;
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+ siginfo_t info;
+ int fault;
+
+ tsk = current;
+
+ /*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ *
+ * NOTE2: This is done so that, when updating the vmalloc
+ * mappings we don't have to walk all processes pgdirs and
+ * add the high mappings all at once. Instead we do it as they
+ * are used. However vmalloc'ed page entries have the PAGE_GLOBAL
+ * bit set so sometimes the TLB can use a lingering entry.
+ *
+ * This verifies that the fault happens in kernel space
+ * and that the fault was not a protection error.
+ */
+
+ if (address >= VMALLOC_START &&
+ (vector != 0x300 && vector != 0x400) &&
+ !user_mode(regs))
+ goto vmalloc_fault;
+
+ /* If exceptions were enabled, we can reenable them here */
+ if (user_mode(regs)) {
+ /* Exception was in userspace: reenable interrupts */
+ local_irq_enable();
+ } else {
+ /* If exception was in a syscall, then IRQ's may have
+ * been enabled or disabled. If they were enabled,
+ * reenable them.
+ */
+ if (regs->sr && (SPR_SR_IEE | SPR_SR_TEE))
+ local_irq_enable();
+ }
+
+ mm = tsk->mm;
+ info.si_code = SEGV_MAPERR;
+
+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+
+ if (in_interrupt() || !mm)
+ goto no_context;
+
+ 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 (user_mode(regs)) {
+ /*
+ * accessing the stack below usp is always a bug.
+ * we get page-aligned addresses so we can only check
+ * if we're within a page from usp, but that might be
+ * enough to catch brutal errors at least.
+ */
+ if (address + PAGE_SIZE < regs->sp)
+ goto bad_area;
+ }
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+ /*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+
+good_area:
+ info.si_code = SEGV_ACCERR;
+
+ /* first do some preliminary protection checks */
+
+ if (write_acc) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
+ /* not present */
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+
+ /* are we trying to execute nonexecutable area */
+ if ((vector == 0x400) && !(vma->vm_page_prot.pgprot & _PAGE_EXEC))
+ goto bad_area;
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+
+ fault = handle_mm_fault(mm, vma, address, write_acc);
+ if (unlikely(fault & VM_FAULT_ERROR)) {
+ if (fault & VM_FAULT_OOM)
+ goto out_of_memory;
+ else if (fault & VM_FAULT_SIGBUS)
+ goto do_sigbus;
+ BUG();
+ }
+ /*RGD modeled on Cris */
+ if (fault & VM_FAULT_MAJOR)
+ tsk->maj_flt++;
+ else
+ tsk->min_flt++;
+
+ up_read(&mm->mmap_sem);
+ return;
+
+ /*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+
+bad_area:
+ up_read(&mm->mmap_sem);
+
+bad_area_nosemaphore:
+
+ /* User mode accesses just cause a SIGSEGV */
+
+ if (user_mode(regs)) {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code has been set above */
+ info.si_addr = (void *)address;
+ force_sig_info(SIGSEGV, &info, tsk);
+ return;
+ }
+
+no_context:
+
+ /* Are we prepared to handle this kernel fault?
+ *
+ * (The kernel has valid exception-points in the source
+ * when it acesses user-memory. When it fails in one
+ * of those points, we find it in a table and do a jump
+ * to some fixup code that loads an appropriate error
+ * code)
+ */
+
+ {
+ const struct exception_table_entry *entry;
+
+ __asm__ __volatile__("l.nop 42");
+
+ if ((entry = search_exception_tables(regs->pc)) != NULL) {
+ /* Adjust the instruction pointer in the stackframe */
+ regs->pc = entry->fixup;
+ return;
+ }
+ }
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+ if ((unsigned long)(address) < PAGE_SIZE)
+ printk(KERN_ALERT
+ "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel access");
+ printk(" at virtual address 0x%08lx\n", address);
+
+ die("Oops", regs, write_acc);
+
+ do_exit(SIGKILL);
+
+ /*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+
+out_of_memory:
+ __asm__ __volatile__("l.nop 42");
+ __asm__ __volatile__("l.nop 1");
+
+ up_read(&mm->mmap_sem);
+ printk("VM: killing process %s\n", tsk->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+
+do_sigbus:
+ up_read(&mm->mmap_sem);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGBUS, &info, tsk);
+
+ /* Kernel mode? Handle exceptions or die */
+ if (!user_mode(regs))
+ goto no_context;
+ return;
+
+vmalloc_fault:
+ {
+ /*
+ * Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ *
+ * Use current_pgd instead of tsk->active_mm->pgd
+ * since the latter might be unavailable if this
+ * code is executed in a misfortunately run irq
+ * (like inside schedule() between switch_mm and
+ * switch_to...).
+ */
+
+ int offset = pgd_index(address);
+ pgd_t *pgd, *pgd_k;
+ pud_t *pud, *pud_k;
+ pmd_t *pmd, *pmd_k;
+ pte_t *pte_k;
+
+/*
+ phx_warn("do_page_fault(): vmalloc_fault will not work, "
+ "since current_pgd assign a proper value somewhere\n"
+ "anyhow we don't need this at the moment\n");
+
+ phx_mmu("vmalloc_fault");
+*/
+ pgd = (pgd_t *)current_pgd + offset;
+ pgd_k = init_mm.pgd + offset;
+
+ /* Since we're two-level, we don't need to do both
+ * set_pgd and set_pmd (they do the same thing). If
+ * we go three-level at some point, do the right thing
+ * with pgd_present and set_pgd here.
+ *
+ * Also, since the vmalloc area is global, we don't
+ * need to copy individual PTE's, it is enough to
+ * copy the pgd pointer into the pte page of the
+ * root task. If that is there, we'll find our pte if
+ * it exists.
+ */
+
+ pud = pud_offset(pgd, address);
+ pud_k = pud_offset(pgd_k, address);
+ if (!pud_present(*pud_k))
+ goto no_context;
+
+ pmd = pmd_offset(pud, address);
+ pmd_k = pmd_offset(pud_k, address);
+
+ if (!pmd_present(*pmd_k))
+ goto bad_area_nosemaphore;
+
+ set_pmd(pmd, *pmd_k);
+
+ /* Make sure the actual PTE exists as well to
+ * catch kernel vmalloc-area accesses to non-mapped
+ * addresses. If we don't do this, this will just
+ * silently loop forever.
+ */
+
+ pte_k = pte_offset_kernel(pmd_k, address);
+ if (!pte_present(*pte_k))
+ goto no_context;
+
+ return;
+ }
+}
diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c
new file mode 100644
index 000000000000..359dcb20fe85
--- /dev/null
+++ b/arch/openrisc/mm/init.c
@@ -0,0 +1,283 @@
+/*
+ * OpenRISC idle.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h> /* for initrd_* */
+#include <linux/pagemap.h>
+#include <linux/memblock.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+#include <asm/tlbflush.h>
+
+int mem_init_done;
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+static void __init zone_sizes_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES];
+
+ /* Clear the zone sizes */
+ memset(zones_size, 0, sizeof(zones_size));
+
+ /*
+ * We use only ZONE_NORMAL
+ */
+ zones_size[ZONE_NORMAL] = max_low_pfn;
+
+ free_area_init(zones_size);
+}
+
+extern const char _s_kernel_ro[], _e_kernel_ro[];
+
+/*
+ * Map all physical memory into kernel's address space.
+ *
+ * This is explicitly coded for two-level page tables, so if you need
+ * something else then this needs to change.
+ */
+static void __init map_ram(void)
+{
+ unsigned long v, p, e;
+ pgprot_t prot;
+ pgd_t *pge;
+ pud_t *pue;
+ pmd_t *pme;
+ pte_t *pte;
+ /* These mark extents of read-only kernel pages...
+ * ...from vmlinux.lds.S
+ */
+ struct memblock_region *region;
+
+ v = PAGE_OFFSET;
+
+ for_each_memblock(memory, region) {
+ p = (u32) region->base & PAGE_MASK;
+ e = p + (u32) region->size;
+
+ v = (u32) __va(p);
+ pge = pgd_offset_k(v);
+
+ while (p < e) {
+ int j;
+ pue = pud_offset(pge, v);
+ pme = pmd_offset(pue, v);
+
+ if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) {
+ panic("%s: OR1K kernel hardcoded for "
+ "two-level page tables",
+ __func__);
+ }
+
+ /* Alloc one page for holding PTE's... */
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte)));
+
+ /* Fill the newly allocated page with PTE'S */
+ for (j = 0; p < e && j < PTRS_PER_PGD;
+ v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
+ if (v >= (u32) _e_kernel_ro ||
+ v < (u32) _s_kernel_ro)
+ prot = PAGE_KERNEL;
+ else
+ prot = PAGE_KERNEL_RO;
+
+ set_pte(pte, mk_pte_phys(p, prot));
+ }
+
+ pge++;
+ }
+
+ printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
+ region->base, region->base + region->size);
+ }
+}
+
+void __init paging_init(void)
+{
+ extern void tlb_init(void);
+
+ unsigned long end;
+ int i;
+
+ printk(KERN_INFO "Setting up paging and PTEs.\n");
+
+ /* clear out the init_mm.pgd that will contain the kernel's mappings */
+
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ swapper_pg_dir[i] = __pgd(0);
+
+ /* make sure the current pgd table points to something sane
+ * (even if it is most probably not used until the next
+ * switch_mm)
+ */
+ current_pgd = init_mm.pgd;
+
+ end = (unsigned long)__va(max_low_pfn * PAGE_SIZE);
+
+ map_ram();
+
+ zone_sizes_init();
+
+ /* self modifying code ;) */
+ /* Since the old TLB miss handler has been running up until now,
+ * the kernel pages are still all RW, so we can still modify the
+ * text directly... after this change and a TLB flush, the kernel
+ * pages will become RO.
+ */
+ {
+ extern unsigned long dtlb_miss_handler;
+ extern unsigned long itlb_miss_handler;
+
+ unsigned long *dtlb_vector = __va(0x900);
+ unsigned long *itlb_vector = __va(0xa00);
+
+ printk(KERN_INFO "dtlb_miss_handler %p\n", &dtlb_miss_handler);
+ *dtlb_vector = ((unsigned long)&dtlb_miss_handler -
+ (unsigned long)dtlb_vector) >> 2;
+
+ printk(KERN_INFO "itlb_miss_handler %p\n", &itlb_miss_handler);
+ *itlb_vector = ((unsigned long)&itlb_miss_handler -
+ (unsigned long)itlb_vector) >> 2;
+ }
+
+ /* Invalidate instruction caches after code modification */
+ mtspr(SPR_ICBIR, 0x900);
+ mtspr(SPR_ICBIR, 0xa00);
+
+ /* New TLB miss handlers and kernel page tables are in now place.
+ * Make sure that page flags get updated for all pages in TLB by
+ * flushing the TLB and forcing all TLB entries to be recreated
+ * from their page table flags.
+ */
+ flush_tlb_all();
+}
+
+/* References to section boundaries */
+
+extern char _stext, _etext, _edata, __bss_start, _end;
+extern char __init_begin, __init_end;
+
+static int __init free_pages_init(void)
+{
+ int reservedpages, pfn;
+
+ /* this will put all low memory onto the freelists */
+ totalram_pages = free_all_bootmem();
+
+ reservedpages = 0;
+ for (pfn = 0; pfn < max_low_pfn; pfn++) {
+ /*
+ * Only count reserved RAM pages
+ */
+ if (PageReserved(mem_map + pfn))
+ reservedpages++;
+ }
+
+ return reservedpages;
+}
+
+static void __init set_max_mapnr_init(void)
+{
+ max_mapnr = num_physpages = max_low_pfn;
+}
+
+void __init mem_init(void)
+{
+ int codesize, reservedpages, datasize, initsize;
+
+ if (!mem_map)
+ BUG();
+
+ set_max_mapnr_init();
+
+ high_memory = (void *)__va(max_low_pfn * PAGE_SIZE);
+
+ /* clear the zero-page */
+ memset((void *)empty_zero_page, 0, PAGE_SIZE);
+
+ reservedpages = free_pages_init();
+
+ codesize = (unsigned long)&_etext - (unsigned long)&_stext;
+ datasize = (unsigned long)&_edata - (unsigned long)&_etext;
+ initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
+
+ printk(KERN_INFO
+ "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
+ (unsigned long)nr_free_pages() << (PAGE_SHIFT - 10),
+ max_mapnr << (PAGE_SHIFT - 10), codesize >> 10,
+ reservedpages << (PAGE_SHIFT - 10), datasize >> 10,
+ initsize >> 10, (unsigned long)(0 << (PAGE_SHIFT - 10))
+ );
+
+ printk("mem_init_done ...........................................\n");
+ mem_init_done = 1;
+ return;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
+ (end - start) >> 10);
+
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(start));
+ init_page_count(virt_to_page(start));
+ free_page(start);
+ totalram_pages++;
+ }
+}
+#endif
+
+void free_initmem(void)
+{
+ unsigned long addr;
+
+ addr = (unsigned long)(&__init_begin);
+ for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ init_page_count(virt_to_page(addr));
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n",
+ ((unsigned long)&__init_end -
+ (unsigned long)&__init_begin) >> 10);
+}
diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c
new file mode 100644
index 000000000000..62b08ef392be
--- /dev/null
+++ b/arch/openrisc/mm/ioremap.c
@@ -0,0 +1,137 @@
+/*
+ * OpenRISC ioremap.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/vmalloc.h>
+#include <linux/io.h>
+#include <asm/pgalloc.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+#include <asm/bug.h>
+#include <asm/pgtable.h>
+#include <linux/sched.h>
+#include <asm/tlbflush.h>
+
+extern int mem_init_done;
+
+static unsigned int fixmaps_used __initdata;
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void __iomem *__init_refok
+__ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot)
+{
+ phys_addr_t p;
+ unsigned long v;
+ unsigned long offset, last_addr;
+ struct vm_struct *area = NULL;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = addr + size - 1;
+ if (!size || last_addr < addr)
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = addr & ~PAGE_MASK;
+ p = addr & PAGE_MASK;
+ size = PAGE_ALIGN(last_addr + 1) - p;
+
+ if (likely(mem_init_done)) {
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ v = (unsigned long)area->addr;
+ } else {
+ if ((fixmaps_used + (size >> PAGE_SHIFT)) > FIX_N_IOREMAPS)
+ return NULL;
+ v = fix_to_virt(FIX_IOREMAP_BEGIN + fixmaps_used);
+ fixmaps_used += (size >> PAGE_SHIFT);
+ }
+
+ if (ioremap_page_range(v, v + size, p, prot)) {
+ if (likely(mem_init_done))
+ vfree(area->addr);
+ else
+ fixmaps_used -= (size >> PAGE_SHIFT);
+ return NULL;
+ }
+
+ return (void __iomem *)(offset + (char *)v);
+}
+
+void iounmap(void *addr)
+{
+ /* If the page is from the fixmap pool then we just clear out
+ * the fixmap mapping.
+ */
+ if (unlikely((unsigned long)addr > FIXADDR_START)) {
+ /* This is a bit broken... we don't really know
+ * how big the area is so it's difficult to know
+ * how many fixed pages to invalidate...
+ * just flush tlb and hope for the best...
+ * consider this a FIXME
+ *
+ * Really we should be clearing out one or more page
+ * table entries for these virtual addresses so that
+ * future references cause a page fault... for now, we
+ * rely on two things:
+ * i) this code never gets called on known boards
+ * ii) invalid accesses to the freed areas aren't made
+ */
+ flush_tlb_all();
+ return;
+ }
+
+ return vfree((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+/**
+ * OK, this one's a bit tricky... ioremap can get called before memory is
+ * initialized (early serial console does this) and will want to alloc a page
+ * for its mapping. No userspace pages will ever get allocated before memory
+ * is initialized so this applies only to kernel pages. In the event that
+ * this is called before memory is initialized we allocate the page using
+ * the memblock infrastructure.
+ */
+
+pte_t __init_refok *pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address)
+{
+ pte_t *pte;
+
+ if (likely(mem_init_done)) {
+ pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT);
+ } else {
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+#if 0
+ /* FIXME: use memblock... */
+ pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
+#endif
+ }
+
+ if (pte)
+ clear_page(pte);
+ return pte;
+}
diff --git a/arch/openrisc/mm/tlb.c b/arch/openrisc/mm/tlb.c
new file mode 100644
index 000000000000..56b0b89624af
--- /dev/null
+++ b/arch/openrisc/mm/tlb.c
@@ -0,0 +1,193 @@
+/*
+ * OpenRISC tlb.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Julius Baxter <julius.baxter@orsoc.se>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/spr_defs.h>
+
+#define NO_CONTEXT -1
+
+#define NUM_DTLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \
+ SPR_DMMUCFGR_NTS_OFF))
+#define NUM_ITLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \
+ SPR_IMMUCFGR_NTS_OFF))
+#define DTLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_DTLB_SETS-1))
+#define ITLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_ITLB_SETS-1))
+/*
+ * Invalidate all TLB entries.
+ *
+ * This comes down to setting the 'valid' bit for all xTLBMR registers to 0.
+ * Easiest way to accomplish this is to just zero out the xTLBMR register
+ * completely.
+ *
+ */
+
+void flush_tlb_all(void)
+{
+ int i;
+ unsigned long num_tlb_sets;
+
+ /* Determine number of sets for IMMU. */
+ /* FIXME: Assumption is I & D nsets equal. */
+ num_tlb_sets = NUM_ITLB_SETS;
+
+ for (i = 0; i < num_tlb_sets; i++) {
+ mtspr_off(SPR_DTLBMR_BASE(0), i, 0);
+ mtspr_off(SPR_ITLBMR_BASE(0), i, 0);
+ }
+}
+
+#define have_dtlbeir (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_TEIRI)
+#define have_itlbeir (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_TEIRI)
+
+/*
+ * Invalidate a single page. This is what the xTLBEIR register is for.
+ *
+ * There's no point in checking the vma for PAGE_EXEC to determine whether it's
+ * the data or instruction TLB that should be flushed... that would take more
+ * than the few instructions that the following compiles down to!
+ *
+ * The case where we don't have the xTLBEIR register really only works for
+ * MMU's with a single way and is hard-coded that way.
+ */
+
+#define flush_dtlb_page_eir(addr) mtspr(SPR_DTLBEIR, addr)
+#define flush_dtlb_page_no_eir(addr) \
+ mtspr_off(SPR_DTLBMR_BASE(0), DTLB_OFFSET(addr), 0);
+
+#define flush_itlb_page_eir(addr) mtspr(SPR_ITLBEIR, addr)
+#define flush_itlb_page_no_eir(addr) \
+ mtspr_off(SPR_ITLBMR_BASE(0), ITLB_OFFSET(addr), 0);
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+ if (have_dtlbeir)
+ flush_dtlb_page_eir(addr);
+ else
+ flush_dtlb_page_no_eir(addr);
+
+ if (have_itlbeir)
+ flush_itlb_page_eir(addr);
+ else
+ flush_itlb_page_no_eir(addr);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ int addr;
+ bool dtlbeir;
+ bool itlbeir;
+
+ dtlbeir = have_dtlbeir;
+ itlbeir = have_itlbeir;
+
+ for (addr = start; addr < end; addr += PAGE_SIZE) {
+ if (dtlbeir)
+ flush_dtlb_page_eir(addr);
+ else
+ flush_dtlb_page_no_eir(addr);
+
+ if (itlbeir)
+ flush_itlb_page_eir(addr);
+ else
+ flush_itlb_page_no_eir(addr);
+ }
+}
+
+/*
+ * Invalidate the selected mm context only.
+ *
+ * FIXME: Due to some bug here, we're flushing everything for now.
+ * This should be changed to loop over over mm and call flush_tlb_range.
+ */
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+
+ /* Was seeing bugs with the mm struct passed to us. Scrapped most of
+ this function. */
+ /* Several architctures do this */
+ flush_tlb_all();
+}
+
+/* called in schedule() just before actually doing the switch_to */
+
+void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *next_tsk)
+{
+ /* remember the pgd for the fault handlers
+ * this is similar to the pgd register in some other CPU's.
+ * we need our own copy of it because current and active_mm
+ * might be invalid at points where we still need to derefer
+ * the pgd.
+ */
+ current_pgd = next->pgd;
+
+ /* We don't have context support implemented, so flush all
+ * entries belonging to previous map
+ */
+
+ if (prev != next)
+ flush_tlb_mm(prev);
+
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+ mm->context = NO_CONTEXT;
+ return 0;
+}
+
+/* called by __exit_mm to destroy the used MMU context if any before
+ * destroying the mm itself. this is only called when the last user of the mm
+ * drops it.
+ */
+
+void destroy_context(struct mm_struct *mm)
+{
+ flush_tlb_mm(mm);
+
+}
+
+/* called once during VM initialization, from init.c */
+
+void __init tlb_init(void)
+{
+ /* Do nothing... */
+ /* invalidate the entire TLB */
+ /* flush_tlb_all(); */
+}
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index f81955934aeb..b1dc71f5534e 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -197,15 +197,15 @@ static __inline__ int atomic_read(const atomic_t *v)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -217,10 +217,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#define atomic_add(i,v) ((void)(__atomic_add_return( (i),(v))))
#define atomic_sub(i,v) ((void)(__atomic_add_return(-(i),(v))))
@@ -317,7 +316,7 @@ atomic64_read(const atomic64_t *v)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
{
@@ -336,12 +335,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
-#else /* CONFIG_64BIT */
-
-#include <asm-generic/atomic64.h>
-
#endif /* !CONFIG_64BIT */
-#include <asm-generic/atomic-long.h>
#endif /* _ASM_PARISC_ATOMIC_H_ */
diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h
index 43c516fa17ff..8c9b631d2a78 100644
--- a/arch/parisc/include/asm/bitops.h
+++ b/arch/parisc/include/asm/bitops.h
@@ -8,7 +8,7 @@
#include <linux/compiler.h>
#include <asm/types.h> /* for BITS_PER_LONG/SHIFT_PER_LONG */
#include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/*
* HP-PARISC specific bit operations
@@ -223,14 +223,7 @@ static __inline__ int fls(int x)
#ifdef __KERNEL__
#include <asm-generic/bitops/le.h>
-
-/* '3' is bits per byte */
-#define LE_BYTE_ADDR ((sizeof(unsigned long) - 1) << 3)
-
-#define ext2_set_bit_atomic(l,nr,addr) \
- test_and_set_bit((nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
-#define ext2_clear_bit_atomic(l,nr,addr) \
- test_and_clear_bit( (nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* __KERNEL__ */
diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h
index 4ef73b09b168..890531e32fe8 100644
--- a/arch/parisc/include/asm/dma-mapping.h
+++ b/arch/parisc/include/asm/dma-mapping.h
@@ -210,7 +210,7 @@ parisc_walk_tree(struct device *dev)
return dev->platform_data;
}
-#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu);
+#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu)
#ifdef CONFIG_IOMMU_CCIO
diff --git a/arch/parisc/include/asm/mmu_context.h b/arch/parisc/include/asm/mmu_context.h
index 354b2aca990e..59be25764433 100644
--- a/arch/parisc/include/asm/mmu_context.h
+++ b/arch/parisc/include/asm/mmu_context.h
@@ -3,7 +3,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm-generic/mm_hooks.h>
diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h
index 7f09533da771..250ae35aa062 100644
--- a/arch/parisc/include/asm/ptrace.h
+++ b/arch/parisc/include/asm/ptrace.h
@@ -56,7 +56,6 @@ struct pt_regs {
#define instruction_pointer(regs) ((regs)->iaoq[0] & ~3)
#define user_stack_pointer(regs) ((regs)->gr[30])
unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
#endif /* __KERNEL__ */
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index cedbbb8b18d9..5e34ccf39a49 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -540,18 +540,6 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
return (Elf_Addr)stub;
}
-int apply_relocate(Elf_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- /* parisc should not need this ... */
- printk(KERN_ERR "module %s: RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
-
#ifndef CONFIG_64BIT
int apply_relocate_add(Elf_Shdr *sechdrs,
const char *strtab,
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index df653663d3db..a7bb757a5497 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -31,7 +31,7 @@
#include <linux/string.h>
EXPORT_SYMBOL(memset);
-#include <asm/atomic.h>
+#include <linux/atomic.h>
EXPORT_SYMBOL(__xchg8);
EXPORT_SYMBOL(__xchg32);
EXPORT_SYMBOL(__cmpxchg_u32);
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 828305f19cff..32d588488f04 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -33,7 +33,7 @@
#include <linux/ftrace.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/current.h>
#include <asm/delay.h>
#include <asm/tlbflush.h>
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 8b58bf0b7d5a..f19e6604026a 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -33,7 +33,7 @@
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/unaligned.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
#include <asm/pdc.h>
#include <asm/pdc_chassis.h>
diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c
index 353963d42059..a8bffd8af77d 100644
--- a/arch/parisc/lib/bitops.c
+++ b/arch/parisc/lib/bitops.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#ifdef CONFIG_SMP
arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c
index 27a7492ddb0d..04e550e76ae8 100644
--- a/arch/parisc/math-emu/decode_exc.c
+++ b/arch/parisc/math-emu/decode_exc.c
@@ -56,7 +56,7 @@
/* General definitions */
#define DOESTRAP 1
#define NOTRAP 0
-#define SIGNALCODE(signal, code) ((signal) << 24 | (code));
+#define SIGNALCODE(signal, code) ((signal) << 24 | (code))
#define copropbit 1<<31-2 /* bit position 2 */
#define opclass 9 /* bits 21 & 22 */
#define fmt 11 /* bits 19 & 20 */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2729c6663d8a..374c475e56a3 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -134,6 +134,8 @@ config PPC
select GENERIC_IRQ_SHOW_LEVEL
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_SYSCALL_TRACEPOINTS
+ select HAVE_BPF_JIT if (PPC64 && NET)
+ select HAVE_ARCH_JUMP_LABEL
config EARLY_PRINTK
bool
@@ -841,7 +843,7 @@ config LOWMEM_CAM_NUM
config RELOCATABLE
bool "Build a relocatable kernel (EXPERIMENTAL)"
- depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
+ depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && (FSL_BOOKE || PPC_47x)
help
This builds a kernel image that is capable of running at the
location the kernel is loaded at (some alignment restrictions may
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index e72dcf6a421d..067cb8480747 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -167,6 +167,13 @@ config PPC_EARLY_DEBUG_LPAR
Select this to enable early debugging for a machine with a HVC
console on vterm 0.
+config PPC_EARLY_DEBUG_LPAR_HVSI
+ bool "LPAR HVSI Console"
+ depends on PPC_PSERIES
+ help
+ Select this to enable early debugging for a machine with a HVSI
+ console on a specified vterm.
+
config PPC_EARLY_DEBUG_G5
bool "Apple G5"
depends on PPC_PMAC64
@@ -253,6 +260,14 @@ config PPC_EARLY_DEBUG_WSP
endchoice
+config PPC_EARLY_DEBUG_HVSI_VTERMNO
+ hex "vterm number to use with early debug HVSI"
+ depends on PPC_EARLY_DEBUG_LPAR_HVSI
+ default "0x30000000"
+ help
+ You probably want 0x30000000 for your first serial port and
+ 0x30000001 for your second one
+
config PPC_EARLY_DEBUG_44x_PHYSLOW
hex "Low 32 bits of early debug UART physical address"
depends on PPC_EARLY_DEBUG_44x
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index b7212b619c52..57af16edc192 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -67,7 +67,7 @@ LDFLAGS_vmlinux-yy := -Bstatic
LDFLAGS_vmlinux-$(CONFIG_PPC64)$(CONFIG_RELOCATABLE) := -pie
LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-yy)
-CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
+CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=no -mcall-aixdesc
CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
KBUILD_CPPFLAGS += -Iarch/$(ARCH)
KBUILD_AFLAGS += -Iarch/$(ARCH)
@@ -154,7 +154,8 @@ core-y += arch/powerpc/kernel/ \
arch/powerpc/lib/ \
arch/powerpc/sysdev/ \
arch/powerpc/platforms/ \
- arch/powerpc/math-emu/
+ arch/powerpc/math-emu/ \
+ arch/powerpc/net/
core-$(CONFIG_XMON) += arch/powerpc/xmon/
core-$(CONFIG_KVM) += arch/powerpc/kvm/
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index 22dd6ae84da0..3dc75deafbb3 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -143,6 +143,11 @@
interrupts = <0x1d 0x4>;
};
+ HWRNG: hwrng@110000 {
+ compatible = "amcc,ppc460ex-rng", "ppc4xx-rng";
+ reg = <4 0x00110000 0x50>;
+ };
+
MAL0: mcmal {
compatible = "ibm,mcmal-460ex", "ibm,mcmal2";
dcr-reg = <0x180 0x062>;
diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts
index e618fc4cbc9e..2000060386d7 100644
--- a/arch/powerpc/boot/dts/glacier.dts
+++ b/arch/powerpc/boot/dts/glacier.dts
@@ -130,12 +130,18 @@
};
CRYPTO: crypto@180000 {
- compatible = "amcc,ppc460gt-crypto", "amcc,ppc4xx-crypto";
+ compatible = "amcc,ppc460gt-crypto", "amcc,ppc460ex-crypto",
+ "amcc,ppc4xx-crypto";
reg = <4 0x00180000 0x80400>;
interrupt-parent = <&UIC0>;
interrupts = <0x1d 0x4>;
};
+ HWRNG: hwrng@110000 {
+ compatible = "amcc,ppc460ex-rng", "ppc4xx-rng";
+ reg = <4 0x00110000 0x50>;
+ };
+
MAL0: mcmal {
compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
dcr-reg = <0x180 0x062>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 30cf0e098bb9..647daf8e7291 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -60,6 +60,8 @@
compatible = "fsl,mpc8568-localbus", "fsl,pq3-localbus",
"simple-bus";
reg = <0xe0005000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
ranges = <0x0 0x0 0xfe000000 0x02000000
0x1 0x0 0xf8000000 0x00008000
diff --git a/arch/powerpc/boot/dts/p1010rdb.dts b/arch/powerpc/boot/dts/p1010rdb.dts
new file mode 100644
index 000000000000..6b33b73a5ba0
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1010rdb.dts
@@ -0,0 +1,280 @@
+/*
+ * P1010 RDB Device Tree Source
+ *
+ * Copyright 2011 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/include/ "p1010si.dtsi"
+
+/ {
+ model = "fsl,P1010RDB";
+ compatible = "fsl,P1010RDB";
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ };
+
+ memory {
+ device_type = "memory";
+ };
+
+ ifc@ffe1e000 {
+ /* NOR, NAND Flashes and CPLD on board */
+ ranges = <0x0 0x0 0x0 0xee000000 0x02000000
+ 0x1 0x0 0x0 0xff800000 0x00010000
+ 0x3 0x0 0x0 0xffb00000 0x00000020>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x2000000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ partition@40000 {
+ /* 256KB for DTB Image */
+ reg = <0x00040000 0x00040000>;
+ label = "NOR DTB Image";
+ };
+
+ partition@80000 {
+ /* 7 MB for Linux Kernel Image */
+ reg = <0x00080000 0x00700000>;
+ label = "NOR Linux Kernel Image";
+ };
+
+ partition@800000 {
+ /* 20MB for JFFS2 based Root file System */
+ reg = <0x00800000 0x01400000>;
+ label = "NOR JFFS2 Root File System";
+ };
+
+ partition@1f00000 {
+ /* This location must not be altered */
+ /* 512KB for u-boot Bootloader Image */
+ /* 512KB for u-boot Environment Variables */
+ reg = <0x01f00000 0x00100000>;
+ label = "NOR U-Boot Image";
+ read-only;
+ };
+ };
+
+ nand@1,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc-nand";
+ reg = <0x1 0x0 0x10000>;
+
+ partition@0 {
+ /* This location must not be altered */
+ /* 1MB for u-boot Bootloader Image */
+ reg = <0x0 0x00100000>;
+ label = "NAND U-Boot Image";
+ read-only;
+ };
+
+ partition@100000 {
+ /* 1MB for DTB Image */
+ reg = <0x00100000 0x00100000>;
+ label = "NAND DTB Image";
+ };
+
+ partition@200000 {
+ /* 4MB for Linux Kernel Image */
+ reg = <0x00200000 0x00400000>;
+ label = "NAND Linux Kernel Image";
+ };
+
+ partition@600000 {
+ /* 4MB for Compressed Root file System Image */
+ reg = <0x00600000 0x00400000>;
+ label = "NAND Compressed RFS Image";
+ };
+
+ partition@a00000 {
+ /* 15MB for JFFS2 based Root file System */
+ reg = <0x00a00000 0x00f00000>;
+ label = "NAND JFFS2 Root File System";
+ };
+
+ partition@1900000 {
+ /* 7MB for User Area */
+ reg = <0x01900000 0x00700000>;
+ label = "NAND User area";
+ };
+ };
+
+ cpld@3,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p1010rdb-cpld";
+ reg = <0x3 0x0 0x0000020>;
+ bank-width = <1>;
+ device-width = <1>;
+ };
+ };
+
+ soc@ffe00000 {
+ spi@7000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+
+ partition@0 {
+ /* 1MB for u-boot Bootloader Image */
+ /* 1MB for Environment */
+ reg = <0x0 0x00100000>;
+ label = "SPI Flash U-Boot Image";
+ read-only;
+ };
+
+ partition@100000 {
+ /* 512KB for DTB Image */
+ reg = <0x00100000 0x00080000>;
+ label = "SPI Flash DTB Image";
+ };
+
+ partition@180000 {
+ /* 4MB for Linux Kernel Image */
+ reg = <0x00180000 0x00400000>;
+ label = "SPI Flash Linux Kernel Image";
+ };
+
+ partition@580000 {
+ /* 4MB for Compressed RFS Image */
+ reg = <0x00580000 0x00400000>;
+ label = "SPI Flash Compressed RFSImage";
+ };
+
+ partition@980000 {
+ /* 6.5MB for JFFS2 based RFS */
+ reg = <0x00980000 0x00680000>;
+ label = "SPI Flash JFFS2 RFS";
+ };
+ };
+ };
+
+ can0@1c000 {
+ fsl,flexcan-clock-source = "platform";
+ };
+
+ can1@1d000 {
+ fsl,flexcan-clock-source = "platform";
+ };
+
+ usb@22000 {
+ phy_type = "utmi";
+ };
+
+ mdio@24000 {
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <3 1>;
+ reg = <0x1>;
+ };
+
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+ reg = <0x0>;
+ };
+
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+ reg = <0x2>;
+ };
+ };
+
+ enet0: ethernet@b0000 {
+ phy-handle = <&phy0>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ enet1: ethernet@b1000 {
+ phy-handle = <&phy1>;
+ tbi-handle = <&tbi0>;
+ phy-connection-type = "sgmii";
+ };
+
+ enet2: ethernet@b2000 {
+ phy-handle = <&phy2>;
+ tbi-handle = <&tbi1>;
+ phy-connection-type = "sgmii";
+ };
+ };
+
+ pci0: pcie@ffe09000 {
+ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
+ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
+ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
+ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ >;
+
+ ranges = <0x2000000 0x0 0xa0000000
+ 0x2000000 0x0 0xa0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@ffe0a000 {
+ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
+ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
+ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
+ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ >;
+ ranges = <0x2000000 0x0 0x80000000
+ 0x2000000 0x0 0x80000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p1010si.dtsi b/arch/powerpc/boot/dts/p1010si.dtsi
new file mode 100644
index 000000000000..7f51104f2e36
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1010si.dtsi
@@ -0,0 +1,376 @@
+/*
+ * P1010si Device Tree Source
+ *
+ * Copyright 2011 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+/ {
+ compatible = "fsl,P1010";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,P1010@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ ifc@ffe1e000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc", "simple-bus";
+ reg = <0x0 0xffe1e000 0 0x2000>;
+ interrupts = <16 2 19 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ soc@ffe00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,p1010-immr", "simple-bus";
+ ranges = <0x0 0x0 0xffe00000 0x100000>;
+ bus-frequency = <0>; // Filled out by uboot.
+
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <12>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,p1010-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <16 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ memory-controller@2000 {
+ compatible = "fsl,p1010-memory-controller";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ serial0: serial@4500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ serial1: serial@4600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ spi@7000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc8536-espi";
+ reg = <0x7000 0x1000>;
+ interrupts = <59 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,espi-num-chipselects = <1>;
+ };
+
+ gpio: gpio-controller@f000 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8572-gpio";
+ reg = <0xf000 0x100>;
+ interrupts = <47 0x2>;
+ interrupt-parent = <&mpic>;
+ gpio-controller;
+ };
+
+ sata@18000 {
+ compatible = "fsl,pq-sata-v2";
+ reg = <0x18000 0x1000>;
+ cell-index = <1>;
+ interrupts = <74 0x2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ sata@19000 {
+ compatible = "fsl,pq-sata-v2";
+ reg = <0x19000 0x1000>;
+ cell-index = <2>;
+ interrupts = <41 0x2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ can0@1c000 {
+ compatible = "fsl,flexcan-v1.0";
+ reg = <0x1c000 0x1000>;
+ interrupts = <48 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,flexcan-clock-divider = <2>;
+ };
+
+ can1@1d000 {
+ compatible = "fsl,flexcan-v1.0";
+ reg = <0x1d000 0x1000>;
+ interrupts = <61 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,flexcan-clock-divider = <2>;
+ };
+
+ L2: l2-cache-controller@20000 {
+ compatible = "fsl,p1010-l2-cache-controller",
+ "fsl,p1014-l2-cache-controller";
+ reg = <0x20000 0x1000>;
+ cache-line-size = <32>; // 32 bytes
+ cache-size = <0x40000>; // L2,256K
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ dma@21300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p1010-dma", "fsl,eloplus-dma";
+ reg = <0x21300 0x4>;
+ ranges = <0x0 0x21100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <20 2>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupt-parent = <&mpic>;
+ interrupts = <21 2>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupt-parent = <&mpic>;
+ interrupts = <22 2>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupt-parent = <&mpic>;
+ interrupts = <23 2>;
+ };
+ };
+
+ usb@22000 {
+ compatible = "fsl-usb2-dr";
+ reg = <0x22000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <28 0x2>;
+ dr_mode = "host";
+ };
+
+ mdio@24000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,etsec2-mdio";
+ reg = <0x24000 0x1000 0xb0030 0x4>;
+ };
+
+ mdio@25000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,etsec2-tbi";
+ reg = <0x25000 0x1000 0xb1030 0x4>;
+ tbi0: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ mdio@26000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,etsec2-tbi";
+ reg = <0x26000 0x1000 0xb1030 0x4>;
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ sdhci@2e000 {
+ compatible = "fsl,esdhc";
+ reg = <0x2e000 0x1000>;
+ interrupts = <72 0x8>;
+ interrupt-parent = <&mpic>;
+ /* Filled in by U-Boot */
+ clock-frequency = <0>;
+ fsl,sdhci-auto-cmd12;
+ };
+
+ enet0: ethernet@b0000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "fsl,etsec2";
+ fsl,num_rx_queues = <0x8>;
+ fsl,num_tx_queues = <0x8>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupt-parent = <&mpic>;
+
+ queue-group@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb0000 0x1000>;
+ fsl,rx-bit-map = <0xff>;
+ fsl,tx-bit-map = <0xff>;
+ interrupts = <29 2 30 2 34 2>;
+ };
+
+ };
+
+ enet1: ethernet@b1000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "fsl,etsec2";
+ fsl,num_rx_queues = <0x8>;
+ fsl,num_tx_queues = <0x8>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupt-parent = <&mpic>;
+
+ queue-group@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb1000 0x1000>;
+ fsl,rx-bit-map = <0xff>;
+ fsl,tx-bit-map = <0xff>;
+ interrupts = <35 2 36 2 40 2>;
+ };
+
+ };
+
+ enet2: ethernet@b2000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "fsl,etsec2";
+ fsl,num_rx_queues = <0x8>;
+ fsl,num_tx_queues = <0x8>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupt-parent = <&mpic>;
+
+ queue-group@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb2000 0x1000>;
+ fsl,rx-bit-map = <0xff>;
+ fsl,tx-bit-map = <0xff>;
+ interrupts = <31 2 32 2 33 2>;
+ };
+
+ };
+
+ mpic: pic@40000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi@41600 {
+ compatible = "fsl,p1010-msi", "fsl,mpic-msi";
+ reg = <0x41600 0x80>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0
+ 0xe1 0
+ 0xe2 0
+ 0xe3 0
+ 0xe4 0
+ 0xe5 0
+ 0xe6 0
+ 0xe7 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities@e0000 { //global utilities block
+ compatible = "fsl,p1010-guts";
+ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+ };
+
+ pci0: pcie@ffe09000 {
+ compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0 0xffe09000 0 0x1000>;
+ bus-range = <0 255>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ pci1: pcie@ffe0a000 {
+ compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0 0xffe0a000 0 0x1000>;
+ bus-range = <0 255>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+};
diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts
index 98d9426d4b85..1be9743ab5e0 100644
--- a/arch/powerpc/boot/dts/p1022ds.dts
+++ b/arch/powerpc/boot/dts/p1022ds.dts
@@ -412,7 +412,6 @@
fsl,magic-packet;
fsl,wake-on-filer;
local-mac-address = [ 00 00 00 00 00 00 ];
- fixed-link = <1 1 1000 0 0>;
phy-handle = <&phy0>;
phy-connection-type = "rgmii-id";
queue-group@0{
@@ -439,7 +438,6 @@
fsl,num_rx_queues = <0x8>;
fsl,num_tx_queues = <0x8>;
local-mac-address = [ 00 00 00 00 00 00 ];
- fixed-link = <1 1 1000 0 0>;
phy-handle = <&phy1>;
phy-connection-type = "rgmii-id";
queue-group@0{
diff --git a/arch/powerpc/boot/dts/p1023rds.dts b/arch/powerpc/boot/dts/p1023rds.dts
new file mode 100644
index 000000000000..bfa96aa8f2ca
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1023rds.dts
@@ -0,0 +1,546 @@
+/*
+ * P1023 RDS Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "fsl,P1023";
+ compatible = "fsl,P1023RDS";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,P1023@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu1: PowerPC,P1023@1 {
+ device_type = "cpu";
+ reg = <0x1>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ };
+
+ soc@ff600000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,p1023-immr", "simple-bus";
+ ranges = <0x0 0x0 0xff600000 0x200000>;
+ bus-frequency = <0>; // Filled out by uboot.
+
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <12>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,p1023-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <16 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ memory-controller@2000 {
+ compatible = "fsl,p1023-memory-controller";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ rtc@68 {
+ compatible = "dallas,ds1374";
+ reg = <0x68>;
+ };
+ };
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ serial0: serial@4500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ serial1: serial@4600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ spi@7000 {
+ cell-index = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p1023-espi", "fsl,mpc8536-espi";
+ reg = <0x7000 0x1000>;
+ interrupts = <59 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,espi-num-chipselects = <4>;
+
+ fsl_dataflash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at45db081d";
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ partition@u-boot {
+ /* 512KB for u-boot Bootloader Image */
+ label = "u-boot-spi";
+ reg = <0x00000000 0x00080000>;
+ read-only;
+ };
+ partition@dtb {
+ /* 512KB for DTB Image */
+ label = "dtb-spi";
+ reg = <0x00080000 0x00080000>;
+ read-only;
+ };
+ };
+ };
+
+ gpio: gpio-controller@f000 {
+ #gpio-cells = <2>;
+ compatible = "fsl,qoriq-gpio";
+ reg = <0xf000 0x100>;
+ interrupts = <47 0x2>;
+ interrupt-parent = <&mpic>;
+ gpio-controller;
+ };
+
+ L2: l2-cache-controller@20000 {
+ compatible = "fsl,p1023-l2-cache-controller";
+ reg = <0x20000 0x1000>;
+ cache-line-size = <32>; // 32 bytes
+ cache-size = <0x40000>; // L2,256K
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ dma@21300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,eloplus-dma";
+ reg = <0x21300 0x4>;
+ ranges = <0x0 0x21100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <20 2>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupt-parent = <&mpic>;
+ interrupts = <21 2>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupt-parent = <&mpic>;
+ interrupts = <22 2>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupt-parent = <&mpic>;
+ interrupts = <23 2>;
+ };
+ };
+
+ usb@22000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl-usb2-dr";
+ reg = <0x22000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <28 0x2>;
+ dr_mode = "host";
+ phy_type = "ulpi";
+ };
+
+ crypto: crypto@300000 {
+ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x30000 0x10000>;
+ ranges = <0 0x30000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <58 2>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <45 2>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <45 2>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <57 2>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupts = <57 2>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,sec-v4.2-rtic",
+ "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ power@e0070{
+ compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc",
+ "fsl,p1022-pmc";
+ reg = <0xe0070 0x20>;
+ etsec1_clk: soc-clk@B0{
+ fsl,pmcdr-mask = <0x00000080>;
+ };
+ etsec2_clk: soc-clk@B1{
+ fsl,pmcdr-mask = <0x00000040>;
+ };
+ etsec3_clk: soc-clk@B2{
+ fsl,pmcdr-mask = <0x00000020>;
+ };
+ };
+
+ mpic: pic@40000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi@41600 {
+ compatible = "fsl,p1023-msi", "fsl,mpic-msi";
+ reg = <0x41600 0x80>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0
+ 0xe1 0
+ 0xe2 0
+ 0xe3 0
+ 0xe4 0
+ 0xe5 0
+ 0xe6 0
+ 0xe7 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities@e0000 { //global utilities block
+ compatible = "fsl,p1023-guts";
+ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+ };
+
+ localbus@ff605000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,p1023-elbc", "fsl,elbc", "simple-bus";
+ reg = <0 0xff605000 0 0x1000>;
+ interrupts = <19 2>;
+ interrupt-parent = <&mpic>;
+
+ /* NOR Flash, BCSR */
+ ranges = <0x0 0x0 0x0 0xee000000 0x02000000
+ 0x1 0x0 0x0 0xe0000000 0x00008000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x02000000>;
+ bank-width = <1>;
+ device-width = <1>;
+ partition@0 {
+ label = "ramdisk";
+ reg = <0x00000000 0x01c00000>;
+ };
+ partition@1c00000 {
+ label = "kernel";
+ reg = <0x01c00000 0x002e0000>;
+ };
+ partiton@1ee0000 {
+ label = "dtb";
+ reg = <0x01ee0000 0x00020000>;
+ };
+ partition@1f00000 {
+ label = "firmware";
+ reg = <0x01f00000 0x00080000>;
+ read-only;
+ };
+ partition@1f80000 {
+ label = "u-boot";
+ reg = <0x01f80000 0x00080000>;
+ read-only;
+ };
+ };
+
+ fpga@1,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p1023rds-fpga";
+ reg = <1 0 0x8000>;
+ ranges = <0 1 0 0x8000>;
+
+ bcsr@20 {
+ compatible = "fsl,p1023rds-bcsr";
+ reg = <0x20 0x20>;
+ };
+ };
+ };
+
+ pci0: pcie@ff60a000 {
+ compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2";
+ cell-index = <1>;
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0 0xff60a000 0 0x1000>;
+ bus-range = <0 255>;
+ ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 0 1
+ 0000 0 0 2 &mpic 1 1
+ 0000 0 0 3 &mpic 2 1
+ 0000 0 0 4 &mpic 3 1
+ >;
+ ranges = <0x2000000 0x0 0xc0000000
+ 0x2000000 0x0 0xc0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@ff609000 {
+ compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2";
+ cell-index = <2>;
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0 0xff609000 0 0x1000>;
+ bus-range = <0 255>;
+ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 4 1
+ 0000 0 0 2 &mpic 5 1
+ 0000 0 0 3 &mpic 6 1
+ 0000 0 0 4 &mpic 7 1
+ >;
+ ranges = <0x2000000 0x0 0xa0000000
+ 0x2000000 0x0 0xa0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci2: pcie@ff60b000 {
+ cell-index = <3>;
+ compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0 0xff60b000 0 0x1000>;
+ bus-range = <0 255>;
+ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 8 1
+ 0000 0 0 2 &mpic 9 1
+ 0000 0 0 3 &mpic 10 1
+ 0000 0 0 4 &mpic 11 1
+ >;
+ ranges = <0x2000000 0x0 0x80000000
+ 0x2000000 0x0 0x80000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p2040rdb.dts b/arch/powerpc/boot/dts/p2040rdb.dts
new file mode 100644
index 000000000000..7d84e391c632
--- /dev/null
+++ b/arch/powerpc/boot/dts/p2040rdb.dts
@@ -0,0 +1,166 @@
+/*
+ * P2040RDB Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "p2040si.dtsi"
+
+/ {
+ model = "fsl,P2040RDB";
+ compatible = "fsl,P2040RDB";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ memory {
+ device_type = "memory";
+ };
+
+ soc: soc@ffe000000 {
+ spi@110000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ partition@u-boot {
+ label = "u-boot";
+ reg = <0x00000000 0x00100000>;
+ read-only;
+ };
+ partition@kernel {
+ label = "kernel";
+ reg = <0x00100000 0x00500000>;
+ read-only;
+ };
+ partition@dtb {
+ label = "dtb";
+ reg = <0x00600000 0x00100000>;
+ read-only;
+ };
+ partition@fs {
+ label = "file system";
+ reg = <0x00700000 0x00900000>;
+ };
+ };
+ };
+
+ i2c@118000 {
+ lm75b@48 {
+ compatible = "nxp,lm75a";
+ reg = <0x48>;
+ };
+ eeprom@50 {
+ compatible = "at24,24c256";
+ reg = <0x50>;
+ };
+ rtc@68 {
+ compatible = "pericom,pt7c4338";
+ reg = <0x68>;
+ };
+ };
+
+ i2c@118100 {
+ eeprom@50 {
+ compatible = "at24,24c256";
+ reg = <0x50>;
+ };
+ };
+
+ usb0: usb@210000 {
+ phy_type = "utmi";
+ };
+
+ usb1: usb@211000 {
+ dr_mode = "host";
+ phy_type = "utmi";
+ };
+ };
+
+ localbus@ffe124000 {
+ reg = <0xf 0xfe124000 0 0x1000>;
+ ranges = <0 0 0xf 0xe8000000 0x08000000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x08000000>;
+ bank-width = <2>;
+ device-width = <2>;
+ };
+ };
+
+ pci0: pcie@ffe200000 {
+ reg = <0xf 0xfe200000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ reg = <0xf 0xfe201000 0 0x1000>;
+ ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+ 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie@ffe202000 {
+ reg = <0xf 0xfe202000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p2040si.dtsi b/arch/powerpc/boot/dts/p2040si.dtsi
new file mode 100644
index 000000000000..5fdbb24c0763
--- /dev/null
+++ b/arch/powerpc/boot/dts/p2040si.dtsi
@@ -0,0 +1,623 @@
+/*
+ * P2040 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "fsl,P2040";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e500mc@0 {
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e500mc@1 {
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu2: PowerPC,e500mc@2 {
+ device_type = "cpu";
+ reg = <2>;
+ next-level-cache = <&L2_2>;
+ L2_2: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu3: PowerPC,e500mc@3 {
+ device_type = "cpu";
+ reg = <3>;
+ next-level-cache = <&L2_3>;
+ L2_3: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+
+ soc: soc@ffe000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law@0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ memory-controller@8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ cpc: l3-cache-controller@10000 {
+ compatible = "fsl,p2040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000>;
+ interrupts = <16 2 1 27>;
+ };
+
+ corenet-cf@18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu@20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x4000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+ mpic: pic@40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <4>;
+ reg = <0x40000 0x40000>;
+ compatible = "fsl,mpic", "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi0: msi@41600 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41600 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0 0 0
+ 0xe1 0 0 0
+ 0xe2 0 0 0
+ 0xe3 0 0 0
+ 0xe4 0 0 0
+ 0xe5 0 0 0
+ 0xe6 0 0 0
+ 0xe7 0 0 0>;
+ };
+
+ msi1: msi@41800 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41800 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe8 0 0 0
+ 0xe9 0 0 0
+ 0xea 0 0 0
+ 0xeb 0 0 0
+ 0xec 0 0 0
+ 0xed 0 0 0
+ 0xee 0 0 0
+ 0xef 0 0 0>;
+ };
+
+ msi2: msi@41a00 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41a00 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xf0 0 0 0
+ 0xf1 0 0 0
+ 0xf2 0 0 0
+ 0xf3 0 0 0
+ 0xf4 0 0 0
+ 0xf5 0 0 0
+ 0xf6 0 0 0
+ 0xf7 0 0 0>;
+ };
+
+ guts: global-utilities@e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities@e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities@e1000 {
+ compatible = "fsl,p2040-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities@e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp@e8000 {
+ compatible = "fsl,p2040-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes@ea000 {
+ compatible = "fsl,p2040-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+ dma0: dma@100300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+ reg = <0x100300 0x4>;
+ ranges = <0x0 0x100100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <28 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <29 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <30 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <31 2 0 0>;
+ };
+ };
+
+ dma1: dma@101300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+ reg = <0x101300 0x4>;
+ ranges = <0x0 0x101100 0x200>;
+ cell-index = <1>;
+ dma-channel@0 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <32 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <33 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <34 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p2040-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <35 2 0 0>;
+ };
+ };
+
+ spi@110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p2040-espi", "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2 0 0>;
+ fsl,espi-num-chipselects = <4>;
+
+ };
+
+ sdhc: sdhc@114000 {
+ compatible = "fsl,p2040-esdhc", "fsl,esdhc";
+ reg = <0x114000 0x1000>;
+ interrupts = <48 2 0 0>;
+ sdhci,auto-cmd12;
+ clock-frequency = <0>;
+ };
+
+
+ i2c@118000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x118000 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@118100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x118100 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ compatible = "fsl-i2c";
+ reg = <0x119000 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <3>;
+ compatible = "fsl-i2c";
+ reg = <0x119100 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ serial0: serial@11c500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial1: serial@11c600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial2: serial@11d500 {
+ cell-index = <2>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ serial3: serial@11d600 {
+ cell-index = <3>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ gpio0: gpio@130000 {
+ compatible = "fsl,p2040-gpio", "fsl,qoriq-gpio";
+ reg = <0x130000 0x1000>;
+ interrupts = <55 2 0 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ usb0: usb@210000 {
+ compatible = "fsl,p2040-usb2-mph",
+ "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ reg = <0x210000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x2 0 0>;
+ port0;
+ };
+
+ usb1: usb@211000 {
+ compatible = "fsl,p2040-usb2-dr",
+ "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ reg = <0x211000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <45 0x2 0 0>;
+ };
+
+ sata@220000 {
+ compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+ reg = <0x220000 0x1000>;
+ interrupts = <68 0x2 0 0>;
+ };
+
+ sata@221000 {
+ compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+ reg = <0x221000 0x1000>;
+ interrupts = <69 0x2 0 0>;
+ };
+
+ crypto: crypto@300000 {
+ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupts = <92 2 0 0>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <88 2 0 0>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <89 2 0 0>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <90 2 0 0>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupts = <91 2 0 0>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,sec-v4.2-rtic",
+ "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupts = <93 2 0 0>;
+ };
+
+ };
+
+ localbus@ffe124000 {
+ compatible = "fsl,p2040-elbc", "fsl,elbc", "simple-bus";
+ interrupts = <25 2 0 0>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ pci0: pcie@ffe200000 {
+ compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi0>;
+ interrupts = <16 2 1 15>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi1>;
+ interrupts = <16 2 1 14>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+ };
+
+ pci2: pcie@ffe202000 {
+ compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 13>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p3041ds.dts b/arch/powerpc/boot/dts/p3041ds.dts
new file mode 100644
index 000000000000..69cae674f396
--- /dev/null
+++ b/arch/powerpc/boot/dts/p3041ds.dts
@@ -0,0 +1,214 @@
+/*
+ * P3041DS Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "p3041si.dtsi"
+
+/ {
+ model = "fsl,P3041DS";
+ compatible = "fsl,P3041DS";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ memory {
+ device_type = "memory";
+ };
+
+ soc: soc@ffe000000 {
+ spi@110000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ partition@u-boot {
+ label = "u-boot";
+ reg = <0x00000000 0x00100000>;
+ read-only;
+ };
+ partition@kernel {
+ label = "kernel";
+ reg = <0x00100000 0x00500000>;
+ read-only;
+ };
+ partition@dtb {
+ label = "dtb";
+ reg = <0x00600000 0x00100000>;
+ read-only;
+ };
+ partition@fs {
+ label = "file system";
+ reg = <0x00700000 0x00900000>;
+ };
+ };
+ };
+
+ i2c@118100 {
+ eeprom@51 {
+ compatible = "at24,24c256";
+ reg = <0x51>;
+ };
+ eeprom@52 {
+ compatible = "at24,24c256";
+ reg = <0x52>;
+ };
+ };
+
+ i2c@119100 {
+ rtc@68 {
+ compatible = "dallas,ds3232";
+ reg = <0x68>;
+ interrupts = <0x1 0x1 0 0>;
+ };
+ };
+ };
+
+ localbus@ffe124000 {
+ reg = <0xf 0xfe124000 0 0x1000>;
+ ranges = <0 0 0xf 0xe8000000 0x08000000
+ 2 0 0xf 0xffa00000 0x00040000
+ 3 0 0xf 0xffdf0000 0x00008000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x08000000>;
+ bank-width = <2>;
+ device-width = <2>;
+ };
+
+ nand@2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,elbc-fcm-nand";
+ reg = <0x2 0x0 0x40000>;
+
+ partition@0 {
+ label = "NAND U-Boot Image";
+ reg = <0x0 0x02000000>;
+ read-only;
+ };
+
+ partition@2000000 {
+ label = "NAND Root File System";
+ reg = <0x02000000 0x10000000>;
+ };
+
+ partition@12000000 {
+ label = "NAND Compressed RFS Image";
+ reg = <0x12000000 0x08000000>;
+ };
+
+ partition@1a000000 {
+ label = "NAND Linux Kernel Image";
+ reg = <0x1a000000 0x04000000>;
+ };
+
+ partition@1e000000 {
+ label = "NAND DTB Image";
+ reg = <0x1e000000 0x01000000>;
+ };
+
+ partition@1f000000 {
+ label = "NAND Writable User area";
+ reg = <0x1f000000 0x21000000>;
+ };
+ };
+
+ board-control@3,0 {
+ compatible = "fsl,p3041ds-pixis";
+ reg = <3 0 0x20>;
+ };
+ };
+
+ pci0: pcie@ffe200000 {
+ reg = <0xf 0xfe200000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ reg = <0xf 0xfe201000 0 0x1000>;
+ ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+ 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie@ffe202000 {
+ reg = <0xf 0xfe202000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci3: pcie@ffe203000 {
+ reg = <0xf 0xfe203000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p3041si.dtsi b/arch/powerpc/boot/dts/p3041si.dtsi
new file mode 100644
index 000000000000..8b695801f505
--- /dev/null
+++ b/arch/powerpc/boot/dts/p3041si.dtsi
@@ -0,0 +1,660 @@
+/*
+ * P3041 Silicon Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "fsl,P3041";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ pci3 = &pci3;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+/*
+ rio0 = &rapidio0;
+ */
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e500mc@0 {
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e500mc@1 {
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu2: PowerPC,e500mc@2 {
+ device_type = "cpu";
+ reg = <2>;
+ next-level-cache = <&L2_2>;
+ L2_2: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu3: PowerPC,e500mc@3 {
+ device_type = "cpu";
+ reg = <3>;
+ next-level-cache = <&L2_3>;
+ L2_3: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+
+ soc: soc@ffe000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law@0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ memory-controller@8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ cpc: l3-cache-controller@10000 {
+ compatible = "fsl,p3041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000>;
+ interrupts = <16 2 1 27>;
+ };
+
+ corenet-cf@18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu@20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x4000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+ mpic: pic@40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <4>;
+ reg = <0x40000 0x40000>;
+ compatible = "fsl,mpic", "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi0: msi@41600 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41600 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0 0 0
+ 0xe1 0 0 0
+ 0xe2 0 0 0
+ 0xe3 0 0 0
+ 0xe4 0 0 0
+ 0xe5 0 0 0
+ 0xe6 0 0 0
+ 0xe7 0 0 0>;
+ };
+
+ msi1: msi@41800 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41800 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe8 0 0 0
+ 0xe9 0 0 0
+ 0xea 0 0 0
+ 0xeb 0 0 0
+ 0xec 0 0 0
+ 0xed 0 0 0
+ 0xee 0 0 0
+ 0xef 0 0 0>;
+ };
+
+ msi2: msi@41a00 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41a00 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xf0 0 0 0
+ 0xf1 0 0 0
+ 0xf2 0 0 0
+ 0xf3 0 0 0
+ 0xf4 0 0 0
+ 0xf5 0 0 0
+ 0xf6 0 0 0
+ 0xf7 0 0 0>;
+ };
+
+ guts: global-utilities@e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities@e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities@e1000 {
+ compatible = "fsl,p3041-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities@e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp@e8000 {
+ compatible = "fsl,p3041-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes@ea000 {
+ compatible = "fsl,p3041-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+ dma0: dma@100300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
+ reg = <0x100300 0x4>;
+ ranges = <0x0 0x100100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <28 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <29 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <30 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <31 2 0 0>;
+ };
+ };
+
+ dma1: dma@101300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
+ reg = <0x101300 0x4>;
+ ranges = <0x0 0x101100 0x200>;
+ cell-index = <1>;
+ dma-channel@0 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <32 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <33 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <34 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <35 2 0 0>;
+ };
+ };
+
+ spi@110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p3041-espi", "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2 0 0>;
+ fsl,espi-num-chipselects = <4>;
+ };
+
+ sdhc: sdhc@114000 {
+ compatible = "fsl,p3041-esdhc", "fsl,esdhc";
+ reg = <0x114000 0x1000>;
+ interrupts = <48 2 0 0>;
+ sdhci,auto-cmd12;
+ clock-frequency = <0>;
+ };
+
+ i2c@118000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x118000 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@118100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x118100 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ compatible = "fsl-i2c";
+ reg = <0x119000 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <3>;
+ compatible = "fsl-i2c";
+ reg = <0x119100 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ serial0: serial@11c500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial1: serial@11c600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial2: serial@11d500 {
+ cell-index = <2>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ serial3: serial@11d600 {
+ cell-index = <3>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ gpio0: gpio@130000 {
+ compatible = "fsl,p3041-gpio", "fsl,qoriq-gpio";
+ reg = <0x130000 0x1000>;
+ interrupts = <55 2 0 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ usb0: usb@210000 {
+ compatible = "fsl,p3041-usb2-mph",
+ "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ reg = <0x210000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x2 0 0>;
+ phy_type = "utmi";
+ port0;
+ };
+
+ usb1: usb@211000 {
+ compatible = "fsl,p3041-usb2-dr",
+ "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ reg = <0x211000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <45 0x2 0 0>;
+ dr_mode = "host";
+ phy_type = "utmi";
+ };
+
+ sata@220000 {
+ compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
+ reg = <0x220000 0x1000>;
+ interrupts = <68 0x2 0 0>;
+ };
+
+ sata@221000 {
+ compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
+ reg = <0x221000 0x1000>;
+ interrupts = <69 0x2 0 0>;
+ };
+
+ crypto: crypto@300000 {
+ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupts = <92 2 0 0>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <88 2 0 0>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <89 2 0 0>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <90 2 0 0>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupts = <91 2 0 0>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,sec-v4.2-rtic",
+ "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupts = <93 2 0 0>;
+ };
+ };
+
+/*
+ rapidio0: rapidio@ffe0c0000
+*/
+
+ localbus@ffe124000 {
+ compatible = "fsl,p3041-elbc", "fsl,elbc", "simple-bus";
+ interrupts = <25 2 0 0>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ pci0: pcie@ffe200000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi0>;
+ interrupts = <16 2 1 15>;
+
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi1>;
+ interrupts = <16 2 1 14>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+ };
+
+ pci2: pcie@ffe202000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 13>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+ };
+
+ pci3: pcie@ffe203000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 12>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 12>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 43 1 0 0
+ 0000 0 0 2 &mpic 0 1 0 0
+ 0000 0 0 3 &mpic 4 1 0 0
+ 0000 0 0 4 &mpic 8 1 0 0
+ >;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 927f94d16e9b..eb11098bb687 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -3,258 +3,50 @@
*
* Copyright 2009-2011 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
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
*/
-/dts-v1/;
+/include/ "p4080si.dtsi"
/ {
model = "fsl,P4080DS";
compatible = "fsl,P4080DS";
#address-cells = <2>;
#size-cells = <2>;
-
- aliases {
- ccsr = &soc;
-
- serial0 = &serial0;
- serial1 = &serial1;
- serial2 = &serial2;
- serial3 = &serial3;
- pci0 = &pci0;
- pci1 = &pci1;
- pci2 = &pci2;
- usb0 = &usb0;
- usb1 = &usb1;
- dma0 = &dma0;
- dma1 = &dma1;
- sdhc = &sdhc;
-
- crypto = &crypto;
- sec_jr0 = &sec_jr0;
- sec_jr1 = &sec_jr1;
- sec_jr2 = &sec_jr2;
- sec_jr3 = &sec_jr3;
- rtic_a = &rtic_a;
- rtic_b = &rtic_b;
- rtic_c = &rtic_c;
- rtic_d = &rtic_d;
- sec_mon = &sec_mon;
-
- rio0 = &rapidio0;
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu0: PowerPC,4080@0 {
- device_type = "cpu";
- reg = <0>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
- };
- };
- cpu1: PowerPC,4080@1 {
- device_type = "cpu";
- reg = <1>;
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
- };
- };
- cpu2: PowerPC,4080@2 {
- device_type = "cpu";
- reg = <2>;
- next-level-cache = <&L2_2>;
- L2_2: l2-cache {
- };
- };
- cpu3: PowerPC,4080@3 {
- device_type = "cpu";
- reg = <3>;
- next-level-cache = <&L2_3>;
- L2_3: l2-cache {
- };
- };
- cpu4: PowerPC,4080@4 {
- device_type = "cpu";
- reg = <4>;
- next-level-cache = <&L2_4>;
- L2_4: l2-cache {
- };
- };
- cpu5: PowerPC,4080@5 {
- device_type = "cpu";
- reg = <5>;
- next-level-cache = <&L2_5>;
- L2_5: l2-cache {
- };
- };
- cpu6: PowerPC,4080@6 {
- device_type = "cpu";
- reg = <6>;
- next-level-cache = <&L2_6>;
- L2_6: l2-cache {
- };
- };
- cpu7: PowerPC,4080@7 {
- device_type = "cpu";
- reg = <7>;
- next-level-cache = <&L2_7>;
- L2_7: l2-cache {
- };
- };
- };
+ interrupt-parent = <&mpic>;
memory {
device_type = "memory";
};
soc: soc@ffe000000 {
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "soc";
- compatible = "simple-bus";
- ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
- reg = <0xf 0xfe000000 0 0x00001000>;
-
- corenet-law@0 {
- compatible = "fsl,corenet-law";
- reg = <0x0 0x1000>;
- fsl,num-laws = <32>;
- };
-
- memory-controller@8000 {
- compatible = "fsl,p4080-memory-controller";
- reg = <0x8000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <0x12 2>;
- };
-
- memory-controller@9000 {
- compatible = "fsl,p4080-memory-controller";
- reg = <0x9000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <0x12 2>;
- };
-
- corenet-cf@18000 {
- compatible = "fsl,corenet-cf";
- reg = <0x18000 0x1000>;
- fsl,ccf-num-csdids = <32>;
- fsl,ccf-num-snoopids = <32>;
- };
-
- iommu@20000 {
- compatible = "fsl,p4080-pamu";
- reg = <0x20000 0x10000>;
- interrupts = <24 2>;
- interrupt-parent = <&mpic>;
- };
-
- mpic: pic@40000 {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
- reg = <0x40000 0x40000>;
- compatible = "chrp,open-pic";
- device_type = "open-pic";
- };
-
- dma0: dma@100300 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
- reg = <0x100300 0x4>;
- ranges = <0x0 0x100100 0x200>;
- cell-index = <0>;
- dma-channel@0 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x0 0x80>;
- cell-index = <0>;
- interrupt-parent = <&mpic>;
- interrupts = <28 2>;
- };
- dma-channel@80 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x80 0x80>;
- cell-index = <1>;
- interrupt-parent = <&mpic>;
- interrupts = <29 2>;
- };
- dma-channel@100 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x100 0x80>;
- cell-index = <2>;
- interrupt-parent = <&mpic>;
- interrupts = <30 2>;
- };
- dma-channel@180 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x180 0x80>;
- cell-index = <3>;
- interrupt-parent = <&mpic>;
- interrupts = <31 2>;
- };
- };
-
- dma1: dma@101300 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
- reg = <0x101300 0x4>;
- ranges = <0x0 0x101100 0x200>;
- cell-index = <1>;
- dma-channel@0 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x0 0x80>;
- cell-index = <0>;
- interrupt-parent = <&mpic>;
- interrupts = <32 2>;
- };
- dma-channel@80 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x80 0x80>;
- cell-index = <1>;
- interrupt-parent = <&mpic>;
- interrupts = <33 2>;
- };
- dma-channel@100 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x100 0x80>;
- cell-index = <2>;
- interrupt-parent = <&mpic>;
- interrupts = <34 2>;
- };
- dma-channel@180 {
- compatible = "fsl,p4080-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x180 0x80>;
- cell-index = <3>;
- interrupt-parent = <&mpic>;
- interrupts = <35 2>;
- };
- };
-
spi@110000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
- reg = <0x110000 0x1000>;
- interrupts = <53 0x2>;
- interrupt-parent = <&mpic>;
- fsl,espi-num-chipselects = <4>;
-
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
@@ -283,35 +75,7 @@
};
};
- sdhc: sdhc@114000 {
- compatible = "fsl,p4080-esdhc", "fsl,esdhc";
- reg = <0x114000 0x1000>;
- interrupts = <48 2>;
- interrupt-parent = <&mpic>;
- voltage-ranges = <3300 3300>;
- sdhci,auto-cmd12;
- };
-
- i2c@118000 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
- reg = <0x118000 0x100>;
- interrupts = <38 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-
i2c@118100 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <1>;
- compatible = "fsl-i2c";
- reg = <0x118100 0x100>;
- interrupts = <38 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
eeprom@51 {
compatible = "at24,24c256";
reg = <0x51>;
@@ -323,198 +87,27 @@
rtc@68 {
compatible = "dallas,ds3232";
reg = <0x68>;
- interrupts = <0 0x1>;
- interrupt-parent = <&mpic>;
+ interrupts = <0x1 0x1 0 0>;
};
};
- i2c@119000 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <2>;
- compatible = "fsl-i2c";
- reg = <0x119000 0x100>;
- interrupts = <39 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-
- i2c@119100 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <3>;
- compatible = "fsl-i2c";
- reg = <0x119100 0x100>;
- interrupts = <39 2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-
- serial0: serial@11c500 {
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11c500 0x100>;
- clock-frequency = <0>;
- interrupts = <36 2>;
- interrupt-parent = <&mpic>;
- };
-
- serial1: serial@11c600 {
- cell-index = <1>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11c600 0x100>;
- clock-frequency = <0>;
- interrupts = <36 2>;
- interrupt-parent = <&mpic>;
- };
-
- serial2: serial@11d500 {
- cell-index = <2>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11d500 0x100>;
- clock-frequency = <0>;
- interrupts = <37 2>;
- interrupt-parent = <&mpic>;
- };
-
- serial3: serial@11d600 {
- cell-index = <3>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11d600 0x100>;
- clock-frequency = <0>;
- interrupts = <37 2>;
- interrupt-parent = <&mpic>;
- };
-
- gpio0: gpio@130000 {
- compatible = "fsl,p4080-gpio";
- reg = <0x130000 0x1000>;
- interrupts = <55 2>;
- interrupt-parent = <&mpic>;
- #gpio-cells = <2>;
- gpio-controller;
- };
-
usb0: usb@210000 {
- compatible = "fsl,p4080-usb2-mph",
- "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
- reg = <0x210000 0x1000>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupt-parent = <&mpic>;
- interrupts = <44 0x2>;
phy_type = "ulpi";
};
usb1: usb@211000 {
- compatible = "fsl,p4080-usb2-dr",
- "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
- reg = <0x211000 0x1000>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupt-parent = <&mpic>;
- interrupts = <45 0x2>;
dr_mode = "host";
phy_type = "ulpi";
};
-
- crypto: crypto@300000 {
- compatible = "fsl,sec-v4.0";
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x300000 0x10000>;
- ranges = <0 0x300000 0x10000>;
- interrupt-parent = <&mpic>;
- interrupts = <92 2>;
-
- sec_jr0: jr@1000 {
- compatible = "fsl,sec-v4.0-job-ring";
- reg = <0x1000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <88 2>;
- };
-
- sec_jr1: jr@2000 {
- compatible = "fsl,sec-v4.0-job-ring";
- reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <89 2>;
- };
-
- sec_jr2: jr@3000 {
- compatible = "fsl,sec-v4.0-job-ring";
- reg = <0x3000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <90 2>;
- };
-
- sec_jr3: jr@4000 {
- compatible = "fsl,sec-v4.0-job-ring";
- reg = <0x4000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <91 2>;
- };
-
- rtic@6000 {
- compatible = "fsl,sec-v4.0-rtic";
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x6000 0x100>;
- ranges = <0x0 0x6100 0xe00>;
-
- rtic_a: rtic-a@0 {
- compatible = "fsl,sec-v4.0-rtic-memory";
- reg = <0x00 0x20 0x100 0x80>;
- };
-
- rtic_b: rtic-b@20 {
- compatible = "fsl,sec-v4.0-rtic-memory";
- reg = <0x20 0x20 0x200 0x80>;
- };
-
- rtic_c: rtic-c@40 {
- compatible = "fsl,sec-v4.0-rtic-memory";
- reg = <0x40 0x20 0x300 0x80>;
- };
-
- rtic_d: rtic-d@60 {
- compatible = "fsl,sec-v4.0-rtic-memory";
- reg = <0x60 0x20 0x500 0x80>;
- };
- };
- };
-
- sec_mon: sec_mon@314000 {
- compatible = "fsl,sec-v4.0-mon";
- reg = <0x314000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <93 2>;
- };
};
rapidio0: rapidio@ffe0c0000 {
- #address-cells = <2>;
- #size-cells = <2>;
- compatible = "fsl,rapidio-delta";
reg = <0xf 0xfe0c0000 0 0x20000>;
- ranges = <0 0 0xf 0xf5000000 0 0x01000000>;
- interrupt-parent = <&mpic>;
- /* err_irq bell_outb_irq bell_inb_irq
- msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */
- interrupts = <16 2 56 2 57 2 60 2 61 2 62 2 63 2>;
+ ranges = <0 0 0xc 0x20000000 0 0x01000000>;
};
localbus@ffe124000 {
- compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus";
reg = <0xf 0xfe124000 0 0x1000>;
- interrupts = <25 2>;
- #address-cells = <2>;
- #size-cells = <1>;
-
ranges = <0 0 0xf 0xe8000000 0x08000000>;
flash@0,0 {
@@ -526,32 +119,10 @@
};
pci0: pcie@ffe200000 {
- compatible = "fsl,p4080-pcie";
- device_type = "pci";
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
reg = <0xf 0xfe200000 0 0x1000>;
- bus-range = <0x0 0xff>;
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
- clock-frequency = <0x1fca055>;
- interrupt-parent = <&mpic>;
- interrupts = <16 2>;
-
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <
- /* IDSEL 0x0 */
- 0000 0 0 1 &mpic 40 1
- 0000 0 0 2 &mpic 1 1
- 0000 0 0 3 &mpic 2 1
- 0000 0 0 4 &mpic 3 1
- >;
pcie@0 {
- reg = <0 0 0 0 0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
0 0x20000000
@@ -563,31 +134,10 @@
};
pci1: pcie@ffe201000 {
- compatible = "fsl,p4080-pcie";
- device_type = "pci";
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
reg = <0xf 0xfe201000 0 0x1000>;
- bus-range = <0 0xff>;
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
- clock-frequency = <0x1fca055>;
- interrupt-parent = <&mpic>;
- interrupts = <16 2>;
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <
- /* IDSEL 0x0 */
- 0000 0 0 1 &mpic 41 1
- 0000 0 0 2 &mpic 5 1
- 0000 0 0 3 &mpic 6 1
- 0000 0 0 4 &mpic 7 1
- >;
pcie@0 {
- reg = <0 0 0 0 0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
0 0x20000000
@@ -599,31 +149,10 @@
};
pci2: pcie@ffe202000 {
- compatible = "fsl,p4080-pcie";
- device_type = "pci";
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
reg = <0xf 0xfe202000 0 0x1000>;
- bus-range = <0x0 0xff>;
ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
- clock-frequency = <0x1fca055>;
- interrupt-parent = <&mpic>;
- interrupts = <16 2>;
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <
- /* IDSEL 0x0 */
- 0000 0 0 1 &mpic 42 1
- 0000 0 0 2 &mpic 9 1
- 0000 0 0 3 &mpic 10 1
- 0000 0 0 4 &mpic 11 1
- >;
pcie@0 {
- reg = <0 0 0 0 0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
0 0x20000000
diff --git a/arch/powerpc/boot/dts/p4080si.dtsi b/arch/powerpc/boot/dts/p4080si.dtsi
new file mode 100644
index 000000000000..b71051f506c1
--- /dev/null
+++ b/arch/powerpc/boot/dts/p4080si.dtsi
@@ -0,0 +1,661 @@
+/*
+ * P4080 Silicon Device Tree Source
+ *
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "fsl,P4080";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+ rio0 = &rapidio0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,4080@0 {
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,4080@1 {
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu2: PowerPC,4080@2 {
+ device_type = "cpu";
+ reg = <2>;
+ next-level-cache = <&L2_2>;
+ L2_2: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu3: PowerPC,4080@3 {
+ device_type = "cpu";
+ reg = <3>;
+ next-level-cache = <&L2_3>;
+ L2_3: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu4: PowerPC,4080@4 {
+ device_type = "cpu";
+ reg = <4>;
+ next-level-cache = <&L2_4>;
+ L2_4: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu5: PowerPC,4080@5 {
+ device_type = "cpu";
+ reg = <5>;
+ next-level-cache = <&L2_5>;
+ L2_5: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu6: PowerPC,4080@6 {
+ device_type = "cpu";
+ reg = <6>;
+ next-level-cache = <&L2_6>;
+ L2_6: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu7: PowerPC,4080@7 {
+ device_type = "cpu";
+ reg = <7>;
+ next-level-cache = <&L2_7>;
+ L2_7: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+
+ soc: soc@ffe000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law@0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ memory-controller@8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ memory-controller@9000 {
+ compatible = "fsl,qoriq-memory-controller-v4.4","fsl,qoriq-memory-controller";
+ reg = <0x9000 0x1000>;
+ interrupts = <16 2 1 22>;
+ };
+
+ cpc: l3-cache-controller@10000 {
+ compatible = "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000
+ 0x11000 0x1000>;
+ interrupts = <16 2 1 27
+ 16 2 1 26>;
+ };
+
+ corenet-cf@18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu@20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x5000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+ mpic: pic@40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <4>;
+ reg = <0x40000 0x40000>;
+ compatible = "fsl,mpic", "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi0: msi@41600 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41600 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0 0 0
+ 0xe1 0 0 0
+ 0xe2 0 0 0
+ 0xe3 0 0 0
+ 0xe4 0 0 0
+ 0xe5 0 0 0
+ 0xe6 0 0 0
+ 0xe7 0 0 0>;
+ };
+
+ msi1: msi@41800 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41800 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe8 0 0 0
+ 0xe9 0 0 0
+ 0xea 0 0 0
+ 0xeb 0 0 0
+ 0xec 0 0 0
+ 0xed 0 0 0
+ 0xee 0 0 0
+ 0xef 0 0 0>;
+ };
+
+ msi2: msi@41a00 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41a00 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xf0 0 0 0
+ 0xf1 0 0 0
+ 0xf2 0 0 0
+ 0xf3 0 0 0
+ 0xf4 0 0 0
+ 0xf5 0 0 0
+ 0xf6 0 0 0
+ 0xf7 0 0 0>;
+ };
+
+ guts: global-utilities@e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities@e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities@e1000 {
+ compatible = "fsl,p4080-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities@e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp@e8000 {
+ compatible = "fsl,p4080-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes@ea000 {
+ compatible = "fsl,p4080-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+ dma0: dma@100300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
+ reg = <0x100300 0x4>;
+ ranges = <0x0 0x100100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <28 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <29 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <30 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <31 2 0 0>;
+ };
+ };
+
+ dma1: dma@101300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
+ reg = <0x101300 0x4>;
+ ranges = <0x0 0x101100 0x200>;
+ cell-index = <1>;
+ dma-channel@0 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <32 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <33 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <34 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p4080-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <35 2 0 0>;
+ };
+ };
+
+ spi@110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2 0 0>;
+ fsl,espi-num-chipselects = <4>;
+ };
+
+ sdhc: sdhc@114000 {
+ compatible = "fsl,p4080-esdhc", "fsl,esdhc";
+ reg = <0x114000 0x1000>;
+ interrupts = <48 2 0 0>;
+ voltage-ranges = <3300 3300>;
+ sdhci,auto-cmd12;
+ clock-frequency = <0>;
+ };
+
+ i2c@118000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x118000 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@118100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x118100 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ compatible = "fsl-i2c";
+ reg = <0x119000 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <3>;
+ compatible = "fsl-i2c";
+ reg = <0x119100 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ serial0: serial@11c500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial1: serial@11c600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial2: serial@11d500 {
+ cell-index = <2>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ serial3: serial@11d600 {
+ cell-index = <3>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ gpio0: gpio@130000 {
+ compatible = "fsl,p4080-gpio", "fsl,qoriq-gpio";
+ reg = <0x130000 0x1000>;
+ interrupts = <55 2 0 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ usb0: usb@210000 {
+ compatible = "fsl,p4080-usb2-mph",
+ "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ reg = <0x210000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x2 0 0>;
+ };
+
+ usb1: usb@211000 {
+ compatible = "fsl,p4080-usb2-dr",
+ "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ reg = <0x211000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <45 0x2 0 0>;
+ };
+
+ crypto: crypto@300000 {
+ compatible = "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <92 2 0 0>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <88 2 0 0>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <89 2 0 0>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <90 2 0 0>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <91 2 0 0>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <93 2 0 0>;
+ };
+ };
+
+ rapidio0: rapidio@ffe0c0000 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "fsl,rapidio-delta";
+ interrupts = <
+ 16 2 1 11 /* err_irq */
+ 56 2 0 0 /* bell_outb_irq */
+ 57 2 0 0 /* bell_inb_irq */
+ 60 2 0 0 /* msg1_tx_irq */
+ 61 2 0 0 /* msg1_rx_irq */
+ 62 2 0 0 /* msg2_tx_irq */
+ 63 2 0 0>; /* msg2_rx_irq */
+ };
+
+ localbus@ffe124000 {
+ compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus";
+ interrupts = <25 2 0 0>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ pci0: pcie@ffe200000 {
+ compatible = "fsl,p4080-pcie";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi0>;
+ interrupts = <16 2 1 15>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ compatible = "fsl,p4080-pcie";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi1>;
+ interrupts = <16 2 1 14>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+ };
+
+ pci2: pcie@ffe202000 {
+ compatible = "fsl,p4080-pcie";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 13>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p5020ds.dts b/arch/powerpc/boot/dts/p5020ds.dts
new file mode 100644
index 000000000000..8366e2fd2fba
--- /dev/null
+++ b/arch/powerpc/boot/dts/p5020ds.dts
@@ -0,0 +1,215 @@
+/*
+ * P5020DS Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "p5020si.dtsi"
+
+/ {
+ model = "fsl,P5020DS";
+ compatible = "fsl,P5020DS";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ memory {
+ device_type = "memory";
+ };
+
+ soc: soc@ffe000000 {
+ spi@110000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ partition@u-boot {
+ label = "u-boot";
+ reg = <0x00000000 0x00100000>;
+ read-only;
+ };
+ partition@kernel {
+ label = "kernel";
+ reg = <0x00100000 0x00500000>;
+ read-only;
+ };
+ partition@dtb {
+ label = "dtb";
+ reg = <0x00600000 0x00100000>;
+ read-only;
+ };
+ partition@fs {
+ label = "file system";
+ reg = <0x00700000 0x00900000>;
+ };
+ };
+ };
+
+ i2c@118100 {
+ eeprom@51 {
+ compatible = "at24,24c256";
+ reg = <0x51>;
+ };
+ eeprom@52 {
+ compatible = "at24,24c256";
+ reg = <0x52>;
+ };
+ };
+
+ i2c@119100 {
+ rtc@68 {
+ compatible = "dallas,ds3232";
+ reg = <0x68>;
+ interrupts = <0x1 0x1 0 0>;
+ };
+ };
+ };
+
+ localbus@ffe124000 {
+ reg = <0xf 0xfe124000 0 0x1000>;
+ ranges = <0 0 0xf 0xe8000000 0x08000000
+ 2 0 0xf 0xffa00000 0x00040000
+ 3 0 0xf 0xffdf0000 0x00008000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x08000000>;
+ bank-width = <2>;
+ device-width = <2>;
+ };
+
+ nand@2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,elbc-fcm-nand";
+ reg = <0x2 0x0 0x40000>;
+
+ partition@0 {
+ label = "NAND U-Boot Image";
+ reg = <0x0 0x02000000>;
+ read-only;
+ };
+
+ partition@2000000 {
+ label = "NAND Root File System";
+ reg = <0x02000000 0x10000000>;
+ };
+
+ partition@12000000 {
+ label = "NAND Compressed RFS Image";
+ reg = <0x12000000 0x08000000>;
+ };
+
+ partition@1a000000 {
+ label = "NAND Linux Kernel Image";
+ reg = <0x1a000000 0x04000000>;
+ };
+
+ partition@1e000000 {
+ label = "NAND DTB Image";
+ reg = <0x1e000000 0x01000000>;
+ };
+
+ partition@1f000000 {
+ label = "NAND Writable User area";
+ reg = <0x1f000000 0x21000000>;
+ };
+ };
+
+ board-control@3,0 {
+ compatible = "fsl,p5020ds-pixis";
+ reg = <3 0 0x20>;
+ };
+ };
+
+ pci0: pcie@ffe200000 {
+ reg = <0xf 0xfe200000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ reg = <0xf 0xfe201000 0 0x1000>;
+ ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+ 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie@ffe202000 {
+ reg = <0xf 0xfe202000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci3: pcie@ffe203000 {
+ reg = <0xf 0xfe203000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p5020si.dtsi b/arch/powerpc/boot/dts/p5020si.dtsi
new file mode 100644
index 000000000000..5e6048ec55bb
--- /dev/null
+++ b/arch/powerpc/boot/dts/p5020si.dtsi
@@ -0,0 +1,652 @@
+/*
+ * P5020 Silicon Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "fsl,P5020";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ pci3 = &pci3;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+/*
+ rio0 = &rapidio0;
+ */
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e5500@0 {
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e5500@1 {
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+
+ soc: soc@ffe000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law@0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ memory-controller@8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ memory-controller@9000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x9000 0x1000>;
+ interrupts = <16 2 1 22>;
+ };
+
+ cpc: l3-cache-controller@10000 {
+ compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000
+ 0x11000 0x1000>;
+ interrupts = <16 2 1 27
+ 16 2 1 26>;
+ };
+
+ corenet-cf@18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu@20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x4000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+ mpic: pic@40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <4>;
+ reg = <0x40000 0x40000>;
+ compatible = "fsl,mpic", "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi0: msi@41600 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41600 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0 0 0
+ 0xe1 0 0 0
+ 0xe2 0 0 0
+ 0xe3 0 0 0
+ 0xe4 0 0 0
+ 0xe5 0 0 0
+ 0xe6 0 0 0
+ 0xe7 0 0 0>;
+ };
+
+ msi1: msi@41800 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41800 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe8 0 0 0
+ 0xe9 0 0 0
+ 0xea 0 0 0
+ 0xeb 0 0 0
+ 0xec 0 0 0
+ 0xed 0 0 0
+ 0xee 0 0 0
+ 0xef 0 0 0>;
+ };
+
+ msi2: msi@41a00 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41a00 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xf0 0 0 0
+ 0xf1 0 0 0
+ 0xf2 0 0 0
+ 0xf3 0 0 0
+ 0xf4 0 0 0
+ 0xf5 0 0 0
+ 0xf6 0 0 0
+ 0xf7 0 0 0>;
+ };
+
+ guts: global-utilities@e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities@e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities@e1000 {
+ compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities@e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp@e8000 {
+ compatible = "fsl,p5020-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes@ea000 {
+ compatible = "fsl,p5020-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+ dma0: dma@100300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p5020-dma", "fsl,eloplus-dma";
+ reg = <0x100300 0x4>;
+ ranges = <0x0 0x100100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <28 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <29 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <30 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <31 2 0 0>;
+ };
+ };
+
+ dma1: dma@101300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p5020-dma", "fsl,eloplus-dma";
+ reg = <0x101300 0x4>;
+ ranges = <0x0 0x101100 0x200>;
+ cell-index = <1>;
+ dma-channel@0 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <32 2 0 0>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <33 2 0 0>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <34 2 0 0>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <35 2 0 0>;
+ };
+ };
+
+ spi@110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p5020-espi", "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2 0 0>;
+ fsl,espi-num-chipselects = <4>;
+ };
+
+ sdhc: sdhc@114000 {
+ compatible = "fsl,p5020-esdhc", "fsl,esdhc";
+ reg = <0x114000 0x1000>;
+ interrupts = <48 2 0 0>;
+ sdhci,auto-cmd12;
+ clock-frequency = <0>;
+ };
+
+ i2c@118000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x118000 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@118100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x118100 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ compatible = "fsl-i2c";
+ reg = <0x119000 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ i2c@119100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <3>;
+ compatible = "fsl-i2c";
+ reg = <0x119100 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ serial0: serial@11c500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial1: serial@11c600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial2: serial@11d500 {
+ cell-index = <2>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ serial3: serial@11d600 {
+ cell-index = <3>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ gpio0: gpio@130000 {
+ compatible = "fsl,p5020-gpio", "fsl,qoriq-gpio";
+ reg = <0x130000 0x1000>;
+ interrupts = <55 2 0 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ usb0: usb@210000 {
+ compatible = "fsl,p5020-usb2-mph",
+ "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ reg = <0x210000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x2 0 0>;
+ phy_type = "utmi";
+ port0;
+ };
+
+ usb1: usb@211000 {
+ compatible = "fsl,p5020-usb2-dr",
+ "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ reg = <0x211000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <45 0x2 0 0>;
+ dr_mode = "host";
+ phy_type = "utmi";
+ };
+
+ sata@220000 {
+ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+ reg = <0x220000 0x1000>;
+ interrupts = <68 0x2 0 0>;
+ };
+
+ sata@221000 {
+ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+ reg = <0x221000 0x1000>;
+ interrupts = <69 0x2 0 0>;
+ };
+
+ crypto: crypto@300000 {
+ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupts = <92 2 0 0>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <88 2 0 0>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <89 2 0 0>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <90 2 0 0>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupts = <91 2 0 0>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,sec-v4.2-rtic",
+ "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupts = <93 2 0 0>;
+ };
+ };
+
+/*
+ rapidio0: rapidio@ffe0c0000
+*/
+
+ localbus@ffe124000 {
+ compatible = "fsl,p5020-elbc", "fsl,elbc", "simple-bus";
+ interrupts = <25 2 0 0>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ pci0: pcie@ffe200000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi0>;
+ interrupts = <16 2 1 15>;
+
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi1>;
+ interrupts = <16 2 1 14>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+ };
+
+ pci2: pcie@ffe202000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 13>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+ };
+
+ pci3: pcie@ffe203000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 12>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 12>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 43 1 0 0
+ 0000 0 0 2 &mpic 0 1 0 0
+ 0000 0 0 3 &mpic 4 1 0 0
+ 0000 0 0 4 &mpic 8 1 0 0
+ >;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts
index 739dd0da2416..b1d329246b08 100644
--- a/arch/powerpc/boot/dts/sequoia.dts
+++ b/arch/powerpc/boot/dts/sequoia.dts
@@ -110,6 +110,18 @@
dcr-reg = <0x010 0x002>;
};
+ CRYPTO: crypto@e0100000 {
+ compatible = "amcc,ppc440epx-crypto","amcc,ppc4xx-crypto";
+ reg = <0 0xE0100000 0x80400>;
+ interrupt-parent = <&UIC0>;
+ interrupts = <0x17 0x4>;
+ };
+
+ rng@e0120000 {
+ compatible = "amcc,ppc440epx-rng","amcc,ppc4xx-rng";
+ reg = <0 0xE0120000 0x150>;
+ };
+
DMA0: dma {
compatible = "ibm,dma-440epx", "ibm,dma-4xx";
dcr-reg = <0x100 0x027>;
diff --git a/arch/powerpc/boot/dts/socrates.dts b/arch/powerpc/boot/dts/socrates.dts
index feb4ef6bd144..38c35404bdc3 100644
--- a/arch/powerpc/boot/dts/socrates.dts
+++ b/arch/powerpc/boot/dts/socrates.dts
@@ -240,6 +240,8 @@
#address-cells = <2>;
#size-cells = <1>;
reg = <0xe0005000 0x40>;
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
ranges = <0 0 0xfc000000 0x04000000
2 0 0xc8000000 0x04000000
diff --git a/arch/powerpc/boot/dts/taishan.dts b/arch/powerpc/boot/dts/taishan.dts
index 058438f9629b..1657ad0bf8a6 100644
--- a/arch/powerpc/boot/dts/taishan.dts
+++ b/arch/powerpc/boot/dts/taishan.dts
@@ -337,7 +337,7 @@
rx-fifo-size = <4096>;
tx-fifo-size = <2048>;
phy-mode = "rgmii";
- phy-map = <0x00000001>;
+ phy-address = <1>;
rgmii-device = <&RGMII0>;
rgmii-channel = <0>;
zmii-device = <&ZMII0>;
@@ -361,7 +361,7 @@
rx-fifo-size = <4096>;
tx-fifo-size = <2048>;
phy-mode = "rgmii";
- phy-map = <0x00000003>;
+ phy-address = <3>;
rgmii-device = <&RGMII0>;
rgmii-channel = <1>;
zmii-device = <&ZMII0>;
diff --git a/arch/powerpc/boot/dts/tqm8540.dts b/arch/powerpc/boot/dts/tqm8540.dts
index 15ca731bc24e..0a4cedbdcb55 100644
--- a/arch/powerpc/boot/dts/tqm8540.dts
+++ b/arch/powerpc/boot/dts/tqm8540.dts
@@ -277,6 +277,48 @@
};
};
+ localbus@e0005000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8540-localbus", "fsl,pq3-localbus",
+ "simple-bus";
+ reg = <0xe0005000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
+
+ ranges = <0x0 0x0 0xfe000000 0x02000000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x02000000>;
+ bank-width = <4>;
+ device-width = <2>;
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00180000>;
+ };
+ partition@180000 {
+ label = "root";
+ reg = <0x00180000 0x01dc0000>;
+ };
+ partition@1f40000 {
+ label = "env1";
+ reg = <0x01f40000 0x00040000>;
+ };
+ partition@1f80000 {
+ label = "env2";
+ reg = <0x01f80000 0x00040000>;
+ };
+ partition@1fc0000 {
+ label = "u-boot";
+ reg = <0x01fc0000 0x00040000>;
+ read-only;
+ };
+ };
+ };
+
pci0: pci@e0008000 {
#interrupt-cells = <1>;
#size-cells = <2>;
diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 5dbb36edb038..9452c3c05114 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -346,6 +346,8 @@
#address-cells = <2>;
#size-cells = <1>;
reg = <0xa0005000 0x100>; // BRx, ORx, etc.
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
ranges = <
0 0x0 0xfc000000 0x04000000 // NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index a050ae427108..619776f72c90 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -346,6 +346,8 @@
#address-cells = <2>;
#size-cells = <1>;
reg = <0xe0005000 0x100>; // BRx, ORx, etc.
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
ranges = <
0 0x0 0xfc000000 0x04000000 // NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/tqm8560.dts b/arch/powerpc/boot/dts/tqm8560.dts
index 22ec39b5beeb..7665a16a8b9a 100644
--- a/arch/powerpc/boot/dts/tqm8560.dts
+++ b/arch/powerpc/boot/dts/tqm8560.dts
@@ -312,6 +312,8 @@
#address-cells = <2>;
#size-cells = <1>;
reg = <0xe0005000 0x100>; // BRx, ORx, etc.
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
ranges = <
0 0x0 0xfc000000 0x04000000 // NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/xpedite5200.dts b/arch/powerpc/boot/dts/xpedite5200.dts
index a0cf53fbd55c..c41a80c55e47 100644
--- a/arch/powerpc/boot/dts/xpedite5200.dts
+++ b/arch/powerpc/boot/dts/xpedite5200.dts
@@ -374,6 +374,8 @@
#address-cells = <2>;
#size-cells = <1>;
reg = <0xef005000 0x100>; // BRx, ORx, etc.
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
ranges = <
0 0x0 0xfc000000 0x04000000 // NOR boot flash
diff --git a/arch/powerpc/boot/dts/xpedite5200_xmon.dts b/arch/powerpc/boot/dts/xpedite5200_xmon.dts
index c5b29752651a..c0efcbb45137 100644
--- a/arch/powerpc/boot/dts/xpedite5200_xmon.dts
+++ b/arch/powerpc/boot/dts/xpedite5200_xmon.dts
@@ -378,6 +378,8 @@
#address-cells = <2>;
#size-cells = <1>;
reg = <0xef005000 0x100>; // BRx, ORx, etc.
+ interrupt-parent = <&mpic>;
+ interrupts = <19 2>;
ranges = <
0 0x0 0xf8000000 0x08000000 // NOR boot flash
diff --git a/arch/powerpc/boot/treeboot-iss4xx.c b/arch/powerpc/boot/treeboot-iss4xx.c
index fcc44952874e..329e710feda2 100644
--- a/arch/powerpc/boot/treeboot-iss4xx.c
+++ b/arch/powerpc/boot/treeboot-iss4xx.c
@@ -34,9 +34,29 @@
BSS_STACK(4096);
+static u32 ibm4xx_memstart;
+
static void iss_4xx_fixups(void)
{
- ibm4xx_sdram_fixup_memsize();
+ void *memory;
+ u32 reg[3];
+
+ memory = finddevice("/memory");
+ if (!memory)
+ fatal("Can't find memory node\n");
+ /* This assumes #address-cells = 2, #size-cells =1 and that */
+ getprop(memory, "reg", reg, sizeof(reg));
+ if (reg[2])
+ /* If the device tree specifies the memory range, use it */
+ ibm4xx_memstart = reg[1];
+ else
+ /* othersize, read it from the SDRAM controller */
+ ibm4xx_sdram_fixup_memsize();
+}
+
+static void *iss_4xx_vmlinux_alloc(unsigned long size)
+{
+ return (void *)ibm4xx_memstart;
}
#define SPRN_PIR 0x11E /* Processor Indentification Register */
@@ -48,6 +68,7 @@ void platform_init(void)
simple_alloc_init(_end, avail_ram, 128, 64);
platform_ops.fixups = iss_4xx_fixups;
+ platform_ops.vmlinux_alloc = iss_4xx_vmlinux_alloc;
platform_ops.exit = ibm44x_dbcr_reset;
pir_reg = mfspr(SPRN_PIR);
fdt_set_boot_cpuid_phys(_dtb_start, pir_reg);
diff --git a/arch/powerpc/configs/44x/iss476-smp_defconfig b/arch/powerpc/configs/44x/iss476-smp_defconfig
index 92f863ac8443..a6eb6ad05b2d 100644
--- a/arch/powerpc/configs/44x/iss476-smp_defconfig
+++ b/arch/powerpc/configs/44x/iss476-smp_defconfig
@@ -3,8 +3,8 @@ CONFIG_SMP=y
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_SPARSE_IRQ=y
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
@@ -21,10 +21,11 @@ CONFIG_ISS4xx=y
CONFIG_HZ_100=y
CONFIG_MATH_EMULATION=y
CONFIG_IRQ_ALL_CPUS=y
-CONFIG_SPARSE_IRQ=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="root=/dev/issblk0"
# CONFIG_PCI is not set
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_RELOCATABLE=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -67,7 +68,6 @@ CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_CRAMFS=y
diff --git a/arch/powerpc/configs/85xx/p1023rds_defconfig b/arch/powerpc/configs/85xx/p1023rds_defconfig
new file mode 100644
index 000000000000..980ff8f61fd4
--- /dev/null
+++ b/arch/powerpc/configs/85xx/p1023rds_defconfig
@@ -0,0 +1,173 @@
+CONFIG_PPC_85xx=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
+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_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_P1023_RDS=y
+CONFIG_QUICC_ENGINE=y
+CONFIG_QE_GPIO=y
+CONFIG_CPM2=y
+CONFIG_MPC8xxx_GPIO=y
+CONFIG_HIGHMEM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_MATH_EMULATION=y
+CONFIG_SWIOTLB=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEAER is not set
+# CONFIG_PCIEASPM is not set
+CONFIG_PCI_MSI=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IP_SCTP=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_LEGACY=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_ATA=y
+CONFIG_SATA_FSL=y
+CONFIG_SATA_SIL24=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_FS_ENET=y
+CONFIG_E1000E=y
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_QE=m
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_I2C=y
+CONFIG_I2C_CPM=m
+CONFIG_I2C_MPC=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_DMADEVICES=y
+CONFIG_FSL_DMA=y
+# CONFIG_NET_DMA is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_ADFS_FS=m
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_CRC_T10DIF=y
+CONFIG_FRAME_WARN=8092
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_VIRQ_DEBUG=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index 036bfb2d18cd..0db9ba0423ff 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -89,6 +89,11 @@ CONFIG_I2C_MPC=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
CONFIG_FB_FSL_DIU=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_MIXER_OSS=y
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
new file mode 100644
index 000000000000..10562a5c65b9
--- /dev/null
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -0,0 +1,187 @@
+CONFIG_PPC_85xx=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_RCU_TRACE=y
+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_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=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_P2040_RDB=y
+CONFIG_P3041_DS=y
+CONFIG_P4080_DS=y
+CONFIG_P5020_DS=y
+CONFIG_HIGHMEM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_KEXEC=y
+CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_FSL_LBC=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEASPM is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IP_SCTP=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_FSL=y
+CONFIG_SATA_SIL24=y
+CONFIG_SATA_SIL=y
+CONFIG_PATA_SIL680=y
+CONFIG_NETDEVICES=y
+CONFIG_VITESSE_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_FSL_PQ_MDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PPC_EPAPR_HV_BYTECHAN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_I2C=y
+CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_FSL_SPI=y
+CONFIG_SPI_FSL_ESPI=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_USB_HID=m
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_OF=y
+CONFIG_MMC_SDHCI_OF_ESDHC=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_MPC85XX=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS3232=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_VIRT_DRIVERS=y
+CONFIG_FSL_HV_MANAGER=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=m
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/e55xx_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index d32283555b53..d32283555b53 100644
--- a/arch/powerpc/configs/e55xx_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 96b89df7752a..fcd85d2c72dc 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -5,6 +5,7 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -25,7 +26,9 @@ CONFIG_MPC85xx_MDS=y
CONFIG_MPC8536_DS=y
CONFIG_MPC85xx_DS=y
CONFIG_MPC85xx_RDB=y
+CONFIG_P1010_RDB=y
CONFIG_P1022_DS=y
+CONFIG_P1023_RDS=y
CONFIG_SOCRATES=y
CONFIG_KSI8560=y
CONFIG_XES_MPC85xx=y
@@ -44,7 +47,6 @@ CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BINFMT_MISC=m
CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_PCI=y
CONFIG_PCI_MSI=y
@@ -65,8 +67,6 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
@@ -128,6 +128,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
CONFIG_FB_FSL_DIU=y
# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
CONFIG_SOUND=y
CONFIG_SND=y
# CONFIG_SND_SUPPORT_OLD_API is not set
@@ -170,7 +174,6 @@ CONFIG_FSL_DMA=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
@@ -205,7 +208,6 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_VIRQ_DEBUG=y
CONFIG_CRYPTO_PCBC=m
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index de65841aa04e..908c941fc24c 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -7,6 +7,7 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -28,6 +29,7 @@ CONFIG_MPC8536_DS=y
CONFIG_MPC85xx_DS=y
CONFIG_MPC85xx_RDB=y
CONFIG_P1022_DS=y
+CONFIG_P1023_RDS=y
CONFIG_SOCRATES=y
CONFIG_KSI8560=y
CONFIG_XES_MPC85xx=y
@@ -46,7 +48,6 @@ CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BINFMT_MISC=m
CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_PCI=y
CONFIG_PCI_MSI=y
@@ -67,8 +68,6 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
@@ -130,6 +129,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
CONFIG_FB_FSL_DIU=y
# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
CONFIG_SOUND=y
CONFIG_SND=y
# CONFIG_SND_SUPPORT_OLD_API is not set
@@ -172,7 +175,6 @@ CONFIG_FSL_DMA=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 76736017cd34..84a685a505fe 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -176,12 +176,19 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+CONFIG_BE2ISCSI=m
+CONFIG_SCSI_MPT2SAS=m
CONFIG_SCSI_IBMVSCSI=y
CONFIG_SCSI_IBMVFC=m
CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_IPR=y
CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
CONFIG_SCSI_LPFC=m
CONFIG_ATA=y
CONFIG_SATA_SIL24=y
@@ -235,11 +242,13 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_TIGON3=y
+CONFIG_BNX2=m
CONFIG_SPIDER_NET=m
CONFIG_GELIC_NET=m
CONFIG_GELIC_WIRELESS=y
CONFIG_CHELSIO_T1=m
CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4=m
CONFIG_EHEA=m
CONFIG_IXGBE=m
CONFIG_IXGB=m
@@ -248,6 +257,8 @@ CONFIG_MYRI10GE=m
CONFIG_NETXEN_NIC=m
CONFIG_PASEMI_MAC=y
CONFIG_MLX4_EN=m
+CONFIG_QLGE=m
+CONFIG_BE2NET=m
CONFIG_ISERIES_VETH=m
CONFIG_PPP=m
CONFIG_PPP_ASYNC=m
@@ -330,6 +341,8 @@ CONFIG_INFINIBAND_USER_MAD=m
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_EHCA=m
+CONFIG_INFINIBAND_CXGB3=m
+CONFIG_INFINIBAND_CXGB4=m
CONFIG_MLX4_INFINIBAND=m
CONFIG_INFINIBAND_IPOIB=m
CONFIG_INFINIBAND_IPOIB_CM=y
@@ -430,11 +443,12 @@ CONFIG_NLS_KOI8_U=m
CONFIG_CRC_T10DIF=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_MUTEXES=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_LATENCYTOP=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQSOFF_TRACER=y
CONFIG_SCHED_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_DEBUG_STACKOVERFLOW=y
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 80bc5de7ee1d..96a58b709705 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -149,6 +149,7 @@ CONFIG_SCSI_CXGB3_ISCSI=m
CONFIG_SCSI_CXGB4_ISCSI=m
CONFIG_SCSI_BNX2_ISCSI=m
CONFIG_BE2ISCSI=m
+CONFIG_SCSI_MPT2SAS=m
CONFIG_SCSI_IBMVSCSI=y
CONFIG_SCSI_IBMVFC=m
CONFIG_SCSI_SYM53C8XX_2=y
@@ -320,6 +321,8 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_CRC_T10DIF=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DETECT_HUNG_TASK=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_LATENCYTOP=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
diff --git a/arch/powerpc/include/asm/8253pit.h b/arch/powerpc/include/asm/8253pit.h
deleted file mode 100644
index a71c9c1455a7..000000000000
--- a/arch/powerpc/include/asm/8253pit.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * 8253/8254 Programmable Interval Timer
- */
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index b8f152ece025..e2a4c26ad377 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -181,21 +181,21 @@ static __inline__ int atomic_dec_return(atomic_t *v)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int t;
__asm__ __volatile__ (
PPC_RELEASE_BARRIER
-"1: lwarx %0,0,%1 # atomic_add_unless\n\
+"1: lwarx %0,0,%1 # __atomic_add_unless\n\
cmpw 0,%0,%3 \n\
beq- 2f \n\
add %0,%2,%0 \n"
@@ -209,10 +209,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
: "r" (&v->counter), "r" (a), "r" (u)
: "cc", "memory");
- return t != u;
+ return t;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
@@ -444,7 +443,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
{
@@ -452,7 +451,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
__asm__ __volatile__ (
PPC_RELEASE_BARRIER
-"1: ldarx %0,0,%1 # atomic_add_unless\n\
+"1: ldarx %0,0,%1 # __atomic_add_unless\n\
cmpd 0,%0,%3 \n\
beq- 2f \n\
add %0,%2,%0 \n"
@@ -470,11 +469,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
-#else /* __powerpc64__ */
-#include <asm-generic/atomic64.h>
-
#endif /* __powerpc64__ */
-#include <asm-generic/atomic-long.h>
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_ATOMIC_H_ */
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index f18c6d9b9510..e137afcc10fa 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -327,10 +327,7 @@ unsigned long find_next_bit_le(const void *addr,
unsigned long size, unsigned long offset);
/* Bitmap functions for the ext2 filesystem */
-#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit_le((nr), (unsigned long*)addr)
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit_le((nr), (unsigned long*)addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#include <asm-generic/bitops/sched.h>
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index c0d842cfd012..e30442c539ce 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -179,8 +179,9 @@ extern const char *powerpc_base_platform;
#define LONG_ASM_CONST(x) 0
#endif
-
-#define CPU_FTR_HVMODE_206 LONG_ASM_CONST(0x0000000800000000)
+#define CPU_FTR_HVMODE LONG_ASM_CONST(0x0000000200000000)
+#define CPU_FTR_ARCH_201 LONG_ASM_CONST(0x0000000400000000)
+#define CPU_FTR_ARCH_206 LONG_ASM_CONST(0x0000000800000000)
#define CPU_FTR_CFAR LONG_ASM_CONST(0x0000001000000000)
#define CPU_FTR_IABR LONG_ASM_CONST(0x0000002000000000)
#define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000)
@@ -401,9 +402,10 @@ extern const char *powerpc_base_platform;
CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \
CPU_FTR_STCX_CHECKS_ADDRESS)
#define CPU_FTRS_PPC970 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_201 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \
- CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS)
+ CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS | \
+ CPU_FTR_HVMODE)
#define CPU_FTRS_POWER5 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -417,13 +419,13 @@ extern const char *powerpc_base_platform;
CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_CFAR)
#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_HVMODE_206 |\
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | \
CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
- CPU_FTR_ICSWX | CPU_FTR_CFAR)
+ CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE)
#define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
index 9c70d0ca96d4..efa74ac44a35 100644
--- a/arch/powerpc/include/asm/dbell.h
+++ b/arch/powerpc/include/asm/dbell.h
@@ -18,7 +18,7 @@
#include <asm/ppc-opcode.h>
#define PPC_DBELL_MSG_BRDCAST (0x04000000)
-#define PPC_DBELL_TYPE(x) (((x) & 0xf) << 28)
+#define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36))
enum ppc_dbell {
PPC_DBELL = 0, /* doorbell */
PPC_DBELL_CRIT = 1, /* critical doorbell */
diff --git a/arch/powerpc/include/asm/ehv_pic.h b/arch/powerpc/include/asm/ehv_pic.h
new file mode 100644
index 000000000000..a9e1f4f796f6
--- /dev/null
+++ b/arch/powerpc/include/asm/ehv_pic.h
@@ -0,0 +1,40 @@
+/*
+ * EHV_PIC private definitions and structure.
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+#ifndef __EHV_PIC_H__
+#define __EHV_PIC_H__
+
+#include <linux/irq.h>
+
+#define NR_EHV_PIC_INTS 1024
+
+#define EHV_PIC_INFO(name) EHV_PIC_##name
+
+#define EHV_PIC_VECPRI_POLARITY_NEGATIVE 0
+#define EHV_PIC_VECPRI_POLARITY_POSITIVE 1
+#define EHV_PIC_VECPRI_SENSE_EDGE 0
+#define EHV_PIC_VECPRI_SENSE_LEVEL 0x2
+#define EHV_PIC_VECPRI_POLARITY_MASK 0x1
+#define EHV_PIC_VECPRI_SENSE_MASK 0x2
+
+struct ehv_pic {
+ /* The remapper for this EHV_PIC */
+ struct irq_host *irqhost;
+
+ /* The "linux" controller struct */
+ struct irq_chip hc_irq;
+
+ /* core int flag */
+ int coreint_flag;
+};
+
+void ehv_pic_init(void);
+unsigned int ehv_pic_get_irq(void);
+
+#endif /* __EHV_PIC_H__ */
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index 2b917c69ed15..3bf9cca35147 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -267,7 +267,7 @@ extern int ucache_bsize;
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);
-#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b);
+#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b)
/* 1GB for 64bit, 8MB for 32bit */
#define STACK_RND_MASK (is_32bit_task() ? \
@@ -298,7 +298,7 @@ do { \
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
- VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base) \
+ VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base); \
} while (0)
/* PowerPC64 relocations defined by the ABIs */
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h
index 45921672b97a..63f2a22e9954 100644
--- a/arch/powerpc/include/asm/emulated_ops.h
+++ b/arch/powerpc/include/asm/emulated_ops.h
@@ -18,7 +18,7 @@
#ifndef _ASM_POWERPC_EMULATED_OPS_H
#define _ASM_POWERPC_EMULATED_OPS_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/perf_event.h>
@@ -78,14 +78,14 @@ extern void ppc_warn_emulated_print(const char *type);
#define PPC_WARN_EMULATED(type, regs) \
do { \
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, \
- 1, 0, regs, 0); \
+ 1, regs, 0); \
__PPC_WARN_EMULATED(type); \
} while (0)
#define PPC_WARN_ALIGNMENT(type, regs) \
do { \
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, \
- 1, 0, regs, regs->dar); \
+ 1, regs, regs->dar); \
__PPC_WARN_EMULATED(type); \
} while (0)
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
new file mode 100644
index 000000000000..f3b0c2cc9fea
--- /dev/null
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -0,0 +1,502 @@
+/*
+ * ePAPR hcall interface
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is provided under a dual BSD/GPL license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/* A "hypercall" is an "sc 1" instruction. This header file file provides C
+ * wrapper functions for the ePAPR hypervisor interface. It is inteded
+ * for use by Linux device drivers and other operating systems.
+ *
+ * The hypercalls are implemented as inline assembly, rather than assembly
+ * language functions in a .S file, for optimization. It allows
+ * the caller to issue the hypercall instruction directly, improving both
+ * performance and memory footprint.
+ */
+
+#ifndef _EPAPR_HCALLS_H
+#define _EPAPR_HCALLS_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+
+#define EV_BYTE_CHANNEL_SEND 1
+#define EV_BYTE_CHANNEL_RECEIVE 2
+#define EV_BYTE_CHANNEL_POLL 3
+#define EV_INT_SET_CONFIG 4
+#define EV_INT_GET_CONFIG 5
+#define EV_INT_SET_MASK 6
+#define EV_INT_GET_MASK 7
+#define EV_INT_IACK 9
+#define EV_INT_EOI 10
+#define EV_INT_SEND_IPI 11
+#define EV_INT_SET_TASK_PRIORITY 12
+#define EV_INT_GET_TASK_PRIORITY 13
+#define EV_DOORBELL_SEND 14
+#define EV_MSGSND 15
+#define EV_IDLE 16
+
+/* vendor ID: epapr */
+#define EV_LOCAL_VENDOR_ID 0 /* for private use */
+#define EV_EPAPR_VENDOR_ID 1
+#define EV_FSL_VENDOR_ID 2 /* Freescale Semiconductor */
+#define EV_IBM_VENDOR_ID 3 /* IBM */
+#define EV_GHS_VENDOR_ID 4 /* Green Hills Software */
+#define EV_ENEA_VENDOR_ID 5 /* Enea */
+#define EV_WR_VENDOR_ID 6 /* Wind River Systems */
+#define EV_AMCC_VENDOR_ID 7 /* Applied Micro Circuits */
+#define EV_KVM_VENDOR_ID 42 /* KVM */
+
+/* The max number of bytes that a byte channel can send or receive per call */
+#define EV_BYTE_CHANNEL_MAX_BYTES 16
+
+
+#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
+#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
+
+/* epapr error codes */
+#define EV_EPERM 1 /* Operation not permitted */
+#define EV_ENOENT 2 /* Entry Not Found */
+#define EV_EIO 3 /* I/O error occured */
+#define EV_EAGAIN 4 /* The operation had insufficient
+ * resources to complete and should be
+ * retried
+ */
+#define EV_ENOMEM 5 /* There was insufficient memory to
+ * complete the operation */
+#define EV_EFAULT 6 /* Bad guest address */
+#define EV_ENODEV 7 /* No such device */
+#define EV_EINVAL 8 /* An argument supplied to the hcall
+ was out of range or invalid */
+#define EV_INTERNAL 9 /* An internal error occured */
+#define EV_CONFIG 10 /* A configuration error was detected */
+#define EV_INVALID_STATE 11 /* The object is in an invalid state */
+#define EV_UNIMPLEMENTED 12 /* Unimplemented hypercall */
+#define EV_BUFFER_OVERFLOW 13 /* Caller-supplied buffer too small */
+
+/*
+ * Hypercall register clobber list
+ *
+ * These macros are used to define the list of clobbered registers during a
+ * hypercall. Technically, registers r0 and r3-r12 are always clobbered,
+ * but the gcc inline assembly syntax does not allow us to specify registers
+ * on the clobber list that are also on the input/output list. Therefore,
+ * the lists of clobbered registers depends on the number of register
+ * parmeters ("+r" and "=r") passed to the hypercall.
+ *
+ * Each assembly block should use one of the HCALL_CLOBBERSx macros. As a
+ * general rule, 'x' is the number of parameters passed to the assembly
+ * block *except* for r11.
+ *
+ * If you're not sure, just use the smallest value of 'x' that does not
+ * generate a compilation error. Because these are static inline functions,
+ * the compiler will only check the clobber list for a function if you
+ * compile code that calls that function.
+ *
+ * r3 and r11 are not included in any clobbers list because they are always
+ * listed as output registers.
+ *
+ * XER, CTR, and LR are currently listed as clobbers because it's uncertain
+ * whether they will be clobbered.
+ *
+ * Note that r11 can be used as an output parameter.
+*/
+
+/* List of common clobbered registers. Do not use this macro. */
+#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc"
+
+#define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS
+#define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10"
+#define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9"
+#define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8"
+#define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7"
+#define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6"
+#define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
+#define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
+
+
+/*
+ * We use "uintptr_t" to define a register because it's guaranteed to be a
+ * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
+ * platform.
+ *
+ * All registers are either input/output or output only. Registers that are
+ * initialized before making the hypercall are input/output. All
+ * input/output registers are represented with "+r". Output-only registers
+ * are represented with "=r". Do not specify any unused registers. The
+ * clobber list will tell the compiler that the hypercall modifies those
+ * registers, which is good enough.
+ */
+
+/**
+ * ev_int_set_config - configure the specified interrupt
+ * @interrupt: the interrupt number
+ * @config: configuration for this interrupt
+ * @priority: interrupt priority
+ * @destination: destination CPU number
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_set_config(unsigned int interrupt,
+ uint32_t config, unsigned int priority, uint32_t destination)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r6 __asm__("r6");
+
+ r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG);
+ r3 = interrupt;
+ r4 = config;
+ r5 = priority;
+ r6 = destination;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
+ : : EV_HCALL_CLOBBERS4
+ );
+
+ return r3;
+}
+
+/**
+ * ev_int_get_config - return the config of the specified interrupt
+ * @interrupt: the interrupt number
+ * @config: returned configuration for this interrupt
+ * @priority: returned interrupt priority
+ * @destination: returned destination CPU number
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_get_config(unsigned int interrupt,
+ uint32_t *config, unsigned int *priority, uint32_t *destination)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r6 __asm__("r6");
+
+ r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
+ r3 = interrupt;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
+ : : EV_HCALL_CLOBBERS4
+ );
+
+ *config = r4;
+ *priority = r5;
+ *destination = r6;
+
+ return r3;
+}
+
+/**
+ * ev_int_set_mask - sets the mask for the specified interrupt source
+ * @interrupt: the interrupt number
+ * @mask: 0=enable interrupts, 1=disable interrupts
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_set_mask(unsigned int interrupt,
+ unsigned int mask)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK);
+ r3 = interrupt;
+ r4 = mask;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ return r3;
+}
+
+/**
+ * ev_int_get_mask - returns the mask for the specified interrupt source
+ * @interrupt: the interrupt number
+ * @mask: returned mask for this interrupt (0=enabled, 1=disabled)
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_get_mask(unsigned int interrupt,
+ unsigned int *mask)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
+ r3 = interrupt;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "=r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ *mask = r4;
+
+ return r3;
+}
+
+/**
+ * ev_int_eoi - signal the end of interrupt processing
+ * @interrupt: the interrupt number
+ *
+ * This function signals the end of processing for the the specified
+ * interrupt, which must be the interrupt currently in service. By
+ * definition, this is also the highest-priority interrupt.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_eoi(unsigned int interrupt)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = EV_HCALL_TOKEN(EV_INT_EOI);
+ r3 = interrupt;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+/**
+ * ev_byte_channel_send - send characters to a byte stream
+ * @handle: byte stream handle
+ * @count: (input) num of chars to send, (output) num chars sent
+ * @buffer: pointer to a 16-byte buffer
+ *
+ * @buffer must be at least 16 bytes long, because all 16 bytes will be
+ * read from memory into registers, even if count < 16.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_byte_channel_send(unsigned int handle,
+ unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r6 __asm__("r6");
+ register uintptr_t r7 __asm__("r7");
+ register uintptr_t r8 __asm__("r8");
+ const uint32_t *p = (const uint32_t *) buffer;
+
+ r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND);
+ r3 = handle;
+ r4 = *count;
+ r5 = be32_to_cpu(p[0]);
+ r6 = be32_to_cpu(p[1]);
+ r7 = be32_to_cpu(p[2]);
+ r8 = be32_to_cpu(p[3]);
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3),
+ "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
+ : : EV_HCALL_CLOBBERS6
+ );
+
+ *count = r4;
+
+ return r3;
+}
+
+/**
+ * ev_byte_channel_receive - fetch characters from a byte channel
+ * @handle: byte channel handle
+ * @count: (input) max num of chars to receive, (output) num chars received
+ * @buffer: pointer to a 16-byte buffer
+ *
+ * The size of @buffer must be at least 16 bytes, even if you request fewer
+ * than 16 characters, because we always write 16 bytes to @buffer. This is
+ * for performance reasons.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_byte_channel_receive(unsigned int handle,
+ unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r6 __asm__("r6");
+ register uintptr_t r7 __asm__("r7");
+ register uintptr_t r8 __asm__("r8");
+ uint32_t *p = (uint32_t *) buffer;
+
+ r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE);
+ r3 = handle;
+ r4 = *count;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4),
+ "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
+ : : EV_HCALL_CLOBBERS6
+ );
+
+ *count = r4;
+ p[0] = cpu_to_be32(r5);
+ p[1] = cpu_to_be32(r6);
+ p[2] = cpu_to_be32(r7);
+ p[3] = cpu_to_be32(r8);
+
+ return r3;
+}
+
+/**
+ * ev_byte_channel_poll - returns the status of the byte channel buffers
+ * @handle: byte channel handle
+ * @rx_count: returned count of bytes in receive queue
+ * @tx_count: returned count of free space in transmit queue
+ *
+ * This function reports the amount of data in the receive queue (i.e. the
+ * number of bytes you can read), and the amount of free space in the transmit
+ * queue (i.e. the number of bytes you can write).
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_byte_channel_poll(unsigned int handle,
+ unsigned int *rx_count, unsigned int *tx_count)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+
+ r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
+ r3 = handle;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
+ : : EV_HCALL_CLOBBERS3
+ );
+
+ *rx_count = r4;
+ *tx_count = r5;
+
+ return r3;
+}
+
+/**
+ * ev_int_iack - acknowledge an interrupt
+ * @handle: handle to the target interrupt controller
+ * @vector: returned interrupt vector
+ *
+ * If handle is zero, the function returns the next interrupt source
+ * number to be handled irrespective of the hierarchy or cascading
+ * of interrupt controllers. If non-zero, specifies a handle to the
+ * interrupt controller that is the target of the acknowledge.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_iack(unsigned int handle,
+ unsigned int *vector)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = EV_HCALL_TOKEN(EV_INT_IACK);
+ r3 = handle;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "=r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ *vector = r4;
+
+ return r3;
+}
+
+/**
+ * ev_doorbell_send - send a doorbell to another partition
+ * @handle: doorbell send handle
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_doorbell_send(unsigned int handle)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
+ r3 = handle;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+/**
+ * ev_idle -- wait for next interrupt on this core
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_idle(void)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = EV_HCALL_TOKEN(EV_IDLE);
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "=r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+#endif
diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index 6d53f311d942..ac13addb8495 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -48,30 +48,33 @@
#define EX_R14 (4 * 8)
#define EX_R15 (5 * 8)
-/* The TLB miss exception uses different slots */
+/*
+ * The TLB miss exception uses different slots.
+ *
+ * The bolted variant uses only the first six fields,
+ * which in combination with pgd and kernel_pgd fits in
+ * one 64-byte cache line.
+ */
#define EX_TLB_R10 ( 0 * 8)
#define EX_TLB_R11 ( 1 * 8)
-#define EX_TLB_R12 ( 2 * 8)
-#define EX_TLB_R13 ( 3 * 8)
-#define EX_TLB_R14 ( 4 * 8)
-#define EX_TLB_R15 ( 5 * 8)
-#define EX_TLB_R16 ( 6 * 8)
-#define EX_TLB_CR ( 7 * 8)
+#define EX_TLB_R14 ( 2 * 8)
+#define EX_TLB_R15 ( 3 * 8)
+#define EX_TLB_R16 ( 4 * 8)
+#define EX_TLB_CR ( 5 * 8)
+#define EX_TLB_R12 ( 6 * 8)
+#define EX_TLB_R13 ( 7 * 8)
#define EX_TLB_DEAR ( 8 * 8) /* Level 0 and 2 only */
#define EX_TLB_ESR ( 9 * 8) /* Level 0 and 2 only */
#define EX_TLB_SRR0 (10 * 8)
#define EX_TLB_SRR1 (11 * 8)
-#define EX_TLB_MMUCR0 (12 * 8) /* Level 0 */
-#define EX_TLB_MAS1 (12 * 8) /* Level 0 */
-#define EX_TLB_MAS2 (13 * 8) /* Level 0 */
#ifdef CONFIG_BOOK3E_MMU_TLB_STATS
-#define EX_TLB_R8 (14 * 8)
-#define EX_TLB_R9 (15 * 8)
-#define EX_TLB_LR (16 * 8)
-#define EX_TLB_SIZE (17 * 8)
+#define EX_TLB_R8 (12 * 8)
+#define EX_TLB_R9 (13 * 8)
+#define EX_TLB_LR (14 * 8)
+#define EX_TLB_SIZE (15 * 8)
#else
-#define EX_TLB_SIZE (14 * 8)
+#define EX_TLB_SIZE (12 * 8)
#endif
#define START_EXCEPTION(label) \
@@ -168,6 +171,16 @@ exc_##label##_book3e:
ld r9,EX_TLB_R9(r12); \
ld r8,EX_TLB_R8(r12); \
mtlr r16;
+#define TLB_MISS_PROLOG_STATS_BOLTED \
+ mflr r10; \
+ std r8,PACA_EXTLB+EX_TLB_R8(r13); \
+ std r9,PACA_EXTLB+EX_TLB_R9(r13); \
+ std r10,PACA_EXTLB+EX_TLB_LR(r13);
+#define TLB_MISS_RESTORE_STATS_BOLTED \
+ ld r16,PACA_EXTLB+EX_TLB_LR(r13); \
+ ld r9,PACA_EXTLB+EX_TLB_R9(r13); \
+ ld r8,PACA_EXTLB+EX_TLB_R8(r13); \
+ mtlr r16;
#define TLB_MISS_STATS_D(name) \
addi r9,r13,MMSTAT_DSTATS+name; \
bl .tlb_stat_inc;
@@ -183,17 +196,20 @@ exc_##label##_book3e:
61: addi r9,r13,MMSTAT_ISTATS+name; \
62: bl .tlb_stat_inc;
#define TLB_MISS_STATS_SAVE_INFO \
- std r14,EX_TLB_ESR(r12); /* save ESR */ \
-
-
+ std r14,EX_TLB_ESR(r12); /* save ESR */
+#define TLB_MISS_STATS_SAVE_INFO_BOLTED \
+ std r14,PACA_EXTLB+EX_TLB_ESR(r13); /* save ESR */
#else
#define TLB_MISS_PROLOG_STATS
#define TLB_MISS_RESTORE_STATS
+#define TLB_MISS_PROLOG_STATS_BOLTED
+#define TLB_MISS_RESTORE_STATS_BOLTED
#define TLB_MISS_STATS_D(name)
#define TLB_MISS_STATS_I(name)
#define TLB_MISS_STATS_X(name)
#define TLB_MISS_STATS_Y(name)
#define TLB_MISS_STATS_SAVE_INFO
+#define TLB_MISS_STATS_SAVE_INFO_BOLTED
#endif
#define SET_IVOR(vector_number, vector_offset) \
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index f5dfe3411f64..8057f4f6980f 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -61,19 +61,22 @@
#define EXC_HV H
#define EXC_STD
-#define EXCEPTION_PROLOG_1(area) \
+#define __EXCEPTION_PROLOG_1(area, extra, vec) \
GET_PACA(r13); \
std r9,area+EX_R9(r13); /* save r9 - r12 */ \
std r10,area+EX_R10(r13); \
- std r11,area+EX_R11(r13); \
- std r12,area+EX_R12(r13); \
BEGIN_FTR_SECTION_NESTED(66); \
mfspr r10,SPRN_CFAR; \
std r10,area+EX_CFAR(r13); \
END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \
- GET_SCRATCH0(r9); \
- std r9,area+EX_R13(r13); \
- mfcr r9
+ mfcr r9; \
+ extra(vec); \
+ std r11,area+EX_R11(r13); \
+ std r12,area+EX_R12(r13); \
+ GET_SCRATCH0(r10); \
+ std r10,area+EX_R13(r13)
+#define EXCEPTION_PROLOG_1(area, extra, vec) \
+ __EXCEPTION_PROLOG_1(area, extra, vec)
#define __EXCEPTION_PROLOG_PSERIES_1(label, h) \
ld r12,PACAKBASE(r13); /* get high part of &label */ \
@@ -85,13 +88,65 @@
mtspr SPRN_##h##SRR1,r10; \
h##rfid; \
b . /* prevent speculative execution */
-#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
+#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
__EXCEPTION_PROLOG_PSERIES_1(label, h)
-#define EXCEPTION_PROLOG_PSERIES(area, label, h) \
- EXCEPTION_PROLOG_1(area); \
+#define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec) \
+ EXCEPTION_PROLOG_1(area, extra, vec); \
EXCEPTION_PROLOG_PSERIES_1(label, h);
+#define __KVMTEST(n) \
+ lbz r10,HSTATE_IN_GUEST(r13); \
+ cmpwi r10,0; \
+ bne do_kvm_##n
+
+#define __KVM_HANDLER(area, h, n) \
+do_kvm_##n: \
+ ld r10,area+EX_R10(r13); \
+ stw r9,HSTATE_SCRATCH1(r13); \
+ ld r9,area+EX_R9(r13); \
+ std r12,HSTATE_SCRATCH0(r13); \
+ li r12,n; \
+ b kvmppc_interrupt
+
+#define __KVM_HANDLER_SKIP(area, h, n) \
+do_kvm_##n: \
+ cmpwi r10,KVM_GUEST_MODE_SKIP; \
+ ld r10,area+EX_R10(r13); \
+ beq 89f; \
+ stw r9,HSTATE_SCRATCH1(r13); \
+ ld r9,area+EX_R9(r13); \
+ std r12,HSTATE_SCRATCH0(r13); \
+ li r12,n; \
+ b kvmppc_interrupt; \
+89: mtocrf 0x80,r9; \
+ ld r9,area+EX_R9(r13); \
+ b kvmppc_skip_##h##interrupt
+
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#define KVMTEST(n) __KVMTEST(n)
+#define KVM_HANDLER(area, h, n) __KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_SKIP(area, h, n) __KVM_HANDLER_SKIP(area, h, n)
+
+#else
+#define KVMTEST(n)
+#define KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_SKIP(area, h, n)
+#endif
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+#define KVMTEST_PR(n) __KVMTEST(n)
+#define KVM_HANDLER_PR(area, h, n) __KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_PR_SKIP(area, h, n) __KVM_HANDLER_SKIP(area, h, n)
+
+#else
+#define KVMTEST_PR(n)
+#define KVM_HANDLER_PR(area, h, n)
+#define KVM_HANDLER_PR_SKIP(area, h, n)
+#endif
+
+#define NOTEST(n)
+
/*
* The common exception prolog is used for all except a few exceptions
* such as a segment miss on a kernel address. We have to be prepared
@@ -164,57 +219,58 @@
.globl label##_pSeries; \
label##_pSeries: \
HMT_MEDIUM; \
- DO_KVM vec; \
SET_SCRATCH0(r13); /* save r13 */ \
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD)
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
+ EXC_STD, KVMTEST_PR, vec)
#define STD_EXCEPTION_HV(loc, vec, label) \
. = loc; \
.globl label##_hv; \
label##_hv: \
HMT_MEDIUM; \
- DO_KVM vec; \
- SET_SCRATCH0(r13); /* save r13 */ \
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV)
+ SET_SCRATCH0(r13); /* save r13 */ \
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
+ EXC_HV, KVMTEST, vec)
-#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h) \
- HMT_MEDIUM; \
- DO_KVM vec; \
- SET_SCRATCH0(r13); /* save r13 */ \
- GET_PACA(r13); \
- std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \
- std r10,PACA_EXGEN+EX_R10(r13); \
+#define __SOFTEN_TEST(h) \
lbz r10,PACASOFTIRQEN(r13); \
- mfcr r9; \
cmpwi r10,0; \
- beq masked_##h##interrupt; \
- GET_SCRATCH0(r10); \
- std r10,PACA_EXGEN+EX_R13(r13); \
- std r11,PACA_EXGEN+EX_R11(r13); \
- std r12,PACA_EXGEN+EX_R12(r13); \
- ld r12,PACAKBASE(r13); /* get high part of &label */ \
- ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \
- mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \
- LOAD_HANDLER(r12,label##_common) \
- mtspr SPRN_##h##SRR0,r12; \
- mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \
- mtspr SPRN_##h##SRR1,r10; \
- h##rfid; \
- b . /* prevent speculative execution */
-#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h) \
- __MASKABLE_EXCEPTION_PSERIES(vec, label, h)
+ beq masked_##h##interrupt
+#define _SOFTEN_TEST(h) __SOFTEN_TEST(h)
+
+#define SOFTEN_TEST_PR(vec) \
+ KVMTEST_PR(vec); \
+ _SOFTEN_TEST(EXC_STD)
+
+#define SOFTEN_TEST_HV(vec) \
+ KVMTEST(vec); \
+ _SOFTEN_TEST(EXC_HV)
+
+#define SOFTEN_TEST_HV_201(vec) \
+ KVMTEST(vec); \
+ _SOFTEN_TEST(EXC_STD)
+
+#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \
+ HMT_MEDIUM; \
+ SET_SCRATCH0(r13); /* save r13 */ \
+ __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \
+ EXCEPTION_PROLOG_PSERIES_1(label##_common, h);
+#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \
+ __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)
#define MASKABLE_EXCEPTION_PSERIES(loc, vec, label) \
. = loc; \
.globl label##_pSeries; \
label##_pSeries: \
- _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_STD)
+ _MASKABLE_EXCEPTION_PSERIES(vec, label, \
+ EXC_STD, SOFTEN_TEST_PR)
#define MASKABLE_EXCEPTION_HV(loc, vec, label) \
. = loc; \
.globl label##_hv; \
label##_hv: \
- _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_HV)
+ _MASKABLE_EXCEPTION_PSERIES(vec, label, \
+ EXC_HV, SOFTEN_TEST_HV)
#ifdef CONFIG_PPC_ISERIES
#define DISABLE_INTS \
diff --git a/arch/powerpc/include/asm/fsl_hcalls.h b/arch/powerpc/include/asm/fsl_hcalls.h
new file mode 100644
index 000000000000..922d9b5fe3d5
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_hcalls.h
@@ -0,0 +1,655 @@
+/*
+ * Freescale hypervisor call interface
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is provided under a dual BSD/GPL license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * 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 of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 _FSL_HCALLS_H
+#define _FSL_HCALLS_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+#include <asm/epapr_hcalls.h>
+
+#define FH_API_VERSION 1
+
+#define FH_ERR_GET_INFO 1
+#define FH_PARTITION_GET_DTPROP 2
+#define FH_PARTITION_SET_DTPROP 3
+#define FH_PARTITION_RESTART 4
+#define FH_PARTITION_GET_STATUS 5
+#define FH_PARTITION_START 6
+#define FH_PARTITION_STOP 7
+#define FH_PARTITION_MEMCPY 8
+#define FH_DMA_ENABLE 9
+#define FH_DMA_DISABLE 10
+#define FH_SEND_NMI 11
+#define FH_VMPIC_GET_MSIR 12
+#define FH_SYSTEM_RESET 13
+#define FH_GET_CORE_STATE 14
+#define FH_ENTER_NAP 15
+#define FH_EXIT_NAP 16
+#define FH_CLAIM_DEVICE 17
+#define FH_PARTITION_STOP_DMA 18
+
+/* vendor ID: Freescale Semiconductor */
+#define FH_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_FSL_VENDOR_ID, num)
+
+/*
+ * We use "uintptr_t" to define a register because it's guaranteed to be a
+ * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
+ * platform.
+ *
+ * All registers are either input/output or output only. Registers that are
+ * initialized before making the hypercall are input/output. All
+ * input/output registers are represented with "+r". Output-only registers
+ * are represented with "=r". Do not specify any unused registers. The
+ * clobber list will tell the compiler that the hypercall modifies those
+ * registers, which is good enough.
+ */
+
+/**
+ * fh_send_nmi - send NMI to virtual cpu(s).
+ * @vcpu_mask: send NMI to virtual cpu(s) specified by this mask.
+ *
+ * Returns 0 for success, or EINVAL for invalid vcpu_mask.
+ */
+static inline unsigned int fh_send_nmi(unsigned int vcpu_mask)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_SEND_NMI);
+ r3 = vcpu_mask;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+/* Arbitrary limits to avoid excessive memory allocation in hypervisor */
+#define FH_DTPROP_MAX_PATHLEN 4096
+#define FH_DTPROP_MAX_PROPLEN 32768
+
+/**
+ * fh_partiton_get_dtprop - get a property from a guest device tree.
+ * @handle: handle of partition whose device tree is to be accessed
+ * @dtpath_addr: physical address of device tree path to access
+ * @propname_addr: physical address of name of property
+ * @propvalue_addr: physical address of property value buffer
+ * @propvalue_len: length of buffer on entry, length of property on return
+ *
+ * Returns zero on success, non-zero on error.
+ */
+static inline unsigned int fh_partition_get_dtprop(int handle,
+ uint64_t dtpath_addr,
+ uint64_t propname_addr,
+ uint64_t propvalue_addr,
+ uint32_t *propvalue_len)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r6 __asm__("r6");
+ register uintptr_t r7 __asm__("r7");
+ register uintptr_t r8 __asm__("r8");
+ register uintptr_t r9 __asm__("r9");
+ register uintptr_t r10 __asm__("r10");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_DTPROP);
+ r3 = handle;
+
+#ifdef CONFIG_PHYS_64BIT
+ r4 = dtpath_addr >> 32;
+ r6 = propname_addr >> 32;
+ r8 = propvalue_addr >> 32;
+#else
+ r4 = 0;
+ r6 = 0;
+ r8 = 0;
+#endif
+ r5 = (uint32_t)dtpath_addr;
+ r7 = (uint32_t)propname_addr;
+ r9 = (uint32_t)propvalue_addr;
+ r10 = *propvalue_len;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11),
+ "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
+ "+r" (r8), "+r" (r9), "+r" (r10)
+ : : EV_HCALL_CLOBBERS8
+ );
+
+ *propvalue_len = r4;
+ return r3;
+}
+
+/**
+ * Set a property in a guest device tree.
+ * @handle: handle of partition whose device tree is to be accessed
+ * @dtpath_addr: physical address of device tree path to access
+ * @propname_addr: physical address of name of property
+ * @propvalue_addr: physical address of property value
+ * @propvalue_len: length of property
+ *
+ * Returns zero on success, non-zero on error.
+ */
+static inline unsigned int fh_partition_set_dtprop(int handle,
+ uint64_t dtpath_addr,
+ uint64_t propname_addr,
+ uint64_t propvalue_addr,
+ uint32_t propvalue_len)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r6 __asm__("r6");
+ register uintptr_t r8 __asm__("r8");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r7 __asm__("r7");
+ register uintptr_t r9 __asm__("r9");
+ register uintptr_t r10 __asm__("r10");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_SET_DTPROP);
+ r3 = handle;
+
+#ifdef CONFIG_PHYS_64BIT
+ r4 = dtpath_addr >> 32;
+ r6 = propname_addr >> 32;
+ r8 = propvalue_addr >> 32;
+#else
+ r4 = 0;
+ r6 = 0;
+ r8 = 0;
+#endif
+ r5 = (uint32_t)dtpath_addr;
+ r7 = (uint32_t)propname_addr;
+ r9 = (uint32_t)propvalue_addr;
+ r10 = propvalue_len;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11),
+ "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
+ "+r" (r8), "+r" (r9), "+r" (r10)
+ : : EV_HCALL_CLOBBERS8
+ );
+
+ return r3;
+}
+
+/**
+ * fh_partition_restart - reboot the current partition
+ * @partition: partition ID
+ *
+ * Returns an error code if reboot failed. Does not return if it succeeds.
+ */
+static inline unsigned int fh_partition_restart(unsigned int partition)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART);
+ r3 = partition;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+#define FH_PARTITION_STOPPED 0
+#define FH_PARTITION_RUNNING 1
+#define FH_PARTITION_STARTING 2
+#define FH_PARTITION_STOPPING 3
+#define FH_PARTITION_PAUSING 4
+#define FH_PARTITION_PAUSED 5
+#define FH_PARTITION_RESUMING 6
+
+/**
+ * fh_partition_get_status - gets the status of a partition
+ * @partition: partition ID
+ * @status: returned status code
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_get_status(unsigned int partition,
+ unsigned int *status)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS);
+ r3 = partition;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "=r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ *status = r4;
+
+ return r3;
+}
+
+/**
+ * fh_partition_start - boots and starts execution of the specified partition
+ * @partition: partition ID
+ * @entry_point: guest physical address to start execution
+ *
+ * The hypervisor creates a 1-to-1 virtual/physical IMA mapping, so at boot
+ * time, guest physical address are the same as guest virtual addresses.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_start(unsigned int partition,
+ uint32_t entry_point, int load)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_START);
+ r3 = partition;
+ r4 = entry_point;
+ r5 = load;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5)
+ : : EV_HCALL_CLOBBERS3
+ );
+
+ return r3;
+}
+
+/**
+ * fh_partition_stop - stops another partition
+ * @partition: partition ID
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_stop(unsigned int partition)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP);
+ r3 = partition;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+/**
+ * struct fh_sg_list: definition of the fh_partition_memcpy S/G list
+ * @source: guest physical address to copy from
+ * @target: guest physical address to copy to
+ * @size: number of bytes to copy
+ * @reserved: reserved, must be zero
+ *
+ * The scatter/gather list for fh_partition_memcpy() is an array of these
+ * structures. The array must be guest physically contiguous.
+ *
+ * This structure must be aligned on 32-byte boundary, so that no single
+ * strucuture can span two pages.
+ */
+struct fh_sg_list {
+ uint64_t source; /**< guest physical address to copy from */
+ uint64_t target; /**< guest physical address to copy to */
+ uint64_t size; /**< number of bytes to copy */
+ uint64_t reserved; /**< reserved, must be zero */
+} __attribute__ ((aligned(32)));
+
+/**
+ * fh_partition_memcpy - copies data from one guest to another
+ * @source: the ID of the partition to copy from
+ * @target: the ID of the partition to copy to
+ * @sg_list: guest physical address of an array of &fh_sg_list structures
+ * @count: the number of entries in @sg_list
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_memcpy(unsigned int source,
+ unsigned int target, phys_addr_t sg_list, unsigned int count)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r6 __asm__("r6");
+ register uintptr_t r7 __asm__("r7");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_MEMCPY);
+ r3 = source;
+ r4 = target;
+ r5 = (uint32_t) sg_list;
+
+#ifdef CONFIG_PHYS_64BIT
+ r6 = sg_list >> 32;
+#else
+ r6 = 0;
+#endif
+ r7 = count;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11),
+ "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7)
+ : : EV_HCALL_CLOBBERS5
+ );
+
+ return r3;
+}
+
+/**
+ * fh_dma_enable - enable DMA for the specified device
+ * @liodn: the LIODN of the I/O device for which to enable DMA
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_dma_enable(unsigned int liodn)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE);
+ r3 = liodn;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+/**
+ * fh_dma_disable - disable DMA for the specified device
+ * @liodn: the LIODN of the I/O device for which to disable DMA
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_dma_disable(unsigned int liodn)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE);
+ r3 = liodn;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+
+/**
+ * fh_vmpic_get_msir - returns the MPIC-MSI register value
+ * @interrupt: the interrupt number
+ * @msir_val: returned MPIC-MSI register value
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt,
+ unsigned int *msir_val)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR);
+ r3 = interrupt;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "=r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ *msir_val = r4;
+
+ return r3;
+}
+
+/**
+ * fh_system_reset - reset the system
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_system_reset(void)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET);
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "=r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+
+/**
+ * fh_err_get_info - get platform error information
+ * @queue id:
+ * 0 for guest error event queue
+ * 1 for global error event queue
+ *
+ * @pointer to store the platform error data:
+ * platform error data is returned in registers r4 - r11
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize,
+ uint32_t addr_hi, uint32_t addr_lo, int peek)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+ register uintptr_t r5 __asm__("r5");
+ register uintptr_t r6 __asm__("r6");
+ register uintptr_t r7 __asm__("r7");
+
+ r11 = FH_HCALL_TOKEN(FH_ERR_GET_INFO);
+ r3 = queue;
+ r4 = *bufsize;
+ r5 = addr_hi;
+ r6 = addr_lo;
+ r7 = peek;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6),
+ "+r" (r7)
+ : : EV_HCALL_CLOBBERS5
+ );
+
+ *bufsize = r4;
+
+ return r3;
+}
+
+
+#define FH_VCPU_RUN 0
+#define FH_VCPU_IDLE 1
+#define FH_VCPU_NAP 2
+
+/**
+ * fh_get_core_state - get the state of a vcpu
+ *
+ * @handle: handle of partition containing the vcpu
+ * @vcpu: vcpu number within the partition
+ * @state:the current state of the vcpu, see FH_VCPU_*
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_get_core_state(unsigned int handle,
+ unsigned int vcpu, unsigned int *state)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = FH_HCALL_TOKEN(FH_GET_CORE_STATE);
+ r3 = handle;
+ r4 = vcpu;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ *state = r4;
+ return r3;
+}
+
+/**
+ * fh_enter_nap - enter nap on a vcpu
+ *
+ * Note that though the API supports entering nap on a vcpu other
+ * than the caller, this may not be implmented and may return EINVAL.
+ *
+ * @handle: handle of partition containing the vcpu
+ * @vcpu: vcpu number within the partition
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = FH_HCALL_TOKEN(FH_ENTER_NAP);
+ r3 = handle;
+ r4 = vcpu;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ return r3;
+}
+
+/**
+ * fh_exit_nap - exit nap on a vcpu
+ * @handle: handle of partition containing the vcpu
+ * @vcpu: vcpu number within the partition
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+ register uintptr_t r4 __asm__("r4");
+
+ r11 = FH_HCALL_TOKEN(FH_EXIT_NAP);
+ r3 = handle;
+ r4 = vcpu;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3), "+r" (r4)
+ : : EV_HCALL_CLOBBERS2
+ );
+
+ return r3;
+}
+/**
+ * fh_claim_device - claim a "claimable" shared device
+ * @handle: fsl,hv-device-handle of node to claim
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_claim_device(unsigned int handle)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE);
+ r3 = handle;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+
+/**
+ * Run deferred DMA disabling on a partition's private devices
+ *
+ * This applies to devices which a partition owns either privately,
+ * or which are claimable and still actively owned by that partition,
+ * and which do not have the no-dma-disable property.
+ *
+ * @handle: partition (must be stopped) whose DMA is to be disabled
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_stop_dma(unsigned int handle)
+{
+ register uintptr_t r11 __asm__("r11");
+ register uintptr_t r3 __asm__("r3");
+
+ r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA);
+ r3 = handle;
+
+ __asm__ __volatile__ ("sc 1"
+ : "+r" (r11), "+r" (r3)
+ : : EV_HCALL_CLOBBERS1
+ );
+
+ return r3;
+}
+#endif
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index fd8201dddd4b..1c324ff55ea8 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -29,6 +29,10 @@
#define H_LONG_BUSY_ORDER_100_SEC 9905 /* Long busy, hint that 100sec \
is a good time to retry */
#define H_LONG_BUSY_END_RANGE 9905 /* End of long busy range */
+
+/* Internal value used in book3s_hv kvm support; not returned to guests */
+#define H_TOO_HARD 9999
+
#define H_HARDWARE -1 /* Hardware error */
#define H_FUNCTION -2 /* Function not supported */
#define H_PRIVILEGE -3 /* Caller not privileged */
@@ -100,6 +104,7 @@
#define H_PAGE_SET_ACTIVE H_PAGE_STATE_CHANGE
#define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */
#define H_ANDCOND (1UL<<(63-33))
+#define H_LOCAL (1UL<<(63-35))
#define H_ICACHE_INVALIDATE (1UL<<(63-40)) /* icbi, etc. (ignored for IO pages) */
#define H_ICACHE_SYNCHRONIZE (1UL<<(63-41)) /* dcbst, icbi, etc (ignored for IO pages */
#define H_COALESCE_CAND (1UL<<(63-42)) /* page is a good candidate for coalescing */
diff --git a/arch/powerpc/include/asm/hvsi.h b/arch/powerpc/include/asm/hvsi.h
new file mode 100644
index 000000000000..d3f64f361814
--- /dev/null
+++ b/arch/powerpc/include/asm/hvsi.h
@@ -0,0 +1,94 @@
+#ifndef _HVSI_H
+#define _HVSI_H
+
+#define VS_DATA_PACKET_HEADER 0xff
+#define VS_CONTROL_PACKET_HEADER 0xfe
+#define VS_QUERY_PACKET_HEADER 0xfd
+#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
+
+/* control verbs */
+#define VSV_SET_MODEM_CTL 1 /* to service processor only */
+#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
+#define VSV_CLOSE_PROTOCOL 3
+
+/* query verbs */
+#define VSV_SEND_VERSION_NUMBER 1
+#define VSV_SEND_MODEM_CTL_STATUS 2
+
+/* yes, these masks are not consecutive. */
+#define HVSI_TSDTR 0x01
+#define HVSI_TSCD 0x20
+
+#define HVSI_MAX_OUTGOING_DATA 12
+#define HVSI_VERSION 1
+
+struct hvsi_header {
+ uint8_t type;
+ uint8_t len;
+ uint16_t seqno;
+} __attribute__((packed));
+
+struct hvsi_data {
+ struct hvsi_header hdr;
+ uint8_t data[HVSI_MAX_OUTGOING_DATA];
+} __attribute__((packed));
+
+struct hvsi_control {
+ struct hvsi_header hdr;
+ uint16_t verb;
+ /* optional depending on verb: */
+ uint32_t word;
+ uint32_t mask;
+} __attribute__((packed));
+
+struct hvsi_query {
+ struct hvsi_header hdr;
+ uint16_t verb;
+} __attribute__((packed));
+
+struct hvsi_query_response {
+ struct hvsi_header hdr;
+ uint16_t verb;
+ uint16_t query_seqno;
+ union {
+ uint8_t version;
+ uint32_t mctrl_word;
+ } u;
+} __attribute__((packed));
+
+/* hvsi lib struct definitions */
+#define HVSI_INBUF_SIZE 255
+struct tty_struct;
+struct hvsi_priv {
+ unsigned int inbuf_len; /* data in input buffer */
+ unsigned char inbuf[HVSI_INBUF_SIZE];
+ unsigned int inbuf_cur; /* Cursor in input buffer */
+ unsigned int inbuf_pktlen; /* packet lenght from cursor */
+ atomic_t seqno; /* packet sequence number */
+ unsigned int opened:1; /* driver opened */
+ unsigned int established:1; /* protocol established */
+ unsigned int is_console:1; /* used as a kernel console device */
+ unsigned int mctrl_update:1; /* modem control updated */
+ unsigned short mctrl; /* modem control */
+ struct tty_struct *tty; /* tty structure */
+ int (*get_chars)(uint32_t termno, char *buf, int count);
+ int (*put_chars)(uint32_t termno, const char *buf, int count);
+ uint32_t termno;
+};
+
+/* hvsi lib functions */
+struct hvc_struct;
+extern void hvsilib_init(struct hvsi_priv *pv,
+ int (*get_chars)(uint32_t termno, char *buf, int count),
+ int (*put_chars)(uint32_t termno, const char *buf,
+ int count),
+ int termno, int is_console);
+extern int hvsilib_open(struct hvsi_priv *pv, struct hvc_struct *hp);
+extern void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp);
+extern int hvsilib_read_mctrl(struct hvsi_priv *pv);
+extern int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr);
+extern void hvsilib_establish(struct hvsi_priv *pv);
+extern int hvsilib_get_chars(struct hvsi_priv *pv, char *buf, int count);
+extern int hvsilib_put_chars(struct hvsi_priv *pv, const char *buf, int count);
+
+#endif /* _HVSI_H */
diff --git a/arch/powerpc/include/asm/hw_breakpoint.h b/arch/powerpc/include/asm/hw_breakpoint.h
index 1c33ec17ca36..80fd4d2b4a62 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -57,7 +57,7 @@ void hw_breakpoint_pmu_read(struct perf_event *bp);
extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
extern struct pmu perf_ops_bp;
-extern void ptrace_triggered(struct perf_event *bp, int nmi,
+extern void ptrace_triggered(struct perf_event *bp,
struct perf_sample_data *data, struct pt_regs *regs);
static inline void hw_breakpoint_disable(void)
{
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index 1bff591f7f72..c0e1bc319e35 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -14,7 +14,7 @@
#include <linux/radix-tree.h>
#include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/* Define a way to iterate across irqs. */
@@ -330,5 +330,7 @@ extern int call_handle_irq(int irq, void *p1,
struct thread_info *tp, void *func);
extern void do_IRQ(struct pt_regs *regs);
+int irq_choose_cpu(const struct cpumask *mask);
+
#endif /* _ASM_IRQ_H */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
new file mode 100644
index 000000000000..1f780b95c0f0
--- /dev/null
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -0,0 +1,47 @@
+#ifndef _ASM_POWERPC_JUMP_LABEL_H
+#define _ASM_POWERPC_JUMP_LABEL_H
+
+/*
+ * Copyright 2010 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+
+#include <asm/feature-fixups.h>
+
+#define JUMP_ENTRY_TYPE stringify_in_c(FTR_ENTRY_LONG)
+#define JUMP_LABEL_NOP_SIZE 4
+
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+ asm goto("1:\n\t"
+ "nop\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ ".align 4\n\t"
+ JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
+ ".popsection \n\t"
+ : : "i" (key) : : l_yes);
+ return false;
+l_yes:
+ return true;
+}
+
+#ifdef CONFIG_PPC64
+typedef u64 jump_label_t;
+#else
+typedef u32 jump_label_t;
+#endif
+
+struct jump_entry {
+ jump_label_t code;
+ jump_label_t target;
+ jump_label_t key;
+ jump_label_t pad;
+};
+
+#endif /* _ASM_POWERPC_JUMP_LABEL_H */
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index d2ca5ed3877b..a4f6c85431f8 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -22,6 +22,10 @@
#include <linux/types.h>
+/* Select powerpc specific features in <linux/kvm.h> */
+#define __KVM_HAVE_SPAPR_TCE
+#define __KVM_HAVE_PPC_SMT
+
struct kvm_regs {
__u64 pc;
__u64 cr;
@@ -272,4 +276,15 @@ struct kvm_guest_debug_arch {
#define KVM_INTERRUPT_UNSET -2U
#define KVM_INTERRUPT_SET_LEVEL -3U
+/* for KVM_CAP_SPAPR_TCE */
+struct kvm_create_spapr_tce {
+ __u64 liobn;
+ __u32 window_size;
+};
+
+/* for KVM_ALLOCATE_RMA */
+struct kvm_allocate_rma {
+ __u64 rma_size;
+};
+
#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index 0951b17f4eb5..7b1f0e0fc653 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -64,8 +64,12 @@
#define BOOK3S_INTERRUPT_PROGRAM 0x700
#define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800
#define BOOK3S_INTERRUPT_DECREMENTER 0x900
+#define BOOK3S_INTERRUPT_HV_DECREMENTER 0x980
#define BOOK3S_INTERRUPT_SYSCALL 0xc00
#define BOOK3S_INTERRUPT_TRACE 0xd00
+#define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00
+#define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20
+#define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40
#define BOOK3S_INTERRUPT_PERFMON 0xf00
#define BOOK3S_INTERRUPT_ALTIVEC 0xf20
#define BOOK3S_INTERRUPT_VSX 0xf40
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index d62e703f1214..98da010252a3 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -24,20 +24,6 @@
#include <linux/kvm_host.h>
#include <asm/kvm_book3s_asm.h>
-struct kvmppc_slb {
- u64 esid;
- u64 vsid;
- u64 orige;
- u64 origv;
- bool valid : 1;
- bool Ks : 1;
- bool Kp : 1;
- bool nx : 1;
- bool large : 1; /* PTEs are 16MB */
- bool tb : 1; /* 1TB segment */
- bool class : 1;
-};
-
struct kvmppc_bat {
u64 raw;
u32 bepi;
@@ -67,11 +53,22 @@ struct kvmppc_sid_map {
#define VSID_POOL_SIZE (SID_CONTEXTS * 16)
#endif
+struct hpte_cache {
+ struct hlist_node list_pte;
+ struct hlist_node list_pte_long;
+ struct hlist_node list_vpte;
+ struct hlist_node list_vpte_long;
+ struct rcu_head rcu_head;
+ u64 host_va;
+ u64 pfn;
+ ulong slot;
+ struct kvmppc_pte pte;
+};
+
struct kvmppc_vcpu_book3s {
struct kvm_vcpu vcpu;
struct kvmppc_book3s_shadow_vcpu *shadow_vcpu;
struct kvmppc_sid_map sid_map[SID_MAP_NUM];
- struct kvmppc_slb slb[64];
struct {
u64 esid;
u64 vsid;
@@ -81,7 +78,6 @@ struct kvmppc_vcpu_book3s {
struct kvmppc_bat dbat[8];
u64 hid[6];
u64 gqr[8];
- int slb_nr;
u64 sdr1;
u64 hior;
u64 msr_mask;
@@ -93,7 +89,13 @@ struct kvmppc_vcpu_book3s {
u64 vsid_max;
#endif
int context_id[SID_CONTEXTS];
- ulong prog_flags; /* flags to inject when giving a 700 trap */
+
+ 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];
+ struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG];
+ int hpte_cache_count;
+ spinlock_t mmu_lock;
};
#define CONTEXT_HOST 0
@@ -110,8 +112,10 @@ extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong ea, ulong ea_mask)
extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask);
extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end);
extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr);
+extern void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr);
extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu);
extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu);
+extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu);
extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte);
extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr);
extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu);
@@ -123,19 +127,22 @@ extern int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu);
extern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte);
extern int kvmppc_mmu_hpte_sysinit(void);
extern void kvmppc_mmu_hpte_sysexit(void);
+extern int kvmppc_mmu_hv_init(void);
extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
+extern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags);
extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
bool upper, u32 val);
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 ulong kvmppc_trampoline_lowmem;
-extern ulong kvmppc_trampoline_enter;
+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_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);
@@ -147,15 +154,32 @@ static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
return container_of(vcpu, struct kvmppc_vcpu_book3s, vcpu);
}
-static inline ulong dsisr(void)
+extern void kvm_return_point(void);
+
+/* Also add subarch specific defines */
+
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
+#include <asm/kvm_book3s_32.h>
+#endif
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#include <asm/kvm_book3s_64.h>
+#endif
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+
+static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
{
- ulong r;
- asm ( "mfdsisr %0 " : "=r" (r) );
- return r;
+ return to_book3s(vcpu)->hior;
}
-extern void kvm_return_point(void);
-static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu);
+static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
+ unsigned long pending_now, unsigned long old_pending)
+{
+ if (pending_now)
+ vcpu->arch.shared->int_pending = 1;
+ else if (old_pending)
+ vcpu->arch.shared->int_pending = 0;
+}
static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
{
@@ -244,6 +268,120 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
return to_svcpu(vcpu)->fault_dar;
}
+static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
+{
+ ulong crit_raw = vcpu->arch.shared->critical;
+ ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+ bool crit;
+
+ /* Truncate crit indicators in 32 bit mode */
+ if (!(vcpu->arch.shared->msr & MSR_SF)) {
+ crit_raw &= 0xffffffff;
+ crit_r1 &= 0xffffffff;
+ }
+
+ /* Critical section when crit == r1 */
+ crit = (crit_raw == crit_r1);
+ /* ... and we're in supervisor mode */
+ crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
+
+ return crit;
+}
+#else /* CONFIG_KVM_BOOK3S_PR */
+
+static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+
+static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
+ unsigned long pending_now, unsigned long old_pending)
+{
+}
+
+static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
+{
+ vcpu->arch.gpr[num] = val;
+}
+
+static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
+{
+ return vcpu->arch.gpr[num];
+}
+
+static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
+{
+ vcpu->arch.cr = val;
+}
+
+static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.cr;
+}
+
+static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val)
+{
+ vcpu->arch.xer = val;
+}
+
+static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.xer;
+}
+
+static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
+{
+ vcpu->arch.ctr = val;
+}
+
+static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.ctr;
+}
+
+static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val)
+{
+ vcpu->arch.lr = val;
+}
+
+static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.lr;
+}
+
+static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val)
+{
+ vcpu->arch.pc = val;
+}
+
+static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.pc;
+}
+
+static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
+{
+ ulong pc = kvmppc_get_pc(vcpu);
+
+ /* Load the instruction manually if it failed to do so in the
+ * exit path */
+ if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
+ kvmppc_ld(vcpu, &pc, sizeof(u32), &vcpu->arch.last_inst, false);
+
+ return vcpu->arch.last_inst;
+}
+
+static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.fault_dar;
+}
+
+static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+#endif
+
/* Magic register values loaded into r3 and r4 before the 'sc' assembly
* instruction for the OSI hypercalls */
#define OSI_SC_MAGIC_R3 0x113724FA
@@ -251,12 +389,4 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
#define INS_DCBZ 0x7c0007ec
-/* Also add subarch specific defines */
-
-#ifdef CONFIG_PPC_BOOK3S_32
-#include <asm/kvm_book3s_32.h>
-#else
-#include <asm/kvm_book3s_64.h>
-#endif
-
#endif /* __ASM_KVM_BOOK3S_H__ */
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 4cadd612d575..e43fe42b9875 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -20,9 +20,13 @@
#ifndef __ASM_KVM_BOOK3S_64_H__
#define __ASM_KVM_BOOK3S_64_H__
+#ifdef CONFIG_KVM_BOOK3S_PR
static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu)
{
return &get_paca()->shadow_vcpu;
}
+#endif
+
+#define SPAPR_TCE_SHIFT 12
#endif /* __ASM_KVM_BOOK3S_64_H__ */
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index d5a8a3861635..ef7b3688c3b6 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -60,6 +60,36 @@ kvmppc_resume_\intno:
#else /*__ASSEMBLY__ */
+/*
+ * This struct goes in the PACA on 64-bit processors. It is used
+ * to store host state that needs to be saved when we enter a guest
+ * and restored when we exit, but isn't specific to any particular
+ * guest or vcpu. It also has some scratch fields used by the guest
+ * exit code.
+ */
+struct kvmppc_host_state {
+ ulong host_r1;
+ ulong host_r2;
+ ulong host_msr;
+ ulong vmhandler;
+ ulong scratch0;
+ ulong scratch1;
+ u8 in_guest;
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ struct kvm_vcpu *kvm_vcpu;
+ struct kvmppc_vcore *kvm_vcore;
+ unsigned long xics_phys;
+ u64 dabr;
+ u64 host_mmcr[3];
+ u32 host_pmc[8];
+ u64 host_purr;
+ u64 host_spurr;
+ u64 host_dscr;
+ u64 dec_expires;
+#endif
+};
+
struct kvmppc_book3s_shadow_vcpu {
ulong gpr[14];
u32 cr;
@@ -73,17 +103,12 @@ struct kvmppc_book3s_shadow_vcpu {
ulong shadow_srr1;
ulong fault_dar;
- ulong host_r1;
- ulong host_r2;
- ulong handler;
- ulong scratch0;
- ulong scratch1;
- ulong vmhandler;
- u8 in_guest;
-
#ifdef CONFIG_PPC_BOOK3S_32
u32 sr[16]; /* Guest SRs */
+
+ struct kvmppc_host_state hstate;
#endif
+
#ifdef CONFIG_PPC_BOOK3S_64
u8 slb_max; /* highest used guest slb entry */
struct {
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index 9c9ba3d59b1b..a90e09188777 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -93,4 +93,8 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
return vcpu->arch.fault_dear;
}
+static inline ulong kvmppc_get_msr(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.shared->msr;
+}
#endif /* __ASM_KVM_BOOKE_H__ */
diff --git a/arch/powerpc/include/asm/kvm_e500.h b/arch/powerpc/include/asm/kvm_e500.h
index 7a2a565f88c4..adbfca9dd100 100644
--- a/arch/powerpc/include/asm/kvm_e500.h
+++ b/arch/powerpc/include/asm/kvm_e500.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Yu Liu, <yu.liu@freescale.com>
*
@@ -29,17 +29,25 @@ struct tlbe{
u32 mas7;
};
+#define E500_TLB_VALID 1
+#define E500_TLB_DIRTY 2
+
+struct tlbe_priv {
+ pfn_t pfn;
+ unsigned int flags; /* E500_TLB_* */
+};
+
+struct vcpu_id_table;
+
struct kvmppc_vcpu_e500 {
/* Unmodified copy of the guest's TLB. */
- struct tlbe *guest_tlb[E500_TLB_NUM];
- /* TLB that's actually used when the guest is running. */
- struct tlbe *shadow_tlb[E500_TLB_NUM];
- /* Pages which are referenced in the shadow TLB. */
- struct page **shadow_pages[E500_TLB_NUM];
+ struct tlbe *gtlb_arch[E500_TLB_NUM];
- unsigned int guest_tlb_size[E500_TLB_NUM];
- unsigned int shadow_tlb_size[E500_TLB_NUM];
- unsigned int guest_tlb_nv[E500_TLB_NUM];
+ /* KVM internal information associated with each guest TLB entry */
+ struct tlbe_priv *gtlb_priv[E500_TLB_NUM];
+
+ unsigned int gtlb_size[E500_TLB_NUM];
+ unsigned int gtlb_nv[E500_TLB_NUM];
u32 host_pid[E500_PID_NUM];
u32 pid[E500_PID_NUM];
@@ -53,6 +61,10 @@ struct kvmppc_vcpu_e500 {
u32 mas5;
u32 mas6;
u32 mas7;
+
+ /* vcpu id table */
+ struct vcpu_id_table *idt;
+
u32 l1csr0;
u32 l1csr1;
u32 hid0;
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 186f150b9b89..cc22b282d755 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -25,15 +25,23 @@
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/kvm_types.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
#include <linux/kvm_para.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
#include <asm/kvm_asm.h>
+#include <asm/processor.h>
-#define KVM_MAX_VCPUS 1
+#define KVM_MAX_VCPUS NR_CPUS
+#define KVM_MAX_VCORES NR_CPUS
#define KVM_MEMORY_SLOTS 32
/* memory slots that does not exposed to userspace */
#define KVM_PRIVATE_MEM_SLOTS 4
+#ifdef CONFIG_KVM_MMIO
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#endif
/* We don't currently support large pages. */
#define KVM_HPAGE_GFN_SHIFT(x) 0
@@ -57,6 +65,10 @@ struct kvm;
struct kvm_run;
struct kvm_vcpu;
+struct lppaca;
+struct slb_shadow;
+struct dtl;
+
struct kvm_vm_stat {
u32 remote_tlb_flush;
};
@@ -133,9 +145,74 @@ struct kvmppc_exit_timing {
};
};
+struct kvmppc_pginfo {
+ unsigned long pfn;
+ atomic_t refcnt;
+};
+
+struct kvmppc_spapr_tce_table {
+ struct list_head list;
+ struct kvm *kvm;
+ u64 liobn;
+ u32 window_size;
+ struct page *pages[0];
+};
+
+struct kvmppc_rma_info {
+ void *base_virt;
+ unsigned long base_pfn;
+ unsigned long npages;
+ struct list_head list;
+ atomic_t use_count;
+};
+
struct kvm_arch {
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ unsigned long hpt_virt;
+ unsigned long ram_npages;
+ unsigned long ram_psize;
+ unsigned long ram_porder;
+ struct kvmppc_pginfo *ram_pginfo;
+ unsigned int lpid;
+ unsigned int host_lpid;
+ unsigned long host_lpcr;
+ unsigned long sdr1;
+ unsigned long host_sdr1;
+ int tlbie_lock;
+ int n_rma_pages;
+ unsigned long lpcr;
+ unsigned long rmor;
+ struct kvmppc_rma_info *rma;
+ struct list_head spapr_tce_tables;
+ unsigned short last_vcpu[NR_CPUS];
+ struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
};
+/*
+ * Struct for a virtual core.
+ * Note: entry_exit_count combines an entry count in the bottom 8 bits
+ * and an exit count in the next 8 bits. This is so that we can
+ * atomically increment the entry count iff the exit count is 0
+ * without taking the lock.
+ */
+struct kvmppc_vcore {
+ int n_runnable;
+ int n_blocked;
+ int num_threads;
+ int entry_exit_count;
+ int n_woken;
+ int nap_count;
+ u16 pcpu;
+ u8 vcore_running;
+ u8 in_guest;
+ struct list_head runnable_threads;
+ spinlock_t lock;
+};
+
+#define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff)
+#define VCORE_EXIT_COUNT(vc) ((vc)->entry_exit_count >> 8)
+
struct kvmppc_pte {
ulong eaddr;
u64 vpage;
@@ -163,16 +240,18 @@ struct kvmppc_mmu {
bool (*is_dcbz32)(struct kvm_vcpu *vcpu);
};
-struct hpte_cache {
- struct hlist_node list_pte;
- struct hlist_node list_pte_long;
- struct hlist_node list_vpte;
- struct hlist_node list_vpte_long;
- struct rcu_head rcu_head;
- u64 host_va;
- u64 pfn;
- ulong slot;
- struct kvmppc_pte pte;
+struct kvmppc_slb {
+ u64 esid;
+ u64 vsid;
+ u64 orige;
+ u64 origv;
+ bool valid : 1;
+ bool Ks : 1;
+ bool Kp : 1;
+ bool nx : 1;
+ bool large : 1; /* PTEs are 16MB */
+ bool tb : 1; /* 1TB segment */
+ bool class : 1;
};
struct kvm_vcpu_arch {
@@ -187,6 +266,9 @@ struct kvm_vcpu_arch {
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 */
struct kvmppc_mmu mmu;
#endif
@@ -195,13 +277,19 @@ struct kvm_vcpu_arch {
u64 fpr[32];
u64 fpscr;
+#ifdef CONFIG_SPE
+ ulong evr[32];
+ ulong spefscr;
+ ulong host_spefscr;
+ u64 acc;
+#endif
#ifdef CONFIG_ALTIVEC
vector128 vr[32];
vector128 vscr;
#endif
#ifdef CONFIG_VSX
- u64 vsr[32];
+ u64 vsr[64];
#endif
#ifdef CONFIG_PPC_BOOK3S
@@ -209,22 +297,27 @@ struct kvm_vcpu_arch {
u32 qpr[32];
#endif
-#ifdef CONFIG_BOOKE
ulong pc;
ulong ctr;
ulong lr;
ulong xer;
u32 cr;
-#endif
#ifdef CONFIG_PPC_BOOK3S
- ulong shadow_msr;
ulong hflags;
ulong guest_owned_ext;
+ ulong purr;
+ ulong spurr;
+ ulong dscr;
+ ulong amr;
+ ulong uamor;
+ u32 ctrl;
+ ulong dabr;
#endif
u32 vrsave; /* also USPRG0 */
u32 mmucr;
+ ulong shadow_msr;
ulong sprg4;
ulong sprg5;
ulong sprg6;
@@ -249,6 +342,7 @@ struct kvm_vcpu_arch {
u32 pvr;
u32 shadow_pid;
+ u32 shadow_pid1;
u32 pid;
u32 swap_pid;
@@ -258,6 +352,9 @@ struct kvm_vcpu_arch {
u32 dbcr1;
u32 dbsr;
+ u64 mmcr[3];
+ u32 pmc[8];
+
#ifdef CONFIG_KVM_EXIT_TIMING
struct mutex exit_timing_lock;
struct kvmppc_exit_timing timing_exit;
@@ -272,8 +369,12 @@ struct kvm_vcpu_arch {
struct dentry *debugfs_exit_timing;
#endif
+#ifdef CONFIG_PPC_BOOK3S
+ ulong fault_dar;
+ u32 fault_dsisr;
+#endif
+
#ifdef CONFIG_BOOKE
- u32 last_inst;
ulong fault_dear;
ulong fault_esr;
ulong queued_dear;
@@ -288,25 +389,47 @@ struct kvm_vcpu_arch {
u8 dcr_is_write;
u8 osi_needed;
u8 osi_enabled;
+ u8 hcall_needed;
u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
struct hrtimer dec_timer;
struct tasklet_struct tasklet;
u64 dec_jiffies;
+ u64 dec_expires;
unsigned long pending_exceptions;
+ u16 last_cpu;
+ u8 ceded;
+ u8 prodded;
+ u32 last_inst;
+
+ struct lppaca *vpa;
+ struct slb_shadow *slb_shadow;
+ struct dtl *dtl;
+ struct dtl *dtl_end;
+
+ struct kvmppc_vcore *vcore;
+ int ret;
+ int trap;
+ int state;
+ int ptid;
+ wait_queue_head_t cpu_run;
+
struct kvm_vcpu_arch_shared *shared;
unsigned long magic_page_pa; /* phys addr to map the magic page to */
unsigned long magic_page_ea; /* effect. addr to map the magic page to */
-#ifdef CONFIG_PPC_BOOK3S
- 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];
- struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG];
- int hpte_cache_count;
- spinlock_t mmu_lock;
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ struct kvm_vcpu_arch_shared shregs;
+
+ struct list_head run_list;
+ struct task_struct *run_task;
+ struct kvm_run *kvm_run;
#endif
};
+#define KVMPPC_VCPU_BUSY_IN_HOST 0
+#define KVMPPC_VCPU_BLOCKED 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 9345238edecf..d121f49d62b8 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -33,6 +33,9 @@
#else
#include <asm/kvm_booke.h>
#endif
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#include <asm/paca.h>
+#endif
enum emulation_result {
EMULATE_DONE, /* no further processing */
@@ -42,6 +45,7 @@ enum emulation_result {
EMULATE_AGAIN, /* something went wrong. go again */
};
+extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
extern char kvmppc_handlers_start[];
extern unsigned long kvmppc_handler_len;
@@ -109,6 +113,27 @@ extern void kvmppc_booke_exit(void);
extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu);
+extern void kvmppc_map_magic(struct kvm_vcpu *vcpu);
+
+extern long kvmppc_alloc_hpt(struct kvm *kvm);
+extern void kvmppc_free_hpt(struct kvm *kvm);
+extern long kvmppc_prepare_vrma(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem);
+extern void kvmppc_map_vrma(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem);
+extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
+extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
+ struct kvm_create_spapr_tce *args);
+extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
+ struct kvm_allocate_rma *rma);
+extern struct kvmppc_rma_info *kvm_alloc_rma(void);
+extern void kvm_release_rma(struct kvmppc_rma_info *ri);
+extern int kvmppc_core_init_vm(struct kvm *kvm);
+extern void kvmppc_core_destroy_vm(struct kvm *kvm);
+extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem);
+extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem);
/*
* Cuts out inst bits with ordering according to spec.
@@ -151,4 +176,20 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
+{
+ paca[cpu].kvm_hstate.xics_phys = addr;
+}
+
+extern void kvm_rma_init(void);
+
+#else
+static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
+{}
+
+static inline void kvm_rma_init(void)
+{}
+#endif
+
#endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/local.h b/arch/powerpc/include/asm/local.h
index c2410af6bfd9..b8da91363864 100644
--- a/arch/powerpc/include/asm/local.h
+++ b/arch/powerpc/include/asm/local.h
@@ -2,7 +2,7 @@
#define _ARCH_POWERPC_LOCAL_H
#include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
typedef struct
{
diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h
index 7ab82c825a03..27af7f8bbb8d 100644
--- a/arch/powerpc/include/asm/macio.h
+++ b/arch/powerpc/include/asm/macio.h
@@ -76,7 +76,7 @@ static inline unsigned long macio_resource_len(struct macio_dev *dev, int resour
struct resource *res = &dev->resource[resource_no];
if (res->start == 0 || res->end == 0 || res->end < res->start)
return 0;
- return res->end - res->start + 1;
+ return resource_size(res);
}
extern int macio_enable_devres(struct macio_dev *dev);
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index d865bd909c7d..b445e0af4c2b 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -90,13 +90,19 @@ extern char initial_stab[];
#define HPTE_R_PP0 ASM_CONST(0x8000000000000000)
#define HPTE_R_TS ASM_CONST(0x4000000000000000)
+#define HPTE_R_KEY_HI ASM_CONST(0x3000000000000000)
#define HPTE_R_RPN_SHIFT 12
-#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000)
-#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff)
+#define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000)
#define HPTE_R_PP ASM_CONST(0x0000000000000003)
#define HPTE_R_N ASM_CONST(0x0000000000000004)
+#define HPTE_R_G ASM_CONST(0x0000000000000008)
+#define HPTE_R_M ASM_CONST(0x0000000000000010)
+#define HPTE_R_I ASM_CONST(0x0000000000000020)
+#define HPTE_R_W ASM_CONST(0x0000000000000040)
+#define HPTE_R_WIMG ASM_CONST(0x0000000000000078)
#define HPTE_R_C ASM_CONST(0x0000000000000080)
#define HPTE_R_R ASM_CONST(0x0000000000000100)
+#define HPTE_R_KEY_LO ASM_CONST(0x0000000000000e00)
#define HPTE_V_1TB_SEG ASM_CONST(0x4000000000000000)
#define HPTE_V_VRMA_MASK ASM_CONST(0x4001ffffff000000)
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 4138b21ae80a..698b30638681 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -115,14 +115,24 @@
#ifndef __ASSEMBLY__
#include <asm/cputable.h>
+#ifdef CONFIG_PPC_FSL_BOOK3E
+#include <asm/percpu.h>
+DECLARE_PER_CPU(int, next_tlbcam_idx);
+#endif
+
static inline int mmu_has_feature(unsigned long feature)
{
return (cur_cpu_spec->mmu_features & feature);
}
+static inline void mmu_clear_feature(unsigned long feature)
+{
+ cur_cpu_spec->mmu_features &= ~feature;
+}
+
extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
-/* MMU initialization (64-bit only fo now) */
+/* MMU initialization */
extern void early_init_mmu(void);
extern void early_init_mmu_secondary(void);
diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h
index 89d2f99c1bf4..23cd6cc30bcf 100644
--- a/arch/powerpc/include/asm/pSeries_reconfig.h
+++ b/arch/powerpc/include/asm/pSeries_reconfig.h
@@ -17,7 +17,7 @@
#ifdef CONFIG_PPC_PSERIES
extern int pSeries_reconfig_notifier_register(struct notifier_block *);
extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
-extern struct blocking_notifier_head pSeries_reconfig_chain;
+extern int pSeries_reconfig_notify(unsigned long action, void *p);
/* Not the best place to put this, will be fixed when we move some
* of the rtas suspend-me stuff to pseries */
extern void pSeries_coalesce_init(void);
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 74126765106a..516bfb3f47d9 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -103,11 +103,12 @@ struct paca_struct {
#endif /* CONFIG_PPC_STD_MMU_64 */
#ifdef CONFIG_PPC_BOOK3E
- pgd_t *pgd; /* Current PGD */
- pgd_t *kernel_pgd; /* Kernel PGD */
u64 exgen[8] __attribute__((aligned(0x80)));
+ /* Keep pgd in the same cacheline as the start of extlb */
+ pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */
+ pgd_t *kernel_pgd; /* Kernel PGD */
/* We can have up to 3 levels of reentrancy in the TLB miss handler */
- u64 extlb[3][EX_TLB_SIZE / sizeof(u64)] __attribute__((aligned(0x80)));
+ u64 extlb[3][EX_TLB_SIZE / sizeof(u64)];
u64 exmc[8]; /* used for machine checks */
u64 excrit[8]; /* used for crit interrupts */
u64 exdbg[8]; /* used for debug interrupts */
@@ -147,9 +148,12 @@ struct paca_struct {
struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */
#ifdef CONFIG_KVM_BOOK3S_HANDLER
+#ifdef CONFIG_KVM_BOOK3S_PR
/* We use this to store guest state in */
struct kvmppc_book3s_shadow_vcpu shadow_vcpu;
#endif
+ struct kvmppc_host_state kvm_hstate;
+#endif
};
extern struct paca_struct *paca;
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index b90dbf8e5cd9..56b879ab3a40 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -10,58 +10,10 @@
#include <linux/pci.h>
#include <linux/list.h>
#include <linux/ioport.h>
+#include <asm-generic/pci-bridge.h>
struct device_node;
-enum {
- /* Force re-assigning all resources (ignore firmware
- * setup completely)
- */
- PPC_PCI_REASSIGN_ALL_RSRC = 0x00000001,
-
- /* Re-assign all bus numbers */
- PPC_PCI_REASSIGN_ALL_BUS = 0x00000002,
-
- /* Do not try to assign, just use existing setup */
- PPC_PCI_PROBE_ONLY = 0x00000004,
-
- /* Don't bother with ISA alignment unless the bridge has
- * ISA forwarding enabled
- */
- PPC_PCI_CAN_SKIP_ISA_ALIGN = 0x00000008,
-
- /* Enable domain numbers in /proc */
- PPC_PCI_ENABLE_PROC_DOMAINS = 0x00000010,
- /* ... except for domain 0 */
- PPC_PCI_COMPAT_DOMAIN_0 = 0x00000020,
-};
-#ifdef CONFIG_PCI
-extern unsigned int ppc_pci_flags;
-
-static inline void ppc_pci_set_flags(int flags)
-{
- ppc_pci_flags = flags;
-}
-
-static inline void ppc_pci_add_flags(int flags)
-{
- ppc_pci_flags |= flags;
-}
-
-static inline int ppc_pci_has_flag(int flag)
-{
- return (ppc_pci_flags & flag);
-}
-#else
-static inline void ppc_pci_set_flags(int flags) { }
-static inline void ppc_pci_add_flags(int flags) { }
-static inline int ppc_pci_has_flag(int flag)
-{
- return 0;
-}
-#endif
-
-
/*
* Structure of a PCI controller (host bridge)
*/
@@ -171,15 +123,9 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
#ifndef CONFIG_PPC64
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
- struct pci_controller *host;
-
- if (bus->self)
- return pci_device_to_OF_node(bus->self);
- host = pci_bus_to_host(bus);
- return host ? host->dn : NULL;
-}
+extern int pci_device_from_OF_node(struct device_node *node,
+ u8 *bus, u8 *devfn);
+extern void pci_create_OF_bus_map(void);
static inline int isa_vaddr_is_ioport(void __iomem *address)
{
@@ -223,17 +169,8 @@ struct pci_dn {
/* Get the pointer to a device_node's pci_dn */
#define PCI_DN(dn) ((struct pci_dn *) (dn)->data)
-extern struct device_node *fetch_dev_dn(struct pci_dev *dev);
extern void * update_dn_pci_info(struct device_node *dn, void *data);
-/* Get a device_node from a pci_dev. This code must be fast except
- * in the case where the sysdata is incorrect and needs to be fixed
- * up (this will only happen once). */
-static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
-{
- return dev->dev.of_node ? dev->dev.of_node : fetch_dev_dn(dev);
-}
-
static inline int pci_device_from_OF_node(struct device_node *np,
u8 *bus, u8 *devfn)
{
@@ -244,14 +181,6 @@ static inline int pci_device_from_OF_node(struct device_node *np,
return 0;
}
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
- if (bus->self)
- return pci_device_to_OF_node(bus->self);
- else
- return bus->dev.of_node; /* Must be root bus (PHB) */
-}
-
/** Find the bus corresponding to the indicated device node */
extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 7d7790954e02..49c3de582be0 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -44,7 +44,7 @@ struct pci_dev;
* bus numbers (don't do that on ppc64 yet !)
*/
#define pcibios_assign_all_busses() \
- (ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
+ (pci_has_flag(PCI_REASSIGN_ALL_BUS))
static inline void pcibios_set_master(struct pci_dev *dev)
{
@@ -179,8 +179,7 @@ extern int remove_phb_dynamic(struct pci_controller *phb);
extern struct pci_dev *of_create_pci_dev(struct device_node *node,
struct pci_bus *bus, int devfn);
-extern void of_scan_pci_bridge(struct device_node *node,
- struct pci_dev *dev);
+extern void of_scan_pci_bridge(struct pci_dev *dev);
extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index 81576ee0cfb1..c4205616dfb5 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -357,7 +357,8 @@ void pgtable_cache_init(void);
/*
* find_linux_pte returns the address of a linux pte for a given
* effective address and directory. If not found, it returns zero.
- */static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
+ */
+static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
{
pgd_t *pg;
pud_t *pu;
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index e472659d906c..e980faae4225 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -71,6 +71,42 @@
#define PPC_INST_ERATSX 0x7c000126
#define PPC_INST_ERATSX_DOT 0x7c000127
+/* Misc instructions for BPF compiler */
+#define PPC_INST_LD 0xe8000000
+#define PPC_INST_LHZ 0xa0000000
+#define PPC_INST_LWZ 0x80000000
+#define PPC_INST_STD 0xf8000000
+#define PPC_INST_STDU 0xf8000001
+#define PPC_INST_MFLR 0x7c0802a6
+#define PPC_INST_MTLR 0x7c0803a6
+#define PPC_INST_CMPWI 0x2c000000
+#define PPC_INST_CMPDI 0x2c200000
+#define PPC_INST_CMPLW 0x7c000040
+#define PPC_INST_CMPLWI 0x28000000
+#define PPC_INST_ADDI 0x38000000
+#define PPC_INST_ADDIS 0x3c000000
+#define PPC_INST_ADD 0x7c000214
+#define PPC_INST_SUB 0x7c000050
+#define PPC_INST_BLR 0x4e800020
+#define PPC_INST_BLRL 0x4e800021
+#define PPC_INST_MULLW 0x7c0001d6
+#define PPC_INST_MULHWU 0x7c000016
+#define PPC_INST_MULLI 0x1c000000
+#define PPC_INST_DIVWU 0x7c0003d6
+#define PPC_INST_RLWINM 0x54000000
+#define PPC_INST_RLDICR 0x78000004
+#define PPC_INST_SLW 0x7c000030
+#define PPC_INST_SRW 0x7c000430
+#define PPC_INST_AND 0x7c000038
+#define PPC_INST_ANDDOT 0x7c000039
+#define PPC_INST_OR 0x7c000378
+#define PPC_INST_ANDI 0x70000000
+#define PPC_INST_ORI 0x60000000
+#define PPC_INST_ORIS 0x64000000
+#define PPC_INST_NEG 0x7c0000d0
+#define PPC_INST_BRANCH 0x48000000
+#define PPC_INST_BRANCH_COND 0x40800000
+
/* macros to insert fields into opcodes */
#define __PPC_RA(a) (((a) & 0x1f) << 16)
#define __PPC_RB(b) (((b) & 0x1f) << 11)
@@ -83,6 +119,10 @@
#define __PPC_T_TLB(t) (((t) & 0x3) << 21)
#define __PPC_WC(w) (((w) & 0x3) << 21)
#define __PPC_WS(w) (((w) & 0x1f) << 11)
+#define __PPC_SH(s) __PPC_WS(s)
+#define __PPC_MB(s) (((s) & 0x1f) << 6)
+#define __PPC_ME(s) (((s) & 0x1f) << 1)
+#define __PPC_BI(s) (((s) & 0x1f) << 16)
/*
* Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 1b422381fc16..368f72f79808 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -150,18 +150,22 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
#define REST_16VSRSU(n,b,base) REST_8VSRSU(n,b,base); REST_8VSRSU(n+8,b,base)
#define REST_32VSRSU(n,b,base) REST_16VSRSU(n,b,base); REST_16VSRSU(n+16,b,base)
-#define SAVE_EVR(n,s,base) evmergehi s,s,n; stw s,THREAD_EVR0+4*(n)(base)
-#define SAVE_2EVRS(n,s,base) SAVE_EVR(n,s,base); SAVE_EVR(n+1,s,base)
-#define SAVE_4EVRS(n,s,base) SAVE_2EVRS(n,s,base); SAVE_2EVRS(n+2,s,base)
-#define SAVE_8EVRS(n,s,base) SAVE_4EVRS(n,s,base); SAVE_4EVRS(n+4,s,base)
-#define SAVE_16EVRS(n,s,base) SAVE_8EVRS(n,s,base); SAVE_8EVRS(n+8,s,base)
-#define SAVE_32EVRS(n,s,base) SAVE_16EVRS(n,s,base); SAVE_16EVRS(n+16,s,base)
-#define REST_EVR(n,s,base) lwz s,THREAD_EVR0+4*(n)(base); evmergelo n,s,n
-#define REST_2EVRS(n,s,base) REST_EVR(n,s,base); REST_EVR(n+1,s,base)
-#define REST_4EVRS(n,s,base) REST_2EVRS(n,s,base); REST_2EVRS(n+2,s,base)
-#define REST_8EVRS(n,s,base) REST_4EVRS(n,s,base); REST_4EVRS(n+4,s,base)
-#define REST_16EVRS(n,s,base) REST_8EVRS(n,s,base); REST_8EVRS(n+8,s,base)
-#define REST_32EVRS(n,s,base) REST_16EVRS(n,s,base); REST_16EVRS(n+16,s,base)
+/*
+ * b = base register for addressing, o = base offset from register of 1st EVR
+ * n = first EVR, s = scratch
+ */
+#define SAVE_EVR(n,s,b,o) evmergehi s,s,n; stw s,o+4*(n)(b)
+#define SAVE_2EVRS(n,s,b,o) SAVE_EVR(n,s,b,o); SAVE_EVR(n+1,s,b,o)
+#define SAVE_4EVRS(n,s,b,o) SAVE_2EVRS(n,s,b,o); SAVE_2EVRS(n+2,s,b,o)
+#define SAVE_8EVRS(n,s,b,o) SAVE_4EVRS(n,s,b,o); SAVE_4EVRS(n+4,s,b,o)
+#define SAVE_16EVRS(n,s,b,o) SAVE_8EVRS(n,s,b,o); SAVE_8EVRS(n+8,s,b,o)
+#define SAVE_32EVRS(n,s,b,o) SAVE_16EVRS(n,s,b,o); SAVE_16EVRS(n+16,s,b,o)
+#define REST_EVR(n,s,b,o) lwz s,o+4*(n)(b); evmergelo n,s,n
+#define REST_2EVRS(n,s,b,o) REST_EVR(n,s,b,o); REST_EVR(n+1,s,b,o)
+#define REST_4EVRS(n,s,b,o) REST_2EVRS(n,s,b,o); REST_2EVRS(n+2,s,b,o)
+#define REST_8EVRS(n,s,b,o) REST_4EVRS(n,s,b,o); REST_4EVRS(n+4,s,b,o)
+#define REST_16EVRS(n,s,b,o) REST_8EVRS(n,s,b,o); REST_8EVRS(n+8,s,b,o)
+#define REST_32EVRS(n,s,b,o) REST_16EVRS(n,s,b,o); REST_16EVRS(n+16,s,b,o)
/* Macros to adjust thread priority for hardware multithreading */
#define HMT_VERY_LOW or 31,31,31 # very low priority
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index d50c2b6d9bc3..eb11a446720e 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -20,6 +20,7 @@
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
+#include <linux/cache.h>
#include <asm/ptrace.h>
#include <asm/types.h>
@@ -156,6 +157,10 @@ struct thread_struct {
#endif
struct pt_regs *regs; /* Pointer to saved register state */
mm_segment_t fs; /* for get_fs() validation */
+#ifdef CONFIG_BOOKE
+ /* BookE base exception scratch space; align on cacheline */
+ unsigned long normsave[8] ____cacheline_aligned;
+#endif
#ifdef CONFIG_PPC32
void *pgdir; /* root of page-table tree */
#endif
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index c189aa5fe1f4..b5c91901e384 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -18,24 +18,10 @@
*/
#include <linux/types.h>
#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define HAVE_ARCH_DEVTREE_FIXUPS
-#ifdef CONFIG_PPC32
-/*
- * PCI <-> OF matching functions
- * (XXX should these be here?)
- */
-struct pci_bus;
-struct pci_dev;
-extern int pci_device_from_OF_node(struct device_node *node,
- u8* bus, u8* devfn);
-extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
-extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
-extern void pci_create_OF_bus_map(void);
-#endif
-
/*
* OF address retreival & translation
*/
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index c5cae0dd176c..e8aaf6fce38b 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -189,6 +189,9 @@
#define SPRN_CTR 0x009 /* Count Register */
#define SPRN_DSCR 0x11
#define SPRN_CFAR 0x1c /* Come From Address Register */
+#define SPRN_AMR 0x1d /* Authority Mask Register */
+#define SPRN_UAMOR 0x9d /* User Authority Mask Override Register */
+#define SPRN_AMOR 0x15d /* Authority Mask Override Register */
#define SPRN_ACOP 0x1F /* Available Coprocessor Register */
#define SPRN_CTRLF 0x088
#define SPRN_CTRLT 0x098
@@ -232,22 +235,28 @@
#define LPCR_VPM0 (1ul << (63-0))
#define LPCR_VPM1 (1ul << (63-1))
#define LPCR_ISL (1ul << (63-2))
+#define LPCR_VC_SH (63-2)
#define LPCR_DPFD_SH (63-11)
#define LPCR_VRMA_L (1ul << (63-12))
#define LPCR_VRMA_LP0 (1ul << (63-15))
#define LPCR_VRMA_LP1 (1ul << (63-16))
+#define LPCR_VRMASD_SH (63-16)
#define LPCR_RMLS 0x1C000000 /* impl dependent rmo limit sel */
+#define LPCR_RMLS_SH (63-37)
#define LPCR_ILE 0x02000000 /* !HV irqs set MSR:LE */
#define LPCR_PECE 0x00007000 /* powersave exit cause enable */
#define LPCR_PECE0 0x00004000 /* ext. exceptions can cause exit */
#define LPCR_PECE1 0x00002000 /* decrementer can cause exit */
#define LPCR_PECE2 0x00001000 /* machine check etc can cause exit */
#define LPCR_MER 0x00000800 /* Mediated External Exception */
+#define LPCR_LPES 0x0000000c
#define LPCR_LPES0 0x00000008 /* LPAR Env selector 0 */
#define LPCR_LPES1 0x00000004 /* LPAR Env selector 1 */
+#define LPCR_LPES_SH 2
#define LPCR_RMI 0x00000002 /* real mode is cache inhibit */
#define LPCR_HDICE 0x00000001 /* Hyp Decr enable (HV,PR,EE) */
#define SPRN_LPID 0x13F /* Logical Partition Identifier */
+#define LPID_RSVD 0x3ff /* Reserved LPID for partn switching */
#define SPRN_HMER 0x150 /* Hardware m? error recovery */
#define SPRN_HMEER 0x151 /* Hardware m? enable error recovery */
#define SPRN_HEIR 0x153 /* Hypervisor Emulated Instruction Register */
@@ -298,6 +307,7 @@
#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
+#define HID0_HDICE_SH (63 - 23) /* 970 HDEC interrupt enable */
#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
@@ -353,6 +363,13 @@
#define SPRN_IABR2 0x3FA /* 83xx */
#define SPRN_IBCR 0x135 /* 83xx Insn Breakpoint Control Reg */
#define SPRN_HID4 0x3F4 /* 970 HID4 */
+#define HID4_LPES0 (1ul << (63-0)) /* LPAR env. sel. bit 0 */
+#define HID4_RMLS2_SH (63 - 2) /* Real mode limit bottom 2 bits */
+#define HID4_LPID5_SH (63 - 6) /* partition ID bottom 4 bits */
+#define HID4_RMOR_SH (63 - 22) /* real mode offset (16 bits) */
+#define HID4_LPES1 (1 << (63-57)) /* LPAR env. sel. bit 1 */
+#define HID4_RMLS0_SH (63 - 58) /* Real mode limit top bit */
+#define HID4_LPID1_SH 0 /* partition ID top 2 bits */
#define SPRN_HID4_GEKKO 0x3F3 /* Gekko HID4 */
#define SPRN_HID5 0x3F6 /* 970 HID5 */
#define SPRN_HID6 0x3F9 /* BE HID 6 */
@@ -802,28 +819,28 @@
mfspr rX,SPRN_SPRG_PACA; \
FTR_SECTION_ELSE_NESTED(66); \
mfspr rX,SPRN_SPRG_HPACA; \
- ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
#define SET_PACA(rX) \
BEGIN_FTR_SECTION_NESTED(66); \
mtspr SPRN_SPRG_PACA,rX; \
FTR_SECTION_ELSE_NESTED(66); \
mtspr SPRN_SPRG_HPACA,rX; \
- ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
#define GET_SCRATCH0(rX) \
BEGIN_FTR_SECTION_NESTED(66); \
mfspr rX,SPRN_SPRG_SCRATCH0; \
FTR_SECTION_ELSE_NESTED(66); \
mfspr rX,SPRN_SPRG_HSCRATCH0; \
- ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
#define SET_SCRATCH0(rX) \
BEGIN_FTR_SECTION_NESTED(66); \
mtspr SPRN_SPRG_SCRATCH0,rX; \
FTR_SECTION_ELSE_NESTED(66); \
mtspr SPRN_SPRG_HSCRATCH0,rX; \
- ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
#else /* CONFIG_PPC_BOOK3S_64 */
#define GET_SCRATCH0(rX) mfspr rX,SPRN_SPRG_SCRATCH0
@@ -872,8 +889,8 @@
#define SPRN_SPRG_WSCRATCH2 SPRN_SPRG4W
#define SPRN_SPRG_RSCRATCH3 SPRN_SPRG5R
#define SPRN_SPRG_WSCRATCH3 SPRN_SPRG5W
-#define SPRN_SPRG_RSCRATCH_MC SPRN_SPRG6R
-#define SPRN_SPRG_WSCRATCH_MC SPRN_SPRG6W
+#define SPRN_SPRG_RSCRATCH_MC SPRN_SPRG1
+#define SPRN_SPRG_WSCRATCH_MC SPRN_SPRG1
#define SPRN_SPRG_RSCRATCH4 SPRN_SPRG7R
#define SPRN_SPRG_WSCRATCH4 SPRN_SPRG7W
#ifdef CONFIG_E200
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 0f0ad9fa01c1..9ec0b39f9ddc 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -318,6 +318,7 @@
#define ESR_ILK 0x00100000 /* Instr. Cache Locking */
#define ESR_PUO 0x00040000 /* Unimplemented Operation exception */
#define ESR_BO 0x00020000 /* Byte Ordering */
+#define ESR_SPV 0x00000080 /* Signal Processing operation */
/* Bit definitions related to the DBCR0. */
#if defined(CONFIG_40x)
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index dae19342f0b9..186e0fb835bd 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -3,4 +3,8 @@
#include <asm-generic/setup.h>
+#ifndef __ASSEMBLY__
+extern void ppc_printk_progress(char *s, unsigned short hex);
+#endif
+
#endif /* _ASM_POWERPC_SETUP_H */
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 11eb404b5606..15a70b7f638b 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -30,7 +30,7 @@
#include <asm/percpu.h>
extern int boot_cpuid;
-extern int boot_cpu_count;
+extern int spinning_secondaries;
extern void cpu_die(void);
@@ -119,7 +119,6 @@ extern const char *smp_ipi_name[];
/* for irq controllers with only a single ipi */
extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
extern void smp_muxed_ipi_message_pass(int cpu, int msg);
-extern void smp_muxed_ipi_resend(void);
extern irqreturn_t smp_ipi_demux(void);
void smp_init_iSeries(void);
diff --git a/arch/powerpc/include/asm/smu.h b/arch/powerpc/include/asm/smu.h
index e3bdada8c542..ae20ce1af4c7 100644
--- a/arch/powerpc/include/asm/smu.h
+++ b/arch/powerpc/include/asm/smu.h
@@ -547,7 +547,7 @@ struct smu_sdbp_header {
* (currently, afaik, this concerns only the FVT partition
* (0x12)
*/
-#define SMU_U16_MIX(x) le16_to_cpu(x);
+#define SMU_U16_MIX(x) le16_to_cpu(x)
#define SMU_U32_MIX(x) ((((x) & 0xff00ff00u) >> 8)|(((x) & 0x00ff00ffu) << 8))
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index 2dc595dda03b..e30a13d1ee76 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -120,7 +120,6 @@ extern void do_dabr(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
#endif
extern void print_backtrace(unsigned long *);
-extern void show_regs(struct pt_regs * regs);
extern void flush_instruction_cache(void);
extern void hard_reset_now(void);
extern void poweroff_now(void);
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 58580e94a2bb..93e05d1b34b2 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -40,6 +40,7 @@ extern void udbg_adb_init_early(void);
extern void __init udbg_early_init(void);
extern void __init udbg_init_debug_lpar(void);
+extern void __init udbg_init_debug_lpar_hvsi(void);
extern void __init udbg_init_pmac_realmode(void);
extern void __init udbg_init_maple_realmode(void);
extern void __init udbg_init_pas_realmode(void);
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index e8b981897d44..ce4f7f179117 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_44x) += cpu_setup_44x.o
obj-$(CONFIG_PPC_FSL_BOOK3E) += cpu_setup_fsl_booke.o dbell.o
obj-$(CONFIG_PPC_BOOK3E_64) += dbell.o
+obj-$(CONFIG_JUMP_LABEL) += jump_label.o
extra-y := head_$(CONFIG_WORD_SIZE).o
extra-$(CONFIG_40x) := head_40x.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 36e1c8a29be8..5f078bc2063e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -82,6 +82,9 @@ int main(void)
DEFINE(KSP, offsetof(struct thread_struct, ksp));
DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
+#ifdef CONFIG_BOOKE
+ DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
+#endif
DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
@@ -128,6 +131,7 @@ int main(void)
DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
/* paca */
DEFINE(PACA_SIZE, sizeof(struct paca_struct));
+ DEFINE(PACA_LOCK_TOKEN, offsetof(struct paca_struct, lock_token));
DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start));
DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack));
@@ -187,7 +191,9 @@ int main(void)
DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
+ DEFINE(LPPACA_PMCINUSE, offsetof(struct lppaca, pmcregs_in_use));
DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
+ DEFINE(LPPACA_YIELDCOUNT, offsetof(struct lppaca, yield_count));
DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
#endif /* CONFIG_PPC_STD_MMU_64 */
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
@@ -198,11 +204,6 @@ int main(void)
DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
-#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
- DEFINE(PACA_KVM_SVCPU, offsetof(struct paca_struct, shadow_vcpu));
- DEFINE(SVCPU_SLB, offsetof(struct kvmppc_book3s_shadow_vcpu, slb));
- DEFINE(SVCPU_SLB_MAX, offsetof(struct kvmppc_book3s_shadow_vcpu, slb_max));
-#endif
#endif /* CONFIG_PPC64 */
/* RTAS */
@@ -397,67 +398,160 @@ int main(void)
DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave));
+ DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fpr));
+ DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fpscr));
+#ifdef CONFIG_ALTIVEC
+ DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr));
+ DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vscr));
+#endif
+#ifdef CONFIG_VSX
+ DEFINE(VCPU_VSRS, offsetof(struct kvm_vcpu, arch.vsr));
+#endif
+ DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
+ DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
+ DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
+ DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
+ DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.shregs.msr));
+ DEFINE(VCPU_SRR0, offsetof(struct kvm_vcpu, arch.shregs.srr0));
+ DEFINE(VCPU_SRR1, offsetof(struct kvm_vcpu, arch.shregs.srr1));
+ DEFINE(VCPU_SPRG0, offsetof(struct kvm_vcpu, arch.shregs.sprg0));
+ DEFINE(VCPU_SPRG1, offsetof(struct kvm_vcpu, arch.shregs.sprg1));
+ DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2));
+ DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3));
+#endif
DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
+ DEFINE(VCPU_SHADOW_PID1, offsetof(struct kvm_vcpu, arch.shadow_pid1));
DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
+ DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
/* book3s */
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid));
+ DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1));
+ DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid));
+ DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
+ DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
+ DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
+ DEFINE(KVM_ONLINE_CPUS, offsetof(struct kvm, online_vcpus.counter));
+ DEFINE(KVM_LAST_VCPU, offsetof(struct kvm, arch.last_vcpu));
+ DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
+ DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
+ DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr));
+ DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
+#endif
#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_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_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));
+ DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr));
+ 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_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));
+ DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb));
+ DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max));
+ DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
+ DEFINE(VCPU_LAST_CPU, offsetof(struct kvm_vcpu, arch.last_cpu));
+ DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
+ DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
+ DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
+ DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
+ DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid));
+ 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(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) -
offsetof(struct kvmppc_vcpu_book3s, vcpu));
- DEFINE(SVCPU_CR, offsetof(struct kvmppc_book3s_shadow_vcpu, cr));
- DEFINE(SVCPU_XER, offsetof(struct kvmppc_book3s_shadow_vcpu, xer));
- DEFINE(SVCPU_CTR, offsetof(struct kvmppc_book3s_shadow_vcpu, ctr));
- DEFINE(SVCPU_LR, offsetof(struct kvmppc_book3s_shadow_vcpu, lr));
- DEFINE(SVCPU_PC, offsetof(struct kvmppc_book3s_shadow_vcpu, pc));
- DEFINE(SVCPU_R0, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[0]));
- DEFINE(SVCPU_R1, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[1]));
- DEFINE(SVCPU_R2, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[2]));
- DEFINE(SVCPU_R3, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[3]));
- DEFINE(SVCPU_R4, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[4]));
- DEFINE(SVCPU_R5, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[5]));
- DEFINE(SVCPU_R6, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[6]));
- DEFINE(SVCPU_R7, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[7]));
- DEFINE(SVCPU_R8, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[8]));
- DEFINE(SVCPU_R9, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[9]));
- DEFINE(SVCPU_R10, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[10]));
- DEFINE(SVCPU_R11, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[11]));
- DEFINE(SVCPU_R12, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[12]));
- DEFINE(SVCPU_R13, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[13]));
- DEFINE(SVCPU_HOST_R1, offsetof(struct kvmppc_book3s_shadow_vcpu, host_r1));
- DEFINE(SVCPU_HOST_R2, offsetof(struct kvmppc_book3s_shadow_vcpu, host_r2));
- DEFINE(SVCPU_VMHANDLER, offsetof(struct kvmppc_book3s_shadow_vcpu,
- vmhandler));
- DEFINE(SVCPU_SCRATCH0, offsetof(struct kvmppc_book3s_shadow_vcpu,
- scratch0));
- DEFINE(SVCPU_SCRATCH1, offsetof(struct kvmppc_book3s_shadow_vcpu,
- scratch1));
- DEFINE(SVCPU_IN_GUEST, offsetof(struct kvmppc_book3s_shadow_vcpu,
- in_guest));
- DEFINE(SVCPU_FAULT_DSISR, offsetof(struct kvmppc_book3s_shadow_vcpu,
- fault_dsisr));
- DEFINE(SVCPU_FAULT_DAR, offsetof(struct kvmppc_book3s_shadow_vcpu,
- fault_dar));
- DEFINE(SVCPU_LAST_INST, offsetof(struct kvmppc_book3s_shadow_vcpu,
- last_inst));
- DEFINE(SVCPU_SHADOW_SRR1, offsetof(struct kvmppc_book3s_shadow_vcpu,
- shadow_srr1));
+ DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
+ DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
+ DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
+
+#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_KVM_BOOK3S_PR
+# define SVCPU_FIELD(x, f) DEFINE(x, offsetof(struct paca_struct, shadow_vcpu.f))
+#else
+# define SVCPU_FIELD(x, f)
+#endif
+# define HSTATE_FIELD(x, f) DEFINE(x, offsetof(struct paca_struct, kvm_hstate.f))
+#else /* 32-bit */
+# define SVCPU_FIELD(x, f) DEFINE(x, offsetof(struct kvmppc_book3s_shadow_vcpu, f))
+# define HSTATE_FIELD(x, f) DEFINE(x, offsetof(struct kvmppc_book3s_shadow_vcpu, hstate.f))
+#endif
+
+ SVCPU_FIELD(SVCPU_CR, cr);
+ SVCPU_FIELD(SVCPU_XER, xer);
+ SVCPU_FIELD(SVCPU_CTR, ctr);
+ SVCPU_FIELD(SVCPU_LR, lr);
+ SVCPU_FIELD(SVCPU_PC, pc);
+ SVCPU_FIELD(SVCPU_R0, gpr[0]);
+ SVCPU_FIELD(SVCPU_R1, gpr[1]);
+ SVCPU_FIELD(SVCPU_R2, gpr[2]);
+ SVCPU_FIELD(SVCPU_R3, gpr[3]);
+ SVCPU_FIELD(SVCPU_R4, gpr[4]);
+ SVCPU_FIELD(SVCPU_R5, gpr[5]);
+ SVCPU_FIELD(SVCPU_R6, gpr[6]);
+ SVCPU_FIELD(SVCPU_R7, gpr[7]);
+ SVCPU_FIELD(SVCPU_R8, gpr[8]);
+ SVCPU_FIELD(SVCPU_R9, gpr[9]);
+ SVCPU_FIELD(SVCPU_R10, gpr[10]);
+ SVCPU_FIELD(SVCPU_R11, gpr[11]);
+ SVCPU_FIELD(SVCPU_R12, gpr[12]);
+ SVCPU_FIELD(SVCPU_R13, gpr[13]);
+ SVCPU_FIELD(SVCPU_FAULT_DSISR, fault_dsisr);
+ SVCPU_FIELD(SVCPU_FAULT_DAR, fault_dar);
+ SVCPU_FIELD(SVCPU_LAST_INST, last_inst);
+ SVCPU_FIELD(SVCPU_SHADOW_SRR1, shadow_srr1);
#ifdef CONFIG_PPC_BOOK3S_32
- DEFINE(SVCPU_SR, offsetof(struct kvmppc_book3s_shadow_vcpu, sr));
+ SVCPU_FIELD(SVCPU_SR, sr);
#endif
-#else
+#ifdef CONFIG_PPC64
+ SVCPU_FIELD(SVCPU_SLB, slb);
+ SVCPU_FIELD(SVCPU_SLB_MAX, slb_max);
+#endif
+
+ HSTATE_FIELD(HSTATE_HOST_R1, host_r1);
+ HSTATE_FIELD(HSTATE_HOST_R2, host_r2);
+ HSTATE_FIELD(HSTATE_HOST_MSR, host_msr);
+ HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
+ HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
+ HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
+ HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu);
+ HSTATE_FIELD(HSTATE_KVM_VCORE, kvm_vcore);
+ HSTATE_FIELD(HSTATE_XICS_PHYS, xics_phys);
+ HSTATE_FIELD(HSTATE_MMCR, host_mmcr);
+ HSTATE_FIELD(HSTATE_PMC, host_pmc);
+ HSTATE_FIELD(HSTATE_PURR, host_purr);
+ HSTATE_FIELD(HSTATE_SPURR, host_spurr);
+ HSTATE_FIELD(HSTATE_DSCR, host_dscr);
+ HSTATE_FIELD(HSTATE_DABR, dabr);
+ HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
+#else /* CONFIG_PPC_BOOK3S */
DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
@@ -467,7 +561,7 @@ int main(void)
DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
#endif /* CONFIG_PPC_BOOK3S */
-#endif
+#endif /* CONFIG_KVM */
#ifdef CONFIG_KVM_GUEST
DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared,
@@ -497,6 +591,13 @@ int main(void)
DEFINE(TLBCAM_MAS7, offsetof(struct tlbcam, MAS7));
#endif
+#if defined(CONFIG_KVM) && defined(CONFIG_SPE)
+ DEFINE(VCPU_EVR, offsetof(struct kvm_vcpu, arch.evr[0]));
+ DEFINE(VCPU_ACC, offsetof(struct kvm_vcpu, arch.acc));
+ DEFINE(VCPU_SPEFSCR, offsetof(struct kvm_vcpu, arch.spefscr));
+ DEFINE(VCPU_HOST_SPEFSCR, offsetof(struct kvm_vcpu, arch.host_spefscr));
+#endif
+
#ifdef CONFIG_KVM_EXIT_TIMING
DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
arch.timing_exit.tv32.tbu));
diff --git a/arch/powerpc/kernel/cpu_setup_power7.S b/arch/powerpc/kernel/cpu_setup_power7.S
index 4f9a93fcfe07..76797c5105d6 100644
--- a/arch/powerpc/kernel/cpu_setup_power7.S
+++ b/arch/powerpc/kernel/cpu_setup_power7.S
@@ -45,12 +45,12 @@ _GLOBAL(__restore_cpu_power7)
blr
__init_hvmode_206:
- /* Disable CPU_FTR_HVMODE_206 and exit if MSR:HV is not set */
+ /* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */
mfmsr r3
rldicl. r0,r3,4,63
bnelr
ld r5,CPU_SPEC_FEATURES(r4)
- LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE_206)
+ LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE)
xor r5,r5,r6
std r5,CPU_SPEC_FEATURES(r4)
blr
@@ -61,19 +61,23 @@ __init_LPCR:
* LPES = 0b01 (HSRR0/1 used for 0x500)
* PECE = 0b111
* DPFD = 4
+ * HDICE = 0
+ * VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
+ * VRMASD = 0b10000 (L=1, LP=00)
*
* Other bits untouched for now
*/
mfspr r3,SPRN_LPCR
- ori r3,r3,(LPCR_LPES0|LPCR_LPES1)
- xori r3,r3, LPCR_LPES0
+ li r5,1
+ rldimi r3,r5, LPCR_LPES_SH, 64-LPCR_LPES_SH-2
ori r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2)
- li r5,7
- sldi r5,r5,LPCR_DPFD_SH
- andc r3,r3,r5
li r5,4
- sldi r5,r5,LPCR_DPFD_SH
- or r3,r3,r5
+ rldimi r3,r5, LPCR_DPFD_SH, 64-LPCR_DPFD_SH-3
+ clrrdi r3,r3,1 /* clear HDICE */
+ li r5,4
+ rldimi r3,r5, LPCR_VC_SH, 0
+ li r5,0x10
+ rldimi r3,r5, LPCR_VRMASD_SH, 64-LPCR_VRMASD_SH-5
mtspr SPRN_LPCR,r3
isync
blr
diff --git a/arch/powerpc/kernel/cpu_setup_ppc970.S b/arch/powerpc/kernel/cpu_setup_ppc970.S
index 27f2507279d8..12fac8df01c5 100644
--- a/arch/powerpc/kernel/cpu_setup_ppc970.S
+++ b/arch/powerpc/kernel/cpu_setup_ppc970.S
@@ -76,7 +76,7 @@ _GLOBAL(__setup_cpu_ppc970)
/* Do nothing if not running in HV mode */
mfmsr r0
rldicl. r0,r0,4,63
- beqlr
+ beq no_hv_mode
mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */
@@ -90,7 +90,7 @@ _GLOBAL(__setup_cpu_ppc970MP)
/* Do nothing if not running in HV mode */
mfmsr r0
rldicl. r0,r0,4,63
- beqlr
+ beq no_hv_mode
mfspr r0,SPRN_HID0
li r11,0x15 /* clear DOZE and SLEEP */
@@ -109,6 +109,14 @@ load_hids:
sync
isync
+ /* Try to set LPES = 01 in HID4 */
+ mfspr r0,SPRN_HID4
+ clrldi r0,r0,1 /* clear LPES0 */
+ ori r0,r0,HID4_LPES1 /* set LPES1 */
+ sync
+ mtspr SPRN_HID4,r0
+ isync
+
/* Save away cpu state */
LOAD_REG_ADDR(r5,cpu_state_storage)
@@ -117,11 +125,21 @@ load_hids:
std r3,CS_HID0(r5)
mfspr r3,SPRN_HID1
std r3,CS_HID1(r5)
- mfspr r3,SPRN_HID4
- std r3,CS_HID4(r5)
+ mfspr r4,SPRN_HID4
+ std r4,CS_HID4(r5)
mfspr r3,SPRN_HID5
std r3,CS_HID5(r5)
+ /* See if we successfully set LPES1 to 1; if not we are in Apple mode */
+ andi. r4,r4,HID4_LPES1
+ bnelr
+
+no_hv_mode:
+ /* Disable CPU_FTR_HVMODE and exit, since we don't have HV mode */
+ ld r5,CPU_SPEC_FEATURES(r4)
+ LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE)
+ andc r5,r5,r6
+ std r5,CPU_SPEC_FEATURES(r4)
blr
/* Called with no MMU context (typically MSR:IR/DR off) to
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 4e6ee944495a..cc6a9d5d69ab 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -242,12 +242,8 @@ static void crash_kexec_wait_realmode(int cpu)
while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
barrier();
- if (!cpu_possible(i)) {
+ if (!cpu_possible(i) || !cpu_online(i) || (msecs <= 0))
break;
- }
- if (!cpu_online(i)) {
- break;
- }
msecs--;
mdelay(1);
}
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index d238c082c3c5..4f0959fbfbee 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -161,9 +161,7 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
if (ppc_md.dma_set_mask)
return ppc_md.dma_set_mask(dev, dma_mask);
- if (unlikely(dma_ops == NULL))
- return -EIO;
- if (dma_ops->set_dma_mask != NULL)
+ if ((dma_ops != NULL) && (dma_ops->set_dma_mask != NULL))
return dma_ops->set_dma_mask(dev, dma_mask);
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c
index b150b510510f..cb2e2949c8d1 100644
--- a/arch/powerpc/kernel/e500-pmu.c
+++ b/arch/powerpc/kernel/e500-pmu.c
@@ -75,6 +75,11 @@ static int e500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
static int num_events = 128;
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index d24d4400cc79..429983c06f91 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -120,6 +120,12 @@
std r14,PACA_EXMC+EX_R14(r13); \
std r15,PACA_EXMC+EX_R15(r13)
+#define PROLOG_ADDITION_DOORBELL_GEN \
+ lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \
+ cmpwi cr0,r11,0; /* yes -> go out of line */ \
+ beq masked_doorbell_book3e
+
+
/* Core exception code for all exceptions except TLB misses.
* XXX: Needs to make SPRN_SPRG_GEN depend on exception type
*/
@@ -522,7 +528,13 @@ kernel_dbg_exc:
MASKABLE_EXCEPTION(0x260, perfmon, .performance_monitor_exception, ACK_NONE)
/* Doorbell interrupt */
- MASKABLE_EXCEPTION(0x2070, doorbell, .doorbell_exception, ACK_NONE)
+ START_EXCEPTION(doorbell)
+ NORMAL_EXCEPTION_PROLOG(0x2070, PROLOG_ADDITION_DOORBELL)
+ EXCEPTION_COMMON(0x2070, PACA_EXGEN, INTS_DISABLE_ALL)
+ CHECK_NAPPING()
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .doorbell_exception
+ b .ret_from_except_lite
/* Doorbell critical Interrupt */
START_EXCEPTION(doorbell_crit);
@@ -545,8 +557,16 @@ kernel_dbg_exc:
* An interrupt came in while soft-disabled; clear EE in SRR1,
* clear paca->hard_enabled and return.
*/
+masked_doorbell_book3e:
+ mtcr r10
+ /* Resend the doorbell to fire again when ints enabled */
+ mfspr r10,SPRN_PIR
+ PPC_MSGSND(r10)
+ b masked_interrupt_book3e_common
+
masked_interrupt_book3e:
mtcr r10
+masked_interrupt_book3e_common:
stb r11,PACAHARDIRQEN(r13)
mfspr r10,SPRN_SRR1
rldicl r11,r10,48,1 /* clear MSR_EE */
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index a85f4874cba7..41b02c792aa3 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -40,7 +40,6 @@ __start_interrupts:
.globl system_reset_pSeries;
system_reset_pSeries:
HMT_MEDIUM;
- DO_KVM 0x100;
SET_SCRATCH0(r13)
#ifdef CONFIG_PPC_P7_NAP
BEGIN_FTR_SECTION
@@ -50,82 +49,73 @@ BEGIN_FTR_SECTION
* state loss at this time.
*/
mfspr r13,SPRN_SRR1
- rlwinm r13,r13,47-31,30,31
- cmpwi cr0,r13,1
- bne 1f
- b .power7_wakeup_noloss
-1: cmpwi cr0,r13,2
- bne 1f
- b .power7_wakeup_loss
+ rlwinm. r13,r13,47-31,30,31
+ beq 9f
+
+ /* waking up from powersave (nap) state */
+ cmpwi cr1,r13,2
/* Total loss of HV state is fatal, we could try to use the
* PIR to locate a PACA, then use an emergency stack etc...
* but for now, let's just stay stuck here
*/
-1: cmpwi cr0,r13,3
- beq .
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE_206)
+ bgt cr1,.
+ GET_PACA(r13)
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ lbz r0,PACAPROCSTART(r13)
+ cmpwi r0,0x80
+ bne 1f
+ li r0,0
+ stb r0,PACAPROCSTART(r13)
+ b kvm_start_guest
+1:
+#endif
+
+ beq cr1,2f
+ b .power7_wakeup_noloss
+2: b .power7_wakeup_loss
+9:
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
#endif /* CONFIG_PPC_P7_NAP */
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+ NOTEST, 0x100)
. = 0x200
-_machine_check_pSeries:
- HMT_MEDIUM
- DO_KVM 0x200
- SET_SCRATCH0(r13)
- EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
+machine_check_pSeries_1:
+ /* This is moved out of line as it can be patched by FW, but
+ * some code path might still want to branch into the original
+ * vector
+ */
+ b machine_check_pSeries
. = 0x300
.globl data_access_pSeries
data_access_pSeries:
HMT_MEDIUM
- DO_KVM 0x300
SET_SCRATCH0(r13)
+#ifndef CONFIG_POWER4_ONLY
BEGIN_FTR_SECTION
- GET_PACA(r13)
- std r9,PACA_EXSLB+EX_R9(r13)
- std r10,PACA_EXSLB+EX_R10(r13)
- mfspr r10,SPRN_DAR
- mfspr r9,SPRN_DSISR
- srdi r10,r10,60
- rlwimi r10,r9,16,0x20
- mfcr r9
- cmpwi r10,0x2c
- beq do_stab_bolted_pSeries
- ld r10,PACA_EXSLB+EX_R10(r13)
- std r11,PACA_EXGEN+EX_R11(r13)
- ld r11,PACA_EXSLB+EX_R9(r13)
- std r12,PACA_EXGEN+EX_R12(r13)
- GET_SCRATCH0(r12)
- std r10,PACA_EXGEN+EX_R10(r13)
- std r11,PACA_EXGEN+EX_R9(r13)
- std r12,PACA_EXGEN+EX_R13(r13)
- EXCEPTION_PROLOG_PSERIES_1(data_access_common, EXC_STD)
-FTR_SECTION_ELSE
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD)
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
+ b data_access_check_stab
+data_access_not_stab:
+END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
+#endif
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
+ KVMTEST_PR, 0x300)
. = 0x380
.globl data_access_slb_pSeries
data_access_slb_pSeries:
HMT_MEDIUM
- DO_KVM 0x380
SET_SCRATCH0(r13)
- GET_PACA(r13)
+ EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
std r3,PACA_EXSLB+EX_R3(r13)
mfspr r3,SPRN_DAR
- std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
- mfcr r9
#ifdef __DISABLED__
/* Keep that around for when we re-implement dynamic VSIDs */
cmpdi r3,0
bge slb_miss_user_pseries
#endif /* __DISABLED__ */
- std r10,PACA_EXSLB+EX_R10(r13)
- std r11,PACA_EXSLB+EX_R11(r13)
- std r12,PACA_EXSLB+EX_R12(r13)
- GET_SCRATCH0(r10)
- std r10,PACA_EXSLB+EX_R13(r13)
- mfspr r12,SPRN_SRR1 /* and SRR1 */
+ mfspr r12,SPRN_SRR1
#ifndef CONFIG_RELOCATABLE
b .slb_miss_realmode
#else
@@ -147,24 +137,16 @@ data_access_slb_pSeries:
.globl instruction_access_slb_pSeries
instruction_access_slb_pSeries:
HMT_MEDIUM
- DO_KVM 0x480
SET_SCRATCH0(r13)
- GET_PACA(r13)
+ EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480)
std r3,PACA_EXSLB+EX_R3(r13)
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
- std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
- mfcr r9
#ifdef __DISABLED__
/* Keep that around for when we re-implement dynamic VSIDs */
cmpdi r3,0
bge slb_miss_user_pseries
#endif /* __DISABLED__ */
- std r10,PACA_EXSLB+EX_R10(r13)
- std r11,PACA_EXSLB+EX_R11(r13)
- std r12,PACA_EXSLB+EX_R12(r13)
- GET_SCRATCH0(r10)
- std r10,PACA_EXSLB+EX_R13(r13)
- mfspr r12,SPRN_SRR1 /* and SRR1 */
+ mfspr r12,SPRN_SRR1
#ifndef CONFIG_RELOCATABLE
b .slb_miss_realmode
#else
@@ -184,26 +166,46 @@ instruction_access_slb_pSeries:
hardware_interrupt_pSeries:
hardware_interrupt_hv:
BEGIN_FTR_SECTION
- _MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD)
+ _MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt,
+ EXC_HV, SOFTEN_TEST_HV)
+ KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x502)
FTR_SECTION_ELSE
- _MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV)
- ALT_FTR_SECTION_END_IFCLR(CPU_FTR_HVMODE_206)
+ _MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt,
+ EXC_STD, SOFTEN_TEST_HV_201)
+ KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x500)
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
STD_EXCEPTION_PSERIES(0x600, 0x600, alignment)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x600)
+
STD_EXCEPTION_PSERIES(0x700, 0x700, program_check)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x700)
+
STD_EXCEPTION_PSERIES(0x800, 0x800, fp_unavailable)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800)
MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer)
- MASKABLE_EXCEPTION_HV(0x980, 0x980, decrementer)
+ MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer)
STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00)
+
STD_EXCEPTION_PSERIES(0xb00, 0xb00, trap_0b)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xb00)
. = 0xc00
.globl system_call_pSeries
system_call_pSeries:
HMT_MEDIUM
- DO_KVM 0xc00
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+ SET_SCRATCH0(r13)
+ GET_PACA(r13)
+ std r9,PACA_EXGEN+EX_R9(r13)
+ std r10,PACA_EXGEN+EX_R10(r13)
+ mfcr r9
+ KVMTEST(0xc00)
+ GET_SCRATCH0(r13)
+#endif
BEGIN_FTR_SECTION
cmpdi r0,0x1ebe
beq- 1f
@@ -220,6 +222,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
rfid
b . /* prevent speculative execution */
+ KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xc00)
+
/* Fast LE/BE switch system call */
1: mfspr r12,SPRN_SRR1
xori r12,r12,MSR_LE
@@ -228,6 +232,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
b .
STD_EXCEPTION_PSERIES(0xd00, 0xd00, single_step)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xd00)
/* At 0xe??? we have a bunch of hypervisor exceptions, we branch
* out of line to handle them
@@ -262,30 +267,93 @@ vsx_unavailable_pSeries_1:
#ifdef CONFIG_CBE_RAS
STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
+ KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
#endif /* CONFIG_CBE_RAS */
+
STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
+ KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
+
#ifdef CONFIG_CBE_RAS
STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
+ KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
#endif /* CONFIG_CBE_RAS */
+
STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x1700)
+
#ifdef CONFIG_CBE_RAS
STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
+ KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
#endif /* CONFIG_CBE_RAS */
. = 0x3000
/*** Out of line interrupts support ***/
+ /* moved from 0x200 */
+machine_check_pSeries:
+ .globl machine_check_fwnmi
+machine_check_fwnmi:
+ HMT_MEDIUM
+ SET_SCRATCH0(r13) /* save r13 */
+ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common,
+ EXC_STD, KVMTEST, 0x200)
+ KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200)
+
+#ifndef CONFIG_POWER4_ONLY
+ /* moved from 0x300 */
+data_access_check_stab:
+ GET_PACA(r13)
+ std r9,PACA_EXSLB+EX_R9(r13)
+ std r10,PACA_EXSLB+EX_R10(r13)
+ mfspr r10,SPRN_DAR
+ mfspr r9,SPRN_DSISR
+ srdi r10,r10,60
+ rlwimi r10,r9,16,0x20
+#ifdef CONFIG_KVM_BOOK3S_PR
+ lbz r9,HSTATE_IN_GUEST(r13)
+ rlwimi r10,r9,8,0x300
+#endif
+ mfcr r9
+ cmpwi r10,0x2c
+ beq do_stab_bolted_pSeries
+ mtcrf 0x80,r9
+ ld r9,PACA_EXSLB+EX_R9(r13)
+ ld r10,PACA_EXSLB+EX_R10(r13)
+ b data_access_not_stab
+do_stab_bolted_pSeries:
+ std r11,PACA_EXSLB+EX_R11(r13)
+ std r12,PACA_EXSLB+EX_R12(r13)
+ GET_SCRATCH0(r10)
+ std r10,PACA_EXSLB+EX_R13(r13)
+ EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
+#endif /* CONFIG_POWER4_ONLY */
+
+ KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x300)
+ KVM_HANDLER_PR_SKIP(PACA_EXSLB, EXC_STD, 0x380)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400)
+ KVM_HANDLER_PR(PACA_EXSLB, EXC_STD, 0x480)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
+ KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982)
+
+ .align 7
/* moved from 0xe00 */
- STD_EXCEPTION_HV(., 0xe00, h_data_storage)
- STD_EXCEPTION_HV(., 0xe20, h_instr_storage)
- STD_EXCEPTION_HV(., 0xe40, emulation_assist)
- STD_EXCEPTION_HV(., 0xe60, hmi_exception) /* need to flush cache ? */
+ STD_EXCEPTION_HV(., 0xe02, h_data_storage)
+ KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02)
+ STD_EXCEPTION_HV(., 0xe22, h_instr_storage)
+ KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22)
+ STD_EXCEPTION_HV(., 0xe42, emulation_assist)
+ KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42)
+ STD_EXCEPTION_HV(., 0xe62, hmi_exception) /* need to flush cache ? */
+ KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62)
/* moved from 0xf00 */
STD_EXCEPTION_PSERIES(., 0xf00, performance_monitor)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf00)
STD_EXCEPTION_PSERIES(., 0xf20, altivec_unavailable)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20)
STD_EXCEPTION_PSERIES(., 0xf40, vsx_unavailable)
+ KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
/*
* An interrupt came in while soft-disabled; clear EE in SRR1,
@@ -317,14 +385,6 @@ masked_Hinterrupt:
hrfid
b .
- .align 7
-do_stab_bolted_pSeries:
- std r11,PACA_EXSLB+EX_R11(r13)
- std r12,PACA_EXSLB+EX_R12(r13)
- GET_SCRATCH0(r10)
- std r10,PACA_EXSLB+EX_R13(r13)
- EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
-
#ifdef CONFIG_PPC_PSERIES
/*
* Vectors for the FWNMI option. Share common code.
@@ -334,14 +394,8 @@ do_stab_bolted_pSeries:
system_reset_fwnmi:
HMT_MEDIUM
SET_SCRATCH0(r13) /* save r13 */
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
-
- .globl machine_check_fwnmi
- .align 7
-machine_check_fwnmi:
- HMT_MEDIUM
- SET_SCRATCH0(r13) /* save r13 */
- EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+ NOTEST, 0x100)
#endif /* CONFIG_PPC_PSERIES */
@@ -376,7 +430,11 @@ slb_miss_user_pseries:
/* 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
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 5e12b741ba5f..f8e971ba94f5 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -93,6 +93,30 @@ _ENTRY(_start);
bl early_init
+#ifdef CONFIG_RELOCATABLE
+ /*
+ * r25 will contain RPN/ERPN for the start address of memory
+ *
+ * Add the difference between KERNELBASE and PAGE_OFFSET to the
+ * start of physical memory to get kernstart_addr.
+ */
+ lis r3,kernstart_addr@ha
+ la r3,kernstart_addr@l(r3)
+
+ lis r4,KERNELBASE@h
+ ori r4,r4,KERNELBASE@l
+ lis r5,PAGE_OFFSET@h
+ ori r5,r5,PAGE_OFFSET@l
+ subf r4,r5,r4
+
+ rlwinm r6,r25,0,28,31 /* ERPN */
+ rlwinm r7,r25,0,0,3 /* RPN - assuming 256 MB page size */
+ add r7,r7,r4
+
+ stw r6,0(r3)
+ stw r7,4(r3)
+#endif
+
/*
* Decide what sort of machine this is and initialize the MMU.
*/
@@ -1001,9 +1025,6 @@ clear_utlb_entry:
lis r3,PAGE_OFFSET@h
ori r3,r3,PAGE_OFFSET@l
- /* Kernel is at the base of RAM */
- li r4, 0 /* Load the kernel physical address */
-
/* Load the kernel PID = 0 */
li r0,0
mtspr SPRN_PID,r0
@@ -1013,9 +1034,8 @@ clear_utlb_entry:
clrrwi r3,r3,12 /* Mask off the effective page number */
ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M
- /* Word 1 */
- clrrwi r4,r4,12 /* Mask off the real page number */
- /* ERPN is 0 for first 4GB page */
+ /* Word 1 - use r25. RPN is the same as the original entry */
+
/* Word 2 */
li r5,0
ori r5,r5,PPC47x_TLB2_S_RWX
@@ -1026,7 +1046,7 @@ clear_utlb_entry:
/* We write to way 0 and bolted 0 */
lis r0,0x8800
tlbwe r3,r0,0
- tlbwe r4,r0,1
+ tlbwe r25,r0,1
tlbwe r5,r0,2
/*
@@ -1124,7 +1144,13 @@ head_start_common:
lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
mtspr SPRN_IVPR,r4
- addis r22,r22,KERNELBASE@h
+ /*
+ * If the kernel was loaded at a non-zero 256 MB page, we need to
+ * mask off the most significant 4 bits to get the relative address
+ * from the start of physical memory
+ */
+ rlwinm r22,r22,0,4,31
+ addis r22,r22,PAGE_OFFSET@h
mtlr r22
isync
blr
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index ba504099844a..3564c49c683e 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -255,7 +255,7 @@ generic_secondary_common_init:
mtctr r23
bctrl
-3: LOAD_REG_ADDR(r3, boot_cpu_count) /* Decrement boot_cpu_count */
+3: LOAD_REG_ADDR(r3, spinning_secondaries) /* Decrement spinning_secondaries */
lwarx r4,0,r3
subi r4,r4,1
stwcx. r4,0,r3
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index a0bf158c8b47..fc921bf62e15 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -20,33 +20,43 @@
addi reg,reg,val@l
#endif
+/*
+ * Macro used to get to thread save registers.
+ * Note that entries 0-3 are used for the prolog code, and the remaining
+ * entries are available for specific exception use in the event a handler
+ * requires more than 4 scratch registers.
+ */
+#define THREAD_NORMSAVE(offset) (THREAD_NORMSAVES + (offset * 4))
+
#define NORMAL_EXCEPTION_PROLOG \
- mtspr SPRN_SPRG_WSCRATCH0,r10;/* save two registers to work with */\
- mtspr SPRN_SPRG_WSCRATCH1,r11; \
- mtspr SPRN_SPRG_WSCRATCH2,r1; \
- mfcr r10; /* save CR in r10 for now */\
+ mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \
+ mfspr r10, SPRN_SPRG_THREAD; \
+ stw r11, THREAD_NORMSAVE(0)(r10); \
+ stw r13, THREAD_NORMSAVE(2)(r10); \
+ mfcr r13; /* save CR in r13 for now */\
mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
+ mr r11, r1; \
beq 1f; \
- mfspr r1,SPRN_SPRG_THREAD; /* if from user, start at top of */\
- lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
- ALLOC_STACK_FRAME(r1, THREAD_SIZE); \
-1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
- mr r11,r1; \
- stw r10,_CCR(r11); /* save various registers */\
+ /* if from user, start at top of this thread's kernel stack */ \
+ lwz r11, THREAD_INFO-THREAD(r10); \
+ ALLOC_STACK_FRAME(r11, THREAD_SIZE); \
+1 : subi r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */ \
+ stw r13, _CCR(r11); /* save various registers */ \
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
- mfspr r10,SPRN_SPRG_RSCRATCH0; \
- stw r10,GPR10(r11); \
- mfspr r12,SPRN_SPRG_RSCRATCH1; \
+ mfspr r13, SPRN_SPRG_RSCRATCH0; \
+ stw r13, GPR10(r11); \
+ lwz r12, THREAD_NORMSAVE(0)(r10); \
stw r12,GPR11(r11); \
+ lwz r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */ \
mflr r10; \
stw r10,_LINK(r11); \
- mfspr r10,SPRN_SPRG_RSCRATCH2; \
mfspr r12,SPRN_SRR0; \
- stw r10,GPR1(r11); \
+ stw r1, GPR1(r11); \
mfspr r9,SPRN_SRR1; \
- stw r10,0(r11); \
+ stw r1, 0(r11); \
+ mr r1, r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
lis r10, STACK_FRAME_REGS_MARKER@ha;/* exception frame marker */ \
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 5ecf54cfa7d4..50845924b7d9 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -346,11 +346,12 @@ interrupt_base:
/* Data TLB Error Interrupt */
START_EXCEPTION(DataTLBError)
mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
- mtspr SPRN_SPRG_WSCRATCH1, r11
- mtspr SPRN_SPRG_WSCRATCH2, r12
- mtspr SPRN_SPRG_WSCRATCH3, r13
- mfcr r11
- mtspr SPRN_SPRG_WSCRATCH4, r11
+ mfspr r10, SPRN_SPRG_THREAD
+ stw r11, THREAD_NORMSAVE(0)(r10)
+ stw r12, THREAD_NORMSAVE(1)(r10)
+ stw r13, THREAD_NORMSAVE(2)(r10)
+ mfcr r13
+ stw r13, THREAD_NORMSAVE(3)(r10)
mfspr r10, SPRN_DEAR /* Get faulting address */
/* If we are faulting a kernel address, we have to use the
@@ -416,11 +417,12 @@ interrupt_base:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRN_SPRG_RSCRATCH4
+ mfspr r10, SPRN_SPRG_THREAD
+ lwz r11, THREAD_NORMSAVE(3)(r10)
mtcr r11
- mfspr r13, SPRN_SPRG_RSCRATCH3
- mfspr r12, SPRN_SPRG_RSCRATCH2
- mfspr r11, SPRN_SPRG_RSCRATCH1
+ lwz r13, THREAD_NORMSAVE(2)(r10)
+ lwz r12, THREAD_NORMSAVE(1)(r10)
+ lwz r11, THREAD_NORMSAVE(0)(r10)
mfspr r10, SPRN_SPRG_RSCRATCH0
b DataStorage
@@ -432,11 +434,12 @@ interrupt_base:
*/
START_EXCEPTION(InstructionTLBError)
mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
- mtspr SPRN_SPRG_WSCRATCH1, r11
- mtspr SPRN_SPRG_WSCRATCH2, r12
- mtspr SPRN_SPRG_WSCRATCH3, r13
- mfcr r11
- mtspr SPRN_SPRG_WSCRATCH4, r11
+ mfspr r10, SPRN_SPRG_THREAD
+ stw r11, THREAD_NORMSAVE(0)(r10)
+ stw r12, THREAD_NORMSAVE(1)(r10)
+ stw r13, THREAD_NORMSAVE(2)(r10)
+ mfcr r13
+ stw r13, THREAD_NORMSAVE(3)(r10)
mfspr r10, SPRN_SRR0 /* Get faulting address */
/* If we are faulting a kernel address, we have to use the
@@ -496,11 +499,12 @@ interrupt_base:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRN_SPRG_RSCRATCH4
+ mfspr r10, SPRN_SPRG_THREAD
+ lwz r11, THREAD_NORMSAVE(3)(r10)
mtcr r11
- mfspr r13, SPRN_SPRG_RSCRATCH3
- mfspr r12, SPRN_SPRG_RSCRATCH2
- mfspr r11, SPRN_SPRG_RSCRATCH1
+ lwz r13, THREAD_NORMSAVE(2)(r10)
+ lwz r12, THREAD_NORMSAVE(1)(r10)
+ lwz r11, THREAD_NORMSAVE(0)(r10)
mfspr r10, SPRN_SPRG_RSCRATCH0
b InstructionStorage
@@ -621,11 +625,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
tlbwe
/* Done...restore registers and get out of here. */
- mfspr r11, SPRN_SPRG_RSCRATCH4
+ mfspr r10, SPRN_SPRG_THREAD
+ lwz r11, THREAD_NORMSAVE(3)(r10)
mtcr r11
- mfspr r13, SPRN_SPRG_RSCRATCH3
- mfspr r12, SPRN_SPRG_RSCRATCH2
- mfspr r11, SPRN_SPRG_RSCRATCH1
+ lwz r13, THREAD_NORMSAVE(2)(r10)
+ lwz r12, THREAD_NORMSAVE(1)(r10)
+ lwz r11, THREAD_NORMSAVE(0)(r10)
mfspr r10, SPRN_SPRG_RSCRATCH0
rfi /* Force context change */
@@ -656,7 +661,7 @@ load_up_spe:
cmpi 0,r4,0
beq 1f
addi r4,r4,THREAD /* want THREAD of last_task_used_spe */
- SAVE_32EVRS(0,r10,r4)
+ SAVE_32EVRS(0,r10,r4,THREAD_EVR0)
evxor evr10, evr10, evr10 /* clear out evr10 */
evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */
li r5,THREAD_ACC
@@ -676,7 +681,7 @@ load_up_spe:
stw r4,THREAD_USED_SPE(r5)
evlddx evr4,r10,r5
evmra evr4,evr4
- REST_32EVRS(0,r10,r5)
+ REST_32EVRS(0,r10,r5,THREAD_EVR0)
#ifndef CONFIG_SMP
subi r4,r5,THREAD
stw r4,last_task_used_spe@l(r3)
@@ -787,13 +792,11 @@ _GLOBAL(giveup_spe)
addi r3,r3,THREAD /* want THREAD of task */
lwz r5,PT_REGS(r3)
cmpi 0,r5,0
- SAVE_32EVRS(0, r4, r3)
+ SAVE_32EVRS(0, r4, r3, THREAD_EVR0)
evxor evr6, evr6, evr6 /* clear out evr6 */
evmwumiaa evr6, evr6, evr6 /* evr6 <- ACC = 0 * 0 + ACC */
li r4,THREAD_ACC
evstddx evr6, r4, r3 /* save off accumulator */
- mfspr r6,SPRN_SPEFSCR
- stw r6,THREAD_SPEFSCR(r3) /* save spefscr register value */
beq 1f
lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
lis r3,MSR_SPE@h
diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
index 47a1a983ff88..3e2b95c6ae67 100644
--- a/arch/powerpc/kernel/idle_e500.S
+++ b/arch/powerpc/kernel/idle_e500.S
@@ -26,6 +26,17 @@ _GLOBAL(e500_idle)
ori r4,r4,_TLF_NAPPING /* so when we take an exception */
stw r4,TI_LOCAL_FLAGS(r3) /* it will return to our caller */
+#ifdef CONFIG_E500MC
+ wrteei 1
+1: wait
+
+ /*
+ * Guard against spurious wakeups (e.g. from a hypervisor) --
+ * any real interrupt will cause us to return to LR due to
+ * _TLF_NAPPING.
+ */
+ b 1b
+#else
/* Check if we can nap or doze, put HID0 mask in r3 */
lis r3,0
BEGIN_FTR_SECTION
@@ -72,6 +83,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
mtmsr r7
isync
2: b 2b
+#endif /* !E500MC */
/*
* Return from NAP/DOZE mode, restore some CPU specific registers,
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index f8f0bc7f1d4f..3a70845a51c7 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -73,7 +73,6 @@ _GLOBAL(power7_idle)
b .
_GLOBAL(power7_wakeup_loss)
- GET_PACA(r13)
ld r1,PACAR1(r13)
REST_NVGPRS(r1)
REST_GPR(2, r1)
@@ -87,7 +86,6 @@ _GLOBAL(power7_wakeup_loss)
rfid
_GLOBAL(power7_wakeup_noloss)
- GET_PACA(r13)
ld r1,PACAR1(r13)
ld r4,_MSR(r1)
ld r5,_NIP(r1)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5b428e308666..d281fb6f12f3 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -157,12 +157,6 @@ notrace void arch_local_irq_restore(unsigned long en)
if (get_hard_enabled())
return;
-#if defined(CONFIG_BOOKE) && defined(CONFIG_SMP)
- /* Check for pending doorbell interrupts and resend to ourself */
- if (cpu_has_feature(CPU_FTR_DBELL))
- smp_muxed_ipi_resend();
-#endif
-
/*
* Need to hard-enable interrupts here. Since currently disabled,
* no need to take further asm precautions against preemption; but
@@ -457,11 +451,18 @@ static inline void do_softirq_onstack(void)
curtp = current_thread_info();
irqtp = softirq_ctx[smp_processor_id()];
irqtp->task = curtp->task;
+ irqtp->flags = 0;
current->thread.ksp_limit = (unsigned long)irqtp +
_ALIGN_UP(sizeof(struct thread_info), 16);
call_do_softirq(irqtp);
current->thread.ksp_limit = saved_sp_limit;
irqtp->task = NULL;
+
+ /* Set any flag that may have been set on the
+ * alternate stack
+ */
+ if (irqtp->flags)
+ set_bits(irqtp->flags, &curtp->flags);
}
void do_softirq(void)
@@ -750,7 +751,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
if (irq_setup_virq(host, virq, hwirq))
return NO_IRQ;
- printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n",
+ pr_debug("irq: irq %lu on host %s mapped to virtual irq %u\n",
hwirq, host->of_node ? host->of_node->full_name : "null", virq);
return virq;
@@ -882,6 +883,41 @@ unsigned int irq_find_mapping(struct irq_host *host,
}
EXPORT_SYMBOL_GPL(irq_find_mapping);
+#ifdef CONFIG_SMP
+int irq_choose_cpu(const struct cpumask *mask)
+{
+ int cpuid;
+
+ if (cpumask_equal(mask, cpu_all_mask)) {
+ static int irq_rover;
+ static DEFINE_RAW_SPINLOCK(irq_rover_lock);
+ unsigned long flags;
+
+ /* Round-robin distribution... */
+do_round_robin:
+ raw_spin_lock_irqsave(&irq_rover_lock, flags);
+
+ irq_rover = cpumask_next(irq_rover, cpu_online_mask);
+ if (irq_rover >= nr_cpu_ids)
+ irq_rover = cpumask_first(cpu_online_mask);
+
+ cpuid = irq_rover;
+
+ raw_spin_unlock_irqrestore(&irq_rover_lock, flags);
+ } else {
+ cpuid = cpumask_first_and(mask, cpu_online_mask);
+ if (cpuid >= nr_cpu_ids)
+ goto do_round_robin;
+ }
+
+ return get_hard_smp_processor_id(cpuid);
+}
+#else
+int irq_choose_cpu(const struct cpumask *mask)
+{
+ return hard_smp_processor_id();
+}
+#endif
unsigned int irq_radix_revmap_lookup(struct irq_host *host,
irq_hw_number_t hwirq)
diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c
new file mode 100644
index 000000000000..368d158d665d
--- /dev/null
+++ b/arch/powerpc/kernel/jump_label.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/jump_label.h>
+#include <asm/code-patching.h>
+
+void arch_jump_label_transform(struct jump_entry *entry,
+ enum jump_label_type type)
+{
+ u32 *addr = (u32 *)(unsigned long)entry->code;
+
+ if (type == JUMP_LABEL_ENABLE)
+ patch_branch(addr, entry->target, 0);
+ else
+ patch_instruction(addr, PPC_INST_NOP);
+}
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index 7ee50f0547cb..6658a1589955 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -126,7 +126,7 @@ void __init reserve_crashkernel(void)
/* We might have got these values via the command line or the
* device tree, either way sanitise them now. */
- crash_size = crashk_res.end - crashk_res.start + 1;
+ crash_size = resource_size(&crashk_res);
#ifndef CONFIG_RELOCATABLE
if (crashk_res.start != KDUMP_KERNELBASE)
@@ -222,7 +222,7 @@ static void __init export_crashk_values(struct device_node *node)
if (crashk_res.start != 0) {
prom_add_property(node, &crashk_base_prop);
- crashk_size = crashk_res.end - crashk_res.start + 1;
+ crashk_size = resource_size(&crashk_res);
prom_add_property(node, &crashk_size_prop);
}
}
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index e89df59cdc5a..616921ef1439 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -339,7 +339,7 @@ _GLOBAL(real_205_writeb)
#endif /* CONFIG_PPC_PASEMI */
-#ifdef CONFIG_CPU_FREQ_PMAC64
+#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE)
/*
* SCOM access functions for 970 (FX only for now)
*
@@ -408,7 +408,7 @@ _GLOBAL(scom970_write)
/* restore interrupts */
mtmsrd r5,1
blr
-#endif /* CONFIG_CPU_FREQ_PMAC64 */
+#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
/*
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 49cee9df225b..a1cd701b5753 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -31,20 +31,6 @@
LIST_HEAD(module_bug_list);
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
-
- return vmalloc_exec(size);
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
const char *name)
@@ -93,7 +79,3 @@ int module_finalize(const Elf_Ehdr *hdr,
return 0;
}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index f832773fc28e..0b6d79617d7b 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -174,17 +174,6 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr,
return 0;
}
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *module)
-{
- printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n",
- module->name);
- return -ENOEXEC;
-}
-
static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
{
if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 8fbb12508bf3..9f44a775a106 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -243,16 +243,6 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
return 0;
}
-int apply_relocate(Elf64_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", me->name);
- return -ENOEXEC;
-}
-
/* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
gives the value maximum span in an instruction which uses a signed
offset) */
diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c
index 2cc5e0301d0b..fe21b515ca44 100644
--- a/arch/powerpc/kernel/mpc7450-pmu.c
+++ b/arch/powerpc/kernel/mpc7450-pmu.c
@@ -388,6 +388,11 @@ static int mpc7450_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
struct power_pmu mpc7450_pmu = {
@@ -405,7 +410,7 @@ struct power_pmu mpc7450_pmu = {
.cache_events = &mpc7450_cache_events,
};
-static int init_mpc7450_pmu(void)
+static int __init init_mpc7450_pmu(void)
{
if (!cur_cpu_spec->oprofile_cpu_type ||
strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450"))
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index 24582181b6ec..59dbf6abaaf3 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -26,7 +26,7 @@
#include <asm/topology.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#ifdef CONFIG_PPC_OF_PLATFORM_PCI
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index efeb88184182..0a5a899846bb 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -167,7 +167,7 @@ void setup_paca(struct paca_struct *new_paca)
* if we do a GET_PACA() before the feature fixups have been
* applied
*/
- if (cpu_has_feature(CPU_FTR_HVMODE_206))
+ if (cpu_has_feature(CPU_FTR_HVMODE))
mtspr(SPRN_SPRG_HPACA, local_paca);
#endif
mtspr(SPRN_SPRG_PACA, local_paca);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 893af2a9cd03..32656f105250 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -50,7 +50,7 @@ static int global_phb_number; /* Global phb counter */
resource_size_t isa_mem_base;
/* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
-unsigned int ppc_pci_flags = 0;
+unsigned int pci_flags = 0;
static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
@@ -107,7 +107,7 @@ static resource_size_t pcibios_io_size(const struct pci_controller *hose)
#ifdef CONFIG_PPC64
return hose->pci_io_size;
#else
- return hose->io_resource.end - hose->io_resource.start + 1;
+ return resource_size(&hose->io_resource);
#endif
}
@@ -842,9 +842,9 @@ int pci_proc_domain(struct pci_bus *bus)
{
struct pci_controller *hose = pci_bus_to_host(bus);
- if (!(ppc_pci_flags & PPC_PCI_ENABLE_PROC_DOMAINS))
+ if (!pci_has_flag(PCI_ENABLE_PROC_DOMAINS))
return 0;
- if (ppc_pci_flags & PPC_PCI_COMPAT_DOMAIN_0)
+ if (pci_has_flag(PCI_COMPAT_DOMAIN_0))
return hose->global_number != 0;
return 1;
}
@@ -920,13 +920,13 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
struct resource *res = dev->resource + i;
if (!res->flags)
continue;
- /* On platforms that have PPC_PCI_PROBE_ONLY set, we don't
+ /* On platforms that have PCI_PROBE_ONLY set, we don't
* consider 0 as an unassigned BAR value. It's technically
* a valid value, but linux doesn't like it... so when we can
* re-assign things, we do so, but if we can't, we keep it
* around and hope for the best...
*/
- if (res->start == 0 && !(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+ if (res->start == 0 && !pci_has_flag(PCI_PROBE_ONLY)) {
pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n",
pci_name(dev), i,
(unsigned long long)res->start,
@@ -973,7 +973,7 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
int i;
/* We don't do anything if PCI_PROBE_ONLY is set */
- if (ppc_pci_flags & PPC_PCI_PROBE_ONLY)
+ if (pci_has_flag(PCI_PROBE_ONLY))
return 0;
/* Job is a bit different between memory and IO */
@@ -1097,9 +1097,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
if (dev->is_added)
continue;
- /* Setup OF node pointer in the device */
- dev->dev.of_node = pci_device_to_OF_node(dev);
-
/* Fixup NUMA node as it may not be setup yet by the generic
* code and is needed by the DMA init
*/
@@ -1146,7 +1143,7 @@ void __devinit pci_fixup_cardbus(struct pci_bus *bus)
static int skip_isa_ioresource_align(struct pci_dev *dev)
{
- if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+ if (pci_has_flag(PCI_CAN_SKIP_ISA_ALIGN) &&
!(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
return 1;
return 0;
@@ -1274,7 +1271,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
* and as such ensure proper re-allocation
* later.
*/
- if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+ if (pci_has_flag(PCI_REASSIGN_ALL_RSRC))
goto clear_resource;
pr = pci_find_parent_resource(bus->self, res);
if (pr == res) {
@@ -1459,7 +1456,7 @@ void __init pcibios_resource_survey(void)
list_for_each_entry(b, &pci_root_buses, node)
pcibios_allocate_bus_resources(b);
- if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+ if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
pcibios_allocate_resources(0);
pcibios_allocate_resources(1);
}
@@ -1468,7 +1465,7 @@ void __init pcibios_resource_survey(void)
* the low IO area and the VGA memory area if they intersect the
* bus available resources to avoid allocating things on top of them
*/
- if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+ if (!pci_has_flag(PCI_PROBE_ONLY)) {
list_for_each_entry(b, &pci_root_buses, node)
pcibios_reserve_legacy_regions(b);
}
@@ -1476,7 +1473,7 @@ void __init pcibios_resource_survey(void)
/* Now, if the platform didn't decide to blindly trust the firmware,
* we proceed to assigning things that were left unassigned
*/
- if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+ if (!pci_has_flag(PCI_PROBE_ONLY)) {
pr_debug("PCI: Assigning unassigned resources...\n");
pci_assign_unassigned_resources();
}
@@ -1685,6 +1682,13 @@ int early_find_capability(struct pci_controller *hose, int bus, int devfn,
return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap);
}
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+ struct pci_controller *hose = bus->sysdata;
+
+ return of_node_get(hose->dn);
+}
+
/**
* pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
* @hose: Pointer to the PCI host controller instance structure
@@ -1705,7 +1709,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
hose->global_number);
return;
}
- bus->dev.of_node = of_node_get(node);
bus->secondary = hose->first_busno;
hose->bus = bus;
@@ -1728,3 +1731,21 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
if (mode == PCI_PROBE_NORMAL)
hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
}
+
+static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
+{
+ int i, class = dev->class >> 8;
+
+ if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
+ class == PCI_CLASS_BRIDGE_OTHER) &&
+ (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
+ (dev->bus->parent == NULL)) {
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ dev->resource[i].start = 0;
+ dev->resource[i].end = 0;
+ dev->resource[i].flags = 0;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MOTOROLA, PCI_ANY_ID, fixup_hide_host_resource_fsl);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl);
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index bedb370459f2..bb154511db5e 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -51,25 +51,6 @@ struct pci_dev *isa_bridge_pcidev;
EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
static void
-fixup_hide_host_resource_fsl(struct pci_dev *dev)
-{
- int i, class = dev->class >> 8;
-
- if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
- class == PCI_CLASS_BRIDGE_OTHER) &&
- (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
- (dev->bus->parent == NULL)) {
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
- }
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MOTOROLA, PCI_ANY_ID, fixup_hide_host_resource_fsl);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl);
-
-static void
fixup_cpc710_pci64(struct pci_dev* dev)
{
/* Hide the PCI64 BARs from the kernel as their content doesn't
@@ -167,150 +148,26 @@ pcibios_make_OF_bus_map(void)
#endif
}
-typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
-
-static struct device_node*
-scan_OF_pci_childs(struct device_node *parent, pci_OF_scan_iterator filter, void* data)
-{
- struct device_node *node;
- struct device_node* sub_node;
-
- for_each_child_of_node(parent, node) {
- const unsigned int *class_code;
-
- if (filter(node, data)) {
- of_node_put(node);
- return node;
- }
-
- /* For PCI<->PCI bridges or CardBus bridges, we go down
- * Note: some OFs create a parent node "multifunc-device" as
- * a fake root for all functions of a multi-function device,
- * we go down them as well.
- */
- class_code = of_get_property(node, "class-code", NULL);
- if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
- strcmp(node->name, "multifunc-device"))
- continue;
- sub_node = scan_OF_pci_childs(node, filter, data);
- if (sub_node) {
- of_node_put(node);
- return sub_node;
- }
- }
- return NULL;
-}
-
-static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
- unsigned int devfn)
-{
- struct device_node *np, *cnp;
- const u32 *reg;
- unsigned int psize;
-
- for_each_child_of_node(parent, np) {
- reg = of_get_property(np, "reg", &psize);
- if (reg && psize >= 4 && ((reg[0] >> 8) & 0xff) == devfn)
- return np;
-
- /* Note: some OFs create a parent node "multifunc-device" as
- * a fake root for all functions of a multi-function device,
- * we go down them as well. */
- if (!strcmp(np->name, "multifunc-device")) {
- cnp = scan_OF_for_pci_dev(np, devfn);
- if (cnp)
- return cnp;
- }
- }
- return NULL;
-}
-
-
-static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
-{
- struct device_node *parent, *np;
-
- /* Are we a root bus ? */
- if (bus->self == NULL || bus->parent == NULL) {
- struct pci_controller *hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return NULL;
- return of_node_get(hose->dn);
- }
-
- /* not a root bus, we need to get our parent */
- parent = scan_OF_for_pci_bus(bus->parent);
- if (parent == NULL)
- return NULL;
-
- /* now iterate for children for a match */
- np = scan_OF_for_pci_dev(parent, bus->self->devfn);
- of_node_put(parent);
-
- return np;
-}
-
-/*
- * Scans the OF tree for a device node matching a PCI device
- */
-struct device_node *
-pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
-{
- struct device_node *parent, *np;
-
- pr_debug("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
- parent = scan_OF_for_pci_bus(bus);
- if (parent == NULL)
- return NULL;
- pr_debug(" parent is %s\n", parent ? parent->full_name : "<NULL>");
- np = scan_OF_for_pci_dev(parent, devfn);
- of_node_put(parent);
- pr_debug(" result is %s\n", np ? np->full_name : "<NULL>");
-
- /* XXX most callers don't release the returned node
- * mostly because ppc64 doesn't increase the refcount,
- * we need to fix that.
- */
- return np;
-}
-EXPORT_SYMBOL(pci_busdev_to_OF_node);
-
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
-{
- return pci_busdev_to_OF_node(dev->bus, dev->devfn);
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
-static int
-find_OF_pci_device_filter(struct device_node* node, void* data)
-{
- return ((void *)node == data);
-}
/*
* Returns the PCI device matching a given OF node
*/
-int
-pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
+int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
{
- const unsigned int *reg;
- struct pci_controller* hose;
- struct pci_dev* dev = NULL;
-
- /* Make sure it's really a PCI device */
- hose = pci_find_hose_for_OF_device(node);
- if (!hose || !hose->dn)
- return -ENODEV;
- if (!scan_OF_pci_childs(hose->dn,
- find_OF_pci_device_filter, (void *)node))
+ struct pci_dev *dev = NULL;
+ const __be32 *reg;
+ int size;
+
+ /* Check if it might have a chance to be a PCI device */
+ if (!pci_find_hose_for_OF_device(node))
return -ENODEV;
- reg = of_get_property(node, "reg", NULL);
- if (!reg)
+
+ reg = of_get_property(node, "reg", &size);
+ if (!reg || size < 5 * sizeof(u32))
return -ENODEV;
- *bus = (reg[0] >> 16) & 0xff;
- *devfn = ((reg[0] >> 8) & 0xff);
+
+ *bus = (be32_to_cpup(&reg[0]) >> 16) & 0xff;
+ *devfn = (be32_to_cpup(&reg[0]) >> 8) & 0xff;
/* Ok, here we need some tweak. If we have already renumbered
* all busses, we can't rely on the OF bus number any more.
@@ -373,7 +230,7 @@ static int __init pcibios_init(void)
printk(KERN_INFO "PCI: Probing PCI hardware\n");
- if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+ if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
pci_assign_all_buses = 1;
/* Scan all of the recorded PCI controllers. */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index fc6452b6be9f..ab34046752bf 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -55,12 +55,12 @@ static int __init pcibios_init(void)
ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
if (pci_probe_only)
- ppc_pci_flags |= PPC_PCI_PROBE_ONLY;
+ pci_add_flags(PCI_PROBE_ONLY);
/* On ppc64, we always enable PCI domains and we keep domain 0
* backward compatible in /proc for video cards
*/
- ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+ pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
/* Scan all of the recorded PCI controllers. */
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 6baabc13306a..478f8d78716b 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -142,53 +142,6 @@ void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
traverse_pci_devices(dn, update_dn_pci_info, phb);
}
-/*
- * Traversal func that looks for a <busno,devfcn> value.
- * If found, the pci_dn is returned (thus terminating the traversal).
- */
-static void *is_devfn_node(struct device_node *dn, void *data)
-{
- int busno = ((unsigned long)data >> 8) & 0xff;
- int devfn = ((unsigned long)data) & 0xff;
- struct pci_dn *pci = dn->data;
-
- if (pci && (devfn == pci->devfn) && (busno == pci->busno))
- return dn;
- return NULL;
-}
-
-/*
- * This is the "slow" path for looking up a device_node from a
- * pci_dev. It will hunt for the device under its parent's
- * phb and then update of_node pointer.
- *
- * It may also do fixups on the actual device since this happens
- * on the first read/write.
- *
- * Note that it also must deal with devices that don't exist.
- * In this case it may probe for real hardware ("just in case")
- * and add a device_node to the device tree if necessary.
- *
- * Is this function necessary anymore now that dev->dev.of_node is
- * used to store the node pointer?
- *
- */
-struct device_node *fetch_dev_dn(struct pci_dev *dev)
-{
- struct pci_controller *phb = dev->sysdata;
- struct device_node *dn;
- unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
-
- if (WARN_ON(!phb))
- return NULL;
-
- dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval);
- if (dn)
- dev->dev.of_node = dn;
- return dn;
-}
-EXPORT_SYMBOL(fetch_dev_dn);
-
/**
* pci_devs_phb_init - Initialize phbs and pci devs under them.
*
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 1e89a72fd030..fe0a5ad6f73e 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -202,9 +202,9 @@ EXPORT_SYMBOL(of_create_pci_dev);
* this routine in turn call of_scan_bus() recusively to scan for more child
* devices.
*/
-void __devinit of_scan_pci_bridge(struct device_node *node,
- struct pci_dev *dev)
+void __devinit of_scan_pci_bridge(struct pci_dev *dev)
{
+ struct device_node *node = dev->dev.of_node;
struct pci_bus *bus;
const u32 *busrange, *ranges;
int len, i, mode;
@@ -238,7 +238,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
bus->primary = dev->bus->number;
bus->subordinate = busrange[1];
bus->bridge_ctl = 0;
- bus->dev.of_node = of_node_get(node);
/* parse ranges property */
/* PCI #address-cells == 3 and #size-cells == 2 always */
@@ -335,9 +334,7 @@ static void __devinit __of_scan_bus(struct device_node *node,
list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
- struct device_node *child = pci_device_to_OF_node(dev);
- if (child)
- of_scan_pci_bridge(child, dev);
+ of_scan_pci_bridge(dev);
}
}
}
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 822f63008ae1..10a140f82cb8 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1207,7 +1207,7 @@ struct pmu power_pmu = {
* here so there is no possibility of being interrupted.
*/
static void record_and_restart(struct perf_event *event, unsigned long val,
- struct pt_regs *regs, int nmi)
+ struct pt_regs *regs)
{
u64 period = event->hw.sample_period;
s64 prev, delta, left;
@@ -1258,7 +1258,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
if (event->attr.sample_type & PERF_SAMPLE_ADDR)
perf_get_data_addr(regs, &data.addr);
- if (perf_event_overflow(event, nmi, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
power_pmu_stop(event, 0);
}
}
@@ -1346,7 +1346,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
if ((int)val < 0) {
/* event has overflowed */
found = 1;
- record_and_restart(event, val, regs, nmi);
+ record_and_restart(event, val, regs);
}
}
@@ -1408,7 +1408,7 @@ power_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu
return NOTIFY_OK;
}
-int register_power_pmu(struct power_pmu *pmu)
+int __cpuinit register_power_pmu(struct power_pmu *pmu)
{
if (ppmu)
return -EBUSY; /* something's already registered */
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
index b0dc8f7069cd..0a6d2a9d569c 100644
--- a/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -568,7 +568,7 @@ static struct pmu fsl_emb_pmu = {
* here so there is no possibility of being interrupted.
*/
static void record_and_restart(struct perf_event *event, unsigned long val,
- struct pt_regs *regs, int nmi)
+ struct pt_regs *regs)
{
u64 period = event->hw.sample_period;
s64 prev, delta, left;
@@ -616,7 +616,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
perf_sample_data_init(&data, 0);
data.period = event->hw.last_period;
- if (perf_event_overflow(event, nmi, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
fsl_emb_pmu_stop(event, 0);
}
}
@@ -644,7 +644,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
if (event) {
/* event has overflowed */
found = 1;
- record_and_restart(event, val, regs, nmi);
+ record_and_restart(event, val, regs);
} else {
/*
* Disabled counter is negative,
diff --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/kernel/power4-pmu.c
index ead8b3c2649e..b4f1dda4d089 100644
--- a/arch/powerpc/kernel/power4-pmu.c
+++ b/arch/powerpc/kernel/power4-pmu.c
@@ -587,6 +587,11 @@ static int power4_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
static struct power_pmu power4_pmu = {
@@ -604,7 +609,7 @@ static struct power_pmu power4_pmu = {
.cache_events = &power4_cache_events,
};
-static int init_power4_pmu(void)
+static int __init init_power4_pmu(void)
{
if (!cur_cpu_spec->oprofile_cpu_type ||
strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4"))
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c
index eca0ac595cb6..a8757baa28f3 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/kernel/power5+-pmu.c
@@ -653,6 +653,11 @@ static int power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
static struct power_pmu power5p_pmu = {
@@ -672,7 +677,7 @@ static struct power_pmu power5p_pmu = {
.cache_events = &power5p_cache_events,
};
-static int init_power5p_pmu(void)
+static int __init init_power5p_pmu(void)
{
if (!cur_cpu_spec->oprofile_cpu_type ||
(strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+")
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c
index d5ff0f64a5e6..e7f06eb7a861 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/kernel/power5-pmu.c
@@ -595,6 +595,11 @@ static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
static struct power_pmu power5_pmu = {
@@ -612,7 +617,7 @@ static struct power_pmu power5_pmu = {
.cache_events = &power5_cache_events,
};
-static int init_power5_pmu(void)
+static int __init init_power5_pmu(void)
{
if (!cur_cpu_spec->oprofile_cpu_type ||
strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c
index 31603927e376..03b95e2c6d65 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/kernel/power6-pmu.c
@@ -516,6 +516,11 @@ static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
static struct power_pmu power6_pmu = {
@@ -535,7 +540,7 @@ static struct power_pmu power6_pmu = {
.cache_events = &power6_cache_events,
};
-static int init_power6_pmu(void)
+static int __init init_power6_pmu(void)
{
if (!cur_cpu_spec->oprofile_cpu_type ||
strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6"))
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c
index 593740fcb799..de83d6060dda 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/kernel/power7-pmu.c
@@ -342,6 +342,11 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
static struct power_pmu power7_pmu = {
@@ -360,7 +365,7 @@ static struct power_pmu power7_pmu = {
.cache_events = &power7_cache_events,
};
-static int init_power7_pmu(void)
+static int __init init_power7_pmu(void)
{
if (!cur_cpu_spec->oprofile_cpu_type ||
strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7"))
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 9a6e093858fe..8c2190206964 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -467,6 +467,11 @@ static int ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
+ [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { -1, -1 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
};
static struct power_pmu ppc970_pmu = {
@@ -484,7 +489,7 @@ static struct power_pmu ppc970_pmu = {
.cache_events = &ppc970_cache_events,
};
-static int init_ppc970_pmu(void)
+static int __init init_ppc970_pmu(void)
{
if (!cur_cpu_spec->oprofile_cpu_type ||
(strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970")
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 7d28f540200c..f5ae872a2ef0 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -18,7 +18,7 @@
#include <asm/cacheflush.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/checksum.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 91e52df3d81d..8f53954e75a3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -96,6 +96,7 @@ void flush_fp_to_thread(struct task_struct *tsk)
preempt_enable();
}
}
+EXPORT_SYMBOL_GPL(flush_fp_to_thread);
void enable_kernel_fp(void)
{
@@ -145,6 +146,7 @@ void flush_altivec_to_thread(struct task_struct *tsk)
preempt_enable();
}
}
+EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_VSX
@@ -186,6 +188,7 @@ void flush_vsx_to_thread(struct task_struct *tsk)
preempt_enable();
}
}
+EXPORT_SYMBOL_GPL(flush_vsx_to_thread);
#endif /* CONFIG_VSX */
#ifdef CONFIG_SPE
@@ -213,6 +216,7 @@ void flush_spe_to_thread(struct task_struct *tsk)
#ifdef CONFIG_SMP
BUG_ON(tsk != current);
#endif
+ tsk->thread.spefscr = mfspr(SPRN_SPEFSCR);
giveup_spe(tsk);
}
preempt_enable();
@@ -650,6 +654,8 @@ void show_regs(struct pt_regs * regs)
printbits(regs->msr, msr_bits);
printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
trap = TRAP(regs);
+ if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
+ printk("CFAR: "REG"\n", regs->orig_gpr3);
if (trap == 0x300 || trap == 0x600)
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
@@ -831,8 +837,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */
#endif
- set_fs(USER_DS);
-
/*
* If we exec out of a kernel thread then thread.regs will not be
* set. Do it now.
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 8c3112a57cf2..174e1e96175e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -69,6 +69,7 @@ unsigned long tce_alloc_start, tce_alloc_end;
u64 ppc64_rma_size;
#endif
static phys_addr_t first_memblock_size;
+static int __initdata boot_cpu_count;
static int __init early_parse_mem(char *p)
{
@@ -769,6 +770,13 @@ void __init early_init_devtree(void *params)
*/
of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
+#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
+ /* We'll later wait for secondaries to check in; there are
+ * NCPUS-1 non-boot CPUs :-)
+ */
+ spinning_secondaries = boot_cpu_count - 1;
+#endif
+
DBG(" <- early_init_devtree()\n");
}
@@ -862,16 +870,14 @@ static int prom_reconfig_notifier(struct notifier_block *nb,
switch (action) {
case PSERIES_RECONFIG_ADD:
err = of_finish_dynamic_node(node);
- if (err < 0) {
+ if (err < 0)
printk(KERN_ERR "finish_node returned %d\n", err);
- err = NOTIFY_BAD;
- }
break;
default:
- err = NOTIFY_DONE;
+ err = 0;
break;
}
- return err;
+ return notifier_from_errno(err);
}
static struct notifier_block prom_reconfig_nb = {
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index cb22024f2b42..05b7dd217f60 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -882,7 +882,7 @@ void user_disable_single_step(struct task_struct *task)
}
#ifdef CONFIG_HAVE_HW_BREAKPOINT
-void ptrace_triggered(struct perf_event *bp, int nmi,
+void ptrace_triggered(struct perf_event *bp,
struct perf_sample_data *data, struct pt_regs *regs)
{
struct perf_event_attr attr;
@@ -973,7 +973,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
&attr.bp_type);
thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
- ptrace_triggered, task);
+ ptrace_triggered, NULL, task);
if (IS_ERR(bp)) {
thread->ptrace_bps[0] = NULL;
ptrace_put_breakpoints(task);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 271ff6318eda..d5ca8236315c 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -24,6 +24,7 @@
#include <linux/cpumask.h>
#include <linux/memblock.h>
#include <linux/slab.h>
+#include <linux/reboot.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -38,7 +39,7 @@
#include <asm/udbg.h>
#include <asm/syscalls.h>
#include <asm/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/mmu.h>
#include <asm/topology.h>
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index bf5f5ce3a7bd..e037c7494fd8 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+#include <linux/reboot.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 54e66da8f743..6cd8f0196b6d 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -291,7 +291,7 @@ void __init find_and_init_phbs(void)
prop = of_get_property(of_chosen,
"linux,pci-assign-all-buses", NULL);
if (prop && *prop)
- ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
#endif /* CONFIG_PPC32 */
}
}
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 67f6c3b51357..481ef064c8f1 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -27,7 +27,7 @@
#include <asm/rtas.h>
#include <asm/prom.h>
#include <asm/nvram.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 79fca2651b65..b1d738d12890 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -375,6 +375,9 @@ void __init check_for_initrd(void)
int threads_per_core, threads_shift;
cpumask_t threads_core_mask;
+EXPORT_SYMBOL_GPL(threads_per_core);
+EXPORT_SYMBOL_GPL(threads_shift);
+EXPORT_SYMBOL_GPL(threads_core_mask);
static void __init cpu_init_thread_core_maps(int tpc)
{
@@ -704,29 +707,14 @@ static int powerpc_debugfs_init(void)
arch_initcall(powerpc_debugfs_init);
#endif
-static int ppc_dflt_bus_notify(struct notifier_block *nb,
- unsigned long action, void *data)
+void ppc_printk_progress(char *s, unsigned short hex)
{
- struct device *dev = data;
-
- /* We are only intereted in device addition */
- if (action != BUS_NOTIFY_ADD_DEVICE)
- return 0;
-
- set_dma_ops(dev, &dma_direct_ops);
-
- return NOTIFY_DONE;
+ pr_info("%s\n", s);
}
-static struct notifier_block ppc_dflt_plat_bus_notifier = {
- .notifier_call = ppc_dflt_bus_notify,
- .priority = INT_MAX,
-};
-
-static int __init setup_bus_notifier(void)
+void arch_setup_pdev_archdata(struct platform_device *pdev)
{
- bus_register_notifier(&platform_bus_type, &ppc_dflt_plat_bus_notifier);
- return 0;
+ pdev->archdata.dma_mask = DMA_BIT_MASK(32);
+ pdev->dev.dma_mask = &pdev->archdata.dma_mask;
+ set_dma_ops(&pdev->dev, &dma_direct_ops);
}
-
-arch_initcall(setup_bus_notifier);
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 620d792b52e4..209135af0a40 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -48,8 +48,8 @@ extern void bootx_init(unsigned long r4, unsigned long phys);
int boot_cpuid = -1;
EXPORT_SYMBOL_GPL(boot_cpuid);
-int __initdata boot_cpu_count;
int boot_cpuid_phys;
+EXPORT_SYMBOL_GPL(boot_cpuid_phys);
int smp_hw_index[NR_CPUS];
@@ -127,6 +127,8 @@ notrace void __init machine_init(unsigned long dt_ptr)
/* Do some early initialization based on the flat device tree */
early_init_devtree(__va(dt_ptr));
+ early_init_mmu();
+
probe_machine();
setup_kdump_trampoline();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index a88bf2713d41..aebef1320ed7 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -63,6 +63,7 @@
#include <asm/kexec.h>
#include <asm/mmu_context.h>
#include <asm/code-patching.h>
+#include <asm/kvm_ppc.h>
#include "setup.h"
@@ -73,7 +74,7 @@
#endif
int boot_cpuid = 0;
-int __initdata boot_cpu_count;
+int __initdata spinning_secondaries;
u64 ppc64_pft_size;
/* Pick defaults since we might want to patch instructions
@@ -253,11 +254,11 @@ void smp_release_cpus(void)
for (i = 0; i < 100000; i++) {
mb();
HMT_low();
- if (boot_cpu_count == 0)
+ if (spinning_secondaries == 0)
break;
udelay(1);
}
- DBG("boot_cpu_count = %d\n", boot_cpu_count);
+ DBG("spinning_secondaries = %d\n", spinning_secondaries);
DBG(" <- smp_release_cpus()\n");
}
@@ -580,6 +581,8 @@ void __init setup_arch(char **cmdline_p)
/* Initialize the MMU context management stuff */
mmu_context_init();
+ kvm_rma_init();
+
ppc64_boot_msg(0x15, "Setup Done");
}
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c
index 03e45c4a9ef1..640de836e466 100644
--- a/arch/powerpc/kernel/smp-tbsync.c
+++ b/arch/powerpc/kernel/smp-tbsync.c
@@ -11,7 +11,7 @@
#include <linux/unistd.h>
#include <linux/init.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
#include <asm/time.h>
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 8ebc6700b98d..7bf2187dfd99 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -33,7 +33,7 @@
#include <linux/topology.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -202,14 +202,6 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
smp_ops->cause_ipi(cpu, info->data);
}
-void smp_muxed_ipi_resend(void)
-{
- struct cpu_messages *info = &__get_cpu_var(ipi_message);
-
- if (info->messages)
- smp_ops->cause_ipi(smp_processor_id(), info->data);
-}
-
irqreturn_t smp_ipi_demux(void)
{
struct cpu_messages *info = &__get_cpu_var(ipi_message);
@@ -238,15 +230,26 @@ irqreturn_t smp_ipi_demux(void)
}
#endif /* CONFIG_PPC_SMP_MUXED_IPI */
+static inline void do_message_pass(int cpu, int msg)
+{
+ if (smp_ops->message_pass)
+ smp_ops->message_pass(cpu, msg);
+#ifdef CONFIG_PPC_SMP_MUXED_IPI
+ else
+ smp_muxed_ipi_message_pass(cpu, msg);
+#endif
+}
+
void smp_send_reschedule(int cpu)
{
if (likely(smp_ops))
- smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
+ do_message_pass(cpu, PPC_MSG_RESCHEDULE);
}
+EXPORT_SYMBOL_GPL(smp_send_reschedule);
void arch_send_call_function_single_ipi(int cpu)
{
- smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNC_SINGLE);
+ do_message_pass(cpu, PPC_MSG_CALL_FUNC_SINGLE);
}
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -254,7 +257,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
unsigned int cpu;
for_each_cpu(cpu, mask)
- smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION);
+ do_message_pass(cpu, PPC_MSG_CALL_FUNCTION);
}
#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
@@ -268,7 +271,7 @@ void smp_send_debugger_break(void)
for_each_online_cpu(cpu)
if (cpu != me)
- smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
+ do_message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
}
#endif
@@ -303,6 +306,10 @@ struct thread_info *current_set[NR_CPUS];
static void __devinit smp_store_cpu_info(int id)
{
per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
+#ifdef CONFIG_PPC_FSL_BOOK3E
+ per_cpu(next_tlbcam_idx, id)
+ = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1;
+#endif
}
void __init smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index f33acfd872ad..03b29a6759ab 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -544,7 +544,7 @@ DEFINE_PER_CPU(u8, irq_work_pending);
#endif /* 32 vs 64 bit */
-void set_irq_work_pending(void)
+void arch_irq_work_raise(void)
{
preempt_disable();
set_irq_work_pending_flag();
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 1a0141426cda..f19d9777d3c1 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1387,10 +1387,7 @@ void SPEFloatingPointException(struct pt_regs *regs)
int code = 0;
int err;
- preempt_disable();
- if (regs->msr & MSR_SPE)
- giveup_spe(current);
- preempt_enable();
+ flush_spe_to_thread(current);
spefscr = current->thread.spefscr;
fpexc_mode = current->thread.fpexc_mode;
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 23d65abbedce..faa82c1f3f68 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -31,6 +31,9 @@ void __init udbg_early_init(void)
#if defined(CONFIG_PPC_EARLY_DEBUG_LPAR)
/* For LPAR machines that have an HVC console on vterm 0 */
udbg_init_debug_lpar();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI)
+ /* For LPAR machines that have an HVSI console on vterm 0 */
+ udbg_init_debug_lpar_hvsi();
#elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
/* For use on Apple G5 machines */
udbg_init_pmac_realmode();
@@ -68,6 +71,8 @@ void __init udbg_early_init(void)
#ifdef CONFIG_PPC_EARLY_DEBUG
console_loglevel = 10;
+
+ register_early_udbg_console();
#endif
}
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 5f3cff83e089..33aa715dab28 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -387,8 +387,10 @@ static void kvmppc_44x_invalidate(struct kvm_vcpu *vcpu,
}
}
-void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
+void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
{
+ int usermode = vcpu->arch.shared->msr & MSR_PR;
+
vcpu->arch.shadow_pid = !usermode;
}
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index b7baff78f90c..78133deb4b64 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -20,7 +20,6 @@ config KVM
bool
select PREEMPT_NOTIFIERS
select ANON_INODES
- select KVM_MMIO
config KVM_BOOK3S_HANDLER
bool
@@ -28,16 +27,22 @@ config KVM_BOOK3S_HANDLER
config KVM_BOOK3S_32_HANDLER
bool
select KVM_BOOK3S_HANDLER
+ select KVM_MMIO
config KVM_BOOK3S_64_HANDLER
bool
select KVM_BOOK3S_HANDLER
+config KVM_BOOK3S_PR
+ bool
+ select KVM_MMIO
+
config KVM_BOOK3S_32
tristate "KVM support for PowerPC book3s_32 processors"
depends on EXPERIMENTAL && PPC_BOOK3S_32 && !SMP && !PTE_64BIT
select KVM
select KVM_BOOK3S_32_HANDLER
+ select KVM_BOOK3S_PR
---help---
Support running unmodified book3s_32 guest kernels
in virtual machines on book3s_32 host processors.
@@ -50,8 +55,8 @@ config KVM_BOOK3S_32
config KVM_BOOK3S_64
tristate "KVM support for PowerPC book3s_64 processors"
depends on EXPERIMENTAL && PPC_BOOK3S_64
- select KVM
select KVM_BOOK3S_64_HANDLER
+ select KVM
---help---
Support running unmodified book3s_64 and book3s_32 guest kernels
in virtual machines on book3s_64 host processors.
@@ -61,10 +66,34 @@ config KVM_BOOK3S_64
If unsure, say N.
+config KVM_BOOK3S_64_HV
+ bool "KVM support for POWER7 and PPC970 using hypervisor mode in host"
+ depends on KVM_BOOK3S_64
+ ---help---
+ Support running unmodified book3s_64 guest kernels in
+ virtual machines on POWER7 and PPC970 processors that have
+ hypervisor mode available to the host.
+
+ If you say Y here, KVM will use the hardware virtualization
+ facilities of POWER7 (and later) processors, meaning that
+ guest operating systems will run at full hardware speed
+ using supervisor and user modes. However, this also means
+ that KVM is not usable under PowerVM (pHyp), is only usable
+ on POWER7 (or later) processors and PPC970-family processors,
+ and cannot emulate a different processor from the host processor.
+
+ If unsure, say N.
+
+config KVM_BOOK3S_64_PR
+ def_bool y
+ depends on KVM_BOOK3S_64 && !KVM_BOOK3S_64_HV
+ select KVM_BOOK3S_PR
+
config KVM_440
bool "KVM support for PowerPC 440 processors"
depends on EXPERIMENTAL && 44x
select KVM
+ select KVM_MMIO
---help---
Support running unmodified 440 guest kernels in virtual machines on
440 host processors.
@@ -89,6 +118,7 @@ config KVM_E500
bool "KVM support for PowerPC E500 processors"
depends on EXPERIMENTAL && E500
select KVM
+ select KVM_MMIO
---help---
Support running unmodified E500 guest kernels in virtual machines on
E500 host processors.
@@ -99,6 +129,5 @@ config KVM_E500
If unsure, say N.
source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
endif # VIRTUALIZATION
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 4d6863823f69..08428e2c188d 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -38,24 +38,42 @@ kvm-e500-objs := \
e500_emulate.o
kvm-objs-$(CONFIG_KVM_E500) := $(kvm-e500-objs)
-kvm-book3s_64-objs := \
- $(common-objs-y) \
+kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
+ ../../../virt/kvm/coalesced_mmio.o \
fpu.o \
book3s_paired_singles.o \
- book3s.o \
+ book3s_pr.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-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-objs)
+
+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_rm_mmu.o \
+ book3s_64_vio_hv.o \
+ book3s_hv_builtin.o
+
+kvm-book3s_64-module-objs := \
+ ../../../virt/kvm/kvm_main.o \
+ powerpc.o \
+ emulate.o \
+ book3s.o \
+ $(kvm-book3s_64-objs-y)
+
+kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs)
kvm-book3s_32-objs := \
$(common-objs-y) \
fpu.o \
book3s_paired_singles.o \
book3s.o \
+ book3s_pr.o \
book3s_emulate.o \
book3s_interrupts.o \
book3s_mmu_hpte.o \
@@ -70,3 +88,4 @@ obj-$(CONFIG_KVM_E500) += kvm.o
obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o
obj-$(CONFIG_KVM_BOOK3S_32) += kvm.o
+obj-y += $(kvm-book3s_64-builtin-objs-y)
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 0f95b5cce033..f68a34d16035 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -17,7 +17,6 @@
#include <linux/kvm_host.h>
#include <linux/err.h>
#include <linux/slab.h>
-#include "trace.h"
#include <asm/reg.h>
#include <asm/cputable.h>
@@ -28,25 +27,17 @@
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
#include <asm/mmu_context.h>
+#include <asm/page.h>
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <linux/highmem.h>
+#include "trace.h"
+
#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
/* #define EXIT_DEBUG */
-/* #define DEBUG_EXT */
-
-static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
- ulong msr);
-
-/* Some compatibility defines */
-#ifdef CONFIG_PPC_BOOK3S_32
-#define MSR_USER32 MSR_USER
-#define MSR_USER64 MSR_USER
-#define HW_PAGE_SIZE PAGE_SIZE
-#endif
struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "exits", VCPU_STAT(sum_exits) },
@@ -77,100 +68,11 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
{
}
-void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
-{
-#ifdef CONFIG_PPC_BOOK3S_64
- memcpy(to_svcpu(vcpu)->slb, to_book3s(vcpu)->slb_shadow, sizeof(to_svcpu(vcpu)->slb));
- memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu,
- sizeof(get_paca()->shadow_vcpu));
- to_svcpu(vcpu)->slb_max = to_book3s(vcpu)->slb_shadow_max;
-#endif
-
-#ifdef CONFIG_PPC_BOOK3S_32
- current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
-#endif
-}
-
-void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_PPC_BOOK3S_64
- memcpy(to_book3s(vcpu)->slb_shadow, to_svcpu(vcpu)->slb, sizeof(to_svcpu(vcpu)->slb));
- memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu,
- sizeof(get_paca()->shadow_vcpu));
- to_book3s(vcpu)->slb_shadow_max = to_svcpu(vcpu)->slb_max;
-#endif
-
- kvmppc_giveup_ext(vcpu, MSR_FP);
- kvmppc_giveup_ext(vcpu, MSR_VEC);
- kvmppc_giveup_ext(vcpu, MSR_VSX);
-}
-
-static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
-{
- ulong smsr = vcpu->arch.shared->msr;
-
- /* Guest MSR values */
- smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
- /* Process MSR values */
- smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
- /* External providers the guest reserved */
- smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
- /* 64-bit Process MSR values */
-#ifdef CONFIG_PPC_BOOK3S_64
- smsr |= MSR_ISF | MSR_HV;
-#endif
- vcpu->arch.shadow_msr = smsr;
-}
-
-void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
-{
- ulong old_msr = vcpu->arch.shared->msr;
-
-#ifdef EXIT_DEBUG
- printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
-#endif
-
- msr &= to_book3s(vcpu)->msr_mask;
- vcpu->arch.shared->msr = msr;
- kvmppc_recalc_shadow_msr(vcpu);
-
- if (msr & MSR_POW) {
- if (!vcpu->arch.pending_exceptions) {
- kvm_vcpu_block(vcpu);
- vcpu->stat.halt_wakeup++;
-
- /* Unset POW bit after we woke up */
- msr &= ~MSR_POW;
- vcpu->arch.shared->msr = msr;
- }
- }
-
- if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
- (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
- kvmppc_mmu_flush_segments(vcpu);
- kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
-
- /* Preload magic page segment when in kernel mode */
- if (!(msr & MSR_PR) && vcpu->arch.magic_page_pa) {
- struct kvm_vcpu_arch *a = &vcpu->arch;
-
- if (msr & MSR_DR)
- kvmppc_mmu_map_segment(vcpu, a->magic_page_ea);
- else
- kvmppc_mmu_map_segment(vcpu, a->magic_page_pa);
- }
- }
-
- /* Preload FPU if it's enabled */
- if (vcpu->arch.shared->msr & MSR_FP)
- kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
-}
-
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{
vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu);
vcpu->arch.shared->srr1 = vcpu->arch.shared->msr | flags;
- kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec);
+ kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
vcpu->arch.mmu.reset_msr(vcpu);
}
@@ -204,11 +106,13 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
unsigned int vec)
{
+ unsigned long old_pending = vcpu->arch.pending_exceptions;
+
clear_bit(kvmppc_book3s_vec2irqprio(vec),
&vcpu->arch.pending_exceptions);
- if (!vcpu->arch.pending_exceptions)
- vcpu->arch.shared->int_pending = 0;
+ kvmppc_update_int_pending(vcpu, vcpu->arch.pending_exceptions,
+ old_pending);
}
void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
@@ -225,8 +129,8 @@ void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
{
- to_book3s(vcpu)->prog_flags = flags;
- kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_PROGRAM);
+ /* might as well deliver this straight away */
+ kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_PROGRAM, flags);
}
void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
@@ -266,21 +170,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
{
int deliver = 1;
int vec = 0;
- ulong flags = 0ULL;
- ulong crit_raw = vcpu->arch.shared->critical;
- ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
- bool crit;
-
- /* Truncate crit indicators in 32 bit mode */
- if (!(vcpu->arch.shared->msr & MSR_SF)) {
- crit_raw &= 0xffffffff;
- crit_r1 &= 0xffffffff;
- }
-
- /* Critical section when crit == r1 */
- crit = (crit_raw == crit_r1);
- /* ... and we're in supervisor mode */
- crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
+ bool crit = kvmppc_critical_section(vcpu);
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
@@ -315,7 +205,6 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
break;
case BOOK3S_IRQPRIO_PROGRAM:
vec = BOOK3S_INTERRUPT_PROGRAM;
- flags = to_book3s(vcpu)->prog_flags;
break;
case BOOK3S_IRQPRIO_VSX:
vec = BOOK3S_INTERRUPT_VSX;
@@ -346,7 +235,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
#endif
if (deliver)
- kvmppc_inject_interrupt(vcpu, vec, flags);
+ kvmppc_inject_interrupt(vcpu, vec, 0);
return deliver;
}
@@ -392,64 +281,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
}
/* Tell the guest about our interrupt status */
- if (*pending)
- vcpu->arch.shared->int_pending = 1;
- else if (old_pending)
- vcpu->arch.shared->int_pending = 0;
-}
-
-void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
-{
- u32 host_pvr;
-
- vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB;
- vcpu->arch.pvr = pvr;
-#ifdef CONFIG_PPC_BOOK3S_64
- if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
- kvmppc_mmu_book3s_64_init(vcpu);
- to_book3s(vcpu)->hior = 0xfff00000;
- to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
- } else
-#endif
- {
- kvmppc_mmu_book3s_32_init(vcpu);
- to_book3s(vcpu)->hior = 0;
- to_book3s(vcpu)->msr_mask = 0xffffffffULL;
- }
-
- /* 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;
- if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) &&
- !strcmp(cur_cpu_spec->platform, "ppc970"))
- vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
-
- /* Cell performs badly if MSR_FEx are set. So let's hope nobody
- really needs them in a VM on Cell and force disable them. */
- if (!strcmp(cur_cpu_spec->platform, "ppc-cell-be"))
- to_book3s(vcpu)->msr_mask &= ~(MSR_FE0 | MSR_FE1);
-
-#ifdef CONFIG_PPC_BOOK3S_32
- /* 32 bit Book3S always has 32 byte dcbz */
- vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
-#endif
-
- /* On some CPUs we can execute paired single operations natively */
- asm ( "mfpvr %0" : "=r"(host_pvr));
- switch (host_pvr) {
- case 0x00080200: /* lonestar 2.0 */
- case 0x00088202: /* lonestar 2.2 */
- case 0x70000100: /* gekko 1.0 */
- case 0x00080100: /* gekko 2.0 */
- case 0x00083203: /* gekko 2.3a */
- case 0x00083213: /* gekko 2.3b */
- case 0x00083204: /* gekko 2.4 */
- case 0x00083214: /* gekko 2.4e (8SE) - retail HW2 */
- case 0x00087200: /* broadway */
- vcpu->arch.hflags |= BOOK3S_HFLAG_NATIVE_PS;
- /* Enable HID2.PSE - in case we need it later */
- mtspr(SPRN_HID2_GEKKO, mfspr(SPRN_HID2_GEKKO) | (1 << 29));
- }
+ kvmppc_update_int_pending(vcpu, *pending, old_pending);
}
pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn)
@@ -471,44 +303,6 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn)
return gfn_to_pfn(vcpu->kvm, gfn);
}
-/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To
- * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to
- * emulate 32 bytes dcbz length.
- *
- * The Book3s_64 inventors also realized this case and implemented a special bit
- * in the HID5 register, which is a hypervisor ressource. Thus we can't use it.
- *
- * My approach here is to patch the dcbz instruction on executing pages.
- */
-static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
-{
- struct page *hpage;
- u64 hpage_offset;
- u32 *page;
- int i;
-
- hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
- if (is_error_page(hpage)) {
- kvm_release_page_clean(hpage);
- return;
- }
-
- hpage_offset = pte->raddr & ~PAGE_MASK;
- hpage_offset &= ~0xFFFULL;
- hpage_offset /= 4;
-
- get_page(hpage);
- page = kmap_atomic(hpage, KM_USER0);
-
- /* patch dcbz into reserved instruction, so we trap */
- for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
- if ((page[i] & 0xff0007ff) == INS_DCBZ)
- page[i] &= 0xfffffff7;
-
- kunmap_atomic(page, KM_USER0);
- put_page(hpage);
-}
-
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
struct kvmppc_pte *pte)
{
@@ -606,519 +400,6 @@ mmio:
return EMULATE_DO_MMIO;
}
-static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
-{
- ulong mp_pa = vcpu->arch.magic_page_pa;
-
- if (unlikely(mp_pa) &&
- unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) {
- return 1;
- }
-
- return kvm_is_visible_gfn(vcpu->kvm, gfn);
-}
-
-int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
- ulong eaddr, int vec)
-{
- bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE);
- int r = RESUME_GUEST;
- int relocated;
- int page_found = 0;
- struct kvmppc_pte pte;
- bool is_mmio = false;
- bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
- bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
- u64 vsid;
-
- relocated = data ? dr : ir;
-
- /* Resolve real address if translation turned on */
- if (relocated) {
- page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data);
- } else {
- pte.may_execute = true;
- pte.may_read = true;
- pte.may_write = true;
- pte.raddr = eaddr & KVM_PAM;
- pte.eaddr = eaddr;
- pte.vpage = eaddr >> 12;
- }
-
- switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
- case 0:
- pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
- break;
- case MSR_DR:
- case MSR_IR:
- vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
-
- if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
- pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
- else
- pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
- pte.vpage |= vsid;
-
- if (vsid == -1)
- page_found = -EINVAL;
- break;
- }
-
- if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
- (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
- /*
- * If we do the dcbz hack, we have to NX on every execution,
- * so we can patch the executing code. This renders our guest
- * NX-less.
- */
- pte.may_execute = !data;
- }
-
- if (page_found == -ENOENT) {
- /* Page not found in guest PTE entries */
- vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
- vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
- vcpu->arch.shared->msr |=
- (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
- kvmppc_book3s_queue_irqprio(vcpu, vec);
- } else if (page_found == -EPERM) {
- /* Storage protection */
- vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
- vcpu->arch.shared->dsisr =
- to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
- vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
- vcpu->arch.shared->msr |=
- (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
- kvmppc_book3s_queue_irqprio(vcpu, vec);
- } else if (page_found == -EINVAL) {
- /* Page not found in guest SLB */
- vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
- kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
- } else if (!is_mmio &&
- kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
- /* The guest's PTE is not mapped yet. Map on the host */
- kvmppc_mmu_map_page(vcpu, &pte);
- if (data)
- vcpu->stat.sp_storage++;
- else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
- (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32)))
- kvmppc_patch_dcbz(vcpu, &pte);
- } else {
- /* MMIO */
- vcpu->stat.mmio_exits++;
- vcpu->arch.paddr_accessed = pte.raddr;
- r = kvmppc_emulate_mmio(run, vcpu);
- if ( r == RESUME_HOST_NV )
- r = RESUME_HOST;
- }
-
- return r;
-}
-
-static inline int get_fpr_index(int i)
-{
-#ifdef CONFIG_VSX
- i *= 2;
-#endif
- return i;
-}
-
-/* Give up external provider (FPU, Altivec, VSX) */
-void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
-{
- struct thread_struct *t = &current->thread;
- u64 *vcpu_fpr = vcpu->arch.fpr;
-#ifdef CONFIG_VSX
- u64 *vcpu_vsx = vcpu->arch.vsr;
-#endif
- u64 *thread_fpr = (u64*)t->fpr;
- int i;
-
- if (!(vcpu->arch.guest_owned_ext & msr))
- return;
-
-#ifdef DEBUG_EXT
- printk(KERN_INFO "Giving up ext 0x%lx\n", msr);
-#endif
-
- switch (msr) {
- case MSR_FP:
- giveup_fpu(current);
- for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
- vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
-
- vcpu->arch.fpscr = t->fpscr.val;
- break;
- case MSR_VEC:
-#ifdef CONFIG_ALTIVEC
- giveup_altivec(current);
- memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
- vcpu->arch.vscr = t->vscr;
-#endif
- break;
- case MSR_VSX:
-#ifdef CONFIG_VSX
- __giveup_vsx(current);
- for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
- vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
-#endif
- break;
- default:
- BUG();
- }
-
- vcpu->arch.guest_owned_ext &= ~msr;
- current->thread.regs->msr &= ~msr;
- kvmppc_recalc_shadow_msr(vcpu);
-}
-
-static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
-{
- ulong srr0 = kvmppc_get_pc(vcpu);
- u32 last_inst = kvmppc_get_last_inst(vcpu);
- int ret;
-
- ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
- if (ret == -ENOENT) {
- ulong msr = vcpu->arch.shared->msr;
-
- msr = kvmppc_set_field(msr, 33, 33, 1);
- msr = kvmppc_set_field(msr, 34, 36, 0);
- vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
- kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
- return EMULATE_AGAIN;
- }
-
- return EMULATE_DONE;
-}
-
-static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
-{
-
- /* Need to do paired single emulation? */
- if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
- return EMULATE_DONE;
-
- /* Read out the instruction */
- if (kvmppc_read_inst(vcpu) == EMULATE_DONE)
- /* Need to emulate */
- return EMULATE_FAIL;
-
- return EMULATE_AGAIN;
-}
-
-/* Handle external providers (FPU, Altivec, VSX) */
-static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
- ulong msr)
-{
- struct thread_struct *t = &current->thread;
- u64 *vcpu_fpr = vcpu->arch.fpr;
-#ifdef CONFIG_VSX
- u64 *vcpu_vsx = vcpu->arch.vsr;
-#endif
- u64 *thread_fpr = (u64*)t->fpr;
- int i;
-
- /* When we have paired singles, we emulate in software */
- if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
- return RESUME_GUEST;
-
- if (!(vcpu->arch.shared->msr & msr)) {
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- return RESUME_GUEST;
- }
-
- /* We already own the ext */
- if (vcpu->arch.guest_owned_ext & msr) {
- return RESUME_GUEST;
- }
-
-#ifdef DEBUG_EXT
- printk(KERN_INFO "Loading up ext 0x%lx\n", msr);
-#endif
-
- current->thread.regs->msr |= msr;
-
- switch (msr) {
- case MSR_FP:
- for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
- thread_fpr[get_fpr_index(i)] = vcpu_fpr[i];
-
- t->fpscr.val = vcpu->arch.fpscr;
- t->fpexc_mode = 0;
- kvmppc_load_up_fpu();
- break;
- case MSR_VEC:
-#ifdef CONFIG_ALTIVEC
- memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
- t->vscr = vcpu->arch.vscr;
- t->vrsave = -1;
- kvmppc_load_up_altivec();
-#endif
- break;
- case MSR_VSX:
-#ifdef CONFIG_VSX
- for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
- thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
- kvmppc_load_up_vsx();
-#endif
- break;
- default:
- BUG();
- }
-
- vcpu->arch.guest_owned_ext |= msr;
-
- kvmppc_recalc_shadow_msr(vcpu);
-
- return RESUME_GUEST;
-}
-
-int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
- unsigned int exit_nr)
-{
- int r = RESUME_HOST;
-
- vcpu->stat.sum_exits++;
-
- run->exit_reason = KVM_EXIT_UNKNOWN;
- run->ready_for_interrupt_injection = 1;
-
- trace_kvm_book3s_exit(exit_nr, vcpu);
- kvm_resched(vcpu);
- switch (exit_nr) {
- case BOOK3S_INTERRUPT_INST_STORAGE:
- vcpu->stat.pf_instruc++;
-
-#ifdef CONFIG_PPC_BOOK3S_32
- /* We set segments as unused segments when invalidating them. So
- * treat the respective fault as segment fault. */
- if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]
- == SR_INVALID) {
- kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
- r = RESUME_GUEST;
- break;
- }
-#endif
-
- /* only care about PTEG not found errors, but leave NX alone */
- if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) {
- r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr);
- vcpu->stat.sp_instruc++;
- } else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
- (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
- /*
- * XXX If we do the dcbz hack we use the NX bit to flush&patch the page,
- * so we can't use the NX bit inside the guest. Let's cross our fingers,
- * that no guest that needs the dcbz hack does NX.
- */
- kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
- r = RESUME_GUEST;
- } else {
- vcpu->arch.shared->msr |=
- to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- r = RESUME_GUEST;
- }
- break;
- case BOOK3S_INTERRUPT_DATA_STORAGE:
- {
- ulong dar = kvmppc_get_fault_dar(vcpu);
- vcpu->stat.pf_storage++;
-
-#ifdef CONFIG_PPC_BOOK3S_32
- /* We set segments as unused segments when invalidating them. So
- * treat the respective fault as segment fault. */
- if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) == SR_INVALID) {
- kvmppc_mmu_map_segment(vcpu, dar);
- r = RESUME_GUEST;
- break;
- }
-#endif
-
- /* The only case we need to handle is missing shadow PTEs */
- if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
- r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
- } else {
- vcpu->arch.shared->dar = dar;
- vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- r = RESUME_GUEST;
- }
- break;
- }
- case BOOK3S_INTERRUPT_DATA_SEGMENT:
- if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
- vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
- kvmppc_book3s_queue_irqprio(vcpu,
- BOOK3S_INTERRUPT_DATA_SEGMENT);
- }
- r = RESUME_GUEST;
- break;
- case BOOK3S_INTERRUPT_INST_SEGMENT:
- if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)) < 0) {
- kvmppc_book3s_queue_irqprio(vcpu,
- BOOK3S_INTERRUPT_INST_SEGMENT);
- }
- r = RESUME_GUEST;
- break;
- /* We're good on these - the host merely wanted to get our attention */
- case BOOK3S_INTERRUPT_DECREMENTER:
- vcpu->stat.dec_exits++;
- r = RESUME_GUEST;
- break;
- case BOOK3S_INTERRUPT_EXTERNAL:
- vcpu->stat.ext_intr_exits++;
- r = RESUME_GUEST;
- break;
- case BOOK3S_INTERRUPT_PERFMON:
- r = RESUME_GUEST;
- break;
- case BOOK3S_INTERRUPT_PROGRAM:
- {
- enum emulation_result er;
- ulong flags;
-
-program_interrupt:
- flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
-
- if (vcpu->arch.shared->msr & MSR_PR) {
-#ifdef EXIT_DEBUG
- printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
-#endif
- if ((kvmppc_get_last_inst(vcpu) & 0xff0007ff) !=
- (INS_DCBZ & 0xfffffff7)) {
- kvmppc_core_queue_program(vcpu, flags);
- r = RESUME_GUEST;
- break;
- }
- }
-
- vcpu->stat.emulated_inst_exits++;
- er = kvmppc_emulate_instruction(run, vcpu);
- switch (er) {
- case EMULATE_DONE:
- r = RESUME_GUEST_NV;
- break;
- case EMULATE_AGAIN:
- r = RESUME_GUEST;
- break;
- case EMULATE_FAIL:
- printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
- __func__, kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
- kvmppc_core_queue_program(vcpu, flags);
- r = RESUME_GUEST;
- break;
- case EMULATE_DO_MMIO:
- run->exit_reason = KVM_EXIT_MMIO;
- r = RESUME_HOST_NV;
- break;
- default:
- BUG();
- }
- break;
- }
- case BOOK3S_INTERRUPT_SYSCALL:
- 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 */
- u64 *gprs = run->osi.gprs;
- int i;
-
- run->exit_reason = KVM_EXIT_OSI;
- for (i = 0; i < 32; i++)
- gprs[i] = kvmppc_get_gpr(vcpu, i);
- vcpu->arch.osi_needed = 1;
- r = RESUME_HOST_NV;
- } else if (!(vcpu->arch.shared->msr & MSR_PR) &&
- (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) {
- /* KVM PV hypercalls */
- kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
- r = RESUME_GUEST;
- } else {
- /* Guest syscalls */
- vcpu->stat.syscall_exits++;
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- r = RESUME_GUEST;
- }
- break;
- case BOOK3S_INTERRUPT_FP_UNAVAIL:
- case BOOK3S_INTERRUPT_ALTIVEC:
- case BOOK3S_INTERRUPT_VSX:
- {
- int ext_msr = 0;
-
- switch (exit_nr) {
- case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP; break;
- case BOOK3S_INTERRUPT_ALTIVEC: ext_msr = MSR_VEC; break;
- case BOOK3S_INTERRUPT_VSX: ext_msr = MSR_VSX; break;
- }
-
- switch (kvmppc_check_ext(vcpu, exit_nr)) {
- case EMULATE_DONE:
- /* everything ok - let's enable the ext */
- r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
- break;
- case EMULATE_FAIL:
- /* we need to emulate this instruction */
- goto program_interrupt;
- break;
- default:
- /* nothing to worry about - go again */
- break;
- }
- break;
- }
- case BOOK3S_INTERRUPT_ALIGNMENT:
- if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
- vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
- kvmppc_get_last_inst(vcpu));
- vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
- kvmppc_get_last_inst(vcpu));
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- }
- r = RESUME_GUEST;
- break;
- case BOOK3S_INTERRUPT_MACHINE_CHECK:
- case BOOK3S_INTERRUPT_TRACE:
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- r = RESUME_GUEST;
- break;
- default:
- /* Ugh - bork here! What did we get? */
- printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n",
- exit_nr, kvmppc_get_pc(vcpu), to_svcpu(vcpu)->shadow_srr1);
- r = RESUME_HOST;
- BUG();
- 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(current)) {
-#ifdef EXIT_DEBUG
- printk(KERN_EMERG "KVM: Going back to host\n");
-#endif
- vcpu->stat.signal_exits++;
- run->exit_reason = KVM_EXIT_INTR;
- r = -EINTR;
- } else {
- /* In case an interrupt came in that was triggered
- * from userspace (like DEC), we need to check what
- * to inject now! */
- kvmppc_core_deliver_interrupts(vcpu);
- }
- }
-
- trace_kvm_book3s_reenter(r, vcpu);
-
- return r;
-}
-
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
return 0;
@@ -1179,69 +460,6 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
return 0;
}
-int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
- struct kvm_sregs *sregs)
-{
- struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
- int i;
-
- sregs->pvr = vcpu->arch.pvr;
-
- sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1;
- if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
- for (i = 0; i < 64; i++) {
- sregs->u.s.ppc64.slb[i].slbe = vcpu3s->slb[i].orige | i;
- sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv;
- }
- } else {
- for (i = 0; i < 16; i++)
- sregs->u.s.ppc32.sr[i] = vcpu->arch.shared->sr[i];
-
- for (i = 0; i < 8; i++) {
- sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw;
- sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw;
- }
- }
-
- return 0;
-}
-
-int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
- struct kvm_sregs *sregs)
-{
- struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
- int i;
-
- kvmppc_set_pvr(vcpu, sregs->pvr);
-
- vcpu3s->sdr1 = sregs->u.s.sdr1;
- if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
- for (i = 0; i < 64; i++) {
- vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv,
- sregs->u.s.ppc64.slb[i].slbe);
- }
- } else {
- for (i = 0; i < 16; i++) {
- vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]);
- }
- for (i = 0; i < 8; i++) {
- kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false,
- (u32)sregs->u.s.ppc32.ibat[i]);
- kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true,
- (u32)(sregs->u.s.ppc32.ibat[i] >> 32));
- kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false,
- (u32)sregs->u.s.ppc32.dbat[i]);
- kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true,
- (u32)(sregs->u.s.ppc32.dbat[i] >> 32));
- }
- }
-
- /* Flush the MMU after messing with the segments */
- kvmppc_mmu_pte_flush(vcpu, 0, 0);
-
- return 0;
-}
-
int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{
return -ENOTSUPP;
@@ -1296,202 +514,3 @@ out:
mutex_unlock(&kvm->slots_lock);
return r;
}
-
-int kvmppc_core_check_processor_compat(void)
-{
- return 0;
-}
-
-struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
-{
- struct kvmppc_vcpu_book3s *vcpu_book3s;
- struct kvm_vcpu *vcpu;
- int err = -ENOMEM;
- unsigned long p;
-
- vcpu_book3s = vzalloc(sizeof(struct kvmppc_vcpu_book3s));
- if (!vcpu_book3s)
- goto out;
-
- vcpu_book3s->shadow_vcpu = (struct kvmppc_book3s_shadow_vcpu *)
- kzalloc(sizeof(*vcpu_book3s->shadow_vcpu), GFP_KERNEL);
- if (!vcpu_book3s->shadow_vcpu)
- goto free_vcpu;
-
- vcpu = &vcpu_book3s->vcpu;
- err = kvm_vcpu_init(vcpu, kvm, id);
- if (err)
- goto free_shadow_vcpu;
-
- p = __get_free_page(GFP_KERNEL|__GFP_ZERO);
- /* the real shared page fills the last 4k of our page */
- vcpu->arch.shared = (void*)(p + PAGE_SIZE - 4096);
- 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;
-#else
- /* default to book3s_32 (750) */
- vcpu->arch.pvr = 0x84202;
-#endif
- kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
- vcpu_book3s->slb_nr = 64;
-
- /* remember where some real-mode handlers are */
- vcpu->arch.trampoline_lowmem = kvmppc_trampoline_lowmem;
- vcpu->arch.trampoline_enter = kvmppc_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);
- if (err < 0)
- goto uninit_vcpu;
-
- return vcpu;
-
-uninit_vcpu:
- kvm_vcpu_uninit(vcpu);
-free_shadow_vcpu:
- kfree(vcpu_book3s->shadow_vcpu);
-free_vcpu:
- vfree(vcpu_book3s);
-out:
- return ERR_PTR(err);
-}
-
-void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
-{
- struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
-
- free_page((unsigned long)vcpu->arch.shared & PAGE_MASK);
- kvm_vcpu_uninit(vcpu);
- kfree(vcpu_book3s->shadow_vcpu);
- vfree(vcpu_book3s);
-}
-
-extern int __kvmppc_vcpu_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
-int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
-{
- int ret;
- double fpr[32][TS_FPRWIDTH];
- unsigned int fpscr;
- int fpexc_mode;
-#ifdef CONFIG_ALTIVEC
- vector128 vr[32];
- vector128 vscr;
- unsigned long uninitialized_var(vrsave);
- int used_vr;
-#endif
-#ifdef CONFIG_VSX
- int used_vsr;
-#endif
- ulong ext_msr;
-
- /* 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;
- }
-
- /* Save FPU state in stack */
- if (current->thread.regs->msr & MSR_FP)
- giveup_fpu(current);
- memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
- fpscr = current->thread.fpscr.val;
- fpexc_mode = current->thread.fpexc_mode;
-
-#ifdef CONFIG_ALTIVEC
- /* Save Altivec state in stack */
- used_vr = current->thread.used_vr;
- if (used_vr) {
- if (current->thread.regs->msr & MSR_VEC)
- giveup_altivec(current);
- memcpy(vr, current->thread.vr, sizeof(current->thread.vr));
- vscr = current->thread.vscr;
- vrsave = current->thread.vrsave;
- }
-#endif
-
-#ifdef CONFIG_VSX
- /* Save VSX state in stack */
- used_vsr = current->thread.used_vsr;
- if (used_vsr && (current->thread.regs->msr & MSR_VSX))
- __giveup_vsx(current);
-#endif
-
- /* Remember the MSR with disabled extensions */
- ext_msr = current->thread.regs->msr;
-
- /* XXX we get called with irq disabled - change that! */
- local_irq_enable();
-
- /* Preload FPU if it's enabled */
- if (vcpu->arch.shared->msr & MSR_FP)
- kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
-
- ret = __kvmppc_vcpu_entry(kvm_run, vcpu);
-
- local_irq_disable();
-
- current->thread.regs->msr = ext_msr;
-
- /* Make sure we save the guest FPU/Altivec/VSX state */
- kvmppc_giveup_ext(vcpu, MSR_FP);
- kvmppc_giveup_ext(vcpu, MSR_VEC);
- kvmppc_giveup_ext(vcpu, MSR_VSX);
-
- /* Restore FPU state from stack */
- memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
- current->thread.fpscr.val = fpscr;
- current->thread.fpexc_mode = fpexc_mode;
-
-#ifdef CONFIG_ALTIVEC
- /* Restore Altivec state from stack */
- if (used_vr && current->thread.used_vr) {
- memcpy(current->thread.vr, vr, sizeof(current->thread.vr));
- current->thread.vscr = vscr;
- current->thread.vrsave = vrsave;
- }
- current->thread.used_vr = used_vr;
-#endif
-
-#ifdef CONFIG_VSX
- current->thread.used_vsr = used_vsr;
-#endif
-
- return ret;
-}
-
-static int kvmppc_book3s_init(void)
-{
- int r;
-
- r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), 0,
- THIS_MODULE);
-
- if (r)
- return r;
-
- r = kvmppc_mmu_hpte_sysinit();
-
- return r;
-}
-
-static void kvmppc_book3s_exit(void)
-{
- kvmppc_mmu_hpte_sysexit();
- kvm_exit();
-}
-
-module_init(kvmppc_book3s_init);
-module_exit(kvmppc_book3s_exit);
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index d7889ef3211e..c6d3e194b6b4 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -41,36 +41,36 @@ static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
}
static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
- struct kvmppc_vcpu_book3s *vcpu_book3s,
+ struct kvm_vcpu *vcpu,
gva_t eaddr)
{
int i;
u64 esid = GET_ESID(eaddr);
u64 esid_1t = GET_ESID_1T(eaddr);
- for (i = 0; i < vcpu_book3s->slb_nr; i++) {
+ for (i = 0; i < vcpu->arch.slb_nr; i++) {
u64 cmp_esid = esid;
- if (!vcpu_book3s->slb[i].valid)
+ if (!vcpu->arch.slb[i].valid)
continue;
- if (vcpu_book3s->slb[i].tb)
+ if (vcpu->arch.slb[i].tb)
cmp_esid = esid_1t;
- if (vcpu_book3s->slb[i].esid == cmp_esid)
- return &vcpu_book3s->slb[i];
+ if (vcpu->arch.slb[i].esid == cmp_esid)
+ return &vcpu->arch.slb[i];
}
dprintk("KVM: No SLB entry found for 0x%lx [%llx | %llx]\n",
eaddr, esid, esid_1t);
- for (i = 0; i < vcpu_book3s->slb_nr; i++) {
- if (vcpu_book3s->slb[i].vsid)
+ for (i = 0; i < vcpu->arch.slb_nr; i++) {
+ if (vcpu->arch.slb[i].vsid)
dprintk(" %d: %c%c%c %llx %llx\n", i,
- vcpu_book3s->slb[i].valid ? 'v' : ' ',
- vcpu_book3s->slb[i].large ? 'l' : ' ',
- vcpu_book3s->slb[i].tb ? 't' : ' ',
- vcpu_book3s->slb[i].esid,
- vcpu_book3s->slb[i].vsid);
+ vcpu->arch.slb[i].valid ? 'v' : ' ',
+ vcpu->arch.slb[i].large ? 'l' : ' ',
+ vcpu->arch.slb[i].tb ? 't' : ' ',
+ vcpu->arch.slb[i].esid,
+ vcpu->arch.slb[i].vsid);
}
return NULL;
@@ -81,7 +81,7 @@ static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
{
struct kvmppc_slb *slb;
- slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), eaddr);
+ slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, eaddr);
if (!slb)
return 0;
@@ -180,7 +180,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
return 0;
}
- slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr);
+ slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu, eaddr);
if (!slbe)
goto no_seg_found;
@@ -320,10 +320,10 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb)
esid_1t = GET_ESID_1T(rb);
slb_nr = rb & 0xfff;
- if (slb_nr > vcpu_book3s->slb_nr)
+ if (slb_nr > vcpu->arch.slb_nr)
return;
- slbe = &vcpu_book3s->slb[slb_nr];
+ slbe = &vcpu->arch.slb[slb_nr];
slbe->large = (rs & SLB_VSID_L) ? 1 : 0;
slbe->tb = (rs & SLB_VSID_B_1T) ? 1 : 0;
@@ -344,38 +344,35 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb)
static u64 kvmppc_mmu_book3s_64_slbmfee(struct kvm_vcpu *vcpu, u64 slb_nr)
{
- struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
struct kvmppc_slb *slbe;
- if (slb_nr > vcpu_book3s->slb_nr)
+ if (slb_nr > vcpu->arch.slb_nr)
return 0;
- slbe = &vcpu_book3s->slb[slb_nr];
+ slbe = &vcpu->arch.slb[slb_nr];
return slbe->orige;
}
static u64 kvmppc_mmu_book3s_64_slbmfev(struct kvm_vcpu *vcpu, u64 slb_nr)
{
- struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
struct kvmppc_slb *slbe;
- if (slb_nr > vcpu_book3s->slb_nr)
+ if (slb_nr > vcpu->arch.slb_nr)
return 0;
- slbe = &vcpu_book3s->slb[slb_nr];
+ slbe = &vcpu->arch.slb[slb_nr];
return slbe->origv;
}
static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea)
{
- struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
struct kvmppc_slb *slbe;
dprintk("KVM MMU: slbie(0x%llx)\n", ea);
- slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, ea);
+ slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea);
if (!slbe)
return;
@@ -389,13 +386,12 @@ static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea)
static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)
{
- struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
int i;
dprintk("KVM MMU: slbia()\n");
- for (i = 1; i < vcpu_book3s->slb_nr; i++)
- vcpu_book3s->slb[i].valid = false;
+ for (i = 1; i < vcpu->arch.slb_nr; i++)
+ vcpu->arch.slb[i].valid = false;
if (vcpu->arch.shared->msr & MSR_IR) {
kvmppc_mmu_flush_segments(vcpu);
@@ -464,7 +460,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
ulong mp_ea = vcpu->arch.magic_page_ea;
if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
- slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
+ slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea);
if (slb)
gvsid = slb->vsid;
}
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
new file mode 100644
index 000000000000..bc3a2ea94217
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -0,0 +1,180 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
+
+#include <asm/tlbflush.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu-hash64.h>
+#include <asm/hvcall.h>
+#include <asm/synch.h>
+#include <asm/ppc-opcode.h>
+#include <asm/cputable.h>
+
+/* For now use fixed-size 16MB page table */
+#define HPT_ORDER 24
+#define HPT_NPTEG (1ul << (HPT_ORDER - 7)) /* 128B per pteg */
+#define HPT_HASH_MASK (HPT_NPTEG - 1)
+
+/* Pages in the VRMA are 16MB pages */
+#define VRMA_PAGE_ORDER 24
+#define VRMA_VSID 0x1ffffffUL /* 1TB VSID reserved for VRMA */
+
+/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
+#define MAX_LPID_970 63
+#define NR_LPIDS (LPID_RSVD + 1)
+unsigned long lpid_inuse[BITS_TO_LONGS(NR_LPIDS)];
+
+long kvmppc_alloc_hpt(struct kvm *kvm)
+{
+ unsigned long hpt;
+ unsigned long lpid;
+
+ hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
+ HPT_ORDER - PAGE_SHIFT);
+ if (!hpt) {
+ pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n");
+ return -ENOMEM;
+ }
+ kvm->arch.hpt_virt = hpt;
+
+ do {
+ lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS);
+ if (lpid >= NR_LPIDS) {
+ pr_err("kvm_alloc_hpt: No LPIDs free\n");
+ free_pages(hpt, HPT_ORDER - PAGE_SHIFT);
+ return -ENOMEM;
+ }
+ } while (test_and_set_bit(lpid, lpid_inuse));
+
+ kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18);
+ kvm->arch.lpid = lpid;
+
+ pr_info("KVM guest htab at %lx, LPID %lx\n", hpt, lpid);
+ return 0;
+}
+
+void kvmppc_free_hpt(struct kvm *kvm)
+{
+ clear_bit(kvm->arch.lpid, lpid_inuse);
+ free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+}
+
+void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
+{
+ unsigned long i;
+ unsigned long npages = kvm->arch.ram_npages;
+ unsigned long pfn;
+ unsigned long *hpte;
+ unsigned long hash;
+ struct kvmppc_pginfo *pginfo = kvm->arch.ram_pginfo;
+
+ if (!pginfo)
+ return;
+
+ /* VRMA can't be > 1TB */
+ if (npages > 1ul << (40 - kvm->arch.ram_porder))
+ npages = 1ul << (40 - kvm->arch.ram_porder);
+ /* Can't use more than 1 HPTE per HPTEG */
+ if (npages > HPT_NPTEG)
+ npages = HPT_NPTEG;
+
+ for (i = 0; i < npages; ++i) {
+ pfn = pginfo[i].pfn;
+ if (!pfn)
+ break;
+ /* can't use hpt_hash since va > 64 bits */
+ hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK;
+ /*
+ * We assume that the hash table is empty and no
+ * vcpus are using it at this stage. Since we create
+ * at most one HPTE per HPTEG, we just assume entry 7
+ * is available and use it.
+ */
+ hpte = (unsigned long *) (kvm->arch.hpt_virt + (hash << 7));
+ hpte += 7 * 2;
+ /* HPTE low word - RPN, protection, etc. */
+ hpte[1] = (pfn << PAGE_SHIFT) | HPTE_R_R | HPTE_R_C |
+ HPTE_R_M | PP_RWXX;
+ wmb();
+ hpte[0] = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
+ (i << (VRMA_PAGE_ORDER - 16)) | HPTE_V_BOLTED |
+ HPTE_V_LARGE | HPTE_V_VALID;
+ }
+}
+
+int kvmppc_mmu_hv_init(void)
+{
+ unsigned long host_lpid, rsvd_lpid;
+
+ if (!cpu_has_feature(CPU_FTR_HVMODE))
+ return -EINVAL;
+
+ memset(lpid_inuse, 0, sizeof(lpid_inuse));
+
+ if (cpu_has_feature(CPU_FTR_ARCH_206)) {
+ host_lpid = mfspr(SPRN_LPID); /* POWER7 */
+ rsvd_lpid = LPID_RSVD;
+ } else {
+ host_lpid = 0; /* PPC970 */
+ rsvd_lpid = MAX_LPID_970;
+ }
+
+ set_bit(host_lpid, lpid_inuse);
+ /* rsvd_lpid is reserved for use in partition switching */
+ set_bit(rsvd_lpid, lpid_inuse);
+
+ return 0;
+}
+
+void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
+{
+}
+
+static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
+{
+ kvmppc_set_msr(vcpu, MSR_SF | MSR_ME);
+}
+
+static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
+ struct kvmppc_pte *gpte, bool data)
+{
+ return -ENOENT;
+}
+
+void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
+
+ if (cpu_has_feature(CPU_FTR_ARCH_206))
+ vcpu->arch.slb_nr = 32; /* POWER7 */
+ else
+ vcpu->arch.slb_nr = 64;
+
+ mmu->xlate = kvmppc_mmu_book3s_64_hv_xlate;
+ mmu->reset_msr = kvmppc_mmu_book3s_64_hv_reset_msr;
+
+ vcpu->arch.hflags |= BOOK3S_HFLAG_SLB;
+}
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
new file mode 100644
index 000000000000..ea0f8c537c28
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -0,0 +1,73 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
+#include <linux/list.h>
+
+#include <asm/tlbflush.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu-hash64.h>
+#include <asm/hvcall.h>
+#include <asm/synch.h>
+#include <asm/ppc-opcode.h>
+#include <asm/kvm_host.h>
+#include <asm/udbg.h>
+
+#define TCES_PER_PAGE (PAGE_SIZE / sizeof(u64))
+
+long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+ unsigned long ioba, unsigned long tce)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct kvmppc_spapr_tce_table *stt;
+
+ /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
+ /* liobn, ioba, tce); */
+
+ list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
+ if (stt->liobn == liobn) {
+ unsigned long idx = ioba >> SPAPR_TCE_SHIFT;
+ struct page *page;
+ u64 *tbl;
+
+ /* udbg_printf("H_PUT_TCE: liobn 0x%lx => stt=%p window_size=0x%x\n", */
+ /* liobn, stt, stt->window_size); */
+ if (ioba >= stt->window_size)
+ return H_PARAMETER;
+
+ page = stt->pages[idx / TCES_PER_PAGE];
+ tbl = (u64 *)page_address(page);
+
+ /* FIXME: Need to validate the TCE itself */
+ /* udbg_printf("tce @ %p\n", &tbl[idx % TCES_PER_PAGE]); */
+ tbl[idx % TCES_PER_PAGE] = tce;
+ return H_SUCCESS;
+ }
+ }
+
+ /* Didn't find the liobn, punt it to userspace */
+ return H_TOO_HARD;
+}
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c
index 1dd5a1ddfd0d..88c8f26add02 100644
--- a/arch/powerpc/kvm/book3s_exports.c
+++ b/arch/powerpc/kvm/book3s_exports.c
@@ -20,8 +20,11 @@
#include <linux/module.h>
#include <asm/kvm_book3s.h>
-EXPORT_SYMBOL_GPL(kvmppc_trampoline_enter);
-EXPORT_SYMBOL_GPL(kvmppc_trampoline_lowmem);
+#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_load_up_fpu);
#ifdef CONFIG_ALTIVEC
@@ -30,3 +33,5 @@ EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
#ifdef CONFIG_VSX
EXPORT_SYMBOL_GPL(kvmppc_load_up_vsx);
#endif
+#endif
+
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
new file mode 100644
index 000000000000..cc0d7f1b19ab
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -0,0 +1,1269 @@
+/*
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ * Paul Mackerras <paulus@au1.ibm.com>
+ * Alexander Graf <agraf@suse.de>
+ * Kevin Wolf <mail@kevin-wolf.de>
+ *
+ * Description: KVM functions specific to running on Book 3S
+ * processors in hypervisor mode (specifically POWER7 and later).
+ *
+ * This file is derived from arch/powerpc/kvm/book3s.c,
+ * by Alexander Graf <agraf@suse.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/kvm_host.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/anon_inodes.h>
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <linux/page-flags.h>
+
+#include <asm/reg.h>
+#include <asm/cputable.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu_context.h>
+#include <asm/lppaca.h>
+#include <asm/processor.h>
+#include <asm/cputhreads.h>
+#include <asm/page.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+
+/*
+ * For now, limit memory to 64GB and require it to be large pages.
+ * This value is chosen because it makes the ram_pginfo array be
+ * 64kB in size, which is about as large as we want to be trying
+ * to allocate with kmalloc.
+ */
+#define MAX_MEM_ORDER 36
+
+#define LARGE_PAGE_ORDER 24 /* 16MB pages */
+
+/* #define EXIT_DEBUG */
+/* #define EXIT_DEBUG_SIMPLE */
+/* #define EXIT_DEBUG_INT */
+
+void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+ local_paca->kvm_hstate.kvm_vcpu = vcpu;
+ local_paca->kvm_hstate.kvm_vcore = vcpu->arch.vcore;
+}
+
+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;
+}
+
+void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
+{
+ vcpu->arch.pvr = pvr;
+}
+
+void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
+{
+ int r;
+
+ pr_err("vcpu %p (%d):\n", vcpu, vcpu->vcpu_id);
+ pr_err("pc = %.16lx msr = %.16llx trap = %x\n",
+ vcpu->arch.pc, vcpu->arch.shregs.msr, vcpu->arch.trap);
+ for (r = 0; r < 16; ++r)
+ pr_err("r%2d = %.16lx r%d = %.16lx\n",
+ r, kvmppc_get_gpr(vcpu, r),
+ r+16, kvmppc_get_gpr(vcpu, r+16));
+ pr_err("ctr = %.16lx lr = %.16lx\n",
+ vcpu->arch.ctr, vcpu->arch.lr);
+ pr_err("srr0 = %.16llx srr1 = %.16llx\n",
+ vcpu->arch.shregs.srr0, vcpu->arch.shregs.srr1);
+ pr_err("sprg0 = %.16llx sprg1 = %.16llx\n",
+ vcpu->arch.shregs.sprg0, vcpu->arch.shregs.sprg1);
+ pr_err("sprg2 = %.16llx sprg3 = %.16llx\n",
+ vcpu->arch.shregs.sprg2, vcpu->arch.shregs.sprg3);
+ pr_err("cr = %.8x xer = %.16lx dsisr = %.8x\n",
+ vcpu->arch.cr, vcpu->arch.xer, vcpu->arch.shregs.dsisr);
+ pr_err("dar = %.16llx\n", vcpu->arch.shregs.dar);
+ pr_err("fault dar = %.16lx dsisr = %.8x\n",
+ vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+ pr_err("SLB (%d entries):\n", vcpu->arch.slb_max);
+ for (r = 0; r < vcpu->arch.slb_max; ++r)
+ pr_err(" ESID = %.16llx VSID = %.16llx\n",
+ vcpu->arch.slb[r].orige, vcpu->arch.slb[r].origv);
+ pr_err("lpcr = %.16lx sdr1 = %.16lx last_inst = %.8x\n",
+ vcpu->kvm->arch.lpcr, vcpu->kvm->arch.sdr1,
+ vcpu->arch.last_inst);
+}
+
+struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id)
+{
+ int r;
+ struct kvm_vcpu *v, *ret = NULL;
+
+ mutex_lock(&kvm->lock);
+ kvm_for_each_vcpu(r, v, kvm) {
+ if (v->vcpu_id == id) {
+ ret = v;
+ break;
+ }
+ }
+ mutex_unlock(&kvm->lock);
+ return ret;
+}
+
+static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
+{
+ vpa->shared_proc = 1;
+ vpa->yield_count = 1;
+}
+
+static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
+ unsigned long flags,
+ unsigned long vcpuid, unsigned long vpa)
+{
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long pg_index, ra, len;
+ unsigned long pg_offset;
+ void *va;
+ struct kvm_vcpu *tvcpu;
+
+ tvcpu = kvmppc_find_vcpu(kvm, vcpuid);
+ if (!tvcpu)
+ return H_PARAMETER;
+
+ flags >>= 63 - 18;
+ flags &= 7;
+ if (flags == 0 || flags == 4)
+ return H_PARAMETER;
+ if (flags < 4) {
+ if (vpa & 0x7f)
+ return H_PARAMETER;
+ /* registering new area; convert logical addr to real */
+ pg_index = vpa >> kvm->arch.ram_porder;
+ pg_offset = vpa & (kvm->arch.ram_psize - 1);
+ if (pg_index >= kvm->arch.ram_npages)
+ return H_PARAMETER;
+ if (kvm->arch.ram_pginfo[pg_index].pfn == 0)
+ return H_PARAMETER;
+ ra = kvm->arch.ram_pginfo[pg_index].pfn << PAGE_SHIFT;
+ ra |= pg_offset;
+ va = __va(ra);
+ if (flags <= 1)
+ len = *(unsigned short *)(va + 4);
+ else
+ len = *(unsigned int *)(va + 4);
+ if (pg_offset + len > kvm->arch.ram_psize)
+ return H_PARAMETER;
+ switch (flags) {
+ case 1: /* register VPA */
+ if (len < 640)
+ return H_PARAMETER;
+ tvcpu->arch.vpa = va;
+ init_vpa(vcpu, va);
+ break;
+ case 2: /* register DTL */
+ if (len < 48)
+ return H_PARAMETER;
+ if (!tvcpu->arch.vpa)
+ return H_RESOURCE;
+ len -= len % 48;
+ tvcpu->arch.dtl = va;
+ tvcpu->arch.dtl_end = va + len;
+ break;
+ case 3: /* register SLB shadow buffer */
+ if (len < 8)
+ return H_PARAMETER;
+ if (!tvcpu->arch.vpa)
+ return H_RESOURCE;
+ tvcpu->arch.slb_shadow = va;
+ len = (len - 16) / 16;
+ tvcpu->arch.slb_shadow = va;
+ break;
+ }
+ } else {
+ switch (flags) {
+ case 5: /* unregister VPA */
+ if (tvcpu->arch.slb_shadow || tvcpu->arch.dtl)
+ return H_RESOURCE;
+ tvcpu->arch.vpa = NULL;
+ break;
+ case 6: /* unregister DTL */
+ tvcpu->arch.dtl = NULL;
+ break;
+ case 7: /* unregister SLB shadow buffer */
+ tvcpu->arch.slb_shadow = NULL;
+ break;
+ }
+ }
+ return H_SUCCESS;
+}
+
+int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
+{
+ unsigned long req = kvmppc_get_gpr(vcpu, 3);
+ unsigned long target, ret = H_SUCCESS;
+ struct kvm_vcpu *tvcpu;
+
+ 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);
+ tvcpu = kvmppc_find_vcpu(vcpu->kvm, target);
+ if (!tvcpu) {
+ ret = H_PARAMETER;
+ break;
+ }
+ tvcpu->arch.prodded = 1;
+ smp_mb();
+ if (vcpu->arch.ceded) {
+ if (waitqueue_active(&vcpu->wq)) {
+ wake_up_interruptible(&vcpu->wq);
+ vcpu->stat.halt_wakeup++;
+ }
+ }
+ break;
+ case H_CONFER:
+ break;
+ case H_REGISTER_VPA:
+ ret = do_h_register_vpa(vcpu, kvmppc_get_gpr(vcpu, 4),
+ kvmppc_get_gpr(vcpu, 5),
+ kvmppc_get_gpr(vcpu, 6));
+ break;
+ default:
+ return RESUME_HOST;
+ }
+ kvmppc_set_gpr(vcpu, 3, ret);
+ vcpu->arch.hcall_needed = 0;
+ return RESUME_GUEST;
+}
+
+static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ struct task_struct *tsk)
+{
+ int r = RESUME_HOST;
+
+ vcpu->stat.sum_exits++;
+
+ run->exit_reason = KVM_EXIT_UNKNOWN;
+ run->ready_for_interrupt_injection = 1;
+ switch (vcpu->arch.trap) {
+ /* We're good on these - the host merely wanted to get our attention */
+ case BOOK3S_INTERRUPT_HV_DECREMENTER:
+ vcpu->stat.dec_exits++;
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_EXTERNAL:
+ vcpu->stat.ext_intr_exits++;
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_PERFMON:
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_PROGRAM:
+ {
+ ulong flags;
+ /*
+ * Normally program interrupts are delivered directly
+ * to the guest by the hardware, but we can get here
+ * as a result of a hypervisor emulation interrupt
+ * (e40) getting turned into a 700 by BML RTAS.
+ */
+ flags = vcpu->arch.shregs.msr & 0x1f0000ull;
+ kvmppc_core_queue_program(vcpu, flags);
+ r = RESUME_GUEST;
+ break;
+ }
+ case BOOK3S_INTERRUPT_SYSCALL:
+ {
+ /* hcall - punt to userspace */
+ int i;
+
+ if (vcpu->arch.shregs.msr & MSR_PR) {
+ /* sc 1 from userspace - reflect to guest syscall */
+ kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_SYSCALL);
+ r = RESUME_GUEST;
+ break;
+ }
+ run->papr_hcall.nr = kvmppc_get_gpr(vcpu, 3);
+ for (i = 0; i < 9; ++i)
+ run->papr_hcall.args[i] = kvmppc_get_gpr(vcpu, 4 + i);
+ run->exit_reason = KVM_EXIT_PAPR_HCALL;
+ vcpu->arch.hcall_needed = 1;
+ r = RESUME_HOST;
+ break;
+ }
+ /*
+ * We get these next two if the guest does a bad real-mode access,
+ * as we have enabled VRMA (virtualized real mode area) mode in the
+ * LPCR. We just generate an appropriate DSI/ISI to the guest.
+ */
+ case BOOK3S_INTERRUPT_H_DATA_STORAGE:
+ vcpu->arch.shregs.dsisr = vcpu->arch.fault_dsisr;
+ vcpu->arch.shregs.dar = vcpu->arch.fault_dar;
+ kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, 0);
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_H_INST_STORAGE:
+ kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE,
+ 0x08000000);
+ r = RESUME_GUEST;
+ break;
+ /*
+ * This occurs if the guest executes an illegal instruction.
+ * We just generate a program interrupt to the guest, since
+ * we don't emulate any guest instructions at this stage.
+ */
+ case BOOK3S_INTERRUPT_H_EMUL_ASSIST:
+ kvmppc_core_queue_program(vcpu, 0x80000);
+ r = RESUME_GUEST;
+ break;
+ default:
+ kvmppc_dump_regs(vcpu);
+ printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n",
+ vcpu->arch.trap, kvmppc_get_pc(vcpu),
+ vcpu->arch.shregs.msr);
+ r = RESUME_HOST;
+ BUG();
+ 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;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
+{
+ int i;
+
+ sregs->pvr = vcpu->arch.pvr;
+
+ memset(sregs, 0, sizeof(struct kvm_sregs));
+ for (i = 0; i < vcpu->arch.slb_max; i++) {
+ sregs->u.s.ppc64.slb[i].slbe = vcpu->arch.slb[i].orige;
+ sregs->u.s.ppc64.slb[i].slbv = vcpu->arch.slb[i].origv;
+ }
+
+ return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
+{
+ int i, j;
+
+ kvmppc_set_pvr(vcpu, sregs->pvr);
+
+ j = 0;
+ for (i = 0; i < vcpu->arch.slb_nr; i++) {
+ if (sregs->u.s.ppc64.slb[i].slbe & SLB_ESID_V) {
+ vcpu->arch.slb[j].orige = sregs->u.s.ppc64.slb[i].slbe;
+ vcpu->arch.slb[j].origv = sregs->u.s.ppc64.slb[i].slbv;
+ ++j;
+ }
+ }
+ vcpu->arch.slb_max = j;
+
+ return 0;
+}
+
+int kvmppc_core_check_processor_compat(void)
+{
+ if (cpu_has_feature(CPU_FTR_HVMODE))
+ return 0;
+ return -EIO;
+}
+
+struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+ struct kvm_vcpu *vcpu;
+ int err = -EINVAL;
+ int core;
+ struct kvmppc_vcore *vcore;
+
+ core = id / threads_per_core;
+ if (core >= KVM_MAX_VCORES)
+ goto out;
+
+ err = -ENOMEM;
+ vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+ if (!vcpu)
+ goto out;
+
+ err = kvm_vcpu_init(vcpu, kvm, id);
+ if (err)
+ goto free_vcpu;
+
+ vcpu->arch.shared = &vcpu->arch.shregs;
+ vcpu->arch.last_cpu = -1;
+ vcpu->arch.mmcr[0] = MMCR0_FC;
+ vcpu->arch.ctrl = CTRL_RUNLATCH;
+ /* default to host PVR, since we can't spoof it */
+ vcpu->arch.pvr = mfspr(SPRN_PVR);
+ kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
+
+ 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.
+ */
+ vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
+
+ init_waitqueue_head(&vcpu->arch.cpu_run);
+
+ mutex_lock(&kvm->lock);
+ vcore = kvm->arch.vcores[core];
+ if (!vcore) {
+ vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL);
+ if (vcore) {
+ INIT_LIST_HEAD(&vcore->runnable_threads);
+ spin_lock_init(&vcore->lock);
+ }
+ kvm->arch.vcores[core] = vcore;
+ }
+ mutex_unlock(&kvm->lock);
+
+ if (!vcore)
+ goto free_vcpu;
+
+ spin_lock(&vcore->lock);
+ ++vcore->num_threads;
+ ++vcore->n_blocked;
+ spin_unlock(&vcore->lock);
+ vcpu->arch.vcore = vcore;
+
+ return vcpu;
+
+free_vcpu:
+ kfree(vcpu);
+out:
+ return ERR_PTR(err);
+}
+
+void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
+{
+ kvm_vcpu_uninit(vcpu);
+ kfree(vcpu);
+}
+
+static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_vcore *vc = vcpu->arch.vcore;
+
+ 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);
+ }
+ spin_unlock(&vc->lock);
+}
+
+static void kvmppc_vcpu_unblocked(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);
+}
+
+extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
+extern void xics_wake_cpu(int cpu);
+
+static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
+ struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu *v;
+
+ if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
+ return;
+ vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
+ --vc->n_runnable;
+ /* decrement the physical thread id of each following vcpu */
+ v = vcpu;
+ list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
+ --v->arch.ptid;
+ list_del(&vcpu->arch.run_list);
+}
+
+static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
+{
+ int cpu;
+ struct paca_struct *tpaca;
+ struct kvmppc_vcore *vc = vcpu->arch.vcore;
+
+ cpu = vc->pcpu + vcpu->arch.ptid;
+ tpaca = &paca[cpu];
+ tpaca->kvm_hstate.kvm_vcpu = vcpu;
+ tpaca->kvm_hstate.kvm_vcore = vc;
+ 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;
+ }
+#endif
+}
+
+static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc)
+{
+ int i;
+
+ HMT_low();
+ i = 0;
+ while (vc->nap_count < vc->n_woken) {
+ if (++i >= 1000000) {
+ pr_err("kvmppc_wait_for_nap timeout %d %d\n",
+ vc->nap_count, vc->n_woken);
+ break;
+ }
+ cpu_relax();
+ }
+ HMT_medium();
+}
+
+/*
+ * Check that we are on thread 0 and that any other threads in
+ * this core are off-line.
+ */
+static int on_primary_thread(void)
+{
+ int cpu = smp_processor_id();
+ int thr = cpu_thread_in_core(cpu);
+
+ if (thr)
+ return 0;
+ while (++thr < threads_per_core)
+ if (cpu_online(cpu + thr))
+ return 0;
+ return 1;
+}
+
+/*
+ * Run a set of guest threads on a physical core.
+ * Called with vc->lock held.
+ */
+static int kvmppc_run_core(struct kvmppc_vcore *vc)
+{
+ struct kvm_vcpu *vcpu, *vnext;
+ long ret;
+ u64 now;
+
+ /* don't start if any threads have a signal pending */
+ list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+ if (signal_pending(vcpu->arch.run_task))
+ return 0;
+
+ /*
+ * Make sure we are running on thread 0, and that
+ * secondary threads are offline.
+ * XXX we should also block attempts to bring any
+ * secondary threads online.
+ */
+ if (threads_per_core > 1 && !on_primary_thread()) {
+ list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+ vcpu->arch.ret = -EBUSY;
+ goto out;
+ }
+
+ vc->n_woken = 0;
+ vc->nap_count = 0;
+ vc->entry_exit_count = 0;
+ vc->vcore_running = 1;
+ vc->in_guest = 0;
+ vc->pcpu = smp_processor_id();
+ 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);
+
+ spin_unlock(&vc->lock);
+
+ preempt_disable();
+ kvm_guest_enter();
+ __kvmppc_vcore_entry(NULL, vcpu);
+
+ /* wait for secondary threads to finish writing their state to memory */
+ spin_lock(&vc->lock);
+ 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;
+ spin_unlock(&vc->lock);
+
+ /* make sure updates to secondary vcpu structs are visible now */
+ smp_mb();
+ kvm_guest_exit();
+
+ preempt_enable();
+ kvm_resched(vcpu);
+
+ now = get_tb();
+ list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
+ /* cancel pending dec exception if dec is positive */
+ 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);
+ vcpu->arch.ret = ret;
+ vcpu->arch.trap = 0;
+ }
+
+ spin_lock(&vc->lock);
+ out:
+ vc->vcore_running = 0;
+ list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
+ arch.run_list) {
+ if (vcpu->arch.ret != RESUME_GUEST) {
+ kvmppc_remove_runnable(vc, vcpu);
+ wake_up(&vcpu->arch.cpu_run);
+ }
+ }
+
+ return 1;
+}
+
+static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+ 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;
+ }
+
+ /* On PPC970, check that we have an RMA region */
+ if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
+ return -EPERM;
+
+ 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.run_task = current;
+ vcpu->arch.kvm_run = kvm_run;
+ vcpu->arch.ptid = ptid;
+ 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);
+ }
+
+ if (!vc->vcore_running &&
+ vc->n_runnable + vc->n_blocked == vc->num_threads) {
+ /* we can run now */
+ if (kvmppc_run_core(vc))
+ continue;
+ }
+
+ if (vc->vcore_running == 1 && VCORE_EXIT_COUNT(vc) == 0)
+ kvmppc_start_thread(vcpu);
+
+ /* 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 (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
+ kvmppc_remove_runnable(vc, vcpu);
+ spin_unlock(&vc->lock);
+
+ return vcpu->arch.ret;
+}
+
+int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+ int r;
+
+ do {
+ r = kvmppc_run_vcpu(run, vcpu);
+
+ if (run->exit_reason == KVM_EXIT_PAPR_HCALL &&
+ !(vcpu->arch.shregs.msr & MSR_PR)) {
+ r = kvmppc_pseries_do_hcall(vcpu);
+ kvmppc_core_deliver_interrupts(vcpu);
+ }
+ } while (r == RESUME_GUEST);
+ return r;
+}
+
+static long kvmppc_stt_npages(unsigned long window_size)
+{
+ return ALIGN((window_size >> SPAPR_TCE_SHIFT)
+ * sizeof(u64), PAGE_SIZE) / PAGE_SIZE;
+}
+
+static void release_spapr_tce_table(struct kvmppc_spapr_tce_table *stt)
+{
+ struct kvm *kvm = stt->kvm;
+ int i;
+
+ mutex_lock(&kvm->lock);
+ list_del(&stt->list);
+ for (i = 0; i < kvmppc_stt_npages(stt->window_size); i++)
+ __free_page(stt->pages[i]);
+ kfree(stt);
+ mutex_unlock(&kvm->lock);
+
+ kvm_put_kvm(kvm);
+}
+
+static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data;
+ struct page *page;
+
+ if (vmf->pgoff >= kvmppc_stt_npages(stt->window_size))
+ return VM_FAULT_SIGBUS;
+
+ page = stt->pages[vmf->pgoff];
+ get_page(page);
+ vmf->page = page;
+ return 0;
+}
+
+static const struct vm_operations_struct kvm_spapr_tce_vm_ops = {
+ .fault = kvm_spapr_tce_fault,
+};
+
+static int kvm_spapr_tce_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ vma->vm_ops = &kvm_spapr_tce_vm_ops;
+ return 0;
+}
+
+static int kvm_spapr_tce_release(struct inode *inode, struct file *filp)
+{
+ struct kvmppc_spapr_tce_table *stt = filp->private_data;
+
+ release_spapr_tce_table(stt);
+ return 0;
+}
+
+static struct file_operations kvm_spapr_tce_fops = {
+ .mmap = kvm_spapr_tce_mmap,
+ .release = kvm_spapr_tce_release,
+};
+
+long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
+ struct kvm_create_spapr_tce *args)
+{
+ struct kvmppc_spapr_tce_table *stt = NULL;
+ long npages;
+ int ret = -ENOMEM;
+ int i;
+
+ /* Check this LIOBN hasn't been previously allocated */
+ list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
+ if (stt->liobn == args->liobn)
+ return -EBUSY;
+ }
+
+ npages = kvmppc_stt_npages(args->window_size);
+
+ stt = kzalloc(sizeof(*stt) + npages* sizeof(struct page *),
+ GFP_KERNEL);
+ if (!stt)
+ goto fail;
+
+ stt->liobn = args->liobn;
+ stt->window_size = args->window_size;
+ stt->kvm = kvm;
+
+ for (i = 0; i < npages; i++) {
+ stt->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!stt->pages[i])
+ goto fail;
+ }
+
+ kvm_get_kvm(kvm);
+
+ mutex_lock(&kvm->lock);
+ list_add(&stt->list, &kvm->arch.spapr_tce_tables);
+
+ mutex_unlock(&kvm->lock);
+
+ return anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops,
+ stt, O_RDWR);
+
+fail:
+ if (stt) {
+ for (i = 0; i < npages; i++)
+ if (stt->pages[i])
+ __free_page(stt->pages[i]);
+
+ kfree(stt);
+ }
+ return ret;
+}
+
+/* Work out RMLS (real mode limit selector) field value for a given RMA size.
+ Assumes POWER7 or PPC970. */
+static inline int lpcr_rmls(unsigned long rma_size)
+{
+ switch (rma_size) {
+ case 32ul << 20: /* 32 MB */
+ if (cpu_has_feature(CPU_FTR_ARCH_206))
+ return 8; /* only supported on POWER7 */
+ return -1;
+ case 64ul << 20: /* 64 MB */
+ return 3;
+ case 128ul << 20: /* 128 MB */
+ return 7;
+ case 256ul << 20: /* 256 MB */
+ return 4;
+ case 1ul << 30: /* 1 GB */
+ return 2;
+ case 16ul << 30: /* 16 GB */
+ return 1;
+ case 256ul << 30: /* 256 GB */
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+static int kvm_rma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct kvmppc_rma_info *ri = vma->vm_file->private_data;
+ struct page *page;
+
+ if (vmf->pgoff >= ri->npages)
+ return VM_FAULT_SIGBUS;
+
+ page = pfn_to_page(ri->base_pfn + vmf->pgoff);
+ get_page(page);
+ vmf->page = page;
+ return 0;
+}
+
+static const struct vm_operations_struct kvm_rma_vm_ops = {
+ .fault = kvm_rma_fault,
+};
+
+static int kvm_rma_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &kvm_rma_vm_ops;
+ return 0;
+}
+
+static int kvm_rma_release(struct inode *inode, struct file *filp)
+{
+ struct kvmppc_rma_info *ri = filp->private_data;
+
+ kvm_release_rma(ri);
+ return 0;
+}
+
+static struct file_operations kvm_rma_fops = {
+ .mmap = kvm_rma_mmap,
+ .release = kvm_rma_release,
+};
+
+long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
+{
+ struct kvmppc_rma_info *ri;
+ long fd;
+
+ ri = kvm_alloc_rma();
+ if (!ri)
+ return -ENOMEM;
+
+ fd = anon_inode_getfd("kvm-rma", &kvm_rma_fops, ri, O_RDWR);
+ if (fd < 0)
+ kvm_release_rma(ri);
+
+ ret->rma_size = ri->npages << PAGE_SHIFT;
+ return fd;
+}
+
+static struct page *hva_to_page(unsigned long addr)
+{
+ struct page *page[1];
+ int npages;
+
+ might_sleep();
+
+ npages = get_user_pages_fast(addr, 1, 1, page);
+
+ if (unlikely(npages != 1))
+ return 0;
+
+ return page[0];
+}
+
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem)
+{
+ unsigned long psize, porder;
+ unsigned long i, npages, totalpages;
+ unsigned long pg_ix;
+ struct kvmppc_pginfo *pginfo;
+ unsigned long hva;
+ struct kvmppc_rma_info *ri = NULL;
+ struct page *page;
+
+ /* For now, only allow 16MB pages */
+ porder = LARGE_PAGE_ORDER;
+ psize = 1ul << porder;
+ if ((mem->memory_size & (psize - 1)) ||
+ (mem->guest_phys_addr & (psize - 1))) {
+ pr_err("bad memory_size=%llx @ %llx\n",
+ mem->memory_size, mem->guest_phys_addr);
+ return -EINVAL;
+ }
+
+ npages = mem->memory_size >> porder;
+ totalpages = (mem->guest_phys_addr + mem->memory_size) >> porder;
+
+ /* More memory than we have space to track? */
+ if (totalpages > (1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER)))
+ return -EINVAL;
+
+ /* Do we already have an RMA registered? */
+ if (mem->guest_phys_addr == 0 && kvm->arch.rma)
+ return -EINVAL;
+
+ if (totalpages > kvm->arch.ram_npages)
+ kvm->arch.ram_npages = totalpages;
+
+ /* Is this one of our preallocated RMAs? */
+ if (mem->guest_phys_addr == 0) {
+ struct vm_area_struct *vma;
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, mem->userspace_addr);
+ if (vma && vma->vm_file &&
+ vma->vm_file->f_op == &kvm_rma_fops &&
+ mem->userspace_addr == vma->vm_start)
+ ri = vma->vm_file->private_data;
+ up_read(&current->mm->mmap_sem);
+ if (!ri && cpu_has_feature(CPU_FTR_ARCH_201)) {
+ pr_err("CPU requires an RMO\n");
+ return -EINVAL;
+ }
+ }
+
+ if (ri) {
+ unsigned long rma_size;
+ unsigned long lpcr;
+ long rmls;
+
+ rma_size = ri->npages << PAGE_SHIFT;
+ if (rma_size > mem->memory_size)
+ rma_size = mem->memory_size;
+ rmls = lpcr_rmls(rma_size);
+ if (rmls < 0) {
+ pr_err("Can't use RMA of 0x%lx bytes\n", rma_size);
+ return -EINVAL;
+ }
+ atomic_inc(&ri->use_count);
+ kvm->arch.rma = ri;
+ kvm->arch.n_rma_pages = rma_size >> porder;
+
+ /* Update LPCR and RMOR */
+ lpcr = kvm->arch.lpcr;
+ if (cpu_has_feature(CPU_FTR_ARCH_201)) {
+ /* PPC970; insert RMLS value (split field) in HID4 */
+ lpcr &= ~((1ul << HID4_RMLS0_SH) |
+ (3ul << HID4_RMLS2_SH));
+ lpcr |= ((rmls >> 2) << HID4_RMLS0_SH) |
+ ((rmls & 3) << HID4_RMLS2_SH);
+ /* RMOR is also in HID4 */
+ lpcr |= ((ri->base_pfn >> (26 - PAGE_SHIFT)) & 0xffff)
+ << HID4_RMOR_SH;
+ } else {
+ /* POWER7 */
+ lpcr &= ~(LPCR_VPM0 | LPCR_VRMA_L);
+ lpcr |= rmls << LPCR_RMLS_SH;
+ kvm->arch.rmor = kvm->arch.rma->base_pfn << PAGE_SHIFT;
+ }
+ kvm->arch.lpcr = lpcr;
+ pr_info("Using RMO at %lx size %lx (LPCR = %lx)\n",
+ ri->base_pfn << PAGE_SHIFT, rma_size, lpcr);
+ }
+
+ pg_ix = mem->guest_phys_addr >> porder;
+ pginfo = kvm->arch.ram_pginfo + pg_ix;
+ for (i = 0; i < npages; ++i, ++pg_ix) {
+ if (ri && pg_ix < kvm->arch.n_rma_pages) {
+ pginfo[i].pfn = ri->base_pfn +
+ (pg_ix << (porder - PAGE_SHIFT));
+ continue;
+ }
+ hva = mem->userspace_addr + (i << porder);
+ page = hva_to_page(hva);
+ if (!page) {
+ pr_err("oops, no pfn for hva %lx\n", hva);
+ goto err;
+ }
+ /* Check it's a 16MB page */
+ if (!PageHead(page) ||
+ compound_order(page) != (LARGE_PAGE_ORDER - PAGE_SHIFT)) {
+ pr_err("page at %lx isn't 16MB (o=%d)\n",
+ hva, compound_order(page));
+ goto err;
+ }
+ pginfo[i].pfn = page_to_pfn(page);
+ }
+
+ return 0;
+
+ err:
+ return -EINVAL;
+}
+
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem)
+{
+ if (mem->guest_phys_addr == 0 && mem->memory_size != 0 &&
+ !kvm->arch.rma)
+ kvmppc_map_vrma(kvm, mem);
+}
+
+int kvmppc_core_init_vm(struct kvm *kvm)
+{
+ long r;
+ unsigned long npages = 1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER);
+ long err = -ENOMEM;
+ unsigned long lpcr;
+
+ /* Allocate hashed page table */
+ r = kvmppc_alloc_hpt(kvm);
+ if (r)
+ return r;
+
+ INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
+
+ kvm->arch.ram_pginfo = kzalloc(npages * sizeof(struct kvmppc_pginfo),
+ GFP_KERNEL);
+ if (!kvm->arch.ram_pginfo) {
+ pr_err("kvmppc_core_init_vm: couldn't alloc %lu bytes\n",
+ npages * sizeof(struct kvmppc_pginfo));
+ goto out_free;
+ }
+
+ kvm->arch.ram_npages = 0;
+ kvm->arch.ram_psize = 1ul << LARGE_PAGE_ORDER;
+ kvm->arch.ram_porder = LARGE_PAGE_ORDER;
+ kvm->arch.rma = NULL;
+ kvm->arch.n_rma_pages = 0;
+
+ kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
+
+ if (cpu_has_feature(CPU_FTR_ARCH_201)) {
+ /* PPC970; HID4 is effectively the LPCR */
+ unsigned long lpid = kvm->arch.lpid;
+ kvm->arch.host_lpid = 0;
+ kvm->arch.host_lpcr = lpcr = mfspr(SPRN_HID4);
+ lpcr &= ~((3 << HID4_LPID1_SH) | (0xful << HID4_LPID5_SH));
+ lpcr |= ((lpid >> 4) << HID4_LPID1_SH) |
+ ((lpid & 0xf) << HID4_LPID5_SH);
+ } else {
+ /* POWER7; init LPCR for virtual RMA mode */
+ kvm->arch.host_lpid = mfspr(SPRN_LPID);
+ kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR);
+ lpcr &= LPCR_PECE | LPCR_LPES;
+ lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE |
+ LPCR_VPM0 | LPCR_VRMA_L;
+ }
+ kvm->arch.lpcr = lpcr;
+
+ return 0;
+
+ out_free:
+ kvmppc_free_hpt(kvm);
+ return err;
+}
+
+void kvmppc_core_destroy_vm(struct kvm *kvm)
+{
+ struct kvmppc_pginfo *pginfo;
+ unsigned long i;
+
+ if (kvm->arch.ram_pginfo) {
+ pginfo = kvm->arch.ram_pginfo;
+ kvm->arch.ram_pginfo = NULL;
+ for (i = kvm->arch.n_rma_pages; i < kvm->arch.ram_npages; ++i)
+ if (pginfo[i].pfn)
+ put_page(pfn_to_page(pginfo[i].pfn));
+ kfree(pginfo);
+ }
+ if (kvm->arch.rma) {
+ kvm_release_rma(kvm->arch.rma);
+ kvm->arch.rma = NULL;
+ }
+
+ kvmppc_free_hpt(kvm);
+ WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
+}
+
+/* These are stubs for now */
+void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
+{
+}
+
+/* We don't need to emulate any privileged instructions or dcbz */
+int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int inst, int *advance)
+{
+ return EMULATE_FAIL;
+}
+
+int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+ return EMULATE_FAIL;
+}
+
+int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+ return EMULATE_FAIL;
+}
+
+static int kvmppc_book3s_hv_init(void)
+{
+ int r;
+
+ r = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+
+ if (r)
+ return r;
+
+ r = kvmppc_mmu_hv_init();
+
+ return r;
+}
+
+static void kvmppc_book3s_hv_exit(void)
+{
+ kvm_exit();
+}
+
+module_init(kvmppc_book3s_hv_init);
+module_exit(kvmppc_book3s_hv_exit);
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
new file mode 100644
index 000000000000..d43120355eec
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.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/kvm_host.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+
+#include <asm/cputable.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+
+/*
+ * This maintains a list of RMAs (real mode areas) for KVM guests to use.
+ * Each RMA has to be physically contiguous and of a size that the
+ * hardware supports. PPC970 and POWER7 support 64MB, 128MB and 256MB,
+ * and other larger sizes. Since we are unlikely to be allocate that
+ * much physically contiguous memory after the system is up and running,
+ * we preallocate a set of RMAs in early boot for KVM to use.
+ */
+static unsigned long kvm_rma_size = 64 << 20; /* 64MB */
+static unsigned long kvm_rma_count;
+
+static int __init early_parse_rma_size(char *p)
+{
+ if (!p)
+ return 1;
+
+ kvm_rma_size = memparse(p, &p);
+
+ return 0;
+}
+early_param("kvm_rma_size", early_parse_rma_size);
+
+static int __init early_parse_rma_count(char *p)
+{
+ if (!p)
+ return 1;
+
+ kvm_rma_count = simple_strtoul(p, NULL, 0);
+
+ return 0;
+}
+early_param("kvm_rma_count", early_parse_rma_count);
+
+static struct kvmppc_rma_info *rma_info;
+static LIST_HEAD(free_rmas);
+static DEFINE_SPINLOCK(rma_lock);
+
+/* Work out RMLS (real mode limit selector) field value for a given RMA size.
+ Assumes POWER7 or PPC970. */
+static inline int lpcr_rmls(unsigned long rma_size)
+{
+ switch (rma_size) {
+ case 32ul << 20: /* 32 MB */
+ if (cpu_has_feature(CPU_FTR_ARCH_206))
+ return 8; /* only supported on POWER7 */
+ return -1;
+ case 64ul << 20: /* 64 MB */
+ return 3;
+ case 128ul << 20: /* 128 MB */
+ return 7;
+ case 256ul << 20: /* 256 MB */
+ return 4;
+ case 1ul << 30: /* 1 GB */
+ return 2;
+ case 16ul << 30: /* 16 GB */
+ return 1;
+ case 256ul << 30: /* 256 GB */
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Called at boot time while the bootmem allocator is active,
+ * to allocate contiguous physical memory for the real memory
+ * areas for guests.
+ */
+void kvm_rma_init(void)
+{
+ unsigned long i;
+ unsigned long j, npages;
+ void *rma;
+ struct page *pg;
+
+ /* Only do this on PPC970 in HV mode */
+ if (!cpu_has_feature(CPU_FTR_HVMODE) ||
+ !cpu_has_feature(CPU_FTR_ARCH_201))
+ return;
+
+ if (!kvm_rma_size || !kvm_rma_count)
+ return;
+
+ /* Check that the requested size is one supported in hardware */
+ if (lpcr_rmls(kvm_rma_size) < 0) {
+ pr_err("RMA size of 0x%lx not supported\n", kvm_rma_size);
+ return;
+ }
+
+ npages = kvm_rma_size >> PAGE_SHIFT;
+ rma_info = alloc_bootmem(kvm_rma_count * sizeof(struct kvmppc_rma_info));
+ for (i = 0; i < kvm_rma_count; ++i) {
+ rma = alloc_bootmem_align(kvm_rma_size, kvm_rma_size);
+ pr_info("Allocated KVM RMA at %p (%ld MB)\n", rma,
+ kvm_rma_size >> 20);
+ rma_info[i].base_virt = rma;
+ rma_info[i].base_pfn = __pa(rma) >> PAGE_SHIFT;
+ rma_info[i].npages = npages;
+ list_add_tail(&rma_info[i].list, &free_rmas);
+ atomic_set(&rma_info[i].use_count, 0);
+
+ pg = pfn_to_page(rma_info[i].base_pfn);
+ for (j = 0; j < npages; ++j) {
+ atomic_inc(&pg->_count);
+ ++pg;
+ }
+ }
+}
+
+struct kvmppc_rma_info *kvm_alloc_rma(void)
+{
+ struct kvmppc_rma_info *ri;
+
+ ri = NULL;
+ spin_lock(&rma_lock);
+ if (!list_empty(&free_rmas)) {
+ ri = list_first_entry(&free_rmas, struct kvmppc_rma_info, list);
+ list_del(&ri->list);
+ atomic_inc(&ri->use_count);
+ }
+ spin_unlock(&rma_lock);
+ return ri;
+}
+EXPORT_SYMBOL_GPL(kvm_alloc_rma);
+
+void kvm_release_rma(struct kvmppc_rma_info *ri)
+{
+ if (atomic_dec_and_test(&ri->use_count)) {
+ spin_lock(&rma_lock);
+ list_add_tail(&ri->list, &free_rmas);
+ spin_unlock(&rma_lock);
+
+ }
+}
+EXPORT_SYMBOL_GPL(kvm_release_rma);
+
diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S
new file mode 100644
index 000000000000..3f7b674dd4bf
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_interrupts.S
@@ -0,0 +1,166 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *
+ * Derived from book3s_interrupts.S, which is:
+ * Copyright SUSE Linux Products GmbH 2009
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+#include <asm/exception-64s.h>
+#include <asm/ppc-opcode.h>
+
+/*****************************************************************************
+ * *
+ * Guest entry / exit code that is in kernel module memory (vmalloc) *
+ * *
+ ****************************************************************************/
+
+/* Registers:
+ * r4: vcpu pointer
+ */
+_GLOBAL(__kvmppc_vcore_entry)
+
+ /* Write correct stack frame */
+ mflr r0
+ std r0,PPC_LR_STKOFF(r1)
+
+ /* Save host state to the stack */
+ stdu r1, -SWITCH_FRAME_SIZE(r1)
+
+ /* Save non-volatile registers (r14 - r31) */
+ SAVE_NVGPRS(r1)
+
+ /* Save host DSCR */
+BEGIN_FTR_SECTION
+ mfspr r3, SPRN_DSCR
+ std r3, HSTATE_DSCR(r13)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+ /* Save host DABR */
+ mfspr r3, SPRN_DABR
+ std r3, HSTATE_DABR(r13)
+
+ /* Hard-disable interrupts */
+ mfmsr r10
+ std r10, HSTATE_HOST_MSR(r13)
+ rldicl r10,r10,48,1
+ rotldi r10,r10,16
+ mtmsrd r10,1
+
+ /* Save host PMU registers and load guest PMU registers */
+ /* R4 is live here (vcpu pointer) but not r3 or r5 */
+ li r3, 1
+ sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */
+ mfspr r7, SPRN_MMCR0 /* save MMCR0 */
+ mtspr SPRN_MMCR0, r3 /* freeze all counters, disable interrupts */
+ isync
+ ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */
+ lbz r5, LPPACA_PMCINUSE(r3)
+ cmpwi r5, 0
+ beq 31f /* skip if not */
+ mfspr r5, SPRN_MMCR1
+ mfspr r6, SPRN_MMCRA
+ std r7, HSTATE_MMCR(r13)
+ std r5, HSTATE_MMCR + 8(r13)
+ std r6, HSTATE_MMCR + 16(r13)
+ mfspr r3, SPRN_PMC1
+ mfspr r5, SPRN_PMC2
+ mfspr r6, SPRN_PMC3
+ mfspr r7, SPRN_PMC4
+ mfspr r8, SPRN_PMC5
+ mfspr r9, SPRN_PMC6
+BEGIN_FTR_SECTION
+ mfspr r10, SPRN_PMC7
+ mfspr r11, SPRN_PMC8
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ stw r3, HSTATE_PMC(r13)
+ stw r5, HSTATE_PMC + 4(r13)
+ stw r6, HSTATE_PMC + 8(r13)
+ stw r7, HSTATE_PMC + 12(r13)
+ stw r8, HSTATE_PMC + 16(r13)
+ stw r9, HSTATE_PMC + 20(r13)
+BEGIN_FTR_SECTION
+ stw r10, HSTATE_PMC + 24(r13)
+ stw r11, HSTATE_PMC + 28(r13)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+31:
+
+ /*
+ * Put whatever is in the decrementer into the
+ * hypervisor decrementer.
+ */
+ mfspr r8,SPRN_DEC
+ mftb r7
+ mtspr SPRN_HDEC,r8
+ extsw r8,r8
+ add r8,r8,r7
+ std r8,HSTATE_DECEXP(r13)
+
+ /*
+ * On PPC970, if the guest vcpu has an external interrupt pending,
+ * send ourselves an IPI so as to interrupt the guest once it
+ * enables interrupts. (It must have interrupts disabled,
+ * otherwise we would already have delivered the interrupt.)
+ */
+BEGIN_FTR_SECTION
+ 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 32f
+ mr r31, r4
+ lhz r3, PACAPACAINDEX(r13)
+ bl smp_send_reschedule
+ nop
+ mr r4, r31
+32:
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+
+ /* Jump to partition switch code */
+ bl .kvmppc_hv_entry_trampoline
+ nop
+
+/*
+ * We return here in virtual mode after the guest exits
+ * with something that we can't handle in real mode.
+ * Interrupts are enabled again at this point.
+ */
+
+.global kvmppc_handler_highmem
+kvmppc_handler_highmem:
+
+ /*
+ * Register usage at this point:
+ *
+ * R1 = host R1
+ * R2 = host R2
+ * R12 = exit handler id
+ * R13 = PACA
+ */
+
+ /* Restore non-volatile host registers (r14 - r31) */
+ REST_NVGPRS(r1)
+
+ addi r1, r1, SWITCH_FRAME_SIZE
+ ld r0, PPC_LR_STKOFF(r1)
+ mtlr r0
+ blr
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
new file mode 100644
index 000000000000..fcfe6b055558
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -0,0 +1,370 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * Copyright 2010-2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/hugetlb.h>
+
+#include <asm/tlbflush.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu-hash64.h>
+#include <asm/hvcall.h>
+#include <asm/synch.h>
+#include <asm/ppc-opcode.h>
+
+/* For now use fixed-size 16MB page table */
+#define HPT_ORDER 24
+#define HPT_NPTEG (1ul << (HPT_ORDER - 7)) /* 128B per pteg */
+#define HPT_HASH_MASK (HPT_NPTEG - 1)
+
+#define HPTE_V_HVLOCK 0x40UL
+
+static inline long lock_hpte(unsigned long *hpte, unsigned long bits)
+{
+ unsigned long tmp, old;
+
+ asm volatile(" ldarx %0,0,%2\n"
+ " and. %1,%0,%3\n"
+ " bne 2f\n"
+ " ori %0,%0,%4\n"
+ " stdcx. %0,0,%2\n"
+ " beq+ 2f\n"
+ " li %1,%3\n"
+ "2: isync"
+ : "=&r" (tmp), "=&r" (old)
+ : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
+ : "cc", "memory");
+ return old == 0;
+}
+
+long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+ long pte_index, unsigned long pteh, unsigned long ptel)
+{
+ unsigned long porder;
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long i, lpn, pa;
+ unsigned long *hpte;
+
+ /* only handle 4k, 64k and 16M pages for now */
+ porder = 12;
+ if (pteh & HPTE_V_LARGE) {
+ if (cpu_has_feature(CPU_FTR_ARCH_206) &&
+ (ptel & 0xf000) == 0x1000) {
+ /* 64k page */
+ porder = 16;
+ } else if ((ptel & 0xff000) == 0) {
+ /* 16M page */
+ porder = 24;
+ /* lowest AVA bit must be 0 for 16M pages */
+ if (pteh & 0x80)
+ return H_PARAMETER;
+ } else
+ return H_PARAMETER;
+ }
+ lpn = (ptel & HPTE_R_RPN) >> kvm->arch.ram_porder;
+ if (lpn >= kvm->arch.ram_npages || porder > kvm->arch.ram_porder)
+ return H_PARAMETER;
+ pa = kvm->arch.ram_pginfo[lpn].pfn << PAGE_SHIFT;
+ if (!pa)
+ return H_PARAMETER;
+ /* Check WIMG */
+ if ((ptel & HPTE_R_WIMG) != HPTE_R_M &&
+ (ptel & HPTE_R_WIMG) != (HPTE_R_W | HPTE_R_I | HPTE_R_M))
+ return H_PARAMETER;
+ pteh &= ~0x60UL;
+ ptel &= ~(HPTE_R_PP0 - kvm->arch.ram_psize);
+ ptel |= pa;
+ if (pte_index >= (HPT_NPTEG << 3))
+ return H_PARAMETER;
+ if (likely((flags & H_EXACT) == 0)) {
+ pte_index &= ~7UL;
+ hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ for (i = 0; ; ++i) {
+ if (i == 8)
+ return H_PTEG_FULL;
+ if ((*hpte & HPTE_V_VALID) == 0 &&
+ lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
+ break;
+ hpte += 2;
+ }
+ } else {
+ i = 0;
+ hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
+ return H_PTEG_FULL;
+ }
+ hpte[1] = ptel;
+ eieio();
+ hpte[0] = pteh;
+ asm volatile("ptesync" : : : "memory");
+ atomic_inc(&kvm->arch.ram_pginfo[lpn].refcnt);
+ vcpu->arch.gpr[4] = pte_index + i;
+ 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)
+{
+ unsigned int tmp, old;
+ unsigned int token = LOCK_TOKEN;
+
+ asm volatile("1:lwarx %1,0,%2\n"
+ " cmpwi cr0,%1,0\n"
+ " bne 2f\n"
+ " stwcx. %3,0,%2\n"
+ " bne- 1b\n"
+ " isync\n"
+ "2:"
+ : "=&r" (tmp), "=&r" (old)
+ : "r" (lock), "r" (token)
+ : "cc", "memory");
+ return old == 0;
+}
+
+long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
+ unsigned long pte_index, unsigned long avpn,
+ unsigned long va)
+{
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long *hpte;
+ unsigned long v, r, rb;
+
+ if (pte_index >= (HPT_NPTEG << 3))
+ return H_PARAMETER;
+ hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+ cpu_relax();
+ if ((hpte[0] & HPTE_V_VALID) == 0 ||
+ ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
+ ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
+ hpte[0] &= ~HPTE_V_HVLOCK;
+ return H_NOT_FOUND;
+ }
+ if (atomic_read(&kvm->online_vcpus) == 1)
+ flags |= H_LOCAL;
+ vcpu->arch.gpr[4] = v = hpte[0] & ~HPTE_V_HVLOCK;
+ vcpu->arch.gpr[5] = r = hpte[1];
+ rb = compute_tlbie_rb(v, r, pte_index);
+ hpte[0] = 0;
+ if (!(flags & H_LOCAL)) {
+ while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+ cpu_relax();
+ asm volatile("ptesync" : : : "memory");
+ asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+ : : "r" (rb), "r" (kvm->arch.lpid));
+ asm volatile("ptesync" : : : "memory");
+ kvm->arch.tlbie_lock = 0;
+ } else {
+ asm volatile("ptesync" : : : "memory");
+ asm volatile("tlbiel %0" : : "r" (rb));
+ asm volatile("ptesync" : : : "memory");
+ }
+ return H_SUCCESS;
+}
+
+long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long *args = &vcpu->arch.gpr[4];
+ unsigned long *hp, tlbrb[4];
+ long int i, found;
+ long int n_inval = 0;
+ unsigned long flags, req, pte_index;
+ long int local = 0;
+ long int ret = H_SUCCESS;
+
+ if (atomic_read(&kvm->online_vcpus) == 1)
+ local = 1;
+ for (i = 0; i < 4; ++i) {
+ pte_index = args[i * 2];
+ flags = pte_index >> 56;
+ pte_index &= ((1ul << 56) - 1);
+ req = flags >> 6;
+ flags &= 3;
+ if (req == 3)
+ break;
+ if (req != 1 || flags == 3 ||
+ pte_index >= (HPT_NPTEG << 3)) {
+ /* parameter error */
+ args[i * 2] = ((0xa0 | flags) << 56) + pte_index;
+ ret = H_PARAMETER;
+ break;
+ }
+ hp = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ while (!lock_hpte(hp, HPTE_V_HVLOCK))
+ cpu_relax();
+ found = 0;
+ if (hp[0] & HPTE_V_VALID) {
+ switch (flags & 3) {
+ case 0: /* absolute */
+ found = 1;
+ break;
+ case 1: /* andcond */
+ if (!(hp[0] & args[i * 2 + 1]))
+ found = 1;
+ break;
+ case 2: /* AVPN */
+ if ((hp[0] & ~0x7fUL) == args[i * 2 + 1])
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ hp[0] &= ~HPTE_V_HVLOCK;
+ args[i * 2] = ((0x90 | flags) << 56) + pte_index;
+ continue;
+ }
+ /* insert R and C bits from PTE */
+ flags |= (hp[1] >> 5) & 0x0c;
+ args[i * 2] = ((0x80 | flags) << 56) + pte_index;
+ tlbrb[n_inval++] = compute_tlbie_rb(hp[0], hp[1], pte_index);
+ hp[0] = 0;
+ }
+ if (n_inval == 0)
+ return ret;
+
+ if (!local) {
+ while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+ cpu_relax();
+ asm volatile("ptesync" : : : "memory");
+ for (i = 0; i < n_inval; ++i)
+ asm volatile(PPC_TLBIE(%1,%0)
+ : : "r" (tlbrb[i]), "r" (kvm->arch.lpid));
+ asm volatile("eieio; tlbsync; ptesync" : : : "memory");
+ kvm->arch.tlbie_lock = 0;
+ } else {
+ asm volatile("ptesync" : : : "memory");
+ for (i = 0; i < n_inval; ++i)
+ asm volatile("tlbiel %0" : : "r" (tlbrb[i]));
+ asm volatile("ptesync" : : : "memory");
+ }
+ return ret;
+}
+
+long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
+ unsigned long pte_index, unsigned long avpn,
+ unsigned long va)
+{
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long *hpte;
+ unsigned long v, r, rb;
+
+ if (pte_index >= (HPT_NPTEG << 3))
+ return H_PARAMETER;
+ hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+ cpu_relax();
+ if ((hpte[0] & HPTE_V_VALID) == 0 ||
+ ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
+ hpte[0] &= ~HPTE_V_HVLOCK;
+ return H_NOT_FOUND;
+ }
+ if (atomic_read(&kvm->online_vcpus) == 1)
+ flags |= H_LOCAL;
+ v = hpte[0];
+ r = hpte[1] & ~(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);
+ rb = compute_tlbie_rb(v, r, pte_index);
+ hpte[0] = v & ~HPTE_V_VALID;
+ if (!(flags & H_LOCAL)) {
+ while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+ cpu_relax();
+ asm volatile("ptesync" : : : "memory");
+ asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+ : : "r" (rb), "r" (kvm->arch.lpid));
+ asm volatile("ptesync" : : : "memory");
+ kvm->arch.tlbie_lock = 0;
+ } else {
+ asm volatile("ptesync" : : : "memory");
+ asm volatile("tlbiel %0" : : "r" (rb));
+ asm volatile("ptesync" : : : "memory");
+ }
+ hpte[1] = r;
+ eieio();
+ hpte[0] = v & ~HPTE_V_HVLOCK;
+ asm volatile("ptesync" : : : "memory");
+ return H_SUCCESS;
+}
+
+static unsigned long reverse_xlate(struct kvm *kvm, unsigned long realaddr)
+{
+ long int i;
+ unsigned long offset, rpn;
+
+ offset = realaddr & (kvm->arch.ram_psize - 1);
+ rpn = (realaddr - offset) >> PAGE_SHIFT;
+ for (i = 0; i < kvm->arch.ram_npages; ++i)
+ if (rpn == kvm->arch.ram_pginfo[i].pfn)
+ return (i << PAGE_SHIFT) + offset;
+ return HPTE_R_RPN; /* all 1s in the RPN field */
+}
+
+long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
+ unsigned long pte_index)
+{
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long *hpte, r;
+ int i, n = 1;
+
+ if (pte_index >= (HPT_NPTEG << 3))
+ return H_PARAMETER;
+ if (flags & H_READ_4) {
+ pte_index &= ~3;
+ n = 4;
+ }
+ for (i = 0; i < n; ++i, ++pte_index) {
+ hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ r = hpte[1];
+ if ((flags & H_R_XLATE) && (hpte[0] & HPTE_V_VALID))
+ r = reverse_xlate(kvm, r & HPTE_R_RPN) |
+ (r & ~HPTE_R_RPN);
+ vcpu->arch.gpr[4 + i * 2] = hpte[0];
+ vcpu->arch.gpr[5 + i * 2] = r;
+ }
+ return H_SUCCESS;
+}
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
new file mode 100644
index 000000000000..6dd33581a228
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -0,0 +1,1345 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *
+ * Derived from book3s_rmhandlers.S and other files, which are:
+ *
+ * Copyright SUSE Linux Products GmbH 2009
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+#include <asm/exception-64s.h>
+
+/*****************************************************************************
+ * *
+ * Real Mode handlers that need to be in the linear mapping *
+ * *
+ ****************************************************************************/
+
+ .globl kvmppc_skip_interrupt
+kvmppc_skip_interrupt:
+ mfspr r13,SPRN_SRR0
+ addi r13,r13,4
+ mtspr SPRN_SRR0,r13
+ GET_SCRATCH0(r13)
+ rfid
+ b .
+
+ .globl kvmppc_skip_Hinterrupt
+kvmppc_skip_Hinterrupt:
+ mfspr r13,SPRN_HSRR0
+ addi r13,r13,4
+ mtspr SPRN_HSRR0,r13
+ GET_SCRATCH0(r13)
+ hrfid
+ b .
+
+/*
+ * Call kvmppc_handler_trampoline_enter in real mode.
+ * Must be called with interrupts hard-disabled.
+ *
+ * Input Registers:
+ *
+ * LR = return address to continue at after eventually re-enabling MMU
+ */
+_GLOBAL(kvmppc_hv_entry_trampoline)
+ mfmsr r10
+ LOAD_REG_ADDR(r5, kvmppc_hv_entry)
+ li r0,MSR_RI
+ andc r0,r10,r0
+ li r6,MSR_IR | MSR_DR
+ andc r6,r10,r6
+ mtmsrd r0,1 /* clear RI in MSR */
+ mtsrr0 r5
+ mtsrr1 r6
+ RFI
+
+#define ULONG_SIZE 8
+#define VCPU_GPR(n) (VCPU_GPRS + (n * ULONG_SIZE))
+
+/******************************************************************************
+ * *
+ * Entry code *
+ * *
+ *****************************************************************************/
+
+#define XICS_XIRR 4
+#define XICS_QIRR 0xc
+
+/*
+ * We come in here when wakened from nap mode on a secondary hw thread.
+ * Relocation is off and most register values are lost.
+ * r13 points to the PACA.
+ */
+ .globl kvm_start_guest
+kvm_start_guest:
+ ld r1,PACAEMERGSP(r13)
+ subi r1,r1,STACK_FRAME_OVERHEAD
+
+ /* get vcpu pointer */
+ ld r4, HSTATE_KVM_VCPU(r13)
+
+ /* We got here with an IPI; clear it */
+ 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 */
+
+.global kvmppc_hv_entry
+kvmppc_hv_entry:
+
+ /* Required state:
+ *
+ * R4 = vcpu pointer
+ * MSR = ~IR|DR
+ * R13 = PACA
+ * R1 = host R1
+ * all other volatile GPRS = free
+ */
+ mflr r0
+ std r0, HSTATE_VMHANDLER(r13)
+
+ 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)
+
+ /* Load guest PMU registers */
+ /* R4 is live here (vcpu pointer) */
+ li r3, 1
+ sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */
+ mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */
+ isync
+ lwz r3, VCPU_PMC(r4) /* always load up guest PMU registers */
+ lwz r5, VCPU_PMC + 4(r4) /* to prevent information leak */
+ lwz r6, VCPU_PMC + 8(r4)
+ lwz r7, VCPU_PMC + 12(r4)
+ lwz r8, VCPU_PMC + 16(r4)
+ lwz r9, VCPU_PMC + 20(r4)
+BEGIN_FTR_SECTION
+ lwz r10, VCPU_PMC + 24(r4)
+ lwz r11, VCPU_PMC + 28(r4)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ mtspr SPRN_PMC1, r3
+ mtspr SPRN_PMC2, r5
+ mtspr SPRN_PMC3, r6
+ mtspr SPRN_PMC4, r7
+ mtspr SPRN_PMC5, r8
+ mtspr SPRN_PMC6, r9
+BEGIN_FTR_SECTION
+ mtspr SPRN_PMC7, r10
+ mtspr SPRN_PMC8, r11
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ ld r3, VCPU_MMCR(r4)
+ ld r5, VCPU_MMCR + 8(r4)
+ ld r6, VCPU_MMCR + 16(r4)
+ mtspr SPRN_MMCR1, r5
+ mtspr SPRN_MMCRA, r6
+ mtspr SPRN_MMCR0, r3
+ isync
+
+ /* Load up FP, VMX and VSX registers */
+ bl kvmppc_load_fp
+
+BEGIN_FTR_SECTION
+ /* Switch DSCR to guest value */
+ ld r5, VCPU_DSCR(r4)
+ mtspr SPRN_DSCR, r5
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+ /*
+ * Set the decrementer to the guest decrementer.
+ */
+ ld r8,VCPU_DEC_EXPIRES(r4)
+ mftb r7
+ subf r3,r7,r8
+ mtspr SPRN_DEC,r3
+ stw r3,VCPU_DEC(r4)
+
+ ld r5, VCPU_SPRG0(r4)
+ ld r6, VCPU_SPRG1(r4)
+ ld r7, VCPU_SPRG2(r4)
+ ld r8, VCPU_SPRG3(r4)
+ mtspr SPRN_SPRG0, r5
+ mtspr SPRN_SPRG1, r6
+ mtspr SPRN_SPRG2, r7
+ mtspr SPRN_SPRG3, r8
+
+ /* Save R1 in the PACA */
+ std r1, HSTATE_HOST_R1(r13)
+
+ /* Increment yield count if they have a VPA */
+ ld r3, VCPU_VPA(r4)
+ cmpdi r3, 0
+ beq 25f
+ lwz r5, LPPACA_YIELDCOUNT(r3)
+ addi r5, r5, 1
+ stw r5, LPPACA_YIELDCOUNT(r3)
+25:
+ /* Load up DAR and DSISR */
+ ld r5, VCPU_DAR(r4)
+ lwz r6, VCPU_DSISR(r4)
+ mtspr SPRN_DAR, r5
+ mtspr SPRN_DSISR, r6
+
+ /* Set partition DABR */
+ li r5,3
+ ld r6,VCPU_DABR(r4)
+ mtspr SPRN_DABRX,r5
+ mtspr SPRN_DABR,r6
+
+BEGIN_FTR_SECTION
+ /* Restore AMR and UAMOR, set AMOR to all 1s */
+ ld r5,VCPU_AMR(r4)
+ ld r6,VCPU_UAMOR(r4)
+ li r7,-1
+ mtspr SPRN_AMR,r5
+ mtspr SPRN_UAMOR,r6
+ mtspr SPRN_AMOR,r7
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+ /* Clear out SLB */
+ li r6,0
+ slbmte r6,r6
+ slbia
+ ptesync
+
+BEGIN_FTR_SECTION
+ b 30f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ /*
+ * POWER7 host -> guest partition switch code.
+ * We don't have to lock against concurrent tlbies,
+ * but we do have to coordinate across hardware threads.
+ */
+ /* Increment entry count iff exit count is zero. */
+ ld r5,HSTATE_KVM_VCORE(r13)
+ addi r9,r5,VCORE_ENTRY_EXIT
+21: lwarx r3,0,r9
+ cmpwi r3,0x100 /* any threads starting to exit? */
+ bge secondary_too_late /* if so we're too late to the party */
+ addi r3,r3,1
+ stwcx. r3,0,r9
+ bne 21b
+
+ /* Primary thread switches to guest partition. */
+ ld r9,VCPU_KVM(r4) /* pointer to struct kvm */
+ lwz r6,VCPU_PTID(r4)
+ cmpwi r6,0
+ bne 20f
+ ld r6,KVM_SDR1(r9)
+ lwz r7,KVM_LPID(r9)
+ li r0,LPID_RSVD /* switch to reserved LPID */
+ mtspr SPRN_LPID,r0
+ ptesync
+ mtspr SPRN_SDR1,r6 /* switch to partition page table */
+ mtspr SPRN_LPID,r7
+ isync
+ li r0,1
+ stb r0,VCORE_IN_GUEST(r5) /* signal secondaries to continue */
+ b 10f
+
+ /* Secondary threads wait for primary to have done partition switch */
+20: lbz r0,VCORE_IN_GUEST(r5)
+ cmpwi r0,0
+ beq 20b
+
+ /* Set LPCR. Set the MER bit if there is a pending external irq. */
+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
+ ld r8,KVM_RMOR(r9)
+ mtspr SPRN_RMOR,r8
+ isync
+
+ /* Check if HDEC expires soon */
+ mfspr r3,SPRN_HDEC
+ cmpwi r3,10
+ li r12,BOOK3S_INTERRUPT_HV_DECREMENTER
+ mr r9,r4
+ blt hdec_soon
+
+ /*
+ * Invalidate the TLB if we could possibly have stale TLB
+ * entries for this partition on this core due to the use
+ * of tlbiel.
+ * XXX maybe only need this on primary thread?
+ */
+ ld r9,VCPU_KVM(r4) /* pointer to struct kvm */
+ lwz r5,VCPU_VCPUID(r4)
+ lhz r6,PACAPACAINDEX(r13)
+ rldimi r6,r5,0,62 /* XXX map as if threads 1:1 p:v */
+ lhz r8,VCPU_LAST_CPU(r4)
+ sldi r7,r6,1 /* see if this is the same vcpu */
+ add r7,r7,r9 /* as last ran on this pcpu */
+ lhz r0,KVM_LAST_VCPU(r7)
+ cmpw r6,r8 /* on the same cpu core as last time? */
+ bne 3f
+ cmpw r0,r5 /* same vcpu as this core last ran? */
+ beq 1f
+3: sth r6,VCPU_LAST_CPU(r4) /* if not, invalidate partition TLB */
+ sth r5,KVM_LAST_VCPU(r7)
+ li r6,128
+ mtctr r6
+ li r7,0x800 /* IS field = 0b10 */
+ ptesync
+2: tlbiel r7
+ addi r7,r7,0x1000
+ bdnz 2b
+ ptesync
+1:
+
+ /* Save purr/spurr */
+ mfspr r5,SPRN_PURR
+ mfspr r6,SPRN_SPURR
+ std r5,HSTATE_PURR(r13)
+ std r6,HSTATE_SPURR(r13)
+ ld r7,VCPU_PURR(r4)
+ ld r8,VCPU_SPURR(r4)
+ mtspr SPRN_PURR,r7
+ mtspr SPRN_SPURR,r8
+ b 31f
+
+ /*
+ * PPC970 host -> guest partition switch code.
+ * We have to lock against concurrent tlbies,
+ * using native_tlbie_lock to lock against host tlbies
+ * and kvm->arch.tlbie_lock to lock against guest tlbies.
+ * We also have to invalidate the TLB since its
+ * entries aren't tagged with the LPID.
+ */
+30: ld r9,VCPU_KVM(r4) /* pointer to struct kvm */
+
+ /* first take native_tlbie_lock */
+ .section ".toc","aw"
+toc_tlbie_lock:
+ .tc native_tlbie_lock[TC],native_tlbie_lock
+ .previous
+ ld r3,toc_tlbie_lock@toc(2)
+ lwz r8,PACA_LOCK_TOKEN(r13)
+24: lwarx r0,0,r3
+ cmpwi r0,0
+ bne 24b
+ stwcx. r8,0,r3
+ bne 24b
+ isync
+
+ ld r7,KVM_LPCR(r9) /* use kvm->arch.lpcr to store HID4 */
+ li r0,0x18f
+ rotldi r0,r0,HID4_LPID5_SH /* all lpid bits in HID4 = 1 */
+ or r0,r7,r0
+ ptesync
+ sync
+ mtspr SPRN_HID4,r0 /* switch to reserved LPID */
+ isync
+ li r0,0
+ stw r0,0(r3) /* drop native_tlbie_lock */
+
+ /* invalidate the whole TLB */
+ li r0,256
+ mtctr r0
+ li r6,0
+25: tlbiel r6
+ addi r6,r6,0x1000
+ bdnz 25b
+ ptesync
+
+ /* Take the guest's tlbie_lock */
+ addi r3,r9,KVM_TLBIE_LOCK
+24: lwarx r0,0,r3
+ cmpwi r0,0
+ bne 24b
+ stwcx. r8,0,r3
+ bne 24b
+ isync
+ ld r6,KVM_SDR1(r9)
+ mtspr SPRN_SDR1,r6 /* switch to partition page table */
+
+ /* Set up HID4 with the guest's LPID etc. */
+ sync
+ mtspr SPRN_HID4,r7
+ isync
+
+ /* drop the guest's tlbie_lock */
+ li r0,0
+ stw r0,0(r3)
+
+ /* Check if HDEC expires soon */
+ mfspr r3,SPRN_HDEC
+ cmpwi r3,10
+ li r12,BOOK3S_INTERRUPT_HV_DECREMENTER
+ mr r9,r4
+ blt hdec_soon
+
+ /* Enable HDEC interrupts */
+ mfspr r0,SPRN_HID0
+ li r3,1
+ rldimi r0,r3, HID0_HDICE_SH, 64-HID0_HDICE_SH-1
+ sync
+ mtspr SPRN_HID0,r0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+
+ /* Load up guest SLB entries */
+31: lwz r5,VCPU_SLB_MAX(r4)
+ cmpwi r5,0
+ beq 9f
+ mtctr r5
+ addi r6,r4,VCPU_SLB
+1: ld r8,VCPU_SLB_E(r6)
+ ld r9,VCPU_SLB_V(r6)
+ slbmte r9,r8
+ addi r6,r6,VCPU_SLB_SIZE
+ bdnz 1b
+9:
+
+ /* Restore state of CTRL run bit; assume 1 on entry */
+ lwz r5,VCPU_CTRL(r4)
+ andi. r5,r5,1
+ bne 4f
+ mfspr r6,SPRN_CTRLF
+ clrrdi r6,r6,1
+ mtspr SPRN_CTRLT,r6
+4:
+ ld r6, VCPU_CTR(r4)
+ lwz r7, VCPU_XER(r4)
+
+ mtctr r6
+ mtxer r7
+
+ /* Move SRR0 and SRR1 into the respective regs */
+ 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) /* 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
+
+fast_guest_return:
+ mtspr SPRN_HSRR0,r10
+ mtspr SPRN_HSRR1,r11
+
+ /* Activate guest mode, so faults get handled by KVM */
+ li r9, KVM_GUEST_MODE_GUEST
+ stb r9, HSTATE_IN_GUEST(r13)
+
+ /* Enter guest */
+
+ ld r5, VCPU_LR(r4)
+ lwz r6, VCPU_CR(r4)
+ mtlr r5
+ mtcr r6
+
+ ld r0, VCPU_GPR(r0)(r4)
+ ld r1, VCPU_GPR(r1)(r4)
+ ld r2, VCPU_GPR(r2)(r4)
+ ld r3, VCPU_GPR(r3)(r4)
+ ld r5, VCPU_GPR(r5)(r4)
+ ld r6, VCPU_GPR(r6)(r4)
+ ld r7, VCPU_GPR(r7)(r4)
+ ld r8, VCPU_GPR(r8)(r4)
+ ld r9, VCPU_GPR(r9)(r4)
+ ld r10, VCPU_GPR(r10)(r4)
+ ld r11, VCPU_GPR(r11)(r4)
+ ld r12, VCPU_GPR(r12)(r4)
+ ld r13, VCPU_GPR(r13)(r4)
+
+ ld r4, VCPU_GPR(r4)(r4)
+
+ hrfid
+ b .
+
+/******************************************************************************
+ * *
+ * Exit code *
+ * *
+ *****************************************************************************/
+
+/*
+ * We come here from the first-level interrupt handlers.
+ */
+ .globl kvmppc_interrupt
+kvmppc_interrupt:
+ /*
+ * Register contents:
+ * R12 = interrupt vector
+ * R13 = PACA
+ * guest CR, R12 saved in shadow VCPU SCRATCH1/0
+ * guest R13 saved in SPRN_SCRATCH0
+ */
+ /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */
+ std r9, HSTATE_HOST_R2(r13)
+ ld r9, HSTATE_KVM_VCPU(r13)
+
+ /* Save registers */
+
+ std r0, VCPU_GPR(r0)(r9)
+ std r1, VCPU_GPR(r1)(r9)
+ std r2, VCPU_GPR(r2)(r9)
+ std r3, VCPU_GPR(r3)(r9)
+ std r4, VCPU_GPR(r4)(r9)
+ std r5, VCPU_GPR(r5)(r9)
+ std r6, VCPU_GPR(r6)(r9)
+ std r7, VCPU_GPR(r7)(r9)
+ std r8, VCPU_GPR(r8)(r9)
+ ld r0, HSTATE_HOST_R2(r13)
+ std r0, VCPU_GPR(r9)(r9)
+ std r10, VCPU_GPR(r10)(r9)
+ std r11, VCPU_GPR(r11)(r9)
+ ld r3, HSTATE_SCRATCH0(r13)
+ lwz r4, HSTATE_SCRATCH1(r13)
+ std r3, VCPU_GPR(r12)(r9)
+ stw r4, VCPU_CR(r9)
+
+ /* Restore R1/R2 so we can handle faults */
+ ld r1, HSTATE_HOST_R1(r13)
+ ld r2, PACATOC(r13)
+
+ mfspr r10, SPRN_SRR0
+ mfspr r11, SPRN_SRR1
+ std r10, VCPU_SRR0(r9)
+ std r11, VCPU_SRR1(r9)
+ andi. r0, r12, 2 /* need to read HSRR0/1? */
+ beq 1f
+ mfspr r10, SPRN_HSRR0
+ mfspr r11, SPRN_HSRR1
+ clrrdi r12, r12, 2
+1: std r10, VCPU_PC(r9)
+ std r11, VCPU_MSR(r9)
+
+ GET_SCRATCH0(r3)
+ mflr r4
+ std r3, VCPU_GPR(r13)(r9)
+ std r4, VCPU_LR(r9)
+
+ /* Unset guest mode */
+ li r0, KVM_GUEST_MODE_NONE
+ stb r0, HSTATE_IN_GUEST(r13)
+
+ stw r12,VCPU_TRAP(r9)
+
+ /* See if this is a leftover HDEC interrupt */
+ cmpwi r12,BOOK3S_INTERRUPT_HV_DECREMENTER
+ bne 2f
+ mfspr r3,SPRN_HDEC
+ cmpwi r3,0
+ bge ignore_hdec
+2:
+ /* 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
+ andi. r0,r5,LPCR_MER
+ bne bounce_ext_interrupt
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+ /* Save DEC */
+ mfspr r5,SPRN_DEC
+ mftb r6
+ extsw r5,r5
+ add r5,r5,r6
+ std r5,VCPU_DEC_EXPIRES(r9)
+
+ /* Save HEIR (HV emulation assist reg) in last_inst
+ if this is an HEI (HV emulation interrupt, e40) */
+ li r3,-1
+BEGIN_FTR_SECTION
+ cmpwi r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
+ bne 11f
+ mfspr r3,SPRN_HEIR
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+11: stw r3,VCPU_LAST_INST(r9)
+
+ /* Save more register state */
+ mfxer r5
+ mfdar r6
+ mfdsisr r7
+ mfctr r8
+
+ stw r5, VCPU_XER(r9)
+ std r6, VCPU_DAR(r9)
+ stw r7, VCPU_DSISR(r9)
+ std r8, VCPU_CTR(r9)
+ /* grab HDAR & HDSISR if HV data storage interrupt (HDSI) */
+BEGIN_FTR_SECTION
+ cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE
+ beq 6f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+7: std r6, VCPU_FAULT_DAR(r9)
+ stw r7, VCPU_FAULT_DSISR(r9)
+
+ /* Save guest CTRL register, set runlatch to 1 */
+ mfspr r6,SPRN_CTRLF
+ stw r6,VCPU_CTRL(r9)
+ andi. r0,r6,1
+ bne 4f
+ ori r6,r6,1
+ mtspr SPRN_CTRLT,r6
+4:
+ /* Read the guest SLB and save it away */
+ lwz r0,VCPU_SLB_NR(r9) /* number of entries in SLB */
+ mtctr r0
+ li r6,0
+ addi r7,r9,VCPU_SLB
+ li r5,0
+1: slbmfee r8,r6
+ andis. r0,r8,SLB_ESID_V@h
+ beq 2f
+ add r8,r8,r6 /* put index in */
+ slbmfev r3,r6
+ std r8,VCPU_SLB_E(r7)
+ std r3,VCPU_SLB_V(r7)
+ addi r7,r7,VCPU_SLB_SIZE
+ addi r5,r5,1
+2: addi r6,r6,1
+ bdnz 1b
+ stw r5,VCPU_SLB_MAX(r9)
+
+ /*
+ * Save the guest PURR/SPURR
+ */
+BEGIN_FTR_SECTION
+ mfspr r5,SPRN_PURR
+ mfspr r6,SPRN_SPURR
+ ld r7,VCPU_PURR(r9)
+ ld r8,VCPU_SPURR(r9)
+ std r5,VCPU_PURR(r9)
+ std r6,VCPU_SPURR(r9)
+ subf r5,r7,r5
+ subf r6,r8,r6
+
+ /*
+ * Restore host PURR/SPURR and add guest times
+ * so that the time in the guest gets accounted.
+ */
+ ld r3,HSTATE_PURR(r13)
+ ld r4,HSTATE_SPURR(r13)
+ add r3,r3,r5
+ add r4,r4,r6
+ mtspr SPRN_PURR,r3
+ mtspr SPRN_SPURR,r4
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_201)
+
+ /* Clear out SLB */
+ li r5,0
+ slbmte r5,r5
+ slbia
+ ptesync
+
+hdec_soon:
+BEGIN_FTR_SECTION
+ b 32f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ /*
+ * POWER7 guest -> host partition switch code.
+ * We don't have to lock against tlbies but we do
+ * have to coordinate the hardware threads.
+ */
+ /* Increment the threads-exiting-guest count in the 0xff00
+ bits of vcore->entry_exit_count */
+ lwsync
+ ld r5,HSTATE_KVM_VCORE(r13)
+ addi r6,r5,VCORE_ENTRY_EXIT
+41: lwarx r3,0,r6
+ addi r0,r3,0x100
+ stwcx. r0,0,r6
+ bne 41b
+
+ /*
+ * At this point we have an interrupt that we have to pass
+ * up to the kernel or qemu; we can't handle it in real mode.
+ * Thus we have to do a partition switch, so we have to
+ * collect the other threads, if we are the first thread
+ * to take an interrupt. To do this, we set the HDEC to 0,
+ * which causes an HDEC interrupt in all threads within 2ns
+ * because the HDEC register is shared between all 4 threads.
+ * However, we don't need to bother if this is an HDEC
+ * interrupt, since the other threads will already be on their
+ * way here in that case.
+ */
+ 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:
+
+ /* Secondary threads wait for primary to do partition switch */
+ ld r4,VCPU_KVM(r9) /* pointer to struct kvm */
+ ld r5,HSTATE_KVM_VCORE(r13)
+ lwz r3,VCPU_PTID(r9)
+ cmpwi r3,0
+ beq 15f
+ HMT_LOW
+13: lbz r3,VCORE_IN_GUEST(r5)
+ cmpwi r3,0
+ bne 13b
+ HMT_MEDIUM
+ b 16f
+
+ /* Primary thread waits for all the secondaries to exit guest */
+15: lwz r3,VCORE_ENTRY_EXIT(r5)
+ srwi r0,r3,8
+ clrldi r3,r3,56
+ cmpw r3,r0
+ bne 15b
+ isync
+
+ /* Primary thread switches back to host partition */
+ ld r6,KVM_HOST_SDR1(r4)
+ lwz r7,KVM_HOST_LPID(r4)
+ li r8,LPID_RSVD /* switch to reserved LPID */
+ mtspr SPRN_LPID,r8
+ ptesync
+ mtspr SPRN_SDR1,r6 /* switch to partition page table */
+ mtspr SPRN_LPID,r7
+ isync
+ li r0,0
+ stb r0,VCORE_IN_GUEST(r5)
+ lis r8,0x7fff /* MAX_INT@h */
+ mtspr SPRN_HDEC,r8
+
+16: ld r8,KVM_HOST_LPCR(r4)
+ mtspr SPRN_LPCR,r8
+ isync
+ b 33f
+
+ /*
+ * PPC970 guest -> host partition switch code.
+ * We have to lock against concurrent tlbies, and
+ * we have to flush the whole TLB.
+ */
+32: ld r4,VCPU_KVM(r9) /* pointer to struct kvm */
+
+ /* Take the guest's tlbie_lock */
+ lwz r8,PACA_LOCK_TOKEN(r13)
+ addi r3,r4,KVM_TLBIE_LOCK
+24: lwarx r0,0,r3
+ cmpwi r0,0
+ bne 24b
+ stwcx. r8,0,r3
+ bne 24b
+ isync
+
+ ld r7,KVM_HOST_LPCR(r4) /* use kvm->arch.host_lpcr for HID4 */
+ li r0,0x18f
+ rotldi r0,r0,HID4_LPID5_SH /* all lpid bits in HID4 = 1 */
+ or r0,r7,r0
+ ptesync
+ sync
+ mtspr SPRN_HID4,r0 /* switch to reserved LPID */
+ isync
+ li r0,0
+ stw r0,0(r3) /* drop guest tlbie_lock */
+
+ /* invalidate the whole TLB */
+ li r0,256
+ mtctr r0
+ li r6,0
+25: tlbiel r6
+ addi r6,r6,0x1000
+ bdnz 25b
+ ptesync
+
+ /* take native_tlbie_lock */
+ ld r3,toc_tlbie_lock@toc(2)
+24: lwarx r0,0,r3
+ cmpwi r0,0
+ bne 24b
+ stwcx. r8,0,r3
+ bne 24b
+ isync
+
+ ld r6,KVM_HOST_SDR1(r4)
+ mtspr SPRN_SDR1,r6 /* switch to host page table */
+
+ /* Set up host HID4 value */
+ sync
+ mtspr SPRN_HID4,r7
+ isync
+ li r0,0
+ stw r0,0(r3) /* drop native_tlbie_lock */
+
+ lis r8,0x7fff /* MAX_INT@h */
+ mtspr SPRN_HDEC,r8
+
+ /* Disable HDEC interrupts */
+ mfspr r0,SPRN_HID0
+ li r3,0
+ rldimi r0,r3, HID0_HDICE_SH, 64-HID0_HDICE_SH-1
+ sync
+ mtspr SPRN_HID0,r0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+
+ /* load host SLB entries */
+33: ld r8,PACA_SLBSHADOWPTR(r13)
+
+ .rept SLB_NUM_BOLTED
+ ld r5,SLBSHADOW_SAVEAREA(r8)
+ ld r6,SLBSHADOW_SAVEAREA+8(r8)
+ andis. r7,r5,SLB_ESID_V@h
+ beq 1f
+ slbmte r6,r5
+1: addi r8,r8,16
+ .endr
+
+ /* Save and reset AMR and UAMOR before turning on the MMU */
+BEGIN_FTR_SECTION
+ mfspr r5,SPRN_AMR
+ mfspr r6,SPRN_UAMOR
+ std r5,VCPU_AMR(r9)
+ std r6,VCPU_UAMOR(r9)
+ li r6,0
+ mtspr SPRN_AMR,r6
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+ /* Restore host DABR and DABRX */
+ ld r5,HSTATE_DABR(r13)
+ li r6,7
+ mtspr SPRN_DABR,r5
+ mtspr SPRN_DABRX,r6
+
+ /* Switch DSCR back to host value */
+BEGIN_FTR_SECTION
+ mfspr r8, SPRN_DSCR
+ ld r7, HSTATE_DSCR(r13)
+ std r8, VCPU_DSCR(r7)
+ mtspr SPRN_DSCR, r7
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+ /* Save non-volatile GPRs */
+ std r14, VCPU_GPR(r14)(r9)
+ std r15, VCPU_GPR(r15)(r9)
+ std r16, VCPU_GPR(r16)(r9)
+ std r17, VCPU_GPR(r17)(r9)
+ std r18, VCPU_GPR(r18)(r9)
+ std r19, VCPU_GPR(r19)(r9)
+ std r20, VCPU_GPR(r20)(r9)
+ std r21, VCPU_GPR(r21)(r9)
+ std r22, VCPU_GPR(r22)(r9)
+ std r23, VCPU_GPR(r23)(r9)
+ std r24, VCPU_GPR(r24)(r9)
+ std r25, VCPU_GPR(r25)(r9)
+ std r26, VCPU_GPR(r26)(r9)
+ std r27, VCPU_GPR(r27)(r9)
+ std r28, VCPU_GPR(r28)(r9)
+ std r29, VCPU_GPR(r29)(r9)
+ std r30, VCPU_GPR(r30)(r9)
+ std r31, VCPU_GPR(r31)(r9)
+
+ /* Save SPRGs */
+ mfspr r3, SPRN_SPRG0
+ mfspr r4, SPRN_SPRG1
+ mfspr r5, SPRN_SPRG2
+ mfspr r6, SPRN_SPRG3
+ std r3, VCPU_SPRG0(r9)
+ std r4, VCPU_SPRG1(r9)
+ std r5, VCPU_SPRG2(r9)
+ std r6, VCPU_SPRG3(r9)
+
+ /* Increment yield count if they have a VPA */
+ ld r8, VCPU_VPA(r9) /* do they have a VPA? */
+ cmpdi r8, 0
+ beq 25f
+ lwz r3, LPPACA_YIELDCOUNT(r8)
+ addi r3, r3, 1
+ stw r3, LPPACA_YIELDCOUNT(r8)
+25:
+ /* Save PMU registers if requested */
+ /* r8 and cr0.eq are live here */
+ li r3, 1
+ sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */
+ mfspr r4, SPRN_MMCR0 /* save MMCR0 */
+ mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */
+ isync
+ beq 21f /* if no VPA, save PMU stuff anyway */
+ lbz r7, LPPACA_PMCINUSE(r8)
+ cmpwi r7, 0 /* did they ask for PMU stuff to be saved? */
+ bne 21f
+ std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */
+ b 22f
+21: mfspr r5, SPRN_MMCR1
+ mfspr r6, SPRN_MMCRA
+ std r4, VCPU_MMCR(r9)
+ std r5, VCPU_MMCR + 8(r9)
+ std r6, VCPU_MMCR + 16(r9)
+ mfspr r3, SPRN_PMC1
+ mfspr r4, SPRN_PMC2
+ mfspr r5, SPRN_PMC3
+ mfspr r6, SPRN_PMC4
+ mfspr r7, SPRN_PMC5
+ mfspr r8, SPRN_PMC6
+BEGIN_FTR_SECTION
+ mfspr r10, SPRN_PMC7
+ mfspr r11, SPRN_PMC8
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ stw r3, VCPU_PMC(r9)
+ stw r4, VCPU_PMC + 4(r9)
+ stw r5, VCPU_PMC + 8(r9)
+ stw r6, VCPU_PMC + 12(r9)
+ stw r7, VCPU_PMC + 16(r9)
+ stw r8, VCPU_PMC + 20(r9)
+BEGIN_FTR_SECTION
+ stw r10, VCPU_PMC + 24(r9)
+ stw r11, VCPU_PMC + 28(r9)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+22:
+ /* save FP state */
+ mr r3, r9
+ bl .kvmppc_save_fp
+
+ /* Secondary threads go off to take a nap on POWER7 */
+BEGIN_FTR_SECTION
+ lwz r0,VCPU_PTID(r3)
+ cmpwi r0,0
+ bne secondary_nap
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+ /*
+ * Reload DEC. HDEC interrupts were disabled when
+ * we reloaded the host's LPCR value.
+ */
+ ld r3, HSTATE_DECEXP(r13)
+ mftb r4
+ subf r4, r4, r3
+ mtspr SPRN_DEC, r4
+
+ /* Reload the host's PMU registers */
+ ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */
+ lbz r4, LPPACA_PMCINUSE(r3)
+ cmpwi r4, 0
+ beq 23f /* skip if not */
+ lwz r3, HSTATE_PMC(r13)
+ lwz r4, HSTATE_PMC + 4(r13)
+ lwz r5, HSTATE_PMC + 8(r13)
+ lwz r6, HSTATE_PMC + 12(r13)
+ lwz r8, HSTATE_PMC + 16(r13)
+ lwz r9, HSTATE_PMC + 20(r13)
+BEGIN_FTR_SECTION
+ lwz r10, HSTATE_PMC + 24(r13)
+ lwz r11, HSTATE_PMC + 28(r13)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ mtspr SPRN_PMC1, r3
+ mtspr SPRN_PMC2, r4
+ mtspr SPRN_PMC3, r5
+ mtspr SPRN_PMC4, r6
+ mtspr SPRN_PMC5, r8
+ mtspr SPRN_PMC6, r9
+BEGIN_FTR_SECTION
+ mtspr SPRN_PMC7, r10
+ mtspr SPRN_PMC8, r11
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ ld r3, HSTATE_MMCR(r13)
+ ld r4, HSTATE_MMCR + 8(r13)
+ ld r5, HSTATE_MMCR + 16(r13)
+ mtspr SPRN_MMCR1, r4
+ mtspr SPRN_MMCRA, r5
+ mtspr SPRN_MMCR0, r3
+ isync
+23:
+ /*
+ * For external and machine check interrupts, we need
+ * to call the Linux handler to process the interrupt.
+ * We do that by jumping to the interrupt vector address
+ * which we have in r12. The [h]rfid at the end of the
+ * handler will return to the book3s_hv_interrupts.S code.
+ * For other interrupts we do the rfid to get back
+ * to the book3s_interrupts.S code here.
+ */
+ ld r8, HSTATE_VMHANDLER(r13)
+ ld r7, HSTATE_HOST_MSR(r13)
+
+ cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL
+ beq 11f
+ cmpwi r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+
+ /* RFI into the highmem handler, or branch to interrupt handler */
+12: mfmsr r6
+ mtctr r12
+ li r0, MSR_RI
+ andc r6, r6, r0
+ mtmsrd r6, 1 /* Clear RI in MSR */
+ mtsrr0 r8
+ mtsrr1 r7
+ beqctr
+ RFI
+
+11:
+BEGIN_FTR_SECTION
+ b 12b
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+ mtspr SPRN_HSRR0, r8
+ mtspr SPRN_HSRR1, r7
+ ba 0x500
+
+6: mfspr r6,SPRN_HDAR
+ mfspr r7,SPRN_HDSISR
+ b 7b
+
+/*
+ * Try to handle an hcall in real mode.
+ * Returns to the guest if we handle it, or continues on up to
+ * the kernel if we can't (i.e. if we don't have a handler for
+ * it, or if the handler returns H_TOO_HARD).
+ */
+ .globl hcall_try_real_mode
+hcall_try_real_mode:
+ ld r3,VCPU_GPR(r3)(r9)
+ andi. r0,r11,MSR_PR
+ bne hcall_real_cont
+ clrrdi r3,r3,2
+ cmpldi r3,hcall_real_table_end - hcall_real_table
+ bge hcall_real_cont
+ LOAD_REG_ADDR(r4, hcall_real_table)
+ lwzx r3,r3,r4
+ cmpwi r3,0
+ beq hcall_real_cont
+ add r3,r3,r4
+ mtctr r3
+ mr r3,r9 /* get vcpu pointer */
+ ld r4,VCPU_GPR(r4)(r9)
+ bctrl
+ cmpdi r3,H_TOO_HARD
+ beq hcall_real_fallback
+ ld r4,HSTATE_KVM_VCPU(r13)
+ std r3,VCPU_GPR(r3)(r4)
+ ld r10,VCPU_PC(r4)
+ ld r11,VCPU_MSR(r4)
+ b fast_guest_return
+
+ /* We've attempted a real mode hcall, but it's punted it back
+ * to userspace. We need to restore some clobbered volatiles
+ * before resuming the pass-it-to-qemu path */
+hcall_real_fallback:
+ li r12,BOOK3S_INTERRUPT_SYSCALL
+ ld r9, HSTATE_KVM_VCPU(r13)
+ ld r11, VCPU_MSR(r9)
+
+ b hcall_real_cont
+
+ .globl hcall_real_table
+hcall_real_table:
+ .long 0 /* 0 - unused */
+ .long .kvmppc_h_remove - hcall_real_table
+ .long .kvmppc_h_enter - hcall_real_table
+ .long .kvmppc_h_read - hcall_real_table
+ .long 0 /* 0x10 - H_CLEAR_MOD */
+ .long 0 /* 0x14 - H_CLEAR_REF */
+ .long .kvmppc_h_protect - hcall_real_table
+ .long 0 /* 0x1c - H_GET_TCE */
+ .long .kvmppc_h_put_tce - hcall_real_table
+ .long 0 /* 0x24 - H_SET_SPRG0 */
+ .long .kvmppc_h_set_dabr - hcall_real_table
+ .long 0 /* 0x2c */
+ .long 0 /* 0x30 */
+ .long 0 /* 0x34 */
+ .long 0 /* 0x38 */
+ .long 0 /* 0x3c */
+ .long 0 /* 0x40 */
+ .long 0 /* 0x44 */
+ .long 0 /* 0x48 */
+ .long 0 /* 0x4c */
+ .long 0 /* 0x50 */
+ .long 0 /* 0x54 */
+ .long 0 /* 0x58 */
+ .long 0 /* 0x5c */
+ .long 0 /* 0x60 */
+ .long 0 /* 0x64 */
+ .long 0 /* 0x68 */
+ .long 0 /* 0x6c */
+ .long 0 /* 0x70 */
+ .long 0 /* 0x74 */
+ .long 0 /* 0x78 */
+ .long 0 /* 0x7c */
+ .long 0 /* 0x80 */
+ .long 0 /* 0x84 */
+ .long 0 /* 0x88 */
+ .long 0 /* 0x8c */
+ .long 0 /* 0x90 */
+ .long 0 /* 0x94 */
+ .long 0 /* 0x98 */
+ .long 0 /* 0x9c */
+ .long 0 /* 0xa0 */
+ .long 0 /* 0xa4 */
+ .long 0 /* 0xa8 */
+ .long 0 /* 0xac */
+ .long 0 /* 0xb0 */
+ .long 0 /* 0xb4 */
+ .long 0 /* 0xb8 */
+ .long 0 /* 0xbc */
+ .long 0 /* 0xc0 */
+ .long 0 /* 0xc4 */
+ .long 0 /* 0xc8 */
+ .long 0 /* 0xcc */
+ .long 0 /* 0xd0 */
+ .long 0 /* 0xd4 */
+ .long 0 /* 0xd8 */
+ .long 0 /* 0xdc */
+ .long 0 /* 0xe0 */
+ .long 0 /* 0xe4 */
+ .long 0 /* 0xe8 */
+ .long 0 /* 0xec */
+ .long 0 /* 0xf0 */
+ .long 0 /* 0xf4 */
+ .long 0 /* 0xf8 */
+ .long 0 /* 0xfc */
+ .long 0 /* 0x100 */
+ .long 0 /* 0x104 */
+ .long 0 /* 0x108 */
+ .long 0 /* 0x10c */
+ .long 0 /* 0x110 */
+ .long 0 /* 0x114 */
+ .long 0 /* 0x118 */
+ .long 0 /* 0x11c */
+ .long 0 /* 0x120 */
+ .long .kvmppc_h_bulk_remove - hcall_real_table
+hcall_real_table_end:
+
+ignore_hdec:
+ mr r4,r9
+ b fast_guest_return
+
+bounce_ext_interrupt:
+ mr r4,r9
+ mtspr SPRN_SRR0,r10
+ mtspr SPRN_SRR1,r11
+ li r10,BOOK3S_INTERRUPT_EXTERNAL
+ LOAD_REG_IMMEDIATE(r11,MSR_SF | MSR_ME);
+ b fast_guest_return
+
+_GLOBAL(kvmppc_h_set_dabr)
+ std r4,VCPU_DABR(r3)
+ mtspr SPRN_DABR,r4
+ li r3,0
+ blr
+
+secondary_too_late:
+ ld r5,HSTATE_KVM_VCORE(r13)
+ HMT_LOW
+13: lbz r3,VCORE_IN_GUEST(r5)
+ cmpwi r3,0
+ bne 13b
+ HMT_MEDIUM
+ ld r11,PACA_SLBSHADOWPTR(r13)
+
+ .rept SLB_NUM_BOLTED
+ ld r5,SLBSHADOW_SAVEAREA(r11)
+ ld r6,SLBSHADOW_SAVEAREA+8(r11)
+ andis. r7,r5,SLB_ESID_V@h
+ beq 1f
+ slbmte r6,r5
+1: addi r11,r11,16
+ .endr
+ b 50f
+
+secondary_nap:
+ /* Clear any pending IPI */
+50: ld r5, HSTATE_XICS_PHYS(r13)
+ li r0, 0xff
+ li r6, XICS_QIRR
+ stbcix r0, r5, r6
+
+ /* increment the nap count and then go to nap mode */
+ ld r4, HSTATE_KVM_VCORE(r13)
+ addi r4, r4, VCORE_NAP_COUNT
+ lwsync /* make previous updates visible */
+51: lwarx r3, 0, r4
+ addi r3, r3, 1
+ stwcx. r3, 0, r4
+ bne 51b
+ isync
+
+ mfspr r4, SPRN_LPCR
+ li r0, LPCR_PECE
+ andc r4, r4, r0
+ ori r4, r4, LPCR_PECE0 /* exit nap on interrupt */
+ mtspr SPRN_LPCR, r4
+ li r0, 0
+ std r0, HSTATE_SCRATCH0(r13)
+ ptesync
+ ld r0, HSTATE_SCRATCH0(r13)
+1: cmpd r0, r0
+ bne 1b
+ nap
+ b .
+
+/*
+ * Save away FP, VMX and VSX registers.
+ * r3 = vcpu pointer
+ */
+_GLOBAL(kvmppc_save_fp)
+ mfmsr r9
+ ori r8,r9,MSR_FP
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+ oris r8,r8,MSR_VEC@h
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+ oris r8,r8,MSR_VSX@h
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+ mtmsrd r8
+ isync
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+ reg = 0
+ .rept 32
+ li r6,reg*16+VCPU_VSRS
+ stxvd2x reg,r6,r3
+ reg = reg + 1
+ .endr
+FTR_SECTION_ELSE
+#endif
+ reg = 0
+ .rept 32
+ stfd reg,reg*8+VCPU_FPRS(r3)
+ reg = reg + 1
+ .endr
+#ifdef CONFIG_VSX
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
+#endif
+ mffs fr0
+ stfd fr0,VCPU_FPSCR(r3)
+
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+ reg = 0
+ .rept 32
+ li r6,reg*16+VCPU_VRS
+ stvx reg,r6,r3
+ reg = reg + 1
+ .endr
+ mfvscr vr0
+ li r6,VCPU_VSCR
+ stvx vr0,r6,r3
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+ mfspr r6,SPRN_VRSAVE
+ stw r6,VCPU_VRSAVE(r3)
+ mtmsrd r9
+ isync
+ blr
+
+/*
+ * Load up FP, VMX and VSX registers
+ * r4 = vcpu pointer
+ */
+ .globl kvmppc_load_fp
+kvmppc_load_fp:
+ mfmsr r9
+ ori r8,r9,MSR_FP
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+ oris r8,r8,MSR_VEC@h
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+ oris r8,r8,MSR_VSX@h
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+ mtmsrd r8
+ isync
+ lfd fr0,VCPU_FPSCR(r4)
+ MTFSF_L(fr0)
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+ reg = 0
+ .rept 32
+ li r7,reg*16+VCPU_VSRS
+ lxvd2x reg,r7,r4
+ reg = reg + 1
+ .endr
+FTR_SECTION_ELSE
+#endif
+ reg = 0
+ .rept 32
+ lfd reg,reg*8+VCPU_FPRS(r4)
+ reg = reg + 1
+ .endr
+#ifdef CONFIG_VSX
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
+#endif
+
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+ li r7,VCPU_VSCR
+ lvx vr0,r7,r4
+ mtvscr vr0
+ reg = 0
+ .rept 32
+ li r7,reg*16+VCPU_VRS
+ lvx reg,r7,r4
+ reg = reg + 1
+ .endr
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+ lwz r7,VCPU_VRSAVE(r4)
+ mtspr SPRN_VRSAVE,r7
+ blr
diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S
index 2f0bc928b08a..c54b0e30cf3f 100644
--- a/arch/powerpc/kvm/book3s_interrupts.S
+++ b/arch/powerpc/kvm/book3s_interrupts.S
@@ -29,8 +29,7 @@
#define ULONG_SIZE 8
#define FUNC(name) GLUE(.,name)
-#define GET_SHADOW_VCPU(reg) \
- addi reg, r13, PACA_KVM_SVCPU
+#define GET_SHADOW_VCPU_R13
#define DISABLE_INTERRUPTS \
mfmsr r0; \
@@ -43,8 +42,8 @@
#define ULONG_SIZE 4
#define FUNC(name) name
-#define GET_SHADOW_VCPU(reg) \
- lwz reg, (THREAD + THREAD_KVM_SVCPU)(r2)
+#define GET_SHADOW_VCPU_R13 \
+ lwz r13, (THREAD + THREAD_KVM_SVCPU)(r2)
#define DISABLE_INTERRUPTS \
mfmsr r0; \
@@ -85,7 +84,7 @@
* r3: kvm_run pointer
* r4: vcpu pointer
*/
-_GLOBAL(__kvmppc_vcpu_entry)
+_GLOBAL(__kvmppc_vcpu_run)
kvm_start_entry:
/* Write correct stack frame */
@@ -107,17 +106,11 @@ kvm_start_entry:
/* Load non-volatile guest state from the vcpu */
VCPU_LOAD_NVGPRS(r4)
- GET_SHADOW_VCPU(r5)
-
- /* Save R1/R2 in the PACA */
- PPC_STL r1, SVCPU_HOST_R1(r5)
- PPC_STL r2, SVCPU_HOST_R2(r5)
+kvm_start_lightweight:
- /* XXX swap in/out on load? */
+ GET_SHADOW_VCPU_R13
PPC_LL r3, VCPU_HIGHMEM_HANDLER(r4)
- PPC_STL r3, SVCPU_VMHANDLER(r5)
-
-kvm_start_lightweight:
+ PPC_STL r3, HSTATE_VMHANDLER(r13)
PPC_LL r10, VCPU_SHADOW_MSR(r4) /* r10 = vcpu->arch.shadow_msr */
diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c b/arch/powerpc/kvm/book3s_mmu_hpte.c
index 79751d8dd131..41cb0017e757 100644
--- a/arch/powerpc/kvm/book3s_mmu_hpte.c
+++ b/arch/powerpc/kvm/book3s_mmu_hpte.c
@@ -21,7 +21,6 @@
#include <linux/kvm_host.h>
#include <linux/hash.h>
#include <linux/slab.h>
-#include "trace.h"
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
@@ -29,6 +28,8 @@
#include <asm/mmu_context.h>
#include <asm/hw_irq.h>
+#include "trace.h"
+
#define PTE_SIZE 12
static struct kmem_cache *hpte_cache;
@@ -58,30 +59,31 @@ static inline u64 kvmppc_mmu_hash_vpte_long(u64 vpage)
void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
{
u64 index;
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
trace_kvm_book3s_mmu_map(pte);
- spin_lock(&vcpu->arch.mmu_lock);
+ spin_lock(&vcpu3s->mmu_lock);
/* Add to ePTE list */
index = kvmppc_mmu_hash_pte(pte->pte.eaddr);
- hlist_add_head_rcu(&pte->list_pte, &vcpu->arch.hpte_hash_pte[index]);
+ hlist_add_head_rcu(&pte->list_pte, &vcpu3s->hpte_hash_pte[index]);
/* Add to ePTE_long list */
index = kvmppc_mmu_hash_pte_long(pte->pte.eaddr);
hlist_add_head_rcu(&pte->list_pte_long,
- &vcpu->arch.hpte_hash_pte_long[index]);
+ &vcpu3s->hpte_hash_pte_long[index]);
/* Add to vPTE list */
index = kvmppc_mmu_hash_vpte(pte->pte.vpage);
- hlist_add_head_rcu(&pte->list_vpte, &vcpu->arch.hpte_hash_vpte[index]);
+ hlist_add_head_rcu(&pte->list_vpte, &vcpu3s->hpte_hash_vpte[index]);
/* Add to vPTE_long list */
index = kvmppc_mmu_hash_vpte_long(pte->pte.vpage);
hlist_add_head_rcu(&pte->list_vpte_long,
- &vcpu->arch.hpte_hash_vpte_long[index]);
+ &vcpu3s->hpte_hash_vpte_long[index]);
- spin_unlock(&vcpu->arch.mmu_lock);
+ spin_unlock(&vcpu3s->mmu_lock);
}
static void free_pte_rcu(struct rcu_head *head)
@@ -92,16 +94,18 @@ static void free_pte_rcu(struct rcu_head *head)
static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+
trace_kvm_book3s_mmu_invalidate(pte);
/* Different for 32 and 64 bit */
kvmppc_mmu_invalidate_pte(vcpu, pte);
- spin_lock(&vcpu->arch.mmu_lock);
+ spin_lock(&vcpu3s->mmu_lock);
/* pte already invalidated in between? */
if (hlist_unhashed(&pte->list_pte)) {
- spin_unlock(&vcpu->arch.mmu_lock);
+ spin_unlock(&vcpu3s->mmu_lock);
return;
}
@@ -115,14 +119,15 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
else
kvm_release_pfn_clean(pte->pfn);
- spin_unlock(&vcpu->arch.mmu_lock);
+ spin_unlock(&vcpu3s->mmu_lock);
- vcpu->arch.hpte_cache_count--;
+ vcpu3s->hpte_cache_count--;
call_rcu(&pte->rcu_head, free_pte_rcu);
}
static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
struct hpte_cache *pte;
struct hlist_node *node;
int i;
@@ -130,7 +135,7 @@ static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
rcu_read_lock();
for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) {
- struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i];
+ struct hlist_head *list = &vcpu3s->hpte_hash_vpte_long[i];
hlist_for_each_entry_rcu(pte, node, list, list_vpte_long)
invalidate_pte(vcpu, pte);
@@ -141,12 +146,13 @@ static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
static void kvmppc_mmu_pte_flush_page(struct kvm_vcpu *vcpu, ulong guest_ea)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
struct hlist_head *list;
struct hlist_node *node;
struct hpte_cache *pte;
/* Find the list of entries in the map */
- list = &vcpu->arch.hpte_hash_pte[kvmppc_mmu_hash_pte(guest_ea)];
+ list = &vcpu3s->hpte_hash_pte[kvmppc_mmu_hash_pte(guest_ea)];
rcu_read_lock();
@@ -160,12 +166,13 @@ static void kvmppc_mmu_pte_flush_page(struct kvm_vcpu *vcpu, ulong guest_ea)
static void kvmppc_mmu_pte_flush_long(struct kvm_vcpu *vcpu, ulong guest_ea)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
struct hlist_head *list;
struct hlist_node *node;
struct hpte_cache *pte;
/* Find the list of entries in the map */
- list = &vcpu->arch.hpte_hash_pte_long[
+ list = &vcpu3s->hpte_hash_pte_long[
kvmppc_mmu_hash_pte_long(guest_ea)];
rcu_read_lock();
@@ -203,12 +210,13 @@ void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong ea_mask)
/* Flush with mask 0xfffffffff */
static void kvmppc_mmu_pte_vflush_short(struct kvm_vcpu *vcpu, u64 guest_vp)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
struct hlist_head *list;
struct hlist_node *node;
struct hpte_cache *pte;
u64 vp_mask = 0xfffffffffULL;
- list = &vcpu->arch.hpte_hash_vpte[kvmppc_mmu_hash_vpte(guest_vp)];
+ list = &vcpu3s->hpte_hash_vpte[kvmppc_mmu_hash_vpte(guest_vp)];
rcu_read_lock();
@@ -223,12 +231,13 @@ static void kvmppc_mmu_pte_vflush_short(struct kvm_vcpu *vcpu, u64 guest_vp)
/* Flush with mask 0xffffff000 */
static void kvmppc_mmu_pte_vflush_long(struct kvm_vcpu *vcpu, u64 guest_vp)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
struct hlist_head *list;
struct hlist_node *node;
struct hpte_cache *pte;
u64 vp_mask = 0xffffff000ULL;
- list = &vcpu->arch.hpte_hash_vpte_long[
+ list = &vcpu3s->hpte_hash_vpte_long[
kvmppc_mmu_hash_vpte_long(guest_vp)];
rcu_read_lock();
@@ -261,6 +270,7 @@ void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask)
void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
struct hlist_node *node;
struct hpte_cache *pte;
int i;
@@ -270,7 +280,7 @@ void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
rcu_read_lock();
for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) {
- struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i];
+ struct hlist_head *list = &vcpu3s->hpte_hash_vpte_long[i];
hlist_for_each_entry_rcu(pte, node, list, list_vpte_long)
if ((pte->pte.raddr >= pa_start) &&
@@ -283,12 +293,13 @@ void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
struct hpte_cache *pte;
pte = kmem_cache_zalloc(hpte_cache, GFP_KERNEL);
- vcpu->arch.hpte_cache_count++;
+ vcpu3s->hpte_cache_count++;
- if (vcpu->arch.hpte_cache_count == HPTEG_CACHE_NUM)
+ if (vcpu3s->hpte_cache_count == HPTEG_CACHE_NUM)
kvmppc_mmu_pte_flush_all(vcpu);
return pte;
@@ -309,17 +320,19 @@ static void kvmppc_mmu_hpte_init_hash(struct hlist_head *hash_list, int len)
int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu)
{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+
/* init hpte lookup hashes */
- kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_pte,
- ARRAY_SIZE(vcpu->arch.hpte_hash_pte));
- kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_pte_long,
- ARRAY_SIZE(vcpu->arch.hpte_hash_pte_long));
- kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte,
- ARRAY_SIZE(vcpu->arch.hpte_hash_vpte));
- kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte_long,
- ARRAY_SIZE(vcpu->arch.hpte_hash_vpte_long));
-
- spin_lock_init(&vcpu->arch.mmu_lock);
+ kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_pte,
+ ARRAY_SIZE(vcpu3s->hpte_hash_pte));
+ kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_pte_long,
+ ARRAY_SIZE(vcpu3s->hpte_hash_pte_long));
+ kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_vpte,
+ ARRAY_SIZE(vcpu3s->hpte_hash_vpte));
+ kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_vpte_long,
+ ARRAY_SIZE(vcpu3s->hpte_hash_vpte_long));
+
+ spin_lock_init(&vcpu3s->mmu_lock);
return 0;
}
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
new file mode 100644
index 000000000000..0c0d3f274437
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ * Alexander Graf <agraf@suse.de>
+ * Kevin Wolf <mail@kevin-wolf.de>
+ * Paul Mackerras <paulus@samba.org>
+ *
+ * Description:
+ * Functions relating to running KVM on Book 3S processors where
+ * we don't have access to hypervisor mode, and we run the guest
+ * in problem state (user mode).
+ *
+ * This file is derived from arch/powerpc/kvm/44x.c,
+ * by Hollis Blanchard <hollisb@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, version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <asm/reg.h>
+#include <asm/cputable.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu_context.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+
+#include "trace.h"
+
+/* #define EXIT_DEBUG */
+/* #define DEBUG_EXT */
+
+static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
+ ulong msr);
+
+/* Some compatibility defines */
+#ifdef CONFIG_PPC_BOOK3S_32
+#define MSR_USER32 MSR_USER
+#define MSR_USER64 MSR_USER
+#define HW_PAGE_SIZE PAGE_SIZE
+#endif
+
+void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+ memcpy(to_svcpu(vcpu)->slb, to_book3s(vcpu)->slb_shadow, sizeof(to_svcpu(vcpu)->slb));
+ memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu,
+ sizeof(get_paca()->shadow_vcpu));
+ to_svcpu(vcpu)->slb_max = to_book3s(vcpu)->slb_shadow_max;
+#endif
+
+#ifdef CONFIG_PPC_BOOK3S_32
+ current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
+#endif
+}
+
+void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+ memcpy(to_book3s(vcpu)->slb_shadow, to_svcpu(vcpu)->slb, sizeof(to_svcpu(vcpu)->slb));
+ memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu,
+ sizeof(get_paca()->shadow_vcpu));
+ to_book3s(vcpu)->slb_shadow_max = to_svcpu(vcpu)->slb_max;
+#endif
+
+ kvmppc_giveup_ext(vcpu, MSR_FP);
+ kvmppc_giveup_ext(vcpu, MSR_VEC);
+ kvmppc_giveup_ext(vcpu, MSR_VSX);
+}
+
+static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
+{
+ ulong smsr = vcpu->arch.shared->msr;
+
+ /* Guest MSR values */
+ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
+ /* Process MSR values */
+ smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
+ /* External providers the guest reserved */
+ smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
+ /* 64-bit Process MSR values */
+#ifdef CONFIG_PPC_BOOK3S_64
+ smsr |= MSR_ISF | MSR_HV;
+#endif
+ vcpu->arch.shadow_msr = smsr;
+}
+
+void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
+{
+ ulong old_msr = vcpu->arch.shared->msr;
+
+#ifdef EXIT_DEBUG
+ printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
+#endif
+
+ msr &= to_book3s(vcpu)->msr_mask;
+ vcpu->arch.shared->msr = msr;
+ kvmppc_recalc_shadow_msr(vcpu);
+
+ if (msr & MSR_POW) {
+ if (!vcpu->arch.pending_exceptions) {
+ kvm_vcpu_block(vcpu);
+ vcpu->stat.halt_wakeup++;
+
+ /* Unset POW bit after we woke up */
+ msr &= ~MSR_POW;
+ vcpu->arch.shared->msr = msr;
+ }
+ }
+
+ if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
+ (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
+ kvmppc_mmu_flush_segments(vcpu);
+ kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
+
+ /* Preload magic page segment when in kernel mode */
+ if (!(msr & MSR_PR) && vcpu->arch.magic_page_pa) {
+ struct kvm_vcpu_arch *a = &vcpu->arch;
+
+ if (msr & MSR_DR)
+ kvmppc_mmu_map_segment(vcpu, a->magic_page_ea);
+ else
+ kvmppc_mmu_map_segment(vcpu, a->magic_page_pa);
+ }
+ }
+
+ /* Preload FPU if it's enabled */
+ if (vcpu->arch.shared->msr & MSR_FP)
+ kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
+}
+
+void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
+{
+ u32 host_pvr;
+
+ vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB;
+ vcpu->arch.pvr = pvr;
+#ifdef CONFIG_PPC_BOOK3S_64
+ if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
+ kvmppc_mmu_book3s_64_init(vcpu);
+ to_book3s(vcpu)->hior = 0xfff00000;
+ to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
+ } else
+#endif
+ {
+ kvmppc_mmu_book3s_32_init(vcpu);
+ to_book3s(vcpu)->hior = 0;
+ to_book3s(vcpu)->msr_mask = 0xffffffffULL;
+ }
+
+ /* 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;
+ if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) &&
+ !strcmp(cur_cpu_spec->platform, "ppc970"))
+ vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
+
+ /* Cell performs badly if MSR_FEx are set. So let's hope nobody
+ really needs them in a VM on Cell and force disable them. */
+ if (!strcmp(cur_cpu_spec->platform, "ppc-cell-be"))
+ to_book3s(vcpu)->msr_mask &= ~(MSR_FE0 | MSR_FE1);
+
+#ifdef CONFIG_PPC_BOOK3S_32
+ /* 32 bit Book3S always has 32 byte dcbz */
+ vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
+#endif
+
+ /* On some CPUs we can execute paired single operations natively */
+ asm ( "mfpvr %0" : "=r"(host_pvr));
+ switch (host_pvr) {
+ case 0x00080200: /* lonestar 2.0 */
+ case 0x00088202: /* lonestar 2.2 */
+ case 0x70000100: /* gekko 1.0 */
+ case 0x00080100: /* gekko 2.0 */
+ case 0x00083203: /* gekko 2.3a */
+ case 0x00083213: /* gekko 2.3b */
+ case 0x00083204: /* gekko 2.4 */
+ case 0x00083214: /* gekko 2.4e (8SE) - retail HW2 */
+ case 0x00087200: /* broadway */
+ vcpu->arch.hflags |= BOOK3S_HFLAG_NATIVE_PS;
+ /* Enable HID2.PSE - in case we need it later */
+ mtspr(SPRN_HID2_GEKKO, mfspr(SPRN_HID2_GEKKO) | (1 << 29));
+ }
+}
+
+/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To
+ * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to
+ * emulate 32 bytes dcbz length.
+ *
+ * The Book3s_64 inventors also realized this case and implemented a special bit
+ * in the HID5 register, which is a hypervisor ressource. Thus we can't use it.
+ *
+ * My approach here is to patch the dcbz instruction on executing pages.
+ */
+static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
+{
+ struct page *hpage;
+ u64 hpage_offset;
+ u32 *page;
+ int i;
+
+ hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
+ if (is_error_page(hpage)) {
+ kvm_release_page_clean(hpage);
+ return;
+ }
+
+ hpage_offset = pte->raddr & ~PAGE_MASK;
+ hpage_offset &= ~0xFFFULL;
+ hpage_offset /= 4;
+
+ get_page(hpage);
+ page = kmap_atomic(hpage, KM_USER0);
+
+ /* patch dcbz into reserved instruction, so we trap */
+ for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
+ if ((page[i] & 0xff0007ff) == INS_DCBZ)
+ page[i] &= 0xfffffff7;
+
+ kunmap_atomic(page, KM_USER0);
+ put_page(hpage);
+}
+
+static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ if (unlikely(mp_pa) &&
+ unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) {
+ return 1;
+ }
+
+ return kvm_is_visible_gfn(vcpu->kvm, gfn);
+}
+
+int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ ulong eaddr, int vec)
+{
+ bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE);
+ int r = RESUME_GUEST;
+ int relocated;
+ int page_found = 0;
+ struct kvmppc_pte pte;
+ bool is_mmio = false;
+ bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
+ bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
+ u64 vsid;
+
+ relocated = data ? dr : ir;
+
+ /* Resolve real address if translation turned on */
+ if (relocated) {
+ page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data);
+ } else {
+ pte.may_execute = true;
+ pte.may_read = true;
+ pte.may_write = true;
+ pte.raddr = eaddr & KVM_PAM;
+ pte.eaddr = eaddr;
+ pte.vpage = eaddr >> 12;
+ }
+
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
+ case 0:
+ pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
+ break;
+ case MSR_DR:
+ case MSR_IR:
+ vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
+
+ if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
+ pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
+ else
+ pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
+ pte.vpage |= vsid;
+
+ if (vsid == -1)
+ page_found = -EINVAL;
+ break;
+ }
+
+ if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
+ (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
+ /*
+ * If we do the dcbz hack, we have to NX on every execution,
+ * so we can patch the executing code. This renders our guest
+ * NX-less.
+ */
+ pte.may_execute = !data;
+ }
+
+ if (page_found == -ENOENT) {
+ /* Page not found in guest PTE entries */
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+ vcpu->arch.shared->msr |=
+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ kvmppc_book3s_queue_irqprio(vcpu, vec);
+ } else if (page_found == -EPERM) {
+ /* Storage protection */
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dsisr =
+ to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
+ vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
+ vcpu->arch.shared->msr |=
+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ kvmppc_book3s_queue_irqprio(vcpu, vec);
+ } else if (page_found == -EINVAL) {
+ /* Page not found in guest SLB */
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+ kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
+ } else if (!is_mmio &&
+ kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
+ /* The guest's PTE is not mapped yet. Map on the host */
+ kvmppc_mmu_map_page(vcpu, &pte);
+ if (data)
+ vcpu->stat.sp_storage++;
+ else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
+ (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32)))
+ kvmppc_patch_dcbz(vcpu, &pte);
+ } else {
+ /* MMIO */
+ vcpu->stat.mmio_exits++;
+ vcpu->arch.paddr_accessed = pte.raddr;
+ r = kvmppc_emulate_mmio(run, vcpu);
+ if ( r == RESUME_HOST_NV )
+ r = RESUME_HOST;
+ }
+
+ return r;
+}
+
+static inline int get_fpr_index(int i)
+{
+#ifdef CONFIG_VSX
+ i *= 2;
+#endif
+ return i;
+}
+
+/* Give up external provider (FPU, Altivec, VSX) */
+void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
+{
+ struct thread_struct *t = &current->thread;
+ u64 *vcpu_fpr = vcpu->arch.fpr;
+#ifdef CONFIG_VSX
+ u64 *vcpu_vsx = vcpu->arch.vsr;
+#endif
+ u64 *thread_fpr = (u64*)t->fpr;
+ int i;
+
+ if (!(vcpu->arch.guest_owned_ext & msr))
+ return;
+
+#ifdef DEBUG_EXT
+ printk(KERN_INFO "Giving up ext 0x%lx\n", msr);
+#endif
+
+ switch (msr) {
+ case MSR_FP:
+ giveup_fpu(current);
+ for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
+ vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
+
+ vcpu->arch.fpscr = t->fpscr.val;
+ break;
+ case MSR_VEC:
+#ifdef CONFIG_ALTIVEC
+ giveup_altivec(current);
+ memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
+ vcpu->arch.vscr = t->vscr;
+#endif
+ break;
+ case MSR_VSX:
+#ifdef CONFIG_VSX
+ __giveup_vsx(current);
+ for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
+ vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
+#endif
+ break;
+ default:
+ BUG();
+ }
+
+ vcpu->arch.guest_owned_ext &= ~msr;
+ current->thread.regs->msr &= ~msr;
+ kvmppc_recalc_shadow_msr(vcpu);
+}
+
+static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
+{
+ ulong srr0 = kvmppc_get_pc(vcpu);
+ u32 last_inst = kvmppc_get_last_inst(vcpu);
+ int ret;
+
+ ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
+ if (ret == -ENOENT) {
+ ulong msr = vcpu->arch.shared->msr;
+
+ msr = kvmppc_set_field(msr, 33, 33, 1);
+ msr = kvmppc_set_field(msr, 34, 36, 0);
+ vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
+ kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
+ return EMULATE_AGAIN;
+ }
+
+ return EMULATE_DONE;
+}
+
+static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
+{
+
+ /* Need to do paired single emulation? */
+ if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
+ return EMULATE_DONE;
+
+ /* Read out the instruction */
+ if (kvmppc_read_inst(vcpu) == EMULATE_DONE)
+ /* Need to emulate */
+ return EMULATE_FAIL;
+
+ return EMULATE_AGAIN;
+}
+
+/* Handle external providers (FPU, Altivec, VSX) */
+static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
+ ulong msr)
+{
+ struct thread_struct *t = &current->thread;
+ u64 *vcpu_fpr = vcpu->arch.fpr;
+#ifdef CONFIG_VSX
+ u64 *vcpu_vsx = vcpu->arch.vsr;
+#endif
+ u64 *thread_fpr = (u64*)t->fpr;
+ int i;
+
+ /* When we have paired singles, we emulate in software */
+ if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
+ return RESUME_GUEST;
+
+ if (!(vcpu->arch.shared->msr & msr)) {
+ kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ return RESUME_GUEST;
+ }
+
+ /* We already own the ext */
+ if (vcpu->arch.guest_owned_ext & msr) {
+ return RESUME_GUEST;
+ }
+
+#ifdef DEBUG_EXT
+ printk(KERN_INFO "Loading up ext 0x%lx\n", msr);
+#endif
+
+ current->thread.regs->msr |= msr;
+
+ switch (msr) {
+ case MSR_FP:
+ for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
+ thread_fpr[get_fpr_index(i)] = vcpu_fpr[i];
+
+ t->fpscr.val = vcpu->arch.fpscr;
+ t->fpexc_mode = 0;
+ kvmppc_load_up_fpu();
+ break;
+ case MSR_VEC:
+#ifdef CONFIG_ALTIVEC
+ memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
+ t->vscr = vcpu->arch.vscr;
+ t->vrsave = -1;
+ kvmppc_load_up_altivec();
+#endif
+ break;
+ case MSR_VSX:
+#ifdef CONFIG_VSX
+ for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
+ thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
+ kvmppc_load_up_vsx();
+#endif
+ break;
+ default:
+ BUG();
+ }
+
+ vcpu->arch.guest_owned_ext |= msr;
+
+ kvmppc_recalc_shadow_msr(vcpu);
+
+ return RESUME_GUEST;
+}
+
+int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int exit_nr)
+{
+ int r = RESUME_HOST;
+
+ vcpu->stat.sum_exits++;
+
+ run->exit_reason = KVM_EXIT_UNKNOWN;
+ run->ready_for_interrupt_injection = 1;
+
+ trace_kvm_book3s_exit(exit_nr, vcpu);
+ kvm_resched(vcpu);
+ switch (exit_nr) {
+ case BOOK3S_INTERRUPT_INST_STORAGE:
+ vcpu->stat.pf_instruc++;
+
+#ifdef CONFIG_PPC_BOOK3S_32
+ /* We set segments as unused segments when invalidating them. So
+ * treat the respective fault as segment fault. */
+ if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]
+ == SR_INVALID) {
+ kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
+ r = RESUME_GUEST;
+ break;
+ }
+#endif
+
+ /* only care about PTEG not found errors, but leave NX alone */
+ if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) {
+ r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr);
+ vcpu->stat.sp_instruc++;
+ } else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
+ (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
+ /*
+ * XXX If we do the dcbz hack we use the NX bit to flush&patch the page,
+ * so we can't use the NX bit inside the guest. Let's cross our fingers,
+ * that no guest that needs the dcbz hack does NX.
+ */
+ kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
+ r = RESUME_GUEST;
+ } else {
+ vcpu->arch.shared->msr |=
+ to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
+ kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ r = RESUME_GUEST;
+ }
+ break;
+ case BOOK3S_INTERRUPT_DATA_STORAGE:
+ {
+ ulong dar = kvmppc_get_fault_dar(vcpu);
+ vcpu->stat.pf_storage++;
+
+#ifdef CONFIG_PPC_BOOK3S_32
+ /* We set segments as unused segments when invalidating them. So
+ * treat the respective fault as segment fault. */
+ if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) == SR_INVALID) {
+ kvmppc_mmu_map_segment(vcpu, dar);
+ r = RESUME_GUEST;
+ break;
+ }
+#endif
+
+ /* The only case we need to handle is missing shadow PTEs */
+ if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
+ r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
+ } else {
+ vcpu->arch.shared->dar = dar;
+ vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+ kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ r = RESUME_GUEST;
+ }
+ break;
+ }
+ case BOOK3S_INTERRUPT_DATA_SEGMENT:
+ if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+ kvmppc_book3s_queue_irqprio(vcpu,
+ BOOK3S_INTERRUPT_DATA_SEGMENT);
+ }
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_INST_SEGMENT:
+ if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)) < 0) {
+ kvmppc_book3s_queue_irqprio(vcpu,
+ BOOK3S_INTERRUPT_INST_SEGMENT);
+ }
+ r = RESUME_GUEST;
+ break;
+ /* We're good on these - the host merely wanted to get our attention */
+ case BOOK3S_INTERRUPT_DECREMENTER:
+ vcpu->stat.dec_exits++;
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_EXTERNAL:
+ vcpu->stat.ext_intr_exits++;
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_PERFMON:
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_PROGRAM:
+ {
+ enum emulation_result er;
+ ulong flags;
+
+program_interrupt:
+ flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
+
+ if (vcpu->arch.shared->msr & MSR_PR) {
+#ifdef EXIT_DEBUG
+ printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+#endif
+ if ((kvmppc_get_last_inst(vcpu) & 0xff0007ff) !=
+ (INS_DCBZ & 0xfffffff7)) {
+ kvmppc_core_queue_program(vcpu, flags);
+ r = RESUME_GUEST;
+ break;
+ }
+ }
+
+ vcpu->stat.emulated_inst_exits++;
+ er = kvmppc_emulate_instruction(run, vcpu);
+ switch (er) {
+ case EMULATE_DONE:
+ r = RESUME_GUEST_NV;
+ break;
+ case EMULATE_AGAIN:
+ r = RESUME_GUEST;
+ break;
+ case EMULATE_FAIL:
+ printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
+ __func__, kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+ kvmppc_core_queue_program(vcpu, flags);
+ r = RESUME_GUEST;
+ break;
+ case EMULATE_DO_MMIO:
+ run->exit_reason = KVM_EXIT_MMIO;
+ r = RESUME_HOST_NV;
+ break;
+ default:
+ BUG();
+ }
+ break;
+ }
+ case BOOK3S_INTERRUPT_SYSCALL:
+ 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 */
+ u64 *gprs = run->osi.gprs;
+ int i;
+
+ run->exit_reason = KVM_EXIT_OSI;
+ for (i = 0; i < 32; i++)
+ gprs[i] = kvmppc_get_gpr(vcpu, i);
+ vcpu->arch.osi_needed = 1;
+ r = RESUME_HOST_NV;
+ } else if (!(vcpu->arch.shared->msr & MSR_PR) &&
+ (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) {
+ /* KVM PV hypercalls */
+ kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
+ r = RESUME_GUEST;
+ } else {
+ /* Guest syscalls */
+ vcpu->stat.syscall_exits++;
+ kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ r = RESUME_GUEST;
+ }
+ break;
+ case BOOK3S_INTERRUPT_FP_UNAVAIL:
+ case BOOK3S_INTERRUPT_ALTIVEC:
+ case BOOK3S_INTERRUPT_VSX:
+ {
+ int ext_msr = 0;
+
+ switch (exit_nr) {
+ case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP; break;
+ case BOOK3S_INTERRUPT_ALTIVEC: ext_msr = MSR_VEC; break;
+ case BOOK3S_INTERRUPT_VSX: ext_msr = MSR_VSX; break;
+ }
+
+ switch (kvmppc_check_ext(vcpu, exit_nr)) {
+ case EMULATE_DONE:
+ /* everything ok - let's enable the ext */
+ r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
+ break;
+ case EMULATE_FAIL:
+ /* we need to emulate this instruction */
+ goto program_interrupt;
+ break;
+ default:
+ /* nothing to worry about - go again */
+ break;
+ }
+ break;
+ }
+ case BOOK3S_INTERRUPT_ALIGNMENT:
+ if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
+ vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
+ kvmppc_get_last_inst(vcpu));
+ vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
+ kvmppc_get_last_inst(vcpu));
+ kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ }
+ r = RESUME_GUEST;
+ break;
+ case BOOK3S_INTERRUPT_MACHINE_CHECK:
+ case BOOK3S_INTERRUPT_TRACE:
+ kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ r = RESUME_GUEST;
+ break;
+ default:
+ /* Ugh - bork here! What did we get? */
+ printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n",
+ exit_nr, kvmppc_get_pc(vcpu), to_svcpu(vcpu)->shadow_srr1);
+ r = RESUME_HOST;
+ BUG();
+ 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(current)) {
+#ifdef EXIT_DEBUG
+ printk(KERN_EMERG "KVM: Going back to host\n");
+#endif
+ vcpu->stat.signal_exits++;
+ run->exit_reason = KVM_EXIT_INTR;
+ r = -EINTR;
+ } else {
+ /* In case an interrupt came in that was triggered
+ * from userspace (like DEC), we need to check what
+ * to inject now! */
+ kvmppc_core_deliver_interrupts(vcpu);
+ }
+ }
+
+ trace_kvm_book3s_reenter(r, vcpu);
+
+ return r;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
+{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+ int i;
+
+ sregs->pvr = vcpu->arch.pvr;
+
+ sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1;
+ if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
+ for (i = 0; i < 64; i++) {
+ sregs->u.s.ppc64.slb[i].slbe = vcpu->arch.slb[i].orige | i;
+ sregs->u.s.ppc64.slb[i].slbv = vcpu->arch.slb[i].origv;
+ }
+ } else {
+ for (i = 0; i < 16; i++)
+ sregs->u.s.ppc32.sr[i] = vcpu->arch.shared->sr[i];
+
+ for (i = 0; i < 8; i++) {
+ sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw;
+ sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw;
+ }
+ }
+
+ return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
+{
+ struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+ int i;
+
+ kvmppc_set_pvr(vcpu, sregs->pvr);
+
+ vcpu3s->sdr1 = sregs->u.s.sdr1;
+ if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
+ for (i = 0; i < 64; i++) {
+ vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv,
+ sregs->u.s.ppc64.slb[i].slbe);
+ }
+ } else {
+ for (i = 0; i < 16; i++) {
+ vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false,
+ (u32)sregs->u.s.ppc32.ibat[i]);
+ kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true,
+ (u32)(sregs->u.s.ppc32.ibat[i] >> 32));
+ kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false,
+ (u32)sregs->u.s.ppc32.dbat[i]);
+ kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true,
+ (u32)(sregs->u.s.ppc32.dbat[i] >> 32));
+ }
+ }
+
+ /* Flush the MMU after messing with the segments */
+ kvmppc_mmu_pte_flush(vcpu, 0, 0);
+
+ return 0;
+}
+
+int kvmppc_core_check_processor_compat(void)
+{
+ return 0;
+}
+
+struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+ struct kvmppc_vcpu_book3s *vcpu_book3s;
+ struct kvm_vcpu *vcpu;
+ int err = -ENOMEM;
+ unsigned long p;
+
+ vcpu_book3s = vzalloc(sizeof(struct kvmppc_vcpu_book3s));
+ if (!vcpu_book3s)
+ goto out;
+
+ vcpu_book3s->shadow_vcpu = (struct kvmppc_book3s_shadow_vcpu *)
+ kzalloc(sizeof(*vcpu_book3s->shadow_vcpu), GFP_KERNEL);
+ if (!vcpu_book3s->shadow_vcpu)
+ goto free_vcpu;
+
+ vcpu = &vcpu_book3s->vcpu;
+ err = kvm_vcpu_init(vcpu, kvm, id);
+ if (err)
+ goto free_shadow_vcpu;
+
+ p = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+ /* the real shared page fills the last 4k of our page */
+ vcpu->arch.shared = (void*)(p + PAGE_SIZE - 4096);
+ 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;
+#else
+ /* default to book3s_32 (750) */
+ vcpu->arch.pvr = 0x84202;
+#endif
+ 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);
+ if (err < 0)
+ goto uninit_vcpu;
+
+ return vcpu;
+
+uninit_vcpu:
+ kvm_vcpu_uninit(vcpu);
+free_shadow_vcpu:
+ kfree(vcpu_book3s->shadow_vcpu);
+free_vcpu:
+ vfree(vcpu_book3s);
+out:
+ return ERR_PTR(err);
+}
+
+void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
+
+ free_page((unsigned long)vcpu->arch.shared & PAGE_MASK);
+ kvm_vcpu_uninit(vcpu);
+ kfree(vcpu_book3s->shadow_vcpu);
+ vfree(vcpu_book3s);
+}
+
+int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+ int ret;
+ double fpr[32][TS_FPRWIDTH];
+ unsigned int fpscr;
+ int fpexc_mode;
+#ifdef CONFIG_ALTIVEC
+ vector128 vr[32];
+ vector128 vscr;
+ unsigned long uninitialized_var(vrsave);
+ int used_vr;
+#endif
+#ifdef CONFIG_VSX
+ int used_vsr;
+#endif
+ ulong ext_msr;
+
+ /* 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;
+ }
+
+ /* Save FPU state in stack */
+ if (current->thread.regs->msr & MSR_FP)
+ giveup_fpu(current);
+ memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
+ fpscr = current->thread.fpscr.val;
+ fpexc_mode = current->thread.fpexc_mode;
+
+#ifdef CONFIG_ALTIVEC
+ /* Save Altivec state in stack */
+ used_vr = current->thread.used_vr;
+ if (used_vr) {
+ if (current->thread.regs->msr & MSR_VEC)
+ giveup_altivec(current);
+ memcpy(vr, current->thread.vr, sizeof(current->thread.vr));
+ vscr = current->thread.vscr;
+ vrsave = current->thread.vrsave;
+ }
+#endif
+
+#ifdef CONFIG_VSX
+ /* Save VSX state in stack */
+ used_vsr = current->thread.used_vsr;
+ if (used_vsr && (current->thread.regs->msr & MSR_VSX))
+ __giveup_vsx(current);
+#endif
+
+ /* Remember the MSR with disabled extensions */
+ ext_msr = current->thread.regs->msr;
+
+ /* Preload FPU if it's enabled */
+ if (vcpu->arch.shared->msr & MSR_FP)
+ kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
+
+ kvm_guest_enter();
+
+ ret = __kvmppc_vcpu_run(kvm_run, vcpu);
+
+ kvm_guest_exit();
+
+ local_irq_disable();
+
+ current->thread.regs->msr = ext_msr;
+
+ /* Make sure we save the guest FPU/Altivec/VSX state */
+ kvmppc_giveup_ext(vcpu, MSR_FP);
+ kvmppc_giveup_ext(vcpu, MSR_VEC);
+ kvmppc_giveup_ext(vcpu, MSR_VSX);
+
+ /* Restore FPU state from stack */
+ memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
+ current->thread.fpscr.val = fpscr;
+ current->thread.fpexc_mode = fpexc_mode;
+
+#ifdef CONFIG_ALTIVEC
+ /* Restore Altivec state from stack */
+ if (used_vr && current->thread.used_vr) {
+ memcpy(current->thread.vr, vr, sizeof(current->thread.vr));
+ current->thread.vscr = vscr;
+ current->thread.vrsave = vrsave;
+ }
+ current->thread.used_vr = used_vr;
+#endif
+
+#ifdef CONFIG_VSX
+ current->thread.used_vsr = used_vsr;
+#endif
+
+ return ret;
+}
+
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem)
+{
+ return 0;
+}
+
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem)
+{
+}
+
+int kvmppc_core_init_vm(struct kvm *kvm)
+{
+ return 0;
+}
+
+void kvmppc_core_destroy_vm(struct kvm *kvm)
+{
+}
+
+static int kvmppc_book3s_init(void)
+{
+ int r;
+
+ r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), 0,
+ THIS_MODULE);
+
+ if (r)
+ return r;
+
+ r = kvmppc_mmu_hpte_sysinit();
+
+ return r;
+}
+
+static void kvmppc_book3s_exit(void)
+{
+ kvmppc_mmu_hpte_sysexit();
+ kvm_exit();
+}
+
+module_init(kvmppc_book3s_init);
+module_exit(kvmppc_book3s_exit);
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S
index 1a1b34487e71..c1f877c4a884 100644
--- a/arch/powerpc/kvm/book3s_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_rmhandlers.S
@@ -36,41 +36,44 @@
#if defined(CONFIG_PPC_BOOK3S_64)
#define LOAD_SHADOW_VCPU(reg) GET_PACA(reg)
-#define SHADOW_VCPU_OFF PACA_KVM_SVCPU
#define MSR_NOIRQ MSR_KERNEL & ~(MSR_IR | MSR_DR)
#define FUNC(name) GLUE(.,name)
+kvmppc_skip_interrupt:
+ /*
+ * Here all GPRs are unchanged from when the interrupt happened
+ * except for r13, which is saved in SPRG_SCRATCH0.
+ */
+ mfspr r13, SPRN_SRR0
+ addi r13, r13, 4
+ mtspr SPRN_SRR0, r13
+ GET_SCRATCH0(r13)
+ rfid
+ b .
+
+kvmppc_skip_Hinterrupt:
+ /*
+ * Here all GPRs are unchanged from when the interrupt happened
+ * except for r13, which is saved in SPRG_SCRATCH0.
+ */
+ mfspr r13, SPRN_HSRR0
+ addi r13, r13, 4
+ mtspr SPRN_HSRR0, r13
+ GET_SCRATCH0(r13)
+ hrfid
+ b .
+
#elif defined(CONFIG_PPC_BOOK3S_32)
-#define LOAD_SHADOW_VCPU(reg) \
- mfspr reg, SPRN_SPRG_THREAD; \
- lwz reg, THREAD_KVM_SVCPU(reg); \
- /* PPC32 can have a NULL pointer - let's check for that */ \
- mtspr SPRN_SPRG_SCRATCH1, r12; /* Save r12 */ \
- mfcr r12; \
- cmpwi reg, 0; \
- bne 1f; \
- mfspr reg, SPRN_SPRG_SCRATCH0; \
- mtcr r12; \
- mfspr r12, SPRN_SPRG_SCRATCH1; \
- b kvmppc_resume_\intno; \
-1:; \
- mtcr r12; \
- mfspr r12, SPRN_SPRG_SCRATCH1; \
- tophys(reg, reg)
-
-#define SHADOW_VCPU_OFF 0
#define MSR_NOIRQ MSR_KERNEL
#define FUNC(name) name
-#endif
-
.macro INTERRUPT_TRAMPOLINE intno
.global kvmppc_trampoline_\intno
kvmppc_trampoline_\intno:
- SET_SCRATCH0(r13) /* Save r13 */
+ mtspr SPRN_SPRG_SCRATCH0, r13 /* Save r13 */
/*
* First thing to do is to find out if we're coming
@@ -78,19 +81,28 @@ kvmppc_trampoline_\intno:
*
* To distinguish, we check a magic byte in the PACA/current
*/
- LOAD_SHADOW_VCPU(r13)
- PPC_STL r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
+ mfspr r13, SPRN_SPRG_THREAD
+ lwz r13, THREAD_KVM_SVCPU(r13)
+ /* PPC32 can have a NULL pointer - let's check for that */
+ mtspr SPRN_SPRG_SCRATCH1, r12 /* Save r12 */
mfcr r12
- stw r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
- lbz r12, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)
+ cmpwi r13, 0
+ bne 1f
+2: mtcr r12
+ mfspr r12, SPRN_SPRG_SCRATCH1
+ mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */
+ b kvmppc_resume_\intno /* Get back original handler */
+
+1: tophys(r13, r13)
+ stw r12, HSTATE_SCRATCH1(r13)
+ mfspr r12, SPRN_SPRG_SCRATCH1
+ stw r12, HSTATE_SCRATCH0(r13)
+ lbz r12, HSTATE_IN_GUEST(r13)
cmpwi r12, KVM_GUEST_MODE_NONE
bne ..kvmppc_handler_hasmagic_\intno
/* No KVM guest? Then jump back to the Linux handler! */
- lwz r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
- mtcr r12
- PPC_LL r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
- GET_SCRATCH0(r13) /* r13 = original r13 */
- b kvmppc_resume_\intno /* Get back original handler */
+ lwz r12, HSTATE_SCRATCH1(r13)
+ b 2b
/* Now we know we're handling a KVM guest */
..kvmppc_handler_hasmagic_\intno:
@@ -112,9 +124,6 @@ INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_MACHINE_CHECK
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_STORAGE
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_STORAGE
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_EXTERNAL
-#ifdef CONFIG_PPC_BOOK3S_64
-INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_EXTERNAL_HV
-#endif
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALIGNMENT
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PROGRAM
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_FP_UNAVAIL
@@ -124,14 +133,6 @@ INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_TRACE
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PERFMON
INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALTIVEC
-/* Those are only available on 64 bit machines */
-
-#ifdef CONFIG_PPC_BOOK3S_64
-INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_SEGMENT
-INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_SEGMENT
-INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX
-#endif
-
/*
* Bring us back to the faulting code, but skip the
* faulting instruction.
@@ -143,8 +144,8 @@ INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX
*
* R12 = free
* R13 = Shadow VCPU (PACA)
- * SVCPU.SCRATCH0 = guest R12
- * SVCPU.SCRATCH1 = guest CR
+ * HSTATE.SCRATCH0 = guest R12
+ * HSTATE.SCRATCH1 = guest CR
* SPRG_SCRATCH0 = guest R13
*
*/
@@ -156,13 +157,14 @@ kvmppc_handler_skip_ins:
mtsrr0 r12
/* Clean up all state */
- lwz r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
+ lwz r12, HSTATE_SCRATCH1(r13)
mtcr r12
- PPC_LL r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
+ PPC_LL r12, HSTATE_SCRATCH0(r13)
GET_SCRATCH0(r13)
/* And get back into the code */
RFI
+#endif
/*
* This trampoline brings us back to a real mode handler
@@ -251,12 +253,4 @@ define_load_up(altivec)
define_load_up(vsx)
#endif
-.global kvmppc_trampoline_lowmem
-kvmppc_trampoline_lowmem:
- PPC_LONG kvmppc_handler_lowmem_trampoline - CONFIG_KERNEL_START
-
-.global kvmppc_trampoline_enter
-kvmppc_trampoline_enter:
- PPC_LONG kvmppc_handler_trampoline_enter - CONFIG_KERNEL_START
-
#include "book3s_segment.S"
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S
index 451264274b8c..aed32e517212 100644
--- a/arch/powerpc/kvm/book3s_segment.S
+++ b/arch/powerpc/kvm/book3s_segment.S
@@ -22,7 +22,7 @@
#if defined(CONFIG_PPC_BOOK3S_64)
#define GET_SHADOW_VCPU(reg) \
- addi reg, r13, PACA_KVM_SVCPU
+ mr reg, r13
#elif defined(CONFIG_PPC_BOOK3S_32)
@@ -71,6 +71,10 @@ kvmppc_handler_trampoline_enter:
/* r3 = shadow vcpu */
GET_SHADOW_VCPU(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
@@ -78,36 +82,36 @@ kvmppc_handler_trampoline_enter:
/* Activate guest mode, so faults get handled by KVM */
li r11, KVM_GUEST_MODE_GUEST
- stb r11, SVCPU_IN_GUEST(r3)
+ stb r11, HSTATE_IN_GUEST(r3)
/* Switch to guest segment. This is subarch specific. */
LOAD_GUEST_SEGMENTS
/* 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 r4, SVCPU_CTR(r3)
+ PPC_LL r5, SVCPU_LR(r3)
+ lwz r6, SVCPU_CR(r3)
+ lwz r7, SVCPU_XER(r3)
mtctr r4
mtlr r5
mtcr r6
mtxer r7
- PPC_LL r0, (SVCPU_R0)(r3)
- PPC_LL r1, (SVCPU_R1)(r3)
- PPC_LL r2, (SVCPU_R2)(r3)
- PPC_LL r4, (SVCPU_R4)(r3)
- PPC_LL r5, (SVCPU_R5)(r3)
- PPC_LL r6, (SVCPU_R6)(r3)
- PPC_LL r7, (SVCPU_R7)(r3)
- PPC_LL r8, (SVCPU_R8)(r3)
- PPC_LL r9, (SVCPU_R9)(r3)
- PPC_LL r10, (SVCPU_R10)(r3)
- PPC_LL r11, (SVCPU_R11)(r3)
- PPC_LL r12, (SVCPU_R12)(r3)
- PPC_LL r13, (SVCPU_R13)(r3)
+ PPC_LL r0, SVCPU_R0(r3)
+ PPC_LL r1, SVCPU_R1(r3)
+ PPC_LL r2, SVCPU_R2(r3)
+ PPC_LL r4, SVCPU_R4(r3)
+ PPC_LL r5, SVCPU_R5(r3)
+ PPC_LL r6, SVCPU_R6(r3)
+ PPC_LL r7, SVCPU_R7(r3)
+ PPC_LL r8, SVCPU_R8(r3)
+ PPC_LL r9, SVCPU_R9(r3)
+ PPC_LL r10, SVCPU_R10(r3)
+ PPC_LL r11, SVCPU_R11(r3)
+ PPC_LL r12, SVCPU_R12(r3)
+ PPC_LL r13, SVCPU_R13(r3)
PPC_LL r3, (SVCPU_R3)(r3)
@@ -125,56 +129,63 @@ kvmppc_handler_trampoline_enter_end:
.global kvmppc_handler_trampoline_exit
kvmppc_handler_trampoline_exit:
+.global kvmppc_interrupt
+kvmppc_interrupt:
+
/* Register usage at this point:
*
* SPRG_SCRATCH0 = guest R13
* R12 = exit handler id
- * R13 = shadow vcpu - SHADOW_VCPU_OFF [=PACA on PPC64]
- * SVCPU.SCRATCH0 = guest R12
- * SVCPU.SCRATCH1 = guest CR
+ * R13 = shadow vcpu (32-bit) or PACA (64-bit)
+ * HSTATE.SCRATCH0 = guest R12
+ * HSTATE.SCRATCH1 = guest CR
*
*/
/* Save registers */
- PPC_STL r0, (SHADOW_VCPU_OFF + SVCPU_R0)(r13)
- PPC_STL r1, (SHADOW_VCPU_OFF + SVCPU_R1)(r13)
- PPC_STL r2, (SHADOW_VCPU_OFF + SVCPU_R2)(r13)
- PPC_STL r3, (SHADOW_VCPU_OFF + SVCPU_R3)(r13)
- PPC_STL r4, (SHADOW_VCPU_OFF + SVCPU_R4)(r13)
- PPC_STL r5, (SHADOW_VCPU_OFF + SVCPU_R5)(r13)
- PPC_STL r6, (SHADOW_VCPU_OFF + SVCPU_R6)(r13)
- PPC_STL r7, (SHADOW_VCPU_OFF + SVCPU_R7)(r13)
- PPC_STL r8, (SHADOW_VCPU_OFF + SVCPU_R8)(r13)
- PPC_STL r9, (SHADOW_VCPU_OFF + SVCPU_R9)(r13)
- PPC_STL r10, (SHADOW_VCPU_OFF + SVCPU_R10)(r13)
- PPC_STL r11, (SHADOW_VCPU_OFF + SVCPU_R11)(r13)
+ PPC_STL r0, SVCPU_R0(r13)
+ PPC_STL r1, SVCPU_R1(r13)
+ PPC_STL r2, SVCPU_R2(r13)
+ PPC_STL r3, SVCPU_R3(r13)
+ PPC_STL r4, SVCPU_R4(r13)
+ PPC_STL r5, SVCPU_R5(r13)
+ PPC_STL r6, SVCPU_R6(r13)
+ PPC_STL r7, SVCPU_R7(r13)
+ PPC_STL r8, SVCPU_R8(r13)
+ PPC_STL r9, SVCPU_R9(r13)
+ PPC_STL r10, SVCPU_R10(r13)
+ PPC_STL r11, SVCPU_R11(r13)
/* Restore R1/R2 so we can handle faults */
- PPC_LL r1, (SHADOW_VCPU_OFF + SVCPU_HOST_R1)(r13)
- PPC_LL r2, (SHADOW_VCPU_OFF + SVCPU_HOST_R2)(r13)
+ PPC_LL r1, HSTATE_HOST_R1(r13)
+ PPC_LL r2, HSTATE_HOST_R2(r13)
/* Save guest PC and MSR */
+#ifdef CONFIG_PPC64
+BEGIN_FTR_SECTION
andi. r0,r12,0x2
beq 1f
mfspr r3,SPRN_HSRR0
mfspr r4,SPRN_HSRR1
andi. r12,r12,0x3ffd
b 2f
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+#endif
1: mfsrr0 r3
mfsrr1 r4
2:
- PPC_STL r3, (SHADOW_VCPU_OFF + SVCPU_PC)(r13)
- PPC_STL r4, (SHADOW_VCPU_OFF + SVCPU_SHADOW_SRR1)(r13)
+ PPC_STL r3, SVCPU_PC(r13)
+ PPC_STL r4, SVCPU_SHADOW_SRR1(r13)
/* Get scratch'ed off registers */
GET_SCRATCH0(r9)
- PPC_LL r8, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
- lwz r7, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
+ PPC_LL r8, HSTATE_SCRATCH0(r13)
+ lwz r7, HSTATE_SCRATCH1(r13)
- PPC_STL r9, (SHADOW_VCPU_OFF + SVCPU_R13)(r13)
- PPC_STL r8, (SHADOW_VCPU_OFF + SVCPU_R12)(r13)
- stw r7, (SHADOW_VCPU_OFF + SVCPU_CR)(r13)
+ PPC_STL r9, SVCPU_R13(r13)
+ PPC_STL r8, SVCPU_R12(r13)
+ stw r7, SVCPU_CR(r13)
/* Save more register state */
@@ -184,11 +195,11 @@ kvmppc_handler_trampoline_exit:
mfctr r8
mflr r9
- stw r5, (SHADOW_VCPU_OFF + SVCPU_XER)(r13)
- PPC_STL r6, (SHADOW_VCPU_OFF + SVCPU_FAULT_DAR)(r13)
- stw r7, (SHADOW_VCPU_OFF + SVCPU_FAULT_DSISR)(r13)
- PPC_STL r8, (SHADOW_VCPU_OFF + SVCPU_CTR)(r13)
- PPC_STL r9, (SHADOW_VCPU_OFF + SVCPU_LR)(r13)
+ stw r5, SVCPU_XER(r13)
+ PPC_STL r6, SVCPU_FAULT_DAR(r13)
+ stw r7, SVCPU_FAULT_DSISR(r13)
+ PPC_STL r8, SVCPU_CTR(r13)
+ PPC_STL r9, SVCPU_LR(r13)
/*
* In order for us to easily get the last instruction,
@@ -218,7 +229,7 @@ ld_last_inst:
/* Set guest mode to 'jump over instruction' so if lwz faults
* we'll just continue at the next IP. */
li r9, KVM_GUEST_MODE_SKIP
- stb r9, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)
+ stb r9, HSTATE_IN_GUEST(r13)
/* 1) enable paging for data */
mfmsr r9
@@ -232,13 +243,13 @@ ld_last_inst:
sync
#endif
- stw r0, (SHADOW_VCPU_OFF + SVCPU_LAST_INST)(r13)
+ stw r0, SVCPU_LAST_INST(r13)
no_ld_last_inst:
/* Unset guest mode */
li r9, KVM_GUEST_MODE_NONE
- stb r9, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)
+ stb r9, HSTATE_IN_GUEST(r13)
/* Switch back to host MMU */
LOAD_HOST_SEGMENTS
@@ -248,7 +259,7 @@ no_ld_last_inst:
* R1 = host R1
* R2 = host R2
* R12 = exit handler id
- * R13 = shadow vcpu - SHADOW_VCPU_OFF [=PACA on PPC64]
+ * R13 = shadow vcpu (32-bit) or PACA (64-bit)
* SVCPU.* = guest *
*
*/
@@ -258,7 +269,7 @@ no_ld_last_inst:
ori r7, r7, MSR_IR|MSR_DR|MSR_RI|MSR_ME /* Enable paging */
mtsrr1 r7
/* Load highmem handler address */
- PPC_LL r8, (SHADOW_VCPU_OFF + SVCPU_VMHANDLER)(r13)
+ PPC_LL r8, HSTATE_VMHANDLER(r13)
mtsrr0 r8
RFI
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 8462b3a1c1c7..ee45fa01220e 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -13,6 +13,7 @@
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright IBM Corp. 2007
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
*
* Authors: Hollis Blanchard <hollisb@us.ibm.com>
* Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
@@ -78,6 +79,60 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
}
}
+#ifdef CONFIG_SPE
+void kvmppc_vcpu_disable_spe(struct kvm_vcpu *vcpu)
+{
+ preempt_disable();
+ enable_kernel_spe();
+ kvmppc_save_guest_spe(vcpu);
+ vcpu->arch.shadow_msr &= ~MSR_SPE;
+ preempt_enable();
+}
+
+static void kvmppc_vcpu_enable_spe(struct kvm_vcpu *vcpu)
+{
+ preempt_disable();
+ enable_kernel_spe();
+ kvmppc_load_guest_spe(vcpu);
+ vcpu->arch.shadow_msr |= MSR_SPE;
+ preempt_enable();
+}
+
+static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->arch.shared->msr & MSR_SPE) {
+ if (!(vcpu->arch.shadow_msr & MSR_SPE))
+ kvmppc_vcpu_enable_spe(vcpu);
+ } else if (vcpu->arch.shadow_msr & MSR_SPE) {
+ kvmppc_vcpu_disable_spe(vcpu);
+ }
+}
+#else
+static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
+{
+}
+#endif
+
+/*
+ * Helper function for "full" MSR writes. No need to call this if only
+ * EE/CE/ME/DE/RI are changing.
+ */
+void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
+{
+ u32 old_msr = vcpu->arch.shared->msr;
+
+ vcpu->arch.shared->msr = new_msr;
+
+ kvmppc_mmu_msr_notify(vcpu, old_msr);
+
+ if (vcpu->arch.shared->msr & MSR_WE) {
+ kvm_vcpu_block(vcpu);
+ kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
+ };
+
+ kvmppc_vcpu_sync_spe(vcpu);
+}
+
static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
unsigned int priority)
{
@@ -257,6 +312,19 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
vcpu->arch.shared->int_pending = 0;
}
+int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+ int ret;
+
+ local_irq_disable();
+ kvm_guest_enter();
+ ret = __kvmppc_vcpu_run(kvm_run, vcpu);
+ kvm_guest_exit();
+ local_irq_enable();
+
+ return ret;
+}
+
/**
* kvmppc_handle_exit
*
@@ -344,10 +412,16 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = RESUME_GUEST;
break;
- case BOOKE_INTERRUPT_SPE_UNAVAIL:
- kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_UNAVAIL);
+#ifdef CONFIG_SPE
+ case BOOKE_INTERRUPT_SPE_UNAVAIL: {
+ if (vcpu->arch.shared->msr & MSR_SPE)
+ kvmppc_vcpu_enable_spe(vcpu);
+ else
+ kvmppc_booke_queue_irqprio(vcpu,
+ BOOKE_IRQPRIO_SPE_UNAVAIL);
r = RESUME_GUEST;
break;
+ }
case BOOKE_INTERRUPT_SPE_FP_DATA:
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA);
@@ -358,6 +432,28 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND);
r = RESUME_GUEST;
break;
+#else
+ case BOOKE_INTERRUPT_SPE_UNAVAIL:
+ /*
+ * Guest wants SPE, but host kernel doesn't support it. Send
+ * an "unimplemented operation" program check to the guest.
+ */
+ kvmppc_core_queue_program(vcpu, ESR_PUO | ESR_SPV);
+ r = RESUME_GUEST;
+ break;
+
+ /*
+ * These really should never happen without CONFIG_SPE,
+ * as we should never enable the real MSR[SPE] in the guest.
+ */
+ case BOOKE_INTERRUPT_SPE_FP_DATA:
+ case BOOKE_INTERRUPT_SPE_FP_ROUND:
+ printk(KERN_CRIT "%s: unexpected SPE interrupt %u at %08lx\n",
+ __func__, exit_nr, vcpu->arch.pc);
+ run->hw.hardware_exit_reason = exit_nr;
+ r = RESUME_HOST;
+ break;
+#endif
case BOOKE_INTERRUPT_DATA_STORAGE:
kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
@@ -392,6 +488,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
gpa_t gpaddr;
gfn_t gfn;
+#ifdef CONFIG_KVM_E500
+ if (!(vcpu->arch.shared->msr & MSR_PR) &&
+ (eaddr & PAGE_MASK) == vcpu->arch.magic_page_ea) {
+ kvmppc_map_magic(vcpu);
+ kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
+ r = RESUME_GUEST;
+
+ break;
+ }
+#endif
+
/* Check the guest TLB. */
gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
if (gtlb_index < 0) {
@@ -514,6 +621,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
vcpu->arch.pc = 0;
vcpu->arch.shared->msr = 0;
+ vcpu->arch.shadow_msr = MSR_USER | MSR_DE | MSR_IS | MSR_DS;
kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
vcpu->arch.shadow_pid = 1;
@@ -770,6 +878,26 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
return -ENOTSUPP;
}
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem)
+{
+ return 0;
+}
+
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem)
+{
+}
+
+int kvmppc_core_init_vm(struct kvm *kvm)
+{
+ return 0;
+}
+
+void kvmppc_core_destroy_vm(struct kvm *kvm)
+{
+}
+
int __init kvmppc_booke_init(void)
{
unsigned long ivor[16];
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index 492bb7030358..8e1fe33d64e5 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -52,24 +52,19 @@
extern unsigned long kvmppc_booke_handlers;
-/* Helper function for "full" MSR writes. No need to call this if only EE is
- * changing. */
-static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
-{
- if ((new_msr & MSR_PR) != (vcpu->arch.shared->msr & MSR_PR))
- kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
-
- vcpu->arch.shared->msr = new_msr;
-
- if (vcpu->arch.shared->msr & MSR_WE) {
- kvm_vcpu_block(vcpu);
- kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
- };
-}
+void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
+void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int inst, int *advance);
int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt);
int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs);
+/* low-level asm code to transfer guest state */
+void kvmppc_load_guest_spe(struct kvm_vcpu *vcpu);
+void kvmppc_save_guest_spe(struct kvm_vcpu *vcpu);
+
+/* high-level function, manages flags, host state */
+void kvmppc_vcpu_disable_spe(struct kvm_vcpu *vcpu);
+
#endif /* __KVM_BOOKE_H__ */
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index b58ccae95904..42f2fb1f66e9 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -13,6 +13,7 @@
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright IBM Corp. 2007
+ * Copyright 2011 Freescale Semiconductor, Inc.
*
* Authors: Hollis Blanchard <hollisb@us.ibm.com>
*/
@@ -24,8 +25,6 @@
#include <asm/page.h>
#include <asm/asm-offsets.h>
-#define KVMPPC_MSR_MASK (MSR_CE|MSR_EE|MSR_PR|MSR_DE|MSR_ME|MSR_IS|MSR_DS)
-
#define VCPU_GPR(n) (VCPU_GPRS + (n * 4))
/* The host stack layout: */
@@ -192,6 +191,12 @@ _GLOBAL(kvmppc_resume_host)
lwz r3, VCPU_HOST_PID(r4)
mtspr SPRN_PID, r3
+#ifdef CONFIG_FSL_BOOKE
+ /* we cheat and know that Linux doesn't use PID1 which is always 0 */
+ lis r3, 0
+ mtspr SPRN_PID1, r3
+#endif
+
/* Restore host IVPR before re-enabling interrupts. We cheat and know
* that Linux IVPR is always 0xc0000000. */
lis r3, 0xc000
@@ -241,6 +246,14 @@ _GLOBAL(kvmppc_resume_host)
heavyweight_exit:
/* Not returning to guest. */
+#ifdef CONFIG_SPE
+ /* save guest SPEFSCR and load host SPEFSCR */
+ mfspr r9, SPRN_SPEFSCR
+ stw r9, VCPU_SPEFSCR(r4)
+ lwz r9, VCPU_HOST_SPEFSCR(r4)
+ mtspr SPRN_SPEFSCR, r9
+#endif
+
/* We already saved guest volatile register state; now save the
* non-volatiles. */
stw r15, VCPU_GPR(r15)(r4)
@@ -342,6 +355,14 @@ _GLOBAL(__kvmppc_vcpu_run)
lwz r30, VCPU_GPR(r30)(r4)
lwz r31, VCPU_GPR(r31)(r4)
+#ifdef CONFIG_SPE
+ /* save host SPEFSCR and load guest SPEFSCR */
+ mfspr r3, SPRN_SPEFSCR
+ stw r3, VCPU_HOST_SPEFSCR(r4)
+ lwz r3, VCPU_SPEFSCR(r4)
+ mtspr SPRN_SPEFSCR, r3
+#endif
+
lightweight_exit:
stw r2, HOST_R2(r1)
@@ -350,6 +371,11 @@ lightweight_exit:
lwz r3, VCPU_SHADOW_PID(r4)
mtspr SPRN_PID, r3
+#ifdef CONFIG_FSL_BOOKE
+ lwz r3, VCPU_SHADOW_PID1(r4)
+ mtspr SPRN_PID1, r3
+#endif
+
#ifdef CONFIG_44x
iccci 0, 0 /* XXX hack */
#endif
@@ -405,20 +431,17 @@ lightweight_exit:
/* Finish loading guest volatiles and jump to guest. */
lwz r3, VCPU_CTR(r4)
+ lwz r5, VCPU_CR(r4)
+ lwz r6, VCPU_PC(r4)
+ lwz r7, VCPU_SHADOW_MSR(r4)
mtctr r3
- lwz r3, VCPU_CR(r4)
- mtcr r3
+ mtcr r5
+ mtsrr0 r6
+ mtsrr1 r7
lwz r5, VCPU_GPR(r5)(r4)
lwz r6, VCPU_GPR(r6)(r4)
lwz r7, VCPU_GPR(r7)(r4)
lwz r8, VCPU_GPR(r8)(r4)
- lwz r3, VCPU_PC(r4)
- mtsrr0 r3
- lwz r3, VCPU_SHARED(r4)
- lwz r3, (VCPU_SHARED_MSR + 4)(r3)
- oris r3, r3, KVMPPC_MSR_MASK@h
- ori r3, r3, KVMPPC_MSR_MASK@l
- mtsrr1 r3
/* Clear any debug events which occurred since we disabled MSR[DE].
* XXX This gives us a 3-instruction window in which a breakpoint
@@ -430,3 +453,24 @@ lightweight_exit:
lwz r3, VCPU_GPR(r3)(r4)
lwz r4, VCPU_GPR(r4)(r4)
rfi
+
+#ifdef CONFIG_SPE
+_GLOBAL(kvmppc_save_guest_spe)
+ cmpi 0,r3,0
+ beqlr-
+ SAVE_32EVRS(0, r4, r3, VCPU_EVR)
+ evxor evr6, evr6, evr6
+ evmwumiaa evr6, evr6, evr6
+ li r4,VCPU_ACC
+ evstddx evr6, r4, r3 /* save acc */
+ blr
+
+_GLOBAL(kvmppc_load_guest_spe)
+ cmpi 0,r3,0
+ beqlr-
+ li r4,VCPU_ACC
+ evlddx evr6,r4,r3
+ evmra evr6,evr6 /* load acc */
+ REST_32EVRS(0, r4, r3, VCPU_EVR)
+ blr
+#endif
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 318dbc61ba44..797a7447c268 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Yu Liu, <yu.liu@freescale.com>
*
@@ -41,6 +41,11 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
{
kvmppc_e500_tlb_put(vcpu);
+
+#ifdef CONFIG_SPE
+ if (vcpu->arch.shadow_msr & MSR_SPE)
+ kvmppc_vcpu_disable_spe(vcpu);
+#endif
}
int kvmppc_core_check_processor_compat(void)
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index 69cd665a0caf..d48ae396f41e 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -81,8 +81,12 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
kvmppc_set_pid(vcpu, spr_val);
break;
case SPRN_PID1:
+ if (spr_val != 0)
+ return EMULATE_FAIL;
vcpu_e500->pid[1] = spr_val; break;
case SPRN_PID2:
+ if (spr_val != 0)
+ return EMULATE_FAIL;
vcpu_e500->pid[2] = spr_val; break;
case SPRN_MAS0:
vcpu_e500->mas0 = spr_val; break;
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index b18fe353397d..13c432ea2fa8 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -28,8 +28,196 @@
#define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1)
+struct id {
+ unsigned long val;
+ struct id **pentry;
+};
+
+#define NUM_TIDS 256
+
+/*
+ * This table provide mappings from:
+ * (guestAS,guestTID,guestPR) --> ID of physical cpu
+ * guestAS [0..1]
+ * guestTID [0..255]
+ * guestPR [0..1]
+ * ID [1..255]
+ * Each vcpu keeps one vcpu_id_table.
+ */
+struct vcpu_id_table {
+ struct id id[2][NUM_TIDS][2];
+};
+
+/*
+ * This table provide reversed mappings of vcpu_id_table:
+ * ID --> address of vcpu_id_table item.
+ * Each physical core has one pcpu_id_table.
+ */
+struct pcpu_id_table {
+ struct id *entry[NUM_TIDS];
+};
+
+static DEFINE_PER_CPU(struct pcpu_id_table, pcpu_sids);
+
+/* This variable keeps last used shadow ID on local core.
+ * The valid range of shadow ID is [1..255] */
+static DEFINE_PER_CPU(unsigned long, pcpu_last_used_sid);
+
static unsigned int tlb1_entry_num;
+/*
+ * Allocate a free shadow id and setup a valid sid mapping in given entry.
+ * A mapping is only valid when vcpu_id_table and pcpu_id_table are match.
+ *
+ * The caller must have preemption disabled, and keep it that way until
+ * it has finished with the returned shadow id (either written into the
+ * TLB or arch.shadow_pid, or discarded).
+ */
+static inline int local_sid_setup_one(struct id *entry)
+{
+ unsigned long sid;
+ int ret = -1;
+
+ sid = ++(__get_cpu_var(pcpu_last_used_sid));
+ if (sid < NUM_TIDS) {
+ __get_cpu_var(pcpu_sids).entry[sid] = entry;
+ entry->val = sid;
+ entry->pentry = &__get_cpu_var(pcpu_sids).entry[sid];
+ ret = sid;
+ }
+
+ /*
+ * If sid == NUM_TIDS, we've run out of sids. We return -1, and
+ * the caller will invalidate everything and start over.
+ *
+ * sid > NUM_TIDS indicates a race, which we disable preemption to
+ * avoid.
+ */
+ WARN_ON(sid > NUM_TIDS);
+
+ return ret;
+}
+
+/*
+ * Check if given entry contain a valid shadow id mapping.
+ * An ID mapping is considered valid only if
+ * both vcpu and pcpu know this mapping.
+ *
+ * The caller must have preemption disabled, and keep it that way until
+ * it has finished with the returned shadow id (either written into the
+ * TLB or arch.shadow_pid, or discarded).
+ */
+static inline int local_sid_lookup(struct id *entry)
+{
+ if (entry && entry->val != 0 &&
+ __get_cpu_var(pcpu_sids).entry[entry->val] == entry &&
+ entry->pentry == &__get_cpu_var(pcpu_sids).entry[entry->val])
+ return entry->val;
+ return -1;
+}
+
+/* Invalidate all id mappings on local core */
+static inline void local_sid_destroy_all(void)
+{
+ preempt_disable();
+ __get_cpu_var(pcpu_last_used_sid) = 0;
+ memset(&__get_cpu_var(pcpu_sids), 0, sizeof(__get_cpu_var(pcpu_sids)));
+ preempt_enable();
+}
+
+static void *kvmppc_e500_id_table_alloc(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+ vcpu_e500->idt = kzalloc(sizeof(struct vcpu_id_table), GFP_KERNEL);
+ return vcpu_e500->idt;
+}
+
+static void kvmppc_e500_id_table_free(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+ kfree(vcpu_e500->idt);
+}
+
+/* Invalidate all mappings on vcpu */
+static void kvmppc_e500_id_table_reset_all(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+ memset(vcpu_e500->idt, 0, sizeof(struct vcpu_id_table));
+
+ /* Update shadow pid when mappings are changed */
+ kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+}
+
+/* Invalidate one ID mapping on vcpu */
+static inline void kvmppc_e500_id_table_reset_one(
+ struct kvmppc_vcpu_e500 *vcpu_e500,
+ int as, int pid, int pr)
+{
+ struct vcpu_id_table *idt = vcpu_e500->idt;
+
+ BUG_ON(as >= 2);
+ BUG_ON(pid >= NUM_TIDS);
+ BUG_ON(pr >= 2);
+
+ idt->id[as][pid][pr].val = 0;
+ idt->id[as][pid][pr].pentry = NULL;
+
+ /* Update shadow pid when mappings are changed */
+ kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+}
+
+/*
+ * Map guest (vcpu,AS,ID,PR) to physical core shadow id.
+ * This function first lookup if a valid mapping exists,
+ * if not, then creates a new one.
+ *
+ * The caller must have preemption disabled, and keep it that way until
+ * it has finished with the returned shadow id (either written into the
+ * TLB or arch.shadow_pid, or discarded).
+ */
+static unsigned int kvmppc_e500_get_sid(struct kvmppc_vcpu_e500 *vcpu_e500,
+ unsigned int as, unsigned int gid,
+ unsigned int pr, int avoid_recursion)
+{
+ struct vcpu_id_table *idt = vcpu_e500->idt;
+ int sid;
+
+ BUG_ON(as >= 2);
+ BUG_ON(gid >= NUM_TIDS);
+ BUG_ON(pr >= 2);
+
+ sid = local_sid_lookup(&idt->id[as][gid][pr]);
+
+ while (sid <= 0) {
+ /* No mapping yet */
+ sid = local_sid_setup_one(&idt->id[as][gid][pr]);
+ if (sid <= 0) {
+ _tlbil_all();
+ local_sid_destroy_all();
+ }
+
+ /* Update shadow pid when mappings are changed */
+ if (!avoid_recursion)
+ kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+ }
+
+ return sid;
+}
+
+/* Map guest pid to shadow.
+ * We use PID to keep shadow of current guest non-zero PID,
+ * and use PID1 to keep shadow of guest zero PID.
+ * So that guest tlbe with TID=0 can be accessed at any time */
+void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+ preempt_disable();
+ vcpu_e500->vcpu.arch.shadow_pid = kvmppc_e500_get_sid(vcpu_e500,
+ get_cur_as(&vcpu_e500->vcpu),
+ get_cur_pid(&vcpu_e500->vcpu),
+ get_cur_pr(&vcpu_e500->vcpu), 1);
+ vcpu_e500->vcpu.arch.shadow_pid1 = kvmppc_e500_get_sid(vcpu_e500,
+ get_cur_as(&vcpu_e500->vcpu), 0,
+ get_cur_pr(&vcpu_e500->vcpu), 1);
+ preempt_enable();
+}
+
void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
@@ -41,25 +229,14 @@ void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
for (tlbsel = 0; tlbsel < 2; tlbsel++) {
printk("Guest TLB%d:\n", tlbsel);
- for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++) {
- tlbe = &vcpu_e500->guest_tlb[tlbsel][i];
+ for (i = 0; i < vcpu_e500->gtlb_size[tlbsel]; i++) {
+ tlbe = &vcpu_e500->gtlb_arch[tlbsel][i];
if (tlbe->mas1 & MAS1_VALID)
printk(" G[%d][%3d] | %08X | %08X | %08X | %08X |\n",
tlbsel, i, tlbe->mas1, tlbe->mas2,
tlbe->mas3, tlbe->mas7);
}
}
-
- for (tlbsel = 0; tlbsel < 2; tlbsel++) {
- printk("Shadow TLB%d:\n", tlbsel);
- for (i = 0; i < vcpu_e500->shadow_tlb_size[tlbsel]; i++) {
- tlbe = &vcpu_e500->shadow_tlb[tlbsel][i];
- if (tlbe->mas1 & MAS1_VALID)
- printk(" S[%d][%3d] | %08X | %08X | %08X | %08X |\n",
- tlbsel, i, tlbe->mas1, tlbe->mas2,
- tlbe->mas3, tlbe->mas7);
- }
- }
}
static inline unsigned int tlb0_get_next_victim(
@@ -67,16 +244,17 @@ static inline unsigned int tlb0_get_next_victim(
{
unsigned int victim;
- victim = vcpu_e500->guest_tlb_nv[0]++;
- if (unlikely(vcpu_e500->guest_tlb_nv[0] >= KVM_E500_TLB0_WAY_NUM))
- vcpu_e500->guest_tlb_nv[0] = 0;
+ victim = vcpu_e500->gtlb_nv[0]++;
+ if (unlikely(vcpu_e500->gtlb_nv[0] >= KVM_E500_TLB0_WAY_NUM))
+ vcpu_e500->gtlb_nv[0] = 0;
return victim;
}
static inline unsigned int tlb1_max_shadow_size(void)
{
- return tlb1_entry_num - tlbcam_index;
+ /* reserve one entry for magic page */
+ return tlb1_entry_num - tlbcam_index - 1;
}
static inline int tlbe_is_writable(struct tlbe *tlbe)
@@ -112,72 +290,149 @@ static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode)
/*
* writing shadow tlb entry to host TLB
*/
-static inline void __write_host_tlbe(struct tlbe *stlbe)
+static inline void __write_host_tlbe(struct tlbe *stlbe, uint32_t mas0)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mtspr(SPRN_MAS0, mas0);
mtspr(SPRN_MAS1, stlbe->mas1);
mtspr(SPRN_MAS2, stlbe->mas2);
mtspr(SPRN_MAS3, stlbe->mas3);
mtspr(SPRN_MAS7, stlbe->mas7);
- __asm__ __volatile__ ("tlbwe\n" : : );
+ asm volatile("isync; tlbwe" : : : "memory");
+ local_irq_restore(flags);
}
static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
- int tlbsel, int esel)
+ int tlbsel, int esel, struct tlbe *stlbe)
{
- struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
-
- local_irq_disable();
if (tlbsel == 0) {
- __write_host_tlbe(stlbe);
+ __write_host_tlbe(stlbe,
+ MAS0_TLBSEL(0) |
+ MAS0_ESEL(esel & (KVM_E500_TLB0_WAY_NUM - 1)));
} else {
- unsigned register mas0;
-
- mas0 = mfspr(SPRN_MAS0);
-
- mtspr(SPRN_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(to_htlb1_esel(esel)));
- __write_host_tlbe(stlbe);
-
- mtspr(SPRN_MAS0, mas0);
+ __write_host_tlbe(stlbe,
+ MAS0_TLBSEL(1) |
+ MAS0_ESEL(to_htlb1_esel(esel)));
}
- local_irq_enable();
+ trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
+ stlbe->mas3, stlbe->mas7);
+}
+
+void kvmppc_map_magic(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+ struct tlbe magic;
+ ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
+ unsigned int stid;
+ pfn_t pfn;
+
+ pfn = (pfn_t)virt_to_phys((void *)shared_page) >> PAGE_SHIFT;
+ get_page(pfn_to_page(pfn));
+
+ preempt_disable();
+ stid = kvmppc_e500_get_sid(vcpu_e500, 0, 0, 0, 0);
+
+ magic.mas1 = MAS1_VALID | MAS1_TS | MAS1_TID(stid) |
+ MAS1_TSIZE(BOOK3E_PAGESZ_4K);
+ magic.mas2 = vcpu->arch.magic_page_ea | MAS2_M;
+ magic.mas3 = (pfn << PAGE_SHIFT) |
+ MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
+ magic.mas7 = pfn >> (32 - PAGE_SHIFT);
+
+ __write_host_tlbe(&magic, MAS0_TLBSEL(1) | MAS0_ESEL(tlbcam_index));
+ preempt_enable();
}
void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
- int i;
- unsigned register mas0;
-
- /* Load all valid TLB1 entries to reduce guest tlb miss fault */
- local_irq_disable();
- mas0 = mfspr(SPRN_MAS0);
- for (i = 0; i < tlb1_max_shadow_size(); i++) {
- struct tlbe *stlbe = &vcpu_e500->shadow_tlb[1][i];
-
- if (get_tlb_v(stlbe)) {
- mtspr(SPRN_MAS0, MAS0_TLBSEL(1)
- | MAS0_ESEL(to_htlb1_esel(i)));
- __write_host_tlbe(stlbe);
- }
- }
- mtspr(SPRN_MAS0, mas0);
- local_irq_enable();
+
+ /* Shadow PID may be expired on local core */
+ kvmppc_e500_recalc_shadow_pid(vcpu_e500);
}
void kvmppc_e500_tlb_put(struct kvm_vcpu *vcpu)
{
- _tlbil_all();
+}
+
+static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
+ int tlbsel, int esel)
+{
+ struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+ struct vcpu_id_table *idt = vcpu_e500->idt;
+ unsigned int pr, tid, ts, pid;
+ u32 val, eaddr;
+ unsigned long flags;
+
+ ts = get_tlb_ts(gtlbe);
+ tid = get_tlb_tid(gtlbe);
+
+ preempt_disable();
+
+ /* One guest ID may be mapped to two shadow IDs */
+ for (pr = 0; pr < 2; pr++) {
+ /*
+ * The shadow PID can have a valid mapping on at most one
+ * host CPU. In the common case, it will be valid on this
+ * CPU, in which case (for TLB0) we do a local invalidation
+ * of the specific address.
+ *
+ * If the shadow PID is not valid on the current host CPU, or
+ * if we're invalidating a TLB1 entry, we invalidate the
+ * entire shadow PID.
+ */
+ if (tlbsel == 1 ||
+ (pid = local_sid_lookup(&idt->id[ts][tid][pr])) <= 0) {
+ kvmppc_e500_id_table_reset_one(vcpu_e500, ts, tid, pr);
+ continue;
+ }
+
+ /*
+ * The guest is invalidating a TLB0 entry which is in a PID
+ * that has a valid shadow mapping on this host CPU. We
+ * search host TLB0 to invalidate it's shadow TLB entry,
+ * similar to __tlbil_va except that we need to look in AS1.
+ */
+ val = (pid << MAS6_SPID_SHIFT) | MAS6_SAS;
+ eaddr = get_tlb_eaddr(gtlbe);
+
+ local_irq_save(flags);
+
+ mtspr(SPRN_MAS6, val);
+ asm volatile("tlbsx 0, %[eaddr]" : : [eaddr] "r" (eaddr));
+ val = mfspr(SPRN_MAS1);
+ if (val & MAS1_VALID) {
+ mtspr(SPRN_MAS1, val & ~MAS1_VALID);
+ asm volatile("tlbwe");
+ }
+
+ local_irq_restore(flags);
+ }
+
+ preempt_enable();
}
/* Search the guest TLB for a matching entry. */
static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
gva_t eaddr, int tlbsel, unsigned int pid, int as)
{
+ int size = vcpu_e500->gtlb_size[tlbsel];
+ int set_base;
int i;
- /* XXX Replace loop with fancy data structures. */
- for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++) {
- struct tlbe *tlbe = &vcpu_e500->guest_tlb[tlbsel][i];
+ if (tlbsel == 0) {
+ int mask = size / KVM_E500_TLB0_WAY_NUM - 1;
+ set_base = (eaddr >> PAGE_SHIFT) & mask;
+ set_base *= KVM_E500_TLB0_WAY_NUM;
+ size = KVM_E500_TLB0_WAY_NUM;
+ } else {
+ set_base = 0;
+ }
+
+ for (i = 0; i < size; i++) {
+ struct tlbe *tlbe = &vcpu_e500->gtlb_arch[tlbsel][set_base + i];
unsigned int tid;
if (eaddr < get_tlb_eaddr(tlbe))
@@ -196,66 +451,32 @@ static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
if (get_tlb_ts(tlbe) != as && as != -1)
continue;
- return i;
+ return set_base + i;
}
return -1;
}
-static void kvmppc_e500_shadow_release(struct kvmppc_vcpu_e500 *vcpu_e500,
- int tlbsel, int esel)
-{
- struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
- struct page *page = vcpu_e500->shadow_pages[tlbsel][esel];
-
- if (page) {
- vcpu_e500->shadow_pages[tlbsel][esel] = NULL;
-
- if (get_tlb_v(stlbe)) {
- if (tlbe_is_writable(stlbe))
- kvm_release_page_dirty(page);
- else
- kvm_release_page_clean(page);
- }
- }
-}
-
-static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
- int tlbsel, int esel)
+static inline void kvmppc_e500_priv_setup(struct tlbe_priv *priv,
+ struct tlbe *gtlbe,
+ pfn_t pfn)
{
- struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
+ priv->pfn = pfn;
+ priv->flags = E500_TLB_VALID;
- kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel);
- stlbe->mas1 = 0;
- trace_kvm_stlb_inval(index_of(tlbsel, esel));
+ if (tlbe_is_writable(gtlbe))
+ priv->flags |= E500_TLB_DIRTY;
}
-static void kvmppc_e500_tlb1_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
- gva_t eaddr, gva_t eend, u32 tid)
+static inline void kvmppc_e500_priv_release(struct tlbe_priv *priv)
{
- unsigned int pid = tid & 0xff;
- unsigned int i;
-
- /* XXX Replace loop with fancy data structures. */
- for (i = 0; i < vcpu_e500->guest_tlb_size[1]; i++) {
- struct tlbe *stlbe = &vcpu_e500->shadow_tlb[1][i];
- unsigned int tid;
-
- if (!get_tlb_v(stlbe))
- continue;
-
- if (eend < get_tlb_eaddr(stlbe))
- continue;
+ if (priv->flags & E500_TLB_VALID) {
+ if (priv->flags & E500_TLB_DIRTY)
+ kvm_release_pfn_dirty(priv->pfn);
+ else
+ kvm_release_pfn_clean(priv->pfn);
- if (eaddr > get_tlb_end(stlbe))
- continue;
-
- tid = get_tlb_tid(stlbe);
- if (tid && (tid != pid))
- continue;
-
- kvmppc_e500_stlbe_invalidate(vcpu_e500, 1, i);
- write_host_tlbe(vcpu_e500, 1, i);
+ priv->flags = 0;
}
}
@@ -273,7 +494,7 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
tsized = (vcpu_e500->mas4 >> 7) & 0x1f;
vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
- | MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+ | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
vcpu_e500->mas1 = MAS1_VALID | (as ? MAS1_TS : 0)
| MAS1_TID(vcpu_e500->pid[pidsel])
| MAS1_TSIZE(tsized);
@@ -286,56 +507,154 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
vcpu_e500->mas7 = 0;
}
-static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
- u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel)
+static inline void kvmppc_e500_setup_stlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
+ struct tlbe *gtlbe, int tsize,
+ struct tlbe_priv *priv,
+ u64 gvaddr, struct tlbe *stlbe)
{
- struct page *new_page;
- struct tlbe *stlbe;
- hpa_t hpaddr;
-
- stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
-
- /* Get reference to new page. */
- new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn);
- if (is_error_page(new_page)) {
- printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n",
- (long)gfn);
- kvm_release_page_clean(new_page);
- return;
- }
- hpaddr = page_to_phys(new_page);
-
- /* Drop reference to old page. */
- kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel);
+ pfn_t pfn = priv->pfn;
+ unsigned int stid;
- vcpu_e500->shadow_pages[tlbsel][esel] = new_page;
+ stid = kvmppc_e500_get_sid(vcpu_e500, get_tlb_ts(gtlbe),
+ get_tlb_tid(gtlbe),
+ get_cur_pr(&vcpu_e500->vcpu), 0);
- /* Force TS=1 IPROT=0 TSIZE=4KB for all guest mappings. */
- stlbe->mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K)
- | MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
+ /* Force TS=1 IPROT=0 for all guest mappings. */
+ stlbe->mas1 = MAS1_TSIZE(tsize)
+ | MAS1_TID(stid) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
| e500_shadow_mas2_attrib(gtlbe->mas2,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
- stlbe->mas3 = (hpaddr & MAS3_RPN)
+ stlbe->mas3 = ((pfn << PAGE_SHIFT) & MAS3_RPN)
| e500_shadow_mas3_attrib(gtlbe->mas3,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
- stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
+ stlbe->mas7 = (pfn >> (32 - PAGE_SHIFT)) & MAS7_RPN;
+}
- trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
- stlbe->mas3, stlbe->mas7);
+
+static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
+ u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel,
+ struct tlbe *stlbe)
+{
+ struct kvm_memory_slot *slot;
+ unsigned long pfn, hva;
+ int pfnmap = 0;
+ int tsize = BOOK3E_PAGESZ_4K;
+ struct tlbe_priv *priv;
+
+ /*
+ * Translate guest physical to true physical, acquiring
+ * a page reference if it is normal, non-reserved memory.
+ *
+ * gfn_to_memslot() must succeed because otherwise we wouldn't
+ * have gotten this far. Eventually we should just pass the slot
+ * pointer through from the first lookup.
+ */
+ slot = gfn_to_memslot(vcpu_e500->vcpu.kvm, gfn);
+ hva = gfn_to_hva_memslot(slot, gfn);
+
+ if (tlbsel == 1) {
+ struct vm_area_struct *vma;
+ down_read(&current->mm->mmap_sem);
+
+ vma = find_vma(current->mm, hva);
+ if (vma && hva >= vma->vm_start &&
+ (vma->vm_flags & VM_PFNMAP)) {
+ /*
+ * This VMA is a physically contiguous region (e.g.
+ * /dev/mem) that bypasses normal Linux page
+ * management. Find the overlap between the
+ * vma and the memslot.
+ */
+
+ unsigned long start, end;
+ unsigned long slot_start, slot_end;
+
+ pfnmap = 1;
+
+ start = vma->vm_pgoff;
+ end = start +
+ ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT);
+
+ pfn = start + ((hva - vma->vm_start) >> PAGE_SHIFT);
+
+ slot_start = pfn - (gfn - slot->base_gfn);
+ slot_end = slot_start + slot->npages;
+
+ if (start < slot_start)
+ start = slot_start;
+ if (end > slot_end)
+ end = slot_end;
+
+ tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >>
+ MAS1_TSIZE_SHIFT;
+
+ /*
+ * e500 doesn't implement the lowest tsize bit,
+ * or 1K pages.
+ */
+ tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1);
+
+ /*
+ * Now find the largest tsize (up to what the guest
+ * requested) that will cover gfn, stay within the
+ * range, and for which gfn and pfn are mutually
+ * aligned.
+ */
+
+ for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) {
+ unsigned long gfn_start, gfn_end, tsize_pages;
+ tsize_pages = 1 << (tsize - 2);
+
+ gfn_start = gfn & ~(tsize_pages - 1);
+ gfn_end = gfn_start + tsize_pages;
+
+ if (gfn_start + pfn - gfn < start)
+ continue;
+ if (gfn_end + pfn - gfn > end)
+ continue;
+ if ((gfn & (tsize_pages - 1)) !=
+ (pfn & (tsize_pages - 1)))
+ continue;
+
+ gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
+ pfn &= ~(tsize_pages - 1);
+ break;
+ }
+ }
+
+ up_read(&current->mm->mmap_sem);
+ }
+
+ if (likely(!pfnmap)) {
+ pfn = gfn_to_pfn_memslot(vcpu_e500->vcpu.kvm, slot, gfn);
+ if (is_error_pfn(pfn)) {
+ printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
+ (long)gfn);
+ kvm_release_pfn_clean(pfn);
+ return;
+ }
+ }
+
+ /* Drop old priv and setup new one. */
+ priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
+ kvmppc_e500_priv_release(priv);
+ kvmppc_e500_priv_setup(priv, gtlbe, pfn);
+
+ kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, tsize, priv, gvaddr, stlbe);
}
/* XXX only map the one-one case, for now use TLB0 */
-static int kvmppc_e500_stlbe_map(struct kvmppc_vcpu_e500 *vcpu_e500,
- int tlbsel, int esel)
+static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500,
+ int esel, struct tlbe *stlbe)
{
struct tlbe *gtlbe;
- gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+ gtlbe = &vcpu_e500->gtlb_arch[0][esel];
kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe),
get_tlb_raddr(gtlbe) >> PAGE_SHIFT,
- gtlbe, tlbsel, esel);
+ gtlbe, 0, esel, stlbe);
return esel;
}
@@ -344,53 +663,37 @@ static int kvmppc_e500_stlbe_map(struct kvmppc_vcpu_e500 *vcpu_e500,
* the shadow TLB. */
/* XXX for both one-one and one-to-many , for now use TLB1 */
static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
- u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe)
+ u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, struct tlbe *stlbe)
{
unsigned int victim;
- victim = vcpu_e500->guest_tlb_nv[1]++;
+ victim = vcpu_e500->gtlb_nv[1]++;
- if (unlikely(vcpu_e500->guest_tlb_nv[1] >= tlb1_max_shadow_size()))
- vcpu_e500->guest_tlb_nv[1] = 0;
+ if (unlikely(vcpu_e500->gtlb_nv[1] >= tlb1_max_shadow_size()))
+ vcpu_e500->gtlb_nv[1] = 0;
- kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, victim);
+ kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, victim, stlbe);
return victim;
}
-/* Invalidate all guest kernel mappings when enter usermode,
- * so that when they fault back in they will get the
- * proper permission bits. */
-void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
+void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
{
- if (usermode) {
- struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
- int i;
-
- /* XXX Replace loop with fancy data structures. */
- for (i = 0; i < tlb1_max_shadow_size(); i++)
- kvmppc_e500_stlbe_invalidate(vcpu_e500, 1, i);
+ struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
- _tlbil_all();
- }
+ /* Recalc shadow pid since MSR changes */
+ kvmppc_e500_recalc_shadow_pid(vcpu_e500);
}
-static int kvmppc_e500_gtlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
- int tlbsel, int esel)
+static inline int kvmppc_e500_gtlbe_invalidate(
+ struct kvmppc_vcpu_e500 *vcpu_e500,
+ int tlbsel, int esel)
{
- struct tlbe *gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+ struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
if (unlikely(get_tlb_iprot(gtlbe)))
return -1;
- if (tlbsel == 1) {
- kvmppc_e500_tlb1_invalidate(vcpu_e500, get_tlb_eaddr(gtlbe),
- get_tlb_end(gtlbe),
- get_tlb_tid(gtlbe));
- } else {
- kvmppc_e500_stlbe_invalidate(vcpu_e500, tlbsel, esel);
- }
-
gtlbe->mas1 = 0;
return 0;
@@ -401,13 +704,14 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
int esel;
if (value & MMUCSR0_TLB0FI)
- for (esel = 0; esel < vcpu_e500->guest_tlb_size[0]; esel++)
+ for (esel = 0; esel < vcpu_e500->gtlb_size[0]; esel++)
kvmppc_e500_gtlbe_invalidate(vcpu_e500, 0, esel);
if (value & MMUCSR0_TLB1FI)
- for (esel = 0; esel < vcpu_e500->guest_tlb_size[1]; esel++)
+ for (esel = 0; esel < vcpu_e500->gtlb_size[1]; esel++)
kvmppc_e500_gtlbe_invalidate(vcpu_e500, 1, esel);
- _tlbil_all();
+ /* Invalidate all vcpu id mappings */
+ kvmppc_e500_id_table_reset_all(vcpu_e500);
return EMULATE_DONE;
}
@@ -428,7 +732,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
if (ia) {
/* invalidate all entries */
- for (esel = 0; esel < vcpu_e500->guest_tlb_size[tlbsel]; esel++)
+ for (esel = 0; esel < vcpu_e500->gtlb_size[tlbsel]; esel++)
kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
} else {
ea &= 0xfffff000;
@@ -438,7 +742,8 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
}
- _tlbil_all();
+ /* Invalidate all vcpu id mappings */
+ kvmppc_e500_id_table_reset_all(vcpu_e500);
return EMULATE_DONE;
}
@@ -452,9 +757,9 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
tlbsel = get_tlb_tlbsel(vcpu_e500);
esel = get_tlb_esel(vcpu_e500, tlbsel);
- gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+ gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
vcpu_e500->mas0 &= ~MAS0_NV(~0);
- vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+ vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
vcpu_e500->mas1 = gtlbe->mas1;
vcpu_e500->mas2 = gtlbe->mas2;
vcpu_e500->mas3 = gtlbe->mas3;
@@ -477,14 +782,14 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
for (tlbsel = 0; tlbsel < 2; tlbsel++) {
esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
if (esel >= 0) {
- gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+ gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
break;
}
}
if (gtlbe) {
vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel)
- | MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+ | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
vcpu_e500->mas1 = gtlbe->mas1;
vcpu_e500->mas2 = gtlbe->mas2;
vcpu_e500->mas3 = gtlbe->mas3;
@@ -497,7 +802,7 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0;
vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
- | MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+ | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
vcpu_e500->mas1 = (vcpu_e500->mas6 & MAS6_SPID0)
| (vcpu_e500->mas6 & (MAS6_SAS ? MAS1_TS : 0))
| (vcpu_e500->mas4 & MAS4_TSIZED(~0));
@@ -514,23 +819,16 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
- u64 eaddr;
- u64 raddr;
- u32 tid;
struct tlbe *gtlbe;
- int tlbsel, esel, stlbsel, sesel;
+ int tlbsel, esel;
tlbsel = get_tlb_tlbsel(vcpu_e500);
esel = get_tlb_esel(vcpu_e500, tlbsel);
- gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+ gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
- if (get_tlb_v(gtlbe) && tlbsel == 1) {
- eaddr = get_tlb_eaddr(gtlbe);
- tid = get_tlb_tid(gtlbe);
- kvmppc_e500_tlb1_invalidate(vcpu_e500, eaddr,
- get_tlb_end(gtlbe), tid);
- }
+ if (get_tlb_v(gtlbe))
+ kvmppc_e500_stlbe_invalidate(vcpu_e500, tlbsel, esel);
gtlbe->mas1 = vcpu_e500->mas1;
gtlbe->mas2 = vcpu_e500->mas2;
@@ -542,6 +840,12 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
/* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
if (tlbe_is_host_safe(vcpu, gtlbe)) {
+ struct tlbe stlbe;
+ int stlbsel, sesel;
+ u64 eaddr;
+ u64 raddr;
+
+ preempt_disable();
switch (tlbsel) {
case 0:
/* TLB0 */
@@ -549,7 +853,7 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
gtlbe->mas1 |= MAS1_TSIZE(BOOK3E_PAGESZ_4K);
stlbsel = 0;
- sesel = kvmppc_e500_stlbe_map(vcpu_e500, 0, esel);
+ sesel = kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
break;
@@ -564,13 +868,14 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
* are mapped on the fly. */
stlbsel = 1;
sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr,
- raddr >> PAGE_SHIFT, gtlbe);
+ raddr >> PAGE_SHIFT, gtlbe, &stlbe);
break;
default:
BUG();
}
- write_host_tlbe(vcpu_e500, stlbsel, sesel);
+ write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
+ preempt_enable();
}
kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
@@ -610,7 +915,7 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index,
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
struct tlbe *gtlbe =
- &vcpu_e500->guest_tlb[tlbsel_of(index)][esel_of(index)];
+ &vcpu_e500->gtlb_arch[tlbsel_of(index)][esel_of(index)];
u64 pgmask = get_tlb_bytes(gtlbe) - 1;
return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
@@ -618,38 +923,37 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index,
void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
{
- struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
- int tlbsel, i;
-
- for (tlbsel = 0; tlbsel < 2; tlbsel++)
- for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++)
- kvmppc_e500_shadow_release(vcpu_e500, tlbsel, i);
-
- /* discard all guest mapping */
- _tlbil_all();
}
void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
unsigned int index)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+ struct tlbe_priv *priv;
+ struct tlbe *gtlbe, stlbe;
int tlbsel = tlbsel_of(index);
int esel = esel_of(index);
int stlbsel, sesel;
+ gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+
+ preempt_disable();
switch (tlbsel) {
case 0:
stlbsel = 0;
sesel = esel;
+ priv = &vcpu_e500->gtlb_priv[stlbsel][sesel];
+
+ kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, BOOK3E_PAGESZ_4K,
+ priv, eaddr, &stlbe);
break;
case 1: {
gfn_t gfn = gpaddr >> PAGE_SHIFT;
- struct tlbe *gtlbe
- = &vcpu_e500->guest_tlb[tlbsel][esel];
stlbsel = 1;
- sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr, gfn, gtlbe);
+ sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr, gfn,
+ gtlbe, &stlbe);
break;
}
@@ -657,7 +961,9 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
BUG();
break;
}
- write_host_tlbe(vcpu_e500, stlbsel, sesel);
+
+ write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
+ preempt_enable();
}
int kvmppc_e500_tlb_search(struct kvm_vcpu *vcpu,
@@ -679,8 +985,10 @@ void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
- vcpu_e500->pid[0] = vcpu->arch.shadow_pid =
- vcpu->arch.pid = pid;
+ if (vcpu->arch.pid != pid) {
+ vcpu_e500->pid[0] = vcpu->arch.pid = pid;
+ kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+ }
}
void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)
@@ -688,14 +996,14 @@ void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)
struct tlbe *tlbe;
/* Insert large initial mapping for guest. */
- tlbe = &vcpu_e500->guest_tlb[1][0];
+ tlbe = &vcpu_e500->gtlb_arch[1][0];
tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_256M);
tlbe->mas2 = 0;
tlbe->mas3 = E500_TLB_SUPER_PERM_MASK;
tlbe->mas7 = 0;
/* 4K map for serial output. Used by kernel wrapper. */
- tlbe = &vcpu_e500->guest_tlb[1][1];
+ tlbe = &vcpu_e500->gtlb_arch[1][1];
tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_4K);
tlbe->mas2 = (0xe0004500 & 0xFFFFF000) | MAS2_I | MAS2_G;
tlbe->mas3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK;
@@ -706,68 +1014,64 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
{
tlb1_entry_num = mfspr(SPRN_TLB1CFG) & 0xFFF;
- vcpu_e500->guest_tlb_size[0] = KVM_E500_TLB0_SIZE;
- vcpu_e500->guest_tlb[0] =
+ vcpu_e500->gtlb_size[0] = KVM_E500_TLB0_SIZE;
+ vcpu_e500->gtlb_arch[0] =
kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
- if (vcpu_e500->guest_tlb[0] == NULL)
+ if (vcpu_e500->gtlb_arch[0] == NULL)
goto err_out;
- vcpu_e500->shadow_tlb_size[0] = KVM_E500_TLB0_SIZE;
- vcpu_e500->shadow_tlb[0] =
- kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
- if (vcpu_e500->shadow_tlb[0] == NULL)
- goto err_out_guest0;
-
- vcpu_e500->guest_tlb_size[1] = KVM_E500_TLB1_SIZE;
- vcpu_e500->guest_tlb[1] =
+ vcpu_e500->gtlb_size[1] = KVM_E500_TLB1_SIZE;
+ vcpu_e500->gtlb_arch[1] =
kzalloc(sizeof(struct tlbe) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
- if (vcpu_e500->guest_tlb[1] == NULL)
- goto err_out_shadow0;
+ if (vcpu_e500->gtlb_arch[1] == NULL)
+ goto err_out_guest0;
- vcpu_e500->shadow_tlb_size[1] = tlb1_entry_num;
- vcpu_e500->shadow_tlb[1] =
- kzalloc(sizeof(struct tlbe) * tlb1_entry_num, GFP_KERNEL);
- if (vcpu_e500->shadow_tlb[1] == NULL)
+ vcpu_e500->gtlb_priv[0] = (struct tlbe_priv *)
+ kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
+ if (vcpu_e500->gtlb_priv[0] == NULL)
goto err_out_guest1;
+ vcpu_e500->gtlb_priv[1] = (struct tlbe_priv *)
+ kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
- vcpu_e500->shadow_pages[0] = (struct page **)
- kzalloc(sizeof(struct page *) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
- if (vcpu_e500->shadow_pages[0] == NULL)
- goto err_out_shadow1;
+ if (vcpu_e500->gtlb_priv[1] == NULL)
+ goto err_out_priv0;
- vcpu_e500->shadow_pages[1] = (struct page **)
- kzalloc(sizeof(struct page *) * tlb1_entry_num, GFP_KERNEL);
- if (vcpu_e500->shadow_pages[1] == NULL)
- goto err_out_page0;
+ if (kvmppc_e500_id_table_alloc(vcpu_e500) == NULL)
+ goto err_out_priv1;
/* Init TLB configuration register */
vcpu_e500->tlb0cfg = mfspr(SPRN_TLB0CFG) & ~0xfffUL;
- vcpu_e500->tlb0cfg |= vcpu_e500->guest_tlb_size[0];
+ vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_size[0];
vcpu_e500->tlb1cfg = mfspr(SPRN_TLB1CFG) & ~0xfffUL;
- vcpu_e500->tlb1cfg |= vcpu_e500->guest_tlb_size[1];
+ vcpu_e500->tlb1cfg |= vcpu_e500->gtlb_size[1];
return 0;
-err_out_page0:
- kfree(vcpu_e500->shadow_pages[0]);
-err_out_shadow1:
- kfree(vcpu_e500->shadow_tlb[1]);
+err_out_priv1:
+ kfree(vcpu_e500->gtlb_priv[1]);
+err_out_priv0:
+ kfree(vcpu_e500->gtlb_priv[0]);
err_out_guest1:
- kfree(vcpu_e500->guest_tlb[1]);
-err_out_shadow0:
- kfree(vcpu_e500->shadow_tlb[0]);
+ kfree(vcpu_e500->gtlb_arch[1]);
err_out_guest0:
- kfree(vcpu_e500->guest_tlb[0]);
+ kfree(vcpu_e500->gtlb_arch[0]);
err_out:
return -1;
}
void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
{
- kfree(vcpu_e500->shadow_pages[1]);
- kfree(vcpu_e500->shadow_pages[0]);
- kfree(vcpu_e500->shadow_tlb[1]);
- kfree(vcpu_e500->guest_tlb[1]);
- kfree(vcpu_e500->shadow_tlb[0]);
- kfree(vcpu_e500->guest_tlb[0]);
+ int stlbsel, i;
+
+ /* release all privs */
+ for (stlbsel = 0; stlbsel < 2; stlbsel++)
+ for (i = 0; i < vcpu_e500->gtlb_size[stlbsel]; i++) {
+ struct tlbe_priv *priv =
+ &vcpu_e500->gtlb_priv[stlbsel][i];
+ kvmppc_e500_priv_release(priv);
+ }
+
+ kvmppc_e500_id_table_free(vcpu_e500);
+ kfree(vcpu_e500->gtlb_arch[1]);
+ kfree(vcpu_e500->gtlb_arch[0]);
}
diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h
index 458946b4775d..59b88e99a235 100644
--- a/arch/powerpc/kvm/e500_tlb.h
+++ b/arch/powerpc/kvm/e500_tlb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Yu Liu, yu.liu@freescale.com
*
@@ -55,6 +55,7 @@ extern void kvmppc_e500_tlb_load(struct kvm_vcpu *, int);
extern int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *);
extern void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *);
extern void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *);
+extern void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *);
/* TLB helper functions */
static inline unsigned int get_tlb_size(const struct tlbe *tlbe)
@@ -110,6 +111,16 @@ static inline unsigned int get_cur_pid(struct kvm_vcpu *vcpu)
return vcpu->arch.pid & 0xff;
}
+static inline unsigned int get_cur_as(struct kvm_vcpu *vcpu)
+{
+ return !!(vcpu->arch.shared->msr & (MSR_IS | MSR_DS));
+}
+
+static inline unsigned int get_cur_pr(struct kvm_vcpu *vcpu)
+{
+ return !!(vcpu->arch.shared->msr & MSR_PR);
+}
+
static inline unsigned int get_cur_spid(
const struct kvmppc_vcpu_e500 *vcpu_e500)
{
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 616dd516ca1f..a107c9be0fb1 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -30,6 +30,7 @@
#include <asm/uaccess.h>
#include <asm/kvm_ppc.h>
#include <asm/tlbflush.h>
+#include <asm/cputhreads.h>
#include "timing.h"
#include "../mm/mmu_decl.h"
@@ -38,8 +39,12 @@
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)
@@ -73,7 +78,8 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
}
case HC_VENDOR_KVM | KVM_HC_FEATURES:
r = HC_EV_SUCCESS;
-#if defined(CONFIG_PPC_BOOK3S) /* XXX Missing magic page on BookE */
+#if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500)
+ /* XXX Missing magic page on 44x */
r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
#endif
@@ -147,7 +153,7 @@ void kvm_arch_check_processor_compat(void *rtn)
int kvm_arch_init_vm(struct kvm *kvm)
{
- return 0;
+ return kvmppc_core_init_vm(kvm);
}
void kvm_arch_destroy_vm(struct kvm *kvm)
@@ -163,6 +169,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
kvm->vcpus[i] = NULL;
atomic_set(&kvm->online_vcpus, 0);
+
+ kvmppc_core_destroy_vm(kvm);
+
mutex_unlock(&kvm->lock);
}
@@ -180,10 +189,13 @@ int kvm_dev_ioctl_check_extension(long ext)
#else
case KVM_CAP_PPC_SEGSTATE:
#endif
- case KVM_CAP_PPC_PAIRED_SINGLES:
case KVM_CAP_PPC_UNSET_IRQ:
case KVM_CAP_PPC_IRQ_LEVEL:
case KVM_CAP_ENABLE_CAP:
+ r = 1;
+ break;
+#ifndef CONFIG_KVM_BOOK3S_64_HV
+ case KVM_CAP_PPC_PAIRED_SINGLES:
case KVM_CAP_PPC_OSI:
case KVM_CAP_PPC_GET_PVINFO:
r = 1;
@@ -191,6 +203,21 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_COALESCED_MMIO:
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
break;
+#endif
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ case KVM_CAP_SPAPR_TCE:
+ r = 1;
+ break;
+ case KVM_CAP_PPC_SMT:
+ r = threads_per_core;
+ break;
+ case KVM_CAP_PPC_RMA:
+ r = 1;
+ /* PPC970 requires an RMA */
+ if (cpu_has_feature(CPU_FTR_ARCH_201))
+ r = 2;
+ break;
+#endif
default:
r = 0;
break;
@@ -211,7 +238,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
struct kvm_userspace_memory_region *mem,
int user_alloc)
{
- return 0;
+ return kvmppc_core_prepare_memory_region(kvm, mem);
}
void kvm_arch_commit_memory_region(struct kvm *kvm,
@@ -219,7 +246,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
struct kvm_memory_slot old,
int user_alloc)
{
- return;
+ kvmppc_core_commit_memory_region(kvm, mem);
}
@@ -287,6 +314,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
+ vcpu->arch.dec_expires = ~(u64)0;
#ifdef CONFIG_KVM_EXIT_TIMING
mutex_init(&vcpu->arch.exit_timing_lock);
@@ -313,6 +341,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
mtspr(SPRN_VRSAVE, vcpu->arch.vrsave);
#endif
kvmppc_core_vcpu_load(vcpu, cpu);
+ vcpu->cpu = smp_processor_id();
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -321,6 +350,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
#ifdef CONFIG_BOOKE
vcpu->arch.vrsave = mfspr(SPRN_VRSAVE);
#endif
+ vcpu->cpu = -1;
}
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
@@ -492,15 +522,18 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
for (i = 0; i < 32; i++)
kvmppc_set_gpr(vcpu, i, gprs[i]);
vcpu->arch.osi_needed = 0;
+ } else if (vcpu->arch.hcall_needed) {
+ int i;
+
+ kvmppc_set_gpr(vcpu, 3, run->papr_hcall.ret);
+ for (i = 0; i < 9; ++i)
+ kvmppc_set_gpr(vcpu, 4 + i, run->papr_hcall.args[i]);
+ vcpu->arch.hcall_needed = 0;
}
kvmppc_core_deliver_interrupts(vcpu);
- local_irq_disable();
- kvm_guest_enter();
- r = __kvmppc_vcpu_run(run, vcpu);
- kvm_guest_exit();
- local_irq_enable();
+ r = kvmppc_vcpu_run(run, vcpu);
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &sigsaved, NULL);
@@ -518,6 +551,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
if (waitqueue_active(&vcpu->wq)) {
wake_up_interruptible(&vcpu->wq);
vcpu->stat.halt_wakeup++;
+ } else if (vcpu->cpu != -1) {
+ smp_send_reschedule(vcpu->cpu);
}
return 0;
@@ -633,6 +668,29 @@ long kvm_arch_vm_ioctl(struct file *filp,
break;
}
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ case KVM_CREATE_SPAPR_TCE: {
+ struct kvm_create_spapr_tce create_tce;
+ struct kvm *kvm = filp->private_data;
+
+ r = -EFAULT;
+ if (copy_from_user(&create_tce, argp, sizeof(create_tce)))
+ goto out;
+ r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce);
+ goto out;
+ }
+
+ case KVM_ALLOCATE_RMA: {
+ struct kvm *kvm = filp->private_data;
+ struct kvm_allocate_rma rma;
+
+ r = kvm_vm_ioctl_allocate_rma(kvm, &rma);
+ if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma)))
+ r = -EFAULT;
+ break;
+ }
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
default:
r = -ENOTTY;
}
diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c
index 319177df9587..07b6110a4bb7 100644
--- a/arch/powerpc/kvm/timing.c
+++ b/arch/powerpc/kvm/timing.c
@@ -56,15 +56,6 @@ static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type)
{
u64 old;
- do_div(duration, tb_ticks_per_usec);
- if (unlikely(duration > 0xFFFFFFFF)) {
- printk(KERN_ERR"%s - duration too big -> overflow"
- " duration %lld type %d exit #%d\n",
- __func__, duration, type,
- vcpu->arch.timing_count_type[type]);
- return;
- }
-
mutex_lock(&vcpu->arch.exit_timing_lock);
vcpu->arch.timing_count_type[type]++;
diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h
index 3aca1b042b8c..b135d3d397db 100644
--- a/arch/powerpc/kvm/trace.h
+++ b/arch/powerpc/kvm/trace.h
@@ -103,7 +103,7 @@ TRACE_EVENT(kvm_gtlb_write,
* Book3S trace points *
*************************************************************************/
-#ifdef CONFIG_PPC_BOOK3S
+#ifdef CONFIG_KVM_BOOK3S_PR
TRACE_EVENT(kvm_book3s_exit,
TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
@@ -252,7 +252,7 @@ TRACE_EVENT(kvm_book3s_mmu_flush,
),
TP_fast_assign(
- __entry->count = vcpu->arch.hpte_cache_count;
+ __entry->count = to_book3s(vcpu)->hpte_cache_count;
__entry->p1 = p1;
__entry->p2 = p2;
__entry->type = type;
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index 024acab588fd..f60e006d90c3 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -186,10 +186,11 @@ void __init MMU_init_hw(void)
unsigned long __init mmu_mapin_ram(unsigned long top)
{
unsigned long addr;
+ unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);
/* Pin in enough TLBs to cover any lowmem not covered by the
* initial 256M mapping established in head_44x.S */
- for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
+ for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
addr += PPC_PIN_SIZE) {
if (mmu_has_feature(MMU_FTR_TYPE_47x))
ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
@@ -218,19 +219,25 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
{
+ u64 size;
+
+#ifndef CONFIG_RELOCATABLE
/* We don't currently support the first MEMBLOCK not mapping 0
* physical on those processors
*/
BUG_ON(first_memblock_base != 0);
+#endif
/* 44x has a 256M TLB entry pinned at boot */
- memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE));
+ size = (min_t(u64, first_memblock_size, PPC_PIN_SIZE));
+ memblock_set_current_limit(first_memblock_base + size);
}
#ifdef CONFIG_SMP
void __cpuinit mmu_init_secondary(int cpu)
{
unsigned long addr;
+ unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);
/* Pin in enough TLBs to cover any lowmem not covered by the
* initial 256M mapping established in head_44x.S
@@ -241,7 +248,7 @@ void __cpuinit mmu_init_secondary(int cpu)
* stack. current (r2) isn't initialized, smp_processor_id()
* will not work, current thread info isn't accessible, ...
*/
- for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
+ for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
addr += PPC_PIN_SIZE) {
if (mmu_has_feature(MMU_FTR_TYPE_47x))
ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ad35f66c69e8..5efe8c96d37f 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -174,7 +174,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
die("Weird page fault", regs, SIGSEGV);
}
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
/* When running in the kernel we expect faults to occur only to
* addresses in user space. All other faults represent errors in the
@@ -320,7 +320,7 @@ good_area:
}
if (ret & VM_FAULT_MAJOR) {
current->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
regs, address);
#ifdef CONFIG_PPC_SMLPAR
if (firmware_has_feature(FW_FEATURE_CMO)) {
@@ -331,7 +331,7 @@ good_area:
#endif
} else {
current->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
regs, address);
}
up_read(&mm->mmap_sem);
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index dfd764896db0..90039bc64119 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -37,7 +37,7 @@
#define HPTE_LOCK_BIT 3
-static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
+DEFINE_RAW_SPINLOCK(native_tlbie_lock);
static inline void __tlbie(unsigned long va, int psize, int ssize)
{
@@ -51,7 +51,7 @@ static inline void __tlbie(unsigned long va, int psize, int ssize)
va &= ~0xffful;
va |= ssize << 8;
asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
- : : "r" (va), "r"(0), "i" (CPU_FTR_HVMODE_206)
+ : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
: "memory");
break;
default:
@@ -61,7 +61,7 @@ static inline void __tlbie(unsigned long va, int psize, int ssize)
va |= ssize << 8;
va |= 1; /* L */
asm volatile(ASM_FTR_IFCLR("tlbie %0,1", PPC_TLBIE(%1,%0), %2)
- : : "r" (va), "r"(0), "i" (CPU_FTR_HVMODE_206)
+ : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
: "memory");
break;
}
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 5de0f254dbb5..c77fef56dad6 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -191,38 +191,6 @@ void __init *early_get_page(void)
return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
}
-/* Free up now-unused memory */
-static void free_sec(unsigned long start, unsigned long end, const char *name)
-{
- unsigned long cnt = 0;
-
- while (start < end) {
- ClearPageReserved(virt_to_page(start));
- init_page_count(virt_to_page(start));
- free_page(start);
- cnt++;
- start += PAGE_SIZE;
- }
- if (cnt) {
- printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name);
- totalram_pages += cnt;
- }
-}
-
-void free_initmem(void)
-{
-#define FREESEC(TYPE) \
- free_sec((unsigned long)(&__ ## TYPE ## _begin), \
- (unsigned long)(&__ ## TYPE ## _end), \
- #TYPE);
-
- printk ("Freeing unused kernel memory:");
- FREESEC(init);
- printk("\n");
- ppc_md.progress = NULL;
-#undef FREESEC
-}
-
#ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index f6dbb4c20e64..e94b57fb79a0 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -83,22 +83,6 @@ EXPORT_SYMBOL_GPL(memstart_addr);
phys_addr_t kernstart_addr;
EXPORT_SYMBOL_GPL(kernstart_addr);
-void free_initmem(void)
-{
- unsigned long addr;
-
- addr = (unsigned long)__init_begin;
- for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
- memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
- ClearPageReserved(virt_to_page(addr));
- init_page_count(virt_to_page(addr));
- free_page(addr);
- totalram_pages++;
- }
- printk ("Freeing unused kernel memory: %luk freed\n",
- ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10);
-}
-
static void pgd_ctor(void *addr)
{
memset(addr, 0, PGD_TABLE_SIZE);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 29d4dde65c45..c781bbcf7338 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -249,7 +249,7 @@ static int __init mark_nonram_nosave(void)
*/
void __init paging_init(void)
{
- unsigned long total_ram = memblock_phys_mem_size();
+ unsigned long long total_ram = memblock_phys_mem_size();
phys_addr_t top_of_ram = memblock_end_of_DRAM();
unsigned long max_zone_pfns[MAX_NR_ZONES];
@@ -269,7 +269,7 @@ void __init paging_init(void)
kmap_prot = PAGE_KERNEL;
#endif /* CONFIG_HIGHMEM */
- printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%lx\n",
+ printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%llx\n",
(unsigned long long)top_of_ram, total_ram);
printk(KERN_DEBUG "Memory hole size: %ldMB\n",
(long int)((top_of_ram - total_ram) >> 20));
@@ -337,8 +337,9 @@ void __init mem_init(void)
highmem_mapnr = lowmem_end_addr >> PAGE_SHIFT;
for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
+ phys_addr_t paddr = (phys_addr_t)pfn << PAGE_SHIFT;
struct page *page = pfn_to_page(pfn);
- if (memblock_is_reserved(pfn << PAGE_SHIFT))
+ if (memblock_is_reserved(paddr))
continue;
ClearPageReserved(page);
init_page_count(page);
@@ -352,6 +353,15 @@ void __init mem_init(void)
}
#endif /* CONFIG_HIGHMEM */
+#if defined(CONFIG_PPC_FSL_BOOK3E) && !defined(CONFIG_SMP)
+ /*
+ * If smp is enabled, next_tlbcam_idx is initialized in the cpu up
+ * functions.... do it here for the non-smp case.
+ */
+ per_cpu(next_tlbcam_idx, smp_processor_id()) =
+ (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1;
+#endif
+
printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, "
"%luk reserved, %luk data, %luk bss, %luk init)\n",
nr_free_pages() << (PAGE_SHIFT-10),
@@ -382,6 +392,25 @@ void __init mem_init(void)
mem_init_done = 1;
}
+void free_initmem(void)
+{
+ unsigned long addr;
+
+ ppc_md.progress = ppc_printk_progress;
+
+ addr = (unsigned long)__init_begin;
+ for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
+ memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
+ ClearPageReserved(virt_to_page(addr));
+ init_page_count(virt_to_page(addr));
+ free_page(addr);
+ totalram_pages++;
+ }
+ pr_info("Freeing unused kernel memory: %luk freed\n",
+ ((unsigned long)__init_end -
+ (unsigned long)__init_begin) >> 10);
+}
+
#ifdef CONFIG_BLK_DEV_INITRD
void __init free_initrd_mem(unsigned long start, unsigned long end)
{
diff --git a/arch/powerpc/mm/tlb_hash32.c b/arch/powerpc/mm/tlb_hash32.c
index 27b863c14941..9a445f64accd 100644
--- a/arch/powerpc/mm/tlb_hash32.c
+++ b/arch/powerpc/mm/tlb_hash32.c
@@ -177,3 +177,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
flush_range(vma->vm_mm, start, end);
}
EXPORT_SYMBOL(flush_tlb_range);
+
+void __init early_init_mmu(void)
+{
+}
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index af0892209417..4ebb34bc01d6 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -30,6 +30,212 @@
#define VPTE_PGD_SHIFT (VPTE_PUD_SHIFT + PUD_INDEX_SIZE)
#define VPTE_INDEX_SIZE (VPTE_PGD_SHIFT + PGD_INDEX_SIZE)
+/**********************************************************************
+ * *
+ * TLB miss handling for Book3E with a bolted linear mapping *
+ * No virtual page table, no nested TLB misses *
+ * *
+ **********************************************************************/
+
+.macro tlb_prolog_bolted addr
+ mtspr SPRN_SPRG_TLB_SCRATCH,r13
+ mfspr r13,SPRN_SPRG_PACA
+ std r10,PACA_EXTLB+EX_TLB_R10(r13)
+ mfcr r10
+ std r11,PACA_EXTLB+EX_TLB_R11(r13)
+ std r16,PACA_EXTLB+EX_TLB_R16(r13)
+ mfspr r16,\addr /* get faulting address */
+ std r14,PACA_EXTLB+EX_TLB_R14(r13)
+ ld r14,PACAPGD(r13)
+ std r15,PACA_EXTLB+EX_TLB_R15(r13)
+ std r10,PACA_EXTLB+EX_TLB_CR(r13)
+ TLB_MISS_PROLOG_STATS_BOLTED
+.endm
+
+.macro tlb_epilog_bolted
+ ld r14,PACA_EXTLB+EX_TLB_CR(r13)
+ ld r10,PACA_EXTLB+EX_TLB_R10(r13)
+ ld r11,PACA_EXTLB+EX_TLB_R11(r13)
+ mtcr r14
+ ld r14,PACA_EXTLB+EX_TLB_R14(r13)
+ ld r15,PACA_EXTLB+EX_TLB_R15(r13)
+ TLB_MISS_RESTORE_STATS_BOLTED
+ ld r16,PACA_EXTLB+EX_TLB_R16(r13)
+ mfspr r13,SPRN_SPRG_TLB_SCRATCH
+.endm
+
+/* Data TLB miss */
+ START_EXCEPTION(data_tlb_miss_bolted)
+ tlb_prolog_bolted SPRN_DEAR
+
+ /* We need _PAGE_PRESENT and _PAGE_ACCESSED set */
+
+ /* We do the user/kernel test for the PID here along with the RW test
+ */
+ /* We pre-test some combination of permissions to avoid double
+ * faults:
+ *
+ * We move the ESR:ST bit into the position of _PAGE_BAP_SW in the PTE
+ * ESR_ST is 0x00800000
+ * _PAGE_BAP_SW is 0x00000010
+ * So the shift is >> 19. This tests for supervisor writeability.
+ * If the page happens to be supervisor writeable and not user
+ * writeable, we will take a new fault later, but that should be
+ * a rare enough case.
+ *
+ * We also move ESR_ST in _PAGE_DIRTY position
+ * _PAGE_DIRTY is 0x00001000 so the shift is >> 11
+ *
+ * MAS1 is preset for all we need except for TID that needs to
+ * be cleared for kernel translations
+ */
+
+ mfspr r11,SPRN_ESR
+
+ srdi r15,r16,60 /* get region */
+ rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
+ bne- dtlb_miss_fault_bolted
+
+ rlwinm r10,r11,32-19,27,27
+ rlwimi r10,r11,32-16,19,19
+ cmpwi r15,0
+ ori r10,r10,_PAGE_PRESENT
+ oris r11,r10,_PAGE_ACCESSED@h
+
+ TLB_MISS_STATS_SAVE_INFO_BOLTED
+ bne tlb_miss_kernel_bolted
+
+tlb_miss_common_bolted:
+/*
+ * This is the guts of the TLB miss handler for bolted-linear.
+ * We are entered with:
+ *
+ * r16 = faulting address
+ * r15 = crap (free to use)
+ * r14 = page table base
+ * r13 = PACA
+ * r11 = PTE permission mask
+ * r10 = crap (free to use)
+ */
+ rldicl r15,r16,64-PGDIR_SHIFT+3,64-PGD_INDEX_SIZE-3
+ cmpldi cr0,r14,0
+ clrrdi r15,r15,3
+ beq tlb_miss_fault_bolted
+
+BEGIN_MMU_FTR_SECTION
+ /* Set the TLB reservation and search for existing entry. Then load
+ * the entry.
+ */
+ PPC_TLBSRX_DOT(0,r16)
+ ldx r14,r14,r15
+ beq normal_tlb_miss_done
+MMU_FTR_SECTION_ELSE
+ ldx r14,r14,r15
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBRSRV)
+
+#ifndef CONFIG_PPC_64K_PAGES
+ rldicl r15,r16,64-PUD_SHIFT+3,64-PUD_INDEX_SIZE-3
+ clrrdi r15,r15,3
+
+ cmpldi cr0,r14,0
+ beq tlb_miss_fault_bolted
+
+ ldx r14,r14,r15
+#endif /* CONFIG_PPC_64K_PAGES */
+
+ rldicl r15,r16,64-PMD_SHIFT+3,64-PMD_INDEX_SIZE-3
+ clrrdi r15,r15,3
+
+ cmpldi cr0,r14,0
+ beq tlb_miss_fault_bolted
+
+ ldx r14,r14,r15
+
+ rldicl r15,r16,64-PAGE_SHIFT+3,64-PTE_INDEX_SIZE-3
+ clrrdi r15,r15,3
+
+ cmpldi cr0,r14,0
+ beq tlb_miss_fault_bolted
+
+ ldx r14,r14,r15
+
+ /* Check if required permissions are met */
+ andc. r15,r11,r14
+ rldicr r15,r14,64-(PTE_RPN_SHIFT-PAGE_SHIFT),63-PAGE_SHIFT
+ bne- tlb_miss_fault_bolted
+
+ /* Now we build the MAS:
+ *
+ * MAS 0 : Fully setup with defaults in MAS4 and TLBnCFG
+ * MAS 1 : Almost fully setup
+ * - PID already updated by caller if necessary
+ * - TSIZE need change if !base page size, not
+ * yet implemented for now
+ * MAS 2 : Defaults not useful, need to be redone
+ * MAS 3+7 : Needs to be done
+ */
+ clrrdi r11,r16,12 /* Clear low crap in EA */
+ clrldi r15,r15,12 /* Clear crap at the top */
+ rlwimi r11,r14,32-19,27,31 /* Insert WIMGE */
+ rlwimi r15,r14,32-8,22,25 /* Move in U bits */
+ mtspr SPRN_MAS2,r11
+ andi. r11,r14,_PAGE_DIRTY
+ rlwimi r15,r14,32-2,26,31 /* Move in BAP bits */
+
+ /* Mask out SW and UW if !DIRTY (XXX optimize this !) */
+ bne 1f
+ li r11,MAS3_SW|MAS3_UW
+ andc r15,r15,r11
+1:
+ mtspr SPRN_MAS7_MAS3,r15
+ tlbwe
+
+ TLB_MISS_STATS_X(MMSTAT_TLB_MISS_NORM_OK)
+ tlb_epilog_bolted
+ rfi
+
+itlb_miss_kernel_bolted:
+ li r11,_PAGE_PRESENT|_PAGE_BAP_SX /* Base perm */
+ oris r11,r11,_PAGE_ACCESSED@h
+tlb_miss_kernel_bolted:
+ mfspr r10,SPRN_MAS1
+ ld r14,PACA_KERNELPGD(r13)
+ cmpldi cr0,r15,8 /* Check for vmalloc region */
+ rlwinm r10,r10,0,16,1 /* Clear TID */
+ mtspr SPRN_MAS1,r10
+ beq+ tlb_miss_common_bolted
+
+tlb_miss_fault_bolted:
+ /* We need to check if it was an instruction miss */
+ andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX
+ bne itlb_miss_fault_bolted
+dtlb_miss_fault_bolted:
+ TLB_MISS_STATS_D(MMSTAT_TLB_MISS_NORM_FAULT)
+ tlb_epilog_bolted
+ b exc_data_storage_book3e
+itlb_miss_fault_bolted:
+ TLB_MISS_STATS_I(MMSTAT_TLB_MISS_NORM_FAULT)
+ tlb_epilog_bolted
+ b exc_instruction_storage_book3e
+
+/* Instruction TLB miss */
+ START_EXCEPTION(instruction_tlb_miss_bolted)
+ tlb_prolog_bolted SPRN_SRR0
+
+ rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
+ srdi r15,r16,60 /* get region */
+ TLB_MISS_STATS_SAVE_INFO_BOLTED
+ bne- itlb_miss_fault_bolted
+
+ li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
+
+ /* We do the user/kernel test for the PID here along with the RW test
+ */
+
+ cmpldi cr0,r15,0 /* Check for user region */
+ oris r11,r11,_PAGE_ACCESSED@h
+ beq tlb_miss_common_bolted
+ b itlb_miss_kernel_bolted
/**********************************************************************
* *
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 0bdad3aecc67..d32ec643c231 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -35,6 +35,7 @@
#include <linux/preempt.h>
#include <linux/spinlock.h>
#include <linux/memblock.h>
+#include <linux/of_fdt.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
@@ -102,6 +103,12 @@ unsigned long linear_map_top; /* Top of linear mapping */
#endif /* CONFIG_PPC64 */
+#ifdef CONFIG_PPC_FSL_BOOK3E
+/* next_tlbcam_idx is used to round-robin tlbcam entry assignment */
+DEFINE_PER_CPU(int, next_tlbcam_idx);
+EXPORT_PER_CPU_SYMBOL(next_tlbcam_idx);
+#endif
+
/*
* Base TLB flushing operations:
*
@@ -266,6 +273,17 @@ EXPORT_SYMBOL(flush_tlb_page);
#endif /* CONFIG_SMP */
+#ifdef CONFIG_PPC_47x
+void __init early_init_mmu_47x(void)
+{
+#ifdef CONFIG_SMP
+ unsigned long root = of_get_flat_dt_root();
+ if (of_get_flat_dt_prop(root, "cooperative-partition", NULL))
+ mmu_clear_feature(MMU_FTR_USE_TLBIVAX_BCAST);
+#endif /* CONFIG_SMP */
+}
+#endif /* CONFIG_PPC_47x */
+
/*
* Flush kernel TLB entries in the given range
*/
@@ -443,14 +461,27 @@ static void setup_page_sizes(void)
}
}
-static void setup_mmu_htw(void)
+static void __patch_exception(int exc, unsigned long addr)
{
extern unsigned int interrupt_base_book3e;
- extern unsigned int exc_data_tlb_miss_htw_book3e;
- extern unsigned int exc_instruction_tlb_miss_htw_book3e;
+ unsigned int *ibase = &interrupt_base_book3e;
+
+ /* Our exceptions vectors start with a NOP and -then- a branch
+ * to deal with single stepping from userspace which stops on
+ * the second instruction. Thus we need to patch the second
+ * instruction of the exception, not the first one
+ */
- unsigned int *ibase = &interrupt_base_book3e;
+ patch_branch(ibase + (exc / 4) + 1, addr, 0);
+}
+
+#define patch_exception(exc, name) do { \
+ extern unsigned int name; \
+ __patch_exception((exc), (unsigned long)&name); \
+} while (0)
+static void setup_mmu_htw(void)
+{
/* Check if HW tablewalk is present, and if yes, enable it by:
*
* - patching the TLB miss handlers to branch to the
@@ -462,19 +493,12 @@ static void setup_mmu_htw(void)
if ((tlb0cfg & TLBnCFG_IND) &&
(tlb0cfg & TLBnCFG_PT)) {
- /* Our exceptions vectors start with a NOP and -then- a branch
- * to deal with single stepping from userspace which stops on
- * the second instruction. Thus we need to patch the second
- * instruction of the exception, not the first one
- */
- patch_branch(ibase + (0x1c0 / 4) + 1,
- (unsigned long)&exc_data_tlb_miss_htw_book3e, 0);
- patch_branch(ibase + (0x1e0 / 4) + 1,
- (unsigned long)&exc_instruction_tlb_miss_htw_book3e, 0);
+ patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e);
+ patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e);
book3e_htw_enabled = 1;
}
- pr_info("MMU: Book3E Page Tables %s\n",
- book3e_htw_enabled ? "Enabled" : "Disabled");
+ pr_info("MMU: Book3E HW tablewalk %s\n",
+ book3e_htw_enabled ? "enabled" : "not supported");
}
/*
@@ -549,6 +573,9 @@ static void __early_init_mmu(int boot_cpu)
/* limit memory so we dont have linear faults */
memblock_enforce_memory_limit(linear_map_top);
memblock_analyze();
+
+ patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
+ patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e);
}
#endif
@@ -584,4 +611,11 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
/* Finally limit subsequent allocations */
memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
}
+#else /* ! CONFIG_PPC64 */
+void __init early_init_mmu(void)
+{
+#ifdef CONFIG_PPC_47x
+ early_init_mmu_47x();
+#endif
+}
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile
new file mode 100644
index 000000000000..266b3950c3ac
--- /dev/null
+++ b/arch/powerpc/net/Makefile
@@ -0,0 +1,4 @@
+#
+# Arch-specific network modules
+#
+obj-$(CONFIG_BPF_JIT) += bpf_jit_64.o bpf_jit_comp.o
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
new file mode 100644
index 000000000000..af1ab5e9a691
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit.h
@@ -0,0 +1,227 @@
+/* bpf_jit.h: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _BPF_JIT_H
+#define _BPF_JIT_H
+
+#define BPF_PPC_STACK_LOCALS 32
+#define BPF_PPC_STACK_BASIC (48+64)
+#define BPF_PPC_STACK_SAVE (18*8)
+#define BPF_PPC_STACKFRAME (BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \
+ BPF_PPC_STACK_SAVE)
+#define BPF_PPC_SLOWPATH_FRAME (48+64)
+
+/*
+ * Generated code register usage:
+ *
+ * As normal PPC C ABI (e.g. r1=sp, r2=TOC), with:
+ *
+ * skb r3 (Entry parameter)
+ * A register r4
+ * X register r5
+ * addr param r6
+ * r7-r10 scratch
+ * skb->data r14
+ * skb headlen r15 (skb->len - skb->data_len)
+ * m[0] r16
+ * m[...] ...
+ * m[15] r31
+ */
+#define r_skb 3
+#define r_ret 3
+#define r_A 4
+#define r_X 5
+#define r_addr 6
+#define r_scratch1 7
+#define r_D 14
+#define r_HL 15
+#define r_M 16
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Assembly helpers from arch/powerpc/net/bpf_jit.S:
+ */
+extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
+
+#define FUNCTION_DESCR_SIZE 24
+
+/*
+ * 16-bit immediate helper macros: HA() is for use with sign-extending instrs
+ * (e.g. LD, ADDI). If the bottom 16 bits is "-ve", add another bit into the
+ * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000).
+ */
+#define IMM_H(i) ((uintptr_t)(i)>>16)
+#define IMM_HA(i) (((uintptr_t)(i)>>16) + \
+ (((uintptr_t)(i) & 0x8000) >> 15))
+#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
+
+#define PLANT_INSTR(d, idx, instr) \
+ do { if (d) { (d)[idx] = instr; } idx++; } while (0)
+#define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr)
+
+#define PPC_NOP() EMIT(PPC_INST_NOP)
+#define PPC_BLR() EMIT(PPC_INST_BLR)
+#define PPC_BLRL() EMIT(PPC_INST_BLRL)
+#define PPC_MTLR(r) EMIT(PPC_INST_MTLR | __PPC_RT(r))
+#define PPC_ADDI(d, a, i) EMIT(PPC_INST_ADDI | __PPC_RT(d) | \
+ __PPC_RA(a) | IMM_L(i))
+#define PPC_MR(d, a) PPC_OR(d, a, a)
+#define PPC_LI(r, i) PPC_ADDI(r, 0, i)
+#define PPC_ADDIS(d, a, i) EMIT(PPC_INST_ADDIS | \
+ __PPC_RS(d) | __PPC_RA(a) | IMM_L(i))
+#define PPC_LIS(r, i) PPC_ADDIS(r, 0, i)
+#define PPC_STD(r, base, i) EMIT(PPC_INST_STD | __PPC_RS(r) | \
+ __PPC_RA(base) | ((i) & 0xfffc))
+
+#define PPC_LD(r, base, i) EMIT(PPC_INST_LD | __PPC_RT(r) | \
+ __PPC_RA(base) | IMM_L(i))
+#define PPC_LWZ(r, base, i) EMIT(PPC_INST_LWZ | __PPC_RT(r) | \
+ __PPC_RA(base) | IMM_L(i))
+#define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | __PPC_RT(r) | \
+ __PPC_RA(base) | IMM_L(i))
+/* Convenience helpers for the above with 'far' offsets: */
+#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \
+ else { PPC_ADDIS(r, base, IMM_HA(i)); \
+ PPC_LD(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LWZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LWZ(r, base, i); \
+ else { PPC_ADDIS(r, base, IMM_HA(i)); \
+ PPC_LWZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LHZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LHZ(r, base, i); \
+ else { PPC_ADDIS(r, base, IMM_HA(i)); \
+ PPC_LHZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_CMPWI(a, i) EMIT(PPC_INST_CMPWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPDI(a, i) EMIT(PPC_INST_CMPDI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLWI(a, i) EMIT(PPC_INST_CMPLWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLW(a, b) EMIT(PPC_INST_CMPLW | __PPC_RA(a) | __PPC_RB(b))
+
+#define PPC_SUB(d, a, b) EMIT(PPC_INST_SUB | __PPC_RT(d) | \
+ __PPC_RB(a) | __PPC_RA(b))
+#define PPC_ADD(d, a, b) EMIT(PPC_INST_ADD | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MUL(d, a, b) EMIT(PPC_INST_MULLW | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULHWU(d, a, b) EMIT(PPC_INST_MULHWU | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULI(d, a, i) EMIT(PPC_INST_MULLI | __PPC_RT(d) | \
+ __PPC_RA(a) | IMM_L(i))
+#define PPC_DIVWU(d, a, b) EMIT(PPC_INST_DIVWU | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_AND(d, a, b) EMIT(PPC_INST_AND | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ANDI(d, a, i) EMIT(PPC_INST_ANDI | __PPC_RA(d) | \
+ __PPC_RS(a) | IMM_L(i))
+#define PPC_AND_DOT(d, a, b) EMIT(PPC_INST_ANDDOT | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(b))
+#define PPC_OR(d, a, b) EMIT(PPC_INST_OR | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ORI(d, a, i) EMIT(PPC_INST_ORI | __PPC_RA(d) | \
+ __PPC_RS(a) | IMM_L(i))
+#define PPC_ORIS(d, a, i) EMIT(PPC_INST_ORIS | __PPC_RA(d) | \
+ __PPC_RS(a) | IMM_L(i))
+#define PPC_SLW(d, a, s) EMIT(PPC_INST_SLW | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(s))
+#define PPC_SRW(d, a, s) EMIT(PPC_INST_SRW | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(s))
+/* slwi = rlwinm Rx, Ry, n, 0, 31-n */
+#define PPC_SLWI(d, a, i) EMIT(PPC_INST_RLWINM | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_SH(i) | \
+ __PPC_MB(0) | __PPC_ME(31-(i)))
+/* srwi = rlwinm Rx, Ry, 32-n, n, 31 */
+#define PPC_SRWI(d, a, i) EMIT(PPC_INST_RLWINM | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_SH(32-(i)) | \
+ __PPC_MB(i) | __PPC_ME(31))
+/* sldi = rldicr Rx, Ry, n, 63-n */
+#define PPC_SLDI(d, a, i) EMIT(PPC_INST_RLDICR | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_SH(i) | \
+ __PPC_MB(63-(i)) | (((i) & 0x20) >> 4))
+#define PPC_NEG(d, a) EMIT(PPC_INST_NEG | __PPC_RT(d) | __PPC_RA(a))
+
+/* Long jump; (unconditional 'branch') */
+#define PPC_JMP(dest) EMIT(PPC_INST_BRANCH | \
+ (((dest) - (ctx->idx * 4)) & 0x03fffffc))
+/* "cond" here covers BO:BI fields. */
+#define PPC_BCC_SHORT(cond, dest) EMIT(PPC_INST_BRANCH_COND | \
+ (((cond) & 0x3ff) << 16) | \
+ (((dest) - (ctx->idx * 4)) & \
+ 0xfffc))
+#define PPC_LI32(d, i) do { PPC_LI(d, IMM_L(i)); \
+ if ((u32)(uintptr_t)(i) >= 32768) { \
+ PPC_ADDIS(d, d, IMM_HA(i)); \
+ } } while(0)
+#define PPC_LI64(d, i) do { \
+ if (!((uintptr_t)(i) & 0xffffffff00000000ULL)) \
+ PPC_LI32(d, i); \
+ else { \
+ PPC_LIS(d, ((uintptr_t)(i) >> 48)); \
+ if ((uintptr_t)(i) & 0x0000ffff00000000ULL) \
+ PPC_ORI(d, d, \
+ ((uintptr_t)(i) >> 32) & 0xffff); \
+ PPC_SLDI(d, d, 32); \
+ if ((uintptr_t)(i) & 0x00000000ffff0000ULL) \
+ PPC_ORIS(d, d, \
+ ((uintptr_t)(i) >> 16) & 0xffff); \
+ if ((uintptr_t)(i) & 0x000000000000ffffULL) \
+ PPC_ORI(d, d, (uintptr_t)(i) & 0xffff); \
+ } } while (0);
+
+static inline bool is_nearbranch(int offset)
+{
+ return (offset < 32768) && (offset >= -32768);
+}
+
+/*
+ * The fly in the ointment of code size changing from pass to pass is
+ * avoided by padding the short branch case with a NOP. If code size differs
+ * with different branch reaches we will have the issue of code moving from
+ * one pass to the next and will need a few passes to converge on a stable
+ * state.
+ */
+#define PPC_BCC(cond, dest) do { \
+ if (is_nearbranch((dest) - (ctx->idx * 4))) { \
+ PPC_BCC_SHORT(cond, dest); \
+ PPC_NOP(); \
+ } else { \
+ /* Flip the 'T or F' bit to invert comparison */ \
+ PPC_BCC_SHORT(cond ^ COND_CMP_TRUE, (ctx->idx+2)*4); \
+ PPC_JMP(dest); \
+ } } while(0)
+
+/* To create a branch condition, select a bit of cr0... */
+#define CR0_LT 0
+#define CR0_GT 1
+#define CR0_EQ 2
+/* ...and modify BO[3] */
+#define COND_CMP_TRUE 0x100
+#define COND_CMP_FALSE 0x000
+/* Together, they make all required comparisons: */
+#define COND_GT (CR0_GT | COND_CMP_TRUE)
+#define COND_GE (CR0_LT | COND_CMP_FALSE)
+#define COND_EQ (CR0_EQ | COND_CMP_TRUE)
+#define COND_NE (CR0_EQ | COND_CMP_FALSE)
+#define COND_LT (CR0_LT | COND_CMP_TRUE)
+
+#define SEEN_DATAREF 0x10000 /* might call external helpers */
+#define SEEN_XREG 0x20000 /* X reg is used */
+#define SEEN_MEM 0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary
+ * storage */
+#define SEEN_MEM_MSK 0x0ffff
+
+struct codegen_context {
+ unsigned int seen;
+ unsigned int idx;
+ int pc_ret0; /* bpf index of first RET #0 instruction (if any) */
+};
+
+#endif
+
+#endif
diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S
new file mode 100644
index 000000000000..ff4506e85cce
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit_64.S
@@ -0,0 +1,138 @@
+/* bpf_jit.S: Packet/header access helper functions
+ * for PPC64 BPF compiler.
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <asm/ppc_asm.h>
+#include "bpf_jit.h"
+
+/*
+ * All of these routines are called directly from generated code,
+ * whose register usage is:
+ *
+ * r3 skb
+ * r4,r5 A,X
+ * r6 *** address parameter to helper ***
+ * r7-r10 scratch
+ * r14 skb->data
+ * r15 skb headlen
+ * r16-31 M[]
+ */
+
+/*
+ * To consider: These helpers are so small it could be better to just
+ * generate them inline. Inline code can do the simple headlen check
+ * then branch directly to slow_path_XXX if required. (In fact, could
+ * load a spare GPR with the address of slow_path_generic and pass size
+ * as an argument, making the call site a mtlr, li and bllr.)
+ *
+ * Technically, the "is addr < 0" check is unnecessary & slowing down
+ * the ABS path, as it's statically checked on generation.
+ */
+ .globl sk_load_word
+sk_load_word:
+ cmpdi r_addr, 0
+ blt bpf_error
+ /* Are we accessing past headlen? */
+ subi r_scratch1, r_HL, 4
+ cmpd r_scratch1, r_addr
+ blt bpf_slow_path_word
+ /* Nope, just hitting the header. cr0 here is eq or gt! */
+ lwzx r_A, r_D, r_addr
+ /* When big endian we don't need to byteswap. */
+ blr /* Return success, cr0 != LT */
+
+ .globl sk_load_half
+sk_load_half:
+ cmpdi r_addr, 0
+ blt bpf_error
+ subi r_scratch1, r_HL, 2
+ cmpd r_scratch1, r_addr
+ blt bpf_slow_path_half
+ lhzx r_A, r_D, r_addr
+ blr
+
+ .globl sk_load_byte
+sk_load_byte:
+ cmpdi r_addr, 0
+ blt bpf_error
+ cmpd r_HL, r_addr
+ ble bpf_slow_path_byte
+ lbzx r_A, r_D, r_addr
+ blr
+
+/*
+ * BPF_S_LDX_B_MSH: ldxb 4*([offset]&0xf)
+ * r_addr is the offset value, already known positive
+ */
+ .globl sk_load_byte_msh
+sk_load_byte_msh:
+ cmpd r_HL, r_addr
+ ble bpf_slow_path_byte_msh
+ lbzx r_X, r_D, r_addr
+ rlwinm r_X, r_X, 2, 32-4-2, 31-2
+ blr
+
+bpf_error:
+ /* Entered with cr0 = lt */
+ li r3, 0
+ /* Generated code will 'blt epilogue', returning 0. */
+ blr
+
+/* Call out to skb_copy_bits:
+ * We'll need to back up our volatile regs first; we have
+ * local variable space at r1+(BPF_PPC_STACK_BASIC).
+ * Allocate a new stack frame here to remain ABI-compliant in
+ * stashing LR.
+ */
+#define bpf_slow_path_common(SIZE) \
+ mflr r0; \
+ std r0, 16(r1); \
+ /* R3 goes in parameter space of caller's frame */ \
+ std r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
+ std r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
+ std r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
+ addi r5, r1, BPF_PPC_STACK_BASIC+(2*8); \
+ stdu r1, -BPF_PPC_SLOWPATH_FRAME(r1); \
+ /* R3 = r_skb, as passed */ \
+ mr r4, r_addr; \
+ li r6, SIZE; \
+ bl skb_copy_bits; \
+ /* R3 = 0 on success */ \
+ addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \
+ ld r0, 16(r1); \
+ ld r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
+ ld r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
+ mtlr r0; \
+ cmpdi r3, 0; \
+ blt bpf_error; /* cr0 = LT */ \
+ ld r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
+ /* Great success! */
+
+bpf_slow_path_word:
+ bpf_slow_path_common(4)
+ /* Data value is on stack, and cr0 != LT */
+ lwz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ blr
+
+bpf_slow_path_half:
+ bpf_slow_path_common(2)
+ lhz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ blr
+
+bpf_slow_path_byte:
+ bpf_slow_path_common(1)
+ lbz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ blr
+
+bpf_slow_path_byte_msh:
+ bpf_slow_path_common(1)
+ lbz r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ rlwinm r_X, r_X, 2, 32-4-2, 31-2
+ blr
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
new file mode 100644
index 000000000000..73619d3aeb6c
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -0,0 +1,694 @@
+/* bpf_jit_comp.c: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * Based on the x86 BPF compiler, by Eric Dumazet (eric.dumazet@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/moduleloader.h>
+#include <asm/cacheflush.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include "bpf_jit.h"
+
+#ifndef __BIG_ENDIAN
+/* There are endianness assumptions herein. */
+#error "Little-endian PPC not supported in BPF compiler"
+#endif
+
+int bpf_jit_enable __read_mostly;
+
+
+static inline void bpf_flush_icache(void *start, void *end)
+{
+ smp_wmb();
+ flush_icache_range((unsigned long)start, (unsigned long)end);
+}
+
+static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
+ struct codegen_context *ctx)
+{
+ int i;
+ const struct sock_filter *filter = fp->insns;
+
+ if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+ /* Make stackframe */
+ if (ctx->seen & SEEN_DATAREF) {
+ /* If we call any helpers (for loads), save LR */
+ EMIT(PPC_INST_MFLR | __PPC_RT(0));
+ PPC_STD(0, 1, 16);
+
+ /* Back up non-volatile regs. */
+ PPC_STD(r_D, 1, -(8*(32-r_D)));
+ PPC_STD(r_HL, 1, -(8*(32-r_HL)));
+ }
+ if (ctx->seen & SEEN_MEM) {
+ /*
+ * Conditionally save regs r15-r31 as some will be used
+ * for M[] data.
+ */
+ for (i = r_M; i < (r_M+16); i++) {
+ if (ctx->seen & (1 << (i-r_M)))
+ PPC_STD(i, 1, -(8*(32-i)));
+ }
+ }
+ EMIT(PPC_INST_STDU | __PPC_RS(1) | __PPC_RA(1) |
+ (-BPF_PPC_STACKFRAME & 0xfffc));
+ }
+
+ if (ctx->seen & SEEN_DATAREF) {
+ /*
+ * If this filter needs to access skb data,
+ * prepare r_D and r_HL:
+ * r_HL = skb->len - skb->data_len
+ * r_D = skb->data
+ */
+ PPC_LWZ_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+ data_len));
+ PPC_LWZ_OFFS(r_HL, r_skb, offsetof(struct sk_buff, len));
+ PPC_SUB(r_HL, r_HL, r_scratch1);
+ PPC_LD_OFFS(r_D, r_skb, offsetof(struct sk_buff, data));
+ }
+
+ if (ctx->seen & SEEN_XREG) {
+ /*
+ * TODO: Could also detect whether first instr. sets X and
+ * avoid this (as below, with A).
+ */
+ PPC_LI(r_X, 0);
+ }
+
+ switch (filter[0].code) {
+ case BPF_S_RET_K:
+ case BPF_S_LD_W_LEN:
+ case BPF_S_ANC_PROTOCOL:
+ case BPF_S_ANC_IFINDEX:
+ case BPF_S_ANC_MARK:
+ case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_CPU:
+ case BPF_S_ANC_QUEUE:
+ case BPF_S_LD_W_ABS:
+ case BPF_S_LD_H_ABS:
+ case BPF_S_LD_B_ABS:
+ /* first instruction sets A register (or is RET 'constant') */
+ break;
+ default:
+ /* make sure we dont leak kernel information to user */
+ PPC_LI(r_A, 0);
+ }
+}
+
+static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
+{
+ int i;
+
+ if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+ PPC_ADDI(1, 1, BPF_PPC_STACKFRAME);
+ if (ctx->seen & SEEN_DATAREF) {
+ PPC_LD(0, 1, 16);
+ PPC_MTLR(0);
+ PPC_LD(r_D, 1, -(8*(32-r_D)));
+ PPC_LD(r_HL, 1, -(8*(32-r_HL)));
+ }
+ if (ctx->seen & SEEN_MEM) {
+ /* Restore any saved non-vol registers */
+ for (i = r_M; i < (r_M+16); i++) {
+ if (ctx->seen & (1 << (i-r_M)))
+ PPC_LD(i, 1, -(8*(32-i)));
+ }
+ }
+ }
+ /* The RETs have left a return value in R3. */
+
+ PPC_BLR();
+}
+
+/* Assemble the body code between the prologue & epilogue. */
+static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
+ struct codegen_context *ctx,
+ unsigned int *addrs)
+{
+ const struct sock_filter *filter = fp->insns;
+ int flen = fp->len;
+ u8 *func;
+ unsigned int true_cond;
+ int i;
+
+ /* Start of epilogue code */
+ unsigned int exit_addr = addrs[flen];
+
+ for (i = 0; i < flen; i++) {
+ unsigned int K = filter[i].k;
+
+ /*
+ * addrs[] maps a BPF bytecode address into a real offset from
+ * the start of the body code.
+ */
+ addrs[i] = ctx->idx * 4;
+
+ switch (filter[i].code) {
+ /*** ALU ops ***/
+ case BPF_S_ALU_ADD_X: /* A += X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_ADD(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_ADD_K: /* A += K; */
+ if (!K)
+ break;
+ PPC_ADDI(r_A, r_A, IMM_L(K));
+ if (K >= 32768)
+ PPC_ADDIS(r_A, r_A, IMM_HA(K));
+ break;
+ case BPF_S_ALU_SUB_X: /* A -= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_SUB(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_SUB_K: /* A -= K */
+ if (!K)
+ break;
+ PPC_ADDI(r_A, r_A, IMM_L(-K));
+ if (K >= 32768)
+ PPC_ADDIS(r_A, r_A, IMM_HA(-K));
+ break;
+ case BPF_S_ALU_MUL_X: /* A *= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_MUL(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_MUL_K: /* A *= K */
+ if (K < 32768)
+ PPC_MULI(r_A, r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_MUL(r_A, r_A, r_scratch1);
+ }
+ break;
+ case BPF_S_ALU_DIV_X: /* A /= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_CMPWI(r_X, 0);
+ if (ctx->pc_ret0 != -1) {
+ PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+ } else {
+ /*
+ * Exit, returning 0; first pass hits here
+ * (longer worst-case code size).
+ */
+ PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+ PPC_LI(r_ret, 0);
+ PPC_JMP(exit_addr);
+ }
+ PPC_DIVWU(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+ PPC_LI32(r_scratch1, K);
+ /* Top 32 bits of 64bit result -> A */
+ PPC_MULHWU(r_A, r_A, r_scratch1);
+ break;
+ case BPF_S_ALU_AND_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_AND(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_AND_K:
+ if (!IMM_H(K))
+ PPC_ANDI(r_A, r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_AND(r_A, r_A, r_scratch1);
+ }
+ break;
+ case BPF_S_ALU_OR_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_OR(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_OR_K:
+ if (IMM_L(K))
+ PPC_ORI(r_A, r_A, IMM_L(K));
+ if (K >= 65536)
+ PPC_ORIS(r_A, r_A, IMM_H(K));
+ break;
+ case BPF_S_ALU_LSH_X: /* A <<= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_SLW(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_LSH_K:
+ if (K == 0)
+ break;
+ else
+ PPC_SLWI(r_A, r_A, K);
+ break;
+ case BPF_S_ALU_RSH_X: /* A >>= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_SRW(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_RSH_K: /* A >>= K; */
+ if (K == 0)
+ break;
+ else
+ PPC_SRWI(r_A, r_A, K);
+ break;
+ case BPF_S_ALU_NEG:
+ PPC_NEG(r_A, r_A);
+ break;
+ case BPF_S_RET_K:
+ PPC_LI32(r_ret, K);
+ if (!K) {
+ if (ctx->pc_ret0 == -1)
+ ctx->pc_ret0 = i;
+ }
+ /*
+ * If this isn't the very last instruction, branch to
+ * the epilogue if we've stuff to clean up. Otherwise,
+ * if there's nothing to tidy, just return. If we /are/
+ * the last instruction, we're about to fall through to
+ * the epilogue to return.
+ */
+ if (i != flen - 1) {
+ /*
+ * Note: 'seen' is properly valid only on pass
+ * #2. Both parts of this conditional are the
+ * same instruction size though, meaning the
+ * first pass will still correctly determine the
+ * code size/addresses.
+ */
+ if (ctx->seen)
+ PPC_JMP(exit_addr);
+ else
+ PPC_BLR();
+ }
+ break;
+ case BPF_S_RET_A:
+ PPC_MR(r_ret, r_A);
+ if (i != flen - 1) {
+ if (ctx->seen)
+ PPC_JMP(exit_addr);
+ else
+ PPC_BLR();
+ }
+ break;
+ case BPF_S_MISC_TAX: /* X = A */
+ PPC_MR(r_X, r_A);
+ break;
+ case BPF_S_MISC_TXA: /* A = X */
+ ctx->seen |= SEEN_XREG;
+ PPC_MR(r_A, r_X);
+ break;
+
+ /*** Constant loads/M[] access ***/
+ case BPF_S_LD_IMM: /* A = K */
+ PPC_LI32(r_A, K);
+ break;
+ case BPF_S_LDX_IMM: /* X = K */
+ PPC_LI32(r_X, K);
+ break;
+ case BPF_S_LD_MEM: /* A = mem[K] */
+ PPC_MR(r_A, r_M + (K & 0xf));
+ ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_LDX_MEM: /* X = mem[K] */
+ PPC_MR(r_X, r_M + (K & 0xf));
+ ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_ST: /* mem[K] = A */
+ PPC_MR(r_M + (K & 0xf), r_A);
+ ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_STX: /* mem[K] = X */
+ PPC_MR(r_M + (K & 0xf), r_X);
+ ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_LD_W_LEN: /* A = skb->len; */
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+ PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, len));
+ break;
+ case BPF_S_LDX_W_LEN: /* X = skb->len; */
+ PPC_LWZ_OFFS(r_X, r_skb, offsetof(struct sk_buff, len));
+ break;
+
+ /*** Ancillary info loads ***/
+
+ /* None of the BPF_S_ANC* codes appear to be passed by
+ * sk_chk_filter(). The interpreter and the x86 BPF
+ * compiler implement them so we do too -- they may be
+ * planted in future.
+ */
+ case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ protocol) != 2);
+ PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ protocol));
+ /* ntohs is a NOP with BE loads. */
+ break;
+ case BPF_S_ANC_IFINDEX:
+ PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+ dev));
+ PPC_CMPDI(r_scratch1, 0);
+ if (ctx->pc_ret0 != -1) {
+ PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+ } else {
+ /* Exit, returning 0; first pass hits here. */
+ PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+ PPC_LI(r_ret, 0);
+ PPC_JMP(exit_addr);
+ }
+ BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+ ifindex) != 4);
+ PPC_LWZ_OFFS(r_A, r_scratch1,
+ offsetof(struct net_device, ifindex));
+ break;
+ case BPF_S_ANC_MARK:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+ PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ mark));
+ break;
+ case BPF_S_ANC_RXHASH:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+ PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ rxhash));
+ break;
+ case BPF_S_ANC_QUEUE:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ queue_mapping) != 2);
+ PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ queue_mapping));
+ break;
+ case BPF_S_ANC_CPU:
+#ifdef CONFIG_SMP
+ /*
+ * PACA ptr is r13:
+ * raw_smp_processor_id() = local_paca->paca_index
+ */
+ BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct,
+ paca_index) != 2);
+ PPC_LHZ_OFFS(r_A, 13,
+ offsetof(struct paca_struct, paca_index));
+#else
+ PPC_LI(r_A, 0);
+#endif
+ break;
+
+ /*** Absolute loads from packet header/data ***/
+ case BPF_S_LD_W_ABS:
+ func = sk_load_word;
+ goto common_load;
+ case BPF_S_LD_H_ABS:
+ func = sk_load_half;
+ goto common_load;
+ case BPF_S_LD_B_ABS:
+ func = sk_load_byte;
+ common_load:
+ /*
+ * Load from [K]. Reference with the (negative)
+ * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported.
+ */
+ ctx->seen |= SEEN_DATAREF;
+ if ((int)K < 0)
+ return -ENOTSUPP;
+ PPC_LI64(r_scratch1, func);
+ PPC_MTLR(r_scratch1);
+ PPC_LI32(r_addr, K);
+ PPC_BLRL();
+ /*
+ * Helper returns 'lt' condition on error, and an
+ * appropriate return value in r3
+ */
+ PPC_BCC(COND_LT, exit_addr);
+ break;
+
+ /*** Indirect loads from packet header/data ***/
+ case BPF_S_LD_W_IND:
+ func = sk_load_word;
+ goto common_load_ind;
+ case BPF_S_LD_H_IND:
+ func = sk_load_half;
+ goto common_load_ind;
+ case BPF_S_LD_B_IND:
+ func = sk_load_byte;
+ common_load_ind:
+ /*
+ * Load from [X + K]. Negative offsets are tested for
+ * in the helper functions, and result in a 'ret 0'.
+ */
+ ctx->seen |= SEEN_DATAREF | SEEN_XREG;
+ PPC_LI64(r_scratch1, func);
+ PPC_MTLR(r_scratch1);
+ PPC_ADDI(r_addr, r_X, IMM_L(K));
+ if (K >= 32768)
+ PPC_ADDIS(r_addr, r_addr, IMM_HA(K));
+ PPC_BLRL();
+ /* If error, cr0.LT set */
+ PPC_BCC(COND_LT, exit_addr);
+ break;
+
+ case BPF_S_LDX_B_MSH:
+ /*
+ * x86 version drops packet (RET 0) when K<0, whereas
+ * interpreter does allow K<0 (__load_pointer, special
+ * ancillary data). common_load returns ENOTSUPP if K<0,
+ * so we fall back to interpreter & filter works.
+ */
+ func = sk_load_byte_msh;
+ goto common_load;
+ break;
+
+ /*** Jump and branches ***/
+ case BPF_S_JMP_JA:
+ if (K != 0)
+ PPC_JMP(addrs[i + 1 + K]);
+ break;
+
+ case BPF_S_JMP_JGT_K:
+ case BPF_S_JMP_JGT_X:
+ true_cond = COND_GT;
+ goto cond_branch;
+ case BPF_S_JMP_JGE_K:
+ case BPF_S_JMP_JGE_X:
+ true_cond = COND_GE;
+ goto cond_branch;
+ case BPF_S_JMP_JEQ_K:
+ case BPF_S_JMP_JEQ_X:
+ true_cond = COND_EQ;
+ goto cond_branch;
+ case BPF_S_JMP_JSET_K:
+ case BPF_S_JMP_JSET_X:
+ true_cond = COND_NE;
+ /* Fall through */
+ cond_branch:
+ /* same targets, can avoid doing the test :) */
+ if (filter[i].jt == filter[i].jf) {
+ if (filter[i].jt > 0)
+ PPC_JMP(addrs[i + 1 + filter[i].jt]);
+ break;
+ }
+
+ switch (filter[i].code) {
+ case BPF_S_JMP_JGT_X:
+ case BPF_S_JMP_JGE_X:
+ case BPF_S_JMP_JEQ_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_CMPLW(r_A, r_X);
+ break;
+ case BPF_S_JMP_JSET_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_AND_DOT(r_scratch1, r_A, r_X);
+ break;
+ case BPF_S_JMP_JEQ_K:
+ case BPF_S_JMP_JGT_K:
+ case BPF_S_JMP_JGE_K:
+ if (K < 32768)
+ PPC_CMPLWI(r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_CMPLW(r_A, r_scratch1);
+ }
+ break;
+ case BPF_S_JMP_JSET_K:
+ if (K < 32768)
+ /* PPC_ANDI is /only/ dot-form */
+ PPC_ANDI(r_scratch1, r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_AND_DOT(r_scratch1, r_A,
+ r_scratch1);
+ }
+ break;
+ }
+ /* Sometimes branches are constructed "backward", with
+ * the false path being the branch and true path being
+ * a fallthrough to the next instruction.
+ */
+ if (filter[i].jt == 0)
+ /* Swap the sense of the branch */
+ PPC_BCC(true_cond ^ COND_CMP_TRUE,
+ addrs[i + 1 + filter[i].jf]);
+ else {
+ PPC_BCC(true_cond, addrs[i + 1 + filter[i].jt]);
+ if (filter[i].jf != 0)
+ PPC_JMP(addrs[i + 1 + filter[i].jf]);
+ }
+ break;
+ default:
+ /* The filter contains something cruel & unusual.
+ * We don't handle it, but also there shouldn't be
+ * anything missing from our list.
+ */
+ if (printk_ratelimit())
+ pr_err("BPF filter opcode %04x (@%d) unsupported\n",
+ filter[i].code, i);
+ return -ENOTSUPP;
+ }
+
+ }
+ /* Set end-of-body-code address for exit. */
+ addrs[i] = ctx->idx * 4;
+
+ return 0;
+}
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+ unsigned int proglen;
+ unsigned int alloclen;
+ u32 *image = NULL;
+ u32 *code_base;
+ unsigned int *addrs;
+ struct codegen_context cgctx;
+ int pass;
+ int flen = fp->len;
+
+ if (!bpf_jit_enable)
+ return;
+
+ addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL);
+ if (addrs == NULL)
+ return;
+
+ /*
+ * There are multiple assembly passes as the generated code will change
+ * size as it settles down, figuring out the max branch offsets/exit
+ * paths required.
+ *
+ * The range of standard conditional branches is +/- 32Kbytes. Since
+ * BPF_MAXINSNS = 4096, we can only jump from (worst case) start to
+ * finish with 8 bytes/instruction. Not feasible, so long jumps are
+ * used, distinct from short branches.
+ *
+ * Current:
+ *
+ * For now, both branch types assemble to 2 words (short branches padded
+ * with a NOP); this is less efficient, but assembly will always complete
+ * after exactly 3 passes:
+ *
+ * First pass: No code buffer; Program is "faux-generated" -- no code
+ * emitted but maximum size of output determined (and addrs[] filled
+ * in). Also, we note whether we use M[], whether we use skb data, etc.
+ * All generation choices assumed to be 'worst-case', e.g. branches all
+ * far (2 instructions), return path code reduction not available, etc.
+ *
+ * Second pass: Code buffer allocated with size determined previously.
+ * Prologue generated to support features we have seen used. Exit paths
+ * determined and addrs[] is filled in again, as code may be slightly
+ * smaller as a result.
+ *
+ * Third pass: Code generated 'for real', and branch destinations
+ * determined from now-accurate addrs[] map.
+ *
+ * Ideal:
+ *
+ * If we optimise this, near branches will be shorter. On the
+ * first assembly pass, we should err on the side of caution and
+ * generate the biggest code. On subsequent passes, branches will be
+ * generated short or long and code size will reduce. With smaller
+ * code, more branches may fall into the short category, and code will
+ * reduce more.
+ *
+ * Finally, if we see one pass generate code the same size as the
+ * previous pass we have converged and should now generate code for
+ * real. Allocating at the end will also save the memory that would
+ * otherwise be wasted by the (small) current code shrinkage.
+ * Preferably, we should do a small number of passes (e.g. 5) and if we
+ * haven't converged by then, get impatient and force code to generate
+ * as-is, even if the odd branch would be left long. The chances of a
+ * long jump are tiny with all but the most enormous of BPF filter
+ * inputs, so we should usually converge on the third pass.
+ */
+
+ cgctx.idx = 0;
+ cgctx.seen = 0;
+ cgctx.pc_ret0 = -1;
+ /* Scouting faux-generate pass 0 */
+ if (bpf_jit_build_body(fp, 0, &cgctx, addrs))
+ /* We hit something illegal or unsupported. */
+ goto out;
+
+ /*
+ * Pretend to build prologue, given the features we've seen. This will
+ * update ctgtx.idx as it pretends to output instructions, then we can
+ * calculate total size from idx.
+ */
+ bpf_jit_build_prologue(fp, 0, &cgctx);
+ bpf_jit_build_epilogue(0, &cgctx);
+
+ proglen = cgctx.idx * 4;
+ alloclen = proglen + FUNCTION_DESCR_SIZE;
+ image = module_alloc(max_t(unsigned int, alloclen,
+ sizeof(struct work_struct)));
+ if (!image)
+ goto out;
+
+ code_base = image + (FUNCTION_DESCR_SIZE/4);
+
+ /* Code generation passes 1-2 */
+ for (pass = 1; pass < 3; pass++) {
+ /* Now build the prologue, body code & epilogue for real. */
+ cgctx.idx = 0;
+ bpf_jit_build_prologue(fp, code_base, &cgctx);
+ bpf_jit_build_body(fp, code_base, &cgctx, addrs);
+ bpf_jit_build_epilogue(code_base, &cgctx);
+
+ if (bpf_jit_enable > 1)
+ pr_info("Pass %d: shrink = %d, seen = 0x%x\n", pass,
+ proglen - (cgctx.idx * 4), cgctx.seen);
+ }
+
+ if (bpf_jit_enable > 1)
+ pr_info("flen=%d proglen=%u pass=%d image=%p\n",
+ flen, proglen, pass, image);
+
+ if (image) {
+ if (bpf_jit_enable > 1)
+ print_hex_dump(KERN_ERR, "JIT code: ",
+ DUMP_PREFIX_ADDRESS,
+ 16, 1, code_base,
+ proglen, false);
+
+ bpf_flush_icache(code_base, code_base + (proglen/4));
+ /* Function descriptor nastiness: Address + TOC */
+ ((u64 *)image)[0] = (u64)code_base;
+ ((u64 *)image)[1] = local_paca->kernel_toc;
+ fp->bpf_func = (void *)image;
+ }
+out:
+ kfree(addrs);
+ return;
+}
+
+static void jit_free_defer(struct work_struct *arg)
+{
+ module_free(NULL, arg);
+}
+
+/* run from softirq, we must use a work_struct to call
+ * module_free() from process context
+ */
+void bpf_jit_free(struct sk_filter *fp)
+{
+ if (fp->bpf_func != sk_run_filter) {
+ struct work_struct *work = (struct work_struct *)fp->bpf_func;
+
+ INIT_WORK(work, jit_free_defer);
+ schedule_work(work);
+ }
+}
diff --git a/arch/powerpc/platforms/40x/ep405.c b/arch/powerpc/platforms/40x/ep405.c
index 4058fd1e7fc7..b0389bbe4f94 100644
--- a/arch/powerpc/platforms/40x/ep405.c
+++ b/arch/powerpc/platforms/40x/ep405.c
@@ -100,7 +100,7 @@ static void __init ep405_setup_arch(void)
/* Find & init the BCSR CPLD */
ep405_init_bcsr();
- ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+ pci_set_flags(PCI_REASSIGN_ALL_RSRC);
}
static int __init ep405_probe(void)
diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c
index 2521d93ef136..e8dd5c5df7d9 100644
--- a/arch/powerpc/platforms/40x/ppc40x_simple.c
+++ b/arch/powerpc/platforms/40x/ppc40x_simple.c
@@ -61,7 +61,7 @@ static const char *board[] __initdata = {
static int __init ppc40x_probe(void)
{
if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
- ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+ pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index 335df91fbee5..8b691df72f74 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -51,7 +51,7 @@ static int __init walnut_probe(void)
if (!of_flat_dt_is_compatible(root, "ibm,walnut"))
return 0;
- ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+ pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
index afc5e8ea3775..e300dd4c89bf 100644
--- a/arch/powerpc/platforms/44x/canyonlands.c
+++ b/arch/powerpc/platforms/44x/canyonlands.c
@@ -55,7 +55,7 @@ static int __init ppc460ex_probe(void)
{
unsigned long root = of_get_flat_dt_root();
if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
- ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+ pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
return 0;
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
index 88b9117fa691..6a4232bbdf88 100644
--- a/arch/powerpc/platforms/44x/ebony.c
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -54,7 +54,7 @@ static int __init ebony_probe(void)
if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
return 0;
- ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+ pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index c81c19c0b3d4..8d2202763415 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -72,7 +72,7 @@ static int __init ppc44x_probe(void)
for (i = 0; i < ARRAY_SIZE(board); i++) {
if (of_flat_dt_is_compatible(root, board[i])) {
- ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+ pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
}
diff --git a/arch/powerpc/platforms/44x/sam440ep.c b/arch/powerpc/platforms/44x/sam440ep.c
index a78e8eb6da41..9e09b835758b 100644
--- a/arch/powerpc/platforms/44x/sam440ep.c
+++ b/arch/powerpc/platforms/44x/sam440ep.c
@@ -51,7 +51,7 @@ static int __init sam440ep_probe(void)
if (!of_flat_dt_is_compatible(root, "acube,sam440ep"))
return 0;
- ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+ pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index 47ea1be1481b..90f4496017e4 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -55,14 +55,6 @@ config PPC_MPC5200_BUGFIX
It is safe to say 'Y' here
-config PPC_MPC5200_GPIO
- bool "MPC5200 GPIO support"
- depends on PPC_MPC52xx
- select ARCH_REQUIRE_GPIOLIB
- select GENERIC_GPIO
- help
- Enable gpiolib support for mpc5200 based boards
-
config PPC_MPC5200_LPBFIFO
tristate "MPC5200 LocalPlus bus FIFO driver"
depends on PPC_MPC52xx
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index 2bc8cd0c5cfc..4e62486791e9 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -14,5 +14,4 @@ ifeq ($(CONFIG_PPC_LITE5200),y)
obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o
endif
-obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o
obj-$(CONFIG_PPC_MPC5200_LPBFIFO) += mpc52xx_lpbfifo.o
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index da110bd88346..bfb11e01133e 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -264,7 +264,7 @@ mpc52xx_pci_setup(struct pci_controller *hose,
(unsigned long long)res->flags);
out_be32(&pci_regs->iw0btar,
MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
- res->end - res->start + 1));
+ resource_size(res)));
iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
if (res->flags & IORESOURCE_PREFETCH)
iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
@@ -278,7 +278,7 @@ mpc52xx_pci_setup(struct pci_controller *hose,
res->start, res->end, res->flags);
out_be32(&pci_regs->iw1btar,
MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
- res->end - res->start + 1));
+ resource_size(res)));
iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
if (res->flags & IORESOURCE_PREFETCH)
iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
@@ -300,7 +300,7 @@ mpc52xx_pci_setup(struct pci_controller *hose,
out_be32(&pci_regs->iw2btar,
MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
res->start,
- res->end - res->start + 1));
+ resource_size(res)));
iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
/* Set all the IWCR fields at once; they're in the same reg */
@@ -371,7 +371,7 @@ mpc52xx_add_bridge(struct device_node *node)
pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
- ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
if (of_address_to_resource(node, 0, &rsrc) != 0) {
printk(KERN_ERR "Can't get %s resources\n", node->full_name);
@@ -402,7 +402,7 @@ mpc52xx_add_bridge(struct device_node *node)
hose->ops = &mpc52xx_pci_ops;
- pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+ pci_regs = ioremap(rsrc.start, resource_size(&rsrc));
if (!pci_regs)
return -ENOMEM;
diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c
index 9761a59f175f..d111b024eafd 100644
--- a/arch/powerpc/platforms/82xx/pq2.c
+++ b/arch/powerpc/platforms/82xx/pq2.c
@@ -53,7 +53,7 @@ static void __init pq2_pci_add_bridge(struct device_node *np)
if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
goto err;
- ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
hose = pcibios_alloc_controller(np);
if (!hose)
diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c
index a2b9b9ef1240..c55129f5760a 100644
--- a/arch/powerpc/platforms/83xx/km83xx.c
+++ b/arch/powerpc/platforms/83xx/km83xx.c
@@ -28,7 +28,7 @@
#include <linux/of_device.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
@@ -101,7 +101,7 @@ static void __init mpc83xx_km_setup_arch(void)
__func__);
return;
}
- base = ioremap(res.start, res.end - res.start + 1);
+ base = ioremap(res.start, resource_size(&res));
/*
* IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2)
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index ec0b401bc9cf..32a52896822f 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -27,7 +27,7 @@
#include <linux/of_device.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
@@ -68,7 +68,7 @@ static void __init mpc832x_sys_setup_arch(void)
struct resource res;
of_address_to_resource(np, 0, &res);
- bcsr_regs = ioremap(res.start, res.end - res.start +1);
+ bcsr_regs = ioremap(res.start, resource_size(&res));
of_node_put(np);
}
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 81e44fa1c644..6b45969567d4 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -26,7 +26,7 @@
#include <linux/of_platform.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index d0a634b056ca..041c5177e737 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -26,7 +26,7 @@
#include <linux/of_platform.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
@@ -53,7 +53,7 @@ static int mpc834xemds_usb_cfg(void)
struct resource res;
of_address_to_resource(np, 0, &res);
- bcsr_regs = ioremap(res.start, res.end - res.start + 1);
+ bcsr_regs = ioremap(res.start, resource_size(&res));
of_node_put(np);
}
if (!bcsr_regs)
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 09e9d6fb7411..934cc8c46bbc 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -34,7 +34,7 @@
#include <linux/of_device.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
@@ -76,7 +76,7 @@ static void __init mpc836x_mds_setup_arch(void)
struct resource res;
of_address_to_resource(np, 0, &res);
- bcsr_regs = ioremap(res.start, res.end - res.start +1);
+ bcsr_regs = ioremap(res.start, resource_size(&res));
of_node_put(np);
}
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
index 49023dbe1576..af41d8c810a8 100644
--- a/arch/powerpc/platforms/83xx/sbc834x.c
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -28,7 +28,7 @@
#include <linux/of_platform.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index 2c64164722d0..1ad748bb39b4 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -171,7 +171,7 @@ int mpc831x_usb_cfg(void)
of_node_put(np);
return ret;
}
- usb_regs = ioremap(res.start, res.end - res.start + 1);
+ usb_regs = ioremap(res.start, resource_size(&res));
/* Using on-chip PHY */
if (prop && (!strcmp(prop, "utmi_wide") ||
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index b6976e1726e4..498534cd5265 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -67,6 +67,16 @@ config MPC85xx_RDB
help
This option enables support for the MPC85xx RDB (P2020 RDB) board
+config P1010_RDB
+ bool "Freescale P1010RDB"
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the MPC85xx RDB (P1010 RDB) board
+
+ P1010RDB contains P1010Si, which provides CPU performance up to 800
+ MHz and 1600 DMIPS, additional functionality and faster interfaces
+ (DDR3/3L, SATA II, and PCI Express).
+
config P1022_DS
bool "Freescale P1022 DS"
select DEFAULT_UIMAGE
@@ -75,6 +85,12 @@ config P1022_DS
help
This option enables support for the Freescale P1022DS reference board.
+config P1023_RDS
+ bool "Freescale P1023 RDS"
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the P1023 RDS board
+
config SOCRATES
bool "Socrates"
select DEFAULT_UIMAGE
@@ -155,6 +171,18 @@ config SBC8560
help
This option enables support for the Wind River SBC8560 board
+config P2040_RDB
+ bool "Freescale P2040 RDB"
+ select DEFAULT_UIMAGE
+ select PPC_E500MC
+ select PHYS_64BIT
+ select SWIOTLB
+ select MPC8xxx_GPIO
+ select HAS_RAPIDIO
+ select PPC_EPAPR_HV_PIC
+ help
+ This option enables support for the P2040 RDB board
+
config P3041_DS
bool "Freescale P3041 DS"
select DEFAULT_UIMAGE
@@ -163,6 +191,7 @@ config P3041_DS
select SWIOTLB
select MPC8xxx_GPIO
select HAS_RAPIDIO
+ select PPC_EPAPR_HV_PIC
help
This option enables support for the P3041 DS board
@@ -174,6 +203,7 @@ config P4080_DS
select SWIOTLB
select MPC8xxx_GPIO
select HAS_RAPIDIO
+ select PPC_EPAPR_HV_PIC
help
This option enables support for the P4080 DS board
@@ -188,6 +218,7 @@ config P5020_DS
select SWIOTLB
select MPC8xxx_GPIO
select HAS_RAPIDIO
+ select PPC_EPAPR_HV_PIC
help
This option enables support for the P5020 DS board
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index dd70db77d63e..a971b32c5c0a 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -10,7 +10,10 @@ obj-$(CONFIG_MPC8536_DS) += mpc8536_ds.o
obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o
obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
+obj-$(CONFIG_P1010_RDB) += p1010rdb.o
obj-$(CONFIG_P1022_DS) += p1022_ds.o
+obj-$(CONFIG_P1023_RDS) += p1023_rds.o
+obj-$(CONFIG_P2040_RDB) += p2040_rdb.o corenet_ds.o
obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o
obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o
obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
index 2ab338c9ac37..802ad110b757 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ b/arch/powerpc/platforms/85xx/corenet_ds.c
@@ -3,7 +3,7 @@
*
* Maintained by Kumar Gala (see MAINTAINERS for contact information)
*
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 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
@@ -22,6 +22,7 @@
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
#include <mm/mmu_decl.h>
#include <asm/prom.h>
#include <asm/udbg.h>
@@ -61,10 +62,6 @@ void __init corenet_ds_pic_init(void)
mpic_init(mpic);
}
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
/*
* Setup the architecture
*/
@@ -85,18 +82,19 @@ void __init corenet_ds_setup_arch(void)
#endif
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,p4080-pcie") {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == primary_phb_addr)
- fsl_add_bridge(np, 1);
- else
+ for_each_node_by_type(np, "pci") {
+ if (of_device_is_compatible(np, "fsl,p4080-pcie") ||
+ of_device_is_compatible(np, "fsl,qoriq-pcie-v2.2")) {
fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
+ hose = pci_find_hose_for_OF_device(np);
+ max = min(max, hose->dma_window_base_cur +
+ hose->dma_window_size);
+ }
}
+
+#ifdef CONFIG_PPC64
+ pci_devs_phb_init();
+#endif
#endif
#ifdef CONFIG_SWIOTLB
@@ -116,6 +114,19 @@ static const struct of_device_id of_device_ids[] __devinitconst = {
{
.compatible = "fsl,rapidio-delta",
},
+ {
+ .compatible = "fsl,p4080-pcie",
+ },
+ {
+ .compatible = "fsl,qoriq-pcie-v2.2",
+ },
+ /* The following two are for the Freescale hypervisor */
+ {
+ .name = "hypervisor",
+ },
+ {
+ .name = "handles",
+ },
{}
};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 6299a2a51ae8..2bf99786d249 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -31,7 +31,7 @@
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index c7b97f70312e..1b9a8cf1873a 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -83,7 +83,8 @@ void __init mpc85xx_ds_pic_init(void)
if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
mpic = mpic_alloc(np, r.start,
MPIC_PRIMARY |
- MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
+ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
+ MPIC_SINGLE_DEST_CPU,
0, 256, " OpenPIC ");
} else {
mpic = mpic_alloc(np, r.start,
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 747d1ee661fd..973b3f4a4b49 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -36,7 +36,7 @@
#include <linux/memblock.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 088f30b0c088..f5ff9110c97e 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -58,10 +58,11 @@ void __init mpc85xx_rdb_pic_init(void)
return;
}
- if (of_flat_dt_is_compatible(root, "fsl,85XXRDB-CAMP")) {
+ if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) {
mpic = mpic_alloc(np, r.start,
MPIC_PRIMARY |
- MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
+ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
+ MPIC_SINGLE_DEST_CPU,
0, 256, " OpenPIC ");
} else {
mpic = mpic_alloc(np, r.start,
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
new file mode 100644
index 000000000000..d7387fa7f534
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -0,0 +1,122 @@
+/*
+ * P1010RDB Board Setup
+ *
+ * Copyright 2011 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+void __init p1010_rdb_pic_init(void)
+{
+ struct mpic *mpic;
+ struct resource r;
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "open-pic");
+ if (np == NULL) {
+ printk(KERN_ERR "Could not find open-pic node\n");
+ return;
+ }
+
+ if (of_address_to_resource(np, 0, &r)) {
+ printk(KERN_ERR "Failed to map mpic register space\n");
+ of_node_put(np);
+ return;
+ }
+
+ mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET |
+ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
+ 0, 256, " OpenPIC ");
+
+ BUG_ON(mpic == NULL);
+ of_node_put(np);
+
+ mpic_init(mpic);
+
+}
+
+
+/*
+ * Setup the architecture
+ */
+static void __init p1010_rdb_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+ struct device_node *np;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("p1010_rdb_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+ for_each_node_by_type(np, "pci") {
+ if (of_device_is_compatible(np, "fsl,p1010-pcie"))
+ fsl_add_bridge(np, 0);
+ }
+
+#endif
+
+ printk(KERN_INFO "P1010 RDB board from Freescale Semiconductor\n");
+}
+
+static struct of_device_id __initdata p1010rdb_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .compatible = "simple-bus", },
+ {},
+};
+
+static int __init p1010rdb_publish_devices(void)
+{
+ return of_platform_bus_probe(NULL, p1010rdb_ids, NULL);
+}
+machine_device_initcall(p1010_rdb, p1010rdb_publish_devices);
+machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p1010_rdb_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "fsl,P1010RDB"))
+ return 1;
+ return 0;
+}
+
+define_machine(p1010_rdb) {
+ .name = "P1010 RDB",
+ .probe = p1010_rdb_probe,
+ .setup_arch = p1010_rdb_setup_arch,
+ .init_IRQ = p1010_rdb_pic_init,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 7eb5c40c069f..266b3aadfe5e 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -129,6 +129,7 @@ static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
static void p1022ds_set_monitor_port(int monitor_port)
{
struct device_node *pixis_node;
+ void __iomem *pixis;
u8 __iomem *brdcfg1;
pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
@@ -137,12 +138,12 @@ static void p1022ds_set_monitor_port(int monitor_port)
return;
}
- brdcfg1 = of_iomap(pixis_node, 0);
- if (!brdcfg1) {
+ pixis = of_iomap(pixis_node, 0);
+ if (!pixis) {
pr_err("p1022ds: could not map ngPIXIS registers\n");
return;
}
- brdcfg1 += 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */
+ brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */
switch (monitor_port) {
case 0: /* DVI */
@@ -158,6 +159,8 @@ static void p1022ds_set_monitor_port(int monitor_port)
default:
pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
}
+
+ iounmap(pixis);
}
/**
@@ -192,8 +195,13 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
do_div(temp, pixclock);
freq = temp;
- /* pixclk is the ratio of the platform clock to the pixel clock */
+ /*
+ * 'pxclk' is the ratio of the platform clock to the pixel clock.
+ * This number is programmed into the CLKDVDR register, and the valid
+ * range of values is 2-255.
+ */
pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+ pxclk = clamp_t(u32, pxclk, 2, 255);
/* Disable the pixel clock, and set it to non-inverted and no delay */
clrbits32(&guts->clkdvdr,
@@ -201,6 +209,8 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
/* Enable the clock and set the pxclk */
setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+ iounmap(guts);
}
/**
diff --git a/arch/powerpc/platforms/85xx/p1023_rds.c b/arch/powerpc/platforms/85xx/p1023_rds.c
new file mode 100644
index 000000000000..835e0b335bfa
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p1023_rds.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * Description:
+ * P1023 RDS Board Setup
+ *
+ * This program is free software; you can redistribute it and/or modify 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/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+#ifdef CONFIG_SMP
+void __init mpc85xx_smp_init(void);
+#endif
+
+static void __init mpc85xx_rds_setup_arch(void)
+{
+ struct device_node *np;
+
+ if (ppc_md.progress)
+ ppc_md.progress("p1023_rds_setup_arch()", 0);
+
+ /* Map BCSR area */
+ np = of_find_node_by_name(NULL, "bcsr");
+ if (np != NULL) {
+ static u8 __iomem *bcsr_regs;
+
+ bcsr_regs = of_iomap(np, 0);
+ of_node_put(np);
+
+ if (!bcsr_regs) {
+ printk(KERN_ERR
+ "BCSR: Failed to map bcsr register space\n");
+ return;
+ } else {
+#define BCSR15_I2C_BUS0_SEG_CLR 0x07
+#define BCSR15_I2C_BUS0_SEG2 0x02
+/*
+ * Note: Accessing exclusively i2c devices.
+ *
+ * The i2c controller selects initially ID EEPROM in the u-boot;
+ * but if menu configuration selects RTC support in the kernel,
+ * the i2c controller switches to select RTC chip in the kernel.
+ */
+#ifdef CONFIG_RTC_CLASS
+ /* Enable RTC chip on the segment #2 of i2c */
+ clrbits8(&bcsr_regs[15], BCSR15_I2C_BUS0_SEG_CLR);
+ setbits8(&bcsr_regs[15], BCSR15_I2C_BUS0_SEG2);
+#endif
+
+ iounmap(bcsr_regs);
+ }
+ }
+
+#ifdef CONFIG_PCI
+ for_each_compatible_node(np, "pci", "fsl,p1023-pcie")
+ fsl_add_bridge(np, 0);
+#endif
+
+#ifdef CONFIG_SMP
+ mpc85xx_smp_init();
+#endif
+}
+
+static struct of_device_id p1023_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .compatible = "simple-bus", },
+ {},
+};
+
+
+static int __init p1023_publish_devices(void)
+{
+ of_platform_bus_probe(NULL, p1023_ids, NULL);
+
+ return 0;
+}
+
+machine_device_initcall(p1023_rds, p1023_publish_devices);
+
+static void __init mpc85xx_rds_pic_init(void)
+{
+ struct mpic *mpic;
+ struct resource r;
+ struct device_node *np = NULL;
+
+ np = of_find_node_by_type(NULL, "open-pic");
+ if (!np) {
+ printk(KERN_ERR "Could not find open-pic node\n");
+ return;
+ }
+
+ if (of_address_to_resource(np, 0, &r)) {
+ printk(KERN_ERR "Failed to map mpic register space\n");
+ of_node_put(np);
+ return;
+ }
+
+ mpic = mpic_alloc(np, r.start,
+ MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN |
+ MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
+ 0, 256, " OpenPIC ");
+
+ BUG_ON(mpic == NULL);
+ of_node_put(np);
+
+ mpic_init(mpic);
+}
+
+static int __init p1023_rds_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "fsl,P1023RDS");
+
+}
+
+define_machine(p1023_rds) {
+ .name = "P1023 RDS",
+ .probe = p1023_rds_probe,
+ .setup_arch = mpc85xx_rds_setup_arch,
+ .init_IRQ = mpc85xx_rds_pic_init,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};
+
diff --git a/arch/powerpc/platforms/85xx/p2040_rdb.c b/arch/powerpc/platforms/85xx/p2040_rdb.c
new file mode 100644
index 000000000000..32b56ac73dfb
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p2040_rdb.c
@@ -0,0 +1,88 @@
+/*
+ * P2040 RDB Setup
+ *
+ * Copyright 2011 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p2040_rdb_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+ extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+ if (of_flat_dt_is_compatible(root, "fsl,P2040RDB"))
+ return 1;
+
+ /* Check if we're running under the Freescale hypervisor */
+ if (of_flat_dt_is_compatible(root, "fsl,P2040RDB-hv")) {
+ ppc_md.init_IRQ = ehv_pic_init;
+ ppc_md.get_irq = ehv_pic_get_irq;
+ ppc_md.restart = fsl_hv_restart;
+ ppc_md.power_off = fsl_hv_halt;
+ ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+ /*
+ * Disable the timebase sync operations because we can't write
+ * to the timebase registers under the hypervisor.
+ */
+ smp_85xx_ops.give_timebase = NULL;
+ smp_85xx_ops.take_timebase = NULL;
+#endif
+ return 1;
+ }
+
+ return 0;
+}
+
+define_machine(p2040_rdb) {
+ .name = "P2040 RDB",
+ .probe = p2040_rdb_probe,
+ .setup_arch = corenet_ds_setup_arch,
+ .init_IRQ = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+ .get_irq = mpic_get_coreint_irq,
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+ .power_save = e500_idle,
+};
+
+machine_device_initcall(p2040_rdb, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p2040_rdb, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
index 0ed52e18298c..96d99a374dcf 100644
--- a/arch/powerpc/platforms/85xx/p3041_ds.c
+++ b/arch/powerpc/platforms/85xx/p3041_ds.c
@@ -30,6 +30,7 @@
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
#include "corenet_ds.h"
@@ -39,8 +40,32 @@
static int __init p3041_ds_probe(void)
{
unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+ extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+ if (of_flat_dt_is_compatible(root, "fsl,P3041DS"))
+ return 1;
+
+ /* Check if we're running under the Freescale hypervisor */
+ if (of_flat_dt_is_compatible(root, "fsl,P3041DS-hv")) {
+ ppc_md.init_IRQ = ehv_pic_init;
+ ppc_md.get_irq = ehv_pic_get_irq;
+ ppc_md.restart = fsl_hv_restart;
+ ppc_md.power_off = fsl_hv_halt;
+ ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+ /*
+ * Disable the timebase sync operations because we can't write
+ * to the timebase registers under the hypervisor.
+ */
+ smp_85xx_ops.give_timebase = NULL;
+ smp_85xx_ops.take_timebase = NULL;
+#endif
+ return 1;
+ }
- return of_flat_dt_is_compatible(root, "fsl,P3041DS");
+ return 0;
}
define_machine(p3041_ds) {
@@ -55,6 +80,7 @@ define_machine(p3041_ds) {
.restart = fsl_rstcr_restart,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
+ .power_save = e500_idle,
};
machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c
index 84170460497b..d1b21d7663e3 100644
--- a/arch/powerpc/platforms/85xx/p4080_ds.c
+++ b/arch/powerpc/platforms/85xx/p4080_ds.c
@@ -29,31 +29,42 @@
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
#include "corenet_ds.h"
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
/*
* Called very early, device-tree isn't unflattened
*/
static int __init p4080_ds_probe(void)
{
unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+ extern struct smp_ops_t smp_85xx_ops;
+#endif
- if (of_flat_dt_is_compatible(root, "fsl,P4080DS")) {
-#ifdef CONFIG_PCI
- /* treat PCIe1 as primary,
- * shouldn't matter as we have no ISA on the board
- */
- primary_phb_addr = 0x0000;
+ if (of_flat_dt_is_compatible(root, "fsl,P4080DS"))
+ return 1;
+
+ /* Check if we're running under the Freescale hypervisor */
+ if (of_flat_dt_is_compatible(root, "fsl,P4080DS-hv")) {
+ ppc_md.init_IRQ = ehv_pic_init;
+ ppc_md.get_irq = ehv_pic_get_irq;
+ ppc_md.restart = fsl_hv_restart;
+ ppc_md.power_off = fsl_hv_halt;
+ ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+ /*
+ * Disable the timebase sync operations because we can't write
+ * to the timebase registers under the hypervisor.
+ */
+ smp_85xx_ops.give_timebase = NULL;
+ smp_85xx_ops.take_timebase = NULL;
#endif
return 1;
- } else {
- return 0;
}
+
+ return 0;
}
define_machine(p4080_ds) {
@@ -68,7 +79,10 @@ define_machine(p4080_ds) {
.restart = fsl_rstcr_restart,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
+ .power_save = e500_idle,
};
machine_device_initcall(p4080_ds, corenet_ds_publish_devices);
+#ifdef CONFIG_SWIOTLB
machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
index 7467b712ee00..e8cba5004fd8 100644
--- a/arch/powerpc/platforms/85xx/p5020_ds.c
+++ b/arch/powerpc/platforms/85xx/p5020_ds.c
@@ -30,6 +30,7 @@
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
#include "corenet_ds.h"
@@ -39,8 +40,32 @@
static int __init p5020_ds_probe(void)
{
unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+ extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+ if (of_flat_dt_is_compatible(root, "fsl,P5020DS"))
+ return 1;
+
+ /* Check if we're running under the Freescale hypervisor */
+ if (of_flat_dt_is_compatible(root, "fsl,P5020DS-hv")) {
+ ppc_md.init_IRQ = ehv_pic_init;
+ ppc_md.get_irq = ehv_pic_get_irq;
+ ppc_md.restart = fsl_hv_restart;
+ ppc_md.power_off = fsl_hv_halt;
+ ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+ /*
+ * Disable the timebase sync operations because we can't write
+ * to the timebase registers under the hypervisor.
+ */
+ smp_85xx_ops.give_timebase = NULL;
+ smp_85xx_ops.take_timebase = NULL;
+#endif
+ return 1;
+ }
- return of_flat_dt_is_compatible(root, "fsl,P5020DS");
+ return 0;
}
define_machine(p5020_ds) {
@@ -60,6 +85,11 @@ define_machine(p5020_ds) {
.restart = fsl_rstcr_restart,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
+#ifdef CONFIG_PPC64
+ .power_save = book3e_idle,
+#else
+ .power_save = e500_idle,
+#endif
};
machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index ecdd8c09e4ed..d07dcb7f4ee9 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -34,7 +34,7 @@
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index d2dfd465fbf6..09ced7221750 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -285,7 +285,7 @@ static int __init sbc8560_bdrstcr_init(void)
printk(KERN_INFO "sbc8560: Found BRSTCR at i/o 0x%x\n", res.start);
- brstcr = ioremap(res.start, res.end - res.start);
+ brstcr = ioremap(res.start, resource_size(&res));
if(!brstcr)
printk(KERN_WARNING "sbc8560: ioremap of brstcr failed.\n");
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index d6a93a10c0f5..5b9b901f6443 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -2,7 +2,7 @@
* Author: Andy Fleming <afleming@freescale.com>
* Kumar Gala <galak@kernel.crashing.org>
*
- * Copyright 2006-2008 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011 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
@@ -111,14 +111,6 @@ smp_85xx_kick_cpu(int nr)
return 0;
}
-static void __init
-smp_85xx_setup_cpu(int cpu_nr)
-{
- mpic_setup_this_cpu();
- if (cpu_has_feature(CPU_FTR_DBELL))
- doorbell_setup_this_cpu();
-}
-
struct smp_ops_t smp_85xx_ops = {
.kick_cpu = smp_85xx_kick_cpu,
#ifdef CONFIG_KEXEC
@@ -224,24 +216,36 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
}
#endif /* CONFIG_KEXEC */
+static void __init
+smp_85xx_setup_cpu(int cpu_nr)
+{
+ if (smp_85xx_ops.probe == smp_mpic_probe)
+ mpic_setup_this_cpu();
+
+ if (cpu_has_feature(CPU_FTR_DBELL))
+ doorbell_setup_this_cpu();
+}
+
void __init mpc85xx_smp_init(void)
{
struct device_node *np;
+ smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
+
np = of_find_node_by_type(NULL, "open-pic");
if (np) {
smp_85xx_ops.probe = smp_mpic_probe;
- smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
smp_85xx_ops.message_pass = smp_mpic_message_pass;
}
if (cpu_has_feature(CPU_FTR_DBELL)) {
- smp_85xx_ops.message_pass = smp_muxed_ipi_message_pass;
+ /*
+ * If left NULL, .message_pass defaults to
+ * smp_muxed_ipi_message_pass
+ */
smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
}
- BUG_ON(!smp_85xx_ops.message_pass);
-
smp_ops = &smp_85xx_ops;
#ifdef CONFIG_KEXEC
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 0125604d096e..a9dc5e795123 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -123,7 +123,7 @@ static void xes_mpc85xx_fixups(void)
continue;
}
- l2_base = ioremap(r[0].start, r[0].end - r[0].start + 1);
+ l2_base = ioremap(r[0].start, resource_size(&r[0]));
xes_mpc85xx_configure_l2(l2_base);
}
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index a896511690c2..74e018ef724b 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -39,12 +39,19 @@
#include <sysdev/fsl_pci.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/simple_gpio.h>
+#include <asm/fsl_guts.h>
#include "mpc86xx.h"
static struct device_node *pixis_node;
static unsigned char *pixis_bdcfg0, *pixis_arch;
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN 0x80000000
+#define CLKDVDR_PXCKINV 0x10000000
+#define CLKDVDR_PXCKDLY 0x06000000
+#define CLKDVDR_PXCLK_MASK 0x001F0000
+
#ifdef CONFIG_SUSPEND
static irqreturn_t mpc8610_sw9_irq(int irq, void *data)
{
@@ -205,72 +212,54 @@ void mpc8610hpcd_set_monitor_port(int monitor_port)
bdcfg[monitor_port]);
}
+/**
+ * mpc8610hpcd_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
{
- u32 __iomem *clkdvdr;
- u32 temp;
- /* variables for pixel clock calcs */
- ulong bestval, bestfreq, speed_ccb, minpixclock, maxpixclock;
- ulong pixval;
- long err;
- int i;
-
- clkdvdr = ioremap(get_immrbase() + 0xe0800, sizeof(u32));
- if (!clkdvdr) {
- printk(KERN_ERR "Err: can't map clock divider register!\n");
+ struct device_node *guts_np = NULL;
+ struct ccsr_guts_86xx __iomem *guts;
+ unsigned long freq;
+ u64 temp;
+ u32 pxclk;
+
+ /* Map the global utilities registers. */
+ guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
+ if (!guts_np) {
+ pr_err("mpc8610hpcd: missing global utilties device node\n");
return;
}
- /* Pixel Clock configuration */
- speed_ccb = fsl_get_sys_freq();
-
- /* Calculate the pixel clock with the smallest error */
- /* calculate the following in steps to avoid overflow */
- pr_debug("DIU pixclock in ps - %d\n", pixclock);
- temp = 1000000000/pixclock;
- temp *= 1000;
- pixclock = temp;
- pr_debug("DIU pixclock freq - %u\n", pixclock);
-
- temp = pixclock * 5 / 100;
- pr_debug("deviation = %d\n", temp);
- minpixclock = pixclock - temp;
- maxpixclock = pixclock + temp;
- pr_debug("DIU minpixclock - %lu\n", minpixclock);
- pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
- pixval = speed_ccb/pixclock;
- pr_debug("DIU pixval = %lu\n", pixval);
-
- err = 100000000;
- bestval = pixval;
- pr_debug("DIU bestval = %lu\n", bestval);
-
- bestfreq = 0;
- for (i = -1; i <= 1; i++) {
- temp = speed_ccb / ((pixval+i) + 1);
- pr_debug("DIU test pixval i= %d, pixval=%lu, temp freq. = %u\n",
- i, pixval, temp);
- if ((temp < minpixclock) || (temp > maxpixclock))
- pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
- minpixclock, maxpixclock);
- else if (abs(temp - pixclock) < err) {
- pr_debug("Entered the else if block %d\n", i);
- err = abs(temp - pixclock);
- bestval = pixval+i;
- bestfreq = temp;
- }
+ guts = of_iomap(guts_np, 0);
+ of_node_put(guts_np);
+ if (!guts) {
+ pr_err("mpc8610hpcd: could not map global utilties device\n");
+ return;
}
- pr_debug("DIU chose = %lx\n", bestval);
- pr_debug("DIU error = %ld\n NomPixClk ", err);
- pr_debug("DIU: Best Freq = %lx\n", bestfreq);
- /* Modify PXCLK in GUTS CLKDVDR */
- pr_debug("DIU: Current value of CLKDVDR = 0x%08x\n", (*clkdvdr));
- temp = (*clkdvdr) & 0x2000FFFF;
- *clkdvdr = temp; /* turn off clock */
- *clkdvdr = temp | 0x80000000 | (((bestval) & 0x1F) << 16);
- pr_debug("DIU: Modified value of CLKDVDR = 0x%08x\n", (*clkdvdr));
- iounmap(clkdvdr);
+ /* Convert pixclock from a wavelength to a frequency */
+ temp = 1000000000000ULL;
+ do_div(temp, pixclock);
+ freq = temp;
+
+ /*
+ * 'pxclk' is the ratio of the platform clock to the pixel clock.
+ * On the MPC8610, the value programmed into CLKDVDR is the ratio
+ * minus one. The valid range of values is 2-31.
+ */
+ pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq) - 1;
+ pxclk = clamp_t(u32, pxclk, 2, 31);
+
+ /* Disable the pixel clock, and set it to non-inverted and no delay */
+ clrbits32(&guts->clkdvdr,
+ CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+ /* Enable the clock and set the pxclk */
+ setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+ iounmap(guts);
}
ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index f970ca2b180c..d0af7fb2f344 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -78,6 +78,10 @@ config MPIC
bool
default n
+config PPC_EPAPR_HV_PIC
+ bool
+ default n
+
config MPIC_WEIRD
bool
default n
@@ -266,7 +270,7 @@ config TAU_AVERAGE
config QUICC_ENGINE
bool "Freescale QUICC Engine (QE) Support"
- depends on FSL_SOC
+ depends on FSL_SOC && PPC32
select PPC_LIB_RHEAP
select CRC32
help
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 2165b65876f9..e06e39589a09 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -1,7 +1,6 @@
config PPC64
bool "64-bit kernel"
default n
- select PPC_HAVE_PMU_SUPPORT
help
This option selects whether a 32-bit or a 64-bit kernel
will be built.
@@ -69,6 +68,7 @@ choice
config PPC_BOOK3S_64
bool "Server processors"
select PPC_FPU
+ select PPC_HAVE_PMU_SUPPORT
config PPC_BOOK3E_64
bool "Embedded processors"
diff --git a/arch/powerpc/platforms/amigaone/Kconfig b/arch/powerpc/platforms/amigaone/Kconfig
index 022476717718..128de25cc284 100644
--- a/arch/powerpc/platforms/amigaone/Kconfig
+++ b/arch/powerpc/platforms/amigaone/Kconfig
@@ -8,7 +8,7 @@ config AMIGAONE
select NOT_COHERENT_CACHE
select CHECK_CACHE_COHERENCY
select DEFAULT_UIMAGE
- select PCSPKR_PLATFORM
+ select HAVE_PCSPKR_PLATFORM
help
Select AmigaOne for the following machines:
- AmigaOne SE/Teron CX (G3 only)
diff --git a/arch/powerpc/platforms/cell/celleb_scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c
index 05b0db3ef638..844c0facb4f7 100644
--- a/arch/powerpc/platforms/cell/celleb_scc_epci.c
+++ b/arch/powerpc/platforms/cell/celleb_scc_epci.c
@@ -393,19 +393,19 @@ static int __init celleb_setup_epci(struct device_node *node,
if (of_address_to_resource(node, 0, &r))
goto error;
- hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
+ hose->cfg_addr = ioremap(r.start, resource_size(&r));
if (!hose->cfg_addr)
goto error;
pr_debug("EPCI: cfg_addr map 0x%016llx->0x%016lx + 0x%016llx\n",
- r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1));
+ r.start, (unsigned long)hose->cfg_addr, resource_size(&r));
if (of_address_to_resource(node, 2, &r))
goto error;
- hose->cfg_data = ioremap(r.start, (r.end - r.start + 1));
+ hose->cfg_data = ioremap(r.start, resource_size(&r));
if (!hose->cfg_data)
goto error;
pr_debug("EPCI: cfg_data map 0x%016llx->0x%016lx + 0x%016llx\n",
- r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1));
+ r.start, (unsigned long)hose->cfg_data, resource_size(&r));
hose->ops = &celleb_epci_ops;
celleb_epci_init(hose);
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
index a881bbee8de0..ae790ac4a589 100644
--- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
@@ -494,7 +494,7 @@ static __init int celleb_setup_pciex(struct device_node *node,
pr_err("PCIEXC:Failed to get config resource.\n");
return 1;
}
- phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
+ phb->cfg_addr = ioremap(r.start, resource_size(&r));
if (!phb->cfg_addr) {
pr_err("PCIEXC:Failed to remap SMMIO region.\n");
return 1;
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
index d809836bcf5f..7f92096fe968 100644
--- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -24,7 +24,7 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/machdep.h>
#include <asm/spu.h>
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index dbb641ea90dd..f2e1dfe4bf31 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -28,7 +28,7 @@
#include <linux/cpu.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index f465d474ad9b..4e5c91489c02 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -222,7 +222,7 @@ static int spu_map_resource(struct spu *spu, int nr,
return ret;
if (phys)
*phys = resource.start;
- len = resource.end - resource.start + 1;
+ len = resource_size(&resource);
*virt = ioremap(resource.start, len);
if (!*virt)
return -EINVAL;
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 0c87bcd2452a..bf4d41d8fa14 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -24,7 +24,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/spu.h>
#include <asm/spu_csa.h>
#include "spufs.h"
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 3c7c3f82d842..fb59c46e9e9e 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1850,9 +1850,16 @@ out:
return ret;
}
-static int spufs_mfc_fsync(struct file *file, int datasync)
+static int spufs_mfc_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
- return spufs_mfc_flush(file, NULL);
+ struct inode *inode = file->f_path.dentry->d_inode;
+ int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ if (!err) {
+ mutex_lock(&inode->i_mutex);
+ err = spufs_mfc_flush(file, NULL);
+ mutex_unlock(&inode->i_mutex);
+ }
+ return err;
}
static int spufs_mfc_fasync(int fd, struct file *file, int on)
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 856e9c398068..e481f6b9a789 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -611,15 +611,14 @@ out:
static struct file_system_type spufs_type;
-long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
- struct file *filp)
+long spufs_create(struct path *path, struct dentry *dentry,
+ unsigned int flags, mode_t mode, struct file *filp)
{
- struct dentry *dentry;
int ret;
ret = -EINVAL;
/* check if we are on spufs */
- if (nd->path.dentry->d_sb->s_type != &spufs_type)
+ if (path->dentry->d_sb->s_type != &spufs_type)
goto out;
/* don't accept undefined flags */
@@ -627,33 +626,27 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
goto out;
/* only threads can be underneath a gang */
- if (nd->path.dentry != nd->path.dentry->d_sb->s_root) {
+ if (path->dentry != path->dentry->d_sb->s_root) {
if ((flags & SPU_CREATE_GANG) ||
- !SPUFS_I(nd->path.dentry->d_inode)->i_gang)
+ !SPUFS_I(path->dentry->d_inode)->i_gang)
goto out;
}
- dentry = lookup_create(nd, 1);
- ret = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out_dir;
-
mode &= ~current_umask();
if (flags & SPU_CREATE_GANG)
- ret = spufs_create_gang(nd->path.dentry->d_inode,
- dentry, nd->path.mnt, mode);
+ ret = spufs_create_gang(path->dentry->d_inode,
+ dentry, path->mnt, mode);
else
- ret = spufs_create_context(nd->path.dentry->d_inode,
- dentry, nd->path.mnt, flags, mode,
+ ret = spufs_create_context(path->dentry->d_inode,
+ dentry, path->mnt, flags, mode,
filp);
if (ret >= 0)
- fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
+ fsnotify_mkdir(path->dentry->d_inode, dentry);
return ret;
-out_dir:
- mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
out:
+ mutex_unlock(&path->dentry->d_inode->i_mutex);
return ret;
}
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index c448bac65518..099245f230b2 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -248,7 +248,7 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[];
/* system call implementation */
extern struct spufs_calls spufs_calls;
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
-long spufs_create(struct nameidata *nd, unsigned int flags,
+long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags,
mode_t mode, struct file *filp);
/* ELF coredump callbacks for writing SPU ELF notes */
extern int spufs_coredump_extra_notes_size(void);
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index a3d2ce54ea2e..609e016e92d0 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -62,21 +62,17 @@ out:
static long do_spu_create(const char __user *pathname, unsigned int flags,
mode_t mode, struct file *neighbor)
{
- char *tmp;
+ struct path path;
+ struct dentry *dentry;
int ret;
- tmp = getname(pathname);
- ret = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- struct nameidata nd;
-
- ret = kern_path_parent(tmp, &nd);
- if (!ret) {
- nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
- ret = spufs_create(&nd, flags, mode, neighbor);
- path_put(&nd.path);
- }
- putname(tmp);
+ dentry = user_path_create(AT_FDCWD, pathname, &path, 1);
+ ret = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ ret = spufs_create(&path, dentry, flags, mode, neighbor);
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ dput(dentry);
+ path_put(&path);
}
return ret;
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
index bc0b0efdc5fe..d3cdab582c5d 100644
--- a/arch/powerpc/platforms/chrp/Kconfig
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -1,6 +1,7 @@
config PPC_CHRP
bool "Common Hardware Reference Platform (CHRP) based machines"
depends on 6xx
+ select HAVE_PCSPKR_PLATFORM
select MPIC
select PPC_I8259
select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 8f67a394b2d0..83285c5a2049 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -142,7 +142,7 @@ hydra_init(void)
return 0;
}
of_node_put(np);
- Hydra = ioremap(r.start, r.end-r.start);
+ Hydra = ioremap(r.start, resource_size(&r));
printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start);
printk("Hydra Feature_Control was %x",
in_le32(&Hydra->Feature_Control));
@@ -199,7 +199,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
printk ("RTAS supporting Pegasos OF not found, please upgrade"
" your firmware\n");
}
- ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
/* keep the reference to the root node */
}
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c
index a800122e4dda..feab30bbae23 100644
--- a/arch/powerpc/platforms/chrp/smp.c
+++ b/arch/powerpc/platforms/chrp/smp.c
@@ -18,7 +18,7 @@
#include <linux/spinlock.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
index 29c02f36b32f..f519ee17ff7d 100644
--- a/arch/powerpc/platforms/iseries/exception.S
+++ b/arch/powerpc/platforms/iseries/exception.S
@@ -167,7 +167,7 @@ BEGIN_FTR_SECTION
std r12,PACA_EXGEN+EX_R13(r13)
EXCEPTION_PROLOG_ISERIES_1
FTR_SECTION_ELSE
- EXCEPTION_PROLOG_1(PACA_EXGEN)
+ EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0)
EXCEPTION_PROLOG_ISERIES_1
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
b data_access_common
diff --git a/arch/powerpc/platforms/iseries/exception.h b/arch/powerpc/platforms/iseries/exception.h
index bae3fba5ad8e..50271b550a99 100644
--- a/arch/powerpc/platforms/iseries/exception.h
+++ b/arch/powerpc/platforms/iseries/exception.h
@@ -39,7 +39,7 @@
label##_iSeries: \
HMT_MEDIUM; \
mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
- EXCEPTION_PROLOG_1(area); \
+ EXCEPTION_PROLOG_1(area, NOTEST, 0); \
EXCEPTION_PROLOG_ISERIES_1; \
b label##_common
@@ -48,7 +48,7 @@ label##_iSeries: \
label##_iSeries: \
HMT_MEDIUM; \
mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
- EXCEPTION_PROLOG_1(PACA_EXGEN); \
+ EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0); \
lbz r10,PACASOFTIRQEN(r13); \
cmpwi 0,r10,0; \
beq- label##_iSeries_masked; \
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index e3265adde5d3..8bda9be06fa0 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -29,7 +29,7 @@
#include <linux/cpu.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -75,7 +75,7 @@ static void __devinit smp_iSeries_setup_cpu(int nr)
}
static struct smp_ops_t iSeries_smp_ops = {
- .message_pass = smp_muxed_ipi_message_pass,
+ .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
.cause_ipi = smp_iSeries_cause_ipi,
.probe = smp_iSeries_probe,
.kick_cpu = smp_iSeries_kick_cpu,
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index fe34c3d9bb74..5b3388b9f911 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -338,35 +338,16 @@ define_machine(maple) {
#ifdef CONFIG_EDAC
/*
* Register a platform device for CPC925 memory controller on
- * Motorola ATCA-6101 blade.
+ * all boards with U3H (CPC925) bridge.
*/
-#define MAPLE_CPC925_MODEL "Motorola,ATCA-6101"
static int __init maple_cpc925_edac_setup(void)
{
struct platform_device *pdev;
struct device_node *np = NULL;
struct resource r;
- const unsigned char *model;
int ret;
-
- np = of_find_node_by_path("/");
- if (!np) {
- printk(KERN_ERR "%s: Unable to get root node\n", __func__);
- return -ENODEV;
- }
-
- model = (const unsigned char *)of_get_property(np, "model", NULL);
- if (!model) {
- printk(KERN_ERR "%s: Unabel to get model info\n", __func__);
- of_node_put(np);
- return -ENODEV;
- }
-
- ret = strcmp(model, MAPLE_CPC925_MODEL);
- of_node_put(np);
-
- if (ret != 0)
- return 0;
+ volatile void __iomem *mem;
+ u32 rev;
np = of_find_node_by_type(NULL, "memory-controller");
if (!np) {
@@ -384,6 +365,22 @@ static int __init maple_cpc925_edac_setup(void)
return -ENODEV;
}
+ mem = ioremap(r.start, resource_size(&r));
+ if (!mem) {
+ printk(KERN_ERR "%s: Unable to map memory-controller memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ rev = __raw_readl(mem);
+ iounmap(mem);
+
+ if (rev < 0x34 || rev > 0x3f) { /* U3H */
+ printk(KERN_ERR "%s: Non-CPC925(U3H) bridge revision: %02x\n",
+ __func__, rev);
+ return 0;
+ }
+
pdev = platform_device_register_simple("cpc925_edac", 0, &r, 1);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c
index 321a9b3a2d00..756123bf06ac 100644
--- a/arch/powerpc/platforms/pasemi/dma_lib.c
+++ b/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -576,7 +576,7 @@ int pasemi_dma_init(void)
res.start = 0xfd800000;
res.end = res.start + 0x1000;
}
- dma_status = __ioremap(res.start, res.end-res.start, 0);
+ dma_status = __ioremap(res.start, resource_size(&res), 0);
pci_dev_put(iob_pdev);
for (i = 0; i < MAX_TXCH; i++)
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index d679964ae2ab..c2f3e861f5ea 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -12,7 +12,7 @@
#include <linux/backlight.h>
#include <linux/adb.h>
#include <linux/pmu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/prom.h>
#include <asm/backlight.h>
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index b1cdcf94aa8e..695443bfdb08 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -580,10 +580,10 @@ int __init pmac_nvram_init(void)
/* Try to obtain an address */
if (of_address_to_resource(dp, 0, &r1) == 0) {
nvram_naddrs = 1;
- s1 = (r1.end - r1.start) + 1;
+ s1 = resource_size(&r1);
if (of_address_to_resource(dp, 1, &r2) == 0) {
nvram_naddrs = 2;
- s2 = (r2.end - r2.start) + 1;
+ s2 = resource_size(&r2);
}
}
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f33e08d573ce..5cc83851ad06 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
+#include <linux/of_pci.h>
#include <asm/sections.h>
#include <asm/io.h>
@@ -235,7 +236,7 @@ static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
if (offset >= 0x100)
return PCIBIOS_BAD_REGISTER_NUMBER;
- np = pci_busdev_to_OF_node(bus, devfn);
+ np = of_pci_find_child_device(bus->dev.of_node, devfn);
if (np == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -731,7 +732,7 @@ static void __init setup_bandit(struct pci_controller *hose,
static int __init setup_uninorth(struct pci_controller *hose,
struct resource *addr)
{
- ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
has_uninorth = 1;
hose->ops = &macrisc_pci_ops;
hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -838,8 +839,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
* into cfg_addr
*/
hose->cfg_data = ioremap(cfg_res.start, 0x02000000);
- hose->cfg_addr = ioremap(self_res.start,
- self_res.end - self_res.start + 1);
+ hose->cfg_addr = ioremap(self_res.start, resource_size(&self_res));
/*
* /ht node doesn't expose a "ranges" property, we read the register
@@ -998,7 +998,7 @@ void __init pmac_pci_init(void)
struct device_node *np, *root;
struct device_node *ht = NULL;
- ppc_pci_set_flags(PPC_PCI_CAN_SKIP_ISA_ALIGN);
+ pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
root = of_find_node_by_path("/");
if (root == NULL) {
@@ -1057,7 +1057,7 @@ void __init pmac_pci_init(void)
* some offset between bus number and domains for now when we
* assign all busses should help for now
*/
- if (ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
+ if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
pcibios_assign_bus_offset = 0x10;
#endif
}
@@ -1323,8 +1323,7 @@ static void fixup_u4_pcie(struct pci_dev* dev)
*/
if (r->start >= 0xf0000000 && r->start < 0xf3000000)
continue;
- if (!region || (r->end - r->start) >
- (region->end - region->start))
+ if (!region || resource_size(r) > resource_size(region))
region = r;
}
/* Nothing found, bail */
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index aa45281bd296..a028f08309d6 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -355,9 +355,6 @@ static int initializing = 1;
static int pmac_late_init(void)
{
initializing = 0;
- /* this is udbg (which is __init) and we can later use it during
- * cpu hotplug (in smp_core99_kick_cpu) */
- ppc_md.progress = NULL;
return 0;
}
machine_late_initcall(powermac, pmac_late_init);
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index db092d7c4c5b..9a521dc8e485 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -35,7 +35,7 @@
#include <linux/compiler.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/code-patching.h>
#include <asm/irq.h>
#include <asm/page.h>
@@ -447,7 +447,7 @@ void __init smp_psurge_give_timebase(void)
/* PowerSurge-style Macs */
struct smp_ops_t psurge_smp_ops = {
- .message_pass = smp_muxed_ipi_message_pass,
+ .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
.cause_ipi = smp_psurge_cause_ipi,
.probe = smp_psurge_probe,
.kick_cpu = smp_psurge_kick_cpu,
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 48211ca134c3..11c9fce43b5b 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -274,7 +274,7 @@ int __init via_calibrate_decr(void)
return 0;
}
of_node_put(vias);
- via = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+ via = ioremap(rsrc.start, resource_size(&rsrc));
if (via == NULL) {
printk(KERN_ERR "Failed to map VIA for timer calibration !\n");
return 0;
diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig
index bf8330ef2e76..f0536c7cda9f 100644
--- a/arch/powerpc/platforms/prep/Kconfig
+++ b/arch/powerpc/platforms/prep/Kconfig
@@ -1,6 +1,7 @@
config PPC_PREP
bool "PowerPC Reference Platform (PReP) based machines"
depends on 6xx && BROKEN
+ select HAVE_PCSPKR_PLATFORM
select MPIC
select PPC_I8259
select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 71af4c5d6c05..05cf4769b88c 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -1,6 +1,7 @@
config PPC_PSERIES
depends on PPC64 && PPC_BOOK3S
bool "IBM pSeries & new (POWER5-based) iSeries"
+ select HAVE_PCSPKR_PLATFORM
select MPIC
select PCI_MSI
select PPC_XICS
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 57ceb92b2288..e9be25bc571b 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -262,12 +262,11 @@ int dlpar_attach_node(struct device_node *dn)
if (!dn->parent)
return -ENOMEM;
- rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_ADD, dn);
- if (rc == NOTIFY_BAD) {
+ rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn);
+ if (rc) {
printk(KERN_ERR "Failed to add device node %s\n",
dn->full_name);
- return -ENOMEM; /* For now, safe to assume kmalloc failure */
+ return rc;
}
of_attach_node(dn);
@@ -297,8 +296,7 @@ int dlpar_detach_node(struct device_node *dn)
remove_proc_entry(dn->pde->name, parent->pde);
#endif
- blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_REMOVE, dn);
+ pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
of_detach_node(dn);
of_node_put(dn); /* Must decrement the refcount */
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 46b55cf563e3..ada6e07532ec 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -31,7 +31,7 @@
#include <linux/spinlock.h>
#include <linux/of.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/eeh.h>
#include <asm/eeh_event.h>
#include <asm/io.h>
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index 8ed0d2d0e1b5..fc5ae767989e 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -25,7 +25,7 @@
#include <linux/rbtree.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 46f13a3c5d09..bc0288501f17 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -330,21 +330,17 @@ static void pseries_remove_processor(struct device_node *np)
static int pseries_smp_notifier(struct notifier_block *nb,
unsigned long action, void *node)
{
- int err = NOTIFY_OK;
+ int err = 0;
switch (action) {
case PSERIES_RECONFIG_ADD:
- if (pseries_add_processor(node))
- err = NOTIFY_BAD;
+ err = pseries_add_processor(node);
break;
case PSERIES_RECONFIG_REMOVE:
pseries_remove_processor(node);
break;
- default:
- err = NOTIFY_DONE;
- break;
}
- return err;
+ return notifier_from_errno(err);
}
static struct notifier_block pseries_smp_nb = {
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 9d6a8effeda2..11d8e0544ac0 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -205,27 +205,21 @@ static int pseries_drconf_memory(unsigned long *base, unsigned int action)
static int pseries_memory_notifier(struct notifier_block *nb,
unsigned long action, void *node)
{
- int err = NOTIFY_OK;
+ int err = 0;
switch (action) {
case PSERIES_RECONFIG_ADD:
- if (pseries_add_memory(node))
- err = NOTIFY_BAD;
+ err = pseries_add_memory(node);
break;
case PSERIES_RECONFIG_REMOVE:
- if (pseries_remove_memory(node))
- err = NOTIFY_BAD;
+ err = pseries_remove_memory(node);
break;
case PSERIES_DRCONF_MEM_ADD:
case PSERIES_DRCONF_MEM_REMOVE:
- if (pseries_drconf_memory(node, action))
- err = NOTIFY_BAD;
- break;
- default:
- err = NOTIFY_DONE;
+ err = pseries_drconf_memory(node, action);
break;
}
- return err;
+ return notifier_from_errno(err);
}
static struct notifier_block pseries_mem_nb = {
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index 3f6a89b09816..041e87ca1893 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -73,7 +73,7 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
if (ret == H_SUCCESS)
return count;
if (ret == H_BUSY)
- return 0;
+ return -EAGAIN;
return -EIO;
}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 39e6e0a7b2fa..f7205d344efd 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -52,197 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_norets);
extern void pSeries_find_serial_port(void);
-
-static int vtermno; /* virtual terminal# for udbg */
-
-#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
-static void udbg_hvsi_putc(char c)
-{
- /* packet's seqno isn't used anyways */
- uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
- int rc;
-
- if (c == '\n')
- udbg_hvsi_putc('\r');
-
- do {
- rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
- } while (rc == H_BUSY);
-}
-
-static long hvsi_udbg_buf_len;
-static uint8_t hvsi_udbg_buf[256];
-
-static int udbg_hvsi_getc_poll(void)
-{
- unsigned char ch;
- int rc, i;
-
- if (hvsi_udbg_buf_len == 0) {
- rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
- if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
- /* bad read or non-data packet */
- hvsi_udbg_buf_len = 0;
- } else {
- /* remove the packet header */
- for (i = 4; i < hvsi_udbg_buf_len; i++)
- hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
- hvsi_udbg_buf_len -= 4;
- }
- }
-
- if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
- /* no data ready */
- hvsi_udbg_buf_len = 0;
- return -1;
- }
-
- ch = hvsi_udbg_buf[0];
- /* shift remaining data down */
- for (i = 1; i < hvsi_udbg_buf_len; i++) {
- hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
- }
- hvsi_udbg_buf_len--;
-
- return ch;
-}
-
-static int udbg_hvsi_getc(void)
-{
- int ch;
- for (;;) {
- ch = udbg_hvsi_getc_poll();
- if (ch == -1) {
- /* This shouldn't be needed...but... */
- volatile unsigned long delay;
- for (delay=0; delay < 2000000; delay++)
- ;
- } else {
- return ch;
- }
- }
-}
-
-static void udbg_putcLP(char c)
-{
- char buf[16];
- unsigned long rc;
-
- if (c == '\n')
- udbg_putcLP('\r');
-
- buf[0] = c;
- do {
- rc = plpar_put_term_char(vtermno, 1, buf);
- } while(rc == H_BUSY);
-}
-
-/* Buffered chars getc */
-static long inbuflen;
-static long inbuf[2]; /* must be 2 longs */
-
-static int udbg_getc_pollLP(void)
-{
- /* The interface is tricky because it may return up to 16 chars.
- * We save them statically for future calls to udbg_getc().
- */
- char ch, *buf = (char *)inbuf;
- int i;
- long rc;
- if (inbuflen == 0) {
- /* get some more chars. */
- inbuflen = 0;
- rc = plpar_get_term_char(vtermno, &inbuflen, buf);
- if (rc != H_SUCCESS)
- inbuflen = 0; /* otherwise inbuflen is garbage */
- }
- if (inbuflen <= 0 || inbuflen > 16) {
- /* Catch error case as well as other oddities (corruption) */
- inbuflen = 0;
- return -1;
- }
- ch = buf[0];
- for (i = 1; i < inbuflen; i++) /* shuffle them down. */
- buf[i-1] = buf[i];
- inbuflen--;
- return ch;
-}
-
-static int udbg_getcLP(void)
-{
- int ch;
- for (;;) {
- ch = udbg_getc_pollLP();
- if (ch == -1) {
- /* This shouldn't be needed...but... */
- volatile unsigned long delay;
- for (delay=0; delay < 2000000; delay++)
- ;
- } else {
- return ch;
- }
- }
-}
-
-/* call this from early_init() for a working debug console on
- * vterm capable LPAR machines
- */
-void __init udbg_init_debug_lpar(void)
-{
- vtermno = 0;
- udbg_putc = udbg_putcLP;
- udbg_getc = udbg_getcLP;
- udbg_getc_poll = udbg_getc_pollLP;
-
- register_early_udbg_console();
-}
-
-/* returns 0 if couldn't find or use /chosen/stdout as console */
-void __init find_udbg_vterm(void)
-{
- struct device_node *stdout_node;
- const u32 *termno;
- const char *name;
-
- /* find the boot console from /chosen/stdout */
- if (!of_chosen)
- return;
- name = of_get_property(of_chosen, "linux,stdout-path", NULL);
- if (name == NULL)
- return;
- stdout_node = of_find_node_by_path(name);
- if (!stdout_node)
- return;
- name = of_get_property(stdout_node, "name", NULL);
- if (!name) {
- printk(KERN_WARNING "stdout node missing 'name' property!\n");
- goto out;
- }
-
- /* Check if it's a virtual terminal */
- if (strncmp(name, "vty", 3) != 0)
- goto out;
- termno = of_get_property(stdout_node, "reg", NULL);
- if (termno == NULL)
- goto out;
- vtermno = termno[0];
-
- if (of_device_is_compatible(stdout_node, "hvterm1")) {
- udbg_putc = udbg_putcLP;
- udbg_getc = udbg_getcLP;
- udbg_getc_poll = udbg_getc_pollLP;
- add_preferred_console("hvc", termno[0] & 0xff, NULL);
- } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
- vtermno = termno[0];
- udbg_putc = udbg_hvsi_putc;
- udbg_getc = udbg_hvsi_getc;
- udbg_getc_poll = udbg_hvsi_getc_poll;
- add_preferred_console("hvsi", termno[0] & 0xff, NULL);
- }
-out:
- of_node_put(stdout_node);
-}
-
void vpa_init(int cpu)
{
int hwcpu = get_hard_smp_processor_id(cpu);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index e9f6d2859c3c..24c7162f11d9 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -47,7 +47,8 @@ extern void pSeries_final_fixup(void);
/* Poweron flag used for enabling auto ups restart */
extern unsigned long rtas_poweron_auto;
-extern void find_udbg_vterm(void);
+/* Provided by HVC VIO */
+extern void hvc_vio_init_early(void);
/* Dynamic logical Partitioning/Mobility */
extern void dlpar_free_cc_nodes(struct device_node *);
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 1de2cbb92303..168651acdd83 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -97,7 +97,7 @@ static struct device_node *derive_parent(const char *path)
return parent;
}
-BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
+static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
@@ -109,6 +109,14 @@ void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
}
+int pSeries_reconfig_notify(unsigned long action, void *p)
+{
+ int err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ action, p);
+
+ return notifier_to_errno(err);
+}
+
static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
{
struct device_node *np;
@@ -132,11 +140,9 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
goto out_err;
}
- err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_ADD, np);
- if (err == NOTIFY_BAD) {
+ err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np);
+ if (err) {
printk(KERN_ERR "Failed to add device node %s\n", path);
- err = -ENOMEM; /* For now, safe to assume kmalloc failure */
goto out_err;
}
@@ -173,8 +179,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
remove_node_proc_entries(np);
- blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_REMOVE, np);
+ pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
of_detach_node(np);
of_node_put(parent);
@@ -472,11 +477,10 @@ static int do_update_property(char *buf, size_t bufsize)
else
action = PSERIES_DRCONF_MEM_REMOVE;
- rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
- action, value);
- if (rc == NOTIFY_BAD) {
- rc = prom_update_property(np, oldprop, newprop);
- return -ENOMEM;
+ rc = pSeries_reconfig_notify(action, value);
+ if (rc) {
+ prom_update_property(np, oldprop, newprop);
+ return rc;
}
}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 593acceeff96..d00e52926b71 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -512,9 +512,10 @@ static void __init pSeries_init_early(void)
{
pr_debug(" -> pSeries_init_early()\n");
+#ifdef CONFIG_HVC_CONSOLE
if (firmware_has_feature(FW_FEATURE_LPAR))
- find_udbg_vterm();
-
+ hvc_vio_init_early();
+#endif
if (firmware_has_feature(FW_FEATURE_DABR))
ppc_md.set_dabr = pseries_set_dabr;
else if (firmware_has_feature(FW_FEATURE_XDABR))
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index fbffd7e47ab8..4e44c4dcd11c 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -27,7 +27,7 @@
#include <linux/cpu.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -44,7 +44,6 @@
#include <asm/mpic.h>
#include <asm/vdso_datapage.h>
#include <asm/cputhreads.h>
-#include <asm/mpic.h>
#include <asm/xics.h>
#include "plpar_wrappers.h"
@@ -207,7 +206,7 @@ static struct smp_ops_t pSeries_mpic_smp_ops = {
};
static struct smp_ops_t pSeries_xics_smp_ops = {
- .message_pass = smp_muxed_ipi_message_pass,
+ .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
.cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
.probe = xics_smp_probe,
.kick_cpu = smp_pSeries_kick_cpu,
diff --git a/arch/powerpc/platforms/wsp/smp.c b/arch/powerpc/platforms/wsp/smp.c
index 9d20fa9d3710..71bd105f3863 100644
--- a/arch/powerpc/platforms/wsp/smp.c
+++ b/arch/powerpc/platforms/wsp/smp.c
@@ -75,7 +75,7 @@ static int __init smp_a2_probe(void)
}
static struct smp_ops_t a2_smp_ops = {
- .message_pass = smp_muxed_ipi_message_pass,
+ .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
.cause_ipi = doorbell_cause_ipi,
.probe = smp_a2_probe,
.kick_cpu = smp_a2_kick_cpu,
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 0efa990e3344..cf736ca0cf05 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
+obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o
fsl-msi-obj-$(CONFIG_PCI_MSI) += fsl_msi.o
obj-$(CONFIG_PPC_MSI_BITMAP) += msi_bitmap.o
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index bd0d54060b94..265f0f09395a 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -203,7 +203,7 @@ static int axon_ram_probe(struct platform_device *device)
goto failed;
}
- bank->size = resource.end - resource.start + 1;
+ bank->size = resource_size(&resource);
if (bank->size == 0) {
dev_err(&device->dev, "No DDR2 memory found for %s%d\n",
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index 350787c83e22..5d7d59a43c4c 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -148,7 +148,7 @@ unsigned int cpm_pic_init(void)
if (ret)
goto end;
- cpic_reg = ioremap(res.start, res.end - res.start + 1);
+ cpic_reg = ioremap(res.start, resource_size(&res));
if (cpic_reg == NULL)
goto end;
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 2b69aa0315b3..d55d0ad0deab 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -115,7 +115,7 @@ int cpm_muram_init(void)
max = r.end;
rh_attach_region(&cpm_muram_info, r.start - muram_pbase,
- r.end - r.start + 1);
+ resource_size(&r));
}
muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1);
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 8e9e06a7ca59..4f2680f431b5 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -239,7 +239,7 @@ static int __init dart_init(struct device_node *dart_node)
DARTMAP_RPNMASK);
/* Map in DART registers */
- dart = ioremap(r.start, r.end - r.start + 1);
+ dart = ioremap(r.start, resource_size(&r));
if (dart == NULL)
panic("DART: Cannot map registers!");
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
new file mode 100644
index 000000000000..af1a5df46b3e
--- /dev/null
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -0,0 +1,302 @@
+/*
+ * Driver for ePAPR Embedded Hypervisor PIC
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Ashish Kalra <ashish.kalra@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/ehv_pic.h>
+#include <asm/fsl_hcalls.h>
+
+#include "../../../kernel/irq/settings.h"
+
+static struct ehv_pic *global_ehv_pic;
+static DEFINE_SPINLOCK(ehv_pic_lock);
+
+static u32 hwirq_intspec[NR_EHV_PIC_INTS];
+static u32 __iomem *mpic_percpu_base_vaddr;
+
+#define IRQ_TYPE_MPIC_DIRECT 4
+#define MPIC_EOI 0x00B0
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+void ehv_pic_unmask_irq(struct irq_data *d)
+{
+ unsigned int src = virq_to_hw(d->irq);
+
+ ev_int_set_mask(src, 0);
+}
+
+void ehv_pic_mask_irq(struct irq_data *d)
+{
+ unsigned int src = virq_to_hw(d->irq);
+
+ ev_int_set_mask(src, 1);
+}
+
+void ehv_pic_end_irq(struct irq_data *d)
+{
+ unsigned int src = virq_to_hw(d->irq);
+
+ ev_int_eoi(src);
+}
+
+void ehv_pic_direct_end_irq(struct irq_data *d)
+{
+ out_be32(mpic_percpu_base_vaddr + MPIC_EOI / 4, 0);
+}
+
+int ehv_pic_set_affinity(struct irq_data *d, const struct cpumask *dest,
+ bool force)
+{
+ unsigned int src = virq_to_hw(d->irq);
+ unsigned int config, prio, cpu_dest;
+ int cpuid = irq_choose_cpu(dest);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ehv_pic_lock, flags);
+ ev_int_get_config(src, &config, &prio, &cpu_dest);
+ ev_int_set_config(src, config, prio, cpuid);
+ spin_unlock_irqrestore(&ehv_pic_lock, flags);
+
+ return 0;
+}
+
+static unsigned int ehv_pic_type_to_vecpri(unsigned int type)
+{
+ /* Now convert sense value */
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_RISING:
+ return EHV_PIC_INFO(VECPRI_SENSE_EDGE) |
+ EHV_PIC_INFO(VECPRI_POLARITY_POSITIVE);
+
+ case IRQ_TYPE_EDGE_FALLING:
+ case IRQ_TYPE_EDGE_BOTH:
+ return EHV_PIC_INFO(VECPRI_SENSE_EDGE) |
+ EHV_PIC_INFO(VECPRI_POLARITY_NEGATIVE);
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ return EHV_PIC_INFO(VECPRI_SENSE_LEVEL) |
+ EHV_PIC_INFO(VECPRI_POLARITY_POSITIVE);
+
+ case IRQ_TYPE_LEVEL_LOW:
+ default:
+ return EHV_PIC_INFO(VECPRI_SENSE_LEVEL) |
+ EHV_PIC_INFO(VECPRI_POLARITY_NEGATIVE);
+ }
+}
+
+int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
+{
+ unsigned int src = virq_to_hw(d->irq);
+ struct irq_desc *desc = irq_to_desc(d->irq);
+ unsigned int vecpri, vold, vnew, prio, cpu_dest;
+ unsigned long flags;
+
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ irq_settings_clr_level(desc);
+ irq_settings_set_trigger_mask(desc, flow_type);
+ if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+ irq_settings_set_level(desc);
+
+ vecpri = ehv_pic_type_to_vecpri(flow_type);
+
+ spin_lock_irqsave(&ehv_pic_lock, flags);
+ ev_int_get_config(src, &vold, &prio, &cpu_dest);
+ vnew = vold & ~(EHV_PIC_INFO(VECPRI_POLARITY_MASK) |
+ EHV_PIC_INFO(VECPRI_SENSE_MASK));
+ vnew |= vecpri;
+
+ /*
+ * TODO : Add specific interface call for platform to set
+ * individual interrupt priorities.
+ * platform currently using static/default priority for all ints
+ */
+
+ prio = 8;
+
+ ev_int_set_config(src, vecpri, prio, cpu_dest);
+
+ spin_unlock_irqrestore(&ehv_pic_lock, flags);
+ return 0;
+}
+
+static struct irq_chip ehv_pic_irq_chip = {
+ .irq_mask = ehv_pic_mask_irq,
+ .irq_unmask = ehv_pic_unmask_irq,
+ .irq_eoi = ehv_pic_end_irq,
+ .irq_set_type = ehv_pic_set_irq_type,
+};
+
+static struct irq_chip ehv_pic_direct_eoi_irq_chip = {
+ .irq_mask = ehv_pic_mask_irq,
+ .irq_unmask = ehv_pic_unmask_irq,
+ .irq_eoi = ehv_pic_direct_end_irq,
+ .irq_set_type = ehv_pic_set_irq_type,
+};
+
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int ehv_pic_get_irq(void)
+{
+ int irq;
+
+ BUG_ON(global_ehv_pic == NULL);
+
+ if (global_ehv_pic->coreint_flag)
+ irq = mfspr(SPRN_EPR); /* if core int mode */
+ else
+ ev_int_iack(0, &irq); /* legacy mode */
+
+ if (irq == 0xFFFF) /* 0xFFFF --> no irq is pending */
+ return NO_IRQ;
+
+ /*
+ * this will also setup revmap[] in the slow path for the first
+ * time, next calls will always use fast path by indexing revmap
+ */
+ return irq_linear_revmap(global_ehv_pic->irqhost, irq);
+}
+
+static int ehv_pic_host_match(struct irq_host *h, struct device_node *node)
+{
+ /* Exact match, unless ehv_pic node is NULL */
+ return h->of_node == NULL || h->of_node == node;
+}
+
+static int ehv_pic_host_map(struct irq_host *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct ehv_pic *ehv_pic = h->host_data;
+ struct irq_chip *chip;
+
+ /* Default chip */
+ chip = &ehv_pic->hc_irq;
+
+ if (mpic_percpu_base_vaddr)
+ if (hwirq_intspec[hw] & IRQ_TYPE_MPIC_DIRECT)
+ chip = &ehv_pic_direct_eoi_irq_chip;
+
+ irq_set_chip_data(virq, chip);
+ /*
+ * using handle_fasteoi_irq as our irq handler, this will
+ * only call the eoi callback and suitable for the MPIC
+ * controller which set ISR/IPR automatically and clear the
+ * highest priority active interrupt in ISR/IPR when we do
+ * a specific eoi
+ */
+ irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
+
+ /* Set default irq type */
+ irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+ return 0;
+}
+
+static int ehv_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+ const u32 *intspec, unsigned int intsize,
+ irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+
+{
+ /*
+ * interrupt sense values coming from the guest device tree
+ * interrupt specifiers can have four possible sense and
+ * level encoding information and they need to
+ * be translated between firmware type & linux type.
+ */
+
+ static unsigned char map_of_senses_to_linux_irqtype[4] = {
+ IRQ_TYPE_EDGE_FALLING,
+ IRQ_TYPE_EDGE_RISING,
+ IRQ_TYPE_LEVEL_LOW,
+ IRQ_TYPE_LEVEL_HIGH,
+ };
+
+ *out_hwirq = intspec[0];
+ if (intsize > 1) {
+ hwirq_intspec[intspec[0]] = intspec[1];
+ *out_flags = map_of_senses_to_linux_irqtype[intspec[1] &
+ ~IRQ_TYPE_MPIC_DIRECT];
+ } else {
+ *out_flags = IRQ_TYPE_NONE;
+ }
+
+ return 0;
+}
+
+static struct irq_host_ops ehv_pic_host_ops = {
+ .match = ehv_pic_host_match,
+ .map = ehv_pic_host_map,
+ .xlate = ehv_pic_host_xlate,
+};
+
+void __init ehv_pic_init(void)
+{
+ struct device_node *np, *np2;
+ struct ehv_pic *ehv_pic;
+ int coreint_flag = 1;
+
+ np = of_find_compatible_node(NULL, NULL, "epapr,hv-pic");
+ if (!np) {
+ pr_err("ehv_pic_init: could not find epapr,hv-pic node\n");
+ return;
+ }
+
+ if (!of_find_property(np, "has-external-proxy", NULL))
+ coreint_flag = 0;
+
+ ehv_pic = kzalloc(sizeof(struct ehv_pic), GFP_KERNEL);
+ if (!ehv_pic) {
+ of_node_put(np);
+ return;
+ }
+
+ ehv_pic->irqhost = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
+ NR_EHV_PIC_INTS, &ehv_pic_host_ops, 0);
+
+ if (!ehv_pic->irqhost) {
+ of_node_put(np);
+ return;
+ }
+
+ np2 = of_find_compatible_node(NULL, NULL, "fsl,hv-mpic-per-cpu");
+ if (np2) {
+ mpic_percpu_base_vaddr = of_iomap(np2, 0);
+ if (!mpic_percpu_base_vaddr)
+ pr_err("ehv_pic_init: of_iomap failed\n");
+
+ of_node_put(np2);
+ }
+
+ ehv_pic->irqhost->host_data = ehv_pic;
+ ehv_pic->hc_irq = ehv_pic_irq_chip;
+ ehv_pic->hc_irq.irq_set_affinity = ehv_pic_set_affinity;
+ ehv_pic->coreint_flag = coreint_flag;
+
+ global_ehv_pic = ehv_pic;
+ irq_set_default_host(global_ehv_pic->irqhost);
+}
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 92e78333c47c..419a77239bd7 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -349,7 +349,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
goto error_out;
}
- msi->msi_regs = ioremap(res.start, res.end - res.start + 1);
+ msi->msi_regs = ioremap(res.start, resource_size(&res));
if (!msi->msi_regs) {
dev_err(&dev->dev, "ioremap problem failed\n");
goto error_out;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 68ca9290df94..4ce547e00473 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -38,10 +38,17 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
{
+ u8 progif;
+
/* if we aren't a PCIe don't bother */
if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
return;
+ /* if we aren't in host mode don't bother */
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+ if (progif & 0x1)
+ return;
+
dev->class = PCI_CLASS_BRIDGE_PCI << 8;
fsl_pcie_bus_fixup = 1;
return;
@@ -64,7 +71,7 @@ static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
{
resource_size_t pci_addr = res->start - offset;
resource_size_t phys_addr = res->start;
- resource_size_t size = res->end - res->start + 1;
+ resource_size_t size = resource_size(res);
u32 flags = 0x80044000; /* enable & mem R/W */
unsigned int i;
@@ -108,7 +115,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
char *name = hose->dn->full_name;
pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
- (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
+ (u64)rsrc->start, (u64)resource_size(rsrc));
if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
win_idx = 2;
@@ -116,7 +123,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
end_idx = 3;
}
- pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+ pci = ioremap(rsrc->start, resource_size(rsrc));
if (!pci) {
dev_err(hose->parent, "Unable to map ATMU registers\n");
return;
@@ -153,9 +160,9 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
} else {
pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, "
"phy base 0x%016llx.\n",
- (u64)hose->io_resource.start,
- (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1,
- (u64)hose->io_base_phys);
+ (u64)hose->io_resource.start,
+ (u64)resource_size(&hose->io_resource),
+ (u64)hose->io_base_phys);
out_be32(&pci->pow[j].potar, (hose->io_resource.start >> 12));
out_be32(&pci->pow[j].potear, 0);
out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12));
@@ -323,6 +330,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
struct pci_controller *hose;
struct resource rsrc;
const int *bus_range;
+ u8 progif;
if (!of_device_is_available(dev)) {
pr_warning("%s: disabled\n", dev->full_name);
@@ -343,7 +351,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
- ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
@@ -353,6 +361,18 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
PPC_INDIRECT_TYPE_BIG_ENDIAN);
+
+ early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif);
+ if ((progif & 1) == 1) {
+ /* unmap cfg_data & cfg_addr separately if not on same page */
+ if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
+ ((unsigned long)hose->cfg_addr & PAGE_MASK))
+ iounmap(hose->cfg_data);
+ iounmap(hose->cfg_addr);
+ pcibios_free_controller(hose);
+ return 0;
+ }
+
setup_pci_cmd(hose);
/* check PCI express link status */
@@ -380,70 +400,11 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
return 0;
}
-
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8547E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8533E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8533, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_header);
#endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
-#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8308, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header);
+#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
struct mpc83xx_pcie_priv {
void __iomem *cfg_type0;
void __iomem *cfg_type1;
@@ -679,7 +640,7 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
" bus 0\n", dev->full_name);
}
- ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index b3fd081d56f5..2de8551df40f 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1524,7 +1524,7 @@ int fsl_rio_setup(struct platform_device *dev)
port->priv = priv;
port->phys_efptr = 0x100;
- priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
+ priv->regs_win = ioremap(regs.start, resource_size(&regs));
rio_regs_win = priv->regs_win;
/* Probe the master port phy type */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 19e5015e039b..2d66275e489f 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -32,7 +32,7 @@
#include <linux/fs_uart_pd.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/time.h>
@@ -41,6 +41,7 @@
#include <sysdev/fsl_soc.h>
#include <mm/mmu_decl.h>
#include <asm/cpm2.h>
+#include <asm/fsl_hcalls.h> /* For the Freescale hypervisor */
extern void init_fcc_ioports(struct fs_platform_info*);
extern void init_fec_ioports(struct fs_platform_info*);
@@ -252,3 +253,29 @@ void fsl_rstcr_restart(char *cmd)
struct platform_diu_data_ops diu_ops;
EXPORT_SYMBOL(diu_ops);
#endif
+
+/*
+ * Restart the current partition
+ *
+ * This function should be assigned to the ppc_md.restart function pointer,
+ * to initiate a partition restart when we're running under the Freescale
+ * hypervisor.
+ */
+void fsl_hv_restart(char *cmd)
+{
+ pr_info("hv restart\n");
+ fh_partition_restart(-1);
+}
+
+/*
+ * Halt the current partition
+ *
+ * This function should be assigned to the ppc_md.power_off and ppc_md.halt
+ * function pointers, to shut down the partition when we're running under
+ * the Freescale hypervisor.
+ */
+void fsl_hv_halt(void)
+{
+ pr_info("hv exit\n");
+ fh_partition_stop(-1);
+}
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 53609489a62b..2ece02beb8ff 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -36,5 +36,8 @@ struct platform_diu_data_ops {
extern struct platform_diu_data_ops diu_ops;
#endif
+void fsl_hv_restart(char *cmd);
+void fsl_hv_halt(void);
+
#endif
#endif
diff --git a/arch/powerpc/sysdev/grackle.c b/arch/powerpc/sysdev/grackle.c
index cf27df6e508b..08abe91ae798 100644
--- a/arch/powerpc/sysdev/grackle.c
+++ b/arch/powerpc/sysdev/grackle.c
@@ -57,7 +57,7 @@ void __init setup_grackle(struct pci_controller *hose)
{
setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
if (of_machine_is_compatible("PowerMac1,1"))
- ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
if (of_machine_is_compatible("AAPL,PowerBook1998"))
grackle_set_loop_snoop(hose, 1);
#if 0 /* Disabled for now, HW problems ??? */
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 7367d17364cb..95da897f05a7 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -736,7 +736,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
return NULL;
}
- ipic->regs = ioremap(res.start, res.end - res.start + 1);
+ ipic->regs = ioremap(res.start, resource_size(&res));
ipic->irqhost->host_data = ipic;
diff --git a/arch/powerpc/sysdev/mmio_nvram.c b/arch/powerpc/sysdev/mmio_nvram.c
index ddc877a3a23a..69f5814ae6d4 100644
--- a/arch/powerpc/sysdev/mmio_nvram.c
+++ b/arch/powerpc/sysdev/mmio_nvram.c
@@ -129,7 +129,7 @@ int __init mmio_nvram_init(void)
goto out;
}
nvram_addr = r.start;
- mmio_nvram_len = r.end - r.start + 1;
+ mmio_nvram_len = resource_size(&r);
if ( (!mmio_nvram_len) || (!nvram_addr) ) {
printk(KERN_WARNING "nvram: address or length is 0\n");
ret = -EIO;
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 20924f2246f0..22e48e2d71f1 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -166,7 +166,7 @@ int mpc8xx_pic_init(void)
if (ret)
goto out;
- siu_reg = ioremap(res.start, res.end - res.start + 1);
+ siu_reg = ioremap(res.start, resource_size(&res));
if (siu_reg == NULL) {
ret = -EINVAL;
goto out;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 58d7a534f877..d5d3ff3d757e 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -598,42 +598,6 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
#endif /* CONFIG_MPIC_U3_HT_IRQS */
-#ifdef CONFIG_SMP
-static int irq_choose_cpu(const struct cpumask *mask)
-{
- int cpuid;
-
- if (cpumask_equal(mask, cpu_all_mask)) {
- static int irq_rover = 0;
- static DEFINE_RAW_SPINLOCK(irq_rover_lock);
- unsigned long flags;
-
- /* Round-robin distribution... */
- do_round_robin:
- raw_spin_lock_irqsave(&irq_rover_lock, flags);
-
- irq_rover = cpumask_next(irq_rover, cpu_online_mask);
- if (irq_rover >= nr_cpu_ids)
- irq_rover = cpumask_first(cpu_online_mask);
-
- cpuid = irq_rover;
-
- raw_spin_unlock_irqrestore(&irq_rover_lock, flags);
- } else {
- cpuid = cpumask_first_and(mask, cpu_online_mask);
- if (cpuid >= nr_cpu_ids)
- goto do_round_robin;
- }
-
- return get_hard_smp_processor_id(cpuid);
-}
-#else
-static int irq_choose_cpu(const struct cpumask *mask)
-{
- return hard_smp_processor_id();
-}
-#endif
-
/* Find an mpic associated with a given linux interrupt */
static struct mpic *mpic_find(unsigned int irq)
{
@@ -849,7 +813,7 @@ static void mpic_unmask_tm(struct irq_data *d)
struct mpic *mpic = mpic_from_irq_data(d);
unsigned int src = virq_to_hw(d->irq) - mpic->timer_vecs[0];
- DBG("%s: enable_tm: %d (tm %d)\n", mpic->name, irq, src);
+ DBG("%s: enable_tm: %d (tm %d)\n", mpic->name, d->irq, src);
mpic_tm_write(src, mpic_tm_read(src) & ~MPIC_VECPRI_MASK);
mpic_tm_read(src);
}
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
index 2792dc8b038c..50a81387e9b1 100644
--- a/arch/powerpc/sysdev/mv64x60_udbg.c
+++ b/arch/powerpc/sysdev/mv64x60_udbg.c
@@ -125,11 +125,11 @@ static void mv64x60_udbg_init(void)
of_node_put(np);
- mpsc_base = ioremap(r[0].start, r[0].end - r[0].start + 1);
+ mpsc_base = ioremap(r[0].start, resource_size(&r[0]));
if (!mpsc_base)
return;
- mpsc_intr_cause = ioremap(r[1].start, r[1].end - r[1].start + 1);
+ mpsc_intr_cause = ioremap(r[1].start, resource_size(&r[1]));
if (!mpsc_intr_cause) {
iounmap(mpsc_base);
return;
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 156aa7d36258..a59ba96d2c21 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -265,7 +265,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
if (ppc4xx_setup_one_pci_PMM(hose, reg,
res->start,
res->start - hose->pci_mem_offset,
- res->end + 1 - res->start,
+ resource_size(res),
res->flags,
j) == 0) {
j++;
@@ -290,7 +290,7 @@ static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,
void __iomem *reg,
const struct resource *res)
{
- resource_size_t size = res->end - res->start + 1;
+ resource_size_t size = resource_size(res);
u32 sa;
/* Calculate window size */
@@ -349,7 +349,7 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
bus_range = of_get_property(np, "bus-range", NULL);
/* Map registers */
- reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
+ reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));
if (reg == NULL) {
printk(KERN_ERR "%s: Can't map registers !", np->full_name);
goto fail;
@@ -465,7 +465,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
if (ppc4xx_setup_one_pcix_POM(hose, reg,
res->start,
res->start - hose->pci_mem_offset,
- res->end + 1 - res->start,
+ resource_size(res),
res->flags,
j) == 0) {
j++;
@@ -492,7 +492,7 @@ static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
int big_pim,
int enable_msi_hole)
{
- resource_size_t size = res->end - res->start + 1;
+ resource_size_t size = resource_size(res);
u32 sa;
/* RAM is always at 0 */
@@ -555,7 +555,7 @@ static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
bus_range = of_get_property(np, "bus-range", NULL);
/* Map registers */
- reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
+ reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));
if (reg == NULL) {
printk(KERN_ERR "%s: Can't map registers !", np->full_name);
goto fail;
@@ -650,12 +650,74 @@ struct ppc4xx_pciex_hwops
int (*core_init)(struct device_node *np);
int (*port_init_hw)(struct ppc4xx_pciex_port *port);
int (*setup_utl)(struct ppc4xx_pciex_port *port);
+ void (*check_link)(struct ppc4xx_pciex_port *port);
};
static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops;
#ifdef CONFIG_44x
+static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
+ unsigned int sdr_offset,
+ unsigned int mask,
+ unsigned int value,
+ int timeout_ms)
+{
+ u32 val;
+
+ while(timeout_ms--) {
+ val = mfdcri(SDR0, port->sdr_base + sdr_offset);
+ if ((val & mask) == value) {
+ pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n",
+ port->index, sdr_offset, timeout_ms, val);
+ return 0;
+ }
+ msleep(1);
+ }
+ return -1;
+}
+
+static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
+{
+ /* Wait for reset to complete */
+ if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) {
+ printk(KERN_WARNING "PCIE%d: PGRST failed\n",
+ port->index);
+ return -1;
+ }
+ return 0;
+}
+
+static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port)
+{
+ printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
+
+ /* Check for card presence detect if supported, if not, just wait for
+ * link unconditionally.
+ *
+ * note that we don't fail if there is no link, we just filter out
+ * config space accesses. That way, it will be easier to implement
+ * hotplug later on.
+ */
+ if (!port->has_ibpre ||
+ !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
+ 1 << 28, 1 << 28, 100)) {
+ printk(KERN_INFO
+ "PCIE%d: Device detected, waiting for link...\n",
+ port->index);
+ if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
+ 0x1000, 0x1000, 2000))
+ printk(KERN_WARNING
+ "PCIE%d: Link up failed\n", port->index);
+ else {
+ printk(KERN_INFO
+ "PCIE%d: link is up !\n", port->index);
+ port->link = 1;
+ }
+ } else
+ printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
+}
+
/* Check various reset bits of the 440SPe PCIe core */
static int __init ppc440spe_pciex_check_reset(struct device_node *np)
{
@@ -806,7 +868,7 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
(1 << 24) | (1 << 16), 1 << 12);
- return 0;
+ return ppc4xx_pciex_port_reset_sdr(port);
}
static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
@@ -856,6 +918,7 @@ static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata =
.core_init = ppc440spe_pciex_core_init,
.port_init_hw = ppc440speA_pciex_init_port_hw,
.setup_utl = ppc440speA_pciex_init_utl,
+ .check_link = ppc4xx_pciex_check_link_sdr,
};
static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
@@ -863,6 +926,7 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
.core_init = ppc440spe_pciex_core_init,
.port_init_hw = ppc440speB_pciex_init_port_hw,
.setup_utl = ppc440speB_pciex_init_utl,
+ .check_link = ppc4xx_pciex_check_link_sdr,
};
static int __init ppc460ex_pciex_core_init(struct device_node *np)
@@ -944,7 +1008,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
port->has_ibpre = 1;
- return 0;
+ return ppc4xx_pciex_port_reset_sdr(port);
}
static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
@@ -972,6 +1036,7 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
.core_init = ppc460ex_pciex_core_init,
.port_init_hw = ppc460ex_pciex_init_port_hw,
.setup_utl = ppc460ex_pciex_init_utl,
+ .check_link = ppc4xx_pciex_check_link_sdr,
};
static int __init ppc460sx_pciex_core_init(struct device_node *np)
@@ -1075,7 +1140,7 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
port->has_ibpre = 1;
- return 0;
+ return ppc4xx_pciex_port_reset_sdr(port);
}
static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
@@ -1089,6 +1154,7 @@ static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
.core_init = ppc460sx_pciex_core_init,
.port_init_hw = ppc460sx_pciex_init_port_hw,
.setup_utl = ppc460sx_pciex_init_utl,
+ .check_link = ppc4xx_pciex_check_link_sdr,
};
#endif /* CONFIG_44x */
@@ -1154,7 +1220,7 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
port->has_ibpre = 1;
- return 0;
+ return ppc4xx_pciex_port_reset_sdr(port);
}
static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
@@ -1183,11 +1249,11 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =
.core_init = ppc405ex_pciex_core_init,
.port_init_hw = ppc405ex_pciex_init_port_hw,
.setup_utl = ppc405ex_pciex_init_utl,
+ .check_link = ppc4xx_pciex_check_link_sdr,
};
#endif /* CONFIG_40x */
-
/* Check that the core has been initied and if not, do it */
static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
{
@@ -1261,26 +1327,6 @@ static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port
dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0);
}
-static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
- unsigned int sdr_offset,
- unsigned int mask,
- unsigned int value,
- int timeout_ms)
-{
- u32 val;
-
- while(timeout_ms--) {
- val = mfdcri(SDR0, port->sdr_base + sdr_offset);
- if ((val & mask) == value) {
- pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n",
- port->index, sdr_offset, timeout_ms, val);
- return 0;
- }
- msleep(1);
- }
- return -1;
-}
-
static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
{
int rc = 0;
@@ -1291,40 +1337,8 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
if (rc != 0)
return rc;
- printk(KERN_INFO "PCIE%d: Checking link...\n",
- port->index);
-
- /* Wait for reset to complete */
- if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) {
- printk(KERN_WARNING "PCIE%d: PGRST failed\n",
- port->index);
- return -1;
- }
-
- /* Check for card presence detect if supported, if not, just wait for
- * link unconditionally.
- *
- * note that we don't fail if there is no link, we just filter out
- * config space accesses. That way, it will be easier to implement
- * hotplug later on.
- */
- if (!port->has_ibpre ||
- !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
- 1 << 28, 1 << 28, 100)) {
- printk(KERN_INFO
- "PCIE%d: Device detected, waiting for link...\n",
- port->index);
- if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
- 0x1000, 0x1000, 2000))
- printk(KERN_WARNING
- "PCIE%d: Link up failed\n", port->index);
- else {
- printk(KERN_INFO
- "PCIE%d: link is up !\n", port->index);
- port->link = 1;
- }
- } else
- printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
+ if (ppc4xx_pciex_hwops->check_link)
+ ppc4xx_pciex_hwops->check_link(port);
/*
* Initialize mapping: disable all regions and configure
@@ -1347,14 +1361,17 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
/*
* Check for VC0 active and assert RDY.
*/
- if (port->link &&
- ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
- 1 << 16, 1 << 16, 5000)) {
- printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
- port->link = 0;
+ if (port->sdr_base) {
+ if (port->link &&
+ ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
+ 1 << 16, 1 << 16, 5000)) {
+ printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
+ port->link = 0;
+ }
+
+ dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
}
- dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
msleep(100);
return 0;
@@ -1604,7 +1621,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
res->start,
res->start - hose->pci_mem_offset,
- res->end + 1 - res->start,
+ resource_size(res),
res->flags,
j) == 0) {
j++;
@@ -1639,7 +1656,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
void __iomem *mbase,
struct resource *res)
{
- resource_size_t size = res->end - res->start + 1;
+ resource_size_t size = resource_size(res);
u64 sa;
if (port->endpoint) {
@@ -1960,7 +1977,7 @@ static int __init ppc4xx_pci_find_bridges(void)
{
struct device_node *np;
- ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+ pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
#ifdef CONFIG_PPC4xx_PCI_EXPRESS
for_each_compatible_node(np, NULL, "ibm,plb-pciex")
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index b2acda07220d..18e75ca19fe6 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -347,7 +347,7 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
return;
}
- qe_ic->regs = ioremap(res.start, res.end - res.start + 1);
+ qe_ic->regs = ioremap(res.start, resource_size(&res));
qe_ic->irqhost->host_data = qe_ic;
qe_ic->hc_irq = qe_ic_irq_chip;
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index 77e4934b88c5..fd1a6c3b1721 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -41,7 +41,7 @@ int par_io_init(struct device_node *np)
ret = of_address_to_resource(np, 0, &res);
if (ret)
return ret;
- par_io = ioremap(res.start, res.end - res.start + 1);
+ par_io = ioremap(res.start, resource_size(&res));
num_ports = of_get_property(np, "num-ports", NULL);
if (num_ports)
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index ee056807b52c..9f51f97abb5d 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -23,7 +23,7 @@
#include <asm/tsi108.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index 1f15ad436140..50e32afe392e 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -17,6 +17,7 @@
#include <linux/cpu.h>
#include <linux/of.h>
#include <linux/spinlock.h>
+#include <linux/module.h>
#include <asm/prom.h>
#include <asm/io.h>
@@ -24,6 +25,7 @@
#include <asm/irq.h>
#include <asm/errno.h>
#include <asm/xics.h>
+#include <asm/kvm_ppc.h>
struct icp_ipl {
union {
@@ -139,6 +141,12 @@ static void icp_native_cause_ipi(int cpu, unsigned long data)
icp_native_set_qirr(cpu, IPI_PRIORITY);
}
+void xics_wake_cpu(int cpu)
+{
+ icp_native_set_qirr(cpu, IPI_PRIORITY);
+}
+EXPORT_SYMBOL_GPL(xics_wake_cpu);
+
static irqreturn_t icp_native_ipi_action(int irq, void *dev_id)
{
int cpu = smp_processor_id();
@@ -185,6 +193,7 @@ static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr,
}
icp_native_regs[cpu] = ioremap(addr, size);
+ kvmppc_set_xics_phys(cpu, addr);
if (!icp_native_regs[cpu]) {
pr_warning("icp_native: Failed ioremap for CPU %d, "
"interrupt server #0x%x, addr %#lx\n",
@@ -247,7 +256,7 @@ static int __init icp_native_init_one_node(struct device_node *np,
return -1;
}
- if (icp_native_map_one_cpu(*indx, r.start, r.end - r.start))
+ if (icp_native_map_one_cpu(*indx, r.start, resource_size(&r)))
return -1;
(*indx)++;
diff --git a/arch/s390/boot/compressed/head31.S b/arch/s390/boot/compressed/head31.S
index 2a5523a32bcc..e8c9e18b8039 100644
--- a/arch/s390/boot/compressed/head31.S
+++ b/arch/s390/boot/compressed/head31.S
@@ -7,14 +7,14 @@
*/
#include <linux/init.h>
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
#include "sizes.h"
__HEAD
- .globl startup_continue
-startup_continue:
+ENTRY(startup_continue)
basr %r13,0 # get base
.LPG1:
# setup stack
diff --git a/arch/s390/boot/compressed/head64.S b/arch/s390/boot/compressed/head64.S
index 2982cb140550..f86a4eef28a9 100644
--- a/arch/s390/boot/compressed/head64.S
+++ b/arch/s390/boot/compressed/head64.S
@@ -7,14 +7,14 @@
*/
#include <linux/init.h>
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
#include "sizes.h"
__HEAD
- .globl startup_continue
-startup_continue:
+ENTRY(startup_continue)
basr %r13,0 # get base
.LPG1:
# setup stack
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index 5ed8d64fc2ed..0317a3547cb9 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -1,15 +1,12 @@
/*
* Cryptographic API.
*
- * s390 implementation of the SHA256 Secure Hash Algorithm.
+ * s390 implementation of the SHA256 and SHA224 Secure Hash Algorithm.
*
* s390 Version:
- * Copyright IBM Corp. 2005,2007
+ * Copyright IBM Corp. 2005,2011
* Author(s): Jan Glauber (jang@de.ibm.com)
*
- * Derived from "crypto/sha256_generic.c"
- * and "arch/s390/crypto/sha1_s390.c"
- *
* This program is free software; you can redistribute it and/or modify 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)
@@ -65,7 +62,7 @@ static int sha256_import(struct shash_desc *desc, const void *in)
return 0;
}
-static struct shash_alg alg = {
+static struct shash_alg sha256_alg = {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_init,
.update = s390_sha_update,
@@ -84,22 +81,69 @@ static struct shash_alg alg = {
}
};
-static int sha256_s390_init(void)
+static int sha224_init(struct shash_desc *desc)
{
+ struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
+
+ sctx->state[0] = SHA224_H0;
+ sctx->state[1] = SHA224_H1;
+ sctx->state[2] = SHA224_H2;
+ sctx->state[3] = SHA224_H3;
+ sctx->state[4] = SHA224_H4;
+ sctx->state[5] = SHA224_H5;
+ sctx->state[6] = SHA224_H6;
+ sctx->state[7] = SHA224_H7;
+ sctx->count = 0;
+ sctx->func = KIMD_SHA_256;
+
+ return 0;
+}
+
+static struct shash_alg sha224_alg = {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .init = sha224_init,
+ .update = s390_sha_update,
+ .final = s390_sha_final,
+ .export = sha256_export,
+ .import = sha256_import,
+ .descsize = sizeof(struct s390_sha_ctx),
+ .statesize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "sha224",
+ .cra_driver_name= "sha224-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static int __init sha256_s390_init(void)
+{
+ int ret;
+
if (!crypt_s390_func_available(KIMD_SHA_256, CRYPT_S390_MSA))
return -EOPNOTSUPP;
-
- return crypto_register_shash(&alg);
+ ret = crypto_register_shash(&sha256_alg);
+ if (ret < 0)
+ goto out;
+ ret = crypto_register_shash(&sha224_alg);
+ if (ret < 0)
+ crypto_unregister_shash(&sha256_alg);
+out:
+ return ret;
}
static void __exit sha256_s390_fini(void)
{
- crypto_unregister_shash(&alg);
+ crypto_unregister_shash(&sha224_alg);
+ crypto_unregister_shash(&sha256_alg);
}
module_init(sha256_s390_init);
module_exit(sha256_s390_fini);
MODULE_ALIAS("sha256");
+MODULE_ALIAS("sha224");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
+MODULE_DESCRIPTION("SHA256 and SHA224 Secure Hash Algorithm");
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index d9db13810d15..8517d2ae3b5c 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -93,7 +93,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return old;
}
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -105,10 +105,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != u;
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#undef __CS_LOOP
@@ -332,6 +331,4 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v)
#define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb()
-#include <asm-generic/atomic-long.h>
-
#endif /* __ARCH_S390_ATOMIC__ */
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 667c6e9f6a34..e5beb490959b 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -832,10 +832,7 @@ static inline int find_next_bit_le(void *vaddr, unsigned long size,
#include <asm-generic/bitops/le.h>
-#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit_le(nr, addr)
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit_le(nr, addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/irqflags.h b/arch/s390/include/asm/irqflags.h
index 865d6d891ace..38fdf451febb 100644
--- a/arch/s390/include/asm/irqflags.h
+++ b/arch/s390/include/asm/irqflags.h
@@ -29,42 +29,42 @@
})
/* set system mask. */
-static inline void __arch_local_irq_ssm(unsigned long flags)
+static inline notrace void __arch_local_irq_ssm(unsigned long flags)
{
asm volatile("ssm %0" : : "Q" (flags) : "memory");
}
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
{
return __arch_local_irq_stosm(0x00);
}
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
{
return __arch_local_irq_stnsm(0xfc);
}
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
{
arch_local_irq_save();
}
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
{
__arch_local_irq_stosm(0x03);
}
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
{
__arch_local_irq_ssm(flags);
}
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
{
return !(flags & (3UL << (BITS_PER_LONG - 8)));
}
-static inline bool arch_irqs_disabled(void)
+static inline notrace bool arch_irqs_disabled(void)
{
return arch_irqs_disabled_flags(arch_local_save_flags());
}
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index cef7dbf69dfc..00ff00dfb24c 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -93,9 +93,7 @@ struct kvm_s390_sie_block {
__u32 scaol; /* 0x0064 */
__u8 reserved68[4]; /* 0x0068 */
__u32 todpr; /* 0x006c */
- __u8 reserved70[16]; /* 0x0070 */
- __u64 gmsor; /* 0x0080 */
- __u64 gmslm; /* 0x0088 */
+ __u8 reserved70[32]; /* 0x0070 */
psw_t gpsw; /* 0x0090 */
__u64 gg14; /* 0x00a0 */
__u64 gg15; /* 0x00a8 */
@@ -138,6 +136,7 @@ struct kvm_vcpu_stat {
u32 instruction_chsc;
u32 instruction_stsi;
u32 instruction_stfl;
+ u32 instruction_tprot;
u32 instruction_sigp_sense;
u32 instruction_sigp_emergency;
u32 instruction_sigp_stop;
@@ -175,6 +174,10 @@ struct kvm_s390_prefix_info {
__u32 address;
};
+struct kvm_s390_emerg_info {
+ __u16 code;
+};
+
struct kvm_s390_interrupt_info {
struct list_head list;
u64 type;
@@ -182,6 +185,7 @@ struct kvm_s390_interrupt_info {
struct kvm_s390_io_info io;
struct kvm_s390_ext_info ext;
struct kvm_s390_pgm_info pgm;
+ struct kvm_s390_emerg_info emerg;
struct kvm_s390_prefix_info prefix;
};
};
@@ -226,6 +230,7 @@ struct kvm_vcpu_arch {
struct cpuid cpu_id;
u64 stidp_data;
};
+ struct gmap *gmap;
};
struct kvm_vm_stat {
@@ -236,6 +241,7 @@ struct kvm_arch{
struct sca_block *sca;
debug_info_t *dbf;
struct kvm_s390_float_interrupt float_int;
+ struct gmap *gmap;
};
extern int sie64a(struct kvm_s390_sie_block *, unsigned long *);
diff --git a/arch/s390/include/asm/linkage.h b/arch/s390/include/asm/linkage.h
index 291c2d01c44f..fc8a8284778e 100644
--- a/arch/s390/include/asm/linkage.h
+++ b/arch/s390/include/asm/linkage.h
@@ -1,6 +1,9 @@
#ifndef __ASM_LINKAGE_H
#define __ASM_LINKAGE_H
-/* Nothing to see here... */
+#include <linux/stringify.h>
+
+#define __ALIGN .align 4, 0x07
+#define __ALIGN_STR __stringify(__ALIGN)
#endif
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 228cf0b295db..f26280d9e88d 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -268,7 +268,7 @@ struct _lowcore {
__u64 vdso_per_cpu_data; /* 0x0358 */
__u64 machine_flags; /* 0x0360 */
__u64 ftrace_func; /* 0x0368 */
- __u64 sie_hook; /* 0x0370 */
+ __u64 gmap; /* 0x0370 */
__u64 cmf_hpp; /* 0x0378 */
/* Interrupt response block. */
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index 82d0847896a0..4506791adcd5 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -6,6 +6,7 @@ typedef struct {
unsigned int flush_mm;
spinlock_t list_lock;
struct list_head pgtable_list;
+ struct list_head gmap_list;
unsigned long asce_bits;
unsigned long asce_limit;
unsigned long vdso_base;
@@ -17,6 +18,7 @@ typedef struct {
#define INIT_MM_CONTEXT(name) \
.context.list_lock = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \
- .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),
+ .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \
+ .context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
#endif
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index 38e71ebcd3c2..8eef9b5b3cf4 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -20,7 +20,7 @@
unsigned long *crst_table_alloc(struct mm_struct *);
void crst_table_free(struct mm_struct *, unsigned long *);
-unsigned long *page_table_alloc(struct mm_struct *);
+unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
void page_table_free(struct mm_struct *, unsigned long *);
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
void page_table_free_rcu(struct mmu_gather *, unsigned long *);
@@ -115,6 +115,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
spin_lock_init(&mm->context.list_lock);
INIT_LIST_HEAD(&mm->context.pgtable_list);
+ INIT_LIST_HEAD(&mm->context.gmap_list);
return (pgd_t *) crst_table_alloc(mm);
}
#define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
@@ -133,8 +134,8 @@ static inline void pmd_populate(struct mm_struct *mm,
/*
* page table entry allocation/free routines.
*/
-#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
-#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
+#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
+#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
#define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
#define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 801fbe1d837d..519eb5f187ef 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -654,6 +654,48 @@ static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
#endif
}
+/**
+ * struct gmap_struct - guest address space
+ * @mm: pointer to the parent mm_struct
+ * @table: pointer to the page directory
+ * @crst_list: list of all crst tables used in the guest address space
+ */
+struct gmap {
+ struct list_head list;
+ struct mm_struct *mm;
+ unsigned long *table;
+ struct list_head crst_list;
+};
+
+/**
+ * struct gmap_rmap - reverse mapping for segment table entries
+ * @next: pointer to the next gmap_rmap structure in the list
+ * @entry: pointer to a segment table entry
+ */
+struct gmap_rmap {
+ struct list_head list;
+ unsigned long *entry;
+};
+
+/**
+ * struct gmap_pgtable - gmap information attached to a page table
+ * @vmaddr: address of the 1MB segment in the process virtual memory
+ * @mapper: list of segment table entries maping a page table
+ */
+struct gmap_pgtable {
+ unsigned long vmaddr;
+ struct list_head mapper;
+};
+
+struct gmap *gmap_alloc(struct mm_struct *mm);
+void gmap_free(struct gmap *gmap);
+void gmap_enable(struct gmap *gmap);
+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 *);
+
/*
* Certain architectures need to do special things when PTEs
* within a page table are directly modified. Thus, the following
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 1300c3025334..55dfcc8bdc0d 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -80,6 +80,7 @@ struct thread_struct {
mm_segment_t mm_segment;
unsigned long prot_addr; /* address of protection-excep. */
unsigned int trap_no;
+ unsigned long gmap_addr; /* address of last gmap fault. */
struct per_regs per_user; /* User specified PER registers */
struct per_event per_event; /* Cause of the last PER trap */
/* pfault_wait is used to block the process on a pfault event */
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 9ad628a8574a..62fd80c9e98c 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -539,7 +539,6 @@ struct user_regs_struct
* These are defined as per linux/ptrace.h, which see.
*/
#define arch_has_single_step() (1)
-extern void show_regs(struct pt_regs * regs);
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index ad1382f7932e..1a5dbb6f1495 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */
#define TIF_SECCOMP 10 /* secure computing */
#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */
+#define TIF_SIE 12 /* guest execution active */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_31BIT 17 /* 32bit process */
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
+#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)
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index b7a4f2eb0057..304445382382 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -80,7 +80,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
* on all cpus instead of doing a local flush if the mm
* only ran on the local cpu.
*/
- if (MACHINE_HAS_IDTE)
+ if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list))
__tlb_flush_idte((unsigned long) mm->pgd |
mm->context.asce_bits);
else
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index edfbd17d7082..05d8f38734ec 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -151,7 +151,7 @@ int main(void)
DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area));
DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
- DEFINE(__LC_SIE_HOOK, offsetof(struct _lowcore, sie_hook));
+ DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap));
DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp));
#endif /* CONFIG_32BIT */
return 0;
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
index 15e46ca94335..209938c1dfc8 100644
--- a/arch/s390/kernel/base.S
+++ b/arch/s390/kernel/base.S
@@ -6,13 +6,13 @@
* Michael Holzheu <holzheu@de.ibm.com>
*/
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
#ifdef CONFIG_64BIT
- .globl s390_base_mcck_handler
-s390_base_mcck_handler:
+ENTRY(s390_base_mcck_handler)
basr %r13,0
0: lg %r15,__LC_PANIC_STACK # load panic stack
aghi %r15,-STACK_FRAME_OVERHEAD
@@ -26,13 +26,13 @@ s390_base_mcck_handler:
lpswe __LC_MCK_OLD_PSW
.section .bss
+ .align 8
.globl s390_base_mcck_handler_fn
s390_base_mcck_handler_fn:
.quad 0
.previous
- .globl s390_base_ext_handler
-s390_base_ext_handler:
+ENTRY(s390_base_ext_handler)
stmg %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: aghi %r15,-STACK_FRAME_OVERHEAD
@@ -46,13 +46,13 @@ s390_base_ext_handler:
lpswe __LC_EXT_OLD_PSW
.section .bss
+ .align 8
.globl s390_base_ext_handler_fn
s390_base_ext_handler_fn:
.quad 0
.previous
- .globl s390_base_pgm_handler
-s390_base_pgm_handler:
+ENTRY(s390_base_pgm_handler)
stmg %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: aghi %r15,-STACK_FRAME_OVERHEAD
@@ -70,6 +70,7 @@ disabled_wait_psw:
.quad 0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler
.section .bss
+ .align 8
.globl s390_base_pgm_handler_fn
s390_base_pgm_handler_fn:
.quad 0
@@ -77,8 +78,7 @@ s390_base_pgm_handler_fn:
#else /* CONFIG_64BIT */
- .globl s390_base_mcck_handler
-s390_base_mcck_handler:
+ENTRY(s390_base_mcck_handler)
basr %r13,0
0: l %r15,__LC_PANIC_STACK # load panic stack
ahi %r15,-STACK_FRAME_OVERHEAD
@@ -93,13 +93,13 @@ s390_base_mcck_handler:
2: .long s390_base_mcck_handler_fn
.section .bss
+ .align 4
.globl s390_base_mcck_handler_fn
s390_base_mcck_handler_fn:
.long 0
.previous
- .globl s390_base_ext_handler
-s390_base_ext_handler:
+ENTRY(s390_base_ext_handler)
stm %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: ahi %r15,-STACK_FRAME_OVERHEAD
@@ -115,13 +115,13 @@ s390_base_ext_handler:
2: .long s390_base_ext_handler_fn
.section .bss
+ .align 4
.globl s390_base_ext_handler_fn
s390_base_ext_handler_fn:
.long 0
.previous
- .globl s390_base_pgm_handler
-s390_base_pgm_handler:
+ENTRY(s390_base_pgm_handler)
stm %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: ahi %r15,-STACK_FRAME_OVERHEAD
@@ -142,6 +142,7 @@ disabled_wait_psw:
.long 0x000a0000,0x00000000 + s390_base_pgm_handler
.section .bss
+ .align 4
.globl s390_base_pgm_handler_fn
s390_base_pgm_handler_fn:
.long 0
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 1f5eb789c3a7..08ab9aa6a0d5 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -7,86 +7,74 @@
* Thomas Spatzier (tspat@de.ibm.com)
*/
- .globl sys32_exit_wrapper
-sys32_exit_wrapper:
+#include <linux/linkage.h>
+
+ENTRY(sys32_exit_wrapper)
lgfr %r2,%r2 # int
jg sys_exit # branch to sys_exit
- .globl sys32_read_wrapper
-sys32_read_wrapper:
+ENTRY(sys32_read_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # char *
llgfr %r4,%r4 # size_t
jg sys32_read # branch to sys_read
- .globl sys32_write_wrapper
-sys32_write_wrapper:
+ENTRY(sys32_write_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # size_t
jg sys32_write # branch to system call
- .globl sys32_open_wrapper
-sys32_open_wrapper:
+ENTRY(sys32_open_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
jg sys_open # branch to system call
- .globl sys32_close_wrapper
-sys32_close_wrapper:
+ENTRY(sys32_close_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_close # branch to system call
- .globl sys32_creat_wrapper
-sys32_creat_wrapper:
+ENTRY(sys32_creat_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_creat # branch to system call
- .globl sys32_link_wrapper
-sys32_link_wrapper:
+ENTRY(sys32_link_wrapper)
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_link # branch to system call
- .globl sys32_unlink_wrapper
-sys32_unlink_wrapper:
+ENTRY(sys32_unlink_wrapper)
llgtr %r2,%r2 # const char *
jg sys_unlink # branch to system call
- .globl sys32_chdir_wrapper
-sys32_chdir_wrapper:
+ENTRY(sys32_chdir_wrapper)
llgtr %r2,%r2 # const char *
jg sys_chdir # branch to system call
- .globl sys32_time_wrapper
-sys32_time_wrapper:
+ENTRY(sys32_time_wrapper)
llgtr %r2,%r2 # int *
jg compat_sys_time # branch to system call
- .globl sys32_mknod_wrapper
-sys32_mknod_wrapper:
+ENTRY(sys32_mknod_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
llgfr %r4,%r4 # dev
jg sys_mknod # branch to system call
- .globl sys32_chmod_wrapper
-sys32_chmod_wrapper:
+ENTRY(sys32_chmod_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # mode_t
jg sys_chmod # branch to system call
- .globl sys32_lchown16_wrapper
-sys32_lchown16_wrapper:
+ENTRY(sys32_lchown16_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # __kernel_old_uid_emu31_t
llgfr %r4,%r4 # __kernel_old_uid_emu31_t
jg sys32_lchown16 # branch to system call
- .globl sys32_lseek_wrapper
-sys32_lseek_wrapper:
+ENTRY(sys32_lseek_wrapper)
llgfr %r2,%r2 # unsigned int
lgfr %r3,%r3 # off_t
llgfr %r4,%r4 # unsigned int
@@ -94,8 +82,7 @@ sys32_lseek_wrapper:
#sys32_getpid_wrapper # void
- .globl sys32_mount_wrapper
-sys32_mount_wrapper:
+ENTRY(sys32_mount_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # char *
@@ -103,102 +90,85 @@ sys32_mount_wrapper:
llgtr %r6,%r6 # void *
jg compat_sys_mount # branch to system call
- .globl sys32_oldumount_wrapper
-sys32_oldumount_wrapper:
+ENTRY(sys32_oldumount_wrapper)
llgtr %r2,%r2 # char *
jg sys_oldumount # branch to system call
- .globl sys32_setuid16_wrapper
-sys32_setuid16_wrapper:
+ENTRY(sys32_setuid16_wrapper)
llgfr %r2,%r2 # __kernel_old_uid_emu31_t
jg sys32_setuid16 # branch to system call
#sys32_getuid16_wrapper # void
- .globl sys32_ptrace_wrapper
-sys32_ptrace_wrapper:
+ENTRY(sys32_ptrace_wrapper)
lgfr %r2,%r2 # long
lgfr %r3,%r3 # long
llgtr %r4,%r4 # long
llgfr %r5,%r5 # long
jg compat_sys_ptrace # branch to system call
- .globl sys32_alarm_wrapper
-sys32_alarm_wrapper:
+ENTRY(sys32_alarm_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_alarm # branch to system call
- .globl compat_sys_utime_wrapper
-compat_sys_utime_wrapper:
+ENTRY(compat_sys_utime_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct compat_utimbuf *
jg compat_sys_utime # branch to system call
- .globl sys32_access_wrapper
-sys32_access_wrapper:
+ENTRY(sys32_access_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_access # branch to system call
- .globl sys32_nice_wrapper
-sys32_nice_wrapper:
+ENTRY(sys32_nice_wrapper)
lgfr %r2,%r2 # int
jg sys_nice # branch to system call
#sys32_sync_wrapper # void
- .globl sys32_kill_wrapper
-sys32_kill_wrapper:
+ENTRY(sys32_kill_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
jg sys_kill # branch to system call
- .globl sys32_rename_wrapper
-sys32_rename_wrapper:
+ENTRY(sys32_rename_wrapper)
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_rename # branch to system call
- .globl sys32_mkdir_wrapper
-sys32_mkdir_wrapper:
+ENTRY(sys32_mkdir_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_mkdir # branch to system call
- .globl sys32_rmdir_wrapper
-sys32_rmdir_wrapper:
+ENTRY(sys32_rmdir_wrapper)
llgtr %r2,%r2 # const char *
jg sys_rmdir # branch to system call
- .globl sys32_dup_wrapper
-sys32_dup_wrapper:
+ENTRY(sys32_dup_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_dup # branch to system call
- .globl sys32_pipe_wrapper
-sys32_pipe_wrapper:
+ENTRY(sys32_pipe_wrapper)
llgtr %r2,%r2 # u32 *
jg sys_pipe # branch to system call
- .globl compat_sys_times_wrapper
-compat_sys_times_wrapper:
+ENTRY(compat_sys_times_wrapper)
llgtr %r2,%r2 # struct compat_tms *
jg compat_sys_times # branch to system call
- .globl sys32_brk_wrapper
-sys32_brk_wrapper:
+ENTRY(sys32_brk_wrapper)
llgtr %r2,%r2 # unsigned long
jg sys_brk # branch to system call
- .globl sys32_setgid16_wrapper
-sys32_setgid16_wrapper:
+ENTRY(sys32_setgid16_wrapper)
llgfr %r2,%r2 # __kernel_old_gid_emu31_t
jg sys32_setgid16 # branch to system call
#sys32_getgid16_wrapper # void
- .globl sys32_signal_wrapper
-sys32_signal_wrapper:
+ENTRY(sys32_signal_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # __sighandler_t
jg sys_signal
@@ -207,55 +177,46 @@ sys32_signal_wrapper:
#sys32_getegid16_wrapper # void
- .globl sys32_acct_wrapper
-sys32_acct_wrapper:
+ENTRY(sys32_acct_wrapper)
llgtr %r2,%r2 # char *
jg sys_acct # branch to system call
- .globl sys32_umount_wrapper
-sys32_umount_wrapper:
+ENTRY(sys32_umount_wrapper)
llgtr %r2,%r2 # char *
lgfr %r3,%r3 # int
jg sys_umount # branch to system call
- .globl compat_sys_ioctl_wrapper
-compat_sys_ioctl_wrapper:
+ENTRY(compat_sys_ioctl_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
llgfr %r4,%r4 # unsigned int
jg compat_sys_ioctl # branch to system call
- .globl compat_sys_fcntl_wrapper
-compat_sys_fcntl_wrapper:
+ENTRY(compat_sys_fcntl_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
llgfr %r4,%r4 # unsigned long
jg compat_sys_fcntl # branch to system call
- .globl sys32_setpgid_wrapper
-sys32_setpgid_wrapper:
+ENTRY(sys32_setpgid_wrapper)
lgfr %r2,%r2 # pid_t
lgfr %r3,%r3 # pid_t
jg sys_setpgid # branch to system call
- .globl sys32_umask_wrapper
-sys32_umask_wrapper:
+ENTRY(sys32_umask_wrapper)
lgfr %r2,%r2 # int
jg sys_umask # branch to system call
- .globl sys32_chroot_wrapper
-sys32_chroot_wrapper:
+ENTRY(sys32_chroot_wrapper)
llgtr %r2,%r2 # char *
jg sys_chroot # branch to system call
- .globl sys32_ustat_wrapper
-sys32_ustat_wrapper:
+ENTRY(sys32_ustat_wrapper)
llgfr %r2,%r2 # dev_t
llgtr %r3,%r3 # struct ustat *
jg compat_sys_ustat
- .globl sys32_dup2_wrapper
-sys32_dup2_wrapper:
+ENTRY(sys32_dup2_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
jg sys_dup2 # branch to system call
@@ -266,262 +227,220 @@ sys32_dup2_wrapper:
#sys32_setsid_wrapper # void
- .globl sys32_sigaction_wrapper
-sys32_sigaction_wrapper:
+ENTRY(sys32_sigaction_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct old_sigaction *
llgtr %r4,%r4 # struct old_sigaction32 *
jg sys32_sigaction # branch to system call
- .globl sys32_setreuid16_wrapper
-sys32_setreuid16_wrapper:
+ENTRY(sys32_setreuid16_wrapper)
llgfr %r2,%r2 # __kernel_old_uid_emu31_t
llgfr %r3,%r3 # __kernel_old_uid_emu31_t
jg sys32_setreuid16 # branch to system call
- .globl sys32_setregid16_wrapper
-sys32_setregid16_wrapper:
+ENTRY(sys32_setregid16_wrapper)
llgfr %r2,%r2 # __kernel_old_gid_emu31_t
llgfr %r3,%r3 # __kernel_old_gid_emu31_t
jg sys32_setregid16 # branch to system call
- .globl sys_sigsuspend_wrapper
-sys_sigsuspend_wrapper:
+ENTRY(sys_sigsuspend_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
llgfr %r4,%r4 # old_sigset_t
jg sys_sigsuspend
- .globl compat_sys_sigpending_wrapper
-compat_sys_sigpending_wrapper:
+ENTRY(compat_sys_sigpending_wrapper)
llgtr %r2,%r2 # compat_old_sigset_t *
jg compat_sys_sigpending # branch to system call
- .globl sys32_sethostname_wrapper
-sys32_sethostname_wrapper:
+ENTRY(sys32_sethostname_wrapper)
llgtr %r2,%r2 # char *
lgfr %r3,%r3 # int
jg sys_sethostname # branch to system call
- .globl compat_sys_setrlimit_wrapper
-compat_sys_setrlimit_wrapper:
+ENTRY(compat_sys_setrlimit_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct rlimit_emu31 *
jg compat_sys_setrlimit # branch to system call
- .globl compat_sys_old_getrlimit_wrapper
-compat_sys_old_getrlimit_wrapper:
+ENTRY(compat_sys_old_getrlimit_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct rlimit_emu31 *
jg compat_sys_old_getrlimit # branch to system call
- .globl compat_sys_getrlimit_wrapper
-compat_sys_getrlimit_wrapper:
+ENTRY(compat_sys_getrlimit_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct rlimit_emu31 *
jg compat_sys_getrlimit # branch to system call
- .globl sys32_mmap2_wrapper
-sys32_mmap2_wrapper:
+ENTRY(sys32_mmap2_wrapper)
llgtr %r2,%r2 # struct mmap_arg_struct_emu31 *
jg sys32_mmap2 # branch to system call
- .globl compat_sys_getrusage_wrapper
-compat_sys_getrusage_wrapper:
+ENTRY(compat_sys_getrusage_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct rusage_emu31 *
jg compat_sys_getrusage # branch to system call
- .globl compat_sys_gettimeofday_wrapper
-compat_sys_gettimeofday_wrapper:
+ENTRY(compat_sys_gettimeofday_wrapper)
llgtr %r2,%r2 # struct timeval_emu31 *
llgtr %r3,%r3 # struct timezone *
jg compat_sys_gettimeofday # branch to system call
- .globl compat_sys_settimeofday_wrapper
-compat_sys_settimeofday_wrapper:
+ENTRY(compat_sys_settimeofday_wrapper)
llgtr %r2,%r2 # struct timeval_emu31 *
llgtr %r3,%r3 # struct timezone *
jg compat_sys_settimeofday # branch to system call
- .globl sys32_getgroups16_wrapper
-sys32_getgroups16_wrapper:
+ENTRY(sys32_getgroups16_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # __kernel_old_gid_emu31_t *
jg sys32_getgroups16 # branch to system call
- .globl sys32_setgroups16_wrapper
-sys32_setgroups16_wrapper:
+ENTRY(sys32_setgroups16_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # __kernel_old_gid_emu31_t *
jg sys32_setgroups16 # branch to system call
- .globl sys32_symlink_wrapper
-sys32_symlink_wrapper:
+ENTRY(sys32_symlink_wrapper)
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_symlink # branch to system call
- .globl sys32_readlink_wrapper
-sys32_readlink_wrapper:
+ENTRY(sys32_readlink_wrapper)
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # char *
lgfr %r4,%r4 # int
jg sys_readlink # branch to system call
- .globl sys32_uselib_wrapper
-sys32_uselib_wrapper:
+ENTRY(sys32_uselib_wrapper)
llgtr %r2,%r2 # const char *
jg sys_uselib # branch to system call
- .globl sys32_swapon_wrapper
-sys32_swapon_wrapper:
+ENTRY(sys32_swapon_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_swapon # branch to system call
- .globl sys32_reboot_wrapper
-sys32_reboot_wrapper:
+ENTRY(sys32_reboot_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
llgfr %r4,%r4 # unsigned int
llgtr %r5,%r5 # void *
jg sys_reboot # branch to system call
- .globl old32_readdir_wrapper
-old32_readdir_wrapper:
+ENTRY(old32_readdir_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # void *
llgfr %r4,%r4 # unsigned int
jg compat_sys_old_readdir # branch to system call
- .globl old32_mmap_wrapper
-old32_mmap_wrapper:
+ENTRY(old32_mmap_wrapper)
llgtr %r2,%r2 # struct mmap_arg_struct_emu31 *
jg old32_mmap # branch to system call
- .globl sys32_munmap_wrapper
-sys32_munmap_wrapper:
+ENTRY(sys32_munmap_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
jg sys_munmap # branch to system call
- .globl sys32_truncate_wrapper
-sys32_truncate_wrapper:
+ENTRY(sys32_truncate_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # long
jg sys_truncate # branch to system call
- .globl sys32_ftruncate_wrapper
-sys32_ftruncate_wrapper:
+ENTRY(sys32_ftruncate_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned long
jg sys_ftruncate # branch to system call
- .globl sys32_fchmod_wrapper
-sys32_fchmod_wrapper:
+ENTRY(sys32_fchmod_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # mode_t
jg sys_fchmod # branch to system call
- .globl sys32_fchown16_wrapper
-sys32_fchown16_wrapper:
+ENTRY(sys32_fchown16_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # compat_uid_t
llgfr %r4,%r4 # compat_uid_t
jg sys32_fchown16 # branch to system call
- .globl sys32_getpriority_wrapper
-sys32_getpriority_wrapper:
+ENTRY(sys32_getpriority_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
jg sys_getpriority # branch to system call
- .globl sys32_setpriority_wrapper
-sys32_setpriority_wrapper:
+ENTRY(sys32_setpriority_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
jg sys_setpriority # branch to system call
- .globl compat_sys_statfs_wrapper
-compat_sys_statfs_wrapper:
+ENTRY(compat_sys_statfs_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct compat_statfs *
jg compat_sys_statfs # branch to system call
- .globl compat_sys_fstatfs_wrapper
-compat_sys_fstatfs_wrapper:
+ENTRY(compat_sys_fstatfs_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct compat_statfs *
jg compat_sys_fstatfs # branch to system call
- .globl compat_sys_socketcall_wrapper
-compat_sys_socketcall_wrapper:
+ENTRY(compat_sys_socketcall_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # u32 *
jg compat_sys_socketcall # branch to system call
- .globl sys32_syslog_wrapper
-sys32_syslog_wrapper:
+ENTRY(sys32_syslog_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # char *
lgfr %r4,%r4 # int
jg sys_syslog # branch to system call
- .globl compat_sys_setitimer_wrapper
-compat_sys_setitimer_wrapper:
+ENTRY(compat_sys_setitimer_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct itimerval_emu31 *
llgtr %r4,%r4 # struct itimerval_emu31 *
jg compat_sys_setitimer # branch to system call
- .globl compat_sys_getitimer_wrapper
-compat_sys_getitimer_wrapper:
+ENTRY(compat_sys_getitimer_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct itimerval_emu31 *
jg compat_sys_getitimer # branch to system call
- .globl compat_sys_newstat_wrapper
-compat_sys_newstat_wrapper:
+ENTRY(compat_sys_newstat_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct stat_emu31 *
jg compat_sys_newstat # branch to system call
- .globl compat_sys_newlstat_wrapper
-compat_sys_newlstat_wrapper:
+ENTRY(compat_sys_newlstat_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct stat_emu31 *
jg compat_sys_newlstat # branch to system call
- .globl compat_sys_newfstat_wrapper
-compat_sys_newfstat_wrapper:
+ENTRY(compat_sys_newfstat_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct stat_emu31 *
jg compat_sys_newfstat # branch to system call
#sys32_vhangup_wrapper # void
- .globl compat_sys_wait4_wrapper
-compat_sys_wait4_wrapper:
+ENTRY(compat_sys_wait4_wrapper)
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # unsigned int *
lgfr %r4,%r4 # int
llgtr %r5,%r5 # struct rusage *
jg compat_sys_wait4 # branch to system call
- .globl sys32_swapoff_wrapper
-sys32_swapoff_wrapper:
+ENTRY(sys32_swapoff_wrapper)
llgtr %r2,%r2 # const char *
jg sys_swapoff # branch to system call
- .globl compat_sys_sysinfo_wrapper
-compat_sys_sysinfo_wrapper:
+ENTRY(compat_sys_sysinfo_wrapper)
llgtr %r2,%r2 # struct sysinfo_emu31 *
jg compat_sys_sysinfo # branch to system call
- .globl sys32_ipc_wrapper
-sys32_ipc_wrapper:
+ENTRY(sys32_ipc_wrapper)
llgfr %r2,%r2 # uint
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
@@ -529,8 +448,7 @@ sys32_ipc_wrapper:
llgfr %r6,%r6 # u32
jg sys32_ipc # branch to system call
- .globl sys32_fsync_wrapper
-sys32_fsync_wrapper:
+ENTRY(sys32_fsync_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_fsync # branch to system call
@@ -538,97 +456,81 @@ sys32_fsync_wrapper:
#sys32_clone_wrapper # done in clone_glue
- .globl sys32_setdomainname_wrapper
-sys32_setdomainname_wrapper:
+ENTRY(sys32_setdomainname_wrapper)
llgtr %r2,%r2 # char *
lgfr %r3,%r3 # int
jg sys_setdomainname # branch to system call
- .globl sys32_newuname_wrapper
-sys32_newuname_wrapper:
+ENTRY(sys32_newuname_wrapper)
llgtr %r2,%r2 # struct new_utsname *
jg sys_newuname # branch to system call
- .globl compat_sys_adjtimex_wrapper
-compat_sys_adjtimex_wrapper:
+ENTRY(compat_sys_adjtimex_wrapper)
llgtr %r2,%r2 # struct compat_timex *
jg compat_sys_adjtimex # branch to system call
- .globl sys32_mprotect_wrapper
-sys32_mprotect_wrapper:
+ENTRY(sys32_mprotect_wrapper)
llgtr %r2,%r2 # unsigned long (actually pointer
llgfr %r3,%r3 # size_t
llgfr %r4,%r4 # unsigned long
jg sys_mprotect # branch to system call
- .globl compat_sys_sigprocmask_wrapper
-compat_sys_sigprocmask_wrapper:
+ENTRY(compat_sys_sigprocmask_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_old_sigset_t *
llgtr %r4,%r4 # compat_old_sigset_t *
jg compat_sys_sigprocmask # branch to system call
- .globl sys_init_module_wrapper
-sys_init_module_wrapper:
+ENTRY(sys_init_module_wrapper)
llgtr %r2,%r2 # void *
llgfr %r3,%r3 # unsigned long
llgtr %r4,%r4 # char *
jg sys_init_module # branch to system call
- .globl sys_delete_module_wrapper
-sys_delete_module_wrapper:
+ENTRY(sys_delete_module_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # unsigned int
jg sys_delete_module # branch to system call
- .globl sys32_quotactl_wrapper
-sys32_quotactl_wrapper:
+ENTRY(sys32_quotactl_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # qid_t
llgtr %r5,%r5 # caddr_t
jg sys_quotactl # branch to system call
- .globl sys32_getpgid_wrapper
-sys32_getpgid_wrapper:
+ENTRY(sys32_getpgid_wrapper)
lgfr %r2,%r2 # pid_t
jg sys_getpgid # branch to system call
- .globl sys32_fchdir_wrapper
-sys32_fchdir_wrapper:
+ENTRY(sys32_fchdir_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_fchdir # branch to system call
- .globl sys32_bdflush_wrapper
-sys32_bdflush_wrapper:
+ENTRY(sys32_bdflush_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # long
jg sys_bdflush # branch to system call
- .globl sys32_sysfs_wrapper
-sys32_sysfs_wrapper:
+ENTRY(sys32_sysfs_wrapper)
lgfr %r2,%r2 # int
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
jg sys_sysfs # branch to system call
- .globl sys32_personality_wrapper
-sys32_personality_wrapper:
+ENTRY(sys32_personality_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_s390_personality # branch to system call
- .globl sys32_setfsuid16_wrapper
-sys32_setfsuid16_wrapper:
+ENTRY(sys32_setfsuid16_wrapper)
llgfr %r2,%r2 # __kernel_old_uid_emu31_t
jg sys32_setfsuid16 # branch to system call
- .globl sys32_setfsgid16_wrapper
-sys32_setfsgid16_wrapper:
+ENTRY(sys32_setfsgid16_wrapper)
llgfr %r2,%r2 # __kernel_old_gid_emu31_t
jg sys32_setfsgid16 # branch to system call
- .globl sys32_llseek_wrapper
-sys32_llseek_wrapper:
+ENTRY(sys32_llseek_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
@@ -636,15 +538,13 @@ sys32_llseek_wrapper:
llgfr %r6,%r6 # unsigned int
jg sys_llseek # branch to system call
- .globl sys32_getdents_wrapper
-sys32_getdents_wrapper:
+ENTRY(sys32_getdents_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # void *
llgfr %r4,%r4 # unsigned int
jg compat_sys_getdents # branch to system call
- .globl compat_sys_select_wrapper
-compat_sys_select_wrapper:
+ENTRY(compat_sys_select_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_fd_set *
llgtr %r4,%r4 # compat_fd_set *
@@ -652,112 +552,94 @@ compat_sys_select_wrapper:
llgtr %r6,%r6 # struct compat_timeval *
jg compat_sys_select # branch to system call
- .globl sys32_flock_wrapper
-sys32_flock_wrapper:
+ENTRY(sys32_flock_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
jg sys_flock # branch to system call
- .globl sys32_msync_wrapper
-sys32_msync_wrapper:
+ENTRY(sys32_msync_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
lgfr %r4,%r4 # int
jg sys_msync # branch to system call
- .globl compat_sys_readv_wrapper
-compat_sys_readv_wrapper:
+ENTRY(compat_sys_readv_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct compat_iovec *
llgfr %r4,%r4 # unsigned long
jg compat_sys_readv # branch to system call
- .globl compat_sys_writev_wrapper
-compat_sys_writev_wrapper:
+ENTRY(compat_sys_writev_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct compat_iovec *
llgfr %r4,%r4 # unsigned long
jg compat_sys_writev # branch to system call
- .globl sys32_getsid_wrapper
-sys32_getsid_wrapper:
+ENTRY(sys32_getsid_wrapper)
lgfr %r2,%r2 # pid_t
jg sys_getsid # branch to system call
- .globl sys32_fdatasync_wrapper
-sys32_fdatasync_wrapper:
+ENTRY(sys32_fdatasync_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_fdatasync # branch to system call
- .globl sys32_mlock_wrapper
-sys32_mlock_wrapper:
+ENTRY(sys32_mlock_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
jg sys_mlock # branch to system call
- .globl sys32_munlock_wrapper
-sys32_munlock_wrapper:
+ENTRY(sys32_munlock_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
jg sys_munlock # branch to system call
- .globl sys32_mlockall_wrapper
-sys32_mlockall_wrapper:
+ENTRY(sys32_mlockall_wrapper)
lgfr %r2,%r2 # int
jg sys_mlockall # branch to system call
#sys32_munlockall_wrapper # void
- .globl sys32_sched_setparam_wrapper
-sys32_sched_setparam_wrapper:
+ENTRY(sys32_sched_setparam_wrapper)
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # struct sched_param *
jg sys_sched_setparam # branch to system call
- .globl sys32_sched_getparam_wrapper
-sys32_sched_getparam_wrapper:
+ENTRY(sys32_sched_getparam_wrapper)
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # struct sched_param *
jg sys_sched_getparam # branch to system call
- .globl sys32_sched_setscheduler_wrapper
-sys32_sched_setscheduler_wrapper:
+ENTRY(sys32_sched_setscheduler_wrapper)
lgfr %r2,%r2 # pid_t
lgfr %r3,%r3 # int
llgtr %r4,%r4 # struct sched_param *
jg sys_sched_setscheduler # branch to system call
- .globl sys32_sched_getscheduler_wrapper
-sys32_sched_getscheduler_wrapper:
+ENTRY(sys32_sched_getscheduler_wrapper)
lgfr %r2,%r2 # pid_t
jg sys_sched_getscheduler # branch to system call
#sys32_sched_yield_wrapper # void
- .globl sys32_sched_get_priority_max_wrapper
-sys32_sched_get_priority_max_wrapper:
+ENTRY(sys32_sched_get_priority_max_wrapper)
lgfr %r2,%r2 # int
jg sys_sched_get_priority_max # branch to system call
- .globl sys32_sched_get_priority_min_wrapper
-sys32_sched_get_priority_min_wrapper:
+ENTRY(sys32_sched_get_priority_min_wrapper)
lgfr %r2,%r2 # int
jg sys_sched_get_priority_min # branch to system call
- .globl sys32_sched_rr_get_interval_wrapper
-sys32_sched_rr_get_interval_wrapper:
+ENTRY(sys32_sched_rr_get_interval_wrapper)
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # struct compat_timespec *
jg sys32_sched_rr_get_interval # branch to system call
- .globl compat_sys_nanosleep_wrapper
-compat_sys_nanosleep_wrapper:
+ENTRY(compat_sys_nanosleep_wrapper)
llgtr %r2,%r2 # struct compat_timespec *
llgtr %r3,%r3 # struct compat_timespec *
jg compat_sys_nanosleep # branch to system call
- .globl sys32_mremap_wrapper
-sys32_mremap_wrapper:
+ENTRY(sys32_mremap_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
@@ -765,50 +647,43 @@ sys32_mremap_wrapper:
llgfr %r6,%r6 # unsigned long
jg sys_mremap # branch to system call
- .globl sys32_setresuid16_wrapper
-sys32_setresuid16_wrapper:
+ENTRY(sys32_setresuid16_wrapper)
llgfr %r2,%r2 # __kernel_old_uid_emu31_t
llgfr %r3,%r3 # __kernel_old_uid_emu31_t
llgfr %r4,%r4 # __kernel_old_uid_emu31_t
jg sys32_setresuid16 # branch to system call
- .globl sys32_getresuid16_wrapper
-sys32_getresuid16_wrapper:
+ENTRY(sys32_getresuid16_wrapper)
llgtr %r2,%r2 # __kernel_old_uid_emu31_t *
llgtr %r3,%r3 # __kernel_old_uid_emu31_t *
llgtr %r4,%r4 # __kernel_old_uid_emu31_t *
jg sys32_getresuid16 # branch to system call
- .globl sys32_poll_wrapper
-sys32_poll_wrapper:
+ENTRY(sys32_poll_wrapper)
llgtr %r2,%r2 # struct pollfd *
llgfr %r3,%r3 # unsigned int
lgfr %r4,%r4 # long
jg sys_poll # branch to system call
- .globl compat_sys_nfsservctl_wrapper
-compat_sys_nfsservctl_wrapper:
+ENTRY(compat_sys_nfsservctl_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct compat_nfsctl_arg*
llgtr %r4,%r4 # union compat_nfsctl_res*
jg compat_sys_nfsservctl # branch to system call
- .globl sys32_setresgid16_wrapper
-sys32_setresgid16_wrapper:
+ENTRY(sys32_setresgid16_wrapper)
llgfr %r2,%r2 # __kernel_old_gid_emu31_t
llgfr %r3,%r3 # __kernel_old_gid_emu31_t
llgfr %r4,%r4 # __kernel_old_gid_emu31_t
jg sys32_setresgid16 # branch to system call
- .globl sys32_getresgid16_wrapper
-sys32_getresgid16_wrapper:
+ENTRY(sys32_getresgid16_wrapper)
llgtr %r2,%r2 # __kernel_old_gid_emu31_t *
llgtr %r3,%r3 # __kernel_old_gid_emu31_t *
llgtr %r4,%r4 # __kernel_old_gid_emu31_t *
jg sys32_getresgid16 # branch to system call
- .globl sys32_prctl_wrapper
-sys32_prctl_wrapper:
+ENTRY(sys32_prctl_wrapper)
lgfr %r2,%r2 # int
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
@@ -818,51 +693,44 @@ sys32_prctl_wrapper:
#sys32_rt_sigreturn_wrapper # done in rt_sigreturn_glue
- .globl sys32_rt_sigaction_wrapper
-sys32_rt_sigaction_wrapper:
+ENTRY(sys32_rt_sigaction_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct sigaction_emu31 *
llgtr %r4,%r4 # const struct sigaction_emu31 *
llgfr %r5,%r5 # size_t
jg sys32_rt_sigaction # branch to system call
- .globl sys32_rt_sigprocmask_wrapper
-sys32_rt_sigprocmask_wrapper:
+ENTRY(sys32_rt_sigprocmask_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # old_sigset_emu31 *
llgtr %r4,%r4 # old_sigset_emu31 *
llgfr %r5,%r5 # size_t
jg sys32_rt_sigprocmask # branch to system call
- .globl sys32_rt_sigpending_wrapper
-sys32_rt_sigpending_wrapper:
+ENTRY(sys32_rt_sigpending_wrapper)
llgtr %r2,%r2 # sigset_emu31 *
llgfr %r3,%r3 # size_t
jg sys32_rt_sigpending # branch to system call
- .globl compat_sys_rt_sigtimedwait_wrapper
-compat_sys_rt_sigtimedwait_wrapper:
+ENTRY(compat_sys_rt_sigtimedwait_wrapper)
llgtr %r2,%r2 # const sigset_emu31_t *
llgtr %r3,%r3 # siginfo_emu31_t *
llgtr %r4,%r4 # const struct compat_timespec *
llgfr %r5,%r5 # size_t
jg compat_sys_rt_sigtimedwait # branch to system call
- .globl sys32_rt_sigqueueinfo_wrapper
-sys32_rt_sigqueueinfo_wrapper:
+ENTRY(sys32_rt_sigqueueinfo_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
llgtr %r4,%r4 # siginfo_emu31_t *
jg sys32_rt_sigqueueinfo # branch to system call
- .globl compat_sys_rt_sigsuspend_wrapper
-compat_sys_rt_sigsuspend_wrapper:
+ENTRY(compat_sys_rt_sigsuspend_wrapper)
llgtr %r2,%r2 # compat_sigset_t *
llgfr %r3,%r3 # compat_size_t
jg compat_sys_rt_sigsuspend
- .globl sys32_pread64_wrapper
-sys32_pread64_wrapper:
+ENTRY(sys32_pread64_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # char *
llgfr %r4,%r4 # size_t
@@ -870,8 +738,7 @@ sys32_pread64_wrapper:
llgfr %r6,%r6 # u32
jg sys32_pread64 # branch to system call
- .globl sys32_pwrite64_wrapper
-sys32_pwrite64_wrapper:
+ENTRY(sys32_pwrite64_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # size_t
@@ -879,39 +746,33 @@ sys32_pwrite64_wrapper:
llgfr %r6,%r6 # u32
jg sys32_pwrite64 # branch to system call
- .globl sys32_chown16_wrapper
-sys32_chown16_wrapper:
+ENTRY(sys32_chown16_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # __kernel_old_uid_emu31_t
llgfr %r4,%r4 # __kernel_old_gid_emu31_t
jg sys32_chown16 # branch to system call
- .globl sys32_getcwd_wrapper
-sys32_getcwd_wrapper:
+ENTRY(sys32_getcwd_wrapper)
llgtr %r2,%r2 # char *
llgfr %r3,%r3 # unsigned long
jg sys_getcwd # branch to system call
- .globl sys32_capget_wrapper
-sys32_capget_wrapper:
+ENTRY(sys32_capget_wrapper)
llgtr %r2,%r2 # cap_user_header_t
llgtr %r3,%r3 # cap_user_data_t
jg sys_capget # branch to system call
- .globl sys32_capset_wrapper
-sys32_capset_wrapper:
+ENTRY(sys32_capset_wrapper)
llgtr %r2,%r2 # cap_user_header_t
llgtr %r3,%r3 # const cap_user_data_t
jg sys_capset # branch to system call
- .globl sys32_sigaltstack_wrapper
-sys32_sigaltstack_wrapper:
+ENTRY(sys32_sigaltstack_wrapper)
llgtr %r2,%r2 # const stack_emu31_t *
llgtr %r3,%r3 # stack_emu31_t *
jg sys32_sigaltstack
- .globl sys32_sendfile_wrapper
-sys32_sendfile_wrapper:
+ENTRY(sys32_sendfile_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
llgtr %r4,%r4 # __kernel_off_emu31_t *
@@ -920,22 +781,19 @@ sys32_sendfile_wrapper:
#sys32_vfork_wrapper # done in vfork_glue
- .globl sys32_truncate64_wrapper
-sys32_truncate64_wrapper:
+ENTRY(sys32_truncate64_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
jg sys32_truncate64 # branch to system call
- .globl sys32_ftruncate64_wrapper
-sys32_ftruncate64_wrapper:
+ENTRY(sys32_ftruncate64_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
jg sys32_ftruncate64 # branch to system call
- .globl sys32_lchown_wrapper
-sys32_lchown_wrapper:
+ENTRY(sys32_lchown_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # gid_t
@@ -946,156 +804,131 @@ sys32_lchown_wrapper:
#sys32_geteuid_wrapper # void
#sys32_getegid_wrapper # void
- .globl sys32_setreuid_wrapper
-sys32_setreuid_wrapper:
+ENTRY(sys32_setreuid_wrapper)
llgfr %r2,%r2 # uid_t
llgfr %r3,%r3 # uid_t
jg sys_setreuid # branch to system call
- .globl sys32_setregid_wrapper
-sys32_setregid_wrapper:
+ENTRY(sys32_setregid_wrapper)
llgfr %r2,%r2 # gid_t
llgfr %r3,%r3 # gid_t
jg sys_setregid # branch to system call
- .globl sys32_getgroups_wrapper
-sys32_getgroups_wrapper:
+ENTRY(sys32_getgroups_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # gid_t *
jg sys_getgroups # branch to system call
- .globl sys32_setgroups_wrapper
-sys32_setgroups_wrapper:
+ENTRY(sys32_setgroups_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # gid_t *
jg sys_setgroups # branch to system call
- .globl sys32_fchown_wrapper
-sys32_fchown_wrapper:
+ENTRY(sys32_fchown_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # gid_t
jg sys_fchown # branch to system call
- .globl sys32_setresuid_wrapper
-sys32_setresuid_wrapper:
+ENTRY(sys32_setresuid_wrapper)
llgfr %r2,%r2 # uid_t
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # uid_t
jg sys_setresuid # branch to system call
- .globl sys32_getresuid_wrapper
-sys32_getresuid_wrapper:
+ENTRY(sys32_getresuid_wrapper)
llgtr %r2,%r2 # uid_t *
llgtr %r3,%r3 # uid_t *
llgtr %r4,%r4 # uid_t *
jg sys_getresuid # branch to system call
- .globl sys32_setresgid_wrapper
-sys32_setresgid_wrapper:
+ENTRY(sys32_setresgid_wrapper)
llgfr %r2,%r2 # gid_t
llgfr %r3,%r3 # gid_t
llgfr %r4,%r4 # gid_t
jg sys_setresgid # branch to system call
- .globl sys32_getresgid_wrapper
-sys32_getresgid_wrapper:
+ENTRY(sys32_getresgid_wrapper)
llgtr %r2,%r2 # gid_t *
llgtr %r3,%r3 # gid_t *
llgtr %r4,%r4 # gid_t *
jg sys_getresgid # branch to system call
- .globl sys32_chown_wrapper
-sys32_chown_wrapper:
+ENTRY(sys32_chown_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # gid_t
jg sys_chown # branch to system call
- .globl sys32_setuid_wrapper
-sys32_setuid_wrapper:
+ENTRY(sys32_setuid_wrapper)
llgfr %r2,%r2 # uid_t
jg sys_setuid # branch to system call
- .globl sys32_setgid_wrapper
-sys32_setgid_wrapper:
+ENTRY(sys32_setgid_wrapper)
llgfr %r2,%r2 # gid_t
jg sys_setgid # branch to system call
- .globl sys32_setfsuid_wrapper
-sys32_setfsuid_wrapper:
+ENTRY(sys32_setfsuid_wrapper)
llgfr %r2,%r2 # uid_t
jg sys_setfsuid # branch to system call
- .globl sys32_setfsgid_wrapper
-sys32_setfsgid_wrapper:
+ENTRY(sys32_setfsgid_wrapper)
llgfr %r2,%r2 # gid_t
jg sys_setfsgid # branch to system call
- .globl sys32_pivot_root_wrapper
-sys32_pivot_root_wrapper:
+ENTRY(sys32_pivot_root_wrapper)
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_pivot_root # branch to system call
- .globl sys32_mincore_wrapper
-sys32_mincore_wrapper:
+ENTRY(sys32_mincore_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
llgtr %r4,%r4 # unsigned char *
jg sys_mincore # branch to system call
- .globl sys32_madvise_wrapper
-sys32_madvise_wrapper:
+ENTRY(sys32_madvise_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
lgfr %r4,%r4 # int
jg sys_madvise # branch to system call
- .globl sys32_getdents64_wrapper
-sys32_getdents64_wrapper:
+ENTRY(sys32_getdents64_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # void *
llgfr %r4,%r4 # unsigned int
jg sys_getdents64 # branch to system call
- .globl compat_sys_fcntl64_wrapper
-compat_sys_fcntl64_wrapper:
+ENTRY(compat_sys_fcntl64_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
llgfr %r4,%r4 # unsigned long
jg compat_sys_fcntl64 # branch to system call
- .globl sys32_stat64_wrapper
-sys32_stat64_wrapper:
+ENTRY(sys32_stat64_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct stat64 *
jg sys32_stat64 # branch to system call
- .globl sys32_lstat64_wrapper
-sys32_lstat64_wrapper:
+ENTRY(sys32_lstat64_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct stat64 *
jg sys32_lstat64 # branch to system call
- .globl sys32_stime_wrapper
-sys32_stime_wrapper:
+ENTRY(sys32_stime_wrapper)
llgtr %r2,%r2 # long *
jg compat_sys_stime # branch to system call
- .globl sys32_sysctl_wrapper
-sys32_sysctl_wrapper:
+ENTRY(sys32_sysctl_wrapper)
llgtr %r2,%r2 # struct compat_sysctl_args *
jg compat_sys_sysctl
- .globl sys32_fstat64_wrapper
-sys32_fstat64_wrapper:
+ENTRY(sys32_fstat64_wrapper)
llgfr %r2,%r2 # unsigned long
llgtr %r3,%r3 # struct stat64 *
jg sys32_fstat64 # branch to system call
- .globl compat_sys_futex_wrapper
-compat_sys_futex_wrapper:
+ENTRY(compat_sys_futex_wrapper)
llgtr %r2,%r2 # u32 *
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
@@ -1105,8 +938,7 @@ compat_sys_futex_wrapper:
stg %r0,160(%r15)
jg compat_sys_futex # branch to system call
- .globl sys32_setxattr_wrapper
-sys32_setxattr_wrapper:
+ENTRY(sys32_setxattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # void *
@@ -1114,8 +946,7 @@ sys32_setxattr_wrapper:
lgfr %r6,%r6 # int
jg sys_setxattr
- .globl sys32_lsetxattr_wrapper
-sys32_lsetxattr_wrapper:
+ENTRY(sys32_lsetxattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # void *
@@ -1123,8 +954,7 @@ sys32_lsetxattr_wrapper:
lgfr %r6,%r6 # int
jg sys_lsetxattr
- .globl sys32_fsetxattr_wrapper
-sys32_fsetxattr_wrapper:
+ENTRY(sys32_fsetxattr_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # void *
@@ -1132,124 +962,106 @@ sys32_fsetxattr_wrapper:
lgfr %r6,%r6 # int
jg sys_fsetxattr
- .globl sys32_getxattr_wrapper
-sys32_getxattr_wrapper:
+ENTRY(sys32_getxattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # void *
llgfr %r5,%r5 # size_t
jg sys_getxattr
- .globl sys32_lgetxattr_wrapper
-sys32_lgetxattr_wrapper:
+ENTRY(sys32_lgetxattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # void *
llgfr %r5,%r5 # size_t
jg sys_lgetxattr
- .globl sys32_fgetxattr_wrapper
-sys32_fgetxattr_wrapper:
+ENTRY(sys32_fgetxattr_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # void *
llgfr %r5,%r5 # size_t
jg sys_fgetxattr
- .globl sys32_listxattr_wrapper
-sys32_listxattr_wrapper:
+ENTRY(sys32_listxattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
llgfr %r4,%r4 # size_t
jg sys_listxattr
- .globl sys32_llistxattr_wrapper
-sys32_llistxattr_wrapper:
+ENTRY(sys32_llistxattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
llgfr %r4,%r4 # size_t
jg sys_llistxattr
- .globl sys32_flistxattr_wrapper
-sys32_flistxattr_wrapper:
+ENTRY(sys32_flistxattr_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # char *
llgfr %r4,%r4 # size_t
jg sys_flistxattr
- .globl sys32_removexattr_wrapper
-sys32_removexattr_wrapper:
+ENTRY(sys32_removexattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
jg sys_removexattr
- .globl sys32_lremovexattr_wrapper
-sys32_lremovexattr_wrapper:
+ENTRY(sys32_lremovexattr_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
jg sys_lremovexattr
- .globl sys32_fremovexattr_wrapper
-sys32_fremovexattr_wrapper:
+ENTRY(sys32_fremovexattr_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # char *
jg sys_fremovexattr
- .globl sys32_sched_setaffinity_wrapper
-sys32_sched_setaffinity_wrapper:
+ENTRY(sys32_sched_setaffinity_wrapper)
lgfr %r2,%r2 # int
llgfr %r3,%r3 # unsigned int
llgtr %r4,%r4 # unsigned long *
jg compat_sys_sched_setaffinity
- .globl sys32_sched_getaffinity_wrapper
-sys32_sched_getaffinity_wrapper:
+ENTRY(sys32_sched_getaffinity_wrapper)
lgfr %r2,%r2 # int
llgfr %r3,%r3 # unsigned int
llgtr %r4,%r4 # unsigned long *
jg compat_sys_sched_getaffinity
- .globl sys32_exit_group_wrapper
-sys32_exit_group_wrapper:
+ENTRY(sys32_exit_group_wrapper)
lgfr %r2,%r2 # int
jg sys_exit_group # branch to system call
- .globl sys32_set_tid_address_wrapper
-sys32_set_tid_address_wrapper:
+ENTRY(sys32_set_tid_address_wrapper)
llgtr %r2,%r2 # int *
jg sys_set_tid_address # branch to system call
- .globl sys_epoll_create_wrapper
-sys_epoll_create_wrapper:
+ENTRY(sys_epoll_create_wrapper)
lgfr %r2,%r2 # int
jg sys_epoll_create # branch to system call
- .globl sys_epoll_ctl_wrapper
-sys_epoll_ctl_wrapper:
+ENTRY(sys_epoll_ctl_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
llgtr %r5,%r5 # struct epoll_event *
jg sys_epoll_ctl # branch to system call
- .globl sys_epoll_wait_wrapper
-sys_epoll_wait_wrapper:
+ENTRY(sys_epoll_wait_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct epoll_event *
lgfr %r4,%r4 # int
lgfr %r5,%r5 # int
jg sys_epoll_wait # branch to system call
- .globl sys32_lookup_dcookie_wrapper
-sys32_lookup_dcookie_wrapper:
+ENTRY(sys32_lookup_dcookie_wrapper)
sllg %r2,%r2,32 # get high word of 64bit dcookie
or %r2,%r3 # get low word of 64bit dcookie
llgtr %r3,%r4 # char *
llgfr %r4,%r5 # size_t
jg sys_lookup_dcookie
- .globl sys32_fadvise64_wrapper
-sys32_fadvise64_wrapper:
+ENTRY(sys32_fadvise64_wrapper)
lgfr %r2,%r2 # int
sllg %r3,%r3,32 # get high word of 64bit loff_t
or %r3,%r4 # get low word of 64bit loff_t
@@ -1257,81 +1069,68 @@ sys32_fadvise64_wrapper:
lgfr %r5,%r6 # int
jg sys32_fadvise64
- .globl sys32_fadvise64_64_wrapper
-sys32_fadvise64_64_wrapper:
+ENTRY(sys32_fadvise64_64_wrapper)
llgtr %r2,%r2 # struct fadvise64_64_args *
jg sys32_fadvise64_64
- .globl sys32_clock_settime_wrapper
-sys32_clock_settime_wrapper:
+ENTRY(sys32_clock_settime_wrapper)
lgfr %r2,%r2 # clockid_t (int)
llgtr %r3,%r3 # struct compat_timespec *
jg compat_sys_clock_settime
- .globl sys32_clock_gettime_wrapper
-sys32_clock_gettime_wrapper:
+ENTRY(sys32_clock_gettime_wrapper)
lgfr %r2,%r2 # clockid_t (int)
llgtr %r3,%r3 # struct compat_timespec *
jg compat_sys_clock_gettime
- .globl sys32_clock_getres_wrapper
-sys32_clock_getres_wrapper:
+ENTRY(sys32_clock_getres_wrapper)
lgfr %r2,%r2 # clockid_t (int)
llgtr %r3,%r3 # struct compat_timespec *
jg compat_sys_clock_getres
- .globl sys32_clock_nanosleep_wrapper
-sys32_clock_nanosleep_wrapper:
+ENTRY(sys32_clock_nanosleep_wrapper)
lgfr %r2,%r2 # clockid_t (int)
lgfr %r3,%r3 # int
llgtr %r4,%r4 # struct compat_timespec *
llgtr %r5,%r5 # struct compat_timespec *
jg compat_sys_clock_nanosleep
- .globl sys32_timer_create_wrapper
-sys32_timer_create_wrapper:
+ENTRY(sys32_timer_create_wrapper)
lgfr %r2,%r2 # timer_t (int)
llgtr %r3,%r3 # struct compat_sigevent *
llgtr %r4,%r4 # timer_t *
jg compat_sys_timer_create
- .globl sys32_timer_settime_wrapper
-sys32_timer_settime_wrapper:
+ENTRY(sys32_timer_settime_wrapper)
lgfr %r2,%r2 # timer_t (int)
lgfr %r3,%r3 # int
llgtr %r4,%r4 # struct compat_itimerspec *
llgtr %r5,%r5 # struct compat_itimerspec *
jg compat_sys_timer_settime
- .globl sys32_timer_gettime_wrapper
-sys32_timer_gettime_wrapper:
+ENTRY(sys32_timer_gettime_wrapper)
lgfr %r2,%r2 # timer_t (int)
llgtr %r3,%r3 # struct compat_itimerspec *
jg compat_sys_timer_gettime
- .globl sys32_timer_getoverrun_wrapper
-sys32_timer_getoverrun_wrapper:
+ENTRY(sys32_timer_getoverrun_wrapper)
lgfr %r2,%r2 # timer_t (int)
jg sys_timer_getoverrun
- .globl sys32_timer_delete_wrapper
-sys32_timer_delete_wrapper:
+ENTRY(sys32_timer_delete_wrapper)
lgfr %r2,%r2 # timer_t (int)
jg sys_timer_delete
- .globl sys32_io_setup_wrapper
-sys32_io_setup_wrapper:
+ENTRY(sys32_io_setup_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # u32 *
jg compat_sys_io_setup
- .globl sys32_io_destroy_wrapper
-sys32_io_destroy_wrapper:
+ENTRY(sys32_io_destroy_wrapper)
llgfr %r2,%r2 # (aio_context_t) u32
jg sys_io_destroy
- .globl sys32_io_getevents_wrapper
-sys32_io_getevents_wrapper:
+ENTRY(sys32_io_getevents_wrapper)
llgfr %r2,%r2 # (aio_context_t) u32
lgfr %r3,%r3 # long
lgfr %r4,%r4 # long
@@ -1339,49 +1138,42 @@ sys32_io_getevents_wrapper:
llgtr %r6,%r6 # struct compat_timespec *
jg compat_sys_io_getevents
- .globl sys32_io_submit_wrapper
-sys32_io_submit_wrapper:
+ENTRY(sys32_io_submit_wrapper)
llgfr %r2,%r2 # (aio_context_t) u32
lgfr %r3,%r3 # long
llgtr %r4,%r4 # struct iocb **
jg compat_sys_io_submit
- .globl sys32_io_cancel_wrapper
-sys32_io_cancel_wrapper:
+ENTRY(sys32_io_cancel_wrapper)
llgfr %r2,%r2 # (aio_context_t) u32
llgtr %r3,%r3 # struct iocb *
llgtr %r4,%r4 # struct io_event *
jg sys_io_cancel
- .globl compat_sys_statfs64_wrapper
-compat_sys_statfs64_wrapper:
+ENTRY(compat_sys_statfs64_wrapper)
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # compat_size_t
llgtr %r4,%r4 # struct compat_statfs64 *
jg compat_sys_statfs64
- .globl compat_sys_fstatfs64_wrapper
-compat_sys_fstatfs64_wrapper:
+ENTRY(compat_sys_fstatfs64_wrapper)
llgfr %r2,%r2 # unsigned int fd
llgfr %r3,%r3 # compat_size_t
llgtr %r4,%r4 # struct compat_statfs64 *
jg compat_sys_fstatfs64
- .globl compat_sys_mq_open_wrapper
-compat_sys_mq_open_wrapper:
+ENTRY(compat_sys_mq_open_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
llgfr %r4,%r4 # mode_t
llgtr %r5,%r5 # struct compat_mq_attr *
jg compat_sys_mq_open
- .globl sys32_mq_unlink_wrapper
-sys32_mq_unlink_wrapper:
+ENTRY(sys32_mq_unlink_wrapper)
llgtr %r2,%r2 # const char *
jg sys_mq_unlink
- .globl compat_sys_mq_timedsend_wrapper
-compat_sys_mq_timedsend_wrapper:
+ENTRY(compat_sys_mq_timedsend_wrapper)
lgfr %r2,%r2 # mqd_t
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # size_t
@@ -1389,8 +1181,7 @@ compat_sys_mq_timedsend_wrapper:
llgtr %r6,%r6 # const struct compat_timespec *
jg compat_sys_mq_timedsend
- .globl compat_sys_mq_timedreceive_wrapper
-compat_sys_mq_timedreceive_wrapper:
+ENTRY(compat_sys_mq_timedreceive_wrapper)
lgfr %r2,%r2 # mqd_t
llgtr %r3,%r3 # char *
llgfr %r4,%r4 # size_t
@@ -1398,21 +1189,18 @@ compat_sys_mq_timedreceive_wrapper:
llgtr %r6,%r6 # const struct compat_timespec *
jg compat_sys_mq_timedreceive
- .globl compat_sys_mq_notify_wrapper
-compat_sys_mq_notify_wrapper:
+ENTRY(compat_sys_mq_notify_wrapper)
lgfr %r2,%r2 # mqd_t
llgtr %r3,%r3 # struct compat_sigevent *
jg compat_sys_mq_notify
- .globl compat_sys_mq_getsetattr_wrapper
-compat_sys_mq_getsetattr_wrapper:
+ENTRY(compat_sys_mq_getsetattr_wrapper)
lgfr %r2,%r2 # mqd_t
llgtr %r3,%r3 # struct compat_mq_attr *
llgtr %r4,%r4 # struct compat_mq_attr *
jg compat_sys_mq_getsetattr
- .globl compat_sys_add_key_wrapper
-compat_sys_add_key_wrapper:
+ENTRY(compat_sys_add_key_wrapper)
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
llgtr %r4,%r4 # const void *
@@ -1420,16 +1208,14 @@ compat_sys_add_key_wrapper:
llgfr %r6,%r6 # (key_serial_t) u32
jg sys_add_key
- .globl compat_sys_request_key_wrapper
-compat_sys_request_key_wrapper:
+ENTRY(compat_sys_request_key_wrapper)
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
llgtr %r4,%r4 # const void *
llgfr %r5,%r5 # (key_serial_t) u32
jg sys_request_key
- .globl sys32_remap_file_pages_wrapper
-sys32_remap_file_pages_wrapper:
+ENTRY(sys32_remap_file_pages_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
@@ -1437,8 +1223,7 @@ sys32_remap_file_pages_wrapper:
llgfr %r6,%r6 # unsigned long
jg sys_remap_file_pages
- .globl compat_sys_waitid_wrapper
-compat_sys_waitid_wrapper:
+ENTRY(compat_sys_waitid_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # pid_t
llgtr %r4,%r4 # siginfo_emu31_t *
@@ -1446,65 +1231,56 @@ compat_sys_waitid_wrapper:
llgtr %r6,%r6 # struct rusage_emu31 *
jg compat_sys_waitid
- .globl compat_sys_kexec_load_wrapper
-compat_sys_kexec_load_wrapper:
+ENTRY(compat_sys_kexec_load_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # unsigned long
llgtr %r4,%r4 # struct kexec_segment *
llgfr %r5,%r5 # unsigned long
jg compat_sys_kexec_load
- .globl sys_ioprio_set_wrapper
-sys_ioprio_set_wrapper:
+ENTRY(sys_ioprio_set_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
jg sys_ioprio_set
- .globl sys_ioprio_get_wrapper
-sys_ioprio_get_wrapper:
+ENTRY(sys_ioprio_get_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
jg sys_ioprio_get
- .globl sys_inotify_add_watch_wrapper
-sys_inotify_add_watch_wrapper:
+ENTRY(sys_inotify_add_watch_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # u32
jg sys_inotify_add_watch
- .globl sys_inotify_rm_watch_wrapper
-sys_inotify_rm_watch_wrapper:
+ENTRY(sys_inotify_rm_watch_wrapper)
lgfr %r2,%r2 # int
llgfr %r3,%r3 # u32
jg sys_inotify_rm_watch
- .globl compat_sys_openat_wrapper
-compat_sys_openat_wrapper:
+ENTRY(compat_sys_openat_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # const char *
lgfr %r4,%r4 # int
lgfr %r5,%r5 # int
jg compat_sys_openat
- .globl sys_mkdirat_wrapper
-sys_mkdirat_wrapper:
+ENTRY(sys_mkdirat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
lgfr %r4,%r4 # int
jg sys_mkdirat
- .globl sys_mknodat_wrapper
-sys_mknodat_wrapper:
+ENTRY(sys_mknodat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
lgfr %r4,%r4 # int
llgfr %r5,%r5 # unsigned int
jg sys_mknodat
- .globl sys_fchownat_wrapper
-sys_fchownat_wrapper:
+ENTRY(sys_fchownat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # uid_t
@@ -1512,38 +1288,33 @@ sys_fchownat_wrapper:
lgfr %r6,%r6 # int
jg sys_fchownat
- .globl compat_sys_futimesat_wrapper
-compat_sys_futimesat_wrapper:
+ENTRY(compat_sys_futimesat_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # struct timeval *
jg compat_sys_futimesat
- .globl sys32_fstatat64_wrapper
-sys32_fstatat64_wrapper:
+ENTRY(sys32_fstatat64_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # struct stat64 *
lgfr %r5,%r5 # int
jg sys32_fstatat64
- .globl sys_unlinkat_wrapper
-sys_unlinkat_wrapper:
+ENTRY(sys_unlinkat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
lgfr %r4,%r4 # int
jg sys_unlinkat
- .globl sys_renameat_wrapper
-sys_renameat_wrapper:
+ENTRY(sys_renameat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
lgfr %r4,%r4 # int
llgtr %r5,%r5 # const char *
jg sys_renameat
- .globl sys_linkat_wrapper
-sys_linkat_wrapper:
+ENTRY(sys_linkat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
lgfr %r4,%r4 # int
@@ -1551,37 +1322,32 @@ sys_linkat_wrapper:
lgfr %r6,%r6 # int
jg sys_linkat
- .globl sys_symlinkat_wrapper
-sys_symlinkat_wrapper:
+ENTRY(sys_symlinkat_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
llgtr %r4,%r4 # const char *
jg sys_symlinkat
- .globl sys_readlinkat_wrapper
-sys_readlinkat_wrapper:
+ENTRY(sys_readlinkat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
llgtr %r4,%r4 # char *
lgfr %r5,%r5 # int
jg sys_readlinkat
- .globl sys_fchmodat_wrapper
-sys_fchmodat_wrapper:
+ENTRY(sys_fchmodat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # mode_t
jg sys_fchmodat
- .globl sys_faccessat_wrapper
-sys_faccessat_wrapper:
+ENTRY(sys_faccessat_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char *
lgfr %r4,%r4 # int
jg sys_faccessat
- .globl compat_sys_pselect6_wrapper
-compat_sys_pselect6_wrapper:
+ENTRY(compat_sys_pselect6_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # fd_set *
llgtr %r4,%r4 # fd_set *
@@ -1591,8 +1357,7 @@ compat_sys_pselect6_wrapper:
stg %r0,160(%r15)
jg compat_sys_pselect6
- .globl compat_sys_ppoll_wrapper
-compat_sys_ppoll_wrapper:
+ENTRY(compat_sys_ppoll_wrapper)
llgtr %r2,%r2 # struct pollfd *
llgfr %r3,%r3 # unsigned int
llgtr %r4,%r4 # struct timespec *
@@ -1600,26 +1365,22 @@ compat_sys_ppoll_wrapper:
llgfr %r6,%r6 # size_t
jg compat_sys_ppoll
- .globl sys_unshare_wrapper
-sys_unshare_wrapper:
+ENTRY(sys_unshare_wrapper)
llgfr %r2,%r2 # unsigned long
jg sys_unshare
- .globl compat_sys_set_robust_list_wrapper
-compat_sys_set_robust_list_wrapper:
+ENTRY(compat_sys_set_robust_list_wrapper)
llgtr %r2,%r2 # struct compat_robust_list_head *
llgfr %r3,%r3 # size_t
jg compat_sys_set_robust_list
- .globl compat_sys_get_robust_list_wrapper
-compat_sys_get_robust_list_wrapper:
+ENTRY(compat_sys_get_robust_list_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_uptr_t_t *
llgtr %r4,%r4 # compat_size_t *
jg compat_sys_get_robust_list
- .globl sys_splice_wrapper
-sys_splice_wrapper:
+ENTRY(sys_splice_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # loff_t *
lgfr %r4,%r4 # int
@@ -1629,8 +1390,7 @@ sys_splice_wrapper:
stg %r0,160(%r15)
jg sys_splice
- .globl sys_sync_file_range_wrapper
-sys_sync_file_range_wrapper:
+ENTRY(sys_sync_file_range_wrapper)
lgfr %r2,%r2 # int
sllg %r3,%r3,32 # get high word of 64bit loff_t
or %r3,%r4 # get low word of 64bit loff_t
@@ -1639,31 +1399,27 @@ sys_sync_file_range_wrapper:
llgf %r5,164(%r15) # unsigned int
jg sys_sync_file_range
- .globl sys_tee_wrapper
-sys_tee_wrapper:
+ENTRY(sys_tee_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
llgfr %r4,%r4 # size_t
llgfr %r5,%r5 # unsigned int
jg sys_tee
- .globl compat_sys_vmsplice_wrapper
-compat_sys_vmsplice_wrapper:
+ENTRY(compat_sys_vmsplice_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_iovec *
llgfr %r4,%r4 # unsigned int
llgfr %r5,%r5 # unsigned int
jg compat_sys_vmsplice
- .globl sys_getcpu_wrapper
-sys_getcpu_wrapper:
+ENTRY(sys_getcpu_wrapper)
llgtr %r2,%r2 # unsigned *
llgtr %r3,%r3 # unsigned *
llgtr %r4,%r4 # struct getcpu_cache *
jg sys_getcpu
- .globl compat_sys_epoll_pwait_wrapper
-compat_sys_epoll_pwait_wrapper:
+ENTRY(compat_sys_epoll_pwait_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct compat_epoll_event *
lgfr %r4,%r4 # int
@@ -1673,34 +1429,29 @@ compat_sys_epoll_pwait_wrapper:
stg %r0,160(%r15)
jg compat_sys_epoll_pwait
- .globl compat_sys_utimes_wrapper
-compat_sys_utimes_wrapper:
+ENTRY(compat_sys_utimes_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct compat_timeval *
jg compat_sys_utimes
- .globl compat_sys_utimensat_wrapper
-compat_sys_utimensat_wrapper:
+ENTRY(compat_sys_utimensat_wrapper)
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # char *
llgtr %r4,%r4 # struct compat_timespec *
lgfr %r5,%r5 # int
jg compat_sys_utimensat
- .globl compat_sys_signalfd_wrapper
-compat_sys_signalfd_wrapper:
+ENTRY(compat_sys_signalfd_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_sigset_t *
llgfr %r4,%r4 # compat_size_t
jg compat_sys_signalfd
- .globl sys_eventfd_wrapper
-sys_eventfd_wrapper:
+ENTRY(sys_eventfd_wrapper)
llgfr %r2,%r2 # unsigned int
jg sys_eventfd
- .globl sys_fallocate_wrapper
-sys_fallocate_wrapper:
+ENTRY(sys_fallocate_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
sllg %r4,%r4,32 # get high word of 64bit loff_t
@@ -1709,94 +1460,80 @@ sys_fallocate_wrapper:
l %r5,164(%r15) # get low word of 64bit loff_t
jg sys_fallocate
- .globl sys_timerfd_create_wrapper
-sys_timerfd_create_wrapper:
+ENTRY(sys_timerfd_create_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
jg sys_timerfd_create
- .globl compat_sys_timerfd_settime_wrapper
-compat_sys_timerfd_settime_wrapper:
+ENTRY(compat_sys_timerfd_settime_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
llgtr %r4,%r4 # struct compat_itimerspec *
llgtr %r5,%r5 # struct compat_itimerspec *
jg compat_sys_timerfd_settime
- .globl compat_sys_timerfd_gettime_wrapper
-compat_sys_timerfd_gettime_wrapper:
+ENTRY(compat_sys_timerfd_gettime_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct compat_itimerspec *
jg compat_sys_timerfd_gettime
- .globl compat_sys_signalfd4_wrapper
-compat_sys_signalfd4_wrapper:
+ENTRY(compat_sys_signalfd4_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_sigset_t *
llgfr %r4,%r4 # compat_size_t
lgfr %r5,%r5 # int
jg compat_sys_signalfd4
- .globl sys_eventfd2_wrapper
-sys_eventfd2_wrapper:
+ENTRY(sys_eventfd2_wrapper)
llgfr %r2,%r2 # unsigned int
lgfr %r3,%r3 # int
jg sys_eventfd2
- .globl sys_inotify_init1_wrapper
-sys_inotify_init1_wrapper:
+ENTRY(sys_inotify_init1_wrapper)
lgfr %r2,%r2 # int
jg sys_inotify_init1
- .globl sys_pipe2_wrapper
-sys_pipe2_wrapper:
+ENTRY(sys_pipe2_wrapper)
llgtr %r2,%r2 # u32 *
lgfr %r3,%r3 # int
jg sys_pipe2 # branch to system call
- .globl sys_dup3_wrapper
-sys_dup3_wrapper:
+ENTRY(sys_dup3_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
lgfr %r4,%r4 # int
jg sys_dup3 # branch to system call
- .globl sys_epoll_create1_wrapper
-sys_epoll_create1_wrapper:
+ENTRY(sys_epoll_create1_wrapper)
lgfr %r2,%r2 # int
jg sys_epoll_create1 # branch to system call
- .globl sys32_readahead_wrapper
-sys32_readahead_wrapper:
+ENTRY(sys32_readahead_wrapper)
lgfr %r2,%r2 # int
llgfr %r3,%r3 # u32
llgfr %r4,%r4 # u32
lgfr %r5,%r5 # s32
jg sys32_readahead # branch to system call
- .globl sys32_sendfile64_wrapper
-sys32_sendfile64_wrapper:
+ENTRY(sys32_sendfile64_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
llgtr %r4,%r4 # compat_loff_t *
lgfr %r5,%r5 # s32
jg sys32_sendfile64 # branch to system call
- .globl sys_tkill_wrapper
-sys_tkill_wrapper:
+ENTRY(sys_tkill_wrapper)
lgfr %r2,%r2 # pid_t
lgfr %r3,%r3 # int
jg sys_tkill # branch to system call
- .globl sys_tgkill_wrapper
-sys_tgkill_wrapper:
+ENTRY(sys_tgkill_wrapper)
lgfr %r2,%r2 # pid_t
lgfr %r3,%r3 # pid_t
lgfr %r4,%r4 # int
jg sys_tgkill # branch to system call
- .globl compat_sys_keyctl_wrapper
-compat_sys_keyctl_wrapper:
+ENTRY(compat_sys_keyctl_wrapper)
llgfr %r2,%r2 # u32
llgfr %r3,%r3 # u32
llgfr %r4,%r4 # u32
@@ -1804,8 +1541,7 @@ compat_sys_keyctl_wrapper:
llgfr %r6,%r6 # u32
jg compat_sys_keyctl # branch to system call
- .globl compat_sys_preadv_wrapper
-compat_sys_preadv_wrapper:
+ENTRY(compat_sys_preadv_wrapper)
llgfr %r2,%r2 # unsigned long
llgtr %r3,%r3 # compat_iovec *
llgfr %r4,%r4 # unsigned long
@@ -1813,8 +1549,7 @@ compat_sys_preadv_wrapper:
llgfr %r6,%r6 # u32
jg compat_sys_preadv # branch to system call
- .globl compat_sys_pwritev_wrapper
-compat_sys_pwritev_wrapper:
+ENTRY(compat_sys_pwritev_wrapper)
llgfr %r2,%r2 # unsigned long
llgtr %r3,%r3 # compat_iovec *
llgfr %r4,%r4 # unsigned long
@@ -1822,16 +1557,14 @@ compat_sys_pwritev_wrapper:
llgfr %r6,%r6 # u32
jg compat_sys_pwritev # branch to system call
- .globl compat_sys_rt_tgsigqueueinfo_wrapper
-compat_sys_rt_tgsigqueueinfo_wrapper:
+ENTRY(compat_sys_rt_tgsigqueueinfo_wrapper)
lgfr %r2,%r2 # compat_pid_t
lgfr %r3,%r3 # compat_pid_t
lgfr %r4,%r4 # int
llgtr %r5,%r5 # struct compat_siginfo *
jg compat_sys_rt_tgsigqueueinfo_wrapper # branch to system call
- .globl sys_perf_event_open_wrapper
-sys_perf_event_open_wrapper:
+ENTRY(sys_perf_event_open_wrapper)
llgtr %r2,%r2 # const struct perf_event_attr *
lgfr %r3,%r3 # pid_t
lgfr %r4,%r4 # int
@@ -1839,29 +1572,25 @@ sys_perf_event_open_wrapper:
llgfr %r6,%r6 # unsigned long
jg sys_perf_event_open # branch to system call
- .globl sys_clone_wrapper
-sys_clone_wrapper:
+ENTRY(sys_clone_wrapper)
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # unsigned long
llgtr %r4,%r4 # int *
llgtr %r5,%r5 # int *
jg sys_clone # branch to system call
- .globl sys32_execve_wrapper
-sys32_execve_wrapper:
+ENTRY(sys32_execve_wrapper)
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # compat_uptr_t *
llgtr %r4,%r4 # compat_uptr_t *
jg sys32_execve # branch to system call
- .globl sys_fanotify_init_wrapper
-sys_fanotify_init_wrapper:
+ENTRY(sys_fanotify_init_wrapper)
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
jg sys_fanotify_init # branch to system call
- .globl sys_fanotify_mark_wrapper
-sys_fanotify_mark_wrapper:
+ENTRY(sys_fanotify_mark_wrapper)
lgfr %r2,%r2 # int
llgfr %r3,%r3 # unsigned int
sllg %r4,%r4,32 # get high word of 64bit mask
@@ -1870,16 +1599,14 @@ sys_fanotify_mark_wrapper:
llgt %r6,164(%r15) # char *
jg sys_fanotify_mark # branch to system call
- .globl sys_prlimit64_wrapper
-sys_prlimit64_wrapper:
+ENTRY(sys_prlimit64_wrapper)
lgfr %r2,%r2 # pid_t
llgfr %r3,%r3 # unsigned int
llgtr %r4,%r4 # const struct rlimit64 __user *
llgtr %r5,%r5 # struct rlimit64 __user *
jg sys_prlimit64 # branch to system call
- .globl sys_name_to_handle_at_wrapper
-sys_name_to_handle_at_wrapper:
+ENTRY(sys_name_to_handle_at_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const char __user *
llgtr %r4,%r4 # struct file_handle __user *
@@ -1887,21 +1614,18 @@ sys_name_to_handle_at_wrapper:
lgfr %r6,%r6 # int
jg sys_name_to_handle_at
- .globl compat_sys_open_by_handle_at_wrapper
-compat_sys_open_by_handle_at_wrapper:
+ENTRY(compat_sys_open_by_handle_at_wrapper)
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct file_handle __user *
lgfr %r4,%r4 # int
jg compat_sys_open_by_handle_at
- .globl compat_sys_clock_adjtime_wrapper
-compat_sys_clock_adjtime_wrapper:
+ENTRY(compat_sys_clock_adjtime_wrapper)
lgfr %r2,%r2 # clockid_t (int)
llgtr %r3,%r3 # struct compat_timex __user *
jg compat_sys_clock_adjtime
- .globl sys_syncfs_wrapper
-sys_syncfs_wrapper:
+ENTRY(sys_syncfs_wrapper)
lgfr %r2,%r2 # int
jg sys_syncfs
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 1ca3d1d6a86c..45df6d456aa1 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -27,7 +27,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/mathemu.h>
#include <asm/cpcmd.h>
#include <asm/lowcore.h>
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 0476174dfff5..3eab7cfab07c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -9,8 +9,8 @@
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
-#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/linkage.h>
#include <asm/cache.h>
#include <asm/errno.h>
#include <asm/ptrace.h>
@@ -197,8 +197,7 @@ STACK_SIZE = 1 << STACK_SHIFT
* Returns:
* gpr2 = prev
*/
- .globl __switch_to
-__switch_to:
+ENTRY(__switch_to)
basr %r1,0
0: l %r4,__THREAD_info(%r2) # get thread_info of prev
l %r5,__THREAD_info(%r3) # get thread_info of next
@@ -224,8 +223,7 @@ __critical_start:
* are executed with interrupts enabled.
*/
- .globl system_call
-system_call:
+ENTRY(system_call)
stpt __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
@@ -388,8 +386,7 @@ sysc_tracenogo:
#
# a new process exits the kernel with ret_from_fork
#
- .globl ret_from_fork
-ret_from_fork:
+ENTRY(ret_from_fork)
l %r13,__LC_SVC_NEW_PSW+4
l %r12,__LC_THREAD_INFO # load pointer to thread_info struct
tm SP_PSW+1(%r15),0x01 # forking a kernel thread ?
@@ -405,8 +402,7 @@ ret_from_fork:
# kernel_execve function needs to deal with pt_regs that is not
# at the usual place
#
- .globl kernel_execve
-kernel_execve:
+ENTRY(kernel_execve)
stm %r12,%r15,48(%r15)
lr %r14,%r15
l %r13,__LC_SVC_NEW_PSW+4
@@ -438,8 +434,7 @@ kernel_execve:
* Program check handler routine
*/
- .globl pgm_check_handler
-pgm_check_handler:
+ENTRY(pgm_check_handler)
/*
* First we need to check for a special case:
* Single stepping an instruction that disables the PER event mask will
@@ -565,8 +560,7 @@ kernel_per:
* IO interrupt handler routine
*/
- .globl io_int_handler
-io_int_handler:
+ENTRY(io_int_handler)
stck __LC_INT_CLOCK
stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
@@ -703,8 +697,7 @@ io_notify_resume:
* External interrupt handler routine
*/
- .globl ext_int_handler
-ext_int_handler:
+ENTRY(ext_int_handler)
stck __LC_INT_CLOCK
stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
@@ -731,8 +724,7 @@ __critical_end:
* Machine check handler routines
*/
- .globl mcck_int_handler
-mcck_int_handler:
+ENTRY(mcck_int_handler)
stck __LC_MCCK_CLOCK
spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
@@ -818,8 +810,7 @@ mcck_return:
*/
#ifdef CONFIG_SMP
__CPUINIT
- .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
basr %r1,0
restart_base:
spt restart_vtime-restart_base(%r1)
@@ -848,8 +839,7 @@ restart_vtime:
/*
* If we do not run with SMP enabled, let the new CPU crash ...
*/
- .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
basr %r1,0
restart_base:
lpsw restart_crash-restart_base(%r1)
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 17a6f83a2d67..66729eb7bbc5 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -5,10 +5,9 @@
#include <linux/signal.h>
#include <asm/ptrace.h>
-typedef void pgm_check_handler_t(struct pt_regs *, long, unsigned long);
-extern pgm_check_handler_t *pgm_check_table[128];
-pgm_check_handler_t do_protection_exception;
-pgm_check_handler_t do_dat_exception;
+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;
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d61967e2eab0..7a0fd426ca92 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -9,8 +9,8 @@
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
-#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/linkage.h>
#include <asm/cache.h>
#include <asm/errno.h>
#include <asm/ptrace.h>
@@ -56,15 +56,28 @@ _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_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
#define BASED(name) name-system_call(%r13)
+ .macro SPP newpp
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+ tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP
+ jz .+8
+ .insn s,0xb2800000,\newpp
+#endif
+ .endm
+
.macro HANDLE_SIE_INTERCEPT
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
- lg %r3,__LC_SIE_HOOK
- ltgr %r3,%r3
+ tm __TI_flags+6(%r12),_TIF_SIE>>8
jz 0f
- basr %r14,%r3
+ SPP __LC_CMF_HPP # set host id
+ clc SP_PSW+8(8,%r15),BASED(.Lsie_loop)
+ jl 0f
+ clc SP_PSW+8(8,%r15),BASED(.Lsie_done)
+ jhe 0f
+ mvc SP_PSW+8(8,%r15),BASED(.Lsie_loop)
0:
#endif
.endm
@@ -206,8 +219,7 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
* Returns:
* gpr2 = prev
*/
- .globl __switch_to
-__switch_to:
+ENTRY(__switch_to)
lg %r4,__THREAD_info(%r2) # get thread_info of prev
lg %r5,__THREAD_info(%r3) # get thread_info of next
tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
@@ -232,8 +244,7 @@ __critical_start:
* are executed with interrupts enabled.
*/
- .globl system_call
-system_call:
+ENTRY(system_call)
stpt __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
@@ -395,8 +406,7 @@ sysc_tracenogo:
#
# a new process exits the kernel with ret_from_fork
#
- .globl ret_from_fork
-ret_from_fork:
+ENTRY(ret_from_fork)
lg %r13,__LC_SVC_NEW_PSW+8
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
tm SP_PSW+1(%r15),0x01 # forking a kernel thread ?
@@ -411,8 +421,7 @@ ret_from_fork:
# kernel_execve function needs to deal with pt_regs that is not
# at the usual place
#
- .globl kernel_execve
-kernel_execve:
+ENTRY(kernel_execve)
stmg %r12,%r15,96(%r15)
lgr %r14,%r15
aghi %r15,-SP_SIZE
@@ -442,8 +451,7 @@ kernel_execve:
* Program check handler routine
*/
- .globl pgm_check_handler
-pgm_check_handler:
+ENTRY(pgm_check_handler)
/*
* First we need to check for a special case:
* Single stepping an instruction that disables the PER event mask will
@@ -465,6 +473,7 @@ pgm_check_handler:
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
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz pgm_no_vtime
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -472,7 +481,6 @@ pgm_check_handler:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
LAST_BREAK
pgm_no_vtime:
- HANDLE_SIE_INTERCEPT
stg %r11,SP_ARGS(%r15)
lgf %r3,__LC_PGM_ILC # load program interruption code
lg %r4,__LC_TRANS_EXC_CODE
@@ -507,6 +515,7 @@ pgm_per_std:
CREATE_STACK_FRAME __LC_SAVE_AREA
mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
+ HANDLE_SIE_INTERCEPT
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz pgm_no_vtime2
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -514,7 +523,6 @@ pgm_per_std:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
LAST_BREAK
pgm_no_vtime2:
- HANDLE_SIE_INTERCEPT
lg %r1,__TI_task(%r12)
tm SP_PSW+1(%r15),0x01 # kernel per event ?
jz kernel_per
@@ -571,14 +579,14 @@ kernel_per:
/*
* IO interrupt handler routine
*/
- .globl io_int_handler
-io_int_handler:
+ENTRY(io_int_handler)
stck __LC_INT_CLOCK
stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40
CREATE_STACK_FRAME __LC_SAVE_AREA+40
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
+ HANDLE_SIE_INTERCEPT
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz io_no_vtime
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -586,7 +594,6 @@ io_int_handler:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
LAST_BREAK
io_no_vtime:
- HANDLE_SIE_INTERCEPT
TRACE_IRQS_OFF
la %r2,SP_PTREGS(%r15) # address of register-save area
brasl %r14,do_IRQ # call standard irq handler
@@ -706,14 +713,14 @@ io_notify_resume:
/*
* External interrupt handler routine
*/
- .globl ext_int_handler
-ext_int_handler:
+ENTRY(ext_int_handler)
stck __LC_INT_CLOCK
stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40
CREATE_STACK_FRAME __LC_SAVE_AREA+40
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
+ HANDLE_SIE_INTERCEPT
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz ext_no_vtime
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -721,7 +728,6 @@ ext_int_handler:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
LAST_BREAK
ext_no_vtime:
- HANDLE_SIE_INTERCEPT
TRACE_IRQS_OFF
lghi %r1,4096
la %r2,SP_PTREGS(%r15) # address of register-save area
@@ -736,8 +742,7 @@ __critical_end:
/*
* Machine check handler routines
*/
- .globl mcck_int_handler
-mcck_int_handler:
+ENTRY(mcck_int_handler)
stck __LC_MCCK_CLOCK
la %r1,4095 # revalidate r1
spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
@@ -785,6 +790,7 @@ mcck_int_main:
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
jno mcck_no_vtime # no -> no timer update
+ HANDLE_SIE_INTERCEPT
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz mcck_no_vtime
UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
@@ -804,7 +810,6 @@ mcck_no_vtime:
stosm __SF_EMPTY(%r15),0x04 # turn dat on
tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
jno mcck_return
- HANDLE_SIE_INTERCEPT
TRACE_IRQS_OFF
brasl %r14,s390_handle_mcck
TRACE_IRQS_ON
@@ -823,8 +828,7 @@ mcck_done:
*/
#ifdef CONFIG_SMP
__CPUINIT
- .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
basr %r1,0
restart_base:
spt restart_vtime-restart_base(%r1)
@@ -851,8 +855,7 @@ restart_vtime:
/*
* If we do not run with SMP enabled, let the new CPU crash ...
*/
- .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
basr %r1,0
restart_base:
lpswe restart_crash-restart_base(%r1)
@@ -1036,6 +1039,56 @@ cleanup_io_restore_insn:
.Lcritical_end:
.quad __critical_end
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+/*
+ * sie64a calling convention:
+ * %r2 pointer to sie control block
+ * %r3 guest register save area
+ */
+ENTRY(sie64a)
+ stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
+ stg %r2,__SF_EMPTY(%r15) # save control block pointer
+ stg %r3,__SF_EMPTY+8(%r15) # save guest register save area
+ lmg %r0,%r13,0(%r3) # load guest gprs 0-13
+ lg %r14,__LC_THREAD_INFO # pointer thread_info struct
+ oi __TI_flags+6(%r14),_TIF_SIE>>8
+sie_loop:
+ lg %r14,__LC_THREAD_INFO # pointer thread_info struct
+ tm __TI_flags+7(%r14),_TIF_EXIT_SIE
+ jnz sie_exit
+ lg %r14,__SF_EMPTY(%r15) # get control block pointer
+ SPP __SF_EMPTY(%r15) # set guest id
+ sie 0(%r14)
+sie_done:
+ SPP __LC_CMF_HPP # set host id
+ lg %r14,__LC_THREAD_INFO # pointer thread_info struct
+sie_exit:
+ ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
+ lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
+ stmg %r0,%r13,0(%r14) # save guest gprs 0-13
+ lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
+ lghi %r2,0
+ br %r14
+sie_fault:
+ 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
+ stmg %r0,%r13,0(%r14) # save guest gprs 0-13
+ lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
+ lghi %r2,-EFAULT
+ br %r14
+
+ .align 8
+.Lsie_loop:
+ .quad sie_loop
+.Lsie_done:
+ .quad sie_done
+
+ .section __ex_table,"a"
+ .quad sie_loop,sie_fault
+ .previous
+#endif
+
.section .rodata, "a"
#define SYSCALL(esa,esame,emu) .long esame
.globl sys_call_table
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index fb317bf2c378..2d781bab37bb 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -22,6 +22,7 @@
*/
#include <linux/init.h>
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
@@ -383,8 +384,7 @@ iplstart:
# doesn't need a builtin ipl record.
#
.org 0x800
- .globl start
-start:
+ENTRY(start)
stm %r0,%r15,0x07b0 # store registers
basr %r12,%r0
.base:
@@ -448,8 +448,7 @@ start:
# or linload or SALIPL
#
.org 0x10000
- .globl startup
-startup:
+ENTRY(startup)
basr %r13,0 # get base
.LPG0:
xc 0x200(256),0x200 # partially clear lowcore
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index b8f8dc126102..f21954b44dc1 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -11,13 +11,13 @@
*/
#include <linux/init.h>
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
__HEAD
- .globl startup_continue
-startup_continue:
+ENTRY(startup_continue)
basr %r13,0 # get base
.LPG1:
@@ -45,7 +45,7 @@ startup_continue:
# virtual and never return ...
.align 8
.Lentry:.long 0x00080000,0x80000000 + _stext
-.Lctl: .long 0x04b50002 # cr0: various things
+.Lctl: .long 0x04b50000 # cr0: various things
.long 0 # cr1: primary space segment table
.long .Lduct # cr2: dispatchable unit control table
.long 0 # cr3: instruction authorization
@@ -78,8 +78,7 @@ startup_continue:
.Lbase_cc:
.long sched_clock_base_cc
- .globl _ehead
-_ehead:
+ENTRY(_ehead)
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000 - 0x11000 # head.o ends at 0x11000
@@ -88,8 +87,8 @@ _ehead:
#
# startup-code, running in absolute addressing mode
#
- .globl _stext
-_stext: basr %r13,0 # get base
+ENTRY(_stext)
+ basr %r13,0 # get base
.LPG3:
# check control registers
stctl %c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index cdef68717416..ae5d492b069e 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -11,13 +11,13 @@
*/
#include <linux/init.h>
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
__HEAD
- .globl startup_continue
-startup_continue:
+ENTRY(startup_continue)
larl %r1,sched_clock_base_cc
mvc 0(8,%r1),__LC_LAST_UPDATE_CLOCK
larl %r13,.LPG1 # get base
@@ -46,7 +46,7 @@ startup_continue:
.align 16
.LPG1:
.Lentry:.quad 0x0000000180000000,_stext
-.Lctl: .quad 0x04350002 # cr0: various things
+.Lctl: .quad 0x04040000 # cr0: AFP registers & secondary space
.quad 0 # cr1: primary space segment table
.quad .Lduct # cr2: dispatchable unit control table
.quad 0 # cr3: instruction authorization
@@ -76,8 +76,7 @@ startup_continue:
.long 0x80000000,0,0,0 # invalid access-list entries
.endr
- .globl _ehead
-_ehead:
+ENTRY(_ehead)
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000 - 0x11000 # head.o ends at 0x11000
@@ -86,8 +85,8 @@ _ehead:
#
# startup-code, running in absolute addressing mode
#
- .globl _stext
-_stext: basr %r13,0 # get base
+ENTRY(_stext)
+ basr %r13,0 # get base
.LPG3:
# check control registers
stctg %c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index e3264f6a9720..1f4050d45f78 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -88,15 +88,6 @@ int show_interrupts(struct seq_file *p, void *v)
}
/*
- * For compatibilty only. S/390 specific setup of interrupts et al. is done
- * much later in init_channel_subsystem().
- */
-void __init init_IRQ(void)
-{
- /* nothing... */
-}
-
-/*
* Switch to the asynchronous interrupt stack for softirq execution.
*/
asmlinkage void do_softirq(void)
@@ -144,28 +135,45 @@ void init_irq_proc(void)
#endif
/*
- * ext_int_hash[index] is the start of the list for all external interrupts
- * that hash to this index. With the current set of external interrupts
- * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000
- * iucv and 0x2603 pfault) this is always the first element.
+ * ext_int_hash[index] is the list head for all external interrupts that hash
+ * to this index.
*/
+static struct list_head ext_int_hash[256];
struct ext_int_info {
- struct ext_int_info *next;
ext_int_handler_t handler;
u16 code;
+ struct list_head entry;
+ struct rcu_head rcu;
};
-static struct ext_int_info *ext_int_hash[256];
+/* ext_int_hash_lock protects the handler lists for external interrupts */
+DEFINE_SPINLOCK(ext_int_hash_lock);
+
+static void __init init_external_interrupts(void)
+{
+ int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(ext_int_hash); idx++)
+ INIT_LIST_HEAD(&ext_int_hash[idx]);
+}
static inline int ext_hash(u16 code)
{
return (code + (code >> 9)) & 0xff;
}
+static void ext_int_hash_update(struct rcu_head *head)
+{
+ struct ext_int_info *p = container_of(head, struct ext_int_info, rcu);
+
+ kfree(p);
+}
+
int register_external_interrupt(u16 code, ext_int_handler_t handler)
{
struct ext_int_info *p;
+ unsigned long flags;
int index;
p = kmalloc(sizeof(*p), GFP_ATOMIC);
@@ -174,33 +182,27 @@ int register_external_interrupt(u16 code, ext_int_handler_t handler)
p->code = code;
p->handler = handler;
index = ext_hash(code);
- p->next = ext_int_hash[index];
- ext_int_hash[index] = p;
+
+ spin_lock_irqsave(&ext_int_hash_lock, flags);
+ list_add_rcu(&p->entry, &ext_int_hash[index]);
+ spin_unlock_irqrestore(&ext_int_hash_lock, flags);
return 0;
}
EXPORT_SYMBOL(register_external_interrupt);
int unregister_external_interrupt(u16 code, ext_int_handler_t handler)
{
- struct ext_int_info *p, *q;
- int index;
+ struct ext_int_info *p;
+ unsigned long flags;
+ int index = ext_hash(code);
- index = ext_hash(code);
- q = NULL;
- p = ext_int_hash[index];
- while (p) {
- if (p->code == code && p->handler == handler)
- break;
- q = p;
- p = p->next;
- }
- if (!p)
- return -ENOENT;
- if (q)
- q->next = p->next;
- else
- ext_int_hash[index] = p->next;
- kfree(p);
+ spin_lock_irqsave(&ext_int_hash_lock, flags);
+ list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
+ if (p->code == code && p->handler == handler) {
+ list_del_rcu(&p->entry);
+ call_rcu(&p->rcu, ext_int_hash_update);
+ }
+ spin_unlock_irqrestore(&ext_int_hash_lock, flags);
return 0;
}
EXPORT_SYMBOL(unregister_external_interrupt);
@@ -224,15 +226,22 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
if (code != 0x1004)
__get_cpu_var(s390_idle).nohz_delay = 1;
+
index = ext_hash(code);
- for (p = ext_int_hash[index]; p; p = p->next) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
if (likely(p->code == code))
p->handler(ext_int_code, param32, param64);
- }
+ rcu_read_unlock();
irq_exit();
set_irq_regs(old_regs);
}
+void __init init_IRQ(void)
+{
+ init_external_interrupts();
+}
+
static DEFINE_SPINLOCK(sc_irq_lock);
static int sc_irq_refcount;
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 1e6a55795628..7e2c38ba1373 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -5,21 +5,19 @@
*
*/
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
.section .kprobes.text, "ax"
- .globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
br %r14
- .globl _mcount
-_mcount:
+ENTRY(_mcount)
#ifdef CONFIG_DYNAMIC_FTRACE
br %r14
- .globl ftrace_caller
-ftrace_caller:
+ENTRY(ftrace_caller)
#endif
stm %r2,%r5,16(%r15)
bras %r1,2f
@@ -41,8 +39,7 @@ ftrace_caller:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
l %r2,100(%r15)
l %r3,152(%r15)
- .globl ftrace_graph_caller
-ftrace_graph_caller:
+ENTRY(ftrace_graph_caller)
# The bras instruction gets runtime patched to call prepare_ftrace_return.
# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
# bras %r14,prepare_ftrace_return
@@ -56,8 +53,7 @@ ftrace_graph_caller:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- .globl return_to_handler
-return_to_handler:
+ENTRY(return_to_handler)
stm %r2,%r5,16(%r15)
st %r14,56(%r15)
lr %r0,%r15
diff --git a/arch/s390/kernel/mcount64.S b/arch/s390/kernel/mcount64.S
index e73667286ac0..f70cadec68fc 100644
--- a/arch/s390/kernel/mcount64.S
+++ b/arch/s390/kernel/mcount64.S
@@ -5,21 +5,19 @@
*
*/
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
.section .kprobes.text, "ax"
- .globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
br %r14
- .globl _mcount
-_mcount:
+ENTRY(_mcount)
#ifdef CONFIG_DYNAMIC_FTRACE
br %r14
- .globl ftrace_caller
-ftrace_caller:
+ENTRY(ftrace_caller)
#endif
larl %r1,function_trace_stop
icm %r1,0xf,0(%r1)
@@ -37,8 +35,7 @@ ftrace_caller:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
lg %r2,168(%r15)
lg %r3,272(%r15)
- .globl ftrace_graph_caller
-ftrace_graph_caller:
+ENTRY(ftrace_graph_caller)
# The bras instruction gets runtime patched to call prepare_ftrace_return.
# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
# bras %r14,prepare_ftrace_return
@@ -52,8 +49,7 @@ ftrace_graph_caller:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- .globl return_to_handler
-return_to_handler:
+ENTRY(return_to_handler)
stmg %r2,%r5,32(%r15)
lgr %r1,%r15
aghi %r15,-160
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index f7167ee4604c..dfcb3436bad0 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -45,13 +45,6 @@
#define PLT_ENTRY_SIZE 20
#endif /* CONFIG_64BIT */
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc(size);
-}
-
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
@@ -176,15 +169,6 @@ module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
return 0;
}
-int
-apply_relocate(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex,
- unsigned int relsec, struct module *me)
-{
- printk(KERN_ERR "module %s: RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
-
static int
apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
struct module *me)
@@ -409,7 +393,3 @@ int module_finalize(const Elf_Ehdr *hdr,
me->arch.syminfo = NULL;
return 0;
}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index cb899d9f8505..303d961c3bb5 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -6,14 +6,15 @@
* Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
*/
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#
# do_reipl_asm
# Parameter: r2 = schid of reipl device
#
- .globl do_reipl_asm
-do_reipl_asm: basr %r13,0
+ENTRY(do_reipl_asm)
+ basr %r13,0
.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13)
.Lpg1: # do store status of all registers
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index 9eabbc90795d..78eb7cfbd3d1 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -4,6 +4,7 @@
* Denis Joseph Barrow,
*/
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#
@@ -11,8 +12,8 @@
# Parameter: r2 = schid of reipl device
#
- .globl do_reipl_asm
-do_reipl_asm: basr %r13,0
+ENTRY(do_reipl_asm)
+ basr %r13,0
.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13)
.Lpg1: # do store status of all registers
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
index 3b456b80bcee..c91d70aede91 100644
--- a/arch/s390/kernel/relocate_kernel.S
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -8,6 +8,8 @@
*
*/
+#include <linux/linkage.h>
+
/*
* moves the new kernel to its destination...
* %r2 = pointer to first kimage_entry_t
@@ -22,8 +24,7 @@
*/
.text
- .globl relocate_kernel
- relocate_kernel:
+ENTRY(relocate_kernel)
basr %r13,0 # base address
.base:
stnsm sys_msk-.base(%r13),0xfb # disable DAT
@@ -112,6 +113,7 @@
.byte 0
.align 8
relocate_kernel_end:
+ .align 8
.globl relocate_kernel_len
relocate_kernel_len:
.quad relocate_kernel_end - relocate_kernel
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
index 1f9ea2067b59..7c3ce589a7f0 100644
--- a/arch/s390/kernel/relocate_kernel64.S
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -8,6 +8,8 @@
*
*/
+#include <linux/linkage.h>
+
/*
* moves the new kernel to its destination...
* %r2 = pointer to first kimage_entry_t
@@ -23,8 +25,7 @@
*/
.text
- .globl relocate_kernel
- relocate_kernel:
+ENTRY(relocate_kernel)
basr %r13,0 # base address
.base:
stnsm sys_msk-.base(%r13),0xfb # disable DAT
@@ -115,6 +116,7 @@
.byte 0
.align 8
relocate_kernel_end:
+ .align 8
.globl relocate_kernel_len
relocate_kernel_len:
.quad relocate_kernel_end - relocate_kernel
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 656fcbb9bd83..57b536649b00 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -1,6 +1,10 @@
#include <linux/module.h>
+#include <linux/kvm_host.h>
#include <asm/ftrace.h>
#ifdef CONFIG_FUNCTION_TRACER
EXPORT_SYMBOL(_mcount);
#endif
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+EXPORT_SYMBOL(sie64a);
+#endif
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
index 2e82fdd89320..95792d846bb6 100644
--- a/arch/s390/kernel/sclp.S
+++ b/arch/s390/kernel/sclp.S
@@ -8,6 +8,8 @@
*
*/
+#include <linux/linkage.h>
+
LC_EXT_NEW_PSW = 0x58 # addr of ext int handler
LC_EXT_NEW_PSW_64 = 0x1b0 # addr of ext int handler 64 bit
LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter
@@ -260,8 +262,7 @@ _sclp_print:
# R2 = 0 on success, 1 on failure
#
- .globl _sclp_print_early
-_sclp_print_early:
+ENTRY(_sclp_print_early)
stm %r6,%r15,24(%r15) # save registers
ahi %r15,-96 # create stack frame
#ifdef CONFIG_64BIT
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 1d55c95f617c..a6d85c0a7f20 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -654,7 +654,8 @@ int __cpu_disable(void)
/* disable all external interrupts */
cr_parms.orvals[0] = 0;
cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 11 |
- 1 << 10 | 1 << 9 | 1 << 6 | 1 << 4);
+ 1 << 10 | 1 << 9 | 1 << 6 | 1 << 5 |
+ 1 << 4);
/* disable all I/O interrupts */
cr_parms.orvals[6] = 0;
cr_parms.andvals[6] = ~(1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 |
diff --git a/arch/s390/kernel/switch_cpu.S b/arch/s390/kernel/switch_cpu.S
index 20530dd2eab1..bfe070bc7659 100644
--- a/arch/s390/kernel/switch_cpu.S
+++ b/arch/s390/kernel/switch_cpu.S
@@ -5,6 +5,7 @@
*
*/
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
@@ -16,9 +17,7 @@
# %r6 - destination cpu
.section .text
- .align 4
- .globl smp_switch_to_cpu
-smp_switch_to_cpu:
+ENTRY(smp_switch_to_cpu)
stm %r6,%r15,__SF_GPRS(%r15)
lr %r1,%r15
ahi %r15,-STACK_FRAME_OVERHEAD
@@ -33,8 +32,7 @@ smp_switch_to_cpu:
brc 2,2b /* busy, try again */
3: j 3b
- .globl smp_restart_cpu
-smp_restart_cpu:
+ENTRY(smp_restart_cpu)
basr %r13,0
0: la %r1,.gprregs_addr-0b(%r13)
l %r1,0(%r1)
diff --git a/arch/s390/kernel/switch_cpu64.S b/arch/s390/kernel/switch_cpu64.S
index 5be3f43898f9..fcc42d799e41 100644
--- a/arch/s390/kernel/switch_cpu64.S
+++ b/arch/s390/kernel/switch_cpu64.S
@@ -5,6 +5,7 @@
*
*/
+#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
@@ -16,9 +17,7 @@
# %r6 - destination cpu
.section .text
- .align 4
- .globl smp_switch_to_cpu
-smp_switch_to_cpu:
+ENTRY(smp_switch_to_cpu)
stmg %r6,%r15,__SF_GPRS(%r15)
lgr %r1,%r15
aghi %r15,-STACK_FRAME_OVERHEAD
@@ -31,8 +30,7 @@ smp_switch_to_cpu:
brc 2,2b /* busy, try again */
3: j 3b
- .globl smp_restart_cpu
-smp_restart_cpu:
+ENTRY(smp_restart_cpu)
larl %r1,.gprregs
lmg %r0,%r15,0(%r1)
1: sigp %r0,%r5,__SIGP_SENSE /* Wait for calling CPU */
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index 1f066e46e83e..51bcdb50a230 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -7,6 +7,7 @@
* Michael Holzheu <holzheu@linux.vnet.ibm.com>
*/
+#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
@@ -22,9 +23,7 @@
* This function runs with disabled interrupts.
*/
.section .text
- .align 4
- .globl swsusp_arch_suspend
-swsusp_arch_suspend:
+ENTRY(swsusp_arch_suspend)
stmg %r6,%r15,__SF_GPRS(%r15)
lgr %r1,%r15
aghi %r15,-STACK_FRAME_OVERHEAD
@@ -112,8 +111,7 @@ swsusp_arch_suspend:
* Then we return to the function that called swsusp_arch_suspend().
* swsusp_arch_resume() runs with disabled interrupts.
*/
- .globl swsusp_arch_resume
-swsusp_arch_resume:
+ENTRY(swsusp_arch_resume)
stmg %r6,%r15,__SF_GPRS(%r15)
lgr %r1,%r15
aghi %r15,-STACK_FRAME_OVERHEAD
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index a65d2e82f61d..ffabcd9d3363 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -18,7 +18,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
-#include <linux/tracehook.h>
+#include <linux/ptrace.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -36,21 +36,17 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/mathemu.h>
#include <asm/cpcmd.h>
#include <asm/lowcore.h>
#include <asm/debug.h>
#include "entry.h"
-pgm_check_handler_t *pgm_check_table[128];
+void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long);
int show_unhandled_signals;
-extern pgm_check_handler_t do_protection_exception;
-extern pgm_check_handler_t do_dat_exception;
-extern pgm_check_handler_t do_asce_exception;
-
#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
#ifndef CONFIG_64BIT
@@ -329,10 +325,17 @@ static inline void __user *get_psw_address(struct pt_regs *regs,
void __kprobes do_per_trap(struct pt_regs *regs)
{
+ siginfo_t info;
+
if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
return;
- if (tracehook_consider_fatal_signal(current, SIGTRAP))
- force_sig(SIGTRAP, current);
+ if (!current->ptrace)
+ return;
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_HWBKPT;
+ info.si_addr = (void *) current->thread.per_event.address;
+ force_sig_info(SIGTRAP, &info, current);
}
static void default_trap_handler(struct pt_regs *regs, long pgm_int_code,
@@ -425,9 +428,13 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
return;
if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
- if (tracehook_consider_fatal_signal(current, SIGTRAP))
- force_sig(SIGTRAP, current);
- else
+ if (current->ptrace) {
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+ info.si_addr = location;
+ force_sig_info(SIGTRAP, &info, current);
+ } else
signal = SIGILL;
#ifdef CONFIG_MATHEMU
} else if (opcode[0] == 0xb3) {
@@ -489,9 +496,8 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
#ifdef CONFIG_MATHEMU
-asmlinkage void specification_exception(struct pt_regs *regs,
- long pgm_int_code,
- unsigned long trans_exc_code)
+void specification_exception(struct pt_regs *regs, long pgm_int_code,
+ unsigned long trans_exc_code)
{
__u8 opcode[6];
__u16 __user *location = NULL;
@@ -648,7 +654,7 @@ static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
}
-asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs)
+void __kprobes kernel_stack_overflow(struct pt_regs * regs)
{
bust_spinlocks(1);
printk("Kernel stack overflow.\n");
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index f66a1bdbb61d..a21634173a66 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -37,6 +37,5 @@ config KVM
# OK, it's a little counter-intuitive to do this, but it puts it neatly under
# the virtualization menu.
source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
endif # VIRTUALIZATION
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index 860d26514c08..3975722bb19d 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -10,5 +10,5 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
-kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
+kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o diag.o
obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
index 03c716a0f01f..c86f6ae43f76 100644
--- a/arch/s390/kvm/gaccess.h
+++ b/arch/s390/kvm/gaccess.h
@@ -1,5 +1,5 @@
/*
- * gaccess.h - access guest memory
+ * access.h - access guest memory
*
* Copyright IBM Corp. 2008,2009
*
@@ -22,20 +22,13 @@ static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
unsigned long guestaddr)
{
unsigned long prefix = vcpu->arch.sie_block->prefix;
- unsigned long origin = vcpu->arch.sie_block->gmsor;
- unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
if (guestaddr < 2 * PAGE_SIZE)
guestaddr += prefix;
else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
guestaddr -= prefix;
- if (guestaddr > memsize)
- return (void __user __force *) ERR_PTR(-EFAULT);
-
- guestaddr += origin;
-
- return (void __user *) guestaddr;
+ return (void __user *) gmap_fault(guestaddr, vcpu->arch.gmap);
}
static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
@@ -141,11 +134,11 @@ static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
unsigned long guestdest,
- const void *from, unsigned long n)
+ void *from, unsigned long n)
{
int rc;
unsigned long i;
- const u8 *data = from;
+ u8 *data = from;
for (i = 0; i < n; i++) {
rc = put_guest_u8(vcpu, guestdest++, *(data++));
@@ -155,12 +148,95 @@ static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
return 0;
}
+static inline int __copy_to_guest_fast(struct kvm_vcpu *vcpu,
+ unsigned long guestdest,
+ void *from, unsigned long n)
+{
+ int r;
+ void __user *uptr;
+ unsigned long size;
+
+ if (guestdest + n < guestdest)
+ return -EFAULT;
+
+ /* simple case: all within one segment table entry? */
+ if ((guestdest & PMD_MASK) == ((guestdest+n) & PMD_MASK)) {
+ uptr = (void __user *) gmap_fault(guestdest, vcpu->arch.gmap);
+
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
+
+ r = copy_to_user(uptr, from, n);
+
+ if (r)
+ r = -EFAULT;
+
+ goto out;
+ }
+
+ /* copy first segment */
+ uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
+
+ size = PMD_SIZE - (guestdest & ~PMD_MASK);
+
+ r = copy_to_user(uptr, from, size);
+
+ if (r) {
+ r = -EFAULT;
+ goto out;
+ }
+ from += size;
+ n -= size;
+ guestdest += size;
+
+ /* copy full segments */
+ while (n >= PMD_SIZE) {
+ uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
+
+ r = copy_to_user(uptr, from, PMD_SIZE);
+
+ if (r) {
+ r = -EFAULT;
+ goto out;
+ }
+ from += PMD_SIZE;
+ n -= PMD_SIZE;
+ guestdest += PMD_SIZE;
+ }
+
+ /* copy the tail segment */
+ if (n) {
+ uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
+
+ r = copy_to_user(uptr, from, n);
+
+ if (r)
+ r = -EFAULT;
+ }
+out:
+ return r;
+}
+
+static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
+ unsigned long guestdest,
+ void *from, unsigned long n)
+{
+ return __copy_to_guest_fast(vcpu, guestdest, from, n);
+}
+
static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
- const void *from, unsigned long n)
+ void *from, unsigned long n)
{
unsigned long prefix = vcpu->arch.sie_block->prefix;
- unsigned long origin = vcpu->arch.sie_block->gmsor;
- unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
goto slowpath;
@@ -177,15 +253,7 @@ static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
guestdest -= prefix;
- if (guestdest + n > memsize)
- return -EFAULT;
-
- if (guestdest + n < guestdest)
- return -EFAULT;
-
- guestdest += origin;
-
- return copy_to_user((void __user *) guestdest, from, n);
+ return __copy_to_guest_fast(vcpu, guestdest, from, n);
slowpath:
return __copy_to_guest_slow(vcpu, guestdest, from, n);
}
@@ -206,74 +274,113 @@ static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
return 0;
}
-static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
- unsigned long guestsrc, unsigned long n)
+static inline int __copy_from_guest_fast(struct kvm_vcpu *vcpu, void *to,
+ unsigned long guestsrc,
+ unsigned long n)
{
- unsigned long prefix = vcpu->arch.sie_block->prefix;
- unsigned long origin = vcpu->arch.sie_block->gmsor;
- unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+ int r;
+ void __user *uptr;
+ unsigned long size;
- if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
- goto slowpath;
+ if (guestsrc + n < guestsrc)
+ return -EFAULT;
- if ((guestsrc < prefix) && (guestsrc + n > prefix))
- goto slowpath;
+ /* simple case: all within one segment table entry? */
+ if ((guestsrc & PMD_MASK) == ((guestsrc+n) & PMD_MASK)) {
+ uptr = (void __user *) gmap_fault(guestsrc, vcpu->arch.gmap);
- if ((guestsrc < prefix + 2 * PAGE_SIZE)
- && (guestsrc + n > prefix + 2 * PAGE_SIZE))
- goto slowpath;
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
- if (guestsrc < 2 * PAGE_SIZE)
- guestsrc += prefix;
- else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
- guestsrc -= prefix;
+ r = copy_from_user(to, uptr, n);
- if (guestsrc + n > memsize)
- return -EFAULT;
+ if (r)
+ r = -EFAULT;
- if (guestsrc + n < guestsrc)
- return -EFAULT;
+ goto out;
+ }
- guestsrc += origin;
+ /* copy first segment */
+ uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
- return copy_from_user(to, (void __user *) guestsrc, n);
-slowpath:
- return __copy_from_guest_slow(vcpu, to, guestsrc, n);
-}
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
-static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
- unsigned long guestdest,
- const void *from, unsigned long n)
-{
- unsigned long origin = vcpu->arch.sie_block->gmsor;
- unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+ size = PMD_SIZE - (guestsrc & ~PMD_MASK);
- if (guestdest + n > memsize)
- return -EFAULT;
+ r = copy_from_user(to, uptr, size);
- if (guestdest + n < guestdest)
- return -EFAULT;
+ if (r) {
+ r = -EFAULT;
+ goto out;
+ }
+ to += size;
+ n -= size;
+ guestsrc += size;
+
+ /* copy full segments */
+ while (n >= PMD_SIZE) {
+ uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
+
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
+
+ r = copy_from_user(to, uptr, PMD_SIZE);
+
+ if (r) {
+ r = -EFAULT;
+ goto out;
+ }
+ to += PMD_SIZE;
+ n -= PMD_SIZE;
+ guestsrc += PMD_SIZE;
+ }
+
+ /* copy the tail segment */
+ if (n) {
+ uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
- guestdest += origin;
+ if (IS_ERR((void __force *) uptr))
+ return PTR_ERR((void __force *) uptr);
- return copy_to_user((void __user *) guestdest, from, n);
+ r = copy_from_user(to, uptr, n);
+
+ if (r)
+ r = -EFAULT;
+ }
+out:
+ return r;
}
static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
unsigned long guestsrc,
unsigned long n)
{
- unsigned long origin = vcpu->arch.sie_block->gmsor;
- unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+ return __copy_from_guest_fast(vcpu, to, guestsrc, n);
+}
- if (guestsrc + n > memsize)
- return -EFAULT;
+static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
+ unsigned long guestsrc, unsigned long n)
+{
+ unsigned long prefix = vcpu->arch.sie_block->prefix;
- if (guestsrc + n < guestsrc)
- return -EFAULT;
+ if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
+ goto slowpath;
- guestsrc += origin;
+ if ((guestsrc < prefix) && (guestsrc + n > prefix))
+ goto slowpath;
+
+ if ((guestsrc < prefix + 2 * PAGE_SIZE)
+ && (guestsrc + n > prefix + 2 * PAGE_SIZE))
+ goto slowpath;
+
+ if (guestsrc < 2 * PAGE_SIZE)
+ guestsrc += prefix;
+ else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
+ guestsrc -= prefix;
- return copy_from_user(to, (void __user *) guestsrc, n);
+ return __copy_from_guest_fast(vcpu, to, guestsrc, n);
+slowpath:
+ return __copy_from_guest_slow(vcpu, to, guestsrc, n);
}
#endif
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index f7b6df45d8be..c7c51898984e 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -105,6 +105,7 @@ static intercept_handler_t instruction_handlers[256] = {
[0xae] = kvm_s390_handle_sigp,
[0xb2] = kvm_s390_handle_b2,
[0xb7] = handle_lctl,
+ [0xe5] = kvm_s390_handle_e5,
[0xeb] = handle_lctlg,
};
@@ -159,22 +160,42 @@ static int handle_stop(struct kvm_vcpu *vcpu)
static int handle_validity(struct kvm_vcpu *vcpu)
{
+ unsigned long vmaddr;
int viwhy = vcpu->arch.sie_block->ipb >> 16;
int rc;
vcpu->stat.exit_validity++;
- if ((viwhy == 0x37) && (vcpu->arch.sie_block->prefix
- <= kvm_s390_vcpu_get_memsize(vcpu) - 2*PAGE_SIZE)) {
- rc = fault_in_pages_writeable((char __user *)
- vcpu->arch.sie_block->gmsor +
- vcpu->arch.sie_block->prefix,
- 2*PAGE_SIZE);
- if (rc)
+ if (viwhy == 0x37) {
+ vmaddr = gmap_fault(vcpu->arch.sie_block->prefix,
+ vcpu->arch.gmap);
+ if (IS_ERR_VALUE(vmaddr)) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ rc = fault_in_pages_writeable((char __user *) vmaddr,
+ PAGE_SIZE);
+ if (rc) {
+ /* user will receive sigsegv, exit to user */
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ vmaddr = gmap_fault(vcpu->arch.sie_block->prefix + PAGE_SIZE,
+ vcpu->arch.gmap);
+ if (IS_ERR_VALUE(vmaddr)) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ rc = fault_in_pages_writeable((char __user *) vmaddr,
+ PAGE_SIZE);
+ if (rc) {
/* user will receive sigsegv, exit to user */
rc = -EOPNOTSUPP;
+ goto out;
+ }
} else
rc = -EOPNOTSUPP;
+out:
if (rc)
VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
viwhy);
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 35c21bf910c5..c9aeb4b4d0b8 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -128,6 +128,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
if (rc == -EFAULT)
exception = 1;
+ rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->emerg.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)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 67345ae7ce8d..f17296e4fc89 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -62,6 +62,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "instruction_chsc", VCPU_STAT(instruction_chsc) },
{ "instruction_stsi", VCPU_STAT(instruction_stsi) },
{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
+ { "instruction_tprot", VCPU_STAT(instruction_tprot) },
{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
{ "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
{ "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
@@ -189,7 +190,13 @@ int kvm_arch_init_vm(struct kvm *kvm)
debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
VM_EVENT(kvm, 3, "%s", "vm created");
+ kvm->arch.gmap = gmap_alloc(current->mm);
+ if (!kvm->arch.gmap)
+ goto out_nogmap;
+
return 0;
+out_nogmap:
+ debug_unregister(kvm->arch.dbf);
out_nodbf:
free_page((unsigned long)(kvm->arch.sca));
out_err:
@@ -234,11 +241,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
kvm_free_vcpus(kvm);
free_page((unsigned long)(kvm->arch.sca));
debug_unregister(kvm->arch.dbf);
+ gmap_free(kvm->arch.gmap);
}
/* Section: vcpu related */
int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
{
+ vcpu->arch.gmap = vcpu->kvm->arch.gmap;
return 0;
}
@@ -284,8 +293,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
- atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
- set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests);
+ atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
vcpu->arch.sie_block->ecb = 6;
vcpu->arch.sie_block->eca = 0xC1002001U;
vcpu->arch.sie_block->fac = (int) (long) facilities;
@@ -453,6 +461,7 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
local_irq_disable();
kvm_guest_enter();
local_irq_enable();
+ gmap_enable(vcpu->arch.gmap);
VCPU_EVENT(vcpu, 6, "entering sie flags %x",
atomic_read(&vcpu->arch.sie_block->cpuflags));
if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
@@ -461,6 +470,7 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
}
VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
vcpu->arch.sie_block->icptcode);
+ gmap_disable(vcpu->arch.gmap);
local_irq_disable();
kvm_guest_exit();
local_irq_enable();
@@ -474,17 +484,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
sigset_t sigsaved;
rerun_vcpu:
- if (vcpu->requests)
- if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
- kvm_s390_vcpu_set_mem(vcpu);
-
- /* verify, that memory has been registered */
- if (!vcpu->arch.sie_block->gmslm) {
- vcpu_put(vcpu);
- VCPU_EVENT(vcpu, 3, "%s", "no memory registered to run vcpu");
- return -EINVAL;
- }
-
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
@@ -545,7 +544,7 @@ rerun_vcpu:
return rc;
}
-static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
+static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from,
unsigned long n, int prefix)
{
if (prefix)
@@ -562,7 +561,7 @@ static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
*/
int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
{
- const unsigned char archmode = 1;
+ unsigned char archmode = 1;
int prefix;
if (addr == KVM_S390_STORE_STATUS_NOADDR) {
@@ -680,10 +679,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
if (mem->guest_phys_addr)
return -EINVAL;
- if (mem->userspace_addr & (PAGE_SIZE - 1))
+ if (mem->userspace_addr & 0xffffful)
return -EINVAL;
- if (mem->memory_size & (PAGE_SIZE - 1))
+ if (mem->memory_size & 0xffffful)
return -EINVAL;
if (!user_alloc)
@@ -697,15 +696,14 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
struct kvm_memory_slot old,
int user_alloc)
{
- int i;
- struct kvm_vcpu *vcpu;
+ int rc;
- /* request update of sie control block for all available vcpus */
- kvm_for_each_vcpu(i, vcpu, kvm) {
- if (test_and_set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
- continue;
- kvm_s390_inject_sigp_stop(vcpu, ACTION_RELOADVCPU_ON_STOP);
- }
+
+ rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
+ mem->guest_phys_addr, mem->memory_size);
+ if (rc)
+ printk(KERN_WARNING "kvm-s390: failed to commit memory region\n");
+ return;
}
void kvm_arch_flush_shadow(struct kvm *kvm)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index a7b7586626db..99b0b7597115 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -58,35 +58,9 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action);
-static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.sie_block->gmslm
- - vcpu->arch.sie_block->gmsor
- - VIRTIODESCSPACE + 1ul;
-}
-
-static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu)
-{
- int idx;
- struct kvm_memory_slot *mem;
- struct kvm_memslots *memslots;
-
- idx = srcu_read_lock(&vcpu->kvm->srcu);
- memslots = kvm_memslots(vcpu->kvm);
-
- mem = &memslots->memslots[0];
-
- vcpu->arch.sie_block->gmsor = mem->userspace_addr;
- vcpu->arch.sie_block->gmslm =
- mem->userspace_addr +
- (mem->npages << PAGE_SHIFT) +
- VIRTIODESCSPACE - 1ul;
-
- srcu_read_unlock(&vcpu->kvm->srcu, idx);
-}
-
/* implemented in priv.c */
int kvm_s390_handle_b2(struct kvm_vcpu *vcpu);
+int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
/* implemented in sigp.c */
int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 73c47bd95db3..391626361084 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -326,3 +326,52 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
}
return -EOPNOTSUPP;
}
+
+static int handle_tprot(struct kvm_vcpu *vcpu)
+{
+ int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
+ int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
+ int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
+ int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
+ u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
+ u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
+ struct vm_area_struct *vma;
+
+ vcpu->stat.instruction_tprot++;
+
+ /* we only handle the Linux memory detection case:
+ * access key == 0
+ * guest DAT == off
+ * everything else goes to userspace. */
+ if (address2 & 0xf0)
+ return -EOPNOTSUPP;
+ if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
+ return -EOPNOTSUPP;
+
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm,
+ (unsigned long) __guestaddr_to_user(vcpu, address1));
+ if (!vma) {
+ up_read(&current->mm->mmap_sem);
+ return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+ }
+
+ vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+ if (!(vma->vm_flags & VM_WRITE) && (vma->vm_flags & VM_READ))
+ vcpu->arch.sie_block->gpsw.mask |= (1ul << 44);
+ if (!(vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_READ))
+ vcpu->arch.sie_block->gpsw.mask |= (2ul << 44);
+
+ up_read(&current->mm->mmap_sem);
+ return 0;
+}
+
+int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)
+{
+ /* For e5xx... instructions we only handle TPROT */
+ if ((vcpu->arch.sie_block->ipa & 0x00ff) == 0x01)
+ return handle_tprot(vcpu);
+ return -EOPNOTSUPP;
+}
+
diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S
deleted file mode 100644
index 5faa1b1b23fa..000000000000
--- a/arch/s390/kvm/sie64a.S
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * sie64a.S - low level sie call
- *
- * Copyright IBM Corp. 2008,2010
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (version 2 only)
- * as published by the Free Software Foundation.
- *
- * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- */
-
-#include <linux/errno.h>
-#include <asm/asm-offsets.h>
-#include <asm/setup.h>
-#include <asm/asm-offsets.h>
-#include <asm/ptrace.h>
-#include <asm/thread_info.h>
-
-_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
-
-/*
- * offsets into stackframe
- * SP_ = offsets into stack sie64 is called with
- * SPI_ = offsets into irq stack
- */
-SP_GREGS = __SF_EMPTY
-SP_HOOK = __SF_EMPTY+8
-SP_GPP = __SF_EMPTY+16
-SPI_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
-
-
- .macro SPP newpp
- tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP
- jz 0f
- .insn s,0xb2800000,\newpp
-0:
- .endm
-
-sie_irq_handler:
- SPP __LC_CMF_HPP # set host id
- larl %r2,sie_inst
- clg %r2,SPI_PSW+8(0,%r15) # intercepted sie
- jne 1f
- xc __LC_SIE_HOOK(8),__LC_SIE_HOOK
- lg %r2,__LC_THREAD_INFO # pointer thread_info struct
- tm __TI_flags+7(%r2),_TIF_EXIT_SIE
- jz 0f
- larl %r2,sie_exit # work pending, leave sie
- stg %r2,SPI_PSW+8(0,%r15)
- br %r14
-0: larl %r2,sie_reenter # re-enter with guest id
- stg %r2,SPI_PSW+8(0,%r15)
-1: br %r14
-
-/*
- * sie64a calling convention:
- * %r2 pointer to sie control block
- * %r3 guest register save area
- */
- .globl sie64a
-sie64a:
- stg %r3,SP_GREGS(%r15) # save guest register save area
- stmg %r6,%r14,__SF_GPRS(%r15) # save registers on entry
- lgr %r14,%r2 # pointer to sie control block
- larl %r5,sie_irq_handler
- stg %r2,SP_GPP(%r15)
- stg %r5,SP_HOOK(%r15) # save hook target
- lmg %r0,%r13,0(%r3) # load guest gprs 0-13
-sie_reenter:
- mvc __LC_SIE_HOOK(8),SP_HOOK(%r15)
- SPP SP_GPP(%r15) # set guest id
-sie_inst:
- sie 0(%r14)
- xc __LC_SIE_HOOK(8),__LC_SIE_HOOK
- SPP __LC_CMF_HPP # set host id
-sie_exit:
- lg %r14,SP_GREGS(%r15)
- stmg %r0,%r13,0(%r14) # save guest gprs 0-13
- lghi %r2,0
- lmg %r6,%r14,__SF_GPRS(%r15)
- br %r14
-
-sie_err:
- xc __LC_SIE_HOOK(8),__LC_SIE_HOOK
- SPP __LC_CMF_HPP # set host id
- lg %r14,SP_GREGS(%r15)
- stmg %r0,%r13,0(%r14) # save guest gprs 0-13
- lghi %r2,-EFAULT
- lmg %r6,%r14,__SF_GPRS(%r15)
- br %r14
-
- .section __ex_table,"a"
- .quad sie_inst,sie_err
- .quad sie_exit,sie_err
- .quad sie_reenter,sie_err
- .previous
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 702276f5e2fa..d6a50c1fb2e6 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -189,10 +189,8 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
/* make sure that the new value is valid memory */
address = address & 0x7fffe000u;
- if ((copy_from_user(&tmp, (void __user *)
- (address + vcpu->arch.sie_block->gmsor) , 1)) ||
- (copy_from_user(&tmp, (void __user *)(address +
- vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) {
+ if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
+ copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) {
*reg |= SIGP_STAT_INVALID_PARAMETER;
return 1; /* invalid parameter */
}
diff --git a/arch/s390/lib/qrnnd.S b/arch/s390/lib/qrnnd.S
index eb1df632e749..d321329130ec 100644
--- a/arch/s390/lib/qrnnd.S
+++ b/arch/s390/lib/qrnnd.S
@@ -1,5 +1,7 @@
# S/390 __udiv_qrnnd
+#include <linux/linkage.h>
+
# r2 : &__r
# r3 : upper half of 64 bit word n
# r4 : lower half of 64 bit word n
@@ -8,8 +10,7 @@
# the quotient q is to be returned
.text
- .globl __udiv_qrnnd
-__udiv_qrnnd:
+ENTRY(__udiv_qrnnd)
st %r2,24(%r15) # store pointer to reminder for later
lr %r0,%r3 # reload n
lr %r1,%r4
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index fe103e891e7a..9564fc779b27 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -299,13 +299,28 @@ static inline int do_exception(struct pt_regs *regs, int access,
goto out;
address = trans_exc_code & __FAIL_ADDR_MASK;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
flags = FAULT_FLAG_ALLOW_RETRY;
if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
flags |= FAULT_FLAG_WRITE;
-retry:
down_read(&mm->mmap_sem);
+#ifdef CONFIG_PGSTE
+ if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
+ address = gmap_fault(address,
+ (struct gmap *) S390_lowcore.gmap);
+ if (address == -EFAULT) {
+ fault = VM_FAULT_BADMAP;
+ goto out_up;
+ }
+ if (address == -ENOMEM) {
+ fault = VM_FAULT_OOM;
+ goto out_up;
+ }
+ }
+#endif
+
+retry:
fault = VM_FAULT_BADMAP;
vma = find_vma(mm, address);
if (!vma)
@@ -345,17 +360,18 @@ retry:
if (flags & FAULT_FLAG_ALLOW_RETRY) {
if (fault & VM_FAULT_MAJOR) {
tsk->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
regs, address);
} else {
tsk->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
regs, address);
}
if (fault & VM_FAULT_RETRY) {
/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
* of starvation. */
flags &= ~FAULT_FLAG_ALLOW_RETRY;
+ down_read(&mm->mmap_sem);
goto retry;
}
}
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index a4d856db9154..597bb2d27c3c 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -35,7 +35,7 @@ int arch_prepare_hugepage(struct page *page)
if (MACHINE_HAS_HPAGE)
return 0;
- ptep = (pte_t *) pte_alloc_one(&init_mm, address);
+ ptep = (pte_t *) pte_alloc_one(&init_mm, addr);
if (!ptep)
return -ENOMEM;
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 37a23c223705..2adb23938a7f 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/quicklist.h>
#include <linux/rcupdate.h>
+#include <linux/slab.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -133,30 +134,374 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
}
#endif
-static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+#ifdef CONFIG_PGSTE
+
+/**
+ * gmap_alloc - allocate a guest address space
+ * @mm: pointer to the parent mm_struct
+ *
+ * Returns a guest address space structure.
+ */
+struct gmap *gmap_alloc(struct mm_struct *mm)
{
- unsigned int old, new;
+ struct gmap *gmap;
+ struct page *page;
+ unsigned long *table;
- do {
- old = atomic_read(v);
- new = old ^ bits;
- } while (atomic_cmpxchg(v, old, new) != old);
- return new;
+ gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL);
+ if (!gmap)
+ goto out;
+ INIT_LIST_HEAD(&gmap->crst_list);
+ gmap->mm = mm;
+ page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+ if (!page)
+ goto out_free;
+ list_add(&page->lru, &gmap->crst_list);
+ table = (unsigned long *) page_to_phys(page);
+ crst_table_init(table, _REGION1_ENTRY_EMPTY);
+ gmap->table = table;
+ list_add(&gmap->list, &mm->context.gmap_list);
+ return gmap;
+
+out_free:
+ kfree(gmap);
+out:
+ return NULL;
}
+EXPORT_SYMBOL_GPL(gmap_alloc);
-/*
- * page table entry allocation/free routines.
+static int gmap_unlink_segment(struct gmap *gmap, unsigned long *table)
+{
+ struct gmap_pgtable *mp;
+ struct gmap_rmap *rmap;
+ struct page *page;
+
+ if (*table & _SEGMENT_ENTRY_INV)
+ return 0;
+ page = pfn_to_page(*table >> PAGE_SHIFT);
+ mp = (struct gmap_pgtable *) page->index;
+ list_for_each_entry(rmap, &mp->mapper, list) {
+ if (rmap->entry != table)
+ continue;
+ list_del(&rmap->list);
+ kfree(rmap);
+ break;
+ }
+ *table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+ return 1;
+}
+
+static void gmap_flush_tlb(struct gmap *gmap)
+{
+ if (MACHINE_HAS_IDTE)
+ __tlb_flush_idte((unsigned long) gmap->table |
+ _ASCE_TYPE_REGION1);
+ else
+ __tlb_flush_global();
+}
+
+/**
+ * gmap_free - free a guest address space
+ * @gmap: pointer to the guest address space structure
*/
-#ifdef CONFIG_PGSTE
-static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
+void gmap_free(struct gmap *gmap)
+{
+ struct page *page, *next;
+ unsigned long *table;
+ int i;
+
+
+ /* Flush tlb. */
+ if (MACHINE_HAS_IDTE)
+ __tlb_flush_idte((unsigned long) gmap->table |
+ _ASCE_TYPE_REGION1);
+ else
+ __tlb_flush_global();
+
+ /* Free all segment & region tables. */
+ down_read(&gmap->mm->mmap_sem);
+ 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)
+ /* Remove gmap rmap structures for segment table. */
+ for (i = 0; i < PTRS_PER_PMD; i++, table++)
+ gmap_unlink_segment(gmap, table);
+ __free_pages(page, ALLOC_ORDER);
+ }
+ up_read(&gmap->mm->mmap_sem);
+ list_del(&gmap->list);
+ kfree(gmap);
+}
+EXPORT_SYMBOL_GPL(gmap_free);
+
+/**
+ * gmap_enable - switch primary space to the guest address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_enable(struct gmap *gmap)
+{
+ /* Load primary space page table origin. */
+ S390_lowcore.user_asce = _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH |
+ _ASCE_USER_BITS | __pa(gmap->table);
+ asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) );
+ S390_lowcore.gmap = (unsigned long) gmap;
+}
+EXPORT_SYMBOL_GPL(gmap_enable);
+
+/**
+ * gmap_disable - switch back to the standard primary address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_disable(struct gmap *gmap)
+{
+ /* Load primary space page table origin. */
+ S390_lowcore.user_asce =
+ gmap->mm->context.asce_bits | __pa(gmap->mm->pgd);
+ asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) );
+ S390_lowcore.gmap = 0UL;
+}
+EXPORT_SYMBOL_GPL(gmap_disable);
+
+static int gmap_alloc_table(struct gmap *gmap,
+ unsigned long *table, unsigned long init)
+{
+ struct page *page;
+ unsigned long *new;
+
+ page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+ if (!page)
+ 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;
+}
+
+/**
+ * gmap_unmap_segment - unmap segment from the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @addr: address in the guest address space
+ * @len: length of the memory area to unmap
+ *
+ * Returns 0 if the unmap succeded, -EINVAL if not.
+ */
+int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
+{
+ unsigned long *table;
+ unsigned long off;
+ int flush;
+
+ if ((to | len) & (PMD_SIZE - 1))
+ return -EINVAL;
+ if (len == 0 || to + len < to)
+ return -EINVAL;
+
+ flush = 0;
+ down_read(&gmap->mm->mmap_sem);
+ for (off = 0; off < len; off += PMD_SIZE) {
+ /* Walk the guest addr space page table */
+ table = gmap->table + (((to + off) >> 53) & 0x7ff);
+ if (*table & _REGION_ENTRY_INV)
+ return 0;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + (((to + off) >> 42) & 0x7ff);
+ if (*table & _REGION_ENTRY_INV)
+ return 0;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + (((to + off) >> 31) & 0x7ff);
+ if (*table & _REGION_ENTRY_INV)
+ return 0;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + (((to + off) >> 20) & 0x7ff);
+
+ /* Clear segment table entry in guest address space. */
+ flush |= gmap_unlink_segment(gmap, table);
+ *table = _SEGMENT_ENTRY_INV;
+ }
+ up_read(&gmap->mm->mmap_sem);
+ if (flush)
+ gmap_flush_tlb(gmap);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gmap_unmap_segment);
+
+/**
+ * gmap_mmap_segment - map a segment to the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @from: source address in the parent address space
+ * @to: target address in the guest address space
+ *
+ * Returns 0 if the mmap succeded, -EINVAL or -ENOMEM if not.
+ */
+int gmap_map_segment(struct gmap *gmap, unsigned long from,
+ unsigned long to, unsigned long len)
+{
+ unsigned long *table;
+ unsigned long off;
+ int flush;
+
+ if ((from | to | len) & (PMD_SIZE - 1))
+ return -EINVAL;
+ if (len == 0 || from + len > PGDIR_SIZE ||
+ from + len < from || to + len < to)
+ return -EINVAL;
+
+ flush = 0;
+ down_read(&gmap->mm->mmap_sem);
+ for (off = 0; off < len; off += PMD_SIZE) {
+ /* Walk the gmap address space page table */
+ table = gmap->table + (((to + off) >> 53) & 0x7ff);
+ if ((*table & _REGION_ENTRY_INV) &&
+ gmap_alloc_table(gmap, table, _REGION2_ENTRY_EMPTY))
+ goto out_unmap;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + (((to + off) >> 42) & 0x7ff);
+ if ((*table & _REGION_ENTRY_INV) &&
+ gmap_alloc_table(gmap, table, _REGION3_ENTRY_EMPTY))
+ goto out_unmap;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + (((to + off) >> 31) & 0x7ff);
+ if ((*table & _REGION_ENTRY_INV) &&
+ gmap_alloc_table(gmap, table, _SEGMENT_ENTRY_EMPTY))
+ goto out_unmap;
+ table = (unsigned long *) (*table & _REGION_ENTRY_ORIGIN);
+ table = table + (((to + off) >> 20) & 0x7ff);
+
+ /* Store 'from' address in an invalid segment table entry. */
+ flush |= gmap_unlink_segment(gmap, table);
+ *table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | (from + off);
+ }
+ up_read(&gmap->mm->mmap_sem);
+ if (flush)
+ gmap_flush_tlb(gmap);
+ return 0;
+
+out_unmap:
+ 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)
+{
+ unsigned long *table, vmaddr, segment;
+ struct mm_struct *mm;
+ struct gmap_pgtable *mp;
+ struct gmap_rmap *rmap;
+ struct vm_area_struct *vma;
+ struct page *page;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ current->thread.gmap_addr = address;
+ mm = gmap->mm;
+ /* Walk the gmap address space page table */
+ table = gmap->table + ((address >> 53) & 0x7ff);
+ if (unlikely(*table & _REGION_ENTRY_INV))
+ return -EFAULT;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + ((address >> 42) & 0x7ff);
+ if (unlikely(*table & _REGION_ENTRY_INV))
+ return -EFAULT;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + ((address >> 31) & 0x7ff);
+ if (unlikely(*table & _REGION_ENTRY_INV))
+ return -EFAULT;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + ((address >> 20) & 0x7ff);
+
+ /* Convert the gmap address to an mm address. */
+ segment = *table;
+ if (likely(!(segment & _SEGMENT_ENTRY_INV))) {
+ page = pfn_to_page(segment >> PAGE_SHIFT);
+ mp = (struct gmap_pgtable *) page->index;
+ return mp->vmaddr | (address & ~PMD_MASK);
+ } else if (segment & _SEGMENT_ENTRY_RO) {
+ vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
+ vma = find_vma(mm, vmaddr);
+ if (!vma || vma->vm_start > vmaddr)
+ return -EFAULT;
+
+ /* Walk the parent mm page table */
+ pgd = pgd_offset(mm, vmaddr);
+ pud = pud_alloc(mm, pgd, vmaddr);
+ if (!pud)
+ return -ENOMEM;
+ pmd = pmd_alloc(mm, pud, vmaddr);
+ if (!pmd)
+ return -ENOMEM;
+ if (!pmd_present(*pmd) &&
+ __pte_alloc(mm, vma, pmd, vmaddr))
+ return -ENOMEM;
+ /* pmd now points to a valid segment table entry. */
+ rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
+ if (!rmap)
+ return -ENOMEM;
+ /* Link gmap segment table entry location to page table. */
+ page = pmd_page(*pmd);
+ mp = (struct gmap_pgtable *) page->index;
+ rmap->entry = table;
+ list_add(&rmap->list, &mp->mapper);
+ /* Set gmap segment table entry to page table. */
+ *table = pmd_val(*pmd) & PAGE_MASK;
+ return vmaddr | (address & ~PMD_MASK);
+ }
+ return -EFAULT;
+
+}
+EXPORT_SYMBOL_GPL(gmap_fault);
+
+void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
+{
+ struct gmap_rmap *rmap, *next;
+ struct gmap_pgtable *mp;
+ struct page *page;
+ int flush;
+
+ flush = 0;
+ spin_lock(&mm->page_table_lock);
+ page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+ mp = (struct gmap_pgtable *) page->index;
+ list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
+ *rmap->entry =
+ _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+ list_del(&rmap->list);
+ kfree(rmap);
+ flush = 1;
+ }
+ spin_unlock(&mm->page_table_lock);
+ if (flush)
+ __tlb_flush_global();
+}
+
+static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
+ unsigned long vmaddr)
{
struct page *page;
unsigned long *table;
+ struct gmap_pgtable *mp;
page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
if (!page)
return NULL;
+ mp = kmalloc(sizeof(*mp), GFP_KERNEL|__GFP_REPEAT);
+ if (!mp) {
+ __free_page(page);
+ return NULL;
+ }
pgtable_page_ctor(page);
+ mp->vmaddr = vmaddr & PMD_MASK;
+ INIT_LIST_HEAD(&mp->mapper);
+ page->index = (unsigned long) mp;
atomic_set(&page->_mapcount, 3);
table = (unsigned long *) page_to_phys(page);
clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
@@ -167,24 +512,57 @@ static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
static inline void page_table_free_pgste(unsigned long *table)
{
struct page *page;
+ struct gmap_pgtable *mp;
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+ mp = (struct gmap_pgtable *) page->index;
+ BUG_ON(!list_empty(&mp->mapper));
pgtable_page_ctor(page);
atomic_set(&page->_mapcount, -1);
+ kfree(mp);
__free_page(page);
}
-#endif
-unsigned long *page_table_alloc(struct mm_struct *mm)
+#else /* CONFIG_PGSTE */
+
+static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
+ unsigned long vmaddr)
+{
+}
+
+static inline void page_table_free_pgste(unsigned long *table)
+{
+}
+
+static inline void gmap_unmap_notifier(struct mm_struct *mm,
+ unsigned long *table)
+{
+}
+
+#endif /* CONFIG_PGSTE */
+
+static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+{
+ unsigned int old, new;
+
+ do {
+ old = atomic_read(v);
+ new = old ^ bits;
+ } while (atomic_cmpxchg(v, old, new) != old);
+ return new;
+}
+
+/*
+ * page table entry allocation/free routines.
+ */
+unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
{
struct page *page;
unsigned long *table;
unsigned int mask, bit;
-#ifdef CONFIG_PGSTE
if (mm_has_pgste(mm))
- return page_table_alloc_pgste(mm);
-#endif
+ return page_table_alloc_pgste(mm, vmaddr);
/* Allocate fragments of a 4K page as 1K/2K page table */
spin_lock_bh(&mm->context.list_lock);
mask = FRAG_MASK;
@@ -222,10 +600,10 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
struct page *page;
unsigned int bit, mask;
-#ifdef CONFIG_PGSTE
- if (mm_has_pgste(mm))
+ if (mm_has_pgste(mm)) {
+ gmap_unmap_notifier(mm, table);
return page_table_free_pgste(table);
-#endif
+ }
/* Free 1K/2K page table fragment of a 4K page */
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)));
@@ -249,10 +627,8 @@ static void __page_table_free_rcu(void *table, unsigned bit)
{
struct page *page;
-#ifdef CONFIG_PGSTE
if (bit == FRAG_MASK)
return page_table_free_pgste(table);
-#endif
/* Free 1K/2K page table fragment of a 4K page */
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
if (atomic_xor_bits(&page->_mapcount, bit) == 0) {
@@ -269,13 +645,12 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
unsigned int bit, mask;
mm = tlb->mm;
-#ifdef CONFIG_PGSTE
if (mm_has_pgste(mm)) {
+ gmap_unmap_notifier(mm, table);
table = (unsigned long *) (__pa(table) | FRAG_MASK);
tlb_remove_table(tlb, table);
return;
}
-#endif
bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t)));
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
spin_lock_bh(&mm->context.list_lock);
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 8c1970d1dd91..781ff5169560 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -61,12 +61,12 @@ static inline pmd_t *vmem_pmd_alloc(void)
return pmd;
}
-static pte_t __ref *vmem_pte_alloc(void)
+static pte_t __ref *vmem_pte_alloc(unsigned long address)
{
pte_t *pte;
if (slab_is_available())
- pte = (pte_t *) page_table_alloc(&init_mm);
+ pte = (pte_t *) page_table_alloc(&init_mm, address);
else
pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
if (!pte)
@@ -120,7 +120,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
}
#endif
if (pmd_none(*pm_dir)) {
- pt_dir = vmem_pte_alloc();
+ pt_dir = vmem_pte_alloc(address);
if (!pt_dir)
goto out;
pmd_populate(&init_mm, pm_dir, pt_dir);
@@ -205,7 +205,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
pm_dir = pmd_offset(pu_dir, address);
if (pmd_none(*pm_dir)) {
- pt_dir = vmem_pte_alloc();
+ pt_dir = vmem_pte_alloc(address);
if (!pt_dir)
goto out;
pmd_populate(&init_mm, pm_dir, pt_dir);
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index 0e358c2cffeb..6efc18b5e60a 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -13,8 +13,6 @@
#include <linux/oprofile.h>
#include <linux/init.h>
#include <linux/errno.h>
-#include <linux/oprofile.h>
-#include <linux/errno.h>
#include <linux/fs.h>
#include "../../../drivers/oprofile/oprof.h"
diff --git a/arch/score/kernel/module.c b/arch/score/kernel/module.c
index 4de8d47becd3..469e3b64e2f2 100644
--- a/arch/score/kernel/module.c
+++ b/arch/score/kernel/module.c
@@ -27,23 +27,6 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
-void *module_alloc(unsigned long size)
-{
- return size ? vmalloc(size) : NULL;
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
- char *secstrings, struct module *mod)
-{
- return 0;
-}
-
int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
unsigned int symindex, unsigned int relindex,
struct module *me)
@@ -146,6 +129,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
unsigned int symindex, unsigned int relsec,
struct module *me)
{
+ /* Non-standard return value... most other arch's return -ENOEXEC
+ * for an unsupported relocation variant
+ */
return 0;
}
@@ -154,12 +140,3 @@ const struct exception_table_entry *search_module_dbetables(unsigned long addr)
{
return NULL;
}
-
-/* Put in dbe list if necessary. */
-int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod) {}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index bbdeb48bbf8e..748ff1920068 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -897,20 +897,4 @@ source "security/Kconfig"
source "crypto/Kconfig"
-menuconfig VIRTUALIZATION
- bool "Virtualization"
- default n
- ---help---
- Say Y here to get to see options for using your Linux host to run other
- operating systems inside virtual machines (guests).
- This option alone does not add any kernel code.
-
- If you say N, all options in this submenu will be skipped and disabled.
-
-if VIRTUALIZATION
-
-source drivers/virtio/Kconfig
-
-endif # VIRTUALIZATION
-
source "lib/Kconfig"
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 969421f64a15..1dc924b2f508 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -188,7 +188,7 @@ static void ap320_wvga_power_off(void *board_data)
__raw_writew(0, FPGA_LCDREG);
}
-const static struct fb_videomode ap325rxa_lcdc_modes[] = {
+static const struct fb_videomode ap325rxa_lcdc_modes[] = {
{
.name = "LB070WV1",
.xres = 800,
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 513cb1a2e6c8..b24d69d509e7 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -280,7 +280,7 @@ static struct platform_device usbhs_device = {
};
/* LCDC */
-const static struct fb_videomode ecovec_lcd_modes[] = {
+static const struct fb_videomode ecovec_lcd_modes[] = {
{
.name = "Panel",
.xres = 800,
@@ -295,7 +295,7 @@ const static struct fb_videomode ecovec_lcd_modes[] = {
},
};
-const static struct fb_videomode ecovec_dvi_modes[] = {
+static const struct fb_videomode ecovec_dvi_modes[] = {
{
.name = "DVI",
.xres = 1280,
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 8b4abbbd1477..f65271a8d075 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -127,7 +127,7 @@ static struct platform_device kfr2r09_sh_keysc_device = {
},
};
-const static struct fb_videomode kfr2r09_lcdc_modes[] = {
+static const struct fb_videomode kfr2r09_lcdc_modes[] = {
{
.name = "TX07D34VM0AAA",
.xres = 240,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 184fde169132..2d4c9c8c6664 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -214,7 +214,7 @@ static struct platform_device migor_nand_flash_device = {
}
};
-const static struct fb_videomode migor_lcd_modes[] = {
+static const struct fb_videomode migor_lcd_modes[] = {
{
#if defined(CONFIG_SH_MIGOR_RTA_WVGA)
.name = "LB070WV1",
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 12357671023e..d00756728bd2 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -145,7 +145,7 @@ static struct platform_device nor_flash_device = {
};
/* LCDC */
-const static struct fb_videomode lcdc_720p_modes[] = {
+static const struct fb_videomode lcdc_720p_modes[] = {
{
.name = "LB070WV1",
.sync = 0, /* hsync and vsync are active low */
@@ -160,7 +160,7 @@ const static struct fb_videomode lcdc_720p_modes[] = {
},
};
-const static struct fb_videomode lcdc_vga_modes[] = {
+static const struct fb_videomode lcdc_vga_modes[] = {
{
.name = "LB070WV1",
.sync = 0, /* hsync and vsync are active low */
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index c7983124d99d..63a27dbc952e 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -30,7 +30,6 @@
#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_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))
@@ -39,15 +38,15 @@
#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
/**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -60,7 +59,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
c = old;
}
- return c != (u);
+ return c;
}
#define smp_mb__before_atomic_dec() smp_mb()
@@ -68,7 +67,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb()
-#include <asm-generic/atomic-long.h>
-#include <asm-generic/atomic64.h>
-
#endif /* __ASM_SH_ATOMIC_H */
diff --git a/arch/sh/include/asm/delay.h b/arch/sh/include/asm/delay.h
index 4b16bf9b56bd..9670e127b7b2 100644
--- a/arch/sh/include/asm/delay.h
+++ b/arch/sh/include/asm/delay.h
@@ -1,26 +1 @@
-#ifndef __ASM_SH_DELAY_H
-#define __ASM_SH_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/sh/lib/delay.c
- */
-
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
- __udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
- __ndelay(n))
-
-#endif /* __ASM_SH_DELAY_H */
+#include <asm-generic/delay.h>
diff --git a/arch/sh/include/asm/hw_irq.h b/arch/sh/include/asm/hw_irq.h
index 603cdde813d1..693d44184058 100644
--- a/arch/sh/include/asm/hw_irq.h
+++ b/arch/sh/include/asm/hw_irq.h
@@ -3,7 +3,7 @@
#include <linux/init.h>
#include <linux/sh_intc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
extern atomic_t irq_err_count;
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index 88bd6be168a9..b97baf81a87b 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -45,8 +45,6 @@
#define GET_FP(regs) ((regs)->regs[14])
#define GET_USP(regs) ((regs)->regs[15])
-extern void show_regs(struct pt_regs *);
-
#define arch_has_single_step() (1)
/*
diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h
index 9070d943ddde..78b0d0f4b24b 100644
--- a/arch/sh/include/asm/smp.h
+++ b/arch/sh/include/asm/smp.h
@@ -8,7 +8,7 @@
#ifdef CONFIG_SMP
#include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/current.h>
#include <asm/percpu.h>
diff --git a/arch/sh/kernel/cpu/sh4/perf_event.c b/arch/sh/kernel/cpu/sh4/perf_event.c
index 748955df018d..fa4f724b295a 100644
--- a/arch/sh/kernel/cpu/sh4/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4/perf_event.c
@@ -180,6 +180,21 @@ static const int sh7750_cache_events
[ C(RESULT_MISS) ] = -1,
},
},
+
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
};
static int sh7750_event_map(int event)
diff --git a/arch/sh/kernel/cpu/sh4a/perf_event.c b/arch/sh/kernel/cpu/sh4a/perf_event.c
index 17e6bebfede0..84a2c396ceee 100644
--- a/arch/sh/kernel/cpu/sh4a/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4a/perf_event.c
@@ -205,6 +205,21 @@ static const int sh4a_cache_events
[ C(RESULT_MISS) ] = -1,
},
},
+
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
};
static int sh4a_event_map(int event)
diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
index 64c807c39208..bf280c812d2f 100644
--- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c
+++ b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
@@ -256,7 +256,7 @@ out:
return ret;
}
-static struct dev_power_domain default_power_domain = {
+static struct dev_pm_domain default_pm_domain = {
.ops = {
.runtime_suspend = default_platform_runtime_suspend,
.runtime_resume = default_platform_runtime_resume,
@@ -285,7 +285,7 @@ static int platform_bus_notify(struct notifier_block *nb,
hwblk_disable(hwblk_info, hwblk);
/* make sure driver re-inits itself once */
__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
- dev->pwr_domain = &default_power_domain;
+ dev->pm_domain = &default_pm_domain;
break;
/* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
case BUS_NOTIFY_BOUND_DRIVER:
@@ -299,7 +299,7 @@ static int platform_bus_notify(struct notifier_block *nb,
__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
break;
case BUS_NOTIFY_DEL_DEVICE:
- dev->pwr_domain = NULL;
+ dev->pm_domain = NULL;
break;
}
return 0;
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
index 425d604e3a28..84db0d6ccd0d 100644
--- a/arch/sh/kernel/idle.c
+++ b/arch/sh/kernel/idle.c
@@ -18,7 +18,7 @@
#include <linux/smp.h>
#include <asm/pgalloc.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
void (*pm_idle)(void) = NULL;
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 32c385ef1011..0f62f4672754 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -58,7 +58,7 @@ int register_trapped_io(struct trapped_io *tiop)
for (k = 0; k < tiop->num_resources; k++) {
res = tiop->resource + k;
- len += roundup((res->end - res->start) + 1, PAGE_SIZE);
+ len += roundup(resource_size(res), PAGE_SIZE);
flags |= res->flags;
}
@@ -85,7 +85,7 @@ int register_trapped_io(struct trapped_io *tiop)
(unsigned long)(tiop->virt_base + len),
res->flags & IORESOURCE_IO ? "io" : "mmio",
(unsigned long)res->start);
- len += roundup((res->end - res->start) + 1, PAGE_SIZE);
+ len += roundup(resource_size(res), PAGE_SIZE);
}
tiop->magic = IO_TRAPPED_MAGIC;
@@ -128,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
return tiop->virt_base + voffs;
}
- len = (res->end - res->start) + 1;
+ len = resource_size(res);
voffs += roundup(len, PAGE_SIZE);
}
}
@@ -173,7 +173,7 @@ static unsigned long lookup_address(struct trapped_io *tiop,
for (k = 0; k < tiop->num_resources; k++) {
res = tiop->resource + k;
- len = roundup((res->end - res->start) + 1, PAGE_SIZE);
+ len = roundup(resource_size(res), PAGE_SIZE);
if (address < (vaddr + len))
return res->start + (address - vaddr);
vaddr += len;
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index e2a3af31ff99..c5a33f007f88 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -170,7 +170,7 @@ void __init reserve_crashkernel(void)
if (crashk_res.end == crashk_res.start)
goto disable;
- crash_size = PAGE_ALIGN(crashk_res.end - crashk_res.start + 1);
+ crash_size = PAGE_ALIGN(resource_size(&crashk_res));
if (!crashk_res.start) {
unsigned long max = memblock_end_of_DRAM() - memory_limit;
crashk_res.start = __memblock_alloc_base(crash_size, PAGE_SIZE, max);
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
index 19b1f8826aef..1b525dedd29a 100644
--- a/arch/sh/kernel/module.c
+++ b/arch/sh/kernel/module.c
@@ -34,30 +34,6 @@
#include <asm/unaligned.h>
#include <asm/dwarf.h>
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
-
- return vmalloc_exec(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
int apply_relocate_add(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
@@ -133,17 +109,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
return 0;
}
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
-
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 3d7b209b2178..92b3c276339a 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -63,7 +63,7 @@ static inline int put_stack_long(struct task_struct *task, int offset,
return 0;
}
-void ptrace_triggered(struct perf_event *bp, int nmi,
+void ptrace_triggered(struct perf_event *bp,
struct perf_sample_data *data, struct pt_regs *regs)
{
struct perf_event_attr attr;
@@ -91,7 +91,8 @@ static int set_single_step(struct task_struct *tsk, unsigned long addr)
attr.bp_len = HW_BREAKPOINT_LEN_2;
attr.bp_type = HW_BREAKPOINT_R;
- bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
+ bp = register_user_hw_breakpoint(&attr, ptrace_triggered,
+ NULL, tsk);
if (IS_ERR(bp))
return PTR_ERR(bp);
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index 6207561ea34a..3147a9a6fb8b 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -21,7 +21,7 @@
#include <linux/cpu.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/mmu_context.h>
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index b51a17104b5f..d9006f8ffc14 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -393,7 +393,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
*/
if (!expected) {
unaligned_fixups_notify(current, instruction, regs);
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1,
regs, address);
}
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index 6713ca97e553..cd3a40483299 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -28,7 +28,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/fpu.h>
@@ -434,7 +434,7 @@ static int misaligned_load(struct pt_regs *regs,
return error;
}
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
destreg = (opcode >> 4) & 0x3f;
if (user_mode(regs)) {
@@ -512,7 +512,7 @@ static int misaligned_store(struct pt_regs *regs,
return error;
}
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
srcreg = (opcode >> 4) & 0x3f;
if (user_mode(regs)) {
@@ -588,7 +588,7 @@ static int misaligned_fpu_load(struct pt_regs *regs,
return error;
}
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
destreg = (opcode >> 4) & 0x3f;
if (user_mode(regs)) {
@@ -665,7 +665,7 @@ static int misaligned_fpu_store(struct pt_regs *regs,
return error;
}
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
srcreg = (opcode >> 4) & 0x3f;
if (user_mode(regs)) {
diff --git a/arch/sh/kernel/unwinder.c b/arch/sh/kernel/unwinder.c
index 468889d958f4..521b5432471f 100644
--- a/arch/sh/kernel/unwinder.c
+++ b/arch/sh/kernel/unwinder.c
@@ -13,7 +13,7 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <asm/unwinder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/*
* This is the most basic stack unwinder an architecture can
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index f76a5090d5d1..977195210653 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -620,7 +620,7 @@ int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
struct task_struct *tsk = current;
struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
/* initialize once. */
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index d4c34d757f0d..7bebd044f2a1 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -160,7 +160,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
if ((regs->sr & SR_IMASK) != SR_IMASK)
local_irq_enable();
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
/*
* If we're in an interrupt, have no user context or are running
@@ -210,11 +210,11 @@ good_area:
}
if (fault & VM_FAULT_MAJOR) {
tsk->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
regs, address);
} else {
tsk->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
regs, address);
}
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c
index 7f5810f5dfdc..e3430e093d43 100644
--- a/arch/sh/mm/tlbflush_64.c
+++ b/arch/sh/mm/tlbflush_64.c
@@ -116,7 +116,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
/* Not an IO address, so reenable interrupts */
local_irq_enable();
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
/*
* If we're in an interrupt or have no user
@@ -200,11 +200,11 @@ good_area:
if (fault & VM_FAULT_MAJOR) {
tsk->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
regs, address);
} else {
tsk->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
regs, address);
}
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 253986bd6bb6..1074dddcb104 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -41,6 +41,7 @@ config SPARC64
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_KRETPROBES
select HAVE_KPROBES
+ select HAVE_RCU_TABLE_FREE if SMP
select HAVE_MEMBLOCK
select HAVE_SYSCALL_WRAPPERS
select HAVE_DYNAMIC_FTRACE
@@ -81,10 +82,6 @@ config IOMMU_HELPER
bool
default y if SPARC64
-config QUICKLIST
- bool
- default y if SPARC64
-
config STACKTRACE_SUPPORT
bool
default y if SPARC64
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
index 7ae128b19d3f..5c3c8b69884d 100644
--- a/arch/sparc/include/asm/atomic_32.h
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -22,7 +22,7 @@
extern int __atomic_add_return(int, atomic_t *);
extern int atomic_cmpxchg(atomic_t *, int, int);
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-extern int atomic_add_unless(atomic_t *, int, int);
+extern int __atomic_add_unless(atomic_t *, int, int);
extern void atomic_set(atomic_t *, int);
#define atomic_read(v) (*(volatile int *)&(v)->counter)
@@ -52,7 +52,6 @@ extern void atomic_set(atomic_t *, int);
#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
/* This is the old 24-bit implementation. It's still used internally
* by some sparc-specific code, notably the semaphore implementation.
@@ -161,5 +160,4 @@ static inline int __atomic24_sub(int i, atomic24_t *v)
#endif /* !(__KERNEL__) */
-#include <asm-generic/atomic-long.h>
#endif /* !(__ARCH_SPARC_ATOMIC__) */
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
index bdb2ff880bdd..9f421df46aec 100644
--- a/arch/sparc/include/asm/atomic_64.h
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -70,7 +70,7 @@ extern long atomic64_sub_ret(long, atomic64_t *);
#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -82,10 +82,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#define atomic64_cmpxchg(v, o, n) \
((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
@@ -114,5 +113,4 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
#endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
index 38e9aa1b2cea..325e295d60de 100644
--- a/arch/sparc/include/asm/bitops_64.h
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -91,10 +91,7 @@ static inline unsigned int __arch_hweight8(unsigned int w)
#include <asm-generic/bitops/le.h>
-#define ext2_set_bit_atomic(lock,nr,addr) \
- test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock,nr,addr) \
- test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* __KERNEL__ */
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
index e67880381b84..cfa9cd2e5519 100644
--- a/arch/sparc/include/asm/elf_64.h
+++ b/arch/sparc/include/asm/elf_64.h
@@ -186,7 +186,7 @@ static inline unsigned int sparc64_elf_hwcap(void)
return cap;
}
-#define ELF_HWCAP sparc64_elf_hwcap();
+#define ELF_HWCAP sparc64_elf_hwcap()
/* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index 862e3ce92b15..02939abd356c 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -42,9 +42,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
-struct device_node;
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
-
#endif /* __KERNEL__ */
#ifndef CONFIG_LEON_PCI
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index 948b686ec089..2614d96141c9 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -91,9 +91,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
return PCI_IRQ_NONE;
}
-struct device_node;
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
-
#define HAVE_ARCH_PCI_RESOURCE_TO_USER
extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h
index 4e5e0878144f..40b2d7a7023d 100644
--- a/arch/sparc/include/asm/pgalloc_64.h
+++ b/arch/sparc/include/asm/pgalloc_64.h
@@ -5,7 +5,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/quicklist.h>
#include <asm/spitfire.h>
#include <asm/cpudata.h>
@@ -14,71 +13,114 @@
/* Page table allocation/freeing. */
+extern struct kmem_cache *pgtable_cache;
+
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
}
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
- quicklist_free(0, NULL, pgd);
+ kmem_cache_free(pgtable_cache, pgd);
}
#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return kmem_cache_alloc(pgtable_cache,
+ GFP_KERNEL|__GFP_REPEAT);
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
- quicklist_free(0, NULL, pmd);
+ kmem_cache_free(pgtable_cache, pmd);
}
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
}
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
unsigned long address)
{
struct page *page;
- void *pg;
+ pte_t *pte;
- pg = quicklist_alloc(0, GFP_KERNEL, NULL);
- if (!pg)
+ pte = pte_alloc_one_kernel(mm, address);
+ if (!pte)
return NULL;
- page = virt_to_page(pg);
+ page = virt_to_page(pte);
pgtable_page_ctor(page);
return page;
}
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
- quicklist_free(0, NULL, pte);
+ free_page((unsigned long)pte);
}
static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
{
pgtable_page_dtor(ptepage);
- quicklist_free_page(0, NULL, ptepage);
+ __free_page(ptepage);
}
-
#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
#define pmd_populate(MM,PMD,PTE_PAGE) \
pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
#define pmd_pgtable(pmd) pmd_page(pmd)
-static inline void check_pgt_cache(void)
+#define check_pgt_cache() do { } while (0)
+
+static inline void pgtable_free(void *table, bool is_page)
+{
+ if (is_page)
+ free_page((unsigned long)table);
+ else
+ kmem_cache_free(pgtable_cache, table);
+}
+
+#ifdef CONFIG_SMP
+
+struct mmu_gather;
+extern void tlb_remove_table(struct mmu_gather *, void *);
+
+static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
+{
+ unsigned long pgf = (unsigned long)table;
+ if (is_page)
+ pgf |= 0x1UL;
+ tlb_remove_table(tlb, (void *)pgf);
+}
+
+static inline void __tlb_remove_table(void *_table)
+{
+ void *table = (void *)((unsigned long)_table & ~0x1UL);
+ bool is_page = false;
+
+ if ((unsigned long)_table & 0x1UL)
+ is_page = true;
+ pgtable_free(table, is_page);
+}
+#else /* CONFIG_SMP */
+static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
{
- quicklist_trim(0, NULL, 25, 16);
+ pgtable_free(table, is_page);
+}
+#endif /* !CONFIG_SMP */
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage,
+ unsigned long address)
+{
+ pgtable_page_dtor(ptepage);
+ pgtable_free_tlb(tlb, page_address(ptepage), true);
}
-#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
-#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
+#define __pmd_free_tlb(tlb, pmd, addr) \
+ pgtable_free_tlb(tlb, pmd, false)
#endif /* _SPARC64_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1e03c5a6b4f7..adf89329af59 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -95,6 +95,10 @@
/* PTE bits which are the same in SUN4U and SUN4V format. */
#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */
#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
+#define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */
+
+/* Advertise support for _PAGE_SPECIAL */
+#define __HAVE_ARCH_PTE_SPECIAL
/* SUN4U pte bits... */
#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */
@@ -104,6 +108,7 @@
#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */
#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */
#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
+#define _PAGE_SPECIAL_4U _AC(0x0200000000000000,UL) /* Special page */
#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */
#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */
#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
@@ -133,6 +138,7 @@
#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */
#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */
#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */
+#define _PAGE_SPECIAL_4V _AC(0x0200000000000000,UL) /* Special page */
#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */
#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */
#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */
@@ -302,10 +308,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
: "=r" (mask), "=r" (tmp)
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
- _PAGE_SZBITS_4U),
+ _PAGE_SZBITS_4U | _PAGE_SPECIAL),
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
- _PAGE_SZBITS_4V));
+ _PAGE_SZBITS_4V | _PAGE_SPECIAL));
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
}
@@ -502,6 +508,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
static inline pte_t pte_mkspecial(pte_t pte)
{
+ pte_val(pte) |= _PAGE_SPECIAL;
return pte;
}
@@ -607,9 +614,9 @@ static inline unsigned long pte_present(pte_t pte)
return val;
}
-static inline int pte_special(pte_t pte)
+static inline unsigned long pte_special(pte_t pte)
{
- return 0;
+ return pte_val(pte) & _PAGE_SPECIAL;
}
#define pmd_set(pmdp, ptep) \
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
index 56bbaadef646..edd3d3cde460 100644
--- a/arch/sparc/include/asm/prom.h
+++ b/arch/sparc/include/asm/prom.h
@@ -21,7 +21,7 @@
#include <linux/of_pdt.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2
#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index b928b31424b1..a0e1bcf843a1 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -213,7 +213,6 @@ extern unsigned long profile_pc(struct pt_regs *);
#else
#define profile_pc(regs) instruction_pointer(regs)
#endif
-extern void show_regs(struct pt_regs *);
#endif /* (__KERNEL__) */
#else /* __ASSEMBLY__ */
@@ -257,7 +256,6 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
#endif /* (__KERNEL__) */
#else /* (!__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 093f10843ff2..01c51c704341 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -22,7 +22,7 @@
#include <asm/ptrace.h>
#include <asm/asi.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/*
* Private routines/data
diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h
index 20bca8950710..29862a9e9065 100644
--- a/arch/sparc/include/asm/smp_64.h
+++ b/arch/sparc/include/asm/smp_64.h
@@ -27,7 +27,7 @@
*/
#include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/percpu.h>
DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 1c9c80a1a86a..6ffccd6e0156 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -228,7 +228,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
}
pa &= PAGE_MASK;
- sparc_mapiorange(bus, pa, res->start, res->end - res->start + 1);
+ sparc_mapiorange(bus, pa, res->start, resource_size(res));
return (void __iomem *)(unsigned long)(res->start + offset);
}
@@ -240,7 +240,7 @@ static void _sparc_free_io(struct resource *res)
{
unsigned long plen;
- plen = res->end - res->start + 1;
+ plen = resource_size(res);
BUG_ON((plen & (PAGE_SIZE-1)) != 0);
sparc_unmapiorange(res->start, plen);
release_resource(res);
@@ -331,9 +331,9 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
}
n = PAGE_ALIGN(n);
- if ((res->end-res->start)+1 != n) {
+ if (resource_size(res) != n) {
printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
- (long)((res->end-res->start)+1), n);
+ (long)resource_size(res), n);
return;
}
@@ -504,9 +504,9 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
}
n = PAGE_ALIGN(n);
- if ((res->end-res->start)+1 != n) {
+ if (resource_size(res) != n) {
printk("pci_free_consistent: region 0x%lx asked 0x%lx\n",
- (long)((res->end-res->start)+1), (long)n);
+ (long)resource_size(res), (long)n);
return;
}
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 4e78862d12fd..0dd8422a469c 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -26,7 +26,7 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/io.h>
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index fe8fb44c609c..1210fde18740 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -28,7 +28,7 @@
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq_regs.h>
#include <asm/traps.h>
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 99ba5baa9497..da0c6c70ccb2 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -68,12 +68,6 @@ void *module_alloc(unsigned long size)
return ret;
}
-/* Free memory returned from module_core_alloc/module_init_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
/* Make generic code ignore STT_REGISTER dummy undefined symbols. */
int module_frob_arch_sections(Elf_Ehdr *hdr,
Elf_Shdr *sechdrs,
@@ -107,17 +101,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
return 0;
}
-int apply_relocate(Elf_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
-
int apply_relocate_add(Elf_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
@@ -239,15 +222,4 @@ int module_finalize(const Elf_Ehdr *hdr,
return 0;
}
-#else
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
#endif /* CONFIG_SPARC64 */
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 713dc91020a6..1e94f946570e 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -284,7 +284,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
dev->sysdata = node;
dev->dev.parent = bus->bridge;
dev->dev.bus = &pci_bus_type;
- dev->dev.of_node = node;
+ dev->dev.of_node = of_node_get(node);
dev->devfn = devfn;
dev->multifunction = 0; /* maybe a lie? */
set_pcie_port_type(dev);
@@ -820,11 +820,9 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
unsigned long space_size, user_offset, user_size;
if (mmap_state == pci_mmap_io) {
- space_size = (pbm->io_space.end -
- pbm->io_space.start) + 1;
+ space_size = resource_size(&pbm->io_space);
} else {
- space_size = (pbm->mem_space.end -
- pbm->mem_space.start) + 1;
+ space_size = resource_size(&pbm->mem_space);
}
/* Make sure the request is in range. */
@@ -1021,12 +1019,6 @@ void arch_teardown_msi_irq(unsigned int irq)
}
#endif /* !(CONFIG_PCI_MSI) */
-struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
- return pdev->dev.of_node;
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
{
struct pci_dev *ali_isa_bridge;
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 948601a066ff..a19f04195478 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -885,14 +885,6 @@ int pcibios_assign_resource(struct pci_dev *pdev, int resource)
return -ENXIO;
}
-struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
- struct pcidev_cookie *pc = pdev->sysdata;
-
- return pc->prom_node;
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
/*
* This probably belongs here rather than ioport.c because
* we do not want this crud linked into SBus kernels.
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 2cb0e1c001e2..171e8d84dc3f 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -22,7 +22,7 @@
#include <asm/stacktrace.h>
#include <asm/cpudata.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/nmi.h>
#include <asm/pcr.h>
@@ -246,6 +246,20 @@ static const cache_map_t ultra3_cache_map = {
[ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
},
},
+[C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+ [C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+ [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+ [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+},
};
static const struct sparc_pmu ultra3_pmu = {
@@ -361,6 +375,20 @@ static const cache_map_t niagara1_cache_map = {
[ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
},
},
+[C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+ [C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+ [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+ [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+},
};
static const struct sparc_pmu niagara1_pmu = {
@@ -473,6 +501,20 @@ static const cache_map_t niagara2_cache_map = {
[ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
},
},
+[C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+ [C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+ [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+ [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
+ },
+},
};
static const struct sparc_pmu niagara2_pmu = {
@@ -1277,7 +1319,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
if (!sparc_perf_event_set_period(event, hwc, idx))
continue;
- if (perf_event_overflow(event, 1, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
sparc_pmu_stop(event, 0);
}
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index 21b125341bf7..f671e7fd6ddc 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -22,7 +22,7 @@
#include <linux/delay.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 99cb17251bb5..4a442c32e117 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -28,7 +28,7 @@
#include <asm/head.h>
#include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/cpudata.h>
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c
index 4491f4cb2695..7efbb2f9e77f 100644
--- a/arch/sparc/kernel/unaligned_32.c
+++ b/arch/sparc/kernel/unaligned_32.c
@@ -247,7 +247,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
unsigned long addr = compute_effective_address(regs, insn);
int err;
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr);
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
switch (dir) {
case load:
err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
@@ -338,7 +338,7 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
}
addr = compute_effective_address(regs, insn);
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr);
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
switch(dir) {
case load:
err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index b2b019ea8caa..35cff1673aa4 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -317,7 +317,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
addr = compute_effective_address(regs, insn,
((insn >> 25) & 0x1f));
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr);
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
switch (asi) {
case ASI_NL:
case ASI_AIUPL:
@@ -384,7 +384,7 @@ int handle_popc(u32 insn, struct pt_regs *regs)
int ret, i, rd = ((insn >> 25) & 0x1f);
int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
if (insn & 0x2000) {
maybe_flush_windows(0, 0, rd, from_kernel);
value = sign_extend_imm13(insn);
@@ -431,7 +431,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
int asi = decode_asi(insn, regs);
int flag = (freg < 32) ? FPRS_DL : FPRS_DU;
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
save_and_clear_fpu();
current_thread_info()->xfsr[0] &= ~0x1c000;
@@ -554,7 +554,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
unsigned long *reg;
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
maybe_flush_windows(0, 0, rd, from_kernel);
reg = fetch_reg_addr(rd, regs);
@@ -586,7 +586,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
if (tstate & TSTATE_PRIV)
die_if_kernel("lddfmna from kernel", regs);
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar);
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
if (test_thread_flag(TIF_32BIT))
pc = (u32)pc;
if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
@@ -647,7 +647,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
if (tstate & TSTATE_PRIV)
die_if_kernel("stdfmna from kernel", regs);
- perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar);
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
if (test_thread_flag(TIF_32BIT))
pc = (u32)pc;
if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c
index 36357717d691..32b626c9d815 100644
--- a/arch/sparc/kernel/visemul.c
+++ b/arch/sparc/kernel/visemul.c
@@ -802,7 +802,7 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
BUG_ON(regs->tstate & TSTATE_PRIV);
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
if (test_thread_flag(TIF_32BIT))
pc = (u32)pc;
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index d3c7a12ad879..1a371f8ae0b0 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -7,7 +7,7 @@
* Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/spinlock.h>
#include <linux/module.h>
diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c
index a3fccde894ec..aa4d55b0bdf0 100644
--- a/arch/sparc/math-emu/math_32.c
+++ b/arch/sparc/math-emu/math_32.c
@@ -164,7 +164,7 @@ int do_mathemu(struct pt_regs *regs, struct task_struct *fpt)
int retcode = 0; /* assume all succeed */
unsigned long insn;
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
#ifdef DEBUG_MATHEMU
printk("In do_mathemu()... pc is %08lx\n", regs->pc);
diff --git a/arch/sparc/math-emu/math_64.c b/arch/sparc/math-emu/math_64.c
index 56d2c44747b8..e575bd2fe381 100644
--- a/arch/sparc/math-emu/math_64.c
+++ b/arch/sparc/math-emu/math_64.c
@@ -184,7 +184,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
if (tstate & TSTATE_PRIV)
die_if_kernel("unfinished/unimplemented FPop from kernel", regs);
- perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
if (test_thread_flag(TIF_32BIT))
pc = (u32)pc;
if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 79836a7dd00c..e3cda21b5ee9 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -4,7 +4,7 @@
asflags-y := -ansi
ccflags-y := -Werror
-obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o
+obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o
obj-y += fault_$(BITS).o
obj-y += init_$(BITS).o
obj-$(CONFIG_SPARC32) += loadmmu.o
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 7543ddbdadb2..aa1c1b1ce5cc 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -251,7 +251,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
if (in_atomic() || !mm)
goto no_context;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
down_read(&mm->mmap_sem);
@@ -301,12 +301,10 @@ good_area:
}
if (fault & VM_FAULT_MAJOR) {
current->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
- regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
} else {
current->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
- regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
}
up_read(&mm->mmap_sem);
return;
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index f92ce56a8b22..504c0622f729 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -325,7 +325,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
if (in_atomic() || !mm)
goto intr_or_no_mm;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
if (!down_read_trylock(&mm->mmap_sem)) {
if ((regs->tstate & TSTATE_PRIV) &&
@@ -433,12 +433,10 @@ good_area:
}
if (fault & VM_FAULT_MAJOR) {
current->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
- regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
} else {
current->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
- regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
}
up_read(&mm->mmap_sem);
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
new file mode 100644
index 000000000000..a986b5d05712
--- /dev/null
+++ b/arch/sparc/mm/gup.c
@@ -0,0 +1,181 @@
+/*
+ * Lockless get_user_pages_fast for sparc, cribbed from powerpc
+ *
+ * Copyright (C) 2008 Nick Piggin
+ * Copyright (C) 2008 Novell Inc.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmstat.h>
+#include <linux/pagemap.h>
+#include <linux/rwsem.h>
+#include <asm/pgtable.h>
+
+/*
+ * The performance critical leaf functions are made noinline otherwise gcc
+ * inlines everything into a single function which results in too much
+ * register pressure.
+ */
+static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
+ unsigned long end, int write, struct page **pages, int *nr)
+{
+ unsigned long mask, result;
+ pte_t *ptep;
+
+ if (tlb_type == hypervisor) {
+ result = _PAGE_PRESENT_4V|_PAGE_P_4V;
+ if (write)
+ result |= _PAGE_WRITE_4V;
+ } else {
+ result = _PAGE_PRESENT_4U|_PAGE_P_4U;
+ if (write)
+ result |= _PAGE_WRITE_4U;
+ }
+ mask = result | _PAGE_SPECIAL;
+
+ ptep = pte_offset_kernel(&pmd, addr);
+ do {
+ struct page *page, *head;
+ pte_t pte = *ptep;
+
+ if ((pte_val(pte) & mask) != result)
+ return 0;
+ VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+
+ /* The hugepage case is simplified on sparc64 because
+ * we encode the sub-page pfn offsets into the
+ * hugepage PTEs. We could optimize this in the future
+ * use page_cache_add_speculative() for the hugepage case.
+ */
+ page = pte_page(pte);
+ head = compound_head(page);
+ if (!page_cache_get_speculative(head))
+ return 0;
+ if (unlikely(pte_val(pte) != pte_val(*ptep))) {
+ put_page(head);
+ return 0;
+ }
+
+ pages[*nr] = page;
+ (*nr)++;
+ } while (ptep++, addr += PAGE_SIZE, addr != end);
+
+ return 1;
+}
+
+static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
+ int write, struct page **pages, int *nr)
+{
+ unsigned long next;
+ pmd_t *pmdp;
+
+ pmdp = pmd_offset(&pud, addr);
+ do {
+ pmd_t pmd = *pmdp;
+
+ next = pmd_addr_end(addr, end);
+ if (pmd_none(pmd))
+ return 0;
+ if (!gup_pte_range(pmd, addr, next, write, pages, nr))
+ return 0;
+ } while (pmdp++, addr = next, addr != end);
+
+ return 1;
+}
+
+static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
+ int write, struct page **pages, int *nr)
+{
+ unsigned long next;
+ pud_t *pudp;
+
+ pudp = pud_offset(&pgd, addr);
+ do {
+ pud_t pud = *pudp;
+
+ next = pud_addr_end(addr, end);
+ if (pud_none(pud))
+ return 0;
+ if (!gup_pmd_range(pud, addr, next, write, pages, nr))
+ return 0;
+ } while (pudp++, addr = next, addr != end);
+
+ return 1;
+}
+
+int get_user_pages_fast(unsigned long start, int nr_pages, int write,
+ struct page **pages)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long addr, len, end;
+ unsigned long next;
+ pgd_t *pgdp;
+ int nr = 0;
+
+ start &= PAGE_MASK;
+ addr = start;
+ len = (unsigned long) nr_pages << PAGE_SHIFT;
+ end = start + len;
+
+ /*
+ * XXX: batch / limit 'nr', to avoid large irq off latency
+ * needs some instrumenting to determine the common sizes used by
+ * important workloads (eg. DB2), and whether limiting the batch size
+ * will decrease performance.
+ *
+ * It seems like we're in the clear for the moment. Direct-IO is
+ * the main guy that batches up lots of get_user_pages, and even
+ * they are limited to 64-at-a-time which is not so many.
+ */
+ /*
+ * This doesn't prevent pagetable teardown, but does prevent
+ * the pagetables from being freed on sparc.
+ *
+ * So long as we atomically load page table pointers versus teardown,
+ * we can follow the address down to the the page and take a ref on it.
+ */
+ local_irq_disable();
+
+ pgdp = pgd_offset(mm, addr);
+ do {
+ pgd_t pgd = *pgdp;
+
+ next = pgd_addr_end(addr, end);
+ if (pgd_none(pgd))
+ goto slow;
+ if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+ goto slow;
+ } while (pgdp++, addr = next, addr != end);
+
+ local_irq_enable();
+
+ VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
+ return nr;
+
+ {
+ int ret;
+
+slow:
+ local_irq_enable();
+
+ /* Try to get the remaining pages with get_user_pages */
+ start += nr << PAGE_SHIFT;
+ pages += nr;
+
+ down_read(&mm->mmap_sem);
+ ret = get_user_pages(current, mm, start,
+ (end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
+ up_read(&mm->mmap_sem);
+
+ /* Have to be a bit careful with return values */
+ if (nr > 0) {
+ if (ret < 0)
+ ret = nr;
+ else
+ ret += nr;
+ }
+
+ return ret;
+ }
+}
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index a5f51b22fcbe..536412d8f416 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -236,6 +236,8 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
}
}
+struct kmem_cache *pgtable_cache __read_mostly;
+
static struct kmem_cache *tsb_caches[8] __read_mostly;
static const char *tsb_cache_names[8] = {
@@ -253,6 +255,15 @@ void __init pgtable_cache_init(void)
{
unsigned long i;
+ pgtable_cache = kmem_cache_create("pgtable_cache",
+ PAGE_SIZE, PAGE_SIZE,
+ 0,
+ _clear_page);
+ if (!pgtable_cache) {
+ prom_printf("pgtable_cache_init(): Could not create!\n");
+ prom_halt();
+ }
+
for (i = 0; i < 8; i++) {
unsigned long size = 8192 << i;
const char *name = tsb_cache_names[i];
diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig
index 09f1c7fad8bf..2ad73fb707b9 100644
--- a/arch/tile/configs/tilegx_defconfig
+++ b/arch/tile/configs/tilegx_defconfig
@@ -1479,7 +1479,6 @@ CONFIG_NFS_FSCACHE=y
CONFIG_NFS_USE_KERNEL_DNS=y
# CONFIG_NFS_USE_NEW_IDMAPPER is not set
CONFIG_NFSD=m
-CONFIG_NFSD_DEPRECATED=y
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h
index 739cfe0499d1..921dbeb8a70c 100644
--- a/arch/tile/include/asm/atomic.h
+++ b/arch/tile/include/asm/atomic.h
@@ -121,15 +121,6 @@ static inline int atomic_read(const atomic_t *v)
*/
#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0)
-/**
- * atomic_inc_not_zero - increment unless the number is zero
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1, so long as @v is non-zero.
- * Returns non-zero if @v was non-zero, and zero otherwise.
- */
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
/* Nonexistent functions intended to cause link errors. */
extern unsigned long __xchg_called_with_bad_pointer(void);
extern unsigned long __cmpxchg_called_with_bad_pointer(void);
@@ -186,9 +177,4 @@ extern unsigned long __cmpxchg_called_with_bad_pointer(void);
#include <asm/atomic_64.h>
#endif
-/* Provide the appropriate atomic_long_t definitions. */
-#ifndef __ASSEMBLY__
-#include <asm-generic/atomic-long.h>
-#endif
-
#endif /* _ASM_TILE_ATOMIC_H */
diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
index 92a8bee32311..c03349e0ca9f 100644
--- a/arch/tile/include/asm/atomic_32.h
+++ b/arch/tile/include/asm/atomic_32.h
@@ -11,7 +11,7 @@
* NON INFRINGEMENT. See the GNU General Public License for
* more details.
*
- * Do not include directly; use <asm/atomic.h>.
+ * Do not include directly; use <linux/atomic.h>.
*/
#ifndef _ASM_TILE_ATOMIC_32_H
@@ -21,7 +21,7 @@
#ifndef __ASSEMBLY__
-/* Tile-specific routines to support <asm/atomic.h>. */
+/* Tile-specific routines to support <linux/atomic.h>. */
int _atomic_xchg(atomic_t *v, int n);
int _atomic_xchg_add(atomic_t *v, int i);
int _atomic_xchg_add_unless(atomic_t *v, int a, int u);
@@ -81,18 +81,18 @@ static inline int atomic_add_return(int i, atomic_t *v)
}
/**
- * atomic_add_unless - add unless the number is already a given value
+ * __atomic_add_unless - add unless the number is already a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
smp_mb(); /* barrier for proper semantics */
- return _atomic_xchg_add_unless(v, a, u) != u;
+ return _atomic_xchg_add_unless(v, a, u);
}
/**
@@ -199,7 +199,7 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
{
diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h
index 1c1e60d8ccb6..27fe667fddfe 100644
--- a/arch/tile/include/asm/atomic_64.h
+++ b/arch/tile/include/asm/atomic_64.h
@@ -11,7 +11,7 @@
* NON INFRINGEMENT. See the GNU General Public License for
* more details.
*
- * Do not include directly; use <asm/atomic.h>.
+ * Do not include directly; use <linux/atomic.h>.
*/
#ifndef _ASM_TILE_ATOMIC_64_H
@@ -64,7 +64,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
return val;
}
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int guess, oldval = v->counter;
do {
@@ -73,7 +73,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
guess = oldval;
oldval = atomic_cmpxchg(v, guess, guess + a);
} while (guess != oldval);
- return oldval != u;
+ return oldval;
}
/* Now the true 64-bit operations. */
diff --git a/arch/tile/include/asm/bitops_32.h b/arch/tile/include/asm/bitops_32.h
index d31ab905cfa7..571b118bfd9b 100644
--- a/arch/tile/include/asm/bitops_32.h
+++ b/arch/tile/include/asm/bitops_32.h
@@ -16,7 +16,7 @@
#define _ASM_TILE_BITOPS_32_H
#include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
/* Tile-specific routines to support <asm/bitops.h>. */
diff --git a/arch/tile/include/asm/bitops_64.h b/arch/tile/include/asm/bitops_64.h
index 99615e8d2d8b..e9c8e381ee0e 100644
--- a/arch/tile/include/asm/bitops_64.h
+++ b/arch/tile/include/asm/bitops_64.h
@@ -16,7 +16,7 @@
#define _ASM_TILE_BITOPS_64_H
#include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
/* See <asm/bitops.h> for API comments. */
@@ -97,9 +97,6 @@ static inline int test_and_change_bit(unsigned nr,
return (oldval & mask) != 0;
}
-#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit((nr), (unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* _ASM_TILE_BITOPS_64_H */
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index 6be2246e015c..c6cddd7e8d51 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -112,8 +112,6 @@ struct pt_regs *get_pt_regs(struct pt_regs *);
/* Trace the current syscall. */
extern void do_syscall_trace(void);
-extern void show_regs(struct pt_regs *);
-
#define arch_has_single_step() (1)
/*
diff --git a/arch/tile/include/asm/spinlock_32.h b/arch/tile/include/asm/spinlock_32.h
index a8f2c6e31a87..a5e4208d34f9 100644
--- a/arch/tile/include/asm/spinlock_32.h
+++ b/arch/tile/include/asm/spinlock_32.h
@@ -17,7 +17,7 @@
#ifndef _ASM_TILE_SPINLOCK_32_H
#define _ASM_TILE_SPINLOCK_32_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/page.h>
#include <asm/system.h>
#include <linux/compiler.h>
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index 72ade79b621b..fc94607f0bd5 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -21,7 +21,7 @@
#include <asm/ptrace.h>
#include <asm/thread_info.h>
#include <asm/irqflags.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/asm-offsets.h>
#include <hv/hypervisor.h>
#include <arch/abi.h>
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c
index f68df69f1f67..28fa6ece9d3a 100644
--- a/arch/tile/kernel/module.c
+++ b/arch/tile/kernel/module.c
@@ -98,25 +98,6 @@ void module_free(struct module *mod, void *module_region)
*/
}
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
-int apply_relocate(Elf_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- pr_err("module %s: .rel relocation unsupported\n", me->name);
- return -ENOEXEC;
-}
-
#ifdef __tilegx__
/*
* Validate that the high 16 bits of "value" is just the sign-extension of
@@ -249,15 +230,3 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
}
return 0;
}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- /* FIXME: perhaps remove the "writable" bit from the TLB? */
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 6cdc9ba55fe0..5f85d8b34dbb 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -553,8 +553,7 @@ static void __init setup_bootmem_allocator(void)
#ifdef CONFIG_KEXEC
if (crashk_res.start != crashk_res.end)
- reserve_bootmem(crashk_res.start,
- crashk_res.end - crashk_res.start + 1, 0);
+ reserve_bootmem(crashk_res.start, resource_size(&crashk_res), 0);
#endif
}
diff --git a/arch/tile/kvm/Kconfig b/arch/tile/kvm/Kconfig
index b88f9c047781..669fcdba31ea 100644
--- a/arch/tile/kvm/Kconfig
+++ b/arch/tile/kvm/Kconfig
@@ -33,6 +33,5 @@ config KVM
If unsure, say N.
source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
endif # VIRTUALIZATION
diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c
index 46570211df52..771b251b409d 100644
--- a/arch/tile/lib/atomic_32.c
+++ b/arch/tile/lib/atomic_32.c
@@ -17,7 +17,7 @@
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/mm.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/futex.h>
#include <arch/chip.h>
diff --git a/arch/tile/lib/atomic_asm_32.S b/arch/tile/lib/atomic_asm_32.S
index 24448734f6f1..1f75a2a56101 100644
--- a/arch/tile/lib/atomic_asm_32.S
+++ b/arch/tile/lib/atomic_asm_32.S
@@ -70,7 +70,7 @@
*/
#include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/page.h>
#include <asm/processor.h>
diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86
index 8aae429a56e2..d31ecf346b4e 100644
--- a/arch/um/Kconfig.x86
+++ b/arch/um/Kconfig.x86
@@ -1,3 +1,5 @@
+mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
+
source "arch/um/Kconfig.common"
menu "UML-specific options"
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 25e1965df7ce..d4191fe1cede 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -543,11 +543,10 @@ int parse_chan_pair(char *str, struct line *line, int device,
const struct chan_opts *opts, char **error_out)
{
struct list_head *chans = &line->chan_list;
- struct chan *new, *chan;
+ struct chan *new;
char *in, *out;
if (!list_empty(chans)) {
- chan = list_entry(chans->next, struct chan, list);
free_chan(chans, 0);
INIT_LIST_HEAD(chans);
}
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 93f227a25ba4..9cbb426c0b91 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -186,7 +186,11 @@ static int absolutize(char *to, int size, char *from)
strcat(to, "/");
strcat(to, from);
}
- chdir(save_cwd);
+ if (chdir(save_cwd)) {
+ cow_printf("absolutize : Can't cd to '%s' - "
+ "errno = %d\n", save_cwd, errno);
+ return -1;
+ }
return 0;
}
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index b56f8e0196a9..84dce3fc590c 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -32,7 +32,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
{
struct dog_data data;
int in_fds[2], out_fds[2], pid, n, err;
- char pid_buf[sizeof("nnnnn\0")], c;
+ char pid_buf[sizeof("nnnnnnn\0")], c;
char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
NULL };
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 35dd0b86401a..d51c404239a8 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -176,10 +176,9 @@ void line_flush_buffer(struct tty_struct *tty)
{
struct line *line = tty->driver_data;
unsigned long flags;
- int err;
spin_lock_irqsave(&line->lock, flags);
- err = flush_buffer(line);
+ flush_buffer(line);
spin_unlock_irqrestore(&line->lock, flags);
}
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 47d0c37897d5..22745b47c829 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -262,6 +262,15 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uml_net_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ uml_net_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
static void uml_net_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -364,6 +373,9 @@ static const struct net_device_ops uml_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = uml_net_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = uml_net_poll_controller,
+#endif
};
/*
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 9415dd9e63ef..520118888f16 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -228,7 +228,10 @@ static void change(char *dev, char *what, unsigned char *addr,
"buffer\n");
pid = change_tramp(argv, output, output_len);
- if (pid < 0) return;
+ if (pid < 0) {
+ kfree(output);
+ return;
+ }
if (output != NULL) {
printk("%s", output);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index a1c2d2c98a94..cbacfc4e63e6 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -102,7 +102,7 @@ static int slip_tramp(char **argv, int fd)
"buffer\n");
os_kill_process(pid, 1);
err = -ENOMEM;
- goto out_free;
+ goto out_close;
}
close(fds[1]);
@@ -112,7 +112,6 @@ static int slip_tramp(char **argv, int fd)
err = helper_wait(pid);
close(fds[0]);
-out_free:
kfree(output);
return err;
diff --git a/arch/um/include/asm/delay.h b/arch/um/include/asm/delay.h
index c71e32b6741e..8a5576d8eda5 100644
--- a/arch/um/include/asm/delay.h
+++ b/arch/um/include/asm/delay.h
@@ -1,20 +1,18 @@
#ifndef __UM_DELAY_H
#define __UM_DELAY_H
-#define MILLION 1000000
-
/* Undefined on purpose */
extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long usecs);
extern void __delay(unsigned long loops);
#define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
__bad_udelay() : __udelay(n))
-/* It appears that ndelay is not used at all for UML, and has never been
- * implemented. */
-extern void __unimplemented_ndelay(void);
-#define ndelay(n) __unimplemented_ndelay()
+#define ndelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
+ __bad_ndelay() : __ndelay(n))
#endif
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index b7c5bab9bd77..ae084ad1a3a0 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -47,8 +47,6 @@ extern int get_fpregs(struct user_i387_struct __user *buf,
extern int set_fpregs(struct user_i387_struct __user *buf,
struct task_struct *child);
-extern void show_regs(struct pt_regs *regs);
-
extern int arch_copy_tls(struct task_struct *new);
extern void clear_flushed_tls(struct task_struct *task);
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 09bd7b585726..939a4a67f0fd 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -38,7 +38,6 @@ void flush_thread(void)
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
- set_fs(USER_DS);
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
}
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 869bec9f2516..4d93dff6b371 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -20,9 +20,8 @@ static void kill_off_processes(void)
os_kill_ptraced_process(userspace_pid[0], 1);
else {
struct task_struct *p;
- int pid, me;
+ int pid;
- me = os_getpid();
for_each_process(p) {
if (p->mm == NULL)
continue;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index d66f0388f091..b33f4dfe7ae5 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,10 +3,12 @@
# Licensed under the GPL
#
-obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
+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/
+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
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 608784d4ec57..953323799381 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -14,16 +14,11 @@
#include "mem_user.h"
#include <kern_constants.h>
-/* Use the one from the kernel - the host may miss it, if having old headers. */
-#if UM_ELF_CLASS == UM_ELFCLASS32
typedef Elf32_auxv_t elf_auxv_t;
-#else
-typedef Elf64_auxv_t elf_auxv_t;
-#endif
/* These are initialized very early in boot and never changed */
char * elf_aux_platform;
-long elf_aux_hwcap;
+extern long elf_aux_hwcap;
unsigned long vsyscall_ehdr;
unsigned long vsyscall_end;
unsigned long __kernel_vsyscall;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index b6b1096152aa..feff22d64672 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -28,14 +28,14 @@ static int helper_child(void *arg)
{
struct helper_data *data = arg;
char **argv = data->argv;
- int err;
+ int err, ret;
if (data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
err = execvp_noalloc(data->buf, argv[0], argv);
/* If the exec succeeds, we don't get here */
- write(data->fd, &err, sizeof(err));
+ CATCH_EINTR(ret = write(data->fd, &err, sizeof(err)));
return 0;
}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index fb2a97a75fb1..8471b817d94f 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -21,6 +21,8 @@
#define STACKSIZE (8 * 1024 * 1024)
#define THREAD_NAME_LEN (256)
+long elf_aux_hwcap;
+
static void set_stklim(void)
{
struct rlimit lim;
@@ -143,7 +145,9 @@ int __init main(int argc, char **argv, char **envp)
install_fatal_handler(SIGINT);
install_fatal_handler(SIGTERM);
+#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
scan_elf_aux(envp);
+#endif
do_uml_initcalls();
ret = linux_main(argc, argv);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index e696144d2be3..62878cf1d33f 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -176,7 +176,7 @@ static int __init make_tempfile(const char *template, char **out_tempname,
find_tempdir();
if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN))
- return -1;
+ goto out;
if (template[0] != '/')
strcpy(tempname, tempdir);
@@ -191,13 +191,15 @@ static int __init make_tempfile(const char *template, char **out_tempname,
}
if (do_unlink && (unlink(tempname) < 0)) {
perror("unlink");
- goto out;
+ goto close;
}
if (out_tempname) {
*out_tempname = tempname;
} else
free(tempname);
return fd;
+close:
+ close(fd);
out:
free(tempname);
return -1;
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 05f5ea8e83d2..45ffe46871e0 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -113,3 +113,8 @@ EXPORT_SYMBOL(__stack_smash_handler);
extern long __guard __attribute__((weak));
EXPORT_SYMBOL(__guard);
+
+#ifdef _FORTIFY_SOURCE
+extern int __sprintf_chk(char *str, int flag, size_t strlen, const char *format);
+EXPORT_SYMBOL(__sprintf_chk);
+#endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index b1da91c1b200..3923cfb87649 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -4,11 +4,12 @@
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
+ sys_call_table.o tls.o atomic64_cx8_32.o mem.o
obj-$(CONFIG_BINFMT_ELF) += elfcore.o
-subarch-obj-y = lib/semaphore_32.o lib/string_32.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
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index d964a4111ac6..42305551d204 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -105,6 +105,8 @@ extern unsigned long __kernel_vsyscall;
#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.
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index d623e074f41d..f3fe1a688f7e 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,29 +1,60 @@
+/*
+ * 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 time)
+void __delay(unsigned long loops)
{
- /* Stolen from the i386 __loop_delay */
- int d0;
- __asm__ __volatile__(
- "\tjmp 1f\n"
+ asm volatile(
+ "test %0,%0\n"
+ "jz 3f\n"
+ "jmp 1f\n"
+
".align 16\n"
- "1:\tjmp 2f\n"
+ "1: jmp 2f\n"
+
".align 16\n"
- "2:\tdecl %0\n\tjns 2b"
- :"=&a" (d0)
- :"0" (time));
+ "2: dec %0\n"
+ " jnz 2b\n"
+ "3: dec %0\n"
+
+ : /* we don't need output */
+ : "a" (loops)
+ );
}
+EXPORT_SYMBOL(__delay);
-void __udelay(unsigned long usecs)
+inline void __const_udelay(unsigned long xloops)
{
- int i, n;
+ int d0;
- n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++)
- cpu_relax();
+ 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-i386/mem.c b/arch/um/sys-i386/mem.c
new file mode 100644
index 000000000000..639900a6fde9
--- /dev/null
+++ b/arch/um/sys-i386/mem.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.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/mm.h>
+#include <asm/page.h>
+#include <asm/mman.h>
+
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+ if (!FIXADDR_USER_START)
+ return 0;
+
+ gate_vma.vm_mm = NULL;
+ gate_vma.vm_start = FIXADDR_USER_START;
+ gate_vma.vm_end = FIXADDR_USER_END;
+ gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+ gate_vma.vm_page_prot = __P101;
+
+ /*
+ * Make sure the vDSO gets into every core dump.
+ * Dumping its contents makes post-mortem fully interpretable later
+ * without matching up the same kernel and hardware config to see
+ * what PC values meant.
+ */
+ gate_vma.vm_flags |= VM_ALWAYSDUMP;
+
+ return 0;
+}
+__initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+ return FIXADDR_USER_START ? &gate_vma : NULL;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+ if (!FIXADDR_USER_START)
+ return 0;
+
+ if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
+ return 1;
+
+ return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+ struct vm_area_struct *vma = get_gate_vma(mm);
+
+ if (!vma)
+ return 0;
+
+ return (addr >= vma->vm_start) && (addr < vma->vm_end);
+}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 129647375a6c..89a46626bfd8 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -58,7 +58,7 @@ static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
unsigned long ret = 0xffff0000;
int i;
-#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16)
for (i = 0; i < 8; i++) {
if (twd & 0x1) {
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c1ea9eb04466..bd4d1d3ba919 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -4,12 +4,14 @@
# Licensed under the GPL
#
-obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
+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_64.o
+ lib/rwsem.o
subarch-obj-$(CONFIG_MODULES) += kernel/module.o
ldt-y = ../sys-i386/ldt.o
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h
index d6d5af376251..11a2bfb38859 100644
--- a/arch/um/sys-x86_64/asm/elf.h
+++ b/arch/um/sys-x86_64/asm/elf.h
@@ -119,4 +119,14 @@ extern long elf_aux_hwcap;
#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/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index dee5be66da82..f3fe1a688f7e 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -1,30 +1,60 @@
/*
- * Copyright 2003 PathScale, Inc.
- * Copied from arch/x86_64
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ * Mostly copied from arch/x86/lib/delay.c
*
- * Licensed under the GPL
+ * 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/processor.h>
#include <asm/param.h>
void __delay(unsigned long loops)
{
- unsigned long i;
+ asm volatile(
+ "test %0,%0\n"
+ "jz 3f\n"
+ "jmp 1f\n"
- for(i = 0; i < loops; i++)
- cpu_relax();
+ ".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);
-void __udelay(unsigned long usecs)
+inline void __const_udelay(unsigned long xloops)
{
- unsigned long i, n;
+ int d0;
- n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++)
- cpu_relax();
+ 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/mem.c b/arch/um/sys-x86_64/mem.c
index 3f8df8abf347..546518727a73 100644
--- a/arch/um/sys-x86_64/mem.c
+++ b/arch/um/sys-x86_64/mem.c
@@ -1,16 +1,26 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
#include "linux/mm.h"
#include "asm/page.h"
#include "asm/mman.h"
-unsigned long vm_stack_flags = __VM_STACK_FLAGS;
-unsigned long vm_stack_flags32 = __VM_STACK_FLAGS;
-unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS;
-unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS;
-unsigned long vm_force_exec32 = PROT_EXEC;
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_mm && vma->vm_start == um_vdso_addr)
+ return "[vdso]";
+
+ return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+ return NULL;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+ return 0;
+}
+int in_gate_area_no_mm(unsigned long addr)
+{
+ return 0;
+}
diff --git a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
index 3213edfa7888..3978e55132d2 100644
--- a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
+++ b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
@@ -7,27 +7,9 @@
#ifndef __VM_FLAGS_X86_64_H
#define __VM_FLAGS_X86_64_H
-#define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
- VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \
- VM_MAYEXEC)
-
-extern unsigned long vm_stack_flags, vm_stack_flags32;
-extern unsigned long vm_data_default_flags, vm_data_default_flags32;
-extern unsigned long vm_force_exec32;
-
-#ifdef TIF_IA32
-#define VM_DATA_DEFAULT_FLAGS \
- (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \
- vm_data_default_flags)
-
-#define VM_STACK_DEFAULT_FLAGS \
- (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags)
-#endif
-
-#define VM_DATA_DEFAULT_FLAGS vm_data_default_flags
-
-#define VM_STACK_DEFAULT_FLAGS vm_stack_flags
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
+ VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#endif
diff --git a/arch/um/sys-x86_64/vdso/Makefile b/arch/um/sys-x86_64/vdso/Makefile
new file mode 100644
index 000000000000..5dffe6d46686
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/Makefile
@@ -0,0 +1,90 @@
+#
+# Building vDSO images for x86.
+#
+
+VDSO64-y := y
+
+vdso-install-$(VDSO64-y) += vdso.so
+
+
+# files to link into the vdso
+vobjs-y := vdso-note.o um_vdso.o
+
+# files to link into kernel
+obj-$(VDSO64-y) += vdso.o vma.o
+
+vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
+
+$(obj)/vdso.o: $(obj)/vdso.so
+
+targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
+
+export CPPFLAGS_vdso.lds += -P -C
+
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
+ -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+
+$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
+
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
+ $(call if_changed,vdso)
+
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+ $(call if_changed,objcopy)
+
+#
+# Don't omit frame pointers for ease of userspace debugging, but do
+# optimize sibling calls.
+#
+CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
+ $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
+ -fno-omit-frame-pointer -foptimize-sibling-calls
+
+$(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
+
+targets += vdso-syms.lds
+obj-$(VDSO64-y) += vdso-syms.lds
+
+#
+# Match symbols in the DSO that look like VDSO*; produce a file of constants.
+#
+sed-vdsosym := -e 's/^00*/0/' \
+ -e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+ $(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
+endef
+
+$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
+ $(call if_changed,vdsosym)
+
+#
+# The DSO images are built using a special linker script.
+#
+quiet_cmd_vdso = VDSO $@
+ cmd_vdso = $(CC) -nostdlib -o $@ \
+ $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
+ -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+ sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+GCOV_PROFILE := n
+
+#
+# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
+#
+quiet_cmd_vdso_install = INSTALL $@
+ cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
+ @mkdir -p $(MODLIB)/vdso
+ $(call cmd,vdso_install)
+
+PHONY += vdso_install $(vdso-install-y)
+vdso_install: $(vdso-install-y)
diff --git a/arch/um/sys-x86_64/vdso/checkundef.sh b/arch/um/sys-x86_64/vdso/checkundef.sh
new file mode 100644
index 000000000000..7ee90a9b549d
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/checkundef.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+$nm "$file" | grep '^ *U' > /dev/null 2>&1
+if [ $? -eq 1 ]; then
+ exit 0
+else
+ echo "$file: undefined symbols found" >&2
+ exit 1
+fi
diff --git a/arch/um/sys-x86_64/vdso/um_vdso.c b/arch/um/sys-x86_64/vdso/um_vdso.c
new file mode 100644
index 000000000000..7c441b59d375
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/um_vdso.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.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.
+ *
+ * This vDSO turns all calls into a syscall so that UML can trap them.
+ */
+
+
+/* Disable profiling for userspace code */
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/time.h>
+#include <linux/getcpu.h>
+#include <asm/unistd.h>
+
+int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+ long ret;
+
+ asm("syscall" : "=a" (ret) :
+ "0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
+
+ return ret;
+}
+int clock_gettime(clockid_t, struct timespec *)
+ __attribute__((weak, alias("__vdso_clock_gettime")));
+
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ long ret;
+
+ asm("syscall" : "=a" (ret) :
+ "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+
+ return ret;
+}
+int gettimeofday(struct timeval *, struct timezone *)
+ __attribute__((weak, alias("__vdso_gettimeofday")));
+
+time_t __vdso_time(time_t *t)
+{
+ long secs;
+
+ asm volatile("syscall"
+ : "=a" (secs)
+ : "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
+
+ return secs;
+}
+int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
+
+long
+__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
+{
+ /*
+ * UML does not support SMP, we can cheat here. :)
+ */
+
+ if (cpu)
+ *cpu = 0;
+ if (node)
+ *node = 0;
+
+ return 0;
+}
+
+long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+ __attribute__((weak, alias("__vdso_getcpu")));
diff --git a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
new file mode 100644
index 000000000000..634a2cf62046
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
@@ -0,0 +1,64 @@
+/*
+ * Linker script for vDSO. This is an ELF shared object prelinked to
+ * its virtual address, and with only one read-only segment.
+ * This script controls its layout.
+ */
+
+SECTIONS
+{
+ . = VDSO_PRELINK + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note.*) } :text :note
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ .rodata : { *(.rodata*) } :text
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ }
+
+ .altinstructions : { *(.altinstructions) }
+ .altinstr_replacement : { *(.altinstr_replacement) }
+
+ /*
+ * Align the actual code well away from the non-instruction data.
+ * This is the best thing for the I-cache.
+ */
+ . = ALIGN(0x100);
+
+ .text : { *(.text*) } :text =0x90909090
+}
+
+/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME 0x6474e550
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+ text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME;
+}
diff --git a/arch/um/sys-x86_64/vdso/vdso-note.S b/arch/um/sys-x86_64/vdso/vdso-note.S
new file mode 100644
index 000000000000..79a071e4357e
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso-note.S
@@ -0,0 +1,12 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+ .long LINUX_VERSION_CODE
+ELFNOTE_END
diff --git a/arch/um/sys-x86_64/vdso/vdso.S b/arch/um/sys-x86_64/vdso/vdso.S
new file mode 100644
index 000000000000..ec82c1686bd6
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso.S
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+ .globl vdso_start, vdso_end
+vdso_start:
+ .incbin "arch/um/sys-x86_64/vdso/vdso.so"
+vdso_end:
+
+__FINIT
diff --git a/arch/um/sys-x86_64/vdso/vdso.lds.S b/arch/um/sys-x86_64/vdso/vdso.lds.S
new file mode 100644
index 000000000000..b96b2677cad8
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso.lds.S
@@ -0,0 +1,32 @@
+/*
+ * Linker script for 64-bit vDSO.
+ * We #include the file to define the layout details.
+ * Here we only choose the prelinked virtual address.
+ *
+ * This file defines the version script giving the user-exported symbols in
+ * the DSO. We can define local symbols here called VDSO* to make their
+ * values visible using the asm-x86/vdso.h macros from the kernel proper.
+ */
+
+#define VDSO_PRELINK 0xffffffffff700000
+#include "vdso-layout.lds.S"
+
+/*
+ * This controls what userland symbols we export from the vDSO.
+ */
+VERSION {
+ LINUX_2.6 {
+ global:
+ clock_gettime;
+ __vdso_clock_gettime;
+ gettimeofday;
+ __vdso_gettimeofday;
+ getcpu;
+ __vdso_getcpu;
+ time;
+ __vdso_time;
+ local: *;
+ };
+}
+
+VDSO64_PRELINK = VDSO_PRELINK;
diff --git a/arch/um/sys-x86_64/vdso/vma.c b/arch/um/sys-x86_64/vdso/vma.c
new file mode 100644
index 000000000000..9495c8d0ce37
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vma.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.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/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <linux/init.h>
+
+unsigned int __read_mostly vdso_enabled = 1;
+unsigned long um_vdso_addr;
+
+extern unsigned long task_size;
+extern char vdso_start[], vdso_end[];
+
+static struct page **vdsop;
+
+static int __init init_vdso(void)
+{
+ struct page *um_vdso;
+
+ BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
+
+ um_vdso_addr = task_size - PAGE_SIZE;
+
+ vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
+ if (!vdsop)
+ goto oom;
+
+ um_vdso = alloc_page(GFP_KERNEL);
+ if (!um_vdso) {
+ kfree(vdsop);
+
+ goto oom;
+ }
+
+ copy_page(page_address(um_vdso), vdso_start);
+ *vdsop = um_vdso;
+
+ return 0;
+
+oom:
+ printk(KERN_ERR "Cannot allocate vdso\n");
+ vdso_enabled = 0;
+
+ return -ENOMEM;
+}
+subsys_initcall(init_vdso);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+ int err;
+ struct mm_struct *mm = current->mm;
+
+ if (!vdso_enabled)
+ return 0;
+
+ down_write(&mm->mmap_sem);
+
+ err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
+ VM_READ|VM_EXEC|
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+ VM_ALWAYSDUMP,
+ vdsop);
+
+ up_write(&mm->mmap_sem);
+
+ return err;
+}
diff --git a/arch/unicore32/kernel/module.c b/arch/unicore32/kernel/module.c
index 3e5a38d71a1e..8fbe8577f5e6 100644
--- a/arch/unicore32/kernel/module.c
+++ b/arch/unicore32/kernel/module.c
@@ -37,19 +37,6 @@ void *module_alloc(unsigned long size)
return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
}
-void module_free(struct module *module, void *region)
-{
- vfree(region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
int
apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
unsigned int relindex, struct module *module)
@@ -128,25 +115,3 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
}
return 0;
}
-
-int
-apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec,
- struct module *module)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
- module->name);
- return -ENOEXEC;
-}
-
-int
-module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
- struct module *module)
-{
- return 0;
-}
-
-void
-module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 37357a599dca..153aa6f78299 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -20,6 +20,7 @@ config X86
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_IDE
select HAVE_OPROFILE
+ select HAVE_PCSPKR_PLATFORM
select HAVE_PERF_EVENTS
select HAVE_IRQ_WORK
select HAVE_IOREMAP_PROT
@@ -70,6 +71,7 @@ config X86
select IRQ_FORCED_THREADING
select USE_GENERIC_SMP_HELPERS if SMP
select HAVE_BPF_JIT if (X86_64 && NET)
+ select CLKEVT_I8253
config INSTRUCTION_DECODER
def_bool (KPROBES || PERF_EVENTS)
@@ -93,6 +95,10 @@ config CLOCKSOURCE_WATCHDOG
config GENERIC_CLOCKEVENTS
def_bool y
+config ARCH_CLOCKSOURCE_DATA
+ def_bool y
+ depends on X86_64
+
config GENERIC_CLOCKEVENTS_BROADCAST
def_bool y
depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
@@ -384,12 +390,21 @@ config X86_INTEL_CE
This option compiles in support for the CE4100 SOC for settop
boxes and media devices.
+config X86_INTEL_MID
+ bool "Intel MID platform support"
+ depends on X86_32
+ depends on X86_EXTENDED_PLATFORM
+ ---help---
+ Select to build a kernel capable of supporting Intel MID platform
+ systems which do not have the PCI legacy interfaces (Moorestown,
+ Medfield). If you are building for a PC class system say N here.
+
+if X86_INTEL_MID
+
config X86_MRST
bool "Moorestown MID platform"
depends on PCI
depends on PCI_GOANY
- depends on X86_32
- depends on X86_EXTENDED_PLATFORM
depends on X86_IO_APIC
select APB_TIMER
select I2C
@@ -404,6 +419,8 @@ config X86_MRST
nor standard legacy replacement devices/features. e.g. Moorestown does
not contain i8259, i8254, HPET, legacy BIOS, most of the io ports.
+endif
+
config X86_RDC321X
bool "RDC R-321x SoC"
depends on X86_32
@@ -512,6 +529,18 @@ menuconfig PARAVIRT_GUEST
if PARAVIRT_GUEST
+config PARAVIRT_TIME_ACCOUNTING
+ bool "Paravirtual steal time accounting"
+ select PARAVIRT
+ default n
+ ---help---
+ Select this option to enable fine granularity task steal time
+ accounting. Time spent executing other tasks in parallel with
+ the current vCPU is discounted from the vCPU power. To account for
+ that, there can be a small performance impact.
+
+ If in doubt, say N here.
+
source "arch/x86/xen/Kconfig"
config KVM_CLOCK
@@ -617,6 +646,7 @@ config HPET_EMULATE_RTC
config APB_TIMER
def_bool y if MRST
prompt "Langwell APB Timer Support" if X86_MRST
+ select DW_APB_TIMER
help
APB timer is the replacement for 8254, HPET on X86 MID platforms.
The APBT provides a stable time base on SMP
@@ -680,33 +710,6 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
Calgary anyway, pass 'iommu=calgary' on the kernel command line.
If unsure, say Y.
-config AMD_IOMMU
- bool "AMD IOMMU support"
- select SWIOTLB
- select PCI_MSI
- select PCI_IOV
- depends on X86_64 && PCI && ACPI
- ---help---
- With this option you can enable support for AMD IOMMU hardware in
- your system. An IOMMU is a hardware component which provides
- remapping of DMA memory accesses from devices. With an AMD IOMMU you
- can isolate the the DMA memory of different devices and protect the
- system from misbehaving device drivers or hardware.
-
- You can find out if your system has an AMD IOMMU if you look into
- your BIOS for an option to enable it or if you have an IVRS ACPI
- table.
-
-config AMD_IOMMU_STATS
- bool "Export AMD IOMMU statistics to debugfs"
- depends on AMD_IOMMU
- select DEBUG_FS
- ---help---
- This option enables code in the AMD IOMMU driver to collect various
- statistics about whats happening in the driver and exports that
- information to userspace via debugfs.
- If unsure, say N.
-
# need this always selected by IOMMU for the VIA workaround
config SWIOTLB
def_bool y if X86_64
@@ -720,9 +723,6 @@ config SWIOTLB
config IOMMU_HELPER
def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU)
-config IOMMU_API
- def_bool (AMD_IOMMU || DMAR)
-
config MAXSMP
bool "Enable Maximum number of SMP Processors and NUMA Nodes"
depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
@@ -1737,8 +1737,8 @@ menuconfig APM
machines with more than one CPU.
In order to use APM, you will need supporting software. For location
- and more information, read <file:Documentation/power/pm.txt> and the
- Battery Powered Linux mini-HOWTO, available from
+ and more information, read <file:Documentation/power/apm-acpi.txt>
+ and the Battery Powered Linux mini-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
This driver does not spin down disk drives (see the hdparm(8)
@@ -1942,55 +1942,6 @@ config PCI_CNB20LE_QUIRK
You should say N unless you know you need this.
-config DMAR
- bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
- depends on PCI_MSI && ACPI && EXPERIMENTAL
- help
- DMA remapping (DMAR) devices support enables independent address
- translations for Direct Memory Access (DMA) from devices.
- These DMA remapping devices are reported via ACPI tables
- and include PCI device scope covered by these DMA
- remapping devices.
-
-config DMAR_DEFAULT_ON
- def_bool y
- prompt "Enable DMA Remapping Devices by default"
- depends on DMAR
- 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. It is
- recommended you say N here while the DMAR code remains
- experimental.
-
-config DMAR_BROKEN_GFX_WA
- bool "Workaround broken graphics drivers (going away soon)"
- depends on DMAR && BROKEN
- ---help---
- Current Graphics drivers tend to use physical address
- for DMA and avoid using DMA APIs. Setting this config
- option permits the IOMMU driver to set a unity map for
- all the OS-visible memory. Hence the driver can continue
- to use physical addresses for DMA, at least until this
- option is removed in the 2.6.32 kernel.
-
-config DMAR_FLOPPY_WA
- def_bool y
- depends on DMAR
- ---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
- bool "Support for Interrupt Remapping (EXPERIMENTAL)"
- depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
- ---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.
-
source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig"
@@ -2073,11 +2024,44 @@ config OLPC
Add support for detecting the unique features of the OLPC
XO hardware.
-config OLPC_XO1
- tristate "OLPC XO-1 support"
- depends on OLPC && MFD_CS5535
- ---help---
- Add support for non-essential features of the OLPC XO-1 laptop.
+config OLPC_XO1_PM
+ bool "OLPC XO-1 Power Management"
+ depends on OLPC && MFD_CS5535 && PM_SLEEP
+ select MFD_CORE
+ ---help---
+ Add support for poweroff and suspend of the OLPC XO-1 laptop.
+
+config OLPC_XO1_RTC
+ bool "OLPC XO-1 Real Time Clock"
+ depends on OLPC_XO1_PM && RTC_DRV_CMOS
+ ---help---
+ Add support for the XO-1 real time clock, which can be used as a
+ programmable wakeup source.
+
+config OLPC_XO1_SCI
+ bool "OLPC XO-1 SCI extras"
+ depends on OLPC && OLPC_XO1_PM
+ select POWER_SUPPLY
+ select GPIO_CS5535
+ select MFD_CORE
+ ---help---
+ Add support for SCI-based features of the OLPC XO-1 laptop:
+ - EC-driven system wakeups
+ - Power button
+ - Ebook switch
+ - Lid switch
+ - AC adapter status updates
+ - Battery status updates
+
+config OLPC_XO15_SCI
+ bool "OLPC XO-1.5 SCI extras"
+ depends on OLPC && ACPI
+ select POWER_SUPPLY
+ ---help---
+ Add support for SCI-based features of the OLPC XO-1.5 laptop:
+ - EC-driven system wakeups
+ - AC adapter status updates
+ - Battery status updates
endif # X86_32
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 6a7cfdf8ff69..e3ca7e0d858c 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -312,6 +312,9 @@ config X86_CMPXCHG
config CMPXCHG_LOCAL
def_bool X86_64 || (X86_32 && !M386)
+config CMPXCHG_DOUBLE
+ def_bool y
+
config X86_L1_CACHE_SHIFT
int
default "7" if MPENTIUM4 || MPSC
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index f7cb086b4add..95365a82b6a0 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -9,12 +9,6 @@
# Changed by many, many contributors over the years.
#
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
-# the default of FLOPPY is used by 'build'.
-
-ROOT_DEV := CURRENT
-
# If you want to preset the SVGA mode, uncomment the next line and
# set SVGA_MODE to whatever number you want.
# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
@@ -75,8 +69,7 @@ GCOV_PROFILE := n
$(obj)/bzImage: asflags-y := $(SVGA_MODE)
quiet_cmd_image = BUILD $@
-cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \
- $(ROOT_DEV) > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@
$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index ee3a4ea923ac..fdc60a0b3c20 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -130,7 +130,7 @@ static void die(const char * str, ...)
static void usage(void)
{
- die("Usage: build setup system [rootdev] [> image]");
+ die("Usage: build setup system [> image]");
}
int main(int argc, char ** argv)
@@ -138,39 +138,14 @@ int main(int argc, char ** argv)
unsigned int i, sz, setup_sectors;
int c;
u32 sys_size;
- u8 major_root, minor_root;
struct stat sb;
FILE *file;
int fd;
void *kernel;
u32 crc = 0xffffffffUL;
- if ((argc < 3) || (argc > 4))
+ if (argc != 3)
usage();
- if (argc > 3) {
- if (!strcmp(argv[3], "CURRENT")) {
- if (stat("/", &sb)) {
- perror("/");
- die("Couldn't stat /");
- }
- major_root = major(sb.st_dev);
- minor_root = minor(sb.st_dev);
- } else if (strcmp(argv[3], "FLOPPY")) {
- if (stat(argv[3], &sb)) {
- perror(argv[3]);
- die("Couldn't stat root device.");
- }
- major_root = major(sb.st_rdev);
- minor_root = minor(sb.st_rdev);
- } else {
- major_root = 0;
- minor_root = 0;
- }
- } else {
- major_root = DEFAULT_MAJOR_ROOT;
- minor_root = DEFAULT_MINOR_ROOT;
- }
- fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
/* Copy the setup code */
file = fopen(argv[1], "r");
@@ -193,8 +168,8 @@ int main(int argc, char ** argv)
memset(buf+c, 0, i-c);
/* Set the default root device */
- buf[508] = minor_root;
- buf[509] = major_root;
+ buf[508] = DEFAULT_MINOR_ROOT;
+ buf[509] = DEFAULT_MAJOR_ROOT;
fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c
index 7a6e68e4f748..976aa64d9a20 100644
--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c
+++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c
@@ -245,7 +245,7 @@ static int ghash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
crypto_ahash_set_flags(tfm, crypto_ahash_get_flags(child)
& CRYPTO_TFM_RES_MASK);
- return 0;
+ return err;
}
static int ghash_async_init_tfm(struct crypto_tfm *tfm)
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 588a7aa937e1..65577698cab2 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -127,15 +127,17 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);
current->state = TASK_INTERRUPTIBLE;
schedule();
+
set_restore_sigmask();
return -ERESTARTNOHAND;
}
@@ -279,10 +281,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
goto badframe;
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 (ia32_restore_sigcontext(regs, &frame->sc, &ax))
goto badframe;
@@ -308,10 +307,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
goto badframe;
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 (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
goto badframe;
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index c1870dddd322..a0e866d233ee 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -143,7 +143,7 @@ ENTRY(ia32_sysenter_target)
CFI_REL_OFFSET rip,0
pushq_cfi %rax
cld
- SAVE_ARGS 0,0,1
+ SAVE_ARGS 0,1,0
/* no need to do an access_ok check here because rbp has been
32bit zero extended */
1: movl (%rbp),%ebp
@@ -173,7 +173,7 @@ sysexit_from_sys_call:
andl $~0x200,EFLAGS-R11(%rsp)
movl RIP-R11(%rsp),%edx /* User %eip */
CFI_REGISTER rip,rdx
- RESTORE_ARGS 1,24,1,1,1,1
+ RESTORE_ARGS 0,24,0,0,0,0
xorq %r8,%r8
xorq %r9,%r9
xorq %r10,%r10
@@ -289,7 +289,7 @@ ENTRY(ia32_cstar_target)
* disabled irqs and here we enable it straight after entry:
*/
ENABLE_INTERRUPTS(CLBR_NONE)
- SAVE_ARGS 8,1,1
+ SAVE_ARGS 8,0,0
movl %eax,%eax /* zero extension */
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
@@ -328,7 +328,7 @@ cstar_dispatch:
jnz sysretl_audit
sysretl_from_sys_call:
andl $~TS_COMPAT,TI_status(%r10)
- RESTORE_ARGS 1,-ARG_SKIP,1,1,1
+ RESTORE_ARGS 0,-ARG_SKIP,0,0,0
movl RIP-ARGOFFSET(%rsp),%ecx
CFI_REGISTER rip,rcx
movl EFLAGS-ARGOFFSET(%rsp),%r11d
@@ -419,7 +419,7 @@ ENTRY(ia32_syscall)
cld
/* note the registers are not zero extended to the sf.
this could be a problem. */
- SAVE_ARGS 0,0,1
+ SAVE_ARGS 0,1,0
GET_THREAD_INFO(%r10)
orl $TS_COMPAT,TI_status(%r10)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 5852519b2d0f..f6f5c53dc903 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -43,7 +43,7 @@
#include <asm/mman.h>
#include <asm/types.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/vgtod.h>
#include <asm/sys_ia32.h>
diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h
index 94d420b360d1..4554cc6fb96a 100644
--- a/arch/x86/include/asm/alternative-asm.h
+++ b/arch/x86/include/asm/alternative-asm.h
@@ -17,8 +17,8 @@
.macro altinstruction_entry orig alt feature orig_len alt_len
.align 8
- .quad \orig
- .quad \alt
+ .long \orig - .
+ .long \alt - .
.word \feature
.byte \orig_len
.byte \alt_len
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index bf535f947e8c..23fb6d79f209 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -43,8 +43,8 @@
#endif
struct alt_instr {
- u8 *instr; /* original instruction */
- u8 *replacement;
+ s32 instr_offset; /* original instruction */
+ s32 repl_offset; /* offset to replacement instruction */
u16 cpuid; /* cpuid bit set for replacement */
u8 instrlen; /* length of original instruction */
u8 replacementlen; /* length of new instruction, <= instrlen */
@@ -84,8 +84,8 @@ static inline int alternatives_text_reserved(void *start, void *end)
"661:\n\t" oldinstr "\n662:\n" \
".section .altinstructions,\"a\"\n" \
_ASM_ALIGN "\n" \
- _ASM_PTR "661b\n" /* label */ \
- _ASM_PTR "663f\n" /* new instruction */ \
+ " .long 661b - .\n" /* label */ \
+ " .long 663f - .\n" /* new instruction */ \
" .word " __stringify(feature) "\n" /* feature bit */ \
" .byte 662b-661b\n" /* sourcelen */ \
" .byte 664f-663f\n" /* replacementlen */ \
diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
index af60d8a2e288..0acbac299e49 100644
--- a/arch/x86/include/asm/apb_timer.h
+++ b/arch/x86/include/asm/apb_timer.h
@@ -18,24 +18,6 @@
#ifdef CONFIG_APB_TIMER
-/* Langwell DW APB timer registers */
-#define APBTMR_N_LOAD_COUNT 0x00
-#define APBTMR_N_CURRENT_VALUE 0x04
-#define APBTMR_N_CONTROL 0x08
-#define APBTMR_N_EOI 0x0c
-#define APBTMR_N_INT_STATUS 0x10
-
-#define APBTMRS_INT_STATUS 0xa0
-#define APBTMRS_EOI 0xa4
-#define APBTMRS_RAW_INT_STATUS 0xa8
-#define APBTMRS_COMP_VERSION 0xac
-#define APBTMRS_REG_SIZE 0x14
-
-/* register bits */
-#define APBTMR_CONTROL_ENABLE (1<<0)
-#define APBTMR_CONTROL_MODE_PERIODIC (1<<1) /*1: periodic 0:free running */
-#define APBTMR_CONTROL_INT (1<<2)
-
/* default memory mapped register base */
#define LNW_SCU_ADDR 0xFF100000
#define LNW_EXT_TIMER_OFFSET 0x1B800
@@ -43,14 +25,13 @@
#define LNW_EXT_TIMER_PGOFFSET 0x800
/* APBT clock speed range from PCLK to fabric base, 25-100MHz */
-#define APBT_MAX_FREQ 50
-#define APBT_MIN_FREQ 1
+#define APBT_MAX_FREQ 50000000
+#define APBT_MIN_FREQ 1000000
#define APBT_MMAP_SIZE 1024
#define APBT_DEV_USED 1
extern void apbt_time_init(void);
-extern struct clock_event_device *global_clock_event;
extern unsigned long apbt_quick_calibrate(void);
extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
extern void apbt_setup_secondary_clock(void);
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 4a0b7c7e2cce..7b3ca8324b69 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -8,7 +8,7 @@
#include <asm/cpufeature.h>
#include <asm/processor.h>
#include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/fixmap.h>
#include <asm/mpspec.h>
#include <asm/system.h>
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index b3ed1e1460ff..9412d6558c88 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -3,9 +3,11 @@
#ifdef __ASSEMBLY__
# define __ASM_FORM(x) x
+# define __ASM_FORM_COMMA(x) x,
# define __ASM_EX_SEC .section __ex_table, "a"
#else
# define __ASM_FORM(x) " " #x " "
+# define __ASM_FORM_COMMA(x) " " #x ","
# define __ASM_EX_SEC " .section __ex_table,\"a\"\n"
#endif
@@ -15,7 +17,8 @@
# define __ASM_SEL(a,b) __ASM_FORM(b)
#endif
-#define __ASM_SIZE(inst) __ASM_SEL(inst##l, inst##q)
+#define __ASM_SIZE(inst, ...) __ASM_SEL(inst##l##__VA_ARGS__, \
+ inst##q##__VA_ARGS__)
#define __ASM_REG(reg) __ASM_SEL(e##reg, r##reg)
#define _ASM_PTR __ASM_SEL(.long, .quad)
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 952a826ac4e5..10572e309ab2 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -221,15 +221,15 @@ static inline int atomic_xchg(atomic_t *v, int new)
}
/**
- * atomic_add_unless - add unless the number is already a given value
+ * __atomic_add_unless - add unless the number is already a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -241,10 +241,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
/*
* atomic_dec_if_positive - decrement by 1 if old value positive
@@ -319,5 +318,4 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
# include "atomic64_64.h"
#endif
-#include <asm-generic/atomic-long.h>
#endif /* _ASM_X86_ATOMIC_H */
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
index 2a934aa19a43..24098aafce0d 100644
--- a/arch/x86/include/asm/atomic64_32.h
+++ b/arch/x86/include/asm/atomic64_32.h
@@ -263,7 +263,7 @@ static inline int atomic64_add_negative(long long i, atomic64_t *v)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
{
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 49fd1ea22951..017594d403f6 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -202,7 +202,7 @@ static inline long atomic64_xchg(atomic64_t *v, long new)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
{
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 69d58131bc8e..1775d6e5920e 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -458,10 +458,7 @@ static inline int fls(int x)
#include <asm-generic/bitops/le.h>
-#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit((nr), (unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* __KERNEL__ */
#endif /* _ASM_X86_BITOPS_H */
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h
index 30af5a832163..a9e3a740f697 100644
--- a/arch/x86/include/asm/calling.h
+++ b/arch/x86/include/asm/calling.h
@@ -46,6 +46,7 @@ For 32-bit we have the following conventions - kernel is built with
*/
+#include "dwarf2.h"
/*
* 64-bit system call stack frame layout defines and helpers, for
@@ -84,72 +85,57 @@ For 32-bit we have the following conventions - kernel is built with
#define ARGOFFSET R11
#define SWFRAME ORIG_RAX
- .macro SAVE_ARGS addskip=0, norcx=0, nor891011=0
+ .macro SAVE_ARGS addskip=0, save_rcx=1, save_r891011=1
subq $9*8+\addskip, %rsp
CFI_ADJUST_CFA_OFFSET 9*8+\addskip
- movq %rdi, 8*8(%rsp)
- CFI_REL_OFFSET rdi, 8*8
- movq %rsi, 7*8(%rsp)
- CFI_REL_OFFSET rsi, 7*8
- movq %rdx, 6*8(%rsp)
- CFI_REL_OFFSET rdx, 6*8
- .if \norcx
- .else
- movq %rcx, 5*8(%rsp)
- CFI_REL_OFFSET rcx, 5*8
+ movq_cfi rdi, 8*8
+ movq_cfi rsi, 7*8
+ movq_cfi rdx, 6*8
+
+ .if \save_rcx
+ movq_cfi rcx, 5*8
.endif
- movq %rax, 4*8(%rsp)
- CFI_REL_OFFSET rax, 4*8
- .if \nor891011
- .else
- movq %r8, 3*8(%rsp)
- CFI_REL_OFFSET r8, 3*8
- movq %r9, 2*8(%rsp)
- CFI_REL_OFFSET r9, 2*8
- movq %r10, 1*8(%rsp)
- CFI_REL_OFFSET r10, 1*8
- movq %r11, (%rsp)
- CFI_REL_OFFSET r11, 0*8
+
+ movq_cfi rax, 4*8
+
+ .if \save_r891011
+ movq_cfi r8, 3*8
+ movq_cfi r9, 2*8
+ movq_cfi r10, 1*8
+ movq_cfi r11, 0*8
.endif
+
.endm
#define ARG_SKIP (9*8)
- .macro RESTORE_ARGS skiprax=0, addskip=0, skiprcx=0, skipr11=0, \
- skipr8910=0, skiprdx=0
- .if \skipr11
- .else
- movq (%rsp), %r11
- CFI_RESTORE r11
+ .macro RESTORE_ARGS rstor_rax=1, addskip=0, rstor_rcx=1, rstor_r11=1, \
+ rstor_r8910=1, rstor_rdx=1
+ .if \rstor_r11
+ movq_cfi_restore 0*8, r11
.endif
- .if \skipr8910
- .else
- movq 1*8(%rsp), %r10
- CFI_RESTORE r10
- movq 2*8(%rsp), %r9
- CFI_RESTORE r9
- movq 3*8(%rsp), %r8
- CFI_RESTORE r8
+
+ .if \rstor_r8910
+ movq_cfi_restore 1*8, r10
+ movq_cfi_restore 2*8, r9
+ movq_cfi_restore 3*8, r8
.endif
- .if \skiprax
- .else
- movq 4*8(%rsp), %rax
- CFI_RESTORE rax
+
+ .if \rstor_rax
+ movq_cfi_restore 4*8, rax
.endif
- .if \skiprcx
- .else
- movq 5*8(%rsp), %rcx
- CFI_RESTORE rcx
+
+ .if \rstor_rcx
+ movq_cfi_restore 5*8, rcx
.endif
- .if \skiprdx
- .else
- movq 6*8(%rsp), %rdx
- CFI_RESTORE rdx
+
+ .if \rstor_rdx
+ movq_cfi_restore 6*8, rdx
.endif
- movq 7*8(%rsp), %rsi
- CFI_RESTORE rsi
- movq 8*8(%rsp), %rdi
- CFI_RESTORE rdi
+
+ movq_cfi_restore 7*8, rsi
+ movq_cfi_restore 8*8, rdi
+
.if ARG_SKIP+\addskip > 0
addq $ARG_SKIP+\addskip, %rsp
CFI_ADJUST_CFA_OFFSET -(ARG_SKIP+\addskip)
@@ -176,33 +162,21 @@ For 32-bit we have the following conventions - kernel is built with
.macro SAVE_REST
subq $REST_SKIP, %rsp
CFI_ADJUST_CFA_OFFSET REST_SKIP
- movq %rbx, 5*8(%rsp)
- CFI_REL_OFFSET rbx, 5*8
- movq %rbp, 4*8(%rsp)
- CFI_REL_OFFSET rbp, 4*8
- movq %r12, 3*8(%rsp)
- CFI_REL_OFFSET r12, 3*8
- movq %r13, 2*8(%rsp)
- CFI_REL_OFFSET r13, 2*8
- movq %r14, 1*8(%rsp)
- CFI_REL_OFFSET r14, 1*8
- movq %r15, (%rsp)
- CFI_REL_OFFSET r15, 0*8
+ movq_cfi rbx, 5*8
+ movq_cfi rbp, 4*8
+ movq_cfi r12, 3*8
+ movq_cfi r13, 2*8
+ movq_cfi r14, 1*8
+ movq_cfi r15, 0*8
.endm
.macro RESTORE_REST
- movq (%rsp), %r15
- CFI_RESTORE r15
- movq 1*8(%rsp), %r14
- CFI_RESTORE r14
- movq 2*8(%rsp), %r13
- CFI_RESTORE r13
- movq 3*8(%rsp), %r12
- CFI_RESTORE r12
- movq 4*8(%rsp), %rbp
- CFI_RESTORE rbp
- movq 5*8(%rsp), %rbx
- CFI_RESTORE rbx
+ movq_cfi_restore 0*8, r15
+ movq_cfi_restore 1*8, r14
+ movq_cfi_restore 2*8, r13
+ movq_cfi_restore 3*8, r12
+ movq_cfi_restore 4*8, rbp
+ movq_cfi_restore 5*8, rbx
addq $REST_SKIP, %rsp
CFI_ADJUST_CFA_OFFSET -(REST_SKIP)
.endm
@@ -214,7 +188,7 @@ For 32-bit we have the following conventions - kernel is built with
.macro RESTORE_ALL addskip=0
RESTORE_REST
- RESTORE_ARGS 0, \addskip
+ RESTORE_ARGS 1, \addskip
.endm
.macro icebp
diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h
new file mode 100644
index 000000000000..0bdbbb3b9ce7
--- /dev/null
+++ b/arch/x86/include/asm/clocksource.h
@@ -0,0 +1,18 @@
+/* x86-specific clocksource additions */
+
+#ifndef _ASM_X86_CLOCKSOURCE_H
+#define _ASM_X86_CLOCKSOURCE_H
+
+#ifdef CONFIG_X86_64
+
+#define VCLOCK_NONE 0 /* No vDSO clock available. */
+#define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */
+#define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */
+
+struct arch_clocksource_data {
+ int vclock_mode;
+};
+
+#endif /* CONFIG_X86_64 */
+
+#endif /* _ASM_X86_CLOCKSOURCE_H */
diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index 284a6e8f7ce1..3deb7250624c 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -280,4 +280,52 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
#endif
+#define cmpxchg8b(ptr, o1, o2, n1, n2) \
+({ \
+ char __ret; \
+ __typeof__(o2) __dummy; \
+ __typeof__(*(ptr)) __old1 = (o1); \
+ __typeof__(o2) __old2 = (o2); \
+ __typeof__(*(ptr)) __new1 = (n1); \
+ __typeof__(o2) __new2 = (n2); \
+ asm volatile(LOCK_PREFIX "cmpxchg8b %2; setz %1" \
+ : "=d"(__dummy), "=a" (__ret), "+m" (*ptr)\
+ : "a" (__old1), "d"(__old2), \
+ "b" (__new1), "c" (__new2) \
+ : "memory"); \
+ __ret; })
+
+
+#define cmpxchg8b_local(ptr, o1, o2, n1, n2) \
+({ \
+ char __ret; \
+ __typeof__(o2) __dummy; \
+ __typeof__(*(ptr)) __old1 = (o1); \
+ __typeof__(o2) __old2 = (o2); \
+ __typeof__(*(ptr)) __new1 = (n1); \
+ __typeof__(o2) __new2 = (n2); \
+ asm volatile("cmpxchg8b %2; setz %1" \
+ : "=d"(__dummy), "=a"(__ret), "+m" (*ptr)\
+ : "a" (__old), "d"(__old2), \
+ "b" (__new1), "c" (__new2), \
+ : "memory"); \
+ __ret; })
+
+
+#define cmpxchg_double(ptr, o1, o2, n1, n2) \
+({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
+ VM_BUG_ON((unsigned long)(ptr) % 8); \
+ cmpxchg8b((ptr), (o1), (o2), (n1), (n2)); \
+})
+
+#define cmpxchg_double_local(ptr, o1, o2, n1, n2) \
+({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
+ VM_BUG_ON((unsigned long)(ptr) % 8); \
+ cmpxchg16b_local((ptr), (o1), (o2), (n1), (n2)); \
+})
+
+#define system_has_cmpxchg_double() cpu_has_cx8
+
#endif /* _ASM_X86_CMPXCHG_32_H */
diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h
index 423ae58aa020..7cf5c0a24434 100644
--- a/arch/x86/include/asm/cmpxchg_64.h
+++ b/arch/x86/include/asm/cmpxchg_64.h
@@ -151,4 +151,49 @@ extern void __cmpxchg_wrong_size(void);
cmpxchg_local((ptr), (o), (n)); \
})
+#define cmpxchg16b(ptr, o1, o2, n1, n2) \
+({ \
+ char __ret; \
+ __typeof__(o2) __junk; \
+ __typeof__(*(ptr)) __old1 = (o1); \
+ __typeof__(o2) __old2 = (o2); \
+ __typeof__(*(ptr)) __new1 = (n1); \
+ __typeof__(o2) __new2 = (n2); \
+ asm volatile(LOCK_PREFIX "cmpxchg16b %2;setz %1" \
+ : "=d"(__junk), "=a"(__ret), "+m" (*ptr) \
+ : "b"(__new1), "c"(__new2), \
+ "a"(__old1), "d"(__old2)); \
+ __ret; })
+
+
+#define cmpxchg16b_local(ptr, o1, o2, n1, n2) \
+({ \
+ char __ret; \
+ __typeof__(o2) __junk; \
+ __typeof__(*(ptr)) __old1 = (o1); \
+ __typeof__(o2) __old2 = (o2); \
+ __typeof__(*(ptr)) __new1 = (n1); \
+ __typeof__(o2) __new2 = (n2); \
+ asm volatile("cmpxchg16b %2;setz %1" \
+ : "=d"(__junk), "=a"(__ret), "+m" (*ptr) \
+ : "b"(__new1), "c"(__new2), \
+ "a"(__old1), "d"(__old2)); \
+ __ret; })
+
+#define cmpxchg_double(ptr, o1, o2, n1, n2) \
+({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ VM_BUG_ON((unsigned long)(ptr) % 16); \
+ cmpxchg16b((ptr), (o1), (o2), (n1), (n2)); \
+})
+
+#define cmpxchg_double_local(ptr, o1, o2, n1, n2) \
+({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ VM_BUG_ON((unsigned long)(ptr) % 16); \
+ cmpxchg16b_local((ptr), (o1), (o2), (n1), (n2)); \
+})
+
+#define system_has_cmpxchg_double() cpu_has_cx16
+
#endif /* _ASM_X86_CMPXCHG_64_H */
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 71cc3800712c..4258aac99a6e 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -288,6 +288,8 @@ extern const char * const x86_power_flags[32];
#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)
+#define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8)
+#define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16)
#if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
# define cpu_has_invlpg 1
@@ -331,8 +333,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
"2:\n"
".section .altinstructions,\"a\"\n"
_ASM_ALIGN "\n"
- _ASM_PTR "1b\n"
- _ASM_PTR "0\n" /* no replacement */
+ " .long 1b - .\n"
+ " .long 0\n" /* no replacement */
" .word %P0\n" /* feature bit */
" .byte 2b - 1b\n" /* source len */
" .byte 0\n" /* replacement len */
@@ -349,8 +351,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
"2:\n"
".section .altinstructions,\"a\"\n"
_ASM_ALIGN "\n"
- _ASM_PTR "1b\n"
- _ASM_PTR "3f\n"
+ " .long 1b - .\n"
+ " .long 3f - .\n"
" .word %P1\n" /* feature bit */
" .byte 2b - 1b\n" /* source len */
" .byte 4f - 3f\n" /* replacement len */
diff --git a/arch/x86/include/asm/delay.h b/arch/x86/include/asm/delay.h
index 409a649204aa..9b3b4f2754c7 100644
--- a/arch/x86/include/asm/delay.h
+++ b/arch/x86/include/asm/delay.h
@@ -1,30 +1,7 @@
#ifndef _ASM_X86_DELAY_H
#define _ASM_X86_DELAY_H
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/x86/lib/delay.c
- */
-
-/* Undefined functions to get compile-time errors */
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
- __udelay(n))
-
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
- __ndelay(n))
+#include <asm-generic/delay.h>
void use_tsc_delay(void);
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index 1cd6d26a0a8d..0baa628e330c 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -53,8 +53,4 @@ BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
BUILD_INTERRUPT(threshold_interrupt,THRESHOLD_APIC_VECTOR)
#endif
-#ifdef CONFIG_X86_MCE
-BUILD_INTERRUPT(mce_self_interrupt,MCE_SELF_VECTOR)
-#endif
-
#endif
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 4729b2b63117..460c74e4852c 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -78,6 +78,7 @@ enum fixed_addresses {
VSYSCALL_LAST_PAGE,
VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
+ ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+ VVAR_PAGE,
VSYSCALL_HPET,
#endif
FIX_DBGP_BASE,
diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h
index 2c6fc9e62812..3b629f47eb65 100644
--- a/arch/x86/include/asm/frame.h
+++ b/arch/x86/include/asm/frame.h
@@ -1,5 +1,6 @@
#ifdef __ASSEMBLY__
+#include <asm/asm.h>
#include <asm/dwarf2.h>
/* The annotation hides the frame from the unwinder and makes it look
@@ -7,13 +8,13 @@
frame pointer later */
#ifdef CONFIG_FRAME_POINTER
.macro FRAME
- pushl_cfi %ebp
- CFI_REL_OFFSET ebp,0
- movl %esp,%ebp
+ __ASM_SIZE(push,_cfi) %__ASM_REG(bp)
+ CFI_REL_OFFSET __ASM_REG(bp), 0
+ __ASM_SIZE(mov) %__ASM_REG(sp), %__ASM_REG(bp)
.endm
.macro ENDFRAME
- popl_cfi %ebp
- CFI_RESTORE ebp
+ __ASM_SIZE(pop,_cfi) %__ASM_REG(bp)
+ CFI_RESTORE __ASM_REG(bp)
.endm
#else
.macro FRAME
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index bb9efe8706e2..09199052060f 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -21,7 +21,7 @@
#include <linux/profile.h>
#include <linux/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/sections.h>
@@ -34,7 +34,6 @@ extern void irq_work_interrupt(void);
extern void spurious_interrupt(void);
extern void thermal_interrupt(void);
extern void reschedule_interrupt(void);
-extern void mce_self_interrupt(void);
extern void invalidate_interrupt(void);
extern void invalidate_interrupt0(void);
diff --git a/arch/x86/include/asm/i8253.h b/arch/x86/include/asm/i8253.h
deleted file mode 100644
index 65aaa91d5850..000000000000
--- a/arch/x86/include/asm/i8253.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_X86_I8253_H
-#define _ASM_X86_I8253_H
-
-/* i8253A PIT registers */
-#define PIT_MODE 0x43
-#define PIT_CH0 0x40
-#define PIT_CH2 0x42
-
-#define PIT_LATCH LATCH
-
-extern raw_spinlock_t i8253_lock;
-
-extern struct clock_event_device *global_clock_event;
-
-extern void setup_pit_timer(void);
-
-#define inb_pit inb_p
-#define outb_pit outb_p
-
-#endif /* _ASM_X86_I8253_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 6e976ee3b3ef..f9a320984a10 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -17,7 +17,8 @@
* Vectors 0 ... 31 : system traps and exceptions - hardcoded events
* Vectors 32 ... 127 : device interrupts
* Vector 128 : legacy int80 syscall interface
- * Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 : device interrupts
+ * Vector 204 : legacy x86_64 vsyscall emulation
+ * Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 except 204 : device interrupts
* Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
*
* 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table.
@@ -50,6 +51,9 @@
#ifdef CONFIG_X86_32
# define SYSCALL_VECTOR 0x80
#endif
+#ifdef CONFIG_X86_64
+# define VSYSCALL_EMU_VECTOR 0xcc
+#endif
/*
* Vectors 0x30-0x3f are used for ISA interrupts.
@@ -109,11 +113,6 @@
#define UV_BAU_MESSAGE 0xf5
-/*
- * Self IPI vector for machine checks
- */
-#define MCE_SELF_VECTOR 0xf4
-
/* Xen vector callback to receive events in a HVM domain */
#define XEN_HVM_EVTCHN_CALLBACK 0xf3
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h
index 5745ce8bf108..bba3cf88e624 100644
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -60,23 +60,24 @@ static inline void native_halt(void)
#include <asm/paravirt.h>
#else
#ifndef __ASSEMBLY__
+#include <linux/types.h>
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
{
return native_save_fl();
}
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
{
native_restore_fl(flags);
}
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
{
native_irq_disable();
}
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
{
native_irq_enable();
}
@@ -102,7 +103,7 @@ static inline void halt(void)
/*
* For spinlocks, etc:
*/
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
{
unsigned long flags = arch_local_save_flags();
arch_local_irq_disable();
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h
index fe2cc6e105fa..d73f1571bde7 100644
--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -28,7 +28,6 @@ extern void show_registers(struct pt_regs *regs);
extern void show_trace(struct task_struct *t, struct pt_regs *regs,
unsigned long *sp, unsigned long bp);
extern void __show_regs(struct pt_regs *regs, int all);
-extern void show_regs(struct pt_regs *regs);
extern unsigned long oops_begin(void);
extern void oops_end(unsigned long, struct pt_regs *, int signr);
#ifdef CONFIG_KEXEC
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 0049211959c0..6040d115ef51 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -229,7 +229,26 @@ struct read_cache {
unsigned long end;
};
-struct decode_cache {
+struct x86_emulate_ctxt {
+ struct x86_emulate_ops *ops;
+
+ /* Register state before/after emulation. */
+ unsigned long eflags;
+ unsigned long eip; /* eip before instruction emulation */
+ /* Emulated execution mode, represented by an X86EMUL_MODE value. */
+ int mode;
+
+ /* interruptibility state, as a result of execution of STI or MOV SS */
+ int interruptibility;
+
+ bool guest_mode; /* guest running a nested guest */
+ bool perm_ok; /* do not check permissions if true */
+ bool only_vendor_specific_insn;
+
+ bool have_exception;
+ struct x86_exception exception;
+
+ /* decode cache */
u8 twobyte;
u8 b;
u8 intercept;
@@ -246,8 +265,6 @@ struct decode_cache {
unsigned int d;
int (*execute)(struct x86_emulate_ctxt *ctxt);
int (*check_perm)(struct x86_emulate_ctxt *ctxt);
- unsigned long regs[NR_VCPU_REGS];
- unsigned long eip;
/* modrm */
u8 modrm;
u8 modrm_mod;
@@ -255,34 +272,14 @@ struct decode_cache {
u8 modrm_rm;
u8 modrm_seg;
bool rip_relative;
+ unsigned long _eip;
+ /* Fields above regs are cleared together. */
+ unsigned long regs[NR_VCPU_REGS];
struct fetch_cache fetch;
struct read_cache io_read;
struct read_cache mem_read;
};
-struct x86_emulate_ctxt {
- struct x86_emulate_ops *ops;
-
- /* Register state before/after emulation. */
- unsigned long eflags;
- unsigned long eip; /* eip before instruction emulation */
- /* Emulated execution mode, represented by an X86EMUL_MODE value. */
- int mode;
-
- /* interruptibility state, as a result of execution of STI or MOV SS */
- int interruptibility;
-
- bool guest_mode; /* guest running a nested guest */
- bool perm_ok; /* do not check permissions if true */
- bool only_vendor_specific_insn;
-
- bool have_exception;
- struct x86_exception exception;
-
- /* decode cache */
- struct decode_cache decode;
-};
-
/* Repeat String Operation Prefix */
#define REPE_PREFIX 0xf3
#define REPNE_PREFIX 0xf2
@@ -373,6 +370,5 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt);
int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
u16 tss_selector, int reason,
bool has_error_code, u32 error_code);
-int emulate_int_real(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, int irq);
+int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq);
#endif /* _ASM_X86_KVM_X86_EMULATE_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d2ac8e2ee897..dd51c83aa5de 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -48,7 +48,7 @@
(~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
| X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \
| X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR \
- | X86_CR4_OSXSAVE \
+ | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_RDWRGSFS \
| X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
@@ -205,6 +205,7 @@ union kvm_mmu_page_role {
unsigned invalid:1;
unsigned nxe:1;
unsigned cr0_wp:1;
+ unsigned smep_andnot_wp:1;
};
};
@@ -227,15 +228,17 @@ struct kvm_mmu_page {
* in this shadow page.
*/
DECLARE_BITMAP(slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
- bool multimapped; /* More than one parent_pte? */
bool unsync;
int root_count; /* Currently serving as active root */
unsigned int unsync_children;
- union {
- u64 *parent_pte; /* !multimapped */
- struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */
- };
+ unsigned long parent_ptes; /* Reverse mapping for parent_pte */
DECLARE_BITMAP(unsync_child_bitmap, 512);
+
+#ifdef CONFIG_X86_32
+ int clear_spte_count;
+#endif
+
+ struct rcu_head rcu;
};
struct kvm_pv_mmu_op_buffer {
@@ -269,8 +272,6 @@ struct kvm_mmu {
gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
struct x86_exception *exception);
gpa_t (*translate_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access);
- void (*prefetch_page)(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *page);
int (*sync_page)(struct kvm_vcpu *vcpu,
struct kvm_mmu_page *sp);
void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva);
@@ -346,8 +347,7 @@ struct kvm_vcpu_arch {
* put it here to avoid allocation */
struct kvm_pv_mmu_op_buffer mmu_op_buffer;
- struct kvm_mmu_memory_cache mmu_pte_chain_cache;
- struct kvm_mmu_memory_cache mmu_rmap_desc_cache;
+ struct kvm_mmu_memory_cache mmu_pte_list_desc_cache;
struct kvm_mmu_memory_cache mmu_page_cache;
struct kvm_mmu_memory_cache mmu_page_header_cache;
@@ -393,6 +393,15 @@ struct kvm_vcpu_arch {
unsigned int hw_tsc_khz;
unsigned int time_offset;
struct page *time_page;
+
+ struct {
+ u64 msr_val;
+ u64 last_steal;
+ u64 accum_steal;
+ struct gfn_to_hva_cache stime;
+ struct kvm_steal_time steal;
+ } st;
+
u64 last_guest_tsc;
u64 last_kernel_ns;
u64 last_tsc_nsec;
@@ -419,6 +428,11 @@ struct kvm_vcpu_arch {
u64 mcg_ctl;
u64 *mce_banks;
+ /* Cache MMIO info */
+ u64 mmio_gva;
+ unsigned access;
+ gfn_t mmio_gfn;
+
/* used for guest single stepping over the given code position */
unsigned long singlestep_rip;
@@ -441,6 +455,7 @@ struct kvm_arch {
unsigned int n_used_mmu_pages;
unsigned int n_requested_mmu_pages;
unsigned int n_max_mmu_pages;
+ unsigned int indirect_shadow_pages;
atomic_t invlpg_counter;
struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
/*
@@ -477,6 +492,8 @@ struct kvm_arch {
u64 hv_guest_os_id;
u64 hv_hypercall;
+ atomic_t reader_counter;
+
#ifdef CONFIG_KVM_MMU_AUDIT
int audit_point;
#endif
@@ -559,7 +576,7 @@ struct kvm_x86_ops {
void (*decache_cr4_guest_bits)(struct kvm_vcpu *vcpu);
void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
- void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
+ int (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
void (*set_efer)(struct kvm_vcpu *vcpu, u64 efer);
void (*get_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
void (*set_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
@@ -636,7 +653,6 @@ void kvm_mmu_module_exit(void);
void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
int kvm_mmu_create(struct kvm_vcpu *vcpu);
int kvm_mmu_setup(struct kvm_vcpu *vcpu);
-void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte);
void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
u64 dirty_mask, u64 nx_mask, u64 x_mask);
@@ -830,11 +846,12 @@ enum {
asmlinkage void kvm_spurious_fault(void);
extern bool kvm_rebooting;
-#define __kvm_handle_fault_on_reboot(insn) \
+#define ____kvm_handle_fault_on_reboot(insn, cleanup_insn) \
"666: " insn "\n\t" \
"668: \n\t" \
".pushsection .fixup, \"ax\" \n" \
"667: \n\t" \
+ cleanup_insn "\n\t" \
"cmpb $0, kvm_rebooting \n\t" \
"jne 668b \n\t" \
__ASM_SIZE(push) " $666b \n\t" \
@@ -844,6 +861,9 @@ extern bool kvm_rebooting;
_ASM_PTR " 666b, 667b \n\t" \
".popsection"
+#define __kvm_handle_fault_on_reboot(insn) \
+ ____kvm_handle_fault_on_reboot(insn, "")
+
#define KVM_ARCH_WANT_MMU_NOTIFIER
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
int kvm_age_hva(struct kvm *kvm, unsigned long hva);
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index a427bf77a93d..734c3767cfac 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -21,6 +21,7 @@
*/
#define KVM_FEATURE_CLOCKSOURCE2 3
#define KVM_FEATURE_ASYNC_PF 4
+#define KVM_FEATURE_STEAL_TIME 5
/* The last 8 bits are used to indicate how to interpret the flags field
* in pvclock structure. If no bits are set, all flags are ignored.
@@ -30,10 +31,23 @@
#define MSR_KVM_WALL_CLOCK 0x11
#define MSR_KVM_SYSTEM_TIME 0x12
+#define KVM_MSR_ENABLED 1
/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
#define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00
#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
+#define MSR_KVM_STEAL_TIME 0x4b564d03
+
+struct kvm_steal_time {
+ __u64 steal;
+ __u32 version;
+ __u32 flags;
+ __u32 pad[12];
+};
+
+#define KVM_STEAL_ALIGNMENT_BITS 5
+#define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
+#define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
#define KVM_MAX_MMU_OP_BATCH 32
@@ -178,6 +192,7 @@ void __init kvm_guest_init(void);
void kvm_async_pf_task_wait(u32 token);
void kvm_async_pf_task_wake(u32 token);
u32 kvm_read_and_reset_pf_reason(void);
+extern void kvm_disable_steal_time(void);
#else
#define kvm_guest_init() do { } while (0)
#define kvm_async_pf_task_wait(T) do {} while(0)
@@ -186,6 +201,11 @@ static inline u32 kvm_read_and_reset_pf_reason(void)
{
return 0;
}
+
+static inline void kvm_disable_steal_time(void)
+{
+ return;
+}
#endif
#endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/lguest_hcall.h b/arch/x86/include/asm/lguest_hcall.h
index b60f2924c413..879fd7d33877 100644
--- a/arch/x86/include/asm/lguest_hcall.h
+++ b/arch/x86/include/asm/lguest_hcall.h
@@ -61,6 +61,7 @@ hcall(unsigned long call,
: "memory");
return call;
}
+/*:*/
/* Can't use our min() macro here: needs to be a constant */
#define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
index 2e9972468a5d..9cdae5d47e8f 100644
--- a/arch/x86/include/asm/local.h
+++ b/arch/x86/include/asm/local.h
@@ -4,7 +4,7 @@
#include <linux/percpu.h>
#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/asm.h>
typedef struct {
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 021979a6e23f..c9321f34e55b 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -8,6 +8,7 @@
* Machine Check support for x86
*/
+/* MCG_CAP register defines */
#define MCG_BANKCNT_MASK 0xff /* Number of Banks */
#define MCG_CTL_P (1ULL<<8) /* MCG_CTL register available */
#define MCG_EXT_P (1ULL<<9) /* Extended registers available */
@@ -17,10 +18,12 @@
#define MCG_EXT_CNT(c) (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
+/* MCG_STATUS register defines */
#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */
#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */
#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */
+/* MCi_STATUS register defines */
#define MCI_STATUS_VAL (1ULL<<63) /* valid error */
#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */
#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */
@@ -31,12 +34,14 @@
#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */
#define MCI_STATUS_AR (1ULL<<55) /* Action required */
-/* MISC register defines */
-#define MCM_ADDR_SEGOFF 0 /* segment offset */
-#define MCM_ADDR_LINEAR 1 /* linear address */
-#define MCM_ADDR_PHYS 2 /* physical address */
-#define MCM_ADDR_MEM 3 /* memory address */
-#define MCM_ADDR_GENERIC 7 /* generic */
+/* MCi_MISC register defines */
+#define MCI_MISC_ADDR_LSB(m) ((m) & 0x3f)
+#define MCI_MISC_ADDR_MODE(m) (((m) >> 6) & 7)
+#define MCI_MISC_ADDR_SEGOFF 0 /* segment offset */
+#define MCI_MISC_ADDR_LINEAR 1 /* linear address */
+#define MCI_MISC_ADDR_PHYS 2 /* physical address */
+#define MCI_MISC_ADDR_MEM 3 /* memory address */
+#define MCI_MISC_ADDR_GENERIC 7 /* generic */
/* CTL2 register defines */
#define MCI_CTL2_CMCI_EN (1ULL << 30)
@@ -119,7 +124,7 @@ extern struct atomic_notifier_head x86_mce_decoder_chain;
#include <linux/percpu.h>
#include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
extern int mce_disabled;
extern int mce_p5_enabled;
@@ -144,7 +149,7 @@ static inline void enable_p5_mce(void) {}
void mce_setup(struct mce *m);
void mce_log(struct mce *m);
-DECLARE_PER_CPU(struct sys_device, mce_dev);
+DECLARE_PER_CPU(struct sys_device, mce_sysdev);
/*
* Maximum banks number.
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 8b5393ec1080..69021528b43c 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -2,7 +2,7 @@
#define _ASM_X86_MMU_CONTEXT_H
#include <asm/desc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/paravirt.h>
diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h
index ffa037f28d39..55728e121473 100644
--- a/arch/x86/include/asm/mmzone_32.h
+++ b/arch/x86/include/asm/mmzone_32.h
@@ -34,15 +34,15 @@ static inline void resume_map_numa_kva(pgd_t *pgd) {}
* 64Gb / 4096bytes/page = 16777216 pages
*/
#define MAX_NR_PAGES 16777216
-#define MAX_ELEMENTS 1024
-#define PAGES_PER_ELEMENT (MAX_NR_PAGES/MAX_ELEMENTS)
+#define MAX_SECTIONS 1024
+#define PAGES_PER_SECTION (MAX_NR_PAGES/MAX_SECTIONS)
extern s8 physnode_map[];
static inline int pfn_to_nid(unsigned long pfn)
{
#ifdef CONFIG_NUMA
- return((int) physnode_map[(pfn) / PAGES_PER_ELEMENT]);
+ return((int) physnode_map[(pfn) / PAGES_PER_SECTION]);
#else
return 0;
#endif
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 485b4f1f079b..d52609aeeab8 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -259,6 +259,9 @@
#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
+#define ENERGY_PERF_BIAS_PERFORMANCE 0
+#define ENERGY_PERF_BIAS_NORMAL 6
+#define ENERGY_PERF_BIAS_POWERSAVE 15
#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
@@ -438,6 +441,18 @@
#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a
#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b
#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c
+#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x0000048d
+#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e
+#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f
+#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490
+
+/* VMX_BASIC bits and bitmasks */
+#define VMX_BASIC_VMCS_SIZE_SHIFT 32
+#define VMX_BASIC_64 0x0001000000000000LLU
+#define VMX_BASIC_MEM_TYPE_SHIFT 50
+#define VMX_BASIC_MEM_TYPE_MASK 0x003c000000000000LLU
+#define VMX_BASIC_MEM_TYPE_WB 6LLU
+#define VMX_BASIC_INOUT 0x0040000000000000LLU
/* AMD-V MSRs */
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 5ca6801b75f3..87bdbca72f94 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -13,6 +13,7 @@ struct olpc_platform_t {
#define OLPC_F_PRESENT 0x01
#define OLPC_F_DCON 0x02
+#define OLPC_F_EC_WIDE_SCI 0x04
#ifdef CONFIG_OLPC
@@ -62,6 +63,13 @@ static inline int olpc_board_at_least(uint32_t rev)
return olpc_platform_info.boardrev >= rev;
}
+extern void olpc_ec_wakeup_set(u16 value);
+extern void olpc_ec_wakeup_clear(u16 value);
+extern bool olpc_ec_wakeup_available(void);
+
+extern int olpc_ec_mask_write(u16 bits);
+extern int olpc_ec_sci_query(u16 *sci_value);
+
#else
static inline int machine_is_olpc(void)
@@ -74,6 +82,20 @@ static inline int olpc_has_dcon(void)
return 0;
}
+static inline void olpc_ec_wakeup_set(u16 value) { }
+static inline void olpc_ec_wakeup_clear(u16 value) { }
+
+static inline bool olpc_ec_wakeup_available(void)
+{
+ return false;
+}
+
+#endif
+
+#ifdef CONFIG_OLPC_XO1_PM
+extern void do_olpc_suspend_lowlevel(void);
+extern void olpc_xo1_pm_wakeup_set(u16 value);
+extern void olpc_xo1_pm_wakeup_clear(u16 value);
#endif
extern int pci_olpc_init(void);
@@ -83,14 +105,19 @@ extern int pci_olpc_init(void);
extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
unsigned char *outbuf, size_t outlen);
-extern int olpc_ec_mask_set(uint8_t bits);
-extern int olpc_ec_mask_unset(uint8_t bits);
-
/* EC commands */
-#define EC_FIRMWARE_REV 0x08
-#define EC_WLAN_ENTER_RESET 0x35
-#define EC_WLAN_LEAVE_RESET 0x25
+#define EC_FIRMWARE_REV 0x08
+#define EC_WRITE_SCI_MASK 0x1b
+#define EC_WAKE_UP_WLAN 0x24
+#define EC_WLAN_LEAVE_RESET 0x25
+#define EC_READ_EB_MODE 0x2a
+#define EC_SET_SCI_INHIBIT 0x32
+#define EC_SET_SCI_INHIBIT_RELEASE 0x34
+#define EC_WLAN_ENTER_RESET 0x35
+#define EC_WRITE_EXT_SCI_MASK 0x38
+#define EC_SCI_QUERY 0x84
+#define EC_EXT_SCI_QUERY 0x85
/* SCI source values */
@@ -99,10 +126,12 @@ extern int olpc_ec_mask_unset(uint8_t bits);
#define EC_SCI_SRC_BATTERY 0x02
#define EC_SCI_SRC_BATSOC 0x04
#define EC_SCI_SRC_BATERR 0x08
-#define EC_SCI_SRC_EBOOK 0x10
-#define EC_SCI_SRC_WLAN 0x20
+#define EC_SCI_SRC_EBOOK 0x10 /* XO-1 only */
+#define EC_SCI_SRC_WLAN 0x20 /* XO-1 only */
#define EC_SCI_SRC_ACPWR 0x40
-#define EC_SCI_SRC_ALL 0x7F
+#define EC_SCI_SRC_BATCRIT 0x80
+#define EC_SCI_SRC_GPWAKE 0x100 /* XO-1.5 only */
+#define EC_SCI_SRC_ALL 0x1FF
/* GPIO assignments */
@@ -116,7 +145,7 @@ extern int olpc_ec_mask_unset(uint8_t bits);
#define OLPC_GPIO_SMB_CLK 14
#define OLPC_GPIO_SMB_DATA 15
#define OLPC_GPIO_WORKAUX geode_gpio(24)
-#define OLPC_GPIO_LID geode_gpio(26)
-#define OLPC_GPIO_ECSCI geode_gpio(27)
+#define OLPC_GPIO_LID 26
+#define OLPC_GPIO_ECSCI 27
#endif /* _ASM_X86_OLPC_H */
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index ebbc4d8ab170..a7d2db9a74fb 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -230,6 +230,15 @@ static inline unsigned long long paravirt_sched_clock(void)
return PVOP_CALL0(unsigned long long, pv_time_ops.sched_clock);
}
+struct jump_label_key;
+extern struct jump_label_key paravirt_steal_enabled;
+extern struct jump_label_key paravirt_steal_rq_enabled;
+
+static inline u64 paravirt_steal_clock(int cpu)
+{
+ return PVOP_CALL1(u64, pv_time_ops.steal_clock, cpu);
+}
+
static inline unsigned long long paravirt_read_pmc(int counter)
{
return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter);
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 82885099c869..2c7652163111 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -89,6 +89,7 @@ struct pv_lazy_ops {
struct pv_time_ops {
unsigned long long (*sched_clock)(void);
+ unsigned long long (*steal_clock)(int cpu);
unsigned long (*get_tsc_khz)(void);
};
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index a0a9779084d1..3470c9d0ebba 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -388,12 +388,9 @@ do { \
#define __this_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val)
#define __this_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val)
#define __this_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val)
-/*
- * Generic fallback operations for __this_cpu_xchg_[1-4] are okay and much
- * faster than an xchg with forced lock semantics.
- */
-#define __this_cpu_xchg_8(pcp, nval) percpu_xchg_op(pcp, nval)
-#define __this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(pcp, oval, nval)
+#define __this_cpu_xchg_1(pcp, val) percpu_xchg_op(pcp, val)
+#define __this_cpu_xchg_2(pcp, val) percpu_xchg_op(pcp, val)
+#define __this_cpu_xchg_4(pcp, val) percpu_xchg_op(pcp, val)
#define this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
#define this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
@@ -485,6 +482,8 @@ do { \
#define __this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val)
#define __this_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val)
#define __this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val)
+#define __this_cpu_xchg_8(pcp, nval) percpu_xchg_op(pcp, nval)
+#define __this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(pcp, oval, nval)
#define this_cpu_read_8(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
#define this_cpu_write_8(pcp, val) percpu_to_op("mov", (pcp), val)
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index d9d4dae305f6..094fb30817ab 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -152,6 +152,11 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
(regs)->bp = caller_frame_pointer(); \
(regs)->cs = __KERNEL_CS; \
regs->flags = 0; \
+ asm volatile( \
+ _ASM_MOV "%%"_ASM_SP ", %0\n" \
+ : "=m" ((regs)->sp) \
+ :: "memory" \
+ ); \
}
#else
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
index 56fd9e3abbda..4f7e67e2345e 100644
--- a/arch/x86/include/asm/perf_event_p4.h
+++ b/arch/x86/include/asm/perf_event_p4.h
@@ -102,6 +102,14 @@
#define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT)
/*
+ * If an event has alias it should be marked
+ * with a special bit. (Don't forget to check
+ * P4_PEBS_CONFIG_MASK and related bits on
+ * modification.)
+ */
+#define P4_CONFIG_ALIASABLE (1 << 9)
+
+/*
* The bits we allow to pass for RAW events
*/
#define P4_CONFIG_MASK_ESCR \
@@ -123,6 +131,31 @@
(p4_config_pack_escr(P4_CONFIG_MASK_ESCR)) | \
(p4_config_pack_cccr(P4_CONFIG_MASK_CCCR))
+/*
+ * In case of event aliasing we need to preserve some
+ * caller bits, otherwise the mapping won't be complete.
+ */
+#define P4_CONFIG_EVENT_ALIAS_MASK \
+ (p4_config_pack_escr(P4_CONFIG_MASK_ESCR) | \
+ p4_config_pack_cccr(P4_CCCR_EDGE | \
+ P4_CCCR_THRESHOLD_MASK | \
+ P4_CCCR_COMPLEMENT | \
+ P4_CCCR_COMPARE))
+
+#define P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS \
+ ((P4_CONFIG_HT) | \
+ p4_config_pack_escr(P4_ESCR_T0_OS | \
+ P4_ESCR_T0_USR | \
+ P4_ESCR_T1_OS | \
+ P4_ESCR_T1_USR) | \
+ p4_config_pack_cccr(P4_CCCR_OVF | \
+ P4_CCCR_CASCADE | \
+ P4_CCCR_FORCE_OVF | \
+ P4_CCCR_THREAD_ANY | \
+ P4_CCCR_OVF_PMI_T0 | \
+ P4_CCCR_OVF_PMI_T1 | \
+ P4_CONFIG_ALIASABLE))
+
static inline bool p4_is_event_cascaded(u64 config)
{
u32 cccr = p4_config_unpack_cccr(config);
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index d56187c6b838..013286a10c2c 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -107,7 +107,8 @@
#define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
#define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD)
#define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER)
-#define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
+#define __PAGE_KERNEL_VVAR (__PAGE_KERNEL_RO | _PAGE_USER)
+#define __PAGE_KERNEL_VVAR_NOCACHE (__PAGE_KERNEL_VVAR | _PAGE_PCD | _PAGE_PWT)
#define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE)
#define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
#define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE)
@@ -129,7 +130,8 @@
#define PAGE_KERNEL_LARGE_NOCACHE __pgprot(__PAGE_KERNEL_LARGE_NOCACHE)
#define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC)
#define PAGE_KERNEL_VSYSCALL __pgprot(__PAGE_KERNEL_VSYSCALL)
-#define PAGE_KERNEL_VSYSCALL_NOCACHE __pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+#define PAGE_KERNEL_VVAR __pgprot(__PAGE_KERNEL_VVAR)
+#define PAGE_KERNEL_VVAR_NOCACHE __pgprot(__PAGE_KERNEL_VVAR_NOCACHE)
#define PAGE_KERNEL_IO __pgprot(__PAGE_KERNEL_IO)
#define PAGE_KERNEL_IO_NOCACHE __pgprot(__PAGE_KERNEL_IO_NOCACHE)
diff --git a/arch/x86/include/asm/processor-flags.h b/arch/x86/include/asm/processor-flags.h
index 59ab4dffa377..2dddb317bb39 100644
--- a/arch/x86/include/asm/processor-flags.h
+++ b/arch/x86/include/asm/processor-flags.h
@@ -59,6 +59,7 @@
#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
#define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
+#define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
#define X86_CR4_SMEP 0x00100000 /* enable SMEP support */
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index 971e0b46446e..644dd885f05a 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -19,7 +19,7 @@
#include <linux/pci.h>
#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/setup.h>
#include <asm/irq_controller.h>
@@ -30,17 +30,6 @@ extern void add_dtb(u64 data);
extern void x86_add_irq_domains(void);
void __cpuinit x86_of_pci_init(void);
void x86_dtb_init(void);
-
-static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
- return pdev ? pdev->dev.of_node : NULL;
-}
-
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
- return pci_device_to_OF_node(bus->self);
-}
-
#else
static inline void add_dtb(u64 data) { }
static inline void x86_add_irq_domains(void) { }
diff --git a/arch/x86/include/asm/rwlock.h b/arch/x86/include/asm/rwlock.h
index 6a8c0d645108..a5370a03d90c 100644
--- a/arch/x86/include/asm/rwlock.h
+++ b/arch/x86/include/asm/rwlock.h
@@ -1,7 +1,48 @@
#ifndef _ASM_X86_RWLOCK_H
#define _ASM_X86_RWLOCK_H
-#define RW_LOCK_BIAS 0x01000000
+#include <asm/asm.h>
+
+#if CONFIG_NR_CPUS <= 2048
+
+#ifndef __ASSEMBLY__
+typedef union {
+ s32 lock;
+ s32 write;
+} arch_rwlock_t;
+#endif
+
+#define RW_LOCK_BIAS 0x00100000
+#define READ_LOCK_SIZE(insn) __ASM_FORM(insn##l)
+#define READ_LOCK_ATOMIC(n) atomic_##n
+#define WRITE_LOCK_ADD(n) __ASM_FORM_COMMA(addl n)
+#define WRITE_LOCK_SUB(n) __ASM_FORM_COMMA(subl n)
+#define WRITE_LOCK_CMP RW_LOCK_BIAS
+
+#else /* CONFIG_NR_CPUS > 2048 */
+
+#include <linux/const.h>
+
+#ifndef __ASSEMBLY__
+typedef union {
+ s64 lock;
+ struct {
+ u32 read;
+ s32 write;
+ };
+} arch_rwlock_t;
+#endif
+
+#define RW_LOCK_BIAS (_AC(1,L) << 32)
+#define READ_LOCK_SIZE(insn) __ASM_FORM(insn##q)
+#define READ_LOCK_ATOMIC(n) atomic64_##n
+#define WRITE_LOCK_ADD(n) __ASM_FORM(incl)
+#define WRITE_LOCK_SUB(n) __ASM_FORM(decl)
+#define WRITE_LOCK_CMP 1
+
+#endif /* CONFIG_NR_CPUS */
+
+#define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
/* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index cd84f7208f76..5e641715c3fe 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -162,7 +162,7 @@
#define GDT_ENTRY_DEFAULT_USER32_CS 4
#define GDT_ENTRY_DEFAULT_USER_DS 5
#define GDT_ENTRY_DEFAULT_USER_CS 6
-#define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS * 8 + 3)
+#define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8+3)
#define __USER32_DS __USER_DS
#define GDT_ENTRY_TSS 8 /* needs two entries */
diff --git a/arch/x86/include/asm/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h
index 725b77831993..49adfd7bb4a4 100644
--- a/arch/x86/include/asm/smpboot_hooks.h
+++ b/arch/x86/include/asm/smpboot_hooks.h
@@ -10,7 +10,11 @@ static inline void smpboot_clear_io_apic_irqs(void)
static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(0xa, 0xf);
+ spin_unlock_irqrestore(&rtc_lock, flags);
local_flush_tlb();
pr_debug("1.\n");
*((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_high)) =
@@ -23,6 +27,8 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
static inline void smpboot_restore_warm_reset_vector(void)
{
+ unsigned long flags;
+
/*
* Install writable page 0 entry to set BIOS data area.
*/
@@ -32,7 +38,9 @@ static inline void smpboot_restore_warm_reset_vector(void)
* Paranoid: Set warm reset code and vector here back
* to default values.
*/
+ spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(0, 0xf);
+ spin_unlock_irqrestore(&rtc_lock, flags);
*((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0;
}
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index 3089f70c0c52..ee67edf86fdd 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -1,8 +1,7 @@
#ifndef _ASM_X86_SPINLOCK_H
#define _ASM_X86_SPINLOCK_H
-#include <asm/atomic.h>
-#include <asm/rwlock.h>
+#include <linux/atomic.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <linux/compiler.h>
@@ -234,7 +233,7 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
*/
static inline int arch_read_can_lock(arch_rwlock_t *lock)
{
- return (int)(lock)->lock > 0;
+ return lock->lock > 0;
}
/**
@@ -243,12 +242,12 @@ static inline int arch_read_can_lock(arch_rwlock_t *lock)
*/
static inline int arch_write_can_lock(arch_rwlock_t *lock)
{
- return (lock)->lock == RW_LOCK_BIAS;
+ return lock->write == WRITE_LOCK_CMP;
}
static inline void arch_read_lock(arch_rwlock_t *rw)
{
- asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
+ asm volatile(LOCK_PREFIX READ_LOCK_SIZE(dec) " (%0)\n\t"
"jns 1f\n"
"call __read_lock_failed\n\t"
"1:\n"
@@ -257,47 +256,55 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
static inline void arch_write_lock(arch_rwlock_t *rw)
{
- asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t"
+ asm volatile(LOCK_PREFIX WRITE_LOCK_SUB(%1) "(%0)\n\t"
"jz 1f\n"
"call __write_lock_failed\n\t"
"1:\n"
- ::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory");
+ ::LOCK_PTR_REG (&rw->write), "i" (RW_LOCK_BIAS)
+ : "memory");
}
static inline int arch_read_trylock(arch_rwlock_t *lock)
{
- atomic_t *count = (atomic_t *)lock;
+ READ_LOCK_ATOMIC(t) *count = (READ_LOCK_ATOMIC(t) *)lock;
- if (atomic_dec_return(count) >= 0)
+ if (READ_LOCK_ATOMIC(dec_return)(count) >= 0)
return 1;
- atomic_inc(count);
+ READ_LOCK_ATOMIC(inc)(count);
return 0;
}
static inline int arch_write_trylock(arch_rwlock_t *lock)
{
- atomic_t *count = (atomic_t *)lock;
+ atomic_t *count = (atomic_t *)&lock->write;
- if (atomic_sub_and_test(RW_LOCK_BIAS, count))
+ if (atomic_sub_and_test(WRITE_LOCK_CMP, count))
return 1;
- atomic_add(RW_LOCK_BIAS, count);
+ atomic_add(WRITE_LOCK_CMP, count);
return 0;
}
static inline void arch_read_unlock(arch_rwlock_t *rw)
{
- asm volatile(LOCK_PREFIX "incl %0" :"+m" (rw->lock) : : "memory");
+ asm volatile(LOCK_PREFIX READ_LOCK_SIZE(inc) " %0"
+ :"+m" (rw->lock) : : "memory");
}
static inline void arch_write_unlock(arch_rwlock_t *rw)
{
- asm volatile(LOCK_PREFIX "addl %1, %0"
- : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory");
+ asm volatile(LOCK_PREFIX WRITE_LOCK_ADD(%1) "%0"
+ : "+m" (rw->write) : "i" (RW_LOCK_BIAS) : "memory");
}
#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+#undef READ_LOCK_SIZE
+#undef READ_LOCK_ATOMIC
+#undef WRITE_LOCK_ADD
+#undef WRITE_LOCK_SUB
+#undef WRITE_LOCK_CMP
+
#define arch_spin_relax(lock) cpu_relax()
#define arch_read_relax(lock) cpu_relax()
#define arch_write_relax(lock) cpu_relax()
diff --git a/arch/x86/include/asm/spinlock_types.h b/arch/x86/include/asm/spinlock_types.h
index dcb48b2edc11..7c7a486fcb68 100644
--- a/arch/x86/include/asm/spinlock_types.h
+++ b/arch/x86/include/asm/spinlock_types.h
@@ -11,10 +11,6 @@ typedef struct arch_spinlock {
#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
-typedef struct {
- unsigned int lock;
-} arch_rwlock_t;
-
-#define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
+#include <asm/rwlock.h>
#endif /* _ASM_X86_SPINLOCK_TYPES_H */
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 1f2e61e28981..a1fe5c127b52 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -21,7 +21,7 @@ struct task_struct;
struct exec_domain;
#include <asm/processor.h>
#include <asm/ftrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
struct thread_info {
struct task_struct *task; /* main task structure */
diff --git a/arch/x86/include/asm/time.h b/arch/x86/include/asm/time.h
index 7bdec4e9b739..92b8aec06970 100644
--- a/arch/x86/include/asm/time.h
+++ b/arch/x86/include/asm/time.h
@@ -1,10 +1,12 @@
#ifndef _ASM_X86_TIME_H
#define _ASM_X86_TIME_H
-extern void hpet_time_init(void);
-
+#include <linux/clocksource.h>
#include <asm/mc146818rtc.h>
+extern void hpet_time_init(void);
extern void time_init(void);
+extern struct clock_event_device *global_clock_event;
+
#endif /* _ASM_X86_TIME_H */
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 0310da67307f..2bae0a513b40 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -1,6 +1,8 @@
#ifndef _ASM_X86_TRAPS_H
#define _ASM_X86_TRAPS_H
+#include <linux/kprobes.h>
+
#include <asm/debugreg.h>
#include <asm/siginfo.h> /* TRAP_TRACE, ... */
@@ -38,6 +40,7 @@ asmlinkage void alignment_check(void);
asmlinkage void machine_check(void);
#endif /* CONFIG_X86_MCE */
asmlinkage void simd_coprocessor_error(void);
+asmlinkage void emulate_vsyscall(void);
dotraplinkage void do_divide_error(struct pt_regs *, long);
dotraplinkage void do_debug(struct pt_regs *, long);
@@ -64,6 +67,7 @@ dotraplinkage void do_alignment_check(struct pt_regs *, long);
dotraplinkage void do_machine_check(struct pt_regs *, long);
#endif
dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
+dotraplinkage void do_emulate_vsyscall(struct pt_regs *, long);
#ifdef CONFIG_X86_32
dotraplinkage void do_iret_error(struct pt_regs *, long);
#endif
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index 9db5583b6d38..83e2efd181e2 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -51,10 +51,6 @@ extern int unsynchronized_tsc(void);
extern int check_tsc_unstable(void);
extern unsigned long native_calibrate_tsc(void);
-#ifdef CONFIG_X86_64
-extern cycles_t vread_tsc(void);
-#endif
-
/*
* Boot-time check whether the TSCs are synchronized across
* all CPUs/cores:
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 99ddd148a760..36361bf6fdd1 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -555,6 +555,9 @@ struct __large_struct { unsigned long buf[100]; };
#endif /* CONFIG_X86_WP_WORKS_OK */
+extern unsigned long
+copy_from_user_nmi(void *to, const void __user *from, unsigned long n);
+
/*
* movsl can be slow when source and dest are not both 8-byte aligned
*/
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index a291c40efd43..37d369859c8e 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -67,7 +67,7 @@
* we're using 655us, similar to UV1: 65 units of 10us
*/
#define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL)
-#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (65*10UL)
+#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL)
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD (is_uv1_hub() ? \
UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD : \
@@ -106,12 +106,20 @@
#define DS_SOURCE_TIMEOUT 3
/*
* bits put together from HRP_LB_BAU_SB_ACTIVATION_STATUS_0/1/2
- * values 1 and 5 will not occur
+ * values 1 and 3 will not occur
+ * Decoded meaning ERROR BUSY AUX ERR
+ * ------------------------------- ---- ----- -------
+ * IDLE 0 0 0
+ * BUSY (active) 0 1 0
+ * SW Ack Timeout (destination) 1 0 0
+ * SW Ack INTD rejected (strong NACK) 1 0 1
+ * Source Side Time Out Detected 1 1 0
+ * Destination Side PUT Failed 1 1 1
*/
#define UV2H_DESC_IDLE 0
-#define UV2H_DESC_DEST_TIMEOUT 2
-#define UV2H_DESC_DEST_STRONG_NACK 3
-#define UV2H_DESC_BUSY 4
+#define UV2H_DESC_BUSY 2
+#define UV2H_DESC_DEST_TIMEOUT 4
+#define UV2H_DESC_DEST_STRONG_NACK 5
#define UV2H_DESC_SOURCE_TIMEOUT 6
#define UV2H_DESC_DEST_PUT_ERR 7
@@ -183,7 +191,7 @@
* 'base_dest_nasid' field of the header corresponds to the
* destination nodeID associated with that specified bit.
*/
-struct bau_targ_hubmask {
+struct pnmask {
unsigned long bits[BITS_TO_LONGS(UV_DISTRIBUTION_SIZE)];
};
@@ -314,7 +322,7 @@ struct bau_msg_header {
* Should be 64 bytes
*/
struct bau_desc {
- struct bau_targ_hubmask distribution;
+ struct pnmask distribution;
/*
* message template, consisting of header and payload:
*/
@@ -488,6 +496,7 @@ struct bau_control {
struct bau_control *uvhub_master;
struct bau_control *socket_master;
struct ptc_stats *statp;
+ cpumask_t *cpumask;
unsigned long timeout_interval;
unsigned long set_bau_on_time;
atomic_t active_descriptor_count;
@@ -526,90 +535,90 @@ struct bau_control {
struct hub_and_pnode *thp;
};
-static unsigned long read_mmr_uv2_status(void)
+static inline unsigned long read_mmr_uv2_status(void)
{
return read_lmmr(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2);
}
-static void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
+static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
}
-static void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
+static inline void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, mmr_image);
}
-static void write_mmr_activation(unsigned long index)
+static inline void write_mmr_activation(unsigned long index)
{
write_lmmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
}
-static void write_gmmr_activation(int pnode, unsigned long mmr_image)
+static inline void write_gmmr_activation(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, mmr_image);
}
-static void write_mmr_payload_first(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_first(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, mmr_image);
}
-static void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, mmr_image);
}
-static void write_mmr_payload_last(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_last(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST, mmr_image);
}
-static void write_mmr_misc_control(int pnode, unsigned long mmr_image)
+static inline void write_mmr_misc_control(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
}
-static unsigned long read_mmr_misc_control(int pnode)
+static inline unsigned long read_mmr_misc_control(int pnode)
{
return read_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL);
}
-static void write_mmr_sw_ack(unsigned long mr)
+static inline void write_mmr_sw_ack(unsigned long mr)
{
uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
}
-static unsigned long read_mmr_sw_ack(void)
+static inline unsigned long read_mmr_sw_ack(void)
{
return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
}
-static unsigned long read_gmmr_sw_ack(int pnode)
+static inline unsigned long read_gmmr_sw_ack(int pnode)
{
return read_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
}
-static void write_mmr_data_config(int pnode, unsigned long mr)
+static inline void write_mmr_data_config(int pnode, unsigned long mr)
{
uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
}
-static inline int bau_uvhub_isset(int uvhub, struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_isset(int uvhub, struct pnmask *dstp)
{
return constant_test_bit(uvhub, &dstp->bits[0]);
}
-static inline void bau_uvhub_set(int pnode, struct bau_targ_hubmask *dstp)
+static inline void bau_uvhub_set(int pnode, struct pnmask *dstp)
{
__set_bit(pnode, &dstp->bits[0]);
}
-static inline void bau_uvhubs_clear(struct bau_targ_hubmask *dstp,
+static inline void bau_uvhubs_clear(struct pnmask *dstp,
int nbits)
{
bitmap_zero(&dstp->bits[0], nbits);
}
-static inline int bau_uvhub_weight(struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_weight(struct pnmask *dstp)
{
return bitmap_weight((unsigned long *)&dstp->bits[0],
UV_DISTRIBUTION_SIZE);
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h
index 4be52c863448..10474fb1185d 100644
--- a/arch/x86/include/asm/uv/uv_mmrs.h
+++ b/arch/x86/include/asm/uv/uv_mmrs.h
@@ -61,1689 +61,2016 @@
/* Compat: if this #define is present, UV headers support UV2 */
#define UV2_HUB_IS_SUPPORTED 1
-/* KABI compat: if this #define is present, KABI hacks are present */
-#define UV2_HUB_KABI_HACKS 1
-
/* ========================================================================= */
/* UVH_BAU_DATA_BROADCAST */
/* ========================================================================= */
-#define UVH_BAU_DATA_BROADCAST 0x61688UL
-#define UVH_BAU_DATA_BROADCAST_32 0x440
+#define UVH_BAU_DATA_BROADCAST 0x61688UL
+#define UVH_BAU_DATA_BROADCAST_32 0x440
-#define UVH_BAU_DATA_BROADCAST_ENABLE_SHFT 0
-#define UVH_BAU_DATA_BROADCAST_ENABLE_MASK 0x0000000000000001UL
+#define UVH_BAU_DATA_BROADCAST_ENABLE_SHFT 0
+#define UVH_BAU_DATA_BROADCAST_ENABLE_MASK 0x0000000000000001UL
union uvh_bau_data_broadcast_u {
- unsigned long v;
- struct uvh_bau_data_broadcast_s {
- unsigned long enable : 1; /* RW */
- unsigned long rsvd_1_63: 63; /* */
- } s;
+ unsigned long v;
+ struct uvh_bau_data_broadcast_s {
+ unsigned long enable:1; /* RW */
+ unsigned long rsvd_1_63:63;
+ } s;
};
/* ========================================================================= */
/* UVH_BAU_DATA_CONFIG */
/* ========================================================================= */
-#define UVH_BAU_DATA_CONFIG 0x61680UL
-#define UVH_BAU_DATA_CONFIG_32 0x438
-
-#define UVH_BAU_DATA_CONFIG_VECTOR_SHFT 0
-#define UVH_BAU_DATA_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_BAU_DATA_CONFIG_DM_SHFT 8
-#define UVH_BAU_DATA_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_BAU_DATA_CONFIG_DESTMODE_SHFT 11
-#define UVH_BAU_DATA_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_BAU_DATA_CONFIG_STATUS_SHFT 12
-#define UVH_BAU_DATA_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_BAU_DATA_CONFIG_P_SHFT 13
-#define UVH_BAU_DATA_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_BAU_DATA_CONFIG_T_SHFT 15
-#define UVH_BAU_DATA_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_BAU_DATA_CONFIG_M_SHFT 16
-#define UVH_BAU_DATA_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_BAU_DATA_CONFIG_APIC_ID_SHFT 32
-#define UVH_BAU_DATA_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_BAU_DATA_CONFIG 0x61680UL
+#define UVH_BAU_DATA_CONFIG_32 0x438
+
+#define UVH_BAU_DATA_CONFIG_VECTOR_SHFT 0
+#define UVH_BAU_DATA_CONFIG_DM_SHFT 8
+#define UVH_BAU_DATA_CONFIG_DESTMODE_SHFT 11
+#define UVH_BAU_DATA_CONFIG_STATUS_SHFT 12
+#define UVH_BAU_DATA_CONFIG_P_SHFT 13
+#define UVH_BAU_DATA_CONFIG_T_SHFT 15
+#define UVH_BAU_DATA_CONFIG_M_SHFT 16
+#define UVH_BAU_DATA_CONFIG_APIC_ID_SHFT 32
+#define UVH_BAU_DATA_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_BAU_DATA_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_BAU_DATA_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_BAU_DATA_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_BAU_DATA_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_BAU_DATA_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_BAU_DATA_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_BAU_DATA_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
union uvh_bau_data_config_u {
- unsigned long v;
- struct uvh_bau_data_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_bau_data_config_s {
+ unsigned long vector_:8; /* RW */
+ unsigned long dm:3; /* RW */
+ unsigned long destmode:1; /* RW */
+ unsigned long status:1; /* RO */
+ unsigned long p:1; /* RO */
+ unsigned long rsvd_14:1;
+ unsigned long t:1; /* RO */
+ unsigned long m:1; /* RW */
+ unsigned long rsvd_17_31:15;
+ unsigned long apic_id:32; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_EVENT_OCCURRED0 */
/* ========================================================================= */
-#define UVH_EVENT_OCCURRED0 0x70000UL
-#define UVH_EVENT_OCCURRED0_32 0x5e8
-
-#define UV1H_EVENT_OCCURRED0_LB_HCERR_SHFT 0
-#define UV1H_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
-#define UV1H_EVENT_OCCURRED0_GR0_HCERR_SHFT 1
-#define UV1H_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000002UL
-#define UV1H_EVENT_OCCURRED0_GR1_HCERR_SHFT 2
-#define UV1H_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000004UL
-#define UV1H_EVENT_OCCURRED0_LH_HCERR_SHFT 3
-#define UV1H_EVENT_OCCURRED0_LH_HCERR_MASK 0x0000000000000008UL
-#define UV1H_EVENT_OCCURRED0_RH_HCERR_SHFT 4
-#define UV1H_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000010UL
-#define UV1H_EVENT_OCCURRED0_XN_HCERR_SHFT 5
-#define UV1H_EVENT_OCCURRED0_XN_HCERR_MASK 0x0000000000000020UL
-#define UV1H_EVENT_OCCURRED0_SI_HCERR_SHFT 6
-#define UV1H_EVENT_OCCURRED0_SI_HCERR_MASK 0x0000000000000040UL
-#define UV1H_EVENT_OCCURRED0_LB_AOERR0_SHFT 7
-#define UV1H_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000080UL
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_SHFT 8
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000000100UL
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_SHFT 9
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000000200UL
-#define UV1H_EVENT_OCCURRED0_LH_AOERR0_SHFT 10
-#define UV1H_EVENT_OCCURRED0_LH_AOERR0_MASK 0x0000000000000400UL
-#define UV1H_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
-#define UV1H_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
-#define UV1H_EVENT_OCCURRED0_XN_AOERR0_SHFT 12
-#define UV1H_EVENT_OCCURRED0_XN_AOERR0_MASK 0x0000000000001000UL
-#define UV1H_EVENT_OCCURRED0_SI_AOERR0_SHFT 13
-#define UV1H_EVENT_OCCURRED0_SI_AOERR0_MASK 0x0000000000002000UL
-#define UV1H_EVENT_OCCURRED0_LB_AOERR1_SHFT 14
-#define UV1H_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000004000UL
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_SHFT 15
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000000008000UL
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_SHFT 16
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000000010000UL
-#define UV1H_EVENT_OCCURRED0_LH_AOERR1_SHFT 17
-#define UV1H_EVENT_OCCURRED0_LH_AOERR1_MASK 0x0000000000020000UL
-#define UV1H_EVENT_OCCURRED0_RH_AOERR1_SHFT 18
-#define UV1H_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000040000UL
-#define UV1H_EVENT_OCCURRED0_XN_AOERR1_SHFT 19
-#define UV1H_EVENT_OCCURRED0_XN_AOERR1_MASK 0x0000000000080000UL
-#define UV1H_EVENT_OCCURRED0_SI_AOERR1_SHFT 20
-#define UV1H_EVENT_OCCURRED0_SI_AOERR1_MASK 0x0000000000100000UL
-#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_SHFT 21
-#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_MASK 0x0000000000200000UL
-#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 22
-#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000000400000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 23
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000000800000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 24
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000001000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 25
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000002000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 26
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000004000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 27
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000000008000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 28
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000000010000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 29
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000000020000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 30
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000000040000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 31
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000000080000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 32
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000000100000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 33
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000000200000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 34
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000000400000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 35
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000000800000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 36
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000001000000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 37
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000002000000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 38
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000004000000000UL
-#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_SHFT 39
-#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0000008000000000UL
-#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_SHFT 40
-#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0000010000000000UL
-#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 41
-#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0000020000000000UL
-#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 42
-#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0000040000000000UL
-#define UV1H_EVENT_OCCURRED0_LTC_INT_SHFT 43
-#define UV1H_EVENT_OCCURRED0_LTC_INT_MASK 0x0000080000000000UL
-#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 44
-#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0000100000000000UL
-#define UV1H_EVENT_OCCURRED0_IPI_INT_SHFT 45
-#define UV1H_EVENT_OCCURRED0_IPI_INT_MASK 0x0000200000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT 46
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0000400000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_SHFT 47
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0000800000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_SHFT 48
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0001000000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_SHFT 49
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0002000000000000UL
-#define UV1H_EVENT_OCCURRED0_PROFILE_INT_SHFT 50
-#define UV1H_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0004000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC0_SHFT 51
-#define UV1H_EVENT_OCCURRED0_RTC0_MASK 0x0008000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC1_SHFT 52
-#define UV1H_EVENT_OCCURRED0_RTC1_MASK 0x0010000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC2_SHFT 53
-#define UV1H_EVENT_OCCURRED0_RTC2_MASK 0x0020000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC3_SHFT 54
-#define UV1H_EVENT_OCCURRED0_RTC3_MASK 0x0040000000000000UL
-#define UV1H_EVENT_OCCURRED0_BAU_DATA_SHFT 55
-#define UV1H_EVENT_OCCURRED0_BAU_DATA_MASK 0x0080000000000000UL
-#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_SHFT 56
-#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_MASK 0x0100000000000000UL
-
-#define UV2H_EVENT_OCCURRED0_LB_HCERR_SHFT 0
-#define UV2H_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
-#define UV2H_EVENT_OCCURRED0_QP_HCERR_SHFT 1
-#define UV2H_EVENT_OCCURRED0_QP_HCERR_MASK 0x0000000000000002UL
-#define UV2H_EVENT_OCCURRED0_RH_HCERR_SHFT 2
-#define UV2H_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000004UL
-#define UV2H_EVENT_OCCURRED0_LH0_HCERR_SHFT 3
-#define UV2H_EVENT_OCCURRED0_LH0_HCERR_MASK 0x0000000000000008UL
-#define UV2H_EVENT_OCCURRED0_LH1_HCERR_SHFT 4
-#define UV2H_EVENT_OCCURRED0_LH1_HCERR_MASK 0x0000000000000010UL
-#define UV2H_EVENT_OCCURRED0_GR0_HCERR_SHFT 5
-#define UV2H_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000020UL
-#define UV2H_EVENT_OCCURRED0_GR1_HCERR_SHFT 6
-#define UV2H_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000040UL
-#define UV2H_EVENT_OCCURRED0_NI0_HCERR_SHFT 7
-#define UV2H_EVENT_OCCURRED0_NI0_HCERR_MASK 0x0000000000000080UL
-#define UV2H_EVENT_OCCURRED0_NI1_HCERR_SHFT 8
-#define UV2H_EVENT_OCCURRED0_NI1_HCERR_MASK 0x0000000000000100UL
-#define UV2H_EVENT_OCCURRED0_LB_AOERR0_SHFT 9
-#define UV2H_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000200UL
-#define UV2H_EVENT_OCCURRED0_QP_AOERR0_SHFT 10
-#define UV2H_EVENT_OCCURRED0_QP_AOERR0_MASK 0x0000000000000400UL
-#define UV2H_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
-#define UV2H_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_SHFT 12
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_MASK 0x0000000000001000UL
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_SHFT 13
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_MASK 0x0000000000002000UL
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_SHFT 14
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000004000UL
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_SHFT 15
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000008000UL
-#define UV2H_EVENT_OCCURRED0_XB_AOERR0_SHFT 16
-#define UV2H_EVENT_OCCURRED0_XB_AOERR0_MASK 0x0000000000010000UL
-#define UV2H_EVENT_OCCURRED0_RT_AOERR0_SHFT 17
-#define UV2H_EVENT_OCCURRED0_RT_AOERR0_MASK 0x0000000000020000UL
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_SHFT 18
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_MASK 0x0000000000040000UL
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_SHFT 19
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_MASK 0x0000000000080000UL
-#define UV2H_EVENT_OCCURRED0_LB_AOERR1_SHFT 20
-#define UV2H_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000100000UL
-#define UV2H_EVENT_OCCURRED0_QP_AOERR1_SHFT 21
-#define UV2H_EVENT_OCCURRED0_QP_AOERR1_MASK 0x0000000000200000UL
-#define UV2H_EVENT_OCCURRED0_RH_AOERR1_SHFT 22
-#define UV2H_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000400000UL
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_SHFT 23
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_MASK 0x0000000000800000UL
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_SHFT 24
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_MASK 0x0000000001000000UL
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_SHFT 25
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000002000000UL
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_SHFT 26
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000004000000UL
-#define UV2H_EVENT_OCCURRED0_XB_AOERR1_SHFT 27
-#define UV2H_EVENT_OCCURRED0_XB_AOERR1_MASK 0x0000000008000000UL
-#define UV2H_EVENT_OCCURRED0_RT_AOERR1_SHFT 28
-#define UV2H_EVENT_OCCURRED0_RT_AOERR1_MASK 0x0000000010000000UL
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_SHFT 29
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_MASK 0x0000000020000000UL
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_SHFT 30
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_MASK 0x0000000040000000UL
-#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 31
-#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000080000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 32
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000100000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 33
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000200000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 34
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000400000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 35
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000800000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 36
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000001000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 37
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000002000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 38
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000004000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 39
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000008000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 40
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000010000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 41
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000020000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 42
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000040000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 43
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000080000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 44
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000100000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 45
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000200000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 46
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000400000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 47
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000800000000000UL
-#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_SHFT 48
-#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0001000000000000UL
-#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_SHFT 49
-#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0002000000000000UL
-#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 50
-#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0004000000000000UL
-#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 51
-#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0008000000000000UL
-#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 52
-#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0010000000000000UL
-#define UV2H_EVENT_OCCURRED0_IPI_INT_SHFT 53
-#define UV2H_EVENT_OCCURRED0_IPI_INT_MASK 0x0020000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_SHFT 54
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0040000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_SHFT 55
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0080000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_SHFT 56
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0100000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_SHFT 57
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0200000000000000UL
-#define UV2H_EVENT_OCCURRED0_PROFILE_INT_SHFT 58
-#define UV2H_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0400000000000000UL
+#define UVH_EVENT_OCCURRED0 0x70000UL
+#define UVH_EVENT_OCCURRED0_32 0x5e8
+
+#define UV1H_EVENT_OCCURRED0_LB_HCERR_SHFT 0
+#define UV1H_EVENT_OCCURRED0_GR0_HCERR_SHFT 1
+#define UV1H_EVENT_OCCURRED0_GR1_HCERR_SHFT 2
+#define UV1H_EVENT_OCCURRED0_LH_HCERR_SHFT 3
+#define UV1H_EVENT_OCCURRED0_RH_HCERR_SHFT 4
+#define UV1H_EVENT_OCCURRED0_XN_HCERR_SHFT 5
+#define UV1H_EVENT_OCCURRED0_SI_HCERR_SHFT 6
+#define UV1H_EVENT_OCCURRED0_LB_AOERR0_SHFT 7
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_SHFT 8
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_SHFT 9
+#define UV1H_EVENT_OCCURRED0_LH_AOERR0_SHFT 10
+#define UV1H_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
+#define UV1H_EVENT_OCCURRED0_XN_AOERR0_SHFT 12
+#define UV1H_EVENT_OCCURRED0_SI_AOERR0_SHFT 13
+#define UV1H_EVENT_OCCURRED0_LB_AOERR1_SHFT 14
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_SHFT 15
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_SHFT 16
+#define UV1H_EVENT_OCCURRED0_LH_AOERR1_SHFT 17
+#define UV1H_EVENT_OCCURRED0_RH_AOERR1_SHFT 18
+#define UV1H_EVENT_OCCURRED0_XN_AOERR1_SHFT 19
+#define UV1H_EVENT_OCCURRED0_SI_AOERR1_SHFT 20
+#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_SHFT 21
+#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 22
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 23
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 24
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 25
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 26
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 27
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 28
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 29
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 30
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 31
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 32
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 33
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 34
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 35
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 36
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 37
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 38
+#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_SHFT 39
+#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_SHFT 40
+#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 41
+#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 42
+#define UV1H_EVENT_OCCURRED0_LTC_INT_SHFT 43
+#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 44
+#define UV1H_EVENT_OCCURRED0_IPI_INT_SHFT 45
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT 46
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_SHFT 47
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_SHFT 48
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_SHFT 49
+#define UV1H_EVENT_OCCURRED0_PROFILE_INT_SHFT 50
+#define UV1H_EVENT_OCCURRED0_RTC0_SHFT 51
+#define UV1H_EVENT_OCCURRED0_RTC1_SHFT 52
+#define UV1H_EVENT_OCCURRED0_RTC2_SHFT 53
+#define UV1H_EVENT_OCCURRED0_RTC3_SHFT 54
+#define UV1H_EVENT_OCCURRED0_BAU_DATA_SHFT 55
+#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_SHFT 56
+#define UV1H_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
+#define UV1H_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000002UL
+#define UV1H_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000004UL
+#define UV1H_EVENT_OCCURRED0_LH_HCERR_MASK 0x0000000000000008UL
+#define UV1H_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000010UL
+#define UV1H_EVENT_OCCURRED0_XN_HCERR_MASK 0x0000000000000020UL
+#define UV1H_EVENT_OCCURRED0_SI_HCERR_MASK 0x0000000000000040UL
+#define UV1H_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000080UL
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000000100UL
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000000200UL
+#define UV1H_EVENT_OCCURRED0_LH_AOERR0_MASK 0x0000000000000400UL
+#define UV1H_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
+#define UV1H_EVENT_OCCURRED0_XN_AOERR0_MASK 0x0000000000001000UL
+#define UV1H_EVENT_OCCURRED0_SI_AOERR0_MASK 0x0000000000002000UL
+#define UV1H_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000004000UL
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000000008000UL
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000000010000UL
+#define UV1H_EVENT_OCCURRED0_LH_AOERR1_MASK 0x0000000000020000UL
+#define UV1H_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000040000UL
+#define UV1H_EVENT_OCCURRED0_XN_AOERR1_MASK 0x0000000000080000UL
+#define UV1H_EVENT_OCCURRED0_SI_AOERR1_MASK 0x0000000000100000UL
+#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_MASK 0x0000000000200000UL
+#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000000400000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000000800000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000001000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000002000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000004000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000000008000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000000010000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000000020000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000000040000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000000080000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000000100000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000000200000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000000400000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000000800000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000001000000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000002000000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000004000000000UL
+#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0000008000000000UL
+#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0000010000000000UL
+#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0000020000000000UL
+#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0000040000000000UL
+#define UV1H_EVENT_OCCURRED0_LTC_INT_MASK 0x0000080000000000UL
+#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0000100000000000UL
+#define UV1H_EVENT_OCCURRED0_IPI_INT_MASK 0x0000200000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0000400000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0000800000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0001000000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0002000000000000UL
+#define UV1H_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0004000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC0_MASK 0x0008000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC1_MASK 0x0010000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC2_MASK 0x0020000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC3_MASK 0x0040000000000000UL
+#define UV1H_EVENT_OCCURRED0_BAU_DATA_MASK 0x0080000000000000UL
+#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_MASK 0x0100000000000000UL
+
+#define UV2H_EVENT_OCCURRED0_LB_HCERR_SHFT 0
+#define UV2H_EVENT_OCCURRED0_QP_HCERR_SHFT 1
+#define UV2H_EVENT_OCCURRED0_RH_HCERR_SHFT 2
+#define UV2H_EVENT_OCCURRED0_LH0_HCERR_SHFT 3
+#define UV2H_EVENT_OCCURRED0_LH1_HCERR_SHFT 4
+#define UV2H_EVENT_OCCURRED0_GR0_HCERR_SHFT 5
+#define UV2H_EVENT_OCCURRED0_GR1_HCERR_SHFT 6
+#define UV2H_EVENT_OCCURRED0_NI0_HCERR_SHFT 7
+#define UV2H_EVENT_OCCURRED0_NI1_HCERR_SHFT 8
+#define UV2H_EVENT_OCCURRED0_LB_AOERR0_SHFT 9
+#define UV2H_EVENT_OCCURRED0_QP_AOERR0_SHFT 10
+#define UV2H_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_SHFT 12
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_SHFT 13
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_SHFT 14
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_SHFT 15
+#define UV2H_EVENT_OCCURRED0_XB_AOERR0_SHFT 16
+#define UV2H_EVENT_OCCURRED0_RT_AOERR0_SHFT 17
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_SHFT 18
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_SHFT 19
+#define UV2H_EVENT_OCCURRED0_LB_AOERR1_SHFT 20
+#define UV2H_EVENT_OCCURRED0_QP_AOERR1_SHFT 21
+#define UV2H_EVENT_OCCURRED0_RH_AOERR1_SHFT 22
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_SHFT 23
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_SHFT 24
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_SHFT 25
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_SHFT 26
+#define UV2H_EVENT_OCCURRED0_XB_AOERR1_SHFT 27
+#define UV2H_EVENT_OCCURRED0_RT_AOERR1_SHFT 28
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_SHFT 29
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_SHFT 30
+#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 31
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 32
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 33
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 34
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 35
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 36
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 37
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 38
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 39
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 40
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 41
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 42
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 43
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 44
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 45
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 46
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 47
+#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_SHFT 48
+#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_SHFT 49
+#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 50
+#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 51
+#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 52
+#define UV2H_EVENT_OCCURRED0_IPI_INT_SHFT 53
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_SHFT 54
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_SHFT 55
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_SHFT 56
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_SHFT 57
+#define UV2H_EVENT_OCCURRED0_PROFILE_INT_SHFT 58
+#define UV2H_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
+#define UV2H_EVENT_OCCURRED0_QP_HCERR_MASK 0x0000000000000002UL
+#define UV2H_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000004UL
+#define UV2H_EVENT_OCCURRED0_LH0_HCERR_MASK 0x0000000000000008UL
+#define UV2H_EVENT_OCCURRED0_LH1_HCERR_MASK 0x0000000000000010UL
+#define UV2H_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000020UL
+#define UV2H_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000040UL
+#define UV2H_EVENT_OCCURRED0_NI0_HCERR_MASK 0x0000000000000080UL
+#define UV2H_EVENT_OCCURRED0_NI1_HCERR_MASK 0x0000000000000100UL
+#define UV2H_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000200UL
+#define UV2H_EVENT_OCCURRED0_QP_AOERR0_MASK 0x0000000000000400UL
+#define UV2H_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_MASK 0x0000000000001000UL
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_MASK 0x0000000000002000UL
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000004000UL
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000008000UL
+#define UV2H_EVENT_OCCURRED0_XB_AOERR0_MASK 0x0000000000010000UL
+#define UV2H_EVENT_OCCURRED0_RT_AOERR0_MASK 0x0000000000020000UL
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_MASK 0x0000000000040000UL
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_MASK 0x0000000000080000UL
+#define UV2H_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000100000UL
+#define UV2H_EVENT_OCCURRED0_QP_AOERR1_MASK 0x0000000000200000UL
+#define UV2H_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000400000UL
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_MASK 0x0000000000800000UL
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_MASK 0x0000000001000000UL
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000002000000UL
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000004000000UL
+#define UV2H_EVENT_OCCURRED0_XB_AOERR1_MASK 0x0000000008000000UL
+#define UV2H_EVENT_OCCURRED0_RT_AOERR1_MASK 0x0000000010000000UL
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_MASK 0x0000000020000000UL
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_MASK 0x0000000040000000UL
+#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000080000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000100000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000200000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000400000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000800000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000001000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000002000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000004000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000008000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000010000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000020000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000040000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000080000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000100000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000200000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000400000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000800000000000UL
+#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0001000000000000UL
+#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0002000000000000UL
+#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0004000000000000UL
+#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0008000000000000UL
+#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0010000000000000UL
+#define UV2H_EVENT_OCCURRED0_IPI_INT_MASK 0x0020000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0040000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0080000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0100000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0200000000000000UL
+#define UV2H_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0400000000000000UL
union uvh_event_occurred0_u {
- unsigned long v;
- struct uv1h_event_occurred0_s {
- unsigned long lb_hcerr : 1; /* RW, W1C */
- unsigned long gr0_hcerr : 1; /* RW, W1C */
- unsigned long gr1_hcerr : 1; /* RW, W1C */
- unsigned long lh_hcerr : 1; /* RW, W1C */
- unsigned long rh_hcerr : 1; /* RW, W1C */
- unsigned long xn_hcerr : 1; /* RW, W1C */
- unsigned long si_hcerr : 1; /* RW, W1C */
- unsigned long lb_aoerr0 : 1; /* RW, W1C */
- unsigned long gr0_aoerr0 : 1; /* RW, W1C */
- unsigned long gr1_aoerr0 : 1; /* RW, W1C */
- unsigned long lh_aoerr0 : 1; /* RW, W1C */
- unsigned long rh_aoerr0 : 1; /* RW, W1C */
- unsigned long xn_aoerr0 : 1; /* RW, W1C */
- unsigned long si_aoerr0 : 1; /* RW, W1C */
- unsigned long lb_aoerr1 : 1; /* RW, W1C */
- unsigned long gr0_aoerr1 : 1; /* RW, W1C */
- unsigned long gr1_aoerr1 : 1; /* RW, W1C */
- unsigned long lh_aoerr1 : 1; /* RW, W1C */
- unsigned long rh_aoerr1 : 1; /* RW, W1C */
- unsigned long xn_aoerr1 : 1; /* RW, W1C */
- unsigned long si_aoerr1 : 1; /* RW, W1C */
- unsigned long rh_vpi_int : 1; /* RW, W1C */
- unsigned long system_shutdown_int : 1; /* RW, W1C */
- unsigned long lb_irq_int_0 : 1; /* RW, W1C */
- unsigned long lb_irq_int_1 : 1; /* RW, W1C */
- unsigned long lb_irq_int_2 : 1; /* RW, W1C */
- unsigned long lb_irq_int_3 : 1; /* RW, W1C */
- unsigned long lb_irq_int_4 : 1; /* RW, W1C */
- unsigned long lb_irq_int_5 : 1; /* RW, W1C */
- unsigned long lb_irq_int_6 : 1; /* RW, W1C */
- unsigned long lb_irq_int_7 : 1; /* RW, W1C */
- unsigned long lb_irq_int_8 : 1; /* RW, W1C */
- unsigned long lb_irq_int_9 : 1; /* RW, W1C */
- unsigned long lb_irq_int_10 : 1; /* RW, W1C */
- unsigned long lb_irq_int_11 : 1; /* RW, W1C */
- unsigned long lb_irq_int_12 : 1; /* RW, W1C */
- unsigned long lb_irq_int_13 : 1; /* RW, W1C */
- unsigned long lb_irq_int_14 : 1; /* RW, W1C */
- unsigned long lb_irq_int_15 : 1; /* RW, W1C */
- unsigned long l1_nmi_int : 1; /* RW, W1C */
- unsigned long stop_clock : 1; /* RW, W1C */
- unsigned long asic_to_l1 : 1; /* RW, W1C */
- unsigned long l1_to_asic : 1; /* RW, W1C */
- unsigned long ltc_int : 1; /* RW, W1C */
- unsigned long la_seq_trigger : 1; /* RW, W1C */
- unsigned long ipi_int : 1; /* RW, W1C */
- unsigned long extio_int0 : 1; /* RW, W1C */
- unsigned long extio_int1 : 1; /* RW, W1C */
- unsigned long extio_int2 : 1; /* RW, W1C */
- unsigned long extio_int3 : 1; /* RW, W1C */
- unsigned long profile_int : 1; /* RW, W1C */
- unsigned long rtc0 : 1; /* RW, W1C */
- unsigned long rtc1 : 1; /* RW, W1C */
- unsigned long rtc2 : 1; /* RW, W1C */
- unsigned long rtc3 : 1; /* RW, W1C */
- unsigned long bau_data : 1; /* RW, W1C */
- unsigned long power_management_req : 1; /* RW, W1C */
- unsigned long rsvd_57_63 : 7; /* */
- } s1;
- struct uv2h_event_occurred0_s {
- unsigned long lb_hcerr : 1; /* RW */
- unsigned long qp_hcerr : 1; /* RW */
- unsigned long rh_hcerr : 1; /* RW */
- unsigned long lh0_hcerr : 1; /* RW */
- unsigned long lh1_hcerr : 1; /* RW */
- unsigned long gr0_hcerr : 1; /* RW */
- unsigned long gr1_hcerr : 1; /* RW */
- unsigned long ni0_hcerr : 1; /* RW */
- unsigned long ni1_hcerr : 1; /* RW */
- unsigned long lb_aoerr0 : 1; /* RW */
- unsigned long qp_aoerr0 : 1; /* RW */
- unsigned long rh_aoerr0 : 1; /* RW */
- unsigned long lh0_aoerr0 : 1; /* RW */
- unsigned long lh1_aoerr0 : 1; /* RW */
- unsigned long gr0_aoerr0 : 1; /* RW */
- unsigned long gr1_aoerr0 : 1; /* RW */
- unsigned long xb_aoerr0 : 1; /* RW */
- unsigned long rt_aoerr0 : 1; /* RW */
- unsigned long ni0_aoerr0 : 1; /* RW */
- unsigned long ni1_aoerr0 : 1; /* RW */
- unsigned long lb_aoerr1 : 1; /* RW */
- unsigned long qp_aoerr1 : 1; /* RW */
- unsigned long rh_aoerr1 : 1; /* RW */
- unsigned long lh0_aoerr1 : 1; /* RW */
- unsigned long lh1_aoerr1 : 1; /* RW */
- unsigned long gr0_aoerr1 : 1; /* RW */
- unsigned long gr1_aoerr1 : 1; /* RW */
- unsigned long xb_aoerr1 : 1; /* RW */
- unsigned long rt_aoerr1 : 1; /* RW */
- unsigned long ni0_aoerr1 : 1; /* RW */
- unsigned long ni1_aoerr1 : 1; /* RW */
- unsigned long system_shutdown_int : 1; /* RW */
- unsigned long lb_irq_int_0 : 1; /* RW */
- unsigned long lb_irq_int_1 : 1; /* RW */
- unsigned long lb_irq_int_2 : 1; /* RW */
- unsigned long lb_irq_int_3 : 1; /* RW */
- unsigned long lb_irq_int_4 : 1; /* RW */
- unsigned long lb_irq_int_5 : 1; /* RW */
- unsigned long lb_irq_int_6 : 1; /* RW */
- unsigned long lb_irq_int_7 : 1; /* RW */
- unsigned long lb_irq_int_8 : 1; /* RW */
- unsigned long lb_irq_int_9 : 1; /* RW */
- unsigned long lb_irq_int_10 : 1; /* RW */
- unsigned long lb_irq_int_11 : 1; /* RW */
- unsigned long lb_irq_int_12 : 1; /* RW */
- unsigned long lb_irq_int_13 : 1; /* RW */
- unsigned long lb_irq_int_14 : 1; /* RW */
- unsigned long lb_irq_int_15 : 1; /* RW */
- unsigned long l1_nmi_int : 1; /* RW */
- unsigned long stop_clock : 1; /* RW */
- unsigned long asic_to_l1 : 1; /* RW */
- unsigned long l1_to_asic : 1; /* RW */
- unsigned long la_seq_trigger : 1; /* RW */
- unsigned long ipi_int : 1; /* RW */
- unsigned long extio_int0 : 1; /* RW */
- unsigned long extio_int1 : 1; /* RW */
- unsigned long extio_int2 : 1; /* RW */
- unsigned long extio_int3 : 1; /* RW */
- unsigned long profile_int : 1; /* RW */
- unsigned long rsvd_59_63 : 5; /* */
- } s2;
+ unsigned long v;
+ struct uv1h_event_occurred0_s {
+ unsigned long lb_hcerr:1; /* RW, W1C */
+ unsigned long gr0_hcerr:1; /* RW, W1C */
+ unsigned long gr1_hcerr:1; /* RW, W1C */
+ unsigned long lh_hcerr:1; /* RW, W1C */
+ unsigned long rh_hcerr:1; /* RW, W1C */
+ unsigned long xn_hcerr:1; /* RW, W1C */
+ unsigned long si_hcerr:1; /* RW, W1C */
+ unsigned long lb_aoerr0:1; /* RW, W1C */
+ unsigned long gr0_aoerr0:1; /* RW, W1C */
+ unsigned long gr1_aoerr0:1; /* RW, W1C */
+ unsigned long lh_aoerr0:1; /* RW, W1C */
+ unsigned long rh_aoerr0:1; /* RW, W1C */
+ unsigned long xn_aoerr0:1; /* RW, W1C */
+ unsigned long si_aoerr0:1; /* RW, W1C */
+ unsigned long lb_aoerr1:1; /* RW, W1C */
+ unsigned long gr0_aoerr1:1; /* RW, W1C */
+ unsigned long gr1_aoerr1:1; /* RW, W1C */
+ unsigned long lh_aoerr1:1; /* RW, W1C */
+ unsigned long rh_aoerr1:1; /* RW, W1C */
+ unsigned long xn_aoerr1:1; /* RW, W1C */
+ unsigned long si_aoerr1:1; /* RW, W1C */
+ unsigned long rh_vpi_int:1; /* RW, W1C */
+ unsigned long system_shutdown_int:1; /* RW, W1C */
+ unsigned long lb_irq_int_0:1; /* RW, W1C */
+ unsigned long lb_irq_int_1:1; /* RW, W1C */
+ unsigned long lb_irq_int_2:1; /* RW, W1C */
+ unsigned long lb_irq_int_3:1; /* RW, W1C */
+ unsigned long lb_irq_int_4:1; /* RW, W1C */
+ unsigned long lb_irq_int_5:1; /* RW, W1C */
+ unsigned long lb_irq_int_6:1; /* RW, W1C */
+ unsigned long lb_irq_int_7:1; /* RW, W1C */
+ unsigned long lb_irq_int_8:1; /* RW, W1C */
+ unsigned long lb_irq_int_9:1; /* RW, W1C */
+ unsigned long lb_irq_int_10:1; /* RW, W1C */
+ unsigned long lb_irq_int_11:1; /* RW, W1C */
+ unsigned long lb_irq_int_12:1; /* RW, W1C */
+ unsigned long lb_irq_int_13:1; /* RW, W1C */
+ unsigned long lb_irq_int_14:1; /* RW, W1C */
+ unsigned long lb_irq_int_15:1; /* RW, W1C */
+ unsigned long l1_nmi_int:1; /* RW, W1C */
+ unsigned long stop_clock:1; /* RW, W1C */
+ unsigned long asic_to_l1:1; /* RW, W1C */
+ unsigned long l1_to_asic:1; /* RW, W1C */
+ unsigned long ltc_int:1; /* RW, W1C */
+ unsigned long la_seq_trigger:1; /* RW, W1C */
+ unsigned long ipi_int:1; /* RW, W1C */
+ unsigned long extio_int0:1; /* RW, W1C */
+ unsigned long extio_int1:1; /* RW, W1C */
+ unsigned long extio_int2:1; /* RW, W1C */
+ unsigned long extio_int3:1; /* RW, W1C */
+ unsigned long profile_int:1; /* RW, W1C */
+ unsigned long rtc0:1; /* RW, W1C */
+ unsigned long rtc1:1; /* RW, W1C */
+ unsigned long rtc2:1; /* RW, W1C */
+ unsigned long rtc3:1; /* RW, W1C */
+ unsigned long bau_data:1; /* RW, W1C */
+ unsigned long power_management_req:1; /* RW, W1C */
+ unsigned long rsvd_57_63:7;
+ } s1;
+ struct uv2h_event_occurred0_s {
+ unsigned long lb_hcerr:1; /* RW */
+ unsigned long qp_hcerr:1; /* RW */
+ unsigned long rh_hcerr:1; /* RW */
+ unsigned long lh0_hcerr:1; /* RW */
+ unsigned long lh1_hcerr:1; /* RW */
+ unsigned long gr0_hcerr:1; /* RW */
+ unsigned long gr1_hcerr:1; /* RW */
+ unsigned long ni0_hcerr:1; /* RW */
+ unsigned long ni1_hcerr:1; /* RW */
+ unsigned long lb_aoerr0:1; /* RW */
+ unsigned long qp_aoerr0:1; /* RW */
+ unsigned long rh_aoerr0:1; /* RW */
+ unsigned long lh0_aoerr0:1; /* RW */
+ unsigned long lh1_aoerr0:1; /* RW */
+ unsigned long gr0_aoerr0:1; /* RW */
+ unsigned long gr1_aoerr0:1; /* RW */
+ unsigned long xb_aoerr0:1; /* RW */
+ unsigned long rt_aoerr0:1; /* RW */
+ unsigned long ni0_aoerr0:1; /* RW */
+ unsigned long ni1_aoerr0:1; /* RW */
+ unsigned long lb_aoerr1:1; /* RW */
+ unsigned long qp_aoerr1:1; /* RW */
+ unsigned long rh_aoerr1:1; /* RW */
+ unsigned long lh0_aoerr1:1; /* RW */
+ unsigned long lh1_aoerr1:1; /* RW */
+ unsigned long gr0_aoerr1:1; /* RW */
+ unsigned long gr1_aoerr1:1; /* RW */
+ unsigned long xb_aoerr1:1; /* RW */
+ unsigned long rt_aoerr1:1; /* RW */
+ unsigned long ni0_aoerr1:1; /* RW */
+ unsigned long ni1_aoerr1:1; /* RW */
+ unsigned long system_shutdown_int:1; /* RW */
+ unsigned long lb_irq_int_0:1; /* RW */
+ unsigned long lb_irq_int_1:1; /* RW */
+ unsigned long lb_irq_int_2:1; /* RW */
+ unsigned long lb_irq_int_3:1; /* RW */
+ unsigned long lb_irq_int_4:1; /* RW */
+ unsigned long lb_irq_int_5:1; /* RW */
+ unsigned long lb_irq_int_6:1; /* RW */
+ unsigned long lb_irq_int_7:1; /* RW */
+ unsigned long lb_irq_int_8:1; /* RW */
+ unsigned long lb_irq_int_9:1; /* RW */
+ unsigned long lb_irq_int_10:1; /* RW */
+ unsigned long lb_irq_int_11:1; /* RW */
+ unsigned long lb_irq_int_12:1; /* RW */
+ unsigned long lb_irq_int_13:1; /* RW */
+ unsigned long lb_irq_int_14:1; /* RW */
+ unsigned long lb_irq_int_15:1; /* RW */
+ unsigned long l1_nmi_int:1; /* RW */
+ unsigned long stop_clock:1; /* RW */
+ unsigned long asic_to_l1:1; /* RW */
+ unsigned long l1_to_asic:1; /* RW */
+ unsigned long la_seq_trigger:1; /* RW */
+ unsigned long ipi_int:1; /* RW */
+ unsigned long extio_int0:1; /* RW */
+ unsigned long extio_int1:1; /* RW */
+ unsigned long extio_int2:1; /* RW */
+ unsigned long extio_int3:1; /* RW */
+ unsigned long profile_int:1; /* RW */
+ unsigned long rsvd_59_63:5;
+ } s2;
};
/* ========================================================================= */
/* UVH_EVENT_OCCURRED0_ALIAS */
/* ========================================================================= */
-#define UVH_EVENT_OCCURRED0_ALIAS 0x0000000000070008UL
-#define UVH_EVENT_OCCURRED0_ALIAS_32 0x5f0
+#define UVH_EVENT_OCCURRED0_ALIAS 0x0000000000070008UL
+#define UVH_EVENT_OCCURRED0_ALIAS_32 0x5f0
/* ========================================================================= */
/* UVH_GR0_TLB_INT0_CONFIG */
/* ========================================================================= */
-#define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL
-
-#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_SHFT 0
-#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR0_TLB_INT0_CONFIG_DM_SHFT 8
-#define UVH_GR0_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR0_TLB_INT0_CONFIG_STATUS_SHFT 12
-#define UVH_GR0_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR0_TLB_INT0_CONFIG_P_SHFT 13
-#define UVH_GR0_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR0_TLB_INT0_CONFIG_T_SHFT 15
-#define UVH_GR0_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR0_TLB_INT0_CONFIG_M_SHFT 16
-#define UVH_GR0_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL
+
+#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_SHFT 0
+#define UVH_GR0_TLB_INT0_CONFIG_DM_SHFT 8
+#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_SHFT 11
+#define UVH_GR0_TLB_INT0_CONFIG_STATUS_SHFT 12
+#define UVH_GR0_TLB_INT0_CONFIG_P_SHFT 13
+#define UVH_GR0_TLB_INT0_CONFIG_T_SHFT 15
+#define UVH_GR0_TLB_INT0_CONFIG_M_SHFT 16
+#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_SHFT 32
+#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_GR0_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_GR0_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_GR0_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_GR0_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_GR0_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
union uvh_gr0_tlb_int0_config_u {
- unsigned long v;
- struct uvh_gr0_tlb_int0_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_gr0_tlb_int0_config_s {
+ unsigned long vector_:8; /* RW */
+ unsigned long dm:3; /* RW */
+ unsigned long destmode:1; /* RW */
+ unsigned long status:1; /* RO */
+ unsigned long p:1; /* RO */
+ unsigned long rsvd_14:1;
+ unsigned long t:1; /* RO */
+ unsigned long m:1; /* RW */
+ unsigned long rsvd_17_31:15;
+ unsigned long apic_id:32; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_GR0_TLB_INT1_CONFIG */
/* ========================================================================= */
-#define UVH_GR0_TLB_INT1_CONFIG 0x61b40UL
-
-#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_SHFT 0
-#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR0_TLB_INT1_CONFIG_DM_SHFT 8
-#define UVH_GR0_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR0_TLB_INT1_CONFIG_STATUS_SHFT 12
-#define UVH_GR0_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR0_TLB_INT1_CONFIG_P_SHFT 13
-#define UVH_GR0_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR0_TLB_INT1_CONFIG_T_SHFT 15
-#define UVH_GR0_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR0_TLB_INT1_CONFIG_M_SHFT 16
-#define UVH_GR0_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR0_TLB_INT1_CONFIG 0x61b40UL
+
+#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_SHFT 0
+#define UVH_GR0_TLB_INT1_CONFIG_DM_SHFT 8
+#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_SHFT 11
+#define UVH_GR0_TLB_INT1_CONFIG_STATUS_SHFT 12
+#define UVH_GR0_TLB_INT1_CONFIG_P_SHFT 13
+#define UVH_GR0_TLB_INT1_CONFIG_T_SHFT 15
+#define UVH_GR0_TLB_INT1_CONFIG_M_SHFT 16
+#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_SHFT 32
+#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_GR0_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_GR0_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_GR0_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_GR0_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_GR0_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
union uvh_gr0_tlb_int1_config_u {
- unsigned long v;
- struct uvh_gr0_tlb_int1_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_gr0_tlb_int1_config_s {
+ unsigned long vector_:8; /* RW */
+ unsigned long dm:3; /* RW */
+ unsigned long destmode:1; /* RW */
+ unsigned long status:1; /* RO */
+ unsigned long p:1; /* RO */
+ unsigned long rsvd_14:1;
+ unsigned long t:1; /* RO */
+ unsigned long m:1; /* RW */
+ unsigned long rsvd_17_31:15;
+ unsigned long apic_id:32; /* RW */
+ } s;
+};
+
+/* ========================================================================= */
+/* UVH_GR0_TLB_MMR_CONTROL */
+/* ========================================================================= */
+#define UV1H_GR0_TLB_MMR_CONTROL 0x401080UL
+#define UV2H_GR0_TLB_MMR_CONTROL 0xc01080UL
+#define UVH_GR0_TLB_MMR_CONTROL (is_uv1_hub() ? \
+ UV1H_GR0_TLB_MMR_CONTROL : \
+ UV2H_GR0_TLB_MMR_CONTROL)
+
+#define UVH_GR0_TLB_MMR_CONTROL_INDEX_SHFT 0
+#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT 12
+#define UVH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT 16
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT 20
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT 30
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT 31
+#define UVH_GR0_TLB_MMR_CONTROL_INDEX_MASK 0x0000000000000fffUL
+#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK 0x0000000000003000UL
+#define UVH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK 0x0000000000010000UL
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK 0x0000000000100000UL
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK 0x0000000040000000UL
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_READ_MASK 0x0000000080000000UL
+
+#define UV1H_GR0_TLB_MMR_CONTROL_INDEX_SHFT 0
+#define UV1H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT 12
+#define UV1H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT 16
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT 20
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT 30
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT 31
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT 48
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT 52
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_SHFT 54
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_SHFT 56
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_SHFT 60
+#define UV1H_GR0_TLB_MMR_CONTROL_INDEX_MASK 0x0000000000000fffUL
+#define UV1H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK 0x0000000000003000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK 0x0000000000010000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK 0x0000000000100000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK 0x0000000040000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_READ_MASK 0x0000000080000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_MASK 0x0001000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK 0x0010000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_MASK 0x0040000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_MASK 0x0100000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_MASK 0x1000000000000000UL
+
+#define UV2H_GR0_TLB_MMR_CONTROL_INDEX_SHFT 0
+#define UV2H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT 12
+#define UV2H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT 16
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT 20
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT 30
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT 31
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT 32
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT 48
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT 52
+#define UV2H_GR0_TLB_MMR_CONTROL_INDEX_MASK 0x0000000000000fffUL
+#define UV2H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK 0x0000000000003000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK 0x0000000000010000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK 0x0000000000100000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK 0x0000000040000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_READ_MASK 0x0000000080000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_MASK 0x0000000100000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_MASK 0x0001000000000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK 0x0010000000000000UL
+
+union uvh_gr0_tlb_mmr_control_u {
+ unsigned long v;
+ struct uvh_gr0_tlb_mmr_control_s {
+ unsigned long index:12; /* RW */
+ unsigned long mem_sel:2; /* RW */
+ unsigned long rsvd_14_15:2;
+ unsigned long auto_valid_en:1; /* RW */
+ unsigned long rsvd_17_19:3;
+ unsigned long mmr_hash_index_en:1; /* RW */
+ unsigned long rsvd_21_29:9;
+ unsigned long mmr_write:1; /* WP */
+ unsigned long mmr_read:1; /* WP */
+ unsigned long rsvd_32_63:32;
+ } s;
+ struct uv1h_gr0_tlb_mmr_control_s {
+ unsigned long index:12; /* RW */
+ unsigned long mem_sel:2; /* RW */
+ unsigned long rsvd_14_15:2;
+ unsigned long auto_valid_en:1; /* RW */
+ unsigned long rsvd_17_19:3;
+ unsigned long mmr_hash_index_en:1; /* RW */
+ unsigned long rsvd_21_29:9;
+ unsigned long mmr_write:1; /* WP */
+ unsigned long mmr_read:1; /* WP */
+ unsigned long rsvd_32_47:16;
+ unsigned long mmr_inj_con:1; /* RW */
+ unsigned long rsvd_49_51:3;
+ unsigned long mmr_inj_tlbram:1; /* RW */
+ unsigned long rsvd_53:1;
+ unsigned long mmr_inj_tlbpgsize:1; /* RW */
+ unsigned long rsvd_55:1;
+ unsigned long mmr_inj_tlbrreg:1; /* RW */
+ unsigned long rsvd_57_59:3;
+ unsigned long mmr_inj_tlblruv:1; /* RW */
+ unsigned long rsvd_61_63:3;
+ } s1;
+ struct uv2h_gr0_tlb_mmr_control_s {
+ unsigned long index:12; /* RW */
+ unsigned long mem_sel:2; /* RW */
+ unsigned long rsvd_14_15:2;
+ unsigned long auto_valid_en:1; /* RW */
+ unsigned long rsvd_17_19:3;
+ unsigned long mmr_hash_index_en:1; /* RW */
+ unsigned long rsvd_21_29:9;
+ unsigned long mmr_write:1; /* WP */
+ unsigned long mmr_read:1; /* WP */
+ unsigned long mmr_op_done:1; /* RW */
+ unsigned long rsvd_33_47:15;
+ unsigned long mmr_inj_con:1; /* RW */
+ unsigned long rsvd_49_51:3;
+ unsigned long mmr_inj_tlbram:1; /* RW */
+ unsigned long rsvd_53_63:11;
+ } s2;
+};
+
+/* ========================================================================= */
+/* UVH_GR0_TLB_MMR_READ_DATA_HI */
+/* ========================================================================= */
+#define UV1H_GR0_TLB_MMR_READ_DATA_HI 0x4010a0UL
+#define UV2H_GR0_TLB_MMR_READ_DATA_HI 0xc010a0UL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI (is_uv1_hub() ? \
+ UV1H_GR0_TLB_MMR_READ_DATA_HI : \
+ UV2H_GR0_TLB_MMR_READ_DATA_HI)
+
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_PFN_SHFT 0
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_GAA_SHFT 41
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_SHFT 43
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_LARGER_SHFT 44
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_PFN_MASK 0x000001ffffffffffUL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_GAA_MASK 0x0000060000000000UL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_MASK 0x0000080000000000UL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_LARGER_MASK 0x0000100000000000UL
+
+union uvh_gr0_tlb_mmr_read_data_hi_u {
+ unsigned long v;
+ struct uvh_gr0_tlb_mmr_read_data_hi_s {
+ unsigned long pfn:41; /* RO */
+ unsigned long gaa:2; /* RO */
+ unsigned long dirty:1; /* RO */
+ unsigned long larger:1; /* RO */
+ unsigned long rsvd_45_63:19;
+ } s;
+};
+
+/* ========================================================================= */
+/* UVH_GR0_TLB_MMR_READ_DATA_LO */
+/* ========================================================================= */
+#define UV1H_GR0_TLB_MMR_READ_DATA_LO 0x4010a8UL
+#define UV2H_GR0_TLB_MMR_READ_DATA_LO 0xc010a8UL
+#define UVH_GR0_TLB_MMR_READ_DATA_LO (is_uv1_hub() ? \
+ UV1H_GR0_TLB_MMR_READ_DATA_LO : \
+ UV2H_GR0_TLB_MMR_READ_DATA_LO)
+
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VPN_SHFT 0
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_ASID_SHFT 39
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VALID_SHFT 63
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VPN_MASK 0x0000007fffffffffUL
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_ASID_MASK 0x7fffff8000000000UL
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VALID_MASK 0x8000000000000000UL
+
+union uvh_gr0_tlb_mmr_read_data_lo_u {
+ unsigned long v;
+ struct uvh_gr0_tlb_mmr_read_data_lo_s {
+ unsigned long vpn:39; /* RO */
+ unsigned long asid:24; /* RO */
+ unsigned long valid:1; /* RO */
+ } s;
};
/* ========================================================================= */
/* UVH_GR1_TLB_INT0_CONFIG */
/* ========================================================================= */
-#define UVH_GR1_TLB_INT0_CONFIG 0x61f00UL
-
-#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_SHFT 0
-#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR1_TLB_INT0_CONFIG_DM_SHFT 8
-#define UVH_GR1_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR1_TLB_INT0_CONFIG_STATUS_SHFT 12
-#define UVH_GR1_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR1_TLB_INT0_CONFIG_P_SHFT 13
-#define UVH_GR1_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR1_TLB_INT0_CONFIG_T_SHFT 15
-#define UVH_GR1_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR1_TLB_INT0_CONFIG_M_SHFT 16
-#define UVH_GR1_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR1_TLB_INT0_CONFIG 0x61f00UL
+
+#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_SHFT 0
+#define UVH_GR1_TLB_INT0_CONFIG_DM_SHFT 8
+#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_SHFT 11
+#define UVH_GR1_TLB_INT0_CONFIG_STATUS_SHFT 12
+#define UVH_GR1_TLB_INT0_CONFIG_P_SHFT 13
+#define UVH_GR1_TLB_INT0_CONFIG_T_SHFT 15
+#define UVH_GR1_TLB_INT0_CONFIG_M_SHFT 16
+#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_SHFT 32
+#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_GR1_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_GR1_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_GR1_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_GR1_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_GR1_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
union uvh_gr1_tlb_int0_config_u {
- unsigned long v;
- struct uvh_gr1_tlb_int0_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_gr1_tlb_int0_config_s {
+ unsigned long vector_:8; /* RW */
+ unsigned long dm:3; /* RW */
+ unsigned long destmode:1; /* RW */
+ unsigned long status:1; /* RO */
+ unsigned long p:1; /* RO */
+ unsigned long rsvd_14:1;
+ unsigned long t:1; /* RO */
+ unsigned long m:1; /* RW */
+ unsigned long rsvd_17_31:15;
+ unsigned long apic_id:32; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_GR1_TLB_INT1_CONFIG */
/* ========================================================================= */
-#define UVH_GR1_TLB_INT1_CONFIG 0x61f40UL
-
-#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_SHFT 0
-#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR1_TLB_INT1_CONFIG_DM_SHFT 8
-#define UVH_GR1_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR1_TLB_INT1_CONFIG_STATUS_SHFT 12
-#define UVH_GR1_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR1_TLB_INT1_CONFIG_P_SHFT 13
-#define UVH_GR1_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR1_TLB_INT1_CONFIG_T_SHFT 15
-#define UVH_GR1_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR1_TLB_INT1_CONFIG_M_SHFT 16
-#define UVH_GR1_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR1_TLB_INT1_CONFIG 0x61f40UL
+
+#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_SHFT 0
+#define UVH_GR1_TLB_INT1_CONFIG_DM_SHFT 8
+#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_SHFT 11
+#define UVH_GR1_TLB_INT1_CONFIG_STATUS_SHFT 12
+#define UVH_GR1_TLB_INT1_CONFIG_P_SHFT 13
+#define UVH_GR1_TLB_INT1_CONFIG_T_SHFT 15
+#define UVH_GR1_TLB_INT1_CONFIG_M_SHFT 16
+#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_SHFT 32
+#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_GR1_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_GR1_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_GR1_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_GR1_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_GR1_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
union uvh_gr1_tlb_int1_config_u {
- unsigned long v;
- struct uvh_gr1_tlb_int1_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_gr1_tlb_int1_config_s {
+ unsigned long vector_:8; /* RW */
+ unsigned long dm:3; /* RW */
+ unsigned long destmode:1; /* RW */
+ unsigned long status:1; /* RO */
+ unsigned long p:1; /* RO */
+ unsigned long rsvd_14:1;
+ unsigned long t:1; /* RO */
+ unsigned long m:1; /* RW */
+ unsigned long rsvd_17_31:15;
+ unsigned long apic_id:32; /* RW */
+ } s;
+};
+
+/* ========================================================================= */
+/* UVH_GR1_TLB_MMR_CONTROL */
+/* ========================================================================= */
+#define UV1H_GR1_TLB_MMR_CONTROL 0x801080UL
+#define UV2H_GR1_TLB_MMR_CONTROL 0x1001080UL
+#define UVH_GR1_TLB_MMR_CONTROL (is_uv1_hub() ? \
+ UV1H_GR1_TLB_MMR_CONTROL : \
+ UV2H_GR1_TLB_MMR_CONTROL)
+
+#define UVH_GR1_TLB_MMR_CONTROL_INDEX_SHFT 0
+#define UVH_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT 12
+#define UVH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT 16
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT 20
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT 30
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT 31
+#define UVH_GR1_TLB_MMR_CONTROL_INDEX_MASK 0x0000000000000fffUL
+#define UVH_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK 0x0000000000003000UL
+#define UVH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK 0x0000000000010000UL
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK 0x0000000000100000UL
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK 0x0000000040000000UL
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_READ_MASK 0x0000000080000000UL
+
+#define UV1H_GR1_TLB_MMR_CONTROL_INDEX_SHFT 0
+#define UV1H_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT 12
+#define UV1H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT 16
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT 20
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT 30
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT 31
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT 48
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT 52
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_SHFT 54
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_SHFT 56
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_SHFT 60
+#define UV1H_GR1_TLB_MMR_CONTROL_INDEX_MASK 0x0000000000000fffUL
+#define UV1H_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK 0x0000000000003000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK 0x0000000000010000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK 0x0000000000100000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK 0x0000000040000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_READ_MASK 0x0000000080000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_MASK 0x0001000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK 0x0010000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_MASK 0x0040000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_MASK 0x0100000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_MASK 0x1000000000000000UL
+
+#define UV2H_GR1_TLB_MMR_CONTROL_INDEX_SHFT 0
+#define UV2H_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT 12
+#define UV2H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT 16
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT 20
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT 30
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT 31
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT 32
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT 48
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT 52
+#define UV2H_GR1_TLB_MMR_CONTROL_INDEX_MASK 0x0000000000000fffUL
+#define UV2H_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK 0x0000000000003000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK 0x0000000000010000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK 0x0000000000100000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK 0x0000000040000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_READ_MASK 0x0000000080000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_MASK 0x0000000100000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_MASK 0x0001000000000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK 0x0010000000000000UL
+
+union uvh_gr1_tlb_mmr_control_u {
+ unsigned long v;
+ struct uvh_gr1_tlb_mmr_control_s {
+ unsigned long index:12; /* RW */
+ unsigned long mem_sel:2; /* RW */
+ unsigned long rsvd_14_15:2;
+ unsigned long auto_valid_en:1; /* RW */
+ unsigned long rsvd_17_19:3;
+ unsigned long mmr_hash_index_en:1; /* RW */
+ unsigned long rsvd_21_29:9;
+ unsigned long mmr_write:1; /* WP */
+ unsigned long mmr_read:1; /* WP */
+ unsigned long rsvd_32_63:32;
+ } s;
+ struct uv1h_gr1_tlb_mmr_control_s {
+ unsigned long index:12; /* RW */
+ unsigned long mem_sel:2; /* RW */
+ unsigned long rsvd_14_15:2;
+ unsigned long auto_valid_en:1; /* RW */
+ unsigned long rsvd_17_19:3;
+ unsigned long mmr_hash_index_en:1; /* RW */
+ unsigned long rsvd_21_29:9;
+ unsigned long mmr_write:1; /* WP */
+ unsigned long mmr_read:1; /* WP */
+ unsigned long rsvd_32_47:16;
+ unsigned long mmr_inj_con:1; /* RW */
+ unsigned long rsvd_49_51:3;
+ unsigned long mmr_inj_tlbram:1; /* RW */
+ unsigned long rsvd_53:1;
+ unsigned long mmr_inj_tlbpgsize:1; /* RW */
+ unsigned long rsvd_55:1;
+ unsigned long mmr_inj_tlbrreg:1; /* RW */
+ unsigned long rsvd_57_59:3;
+ unsigned long mmr_inj_tlblruv:1; /* RW */
+ unsigned long rsvd_61_63:3;
+ } s1;
+ struct uv2h_gr1_tlb_mmr_control_s {
+ unsigned long index:12; /* RW */
+ unsigned long mem_sel:2; /* RW */
+ unsigned long rsvd_14_15:2;
+ unsigned long auto_valid_en:1; /* RW */
+ unsigned long rsvd_17_19:3;
+ unsigned long mmr_hash_index_en:1; /* RW */
+ unsigned long rsvd_21_29:9;
+ unsigned long mmr_write:1; /* WP */
+ unsigned long mmr_read:1; /* WP */
+ unsigned long mmr_op_done:1; /* RW */
+ unsigned long rsvd_33_47:15;
+ unsigned long mmr_inj_con:1; /* RW */
+ unsigned long rsvd_49_51:3;
+ unsigned long mmr_inj_tlbram:1; /* RW */
+ unsigned long rsvd_53_63:11;
+ } s2;
+};
+
+/* ========================================================================= */
+/* UVH_GR1_TLB_MMR_READ_DATA_HI */
+/* ========================================================================= */
+#define UV1H_GR1_TLB_MMR_READ_DATA_HI 0x8010a0UL
+#define UV2H_GR1_TLB_MMR_READ_DATA_HI 0x10010a0UL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI (is_uv1_hub() ? \
+ UV1H_GR1_TLB_MMR_READ_DATA_HI : \
+ UV2H_GR1_TLB_MMR_READ_DATA_HI)
+
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_PFN_SHFT 0
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_GAA_SHFT 41
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_SHFT 43
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_LARGER_SHFT 44
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_PFN_MASK 0x000001ffffffffffUL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_GAA_MASK 0x0000060000000000UL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_MASK 0x0000080000000000UL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_LARGER_MASK 0x0000100000000000UL
+
+union uvh_gr1_tlb_mmr_read_data_hi_u {
+ unsigned long v;
+ struct uvh_gr1_tlb_mmr_read_data_hi_s {
+ unsigned long pfn:41; /* RO */
+ unsigned long gaa:2; /* RO */
+ unsigned long dirty:1; /* RO */
+ unsigned long larger:1; /* RO */
+ unsigned long rsvd_45_63:19;
+ } s;
+};
+
+/* ========================================================================= */
+/* UVH_GR1_TLB_MMR_READ_DATA_LO */
+/* ========================================================================= */
+#define UV1H_GR1_TLB_MMR_READ_DATA_LO 0x8010a8UL
+#define UV2H_GR1_TLB_MMR_READ_DATA_LO 0x10010a8UL
+#define UVH_GR1_TLB_MMR_READ_DATA_LO (is_uv1_hub() ? \
+ UV1H_GR1_TLB_MMR_READ_DATA_LO : \
+ UV2H_GR1_TLB_MMR_READ_DATA_LO)
+
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VPN_SHFT 0
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_ASID_SHFT 39
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VALID_SHFT 63
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VPN_MASK 0x0000007fffffffffUL
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_ASID_MASK 0x7fffff8000000000UL
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VALID_MASK 0x8000000000000000UL
+
+union uvh_gr1_tlb_mmr_read_data_lo_u {
+ unsigned long v;
+ struct uvh_gr1_tlb_mmr_read_data_lo_s {
+ unsigned long vpn:39; /* RO */
+ unsigned long asid:24; /* RO */
+ unsigned long valid:1; /* RO */
+ } s;
};
/* ========================================================================= */
/* UVH_INT_CMPB */
/* ========================================================================= */
-#define UVH_INT_CMPB 0x22080UL
+#define UVH_INT_CMPB 0x22080UL
-#define UVH_INT_CMPB_REAL_TIME_CMPB_SHFT 0
-#define UVH_INT_CMPB_REAL_TIME_CMPB_MASK 0x00ffffffffffffffUL
+#define UVH_INT_CMPB_REAL_TIME_CMPB_SHFT 0
+#define UVH_INT_CMPB_REAL_TIME_CMPB_MASK 0x00ffffffffffffffUL
union uvh_int_cmpb_u {
- unsigned long v;
- struct uvh_int_cmpb_s {
- unsigned long real_time_cmpb : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
+ unsigned long v;
+ struct uvh_int_cmpb_s {
+ unsigned long real_time_cmpb:56; /* RW */
+ unsigned long rsvd_56_63:8;
+ } s;
};
/* ========================================================================= */
/* UVH_INT_CMPC */
/* ========================================================================= */
-#define UVH_INT_CMPC 0x22100UL
+#define UVH_INT_CMPC 0x22100UL
-#define UV1H_INT_CMPC_REAL_TIME_CMPC_SHFT 0
-#define UV2H_INT_CMPC_REAL_TIME_CMPC_SHFT 0
-#define UVH_INT_CMPC_REAL_TIME_CMPC_SHFT (is_uv1_hub() ? \
- UV1H_INT_CMPC_REAL_TIME_CMPC_SHFT : \
- UV2H_INT_CMPC_REAL_TIME_CMPC_SHFT)
-#define UV1H_INT_CMPC_REAL_TIME_CMPC_MASK 0xffffffffffffffUL
-#define UV2H_INT_CMPC_REAL_TIME_CMPC_MASK 0xffffffffffffffUL
-#define UVH_INT_CMPC_REAL_TIME_CMPC_MASK (is_uv1_hub() ? \
- UV1H_INT_CMPC_REAL_TIME_CMPC_MASK : \
- UV2H_INT_CMPC_REAL_TIME_CMPC_MASK)
+#define UVH_INT_CMPC_REAL_TIME_CMPC_SHFT 0
+#define UVH_INT_CMPC_REAL_TIME_CMPC_MASK 0xffffffffffffffUL
union uvh_int_cmpc_u {
- unsigned long v;
- struct uvh_int_cmpc_s {
- unsigned long real_time_cmpc : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
+ unsigned long v;
+ struct uvh_int_cmpc_s {
+ unsigned long real_time_cmpc:56; /* RW */
+ unsigned long rsvd_56_63:8;
+ } s;
};
/* ========================================================================= */
/* UVH_INT_CMPD */
/* ========================================================================= */
-#define UVH_INT_CMPD 0x22180UL
+#define UVH_INT_CMPD 0x22180UL
-#define UV1H_INT_CMPD_REAL_TIME_CMPD_SHFT 0
-#define UV2H_INT_CMPD_REAL_TIME_CMPD_SHFT 0
-#define UVH_INT_CMPD_REAL_TIME_CMPD_SHFT (is_uv1_hub() ? \
- UV1H_INT_CMPD_REAL_TIME_CMPD_SHFT : \
- UV2H_INT_CMPD_REAL_TIME_CMPD_SHFT)
-#define UV1H_INT_CMPD_REAL_TIME_CMPD_MASK 0xffffffffffffffUL
-#define UV2H_INT_CMPD_REAL_TIME_CMPD_MASK 0xffffffffffffffUL
-#define UVH_INT_CMPD_REAL_TIME_CMPD_MASK (is_uv1_hub() ? \
- UV1H_INT_CMPD_REAL_TIME_CMPD_MASK : \
- UV2H_INT_CMPD_REAL_TIME_CMPD_MASK)
+#define UVH_INT_CMPD_REAL_TIME_CMPD_SHFT 0
+#define UVH_INT_CMPD_REAL_TIME_CMPD_MASK 0xffffffffffffffUL
union uvh_int_cmpd_u {
- unsigned long v;
- struct uvh_int_cmpd_s {
- unsigned long real_time_cmpd : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
+ unsigned long v;
+ struct uvh_int_cmpd_s {
+ unsigned long real_time_cmpd:56; /* RW */
+ unsigned long rsvd_56_63:8;
+ } s;
};
/* ========================================================================= */
/* UVH_IPI_INT */
/* ========================================================================= */
-#define UVH_IPI_INT 0x60500UL
-#define UVH_IPI_INT_32 0x348
+#define UVH_IPI_INT 0x60500UL
+#define UVH_IPI_INT_32 0x348
-#define UVH_IPI_INT_VECTOR_SHFT 0
-#define UVH_IPI_INT_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_IPI_INT_DELIVERY_MODE_SHFT 8
-#define UVH_IPI_INT_DELIVERY_MODE_MASK 0x0000000000000700UL
-#define UVH_IPI_INT_DESTMODE_SHFT 11
-#define UVH_IPI_INT_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_IPI_INT_APIC_ID_SHFT 16
-#define UVH_IPI_INT_APIC_ID_MASK 0x0000ffffffff0000UL
-#define UVH_IPI_INT_SEND_SHFT 63
-#define UVH_IPI_INT_SEND_MASK 0x8000000000000000UL
+#define UVH_IPI_INT_VECTOR_SHFT 0
+#define UVH_IPI_INT_DELIVERY_MODE_SHFT 8
+#define UVH_IPI_INT_DESTMODE_SHFT 11
+#define UVH_IPI_INT_APIC_ID_SHFT 16
+#define UVH_IPI_INT_SEND_SHFT 63
+#define UVH_IPI_INT_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_IPI_INT_DELIVERY_MODE_MASK 0x0000000000000700UL
+#define UVH_IPI_INT_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_IPI_INT_APIC_ID_MASK 0x0000ffffffff0000UL
+#define UVH_IPI_INT_SEND_MASK 0x8000000000000000UL
union uvh_ipi_int_u {
- unsigned long v;
- struct uvh_ipi_int_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long delivery_mode : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long rsvd_12_15 : 4; /* */
- unsigned long apic_id : 32; /* RW */
- unsigned long rsvd_48_62 : 15; /* */
- unsigned long send : 1; /* WP */
- } s;
+ unsigned long v;
+ struct uvh_ipi_int_s {
+ unsigned long vector_:8; /* RW */
+ unsigned long delivery_mode:3; /* RW */
+ unsigned long destmode:1; /* RW */
+ unsigned long rsvd_12_15:4;
+ unsigned long apic_id:32; /* RW */
+ unsigned long rsvd_48_62:15;
+ unsigned long send:1; /* WP */
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST */
/* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_32 0x9c0
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_32 0x9c0
#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
union uvh_lb_bau_intd_payload_queue_first_u {
- unsigned long v;
- struct uvh_lb_bau_intd_payload_queue_first_s {
- unsigned long rsvd_0_3: 4; /* */
- unsigned long address : 39; /* RW */
- unsigned long rsvd_43_48: 6; /* */
- unsigned long node_id : 14; /* RW */
- unsigned long rsvd_63 : 1; /* */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_intd_payload_queue_first_s {
+ unsigned long rsvd_0_3:4;
+ unsigned long address:39; /* RW */
+ unsigned long rsvd_43_48:6;
+ unsigned long node_id:14; /* RW */
+ unsigned long rsvd_63:1;
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST */
/* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_32 0x9c8
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_32 0x9c8
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
union uvh_lb_bau_intd_payload_queue_last_u {
- unsigned long v;
- struct uvh_lb_bau_intd_payload_queue_last_s {
- unsigned long rsvd_0_3: 4; /* */
- unsigned long address : 39; /* RW */
- unsigned long rsvd_43_63: 21; /* */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_intd_payload_queue_last_s {
+ unsigned long rsvd_0_3:4;
+ unsigned long address:39; /* RW */
+ unsigned long rsvd_43_63:21;
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL */
/* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_32 0x9d0
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_32 0x9d0
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
union uvh_lb_bau_intd_payload_queue_tail_u {
- unsigned long v;
- struct uvh_lb_bau_intd_payload_queue_tail_s {
- unsigned long rsvd_0_3: 4; /* */
- unsigned long address : 39; /* RW */
- unsigned long rsvd_43_63: 21; /* */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_intd_payload_queue_tail_s {
+ unsigned long rsvd_0_3:4;
+ unsigned long address:39; /* RW */
+ unsigned long rsvd_43_63:21;
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE */
/* ========================================================================= */
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_32 0xa68
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_32 0xa68
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
union uvh_lb_bau_intd_software_acknowledge_u {
- unsigned long v;
- struct uvh_lb_bau_intd_software_acknowledge_s {
- unsigned long pending_0 : 1; /* RW, W1C */
- unsigned long pending_1 : 1; /* RW, W1C */
- unsigned long pending_2 : 1; /* RW, W1C */
- unsigned long pending_3 : 1; /* RW, W1C */
- unsigned long pending_4 : 1; /* RW, W1C */
- unsigned long pending_5 : 1; /* RW, W1C */
- unsigned long pending_6 : 1; /* RW, W1C */
- unsigned long pending_7 : 1; /* RW, W1C */
- unsigned long timeout_0 : 1; /* RW, W1C */
- unsigned long timeout_1 : 1; /* RW, W1C */
- unsigned long timeout_2 : 1; /* RW, W1C */
- unsigned long timeout_3 : 1; /* RW, W1C */
- unsigned long timeout_4 : 1; /* RW, W1C */
- unsigned long timeout_5 : 1; /* RW, W1C */
- unsigned long timeout_6 : 1; /* RW, W1C */
- unsigned long timeout_7 : 1; /* RW, W1C */
- unsigned long rsvd_16_63: 48; /* */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_intd_software_acknowledge_s {
+ unsigned long pending_0:1; /* RW, W1C */
+ unsigned long pending_1:1; /* RW, W1C */
+ unsigned long pending_2:1; /* RW, W1C */
+ unsigned long pending_3:1; /* RW, W1C */
+ unsigned long pending_4:1; /* RW, W1C */
+ unsigned long pending_5:1; /* RW, W1C */
+ unsigned long pending_6:1; /* RW, W1C */
+ unsigned long pending_7:1; /* RW, W1C */
+ unsigned long timeout_0:1; /* RW, W1C */
+ unsigned long timeout_1:1; /* RW, W1C */
+ unsigned long timeout_2:1; /* RW, W1C */
+ unsigned long timeout_3:1; /* RW, W1C */
+ unsigned long timeout_4:1; /* RW, W1C */
+ unsigned long timeout_5:1; /* RW, W1C */
+ unsigned long timeout_6:1; /* RW, W1C */
+ unsigned long timeout_7:1; /* RW, W1C */
+ unsigned long rsvd_16_63:48;
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS */
/* ========================================================================= */
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x0000000000320088UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS_32 0xa70
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x0000000000320088UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS_32 0xa70
/* ========================================================================= */
/* UVH_LB_BAU_MISC_CONTROL */
/* ========================================================================= */
-#define UVH_LB_BAU_MISC_CONTROL 0x320170UL
-#define UVH_LB_BAU_MISC_CONTROL_32 0xa10
-
-#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
-#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
-#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
-#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UVH_LB_BAU_MISC_CONTROL 0x320170UL
+#define UVH_LB_BAU_MISC_CONTROL_32 0xa10
+
+#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
+#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
#define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
-#define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
-#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
-#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
-#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
-#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
-#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
-#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
-#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
#define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
+#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
+#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
+#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
#define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
-#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
-#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
-#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
-#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
+#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
#define UV1H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
-#define UV1H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
#define UV1H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UV1H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
#define UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
-#define UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
-#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
-#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
-#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
#define UV1H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
-#define UV1H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
#define UV1H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
-#define UV1H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
#define UV1H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
-#define UV1H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
+#define UV1H_LB_BAU_MISC_CONTROL_FUN_SHFT 48
+#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
+#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UV1H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UV1H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
+#define UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
+#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UV1H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UV1H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UV1H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
-#define UV1H_LB_BAU_MISC_CONTROL_FUN_SHFT 48
-#define UV1H_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL
-
-#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
-#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UV1H_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL
+
+#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
#define UV2H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
-#define UV2H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
#define UV2H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UV2H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
#define UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
-#define UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
-#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
-#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
-#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
#define UV2H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
-#define UV2H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
#define UV2H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
-#define UV2H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_SHFT 29
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_MASK 0x0000000020000000UL
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_SHFT 30
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_MASK 0x0000000040000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_SHFT 30
#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_SHFT 31
-#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_MASK 0x0000000080000000UL
#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_SHFT 32
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_MASK 0x0000000100000000UL
#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT 33
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_MASK 0x0000000200000000UL
#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_SHFT 34
-#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_MASK 0x0000000400000000UL
#define UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_SHFT 35
+#define UV2H_LB_BAU_MISC_CONTROL_FUN_SHFT 48
+#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UV2H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UV2H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
+#define UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UV2H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_MASK 0x0000000020000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_MASK 0x0000000040000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_MASK 0x0000000080000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_MASK 0x0000000100000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_MASK 0x0000000200000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_MASK 0x0000000400000000UL
#define UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_MASK 0x0000000800000000UL
-#define UV2H_LB_BAU_MISC_CONTROL_FUN_SHFT 48
-#define UV2H_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL
union uvh_lb_bau_misc_control_u {
- unsigned long v;
- struct uvh_lb_bau_misc_control_s {
- unsigned long rejection_delay : 8; /* RW */
- unsigned long apic_mode : 1; /* RW */
- unsigned long force_broadcast : 1; /* RW */
- unsigned long force_lock_nop : 1; /* RW */
- unsigned long qpi_agent_presence_vector : 3; /* RW */
- unsigned long descriptor_fetch_mode : 1; /* RW */
- unsigned long enable_intd_soft_ack_mode : 1; /* RW */
- unsigned long intd_soft_ack_timeout_period : 4; /* RW */
- unsigned long enable_dual_mapping_mode : 1; /* RW */
- unsigned long vga_io_port_decode_enable : 1; /* RW */
- unsigned long vga_io_port_16_bit_decode : 1; /* RW */
- unsigned long suppress_dest_registration : 1; /* RW */
- unsigned long programmed_initial_priority : 3; /* RW */
- unsigned long use_incoming_priority : 1; /* RW */
- unsigned long enable_programmed_initial_priority : 1; /* RW */
- unsigned long rsvd_29_63 : 35;
- } s;
- struct uv1h_lb_bau_misc_control_s {
- unsigned long rejection_delay : 8; /* RW */
- unsigned long apic_mode : 1; /* RW */
- unsigned long force_broadcast : 1; /* RW */
- unsigned long force_lock_nop : 1; /* RW */
- unsigned long qpi_agent_presence_vector : 3; /* RW */
- unsigned long descriptor_fetch_mode : 1; /* RW */
- unsigned long enable_intd_soft_ack_mode : 1; /* RW */
- unsigned long intd_soft_ack_timeout_period : 4; /* RW */
- unsigned long enable_dual_mapping_mode : 1; /* RW */
- unsigned long vga_io_port_decode_enable : 1; /* RW */
- unsigned long vga_io_port_16_bit_decode : 1; /* RW */
- unsigned long suppress_dest_registration : 1; /* RW */
- unsigned long programmed_initial_priority : 3; /* RW */
- unsigned long use_incoming_priority : 1; /* RW */
- unsigned long enable_programmed_initial_priority : 1; /* RW */
- unsigned long rsvd_29_47 : 19; /* */
- unsigned long fun : 16; /* RW */
- } s1;
- struct uv2h_lb_bau_misc_control_s {
- unsigned long rejection_delay : 8; /* RW */
- unsigned long apic_mode : 1; /* RW */
- unsigned long force_broadcast : 1; /* RW */
- unsigned long force_lock_nop : 1; /* RW */
- unsigned long qpi_agent_presence_vector : 3; /* RW */
- unsigned long descriptor_fetch_mode : 1; /* RW */
- unsigned long enable_intd_soft_ack_mode : 1; /* RW */
- unsigned long intd_soft_ack_timeout_period : 4; /* RW */
- unsigned long enable_dual_mapping_mode : 1; /* RW */
- unsigned long vga_io_port_decode_enable : 1; /* RW */
- unsigned long vga_io_port_16_bit_decode : 1; /* RW */
- unsigned long suppress_dest_registration : 1; /* RW */
- unsigned long programmed_initial_priority : 3; /* RW */
- unsigned long use_incoming_priority : 1; /* RW */
- unsigned long enable_programmed_initial_priority : 1; /* RW */
- unsigned long enable_automatic_apic_mode_selection : 1; /* RW */
- unsigned long apic_mode_status : 1; /* RO */
- unsigned long suppress_interrupts_to_self : 1; /* RW */
- unsigned long enable_lock_based_system_flush : 1; /* RW */
- unsigned long enable_extended_sb_status : 1; /* RW */
- unsigned long suppress_int_prio_udt_to_self : 1; /* RW */
- unsigned long use_legacy_descriptor_formats : 1; /* RW */
- unsigned long rsvd_36_47 : 12; /* */
- unsigned long fun : 16; /* RW */
- } s2;
+ unsigned long v;
+ struct uvh_lb_bau_misc_control_s {
+ unsigned long rejection_delay:8; /* RW */
+ unsigned long apic_mode:1; /* RW */
+ unsigned long force_broadcast:1; /* RW */
+ unsigned long force_lock_nop:1; /* RW */
+ unsigned long qpi_agent_presence_vector:3; /* RW */
+ unsigned long descriptor_fetch_mode:1; /* RW */
+ unsigned long enable_intd_soft_ack_mode:1; /* RW */
+ unsigned long intd_soft_ack_timeout_period:4; /* RW */
+ unsigned long enable_dual_mapping_mode:1; /* RW */
+ unsigned long vga_io_port_decode_enable:1; /* RW */
+ unsigned long vga_io_port_16_bit_decode:1; /* RW */
+ unsigned long suppress_dest_registration:1; /* RW */
+ unsigned long programmed_initial_priority:3; /* RW */
+ unsigned long use_incoming_priority:1; /* RW */
+ unsigned long enable_programmed_initial_priority:1;/* RW */
+ unsigned long rsvd_29_63:35;
+ } s;
+ struct uv1h_lb_bau_misc_control_s {
+ unsigned long rejection_delay:8; /* RW */
+ unsigned long apic_mode:1; /* RW */
+ unsigned long force_broadcast:1; /* RW */
+ unsigned long force_lock_nop:1; /* RW */
+ unsigned long qpi_agent_presence_vector:3; /* RW */
+ unsigned long descriptor_fetch_mode:1; /* RW */
+ unsigned long enable_intd_soft_ack_mode:1; /* RW */
+ unsigned long intd_soft_ack_timeout_period:4; /* RW */
+ unsigned long enable_dual_mapping_mode:1; /* RW */
+ unsigned long vga_io_port_decode_enable:1; /* RW */
+ unsigned long vga_io_port_16_bit_decode:1; /* RW */
+ unsigned long suppress_dest_registration:1; /* RW */
+ unsigned long programmed_initial_priority:3; /* RW */
+ unsigned long use_incoming_priority:1; /* RW */
+ unsigned long enable_programmed_initial_priority:1;/* RW */
+ unsigned long rsvd_29_47:19;
+ unsigned long fun:16; /* RW */
+ } s1;
+ struct uv2h_lb_bau_misc_control_s {
+ unsigned long rejection_delay:8; /* RW */
+ unsigned long apic_mode:1; /* RW */
+ unsigned long force_broadcast:1; /* RW */
+ unsigned long force_lock_nop:1; /* RW */
+ unsigned long qpi_agent_presence_vector:3; /* RW */
+ unsigned long descriptor_fetch_mode:1; /* RW */
+ unsigned long enable_intd_soft_ack_mode:1; /* RW */
+ unsigned long intd_soft_ack_timeout_period:4; /* RW */
+ unsigned long enable_dual_mapping_mode:1; /* RW */
+ unsigned long vga_io_port_decode_enable:1; /* RW */
+ unsigned long vga_io_port_16_bit_decode:1; /* RW */
+ unsigned long suppress_dest_registration:1; /* RW */
+ unsigned long programmed_initial_priority:3; /* RW */
+ unsigned long use_incoming_priority:1; /* RW */
+ unsigned long enable_programmed_initial_priority:1;/* RW */
+ unsigned long enable_automatic_apic_mode_selection:1;/* RW */
+ unsigned long apic_mode_status:1; /* RO */
+ unsigned long suppress_interrupts_to_self:1; /* RW */
+ unsigned long enable_lock_based_system_flush:1;/* RW */
+ unsigned long enable_extended_sb_status:1; /* RW */
+ unsigned long suppress_int_prio_udt_to_self:1;/* RW */
+ unsigned long use_legacy_descriptor_formats:1;/* RW */
+ unsigned long rsvd_36_47:12;
+ unsigned long fun:16; /* RW */
+ } s2;
};
/* ========================================================================= */
/* UVH_LB_BAU_SB_ACTIVATION_CONTROL */
/* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9a8
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9a8
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_SHFT 0
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_MASK 0x000000000000003fUL
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT 62
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_MASK 0x4000000000000000UL
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_SHFT 63
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_MASK 0x8000000000000000UL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_SHFT 0
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT 62
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_SHFT 63
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_MASK 0x000000000000003fUL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_MASK 0x4000000000000000UL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_MASK 0x8000000000000000UL
union uvh_lb_bau_sb_activation_control_u {
- unsigned long v;
- struct uvh_lb_bau_sb_activation_control_s {
- unsigned long index : 6; /* RW */
- unsigned long rsvd_6_61: 56; /* */
- unsigned long push : 1; /* WP */
- unsigned long init : 1; /* WP */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_sb_activation_control_s {
+ unsigned long index:6; /* RW */
+ unsigned long rsvd_6_61:56;
+ unsigned long push:1; /* WP */
+ unsigned long init:1; /* WP */
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_SB_ACTIVATION_STATUS_0 */
/* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9b0
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9b0
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_SHFT 0
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_MASK 0xffffffffffffffffUL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_SHFT 0
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_MASK 0xffffffffffffffffUL
union uvh_lb_bau_sb_activation_status_0_u {
- unsigned long v;
- struct uvh_lb_bau_sb_activation_status_0_s {
- unsigned long status : 64; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_sb_activation_status_0_s {
+ unsigned long status:64; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_SB_ACTIVATION_STATUS_1 */
/* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9b8
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9b8
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_SHFT 0
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_MASK 0xffffffffffffffffUL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_SHFT 0
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_MASK 0xffffffffffffffffUL
union uvh_lb_bau_sb_activation_status_1_u {
- unsigned long v;
- struct uvh_lb_bau_sb_activation_status_1_s {
- unsigned long status : 64; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_sb_activation_status_1_s {
+ unsigned long status:64; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_LB_BAU_SB_DESCRIPTOR_BASE */
/* ========================================================================= */
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9a0
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9a0
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_SHFT 12
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_SHFT 49
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_MASK 0x7ffe000000000000UL
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_SHFT 12
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_SHFT 49
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_MASK 0x7ffe000000000000UL
union uvh_lb_bau_sb_descriptor_base_u {
- unsigned long v;
- struct uvh_lb_bau_sb_descriptor_base_s {
- unsigned long rsvd_0_11 : 12; /* */
- unsigned long page_address : 31; /* RW */
- unsigned long rsvd_43_48 : 6; /* */
- unsigned long node_id : 14; /* RW */
- unsigned long rsvd_63 : 1; /* */
- } s;
+ unsigned long v;
+ struct uvh_lb_bau_sb_descriptor_base_s {
+ unsigned long rsvd_0_11:12;
+ unsigned long page_address:31; /* RW */
+ unsigned long rsvd_43_48:6;
+ unsigned long node_id:14; /* RW */
+ unsigned long rsvd_63:1;
+ } s;
};
/* ========================================================================= */
/* UVH_NODE_ID */
/* ========================================================================= */
-#define UVH_NODE_ID 0x0UL
-
-#define UVH_NODE_ID_FORCE1_SHFT 0
-#define UVH_NODE_ID_FORCE1_MASK 0x0000000000000001UL
-#define UVH_NODE_ID_MANUFACTURER_SHFT 1
-#define UVH_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
-#define UVH_NODE_ID_PART_NUMBER_SHFT 12
-#define UVH_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
-#define UVH_NODE_ID_REVISION_SHFT 28
-#define UVH_NODE_ID_REVISION_MASK 0x00000000f0000000UL
-#define UVH_NODE_ID_NODE_ID_SHFT 32
-#define UVH_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
-
-#define UV1H_NODE_ID_FORCE1_SHFT 0
-#define UV1H_NODE_ID_FORCE1_MASK 0x0000000000000001UL
-#define UV1H_NODE_ID_MANUFACTURER_SHFT 1
-#define UV1H_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
-#define UV1H_NODE_ID_PART_NUMBER_SHFT 12
-#define UV1H_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
-#define UV1H_NODE_ID_REVISION_SHFT 28
-#define UV1H_NODE_ID_REVISION_MASK 0x00000000f0000000UL
-#define UV1H_NODE_ID_NODE_ID_SHFT 32
-#define UV1H_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
-#define UV1H_NODE_ID_NODES_PER_BIT_SHFT 48
-#define UV1H_NODE_ID_NODES_PER_BIT_MASK 0x007f000000000000UL
-#define UV1H_NODE_ID_NI_PORT_SHFT 56
-#define UV1H_NODE_ID_NI_PORT_MASK 0x0f00000000000000UL
-
-#define UV2H_NODE_ID_FORCE1_SHFT 0
-#define UV2H_NODE_ID_FORCE1_MASK 0x0000000000000001UL
-#define UV2H_NODE_ID_MANUFACTURER_SHFT 1
-#define UV2H_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
-#define UV2H_NODE_ID_PART_NUMBER_SHFT 12
-#define UV2H_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
-#define UV2H_NODE_ID_REVISION_SHFT 28
-#define UV2H_NODE_ID_REVISION_MASK 0x00000000f0000000UL
-#define UV2H_NODE_ID_NODE_ID_SHFT 32
-#define UV2H_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
-#define UV2H_NODE_ID_NODES_PER_BIT_SHFT 50
-#define UV2H_NODE_ID_NODES_PER_BIT_MASK 0x01fc000000000000UL
-#define UV2H_NODE_ID_NI_PORT_SHFT 57
-#define UV2H_NODE_ID_NI_PORT_MASK 0x3e00000000000000UL
+#define UVH_NODE_ID 0x0UL
+
+#define UVH_NODE_ID_FORCE1_SHFT 0
+#define UVH_NODE_ID_MANUFACTURER_SHFT 1
+#define UVH_NODE_ID_PART_NUMBER_SHFT 12
+#define UVH_NODE_ID_REVISION_SHFT 28
+#define UVH_NODE_ID_NODE_ID_SHFT 32
+#define UVH_NODE_ID_FORCE1_MASK 0x0000000000000001UL
+#define UVH_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
+#define UVH_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
+#define UVH_NODE_ID_REVISION_MASK 0x00000000f0000000UL
+#define UVH_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
+
+#define UV1H_NODE_ID_FORCE1_SHFT 0
+#define UV1H_NODE_ID_MANUFACTURER_SHFT 1
+#define UV1H_NODE_ID_PART_NUMBER_SHFT 12
+#define UV1H_NODE_ID_REVISION_SHFT 28
+#define UV1H_NODE_ID_NODE_ID_SHFT 32
+#define UV1H_NODE_ID_NODES_PER_BIT_SHFT 48
+#define UV1H_NODE_ID_NI_PORT_SHFT 56
+#define UV1H_NODE_ID_FORCE1_MASK 0x0000000000000001UL
+#define UV1H_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
+#define UV1H_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
+#define UV1H_NODE_ID_REVISION_MASK 0x00000000f0000000UL
+#define UV1H_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
+#define UV1H_NODE_ID_NODES_PER_BIT_MASK 0x007f000000000000UL
+#define UV1H_NODE_ID_NI_PORT_MASK 0x0f00000000000000UL
+
+#define UV2H_NODE_ID_FORCE1_SHFT 0
+#define UV2H_NODE_ID_MANUFACTURER_SHFT 1
+#define UV2H_NODE_ID_PART_NUMBER_SHFT 12
+#define UV2H_NODE_ID_REVISION_SHFT 28
+#define UV2H_NODE_ID_NODE_ID_SHFT 32
+#define UV2H_NODE_ID_NODES_PER_BIT_SHFT 50
+#define UV2H_NODE_ID_NI_PORT_SHFT 57
+#define UV2H_NODE_ID_FORCE1_MASK 0x0000000000000001UL
+#define UV2H_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
+#define UV2H_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
+#define UV2H_NODE_ID_REVISION_MASK 0x00000000f0000000UL
+#define UV2H_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
+#define UV2H_NODE_ID_NODES_PER_BIT_MASK 0x01fc000000000000UL
+#define UV2H_NODE_ID_NI_PORT_MASK 0x3e00000000000000UL
union uvh_node_id_u {
- unsigned long v;
- struct uvh_node_id_s {
- unsigned long force1 : 1; /* RO */
- unsigned long manufacturer : 11; /* RO */
- unsigned long part_number : 16; /* RO */
- unsigned long revision : 4; /* RO */
- unsigned long node_id : 15; /* RW */
- unsigned long rsvd_47_63 : 17;
- } s;
- struct uv1h_node_id_s {
- unsigned long force1 : 1; /* RO */
- unsigned long manufacturer : 11; /* RO */
- unsigned long part_number : 16; /* RO */
- unsigned long revision : 4; /* RO */
- unsigned long node_id : 15; /* RW */
- unsigned long rsvd_47 : 1; /* */
- unsigned long nodes_per_bit : 7; /* RW */
- unsigned long rsvd_55 : 1; /* */
- unsigned long ni_port : 4; /* RO */
- unsigned long rsvd_60_63 : 4; /* */
- } s1;
- struct uv2h_node_id_s {
- unsigned long force1 : 1; /* RO */
- unsigned long manufacturer : 11; /* RO */
- unsigned long part_number : 16; /* RO */
- unsigned long revision : 4; /* RO */
- unsigned long node_id : 15; /* RW */
- unsigned long rsvd_47_49 : 3; /* */
- unsigned long nodes_per_bit : 7; /* RO */
- unsigned long ni_port : 5; /* RO */
- unsigned long rsvd_62_63 : 2; /* */
- } s2;
+ unsigned long v;
+ struct uvh_node_id_s {
+ unsigned long force1:1; /* RO */
+ unsigned long manufacturer:11; /* RO */
+ unsigned long part_number:16; /* RO */
+ unsigned long revision:4; /* RO */
+ unsigned long node_id:15; /* RW */
+ unsigned long rsvd_47_63:17;
+ } s;
+ struct uv1h_node_id_s {
+ unsigned long force1:1; /* RO */
+ unsigned long manufacturer:11; /* RO */
+ unsigned long part_number:16; /* RO */
+ unsigned long revision:4; /* RO */
+ unsigned long node_id:15; /* RW */
+ unsigned long rsvd_47:1;
+ unsigned long nodes_per_bit:7; /* RW */
+ unsigned long rsvd_55:1;
+ unsigned long ni_port:4; /* RO */
+ unsigned long rsvd_60_63:4;
+ } s1;
+ struct uv2h_node_id_s {
+ unsigned long force1:1; /* RO */
+ unsigned long manufacturer:11; /* RO */
+ unsigned long part_number:16; /* RO */
+ unsigned long revision:4; /* RO */
+ unsigned long node_id:15; /* RW */
+ unsigned long rsvd_47_49:3;
+ unsigned long nodes_per_bit:7; /* RO */
+ unsigned long ni_port:5; /* RO */
+ unsigned long rsvd_62_63:2;
+ } s2;
};
/* ========================================================================= */
/* UVH_NODE_PRESENT_TABLE */
/* ========================================================================= */
-#define UVH_NODE_PRESENT_TABLE 0x1400UL
-#define UVH_NODE_PRESENT_TABLE_DEPTH 16
+#define UVH_NODE_PRESENT_TABLE 0x1400UL
+#define UVH_NODE_PRESENT_TABLE_DEPTH 16
-#define UVH_NODE_PRESENT_TABLE_NODES_SHFT 0
-#define UVH_NODE_PRESENT_TABLE_NODES_MASK 0xffffffffffffffffUL
+#define UVH_NODE_PRESENT_TABLE_NODES_SHFT 0
+#define UVH_NODE_PRESENT_TABLE_NODES_MASK 0xffffffffffffffffUL
union uvh_node_present_table_u {
- unsigned long v;
- struct uvh_node_present_table_s {
- unsigned long nodes : 64; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_node_present_table_s {
+ unsigned long nodes:64; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x16000c8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x16000c8UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_BASE_MASK 0x00000000ff000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_SHFT 48
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_MASK 0x001f000000000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_ENABLE_SHFT 63
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_BASE_MASK 0x00000000ff000000UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_MASK 0x001f000000000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_ENABLE_MASK 0x8000000000000000UL
union uvh_rh_gam_alias210_overlay_config_0_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_overlay_config_0_mmr_s {
- unsigned long rsvd_0_23: 24; /* */
- unsigned long base : 8; /* RW */
- unsigned long rsvd_32_47: 16; /* */
- unsigned long m_alias : 5; /* RW */
- unsigned long rsvd_53_62: 10; /* */
- unsigned long enable : 1; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_rh_gam_alias210_overlay_config_0_mmr_s {
+ unsigned long rsvd_0_23:24;
+ unsigned long base:8; /* RW */
+ unsigned long rsvd_32_47:16;
+ unsigned long m_alias:5; /* RW */
+ unsigned long rsvd_53_62:10;
+ unsigned long enable:1; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x16000d8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x16000d8UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_BASE_MASK 0x00000000ff000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_SHFT 48
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_MASK 0x001f000000000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_ENABLE_SHFT 63
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_BASE_MASK 0x00000000ff000000UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_MASK 0x001f000000000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_ENABLE_MASK 0x8000000000000000UL
union uvh_rh_gam_alias210_overlay_config_1_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_overlay_config_1_mmr_s {
- unsigned long rsvd_0_23: 24; /* */
- unsigned long base : 8; /* RW */
- unsigned long rsvd_32_47: 16; /* */
- unsigned long m_alias : 5; /* RW */
- unsigned long rsvd_53_62: 10; /* */
- unsigned long enable : 1; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_rh_gam_alias210_overlay_config_1_mmr_s {
+ unsigned long rsvd_0_23:24;
+ unsigned long base:8; /* RW */
+ unsigned long rsvd_32_47:16;
+ unsigned long m_alias:5; /* RW */
+ unsigned long rsvd_53_62:10;
+ unsigned long enable:1; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x16000e8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x16000e8UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_BASE_MASK 0x00000000ff000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_SHFT 48
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_MASK 0x001f000000000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_ENABLE_SHFT 63
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_BASE_MASK 0x00000000ff000000UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_MASK 0x001f000000000000UL
#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_ENABLE_MASK 0x8000000000000000UL
union uvh_rh_gam_alias210_overlay_config_2_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_overlay_config_2_mmr_s {
- unsigned long rsvd_0_23: 24; /* */
- unsigned long base : 8; /* RW */
- unsigned long rsvd_32_47: 16; /* */
- unsigned long m_alias : 5; /* RW */
- unsigned long rsvd_53_62: 10; /* */
- unsigned long enable : 1; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_rh_gam_alias210_overlay_config_2_mmr_s {
+ unsigned long rsvd_0_23:24;
+ unsigned long base:8; /* RW */
+ unsigned long rsvd_32_47:16;
+ unsigned long m_alias:5; /* RW */
+ unsigned long rsvd_53_62:10;
+ unsigned long enable:1; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT 24
#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_MASK 0x00003fffff000000UL
union uvh_rh_gam_alias210_redirect_config_0_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_redirect_config_0_mmr_s {
- unsigned long rsvd_0_23 : 24; /* */
- unsigned long dest_base : 22; /* RW */
- unsigned long rsvd_46_63: 18; /* */
- } s;
+ unsigned long v;
+ struct uvh_rh_gam_alias210_redirect_config_0_mmr_s {
+ unsigned long rsvd_0_23:24;
+ unsigned long dest_base:22; /* RW */
+ unsigned long rsvd_46_63:18;
+ } s;
};
/* ========================================================================= */
/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_SHFT 24
#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_MASK 0x00003fffff000000UL
union uvh_rh_gam_alias210_redirect_config_1_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_redirect_config_1_mmr_s {
- unsigned long rsvd_0_23 : 24; /* */
- unsigned long dest_base : 22; /* RW */
- unsigned long rsvd_46_63: 18; /* */
- } s;
+ unsigned long v;
+ struct uvh_rh_gam_alias210_redirect_config_1_mmr_s {
+ unsigned long rsvd_0_23:24;
+ unsigned long dest_base:22; /* RW */
+ unsigned long rsvd_46_63:18;
+ } s;
};
/* ========================================================================= */
/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_SHFT 24
#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_MASK 0x00003fffff000000UL
union uvh_rh_gam_alias210_redirect_config_2_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_redirect_config_2_mmr_s {
- unsigned long rsvd_0_23 : 24; /* */
- unsigned long dest_base : 22; /* RW */
- unsigned long rsvd_46_63: 18; /* */
- } s;
+ unsigned long v;
+ struct uvh_rh_gam_alias210_redirect_config_2_mmr_s {
+ unsigned long rsvd_0_23:24;
+ unsigned long dest_base:22; /* RW */
+ unsigned long rsvd_46_63:18;
+ } s;
};
/* ========================================================================= */
/* UVH_RH_GAM_CONFIG_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_CONFIG_MMR 0x1600000UL
+#define UVH_RH_GAM_CONFIG_MMR 0x1600000UL
-#define UVH_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
-#define UVH_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
-#define UVH_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
-#define UVH_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
+#define UVH_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
+#define UVH_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
+#define UVH_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
+#define UVH_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
-#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
-#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
-#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
-#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
-#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_SHFT 12
-#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_MASK 0x0000000000001000UL
+#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
+#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
+#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_SHFT 12
+#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
+#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
+#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_MASK 0x0000000000001000UL
-#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
-#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
-#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
-#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
+#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
+#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
+#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
+#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
union uvh_rh_gam_config_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_config_mmr_s {
- unsigned long m_skt : 6; /* RW */
- unsigned long n_skt : 4; /* RW */
- unsigned long rsvd_10_63 : 54;
- } s;
- struct uv1h_rh_gam_config_mmr_s {
- unsigned long m_skt : 6; /* RW */
- unsigned long n_skt : 4; /* RW */
- unsigned long rsvd_10_11: 2; /* */
- unsigned long mmiol_cfg : 1; /* RW */
- unsigned long rsvd_13_63: 51; /* */
- } s1;
- struct uv2h_rh_gam_config_mmr_s {
- unsigned long m_skt : 6; /* RW */
- unsigned long n_skt : 4; /* RW */
- unsigned long rsvd_10_63: 54; /* */
- } s2;
+ unsigned long v;
+ struct uvh_rh_gam_config_mmr_s {
+ unsigned long m_skt:6; /* RW */
+ unsigned long n_skt:4; /* RW */
+ unsigned long rsvd_10_63:54;
+ } s;
+ struct uv1h_rh_gam_config_mmr_s {
+ unsigned long m_skt:6; /* RW */
+ unsigned long n_skt:4; /* RW */
+ unsigned long rsvd_10_11:2;
+ unsigned long mmiol_cfg:1; /* RW */
+ unsigned long rsvd_13_63:51;
+ } s1;
+ struct uv2h_rh_gam_config_mmr_s {
+ unsigned long m_skt:6; /* RW */
+ unsigned long n_skt:4; /* RW */
+ unsigned long rsvd_10_63:54;
+ } s2;
};
/* ========================================================================= */
/* UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 48
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0001000000000000UL
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 48
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0001000000000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
union uvh_rh_gam_gru_overlay_config_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_gru_overlay_config_mmr_s {
- unsigned long rsvd_0_27: 28; /* */
- unsigned long base : 18; /* RW */
- unsigned long rsvd_46_62 : 17;
- unsigned long enable : 1; /* RW */
- } s;
- struct uv1h_rh_gam_gru_overlay_config_mmr_s {
- unsigned long rsvd_0_27: 28; /* */
- unsigned long base : 18; /* RW */
- unsigned long rsvd_46_47: 2; /* */
- unsigned long gr4 : 1; /* RW */
- unsigned long rsvd_49_51: 3; /* */
- unsigned long n_gru : 4; /* RW */
- unsigned long rsvd_56_62: 7; /* */
- unsigned long enable : 1; /* RW */
- } s1;
- struct uv2h_rh_gam_gru_overlay_config_mmr_s {
- unsigned long rsvd_0_27: 28; /* */
- unsigned long base : 18; /* RW */
- unsigned long rsvd_46_51: 6; /* */
- unsigned long n_gru : 4; /* RW */
- unsigned long rsvd_56_62: 7; /* */
- unsigned long enable : 1; /* RW */
- } s2;
+ unsigned long v;
+ struct uvh_rh_gam_gru_overlay_config_mmr_s {
+ unsigned long rsvd_0_27:28;
+ unsigned long base:18; /* RW */
+ unsigned long rsvd_46_62:17;
+ unsigned long enable:1; /* RW */
+ } s;
+ struct uv1h_rh_gam_gru_overlay_config_mmr_s {
+ unsigned long rsvd_0_27:28;
+ unsigned long base:18; /* RW */
+ unsigned long rsvd_46_47:2;
+ unsigned long gr4:1; /* RW */
+ unsigned long rsvd_49_51:3;
+ unsigned long n_gru:4; /* RW */
+ unsigned long rsvd_56_62:7;
+ unsigned long enable:1; /* RW */
+ } s1;
+ struct uv2h_rh_gam_gru_overlay_config_mmr_s {
+ unsigned long rsvd_0_27:28;
+ unsigned long base:18; /* RW */
+ unsigned long rsvd_46_51:6;
+ unsigned long n_gru:4; /* RW */
+ unsigned long rsvd_56_62:7;
+ unsigned long enable:1; /* RW */
+ } s2;
};
/* ========================================================================= */
/* UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR 0x1600030UL
+#define UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR 0x1600030UL
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT 30
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003fffc0000000UL
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT 46
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK 0x000fc00000000000UL
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT 52
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK 0x00f0000000000000UL
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT 30
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT 46
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT 52
#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003fffc0000000UL
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK 0x000fc00000000000UL
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK 0x00f0000000000000UL
#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT 27
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff8000000UL
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT 46
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK 0x000fc00000000000UL
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT 52
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK 0x00f0000000000000UL
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT 27
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT 46
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT 52
#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff8000000UL
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK 0x000fc00000000000UL
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK 0x00f0000000000000UL
#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
union uvh_rh_gam_mmioh_overlay_config_mmr_u {
- unsigned long v;
- struct uv1h_rh_gam_mmioh_overlay_config_mmr_s {
- unsigned long rsvd_0_29: 30; /* */
- unsigned long base : 16; /* RW */
- unsigned long m_io : 6; /* RW */
- unsigned long n_io : 4; /* RW */
- unsigned long rsvd_56_62: 7; /* */
- unsigned long enable : 1; /* RW */
- } s1;
- struct uv2h_rh_gam_mmioh_overlay_config_mmr_s {
- unsigned long rsvd_0_26: 27; /* */
- unsigned long base : 19; /* RW */
- unsigned long m_io : 6; /* RW */
- unsigned long n_io : 4; /* RW */
- unsigned long rsvd_56_62: 7; /* */
- unsigned long enable : 1; /* RW */
- } s2;
+ unsigned long v;
+ struct uv1h_rh_gam_mmioh_overlay_config_mmr_s {
+ unsigned long rsvd_0_29:30;
+ unsigned long base:16; /* RW */
+ unsigned long m_io:6; /* RW */
+ unsigned long n_io:4; /* RW */
+ unsigned long rsvd_56_62:7;
+ unsigned long enable:1; /* RW */
+ } s1;
+ struct uv2h_rh_gam_mmioh_overlay_config_mmr_s {
+ unsigned long rsvd_0_26:27;
+ unsigned long base:19; /* RW */
+ unsigned long m_io:6; /* RW */
+ unsigned long n_io:4; /* RW */
+ unsigned long rsvd_56_62:7;
+ unsigned long enable:1; /* RW */
+ } s2;
};
/* ========================================================================= */
/* UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR */
/* ========================================================================= */
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
+#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
+#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
+#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_SHFT 46
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_MASK 0x0000400000000000UL
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
union uvh_rh_gam_mmr_overlay_config_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_mmr_overlay_config_mmr_s {
- unsigned long rsvd_0_25: 26; /* */
- unsigned long base : 20; /* RW */
- unsigned long rsvd_46_62 : 17;
- unsigned long enable : 1; /* RW */
- } s;
- struct uv1h_rh_gam_mmr_overlay_config_mmr_s {
- unsigned long rsvd_0_25: 26; /* */
- unsigned long base : 20; /* RW */
- unsigned long dual_hub : 1; /* RW */
- unsigned long rsvd_47_62: 16; /* */
- unsigned long enable : 1; /* RW */
- } s1;
- struct uv2h_rh_gam_mmr_overlay_config_mmr_s {
- unsigned long rsvd_0_25: 26; /* */
- unsigned long base : 20; /* RW */
- unsigned long rsvd_46_62: 17; /* */
- unsigned long enable : 1; /* RW */
- } s2;
+ unsigned long v;
+ struct uvh_rh_gam_mmr_overlay_config_mmr_s {
+ unsigned long rsvd_0_25:26;
+ unsigned long base:20; /* RW */
+ unsigned long rsvd_46_62:17;
+ unsigned long enable:1; /* RW */
+ } s;
+ struct uv1h_rh_gam_mmr_overlay_config_mmr_s {
+ unsigned long rsvd_0_25:26;
+ unsigned long base:20; /* RW */
+ unsigned long dual_hub:1; /* RW */
+ unsigned long rsvd_47_62:16;
+ unsigned long enable:1; /* RW */
+ } s1;
+ struct uv2h_rh_gam_mmr_overlay_config_mmr_s {
+ unsigned long rsvd_0_25:26;
+ unsigned long base:20; /* RW */
+ unsigned long rsvd_46_62:17;
+ unsigned long enable:1; /* RW */
+ } s2;
};
/* ========================================================================= */
/* UVH_RTC */
/* ========================================================================= */
-#define UVH_RTC 0x340000UL
+#define UVH_RTC 0x340000UL
-#define UVH_RTC_REAL_TIME_CLOCK_SHFT 0
-#define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL
+#define UVH_RTC_REAL_TIME_CLOCK_SHFT 0
+#define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL
union uvh_rtc_u {
- unsigned long v;
- struct uvh_rtc_s {
- unsigned long real_time_clock : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
+ unsigned long v;
+ struct uvh_rtc_s {
+ unsigned long real_time_clock:56; /* RW */
+ unsigned long rsvd_56_63:8;
+ } s;
};
/* ========================================================================= */
/* UVH_RTC1_INT_CONFIG */
/* ========================================================================= */
-#define UVH_RTC1_INT_CONFIG 0x615c0UL
-
-#define UVH_RTC1_INT_CONFIG_VECTOR_SHFT 0
-#define UVH_RTC1_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_RTC1_INT_CONFIG_DM_SHFT 8
-#define UVH_RTC1_INT_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_RTC1_INT_CONFIG_DESTMODE_SHFT 11
-#define UVH_RTC1_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_RTC1_INT_CONFIG_STATUS_SHFT 12
-#define UVH_RTC1_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_RTC1_INT_CONFIG_P_SHFT 13
-#define UVH_RTC1_INT_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_RTC1_INT_CONFIG_T_SHFT 15
-#define UVH_RTC1_INT_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_RTC1_INT_CONFIG_M_SHFT 16
-#define UVH_RTC1_INT_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_RTC1_INT_CONFIG_APIC_ID_SHFT 32
-#define UVH_RTC1_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_RTC1_INT_CONFIG 0x615c0UL
+
+#define UVH_RTC1_INT_CONFIG_VECTOR_SHFT 0
+#define UVH_RTC1_INT_CONFIG_DM_SHFT 8
+#define UVH_RTC1_INT_CONFIG_DESTMODE_SHFT 11
+#define UVH_RTC1_INT_CONFIG_STATUS_SHFT 12
+#define UVH_RTC1_INT_CONFIG_P_SHFT 13
+#define UVH_RTC1_INT_CONFIG_T_SHFT 15
+#define UVH_RTC1_INT_CONFIG_M_SHFT 16
+#define UVH_RTC1_INT_CONFIG_APIC_ID_SHFT 32
+#define UVH_RTC1_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_RTC1_INT_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_RTC1_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_RTC1_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_RTC1_INT_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_RTC1_INT_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_RTC1_INT_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_RTC1_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
union uvh_rtc1_int_config_u {
- unsigned long v;
- struct uvh_rtc1_int_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
+ unsigned long v;
+ struct uvh_rtc1_int_config_s {
+ unsigned long vector_:8; /* RW */
+ unsigned long dm:3; /* RW */
+ unsigned long destmode:1; /* RW */
+ unsigned long status:1; /* RO */
+ unsigned long p:1; /* RO */
+ unsigned long rsvd_14:1;
+ unsigned long t:1; /* RO */
+ unsigned long m:1; /* RW */
+ unsigned long rsvd_17_31:15;
+ unsigned long apic_id:32; /* RW */
+ } s;
};
/* ========================================================================= */
/* UVH_SCRATCH5 */
/* ========================================================================= */
-#define UVH_SCRATCH5 0x2d0200UL
-#define UVH_SCRATCH5_32 0x778
+#define UVH_SCRATCH5 0x2d0200UL
+#define UVH_SCRATCH5_32 0x778
-#define UVH_SCRATCH5_SCRATCH5_SHFT 0
-#define UVH_SCRATCH5_SCRATCH5_MASK 0xffffffffffffffffUL
+#define UVH_SCRATCH5_SCRATCH5_SHFT 0
+#define UVH_SCRATCH5_SCRATCH5_MASK 0xffffffffffffffffUL
union uvh_scratch5_u {
- unsigned long v;
- struct uvh_scratch5_s {
- unsigned long scratch5 : 64; /* RW, W1CS */
- } s;
+ unsigned long v;
+ struct uvh_scratch5_s {
+ unsigned long scratch5:64; /* RW, W1CS */
+ } s;
};
/* ========================================================================= */
/* UV2H_EVENT_OCCURRED2 */
/* ========================================================================= */
-#define UV2H_EVENT_OCCURRED2 0x70100UL
-#define UV2H_EVENT_OCCURRED2_32 0xb68
-
-#define UV2H_EVENT_OCCURRED2_RTC_0_SHFT 0
-#define UV2H_EVENT_OCCURRED2_RTC_0_MASK 0x0000000000000001UL
-#define UV2H_EVENT_OCCURRED2_RTC_1_SHFT 1
-#define UV2H_EVENT_OCCURRED2_RTC_1_MASK 0x0000000000000002UL
-#define UV2H_EVENT_OCCURRED2_RTC_2_SHFT 2
-#define UV2H_EVENT_OCCURRED2_RTC_2_MASK 0x0000000000000004UL
-#define UV2H_EVENT_OCCURRED2_RTC_3_SHFT 3
-#define UV2H_EVENT_OCCURRED2_RTC_3_MASK 0x0000000000000008UL
-#define UV2H_EVENT_OCCURRED2_RTC_4_SHFT 4
-#define UV2H_EVENT_OCCURRED2_RTC_4_MASK 0x0000000000000010UL
-#define UV2H_EVENT_OCCURRED2_RTC_5_SHFT 5
-#define UV2H_EVENT_OCCURRED2_RTC_5_MASK 0x0000000000000020UL
-#define UV2H_EVENT_OCCURRED2_RTC_6_SHFT 6
-#define UV2H_EVENT_OCCURRED2_RTC_6_MASK 0x0000000000000040UL
-#define UV2H_EVENT_OCCURRED2_RTC_7_SHFT 7
-#define UV2H_EVENT_OCCURRED2_RTC_7_MASK 0x0000000000000080UL
-#define UV2H_EVENT_OCCURRED2_RTC_8_SHFT 8
-#define UV2H_EVENT_OCCURRED2_RTC_8_MASK 0x0000000000000100UL
-#define UV2H_EVENT_OCCURRED2_RTC_9_SHFT 9
-#define UV2H_EVENT_OCCURRED2_RTC_9_MASK 0x0000000000000200UL
-#define UV2H_EVENT_OCCURRED2_RTC_10_SHFT 10
-#define UV2H_EVENT_OCCURRED2_RTC_10_MASK 0x0000000000000400UL
-#define UV2H_EVENT_OCCURRED2_RTC_11_SHFT 11
-#define UV2H_EVENT_OCCURRED2_RTC_11_MASK 0x0000000000000800UL
-#define UV2H_EVENT_OCCURRED2_RTC_12_SHFT 12
-#define UV2H_EVENT_OCCURRED2_RTC_12_MASK 0x0000000000001000UL
-#define UV2H_EVENT_OCCURRED2_RTC_13_SHFT 13
-#define UV2H_EVENT_OCCURRED2_RTC_13_MASK 0x0000000000002000UL
-#define UV2H_EVENT_OCCURRED2_RTC_14_SHFT 14
-#define UV2H_EVENT_OCCURRED2_RTC_14_MASK 0x0000000000004000UL
-#define UV2H_EVENT_OCCURRED2_RTC_15_SHFT 15
-#define UV2H_EVENT_OCCURRED2_RTC_15_MASK 0x0000000000008000UL
-#define UV2H_EVENT_OCCURRED2_RTC_16_SHFT 16
-#define UV2H_EVENT_OCCURRED2_RTC_16_MASK 0x0000000000010000UL
-#define UV2H_EVENT_OCCURRED2_RTC_17_SHFT 17
-#define UV2H_EVENT_OCCURRED2_RTC_17_MASK 0x0000000000020000UL
-#define UV2H_EVENT_OCCURRED2_RTC_18_SHFT 18
-#define UV2H_EVENT_OCCURRED2_RTC_18_MASK 0x0000000000040000UL
-#define UV2H_EVENT_OCCURRED2_RTC_19_SHFT 19
-#define UV2H_EVENT_OCCURRED2_RTC_19_MASK 0x0000000000080000UL
-#define UV2H_EVENT_OCCURRED2_RTC_20_SHFT 20
-#define UV2H_EVENT_OCCURRED2_RTC_20_MASK 0x0000000000100000UL
-#define UV2H_EVENT_OCCURRED2_RTC_21_SHFT 21
-#define UV2H_EVENT_OCCURRED2_RTC_21_MASK 0x0000000000200000UL
-#define UV2H_EVENT_OCCURRED2_RTC_22_SHFT 22
-#define UV2H_EVENT_OCCURRED2_RTC_22_MASK 0x0000000000400000UL
-#define UV2H_EVENT_OCCURRED2_RTC_23_SHFT 23
-#define UV2H_EVENT_OCCURRED2_RTC_23_MASK 0x0000000000800000UL
-#define UV2H_EVENT_OCCURRED2_RTC_24_SHFT 24
-#define UV2H_EVENT_OCCURRED2_RTC_24_MASK 0x0000000001000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_25_SHFT 25
-#define UV2H_EVENT_OCCURRED2_RTC_25_MASK 0x0000000002000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_26_SHFT 26
-#define UV2H_EVENT_OCCURRED2_RTC_26_MASK 0x0000000004000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_27_SHFT 27
-#define UV2H_EVENT_OCCURRED2_RTC_27_MASK 0x0000000008000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_28_SHFT 28
-#define UV2H_EVENT_OCCURRED2_RTC_28_MASK 0x0000000010000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_29_SHFT 29
-#define UV2H_EVENT_OCCURRED2_RTC_29_MASK 0x0000000020000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_30_SHFT 30
-#define UV2H_EVENT_OCCURRED2_RTC_30_MASK 0x0000000040000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_31_SHFT 31
-#define UV2H_EVENT_OCCURRED2_RTC_31_MASK 0x0000000080000000UL
+#define UV2H_EVENT_OCCURRED2 0x70100UL
+#define UV2H_EVENT_OCCURRED2_32 0xb68
+
+#define UV2H_EVENT_OCCURRED2_RTC_0_SHFT 0
+#define UV2H_EVENT_OCCURRED2_RTC_1_SHFT 1
+#define UV2H_EVENT_OCCURRED2_RTC_2_SHFT 2
+#define UV2H_EVENT_OCCURRED2_RTC_3_SHFT 3
+#define UV2H_EVENT_OCCURRED2_RTC_4_SHFT 4
+#define UV2H_EVENT_OCCURRED2_RTC_5_SHFT 5
+#define UV2H_EVENT_OCCURRED2_RTC_6_SHFT 6
+#define UV2H_EVENT_OCCURRED2_RTC_7_SHFT 7
+#define UV2H_EVENT_OCCURRED2_RTC_8_SHFT 8
+#define UV2H_EVENT_OCCURRED2_RTC_9_SHFT 9
+#define UV2H_EVENT_OCCURRED2_RTC_10_SHFT 10
+#define UV2H_EVENT_OCCURRED2_RTC_11_SHFT 11
+#define UV2H_EVENT_OCCURRED2_RTC_12_SHFT 12
+#define UV2H_EVENT_OCCURRED2_RTC_13_SHFT 13
+#define UV2H_EVENT_OCCURRED2_RTC_14_SHFT 14
+#define UV2H_EVENT_OCCURRED2_RTC_15_SHFT 15
+#define UV2H_EVENT_OCCURRED2_RTC_16_SHFT 16
+#define UV2H_EVENT_OCCURRED2_RTC_17_SHFT 17
+#define UV2H_EVENT_OCCURRED2_RTC_18_SHFT 18
+#define UV2H_EVENT_OCCURRED2_RTC_19_SHFT 19
+#define UV2H_EVENT_OCCURRED2_RTC_20_SHFT 20
+#define UV2H_EVENT_OCCURRED2_RTC_21_SHFT 21
+#define UV2H_EVENT_OCCURRED2_RTC_22_SHFT 22
+#define UV2H_EVENT_OCCURRED2_RTC_23_SHFT 23
+#define UV2H_EVENT_OCCURRED2_RTC_24_SHFT 24
+#define UV2H_EVENT_OCCURRED2_RTC_25_SHFT 25
+#define UV2H_EVENT_OCCURRED2_RTC_26_SHFT 26
+#define UV2H_EVENT_OCCURRED2_RTC_27_SHFT 27
+#define UV2H_EVENT_OCCURRED2_RTC_28_SHFT 28
+#define UV2H_EVENT_OCCURRED2_RTC_29_SHFT 29
+#define UV2H_EVENT_OCCURRED2_RTC_30_SHFT 30
+#define UV2H_EVENT_OCCURRED2_RTC_31_SHFT 31
+#define UV2H_EVENT_OCCURRED2_RTC_0_MASK 0x0000000000000001UL
+#define UV2H_EVENT_OCCURRED2_RTC_1_MASK 0x0000000000000002UL
+#define UV2H_EVENT_OCCURRED2_RTC_2_MASK 0x0000000000000004UL
+#define UV2H_EVENT_OCCURRED2_RTC_3_MASK 0x0000000000000008UL
+#define UV2H_EVENT_OCCURRED2_RTC_4_MASK 0x0000000000000010UL
+#define UV2H_EVENT_OCCURRED2_RTC_5_MASK 0x0000000000000020UL
+#define UV2H_EVENT_OCCURRED2_RTC_6_MASK 0x0000000000000040UL
+#define UV2H_EVENT_OCCURRED2_RTC_7_MASK 0x0000000000000080UL
+#define UV2H_EVENT_OCCURRED2_RTC_8_MASK 0x0000000000000100UL
+#define UV2H_EVENT_OCCURRED2_RTC_9_MASK 0x0000000000000200UL
+#define UV2H_EVENT_OCCURRED2_RTC_10_MASK 0x0000000000000400UL
+#define UV2H_EVENT_OCCURRED2_RTC_11_MASK 0x0000000000000800UL
+#define UV2H_EVENT_OCCURRED2_RTC_12_MASK 0x0000000000001000UL
+#define UV2H_EVENT_OCCURRED2_RTC_13_MASK 0x0000000000002000UL
+#define UV2H_EVENT_OCCURRED2_RTC_14_MASK 0x0000000000004000UL
+#define UV2H_EVENT_OCCURRED2_RTC_15_MASK 0x0000000000008000UL
+#define UV2H_EVENT_OCCURRED2_RTC_16_MASK 0x0000000000010000UL
+#define UV2H_EVENT_OCCURRED2_RTC_17_MASK 0x0000000000020000UL
+#define UV2H_EVENT_OCCURRED2_RTC_18_MASK 0x0000000000040000UL
+#define UV2H_EVENT_OCCURRED2_RTC_19_MASK 0x0000000000080000UL
+#define UV2H_EVENT_OCCURRED2_RTC_20_MASK 0x0000000000100000UL
+#define UV2H_EVENT_OCCURRED2_RTC_21_MASK 0x0000000000200000UL
+#define UV2H_EVENT_OCCURRED2_RTC_22_MASK 0x0000000000400000UL
+#define UV2H_EVENT_OCCURRED2_RTC_23_MASK 0x0000000000800000UL
+#define UV2H_EVENT_OCCURRED2_RTC_24_MASK 0x0000000001000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_25_MASK 0x0000000002000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_26_MASK 0x0000000004000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_27_MASK 0x0000000008000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_28_MASK 0x0000000010000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_29_MASK 0x0000000020000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_30_MASK 0x0000000040000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_31_MASK 0x0000000080000000UL
union uv2h_event_occurred2_u {
- unsigned long v;
- struct uv2h_event_occurred2_s {
- unsigned long rtc_0 : 1; /* RW */
- unsigned long rtc_1 : 1; /* RW */
- unsigned long rtc_2 : 1; /* RW */
- unsigned long rtc_3 : 1; /* RW */
- unsigned long rtc_4 : 1; /* RW */
- unsigned long rtc_5 : 1; /* RW */
- unsigned long rtc_6 : 1; /* RW */
- unsigned long rtc_7 : 1; /* RW */
- unsigned long rtc_8 : 1; /* RW */
- unsigned long rtc_9 : 1; /* RW */
- unsigned long rtc_10 : 1; /* RW */
- unsigned long rtc_11 : 1; /* RW */
- unsigned long rtc_12 : 1; /* RW */
- unsigned long rtc_13 : 1; /* RW */
- unsigned long rtc_14 : 1; /* RW */
- unsigned long rtc_15 : 1; /* RW */
- unsigned long rtc_16 : 1; /* RW */
- unsigned long rtc_17 : 1; /* RW */
- unsigned long rtc_18 : 1; /* RW */
- unsigned long rtc_19 : 1; /* RW */
- unsigned long rtc_20 : 1; /* RW */
- unsigned long rtc_21 : 1; /* RW */
- unsigned long rtc_22 : 1; /* RW */
- unsigned long rtc_23 : 1; /* RW */
- unsigned long rtc_24 : 1; /* RW */
- unsigned long rtc_25 : 1; /* RW */
- unsigned long rtc_26 : 1; /* RW */
- unsigned long rtc_27 : 1; /* RW */
- unsigned long rtc_28 : 1; /* RW */
- unsigned long rtc_29 : 1; /* RW */
- unsigned long rtc_30 : 1; /* RW */
- unsigned long rtc_31 : 1; /* RW */
- unsigned long rsvd_32_63: 32; /* */
- } s1;
+ unsigned long v;
+ struct uv2h_event_occurred2_s {
+ unsigned long rtc_0:1; /* RW */
+ unsigned long rtc_1:1; /* RW */
+ unsigned long rtc_2:1; /* RW */
+ unsigned long rtc_3:1; /* RW */
+ unsigned long rtc_4:1; /* RW */
+ unsigned long rtc_5:1; /* RW */
+ unsigned long rtc_6:1; /* RW */
+ unsigned long rtc_7:1; /* RW */
+ unsigned long rtc_8:1; /* RW */
+ unsigned long rtc_9:1; /* RW */
+ unsigned long rtc_10:1; /* RW */
+ unsigned long rtc_11:1; /* RW */
+ unsigned long rtc_12:1; /* RW */
+ unsigned long rtc_13:1; /* RW */
+ unsigned long rtc_14:1; /* RW */
+ unsigned long rtc_15:1; /* RW */
+ unsigned long rtc_16:1; /* RW */
+ unsigned long rtc_17:1; /* RW */
+ unsigned long rtc_18:1; /* RW */
+ unsigned long rtc_19:1; /* RW */
+ unsigned long rtc_20:1; /* RW */
+ unsigned long rtc_21:1; /* RW */
+ unsigned long rtc_22:1; /* RW */
+ unsigned long rtc_23:1; /* RW */
+ unsigned long rtc_24:1; /* RW */
+ unsigned long rtc_25:1; /* RW */
+ unsigned long rtc_26:1; /* RW */
+ unsigned long rtc_27:1; /* RW */
+ unsigned long rtc_28:1; /* RW */
+ unsigned long rtc_29:1; /* RW */
+ unsigned long rtc_30:1; /* RW */
+ unsigned long rtc_31:1; /* RW */
+ unsigned long rsvd_32_63:32;
+ } s1;
};
/* ========================================================================= */
/* UV2H_EVENT_OCCURRED2_ALIAS */
/* ========================================================================= */
-#define UV2H_EVENT_OCCURRED2_ALIAS 0x70108UL
-#define UV2H_EVENT_OCCURRED2_ALIAS_32 0xb70
+#define UV2H_EVENT_OCCURRED2_ALIAS 0x70108UL
+#define UV2H_EVENT_OCCURRED2_ALIAS_32 0xb70
/* ========================================================================= */
/* UV2H_LB_BAU_SB_ACTIVATION_STATUS_2 */
/* ========================================================================= */
-#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2 0x320130UL
-#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x9f0
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2 0x320130UL
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x9f0
#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_SHFT 0
#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_MASK 0xffffffffffffffffUL
union uv2h_lb_bau_sb_activation_status_2_u {
- unsigned long v;
- struct uv2h_lb_bau_sb_activation_status_2_s {
- unsigned long aux_error : 64; /* RW */
- } s1;
+ unsigned long v;
+ struct uv2h_lb_bau_sb_activation_status_2_s {
+ unsigned long aux_error:64; /* RW */
+ } s1;
};
/* ========================================================================= */
/* UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK */
/* ========================================================================= */
-#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK 0x320130UL
-#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_32 0x9f0
+#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK 0x320130UL
+#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_32 0x9f0
#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_SHFT 0
#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_MASK 0x00000000ffffffffUL
union uv1h_lb_target_physical_apic_id_mask_u {
- unsigned long v;
- struct uv1h_lb_target_physical_apic_id_mask_s {
- unsigned long bit_enables : 32; /* RW */
- unsigned long rsvd_32_63 : 32; /* */
- } s1;
+ unsigned long v;
+ struct uv1h_lb_target_physical_apic_id_mask_s {
+ unsigned long bit_enables:32; /* RW */
+ unsigned long rsvd_32_63:32;
+ } s1;
};
-#endif /* __ASM_UV_MMRS_X86_H__ */
+#endif /* _ASM_X86_UV_UV_MMRS_H */
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
index 646b4c1ca695..815285bcaceb 100644
--- a/arch/x86/include/asm/vgtod.h
+++ b/arch/x86/include/asm/vgtod.h
@@ -11,10 +11,9 @@ struct vsyscall_gtod_data {
time_t wall_time_sec;
u32 wall_time_nsec;
- int sysctl_enabled;
struct timezone sys_tz;
struct { /* extract of a clocksource struct */
- cycle_t (*vread)(void);
+ int vclock_mode;
cycle_t cycle_last;
cycle_t mask;
u32 mult;
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 84471b810460..2caf290e9895 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -132,6 +132,8 @@ enum vmcs_field {
GUEST_IA32_PAT_HIGH = 0x00002805,
GUEST_IA32_EFER = 0x00002806,
GUEST_IA32_EFER_HIGH = 0x00002807,
+ GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808,
+ GUEST_IA32_PERF_GLOBAL_CTRL_HIGH= 0x00002809,
GUEST_PDPTR0 = 0x0000280a,
GUEST_PDPTR0_HIGH = 0x0000280b,
GUEST_PDPTR1 = 0x0000280c,
@@ -144,6 +146,8 @@ enum vmcs_field {
HOST_IA32_PAT_HIGH = 0x00002c01,
HOST_IA32_EFER = 0x00002c02,
HOST_IA32_EFER_HIGH = 0x00002c03,
+ HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04,
+ HOST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002c05,
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
EXCEPTION_BITMAP = 0x00004004,
@@ -426,4 +430,43 @@ struct vmx_msr_entry {
u64 value;
} __aligned(16);
+/*
+ * Exit Qualifications for entry failure during or after loading guest state
+ */
+#define ENTRY_FAIL_DEFAULT 0
+#define ENTRY_FAIL_PDPTE 2
+#define ENTRY_FAIL_NMI 3
+#define ENTRY_FAIL_VMCS_LINK_PTR 4
+
+/*
+ * VM-instruction error numbers
+ */
+enum vm_instruction_error_number {
+ VMXERR_VMCALL_IN_VMX_ROOT_OPERATION = 1,
+ VMXERR_VMCLEAR_INVALID_ADDRESS = 2,
+ VMXERR_VMCLEAR_VMXON_POINTER = 3,
+ VMXERR_VMLAUNCH_NONCLEAR_VMCS = 4,
+ VMXERR_VMRESUME_NONLAUNCHED_VMCS = 5,
+ VMXERR_VMRESUME_AFTER_VMXOFF = 6,
+ VMXERR_ENTRY_INVALID_CONTROL_FIELD = 7,
+ VMXERR_ENTRY_INVALID_HOST_STATE_FIELD = 8,
+ VMXERR_VMPTRLD_INVALID_ADDRESS = 9,
+ VMXERR_VMPTRLD_VMXON_POINTER = 10,
+ VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID = 11,
+ VMXERR_UNSUPPORTED_VMCS_COMPONENT = 12,
+ VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT = 13,
+ VMXERR_VMXON_IN_VMX_ROOT_OPERATION = 15,
+ VMXERR_ENTRY_INVALID_EXECUTIVE_VMCS_POINTER = 16,
+ VMXERR_ENTRY_NONLAUNCHED_EXECUTIVE_VMCS = 17,
+ VMXERR_ENTRY_EXECUTIVE_VMCS_POINTER_NOT_VMXON_POINTER = 18,
+ VMXERR_VMCALL_NONCLEAR_VMCS = 19,
+ VMXERR_VMCALL_INVALID_VM_EXIT_CONTROL_FIELDS = 20,
+ VMXERR_VMCALL_INCORRECT_MSEG_REVISION_ID = 22,
+ VMXERR_VMXOFF_UNDER_DUAL_MONITOR_TREATMENT_OF_SMIS_AND_SMM = 23,
+ VMXERR_VMCALL_INVALID_SMM_MONITOR_FEATURES = 24,
+ VMXERR_ENTRY_INVALID_VM_EXECUTION_CONTROL_FIELDS_IN_EXECUTIVE_VMCS = 25,
+ VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS = 26,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID = 28,
+};
+
#endif
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index d55597351f6a..60107072c28b 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -16,10 +16,6 @@ enum vsyscall_num {
#ifdef __KERNEL__
#include <linux/seqlock.h>
-/* Definitions for CONFIG_GENERIC_TIME definitions */
-#define __vsyscall_fn \
- __attribute__ ((unused, __section__(".vsyscall_fn"))) notrace
-
#define VGETCPU_RDTSCP 1
#define VGETCPU_LSL 2
diff --git a/arch/x86/include/asm/vvar.h b/arch/x86/include/asm/vvar.h
index 341b3559452b..de656ac2af41 100644
--- a/arch/x86/include/asm/vvar.h
+++ b/arch/x86/include/asm/vvar.h
@@ -10,15 +10,14 @@
* In normal kernel code, they are used like any other variable.
* In user code, they are accessed through the VVAR macro.
*
- * Each of these variables lives in the vsyscall page, and each
- * one needs a unique offset within the little piece of the page
- * reserved for vvars. Specify that offset in DECLARE_VVAR.
- * (There are 896 bytes available. If you mess up, the linker will
- * catch it.)
+ * These variables live in a page of kernel data that has an extra RO
+ * mapping for userspace. Each variable needs a unique offset within
+ * that page; specify that offset with the DECLARE_VVAR macro. (If
+ * you mess up, the linker will catch it.)
*/
-/* Offset of vars within vsyscall page */
-#define VSYSCALL_VARS_OFFSET (3072 + 128)
+/* Base address of vvars. This is not ABI. */
+#define VVAR_ADDRESS (-10*1024*1024 - 4096)
#if defined(__VVAR_KERNEL_LDS)
@@ -26,17 +25,17 @@
* right place.
*/
#define DECLARE_VVAR(offset, type, name) \
- EMIT_VVAR(name, VSYSCALL_VARS_OFFSET + offset)
+ EMIT_VVAR(name, offset)
#else
#define DECLARE_VVAR(offset, type, name) \
static type const * const vvaraddr_ ## name = \
- (void *)(VSYSCALL_START + VSYSCALL_VARS_OFFSET + (offset));
+ (void *)(VVAR_ADDRESS + (offset));
#define DEFINE_VVAR(type, name) \
- type __vvar_ ## name \
- __attribute__((section(".vsyscall_var_" #name), aligned(16)))
+ type name \
+ __attribute__((section(".vvar_" #name), aligned(16)))
#define VVAR(name) (*vvaraddr_ ## name)
@@ -45,8 +44,7 @@
/* DECLARE_VVAR(offset, type, name) */
DECLARE_VVAR(0, volatile unsigned long, jiffies)
-DECLARE_VVAR(8, int, vgetcpu_mode)
+DECLARE_VVAR(16, int, vgetcpu_mode)
DECLARE_VVAR(128, struct vsyscall_gtod_data, vsyscall_gtod_data)
#undef DECLARE_VVAR
-#undef VSYSCALL_VARS_OFFSET
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index d240ea950519..417777de5a40 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -39,6 +39,8 @@
#include <linux/string.h>
#include <linux/types.h>
+#include <trace/events/xen.h>
+
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -459,6 +461,8 @@ MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
{
mcl->op = __HYPERVISOR_fpu_taskswitch;
mcl->args[0] = set;
+
+ trace_xen_mc_entry(mcl, 1);
}
static inline void
@@ -475,6 +479,8 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
mcl->args[2] = new_val.pte >> 32;
mcl->args[3] = flags;
}
+
+ trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 3 : 4);
}
static inline void
@@ -485,6 +491,8 @@ MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
mcl->args[0] = cmd;
mcl->args[1] = (unsigned long)uop;
mcl->args[2] = count;
+
+ trace_xen_mc_entry(mcl, 3);
}
static inline void
@@ -504,6 +512,8 @@ MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long v
mcl->args[3] = flags;
mcl->args[4] = domid;
}
+
+ trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 4 : 5);
}
static inline void
@@ -520,6 +530,8 @@ MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
mcl->args[2] = desc.a;
mcl->args[3] = desc.b;
}
+
+ trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4);
}
static inline void
@@ -528,6 +540,8 @@ MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
mcl->op = __HYPERVISOR_memory_op;
mcl->args[0] = cmd;
mcl->args[1] = (unsigned long)arg;
+
+ trace_xen_mc_entry(mcl, 2);
}
static inline void
@@ -539,6 +553,8 @@ MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
mcl->args[1] = count;
mcl->args[2] = (unsigned long)success_count;
mcl->args[3] = domid;
+
+ trace_xen_mc_entry(mcl, 4);
}
static inline void
@@ -550,6 +566,8 @@ MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
mcl->args[1] = count;
mcl->args[2] = (unsigned long)success_count;
mcl->args[3] = domid;
+
+ trace_xen_mc_entry(mcl, 4);
}
static inline void
@@ -558,6 +576,8 @@ MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
mcl->op = __HYPERVISOR_set_gdt;
mcl->args[0] = (unsigned long)frames;
mcl->args[1] = entries;
+
+ trace_xen_mc_entry(mcl, 2);
}
static inline void
@@ -567,6 +587,8 @@ MULTI_stack_switch(struct multicall_entry *mcl,
mcl->op = __HYPERVISOR_stack_switch;
mcl->args[0] = ss;
mcl->args[1] = esp;
+
+ trace_xen_mc_entry(mcl, 2);
}
#endif /* _ASM_X86_XEN_HYPERCALL_H */
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h
index 4fbda9a3f339..968d57dd54c9 100644
--- a/arch/x86/include/asm/xen/pci.h
+++ b/arch/x86/include/asm/xen/pci.h
@@ -14,13 +14,14 @@ static inline int pci_xen_hvm_init(void)
}
#endif
#if defined(CONFIG_XEN_DOM0)
-void __init xen_setup_pirqs(void);
+int __init pci_xen_initial_domain(void);
int xen_find_device_domain_owner(struct pci_dev *dev);
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
int xen_unregister_device_domain_owner(struct pci_dev *dev);
#else
-static inline void __init xen_setup_pirqs(void)
+static inline int __init pci_xen_initial_domain(void)
{
+ return -1;
}
static inline int xen_find_device_domain_owner(struct pci_dev *dev)
{
diff --git a/arch/x86/include/asm/xen/trace_types.h b/arch/x86/include/asm/xen/trace_types.h
new file mode 100644
index 000000000000..21e1874c0a0b
--- /dev/null
+++ b/arch/x86/include/asm/xen/trace_types.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_XEN_TRACE_TYPES_H
+#define _ASM_XEN_TRACE_TYPES_H
+
+enum xen_mc_flush_reason {
+ XEN_MC_FL_NONE, /* explicit flush */
+ XEN_MC_FL_BATCH, /* out of hypercall space */
+ XEN_MC_FL_ARGS, /* out of argument space */
+ XEN_MC_FL_CALLBACK, /* out of callback space */
+};
+
+enum xen_mc_extend_args {
+ XEN_MC_XE_OK,
+ XEN_MC_XE_BAD_OP,
+ XEN_MC_XE_NO_SPACE
+};
+typedef void (*xen_mc_callback_fn_t)(void *);
+
+#endif /* _ASM_XEN_TRACE_TYPES_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 90b06d4daee2..04105574c8e9 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -24,17 +24,12 @@ endif
nostackp := $(call cc-option, -fno-stack-protector)
CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp)
CFLAGS_hpet.o := $(nostackp)
-CFLAGS_vread_tsc_64.o := $(nostackp)
CFLAGS_paravirt.o := $(nostackp)
GCOV_PROFILE_vsyscall_64.o := n
GCOV_PROFILE_hpet.o := n
GCOV_PROFILE_tsc.o := n
-GCOV_PROFILE_vread_tsc_64.o := n
GCOV_PROFILE_paravirt.o := n
-# vread_tsc_64 is hot and should be fully optimized:
-CFLAGS_REMOVE_vread_tsc_64.o = -pg -fno-optimize-sibling-calls
-
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
@@ -43,7 +38,8 @@ obj-$(CONFIG_IRQ_WORK) += irq_work.o
obj-y += probe_roms.o
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
-obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o vread_tsc_64.o
+obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o
+obj-$(CONFIG_X86_64) += vsyscall_emu_64.o
obj-y += bootflag.o e820.o
obj-y += pci-dma.o quirks.o topology.o kdebugfs.o
obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
@@ -123,7 +119,6 @@ ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_GART_IOMMU) += amd_gart_64.o aperture_64.o
obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o
- obj-$(CONFIG_AMD_IOMMU) += amd_iommu_init.o amd_iommu.o
obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
obj-y += vsmp_64.o
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index a81f2d52f869..c63822816249 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -14,7 +14,6 @@
#include <asm/pgtable.h>
#include <asm/mce.h>
#include <asm/nmi.h>
-#include <asm/vsyscall.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/io.h>
@@ -250,7 +249,6 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
extern s32 __smp_locks[], __smp_locks_end[];
-extern char __vsyscall_0;
void *text_poke_early(void *addr, const void *opcode, size_t len);
/* Replace instructions with better alternatives for this CPU type.
@@ -263,6 +261,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
struct alt_instr *end)
{
struct alt_instr *a;
+ u8 *instr, *replacement;
u8 insnbuf[MAX_PATCH_LEN];
DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
@@ -276,25 +275,23 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
* order.
*/
for (a = start; a < end; a++) {
- u8 *instr = a->instr;
+ instr = (u8 *)&a->instr_offset + a->instr_offset;
+ replacement = (u8 *)&a->repl_offset + a->repl_offset;
BUG_ON(a->replacementlen > a->instrlen);
BUG_ON(a->instrlen > sizeof(insnbuf));
BUG_ON(a->cpuid >= NCAPINTS*32);
if (!boot_cpu_has(a->cpuid))
continue;
-#ifdef CONFIG_X86_64
- /* vsyscall code is not mapped yet. resolve it manually. */
- if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
- instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
- DPRINTK("%s: vsyscall fixup: %p => %p\n",
- __func__, a->instr, instr);
- }
-#endif
- memcpy(insnbuf, a->replacement, a->replacementlen);
+
+ memcpy(insnbuf, replacement, a->replacementlen);
+
+ /* 0xe8 is a relative jump; fix the offset. */
if (*insnbuf == 0xe8 && a->replacementlen == 5)
- *(s32 *)(insnbuf + 1) += a->replacement - a->instr;
+ *(s32 *)(insnbuf + 1) += replacement - instr;
+
add_nops(insnbuf + a->replacementlen,
a->instrlen - a->replacementlen);
+
text_poke_early(instr, insnbuf, a->instrlen);
}
}
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index b117efd24f71..8a439d364b94 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -30,7 +30,7 @@
#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <linux/gfp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/mtrr.h>
#include <asm/pgtable.h>
#include <asm/proto.h>
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 289e92862fd9..afdc3f756dea 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -27,15 +27,12 @@
* timer, but by default APB timer has higher rating than local APIC timers.
*/
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
#include <linux/delay.h>
+#include <linux/dw_apb_timer.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/sysdev.h>
#include <linux/slab.h>
#include <linux/pm.h>
-#include <linux/pci.h>
#include <linux/sfi.h>
#include <linux/interrupt.h>
#include <linux/cpu.h>
@@ -44,76 +41,48 @@
#include <asm/fixmap.h>
#include <asm/apb_timer.h>
#include <asm/mrst.h>
+#include <asm/time.h>
-#define APBT_MASK CLOCKSOURCE_MASK(32)
-#define APBT_SHIFT 22
#define APBT_CLOCKEVENT_RATING 110
#define APBT_CLOCKSOURCE_RATING 250
-#define APBT_MIN_DELTA_USEC 200
-#define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt)
#define APBT_CLOCKEVENT0_NUM (0)
-#define APBT_CLOCKEVENT1_NUM (1)
#define APBT_CLOCKSOURCE_NUM (2)
-static unsigned long apbt_address;
+static phys_addr_t apbt_address;
static int apb_timer_block_enabled;
static void __iomem *apbt_virt_address;
-static int phy_cs_timer_id;
/*
* Common DW APB timer info
*/
-static uint64_t apbt_freq;
-
-static void apbt_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt);
-static int apbt_next_event(unsigned long delta,
- struct clock_event_device *evt);
-static cycle_t apbt_read_clocksource(struct clocksource *cs);
-static void apbt_restart_clocksource(struct clocksource *cs);
+static unsigned long apbt_freq;
struct apbt_dev {
- struct clock_event_device evt;
- unsigned int num;
- int cpu;
- unsigned int irq;
- unsigned int tick;
- unsigned int count;
- unsigned int flags;
- char name[10];
+ struct dw_apb_clock_event_device *timer;
+ unsigned int num;
+ int cpu;
+ unsigned int irq;
+ char name[10];
};
-static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
+static struct dw_apb_clocksource *clocksource_apbt;
-#ifdef CONFIG_SMP
-static unsigned int apbt_num_timers_used;
-static struct apbt_dev *apbt_devs;
-#endif
-
-static inline unsigned long apbt_readl_reg(unsigned long a)
+static inline void __iomem *adev_virt_addr(struct apbt_dev *adev)
{
- return readl(apbt_virt_address + a);
+ return apbt_virt_address + adev->num * APBTMRS_REG_SIZE;
}
-static inline void apbt_writel_reg(unsigned long d, unsigned long a)
-{
- writel(d, apbt_virt_address + a);
-}
-
-static inline unsigned long apbt_readl(int n, unsigned long a)
-{
- return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE);
-}
+static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
-static inline void apbt_writel(int n, unsigned long d, unsigned long a)
-{
- writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE);
-}
+#ifdef CONFIG_SMP
+static unsigned int apbt_num_timers_used;
+#endif
static inline void apbt_set_mapping(void)
{
struct sfi_timer_table_entry *mtmr;
+ int phy_cs_timer_id = 0;
if (apbt_virt_address) {
pr_debug("APBT base already mapped\n");
@@ -125,21 +94,18 @@ static inline void apbt_set_mapping(void)
APBT_CLOCKEVENT0_NUM);
return;
}
- apbt_address = (unsigned long)mtmr->phys_addr;
+ apbt_address = (phys_addr_t)mtmr->phys_addr;
if (!apbt_address) {
printk(KERN_WARNING "No timer base from SFI, use default\n");
apbt_address = APBT_DEFAULT_BASE;
}
apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE);
- if (apbt_virt_address) {
- pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\
- (void *)apbt_address, (void *)apbt_virt_address);
- } else {
- pr_debug("Failed mapping APBT phy address at %p\n",\
- (void *)apbt_address);
+ if (!apbt_virt_address) {
+ pr_debug("Failed mapping APBT phy address at %lu\n",\
+ (unsigned long)apbt_address);
goto panic_noapbt;
}
- apbt_freq = mtmr->freq_hz / USEC_PER_SEC;
+ apbt_freq = mtmr->freq_hz;
sfi_free_mtmr(mtmr);
/* Now figure out the physical timer id for clocksource device */
@@ -148,9 +114,14 @@ static inline void apbt_set_mapping(void)
goto panic_noapbt;
/* Now figure out the physical timer id */
- phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff)
- / APBTMRS_REG_SIZE;
- pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id);
+ pr_debug("Use timer %d for clocksource\n",
+ (int)(mtmr->phys_addr & 0xff) / APBTMRS_REG_SIZE);
+ phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) /
+ APBTMRS_REG_SIZE;
+
+ clocksource_apbt = dw_apb_clocksource_init(APBT_CLOCKSOURCE_RATING,
+ "apbt0", apbt_virt_address + phy_cs_timer_id *
+ APBTMRS_REG_SIZE, apbt_freq);
return;
panic_noapbt:
@@ -172,82 +143,6 @@ static inline int is_apbt_capable(void)
return apbt_virt_address ? 1 : 0;
}
-static struct clocksource clocksource_apbt = {
- .name = "apbt",
- .rating = APBT_CLOCKSOURCE_RATING,
- .read = apbt_read_clocksource,
- .mask = APBT_MASK,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- .resume = apbt_restart_clocksource,
-};
-
-/* boot APB clock event device */
-static struct clock_event_device apbt_clockevent = {
- .name = "apbt0",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_mode = apbt_set_mode,
- .set_next_event = apbt_next_event,
- .shift = APBT_SHIFT,
- .irq = 0,
- .rating = APBT_CLOCKEVENT_RATING,
-};
-
-/*
- * start count down from 0xffff_ffff. this is done by toggling the enable bit
- * then load initial load count to ~0.
- */
-static void apbt_start_counter(int n)
-{
- unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
-
- ctrl &= ~APBTMR_CONTROL_ENABLE;
- apbt_writel(n, ctrl, APBTMR_N_CONTROL);
- apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT);
- /* enable, mask interrupt */
- ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
- ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
- apbt_writel(n, ctrl, APBTMR_N_CONTROL);
- /* read it once to get cached counter value initialized */
- apbt_read_clocksource(&clocksource_apbt);
-}
-
-static irqreturn_t apbt_interrupt_handler(int irq, void *data)
-{
- struct apbt_dev *dev = (struct apbt_dev *)data;
- struct clock_event_device *aevt = &dev->evt;
-
- if (!aevt->event_handler) {
- printk(KERN_INFO "Spurious APBT timer interrupt on %d\n",
- dev->num);
- return IRQ_NONE;
- }
- aevt->event_handler(aevt);
- return IRQ_HANDLED;
-}
-
-static void apbt_restart_clocksource(struct clocksource *cs)
-{
- apbt_start_counter(phy_cs_timer_id);
-}
-
-static void apbt_enable_int(int n)
-{
- unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
- /* clear pending intr */
- apbt_readl(n, APBTMR_N_EOI);
- ctrl &= ~APBTMR_CONTROL_INT;
- apbt_writel(n, ctrl, APBTMR_N_CONTROL);
-}
-
-static void apbt_disable_int(int n)
-{
- unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
-
- ctrl |= APBTMR_CONTROL_INT;
- apbt_writel(n, ctrl, APBTMR_N_CONTROL);
-}
-
-
static int __init apbt_clockevent_register(void)
{
struct sfi_timer_table_entry *mtmr;
@@ -260,45 +155,21 @@ static int __init apbt_clockevent_register(void)
return -ENODEV;
}
- /*
- * We need to calculate the scaled math multiplication factor for
- * nanosecond to apbt tick conversion.
- * mult = (nsec/cycle)*2^APBT_SHIFT
- */
- apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz
- , NSEC_PER_SEC, APBT_SHIFT);
-
- /* Calculate the min / max delta */
- apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
- &apbt_clockevent);
- apbt_clockevent.min_delta_ns = clockevent_delta2ns(
- APBT_MIN_DELTA_USEC*apbt_freq,
- &apbt_clockevent);
- /*
- * Start apbt with the boot cpu mask and make it
- * global if not used for per cpu timer.
- */
- apbt_clockevent.cpumask = cpumask_of(smp_processor_id());
adev->num = smp_processor_id();
- memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device));
+ adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0",
+ mrst_timer_options == MRST_TIMER_LAPIC_APBT ?
+ APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING,
+ adev_virt_addr(adev), 0, apbt_freq);
+ /* Firmware does EOI handling for us. */
+ adev->timer->eoi = NULL;
if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
- adev->evt.rating = APBT_CLOCKEVENT_RATING - 100;
- global_clock_event = &adev->evt;
+ global_clock_event = &adev->timer->ced;
printk(KERN_DEBUG "%s clockevent registered as global\n",
global_clock_event->name);
}
- if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler,
- IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
- apbt_clockevent.name, adev)) {
- printk(KERN_ERR "Failed request IRQ for APBT%d\n",
- apbt_clockevent.irq);
- }
-
- clockevents_register_device(&adev->evt);
- /* Start APBT 0 interrupts */
- apbt_enable_int(APBT_CLOCKEVENT0_NUM);
+ dw_apb_clockevent_register(adev->timer);
sfi_free_mtmr(mtmr);
return 0;
@@ -316,52 +187,34 @@ static void apbt_setup_irq(struct apbt_dev *adev)
irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
/* APB timer irqs are set up as mp_irqs, timer is edge type */
__irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
-
- if (system_state == SYSTEM_BOOTING) {
- if (request_irq(adev->irq, apbt_interrupt_handler,
- IRQF_TIMER | IRQF_DISABLED |
- IRQF_NOBALANCING,
- adev->name, adev)) {
- printk(KERN_ERR "Failed request IRQ for APBT%d\n",
- adev->num);
- }
- } else
- enable_irq(adev->irq);
}
/* Should be called with per cpu */
void apbt_setup_secondary_clock(void)
{
struct apbt_dev *adev;
- struct clock_event_device *aevt;
int cpu;
/* Don't register boot CPU clockevent */
cpu = smp_processor_id();
if (!cpu)
return;
- /*
- * We need to calculate the scaled math multiplication factor for
- * nanosecond to apbt tick conversion.
- * mult = (nsec/cycle)*2^APBT_SHIFT
- */
- printk(KERN_INFO "Init per CPU clockevent %d\n", cpu);
- adev = &per_cpu(cpu_apbt_dev, cpu);
- aevt = &adev->evt;
- memcpy(aevt, &apbt_clockevent, sizeof(*aevt));
- aevt->cpumask = cpumask_of(cpu);
- aevt->name = adev->name;
- aevt->mode = CLOCK_EVT_MODE_UNUSED;
+ adev = &__get_cpu_var(cpu_apbt_dev);
+ if (!adev->timer) {
+ adev->timer = dw_apb_clockevent_init(cpu, adev->name,
+ APBT_CLOCKEVENT_RATING, adev_virt_addr(adev),
+ adev->irq, apbt_freq);
+ adev->timer->eoi = NULL;
+ } else {
+ dw_apb_clockevent_resume(adev->timer);
+ }
- printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n",
- cpu, aevt->name, *(u32 *)aevt->cpumask);
+ printk(KERN_INFO "Registering CPU %d clockevent device %s, cpu %08x\n",
+ cpu, adev->name, adev->cpu);
apbt_setup_irq(adev);
-
- clockevents_register_device(aevt);
-
- apbt_enable_int(cpu);
+ dw_apb_clockevent_register(adev->timer);
return;
}
@@ -384,13 +237,12 @@ static int apbt_cpuhp_notify(struct notifier_block *n,
switch (action & 0xf) {
case CPU_DEAD:
- disable_irq(adev->irq);
- apbt_disable_int(cpu);
+ dw_apb_clockevent_pause(adev->timer);
if (system_state == SYSTEM_RUNNING) {
pr_debug("skipping APBT CPU %lu offline\n", cpu);
} else if (adev) {
pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
- free_irq(adev->irq, adev);
+ dw_apb_clockevent_stop(adev->timer);
}
break;
default:
@@ -415,116 +267,16 @@ void apbt_setup_secondary_clock(void) {}
#endif /* CONFIG_SMP */
-static void apbt_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- unsigned long ctrl;
- uint64_t delta;
- int timer_num;
- struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
-
- BUG_ON(!apbt_virt_address);
-
- timer_num = adev->num;
- pr_debug("%s CPU %d timer %d mode=%d\n",
- __func__, first_cpu(*evt->cpumask), timer_num, mode);
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult;
- delta >>= apbt_clockevent.shift;
- ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
- ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- /*
- * DW APB p. 46, have to disable timer before load counter,
- * may cause sync problem.
- */
- ctrl &= ~APBTMR_CONTROL_ENABLE;
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- udelay(1);
- pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ);
- apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
- ctrl |= APBTMR_CONTROL_ENABLE;
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- break;
- /* APB timer does not have one-shot mode, use free running mode */
- case CLOCK_EVT_MODE_ONESHOT:
- ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
- /*
- * set free running mode, this mode will let timer reload max
- * timeout which will give time (3min on 25MHz clock) to rearm
- * the next event, therefore emulate the one-shot mode.
- */
- ctrl &= ~APBTMR_CONTROL_ENABLE;
- ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
-
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- /* write again to set free running mode */
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-
- /*
- * DW APB p. 46, load counter with all 1s before starting free
- * running mode.
- */
- apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT);
- ctrl &= ~APBTMR_CONTROL_INT;
- ctrl |= APBTMR_CONTROL_ENABLE;
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- break;
-
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- apbt_disable_int(timer_num);
- ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
- ctrl &= ~APBTMR_CONTROL_ENABLE;
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- break;
-
- case CLOCK_EVT_MODE_RESUME:
- apbt_enable_int(timer_num);
- break;
- }
-}
-
-static int apbt_next_event(unsigned long delta,
- struct clock_event_device *evt)
-{
- unsigned long ctrl;
- int timer_num;
-
- struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
-
- timer_num = adev->num;
- /* Disable timer */
- ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
- ctrl &= ~APBTMR_CONTROL_ENABLE;
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- /* write new count */
- apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
- ctrl |= APBTMR_CONTROL_ENABLE;
- apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
- return 0;
-}
-
-static cycle_t apbt_read_clocksource(struct clocksource *cs)
-{
- unsigned long current_count;
-
- current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
- return (cycle_t)~current_count;
-}
-
static int apbt_clocksource_register(void)
{
u64 start, now;
cycle_t t1;
/* Start the counter, use timer 2 as source, timer 0/1 for event */
- apbt_start_counter(phy_cs_timer_id);
+ dw_apb_clocksource_start(clocksource_apbt);
/* Verify whether apbt counter works */
- t1 = apbt_read_clocksource(&clocksource_apbt);
+ t1 = dw_apb_clocksource_read(clocksource_apbt);
rdtscll(start);
/*
@@ -539,10 +291,10 @@ static int apbt_clocksource_register(void)
} while ((now - start) < 200000UL);
/* APBT is the only always on clocksource, it has to work! */
- if (t1 == apbt_read_clocksource(&clocksource_apbt))
+ if (t1 == dw_apb_clocksource_read(clocksource_apbt))
panic("APBT counter not counting. APBT disabled\n");
- clocksource_register_khz(&clocksource_apbt, (u32)apbt_freq*1000);
+ dw_apb_clocksource_register(clocksource_apbt);
return 0;
}
@@ -566,10 +318,7 @@ void __init apbt_time_init(void)
if (apb_timer_block_enabled)
return;
apbt_set_mapping();
- if (apbt_virt_address) {
- pr_debug("Found APBT version 0x%lx\n",\
- apbt_readl_reg(APBTMRS_COMP_VERSION));
- } else
+ if (!apbt_virt_address)
goto out_noapbt;
/*
* Read the frequency and check for a sane value, for ESL model
@@ -577,7 +326,7 @@ void __init apbt_time_init(void)
*/
if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) {
- pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq);
+ pr_debug("APBT has invalid freq 0x%lx\n", apbt_freq);
goto out_noapbt;
}
if (apbt_clocksource_register()) {
@@ -603,30 +352,20 @@ void __init apbt_time_init(void)
} else {
percpu_timer = 0;
apbt_num_timers_used = 1;
- adev = &per_cpu(cpu_apbt_dev, 0);
- adev->flags &= ~APBT_DEV_USED;
}
pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);
/* here we set up per CPU timer data structure */
- apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used,
- GFP_KERNEL);
- if (!apbt_devs) {
- printk(KERN_ERR "Failed to allocate APB timer devices\n");
- return;
- }
for (i = 0; i < apbt_num_timers_used; i++) {
adev = &per_cpu(cpu_apbt_dev, i);
adev->num = i;
adev->cpu = i;
p_mtmr = sfi_get_mtmr(i);
- if (p_mtmr) {
- adev->tick = p_mtmr->freq_hz;
+ if (p_mtmr)
adev->irq = p_mtmr->irq;
- } else
+ else
printk(KERN_ERR "Failed to get timer for cpu %d\n", i);
- adev->count = 0;
- sprintf(adev->name, "apbt%d", i);
+ snprintf(adev->name, sizeof(adev->name) - 1, "apbt%d", i);
}
#endif
@@ -638,17 +377,8 @@ out_noapbt:
panic("failed to enable APB timer\n");
}
-static inline void apbt_disable(int n)
-{
- if (is_apbt_capable()) {
- unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
- ctrl &= ~APBTMR_CONTROL_ENABLE;
- apbt_writel(n, ctrl, APBTMR_N_CONTROL);
- }
-}
-
/* called before apb_timer_enable, use early map */
-unsigned long apbt_quick_calibrate()
+unsigned long apbt_quick_calibrate(void)
{
int i, scale;
u64 old, new;
@@ -657,31 +387,31 @@ unsigned long apbt_quick_calibrate()
u32 loop, shift;
apbt_set_mapping();
- apbt_start_counter(phy_cs_timer_id);
+ dw_apb_clocksource_start(clocksource_apbt);
/* check if the timer can count down, otherwise return */
- old = apbt_read_clocksource(&clocksource_apbt);
+ old = dw_apb_clocksource_read(clocksource_apbt);
i = 10000;
while (--i) {
- if (old != apbt_read_clocksource(&clocksource_apbt))
+ if (old != dw_apb_clocksource_read(clocksource_apbt))
break;
}
if (!i)
goto failed;
/* count 16 ms */
- loop = (apbt_freq * 1000) << 4;
+ loop = (apbt_freq / 1000) << 4;
/* restart the timer to ensure it won't get to 0 in the calibration */
- apbt_start_counter(phy_cs_timer_id);
+ dw_apb_clocksource_start(clocksource_apbt);
- old = apbt_read_clocksource(&clocksource_apbt);
+ old = dw_apb_clocksource_read(clocksource_apbt);
old += loop;
t1 = __native_read_tsc();
do {
- new = apbt_read_clocksource(&clocksource_apbt);
+ new = dw_apb_clocksource_read(clocksource_apbt);
} while (new < old);
t2 = __native_read_tsc();
@@ -693,7 +423,7 @@ unsigned long apbt_quick_calibrate()
return 0;
}
scale = (int)div_u64((t2 - t1), loop >> shift);
- khz = (scale * apbt_freq * 1000) >> shift;
+ khz = (scale * (apbt_freq / 1000)) >> shift;
printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz);
return khz;
failed:
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b9338b8cf420..52fa56399a50 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -27,6 +27,7 @@
#include <linux/syscore_ops.h>
#include <linux/delay.h>
#include <linux/timex.h>
+#include <linux/i8253.h>
#include <linux/dmar.h>
#include <linux/init.h>
#include <linux/cpu.h>
@@ -37,9 +38,8 @@
#include <asm/perf_event.h>
#include <asm/x86_init.h>
#include <asm/pgalloc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/mpspec.h>
-#include <asm/i8253.h>
#include <asm/i8259.h>
#include <asm/proto.h>
#include <asm/apic.h>
@@ -48,6 +48,7 @@
#include <asm/hpet.h>
#include <asm/idle.h>
#include <asm/mtrr.h>
+#include <asm/time.h>
#include <asm/smp.h>
#include <asm/mce.h>
#include <asm/tsc.h>
@@ -1429,7 +1430,7 @@ void enable_x2apic(void)
rdmsr(MSR_IA32_APICBASE, msr, msr2);
if (!(msr & X2APIC_ENABLE)) {
printk_once(KERN_INFO "Enabling x2apic\n");
- wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
+ wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, msr2);
}
}
#endif /* CONFIG_X86_X2APIC */
@@ -1943,10 +1944,28 @@ void disconnect_bsp_APIC(int virt_wire_setup)
void __cpuinit generic_processor_info(int apicid, int version)
{
- int cpu;
+ int cpu, max = nr_cpu_ids;
+ bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
+ phys_cpu_present_map);
+
+ /*
+ * If boot cpu has not been detected yet, then only allow upto
+ * nr_cpu_ids - 1 processors and keep one slot free for boot cpu
+ */
+ if (!boot_cpu_detected && num_processors >= nr_cpu_ids - 1 &&
+ apicid != boot_cpu_physical_apicid) {
+ int thiscpu = max + disabled_cpus - 1;
+
+ pr_warning(
+ "ACPI: NR_CPUS/possible_cpus limit of %i almost"
+ " reached. Keeping one slot for boot cpu."
+ " Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
+
+ disabled_cpus++;
+ return;
+ }
if (num_processors >= nr_cpu_ids) {
- int max = nr_cpu_ids;
int thiscpu = max + disabled_cpus;
pr_warning(
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index 9536b3fe43f8..5d513bc47b6b 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -48,7 +48,7 @@
#include <linux/io.h>
#include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/fixmap.h>
#include <asm/mpspec.h>
#include <asm/setup.h>
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e5293394b548..8eb863e27ea6 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1295,6 +1295,16 @@ static int setup_ioapic_entry(int apic_id, int irq,
* 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;
@@ -1337,9 +1347,9 @@ 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)\n",
+ "IRQ %d Mode:%i Active:%i Dest:%d)\n",
apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector,
- irq, trigger, polarity);
+ irq, trigger, polarity, dest);
if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry,
@@ -1522,10 +1532,12 @@ __apicdebuginit(void) print_IO_APIC(void)
printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS);
printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
- printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries);
+ printk(KERN_DEBUG "....... : max redirection entries: %02X\n",
+ reg_01.bits.entries);
printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ);
- printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version);
+ printk(KERN_DEBUG "....... : IO APIC version: %02X\n",
+ reg_01.bits.version);
/*
* Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
@@ -1550,31 +1562,60 @@ __apicdebuginit(void) print_IO_APIC(void)
printk(KERN_DEBUG ".... IRQ redirection table:\n");
- printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
- " Stat Dmod Deli Vect:\n");
+ if (intr_remapping_enabled) {
+ printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR"
+ " Pol Stat Indx2 Zero Vect:\n");
+ } else {
+ printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+ " Stat Dmod Deli Vect:\n");
+ }
for (i = 0; i <= reg_01.bits.entries; i++) {
- struct IO_APIC_route_entry entry;
-
- entry = ioapic_read_entry(apic, i);
-
- printk(KERN_DEBUG " %02x %03X ",
- i,
- entry.dest
- );
+ if (intr_remapping_enabled) {
+ struct IO_APIC_route_entry entry;
+ struct IR_IO_APIC_route_entry *ir_entry;
+
+ entry = ioapic_read_entry(apic, i);
+ ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
+ printk(KERN_DEBUG " %02x %04X ",
+ i,
+ ir_entry->index
+ );
+ printk("%1d %1d %1d %1d %1d "
+ "%1d %1d %X %02X\n",
+ ir_entry->format,
+ ir_entry->mask,
+ ir_entry->trigger,
+ ir_entry->irr,
+ ir_entry->polarity,
+ ir_entry->delivery_status,
+ ir_entry->index2,
+ ir_entry->zero,
+ ir_entry->vector
+ );
+ } else {
+ struct IO_APIC_route_entry entry;
- printk("%1d %1d %1d %1d %1d %1d %1d %02X\n",
- entry.mask,
- entry.trigger,
- entry.irr,
- entry.polarity,
- entry.delivery_status,
- entry.dest_mode,
- entry.delivery_mode,
- entry.vector
- );
+ entry = ioapic_read_entry(apic, i);
+ printk(KERN_DEBUG " %02x %02X ",
+ i,
+ entry.dest
+ );
+ printk("%1d %1d %1d %1d %1d "
+ "%1d %1d %02X\n",
+ entry.mask,
+ entry.trigger,
+ entry.irr,
+ entry.polarity,
+ entry.delivery_status,
+ entry.dest_mode,
+ entry.delivery_mode,
+ entry.vector
+ );
+ }
}
}
+
printk(KERN_DEBUG "IRQ to pin mappings:\n");
for_each_active_irq(irq) {
struct irq_pin_list *entry;
@@ -1792,7 +1833,7 @@ __apicdebuginit(int) print_ICs(void)
return 0;
}
-fs_initcall(print_ICs);
+late_initcall(print_ICs);
/* Where if anywhere is the i8259 connect in external int mode */
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 965a7666c283..0371c484bb8a 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -229,11 +229,11 @@
#include <linux/jiffies.h>
#include <linux/acpi.h>
#include <linux/syscore_ops.h>
+#include <linux/i8253.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/desc.h>
-#include <asm/i8253.h>
#include <asm/olpc.h>
#include <asm/paravirt.h>
#include <asm/reboot.h>
@@ -1220,11 +1220,11 @@ static void reinit_timer(void)
raw_spin_lock_irqsave(&i8253_lock, flags);
/* set the clock to HZ */
- outb_pit(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb_p(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
udelay(10);
- outb_pit(LATCH & 0xff, PIT_CH0); /* LSB */
+ outb_p(LATCH & 0xff, PIT_CH0); /* LSB */
udelay(10);
- outb_pit(LATCH >> 8, PIT_CH0); /* MSB */
+ outb_p(LATCH >> 8, PIT_CH0); /* MSB */
udelay(10);
raw_spin_unlock_irqrestore(&i8253_lock, flags);
#endif
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index c29d631af6fc..395a10e68067 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -63,7 +63,6 @@ void foo(void)
BLANK();
OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
OFFSET(LGUEST_DATA_irq_pending, lguest_data, irq_pending);
- OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir);
BLANK();
OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 525514cf33c3..46674fbb62ba 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -62,6 +62,8 @@ static void __init check_fpu(void)
return;
}
+ kernel_fpu_begin();
+
/*
* trap_init() enabled FXSR and company _before_ testing for FP
* problems here.
@@ -80,6 +82,8 @@ static void __init check_fpu(void)
: "=m" (*&fdiv_bug)
: "m" (*&x), "m" (*&y));
+ kernel_fpu_end();
+
boot_cpu_data.fdiv_bug = fdiv_bug;
if (boot_cpu_data.fdiv_bug)
printk(KERN_WARNING "Hmm, FPU with FDIV bug.\n");
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 22a073d7fbff..62184390a601 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -21,7 +21,7 @@
#include <linux/topology.h>
#include <linux/cpumask.h>
#include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/proto.h>
#include <asm/setup.h>
#include <asm/apic.h>
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 8095f8611f8a..755f64fb0743 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -32,11 +32,11 @@
*/
static const __initconst struct hypervisor_x86 * const hypervisors[] =
{
- &x86_hyper_vmware,
- &x86_hyper_ms_hyperv,
#ifdef CONFIG_XEN_PVHVM
&x86_hyper_xen_hvm,
#endif
+ &x86_hyper_vmware,
+ &x86_hyper_ms_hyperv,
};
const struct hypervisor_x86 *x86_hyper;
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 1edf5ba4fb2b..ed6086eedf1d 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -456,6 +456,24 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
if (cpu_has(c, X86_FEATURE_VMX))
detect_vmx_virtcap(c);
+
+ /*
+ * Initialize MSR_IA32_ENERGY_PERF_BIAS if BIOS did not.
+ * x86_energy_perf_policy(8) is available to change it at run-time
+ */
+ if (cpu_has(c, X86_FEATURE_EPB)) {
+ u64 epb;
+
+ rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
+ if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) {
+ printk_once(KERN_WARNING "ENERGY_PERF_BIAS:"
+ " Set to 'normal', was 'performance'\n"
+ "ENERGY_PERF_BIAS: View and update with"
+ " x86_energy_perf_policy(8)\n");
+ epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL;
+ wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
+ }
+ }
}
#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 1e8d66c1336a..7395d5f4272d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -43,61 +43,105 @@ static struct severity {
unsigned char covered;
char *msg;
} severities[] = {
-#define KERNEL .context = IN_KERNEL
-#define USER .context = IN_USER
-#define SER .ser = SER_REQUIRED
-#define NOSER .ser = NO_SER
-#define SEV(s) .sev = MCE_ ## s ## _SEVERITY
-#define BITCLR(x, s, m, r...) { .mask = x, .result = 0, SEV(s), .msg = m, ## r }
-#define BITSET(x, s, m, r...) { .mask = x, .result = x, SEV(s), .msg = m, ## r }
-#define MCGMASK(x, res, s, m, r...) \
- { .mcgmask = x, .mcgres = res, SEV(s), .msg = m, ## r }
-#define MASK(x, y, s, m, r...) \
- { .mask = x, .result = y, SEV(s), .msg = m, ## r }
+#define MCESEV(s, m, c...) { .sev = MCE_ ## s ## _SEVERITY, .msg = m, ## c }
+#define KERNEL .context = IN_KERNEL
+#define USER .context = IN_USER
+#define SER .ser = SER_REQUIRED
+#define NOSER .ser = NO_SER
+#define BITCLR(x) .mask = x, .result = 0
+#define BITSET(x) .mask = x, .result = x
+#define MCGMASK(x, y) .mcgmask = x, .mcgres = y
+#define MASK(x, y) .mask = x, .result = y
#define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S)
#define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR)
#define MCACOD 0xffff
- BITCLR(MCI_STATUS_VAL, NO, "Invalid"),
- BITCLR(MCI_STATUS_EN, NO, "Not enabled"),
- BITSET(MCI_STATUS_PCC, PANIC, "Processor context corrupt"),
+ MCESEV(
+ NO, "Invalid",
+ BITCLR(MCI_STATUS_VAL)
+ ),
+ MCESEV(
+ NO, "Not enabled",
+ BITCLR(MCI_STATUS_EN)
+ ),
+ MCESEV(
+ PANIC, "Processor context corrupt",
+ BITSET(MCI_STATUS_PCC)
+ ),
/* When MCIP is not set something is very confused */
- MCGMASK(MCG_STATUS_MCIP, 0, PANIC, "MCIP not set in MCA handler"),
+ MCESEV(
+ PANIC, "MCIP not set in MCA handler",
+ MCGMASK(MCG_STATUS_MCIP, 0)
+ ),
/* Neither return not error IP -- no chance to recover -> PANIC */
- MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, 0, PANIC,
- "Neither restart nor error IP"),
- MCGMASK(MCG_STATUS_RIPV, 0, PANIC, "In kernel and no restart IP",
- KERNEL),
- BITCLR(MCI_STATUS_UC, KEEP, "Corrected error", NOSER),
- MASK(MCI_STATUS_OVER|MCI_STATUS_UC|MCI_STATUS_EN, MCI_STATUS_UC, SOME,
- "Spurious not enabled", SER),
+ MCESEV(
+ PANIC, "Neither restart nor error IP",
+ MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, 0)
+ ),
+ MCESEV(
+ PANIC, "In kernel and no restart IP",
+ KERNEL, MCGMASK(MCG_STATUS_RIPV, 0)
+ ),
+ MCESEV(
+ KEEP, "Corrected error",
+ NOSER, BITCLR(MCI_STATUS_UC)
+ ),
/* ignore OVER for UCNA */
- MASK(MCI_UC_SAR, MCI_STATUS_UC, KEEP,
- "Uncorrected no action required", SER),
- MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_UC|MCI_STATUS_AR, PANIC,
- "Illegal combination (UCNA with AR=1)", SER),
- MASK(MCI_STATUS_S, 0, KEEP, "Non signalled machine check", SER),
+ MCESEV(
+ KEEP, "Uncorrected no action required",
+ SER, MASK(MCI_UC_SAR, MCI_STATUS_UC)
+ ),
+ MCESEV(
+ PANIC, "Illegal combination (UCNA with AR=1)",
+ SER,
+ MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_UC|MCI_STATUS_AR)
+ ),
+ MCESEV(
+ KEEP, "Non signalled machine check",
+ SER, BITCLR(MCI_STATUS_S)
+ ),
/* AR add known MCACODs here */
- MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_OVER|MCI_UC_SAR, PANIC,
- "Action required with lost events", SER),
- MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCACOD, MCI_UC_SAR, PANIC,
- "Action required; unknown MCACOD", SER),
+ MCESEV(
+ PANIC, "Action required with lost events",
+ SER, BITSET(MCI_STATUS_OVER|MCI_UC_SAR)
+ ),
+ MCESEV(
+ PANIC, "Action required: unknown MCACOD",
+ SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_SAR)
+ ),
/* known AO MCACODs: */
- MASK(MCI_UC_SAR|MCI_STATUS_OVER|0xfff0, MCI_UC_S|0xc0, AO,
- "Action optional: memory scrubbing error", SER),
- MASK(MCI_UC_SAR|MCI_STATUS_OVER|MCACOD, MCI_UC_S|0x17a, AO,
- "Action optional: last level cache writeback error", SER),
-
- MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S, SOME,
- "Action optional unknown MCACOD", SER),
- MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S|MCI_STATUS_OVER, SOME,
- "Action optional with lost events", SER),
- BITSET(MCI_STATUS_UC|MCI_STATUS_OVER, PANIC, "Overflowed uncorrected"),
- BITSET(MCI_STATUS_UC, UC, "Uncorrected"),
- BITSET(0, SOME, "No match") /* always matches. keep at end */
+ MCESEV(
+ AO, "Action optional: memory scrubbing error",
+ SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|0xfff0, MCI_UC_S|0x00c0)
+ ),
+ MCESEV(
+ AO, "Action optional: last level cache writeback error",
+ SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCACOD, MCI_UC_S|0x017a)
+ ),
+ MCESEV(
+ SOME, "Action optional: unknown MCACOD",
+ SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S)
+ ),
+ MCESEV(
+ SOME, "Action optional with lost events",
+ SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_OVER|MCI_UC_S)
+ ),
+
+ MCESEV(
+ PANIC, "Overflowed uncorrected",
+ BITSET(MCI_STATUS_OVER|MCI_STATUS_UC)
+ ),
+ MCESEV(
+ UC, "Uncorrected",
+ BITSET(MCI_STATUS_UC)
+ ),
+ MCESEV(
+ SOME, "No match",
+ BITSET(0)
+ ) /* always matches. keep at end */
};
/*
@@ -112,15 +156,15 @@ static int error_context(struct mce *m)
return IN_KERNEL;
}
-int mce_severity(struct mce *a, int tolerant, char **msg)
+int mce_severity(struct mce *m, int tolerant, char **msg)
{
- enum context ctx = error_context(a);
+ enum context ctx = error_context(m);
struct severity *s;
for (s = severities;; s++) {
- if ((a->status & s->mask) != s->result)
+ if ((m->status & s->mask) != s->result)
continue;
- if ((a->mcgstatus & s->mcgmask) != s->mcgres)
+ if ((m->mcgstatus & s->mcgmask) != s->mcgres)
continue;
if (s->ser == SER_REQUIRED && !mce_ser)
continue;
@@ -197,15 +241,15 @@ static const struct file_operations severities_coverage_fops = {
static int __init severities_debugfs_init(void)
{
- struct dentry *dmce = NULL, *fseverities_coverage = NULL;
+ struct dentry *dmce, *fsev;
dmce = mce_get_debugfs_dir();
- if (dmce == NULL)
+ if (!dmce)
goto err_out;
- fseverities_coverage = debugfs_create_file("severities-coverage",
- 0444, dmce, NULL,
- &severities_coverage_fops);
- if (fseverities_coverage == NULL)
+
+ fsev = debugfs_create_file("severities-coverage", 0444, dmce, NULL,
+ &severities_coverage_fops);
+ if (!fsev)
goto err_out;
return 0;
@@ -214,4 +258,4 @@ err_out:
return -ENOMEM;
}
late_initcall(severities_debugfs_init);
-#endif
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ff1ae9b6464d..08363b042122 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -10,7 +10,6 @@
#include <linux/thread_info.h>
#include <linux/capability.h>
#include <linux/miscdevice.h>
-#include <linux/interrupt.h>
#include <linux/ratelimit.h>
#include <linux/kallsyms.h>
#include <linux/rcupdate.h>
@@ -38,23 +37,20 @@
#include <linux/mm.h>
#include <linux/debugfs.h>
#include <linux/edac_mce.h>
+#include <linux/irq_work.h>
#include <asm/processor.h>
-#include <asm/hw_irq.h>
-#include <asm/apic.h>
-#include <asm/idle.h>
-#include <asm/ipi.h>
#include <asm/mce.h>
#include <asm/msr.h>
#include "mce-internal.h"
-static DEFINE_MUTEX(mce_read_mutex);
+static DEFINE_MUTEX(mce_chrdev_read_mutex);
#define rcu_dereference_check_mce(p) \
rcu_dereference_index_check((p), \
rcu_read_lock_sched_held() || \
- lockdep_is_held(&mce_read_mutex))
+ lockdep_is_held(&mce_chrdev_read_mutex))
#define CREATE_TRACE_POINTS
#include <trace/events/mce.h>
@@ -94,7 +90,8 @@ static unsigned long mce_need_notify;
static char mce_helper[128];
static char *mce_helper_argv[2] = { mce_helper, NULL };
-static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
+static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait);
+
static DEFINE_PER_CPU(struct mce, mces_seen);
static int cpu_missing;
@@ -373,6 +370,31 @@ static void mce_wrmsrl(u32 msr, u64 v)
}
/*
+ * Collect all global (w.r.t. this processor) status about this machine
+ * check into our "mce" struct so that we can use it later to assess
+ * the severity of the problem as we read per-bank specific details.
+ */
+static inline void mce_gather_info(struct mce *m, struct pt_regs *regs)
+{
+ mce_setup(m);
+
+ m->mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
+ if (regs) {
+ /*
+ * Get the address of the instruction at the time of
+ * the machine check error.
+ */
+ if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) {
+ m->ip = regs->ip;
+ m->cs = regs->cs;
+ }
+ /* Use accurate RIP reporting if available. */
+ if (rip_msr)
+ m->ip = mce_rdmsrl(rip_msr);
+ }
+}
+
+/*
* Simple lockless ring to communicate PFNs from the exception handler with the
* process context work function. This is vastly simplified because there's
* only a single reader and a single writer.
@@ -443,40 +465,13 @@ static void mce_schedule_work(void)
}
}
-/*
- * Get the address of the instruction at the time of the machine check
- * error.
- */
-static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
-{
-
- if (regs && (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV))) {
- m->ip = regs->ip;
- m->cs = regs->cs;
- } else {
- m->ip = 0;
- m->cs = 0;
- }
- if (rip_msr)
- m->ip = mce_rdmsrl(rip_msr);
-}
+DEFINE_PER_CPU(struct irq_work, mce_irq_work);
-#ifdef CONFIG_X86_LOCAL_APIC
-/*
- * Called after interrupts have been reenabled again
- * when a MCE happened during an interrupts off region
- * in the kernel.
- */
-asmlinkage void smp_mce_self_interrupt(struct pt_regs *regs)
+static void mce_irq_work_cb(struct irq_work *entry)
{
- ack_APIC_irq();
- exit_idle();
- irq_enter();
mce_notify_irq();
mce_schedule_work();
- irq_exit();
}
-#endif
static void mce_report_event(struct pt_regs *regs)
{
@@ -492,29 +487,7 @@ static void mce_report_event(struct pt_regs *regs)
return;
}
-#ifdef CONFIG_X86_LOCAL_APIC
- /*
- * Without APIC do not notify. The event will be picked
- * up eventually.
- */
- if (!cpu_has_apic)
- return;
-
- /*
- * When interrupts are disabled we cannot use
- * kernel services safely. Trigger an self interrupt
- * through the APIC to instead do the notification
- * after interrupts are reenabled again.
- */
- apic->send_IPI_self(MCE_SELF_VECTOR);
-
- /*
- * Wait for idle afterwards again so that we don't leave the
- * APIC in a non idle state because the normal APIC writes
- * cannot exclude us.
- */
- apic_wait_icr_idle();
-#endif
+ irq_work_queue(&__get_cpu_var(mce_irq_work));
}
DEFINE_PER_CPU(unsigned, mce_poll_count);
@@ -541,9 +514,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
percpu_inc(mce_poll_count);
- mce_setup(&m);
+ mce_gather_info(&m, NULL);
- m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
for (i = 0; i < banks; i++) {
if (!mce_banks[i].ctl || !test_bit(i, *b))
continue;
@@ -879,9 +851,9 @@ static int mce_usable_address(struct mce *m)
{
if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV))
return 0;
- if ((m->misc & 0x3f) > PAGE_SHIFT)
+ if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT)
return 0;
- if (((m->misc >> 6) & 7) != MCM_ADDR_PHYS)
+ if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS)
return 0;
return 1;
}
@@ -942,9 +914,8 @@ void do_machine_check(struct pt_regs *regs, long error_code)
if (!banks)
goto out;
- mce_setup(&m);
+ mce_gather_info(&m, regs);
- m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
final = &__get_cpu_var(mces_seen);
*final = m;
@@ -1028,7 +999,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
mce_ring_add(m.addr >> PAGE_SHIFT);
- mce_get_rip(&m, regs);
mce_log(&m);
if (severity > worst) {
@@ -1190,7 +1160,8 @@ int mce_notify_irq(void)
clear_thread_flag(TIF_MCE_NOTIFY);
if (test_and_clear_bit(0, &mce_need_notify)) {
- wake_up_interruptible(&mce_wait);
+ /* wake processes polling /dev/mcelog */
+ wake_up_interruptible(&mce_chrdev_wait);
/*
* There is no risk of missing notifications because
@@ -1363,18 +1334,23 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
return 0;
}
-static void __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
+static int __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
{
if (c->x86 != 5)
- return;
+ return 0;
+
switch (c->x86_vendor) {
case X86_VENDOR_INTEL:
intel_p5_mcheck_init(c);
+ return 1;
break;
case X86_VENDOR_CENTAUR:
winchip_mcheck_init(c);
+ return 1;
break;
}
+
+ return 0;
}
static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
@@ -1428,7 +1404,8 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
if (mce_disabled)
return;
- __mcheck_cpu_ancient_init(c);
+ if (__mcheck_cpu_ancient_init(c))
+ return;
if (!mce_available(c))
return;
@@ -1444,44 +1421,45 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
__mcheck_cpu_init_vendor(c);
__mcheck_cpu_init_timer();
INIT_WORK(&__get_cpu_var(mce_work), mce_process_work);
-
+ init_irq_work(&__get_cpu_var(mce_irq_work), &mce_irq_work_cb);
}
/*
- * Character device to read and clear the MCE log.
+ * mce_chrdev: Character device /dev/mcelog to read and clear the MCE log.
*/
-static DEFINE_SPINLOCK(mce_state_lock);
-static int open_count; /* #times opened */
-static int open_exclu; /* already open exclusive? */
+static DEFINE_SPINLOCK(mce_chrdev_state_lock);
+static int mce_chrdev_open_count; /* #times opened */
+static int mce_chrdev_open_exclu; /* already open exclusive? */
-static int mce_open(struct inode *inode, struct file *file)
+static int mce_chrdev_open(struct inode *inode, struct file *file)
{
- spin_lock(&mce_state_lock);
+ spin_lock(&mce_chrdev_state_lock);
- if (open_exclu || (open_count && (file->f_flags & O_EXCL))) {
- spin_unlock(&mce_state_lock);
+ if (mce_chrdev_open_exclu ||
+ (mce_chrdev_open_count && (file->f_flags & O_EXCL))) {
+ spin_unlock(&mce_chrdev_state_lock);
return -EBUSY;
}
if (file->f_flags & O_EXCL)
- open_exclu = 1;
- open_count++;
+ mce_chrdev_open_exclu = 1;
+ mce_chrdev_open_count++;
- spin_unlock(&mce_state_lock);
+ spin_unlock(&mce_chrdev_state_lock);
return nonseekable_open(inode, file);
}
-static int mce_release(struct inode *inode, struct file *file)
+static int mce_chrdev_release(struct inode *inode, struct file *file)
{
- spin_lock(&mce_state_lock);
+ spin_lock(&mce_chrdev_state_lock);
- open_count--;
- open_exclu = 0;
+ mce_chrdev_open_count--;
+ mce_chrdev_open_exclu = 0;
- spin_unlock(&mce_state_lock);
+ spin_unlock(&mce_chrdev_state_lock);
return 0;
}
@@ -1530,8 +1508,8 @@ static int __mce_read_apei(char __user **ubuf, size_t usize)
return 0;
}
-static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
- loff_t *off)
+static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf,
+ size_t usize, loff_t *off)
{
char __user *buf = ubuf;
unsigned long *cpu_tsc;
@@ -1542,7 +1520,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
if (!cpu_tsc)
return -ENOMEM;
- mutex_lock(&mce_read_mutex);
+ mutex_lock(&mce_chrdev_read_mutex);
if (!mce_apei_read_done) {
err = __mce_read_apei(&buf, usize);
@@ -1562,19 +1540,18 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
do {
for (i = prev; i < next; i++) {
unsigned long start = jiffies;
+ struct mce *m = &mcelog.entry[i];
- while (!mcelog.entry[i].finished) {
+ while (!m->finished) {
if (time_after_eq(jiffies, start + 2)) {
- memset(mcelog.entry + i, 0,
- sizeof(struct mce));
+ memset(m, 0, sizeof(*m));
goto timeout;
}
cpu_relax();
}
smp_rmb();
- err |= copy_to_user(buf, mcelog.entry + i,
- sizeof(struct mce));
- buf += sizeof(struct mce);
+ err |= copy_to_user(buf, m, sizeof(*m));
+ buf += sizeof(*m);
timeout:
;
}
@@ -1594,13 +1571,13 @@ timeout:
on_each_cpu(collect_tscs, cpu_tsc, 1);
for (i = next; i < MCE_LOG_LEN; i++) {
- if (mcelog.entry[i].finished &&
- mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) {
- err |= copy_to_user(buf, mcelog.entry+i,
- sizeof(struct mce));
+ struct mce *m = &mcelog.entry[i];
+
+ if (m->finished && m->tsc < cpu_tsc[m->cpu]) {
+ err |= copy_to_user(buf, m, sizeof(*m));
smp_rmb();
- buf += sizeof(struct mce);
- memset(&mcelog.entry[i], 0, sizeof(struct mce));
+ buf += sizeof(*m);
+ memset(m, 0, sizeof(*m));
}
}
@@ -1608,15 +1585,15 @@ timeout:
err = -EFAULT;
out:
- mutex_unlock(&mce_read_mutex);
+ mutex_unlock(&mce_chrdev_read_mutex);
kfree(cpu_tsc);
return err ? err : buf - ubuf;
}
-static unsigned int mce_poll(struct file *file, poll_table *wait)
+static unsigned int mce_chrdev_poll(struct file *file, poll_table *wait)
{
- poll_wait(file, &mce_wait, wait);
+ poll_wait(file, &mce_chrdev_wait, wait);
if (rcu_access_index(mcelog.next))
return POLLIN | POLLRDNORM;
if (!mce_apei_read_done && apei_check_mce())
@@ -1624,7 +1601,8 @@ static unsigned int mce_poll(struct file *file, poll_table *wait)
return 0;
}
-static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
+ unsigned long arg)
{
int __user *p = (int __user *)arg;
@@ -1652,16 +1630,16 @@ static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
/* Modified in mce-inject.c, so not static or const */
struct file_operations mce_chrdev_ops = {
- .open = mce_open,
- .release = mce_release,
- .read = mce_read,
- .poll = mce_poll,
- .unlocked_ioctl = mce_ioctl,
- .llseek = no_llseek,
+ .open = mce_chrdev_open,
+ .release = mce_chrdev_release,
+ .read = mce_chrdev_read,
+ .poll = mce_chrdev_poll,
+ .unlocked_ioctl = mce_chrdev_ioctl,
+ .llseek = no_llseek,
};
EXPORT_SYMBOL_GPL(mce_chrdev_ops);
-static struct miscdevice mce_log_device = {
+static struct miscdevice mce_chrdev_device = {
MISC_MCELOG_MINOR,
"mcelog",
&mce_chrdev_ops,
@@ -1719,7 +1697,7 @@ int __init mcheck_init(void)
}
/*
- * Sysfs support
+ * mce_syscore: PM support
*/
/*
@@ -1739,12 +1717,12 @@ static int mce_disable_error_reporting(void)
return 0;
}
-static int mce_suspend(void)
+static int mce_syscore_suspend(void)
{
return mce_disable_error_reporting();
}
-static void mce_shutdown(void)
+static void mce_syscore_shutdown(void)
{
mce_disable_error_reporting();
}
@@ -1754,18 +1732,22 @@ static void mce_shutdown(void)
* Only one CPU is active at this time, the others get re-added later using
* CPU hotplug:
*/
-static void mce_resume(void)
+static void mce_syscore_resume(void)
{
__mcheck_cpu_init_generic();
__mcheck_cpu_init_vendor(__this_cpu_ptr(&cpu_info));
}
static struct syscore_ops mce_syscore_ops = {
- .suspend = mce_suspend,
- .shutdown = mce_shutdown,
- .resume = mce_resume,
+ .suspend = mce_syscore_suspend,
+ .shutdown = mce_syscore_shutdown,
+ .resume = mce_syscore_resume,
};
+/*
+ * mce_sysdev: Sysfs support
+ */
+
static void mce_cpu_restart(void *data)
{
del_timer_sync(&__get_cpu_var(mce_timer));
@@ -1801,11 +1783,11 @@ static void mce_enable_ce(void *all)
__mcheck_cpu_init_timer();
}
-static struct sysdev_class mce_sysclass = {
+static struct sysdev_class mce_sysdev_class = {
.name = "machinecheck",
};
-DEFINE_PER_CPU(struct sys_device, mce_dev);
+DEFINE_PER_CPU(struct sys_device, mce_sysdev);
__cpuinitdata
void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
@@ -1934,7 +1916,7 @@ static struct sysdev_ext_attribute attr_cmci_disabled = {
&mce_cmci_disabled
};
-static struct sysdev_attribute *mce_attrs[] = {
+static struct sysdev_attribute *mce_sysdev_attrs[] = {
&attr_tolerant.attr,
&attr_check_interval.attr,
&attr_trigger,
@@ -1945,66 +1927,67 @@ static struct sysdev_attribute *mce_attrs[] = {
NULL
};
-static cpumask_var_t mce_dev_initialized;
+static cpumask_var_t mce_sysdev_initialized;
/* Per cpu sysdev init. All of the cpus still share the same ctrl bank: */
-static __cpuinit int mce_create_device(unsigned int cpu)
+static __cpuinit int mce_sysdev_create(unsigned int cpu)
{
+ struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu);
int err;
int i, j;
if (!mce_available(&boot_cpu_data))
return -EIO;
- memset(&per_cpu(mce_dev, cpu).kobj, 0, sizeof(struct kobject));
- per_cpu(mce_dev, cpu).id = cpu;
- per_cpu(mce_dev, cpu).cls = &mce_sysclass;
+ memset(&sysdev->kobj, 0, sizeof(struct kobject));
+ sysdev->id = cpu;
+ sysdev->cls = &mce_sysdev_class;
- err = sysdev_register(&per_cpu(mce_dev, cpu));
+ err = sysdev_register(sysdev);
if (err)
return err;
- for (i = 0; mce_attrs[i]; i++) {
- err = sysdev_create_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+ for (i = 0; mce_sysdev_attrs[i]; i++) {
+ err = sysdev_create_file(sysdev, mce_sysdev_attrs[i]);
if (err)
goto error;
}
for (j = 0; j < banks; j++) {
- err = sysdev_create_file(&per_cpu(mce_dev, cpu),
- &mce_banks[j].attr);
+ err = sysdev_create_file(sysdev, &mce_banks[j].attr);
if (err)
goto error2;
}
- cpumask_set_cpu(cpu, mce_dev_initialized);
+ cpumask_set_cpu(cpu, mce_sysdev_initialized);
return 0;
error2:
while (--j >= 0)
- sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[j].attr);
+ sysdev_remove_file(sysdev, &mce_banks[j].attr);
error:
while (--i >= 0)
- sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+ sysdev_remove_file(sysdev, mce_sysdev_attrs[i]);
- sysdev_unregister(&per_cpu(mce_dev, cpu));
+ sysdev_unregister(sysdev);
return err;
}
-static __cpuinit void mce_remove_device(unsigned int cpu)
+static __cpuinit void mce_sysdev_remove(unsigned int cpu)
{
+ struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu);
int i;
- if (!cpumask_test_cpu(cpu, mce_dev_initialized))
+ if (!cpumask_test_cpu(cpu, mce_sysdev_initialized))
return;
- for (i = 0; mce_attrs[i]; i++)
- sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+ for (i = 0; mce_sysdev_attrs[i]; i++)
+ sysdev_remove_file(sysdev, mce_sysdev_attrs[i]);
for (i = 0; i < banks; i++)
- sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[i].attr);
+ sysdev_remove_file(sysdev, &mce_banks[i].attr);
- sysdev_unregister(&per_cpu(mce_dev, cpu));
- cpumask_clear_cpu(cpu, mce_dev_initialized);
+ sysdev_unregister(sysdev);
+ cpumask_clear_cpu(cpu, mce_sysdev_initialized);
}
/* Make sure there are no machine checks on offlined CPUs. */
@@ -2054,7 +2037,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
- mce_create_device(cpu);
+ mce_sysdev_create(cpu);
if (threshold_cpu_callback)
threshold_cpu_callback(action, cpu);
break;
@@ -2062,7 +2045,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_DEAD_FROZEN:
if (threshold_cpu_callback)
threshold_cpu_callback(action, cpu);
- mce_remove_device(cpu);
+ mce_sysdev_remove(cpu);
break;
case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN:
@@ -2116,27 +2099,28 @@ static __init int mcheck_init_device(void)
if (!mce_available(&boot_cpu_data))
return -EIO;
- zalloc_cpumask_var(&mce_dev_initialized, GFP_KERNEL);
+ zalloc_cpumask_var(&mce_sysdev_initialized, GFP_KERNEL);
mce_init_banks();
- err = sysdev_class_register(&mce_sysclass);
+ err = sysdev_class_register(&mce_sysdev_class);
if (err)
return err;
for_each_online_cpu(i) {
- err = mce_create_device(i);
+ err = mce_sysdev_create(i);
if (err)
return err;
}
register_syscore_ops(&mce_syscore_ops);
register_hotcpu_notifier(&mce_cpu_notifier);
- misc_register(&mce_log_device);
+
+ /* register character device /dev/mcelog */
+ misc_register(&mce_chrdev_device);
return err;
}
-
device_initcall(mcheck_init_device);
/*
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index bb0adad35143..f5474218cffe 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -548,7 +548,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
if (!b)
goto out;
- err = sysfs_create_link(&per_cpu(mce_dev, cpu).kobj,
+ err = sysfs_create_link(&per_cpu(mce_sysdev, cpu).kobj,
b->kobj, name);
if (err)
goto out;
@@ -571,7 +571,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
goto out;
}
- b->kobj = kobject_create_and_add(name, &per_cpu(mce_dev, cpu).kobj);
+ b->kobj = kobject_create_and_add(name, &per_cpu(mce_sysdev, cpu).kobj);
if (!b->kobj)
goto out_free;
@@ -591,7 +591,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
if (i == cpu)
continue;
- err = sysfs_create_link(&per_cpu(mce_dev, i).kobj,
+ err = sysfs_create_link(&per_cpu(mce_sysdev, i).kobj,
b->kobj, name);
if (err)
goto out;
@@ -669,7 +669,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
#ifdef CONFIG_SMP
/* sibling symlink */
if (shared_bank[bank] && b->blocks->cpu != cpu) {
- sysfs_remove_link(&per_cpu(mce_dev, cpu).kobj, name);
+ sysfs_remove_link(&per_cpu(mce_sysdev, cpu).kobj, name);
per_cpu(threshold_banks, cpu)[bank] = NULL;
return;
@@ -681,7 +681,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
if (i == cpu)
continue;
- sysfs_remove_link(&per_cpu(mce_dev, i).kobj, name);
+ sysfs_remove_link(&per_cpu(mce_sysdev, i).kobj, name);
per_cpu(threshold_banks, i)[bank] = NULL;
}
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 929739a653d1..08119a37e53c 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -79,7 +79,6 @@ void set_mtrr_ops(const struct mtrr_ops *ops)
static int have_wrcomb(void)
{
struct pci_dev *dev;
- u8 rev;
dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, NULL);
if (dev != NULL) {
@@ -89,13 +88,11 @@ static int have_wrcomb(void)
* chipsets to be tagged
*/
if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
- dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) {
- pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
- if (rev <= 5) {
- pr_info("mtrr: Serverworks LE rev < 6 detected. Write-combining disabled.\n");
- pci_dev_put(dev);
- return 0;
- }
+ dev->device == PCI_DEVICE_ID_SERVERWORKS_LE &&
+ dev->revision <= 5) {
+ pr_info("mtrr: Serverworks LE rev < 6 detected. Write-combining disabled.\n");
+ pci_dev_put(dev);
+ return 0;
}
/*
* Intel 450NX errata # 23. Non ascending cacheline evictions to
@@ -137,55 +134,43 @@ static void __init init_table(void)
}
struct set_mtrr_data {
- atomic_t count;
- atomic_t gate;
unsigned long smp_base;
unsigned long smp_size;
unsigned int smp_reg;
mtrr_type smp_type;
};
-static DEFINE_PER_CPU(struct cpu_stop_work, mtrr_work);
-
/**
- * mtrr_work_handler - Synchronisation handler. Executed by "other" CPUs.
+ * mtrr_rendezvous_handler - Work done in the synchronization handler. Executed
+ * by all the CPUs.
* @info: pointer to mtrr configuration data
*
* Returns nothing.
*/
-static int mtrr_work_handler(void *info)
+static int mtrr_rendezvous_handler(void *info)
{
#ifdef CONFIG_SMP
struct set_mtrr_data *data = info;
- unsigned long flags;
-
- atomic_dec(&data->count);
- while (!atomic_read(&data->gate))
- cpu_relax();
-
- local_irq_save(flags);
-
- atomic_dec(&data->count);
- while (atomic_read(&data->gate))
- cpu_relax();
- /* The master has cleared me to execute */
+ /*
+ * We use this same function to initialize the mtrrs during boot,
+ * resume, runtime cpu online and on an explicit request to set a
+ * specific MTRR.
+ *
+ * During boot or suspend, the state of the boot cpu's mtrrs has been
+ * saved, and we want to replicate that across all the cpus that come
+ * online (either at the end of boot or resume or during a runtime cpu
+ * online). If we're doing that, @reg is set to something special and on
+ * all the cpu's we do mtrr_if->set_all() (On the logical cpu that
+ * started the boot/resume sequence, this might be a duplicate
+ * set_all()).
+ */
if (data->smp_reg != ~0U) {
mtrr_if->set(data->smp_reg, data->smp_base,
data->smp_size, data->smp_type);
- } else if (mtrr_aps_delayed_init) {
- /*
- * Initialize the MTRRs inaddition to the synchronisation.
- */
+ } else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) {
mtrr_if->set_all();
}
-
- atomic_dec(&data->count);
- while (!atomic_read(&data->gate))
- cpu_relax();
-
- atomic_dec(&data->count);
- local_irq_restore(flags);
#endif
return 0;
}
@@ -223,20 +208,11 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2)
* 14. Wait for buddies to catch up
* 15. Enable interrupts.
*
- * What does that mean for us? Well, first we set data.count to the number
- * of CPUs. As each CPU announces that it started the rendezvous handler by
- * decrementing the count, We reset data.count and set the data.gate flag
- * allowing all the cpu's to proceed with the work. As each cpu disables
- * interrupts, it'll decrement data.count once. We wait until it hits 0 and
- * proceed. We clear the data.gate flag and reset data.count. Meanwhile, they
- * are waiting for that flag to be cleared. Once it's cleared, each
- * CPU goes through the transition of updating MTRRs.
- * The CPU vendors may each do it differently,
- * so we call mtrr_if->set() callback and let them take care of it.
- * When they're done, they again decrement data->count and wait for data.gate
- * to be set.
- * When we finish, we wait for data.count to hit 0 and toggle the data.gate flag
- * Everyone then enables interrupts and we all continue on.
+ * What does that mean for us? Well, stop_machine() will ensure that
+ * the rendezvous handler is started on each CPU. And in lockstep they
+ * do the state transition of disabling interrupts, updating MTRR's
+ * (the CPU vendors may each do it differently, so we call mtrr_if->set()
+ * callback and let them take care of it.) and enabling interrupts.
*
* Note that the mechanism is the same for UP systems, too; all the SMP stuff
* becomes nops.
@@ -244,92 +220,26 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2)
static void
set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type)
{
- struct set_mtrr_data data;
- unsigned long flags;
- int cpu;
-
- preempt_disable();
-
- data.smp_reg = reg;
- data.smp_base = base;
- data.smp_size = size;
- data.smp_type = type;
- atomic_set(&data.count, num_booting_cpus() - 1);
-
- /* Make sure data.count is visible before unleashing other CPUs */
- smp_wmb();
- atomic_set(&data.gate, 0);
-
- /* Start the ball rolling on other CPUs */
- for_each_online_cpu(cpu) {
- struct cpu_stop_work *work = &per_cpu(mtrr_work, cpu);
-
- if (cpu == smp_processor_id())
- continue;
-
- stop_one_cpu_nowait(cpu, mtrr_work_handler, &data, work);
- }
-
-
- while (atomic_read(&data.count))
- cpu_relax();
-
- /* Ok, reset count and toggle gate */
- atomic_set(&data.count, num_booting_cpus() - 1);
- smp_wmb();
- atomic_set(&data.gate, 1);
-
- local_irq_save(flags);
-
- while (atomic_read(&data.count))
- cpu_relax();
-
- /* Ok, reset count and toggle gate */
- atomic_set(&data.count, num_booting_cpus() - 1);
- smp_wmb();
- atomic_set(&data.gate, 0);
-
- /* Do our MTRR business */
-
- /*
- * HACK!
- *
- * We use this same function to initialize the mtrrs during boot,
- * resume, runtime cpu online and on an explicit request to set a
- * specific MTRR.
- *
- * During boot or suspend, the state of the boot cpu's mtrrs has been
- * saved, and we want to replicate that across all the cpus that come
- * online (either at the end of boot or resume or during a runtime cpu
- * online). If we're doing that, @reg is set to something special and on
- * this cpu we still do mtrr_if->set_all(). During boot/resume, this
- * is unnecessary if at this point we are still on the cpu that started
- * the boot/resume sequence. But there is no guarantee that we are still
- * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be
- * sure that we are in sync with everyone else.
- */
- if (reg != ~0U)
- mtrr_if->set(reg, base, size, type);
- else
- mtrr_if->set_all();
+ struct set_mtrr_data data = { .smp_reg = reg,
+ .smp_base = base,
+ .smp_size = size,
+ .smp_type = type
+ };
- /* Wait for the others */
- while (atomic_read(&data.count))
- cpu_relax();
-
- atomic_set(&data.count, num_booting_cpus() - 1);
- smp_wmb();
- atomic_set(&data.gate, 1);
-
- /*
- * Wait here for everyone to have seen the gate change
- * So we're the last ones to touch 'data'
- */
- while (atomic_read(&data.count))
- cpu_relax();
+ stop_machine(mtrr_rendezvous_handler, &data, cpu_online_mask);
+}
- local_irq_restore(flags);
- preempt_enable();
+static void set_mtrr_from_inactive_cpu(unsigned int reg, unsigned long base,
+ unsigned long size, mtrr_type type)
+{
+ struct set_mtrr_data data = { .smp_reg = reg,
+ .smp_base = base,
+ .smp_size = size,
+ .smp_type = type
+ };
+
+ stop_machine_from_inactive_cpu(mtrr_rendezvous_handler, &data,
+ cpu_callout_mask);
}
/**
@@ -783,7 +693,7 @@ void mtrr_ap_init(void)
* 2. cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug
* lock to prevent mtrr entry changes
*/
- set_mtrr(~0U, 0, 0, 0);
+ set_mtrr_from_inactive_cpu(~0U, 0, 0, 0);
}
/**
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 3a0338b4b179..4ee3abf20ed6 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -22,7 +22,6 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
-#include <linux/highmem.h>
#include <linux/cpu.h>
#include <linux/bitops.h>
@@ -45,38 +44,27 @@ do { \
#endif
/*
- * best effort, GUP based copy_from_user() that assumes IRQ or NMI context
+ * | 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.
*/
-static unsigned long
-copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
-{
- unsigned long offset, addr = (unsigned long)from;
- unsigned long size, len = 0;
- struct page *page;
- void *map;
- int ret;
-
- do {
- ret = __get_user_pages_fast(addr, 1, 0, &page);
- if (!ret)
- break;
-
- offset = addr & (PAGE_SIZE - 1);
- size = min(PAGE_SIZE - offset, n - len);
-
- map = kmap_atomic(page);
- memcpy(to, map+offset, size);
- kunmap_atomic(map);
- put_page(page);
+enum extra_reg_type {
+ EXTRA_REG_NONE = -1, /* not used */
- len += size;
- to += size;
- addr += size;
+ EXTRA_REG_RSP_0 = 0, /* offcore_response_0 */
+ EXTRA_REG_RSP_1 = 1, /* offcore_response_1 */
- } while (len < n);
-
- return len;
-}
+ EXTRA_REG_MAX /* number of entries needed */
+};
struct event_constraint {
union {
@@ -132,11 +120,10 @@ struct cpu_hw_events {
struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES];
/*
- * Intel percore register state.
- * Coordinate shared resources between HT threads.
+ * manage shared (per-core, per-cpu) registers
+ * used on Intel NHM/WSM/SNB
*/
- int percore_used; /* Used by this CPU? */
- struct intel_percore *per_core;
+ struct intel_shared_regs *shared_regs;
/*
* AMD specific bits
@@ -187,26 +174,45 @@ struct cpu_hw_events {
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.
- * Define a mapping to these extra registers.
+ * 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) { \
+#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) \
- EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm)
-#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0)
+
+#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 {
@@ -252,7 +258,6 @@ struct x86_pmu {
void (*put_event_constraints)(struct cpu_hw_events *cpuc,
struct perf_event *event);
struct event_constraint *event_constraints;
- struct event_constraint *percore_constraints;
void (*quirks)(void);
int perfctr_second_write;
@@ -286,8 +291,12 @@ struct x86_pmu {
* 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) = {
@@ -393,10 +402,10 @@ static inline unsigned int x86_pmu_event_addr(int index)
*/
static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
{
+ struct hw_perf_event_extra *reg;
struct extra_reg *er;
- event->hw.extra_reg = 0;
- event->hw.extra_config = 0;
+ reg = &event->hw.extra_reg;
if (!x86_pmu.extra_regs)
return 0;
@@ -406,8 +415,10 @@ static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
continue;
if (event->attr.config1 & ~er->valid_mask)
return -EINVAL;
- event->hw.extra_reg = er->msr;
- event->hw.extra_config = event->attr.config1;
+
+ reg->idx = er->idx;
+ reg->config = event->attr.config1;
+ reg->reg = er->msr;
break;
}
return 0;
@@ -706,6 +717,9 @@ static int __x86_pmu_event_init(struct perf_event *event)
event->hw.last_cpu = -1;
event->hw.last_tag = ~0ULL;
+ /* mark unused */
+ event->hw.extra_reg.idx = EXTRA_REG_NONE;
+
return x86_pmu.hw_config(event);
}
@@ -747,8 +761,8 @@ static void x86_pmu_disable(struct pmu *pmu)
static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
u64 enable_mask)
{
- if (hwc->extra_reg)
- wrmsrl(hwc->extra_reg, hwc->extra_config);
+ if (hwc->extra_reg.reg)
+ wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
wrmsrl(hwc->config_base, hwc->config | enable_mask);
}
@@ -1332,7 +1346,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
if (!x86_perf_event_set_period(event))
continue;
- if (perf_event_overflow(event, 1, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
x86_pmu_stop(event, 0);
}
@@ -1637,6 +1651,40 @@ static int x86_pmu_commit_txn(struct pmu *pmu)
perf_pmu_enable(pmu);
return 0;
}
+/*
+ * a fake_cpuc is used to validate event groups. Due to
+ * the extra reg logic, we need to also allocate a fake
+ * per_core and per_cpu structure. Otherwise, group events
+ * using extra reg may conflict without the kernel being
+ * able to catch this when the last event gets added to
+ * the group.
+ */
+static void free_fake_cpuc(struct cpu_hw_events *cpuc)
+{
+ kfree(cpuc->shared_regs);
+ kfree(cpuc);
+}
+
+static struct cpu_hw_events *allocate_fake_cpuc(void)
+{
+ struct cpu_hw_events *cpuc;
+ int cpu = raw_smp_processor_id();
+
+ cpuc = kzalloc(sizeof(*cpuc), GFP_KERNEL);
+ if (!cpuc)
+ return ERR_PTR(-ENOMEM);
+
+ /* only needed, if we have extra_regs */
+ if (x86_pmu.extra_regs) {
+ cpuc->shared_regs = allocate_shared_regs(cpu);
+ if (!cpuc->shared_regs)
+ goto error;
+ }
+ return cpuc;
+error:
+ free_fake_cpuc(cpuc);
+ return ERR_PTR(-ENOMEM);
+}
/*
* validate that we can schedule this event
@@ -1647,9 +1695,9 @@ static int validate_event(struct perf_event *event)
struct event_constraint *c;
int ret = 0;
- fake_cpuc = kmalloc(sizeof(*fake_cpuc), GFP_KERNEL | __GFP_ZERO);
- if (!fake_cpuc)
- return -ENOMEM;
+ fake_cpuc = allocate_fake_cpuc();
+ if (IS_ERR(fake_cpuc))
+ return PTR_ERR(fake_cpuc);
c = x86_pmu.get_event_constraints(fake_cpuc, event);
@@ -1659,7 +1707,7 @@ static int validate_event(struct perf_event *event)
if (x86_pmu.put_event_constraints)
x86_pmu.put_event_constraints(fake_cpuc, event);
- kfree(fake_cpuc);
+ free_fake_cpuc(fake_cpuc);
return ret;
}
@@ -1679,36 +1727,32 @@ static int validate_group(struct perf_event *event)
{
struct perf_event *leader = event->group_leader;
struct cpu_hw_events *fake_cpuc;
- int ret, n;
-
- ret = -ENOMEM;
- fake_cpuc = kmalloc(sizeof(*fake_cpuc), GFP_KERNEL | __GFP_ZERO);
- if (!fake_cpuc)
- goto out;
+ int ret = -ENOSPC, n;
+ fake_cpuc = allocate_fake_cpuc();
+ if (IS_ERR(fake_cpuc))
+ return PTR_ERR(fake_cpuc);
/*
* the event is not yet connected with its
* siblings therefore we must first collect
* existing siblings, then add the new event
* before we can simulate the scheduling
*/
- ret = -ENOSPC;
n = collect_events(fake_cpuc, leader, true);
if (n < 0)
- goto out_free;
+ goto out;
fake_cpuc->n_events = n;
n = collect_events(fake_cpuc, event, false);
if (n < 0)
- goto out_free;
+ goto out;
fake_cpuc->n_events = n;
ret = x86_pmu.schedule_events(fake_cpuc, n, NULL);
-out_free:
- kfree(fake_cpuc);
out:
+ free_fake_cpuc(fake_cpuc);
return ret;
}
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index fe29c1d2219e..941caa2e449b 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -89,6 +89,20 @@ static __initconst const u64 amd_hw_cache_event_ids
[ C(RESULT_MISS) ] = -1,
},
},
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0xb8e9, /* CPU Request to Memory, l+r */
+ [ C(RESULT_MISS) ] = 0x98e9, /* CPU Request to Memory, r */
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
};
/*
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 41178c826c48..45fbb8f7f549 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1,25 +1,15 @@
#ifdef CONFIG_CPU_SUP_INTEL
-#define MAX_EXTRA_REGS 2
-
-/*
- * Per register state.
- */
-struct er_account {
- int ref; /* reference count */
- unsigned int extra_reg; /* extra MSR number */
- u64 extra_config; /* extra MSR config */
-};
-
/*
- * Per core state
- * This used to coordinate shared registers for HT threads.
+ * Per core/cpu state
+ *
+ * Used to coordinate shared registers between HT threads or
+ * among events on a single PMU.
*/
-struct intel_percore {
- raw_spinlock_t lock; /* protect structure */
- struct er_account regs[MAX_EXTRA_REGS];
- int refcnt; /* number of threads */
- unsigned core_id;
+struct intel_shared_regs {
+ struct er_account regs[EXTRA_REG_MAX];
+ int refcnt; /* per-core: #HT threads */
+ unsigned core_id; /* per-core: core id */
};
/*
@@ -88,16 +78,10 @@ static struct event_constraint intel_nehalem_event_constraints[] __read_mostly =
static struct extra_reg intel_nehalem_extra_regs[] __read_mostly =
{
- INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
+ INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
EVENT_EXTRA_END
};
-static struct event_constraint intel_nehalem_percore_constraints[] __read_mostly =
-{
- INTEL_EVENT_CONSTRAINT(0xb7, 0),
- EVENT_CONSTRAINT_END
-};
-
static struct event_constraint intel_westmere_event_constraints[] __read_mostly =
{
FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -116,8 +100,6 @@ static struct event_constraint intel_snb_event_constraints[] __read_mostly =
FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
- INTEL_EVENT_CONSTRAINT(0xb7, 0x1), /* OFF_CORE_RESPONSE_0 */
- INTEL_EVENT_CONSTRAINT(0xbb, 0x8), /* OFF_CORE_RESPONSE_1 */
INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
EVENT_CONSTRAINT_END
@@ -125,15 +107,13 @@ static struct event_constraint intel_snb_event_constraints[] __read_mostly =
static struct extra_reg intel_westmere_extra_regs[] __read_mostly =
{
- INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
- INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff),
+ INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
+ INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff, RSP_1),
EVENT_EXTRA_END
};
-static struct event_constraint intel_westmere_percore_constraints[] __read_mostly =
+static struct event_constraint intel_v1_event_constraints[] __read_mostly =
{
- INTEL_EVENT_CONSTRAINT(0xb7, 0),
- INTEL_EVENT_CONSTRAINT(0xbb, 0),
EVENT_CONSTRAINT_END
};
@@ -145,6 +125,12 @@ static struct event_constraint intel_gen_event_constraints[] __read_mostly =
EVENT_CONSTRAINT_END
};
+static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
+ INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
+ INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
+ EVENT_EXTRA_END
+};
+
static u64 intel_pmu_event_map(int hw_event)
{
return intel_perfmon_event_map[hw_event];
@@ -245,6 +231,21 @@ static __initconst const u64 snb_hw_cache_event_ids
[ C(RESULT_MISS) ] = -1,
},
},
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
+
};
static __initconst const u64 westmere_hw_cache_event_ids
@@ -346,6 +347,20 @@ static __initconst const u64 westmere_hw_cache_event_ids
[ C(RESULT_MISS) ] = -1,
},
},
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x01b7,
+ [ C(RESULT_MISS) ] = 0x01b7,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0x01b7,
+ [ C(RESULT_MISS) ] = 0x01b7,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0x01b7,
+ [ C(RESULT_MISS) ] = 0x01b7,
+ },
+ },
};
/*
@@ -398,7 +413,21 @@ static __initconst const u64 nehalem_hw_cache_extra_regs
[ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS,
[ C(RESULT_MISS) ] = NHM_DMND_PREFETCH|NHM_L3_MISS,
},
- }
+ },
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_ALL_DRAM,
+ [ C(RESULT_MISS) ] = NHM_DMND_READ|NHM_REMOTE_DRAM,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_ALL_DRAM,
+ [ C(RESULT_MISS) ] = NHM_DMND_WRITE|NHM_REMOTE_DRAM,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_ALL_DRAM,
+ [ C(RESULT_MISS) ] = NHM_DMND_PREFETCH|NHM_REMOTE_DRAM,
+ },
+ },
};
static __initconst const u64 nehalem_hw_cache_event_ids
@@ -500,6 +529,20 @@ static __initconst const u64 nehalem_hw_cache_event_ids
[ C(RESULT_MISS) ] = -1,
},
},
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x01b7,
+ [ C(RESULT_MISS) ] = 0x01b7,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0x01b7,
+ [ C(RESULT_MISS) ] = 0x01b7,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0x01b7,
+ [ C(RESULT_MISS) ] = 0x01b7,
+ },
+ },
};
static __initconst const u64 core2_hw_cache_event_ids
@@ -1003,7 +1046,7 @@ again:
data.period = event->hw.last_period;
- if (perf_event_overflow(event, 1, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
x86_pmu_stop(event, 0);
}
@@ -1037,65 +1080,121 @@ intel_bts_constraints(struct perf_event *event)
return NULL;
}
+static bool intel_try_alt_er(struct perf_event *event, int orig_idx)
+{
+ if (!(x86_pmu.er_flags & ERF_HAS_RSP_1))
+ return false;
+
+ if (event->hw.extra_reg.idx == EXTRA_REG_RSP_0) {
+ event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
+ event->hw.config |= 0x01bb;
+ event->hw.extra_reg.idx = EXTRA_REG_RSP_1;
+ event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1;
+ } else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) {
+ event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
+ event->hw.config |= 0x01b7;
+ event->hw.extra_reg.idx = EXTRA_REG_RSP_0;
+ event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0;
+ }
+
+ if (event->hw.extra_reg.idx == orig_idx)
+ return false;
+
+ return true;
+}
+
+/*
+ * manage allocation of shared extra msr for certain events
+ *
+ * sharing can be:
+ * per-cpu: to be shared between the various events on a single PMU
+ * per-core: per-cpu + shared by HT threads
+ */
static struct event_constraint *
-intel_percore_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+__intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc,
+ struct perf_event *event)
{
- struct hw_perf_event *hwc = &event->hw;
- unsigned int e = hwc->config & ARCH_PERFMON_EVENTSEL_EVENT;
- struct event_constraint *c;
- struct intel_percore *pc;
+ struct event_constraint *c = &emptyconstraint;
+ struct hw_perf_event_extra *reg = &event->hw.extra_reg;
struct er_account *era;
- int i;
- int free_slot;
- int found;
+ unsigned long flags;
+ int orig_idx = reg->idx;
- if (!x86_pmu.percore_constraints || hwc->extra_alloc)
- return NULL;
+ /* already allocated shared msr */
+ if (reg->alloc)
+ return &unconstrained;
- for (c = x86_pmu.percore_constraints; c->cmask; c++) {
- if (e != c->code)
- continue;
+again:
+ era = &cpuc->shared_regs->regs[reg->idx];
+ /*
+ * we use spin_lock_irqsave() to avoid lockdep issues when
+ * passing a fake cpuc
+ */
+ raw_spin_lock_irqsave(&era->lock, flags);
+
+ if (!atomic_read(&era->ref) || era->config == reg->config) {
+
+ /* lock in msr value */
+ era->config = reg->config;
+ era->reg = reg->reg;
+
+ /* one more user */
+ atomic_inc(&era->ref);
+
+ /* no need to reallocate during incremental event scheduling */
+ reg->alloc = 1;
/*
- * Allocate resource per core.
+ * All events using extra_reg are unconstrained.
+ * Avoids calling x86_get_event_constraints()
+ *
+ * Must revisit if extra_reg controlling events
+ * ever have constraints. Worst case we go through
+ * the regular event constraint table.
*/
- pc = cpuc->per_core;
- if (!pc)
- break;
- c = &emptyconstraint;
- raw_spin_lock(&pc->lock);
- free_slot = -1;
- found = 0;
- for (i = 0; i < MAX_EXTRA_REGS; i++) {
- era = &pc->regs[i];
- if (era->ref > 0 && hwc->extra_reg == era->extra_reg) {
- /* Allow sharing same config */
- if (hwc->extra_config == era->extra_config) {
- era->ref++;
- cpuc->percore_used = 1;
- hwc->extra_alloc = 1;
- c = NULL;
- }
- /* else conflict */
- found = 1;
- break;
- } else if (era->ref == 0 && free_slot == -1)
- free_slot = i;
- }
- if (!found && free_slot != -1) {
- era = &pc->regs[free_slot];
- era->ref = 1;
- era->extra_reg = hwc->extra_reg;
- era->extra_config = hwc->extra_config;
- cpuc->percore_used = 1;
- hwc->extra_alloc = 1;
- c = NULL;
- }
- raw_spin_unlock(&pc->lock);
- return c;
+ c = &unconstrained;
+ } else if (intel_try_alt_er(event, orig_idx)) {
+ raw_spin_unlock(&era->lock);
+ goto again;
}
+ raw_spin_unlock_irqrestore(&era->lock, flags);
- return NULL;
+ return c;
+}
+
+static void
+__intel_shared_reg_put_constraints(struct cpu_hw_events *cpuc,
+ struct hw_perf_event_extra *reg)
+{
+ struct er_account *era;
+
+ /*
+ * only put constraint if extra reg was actually
+ * allocated. Also takes care of event which do
+ * not use an extra shared reg
+ */
+ if (!reg->alloc)
+ return;
+
+ era = &cpuc->shared_regs->regs[reg->idx];
+
+ /* one fewer user */
+ atomic_dec(&era->ref);
+
+ /* allocate again next time */
+ reg->alloc = 0;
+}
+
+static struct event_constraint *
+intel_shared_regs_constraints(struct cpu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ struct event_constraint *c = NULL;
+
+ if (event->hw.extra_reg.idx != EXTRA_REG_NONE)
+ c = __intel_shared_reg_get_constraints(cpuc, event);
+
+ return c;
}
static struct event_constraint *
@@ -1111,49 +1210,28 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event
if (c)
return c;
- c = intel_percore_constraints(cpuc, event);
+ c = intel_shared_regs_constraints(cpuc, event);
if (c)
return c;
return x86_get_event_constraints(cpuc, event);
}
-static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
+static void
+intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
struct perf_event *event)
{
- struct extra_reg *er;
- struct intel_percore *pc;
- struct er_account *era;
- struct hw_perf_event *hwc = &event->hw;
- int i, allref;
+ struct hw_perf_event_extra *reg;
- if (!cpuc->percore_used)
- return;
-
- for (er = x86_pmu.extra_regs; er->msr; er++) {
- if (er->event != (hwc->config & er->config_mask))
- continue;
+ reg = &event->hw.extra_reg;
+ if (reg->idx != EXTRA_REG_NONE)
+ __intel_shared_reg_put_constraints(cpuc, reg);
+}
- pc = cpuc->per_core;
- raw_spin_lock(&pc->lock);
- for (i = 0; i < MAX_EXTRA_REGS; i++) {
- era = &pc->regs[i];
- if (era->ref > 0 &&
- era->extra_config == hwc->extra_config &&
- era->extra_reg == er->msr) {
- era->ref--;
- hwc->extra_alloc = 0;
- break;
- }
- }
- allref = 0;
- for (i = 0; i < MAX_EXTRA_REGS; i++)
- allref += pc->regs[i].ref;
- if (allref == 0)
- cpuc->percore_used = 0;
- raw_spin_unlock(&pc->lock);
- break;
- }
+static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ intel_put_shared_regs_event_constraints(cpuc, event);
}
static int intel_pmu_hw_config(struct perf_event *event)
@@ -1231,20 +1309,36 @@ static __initconst const struct x86_pmu core_pmu = {
.event_constraints = intel_core_event_constraints,
};
+static struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+ struct intel_shared_regs *regs;
+ int i;
+
+ regs = kzalloc_node(sizeof(struct intel_shared_regs),
+ GFP_KERNEL, cpu_to_node(cpu));
+ if (regs) {
+ /*
+ * initialize the locks to keep lockdep happy
+ */
+ for (i = 0; i < EXTRA_REG_MAX; i++)
+ raw_spin_lock_init(&regs->regs[i].lock);
+
+ regs->core_id = -1;
+ }
+ return regs;
+}
+
static int intel_pmu_cpu_prepare(int cpu)
{
struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
- if (!cpu_has_ht_siblings())
+ if (!x86_pmu.extra_regs)
return NOTIFY_OK;
- cpuc->per_core = kzalloc_node(sizeof(struct intel_percore),
- GFP_KERNEL, cpu_to_node(cpu));
- if (!cpuc->per_core)
+ cpuc->shared_regs = allocate_shared_regs(cpu);
+ if (!cpuc->shared_regs)
return NOTIFY_BAD;
- raw_spin_lock_init(&cpuc->per_core->lock);
- cpuc->per_core->core_id = -1;
return NOTIFY_OK;
}
@@ -1260,32 +1354,34 @@ static void intel_pmu_cpu_starting(int cpu)
*/
intel_pmu_lbr_reset();
- if (!cpu_has_ht_siblings())
+ if (!cpuc->shared_regs || (x86_pmu.er_flags & ERF_NO_HT_SHARING))
return;
for_each_cpu(i, topology_thread_cpumask(cpu)) {
- struct intel_percore *pc = per_cpu(cpu_hw_events, i).per_core;
+ struct intel_shared_regs *pc;
+ pc = per_cpu(cpu_hw_events, i).shared_regs;
if (pc && pc->core_id == core_id) {
- kfree(cpuc->per_core);
- cpuc->per_core = pc;
+ kfree(cpuc->shared_regs);
+ cpuc->shared_regs = pc;
break;
}
}
- cpuc->per_core->core_id = core_id;
- cpuc->per_core->refcnt++;
+ cpuc->shared_regs->core_id = core_id;
+ cpuc->shared_regs->refcnt++;
}
static void intel_pmu_cpu_dying(int cpu)
{
struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
- struct intel_percore *pc = cpuc->per_core;
+ struct intel_shared_regs *pc;
+ pc = cpuc->shared_regs;
if (pc) {
if (pc->core_id == -1 || --pc->refcnt == 0)
kfree(pc);
- cpuc->per_core = NULL;
+ cpuc->shared_regs = NULL;
}
fini_debug_store_on_cpu(cpu);
@@ -1436,7 +1532,6 @@ static __init int intel_pmu_init(void)
x86_pmu.event_constraints = intel_nehalem_event_constraints;
x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
- x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
x86_pmu.enable_all = intel_pmu_nhm_enable_all;
x86_pmu.extra_regs = intel_nehalem_extra_regs;
@@ -1481,10 +1576,10 @@ static __init int intel_pmu_init(void)
intel_pmu_lbr_init_nhm();
x86_pmu.event_constraints = intel_westmere_event_constraints;
- x86_pmu.percore_constraints = intel_westmere_percore_constraints;
x86_pmu.enable_all = intel_pmu_nhm_enable_all;
x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
x86_pmu.extra_regs = intel_westmere_extra_regs;
+ x86_pmu.er_flags |= ERF_HAS_RSP_1;
/* UOPS_ISSUED.STALLED_CYCLES */
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e;
@@ -1502,6 +1597,10 @@ static __init int intel_pmu_init(void)
x86_pmu.event_constraints = intel_snb_event_constraints;
x86_pmu.pebs_constraints = intel_snb_pebs_events;
+ 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;
+ x86_pmu.er_flags |= ERF_NO_HT_SHARING;
/* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e;
@@ -1512,11 +1611,19 @@ static __init int intel_pmu_init(void)
break;
default:
- /*
- * default constraints for v2 and up
- */
- x86_pmu.event_constraints = intel_gen_event_constraints;
- pr_cont("generic architected perfmon, ");
+ switch (x86_pmu.version) {
+ case 1:
+ x86_pmu.event_constraints = intel_v1_event_constraints;
+ pr_cont("generic architected perfmon v1, ");
+ break;
+ default:
+ /*
+ * default constraints for v2 and up
+ */
+ x86_pmu.event_constraints = intel_gen_event_constraints;
+ pr_cont("generic architected perfmon, ");
+ break;
+ }
}
return 0;
}
@@ -1528,4 +1635,8 @@ 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 bab491b8ee25..1b1ef3addcfd 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -340,7 +340,7 @@ static int intel_pmu_drain_bts_buffer(void)
*/
perf_prepare_sample(&header, &data, event, &regs);
- if (perf_output_begin(&handle, event, header.size * (top - at), 1, 1))
+ if (perf_output_begin(&handle, event, header.size * (top - at)))
return 1;
for (; at < top; at++) {
@@ -616,7 +616,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
else
regs.flags &= ~PERF_EFLAGS_EXACT;
- if (perf_event_overflow(event, 1, &data, &regs))
+ if (perf_event_overflow(event, &data, &regs))
x86_pmu_stop(event, 0);
}
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index ead584fb6a7d..7809d2bcb209 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -554,13 +554,102 @@ static __initconst const u64 p4_hw_cache_event_ids
[ C(RESULT_MISS) ] = -1,
},
},
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
};
+/*
+ * Because of Netburst being quite restricted in how many
+ * identical events may run simultaneously, we introduce event aliases,
+ * ie the different events which have the same functionality but
+ * utilize non-intersected resources (ESCR/CCCR/counter registers).
+ *
+ * This allow us to relax restrictions a bit and run two or more
+ * identical events together.
+ *
+ * Never set any custom internal bits such as P4_CONFIG_HT,
+ * P4_CONFIG_ALIASABLE or bits for P4_PEBS_METRIC, they are
+ * either up to date automatically or not applicable at all.
+ */
+struct p4_event_alias {
+ u64 original;
+ u64 alternative;
+} p4_event_aliases[] = {
+ {
+ /*
+ * Non-halted cycles can be substituted with non-sleeping cycles (see
+ * Intel SDM Vol3b for details). We need this alias to be able
+ * to run nmi-watchdog and 'perf top' (or any other user space tool
+ * which is interested in running PERF_COUNT_HW_CPU_CYCLES)
+ * simultaneously.
+ */
+ .original =
+ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
+ .alternative =
+ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_EXECUTION_EVENT) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)|
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)|
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)|
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)|
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3))|
+ p4_config_pack_cccr(P4_CCCR_THRESHOLD(15) | P4_CCCR_COMPLEMENT |
+ P4_CCCR_COMPARE),
+ },
+};
+
+static u64 p4_get_alias_event(u64 config)
+{
+ u64 config_match;
+ int i;
+
+ /*
+ * Only event with special mark is allowed,
+ * we're to be sure it didn't come as malformed
+ * RAW event.
+ */
+ if (!(config & P4_CONFIG_ALIASABLE))
+ return 0;
+
+ config_match = config & P4_CONFIG_EVENT_ALIAS_MASK;
+
+ for (i = 0; i < ARRAY_SIZE(p4_event_aliases); i++) {
+ if (config_match == p4_event_aliases[i].original) {
+ config_match = p4_event_aliases[i].alternative;
+ break;
+ } else if (config_match == p4_event_aliases[i].alternative) {
+ config_match = p4_event_aliases[i].original;
+ break;
+ }
+ }
+
+ if (i >= ARRAY_SIZE(p4_event_aliases))
+ return 0;
+
+ return config_match | (config & P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS);
+}
+
static u64 p4_general_events[PERF_COUNT_HW_MAX] = {
/* non-halted CPU clocks */
[PERF_COUNT_HW_CPU_CYCLES] =
p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) |
- P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
+ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)) |
+ P4_CONFIG_ALIASABLE,
/*
* retired instructions
@@ -945,7 +1034,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
if (!x86_perf_event_set_period(event))
continue;
- if (perf_event_overflow(event, 1, &data, regs))
+ if (perf_event_overflow(event, &data, regs))
x86_pmu_stop(event, 0);
}
@@ -1120,6 +1209,8 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
struct p4_event_bind *bind;
unsigned int i, thread, num;
int cntr_idx, escr_idx;
+ u64 config_alias;
+ int pass;
bitmap_zero(used_mask, X86_PMC_IDX_MAX);
bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE);
@@ -1128,6 +1219,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
hwc = &cpuc->event_list[i]->hw;
thread = p4_ht_thread(cpu);
+ pass = 0;
+
+again:
+ /*
+ * It's possible to hit a circular lock
+ * between original and alternative events
+ * if both are scheduled already.
+ */
+ if (pass > 2)
+ goto done;
+
bind = p4_config_get_bind(hwc->config);
escr_idx = p4_get_escr_idx(bind->escr_msr[thread]);
if (unlikely(escr_idx == -1))
@@ -1141,8 +1243,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
}
cntr_idx = p4_next_cntr(thread, used_mask, bind);
- if (cntr_idx == -1 || test_bit(escr_idx, escr_mask))
- goto done;
+ if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) {
+ /*
+ * Check whether an event alias is still available.
+ */
+ config_alias = p4_get_alias_event(hwc->config);
+ if (!config_alias)
+ goto done;
+ hwc->config = config_alias;
+ pass++;
+ goto again;
+ }
p4_pmu_swap_config_ts(hwc, cpu);
if (assign)
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 9aeb78a23de4..a621f3427685 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -134,6 +134,24 @@ static int __init add_bus_probe(void)
module_init(add_bus_probe);
#ifdef CONFIG_PCI
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+ struct device_node *np;
+
+ for_each_node_by_type(np, "pci") {
+ const void *prop;
+ unsigned int bus_min;
+
+ prop = of_get_property(np, "bus-range", NULL);
+ if (!prop)
+ continue;
+ bus_min = be32_to_cpup(prop);
+ if (bus->number == bus_min)
+ return np;
+ }
+ return NULL;
+}
+
static int x86_of_pci_irq_enable(struct pci_dev *dev)
{
struct of_irq oirq;
@@ -165,50 +183,8 @@ static void x86_of_pci_irq_disable(struct pci_dev *dev)
void __cpuinit x86_of_pci_init(void)
{
- struct device_node *np;
-
pcibios_enable_irq = x86_of_pci_irq_enable;
pcibios_disable_irq = x86_of_pci_irq_disable;
-
- for_each_node_by_type(np, "pci") {
- const void *prop;
- struct pci_bus *bus;
- unsigned int bus_min;
- struct device_node *child;
-
- prop = of_get_property(np, "bus-range", NULL);
- if (!prop)
- continue;
- bus_min = be32_to_cpup(prop);
-
- bus = pci_find_bus(0, bus_min);
- if (!bus) {
- printk(KERN_ERR "Can't find a node for bus %s.\n",
- np->full_name);
- continue;
- }
-
- if (bus->self)
- bus->self->dev.of_node = np;
- else
- bus->dev.of_node = np;
-
- for_each_child_of_node(np, child) {
- struct pci_dev *dev;
- u32 devfn;
-
- prop = of_get_property(child, "reg", NULL);
- if (!prop)
- continue;
-
- devfn = (be32_to_cpup(prop) >> 8) & 0xff;
- dev = pci_get_slot(bus, devfn);
- if (!dev)
- continue;
- dev->dev.of_node = child;
- pci_dev_put(dev);
- }
- }
}
#endif
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index e71c98d3c0d2..19853ad8afc5 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -105,34 +105,6 @@ in_irq_stack(unsigned long *stack, unsigned long *irq_stack,
}
/*
- * We are returning from the irq stack and go to the previous one.
- * If the previous stack is also in the irq stack, then bp in the first
- * frame of the irq stack points to the previous, interrupted one.
- * Otherwise we have another level of indirection: We first save
- * the bp of the previous stack, then we switch the stack to the irq one
- * and save a new bp that links to the previous one.
- * (See save_args())
- */
-static inline unsigned long
-fixup_bp_irq_link(unsigned long bp, unsigned long *stack,
- unsigned long *irq_stack, unsigned long *irq_stack_end)
-{
-#ifdef CONFIG_FRAME_POINTER
- struct stack_frame *frame = (struct stack_frame *)bp;
- unsigned long next;
-
- if (!in_irq_stack(stack, irq_stack, irq_stack_end)) {
- if (!probe_kernel_address(&frame->next_frame, next))
- return next;
- else
- WARN_ONCE(1, "Perf: bad frame pointer = %p in "
- "callchain\n", &frame->next_frame);
- }
-#endif
- return bp;
-}
-
-/*
* x86-64 can have up to three kernel stacks:
* process stack
* interrupt stack
@@ -155,9 +127,12 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
task = current;
if (!stack) {
- stack = &dummy;
- if (task && task != current)
+ if (regs)
+ stack = (unsigned long *)regs->sp;
+ else if (task && task != current)
stack = (unsigned long *)task->thread.sp;
+ else
+ stack = &dummy;
}
if (!bp)
@@ -205,8 +180,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
* pointer (index -1 to end) in the IRQ stack:
*/
stack = (unsigned long *) (irq_stack_end[-1]);
- bp = fixup_bp_irq_link(bp, stack, irq_stack,
- irq_stack_end);
irq_stack_end = NULL;
ops->stack(data, "EOI");
continue;
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 8a445a0c989e..e13329d800c8 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -9,6 +9,8 @@
/*
* entry.S contains the system-call and fault low-level handling routines.
*
+ * Some of this is documented in Documentation/x86/entry_64.txt
+ *
* NOTE: This code handles signal-recognition, which happens every time
* after an interrupt and after each system call.
*
@@ -297,27 +299,26 @@ ENDPROC(native_usergs_sysret64)
.endm
/* save partial stack frame */
- .pushsection .kprobes.text, "ax"
-ENTRY(save_args)
- XCPT_FRAME
+ .macro SAVE_ARGS_IRQ
cld
- /*
- * start from rbp in pt_regs and jump over
- * return address.
- */
- movq_cfi rdi, RDI+8-RBP
- movq_cfi rsi, RSI+8-RBP
- movq_cfi rdx, RDX+8-RBP
- movq_cfi rcx, RCX+8-RBP
- movq_cfi rax, RAX+8-RBP
- movq_cfi r8, R8+8-RBP
- movq_cfi r9, R9+8-RBP
- movq_cfi r10, R10+8-RBP
- movq_cfi r11, R11+8-RBP
-
- leaq -RBP+8(%rsp),%rdi /* arg1 for handler */
- movq_cfi rbp, 8 /* push %rbp */
- leaq 8(%rsp), %rbp /* mov %rsp, %ebp */
+ /* start from rbp in pt_regs and jump over */
+ movq_cfi rdi, RDI-RBP
+ movq_cfi rsi, RSI-RBP
+ movq_cfi rdx, RDX-RBP
+ movq_cfi rcx, RCX-RBP
+ movq_cfi rax, RAX-RBP
+ movq_cfi r8, R8-RBP
+ movq_cfi r9, R9-RBP
+ movq_cfi r10, R10-RBP
+ movq_cfi r11, R11-RBP
+
+ /* Save rbp so that we can unwind from get_irq_regs() */
+ movq_cfi rbp, 0
+
+ /* Save previous stack value */
+ movq %rsp, %rsi
+
+ leaq -RBP(%rsp),%rdi /* arg1 for handler */
testl $3, CS(%rdi)
je 1f
SWAPGS
@@ -329,19 +330,14 @@ ENTRY(save_args)
*/
1: incl PER_CPU_VAR(irq_count)
jne 2f
- popq_cfi %rax /* move return address... */
mov PER_CPU_VAR(irq_stack_ptr),%rsp
EMPTY_FRAME 0
- pushq_cfi %rbp /* backlink for unwinder */
- pushq_cfi %rax /* ... to the new stack */
- /*
- * We entered an interrupt context - irqs are off:
- */
-2: TRACE_IRQS_OFF
- ret
- CFI_ENDPROC
-END(save_args)
- .popsection
+
+2: /* Store previous stack value */
+ pushq %rsi
+ /* We entered an interrupt context - irqs are off: */
+ TRACE_IRQS_OFF
+ .endm
ENTRY(save_rest)
PARTIAL_FRAME 1 REST_SKIP+8
@@ -473,7 +469,7 @@ ENTRY(system_call_after_swapgs)
* and short:
*/
ENABLE_INTERRUPTS(CLBR_NONE)
- SAVE_ARGS 8,1
+ SAVE_ARGS 8,0
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
CFI_REL_OFFSET rip,RIP-ARGOFFSET
@@ -508,7 +504,7 @@ sysret_check:
TRACE_IRQS_ON
movq RIP-ARGOFFSET(%rsp),%rcx
CFI_REGISTER rip,rcx
- RESTORE_ARGS 0,-ARG_SKIP,1
+ RESTORE_ARGS 1,-ARG_SKIP,0
/*CFI_REGISTER rflags,r11*/
movq PER_CPU_VAR(old_rsp), %rsp
USERGS_SYSRET64
@@ -791,7 +787,7 @@ END(interrupt)
/* reserve pt_regs for scratch regs and rbp */
subq $ORIG_RAX-RBP, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
- call save_args
+ SAVE_ARGS_IRQ
PARTIAL_FRAME 0
call \func
.endm
@@ -814,15 +810,14 @@ ret_from_intr:
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
- leaveq
- CFI_RESTORE rbp
+ /* Restore saved previous stack */
+ popq %rsi
+ leaq 16(%rsi), %rsp
+
CFI_DEF_CFA_REGISTER rsp
- CFI_ADJUST_CFA_OFFSET -8
+ CFI_ADJUST_CFA_OFFSET -16
- /* we did not save rbx, restore only from ARGOFFSET */
- addq $8, %rsp
- CFI_ADJUST_CFA_OFFSET -8
exit_intr:
GET_THREAD_INFO(%rcx)
testl $3,CS-ARGOFFSET(%rsp)
@@ -858,7 +853,7 @@ retint_restore_args: /* return to kernel space */
*/
TRACE_IRQS_IRETQ
restore_args:
- RESTORE_ARGS 0,8,0
+ RESTORE_ARGS 1,8,1
irq_return:
INTERRUPT_RETURN
@@ -991,11 +986,6 @@ apicinterrupt THRESHOLD_APIC_VECTOR \
apicinterrupt THERMAL_APIC_VECTOR \
thermal_interrupt smp_thermal_interrupt
-#ifdef CONFIG_X86_MCE
-apicinterrupt MCE_SELF_VECTOR \
- mce_self_interrupt smp_mce_self_interrupt
-#endif
-
#ifdef CONFIG_SMP
apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
call_function_single_interrupt smp_call_function_single_interrupt
@@ -1121,6 +1111,8 @@ zeroentry spurious_interrupt_bug do_spurious_interrupt_bug
zeroentry coprocessor_error do_coprocessor_error
errorentry alignment_check do_alignment_check
zeroentry simd_coprocessor_error do_simd_coprocessor_error
+zeroentry emulate_vsyscall do_emulate_vsyscall
+
/* Reload gs selector with exception handling */
/* edi: new selector */
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 6781765b3a0d..4aecc54236a9 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -4,6 +4,7 @@
#include <linux/sysdev.h>
#include <linux/delay.h>
#include <linux/errno.h>
+#include <linux/i8253.h>
#include <linux/slab.h>
#include <linux/hpet.h>
#include <linux/init.h>
@@ -12,8 +13,8 @@
#include <linux/io.h>
#include <asm/fixmap.h>
-#include <asm/i8253.h>
#include <asm/hpet.h>
+#include <asm/time.h>
#define HPET_MASK CLOCKSOURCE_MASK(32)
@@ -71,7 +72,7 @@ static inline void hpet_set_mapping(void)
{
hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
#ifdef CONFIG_X86_64
- __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
+ __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VVAR_NOCACHE);
#endif
}
@@ -738,13 +739,6 @@ static cycle_t read_hpet(struct clocksource *cs)
return (cycle_t)hpet_readl(HPET_COUNTER);
}
-#ifdef CONFIG_X86_64
-static cycle_t __vsyscall_fn vread_hpet(void)
-{
- return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
-}
-#endif
-
static struct clocksource clocksource_hpet = {
.name = "hpet",
.rating = 250,
@@ -753,7 +747,7 @@ static struct clocksource clocksource_hpet = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
.resume = hpet_resume_counter,
#ifdef CONFIG_X86_64
- .vread = vread_hpet,
+ .archdata = { .vclock_mode = VCLOCK_HPET },
#endif
};
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 12aff2537682..739d8598f789 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -321,7 +321,7 @@ static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
return tmp;
}
-#define FPREG_ADDR(f, n) ((void *)&(f)->st_space + (n) * 16);
+#define FPREG_ADDR(f, n) ((void *)&(f)->st_space + (n) * 16)
#define FP_EXP_TAG_VALID 0
#define FP_EXP_TAG_ZERO 1
#define FP_EXP_TAG_SPECIAL 2
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index fb66dc9e36cb..f2b96de3c7c1 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -3,113 +3,24 @@
*
*/
#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/timex.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
+#include <linux/i8253.h>
-#include <asm/i8253.h>
#include <asm/hpet.h>
+#include <asm/time.h>
#include <asm/smp.h>
-DEFINE_RAW_SPINLOCK(i8253_lock);
-EXPORT_SYMBOL(i8253_lock);
-
/*
* HPET replaces the PIT, when enabled. So we need to know, which of
* the two timers is used
*/
struct clock_event_device *global_clock_event;
-/*
- * Initialize the PIT timer.
- *
- * This is also called after resume to bring the PIT into operation again.
- */
-static void init_pit_timer(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- raw_spin_lock(&i8253_lock);
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- /* binary, mode 2, LSB/MSB, ch 0 */
- outb_pit(0x34, PIT_MODE);
- outb_pit(LATCH & 0xff , PIT_CH0); /* LSB */
- outb_pit(LATCH >> 8 , PIT_CH0); /* MSB */
- break;
-
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_UNUSED:
- if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
- evt->mode == CLOCK_EVT_MODE_ONESHOT) {
- outb_pit(0x30, PIT_MODE);
- outb_pit(0, PIT_CH0);
- outb_pit(0, PIT_CH0);
- }
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* One shot setup */
- outb_pit(0x38, PIT_MODE);
- break;
-
- case CLOCK_EVT_MODE_RESUME:
- /* Nothing to do here */
- break;
- }
- raw_spin_unlock(&i8253_lock);
-}
-
-/*
- * Program the next event in oneshot mode
- *
- * Delta is given in PIT ticks
- */
-static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
-{
- raw_spin_lock(&i8253_lock);
- outb_pit(delta & 0xff , PIT_CH0); /* LSB */
- outb_pit(delta >> 8 , PIT_CH0); /* MSB */
- raw_spin_unlock(&i8253_lock);
-
- return 0;
-}
-
-/*
- * On UP the PIT can serve all of the possible timer functions. On SMP systems
- * it can be solely used for the global tick.
- *
- * The profiling and update capabilities are switched off once the local apic is
- * registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
- * !using_apic_timer decisions in do_timer_interrupt_hook()
- */
-static struct clock_event_device pit_ce = {
- .name = "pit",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_mode = init_pit_timer,
- .set_next_event = pit_next_event,
- .irq = 0,
-};
-
-/*
- * Initialize the conversion factor and the min/max deltas of the clock event
- * structure and register the clock event source with the framework.
- */
void __init setup_pit_timer(void)
{
- /*
- * Start pit with the boot cpu mask and make it global after the
- * IO_APIC has been initialized.
- */
- pit_ce.cpumask = cpumask_of(smp_processor_id());
-
- clockevents_config_and_register(&pit_ce, CLOCK_TICK_RATE, 0xF, 0x7FFF);
- global_clock_event = &pit_ce;
+ clockevent_i8253_init(true);
+ global_clock_event = &i8253_clockevent;
}
#ifndef CONFIG_X86_64
@@ -123,7 +34,7 @@ static int __init init_pit_clocksource(void)
* - when local APIC timer is active (PIT is switched off)
*/
if (num_possible_cpus() > 1 || is_hpet_enabled() ||
- pit_ce.mode != CLOCK_EVT_MODE_PERIODIC)
+ i8253_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
return 0;
return clocksource_i8253_init();
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 65b8f5c2eebf..610485223bdb 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -14,7 +14,7 @@
#include <linux/io.h>
#include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/timer.h>
#include <asm/hw_irq.h>
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index f470e4ef993e..b3300e6bacef 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -15,7 +15,7 @@
#include <linux/io.h>
#include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/timer.h>
#include <asm/hw_irq.h>
@@ -272,9 +272,6 @@ static void __init apic_intr_init(void)
#ifdef CONFIG_X86_MCE_THRESHOLD
alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
#endif
-#if defined(CONFIG_X86_MCE) && defined(CONFIG_X86_LOCAL_APIC)
- alloc_intr_gate(MCE_SELF_VECTOR, mce_self_interrupt);
-#endif
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
/* self generated IPI for local APIC timer */
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 5f9ecff328b5..00354d4919a9 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -608,7 +608,7 @@ int kgdb_arch_init(void)
return register_die_notifier(&kgdb_notifier);
}
-static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
+static void kgdb_hw_overflow_handler(struct perf_event *event,
struct perf_sample_data *data, struct pt_regs *regs)
{
struct task_struct *tsk = current;
@@ -638,7 +638,7 @@ void kgdb_arch_late(void)
for (i = 0; i < HBP_NUM; i++) {
if (breakinfo[i].pev)
continue;
- breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
+ breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL, NULL);
if (IS_ERR((void * __force)breakinfo[i].pev)) {
printk(KERN_ERR "kgdb: Could not allocate hw"
"breakpoints\nDisabling the kernel debugger\n");
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 33c07b0b122e..a9c2116001d6 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -51,6 +51,15 @@ static int parse_no_kvmapf(char *arg)
early_param("no-kvmapf", parse_no_kvmapf);
+static int steal_acc = 1;
+static int parse_no_stealacc(char *arg)
+{
+ steal_acc = 0;
+ return 0;
+}
+
+early_param("no-steal-acc", parse_no_stealacc);
+
struct kvm_para_state {
u8 mmu_queue[MMU_QUEUE_SIZE];
int mmu_queue_len;
@@ -58,6 +67,8 @@ struct kvm_para_state {
static DEFINE_PER_CPU(struct kvm_para_state, para_state);
static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
+static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
+static int has_steal_clock = 0;
static struct kvm_para_state *kvm_para_state(void)
{
@@ -441,6 +452,21 @@ static void __init paravirt_ops_setup(void)
#endif
}
+static void kvm_register_steal_time(void)
+{
+ int cpu = smp_processor_id();
+ struct kvm_steal_time *st = &per_cpu(steal_time, cpu);
+
+ if (!has_steal_clock)
+ return;
+
+ memset(st, 0, sizeof(*st));
+
+ wrmsrl(MSR_KVM_STEAL_TIME, (__pa(st) | KVM_MSR_ENABLED));
+ printk(KERN_INFO "kvm-stealtime: cpu %d, msr %lx\n",
+ cpu, __pa(st));
+}
+
void __cpuinit kvm_guest_cpu_init(void)
{
if (!kvm_para_available())
@@ -457,6 +483,9 @@ void __cpuinit kvm_guest_cpu_init(void)
printk(KERN_INFO"KVM setup async PF for cpu %d\n",
smp_processor_id());
}
+
+ if (has_steal_clock)
+ kvm_register_steal_time();
}
static void kvm_pv_disable_apf(void *unused)
@@ -483,6 +512,31 @@ static struct notifier_block kvm_pv_reboot_nb = {
.notifier_call = kvm_pv_reboot_notify,
};
+static u64 kvm_steal_clock(int cpu)
+{
+ u64 steal;
+ struct kvm_steal_time *src;
+ int version;
+
+ src = &per_cpu(steal_time, cpu);
+ do {
+ version = src->version;
+ rmb();
+ steal = src->steal;
+ rmb();
+ } while ((version & 1) || (version != src->version));
+
+ return steal;
+}
+
+void kvm_disable_steal_time(void)
+{
+ if (!has_steal_clock)
+ return;
+
+ wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
+}
+
#ifdef CONFIG_SMP
static void __init kvm_smp_prepare_boot_cpu(void)
{
@@ -500,6 +554,7 @@ static void __cpuinit kvm_guest_cpu_online(void *dummy)
static void kvm_guest_cpu_offline(void *dummy)
{
+ kvm_disable_steal_time();
kvm_pv_disable_apf(NULL);
apf_task_wake_all();
}
@@ -548,6 +603,11 @@ void __init kvm_guest_init(void)
if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF))
x86_init.irqs.trap_init = kvm_apf_trap_init;
+ if (kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+ has_steal_clock = 1;
+ pv_time_ops.steal_clock = kvm_steal_clock;
+ }
+
#ifdef CONFIG_SMP
smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
register_cpu_notifier(&kvm_cpu_notifier);
@@ -555,3 +615,15 @@ void __init kvm_guest_init(void)
kvm_guest_cpu_init();
#endif
}
+
+static __init int activate_jump_labels(void)
+{
+ if (has_steal_clock) {
+ jump_label_inc(&paravirt_steal_enabled);
+ if (steal_acc)
+ jump_label_inc(&paravirt_steal_rq_enabled);
+ }
+
+ return 0;
+}
+arch_initcall(activate_jump_labels);
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 6389a6bca11b..c1a0188e29ae 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -160,6 +160,7 @@ static void __cpuinit kvm_setup_secondary_clock(void)
static void kvm_crash_shutdown(struct pt_regs *regs)
{
native_write_msr(msr_kvm_system_time, 0, 0);
+ kvm_disable_steal_time();
native_machine_crash_shutdown(regs);
}
#endif
@@ -167,6 +168,7 @@ static void kvm_crash_shutdown(struct pt_regs *regs)
static void kvm_shutdown(void)
{
native_write_msr(msr_kvm_system_time, 0, 0);
+ kvm_disable_steal_time();
native_machine_shutdown();
}
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index c5610384ab16..591be0ee1934 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -66,8 +66,8 @@ struct microcode_amd {
unsigned int mpb[0];
};
-#define UCODE_CONTAINER_SECTION_HDR 8
-#define UCODE_CONTAINER_HEADER_SIZE 12
+#define SECTION_HDR_SIZE 8
+#define CONTAINER_HDR_SZ 12
static struct equiv_cpu_entry *equiv_cpu_table;
@@ -157,7 +157,7 @@ static int apply_microcode_amd(int cpu)
static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
- unsigned int max_size, actual_size;
+ u32 max_size, actual_size;
#define F1XH_MPB_MAX_SIZE 2048
#define F14H_MPB_MAX_SIZE 1824
@@ -175,9 +175,9 @@ static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
break;
}
- actual_size = buf[4] + (buf[5] << 8);
+ actual_size = *(u32 *)(buf + 4);
- if (actual_size > size || actual_size > max_size) {
+ if (actual_size + SECTION_HDR_SIZE > size || actual_size > max_size) {
pr_err("section size mismatch\n");
return 0;
}
@@ -191,7 +191,7 @@ get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
struct microcode_header_amd *mc = NULL;
unsigned int actual_size = 0;
- if (buf[0] != UCODE_UCODE_TYPE) {
+ if (*(u32 *)buf != UCODE_UCODE_TYPE) {
pr_err("invalid type field in container file section header\n");
goto out;
}
@@ -204,8 +204,8 @@ get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
if (!mc)
goto out;
- get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
- *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
+ get_ucode_data(mc, buf + SECTION_HDR_SIZE, actual_size);
+ *mc_size = actual_size + SECTION_HDR_SIZE;
out:
return mc;
@@ -229,9 +229,10 @@ static int install_equiv_cpu_table(const u8 *buf)
return -ENOMEM;
}
- get_ucode_data(equiv_cpu_table, buf + UCODE_CONTAINER_HEADER_SIZE, size);
+ get_ucode_data(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size);
- return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */
+ /* add header length */
+ return size + CONTAINER_HDR_SZ;
}
static void free_equiv_cpu_table(void)
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index 52f256f2cc81..925179f871de 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -45,21 +45,6 @@ void *module_alloc(unsigned long size)
-1, __builtin_return_address(0));
}
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
#ifdef CONFIG_X86_32
int apply_relocate(Elf32_Shdr *sechdrs,
const char *strtab,
@@ -100,17 +85,6 @@ int apply_relocate(Elf32_Shdr *sechdrs,
}
return 0;
}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
#else /*X86_64*/
int apply_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
@@ -181,17 +155,6 @@ overflow:
me->name);
return -ENOEXEC;
}
-
-int apply_relocate(Elf_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "non add relocation not supported\n");
- return -ENOSYS;
-}
-
#endif
int module_finalize(const Elf_Ehdr *hdr,
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 869e1aeeb71b..613a7931ecc1 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -202,6 +202,14 @@ static void native_flush_tlb_single(unsigned long addr)
__native_flush_tlb_single(addr);
}
+struct jump_label_key paravirt_steal_enabled;
+struct jump_label_key paravirt_steal_rq_enabled;
+
+static u64 native_steal_clock(int cpu)
+{
+ return 0;
+}
+
/* These are in entry.S */
extern void native_iret(void);
extern void native_irq_enable_sysexit(void);
@@ -307,6 +315,7 @@ struct pv_init_ops pv_init_ops = {
struct pv_time_ops pv_time_ops = {
.sched_clock = native_sched_clock,
+ .steal_clock = native_steal_clock,
};
struct pv_irq_ops pv_irq_ops = {
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index e8c33a302006..726494b58345 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1553,7 +1553,7 @@ static void __init calgary_fixup_one_tce_space(struct pci_dev *dev)
continue;
/* cover the whole region */
- npages = (r->end - r->start) >> PAGE_SHIFT;
+ npages = resource_size(r) >> PAGE_SHIFT;
npages++;
iommu_range_reserve(tbl, r->start, npages);
diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c
index ba0a4cce53be..63228035f9d7 100644
--- a/arch/x86/kernel/probe_roms.c
+++ b/arch/x86/kernel/probe_roms.c
@@ -234,7 +234,7 @@ void __init probe_roms(void)
/* check for extension rom (ignore length byte!) */
rom = isa_bus_to_virt(extension_rom_resource.start);
if (romsignature(rom)) {
- length = extension_rom_resource.end - extension_rom_resource.start + 1;
+ length = resource_size(&extension_rom_resource);
if (romchecksum(rom, length)) {
request_resource(&iomem_resource, &extension_rom_resource);
upper = extension_rom_resource.start;
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 807c2a2b80f1..82528799c5de 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -528,7 +528,7 @@ static int genregs_set(struct task_struct *target,
return ret;
}
-static void ptrace_triggered(struct perf_event *bp, int nmi,
+static void ptrace_triggered(struct perf_event *bp,
struct perf_sample_data *data,
struct pt_regs *regs)
{
@@ -715,7 +715,8 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,
attr.bp_type = HW_BREAKPOINT_W;
attr.disabled = 1;
- bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
+ bp = register_user_hw_breakpoint(&attr, ptrace_triggered,
+ NULL, tsk);
/*
* CHECKME: the previous code returned -EIO if the addr wasn't
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 8bbe8c56916d..b78643d0f9a5 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -10,7 +10,7 @@
static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
{
- u8 config, rev;
+ u8 config;
u16 word;
/* BIOS may enable hardware IRQ balancing for
@@ -18,8 +18,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
* based platforms.
* Disable SW irqbalance/affinity on those platforms.
*/
- pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
- if (rev > 0x9)
+ if (dev->revision > 0x9)
return;
/* enable access to config space*/
diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S
index 41235531b11c..36818f8ec2be 100644
--- a/arch/x86/kernel/relocate_kernel_32.S
+++ b/arch/x86/kernel/relocate_kernel_32.S
@@ -97,6 +97,8 @@ relocate_kernel:
ret
identity_mapped:
+ /* set return address to 0 if not preserving context */
+ pushl $0
/* store the start address on the stack */
pushl %edx
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 4de8f5b3d476..7a6f3b3be3cf 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -100,6 +100,8 @@ relocate_kernel:
ret
identity_mapped:
+ /* set return address to 0 if not preserving context */
+ pushq $0
/* store the start address on the stack */
pushq %rdx
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 40a24932a8a1..54ddaeb221c1 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -485,17 +485,18 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
asmlinkage int
sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);
current->state = TASK_INTERRUPTIBLE;
schedule();
- set_restore_sigmask();
+ set_restore_sigmask();
return -ERESTARTNOHAND;
}
@@ -572,10 +573,7 @@ unsigned long sys_sigreturn(struct pt_regs *regs)
goto badframe;
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 (restore_sigcontext(regs, &frame->sc, &ax))
goto badframe;
@@ -653,11 +651,15 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
static int
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+ struct pt_regs *regs)
{
int usig = signr_convert(sig);
+ sigset_t *set = &current->blocked;
int ret;
+ if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+ set = &current->saved_sigmask;
+
/* Set up the stack frame */
if (is_ia32) {
if (ka->sa.sa_flags & SA_SIGINFO)
@@ -672,12 +674,13 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return -EFAULT;
}
+ current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
return ret;
}
static int
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
- sigset_t *oldset, struct pt_regs *regs)
+ struct pt_regs *regs)
{
sigset_t blocked;
int ret;
@@ -712,20 +715,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
regs->flags &= ~X86_EFLAGS_TF;
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, regs);
if (ret)
return ret;
-#ifdef CONFIG_X86_64
- /*
- * This has nothing to do with segment registers,
- * despite the name. This magic affects uaccess.h
- * macros' behavior. Reset it to the normal setting.
- */
- set_fs(USER_DS);
-#endif
-
/*
* Clear the direction flag as per the ABI for function entry.
*/
@@ -767,7 +761,6 @@ static void do_signal(struct pt_regs *regs)
struct k_sigaction ka;
siginfo_t info;
int signr;
- sigset_t *oldset;
/*
* We want the common case to go fast, which is why we may in certain
@@ -779,23 +772,10 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs))
return;
- if (current_thread_info()->status & TS_RESTORE_SIGMASK)
- oldset = &current->saved_sigmask;
- else
- oldset = &current->blocked;
-
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
- /*
- * A signal was successfully delivered; the saved
- * sigmask will have been stored in the signal frame,
- * and will be restored by sigreturn, so we can simply
- * clear the TS_RESTORE_SIGMASK flag.
- */
- current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
- }
+ handle_signal(signr, &info, &ka, regs);
return;
}
@@ -823,7 +803,7 @@ static void do_signal(struct pt_regs *regs)
*/
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ set_current_blocked(&current->saved_sigmask);
}
}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 9fd3137230d4..9f548cb4a958 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -438,7 +438,7 @@ static void impress_friends(void)
void __inquire_remote_apic(int apicid)
{
unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
- char *names[] = { "ID", "VERSION", "SPIV" };
+ const char * const names[] = { "ID", "VERSION", "SPIV" };
int timeout;
u32 status;
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 55d9bc03f696..fdd0c6430e5a 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -66,7 +66,7 @@ void save_stack_trace(struct stack_trace *trace)
}
EXPORT_SYMBOL_GPL(save_stack_trace);
-void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs)
+void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
{
dump_trace(current, regs, NULL, 0, &save_stack_ops, trace);
if (trace->nr_entries < trace->max_entries)
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 30ac65df7d4e..e07a2fc876b9 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -36,6 +36,7 @@
#include <asm/bootparam.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
+#include <asm/swiotlb.h>
#include <asm/fixmap.h>
#include <asm/proto.h>
#include <asm/setup.h>
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c
index 00cbb272627f..5a64d057be57 100644
--- a/arch/x86/kernel/time.c
+++ b/arch/x86/kernel/time.c
@@ -11,13 +11,13 @@
#include <linux/clockchips.h>
#include <linux/interrupt.h>
+#include <linux/i8253.h>
#include <linux/time.h>
#include <linux/mca.h>
#include <asm/vsyscall.h>
#include <asm/x86_init.h>
#include <asm/i8259.h>
-#include <asm/i8253.h>
#include <asm/timer.h>
#include <asm/hpet.h>
#include <asm/time.h>
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index b9b67166f9de..9682ec50180c 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -49,7 +49,7 @@
#include <asm/stacktrace.h>
#include <asm/processor.h>
#include <asm/debugreg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/traps.h>
#include <asm/desc.h>
@@ -872,6 +872,12 @@ void __init trap_init(void)
set_bit(SYSCALL_VECTOR, used_vectors);
#endif
+#ifdef CONFIG_X86_64
+ BUG_ON(test_bit(VSYSCALL_EMU_VECTOR, used_vectors));
+ set_system_intr_gate(VSYSCALL_EMU_VECTOR, &emulate_vsyscall);
+ set_bit(VSYSCALL_EMU_VECTOR, used_vectors);
+#endif
+
/*
* Should be a barrier for any external CPU state:
*/
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 6cc6922262af..db483369f10b 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -5,7 +5,6 @@
#include <linux/timer.h>
#include <linux/acpi_pmtmr.h>
#include <linux/cpufreq.h>
-#include <linux/dmi.h>
#include <linux/delay.h>
#include <linux/clocksource.h>
#include <linux/percpu.h>
@@ -777,7 +776,7 @@ static struct clocksource clocksource_tsc = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
CLOCK_SOURCE_MUST_VERIFY,
#ifdef CONFIG_X86_64
- .vread = vread_tsc,
+ .archdata = { .vclock_mode = VCLOCK_TSC },
#endif
};
@@ -800,27 +799,6 @@ void mark_tsc_unstable(char *reason)
EXPORT_SYMBOL_GPL(mark_tsc_unstable);
-static int __init dmi_mark_tsc_unstable(const struct dmi_system_id *d)
-{
- printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
- d->ident);
- tsc_unstable = 1;
- return 0;
-}
-
-/* List of systems that have known TSC problems */
-static struct dmi_system_id __initdata bad_tsc_dmi_table[] = {
- {
- .callback = dmi_mark_tsc_unstable,
- .ident = "IBM Thinkpad 380XD",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
- DMI_MATCH(DMI_BOARD_NAME, "2635FA0"),
- },
- },
- {}
-};
-
static void __init check_system_tsc_reliable(void)
{
#ifdef CONFIG_MGEODE_LX
@@ -1010,8 +988,6 @@ void __init tsc_init(void)
lpj_fine = lpj;
use_tsc_delay();
- /* Check and install the TSC clocksource */
- dmi_check_system(bad_tsc_dmi_table);
if (unsynchronized_tsc())
mark_tsc_unstable("TSCs unsynchronized");
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 89aed99aafce..4aa9c54a9b76 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -161,50 +161,47 @@ SECTIONS
#define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0)
#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
-#define EMIT_VVAR(x, offset) .vsyscall_var_ ## x \
- ADDR(.vsyscall_0) + offset \
- : AT(VLOAD(.vsyscall_var_ ## x)) { \
- *(.vsyscall_var_ ## x) \
- } \
- x = VVIRT(.vsyscall_var_ ## x);
. = ALIGN(4096);
__vsyscall_0 = .;
. = VSYSCALL_ADDR;
- .vsyscall_0 : AT(VLOAD(.vsyscall_0)) {
+ .vsyscall : AT(VLOAD(.vsyscall)) {
*(.vsyscall_0)
- } :user
- . = ALIGN(L1_CACHE_BYTES);
- .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) {
- *(.vsyscall_fn)
- }
-
- .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) {
+ . = 1024;
*(.vsyscall_1)
- }
- .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) {
- *(.vsyscall_2)
- }
- .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) {
- *(.vsyscall_3)
- }
-
-#define __VVAR_KERNEL_LDS
-#include <asm/vvar.h>
-#undef __VVAR_KERNEL_LDS
+ . = 2048;
+ *(.vsyscall_2)
- . = __vsyscall_0 + PAGE_SIZE;
+ . = 4096; /* Pad the whole page. */
+ } :user =0xcc
+ . = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
#undef VSYSCALL_ADDR
#undef VLOAD_OFFSET
#undef VLOAD
#undef VVIRT_OFFSET
#undef VVIRT
+
+ __vvar_page = .;
+
+ .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) {
+
+ /* Place all vvars at the offsets in asm/vvar.h. */
+#define EMIT_VVAR(name, offset) \
+ . = offset; \
+ *(.vvar_ ## name)
+#define __VVAR_KERNEL_LDS
+#include <asm/vvar.h>
+#undef __VVAR_KERNEL_LDS
#undef EMIT_VVAR
+ } :data
+
+ . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
+
#endif /* CONFIG_X86_64 */
/* Init code and data - will be freed after init */
diff --git a/arch/x86/kernel/vread_tsc_64.c b/arch/x86/kernel/vread_tsc_64.c
deleted file mode 100644
index a81aa9e9894c..000000000000
--- a/arch/x86/kernel/vread_tsc_64.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This code runs in userspace. */
-
-#define DISABLE_BRANCH_PROFILING
-#include <asm/vgtod.h>
-
-notrace cycle_t __vsyscall_fn vread_tsc(void)
-{
- cycle_t ret;
- u64 last;
-
- /*
- * Empirically, a fence (of type that depends on the CPU)
- * before rdtsc is enough to ensure that rdtsc is ordered
- * with respect to loads. The various CPU manuals are unclear
- * as to whether rdtsc can be reordered with later loads,
- * but no one has ever seen it happen.
- */
- rdtsc_barrier();
- ret = (cycle_t)vget_cycles();
-
- last = VVAR(vsyscall_gtod_data).clock.cycle_last;
-
- if (likely(ret >= last))
- return ret;
-
- /*
- * GCC likes to generate cmov here, but this branch is extremely
- * predictable (it's just a funciton of time and the likely is
- * very likely) and there's a data dependence, so force GCC
- * to generate a branch instead. I don't barrier() because
- * we don't actually need a barrier, and if this function
- * ever gets inlined it will generate worse code.
- */
- asm volatile ("");
- return last;
-}
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 3e682184d76c..dda7dff9cef7 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -2,6 +2,8 @@
* Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
* Copyright 2003 Andi Kleen, SuSE Labs.
*
+ * [ NOTE: this mechanism is now deprecated in favor of the vDSO. ]
+ *
* Thanks to hpa@transmeta.com for some useful hint.
* Special thanks to Ingo Molnar for his early experience with
* a different vsyscall implementation for Linux/IA32 and for the name.
@@ -11,10 +13,9 @@
* vsyscalls. One vsyscall can reserve more than 1 slot to avoid
* jumping out of line if necessary. We cannot add more with this
* mechanism because older kernels won't return -ENOSYS.
- * If we want more than four we need a vDSO.
*
- * Note: the concept clashes with user mode linux. If you use UML and
- * want per guest time just set the kernel.vsyscall64 sysctl to 0.
+ * Note: the concept clashes with user mode linux. UML users should
+ * use the vDSO.
*/
/* Disable profiling for userspace code: */
@@ -32,9 +33,12 @@
#include <linux/cpu.h>
#include <linux/smp.h>
#include <linux/notifier.h>
+#include <linux/syscalls.h>
+#include <linux/ratelimit.h>
#include <asm/vsyscall.h>
#include <asm/pgtable.h>
+#include <asm/compat.h>
#include <asm/page.h>
#include <asm/unistd.h>
#include <asm/fixmap.h>
@@ -44,16 +48,12 @@
#include <asm/desc.h>
#include <asm/topology.h>
#include <asm/vgtod.h>
-
-#define __vsyscall(nr) \
- __attribute__ ((unused, __section__(".vsyscall_" #nr))) notrace
-#define __syscall_clobber "r11","cx","memory"
+#include <asm/traps.h>
DEFINE_VVAR(int, vgetcpu_mode);
DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) =
{
.lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock),
- .sysctl_enabled = 1,
};
void update_vsyscall_tz(void)
@@ -72,179 +72,149 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
unsigned long flags;
write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+
/* copy vsyscall data */
- vsyscall_gtod_data.clock.vread = clock->vread;
- vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
- vsyscall_gtod_data.clock.mask = clock->mask;
- vsyscall_gtod_data.clock.mult = mult;
- vsyscall_gtod_data.clock.shift = clock->shift;
- vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
- vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
- vsyscall_gtod_data.wall_to_monotonic = *wtm;
- vsyscall_gtod_data.wall_time_coarse = __current_kernel_time();
+ vsyscall_gtod_data.clock.vclock_mode = clock->archdata.vclock_mode;
+ vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
+ vsyscall_gtod_data.clock.mask = clock->mask;
+ vsyscall_gtod_data.clock.mult = mult;
+ vsyscall_gtod_data.clock.shift = clock->shift;
+ vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
+ vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+ vsyscall_gtod_data.wall_to_monotonic = *wtm;
+ vsyscall_gtod_data.wall_time_coarse = __current_kernel_time();
+
write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
}
-/* RED-PEN may want to readd seq locking, but then the variable should be
- * write-once.
- */
-static __always_inline void do_get_tz(struct timezone * tz)
+static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
+ const char *message)
{
- *tz = VVAR(vsyscall_gtod_data).sys_tz;
-}
+ static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
+ struct task_struct *tsk;
-static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- int ret;
- asm volatile("syscall"
- : "=a" (ret)
- : "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
- : __syscall_clobber );
- return ret;
-}
+ if (!show_unhandled_signals || !__ratelimit(&rs))
+ return;
-static __always_inline long time_syscall(long *t)
-{
- long secs;
- asm volatile("syscall"
- : "=a" (secs)
- : "0" (__NR_time),"D" (t) : __syscall_clobber);
- return secs;
-}
+ tsk = current;
-static __always_inline void do_vgettimeofday(struct timeval * tv)
-{
- cycle_t now, base, mask, cycle_delta;
- unsigned seq;
- unsigned long mult, shift, nsec;
- cycle_t (*vread)(void);
- do {
- seq = read_seqbegin(&VVAR(vsyscall_gtod_data).lock);
-
- vread = VVAR(vsyscall_gtod_data).clock.vread;
- if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled ||
- !vread)) {
- gettimeofday(tv,NULL);
- return;
- }
-
- now = vread();
- base = VVAR(vsyscall_gtod_data).clock.cycle_last;
- mask = VVAR(vsyscall_gtod_data).clock.mask;
- mult = VVAR(vsyscall_gtod_data).clock.mult;
- shift = VVAR(vsyscall_gtod_data).clock.shift;
-
- tv->tv_sec = VVAR(vsyscall_gtod_data).wall_time_sec;
- nsec = VVAR(vsyscall_gtod_data).wall_time_nsec;
- } while (read_seqretry(&VVAR(vsyscall_gtod_data).lock, seq));
-
- /* calculate interval: */
- cycle_delta = (now - base) & mask;
- /* convert to nsecs: */
- nsec += (cycle_delta * mult) >> shift;
-
- while (nsec >= NSEC_PER_SEC) {
- tv->tv_sec += 1;
- nsec -= NSEC_PER_SEC;
- }
- tv->tv_usec = nsec / NSEC_PER_USEC;
+ printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+ level, tsk->comm, task_pid_nr(tsk),
+ message, regs->ip - 2, regs->cs,
+ regs->sp, regs->ax, regs->si, regs->di);
}
-int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+static int addr_to_vsyscall_nr(unsigned long addr)
{
- if (tv)
- do_vgettimeofday(tv);
- if (tz)
- do_get_tz(tz);
- return 0;
-}
+ int nr;
-/* This will break when the xtime seconds get inaccurate, but that is
- * unlikely */
-time_t __vsyscall(1) vtime(time_t *t)
-{
- unsigned seq;
- time_t result;
- if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled))
- return time_syscall(t);
+ if ((addr & ~0xC00UL) != VSYSCALL_START)
+ return -EINVAL;
- do {
- seq = read_seqbegin(&VVAR(vsyscall_gtod_data).lock);
+ nr = (addr & 0xC00UL) >> 10;
+ if (nr >= 3)
+ return -EINVAL;
- result = VVAR(vsyscall_gtod_data).wall_time_sec;
+ return nr;
+}
- } while (read_seqretry(&VVAR(vsyscall_gtod_data).lock, seq));
+void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
+{
+ struct task_struct *tsk;
+ unsigned long caller;
+ int vsyscall_nr;
+ long ret;
+
+ local_irq_enable();
+
+ /*
+ * Real 64-bit user mode code has cs == __USER_CS. Anything else
+ * is bogus.
+ */
+ if (regs->cs != __USER_CS) {
+ /*
+ * If we trapped from kernel mode, we might as well OOPS now
+ * instead of returning to some random address and OOPSing
+ * then.
+ */
+ BUG_ON(!user_mode(regs));
+
+ /* Compat mode and non-compat 32-bit CS should both segfault. */
+ warn_bad_vsyscall(KERN_WARNING, regs,
+ "illegal int 0xcc from 32-bit mode");
+ goto sigsegv;
+ }
- if (t)
- *t = result;
- return result;
-}
+ /*
+ * x86-ism here: regs->ip points to the instruction after the int 0xcc,
+ * and int 0xcc is two bytes long.
+ */
+ vsyscall_nr = addr_to_vsyscall_nr(regs->ip - 2);
+ if (vsyscall_nr < 0) {
+ warn_bad_vsyscall(KERN_WARNING, regs,
+ "illegal int 0xcc (exploit attempt?)");
+ goto sigsegv;
+ }
-/* Fast way to get current CPU and node.
- This helps to do per node and per CPU caches in user space.
- The result is not guaranteed without CPU affinity, but usually
- works out because the scheduler tries to keep a thread on the same
- CPU.
+ if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
+ warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack (exploit attempt?)");
+ goto sigsegv;
+ }
- tcache must point to a two element sized long array.
- All arguments can be NULL. */
-long __vsyscall(2)
-vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
-{
- unsigned int p;
- unsigned long j = 0;
-
- /* Fast cache - only recompute value once per jiffies and avoid
- relatively costly rdtscp/cpuid otherwise.
- This works because the scheduler usually keeps the process
- on the same CPU and this syscall doesn't guarantee its
- results anyways.
- We do this here because otherwise user space would do it on
- its own in a likely inferior way (no access to jiffies).
- If you don't like it pass NULL. */
- if (tcache && tcache->blob[0] == (j = VVAR(jiffies))) {
- p = tcache->blob[1];
- } else if (VVAR(vgetcpu_mode) == VGETCPU_RDTSCP) {
- /* Load per CPU data from RDTSCP */
- native_read_tscp(&p);
- } else {
- /* Load per CPU data from GDT */
- asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+ tsk = current;
+ if (seccomp_mode(&tsk->seccomp))
+ do_exit(SIGKILL);
+
+ switch (vsyscall_nr) {
+ case 0:
+ ret = sys_gettimeofday(
+ (struct timeval __user *)regs->di,
+ (struct timezone __user *)regs->si);
+ break;
+
+ case 1:
+ ret = sys_time((time_t __user *)regs->di);
+ break;
+
+ case 2:
+ ret = sys_getcpu((unsigned __user *)regs->di,
+ (unsigned __user *)regs->si,
+ 0);
+ break;
}
- if (tcache) {
- tcache->blob[0] = j;
- tcache->blob[1] = p;
+
+ if (ret == -EFAULT) {
+ /*
+ * Bad news -- userspace fed a bad pointer to a vsyscall.
+ *
+ * With a real vsyscall, that would have caused SIGSEGV.
+ * To make writing reliable exploits using the emulated
+ * vsyscalls harder, generate SIGSEGV here as well.
+ */
+ warn_bad_vsyscall(KERN_INFO, regs,
+ "vsyscall fault (exploit attempt?)");
+ goto sigsegv;
}
- if (cpu)
- *cpu = p & 0xfff;
- if (node)
- *node = p >> 12;
- return 0;
-}
-static long __vsyscall(3) venosys_1(void)
-{
- return -ENOSYS;
-}
+ regs->ax = ret;
-#ifdef CONFIG_SYSCTL
-static ctl_table kernel_table2[] = {
- { .procname = "vsyscall64",
- .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec },
- {}
-};
+ /* Emulate a ret instruction. */
+ regs->ip = caller;
+ regs->sp += 8;
-static ctl_table kernel_root_table2[] = {
- { .procname = "kernel", .mode = 0555,
- .child = kernel_table2 },
- {}
-};
-#endif
+ local_irq_disable();
+ return;
+
+sigsegv:
+ regs->ip -= 2; /* The faulting instruction should be the int 0xcc. */
+ force_sig(SIGSEGV, current);
+ local_irq_disable();
+}
-/* Assume __initcall executes before all user space. Hopefully kmod
- doesn't violate that. We'll find out if it does. */
+/*
+ * Assume __initcall executes before all user space. Hopefully kmod
+ * doesn't violate that. We'll find out if it does.
+ */
static void __cpuinit vsyscall_set_cpu(int cpu)
{
unsigned long d;
@@ -255,13 +225,15 @@ static void __cpuinit vsyscall_set_cpu(int cpu)
if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
write_rdtscp_aux((node << 12) | cpu);
- /* Store cpu number in limit so that it can be loaded quickly
- in user space in vgetcpu.
- 12 bits for the CPU and 8 bits for the node. */
+ /*
+ * Store cpu number in limit so that it can be loaded quickly
+ * in user space in vgetcpu. (12 bits for the CPU and 8 bits for the node)
+ */
d = 0x0f40000000000ULL;
d |= cpu;
d |= (node & 0xf) << 12;
d |= (node >> 4) << 48;
+
write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S);
}
@@ -275,8 +247,10 @@ static int __cpuinit
cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
{
long cpu = (long)arg;
+
if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 1);
+
return NOTIFY_DONE;
}
@@ -284,25 +258,23 @@ void __init map_vsyscall(void)
{
extern char __vsyscall_0;
unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
+ extern char __vvar_page;
+ unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
/* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
+ __set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR);
+ BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) != (unsigned long)VVAR_ADDRESS);
}
static int __init vsyscall_init(void)
{
- BUG_ON(((unsigned long) &vgettimeofday !=
- VSYSCALL_ADDR(__NR_vgettimeofday)));
- BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
- BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
- BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
-#ifdef CONFIG_SYSCTL
- register_sysctl_table(kernel_root_table2);
-#endif
+ BUG_ON(VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE));
+
on_each_cpu(cpu_vsyscall_init, NULL, 1);
/* notifier priority > KVM */
hotcpu_notifier(cpu_vsyscall_notifier, 30);
+
return 0;
}
-
__initcall(vsyscall_init);
diff --git a/arch/x86/kernel/vsyscall_emu_64.S b/arch/x86/kernel/vsyscall_emu_64.S
new file mode 100644
index 000000000000..ffa845eae5ca
--- /dev/null
+++ b/arch/x86/kernel/vsyscall_emu_64.S
@@ -0,0 +1,27 @@
+/*
+ * vsyscall_emu_64.S: Vsyscall emulation page
+ *
+ * Copyright (c) 2011 Andy Lutomirski
+ *
+ * Subject to the GNU General Public License, version 2
+ */
+
+#include <linux/linkage.h>
+#include <asm/irq_vectors.h>
+
+/* The unused parts of the page are filled with 0xcc by the linker script. */
+
+.section .vsyscall_0, "a"
+ENTRY(vsyscall_0)
+ int $VSYSCALL_EMU_VECTOR
+END(vsyscall_0)
+
+.section .vsyscall_1, "a"
+ENTRY(vsyscall_1)
+ int $VSYSCALL_EMU_VECTOR
+END(vsyscall_1)
+
+.section .vsyscall_2, "a"
+ENTRY(vsyscall_2)
+ int $VSYSCALL_EMU_VECTOR
+END(vsyscall_2)
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 50f63648ce1b..988724b236b6 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -31,6 +31,7 @@ config KVM
select KVM_ASYNC_PF
select USER_RETURN_NOTIFIER
select KVM_MMIO
+ select TASK_DELAY_ACCT
---help---
Support hosting fully virtualized guest machines using hardware
virtualization extensions. You will need a fairly recent
@@ -76,6 +77,5 @@ config KVM_MMU_AUDIT
# the virtualization menu.
source drivers/vhost/Kconfig
source drivers/lguest/Kconfig
-source drivers/virtio/Kconfig
endif # VIRTUALIZATION
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index adc98675cda0..6f08bc940fa8 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -407,76 +407,59 @@ struct gprefix {
} \
} while (0)
-/* Fetch next part of the instruction being emulated. */
-#define insn_fetch(_type, _size, _eip) \
-({ unsigned long _x; \
- rc = do_insn_fetch(ctxt, ops, (_eip), &_x, (_size)); \
- if (rc != X86EMUL_CONTINUE) \
- goto done; \
- (_eip) += (_size); \
- (_type)_x; \
-})
-
-#define insn_fetch_arr(_arr, _size, _eip) \
-({ rc = do_insn_fetch(ctxt, ops, (_eip), _arr, (_size)); \
- if (rc != X86EMUL_CONTINUE) \
- goto done; \
- (_eip) += (_size); \
-})
-
static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
enum x86_intercept intercept,
enum x86_intercept_stage stage)
{
struct x86_instruction_info info = {
.intercept = intercept,
- .rep_prefix = ctxt->decode.rep_prefix,
- .modrm_mod = ctxt->decode.modrm_mod,
- .modrm_reg = ctxt->decode.modrm_reg,
- .modrm_rm = ctxt->decode.modrm_rm,
- .src_val = ctxt->decode.src.val64,
- .src_bytes = ctxt->decode.src.bytes,
- .dst_bytes = ctxt->decode.dst.bytes,
- .ad_bytes = ctxt->decode.ad_bytes,
+ .rep_prefix = ctxt->rep_prefix,
+ .modrm_mod = ctxt->modrm_mod,
+ .modrm_reg = ctxt->modrm_reg,
+ .modrm_rm = ctxt->modrm_rm,
+ .src_val = ctxt->src.val64,
+ .src_bytes = ctxt->src.bytes,
+ .dst_bytes = ctxt->dst.bytes,
+ .ad_bytes = ctxt->ad_bytes,
.next_rip = ctxt->eip,
};
return ctxt->ops->intercept(ctxt, &info, stage);
}
-static inline unsigned long ad_mask(struct decode_cache *c)
+static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt)
{
- return (1UL << (c->ad_bytes << 3)) - 1;
+ return (1UL << (ctxt->ad_bytes << 3)) - 1;
}
/* Access/update address held in a register, based on addressing mode. */
static inline unsigned long
-address_mask(struct decode_cache *c, unsigned long reg)
+address_mask(struct x86_emulate_ctxt *ctxt, unsigned long reg)
{
- if (c->ad_bytes == sizeof(unsigned long))
+ if (ctxt->ad_bytes == sizeof(unsigned long))
return reg;
else
- return reg & ad_mask(c);
+ return reg & ad_mask(ctxt);
}
static inline unsigned long
-register_address(struct decode_cache *c, unsigned long reg)
+register_address(struct x86_emulate_ctxt *ctxt, unsigned long reg)
{
- return address_mask(c, reg);
+ return address_mask(ctxt, reg);
}
static inline void
-register_address_increment(struct decode_cache *c, unsigned long *reg, int inc)
+register_address_increment(struct x86_emulate_ctxt *ctxt, unsigned long *reg, int inc)
{
- if (c->ad_bytes == sizeof(unsigned long))
+ if (ctxt->ad_bytes == sizeof(unsigned long))
*reg += inc;
else
- *reg = (*reg & ~ad_mask(c)) | ((*reg + inc) & ad_mask(c));
+ *reg = (*reg & ~ad_mask(ctxt)) | ((*reg + inc) & ad_mask(ctxt));
}
-static inline void jmp_rel(struct decode_cache *c, int rel)
+static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
{
- register_address_increment(c, &c->eip, rel);
+ register_address_increment(ctxt, &ctxt->_eip, rel);
}
static u32 desc_limit_scaled(struct desc_struct *desc)
@@ -486,28 +469,26 @@ static u32 desc_limit_scaled(struct desc_struct *desc)
return desc->g ? (limit << 12) | 0xfff : limit;
}
-static void set_seg_override(struct decode_cache *c, int seg)
+static void set_seg_override(struct x86_emulate_ctxt *ctxt, int seg)
{
- c->has_seg_override = true;
- c->seg_override = seg;
+ ctxt->has_seg_override = true;
+ ctxt->seg_override = seg;
}
-static unsigned long seg_base(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, int seg)
+static unsigned long seg_base(struct x86_emulate_ctxt *ctxt, int seg)
{
if (ctxt->mode == X86EMUL_MODE_PROT64 && seg < VCPU_SREG_FS)
return 0;
- return ops->get_cached_segment_base(ctxt, seg);
+ return ctxt->ops->get_cached_segment_base(ctxt, seg);
}
-static unsigned seg_override(struct x86_emulate_ctxt *ctxt,
- struct decode_cache *c)
+static unsigned seg_override(struct x86_emulate_ctxt *ctxt)
{
- if (!c->has_seg_override)
+ if (!ctxt->has_seg_override)
return 0;
- return c->seg_override;
+ return ctxt->seg_override;
}
static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
@@ -579,7 +560,6 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
unsigned size, bool write, bool fetch,
ulong *linear)
{
- struct decode_cache *c = &ctxt->decode;
struct desc_struct desc;
bool usable;
ulong la;
@@ -587,7 +567,7 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
u16 sel;
unsigned cpl, rpl;
- la = seg_base(ctxt, ctxt->ops, addr.seg) + addr.ea;
+ la = seg_base(ctxt, addr.seg) + addr.ea;
switch (ctxt->mode) {
case X86EMUL_MODE_REAL:
break;
@@ -637,7 +617,7 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
}
break;
}
- if (fetch ? ctxt->mode != X86EMUL_MODE_PROT64 : c->ad_bytes != 8)
+ if (fetch ? ctxt->mode != X86EMUL_MODE_PROT64 : ctxt->ad_bytes != 8)
la &= (u32)-1;
*linear = la;
return X86EMUL_CONTINUE;
@@ -671,11 +651,10 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
}
-static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
+static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt,
unsigned long eip, u8 *dest)
{
- struct fetch_cache *fc = &ctxt->decode.fetch;
+ struct fetch_cache *fc = &ctxt->fetch;
int rc;
int size, cur_size;
@@ -687,8 +666,8 @@ static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
rc = __linearize(ctxt, addr, size, false, true, &linear);
if (rc != X86EMUL_CONTINUE)
return rc;
- rc = ops->fetch(ctxt, linear, fc->data + cur_size,
- size, &ctxt->exception);
+ rc = ctxt->ops->fetch(ctxt, linear, fc->data + cur_size,
+ size, &ctxt->exception);
if (rc != X86EMUL_CONTINUE)
return rc;
fc->end += size;
@@ -698,7 +677,6 @@ static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
}
static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
unsigned long eip, void *dest, unsigned size)
{
int rc;
@@ -707,13 +685,30 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
if (eip + size - ctxt->eip > 15)
return X86EMUL_UNHANDLEABLE;
while (size--) {
- rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++);
+ rc = do_insn_fetch_byte(ctxt, eip++, dest++);
if (rc != X86EMUL_CONTINUE)
return rc;
}
return X86EMUL_CONTINUE;
}
+/* Fetch next part of the instruction being emulated. */
+#define insn_fetch(_type, _size, _eip) \
+({ unsigned long _x; \
+ rc = do_insn_fetch(ctxt, (_eip), &_x, (_size)); \
+ 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)); \
+ if (rc != X86EMUL_CONTINUE) \
+ goto done; \
+ (_eip) += (_size); \
+})
+
/*
* Given the 'reg' portion of a ModRM byte, and a register block, return a
* pointer into the block that addresses the relevant register.
@@ -857,16 +852,15 @@ static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data,
static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
struct operand *op,
- struct decode_cache *c,
int inhibit_bytereg)
{
- unsigned reg = c->modrm_reg;
- int highbyte_regs = c->rex_prefix == 0;
+ unsigned reg = ctxt->modrm_reg;
+ int highbyte_regs = ctxt->rex_prefix == 0;
- if (!(c->d & ModRM))
- reg = (c->b & 7) | ((c->rex_prefix & 1) << 3);
+ if (!(ctxt->d & ModRM))
+ reg = (ctxt->b & 7) | ((ctxt->rex_prefix & 1) << 3);
- if (c->d & Sse) {
+ if (ctxt->d & Sse) {
op->type = OP_XMM;
op->bytes = 16;
op->addr.xmm = reg;
@@ -875,49 +869,47 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
}
op->type = OP_REG;
- if ((c->d & ByteOp) && !inhibit_bytereg) {
- op->addr.reg = decode_register(reg, c->regs, highbyte_regs);
+ if ((ctxt->d & ByteOp) && !inhibit_bytereg) {
+ op->addr.reg = decode_register(reg, ctxt->regs, highbyte_regs);
op->bytes = 1;
} else {
- op->addr.reg = decode_register(reg, c->regs, 0);
- op->bytes = c->op_bytes;
+ op->addr.reg = decode_register(reg, ctxt->regs, 0);
+ op->bytes = ctxt->op_bytes;
}
fetch_register_operand(op);
op->orig_val = op->val;
}
static int decode_modrm(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
struct operand *op)
{
- struct decode_cache *c = &ctxt->decode;
u8 sib;
int index_reg = 0, base_reg = 0, scale;
int rc = X86EMUL_CONTINUE;
ulong modrm_ea = 0;
- if (c->rex_prefix) {
- c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */
- index_reg = (c->rex_prefix & 2) << 2; /* REX.X */
- c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */
+ if (ctxt->rex_prefix) {
+ ctxt->modrm_reg = (ctxt->rex_prefix & 4) << 1; /* REX.R */
+ index_reg = (ctxt->rex_prefix & 2) << 2; /* REX.X */
+ ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
}
- c->modrm = insn_fetch(u8, 1, c->eip);
- c->modrm_mod |= (c->modrm & 0xc0) >> 6;
- c->modrm_reg |= (c->modrm & 0x38) >> 3;
- c->modrm_rm |= (c->modrm & 0x07);
- c->modrm_seg = VCPU_SREG_DS;
+ ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+ ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
+ ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
+ ctxt->modrm_rm |= (ctxt->modrm & 0x07);
+ ctxt->modrm_seg = VCPU_SREG_DS;
- if (c->modrm_mod == 3) {
+ if (ctxt->modrm_mod == 3) {
op->type = OP_REG;
- op->bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
- op->addr.reg = decode_register(c->modrm_rm,
- c->regs, c->d & ByteOp);
- if (c->d & Sse) {
+ op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+ op->addr.reg = decode_register(ctxt->modrm_rm,
+ ctxt->regs, ctxt->d & ByteOp);
+ if (ctxt->d & Sse) {
op->type = OP_XMM;
op->bytes = 16;
- op->addr.xmm = c->modrm_rm;
- read_sse_reg(ctxt, &op->vec_val, c->modrm_rm);
+ op->addr.xmm = ctxt->modrm_rm;
+ read_sse_reg(ctxt, &op->vec_val, ctxt->modrm_rm);
return rc;
}
fetch_register_operand(op);
@@ -926,26 +918,26 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
op->type = OP_MEM;
- if (c->ad_bytes == 2) {
- unsigned bx = c->regs[VCPU_REGS_RBX];
- unsigned bp = c->regs[VCPU_REGS_RBP];
- unsigned si = c->regs[VCPU_REGS_RSI];
- unsigned di = c->regs[VCPU_REGS_RDI];
+ if (ctxt->ad_bytes == 2) {
+ unsigned bx = ctxt->regs[VCPU_REGS_RBX];
+ unsigned bp = ctxt->regs[VCPU_REGS_RBP];
+ unsigned si = ctxt->regs[VCPU_REGS_RSI];
+ unsigned di = ctxt->regs[VCPU_REGS_RDI];
/* 16-bit ModR/M decode. */
- switch (c->modrm_mod) {
+ switch (ctxt->modrm_mod) {
case 0:
- if (c->modrm_rm == 6)
- modrm_ea += insn_fetch(u16, 2, c->eip);
+ if (ctxt->modrm_rm == 6)
+ modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
break;
case 1:
- modrm_ea += insn_fetch(s8, 1, c->eip);
+ modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
break;
case 2:
- modrm_ea += insn_fetch(u16, 2, c->eip);
+ modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
break;
}
- switch (c->modrm_rm) {
+ switch (ctxt->modrm_rm) {
case 0:
modrm_ea += bx + si;
break;
@@ -965,46 +957,46 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
modrm_ea += di;
break;
case 6:
- if (c->modrm_mod != 0)
+ if (ctxt->modrm_mod != 0)
modrm_ea += bp;
break;
case 7:
modrm_ea += bx;
break;
}
- if (c->modrm_rm == 2 || c->modrm_rm == 3 ||
- (c->modrm_rm == 6 && c->modrm_mod != 0))
- c->modrm_seg = VCPU_SREG_SS;
+ if (ctxt->modrm_rm == 2 || ctxt->modrm_rm == 3 ||
+ (ctxt->modrm_rm == 6 && ctxt->modrm_mod != 0))
+ ctxt->modrm_seg = VCPU_SREG_SS;
modrm_ea = (u16)modrm_ea;
} else {
/* 32/64-bit ModR/M decode. */
- if ((c->modrm_rm & 7) == 4) {
- sib = insn_fetch(u8, 1, c->eip);
+ if ((ctxt->modrm_rm & 7) == 4) {
+ sib = insn_fetch(u8, 1, ctxt->_eip);
index_reg |= (sib >> 3) & 7;
base_reg |= sib & 7;
scale = sib >> 6;
- if ((base_reg & 7) == 5 && c->modrm_mod == 0)
- modrm_ea += insn_fetch(s32, 4, c->eip);
+ if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
+ modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
else
- modrm_ea += c->regs[base_reg];
+ modrm_ea += ctxt->regs[base_reg];
if (index_reg != 4)
- modrm_ea += c->regs[index_reg] << scale;
- } else if ((c->modrm_rm & 7) == 5 && c->modrm_mod == 0) {
+ modrm_ea += ctxt->regs[index_reg] << scale;
+ } else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
if (ctxt->mode == X86EMUL_MODE_PROT64)
- c->rip_relative = 1;
+ ctxt->rip_relative = 1;
} else
- modrm_ea += c->regs[c->modrm_rm];
- switch (c->modrm_mod) {
+ modrm_ea += ctxt->regs[ctxt->modrm_rm];
+ switch (ctxt->modrm_mod) {
case 0:
- if (c->modrm_rm == 5)
- modrm_ea += insn_fetch(s32, 4, c->eip);
+ if (ctxt->modrm_rm == 5)
+ modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
break;
case 1:
- modrm_ea += insn_fetch(s8, 1, c->eip);
+ modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
break;
case 2:
- modrm_ea += insn_fetch(s32, 4, c->eip);
+ modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
break;
}
}
@@ -1014,53 +1006,50 @@ done:
}
static int decode_abs(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
struct operand *op)
{
- struct decode_cache *c = &ctxt->decode;
int rc = X86EMUL_CONTINUE;
op->type = OP_MEM;
- switch (c->ad_bytes) {
+ switch (ctxt->ad_bytes) {
case 2:
- op->addr.mem.ea = insn_fetch(u16, 2, c->eip);
+ op->addr.mem.ea = insn_fetch(u16, 2, ctxt->_eip);
break;
case 4:
- op->addr.mem.ea = insn_fetch(u32, 4, c->eip);
+ op->addr.mem.ea = insn_fetch(u32, 4, ctxt->_eip);
break;
case 8:
- op->addr.mem.ea = insn_fetch(u64, 8, c->eip);
+ op->addr.mem.ea = insn_fetch(u64, 8, ctxt->_eip);
break;
}
done:
return rc;
}
-static void fetch_bit_operand(struct decode_cache *c)
+static void fetch_bit_operand(struct x86_emulate_ctxt *ctxt)
{
long sv = 0, mask;
- if (c->dst.type == OP_MEM && c->src.type == OP_REG) {
- mask = ~(c->dst.bytes * 8 - 1);
+ if (ctxt->dst.type == OP_MEM && ctxt->src.type == OP_REG) {
+ mask = ~(ctxt->dst.bytes * 8 - 1);
- if (c->src.bytes == 2)
- sv = (s16)c->src.val & (s16)mask;
- else if (c->src.bytes == 4)
- sv = (s32)c->src.val & (s32)mask;
+ if (ctxt->src.bytes == 2)
+ sv = (s16)ctxt->src.val & (s16)mask;
+ else if (ctxt->src.bytes == 4)
+ sv = (s32)ctxt->src.val & (s32)mask;
- c->dst.addr.mem.ea += (sv >> 3);
+ ctxt->dst.addr.mem.ea += (sv >> 3);
}
/* only subword offset */
- c->src.val &= (c->dst.bytes << 3) - 1;
+ ctxt->src.val &= (ctxt->dst.bytes << 3) - 1;
}
static int read_emulated(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
unsigned long addr, void *dest, unsigned size)
{
int rc;
- struct read_cache *mc = &ctxt->decode.mem_read;
+ struct read_cache *mc = &ctxt->mem_read;
while (size) {
int n = min(size, 8u);
@@ -1068,8 +1057,8 @@ static int read_emulated(struct x86_emulate_ctxt *ctxt,
if (mc->pos < mc->end)
goto read_cached;
- rc = ops->read_emulated(ctxt, addr, mc->data + mc->end, n,
- &ctxt->exception);
+ rc = ctxt->ops->read_emulated(ctxt, addr, mc->data + mc->end, n,
+ &ctxt->exception);
if (rc != X86EMUL_CONTINUE)
return rc;
mc->end += n;
@@ -1094,7 +1083,7 @@ static int segmented_read(struct x86_emulate_ctxt *ctxt,
rc = linearize(ctxt, addr, size, false, &linear);
if (rc != X86EMUL_CONTINUE)
return rc;
- return read_emulated(ctxt, ctxt->ops, linear, data, size);
+ return read_emulated(ctxt, linear, data, size);
}
static int segmented_write(struct x86_emulate_ctxt *ctxt,
@@ -1128,26 +1117,24 @@ static int segmented_cmpxchg(struct x86_emulate_ctxt *ctxt,
}
static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
unsigned int size, unsigned short port,
void *dest)
{
- struct read_cache *rc = &ctxt->decode.io_read;
+ struct read_cache *rc = &ctxt->io_read;
if (rc->pos == rc->end) { /* refill pio read ahead */
- struct decode_cache *c = &ctxt->decode;
unsigned int in_page, n;
- unsigned int count = c->rep_prefix ?
- address_mask(c, c->regs[VCPU_REGS_RCX]) : 1;
+ unsigned int count = ctxt->rep_prefix ?
+ address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) : 1;
in_page = (ctxt->eflags & EFLG_DF) ?
- offset_in_page(c->regs[VCPU_REGS_RDI]) :
- PAGE_SIZE - offset_in_page(c->regs[VCPU_REGS_RDI]);
+ offset_in_page(ctxt->regs[VCPU_REGS_RDI]) :
+ PAGE_SIZE - offset_in_page(ctxt->regs[VCPU_REGS_RDI]);
n = min(min(in_page, (unsigned int)sizeof(rc->data)) / size,
count);
if (n == 0)
n = 1;
rc->pos = rc->end = 0;
- if (!ops->pio_in_emulated(ctxt, size, port, rc->data, n))
+ if (!ctxt->ops->pio_in_emulated(ctxt, size, port, rc->data, n))
return 0;
rc->end = n * size;
}
@@ -1158,9 +1145,10 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
}
static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 selector, struct desc_ptr *dt)
{
+ struct x86_emulate_ops *ops = ctxt->ops;
+
if (selector & 1 << 2) {
struct desc_struct desc;
u16 sel;
@@ -1177,48 +1165,42 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
/* allowed just for 8 bytes segments */
static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 selector, struct desc_struct *desc)
{
struct desc_ptr dt;
u16 index = selector >> 3;
- int ret;
ulong addr;
- get_descriptor_table_ptr(ctxt, ops, selector, &dt);
+ get_descriptor_table_ptr(ctxt, selector, &dt);
if (dt.size < index * 8 + 7)
return emulate_gp(ctxt, selector & 0xfffc);
- addr = dt.address + index * 8;
- ret = ops->read_std(ctxt, addr, desc, sizeof *desc, &ctxt->exception);
- return ret;
+ addr = dt.address + index * 8;
+ return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc,
+ &ctxt->exception);
}
/* allowed just for 8 bytes segments */
static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 selector, struct desc_struct *desc)
{
struct desc_ptr dt;
u16 index = selector >> 3;
ulong addr;
- int ret;
- get_descriptor_table_ptr(ctxt, ops, selector, &dt);
+ get_descriptor_table_ptr(ctxt, selector, &dt);
if (dt.size < index * 8 + 7)
return emulate_gp(ctxt, selector & 0xfffc);
addr = dt.address + index * 8;
- ret = ops->write_std(ctxt, addr, desc, sizeof *desc, &ctxt->exception);
-
- return ret;
+ return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc,
+ &ctxt->exception);
}
/* Does not support long mode */
static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 selector, int seg)
{
struct desc_struct seg_desc;
@@ -1253,7 +1235,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
if (null_selector) /* for NULL selector skip all following checks */
goto load;
- ret = read_segment_descriptor(ctxt, ops, selector, &seg_desc);
+ ret = read_segment_descriptor(ctxt, selector, &seg_desc);
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -1271,7 +1253,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
rpl = selector & 3;
dpl = seg_desc.dpl;
- cpl = ops->cpl(ctxt);
+ cpl = ctxt->ops->cpl(ctxt);
switch (seg) {
case VCPU_SREG_SS:
@@ -1322,12 +1304,12 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
if (seg_desc.s) {
/* mark segment as accessed */
seg_desc.type |= 1;
- ret = write_segment_descriptor(ctxt, ops, selector, &seg_desc);
+ ret = write_segment_descriptor(ctxt, selector, &seg_desc);
if (ret != X86EMUL_CONTINUE)
return ret;
}
load:
- ops->set_segment(ctxt, selector, &seg_desc, 0, seg);
+ ctxt->ops->set_segment(ctxt, selector, &seg_desc, 0, seg);
return X86EMUL_CONTINUE;
exception:
emulate_exception(ctxt, err_vec, err_code, true);
@@ -1356,29 +1338,28 @@ static void write_register_operand(struct operand *op)
static int writeback(struct x86_emulate_ctxt *ctxt)
{
int rc;
- struct decode_cache *c = &ctxt->decode;
- switch (c->dst.type) {
+ switch (ctxt->dst.type) {
case OP_REG:
- write_register_operand(&c->dst);
+ write_register_operand(&ctxt->dst);
break;
case OP_MEM:
- if (c->lock_prefix)
+ if (ctxt->lock_prefix)
rc = segmented_cmpxchg(ctxt,
- c->dst.addr.mem,
- &c->dst.orig_val,
- &c->dst.val,
- c->dst.bytes);
+ ctxt->dst.addr.mem,
+ &ctxt->dst.orig_val,
+ &ctxt->dst.val,
+ ctxt->dst.bytes);
else
rc = segmented_write(ctxt,
- c->dst.addr.mem,
- &c->dst.val,
- c->dst.bytes);
+ ctxt->dst.addr.mem,
+ &ctxt->dst.val,
+ ctxt->dst.bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
break;
case OP_XMM:
- write_sse_reg(ctxt, &c->dst.vec_val, c->dst.addr.xmm);
+ write_sse_reg(ctxt, &ctxt->dst.vec_val, ctxt->dst.addr.xmm);
break;
case OP_NONE:
/* no writeback */
@@ -1391,50 +1372,45 @@ static int writeback(struct x86_emulate_ctxt *ctxt)
static int em_push(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
struct segmented_address addr;
- register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes);
- addr.ea = register_address(c, c->regs[VCPU_REGS_RSP]);
+ register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], -ctxt->op_bytes);
+ addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
addr.seg = VCPU_SREG_SS;
/* Disable writeback. */
- c->dst.type = OP_NONE;
- return segmented_write(ctxt, addr, &c->src.val, c->op_bytes);
+ ctxt->dst.type = OP_NONE;
+ return segmented_write(ctxt, addr, &ctxt->src.val, ctxt->op_bytes);
}
static int emulate_pop(struct x86_emulate_ctxt *ctxt,
void *dest, int len)
{
- struct decode_cache *c = &ctxt->decode;
int rc;
struct segmented_address addr;
- addr.ea = register_address(c, c->regs[VCPU_REGS_RSP]);
+ addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
addr.seg = VCPU_SREG_SS;
rc = segmented_read(ctxt, addr, dest, len);
if (rc != X86EMUL_CONTINUE)
return rc;
- register_address_increment(c, &c->regs[VCPU_REGS_RSP], len);
+ register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], len);
return rc;
}
static int em_pop(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- return emulate_pop(ctxt, &c->dst.val, c->op_bytes);
+ return emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
}
static int emulate_popf(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
- void *dest, int len)
+ void *dest, int len)
{
int rc;
unsigned long val, change_mask;
int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
- int cpl = ops->cpl(ctxt);
+ int cpl = ctxt->ops->cpl(ctxt);
rc = emulate_pop(ctxt, &val, len);
if (rc != X86EMUL_CONTINUE)
@@ -1470,49 +1446,41 @@ static int emulate_popf(struct x86_emulate_ctxt *ctxt,
static int em_popf(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- c->dst.type = OP_REG;
- c->dst.addr.reg = &ctxt->eflags;
- c->dst.bytes = c->op_bytes;
- return emulate_popf(ctxt, ctxt->ops, &c->dst.val, c->op_bytes);
+ ctxt->dst.type = OP_REG;
+ ctxt->dst.addr.reg = &ctxt->eflags;
+ ctxt->dst.bytes = ctxt->op_bytes;
+ return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
}
-static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, int seg)
+static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt, int seg)
{
- struct decode_cache *c = &ctxt->decode;
-
- c->src.val = get_segment_selector(ctxt, seg);
+ ctxt->src.val = get_segment_selector(ctxt, seg);
return em_push(ctxt);
}
-static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, int seg)
+static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, int seg)
{
- struct decode_cache *c = &ctxt->decode;
unsigned long selector;
int rc;
- rc = emulate_pop(ctxt, &selector, c->op_bytes);
+ rc = emulate_pop(ctxt, &selector, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- rc = load_segment_descriptor(ctxt, ops, (u16)selector, seg);
+ rc = load_segment_descriptor(ctxt, (u16)selector, seg);
return rc;
}
static int em_pusha(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- unsigned long old_esp = c->regs[VCPU_REGS_RSP];
+ unsigned long old_esp = ctxt->regs[VCPU_REGS_RSP];
int rc = X86EMUL_CONTINUE;
int reg = VCPU_REGS_RAX;
while (reg <= VCPU_REGS_RDI) {
(reg == VCPU_REGS_RSP) ?
- (c->src.val = old_esp) : (c->src.val = c->regs[reg]);
+ (ctxt->src.val = old_esp) : (ctxt->src.val = ctxt->regs[reg]);
rc = em_push(ctxt);
if (rc != X86EMUL_CONTINUE)
@@ -1526,26 +1494,23 @@ static int em_pusha(struct x86_emulate_ctxt *ctxt)
static int em_pushf(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- c->src.val = (unsigned long)ctxt->eflags;
+ ctxt->src.val = (unsigned long)ctxt->eflags;
return em_push(ctxt);
}
static int em_popa(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc = X86EMUL_CONTINUE;
int reg = VCPU_REGS_RDI;
while (reg >= VCPU_REGS_RAX) {
if (reg == VCPU_REGS_RSP) {
- register_address_increment(c, &c->regs[VCPU_REGS_RSP],
- c->op_bytes);
+ register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP],
+ ctxt->op_bytes);
--reg;
}
- rc = emulate_pop(ctxt, &c->regs[reg], c->op_bytes);
+ rc = emulate_pop(ctxt, &ctxt->regs[reg], ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
break;
--reg;
@@ -1553,10 +1518,9 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
return rc;
}
-int emulate_int_real(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, int irq)
+int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
{
- struct decode_cache *c = &ctxt->decode;
+ struct x86_emulate_ops *ops = ctxt->ops;
int rc;
struct desc_ptr dt;
gva_t cs_addr;
@@ -1564,19 +1528,19 @@ int emulate_int_real(struct x86_emulate_ctxt *ctxt,
u16 cs, eip;
/* TODO: Add limit checks */
- c->src.val = ctxt->eflags;
+ ctxt->src.val = ctxt->eflags;
rc = em_push(ctxt);
if (rc != X86EMUL_CONTINUE)
return rc;
ctxt->eflags &= ~(EFLG_IF | EFLG_TF | EFLG_AC);
- c->src.val = get_segment_selector(ctxt, VCPU_SREG_CS);
+ ctxt->src.val = get_segment_selector(ctxt, VCPU_SREG_CS);
rc = em_push(ctxt);
if (rc != X86EMUL_CONTINUE)
return rc;
- c->src.val = c->eip;
+ ctxt->src.val = ctxt->_eip;
rc = em_push(ctxt);
if (rc != X86EMUL_CONTINUE)
return rc;
@@ -1594,21 +1558,20 @@ int emulate_int_real(struct x86_emulate_ctxt *ctxt,
if (rc != X86EMUL_CONTINUE)
return rc;
- rc = load_segment_descriptor(ctxt, ops, cs, VCPU_SREG_CS);
+ rc = load_segment_descriptor(ctxt, cs, VCPU_SREG_CS);
if (rc != X86EMUL_CONTINUE)
return rc;
- c->eip = eip;
+ ctxt->_eip = eip;
return rc;
}
-static int emulate_int(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, int irq)
+static int emulate_int(struct x86_emulate_ctxt *ctxt, int irq)
{
switch(ctxt->mode) {
case X86EMUL_MODE_REAL:
- return emulate_int_real(ctxt, ops, irq);
+ return emulate_int_real(ctxt, irq);
case X86EMUL_MODE_VM86:
case X86EMUL_MODE_PROT16:
case X86EMUL_MODE_PROT32:
@@ -1619,10 +1582,8 @@ static int emulate_int(struct x86_emulate_ctxt *ctxt,
}
}
-static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops)
+static int emulate_iret_real(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc = X86EMUL_CONTINUE;
unsigned long temp_eip = 0;
unsigned long temp_eflags = 0;
@@ -1634,7 +1595,7 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
/* TODO: Add stack limit check */
- rc = emulate_pop(ctxt, &temp_eip, c->op_bytes);
+ rc = emulate_pop(ctxt, &temp_eip, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
@@ -1642,27 +1603,27 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
if (temp_eip & ~0xffff)
return emulate_gp(ctxt, 0);
- rc = emulate_pop(ctxt, &cs, c->op_bytes);
+ rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- rc = emulate_pop(ctxt, &temp_eflags, c->op_bytes);
+ rc = emulate_pop(ctxt, &temp_eflags, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- rc = load_segment_descriptor(ctxt, ops, (u16)cs, VCPU_SREG_CS);
+ rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
if (rc != X86EMUL_CONTINUE)
return rc;
- c->eip = temp_eip;
+ ctxt->_eip = temp_eip;
- if (c->op_bytes == 4)
+ if (ctxt->op_bytes == 4)
ctxt->eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
- else if (c->op_bytes == 2) {
+ else if (ctxt->op_bytes == 2) {
ctxt->eflags &= ~0xffff;
ctxt->eflags |= temp_eflags;
}
@@ -1673,12 +1634,11 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
return rc;
}
-static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops* ops)
+static int em_iret(struct x86_emulate_ctxt *ctxt)
{
switch(ctxt->mode) {
case X86EMUL_MODE_REAL:
- return emulate_iret_real(ctxt, ops);
+ return emulate_iret_real(ctxt);
case X86EMUL_MODE_VM86:
case X86EMUL_MODE_PROT16:
case X86EMUL_MODE_PROT32:
@@ -1691,53 +1651,49 @@ static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc;
unsigned short sel;
- memcpy(&sel, c->src.valptr + c->op_bytes, 2);
+ memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
- rc = load_segment_descriptor(ctxt, ctxt->ops, sel, VCPU_SREG_CS);
+ rc = load_segment_descriptor(ctxt, sel, VCPU_SREG_CS);
if (rc != X86EMUL_CONTINUE)
return rc;
- c->eip = 0;
- memcpy(&c->eip, c->src.valptr, c->op_bytes);
+ ctxt->_eip = 0;
+ memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
return X86EMUL_CONTINUE;
}
static int em_grp1a(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- return emulate_pop(ctxt, &c->dst.val, c->dst.bytes);
+ return emulate_pop(ctxt, &ctxt->dst.val, ctxt->dst.bytes);
}
static int em_grp2(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- switch (c->modrm_reg) {
+ switch (ctxt->modrm_reg) {
case 0: /* rol */
- emulate_2op_SrcB("rol", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcB("rol", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 1: /* ror */
- emulate_2op_SrcB("ror", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcB("ror", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 2: /* rcl */
- emulate_2op_SrcB("rcl", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcB("rcl", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 3: /* rcr */
- emulate_2op_SrcB("rcr", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcB("rcr", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 4: /* sal/shl */
case 6: /* sal/shl */
- emulate_2op_SrcB("sal", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcB("sal", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 5: /* shr */
- emulate_2op_SrcB("shr", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcB("shr", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 7: /* sar */
- emulate_2op_SrcB("sar", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcB("sar", ctxt->src, ctxt->dst, ctxt->eflags);
break;
}
return X86EMUL_CONTINUE;
@@ -1745,33 +1701,32 @@ static int em_grp2(struct x86_emulate_ctxt *ctxt)
static int em_grp3(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- unsigned long *rax = &c->regs[VCPU_REGS_RAX];
- unsigned long *rdx = &c->regs[VCPU_REGS_RDX];
+ unsigned long *rax = &ctxt->regs[VCPU_REGS_RAX];
+ unsigned long *rdx = &ctxt->regs[VCPU_REGS_RDX];
u8 de = 0;
- switch (c->modrm_reg) {
+ switch (ctxt->modrm_reg) {
case 0 ... 1: /* test */
- emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 2: /* not */
- c->dst.val = ~c->dst.val;
+ ctxt->dst.val = ~ctxt->dst.val;
break;
case 3: /* neg */
- emulate_1op("neg", c->dst, ctxt->eflags);
+ emulate_1op("neg", ctxt->dst, ctxt->eflags);
break;
case 4: /* mul */
- emulate_1op_rax_rdx("mul", c->src, *rax, *rdx, ctxt->eflags);
+ emulate_1op_rax_rdx("mul", ctxt->src, *rax, *rdx, ctxt->eflags);
break;
case 5: /* imul */
- emulate_1op_rax_rdx("imul", c->src, *rax, *rdx, ctxt->eflags);
+ emulate_1op_rax_rdx("imul", ctxt->src, *rax, *rdx, ctxt->eflags);
break;
case 6: /* div */
- emulate_1op_rax_rdx_ex("div", c->src, *rax, *rdx,
+ emulate_1op_rax_rdx_ex("div", ctxt->src, *rax, *rdx,
ctxt->eflags, de);
break;
case 7: /* idiv */
- emulate_1op_rax_rdx_ex("idiv", c->src, *rax, *rdx,
+ emulate_1op_rax_rdx_ex("idiv", ctxt->src, *rax, *rdx,
ctxt->eflags, de);
break;
default:
@@ -1784,26 +1739,25 @@ static int em_grp3(struct x86_emulate_ctxt *ctxt)
static int em_grp45(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc = X86EMUL_CONTINUE;
- switch (c->modrm_reg) {
+ switch (ctxt->modrm_reg) {
case 0: /* inc */
- emulate_1op("inc", c->dst, ctxt->eflags);
+ emulate_1op("inc", ctxt->dst, ctxt->eflags);
break;
case 1: /* dec */
- emulate_1op("dec", c->dst, ctxt->eflags);
+ emulate_1op("dec", ctxt->dst, ctxt->eflags);
break;
case 2: /* call near abs */ {
long int old_eip;
- old_eip = c->eip;
- c->eip = c->src.val;
- c->src.val = old_eip;
+ old_eip = ctxt->_eip;
+ ctxt->_eip = ctxt->src.val;
+ ctxt->src.val = old_eip;
rc = em_push(ctxt);
break;
}
case 4: /* jmp abs */
- c->eip = c->src.val;
+ ctxt->_eip = ctxt->src.val;
break;
case 5: /* jmp far */
rc = em_jmp_far(ctxt);
@@ -1817,68 +1771,70 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
static int em_grp9(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- u64 old = c->dst.orig_val64;
+ u64 old = ctxt->dst.orig_val64;
- if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) ||
- ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) {
- c->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
- c->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
+ if (((u32) (old >> 0) != (u32) ctxt->regs[VCPU_REGS_RAX]) ||
+ ((u32) (old >> 32) != (u32) ctxt->regs[VCPU_REGS_RDX])) {
+ ctxt->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
+ ctxt->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
ctxt->eflags &= ~EFLG_ZF;
} else {
- c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
- (u32) c->regs[VCPU_REGS_RBX];
+ ctxt->dst.val64 = ((u64)ctxt->regs[VCPU_REGS_RCX] << 32) |
+ (u32) ctxt->regs[VCPU_REGS_RBX];
ctxt->eflags |= EFLG_ZF;
}
return X86EMUL_CONTINUE;
}
-static int emulate_ret_far(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops)
+static int em_ret(struct x86_emulate_ctxt *ctxt)
+{
+ ctxt->dst.type = OP_REG;
+ ctxt->dst.addr.reg = &ctxt->_eip;
+ ctxt->dst.bytes = ctxt->op_bytes;
+ return em_pop(ctxt);
+}
+
+static int em_ret_far(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc;
unsigned long cs;
- rc = emulate_pop(ctxt, &c->eip, c->op_bytes);
+ rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- if (c->op_bytes == 4)
- c->eip = (u32)c->eip;
- rc = emulate_pop(ctxt, &cs, c->op_bytes);
+ if (ctxt->op_bytes == 4)
+ ctxt->_eip = (u32)ctxt->_eip;
+ rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- rc = load_segment_descriptor(ctxt, ops, (u16)cs, VCPU_SREG_CS);
+ rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
return rc;
}
-static int emulate_load_segment(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, int seg)
+static int emulate_load_segment(struct x86_emulate_ctxt *ctxt, int seg)
{
- struct decode_cache *c = &ctxt->decode;
unsigned short sel;
int rc;
- memcpy(&sel, c->src.valptr + c->op_bytes, 2);
+ memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
- rc = load_segment_descriptor(ctxt, ops, sel, seg);
+ rc = load_segment_descriptor(ctxt, sel, seg);
if (rc != X86EMUL_CONTINUE)
return rc;
- c->dst.val = c->src.val;
+ ctxt->dst.val = ctxt->src.val;
return rc;
}
-static inline void
+static void
setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops, struct desc_struct *cs,
- struct desc_struct *ss)
+ struct desc_struct *cs, struct desc_struct *ss)
{
u16 selector;
memset(cs, 0, sizeof(struct desc_struct));
- ops->get_segment(ctxt, &selector, cs, NULL, VCPU_SREG_CS);
+ ctxt->ops->get_segment(ctxt, &selector, cs, NULL, VCPU_SREG_CS);
memset(ss, 0, sizeof(struct desc_struct));
cs->l = 0; /* will be adjusted later */
@@ -1901,10 +1857,9 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
ss->p = 1;
}
-static int
-emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+static int em_syscall(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
+ struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct cs, ss;
u64 msr_data;
u16 cs_sel, ss_sel;
@@ -1916,7 +1871,7 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
return emulate_ud(ctxt);
ops->get_msr(ctxt, MSR_EFER, &efer);
- setup_syscalls_segments(ctxt, ops, &cs, &ss);
+ setup_syscalls_segments(ctxt, &cs, &ss);
ops->get_msr(ctxt, MSR_STAR, &msr_data);
msr_data >>= 32;
@@ -1930,15 +1885,15 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
- c->regs[VCPU_REGS_RCX] = c->eip;
+ ctxt->regs[VCPU_REGS_RCX] = ctxt->_eip;
if (efer & EFER_LMA) {
#ifdef CONFIG_X86_64
- c->regs[VCPU_REGS_R11] = ctxt->eflags & ~EFLG_RF;
+ ctxt->regs[VCPU_REGS_R11] = ctxt->eflags & ~EFLG_RF;
ops->get_msr(ctxt,
ctxt->mode == X86EMUL_MODE_PROT64 ?
MSR_LSTAR : MSR_CSTAR, &msr_data);
- c->eip = msr_data;
+ ctxt->_eip = msr_data;
ops->get_msr(ctxt, MSR_SYSCALL_MASK, &msr_data);
ctxt->eflags &= ~(msr_data | EFLG_RF);
@@ -1946,7 +1901,7 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
} else {
/* legacy mode */
ops->get_msr(ctxt, MSR_STAR, &msr_data);
- c->eip = (u32)msr_data;
+ ctxt->_eip = (u32)msr_data;
ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
}
@@ -1954,16 +1909,15 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
return X86EMUL_CONTINUE;
}
-static int
-emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+static int em_sysenter(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
+ struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct cs, ss;
u64 msr_data;
u16 cs_sel, ss_sel;
u64 efer = 0;
- ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
+ ops->get_msr(ctxt, MSR_EFER, &efer);
/* inject #GP if in real mode */
if (ctxt->mode == X86EMUL_MODE_REAL)
return emulate_gp(ctxt, 0);
@@ -1974,7 +1928,7 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
if (ctxt->mode == X86EMUL_MODE_PROT64)
return emulate_ud(ctxt);
- setup_syscalls_segments(ctxt, ops, &cs, &ss);
+ setup_syscalls_segments(ctxt, &cs, &ss);
ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
switch (ctxt->mode) {
@@ -2002,31 +1956,30 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
- c->eip = msr_data;
+ ctxt->_eip = msr_data;
ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
- c->regs[VCPU_REGS_RSP] = msr_data;
+ ctxt->regs[VCPU_REGS_RSP] = msr_data;
return X86EMUL_CONTINUE;
}
-static int
-emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+static int em_sysexit(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
+ struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct cs, ss;
u64 msr_data;
int usermode;
- u16 cs_sel, ss_sel;
+ u16 cs_sel = 0, ss_sel = 0;
/* inject #GP if in real mode or Virtual 8086 mode */
if (ctxt->mode == X86EMUL_MODE_REAL ||
ctxt->mode == X86EMUL_MODE_VM86)
return emulate_gp(ctxt, 0);
- setup_syscalls_segments(ctxt, ops, &cs, &ss);
+ setup_syscalls_segments(ctxt, &cs, &ss);
- if ((c->rex_prefix & 0x8) != 0x0)
+ if ((ctxt->rex_prefix & 0x8) != 0x0)
usermode = X86EMUL_MODE_PROT64;
else
usermode = X86EMUL_MODE_PROT32;
@@ -2056,14 +2009,13 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
- c->eip = c->regs[VCPU_REGS_RDX];
- c->regs[VCPU_REGS_RSP] = c->regs[VCPU_REGS_RCX];
+ ctxt->_eip = ctxt->regs[VCPU_REGS_RDX];
+ ctxt->regs[VCPU_REGS_RSP] = ctxt->regs[VCPU_REGS_RCX];
return X86EMUL_CONTINUE;
}
-static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops)
+static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt)
{
int iopl;
if (ctxt->mode == X86EMUL_MODE_REAL)
@@ -2071,13 +2023,13 @@ static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt,
if (ctxt->mode == X86EMUL_MODE_VM86)
return true;
iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
- return ops->cpl(ctxt) > iopl;
+ return ctxt->ops->cpl(ctxt) > iopl;
}
static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 port, u16 len)
{
+ struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct tr_seg;
u32 base3;
int r;
@@ -2108,14 +2060,13 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
}
static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 port, u16 len)
{
if (ctxt->perm_ok)
return true;
- if (emulator_bad_iopl(ctxt, ops))
- if (!emulator_io_port_access_allowed(ctxt, ops, port, len))
+ if (emulator_bad_iopl(ctxt))
+ if (!emulator_io_port_access_allowed(ctxt, port, len))
return false;
ctxt->perm_ok = true;
@@ -2124,21 +2075,18 @@ static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
}
static void save_state_to_tss16(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
struct tss_segment_16 *tss)
{
- struct decode_cache *c = &ctxt->decode;
-
- tss->ip = c->eip;
+ tss->ip = ctxt->_eip;
tss->flag = ctxt->eflags;
- tss->ax = c->regs[VCPU_REGS_RAX];
- tss->cx = c->regs[VCPU_REGS_RCX];
- tss->dx = c->regs[VCPU_REGS_RDX];
- tss->bx = c->regs[VCPU_REGS_RBX];
- tss->sp = c->regs[VCPU_REGS_RSP];
- tss->bp = c->regs[VCPU_REGS_RBP];
- tss->si = c->regs[VCPU_REGS_RSI];
- tss->di = c->regs[VCPU_REGS_RDI];
+ tss->ax = ctxt->regs[VCPU_REGS_RAX];
+ tss->cx = ctxt->regs[VCPU_REGS_RCX];
+ tss->dx = ctxt->regs[VCPU_REGS_RDX];
+ tss->bx = ctxt->regs[VCPU_REGS_RBX];
+ tss->sp = ctxt->regs[VCPU_REGS_RSP];
+ tss->bp = ctxt->regs[VCPU_REGS_RBP];
+ tss->si = ctxt->regs[VCPU_REGS_RSI];
+ tss->di = ctxt->regs[VCPU_REGS_RDI];
tss->es = get_segment_selector(ctxt, VCPU_SREG_ES);
tss->cs = get_segment_selector(ctxt, VCPU_SREG_CS);
@@ -2148,22 +2096,20 @@ static void save_state_to_tss16(struct x86_emulate_ctxt *ctxt,
}
static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
struct tss_segment_16 *tss)
{
- struct decode_cache *c = &ctxt->decode;
int ret;
- c->eip = tss->ip;
+ ctxt->_eip = tss->ip;
ctxt->eflags = tss->flag | 2;
- c->regs[VCPU_REGS_RAX] = tss->ax;
- c->regs[VCPU_REGS_RCX] = tss->cx;
- c->regs[VCPU_REGS_RDX] = tss->dx;
- c->regs[VCPU_REGS_RBX] = tss->bx;
- c->regs[VCPU_REGS_RSP] = tss->sp;
- c->regs[VCPU_REGS_RBP] = tss->bp;
- c->regs[VCPU_REGS_RSI] = tss->si;
- c->regs[VCPU_REGS_RDI] = tss->di;
+ ctxt->regs[VCPU_REGS_RAX] = tss->ax;
+ ctxt->regs[VCPU_REGS_RCX] = tss->cx;
+ ctxt->regs[VCPU_REGS_RDX] = tss->dx;
+ ctxt->regs[VCPU_REGS_RBX] = tss->bx;
+ ctxt->regs[VCPU_REGS_RSP] = tss->sp;
+ ctxt->regs[VCPU_REGS_RBP] = tss->bp;
+ ctxt->regs[VCPU_REGS_RSI] = tss->si;
+ ctxt->regs[VCPU_REGS_RDI] = tss->di;
/*
* SDM says that segment selectors are loaded before segment
@@ -2179,19 +2125,19 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
* Now load segment descriptors. If fault happenes at this stage
* it is handled in a context of new task
*/
- ret = load_segment_descriptor(ctxt, ops, tss->ldt, VCPU_SREG_LDTR);
+ ret = load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->es, VCPU_SREG_ES);
+ ret = load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->cs, VCPU_SREG_CS);
+ ret = load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->ss, VCPU_SREG_SS);
+ ret = load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->ds, VCPU_SREG_DS);
+ ret = load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS);
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2199,10 +2145,10 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
}
static int task_switch_16(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 tss_selector, u16 old_tss_sel,
ulong old_tss_base, struct desc_struct *new_desc)
{
+ struct x86_emulate_ops *ops = ctxt->ops;
struct tss_segment_16 tss_seg;
int ret;
u32 new_tss_base = get_desc_base(new_desc);
@@ -2213,7 +2159,7 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
/* FIXME: need to provide precise fault address */
return ret;
- save_state_to_tss16(ctxt, ops, &tss_seg);
+ save_state_to_tss16(ctxt, &tss_seg);
ret = ops->write_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
&ctxt->exception);
@@ -2239,26 +2185,23 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
return ret;
}
- return load_state_from_tss16(ctxt, ops, &tss_seg);
+ return load_state_from_tss16(ctxt, &tss_seg);
}
static void save_state_to_tss32(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
struct tss_segment_32 *tss)
{
- struct decode_cache *c = &ctxt->decode;
-
- tss->cr3 = ops->get_cr(ctxt, 3);
- tss->eip = c->eip;
+ tss->cr3 = ctxt->ops->get_cr(ctxt, 3);
+ tss->eip = ctxt->_eip;
tss->eflags = ctxt->eflags;
- tss->eax = c->regs[VCPU_REGS_RAX];
- tss->ecx = c->regs[VCPU_REGS_RCX];
- tss->edx = c->regs[VCPU_REGS_RDX];
- tss->ebx = c->regs[VCPU_REGS_RBX];
- tss->esp = c->regs[VCPU_REGS_RSP];
- tss->ebp = c->regs[VCPU_REGS_RBP];
- tss->esi = c->regs[VCPU_REGS_RSI];
- tss->edi = c->regs[VCPU_REGS_RDI];
+ tss->eax = ctxt->regs[VCPU_REGS_RAX];
+ tss->ecx = ctxt->regs[VCPU_REGS_RCX];
+ tss->edx = ctxt->regs[VCPU_REGS_RDX];
+ tss->ebx = ctxt->regs[VCPU_REGS_RBX];
+ tss->esp = ctxt->regs[VCPU_REGS_RSP];
+ tss->ebp = ctxt->regs[VCPU_REGS_RBP];
+ tss->esi = ctxt->regs[VCPU_REGS_RSI];
+ tss->edi = ctxt->regs[VCPU_REGS_RDI];
tss->es = get_segment_selector(ctxt, VCPU_SREG_ES);
tss->cs = get_segment_selector(ctxt, VCPU_SREG_CS);
@@ -2270,24 +2213,22 @@ static void save_state_to_tss32(struct x86_emulate_ctxt *ctxt,
}
static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
struct tss_segment_32 *tss)
{
- struct decode_cache *c = &ctxt->decode;
int ret;
- if (ops->set_cr(ctxt, 3, tss->cr3))
+ if (ctxt->ops->set_cr(ctxt, 3, tss->cr3))
return emulate_gp(ctxt, 0);
- c->eip = tss->eip;
+ ctxt->_eip = tss->eip;
ctxt->eflags = tss->eflags | 2;
- c->regs[VCPU_REGS_RAX] = tss->eax;
- c->regs[VCPU_REGS_RCX] = tss->ecx;
- c->regs[VCPU_REGS_RDX] = tss->edx;
- c->regs[VCPU_REGS_RBX] = tss->ebx;
- c->regs[VCPU_REGS_RSP] = tss->esp;
- c->regs[VCPU_REGS_RBP] = tss->ebp;
- c->regs[VCPU_REGS_RSI] = tss->esi;
- c->regs[VCPU_REGS_RDI] = tss->edi;
+ ctxt->regs[VCPU_REGS_RAX] = tss->eax;
+ ctxt->regs[VCPU_REGS_RCX] = tss->ecx;
+ ctxt->regs[VCPU_REGS_RDX] = tss->edx;
+ ctxt->regs[VCPU_REGS_RBX] = tss->ebx;
+ ctxt->regs[VCPU_REGS_RSP] = tss->esp;
+ ctxt->regs[VCPU_REGS_RBP] = tss->ebp;
+ ctxt->regs[VCPU_REGS_RSI] = tss->esi;
+ ctxt->regs[VCPU_REGS_RDI] = tss->edi;
/*
* SDM says that segment selectors are loaded before segment
@@ -2305,25 +2246,25 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
* Now load segment descriptors. If fault happenes at this stage
* it is handled in a context of new task
*/
- ret = load_segment_descriptor(ctxt, ops, tss->ldt_selector, VCPU_SREG_LDTR);
+ ret = load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->es, VCPU_SREG_ES);
+ ret = load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->cs, VCPU_SREG_CS);
+ ret = load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->ss, VCPU_SREG_SS);
+ ret = load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->ds, VCPU_SREG_DS);
+ ret = load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->fs, VCPU_SREG_FS);
+ ret = load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = load_segment_descriptor(ctxt, ops, tss->gs, VCPU_SREG_GS);
+ ret = load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS);
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2331,10 +2272,10 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
}
static int task_switch_32(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 tss_selector, u16 old_tss_sel,
ulong old_tss_base, struct desc_struct *new_desc)
{
+ struct x86_emulate_ops *ops = ctxt->ops;
struct tss_segment_32 tss_seg;
int ret;
u32 new_tss_base = get_desc_base(new_desc);
@@ -2345,7 +2286,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
/* FIXME: need to provide precise fault address */
return ret;
- save_state_to_tss32(ctxt, ops, &tss_seg);
+ save_state_to_tss32(ctxt, &tss_seg);
ret = ops->write_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
&ctxt->exception);
@@ -2371,14 +2312,14 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
return ret;
}
- return load_state_from_tss32(ctxt, ops, &tss_seg);
+ return load_state_from_tss32(ctxt, &tss_seg);
}
static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops,
u16 tss_selector, int reason,
bool has_error_code, u32 error_code)
{
+ struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct curr_tss_desc, next_tss_desc;
int ret;
u16 old_tss_sel = get_segment_selector(ctxt, VCPU_SREG_TR);
@@ -2388,10 +2329,10 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
/* FIXME: old_tss_base == ~0 ? */
- ret = read_segment_descriptor(ctxt, ops, tss_selector, &next_tss_desc);
+ ret = read_segment_descriptor(ctxt, tss_selector, &next_tss_desc);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = read_segment_descriptor(ctxt, ops, old_tss_sel, &curr_tss_desc);
+ ret = read_segment_descriptor(ctxt, old_tss_sel, &curr_tss_desc);
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2413,8 +2354,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
if (reason == TASK_SWITCH_IRET || reason == TASK_SWITCH_JMP) {
curr_tss_desc.type &= ~(1 << 1); /* clear busy flag */
- write_segment_descriptor(ctxt, ops, old_tss_sel,
- &curr_tss_desc);
+ write_segment_descriptor(ctxt, old_tss_sel, &curr_tss_desc);
}
if (reason == TASK_SWITCH_IRET)
@@ -2426,10 +2366,10 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
old_tss_sel = 0xffff;
if (next_tss_desc.type & 8)
- ret = task_switch_32(ctxt, ops, tss_selector, old_tss_sel,
+ ret = task_switch_32(ctxt, tss_selector, old_tss_sel,
old_tss_base, &next_tss_desc);
else
- ret = task_switch_16(ctxt, ops, tss_selector, old_tss_sel,
+ ret = task_switch_16(ctxt, tss_selector, old_tss_sel,
old_tss_base, &next_tss_desc);
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2439,19 +2379,16 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
if (reason != TASK_SWITCH_IRET) {
next_tss_desc.type |= (1 << 1); /* set busy flag */
- write_segment_descriptor(ctxt, ops, tss_selector,
- &next_tss_desc);
+ write_segment_descriptor(ctxt, tss_selector, &next_tss_desc);
}
ops->set_cr(ctxt, 0, ops->get_cr(ctxt, 0) | X86_CR0_TS);
ops->set_segment(ctxt, tss_selector, &next_tss_desc, 0, VCPU_SREG_TR);
if (has_error_code) {
- struct decode_cache *c = &ctxt->decode;
-
- c->op_bytes = c->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2;
- c->lock_prefix = 0;
- c->src.val = (unsigned long) error_code;
+ ctxt->op_bytes = ctxt->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2;
+ ctxt->lock_prefix = 0;
+ ctxt->src.val = (unsigned long) error_code;
ret = em_push(ctxt);
}
@@ -2462,18 +2399,16 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
u16 tss_selector, int reason,
bool has_error_code, u32 error_code)
{
- struct x86_emulate_ops *ops = ctxt->ops;
- struct decode_cache *c = &ctxt->decode;
int rc;
- c->eip = ctxt->eip;
- c->dst.type = OP_NONE;
+ ctxt->_eip = ctxt->eip;
+ ctxt->dst.type = OP_NONE;
- rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
+ rc = emulator_do_task_switch(ctxt, tss_selector, reason,
has_error_code, error_code);
if (rc == X86EMUL_CONTINUE)
- ctxt->eip = c->eip;
+ ctxt->eip = ctxt->_eip;
return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
}
@@ -2481,22 +2416,20 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned seg,
int reg, struct operand *op)
{
- struct decode_cache *c = &ctxt->decode;
int df = (ctxt->eflags & EFLG_DF) ? -1 : 1;
- register_address_increment(c, &c->regs[reg], df * op->bytes);
- op->addr.mem.ea = register_address(c, c->regs[reg]);
+ register_address_increment(ctxt, &ctxt->regs[reg], df * op->bytes);
+ op->addr.mem.ea = register_address(ctxt, ctxt->regs[reg]);
op->addr.mem.seg = seg;
}
static int em_das(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
u8 al, old_al;
bool af, cf, old_cf;
cf = ctxt->eflags & X86_EFLAGS_CF;
- al = c->dst.val;
+ al = ctxt->dst.val;
old_al = al;
old_cf = cf;
@@ -2514,12 +2447,12 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
cf = true;
}
- c->dst.val = al;
+ ctxt->dst.val = al;
/* Set PF, ZF, SF */
- c->src.type = OP_IMM;
- c->src.val = 0;
- c->src.bytes = 1;
- emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags);
+ ctxt->src.type = OP_IMM;
+ ctxt->src.val = 0;
+ ctxt->src.bytes = 1;
+ emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
ctxt->eflags &= ~(X86_EFLAGS_AF | X86_EFLAGS_CF);
if (cf)
ctxt->eflags |= X86_EFLAGS_CF;
@@ -2530,175 +2463,189 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
static int em_call_far(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
u16 sel, old_cs;
ulong old_eip;
int rc;
old_cs = get_segment_selector(ctxt, VCPU_SREG_CS);
- old_eip = c->eip;
+ old_eip = ctxt->_eip;
- memcpy(&sel, c->src.valptr + c->op_bytes, 2);
- if (load_segment_descriptor(ctxt, ctxt->ops, sel, VCPU_SREG_CS))
+ memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
+ if (load_segment_descriptor(ctxt, sel, VCPU_SREG_CS))
return X86EMUL_CONTINUE;
- c->eip = 0;
- memcpy(&c->eip, c->src.valptr, c->op_bytes);
+ ctxt->_eip = 0;
+ memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
- c->src.val = old_cs;
+ ctxt->src.val = old_cs;
rc = em_push(ctxt);
if (rc != X86EMUL_CONTINUE)
return rc;
- c->src.val = old_eip;
+ ctxt->src.val = old_eip;
return em_push(ctxt);
}
static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc;
- c->dst.type = OP_REG;
- c->dst.addr.reg = &c->eip;
- c->dst.bytes = c->op_bytes;
- rc = emulate_pop(ctxt, &c->dst.val, c->op_bytes);
+ ctxt->dst.type = OP_REG;
+ ctxt->dst.addr.reg = &ctxt->_eip;
+ ctxt->dst.bytes = ctxt->op_bytes;
+ rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->src.val);
+ register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], ctxt->src.val);
return X86EMUL_CONTINUE;
}
static int em_add(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
return X86EMUL_CONTINUE;
}
static int em_or(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
return X86EMUL_CONTINUE;
}
static int em_adc(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("adc", ctxt->src, ctxt->dst, ctxt->eflags);
return X86EMUL_CONTINUE;
}
static int em_sbb(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("sbb", ctxt->src, ctxt->dst, ctxt->eflags);
return X86EMUL_CONTINUE;
}
static int em_and(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("and", ctxt->src, ctxt->dst, ctxt->eflags);
return X86EMUL_CONTINUE;
}
static int em_sub(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("sub", ctxt->src, ctxt->dst, ctxt->eflags);
return X86EMUL_CONTINUE;
}
static int em_xor(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("xor", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("xor", ctxt->src, ctxt->dst, ctxt->eflags);
return X86EMUL_CONTINUE;
}
static int em_cmp(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
/* Disable writeback. */
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
-static int em_imul(struct x86_emulate_ctxt *ctxt)
+static int em_test(struct x86_emulate_ctxt *ctxt)
+{
+ emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
+ return X86EMUL_CONTINUE;
+}
+
+static int em_xchg(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
+ /* Write back the register source. */
+ ctxt->src.val = ctxt->dst.val;
+ write_register_operand(&ctxt->src);
- emulate_2op_SrcV_nobyte("imul", c->src, c->dst, ctxt->eflags);
+ /* Write back the memory destination with implicit LOCK prefix. */
+ ctxt->dst.val = ctxt->src.orig_val;
+ ctxt->lock_prefix = 1;
return X86EMUL_CONTINUE;
}
-static int em_imul_3op(struct x86_emulate_ctxt *ctxt)
+static int em_imul(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
+ emulate_2op_SrcV_nobyte("imul", ctxt->src, ctxt->dst, ctxt->eflags);
+ return X86EMUL_CONTINUE;
+}
- c->dst.val = c->src2.val;
+static int em_imul_3op(struct x86_emulate_ctxt *ctxt)
+{
+ ctxt->dst.val = ctxt->src2.val;
return em_imul(ctxt);
}
static int em_cwd(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- c->dst.type = OP_REG;
- c->dst.bytes = c->src.bytes;
- c->dst.addr.reg = &c->regs[VCPU_REGS_RDX];
- c->dst.val = ~((c->src.val >> (c->src.bytes * 8 - 1)) - 1);
+ ctxt->dst.type = OP_REG;
+ ctxt->dst.bytes = ctxt->src.bytes;
+ ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+ ctxt->dst.val = ~((ctxt->src.val >> (ctxt->src.bytes * 8 - 1)) - 1);
return X86EMUL_CONTINUE;
}
static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
u64 tsc = 0;
ctxt->ops->get_msr(ctxt, MSR_IA32_TSC, &tsc);
- c->regs[VCPU_REGS_RAX] = (u32)tsc;
- c->regs[VCPU_REGS_RDX] = tsc >> 32;
+ ctxt->regs[VCPU_REGS_RAX] = (u32)tsc;
+ ctxt->regs[VCPU_REGS_RDX] = tsc >> 32;
return X86EMUL_CONTINUE;
}
static int em_mov(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- c->dst.val = c->src.val;
+ ctxt->dst.val = ctxt->src.val;
return X86EMUL_CONTINUE;
}
+static int em_mov_rm_sreg(struct x86_emulate_ctxt *ctxt)
+{
+ if (ctxt->modrm_reg > VCPU_SREG_GS)
+ return emulate_ud(ctxt);
+
+ ctxt->dst.val = get_segment_selector(ctxt, ctxt->modrm_reg);
+ return X86EMUL_CONTINUE;
+}
+
+static int em_mov_sreg_rm(struct x86_emulate_ctxt *ctxt)
+{
+ u16 sel = ctxt->src.val;
+
+ if (ctxt->modrm_reg == VCPU_SREG_CS || ctxt->modrm_reg > VCPU_SREG_GS)
+ return emulate_ud(ctxt);
+
+ if (ctxt->modrm_reg == VCPU_SREG_SS)
+ ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS;
+
+ /* Disable writeback. */
+ ctxt->dst.type = OP_NONE;
+ return load_segment_descriptor(ctxt, sel, ctxt->modrm_reg);
+}
+
static int em_movdqu(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- memcpy(&c->dst.vec_val, &c->src.vec_val, c->op_bytes);
+ memcpy(&ctxt->dst.vec_val, &ctxt->src.vec_val, ctxt->op_bytes);
return X86EMUL_CONTINUE;
}
static int em_invlpg(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc;
ulong linear;
- rc = linearize(ctxt, c->src.addr.mem, 1, false, &linear);
+ rc = linearize(ctxt, ctxt->src.addr.mem, 1, false, &linear);
if (rc == X86EMUL_CONTINUE)
ctxt->ops->invlpg(ctxt, linear);
/* Disable writeback. */
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
@@ -2714,10 +2661,9 @@ static int em_clts(struct x86_emulate_ctxt *ctxt)
static int em_vmcall(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc;
- if (c->modrm_mod != 3 || c->modrm_rm != 1)
+ if (ctxt->modrm_mod != 3 || ctxt->modrm_rm != 1)
return X86EMUL_UNHANDLEABLE;
rc = ctxt->ops->fix_hypercall(ctxt);
@@ -2725,73 +2671,104 @@ static int em_vmcall(struct x86_emulate_ctxt *ctxt)
return rc;
/* Let the processor re-execute the fixed hypercall */
- c->eip = ctxt->eip;
+ ctxt->_eip = ctxt->eip;
/* Disable writeback. */
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
static int em_lgdt(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
struct desc_ptr desc_ptr;
int rc;
- rc = read_descriptor(ctxt, c->src.addr.mem,
+ rc = read_descriptor(ctxt, ctxt->src.addr.mem,
&desc_ptr.size, &desc_ptr.address,
- c->op_bytes);
+ ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
ctxt->ops->set_gdt(ctxt, &desc_ptr);
/* Disable writeback. */
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
static int em_vmmcall(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
int rc;
rc = ctxt->ops->fix_hypercall(ctxt);
/* Disable writeback. */
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
return rc;
}
static int em_lidt(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
struct desc_ptr desc_ptr;
int rc;
- rc = read_descriptor(ctxt, c->src.addr.mem,
+ rc = read_descriptor(ctxt, ctxt->src.addr.mem,
&desc_ptr.size, &desc_ptr.address,
- c->op_bytes);
+ ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
ctxt->ops->set_idt(ctxt, &desc_ptr);
/* Disable writeback. */
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
static int em_smsw(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- c->dst.bytes = 2;
- c->dst.val = ctxt->ops->get_cr(ctxt, 0);
+ ctxt->dst.bytes = 2;
+ ctxt->dst.val = ctxt->ops->get_cr(ctxt, 0);
return X86EMUL_CONTINUE;
}
static int em_lmsw(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
ctxt->ops->set_cr(ctxt, 0, (ctxt->ops->get_cr(ctxt, 0) & ~0x0eul)
- | (c->src.val & 0x0f));
- c->dst.type = OP_NONE;
+ | (ctxt->src.val & 0x0f));
+ ctxt->dst.type = OP_NONE;
+ return X86EMUL_CONTINUE;
+}
+
+static int em_loop(struct x86_emulate_ctxt *ctxt)
+{
+ register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RCX], -1);
+ if ((address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) != 0) &&
+ (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
+ jmp_rel(ctxt, ctxt->src.val);
+
+ return X86EMUL_CONTINUE;
+}
+
+static int em_jcxz(struct x86_emulate_ctxt *ctxt)
+{
+ if (address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) == 0)
+ jmp_rel(ctxt, ctxt->src.val);
+
+ return X86EMUL_CONTINUE;
+}
+
+static int em_cli(struct x86_emulate_ctxt *ctxt)
+{
+ if (emulator_bad_iopl(ctxt))
+ return emulate_gp(ctxt, 0);
+
+ ctxt->eflags &= ~X86_EFLAGS_IF;
+ return X86EMUL_CONTINUE;
+}
+
+static int em_sti(struct x86_emulate_ctxt *ctxt)
+{
+ if (emulator_bad_iopl(ctxt))
+ return emulate_gp(ctxt, 0);
+
+ ctxt->interruptibility = KVM_X86_SHADOW_INT_STI;
+ ctxt->eflags |= X86_EFLAGS_IF;
return X86EMUL_CONTINUE;
}
@@ -2809,9 +2786,7 @@ static bool valid_cr(int nr)
static int check_cr_read(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- if (!valid_cr(c->modrm_reg))
+ if (!valid_cr(ctxt->modrm_reg))
return emulate_ud(ctxt);
return X86EMUL_CONTINUE;
@@ -2819,9 +2794,8 @@ static int check_cr_read(struct x86_emulate_ctxt *ctxt)
static int check_cr_write(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- u64 new_val = c->src.val64;
- int cr = c->modrm_reg;
+ u64 new_val = ctxt->src.val64;
+ int cr = ctxt->modrm_reg;
u64 efer = 0;
static u64 cr_reserved_bits[] = {
@@ -2898,8 +2872,7 @@ static int check_dr7_gd(struct x86_emulate_ctxt *ctxt)
static int check_dr_read(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- int dr = c->modrm_reg;
+ int dr = ctxt->modrm_reg;
u64 cr4;
if (dr > 7)
@@ -2917,9 +2890,8 @@ static int check_dr_read(struct x86_emulate_ctxt *ctxt)
static int check_dr_write(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
- u64 new_val = c->src.val64;
- int dr = c->modrm_reg;
+ u64 new_val = ctxt->src.val64;
+ int dr = ctxt->modrm_reg;
if ((dr == 6 || dr == 7) && (new_val & 0xffffffff00000000ULL))
return emulate_gp(ctxt, 0);
@@ -2941,7 +2913,7 @@ static int check_svme(struct x86_emulate_ctxt *ctxt)
static int check_svme_pa(struct x86_emulate_ctxt *ctxt)
{
- u64 rax = ctxt->decode.regs[VCPU_REGS_RAX];
+ u64 rax = ctxt->regs[VCPU_REGS_RAX];
/* Valid physical address? */
if (rax & 0xffff000000000000ULL)
@@ -2963,7 +2935,7 @@ static int check_rdtsc(struct x86_emulate_ctxt *ctxt)
static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
{
u64 cr4 = ctxt->ops->get_cr(ctxt, 4);
- u64 rcx = ctxt->decode.regs[VCPU_REGS_RCX];
+ u64 rcx = ctxt->regs[VCPU_REGS_RCX];
if ((!(cr4 & X86_CR4_PCE) && ctxt->ops->cpl(ctxt)) ||
(rcx > 3))
@@ -2974,10 +2946,8 @@ static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
static int check_perm_in(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- c->dst.bytes = min(c->dst.bytes, 4u);
- if (!emulator_io_permited(ctxt, ctxt->ops, c->src.val, c->dst.bytes))
+ ctxt->dst.bytes = min(ctxt->dst.bytes, 4u);
+ if (!emulator_io_permited(ctxt, ctxt->src.val, ctxt->dst.bytes))
return emulate_gp(ctxt, 0);
return X86EMUL_CONTINUE;
@@ -2985,10 +2955,8 @@ static int check_perm_in(struct x86_emulate_ctxt *ctxt)
static int check_perm_out(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
- c->src.bytes = min(c->src.bytes, 4u);
- if (!emulator_io_permited(ctxt, ctxt->ops, c->dst.val, c->src.bytes))
+ ctxt->src.bytes = min(ctxt->src.bytes, 4u);
+ if (!emulator_io_permited(ctxt, ctxt->dst.val, ctxt->src.bytes))
return emulate_gp(ctxt, 0);
return X86EMUL_CONTINUE;
@@ -3165,12 +3133,15 @@ static struct opcode opcode_table[256] = {
G(DstMem | SrcImm | ModRM | Group, group1),
G(ByteOp | DstMem | SrcImm | ModRM | No64 | Group, group1),
G(DstMem | SrcImmByte | ModRM | Group, group1),
- D2bv(DstMem | SrcReg | ModRM), D2bv(DstMem | SrcReg | ModRM | Lock),
+ I2bv(DstMem | SrcReg | ModRM, em_test),
+ I2bv(DstMem | SrcReg | ModRM | Lock, em_xchg),
/* 0x88 - 0x8F */
I2bv(DstMem | SrcReg | ModRM | Mov, em_mov),
I2bv(DstReg | SrcMem | ModRM | Mov, em_mov),
- D(DstMem | SrcNone | ModRM | Mov), D(ModRM | SrcMem | NoAccess | DstReg),
- D(ImplicitOps | SrcMem16 | ModRM), G(0, group1A),
+ I(DstMem | SrcNone | ModRM | Mov, em_mov_rm_sreg),
+ D(ModRM | SrcMem | NoAccess | DstReg),
+ I(ImplicitOps | SrcMem16 | ModRM, em_mov_sreg_rm),
+ G(0, group1A),
/* 0x90 - 0x97 */
DI(SrcAcc | DstReg, pause), X7(D(SrcAcc | DstReg)),
/* 0x98 - 0x9F */
@@ -3184,7 +3155,7 @@ static struct opcode opcode_table[256] = {
I2bv(SrcSI | DstDI | Mov | String, em_mov),
I2bv(SrcSI | DstDI | String, em_cmp),
/* 0xA8 - 0xAF */
- D2bv(DstAcc | SrcImm),
+ I2bv(DstAcc | SrcImm, em_test),
I2bv(SrcAcc | DstDI | Mov | String, em_mov),
I2bv(SrcSI | DstAcc | Mov | String, em_mov),
I2bv(SrcAcc | DstDI | String, em_cmp),
@@ -3195,25 +3166,26 @@ static struct opcode opcode_table[256] = {
/* 0xC0 - 0xC7 */
D2bv(DstMem | SrcImmByte | ModRM),
I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
- D(ImplicitOps | Stack),
+ I(ImplicitOps | Stack, em_ret),
D(DstReg | SrcMemFAddr | ModRM | No64), D(DstReg | SrcMemFAddr | ModRM | No64),
G(ByteOp, group11), G(0, group11),
/* 0xC8 - 0xCF */
- N, N, N, D(ImplicitOps | Stack),
+ N, N, N, I(ImplicitOps | Stack, em_ret_far),
D(ImplicitOps), DI(SrcImmByte, intn),
- D(ImplicitOps | No64), DI(ImplicitOps, iret),
+ D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret),
/* 0xD0 - 0xD7 */
D2bv(DstMem | SrcOne | ModRM), D2bv(DstMem | ModRM),
N, N, N, N,
/* 0xD8 - 0xDF */
N, N, N, N, N, N, N, N,
/* 0xE0 - 0xE7 */
- X4(D(SrcImmByte)),
+ X3(I(SrcImmByte, em_loop)),
+ I(SrcImmByte, em_jcxz),
D2bvIP(SrcImmUByte | DstAcc, in, check_perm_in),
D2bvIP(SrcAcc | DstImmUByte, out, check_perm_out),
/* 0xE8 - 0xEF */
D(SrcImm | Stack), D(SrcImm | ImplicitOps),
- D(SrcImmFAddr | No64), D(SrcImmByte | ImplicitOps),
+ I(SrcImmFAddr | No64, em_jmp_far), D(SrcImmByte | ImplicitOps),
D2bvIP(SrcDX | DstAcc, in, check_perm_in),
D2bvIP(SrcAcc | DstDX, out, check_perm_out),
/* 0xF0 - 0xF7 */
@@ -3221,14 +3193,16 @@ static struct opcode opcode_table[256] = {
DI(ImplicitOps | Priv, hlt), D(ImplicitOps),
G(ByteOp, group3), G(0, group3),
/* 0xF8 - 0xFF */
- D(ImplicitOps), D(ImplicitOps), D(ImplicitOps), D(ImplicitOps),
+ D(ImplicitOps), D(ImplicitOps),
+ I(ImplicitOps, em_cli), I(ImplicitOps, em_sti),
D(ImplicitOps), D(ImplicitOps), G(0, group4), G(0, group5),
};
static struct opcode twobyte_table[256] = {
/* 0x00 - 0x0F */
G(0, group6), GD(0, &group7), N, N,
- N, D(ImplicitOps | VendorSpecific), DI(ImplicitOps | Priv, clts), N,
+ N, I(ImplicitOps | VendorSpecific, em_syscall),
+ II(ImplicitOps | Priv, em_clts, clts), N,
DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
N, D(ImplicitOps | ModRM), N, N,
/* 0x10 - 0x1F */
@@ -3245,7 +3219,8 @@ static struct opcode twobyte_table[256] = {
IIP(ImplicitOps, em_rdtsc, rdtsc, check_rdtsc),
DI(ImplicitOps | Priv, rdmsr),
DIP(ImplicitOps | Priv, rdpmc, check_rdpmc),
- D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv | VendorSpecific),
+ I(ImplicitOps | VendorSpecific, em_sysenter),
+ I(ImplicitOps | Priv | VendorSpecific, em_sysexit),
N, N,
N, N, N, N, N, N, N, N,
/* 0x40 - 0x4F */
@@ -3313,11 +3288,11 @@ static struct opcode twobyte_table[256] = {
#undef I2bv
#undef I6ALU
-static unsigned imm_size(struct decode_cache *c)
+static unsigned imm_size(struct x86_emulate_ctxt *ctxt)
{
unsigned size;
- size = (c->d & ByteOp) ? 1 : c->op_bytes;
+ size = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
if (size == 8)
size = 4;
return size;
@@ -3326,23 +3301,21 @@ static unsigned imm_size(struct decode_cache *c)
static int decode_imm(struct x86_emulate_ctxt *ctxt, struct operand *op,
unsigned size, bool sign_extension)
{
- struct decode_cache *c = &ctxt->decode;
- struct x86_emulate_ops *ops = ctxt->ops;
int rc = X86EMUL_CONTINUE;
op->type = OP_IMM;
op->bytes = size;
- op->addr.mem.ea = c->eip;
+ op->addr.mem.ea = ctxt->_eip;
/* NB. Immediates are sign-extended as necessary. */
switch (op->bytes) {
case 1:
- op->val = insn_fetch(s8, 1, c->eip);
+ op->val = insn_fetch(s8, 1, ctxt->_eip);
break;
case 2:
- op->val = insn_fetch(s16, 2, c->eip);
+ op->val = insn_fetch(s16, 2, ctxt->_eip);
break;
case 4:
- op->val = insn_fetch(s32, 4, c->eip);
+ op->val = insn_fetch(s32, 4, ctxt->_eip);
break;
}
if (!sign_extension) {
@@ -3362,11 +3335,8 @@ done:
return rc;
}
-int
-x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
{
- struct x86_emulate_ops *ops = ctxt->ops;
- struct decode_cache *c = &ctxt->decode;
int rc = X86EMUL_CONTINUE;
int mode = ctxt->mode;
int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
@@ -3374,11 +3344,11 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
struct opcode opcode;
struct operand memop = { .type = OP_NONE }, *memopp = NULL;
- c->eip = ctxt->eip;
- c->fetch.start = c->eip;
- c->fetch.end = c->fetch.start + insn_len;
+ ctxt->_eip = ctxt->eip;
+ ctxt->fetch.start = ctxt->_eip;
+ ctxt->fetch.end = ctxt->fetch.start + insn_len;
if (insn_len > 0)
- memcpy(c->fetch.data, insn, insn_len);
+ memcpy(ctxt->fetch.data, insn, insn_len);
switch (mode) {
case X86EMUL_MODE_REAL:
@@ -3399,46 +3369,46 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
return -1;
}
- c->op_bytes = def_op_bytes;
- c->ad_bytes = def_ad_bytes;
+ ctxt->op_bytes = def_op_bytes;
+ ctxt->ad_bytes = def_ad_bytes;
/* Legacy prefixes. */
for (;;) {
- switch (c->b = insn_fetch(u8, 1, c->eip)) {
+ switch (ctxt->b = insn_fetch(u8, 1, ctxt->_eip)) {
case 0x66: /* operand-size override */
op_prefix = true;
/* switch between 2/4 bytes */
- c->op_bytes = def_op_bytes ^ 6;
+ ctxt->op_bytes = def_op_bytes ^ 6;
break;
case 0x67: /* address-size override */
if (mode == X86EMUL_MODE_PROT64)
/* switch between 4/8 bytes */
- c->ad_bytes = def_ad_bytes ^ 12;
+ ctxt->ad_bytes = def_ad_bytes ^ 12;
else
/* switch between 2/4 bytes */
- c->ad_bytes = def_ad_bytes ^ 6;
+ ctxt->ad_bytes = def_ad_bytes ^ 6;
break;
case 0x26: /* ES override */
case 0x2e: /* CS override */
case 0x36: /* SS override */
case 0x3e: /* DS override */
- set_seg_override(c, (c->b >> 3) & 3);
+ set_seg_override(ctxt, (ctxt->b >> 3) & 3);
break;
case 0x64: /* FS override */
case 0x65: /* GS override */
- set_seg_override(c, c->b & 7);
+ set_seg_override(ctxt, ctxt->b & 7);
break;
case 0x40 ... 0x4f: /* REX */
if (mode != X86EMUL_MODE_PROT64)
goto done_prefixes;
- c->rex_prefix = c->b;
+ ctxt->rex_prefix = ctxt->b;
continue;
case 0xf0: /* LOCK */
- c->lock_prefix = 1;
+ ctxt->lock_prefix = 1;
break;
case 0xf2: /* REPNE/REPNZ */
case 0xf3: /* REP/REPE/REPZ */
- c->rep_prefix = c->b;
+ ctxt->rep_prefix = ctxt->b;
break;
default:
goto done_prefixes;
@@ -3446,50 +3416,50 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
/* Any legacy prefix after a REX prefix nullifies its effect. */
- c->rex_prefix = 0;
+ ctxt->rex_prefix = 0;
}
done_prefixes:
/* REX prefix. */
- if (c->rex_prefix & 8)
- c->op_bytes = 8; /* REX.W */
+ if (ctxt->rex_prefix & 8)
+ ctxt->op_bytes = 8; /* REX.W */
/* Opcode byte(s). */
- opcode = opcode_table[c->b];
+ opcode = opcode_table[ctxt->b];
/* Two-byte opcode? */
- if (c->b == 0x0f) {
- c->twobyte = 1;
- c->b = insn_fetch(u8, 1, c->eip);
- opcode = twobyte_table[c->b];
+ if (ctxt->b == 0x0f) {
+ ctxt->twobyte = 1;
+ ctxt->b = insn_fetch(u8, 1, ctxt->_eip);
+ opcode = twobyte_table[ctxt->b];
}
- c->d = opcode.flags;
+ ctxt->d = opcode.flags;
- while (c->d & GroupMask) {
- switch (c->d & GroupMask) {
+ while (ctxt->d & GroupMask) {
+ switch (ctxt->d & GroupMask) {
case Group:
- c->modrm = insn_fetch(u8, 1, c->eip);
- --c->eip;
- goffset = (c->modrm >> 3) & 7;
+ ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+ --ctxt->_eip;
+ goffset = (ctxt->modrm >> 3) & 7;
opcode = opcode.u.group[goffset];
break;
case GroupDual:
- c->modrm = insn_fetch(u8, 1, c->eip);
- --c->eip;
- goffset = (c->modrm >> 3) & 7;
- if ((c->modrm >> 6) == 3)
+ ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+ --ctxt->_eip;
+ goffset = (ctxt->modrm >> 3) & 7;
+ if ((ctxt->modrm >> 6) == 3)
opcode = opcode.u.gdual->mod3[goffset];
else
opcode = opcode.u.gdual->mod012[goffset];
break;
case RMExt:
- goffset = c->modrm & 7;
+ goffset = ctxt->modrm & 7;
opcode = opcode.u.group[goffset];
break;
case Prefix:
- if (c->rep_prefix && op_prefix)
+ if (ctxt->rep_prefix && op_prefix)
return X86EMUL_UNHANDLEABLE;
- simd_prefix = op_prefix ? 0x66 : c->rep_prefix;
+ simd_prefix = op_prefix ? 0x66 : ctxt->rep_prefix;
switch (simd_prefix) {
case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
case 0x66: opcode = opcode.u.gprefix->pfx_66; break;
@@ -3501,61 +3471,61 @@ done_prefixes:
return X86EMUL_UNHANDLEABLE;
}
- c->d &= ~GroupMask;
- c->d |= opcode.flags;
+ ctxt->d &= ~GroupMask;
+ ctxt->d |= opcode.flags;
}
- c->execute = opcode.u.execute;
- c->check_perm = opcode.check_perm;
- c->intercept = opcode.intercept;
+ ctxt->execute = opcode.u.execute;
+ ctxt->check_perm = opcode.check_perm;
+ ctxt->intercept = opcode.intercept;
/* Unrecognised? */
- if (c->d == 0 || (c->d & Undefined))
+ if (ctxt->d == 0 || (ctxt->d & Undefined))
return -1;
- if (!(c->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
+ if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
return -1;
- if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
- c->op_bytes = 8;
+ if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
+ ctxt->op_bytes = 8;
- if (c->d & Op3264) {
+ if (ctxt->d & Op3264) {
if (mode == X86EMUL_MODE_PROT64)
- c->op_bytes = 8;
+ ctxt->op_bytes = 8;
else
- c->op_bytes = 4;
+ ctxt->op_bytes = 4;
}
- if (c->d & Sse)
- c->op_bytes = 16;
+ if (ctxt->d & Sse)
+ ctxt->op_bytes = 16;
/* ModRM and SIB bytes. */
- if (c->d & ModRM) {
- rc = decode_modrm(ctxt, ops, &memop);
- if (!c->has_seg_override)
- set_seg_override(c, c->modrm_seg);
- } else if (c->d & MemAbs)
- rc = decode_abs(ctxt, ops, &memop);
+ if (ctxt->d & ModRM) {
+ rc = decode_modrm(ctxt, &memop);
+ if (!ctxt->has_seg_override)
+ set_seg_override(ctxt, ctxt->modrm_seg);
+ } else if (ctxt->d & MemAbs)
+ rc = decode_abs(ctxt, &memop);
if (rc != X86EMUL_CONTINUE)
goto done;
- if (!c->has_seg_override)
- set_seg_override(c, VCPU_SREG_DS);
+ if (!ctxt->has_seg_override)
+ set_seg_override(ctxt, VCPU_SREG_DS);
- memop.addr.mem.seg = seg_override(ctxt, c);
+ memop.addr.mem.seg = seg_override(ctxt);
- if (memop.type == OP_MEM && c->ad_bytes != 8)
+ if (memop.type == OP_MEM && ctxt->ad_bytes != 8)
memop.addr.mem.ea = (u32)memop.addr.mem.ea;
/*
* Decode and fetch the source operand: register, memory
* or immediate.
*/
- switch (c->d & SrcMask) {
+ switch (ctxt->d & SrcMask) {
case SrcNone:
break;
case SrcReg:
- decode_register_operand(ctxt, &c->src, c, 0);
+ decode_register_operand(ctxt, &ctxt->src, 0);
break;
case SrcMem16:
memop.bytes = 2;
@@ -3564,60 +3534,60 @@ done_prefixes:
memop.bytes = 4;
goto srcmem_common;
case SrcMem:
- memop.bytes = (c->d & ByteOp) ? 1 :
- c->op_bytes;
+ memop.bytes = (ctxt->d & ByteOp) ? 1 :
+ ctxt->op_bytes;
srcmem_common:
- c->src = memop;
- memopp = &c->src;
+ ctxt->src = memop;
+ memopp = &ctxt->src;
break;
case SrcImmU16:
- rc = decode_imm(ctxt, &c->src, 2, false);
+ rc = decode_imm(ctxt, &ctxt->src, 2, false);
break;
case SrcImm:
- rc = decode_imm(ctxt, &c->src, imm_size(c), true);
+ rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), true);
break;
case SrcImmU:
- rc = decode_imm(ctxt, &c->src, imm_size(c), false);
+ rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), false);
break;
case SrcImmByte:
- rc = decode_imm(ctxt, &c->src, 1, true);
+ rc = decode_imm(ctxt, &ctxt->src, 1, true);
break;
case SrcImmUByte:
- rc = decode_imm(ctxt, &c->src, 1, false);
+ rc = decode_imm(ctxt, &ctxt->src, 1, false);
break;
case SrcAcc:
- c->src.type = OP_REG;
- c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
- c->src.addr.reg = &c->regs[VCPU_REGS_RAX];
- fetch_register_operand(&c->src);
+ 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:
- c->src.bytes = 1;
- c->src.val = 1;
+ ctxt->src.bytes = 1;
+ ctxt->src.val = 1;
break;
case SrcSI:
- c->src.type = OP_MEM;
- c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
- c->src.addr.mem.ea =
- register_address(c, c->regs[VCPU_REGS_RSI]);
- c->src.addr.mem.seg = seg_override(ctxt, c);
- c->src.val = 0;
+ 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:
- c->src.type = OP_IMM;
- c->src.addr.mem.ea = c->eip;
- c->src.bytes = c->op_bytes + 2;
- insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip);
+ 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 = c->op_bytes + 2;
+ memop.bytes = ctxt->op_bytes + 2;
goto srcmem_common;
break;
case SrcDX:
- c->src.type = OP_REG;
- c->src.bytes = 2;
- c->src.addr.reg = &c->regs[VCPU_REGS_RDX];
- fetch_register_operand(&c->src);
+ ctxt->src.type = OP_REG;
+ ctxt->src.bytes = 2;
+ ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+ fetch_register_operand(&ctxt->src);
break;
}
@@ -3628,22 +3598,22 @@ done_prefixes:
* Decode and fetch the second source operand: register, memory
* or immediate.
*/
- switch (c->d & Src2Mask) {
+ switch (ctxt->d & Src2Mask) {
case Src2None:
break;
case Src2CL:
- c->src2.bytes = 1;
- c->src2.val = c->regs[VCPU_REGS_RCX] & 0x8;
+ ctxt->src2.bytes = 1;
+ ctxt->src2.val = ctxt->regs[VCPU_REGS_RCX] & 0x8;
break;
case Src2ImmByte:
- rc = decode_imm(ctxt, &c->src2, 1, true);
+ rc = decode_imm(ctxt, &ctxt->src2, 1, true);
break;
case Src2One:
- c->src2.bytes = 1;
- c->src2.val = 1;
+ ctxt->src2.bytes = 1;
+ ctxt->src2.val = 1;
break;
case Src2Imm:
- rc = decode_imm(ctxt, &c->src2, imm_size(c), true);
+ rc = decode_imm(ctxt, &ctxt->src2, imm_size(ctxt), true);
break;
}
@@ -3651,68 +3621,66 @@ done_prefixes:
goto done;
/* Decode and fetch the destination operand: register or memory. */
- switch (c->d & DstMask) {
+ switch (ctxt->d & DstMask) {
case DstReg:
- decode_register_operand(ctxt, &c->dst, c,
- c->twobyte && (c->b == 0xb6 || c->b == 0xb7));
+ decode_register_operand(ctxt, &ctxt->dst,
+ ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
break;
case DstImmUByte:
- c->dst.type = OP_IMM;
- c->dst.addr.mem.ea = c->eip;
- c->dst.bytes = 1;
- c->dst.val = insn_fetch(u8, 1, c->eip);
+ 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:
- c->dst = memop;
- memopp = &c->dst;
- if ((c->d & DstMask) == DstMem64)
- c->dst.bytes = 8;
+ ctxt->dst = memop;
+ memopp = &ctxt->dst;
+ if ((ctxt->d & DstMask) == DstMem64)
+ ctxt->dst.bytes = 8;
else
- c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
- if (c->d & BitOp)
- fetch_bit_operand(c);
- c->dst.orig_val = c->dst.val;
+ 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:
- c->dst.type = OP_REG;
- c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
- c->dst.addr.reg = &c->regs[VCPU_REGS_RAX];
- fetch_register_operand(&c->dst);
- c->dst.orig_val = c->dst.val;
+ 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:
- c->dst.type = OP_MEM;
- c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
- c->dst.addr.mem.ea =
- register_address(c, c->regs[VCPU_REGS_RDI]);
- c->dst.addr.mem.seg = VCPU_SREG_ES;
- c->dst.val = 0;
+ 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:
- c->dst.type = OP_REG;
- c->dst.bytes = 2;
- c->dst.addr.reg = &c->regs[VCPU_REGS_RDX];
- fetch_register_operand(&c->dst);
+ 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:
- c->dst.type = OP_NONE; /* Disable writeback. */
+ ctxt->dst.type = OP_NONE; /* Disable writeback. */
break;
}
done:
- if (memopp && memopp->type == OP_MEM && c->rip_relative)
- memopp->addr.mem.ea += c->eip;
+ if (memopp && memopp->type == OP_MEM && ctxt->rip_relative)
+ memopp->addr.mem.ea += ctxt->_eip;
return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
}
static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
{
- struct decode_cache *c = &ctxt->decode;
-
/* The second termination condition only applies for REPE
* and REPNE. Test if the repeat string operation prefix is
* REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
@@ -3720,304 +3688,232 @@ static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
* - if REPE/REPZ and ZF = 0 then done
* - if REPNE/REPNZ and ZF = 1 then done
*/
- if (((c->b == 0xa6) || (c->b == 0xa7) ||
- (c->b == 0xae) || (c->b == 0xaf))
- && (((c->rep_prefix == REPE_PREFIX) &&
+ if (((ctxt->b == 0xa6) || (ctxt->b == 0xa7) ||
+ (ctxt->b == 0xae) || (ctxt->b == 0xaf))
+ && (((ctxt->rep_prefix == REPE_PREFIX) &&
((ctxt->eflags & EFLG_ZF) == 0))
- || ((c->rep_prefix == REPNE_PREFIX) &&
+ || ((ctxt->rep_prefix == REPNE_PREFIX) &&
((ctxt->eflags & EFLG_ZF) == EFLG_ZF))))
return true;
return false;
}
-int
-x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
+int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
{
struct x86_emulate_ops *ops = ctxt->ops;
u64 msr_data;
- struct decode_cache *c = &ctxt->decode;
int rc = X86EMUL_CONTINUE;
- int saved_dst_type = c->dst.type;
- int irq; /* Used for int 3, int, and into */
+ int saved_dst_type = ctxt->dst.type;
- ctxt->decode.mem_read.pos = 0;
+ ctxt->mem_read.pos = 0;
- if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
+ if (ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) {
rc = emulate_ud(ctxt);
goto done;
}
/* LOCK prefix is allowed only with some instructions */
- if (c->lock_prefix && (!(c->d & Lock) || c->dst.type != OP_MEM)) {
+ if (ctxt->lock_prefix && (!(ctxt->d & Lock) || ctxt->dst.type != OP_MEM)) {
rc = emulate_ud(ctxt);
goto done;
}
- if ((c->d & SrcMask) == SrcMemFAddr && c->src.type != OP_MEM) {
+ if ((ctxt->d & SrcMask) == SrcMemFAddr && ctxt->src.type != OP_MEM) {
rc = emulate_ud(ctxt);
goto done;
}
- if ((c->d & Sse)
+ if ((ctxt->d & Sse)
&& ((ops->get_cr(ctxt, 0) & X86_CR0_EM)
|| !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
rc = emulate_ud(ctxt);
goto done;
}
- if ((c->d & Sse) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
+ if ((ctxt->d & Sse) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
rc = emulate_nm(ctxt);
goto done;
}
- if (unlikely(ctxt->guest_mode) && c->intercept) {
- rc = emulator_check_intercept(ctxt, c->intercept,
+ if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+ rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_PRE_EXCEPT);
if (rc != X86EMUL_CONTINUE)
goto done;
}
/* Privileged instruction can be executed only in CPL=0 */
- if ((c->d & Priv) && ops->cpl(ctxt)) {
+ if ((ctxt->d & Priv) && ops->cpl(ctxt)) {
rc = emulate_gp(ctxt, 0);
goto done;
}
/* Instruction can only be executed in protected mode */
- if ((c->d & Prot) && !(ctxt->mode & X86EMUL_MODE_PROT)) {
+ if ((ctxt->d & Prot) && !(ctxt->mode & X86EMUL_MODE_PROT)) {
rc = emulate_ud(ctxt);
goto done;
}
/* Do instruction specific permission checks */
- if (c->check_perm) {
- rc = c->check_perm(ctxt);
+ if (ctxt->check_perm) {
+ rc = ctxt->check_perm(ctxt);
if (rc != X86EMUL_CONTINUE)
goto done;
}
- if (unlikely(ctxt->guest_mode) && c->intercept) {
- rc = emulator_check_intercept(ctxt, c->intercept,
+ if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+ rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_POST_EXCEPT);
if (rc != X86EMUL_CONTINUE)
goto done;
}
- if (c->rep_prefix && (c->d & String)) {
+ if (ctxt->rep_prefix && (ctxt->d & String)) {
/* All REP prefixes have the same first termination condition */
- if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) {
- ctxt->eip = c->eip;
+ if (address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) == 0) {
+ ctxt->eip = ctxt->_eip;
goto done;
}
}
- if ((c->src.type == OP_MEM) && !(c->d & NoAccess)) {
- rc = segmented_read(ctxt, c->src.addr.mem,
- c->src.valptr, c->src.bytes);
+ if ((ctxt->src.type == OP_MEM) && !(ctxt->d & NoAccess)) {
+ rc = segmented_read(ctxt, ctxt->src.addr.mem,
+ ctxt->src.valptr, ctxt->src.bytes);
if (rc != X86EMUL_CONTINUE)
goto done;
- c->src.orig_val64 = c->src.val64;
+ ctxt->src.orig_val64 = ctxt->src.val64;
}
- if (c->src2.type == OP_MEM) {
- rc = segmented_read(ctxt, c->src2.addr.mem,
- &c->src2.val, c->src2.bytes);
+ if (ctxt->src2.type == OP_MEM) {
+ rc = segmented_read(ctxt, ctxt->src2.addr.mem,
+ &ctxt->src2.val, ctxt->src2.bytes);
if (rc != X86EMUL_CONTINUE)
goto done;
}
- if ((c->d & DstMask) == ImplicitOps)
+ if ((ctxt->d & DstMask) == ImplicitOps)
goto special_insn;
- if ((c->dst.type == OP_MEM) && !(c->d & Mov)) {
+ if ((ctxt->dst.type == OP_MEM) && !(ctxt->d & Mov)) {
/* optimisation - avoid slow emulated read if Mov */
- rc = segmented_read(ctxt, c->dst.addr.mem,
- &c->dst.val, c->dst.bytes);
+ rc = segmented_read(ctxt, ctxt->dst.addr.mem,
+ &ctxt->dst.val, ctxt->dst.bytes);
if (rc != X86EMUL_CONTINUE)
goto done;
}
- c->dst.orig_val = c->dst.val;
+ ctxt->dst.orig_val = ctxt->dst.val;
special_insn:
- if (unlikely(ctxt->guest_mode) && c->intercept) {
- rc = emulator_check_intercept(ctxt, c->intercept,
+ if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+ rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_POST_MEMACCESS);
if (rc != X86EMUL_CONTINUE)
goto done;
}
- if (c->execute) {
- rc = c->execute(ctxt);
+ if (ctxt->execute) {
+ rc = ctxt->execute(ctxt);
if (rc != X86EMUL_CONTINUE)
goto done;
goto writeback;
}
- if (c->twobyte)
+ if (ctxt->twobyte)
goto twobyte_insn;
- switch (c->b) {
+ switch (ctxt->b) {
case 0x06: /* push es */
- rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_ES);
+ rc = emulate_push_sreg(ctxt, VCPU_SREG_ES);
break;
case 0x07: /* pop es */
- rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES);
+ rc = emulate_pop_sreg(ctxt, VCPU_SREG_ES);
break;
case 0x0e: /* push cs */
- rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_CS);
+ rc = emulate_push_sreg(ctxt, VCPU_SREG_CS);
break;
case 0x16: /* push ss */
- rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_SS);
+ rc = emulate_push_sreg(ctxt, VCPU_SREG_SS);
break;
case 0x17: /* pop ss */
- rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS);
+ rc = emulate_pop_sreg(ctxt, VCPU_SREG_SS);
break;
case 0x1e: /* push ds */
- rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_DS);
+ rc = emulate_push_sreg(ctxt, VCPU_SREG_DS);
break;
case 0x1f: /* pop ds */
- rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS);
+ rc = emulate_pop_sreg(ctxt, VCPU_SREG_DS);
break;
case 0x40 ... 0x47: /* inc r16/r32 */
- emulate_1op("inc", c->dst, ctxt->eflags);
+ emulate_1op("inc", ctxt->dst, ctxt->eflags);
break;
case 0x48 ... 0x4f: /* dec r16/r32 */
- emulate_1op("dec", c->dst, ctxt->eflags);
+ emulate_1op("dec", ctxt->dst, ctxt->eflags);
break;
case 0x63: /* movsxd */
if (ctxt->mode != X86EMUL_MODE_PROT64)
goto cannot_emulate;
- c->dst.val = (s32) c->src.val;
+ ctxt->dst.val = (s32) ctxt->src.val;
break;
case 0x6c: /* insb */
case 0x6d: /* insw/insd */
- c->src.val = c->regs[VCPU_REGS_RDX];
+ ctxt->src.val = ctxt->regs[VCPU_REGS_RDX];
goto do_io_in;
case 0x6e: /* outsb */
case 0x6f: /* outsw/outsd */
- c->dst.val = c->regs[VCPU_REGS_RDX];
+ ctxt->dst.val = ctxt->regs[VCPU_REGS_RDX];
goto do_io_out;
break;
case 0x70 ... 0x7f: /* jcc (short) */
- if (test_cc(c->b, ctxt->eflags))
- jmp_rel(c, c->src.val);
- break;
- case 0x84 ... 0x85:
- test:
- emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags);
- break;
- case 0x86 ... 0x87: /* xchg */
- xchg:
- /* Write back the register source. */
- c->src.val = c->dst.val;
- write_register_operand(&c->src);
- /*
- * Write back the memory destination with implicit LOCK
- * prefix.
- */
- c->dst.val = c->src.orig_val;
- c->lock_prefix = 1;
- break;
- case 0x8c: /* mov r/m, sreg */
- if (c->modrm_reg > VCPU_SREG_GS) {
- rc = emulate_ud(ctxt);
- goto done;
- }
- c->dst.val = get_segment_selector(ctxt, c->modrm_reg);
+ if (test_cc(ctxt->b, ctxt->eflags))
+ jmp_rel(ctxt, ctxt->src.val);
break;
case 0x8d: /* lea r16/r32, m */
- c->dst.val = c->src.addr.mem.ea;
+ ctxt->dst.val = ctxt->src.addr.mem.ea;
break;
- case 0x8e: { /* mov seg, r/m16 */
- uint16_t sel;
-
- sel = c->src.val;
-
- if (c->modrm_reg == VCPU_SREG_CS ||
- c->modrm_reg > VCPU_SREG_GS) {
- rc = emulate_ud(ctxt);
- goto done;
- }
-
- if (c->modrm_reg == VCPU_SREG_SS)
- ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS;
-
- rc = load_segment_descriptor(ctxt, ops, sel, c->modrm_reg);
-
- c->dst.type = OP_NONE; /* Disable writeback. */
- break;
- }
case 0x8f: /* pop (sole member of Grp1a) */
rc = em_grp1a(ctxt);
break;
case 0x90 ... 0x97: /* nop / xchg reg, rax */
- if (c->dst.addr.reg == &c->regs[VCPU_REGS_RAX])
+ if (ctxt->dst.addr.reg == &ctxt->regs[VCPU_REGS_RAX])
break;
- goto xchg;
+ rc = em_xchg(ctxt);
+ break;
case 0x98: /* cbw/cwde/cdqe */
- switch (c->op_bytes) {
- case 2: c->dst.val = (s8)c->dst.val; break;
- case 4: c->dst.val = (s16)c->dst.val; break;
- case 8: c->dst.val = (s32)c->dst.val; break;
+ switch (ctxt->op_bytes) {
+ case 2: ctxt->dst.val = (s8)ctxt->dst.val; break;
+ case 4: ctxt->dst.val = (s16)ctxt->dst.val; break;
+ case 8: ctxt->dst.val = (s32)ctxt->dst.val; break;
}
break;
- case 0xa8 ... 0xa9: /* test ax, imm */
- goto test;
case 0xc0 ... 0xc1:
rc = em_grp2(ctxt);
break;
- case 0xc3: /* ret */
- c->dst.type = OP_REG;
- c->dst.addr.reg = &c->eip;
- c->dst.bytes = c->op_bytes;
- rc = em_pop(ctxt);
- break;
case 0xc4: /* les */
- rc = emulate_load_segment(ctxt, ops, VCPU_SREG_ES);
+ rc = emulate_load_segment(ctxt, VCPU_SREG_ES);
break;
case 0xc5: /* lds */
- rc = emulate_load_segment(ctxt, ops, VCPU_SREG_DS);
- break;
- case 0xcb: /* ret far */
- rc = emulate_ret_far(ctxt, ops);
+ rc = emulate_load_segment(ctxt, VCPU_SREG_DS);
break;
case 0xcc: /* int3 */
- irq = 3;
- goto do_interrupt;
+ rc = emulate_int(ctxt, 3);
+ break;
case 0xcd: /* int n */
- irq = c->src.val;
- do_interrupt:
- rc = emulate_int(ctxt, ops, irq);
+ rc = emulate_int(ctxt, ctxt->src.val);
break;
case 0xce: /* into */
- if (ctxt->eflags & EFLG_OF) {
- irq = 4;
- goto do_interrupt;
- }
- break;
- case 0xcf: /* iret */
- rc = emulate_iret(ctxt, ops);
+ if (ctxt->eflags & EFLG_OF)
+ rc = emulate_int(ctxt, 4);
break;
case 0xd0 ... 0xd1: /* Grp2 */
rc = em_grp2(ctxt);
break;
case 0xd2 ... 0xd3: /* Grp2 */
- c->src.val = c->regs[VCPU_REGS_RCX];
+ ctxt->src.val = ctxt->regs[VCPU_REGS_RCX];
rc = em_grp2(ctxt);
break;
- case 0xe0 ... 0xe2: /* loop/loopz/loopnz */
- register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1);
- if (address_mask(c, c->regs[VCPU_REGS_RCX]) != 0 &&
- (c->b == 0xe2 || test_cc(c->b ^ 0x5, ctxt->eflags)))
- jmp_rel(c, c->src.val);
- break;
- case 0xe3: /* jcxz/jecxz/jrcxz */
- if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0)
- jmp_rel(c, c->src.val);
- break;
case 0xe4: /* inb */
case 0xe5: /* in */
goto do_io_in;
@@ -4025,35 +3921,30 @@ special_insn:
case 0xe7: /* out */
goto do_io_out;
case 0xe8: /* call (near) */ {
- long int rel = c->src.val;
- c->src.val = (unsigned long) c->eip;
- jmp_rel(c, rel);
+ long int rel = ctxt->src.val;
+ ctxt->src.val = (unsigned long) ctxt->_eip;
+ jmp_rel(ctxt, rel);
rc = em_push(ctxt);
break;
}
case 0xe9: /* jmp rel */
- goto jmp;
- case 0xea: /* jmp far */
- rc = em_jmp_far(ctxt);
- break;
- case 0xeb:
- jmp: /* jmp rel short */
- jmp_rel(c, c->src.val);
- c->dst.type = OP_NONE; /* Disable writeback. */
+ case 0xeb: /* jmp rel short */
+ jmp_rel(ctxt, ctxt->src.val);
+ ctxt->dst.type = OP_NONE; /* Disable writeback. */
break;
case 0xec: /* in al,dx */
case 0xed: /* in (e/r)ax,dx */
do_io_in:
- if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val,
- &c->dst.val))
+ if (!pio_in_emulated(ctxt, ctxt->dst.bytes, ctxt->src.val,
+ &ctxt->dst.val))
goto done; /* IO is needed */
break;
case 0xee: /* out dx,al */
case 0xef: /* out dx,(e/r)ax */
do_io_out:
- ops->pio_out_emulated(ctxt, c->src.bytes, c->dst.val,
- &c->src.val, 1);
- c->dst.type = OP_NONE; /* Disable writeback. */
+ ops->pio_out_emulated(ctxt, ctxt->src.bytes, ctxt->dst.val,
+ &ctxt->src.val, 1);
+ ctxt->dst.type = OP_NONE; /* Disable writeback. */
break;
case 0xf4: /* hlt */
ctxt->ops->halt(ctxt);
@@ -4071,22 +3962,6 @@ special_insn:
case 0xf9: /* stc */
ctxt->eflags |= EFLG_CF;
break;
- case 0xfa: /* cli */
- if (emulator_bad_iopl(ctxt, ops)) {
- rc = emulate_gp(ctxt, 0);
- goto done;
- } else
- ctxt->eflags &= ~X86_EFLAGS_IF;
- break;
- case 0xfb: /* sti */
- if (emulator_bad_iopl(ctxt, ops)) {
- rc = emulate_gp(ctxt, 0);
- goto done;
- } else {
- ctxt->interruptibility = KVM_X86_SHADOW_INT_STI;
- ctxt->eflags |= X86_EFLAGS_IF;
- }
- break;
case 0xfc: /* cld */
ctxt->eflags &= ~EFLG_DF;
break;
@@ -4115,40 +3990,40 @@ writeback:
* restore dst type in case the decoding will be reused
* (happens for string instruction )
*/
- c->dst.type = saved_dst_type;
+ ctxt->dst.type = saved_dst_type;
- if ((c->d & SrcMask) == SrcSI)
- string_addr_inc(ctxt, seg_override(ctxt, c),
- VCPU_REGS_RSI, &c->src);
+ if ((ctxt->d & SrcMask) == SrcSI)
+ string_addr_inc(ctxt, seg_override(ctxt),
+ VCPU_REGS_RSI, &ctxt->src);
- if ((c->d & DstMask) == DstDI)
+ if ((ctxt->d & DstMask) == DstDI)
string_addr_inc(ctxt, VCPU_SREG_ES, VCPU_REGS_RDI,
- &c->dst);
+ &ctxt->dst);
- if (c->rep_prefix && (c->d & String)) {
- struct read_cache *r = &ctxt->decode.io_read;
- register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1);
+ if (ctxt->rep_prefix && (ctxt->d & String)) {
+ struct read_cache *r = &ctxt->io_read;
+ register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RCX], -1);
if (!string_insn_completed(ctxt)) {
/*
* Re-enter guest when pio read ahead buffer is empty
* or, if it is not used, after each 1024 iteration.
*/
- if ((r->end != 0 || c->regs[VCPU_REGS_RCX] & 0x3ff) &&
+ if ((r->end != 0 || ctxt->regs[VCPU_REGS_RCX] & 0x3ff) &&
(r->end == 0 || r->end != r->pos)) {
/*
* Reset read cache. Usually happens before
* decode, but since instruction is restarted
* we have to do it here.
*/
- ctxt->decode.mem_read.end = 0;
+ ctxt->mem_read.end = 0;
return EMULATION_RESTART;
}
goto done; /* skip rip writeback */
}
}
- ctxt->eip = c->eip;
+ ctxt->eip = ctxt->_eip;
done:
if (rc == X86EMUL_PROPAGATE_FAULT)
@@ -4159,13 +4034,7 @@ done:
return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
twobyte_insn:
- switch (c->b) {
- case 0x05: /* syscall */
- rc = emulate_syscall(ctxt, ops);
- break;
- case 0x06:
- rc = em_clts(ctxt);
- break;
+ switch (ctxt->b) {
case 0x09: /* wbinvd */
(ctxt->ops->wbinvd)(ctxt);
break;
@@ -4174,21 +4043,21 @@ twobyte_insn:
case 0x18: /* Grp16 (prefetch/nop) */
break;
case 0x20: /* mov cr, reg */
- c->dst.val = ops->get_cr(ctxt, c->modrm_reg);
+ ctxt->dst.val = ops->get_cr(ctxt, ctxt->modrm_reg);
break;
case 0x21: /* mov from dr to reg */
- ops->get_dr(ctxt, c->modrm_reg, &c->dst.val);
+ ops->get_dr(ctxt, ctxt->modrm_reg, &ctxt->dst.val);
break;
case 0x22: /* mov reg, cr */
- if (ops->set_cr(ctxt, c->modrm_reg, c->src.val)) {
+ if (ops->set_cr(ctxt, ctxt->modrm_reg, ctxt->src.val)) {
emulate_gp(ctxt, 0);
rc = X86EMUL_PROPAGATE_FAULT;
goto done;
}
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
break;
case 0x23: /* mov from reg to dr */
- if (ops->set_dr(ctxt, c->modrm_reg, c->src.val &
+ if (ops->set_dr(ctxt, ctxt->modrm_reg, ctxt->src.val &
((ctxt->mode == X86EMUL_MODE_PROT64) ?
~0ULL : ~0U)) < 0) {
/* #UD condition is already handled by the code above */
@@ -4197,13 +4066,13 @@ twobyte_insn:
goto done;
}
- c->dst.type = OP_NONE; /* no writeback */
+ ctxt->dst.type = OP_NONE; /* no writeback */
break;
case 0x30:
/* wrmsr */
- msr_data = (u32)c->regs[VCPU_REGS_RAX]
- | ((u64)c->regs[VCPU_REGS_RDX] << 32);
- if (ops->set_msr(ctxt, c->regs[VCPU_REGS_RCX], msr_data)) {
+ msr_data = (u32)ctxt->regs[VCPU_REGS_RAX]
+ | ((u64)ctxt->regs[VCPU_REGS_RDX] << 32);
+ if (ops->set_msr(ctxt, ctxt->regs[VCPU_REGS_RCX], msr_data)) {
emulate_gp(ctxt, 0);
rc = X86EMUL_PROPAGATE_FAULT;
goto done;
@@ -4212,64 +4081,58 @@ twobyte_insn:
break;
case 0x32:
/* rdmsr */
- if (ops->get_msr(ctxt, c->regs[VCPU_REGS_RCX], &msr_data)) {
+ if (ops->get_msr(ctxt, ctxt->regs[VCPU_REGS_RCX], &msr_data)) {
emulate_gp(ctxt, 0);
rc = X86EMUL_PROPAGATE_FAULT;
goto done;
} else {
- c->regs[VCPU_REGS_RAX] = (u32)msr_data;
- c->regs[VCPU_REGS_RDX] = msr_data >> 32;
+ ctxt->regs[VCPU_REGS_RAX] = (u32)msr_data;
+ ctxt->regs[VCPU_REGS_RDX] = msr_data >> 32;
}
rc = X86EMUL_CONTINUE;
break;
- case 0x34: /* sysenter */
- rc = emulate_sysenter(ctxt, ops);
- break;
- case 0x35: /* sysexit */
- rc = emulate_sysexit(ctxt, ops);
- break;
case 0x40 ... 0x4f: /* cmov */
- c->dst.val = c->dst.orig_val = c->src.val;
- if (!test_cc(c->b, ctxt->eflags))
- c->dst.type = OP_NONE; /* no writeback */
+ ctxt->dst.val = ctxt->dst.orig_val = ctxt->src.val;
+ if (!test_cc(ctxt->b, ctxt->eflags))
+ ctxt->dst.type = OP_NONE; /* no writeback */
break;
case 0x80 ... 0x8f: /* jnz rel, etc*/
- if (test_cc(c->b, ctxt->eflags))
- jmp_rel(c, c->src.val);
+ if (test_cc(ctxt->b, ctxt->eflags))
+ jmp_rel(ctxt, ctxt->src.val);
break;
case 0x90 ... 0x9f: /* setcc r/m8 */
- c->dst.val = test_cc(c->b, ctxt->eflags);
+ ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
break;
case 0xa0: /* push fs */
- rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_FS);
+ rc = emulate_push_sreg(ctxt, VCPU_SREG_FS);
break;
case 0xa1: /* pop fs */
- rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_FS);
+ rc = emulate_pop_sreg(ctxt, VCPU_SREG_FS);
break;
case 0xa3:
bt: /* bt */
- c->dst.type = OP_NONE;
+ ctxt->dst.type = OP_NONE;
/* only subword offset */
- c->src.val &= (c->dst.bytes << 3) - 1;
- emulate_2op_SrcV_nobyte("bt", c->src, c->dst, ctxt->eflags);
+ ctxt->src.val &= (ctxt->dst.bytes << 3) - 1;
+ emulate_2op_SrcV_nobyte("bt", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 0xa4: /* shld imm8, r, r/m */
case 0xa5: /* shld cl, r, r/m */
- emulate_2op_cl("shld", c->src2, c->src, c->dst, ctxt->eflags);
+ emulate_2op_cl("shld", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 0xa8: /* push gs */
- rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_GS);
+ rc = emulate_push_sreg(ctxt, VCPU_SREG_GS);
break;
case 0xa9: /* pop gs */
- rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_GS);
+ rc = emulate_pop_sreg(ctxt, VCPU_SREG_GS);
break;
case 0xab:
bts: /* bts */
- emulate_2op_SrcV_nobyte("bts", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV_nobyte("bts", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 0xac: /* shrd imm8, r, r/m */
case 0xad: /* shrd cl, r, r/m */
- emulate_2op_cl("shrd", c->src2, c->src, c->dst, ctxt->eflags);
+ emulate_2op_cl("shrd", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 0xae: /* clflush */
break;
@@ -4278,38 +4141,38 @@ twobyte_insn:
* Save real source value, then compare EAX against
* destination.
*/
- c->src.orig_val = c->src.val;
- c->src.val = c->regs[VCPU_REGS_RAX];
- emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
+ 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);
if (ctxt->eflags & EFLG_ZF) {
/* Success: write back to memory. */
- c->dst.val = c->src.orig_val;
+ ctxt->dst.val = ctxt->src.orig_val;
} else {
/* Failure: write the value we saw to EAX. */
- c->dst.type = OP_REG;
- c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX];
+ ctxt->dst.type = OP_REG;
+ ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
}
break;
case 0xb2: /* lss */
- rc = emulate_load_segment(ctxt, ops, VCPU_SREG_SS);
+ rc = emulate_load_segment(ctxt, VCPU_SREG_SS);
break;
case 0xb3:
btr: /* btr */
- emulate_2op_SrcV_nobyte("btr", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV_nobyte("btr", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 0xb4: /* lfs */
- rc = emulate_load_segment(ctxt, ops, VCPU_SREG_FS);
+ rc = emulate_load_segment(ctxt, VCPU_SREG_FS);
break;
case 0xb5: /* lgs */
- rc = emulate_load_segment(ctxt, ops, VCPU_SREG_GS);
+ rc = emulate_load_segment(ctxt, VCPU_SREG_GS);
break;
case 0xb6 ... 0xb7: /* movzx */
- c->dst.bytes = c->op_bytes;
- c->dst.val = (c->d & ByteOp) ? (u8) c->src.val
- : (u16) c->src.val;
+ ctxt->dst.bytes = ctxt->op_bytes;
+ ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val
+ : (u16) ctxt->src.val;
break;
case 0xba: /* Grp8 */
- switch (c->modrm_reg & 3) {
+ switch (ctxt->modrm_reg & 3) {
case 0:
goto bt;
case 1:
@@ -4322,47 +4185,47 @@ twobyte_insn:
break;
case 0xbb:
btc: /* btc */
- emulate_2op_SrcV_nobyte("btc", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV_nobyte("btc", ctxt->src, ctxt->dst, ctxt->eflags);
break;
case 0xbc: { /* bsf */
u8 zf;
__asm__ ("bsf %2, %0; setz %1"
- : "=r"(c->dst.val), "=q"(zf)
- : "r"(c->src.val));
+ : "=r"(ctxt->dst.val), "=q"(zf)
+ : "r"(ctxt->src.val));
ctxt->eflags &= ~X86_EFLAGS_ZF;
if (zf) {
ctxt->eflags |= X86_EFLAGS_ZF;
- c->dst.type = OP_NONE; /* Disable writeback. */
+ ctxt->dst.type = OP_NONE; /* Disable writeback. */
}
break;
}
case 0xbd: { /* bsr */
u8 zf;
__asm__ ("bsr %2, %0; setz %1"
- : "=r"(c->dst.val), "=q"(zf)
- : "r"(c->src.val));
+ : "=r"(ctxt->dst.val), "=q"(zf)
+ : "r"(ctxt->src.val));
ctxt->eflags &= ~X86_EFLAGS_ZF;
if (zf) {
ctxt->eflags |= X86_EFLAGS_ZF;
- c->dst.type = OP_NONE; /* Disable writeback. */
+ ctxt->dst.type = OP_NONE; /* Disable writeback. */
}
break;
}
case 0xbe ... 0xbf: /* movsx */
- c->dst.bytes = c->op_bytes;
- c->dst.val = (c->d & ByteOp) ? (s8) c->src.val :
- (s16) c->src.val;
+ ctxt->dst.bytes = ctxt->op_bytes;
+ ctxt->dst.val = (ctxt->d & ByteOp) ? (s8) ctxt->src.val :
+ (s16) ctxt->src.val;
break;
case 0xc0 ... 0xc1: /* xadd */
- emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
+ emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
/* Write back the register source. */
- c->src.val = c->dst.orig_val;
- write_register_operand(&c->src);
+ ctxt->src.val = ctxt->dst.orig_val;
+ write_register_operand(&ctxt->src);
break;
case 0xc3: /* movnti */
- c->dst.bytes = c->op_bytes;
- c->dst.val = (c->op_bytes == 4) ? (u32) c->src.val :
- (u64) c->src.val;
+ ctxt->dst.bytes = ctxt->op_bytes;
+ ctxt->dst.val = (ctxt->op_bytes == 4) ? (u32) ctxt->src.val :
+ (u64) ctxt->src.val;
break;
case 0xc7: /* Grp9 (cmpxchg8b) */
rc = em_grp9(ctxt);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2b2255b1f04b..57dcbd4308fa 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -33,7 +33,7 @@
#include <asm/page.h>
#include <asm/current.h>
#include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "kvm_cache_regs.h"
#include "irq.h"
#include "trace.h"
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index aee38623b768..1c5b69373a00 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -22,7 +22,6 @@
#include "mmu.h"
#include "x86.h"
#include "kvm_cache_regs.h"
-#include "x86.h"
#include <linux/kvm_host.h>
#include <linux/types.h>
@@ -148,7 +147,7 @@ module_param(oos_shadow, bool, 0644);
#define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \
| PT64_NX_MASK)
-#define RMAP_EXT 4
+#define PTE_LIST_EXT 4
#define ACC_EXEC_MASK 1
#define ACC_WRITE_MASK PT_WRITABLE_MASK
@@ -164,16 +163,16 @@ module_param(oos_shadow, bool, 0644);
#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
-struct kvm_rmap_desc {
- u64 *sptes[RMAP_EXT];
- struct kvm_rmap_desc *more;
+struct pte_list_desc {
+ u64 *sptes[PTE_LIST_EXT];
+ struct pte_list_desc *more;
};
struct kvm_shadow_walk_iterator {
u64 addr;
hpa_t shadow_addr;
- int level;
u64 *sptep;
+ int level;
unsigned index;
};
@@ -182,32 +181,68 @@ struct kvm_shadow_walk_iterator {
shadow_walk_okay(&(_walker)); \
shadow_walk_next(&(_walker)))
-typedef void (*mmu_parent_walk_fn) (struct kvm_mmu_page *sp, u64 *spte);
+#define for_each_shadow_entry_lockless(_vcpu, _addr, _walker, spte) \
+ for (shadow_walk_init(&(_walker), _vcpu, _addr); \
+ shadow_walk_okay(&(_walker)) && \
+ ({ spte = mmu_spte_get_lockless(_walker.sptep); 1; }); \
+ __shadow_walk_next(&(_walker), spte))
-static struct kmem_cache *pte_chain_cache;
-static struct kmem_cache *rmap_desc_cache;
+static struct kmem_cache *pte_list_desc_cache;
static struct kmem_cache *mmu_page_header_cache;
static struct percpu_counter kvm_total_used_mmu_pages;
-static u64 __read_mostly shadow_trap_nonpresent_pte;
-static u64 __read_mostly shadow_notrap_nonpresent_pte;
static u64 __read_mostly shadow_nx_mask;
static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */
static u64 __read_mostly shadow_user_mask;
static u64 __read_mostly shadow_accessed_mask;
static u64 __read_mostly shadow_dirty_mask;
+static u64 __read_mostly shadow_mmio_mask;
-static inline u64 rsvd_bits(int s, int e)
+static void mmu_spte_set(u64 *sptep, u64 spte);
+
+void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask)
{
- return ((1ULL << (e - s + 1)) - 1) << s;
+ shadow_mmio_mask = mmio_mask;
}
+EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask);
-void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte)
+static void mark_mmio_spte(u64 *sptep, u64 gfn, unsigned access)
{
- shadow_trap_nonpresent_pte = trap_pte;
- shadow_notrap_nonpresent_pte = notrap_pte;
+ access &= ACC_WRITE_MASK | ACC_USER_MASK;
+
+ trace_mark_mmio_spte(sptep, gfn, access);
+ mmu_spte_set(sptep, shadow_mmio_mask | access | gfn << PAGE_SHIFT);
+}
+
+static bool is_mmio_spte(u64 spte)
+{
+ return (spte & shadow_mmio_mask) == shadow_mmio_mask;
+}
+
+static gfn_t get_mmio_spte_gfn(u64 spte)
+{
+ return (spte & ~shadow_mmio_mask) >> PAGE_SHIFT;
+}
+
+static unsigned get_mmio_spte_access(u64 spte)
+{
+ return (spte & ~shadow_mmio_mask) & ~PAGE_MASK;
+}
+
+static bool set_mmio_spte(u64 *sptep, gfn_t gfn, pfn_t pfn, unsigned access)
+{
+ if (unlikely(is_noslot_pfn(pfn))) {
+ mark_mmio_spte(sptep, gfn, access);
+ return true;
+ }
+
+ return false;
+}
+
+static inline u64 rsvd_bits(int s, int e)
+{
+ return ((1ULL << (e - s + 1)) - 1) << s;
}
-EXPORT_SYMBOL_GPL(kvm_mmu_set_nonpresent_ptes);
void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
u64 dirty_mask, u64 nx_mask, u64 x_mask)
@@ -220,11 +255,6 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
}
EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
-static bool is_write_protection(struct kvm_vcpu *vcpu)
-{
- return kvm_read_cr0_bits(vcpu, X86_CR0_WP);
-}
-
static int is_cpuid_PSE36(void)
{
return 1;
@@ -237,8 +267,7 @@ static int is_nx(struct kvm_vcpu *vcpu)
static int is_shadow_present_pte(u64 pte)
{
- return pte != shadow_trap_nonpresent_pte
- && pte != shadow_notrap_nonpresent_pte;
+ return pte & PT_PRESENT_MASK && !is_mmio_spte(pte);
}
static int is_large_pte(u64 pte)
@@ -246,11 +275,6 @@ static int is_large_pte(u64 pte)
return pte & PT_PAGE_SIZE_MASK;
}
-static int is_writable_pte(unsigned long pte)
-{
- return pte & PT_WRITABLE_MASK;
-}
-
static int is_dirty_gpte(unsigned long pte)
{
return pte & PT_DIRTY_MASK;
@@ -282,26 +306,154 @@ static gfn_t pse36_gfn_delta(u32 gpte)
return (gpte & PT32_DIR_PSE36_MASK) << shift;
}
+#ifdef CONFIG_X86_64
static void __set_spte(u64 *sptep, u64 spte)
{
- set_64bit(sptep, spte);
+ *sptep = spte;
}
-static u64 __xchg_spte(u64 *sptep, u64 new_spte)
+static void __update_clear_spte_fast(u64 *sptep, u64 spte)
{
-#ifdef CONFIG_X86_64
- return xchg(sptep, new_spte);
+ *sptep = spte;
+}
+
+static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
+{
+ return xchg(sptep, spte);
+}
+
+static u64 __get_spte_lockless(u64 *sptep)
+{
+ return ACCESS_ONCE(*sptep);
+}
+
+static bool __check_direct_spte_mmio_pf(u64 spte)
+{
+ /* It is valid if the spte is zapped. */
+ return spte == 0ull;
+}
#else
- u64 old_spte;
+union split_spte {
+ struct {
+ u32 spte_low;
+ u32 spte_high;
+ };
+ u64 spte;
+};
- do {
- old_spte = *sptep;
- } while (cmpxchg64(sptep, old_spte, new_spte) != old_spte);
+static void count_spte_clear(u64 *sptep, u64 spte)
+{
+ struct kvm_mmu_page *sp = page_header(__pa(sptep));
- return old_spte;
-#endif
+ if (is_shadow_present_pte(spte))
+ return;
+
+ /* Ensure the spte is completely set before we increase the count */
+ smp_wmb();
+ sp->clear_spte_count++;
+}
+
+static void __set_spte(u64 *sptep, u64 spte)
+{
+ union split_spte *ssptep, sspte;
+
+ ssptep = (union split_spte *)sptep;
+ sspte = (union split_spte)spte;
+
+ ssptep->spte_high = sspte.spte_high;
+
+ /*
+ * If we map the spte from nonpresent to present, We should store
+ * the high bits firstly, then set present bit, so cpu can not
+ * fetch this spte while we are setting the spte.
+ */
+ smp_wmb();
+
+ ssptep->spte_low = sspte.spte_low;
}
+static void __update_clear_spte_fast(u64 *sptep, u64 spte)
+{
+ union split_spte *ssptep, sspte;
+
+ ssptep = (union split_spte *)sptep;
+ sspte = (union split_spte)spte;
+
+ ssptep->spte_low = sspte.spte_low;
+
+ /*
+ * If we map the spte from present to nonpresent, we should clear
+ * present bit firstly to avoid vcpu fetch the old high bits.
+ */
+ smp_wmb();
+
+ ssptep->spte_high = sspte.spte_high;
+ count_spte_clear(sptep, spte);
+}
+
+static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
+{
+ union split_spte *ssptep, sspte, orig;
+
+ ssptep = (union split_spte *)sptep;
+ sspte = (union split_spte)spte;
+
+ /* xchg acts as a barrier before the setting of the high bits */
+ orig.spte_low = xchg(&ssptep->spte_low, sspte.spte_low);
+ orig.spte_high = ssptep->spte_high = sspte.spte_high;
+ count_spte_clear(sptep, spte);
+
+ return orig.spte;
+}
+
+/*
+ * The idea using the light way get the spte on x86_32 guest is from
+ * gup_get_pte(arch/x86/mm/gup.c).
+ * The difference is we can not catch the spte tlb flush if we leave
+ * guest mode, so we emulate it by increase clear_spte_count when spte
+ * is cleared.
+ */
+static u64 __get_spte_lockless(u64 *sptep)
+{
+ struct kvm_mmu_page *sp = page_header(__pa(sptep));
+ union split_spte spte, *orig = (union split_spte *)sptep;
+ int count;
+
+retry:
+ count = sp->clear_spte_count;
+ smp_rmb();
+
+ spte.spte_low = orig->spte_low;
+ smp_rmb();
+
+ spte.spte_high = orig->spte_high;
+ smp_rmb();
+
+ if (unlikely(spte.spte_low != orig->spte_low ||
+ count != sp->clear_spte_count))
+ goto retry;
+
+ return spte.spte;
+}
+
+static bool __check_direct_spte_mmio_pf(u64 spte)
+{
+ union split_spte sspte = (union split_spte)spte;
+ u32 high_mmio_mask = shadow_mmio_mask >> 32;
+
+ /* It is valid if the spte is zapped. */
+ if (spte == 0ull)
+ return true;
+
+ /* It is valid if the spte is being zapped. */
+ if (sspte.spte_low == 0ull &&
+ (sspte.spte_high & high_mmio_mask) == high_mmio_mask)
+ return true;
+
+ return false;
+}
+#endif
+
static bool spte_has_volatile_bits(u64 spte)
{
if (!shadow_accessed_mask)
@@ -322,12 +474,30 @@ static bool spte_is_bit_cleared(u64 old_spte, u64 new_spte, u64 bit_mask)
return (old_spte & bit_mask) && !(new_spte & bit_mask);
}
-static void update_spte(u64 *sptep, u64 new_spte)
+/* Rules for using mmu_spte_set:
+ * Set the sptep from nonpresent to present.
+ * Note: the sptep being assigned *must* be either not present
+ * or in a state where the hardware will not attempt to update
+ * the spte.
+ */
+static void mmu_spte_set(u64 *sptep, u64 new_spte)
+{
+ WARN_ON(is_shadow_present_pte(*sptep));
+ __set_spte(sptep, new_spte);
+}
+
+/* Rules for using mmu_spte_update:
+ * Update the state bits, it means the mapped pfn is not changged.
+ */
+static void mmu_spte_update(u64 *sptep, u64 new_spte)
{
u64 mask, old_spte = *sptep;
WARN_ON(!is_rmap_spte(new_spte));
+ if (!is_shadow_present_pte(old_spte))
+ return mmu_spte_set(sptep, new_spte);
+
new_spte |= old_spte & shadow_dirty_mask;
mask = shadow_accessed_mask;
@@ -335,9 +505,9 @@ static void update_spte(u64 *sptep, u64 new_spte)
mask |= shadow_dirty_mask;
if (!spte_has_volatile_bits(old_spte) || (new_spte & mask) == mask)
- __set_spte(sptep, new_spte);
+ __update_clear_spte_fast(sptep, new_spte);
else
- old_spte = __xchg_spte(sptep, new_spte);
+ old_spte = __update_clear_spte_slow(sptep, new_spte);
if (!shadow_accessed_mask)
return;
@@ -348,6 +518,64 @@ static void update_spte(u64 *sptep, u64 new_spte)
kvm_set_pfn_dirty(spte_to_pfn(old_spte));
}
+/*
+ * Rules for using mmu_spte_clear_track_bits:
+ * It sets the sptep from present to nonpresent, and track the
+ * state bits, it is used to clear the last level sptep.
+ */
+static int mmu_spte_clear_track_bits(u64 *sptep)
+{
+ pfn_t pfn;
+ u64 old_spte = *sptep;
+
+ if (!spte_has_volatile_bits(old_spte))
+ __update_clear_spte_fast(sptep, 0ull);
+ else
+ old_spte = __update_clear_spte_slow(sptep, 0ull);
+
+ if (!is_rmap_spte(old_spte))
+ return 0;
+
+ pfn = spte_to_pfn(old_spte);
+ if (!shadow_accessed_mask || old_spte & shadow_accessed_mask)
+ kvm_set_pfn_accessed(pfn);
+ if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask))
+ kvm_set_pfn_dirty(pfn);
+ return 1;
+}
+
+/*
+ * Rules for using mmu_spte_clear_no_track:
+ * Directly clear spte without caring the state bits of sptep,
+ * it is used to set the upper level spte.
+ */
+static void mmu_spte_clear_no_track(u64 *sptep)
+{
+ __update_clear_spte_fast(sptep, 0ull);
+}
+
+static u64 mmu_spte_get_lockless(u64 *sptep)
+{
+ return __get_spte_lockless(sptep);
+}
+
+static void walk_shadow_page_lockless_begin(struct kvm_vcpu *vcpu)
+{
+ rcu_read_lock();
+ atomic_inc(&vcpu->kvm->arch.reader_counter);
+
+ /* Increase the counter before walking shadow page table */
+ smp_mb__after_atomic_inc();
+}
+
+static void walk_shadow_page_lockless_end(struct kvm_vcpu *vcpu)
+{
+ /* Decrease the counter after walking shadow page table finished */
+ smp_mb__before_atomic_dec();
+ atomic_dec(&vcpu->kvm->arch.reader_counter);
+ rcu_read_unlock();
+}
+
static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
struct kmem_cache *base_cache, int min)
{
@@ -397,12 +625,8 @@ static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)
{
int r;
- r = mmu_topup_memory_cache(&vcpu->arch.mmu_pte_chain_cache,
- pte_chain_cache, 4);
- if (r)
- goto out;
- r = mmu_topup_memory_cache(&vcpu->arch.mmu_rmap_desc_cache,
- rmap_desc_cache, 4 + PTE_PREFETCH_NUM);
+ r = mmu_topup_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache,
+ pte_list_desc_cache, 8 + PTE_PREFETCH_NUM);
if (r)
goto out;
r = mmu_topup_memory_cache_page(&vcpu->arch.mmu_page_cache, 8);
@@ -416,8 +640,8 @@ out:
static void mmu_free_memory_caches(struct kvm_vcpu *vcpu)
{
- mmu_free_memory_cache(&vcpu->arch.mmu_pte_chain_cache, pte_chain_cache);
- mmu_free_memory_cache(&vcpu->arch.mmu_rmap_desc_cache, rmap_desc_cache);
+ mmu_free_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache,
+ pte_list_desc_cache);
mmu_free_memory_cache_page(&vcpu->arch.mmu_page_cache);
mmu_free_memory_cache(&vcpu->arch.mmu_page_header_cache,
mmu_page_header_cache);
@@ -433,26 +657,15 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc,
return p;
}
-static struct kvm_pte_chain *mmu_alloc_pte_chain(struct kvm_vcpu *vcpu)
+static struct pte_list_desc *mmu_alloc_pte_list_desc(struct kvm_vcpu *vcpu)
{
- return mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_chain_cache,
- sizeof(struct kvm_pte_chain));
+ return mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_list_desc_cache,
+ sizeof(struct pte_list_desc));
}
-static void mmu_free_pte_chain(struct kvm_pte_chain *pc)
+static void mmu_free_pte_list_desc(struct pte_list_desc *pte_list_desc)
{
- kmem_cache_free(pte_chain_cache, pc);
-}
-
-static struct kvm_rmap_desc *mmu_alloc_rmap_desc(struct kvm_vcpu *vcpu)
-{
- return mmu_memory_cache_alloc(&vcpu->arch.mmu_rmap_desc_cache,
- sizeof(struct kvm_rmap_desc));
-}
-
-static void mmu_free_rmap_desc(struct kvm_rmap_desc *rd)
-{
- kmem_cache_free(rmap_desc_cache, rd);
+ kmem_cache_free(pte_list_desc_cache, pte_list_desc);
}
static gfn_t kvm_mmu_page_get_gfn(struct kvm_mmu_page *sp, int index)
@@ -498,6 +711,7 @@ static void account_shadowed(struct kvm *kvm, gfn_t gfn)
linfo = lpage_info_slot(gfn, slot, i);
linfo->write_count += 1;
}
+ kvm->arch.indirect_shadow_pages++;
}
static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
@@ -513,6 +727,7 @@ static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
linfo->write_count -= 1;
WARN_ON(linfo->write_count < 0);
}
+ kvm->arch.indirect_shadow_pages--;
}
static int has_wrprotected_page(struct kvm *kvm,
@@ -588,67 +803,42 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
}
/*
- * Take gfn and return the reverse mapping to it.
- */
-
-static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
-{
- struct kvm_memory_slot *slot;
- struct kvm_lpage_info *linfo;
-
- slot = gfn_to_memslot(kvm, gfn);
- if (likely(level == PT_PAGE_TABLE_LEVEL))
- return &slot->rmap[gfn - slot->base_gfn];
-
- linfo = lpage_info_slot(gfn, slot, level);
-
- return &linfo->rmap_pde;
-}
-
-/*
- * Reverse mapping data structures:
+ * Pte mapping structures:
*
- * If rmapp bit zero is zero, then rmapp point to the shadw page table entry
- * that points to page_address(page).
+ * If pte_list bit zero is zero, then pte_list point to the spte.
*
- * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
- * containing more mappings.
+ * If pte_list bit zero is one, (then pte_list & ~1) points to a struct
+ * pte_list_desc containing more mappings.
*
- * Returns the number of rmap entries before the spte was added or zero if
+ * Returns the number of pte entries before the spte was added or zero if
* the spte was not added.
*
*/
-static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
+static int pte_list_add(struct kvm_vcpu *vcpu, u64 *spte,
+ unsigned long *pte_list)
{
- struct kvm_mmu_page *sp;
- struct kvm_rmap_desc *desc;
- unsigned long *rmapp;
+ struct pte_list_desc *desc;
int i, count = 0;
- if (!is_rmap_spte(*spte))
- return count;
- sp = page_header(__pa(spte));
- kvm_mmu_page_set_gfn(sp, spte - sp->spt, gfn);
- rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
- if (!*rmapp) {
- rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
- *rmapp = (unsigned long)spte;
- } else if (!(*rmapp & 1)) {
- rmap_printk("rmap_add: %p %llx 1->many\n", spte, *spte);
- desc = mmu_alloc_rmap_desc(vcpu);
- desc->sptes[0] = (u64 *)*rmapp;
+ if (!*pte_list) {
+ rmap_printk("pte_list_add: %p %llx 0->1\n", spte, *spte);
+ *pte_list = (unsigned long)spte;
+ } else if (!(*pte_list & 1)) {
+ rmap_printk("pte_list_add: %p %llx 1->many\n", spte, *spte);
+ desc = mmu_alloc_pte_list_desc(vcpu);
+ desc->sptes[0] = (u64 *)*pte_list;
desc->sptes[1] = spte;
- *rmapp = (unsigned long)desc | 1;
+ *pte_list = (unsigned long)desc | 1;
++count;
} else {
- rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
- desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
- while (desc->sptes[RMAP_EXT-1] && desc->more) {
+ rmap_printk("pte_list_add: %p %llx many->many\n", spte, *spte);
+ desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+ while (desc->sptes[PTE_LIST_EXT-1] && desc->more) {
desc = desc->more;
- count += RMAP_EXT;
+ count += PTE_LIST_EXT;
}
- if (desc->sptes[RMAP_EXT-1]) {
- desc->more = mmu_alloc_rmap_desc(vcpu);
+ if (desc->sptes[PTE_LIST_EXT-1]) {
+ desc->more = mmu_alloc_pte_list_desc(vcpu);
desc = desc->more;
}
for (i = 0; desc->sptes[i]; ++i)
@@ -658,59 +848,78 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
return count;
}
-static void rmap_desc_remove_entry(unsigned long *rmapp,
- struct kvm_rmap_desc *desc,
- int i,
- struct kvm_rmap_desc *prev_desc)
+static u64 *pte_list_next(unsigned long *pte_list, u64 *spte)
+{
+ struct pte_list_desc *desc;
+ u64 *prev_spte;
+ int i;
+
+ if (!*pte_list)
+ return NULL;
+ else if (!(*pte_list & 1)) {
+ if (!spte)
+ return (u64 *)*pte_list;
+ return NULL;
+ }
+ desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+ prev_spte = NULL;
+ while (desc) {
+ for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i) {
+ if (prev_spte == spte)
+ return desc->sptes[i];
+ prev_spte = desc->sptes[i];
+ }
+ desc = desc->more;
+ }
+ return NULL;
+}
+
+static void
+pte_list_desc_remove_entry(unsigned long *pte_list, struct pte_list_desc *desc,
+ int i, struct pte_list_desc *prev_desc)
{
int j;
- for (j = RMAP_EXT - 1; !desc->sptes[j] && j > i; --j)
+ for (j = PTE_LIST_EXT - 1; !desc->sptes[j] && j > i; --j)
;
desc->sptes[i] = desc->sptes[j];
desc->sptes[j] = NULL;
if (j != 0)
return;
if (!prev_desc && !desc->more)
- *rmapp = (unsigned long)desc->sptes[0];
+ *pte_list = (unsigned long)desc->sptes[0];
else
if (prev_desc)
prev_desc->more = desc->more;
else
- *rmapp = (unsigned long)desc->more | 1;
- mmu_free_rmap_desc(desc);
+ *pte_list = (unsigned long)desc->more | 1;
+ mmu_free_pte_list_desc(desc);
}
-static void rmap_remove(struct kvm *kvm, u64 *spte)
+static void pte_list_remove(u64 *spte, unsigned long *pte_list)
{
- struct kvm_rmap_desc *desc;
- struct kvm_rmap_desc *prev_desc;
- struct kvm_mmu_page *sp;
- gfn_t gfn;
- unsigned long *rmapp;
+ struct pte_list_desc *desc;
+ struct pte_list_desc *prev_desc;
int i;
- sp = page_header(__pa(spte));
- gfn = kvm_mmu_page_get_gfn(sp, spte - sp->spt);
- rmapp = gfn_to_rmap(kvm, gfn, sp->role.level);
- if (!*rmapp) {
- printk(KERN_ERR "rmap_remove: %p 0->BUG\n", spte);
+ if (!*pte_list) {
+ printk(KERN_ERR "pte_list_remove: %p 0->BUG\n", spte);
BUG();
- } else if (!(*rmapp & 1)) {
- rmap_printk("rmap_remove: %p 1->0\n", spte);
- if ((u64 *)*rmapp != spte) {
- printk(KERN_ERR "rmap_remove: %p 1->BUG\n", spte);
+ } else if (!(*pte_list & 1)) {
+ rmap_printk("pte_list_remove: %p 1->0\n", spte);
+ if ((u64 *)*pte_list != spte) {
+ printk(KERN_ERR "pte_list_remove: %p 1->BUG\n", spte);
BUG();
}
- *rmapp = 0;
+ *pte_list = 0;
} else {
- rmap_printk("rmap_remove: %p many->many\n", spte);
- desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
+ rmap_printk("pte_list_remove: %p many->many\n", spte);
+ desc = (struct pte_list_desc *)(*pte_list & ~1ul);
prev_desc = NULL;
while (desc) {
- for (i = 0; i < RMAP_EXT && desc->sptes[i]; ++i)
+ for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i)
if (desc->sptes[i] == spte) {
- rmap_desc_remove_entry(rmapp,
+ pte_list_desc_remove_entry(pte_list,
desc, i,
prev_desc);
return;
@@ -718,62 +927,80 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
prev_desc = desc;
desc = desc->more;
}
- pr_err("rmap_remove: %p many->many\n", spte);
+ pr_err("pte_list_remove: %p many->many\n", spte);
BUG();
}
}
-static int set_spte_track_bits(u64 *sptep, u64 new_spte)
+typedef void (*pte_list_walk_fn) (u64 *spte);
+static void pte_list_walk(unsigned long *pte_list, pte_list_walk_fn fn)
{
- pfn_t pfn;
- u64 old_spte = *sptep;
+ struct pte_list_desc *desc;
+ int i;
- if (!spte_has_volatile_bits(old_spte))
- __set_spte(sptep, new_spte);
- else
- old_spte = __xchg_spte(sptep, new_spte);
+ if (!*pte_list)
+ return;
- if (!is_rmap_spte(old_spte))
- return 0;
+ if (!(*pte_list & 1))
+ return fn((u64 *)*pte_list);
- pfn = spte_to_pfn(old_spte);
- if (!shadow_accessed_mask || old_spte & shadow_accessed_mask)
- kvm_set_pfn_accessed(pfn);
- if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask))
- kvm_set_pfn_dirty(pfn);
- return 1;
+ desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+ while (desc) {
+ for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i)
+ fn(desc->sptes[i]);
+ desc = desc->more;
+ }
}
-static void drop_spte(struct kvm *kvm, u64 *sptep, u64 new_spte)
+/*
+ * Take gfn and return the reverse mapping to it.
+ */
+static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
{
- if (set_spte_track_bits(sptep, new_spte))
- rmap_remove(kvm, sptep);
+ struct kvm_memory_slot *slot;
+ struct kvm_lpage_info *linfo;
+
+ slot = gfn_to_memslot(kvm, gfn);
+ if (likely(level == PT_PAGE_TABLE_LEVEL))
+ return &slot->rmap[gfn - slot->base_gfn];
+
+ linfo = lpage_info_slot(gfn, slot, level);
+
+ return &linfo->rmap_pde;
+}
+
+static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
+{
+ struct kvm_mmu_page *sp;
+ unsigned long *rmapp;
+
+ sp = page_header(__pa(spte));
+ kvm_mmu_page_set_gfn(sp, spte - sp->spt, gfn);
+ rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
+ return pte_list_add(vcpu, spte, rmapp);
}
static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte)
{
- struct kvm_rmap_desc *desc;
- u64 *prev_spte;
- int i;
+ return pte_list_next(rmapp, spte);
+}
- if (!*rmapp)
- return NULL;
- else if (!(*rmapp & 1)) {
- if (!spte)
- return (u64 *)*rmapp;
- return NULL;
- }
- desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
- prev_spte = NULL;
- while (desc) {
- for (i = 0; i < RMAP_EXT && desc->sptes[i]; ++i) {
- if (prev_spte == spte)
- return desc->sptes[i];
- prev_spte = desc->sptes[i];
- }
- desc = desc->more;
- }
- return NULL;
+static void rmap_remove(struct kvm *kvm, u64 *spte)
+{
+ struct kvm_mmu_page *sp;
+ gfn_t gfn;
+ unsigned long *rmapp;
+
+ sp = page_header(__pa(spte));
+ gfn = kvm_mmu_page_get_gfn(sp, spte - sp->spt);
+ rmapp = gfn_to_rmap(kvm, gfn, sp->role.level);
+ pte_list_remove(spte, rmapp);
+}
+
+static void drop_spte(struct kvm *kvm, u64 *sptep)
+{
+ if (mmu_spte_clear_track_bits(sptep))
+ rmap_remove(kvm, sptep);
}
static int rmap_write_protect(struct kvm *kvm, u64 gfn)
@@ -790,7 +1017,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)
BUG_ON(!(*spte & PT_PRESENT_MASK));
rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
if (is_writable_pte(*spte)) {
- update_spte(spte, *spte & ~PT_WRITABLE_MASK);
+ mmu_spte_update(spte, *spte & ~PT_WRITABLE_MASK);
write_protected = 1;
}
spte = rmap_next(kvm, rmapp, spte);
@@ -807,8 +1034,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)
BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK));
pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn);
if (is_writable_pte(*spte)) {
- drop_spte(kvm, spte,
- shadow_trap_nonpresent_pte);
+ drop_spte(kvm, spte);
--kvm->stat.lpages;
spte = NULL;
write_protected = 1;
@@ -829,7 +1055,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
while ((spte = rmap_next(kvm, rmapp, NULL))) {
BUG_ON(!(*spte & PT_PRESENT_MASK));
rmap_printk("kvm_rmap_unmap_hva: spte %p %llx\n", spte, *spte);
- drop_spte(kvm, spte, shadow_trap_nonpresent_pte);
+ drop_spte(kvm, spte);
need_tlb_flush = 1;
}
return need_tlb_flush;
@@ -851,7 +1077,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte);
need_flush = 1;
if (pte_write(*ptep)) {
- drop_spte(kvm, spte, shadow_trap_nonpresent_pte);
+ drop_spte(kvm, spte);
spte = rmap_next(kvm, rmapp, NULL);
} else {
new_spte = *spte &~ (PT64_BASE_ADDR_MASK);
@@ -860,7 +1086,8 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
new_spte &= ~PT_WRITABLE_MASK;
new_spte &= ~SPTE_HOST_WRITEABLE;
new_spte &= ~shadow_accessed_mask;
- set_spte_track_bits(spte, new_spte);
+ mmu_spte_clear_track_bits(spte);
+ mmu_spte_set(spte, new_spte);
spte = rmap_next(kvm, rmapp, spte);
}
}
@@ -1032,151 +1259,89 @@ static inline void kvm_mod_used_mmu_pages(struct kvm *kvm, int nr)
percpu_counter_add(&kvm_total_used_mmu_pages, nr);
}
-static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp)
+/*
+ * Remove the sp from shadow page cache, after call it,
+ * we can not find this sp from the cache, and the shadow
+ * page table is still valid.
+ * It should be under the protection of mmu lock.
+ */
+static void kvm_mmu_isolate_page(struct kvm_mmu_page *sp)
{
ASSERT(is_empty_shadow_page(sp->spt));
hlist_del(&sp->hash_link);
- list_del(&sp->link);
- free_page((unsigned long)sp->spt);
if (!sp->role.direct)
free_page((unsigned long)sp->gfns);
- kmem_cache_free(mmu_page_header_cache, sp);
- kvm_mod_used_mmu_pages(kvm, -1);
}
-static unsigned kvm_page_table_hashfn(gfn_t gfn)
+/*
+ * Free the shadow page table and the sp, we can do it
+ * out of the protection of mmu lock.
+ */
+static void kvm_mmu_free_page(struct kvm_mmu_page *sp)
{
- return gfn & ((1 << KVM_MMU_HASH_SHIFT) - 1);
+ list_del(&sp->link);
+ free_page((unsigned long)sp->spt);
+ kmem_cache_free(mmu_page_header_cache, sp);
}
-static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
- u64 *parent_pte, int direct)
+static unsigned kvm_page_table_hashfn(gfn_t gfn)
{
- struct kvm_mmu_page *sp;
-
- sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache, sizeof *sp);
- sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE);
- if (!direct)
- sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache,
- PAGE_SIZE);
- set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
- list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages);
- bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
- sp->multimapped = 0;
- sp->parent_pte = parent_pte;
- kvm_mod_used_mmu_pages(vcpu->kvm, +1);
- return sp;
+ return gfn & ((1 << KVM_MMU_HASH_SHIFT) - 1);
}
static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu,
struct kvm_mmu_page *sp, u64 *parent_pte)
{
- struct kvm_pte_chain *pte_chain;
- struct hlist_node *node;
- int i;
-
if (!parent_pte)
return;
- if (!sp->multimapped) {
- u64 *old = sp->parent_pte;
- if (!old) {
- sp->parent_pte = parent_pte;
- return;
- }
- sp->multimapped = 1;
- pte_chain = mmu_alloc_pte_chain(vcpu);
- INIT_HLIST_HEAD(&sp->parent_ptes);
- hlist_add_head(&pte_chain->link, &sp->parent_ptes);
- pte_chain->parent_ptes[0] = old;
- }
- hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link) {
- if (pte_chain->parent_ptes[NR_PTE_CHAIN_ENTRIES-1])
- continue;
- for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i)
- if (!pte_chain->parent_ptes[i]) {
- pte_chain->parent_ptes[i] = parent_pte;
- return;
- }
- }
- pte_chain = mmu_alloc_pte_chain(vcpu);
- BUG_ON(!pte_chain);
- hlist_add_head(&pte_chain->link, &sp->parent_ptes);
- pte_chain->parent_ptes[0] = parent_pte;
+ pte_list_add(vcpu, parent_pte, &sp->parent_ptes);
}
static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp,
u64 *parent_pte)
{
- struct kvm_pte_chain *pte_chain;
- struct hlist_node *node;
- int i;
-
- if (!sp->multimapped) {
- BUG_ON(sp->parent_pte != parent_pte);
- sp->parent_pte = NULL;
- return;
- }
- hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
- for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
- if (!pte_chain->parent_ptes[i])
- break;
- if (pte_chain->parent_ptes[i] != parent_pte)
- continue;
- while (i + 1 < NR_PTE_CHAIN_ENTRIES
- && pte_chain->parent_ptes[i + 1]) {
- pte_chain->parent_ptes[i]
- = pte_chain->parent_ptes[i + 1];
- ++i;
- }
- pte_chain->parent_ptes[i] = NULL;
- if (i == 0) {
- hlist_del(&pte_chain->link);
- mmu_free_pte_chain(pte_chain);
- if (hlist_empty(&sp->parent_ptes)) {
- sp->multimapped = 0;
- sp->parent_pte = NULL;
- }
- }
- return;
- }
- BUG();
+ pte_list_remove(parent_pte, &sp->parent_ptes);
}
-static void mmu_parent_walk(struct kvm_mmu_page *sp, mmu_parent_walk_fn fn)
+static void drop_parent_pte(struct kvm_mmu_page *sp,
+ u64 *parent_pte)
{
- struct kvm_pte_chain *pte_chain;
- struct hlist_node *node;
- struct kvm_mmu_page *parent_sp;
- int i;
-
- if (!sp->multimapped && sp->parent_pte) {
- parent_sp = page_header(__pa(sp->parent_pte));
- fn(parent_sp, sp->parent_pte);
- return;
- }
-
- hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
- for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
- u64 *spte = pte_chain->parent_ptes[i];
+ mmu_page_remove_parent_pte(sp, parent_pte);
+ mmu_spte_clear_no_track(parent_pte);
+}
- if (!spte)
- break;
- parent_sp = page_header(__pa(spte));
- fn(parent_sp, spte);
- }
+static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
+ u64 *parent_pte, int direct)
+{
+ struct kvm_mmu_page *sp;
+ sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache,
+ sizeof *sp);
+ sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE);
+ if (!direct)
+ sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache,
+ PAGE_SIZE);
+ set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
+ list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages);
+ bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
+ sp->parent_ptes = 0;
+ mmu_page_add_parent_pte(vcpu, sp, parent_pte);
+ kvm_mod_used_mmu_pages(vcpu->kvm, +1);
+ return sp;
}
-static void mark_unsync(struct kvm_mmu_page *sp, u64 *spte);
+static void mark_unsync(u64 *spte);
static void kvm_mmu_mark_parents_unsync(struct kvm_mmu_page *sp)
{
- mmu_parent_walk(sp, mark_unsync);
+ pte_list_walk(&sp->parent_ptes, mark_unsync);
}
-static void mark_unsync(struct kvm_mmu_page *sp, u64 *spte)
+static void mark_unsync(u64 *spte)
{
+ struct kvm_mmu_page *sp;
unsigned int index;
+ sp = page_header(__pa(spte));
index = spte - sp->spt;
if (__test_and_set_bit(index, sp->unsync_child_bitmap))
return;
@@ -1185,15 +1350,6 @@ static void mark_unsync(struct kvm_mmu_page *sp, u64 *spte)
kvm_mmu_mark_parents_unsync(sp);
}
-static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *sp)
-{
- int i;
-
- for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
- sp->spt[i] = shadow_trap_nonpresent_pte;
-}
-
static int nonpaging_sync_page(struct kvm_vcpu *vcpu,
struct kvm_mmu_page *sp)
{
@@ -1475,6 +1631,14 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
}
}
+static void init_shadow_page_table(struct kvm_mmu_page *sp)
+{
+ int i;
+
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+ sp->spt[i] = 0ull;
+}
+
static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
gfn_t gfn,
gva_t gaddr,
@@ -1537,10 +1701,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
account_shadowed(vcpu->kvm, gfn);
}
- if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte)
- vcpu->arch.mmu.prefetch_page(vcpu, sp);
- else
- nonpaging_prefetch_page(vcpu, sp);
+ init_shadow_page_table(sp);
trace_kvm_mmu_get_page(sp, true);
return sp;
}
@@ -1572,21 +1733,28 @@ static bool shadow_walk_okay(struct kvm_shadow_walk_iterator *iterator)
if (iterator->level < PT_PAGE_TABLE_LEVEL)
return false;
- if (iterator->level == PT_PAGE_TABLE_LEVEL)
- if (is_large_pte(*iterator->sptep))
- return false;
-
iterator->index = SHADOW_PT_INDEX(iterator->addr, iterator->level);
iterator->sptep = ((u64 *)__va(iterator->shadow_addr)) + iterator->index;
return true;
}
-static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator)
+static void __shadow_walk_next(struct kvm_shadow_walk_iterator *iterator,
+ u64 spte)
{
- iterator->shadow_addr = *iterator->sptep & PT64_BASE_ADDR_MASK;
+ if (is_last_spte(spte, iterator->level)) {
+ iterator->level = 0;
+ return;
+ }
+
+ iterator->shadow_addr = spte & PT64_BASE_ADDR_MASK;
--iterator->level;
}
+static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator)
+{
+ return __shadow_walk_next(iterator, *iterator->sptep);
+}
+
static void link_shadow_page(u64 *sptep, struct kvm_mmu_page *sp)
{
u64 spte;
@@ -1594,13 +1762,13 @@ static void link_shadow_page(u64 *sptep, struct kvm_mmu_page *sp)
spte = __pa(sp->spt)
| PT_PRESENT_MASK | PT_ACCESSED_MASK
| PT_WRITABLE_MASK | PT_USER_MASK;
- __set_spte(sptep, spte);
+ mmu_spte_set(sptep, spte);
}
static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
{
if (is_large_pte(*sptep)) {
- drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte);
+ drop_spte(vcpu->kvm, sptep);
kvm_flush_remote_tlbs(vcpu->kvm);
}
}
@@ -1622,38 +1790,39 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, u64 *sptep,
if (child->role.access == direct_access)
return;
- mmu_page_remove_parent_pte(child, sptep);
- __set_spte(sptep, shadow_trap_nonpresent_pte);
+ drop_parent_pte(child, sptep);
kvm_flush_remote_tlbs(vcpu->kvm);
}
}
+static void mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
+ u64 *spte)
+{
+ u64 pte;
+ struct kvm_mmu_page *child;
+
+ pte = *spte;
+ if (is_shadow_present_pte(pte)) {
+ if (is_last_spte(pte, sp->role.level))
+ drop_spte(kvm, spte);
+ else {
+ child = page_header(pte & PT64_BASE_ADDR_MASK);
+ drop_parent_pte(child, spte);
+ }
+ } else if (is_mmio_spte(pte))
+ mmu_spte_clear_no_track(spte);
+
+ if (is_large_pte(pte))
+ --kvm->stat.lpages;
+}
+
static void kvm_mmu_page_unlink_children(struct kvm *kvm,
struct kvm_mmu_page *sp)
{
unsigned i;
- u64 *pt;
- u64 ent;
-
- pt = sp->spt;
-
- for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
- ent = pt[i];
-
- if (is_shadow_present_pte(ent)) {
- if (!is_last_spte(ent, sp->role.level)) {
- ent &= PT64_BASE_ADDR_MASK;
- mmu_page_remove_parent_pte(page_header(ent),
- &pt[i]);
- } else {
- if (is_large_pte(ent))
- --kvm->stat.lpages;
- drop_spte(kvm, &pt[i],
- shadow_trap_nonpresent_pte);
- }
- }
- pt[i] = shadow_trap_nonpresent_pte;
- }
+
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+ mmu_page_zap_pte(kvm, sp, sp->spt + i);
}
static void kvm_mmu_put_page(struct kvm_mmu_page *sp, u64 *parent_pte)
@@ -1674,20 +1843,8 @@ static void kvm_mmu_unlink_parents(struct kvm *kvm, struct kvm_mmu_page *sp)
{
u64 *parent_pte;
- while (sp->multimapped || sp->parent_pte) {
- if (!sp->multimapped)
- parent_pte = sp->parent_pte;
- else {
- struct kvm_pte_chain *chain;
-
- chain = container_of(sp->parent_ptes.first,
- struct kvm_pte_chain, link);
- parent_pte = chain->parent_ptes[0];
- }
- BUG_ON(!parent_pte);
- kvm_mmu_put_page(sp, parent_pte);
- __set_spte(parent_pte, shadow_trap_nonpresent_pte);
- }
+ while ((parent_pte = pte_list_next(&sp->parent_ptes, NULL)))
+ drop_parent_pte(sp, parent_pte);
}
static int mmu_zap_unsync_children(struct kvm *kvm,
@@ -1734,6 +1891,7 @@ static int kvm_mmu_prepare_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp,
/* Count self */
ret++;
list_move(&sp->link, invalid_list);
+ kvm_mod_used_mmu_pages(kvm, -1);
} else {
list_move(&sp->link, &kvm->arch.active_mmu_pages);
kvm_reload_remote_mmus(kvm);
@@ -1744,6 +1902,30 @@ static int kvm_mmu_prepare_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp,
return ret;
}
+static void kvm_mmu_isolate_pages(struct list_head *invalid_list)
+{
+ struct kvm_mmu_page *sp;
+
+ list_for_each_entry(sp, invalid_list, link)
+ kvm_mmu_isolate_page(sp);
+}
+
+static void free_pages_rcu(struct rcu_head *head)
+{
+ struct kvm_mmu_page *next, *sp;
+
+ sp = container_of(head, struct kvm_mmu_page, rcu);
+ while (sp) {
+ if (!list_empty(&sp->link))
+ next = list_first_entry(&sp->link,
+ struct kvm_mmu_page, link);
+ else
+ next = NULL;
+ kvm_mmu_free_page(sp);
+ sp = next;
+ }
+}
+
static void kvm_mmu_commit_zap_page(struct kvm *kvm,
struct list_head *invalid_list)
{
@@ -1754,10 +1936,21 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
kvm_flush_remote_tlbs(kvm);
+ if (atomic_read(&kvm->arch.reader_counter)) {
+ kvm_mmu_isolate_pages(invalid_list);
+ sp = list_first_entry(invalid_list, struct kvm_mmu_page, link);
+ list_del_init(invalid_list);
+
+ trace_kvm_mmu_delay_free_pages(sp);
+ call_rcu(&sp->rcu, free_pages_rcu);
+ return;
+ }
+
do {
sp = list_first_entry(invalid_list, struct kvm_mmu_page, link);
WARN_ON(!sp->role.invalid || sp->root_count);
- kvm_mmu_free_page(kvm, sp);
+ kvm_mmu_isolate_page(sp);
+ kvm_mmu_free_page(sp);
} while (!list_empty(invalid_list));
}
@@ -1783,8 +1976,8 @@ void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int goal_nr_mmu_pages)
page = container_of(kvm->arch.active_mmu_pages.prev,
struct kvm_mmu_page, link);
kvm_mmu_prepare_zap_page(kvm, page, &invalid_list);
- kvm_mmu_commit_zap_page(kvm, &invalid_list);
}
+ kvm_mmu_commit_zap_page(kvm, &invalid_list);
goal_nr_mmu_pages = kvm->arch.n_used_mmu_pages;
}
@@ -1833,20 +2026,6 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
__set_bit(slot, sp->slot_bitmap);
}
-static void mmu_convert_notrap(struct kvm_mmu_page *sp)
-{
- int i;
- u64 *pt = sp->spt;
-
- if (shadow_trap_nonpresent_pte == shadow_notrap_nonpresent_pte)
- return;
-
- for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
- if (pt[i] == shadow_notrap_nonpresent_pte)
- __set_spte(&pt[i], shadow_trap_nonpresent_pte);
- }
-}
-
/*
* The function is based on mtrr_type_lookup() in
* arch/x86/kernel/cpu/mtrr/generic.c
@@ -1959,7 +2138,6 @@ static void __kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
sp->unsync = 1;
kvm_mmu_mark_parents_unsync(sp);
- mmu_convert_notrap(sp);
}
static void kvm_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn)
@@ -2002,13 +2180,16 @@ static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,
static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
unsigned pte_access, int user_fault,
- int write_fault, int dirty, int level,
+ int write_fault, int level,
gfn_t gfn, pfn_t pfn, bool speculative,
bool can_unsync, bool host_writable)
{
u64 spte, entry = *sptep;
int ret = 0;
+ if (set_mmio_spte(sptep, gfn, pfn, pte_access))
+ return 0;
+
/*
* We don't set the accessed bit, since we sometimes want to see
* whether the guest actually used the pte (in order to detect
@@ -2017,8 +2198,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
spte = PT_PRESENT_MASK;
if (!speculative)
spte |= shadow_accessed_mask;
- if (!dirty)
- pte_access &= ~ACC_WRITE_MASK;
+
if (pte_access & ACC_EXEC_MASK)
spte |= shadow_x_mask;
else
@@ -2045,15 +2225,24 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
if (level > PT_PAGE_TABLE_LEVEL &&
has_wrprotected_page(vcpu->kvm, gfn, level)) {
ret = 1;
- drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte);
+ drop_spte(vcpu->kvm, sptep);
goto done;
}
spte |= PT_WRITABLE_MASK;
if (!vcpu->arch.mmu.direct_map
- && !(pte_access & ACC_WRITE_MASK))
+ && !(pte_access & ACC_WRITE_MASK)) {
spte &= ~PT_USER_MASK;
+ /*
+ * If we converted a user page to a kernel page,
+ * so that the kernel can write to it when cr0.wp=0,
+ * then we should prevent the kernel from executing it
+ * if SMEP is enabled.
+ */
+ if (kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
+ spte |= PT64_NX_MASK;
+ }
/*
* Optimization: for pte sync, if spte was writable the hash
@@ -2078,7 +2267,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
mark_page_dirty(vcpu->kvm, gfn);
set_pte:
- update_spte(sptep, spte);
+ mmu_spte_update(sptep, spte);
/*
* If we overwrite a writable spte with a read-only one we
* should flush remote TLBs. Otherwise rmap_write_protect
@@ -2093,8 +2282,8 @@ done:
static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
unsigned pt_access, unsigned pte_access,
- int user_fault, int write_fault, int dirty,
- int *ptwrite, int level, gfn_t gfn,
+ int user_fault, int write_fault,
+ int *emulate, int level, gfn_t gfn,
pfn_t pfn, bool speculative,
bool host_writable)
{
@@ -2117,26 +2306,28 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
u64 pte = *sptep;
child = page_header(pte & PT64_BASE_ADDR_MASK);
- mmu_page_remove_parent_pte(child, sptep);
- __set_spte(sptep, shadow_trap_nonpresent_pte);
+ drop_parent_pte(child, sptep);
kvm_flush_remote_tlbs(vcpu->kvm);
} else if (pfn != spte_to_pfn(*sptep)) {
pgprintk("hfn old %llx new %llx\n",
spte_to_pfn(*sptep), pfn);
- drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte);
+ drop_spte(vcpu->kvm, sptep);
kvm_flush_remote_tlbs(vcpu->kvm);
} else
was_rmapped = 1;
}
if (set_spte(vcpu, sptep, pte_access, user_fault, write_fault,
- dirty, level, gfn, pfn, speculative, true,
+ level, gfn, pfn, speculative, true,
host_writable)) {
if (write_fault)
- *ptwrite = 1;
+ *emulate = 1;
kvm_mmu_flush_tlb(vcpu);
}
+ if (unlikely(is_mmio_spte(*sptep) && emulate))
+ *emulate = 1;
+
pgprintk("%s: setting spte %llx\n", __func__, *sptep);
pgprintk("instantiating %s PTE (%s) at %llx (%llx) addr %p\n",
is_large_pte(*sptep)? "2MB" : "4kB",
@@ -2145,11 +2336,13 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
if (!was_rmapped && is_large_pte(*sptep))
++vcpu->kvm->stat.lpages;
- page_header_update_slot(vcpu->kvm, sptep, gfn);
- if (!was_rmapped) {
- rmap_count = rmap_add(vcpu, sptep, gfn);
- if (rmap_count > RMAP_RECYCLE_THRESHOLD)
- rmap_recycle(vcpu, sptep, gfn);
+ if (is_shadow_present_pte(*sptep)) {
+ page_header_update_slot(vcpu->kvm, sptep, gfn);
+ if (!was_rmapped) {
+ rmap_count = rmap_add(vcpu, sptep, gfn);
+ if (rmap_count > RMAP_RECYCLE_THRESHOLD)
+ rmap_recycle(vcpu, sptep, gfn);
+ }
}
kvm_release_pfn_clean(pfn);
if (speculative) {
@@ -2170,8 +2363,8 @@ static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, no_dirty_log);
if (!slot) {
- get_page(bad_page);
- return page_to_pfn(bad_page);
+ get_page(fault_page);
+ return page_to_pfn(fault_page);
}
hva = gfn_to_hva_memslot(slot, gfn);
@@ -2198,7 +2391,7 @@ static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
for (i = 0; i < ret; i++, gfn++, start++)
mmu_set_spte(vcpu, start, ACC_ALL,
- access, 0, 0, 1, NULL,
+ access, 0, 0, NULL,
sp->role.level, gfn,
page_to_pfn(pages[i]), true, true);
@@ -2217,7 +2410,7 @@ static void __direct_pte_prefetch(struct kvm_vcpu *vcpu,
spte = sp->spt + i;
for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) {
- if (*spte != shadow_trap_nonpresent_pte || spte == sptep) {
+ if (is_shadow_present_pte(*spte) || spte == sptep) {
if (!start)
continue;
if (direct_pte_prefetch_many(vcpu, sp, start, spte) < 0)
@@ -2254,7 +2447,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
{
struct kvm_shadow_walk_iterator iterator;
struct kvm_mmu_page *sp;
- int pt_write = 0;
+ int emulate = 0;
gfn_t pseudo_gfn;
for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
@@ -2262,14 +2455,14 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
unsigned pte_access = ACC_ALL;
mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, pte_access,
- 0, write, 1, &pt_write,
+ 0, write, &emulate,
level, gfn, pfn, prefault, map_writable);
direct_pte_prefetch(vcpu, iterator.sptep);
++vcpu->stat.pf_fixed;
break;
}
- if (*iterator.sptep == shadow_trap_nonpresent_pte) {
+ if (!is_shadow_present_pte(*iterator.sptep)) {
u64 base_addr = iterator.addr;
base_addr &= PT64_LVL_ADDR_MASK(iterator.level);
@@ -2283,14 +2476,14 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
return -ENOMEM;
}
- __set_spte(iterator.sptep,
- __pa(sp->spt)
- | PT_PRESENT_MASK | PT_WRITABLE_MASK
- | shadow_user_mask | shadow_x_mask
- | shadow_accessed_mask);
+ mmu_spte_set(iterator.sptep,
+ __pa(sp->spt)
+ | PT_PRESENT_MASK | PT_WRITABLE_MASK
+ | shadow_user_mask | shadow_x_mask
+ | shadow_accessed_mask);
}
}
- return pt_write;
+ return emulate;
}
static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *tsk)
@@ -2306,16 +2499,15 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *
send_sig_info(SIGBUS, &info, tsk);
}
-static int kvm_handle_bad_page(struct kvm *kvm, gfn_t gfn, pfn_t pfn)
+static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, pfn_t pfn)
{
kvm_release_pfn_clean(pfn);
if (is_hwpoison_pfn(pfn)) {
- kvm_send_hwpoison_signal(gfn_to_hva(kvm, gfn), current);
+ kvm_send_hwpoison_signal(gfn_to_hva(vcpu->kvm, gfn), current);
return 0;
- } else if (is_fault_pfn(pfn))
- return -EFAULT;
+ }
- return 1;
+ return -EFAULT;
}
static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
@@ -2360,6 +2552,30 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
}
}
+static bool mmu_invalid_pfn(pfn_t pfn)
+{
+ return unlikely(is_invalid_pfn(pfn));
+}
+
+static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
+ pfn_t pfn, unsigned access, int *ret_val)
+{
+ bool ret = true;
+
+ /* The pfn is invalid, report the error! */
+ if (unlikely(is_invalid_pfn(pfn))) {
+ *ret_val = kvm_handle_bad_page(vcpu, gfn, pfn);
+ goto exit;
+ }
+
+ if (unlikely(is_noslot_pfn(pfn)))
+ vcpu_cache_mmio_info(vcpu, gva, gfn, access);
+
+ ret = false;
+exit:
+ return ret;
+}
+
static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
gva_t gva, pfn_t *pfn, bool write, bool *writable);
@@ -2394,9 +2610,8 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn,
if (try_async_pf(vcpu, prefault, gfn, v, &pfn, write, &map_writable))
return 0;
- /* mmio */
- if (is_error_pfn(pfn))
- return kvm_handle_bad_page(vcpu->kvm, gfn, pfn);
+ if (handle_abnormal_pfn(vcpu, v, gfn, pfn, ACC_ALL, &r))
+ return r;
spin_lock(&vcpu->kvm->mmu_lock);
if (mmu_notifier_retry(vcpu, mmu_seq))
@@ -2623,6 +2838,7 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu)
if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
return;
+ vcpu_clear_mmio_info(vcpu, ~0ul);
trace_kvm_mmu_audit(vcpu, AUDIT_PRE_SYNC);
if (vcpu->arch.mmu.root_level == PT64_ROOT_LEVEL) {
hpa_t root = vcpu->arch.mmu.root_hpa;
@@ -2667,6 +2883,94 @@ static gpa_t nonpaging_gva_to_gpa_nested(struct kvm_vcpu *vcpu, gva_t vaddr,
return vcpu->arch.nested_mmu.translate_gpa(vcpu, vaddr, access);
}
+static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+{
+ if (direct)
+ return vcpu_match_mmio_gpa(vcpu, addr);
+
+ return vcpu_match_mmio_gva(vcpu, addr);
+}
+
+
+/*
+ * On direct hosts, the last spte is only allows two states
+ * for mmio page fault:
+ * - It is the mmio spte
+ * - It is zapped or it is being zapped.
+ *
+ * This function completely checks the spte when the last spte
+ * is not the mmio spte.
+ */
+static bool check_direct_spte_mmio_pf(u64 spte)
+{
+ return __check_direct_spte_mmio_pf(spte);
+}
+
+static u64 walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr)
+{
+ struct kvm_shadow_walk_iterator iterator;
+ u64 spte = 0ull;
+
+ walk_shadow_page_lockless_begin(vcpu);
+ for_each_shadow_entry_lockless(vcpu, addr, iterator, spte)
+ if (!is_shadow_present_pte(spte))
+ break;
+ walk_shadow_page_lockless_end(vcpu);
+
+ return spte;
+}
+
+/*
+ * If it is a real mmio page fault, return 1 and emulat the instruction
+ * directly, return 0 to let CPU fault again on the address, -1 is
+ * returned if bug is detected.
+ */
+int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+{
+ u64 spte;
+
+ if (quickly_check_mmio_pf(vcpu, addr, direct))
+ return 1;
+
+ spte = walk_shadow_page_get_mmio_spte(vcpu, addr);
+
+ if (is_mmio_spte(spte)) {
+ gfn_t gfn = get_mmio_spte_gfn(spte);
+ unsigned access = get_mmio_spte_access(spte);
+
+ if (direct)
+ addr = 0;
+
+ trace_handle_mmio_page_fault(addr, gfn, access);
+ vcpu_cache_mmio_info(vcpu, addr, gfn, access);
+ return 1;
+ }
+
+ /*
+ * It's ok if the gva is remapped by other cpus on shadow guest,
+ * it's a BUG if the gfn is not a mmio page.
+ */
+ if (direct && !check_direct_spte_mmio_pf(spte))
+ return -1;
+
+ /*
+ * If the page table is zapped by other cpus, let CPU fault again on
+ * the address.
+ */
+ return 0;
+}
+EXPORT_SYMBOL_GPL(handle_mmio_page_fault_common);
+
+static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr,
+ u32 error_code, bool direct)
+{
+ int ret;
+
+ ret = handle_mmio_page_fault_common(vcpu, addr, direct);
+ WARN_ON(ret < 0);
+ return ret;
+}
+
static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
u32 error_code, bool prefault)
{
@@ -2674,6 +2978,10 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
int r;
pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
+
+ if (unlikely(error_code & PFERR_RSVD_MASK))
+ return handle_mmio_page_fault(vcpu, gva, error_code, true);
+
r = mmu_topup_memory_caches(vcpu);
if (r)
return r;
@@ -2750,6 +3058,9 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
ASSERT(vcpu);
ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa));
+ if (unlikely(error_code & PFERR_RSVD_MASK))
+ return handle_mmio_page_fault(vcpu, gpa, error_code, true);
+
r = mmu_topup_memory_caches(vcpu);
if (r)
return r;
@@ -2767,9 +3078,9 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
if (try_async_pf(vcpu, prefault, gfn, gpa, &pfn, write, &map_writable))
return 0;
- /* mmio */
- if (is_error_pfn(pfn))
- return kvm_handle_bad_page(vcpu->kvm, gfn, pfn);
+ if (handle_abnormal_pfn(vcpu, 0, gfn, pfn, ACC_ALL, &r))
+ return r;
+
spin_lock(&vcpu->kvm->mmu_lock);
if (mmu_notifier_retry(vcpu, mmu_seq))
goto out_unlock;
@@ -2800,7 +3111,6 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu,
context->page_fault = nonpaging_page_fault;
context->gva_to_gpa = nonpaging_gva_to_gpa;
context->free = nonpaging_free;
- context->prefetch_page = nonpaging_prefetch_page;
context->sync_page = nonpaging_sync_page;
context->invlpg = nonpaging_invlpg;
context->update_pte = nonpaging_update_pte;
@@ -2848,6 +3158,23 @@ static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0;
}
+static bool sync_mmio_spte(u64 *sptep, gfn_t gfn, unsigned access,
+ int *nr_present)
+{
+ if (unlikely(is_mmio_spte(*sptep))) {
+ if (gfn != get_mmio_spte_gfn(*sptep)) {
+ mmu_spte_clear_no_track(sptep);
+ return true;
+ }
+
+ (*nr_present)++;
+ mark_mmio_spte(sptep, gfn, access);
+ return true;
+ }
+
+ return false;
+}
+
#define PTTYPE 64
#include "paging_tmpl.h"
#undef PTTYPE
@@ -2930,7 +3257,6 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
context->new_cr3 = paging_new_cr3;
context->page_fault = paging64_page_fault;
context->gva_to_gpa = paging64_gva_to_gpa;
- context->prefetch_page = paging64_prefetch_page;
context->sync_page = paging64_sync_page;
context->invlpg = paging64_invlpg;
context->update_pte = paging64_update_pte;
@@ -2959,7 +3285,6 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
context->page_fault = paging32_page_fault;
context->gva_to_gpa = paging32_gva_to_gpa;
context->free = paging_free;
- context->prefetch_page = paging32_prefetch_page;
context->sync_page = paging32_sync_page;
context->invlpg = paging32_invlpg;
context->update_pte = paging32_update_pte;
@@ -2984,7 +3309,6 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
context->new_cr3 = nonpaging_new_cr3;
context->page_fault = tdp_page_fault;
context->free = nonpaging_free;
- context->prefetch_page = nonpaging_prefetch_page;
context->sync_page = nonpaging_sync_page;
context->invlpg = nonpaging_invlpg;
context->update_pte = nonpaging_update_pte;
@@ -3023,6 +3347,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
{
int r;
+ bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
ASSERT(vcpu);
ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa));
@@ -3037,6 +3362,8 @@ int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
vcpu->arch.mmu.base_role.cr4_pae = !!is_pae(vcpu);
vcpu->arch.mmu.base_role.cr0_wp = is_write_protection(vcpu);
+ vcpu->arch.mmu.base_role.smep_andnot_wp
+ = smep && !is_write_protection(vcpu);
return r;
}
@@ -3141,27 +3468,6 @@ void kvm_mmu_unload(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_mmu_unload);
-static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *sp,
- u64 *spte)
-{
- u64 pte;
- struct kvm_mmu_page *child;
-
- pte = *spte;
- if (is_shadow_present_pte(pte)) {
- if (is_last_spte(pte, sp->role.level))
- drop_spte(vcpu->kvm, spte, shadow_trap_nonpresent_pte);
- else {
- child = page_header(pte & PT64_BASE_ADDR_MASK);
- mmu_page_remove_parent_pte(child, spte);
- }
- }
- __set_spte(spte, shadow_trap_nonpresent_pte);
- if (is_large_pte(pte))
- --vcpu->kvm->stat.lpages;
-}
-
static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
struct kvm_mmu_page *sp, u64 *spte,
const void *new)
@@ -3233,6 +3539,13 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
int level, npte, invlpg_counter, r, flooded = 0;
bool remote_flush, local_flush, zap_page;
+ /*
+ * If we don't have indirect shadow pages, it means no page is
+ * write-protected, so we can exit simply.
+ */
+ if (!ACCESS_ONCE(vcpu->kvm->arch.indirect_shadow_pages))
+ return;
+
zap_page = remote_flush = local_flush = false;
offset = offset_in_page(gpa);
@@ -3336,7 +3649,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
spte = &sp->spt[page_offset / sizeof(*spte)];
while (npte--) {
entry = *spte;
- mmu_pte_write_zap_pte(vcpu, sp, spte);
+ mmu_page_zap_pte(vcpu->kvm, sp, spte);
if (gentry &&
!((sp->role.word ^ vcpu->arch.mmu.base_role.word)
& mask.word))
@@ -3380,9 +3693,9 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
sp = container_of(vcpu->kvm->arch.active_mmu_pages.prev,
struct kvm_mmu_page, link);
kvm_mmu_prepare_zap_page(vcpu->kvm, sp, &invalid_list);
- kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
++vcpu->kvm->stat.mmu_recycled;
}
+ kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
}
int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
@@ -3506,15 +3819,15 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
continue;
if (is_large_pte(pt[i])) {
- drop_spte(kvm, &pt[i],
- shadow_trap_nonpresent_pte);
+ drop_spte(kvm, &pt[i]);
--kvm->stat.lpages;
continue;
}
/* avoid RMW */
if (is_writable_pte(pt[i]))
- update_spte(&pt[i], pt[i] & ~PT_WRITABLE_MASK);
+ mmu_spte_update(&pt[i],
+ pt[i] & ~PT_WRITABLE_MASK);
}
}
kvm_flush_remote_tlbs(kvm);
@@ -3590,25 +3903,18 @@ static struct shrinker mmu_shrinker = {
static void mmu_destroy_caches(void)
{
- if (pte_chain_cache)
- kmem_cache_destroy(pte_chain_cache);
- if (rmap_desc_cache)
- kmem_cache_destroy(rmap_desc_cache);
+ if (pte_list_desc_cache)
+ kmem_cache_destroy(pte_list_desc_cache);
if (mmu_page_header_cache)
kmem_cache_destroy(mmu_page_header_cache);
}
int kvm_mmu_module_init(void)
{
- pte_chain_cache = kmem_cache_create("kvm_pte_chain",
- sizeof(struct kvm_pte_chain),
- 0, 0, NULL);
- if (!pte_chain_cache)
- goto nomem;
- rmap_desc_cache = kmem_cache_create("kvm_rmap_desc",
- sizeof(struct kvm_rmap_desc),
+ pte_list_desc_cache = kmem_cache_create("pte_list_desc",
+ sizeof(struct pte_list_desc),
0, 0, NULL);
- if (!rmap_desc_cache)
+ if (!pte_list_desc_cache)
goto nomem;
mmu_page_header_cache = kmem_cache_create("kvm_mmu_page_header",
@@ -3775,16 +4081,17 @@ out:
int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])
{
struct kvm_shadow_walk_iterator iterator;
+ u64 spte;
int nr_sptes = 0;
- spin_lock(&vcpu->kvm->mmu_lock);
- for_each_shadow_entry(vcpu, addr, iterator) {
- sptes[iterator.level-1] = *iterator.sptep;
+ walk_shadow_page_lockless_begin(vcpu);
+ for_each_shadow_entry_lockless(vcpu, addr, iterator, spte) {
+ sptes[iterator.level-1] = spte;
nr_sptes++;
- if (!is_shadow_present_pte(*iterator.sptep))
+ if (!is_shadow_present_pte(spte))
break;
}
- spin_unlock(&vcpu->kvm->mmu_lock);
+ walk_shadow_page_lockless_end(vcpu);
return nr_sptes;
}
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 7086ca85d3e7..e374db9af021 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -49,6 +49,8 @@
#define PFERR_FETCH_MASK (1U << 4)
int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
+void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask);
+int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct);
int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
@@ -76,4 +78,27 @@ static inline int is_present_gpte(unsigned long pte)
return pte & PT_PRESENT_MASK;
}
+static inline int is_writable_pte(unsigned long pte)
+{
+ return pte & PT_WRITABLE_MASK;
+}
+
+static inline bool is_write_protection(struct kvm_vcpu *vcpu)
+{
+ return kvm_read_cr0_bits(vcpu, X86_CR0_WP);
+}
+
+static inline bool check_write_user_access(struct kvm_vcpu *vcpu,
+ bool write_fault, bool user_fault,
+ unsigned long pte)
+{
+ if (unlikely(write_fault && !is_writable_pte(pte)
+ && (user_fault || is_write_protection(vcpu))))
+ return false;
+
+ if (unlikely(user_fault && !(pte & PT_USER_MASK)))
+ return false;
+
+ return true;
+}
#endif
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c
index 5f6223b8bcf7..2460a265be23 100644
--- a/arch/x86/kvm/mmu_audit.c
+++ b/arch/x86/kvm/mmu_audit.c
@@ -99,18 +99,6 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)
"level = %d\n", sp, level);
return;
}
-
- if (*sptep == shadow_notrap_nonpresent_pte) {
- audit_printk(vcpu->kvm, "notrap spte in unsync "
- "sp: %p\n", sp);
- return;
- }
- }
-
- if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) {
- audit_printk(vcpu->kvm, "notrap spte in direct sp: %p\n",
- sp);
- return;
}
if (!is_shadow_present_pte(*sptep) || !is_last_spte(*sptep, level))
diff --git a/arch/x86/kvm/mmutrace.h b/arch/x86/kvm/mmutrace.h
index b60b4fdb3eda..eed67f34146d 100644
--- a/arch/x86/kvm/mmutrace.h
+++ b/arch/x86/kvm/mmutrace.h
@@ -196,6 +196,54 @@ DEFINE_EVENT(kvm_mmu_page_class, kvm_mmu_prepare_zap_page,
TP_ARGS(sp)
);
+DEFINE_EVENT(kvm_mmu_page_class, kvm_mmu_delay_free_pages,
+ TP_PROTO(struct kvm_mmu_page *sp),
+
+ TP_ARGS(sp)
+);
+
+TRACE_EVENT(
+ mark_mmio_spte,
+ TP_PROTO(u64 *sptep, gfn_t gfn, unsigned access),
+ TP_ARGS(sptep, gfn, access),
+
+ TP_STRUCT__entry(
+ __field(void *, sptep)
+ __field(gfn_t, gfn)
+ __field(unsigned, access)
+ ),
+
+ TP_fast_assign(
+ __entry->sptep = sptep;
+ __entry->gfn = gfn;
+ __entry->access = access;
+ ),
+
+ TP_printk("sptep:%p gfn %llx access %x", __entry->sptep, __entry->gfn,
+ __entry->access)
+);
+
+TRACE_EVENT(
+ handle_mmio_page_fault,
+ TP_PROTO(u64 addr, gfn_t gfn, unsigned access),
+ TP_ARGS(addr, gfn, access),
+
+ TP_STRUCT__entry(
+ __field(u64, addr)
+ __field(gfn_t, gfn)
+ __field(unsigned, access)
+ ),
+
+ TP_fast_assign(
+ __entry->addr = addr;
+ __entry->gfn = gfn;
+ __entry->access = access;
+ ),
+
+ TP_printk("addr:%llx gfn %llx access %x", __entry->addr, __entry->gfn,
+ __entry->access)
+);
+
TRACE_EVENT(
kvm_mmu_audit,
TP_PROTO(struct kvm_vcpu *vcpu, int audit_point),
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 9d03ad4dd5ec..507e2b844cfa 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -101,11 +101,15 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
return (ret != orig_pte);
}
-static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte)
+static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte,
+ bool last)
{
unsigned access;
access = (gpte & (PT_WRITABLE_MASK | PT_USER_MASK)) | ACC_EXEC_MASK;
+ if (last && !is_dirty_gpte(gpte))
+ access &= ~ACC_WRITE_MASK;
+
#if PTTYPE == 64
if (vcpu->arch.mmu.nx)
access &= ~(gpte >> PT64_NX_SHIFT);
@@ -113,6 +117,24 @@ static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte)
return access;
}
+static bool FNAME(is_last_gpte)(struct guest_walker *walker,
+ struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+ pt_element_t gpte)
+{
+ if (walker->level == PT_PAGE_TABLE_LEVEL)
+ return true;
+
+ if ((walker->level == PT_DIRECTORY_LEVEL) && is_large_pte(gpte) &&
+ (PTTYPE == 64 || is_pse(vcpu)))
+ return true;
+
+ if ((walker->level == PT_PDPE_LEVEL) && is_large_pte(gpte) &&
+ (mmu->root_level == PT64_ROOT_LEVEL))
+ return true;
+
+ return false;
+}
+
/*
* Fetch a guest pte for a guest virtual address
*/
@@ -125,18 +147,17 @@ 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, present, rsvd_fault;
- int offset, write_fault, user_fault, fetch_fault;
-
- write_fault = access & PFERR_WRITE_MASK;
- user_fault = access & PFERR_USER_MASK;
- fetch_fault = access & PFERR_FETCH_MASK;
+ bool eperm;
+ int offset;
+ const int write_fault = access & PFERR_WRITE_MASK;
+ const int user_fault = access & PFERR_USER_MASK;
+ const int fetch_fault = access & PFERR_FETCH_MASK;
+ u16 errcode = 0;
trace_kvm_mmu_pagetable_walk(addr, write_fault, user_fault,
fetch_fault);
-walk:
- present = true;
- eperm = rsvd_fault = false;
+retry_walk:
+ eperm = false;
walker->level = mmu->root_level;
pte = mmu->get_cr3(vcpu);
@@ -144,10 +165,8 @@ walk:
if (walker->level == PT32E_ROOT_LEVEL) {
pte = kvm_pdptr_read_mmu(vcpu, mmu, (addr >> 30) & 3);
trace_kvm_mmu_paging_element(pte, walker->level);
- if (!is_present_gpte(pte)) {
- present = false;
+ if (!is_present_gpte(pte))
goto error;
- }
--walker->level;
}
#endif
@@ -170,42 +189,31 @@ walk:
real_gfn = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
PFERR_USER_MASK|PFERR_WRITE_MASK);
- if (unlikely(real_gfn == UNMAPPED_GVA)) {
- present = false;
- break;
- }
+ if (unlikely(real_gfn == UNMAPPED_GVA))
+ goto error;
real_gfn = gpa_to_gfn(real_gfn);
host_addr = gfn_to_hva(vcpu->kvm, real_gfn);
- if (unlikely(kvm_is_error_hva(host_addr))) {
- present = false;
- break;
- }
+ if (unlikely(kvm_is_error_hva(host_addr)))
+ goto error;
ptep_user = (pt_element_t __user *)((void *)host_addr + offset);
- if (unlikely(__copy_from_user(&pte, ptep_user, sizeof(pte)))) {
- present = false;
- break;
- }
+ if (unlikely(__copy_from_user(&pte, ptep_user, sizeof(pte))))
+ goto error;
trace_kvm_mmu_paging_element(pte, walker->level);
- if (unlikely(!is_present_gpte(pte))) {
- present = false;
- break;
- }
+ if (unlikely(!is_present_gpte(pte)))
+ goto error;
if (unlikely(is_rsvd_bits_set(&vcpu->arch.mmu, pte,
walker->level))) {
- rsvd_fault = true;
- break;
+ errcode |= PFERR_RSVD_MASK | PFERR_PRESENT_MASK;
+ goto error;
}
- if (unlikely(write_fault && !is_writable_pte(pte)
- && (user_fault || is_write_protection(vcpu))))
- eperm = true;
-
- if (unlikely(user_fault && !(pte & PT_USER_MASK)))
+ if (!check_write_user_access(vcpu, write_fault, user_fault,
+ pte))
eperm = true;
#if PTTYPE == 64
@@ -213,39 +221,35 @@ walk:
eperm = true;
#endif
- if (!eperm && !rsvd_fault
- && unlikely(!(pte & PT_ACCESSED_MASK))) {
+ if (!eperm && unlikely(!(pte & PT_ACCESSED_MASK))) {
int ret;
trace_kvm_mmu_set_accessed_bit(table_gfn, index,
sizeof(pte));
ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index,
pte, pte|PT_ACCESSED_MASK);
- if (unlikely(ret < 0)) {
- present = false;
- break;
- } else if (ret)
- goto walk;
+ if (unlikely(ret < 0))
+ goto error;
+ else if (ret)
+ goto retry_walk;
mark_page_dirty(vcpu->kvm, table_gfn);
pte |= PT_ACCESSED_MASK;
}
- pte_access = pt_access & FNAME(gpte_access)(vcpu, pte);
-
walker->ptes[walker->level - 1] = pte;
- if ((walker->level == PT_PAGE_TABLE_LEVEL) ||
- ((walker->level == PT_DIRECTORY_LEVEL) &&
- is_large_pte(pte) &&
- (PTTYPE == 64 || is_pse(vcpu))) ||
- ((walker->level == PT_PDPE_LEVEL) &&
- is_large_pte(pte) &&
- mmu->root_level == PT64_ROOT_LEVEL)) {
+ if (FNAME(is_last_gpte)(walker, vcpu, mmu, pte)) {
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;
@@ -266,12 +270,14 @@ walk:
break;
}
- pt_access = pte_access;
+ pt_access &= FNAME(gpte_access)(vcpu, pte, false);
--walker->level;
}
- if (unlikely(!present || eperm || rsvd_fault))
+ if (unlikely(eperm)) {
+ errcode |= PFERR_PRESENT_MASK;
goto error;
+ }
if (write_fault && unlikely(!is_dirty_gpte(pte))) {
int ret;
@@ -279,17 +285,17 @@ walk:
trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index,
pte, pte|PT_DIRTY_MASK);
- if (unlikely(ret < 0)) {
- present = false;
+ if (unlikely(ret < 0))
goto error;
- } else if (ret)
- goto walk;
+ else if (ret)
+ goto retry_walk;
mark_page_dirty(vcpu->kvm, table_gfn);
pte |= PT_DIRTY_MASK;
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",
@@ -297,19 +303,14 @@ walk:
return 1;
error:
+ errcode |= write_fault | user_fault;
+ if (fetch_fault && (mmu->nx ||
+ kvm_read_cr4_bits(vcpu, X86_CR4_SMEP)))
+ errcode |= PFERR_FETCH_MASK;
+
walker->fault.vector = PF_VECTOR;
walker->fault.error_code_valid = true;
- walker->fault.error_code = 0;
- if (present)
- walker->fault.error_code |= PFERR_PRESENT_MASK;
-
- walker->fault.error_code |= write_fault | user_fault;
-
- if (fetch_fault && mmu->nx)
- walker->fault.error_code |= PFERR_FETCH_MASK;
- if (rsvd_fault)
- walker->fault.error_code |= PFERR_RSVD_MASK;
-
+ walker->fault.error_code = errcode;
walker->fault.address = addr;
walker->fault.nested_page_fault = mmu != vcpu->arch.walk_mmu;
@@ -336,16 +337,11 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
struct kvm_mmu_page *sp, u64 *spte,
pt_element_t gpte)
{
- u64 nonpresent = shadow_trap_nonpresent_pte;
-
if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
goto no_present;
- if (!is_present_gpte(gpte)) {
- if (!sp->unsync)
- nonpresent = shadow_notrap_nonpresent_pte;
+ if (!is_present_gpte(gpte))
goto no_present;
- }
if (!(gpte & PT_ACCESSED_MASK))
goto no_present;
@@ -353,7 +349,7 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
return false;
no_present:
- drop_spte(vcpu->kvm, spte, nonpresent);
+ drop_spte(vcpu->kvm, spte);
return true;
}
@@ -369,9 +365,9 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
return;
pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
- pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+ pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte, true);
pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
- if (is_error_pfn(pfn)) {
+ if (mmu_invalid_pfn(pfn)) {
kvm_release_pfn_clean(pfn);
return;
}
@@ -381,7 +377,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
* vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
*/
mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
- is_dirty_gpte(gpte), NULL, PT_PAGE_TABLE_LEVEL,
+ NULL, PT_PAGE_TABLE_LEVEL,
gpte_to_gfn(gpte), pfn, true, true);
}
@@ -432,12 +428,11 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
unsigned pte_access;
gfn_t gfn;
pfn_t pfn;
- bool dirty;
if (spte == sptep)
continue;
- if (*spte != shadow_trap_nonpresent_pte)
+ if (is_shadow_present_pte(*spte))
continue;
gpte = gptep[i];
@@ -445,18 +440,18 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
continue;
- pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+ pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte,
+ true);
gfn = gpte_to_gfn(gpte);
- dirty = is_dirty_gpte(gpte);
pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
- (pte_access & ACC_WRITE_MASK) && dirty);
- if (is_error_pfn(pfn)) {
+ pte_access & ACC_WRITE_MASK);
+ if (mmu_invalid_pfn(pfn)) {
kvm_release_pfn_clean(pfn);
break;
}
mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
- dirty, NULL, PT_PAGE_TABLE_LEVEL, gfn,
+ NULL, PT_PAGE_TABLE_LEVEL, gfn,
pfn, true, true);
}
}
@@ -467,12 +462,11 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
struct guest_walker *gw,
int user_fault, int write_fault, int hlevel,
- int *ptwrite, pfn_t pfn, bool map_writable,
+ int *emulate, pfn_t pfn, bool map_writable,
bool prefault)
{
unsigned access = gw->pt_access;
struct kvm_mmu_page *sp = NULL;
- bool dirty = is_dirty_gpte(gw->ptes[gw->level - 1]);
int top_level;
unsigned direct_access;
struct kvm_shadow_walk_iterator it;
@@ -480,9 +474,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
if (!is_present_gpte(gw->ptes[gw->level - 1]))
return NULL;
- direct_access = gw->pt_access & gw->pte_access;
- if (!dirty)
- direct_access &= ~ACC_WRITE_MASK;
+ direct_access = gw->pte_access;
top_level = vcpu->arch.mmu.root_level;
if (top_level == PT32E_ROOT_LEVEL)
@@ -540,8 +532,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
link_shadow_page(it.sptep, sp);
}
- mmu_set_spte(vcpu, it.sptep, access, gw->pte_access & access,
- user_fault, write_fault, dirty, ptwrite, it.level,
+ mmu_set_spte(vcpu, it.sptep, access, gw->pte_access,
+ user_fault, write_fault, emulate, it.level,
gw->gfn, pfn, prefault, map_writable);
FNAME(pte_prefetch)(vcpu, gw, it.sptep);
@@ -575,7 +567,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
int user_fault = error_code & PFERR_USER_MASK;
struct guest_walker walker;
u64 *sptep;
- int write_pt = 0;
+ int emulate = 0;
int r;
pfn_t pfn;
int level = PT_PAGE_TABLE_LEVEL;
@@ -585,6 +577,10 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
+ if (unlikely(error_code & PFERR_RSVD_MASK))
+ return handle_mmio_page_fault(vcpu, addr, error_code,
+ mmu_is_nested(vcpu));
+
r = mmu_topup_memory_caches(vcpu);
if (r)
return r;
@@ -623,9 +619,9 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
&map_writable))
return 0;
- /* mmio */
- if (is_error_pfn(pfn))
- return kvm_handle_bad_page(vcpu->kvm, walker.gfn, pfn);
+ if (handle_abnormal_pfn(vcpu, mmu_is_nested(vcpu) ? 0 : addr,
+ walker.gfn, pfn, walker.pte_access, &r))
+ return r;
spin_lock(&vcpu->kvm->mmu_lock);
if (mmu_notifier_retry(vcpu, mmu_seq))
@@ -636,19 +632,19 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
if (!force_pt_level)
transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
- level, &write_pt, pfn, map_writable, prefault);
+ level, &emulate, pfn, map_writable, prefault);
(void)sptep;
- pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __func__,
- sptep, *sptep, write_pt);
+ pgprintk("%s: shadow pte %p %llx emulate %d\n", __func__,
+ sptep, *sptep, emulate);
- if (!write_pt)
+ if (!emulate)
vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
++vcpu->stat.pf_fixed;
trace_kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT);
spin_unlock(&vcpu->kvm->mmu_lock);
- return write_pt;
+ return emulate;
out_unlock:
spin_unlock(&vcpu->kvm->mmu_lock);
@@ -665,6 +661,8 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
u64 *sptep;
int need_flush = 0;
+ vcpu_clear_mmio_info(vcpu, gva);
+
spin_lock(&vcpu->kvm->mmu_lock);
for_each_shadow_entry(vcpu, gva, iterator) {
@@ -688,11 +686,11 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
if (is_shadow_present_pte(*sptep)) {
if (is_large_pte(*sptep))
--vcpu->kvm->stat.lpages;
- drop_spte(vcpu->kvm, sptep,
- shadow_trap_nonpresent_pte);
+ drop_spte(vcpu->kvm, sptep);
need_flush = 1;
- } else
- __set_spte(sptep, shadow_trap_nonpresent_pte);
+ } else if (is_mmio_spte(*sptep))
+ mmu_spte_clear_no_track(sptep);
+
break;
}
@@ -752,36 +750,6 @@ static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gva_t vaddr,
return gpa;
}
-static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *sp)
-{
- int i, j, offset, r;
- pt_element_t pt[256 / sizeof(pt_element_t)];
- gpa_t pte_gpa;
-
- if (sp->role.direct
- || (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) {
- nonpaging_prefetch_page(vcpu, sp);
- return;
- }
-
- pte_gpa = gfn_to_gpa(sp->gfn);
- if (PTTYPE == 32) {
- offset = sp->role.quadrant << PT64_LEVEL_BITS;
- pte_gpa += offset * sizeof(pt_element_t);
- }
-
- for (i = 0; i < PT64_ENT_PER_PAGE; i += ARRAY_SIZE(pt)) {
- r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, pt, sizeof pt);
- pte_gpa += ARRAY_SIZE(pt) * sizeof(pt_element_t);
- for (j = 0; j < ARRAY_SIZE(pt); ++j)
- if (r || is_present_gpte(pt[j]))
- sp->spt[i+j] = shadow_trap_nonpresent_pte;
- else
- sp->spt[i+j] = shadow_notrap_nonpresent_pte;
- }
-}
-
/*
* Using the cached information from sp->gfns is safe because:
* - The spte has a reference to the struct page, so the pfn for a given gfn
@@ -817,7 +785,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
gpa_t pte_gpa;
gfn_t gfn;
- if (!is_shadow_present_pte(sp->spt[i]))
+ if (!sp->spt[i])
continue;
pte_gpa = first_pte_gpa + i * sizeof(pt_element_t);
@@ -826,26 +794,30 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
sizeof(pt_element_t)))
return -EINVAL;
- gfn = gpte_to_gfn(gpte);
-
if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) {
vcpu->kvm->tlbs_dirty++;
continue;
}
+ gfn = gpte_to_gfn(gpte);
+ pte_access = sp->role.access;
+ pte_access &= FNAME(gpte_access)(vcpu, gpte, true);
+
+ if (sync_mmio_spte(&sp->spt[i], gfn, pte_access, &nr_present))
+ continue;
+
if (gfn != sp->gfns[i]) {
- drop_spte(vcpu->kvm, &sp->spt[i],
- shadow_trap_nonpresent_pte);
+ drop_spte(vcpu->kvm, &sp->spt[i]);
vcpu->kvm->tlbs_dirty++;
continue;
}
nr_present++;
- pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+
host_writable = sp->spt[i] & SPTE_HOST_WRITEABLE;
set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
- is_dirty_gpte(gpte), PT_PAGE_TABLE_LEVEL, gfn,
+ PT_PAGE_TABLE_LEVEL, gfn,
spte_to_pfn(sp->spt[i]), true, false,
host_writable);
}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 506e4fe23adc..475d1c948501 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1496,11 +1496,14 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
update_cr0_intercept(svm);
}
-static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+static int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
{
unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE;
unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
+ if (cr4 & X86_CR4_VMXE)
+ return 1;
+
if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
svm_flush_tlb(vcpu);
@@ -1510,6 +1513,7 @@ static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
cr4 |= host_cr4_mce;
to_svm(vcpu)->vmcb->save.cr4 = cr4;
mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
+ return 0;
}
static void svm_set_segment(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
index abd86e865be3..ae432ea1cd83 100644
--- a/arch/x86/kvm/timer.c
+++ b/arch/x86/kvm/timer.c
@@ -15,7 +15,7 @@
#include <linux/kvm_host.h>
#include <linux/kvm.h>
#include <linux/hrtimer.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "kvm_timer.h"
static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index db932760ea82..3ff898c104f7 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -675,12 +675,12 @@ TRACE_EVENT(kvm_emulate_insn,
),
TP_fast_assign(
- __entry->rip = vcpu->arch.emulate_ctxt.decode.fetch.start;
+ __entry->rip = vcpu->arch.emulate_ctxt.fetch.start;
__entry->csbase = kvm_x86_ops->get_segment_base(vcpu, VCPU_SREG_CS);
- __entry->len = vcpu->arch.emulate_ctxt.decode.eip
- - vcpu->arch.emulate_ctxt.decode.fetch.start;
+ __entry->len = vcpu->arch.emulate_ctxt._eip
+ - vcpu->arch.emulate_ctxt.fetch.start;
memcpy(__entry->insn,
- vcpu->arch.emulate_ctxt.decode.fetch.data,
+ vcpu->arch.emulate_ctxt.fetch.data,
15);
__entry->flags = kei_decode_mode(vcpu->arch.emulate_ctxt.mode);
__entry->failed = failed;
@@ -698,6 +698,29 @@ TRACE_EVENT(kvm_emulate_insn,
#define trace_kvm_emulate_insn_start(vcpu) trace_kvm_emulate_insn(vcpu, 0)
#define trace_kvm_emulate_insn_failed(vcpu) trace_kvm_emulate_insn(vcpu, 1)
+TRACE_EVENT(
+ vcpu_match_mmio,
+ TP_PROTO(gva_t gva, gpa_t gpa, bool write, bool gpa_match),
+ TP_ARGS(gva, gpa, write, gpa_match),
+
+ TP_STRUCT__entry(
+ __field(gva_t, gva)
+ __field(gpa_t, gpa)
+ __field(bool, write)
+ __field(bool, gpa_match)
+ ),
+
+ TP_fast_assign(
+ __entry->gva = gva;
+ __entry->gpa = gpa;
+ __entry->write = write;
+ __entry->gpa_match = gpa_match
+ ),
+
+ TP_printk("gva %#lx gpa %#llx %s %s", __entry->gva, __entry->gpa,
+ __entry->write ? "Write" : "Read",
+ __entry->gpa_match ? "GPA" : "GVA")
+);
#endif /* _TRACE_KVM_H */
#undef TRACE_INCLUDE_PATH
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d48ec60ea421..e65a158dee64 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -43,13 +43,12 @@
#include "trace.h"
#define __ex(x) __kvm_handle_fault_on_reboot(x)
+#define __ex_clear(x, reg) \
+ ____kvm_handle_fault_on_reboot(x, "xor " reg " , " reg)
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
-static int __read_mostly bypass_guest_pf = 1;
-module_param(bypass_guest_pf, bool, S_IRUGO);
-
static int __read_mostly enable_vpid = 1;
module_param_named(vpid, enable_vpid, bool, 0444);
@@ -72,6 +71,14 @@ module_param(vmm_exclusive, bool, S_IRUGO);
static int __read_mostly yield_on_hlt = 1;
module_param(yield_on_hlt, 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
+ * use VMX instructions.
+ */
+static int __read_mostly nested = 0;
+module_param(nested, bool, S_IRUGO);
+
#define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST \
(X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD)
#define KVM_GUEST_CR0_MASK \
@@ -109,6 +116,7 @@ static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
module_param(ple_window, int, S_IRUGO);
#define NR_AUTOLOAD_MSRS 1
+#define VMCS02_POOL_SIZE 1
struct vmcs {
u32 revision_id;
@@ -116,17 +124,237 @@ struct vmcs {
char data[0];
};
+/*
+ * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=-1), also
+ * remember whether it was VMLAUNCHed, and maintain a linked list of all VMCSs
+ * loaded on this CPU (so we can clear them if the CPU goes down).
+ */
+struct loaded_vmcs {
+ struct vmcs *vmcs;
+ int cpu;
+ int launched;
+ struct list_head loaded_vmcss_on_cpu_link;
+};
+
struct shared_msr_entry {
unsigned index;
u64 data;
u64 mask;
};
+/*
+ * struct vmcs12 describes the state that our guest hypervisor (L1) keeps for a
+ * single nested guest (L2), hence the name vmcs12. Any VMX implementation has
+ * a VMCS structure, and vmcs12 is our emulated VMX's VMCS. This structure is
+ * stored in guest memory specified by VMPTRLD, but is opaque to the guest,
+ * which must access it using VMREAD/VMWRITE/VMCLEAR instructions.
+ * More than one of these structures may exist, if L1 runs multiple L2 guests.
+ * nested_vmx_run() will use the data here to build a vmcs02: a VMCS for the
+ * underlying hardware which will be used to run L2.
+ * This structure is packed to ensure that its layout is identical across
+ * machines (necessary for live migration).
+ * If there are changes in this struct, VMCS12_REVISION must be changed.
+ */
+typedef u64 natural_width;
+struct __packed vmcs12 {
+ /* According to the Intel spec, a VMCS region must start with the
+ * following two fields. Then follow implementation-specific data.
+ */
+ u32 revision_id;
+ u32 abort;
+
+ u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+ u32 padding[7]; /* room for future expansion */
+
+ u64 io_bitmap_a;
+ u64 io_bitmap_b;
+ u64 msr_bitmap;
+ u64 vm_exit_msr_store_addr;
+ u64 vm_exit_msr_load_addr;
+ u64 vm_entry_msr_load_addr;
+ u64 tsc_offset;
+ u64 virtual_apic_page_addr;
+ u64 apic_access_addr;
+ u64 ept_pointer;
+ u64 guest_physical_address;
+ u64 vmcs_link_pointer;
+ u64 guest_ia32_debugctl;
+ u64 guest_ia32_pat;
+ u64 guest_ia32_efer;
+ u64 guest_ia32_perf_global_ctrl;
+ u64 guest_pdptr0;
+ u64 guest_pdptr1;
+ u64 guest_pdptr2;
+ u64 guest_pdptr3;
+ u64 host_ia32_pat;
+ u64 host_ia32_efer;
+ u64 host_ia32_perf_global_ctrl;
+ u64 padding64[8]; /* room for future expansion */
+ /*
+ * To allow migration of L1 (complete with its L2 guests) between
+ * machines of different natural widths (32 or 64 bit), we cannot have
+ * unsigned long fields with no explict size. We use u64 (aliased
+ * natural_width) instead. Luckily, x86 is little-endian.
+ */
+ natural_width cr0_guest_host_mask;
+ natural_width cr4_guest_host_mask;
+ natural_width cr0_read_shadow;
+ natural_width cr4_read_shadow;
+ natural_width cr3_target_value0;
+ natural_width cr3_target_value1;
+ natural_width cr3_target_value2;
+ natural_width cr3_target_value3;
+ natural_width exit_qualification;
+ natural_width guest_linear_address;
+ natural_width guest_cr0;
+ natural_width guest_cr3;
+ natural_width guest_cr4;
+ natural_width guest_es_base;
+ natural_width guest_cs_base;
+ natural_width guest_ss_base;
+ natural_width guest_ds_base;
+ natural_width guest_fs_base;
+ natural_width guest_gs_base;
+ natural_width guest_ldtr_base;
+ natural_width guest_tr_base;
+ natural_width guest_gdtr_base;
+ natural_width guest_idtr_base;
+ natural_width guest_dr7;
+ natural_width guest_rsp;
+ natural_width guest_rip;
+ natural_width guest_rflags;
+ natural_width guest_pending_dbg_exceptions;
+ natural_width guest_sysenter_esp;
+ natural_width guest_sysenter_eip;
+ natural_width host_cr0;
+ natural_width host_cr3;
+ natural_width host_cr4;
+ natural_width host_fs_base;
+ natural_width host_gs_base;
+ natural_width host_tr_base;
+ natural_width host_gdtr_base;
+ natural_width host_idtr_base;
+ natural_width host_ia32_sysenter_esp;
+ natural_width host_ia32_sysenter_eip;
+ natural_width host_rsp;
+ natural_width host_rip;
+ natural_width paddingl[8]; /* room for future expansion */
+ u32 pin_based_vm_exec_control;
+ u32 cpu_based_vm_exec_control;
+ u32 exception_bitmap;
+ u32 page_fault_error_code_mask;
+ u32 page_fault_error_code_match;
+ u32 cr3_target_count;
+ u32 vm_exit_controls;
+ u32 vm_exit_msr_store_count;
+ u32 vm_exit_msr_load_count;
+ u32 vm_entry_controls;
+ u32 vm_entry_msr_load_count;
+ u32 vm_entry_intr_info_field;
+ u32 vm_entry_exception_error_code;
+ u32 vm_entry_instruction_len;
+ u32 tpr_threshold;
+ u32 secondary_vm_exec_control;
+ u32 vm_instruction_error;
+ u32 vm_exit_reason;
+ u32 vm_exit_intr_info;
+ u32 vm_exit_intr_error_code;
+ u32 idt_vectoring_info_field;
+ u32 idt_vectoring_error_code;
+ u32 vm_exit_instruction_len;
+ u32 vmx_instruction_info;
+ u32 guest_es_limit;
+ u32 guest_cs_limit;
+ u32 guest_ss_limit;
+ u32 guest_ds_limit;
+ u32 guest_fs_limit;
+ u32 guest_gs_limit;
+ u32 guest_ldtr_limit;
+ u32 guest_tr_limit;
+ u32 guest_gdtr_limit;
+ u32 guest_idtr_limit;
+ u32 guest_es_ar_bytes;
+ u32 guest_cs_ar_bytes;
+ u32 guest_ss_ar_bytes;
+ u32 guest_ds_ar_bytes;
+ u32 guest_fs_ar_bytes;
+ u32 guest_gs_ar_bytes;
+ u32 guest_ldtr_ar_bytes;
+ u32 guest_tr_ar_bytes;
+ u32 guest_interruptibility_info;
+ u32 guest_activity_state;
+ u32 guest_sysenter_cs;
+ u32 host_ia32_sysenter_cs;
+ u32 padding32[8]; /* room for future expansion */
+ u16 virtual_processor_id;
+ u16 guest_es_selector;
+ u16 guest_cs_selector;
+ u16 guest_ss_selector;
+ u16 guest_ds_selector;
+ u16 guest_fs_selector;
+ u16 guest_gs_selector;
+ u16 guest_ldtr_selector;
+ u16 guest_tr_selector;
+ u16 host_es_selector;
+ u16 host_cs_selector;
+ u16 host_ss_selector;
+ u16 host_ds_selector;
+ u16 host_fs_selector;
+ u16 host_gs_selector;
+ u16 host_tr_selector;
+};
+
+/*
+ * VMCS12_REVISION is an arbitrary id that should be changed if the content or
+ * layout of struct vmcs12 is changed. MSR_IA32_VMX_BASIC returns this id, and
+ * VMPTRLD verifies that the VMCS region that L1 is loading contains this id.
+ */
+#define VMCS12_REVISION 0x11e57ed0
+
+/*
+ * VMCS12_SIZE is the number of bytes L1 should allocate for the VMXON region
+ * and any VMCS region. Although only sizeof(struct vmcs12) are used by the
+ * current implementation, 4K are reserved to avoid future complications.
+ */
+#define VMCS12_SIZE 0x1000
+
+/* Used to remember the last vmcs02 used for some recently used vmcs12s */
+struct vmcs02_list {
+ struct list_head list;
+ gpa_t vmptr;
+ struct loaded_vmcs vmcs02;
+};
+
+/*
+ * The nested_vmx structure is part of vcpu_vmx, and holds information we need
+ * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
+ */
+struct nested_vmx {
+ /* Has the level1 guest done vmxon? */
+ bool vmxon;
+
+ /* The guest-physical address of the current VMCS L1 keeps for L2 */
+ gpa_t current_vmptr;
+ /* The host-usable pointer to the above */
+ struct page *current_vmcs12_page;
+ struct vmcs12 *current_vmcs12;
+
+ /* vmcs02_list cache of VMCSs recently used to run L2 guests */
+ struct list_head vmcs02_pool;
+ int vmcs02_num;
+ u64 vmcs01_tsc_offset;
+ /* L2 must run next, and mustn't decide to exit to L1. */
+ bool nested_run_pending;
+ /*
+ * Guest pages referred to in vmcs02 with host-physical pointers, so
+ * we must keep them pinned while L2 runs.
+ */
+ struct page *apic_access_page;
+};
+
struct vcpu_vmx {
struct kvm_vcpu vcpu;
- struct list_head local_vcpus_link;
unsigned long host_rsp;
- int launched;
u8 fail;
u8 cpl;
bool nmi_known_unmasked;
@@ -140,7 +368,14 @@ struct vcpu_vmx {
u64 msr_host_kernel_gs_base;
u64 msr_guest_kernel_gs_base;
#endif
- struct vmcs *vmcs;
+ /*
+ * loaded_vmcs points to the VMCS currently used in this vcpu. For a
+ * non-nested (L1) guest, it always points to vmcs01. For a nested
+ * guest (L2), it points to a different VMCS.
+ */
+ struct loaded_vmcs vmcs01;
+ struct loaded_vmcs *loaded_vmcs;
+ bool __launched; /* temporary, used in vmx_vcpu_run */
struct msr_autoload {
unsigned nr;
struct vmx_msr_entry guest[NR_AUTOLOAD_MSRS];
@@ -176,6 +411,9 @@ struct vcpu_vmx {
u32 exit_reason;
bool rdtscp_enabled;
+
+ /* Support for a guest hypervisor (nested VMX) */
+ struct nested_vmx nested;
};
enum segment_cache_field {
@@ -192,6 +430,174 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
return container_of(vcpu, struct vcpu_vmx, vcpu);
}
+#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x)
+#define FIELD(number, name) [number] = VMCS12_OFFSET(name)
+#define FIELD64(number, name) [number] = VMCS12_OFFSET(name), \
+ [number##_HIGH] = VMCS12_OFFSET(name)+4
+
+static unsigned short vmcs_field_to_offset_table[] = {
+ FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id),
+ FIELD(GUEST_ES_SELECTOR, guest_es_selector),
+ FIELD(GUEST_CS_SELECTOR, guest_cs_selector),
+ FIELD(GUEST_SS_SELECTOR, guest_ss_selector),
+ FIELD(GUEST_DS_SELECTOR, guest_ds_selector),
+ FIELD(GUEST_FS_SELECTOR, guest_fs_selector),
+ FIELD(GUEST_GS_SELECTOR, guest_gs_selector),
+ FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector),
+ FIELD(GUEST_TR_SELECTOR, guest_tr_selector),
+ FIELD(HOST_ES_SELECTOR, host_es_selector),
+ FIELD(HOST_CS_SELECTOR, host_cs_selector),
+ FIELD(HOST_SS_SELECTOR, host_ss_selector),
+ FIELD(HOST_DS_SELECTOR, host_ds_selector),
+ FIELD(HOST_FS_SELECTOR, host_fs_selector),
+ FIELD(HOST_GS_SELECTOR, host_gs_selector),
+ FIELD(HOST_TR_SELECTOR, host_tr_selector),
+ FIELD64(IO_BITMAP_A, io_bitmap_a),
+ FIELD64(IO_BITMAP_B, io_bitmap_b),
+ FIELD64(MSR_BITMAP, msr_bitmap),
+ FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr),
+ FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr),
+ FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr),
+ FIELD64(TSC_OFFSET, tsc_offset),
+ FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr),
+ FIELD64(APIC_ACCESS_ADDR, apic_access_addr),
+ FIELD64(EPT_POINTER, ept_pointer),
+ FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address),
+ FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer),
+ FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl),
+ FIELD64(GUEST_IA32_PAT, guest_ia32_pat),
+ FIELD64(GUEST_IA32_EFER, guest_ia32_efer),
+ FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl),
+ FIELD64(GUEST_PDPTR0, guest_pdptr0),
+ FIELD64(GUEST_PDPTR1, guest_pdptr1),
+ FIELD64(GUEST_PDPTR2, guest_pdptr2),
+ FIELD64(GUEST_PDPTR3, guest_pdptr3),
+ FIELD64(HOST_IA32_PAT, host_ia32_pat),
+ FIELD64(HOST_IA32_EFER, host_ia32_efer),
+ FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl),
+ FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control),
+ FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control),
+ FIELD(EXCEPTION_BITMAP, exception_bitmap),
+ FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask),
+ FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match),
+ FIELD(CR3_TARGET_COUNT, cr3_target_count),
+ FIELD(VM_EXIT_CONTROLS, vm_exit_controls),
+ FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count),
+ FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count),
+ FIELD(VM_ENTRY_CONTROLS, vm_entry_controls),
+ FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count),
+ FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field),
+ FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE, vm_entry_exception_error_code),
+ FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len),
+ FIELD(TPR_THRESHOLD, tpr_threshold),
+ FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control),
+ FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error),
+ FIELD(VM_EXIT_REASON, vm_exit_reason),
+ FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info),
+ FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code),
+ FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field),
+ FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code),
+ FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len),
+ FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info),
+ FIELD(GUEST_ES_LIMIT, guest_es_limit),
+ FIELD(GUEST_CS_LIMIT, guest_cs_limit),
+ FIELD(GUEST_SS_LIMIT, guest_ss_limit),
+ FIELD(GUEST_DS_LIMIT, guest_ds_limit),
+ FIELD(GUEST_FS_LIMIT, guest_fs_limit),
+ FIELD(GUEST_GS_LIMIT, guest_gs_limit),
+ FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit),
+ FIELD(GUEST_TR_LIMIT, guest_tr_limit),
+ FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit),
+ FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit),
+ FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes),
+ FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes),
+ FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes),
+ FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes),
+ FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes),
+ FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes),
+ FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes),
+ FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes),
+ FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info),
+ FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
+ FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
+ FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
+ FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask),
+ FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask),
+ FIELD(CR0_READ_SHADOW, cr0_read_shadow),
+ FIELD(CR4_READ_SHADOW, cr4_read_shadow),
+ FIELD(CR3_TARGET_VALUE0, cr3_target_value0),
+ FIELD(CR3_TARGET_VALUE1, cr3_target_value1),
+ FIELD(CR3_TARGET_VALUE2, cr3_target_value2),
+ FIELD(CR3_TARGET_VALUE3, cr3_target_value3),
+ FIELD(EXIT_QUALIFICATION, exit_qualification),
+ FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address),
+ FIELD(GUEST_CR0, guest_cr0),
+ FIELD(GUEST_CR3, guest_cr3),
+ FIELD(GUEST_CR4, guest_cr4),
+ FIELD(GUEST_ES_BASE, guest_es_base),
+ FIELD(GUEST_CS_BASE, guest_cs_base),
+ FIELD(GUEST_SS_BASE, guest_ss_base),
+ FIELD(GUEST_DS_BASE, guest_ds_base),
+ FIELD(GUEST_FS_BASE, guest_fs_base),
+ FIELD(GUEST_GS_BASE, guest_gs_base),
+ FIELD(GUEST_LDTR_BASE, guest_ldtr_base),
+ FIELD(GUEST_TR_BASE, guest_tr_base),
+ FIELD(GUEST_GDTR_BASE, guest_gdtr_base),
+ FIELD(GUEST_IDTR_BASE, guest_idtr_base),
+ FIELD(GUEST_DR7, guest_dr7),
+ FIELD(GUEST_RSP, guest_rsp),
+ FIELD(GUEST_RIP, guest_rip),
+ FIELD(GUEST_RFLAGS, guest_rflags),
+ FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions),
+ FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp),
+ FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip),
+ FIELD(HOST_CR0, host_cr0),
+ FIELD(HOST_CR3, host_cr3),
+ FIELD(HOST_CR4, host_cr4),
+ FIELD(HOST_FS_BASE, host_fs_base),
+ FIELD(HOST_GS_BASE, host_gs_base),
+ FIELD(HOST_TR_BASE, host_tr_base),
+ FIELD(HOST_GDTR_BASE, host_gdtr_base),
+ FIELD(HOST_IDTR_BASE, host_idtr_base),
+ FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp),
+ FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip),
+ FIELD(HOST_RSP, host_rsp),
+ FIELD(HOST_RIP, host_rip),
+};
+static const int max_vmcs_field = ARRAY_SIZE(vmcs_field_to_offset_table);
+
+static inline short vmcs_field_to_offset(unsigned long field)
+{
+ if (field >= max_vmcs_field || vmcs_field_to_offset_table[field] == 0)
+ return -1;
+ return vmcs_field_to_offset_table[field];
+}
+
+static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.current_vmcs12;
+}
+
+static struct page *nested_get_page(struct kvm_vcpu *vcpu, gpa_t addr)
+{
+ struct page *page = gfn_to_page(vcpu->kvm, addr >> PAGE_SHIFT);
+ if (is_error_page(page)) {
+ kvm_release_page_clean(page);
+ return NULL;
+ }
+ return page;
+}
+
+static void nested_release_page(struct page *page)
+{
+ kvm_release_page_dirty(page);
+}
+
+static void nested_release_page_clean(struct page *page)
+{
+ kvm_release_page_clean(page);
+}
+
static u64 construct_eptp(unsigned long root_hpa);
static void kvm_cpu_vmxon(u64 addr);
static void kvm_cpu_vmxoff(void);
@@ -200,7 +606,11 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr);
static DEFINE_PER_CPU(struct vmcs *, vmxarea);
static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
-static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu);
+/*
+ * We maintain a per-CPU linked-list of VMCS loaded on that CPU. This is needed
+ * when a CPU is brought down, and we need to VMCLEAR all VMCSs loaded on it.
+ */
+static DEFINE_PER_CPU(struct list_head, loaded_vmcss_on_cpu);
static DEFINE_PER_CPU(struct desc_ptr, host_gdt);
static unsigned long *vmx_io_bitmap_a;
@@ -442,6 +852,35 @@ static inline bool report_flexpriority(void)
return flexpriority_enabled;
}
+static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit)
+{
+ return vmcs12->cpu_based_vm_exec_control & bit;
+}
+
+static inline bool nested_cpu_has2(struct vmcs12 *vmcs12, u32 bit)
+{
+ return (vmcs12->cpu_based_vm_exec_control &
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) &&
+ (vmcs12->secondary_vm_exec_control & bit);
+}
+
+static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12,
+ struct kvm_vcpu *vcpu)
+{
+ return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
+}
+
+static inline bool is_exception(u32 intr_info)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
+ == (INTR_TYPE_HARD_EXCEPTION | INTR_INFO_VALID_MASK);
+}
+
+static void nested_vmx_vmexit(struct kvm_vcpu *vcpu);
+static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12,
+ u32 reason, unsigned long qualification);
+
static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
{
int i;
@@ -501,6 +940,13 @@ static void vmcs_clear(struct vmcs *vmcs)
vmcs, phys_addr);
}
+static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)
+{
+ vmcs_clear(loaded_vmcs->vmcs);
+ loaded_vmcs->cpu = -1;
+ loaded_vmcs->launched = 0;
+}
+
static void vmcs_load(struct vmcs *vmcs)
{
u64 phys_addr = __pa(vmcs);
@@ -510,29 +956,28 @@ static void vmcs_load(struct vmcs *vmcs)
: "=qm"(error) : "a"(&phys_addr), "m"(phys_addr)
: "cc", "memory");
if (error)
- printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n",
+ printk(KERN_ERR "kvm: vmptrld %p/%llx failed\n",
vmcs, phys_addr);
}
-static void __vcpu_clear(void *arg)
+static void __loaded_vmcs_clear(void *arg)
{
- struct vcpu_vmx *vmx = arg;
+ struct loaded_vmcs *loaded_vmcs = arg;
int cpu = raw_smp_processor_id();
- if (vmx->vcpu.cpu == cpu)
- vmcs_clear(vmx->vmcs);
- if (per_cpu(current_vmcs, cpu) == vmx->vmcs)
+ if (loaded_vmcs->cpu != cpu)
+ return; /* vcpu migration can race with cpu offline */
+ if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
per_cpu(current_vmcs, cpu) = NULL;
- list_del(&vmx->local_vcpus_link);
- vmx->vcpu.cpu = -1;
- vmx->launched = 0;
+ list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);
+ loaded_vmcs_init(loaded_vmcs);
}
-static void vcpu_clear(struct vcpu_vmx *vmx)
+static void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
{
- if (vmx->vcpu.cpu == -1)
- return;
- smp_call_function_single(vmx->vcpu.cpu, __vcpu_clear, vmx, 1);
+ if (loaded_vmcs->cpu != -1)
+ smp_call_function_single(
+ loaded_vmcs->cpu, __loaded_vmcs_clear, loaded_vmcs, 1);
}
static inline void vpid_sync_vcpu_single(struct vcpu_vmx *vmx)
@@ -585,26 +1030,26 @@ static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
}
}
-static unsigned long vmcs_readl(unsigned long field)
+static __always_inline unsigned long vmcs_readl(unsigned long field)
{
- unsigned long value = 0;
+ unsigned long value;
- asm volatile (__ex(ASM_VMX_VMREAD_RDX_RAX)
- : "+a"(value) : "d"(field) : "cc");
+ asm volatile (__ex_clear(ASM_VMX_VMREAD_RDX_RAX, "%0")
+ : "=a"(value) : "d"(field) : "cc");
return value;
}
-static u16 vmcs_read16(unsigned long field)
+static __always_inline u16 vmcs_read16(unsigned long field)
{
return vmcs_readl(field);
}
-static u32 vmcs_read32(unsigned long field)
+static __always_inline u32 vmcs_read32(unsigned long field)
{
return vmcs_readl(field);
}
-static u64 vmcs_read64(unsigned long field)
+static __always_inline u64 vmcs_read64(unsigned long field)
{
#ifdef CONFIG_X86_64
return vmcs_readl(field);
@@ -731,6 +1176,15 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
if (vcpu->fpu_active)
eb &= ~(1u << NM_VECTOR);
+
+ /* When we are running a nested L2 guest and L1 specified for it a
+ * certain exception bitmap, we must trap the same exceptions and pass
+ * them to L1. When running L2, we will only handle the exceptions
+ * specified above if L1 did not want them.
+ */
+ if (is_guest_mode(vcpu))
+ eb |= get_vmcs12(vcpu)->exception_bitmap;
+
vmcs_write32(EXCEPTION_BITMAP, eb);
}
@@ -971,22 +1425,22 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
if (!vmm_exclusive)
kvm_cpu_vmxon(phys_addr);
- else if (vcpu->cpu != cpu)
- vcpu_clear(vmx);
+ else if (vmx->loaded_vmcs->cpu != cpu)
+ loaded_vmcs_clear(vmx->loaded_vmcs);
- if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
- per_cpu(current_vmcs, cpu) = vmx->vmcs;
- vmcs_load(vmx->vmcs);
+ if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
+ per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
+ vmcs_load(vmx->loaded_vmcs->vmcs);
}
- if (vcpu->cpu != cpu) {
+ if (vmx->loaded_vmcs->cpu != cpu) {
struct desc_ptr *gdt = &__get_cpu_var(host_gdt);
unsigned long sysenter_esp;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
local_irq_disable();
- list_add(&vmx->local_vcpus_link,
- &per_cpu(vcpus_on_cpu, cpu));
+ list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
+ &per_cpu(loaded_vmcss_on_cpu, cpu));
local_irq_enable();
/*
@@ -998,6 +1452,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+ vmx->loaded_vmcs->cpu = cpu;
}
}
@@ -1005,7 +1460,8 @@ static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
{
__vmx_load_host_state(to_vmx(vcpu));
if (!vmm_exclusive) {
- __vcpu_clear(to_vmx(vcpu));
+ __loaded_vmcs_clear(to_vmx(vcpu)->loaded_vmcs);
+ vcpu->cpu = -1;
kvm_cpu_vmxoff();
}
}
@@ -1023,19 +1479,55 @@ static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
vmcs_writel(GUEST_CR0, cr0);
update_exception_bitmap(vcpu);
vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+ if (is_guest_mode(vcpu))
+ vcpu->arch.cr0_guest_owned_bits &=
+ ~get_vmcs12(vcpu)->cr0_guest_host_mask;
vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
}
static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu);
+/*
+ * Return the cr0 value that a nested guest would read. This is a combination
+ * of the real cr0 used to run the guest (guest_cr0), and the bits shadowed by
+ * its hypervisor (cr0_read_shadow).
+ */
+static inline unsigned long nested_read_cr0(struct vmcs12 *fields)
+{
+ return (fields->guest_cr0 & ~fields->cr0_guest_host_mask) |
+ (fields->cr0_read_shadow & fields->cr0_guest_host_mask);
+}
+static inline unsigned long nested_read_cr4(struct vmcs12 *fields)
+{
+ return (fields->guest_cr4 & ~fields->cr4_guest_host_mask) |
+ (fields->cr4_read_shadow & fields->cr4_guest_host_mask);
+}
+
static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)
{
+ /* Note that there is no vcpu->fpu_active = 0 here. The caller must
+ * set this *before* calling this function.
+ */
vmx_decache_cr0_guest_bits(vcpu);
vmcs_set_bits(GUEST_CR0, X86_CR0_TS | X86_CR0_MP);
update_exception_bitmap(vcpu);
vcpu->arch.cr0_guest_owned_bits = 0;
vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
- vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
+ if (is_guest_mode(vcpu)) {
+ /*
+ * L1's specified read shadow might not contain the TS bit,
+ * so now that we turned on shadowing of this bit, we need to
+ * set this bit of the shadow. Like in nested_vmx_run we need
+ * nested_read_cr0(vmcs12), but vmcs12->guest_cr0 is not yet
+ * up-to-date here because we just decached cr0.TS (and we'll
+ * only update vmcs12->guest_cr0 on nested exit).
+ */
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ vmcs12->guest_cr0 = (vmcs12->guest_cr0 & ~X86_CR0_TS) |
+ (vcpu->arch.cr0 & X86_CR0_TS);
+ vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
+ } else
+ vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
}
static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
@@ -1119,6 +1611,25 @@ static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
}
+/*
+ * KVM wants to inject page-faults which it got to the guest. This function
+ * checks whether in a nested guest, we need to inject them to L1 or L2.
+ * This function assumes it is called with the exit reason in vmcs02 being
+ * a #PF exception (this is the only case in which KVM injects a #PF when L2
+ * is running).
+ */
+static int nested_pf_handled(struct kvm_vcpu *vcpu)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ /* TODO: also check PFEC_MATCH/MASK, not just EB.PF. */
+ if (!(vmcs12->exception_bitmap & PF_VECTOR))
+ return 0;
+
+ nested_vmx_vmexit(vcpu);
+ return 1;
+}
+
static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
bool has_error_code, u32 error_code,
bool reinject)
@@ -1126,6 +1637,10 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
struct vcpu_vmx *vmx = to_vmx(vcpu);
u32 intr_info = nr | INTR_INFO_VALID_MASK;
+ if (nr == PF_VECTOR && is_guest_mode(vcpu) &&
+ nested_pf_handled(vcpu))
+ return;
+
if (has_error_code) {
vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
intr_info |= INTR_INFO_DELIVER_CODE_MASK;
@@ -1248,12 +1763,24 @@ 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))
+ /*
+ * 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.
+ */
+ get_vmcs12(vcpu)->tsc_offset = offset -
+ to_vmx(vcpu)->nested.vmcs01_tsc_offset;
}
static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
{
u64 offset = vmcs_read64(TSC_OFFSET);
vmcs_write64(TSC_OFFSET, offset + adjustment);
+ if (is_guest_mode(vcpu)) {
+ /* Even when running L2, the adjustment needs to apply to L1 */
+ to_vmx(vcpu)->nested.vmcs01_tsc_offset += adjustment;
+ }
}
static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
@@ -1261,6 +1788,236 @@ static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
return target_tsc - native_read_tsc();
}
+static bool guest_cpuid_has_vmx(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 1, 0);
+ return best && (best->ecx & (1 << (X86_FEATURE_VMX & 31)));
+}
+
+/*
+ * nested_vmx_allowed() checks whether a guest should be allowed to use VMX
+ * instructions and MSRs (i.e., nested VMX). Nested VMX is disabled for
+ * all guests if the "nested" module option is off, and can also be disabled
+ * for a single guest by disabling its VMX cpuid bit.
+ */
+static inline bool nested_vmx_allowed(struct kvm_vcpu *vcpu)
+{
+ return nested && guest_cpuid_has_vmx(vcpu);
+}
+
+/*
+ * nested_vmx_setup_ctls_msrs() sets up variables containing the values to be
+ * returned for the various VMX controls MSRs when nested VMX is enabled.
+ * The same values should also be used to verify that vmcs12 control fields are
+ * valid during nested entry from L1 to L2.
+ * Each of these control msrs has a low and high 32-bit half: A low bit is on
+ * if the corresponding bit in the (32-bit) control field *must* be on, and a
+ * bit in the high half is on if the corresponding bit in the control field
+ * may be on. See also vmx_control_verify().
+ * TODO: allow these variables to be modified (downgraded) by module options
+ * or other means.
+ */
+static u32 nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high;
+static u32 nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high;
+static u32 nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high;
+static u32 nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high;
+static u32 nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high;
+static __init void nested_vmx_setup_ctls_msrs(void)
+{
+ /*
+ * Note that as a general rule, the high half of the MSRs (bits in
+ * the control fields which may be 1) should be initialized by the
+ * intersection of the underlying hardware's MSR (i.e., features which
+ * can be supported) and the list of features we want to expose -
+ * because they are known to be properly supported in our code.
+ * Also, usually, the low half of the MSRs (bits which must be 1) can
+ * be set to 0, meaning that L1 may turn off any of these bits. The
+ * reason is that if one of these bits is necessary, it will appear
+ * in vmcs01 and prepare_vmcs02, when it bitwise-or's the control
+ * fields of vmcs01 and vmcs02, will turn these bits off - and
+ * nested_vmx_exit_handled() will not pass related exits to L1.
+ * These rules have exceptions below.
+ */
+
+ /* pin-based controls */
+ /*
+ * According to the Intel spec, if bit 55 of VMX_BASIC is off (as it is
+ * in our case), bits 1, 2 and 4 (i.e., 0x16) must be 1 in this MSR.
+ */
+ nested_vmx_pinbased_ctls_low = 0x16 ;
+ nested_vmx_pinbased_ctls_high = 0x16 |
+ PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING |
+ PIN_BASED_VIRTUAL_NMIS;
+
+ /* exit controls */
+ nested_vmx_exit_ctls_low = 0;
+ /* Note that guest use of VM_EXIT_ACK_INTR_ON_EXIT is not supported. */
+#ifdef CONFIG_X86_64
+ nested_vmx_exit_ctls_high = VM_EXIT_HOST_ADDR_SPACE_SIZE;
+#else
+ nested_vmx_exit_ctls_high = 0;
+#endif
+
+ /* entry controls */
+ rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
+ nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high);
+ nested_vmx_entry_ctls_low = 0;
+ nested_vmx_entry_ctls_high &=
+ VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_IA32E_MODE;
+
+ /* cpu-based controls */
+ rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
+ nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high);
+ nested_vmx_procbased_ctls_low = 0;
+ nested_vmx_procbased_ctls_high &=
+ CPU_BASED_VIRTUAL_INTR_PENDING | CPU_BASED_USE_TSC_OFFSETING |
+ CPU_BASED_HLT_EXITING | CPU_BASED_INVLPG_EXITING |
+ CPU_BASED_MWAIT_EXITING | CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_CR3_STORE_EXITING |
+#ifdef CONFIG_X86_64
+ CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING |
+#endif
+ CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
+ CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING |
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+ /*
+ * We can allow some features even when not supported by the
+ * hardware. For example, L1 can specify an MSR bitmap - and we
+ * can use it to avoid exits to L1 - even when L0 runs L2
+ * without MSR bitmaps.
+ */
+ nested_vmx_procbased_ctls_high |= CPU_BASED_USE_MSR_BITMAPS;
+
+ /* secondary cpu-based controls */
+ rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
+ nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high);
+ nested_vmx_secondary_ctls_low = 0;
+ nested_vmx_secondary_ctls_high &=
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+}
+
+static inline bool vmx_control_verify(u32 control, u32 low, u32 high)
+{
+ /*
+ * Bits 0 in high must be 0, and bits 1 in low must be 1.
+ */
+ return ((control & high) | low) == control;
+}
+
+static inline u64 vmx_control_msr(u32 low, u32 high)
+{
+ return low | ((u64)high << 32);
+}
+
+/*
+ * If we allow our guest to use VMX instructions (i.e., nested VMX), we should
+ * also let it use VMX-specific MSRs.
+ * vmx_get_vmx_msr() and vmx_set_vmx_msr() return 1 when we handled a
+ * VMX-specific MSR, or 0 when we haven't (and the caller should handle it
+ * like all other MSRs).
+ */
+static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+{
+ if (!nested_vmx_allowed(vcpu) && msr_index >= MSR_IA32_VMX_BASIC &&
+ msr_index <= MSR_IA32_VMX_TRUE_ENTRY_CTLS) {
+ /*
+ * According to the spec, processors which do not support VMX
+ * should throw a #GP(0) when VMX capability MSRs are read.
+ */
+ kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+ return 1;
+ }
+
+ switch (msr_index) {
+ case MSR_IA32_FEATURE_CONTROL:
+ *pdata = 0;
+ break;
+ case MSR_IA32_VMX_BASIC:
+ /*
+ * This MSR reports some information about VMX support. We
+ * should return information about the VMX we emulate for the
+ * guest, and the VMCS structure we give it - not about the
+ * VMX support of the underlying hardware.
+ */
+ *pdata = VMCS12_REVISION |
+ ((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
+ (VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
+ break;
+ case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
+ case MSR_IA32_VMX_PINBASED_CTLS:
+ *pdata = vmx_control_msr(nested_vmx_pinbased_ctls_low,
+ nested_vmx_pinbased_ctls_high);
+ break;
+ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+ case MSR_IA32_VMX_PROCBASED_CTLS:
+ *pdata = vmx_control_msr(nested_vmx_procbased_ctls_low,
+ nested_vmx_procbased_ctls_high);
+ break;
+ case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+ case MSR_IA32_VMX_EXIT_CTLS:
+ *pdata = vmx_control_msr(nested_vmx_exit_ctls_low,
+ nested_vmx_exit_ctls_high);
+ break;
+ case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+ case MSR_IA32_VMX_ENTRY_CTLS:
+ *pdata = vmx_control_msr(nested_vmx_entry_ctls_low,
+ nested_vmx_entry_ctls_high);
+ break;
+ case MSR_IA32_VMX_MISC:
+ *pdata = 0;
+ break;
+ /*
+ * These MSRs specify bits which the guest must keep fixed (on or off)
+ * while L1 is in VMXON mode (in L1's root mode, or running an L2).
+ * We picked the standard core2 setting.
+ */
+#define VMXON_CR0_ALWAYSON (X86_CR0_PE | X86_CR0_PG | X86_CR0_NE)
+#define VMXON_CR4_ALWAYSON X86_CR4_VMXE
+ case MSR_IA32_VMX_CR0_FIXED0:
+ *pdata = VMXON_CR0_ALWAYSON;
+ break;
+ case MSR_IA32_VMX_CR0_FIXED1:
+ *pdata = -1ULL;
+ break;
+ case MSR_IA32_VMX_CR4_FIXED0:
+ *pdata = VMXON_CR4_ALWAYSON;
+ break;
+ case MSR_IA32_VMX_CR4_FIXED1:
+ *pdata = -1ULL;
+ break;
+ case MSR_IA32_VMX_VMCS_ENUM:
+ *pdata = 0x1f;
+ break;
+ case MSR_IA32_VMX_PROCBASED_CTLS2:
+ *pdata = vmx_control_msr(nested_vmx_secondary_ctls_low,
+ nested_vmx_secondary_ctls_high);
+ break;
+ case MSR_IA32_VMX_EPT_VPID_CAP:
+ /* Currently, no nested ept or nested vpid */
+ *pdata = 0;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+{
+ if (!nested_vmx_allowed(vcpu))
+ return 0;
+
+ if (msr_index == MSR_IA32_FEATURE_CONTROL)
+ /* TODO: the right thing. */
+ return 1;
+ /*
+ * No need to treat VMX capability MSRs specially: If we don't handle
+ * them, handle_wrmsr will #GP(0), which is correct (they are readonly)
+ */
+ return 0;
+}
+
/*
* Reads an msr value (of 'msr_index') into 'pdata'.
* Returns 0 on success, non-0 otherwise.
@@ -1309,6 +2066,8 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
/* Otherwise falls through */
default:
vmx_load_host_state(to_vmx(vcpu));
+ if (vmx_get_vmx_msr(vcpu, msr_index, pdata))
+ return 0;
msr = find_msr_entry(to_vmx(vcpu), msr_index);
if (msr) {
vmx_load_host_state(to_vmx(vcpu));
@@ -1380,6 +2139,8 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
return 1;
/* Otherwise falls through */
default:
+ if (vmx_set_vmx_msr(vcpu, msr_index, data))
+ break;
msr = find_msr_entry(vmx, msr_index);
if (msr) {
vmx_load_host_state(vmx);
@@ -1469,7 +2230,7 @@ static int hardware_enable(void *garbage)
if (read_cr4() & X86_CR4_VMXE)
return -EBUSY;
- INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu));
+ INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
test_bits = FEATURE_CONTROL_LOCKED;
@@ -1493,14 +2254,14 @@ static int hardware_enable(void *garbage)
return 0;
}
-static void vmclear_local_vcpus(void)
+static void vmclear_local_loaded_vmcss(void)
{
int cpu = raw_smp_processor_id();
- struct vcpu_vmx *vmx, *n;
+ struct loaded_vmcs *v, *n;
- list_for_each_entry_safe(vmx, n, &per_cpu(vcpus_on_cpu, cpu),
- local_vcpus_link)
- __vcpu_clear(vmx);
+ list_for_each_entry_safe(v, n, &per_cpu(loaded_vmcss_on_cpu, cpu),
+ loaded_vmcss_on_cpu_link)
+ __loaded_vmcs_clear(v);
}
@@ -1515,7 +2276,7 @@ static void kvm_cpu_vmxoff(void)
static void hardware_disable(void *garbage)
{
if (vmm_exclusive) {
- vmclear_local_vcpus();
+ vmclear_local_loaded_vmcss();
kvm_cpu_vmxoff();
}
write_cr4(read_cr4() & ~X86_CR4_VMXE);
@@ -1696,6 +2457,18 @@ static void free_vmcs(struct vmcs *vmcs)
free_pages((unsigned long)vmcs, vmcs_config.order);
}
+/*
+ * Free a VMCS, but before that VMCLEAR it on the CPU where it was last loaded
+ */
+static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
+{
+ if (!loaded_vmcs->vmcs)
+ return;
+ loaded_vmcs_clear(loaded_vmcs);
+ free_vmcs(loaded_vmcs->vmcs);
+ loaded_vmcs->vmcs = NULL;
+}
+
static void free_kvm_area(void)
{
int cpu;
@@ -1756,6 +2529,9 @@ static __init int hardware_setup(void)
if (!cpu_has_vmx_ple())
ple_gap = 0;
+ if (nested)
+ nested_vmx_setup_ctls_msrs();
+
return alloc_kvm_area();
}
@@ -2041,7 +2817,7 @@ static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
(unsigned long *)&vcpu->arch.regs_dirty);
}
-static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
+static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
unsigned long cr0,
@@ -2139,11 +2915,23 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
vmcs_writel(GUEST_CR3, guest_cr3);
}
-static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
{
unsigned long hw_cr4 = cr4 | (to_vmx(vcpu)->rmode.vm86_active ?
KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
+ if (cr4 & X86_CR4_VMXE) {
+ /*
+ * To use VMXON (and later other VMX instructions), a guest
+ * must first be able to turn on cr4.VMXE (see handle_vmon()).
+ * So basically the check on whether to allow nested VMX
+ * is here.
+ */
+ if (!nested_vmx_allowed(vcpu))
+ return 1;
+ } else if (to_vmx(vcpu)->nested.vmxon)
+ return 1;
+
vcpu->arch.cr4 = cr4;
if (enable_ept) {
if (!is_paging(vcpu)) {
@@ -2156,6 +2944,7 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
vmcs_writel(CR4_READ_SHADOW, cr4);
vmcs_writel(GUEST_CR4, hw_cr4);
+ return 0;
}
static void vmx_get_segment(struct kvm_vcpu *vcpu,
@@ -2721,18 +3510,110 @@ static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
}
/*
+ * Set up the vmcs's constant host-state fields, i.e., host-state fields that
+ * will not change in the lifetime of the guest.
+ * Note that host-state that does change is set elsewhere. E.g., host-state
+ * that is set differently for each CPU is set in vmx_vcpu_load(), not here.
+ */
+static void vmx_set_constant_host_state(void)
+{
+ u32 low32, high32;
+ unsigned long tmpl;
+ struct desc_ptr dt;
+
+ vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS); /* 22.2.3 */
+ vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */
+ vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
+
+ vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
+ vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */
+
+ native_store_idt(&dt);
+ vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */
+
+ asm("mov $.Lkvm_vmx_return, %0" : "=r"(tmpl));
+ vmcs_writel(HOST_RIP, tmpl); /* 22.2.5 */
+
+ rdmsr(MSR_IA32_SYSENTER_CS, low32, high32);
+ vmcs_write32(HOST_IA32_SYSENTER_CS, low32);
+ rdmsrl(MSR_IA32_SYSENTER_EIP, tmpl);
+ vmcs_writel(HOST_IA32_SYSENTER_EIP, tmpl); /* 22.2.3 */
+
+ if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
+ rdmsr(MSR_IA32_CR_PAT, low32, high32);
+ vmcs_write64(HOST_IA32_PAT, low32 | ((u64) high32 << 32));
+ }
+}
+
+static void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
+{
+ vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
+ if (enable_ept)
+ vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
+ if (is_guest_mode(&vmx->vcpu))
+ vmx->vcpu.arch.cr4_guest_owned_bits &=
+ ~get_vmcs12(&vmx->vcpu)->cr4_guest_host_mask;
+ vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
+}
+
+static u32 vmx_exec_control(struct vcpu_vmx *vmx)
+{
+ u32 exec_control = vmcs_config.cpu_based_exec_ctrl;
+ if (!vm_need_tpr_shadow(vmx->vcpu.kvm)) {
+ exec_control &= ~CPU_BASED_TPR_SHADOW;
+#ifdef CONFIG_X86_64
+ exec_control |= CPU_BASED_CR8_STORE_EXITING |
+ CPU_BASED_CR8_LOAD_EXITING;
+#endif
+ }
+ if (!enable_ept)
+ exec_control |= CPU_BASED_CR3_STORE_EXITING |
+ CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_INVLPG_EXITING;
+ return exec_control;
+}
+
+static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
+{
+ u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
+ if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
+ exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ if (vmx->vpid == 0)
+ exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
+ if (!enable_ept) {
+ exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+ enable_unrestricted_guest = 0;
+ }
+ if (!enable_unrestricted_guest)
+ exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
+ if (!ple_gap)
+ exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+ return exec_control;
+}
+
+static void ept_set_mmio_spte_mask(void)
+{
+ /*
+ * EPT Misconfigurations can be generated if the value of bits 2:0
+ * of an EPT paging-structure entry is 110b (write/execute).
+ * Also, magic bits (0xffull << 49) is set to quickly identify mmio
+ * spte.
+ */
+ kvm_mmu_set_mmio_spte_mask(0xffull << 49 | 0x6ull);
+}
+
+/*
* Sets up the vmcs for emulated real mode.
*/
static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
{
- u32 host_sysenter_cs, msr_low, msr_high;
- u32 junk;
- u64 host_pat;
+#ifdef CONFIG_X86_64
unsigned long a;
- struct desc_ptr dt;
+#endif
int i;
- unsigned long kvm_vmx_return;
- u32 exec_control;
/* I/O */
vmcs_write64(IO_BITMAP_A, __pa(vmx_io_bitmap_a));
@@ -2747,36 +3628,11 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
vmcs_config.pin_based_exec_ctrl);
- exec_control = vmcs_config.cpu_based_exec_ctrl;
- if (!vm_need_tpr_shadow(vmx->vcpu.kvm)) {
- exec_control &= ~CPU_BASED_TPR_SHADOW;
-#ifdef CONFIG_X86_64
- exec_control |= CPU_BASED_CR8_STORE_EXITING |
- CPU_BASED_CR8_LOAD_EXITING;
-#endif
- }
- if (!enable_ept)
- exec_control |= CPU_BASED_CR3_STORE_EXITING |
- CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_INVLPG_EXITING;
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
if (cpu_has_secondary_exec_ctrls()) {
- exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
- if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
- exec_control &=
- ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
- if (vmx->vpid == 0)
- exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
- if (!enable_ept) {
- exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
- enable_unrestricted_guest = 0;
- }
- if (!enable_unrestricted_guest)
- exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
- if (!ple_gap)
- exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+ vmx_secondary_exec_control(vmx));
}
if (ple_gap) {
@@ -2784,20 +3640,13 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmcs_write32(PLE_WINDOW, ple_window);
}
- vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, !!bypass_guest_pf);
- vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf);
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */
- vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS); /* 22.2.3 */
- vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */
- vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
-
- vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
- vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
- vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */
vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */
- vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmx_set_constant_host_state();
#ifdef CONFIG_X86_64
rdmsrl(MSR_FS_BASE, a);
vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */
@@ -2808,32 +3657,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
#endif
- vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */
-
- native_store_idt(&dt);
- vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */
-
- asm("mov $.Lkvm_vmx_return, %0" : "=r"(kvm_vmx_return));
- vmcs_writel(HOST_RIP, kvm_vmx_return); /* 22.2.5 */
vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host));
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest));
- rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk);
- vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs);
- rdmsrl(MSR_IA32_SYSENTER_ESP, a);
- vmcs_writel(HOST_IA32_SYSENTER_ESP, a); /* 22.2.3 */
- rdmsrl(MSR_IA32_SYSENTER_EIP, a);
- vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */
-
- if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
- rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
- host_pat = msr_low | ((u64) msr_high << 32);
- vmcs_write64(HOST_IA32_PAT, host_pat);
- }
if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+ u32 msr_low, msr_high;
+ u64 host_pat;
rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
host_pat = msr_low | ((u64) msr_high << 32);
/* Write the default value follow host pat */
@@ -2863,10 +3695,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmcs_write32(VM_ENTRY_CONTROLS, vmcs_config.vmentry_ctrl);
vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
- vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
- if (enable_ept)
- vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
- vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
+ set_cr4_guest_host_mask(vmx);
kvm_write_tsc(&vmx->vcpu, 0);
@@ -2990,9 +3819,25 @@ out:
return ret;
}
+/*
+ * In nested virtualization, check if L1 asked to exit on external interrupts.
+ * For most existing hypervisors, this will always return true.
+ */
+static bool nested_exit_on_intr(struct kvm_vcpu *vcpu)
+{
+ return get_vmcs12(vcpu)->pin_based_vm_exec_control &
+ PIN_BASED_EXT_INTR_MASK;
+}
+
static void enable_irq_window(struct kvm_vcpu *vcpu)
{
u32 cpu_based_vm_exec_control;
+ if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
+ /* We can get here when nested_run_pending caused
+ * vmx_interrupt_allowed() to return false. In this case, do
+ * nothing - the interrupt will be injected later.
+ */
+ return;
cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
@@ -3049,6 +3894,9 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ if (is_guest_mode(vcpu))
+ return;
+
if (!cpu_has_virtual_nmis()) {
/*
* Tracking the NMI-blocked state in software is built upon
@@ -3115,6 +3963,17 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
{
+ if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) {
+ struct vmcs12 *vmcs12;
+ if (to_vmx(vcpu)->nested.nested_run_pending)
+ return 0;
+ nested_vmx_vmexit(vcpu);
+ vmcs12 = get_vmcs12(vcpu);
+ vmcs12->vm_exit_reason = EXIT_REASON_EXTERNAL_INTERRUPT;
+ vmcs12->vm_exit_intr_info = 0;
+ /* fall through to normal code, but now in L1, not L2 */
+ }
+
return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
@@ -3356,6 +4215,58 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
hypercall[2] = 0xc1;
}
+/* called to set cr0 as approriate for a mov-to-cr0 exit. */
+static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ if (to_vmx(vcpu)->nested.vmxon &&
+ ((val & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON))
+ return 1;
+
+ if (is_guest_mode(vcpu)) {
+ /*
+ * We get here when L2 changed cr0 in a way that did not change
+ * any of L1's shadowed bits (see nested_vmx_exit_handled_cr),
+ * but did change L0 shadowed bits. This can currently happen
+ * with the TS bit: L0 may want to leave TS on (for lazy fpu
+ * loading) while pretending to allow the guest to change it.
+ */
+ if (kvm_set_cr0(vcpu, (val & vcpu->arch.cr0_guest_owned_bits) |
+ (vcpu->arch.cr0 & ~vcpu->arch.cr0_guest_owned_bits)))
+ return 1;
+ vmcs_writel(CR0_READ_SHADOW, val);
+ return 0;
+ } else
+ return kvm_set_cr0(vcpu, val);
+}
+
+static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ if (is_guest_mode(vcpu)) {
+ if (kvm_set_cr4(vcpu, (val & vcpu->arch.cr4_guest_owned_bits) |
+ (vcpu->arch.cr4 & ~vcpu->arch.cr4_guest_owned_bits)))
+ return 1;
+ vmcs_writel(CR4_READ_SHADOW, val);
+ return 0;
+ } else
+ return kvm_set_cr4(vcpu, val);
+}
+
+/* called to set cr0 as approriate for clts instruction exit. */
+static void handle_clts(struct kvm_vcpu *vcpu)
+{
+ if (is_guest_mode(vcpu)) {
+ /*
+ * We get here when L2 did CLTS, and L1 didn't shadow CR0.TS
+ * but we did (!fpu_active). We need to keep GUEST_CR0.TS on,
+ * just pretend it's off (also in arch.cr0 for fpu_activate).
+ */
+ vmcs_writel(CR0_READ_SHADOW,
+ vmcs_readl(CR0_READ_SHADOW) & ~X86_CR0_TS);
+ vcpu->arch.cr0 &= ~X86_CR0_TS;
+ } else
+ vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
+}
+
static int handle_cr(struct kvm_vcpu *vcpu)
{
unsigned long exit_qualification, val;
@@ -3372,7 +4283,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
trace_kvm_cr_write(cr, val);
switch (cr) {
case 0:
- err = kvm_set_cr0(vcpu, val);
+ err = handle_set_cr0(vcpu, val);
kvm_complete_insn_gp(vcpu, err);
return 1;
case 3:
@@ -3380,7 +4291,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
kvm_complete_insn_gp(vcpu, err);
return 1;
case 4:
- err = kvm_set_cr4(vcpu, val);
+ err = handle_set_cr4(vcpu, val);
kvm_complete_insn_gp(vcpu, err);
return 1;
case 8: {
@@ -3398,7 +4309,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
};
break;
case 2: /* clts */
- vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
+ handle_clts(vcpu);
trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
skip_emulated_instruction(vcpu);
vmx_fpu_activate(vcpu);
@@ -3574,12 +4485,6 @@ static int handle_vmcall(struct kvm_vcpu *vcpu)
return 1;
}
-static int handle_vmx_insn(struct kvm_vcpu *vcpu)
-{
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
-}
-
static int handle_invd(struct kvm_vcpu *vcpu)
{
return emulate_instruction(vcpu, 0) == EMULATE_DONE;
@@ -3777,11 +4682,19 @@ static void ept_misconfig_inspect_spte(struct kvm_vcpu *vcpu, u64 spte,
static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
{
u64 sptes[4];
- int nr_sptes, i;
+ int nr_sptes, i, ret;
gpa_t gpa;
gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
+ ret = handle_mmio_page_fault_common(vcpu, gpa, true);
+ if (likely(ret == 1))
+ return x86_emulate_instruction(vcpu, gpa, 0, NULL, 0) ==
+ EMULATE_DONE;
+ if (unlikely(!ret))
+ return 1;
+
+ /* It is the real ept misconfig */
printk(KERN_ERR "EPT: Misconfiguration.\n");
printk(KERN_ERR "EPT: GPA: 0x%llx\n", gpa);
@@ -3866,6 +4779,639 @@ static int handle_invalid_op(struct kvm_vcpu *vcpu)
}
/*
+ * To run an L2 guest, we need a vmcs02 based on the L1-specified vmcs12.
+ * We could reuse a single VMCS for all the L2 guests, but we also want the
+ * option to allocate a separate vmcs02 for each separate loaded vmcs12 - this
+ * allows keeping them loaded on the processor, and in the future will allow
+ * optimizations where prepare_vmcs02 doesn't need to set all the fields on
+ * every entry if they never change.
+ * So we keep, in vmx->nested.vmcs02_pool, a cache of size VMCS02_POOL_SIZE
+ * (>=0) with a vmcs02 for each recently loaded vmcs12s, most recent first.
+ *
+ * The following functions allocate and free a vmcs02 in this pool.
+ */
+
+/* Get a VMCS from the pool to use as vmcs02 for the current vmcs12. */
+static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
+{
+ struct vmcs02_list *item;
+ list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
+ if (item->vmptr == vmx->nested.current_vmptr) {
+ list_move(&item->list, &vmx->nested.vmcs02_pool);
+ return &item->vmcs02;
+ }
+
+ if (vmx->nested.vmcs02_num >= max(VMCS02_POOL_SIZE, 1)) {
+ /* Recycle the least recently used VMCS. */
+ item = list_entry(vmx->nested.vmcs02_pool.prev,
+ struct vmcs02_list, list);
+ item->vmptr = vmx->nested.current_vmptr;
+ list_move(&item->list, &vmx->nested.vmcs02_pool);
+ return &item->vmcs02;
+ }
+
+ /* Create a new VMCS */
+ item = (struct vmcs02_list *)
+ kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
+ if (!item)
+ return NULL;
+ item->vmcs02.vmcs = alloc_vmcs();
+ if (!item->vmcs02.vmcs) {
+ kfree(item);
+ return NULL;
+ }
+ loaded_vmcs_init(&item->vmcs02);
+ item->vmptr = vmx->nested.current_vmptr;
+ list_add(&(item->list), &(vmx->nested.vmcs02_pool));
+ vmx->nested.vmcs02_num++;
+ return &item->vmcs02;
+}
+
+/* Free and remove from pool a vmcs02 saved for a vmcs12 (if there is one) */
+static void nested_free_vmcs02(struct vcpu_vmx *vmx, gpa_t vmptr)
+{
+ struct vmcs02_list *item;
+ list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
+ if (item->vmptr == vmptr) {
+ free_loaded_vmcs(&item->vmcs02);
+ list_del(&item->list);
+ kfree(item);
+ vmx->nested.vmcs02_num--;
+ return;
+ }
+}
+
+/*
+ * Free all VMCSs saved for this vcpu, except the one pointed by
+ * vmx->loaded_vmcs. These include the VMCSs in vmcs02_pool (except the one
+ * currently used, if running L2), and vmcs01 when running L2.
+ */
+static void nested_free_all_saved_vmcss(struct vcpu_vmx *vmx)
+{
+ struct vmcs02_list *item, *n;
+ list_for_each_entry_safe(item, n, &vmx->nested.vmcs02_pool, list) {
+ if (vmx->loaded_vmcs != &item->vmcs02)
+ free_loaded_vmcs(&item->vmcs02);
+ list_del(&item->list);
+ kfree(item);
+ }
+ vmx->nested.vmcs02_num = 0;
+
+ if (vmx->loaded_vmcs != &vmx->vmcs01)
+ free_loaded_vmcs(&vmx->vmcs01);
+}
+
+/*
+ * Emulate the VMXON instruction.
+ * Currently, we just remember that VMX is active, and do not save or even
+ * inspect the argument to VMXON (the so-called "VMXON pointer") because we
+ * do not currently need to store anything in that guest-allocated memory
+ * region. Consequently, VMCLEAR and VMPTRLD also do not verify that the their
+ * argument is different from the VMXON pointer (which the spec says they do).
+ */
+static int handle_vmon(struct kvm_vcpu *vcpu)
+{
+ struct kvm_segment cs;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ /* The Intel VMX Instruction Reference lists a bunch of bits that
+ * are prerequisite to running VMXON, most notably cr4.VMXE must be
+ * set to 1 (see vmx_set_cr4() for when we allow the guest to set this).
+ * Otherwise, we should fail with #UD. We test these now:
+ */
+ if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE) ||
+ !kvm_read_cr0_bits(vcpu, X86_CR0_PE) ||
+ (vmx_get_rflags(vcpu) & X86_EFLAGS_VM)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+ if (is_long_mode(vcpu) && !cs.l) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ if (vmx_get_cpl(vcpu)) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool));
+ vmx->nested.vmcs02_num = 0;
+
+ vmx->nested.vmxon = true;
+
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+/*
+ * Intel's VMX Instruction Reference specifies a common set of prerequisites
+ * for running VMX instructions (except VMXON, whose prerequisites are
+ * slightly different). It also specifies what exception to inject otherwise.
+ */
+static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
+{
+ struct kvm_segment cs;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (!vmx->nested.vmxon) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 0;
+ }
+
+ vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+ if ((vmx_get_rflags(vcpu) & X86_EFLAGS_VM) ||
+ (is_long_mode(vcpu) && !cs.l)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 0;
+ }
+
+ if (vmx_get_cpl(vcpu)) {
+ kvm_inject_gp(vcpu, 0);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Free whatever needs to be freed from vmx->nested when L1 goes down, or
+ * just stops using VMX.
+ */
+static void free_nested(struct vcpu_vmx *vmx)
+{
+ if (!vmx->nested.vmxon)
+ return;
+ vmx->nested.vmxon = false;
+ if (vmx->nested.current_vmptr != -1ull) {
+ kunmap(vmx->nested.current_vmcs12_page);
+ nested_release_page(vmx->nested.current_vmcs12_page);
+ vmx->nested.current_vmptr = -1ull;
+ vmx->nested.current_vmcs12 = NULL;
+ }
+ /* Unpin physical memory we referred to in current vmcs02 */
+ if (vmx->nested.apic_access_page) {
+ nested_release_page(vmx->nested.apic_access_page);
+ vmx->nested.apic_access_page = 0;
+ }
+
+ nested_free_all_saved_vmcss(vmx);
+}
+
+/* Emulate the VMXOFF instruction */
+static int handle_vmoff(struct kvm_vcpu *vcpu)
+{
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+ free_nested(to_vmx(vcpu));
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+/*
+ * Decode the memory-address operand of a vmx instruction, as recorded on an
+ * exit caused by such an instruction (run by a guest hypervisor).
+ * On success, returns 0. When the operand is invalid, returns 1 and throws
+ * #UD or #GP.
+ */
+static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
+ unsigned long exit_qualification,
+ u32 vmx_instruction_info, gva_t *ret)
+{
+ /*
+ * According to Vol. 3B, "Information for VM Exits Due to Instruction
+ * Execution", on an exit, vmx_instruction_info holds most of the
+ * addressing components of the operand. Only the displacement part
+ * is put in exit_qualification (see 3B, "Basic VM-Exit Information").
+ * For how an actual address is calculated from all these components,
+ * refer to Vol. 1, "Operand Addressing".
+ */
+ int scaling = vmx_instruction_info & 3;
+ int addr_size = (vmx_instruction_info >> 7) & 7;
+ bool is_reg = vmx_instruction_info & (1u << 10);
+ int seg_reg = (vmx_instruction_info >> 15) & 7;
+ int index_reg = (vmx_instruction_info >> 18) & 0xf;
+ bool index_is_valid = !(vmx_instruction_info & (1u << 22));
+ int base_reg = (vmx_instruction_info >> 23) & 0xf;
+ bool base_is_valid = !(vmx_instruction_info & (1u << 27));
+
+ if (is_reg) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ /* Addr = segment_base + offset */
+ /* offset = base + [index * scale] + displacement */
+ *ret = vmx_get_segment_base(vcpu, seg_reg);
+ if (base_is_valid)
+ *ret += kvm_register_read(vcpu, base_reg);
+ if (index_is_valid)
+ *ret += kvm_register_read(vcpu, index_reg)<<scaling;
+ *ret += exit_qualification; /* holds the displacement */
+
+ if (addr_size == 1) /* 32 bit */
+ *ret &= 0xffffffff;
+
+ /*
+ * TODO: throw #GP (and return 1) in various cases that the VM*
+ * instructions require it - e.g., offset beyond segment limit,
+ * unusable or unreadable/unwritable segment, non-canonical 64-bit
+ * address, and so on. Currently these are not checked.
+ */
+ return 0;
+}
+
+/*
+ * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
+ * set the success or error code of an emulated VMX instruction, as specified
+ * by Vol 2B, VMX Instruction Reference, "Conventions".
+ */
+static void nested_vmx_succeed(struct kvm_vcpu *vcpu)
+{
+ vmx_set_rflags(vcpu, vmx_get_rflags(vcpu)
+ & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+ X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF));
+}
+
+static void nested_vmx_failInvalid(struct kvm_vcpu *vcpu)
+{
+ vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+ & ~(X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF |
+ X86_EFLAGS_SF | X86_EFLAGS_OF))
+ | X86_EFLAGS_CF);
+}
+
+static void nested_vmx_failValid(struct kvm_vcpu *vcpu,
+ u32 vm_instruction_error)
+{
+ if (to_vmx(vcpu)->nested.current_vmptr == -1ull) {
+ /*
+ * failValid writes the error number to the current VMCS, which
+ * can't be done there isn't a current VMCS.
+ */
+ nested_vmx_failInvalid(vcpu);
+ return;
+ }
+ vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+ & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+ X86_EFLAGS_SF | X86_EFLAGS_OF))
+ | X86_EFLAGS_ZF);
+ get_vmcs12(vcpu)->vm_instruction_error = vm_instruction_error;
+}
+
+/* Emulate the VMCLEAR instruction */
+static int handle_vmclear(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ gva_t gva;
+ gpa_t vmptr;
+ struct vmcs12 *vmcs12;
+ struct page *page;
+ struct x86_exception e;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+ vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
+ return 1;
+
+ if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
+ sizeof(vmptr), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+
+ if (!IS_ALIGNED(vmptr, PAGE_SIZE)) {
+ nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+
+ if (vmptr == vmx->nested.current_vmptr) {
+ kunmap(vmx->nested.current_vmcs12_page);
+ nested_release_page(vmx->nested.current_vmcs12_page);
+ vmx->nested.current_vmptr = -1ull;
+ vmx->nested.current_vmcs12 = NULL;
+ }
+
+ page = nested_get_page(vcpu, vmptr);
+ if (page == NULL) {
+ /*
+ * For accurate processor emulation, VMCLEAR beyond available
+ * physical memory should do nothing at all. However, it is
+ * possible that a nested vmx bug, not a guest hypervisor bug,
+ * resulted in this case, so let's shut down before doing any
+ * more damage:
+ */
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+ return 1;
+ }
+ vmcs12 = kmap(page);
+ vmcs12->launch_state = 0;
+ kunmap(page);
+ nested_release_page(page);
+
+ nested_free_vmcs02(vmx, vmptr);
+
+ skip_emulated_instruction(vcpu);
+ nested_vmx_succeed(vcpu);
+ return 1;
+}
+
+static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch);
+
+/* Emulate the VMLAUNCH instruction */
+static int handle_vmlaunch(struct kvm_vcpu *vcpu)
+{
+ return nested_vmx_run(vcpu, true);
+}
+
+/* Emulate the VMRESUME instruction */
+static int handle_vmresume(struct kvm_vcpu *vcpu)
+{
+
+ return nested_vmx_run(vcpu, false);
+}
+
+enum vmcs_field_type {
+ VMCS_FIELD_TYPE_U16 = 0,
+ VMCS_FIELD_TYPE_U64 = 1,
+ VMCS_FIELD_TYPE_U32 = 2,
+ VMCS_FIELD_TYPE_NATURAL_WIDTH = 3
+};
+
+static inline int vmcs_field_type(unsigned long field)
+{
+ if (0x1 & field) /* the *_HIGH fields are all 32 bit */
+ return VMCS_FIELD_TYPE_U32;
+ return (field >> 13) & 0x3 ;
+}
+
+static inline int vmcs_field_readonly(unsigned long field)
+{
+ return (((field >> 10) & 0x3) == 1);
+}
+
+/*
+ * Read a vmcs12 field. Since these can have varying lengths and we return
+ * one type, we chose the biggest type (u64) and zero-extend the return value
+ * to that size. Note that the caller, handle_vmread, might need to use only
+ * some of the bits we return here (e.g., on 32-bit guests, only 32 bits of
+ * 64-bit fields are to be returned).
+ */
+static inline bool vmcs12_read_any(struct kvm_vcpu *vcpu,
+ unsigned long field, u64 *ret)
+{
+ short offset = vmcs_field_to_offset(field);
+ char *p;
+
+ if (offset < 0)
+ return 0;
+
+ p = ((char *)(get_vmcs12(vcpu))) + offset;
+
+ switch (vmcs_field_type(field)) {
+ case VMCS_FIELD_TYPE_NATURAL_WIDTH:
+ *ret = *((natural_width *)p);
+ return 1;
+ case VMCS_FIELD_TYPE_U16:
+ *ret = *((u16 *)p);
+ return 1;
+ case VMCS_FIELD_TYPE_U32:
+ *ret = *((u32 *)p);
+ return 1;
+ case VMCS_FIELD_TYPE_U64:
+ *ret = *((u64 *)p);
+ return 1;
+ default:
+ return 0; /* can never happen. */
+ }
+}
+
+/*
+ * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was
+ * used before) all generate the same failure when it is missing.
+ */
+static int nested_vmx_check_vmcs12(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ if (vmx->nested.current_vmptr == -1ull) {
+ nested_vmx_failInvalid(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 0;
+ }
+ return 1;
+}
+
+static int handle_vmread(struct kvm_vcpu *vcpu)
+{
+ unsigned long field;
+ u64 field_value;
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ gva_t gva = 0;
+
+ if (!nested_vmx_check_permission(vcpu) ||
+ !nested_vmx_check_vmcs12(vcpu))
+ return 1;
+
+ /* Decode instruction info and find the field to read */
+ field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+ /* Read the field, zero-extended to a u64 field_value */
+ if (!vmcs12_read_any(vcpu, field, &field_value)) {
+ nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ /*
+ * Now copy part of this value to register or memory, as requested.
+ * Note that the number of bits actually copied is 32 or 64 depending
+ * on the guest's mode (32 or 64 bit), not on the given field's length.
+ */
+ if (vmx_instruction_info & (1u << 10)) {
+ kvm_register_write(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
+ field_value);
+ } else {
+ if (get_vmx_mem_address(vcpu, exit_qualification,
+ vmx_instruction_info, &gva))
+ return 1;
+ /* _system ok, as nested_vmx_check_permission verified cpl=0 */
+ kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
+ &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL);
+ }
+
+ nested_vmx_succeed(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+
+static int handle_vmwrite(struct kvm_vcpu *vcpu)
+{
+ unsigned long field;
+ gva_t gva;
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ char *p;
+ short offset;
+ /* The value to write might be 32 or 64 bits, depending on L1's long
+ * mode, and eventually we need to write that into a field of several
+ * possible lengths. The code below first zero-extends the value to 64
+ * bit (field_value), and then copies only the approriate number of
+ * bits into the vmcs12 field.
+ */
+ u64 field_value = 0;
+ struct x86_exception e;
+
+ if (!nested_vmx_check_permission(vcpu) ||
+ !nested_vmx_check_vmcs12(vcpu))
+ return 1;
+
+ if (vmx_instruction_info & (1u << 10))
+ field_value = kvm_register_read(vcpu,
+ (((vmx_instruction_info) >> 3) & 0xf));
+ else {
+ if (get_vmx_mem_address(vcpu, exit_qualification,
+ vmx_instruction_info, &gva))
+ return 1;
+ if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
+ &field_value, (is_long_mode(vcpu) ? 8 : 4), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+ }
+
+
+ field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+ if (vmcs_field_readonly(field)) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+
+ offset = vmcs_field_to_offset(field);
+ if (offset < 0) {
+ nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ p = ((char *) get_vmcs12(vcpu)) + offset;
+
+ switch (vmcs_field_type(field)) {
+ case VMCS_FIELD_TYPE_U16:
+ *(u16 *)p = field_value;
+ break;
+ case VMCS_FIELD_TYPE_U32:
+ *(u32 *)p = field_value;
+ break;
+ case VMCS_FIELD_TYPE_U64:
+ *(u64 *)p = field_value;
+ break;
+ case VMCS_FIELD_TYPE_NATURAL_WIDTH:
+ *(natural_width *)p = field_value;
+ break;
+ default:
+ nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+
+ nested_vmx_succeed(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+/* Emulate the VMPTRLD instruction */
+static int handle_vmptrld(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ gva_t gva;
+ gpa_t vmptr;
+ struct x86_exception e;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+ vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
+ return 1;
+
+ if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
+ sizeof(vmptr), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+
+ if (!IS_ALIGNED(vmptr, PAGE_SIZE)) {
+ nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+
+ if (vmx->nested.current_vmptr != vmptr) {
+ struct vmcs12 *new_vmcs12;
+ struct page *page;
+ page = nested_get_page(vcpu, vmptr);
+ if (page == NULL) {
+ nested_vmx_failInvalid(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ new_vmcs12 = kmap(page);
+ if (new_vmcs12->revision_id != VMCS12_REVISION) {
+ kunmap(page);
+ nested_release_page_clean(page);
+ nested_vmx_failValid(vcpu,
+ VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ if (vmx->nested.current_vmptr != -1ull) {
+ kunmap(vmx->nested.current_vmcs12_page);
+ nested_release_page(vmx->nested.current_vmcs12_page);
+ }
+
+ vmx->nested.current_vmptr = vmptr;
+ vmx->nested.current_vmcs12 = new_vmcs12;
+ vmx->nested.current_vmcs12_page = page;
+ }
+
+ nested_vmx_succeed(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+/* Emulate the VMPTRST instruction */
+static int handle_vmptrst(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ gva_t vmcs_gva;
+ struct x86_exception e;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (get_vmx_mem_address(vcpu, exit_qualification,
+ vmx_instruction_info, &vmcs_gva))
+ return 1;
+ /* ok to use *_system, as nested_vmx_check_permission verified cpl=0 */
+ if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva,
+ (void *)&to_vmx(vcpu)->nested.current_vmptr,
+ sizeof(u64), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+ nested_vmx_succeed(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+/*
* The exit handlers return 1 if the exit was handled fully and guest execution
* may resume. Otherwise they set the kvm_run parameter to indicate what needs
* to be done to userspace and return 0.
@@ -3886,15 +5432,15 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
[EXIT_REASON_INVD] = handle_invd,
[EXIT_REASON_INVLPG] = handle_invlpg,
[EXIT_REASON_VMCALL] = handle_vmcall,
- [EXIT_REASON_VMCLEAR] = handle_vmx_insn,
- [EXIT_REASON_VMLAUNCH] = handle_vmx_insn,
- [EXIT_REASON_VMPTRLD] = handle_vmx_insn,
- [EXIT_REASON_VMPTRST] = handle_vmx_insn,
- [EXIT_REASON_VMREAD] = handle_vmx_insn,
- [EXIT_REASON_VMRESUME] = handle_vmx_insn,
- [EXIT_REASON_VMWRITE] = handle_vmx_insn,
- [EXIT_REASON_VMOFF] = handle_vmx_insn,
- [EXIT_REASON_VMON] = handle_vmx_insn,
+ [EXIT_REASON_VMCLEAR] = handle_vmclear,
+ [EXIT_REASON_VMLAUNCH] = handle_vmlaunch,
+ [EXIT_REASON_VMPTRLD] = handle_vmptrld,
+ [EXIT_REASON_VMPTRST] = handle_vmptrst,
+ [EXIT_REASON_VMREAD] = handle_vmread,
+ [EXIT_REASON_VMRESUME] = handle_vmresume,
+ [EXIT_REASON_VMWRITE] = handle_vmwrite,
+ [EXIT_REASON_VMOFF] = handle_vmoff,
+ [EXIT_REASON_VMON] = handle_vmon,
[EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold,
[EXIT_REASON_APIC_ACCESS] = handle_apic_access,
[EXIT_REASON_WBINVD] = handle_wbinvd,
@@ -3911,6 +5457,229 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
static const int kvm_vmx_max_exit_handlers =
ARRAY_SIZE(kvm_vmx_exit_handlers);
+/*
+ * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
+ * rather than handle it ourselves in L0. I.e., check whether L1 expressed
+ * disinterest in the current event (read or write a specific MSR) by using an
+ * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
+ */
+static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12, u32 exit_reason)
+{
+ u32 msr_index = vcpu->arch.regs[VCPU_REGS_RCX];
+ gpa_t bitmap;
+
+ if (!nested_cpu_has(get_vmcs12(vcpu), CPU_BASED_USE_MSR_BITMAPS))
+ return 1;
+
+ /*
+ * The MSR_BITMAP page is divided into four 1024-byte bitmaps,
+ * for the four combinations of read/write and low/high MSR numbers.
+ * First we need to figure out which of the four to use:
+ */
+ bitmap = vmcs12->msr_bitmap;
+ if (exit_reason == EXIT_REASON_MSR_WRITE)
+ bitmap += 2048;
+ if (msr_index >= 0xc0000000) {
+ msr_index -= 0xc0000000;
+ bitmap += 1024;
+ }
+
+ /* Then read the msr_index'th bit from this bitmap: */
+ if (msr_index < 1024*8) {
+ unsigned char b;
+ kvm_read_guest(vcpu->kvm, bitmap + msr_index/8, &b, 1);
+ return 1 & (b >> (msr_index & 7));
+ } else
+ return 1; /* let L1 handle the wrong parameter */
+}
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle a CR access exit,
+ * rather than handle it ourselves in L0. I.e., check if L1 wanted to
+ * intercept (via guest_host_mask etc.) the current event.
+ */
+static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ int cr = exit_qualification & 15;
+ int reg = (exit_qualification >> 8) & 15;
+ unsigned long val = kvm_register_read(vcpu, reg);
+
+ switch ((exit_qualification >> 4) & 3) {
+ case 0: /* mov to cr */
+ switch (cr) {
+ case 0:
+ if (vmcs12->cr0_guest_host_mask &
+ (val ^ vmcs12->cr0_read_shadow))
+ return 1;
+ break;
+ case 3:
+ if ((vmcs12->cr3_target_count >= 1 &&
+ vmcs12->cr3_target_value0 == val) ||
+ (vmcs12->cr3_target_count >= 2 &&
+ vmcs12->cr3_target_value1 == val) ||
+ (vmcs12->cr3_target_count >= 3 &&
+ vmcs12->cr3_target_value2 == val) ||
+ (vmcs12->cr3_target_count >= 4 &&
+ vmcs12->cr3_target_value3 == val))
+ return 0;
+ if (nested_cpu_has(vmcs12, CPU_BASED_CR3_LOAD_EXITING))
+ return 1;
+ break;
+ case 4:
+ if (vmcs12->cr4_guest_host_mask &
+ (vmcs12->cr4_read_shadow ^ val))
+ return 1;
+ break;
+ case 8:
+ if (nested_cpu_has(vmcs12, CPU_BASED_CR8_LOAD_EXITING))
+ return 1;
+ break;
+ }
+ break;
+ case 2: /* clts */
+ if ((vmcs12->cr0_guest_host_mask & X86_CR0_TS) &&
+ (vmcs12->cr0_read_shadow & X86_CR0_TS))
+ return 1;
+ break;
+ case 1: /* mov from cr */
+ switch (cr) {
+ case 3:
+ if (vmcs12->cpu_based_vm_exec_control &
+ CPU_BASED_CR3_STORE_EXITING)
+ return 1;
+ break;
+ case 8:
+ if (vmcs12->cpu_based_vm_exec_control &
+ CPU_BASED_CR8_STORE_EXITING)
+ return 1;
+ break;
+ }
+ break;
+ case 3: /* lmsw */
+ /*
+ * lmsw can change bits 1..3 of cr0, and only set bit 0 of
+ * cr0. Other attempted changes are ignored, with no exit.
+ */
+ if (vmcs12->cr0_guest_host_mask & 0xe &
+ (val ^ vmcs12->cr0_read_shadow))
+ return 1;
+ if ((vmcs12->cr0_guest_host_mask & 0x1) &&
+ !(vmcs12->cr0_read_shadow & 0x1) &&
+ (val & 0x1))
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle an exit, or 0 if we
+ * should handle it ourselves in L0 (and then continue L2). Only call this
+ * when in is_guest_mode (L2).
+ */
+static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
+{
+ u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
+ u32 intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ if (vmx->nested.nested_run_pending)
+ return 0;
+
+ if (unlikely(vmx->fail)) {
+ printk(KERN_INFO "%s failed vm entry %x\n",
+ __func__, vmcs_read32(VM_INSTRUCTION_ERROR));
+ return 1;
+ }
+
+ switch (exit_reason) {
+ case EXIT_REASON_EXCEPTION_NMI:
+ if (!is_exception(intr_info))
+ return 0;
+ else if (is_page_fault(intr_info))
+ return enable_ept;
+ return vmcs12->exception_bitmap &
+ (1u << (intr_info & INTR_INFO_VECTOR_MASK));
+ case EXIT_REASON_EXTERNAL_INTERRUPT:
+ return 0;
+ case EXIT_REASON_TRIPLE_FAULT:
+ return 1;
+ case EXIT_REASON_PENDING_INTERRUPT:
+ case EXIT_REASON_NMI_WINDOW:
+ /*
+ * prepare_vmcs02() set the CPU_BASED_VIRTUAL_INTR_PENDING bit
+ * (aka Interrupt Window Exiting) only when L1 turned it on,
+ * so if we got a PENDING_INTERRUPT exit, this must be for L1.
+ * Same for NMI Window Exiting.
+ */
+ return 1;
+ case EXIT_REASON_TASK_SWITCH:
+ return 1;
+ case EXIT_REASON_CPUID:
+ return 1;
+ case EXIT_REASON_HLT:
+ return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING);
+ case EXIT_REASON_INVD:
+ return 1;
+ case EXIT_REASON_INVLPG:
+ return nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
+ case EXIT_REASON_RDPMC:
+ return nested_cpu_has(vmcs12, CPU_BASED_RDPMC_EXITING);
+ case EXIT_REASON_RDTSC:
+ return nested_cpu_has(vmcs12, CPU_BASED_RDTSC_EXITING);
+ case EXIT_REASON_VMCALL: case EXIT_REASON_VMCLEAR:
+ case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMPTRLD:
+ case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD:
+ case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE:
+ case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
+ /*
+ * VMX instructions trap unconditionally. This allows L1 to
+ * emulate them for its L2 guest, i.e., allows 3-level nesting!
+ */
+ return 1;
+ case EXIT_REASON_CR_ACCESS:
+ return nested_vmx_exit_handled_cr(vcpu, vmcs12);
+ case EXIT_REASON_DR_ACCESS:
+ return nested_cpu_has(vmcs12, CPU_BASED_MOV_DR_EXITING);
+ case EXIT_REASON_IO_INSTRUCTION:
+ /* TODO: support IO bitmaps */
+ return 1;
+ case EXIT_REASON_MSR_READ:
+ case EXIT_REASON_MSR_WRITE:
+ return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason);
+ case EXIT_REASON_INVALID_STATE:
+ return 1;
+ case EXIT_REASON_MWAIT_INSTRUCTION:
+ return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
+ case EXIT_REASON_MONITOR_INSTRUCTION:
+ return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_EXITING);
+ case EXIT_REASON_PAUSE_INSTRUCTION:
+ return nested_cpu_has(vmcs12, CPU_BASED_PAUSE_EXITING) ||
+ nested_cpu_has2(vmcs12,
+ SECONDARY_EXEC_PAUSE_LOOP_EXITING);
+ case EXIT_REASON_MCE_DURING_VMENTRY:
+ return 0;
+ case EXIT_REASON_TPR_BELOW_THRESHOLD:
+ return 1;
+ case EXIT_REASON_APIC_ACCESS:
+ return nested_cpu_has2(vmcs12,
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+ case EXIT_REASON_EPT_VIOLATION:
+ case EXIT_REASON_EPT_MISCONFIG:
+ return 0;
+ case EXIT_REASON_WBINVD:
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
+ case EXIT_REASON_XSETBV:
+ return 1;
+ default:
+ return 1;
+ }
+}
+
static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
{
*info1 = vmcs_readl(EXIT_QUALIFICATION);
@@ -3933,6 +5702,25 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
if (vmx->emulation_required && emulate_invalid_guest_state)
return handle_invalid_guest_state(vcpu);
+ /*
+ * the KVM_REQ_EVENT optimization bit is only on for one entry, and if
+ * we did not inject a still-pending event to L1 now because of
+ * nested_run_pending, we need to re-enable this bit.
+ */
+ if (vmx->nested.nested_run_pending)
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+
+ if (!is_guest_mode(vcpu) && (exit_reason == EXIT_REASON_VMLAUNCH ||
+ exit_reason == EXIT_REASON_VMRESUME))
+ vmx->nested.nested_run_pending = 1;
+ else
+ vmx->nested.nested_run_pending = 0;
+
+ if (is_guest_mode(vcpu) && nested_vmx_exit_handled(vcpu)) {
+ nested_vmx_vmexit(vcpu);
+ return 1;
+ }
+
if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
vcpu->run->fail_entry.hardware_entry_failure_reason
@@ -3955,7 +5743,9 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
"(0x%x) and exit reason is 0x%x\n",
__func__, vectoring_info, exit_reason);
- if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) {
+ if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked &&
+ !(is_guest_mode(vcpu) && nested_cpu_has_virtual_nmis(
+ get_vmcs12(vcpu), vcpu)))) {
if (vmx_interrupt_allowed(vcpu)) {
vmx->soft_vnmi_blocked = 0;
} else if (vmx->vnmi_blocked_time > 1000000000LL &&
@@ -4118,6 +5908,8 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
{
+ if (is_guest_mode(&vmx->vcpu))
+ return;
__vmx_complete_interrupts(vmx, vmx->idt_vectoring_info,
VM_EXIT_INSTRUCTION_LEN,
IDT_VECTORING_ERROR_CODE);
@@ -4125,6 +5917,8 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
{
+ if (is_guest_mode(vcpu))
+ return;
__vmx_complete_interrupts(to_vmx(vcpu),
vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
VM_ENTRY_INSTRUCTION_LEN,
@@ -4145,6 +5939,21 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ if (is_guest_mode(vcpu) && !vmx->nested.nested_run_pending) {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ if (vmcs12->idt_vectoring_info_field &
+ VECTORING_INFO_VALID_MASK) {
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ vmcs12->idt_vectoring_info_field);
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+ vmcs12->vm_exit_instruction_len);
+ if (vmcs12->idt_vectoring_info_field &
+ VECTORING_INFO_DELIVER_CODE_MASK)
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
+ vmcs12->idt_vectoring_error_code);
+ }
+ }
+
/* Record the guest's net vcpu time for enforced NMI injections. */
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
vmx->entry_time = ktime_get();
@@ -4167,6 +5976,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
vmx_set_interrupt_shadow(vcpu, 0);
+ vmx->__launched = vmx->loaded_vmcs->launched;
asm(
/* Store host registers */
"push %%"R"dx; push %%"R"bp;"
@@ -4237,7 +6047,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
"pop %%"R"bp; pop %%"R"dx \n\t"
"setbe %c[fail](%0) \n\t"
: : "c"(vmx), "d"((unsigned long)HOST_RSP),
- [launched]"i"(offsetof(struct vcpu_vmx, launched)),
+ [launched]"i"(offsetof(struct vcpu_vmx, __launched)),
[fail]"i"(offsetof(struct vcpu_vmx, fail)),
[host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)),
[rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),
@@ -4276,8 +6086,19 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+ if (is_guest_mode(vcpu)) {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ vmcs12->idt_vectoring_info_field = vmx->idt_vectoring_info;
+ if (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) {
+ vmcs12->idt_vectoring_error_code =
+ vmcs_read32(IDT_VECTORING_ERROR_CODE);
+ vmcs12->vm_exit_instruction_len =
+ vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ }
+ }
+
asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
- vmx->launched = 1;
+ vmx->loaded_vmcs->launched = 1;
vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
@@ -4289,41 +6110,18 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
#undef R
#undef Q
-static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (vmx->vmcs) {
- vcpu_clear(vmx);
- free_vmcs(vmx->vmcs);
- vmx->vmcs = NULL;
- }
-}
-
static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
free_vpid(vmx);
- vmx_free_vmcs(vcpu);
+ free_nested(vmx);
+ free_loaded_vmcs(vmx->loaded_vmcs);
kfree(vmx->guest_msrs);
kvm_vcpu_uninit(vcpu);
kmem_cache_free(kvm_vcpu_cache, vmx);
}
-static inline void vmcs_init(struct vmcs *vmcs)
-{
- u64 phys_addr = __pa(per_cpu(vmxarea, raw_smp_processor_id()));
-
- if (!vmm_exclusive)
- kvm_cpu_vmxon(phys_addr);
-
- vmcs_clear(vmcs);
-
- if (!vmm_exclusive)
- kvm_cpu_vmxoff();
-}
-
static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
{
int err;
@@ -4345,11 +6143,15 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
goto uninit_vcpu;
}
- vmx->vmcs = alloc_vmcs();
- if (!vmx->vmcs)
+ vmx->loaded_vmcs = &vmx->vmcs01;
+ vmx->loaded_vmcs->vmcs = alloc_vmcs();
+ if (!vmx->loaded_vmcs->vmcs)
goto free_msrs;
-
- vmcs_init(vmx->vmcs);
+ if (!vmm_exclusive)
+ kvm_cpu_vmxon(__pa(per_cpu(vmxarea, raw_smp_processor_id())));
+ loaded_vmcs_init(vmx->loaded_vmcs);
+ if (!vmm_exclusive)
+ kvm_cpu_vmxoff();
cpu = get_cpu();
vmx_vcpu_load(&vmx->vcpu, cpu);
@@ -4375,10 +6177,13 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
goto free_vmcs;
}
+ vmx->nested.current_vmptr = -1ull;
+ vmx->nested.current_vmcs12 = NULL;
+
return &vmx->vcpu;
free_vmcs:
- free_vmcs(vmx->vmcs);
+ free_vmcs(vmx->loaded_vmcs->vmcs);
free_msrs:
kfree(vmx->guest_msrs);
uninit_vcpu:
@@ -4512,6 +6317,650 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
{
+ if (func == 1 && nested)
+ entry->ecx |= bit(X86_FEATURE_VMX);
+}
+
+/*
+ * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested
+ * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it
+ * with L0's requirements for its guest (a.k.a. vmsc01), so we can run the L2
+ * guest in a way that will both be appropriate to L1's requests, and our
+ * needs. In addition to modifying the active vmcs (which is vmcs02), this
+ * function also has additional necessary side-effects, like setting various
+ * vcpu->arch fields.
+ */
+static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 exec_control;
+
+ vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector);
+ vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector);
+ vmcs_write16(GUEST_SS_SELECTOR, vmcs12->guest_ss_selector);
+ vmcs_write16(GUEST_DS_SELECTOR, vmcs12->guest_ds_selector);
+ vmcs_write16(GUEST_FS_SELECTOR, vmcs12->guest_fs_selector);
+ vmcs_write16(GUEST_GS_SELECTOR, vmcs12->guest_gs_selector);
+ vmcs_write16(GUEST_LDTR_SELECTOR, vmcs12->guest_ldtr_selector);
+ vmcs_write16(GUEST_TR_SELECTOR, vmcs12->guest_tr_selector);
+ vmcs_write32(GUEST_ES_LIMIT, vmcs12->guest_es_limit);
+ vmcs_write32(GUEST_CS_LIMIT, vmcs12->guest_cs_limit);
+ vmcs_write32(GUEST_SS_LIMIT, vmcs12->guest_ss_limit);
+ vmcs_write32(GUEST_DS_LIMIT, vmcs12->guest_ds_limit);
+ vmcs_write32(GUEST_FS_LIMIT, vmcs12->guest_fs_limit);
+ vmcs_write32(GUEST_GS_LIMIT, vmcs12->guest_gs_limit);
+ vmcs_write32(GUEST_LDTR_LIMIT, vmcs12->guest_ldtr_limit);
+ vmcs_write32(GUEST_TR_LIMIT, vmcs12->guest_tr_limit);
+ vmcs_write32(GUEST_GDTR_LIMIT, vmcs12->guest_gdtr_limit);
+ vmcs_write32(GUEST_IDTR_LIMIT, vmcs12->guest_idtr_limit);
+ vmcs_write32(GUEST_ES_AR_BYTES, vmcs12->guest_es_ar_bytes);
+ vmcs_write32(GUEST_CS_AR_BYTES, vmcs12->guest_cs_ar_bytes);
+ vmcs_write32(GUEST_SS_AR_BYTES, vmcs12->guest_ss_ar_bytes);
+ vmcs_write32(GUEST_DS_AR_BYTES, vmcs12->guest_ds_ar_bytes);
+ vmcs_write32(GUEST_FS_AR_BYTES, vmcs12->guest_fs_ar_bytes);
+ vmcs_write32(GUEST_GS_AR_BYTES, vmcs12->guest_gs_ar_bytes);
+ vmcs_write32(GUEST_LDTR_AR_BYTES, vmcs12->guest_ldtr_ar_bytes);
+ vmcs_write32(GUEST_TR_AR_BYTES, vmcs12->guest_tr_ar_bytes);
+ vmcs_writel(GUEST_ES_BASE, vmcs12->guest_es_base);
+ vmcs_writel(GUEST_CS_BASE, vmcs12->guest_cs_base);
+ vmcs_writel(GUEST_SS_BASE, vmcs12->guest_ss_base);
+ vmcs_writel(GUEST_DS_BASE, vmcs12->guest_ds_base);
+ vmcs_writel(GUEST_FS_BASE, vmcs12->guest_fs_base);
+ vmcs_writel(GUEST_GS_BASE, vmcs12->guest_gs_base);
+ vmcs_writel(GUEST_LDTR_BASE, vmcs12->guest_ldtr_base);
+ vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base);
+ vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base);
+ vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base);
+
+ vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ vmcs12->vm_entry_intr_info_field);
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
+ vmcs12->vm_entry_exception_error_code);
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+ vmcs12->vm_entry_instruction_len);
+ vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
+ vmcs12->guest_interruptibility_info);
+ vmcs_write32(GUEST_ACTIVITY_STATE, vmcs12->guest_activity_state);
+ vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs);
+ vmcs_writel(GUEST_DR7, vmcs12->guest_dr7);
+ vmcs_writel(GUEST_RFLAGS, vmcs12->guest_rflags);
+ vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS,
+ vmcs12->guest_pending_dbg_exceptions);
+ vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp);
+ vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip);
+
+ vmcs_write64(VMCS_LINK_POINTER, -1ull);
+
+ vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
+ (vmcs_config.pin_based_exec_ctrl |
+ vmcs12->pin_based_vm_exec_control));
+
+ /*
+ * Whether page-faults are trapped is determined by a combination of
+ * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF.
+ * If enable_ept, L0 doesn't care about page faults and we should
+ * set all of these to L1's desires. However, if !enable_ept, L0 does
+ * care about (at least some) page faults, and because it is not easy
+ * (if at all possible?) to merge L0 and L1's desires, we simply ask
+ * to exit on each and every L2 page fault. This is done by setting
+ * MASK=MATCH=0 and (see below) EB.PF=1.
+ * Note that below we don't need special code to set EB.PF beyond the
+ * "or"ing of the EB of vmcs01 and vmcs12, because when enable_ept,
+ * vmcs01's EB.PF is 0 so the "or" will take vmcs12's value, and when
+ * !enable_ept, EB.PF is 1, so the "or" will always be 1.
+ *
+ * A problem with this approach (when !enable_ept) is that L1 may be
+ * injected with more page faults than it asked for. This could have
+ * caused problems, but in practice existing hypervisors don't care.
+ * To fix this, we will need to emulate the PFEC checking (on the L1
+ * page tables), using walk_addr(), when injecting PFs to L1.
+ */
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK,
+ enable_ept ? vmcs12->page_fault_error_code_mask : 0);
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH,
+ enable_ept ? vmcs12->page_fault_error_code_match : 0);
+
+ if (cpu_has_secondary_exec_ctrls()) {
+ u32 exec_control = vmx_secondary_exec_control(vmx);
+ if (!vmx->rdtscp_enabled)
+ exec_control &= ~SECONDARY_EXEC_RDTSCP;
+ /* Take the following fields only from vmcs12 */
+ exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ if (nested_cpu_has(vmcs12,
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
+ exec_control |= vmcs12->secondary_vm_exec_control;
+
+ if (exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) {
+ /*
+ * Translate L1 physical address to host physical
+ * address for vmcs02. Keep the page pinned, so this
+ * physical address remains valid. We keep a reference
+ * to it so we can release it later.
+ */
+ if (vmx->nested.apic_access_page) /* shouldn't happen */
+ nested_release_page(vmx->nested.apic_access_page);
+ vmx->nested.apic_access_page =
+ nested_get_page(vcpu, vmcs12->apic_access_addr);
+ /*
+ * If translation failed, no matter: This feature asks
+ * to exit when accessing the given address, and if it
+ * can never be accessed, this feature won't do
+ * anything anyway.
+ */
+ if (!vmx->nested.apic_access_page)
+ exec_control &=
+ ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ else
+ vmcs_write64(APIC_ACCESS_ADDR,
+ page_to_phys(vmx->nested.apic_access_page));
+ }
+
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+ }
+
+
+ /*
+ * Set host-state according to L0's settings (vmcs12 is irrelevant here)
+ * Some constant fields are set here by vmx_set_constant_host_state().
+ * Other fields are different per CPU, and will be set later when
+ * vmx_vcpu_load() is called, and when vmx_save_host_state() is called.
+ */
+ vmx_set_constant_host_state();
+
+ /*
+ * HOST_RSP is normally set correctly in vmx_vcpu_run() just before
+ * entry, but only if the current (host) sp changed from the value
+ * we wrote last (vmx->host_rsp). This cache is no longer relevant
+ * if we switch vmcs, and rather than hold a separate cache per vmcs,
+ * here we just force the write to happen on entry.
+ */
+ vmx->host_rsp = 0;
+
+ exec_control = vmx_exec_control(vmx); /* L0's desires */
+ exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+ exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
+ exec_control &= ~CPU_BASED_TPR_SHADOW;
+ exec_control |= vmcs12->cpu_based_vm_exec_control;
+ /*
+ * Merging of IO and MSR bitmaps not currently supported.
+ * Rather, exit every time.
+ */
+ exec_control &= ~CPU_BASED_USE_MSR_BITMAPS;
+ exec_control &= ~CPU_BASED_USE_IO_BITMAPS;
+ exec_control |= CPU_BASED_UNCOND_IO_EXITING;
+
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
+
+ /* EXCEPTION_BITMAP and CR0_GUEST_HOST_MASK should basically be the
+ * bitwise-or of what L1 wants to trap for L2, and what we want to
+ * trap. Note that CR0.TS also needs updating - we do this later.
+ */
+ update_exception_bitmap(vcpu);
+ vcpu->arch.cr0_guest_owned_bits &= ~vmcs12->cr0_guest_host_mask;
+ vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+
+ /* Note: IA32_MODE, LOAD_IA32_EFER are modified by vmx_set_efer below */
+ vmcs_write32(VM_EXIT_CONTROLS,
+ vmcs12->vm_exit_controls | vmcs_config.vmexit_ctrl);
+ vmcs_write32(VM_ENTRY_CONTROLS, vmcs12->vm_entry_controls |
+ (vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE));
+
+ if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT)
+ vmcs_write64(GUEST_IA32_PAT, vmcs12->guest_ia32_pat);
+ else if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT)
+ vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat);
+
+
+ set_cr4_guest_host_mask(vmx);
+
+ vmcs_write64(TSC_OFFSET,
+ vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+
+ if (enable_vpid) {
+ /*
+ * Trivially support vpid by letting L2s share their parent
+ * L1's vpid. TODO: move to a more elaborate solution, giving
+ * each L2 its own vpid and exposing the vpid feature to L1.
+ */
+ vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+ vmx_flush_tlb(vcpu);
+ }
+
+ if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)
+ vcpu->arch.efer = vmcs12->guest_ia32_efer;
+ if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE)
+ vcpu->arch.efer |= (EFER_LMA | EFER_LME);
+ else
+ vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
+ /* Note: modifies VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */
+ vmx_set_efer(vcpu, vcpu->arch.efer);
+
+ /*
+ * This sets GUEST_CR0 to vmcs12->guest_cr0, with possibly a modified
+ * TS bit (for lazy fpu) and bits which we consider mandatory enabled.
+ * The CR0_READ_SHADOW is what L2 should have expected to read given
+ * the specifications by L1; It's not enough to take
+ * vmcs12->cr0_read_shadow because on our cr0_guest_host_mask we we
+ * have more bits than L1 expected.
+ */
+ vmx_set_cr0(vcpu, vmcs12->guest_cr0);
+ vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
+
+ vmx_set_cr4(vcpu, vmcs12->guest_cr4);
+ vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12));
+
+ /* shadow page tables on either EPT or shadow page tables */
+ kvm_set_cr3(vcpu, vmcs12->guest_cr3);
+ kvm_mmu_reset_context(vcpu);
+
+ kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
+ kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip);
+}
+
+/*
+ * nested_vmx_run() handles a nested entry, i.e., a VMLAUNCH or VMRESUME on L1
+ * for running an L2 nested guest.
+ */
+static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
+{
+ struct vmcs12 *vmcs12;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int cpu;
+ struct loaded_vmcs *vmcs02;
+
+ if (!nested_vmx_check_permission(vcpu) ||
+ !nested_vmx_check_vmcs12(vcpu))
+ return 1;
+
+ skip_emulated_instruction(vcpu);
+ vmcs12 = get_vmcs12(vcpu);
+
+ /*
+ * The nested entry process starts with enforcing various prerequisites
+ * on vmcs12 as required by the Intel SDM, and act appropriately when
+ * they fail: As the SDM explains, some conditions should cause the
+ * instruction to fail, while others will cause the instruction to seem
+ * to succeed, but return an EXIT_REASON_INVALID_STATE.
+ * To speed up the normal (success) code path, we should avoid checking
+ * for misconfigurations which will anyway be caught by the processor
+ * when using the merged vmcs02.
+ */
+ if (vmcs12->launch_state == launch) {
+ nested_vmx_failValid(vcpu,
+ launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS
+ : VMXERR_VMRESUME_NONLAUNCHED_VMCS);
+ return 1;
+ }
+
+ if ((vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_MSR_BITMAPS) &&
+ !IS_ALIGNED(vmcs12->msr_bitmap, PAGE_SIZE)) {
+ /*TODO: Also verify bits beyond physical address width are 0*/
+ nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+ return 1;
+ }
+
+ if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
+ !IS_ALIGNED(vmcs12->apic_access_addr, PAGE_SIZE)) {
+ /*TODO: Also verify bits beyond physical address width are 0*/
+ nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+ return 1;
+ }
+
+ 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__);
+ nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+ return 1;
+ }
+
+ if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
+ nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high) ||
+ !vmx_control_verify(vmcs12->secondary_vm_exec_control,
+ nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high) ||
+ !vmx_control_verify(vmcs12->pin_based_vm_exec_control,
+ nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high) ||
+ !vmx_control_verify(vmcs12->vm_exit_controls,
+ nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high) ||
+ !vmx_control_verify(vmcs12->vm_entry_controls,
+ nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high))
+ {
+ nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+ return 1;
+ }
+
+ if (((vmcs12->host_cr0 & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) ||
+ ((vmcs12->host_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+ return 1;
+ }
+
+ if (((vmcs12->guest_cr0 & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) ||
+ ((vmcs12->guest_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) {
+ nested_vmx_entry_failure(vcpu, vmcs12,
+ EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
+ return 1;
+ }
+ if (vmcs12->vmcs_link_pointer != -1ull) {
+ nested_vmx_entry_failure(vcpu, vmcs12,
+ EXIT_REASON_INVALID_STATE, ENTRY_FAIL_VMCS_LINK_PTR);
+ return 1;
+ }
+
+ /*
+ * We're finally done with prerequisite checking, and can start with
+ * the nested entry.
+ */
+
+ vmcs02 = nested_get_current_vmcs02(vmx);
+ if (!vmcs02)
+ return -ENOMEM;
+
+ enter_guest_mode(vcpu);
+
+ vmx->nested.vmcs01_tsc_offset = vmcs_read64(TSC_OFFSET);
+
+ cpu = get_cpu();
+ vmx->loaded_vmcs = vmcs02;
+ vmx_vcpu_put(vcpu);
+ vmx_vcpu_load(vcpu, cpu);
+ vcpu->cpu = cpu;
+ put_cpu();
+
+ vmcs12->launch_state = 1;
+
+ prepare_vmcs02(vcpu, vmcs12);
+
+ /*
+ * Note no nested_vmx_succeed or nested_vmx_fail here. At this point
+ * we are no longer running L1, and VMLAUNCH/VMRESUME has not yet
+ * returned as far as L1 is concerned. It will only return (and set
+ * the success flag) when L2 exits (see nested_vmx_vmexit()).
+ */
+ return 1;
+}
+
+/*
+ * On a nested exit from L2 to L1, vmcs12.guest_cr0 might not be up-to-date
+ * because L2 may have changed some cr0 bits directly (CRO_GUEST_HOST_MASK).
+ * This function returns the new value we should put in vmcs12.guest_cr0.
+ * It's not enough to just return the vmcs02 GUEST_CR0. Rather,
+ * 1. Bits that neither L0 nor L1 trapped, were set directly by L2 and are now
+ * available in vmcs02 GUEST_CR0. (Note: It's enough to check that L0
+ * didn't trap the bit, because if L1 did, so would L0).
+ * 2. Bits that L1 asked to trap (and therefore L0 also did) could not have
+ * been modified by L2, and L1 knows it. So just leave the old value of
+ * the bit from vmcs12.guest_cr0. Note that the bit from vmcs02 GUEST_CR0
+ * isn't relevant, because if L0 traps this bit it can set it to anything.
+ * 3. Bits that L1 didn't trap, but L0 did. L1 believes the guest could have
+ * changed these bits, and therefore they need to be updated, but L0
+ * didn't necessarily allow them to be changed in GUEST_CR0 - and rather
+ * put them in vmcs02 CR0_READ_SHADOW. So take these bits from there.
+ */
+static inline unsigned long
+vmcs12_guest_cr0(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ return
+ /*1*/ (vmcs_readl(GUEST_CR0) & vcpu->arch.cr0_guest_owned_bits) |
+ /*2*/ (vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask) |
+ /*3*/ (vmcs_readl(CR0_READ_SHADOW) & ~(vmcs12->cr0_guest_host_mask |
+ vcpu->arch.cr0_guest_owned_bits));
+}
+
+static inline unsigned long
+vmcs12_guest_cr4(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ return
+ /*1*/ (vmcs_readl(GUEST_CR4) & vcpu->arch.cr4_guest_owned_bits) |
+ /*2*/ (vmcs12->guest_cr4 & vmcs12->cr4_guest_host_mask) |
+ /*3*/ (vmcs_readl(CR4_READ_SHADOW) & ~(vmcs12->cr4_guest_host_mask |
+ vcpu->arch.cr4_guest_owned_bits));
+}
+
+/*
+ * prepare_vmcs12 is part of what we need to do when the nested L2 guest exits
+ * and we want to prepare to run its L1 parent. L1 keeps a vmcs for L2 (vmcs12),
+ * and this function updates it to reflect the changes to the guest state while
+ * L2 was running (and perhaps made some exits which were handled directly by L0
+ * without going back to L1), and to reflect the exit reason.
+ * Note that we do not have to copy here all VMCS fields, just those that
+ * could have changed by the L2 guest or the exit - i.e., the guest-state and
+ * exit-information fields only. Other fields are modified by L1 with VMWRITE,
+ * which already writes to vmcs12 directly.
+ */
+void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ /* update guest state fields: */
+ vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
+ vmcs12->guest_cr4 = vmcs12_guest_cr4(vcpu, vmcs12);
+
+ kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
+ vmcs12->guest_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
+ vmcs12->guest_rip = kvm_register_read(vcpu, VCPU_REGS_RIP);
+ vmcs12->guest_rflags = vmcs_readl(GUEST_RFLAGS);
+
+ vmcs12->guest_es_selector = vmcs_read16(GUEST_ES_SELECTOR);
+ vmcs12->guest_cs_selector = vmcs_read16(GUEST_CS_SELECTOR);
+ vmcs12->guest_ss_selector = vmcs_read16(GUEST_SS_SELECTOR);
+ vmcs12->guest_ds_selector = vmcs_read16(GUEST_DS_SELECTOR);
+ vmcs12->guest_fs_selector = vmcs_read16(GUEST_FS_SELECTOR);
+ vmcs12->guest_gs_selector = vmcs_read16(GUEST_GS_SELECTOR);
+ vmcs12->guest_ldtr_selector = vmcs_read16(GUEST_LDTR_SELECTOR);
+ vmcs12->guest_tr_selector = vmcs_read16(GUEST_TR_SELECTOR);
+ vmcs12->guest_es_limit = vmcs_read32(GUEST_ES_LIMIT);
+ vmcs12->guest_cs_limit = vmcs_read32(GUEST_CS_LIMIT);
+ vmcs12->guest_ss_limit = vmcs_read32(GUEST_SS_LIMIT);
+ vmcs12->guest_ds_limit = vmcs_read32(GUEST_DS_LIMIT);
+ vmcs12->guest_fs_limit = vmcs_read32(GUEST_FS_LIMIT);
+ vmcs12->guest_gs_limit = vmcs_read32(GUEST_GS_LIMIT);
+ vmcs12->guest_ldtr_limit = vmcs_read32(GUEST_LDTR_LIMIT);
+ vmcs12->guest_tr_limit = vmcs_read32(GUEST_TR_LIMIT);
+ vmcs12->guest_gdtr_limit = vmcs_read32(GUEST_GDTR_LIMIT);
+ vmcs12->guest_idtr_limit = vmcs_read32(GUEST_IDTR_LIMIT);
+ vmcs12->guest_es_ar_bytes = vmcs_read32(GUEST_ES_AR_BYTES);
+ vmcs12->guest_cs_ar_bytes = vmcs_read32(GUEST_CS_AR_BYTES);
+ vmcs12->guest_ss_ar_bytes = vmcs_read32(GUEST_SS_AR_BYTES);
+ vmcs12->guest_ds_ar_bytes = vmcs_read32(GUEST_DS_AR_BYTES);
+ vmcs12->guest_fs_ar_bytes = vmcs_read32(GUEST_FS_AR_BYTES);
+ vmcs12->guest_gs_ar_bytes = vmcs_read32(GUEST_GS_AR_BYTES);
+ vmcs12->guest_ldtr_ar_bytes = vmcs_read32(GUEST_LDTR_AR_BYTES);
+ vmcs12->guest_tr_ar_bytes = vmcs_read32(GUEST_TR_AR_BYTES);
+ vmcs12->guest_es_base = vmcs_readl(GUEST_ES_BASE);
+ vmcs12->guest_cs_base = vmcs_readl(GUEST_CS_BASE);
+ vmcs12->guest_ss_base = vmcs_readl(GUEST_SS_BASE);
+ vmcs12->guest_ds_base = vmcs_readl(GUEST_DS_BASE);
+ vmcs12->guest_fs_base = vmcs_readl(GUEST_FS_BASE);
+ vmcs12->guest_gs_base = vmcs_readl(GUEST_GS_BASE);
+ vmcs12->guest_ldtr_base = vmcs_readl(GUEST_LDTR_BASE);
+ vmcs12->guest_tr_base = vmcs_readl(GUEST_TR_BASE);
+ vmcs12->guest_gdtr_base = vmcs_readl(GUEST_GDTR_BASE);
+ vmcs12->guest_idtr_base = vmcs_readl(GUEST_IDTR_BASE);
+
+ vmcs12->guest_activity_state = vmcs_read32(GUEST_ACTIVITY_STATE);
+ vmcs12->guest_interruptibility_info =
+ vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+ vmcs12->guest_pending_dbg_exceptions =
+ vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS);
+
+ /* TODO: These cannot have changed unless we have MSR bitmaps and
+ * the relevant bit asks not to trap the change */
+ vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+ if (vmcs12->vm_entry_controls & VM_EXIT_SAVE_IA32_PAT)
+ vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
+ vmcs12->guest_sysenter_cs = vmcs_read32(GUEST_SYSENTER_CS);
+ vmcs12->guest_sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP);
+ vmcs12->guest_sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP);
+
+ /* update exit information fields: */
+
+ vmcs12->vm_exit_reason = vmcs_read32(VM_EXIT_REASON);
+ vmcs12->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ vmcs12->vm_exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+ vmcs12->vm_exit_intr_error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+ vmcs12->idt_vectoring_info_field =
+ vmcs_read32(IDT_VECTORING_INFO_FIELD);
+ vmcs12->idt_vectoring_error_code =
+ vmcs_read32(IDT_VECTORING_ERROR_CODE);
+ vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+
+ /* clear vm-entry fields which are to be cleared on exit */
+ if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
+ vmcs12->vm_entry_intr_info_field &= ~INTR_INFO_VALID_MASK;
+}
+
+/*
+ * A part of what we need to when the nested L2 guest exits and we want to
+ * run its L1 parent, is to reset L1's guest state to the host state specified
+ * in vmcs12.
+ * This function is to be called not only on normal nested exit, but also on
+ * a nested entry failure, as explained in Intel's spec, 3B.23.7 ("VM-Entry
+ * Failures During or After Loading Guest State").
+ * This function should be called when the active VMCS is L1's (vmcs01).
+ */
+void load_vmcs12_host_state(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
+ vcpu->arch.efer = vmcs12->host_ia32_efer;
+ if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
+ vcpu->arch.efer |= (EFER_LMA | EFER_LME);
+ else
+ vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
+ vmx_set_efer(vcpu, vcpu->arch.efer);
+
+ kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp);
+ kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip);
+ /*
+ * Note that calling vmx_set_cr0 is important, even if cr0 hasn't
+ * actually changed, because it depends on the current state of
+ * fpu_active (which may have changed).
+ * Note that vmx_set_cr0 refers to efer set above.
+ */
+ kvm_set_cr0(vcpu, vmcs12->host_cr0);
+ /*
+ * If we did fpu_activate()/fpu_deactivate() during L2's run, we need
+ * to apply the same changes to L1's vmcs. We just set cr0 correctly,
+ * but we also need to update cr0_guest_host_mask and exception_bitmap.
+ */
+ update_exception_bitmap(vcpu);
+ vcpu->arch.cr0_guest_owned_bits = (vcpu->fpu_active ? X86_CR0_TS : 0);
+ vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+
+ /*
+ * Note that CR4_GUEST_HOST_MASK is already set in the original vmcs01
+ * (KVM doesn't change it)- no reason to call set_cr4_guest_host_mask();
+ */
+ vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
+ kvm_set_cr4(vcpu, vmcs12->host_cr4);
+
+ /* shadow page tables on either EPT or shadow page tables */
+ kvm_set_cr3(vcpu, vmcs12->host_cr3);
+ kvm_mmu_reset_context(vcpu);
+
+ if (enable_vpid) {
+ /*
+ * Trivially support vpid by letting L2s share their parent
+ * L1's vpid. TODO: move to a more elaborate solution, giving
+ * each L2 its own vpid and exposing the vpid feature to L1.
+ */
+ vmx_flush_tlb(vcpu);
+ }
+
+
+ vmcs_write32(GUEST_SYSENTER_CS, vmcs12->host_ia32_sysenter_cs);
+ vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->host_ia32_sysenter_esp);
+ vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip);
+ vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base);
+ vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base);
+ vmcs_writel(GUEST_TR_BASE, vmcs12->host_tr_base);
+ vmcs_writel(GUEST_GS_BASE, vmcs12->host_gs_base);
+ vmcs_writel(GUEST_FS_BASE, vmcs12->host_fs_base);
+ vmcs_write16(GUEST_ES_SELECTOR, vmcs12->host_es_selector);
+ vmcs_write16(GUEST_CS_SELECTOR, vmcs12->host_cs_selector);
+ vmcs_write16(GUEST_SS_SELECTOR, vmcs12->host_ss_selector);
+ vmcs_write16(GUEST_DS_SELECTOR, vmcs12->host_ds_selector);
+ vmcs_write16(GUEST_FS_SELECTOR, vmcs12->host_fs_selector);
+ vmcs_write16(GUEST_GS_SELECTOR, vmcs12->host_gs_selector);
+ vmcs_write16(GUEST_TR_SELECTOR, vmcs12->host_tr_selector);
+
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT)
+ vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
+ vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL,
+ vmcs12->host_ia32_perf_global_ctrl);
+}
+
+/*
+ * Emulate an exit from nested guest (L2) to L1, i.e., prepare to run L1
+ * and modify vmcs12 to make it see what it would expect to see there if
+ * L2 was its real guest. Must only be called when in L2 (is_guest_mode())
+ */
+static void nested_vmx_vmexit(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int cpu;
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ leave_guest_mode(vcpu);
+ prepare_vmcs12(vcpu, vmcs12);
+
+ cpu = get_cpu();
+ vmx->loaded_vmcs = &vmx->vmcs01;
+ vmx_vcpu_put(vcpu);
+ vmx_vcpu_load(vcpu, cpu);
+ vcpu->cpu = cpu;
+ put_cpu();
+
+ /* if no vmcs02 cache requested, remove the one we used */
+ if (VMCS02_POOL_SIZE == 0)
+ nested_free_vmcs02(vmx, vmx->nested.current_vmptr);
+
+ load_vmcs12_host_state(vcpu, vmcs12);
+
+ /* Update TSC_OFFSET if vmx_adjust_tsc_offset() was used 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 */
+ vmx->host_rsp = 0;
+
+ /* Unpin physical memory we referred to in vmcs02 */
+ if (vmx->nested.apic_access_page) {
+ nested_release_page(vmx->nested.apic_access_page);
+ vmx->nested.apic_access_page = 0;
+ }
+
+ /*
+ * Exiting from L2 to L1, we're now back to L1 which thinks it just
+ * finished a VMLAUNCH or VMRESUME instruction, so we need to set the
+ * success or failure flag accordingly.
+ */
+ if (unlikely(vmx->fail)) {
+ vmx->fail = 0;
+ nested_vmx_failValid(vcpu, vmcs_read32(VM_INSTRUCTION_ERROR));
+ } else
+ nested_vmx_succeed(vcpu);
+}
+
+/*
+ * L1's failure to enter L2 is a subset of a normal exit, as explained in
+ * 23.7 "VM-entry failures during or after loading guest state" (this also
+ * lists the acceptable exit-reason and exit-qualification parameters).
+ * It should only be called before L2 actually succeeded to run, and when
+ * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
+ */
+static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12,
+ u32 reason, unsigned long qualification)
+{
+ load_vmcs12_host_state(vcpu, vmcs12);
+ vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
+ vmcs12->exit_qualification = qualification;
+ nested_vmx_succeed(vcpu);
}
static int vmx_check_intercept(struct kvm_vcpu *vcpu,
@@ -4670,16 +7119,13 @@ static int __init vmx_init(void)
vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
if (enable_ept) {
- bypass_guest_pf = 0;
kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
VMX_EPT_EXECUTABLE_MASK);
+ ept_set_mmio_spte_mask();
kvm_enable_tdp();
} else
kvm_disable_tdp();
- if (bypass_guest_pf)
- kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
-
return 0;
out3:
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 77c9d8673dc4..84a28ea45fa4 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -347,6 +347,7 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
vcpu->arch.cr2 = fault->address;
kvm_queue_exception_e(vcpu, PF_VECTOR, fault->error_code);
}
+EXPORT_SYMBOL_GPL(kvm_inject_page_fault);
void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
{
@@ -579,6 +580,22 @@ static bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
return best && (best->ecx & bit(X86_FEATURE_XSAVE));
}
+static bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ best = kvm_find_cpuid_entry(vcpu, 7, 0);
+ return best && (best->ebx & bit(X86_FEATURE_SMEP));
+}
+
+static bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ best = kvm_find_cpuid_entry(vcpu, 7, 0);
+ return best && (best->ebx & bit(X86_FEATURE_FSGSBASE));
+}
+
static void update_cpuid(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
@@ -598,14 +615,20 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
{
unsigned long old_cr4 = kvm_read_cr4(vcpu);
- unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE;
-
+ unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE |
+ X86_CR4_PAE | X86_CR4_SMEP;
if (cr4 & CR4_RESERVED_BITS)
return 1;
if (!guest_cpuid_has_xsave(vcpu) && (cr4 & X86_CR4_OSXSAVE))
return 1;
+ if (!guest_cpuid_has_smep(vcpu) && (cr4 & X86_CR4_SMEP))
+ return 1;
+
+ if (!guest_cpuid_has_fsgsbase(vcpu) && (cr4 & X86_CR4_RDWRGSFS))
+ return 1;
+
if (is_long_mode(vcpu)) {
if (!(cr4 & X86_CR4_PAE))
return 1;
@@ -615,11 +638,9 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
kvm_read_cr3(vcpu)))
return 1;
- if (cr4 & X86_CR4_VMXE)
+ if (kvm_x86_ops->set_cr4(vcpu, cr4))
return 1;
- kvm_x86_ops->set_cr4(vcpu, cr4);
-
if ((cr4 ^ old_cr4) & pdptr_bits)
kvm_mmu_reset_context(vcpu);
@@ -787,12 +808,12 @@ EXPORT_SYMBOL_GPL(kvm_get_dr);
* kvm-specific. Those are put in the beginning of the list.
*/
-#define KVM_SAVE_MSRS_BEGIN 8
+#define KVM_SAVE_MSRS_BEGIN 9
static u32 msrs_to_save[] = {
MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
- HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN,
+ HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME,
MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
MSR_STAR,
#ifdef CONFIG_X86_64
@@ -1388,7 +1409,7 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
return 1;
kvm_x86_ops->patch_hypercall(vcpu, instructions);
((unsigned char *)instructions)[3] = 0xc3; /* ret */
- if (copy_to_user((void __user *)addr, instructions, 4))
+ if (__copy_to_user((void __user *)addr, instructions, 4))
return 1;
kvm->arch.hv_hypercall = data;
break;
@@ -1415,7 +1436,7 @@ static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data)
HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT);
if (kvm_is_error_hva(addr))
return 1;
- if (clear_user((void __user *)addr, PAGE_SIZE))
+ if (__clear_user((void __user *)addr, PAGE_SIZE))
return 1;
vcpu->arch.hv_vapic = data;
break;
@@ -1467,6 +1488,35 @@ static void kvmclock_reset(struct kvm_vcpu *vcpu)
}
}
+static void accumulate_steal_time(struct kvm_vcpu *vcpu)
+{
+ u64 delta;
+
+ if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
+ return;
+
+ delta = current->sched_info.run_delay - vcpu->arch.st.last_steal;
+ vcpu->arch.st.last_steal = current->sched_info.run_delay;
+ vcpu->arch.st.accum_steal = delta;
+}
+
+static void record_steal_time(struct kvm_vcpu *vcpu)
+{
+ if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
+ return;
+
+ if (unlikely(kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
+ &vcpu->arch.st.steal, sizeof(struct kvm_steal_time))))
+ return;
+
+ vcpu->arch.st.steal.steal += vcpu->arch.st.accum_steal;
+ vcpu->arch.st.steal.version += 2;
+ vcpu->arch.st.accum_steal = 0;
+
+ kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
+ &vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+}
+
int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
{
switch (msr) {
@@ -1549,6 +1599,33 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
if (kvm_pv_enable_async_pf(vcpu, data))
return 1;
break;
+ case MSR_KVM_STEAL_TIME:
+
+ if (unlikely(!sched_info_on()))
+ return 1;
+
+ if (data & KVM_STEAL_RESERVED_MASK)
+ return 1;
+
+ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
+ data & KVM_STEAL_VALID_BITS))
+ return 1;
+
+ vcpu->arch.st.msr_val = data;
+
+ if (!(data & KVM_MSR_ENABLED))
+ break;
+
+ vcpu->arch.st.last_steal = current->sched_info.run_delay;
+
+ preempt_disable();
+ accumulate_steal_time(vcpu);
+ preempt_enable();
+
+ kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
+
+ break;
+
case MSR_IA32_MCG_CTL:
case MSR_IA32_MCG_STATUS:
case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
@@ -1834,6 +1911,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
case MSR_KVM_ASYNC_PF_EN:
data = vcpu->arch.apf.msr_val;
break;
+ case MSR_KVM_STEAL_TIME:
+ data = vcpu->arch.st.msr_val;
+ break;
case MSR_IA32_P5_MC_ADDR:
case MSR_IA32_P5_MC_TYPE:
case MSR_IA32_MCG_CAP:
@@ -2145,6 +2225,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_migrate_timers(vcpu);
vcpu->cpu = cpu;
}
+
+ accumulate_steal_time(vcpu);
+ kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -2283,6 +2366,13 @@ static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function,
entry->flags = 0;
}
+static bool supported_xcr0_bit(unsigned bit)
+{
+ u64 mask = ((u64)1 << bit);
+
+ return mask & (XSTATE_FP | XSTATE_SSE | XSTATE_YMM) & host_xcr0;
+}
+
#define F(x) bit(X86_FEATURE_##x)
static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
@@ -2328,7 +2418,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
0 /* Reserved, DCA */ | F(XMM4_1) |
F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
- F(F16C);
+ F(F16C) | F(RDRAND);
/* cpuid 0x80000001.ecx */
const u32 kvm_supported_word6_x86_features =
F(LAHF_LM) | F(CMP_LEGACY) | 0 /*SVM*/ | 0 /* ExtApicSpace */ |
@@ -2342,6 +2432,10 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
F(ACE2) | F(ACE2_EN) | F(PHE) | F(PHE_EN) |
F(PMM) | F(PMM_EN);
+ /* cpuid 7.0.ebx */
+ const u32 kvm_supported_word9_x86_features =
+ F(SMEP) | F(FSGSBASE) | F(ERMS);
+
/* all calls to cpuid_count() should be made on the same cpu */
get_cpu();
do_cpuid_1_ent(entry, function, index);
@@ -2376,7 +2470,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
}
break;
}
- /* function 4 and 0xb have additional index. */
+ /* function 4 has additional index. */
case 4: {
int i, cache_type;
@@ -2393,6 +2487,22 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
}
break;
}
+ case 7: {
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ /* Mask ebx against host capbability word 9 */
+ if (index == 0) {
+ entry->ebx &= kvm_supported_word9_x86_features;
+ cpuid_mask(&entry->ebx, 9);
+ } else
+ entry->ebx = 0;
+ entry->eax = 0;
+ entry->ecx = 0;
+ entry->edx = 0;
+ break;
+ }
+ case 9:
+ break;
+ /* function 0xb has additional index. */
case 0xb: {
int i, level_type;
@@ -2410,16 +2520,17 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
break;
}
case 0xd: {
- int i;
+ int idx, i;
entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
- for (i = 1; *nent < maxnent && i < 64; ++i) {
- if (entry[i].eax == 0)
+ for (idx = 1, i = 1; *nent < maxnent && idx < 64; ++idx) {
+ do_cpuid_1_ent(&entry[i], function, idx);
+ if (entry[i].eax == 0 || !supported_xcr0_bit(idx))
continue;
- do_cpuid_1_ent(&entry[i], function, i);
entry[i].flags |=
KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
++*nent;
+ ++i;
}
break;
}
@@ -2438,6 +2549,10 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
(1 << KVM_FEATURE_CLOCKSOURCE2) |
(1 << KVM_FEATURE_ASYNC_PF) |
(1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+
+ if (sched_info_on())
+ entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
+
entry->ebx = 0;
entry->ecx = 0;
entry->edx = 0;
@@ -2451,6 +2566,24 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
entry->ecx &= kvm_supported_word6_x86_features;
cpuid_mask(&entry->ecx, 6);
break;
+ case 0x80000008: {
+ unsigned g_phys_as = (entry->eax >> 16) & 0xff;
+ unsigned virt_as = max((entry->eax >> 8) & 0xff, 48U);
+ unsigned phys_as = entry->eax & 0xff;
+
+ if (!g_phys_as)
+ g_phys_as = phys_as;
+ entry->eax = g_phys_as | (virt_as << 8);
+ entry->ebx = entry->edx = 0;
+ break;
+ }
+ case 0x80000019:
+ entry->ecx = entry->edx = 0;
+ break;
+ case 0x8000001a:
+ break;
+ case 0x8000001d:
+ break;
/*Add support for Centaur's CPUID instruction*/
case 0xC0000000:
/*Just support up to 0xC0000004 now*/
@@ -2460,10 +2593,16 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
entry->edx &= kvm_supported_word5_x86_features;
cpuid_mask(&entry->edx, 5);
break;
+ case 3: /* Processor serial number */
+ case 5: /* MONITOR/MWAIT */
+ case 6: /* Thermal management */
+ case 0xA: /* Architectural Performance Monitoring */
+ case 0x80000007: /* Advanced power management */
case 0xC0000002:
case 0xC0000003:
case 0xC0000004:
- /*Now nothing to do, reserved for the future*/
+ default:
+ entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
break;
}
@@ -3817,7 +3956,7 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
exception);
}
-static int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
+int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
gva_t addr, void *val, unsigned int bytes,
struct x86_exception *exception)
{
@@ -3827,6 +3966,7 @@ static int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
exception);
}
+EXPORT_SYMBOL_GPL(kvm_read_guest_virt);
static int kvm_read_guest_virt_system(struct x86_emulate_ctxt *ctxt,
gva_t addr, void *val, unsigned int bytes,
@@ -3836,7 +3976,7 @@ static int kvm_read_guest_virt_system(struct x86_emulate_ctxt *ctxt,
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception);
}
-static int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
+int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
gva_t addr, void *val,
unsigned int bytes,
struct x86_exception *exception)
@@ -3868,6 +4008,42 @@ static int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
out:
return r;
}
+EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system);
+
+static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
+ gpa_t *gpa, struct x86_exception *exception,
+ bool write)
+{
+ u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+
+ if (vcpu_match_mmio_gva(vcpu, gva) &&
+ check_write_user_access(vcpu, write, access,
+ vcpu->arch.access)) {
+ *gpa = vcpu->arch.mmio_gfn << PAGE_SHIFT |
+ (gva & (PAGE_SIZE - 1));
+ trace_vcpu_match_mmio(gva, *gpa, write, false);
+ return 1;
+ }
+
+ if (write)
+ access |= PFERR_WRITE_MASK;
+
+ *gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, exception);
+
+ if (*gpa == UNMAPPED_GVA)
+ return -1;
+
+ /* For APIC access vmexit */
+ if ((*gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+ return 1;
+
+ if (vcpu_match_mmio_gpa(vcpu, *gpa)) {
+ trace_vcpu_match_mmio(gva, *gpa, write, true);
+ return 1;
+ }
+
+ return 0;
+}
static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
unsigned long addr,
@@ -3876,8 +4052,8 @@ static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
struct x86_exception *exception)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
- gpa_t gpa;
- int handled;
+ gpa_t gpa;
+ int handled, ret;
if (vcpu->mmio_read_completed) {
memcpy(val, vcpu->mmio_data, bytes);
@@ -3887,13 +4063,12 @@ static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
return X86EMUL_CONTINUE;
}
- gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, exception);
+ ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, false);
- if (gpa == UNMAPPED_GVA)
+ if (ret < 0)
return X86EMUL_PROPAGATE_FAULT;
- /* For APIC access vmexit */
- if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+ if (ret)
goto mmio;
if (kvm_read_guest_virt(ctxt, addr, val, bytes, exception)
@@ -3944,16 +4119,16 @@ static int emulator_write_emulated_onepage(unsigned long addr,
struct x86_exception *exception,
struct kvm_vcpu *vcpu)
{
- gpa_t gpa;
- int handled;
+ gpa_t gpa;
+ int handled, ret;
- gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception);
+ ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, true);
- if (gpa == UNMAPPED_GVA)
+ if (ret < 0)
return X86EMUL_PROPAGATE_FAULT;
/* For APIC access vmexit */
- if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+ if (ret)
goto mmio;
if (emulator_write_phys(vcpu, gpa, val, bytes))
@@ -4473,9 +4648,24 @@ static void inject_emulated_exception(struct kvm_vcpu *vcpu)
kvm_queue_exception(vcpu, ctxt->exception.vector);
}
+static void init_decode_cache(struct x86_emulate_ctxt *ctxt,
+ const unsigned long *regs)
+{
+ memset(&ctxt->twobyte, 0,
+ (void *)&ctxt->regs - (void *)&ctxt->twobyte);
+ memcpy(ctxt->regs, regs, sizeof(ctxt->regs));
+
+ ctxt->fetch.start = 0;
+ ctxt->fetch.end = 0;
+ ctxt->io_read.pos = 0;
+ ctxt->io_read.end = 0;
+ ctxt->mem_read.pos = 0;
+ ctxt->mem_read.end = 0;
+}
+
static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
{
- struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
int cs_db, cs_l;
/*
@@ -4488,40 +4678,38 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
- vcpu->arch.emulate_ctxt.eflags = kvm_get_rflags(vcpu);
- vcpu->arch.emulate_ctxt.eip = kvm_rip_read(vcpu);
- vcpu->arch.emulate_ctxt.mode =
- (!is_protmode(vcpu)) ? X86EMUL_MODE_REAL :
- (vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM)
- ? X86EMUL_MODE_VM86 : cs_l
- ? X86EMUL_MODE_PROT64 : cs_db
- ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
- vcpu->arch.emulate_ctxt.guest_mode = is_guest_mode(vcpu);
- memset(c, 0, sizeof(struct decode_cache));
- memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
+ ctxt->eflags = kvm_get_rflags(vcpu);
+ ctxt->eip = kvm_rip_read(vcpu);
+ ctxt->mode = (!is_protmode(vcpu)) ? X86EMUL_MODE_REAL :
+ (ctxt->eflags & X86_EFLAGS_VM) ? X86EMUL_MODE_VM86 :
+ cs_l ? X86EMUL_MODE_PROT64 :
+ cs_db ? X86EMUL_MODE_PROT32 :
+ X86EMUL_MODE_PROT16;
+ ctxt->guest_mode = is_guest_mode(vcpu);
+
+ init_decode_cache(ctxt, vcpu->arch.regs);
vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
}
int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip)
{
- struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
int ret;
init_emulate_ctxt(vcpu);
- vcpu->arch.emulate_ctxt.decode.op_bytes = 2;
- vcpu->arch.emulate_ctxt.decode.ad_bytes = 2;
- vcpu->arch.emulate_ctxt.decode.eip = vcpu->arch.emulate_ctxt.eip +
- inc_eip;
- ret = emulate_int_real(&vcpu->arch.emulate_ctxt, &emulate_ops, irq);
+ ctxt->op_bytes = 2;
+ ctxt->ad_bytes = 2;
+ ctxt->_eip = ctxt->eip + inc_eip;
+ ret = emulate_int_real(ctxt, irq);
if (ret != X86EMUL_CONTINUE)
return EMULATE_FAIL;
- vcpu->arch.emulate_ctxt.eip = c->eip;
- memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
- kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
- kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+ ctxt->eip = ctxt->_eip;
+ memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
+ kvm_rip_write(vcpu, ctxt->eip);
+ kvm_set_rflags(vcpu, ctxt->eflags);
if (irq == NMI_VECTOR)
vcpu->arch.nmi_pending = false;
@@ -4582,21 +4770,21 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
int insn_len)
{
int r;
- struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
bool writeback = true;
kvm_clear_exception_queue(vcpu);
if (!(emulation_type & EMULTYPE_NO_DECODE)) {
init_emulate_ctxt(vcpu);
- vcpu->arch.emulate_ctxt.interruptibility = 0;
- vcpu->arch.emulate_ctxt.have_exception = false;
- vcpu->arch.emulate_ctxt.perm_ok = false;
+ ctxt->interruptibility = 0;
+ ctxt->have_exception = false;
+ ctxt->perm_ok = false;
- vcpu->arch.emulate_ctxt.only_vendor_specific_insn
+ ctxt->only_vendor_specific_insn
= emulation_type & EMULTYPE_TRAP_UD;
- r = x86_decode_insn(&vcpu->arch.emulate_ctxt, insn, insn_len);
+ r = x86_decode_insn(ctxt, insn, insn_len);
trace_kvm_emulate_insn_start(vcpu);
++vcpu->stat.insn_emulation;
@@ -4612,7 +4800,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
}
if (emulation_type & EMULTYPE_SKIP) {
- kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.decode.eip);
+ kvm_rip_write(vcpu, ctxt->_eip);
return EMULATE_DONE;
}
@@ -4620,11 +4808,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
changes registers values during IO operation */
if (vcpu->arch.emulate_regs_need_sync_from_vcpu) {
vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
- memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
+ memcpy(ctxt->regs, vcpu->arch.regs, sizeof ctxt->regs);
}
restart:
- r = x86_emulate_insn(&vcpu->arch.emulate_ctxt);
+ r = x86_emulate_insn(ctxt);
if (r == EMULATION_INTERCEPTED)
return EMULATE_DONE;
@@ -4636,7 +4824,7 @@ restart:
return handle_emulation_failure(vcpu);
}
- if (vcpu->arch.emulate_ctxt.have_exception) {
+ if (ctxt->have_exception) {
inject_emulated_exception(vcpu);
r = EMULATE_DONE;
} else if (vcpu->arch.pio.count) {
@@ -4655,13 +4843,12 @@ restart:
r = EMULATE_DONE;
if (writeback) {
- toggle_interruptibility(vcpu,
- vcpu->arch.emulate_ctxt.interruptibility);
- kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+ toggle_interruptibility(vcpu, ctxt->interruptibility);
+ kvm_set_rflags(vcpu, ctxt->eflags);
kvm_make_request(KVM_REQ_EVENT, vcpu);
- memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
+ memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
- kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
+ kvm_rip_write(vcpu, ctxt->eip);
} else
vcpu->arch.emulate_regs_need_sync_to_vcpu = true;
@@ -4878,6 +5065,30 @@ void kvm_after_handle_nmi(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_after_handle_nmi);
+static void kvm_set_mmio_spte_mask(void)
+{
+ u64 mask;
+ int maxphyaddr = boot_cpu_data.x86_phys_bits;
+
+ /*
+ * Set the reserved bits and the present bit of an paging-structure
+ * entry to generate page fault with PFER.RSV = 1.
+ */
+ mask = ((1ull << (62 - maxphyaddr + 1)) - 1) << maxphyaddr;
+ mask |= 1ull;
+
+#ifdef CONFIG_X86_64
+ /*
+ * If reserved bit is not supported, clear the present bit to disable
+ * mmio page fault.
+ */
+ if (maxphyaddr == 52)
+ mask &= ~1ull;
+#endif
+
+ kvm_mmu_set_mmio_spte_mask(mask);
+}
+
int kvm_arch_init(void *opaque)
{
int r;
@@ -4904,10 +5115,10 @@ int kvm_arch_init(void *opaque)
if (r)
goto out;
+ kvm_set_mmio_spte_mask();
kvm_init_msr_list();
kvm_x86_ops = ops;
- kvm_mmu_set_nonpresent_ptes(0ull, 0ull);
kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
PT_DIRTY_MASK, PT64_NX_MASK, 0);
@@ -5082,8 +5293,7 @@ int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
kvm_x86_ops->patch_hypercall(vcpu, instruction);
- return emulator_write_emulated(&vcpu->arch.emulate_ctxt,
- rip, instruction, 3, NULL);
+ return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
}
static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
@@ -5384,6 +5594,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
r = 1;
goto out;
}
+ if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
+ record_steal_time(vcpu);
+
}
r = kvm_mmu_reload(vcpu);
@@ -5671,8 +5884,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
* that usually, but some bad designed PV devices (vmware
* backdoor interface) need this to work
*/
- struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
- memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
+ memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
}
regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX);
@@ -5801,21 +6014,20 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
bool has_error_code, u32 error_code)
{
- struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
int ret;
init_emulate_ctxt(vcpu);
- ret = emulator_task_switch(&vcpu->arch.emulate_ctxt,
- tss_selector, reason, has_error_code,
- error_code);
+ ret = emulator_task_switch(ctxt, tss_selector, reason,
+ has_error_code, error_code);
if (ret)
return EMULATE_FAIL;
- memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
- kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
- kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+ memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
+ kvm_rip_write(vcpu, ctxt->eip);
+ kvm_set_rflags(vcpu, ctxt->eflags);
kvm_make_request(KVM_REQ_EVENT, vcpu);
return EMULATE_DONE;
}
@@ -6093,12 +6305,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
if (r == 0)
r = kvm_mmu_setup(vcpu);
vcpu_put(vcpu);
- if (r < 0)
- goto free_vcpu;
- return 0;
-free_vcpu:
- kvm_x86_ops->vcpu_free(vcpu);
return r;
}
@@ -6126,6 +6333,7 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
kvm_make_request(KVM_REQ_EVENT, vcpu);
vcpu->arch.apf.msr_val = 0;
+ vcpu->arch.st.msr_val = 0;
kvmclock_reset(vcpu);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index e407ed3df817..d36fe237c665 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -75,10 +75,54 @@ static inline u32 bit(int bitno)
return 1 << (bitno & 31);
}
+static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
+ gva_t gva, gfn_t gfn, unsigned access)
+{
+ vcpu->arch.mmio_gva = gva & PAGE_MASK;
+ vcpu->arch.access = access;
+ vcpu->arch.mmio_gfn = gfn;
+}
+
+/*
+ * Clear the mmio cache info for the given gva,
+ * specially, if gva is ~0ul, we clear all mmio cache info.
+ */
+static inline void vcpu_clear_mmio_info(struct kvm_vcpu *vcpu, gva_t gva)
+{
+ if (gva != (~0ul) && vcpu->arch.mmio_gva != (gva & PAGE_MASK))
+ return;
+
+ vcpu->arch.mmio_gva = 0;
+}
+
+static inline bool vcpu_match_mmio_gva(struct kvm_vcpu *vcpu, unsigned long gva)
+{
+ if (vcpu->arch.mmio_gva && vcpu->arch.mmio_gva == (gva & PAGE_MASK))
+ return true;
+
+ return false;
+}
+
+static inline bool vcpu_match_mmio_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+ if (vcpu->arch.mmio_gfn && vcpu->arch.mmio_gfn == gpa >> PAGE_SHIFT)
+ return true;
+
+ return false;
+}
+
void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data);
+int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
+ gva_t addr, void *val, unsigned int bytes,
+ struct x86_exception *exception);
+
+int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
+ gva_t addr, void *val, unsigned int bytes,
+ struct x86_exception *exception);
+
#endif
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index db832fd65ecb..13ee258442ae 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -71,7 +71,8 @@
#include <asm/stackprotector.h>
#include <asm/reboot.h> /* for struct machine_ops */
-/*G:010 Welcome to the Guest!
+/*G:010
+ * Welcome to the Guest!
*
* The Guest in our tale is a simple creature: identical to the Host but
* behaving in simplified but equivalent ways. In particular, the Guest is the
@@ -190,15 +191,23 @@ static void lazy_hcall4(unsigned long call,
#endif
/*G:036
- * When lazy mode is turned off reset the per-cpu lazy mode variable and then
- * issue the do-nothing hypercall to flush any stored calls.
-:*/
+ * When lazy mode is turned off, we issue the do-nothing hypercall to
+ * flush any stored calls, and call the generic helper to reset the
+ * per-cpu lazy mode variable.
+ */
static void lguest_leave_lazy_mmu_mode(void)
{
hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0);
paravirt_leave_lazy_mmu();
}
+/*
+ * We also catch the end of context switch; we enter lazy mode for much of
+ * that too, so again we need to flush here.
+ *
+ * (Technically, this is lazy CPU mode, and normally we're in lazy MMU
+ * mode, but unlike Xen, lguest doesn't care about the difference).
+ */
static void lguest_end_context_switch(struct task_struct *next)
{
hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0);
@@ -391,7 +400,7 @@ static void lguest_load_tr_desc(void)
* giant ball of hair. Its entry in the current Intel manual runs to 28 pages.
*
* This instruction even it has its own Wikipedia entry. The Wikipedia entry
- * has been translated into 5 languages. I am not making this up!
+ * has been translated into 6 languages. I am not making this up!
*
* We could get funky here and identify ourselves as "GenuineLguest", but
* instead we just use the real "cpuid" instruction. Then I pretty much turned
@@ -458,7 +467,7 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
/*
* PAE systems can mark pages as non-executable. Linux calls this the
* NX bit. Intel calls it XD (eXecute Disable), AMD EVP (Enhanced
- * Virus Protection). We just switch turn if off here, since we don't
+ * Virus Protection). We just switch it off here, since we don't
* support it.
*/
case 0x80000001:
@@ -520,17 +529,16 @@ static unsigned long lguest_read_cr2(void)
/* See lguest_set_pte() below. */
static bool cr3_changed = false;
+static unsigned long current_cr3;
/*
* cr3 is the current toplevel pagetable page: the principle is the same as
- * cr0. Keep a local copy, and tell the Host when it changes. The only
- * difference is that our local copy is in lguest_data because the Host needs
- * to set it upon our initial hypercall.
+ * cr0. Keep a local copy, and tell the Host when it changes.
*/
static void lguest_write_cr3(unsigned long cr3)
{
- lguest_data.pgdir = cr3;
lazy_hcall1(LHCALL_NEW_PGTABLE, cr3);
+ current_cr3 = cr3;
/* These two page tables are simple, linear, and used during boot */
if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table))
@@ -539,7 +547,7 @@ static void lguest_write_cr3(unsigned long cr3)
static unsigned long lguest_read_cr3(void)
{
- return lguest_data.pgdir;
+ return current_cr3;
}
/* cr4 is used to enable and disable PGE, but we don't care. */
@@ -641,7 +649,7 @@ static void lguest_write_cr4(unsigned long val)
/*
* The Guest calls this after it has set a second-level entry (pte), ie. to map
- * a page into a process' address space. Wetell the Host the toplevel and
+ * a page into a process' address space. We tell the Host the toplevel and
* address this corresponds to. The Guest uses one pagetable per process, so
* we need to tell the Host which one we're changing (mm->pgd).
*/
@@ -758,7 +766,7 @@ static void lguest_pmd_clear(pmd_t *pmdp)
static void lguest_flush_tlb_single(unsigned long addr)
{
/* Simply set it to zero: if it was not, it will fault back in. */
- lazy_hcall3(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0);
+ lazy_hcall3(LHCALL_SET_PTE, current_cr3, addr, 0);
}
/*
@@ -1140,7 +1148,7 @@ static struct notifier_block paniced = {
static __init char *lguest_memory_setup(void)
{
/*
- *The Linux bootloader header contains an "e820" memory map: the
+ * The Linux bootloader header contains an "e820" memory map: the
* Launcher populated the first entry with our memory limit.
*/
e820_add_region(boot_params.e820_map[0].addr,
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S
index 4f420c2f2d55..6ddfe4fc23c3 100644
--- a/arch/x86/lguest/i386_head.S
+++ b/arch/x86/lguest/i386_head.S
@@ -6,18 +6,22 @@
#include <asm/processor-flags.h>
/*G:020
- * Our story starts with the kernel booting into startup_32 in
- * arch/x86/kernel/head_32.S. It expects a boot header, which is created by
- * the bootloader (the Launcher in our case).
+
+ * Our story starts with the bzImage: booting starts at startup_32 in
+ * arch/x86/boot/compressed/head_32.S. This merely uncompresses the real
+ * kernel in place and then jumps into it: startup_32 in
+ * arch/x86/kernel/head_32.S. Both routines expects a boot header in the %esi
+ * register, which is created by the bootloader (the Launcher in our case).
*
* The startup_32 function does very little: it clears the uninitialized global
* C variables which we expect to be zero (ie. BSS) and then copies the boot
- * header and kernel command line somewhere safe. Finally it checks the
- * 'hardware_subarch' field. This was introduced in 2.6.24 for lguest and Xen:
- * if it's set to '1' (lguest's assigned number), then it calls us here.
+ * header and kernel command line somewhere safe, and populates some initial
+ * page tables. Finally it checks the 'hardware_subarch' field. This was
+ * introduced in 2.6.24 for lguest and Xen: if it's set to '1' (lguest's
+ * assigned number), then it calls us here.
*
* WARNING: be very careful here! We're running at addresses equal to physical
- * addesses (around 0), not above PAGE_OFFSET as most code expectes
+ * addresses (around 0), not above PAGE_OFFSET as most code expects
* (eg. 0xC0000000). Jumps are relative, so they're OK, but we can't touch any
* data without remembering to subtract __PAGE_OFFSET!
*
@@ -27,13 +31,18 @@
.section .init.text, "ax", @progbits
ENTRY(lguest_entry)
/*
- * We make the "initialization" hypercall now to tell the Host about
- * us, and also find out where it put our page tables.
+ * We make the "initialization" hypercall now to tell the Host where
+ * our lguest_data struct is.
*/
movl $LHCALL_LGUEST_INIT, %eax
movl $lguest_data - __PAGE_OFFSET, %ebx
int $LGUEST_TRAP_ENTRY
+ /* Now turn our pagetables on; setup by arch/x86/kernel/head_32.S. */
+ movl $LHCALL_NEW_PGTABLE, %eax
+ movl $(initial_page_table - __PAGE_OFFSET), %ebx
+ int $LGUEST_TRAP_ENTRY
+
/* Set up the initial stack so we can run C code. */
movl $(init_thread_union+THREAD_SIZE),%esp
@@ -96,12 +105,8 @@ send_interrupts:
*/
pushl %eax
movl $LHCALL_SEND_INTERRUPTS, %eax
- /*
- * This is a vmcall instruction (same thing that KVM uses). Older
- * assembler versions might not know the "vmcall" instruction, so we
- * create one manually here.
- */
- .byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */
+ /* This is the actual hypercall trap. */
+ int $LGUEST_TRAP_ENTRY
/* Put eax back the way we found it. */
popl %eax
ret
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index f2479f19ddde..b00f6785da74 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -18,8 +18,10 @@ obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o
lib-y := delay.o
lib-y += thunk_$(BITS).o
-lib-y += usercopy_$(BITS).o getuser.o putuser.o
+lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
lib-y += memcpy_$(BITS).o
+lib-$(CONFIG_SMP) += rwlock.o
+lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
obj-y += msr.o msr-reg.o msr-reg-export.o
@@ -29,7 +31,7 @@ ifeq ($(CONFIG_X86_32),y)
lib-y += atomic64_cx8_32.o
lib-y += checksum_32.o
lib-y += strstr_32.o
- lib-y += semaphore_32.o string_32.o
+ lib-y += string_32.o
lib-y += cmpxchg.o
ifneq ($(CONFIG_X86_CMPXCHG64),y)
lib-y += cmpxchg8b_emu.o atomic64_386_32.o
@@ -40,7 +42,6 @@ else
lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
lib-y += thunk_64.o clear_page_64.o copy_page_64.o
lib-y += memmove_64.o memset_64.o
- lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
- lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem_64.o
+ lib-y += copy_user_64.o copy_user_nocache_64.o
lib-y += cmpxchg16b_emu.o
endif
diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c
index 540179e8e9fa..042f6826bf57 100644
--- a/arch/x86/lib/atomic64_32.c
+++ b/arch/x86/lib/atomic64_32.c
@@ -4,7 +4,7 @@
#include <asm/processor.h>
#include <asm/cmpxchg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
long long atomic64_read_cx8(long long, const atomic64_t *v);
EXPORT_SYMBOL(atomic64_read_cx8);
diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S
index 6fec2d1cebe1..01c805ba5359 100644
--- a/arch/x86/lib/copy_page_64.S
+++ b/arch/x86/lib/copy_page_64.S
@@ -2,6 +2,7 @@
#include <linux/linkage.h>
#include <asm/dwarf2.h>
+#include <asm/alternative-asm.h>
ALIGN
copy_page_c:
@@ -110,10 +111,6 @@ ENDPROC(copy_page)
2:
.previous
.section .altinstructions,"a"
- .align 8
- .quad copy_page
- .quad 1b
- .word X86_FEATURE_REP_GOOD
- .byte .Lcopy_page_end - copy_page
- .byte 2b - 1b
+ altinstruction_entry copy_page, 1b, X86_FEATURE_REP_GOOD, \
+ .Lcopy_page_end-copy_page, 2b-1b
.previous
diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
index d0ec9c2936d7..ee164610ec46 100644
--- a/arch/x86/lib/memmove_64.S
+++ b/arch/x86/lib/memmove_64.S
@@ -9,6 +9,7 @@
#include <linux/linkage.h>
#include <asm/dwarf2.h>
#include <asm/cpufeature.h>
+#include <asm/alternative-asm.h>
#undef memmove
@@ -214,11 +215,9 @@ ENTRY(memmove)
.previous
.section .altinstructions,"a"
- .align 8
- .quad .Lmemmove_begin_forward
- .quad .Lmemmove_begin_forward_efs
- .word X86_FEATURE_ERMS
- .byte .Lmemmove_end_forward-.Lmemmove_begin_forward
- .byte .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
+ altinstruction_entry .Lmemmove_begin_forward, \
+ .Lmemmove_begin_forward_efs,X86_FEATURE_ERMS, \
+ .Lmemmove_end_forward-.Lmemmove_begin_forward, \
+ .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
.previous
ENDPROC(memmove)
diff --git a/arch/x86/lib/rwlock.S b/arch/x86/lib/rwlock.S
new file mode 100644
index 000000000000..1cad22139c88
--- /dev/null
+++ b/arch/x86/lib/rwlock.S
@@ -0,0 +1,44 @@
+/* Slow paths of read/write spinlocks. */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/rwlock.h>
+
+#ifdef CONFIG_X86_32
+# define __lock_ptr eax
+#else
+# define __lock_ptr rdi
+#endif
+
+ENTRY(__write_lock_failed)
+ CFI_STARTPROC
+ FRAME
+0: LOCK_PREFIX
+ WRITE_LOCK_ADD($RW_LOCK_BIAS) (%__lock_ptr)
+1: rep; nop
+ cmpl $WRITE_LOCK_CMP, (%__lock_ptr)
+ jne 1b
+ LOCK_PREFIX
+ WRITE_LOCK_SUB($RW_LOCK_BIAS) (%__lock_ptr)
+ jnz 0b
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+END(__write_lock_failed)
+
+ENTRY(__read_lock_failed)
+ CFI_STARTPROC
+ FRAME
+0: LOCK_PREFIX
+ READ_LOCK_SIZE(inc) (%__lock_ptr)
+1: rep; nop
+ READ_LOCK_SIZE(cmp) $1, (%__lock_ptr)
+ js 1b
+ LOCK_PREFIX
+ READ_LOCK_SIZE(dec) (%__lock_ptr)
+ js 0b
+ ENDFRAME
+ ret
+ CFI_ENDPROC
+END(__read_lock_failed)
diff --git a/arch/x86/lib/rwlock_64.S b/arch/x86/lib/rwlock_64.S
deleted file mode 100644
index 05ea55f71405..000000000000
--- a/arch/x86/lib/rwlock_64.S
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Slow paths of read/write spinlocks. */
-
-#include <linux/linkage.h>
-#include <asm/rwlock.h>
-#include <asm/alternative-asm.h>
-#include <asm/dwarf2.h>
-
-/* rdi: pointer to rwlock_t */
-ENTRY(__write_lock_failed)
- CFI_STARTPROC
- LOCK_PREFIX
- addl $RW_LOCK_BIAS,(%rdi)
-1: rep
- nop
- cmpl $RW_LOCK_BIAS,(%rdi)
- jne 1b
- LOCK_PREFIX
- subl $RW_LOCK_BIAS,(%rdi)
- jnz __write_lock_failed
- ret
- CFI_ENDPROC
-END(__write_lock_failed)
-
-/* rdi: pointer to rwlock_t */
-ENTRY(__read_lock_failed)
- CFI_STARTPROC
- LOCK_PREFIX
- incl (%rdi)
-1: rep
- nop
- cmpl $1,(%rdi)
- js 1b
- LOCK_PREFIX
- decl (%rdi)
- js __read_lock_failed
- ret
- CFI_ENDPROC
-END(__read_lock_failed)
diff --git a/arch/x86/lib/rwsem_64.S b/arch/x86/lib/rwsem.S
index 67743977398b..5dff5f042468 100644
--- a/arch/x86/lib/rwsem_64.S
+++ b/arch/x86/lib/rwsem.S
@@ -1,4 +1,51 @@
/*
+ * x86 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Portions Copyright 1999 Red Hat, 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.
+ *
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+#define __ASM_HALF_REG(reg) __ASM_SEL(reg, e##reg)
+#define __ASM_HALF_SIZE(inst) __ASM_SEL(inst##w, inst##l)
+
+#ifdef CONFIG_X86_32
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * %eax contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (%eax, %edx and %ecx) except %eax whish is either a return
+ * value or just clobbered..
+ */
+
+#define save_common_regs \
+ pushl_cfi %ecx; CFI_REL_OFFSET ecx, 0
+
+#define restore_common_regs \
+ popl_cfi %ecx; CFI_RESTORE ecx
+
+ /* Avoid uglifying the argument copying x86-64 needs to do. */
+ .macro movq src, dst
+ .endm
+
+#else
+
+/*
* x86-64 rwsem wrappers
*
* This interfaces the inline asm code to the slow-path
@@ -16,12 +63,6 @@
* but %rdi, %rsi, %rcx, %r8-r11 always need saving.
*/
-#include <linux/linkage.h>
-#include <asm/rwlock.h>
-#include <asm/alternative-asm.h>
-#include <asm/frame.h>
-#include <asm/dwarf2.h>
-
#define save_common_regs \
pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
@@ -40,16 +81,18 @@
popq_cfi %rsi; CFI_RESTORE rsi; \
popq_cfi %rdi; CFI_RESTORE rdi
+#endif
+
/* Fix up special calling conventions */
ENTRY(call_rwsem_down_read_failed)
CFI_STARTPROC
save_common_regs
- pushq_cfi %rdx
- CFI_REL_OFFSET rdx, 0
+ __ASM_SIZE(push,_cfi) %__ASM_REG(dx)
+ CFI_REL_OFFSET __ASM_REG(dx), 0
movq %rax,%rdi
call rwsem_down_read_failed
- popq_cfi %rdx
- CFI_RESTORE rdx
+ __ASM_SIZE(pop,_cfi) %__ASM_REG(dx)
+ CFI_RESTORE __ASM_REG(dx)
restore_common_regs
ret
CFI_ENDPROC
@@ -67,7 +110,8 @@ ENDPROC(call_rwsem_down_write_failed)
ENTRY(call_rwsem_wake)
CFI_STARTPROC
- decl %edx /* do nothing if still outstanding active readers */
+ /* do nothing if still outstanding active readers */
+ __ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx)
jnz 1f
save_common_regs
movq %rax,%rdi
@@ -77,16 +121,15 @@ ENTRY(call_rwsem_wake)
CFI_ENDPROC
ENDPROC(call_rwsem_wake)
-/* Fix up special calling conventions */
ENTRY(call_rwsem_downgrade_wake)
CFI_STARTPROC
save_common_regs
- pushq_cfi %rdx
- CFI_REL_OFFSET rdx, 0
+ __ASM_SIZE(push,_cfi) %__ASM_REG(dx)
+ CFI_REL_OFFSET __ASM_REG(dx), 0
movq %rax,%rdi
call rwsem_downgrade_wake
- popq_cfi %rdx
- CFI_RESTORE rdx
+ __ASM_SIZE(pop,_cfi) %__ASM_REG(dx)
+ CFI_RESTORE __ASM_REG(dx)
restore_common_regs
ret
CFI_ENDPROC
diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S
deleted file mode 100644
index 06691daa4108..000000000000
--- a/arch/x86/lib/semaphore_32.S
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * i386 semaphore implementation.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * Portions Copyright 1999 Red Hat, 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.
- *
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
- */
-
-#include <linux/linkage.h>
-#include <asm/rwlock.h>
-#include <asm/alternative-asm.h>
-#include <asm/frame.h>
-#include <asm/dwarf2.h>
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * %eax contains the semaphore pointer on entry. Save the C-clobbered
- * registers (%eax, %edx and %ecx) except %eax whish is either a return
- * value or just clobbered..
- */
- .section .sched.text, "ax"
-
-/*
- * rw spinlock fallbacks
- */
-#ifdef CONFIG_SMP
-ENTRY(__write_lock_failed)
- CFI_STARTPROC
- FRAME
-2: LOCK_PREFIX
- addl $ RW_LOCK_BIAS,(%eax)
-1: rep; nop
- cmpl $ RW_LOCK_BIAS,(%eax)
- jne 1b
- LOCK_PREFIX
- subl $ RW_LOCK_BIAS,(%eax)
- jnz 2b
- ENDFRAME
- ret
- CFI_ENDPROC
- ENDPROC(__write_lock_failed)
-
-ENTRY(__read_lock_failed)
- CFI_STARTPROC
- FRAME
-2: LOCK_PREFIX
- incl (%eax)
-1: rep; nop
- cmpl $1,(%eax)
- js 1b
- LOCK_PREFIX
- decl (%eax)
- js 2b
- ENDFRAME
- ret
- CFI_ENDPROC
- ENDPROC(__read_lock_failed)
-
-#endif
-
-#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
-
-/* Fix up special calling conventions */
-ENTRY(call_rwsem_down_read_failed)
- CFI_STARTPROC
- pushl_cfi %ecx
- CFI_REL_OFFSET ecx,0
- pushl_cfi %edx
- CFI_REL_OFFSET edx,0
- call rwsem_down_read_failed
- popl_cfi %edx
- popl_cfi %ecx
- ret
- CFI_ENDPROC
- ENDPROC(call_rwsem_down_read_failed)
-
-ENTRY(call_rwsem_down_write_failed)
- CFI_STARTPROC
- pushl_cfi %ecx
- CFI_REL_OFFSET ecx,0
- calll rwsem_down_write_failed
- popl_cfi %ecx
- ret
- CFI_ENDPROC
- ENDPROC(call_rwsem_down_write_failed)
-
-ENTRY(call_rwsem_wake)
- CFI_STARTPROC
- decw %dx /* do nothing if still outstanding active readers */
- jnz 1f
- pushl_cfi %ecx
- CFI_REL_OFFSET ecx,0
- call rwsem_wake
- popl_cfi %ecx
-1: ret
- CFI_ENDPROC
- ENDPROC(call_rwsem_wake)
-
-/* Fix up special calling conventions */
-ENTRY(call_rwsem_downgrade_wake)
- CFI_STARTPROC
- pushl_cfi %ecx
- CFI_REL_OFFSET ecx,0
- pushl_cfi %edx
- CFI_REL_OFFSET edx,0
- call rwsem_downgrade_wake
- popl_cfi %edx
- popl_cfi %ecx
- ret
- CFI_ENDPROC
- ENDPROC(call_rwsem_downgrade_wake)
-
-#endif
diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S
index 782b082c9ff7..a63efd6bb6a5 100644
--- a/arch/x86/lib/thunk_64.S
+++ b/arch/x86/lib/thunk_64.S
@@ -5,50 +5,41 @@
* Added trace_hardirqs callers - Copyright 2007 Steven Rostedt, Red Hat, Inc.
* Subject to the GNU public license, v.2. No warranty of any kind.
*/
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/calling.h>
- #include <linux/linkage.h>
- #include <asm/dwarf2.h>
- #include <asm/calling.h>
- #include <asm/rwlock.h>
-
- /* rdi: arg1 ... normal C conventions. rax is saved/restored. */
- .macro thunk name,func
- .globl \name
-\name:
- CFI_STARTPROC
- SAVE_ARGS
- call \func
- jmp restore
- CFI_ENDPROC
- .endm
-
-#ifdef CONFIG_TRACE_IRQFLAGS
- /* put return address in rdi (arg1) */
- .macro thunk_ra name,func
+ /* rdi: arg1 ... normal C conventions. rax is saved/restored. */
+ .macro THUNK name, func, put_ret_addr_in_rdi=0
.globl \name
\name:
CFI_STARTPROC
+
+ /* this one pushes 9 elems, the next one would be %rIP */
SAVE_ARGS
- /* SAVE_ARGS pushs 9 elements */
- /* the next element would be the rip */
- movq 9*8(%rsp), %rdi
+
+ .if \put_ret_addr_in_rdi
+ movq_cfi_restore 9*8, rdi
+ .endif
+
call \func
jmp restore
CFI_ENDPROC
.endm
- thunk_ra trace_hardirqs_on_thunk,trace_hardirqs_on_caller
- thunk_ra trace_hardirqs_off_thunk,trace_hardirqs_off_caller
+#ifdef CONFIG_TRACE_IRQFLAGS
+ THUNK trace_hardirqs_on_thunk,trace_hardirqs_on_caller,1
+ THUNK trace_hardirqs_off_thunk,trace_hardirqs_off_caller,1
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
- thunk lockdep_sys_exit_thunk,lockdep_sys_exit
+ THUNK lockdep_sys_exit_thunk,lockdep_sys_exit
#endif
-
+
/* SAVE_ARGS below is used only for the .cfi directives it contains. */
CFI_STARTPROC
SAVE_ARGS
restore:
RESTORE_ARGS
- ret
+ ret
CFI_ENDPROC
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
new file mode 100644
index 000000000000..97be9cb54483
--- /dev/null
+++ b/arch/x86/lib/usercopy.c
@@ -0,0 +1,43 @@
+/*
+ * User address space access functions.
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+/*
+ * best effort, GUP based copy_from_user() that is NMI-safe
+ */
+unsigned long
+copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
+{
+ unsigned long offset, addr = (unsigned long)from;
+ unsigned long size, len = 0;
+ struct page *page;
+ void *map;
+ int ret;
+
+ do {
+ ret = __get_user_pages_fast(addr, 1, 0, &page);
+ if (!ret)
+ break;
+
+ offset = addr & (PAGE_SIZE - 1);
+ size = min(PAGE_SIZE - offset, n - len);
+
+ map = kmap_atomic(page);
+ memcpy(to, map+offset, size);
+ kunmap_atomic(map);
+ put_page(page);
+
+ len += size;
+ to += size;
+ addr += size;
+
+ } while (len < n);
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(copy_from_user_nmi);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 2dbf6bf4c7e5..4d09df054e39 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1059,7 +1059,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
if (unlikely(error_code & PF_RSVD))
pgtable_bad(regs, error_code, address);
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
/*
* If we're in an interrupt, have no user context or are running
@@ -1161,11 +1161,11 @@ good_area:
if (flags & FAULT_FLAG_ALLOW_RETRY) {
if (fault & VM_FAULT_MAJOR) {
tsk->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
regs, address);
} else {
tsk->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
regs, address);
}
if (fault & VM_FAULT_RETRY) {
diff --git a/arch/x86/mm/kmemcheck/error.c b/arch/x86/mm/kmemcheck/error.c
index 704a37cedddb..dab41876cdd5 100644
--- a/arch/x86/mm/kmemcheck/error.c
+++ b/arch/x86/mm/kmemcheck/error.c
@@ -185,7 +185,7 @@ void kmemcheck_error_save(enum kmemcheck_shadow state,
e->trace.entries = e->trace_entries;
e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
e->trace.skip = 0;
- save_stack_trace_regs(&e->trace, regs);
+ save_stack_trace_regs(regs, &e->trace);
/* Round address down to nearest 16 bytes */
shadow_copy = kmemcheck_shadow_lookup(address
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c
index 3adff7dcc148..67421f38a215 100644
--- a/arch/x86/mm/mmio-mod.c
+++ b/arch/x86/mm/mmio-mod.c
@@ -34,7 +34,7 @@
#include <asm/pgtable.h>
#include <linux/mmiotrace.h>
#include <asm/e820.h> /* for ISA_START_ADDRESS */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/percpu.h>
#include <linux/cpu.h>
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index f5510d889a22..fbeaaf416610 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -496,6 +496,7 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
static int __init numa_register_memblks(struct numa_meminfo *mi)
{
+ unsigned long uninitialized_var(pfn_align);
int i, nid;
/* Account for nodes with cpus and no memory */
@@ -511,6 +512,20 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
/* for out of order entries */
sort_node_map();
+
+ /*
+ * If sections array is gonna be used for pfn -> nid mapping, check
+ * whether its granularity is fine enough.
+ */
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+ pfn_align = node_map_pfn_alignment();
+ if (pfn_align && pfn_align < PAGES_PER_SECTION) {
+ printk(KERN_WARNING "Node alignment %LuMB < min %LuMB, rejecting NUMA config\n",
+ PFN_PHYS(pfn_align) >> 20,
+ PFN_PHYS(PAGES_PER_SECTION) >> 20);
+ return -EINVAL;
+ }
+#endif
if (!numa_meminfo_cover_memory(mi))
return -EINVAL;
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 849a975d3fa0..3adebe7e536a 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -41,7 +41,7 @@
* physnode_map[16-31] = 1;
* physnode_map[32- ] = -1;
*/
-s8 physnode_map[MAX_ELEMENTS] __read_mostly = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+s8 physnode_map[MAX_SECTIONS] __read_mostly = { [0 ... (MAX_SECTIONS - 1)] = -1};
EXPORT_SYMBOL(physnode_map);
void memory_present(int nid, unsigned long start, unsigned long end)
@@ -52,8 +52,8 @@ void memory_present(int nid, unsigned long start, unsigned long end)
nid, start, end);
printk(KERN_DEBUG " Setting physnode_map array to node %d for pfns:\n", nid);
printk(KERN_DEBUG " ");
- for (pfn = start; pfn < end; pfn += PAGES_PER_ELEMENT) {
- physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
+ for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
+ physnode_map[pfn / PAGES_PER_SECTION] = nid;
printk(KERN_CONT "%lx ", pfn);
}
printk(KERN_CONT "\n");
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index e1d106909218..b0086567271c 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -123,12 +123,11 @@ static int pageattr_test(void)
if (print)
printk(KERN_INFO "CPA self-test:\n");
- bm = vmalloc((max_pfn_mapped + 7) / 8);
+ bm = vzalloc((max_pfn_mapped + 7) / 8);
if (!bm) {
printk(KERN_ERR "CPA Cannot vmalloc bitmap\n");
return -ENOMEM;
}
- memset(bm, 0, (max_pfn_mapped + 7) / 8);
failed += print_split(&sa);
srandom32(100);
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index a5b64ab4cd6e..bff89dfe3619 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -11,10 +11,11 @@
#include <linux/oprofile.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/compat.h>
+#include <linux/uaccess.h>
+
#include <asm/ptrace.h>
-#include <asm/uaccess.h>
#include <asm/stacktrace.h>
-#include <linux/compat.h>
static int backtrace_stack(void *data, char *name)
{
@@ -40,13 +41,13 @@ static struct stacktrace_ops backtrace_ops = {
static struct stack_frame_ia32 *
dump_user_backtrace_32(struct stack_frame_ia32 *head)
{
+ /* Also check accessibility of one struct frame_head beyond: */
struct stack_frame_ia32 bufhead[2];
struct stack_frame_ia32 *fp;
+ unsigned long bytes;
- /* Also check accessibility of one struct frame_head beyond */
- if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
- return NULL;
- if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+ bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
+ if (bytes != sizeof(bufhead))
return NULL;
fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);
@@ -87,12 +88,12 @@ x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
static struct stack_frame *dump_user_backtrace(struct stack_frame *head)
{
+ /* Also check accessibility of one struct frame_head beyond: */
struct stack_frame bufhead[2];
+ unsigned long bytes;
- /* Also check accessibility of one struct stack_frame beyond */
- if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
- return NULL;
- if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+ bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
+ if (bytes != sizeof(bufhead))
return NULL;
oprofile_add_trace(bufhead[0].return_address);
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 750c346ef50a..301e325992f6 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -519,7 +519,8 @@ static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
if (cfg->address < 0xFFFFFFFF)
return 0;
- if (!strcmp(mcfg->header.oem_id, "SGI"))
+ if (!strcmp(mcfg->header.oem_id, "SGI") ||
+ !strcmp(mcfg->header.oem_id, "SGI2"))
return 0;
if (mcfg->header.revision >= 1) {
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index f567965c0620..1017c7bee388 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -1,8 +1,13 @@
/*
- * Xen PCI Frontend Stub - puts some "dummy" functions in to the Linux
- * x86 PCI core to support the Xen PCI Frontend
+ * Xen PCI - handle PCI (INTx) and MSI infrastructure calls for PV, HVM and
+ * initial domain support. We also handle the DSDT _PRT callbacks for GSI's
+ * used in HVM and initial domain mode (PV does not parse ACPI, so it has no
+ * concept of GSIs). Under PV we hook under the pnbbios API for IRQs and
+ * 0xcf8 PCI configuration read/write.
*
* Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ * Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -19,22 +24,53 @@
#include <xen/events.h>
#include <asm/xen/pci.h>
+static int xen_pcifront_enable_irq(struct pci_dev *dev)
+{
+ int rc;
+ int share = 1;
+ int pirq;
+ u8 gsi;
+
+ rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
+ if (rc < 0) {
+ dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
+ rc);
+ return rc;
+ }
+ /* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
+ pirq = gsi;
+
+ if (gsi < NR_IRQS_LEGACY)
+ share = 0;
+
+ rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
+ if (rc < 0) {
+ dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
+ gsi, pirq, rc);
+ return rc;
+ }
+
+ dev->irq = rc;
+ dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
+ return 0;
+}
+
#ifdef CONFIG_ACPI
-static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
- int trigger, int polarity)
+static int xen_register_pirq(u32 gsi, int gsi_override, int triggering,
+ bool set_pirq)
{
- int rc, irq;
+ int rc, pirq = -1, irq = -1;
struct physdev_map_pirq map_irq;
int shareable = 0;
char *name;
- if (!xen_hvm_domain())
- return -1;
+ if (set_pirq)
+ pirq = gsi;
map_irq.domid = DOMID_SELF;
map_irq.type = MAP_PIRQ_TYPE_GSI;
map_irq.index = gsi;
- map_irq.pirq = -1;
+ map_irq.pirq = pirq;
rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
if (rc) {
@@ -42,7 +78,7 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
return -1;
}
- if (trigger == ACPI_EDGE_SENSITIVE) {
+ if (triggering == ACPI_EDGE_SENSITIVE) {
shareable = 0;
name = "ioapic-edge";
} else {
@@ -50,12 +86,63 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
name = "ioapic-level";
}
+ if (gsi_override >= 0)
+ gsi = gsi_override;
+
irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name);
+ if (irq < 0)
+ goto out;
+
+ printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", map_irq.pirq, irq, gsi);
+out:
+ return irq;
+}
+
+static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
+ int trigger, int polarity)
+{
+ if (!xen_hvm_domain())
+ return -1;
- printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
+ return xen_register_pirq(gsi, -1 /* no GSI override */, trigger,
+ false /* no mapping of GSI to PIRQ */);
+}
+
+#ifdef CONFIG_XEN_DOM0
+static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
+{
+ int rc, irq;
+ struct physdev_setup_gsi setup_gsi;
+
+ if (!xen_pv_domain())
+ return -1;
+
+ printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
+ gsi, triggering, polarity);
+
+ irq = xen_register_pirq(gsi, gsi_override, triggering, true);
+
+ setup_gsi.gsi = gsi;
+ setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
+ setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+
+ rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi);
+ if (rc == -EEXIST)
+ printk(KERN_INFO "Already setup the GSI :%d\n", gsi);
+ else if (rc) {
+ printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n",
+ gsi, rc);
+ }
return irq;
}
+
+static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
+ int trigger, int polarity)
+{
+ return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
+}
+#endif
#endif
#if defined(CONFIG_PCI_MSI)
@@ -65,6 +152,43 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
struct xen_pci_frontend_ops *xen_pci_frontend;
EXPORT_SYMBOL_GPL(xen_pci_frontend);
+static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+ int irq, ret, i;
+ struct msi_desc *msidesc;
+ int *v;
+
+ v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
+ if (!v)
+ return -ENOMEM;
+
+ if (type == PCI_CAP_ID_MSIX)
+ ret = xen_pci_frontend_enable_msix(dev, v, nvec);
+ else
+ ret = xen_pci_frontend_enable_msi(dev, v);
+ if (ret)
+ goto error;
+ i = 0;
+ list_for_each_entry(msidesc, &dev->msi_list, list) {
+ irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
+ (type == PCI_CAP_ID_MSIX) ?
+ "pcifront-msi-x" :
+ "pcifront-msi",
+ DOMID_SELF);
+ if (irq < 0)
+ goto free;
+ i++;
+ }
+ kfree(v);
+ return 0;
+
+error:
+ dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
+free:
+ kfree(v);
+ return ret;
+}
+
#define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \
MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0))
@@ -123,67 +247,6 @@ error:
return -ENODEV;
}
-/*
- * For MSI interrupts we have to use drivers/xen/event.s functions to
- * allocate an irq_desc and setup the right */
-
-
-static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
- int irq, ret, i;
- struct msi_desc *msidesc;
- int *v;
-
- v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
- if (!v)
- return -ENOMEM;
-
- if (type == PCI_CAP_ID_MSIX)
- ret = xen_pci_frontend_enable_msix(dev, v, nvec);
- else
- ret = xen_pci_frontend_enable_msi(dev, v);
- if (ret)
- goto error;
- i = 0;
- list_for_each_entry(msidesc, &dev->msi_list, list) {
- irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
- (type == PCI_CAP_ID_MSIX) ?
- "pcifront-msi-x" :
- "pcifront-msi",
- DOMID_SELF);
- if (irq < 0)
- goto free;
- i++;
- }
- kfree(v);
- return 0;
-
-error:
- dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
-free:
- kfree(v);
- return ret;
-}
-
-static void xen_teardown_msi_irqs(struct pci_dev *dev)
-{
- struct msi_desc *msidesc;
-
- msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
- if (msidesc->msi_attrib.is_msix)
- xen_pci_frontend_disable_msix(dev);
- else
- xen_pci_frontend_disable_msi(dev);
-
- /* Free the IRQ's and the msidesc using the generic code. */
- default_teardown_msi_irqs(dev);
-}
-
-static void xen_teardown_msi_irq(unsigned int irq)
-{
- xen_destroy_irq(irq);
-}
-
#ifdef CONFIG_XEN_DOM0
static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
@@ -242,45 +305,28 @@ out:
return ret;
}
#endif
-#endif
-static int xen_pcifront_enable_irq(struct pci_dev *dev)
+static void xen_teardown_msi_irqs(struct pci_dev *dev)
{
- int rc;
- int share = 1;
- int pirq;
- u8 gsi;
-
- rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
- if (rc < 0) {
- dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
- rc);
- return rc;
- }
-
- rc = xen_allocate_pirq_gsi(gsi);
- if (rc < 0) {
- dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n",
- gsi, rc);
- return rc;
- }
- pirq = rc;
+ struct msi_desc *msidesc;
- if (gsi < NR_IRQS_LEGACY)
- share = 0;
+ msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
+ if (msidesc->msi_attrib.is_msix)
+ xen_pci_frontend_disable_msix(dev);
+ else
+ xen_pci_frontend_disable_msi(dev);
- rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
- if (rc < 0) {
- dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
- gsi, pirq, rc);
- return rc;
- }
+ /* Free the IRQ's and the msidesc using the generic code. */
+ default_teardown_msi_irqs(dev);
+}
- dev->irq = rc;
- dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
- return 0;
+static void xen_teardown_msi_irq(unsigned int irq)
+{
+ xen_destroy_irq(irq);
}
+#endif
+
int __init pci_xen_init(void)
{
if (!xen_pv_domain() || xen_initial_domain())
@@ -327,79 +373,6 @@ int __init pci_xen_hvm_init(void)
}
#ifdef CONFIG_XEN_DOM0
-static int xen_register_pirq(u32 gsi, int gsi_override, int triggering)
-{
- int rc, pirq, irq = -1;
- struct physdev_map_pirq map_irq;
- int shareable = 0;
- char *name;
-
- if (!xen_pv_domain())
- return -1;
-
- if (triggering == ACPI_EDGE_SENSITIVE) {
- shareable = 0;
- name = "ioapic-edge";
- } else {
- shareable = 1;
- name = "ioapic-level";
- }
- pirq = xen_allocate_pirq_gsi(gsi);
- if (pirq < 0)
- goto out;
-
- if (gsi_override >= 0)
- irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name);
- else
- irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
- if (irq < 0)
- goto out;
-
- printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
-
- map_irq.domid = DOMID_SELF;
- map_irq.type = MAP_PIRQ_TYPE_GSI;
- map_irq.index = gsi;
- map_irq.pirq = pirq;
-
- rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
- if (rc) {
- printk(KERN_WARNING "xen map irq failed %d\n", rc);
- return -1;
- }
-
-out:
- return irq;
-}
-
-static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
-{
- int rc, irq;
- struct physdev_setup_gsi setup_gsi;
-
- if (!xen_pv_domain())
- return -1;
-
- printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
- gsi, triggering, polarity);
-
- irq = xen_register_pirq(gsi, gsi_override, triggering);
-
- setup_gsi.gsi = gsi;
- setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
- setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-
- rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi);
- if (rc == -EEXIST)
- printk(KERN_INFO "Already setup the GSI :%d\n", gsi);
- else if (rc) {
- printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n",
- gsi, rc);
- }
-
- return irq;
-}
-
static __init void xen_setup_acpi_sci(void)
{
int rc;
@@ -419,7 +392,7 @@ static __init void xen_setup_acpi_sci(void)
}
trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
-
+
printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
"polarity=%d\n", gsi, trigger, polarity);
@@ -434,10 +407,9 @@ static __init void xen_setup_acpi_sci(void)
* the ACPI interpreter and keels over since IRQ 9 has not been
* setup as we had setup IRQ 20 for it).
*/
- /* Check whether the GSI != IRQ */
if (acpi_gsi_to_irq(gsi, &irq) == 0) {
- if (irq >= 0 && irq != gsi)
- /* Bugger, we MUST have that IRQ. */
+ /* Use the provided value if it's valid. */
+ if (irq >= 0)
gsi_override = irq;
}
@@ -447,41 +419,16 @@ static __init void xen_setup_acpi_sci(void)
return;
}
-static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
- int trigger, int polarity)
+int __init pci_xen_initial_domain(void)
{
- return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
-}
+ int irq;
-static int __init pci_xen_initial_domain(void)
-{
#ifdef CONFIG_PCI_MSI
x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
#endif
xen_setup_acpi_sci();
__acpi_register_gsi = acpi_register_gsi_xen;
-
- return 0;
-}
-
-void __init xen_setup_pirqs(void)
-{
- int pirq, irq;
-
- pci_xen_initial_domain();
-
- if (0 == nr_ioapics) {
- for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
- pirq = xen_allocate_pirq_gsi(irq);
- if (WARN(pirq < 0,
- "Could not allocate PIRQ for legacy interrupt\n"))
- break;
- irq = xen_bind_pirq_gsi_to_irq(irq, pirq, 0, "xt-pic");
- }
- return;
- }
-
/* Pre-allocate legacy irqs */
for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
int trigger, polarity;
@@ -490,12 +437,16 @@ void __init xen_setup_pirqs(void)
continue;
xen_register_pirq(irq, -1 /* no GSI override */,
- trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE);
+ trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE,
+ true /* Map GSI to PIRQ */);
}
+ if (0 == nr_ioapics) {
+ for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
+ xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
+ }
+ return 0;
}
-#endif
-#ifdef CONFIG_XEN_DOM0
struct xen_device_domain_owner {
domid_t domain;
struct pci_dev *dev;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 899e393d8e73..3ae4128013e6 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -51,7 +51,17 @@
int efi_enabled;
EXPORT_SYMBOL(efi_enabled);
-struct efi efi;
+struct efi __read_mostly efi = {
+ .mps = EFI_INVALID_TABLE_ADDR,
+ .acpi = EFI_INVALID_TABLE_ADDR,
+ .acpi20 = EFI_INVALID_TABLE_ADDR,
+ .smbios = EFI_INVALID_TABLE_ADDR,
+ .sal_systab = EFI_INVALID_TABLE_ADDR,
+ .boot_info = EFI_INVALID_TABLE_ADDR,
+ .hcdp = EFI_INVALID_TABLE_ADDR,
+ .uga = EFI_INVALID_TABLE_ADDR,
+ .uv_systab = EFI_INVALID_TABLE_ADDR,
+};
EXPORT_SYMBOL(efi);
struct efi_memory_map memmap;
@@ -79,26 +89,50 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
{
- return efi_call_virt2(get_time, tm, tc);
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt2(get_time, tm, tc);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
}
static efi_status_t virt_efi_set_time(efi_time_t *tm)
{
- return efi_call_virt1(set_time, tm);
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt1(set_time, tm);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
}
static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
efi_bool_t *pending,
efi_time_t *tm)
{
- return efi_call_virt3(get_wakeup_time,
- enabled, pending, tm);
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt3(get_wakeup_time,
+ enabled, pending, tm);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
}
static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
{
- return efi_call_virt2(set_wakeup_time,
- enabled, tm);
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt2(set_wakeup_time,
+ enabled, tm);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
}
static efi_status_t virt_efi_get_variable(efi_char16_t *name,
@@ -122,7 +156,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
static efi_status_t virt_efi_set_variable(efi_char16_t *name,
efi_guid_t *vendor,
- unsigned long attr,
+ u32 attr,
unsigned long data_size,
void *data)
{
@@ -131,6 +165,18 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
data_size, data);
}
+static efi_status_t virt_efi_query_variable_info(u32 attr,
+ u64 *storage_space,
+ u64 *remaining_space,
+ u64 *max_variable_size)
+{
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ return efi_call_virt4(query_variable_info, attr, storage_space,
+ remaining_space, max_variable_size);
+}
+
static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
{
return efi_call_virt1(get_next_high_mono_count, count);
@@ -145,6 +191,28 @@ static void virt_efi_reset_system(int reset_type,
data_size, data);
}
+static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
+ unsigned long count,
+ unsigned long sg_list)
+{
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ return efi_call_virt3(update_capsule, capsules, count, sg_list);
+}
+
+static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
+ unsigned long count,
+ u64 *max_size,
+ int *reset_type)
+{
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ return efi_call_virt4(query_capsule_caps, capsules, count, max_size,
+ reset_type);
+}
+
static efi_status_t __init phys_efi_set_virtual_address_map(
unsigned long memory_map_size,
unsigned long descriptor_size,
@@ -164,11 +232,14 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
efi_time_cap_t *tc)
{
+ unsigned long flags;
efi_status_t status;
+ spin_lock_irqsave(&rtc_lock, flags);
efi_call_phys_prelog();
status = efi_call_phys2(efi_phys.get_time, tm, tc);
efi_call_phys_epilog();
+ spin_unlock_irqrestore(&rtc_lock, flags);
return status;
}
@@ -669,6 +740,9 @@ void __init efi_enter_virtual_mode(void)
efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
efi.reset_system = virt_efi_reset_system;
efi.set_virtual_address_map = NULL;
+ efi.query_variable_info = virt_efi_query_variable_info;
+ efi.update_capsule = virt_efi_update_capsule;
+ efi.query_capsule_caps = virt_efi_query_capsule_caps;
if (__supported_pte_mask & _PAGE_NX)
runtime_code_page_mkexec();
early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile
index 81c5e2165c24..fd332c533947 100644
--- a/arch/x86/platform/olpc/Makefile
+++ b/arch/x86/platform/olpc/Makefile
@@ -1,2 +1,5 @@
obj-$(CONFIG_OLPC) += olpc.o olpc_ofw.o olpc_dt.o
-obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o
+obj-$(CONFIG_OLPC_XO1_PM) += olpc-xo1-pm.o xo1-wakeup.o
+obj-$(CONFIG_OLPC_XO1_RTC) += olpc-xo1-rtc.o
+obj-$(CONFIG_OLPC_XO1_SCI) += olpc-xo1-sci.o
+obj-$(CONFIG_OLPC_XO15_SCI) += olpc-xo15-sci.o
diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
new file mode 100644
index 000000000000..6f3855a5a2f7
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -0,0 +1,215 @@
+/*
+ * Support for power management features of the OLPC XO-1 laptop
+ *
+ * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, 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.
+ */
+
+#include <linux/cs5535.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/mfd/core.h>
+#include <linux/suspend.h>
+
+#include <asm/io.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo1-pm"
+
+static unsigned long acpi_base;
+static unsigned long pms_base;
+
+static u16 wakeup_mask = CS5536_PM_PWRBTN;
+
+static struct {
+ unsigned long address;
+ unsigned short segment;
+} ofw_bios_entry = { 0xF0000 + PAGE_OFFSET, __KERNEL_CS };
+
+/* Set bits in the wakeup mask */
+void olpc_xo1_pm_wakeup_set(u16 value)
+{
+ wakeup_mask |= value;
+}
+EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_set);
+
+/* Clear bits in the wakeup mask */
+void olpc_xo1_pm_wakeup_clear(u16 value)
+{
+ wakeup_mask &= ~value;
+}
+EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear);
+
+static int xo1_power_state_enter(suspend_state_t pm_state)
+{
+ unsigned long saved_sci_mask;
+ int r;
+
+ /* Only STR is supported */
+ if (pm_state != PM_SUSPEND_MEM)
+ return -EINVAL;
+
+ r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
+ if (r)
+ return r;
+
+ /*
+ * Save SCI mask (this gets lost since PM1_EN is used as a mask for
+ * wakeup events, which is not necessarily the same event set)
+ */
+ saved_sci_mask = inl(acpi_base + CS5536_PM1_STS);
+ saved_sci_mask &= 0xffff0000;
+
+ /* Save CPU state */
+ do_olpc_suspend_lowlevel();
+
+ /* Resume path starts here */
+
+ /* Restore SCI mask (using dword access to CS5536_PM1_EN) */
+ outl(saved_sci_mask, acpi_base + CS5536_PM1_STS);
+
+ /* Tell the EC to stop inhibiting SCIs */
+ olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
+
+ /*
+ * Tell the wireless module to restart USB communication.
+ * Must be done twice.
+ */
+ olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+ olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+
+ return 0;
+}
+
+asmlinkage int xo1_do_sleep(u8 sleep_state)
+{
+ void *pgd_addr = __va(read_cr3());
+
+ /* Program wakeup mask (using dword access to CS5536_PM1_EN) */
+ outl(wakeup_mask << 16, acpi_base + CS5536_PM1_STS);
+
+ __asm__("movl %0,%%eax" : : "r" (pgd_addr));
+ __asm__("call *(%%edi); cld"
+ : : "D" (&ofw_bios_entry));
+ __asm__("movb $0x34, %al\n\t"
+ "outb %al, $0x70\n\t"
+ "movb $0x30, %al\n\t"
+ "outb %al, $0x71\n\t");
+ return 0;
+}
+
+static void xo1_power_off(void)
+{
+ printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
+
+ /* Enable all of these controls with 0 delay */
+ outl(0x40000000, pms_base + CS5536_PM_SCLK);
+ outl(0x40000000, pms_base + CS5536_PM_IN_SLPCTL);
+ outl(0x40000000, pms_base + CS5536_PM_WKXD);
+ outl(0x40000000, pms_base + CS5536_PM_WKD);
+
+ /* Clear status bits (possibly unnecessary) */
+ outl(0x0002ffff, pms_base + CS5536_PM_SSC);
+ outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+
+ /* Write SLP_EN bit to start the machinery */
+ outl(0x00002000, acpi_base + CS5536_PM1_CNT);
+}
+
+static int xo1_power_state_valid(suspend_state_t pm_state)
+{
+ /* suspend-to-RAM only */
+ return pm_state == PM_SUSPEND_MEM;
+}
+
+static const struct platform_suspend_ops xo1_suspend_ops = {
+ .valid = xo1_power_state_valid,
+ .enter = xo1_power_state_enter,
+};
+
+static int __devinit xo1_pm_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int err;
+
+ /* don't run on non-XOs */
+ if (!machine_is_olpc())
+ return -ENODEV;
+
+ err = mfd_cell_enable(pdev);
+ if (err)
+ return err;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ return -EIO;
+ }
+ if (strcmp(pdev->name, "cs5535-pms") == 0)
+ pms_base = res->start;
+ else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
+ acpi_base = res->start;
+
+ /* If we have both addresses, we can override the poweroff hook */
+ if (pms_base && acpi_base) {
+ suspend_set_ops(&xo1_suspend_ops);
+ pm_power_off = xo1_power_off;
+ printk(KERN_INFO "OLPC XO-1 support registered\n");
+ }
+
+ return 0;
+}
+
+static int __devexit xo1_pm_remove(struct platform_device *pdev)
+{
+ mfd_cell_disable(pdev);
+
+ if (strcmp(pdev->name, "cs5535-pms") == 0)
+ pms_base = 0;
+ else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
+ acpi_base = 0;
+
+ pm_power_off = NULL;
+ return 0;
+}
+
+static struct platform_driver cs5535_pms_driver = {
+ .driver = {
+ .name = "cs5535-pms",
+ .owner = THIS_MODULE,
+ },
+ .probe = xo1_pm_probe,
+ .remove = __devexit_p(xo1_pm_remove),
+};
+
+static struct platform_driver cs5535_acpi_driver = {
+ .driver = {
+ .name = "olpc-xo1-pm-acpi",
+ .owner = THIS_MODULE,
+ },
+ .probe = xo1_pm_probe,
+ .remove = __devexit_p(xo1_pm_remove),
+};
+
+static int __init xo1_pm_init(void)
+{
+ int r;
+
+ r = platform_driver_register(&cs5535_pms_driver);
+ if (r)
+ return r;
+
+ r = platform_driver_register(&cs5535_acpi_driver);
+ if (r)
+ platform_driver_unregister(&cs5535_pms_driver);
+
+ return r;
+}
+arch_initcall(xo1_pm_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-rtc.c b/arch/x86/platform/olpc/olpc-xo1-rtc.c
new file mode 100644
index 000000000000..a2b4efddd61a
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-rtc.c
@@ -0,0 +1,81 @@
+/*
+ * Support for OLPC XO-1 Real Time Clock (RTC)
+ *
+ * Copyright (C) 2011 One Laptop per Child
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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/mc146818rtc.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/of.h>
+
+#include <asm/msr.h>
+#include <asm/olpc.h>
+
+static void rtc_wake_on(struct device *dev)
+{
+ olpc_xo1_pm_wakeup_set(CS5536_PM_RTC);
+}
+
+static void rtc_wake_off(struct device *dev)
+{
+ olpc_xo1_pm_wakeup_clear(CS5536_PM_RTC);
+}
+
+static struct resource rtc_platform_resource[] = {
+ [0] = {
+ .start = RTC_PORT(0),
+ .end = RTC_PORT(1),
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct cmos_rtc_board_info rtc_info = {
+ .rtc_day_alarm = 0,
+ .rtc_mon_alarm = 0,
+ .rtc_century = 0,
+ .wake_on = rtc_wake_on,
+ .wake_off = rtc_wake_off,
+};
+
+static struct platform_device xo1_rtc_device = {
+ .name = "rtc_cmos",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_platform_resource),
+ .dev.platform_data = &rtc_info,
+ .resource = rtc_platform_resource,
+};
+
+static int __init xo1_rtc_init(void)
+{
+ int r;
+ struct device_node *node;
+
+ node = of_find_compatible_node(NULL, NULL, "olpc,xo1-rtc");
+ if (!node)
+ return 0;
+ of_node_put(node);
+
+ pr_info("olpc-xo1-rtc: Initializing OLPC XO-1 RTC\n");
+ rdmsrl(MSR_RTC_DOMA_OFFSET, rtc_info.rtc_day_alarm);
+ rdmsrl(MSR_RTC_MONA_OFFSET, rtc_info.rtc_mon_alarm);
+ rdmsrl(MSR_RTC_CEN_OFFSET, rtc_info.rtc_century);
+
+ r = platform_device_register(&xo1_rtc_device);
+ if (r)
+ return r;
+
+ device_init_wakeup(&xo1_rtc_device.dev, 1);
+ return 0;
+}
+arch_initcall(xo1_rtc_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
new file mode 100644
index 000000000000..1d4c783d7325
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -0,0 +1,614 @@
+/*
+ * Support for OLPC XO-1 System Control Interrupts (SCI)
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, 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.
+ */
+
+#include <linux/cs5535.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/mfd/core.h>
+#include <linux/power_supply.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo1-sci"
+#define PFX DRV_NAME ": "
+
+static unsigned long acpi_base;
+static struct input_dev *power_button_idev;
+static struct input_dev *ebook_switch_idev;
+static struct input_dev *lid_switch_idev;
+
+static int sci_irq;
+
+static bool lid_open;
+static bool lid_inverted;
+static int lid_wake_mode;
+
+enum lid_wake_modes {
+ LID_WAKE_ALWAYS,
+ LID_WAKE_OPEN,
+ LID_WAKE_CLOSE,
+};
+
+static const char * const lid_wake_mode_names[] = {
+ [LID_WAKE_ALWAYS] = "always",
+ [LID_WAKE_OPEN] = "open",
+ [LID_WAKE_CLOSE] = "close",
+};
+
+static void battery_status_changed(void)
+{
+ struct power_supply *psy = power_supply_get_by_name("olpc-battery");
+
+ if (psy) {
+ power_supply_changed(psy);
+ put_device(psy->dev);
+ }
+}
+
+static void ac_status_changed(void)
+{
+ struct power_supply *psy = power_supply_get_by_name("olpc-ac");
+
+ if (psy) {
+ power_supply_changed(psy);
+ put_device(psy->dev);
+ }
+}
+
+/* Report current ebook switch state through input layer */
+static void send_ebook_state(void)
+{
+ unsigned char state;
+
+ if (olpc_ec_cmd(EC_READ_EB_MODE, NULL, 0, &state, 1)) {
+ pr_err(PFX "failed to get ebook state\n");
+ return;
+ }
+
+ input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state);
+ input_sync(ebook_switch_idev);
+}
+
+static void flip_lid_inverter(void)
+{
+ /* gpio is high; invert so we'll get l->h event interrupt */
+ if (lid_inverted)
+ cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+ else
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+ lid_inverted = !lid_inverted;
+}
+
+static void detect_lid_state(void)
+{
+ /*
+ * the edge detector hookup on the gpio inputs on the geode is
+ * odd, to say the least. See http://dev.laptop.org/ticket/5703
+ * for details, but in a nutshell: we don't use the edge
+ * detectors. instead, we make use of an anomoly: with the both
+ * edge detectors turned off, we still get an edge event on a
+ * positive edge transition. to take advantage of this, we use the
+ * front-end inverter to ensure that that's the edge we're always
+ * going to see next.
+ */
+
+ int state;
+
+ state = cs5535_gpio_isset(OLPC_GPIO_LID, GPIO_READ_BACK);
+ lid_open = !state ^ !lid_inverted; /* x ^^ y */
+ if (!state)
+ return;
+
+ flip_lid_inverter();
+}
+
+/* Report current lid switch state through input layer */
+static void send_lid_state(void)
+{
+ input_report_switch(lid_switch_idev, SW_LID, !lid_open);
+ input_sync(lid_switch_idev);
+}
+
+static ssize_t lid_wake_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const char *mode = lid_wake_mode_names[lid_wake_mode];
+ return sprintf(buf, "%s\n", mode);
+}
+static ssize_t lid_wake_mode_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(lid_wake_mode_names); i++) {
+ const char *mode = lid_wake_mode_names[i];
+ if (strlen(mode) != count || strncasecmp(mode, buf, count))
+ continue;
+
+ lid_wake_mode = i;
+ return count;
+ }
+ return -EINVAL;
+}
+static DEVICE_ATTR(lid_wake_mode, S_IWUSR | S_IRUGO, lid_wake_mode_show,
+ lid_wake_mode_set);
+
+/*
+ * Process all items in the EC's SCI queue.
+ *
+ * This is handled in a workqueue because olpc_ec_cmd can be slow (and
+ * can even timeout).
+ *
+ * If propagate_events is false, the queue is drained without events being
+ * generated for the interrupts.
+ */
+static void process_sci_queue(bool propagate_events)
+{
+ int r;
+ u16 data;
+
+ do {
+ r = olpc_ec_sci_query(&data);
+ if (r || !data)
+ break;
+
+ pr_debug(PFX "SCI 0x%x received\n", data);
+
+ switch (data) {
+ case EC_SCI_SRC_BATERR:
+ case EC_SCI_SRC_BATSOC:
+ case EC_SCI_SRC_BATTERY:
+ case EC_SCI_SRC_BATCRIT:
+ battery_status_changed();
+ break;
+ case EC_SCI_SRC_ACPWR:
+ ac_status_changed();
+ break;
+ }
+
+ if (data == EC_SCI_SRC_EBOOK && propagate_events)
+ send_ebook_state();
+ } while (data);
+
+ if (r)
+ pr_err(PFX "Failed to clear SCI queue");
+}
+
+static void process_sci_queue_work(struct work_struct *work)
+{
+ process_sci_queue(true);
+}
+
+static DECLARE_WORK(sci_work, process_sci_queue_work);
+
+static irqreturn_t xo1_sci_intr(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ u32 sts;
+ u32 gpe;
+
+ sts = inl(acpi_base + CS5536_PM1_STS);
+ outl(sts | 0xffff, acpi_base + CS5536_PM1_STS);
+
+ gpe = inl(acpi_base + CS5536_PM_GPE0_STS);
+ outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+
+ dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe);
+
+ if (sts & CS5536_PWRBTN_FLAG && !(sts & CS5536_WAK_FLAG)) {
+ input_report_key(power_button_idev, KEY_POWER, 1);
+ input_sync(power_button_idev);
+ input_report_key(power_button_idev, KEY_POWER, 0);
+ input_sync(power_button_idev);
+ }
+
+ if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */
+ cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
+ schedule_work(&sci_work);
+ }
+
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+ detect_lid_state();
+ send_lid_state();
+
+ return IRQ_HANDLED;
+}
+
+static int xo1_sci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ if (device_may_wakeup(&power_button_idev->dev))
+ olpc_xo1_pm_wakeup_set(CS5536_PM_PWRBTN);
+ else
+ olpc_xo1_pm_wakeup_clear(CS5536_PM_PWRBTN);
+
+ if (device_may_wakeup(&ebook_switch_idev->dev))
+ olpc_ec_wakeup_set(EC_SCI_SRC_EBOOK);
+ else
+ olpc_ec_wakeup_clear(EC_SCI_SRC_EBOOK);
+
+ if (!device_may_wakeup(&lid_switch_idev->dev)) {
+ cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+ } else if ((lid_open && lid_wake_mode == LID_WAKE_OPEN) ||
+ (!lid_open && lid_wake_mode == LID_WAKE_CLOSE)) {
+ flip_lid_inverter();
+
+ /* we may have just caused an event */
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+ }
+
+ return 0;
+}
+
+static int xo1_sci_resume(struct platform_device *pdev)
+{
+ /*
+ * We don't know what may have happened while we were asleep.
+ * Reestablish our lid setup so we're sure to catch all transitions.
+ */
+ detect_lid_state();
+ send_lid_state();
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+
+ /* Enable all EC events */
+ olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+ /* Power/battery status might have changed too */
+ battery_status_changed();
+ ac_status_changed();
+ return 0;
+}
+
+static int __devinit setup_sci_interrupt(struct platform_device *pdev)
+{
+ u32 lo, hi;
+ u32 sts;
+ int r;
+
+ rdmsr(0x51400020, lo, hi);
+ sci_irq = (lo >> 20) & 15;
+
+ if (sci_irq) {
+ dev_info(&pdev->dev, "SCI is mapped to IRQ %d\n", sci_irq);
+ } else {
+ /* Zero means masked */
+ dev_info(&pdev->dev, "SCI unmapped. Mapping to IRQ 3\n");
+ sci_irq = 3;
+ lo |= 0x00300000;
+ wrmsrl(0x51400020, lo);
+ }
+
+ /* Select level triggered in PIC */
+ if (sci_irq < 8) {
+ lo = inb(CS5536_PIC_INT_SEL1);
+ lo |= 1 << sci_irq;
+ outb(lo, CS5536_PIC_INT_SEL1);
+ } else {
+ lo = inb(CS5536_PIC_INT_SEL2);
+ lo |= 1 << (sci_irq - 8);
+ outb(lo, CS5536_PIC_INT_SEL2);
+ }
+
+ /* Enable SCI from power button, and clear pending interrupts */
+ sts = inl(acpi_base + CS5536_PM1_STS);
+ outl((CS5536_PM_PWRBTN << 16) | 0xffff, acpi_base + CS5536_PM1_STS);
+
+ r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev);
+ if (r)
+ dev_err(&pdev->dev, "can't request interrupt\n");
+
+ return r;
+}
+
+static int __devinit setup_ec_sci(void)
+{
+ int r;
+
+ r = gpio_request(OLPC_GPIO_ECSCI, "OLPC-ECSCI");
+ if (r)
+ return r;
+
+ gpio_direction_input(OLPC_GPIO_ECSCI);
+
+ /* Clear pending EC SCI events */
+ cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
+ cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_POSITIVE_EDGE_STS);
+
+ /*
+ * Enable EC SCI events, and map them to both a PME and the SCI
+ * interrupt.
+ *
+ * Ordinarily, in addition to functioning as GPIOs, Geode GPIOs can
+ * be mapped to regular interrupts *or* Geode-specific Power
+ * Management Events (PMEs) - events that bring the system out of
+ * suspend. In this case, we want both of those things - the system
+ * wakeup, *and* the ability to get an interrupt when an event occurs.
+ *
+ * To achieve this, we map the GPIO to a PME, and then we use one
+ * of the many generic knobs on the CS5535 PIC to additionally map the
+ * PME to the regular SCI interrupt line.
+ */
+ cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_EVENTS_ENABLE);
+
+ /* Set the SCI to cause a PME event on group 7 */
+ cs5535_gpio_setup_event(OLPC_GPIO_ECSCI, 7, 1);
+
+ /* And have group 7 also fire the SCI interrupt */
+ cs5535_pic_unreqz_select_high(7, sci_irq);
+
+ return 0;
+}
+
+static void free_ec_sci(void)
+{
+ gpio_free(OLPC_GPIO_ECSCI);
+}
+
+static int __devinit setup_lid_events(void)
+{
+ int r;
+
+ r = gpio_request(OLPC_GPIO_LID, "OLPC-LID");
+ if (r)
+ return r;
+
+ gpio_direction_input(OLPC_GPIO_LID);
+
+ cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+ lid_inverted = 0;
+
+ /* Clear edge detection and event enable for now */
+ cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+ cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN);
+ cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN);
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+
+ /* Set the LID to cause an PME event on group 6 */
+ cs5535_gpio_setup_event(OLPC_GPIO_LID, 6, 1);
+
+ /* Set PME group 6 to fire the SCI interrupt */
+ cs5535_gpio_set_irq(6, sci_irq);
+
+ /* Enable the event */
+ cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+
+ return 0;
+}
+
+static void free_lid_events(void)
+{
+ gpio_free(OLPC_GPIO_LID);
+}
+
+static int __devinit setup_power_button(struct platform_device *pdev)
+{
+ int r;
+
+ power_button_idev = input_allocate_device();
+ if (!power_button_idev)
+ return -ENOMEM;
+
+ power_button_idev->name = "Power Button";
+ power_button_idev->phys = DRV_NAME "/input0";
+ set_bit(EV_KEY, power_button_idev->evbit);
+ set_bit(KEY_POWER, power_button_idev->keybit);
+
+ power_button_idev->dev.parent = &pdev->dev;
+ device_init_wakeup(&power_button_idev->dev, 1);
+
+ r = input_register_device(power_button_idev);
+ if (r) {
+ dev_err(&pdev->dev, "failed to register power button: %d\n", r);
+ input_free_device(power_button_idev);
+ }
+
+ return r;
+}
+
+static void free_power_button(void)
+{
+ input_unregister_device(power_button_idev);
+ input_free_device(power_button_idev);
+}
+
+static int __devinit setup_ebook_switch(struct platform_device *pdev)
+{
+ int r;
+
+ ebook_switch_idev = input_allocate_device();
+ if (!ebook_switch_idev)
+ return -ENOMEM;
+
+ ebook_switch_idev->name = "EBook Switch";
+ ebook_switch_idev->phys = DRV_NAME "/input1";
+ set_bit(EV_SW, ebook_switch_idev->evbit);
+ set_bit(SW_TABLET_MODE, ebook_switch_idev->swbit);
+
+ ebook_switch_idev->dev.parent = &pdev->dev;
+ device_set_wakeup_capable(&ebook_switch_idev->dev, true);
+
+ r = input_register_device(ebook_switch_idev);
+ if (r) {
+ dev_err(&pdev->dev, "failed to register ebook switch: %d\n", r);
+ input_free_device(ebook_switch_idev);
+ }
+
+ return r;
+}
+
+static void free_ebook_switch(void)
+{
+ input_unregister_device(ebook_switch_idev);
+ input_free_device(ebook_switch_idev);
+}
+
+static int __devinit setup_lid_switch(struct platform_device *pdev)
+{
+ int r;
+
+ lid_switch_idev = input_allocate_device();
+ if (!lid_switch_idev)
+ return -ENOMEM;
+
+ lid_switch_idev->name = "Lid Switch";
+ lid_switch_idev->phys = DRV_NAME "/input2";
+ set_bit(EV_SW, lid_switch_idev->evbit);
+ set_bit(SW_LID, lid_switch_idev->swbit);
+
+ lid_switch_idev->dev.parent = &pdev->dev;
+ device_set_wakeup_capable(&lid_switch_idev->dev, true);
+
+ r = input_register_device(lid_switch_idev);
+ if (r) {
+ dev_err(&pdev->dev, "failed to register lid switch: %d\n", r);
+ goto err_register;
+ }
+
+ r = device_create_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
+ if (r) {
+ dev_err(&pdev->dev, "failed to create wake mode attr: %d\n", r);
+ goto err_create_attr;
+ }
+
+ return 0;
+
+err_create_attr:
+ input_unregister_device(lid_switch_idev);
+err_register:
+ input_free_device(lid_switch_idev);
+ return r;
+}
+
+static void free_lid_switch(void)
+{
+ device_remove_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
+ input_unregister_device(lid_switch_idev);
+ input_free_device(lid_switch_idev);
+}
+
+static int __devinit xo1_sci_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int r;
+
+ /* don't run on non-XOs */
+ if (!machine_is_olpc())
+ return -ENODEV;
+
+ r = mfd_cell_enable(pdev);
+ if (r)
+ return r;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ return -EIO;
+ }
+ acpi_base = res->start;
+
+ r = setup_power_button(pdev);
+ if (r)
+ return r;
+
+ r = setup_ebook_switch(pdev);
+ if (r)
+ goto err_ebook;
+
+ r = setup_lid_switch(pdev);
+ if (r)
+ goto err_lid;
+
+ r = setup_lid_events();
+ if (r)
+ goto err_lidevt;
+
+ r = setup_ec_sci();
+ if (r)
+ goto err_ecsci;
+
+ /* Enable PME generation for EC-generated events */
+ outl(CS5536_GPIOM6_PME_EN | CS5536_GPIOM7_PME_EN,
+ acpi_base + CS5536_PM_GPE0_EN);
+
+ /* Clear pending events */
+ outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+ process_sci_queue(false);
+
+ /* Initial sync */
+ send_ebook_state();
+ detect_lid_state();
+ send_lid_state();
+
+ r = setup_sci_interrupt(pdev);
+ if (r)
+ goto err_sci;
+
+ /* Enable all EC events */
+ olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+ return r;
+
+err_sci:
+ free_ec_sci();
+err_ecsci:
+ free_lid_events();
+err_lidevt:
+ free_lid_switch();
+err_lid:
+ free_ebook_switch();
+err_ebook:
+ free_power_button();
+ return r;
+}
+
+static int __devexit xo1_sci_remove(struct platform_device *pdev)
+{
+ mfd_cell_disable(pdev);
+ free_irq(sci_irq, pdev);
+ cancel_work_sync(&sci_work);
+ free_ec_sci();
+ free_lid_events();
+ free_lid_switch();
+ free_ebook_switch();
+ free_power_button();
+ acpi_base = 0;
+ return 0;
+}
+
+static struct platform_driver xo1_sci_driver = {
+ .driver = {
+ .name = "olpc-xo1-sci-acpi",
+ },
+ .probe = xo1_sci_probe,
+ .remove = __devexit_p(xo1_sci_remove),
+ .suspend = xo1_sci_suspend,
+ .resume = xo1_sci_resume,
+};
+
+static int __init xo1_sci_init(void)
+{
+ return platform_driver_register(&xo1_sci_driver);
+}
+arch_initcall(xo1_sci_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1.c b/arch/x86/platform/olpc/olpc-xo1.c
deleted file mode 100644
index ab81fb271760..000000000000
--- a/arch/x86/platform/olpc/olpc-xo1.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Support for features of the OLPC XO-1 laptop
- *
- * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
- * Copyright (C) 2010 One Laptop per Child
- * Copyright (C) 2006 Red Hat, Inc.
- * Copyright (C) 2006 Advanced Micro Devices, 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.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/mfd/core.h>
-
-#include <asm/io.h>
-#include <asm/olpc.h>
-
-#define DRV_NAME "olpc-xo1"
-
-/* PMC registers (PMS block) */
-#define PM_SCLK 0x10
-#define PM_IN_SLPCTL 0x20
-#define PM_WKXD 0x34
-#define PM_WKD 0x30
-#define PM_SSC 0x54
-
-/* PM registers (ACPI block) */
-#define PM1_CNT 0x08
-#define PM_GPE0_STS 0x18
-
-static unsigned long acpi_base;
-static unsigned long pms_base;
-
-static void xo1_power_off(void)
-{
- printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
-
- /* Enable all of these controls with 0 delay */
- outl(0x40000000, pms_base + PM_SCLK);
- outl(0x40000000, pms_base + PM_IN_SLPCTL);
- outl(0x40000000, pms_base + PM_WKXD);
- outl(0x40000000, pms_base + PM_WKD);
-
- /* Clear status bits (possibly unnecessary) */
- outl(0x0002ffff, pms_base + PM_SSC);
- outl(0xffffffff, acpi_base + PM_GPE0_STS);
-
- /* Write SLP_EN bit to start the machinery */
- outl(0x00002000, acpi_base + PM1_CNT);
-}
-
-static int __devinit olpc_xo1_probe(struct platform_device *pdev)
-{
- struct resource *res;
- int err;
-
- /* don't run on non-XOs */
- if (!machine_is_olpc())
- return -ENODEV;
-
- err = mfd_cell_enable(pdev);
- if (err)
- return err;
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!res) {
- dev_err(&pdev->dev, "can't fetch device resource info\n");
- return -EIO;
- }
- if (strcmp(pdev->name, "cs5535-pms") == 0)
- pms_base = res->start;
- else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
- acpi_base = res->start;
-
- /* If we have both addresses, we can override the poweroff hook */
- if (pms_base && acpi_base) {
- pm_power_off = xo1_power_off;
- printk(KERN_INFO "OLPC XO-1 support registered\n");
- }
-
- return 0;
-}
-
-static int __devexit olpc_xo1_remove(struct platform_device *pdev)
-{
- mfd_cell_disable(pdev);
-
- if (strcmp(pdev->name, "cs5535-pms") == 0)
- pms_base = 0;
- else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
- acpi_base = 0;
-
- pm_power_off = NULL;
- return 0;
-}
-
-static struct platform_driver cs5535_pms_drv = {
- .driver = {
- .name = "cs5535-pms",
- .owner = THIS_MODULE,
- },
- .probe = olpc_xo1_probe,
- .remove = __devexit_p(olpc_xo1_remove),
-};
-
-static struct platform_driver cs5535_acpi_drv = {
- .driver = {
- .name = "olpc-xo1-pm-acpi",
- .owner = THIS_MODULE,
- },
- .probe = olpc_xo1_probe,
- .remove = __devexit_p(olpc_xo1_remove),
-};
-
-static int __init olpc_xo1_init(void)
-{
- int r;
-
- r = platform_driver_register(&cs5535_pms_drv);
- if (r)
- return r;
-
- r = platform_driver_register(&cs5535_acpi_drv);
- if (r)
- platform_driver_unregister(&cs5535_pms_drv);
-
- return r;
-}
-
-static void __exit olpc_xo1_exit(void)
-{
- platform_driver_unregister(&cs5535_acpi_drv);
- platform_driver_unregister(&cs5535_pms_drv);
-}
-
-MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cs5535-pms");
-
-module_init(olpc_xo1_init);
-module_exit(olpc_xo1_exit);
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
new file mode 100644
index 000000000000..2b235b77d9ab
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -0,0 +1,168 @@
+/*
+ * Support for OLPC XO-1.5 System Control Interrupts (SCI)
+ *
+ * Copyright (C) 2009-2010 One Laptop per Child
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/power_supply.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo15-sci"
+#define PFX DRV_NAME ": "
+#define XO15_SCI_CLASS DRV_NAME
+#define XO15_SCI_DEVICE_NAME "OLPC XO-1.5 SCI"
+
+static unsigned long xo15_sci_gpe;
+
+static void battery_status_changed(void)
+{
+ struct power_supply *psy = power_supply_get_by_name("olpc-battery");
+
+ if (psy) {
+ power_supply_changed(psy);
+ put_device(psy->dev);
+ }
+}
+
+static void ac_status_changed(void)
+{
+ struct power_supply *psy = power_supply_get_by_name("olpc-ac");
+
+ if (psy) {
+ power_supply_changed(psy);
+ put_device(psy->dev);
+ }
+}
+
+static void process_sci_queue(void)
+{
+ u16 data;
+ int r;
+
+ do {
+ r = olpc_ec_sci_query(&data);
+ if (r || !data)
+ break;
+
+ pr_debug(PFX "SCI 0x%x received\n", data);
+
+ switch (data) {
+ case EC_SCI_SRC_BATERR:
+ case EC_SCI_SRC_BATSOC:
+ case EC_SCI_SRC_BATTERY:
+ case EC_SCI_SRC_BATCRIT:
+ battery_status_changed();
+ break;
+ case EC_SCI_SRC_ACPWR:
+ ac_status_changed();
+ break;
+ }
+ } while (data);
+
+ if (r)
+ pr_err(PFX "Failed to clear SCI queue");
+}
+
+static void process_sci_queue_work(struct work_struct *work)
+{
+ process_sci_queue();
+}
+
+static DECLARE_WORK(sci_work, process_sci_queue_work);
+
+static u32 xo15_sci_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
+{
+ schedule_work(&sci_work);
+ return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+static int xo15_sci_add(struct acpi_device *device)
+{
+ unsigned long long tmp;
+ acpi_status status;
+
+ if (!device)
+ return -EINVAL;
+
+ strcpy(acpi_device_name(device), XO15_SCI_DEVICE_NAME);
+ strcpy(acpi_device_class(device), XO15_SCI_CLASS);
+
+ /* Get GPE bit assignment (EC events). */
+ status = acpi_evaluate_integer(device->handle, "_GPE", NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+
+ xo15_sci_gpe = tmp;
+ status = acpi_install_gpe_handler(NULL, xo15_sci_gpe,
+ ACPI_GPE_EDGE_TRIGGERED,
+ xo15_sci_gpe_handler, device);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ dev_info(&device->dev, "Initialized, GPE = 0x%lx\n", xo15_sci_gpe);
+
+ /* Flush queue, and enable all SCI events */
+ process_sci_queue();
+ olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+ acpi_enable_gpe(NULL, xo15_sci_gpe);
+
+ /* Enable wake-on-EC */
+ if (device->wakeup.flags.valid)
+ device_init_wakeup(&device->dev, true);
+
+ return 0;
+}
+
+static int xo15_sci_remove(struct acpi_device *device, int type)
+{
+ acpi_disable_gpe(NULL, xo15_sci_gpe);
+ acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
+ cancel_work_sync(&sci_work);
+ return 0;
+}
+
+static int xo15_sci_resume(struct acpi_device *device)
+{
+ /* Enable all EC events */
+ olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+ /* Power/battery status might have changed */
+ battery_status_changed();
+ ac_status_changed();
+
+ return 0;
+}
+
+static const struct acpi_device_id xo15_sci_device_ids[] = {
+ {"XO15EC", 0},
+ {"", 0},
+};
+
+static struct acpi_driver xo15_sci_drv = {
+ .name = DRV_NAME,
+ .class = XO15_SCI_CLASS,
+ .ids = xo15_sci_device_ids,
+ .ops = {
+ .add = xo15_sci_add,
+ .remove = xo15_sci_remove,
+ .resume = xo15_sci_resume,
+ },
+};
+
+static int __init xo15_sci_init(void)
+{
+ return acpi_bus_register_driver(&xo15_sci_drv);
+}
+device_initcall(xo15_sci_init);
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index 0060fd59ea00..8b9940e78e2f 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/syscore_ops.h>
#include <asm/geode.h>
#include <asm/setup.h>
@@ -30,6 +31,9 @@ EXPORT_SYMBOL_GPL(olpc_platform_info);
static DEFINE_SPINLOCK(ec_lock);
+/* EC event mask to be applied during suspend (defining wakeup sources). */
+static u16 ec_wakeup_mask;
+
/* what the timeout *should* be (in ms) */
#define EC_BASE_TIMEOUT 20
@@ -188,6 +192,88 @@ err:
}
EXPORT_SYMBOL_GPL(olpc_ec_cmd);
+void olpc_ec_wakeup_set(u16 value)
+{
+ ec_wakeup_mask |= value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set);
+
+void olpc_ec_wakeup_clear(u16 value)
+{
+ ec_wakeup_mask &= ~value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear);
+
+/*
+ * Returns true if the compile and runtime configurations allow for EC events
+ * to wake the system.
+ */
+bool olpc_ec_wakeup_available(void)
+{
+ if (!machine_is_olpc())
+ return false;
+
+ /*
+ * XO-1 EC wakeups are available when olpc-xo1-sci driver is
+ * compiled in
+ */
+#ifdef CONFIG_OLPC_XO1_SCI
+ if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */
+ return true;
+#endif
+
+ /*
+ * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is
+ * compiled in
+ */
+#ifdef CONFIG_OLPC_XO15_SCI
+ if (olpc_platform_info.boardrev >= olpc_board_pre(0xd0)) /* XO-1.5 */
+ return true;
+#endif
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available);
+
+int olpc_ec_mask_write(u16 bits)
+{
+ if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
+ __be16 ec_word = cpu_to_be16(bits);
+ return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2,
+ NULL, 0);
+ } else {
+ unsigned char ec_byte = bits & 0xff;
+ return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0);
+ }
+}
+EXPORT_SYMBOL_GPL(olpc_ec_mask_write);
+
+int olpc_ec_sci_query(u16 *sci_value)
+{
+ int ret;
+
+ if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
+ __be16 ec_word;
+ ret = olpc_ec_cmd(EC_EXT_SCI_QUERY,
+ NULL, 0, (void *) &ec_word, 2);
+ if (ret == 0)
+ *sci_value = be16_to_cpu(ec_word);
+ } else {
+ unsigned char ec_byte;
+ ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1);
+ if (ret == 0)
+ *sci_value = ec_byte;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
+
+static int olpc_ec_suspend(void)
+{
+ return olpc_ec_mask_write(ec_wakeup_mask);
+}
+
static bool __init check_ofw_architecture(struct device_node *root)
{
const char *olpc_arch;
@@ -242,6 +328,10 @@ static int __init add_xo1_platform_devices(void)
return 0;
}
+static struct syscore_ops olpc_syscore_ops = {
+ .suspend = olpc_ec_suspend,
+};
+
static int __init olpc_init(void)
{
int r = 0;
@@ -266,6 +356,9 @@ static int __init olpc_init(void)
!cs5535_has_vsa2())
x86_init.pci.arch_init = pci_olpc_init;
#endif
+ /* EC version 0x5f adds support for wide SCI mask */
+ if (olpc_platform_info.ecver >= 0x5f)
+ olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
@@ -278,6 +371,8 @@ static int __init olpc_init(void)
return r;
}
+ register_syscore_ops(&olpc_syscore_ops);
+
return 0;
}
diff --git a/arch/x86/platform/olpc/olpc_dt.c b/arch/x86/platform/olpc/olpc_dt.c
index d39f63d017d2..d6ee92986920 100644
--- a/arch/x86/platform/olpc/olpc_dt.c
+++ b/arch/x86/platform/olpc/olpc_dt.c
@@ -165,6 +165,107 @@ static struct of_pdt_ops prom_olpc_ops __initdata = {
.pkg2path = olpc_dt_pkg2path,
};
+static phandle __init olpc_dt_finddevice(const char *path)
+{
+ phandle node;
+ const void *args[] = { path };
+ void *res[] = { &node };
+
+ if (olpc_ofw("finddevice", args, res)) {
+ pr_err("olpc_dt: finddevice failed!\n");
+ return 0;
+ }
+
+ if ((s32) node == -1)
+ return 0;
+
+ return node;
+}
+
+static int __init olpc_dt_interpret(const char *words)
+{
+ int result;
+ const void *args[] = { words };
+ void *res[] = { &result };
+
+ if (olpc_ofw("interpret", args, res)) {
+ pr_err("olpc_dt: interpret failed!\n");
+ return -1;
+ }
+
+ return result;
+}
+
+/*
+ * Extract board revision directly from OFW device tree.
+ * We can't use olpc_platform_info because that hasn't been set up yet.
+ */
+static u32 __init olpc_dt_get_board_revision(void)
+{
+ phandle node;
+ __be32 rev;
+ int r;
+
+ node = olpc_dt_finddevice("/");
+ if (!node)
+ return 0;
+
+ r = olpc_dt_getproperty(node, "board-revision-int",
+ (char *) &rev, sizeof(rev));
+ if (r < 0)
+ return 0;
+
+ return be32_to_cpu(rev);
+}
+
+void __init olpc_dt_fixup(void)
+{
+ int r;
+ char buf[64];
+ phandle node;
+ u32 board_rev;
+
+ node = olpc_dt_finddevice("/battery@0");
+ if (!node)
+ return;
+
+ /*
+ * If the battery node has a compatible property, we are running a new
+ * enough firmware and don't have fixups to make.
+ */
+ r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
+ if (r > 0)
+ return;
+
+ pr_info("PROM DT: Old firmware detected, applying fixes\n");
+
+ /* Add olpc,xo1-battery compatible marker to battery node */
+ olpc_dt_interpret("\" /battery@0\" find-device"
+ " \" olpc,xo1-battery\" +compatible"
+ " device-end");
+
+ board_rev = olpc_dt_get_board_revision();
+ if (!board_rev)
+ return;
+
+ if (board_rev >= olpc_board_pre(0xd0)) {
+ /* XO-1.5: add dcon device */
+ olpc_dt_interpret("\" /pci/display@1\" find-device"
+ " new-device"
+ " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
+ " finish-device device-end");
+ } else {
+ /* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */
+ olpc_dt_interpret("\" /pci/display@1,1\" find-device"
+ " new-device"
+ " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
+ " finish-device device-end"
+ " \" /rtc\" find-device"
+ " \" olpc,xo1-rtc\" +compatible"
+ " device-end");
+ }
+}
+
void __init olpc_dt_build_devicetree(void)
{
phandle root;
@@ -172,6 +273,8 @@ void __init olpc_dt_build_devicetree(void)
if (!olpc_ofw_is_installed())
return;
+ olpc_dt_fixup();
+
root = olpc_dt_getsibling(0);
if (!root) {
pr_err("PROM: unable to get root node from OFW!\n");
diff --git a/arch/x86/platform/olpc/xo1-wakeup.S b/arch/x86/platform/olpc/xo1-wakeup.S
new file mode 100644
index 000000000000..948deb289753
--- /dev/null
+++ b/arch/x86/platform/olpc/xo1-wakeup.S
@@ -0,0 +1,124 @@
+.text
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable_32.h>
+
+ .macro writepost,value
+ movb $0x34, %al
+ outb %al, $0x70
+ movb $\value, %al
+ outb %al, $0x71
+ .endm
+
+wakeup_start:
+ # OFW lands us here, running in protected mode, with a
+ # kernel-compatible GDT already setup.
+
+ # Clear any dangerous flags
+ pushl $0
+ popfl
+
+ writepost 0x31
+
+ # Set up %cr3
+ movl $initial_page_table - __PAGE_OFFSET, %eax
+ movl %eax, %cr3
+
+ movl saved_cr4, %eax
+ movl %eax, %cr4
+
+ movl saved_cr0, %eax
+ movl %eax, %cr0
+
+ # Control registers were modified, pipeline resync is needed
+ jmp 1f
+1:
+
+ movw $__KERNEL_DS, %ax
+ movw %ax, %ss
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ lgdt saved_gdt
+ lidt saved_idt
+ lldt saved_ldt
+ ljmp $(__KERNEL_CS),$1f
+1:
+ movl %cr3, %eax
+ movl %eax, %cr3
+ wbinvd
+
+ # Go back to the return point
+ jmp ret_point
+
+save_registers:
+ sgdt saved_gdt
+ sidt saved_idt
+ sldt saved_ldt
+
+ pushl %edx
+ movl %cr4, %edx
+ movl %edx, saved_cr4
+
+ movl %cr0, %edx
+ movl %edx, saved_cr0
+
+ popl %edx
+
+ movl %ebx, saved_context_ebx
+ movl %ebp, saved_context_ebp
+ movl %esi, saved_context_esi
+ movl %edi, saved_context_edi
+
+ pushfl
+ popl saved_context_eflags
+
+ ret
+
+restore_registers:
+ movl saved_context_ebp, %ebp
+ movl saved_context_ebx, %ebx
+ movl saved_context_esi, %esi
+ movl saved_context_edi, %edi
+
+ pushl saved_context_eflags
+ popfl
+
+ ret
+
+ENTRY(do_olpc_suspend_lowlevel)
+ call save_processor_state
+ call save_registers
+
+ # This is the stack context we want to remember
+ movl %esp, saved_context_esp
+
+ pushl $3
+ call xo1_do_sleep
+
+ jmp wakeup_start
+ .p2align 4,,7
+ret_point:
+ movl saved_context_esp, %esp
+
+ writepost 0x32
+
+ call restore_registers
+ call restore_processor_state
+ ret
+
+.data
+saved_gdt: .long 0,0
+saved_idt: .long 0,0
+saved_ldt: .long 0
+saved_cr4: .long 0
+saved_cr0: .long 0
+saved_context_esp: .long 0
+saved_context_edi: .long 0
+saved_context_esi: .long 0
+saved_context_ebx: .long 0
+saved_context_ebp: .long 0
+saved_context_eflags: .long 0
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 68e467f69fec..db8b915f54bc 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -296,14 +296,18 @@ static void bau_process_message(struct msg_desc *mdp,
}
/*
- * Determine the first cpu on a uvhub.
+ * Determine the first cpu on a pnode.
*/
-static int uvhub_to_first_cpu(int uvhub)
+static int pnode_to_first_cpu(int pnode, struct bau_control *smaster)
{
int cpu;
- for_each_present_cpu(cpu)
- if (uvhub == uv_cpu_to_blade_id(cpu))
+ struct hub_and_pnode *hpp;
+
+ for_each_present_cpu(cpu) {
+ hpp = &smaster->thp[cpu];
+ if (pnode == hpp->pnode)
return cpu;
+ }
return -1;
}
@@ -366,28 +370,32 @@ static void do_reset(void *ptr)
* Use IPI to get all target uvhubs to release resources held by
* a given sending cpu number.
*/
-static void reset_with_ipi(struct bau_targ_hubmask *distribution, int sender)
+static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
{
- int uvhub;
+ int pnode;
+ int apnode;
int maskbits;
- cpumask_t mask;
+ int sender = bcp->cpu;
+ cpumask_t *mask = bcp->uvhub_master->cpumask;
+ struct bau_control *smaster = bcp->socket_master;
struct reset_args reset_args;
reset_args.sender = sender;
- cpus_clear(mask);
+ cpus_clear(*mask);
/* find a single cpu for each uvhub in this distribution mask */
- maskbits = sizeof(struct bau_targ_hubmask) * BITSPERBYTE;
- for (uvhub = 0; uvhub < maskbits; uvhub++) {
+ maskbits = sizeof(struct pnmask) * BITSPERBYTE;
+ /* each bit is a pnode relative to the partition base pnode */
+ for (pnode = 0; pnode < maskbits; pnode++) {
int cpu;
- if (!bau_uvhub_isset(uvhub, distribution))
+ if (!bau_uvhub_isset(pnode, distribution))
continue;
- /* find a cpu for this uvhub */
- cpu = uvhub_to_first_cpu(uvhub);
- cpu_set(cpu, mask);
+ apnode = pnode + bcp->partition_base_pnode;
+ cpu = pnode_to_first_cpu(apnode, smaster);
+ cpu_set(cpu, *mask);
}
/* IPI all cpus; preemption is already disabled */
- smp_call_function_many(&mask, do_reset, (void *)&reset_args, 1);
+ smp_call_function_many(mask, do_reset, (void *)&reset_args, 1);
return;
}
@@ -604,7 +612,7 @@ static void destination_plugged(struct bau_desc *bau_desc,
quiesce_local_uvhub(hmaster);
spin_lock(&hmaster->queue_lock);
- reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+ reset_with_ipi(&bau_desc->distribution, bcp);
spin_unlock(&hmaster->queue_lock);
end_uvhub_quiesce(hmaster);
@@ -626,7 +634,7 @@ static void destination_timeout(struct bau_desc *bau_desc,
quiesce_local_uvhub(hmaster);
spin_lock(&hmaster->queue_lock);
- reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+ reset_with_ipi(&bau_desc->distribution, bcp);
spin_unlock(&hmaster->queue_lock);
end_uvhub_quiesce(hmaster);
@@ -1334,9 +1342,10 @@ static ssize_t tunables_write(struct file *file, const char __user *user,
instr[count] = '\0';
- bcp = &per_cpu(bau_control, smp_processor_id());
-
+ cpu = get_cpu();
+ bcp = &per_cpu(bau_control, cpu);
ret = parse_tunables_write(bcp, instr, count);
+ put_cpu();
if (ret)
return ret;
@@ -1687,6 +1696,16 @@ static void make_per_cpu_thp(struct bau_control *smaster)
}
/*
+ * Each uvhub is to get a local cpumask.
+ */
+static void make_per_hub_cpumask(struct bau_control *hmaster)
+{
+ int sz = sizeof(cpumask_t);
+
+ hmaster->cpumask = kzalloc_node(sz, GFP_KERNEL, hmaster->osnode);
+}
+
+/*
* Initialize all the per_cpu information for the cpu's on a given socket,
* given what has been gathered into the socket_desc struct.
* And reports the chosen hub and socket masters back to the caller.
@@ -1751,11 +1770,12 @@ static int __init summarize_uvhub_sockets(int nuvhubs,
sdp = &bdp->socket[socket];
if (scan_sock(sdp, bdp, &smaster, &hmaster))
return 1;
+ make_per_cpu_thp(smaster);
}
socket++;
socket_mask = (socket_mask >> 1);
- make_per_cpu_thp(smaster);
}
+ make_per_hub_cpumask(hmaster);
}
return 0;
}
@@ -1777,15 +1797,20 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode)
uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL);
if (get_cpu_topology(base_part_pnode, uvhub_descs, uvhub_mask))
- return 1;
+ goto fail;
if (summarize_uvhub_sockets(nuvhubs, uvhub_descs, uvhub_mask))
- return 1;
+ goto fail;
kfree(uvhub_descs);
kfree(uvhub_mask);
init_per_cpu_tunables();
return 0;
+
+fail:
+ kfree(uvhub_descs);
+ kfree(uvhub_mask);
+ return 1;
}
/*
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index bef0bc962400..5d179502a52c 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -26,6 +26,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
export CPPFLAGS_vdso.lds += -P -C
VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
+ -Wl,--no-undefined \
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index a724905fdae7..6bc0e723b6e8 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -6,7 +6,6 @@
*
* The code should have no internal unresolved relocations.
* Check with readelf after changing.
- * Also alternative() doesn't work.
*/
/* Disable profiling for userspace code: */
@@ -17,6 +16,7 @@
#include <linux/time.h>
#include <linux/string.h>
#include <asm/vsyscall.h>
+#include <asm/fixmap.h>
#include <asm/vgtod.h>
#include <asm/timex.h>
#include <asm/hpet.h>
@@ -25,6 +25,43 @@
#define gtod (&VVAR(vsyscall_gtod_data))
+notrace static cycle_t vread_tsc(void)
+{
+ cycle_t ret;
+ u64 last;
+
+ /*
+ * Empirically, a fence (of type that depends on the CPU)
+ * before rdtsc is enough to ensure that rdtsc is ordered
+ * with respect to loads. The various CPU manuals are unclear
+ * as to whether rdtsc can be reordered with later loads,
+ * but no one has ever seen it happen.
+ */
+ rdtsc_barrier();
+ ret = (cycle_t)vget_cycles();
+
+ last = VVAR(vsyscall_gtod_data).clock.cycle_last;
+
+ if (likely(ret >= last))
+ return ret;
+
+ /*
+ * GCC likes to generate cmov here, but this branch is extremely
+ * predictable (it's just a funciton of time and the likely is
+ * very likely) and there's a data dependence, so force GCC
+ * to generate a branch instead. I don't barrier() because
+ * we don't actually need a barrier, and if this function
+ * ever gets inlined it will generate worse code.
+ */
+ asm volatile ("");
+ return last;
+}
+
+static notrace cycle_t vread_hpet(void)
+{
+ return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+}
+
notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
{
long ret;
@@ -36,9 +73,12 @@ notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
notrace static inline long vgetns(void)
{
long v;
- cycles_t (*vread)(void);
- vread = gtod->clock.vread;
- v = (vread() - gtod->clock.cycle_last) & gtod->clock.mask;
+ cycles_t cycles;
+ if (gtod->clock.vclock_mode == VCLOCK_TSC)
+ cycles = vread_tsc();
+ else
+ cycles = vread_hpet();
+ v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
return (v * gtod->clock.mult) >> gtod->clock.shift;
}
@@ -116,21 +156,21 @@ notrace static noinline int do_monotonic_coarse(struct timespec *ts)
notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
{
- if (likely(gtod->sysctl_enabled))
- switch (clock) {
- case CLOCK_REALTIME:
- if (likely(gtod->clock.vread))
- return do_realtime(ts);
- break;
- case CLOCK_MONOTONIC:
- if (likely(gtod->clock.vread))
- return do_monotonic(ts);
- break;
- case CLOCK_REALTIME_COARSE:
- return do_realtime_coarse(ts);
- case CLOCK_MONOTONIC_COARSE:
- return do_monotonic_coarse(ts);
- }
+ switch (clock) {
+ case CLOCK_REALTIME:
+ if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
+ return do_realtime(ts);
+ break;
+ case CLOCK_MONOTONIC:
+ if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
+ return do_monotonic(ts);
+ break;
+ case CLOCK_REALTIME_COARSE:
+ return do_realtime_coarse(ts);
+ case CLOCK_MONOTONIC_COARSE:
+ return do_monotonic_coarse(ts);
+ }
+
return vdso_fallback_gettime(clock, ts);
}
int clock_gettime(clockid_t, struct timespec *)
@@ -139,7 +179,7 @@ int clock_gettime(clockid_t, struct timespec *)
notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
long ret;
- if (likely(gtod->sysctl_enabled && gtod->clock.vread)) {
+ if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) {
if (likely(tv != NULL)) {
BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
offsetof(struct timespec, tv_nsec) ||
@@ -161,27 +201,14 @@ notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
int gettimeofday(struct timeval *, struct timezone *)
__attribute__((weak, alias("__vdso_gettimeofday")));
-/* This will break when the xtime seconds get inaccurate, but that is
- * unlikely */
-
-static __always_inline long time_syscall(long *t)
-{
- long secs;
- asm volatile("syscall"
- : "=a" (secs)
- : "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
- return secs;
-}
-
+/*
+ * This will break when the xtime seconds get inaccurate, but that is
+ * unlikely
+ */
notrace time_t __vdso_time(time_t *t)
{
- time_t result;
-
- if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled))
- return time_syscall(t);
-
/* This is atomic on x86_64 so we don't need any locks. */
- result = ACCESS_ONCE(VVAR(vsyscall_gtod_data).wall_time_sec);
+ time_t result = ACCESS_ONCE(VVAR(vsyscall_gtod_data).wall_time_sec);
if (t)
*t = result;
diff --git a/arch/x86/vdso/vdso.S b/arch/x86/vdso/vdso.S
index 1d3aa6b87181..1b979c12ba85 100644
--- a/arch/x86/vdso/vdso.S
+++ b/arch/x86/vdso/vdso.S
@@ -1,10 +1,21 @@
+#include <asm/page_types.h>
+#include <linux/linkage.h>
#include <linux/init.h>
-__INITDATA
+__PAGE_ALIGNED_DATA
.globl vdso_start, vdso_end
+ .align PAGE_SIZE
vdso_start:
.incbin "arch/x86/vdso/vdso.so"
vdso_end:
-__FINIT
+.previous
+
+ .globl vdso_pages
+ .bss
+ .align 8
+ .type vdso_pages, @object
+vdso_pages:
+ .zero (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE * 8
+ .size vdso_pages, .-vdso_pages
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 7abd2be0f9b9..316fbca3490e 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -14,41 +14,61 @@
#include <asm/vgtod.h>
#include <asm/proto.h>
#include <asm/vdso.h>
+#include <asm/page.h>
unsigned int __read_mostly vdso_enabled = 1;
extern char vdso_start[], vdso_end[];
extern unsigned short vdso_sync_cpuid;
-static struct page **vdso_pages;
+extern struct page *vdso_pages[];
static unsigned vdso_size;
-static int __init init_vdso_vars(void)
+static void __init patch_vdso(void *vdso, size_t len)
+{
+ Elf64_Ehdr *hdr = vdso;
+ Elf64_Shdr *sechdrs, *alt_sec = 0;
+ char *secstrings;
+ void *alt_data;
+ int i;
+
+ BUG_ON(len < sizeof(Elf64_Ehdr));
+ BUG_ON(memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0);
+
+ sechdrs = (void *)hdr + hdr->e_shoff;
+ secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (i = 1; i < hdr->e_shnum; i++) {
+ Elf64_Shdr *shdr = &sechdrs[i];
+ if (!strcmp(secstrings + shdr->sh_name, ".altinstructions")) {
+ alt_sec = shdr;
+ goto found;
+ }
+ }
+
+ /* If we get here, it's probably a bug. */
+ pr_warning("patch_vdso: .altinstructions not found\n");
+ return; /* nothing to patch */
+
+found:
+ alt_data = (void *)hdr + alt_sec->sh_offset;
+ apply_alternatives(alt_data, alt_data + alt_sec->sh_size);
+}
+
+static int __init init_vdso(void)
{
int npages = (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE;
int i;
+ patch_vdso(vdso_start, vdso_end - vdso_start);
+
vdso_size = npages << PAGE_SHIFT;
- vdso_pages = kmalloc(sizeof(struct page *) * npages, GFP_KERNEL);
- if (!vdso_pages)
- goto oom;
- for (i = 0; i < npages; i++) {
- struct page *p;
- p = alloc_page(GFP_KERNEL);
- if (!p)
- goto oom;
- vdso_pages[i] = p;
- copy_page(page_address(p), vdso_start + i*PAGE_SIZE);
- }
+ for (i = 0; i < npages; i++)
+ vdso_pages[i] = virt_to_page(vdso_start + i*PAGE_SIZE);
return 0;
-
- oom:
- printk("Cannot allocate vdso\n");
- vdso_enabled = 0;
- return -ENOMEM;
}
-subsys_initcall(init_vdso_vars);
+subsys_initcall(init_vdso);
struct linux_binprm;
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 17c565de3d64..ccf73b2f3e69 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -13,10 +13,10 @@ CFLAGS_mmu.o := $(nostackp)
obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
time.o xen-asm.o xen-asm_$(BITS).o \
grant-table.o suspend.o platform-pci-unplug.o \
- p2m.o
+ p2m.o trace.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
-
+obj-$(CONFIG_XEN_DOM0) += vga.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 5525163a0398..974a528458a0 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -341,6 +341,8 @@ static void xen_set_ldt(const void *addr, unsigned entries)
struct mmuext_op *op;
struct multicall_space mcs = xen_mc_entry(sizeof(*op));
+ trace_xen_cpu_set_ldt(addr, entries);
+
op = mcs.args;
op->cmd = MMUEXT_SET_LDT;
op->arg1.linear_addr = (unsigned long)addr;
@@ -496,6 +498,8 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]);
u64 entry = *(u64 *)ptr;
+ trace_xen_cpu_write_ldt_entry(dt, entrynum, entry);
+
preempt_disable();
xen_mc_flush();
@@ -565,6 +569,8 @@ static void xen_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g)
unsigned long p = (unsigned long)&dt[entrynum];
unsigned long start, end;
+ trace_xen_cpu_write_idt_entry(dt, entrynum, g);
+
preempt_disable();
start = __this_cpu_read(idt_desc.address);
@@ -619,6 +625,8 @@ static void xen_load_idt(const struct desc_ptr *desc)
static DEFINE_SPINLOCK(lock);
static struct trap_info traps[257];
+ trace_xen_cpu_load_idt(desc);
+
spin_lock(&lock);
__get_cpu_var(idt_desc) = *desc;
@@ -637,6 +645,8 @@ static void xen_load_idt(const struct desc_ptr *desc)
static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
const void *desc, int type)
{
+ trace_xen_cpu_write_gdt_entry(dt, entry, desc, type);
+
preempt_disable();
switch (type) {
@@ -665,6 +675,8 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
static void __init xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
const void *desc, int type)
{
+ trace_xen_cpu_write_gdt_entry(dt, entry, desc, type);
+
switch (type) {
case DESC_LDT:
case DESC_TSS:
@@ -684,7 +696,9 @@ static void __init xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
static void xen_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
- struct multicall_space mcs = xen_mc_entry(0);
+ struct multicall_space mcs;
+
+ mcs = xen_mc_entry(0);
MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0);
xen_mc_issue(PARAVIRT_LAZY_CPU);
}
@@ -1248,6 +1262,14 @@ asmlinkage void __init xen_start_kernel(void)
if (pci_xen)
x86_init.pci.arch_init = pci_xen_init;
} else {
+ const struct dom0_vga_console_info *info =
+ (void *)((char *)xen_start_info +
+ xen_start_info->console.dom0.info_off);
+
+ xen_init_vga(info, xen_start_info->console.dom0.info_size);
+ xen_start_info->console.domU.mfn = 0;
+ xen_start_info->console.domU.evtchn = 0;
+
/* Make sure ACS will be enabled */
pci_request_acs();
}
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 0ccccb67a993..f987bde77c49 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -48,6 +48,8 @@
#include <linux/memblock.h>
#include <linux/seq_file.h>
+#include <trace/events/xen.h>
+
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/fixmap.h>
@@ -194,6 +196,8 @@ void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid)
struct multicall_space mcs;
struct mmu_update *u;
+ trace_xen_mmu_set_domain_pte(ptep, pteval, domid);
+
mcs = xen_mc_entry(sizeof(*u));
u = mcs.args;
@@ -225,6 +229,24 @@ static void xen_extend_mmu_update(const struct mmu_update *update)
*u = *update;
}
+static void xen_extend_mmuext_op(const struct mmuext_op *op)
+{
+ struct multicall_space mcs;
+ struct mmuext_op *u;
+
+ mcs = xen_mc_extend_args(__HYPERVISOR_mmuext_op, sizeof(*u));
+
+ if (mcs.mc != NULL) {
+ mcs.mc->args[1]++;
+ } else {
+ mcs = __xen_mc_entry(sizeof(*u));
+ MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF);
+ }
+
+ u = mcs.args;
+ *u = *op;
+}
+
static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
{
struct mmu_update u;
@@ -245,6 +267,8 @@ static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
static void xen_set_pmd(pmd_t *ptr, pmd_t val)
{
+ trace_xen_mmu_set_pmd(ptr, val);
+
/* If page is not pinned, we can just update the entry
directly */
if (!xen_page_pinned(ptr)) {
@@ -282,22 +306,30 @@ static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval)
return true;
}
-static void xen_set_pte(pte_t *ptep, pte_t pteval)
+static inline void __xen_set_pte(pte_t *ptep, pte_t pteval)
{
if (!xen_batched_set_pte(ptep, pteval))
native_set_pte(ptep, pteval);
}
+static void xen_set_pte(pte_t *ptep, pte_t pteval)
+{
+ trace_xen_mmu_set_pte(ptep, pteval);
+ __xen_set_pte(ptep, pteval);
+}
+
static void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
- xen_set_pte(ptep, pteval);
+ trace_xen_mmu_set_pte_at(mm, addr, ptep, pteval);
+ __xen_set_pte(ptep, pteval);
}
pte_t xen_ptep_modify_prot_start(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
/* Just return the pte as-is. We preserve the bits on commit */
+ trace_xen_mmu_ptep_modify_prot_start(mm, addr, ptep, *ptep);
return *ptep;
}
@@ -306,6 +338,7 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
{
struct mmu_update u;
+ trace_xen_mmu_ptep_modify_prot_commit(mm, addr, ptep, pte);
xen_mc_batch();
u.ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD;
@@ -530,6 +563,8 @@ static void xen_set_pud_hyper(pud_t *ptr, pud_t val)
static void xen_set_pud(pud_t *ptr, pud_t val)
{
+ trace_xen_mmu_set_pud(ptr, val);
+
/* If page is not pinned, we can just update the entry
directly */
if (!xen_page_pinned(ptr)) {
@@ -543,17 +578,20 @@ static void xen_set_pud(pud_t *ptr, pud_t val)
#ifdef CONFIG_X86_PAE
static void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
{
+ trace_xen_mmu_set_pte_atomic(ptep, pte);
set_64bit((u64 *)ptep, native_pte_val(pte));
}
static void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
+ trace_xen_mmu_pte_clear(mm, addr, ptep);
if (!xen_batched_set_pte(ptep, native_make_pte(0)))
native_pte_clear(mm, addr, ptep);
}
static void xen_pmd_clear(pmd_t *pmdp)
{
+ trace_xen_mmu_pmd_clear(pmdp);
set_pmd(pmdp, __pmd(0));
}
#endif /* CONFIG_X86_PAE */
@@ -629,6 +667,8 @@ static void xen_set_pgd(pgd_t *ptr, pgd_t val)
{
pgd_t *user_ptr = xen_get_user_pgd(ptr);
+ trace_xen_mmu_set_pgd(ptr, user_ptr, val);
+
/* If page is not pinned, we can just update the entry
directly */
if (!xen_page_pinned(ptr)) {
@@ -788,14 +828,12 @@ static void xen_pte_unlock(void *v)
static void xen_do_pin(unsigned level, unsigned long pfn)
{
- struct mmuext_op *op;
- struct multicall_space mcs;
+ struct mmuext_op op;
- mcs = __xen_mc_entry(sizeof(*op));
- op = mcs.args;
- op->cmd = level;
- op->arg1.mfn = pfn_to_mfn(pfn);
- MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+ op.cmd = level;
+ op.arg1.mfn = pfn_to_mfn(pfn);
+
+ xen_extend_mmuext_op(&op);
}
static int xen_pin_page(struct mm_struct *mm, struct page *page,
@@ -863,6 +901,8 @@ static int xen_pin_page(struct mm_struct *mm, struct page *page,
read-only, and can be pinned. */
static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd)
{
+ trace_xen_mmu_pgd_pin(mm, pgd);
+
xen_mc_batch();
if (__xen_pgd_walk(mm, pgd, xen_pin_page, USER_LIMIT)) {
@@ -988,6 +1028,8 @@ static int xen_unpin_page(struct mm_struct *mm, struct page *page,
/* Release a pagetables pages back as normal RW */
static void __xen_pgd_unpin(struct mm_struct *mm, pgd_t *pgd)
{
+ trace_xen_mmu_pgd_unpin(mm, pgd);
+
xen_mc_batch();
xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
@@ -1196,6 +1238,8 @@ static void xen_flush_tlb(void)
struct mmuext_op *op;
struct multicall_space mcs;
+ trace_xen_mmu_flush_tlb(0);
+
preempt_disable();
mcs = xen_mc_entry(sizeof(*op));
@@ -1214,6 +1258,8 @@ static void xen_flush_tlb_single(unsigned long addr)
struct mmuext_op *op;
struct multicall_space mcs;
+ trace_xen_mmu_flush_tlb_single(addr);
+
preempt_disable();
mcs = xen_mc_entry(sizeof(*op));
@@ -1240,6 +1286,8 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
} *args;
struct multicall_space mcs;
+ trace_xen_mmu_flush_tlb_others(cpus, mm, va);
+
if (cpumask_empty(cpus))
return; /* nothing to do */
@@ -1275,10 +1323,11 @@ static void set_current_cr3(void *v)
static void __xen_write_cr3(bool kernel, unsigned long cr3)
{
- struct mmuext_op *op;
- struct multicall_space mcs;
+ struct mmuext_op op;
unsigned long mfn;
+ trace_xen_mmu_write_cr3(kernel, cr3);
+
if (cr3)
mfn = pfn_to_mfn(PFN_DOWN(cr3));
else
@@ -1286,13 +1335,10 @@ static void __xen_write_cr3(bool kernel, unsigned long cr3)
WARN_ON(mfn == 0 && kernel);
- mcs = __xen_mc_entry(sizeof(*op));
-
- op = mcs.args;
- op->cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR;
- op->arg1.mfn = mfn;
+ op.cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR;
+ op.arg1.mfn = mfn;
- MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+ xen_extend_mmuext_op(&op);
if (kernel) {
percpu_write(xen_cr3, cr3);
@@ -1451,19 +1497,52 @@ static void __init xen_release_pmd_init(unsigned long pfn)
make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
}
+static inline void __pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
+{
+ struct multicall_space mcs;
+ struct mmuext_op *op;
+
+ mcs = __xen_mc_entry(sizeof(*op));
+ op = mcs.args;
+ op->cmd = cmd;
+ op->arg1.mfn = pfn_to_mfn(pfn);
+
+ MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF);
+}
+
+static inline void __set_pfn_prot(unsigned long pfn, pgprot_t prot)
+{
+ struct multicall_space mcs;
+ unsigned long addr = (unsigned long)__va(pfn << PAGE_SHIFT);
+
+ mcs = __xen_mc_entry(0);
+ MULTI_update_va_mapping(mcs.mc, (unsigned long)addr,
+ pfn_pte(pfn, prot), 0);
+}
+
/* This needs to make sure the new pte page is pinned iff its being
attached to a pinned pagetable. */
-static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level)
+static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn,
+ unsigned level)
{
- struct page *page = pfn_to_page(pfn);
+ bool pinned = PagePinned(virt_to_page(mm->pgd));
+
+ trace_xen_mmu_alloc_ptpage(mm, pfn, level, pinned);
+
+ if (pinned) {
+ struct page *page = pfn_to_page(pfn);
- if (PagePinned(virt_to_page(mm->pgd))) {
SetPagePinned(page);
if (!PageHighMem(page)) {
- make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn)));
+ xen_mc_batch();
+
+ __set_pfn_prot(pfn, PAGE_KERNEL_RO);
+
if (level == PT_PTE && USE_SPLIT_PTLOCKS)
- pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
+ __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
+
+ xen_mc_issue(PARAVIRT_LAZY_MMU);
} else {
/* make sure there are no stray mappings of
this page */
@@ -1483,15 +1562,23 @@ static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn)
}
/* This should never happen until we're OK to use struct page */
-static void xen_release_ptpage(unsigned long pfn, unsigned level)
+static inline void xen_release_ptpage(unsigned long pfn, unsigned level)
{
struct page *page = pfn_to_page(pfn);
+ bool pinned = PagePinned(page);
- if (PagePinned(page)) {
+ trace_xen_mmu_release_ptpage(pfn, level, pinned);
+
+ if (pinned) {
if (!PageHighMem(page)) {
+ xen_mc_batch();
+
if (level == PT_PTE && USE_SPLIT_PTLOCKS)
- pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
- make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
+ __pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
+
+ __set_pfn_prot(pfn, PAGE_KERNEL);
+
+ xen_mc_issue(PARAVIRT_LAZY_MMU);
}
ClearPagePinned(page);
}
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
index 1b2b73ff0a6e..0d82003e76ad 100644
--- a/arch/x86/xen/multicalls.c
+++ b/arch/x86/xen/multicalls.c
@@ -30,12 +30,13 @@
#define MC_BATCH 32
-#define MC_DEBUG 1
+#define MC_DEBUG 0
#define MC_ARGS (MC_BATCH * 16)
struct mc_buffer {
+ unsigned mcidx, argidx, cbidx;
struct multicall_entry entries[MC_BATCH];
#if MC_DEBUG
struct multicall_entry debug[MC_BATCH];
@@ -46,85 +47,15 @@ struct mc_buffer {
void (*fn)(void *);
void *data;
} callbacks[MC_BATCH];
- unsigned mcidx, argidx, cbidx;
};
static DEFINE_PER_CPU(struct mc_buffer, mc_buffer);
DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags);
-/* flush reasons 0- slots, 1- args, 2- callbacks */
-enum flush_reasons
-{
- FL_SLOTS,
- FL_ARGS,
- FL_CALLBACKS,
-
- FL_N_REASONS
-};
-
-#ifdef CONFIG_XEN_DEBUG_FS
-#define NHYPERCALLS 40 /* not really */
-
-static struct {
- unsigned histo[MC_BATCH+1];
-
- unsigned issued;
- unsigned arg_total;
- unsigned hypercalls;
- unsigned histo_hypercalls[NHYPERCALLS];
-
- unsigned flush[FL_N_REASONS];
-} mc_stats;
-
-static u8 zero_stats;
-
-static inline void check_zero(void)
-{
- if (unlikely(zero_stats)) {
- memset(&mc_stats, 0, sizeof(mc_stats));
- zero_stats = 0;
- }
-}
-
-static void mc_add_stats(const struct mc_buffer *mc)
-{
- int i;
-
- check_zero();
-
- mc_stats.issued++;
- mc_stats.hypercalls += mc->mcidx;
- mc_stats.arg_total += mc->argidx;
-
- mc_stats.histo[mc->mcidx]++;
- for(i = 0; i < mc->mcidx; i++) {
- unsigned op = mc->entries[i].op;
- if (op < NHYPERCALLS)
- mc_stats.histo_hypercalls[op]++;
- }
-}
-
-static void mc_stats_flush(enum flush_reasons idx)
-{
- check_zero();
-
- mc_stats.flush[idx]++;
-}
-
-#else /* !CONFIG_XEN_DEBUG_FS */
-
-static inline void mc_add_stats(const struct mc_buffer *mc)
-{
-}
-
-static inline void mc_stats_flush(enum flush_reasons idx)
-{
-}
-#endif /* CONFIG_XEN_DEBUG_FS */
-
void xen_mc_flush(void)
{
struct mc_buffer *b = &__get_cpu_var(mc_buffer);
+ struct multicall_entry *mc;
int ret = 0;
unsigned long flags;
int i;
@@ -135,9 +66,26 @@ void xen_mc_flush(void)
something in the middle */
local_irq_save(flags);
- mc_add_stats(b);
+ trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
+
+ switch (b->mcidx) {
+ case 0:
+ /* no-op */
+ BUG_ON(b->argidx != 0);
+ break;
+
+ case 1:
+ /* Singleton multicall - bypass multicall machinery
+ and just do the call directly. */
+ mc = &b->entries[0];
+
+ mc->result = privcmd_call(mc->op,
+ mc->args[0], mc->args[1], mc->args[2],
+ mc->args[3], mc->args[4]);
+ ret = mc->result < 0;
+ break;
- if (b->mcidx) {
+ default:
#if MC_DEBUG
memcpy(b->debug, b->entries,
b->mcidx * sizeof(struct multicall_entry));
@@ -164,11 +112,10 @@ void xen_mc_flush(void)
}
}
#endif
+ }
- b->mcidx = 0;
- b->argidx = 0;
- } else
- BUG_ON(b->argidx != 0);
+ b->mcidx = 0;
+ b->argidx = 0;
for (i = 0; i < b->cbidx; i++) {
struct callback *cb = &b->callbacks[i];
@@ -188,18 +135,21 @@ struct multicall_space __xen_mc_entry(size_t args)
struct multicall_space ret;
unsigned argidx = roundup(b->argidx, sizeof(u64));
+ trace_xen_mc_entry_alloc(args);
+
BUG_ON(preemptible());
BUG_ON(b->argidx >= MC_ARGS);
- if (b->mcidx == MC_BATCH ||
- (argidx + args) >= MC_ARGS) {
- mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS);
+ if (unlikely(b->mcidx == MC_BATCH ||
+ (argidx + args) >= MC_ARGS)) {
+ trace_xen_mc_flush_reason((b->mcidx == MC_BATCH) ?
+ XEN_MC_FL_BATCH : XEN_MC_FL_ARGS);
xen_mc_flush();
argidx = roundup(b->argidx, sizeof(u64));
}
ret.mc = &b->entries[b->mcidx];
-#ifdef MC_DEBUG
+#if MC_DEBUG
b->caller[b->mcidx] = __builtin_return_address(0);
#endif
b->mcidx++;
@@ -218,20 +168,25 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
BUG_ON(preemptible());
BUG_ON(b->argidx >= MC_ARGS);
- if (b->mcidx == 0)
- return ret;
-
- if (b->entries[b->mcidx - 1].op != op)
- return ret;
+ if (unlikely(b->mcidx == 0 ||
+ b->entries[b->mcidx - 1].op != op)) {
+ trace_xen_mc_extend_args(op, size, XEN_MC_XE_BAD_OP);
+ goto out;
+ }
- if ((b->argidx + size) >= MC_ARGS)
- return ret;
+ if (unlikely((b->argidx + size) >= MC_ARGS)) {
+ trace_xen_mc_extend_args(op, size, XEN_MC_XE_NO_SPACE);
+ goto out;
+ }
ret.mc = &b->entries[b->mcidx - 1];
ret.args = &b->args[b->argidx];
b->argidx += size;
BUG_ON(b->argidx >= MC_ARGS);
+
+ trace_xen_mc_extend_args(op, size, XEN_MC_XE_OK);
+out:
return ret;
}
@@ -241,43 +196,13 @@ void xen_mc_callback(void (*fn)(void *), void *data)
struct callback *cb;
if (b->cbidx == MC_BATCH) {
- mc_stats_flush(FL_CALLBACKS);
+ trace_xen_mc_flush_reason(XEN_MC_FL_CALLBACK);
xen_mc_flush();
}
+ trace_xen_mc_callback(fn, data);
+
cb = &b->callbacks[b->cbidx++];
cb->fn = fn;
cb->data = data;
}
-
-#ifdef CONFIG_XEN_DEBUG_FS
-
-static struct dentry *d_mc_debug;
-
-static int __init xen_mc_debugfs(void)
-{
- struct dentry *d_xen = xen_init_debugfs();
-
- if (d_xen == NULL)
- return -ENOMEM;
-
- d_mc_debug = debugfs_create_dir("multicalls", d_xen);
-
- debugfs_create_u8("zero_stats", 0644, d_mc_debug, &zero_stats);
-
- debugfs_create_u32("batches", 0444, d_mc_debug, &mc_stats.issued);
- debugfs_create_u32("hypercalls", 0444, d_mc_debug, &mc_stats.hypercalls);
- debugfs_create_u32("arg_total", 0444, d_mc_debug, &mc_stats.arg_total);
-
- xen_debugfs_create_u32_array("batch_histo", 0444, d_mc_debug,
- mc_stats.histo, MC_BATCH);
- xen_debugfs_create_u32_array("hypercall_histo", 0444, d_mc_debug,
- mc_stats.histo_hypercalls, NHYPERCALLS);
- xen_debugfs_create_u32_array("flush_reasons", 0444, d_mc_debug,
- mc_stats.flush, FL_N_REASONS);
-
- return 0;
-}
-fs_initcall(xen_mc_debugfs);
-
-#endif /* CONFIG_XEN_DEBUG_FS */
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h
index 4ec8035e3216..dee79b78a90f 100644
--- a/arch/x86/xen/multicalls.h
+++ b/arch/x86/xen/multicalls.h
@@ -1,6 +1,8 @@
#ifndef _XEN_MULTICALLS_H
#define _XEN_MULTICALLS_H
+#include <trace/events/xen.h>
+
#include "xen-ops.h"
/* Multicalls */
@@ -20,8 +22,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
static inline void xen_mc_batch(void)
{
unsigned long flags;
+
/* need to disable interrupts until this entry is complete */
local_irq_save(flags);
+ trace_xen_mc_batch(paravirt_get_lazy_mode());
__this_cpu_write(xen_mc_irq_flags, flags);
}
@@ -37,6 +41,8 @@ void xen_mc_flush(void);
/* Issue a multicall if we're not in a lazy mode */
static inline void xen_mc_issue(unsigned mode)
{
+ trace_xen_mc_issue(mode);
+
if ((paravirt_get_lazy_mode() & mode) == 0)
xen_mc_flush();
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index 25c52f94a27c..ffcf2615640b 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
#ifdef CONFIG_XEN_PVHVM
static int xen_emul_unplug;
-static int __init check_platform_magic(void)
+static int check_platform_magic(void)
{
short magic;
char protocol;
diff --git a/arch/x86/xen/trace.c b/arch/x86/xen/trace.c
new file mode 100644
index 000000000000..734beba2a08c
--- /dev/null
+++ b/arch/x86/xen/trace.c
@@ -0,0 +1,61 @@
+#include <linux/ftrace.h>
+
+#define N(x) [__HYPERVISOR_##x] = "("#x")"
+static const char *xen_hypercall_names[] = {
+ N(set_trap_table),
+ N(mmu_update),
+ N(set_gdt),
+ N(stack_switch),
+ N(set_callbacks),
+ N(fpu_taskswitch),
+ N(sched_op_compat),
+ N(dom0_op),
+ N(set_debugreg),
+ N(get_debugreg),
+ N(update_descriptor),
+ N(memory_op),
+ N(multicall),
+ N(update_va_mapping),
+ N(set_timer_op),
+ N(event_channel_op_compat),
+ N(xen_version),
+ N(console_io),
+ N(physdev_op_compat),
+ N(grant_table_op),
+ N(vm_assist),
+ N(update_va_mapping_otherdomain),
+ N(iret),
+ N(vcpu_op),
+ N(set_segment_base),
+ N(mmuext_op),
+ N(acm_op),
+ N(nmi_op),
+ N(sched_op),
+ N(callback_op),
+ N(xenoprof_op),
+ N(event_channel_op),
+ N(physdev_op),
+ N(hvm_op),
+
+/* Architecture-specific hypercall definitions. */
+ N(arch_0),
+ N(arch_1),
+ N(arch_2),
+ N(arch_3),
+ N(arch_4),
+ N(arch_5),
+ N(arch_6),
+ N(arch_7),
+};
+#undef N
+
+static const char *xen_hypercall_name(unsigned op)
+{
+ if (op < ARRAY_SIZE(xen_hypercall_names) && xen_hypercall_names[op] != NULL)
+ return xen_hypercall_names[op];
+
+ return "";
+}
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/xen.h>
diff --git a/arch/x86/xen/vga.c b/arch/x86/xen/vga.c
new file mode 100644
index 000000000000..1cd7f4d11e29
--- /dev/null
+++ b/arch/x86/xen/vga.c
@@ -0,0 +1,67 @@
+#include <linux/screen_info.h>
+#include <linux/init.h>
+
+#include <asm/bootparam.h>
+#include <asm/setup.h>
+
+#include <xen/interface/xen.h>
+
+#include "xen-ops.h"
+
+void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size)
+{
+ struct screen_info *screen_info = &boot_params.screen_info;
+
+ /* This is drawn from a dump from vgacon:startup in
+ * standard Linux. */
+ screen_info->orig_video_mode = 3;
+ screen_info->orig_video_isVGA = 1;
+ screen_info->orig_video_lines = 25;
+ screen_info->orig_video_cols = 80;
+ screen_info->orig_video_ega_bx = 3;
+ screen_info->orig_video_points = 16;
+ screen_info->orig_y = screen_info->orig_video_lines - 1;
+
+ switch (info->video_type) {
+ case XEN_VGATYPE_TEXT_MODE_3:
+ if (size < offsetof(struct dom0_vga_console_info, u.text_mode_3)
+ + sizeof(info->u.text_mode_3))
+ break;
+ screen_info->orig_video_lines = info->u.text_mode_3.rows;
+ screen_info->orig_video_cols = info->u.text_mode_3.columns;
+ screen_info->orig_x = info->u.text_mode_3.cursor_x;
+ screen_info->orig_y = info->u.text_mode_3.cursor_y;
+ screen_info->orig_video_points =
+ info->u.text_mode_3.font_height;
+ break;
+
+ case XEN_VGATYPE_VESA_LFB:
+ if (size < offsetof(struct dom0_vga_console_info,
+ u.vesa_lfb.gbl_caps))
+ break;
+ screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
+ screen_info->lfb_width = info->u.vesa_lfb.width;
+ screen_info->lfb_height = info->u.vesa_lfb.height;
+ screen_info->lfb_depth = info->u.vesa_lfb.bits_per_pixel;
+ screen_info->lfb_base = info->u.vesa_lfb.lfb_base;
+ screen_info->lfb_size = info->u.vesa_lfb.lfb_size;
+ screen_info->lfb_linelength = info->u.vesa_lfb.bytes_per_line;
+ screen_info->red_size = info->u.vesa_lfb.red_size;
+ screen_info->red_pos = info->u.vesa_lfb.red_pos;
+ screen_info->green_size = info->u.vesa_lfb.green_size;
+ screen_info->green_pos = info->u.vesa_lfb.green_pos;
+ screen_info->blue_size = info->u.vesa_lfb.blue_size;
+ screen_info->blue_pos = info->u.vesa_lfb.blue_pos;
+ screen_info->rsvd_size = info->u.vesa_lfb.rsvd_size;
+ screen_info->rsvd_pos = info->u.vesa_lfb.rsvd_pos;
+ if (size >= offsetof(struct dom0_vga_console_info,
+ u.vesa_lfb.gbl_caps)
+ + sizeof(info->u.vesa_lfb.gbl_caps))
+ screen_info->capabilities = info->u.vesa_lfb.gbl_caps;
+ if (size >= offsetof(struct dom0_vga_console_info,
+ u.vesa_lfb.mode_attrs)
+ + sizeof(info->u.vesa_lfb.mode_attrs))
+ screen_info->vesa_attributes = info->u.vesa_lfb.mode_attrs;
+ break;
+ }
+}
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 97dfdc8757b3..b095739ccd4c 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -88,6 +88,17 @@ static inline void xen_uninit_lock_cpu(int cpu)
}
#endif
+struct dom0_vga_console_info;
+
+#ifdef CONFIG_XEN_DOM0
+void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
+#else
+static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
+ size_t size)
+{
+}
+#endif
+
/* Declare an asm function, along with symbols needed to make it
inlineable */
#define DECL_ASM(ret, name, ...) \
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 5d43c1f8ada8..c346ccdce0df 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -80,18 +80,7 @@ config XTENSA_UNALIGNED_USER
Say Y here to enable unaligned memory access in user space.
-config PREEMPT
- bool "Preemptible Kernel"
- help
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- Unfortunately the kernel code has some race conditions if both
- CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is
- currently disabled if you are building an SMP kernel.
-
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
+source "kernel/Kconfig.preempt"
config MATH_EMULATION
bool "Math emulation"
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h
index a96a0619d0b7..23592eff67ad 100644
--- a/arch/xtensa/include/asm/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -225,15 +225,15 @@ static inline int atomic_sub_return(int i, atomic_t * v)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
*/
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -245,10 +245,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
break;
c = old;
}
- return c != (u);
+ return c;
}
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
{
@@ -292,7 +291,6 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
-#include <asm-generic/atomic-long.h>
#endif /* __KERNEL__ */
#endif /* _XTENSA_ATOMIC_H */
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
index c8fac8d8190d..40aa7fe77f66 100644
--- a/arch/xtensa/include/asm/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -108,19 +108,7 @@ static inline unsigned long __fls(unsigned long word)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/le.h>
-#ifdef __XTENSA_EL__
-# define ext2_set_bit_atomic(lock,nr,addr) \
- test_and_set_bit((nr), (unsigned long*)(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) \
- test_and_clear_bit((nr), (unsigned long*)(addr))
-#elif defined(__XTENSA_EB__)
-# define ext2_set_bit_atomic(lock,nr,addr) \
- test_and_set_bit((nr) ^ 0x18, (unsigned long*)(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) \
- test_and_clear_bit((nr) ^ 0x18, (unsigned long*)(addr))
-#else
-# error processor byte order undefined!
-#endif
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
diff --git a/arch/xtensa/include/asm/posix_types.h b/arch/xtensa/include/asm/posix_types.h
index 43f9dd1126a4..6b2190c35882 100644
--- a/arch/xtensa/include/asm/posix_types.h
+++ b/arch/xtensa/include/asm/posix_types.h
@@ -58,7 +58,7 @@ typedef struct {
#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define __FD_ISSET(d, set) (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
#define __FD_ZERO(set) \
((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h
index 0d42c934b66f..d85d38da8eec 100644
--- a/arch/xtensa/include/asm/ptrace.h
+++ b/arch/xtensa/include/asm/ptrace.h
@@ -120,7 +120,6 @@ struct pt_regs {
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
# define instruction_pointer(regs) ((regs)->pc)
-extern void show_regs(struct pt_regs *);
# ifndef CONFIG_SMP
# define profile_pc(regs) instruction_pointer(regs)
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h
index 5b0c18c1cce1..3fa526fd3c99 100644
--- a/arch/xtensa/include/asm/uaccess.h
+++ b/arch/xtensa/include/asm/uaccess.h
@@ -17,6 +17,8 @@
#define _XTENSA_UACCESS_H
#include <linux/errno.h>
+#include <linux/prefetch.h>
+#include <asm/types.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
@@ -26,7 +28,6 @@
#include <asm/current.h>
#include <asm/asm-offsets.h>
#include <asm/processor.h>
-#include <asm/types.h>
/*
* These assembly macros mirror the C macros that follow below. They
@@ -157,7 +158,6 @@
#else /* __ASSEMBLY__ not defined */
#include <linux/sched.h>
-#include <asm/types.h>
/*
* The fs value determines whether argument validity checking should
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c
index c1accea8cb56..451dda928c93 100644
--- a/arch/xtensa/kernel/module.c
+++ b/arch/xtensa/kernel/module.c
@@ -24,26 +24,6 @@
#undef DEBUG_RELOCATE
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc_exec(size);
-}
-
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-int module_frob_arch_sections(Elf32_Ehdr *hdr,
- Elf32_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
static int
decode_calln_opcode (unsigned char *location)
{
@@ -66,18 +46,6 @@ decode_l32r_opcode (unsigned char *location)
#endif
}
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *mod)
-{
- printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
- mod->name);
- return -ENOEXEC;
-
-}
-
int apply_relocate_add(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
@@ -222,14 +190,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
}
return 0;
}
-
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *mod)
-{
- return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index e3558b9a58ba..47041e7c088c 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -40,7 +40,7 @@
#include <asm/platform.h>
#include <asm/mmu.h>
#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/asm-offsets.h>
#include <asm/regs.h>
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index c72c9473ef99..a0d042aa2967 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -147,6 +147,9 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs)
elf_xtregs_t *xtregs = uregs;
int ret = 0;
+ if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t)))
+ return -EFAULT;
+
#if XTENSA_HAVE_COPROCESSORS
/* Flush all coprocessors before we overwrite them. */
coprocessor_flush_all(ti);
diff --git a/arch/xtensa/variants/s6000/include/variant/dmac.h b/arch/xtensa/variants/s6000/include/variant/dmac.h
index 89ab9484fb71..e81735b2a206 100644
--- a/arch/xtensa/variants/s6000/include/variant/dmac.h
+++ b/arch/xtensa/variants/s6000/include/variant/dmac.h
@@ -357,7 +357,7 @@ static inline u32 s6dmac_channel_enabled(u32 dmac, int chan)
static inline void s6dmac_dp_setup_group(u32 dmac, int port,
int nrch, int frrep)
{
- const static u8 mask[4] = {0, 3, 1, 2};
+ static const u8 mask[4] = {0, 3, 1, 2};
BUG_ON(dmac != S6_REG_DPDMA);
if ((port < 0) || (port > 3) || (nrch < 1) || (nrch > 4))
return;
diff --git a/block/blk-core.c b/block/blk-core.c
index d2f8f4049abd..b850bedad229 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
{
struct request *rq;
+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+ return NULL;
+
BUG_ON(rw != READ && rw != WRITE);
spin_lock_irq(q->queue_lock);
@@ -1279,10 +1282,8 @@ get_rq:
init_request_from_bio(req, bio);
if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
- bio_flagged(bio, BIO_CPU_AFFINE)) {
- req->cpu = blk_cpu_to_group(get_cpu());
- put_cpu();
- }
+ bio_flagged(bio, BIO_CPU_AFFINE))
+ req->cpu = raw_smp_processor_id();
plug = current->plug;
if (plug) {
@@ -1302,7 +1303,10 @@ get_rq:
plug->should_sort = 1;
}
list_add_tail(&req->queuelist, &plug->list);
+ plug->count++;
drive_stat_acct(req, 1);
+ if (plug->count >= BLK_MAX_REQUEST_COUNT)
+ blk_flush_plug_list(plug, false);
} else {
spin_lock_irq(q->queue_lock);
add_acct_request(q, req, where);
@@ -1357,14 +1361,9 @@ static int __init setup_fail_make_request(char *str)
}
__setup("fail_make_request=", setup_fail_make_request);
-static int should_fail_request(struct bio *bio)
+static bool should_fail_request(struct hd_struct *part, unsigned int bytes)
{
- struct hd_struct *part = bio->bi_bdev->bd_part;
-
- if (part_to_disk(part)->part0.make_it_fail || part->make_it_fail)
- return should_fail(&fail_make_request, bio->bi_size);
-
- return 0;
+ return part->make_it_fail && should_fail(&fail_make_request, bytes);
}
static int __init fail_make_request_debugfs(void)
@@ -1377,9 +1376,10 @@ late_initcall(fail_make_request_debugfs);
#else /* CONFIG_FAIL_MAKE_REQUEST */
-static inline int should_fail_request(struct bio *bio)
+static inline bool should_fail_request(struct hd_struct *part,
+ unsigned int bytes)
{
- return 0;
+ return false;
}
#endif /* CONFIG_FAIL_MAKE_REQUEST */
@@ -1462,6 +1462,7 @@ static inline void __generic_make_request(struct bio *bio)
old_dev = 0;
do {
char b[BDEVNAME_SIZE];
+ struct hd_struct *part;
q = bdev_get_queue(bio->bi_bdev);
if (unlikely(!q)) {
@@ -1485,7 +1486,10 @@ static inline void __generic_make_request(struct bio *bio)
if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
- if (should_fail_request(bio))
+ part = bio->bi_bdev->bd_part;
+ if (should_fail_request(part, bio->bi_size) ||
+ should_fail_request(&part_to_disk(part)->part0,
+ bio->bi_size))
goto end_io;
/*
@@ -1700,11 +1704,9 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
if (blk_rq_check_limits(q, rq))
return -EIO;
-#ifdef CONFIG_FAIL_MAKE_REQUEST
- if (rq->rq_disk && rq->rq_disk->part0.make_it_fail &&
- should_fail(&fail_make_request, blk_rq_bytes(rq)))
+ if (rq->rq_disk &&
+ should_fail_request(&rq->rq_disk->part0, blk_rq_bytes(rq)))
return -EIO;
-#endif
spin_lock_irqsave(q->queue_lock, flags);
@@ -2626,6 +2628,7 @@ void blk_start_plug(struct blk_plug *plug)
INIT_LIST_HEAD(&plug->list);
INIT_LIST_HEAD(&plug->cb_list);
plug->should_sort = 0;
+ plug->count = 0;
/*
* If this is a nested plug, don't actually assign it. It will be
@@ -2709,6 +2712,7 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
return;
list_splice_init(&plug->list, &list);
+ plug->count = 0;
if (plug->should_sort) {
list_sort(NULL, &list, plug_rq_cmp);
diff --git a/block/blk-exec.c b/block/blk-exec.c
index 8a0e7ec056e7..a1ebceb332f9 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
{
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
+ rq->errors = -ENXIO;
+ if (rq->end_io)
+ rq->end_io(rq, rq->errors);
+ return;
+ }
+
rq->rq_disk = bd_disk;
rq->end_io = done;
WARN_ON(irqs_disabled());
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 342eae9b0d3c..6f9bbd978653 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -82,26 +82,26 @@ void exit_io_context(struct task_struct *task)
struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
{
- struct io_context *ret;
+ struct io_context *ioc;
- ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
- if (ret) {
- atomic_long_set(&ret->refcount, 1);
- atomic_set(&ret->nr_tasks, 1);
- spin_lock_init(&ret->lock);
- ret->ioprio_changed = 0;
- ret->ioprio = 0;
- ret->last_waited = 0; /* doesn't matter... */
- ret->nr_batch_requests = 0; /* because this is 0 */
- INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);
- INIT_HLIST_HEAD(&ret->cic_list);
- ret->ioc_data = NULL;
+ ioc = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
+ if (ioc) {
+ atomic_long_set(&ioc->refcount, 1);
+ atomic_set(&ioc->nr_tasks, 1);
+ spin_lock_init(&ioc->lock);
+ ioc->ioprio_changed = 0;
+ ioc->ioprio = 0;
+ ioc->last_waited = 0; /* doesn't matter... */
+ ioc->nr_batch_requests = 0; /* because this is 0 */
+ INIT_RADIX_TREE(&ioc->radix_root, GFP_ATOMIC | __GFP_HIGH);
+ INIT_HLIST_HEAD(&ioc->cic_list);
+ ioc->ioc_data = NULL;
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
- ret->cgroup_changed = 0;
+ ioc->cgroup_changed = 0;
#endif
}
- return ret;
+ return ioc;
}
/*
@@ -139,19 +139,19 @@ struct io_context *current_io_context(gfp_t gfp_flags, int node)
*/
struct io_context *get_io_context(gfp_t gfp_flags, int node)
{
- struct io_context *ret = NULL;
+ struct io_context *ioc = NULL;
/*
* Check for unlikely race with exiting task. ioc ref count is
* zero when ioc is being detached.
*/
do {
- ret = current_io_context(gfp_flags, node);
- if (unlikely(!ret))
+ ioc = current_io_context(gfp_flags, node);
+ if (unlikely(!ioc))
break;
- } while (!atomic_long_inc_not_zero(&ret->refcount));
+ } while (!atomic_long_inc_not_zero(&ioc->refcount));
- return ret;
+ return ioc;
}
EXPORT_SYMBOL(get_io_context);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 78e627e2581d..2b461b496a78 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -59,7 +59,10 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
* granularity
*/
max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
- if (q->limits.discard_granularity) {
+ if (unlikely(!max_discard_sectors)) {
+ /* Avoid infinite loop below. Being cautious never hurts. */
+ return -EOPNOTSUPP;
+ } else if (q->limits.discard_granularity) {
unsigned int disc_sects = q->limits.discard_granularity >> 9;
max_discard_sectors &= ~(disc_sects - 1);
diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index ee9c21602228..475fab809a80 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -103,22 +103,25 @@ static struct notifier_block __cpuinitdata blk_cpu_notifier = {
void __blk_complete_request(struct request *req)
{
+ int ccpu, cpu, group_cpu = NR_CPUS;
struct request_queue *q = req->q;
unsigned long flags;
- int ccpu, cpu, group_cpu;
BUG_ON(!q->softirq_done_fn);
local_irq_save(flags);
cpu = smp_processor_id();
- group_cpu = blk_cpu_to_group(cpu);
/*
* Select completion CPU
*/
- if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) && req->cpu != -1)
+ if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) && req->cpu != -1) {
ccpu = req->cpu;
- else
+ if (!test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags)) {
+ ccpu = blk_cpu_to_group(ccpu);
+ group_cpu = blk_cpu_to_group(cpu);
+ }
+ } else
ccpu = cpu;
if (ccpu == cpu || ccpu == group_cpu) {
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index d935bd859c87..0ee17b5e7fb6 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -244,8 +244,9 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
{
bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
+ bool force = test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags);
- return queue_var_show(set, page);
+ return queue_var_show(set << force, page);
}
static ssize_t
@@ -257,10 +258,14 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
ret = queue_var_store(&val, page, count);
spin_lock_irq(q->queue_lock);
- if (val)
+ if (val) {
queue_flag_set(QUEUE_FLAG_SAME_COMP, q);
- else
- queue_flag_clear(QUEUE_FLAG_SAME_COMP, q);
+ if (val == 2)
+ queue_flag_set(QUEUE_FLAG_SAME_FORCE, q);
+ } else {
+ queue_flag_clear(QUEUE_FLAG_SAME_COMP, q);
+ queue_flag_clear(QUEUE_FLAG_SAME_FORCE, q);
+ }
spin_unlock_irq(q->queue_lock);
#endif
return ret;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 3689f833afdc..f6a794120505 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -142,9 +142,9 @@ static inline struct throtl_grp *tg_of_blkg(struct blkio_group *blkg)
return NULL;
}
-static inline int total_nr_queued(struct throtl_data *td)
+static inline unsigned int total_nr_queued(struct throtl_data *td)
{
- return (td->nr_queued[0] + td->nr_queued[1]);
+ return td->nr_queued[0] + td->nr_queued[1];
}
static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
@@ -927,7 +927,7 @@ static int throtl_dispatch(struct request_queue *q)
bio_list_init(&bio_list_on_stack);
- throtl_log(td, "dispatch nr_queued=%d read=%u write=%u",
+ throtl_log(td, "dispatch nr_queued=%u read=%u write=%u",
total_nr_queued(td), td->nr_queued[READ],
td->nr_queued[WRITE]);
@@ -970,7 +970,7 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay)
struct delayed_work *dwork = &td->throtl_work;
/* schedule work if limits changed even if no bio is queued */
- if (total_nr_queued(td) > 0 || td->limits_changed) {
+ if (total_nr_queued(td) || td->limits_changed) {
/*
* We might have a work scheduled to be executed in future.
* Cancel that and schedule a new one.
diff --git a/block/bsg.c b/block/bsg.c
index 0c8b64a16484..702f1316bb8f 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -182,7 +182,7 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
return -ENOMEM;
}
- if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
+ if (copy_from_user(rq->cmd, (void __user *)(unsigned long)hdr->request,
hdr->request_len))
return -EFAULT;
@@ -249,7 +249,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
struct request *rq, *next_rq = NULL;
int ret, rw;
unsigned int dxfer_len;
- void *dxferp = NULL;
+ void __user *dxferp = NULL;
struct bsg_class_device *bcd = &q->bsg_dev;
/* if the LLD has been removed then the bsg_unregister_queue will
@@ -291,7 +291,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
rq->next_rq = next_rq;
next_rq->cmd_type = rq->cmd_type;
- dxferp = (void*)(unsigned long)hdr->din_xferp;
+ dxferp = (void __user *)(unsigned long)hdr->din_xferp;
ret = blk_rq_map_user(q, next_rq, NULL, dxferp,
hdr->din_xfer_len, GFP_KERNEL);
if (ret)
@@ -300,10 +300,10 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
if (hdr->dout_xfer_len) {
dxfer_len = hdr->dout_xfer_len;
- dxferp = (void*)(unsigned long)hdr->dout_xferp;
+ dxferp = (void __user *)(unsigned long)hdr->dout_xferp;
} else if (hdr->din_xfer_len) {
dxfer_len = hdr->din_xfer_len;
- dxferp = (void*)(unsigned long)hdr->din_xferp;
+ dxferp = (void __user *)(unsigned long)hdr->din_xferp;
} else
dxfer_len = 0;
@@ -445,7 +445,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
int len = min_t(unsigned int, hdr->max_response_len,
rq->sense_len);
- ret = copy_to_user((void*)(unsigned long)hdr->response,
+ ret = copy_to_user((void __user *)(unsigned long)hdr->response,
rq->sense, len);
if (!ret)
hdr->response_len = len;
@@ -606,7 +606,7 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
ret = __bsg_read(buf, count, bd, NULL, &bytes_read);
*ppos = bytes_read;
- if (!bytes_read || (bytes_read && err_block_err(ret)))
+ if (!bytes_read || err_block_err(ret))
bytes_read = ret;
return bytes_read;
@@ -686,7 +686,7 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
/*
* return bytes written on non-fatal errors
*/
- if (!bytes_written || (bytes_written && err_block_err(ret)))
+ if (!bytes_written || err_block_err(ret))
bytes_written = ret;
dprintk("%s: returning %Zd\n", bd->name, bytes_written);
@@ -878,7 +878,7 @@ static unsigned int bsg_poll(struct file *file, poll_table *wait)
spin_lock_irq(&bd->lock);
if (!list_empty(&bd->done_list))
mask |= POLLIN | POLLRDNORM;
- if (bd->queued_cmds >= bd->max_queue)
+ if (bd->queued_cmds < bd->max_queue)
mask |= POLLOUT;
spin_unlock_irq(&bd->lock);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ae21919f15e1..1f96ad6254f1 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -87,9 +87,10 @@ struct cfq_rb_root {
unsigned count;
unsigned total_weight;
u64 min_vdisktime;
+ struct cfq_ttime ttime;
};
-#define CFQ_RB_ROOT (struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \
- .count = 0, .min_vdisktime = 0, }
+#define CFQ_RB_ROOT (struct cfq_rb_root) { .rb = RB_ROOT, \
+ .ttime = {.last_end_request = jiffies,},}
/*
* Per process-grouping structure
@@ -129,14 +130,12 @@ struct cfq_queue {
unsigned long slice_end;
long slice_resid;
- /* pending metadata requests */
- int meta_pending;
/* number of requests that are on the dispatch list or inside driver */
int dispatched;
/* io prio of this group */
unsigned short ioprio, org_ioprio;
- unsigned short ioprio_class, org_ioprio_class;
+ unsigned short ioprio_class;
pid_t pid;
@@ -212,6 +211,7 @@ struct cfq_group {
#endif
/* number of requests that are on the dispatch list or inside driver */
int dispatched;
+ struct cfq_ttime ttime;
};
/*
@@ -393,6 +393,18 @@ CFQ_CFQQ_FNS(wait_busy);
j++, st = i < IDLE_WORKLOAD ? \
&cfqg->service_trees[i][j]: NULL) \
+static inline bool cfq_io_thinktime_big(struct cfq_data *cfqd,
+ struct cfq_ttime *ttime, bool group_idle)
+{
+ unsigned long slice;
+ if (!sample_valid(ttime->ttime_samples))
+ return false;
+ if (group_idle)
+ slice = cfqd->cfq_group_idle;
+ else
+ slice = cfqd->cfq_slice_idle;
+ return ttime->ttime_mean > slice;
+}
static inline bool iops_mode(struct cfq_data *cfqd)
{
@@ -670,9 +682,6 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2,
if (rq_is_sync(rq1) != rq_is_sync(rq2))
return rq_is_sync(rq1) ? rq1 : rq2;
- if ((rq1->cmd_flags ^ rq2->cmd_flags) & REQ_META)
- return rq1->cmd_flags & REQ_META ? rq1 : rq2;
-
s1 = blk_rq_pos(rq1);
s2 = blk_rq_pos(rq2);
@@ -1005,8 +1014,8 @@ static inline struct cfq_group *cfqg_of_blkg(struct blkio_group *blkg)
return NULL;
}
-void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
- unsigned int weight)
+static void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
+ unsigned int weight)
{
struct cfq_group *cfqg = cfqg_of_blkg(blkg);
cfqg->new_weight = weight;
@@ -1059,6 +1068,8 @@ static struct cfq_group * cfq_alloc_cfqg(struct cfq_data *cfqd)
*st = CFQ_RB_ROOT;
RB_CLEAR_NODE(&cfqg->rb_node);
+ cfqg->ttime.last_end_request = jiffies;
+
/*
* Take the initial reference that will be released on destroy
* This can be thought of a joint reference by cgroup and
@@ -1235,7 +1246,7 @@ static void cfq_release_cfq_groups(struct cfq_data *cfqd)
* it should not be NULL as even if elevator was exiting, cgroup deltion
* path got to it first.
*/
-void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg)
+static void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg)
{
unsigned long flags;
struct cfq_data *cfqd = key;
@@ -1502,16 +1513,11 @@ static void cfq_add_rq_rb(struct request *rq)
{
struct cfq_queue *cfqq = RQ_CFQQ(rq);
struct cfq_data *cfqd = cfqq->cfqd;
- struct request *__alias, *prev;
+ struct request *prev;
cfqq->queued[rq_is_sync(rq)]++;
- /*
- * looks a little odd, but the first insert might return an alias.
- * if that happens, put the alias on the dispatch list
- */
- while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
- cfq_dispatch_insert(cfqd->queue, __alias);
+ elv_rb_add(&cfqq->sort_list, rq);
if (!cfq_cfqq_on_rr(cfqq))
cfq_add_cfqq_rr(cfqd, cfqq);
@@ -1598,10 +1604,6 @@ static void cfq_remove_request(struct request *rq)
cfqq->cfqd->rq_queued--;
cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
rq_data_dir(rq), rq_is_sync(rq));
- if (rq->cmd_flags & REQ_META) {
- WARN_ON(!cfqq->meta_pending);
- cfqq->meta_pending--;
- }
}
static int cfq_merge(struct request_queue *q, struct request **req,
@@ -1969,7 +1971,8 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
* Otherwise, we do only if they are the last ones
* in their service tree.
*/
- if (service_tree->count == 1 && cfq_cfqq_sync(cfqq))
+ if (service_tree->count == 1 && cfq_cfqq_sync(cfqq) &&
+ !cfq_io_thinktime_big(cfqd, &service_tree->ttime, false))
return true;
cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
service_tree->count);
@@ -2022,10 +2025,10 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
* slice, then don't idle. This avoids overrunning the allotted
* time slice.
*/
- if (sample_valid(cic->ttime_samples) &&
- (cfqq->slice_end - jiffies < cic->ttime_mean)) {
+ if (sample_valid(cic->ttime.ttime_samples) &&
+ (cfqq->slice_end - jiffies < cic->ttime.ttime_mean)) {
cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%lu",
- cic->ttime_mean);
+ cic->ttime.ttime_mean);
return;
}
@@ -2381,8 +2384,9 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
* this group, wait for requests to complete.
*/
check_group_idle:
- if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1
- && cfqq->cfqg->dispatched) {
+ if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1 &&
+ cfqq->cfqg->dispatched &&
+ !cfq_io_thinktime_big(cfqd, &cfqq->cfqg->ttime, true)) {
cfqq = NULL;
goto keep_queue;
}
@@ -2833,7 +2837,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
cfqd->queue->node);
if (cic) {
- cic->last_end_request = jiffies;
+ cic->ttime.last_end_request = jiffies;
INIT_LIST_HEAD(&cic->queue_list);
INIT_HLIST_NODE(&cic->cic_list);
cic->dtor = cfq_free_io_context;
@@ -2883,7 +2887,6 @@ static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc)
* elevate the priority of this queue
*/
cfqq->org_ioprio = cfqq->ioprio;
- cfqq->org_ioprio_class = cfqq->ioprio_class;
cfq_clear_cfqq_prio_changed(cfqq);
}
@@ -3221,14 +3224,28 @@ err:
}
static void
-cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
+__cfq_update_io_thinktime(struct cfq_ttime *ttime, unsigned long slice_idle)
{
- unsigned long elapsed = jiffies - cic->last_end_request;
- unsigned long ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
+ unsigned long elapsed = jiffies - ttime->last_end_request;
+ elapsed = min(elapsed, 2UL * slice_idle);
- cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
- cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
- cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
+ ttime->ttime_samples = (7*ttime->ttime_samples + 256) / 8;
+ ttime->ttime_total = (7*ttime->ttime_total + 256*elapsed) / 8;
+ ttime->ttime_mean = (ttime->ttime_total + 128) / ttime->ttime_samples;
+}
+
+static void
+cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+ struct cfq_io_context *cic)
+{
+ if (cfq_cfqq_sync(cfqq)) {
+ __cfq_update_io_thinktime(&cic->ttime, cfqd->cfq_slice_idle);
+ __cfq_update_io_thinktime(&cfqq->service_tree->ttime,
+ cfqd->cfq_slice_idle);
+ }
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+ __cfq_update_io_thinktime(&cfqq->cfqg->ttime, cfqd->cfq_group_idle);
+#endif
}
static void
@@ -3277,8 +3294,8 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
else if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
(!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq)))
enable_idle = 0;
- else if (sample_valid(cic->ttime_samples)) {
- if (cic->ttime_mean > cfqd->cfq_slice_idle)
+ else if (sample_valid(cic->ttime.ttime_samples)) {
+ if (cic->ttime.ttime_mean > cfqd->cfq_slice_idle)
enable_idle = 0;
else
enable_idle = 1;
@@ -3340,13 +3357,6 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
return true;
/*
- * So both queues are sync. Let the new request get disk time if
- * it's a metadata request and the current queue is doing regular IO.
- */
- if ((rq->cmd_flags & REQ_META) && !cfqq->meta_pending)
- return true;
-
- /*
* Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice.
*/
if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
@@ -3410,10 +3420,8 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_io_context *cic = RQ_CIC(rq);
cfqd->rq_queued++;
- if (rq->cmd_flags & REQ_META)
- cfqq->meta_pending++;
- cfq_update_io_thinktime(cfqd, cic);
+ cfq_update_io_thinktime(cfqd, cfqq, cic);
cfq_update_io_seektime(cfqd, cfqq, rq);
cfq_update_idle_window(cfqd, cfqq, cic);
@@ -3520,12 +3528,16 @@ static bool cfq_should_wait_busy(struct cfq_data *cfqd, struct cfq_queue *cfqq)
if (cfqq->cfqg->nr_cfqq > 1)
return false;
+ /* the only queue in the group, but think time is big */
+ if (cfq_io_thinktime_big(cfqd, &cfqq->cfqg->ttime, true))
+ return false;
+
if (cfq_slice_used(cfqq))
return true;
/* if slice left is less than think time, wait busy */
- if (cic && sample_valid(cic->ttime_samples)
- && (cfqq->slice_end - jiffies < cic->ttime_mean))
+ if (cic && sample_valid(cic->ttime.ttime_samples)
+ && (cfqq->slice_end - jiffies < cic->ttime.ttime_mean))
return true;
/*
@@ -3566,11 +3578,24 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
if (sync) {
- RQ_CIC(rq)->last_end_request = now;
+ struct cfq_rb_root *service_tree;
+
+ RQ_CIC(rq)->ttime.last_end_request = now;
+
+ if (cfq_cfqq_on_rr(cfqq))
+ service_tree = cfqq->service_tree;
+ else
+ service_tree = service_tree_for(cfqq->cfqg,
+ cfqq_prio(cfqq), cfqq_type(cfqq));
+ service_tree->ttime.last_end_request = now;
if (!time_after(rq->start_time + cfqd->cfq_fifo_expire[1], now))
cfqd->last_delayed_sync = now;
}
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+ cfqq->cfqg->ttime.last_end_request = now;
+#endif
+
/*
* If this is the active queue, check if it needs to be expired,
* or if we want to idle in case it has no pending requests.
@@ -3616,30 +3641,6 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
cfq_schedule_dispatch(cfqd);
}
-/*
- * we temporarily boost lower priority queues if they are holding fs exclusive
- * resources. they are boosted to normal prio (CLASS_BE/4)
- */
-static void cfq_prio_boost(struct cfq_queue *cfqq)
-{
- if (has_fs_excl()) {
- /*
- * boost idle prio on transactions that would lock out other
- * users of the filesystem
- */
- if (cfq_class_idle(cfqq))
- cfqq->ioprio_class = IOPRIO_CLASS_BE;
- if (cfqq->ioprio > IOPRIO_NORM)
- cfqq->ioprio = IOPRIO_NORM;
- } else {
- /*
- * unboost the queue (if needed)
- */
- cfqq->ioprio_class = cfqq->org_ioprio_class;
- cfqq->ioprio = cfqq->org_ioprio;
- }
-}
-
static inline int __cfq_may_queue(struct cfq_queue *cfqq)
{
if (cfq_cfqq_wait_request(cfqq) && !cfq_cfqq_must_alloc_slice(cfqq)) {
@@ -3670,7 +3671,6 @@ static int cfq_may_queue(struct request_queue *q, int rw)
cfqq = cic_to_cfqq(cic, rw_is_sync(rw));
if (cfqq) {
cfq_init_prio_data(cfqq, cic->ioc);
- cfq_prio_boost(cfqq);
return __cfq_may_queue(cfqq);
}
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index cc3eb78e333a..7b725020823c 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -208,19 +208,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
#define BLKBSZSET_32 _IOW(0x12, 113, int)
#define BLKGETSIZE64_32 _IOR(0x12, 114, int)
-struct compat_floppy_struct {
- compat_uint_t size;
- compat_uint_t sect;
- compat_uint_t head;
- compat_uint_t track;
- compat_uint_t stretch;
- unsigned char gap;
- unsigned char rate;
- unsigned char spec1;
- unsigned char fmt_gap;
- const compat_caddr_t name;
-};
-
struct compat_floppy_drive_params {
char cmos;
compat_ulong_t max_dtr;
@@ -288,7 +275,6 @@ struct compat_floppy_write_errors {
#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
-#define FDGETPRM32 _IOR(2, 0x04, struct compat_floppy_struct)
#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 5139c0ea1864..c644137d9cd6 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -77,10 +77,8 @@ static void
deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
{
struct rb_root *root = deadline_rb_root(dd, rq);
- struct request *__alias;
- while (unlikely(__alias = elv_rb_add(root, rq)))
- deadline_move_request(dd, __alias);
+ elv_rb_add(root, rq);
}
static inline void
diff --git a/block/elevator.c b/block/elevator.c
index b0b38ce0dcb6..a3b64bc71d88 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -353,7 +353,7 @@ static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
* RB-tree support functions for inserting/lookup/removal of requests
* in a sorted RB tree.
*/
-struct request *elv_rb_add(struct rb_root *root, struct request *rq)
+void elv_rb_add(struct rb_root *root, struct request *rq)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
@@ -365,15 +365,12 @@ struct request *elv_rb_add(struct rb_root *root, struct request *rq)
if (blk_rq_pos(rq) < blk_rq_pos(__rq))
p = &(*p)->rb_left;
- else if (blk_rq_pos(rq) > blk_rq_pos(__rq))
+ else if (blk_rq_pos(rq) >= blk_rq_pos(__rq))
p = &(*p)->rb_right;
- else
- return __rq;
}
rb_link_node(&rq->rb_node, parent, p);
rb_insert_color(&rq->rb_node, root);
- return NULL;
}
EXPORT_SYMBOL(elv_rb_add);
diff --git a/block/genhd.c b/block/genhd.c
index 3608289c8ecd..5cb51c55f6d8 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -602,7 +602,7 @@ void add_disk(struct gendisk *disk)
disk->major = MAJOR(devt);
disk->first_minor = MINOR(devt);
- /* Register BDI before referencing it from bdev */
+ /* Register BDI before referencing it from bdev */
bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, disk_devt(disk));
@@ -1018,14 +1018,6 @@ static const struct attribute_group *disk_attr_groups[] = {
NULL
};
-static void disk_free_ptbl_rcu_cb(struct rcu_head *head)
-{
- struct disk_part_tbl *ptbl =
- container_of(head, struct disk_part_tbl, rcu_head);
-
- kfree(ptbl);
-}
-
/**
* disk_replace_part_tbl - replace disk->part_tbl in RCU-safe way
* @disk: disk to replace part_tbl for
@@ -1046,7 +1038,7 @@ static void disk_replace_part_tbl(struct gendisk *disk,
if (old_ptbl) {
rcu_assign_pointer(old_ptbl->last_lookup, NULL);
- call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
+ kfree_rcu(old_ptbl, rcu_head);
}
}
@@ -1148,7 +1140,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
"wsect wuse running use aveq"
"\n\n");
*/
-
+
disk_part_iter_init(&piter, gp, DISK_PITER_INCL_EMPTY_PART0);
while ((hd = disk_part_iter_next(&piter))) {
cpu = part_stat_lock();
@@ -1172,7 +1164,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
);
}
disk_part_iter_exit(&piter);
-
+
return 0;
}
@@ -1500,30 +1492,32 @@ void disk_unblock_events(struct gendisk *disk)
}
/**
- * disk_check_events - schedule immediate event checking
- * @disk: disk to check events for
+ * disk_flush_events - schedule immediate event checking and flushing
+ * @disk: disk to check and flush events for
+ * @mask: events to flush
*
- * Schedule immediate event checking on @disk if not blocked.
+ * Schedule immediate event checking on @disk if not blocked. Events in
+ * @mask are scheduled to be cleared from the driver. Note that this
+ * doesn't clear the events from @disk->ev.
*
* CONTEXT:
- * Don't care. Safe to call from irq context.
+ * If @mask is non-zero must be called with bdev->bd_mutex held.
*/
-void disk_check_events(struct gendisk *disk)
+void disk_flush_events(struct gendisk *disk, unsigned int mask)
{
struct disk_events *ev = disk->ev;
- unsigned long flags;
if (!ev)
return;
- spin_lock_irqsave(&ev->lock, flags);
+ spin_lock_irq(&ev->lock);
+ ev->clearing |= mask;
if (!ev->block) {
cancel_delayed_work(&ev->dwork);
queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
}
- spin_unlock_irqrestore(&ev->lock, flags);
+ spin_unlock_irq(&ev->lock);
}
-EXPORT_SYMBOL_GPL(disk_check_events);
/**
* disk_clear_events - synchronously check, clear and return pending events
@@ -1713,7 +1707,7 @@ static int disk_events_set_dfl_poll_msecs(const char *val,
mutex_lock(&disk_events_mutex);
list_for_each_entry(ev, &disk_events, node)
- disk_check_events(ev->disk);
+ disk_flush_events(ev->disk, 0);
mutex_unlock(&disk_events_mutex);
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 87b22ca9c223..ae27b7534ea7 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -354,7 +354,7 @@ config CRYPTO_RMD128
RIPEMD-128 (ISO/IEC 10118-3:2004).
RIPEMD-128 is a 128-bit cryptographic hash function. It should only
- to be used as a secure replacement for RIPEMD. For other use cases
+ be used as a secure replacement for RIPEMD. For other use cases,
RIPEMD-160 should be used.
Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
@@ -458,7 +458,7 @@ config CRYPTO_WP512
config CRYPTO_GHASH_CLMUL_NI_INTEL
tristate "GHASH digest algorithm (CLMUL-NI accelerated)"
- depends on (X86 || UML_X86) && 64BIT
+ depends on X86 && 64BIT
select CRYPTO_SHASH
select CRYPTO_CRYPTD
help
@@ -533,7 +533,7 @@ config CRYPTO_AES_X86_64
config CRYPTO_AES_NI_INTEL
tristate "AES cipher algorithms (AES-NI)"
- depends on (X86 || UML_X86)
+ depends on X86
select CRYPTO_AES_X86_64 if 64BIT
select CRYPTO_AES_586 if !64BIT
select CRYPTO_CRYPTD
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 940d70cb5c25..ac33d5f30778 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -12,7 +12,7 @@
*
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <crypto/if_alg.h>
#include <linux/crypto.h>
#include <linux/init.h>
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 62122a1a2f7a..ef5356cd280a 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -68,8 +68,10 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
int newlen;
newlen = af_alg_make_sg(&ctx->sgl, from, len, 0);
- if (newlen < 0)
+ if (newlen < 0) {
+ err = copied ? 0 : newlen;
goto unlock;
+ }
ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL,
newlen);
diff --git a/crypto/arc4.c b/crypto/arc4.c
index 8be47e13a9e3..0d12a96da1d8 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -1,4 +1,4 @@
-/*
+/*
* Cryptographic API
*
* ARC4 Cipher Algorithm
@@ -33,16 +33,15 @@ static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
ctx->x = 1;
ctx->y = 0;
- for(i = 0; i < 256; i++)
+ for (i = 0; i < 256; i++)
ctx->S[i] = i;
- for(i = 0; i < 256; i++)
- {
+ for (i = 0; i < 256; i++) {
u8 a = ctx->S[i];
j = (j + in_key[k] + a) & 0xff;
ctx->S[i] = ctx->S[j];
ctx->S[j] = a;
- if(++k >= key_len)
+ if (++k >= key_len)
k = 0;
}
@@ -80,9 +79,9 @@ static struct crypto_alg arc4_alg = {
.cra_u = { .cipher = {
.cia_min_keysize = ARC4_MIN_KEY_SIZE,
.cia_max_keysize = ARC4_MAX_KEY_SIZE,
- .cia_setkey = arc4_set_key,
- .cia_encrypt = arc4_crypt,
- .cia_decrypt = arc4_crypt } }
+ .cia_setkey = arc4_set_key,
+ .cia_encrypt = arc4_crypt,
+ .cia_decrypt = arc4_crypt } }
};
static int __init arc4_init(void)
diff --git a/crypto/async_tx/raid6test.c b/crypto/async_tx/raid6test.c
index c1321935ebcc..c88ff9e3fd30 100644
--- a/crypto/async_tx/raid6test.c
+++ b/crypto/async_tx/raid6test.c
@@ -21,6 +21,7 @@
*/
#include <linux/async_tx.h>
#include <linux/gfp.h>
+#include <linux/mm.h>
#include <linux/random.h>
#undef pr
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index de9e55c29794..3f9ad2801052 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -224,11 +224,11 @@ static int crc32c_cra_init(struct crypto_tfm *tfm)
static struct shash_alg alg = {
.digestsize = CHKSUM_DIGEST_SIZE,
.setkey = chksum_setkey,
- .init = chksum_init,
- .update = chksum_update,
- .final = chksum_final,
- .finup = chksum_finup,
- .digest = chksum_digest,
+ .init = chksum_init,
+ .update = chksum_update,
+ .final = chksum_final,
+ .finup = chksum_finup,
+ .digest = chksum_digest,
.descsize = sizeof(struct chksum_desc_ctx),
.base = {
.cra_name = "crc32c",
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
index df35e4ccd07e..5276607c72d0 100644
--- a/crypto/gf128mul.c
+++ b/crypto/gf128mul.c
@@ -182,7 +182,7 @@ void gf128mul_lle(be128 *r, const be128 *b)
for (i = 0; i < 7; ++i)
gf128mul_x_lle(&p[i + 1], &p[i]);
- memset(r, 0, sizeof(r));
+ memset(r, 0, sizeof(*r));
for (i = 0;;) {
u8 ch = ((u8 *)b)[15 - i];
@@ -220,7 +220,7 @@ void gf128mul_bbe(be128 *r, const be128 *b)
for (i = 0; i < 7; ++i)
gf128mul_x_bbe(&p[i + 1], &p[i]);
- memset(r, 0, sizeof(r));
+ memset(r, 0, sizeof(*r));
for (i = 0;;) {
u8 ch = ((u8 *)b)[i];
diff --git a/crypto/proc.c b/crypto/proc.c
index 58fef67d4f4d..3808697814d7 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -13,7 +13,7 @@
*
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/rwsem.h>
diff --git a/crypto/rng.c b/crypto/rng.c
index f93cb5311182..45229ae782be 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -12,7 +12,7 @@
*
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <crypto/internal/rng.h>
#include <linux/err.h>
#include <linux/module.h>
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 0416091bf45a..00ae60eb9254 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -43,25 +43,26 @@ static int sha1_update(struct shash_desc *desc, const u8 *data,
unsigned int partial, done;
const u8 *src;
- partial = sctx->count & 0x3f;
+ partial = sctx->count % SHA1_BLOCK_SIZE;
sctx->count += len;
done = 0;
src = data;
- if ((partial + len) > 63) {
+ if ((partial + len) >= SHA1_BLOCK_SIZE) {
u32 temp[SHA_WORKSPACE_WORDS];
if (partial) {
done = -partial;
- memcpy(sctx->buffer + partial, data, done + 64);
+ memcpy(sctx->buffer + partial, data,
+ done + SHA1_BLOCK_SIZE);
src = sctx->buffer;
}
do {
sha_transform(sctx->state, src, temp);
- done += 64;
+ done += SHA1_BLOCK_SIZE;
src = data + done;
- } while (done + 63 < len);
+ } while (done + SHA1_BLOCK_SIZE <= len);
memset(temp, 0, sizeof(temp));
partial = 0;
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 27e60619538e..27adc92842ba 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -2976,8 +2976,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
#define AES_CBC_DEC_TEST_VECTORS 4
#define AES_LRW_ENC_TEST_VECTORS 8
#define AES_LRW_DEC_TEST_VECTORS 8
-#define AES_XTS_ENC_TEST_VECTORS 4
-#define AES_XTS_DEC_TEST_VECTORS 4
+#define AES_XTS_ENC_TEST_VECTORS 5
+#define AES_XTS_DEC_TEST_VECTORS 5
#define AES_CTR_ENC_TEST_VECTORS 3
#define AES_CTR_DEC_TEST_VECTORS 3
#define AES_OFB_ENC_TEST_VECTORS 1
@@ -3926,6 +3926,150 @@ static struct cipher_testvec aes_xts_enc_tv_template[] = {
"\x0a\x28\x2d\xf9\x20\x14\x7b\xea"
"\xbe\x42\x1e\xe5\x31\x9d\x05\x68",
.rlen = 512,
+ }, { /* XTS-AES 10, XTS-AES-256, data unit 512 bytes */
+ .key = "\x27\x18\x28\x18\x28\x45\x90\x45"
+ "\x23\x53\x60\x28\x74\x71\x35\x26"
+ "\x62\x49\x77\x57\x24\x70\x93\x69"
+ "\x99\x59\x57\x49\x66\x96\x76\x27"
+ "\x31\x41\x59\x26\x53\x58\x97\x93"
+ "\x23\x84\x62\x64\x33\x83\x27\x95"
+ "\x02\x88\x41\x97\x16\x93\x99\x37"
+ "\x51\x05\x82\x09\x74\x94\x45\x92",
+ .klen = 64,
+ .iv = "\xff\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x20\x21\x22\x23\x24\x25\x26\x27"
+ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+ "\x30\x31\x32\x33\x34\x35\x36\x37"
+ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+ "\x40\x41\x42\x43\x44\x45\x46\x47"
+ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+ "\x50\x51\x52\x53\x54\x55\x56\x57"
+ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+ "\x60\x61\x62\x63\x64\x65\x66\x67"
+ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+ "\x70\x71\x72\x73\x74\x75\x76\x77"
+ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+ "\x80\x81\x82\x83\x84\x85\x86\x87"
+ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x20\x21\x22\x23\x24\x25\x26\x27"
+ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+ "\x30\x31\x32\x33\x34\x35\x36\x37"
+ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+ "\x40\x41\x42\x43\x44\x45\x46\x47"
+ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+ "\x50\x51\x52\x53\x54\x55\x56\x57"
+ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+ "\x60\x61\x62\x63\x64\x65\x66\x67"
+ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+ "\x70\x71\x72\x73\x74\x75\x76\x77"
+ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+ "\x80\x81\x82\x83\x84\x85\x86\x87"
+ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .ilen = 512,
+ .result = "\x1c\x3b\x3a\x10\x2f\x77\x03\x86"
+ "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b"
+ "\xea\x00\x80\x3f\x5e\x48\x23\x57"
+ "\xa4\xae\x12\xd4\x14\xa3\xe6\x3b"
+ "\x5d\x31\xe2\x76\xf8\xfe\x4a\x8d"
+ "\x66\xb3\x17\xf9\xac\x68\x3f\x44"
+ "\x68\x0a\x86\xac\x35\xad\xfc\x33"
+ "\x45\xbe\xfe\xcb\x4b\xb1\x88\xfd"
+ "\x57\x76\x92\x6c\x49\xa3\x09\x5e"
+ "\xb1\x08\xfd\x10\x98\xba\xec\x70"
+ "\xaa\xa6\x69\x99\xa7\x2a\x82\xf2"
+ "\x7d\x84\x8b\x21\xd4\xa7\x41\xb0"
+ "\xc5\xcd\x4d\x5f\xff\x9d\xac\x89"
+ "\xae\xba\x12\x29\x61\xd0\x3a\x75"
+ "\x71\x23\xe9\x87\x0f\x8a\xcf\x10"
+ "\x00\x02\x08\x87\x89\x14\x29\xca"
+ "\x2a\x3e\x7a\x7d\x7d\xf7\xb1\x03"
+ "\x55\x16\x5c\x8b\x9a\x6d\x0a\x7d"
+ "\xe8\xb0\x62\xc4\x50\x0d\xc4\xcd"
+ "\x12\x0c\x0f\x74\x18\xda\xe3\xd0"
+ "\xb5\x78\x1c\x34\x80\x3f\xa7\x54"
+ "\x21\xc7\x90\xdf\xe1\xde\x18\x34"
+ "\xf2\x80\xd7\x66\x7b\x32\x7f\x6c"
+ "\x8c\xd7\x55\x7e\x12\xac\x3a\x0f"
+ "\x93\xec\x05\xc5\x2e\x04\x93\xef"
+ "\x31\xa1\x2d\x3d\x92\x60\xf7\x9a"
+ "\x28\x9d\x6a\x37\x9b\xc7\x0c\x50"
+ "\x84\x14\x73\xd1\xa8\xcc\x81\xec"
+ "\x58\x3e\x96\x45\xe0\x7b\x8d\x96"
+ "\x70\x65\x5b\xa5\xbb\xcf\xec\xc6"
+ "\xdc\x39\x66\x38\x0a\xd8\xfe\xcb"
+ "\x17\xb6\xba\x02\x46\x9a\x02\x0a"
+ "\x84\xe1\x8e\x8f\x84\x25\x20\x70"
+ "\xc1\x3e\x9f\x1f\x28\x9b\xe5\x4f"
+ "\xbc\x48\x14\x57\x77\x8f\x61\x60"
+ "\x15\xe1\x32\x7a\x02\xb1\x40\xf1"
+ "\x50\x5e\xb3\x09\x32\x6d\x68\x37"
+ "\x8f\x83\x74\x59\x5c\x84\x9d\x84"
+ "\xf4\xc3\x33\xec\x44\x23\x88\x51"
+ "\x43\xcb\x47\xbd\x71\xc5\xed\xae"
+ "\x9b\xe6\x9a\x2f\xfe\xce\xb1\xbe"
+ "\xc9\xde\x24\x4f\xbe\x15\x99\x2b"
+ "\x11\xb7\x7c\x04\x0f\x12\xbd\x8f"
+ "\x6a\x97\x5a\x44\xa0\xf9\x0c\x29"
+ "\xa9\xab\xc3\xd4\xd8\x93\x92\x72"
+ "\x84\xc5\x87\x54\xcc\xe2\x94\x52"
+ "\x9f\x86\x14\xdc\xd2\xab\xa9\x91"
+ "\x92\x5f\xed\xc4\xae\x74\xff\xac"
+ "\x6e\x33\x3b\x93\xeb\x4a\xff\x04"
+ "\x79\xda\x9a\x41\x0e\x44\x50\xe0"
+ "\xdd\x7a\xe4\xc6\xe2\x91\x09\x00"
+ "\x57\x5d\xa4\x01\xfc\x07\x05\x9f"
+ "\x64\x5e\x8b\x7e\x9b\xfd\xef\x33"
+ "\x94\x30\x54\xff\x84\x01\x14\x93"
+ "\xc2\x7b\x34\x29\xea\xed\xb4\xed"
+ "\x53\x76\x44\x1a\x77\xed\x43\x85"
+ "\x1a\xd7\x7f\x16\xf5\x41\xdf\xd2"
+ "\x69\xd5\x0d\x6a\x5f\x14\xfb\x0a"
+ "\xab\x1c\xbb\x4c\x15\x50\xbe\x97"
+ "\xf7\xab\x40\x66\x19\x3c\x4c\xaa"
+ "\x77\x3d\xad\x38\x01\x4b\xd2\x09"
+ "\x2f\xa7\x55\xc8\x24\xbb\x5e\x54"
+ "\xc4\xf3\x6f\xfd\xa9\xfc\xea\x70"
+ "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51",
+ .rlen = 512,
}
};
@@ -4123,6 +4267,151 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
+ }, { /* XTS-AES 10, XTS-AES-256, data unit 512 bytes */
+ .key = "\x27\x18\x28\x18\x28\x45\x90\x45"
+ "\x23\x53\x60\x28\x74\x71\x35\x26"
+ "\x62\x49\x77\x57\x24\x70\x93\x69"
+ "\x99\x59\x57\x49\x66\x96\x76\x27"
+ "\x31\x41\x59\x26\x53\x58\x97\x93"
+ "\x23\x84\x62\x64\x33\x83\x27\x95"
+ "\x02\x88\x41\x97\x16\x93\x99\x37"
+ "\x51\x05\x82\x09\x74\x94\x45\x92",
+ .klen = 64,
+ .iv = "\xff\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .input = "\x1c\x3b\x3a\x10\x2f\x77\x03\x86"
+ "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b"
+ "\xea\x00\x80\x3f\x5e\x48\x23\x57"
+ "\xa4\xae\x12\xd4\x14\xa3\xe6\x3b"
+ "\x5d\x31\xe2\x76\xf8\xfe\x4a\x8d"
+ "\x66\xb3\x17\xf9\xac\x68\x3f\x44"
+ "\x68\x0a\x86\xac\x35\xad\xfc\x33"
+ "\x45\xbe\xfe\xcb\x4b\xb1\x88\xfd"
+ "\x57\x76\x92\x6c\x49\xa3\x09\x5e"
+ "\xb1\x08\xfd\x10\x98\xba\xec\x70"
+ "\xaa\xa6\x69\x99\xa7\x2a\x82\xf2"
+ "\x7d\x84\x8b\x21\xd4\xa7\x41\xb0"
+ "\xc5\xcd\x4d\x5f\xff\x9d\xac\x89"
+ "\xae\xba\x12\x29\x61\xd0\x3a\x75"
+ "\x71\x23\xe9\x87\x0f\x8a\xcf\x10"
+ "\x00\x02\x08\x87\x89\x14\x29\xca"
+ "\x2a\x3e\x7a\x7d\x7d\xf7\xb1\x03"
+ "\x55\x16\x5c\x8b\x9a\x6d\x0a\x7d"
+ "\xe8\xb0\x62\xc4\x50\x0d\xc4\xcd"
+ "\x12\x0c\x0f\x74\x18\xda\xe3\xd0"
+ "\xb5\x78\x1c\x34\x80\x3f\xa7\x54"
+ "\x21\xc7\x90\xdf\xe1\xde\x18\x34"
+ "\xf2\x80\xd7\x66\x7b\x32\x7f\x6c"
+ "\x8c\xd7\x55\x7e\x12\xac\x3a\x0f"
+ "\x93\xec\x05\xc5\x2e\x04\x93\xef"
+ "\x31\xa1\x2d\x3d\x92\x60\xf7\x9a"
+ "\x28\x9d\x6a\x37\x9b\xc7\x0c\x50"
+ "\x84\x14\x73\xd1\xa8\xcc\x81\xec"
+ "\x58\x3e\x96\x45\xe0\x7b\x8d\x96"
+ "\x70\x65\x5b\xa5\xbb\xcf\xec\xc6"
+ "\xdc\x39\x66\x38\x0a\xd8\xfe\xcb"
+ "\x17\xb6\xba\x02\x46\x9a\x02\x0a"
+ "\x84\xe1\x8e\x8f\x84\x25\x20\x70"
+ "\xc1\x3e\x9f\x1f\x28\x9b\xe5\x4f"
+ "\xbc\x48\x14\x57\x77\x8f\x61\x60"
+ "\x15\xe1\x32\x7a\x02\xb1\x40\xf1"
+ "\x50\x5e\xb3\x09\x32\x6d\x68\x37"
+ "\x8f\x83\x74\x59\x5c\x84\x9d\x84"
+ "\xf4\xc3\x33\xec\x44\x23\x88\x51"
+ "\x43\xcb\x47\xbd\x71\xc5\xed\xae"
+ "\x9b\xe6\x9a\x2f\xfe\xce\xb1\xbe"
+ "\xc9\xde\x24\x4f\xbe\x15\x99\x2b"
+ "\x11\xb7\x7c\x04\x0f\x12\xbd\x8f"
+ "\x6a\x97\x5a\x44\xa0\xf9\x0c\x29"
+ "\xa9\xab\xc3\xd4\xd8\x93\x92\x72"
+ "\x84\xc5\x87\x54\xcc\xe2\x94\x52"
+ "\x9f\x86\x14\xdc\xd2\xab\xa9\x91"
+ "\x92\x5f\xed\xc4\xae\x74\xff\xac"
+ "\x6e\x33\x3b\x93\xeb\x4a\xff\x04"
+ "\x79\xda\x9a\x41\x0e\x44\x50\xe0"
+ "\xdd\x7a\xe4\xc6\xe2\x91\x09\x00"
+ "\x57\x5d\xa4\x01\xfc\x07\x05\x9f"
+ "\x64\x5e\x8b\x7e\x9b\xfd\xef\x33"
+ "\x94\x30\x54\xff\x84\x01\x14\x93"
+ "\xc2\x7b\x34\x29\xea\xed\xb4\xed"
+ "\x53\x76\x44\x1a\x77\xed\x43\x85"
+ "\x1a\xd7\x7f\x16\xf5\x41\xdf\xd2"
+ "\x69\xd5\x0d\x6a\x5f\x14\xfb\x0a"
+ "\xab\x1c\xbb\x4c\x15\x50\xbe\x97"
+ "\xf7\xab\x40\x66\x19\x3c\x4c\xaa"
+ "\x77\x3d\xad\x38\x01\x4b\xd2\x09"
+ "\x2f\xa7\x55\xc8\x24\xbb\x5e\x54"
+ "\xc4\xf3\x6f\xfd\xa9\xfc\xea\x70"
+ "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51",
+ .ilen = 512,
+ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x20\x21\x22\x23\x24\x25\x26\x27"
+ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+ "\x30\x31\x32\x33\x34\x35\x36\x37"
+ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+ "\x40\x41\x42\x43\x44\x45\x46\x47"
+ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+ "\x50\x51\x52\x53\x54\x55\x56\x57"
+ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+ "\x60\x61\x62\x63\x64\x65\x66\x67"
+ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+ "\x70\x71\x72\x73\x74\x75\x76\x77"
+ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+ "\x80\x81\x82\x83\x84\x85\x86\x87"
+ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x20\x21\x22\x23\x24\x25\x26\x27"
+ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+ "\x30\x31\x32\x33\x34\x35\x36\x37"
+ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+ "\x40\x41\x42\x43\x44\x45\x46\x47"
+ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+ "\x50\x51\x52\x53\x54\x55\x56\x57"
+ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+ "\x60\x61\x62\x63\x64\x65\x66\x67"
+ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+ "\x70\x71\x72\x73\x74\x75\x76\x77"
+ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+ "\x80\x81\x82\x83\x84\x85\x86\x87"
+ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .rlen = 512,
+
}
};
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 3bb154d8c8cc..95b9e7eefadc 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -94,8 +94,6 @@ source "drivers/memstick/Kconfig"
source "drivers/leds/Kconfig"
-source "drivers/nfc/Kconfig"
-
source "drivers/accessibility/Kconfig"
source "drivers/infiniband/Kconfig"
@@ -114,6 +112,8 @@ source "drivers/uio/Kconfig"
source "drivers/vlynq/Kconfig"
+source "drivers/virtio/Kconfig"
+
source "drivers/xen/Kconfig"
source "drivers/staging/Kconfig"
@@ -126,4 +126,8 @@ source "drivers/hwspinlock/Kconfig"
source "drivers/clocksource/Kconfig"
+source "drivers/iommu/Kconfig"
+
+source "drivers/virt/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 09f3232bcdcd..7fa433a7030c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -122,3 +122,8 @@ obj-y += ieee802154/
obj-y += clk/
obj-$(CONFIG_HWSPINLOCK) += hwspinlock/
+obj-$(CONFIG_NFC) += nfc/
+obj-$(CONFIG_IOMMU_SUPPORT) += iommu/
+
+# Virtualization drivers
+obj-$(CONFIG_VIRT_DRIVERS) += virt/
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 58c3f74bd84c..6512b20aeccd 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -89,7 +89,7 @@ struct acpi_ac {
unsigned long long state;
};
-#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
+#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)
#ifdef CONFIG_ACPI_PROCFS_POWER
static const struct file_operations acpi_ac_fops = {
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index fcc13ac0aa18..2c661353e8f2 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -132,7 +132,7 @@ struct acpi_battery {
unsigned long flags;
};
-#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
+#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
inline int acpi_battery_present(struct acpi_battery *battery)
{
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 51ae3794ec7f..50658ff887d9 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -112,7 +112,7 @@ struct acpi_battery {
u8 have_sysfs_alarm:1;
};
-#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
+#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
struct acpi_sbs {
struct power_supply charger;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index db39e9e607d8..ada4b4d9bdc8 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -46,7 +46,6 @@
#define PREFIX "ACPI: "
-#define ACPI_VIDEO_CLASS "video"
#define ACPI_VIDEO_BUS_NAME "Video Bus"
#define ACPI_VIDEO_DEVICE_NAME "Video Device"
#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
@@ -1445,7 +1444,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch,
* most likely via hotkey. */
acpi_bus_generate_proc_event(device, event, 0);
- keycode = KEY_SWITCHVIDEOMODE;
+ if (!acpi_notifier_call_chain(device, event, 0))
+ keycode = KEY_SWITCHVIDEOMODE;
break;
case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
@@ -1475,7 +1475,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
break;
}
- acpi_notifier_call_chain(device, event, 0);
+ if (event != ACPI_VIDEO_NOTIFY_SWITCH)
+ acpi_notifier_call_chain(device, event, 0);
if (keycode) {
input_report_key(input, keycode, 1);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 75afa75a515e..ca3e6be44a04 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -313,6 +313,7 @@ config PATA_AMD
config PATA_ARASAN_CF
tristate "ARASAN CompactFlash PATA Controller Support"
+ depends on DMADEVICES
select DMA_ENGINE
help
Say Y here to support the ARASAN CompactFlash PATA controller
diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
index ae22be4157b5..3bc8c79bf2c7 100644
--- a/drivers/ata/acard-ahci.c
+++ b/drivers/ata/acard-ahci.c
@@ -135,8 +135,8 @@ static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg
if (mesg.event & PM_EVENT_SUSPEND &&
hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
- dev_printk(KERN_ERR, &pdev->dev,
- "BIOS update required for suspend/resume\n");
+ dev_err(&pdev->dev,
+ "BIOS update required for suspend/resume\n");
return -EIO;
}
@@ -187,7 +187,7 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
+ dev_err(&pdev->dev,
"64-bit DMA enable failed\n");
return rc;
}
@@ -195,14 +195,13 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
} else {
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit consistent DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "32-bit consistent DMA enable failed\n");
return rc;
}
}
@@ -343,14 +342,12 @@ static int acard_ahci_port_start(struct ata_port *ap)
if (cmd & PORT_CMD_FBSCP)
pp->fbs_supported = true;
else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
- dev_printk(KERN_INFO, dev,
- "port %d can do FBS, forcing FBSCP\n",
- ap->port_no);
+ dev_info(dev, "port %d can do FBS, forcing FBSCP\n",
+ ap->port_no);
pp->fbs_supported = true;
} else
- dev_printk(KERN_WARNING, dev,
- "port %d is not capable of FBS\n",
- ap->port_no);
+ dev_warn(dev, "port %d is not capable of FBS\n",
+ ap->port_no);
}
if (pp->fbs_supported) {
@@ -406,7 +403,6 @@ static int acard_ahci_port_start(struct ata_port *ap)
static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
unsigned int board_id = ent->driver_data;
struct ata_port_info pi = acard_ahci_port_info[board_id];
const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -419,8 +415,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id
WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* acquire resources */
rc = pcim_enable_device(pdev);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 71afe0371311..fb7b90b05922 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -79,8 +79,6 @@ enum board_ids {
};
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
@@ -104,12 +102,6 @@ static struct ata_port_operations ahci_p5wdh_ops = {
.hardreset = ahci_p5wdh_hardreset,
};
-static struct ata_port_operations ahci_sb600_ops = {
- .inherits = &ahci_ops,
- .softreset = ahci_sb600_softreset,
- .pmp_softreset = ahci_sb600_softreset,
-};
-
#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
static const struct ata_port_info ahci_port_info[] = {
@@ -188,7 +180,7 @@ static const struct ata_port_info ahci_port_info[] = {
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
- .port_ops = &ahci_sb600_ops,
+ .port_ops = &ahci_pmp_retry_srst_ops,
},
[board_ahci_sb700] = /* for SB700 and SB800 */
{
@@ -196,7 +188,7 @@ static const struct ata_port_info ahci_port_info[] = {
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
- .port_ops = &ahci_sb600_ops,
+ .port_ops = &ahci_pmp_retry_srst_ops,
},
[board_ahci_vt8251] =
{
@@ -267,6 +259,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
+ { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -502,55 +495,6 @@ static void ahci_pci_init_controller(struct ata_host *host)
ahci_init_controller(host);
}
-static int ahci_sb600_check_ready(struct ata_link *link)
-{
- void __iomem *port_mmio = ahci_port_base(link->ap);
- u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
- u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
-
- /*
- * There is no need to check TFDATA if BAD PMP is found due to HW bug,
- * which can save timeout delay.
- */
- if (irq_status & PORT_IRQ_BAD_PMP)
- return -EIO;
-
- return ata_check_ready(status);
-}
-
-static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
-{
- struct ata_port *ap = link->ap;
- void __iomem *port_mmio = ahci_port_base(ap);
- int pmp = sata_srst_pmp(link);
- int rc;
- u32 irq_sts;
-
- DPRINTK("ENTER\n");
-
- rc = ahci_do_softreset(link, class, pmp, deadline,
- ahci_sb600_check_ready);
-
- /*
- * Soft reset fails on some ATI chips with IPMS set when PMP
- * is enabled but SATA HDD/ODD is connected to SATA port,
- * do soft reset again to port 0.
- */
- if (rc == -EIO) {
- irq_sts = readl(port_mmio + PORT_IRQ_STAT);
- if (irq_sts & PORT_IRQ_BAD_PMP) {
- ata_link_printk(link, KERN_WARNING,
- "applying SB600 PMP SRST workaround "
- "and retrying\n");
- rc = ahci_do_softreset(link, class, 0, deadline,
- ahci_check_ready);
- }
- }
-
- return rc;
-}
-
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
@@ -629,8 +573,8 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
if (mesg.event & PM_EVENT_SUSPEND &&
hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
- dev_printk(KERN_ERR, &pdev->dev,
- "BIOS update required for suspend/resume\n");
+ dev_err(&pdev->dev,
+ "BIOS update required for suspend/resume\n");
return -EIO;
}
@@ -681,22 +625,21 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "64-bit DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "64-bit DMA enable failed\n");
return rc;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit consistent DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "32-bit consistent DMA enable failed\n");
return rc;
}
}
@@ -759,8 +702,8 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
dmi_check_system(sysids)) {
struct ata_port *ap = host->ports[1];
- dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
- "Deluxe on-board SIMG4726 workaround\n");
+ dev_info(&pdev->dev,
+ "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
ap->ops = &ahci_p5wdh_ops;
ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
@@ -811,6 +754,18 @@ static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
},
},
+ /*
+ * All BIOS versions for the Asus M3A support 64bit DMA.
+ * (all release versions from 0301 to 1206 were tested)
+ */
+ {
+ .ident = "ASUS M3A",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR,
+ "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "M3A"),
+ },
+ },
{ }
};
const struct dmi_system_id *match;
@@ -831,14 +786,14 @@ static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
if (strcmp(buf, match->driver_data) >= 0)
goto enable_64bit;
else {
- dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
- "forcing 32bit DMA, update BIOS\n", match->ident);
+ dev_warn(&pdev->dev,
+ "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
+ match->ident);
return false;
}
enable_64bit:
- dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
- match->ident);
+ dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
return true;
}
@@ -1041,9 +996,8 @@ static void ahci_gtf_filter_workaround(struct ata_host *host)
return;
filter = (unsigned long)dmi->driver_data;
- dev_printk(KERN_INFO, host->dev,
- "applying extra ACPI _GTF filter 0x%x for %s\n",
- filter, dmi->ident);
+ dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
+ filter, dmi->ident);
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
@@ -1062,7 +1016,6 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
unsigned int board_id = ent->driver_data;
struct ata_port_info pi = ahci_port_info[board_id];
const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -1075,8 +1028,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* The AHCI driver can only drive the SATA ports, the PATA driver
can drive them all so if both drivers are selected make sure
@@ -1099,8 +1051,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
* that for SAS drives they're out of luck.
*/
if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
- dev_printk(KERN_INFO, &pdev->dev, "PDC42819 "
- "can only drive SATA devices with this driver\n");
+ dev_info(&pdev->dev,
+ "PDC42819 can only drive SATA devices with this driver\n");
/* acquire resources */
rc = pcim_enable_device(pdev);
@@ -1126,8 +1078,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
pci_read_config_byte(pdev, ICH_MAP, &map);
if (map & 0x3) {
- dev_printk(KERN_INFO, &pdev->dev, "controller is in "
- "combined mode, can't enable AHCI mode\n");
+ dev_info(&pdev->dev,
+ "controller is in combined mode, can't enable AHCI mode\n");
return -ENODEV;
}
}
@@ -1184,8 +1136,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ahci_broken_suspend(pdev)) {
hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
- dev_printk(KERN_WARNING, &pdev->dev,
- "BIOS update required for suspend/resume\n");
+ dev_warn(&pdev->dev,
+ "BIOS update required for suspend/resume\n");
}
if (ahci_broken_online(pdev)) {
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 12c5282e7fca..b1750007c8dc 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -312,6 +312,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
.sdev_attrs = ahci_sdev_attrs
extern struct ata_port_operations ahci_ops;
+extern struct ata_port_operations ahci_pmp_retry_srst_ops;
void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts);
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 721d38bfa339..7df56ec31819 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -81,14 +81,13 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);
}
- ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
- name);
+ ata_dev_info(dev, "configured for %s\n", name);
dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);
dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);
dev->flags &= ~ATA_DFLAG_PIO;
} else {
- ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+ ata_dev_info(dev, "configured for PIO\n");
dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO;
dev->flags |= ATA_DFLAG_PIO;
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 6f6e7718b05c..43107e9415da 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1225,8 +1225,9 @@ static int piix_pci_device_resume(struct pci_dev *pdev)
*/
rc = pci_reenable_device(pdev);
if (rc)
- dev_printk(KERN_ERR, &pdev->dev, "failed to enable "
- "device after resume (%d)\n", rc);
+ dev_err(&pdev->dev,
+ "failed to enable device after resume (%d)\n",
+ rc);
} else
rc = ata_pci_device_do_resume(pdev);
@@ -1303,9 +1304,11 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
no_piix_dma = 2;
}
if (no_piix_dma)
- dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
- if (no_piix_dma == 2)
- dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
+ dev_warn(&ata_dev->dev,
+ "450NX errata present, disabling IDE DMA%s\n",
+ no_piix_dma == 2 ? " - a BIOS update may resolve this"
+ : "");
+
return no_piix_dma;
}
@@ -1338,37 +1341,36 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
map = map_db->map[map_value & map_db->mask];
- dev_printk(KERN_INFO, &pdev->dev, "MAP [");
+ dev_info(&pdev->dev, "MAP [");
for (i = 0; i < 4; i++) {
switch (map[i]) {
case RV:
invalid_map = 1;
- printk(" XX");
+ pr_cont(" XX");
break;
case NA:
- printk(" --");
+ pr_cont(" --");
break;
case IDE:
WARN_ON((i & 1) || map[i + 1] != IDE);
pinfo[i / 2] = piix_port_info[ich_pata_100];
i++;
- printk(" IDE IDE");
+ pr_cont(" IDE IDE");
break;
default:
- printk(" P%d", map[i]);
+ pr_cont(" P%d", map[i]);
if (i & 1)
pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS;
break;
}
}
- printk(" ]\n");
+ pr_cont(" ]\n");
if (invalid_map)
- dev_printk(KERN_ERR, &pdev->dev,
- "invalid MAP value %u\n", map_value);
+ dev_err(&pdev->dev, "invalid MAP value %u\n", map_value);
return map;
}
@@ -1398,8 +1400,8 @@ static bool piix_no_sidpr(struct ata_host *host)
if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 &&
pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
pdev->subsystem_device == 0xb049) {
- dev_printk(KERN_WARNING, host->dev,
- "Samsung DB-P70 detected, disabling SIDPR\n");
+ dev_warn(host->dev,
+ "Samsung DB-P70 detected, disabling SIDPR\n");
return true;
}
@@ -1451,8 +1453,8 @@ static int __devinit piix_init_sidpr(struct ata_host *host)
piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
if ((scontrol & 0xf00) != 0x300) {
- dev_printk(KERN_INFO, host->dev, "SCR access via "
- "SIDPR is available but doesn't work\n");
+ dev_info(host->dev,
+ "SCR access via SIDPR is available but doesn't work\n");
return 0;
}
}
@@ -1501,8 +1503,7 @@ static void piix_iocfg_bit18_quirk(struct ata_host *host)
* affected systems.
*/
if (hpriv->saved_iocfg & (1 << 18)) {
- dev_printk(KERN_INFO, &pdev->dev,
- "applying IOCFG bit18 quirk\n");
+ dev_info(&pdev->dev, "applying IOCFG bit18 quirk\n");
pci_write_config_dword(pdev, PIIX_IOCFG,
hpriv->saved_iocfg & ~(1 << 18));
}
@@ -1561,7 +1562,6 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev)
static int __devinit piix_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
struct device *dev = &pdev->dev;
struct ata_port_info port_info[2];
const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
@@ -1571,9 +1571,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
struct piix_host_priv *hpriv;
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* no hotplugging support for later devices (FIXME) */
if (!in_module_init && ent->driver_data >= ich5_sata)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 41223c7f0206..3c92dbd751e0 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -82,6 +82,8 @@ static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_detach(struct ata_port *ap);
static int ahci_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
+static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static void ahci_postreset(struct ata_link *link, unsigned int *class);
@@ -178,6 +180,12 @@ struct ata_port_operations ahci_ops = {
};
EXPORT_SYMBOL_GPL(ahci_ops);
+struct ata_port_operations ahci_pmp_retry_srst_ops = {
+ .inherits = &ahci_ops,
+ .softreset = ahci_pmp_retry_softreset,
+};
+EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
+
int ahci_em_messages = 1;
EXPORT_SYMBOL_GPL(ahci_em_messages);
module_param(ahci_em_messages, int, 0444);
@@ -286,10 +294,10 @@ static ssize_t ahci_read_em_buffer(struct device *dev,
/* the count should not be larger than PAGE_SIZE */
if (count > PAGE_SIZE) {
if (printk_ratelimit())
- ata_port_printk(ap, KERN_WARNING,
- "EM read buffer size too large: "
- "buffer size %u, page size %lu\n",
- hpriv->em_buf_sz, PAGE_SIZE);
+ ata_port_warn(ap,
+ "EM read buffer size too large: "
+ "buffer size %u, page size %lu\n",
+ hpriv->em_buf_sz, PAGE_SIZE);
count = PAGE_SIZE;
}
@@ -410,51 +418,46 @@ void ahci_save_initial_config(struct device *dev,
/* some chips have errata preventing 64bit use */
if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
- dev_printk(KERN_INFO, dev,
- "controller can't do 64bit DMA, forcing 32bit\n");
+ dev_info(dev, "controller can't do 64bit DMA, forcing 32bit\n");
cap &= ~HOST_CAP_64;
}
if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
- dev_printk(KERN_INFO, dev,
- "controller can't do NCQ, turning off CAP_NCQ\n");
+ dev_info(dev, "controller can't do NCQ, turning off CAP_NCQ\n");
cap &= ~HOST_CAP_NCQ;
}
if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
- dev_printk(KERN_INFO, dev,
- "controller can do NCQ, turning on CAP_NCQ\n");
+ dev_info(dev, "controller can do NCQ, turning on CAP_NCQ\n");
cap |= HOST_CAP_NCQ;
}
if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
- dev_printk(KERN_INFO, dev,
- "controller can't do PMP, turning off CAP_PMP\n");
+ dev_info(dev, "controller can't do PMP, turning off CAP_PMP\n");
cap &= ~HOST_CAP_PMP;
}
if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
- dev_printk(KERN_INFO, dev,
- "controller can't do SNTF, turning off CAP_SNTF\n");
+ dev_info(dev,
+ "controller can't do SNTF, turning off CAP_SNTF\n");
cap &= ~HOST_CAP_SNTF;
}
if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
- dev_printk(KERN_INFO, dev,
- "controller can do FBS, turning on CAP_FBS\n");
+ dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");
cap |= HOST_CAP_FBS;
}
if (force_port_map && port_map != force_port_map) {
- dev_printk(KERN_INFO, dev, "forcing port_map 0x%x -> 0x%x\n",
- port_map, force_port_map);
+ dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
+ port_map, force_port_map);
port_map = force_port_map;
}
if (mask_port_map) {
- dev_printk(KERN_WARNING, dev, "masking port_map 0x%x -> 0x%x\n",
- port_map,
- port_map & mask_port_map);
+ dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
+ port_map,
+ port_map & mask_port_map);
port_map &= mask_port_map;
}
@@ -470,10 +473,9 @@ void ahci_save_initial_config(struct device *dev,
* port_map and let it be generated from n_ports.
*/
if (map_ports > ahci_nr_ports(cap)) {
- dev_printk(KERN_WARNING, dev,
- "implemented port map (0x%x) contains more "
- "ports than nr_ports (%u), using nr_ports\n",
- port_map, ahci_nr_ports(cap));
+ dev_warn(dev,
+ "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n",
+ port_map, ahci_nr_ports(cap));
port_map = 0;
}
}
@@ -481,8 +483,7 @@ void ahci_save_initial_config(struct device *dev,
/* fabricate port_map from cap.nr_ports */
if (!port_map) {
port_map = (1 << ahci_nr_ports(cap)) - 1;
- dev_printk(KERN_WARNING, dev,
- "forcing PORTS_IMPL to 0x%x\n", port_map);
+ dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
/* write the fixed up value to the PI register */
hpriv->saved_port_map = port_map;
@@ -822,8 +823,8 @@ int ahci_reset_controller(struct ata_host *host)
HOST_RESET, 10, 1000);
if (tmp & HOST_RESET) {
- dev_printk(KERN_ERR, host->dev,
- "controller reset failed (0x%x)\n", tmp);
+ dev_err(host->dev, "controller reset failed (0x%x)\n",
+ tmp);
return -EIO;
}
@@ -835,8 +836,7 @@ int ahci_reset_controller(struct ata_host *host)
*/
ahci_restore_initial_config(host);
} else
- dev_printk(KERN_INFO, host->dev,
- "skipping global host reset\n");
+ dev_info(host->dev, "skipping global host reset\n");
return 0;
}
@@ -1132,8 +1132,8 @@ static void ahci_dev_config(struct ata_device *dev)
if (hpriv->flags & AHCI_HFLAG_SECT255) {
dev->max_sectors = 255;
- ata_dev_printk(dev, KERN_INFO,
- "SB600 AHCI: limiting to 255 sectors per cmd\n");
+ ata_dev_info(dev,
+ "SB600 AHCI: limiting to 255 sectors per cmd\n");
}
}
@@ -1257,8 +1257,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
/* prepare for SRST (AHCI-1.1 10.4.1) */
rc = ahci_kick_engine(ap);
if (rc && rc != -EOPNOTSUPP)
- ata_link_printk(link, KERN_WARNING,
- "failed to reset engine (errno=%d)\n", rc);
+ ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
ata_tf_init(link->device, &tf);
@@ -1291,8 +1290,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
* be trusted. Treat device readiness timeout as link
* offline.
*/
- ata_link_printk(link, KERN_INFO,
- "device not ready, treating as offline\n");
+ ata_link_info(link, "device not ready, treating as offline\n");
*class = ATA_DEV_NONE;
} else if (rc) {
/* link occupied, -ENODEV too is an error */
@@ -1305,7 +1303,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
return 0;
fail:
- ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
+ ata_link_err(link, "softreset failed (%s)\n", reason);
return rc;
}
@@ -1329,6 +1327,55 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,
}
EXPORT_SYMBOL_GPL(ahci_do_softreset);
+static int ahci_bad_pmp_check_ready(struct ata_link *link)
+{
+ void __iomem *port_mmio = ahci_port_base(link->ap);
+ u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
+ u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
+
+ /*
+ * There is no need to check TFDATA if BAD PMP is found due to HW bug,
+ * which can save timeout delay.
+ */
+ if (irq_status & PORT_IRQ_BAD_PMP)
+ return -EIO;
+
+ return ata_check_ready(status);
+}
+
+int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ int pmp = sata_srst_pmp(link);
+ int rc;
+ u32 irq_sts;
+
+ DPRINTK("ENTER\n");
+
+ rc = ahci_do_softreset(link, class, pmp, deadline,
+ ahci_bad_pmp_check_ready);
+
+ /*
+ * Soft reset fails with IPMS set when PMP is enabled but
+ * SATA HDD/ODD is connected to SATA port, do soft reset
+ * again to port 0.
+ */
+ if (rc == -EIO) {
+ irq_sts = readl(port_mmio + PORT_IRQ_STAT);
+ if (irq_sts & PORT_IRQ_BAD_PMP) {
+ ata_link_printk(link, KERN_WARNING,
+ "applying PMP SRST workaround "
+ "and retrying\n");
+ rc = ahci_do_softreset(link, class, 0, deadline,
+ ahci_check_ready);
+ }
+ }
+
+ return rc;
+}
+
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
@@ -1474,8 +1521,7 @@ static void ahci_fbs_dec_intr(struct ata_port *ap)
}
if (fbs & PORT_FBS_DEC)
- dev_printk(KERN_ERR, ap->host->dev,
- "failed to clear device error\n");
+ dev_err(ap->host->dev, "failed to clear device error\n");
}
static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
@@ -1713,8 +1759,8 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance)
} else {
VPRINTK("port %u (no irq)\n", i);
if (ata_ratelimit())
- dev_printk(KERN_WARNING, host->dev,
- "interrupt on disabled port %u\n", i);
+ dev_warn(host->dev,
+ "interrupt on disabled port %u\n", i);
}
handled = 1;
@@ -1865,11 +1911,11 @@ static void ahci_enable_fbs(struct ata_port *ap)
writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);
fbs = readl(port_mmio + PORT_FBS);
if (fbs & PORT_FBS_EN) {
- dev_printk(KERN_INFO, ap->host->dev, "FBS is enabled.\n");
+ dev_info(ap->host->dev, "FBS is enabled\n");
pp->fbs_enabled = true;
pp->fbs_last_dev = -1; /* initialization */
} else
- dev_printk(KERN_ERR, ap->host->dev, "Failed to enable FBS\n");
+ dev_err(ap->host->dev, "Failed to enable FBS\n");
ahci_start_engine(ap);
}
@@ -1897,9 +1943,9 @@ static void ahci_disable_fbs(struct ata_port *ap)
writel(fbs & ~PORT_FBS_EN, port_mmio + PORT_FBS);
fbs = readl(port_mmio + PORT_FBS);
if (fbs & PORT_FBS_EN)
- dev_printk(KERN_ERR, ap->host->dev, "Failed to disable FBS\n");
+ dev_err(ap->host->dev, "Failed to disable FBS\n");
else {
- dev_printk(KERN_INFO, ap->host->dev, "FBS is disabled.\n");
+ dev_info(ap->host->dev, "FBS is disabled\n");
pp->fbs_enabled = false;
}
@@ -1975,7 +2021,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
if (rc == 0)
ahci_power_down(ap);
else {
- ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
+ ata_port_err(ap, "%s (%d)\n", emsg, rc);
ahci_start_port(ap);
}
@@ -2003,14 +2049,12 @@ static int ahci_port_start(struct ata_port *ap)
if (cmd & PORT_CMD_FBSCP)
pp->fbs_supported = true;
else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
- dev_printk(KERN_INFO, dev,
- "port %d can do FBS, forcing FBSCP\n",
- ap->port_no);
+ dev_info(dev, "port %d can do FBS, forcing FBSCP\n",
+ ap->port_no);
pp->fbs_supported = true;
} else
- dev_printk(KERN_WARNING, dev,
- "port %d is not capable of FBS\n",
- ap->port_no);
+ dev_warn(dev, "port %d is not capable of FBS\n",
+ ap->port_no);
}
if (pp->fbs_supported) {
@@ -2072,7 +2116,7 @@ static void ahci_port_stop(struct ata_port *ap)
/* de-initialize port */
rc = ahci_deinit_port(ap, &emsg);
if (rc)
- ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
+ ata_port_warn(ap, "%s (%d)\n", emsg, rc);
}
void ahci_print_info(struct ata_host *host, const char *scc_s)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index a791b8ce6294..e0a5b555cee1 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -332,25 +332,22 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
rc = -EINVAL;
if (ACPI_FAILURE(status)) {
- ata_port_printk(ap, KERN_ERR,
- "ACPI get timing mode failed (AE 0x%x)\n",
- status);
+ ata_port_err(ap, "ACPI get timing mode failed (AE 0x%x)\n",
+ status);
goto out_free;
}
out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
- ata_port_printk(ap, KERN_WARNING,
- "_GTM returned unexpected object type 0x%x\n",
- out_obj->type);
+ ata_port_warn(ap, "_GTM returned unexpected object type 0x%x\n",
+ out_obj->type);
goto out_free;
}
if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) {
- ata_port_printk(ap, KERN_ERR,
- "_GTM returned invalid length %d\n",
- out_obj->buffer.length);
+ ata_port_err(ap, "_GTM returned invalid length %d\n",
+ out_obj->buffer.length);
goto out_free;
}
@@ -402,8 +399,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm)
if (status == AE_NOT_FOUND)
return -ENOENT;
if (ACPI_FAILURE(status)) {
- ata_port_printk(ap, KERN_ERR,
- "ACPI set timing mode failed (status=0x%x)\n", status);
+ ata_port_err(ap, "ACPI set timing mode failed (status=0x%x)\n",
+ status);
return -EINVAL;
}
return 0;
@@ -450,8 +447,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
- __func__, ap->port_no);
+ ata_dev_dbg(dev, "%s: ENTER: port#: %d\n",
+ __func__, ap->port_no);
/* _GTF has no input parameters */
status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
@@ -459,9 +456,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
- ata_dev_printk(dev, KERN_WARNING,
- "_GTF evaluation failed (AE 0x%x)\n",
- status);
+ ata_dev_warn(dev, "_GTF evaluation failed (AE 0x%x)\n",
+ status);
rc = -EINVAL;
}
goto out_free;
@@ -469,27 +465,24 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
if (!output.length || !output.pointer) {
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
- "length or ptr is NULL (0x%llx, 0x%p)\n",
- __func__,
- (unsigned long long)output.length,
- output.pointer);
+ ata_dev_dbg(dev, "%s: Run _GTF: length or ptr is NULL (0x%llx, 0x%p)\n",
+ __func__,
+ (unsigned long long)output.length,
+ output.pointer);
rc = -EINVAL;
goto out_free;
}
if (out_obj->type != ACPI_TYPE_BUFFER) {
- ata_dev_printk(dev, KERN_WARNING,
- "_GTF unexpected object type 0x%x\n",
- out_obj->type);
+ ata_dev_warn(dev, "_GTF unexpected object type 0x%x\n",
+ out_obj->type);
rc = -EINVAL;
goto out_free;
}
if (out_obj->buffer.length % REGS_PER_GTF) {
- ata_dev_printk(dev, KERN_WARNING,
- "unexpected _GTF length (%d)\n",
- out_obj->buffer.length);
+ ata_dev_warn(dev, "unexpected _GTF length (%d)\n",
+ out_obj->buffer.length);
rc = -EINVAL;
goto out_free;
}
@@ -499,9 +492,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
if (gtf) {
*gtf = (void *)out_obj->buffer.pointer;
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: returning gtf=%p, gtf_count=%d\n",
- __func__, *gtf, rc);
+ ata_dev_dbg(dev, "%s: returning gtf=%p, gtf_count=%d\n",
+ __func__, *gtf, rc);
}
return rc;
@@ -811,8 +803,8 @@ static int ata_acpi_push_id(struct ata_device *dev)
union acpi_object in_params[1];
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
- __func__, dev->devno, ap->port_no);
+ ata_dev_dbg(dev, "%s: ix = %d, port#: %d\n",
+ __func__, dev->devno, ap->port_no);
/* Give the drive Identify data to the drive via the _SDD method */
/* _SDD: set up input parameters */
@@ -832,8 +824,7 @@ static int ata_acpi_push_id(struct ata_device *dev)
return -ENOENT;
if (ACPI_FAILURE(status)) {
- ata_dev_printk(dev, KERN_WARNING,
- "ACPI _SDD failed (AE 0x%x)\n", status);
+ ata_dev_warn(dev, "ACPI _SDD failed (AE 0x%x)\n", status);
return -EIO;
}
@@ -983,8 +974,8 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
if (nr_executed) {
rc = ata_dev_reread_id(dev, 0);
if (rc < 0) {
- ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "
- "after ACPI commands\n");
+ ata_dev_err(dev,
+ "failed to IDENTIFY after ACPI commands\n");
return rc;
}
}
@@ -1002,8 +993,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
return rc;
}
- ata_dev_printk(dev, KERN_WARNING,
- "ACPI: failed the second time, disabled\n");
+ ata_dev_warn(dev, "ACPI: failed the second time, disabled\n");
dev->acpi_handle = NULL;
/* We can safely continue if no _GTF command has been executed
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 000d03ae6653..4a3a5ae7bb45 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -335,8 +335,7 @@ void ata_force_cbl(struct ata_port *ap)
continue;
ap->cbl = fe->param.cbl;
- ata_port_printk(ap, KERN_NOTICE,
- "FORCE: cable set to %s\n", fe->param.name);
+ ata_port_notice(ap, "FORCE: cable set to %s\n", fe->param.name);
return;
}
}
@@ -378,8 +377,7 @@ static void ata_force_link_limits(struct ata_link *link)
/* only honor the first spd limit */
if (!did_spd && fe->param.spd_limit) {
link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1;
- ata_link_printk(link, KERN_NOTICE,
- "FORCE: PHY spd limit set to %s\n",
+ ata_link_notice(link, "FORCE: PHY spd limit set to %s\n",
fe->param.name);
did_spd = true;
}
@@ -387,7 +385,7 @@ static void ata_force_link_limits(struct ata_link *link)
/* let lflags stack */
if (fe->param.lflags) {
link->flags |= fe->param.lflags;
- ata_link_printk(link, KERN_NOTICE,
+ ata_link_notice(link,
"FORCE: link flag 0x%x forced -> 0x%x\n",
fe->param.lflags, link->flags);
}
@@ -442,8 +440,8 @@ static void ata_force_xfermask(struct ata_device *dev)
dev->pio_mask = pio_mask;
}
- ata_dev_printk(dev, KERN_NOTICE,
- "FORCE: xfer_mask set to %s\n", fe->param.name);
+ ata_dev_notice(dev, "FORCE: xfer_mask set to %s\n",
+ fe->param.name);
return;
}
}
@@ -486,8 +484,8 @@ static void ata_force_horkage(struct ata_device *dev)
dev->horkage |= fe->param.horkage_on;
dev->horkage &= ~fe->param.horkage_off;
- ata_dev_printk(dev, KERN_NOTICE,
- "FORCE: horkage modified (%s)\n", fe->param.name);
+ ata_dev_notice(dev, "FORCE: horkage modified (%s)\n",
+ fe->param.name);
}
}
@@ -711,8 +709,8 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
sect = tf->lbal;
if (!sect) {
- ata_dev_printk(dev, KERN_WARNING, "device reported "
- "invalid CHS sector 0\n");
+ ata_dev_warn(dev,
+ "device reported invalid CHS sector 0\n");
sect = 1; /* oh well */
}
@@ -1230,8 +1228,9 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) {
- ata_dev_printk(dev, KERN_WARNING, "failed to read native "
- "max address (err_mask=0x%x)\n", err_mask);
+ ata_dev_warn(dev,
+ "failed to read native max address (err_mask=0x%x)\n",
+ err_mask);
if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
return -EACCES;
return -EIO;
@@ -1292,8 +1291,9 @@ static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors)
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) {
- ata_dev_printk(dev, KERN_WARNING, "failed to set "
- "max address (err_mask=0x%x)\n", err_mask);
+ ata_dev_warn(dev,
+ "failed to set max address (err_mask=0x%x)\n",
+ err_mask);
if (err_mask == AC_ERR_DEV &&
(tf.feature & (ATA_ABORTED | ATA_IDNF)))
return -EACCES;
@@ -1336,8 +1336,8 @@ static int ata_hpa_resize(struct ata_device *dev)
* be unlocked, skip HPA resizing.
*/
if (rc == -EACCES || !unlock_hpa) {
- ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
- "broken, skipping HPA handling\n");
+ ata_dev_warn(dev,
+ "HPA support seems broken, skipping HPA handling\n");
dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
/* we can continue if device aborted the command */
@@ -1355,14 +1355,13 @@ static int ata_hpa_resize(struct ata_device *dev)
return 0;
if (native_sectors > sectors)
- ata_dev_printk(dev, KERN_INFO,
+ ata_dev_info(dev,
"HPA detected: current %llu, native %llu\n",
(unsigned long long)sectors,
(unsigned long long)native_sectors);
else if (native_sectors < sectors)
- ata_dev_printk(dev, KERN_WARNING,
- "native sectors (%llu) is smaller than "
- "sectors (%llu)\n",
+ ata_dev_warn(dev,
+ "native sectors (%llu) is smaller than sectors (%llu)\n",
(unsigned long long)native_sectors,
(unsigned long long)sectors);
return 0;
@@ -1372,10 +1371,10 @@ static int ata_hpa_resize(struct ata_device *dev)
rc = ata_set_max_sectors(dev, native_sectors);
if (rc == -EACCES) {
/* if device aborted the command, skip HPA resizing */
- ata_dev_printk(dev, KERN_WARNING, "device aborted resize "
- "(%llu -> %llu), skipping HPA handling\n",
- (unsigned long long)sectors,
- (unsigned long long)native_sectors);
+ ata_dev_warn(dev,
+ "device aborted resize (%llu -> %llu), skipping HPA handling\n",
+ (unsigned long long)sectors,
+ (unsigned long long)native_sectors);
dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
return 0;
} else if (rc)
@@ -1384,14 +1383,14 @@ static int ata_hpa_resize(struct ata_device *dev)
/* re-read IDENTIFY data */
rc = ata_dev_reread_id(dev, 0);
if (rc) {
- ata_dev_printk(dev, KERN_ERR, "failed to re-read IDENTIFY "
- "data after HPA resizing\n");
+ ata_dev_err(dev,
+ "failed to re-read IDENTIFY data after HPA resizing\n");
return rc;
}
if (print_info) {
u64 new_sectors = ata_id_n_sectors(dev->id);
- ata_dev_printk(dev, KERN_INFO,
+ ata_dev_info(dev,
"HPA unlocked: %llu -> %llu, native %llu\n",
(unsigned long long)sectors,
(unsigned long long)new_sectors,
@@ -1655,8 +1654,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
ata_qc_complete(qc);
if (ata_msg_warn(ap))
- ata_dev_printk(dev, KERN_WARNING,
- "qc timeout (cmd 0x%x)\n", command);
+ ata_dev_warn(dev, "qc timeout (cmd 0x%x)\n",
+ command);
}
spin_unlock_irqrestore(ap->lock, flags);
@@ -1870,7 +1869,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
int rc;
if (ata_msg_ctl(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
+ ata_dev_dbg(dev, "%s: ENTER\n", __func__);
retry:
ata_tf_init(dev, &tf);
@@ -1909,14 +1908,13 @@ retry:
if (err_mask) {
if (err_mask & AC_ERR_NODEV_HINT) {
- ata_dev_printk(dev, KERN_DEBUG,
- "NODEV after polling detection\n");
+ ata_dev_dbg(dev, "NODEV after polling detection\n");
return -ENOENT;
}
if (is_semb) {
- ata_dev_printk(dev, KERN_INFO, "IDENTIFY failed on "
- "device w/ SEMB sig, disabled\n");
+ ata_dev_info(dev,
+ "IDENTIFY failed on device w/ SEMB sig, disabled\n");
/* SEMB is not supported yet */
*p_class = ATA_DEV_SEMB_UNSUP;
return 0;
@@ -1942,8 +1940,8 @@ retry:
* both flavors of IDENTIFYs which happens
* sometimes with phantom devices.
*/
- ata_dev_printk(dev, KERN_DEBUG,
- "both IDENTIFYs aborted, assuming NODEV\n");
+ ata_dev_dbg(dev,
+ "both IDENTIFYs aborted, assuming NODEV\n");
return -ENOENT;
}
@@ -1953,9 +1951,9 @@ retry:
}
if (dev->horkage & ATA_HORKAGE_DUMP_ID) {
- ata_dev_printk(dev, KERN_DEBUG, "dumping IDENTIFY data, "
- "class=%d may_fallback=%d tried_spinup=%d\n",
- class, may_fallback, tried_spinup);
+ ata_dev_dbg(dev, "dumping IDENTIFY data, "
+ "class=%d may_fallback=%d tried_spinup=%d\n",
+ class, may_fallback, tried_spinup);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
16, 2, id, ATA_ID_WORDS * sizeof(*id), true);
}
@@ -2034,8 +2032,8 @@ retry:
err_out:
if (ata_msg_warn(ap))
- ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY "
- "(%s, err_mask=0x%x)\n", reason, err_mask);
+ ata_dev_warn(dev, "failed to IDENTIFY (%s, err_mask=0x%x)\n",
+ reason, err_mask);
return rc;
}
@@ -2065,9 +2063,8 @@ static int ata_do_link_spd_horkage(struct ata_device *dev)
* guaranteed by setting sata_spd_limit to target_limit above.
*/
if (plink->sata_spd > target) {
- ata_dev_printk(dev, KERN_INFO,
- "applying link speed limit horkage to %s\n",
- sata_spd_string(target));
+ ata_dev_info(dev, "applying link speed limit horkage to %s\n",
+ sata_spd_string(target));
return -EAGAIN;
}
return 0;
@@ -2110,8 +2107,9 @@ static int ata_dev_config_ncq(struct ata_device *dev,
err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE,
SATA_FPDMA_AA);
if (err_mask) {
- ata_dev_printk(dev, KERN_ERR, "failed to enable AA"
- "(error_mask=0x%x)\n", err_mask);
+ ata_dev_err(dev,
+ "failed to enable AA (error_mask=0x%x)\n",
+ err_mask);
if (err_mask != AC_ERR_DEV) {
dev->horkage |= ATA_HORKAGE_BROKEN_FPDMA_AA;
return -EIO;
@@ -2154,31 +2152,28 @@ int ata_dev_configure(struct ata_device *dev)
int rc;
if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
- ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n",
- __func__);
+ ata_dev_info(dev, "%s: ENTER/EXIT -- nodev\n", __func__);
return 0;
}
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
+ ata_dev_dbg(dev, "%s: ENTER\n", __func__);
/* set horkage */
dev->horkage |= ata_dev_blacklisted(dev);
ata_force_horkage(dev);
if (dev->horkage & ATA_HORKAGE_DISABLE) {
- ata_dev_printk(dev, KERN_INFO,
- "unsupported device, disabling\n");
+ ata_dev_info(dev, "unsupported device, disabling\n");
ata_dev_disable(dev);
return 0;
}
if ((!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) &&
dev->class == ATA_DEV_ATAPI) {
- ata_dev_printk(dev, KERN_WARNING,
- "WARNING: ATAPI is %s, device ignored.\n",
- atapi_enabled ? "not supported with this driver"
- : "disabled");
+ ata_dev_warn(dev, "WARNING: ATAPI is %s, device ignored\n",
+ atapi_enabled ? "not supported with this driver"
+ : "disabled");
ata_dev_disable(dev);
return 0;
}
@@ -2199,12 +2194,12 @@ int ata_dev_configure(struct ata_device *dev)
/* print device capabilities */
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
- "85:%04x 86:%04x 87:%04x 88:%04x\n",
- __func__,
- id[49], id[82], id[83], id[84],
- id[85], id[86], id[87], id[88]);
+ ata_dev_dbg(dev,
+ "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
+ "85:%04x 86:%04x 87:%04x 88:%04x\n",
+ __func__,
+ id[49], id[82], id[83], id[84],
+ id[85], id[86], id[87], id[88]);
/* initialize to-be-configured parameters */
dev->flags &= ~ATA_DFLAG_CFG_MASK;
@@ -2238,17 +2233,15 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_id_is_cfa(id)) {
/* CPRM may make this media unusable */
if (id[ATA_ID_CFA_KEY_MGMT] & 1)
- ata_dev_printk(dev, KERN_WARNING,
- "supports DRM functions and may "
- "not be fully accessible.\n");
+ ata_dev_warn(dev,
+ "supports DRM functions and may not be fully accessible\n");
snprintf(revbuf, 7, "CFA");
} else {
snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
/* Warn the user if the device has TPM extensions */
if (ata_id_has_tpm(id))
- ata_dev_printk(dev, KERN_WARNING,
- "supports DRM functions and may "
- "not be fully accessible.\n");
+ ata_dev_warn(dev,
+ "supports DRM functions and may not be fully accessible\n");
}
dev->n_sectors = ata_id_n_sectors(id);
@@ -2285,12 +2278,11 @@ int ata_dev_configure(struct ata_device *dev)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info) {
- ata_dev_printk(dev, KERN_INFO,
- "%s: %s, %s, max %s\n",
- revbuf, modelbuf, fwrevbuf,
- ata_mode_string(xfer_mask));
- ata_dev_printk(dev, KERN_INFO,
- "%Lu sectors, multi %u: %s %s\n",
+ ata_dev_info(dev, "%s: %s, %s, max %s\n",
+ revbuf, modelbuf, fwrevbuf,
+ ata_mode_string(xfer_mask));
+ ata_dev_info(dev,
+ "%llu sectors, multi %u: %s %s\n",
(unsigned long long)dev->n_sectors,
dev->multi_count, lba_desc, ncq_desc);
}
@@ -2311,15 +2303,14 @@ int ata_dev_configure(struct ata_device *dev)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info) {
- ata_dev_printk(dev, KERN_INFO,
- "%s: %s, %s, max %s\n",
- revbuf, modelbuf, fwrevbuf,
- ata_mode_string(xfer_mask));
- ata_dev_printk(dev, KERN_INFO,
- "%Lu sectors, multi %u, CHS %u/%u/%u\n",
- (unsigned long long)dev->n_sectors,
- dev->multi_count, dev->cylinders,
- dev->heads, dev->sectors);
+ ata_dev_info(dev, "%s: %s, %s, max %s\n",
+ revbuf, modelbuf, fwrevbuf,
+ ata_mode_string(xfer_mask));
+ ata_dev_info(dev,
+ "%llu sectors, multi %u, CHS %u/%u/%u\n",
+ (unsigned long long)dev->n_sectors,
+ dev->multi_count, dev->cylinders,
+ dev->heads, dev->sectors);
}
}
@@ -2336,8 +2327,7 @@ int ata_dev_configure(struct ata_device *dev)
rc = atapi_cdb_len(id);
if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
if (ata_msg_warn(ap))
- ata_dev_printk(dev, KERN_WARNING,
- "unsupported CDB len\n");
+ ata_dev_warn(dev, "unsupported CDB len\n");
rc = -EINVAL;
goto err_out_nosup;
}
@@ -2358,9 +2348,9 @@ int ata_dev_configure(struct ata_device *dev)
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_ENABLE, SATA_AN);
if (err_mask)
- ata_dev_printk(dev, KERN_ERR,
- "failed to enable ATAPI AN "
- "(err_mask=0x%x)\n", err_mask);
+ ata_dev_err(dev,
+ "failed to enable ATAPI AN (err_mask=0x%x)\n",
+ err_mask);
else {
dev->flags |= ATA_DFLAG_AN;
atapi_an_string = ", ATAPI AN";
@@ -2379,12 +2369,12 @@ int ata_dev_configure(struct ata_device *dev)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info)
- ata_dev_printk(dev, KERN_INFO,
- "ATAPI: %s, %s, max %s%s%s%s\n",
- modelbuf, fwrevbuf,
- ata_mode_string(xfer_mask),
- cdb_intr_string, atapi_an_string,
- dma_dir_string);
+ ata_dev_info(dev,
+ "ATAPI: %s, %s, max %s%s%s%s\n",
+ modelbuf, fwrevbuf,
+ ata_mode_string(xfer_mask),
+ cdb_intr_string, atapi_an_string,
+ dma_dir_string);
}
/* determine max_sectors */
@@ -2396,8 +2386,7 @@ int ata_dev_configure(struct ata_device *dev)
200 sectors */
if (ata_dev_knobble(dev)) {
if (ata_msg_drv(ap) && print_info)
- ata_dev_printk(dev, KERN_INFO,
- "applying bridge limits\n");
+ ata_dev_info(dev, "applying bridge limits\n");
dev->udma_mask &= ATA_UDMA5;
dev->max_sectors = ATA_MAX_SECTORS;
}
@@ -2423,26 +2412,23 @@ int ata_dev_configure(struct ata_device *dev)
bugs */
if (print_info) {
- ata_dev_printk(dev, KERN_WARNING,
+ ata_dev_warn(dev,
"Drive reports diagnostics failure. This may indicate a drive\n");
- ata_dev_printk(dev, KERN_WARNING,
+ ata_dev_warn(dev,
"fault or invalid emulation. Contact drive vendor for information.\n");
}
}
if ((dev->horkage & ATA_HORKAGE_FIRMWARE_WARN) && print_info) {
- ata_dev_printk(dev, KERN_WARNING, "WARNING: device requires "
- "firmware update to be fully functional.\n");
- ata_dev_printk(dev, KERN_WARNING, " contact the vendor "
- "or visit http://ata.wiki.kernel.org.\n");
+ ata_dev_warn(dev, "WARNING: device requires firmware update to be fully functional\n");
+ ata_dev_warn(dev, " contact the vendor or visit http://ata.wiki.kernel.org\n");
}
return 0;
err_out_nosup:
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: EXIT, err\n", __func__);
+ ata_dev_dbg(dev, "%s: EXIT, err\n", __func__);
return rc;
}
@@ -2663,13 +2649,11 @@ static void sata_print_link_status(struct ata_link *link)
if (ata_phys_link_online(link)) {
tmp = (sstatus >> 4) & 0xf;
- ata_link_printk(link, KERN_INFO,
- "SATA link up %s (SStatus %X SControl %X)\n",
- sata_spd_string(tmp), sstatus, scontrol);
+ ata_link_info(link, "SATA link up %s (SStatus %X SControl %X)\n",
+ sata_spd_string(tmp), sstatus, scontrol);
} else {
- ata_link_printk(link, KERN_INFO,
- "SATA link down (SStatus %X SControl %X)\n",
- sstatus, scontrol);
+ ata_link_info(link, "SATA link down (SStatus %X SControl %X)\n",
+ sstatus, scontrol);
}
}
@@ -2758,8 +2742,8 @@ int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
link->sata_spd_limit = mask;
- ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",
- sata_spd_string(fls(mask)));
+ ata_link_warn(link, "limiting SATA link speed to %s\n",
+ sata_spd_string(fls(mask)));
return 0;
}
@@ -3136,8 +3120,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
snprintf(buf, sizeof(buf), "%s",
ata_mode_string(xfer_mask));
- ata_dev_printk(dev, KERN_WARNING,
- "limiting speed to %s\n", buf);
+ ata_dev_warn(dev, "limiting speed to %s\n", buf);
}
ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
@@ -3164,9 +3147,9 @@ static int ata_dev_set_mode(struct ata_device *dev)
dev_err_whine = " (SET_XFERMODE skipped)";
else {
if (nosetxfer)
- ata_dev_printk(dev, KERN_WARNING,
- "NOSETXFER but PATA detected - can't "
- "skip SETXFER, might malfunction\n");
+ ata_dev_warn(dev,
+ "NOSETXFER but PATA detected - can't "
+ "skip SETXFER, might malfunction\n");
err_mask = ata_dev_set_xfermode(dev);
}
@@ -3216,15 +3199,14 @@ static int ata_dev_set_mode(struct ata_device *dev)
DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
dev->xfer_shift, (int)dev->xfer_mode);
- ata_dev_printk(dev, KERN_INFO, "configured for %s%s\n",
- ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)),
- dev_err_whine);
+ ata_dev_info(dev, "configured for %s%s\n",
+ ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)),
+ dev_err_whine);
return 0;
fail:
- ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
- "(err_mask=0x%x)\n", err_mask);
+ ata_dev_err(dev, "failed to set xfermode (err_mask=0x%x)\n", err_mask);
return -EIO;
}
@@ -3286,7 +3268,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
/* step 2: always set host PIO timings */
ata_for_each_dev(dev, link, ENABLED) {
if (dev->pio_mode == 0xff) {
- ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
+ ata_dev_warn(dev, "no PIO support\n");
rc = -EINVAL;
goto out;
}
@@ -3404,7 +3386,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
if (!warned && time_after(now, start + 5 * HZ) &&
(deadline - now > 3 * HZ)) {
- ata_link_printk(link, KERN_WARNING,
+ ata_link_warn(link,
"link is slow to respond, please be patient "
"(ready=%d)\n", tmp);
warned = 1;
@@ -3552,16 +3534,14 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
} while ((scontrol & 0xf0f) != 0x300 && --tries);
if ((scontrol & 0xf0f) != 0x300) {
- ata_link_printk(link, KERN_ERR,
- "failed to resume link (SControl %X)\n",
- scontrol);
+ ata_link_warn(link, "failed to resume link (SControl %X)\n",
+ scontrol);
return 0;
}
if (tries < ATA_LINK_RESUME_TRIES)
- ata_link_printk(link, KERN_WARNING,
- "link resume succeeded after %d retries\n",
- ATA_LINK_RESUME_TRIES - tries);
+ ata_link_warn(link, "link resume succeeded after %d retries\n",
+ ATA_LINK_RESUME_TRIES - tries);
if ((rc = sata_link_debounce(link, params, deadline)))
return rc;
@@ -3678,8 +3658,9 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
rc = sata_link_resume(link, timing, deadline);
/* whine about phy resume failure but proceed */
if (rc && rc != -EOPNOTSUPP)
- ata_link_printk(link, KERN_WARNING, "failed to resume "
- "link for reset (errno=%d)\n", rc);
+ ata_link_warn(link,
+ "failed to resume link for reset (errno=%d)\n",
+ rc);
}
/* no point in trying softreset on offline link */
@@ -3795,8 +3776,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
/* online is set iff link is online && reset succeeded */
if (online)
*online = false;
- ata_link_printk(link, KERN_ERR,
- "COMRESET failed (errno=%d)\n", rc);
+ ata_link_err(link, "COMRESET failed (errno=%d)\n", rc);
}
DPRINTK("EXIT, rc=%d\n", rc);
return rc;
@@ -3880,8 +3860,8 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
unsigned char serial[2][ATA_ID_SERNO_LEN + 1];
if (dev->class != new_class) {
- ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
- dev->class, new_class);
+ ata_dev_info(dev, "class mismatch %d != %d\n",
+ dev->class, new_class);
return 0;
}
@@ -3891,14 +3871,14 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));
if (strcmp(model[0], model[1])) {
- ata_dev_printk(dev, KERN_INFO, "model number mismatch "
- "'%s' != '%s'\n", model[0], model[1]);
+ ata_dev_info(dev, "model number mismatch '%s' != '%s'\n",
+ model[0], model[1]);
return 0;
}
if (strcmp(serial[0], serial[1])) {
- ata_dev_printk(dev, KERN_INFO, "serial number mismatch "
- "'%s' != '%s'\n", serial[0], serial[1]);
+ ata_dev_info(dev, "serial number mismatch '%s' != '%s'\n",
+ serial[0], serial[1]);
return 0;
}
@@ -3968,8 +3948,8 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
new_class != ATA_DEV_ATA &&
new_class != ATA_DEV_ATAPI &&
new_class != ATA_DEV_SEMB) {
- ata_dev_printk(dev, KERN_INFO, "class mismatch %u != %u\n",
- dev->class, new_class);
+ ata_dev_info(dev, "class mismatch %u != %u\n",
+ dev->class, new_class);
rc = -ENODEV;
goto fail;
}
@@ -3990,9 +3970,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
return 0;
/* n_sectors has changed */
- ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n",
- (unsigned long long)n_sectors,
- (unsigned long long)dev->n_sectors);
+ ata_dev_warn(dev, "n_sectors mismatch %llu != %llu\n",
+ (unsigned long long)n_sectors,
+ (unsigned long long)dev->n_sectors);
/*
* Something could have caused HPA to be unlocked
@@ -4001,9 +3981,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
*/
if (dev->n_native_sectors == n_native_sectors &&
dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
- ata_dev_printk(dev, KERN_WARNING,
- "new n_sectors matches native, probably "
- "late HPA unlock, n_sectors updated\n");
+ ata_dev_warn(dev,
+ "new n_sectors matches native, probably "
+ "late HPA unlock, n_sectors updated\n");
/* use the larger n_sectors */
return 0;
}
@@ -4017,9 +3997,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
if (dev->n_native_sectors == n_native_sectors &&
dev->n_sectors < n_sectors && n_sectors == n_native_sectors &&
!(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) {
- ata_dev_printk(dev, KERN_WARNING,
- "old n_sectors matches native, probably "
- "late HPA lock, will try to unlock HPA\n");
+ ata_dev_warn(dev,
+ "old n_sectors matches native, probably "
+ "late HPA lock, will try to unlock HPA\n");
/* try unlocking HPA */
dev->flags |= ATA_DFLAG_UNLOCK_HPA;
rc = -EIO;
@@ -4030,7 +4010,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
dev->n_native_sectors = n_native_sectors;
dev->n_sectors = n_sectors;
fail:
- ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
+ ata_dev_err(dev, "revalidation failed (errno=%d)\n", rc);
return rc;
}
@@ -4358,15 +4338,15 @@ static void ata_dev_xfermask(struct ata_device *dev)
if (ata_dma_blacklisted(dev)) {
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
- ata_dev_printk(dev, KERN_WARNING,
- "device is on DMA blacklist, disabling DMA\n");
+ ata_dev_warn(dev,
+ "device is on DMA blacklist, disabling DMA\n");
}
if ((host->flags & ATA_HOST_SIMPLEX) &&
host->simplex_claimed && host->simplex_claimed != ap) {
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
- ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
- "other device, disabling DMA\n");
+ ata_dev_warn(dev,
+ "simplex DMA is claimed by other device, disabling DMA\n");
}
if (ap->flags & ATA_FLAG_NO_IORDY)
@@ -4386,8 +4366,8 @@ static void ata_dev_xfermask(struct ata_device *dev)
if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
/* UDMA/44 or higher would be available */
if (cable_is_40wire(ap)) {
- ata_dev_printk(dev, KERN_WARNING,
- "limited to UDMA/33 due to 40-wire cable\n");
+ ata_dev_warn(dev,
+ "limited to UDMA/33 due to 40-wire cable\n");
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
}
@@ -4954,8 +4934,8 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)
done_mask = ap->qc_active ^ qc_active;
if (unlikely(done_mask & qc_active)) {
- ata_port_printk(ap, KERN_ERR, "illegal qc_active transition "
- "(%08x->%08x)\n", ap->qc_active, qc_active);
+ ata_port_err(ap, "illegal qc_active transition (%08x->%08x)\n",
+ ap->qc_active, qc_active);
return -EINVAL;
}
@@ -5847,9 +5827,9 @@ int ata_host_start(struct ata_host *host)
rc = ap->ops->port_start(ap);
if (rc) {
if (rc != -ENODEV)
- dev_printk(KERN_ERR, host->dev,
- "failed to start port %d "
- "(errno=%d)\n", i, rc);
+ dev_err(host->dev,
+ "failed to start port %d (errno=%d)\n",
+ i, rc);
goto err_out;
}
}
@@ -5971,8 +5951,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
/* host must have been started */
if (!(host->flags & ATA_HOST_STARTED)) {
- dev_printk(KERN_ERR, host->dev,
- "BUG: trying to register unstarted host\n");
+ dev_err(host->dev, "BUG: trying to register unstarted host\n");
WARN_ON(1);
return -EINVAL;
}
@@ -6023,14 +6002,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
ap->udma_mask);
if (!ata_port_is_dummy(ap)) {
- ata_port_printk(ap, KERN_INFO,
- "%cATA max %s %s\n",
- (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
- ata_mode_string(xfer_mask),
- ap->link.eh_info.desc);
+ ata_port_info(ap, "%cATA max %s %s\n",
+ (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
+ ata_mode_string(xfer_mask),
+ ap->link.eh_info.desc);
ata_ehi_clear_desc(&ap->link.eh_info);
} else
- ata_port_printk(ap, KERN_INFO, "DUMMY\n");
+ ata_port_info(ap, "DUMMY\n");
}
/* perform each probe asynchronously */
@@ -6242,8 +6220,8 @@ int ata_pci_device_do_resume(struct pci_dev *pdev)
rc = pcim_enable_device(pdev);
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to enable device after resume (%d)\n", rc);
+ dev_err(&pdev->dev,
+ "failed to enable device after resume (%d)\n", rc);
return rc;
}
@@ -6600,6 +6578,82 @@ const struct ata_port_info ata_dummy_port_info = {
};
/*
+ * Utility print functions
+ */
+int ata_port_printk(const struct ata_port *ap, const char *level,
+ const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ r = printk("%sata%u: %pV", level, ap->print_id, &vaf);
+
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(ata_port_printk);
+
+int ata_link_printk(const struct ata_link *link, const char *level,
+ const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ if (sata_pmp_attached(link->ap) || link->ap->slave_link)
+ r = printk("%sata%u.%02u: %pV",
+ level, link->ap->print_id, link->pmp, &vaf);
+ else
+ r = printk("%sata%u: %pV",
+ level, link->ap->print_id, &vaf);
+
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(ata_link_printk);
+
+int ata_dev_printk(const struct ata_device *dev, const char *level,
+ const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ r = printk("%sata%u.%02u: %pV",
+ level, dev->link->ap->print_id, dev->link->pmp + dev->devno,
+ &vaf);
+
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(ata_dev_printk);
+
+void ata_print_version(const struct device *dev, const char *version)
+{
+ dev_printk(KERN_DEBUG, dev, "version %s\n", version);
+}
+EXPORT_SYMBOL(ata_print_version);
+
+/*
* libata is essentially a library of internal helper functions for
* low-level ATA host controller drivers. As such, the API/ABI is
* likely to change as new drivers are added and updated.
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7f099d6e4e0b..ed16fbedaabd 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -782,8 +782,9 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
spin_unlock_irqrestore(ap->lock, flags);
goto repeat;
}
- ata_port_printk(ap, KERN_ERR, "EH pending after %d "
- "tries, giving up\n", ATA_EH_MAX_TRIES);
+ ata_port_err(ap,
+ "EH pending after %d tries, giving up\n",
+ ATA_EH_MAX_TRIES);
ap->pflags &= ~ATA_PFLAG_EH_PENDING;
}
@@ -816,7 +817,7 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
schedule_delayed_work(&ap->hotplug_task, 0);
if (ap->pflags & ATA_PFLAG_RECOVERED)
- ata_port_printk(ap, KERN_INFO, "EH complete\n");
+ ata_port_info(ap, "EH complete\n");
ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
@@ -1310,7 +1311,7 @@ void ata_dev_disable(struct ata_device *dev)
return;
if (ata_msg_drv(dev->link->ap))
- ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+ ata_dev_warn(dev, "disabled\n");
ata_acpi_on_disable(dev);
ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
dev->class++;
@@ -1515,8 +1516,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
for (i = 0; i < ATA_SECT_SIZE; i++)
csum += buf[i];
if (csum)
- ata_dev_printk(dev, KERN_WARNING,
- "invalid checksum 0x%x on log page 10h\n", csum);
+ ata_dev_warn(dev, "invalid checksum 0x%x on log page 10h\n",
+ csum);
if (buf[0] & 0x80)
return -ENOENT;
@@ -1716,14 +1717,14 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
memset(&tf, 0, sizeof(tf));
rc = ata_eh_read_log_10h(dev, &tag, &tf);
if (rc) {
- ata_link_printk(link, KERN_ERR, "failed to read log page 10h "
- "(errno=%d)\n", rc);
+ ata_link_err(link, "failed to read log page 10h (errno=%d)\n",
+ rc);
return;
}
if (!(link->sactive & (1 << tag))) {
- ata_link_printk(link, KERN_ERR, "log page 10h reported "
- "inactive tag %d\n", tag);
+ ata_link_err(link, "log page 10h reported inactive tag %d\n",
+ tag);
return;
}
@@ -1988,8 +1989,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
(dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ |
ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) {
dev->flags |= ATA_DFLAG_NCQ_OFF;
- ata_dev_printk(dev, KERN_WARNING,
- "NCQ disabled due to excessive errors\n");
+ ata_dev_warn(dev, "NCQ disabled due to excessive errors\n");
goto done;
}
@@ -2374,24 +2374,24 @@ static void ata_eh_link_report(struct ata_link *link)
ap->eh_tries);
if (ehc->i.dev) {
- ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
- "SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
- ehc->i.err_mask, link->sactive, ehc->i.serror,
- ehc->i.action, frozen, tries_buf);
+ ata_dev_err(ehc->i.dev, "exception Emask 0x%x "
+ "SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
+ ehc->i.err_mask, link->sactive, ehc->i.serror,
+ ehc->i.action, frozen, tries_buf);
if (desc)
- ata_dev_printk(ehc->i.dev, KERN_ERR, "%s\n", desc);
+ ata_dev_err(ehc->i.dev, "%s\n", desc);
} else {
- ata_link_printk(link, KERN_ERR, "exception Emask 0x%x "
- "SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
- ehc->i.err_mask, link->sactive, ehc->i.serror,
- ehc->i.action, frozen, tries_buf);
+ ata_link_err(link, "exception Emask 0x%x "
+ "SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
+ ehc->i.err_mask, link->sactive, ehc->i.serror,
+ ehc->i.action, frozen, tries_buf);
if (desc)
- ata_link_printk(link, KERN_ERR, "%s\n", desc);
+ ata_link_err(link, "%s\n", desc);
}
#ifdef CONFIG_ATA_VERBOSE_ERROR
if (ehc->i.serror)
- ata_link_printk(link, KERN_ERR,
+ ata_link_err(link,
"SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n",
ehc->i.serror & SERR_DATA_RECOVERED ? "RecovData " : "",
ehc->i.serror & SERR_COMM_RECOVERED ? "RecovComm " : "",
@@ -2456,11 +2456,11 @@ static void ata_eh_link_report(struct ata_link *link)
} else {
const char *descr = ata_get_cmd_descript(cmd->command);
if (descr)
- ata_dev_printk(qc->dev, KERN_ERR,
- "failed command: %s\n", descr);
+ ata_dev_err(qc->dev, "failed command: %s\n",
+ descr);
}
- ata_dev_printk(qc->dev, KERN_ERR,
+ ata_dev_err(qc->dev,
"cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
"tag %d%s\n %s"
"res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
@@ -2481,11 +2481,9 @@ static void ata_eh_link_report(struct ata_link *link)
if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
ATA_ERR)) {
if (res->command & ATA_BUSY)
- ata_dev_printk(qc->dev, KERN_ERR,
- "status: { Busy }\n");
+ ata_dev_err(qc->dev, "status: { Busy }\n");
else
- ata_dev_printk(qc->dev, KERN_ERR,
- "status: { %s%s%s%s}\n",
+ ata_dev_err(qc->dev, "status: { %s%s%s%s}\n",
res->command & ATA_DRDY ? "DRDY " : "",
res->command & ATA_DF ? "DF " : "",
res->command & ATA_DRQ ? "DRQ " : "",
@@ -2495,8 +2493,7 @@ static void ata_eh_link_report(struct ata_link *link)
if (cmd->command != ATA_CMD_PACKET &&
(res->feature & (ATA_ICRC | ATA_UNC | ATA_IDNF |
ATA_ABORTED)))
- ata_dev_printk(qc->dev, KERN_ERR,
- "error: { %s%s%s%s}\n",
+ ata_dev_err(qc->dev, "error: { %s%s%s%s}\n",
res->feature & ATA_ICRC ? "ICRC " : "",
res->feature & ATA_UNC ? "UNC " : "",
res->feature & ATA_IDNF ? "IDNF " : "",
@@ -2650,8 +2647,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
if (rc) {
if (rc == -ENOENT) {
- ata_link_printk(link, KERN_DEBUG,
- "port disabled. ignoring.\n");
+ ata_link_dbg(link, "port disabled--ignoring\n");
ehc->i.action &= ~ATA_EH_RESET;
ata_for_each_dev(dev, link, ALL)
@@ -2659,8 +2655,9 @@ int ata_eh_reset(struct ata_link *link, int classify,
rc = 0;
} else
- ata_link_printk(link, KERN_ERR,
- "prereset failed (errno=%d)\n", rc);
+ ata_link_err(link,
+ "prereset failed (errno=%d)\n",
+ rc);
goto out;
}
@@ -2689,8 +2686,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
if (reset) {
if (verbose)
- ata_link_printk(link, KERN_INFO, "%s resetting link\n",
- reset == softreset ? "soft" : "hard");
+ ata_link_info(link, "%s resetting link\n",
+ reset == softreset ? "soft" : "hard");
/* mark that this EH session started with reset */
ehc->last_reset = jiffies;
@@ -2710,8 +2707,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
int tmp;
if (verbose)
- ata_link_printk(slave, KERN_INFO,
- "hard resetting link\n");
+ ata_link_info(slave, "hard resetting link\n");
ata_eh_about_to_do(slave, NULL, ATA_EH_RESET);
tmp = ata_do_reset(slave, reset, classes, deadline,
@@ -2734,9 +2730,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
reset = softreset;
if (!reset) {
- ata_link_printk(link, KERN_ERR,
- "follow-up softreset required "
- "but no softreset available\n");
+ ata_link_err(link,
+ "follow-up softreset required but no softreset available\n");
failed_link = link;
rc = -EINVAL;
goto fail;
@@ -2751,8 +2746,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
}
} else {
if (verbose)
- ata_link_printk(link, KERN_INFO, "no reset method "
- "available, skipping reset\n");
+ ata_link_info(link,
+ "no reset method available, skipping reset\n");
if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
lflags |= ATA_LFLAG_ASSUME_ATA;
}
@@ -2830,36 +2825,35 @@ int ata_eh_reset(struct ata_link *link, int classify,
ata_for_each_dev(dev, link, ALL) {
if (ata_phys_link_online(ata_dev_phys_link(dev))) {
if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
- ata_dev_printk(dev, KERN_DEBUG, "link online "
- "but device misclassifed\n");
+ ata_dev_dbg(dev, "link online but device misclassified\n");
classes[dev->devno] = ATA_DEV_NONE;
nr_unknown++;
}
} else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
if (ata_class_enabled(classes[dev->devno]))
- ata_dev_printk(dev, KERN_DEBUG, "link offline, "
- "clearing class %d to NONE\n",
- classes[dev->devno]);
+ ata_dev_dbg(dev,
+ "link offline, clearing class %d to NONE\n",
+ classes[dev->devno]);
classes[dev->devno] = ATA_DEV_NONE;
} else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
- ata_dev_printk(dev, KERN_DEBUG, "link status unknown, "
- "clearing UNKNOWN to NONE\n");
+ ata_dev_dbg(dev,
+ "link status unknown, clearing UNKNOWN to NONE\n");
classes[dev->devno] = ATA_DEV_NONE;
}
}
if (classify && nr_unknown) {
if (try < max_tries) {
- ata_link_printk(link, KERN_WARNING, "link online but "
- "%d devices misclassified, retrying\n",
- nr_unknown);
+ ata_link_warn(link,
+ "link online but %d devices misclassified, retrying\n",
+ nr_unknown);
failed_link = link;
rc = -EAGAIN;
goto fail;
}
- ata_link_printk(link, KERN_WARNING,
- "link online but %d devices misclassified, "
- "device detection might fail\n", nr_unknown);
+ ata_link_warn(link,
+ "link online but %d devices misclassified, "
+ "device detection might fail\n", nr_unknown);
}
/* reset successful, schedule revalidation */
@@ -2889,14 +2883,23 @@ int ata_eh_reset(struct ata_link *link, int classify,
sata_scr_read(link, SCR_STATUS, &sstatus))
rc = -ERESTART;
- if (rc == -ERESTART || try >= max_tries)
+ if (rc == -ERESTART || try >= max_tries) {
+ /*
+ * Thaw host port even if reset failed, so that the port
+ * can be retried on the next phy event. This risks
+ * repeated EH runs but seems to be a better tradeoff than
+ * shutting down a port after a botched hotplug attempt.
+ */
+ if (ata_is_host_link(link))
+ ata_eh_thaw_port(ap);
goto out;
+ }
now = jiffies;
if (time_before(now, deadline)) {
unsigned long delta = deadline - now;
- ata_link_printk(failed_link, KERN_WARNING,
+ ata_link_warn(failed_link,
"reset failed (errno=%d), retrying in %u secs\n",
rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000));
@@ -2987,7 +2990,7 @@ static void ata_eh_park_issue_cmd(struct ata_device *dev, int park)
tf.protocol |= ATA_PROT_NODATA;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
if (park && (err_mask || tf.lbal != 0xc4)) {
- ata_dev_printk(dev, KERN_ERR, "head unload failed!\n");
+ ata_dev_err(dev, "head unload failed!\n");
ehc->unloaded_mask &= ~(1 << dev->devno);
}
}
@@ -3198,8 +3201,9 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
err_mask = atapi_eh_tur(dev, &sense_key);
if (err_mask != 0 && err_mask != AC_ERR_DEV) {
- ata_dev_printk(dev, KERN_WARNING, "TEST_UNIT_READY "
- "failed (err_mask=0x%x)\n", err_mask);
+ ata_dev_warn(dev,
+ "TEST_UNIT_READY failed (err_mask=0x%x)\n",
+ err_mask);
return -EIO;
}
@@ -3208,14 +3212,14 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
err_mask = atapi_eh_request_sense(dev, sense_buffer, sense_key);
if (err_mask) {
- ata_dev_printk(dev, KERN_WARNING, "failed to clear "
+ ata_dev_warn(dev, "failed to clear "
"UNIT ATTENTION (err_mask=0x%x)\n", err_mask);
return -EIO;
}
}
- ata_dev_printk(dev, KERN_WARNING,
- "UNIT ATTENTION persists after %d tries\n", ATA_EH_UA_TRIES);
+ ata_dev_warn(dev, "UNIT ATTENTION persists after %d tries\n",
+ ATA_EH_UA_TRIES);
return 0;
}
@@ -3266,7 +3270,7 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
tf.flags |= ATA_TFLAG_DEVICE;
tf.protocol = ATA_PROT_NODATA;
- ata_dev_printk(dev, KERN_WARNING, "retrying FLUSH 0x%x Emask 0x%x\n",
+ ata_dev_warn(dev, "retrying FLUSH 0x%x Emask 0x%x\n",
tf.command, qc->err_mask);
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
@@ -3281,7 +3285,7 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
*/
qc->scsicmd->allowed = max(qc->scsicmd->allowed, 1);
} else {
- ata_dev_printk(dev, KERN_WARNING, "FLUSH failed Emask 0x%x\n",
+ ata_dev_warn(dev, "FLUSH failed Emask 0x%x\n",
err_mask);
rc = -EIO;
@@ -3355,9 +3359,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_DISABLE, SATA_DIPM);
if (err_mask && err_mask != AC_ERR_DEV) {
- ata_dev_printk(dev, KERN_WARNING,
- "failed to disable DIPM, Emask 0x%x\n",
- err_mask);
+ ata_dev_warn(dev,
+ "failed to disable DIPM, Emask 0x%x\n",
+ err_mask);
rc = -EIO;
goto fail;
}
@@ -3399,7 +3403,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_ENABLE, SATA_DIPM);
if (err_mask && err_mask != AC_ERR_DEV) {
- ata_dev_printk(dev, KERN_WARNING,
+ ata_dev_warn(dev,
"failed to enable DIPM, Emask 0x%x\n",
err_mask);
rc = -EIO;
@@ -3418,8 +3422,7 @@ fail:
/* if no device or only one more chance is left, disable LPM */
if (!dev || ehc->tries[dev->devno] <= 2) {
- ata_link_printk(link, KERN_WARNING,
- "disabling LPM on the link\n");
+ ata_link_warn(link, "disabling LPM on the link\n");
link->flags |= ATA_LFLAG_NO_LPM;
}
if (r_failed_dev)
@@ -3690,8 +3693,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
rc = ata_eh_reset(link, ata_link_nr_vacant(link),
prereset, softreset, hardreset, postreset);
if (rc) {
- ata_link_printk(link, KERN_ERR,
- "reset failed, giving up\n");
+ ata_link_err(link, "reset failed, giving up\n");
goto out;
}
}
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index f06b7ea590d3..3eb2b816eb2a 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -147,8 +147,8 @@ int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val)
err_mask = sata_pmp_read(link, reg, r_val);
if (err_mask) {
- ata_link_printk(link, KERN_WARNING, "failed to read SCR %d "
- "(Emask=0x%x)\n", reg, err_mask);
+ ata_link_warn(link, "failed to read SCR %d (Emask=0x%x)\n",
+ reg, err_mask);
return -EIO;
}
return 0;
@@ -178,8 +178,8 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
err_mask = sata_pmp_write(link, reg, val);
if (err_mask) {
- ata_link_printk(link, KERN_WARNING, "failed to write SCR %d "
- "(Emask=0x%x)\n", reg, err_mask);
+ ata_link_warn(link, "failed to write SCR %d (Emask=0x%x)\n",
+ reg, err_mask);
return -EIO;
}
return 0;
@@ -231,8 +231,8 @@ static int sata_pmp_read_gscr(struct ata_device *dev, u32 *gscr)
err_mask = sata_pmp_read(dev->link, reg, &gscr[reg]);
if (err_mask) {
- ata_dev_printk(dev, KERN_ERR, "failed to read PMP "
- "GSCR[%d] (Emask=0x%x)\n", reg, err_mask);
+ ata_dev_err(dev, "failed to read PMP GSCR[%d] (Emask=0x%x)\n",
+ reg, err_mask);
return -EIO;
}
}
@@ -311,26 +311,25 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
}
if (print_info) {
- ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
- "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
- sata_pmp_spec_rev_str(gscr), vendor, devid,
- sata_pmp_gscr_rev(gscr),
- nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
- gscr[SATA_PMP_GSCR_FEAT]);
+ ata_dev_info(dev, "Port Multiplier %s, "
+ "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
+ sata_pmp_spec_rev_str(gscr), vendor, devid,
+ sata_pmp_gscr_rev(gscr),
+ nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
+ gscr[SATA_PMP_GSCR_FEAT]);
if (!(dev->flags & ATA_DFLAG_AN))
- ata_dev_printk(dev, KERN_INFO,
+ ata_dev_info(dev,
"Asynchronous notification not supported, "
- "hotplug won't\n work on fan-out "
- "ports. Use warm-plug instead.\n");
+ "hotplug won't work on fan-out ports. Use warm-plug instead.\n");
}
return 0;
fail:
- ata_dev_printk(dev, KERN_ERR,
- "failed to configure Port Multiplier (%s, Emask=0x%x)\n",
- reason, err_mask);
+ ata_dev_err(dev,
+ "failed to configure Port Multiplier (%s, Emask=0x%x)\n",
+ reason, err_mask);
return rc;
}
@@ -485,20 +484,17 @@ int sata_pmp_attach(struct ata_device *dev)
/* is it hanging off the right place? */
if (!sata_pmp_supported(ap)) {
- ata_dev_printk(dev, KERN_ERR,
- "host does not support Port Multiplier\n");
+ ata_dev_err(dev, "host does not support Port Multiplier\n");
return -EINVAL;
}
if (!ata_is_host_link(link)) {
- ata_dev_printk(dev, KERN_ERR,
- "Port Multipliers cannot be nested\n");
+ ata_dev_err(dev, "Port Multipliers cannot be nested\n");
return -EINVAL;
}
if (dev->devno) {
- ata_dev_printk(dev, KERN_ERR,
- "Port Multiplier must be the first device\n");
+ ata_dev_err(dev, "Port Multiplier must be the first device\n");
return -EINVAL;
}
@@ -517,8 +513,7 @@ int sata_pmp_attach(struct ata_device *dev)
rc = sata_pmp_init_links(ap, sata_pmp_gscr_ports(dev->gscr));
if (rc) {
- ata_dev_printk(dev, KERN_INFO,
- "failed to initialize PMP links\n");
+ ata_dev_info(dev, "failed to initialize PMP links\n");
goto fail;
}
@@ -562,7 +557,7 @@ static void sata_pmp_detach(struct ata_device *dev)
struct ata_link *tlink;
unsigned long flags;
- ata_dev_printk(dev, KERN_INFO, "Port Multiplier detaching\n");
+ ata_dev_info(dev, "Port Multiplier detaching\n");
WARN_ON(!ata_is_host_link(link) || dev->devno ||
link->pmp != SATA_PMP_CTRL_PORT);
@@ -609,23 +604,23 @@ static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr)
new_nr_ports = sata_pmp_gscr_ports(new_gscr);
if (old_vendor != new_vendor) {
- ata_dev_printk(dev, KERN_INFO, "Port Multiplier "
- "vendor mismatch '0x%x' != '0x%x'\n",
- old_vendor, new_vendor);
+ ata_dev_info(dev,
+ "Port Multiplier vendor mismatch '0x%x' != '0x%x'\n",
+ old_vendor, new_vendor);
return 0;
}
if (old_devid != new_devid) {
- ata_dev_printk(dev, KERN_INFO, "Port Multiplier "
- "device ID mismatch '0x%x' != '0x%x'\n",
- old_devid, new_devid);
+ ata_dev_info(dev,
+ "Port Multiplier device ID mismatch '0x%x' != '0x%x'\n",
+ old_devid, new_devid);
return 0;
}
if (old_nr_ports != new_nr_ports) {
- ata_dev_printk(dev, KERN_INFO, "Port Multiplier "
- "nr_ports mismatch '0x%x' != '0x%x'\n",
- old_nr_ports, new_nr_ports);
+ ata_dev_info(dev,
+ "Port Multiplier nr_ports mismatch '0x%x' != '0x%x'\n",
+ old_nr_ports, new_nr_ports);
return 0;
}
@@ -691,8 +686,7 @@ static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class)
return 0;
fail:
- ata_dev_printk(dev, KERN_ERR,
- "PMP revalidation failed (errno=%d)\n", rc);
+ ata_dev_err(dev, "PMP revalidation failed (errno=%d)\n", rc);
DPRINTK("EXIT, rc=%d\n", rc);
return rc;
}
@@ -716,13 +710,14 @@ static int sata_pmp_revalidate_quick(struct ata_device *dev)
err_mask = sata_pmp_read(dev->link, SATA_PMP_GSCR_PROD_ID, &prod_id);
if (err_mask) {
- ata_dev_printk(dev, KERN_ERR, "failed to read PMP product ID "
- "(Emask=0x%x)\n", err_mask);
+ ata_dev_err(dev,
+ "failed to read PMP product ID (Emask=0x%x)\n",
+ err_mask);
return -EIO;
}
if (prod_id != dev->gscr[SATA_PMP_GSCR_PROD_ID]) {
- ata_dev_printk(dev, KERN_ERR, "PMP product ID mismatch\n");
+ ata_dev_err(dev, "PMP product ID mismatch\n");
/* something weird is going on, request full PMP recovery */
return -EIO;
}
@@ -777,8 +772,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
postreset);
if (rc) {
- ata_link_printk(link, KERN_ERR,
- "failed to reset PMP, giving up\n");
+ ata_link_err(link, "failed to reset PMP, giving up\n");
goto fail;
}
@@ -819,9 +813,9 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
ehc->i.action |= ATA_EH_RESET;
goto retry;
} else {
- ata_dev_printk(dev, KERN_ERR, "failed to recover PMP "
- "after %d tries, giving up\n",
- ATA_EH_PMP_TRIES);
+ ata_dev_err(dev,
+ "failed to recover PMP after %d tries, giving up\n",
+ ATA_EH_PMP_TRIES);
goto fail;
}
}
@@ -867,8 +861,9 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
/* unconditionally clear SError.N */
rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
if (rc) {
- ata_link_printk(link, KERN_ERR, "failed to clear "
- "SError.N (errno=%d)\n", rc);
+ ata_link_err(link,
+ "failed to clear SError.N (errno=%d)\n",
+ rc);
return rc;
}
@@ -890,7 +885,7 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
/* disable this link */
if (!(link->flags & ATA_LFLAG_DISABLED)) {
- ata_link_printk(link, KERN_WARNING,
+ ata_link_warn(link,
"failed to recover link after %d tries, disabling\n",
ATA_EH_PMP_LINK_TRIES);
@@ -974,7 +969,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
gscr[SATA_PMP_GSCR_FEAT_EN]);
if (err_mask) {
- ata_link_printk(pmp_link, KERN_WARNING,
+ ata_link_warn(pmp_link,
"failed to disable NOTIFY (err_mask=0x%x)\n",
err_mask);
goto pmp_fail;
@@ -1018,8 +1013,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
gscr[SATA_PMP_GSCR_FEAT_EN]);
if (err_mask) {
- ata_dev_printk(pmp_dev, KERN_ERR, "failed to write "
- "PMP_FEAT_EN (Emask=0x%x)\n", err_mask);
+ ata_dev_err(pmp_dev,
+ "failed to write PMP_FEAT_EN (Emask=0x%x)\n",
+ err_mask);
rc = -EIO;
goto pmp_fail;
}
@@ -1028,8 +1024,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
/* check GSCR_ERROR */
err_mask = sata_pmp_read(pmp_link, SATA_PMP_GSCR_ERROR, &gscr_error);
if (err_mask) {
- ata_dev_printk(pmp_dev, KERN_ERR, "failed to read "
- "PMP_GSCR_ERROR (Emask=0x%x)\n", err_mask);
+ ata_dev_err(pmp_dev,
+ "failed to read PMP_GSCR_ERROR (Emask=0x%x)\n",
+ err_mask);
rc = -EIO;
goto pmp_fail;
}
@@ -1043,17 +1040,16 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
ata_ehi_hotplugged(&link->eh_context.i);
cnt++;
} else {
- ata_link_printk(link, KERN_WARNING,
- "PHY status changed but maxed out on retries, "
- "giving up\n");
- ata_link_printk(link, KERN_WARNING,
- "Manully issue scan to resume this link\n");
+ ata_link_warn(link,
+ "PHY status changed but maxed out on retries, giving up\n");
+ ata_link_warn(link,
+ "Manually issue scan to resume this link\n");
}
}
if (cnt) {
- ata_port_printk(ap, KERN_INFO, "PMP SError.N set for some "
- "ports, repeating recovery\n");
+ ata_port_info(ap,
+ "PMP SError.N set for some ports, repeating recovery\n");
goto retry;
}
@@ -1081,9 +1077,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
goto retry;
}
- ata_port_printk(ap, KERN_ERR,
- "failed to recover PMP after %d tries, giving up\n",
- ATA_EH_PMP_TRIES);
+ ata_port_err(ap, "failed to recover PMP after %d tries, giving up\n",
+ ATA_EH_PMP_TRIES);
sata_pmp_detach(pmp_dev);
ata_dev_disable(pmp_dev);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 927f968e99d9..46d087f08607 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1108,8 +1108,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
/* configure draining */
buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL);
if (!buf) {
- ata_dev_printk(dev, KERN_ERR,
- "drain buffer allocation failed\n");
+ ata_dev_err(dev, "drain buffer allocation failed\n");
return -ENOMEM;
}
@@ -1127,7 +1126,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
* IDENTIFY_PACKET is executed as ATA_PROT_PIO.
*/
if (sdev->sector_size > PAGE_SIZE)
- ata_dev_printk(dev, KERN_WARNING,
+ ata_dev_warn(dev,
"sector_size=%u > PAGE_SIZE, PIO may malfunction\n",
sdev->sector_size);
@@ -1784,8 +1783,7 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
cmd->sc_data_direction == DMA_TO_DEVICE) {
if (unlikely(scsi_bufflen(cmd) < 1)) {
- ata_dev_printk(dev, KERN_WARNING,
- "WARNING: zero len r/w req\n");
+ ata_dev_warn(dev, "WARNING: zero len r/w req\n");
goto err_did;
}
@@ -2969,9 +2967,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
* with the cached multi_count of libata
*/
if (multi_count != dev->multi_count)
- ata_dev_printk(dev, KERN_WARNING,
- "invalid multi_count %u ignored\n",
- multi_count);
+ ata_dev_warn(dev, "invalid multi_count %u ignored\n",
+ multi_count);
}
/*
@@ -3466,9 +3463,8 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
goto repeat;
}
- ata_port_printk(ap, KERN_ERR, "WARNING: synchronous SCSI scan "
- "failed without making any progress,\n"
- " switching to async\n");
+ ata_port_err(ap,
+ "WARNING: synchronous SCSI scan failed without making any progress, switching to async\n");
}
queue_delayed_work(system_long_wq, &ap->hotplug_task,
@@ -3550,8 +3546,8 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
mutex_unlock(&ap->scsi_host->scan_mutex);
if (sdev) {
- ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
- dev_name(&sdev->sdev_gendev));
+ ata_dev_info(dev, "detaching (SCSI %s)\n",
+ dev_name(&sdev->sdev_gendev));
scsi_remove_device(sdev);
scsi_device_put(sdev);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index b1b926c55a72..c24127dd6ef2 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -227,9 +227,9 @@ int ata_sff_busy_sleep(struct ata_port *ap,
}
if (status != 0xff && (status & ATA_BUSY))
- ata_port_printk(ap, KERN_WARNING,
- "port is slow to respond, please be patient "
- "(Status 0x%x)\n", status);
+ ata_port_warn(ap,
+ "port is slow to respond, please be patient (Status 0x%x)\n",
+ status);
timeout = ata_deadline(timer_start, tmout);
while (status != 0xff && (status & ATA_BUSY) &&
@@ -242,9 +242,9 @@ int ata_sff_busy_sleep(struct ata_port *ap,
return -ENODEV;
if (status & ATA_BUSY) {
- ata_port_printk(ap, KERN_ERR, "port failed to respond "
- "(%lu secs, Status 0x%x)\n",
- DIV_ROUND_UP(tmout, 1000), status);
+ ata_port_err(ap,
+ "port failed to respond (%lu secs, Status 0x%x)\n",
+ DIV_ROUND_UP(tmout, 1000), status);
return -EBUSY;
}
@@ -350,8 +350,8 @@ static void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep)
{
if (ata_msg_probe(ap))
- ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
- "device %u, wait %u\n", device, wait);
+ ata_port_info(ap, "ata_dev_select: ENTER, device %u, wait %u\n",
+ device, wait);
if (wait)
ata_wait_idle(ap);
@@ -1333,9 +1333,10 @@ void ata_sff_flush_pio_task(struct ata_port *ap)
cancel_delayed_work_sync(&ap->sff_pio_task);
ap->hsm_task_state = HSM_ST_IDLE;
+ ap->sff_pio_task_link = NULL;
if (ata_msg_ctl(ap))
- ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__);
+ ata_port_dbg(ap, "%s: EXIT\n", __func__);
}
static void ata_sff_pio_task(struct work_struct *work)
@@ -1513,7 +1514,7 @@ static unsigned int ata_sff_idle_irq(struct ata_port *ap)
ap->ops->sff_check_status(ap);
if (ap->ops->sff_irq_clear)
ap->ops->sff_irq_clear(ap);
- ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+ ata_port_warn(ap, "irq trap\n");
return 1;
}
#endif
@@ -1711,7 +1712,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap)
/* There was a command running, we are no longer busy and we have
no interrupt. */
- ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n",
+ ata_port_warn(ap, "lost interrupt (Status 0x%x)\n",
status);
/* Run the host interrupt logic as if the interrupt had not been
lost */
@@ -1798,8 +1799,9 @@ int ata_sff_prereset(struct ata_link *link, unsigned long deadline)
if (!ata_link_offline(link)) {
rc = ata_sff_wait_ready(link, deadline);
if (rc && rc != -ENODEV) {
- ata_link_printk(link, KERN_WARNING, "device not ready "
- "(errno=%d), forcing hardreset\n", rc);
+ ata_link_warn(link,
+ "device not ready (errno=%d), forcing hardreset\n",
+ rc);
ehc->i.action |= ATA_EH_HARDRESET;
}
}
@@ -2056,7 +2058,7 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
rc = ata_bus_softreset(ap, devmask, deadline);
/* if link is occupied, -ENODEV too is an error */
if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
- ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+ ata_link_err(link, "SRST failed (errno=%d)\n", rc);
return rc;
}
@@ -2170,8 +2172,7 @@ void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
/* Can become DEBUG later */
if (count)
- ata_port_printk(ap, KERN_DEBUG,
- "drained %d bytes to clear DRQ.\n", count);
+ ata_port_dbg(ap, "drained %d bytes to clear DRQ\n", count);
}
EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
@@ -2316,9 +2317,9 @@ int ata_pci_sff_init_host(struct ata_host *host)
rc = pcim_iomap_regions(pdev, 0x3 << base,
dev_driver_string(gdev));
if (rc) {
- dev_printk(KERN_WARNING, gdev,
- "failed to request/iomap BARs for port %d "
- "(errno=%d)\n", i, rc);
+ dev_warn(gdev,
+ "failed to request/iomap BARs for port %d (errno=%d)\n",
+ i, rc);
if (rc == -EBUSY)
pcim_pin_device(pdev);
ap->ops = &ata_dummy_port_ops;
@@ -2340,7 +2341,7 @@ int ata_pci_sff_init_host(struct ata_host *host)
}
if (!mask) {
- dev_printk(KERN_ERR, gdev, "no available native port\n");
+ dev_err(gdev, "no available native port\n");
return -ENODEV;
}
@@ -2375,8 +2376,7 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev,
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
if (!host) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to allocate ATA host\n");
+ dev_err(&pdev->dev, "failed to allocate ATA host\n");
rc = -ENOMEM;
goto err_out;
}
@@ -2542,8 +2542,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
pi = ata_sff_find_valid_pi(ppi);
if (!pi) {
- dev_printk(KERN_ERR, &pdev->dev,
- "no valid port_info specified\n");
+ dev_err(&pdev->dev, "no valid port_info specified\n");
return -EINVAL;
}
@@ -3164,8 +3163,7 @@ static void ata_bmdma_nodma(struct ata_host *host, const char *reason)
{
int i;
- dev_printk(KERN_ERR, host->dev, "BMDMA: %s, falling back to PIO\n",
- reason);
+ dev_err(host->dev, "BMDMA: %s, falling back to PIO\n", reason);
for (i = 0; i < 2; i++) {
host->ports[i]->mwdma_mask = 0;
@@ -3297,8 +3295,7 @@ int ata_pci_bmdma_init_one(struct pci_dev *pdev,
pi = ata_sff_find_valid_pi(ppi);
if (!pi) {
- dev_printk(KERN_ERR, &pdev->dev,
- "no valid port_info specified\n");
+ dev_err(&pdev->dev, "no valid port_info specified\n");
return -EINVAL;
}
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 91949d997555..54145edf50e8 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -195,8 +195,6 @@ static int pacpi_port_start(struct ata_port *ap)
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct pata_acpi *acpi;
- int ret;
-
if (ap->acpi_handle == NULL)
return -ENODEV;
@@ -205,11 +203,7 @@ static int pacpi_port_start(struct ata_port *ap)
return -ENOMEM;
acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);
acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]);
- ret = ata_bmdma_port_start(ap);
- if (ret < 0)
- return ret;
-
- return ret;
+ return ata_bmdma_port_start(ap);
}
static struct scsi_host_template pacpi_sht = {
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 794ec6e3275d..cadd67998bac 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -287,10 +287,10 @@ static void ali_warn_atapi_dma(struct ata_device *adev)
int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
- ata_dev_printk(adev, KERN_WARNING,
- "WARNING: ATAPI DMA disabled for reliability issues. It can be enabled\n");
- ata_dev_printk(adev, KERN_WARNING,
- "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
+ ata_dev_warn(adev,
+ "WARNING: ATAPI DMA disabled for reliability issues. It can be enabled\n");
+ ata_dev_warn(adev,
+ "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
}
}
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index b0975a5ad8c4..dc6b5dae0463 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -60,7 +60,7 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
UT = T / 2;
if (ata_timing_compute(adev, speed, &at, T, UT) < 0) {
- dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed);
+ dev_err(&pdev->dev, "unknown mode %d\n", speed);
return;
}
@@ -311,7 +311,7 @@ static unsigned long nv_mode_filter(struct ata_device *dev,
cable detection result */
limit |= ata_pack_xfermask(ATA_PIO4, ATA_MWDMA2, ATA_UDMA2);
- ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
+ ata_port_dbg(ap, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
xfer_mask, limit, xfer_mask & limit, bios_limit,
saved_udma, acpi_limit, acpi_str);
@@ -530,14 +530,12 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
};
const struct ata_port_info *ppi[] = { NULL, NULL };
- static int printed_version;
int type = id->driver_data;
void *hpriv = NULL;
u8 fifo;
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 2215632e4b31..78a93b690959 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -346,7 +346,6 @@ static struct ata_port_operations artop6260_ops = {
static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
{
- static int printed_version;
static const struct ata_port_info info_6210 = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -378,9 +377,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
const struct ata_port_info *ppi[] = { NULL, NULL };
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c
index 95295935dd95..3cfabb262af2 100644
--- a/drivers/ata/pata_atp867x.c
+++ b/drivers/ata/pata_atp867x.c
@@ -470,7 +470,7 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host)
}
if (!mask) {
- dev_printk(KERN_ERR, gdev, "no available native port\n");
+ dev_err(gdev, "no available native port\n");
return -ENODEV;
}
@@ -487,7 +487,6 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host)
static int atp867x_init_one(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- static int printed_version;
static const struct ata_port_info info_867x = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -499,8 +498,7 @@ static int atp867x_init_one(struct pci_dev *pdev,
const struct ata_port_info *ppi[] = { &info_867x, NULL };
int rc;
- if (!printed_version++)
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
@@ -511,15 +509,14 @@ static int atp867x_init_one(struct pci_dev *pdev,
host = ata_host_alloc_pinfo(&pdev->dev, ppi, ATP867X_NUM_PORTS);
if (!host) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to allocate ATA host\n");
+ dev_err(&pdev->dev, "failed to allocate ATA host\n");
rc = -ENOMEM;
goto err_out;
}
rc = atp867x_ata_pci_sff_init_host(host);
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev, "failed to init host\n");
+ dev_err(&pdev->dev, "failed to init host\n");
goto err_out;
}
@@ -528,7 +525,7 @@ static int atp867x_init_one(struct pci_dev *pdev,
rc = ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
IRQF_SHARED, &atp867x_sht);
if (rc)
- dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n");
+ dev_err(&pdev->dev, "failed to activate host\n");
err_out:
return rc;
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index ea64967000ff..bd987bb082eb 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1129,7 +1129,7 @@ static int bfin_softreset(struct ata_link *link, unsigned int *classes,
/* issue bus reset */
err_mask = bfin_bus_softreset(ap, devmask);
if (err_mask) {
- ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
+ ata_port_err(ap, "SRST failed (err_mask=0x%x)\n",
err_mask);
return -EIO;
}
@@ -1382,7 +1382,7 @@ idle_irq:
#ifdef ATA_IRQ_TRAP
if ((ap->stats.idle_irq % 1000) == 0) {
ap->ops->irq_ack(ap, 0); /* debug trap */
- ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+ ata_port_warn(ap, "irq trap\n");
return 1;
}
#endif
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index e3254fcff0f1..9ddcddc66a20 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -149,8 +149,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
ppi[1] = &pi;
if ((pcicfg & 0x40) == 0) {
- dev_printk(KERN_WARNING, &pdev->dev,
- "DMA mode disabled. Enabling.\n");
+ dev_warn(&pdev->dev, "DMA mode disabled. Enabling.\n");
pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
}
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index a08834758ea2..aca47e4e29ea 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -263,7 +263,6 @@ static struct ata_port_operations efar_ops = {
static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -273,9 +272,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
};
const struct ata_port_info *ppi[] = { &info, &info };
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL,
ATA_HOST_PARALLEL_SCAN);
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 24d7df81546b..b3042dab08bb 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -185,7 +185,6 @@ static void hpt3x3_init_chipset(struct pci_dev *dev)
static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
- static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -206,8 +205,7 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
hpt3x3_init_chipset(pdev);
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
if (!host)
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index 9f2889fe43b2..52e7e7b8c74f 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -210,8 +210,8 @@ static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev
else
iomd_type = 'A', cycle = 562;
- ata_dev_printk(adev, KERN_INFO, "timings: act %dns rec %dns cyc %dns (%c)\n",
- t.active, t.recover, t.cycle, iomd_type);
+ ata_dev_info(adev, "timings: act %dns rec %dns cyc %dns (%c)\n",
+ t.active, t.recover, t.cycle, iomd_type);
state->port[ap->port_no].speed[adev->devno] = cycle;
}
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 4d142a2ab8fd..998af0e629b1 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -258,7 +258,6 @@ static struct ata_port_operations it8213_ops = {
static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -269,9 +268,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
/* Current IT8213 stuff is single port */
const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
return ata_pci_bmdma_init_one(pdev, ppi, &it8213_sht, NULL, 0);
}
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 2d15f2548a10..62c5d00abd2e 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -473,12 +473,12 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus
/* We do need the right mode information for DMA or PIO
and this comes from the current configuration flags */
if (ata_id_has_dma(dev->id)) {
- ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
+ ata_dev_info(dev, "configured for DMA\n");
dev->xfer_mode = XFER_MW_DMA_0;
dev->xfer_shift = ATA_SHIFT_MWDMA;
dev->flags &= ~ATA_DFLAG_PIO;
} else {
- ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+ ata_dev_info(dev, "configured for PIO\n");
dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO;
dev->flags |= ATA_DFLAG_PIO;
@@ -508,12 +508,12 @@ static void it821x_dev_config(struct ata_device *adev)
if (strstr(model_num, "Integrated Technology Express")) {
/* RAID mode */
- ata_dev_printk(adev, KERN_INFO, "%sRAID%d volume",
- adev->id[147]?"Bootable ":"",
- adev->id[129]);
+ ata_dev_info(adev, "%sRAID%d volume",
+ adev->id[147] ? "Bootable " : "",
+ adev->id[129]);
if (adev->id[129] != 1)
- printk("(%dK stripe)", adev->id[146]);
- printk(".\n");
+ pr_cont("(%dK stripe)", adev->id[146]);
+ pr_cont("\n");
}
/* This is a controller firmware triggered funny, don't
report the drive faulty! */
@@ -610,7 +610,7 @@ static void it821x_display_disk(int n, u8 *buf)
char *cbl = "(40 wire cable)";
static const char *types[5] = {
- "RAID0", "RAID1" "RAID 0+1", "JBOD", "DISK"
+ "RAID0", "RAID1", "RAID 0+1", "JBOD", "DISK"
};
if (buf[52] > 4) /* No Disk */
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index f6b3f995f58a..15b64311fe0a 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -31,7 +31,7 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
struct ata_device *dev;
ata_for_each_dev(dev, link, ENABLED) {
- ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
+ ata_dev_info(dev, "configured for PIO0\n");
dev->pio_mode = XFER_PIO_0;
dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO;
@@ -181,7 +181,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* activate host */
return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 6bd9425ba5ab..d960f8e9e8b1 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -213,7 +213,7 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
struct ata_device *dev;
ata_for_each_dev(dev, link, ENABLED) {
- ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+ ata_dev_info(dev, "configured for PIO\n");
dev->pio_mode = XFER_PIO_0;
dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO;
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index 46f589edccdb..b057e3fa44bc 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -772,8 +772,9 @@ static void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume)
pci_restore_state(priv->pdev);
rc = pcim_enable_device(priv->pdev);
if (rc)
- dev_printk(KERN_ERR, &priv->pdev->dev,
- "Failed to enable device after resume (%d)\n", rc);
+ dev_err(&priv->pdev->dev,
+ "Failed to enable device after resume (%d)\n",
+ rc);
else
pci_set_master(priv->pdev);
}
@@ -812,7 +813,7 @@ static int pata_macio_slave_config(struct scsi_device *sdev)
blk_queue_update_dma_pad(sdev->request_queue, 31);
/* Tell the world about it */
- ata_dev_printk(dev, KERN_INFO, "OHare alignment limits applied\n");
+ ata_dev_info(dev, "OHare alignment limits applied\n");
return 0;
}
@@ -838,8 +839,7 @@ static int pata_macio_slave_config(struct scsi_device *sdev)
cmd | PCI_COMMAND_INVALIDATE);
/* Tell the world about it */
- ata_dev_printk(dev, KERN_INFO,
- "K2/Shasta alignment limits applied\n");
+ ata_dev_info(dev, "K2/Shasta alignment limits applied\n");
}
return 0;
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index d8d9c5807740..9dc16df84191 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -152,15 +152,13 @@ static struct ata_port_operations mpiix_port_ops = {
static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
/* Single threaded by the PCI probe logic */
- static int printed_version;
struct ata_host *host;
struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
u16 idetim;
int cmd, ctl, irq;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&dev->dev, DRV_VERSION);
host = ata_host_alloc(&dev->dev, 1);
if (!host)
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 3eb921c746a1..9979a43bc596 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -57,7 +57,6 @@ static struct ata_port_operations netcell_ops = {
static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
/* Actually we don't really care about these as the
@@ -70,9 +69,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
const struct ata_port_info *port_info[] = { &info, NULL };
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 2110863bb3db..31d5986537a3 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -86,7 +86,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
idefr &= ~0x04;
if (ata_timing_compute(adev, adev->pio_mode, &at, 30303, 1) < 0) {
- dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", adev->pio_mode);
+ dev_err(&pdev->dev, "unknown mode %d\n", adev->pio_mode);
return;
}
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index 605f198f958c..f1d517bc5b49 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -350,7 +350,6 @@ static void ns87415_fixup(struct pci_dev *pdev)
static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -370,9 +369,7 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
if (PCI_SLOT(pdev->devfn) == 0x0E)
ppi[0] = &info87560;
#endif
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index 220ddc90608f..1d61d5d278fa 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -405,7 +405,7 @@ static int octeon_cf_softreset16(struct ata_link *link, unsigned int *classes,
rc = ata_sff_wait_after_reset(link, 1, deadline);
if (rc) {
- ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+ ata_link_err(link, "SRST failed (errno=%d)\n", rc);
return rc;
}
@@ -807,6 +807,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
irq_handler_t irq_handler = NULL;
void __iomem *base;
struct octeon_cf_port *cf_port;
+ char version[32];
res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -905,10 +906,11 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);
- dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n",
+ snprintf(version, sizeof(version), "%s %d bit%s",
+ DRV_VERSION,
(ocd->is16bit) ? 16 : 8,
(cs1) ? ", True IDE" : "");
-
+ ata_print_version_once(&pdev->dev, version);
return ata_host_activate(host, irq, irq_handler, 0, &octeon_cf_sht);
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index b811c1636204..98cdf50e4065 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -235,7 +235,6 @@ static struct ata_port_operations oldpiix_pata_ops = {
static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -244,9 +243,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
};
const struct ata_port_info *ppi[] = { &info, NULL };
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
return ata_pci_bmdma_init_one(pdev, ppi, &oldpiix_sht, NULL, 0);
}
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 00c5a02a94fc..accc033faf77 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -167,10 +167,8 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.port_ops = &opti_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
- static int printed_version;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&dev->dev, DRV_VERSION);
return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL, 0);
}
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 0852cd07de08..77cb91408632 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -411,11 +411,9 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.port_ops = &optiplus_port_ops
};
const struct ata_port_info *ppi[] = { &info_82c700, NULL };
- static int printed_version;
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&dev->dev, DRV_VERSION);
rc = pcim_enable_device(dev);
if (rc)
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 021abe6d8527..a808ba03bd7f 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -68,7 +68,7 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d
the same vendor - check serial */
if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO,
ATA_ID_SERNO_LEN) == 0 && master->id[ATA_ID_SERNO] >> 8) {
- ata_dev_printk(slave, KERN_WARNING, "is a ghost device, ignoring.\n");
+ ata_dev_warn(slave, "is a ghost device, ignoring\n");
ata_dev_disable(slave);
}
}
@@ -142,8 +142,7 @@ static void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
ioread8(ap->ioaddr.data_addr);
if (count)
- ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n",
- count);
+ ata_port_warn(ap, "drained %d bytes to clear DRQ\n", count);
}
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 9765ace16921..b1511f38b0e8 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -655,7 +655,7 @@ static int pdc_hardware_init(struct ata_host *host, unsigned int board_idx)
*/
pll_clock = pdc_detect_pll_input_clock(host);
- dev_printk(KERN_INFO, host->dev, "PLL input clock %ld kHz\n", pll_clock/1000);
+ dev_info(host->dev, "PLL input clock %ld kHz\n", pll_clock/1000);
/* Adjust PLL control register */
pdc_adjust_pll(host, pll_clock, board_idx);
@@ -697,7 +697,6 @@ static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
*/
static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
static const unsigned long cmd_offset[] = { 0x17c0, 0x15c0 };
static const unsigned long bmdma_offset[] = { 0x1000, 0x1008 };
unsigned int board_idx = (unsigned int) ent->driver_data;
@@ -707,8 +706,7 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
void __iomem *mmio_base;
int i, rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* alloc host */
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 50400fa120fe..2067308f683f 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -39,7 +39,7 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu
dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO;
dev->flags |= ATA_DFLAG_PIO;
- ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+ ata_dev_info(dev, "configured for PIO\n");
}
return 0;
}
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 8574b31f1773..b2d3a2bb4e60 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -213,7 +213,6 @@ static struct ata_port_operations radisys_pata_ops = {
static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@@ -223,9 +222,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
};
const struct ata_port_info *ppi[] = { &info, NULL };
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
return ata_pci_bmdma_init_one(pdev, ppi, &radisys_sht, NULL, 0);
}
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
index 5fbe9b166c69..4d318f86ae86 100644
--- a/drivers/ata/pata_rdc.c
+++ b/drivers/ata/pata_rdc.c
@@ -312,7 +312,6 @@ static struct scsi_host_template rdc_sht = {
static int __devinit rdc_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
struct device *dev = &pdev->dev;
struct ata_port_info port_info[2];
const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
@@ -321,9 +320,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
struct rdc_host_priv *hpriv;
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
port_info[0] = rdc_port_info;
port_info[1] = rdc_port_info;
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 4d04471794b6..aca321e1e6a2 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -44,7 +44,7 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)
dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO;
dev->flags |= ATA_DFLAG_PIO;
- ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+ ata_dev_info(dev, "configured for PIO\n");
}
return 0;
}
@@ -92,7 +92,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
};
const struct ata_port_info *ppi[] = { &info, NULL };
- printk_once(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
if (rz1000_fifo_disable(pdev) == 0)
return ata_pci_sff_init_one(pdev, ppi, &rz1000_sht, NULL, 0);
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index c446ae6055a3..1b372c297195 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -376,7 +376,7 @@ static int pata_s3c_softreset(struct ata_link *link, unsigned int *classes,
rc = pata_s3c_bus_softreset(ap, deadline);
/* if link is occupied, -ENODEV too is an error */
if (rc && rc != -ENODEV) {
- ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+ ata_link_err(link, "SRST failed (errno=%d)\n", rc);
return rc;
}
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 88ea9b677b47..eb748e327143 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -637,8 +637,7 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes,
DPRINTK("about to softreset, devmask=%x\n", devmask);
err_mask = scc_bus_softreset(ap, devmask, deadline);
if (err_mask) {
- ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
- err_mask);
+ ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask);
return -EIO;
}
@@ -1072,15 +1071,12 @@ static int scc_host_init(struct ata_host *host)
static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
unsigned int board_idx = (unsigned int) ent->driver_data;
const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL };
struct ata_host *host;
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1);
if (!host)
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
index e97b32f03a6e..7c78b9993627 100644
--- a/drivers/ata/pata_sch.c
+++ b/drivers/ata/pata_sch.c
@@ -172,12 +172,9 @@ static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev)
static int __devinit sch_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *ppi[] = { &sch_port_info, NULL };
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);
}
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 118787caa93f..31f759b0ab71 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -327,13 +327,11 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
.port_ops = &sil680_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
- static int printed_version;
struct ata_host *host;
void __iomem *mmio_base;
int rc, try_mmio;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index be08ff92db17..533f2aefab87 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -681,7 +681,6 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *ppi[] = { NULL, NULL };
struct pci_dev *host = NULL;
struct sis_chipset *chipset = NULL;
@@ -735,9 +734,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
0x0, &sis_info100
};
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev,
- "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 7f5d020ed56c..c06ce8ced566 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -317,9 +317,11 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
rev = sl82c105_bridge_revision(dev);
if (rev == -1)
- dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Unable to find bridge, disabling DMA.\n");
+ dev_warn(&dev->dev,
+ "pata_sl82c105: Unable to find bridge, disabling DMA\n");
else if (rev <= 5)
- dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Early bridge revision, no DMA available.\n");
+ dev_warn(&dev->dev,
+ "pata_sl82c105: Early bridge revision, no DMA available\n");
else
ppi[0] = &info_dma;
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index b3e0c9432283..28da1c6becf1 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -196,10 +196,8 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.port_ops = &triflex_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
- static int printed_version;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&dev->dev, DRV_VERSION);
return ata_pci_bmdma_init_one(dev, ppi, &triflex_sht, NULL, 0);
}
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index ac8d7d97e408..65e4be6be220 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -350,8 +350,8 @@ static unsigned long via_mode_filter(struct ata_device *dev, unsigned long mask)
if (config->id == PCI_DEVICE_ID_VIA_82C586_0) {
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
if (strcmp(model_num, "TS64GSSD25-M") == 0) {
- ata_dev_printk(dev, KERN_WARNING,
- "disabling UDMA mode due to reported lockups with this device.\n");
+ ata_dev_warn(dev,
+ "disabling UDMA mode due to reported lockups with this device\n");
mask &= ~ ATA_MASK_UDMA;
}
}
@@ -551,14 +551,12 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
const struct ata_port_info *ppi[] = { NULL, NULL };
struct pci_dev *isa;
const struct via_isa_bridge *config;
- static int printed_version;
u8 enable;
u32 timing;
unsigned long flags = id->driver_data;
int rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 1111712b3d7d..04911d52f59d 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -596,14 +596,12 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit consistent DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");
return rc;
}
return 0;
@@ -612,15 +610,13 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
static int adma_ata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
unsigned int board_idx = (unsigned int) ent->driver_data;
const struct ata_port_info *ppi[] = { &adma_port_info[board_idx], NULL };
struct ata_host *host;
void __iomem *mmio_base;
int rc, port_no;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* alloc host */
host = ata_host_alloc_pinfo(&pdev->dev, ppi, ADMA_PORTS);
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index dc88a39e7db8..0a9a774a7e1e 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -766,11 +766,15 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
static void dma_dwc_exit(struct sata_dwc_device *hsdev)
{
dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__);
- if (host_pvt.sata_dma_regs)
+ if (host_pvt.sata_dma_regs) {
iounmap(host_pvt.sata_dma_regs);
+ host_pvt.sata_dma_regs = NULL;
+ }
- if (hsdev->irq_dma)
+ if (hsdev->irq_dma) {
free_irq(hsdev->irq_dma, hsdev);
+ hsdev->irq_dma = 0;
+ }
}
/*
@@ -1638,13 +1642,12 @@ static int sata_dwc_probe(struct platform_device *ofdev)
const struct ata_port_info *ppi[] = { &pi, NULL };
/* Allocate DWC SATA device */
- hsdev = kmalloc(sizeof(*hsdev), GFP_KERNEL);
+ hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
if (hsdev == NULL) {
dev_err(&ofdev->dev, "kmalloc failed for hsdev\n");
err = -ENOMEM;
- goto error_out;
+ goto error;
}
- memset(hsdev, 0, sizeof(*hsdev));
/* Ioremap SATA registers */
base = of_iomap(ofdev->dev.of_node, 0);
@@ -1652,7 +1655,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
dev_err(&ofdev->dev, "ioremap failed for SATA register"
" address\n");
err = -ENODEV;
- goto error_out;
+ goto error_kmalloc;
}
hsdev->reg_base = base;
dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n");
@@ -1665,7 +1668,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
if (!host) {
dev_err(&ofdev->dev, "ata_host_alloc_pinfo failed\n");
err = -ENOMEM;
- goto error_out;
+ goto error_iomap;
}
host->private_data = hsdev;
@@ -1733,8 +1736,11 @@ error_out:
/* Free SATA DMA resources */
dma_dwc_exit(hsdev);
- if (base)
- iounmap(base);
+error_iomap:
+ iounmap(base);
+error_kmalloc:
+ kfree(hsdev);
+error:
return err;
}
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 35a71d875d0e..78ae7b67b09e 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -346,12 +346,11 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
/* warn if each s/g element is not dword aligned */
if (sg_addr & 0x03)
- ata_port_printk(qc->ap, KERN_ERR,
- "s/g addr unaligned : 0x%llx\n",
- (unsigned long long)sg_addr);
+ ata_port_err(qc->ap, "s/g addr unaligned : 0x%llx\n",
+ (unsigned long long)sg_addr);
if (sg_len & 0x03)
- ata_port_printk(qc->ap, KERN_ERR,
- "s/g len unaligned : 0x%x\n", sg_len);
+ ata_port_err(qc->ap, "s/g len unaligned : 0x%x\n",
+ sg_len);
if (num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1) &&
sg_next(sg) != NULL) {
@@ -661,8 +660,7 @@ static int sata_fsl_port_start(struct ata_port *ap)
sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp);
sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp);
- dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n",
- temp);
+ dev_warn(dev, "scr_control, speed limited to %x\n", temp);
#endif
return 0;
@@ -740,8 +738,7 @@ try_offline_again:
1, 500);
if (temp & ONLINE) {
- ata_port_printk(ap, KERN_ERR,
- "Hardreset failed, not off-lined %d\n", i);
+ ata_port_err(ap, "Hardreset failed, not off-lined %d\n", i);
/*
* Try to offline controller atleast twice
@@ -777,8 +774,7 @@ try_offline_again:
temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, 0, 1, 500);
if (!(temp & ONLINE)) {
- ata_port_printk(ap, KERN_ERR,
- "Hardreset failed, not on-lined\n");
+ ata_port_err(ap, "Hardreset failed, not on-lined\n");
goto err;
}
@@ -794,9 +790,8 @@ try_offline_again:
temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0, 1, 500);
if ((!(temp & 0x10)) || ata_link_offline(link)) {
- ata_port_printk(ap, KERN_WARNING,
- "No Device OR PHYRDY change,Hstatus = 0x%x\n",
- ioread32(hcr_base + HSTATUS));
+ ata_port_warn(ap, "No Device OR PHYRDY change,Hstatus = 0x%x\n",
+ ioread32(hcr_base + HSTATUS));
*class = ATA_DEV_NONE;
return 0;
}
@@ -809,13 +804,12 @@ try_offline_again:
500, jiffies_to_msecs(deadline - start_jiffies));
if ((temp & 0xFF) != 0x18) {
- ata_port_printk(ap, KERN_WARNING, "No Signature Update\n");
+ ata_port_warn(ap, "No Signature Update\n");
*class = ATA_DEV_NONE;
goto do_followup_srst;
} else {
- ata_port_printk(ap, KERN_INFO,
- "Signature Update detected @ %d msecs\n",
- jiffies_to_msecs(jiffies - start_jiffies));
+ ata_port_info(ap, "Signature Update detected @ %d msecs\n",
+ jiffies_to_msecs(jiffies - start_jiffies));
*class = sata_fsl_dev_classify(ap);
return 0;
}
@@ -890,7 +884,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
temp = ata_wait_register(ap, CQ + hcr_base, 0x1, 0x1, 1, 5000);
if (temp & 0x1) {
- ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n");
+ ata_port_warn(ap, "ATA_SRST issue failed\n");
DPRINTK("Softreset@5000,CQ=0x%x,CA=0x%x,CC=0x%x\n",
ioread32(CQ + hcr_base),
@@ -1202,8 +1196,7 @@ static irqreturn_t sata_fsl_interrupt(int irq, void *dev_instance)
if (ap) {
sata_fsl_host_intr(ap);
} else {
- dev_printk(KERN_WARNING, host->dev,
- "interrupt on disabled port 0\n");
+ dev_warn(host->dev, "interrupt on disabled port 0\n");
}
iowrite32(interrupt_enables, hcr_base + HSTATUS);
@@ -1317,8 +1310,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
struct ata_port_info pi = sata_fsl_port_info[0];
const struct ata_port_info *ppi[] = { &pi, NULL };
- dev_printk(KERN_INFO, &ofdev->dev,
- "Sata FSL Platform/CSB Driver init\n");
+ dev_info(&ofdev->dev, "Sata FSL Platform/CSB Driver init\n");
hcr_base = of_iomap(ofdev->dev.of_node, 0);
if (!hcr_base)
@@ -1347,7 +1339,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
if (irq < 0) {
- dev_printk(KERN_ERR, &ofdev->dev, "invalid irq from platform\n");
+ dev_err(&ofdev->dev, "invalid irq from platform\n");
goto error_exit_with_cleanup;
}
host_priv->irq = irq;
@@ -1422,8 +1414,7 @@ static int sata_fsl_resume(struct platform_device *op)
ret = sata_fsl_init_controller(host);
if (ret) {
- dev_printk(KERN_ERR, &op->dev,
- "Error initialize hardware\n");
+ dev_err(&op->dev, "Error initializing hardware\n");
return ret;
}
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 83a44471b189..5c7d70c03bf0 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -396,9 +396,8 @@ static void inic_host_intr(struct ata_port *ap)
}
spurious:
- ata_port_printk(ap, KERN_WARNING, "unhandled interrupt: "
- "cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n",
- qc ? qc->tf.command : 0xff, irq_stat, idma_stat);
+ ata_port_warn(ap, "unhandled interrupt: cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n",
+ qc ? qc->tf.command : 0xff, irq_stat, idma_stat);
}
static irqreturn_t inic_interrupt(int irq, void *dev_instance)
@@ -619,8 +618,9 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
rc = sata_link_resume(link, timing, deadline);
if (rc) {
- ata_link_printk(link, KERN_WARNING, "failed to resume "
- "link after reset (errno=%d)\n", rc);
+ ata_link_warn(link,
+ "failed to resume link after reset (errno=%d)\n",
+ rc);
return rc;
}
@@ -632,8 +632,9 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
rc = ata_wait_after_reset(link, deadline, inic_check_ready);
/* link occupied, -ENODEV too is an error */
if (rc) {
- ata_link_printk(link, KERN_WARNING, "device not ready "
- "after hardreset (errno=%d)\n", rc);
+ ata_link_warn(link,
+ "device not ready after hardreset (errno=%d)\n",
+ rc);
return rc;
}
@@ -799,7 +800,6 @@ static int inic_pci_device_resume(struct pci_dev *pdev)
static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *ppi[] = { &inic_port_info, NULL };
struct ata_host *host;
struct inic_host_priv *hpriv;
@@ -807,8 +807,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
int mmio_bar;
int i, rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* alloc host */
host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);
@@ -847,15 +846,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Set dma_mask. This devices doesn't support 64bit addressing. */
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit consistent DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");
return rc;
}
@@ -866,15 +863,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
rc = pci_set_dma_max_seg_size(pdev, 65536 - 512);
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to set the maximum segment size.\n");
+ dev_err(&pdev->dev, "failed to set the maximum segment size\n");
return rc;
}
rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to initialize controller\n");
+ dev_err(&pdev->dev, "failed to initialize controller\n");
return rc;
}
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index b52c0519ad0b..4b6b2090784b 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1190,7 +1190,7 @@ static void mv_wait_for_edma_empty_idle(struct ata_port *ap)
break;
udelay(per_loop);
}
- /* ata_port_printk(ap, KERN_INFO, "%s: %u+ usecs\n", __func__, i); */
+ /* ata_port_info(ap, "%s: %u+ usecs\n", __func__, i); */
}
/**
@@ -1228,7 +1228,7 @@ static int mv_stop_edma(struct ata_port *ap)
pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
mv_wait_for_edma_empty_idle(ap);
if (mv_stop_edma_engine(port_mmio)) {
- ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
+ ata_port_err(ap, "Unable to stop eDMA\n");
err = -EIO;
}
mv_edma_cfg(ap, 0, 0);
@@ -1382,7 +1382,7 @@ static void mv6_dev_config(struct ata_device *adev)
if (adev->flags & ATA_DFLAG_NCQ) {
if (sata_pmp_attached(adev->link->ap)) {
adev->flags &= ~ATA_DFLAG_NCQ;
- ata_dev_printk(adev, KERN_INFO,
+ ata_dev_info(adev,
"NCQ disabled for command-based switching\n");
}
}
@@ -2225,9 +2225,8 @@ static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords)
/* See if it worked */
if ((ifstat & 0x3000) != 0x1000) {
- ata_port_printk(ap, KERN_WARNING,
- "%s transmission error, ifstat=%08x\n",
- __func__, ifstat);
+ ata_port_warn(ap, "%s transmission error, ifstat=%08x\n",
+ __func__, ifstat);
return AC_ERR_OTHER;
}
return 0;
@@ -2342,9 +2341,9 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
*/
if (limit_warnings > 0 && (qc->nbytes / qc->sect_size) > 1) {
--limit_warnings;
- ata_link_printk(qc->dev->link, KERN_WARNING, DRV_NAME
- ": attempting PIO w/multiple DRQ: "
- "this may fail due to h/w errata\n");
+ ata_link_warn(qc->dev->link, DRV_NAME
+ ": attempting PIO w/multiple DRQ: "
+ "this may fail due to h/w errata\n");
}
/* drop through */
case ATA_PROT_NODATA:
@@ -2499,20 +2498,20 @@ static int mv_handle_fbs_ncq_dev_err(struct ata_port *ap)
}
failed_links = hweight16(new_map);
- ata_port_printk(ap, KERN_INFO, "%s: pmp_map=%04x qc_map=%04x "
- "failed_links=%d nr_active_links=%d\n",
- __func__, pp->delayed_eh_pmp_map,
- ap->qc_active, failed_links,
- ap->nr_active_links);
+ ata_port_info(ap,
+ "%s: pmp_map=%04x qc_map=%04x failed_links=%d nr_active_links=%d\n",
+ __func__, pp->delayed_eh_pmp_map,
+ ap->qc_active, failed_links,
+ ap->nr_active_links);
if (ap->nr_active_links <= failed_links && mv_req_q_empty(ap)) {
mv_process_crpb_entries(ap, pp);
mv_stop_edma(ap);
mv_eh_freeze(ap);
- ata_port_printk(ap, KERN_INFO, "%s: done\n", __func__);
+ ata_port_info(ap, "%s: done\n", __func__);
return 1; /* handled */
}
- ata_port_printk(ap, KERN_INFO, "%s: waiting\n", __func__);
+ ata_port_info(ap, "%s: waiting\n", __func__);
return 1; /* handled */
}
@@ -2554,9 +2553,8 @@ static int mv_handle_dev_err(struct ata_port *ap, u32 edma_err_cause)
* and we cannot handle it here.
*/
if (edma_err_cause & EDMA_ERR_SELF_DIS) {
- ata_port_printk(ap, KERN_WARNING,
- "%s: err_cause=0x%x pp_flags=0x%x\n",
- __func__, edma_err_cause, pp->pp_flags);
+ ata_port_warn(ap, "%s: err_cause=0x%x pp_flags=0x%x\n",
+ __func__, edma_err_cause, pp->pp_flags);
return 0; /* not handled */
}
return mv_handle_fbs_ncq_dev_err(ap);
@@ -2567,9 +2565,8 @@ static int mv_handle_dev_err(struct ata_port *ap, u32 edma_err_cause)
* and we cannot handle it here.
*/
if (!(edma_err_cause & EDMA_ERR_SELF_DIS)) {
- ata_port_printk(ap, KERN_WARNING,
- "%s: err_cause=0x%x pp_flags=0x%x\n",
- __func__, edma_err_cause, pp->pp_flags);
+ ata_port_warn(ap, "%s: err_cause=0x%x pp_flags=0x%x\n",
+ __func__, edma_err_cause, pp->pp_flags);
return 0; /* not handled */
}
return mv_handle_fbs_non_ncq_dev_err(ap);
@@ -2930,8 +2927,7 @@ static int mv_pci_error(struct ata_host *host, void __iomem *mmio)
err_cause = readl(mmio + hpriv->irq_cause_offset);
- dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
- err_cause);
+ dev_err(host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", err_cause);
DPRINTK("All regs @ PCI error\n");
mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
@@ -3760,8 +3756,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
hp_flags |= MV_HP_ERRATA_50XXB2;
break;
default:
- dev_printk(KERN_WARNING, &pdev->dev,
- "Applying 50XXB2 workarounds to unknown rev\n");
+ dev_warn(&pdev->dev,
+ "Applying 50XXB2 workarounds to unknown rev\n");
hp_flags |= MV_HP_ERRATA_50XXB2;
break;
}
@@ -3780,8 +3776,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
hp_flags |= MV_HP_ERRATA_50XXB2;
break;
default:
- dev_printk(KERN_WARNING, &pdev->dev,
- "Applying B2 workarounds to unknown rev\n");
+ dev_warn(&pdev->dev,
+ "Applying B2 workarounds to unknown rev\n");
hp_flags |= MV_HP_ERRATA_50XXB2;
break;
}
@@ -3801,8 +3797,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
hp_flags |= MV_HP_ERRATA_60X1C0;
break;
default:
- dev_printk(KERN_WARNING, &pdev->dev,
- "Applying B2 workarounds to unknown rev\n");
+ dev_warn(&pdev->dev,
+ "Applying B2 workarounds to unknown rev\n");
hp_flags |= MV_HP_ERRATA_60X1B2;
break;
}
@@ -3851,8 +3847,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
hp_flags |= MV_HP_ERRATA_60X1C0;
break;
default:
- dev_printk(KERN_WARNING, &pdev->dev,
- "Applying 60X1C0 workarounds to unknown rev\n");
+ dev_warn(&pdev->dev,
+ "Applying 60X1C0 workarounds to unknown rev\n");
hp_flags |= MV_HP_ERRATA_60X1C0;
break;
}
@@ -3867,8 +3863,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
break;
default:
- dev_printk(KERN_ERR, host->dev,
- "BUG: invalid board index %u\n", board_idx);
+ dev_err(host->dev, "BUG: invalid board index %u\n", board_idx);
return 1;
}
@@ -4023,7 +4018,6 @@ static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,
*/
static int mv_platform_probe(struct platform_device *pdev)
{
- static int printed_version;
const struct mv_sata_platform_data *mv_platform_data;
const struct ata_port_info *ppi[] =
{ &mv_port_info[chip_soc], NULL };
@@ -4032,8 +4026,7 @@ static int mv_platform_probe(struct platform_device *pdev)
struct resource *res;
int n_ports, rc;
- if (!printed_version++)
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/*
* Simple resource validation ..
@@ -4091,9 +4084,8 @@ static int mv_platform_probe(struct platform_device *pdev)
if (rc)
goto err;
- dev_printk(KERN_INFO, &pdev->dev,
- "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH,
- host->n_ports);
+ 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);
@@ -4217,22 +4209,21 @@ static int pci_go_64(struct pci_dev *pdev)
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "64-bit DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "64-bit DMA enable failed\n");
return rc;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit consistent DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "32-bit consistent DMA enable failed\n");
return rc;
}
}
@@ -4276,10 +4267,9 @@ static void mv_print_info(struct ata_host *host)
else
gen = "?";
- dev_printk(KERN_INFO, &pdev->dev,
- "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
- gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
- scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+ dev_info(&pdev->dev, "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
+ gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
+ scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
}
/**
@@ -4293,15 +4283,13 @@ static void mv_print_info(struct ata_host *host)
static int mv_pci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
unsigned int board_idx = (unsigned int)ent->driver_data;
const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
struct ata_host *host;
struct mv_host_priv *hpriv;
int n_ports, port, rc;
- if (!printed_version++)
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* allocate host */
n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index f173ef3bfc10..e0bc9646a38e 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -620,9 +620,8 @@ static void nv_adma_register_mode(struct ata_port *ap)
count++;
}
if (count == 20)
- ata_port_printk(ap, KERN_WARNING,
- "timeout waiting for ADMA IDLE, stat=0x%hx\n",
- status);
+ ata_port_warn(ap, "timeout waiting for ADMA IDLE, stat=0x%hx\n",
+ status);
tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
@@ -635,9 +634,9 @@ static void nv_adma_register_mode(struct ata_port *ap)
count++;
}
if (count == 20)
- ata_port_printk(ap, KERN_WARNING,
- "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
- status);
+ ata_port_warn(ap,
+ "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
+ status);
pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
}
@@ -665,7 +664,7 @@ static void nv_adma_mode(struct ata_port *ap)
count++;
}
if (count == 20)
- ata_port_printk(ap, KERN_WARNING,
+ ata_port_warn(ap,
"timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
status);
@@ -772,10 +771,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
blk_queue_max_segments(sdev->request_queue, sg_tablesize);
- ata_port_printk(ap, KERN_INFO,
- "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
- (unsigned long long)*ap->host->dev->dma_mask,
- segment_boundary, sg_tablesize);
+ ata_port_info(ap,
+ "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
+ (unsigned long long)*ap->host->dev->dma_mask,
+ segment_boundary, sg_tablesize);
spin_unlock_irqrestore(ap->lock, flags);
@@ -1443,8 +1442,7 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
existing commands. */
if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&
(qc->flags & ATA_QCFLAG_RESULT_TF))) {
- ata_dev_printk(qc->dev, KERN_ERR,
- "NCQ w/ RESULT_TF not allowed\n");
+ ata_dev_err(qc->dev, "NCQ w/ RESULT_TF not allowed\n");
return AC_ERR_SYSTEM;
}
@@ -1581,15 +1579,15 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
int rc;
if (!(ehc->i.flags & ATA_EHI_QUIET))
- ata_link_printk(link, KERN_INFO, "nv: skipping "
- "hardreset on occupied port\n");
+ ata_link_info(link,
+ "nv: skipping hardreset on occupied port\n");
/* make sure the link is online */
rc = sata_link_resume(link, timing, deadline);
/* whine about phy resume failure but proceed */
if (rc && rc != -EOPNOTSUPP)
- ata_link_printk(link, KERN_WARNING, "failed to resume "
- "link (errno=%d)\n", rc);
+ ata_link_warn(link, "failed to resume link (errno=%d)\n",
+ rc);
}
/* device signature acquisition is unreliable */
@@ -1686,7 +1684,7 @@ static void nv_adma_error_handler(struct ata_port *ap)
u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);
- ata_port_printk(ap, KERN_ERR,
+ ata_port_err(ap,
"EH in ADMA mode, notifier 0x%X "
"notifier_error 0x%X gen_ctl 0x%X status 0x%X "
"next cpb count 0x%X next cpb idx 0x%x\n",
@@ -1697,7 +1695,7 @@ static void nv_adma_error_handler(struct ata_port *ap)
struct nv_adma_cpb *cpb = &pp->cpb[i];
if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
ap->link.sactive & (1 << i))
- ata_port_printk(ap, KERN_ERR,
+ ata_port_err(ap,
"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
i, cpb->ctl_flags, cpb->resp_flags);
}
@@ -1799,23 +1797,22 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
u32 sactive;
u32 done_mask;
- ata_port_printk(ap, KERN_ERR,
- "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n",
- ap->qc_active, ap->link.sactive);
- ata_port_printk(ap, KERN_ERR,
+ ata_port_err(ap, "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n",
+ ap->qc_active, ap->link.sactive);
+ ata_port_err(ap,
"SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n "
"dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n",
pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag,
pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
- ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n",
- ap->ops->sff_check_status(ap),
- ioread8(ap->ioaddr.error_addr));
+ ata_port_err(ap, "ATA_REG 0x%X ERR_REG 0x%X\n",
+ ap->ops->sff_check_status(ap),
+ ioread8(ap->ioaddr.error_addr));
sactive = readl(pp->sactive_block);
done_mask = pp->qc_active ^ sactive;
- ata_port_printk(ap, KERN_ERR, "tag : dhfis dmafis sdbfis sacitve\n");
+ ata_port_err(ap, "tag : dhfis dmafis sdbfis sactive\n");
for (i = 0; i < ATA_MAX_QUEUE; i++) {
u8 err = 0;
if (pp->qc_active & (1 << i))
@@ -1825,13 +1822,13 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
else
continue;
- ata_port_printk(ap, KERN_ERR,
- "tag 0x%x: %01x %01x %01x %01x %s\n", i,
- (pp->dhfis_bits >> i) & 0x1,
- (pp->dmafis_bits >> i) & 0x1,
- (pp->sdbfis_bits >> i) & 0x1,
- (sactive >> i) & 0x1,
- (err ? "error! tag doesn't exit" : " "));
+ ata_port_err(ap,
+ "tag 0x%x: %01x %01x %01x %01x %s\n", i,
+ (pp->dhfis_bits >> i) & 0x1,
+ (pp->dmafis_bits >> i) & 0x1,
+ (pp->sdbfis_bits >> i) & 0x1,
+ (sactive >> i) & 0x1,
+ (err ? "error! tag doesn't exit" : " "));
}
nv_swncq_pp_reinit(ap);
@@ -1956,8 +1953,8 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
if (strncmp(model_num, "Maxtor", 6) == 0) {
ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
- ata_dev_printk(dev, KERN_NOTICE,
- "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
+ ata_dev_notice(dev, "Disabling SWNCQ mode (depth %x)\n",
+ sdev->queue_depth);
}
return rc;
@@ -2356,7 +2353,6 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)
static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *ppi[] = { NULL, NULL };
struct nv_pi_priv *ipriv;
struct ata_host *host;
@@ -2373,8 +2369,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_resource_start(pdev, bar) == 0)
return -ENODEV;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
@@ -2382,10 +2377,10 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* determine type and allocate host */
if (type == CK804 && adma_enabled) {
- dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
+ dev_notice(&pdev->dev, "Using ADMA mode\n");
type = ADMA;
} else if (type == MCP5x && swncq_enabled) {
- dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n");
+ dev_notice(&pdev->dev, "Using SWNCQ mode\n");
type = SWNCQ;
}
@@ -2429,7 +2424,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
nv_swncq_host_init(host);
if (msi_enabled) {
- dev_printk(KERN_NOTICE, &pdev->dev, "Using MSI\n");
+ dev_notice(&pdev->dev, "Using MSI\n");
pci_enable_msi(pdev);
}
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index a004b1e0ea6d..000fcc99e01d 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -1179,7 +1179,6 @@ static void pdc_host_init(struct ata_host *host)
static int pdc_ata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
const struct ata_port_info *ppi[PDC_MAX_PORTS];
struct ata_host *host;
@@ -1187,8 +1186,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
int n_ports, i, rc;
int is_sataii_tx4;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* enable and acquire resources */
rc = pcim_enable_device(pdev);
@@ -1217,7 +1215,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
if (!host) {
- dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n");
+ dev_err(&pdev->dev, "failed to allocate host\n");
return -ENOMEM;
}
host->iomap = pcim_iomap_table(pdev);
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index c5603265fa58..9d1a47bb21b3 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -563,21 +563,20 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "64-bit DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "64-bit DMA enable failed\n");
return rc;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
+ dev_err(&pdev->dev,
"32-bit consistent DMA enable failed\n");
return rc;
}
@@ -588,14 +587,12 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
static int qs_ata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
unsigned int board_idx = (unsigned int) ent->driver_data;
const struct ata_port_info *ppi[] = { &qs_port_info[board_idx], NULL };
struct ata_host *host;
int rc, port_no;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* alloc host */
host = ata_host_alloc_pinfo(&pdev->dev, ppi, QS_PORTS);
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index b42edaaf3a53..98c1d780f552 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -643,8 +643,8 @@ static void sil_dev_config(struct ata_device *dev)
((ap->flags & SIL_FLAG_MOD15WRITE) &&
(quirks & SIL_QUIRK_MOD15WRITE))) {
if (print_info)
- ata_dev_printk(dev, KERN_INFO, "applying Seagate "
- "errata fix (mod15write workaround)\n");
+ ata_dev_info(dev,
+ "applying Seagate errata fix (mod15write workaround)\n");
dev->max_sectors = 15;
return;
}
@@ -652,8 +652,8 @@ static void sil_dev_config(struct ata_device *dev)
/* limit to udma5 */
if (quirks & SIL_QUIRK_UDMA5MAX) {
if (print_info)
- ata_dev_printk(dev, KERN_INFO, "applying Maxtor "
- "errata fix %s\n", model_num);
+ ata_dev_info(dev, "applying Maxtor errata fix %s\n",
+ model_num);
dev->udma_mask &= ATA_UDMA5;
return;
}
@@ -676,8 +676,8 @@ static void sil_init_controller(struct ata_host *host)
writew(cls << 8 | cls,
mmio_base + sil_port[i].fifo_cfg);
} else
- dev_printk(KERN_WARNING, &pdev->dev,
- "cache line size not set. Driver may not function\n");
+ dev_warn(&pdev->dev,
+ "cache line size not set. Driver may not function\n");
/* Apply R_ERR on DMA activate FIS errata workaround */
if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) {
@@ -688,9 +688,8 @@ static void sil_init_controller(struct ata_host *host)
if ((tmp & 0x3) != 0x01)
continue;
if (!cnt)
- dev_printk(KERN_INFO, &pdev->dev,
- "Applying R_ERR on DMA activate "
- "FIS errata fix\n");
+ dev_info(&pdev->dev,
+ "Applying R_ERR on DMA activate FIS errata fix\n");
writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
cnt++;
}
@@ -733,7 +732,6 @@ static bool sil_broken_system_poweroff(struct pci_dev *pdev)
static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
int board_id = ent->driver_data;
struct ata_port_info pi = sil_port_info[board_id];
const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -742,8 +740,7 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
int n_ports, rc;
unsigned int i;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* allocate host */
n_ports = 2;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 06c564e55051..55470f337e51 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -694,7 +694,7 @@ static int sil24_softreset(struct ata_link *link, unsigned int *class,
return 0;
err:
- ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
+ ata_link_err(link, "softreset failed (%s)\n", reason);
return -EIO;
}
@@ -714,8 +714,8 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
* This happens often after PM DMA CS errata.
*/
if (pp->do_port_rst) {
- ata_port_printk(ap, KERN_WARNING, "controller in dubious "
- "state, performing PORT_RST\n");
+ ata_port_warn(ap,
+ "controller in dubious state, performing PORT_RST\n");
writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT);
ata_msleep(ap, 10);
@@ -773,7 +773,7 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
goto retry;
}
- ata_link_printk(link, KERN_ERR, "hardreset failed (%s)\n", reason);
+ ata_link_err(link, "hardreset failed (%s)\n", reason);
return -EIO;
}
@@ -925,7 +925,7 @@ static void sil24_pmp_attach(struct ata_port *ap)
if (sata_pmp_gscr_vendor(gscr) == 0x11ab &&
sata_pmp_gscr_devid(gscr) == 0x4140) {
- ata_port_printk(ap, KERN_INFO,
+ ata_port_info(ap,
"disabling NCQ support due to sil24-mv4140 quirk\n");
ap->flags &= ~ATA_FLAG_NCQ;
}
@@ -946,8 +946,7 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
rc = sil24_init_port(link->ap);
if (rc) {
- ata_link_printk(link, KERN_ERR,
- "hardreset failed (port not ready)\n");
+ ata_link_err(link, "hardreset failed (port not ready)\n");
return rc;
}
@@ -1141,8 +1140,8 @@ static inline void sil24_host_intr(struct ata_port *ap)
/* spurious interrupts are expected if PCIX_IRQ_WOC */
if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit())
- ata_port_printk(ap, KERN_INFO, "spurious interrupt "
- "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
+ ata_port_info(ap,
+ "spurious interrupt (slot_stat 0x%x active_tag %d sactive 0x%x)\n",
slot_stat, ap->link.active_tag, ap->link.sactive);
}
@@ -1256,8 +1255,8 @@ static void sil24_init_controller(struct ata_host *host)
PORT_CS_PORT_RST,
PORT_CS_PORT_RST, 10, 100);
if (tmp & PORT_CS_PORT_RST)
- dev_printk(KERN_ERR, host->dev,
- "failed to clear port RST\n");
+ dev_err(host->dev,
+ "failed to clear port RST\n");
}
/* configure port */
@@ -1271,7 +1270,6 @@ static void sil24_init_controller(struct ata_host *host)
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
extern int __MARKER__sil24_cmd_block_is_sized_wrongly;
- static int printed_version;
struct ata_port_info pi = sil24_port_info[ent->driver_data];
const struct ata_port_info *ppi[] = { &pi, NULL };
void __iomem * const *iomap;
@@ -1283,8 +1281,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (sizeof(union sil24_cmd_block) != PAGE_SIZE)
__MARKER__sil24_cmd_block_is_sized_wrongly = 1;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* acquire resources */
rc = pcim_enable_device(pdev);
@@ -1302,9 +1299,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pi.flags & SIL24_FLAG_PCIX_IRQ_WOC) {
tmp = readl(iomap[SIL24_HOST_BAR] + HOST_CTRL);
if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
- dev_printk(KERN_INFO, &pdev->dev,
- "Applying completion IRQ loss on PCI-X "
- "errata fix\n");
+ dev_info(&pdev->dev,
+ "Applying completion IRQ loss on PCI-X errata fix\n");
else
pi.flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
}
@@ -1322,22 +1318,21 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "64-bit DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "64-bit DMA enable failed\n");
return rc;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
+ dev_err(&pdev->dev, "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit consistent DMA enable failed\n");
+ dev_err(&pdev->dev,
+ "32-bit consistent DMA enable failed\n");
return rc;
}
}
@@ -1350,7 +1345,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
sil24_init_controller(host);
if (sata_sil24_msi && !pci_enable_msi(pdev)) {
- dev_printk(KERN_INFO, &pdev->dev, "Using MSI\n");
+ dev_info(&pdev->dev, "Using MSI\n");
pci_intx(pdev, 0);
}
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index cdcc13e9cf51..447d9c05fb5a 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -193,7 +193,6 @@ static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
struct ata_port_info pi = sis_port_info;
const struct ata_port_info *ppi[] = { &pi, &pi };
struct ata_host *host;
@@ -202,8 +201,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 port2_start = 0x20;
int i, rc;
- if (!printed_version++)
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
@@ -241,12 +239,12 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
if ((pmr & SIS_PMR_COMBINED) == 0) {
- dev_printk(KERN_INFO, &pdev->dev,
- "Detected SiS 180/181/964 chipset in SATA mode\n");
+ dev_info(&pdev->dev,
+ "Detected SiS 180/181/964 chipset in SATA mode\n");
port2_start = 64;
} else {
- dev_printk(KERN_INFO, &pdev->dev,
- "Detected SiS 180/181 chipset in combined mode\n");
+ dev_info(&pdev->dev,
+ "Detected SiS 180/181 chipset in combined mode\n");
port2_start = 0;
pi.flags |= ATA_FLAG_SLAVE_POSS;
}
@@ -256,24 +254,22 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
case 0x0183:
pci_read_config_dword(pdev, 0x6C, &val);
if (val & (1L << 31)) {
- dev_printk(KERN_INFO, &pdev->dev,
- "Detected SiS 182/965 chipset\n");
+ dev_info(&pdev->dev, "Detected SiS 182/965 chipset\n");
pi.flags |= ATA_FLAG_SLAVE_POSS;
} else {
- dev_printk(KERN_INFO, &pdev->dev,
- "Detected SiS 182/965L chipset\n");
+ dev_info(&pdev->dev, "Detected SiS 182/965L chipset\n");
}
break;
case 0x1182:
- dev_printk(KERN_INFO, &pdev->dev,
- "Detected SiS 1182/966/680 SATA controller\n");
+ dev_info(&pdev->dev,
+ "Detected SiS 1182/966/680 SATA controller\n");
pi.flags |= ATA_FLAG_SLAVE_POSS;
break;
case 0x1183:
- dev_printk(KERN_INFO, &pdev->dev,
- "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
+ dev_info(&pdev->dev,
+ "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
ppi[0] = &sis_info133_for_sata;
ppi[1] = &sis_info133_for_sata;
break;
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 35eabcf34568..c646118943ff 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -414,15 +414,13 @@ static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *ppi[] =
{ &k2_port_info[ent->driver_data], NULL };
struct ata_host *host;
void __iomem *mmio_base;
int n_ports, i, rc, bar_pos;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* allocate host */
n_ports = 4;
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 8fd3b7252bda..cdaebbe3d184 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -1440,15 +1440,13 @@ static void pdc_20621_init(struct ata_host *host)
static int pdc_sata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *ppi[] =
{ &pdc_port_info[ent->driver_data], NULL };
struct ata_host *host;
struct pdc_host_priv *hpriv;
int i, rc;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* allocate host */
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 235be717a713..b54ebfcdda32 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -145,7 +145,6 @@ static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
const struct ata_port_info *ppi[] = { &uli_port_info, NULL };
unsigned int board_idx = (unsigned int) ent->driver_data;
struct ata_host *host;
@@ -154,8 +153,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_ioports *ioaddr;
int n_ports, rc;
- if (!printed_version++)
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 54434db15b12..f93e43b0ccd8 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -360,9 +360,9 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
online = (sstatus & 0xf) == 0x3;
- ata_port_printk(ap, KERN_INFO,
- "SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
- online ? "up" : "down", sstatus, scontrol);
+ ata_port_info(ap,
+ "SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
+ online ? "up" : "down", sstatus, scontrol);
/* SStatus is read one more time */
svia_scr_read(link, SCR_STATUS, &sstatus);
@@ -469,7 +469,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
+ dev_err(&pdev->dev, "failed to iomap PCI BAR 5\n");
return rc;
}
@@ -488,14 +488,14 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
*r_host = host = ata_host_alloc_pinfo(&pdev->dev, ppi, ARRAY_SIZE(ppi));
if (!host) {
- dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n");
+ dev_err(&pdev->dev, "failed to allocate host\n");
return -ENOMEM;
}
rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap "
- "PCI BARs (errno=%d)\n", rc);
+ dev_err(&pdev->dev, "failed to request/iomap PCI BARs (errno=%d)\n",
+ rc);
return rc;
}
host->iomap = pcim_iomap_table(pdev);
@@ -526,7 +526,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
if (rc) {
- dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
+ dev_err(&pdev->dev, "failed to iomap PCI BAR 5\n");
return rc;
}
@@ -542,15 +542,14 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
u8 tmp8;
pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
- dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n",
- (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
+ dev_info(&pdev->dev, "routed to hard irq line %d\n",
+ (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
/* make sure SATA channels are enabled */
pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
- dev_printk(KERN_DEBUG, &pdev->dev,
- "enabling SATA channels (0x%x)\n",
- (int) tmp8);
+ dev_dbg(&pdev->dev, "enabling SATA channels (0x%x)\n",
+ (int)tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
}
@@ -558,9 +557,8 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
/* make sure interrupts for each channel sent to us */
pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
- dev_printk(KERN_DEBUG, &pdev->dev,
- "enabling SATA channel interrupts (0x%x)\n",
- (int) tmp8);
+ dev_dbg(&pdev->dev, "enabling SATA channel interrupts (0x%x)\n",
+ (int) tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
}
@@ -568,9 +566,9 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
/* make sure native mode is enabled */
pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
- dev_printk(KERN_DEBUG, &pdev->dev,
- "enabling SATA channel native mode (0x%x)\n",
- (int) tmp8);
+ dev_dbg(&pdev->dev,
+ "enabling SATA channel native mode (0x%x)\n",
+ (int) tmp8);
tmp8 |= NATIVE_MODE_ALL;
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
@@ -606,15 +604,13 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version;
unsigned int i;
int rc;
struct ata_host *host = NULL;
int board_id = (int) ent->driver_data;
const unsigned *bar_sizes;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
rc = pcim_enable_device(pdev);
if (rc)
@@ -628,7 +624,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
if ((pci_resource_start(pdev, i) == 0) ||
(pci_resource_len(pdev, i) < bar_sizes[i])) {
- dev_printk(KERN_ERR, &pdev->dev,
+ dev_err(&pdev->dev,
"invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n",
i,
(unsigned long long)pci_resource_start(pdev, i),
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 7c987371136e..6135a5288695 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -273,9 +273,8 @@ static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance)
if (unlikely(status == 0xffffffff || status == 0)) {
if (status)
- dev_printk(KERN_ERR, host->dev,
- ": IRQ status == 0xffffffff, "
- "PCI fault or device removal?\n");
+ dev_err(host->dev,
+ ": IRQ status == 0xffffffff, PCI fault or device removal?\n");
goto out;
}
@@ -347,14 +346,12 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev,
.port_ops = &vsc_sata_ops,
};
const struct ata_port_info *ppi[] = { &pi, NULL };
- static int printed_version;
struct ata_host *host;
void __iomem *mmio_base;
int i, rc;
u8 cls;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
/* allocate host */
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index a5fcb1eb862f..f8f41e0e8a8c 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -38,7 +38,7 @@
#include <linux/ihex.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -813,7 +813,7 @@ static void fill_rx_pool (amb_dev * dev, unsigned char pool,
return;
}
-// top up all RX pools (can also be called as a bottom half)
+// top up all RX pools
static void fill_rx_pools (amb_dev * dev) {
unsigned char pool;
@@ -872,11 +872,7 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) {
++irq_work;
if (irq_work) {
-#ifdef FILL_RX_POOLS_IN_BH
- schedule_work (&dev->bh);
-#else
fill_rx_pools (dev);
-#endif
PRINTD (DBG_IRQ, "work done: %u", irq_work);
} else {
@@ -2154,11 +2150,6 @@ static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev)
dev->tx_avail = ATM_OC3_PCR;
dev->rx_avail = ATM_OC3_PCR;
-#ifdef FILL_RX_POOLS_IN_BH
- // initialise bottom half
- INIT_WORK(&dev->bh, (void (*)(void *)) fill_rx_pools, dev);
-#endif
-
// semaphore for txer/rxer modifications - we cannot use a
// spinlock as the critical region needs to switch processes
mutex_init(&dev->vcc_sf);
diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h
index bd1c46a7ef49..aa9710556bd6 100644
--- a/drivers/atm/ambassador.h
+++ b/drivers/atm/ambassador.h
@@ -630,10 +630,6 @@ struct amb_dev {
u32 iobase;
u32 * membase;
-#ifdef FILL_RX_POOLS_IN_BH
- struct work_struct bh;
-#endif
-
amb_cq cq;
amb_txq txq;
amb_rxq rxq[NUM_RX_POOLS];
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index 0b0625054a87..b22d71cac54c 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -11,7 +11,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 3230ea0df83c..93071417315f 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -21,7 +21,7 @@
#include <linux/slab.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <asm/string.h>
#include <asm/byteorder.h>
diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h
index e4c9525e60b3..dc9a62cc2605 100644
--- a/drivers/atm/eni.h
+++ b/drivers/atm/eni.h
@@ -8,12 +8,13 @@
#include <linux/atm.h>
#include <linux/atmdev.h>
+#include <linux/interrupt.h>
#include <linux/sonet.h>
#include <linux/skbuff.h>
#include <linux/time.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "midway.h"
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index ef7a658312a6..5072f8ac16fd 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -44,6 +44,7 @@
#include <linux/ioport.h> /* for request_region */
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/capability.h>
#include <linux/bitops.h>
#include <linux/slab.h>
@@ -51,7 +52,7 @@
#include <asm/system.h>
#include <asm/string.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <linux/wait.h>
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index bc9e702186dd..361f5aee3be1 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -44,7 +44,7 @@
#include <asm/dma.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#ifdef CONFIG_SBUS
#include <linux/of.h>
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index d58e3fcb9db3..b81210330aca 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -38,13 +38,14 @@
#include <linux/delay.h>
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <asm/string.h>
#include <asm/byteorder.h>
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 1f8d724a18bf..db06f34419cf 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -37,6 +37,7 @@
#include <linux/atm.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
@@ -45,7 +46,7 @@
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/byteorder.h>
#ifdef CONFIG_ATM_IDT77252_USE_SUNI
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index dee4f01a64d8..cb90f7a3e074 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -53,11 +53,12 @@
#include <linux/delay.h>
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <asm/string.h>
#include <asm/byteorder.h>
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 4e8ba56f75d3..e828c5487493 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1947,7 +1947,6 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
{
struct pci_dev *pci = lanai->pci;
int result;
- u16 w;
if (pci_enable_device(pci) != 0) {
printk(KERN_ERR DEV_LABEL "(itf %d): can't enable "
@@ -1965,13 +1964,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
"(itf %d): No suitable DMA available.\n", lanai->number);
return -EBUSY;
}
- result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w);
- if (result != PCIBIOS_SUCCESSFUL) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
- "PCI_SUBSYSTEM_ID: %d\n", lanai->number, result);
- return -EINVAL;
- }
- result = check_board_id_and_rev("PCI", w, NULL);
+ result = check_board_id_and_rev("PCI", pci->subsystem_device, NULL);
if (result != 0)
return result;
/* Set latency timer to zero as per lanai docs */
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 6b313ee9231b..1c70c45fa044 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -51,7 +51,7 @@
#include <linux/idr.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "nicstar.h"
#ifdef CONFIG_ATM_NICSTAR_USE_SUNI
#include "suni.h"
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c
index 41c56eae4c81..90f1ccca9e52 100644
--- a/drivers/atm/suni.c
+++ b/drivers/atm/suni.c
@@ -25,7 +25,7 @@
#include <asm/system.h>
#include <asm/param.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "suni.h"
diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c
index c45ae0573bbd..5120a96b3a89 100644
--- a/drivers/atm/uPD98402.c
+++ b/drivers/atm/uPD98402.c
@@ -11,7 +11,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "uPD98402.h"
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 624917902b65..d889f56e8d8c 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/atm_zatm.h>
#include <linux/capability.h>
@@ -26,7 +27,7 @@
#include <asm/system.h>
#include <asm/string.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "uPD98401.h"
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d57e8d0fb823..21cf46f45245 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -16,6 +16,11 @@ config UEVENT_HELPER_PATH
that it creates a high system load, or on smaller systems
it is known to create out-of-memory situations during bootup.
+ To disable user space helper program execution at early boot
+ time specify an empty string here. This setting can be altered
+ via /proc/sys/kernel/hotplug or via /sys/kernel/uevent_helper
+ later at runtime.
+
config DEVTMPFS
bool "Maintain a devtmpfs filesystem to mount at /dev"
depends on HOTPLUG
@@ -65,17 +70,17 @@ config PREVENT_FIRMWARE_BUILD
default y
help
Say yes to avoid building firmware. Firmware is usually shipped
- with the driver, and only when updating the firmware a rebuild
- should be made.
- If unsure say Y here.
+ with the driver and only when updating the firmware should a
+ rebuild be made.
+ If unsure, say Y here.
config FW_LOADER
tristate "Userspace firmware loading support" if EXPERT
default y
---help---
- This option is provided for the case where no in-kernel-tree modules
- require userspace firmware loading support, but a module built outside
- the kernel tree does.
+ This option is provided for the case where none of the in-tree modules
+ require userspace firmware loading support, but a module built
+ out-of-tree does.
config FIRMWARE_IN_KERNEL
bool "Include in-kernel firmware blobs in kernel binary"
@@ -83,22 +88,22 @@ config FIRMWARE_IN_KERNEL
default y
help
The kernel source tree includes a number of firmware 'blobs'
- which are used by various drivers. The recommended way to
- use these is to run "make firmware_install" and to copy the
- resulting binary files created in usr/lib/firmware directory
- of the kernel tree to the /lib/firmware on your system so
+ that are used by various drivers. The recommended way to
+ use these is to run "make firmware_install", which, after
+ converting ihex files to binary, copies all of the needed
+ binary files in firmware/ to /lib/firmware/ on your system so
that they can be loaded by userspace helpers on request.
Enabling this option will build each required firmware blob
into the kernel directly, where request_firmware() will find
them without having to call out to userspace. This may be
- useful if your root file system requires a device which uses
- such firmware, and do not wish to use an initrd.
+ useful if your root file system requires a device that uses
+ such firmware and do not wish to use an initrd.
This single option controls the inclusion of firmware for
- every driver which uses request_firmware() and ships its
- firmware in the kernel source tree, to avoid a proliferation
- of 'Include firmware for xxx device' options.
+ every driver that uses request_firmware() and ships its
+ firmware in the kernel source tree, which avoids a
+ proliferation of 'Include firmware for xxx device' options.
Say 'N' and let firmware be loaded from userspace.
@@ -106,27 +111,27 @@ config EXTRA_FIRMWARE
string "External firmware blobs to build into the kernel binary"
depends on FW_LOADER
help
- This option allows firmware to be built into the kernel, for the
- cases where the user either cannot or doesn't want to provide it from
+ This option allows firmware to be built into the kernel for the case
+ where the user either cannot or doesn't want to provide it from
userspace at runtime (for example, when the firmware in question is
required for accessing the boot device, and the user doesn't want to
use an initrd).
- This option is a string, and takes the (space-separated) names of the
- firmware files -- the same names which appear in MODULE_FIRMWARE()
+ This option is a string and takes the (space-separated) names of the
+ firmware files -- the same names that appear in MODULE_FIRMWARE()
and request_firmware() in the source. These files should exist under
the directory specified by the EXTRA_FIRMWARE_DIR option, which is
- by default the firmware/ subdirectory of the kernel source tree.
+ by default the firmware subdirectory of the kernel source tree.
- So, for example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin",
- copy the usb8388.bin file into the firmware/ directory, and build the
- kernel. Then any request_firmware("usb8388.bin") will be
- satisfied internally without needing to call out to userspace.
+ For example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin", copy
+ the usb8388.bin file into the firmware directory, and build the kernel.
+ Then any request_firmware("usb8388.bin") will be satisfied internally
+ without needing to call out to userspace.
WARNING: If you include additional firmware files into your binary
- kernel image which are not available under the terms of the GPL,
+ kernel image that are not available under the terms of the GPL,
then it may be a violation of the GPL to distribute the resulting
- image -- since it combines both GPL and non-GPL work. You should
+ image since it combines both GPL and non-GPL work. You should
consult a lawyer of your own before distributing such an image.
config EXTRA_FIRMWARE_DIR
@@ -136,10 +141,9 @@ config EXTRA_FIRMWARE_DIR
help
This option controls the directory in which the kernel build system
looks for the firmware files listed in the EXTRA_FIRMWARE option.
- The default is the firmware/ directory in the kernel source tree,
- but by changing this option you can point it elsewhere, such as
- the /lib/firmware/ directory or another separate directory
- containing firmware files.
+ The default is firmware/ in the kernel source tree, but by changing
+ this option you can point it elsewhere, such as /lib/firmware/ or
+ some other directory containing the firmware files.
config DEBUG_DRIVER
bool "Driver Core verbose debug messages"
@@ -168,4 +172,6 @@ config SYS_HYPERVISOR
bool
default n
+source "drivers/base/regmap/Kconfig"
+
endmenu
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 4c5701c15f53..99a375ad2cc9 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -13,11 +13,11 @@ obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
obj-$(CONFIG_SMP) += topology.o
-obj-$(CONFIG_IOMMU_API) += iommu.o
ifeq ($(CONFIG_SYSFS),y)
obj-$(CONFIG_MODULES) += module.o
endif
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
+obj-$(CONFIG_REGMAP) += regmap/
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 82bbb5967aa9..b89fffc1d777 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -21,12 +21,11 @@
#include <linux/fs.h>
#include <linux/shmem_fs.h>
#include <linux/ramfs.h>
-#include <linux/cred.h>
#include <linux/sched.h>
-#include <linux/init_task.h>
#include <linux/slab.h>
+#include <linux/kthread.h>
-static struct vfsmount *dev_mnt;
+static struct task_struct *thread;
#if defined CONFIG_DEVTMPFS_MOUNT
static int mount_dev = 1;
@@ -34,7 +33,16 @@ static int mount_dev = 1;
static int mount_dev;
#endif
-static DEFINE_MUTEX(dirlock);
+static DEFINE_SPINLOCK(req_lock);
+
+static struct req {
+ struct req *next;
+ struct completion done;
+ int err;
+ const char *name;
+ mode_t mode; /* 0 => delete */
+ struct device *dev;
+} *requests;
static int __init mount_param(char *str)
{
@@ -68,131 +76,152 @@ static inline int is_blockdev(struct device *dev)
static inline int is_blockdev(struct device *dev) { return 0; }
#endif
+int devtmpfs_create_node(struct device *dev)
+{
+ const char *tmp = NULL;
+ struct req req;
+
+ if (!thread)
+ return 0;
+
+ req.mode = 0;
+ req.name = device_get_devnode(dev, &req.mode, &tmp);
+ if (!req.name)
+ return -ENOMEM;
+
+ if (req.mode == 0)
+ req.mode = 0600;
+ if (is_blockdev(dev))
+ req.mode |= S_IFBLK;
+ else
+ req.mode |= S_IFCHR;
+
+ req.dev = dev;
+
+ init_completion(&req.done);
+
+ spin_lock(&req_lock);
+ req.next = requests;
+ requests = &req;
+ spin_unlock(&req_lock);
+
+ wake_up_process(thread);
+ wait_for_completion(&req.done);
+
+ kfree(tmp);
+
+ return req.err;
+}
+
+int devtmpfs_delete_node(struct device *dev)
+{
+ const char *tmp = NULL;
+ struct req req;
+
+ if (!thread)
+ return 0;
+
+ req.name = device_get_devnode(dev, NULL, &tmp);
+ if (!req.name)
+ return -ENOMEM;
+
+ req.mode = 0;
+ req.dev = dev;
+
+ init_completion(&req.done);
+
+ spin_lock(&req_lock);
+ req.next = requests;
+ requests = &req;
+ spin_unlock(&req_lock);
+
+ wake_up_process(thread);
+ wait_for_completion(&req.done);
+
+ kfree(tmp);
+ return req.err;
+}
+
static int dev_mkdir(const char *name, mode_t mode)
{
- struct nameidata nd;
struct dentry *dentry;
+ struct path path;
int err;
- err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
- name, LOOKUP_PARENT, &nd);
- if (err)
- return err;
-
- dentry = lookup_create(&nd, 1);
- if (!IS_ERR(dentry)) {
- err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
- if (!err)
- /* mark as kernel-created inode */
- dentry->d_inode->i_private = &dev_mnt;
- dput(dentry);
- } else {
- err = PTR_ERR(dentry);
- }
-
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
- path_put(&nd.path);
+ dentry = kern_path_create(AT_FDCWD, name, &path, 1);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ err = vfs_mkdir(path.dentry->d_inode, dentry, mode);
+ if (!err)
+ /* mark as kernel-created inode */
+ dentry->d_inode->i_private = &thread;
+ dput(dentry);
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ path_put(&path);
return err;
}
static int create_path(const char *nodepath)
{
+ char *path;
+ char *s;
int err;
- mutex_lock(&dirlock);
- err = dev_mkdir(nodepath, 0755);
- if (err == -ENOENT) {
- char *path;
- char *s;
-
- /* parent directories do not exist, create them */
- path = kstrdup(nodepath, GFP_KERNEL);
- if (!path) {
- err = -ENOMEM;
- goto out;
- }
- s = path;
- for (;;) {
- s = strchr(s, '/');
- if (!s)
- break;
- s[0] = '\0';
- err = dev_mkdir(path, 0755);
- if (err && err != -EEXIST)
- break;
- s[0] = '/';
- s++;
- }
- kfree(path);
+ /* parent directories do not exist, create them */
+ path = kstrdup(nodepath, GFP_KERNEL);
+ if (!path)
+ return -ENOMEM;
+
+ s = path;
+ for (;;) {
+ s = strchr(s, '/');
+ if (!s)
+ break;
+ s[0] = '\0';
+ err = dev_mkdir(path, 0755);
+ if (err && err != -EEXIST)
+ break;
+ s[0] = '/';
+ s++;
}
-out:
- mutex_unlock(&dirlock);
+ kfree(path);
return err;
}
-int devtmpfs_create_node(struct device *dev)
+static int handle_create(const char *nodename, mode_t mode, struct device *dev)
{
- const char *tmp = NULL;
- const char *nodename;
- const struct cred *curr_cred;
- mode_t mode = 0;
- struct nameidata nd;
struct dentry *dentry;
+ struct path path;
int err;
- if (!dev_mnt)
- return 0;
-
- nodename = device_get_devnode(dev, &mode, &tmp);
- if (!nodename)
- return -ENOMEM;
-
- if (mode == 0)
- mode = 0600;
- if (is_blockdev(dev))
- mode |= S_IFBLK;
- else
- mode |= S_IFCHR;
-
- curr_cred = override_creds(&init_cred);
-
- err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
- nodename, LOOKUP_PARENT, &nd);
- if (err == -ENOENT) {
+ dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
+ if (dentry == ERR_PTR(-ENOENT)) {
create_path(nodename);
- err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
- nodename, LOOKUP_PARENT, &nd);
+ dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
}
- if (err)
- goto out;
-
- dentry = lookup_create(&nd, 0);
- if (!IS_ERR(dentry)) {
- err = vfs_mknod(nd.path.dentry->d_inode,
- dentry, mode, dev->devt);
- if (!err) {
- struct iattr newattrs;
-
- /* fixup possibly umasked mode */
- newattrs.ia_mode = mode;
- newattrs.ia_valid = ATTR_MODE;
- mutex_lock(&dentry->d_inode->i_mutex);
- notify_change(dentry, &newattrs);
- mutex_unlock(&dentry->d_inode->i_mutex);
-
- /* mark as kernel-created inode */
- dentry->d_inode->i_private = &dev_mnt;
- }
- dput(dentry);
- } else {
- err = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ err = vfs_mknod(path.dentry->d_inode,
+ dentry, mode, dev->devt);
+ if (!err) {
+ struct iattr newattrs;
+
+ /* fixup possibly umasked mode */
+ newattrs.ia_mode = mode;
+ newattrs.ia_valid = ATTR_MODE;
+ mutex_lock(&dentry->d_inode->i_mutex);
+ notify_change(dentry, &newattrs);
+ mutex_unlock(&dentry->d_inode->i_mutex);
+
+ /* mark as kernel-created inode */
+ dentry->d_inode->i_private = &thread;
}
+ dput(dentry);
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
- path_put(&nd.path);
-out:
- kfree(tmp);
- revert_creds(curr_cred);
+ mutex_unlock(&path.dentry->d_inode->i_mutex);
+ path_put(&path);
return err;
}
@@ -202,8 +231,7 @@ static int dev_rmdir(const char *name)
struct dentry *dentry;
int err;
- err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
- name, LOOKUP_PARENT, &nd);
+ err = kern_path_parent(name, &nd);
if (err)
return err;
@@ -211,7 +239,7 @@ static int dev_rmdir(const char *name)
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
if (!IS_ERR(dentry)) {
if (dentry->d_inode) {
- if (dentry->d_inode->i_private == &dev_mnt)
+ if (dentry->d_inode->i_private == &thread)
err = vfs_rmdir(nd.path.dentry->d_inode,
dentry);
else
@@ -238,7 +266,6 @@ static int delete_path(const char *nodepath)
if (!path)
return -ENOMEM;
- mutex_lock(&dirlock);
for (;;) {
char *base;
@@ -250,7 +277,6 @@ static int delete_path(const char *nodepath)
if (err)
break;
}
- mutex_unlock(&dirlock);
kfree(path);
return err;
@@ -259,7 +285,7 @@ static int delete_path(const char *nodepath)
static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
{
/* did we create it */
- if (inode->i_private != &dev_mnt)
+ if (inode->i_private != &thread)
return 0;
/* does the dev_t match */
@@ -277,29 +303,17 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta
return 1;
}
-int devtmpfs_delete_node(struct device *dev)
+static int handle_remove(const char *nodename, struct device *dev)
{
- const char *tmp = NULL;
- const char *nodename;
- const struct cred *curr_cred;
struct nameidata nd;
struct dentry *dentry;
struct kstat stat;
int deleted = 1;
int err;
- if (!dev_mnt)
- return 0;
-
- nodename = device_get_devnode(dev, NULL, &tmp);
- if (!nodename)
- return -ENOMEM;
-
- curr_cred = override_creds(&init_cred);
- err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
- nodename, LOOKUP_PARENT, &nd);
+ err = kern_path_parent(nodename, &nd);
if (err)
- goto out;
+ return err;
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
@@ -337,9 +351,6 @@ int devtmpfs_delete_node(struct device *dev)
path_put(&nd.path);
if (deleted && strchr(nodename, '/'))
delete_path(nodename);
-out:
- kfree(tmp);
- revert_creds(curr_cred);
return err;
}
@@ -354,7 +365,7 @@ int devtmpfs_mount(const char *mntdir)
if (!mount_dev)
return 0;
- if (!dev_mnt)
+ if (!thread)
return 0;
err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
@@ -365,31 +376,80 @@ int devtmpfs_mount(const char *mntdir)
return err;
}
+static __initdata DECLARE_COMPLETION(setup_done);
+
+static int handle(const char *name, mode_t mode, struct device *dev)
+{
+ if (mode)
+ return handle_create(name, mode, dev);
+ else
+ return handle_remove(name, dev);
+}
+
+static int devtmpfsd(void *p)
+{
+ char options[] = "mode=0755";
+ int *err = p;
+ *err = sys_unshare(CLONE_NEWNS);
+ if (*err)
+ goto out;
+ *err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
+ if (*err)
+ goto out;
+ sys_chdir("/.."); /* will traverse into overmounted root */
+ sys_chroot(".");
+ complete(&setup_done);
+ while (1) {
+ spin_lock(&req_lock);
+ while (requests) {
+ struct req *req = requests;
+ requests = NULL;
+ spin_unlock(&req_lock);
+ while (req) {
+ struct req *next = req->next;
+ req->err = handle(req->name, req->mode, req->dev);
+ complete(&req->done);
+ req = next;
+ }
+ spin_lock(&req_lock);
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock(&req_lock);
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ }
+ return 0;
+out:
+ complete(&setup_done);
+ return *err;
+}
+
/*
* Create devtmpfs instance, driver-core devices will add their device
* nodes here.
*/
int __init devtmpfs_init(void)
{
- int err;
- struct vfsmount *mnt;
- char options[] = "mode=0755";
-
- err = register_filesystem(&dev_fs_type);
+ int err = register_filesystem(&dev_fs_type);
if (err) {
printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
"type %i\n", err);
return err;
}
- mnt = kern_mount_data(&dev_fs_type, options);
- if (IS_ERR(mnt)) {
- err = PTR_ERR(mnt);
+ thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
+ if (!IS_ERR(thread)) {
+ wait_for_completion(&setup_done);
+ } else {
+ err = PTR_ERR(thread);
+ thread = NULL;
+ }
+
+ if (err) {
printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
unregister_filesystem(&dev_fs_type);
return err;
}
- dev_mnt = mnt;
printk(KERN_INFO "devtmpfs: initialized\n");
return 0;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 45d7c8fc73bd..2840ed4668c1 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -24,7 +24,7 @@
#include <linux/stat.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
static DEFINE_MUTEX(mem_sysfs_mutex);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 6040717b62bb..0cad9c7f6bb5 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -32,6 +32,25 @@ struct device platform_bus = {
EXPORT_SYMBOL_GPL(platform_bus);
/**
+ * arch_setup_pdev_archdata - Allow manipulation of archdata before its used
+ * @dev: platform device
+ *
+ * This is called before platform_device_add() such that any pdev_archdata may
+ * be setup before the platform_notifier is called. So if a user needs to
+ * manipulate any relevant information in the pdev_archdata they can do:
+ *
+ * platform_devic_alloc()
+ * ... manipulate ...
+ * platform_device_add()
+ *
+ * And if they don't care they can just call platform_device_register() and
+ * everything will just work out.
+ */
+void __weak arch_setup_pdev_archdata(struct platform_device *pdev)
+{
+}
+
+/**
* platform_get_resource - get a resource for a device
* @dev: platform device
* @type: resource type
@@ -173,6 +192,7 @@ struct platform_device *platform_device_alloc(const char *name, int id)
pa->pdev.id = id;
device_initialize(&pa->pdev.dev);
pa->pdev.dev.release = platform_device_release;
+ arch_setup_pdev_archdata(&pa->pdev);
}
return pa ? &pa->pdev : NULL;
@@ -334,6 +354,7 @@ EXPORT_SYMBOL_GPL(platform_device_del);
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
+ arch_setup_pdev_archdata(pdev);
return platform_device_add(pdev);
}
EXPORT_SYMBOL_GPL(platform_device_register);
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index 3647e114d0e7..2639ae79a372 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
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
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index ad367c4139b1..a846b2f95cfb 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -15,9 +15,9 @@
#include <linux/slab.h>
#include <linux/err.h>
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
-struct pm_runtime_clk_data {
+struct pm_clk_data {
struct list_head clock_list;
struct mutex lock;
};
@@ -36,25 +36,25 @@ struct pm_clock_entry {
enum pce_status status;
};
-static struct pm_runtime_clk_data *__to_prd(struct device *dev)
+static struct pm_clk_data *__to_pcd(struct device *dev)
{
return dev ? dev->power.subsys_data : NULL;
}
/**
- * pm_runtime_clk_add - Start using a device clock for runtime PM.
- * @dev: Device whose clock is going to be used for runtime PM.
+ * pm_clk_add - Start using a device clock for power management.
+ * @dev: Device whose clock is going to be used for power management.
* @con_id: Connection ID of the clock.
*
* Add the clock represented by @con_id to the list of clocks used for
- * the runtime PM of @dev.
+ * the power management of @dev.
*/
-int pm_runtime_clk_add(struct device *dev, const char *con_id)
+int pm_clk_add(struct device *dev, const char *con_id)
{
- struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clk_data *pcd = __to_pcd(dev);
struct pm_clock_entry *ce;
- if (!prd)
+ if (!pcd)
return -EINVAL;
ce = kzalloc(sizeof(*ce), GFP_KERNEL);
@@ -73,20 +73,20 @@ int pm_runtime_clk_add(struct device *dev, const char *con_id)
}
}
- mutex_lock(&prd->lock);
- list_add_tail(&ce->node, &prd->clock_list);
- mutex_unlock(&prd->lock);
+ mutex_lock(&pcd->lock);
+ list_add_tail(&ce->node, &pcd->clock_list);
+ mutex_unlock(&pcd->lock);
return 0;
}
/**
- * __pm_runtime_clk_remove - Destroy runtime PM clock entry.
- * @ce: Runtime PM clock entry to destroy.
+ * __pm_clk_remove - Destroy PM clock entry.
+ * @ce: PM clock entry to destroy.
*
- * This routine must be called under the mutex protecting the runtime PM list
- * of clocks corresponding the the @ce's device.
+ * This routine must be called under the mutex protecting the PM list of clocks
+ * corresponding the the @ce's device.
*/
-static void __pm_runtime_clk_remove(struct pm_clock_entry *ce)
+static void __pm_clk_remove(struct pm_clock_entry *ce)
{
if (!ce)
return;
@@ -108,95 +108,99 @@ static void __pm_runtime_clk_remove(struct pm_clock_entry *ce)
}
/**
- * pm_runtime_clk_remove - Stop using a device clock for runtime PM.
- * @dev: Device whose clock should not be used for runtime PM any more.
+ * pm_clk_remove - Stop using a device clock for power management.
+ * @dev: Device whose clock should not be used for PM any more.
* @con_id: Connection ID of the clock.
*
* Remove the clock represented by @con_id from the list of clocks used for
- * the runtime PM of @dev.
+ * the power management of @dev.
*/
-void pm_runtime_clk_remove(struct device *dev, const char *con_id)
+void pm_clk_remove(struct device *dev, const char *con_id)
{
- struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clk_data *pcd = __to_pcd(dev);
struct pm_clock_entry *ce;
- if (!prd)
+ if (!pcd)
return;
- mutex_lock(&prd->lock);
+ mutex_lock(&pcd->lock);
- list_for_each_entry(ce, &prd->clock_list, node) {
+ list_for_each_entry(ce, &pcd->clock_list, node) {
if (!con_id && !ce->con_id) {
- __pm_runtime_clk_remove(ce);
+ __pm_clk_remove(ce);
break;
} else if (!con_id || !ce->con_id) {
continue;
} else if (!strcmp(con_id, ce->con_id)) {
- __pm_runtime_clk_remove(ce);
+ __pm_clk_remove(ce);
break;
}
}
- mutex_unlock(&prd->lock);
+ mutex_unlock(&pcd->lock);
}
/**
- * pm_runtime_clk_init - Initialize a device's list of runtime PM clocks.
- * @dev: Device to initialize the list of runtime PM clocks for.
+ * 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_runtime_clk_data object, initialize its lock member and
+ * Allocate a struct pm_clk_data object, initialize its lock member and
* make the @dev's power.subsys_data field point to it.
*/
-int pm_runtime_clk_init(struct device *dev)
+int pm_clk_init(struct device *dev)
{
- struct pm_runtime_clk_data *prd;
+ struct pm_clk_data *pcd;
- prd = kzalloc(sizeof(*prd), GFP_KERNEL);
- if (!prd) {
- dev_err(dev, "Not enough memory fo runtime PM data.\n");
+ pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
+ if (!pcd) {
+ dev_err(dev, "Not enough memory for PM clock data.\n");
return -ENOMEM;
}
- INIT_LIST_HEAD(&prd->clock_list);
- mutex_init(&prd->lock);
- dev->power.subsys_data = prd;
+ INIT_LIST_HEAD(&pcd->clock_list);
+ mutex_init(&pcd->lock);
+ dev->power.subsys_data = pcd;
return 0;
}
/**
- * pm_runtime_clk_destroy - Destroy a device's list of runtime PM clocks.
- * @dev: Device to destroy the list of runtime PM clocks for.
+ * pm_clk_destroy - Destroy a device's list of power management clocks.
+ * @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_runtime_clk_data object pointed to by it before and free
+ * from the struct pm_clk_data object pointed to by it before and free
* that object.
*/
-void pm_runtime_clk_destroy(struct device *dev)
+void pm_clk_destroy(struct device *dev)
{
- struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clk_data *pcd = __to_pcd(dev);
struct pm_clock_entry *ce, *c;
- if (!prd)
+ if (!pcd)
return;
dev->power.subsys_data = NULL;
- mutex_lock(&prd->lock);
+ mutex_lock(&pcd->lock);
- list_for_each_entry_safe_reverse(ce, c, &prd->clock_list, node)
- __pm_runtime_clk_remove(ce);
+ list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
+ __pm_clk_remove(ce);
- mutex_unlock(&prd->lock);
+ mutex_unlock(&pcd->lock);
- kfree(prd);
+ kfree(pcd);
}
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM_RUNTIME
+
/**
- * pm_runtime_clk_acquire - Acquire a device clock.
+ * pm_clk_acquire - Acquire a device clock.
* @dev: Device whose clock is to be acquired.
* @con_id: Connection ID of the clock.
*/
-static void pm_runtime_clk_acquire(struct device *dev,
+static void pm_clk_acquire(struct device *dev,
struct pm_clock_entry *ce)
{
ce->clk = clk_get(dev, ce->con_id);
@@ -209,24 +213,24 @@ static void pm_runtime_clk_acquire(struct device *dev,
}
/**
- * pm_runtime_clk_suspend - Disable clocks in a device's runtime PM clock list.
+ * pm_clk_suspend - Disable clocks in a device's PM clock list.
* @dev: Device to disable the clocks for.
*/
-int pm_runtime_clk_suspend(struct device *dev)
+int pm_clk_suspend(struct device *dev)
{
- struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clk_data *pcd = __to_pcd(dev);
struct pm_clock_entry *ce;
dev_dbg(dev, "%s()\n", __func__);
- if (!prd)
+ if (!pcd)
return 0;
- mutex_lock(&prd->lock);
+ mutex_lock(&pcd->lock);
- list_for_each_entry_reverse(ce, &prd->clock_list, node) {
+ list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
if (ce->status == PCE_STATUS_NONE)
- pm_runtime_clk_acquire(dev, ce);
+ pm_clk_acquire(dev, ce);
if (ce->status < PCE_STATUS_ERROR) {
clk_disable(ce->clk);
@@ -234,30 +238,30 @@ int pm_runtime_clk_suspend(struct device *dev)
}
}
- mutex_unlock(&prd->lock);
+ mutex_unlock(&pcd->lock);
return 0;
}
/**
- * pm_runtime_clk_resume - Enable clocks in a device's runtime PM clock list.
+ * pm_clk_resume - Enable clocks in a device's PM clock list.
* @dev: Device to enable the clocks for.
*/
-int pm_runtime_clk_resume(struct device *dev)
+int pm_clk_resume(struct device *dev)
{
- struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clk_data *pcd = __to_pcd(dev);
struct pm_clock_entry *ce;
dev_dbg(dev, "%s()\n", __func__);
- if (!prd)
+ if (!pcd)
return 0;
- mutex_lock(&prd->lock);
+ mutex_lock(&pcd->lock);
- list_for_each_entry(ce, &prd->clock_list, node) {
+ list_for_each_entry(ce, &pcd->clock_list, node) {
if (ce->status == PCE_STATUS_NONE)
- pm_runtime_clk_acquire(dev, ce);
+ pm_clk_acquire(dev, ce);
if (ce->status < PCE_STATUS_ERROR) {
clk_enable(ce->clk);
@@ -265,28 +269,28 @@ int pm_runtime_clk_resume(struct device *dev)
}
}
- mutex_unlock(&prd->lock);
+ mutex_unlock(&pcd->lock);
return 0;
}
/**
- * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * pm_clk_notify - Notify routine for device addition and removal.
* @nb: Notifier block object this function is a member of.
* @action: Operation being carried out by the caller.
* @data: Device the routine is being run for.
*
* For this function to work, @nb must be a member of an object of type
* struct pm_clk_notifier_block containing all of the requisite data.
- * Specifically, the pwr_domain member of that object is copied to the device's
- * pwr_domain field and its con_ids member is used to populate the device's list
- * of runtime PM clocks, depending on @action.
+ * Specifically, the pm_domain member of that object is copied to the device's
+ * pm_domain field and its con_ids member is used to populate the device's list
+ * of PM clocks, depending on @action.
*
- * If the device's pwr_domain field is already populated with a value different
+ * If the device's pm_domain field is already populated with a value different
* from the one stored in the struct pm_clk_notifier_block object, the function
* does nothing.
*/
-static int pm_runtime_clk_notify(struct notifier_block *nb,
+static int pm_clk_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
struct pm_clk_notifier_block *clknb;
@@ -300,28 +304,28 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
- if (dev->pwr_domain)
+ if (dev->pm_domain)
break;
- error = pm_runtime_clk_init(dev);
+ error = pm_clk_init(dev);
if (error)
break;
- dev->pwr_domain = clknb->pwr_domain;
+ dev->pm_domain = clknb->pm_domain;
if (clknb->con_ids[0]) {
for (con_id = clknb->con_ids; *con_id; con_id++)
- pm_runtime_clk_add(dev, *con_id);
+ pm_clk_add(dev, *con_id);
} else {
- pm_runtime_clk_add(dev, NULL);
+ pm_clk_add(dev, NULL);
}
break;
case BUS_NOTIFY_DEL_DEVICE:
- if (dev->pwr_domain != clknb->pwr_domain)
+ if (dev->pm_domain != clknb->pm_domain)
break;
- dev->pwr_domain = NULL;
- pm_runtime_clk_destroy(dev);
+ dev->pm_domain = NULL;
+ pm_clk_destroy(dev);
break;
}
@@ -330,6 +334,60 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
#else /* !CONFIG_PM_RUNTIME */
+#ifdef CONFIG_PM
+
+/**
+ * pm_clk_suspend - Disable clocks in a device's PM clock list.
+ * @dev: Device to disable the clocks for.
+ */
+int pm_clk_suspend(struct device *dev)
+{
+ struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_clock_entry *ce;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ /* If there is no driver, the clocks are already disabled. */
+ if (!pcd || !dev->driver)
+ return 0;
+
+ mutex_lock(&pcd->lock);
+
+ list_for_each_entry_reverse(ce, &pcd->clock_list, node)
+ clk_disable(ce->clk);
+
+ mutex_unlock(&pcd->lock);
+
+ return 0;
+}
+
+/**
+ * pm_clk_resume - Enable clocks in a device's PM clock list.
+ * @dev: Device to enable the clocks for.
+ */
+int pm_clk_resume(struct device *dev)
+{
+ struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_clock_entry *ce;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ /* If there is no driver, the clocks should remain disabled. */
+ if (!pcd || !dev->driver)
+ return 0;
+
+ mutex_lock(&pcd->lock);
+
+ list_for_each_entry(ce, &pcd->clock_list, node)
+ clk_enable(ce->clk);
+
+ mutex_unlock(&pcd->lock);
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
/**
* enable_clock - Enable a device clock.
* @dev: Device whose clock is to be enabled.
@@ -365,7 +423,7 @@ static void disable_clock(struct device *dev, const char *con_id)
}
/**
- * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * pm_clk_notify - Notify routine for device addition and removal.
* @nb: Notifier block object this function is a member of.
* @action: Operation being carried out by the caller.
* @data: Device the routine is being run for.
@@ -375,7 +433,7 @@ static void disable_clock(struct device *dev, const char *con_id)
* Specifically, the con_ids member of that object is used to enable or disable
* the device's clocks, depending on @action.
*/
-static int pm_runtime_clk_notify(struct notifier_block *nb,
+static int pm_clk_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
struct pm_clk_notifier_block *clknb;
@@ -411,21 +469,21 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
#endif /* !CONFIG_PM_RUNTIME */
/**
- * pm_runtime_clk_add_notifier - Add bus type notifier for runtime PM clocks.
+ * pm_clk_add_notifier - Add bus type notifier for power management clocks.
* @bus: Bus type to add the notifier to.
* @clknb: Notifier to be added to the given bus type.
*
* The nb member of @clknb is not expected to be initialized and its
- * notifier_call member will be replaced with pm_runtime_clk_notify(). However,
+ * notifier_call member will be replaced with pm_clk_notify(). However,
* the remaining members of @clknb should be populated prior to calling this
* routine.
*/
-void pm_runtime_clk_add_notifier(struct bus_type *bus,
+void pm_clk_add_notifier(struct bus_type *bus,
struct pm_clk_notifier_block *clknb)
{
if (!bus || !clknb)
return;
- clknb->nb.notifier_call = pm_runtime_clk_notify;
+ clknb->nb.notifier_call = pm_clk_notify;
bus_register_notifier(bus, &clknb->nb);
}
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
new file mode 100644
index 000000000000..be8714aa9dd6
--- /dev/null
+++ b/drivers/base/power/domain.c
@@ -0,0 +1,1273 @@
+/*
+ * drivers/base/power/domain.c - Common code related to device power domains.
+ *
+ * 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/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+
+static LIST_HEAD(gpd_list);
+static DEFINE_MUTEX(gpd_list_lock);
+
+#ifdef CONFIG_PM
+
+static struct generic_pm_domain *dev_to_genpd(struct device *dev)
+{
+ if (IS_ERR_OR_NULL(dev->pm_domain))
+ return ERR_PTR(-EINVAL);
+
+ return pd_to_genpd(dev->pm_domain);
+}
+
+static void genpd_sd_counter_dec(struct generic_pm_domain *genpd)
+{
+ if (!WARN_ON(genpd->sd_count == 0))
+ genpd->sd_count--;
+}
+
+static void genpd_acquire_lock(struct generic_pm_domain *genpd)
+{
+ DEFINE_WAIT(wait);
+
+ mutex_lock(&genpd->lock);
+ /*
+ * Wait for the domain to transition into either the active,
+ * or the power off state.
+ */
+ for (;;) {
+ prepare_to_wait(&genpd->status_wait_queue, &wait,
+ TASK_UNINTERRUPTIBLE);
+ if (genpd->status == GPD_STATE_ACTIVE
+ || genpd->status == GPD_STATE_POWER_OFF)
+ break;
+ mutex_unlock(&genpd->lock);
+
+ schedule();
+
+ mutex_lock(&genpd->lock);
+ }
+ finish_wait(&genpd->status_wait_queue, &wait);
+}
+
+static void genpd_release_lock(struct generic_pm_domain *genpd)
+{
+ mutex_unlock(&genpd->lock);
+}
+
+static void genpd_set_active(struct generic_pm_domain *genpd)
+{
+ if (genpd->resume_count == 0)
+ genpd->status = GPD_STATE_ACTIVE;
+}
+
+/**
+ * pm_genpd_poweron - Restore power to a given PM domain and its parents.
+ * @genpd: PM domain to power up.
+ *
+ * Restore power to @genpd and all of its parents so that it is possible to
+ * resume a device belonging to it.
+ */
+int pm_genpd_poweron(struct generic_pm_domain *genpd)
+{
+ struct generic_pm_domain *parent = genpd->parent;
+ DEFINE_WAIT(wait);
+ int ret = 0;
+
+ start:
+ if (parent) {
+ genpd_acquire_lock(parent);
+ mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+ } else {
+ mutex_lock(&genpd->lock);
+ }
+
+ if (genpd->status == GPD_STATE_ACTIVE
+ || (genpd->prepared_count > 0 && genpd->suspend_power_off))
+ goto out;
+
+ if (genpd->status != GPD_STATE_POWER_OFF) {
+ genpd_set_active(genpd);
+ goto out;
+ }
+
+ if (parent && parent->status != GPD_STATE_ACTIVE) {
+ mutex_unlock(&genpd->lock);
+ genpd_release_lock(parent);
+
+ ret = pm_genpd_poweron(parent);
+ if (ret)
+ return ret;
+
+ goto start;
+ }
+
+ if (genpd->power_on) {
+ int ret = genpd->power_on(genpd);
+ if (ret)
+ goto out;
+ }
+
+ genpd_set_active(genpd);
+ if (parent)
+ parent->sd_count++;
+
+ out:
+ mutex_unlock(&genpd->lock);
+ if (parent)
+ genpd_release_lock(parent);
+
+ 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.
+ * @genpd: PM domain the device belongs to.
+ */
+static int __pm_genpd_save_device(struct dev_list_entry *dle,
+ struct generic_pm_domain *genpd)
+ __releases(&genpd->lock) __acquires(&genpd->lock)
+{
+ struct device *dev = dle->dev;
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (dle->need_restore)
+ return 0;
+
+ mutex_unlock(&genpd->lock);
+
+ if (drv && drv->pm && drv->pm->runtime_suspend) {
+ if (genpd->start_device)
+ genpd->start_device(dev);
+
+ ret = drv->pm->runtime_suspend(dev);
+
+ if (genpd->stop_device)
+ genpd->stop_device(dev);
+ }
+
+ mutex_lock(&genpd->lock);
+
+ if (!ret)
+ dle->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.
+ * @genpd: PM domain the device belongs to.
+ */
+static void __pm_genpd_restore_device(struct dev_list_entry *dle,
+ struct generic_pm_domain *genpd)
+ __releases(&genpd->lock) __acquires(&genpd->lock)
+{
+ struct device *dev = dle->dev;
+ struct device_driver *drv = dev->driver;
+
+ if (!dle->need_restore)
+ return;
+
+ mutex_unlock(&genpd->lock);
+
+ if (drv && drv->pm && drv->pm->runtime_resume) {
+ if (genpd->start_device)
+ genpd->start_device(dev);
+
+ drv->pm->runtime_resume(dev);
+
+ if (genpd->stop_device)
+ genpd->stop_device(dev);
+ }
+
+ mutex_lock(&genpd->lock);
+
+ dle->need_restore = false;
+}
+
+/**
+ * genpd_abort_poweroff - Check if a PM domain power off should be aborted.
+ * @genpd: PM domain to check.
+ *
+ * Return true if a PM domain's status changed to GPD_STATE_ACTIVE during
+ * a "power off" operation, which means that a "power on" has occured in the
+ * meantime, or if its resume_count field is different from zero, which means
+ * that one of its devices has been resumed in the meantime.
+ */
+static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
+{
+ return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
+}
+
+/**
+ * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff().
+ * @genpd: PM domait to power off.
+ *
+ * Queue up the execution of pm_genpd_poweroff() unless it's already been done
+ * before.
+ */
+void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
+{
+ if (!work_pending(&genpd->power_off_work))
+ queue_work(pm_wq, &genpd->power_off_work);
+}
+
+/**
+ * pm_genpd_poweroff - Remove power from a given PM domain.
+ * @genpd: PM domain to power down.
+ *
+ * If all of the @genpd's devices have been suspended and all of its subdomains
+ * have been powered down, run the runtime suspend callbacks provided by all of
+ * the @genpd's devices' drivers and remove power from @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;
+ unsigned int not_suspended;
+ int ret = 0;
+
+ start:
+ /*
+ * 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.
+ * (3) One of the domain's devices is being resumed right now.
+ */
+ if (genpd->status == GPD_STATE_POWER_OFF || genpd->prepared_count > 0
+ || genpd->resume_count > 0)
+ return 0;
+
+ if (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))
+ not_suspended++;
+
+ if (not_suspended > genpd->in_progress)
+ return -EBUSY;
+
+ if (genpd->poweroff_task) {
+ /*
+ * Another instance of pm_genpd_poweroff() is executing
+ * callbacks, so tell it to start over and return.
+ */
+ genpd->status = GPD_STATE_REPEAT;
+ return 0;
+ }
+
+ if (genpd->gov && genpd->gov->power_down_ok) {
+ if (!genpd->gov->power_down_ok(&genpd->domain))
+ return -EAGAIN;
+ }
+
+ 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);
+ 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);
+ goto out;
+ }
+ }
+
+ if (genpd->power_off) {
+ 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);
+ }
+
+ out:
+ genpd->poweroff_task = NULL;
+ wake_up_all(&genpd->status_wait_queue);
+ return ret;
+}
+
+/**
+ * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0.
+ * @work: Work structure used for scheduling the execution of this function.
+ */
+static void genpd_power_off_work_fn(struct work_struct *work)
+{
+ struct generic_pm_domain *genpd;
+
+ genpd = container_of(work, struct generic_pm_domain, power_off_work);
+
+ genpd_acquire_lock(genpd);
+ pm_genpd_poweroff(genpd);
+ genpd_release_lock(genpd);
+}
+
+/**
+ * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Carry out a runtime suspend of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_runtime_suspend(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ if (genpd->stop_device) {
+ int ret = genpd->stop_device(dev);
+ if (ret)
+ return ret;
+ }
+
+ mutex_lock(&genpd->lock);
+ genpd->in_progress++;
+ pm_genpd_poweroff(genpd);
+ genpd->in_progress--;
+ mutex_unlock(&genpd->lock);
+
+ return 0;
+}
+
+/**
+ * __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.
+ *
+ * Carry out a runtime resume of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_runtime_resume(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ DEFINE_WAIT(wait);
+ int ret;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ ret = pm_genpd_poweron(genpd);
+ if (ret)
+ return ret;
+
+ mutex_lock(&genpd->lock);
+ genpd->status = GPD_STATE_BUSY;
+ genpd->resume_count++;
+ for (;;) {
+ prepare_to_wait(&genpd->status_wait_queue, &wait,
+ TASK_UNINTERRUPTIBLE);
+ /*
+ * If current is the powering off task, we have been called
+ * reentrantly from one of the device callbacks, so we should
+ * not wait.
+ */
+ if (!genpd->poweroff_task || genpd->poweroff_task == current)
+ break;
+ mutex_unlock(&genpd->lock);
+
+ schedule();
+
+ mutex_lock(&genpd->lock);
+ }
+ finish_wait(&genpd->status_wait_queue, &wait);
+ __pm_genpd_runtime_resume(dev, genpd);
+ genpd->resume_count--;
+ genpd_set_active(genpd);
+ wake_up_all(&genpd->status_wait_queue);
+ mutex_unlock(&genpd->lock);
+
+ if (genpd->start_device)
+ genpd->start_device(dev);
+
+ return 0;
+}
+
+#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
+
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+
+/**
+ * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its parents.
+ * @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.
+ *
+ * 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
+ * sequentially, so it is guaranteed that it will never run twice in parallel).
+ */
+static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
+{
+ struct generic_pm_domain *parent = genpd->parent;
+
+ if (genpd->status == GPD_STATE_POWER_OFF)
+ return;
+
+ if (genpd->suspended_count != genpd->device_count || 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);
+ }
+}
+
+/**
+ * resume_needed - Check whether to resume a device before system suspend.
+ * @dev: Device to check.
+ * @genpd: PM domain the device belongs to.
+ *
+ * There are two cases in which a device that can wake up the system from sleep
+ * states should be resumed by pm_genpd_prepare(): (1) if the device is enabled
+ * to wake up the system and it has to remain active for this purpose while the
+ * system is in the sleep state and (2) if the device is not enabled to wake up
+ * the system from sleep states and it generally doesn't generate wakeup signals
+ * by itself (those signals are generated on its behalf by other parts of the
+ * system). In the latter case it may be necessary to reconfigure the device's
+ * wakeup settings during system suspend, because it may have been set up to
+ * signal remote wakeup from the system's working state as needed by runtime PM.
+ * Return 'true' in either of the above cases.
+ */
+static bool resume_needed(struct device *dev, struct generic_pm_domain *genpd)
+{
+ bool active_wakeup;
+
+ if (!device_can_wakeup(dev))
+ return false;
+
+ active_wakeup = genpd->active_wakeup && genpd->active_wakeup(dev);
+ return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
+}
+
+/**
+ * pm_genpd_prepare - Start power transition of a device in a PM domain.
+ * @dev: Device to start the transition of.
+ *
+ * Start a power transition of a device (during a system-wide power transition)
+ * under the assumption that its pm_domain field points to the domain member of
+ * an object of type struct generic_pm_domain representing a PM domain
+ * consisting of I/O devices.
+ */
+static int pm_genpd_prepare(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ int ret;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ /*
+ * If a wakeup request is pending for the device, it should be woken up
+ * at this point and a system wakeup event should be reported if it's
+ * set up to wake up the system from sleep states.
+ */
+ pm_runtime_get_noresume(dev);
+ if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+ pm_wakeup_event(dev, 0);
+
+ if (pm_wakeup_pending()) {
+ pm_runtime_put_sync(dev);
+ return -EBUSY;
+ }
+
+ if (resume_needed(dev, genpd))
+ pm_runtime_resume(dev);
+
+ genpd_acquire_lock(genpd);
+
+ if (genpd->prepared_count++ == 0)
+ genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
+
+ genpd_release_lock(genpd);
+
+ if (genpd->suspend_power_off) {
+ pm_runtime_put_noidle(dev);
+ return 0;
+ }
+
+ /*
+ * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
+ * so pm_genpd_poweron() will return immediately, but if the device
+ * is suspended (e.g. it's been stopped by .stop_device()), we need
+ * to make it operational.
+ */
+ pm_runtime_resume(dev);
+ __pm_runtime_disable(dev, false);
+
+ ret = pm_generic_prepare(dev);
+ if (ret) {
+ mutex_lock(&genpd->lock);
+
+ if (--genpd->prepared_count == 0)
+ genpd->suspend_power_off = false;
+
+ mutex_unlock(&genpd->lock);
+ pm_runtime_enable(dev);
+ }
+
+ pm_runtime_put_sync(dev);
+ return ret;
+}
+
+/**
+ * pm_genpd_suspend - Suspend a device belonging to an I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Suspend a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_suspend(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ return genpd->suspend_power_off ? 0 : pm_generic_suspend(dev);
+}
+
+/**
+ * pm_genpd_suspend_noirq - Late suspend of a device from an I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Carry out a late suspend of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_suspend_noirq(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ int ret;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ if (genpd->suspend_power_off)
+ return 0;
+
+ ret = pm_generic_suspend_noirq(dev);
+ if (ret)
+ return ret;
+
+ if (device_may_wakeup(dev)
+ && genpd->active_wakeup && genpd->active_wakeup(dev))
+ return 0;
+
+ if (genpd->stop_device)
+ genpd->stop_device(dev);
+
+ /*
+ * Since all of the "noirq" callbacks are executed sequentially, it is
+ * guaranteed that this function will never run twice in parallel for
+ * the same PM domain, so it is not necessary to use locking here.
+ */
+ genpd->suspended_count++;
+ pm_genpd_sync_poweroff(genpd);
+
+ return 0;
+}
+
+/**
+ * pm_genpd_resume_noirq - Early resume of a device from an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Carry out an early resume of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_resume_noirq(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ if (genpd->suspend_power_off)
+ return 0;
+
+ /*
+ * Since all of the "noirq" callbacks are executed sequentially, it is
+ * guaranteed that this function will never run twice in parallel for
+ * the same PM domain, so it is not necessary to use locking here.
+ */
+ pm_genpd_poweron(genpd);
+ genpd->suspended_count--;
+ if (genpd->start_device)
+ genpd->start_device(dev);
+
+ return pm_generic_resume_noirq(dev);
+}
+
+/**
+ * pm_genpd_resume - Resume a device belonging to an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Resume a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_resume(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ return genpd->suspend_power_off ? 0 : pm_generic_resume(dev);
+}
+
+/**
+ * pm_genpd_freeze - Freeze a device belonging to an I/O power domain.
+ * @dev: Device to freeze.
+ *
+ * Freeze a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_freeze(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ return genpd->suspend_power_off ? 0 : pm_generic_freeze(dev);
+}
+
+/**
+ * pm_genpd_freeze_noirq - Late freeze of a device from an I/O power domain.
+ * @dev: Device to freeze.
+ *
+ * Carry out a late freeze of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_freeze_noirq(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ int ret;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ if (genpd->suspend_power_off)
+ return 0;
+
+ ret = pm_generic_freeze_noirq(dev);
+ if (ret)
+ return ret;
+
+ if (genpd->stop_device)
+ genpd->stop_device(dev);
+
+ return 0;
+}
+
+/**
+ * pm_genpd_thaw_noirq - Early thaw of a device from an I/O power domain.
+ * @dev: Device to thaw.
+ *
+ * Carry out an early thaw of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_thaw_noirq(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ if (genpd->suspend_power_off)
+ return 0;
+
+ if (genpd->start_device)
+ genpd->start_device(dev);
+
+ return pm_generic_thaw_noirq(dev);
+}
+
+/**
+ * pm_genpd_thaw - Thaw a device belonging to an I/O power domain.
+ * @dev: Device to thaw.
+ *
+ * Thaw a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_thaw(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ return genpd->suspend_power_off ? 0 : pm_generic_thaw(dev);
+}
+
+/**
+ * pm_genpd_dev_poweroff - Power off a device belonging to an I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Power off a device under the assumption that its pm_domain field points to
+ * the domain member of an object of type struct generic_pm_domain representing
+ * a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_dev_poweroff(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ return genpd->suspend_power_off ? 0 : pm_generic_poweroff(dev);
+}
+
+/**
+ * pm_genpd_dev_poweroff_noirq - Late power off of a device from a PM domain.
+ * @dev: Device to suspend.
+ *
+ * Carry out a late powering off of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_dev_poweroff_noirq(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ int ret;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ if (genpd->suspend_power_off)
+ return 0;
+
+ ret = pm_generic_poweroff_noirq(dev);
+ if (ret)
+ return ret;
+
+ if (device_may_wakeup(dev)
+ && genpd->active_wakeup && genpd->active_wakeup(dev))
+ return 0;
+
+ if (genpd->stop_device)
+ genpd->stop_device(dev);
+
+ /*
+ * Since all of the "noirq" callbacks are executed sequentially, it is
+ * guaranteed that this function will never run twice in parallel for
+ * the same PM domain, so it is not necessary to use locking here.
+ */
+ genpd->suspended_count++;
+ pm_genpd_sync_poweroff(genpd);
+
+ return 0;
+}
+
+/**
+ * pm_genpd_restore_noirq - Early restore of a device from an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Carry out an early restore of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_restore_noirq(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ /*
+ * Since all of the "noirq" callbacks are executed sequentially, it is
+ * guaranteed that this function will never run twice in parallel for
+ * the same PM domain, so it is not necessary to use locking here.
+ */
+ genpd->status = GPD_STATE_POWER_OFF;
+ if (genpd->suspend_power_off) {
+ /*
+ * The boot kernel might put the domain into the power on state,
+ * so make sure it really is powered off.
+ */
+ if (genpd->power_off)
+ genpd->power_off(genpd);
+ return 0;
+ }
+
+ pm_genpd_poweron(genpd);
+ genpd->suspended_count--;
+ if (genpd->start_device)
+ genpd->start_device(dev);
+
+ return pm_generic_restore_noirq(dev);
+}
+
+/**
+ * pm_genpd_restore - Restore a device belonging to an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Restore a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_restore(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return -EINVAL;
+
+ return genpd->suspend_power_off ? 0 : pm_generic_restore(dev);
+}
+
+/**
+ * pm_genpd_complete - Complete power transition of a device in a power domain.
+ * @dev: Device to complete the transition of.
+ *
+ * Complete a power transition of a device (during a system-wide power
+ * transition) under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static void pm_genpd_complete(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ bool run_complete;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return;
+
+ mutex_lock(&genpd->lock);
+
+ run_complete = !genpd->suspend_power_off;
+ if (--genpd->prepared_count == 0)
+ genpd->suspend_power_off = false;
+
+ mutex_unlock(&genpd->lock);
+
+ if (run_complete) {
+ pm_generic_complete(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_idle(dev);
+ }
+}
+
+#else
+
+#define pm_genpd_prepare NULL
+#define pm_genpd_suspend NULL
+#define pm_genpd_suspend_noirq NULL
+#define pm_genpd_resume_noirq NULL
+#define pm_genpd_resume NULL
+#define pm_genpd_freeze NULL
+#define pm_genpd_freeze_noirq NULL
+#define pm_genpd_thaw_noirq NULL
+#define pm_genpd_thaw NULL
+#define pm_genpd_dev_poweroff_noirq NULL
+#define pm_genpd_dev_poweroff NULL
+#define pm_genpd_restore_noirq NULL
+#define pm_genpd_restore NULL
+#define pm_genpd_complete NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
+/**
+ * pm_genpd_add_device - Add a device to an I/O PM domain.
+ * @genpd: PM domain to add the device to.
+ * @dev: Device to be added.
+ */
+int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
+{
+ struct dev_list_entry *dle;
+ int ret = 0;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
+ return -EINVAL;
+
+ genpd_acquire_lock(genpd);
+
+ if (genpd->status == GPD_STATE_POWER_OFF) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (genpd->prepared_count > 0) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ list_for_each_entry(dle, &genpd->dev_list, node)
+ if (dle->dev == dev) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dle = kzalloc(sizeof(*dle), GFP_KERNEL);
+ if (!dle) {
+ 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);
+
+ out:
+ genpd_release_lock(genpd);
+
+ return ret;
+}
+
+/**
+ * pm_genpd_remove_device - Remove a device from an I/O PM domain.
+ * @genpd: PM domain to remove the device from.
+ * @dev: Device to be removed.
+ */
+int pm_genpd_remove_device(struct generic_pm_domain *genpd,
+ struct device *dev)
+{
+ struct dev_list_entry *dle;
+ int ret = -EINVAL;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
+ return -EINVAL;
+
+ genpd_acquire_lock(genpd);
+
+ if (genpd->prepared_count > 0) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ list_for_each_entry(dle, &genpd->dev_list, node) {
+ if (dle->dev != dev)
+ continue;
+
+ spin_lock_irq(&dev->power.lock);
+ dev->pm_domain = NULL;
+ spin_unlock_irq(&dev->power.lock);
+
+ genpd->device_count--;
+ list_del(&dle->node);
+ kfree(dle);
+
+ ret = 0;
+ break;
+ }
+
+ out:
+ genpd_release_lock(genpd);
+
+ return ret;
+}
+
+/**
+ * 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.
+ */
+int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
+ struct generic_pm_domain *new_subdomain)
+{
+ struct generic_pm_domain *subdomain;
+ int ret = 0;
+
+ if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(new_subdomain))
+ return -EINVAL;
+
+ start:
+ genpd_acquire_lock(genpd);
+ mutex_lock_nested(&new_subdomain->lock, SINGLE_DEPTH_NESTING);
+
+ if (new_subdomain->status != GPD_STATE_POWER_OFF
+ && new_subdomain->status != GPD_STATE_ACTIVE) {
+ mutex_unlock(&new_subdomain->lock);
+ genpd_release_lock(genpd);
+ goto start;
+ }
+
+ if (genpd->status == GPD_STATE_POWER_OFF
+ && new_subdomain->status != GPD_STATE_POWER_OFF) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
+ if (subdomain == new_subdomain) {
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ list_add_tail(&new_subdomain->sd_node, &genpd->sd_list);
+ new_subdomain->parent = genpd;
+ if (subdomain->status != GPD_STATE_POWER_OFF)
+ genpd->sd_count++;
+
+ out:
+ mutex_unlock(&new_subdomain->lock);
+ genpd_release_lock(genpd);
+
+ return ret;
+}
+
+/**
+ * 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.
+ */
+int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
+ struct generic_pm_domain *target)
+{
+ struct generic_pm_domain *subdomain;
+ int ret = -EINVAL;
+
+ if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(target))
+ return -EINVAL;
+
+ start:
+ genpd_acquire_lock(genpd);
+
+ list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
+ if (subdomain != target)
+ continue;
+
+ mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
+
+ if (subdomain->status != GPD_STATE_POWER_OFF
+ && subdomain->status != GPD_STATE_ACTIVE) {
+ mutex_unlock(&subdomain->lock);
+ genpd_release_lock(genpd);
+ goto start;
+ }
+
+ list_del(&subdomain->sd_node);
+ subdomain->parent = NULL;
+ if (subdomain->status != GPD_STATE_POWER_OFF)
+ genpd_sd_counter_dec(genpd);
+
+ mutex_unlock(&subdomain->lock);
+
+ ret = 0;
+ break;
+ }
+
+ genpd_release_lock(genpd);
+
+ return ret;
+}
+
+/**
+ * pm_genpd_init - Initialize a generic I/O PM domain object.
+ * @genpd: PM domain object to initialize.
+ * @gov: PM domain governor to associate with the domain (may be NULL).
+ * @is_off: Initial value of the domain's power_is_off field.
+ */
+void pm_genpd_init(struct generic_pm_domain *genpd,
+ struct dev_power_governor *gov, bool is_off)
+{
+ if (IS_ERR_OR_NULL(genpd))
+ return;
+
+ INIT_LIST_HEAD(&genpd->sd_node);
+ genpd->parent = NULL;
+ 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;
+ genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
+ init_waitqueue_head(&genpd->status_wait_queue);
+ genpd->poweroff_task = NULL;
+ genpd->resume_count = 0;
+ genpd->device_count = 0;
+ genpd->suspended_count = 0;
+ genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
+ genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
+ genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
+ genpd->domain.ops.prepare = pm_genpd_prepare;
+ genpd->domain.ops.suspend = pm_genpd_suspend;
+ genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
+ genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
+ genpd->domain.ops.resume = pm_genpd_resume;
+ genpd->domain.ops.freeze = pm_genpd_freeze;
+ genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
+ genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
+ genpd->domain.ops.thaw = pm_genpd_thaw;
+ genpd->domain.ops.poweroff = pm_genpd_dev_poweroff;
+ genpd->domain.ops.poweroff_noirq = pm_genpd_dev_poweroff_noirq;
+ genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
+ genpd->domain.ops.restore = pm_genpd_restore;
+ genpd->domain.ops.complete = pm_genpd_complete;
+ mutex_lock(&gpd_list_lock);
+ list_add(&genpd->gpd_list_node, &gpd_list);
+ mutex_unlock(&gpd_list_lock);
+}
+
+/**
+ * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
+ */
+void pm_genpd_poweroff_unused(void)
+{
+ struct generic_pm_domain *genpd;
+
+ mutex_lock(&gpd_list_lock);
+
+ list_for_each_entry(genpd, &gpd_list, gpd_list_node)
+ genpd_queue_power_off_work(genpd);
+
+ mutex_unlock(&gpd_list_lock);
+}
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index cb3bb368681c..9508df71274b 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -94,12 +94,13 @@ int pm_generic_prepare(struct device *dev)
* __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
* @dev: Device to handle.
* @event: PM transition of the system under way.
+ * @bool: Whether or not this is the "noirq" stage.
*
* If the device has not been suspended at run time, execute the
* suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and
* return its error code. Otherwise, return zero.
*/
-static int __pm_generic_call(struct device *dev, int event)
+static int __pm_generic_call(struct device *dev, int event, bool noirq)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int (*callback)(struct device *);
@@ -109,16 +110,16 @@ static int __pm_generic_call(struct device *dev, int event)
switch (event) {
case PM_EVENT_SUSPEND:
- callback = pm->suspend;
+ callback = noirq ? pm->suspend_noirq : pm->suspend;
break;
case PM_EVENT_FREEZE:
- callback = pm->freeze;
+ callback = noirq ? pm->freeze_noirq : pm->freeze;
break;
case PM_EVENT_HIBERNATE:
- callback = pm->poweroff;
+ callback = noirq ? pm->poweroff_noirq : pm->poweroff;
break;
case PM_EVENT_THAW:
- callback = pm->thaw;
+ callback = noirq ? pm->thaw_noirq : pm->thaw;
break;
default:
callback = NULL;
@@ -129,42 +130,82 @@ static int __pm_generic_call(struct device *dev, int event)
}
/**
+ * pm_generic_suspend_noirq - Generic suspend_noirq callback for subsystems.
+ * @dev: Device to suspend.
+ */
+int pm_generic_suspend_noirq(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_SUSPEND, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_suspend_noirq);
+
+/**
* pm_generic_suspend - Generic suspend callback for subsystems.
* @dev: Device to suspend.
*/
int pm_generic_suspend(struct device *dev)
{
- return __pm_generic_call(dev, PM_EVENT_SUSPEND);
+ return __pm_generic_call(dev, PM_EVENT_SUSPEND, false);
}
EXPORT_SYMBOL_GPL(pm_generic_suspend);
/**
+ * pm_generic_freeze_noirq - Generic freeze_noirq callback for subsystems.
+ * @dev: Device to freeze.
+ */
+int pm_generic_freeze_noirq(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_FREEZE, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_freeze_noirq);
+
+/**
* pm_generic_freeze - Generic freeze callback for subsystems.
* @dev: Device to freeze.
*/
int pm_generic_freeze(struct device *dev)
{
- return __pm_generic_call(dev, PM_EVENT_FREEZE);
+ return __pm_generic_call(dev, PM_EVENT_FREEZE, false);
}
EXPORT_SYMBOL_GPL(pm_generic_freeze);
/**
+ * pm_generic_poweroff_noirq - Generic poweroff_noirq callback for subsystems.
+ * @dev: Device to handle.
+ */
+int pm_generic_poweroff_noirq(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_HIBERNATE, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_poweroff_noirq);
+
+/**
* pm_generic_poweroff - Generic poweroff callback for subsystems.
* @dev: Device to handle.
*/
int pm_generic_poweroff(struct device *dev)
{
- return __pm_generic_call(dev, PM_EVENT_HIBERNATE);
+ return __pm_generic_call(dev, PM_EVENT_HIBERNATE, false);
}
EXPORT_SYMBOL_GPL(pm_generic_poweroff);
/**
+ * pm_generic_thaw_noirq - Generic thaw_noirq callback for subsystems.
+ * @dev: Device to thaw.
+ */
+int pm_generic_thaw_noirq(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_THAW, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_thaw_noirq);
+
+/**
* pm_generic_thaw - Generic thaw callback for subsystems.
* @dev: Device to thaw.
*/
int pm_generic_thaw(struct device *dev)
{
- return __pm_generic_call(dev, PM_EVENT_THAW);
+ return __pm_generic_call(dev, PM_EVENT_THAW, false);
}
EXPORT_SYMBOL_GPL(pm_generic_thaw);
@@ -172,12 +213,13 @@ EXPORT_SYMBOL_GPL(pm_generic_thaw);
* __pm_generic_resume - Generic resume/restore callback for subsystems.
* @dev: Device to handle.
* @event: PM transition of the system under way.
+ * @bool: Whether or not this is the "noirq" stage.
*
* Execute the resume/resotre callback provided by the @dev's driver, if
* defined. If it returns 0, change the device's runtime PM status to 'active'.
* Return the callback's error code.
*/
-static int __pm_generic_resume(struct device *dev, int event)
+static int __pm_generic_resume(struct device *dev, int event, bool noirq)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int (*callback)(struct device *);
@@ -188,10 +230,10 @@ static int __pm_generic_resume(struct device *dev, int event)
switch (event) {
case PM_EVENT_RESUME:
- callback = pm->resume;
+ callback = noirq ? pm->resume_noirq : pm->resume;
break;
case PM_EVENT_RESTORE:
- callback = pm->restore;
+ callback = noirq ? pm->restore_noirq : pm->restore;
break;
default:
callback = NULL;
@@ -202,7 +244,7 @@ static int __pm_generic_resume(struct device *dev, int event)
return 0;
ret = callback(dev);
- if (!ret && pm_runtime_enabled(dev)) {
+ if (!ret && !noirq && pm_runtime_enabled(dev)) {
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -212,22 +254,42 @@ static int __pm_generic_resume(struct device *dev, int event)
}
/**
+ * pm_generic_resume_noirq - Generic resume_noirq callback for subsystems.
+ * @dev: Device to resume.
+ */
+int pm_generic_resume_noirq(struct device *dev)
+{
+ return __pm_generic_resume(dev, PM_EVENT_RESUME, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_resume_noirq);
+
+/**
* pm_generic_resume - Generic resume callback for subsystems.
* @dev: Device to resume.
*/
int pm_generic_resume(struct device *dev)
{
- return __pm_generic_resume(dev, PM_EVENT_RESUME);
+ return __pm_generic_resume(dev, PM_EVENT_RESUME, false);
}
EXPORT_SYMBOL_GPL(pm_generic_resume);
/**
+ * pm_generic_restore_noirq - Generic restore_noirq callback for subsystems.
+ * @dev: Device to restore.
+ */
+int pm_generic_restore_noirq(struct device *dev)
+{
+ return __pm_generic_resume(dev, PM_EVENT_RESTORE, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_restore_noirq);
+
+/**
* pm_generic_restore - Generic restore callback for subsystems.
* @dev: Device to restore.
*/
int pm_generic_restore(struct device *dev)
{
- return __pm_generic_resume(dev, PM_EVENT_RESTORE);
+ return __pm_generic_resume(dev, PM_EVENT_RESTORE, false);
}
EXPORT_SYMBOL_GPL(pm_generic_restore);
@@ -256,11 +318,17 @@ struct dev_pm_ops generic_subsys_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.prepare = pm_generic_prepare,
.suspend = pm_generic_suspend,
+ .suspend_noirq = pm_generic_suspend_noirq,
.resume = pm_generic_resume,
+ .resume_noirq = pm_generic_resume_noirq,
.freeze = pm_generic_freeze,
+ .freeze_noirq = pm_generic_freeze_noirq,
.thaw = pm_generic_thaw,
+ .thaw_noirq = pm_generic_thaw_noirq,
.poweroff = pm_generic_poweroff,
+ .poweroff_noirq = pm_generic_poweroff_noirq,
.restore = pm_generic_restore,
+ .restore_noirq = pm_generic_restore_noirq,
.complete = pm_generic_complete,
#endif
#ifdef CONFIG_PM_RUNTIME
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 06f09bf89cb2..a85459126bc6 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -425,9 +425,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
TRACE_DEVICE(dev);
TRACE_RESUME(0);
- if (dev->pwr_domain) {
+ if (dev->pm_domain) {
pm_dev_dbg(dev, state, "EARLY power domain ");
- error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+ error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
} else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "EARLY type ");
error = pm_noirq_op(dev, dev->type->pm, state);
@@ -505,6 +505,7 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
static int device_resume(struct device *dev, pm_message_t state, bool async)
{
int error = 0;
+ bool put = false;
TRACE_DEVICE(dev);
TRACE_RESUME(0);
@@ -521,9 +522,12 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
if (!dev->power.is_suspended)
goto Unlock;
- if (dev->pwr_domain) {
+ pm_runtime_enable(dev);
+ put = true;
+
+ if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain ");
- error = pm_op(dev, &dev->pwr_domain->ops, state);
+ error = pm_op(dev, &dev->pm_domain->ops, state);
goto End;
}
@@ -563,6 +567,10 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
complete_all(&dev->power.completion);
TRACE_RESUME(error);
+
+ if (put)
+ pm_runtime_put_sync(dev);
+
return error;
}
@@ -641,10 +649,10 @@ static void device_complete(struct device *dev, pm_message_t state)
{
device_lock(dev);
- if (dev->pwr_domain) {
+ if (dev->pm_domain) {
pm_dev_dbg(dev, state, "completing power domain ");
- if (dev->pwr_domain->ops.complete)
- dev->pwr_domain->ops.complete(dev);
+ if (dev->pm_domain->ops.complete)
+ dev->pm_domain->ops.complete(dev);
} else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "completing type ");
if (dev->type->pm->complete)
@@ -744,9 +752,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
{
int error;
- if (dev->pwr_domain) {
+ if (dev->pm_domain) {
pm_dev_dbg(dev, state, "LATE power domain ");
- error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+ error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
if (error)
return error;
} else if (dev->type && dev->type->pm) {
@@ -843,19 +851,25 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
int error = 0;
dpm_wait_for_children(dev, async);
- device_lock(dev);
if (async_error)
- goto Unlock;
+ return 0;
+
+ pm_runtime_get_noresume(dev);
+ if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+ pm_wakeup_event(dev, 0);
if (pm_wakeup_pending()) {
+ pm_runtime_put_sync(dev);
async_error = -EBUSY;
- goto Unlock;
+ return 0;
}
- if (dev->pwr_domain) {
+ device_lock(dev);
+
+ if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain ");
- error = pm_op(dev, &dev->pwr_domain->ops, state);
+ error = pm_op(dev, &dev->pm_domain->ops, state);
goto End;
}
@@ -890,12 +904,15 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
End:
dev->power.is_suspended = !error;
- Unlock:
device_unlock(dev);
complete_all(&dev->power.completion);
- if (error)
+ if (error) {
+ pm_runtime_put_sync(dev);
async_error = error;
+ } else if (dev->power.is_suspended) {
+ __pm_runtime_disable(dev, false);
+ }
return error;
}
@@ -982,11 +999,11 @@ static int device_prepare(struct device *dev, pm_message_t state)
device_lock(dev);
- if (dev->pwr_domain) {
+ if (dev->pm_domain) {
pm_dev_dbg(dev, state, "preparing power domain ");
- if (dev->pwr_domain->ops.prepare)
- error = dev->pwr_domain->ops.prepare(dev);
- suspend_report_result(dev->pwr_domain->ops.prepare, error);
+ if (dev->pm_domain->ops.prepare)
+ error = dev->pm_domain->ops.prepare(dev);
+ suspend_report_result(dev->pm_domain->ops.prepare, error);
if (error)
goto End;
} else if (dev->type && dev->type->pm) {
@@ -1035,13 +1052,7 @@ int dpm_prepare(pm_message_t state)
get_device(dev);
mutex_unlock(&dpm_list_mtx);
- pm_runtime_get_noresume(dev);
- if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
- pm_wakeup_event(dev, 0);
-
- pm_runtime_put_sync(dev);
- error = pm_wakeup_pending() ?
- -EBUSY : device_prepare(dev, state);
+ error = device_prepare(dev, state);
mutex_lock(&dpm_list_mtx);
if (error) {
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 56a6899f5e9e..b23de185cb04 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -453,7 +453,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
static int opp_set_availability(struct device *dev, unsigned long freq,
bool availability_req)
{
- struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+ struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
int r = 0;
@@ -625,4 +625,21 @@ int opp_init_cpufreq_table(struct device *dev,
return 0;
}
+
+/**
+ * opp_free_cpufreq_table() - free the cpufreq table
+ * @dev: device for which we do this operation
+ * @table: table to free
+ *
+ * Free up the table allocated by opp_init_cpufreq_table
+ */
+void opp_free_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ if (!table)
+ return;
+
+ kfree(*table);
+ *table = NULL;
+}
#endif /* CONFIG_CPU_FREQ */
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 0d4587b15c55..8dc247c974af 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1,5 +1,5 @@
/*
- * drivers/base/power/runtime.c - Helper functions for device run-time PM
+ * drivers/base/power/runtime.c - Helper functions for device runtime PM
*
* Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
* Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu>
@@ -135,8 +135,9 @@ static int rpm_check_suspend_allowed(struct device *dev)
if (dev->power.runtime_error)
retval = -EINVAL;
- else if (atomic_read(&dev->power.usage_count) > 0
- || dev->power.disable_depth > 0)
+ else if (dev->power.disable_depth > 0)
+ retval = -EACCES;
+ else if (atomic_read(&dev->power.usage_count) > 0)
retval = -EAGAIN;
else if (!pm_children_suspended(dev))
retval = -EBUSY;
@@ -158,7 +159,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
* @dev: Device to notify the bus type about.
* @rpmflags: Flag bits.
*
- * Check if the device's run-time PM status allows it to be suspended. If
+ * Check if the device's runtime PM status allows it to be suspended. If
* another idle notification has been started earlier, return immediately. If
* the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
* run the ->runtime_idle() callback directly.
@@ -213,8 +214,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
dev->power.idle_notification = true;
- if (dev->pwr_domain)
- callback = dev->pwr_domain->ops.runtime_idle;
+ if (dev->pm_domain)
+ callback = dev->pm_domain->ops.runtime_idle;
else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_idle;
else if (dev->class && dev->class->pm)
@@ -262,15 +263,15 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
spin_lock_irq(&dev->power.lock);
}
dev->power.runtime_error = retval;
- return retval;
+ return retval != -EACCES ? retval : -EIO;
}
/**
- * rpm_suspend - Carry out run-time suspend of given device.
+ * rpm_suspend - Carry out runtime suspend of given device.
* @dev: Device to suspend.
* @rpmflags: Flag bits.
*
- * Check if the device's run-time PM status allows it to be suspended. If
+ * 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
@@ -374,8 +375,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_SUSPENDING);
- if (dev->pwr_domain)
- callback = dev->pwr_domain->ops.runtime_suspend;
+ if (dev->pm_domain)
+ callback = dev->pm_domain->ops.runtime_suspend;
else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_suspend;
else if (dev->class && dev->class->pm)
@@ -388,7 +389,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
retval = rpm_callback(callback, dev);
if (retval) {
__update_runtime_status(dev, RPM_ACTIVE);
- dev->power.deferred_resume = 0;
+ dev->power.deferred_resume = false;
if (retval == -EAGAIN || retval == -EBUSY)
dev->power.runtime_error = 0;
else
@@ -429,11 +430,11 @@ static int rpm_suspend(struct device *dev, int rpmflags)
}
/**
- * rpm_resume - Carry out run-time resume of given device.
+ * rpm_resume - Carry out runtime resume of given device.
* @dev: Device to resume.
* @rpmflags: Flag bits.
*
- * Check if the device's run-time PM status allows it to be resumed. Cancel
+ * Check if the device's runtime PM status allows it to be resumed. Cancel
* any scheduled or pending requests. If another resume has been started
* earlier, either return immediately or wait for it to finish, depending on the
* RPM_NOWAIT and RPM_ASYNC flags. Similarly, if there's a suspend running in
@@ -458,7 +459,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
if (dev->power.runtime_error)
retval = -EINVAL;
else if (dev->power.disable_depth > 0)
- retval = -EAGAIN;
+ retval = -EACCES;
if (retval)
goto out;
@@ -550,7 +551,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
spin_lock(&parent->power.lock);
/*
- * We can resume if the parent's run-time PM is disabled or it
+ * We can resume if the parent's runtime PM is disabled or it
* is set to ignore children.
*/
if (!parent->power.disable_depth
@@ -573,8 +574,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_RESUMING);
- if (dev->pwr_domain)
- callback = dev->pwr_domain->ops.runtime_resume;
+ if (dev->pm_domain)
+ callback = dev->pm_domain->ops.runtime_resume;
else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_resume;
else if (dev->class && dev->class->pm)
@@ -614,11 +615,11 @@ static int rpm_resume(struct device *dev, int rpmflags)
}
/**
- * pm_runtime_work - Universal run-time PM work function.
+ * pm_runtime_work - Universal runtime PM work function.
* @work: Work structure used for scheduling the execution of this function.
*
* Use @work to get the device object the work is to be done for, determine what
- * is to be done and execute the appropriate run-time PM function.
+ * is to be done and execute the appropriate runtime PM function.
*/
static void pm_runtime_work(struct work_struct *work)
{
@@ -717,7 +718,7 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
EXPORT_SYMBOL_GPL(pm_schedule_suspend);
/**
- * __pm_runtime_idle - Entry point for run-time idle operations.
+ * __pm_runtime_idle - Entry point for runtime idle operations.
* @dev: Device to send idle notification for.
* @rpmflags: Flag bits.
*
@@ -746,7 +747,7 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
EXPORT_SYMBOL_GPL(__pm_runtime_idle);
/**
- * __pm_runtime_suspend - Entry point for run-time put/suspend operations.
+ * __pm_runtime_suspend - Entry point for runtime put/suspend operations.
* @dev: Device to suspend.
* @rpmflags: Flag bits.
*
@@ -775,7 +776,7 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
/**
- * __pm_runtime_resume - Entry point for run-time resume operations.
+ * __pm_runtime_resume - Entry point for runtime resume operations.
* @dev: Device to resume.
* @rpmflags: Flag bits.
*
@@ -801,11 +802,11 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
EXPORT_SYMBOL_GPL(__pm_runtime_resume);
/**
- * __pm_runtime_set_status - Set run-time PM status of a device.
+ * __pm_runtime_set_status - Set runtime PM status of a device.
* @dev: Device to handle.
- * @status: New run-time PM status of the device.
+ * @status: New runtime PM status of the device.
*
- * If run-time PM of the device is disabled or its power.runtime_error field is
+ * If runtime PM of the device is disabled or its power.runtime_error field is
* different from zero, the status may be changed either to RPM_ACTIVE, or to
* RPM_SUSPENDED, as long as that reflects the actual state of the device.
* However, if the device has a parent and the parent is not active, and the
@@ -851,7 +852,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
/*
* It is invalid to put an active child under a parent that is
- * not active, has run-time PM enabled and the
+ * not active, has runtime PM enabled and the
* 'power.ignore_children' flag unset.
*/
if (!parent->power.disable_depth
@@ -885,7 +886,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_set_status);
* @dev: Device to handle.
*
* Flush all pending requests for the device from pm_wq and wait for all
- * run-time PM operations involving the device in progress to complete.
+ * runtime PM operations involving the device in progress to complete.
*
* Should be called under dev->power.lock with interrupts disabled.
*/
@@ -933,7 +934,7 @@ static void __pm_runtime_barrier(struct device *dev)
* Prevent the device from being suspended by incrementing its usage counter and
* if there's a pending resume request for the device, wake the device up.
* Next, make sure that all pending requests for the device have been flushed
- * from pm_wq and wait for all run-time PM operations involving the device in
+ * from pm_wq and wait for all runtime PM operations involving the device in
* progress to complete.
*
* Return value:
@@ -963,18 +964,18 @@ int pm_runtime_barrier(struct device *dev)
EXPORT_SYMBOL_GPL(pm_runtime_barrier);
/**
- * __pm_runtime_disable - Disable run-time PM of a device.
+ * __pm_runtime_disable - Disable runtime PM of a device.
* @dev: Device to handle.
* @check_resume: If set, check if there's a resume request for the device.
*
* Increment power.disable_depth for the device and if was zero previously,
- * cancel all pending run-time PM requests for the device and wait for all
+ * cancel all pending runtime PM requests for the device and wait for all
* operations in progress to complete. The device can be either active or
- * suspended after its run-time PM has been disabled.
+ * suspended after its runtime PM has been disabled.
*
* If @check_resume is set and there's a resume request pending when
* __pm_runtime_disable() is called and power.disable_depth is zero, the
- * function will wake up the device before disabling its run-time PM.
+ * function will wake up the device before disabling its runtime PM.
*/
void __pm_runtime_disable(struct device *dev, bool check_resume)
{
@@ -987,7 +988,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
/*
* Wake up the device if there's a resume request pending, because that
- * means there probably is some I/O to process and disabling run-time PM
+ * means there probably is some I/O to process and disabling runtime PM
* shouldn't prevent the device from processing the I/O.
*/
if (check_resume && dev->power.request_pending
@@ -1012,7 +1013,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
EXPORT_SYMBOL_GPL(__pm_runtime_disable);
/**
- * pm_runtime_enable - Enable run-time PM of a device.
+ * pm_runtime_enable - Enable runtime PM of a device.
* @dev: Device to handle.
*/
void pm_runtime_enable(struct device *dev)
@@ -1031,7 +1032,7 @@ void pm_runtime_enable(struct device *dev)
EXPORT_SYMBOL_GPL(pm_runtime_enable);
/**
- * pm_runtime_forbid - Block run-time PM of a device.
+ * pm_runtime_forbid - Block runtime PM of a device.
* @dev: Device to handle.
*
* Increase the device's usage count and clear its power.runtime_auto flag,
@@ -1054,7 +1055,7 @@ void pm_runtime_forbid(struct device *dev)
EXPORT_SYMBOL_GPL(pm_runtime_forbid);
/**
- * pm_runtime_allow - Unblock run-time PM of a device.
+ * pm_runtime_allow - Unblock runtime PM of a device.
* @dev: Device to handle.
*
* Decrease the device's usage count and set its power.runtime_auto flag.
@@ -1075,12 +1076,12 @@ void pm_runtime_allow(struct device *dev)
EXPORT_SYMBOL_GPL(pm_runtime_allow);
/**
- * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device.
+ * pm_runtime_no_callbacks - Ignore runtime PM callbacks for a device.
* @dev: Device to handle.
*
* Set the power.no_callbacks flag, which tells the PM core that this
- * device is power-managed through its parent and has no run-time PM
- * callbacks of its own. The run-time sysfs attributes will be removed.
+ * device is power-managed through its parent and has no runtime PM
+ * callbacks of its own. The runtime sysfs attributes will be removed.
*/
void pm_runtime_no_callbacks(struct device *dev)
{
@@ -1156,8 +1157,8 @@ static void update_autosuspend(struct device *dev, int old_delay, int old_use)
* @delay: Value of the new delay in milliseconds.
*
* Set the device's power.autosuspend_delay value. If it changes to negative
- * and the power.use_autosuspend flag is set, prevent run-time suspends. If it
- * changes the other way, allow run-time suspends.
+ * and the power.use_autosuspend flag is set, prevent runtime suspends. If it
+ * changes the other way, allow runtime suspends.
*/
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
{
@@ -1177,7 +1178,7 @@ EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
* @dev: Device to handle.
* @use: New value for use_autosuspend.
*
- * Set the device's power.use_autosuspend flag, and allow or prevent run-time
+ * Set the device's power.use_autosuspend flag, and allow or prevent runtime
* suspends as needed.
*/
void __pm_runtime_use_autosuspend(struct device *dev, bool use)
@@ -1194,7 +1195,7 @@ void __pm_runtime_use_autosuspend(struct device *dev, bool use)
EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
/**
- * pm_runtime_init - Initialize run-time PM fields in given device object.
+ * pm_runtime_init - Initialize runtime PM fields in given device object.
* @dev: Device object to initialize.
*/
void pm_runtime_init(struct device *dev)
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a9f5b8979611..17b7934f31cb 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -5,7 +5,7 @@
#include <linux/device.h>
#include <linux/string.h>
#include <linux/pm_runtime.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/jiffies.h>
#include "power.h"
@@ -116,12 +116,14 @@ static ssize_t control_store(struct device * dev, struct device_attribute *attr,
cp = memchr(buf, '\n', n);
if (cp)
len = cp - buf;
+ device_lock(dev);
if (len == sizeof ctrl_auto - 1 && strncmp(buf, ctrl_auto, len) == 0)
pm_runtime_allow(dev);
else if (len == sizeof ctrl_on - 1 && strncmp(buf, ctrl_on, len) == 0)
pm_runtime_forbid(dev);
else
- return -EINVAL;
+ n = -EINVAL;
+ device_unlock(dev);
return n;
}
@@ -205,7 +207,9 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
return -EINVAL;
+ device_lock(dev);
pm_runtime_set_autosuspend_delay(dev, delay);
+ device_unlock(dev);
return n;
}
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index c80e138b62fe..af10abecb99b 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -112,7 +112,7 @@ static unsigned int read_magic_time(void)
unsigned int val;
get_rtc_time(&time);
- pr_info("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n",
+ pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n",
time.tm_hour, time.tm_min, time.tm_sec,
time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
val = time.tm_year; /* 100 years */
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
new file mode 100644
index 000000000000..fabbf6cc5367
--- /dev/null
+++ b/drivers/base/regmap/Kconfig
@@ -0,0 +1,13 @@
+# Generic register map support. There are no user servicable options here,
+# this is an API intended to be used by other kernel subsystems. These
+# subsystems should select the appropriate symbols.
+
+config REGMAP
+ default y if (REGMAP_I2C || REGMAP_SPI)
+ bool
+
+config REGMAP_I2C
+ tristate
+
+config REGMAP_SPI
+ tristate
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
new file mode 100644
index 000000000000..f476f4571295
--- /dev/null
+++ b/drivers/base/regmap/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_REGMAP) += regmap.o
+obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
+obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
new file mode 100644
index 000000000000..c2231ff06cbc
--- /dev/null
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -0,0 +1,115 @@
+/*
+ * Register map access API - I2C support
+ *
+ * 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/regmap.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ int ret;
+
+ ret = i2c_master_send(i2c, data, count);
+ if (ret == count)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int regmap_i2c_gather_write(struct device *dev,
+ const void *reg, size_t reg_size,
+ const void *val, size_t val_size)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct i2c_msg xfer[2];
+ int ret;
+
+ /* If the I2C controller can't do a gather tell the core, it
+ * will substitute in a linear write for us.
+ */
+ if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING))
+ return -ENOTSUPP;
+
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = reg_size;
+ xfer[0].buf = (void *)reg;
+
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_NOSTART;
+ xfer[1].len = val_size;
+ xfer[1].buf = (void *)val;
+
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret == 2)
+ return 0;
+ if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int regmap_i2c_read(struct device *dev,
+ const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct i2c_msg xfer[2];
+ int ret;
+
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = reg_size;
+ xfer[0].buf = (void *)reg;
+
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = val_size;
+ xfer[1].buf = val;
+
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret == 2)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+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,
+};
+
+/**
+ * regmap_init_i2c(): Initialise register map
+ *
+ * @i2c: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_i2c(struct i2c_client *i2c,
+ const struct regmap_config *config)
+{
+ return regmap_init(&i2c->dev, &regmap_i2c, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_i2c);
+
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
new file mode 100644
index 000000000000..4deba0621bc7
--- /dev/null
+++ b/drivers/base/regmap/regmap-spi.c
@@ -0,0 +1,72 @@
+/*
+ * Register map access API - SPI support
+ *
+ * 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/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/init.h>
+
+static int regmap_spi_write(struct device *dev, const void *data, size_t count)
+{
+ struct spi_device *spi = to_spi_device(dev);
+
+ return spi_write(spi, data, count);
+}
+
+static int regmap_spi_gather_write(struct device *dev,
+ const void *reg, size_t reg_len,
+ const void *val, size_t val_len)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_message m;
+ struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, },
+ { .tx_buf = val, .len = val_len, }, };
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t[0], &m);
+ spi_message_add_tail(&t[1], &m);
+
+ return spi_sync(spi, &m);
+}
+
+static int regmap_spi_read(struct device *dev,
+ const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct spi_device *spi = to_spi_device(dev);
+
+ return spi_write_then_read(spi, reg, reg_size, val, val_size);
+}
+
+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,
+};
+
+/**
+ * regmap_init_spi(): Initialise register map
+ *
+ * @spi: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_spi(struct spi_device *spi,
+ const struct regmap_config *config)
+{
+ return regmap_init(&spi->dev, &regmap_spi, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_spi);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
new file mode 100644
index 000000000000..cf3565cae93d
--- /dev/null
+++ b/drivers/base/regmap/regmap.c
@@ -0,0 +1,455 @@
+/*
+ * Register map access API
+ *
+ * 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/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;
+};
+
+static void regmap_format_4_12_write(struct regmap *map,
+ unsigned int reg, unsigned int val)
+{
+ __be16 *out = map->work_buf;
+ *out = cpu_to_be16((reg << 12) | val);
+}
+
+static void regmap_format_7_9_write(struct regmap *map,
+ unsigned int reg, unsigned int val)
+{
+ __be16 *out = map->work_buf;
+ *out = cpu_to_be16((reg << 9) | val);
+}
+
+static void regmap_format_8(void *buf, unsigned int val)
+{
+ u8 *b = buf;
+
+ b[0] = val;
+}
+
+static void regmap_format_16(void *buf, unsigned int val)
+{
+ __be16 *b = buf;
+
+ b[0] = cpu_to_be16(val);
+}
+
+static unsigned int regmap_parse_8(void *buf)
+{
+ u8 *b = buf;
+
+ return b[0];
+}
+
+static unsigned int regmap_parse_16(void *buf)
+{
+ __be16 *b = buf;
+
+ b[0] = be16_to_cpu(b[0]);
+
+ return b[0];
+}
+
+/**
+ * regmap_init(): Initialise register map
+ *
+ * @dev: Device that will be interacted with
+ * @bus: Bus-specific callbacks to use with device
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap. This function should generally not be called
+ * directly, it should be called by bus-specific init functions.
+ */
+struct regmap *regmap_init(struct device *dev,
+ const struct regmap_bus *bus,
+ const struct regmap_config *config)
+{
+ struct regmap *map;
+ int ret = -EINVAL;
+
+ if (!bus || !config)
+ return NULL;
+
+ map = kzalloc(sizeof(*map), GFP_KERNEL);
+ if (map == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ mutex_init(&map->lock);
+ map->format.buf_size = (config->reg_bits + config->val_bits) / 8;
+ map->format.reg_bytes = config->reg_bits / 8;
+ map->format.val_bytes = config->val_bits / 8;
+ map->dev = dev;
+ map->bus = bus;
+
+ switch (config->reg_bits) {
+ case 4:
+ switch (config->val_bits) {
+ case 12:
+ map->format.format_write = regmap_format_4_12_write;
+ break;
+ default:
+ goto err_map;
+ }
+ break;
+
+ case 7:
+ switch (config->val_bits) {
+ case 9:
+ map->format.format_write = regmap_format_7_9_write;
+ break;
+ default:
+ goto err_map;
+ }
+ break;
+
+ case 8:
+ map->format.format_reg = regmap_format_8;
+ break;
+
+ case 16:
+ map->format.format_reg = regmap_format_16;
+ break;
+
+ default:
+ goto err_map;
+ }
+
+ switch (config->val_bits) {
+ case 8:
+ map->format.format_val = regmap_format_8;
+ map->format.parse_val = regmap_parse_8;
+ break;
+ case 16:
+ map->format.format_val = regmap_format_16;
+ map->format.parse_val = regmap_parse_16;
+ break;
+ }
+
+ if (!map->format.format_write &&
+ !(map->format.format_reg && map->format.format_val))
+ goto err_map;
+
+ map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL);
+ if (map->work_buf == NULL) {
+ ret = -ENOMEM;
+ goto err_bus;
+ }
+
+ return map;
+
+err_bus:
+ module_put(map->bus->owner);
+err_map:
+ kfree(map);
+err:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(regmap_init);
+
+/**
+ * regmap_exit(): Free a previously allocated register map
+ */
+void regmap_exit(struct regmap *map)
+{
+ kfree(map->work_buf);
+ module_put(map->bus->owner);
+ kfree(map);
+}
+EXPORT_SYMBOL_GPL(regmap_exit);
+
+static int _regmap_raw_write(struct regmap *map, unsigned int reg,
+ const void *val, size_t val_len)
+{
+ void *buf;
+ int ret = -ENOTSUPP;
+ size_t len;
+
+ map->format.format_reg(map->work_buf, reg);
+
+ /* Try to do a gather write if we can */
+ 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 (ret == -ENOTSUPP) {
+ len = map->format.reg_bytes + val_len;
+ buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy(buf, map->work_buf, map->format.reg_bytes);
+ memcpy(buf + map->format.reg_bytes, val, val_len);
+ ret = map->bus->write(map->dev, buf, len);
+
+ kfree(buf);
+ }
+
+ return ret;
+}
+
+static int _regmap_write(struct regmap *map, unsigned int reg,
+ unsigned int val)
+{
+ BUG_ON(!map->format.format_write && !map->format.format_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);
+ } else {
+ map->format.format_val(map->work_buf + map->format.reg_bytes,
+ val);
+ return _regmap_raw_write(map, reg,
+ map->work_buf + map->format.reg_bytes,
+ map->format.val_bytes);
+ }
+}
+
+/**
+ * regmap_write(): Write a value to a single register
+ *
+ * @map: Register map to write to
+ * @reg: Register to write to
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
+{
+ int ret;
+
+ mutex_lock(&map->lock);
+
+ ret = _regmap_write(map, reg, val);
+
+ mutex_unlock(&map->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_write);
+
+/**
+ * regmap_raw_write(): Write raw values to one or more registers
+ *
+ * @map: Register map to write to
+ * @reg: Initial register to write to
+ * @val: Block of data to be written, laid out for direct transmission to the
+ * device
+ * @val_len: Length of data pointed to by val.
+ *
+ * This function is intended to be used for things like firmware
+ * download where a large block of data needs to be transferred to the
+ * device. No formatting will be done on the data provided.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_raw_write(struct regmap *map, unsigned int reg,
+ const void *val, size_t val_len)
+{
+ int ret;
+
+ mutex_lock(&map->lock);
+
+ ret = _regmap_raw_write(map, reg, val, val_len);
+
+ mutex_unlock(&map->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_raw_write);
+
+static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+ unsigned int val_len)
+{
+ u8 *u8 = map->work_buf;
+ int ret;
+
+ map->format.format_reg(map->work_buf, reg);
+
+ /*
+ * Some buses 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;
+
+ ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
+ val, map->format.val_bytes);
+ if (ret != 0)
+ return ret;
+
+ return 0;
+}
+
+static int _regmap_read(struct regmap *map, unsigned int reg,
+ unsigned int *val)
+{
+ int ret;
+
+ if (!map->format.parse_val)
+ return -EINVAL;
+
+ ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
+ if (ret == 0)
+ *val = map->format.parse_val(map->work_buf);
+
+ return ret;
+}
+
+/**
+ * regmap_read(): Read a value from a single register
+ *
+ * @map: Register map to write to
+ * @reg: Register to be read from
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
+{
+ int ret;
+
+ mutex_lock(&map->lock);
+
+ ret = _regmap_read(map, reg, val);
+
+ mutex_unlock(&map->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_read);
+
+/**
+ * regmap_raw_read(): Read raw data from the device
+ *
+ * @map: Register map to write to
+ * @reg: First register to be read from
+ * @val: Pointer to store read value
+ * @val_len: Size of data to read
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+ size_t val_len)
+{
+ int ret;
+
+ mutex_lock(&map->lock);
+
+ ret = _regmap_raw_read(map, reg, val, val_len);
+
+ mutex_unlock(&map->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_raw_read);
+
+/**
+ * regmap_bulk_read(): Read multiple registers from the device
+ *
+ * @map: Register map to write to
+ * @reg: First register to be read from
+ * @val: Pointer to store read value, in native register size for device
+ * @val_count: Number of registers to read
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
+ size_t val_count)
+{
+ int ret, i;
+ size_t val_bytes = map->format.val_bytes;
+
+ if (!map->format.parse_val)
+ return -EINVAL;
+
+ 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);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(regmap_bulk_read);
+
+/**
+ * remap_update_bits: Perform a read/modify/write cycle on the register map
+ *
+ * @map: Register map to update
+ * @reg: Register to update
+ * @mask: Bitmask to change
+ * @val: New value for bitmask
+ *
+ * Returns zero for success, a negative number on error.
+ */
+int regmap_update_bits(struct regmap *map, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ int ret;
+ unsigned int tmp;
+
+ mutex_lock(&map->lock);
+
+ ret = _regmap_read(map, reg, &tmp);
+ if (ret != 0)
+ goto out;
+
+ tmp &= ~mask;
+ tmp |= val & mask;
+
+ ret = _regmap_write(map, reg, tmp);
+
+out:
+ mutex_unlock(&map->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_update_bits);
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index 353781b5b78b..ae0a02e1b808 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -13,6 +13,11 @@ config BCMA
Bus driver for Broadcom specific Advanced Microcontroller Bus
Architecture.
+# Support for Block-I/O. SELECT this from the driver that needs it.
+config BCMA_BLOCKIO
+ bool
+ depends on BCMA
+
config BCMA_HOST_PCI_POSSIBLE
bool
depends on BCMA && PCI = y
@@ -22,6 +27,12 @@ config BCMA_HOST_PCI
bool "Support for BCMA on PCI-host bus"
depends on BCMA_HOST_PCI_POSSIBLE
+config BCMA_DRIVER_PCI_HOSTMODE
+ bool "Driver for PCI core working in hostmode"
+ depends on BCMA && MIPS
+ help
+ PCI core hostmode operation (external PCI bus).
+
config BCMA_DEBUG
bool "BCMA debugging"
depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 0d56245bcb79..a2161cceafb9 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -1,6 +1,7 @@
-bcma-y += main.o scan.o core.o
+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_HOST_PCI) += host_pci.o
obj-$(CONFIG_BCMA) += bcma.o
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 2f72e9c585fd..e02ff21835c9 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -13,16 +13,23 @@
struct bcma_bus;
/* main.c */
-extern int bcma_bus_register(struct bcma_bus *bus);
-extern void bcma_bus_unregister(struct bcma_bus *bus);
+int bcma_bus_register(struct bcma_bus *bus);
+void bcma_bus_unregister(struct bcma_bus *bus);
/* scan.c */
int bcma_bus_scan(struct bcma_bus *bus);
+/* sprom.c */
+int bcma_sprom_get(struct bcma_bus *bus);
+
#ifdef CONFIG_BCMA_HOST_PCI
/* host_pci.c */
extern int __init bcma_host_pci_init(void);
extern void __exit bcma_host_pci_exit(void);
#endif /* CONFIG_BCMA_HOST_PCI */
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
+
#endif
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index ced379f7b371..4a04a49cc06d 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_device *core)
}
EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
-static void bcma_core_disable(struct bcma_device *core, u32 flags)
+void bcma_core_disable(struct bcma_device *core, u32 flags)
{
if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
return;
@@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcma_device *core, u32 flags)
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
udelay(1);
}
+EXPORT_SYMBOL_GPL(bcma_core_disable);
int bcma_core_enable(struct bcma_device *core, u32 flags)
{
@@ -49,3 +50,75 @@ int bcma_core_enable(struct bcma_device *core, u32 flags)
return 0;
}
EXPORT_SYMBOL_GPL(bcma_core_enable);
+
+void bcma_core_set_clockmode(struct bcma_device *core,
+ enum bcma_clkmode clkmode)
+{
+ u16 i;
+
+ WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
+ core->id.id != BCMA_CORE_PCIE &&
+ core->id.id != BCMA_CORE_80211);
+
+ switch (clkmode) {
+ case BCMA_CLKMODE_FAST:
+ bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
+ udelay(64);
+ for (i = 0; i < 1500; i++) {
+ if (bcma_read32(core, BCMA_CLKCTLST) &
+ BCMA_CLKCTLST_HAVEHT) {
+ i = 0;
+ break;
+ }
+ udelay(10);
+ }
+ if (i)
+ pr_err("HT force timeout\n");
+ break;
+ case BCMA_CLKMODE_DYNAMIC:
+ pr_warn("Dynamic clockmode not supported yet!\n");
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
+
+void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
+{
+ u16 i;
+
+ WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
+ WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
+
+ if (on) {
+ bcma_set32(core, BCMA_CLKCTLST, req);
+ for (i = 0; i < 10000; i++) {
+ if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
+ status) {
+ i = 0;
+ break;
+ }
+ udelay(10);
+ }
+ if (i)
+ pr_err("PLL enable timeout\n");
+ } else {
+ pr_warn("Disabling PLL not supported yet!\n");
+ }
+}
+EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
+
+u32 bcma_core_dma_translation(struct bcma_device *core)
+{
+ switch (core->bus->hosttype) {
+ case BCMA_HOSTTYPE_PCI:
+ if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
+ return BCMA_DMA_TRANSLATION_DMA64_CMT;
+ else
+ return BCMA_DMA_TRANSLATION_DMA32_CMT;
+ default:
+ pr_err("DMA translation unknown for host %d\n",
+ core->bus->hosttype);
+ }
+ return BCMA_DMA_TRANSLATION_NONE;
+}
+EXPORT_SYMBOL(bcma_core_dma_translation);
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 606102256b44..851e05bc948a 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -3,7 +3,7 @@
* ChipCommon core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
{
+ u32 leddc_on = 10;
+ u32 leddc_off = 90;
+
if (cc->core->id.rev >= 11)
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -38,6 +41,17 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
bcma_pmu_init(cc);
if (cc->capabilities & BCMA_CC_CAP_PCTL)
pr_err("Power control not implemented!\n");
+
+ if (cc->core->id.rev >= 16) {
+ if (cc->core->bus->sprom.leddc_on_time &&
+ cc->core->bus->sprom.leddc_off_time) {
+ leddc_on = cc->core->bus->sprom.leddc_on_time;
+ leddc_off = cc->core->bus->sprom.leddc_off_time;
+ }
+ bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
+ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
+ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
+ }
}
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index f44177a644c7..fcc63db0ce75 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -2,7 +2,7 @@
* Broadcom specific AMBA
* ChipCommon Power Management Unit driver
*
- * Copyright 2009, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2009, Michael Buesch <m@bues.ch>
* Copyright 2007, Broadcom Corporation
*
* Licensed under the GNU/GPL. See COPYING for details.
@@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
max_msk = 0xFFFF;
break;
case 43224:
+ case 43225:
break;
default:
pr_err("PMU resource config unknown for device 0x%04X\n",
@@ -74,6 +75,7 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
case 0x4313:
case 0x4331:
case 43224:
+ case 43225:
break;
default:
pr_err("PMU switch/regulators init unknown for device "
@@ -96,11 +98,13 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
if (bus->chipinfo.rev == 0) {
pr_err("Workarounds for 43224 rev 0 not fully "
"implemented\n");
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
+ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
} else {
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
}
break;
+ case 43225:
+ break;
default:
pr_err("Workarounds unknown for device 0x%04X\n",
bus->chipinfo.id);
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index e757e4e3c7e2..25f3ddf33823 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -3,7 +3,7 @@
* PCI Core
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -157,7 +157,69 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
* Init.
**************************************************/
-void bcma_core_pci_init(struct bcma_drv_pci *pc)
+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
{
bcma_pcicore_serdes_workaround(pc);
}
+
+static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
+{
+ struct bcma_bus *bus = pc->core->bus;
+ u16 chipid_top;
+
+ chipid_top = (bus->chipinfo.id & 0xFF00);
+ if (chipid_top != 0x4700 &&
+ chipid_top != 0x5300)
+ return false;
+
+#ifdef CONFIG_SSB_DRIVER_PCICORE
+ if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
+ return false;
+#endif /* CONFIG_SSB_DRIVER_PCICORE */
+
+#if 0
+ /* TODO: on BCMA we use address from EROM instead of magic formula */
+ u32 tmp;
+ return !mips_busprobe32(tmp, (bus->mmio +
+ (pc->core->core_index * BCMA_CORE_SIZE)));
+#endif
+
+ return true;
+}
+
+void bcma_core_pci_init(struct bcma_drv_pci *pc)
+{
+ if (bcma_core_pci_is_in_hostmode(pc)) {
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+ bcma_core_pci_hostmode_init(pc);
+#else
+ pr_err("Driver compiled without support for hostmode PCI\n");
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
+ } else {
+ bcma_core_pci_clientmode_init(pc);
+ }
+}
+
+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
+ bool enable)
+{
+ struct pci_dev *pdev = pc->core->bus->host_pci;
+ u32 coremask, tmp;
+ int err;
+
+ err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
+ if (err)
+ goto out;
+
+ coremask = BIT(core->core_index) << 8;
+ if (enable)
+ tmp |= coremask;
+ else
+ tmp &= ~coremask;
+
+ err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
+
+out:
+ return err;
+}
+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
new file mode 100644
index 000000000000..eb332b75ce83
--- /dev/null
+++ b/drivers/bcma/driver_pci_host.c
@@ -0,0 +1,14 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Core in hostmode
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/bcma/bcma.h>
+
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
+{
+ pr_err("No support for PCI core in hostmode yet\n");
+}
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 471a04013fe0..ac4bc626c149 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -65,6 +65,54 @@ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
iowrite32(value, core->bus->mmio + offset);
}
+#ifdef CONFIG_BCMA_BLOCKIO
+void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->bus->mmio + offset;
+ if (core->bus->mapped_core != core)
+ bcma_host_pci_switch_core(core);
+ switch (reg_width) {
+ case sizeof(u8):
+ ioread8_rep(addr, buffer, count);
+ break;
+ case sizeof(u16):
+ WARN_ON(count & 1);
+ ioread16_rep(addr, buffer, count >> 1);
+ break;
+ case sizeof(u32):
+ WARN_ON(count & 3);
+ ioread32_rep(addr, buffer, count >> 2);
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
+
+void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->bus->mmio + offset;
+ if (core->bus->mapped_core != core)
+ bcma_host_pci_switch_core(core);
+ switch (reg_width) {
+ case sizeof(u8):
+ iowrite8_rep(addr, buffer, count);
+ break;
+ case sizeof(u16):
+ WARN_ON(count & 1);
+ iowrite16_rep(addr, buffer, count >> 1);
+ break;
+ case sizeof(u32):
+ WARN_ON(count & 3);
+ iowrite32_rep(addr, buffer, count >> 2);
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
+#endif
+
static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
{
if (core->bus->mapped_core != core)
@@ -87,6 +135,10 @@ const struct bcma_host_ops bcma_host_pci_ops = {
.write8 = bcma_host_pci_write8,
.write16 = bcma_host_pci_write16,
.write32 = bcma_host_pci_write32,
+#ifdef CONFIG_BCMA_BLOCKIO
+ .block_read = bcma_host_pci_block_read,
+ .block_write = bcma_host_pci_block_write,
+#endif
.aread32 = bcma_host_pci_aread32,
.awrite32 = bcma_host_pci_awrite32,
};
@@ -175,6 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
{ 0, },
};
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index be52344ed19d..873e2e4ac55f 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -7,6 +7,7 @@
#include "bcma_private.h"
#include <linux/bcma/bcma.h>
+#include <linux/slab.h>
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL");
@@ -89,6 +90,8 @@ static int bcma_register_cores(struct bcma_bus *bus)
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
core->dev.parent = &bus->host_pci->dev;
+ core->dma_dev = &bus->host_pci->dev;
+ core->irq = bus->host_pci->irq;
break;
case BCMA_HOSTTYPE_NONE:
case BCMA_HOSTTYPE_SDIO:
@@ -144,6 +147,15 @@ int bcma_bus_register(struct bcma_bus *bus)
bcma_core_pci_init(&bus->drv_pci);
}
+ /* Try to get SPROM */
+ err = bcma_sprom_get(bus);
+ if (err == -ENOENT) {
+ pr_err("No SPROM available\n");
+ } else if (err) {
+ pr_err("Failed to get SPROM: %d\n", err);
+ return -ENOENT;
+ }
+
/* Register found cores */
bcma_register_cores(bus);
@@ -151,13 +163,11 @@ int bcma_bus_register(struct bcma_bus *bus)
return 0;
}
-EXPORT_SYMBOL_GPL(bcma_bus_register);
void bcma_bus_unregister(struct bcma_bus *bus)
{
bcma_unregister_cores(bus);
}
-EXPORT_SYMBOL_GPL(bcma_bus_unregister);
int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
{
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
new file mode 100644
index 000000000000..8b5b7856abe3
--- /dev/null
+++ b/drivers/bcma/sprom.c
@@ -0,0 +1,171 @@
+/*
+ * Broadcom specific AMBA
+ * SPROM reading
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_regs.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#define SPOFF(offset) ((offset) / sizeof(u16))
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom)
+{
+ int i;
+ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
+ sprom[i] = bcma_read16(bus->drv_cc.core,
+ offset + (i * 2));
+}
+
+/**************************************************
+ * Validation.
+ **************************************************/
+
+static inline u8 bcma_crc8(u8 crc, u8 data)
+{
+ /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
+ static const u8 t[] = {
+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
+ };
+ return t[crc ^ data];
+}
+
+static u8 bcma_sprom_crc(const u16 *sprom)
+{
+ int word;
+ u8 crc = 0xFF;
+
+ for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
+ crc = bcma_crc8(crc, sprom[word] & 0x00FF);
+ crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
+ }
+ crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
+ crc ^= 0xFF;
+
+ return crc;
+}
+
+static int bcma_sprom_check_crc(const u16 *sprom)
+{
+ u8 crc;
+ u8 expected_crc;
+ u16 tmp;
+
+ crc = bcma_sprom_crc(sprom);
+ tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
+ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
+ if (crc != expected_crc)
+ return -EPROTO;
+
+ return 0;
+}
+
+static int bcma_sprom_valid(const u16 *sprom)
+{
+ u16 revision;
+ int err;
+
+ err = bcma_sprom_check_crc(sprom);
+ if (err)
+ return err;
+
+ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
+ if (revision != 8 && revision != 9) {
+ pr_err("Unsupported SPROM revision: %d\n", revision);
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+/**************************************************
+ * SPROM extraction.
+ **************************************************/
+
+static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
+{
+ u16 v;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
+ *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
+ }
+}
+
+int bcma_sprom_get(struct bcma_bus *bus)
+{
+ u16 offset;
+ u16 *sprom;
+ int err = 0;
+
+ if (!bus->drv_cc.core)
+ return -EOPNOTSUPP;
+
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+ return -ENOENT;
+
+ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
+ GFP_KERNEL);
+ if (!sprom)
+ return -ENOMEM;
+
+ /* 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 */
+ offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
+ BCMA_CC_SPROM_PCIE6;
+ bcma_sprom_read(bus, offset, sprom);
+
+ err = bcma_sprom_valid(sprom);
+ if (err)
+ goto out;
+
+ bcma_sprom_extract_r8(bus, sprom);
+
+out:
+ kfree(sprom);
+ return err;
+}
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 16b4d58d84dd..c049548e68b7 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -223,7 +223,7 @@ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c)
h->ctlr, c->busaddr);
#endif /* CCISS_DEBUG */
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
- readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
+ readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
h->commands_outstanding++;
if ( h->commands_outstanding > h->max_outstanding)
h->max_outstanding = h->commands_outstanding;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 696100241a6f..951a4e33b92b 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -33,7 +33,7 @@
#include <linux/slab.h>
#include <linux/string.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 007c630904c1..b52c9ca146fc 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -155,7 +155,7 @@ else \
#if (HD_DELAY > 0)
-#include <asm/i8253.h>
+#include <linux/i8253.h>
unsigned long last_req;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 07a382eaf0a8..e133f094ab08 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1206,7 +1206,7 @@ static int pkt_start_recovery(struct packet_data *pkt)
if (!sb)
return 0;
- if (!sb->s_op || !sb->s_op->relocate_blocks)
+ if (!sb->s_op->relocate_blocks)
goto out;
old_block = pkt->sector / (CD_FRAMESIZE >> 9);
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 1278098624e6..15f65b5f3fc7 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -630,6 +630,14 @@ static int rbd_get_num_segments(struct rbd_image_header *header,
}
/*
+ * returns the size of an object in the image
+ */
+static u64 rbd_obj_bytes(struct rbd_image_header *header)
+{
+ return 1 << header->obj_order;
+}
+
+/*
* bio helpers
*/
@@ -1253,6 +1261,35 @@ fail:
return ret;
}
+/*
+ * Request sync osd unwatch
+ */
+static int rbd_req_sync_unwatch(struct rbd_device *dev,
+ const char *obj)
+{
+ struct ceph_osd_req_op *ops;
+
+ int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_WATCH, 0);
+ if (ret < 0)
+ return ret;
+
+ ops[0].watch.ver = 0;
+ ops[0].watch.cookie = cpu_to_le64(dev->watch_event->cookie);
+ ops[0].watch.flag = 0;
+
+ ret = rbd_req_sync_op(dev, NULL,
+ CEPH_NOSNAP,
+ 0,
+ CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+ ops,
+ 1, obj, 0, 0, NULL, NULL, NULL);
+
+ rbd_destroy_ops(ops);
+ ceph_osdc_cancel_event(dev->watch_event);
+ dev->watch_event = NULL;
+ return ret;
+}
+
struct rbd_notify_info {
struct rbd_device *dev;
};
@@ -1736,6 +1773,13 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
q = blk_init_queue(rbd_rq_fn, &rbd_dev->lock);
if (!q)
goto out_disk;
+
+ /* set io sizes to object size */
+ blk_queue_max_hw_sectors(q, rbd_obj_bytes(&rbd_dev->header) / 512ULL);
+ blk_queue_max_segment_size(q, rbd_obj_bytes(&rbd_dev->header));
+ blk_queue_io_min(q, rbd_obj_bytes(&rbd_dev->header));
+ blk_queue_io_opt(q, rbd_obj_bytes(&rbd_dev->header));
+
blk_queue_merge_bvec(q, rbd_merge_bvec);
disk->queue = q;
@@ -2290,7 +2334,7 @@ static void rbd_dev_release(struct device *dev)
ceph_osdc_unregister_linger_request(&rbd_dev->client->osdc,
rbd_dev->watch_request);
if (rbd_dev->watch_event)
- ceph_osdc_cancel_event(rbd_dev->watch_event);
+ rbd_req_sync_unwatch(rbd_dev, rbd_dev->obj_md_name);
rbd_put_client(rbd_dev);
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 5cf2993a8338..2330a9ad5e95 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -458,7 +458,8 @@ static void end_block_io_op(struct bio *bio, int error)
* (which has the sectors we want, number of them, grant references, etc),
* and transmute it to the block API to hand it over to the proper block disk.
*/
-static int do_block_io_op(struct xen_blkif *blkif)
+static int
+__do_block_io_op(struct xen_blkif *blkif)
{
union blkif_back_rings *blk_rings = &blkif->blk_rings;
struct blkif_request req;
@@ -515,6 +516,23 @@ static int do_block_io_op(struct xen_blkif *blkif)
return more_to_do;
}
+static int
+do_block_io_op(struct xen_blkif *blkif)
+{
+ union blkif_back_rings *blk_rings = &blkif->blk_rings;
+ int more_to_do;
+
+ do {
+ more_to_do = __do_block_io_op(blkif);
+ if (more_to_do)
+ break;
+
+ RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
+ } while (more_to_do);
+
+ return more_to_do;
+}
+
/*
* Transmutation of the 'struct blkif_request' to a proper 'struct bio'
* and call the 'submit_bio' to pass it to the underlying storage.
@@ -700,7 +718,6 @@ static void make_response(struct xen_blkif *blkif, u64 id,
struct blkif_response resp;
unsigned long flags;
union blkif_back_rings *blk_rings = &blkif->blk_rings;
- int more_to_do = 0;
int notify;
resp.id = id;
@@ -727,22 +744,7 @@ static void make_response(struct xen_blkif *blkif, u64 id,
}
blk_rings->common.rsp_prod_pvt++;
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
- if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
- /*
- * Tail check for pending requests. Allows frontend to avoid
- * notifications if requests are already in flight (lower
- * overheads and promotes batching).
- */
- RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
-
- } else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
- more_to_do = 1;
- }
-
spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
-
- if (more_to_do)
- blkif_notify_work(blkif);
if (notify)
notify_remote_via_irq(blkif->irq);
}
@@ -824,3 +826,4 @@ static int __init xen_blkif_init(void)
module_init(xen_blkif_init);
MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("xen-backend:vbd");
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 6cc0db1bf522..3f129b45451a 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -684,7 +684,7 @@ again:
err = xenbus_switch_state(dev, XenbusStateConnected);
if (err)
- xenbus_dev_fatal(dev, err, "switching to Connected state",
+ xenbus_dev_fatal(dev, err, "%s: switching to Connected state",
dev->nodename);
return;
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 6c7fd7db6dff..fb1975d82a73 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -1155,12 +1155,19 @@ static int __devinit ace_probe(struct platform_device *dev)
{
resource_size_t physaddr = 0;
int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
- int id = dev->id;
+ u32 id = dev->id;
int irq = NO_IRQ;
int i;
dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
+ /* device id and bus width */
+ of_property_read_u32(dev->dev.of_node, "port-number", &id);
+ if (id < 0)
+ id = 0;
+ if (of_find_property(dev->dev.of_node, "8-bit", NULL))
+ bus_width = ACE_BUS_WIDTH_8;
+
for (i = 0; i < dev->num_resources; i++) {
if (dev->resource[i].flags & IORESOURCE_MEM)
physaddr = dev->resource[i].start;
@@ -1181,57 +1188,7 @@ static int __devexit ace_remove(struct platform_device *dev)
return 0;
}
-static struct platform_driver ace_platform_driver = {
- .probe = ace_probe,
- .remove = __devexit_p(ace_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "xsysace",
- },
-};
-
-/* ---------------------------------------------------------------------
- * OF_Platform Bus Support
- */
-
#if defined(CONFIG_OF)
-static int __devinit ace_of_probe(struct platform_device *op)
-{
- struct resource res;
- resource_size_t physaddr;
- const u32 *id;
- int irq, bus_width, rc;
-
- /* device id */
- id = of_get_property(op->dev.of_node, "port-number", NULL);
-
- /* physaddr */
- rc = of_address_to_resource(op->dev.of_node, 0, &res);
- if (rc) {
- dev_err(&op->dev, "invalid address\n");
- return rc;
- }
- physaddr = res.start;
-
- /* irq */
- irq = irq_of_parse_and_map(op->dev.of_node, 0);
-
- /* bus width */
- bus_width = ACE_BUS_WIDTH_16;
- if (of_find_property(op->dev.of_node, "8-bit", NULL))
- bus_width = ACE_BUS_WIDTH_8;
-
- /* Call the bus-independent setup code */
- return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0,
- physaddr, irq, bus_width);
-}
-
-static int __devexit ace_of_remove(struct platform_device *op)
-{
- ace_free(&op->dev);
- return 0;
-}
-
/* Match table for of_platform binding */
static const struct of_device_id ace_of_match[] __devinitconst = {
{ .compatible = "xlnx,opb-sysace-1.00.b", },
@@ -1241,34 +1198,20 @@ static const struct of_device_id ace_of_match[] __devinitconst = {
{},
};
MODULE_DEVICE_TABLE(of, ace_of_match);
+#else /* CONFIG_OF */
+#define ace_of_match NULL
+#endif /* CONFIG_OF */
-static struct platform_driver ace_of_driver = {
- .probe = ace_of_probe,
- .remove = __devexit_p(ace_of_remove),
+static struct platform_driver ace_platform_driver = {
+ .probe = ace_probe,
+ .remove = __devexit_p(ace_remove),
.driver = {
- .name = "xsysace",
.owner = THIS_MODULE,
+ .name = "xsysace",
.of_match_table = ace_of_match,
},
};
-/* Registration helpers to keep the number of #ifdefs to a minimum */
-static inline int __init ace_of_register(void)
-{
- pr_debug("xsysace: registering OF binding\n");
- return platform_driver_register(&ace_of_driver);
-}
-
-static inline void __exit ace_of_unregister(void)
-{
- platform_driver_unregister(&ace_of_driver);
-}
-#else /* CONFIG_OF */
-/* CONFIG_OF not enabled; do nothing helpers */
-static inline int __init ace_of_register(void) { return 0; }
-static inline void __exit ace_of_unregister(void) { }
-#endif /* CONFIG_OF */
-
/* ---------------------------------------------------------------------
* Module init/exit routines
*/
@@ -1282,11 +1225,6 @@ static int __init ace_init(void)
goto err_blk;
}
- rc = ace_of_register();
- if (rc)
- goto err_of;
-
- pr_debug("xsysace: registering platform binding\n");
rc = platform_driver_register(&ace_platform_driver);
if (rc)
goto err_plat;
@@ -1295,21 +1233,17 @@ static int __init ace_init(void)
return 0;
err_plat:
- ace_of_unregister();
-err_of:
unregister_blkdev(ace_major, "xsysace");
err_blk:
printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc);
return rc;
}
+module_init(ace_init);
static void __exit ace_exit(void)
{
pr_debug("Unregistering Xilinx SystemACE driver\n");
platform_driver_unregister(&ace_platform_driver);
- ace_of_unregister();
unregister_blkdev(ace_major, "xsysace");
}
-
-module_init(ace_init);
module_exit(ace_exit);
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 6bacef368fab..a5854735bb2e 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -375,6 +375,11 @@ static int ath3k_probe(struct usb_interface *intf,
/* load patch and sysconfig files for AR3012 */
if (id->driver_info & BTUSB_ATH3012) {
+
+ /* New firmware with patch and sysconfig files already loaded */
+ if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001)
+ return -ENODEV;
+
ret = ath3k_load_patch(udev);
if (ret < 0) {
BT_ERR("Loading patch file failed");
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index c2de8951e3fb..91d13a9e8c65 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -54,6 +54,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_BCM92035 0x10
#define BTUSB_BROKEN_ISOC 0x20
#define BTUSB_WRONG_SCO_MTU 0x40
+#define BTUSB_ATH3012 0x80
static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -110,7 +111,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
/* Atheros 3012 with sflash firmware */
- { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -914,6 +915,15 @@ static int btusb_probe(struct usb_interface *intf,
if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
return -ENODEV;
+ if (id->driver_info & BTUSB_ATH3012) {
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ /* Old firmware would otherwise let ath3k driver load
+ * patch and sysconfig files */
+ if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001)
+ return -ENODEV;
+ }
+
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 548708c4b2b8..a7346ab97a3c 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -606,7 +606,7 @@ static int apm_suspend_notifier(struct notifier_block *nb,
return NOTIFY_OK;
/* interrupted by signal */
- return NOTIFY_BAD;
+ return notifier_from_errno(err);
case PM_POST_SUSPEND:
/*
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index cf39bc08ce08..0c688232aab3 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -212,7 +212,7 @@ static int bsr_add_node(struct device_node *bn)
cur->bsr_minor = i + total_bsr_devs;
cur->bsr_addr = res.start;
- cur->bsr_len = res.end - res.start + 1;
+ cur->bsr_len = resource_size(&res);
cur->bsr_bytes = bsr_bytes[i];
cur->bsr_stride = bsr_stride[i];
cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs);
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 0e941b57482e..6c4f4b5a9dd3 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -34,12 +34,16 @@ static ssize_t nvram_len;
static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
{
switch (origin) {
+ case 0:
+ break;
case 1:
offset += file->f_pos;
break;
case 2:
offset += nvram_len;
break;
+ default:
+ offset = -1;
}
if (offset < 0)
return -EINVAL;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 34d6a1cab8de..0833896cf6f2 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -952,7 +952,7 @@ int hpet_alloc(struct hpet_data *hdp)
#ifdef CONFIG_IA64
if (!hpet_clocksource) {
hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
- CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
+ clocksource_hpet.archdata.fsys_mmio = hpet_mctr;
clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
hpetp->hp_clocksource = &clocksource_hpet;
hpet_clocksource = &clocksource_hpet;
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index a60043b3e409..1d2ebc7a4947 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -210,3 +210,15 @@ config HW_RANDOM_PICOXCELL
module will be called picoxcell-rng.
If unsure, say Y.
+
+config HW_RANDOM_PPC4XX
+ tristate "PowerPC 4xx generic true random number generator support"
+ depends on HW_RANDOM && PPC && 4xx
+ ---help---
+ This driver provides the kernel-side support for the TRNG hardware
+ found in the security function of some PowerPC 4xx SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ppc4xx-rng.
+
+ If unsure, say N.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 3db4eb8b19c0..c88f244c8a71 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
+obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 2016aad85203..1bafb40ec8a2 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -19,7 +19,7 @@
Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
Added generic RNG API
- Copyright 2006 Michael Buesch <mbuesch@freenet.de>
+ Copyright 2006 Michael Buesch <m@bues.ch>
Copyright 2005 (c) MontaVista Software, Inc.
Please read Documentation/hw_random.txt for details on use.
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c
index dd1d143eb8ea..52e08ca3ccd7 100644
--- a/drivers/char/hw_random/nomadik-rng.c
+++ b/drivers/char/hw_random/nomadik-rng.c
@@ -55,7 +55,7 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
ret = amba_request_regions(dev, dev->dev.init_name);
if (ret)
- return ret;
+ goto out_clk;
ret = -ENOMEM;
base = ioremap(dev->res.start, resource_size(&dev->res));
if (!base)
@@ -70,6 +70,7 @@ out_unmap:
iounmap(base);
out_release:
amba_release_regions(dev);
+out_clk:
clk_disable(rng_clk);
clk_put(rng_clk);
return ret;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 2cc755a64302..b757fac3cd1f 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -113,8 +113,10 @@ static int __devinit omap_rng_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENOENT;
+ if (!res) {
+ ret = -ENOENT;
+ goto err_region;
+ }
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
ret = -EBUSY;
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
new file mode 100644
index 000000000000..b8afa6a4ff67
--- /dev/null
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -0,0 +1,156 @@
+/*
+ * Generic PowerPC 44x RNG driver
+ *
+ * Copyright 2011 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+
+#define PPC4XX_TRNG_DEV_CTRL 0x60080
+
+#define PPC4XX_TRNGE 0x00020000
+#define PPC4XX_TRNG_CTRL 0x0008
+#define PPC4XX_TRNG_CTRL_DALM 0x20
+#define PPC4XX_TRNG_STAT 0x0004
+#define PPC4XX_TRNG_STAT_B 0x1
+#define PPC4XX_TRNG_DATA 0x0000
+
+#define MODULE_NAME "ppc4xx_rng"
+
+static int ppc4xx_rng_data_present(struct hwrng *rng, int wait)
+{
+ void __iomem *rng_regs = (void __iomem *) rng->priv;
+ int busy, i, present = 0;
+
+ for (i = 0; i < 20; i++) {
+ busy = (in_le32(rng_regs + PPC4XX_TRNG_STAT) & PPC4XX_TRNG_STAT_B);
+ if (!busy || !wait) {
+ present = 1;
+ break;
+ }
+ udelay(10);
+ }
+ return present;
+}
+
+static int ppc4xx_rng_data_read(struct hwrng *rng, u32 *data)
+{
+ void __iomem *rng_regs = (void __iomem *) rng->priv;
+ *data = in_le32(rng_regs + PPC4XX_TRNG_DATA);
+ return 4;
+}
+
+static int ppc4xx_rng_enable(int enable)
+{
+ struct device_node *ctrl;
+ void __iomem *ctrl_reg;
+ int err = 0;
+ u32 val;
+
+ /* Find the main crypto device node and map it to turn the TRNG on */
+ ctrl = of_find_compatible_node(NULL, NULL, "amcc,ppc4xx-crypto");
+ if (!ctrl)
+ return -ENODEV;
+
+ ctrl_reg = of_iomap(ctrl, 0);
+ if (!ctrl_reg) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ val = in_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL);
+
+ if (enable)
+ val |= PPC4XX_TRNGE;
+ else
+ val = val & ~PPC4XX_TRNGE;
+
+ out_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL, val);
+ iounmap(ctrl_reg);
+
+out:
+ of_node_put(ctrl);
+
+ return err;
+}
+
+static struct hwrng ppc4xx_rng = {
+ .name = MODULE_NAME,
+ .data_present = ppc4xx_rng_data_present,
+ .data_read = ppc4xx_rng_data_read,
+};
+
+static int __devinit ppc4xx_rng_probe(struct platform_device *dev)
+{
+ void __iomem *rng_regs;
+ int err = 0;
+
+ rng_regs = of_iomap(dev->dev.of_node, 0);
+ if (!rng_regs)
+ return -ENODEV;
+
+ err = ppc4xx_rng_enable(1);
+ if (err)
+ return err;
+
+ out_le32(rng_regs + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM);
+ ppc4xx_rng.priv = (unsigned long) rng_regs;
+
+ err = hwrng_register(&ppc4xx_rng);
+
+ return err;
+}
+
+static int __devexit ppc4xx_rng_remove(struct platform_device *dev)
+{
+ void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
+
+ hwrng_unregister(&ppc4xx_rng);
+ ppc4xx_rng_enable(0);
+ iounmap(rng_regs);
+
+ return 0;
+}
+
+static struct of_device_id ppc4xx_rng_match[] = {
+ { .compatible = "ppc4xx-rng", },
+ { .compatible = "amcc,ppc460ex-rng", },
+ { .compatible = "amcc,ppc440epx-rng", },
+ {},
+};
+
+static struct platform_driver ppc4xx_rng_driver = {
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = ppc4xx_rng_match,
+ },
+ .probe = ppc4xx_rng_probe,
+ .remove = ppc4xx_rng_remove,
+};
+
+static int __init ppc4xx_rng_init(void)
+{
+ return platform_driver_register(&ppc4xx_rng_driver);
+}
+module_init(ppc4xx_rng_init);
+
+static void __exit ppc4xx_rng_exit(void)
+{
+ platform_driver_unregister(&ppc4xx_rng_driver);
+}
+module_exit(ppc4xx_rng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors");
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index a94e930575f2..a8428e6f64a9 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -100,8 +100,7 @@ static int __devinit timeriomem_rng_probe(struct platform_device *pdev)
timeriomem_rng_data = pdev->dev.platform_data;
- timeriomem_rng_data->address = ioremap(res->start,
- res->end - res->start + 1);
+ timeriomem_rng_data->address = ioremap(res->start, resource_size(res));
if (!timeriomem_rng_data->address)
return -EIO;
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 320668f4c3aa..3302586655c4 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -52,7 +52,7 @@
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#ifdef CONFIG_X86
/*
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 25d139c9dbed..5c0d96a820fa 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -46,7 +46,7 @@
#include <asm/page.h>
#include <asm/system.h>
#include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/tlbflush.h>
#include <asm/uncached.h>
#include <asm/sn/addrs.h>
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 166f1e7aaa7e..da3cfee782dc 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -224,6 +224,8 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
case 2:
offset += NVRAM_BYTES;
break;
+ default:
+ return -EINVAL;
}
return (offset >= 0) ? (file->f_pos = offset) : -EINVAL;
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index 85c004a518ee..d0c57c2e2909 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -101,12 +101,16 @@ static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
mutex_lock(&file->f_mapping->host->i_mutex);
switch (origin) {
+ case 0:
+ break;
case 1:
offset += file->f_pos;
break;
case 2:
offset += dev->regions[dev->region_idx].size*dev->blk_size;
break;
+ default:
+ offset = -1;
}
if (offset < 0) {
res = -EINVAL;
@@ -305,9 +309,14 @@ static int ps3flash_flush(struct file *file, fl_owner_t id)
return ps3flash_writeback(ps3flash_dev);
}
-static int ps3flash_fsync(struct file *file, int datasync)
+static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
- return ps3flash_writeback(ps3flash_dev);
+ struct inode *inode = file->f_path.dentry->d_inode;
+ int err;
+ mutex_lock(&inode->i_mutex);
+ err = ps3flash_writeback(ps3flash_dev);
+ mutex_unlock(&inode->i_mutex);
+ return err;
}
static irqreturn_t ps3flash_interrupt(int irq, void *data)
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
index 1a9f5f6d6ac5..bd9b94b518f3 100644
--- a/drivers/char/ramoops.c
+++ b/drivers/char/ramoops.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kmsg_dump.h>
@@ -26,11 +28,16 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/ramoops.h>
#define RAMOOPS_KERNMSG_HDR "===="
+#define MIN_MEM_SIZE 4096UL
-#define RECORD_SIZE 4096UL
+static ulong record_size = MIN_MEM_SIZE;
+module_param(record_size, ulong, 0400);
+MODULE_PARM_DESC(record_size,
+ "size of each dump done on oops/panic");
static ulong mem_address;
module_param(mem_address, ulong, 0400);
@@ -52,10 +59,15 @@ static struct ramoops_context {
void *virt_addr;
phys_addr_t phys_addr;
unsigned long size;
+ unsigned long record_size;
+ int dump_oops;
int count;
int max_count;
} oops_cxt;
+static struct platform_device *dummy;
+static struct ramoops_platform_data *dummy_data;
+
static void ramoops_do_dump(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
const char *s2, unsigned long l2)
@@ -74,13 +86,13 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
return;
/* Only dump oopses if dump_oops is set */
- if (reason == KMSG_DUMP_OOPS && !dump_oops)
+ if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
return;
- buf = cxt->virt_addr + (cxt->count * RECORD_SIZE);
+ buf = cxt->virt_addr + (cxt->count * cxt->record_size);
buf_orig = buf;
- memset(buf, '\0', RECORD_SIZE);
+ memset(buf, '\0', cxt->record_size);
res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
buf += res;
do_gettimeofday(&timestamp);
@@ -88,8 +100,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
buf += res;
hdr_size = buf - buf_orig;
- l2_cpy = min(l2, RECORD_SIZE - hdr_size);
- l1_cpy = min(l1, RECORD_SIZE - hdr_size - l2_cpy);
+ l2_cpy = min(l2, cxt->record_size - hdr_size);
+ l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy);
s2_start = l2 - l2_cpy;
s1_start = l1 - l1_cpy;
@@ -106,44 +118,51 @@ static int __init ramoops_probe(struct platform_device *pdev)
struct ramoops_context *cxt = &oops_cxt;
int err = -EINVAL;
- if (pdata) {
- mem_size = pdata->mem_size;
- mem_address = pdata->mem_address;
+ if (!pdata->mem_size || !pdata->record_size) {
+ pr_err("The memory size and the record size must be "
+ "non-zero\n");
+ goto fail3;
}
- if (!mem_size) {
- printk(KERN_ERR "ramoops: invalid size specification");
+ rounddown_pow_of_two(pdata->mem_size);
+ rounddown_pow_of_two(pdata->record_size);
+
+ /* Check for the minimum memory size */
+ if (pdata->mem_size < MIN_MEM_SIZE &&
+ pdata->record_size < MIN_MEM_SIZE) {
+ pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE);
goto fail3;
}
- rounddown_pow_of_two(mem_size);
-
- if (mem_size < RECORD_SIZE) {
- printk(KERN_ERR "ramoops: size too small");
+ if (pdata->mem_size < pdata->record_size) {
+ pr_err("The memory size must be larger than the "
+ "records size\n");
goto fail3;
}
- cxt->max_count = mem_size / RECORD_SIZE;
+ cxt->max_count = pdata->mem_size / pdata->record_size;
cxt->count = 0;
- cxt->size = mem_size;
- cxt->phys_addr = mem_address;
+ cxt->size = pdata->mem_size;
+ cxt->phys_addr = pdata->mem_address;
+ cxt->record_size = pdata->record_size;
+ cxt->dump_oops = pdata->dump_oops;
if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
- printk(KERN_ERR "ramoops: request mem region failed");
+ pr_err("request mem region failed\n");
err = -EINVAL;
goto fail3;
}
cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size);
if (!cxt->virt_addr) {
- printk(KERN_ERR "ramoops: ioremap failed");
+ pr_err("ioremap failed\n");
goto fail2;
}
cxt->dump.dump = ramoops_do_dump;
err = kmsg_dump_register(&cxt->dump);
if (err) {
- printk(KERN_ERR "ramoops: registering kmsg dumper failed");
+ pr_err("registering kmsg dumper failed\n");
goto fail1;
}
@@ -162,7 +181,7 @@ static int __exit ramoops_remove(struct platform_device *pdev)
struct ramoops_context *cxt = &oops_cxt;
if (kmsg_dump_unregister(&cxt->dump) < 0)
- printk(KERN_WARNING "ramoops: could not unregister kmsg_dumper");
+ pr_warn("could not unregister kmsg_dumper\n");
iounmap(cxt->virt_addr);
release_mem_region(cxt->phys_addr, cxt->size);
@@ -179,12 +198,39 @@ static struct platform_driver ramoops_driver = {
static int __init ramoops_init(void)
{
- return platform_driver_probe(&ramoops_driver, ramoops_probe);
+ int ret;
+ ret = platform_driver_probe(&ramoops_driver, ramoops_probe);
+ if (ret == -ENODEV) {
+ /*
+ * If we didn't find a platform device, we use module parameters
+ * building platform data on the fly.
+ */
+ pr_info("platform device not found, using module parameters\n");
+ dummy_data = kzalloc(sizeof(struct ramoops_platform_data),
+ GFP_KERNEL);
+ if (!dummy_data)
+ return -ENOMEM;
+ dummy_data->mem_size = mem_size;
+ dummy_data->mem_address = mem_address;
+ dummy_data->record_size = record_size;
+ dummy_data->dump_oops = dump_oops;
+ dummy = platform_create_bundle(&ramoops_driver, ramoops_probe,
+ NULL, 0, dummy_data,
+ sizeof(struct ramoops_platform_data));
+
+ if (IS_ERR(dummy))
+ ret = PTR_ERR(dummy);
+ else
+ ret = 0;
+ }
+
+ return ret;
}
static void __exit ramoops_exit(void)
{
platform_driver_unregister(&ramoops_driver);
+ kfree(dummy_data);
}
module_init(ramoops_init);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index d4ddeba56682..729281961f22 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1523,6 +1523,21 @@ __u32 secure_ip_id(__be32 daddr)
return half_md4_transform(hash, keyptr->secret);
}
+__u32 secure_ipv6_id(const __be32 daddr[4])
+{
+ const struct keydata *keyptr;
+ __u32 hash[4];
+
+ keyptr = get_keyptr();
+
+ hash[0] = (__force __u32)daddr[0];
+ hash[1] = (__force __u32)daddr[1];
+ hash[2] = (__force __u32)daddr[2];
+ hash[3] = (__force __u32)daddr[3];
+
+ return half_md4_transform(hash, keyptr->secret);
+}
+
#ifdef CONFIG_INET
__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 39ccdeada791..e90e1c74fd4c 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -621,7 +621,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
drvdata->mem_start = regs_res->start;
drvdata->mem_end = regs_res->end;
- drvdata->mem_size = regs_res->end - regs_res->start + 1;
+ drvdata->mem_size = resource_size(regs_res);
if (!request_mem_region(drvdata->mem_start,
drvdata->mem_size, DRIVER_NAME)) {
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c8896e16..35309274ad68 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
config CLKDEV_LOOKUP
bool
select HAVE_CLK
+
+config HAVE_MACH_CLKDEV
+ bool
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 96c921910469..34e9c4f88926 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -1,5 +1,17 @@
config CLKSRC_I8253
bool
+config CLKEVT_I8253
+ bool
+
+config I8253_LOCK
+ bool
+
+config CLKBLD_I8253
+ def_bool y if CLKSRC_I8253 || CLKEVT_I8253 || I8253_LOCK
+
config CLKSRC_MMIO
bool
+
+config DW_APB_TIMER
+ bool
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index b995942a5060..85ad1646a7b7 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o
obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o
obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
-obj-$(CONFIG_CLKSRC_I8253) += i8253.o
+obj-$(CONFIG_CLKBLD_I8253) += i8253.o
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
+obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
new file mode 100644
index 000000000000..580f870541a3
--- /dev/null
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -0,0 +1,401 @@
+/*
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@intel.com)
+ *
+ * Shared with ARM platforms, Jamie Iles, Picochip 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 as
+ * published by the Free Software Foundation.
+ *
+ * Support for the Synopsys DesignWare APB Timers.
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define APBT_MIN_PERIOD 4
+#define APBT_MIN_DELTA_USEC 200
+
+#define APBTMR_N_LOAD_COUNT 0x00
+#define APBTMR_N_CURRENT_VALUE 0x04
+#define APBTMR_N_CONTROL 0x08
+#define APBTMR_N_EOI 0x0c
+#define APBTMR_N_INT_STATUS 0x10
+
+#define APBTMRS_INT_STATUS 0xa0
+#define APBTMRS_EOI 0xa4
+#define APBTMRS_RAW_INT_STATUS 0xa8
+#define APBTMRS_COMP_VERSION 0xac
+
+#define APBTMR_CONTROL_ENABLE (1 << 0)
+/* 1: periodic, 0:free running. */
+#define APBTMR_CONTROL_MODE_PERIODIC (1 << 1)
+#define APBTMR_CONTROL_INT (1 << 2)
+
+static inline struct dw_apb_clock_event_device *
+ced_to_dw_apb_ced(struct clock_event_device *evt)
+{
+ return container_of(evt, struct dw_apb_clock_event_device, ced);
+}
+
+static inline struct dw_apb_clocksource *
+clocksource_to_dw_apb_clocksource(struct clocksource *cs)
+{
+ return container_of(cs, struct dw_apb_clocksource, cs);
+}
+
+static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
+{
+ return readl(timer->base + offs);
+}
+
+static void apbt_writel(struct dw_apb_timer *timer, unsigned long val,
+ unsigned long offs)
+{
+ writel(val, timer->base + offs);
+}
+
+static void apbt_disable_int(struct dw_apb_timer *timer)
+{
+ unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
+
+ ctrl |= APBTMR_CONTROL_INT;
+ apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
+}
+
+/**
+ * dw_apb_clockevent_pause() - stop the clock_event_device from running
+ *
+ * @dw_ced: The APB clock to stop generating events.
+ */
+void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)
+{
+ disable_irq(dw_ced->timer.irq);
+ apbt_disable_int(&dw_ced->timer);
+}
+
+static void apbt_eoi(struct dw_apb_timer *timer)
+{
+ apbt_readl(timer, APBTMR_N_EOI);
+}
+
+static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
+{
+ struct clock_event_device *evt = data;
+ struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
+
+ if (!evt->event_handler) {
+ pr_info("Spurious APBT timer interrupt %d", irq);
+ return IRQ_NONE;
+ }
+
+ if (dw_ced->eoi)
+ dw_ced->eoi(&dw_ced->timer);
+
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+}
+
+static void apbt_enable_int(struct dw_apb_timer *timer)
+{
+ unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
+ /* clear pending intr */
+ apbt_readl(timer, APBTMR_N_EOI);
+ ctrl &= ~APBTMR_CONTROL_INT;
+ apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
+}
+
+static void apbt_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ unsigned long period;
+ struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
+
+ pr_debug("%s CPU %d mode=%d\n", __func__, first_cpu(*evt->cpumask),
+ mode);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
+ ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+ ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ /*
+ * DW APB p. 46, have to disable timer before load counter,
+ * may cause sync problem.
+ */
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ udelay(1);
+ pr_debug("Setting clock period %lu for HZ %d\n", period, HZ);
+ apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT);
+ ctrl |= APBTMR_CONTROL_ENABLE;
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+ /*
+ * set free running mode, this mode will let timer reload max
+ * timeout which will give time (3min on 25MHz clock) to rearm
+ * the next event, therefore emulate the one-shot mode.
+ */
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ /* write again to set free running mode */
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+
+ /*
+ * DW APB p. 46, load counter with all 1s before starting free
+ * running mode.
+ */
+ apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT);
+ ctrl &= ~APBTMR_CONTROL_INT;
+ ctrl |= APBTMR_CONTROL_ENABLE;
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ apbt_enable_int(&dw_ced->timer);
+ break;
+ }
+}
+
+static int apbt_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
+
+ /* Disable timer */
+ ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ /* write new count */
+ apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
+ ctrl |= APBTMR_CONTROL_ENABLE;
+ apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+
+ return 0;
+}
+
+/**
+ * dw_apb_clockevent_init() - use an APB timer as a clock_event_device
+ *
+ * @cpu: The CPU the events will be targeted at.
+ * @name: The name used for the timer and the IRQ for it.
+ * @rating: The rating to give the timer.
+ * @base: I/O base for the timer registers.
+ * @irq: The interrupt number to use for the timer.
+ * @freq: The frequency that the timer counts at.
+ *
+ * This creates a clock_event_device for using with the generic clock layer
+ * but does not start and register it. This should be done with
+ * dw_apb_clockevent_register() as the next step. If this is the first time
+ * it has been called for a timer then the IRQ will be requested, if not it
+ * just be enabled to allow CPU hotplug to avoid repeatedly requesting and
+ * releasing the IRQ.
+ */
+struct dw_apb_clock_event_device *
+dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
+ void __iomem *base, int irq, unsigned long freq)
+{
+ struct dw_apb_clock_event_device *dw_ced =
+ kzalloc(sizeof(*dw_ced), GFP_KERNEL);
+ int err;
+
+ if (!dw_ced)
+ return NULL;
+
+ dw_ced->timer.base = base;
+ dw_ced->timer.irq = irq;
+ dw_ced->timer.freq = freq;
+
+ clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD);
+ dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff,
+ &dw_ced->ced);
+ dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
+ dw_ced->ced.cpumask = cpumask_of(cpu);
+ dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ dw_ced->ced.set_mode = apbt_set_mode;
+ dw_ced->ced.set_next_event = apbt_next_event;
+ dw_ced->ced.irq = dw_ced->timer.irq;
+ dw_ced->ced.rating = rating;
+ dw_ced->ced.name = name;
+
+ dw_ced->irqaction.name = dw_ced->ced.name;
+ dw_ced->irqaction.handler = dw_apb_clockevent_irq;
+ dw_ced->irqaction.dev_id = &dw_ced->ced;
+ dw_ced->irqaction.irq = irq;
+ dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL |
+ IRQF_NOBALANCING |
+ IRQF_DISABLED;
+
+ dw_ced->eoi = apbt_eoi;
+ err = setup_irq(irq, &dw_ced->irqaction);
+ if (err) {
+ pr_err("failed to request timer irq\n");
+ kfree(dw_ced);
+ dw_ced = NULL;
+ }
+
+ return dw_ced;
+}
+
+/**
+ * dw_apb_clockevent_resume() - resume a clock that has been paused.
+ *
+ * @dw_ced: The APB clock to resume.
+ */
+void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced)
+{
+ enable_irq(dw_ced->timer.irq);
+}
+
+/**
+ * dw_apb_clockevent_stop() - stop the clock_event_device and release the IRQ.
+ *
+ * @dw_ced: The APB clock to stop generating the events.
+ */
+void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced)
+{
+ free_irq(dw_ced->timer.irq, &dw_ced->ced);
+}
+
+/**
+ * dw_apb_clockevent_register() - register the clock with the generic layer
+ *
+ * @dw_ced: The APB clock to register as a clock_event_device.
+ */
+void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced)
+{
+ apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL);
+ clockevents_register_device(&dw_ced->ced);
+ apbt_enable_int(&dw_ced->timer);
+}
+
+/**
+ * dw_apb_clocksource_start() - start the clocksource counting.
+ *
+ * @dw_cs: The clocksource to start.
+ *
+ * This is used to start the clocksource before registration and can be used
+ * to enable calibration of timers.
+ */
+void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
+{
+ /*
+ * start count down from 0xffff_ffff. this is done by toggling the
+ * enable bit then load initial load count to ~0.
+ */
+ unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
+
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
+ apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT);
+ /* enable, mask interrupt */
+ ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+ ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
+ apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
+ /* read it once to get cached counter value initialized */
+ dw_apb_clocksource_read(dw_cs);
+}
+
+static cycle_t __apbt_read_clocksource(struct clocksource *cs)
+{
+ unsigned long current_count;
+ struct dw_apb_clocksource *dw_cs =
+ clocksource_to_dw_apb_clocksource(cs);
+
+ current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
+
+ return (cycle_t)~current_count;
+}
+
+static void apbt_restart_clocksource(struct clocksource *cs)
+{
+ struct dw_apb_clocksource *dw_cs =
+ clocksource_to_dw_apb_clocksource(cs);
+
+ dw_apb_clocksource_start(dw_cs);
+}
+
+/**
+ * dw_apb_clocksource_init() - use an APB timer as a clocksource.
+ *
+ * @rating: The rating to give the clocksource.
+ * @name: The name for the clocksource.
+ * @base: The I/O base for the timer registers.
+ * @freq: The frequency that the timer counts at.
+ *
+ * This creates a clocksource using an APB timer but does not yet register it
+ * with the clocksource system. This should be done with
+ * dw_apb_clocksource_register() as the next step.
+ */
+struct dw_apb_clocksource *
+dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
+ unsigned long freq)
+{
+ struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL);
+
+ if (!dw_cs)
+ return NULL;
+
+ dw_cs->timer.base = base;
+ dw_cs->timer.freq = freq;
+ dw_cs->cs.name = name;
+ dw_cs->cs.rating = rating;
+ dw_cs->cs.read = __apbt_read_clocksource;
+ dw_cs->cs.mask = CLOCKSOURCE_MASK(32);
+ dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+ dw_cs->cs.resume = apbt_restart_clocksource;
+
+ return dw_cs;
+}
+
+/**
+ * dw_apb_clocksource_register() - register the APB clocksource.
+ *
+ * @dw_cs: The clocksource to register.
+ */
+void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs)
+{
+ clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq);
+}
+
+/**
+ * dw_apb_clocksource_read() - read the current value of a clocksource.
+ *
+ * @dw_cs: The clocksource to read.
+ */
+cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs)
+{
+ return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
+}
+
+/**
+ * dw_apb_clocksource_unregister() - unregister and free a clocksource.
+ *
+ * @dw_cs: The clocksource to unregister/free.
+ */
+void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs)
+{
+ clocksource_unregister(&dw_cs->cs);
+
+ kfree(dw_cs);
+}
diff --git a/drivers/clocksource/i8253.c b/drivers/clocksource/i8253.c
index 225c1761b372..27c49e60b7d6 100644
--- a/drivers/clocksource/i8253.c
+++ b/drivers/clocksource/i8253.c
@@ -1,14 +1,25 @@
/*
* i8253 PIT clocksource
*/
-#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/timex.h>
+#include <linux/module.h>
+#include <linux/i8253.h>
+#include <linux/smp.h>
-#include <asm/i8253.h>
+/*
+ * Protects access to I/O ports
+ *
+ * 0040-0043 : timer0, i8253 / i8254
+ * 0061-0061 : NMI Control Register which contains two speaker control bits.
+ */
+DEFINE_RAW_SPINLOCK(i8253_lock);
+EXPORT_SYMBOL(i8253_lock);
+#ifdef CONFIG_CLKSRC_I8253
/*
* Since the PIT overflows every tick, its not very useful
* to just read by itself. So use jiffies to emulate a free
@@ -37,15 +48,15 @@ static cycle_t i8253_read(struct clocksource *cs)
* count), it cannot be newer.
*/
jifs = jiffies;
- outb_pit(0x00, PIT_MODE); /* latch the count ASAP */
- count = inb_pit(PIT_CH0); /* read the latched count */
- count |= inb_pit(PIT_CH0) << 8;
+ outb_p(0x00, PIT_MODE); /* latch the count ASAP */
+ count = inb_p(PIT_CH0); /* read the latched count */
+ count |= inb_p(PIT_CH0) << 8;
/* VIA686a test code... reset the latch if count > max + 1 */
if (count > LATCH) {
- outb_pit(0x34, PIT_MODE);
- outb_pit(PIT_LATCH & 0xff, PIT_CH0);
- outb_pit(PIT_LATCH >> 8, PIT_CH0);
+ outb_p(0x34, PIT_MODE);
+ outb_p(PIT_LATCH & 0xff, PIT_CH0);
+ outb_p(PIT_LATCH >> 8, PIT_CH0);
count = PIT_LATCH - 1;
}
@@ -86,3 +97,90 @@ int __init clocksource_i8253_init(void)
{
return clocksource_register_hz(&i8253_cs, PIT_TICK_RATE);
}
+#endif
+
+#ifdef CONFIG_CLKEVT_I8253
+/*
+ * Initialize the PIT timer.
+ *
+ * This is also called after resume to bring the PIT into operation again.
+ */
+static void init_pit_timer(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ raw_spin_lock(&i8253_lock);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* binary, mode 2, LSB/MSB, ch 0 */
+ outb_p(0x34, PIT_MODE);
+ outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
+ outb_p(LATCH >> 8 , PIT_CH0); /* MSB */
+ break;
+
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
+ evt->mode == CLOCK_EVT_MODE_ONESHOT) {
+ outb_p(0x30, PIT_MODE);
+ outb_p(0, PIT_CH0);
+ outb_p(0, PIT_CH0);
+ }
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* One shot setup */
+ outb_p(0x38, PIT_MODE);
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ /* Nothing to do here */
+ break;
+ }
+ raw_spin_unlock(&i8253_lock);
+}
+
+/*
+ * Program the next event in oneshot mode
+ *
+ * Delta is given in PIT ticks
+ */
+static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+ raw_spin_lock(&i8253_lock);
+ outb_p(delta & 0xff , PIT_CH0); /* LSB */
+ outb_p(delta >> 8 , PIT_CH0); /* MSB */
+ raw_spin_unlock(&i8253_lock);
+
+ return 0;
+}
+
+/*
+ * On UP the PIT can serve all of the possible timer functions. On SMP systems
+ * it can be solely used for the global tick.
+ */
+struct clock_event_device i8253_clockevent = {
+ .name = "pit",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .set_mode = init_pit_timer,
+ .set_next_event = pit_next_event,
+};
+
+/*
+ * Initialize the conversion factor and the min/max deltas of the clock event
+ * structure and register the clock event source with the framework.
+ */
+void __init clockevent_i8253_init(bool oneshot)
+{
+ if (oneshot)
+ i8253_clockevent.features |= CLOCK_EVT_FEAT_ONESHOT;
+ /*
+ * Start pit with the boot cpu mask. x86 might make it global
+ * when it is used as broadcast device later.
+ */
+ i8253_clockevent.cpumask = cpumask_of(smp_processor_id());
+
+ clockevents_config_and_register(&i8253_clockevent, PIT_TICK_RATE,
+ 0xF, 0x7FFF);
+}
+#endif
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 2b46a7efa0ac..3ee1fdb31ea7 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -28,7 +28,9 @@
#include <linux/init.h>
#include <linux/connector.h>
#include <linux/gfp.h>
-#include <asm/atomic.h>
+#include <linux/ptrace.h>
+#include <linux/atomic.h>
+
#include <asm/unaligned.h>
#include <linux/cn_proc.h>
@@ -166,6 +168,39 @@ void proc_sid_connector(struct task_struct *task)
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}
+void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
+{
+ 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_PTRACE;
+ ev->event_data.ptrace.process_pid = task->pid;
+ ev->event_data.ptrace.process_tgid = task->tgid;
+ if (ptrace_id == PTRACE_ATTACH) {
+ ev->event_data.ptrace.tracer_pid = current->pid;
+ ev->event_data.ptrace.tracer_tgid = current->tgid;
+ } else if (ptrace_id == PTRACE_DETACH) {
+ ev->event_data.ptrace.tracer_pid = 0;
+ ev->event_data.ptrace.tracer_tgid = 0;
+ } else
+ return;
+
+ 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/Kconfig b/drivers/cpufreq/Kconfig
index 9fb84853d8e3..e24a2a1b6666 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -184,5 +184,15 @@ depends on X86
source "drivers/cpufreq/Kconfig.x86"
endmenu
+menu "ARM CPU frequency scaling drivers"
+depends on ARM
+source "drivers/cpufreq/Kconfig.arm"
+endmenu
+
+menu "PowerPC CPU frequency scaling drivers"
+depends on PPC32 || PPC64
+source "drivers/cpufreq/Kconfig.powerpc"
+endmenu
+
endif
endmenu
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
new file mode 100644
index 000000000000..72a0044c1baa
--- /dev/null
+++ b/drivers/cpufreq/Kconfig.arm
@@ -0,0 +1,32 @@
+#
+# ARM CPU Frequency scaling drivers
+#
+
+config ARM_S3C64XX_CPUFREQ
+ bool "Samsung S3C64XX"
+ depends on CPU_S3C6410
+ default y
+ help
+ This adds the CPUFreq driver for Samsung S3C6410 SoC.
+
+ If in doubt, say N.
+
+config ARM_S5PV210_CPUFREQ
+ bool "Samsung S5PV210 and S5PC110"
+ depends on CPU_S5PV210
+ default y
+ help
+ This adds the CPUFreq driver for Samsung S5PV210 and
+ S5PC110 SoCs.
+
+ If in doubt, say N.
+
+config ARM_EXYNOS4210_CPUFREQ
+ bool "Samsung EXYNOS4210"
+ depends on CPU_EXYNOS4210
+ default y
+ help
+ This adds the CPUFreq driver for Samsung EXYNOS4210
+ SoC (S5PV310 or S5PC210).
+
+ If in doubt, say N.
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
new file mode 100644
index 000000000000..e76992f79683
--- /dev/null
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -0,0 +1,7 @@
+config CPU_FREQ_MAPLE
+ bool "Support for Maple 970FX Evaluation Board"
+ depends on PPC_MAPLE
+ select CPU_FREQ_TABLE
+ help
+ This adds support for frequency switching on Maple 970FX
+ Evaluation Board and compatible boards (IBM JS2x blades).
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index e2fc2d21fa61..a48bc02cd765 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
-##################################################################################d
+##################################################################################
# x86 drivers.
# Link order matters. K8 is preferred to ACPI because of firmware bugs in early
# K8 systems. ACPI is preferred to all other hardware-specific drivers.
@@ -37,7 +37,13 @@ obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
-##################################################################################d
-
+##################################################################################
# ARM SoC drivers
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
+obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
+obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
+obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
+
+##################################################################################
+# PowerPC platform drivers
+obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 596d5dd32f41..56c6c6b4eb4d 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -655,7 +655,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
acpi_processor_notify_smm(THIS_MODULE);
/* Check for APERF/MPERF support in hardware */
- if (cpu_has(c, X86_FEATURE_APERFMPERF))
+ if (boot_cpu_has(X86_FEATURE_APERFMPERF))
acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf;
pr_debug("CPU%u - ACPI performance management activated.\n", cpu);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0a5bea9e3585..987a165ede26 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1199,6 +1199,26 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
}
EXPORT_SYMBOL(cpufreq_quick_get);
+/**
+ * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
+ * @cpu: CPU number
+ *
+ * Just return the max possible frequency for a given CPU.
+ */
+unsigned int cpufreq_quick_get_max(unsigned int cpu)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+ unsigned int ret_freq = 0;
+
+ if (policy) {
+ ret_freq = policy->max;
+ cpufreq_cpu_put(policy);
+ }
+
+ return ret_freq;
+}
+EXPORT_SYMBOL(cpufreq_quick_get_max);
+
static unsigned int __cpufreq_get(unsigned int cpu)
{
diff --git a/arch/arm/mach-exynos4/cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index a1bd258f0c4d..b7c3a84c4cfa 100644
--- a/arch/arm/mach-exynos4/cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos4/cpufreq.c
- *
+/*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
@@ -192,17 +191,17 @@ static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
((200 << 16) | (6 << 8) | 4),
};
-int exynos4_verify_speed(struct cpufreq_policy *policy)
+static int exynos4_verify_speed(struct cpufreq_policy *policy)
{
return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
}
-unsigned int exynos4_getspeed(unsigned int cpu)
+static unsigned int exynos4_getspeed(unsigned int cpu)
{
return clk_get_rate(cpu_clk) / 1000;
}
-void exynos4_set_clkdiv(unsigned int div_index)
+static void exynos4_set_clkdiv(unsigned int div_index)
{
unsigned int tmp;
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
new file mode 100644
index 000000000000..89b178a3f849
--- /dev/null
+++ b/drivers/cpufreq/maple-cpufreq.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * and Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs,
+ * that is iMac G5 and latest single CPU desktop.
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/time.h>
+#include <linux/of.h>
+
+#define DBG(fmt...) pr_debug(fmt)
+
+/* see 970FX user manual */
+
+#define SCOM_PCR 0x0aa001 /* PCR scom addr */
+
+#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */
+#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */
+#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */
+#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */
+#define PCR_SPEED_MASK 0x000e0000U /* speed mask */
+#define PCR_SPEED_SHIFT 17
+#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */
+#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */
+#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */
+#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */
+#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */
+#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */
+
+#define SCOM_PSR 0x408001 /* PSR scom addr */
+/* warning: PSR is a 64 bits register */
+#define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */
+#define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */
+#define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */
+#define PSR_CUR_SPEED_SHIFT (56)
+
+/*
+ * The G5 only supports two frequencies (Quarter speed is not supported)
+ */
+#define CPUFREQ_HIGH 0
+#define CPUFREQ_LOW 1
+
+static struct cpufreq_frequency_table maple_cpu_freqs[] = {
+ {CPUFREQ_HIGH, 0},
+ {CPUFREQ_LOW, 0},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static struct freq_attr *maple_cpu_freqs_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+/* Power mode data is an array of the 32 bits PCR values to use for
+ * the various frequencies, retrieved from the device-tree
+ */
+static int maple_pmode_cur;
+
+static DEFINE_MUTEX(maple_switch_mutex);
+
+static const u32 *maple_pmode_data;
+static int maple_pmode_max;
+
+/*
+ * SCOM based frequency switching for 970FX rev3
+ */
+static int maple_scom_switch_freq(int speed_mode)
+{
+ unsigned long flags;
+ int to;
+
+ local_irq_save(flags);
+
+ /* Clear PCR high */
+ scom970_write(SCOM_PCR, 0);
+ /* Clear PCR low */
+ scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0);
+ /* Set PCR low */
+ scom970_write(SCOM_PCR, PCR_HILO_SELECT |
+ maple_pmode_data[speed_mode]);
+
+ /* Wait for completion */
+ for (to = 0; to < 10; to++) {
+ unsigned long psr = scom970_read(SCOM_PSR);
+
+ if ((psr & PSR_CMD_RECEIVED) == 0 &&
+ (((psr >> PSR_CUR_SPEED_SHIFT) ^
+ (maple_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3)
+ == 0)
+ break;
+ if (psr & PSR_CMD_COMPLETED)
+ break;
+ udelay(100);
+ }
+
+ local_irq_restore(flags);
+
+ maple_pmode_cur = speed_mode;
+ ppc_proc_freq = maple_cpu_freqs[speed_mode].frequency * 1000ul;
+
+ return 0;
+}
+
+static int maple_scom_query_freq(void)
+{
+ unsigned long psr = scom970_read(SCOM_PSR);
+ int i;
+
+ for (i = 0; i <= maple_pmode_max; i++)
+ if ((((psr >> PSR_CUR_SPEED_SHIFT) ^
+ (maple_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0)
+ break;
+ return i;
+}
+
+/*
+ * Common interface to the cpufreq core
+ */
+
+static int maple_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, maple_cpu_freqs);
+}
+
+static int maple_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq, unsigned int relation)
+{
+ unsigned int newstate = 0;
+ struct cpufreq_freqs freqs;
+ int rc;
+
+ if (cpufreq_frequency_table_target(policy, maple_cpu_freqs,
+ target_freq, relation, &newstate))
+ return -EINVAL;
+
+ if (maple_pmode_cur == newstate)
+ return 0;
+
+ mutex_lock(&maple_switch_mutex);
+
+ freqs.old = maple_cpu_freqs[maple_pmode_cur].frequency;
+ freqs.new = maple_cpu_freqs[newstate].frequency;
+ freqs.cpu = 0;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ rc = maple_scom_switch_freq(newstate);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ mutex_unlock(&maple_switch_mutex);
+
+ return rc;
+}
+
+static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
+{
+ return maple_cpu_freqs[maple_pmode_cur].frequency;
+}
+
+static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ policy->cpuinfo.transition_latency = 12000;
+ policy->cur = maple_cpu_freqs[maple_scom_query_freq()].frequency;
+ /* secondary CPUs are tied to the primary one by the
+ * cpufreq core if in the secondary policy we tell it that
+ * it actually must be one policy together with all others. */
+ cpumask_copy(policy->cpus, cpu_online_mask);
+ cpufreq_frequency_table_get_attr(maple_cpu_freqs, policy->cpu);
+
+ return cpufreq_frequency_table_cpuinfo(policy,
+ maple_cpu_freqs);
+}
+
+
+static struct cpufreq_driver maple_cpufreq_driver = {
+ .name = "maple",
+ .owner = THIS_MODULE,
+ .flags = CPUFREQ_CONST_LOOPS,
+ .init = maple_cpufreq_cpu_init,
+ .verify = maple_cpufreq_verify,
+ .target = maple_cpufreq_target,
+ .get = maple_cpufreq_get_speed,
+ .attr = maple_cpu_freqs_attr,
+};
+
+static int __init maple_cpufreq_init(void)
+{
+ struct device_node *cpus;
+ struct device_node *cpunode;
+ unsigned int psize;
+ unsigned long max_freq;
+ const u32 *valp;
+ u32 pvr_hi;
+ int rc = -ENODEV;
+
+ /*
+ * Behave here like powermac driver which checks machine compatibility
+ * to ease merging of two drivers in future.
+ */
+ if (!of_machine_is_compatible("Momentum,Maple") &&
+ !of_machine_is_compatible("Momentum,Apache"))
+ return 0;
+
+ cpus = of_find_node_by_path("/cpus");
+ if (cpus == NULL) {
+ DBG("No /cpus node !\n");
+ return -ENODEV;
+ }
+
+ /* Get first CPU node */
+ for (cpunode = NULL;
+ (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
+ const u32 *reg = of_get_property(cpunode, "reg", NULL);
+ if (reg == NULL || (*reg) != 0)
+ continue;
+ if (!strcmp(cpunode->type, "cpu"))
+ break;
+ }
+ if (cpunode == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n");
+ goto bail_cpus;
+ }
+
+ /* Check 970FX for now */
+ /* we actually don't care on which CPU to access PVR */
+ pvr_hi = PVR_VER(mfspr(SPRN_PVR));
+ if (pvr_hi != 0x3c && pvr_hi != 0x44) {
+ printk(KERN_ERR "cpufreq: Unsupported CPU version (%x)\n",
+ pvr_hi);
+ goto bail_noprops;
+ }
+
+ /* Look for the powertune data in the device-tree */
+ /*
+ * On Maple this property is provided by PIBS in dual-processor config,
+ * not provided by PIBS in CPU0 config and also not provided by SLOF,
+ * so YMMV
+ */
+ maple_pmode_data = of_get_property(cpunode, "power-mode-data", &psize);
+ if (!maple_pmode_data) {
+ DBG("No power-mode-data !\n");
+ goto bail_noprops;
+ }
+ maple_pmode_max = psize / sizeof(u32) - 1;
+
+ /*
+ * From what I see, clock-frequency is always the maximal frequency.
+ * The current driver can not slew sysclk yet, so we really only deal
+ * with powertune steps for now. We also only implement full freq and
+ * half freq in this version. So far, I haven't yet seen a machine
+ * supporting anything else.
+ */
+ valp = of_get_property(cpunode, "clock-frequency", NULL);
+ if (!valp)
+ return -ENODEV;
+ max_freq = (*valp)/1000;
+ maple_cpu_freqs[0].frequency = max_freq;
+ maple_cpu_freqs[1].frequency = max_freq/2;
+
+ /* Force apply current frequency to make sure everything is in
+ * sync (voltage is right for example). Firmware may leave us with
+ * a strange setting ...
+ */
+ msleep(10);
+ maple_pmode_cur = -1;
+ maple_scom_switch_freq(maple_scom_query_freq());
+
+ printk(KERN_INFO "Registering Maple CPU frequency driver\n");
+ printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
+ maple_cpu_freqs[1].frequency/1000,
+ maple_cpu_freqs[0].frequency/1000,
+ maple_cpu_freqs[maple_pmode_cur].frequency/1000);
+
+ rc = cpufreq_register_driver(&maple_cpufreq_driver);
+
+ of_node_put(cpunode);
+ of_node_put(cpus);
+
+ return rc;
+
+bail_noprops:
+ of_node_put(cpunode);
+bail_cpus:
+ of_node_put(cpus);
+
+ return rc;
+}
+
+module_init(maple_cpufreq_init);
+
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-s3c64xx/cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 4375b97588b8..b8d1d205e1ef 100644
--- a/arch/arm/mach-s3c64xx/cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -1,5 +1,4 @@
-/* linux/arch/arm/plat-s3c64xx/cpufreq.c
- *
+/*
* Copyright 2009 Wolfson Microelectronics plc
*
* S3C64xx CPUfreq Support
@@ -32,11 +31,14 @@ static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {
[1] = { 1050000, 1150000 },
[2] = { 1100000, 1150000 },
[3] = { 1200000, 1350000 },
+ [4] = { 1300000, 1350000 },
};
static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
{ 0, 66000 },
+ { 0, 100000 },
{ 0, 133000 },
+ { 1, 200000 },
{ 1, 222000 },
{ 1, 266000 },
{ 2, 333000 },
@@ -44,6 +46,7 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
{ 2, 532000 },
{ 2, 533000 },
{ 3, 667000 },
+ { 4, 800000 },
{ 0, CPUFREQ_TABLE_END },
};
#endif
@@ -111,6 +114,8 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
goto err;
}
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
#ifdef CONFIG_REGULATOR
if (vddarm && freqs.new < freqs.old) {
ret = regulator_set_voltage(vddarm,
@@ -124,8 +129,6 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
}
#endif
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
pr_debug("cpufreq: Set actual frequency %lukHz\n",
clk_get_rate(armclk) / 1000);
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 153af8b359ec..a484aaea9809 100644
--- a/arch/arm/mach-s5pv210/cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-s5pv210/cpufreq.c
- *
+/*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
@@ -17,6 +16,9 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/cpufreq.h>
+#include <linux/reboot.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
@@ -25,11 +27,27 @@ static struct clk *cpu_clk;
static struct clk *dmc0_clk;
static struct clk *dmc1_clk;
static struct cpufreq_freqs freqs;
+static DEFINE_MUTEX(set_freq_lock);
/* APLL M,P,S values for 1G/800Mhz */
#define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1)
#define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1)
+/* Use 800MHz when entering sleep mode */
+#define SLEEP_FREQ (800 * 1000)
+
+/*
+ * relation has an additional symantics other than the standard of cpufreq
+ * DISALBE_FURTHER_CPUFREQ: disable further access to target
+ * ENABLE_FURTUER_CPUFREQ: enable access to target
+ */
+enum cpufreq_access {
+ DISABLE_FURTHER_CPUFREQ = 0x10,
+ ENABLE_FURTHER_CPUFREQ = 0x20,
+};
+
+static bool no_cpufreq_access;
+
/*
* DRAM configurations to calculate refresh counter for changing
* frequency of memory.
@@ -66,6 +84,40 @@ static struct cpufreq_frequency_table s5pv210_freq_table[] = {
{0, CPUFREQ_TABLE_END},
};
+static struct regulator *arm_regulator;
+static struct regulator *int_regulator;
+
+struct s5pv210_dvs_conf {
+ int arm_volt; /* uV */
+ int int_volt; /* uV */
+};
+
+static const int arm_volt_max = 1350000;
+static const int int_volt_max = 1250000;
+
+static struct s5pv210_dvs_conf dvs_conf[] = {
+ [L0] = {
+ .arm_volt = 1250000,
+ .int_volt = 1100000,
+ },
+ [L1] = {
+ .arm_volt = 1200000,
+ .int_volt = 1100000,
+ },
+ [L2] = {
+ .arm_volt = 1050000,
+ .int_volt = 1100000,
+ },
+ [L3] = {
+ .arm_volt = 950000,
+ .int_volt = 1100000,
+ },
+ [L4] = {
+ .arm_volt = 950000,
+ .int_volt = 1000000,
+ },
+};
+
static u32 clkdiv_val[5][11] = {
/*
* Clock divider value for following
@@ -122,7 +174,7 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
__raw_writel(tmp1, reg);
}
-int s5pv210_verify_speed(struct cpufreq_policy *policy)
+static int s5pv210_verify_speed(struct cpufreq_policy *policy)
{
if (policy->cpu)
return -EINVAL;
@@ -130,7 +182,7 @@ int s5pv210_verify_speed(struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
}
-unsigned int s5pv210_getspeed(unsigned int cpu)
+static unsigned int s5pv210_getspeed(unsigned int cpu)
{
if (cpu)
return 0;
@@ -146,30 +198,66 @@ static int s5pv210_target(struct cpufreq_policy *policy,
unsigned int index, priv_index;
unsigned int pll_changing = 0;
unsigned int bus_speed_changing = 0;
+ int arm_volt, int_volt;
+ int ret = 0;
+
+ mutex_lock(&set_freq_lock);
+
+ if (relation & ENABLE_FURTHER_CPUFREQ)
+ no_cpufreq_access = false;
+
+ if (no_cpufreq_access) {
+#ifdef CONFIG_PM_VERBOSE
+ pr_err("%s:%d denied access to %s as it is disabled"
+ "temporarily\n", __FILE__, __LINE__, __func__);
+#endif
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (relation & DISABLE_FURTHER_CPUFREQ)
+ no_cpufreq_access = true;
+
+ relation &= ~(ENABLE_FURTHER_CPUFREQ | DISABLE_FURTHER_CPUFREQ);
freqs.old = s5pv210_getspeed(0);
if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
- target_freq, relation, &index))
- return -EINVAL;
+ target_freq, relation, &index)) {
+ ret = -EINVAL;
+ goto exit;
+ }
freqs.new = s5pv210_freq_table[index].frequency;
freqs.cpu = 0;
if (freqs.new == freqs.old)
- return 0;
+ goto exit;
/* Finding current running level index */
if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
- freqs.old, relation, &priv_index))
- return -EINVAL;
+ freqs.old, relation, &priv_index)) {
+ ret = -EINVAL;
+ goto exit;
+ }
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ arm_volt = dvs_conf[index].arm_volt;
+ int_volt = dvs_conf[index].int_volt;
if (freqs.new > freqs.old) {
- /* Voltage up: will be implemented */
+ ret = regulator_set_voltage(arm_regulator,
+ arm_volt, arm_volt_max);
+ if (ret)
+ goto exit;
+
+ ret = regulator_set_voltage(int_regulator,
+ int_volt, int_volt_max);
+ if (ret)
+ goto exit;
}
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
/* Check if there need to change PLL */
if ((index == L0) || (priv_index == L0))
pll_changing = 1;
@@ -380,15 +468,21 @@ static int s5pv210_target(struct cpufreq_policy *policy,
}
}
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
if (freqs.new < freqs.old) {
- /* Voltage down: will be implemented */
- }
+ regulator_set_voltage(int_regulator,
+ int_volt, int_volt_max);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ regulator_set_voltage(arm_regulator,
+ arm_volt, arm_volt_max);
+ }
printk(KERN_DEBUG "Perf changed[L%d]\n", index);
- return 0;
+exit:
+ mutex_unlock(&set_freq_lock);
+ return ret;
}
#ifdef CONFIG_PM
@@ -416,6 +510,7 @@ static int check_mem_type(void __iomem *dmc_reg)
static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
{
unsigned long mem_type;
+ int ret;
cpu_clk = clk_get(NULL, "armclk");
if (IS_ERR(cpu_clk))
@@ -423,19 +518,20 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
dmc0_clk = clk_get(NULL, "sclk_dmc0");
if (IS_ERR(dmc0_clk)) {
- clk_put(cpu_clk);
- return PTR_ERR(dmc0_clk);
+ ret = PTR_ERR(dmc0_clk);
+ goto out_dmc0;
}
dmc1_clk = clk_get(NULL, "hclk_msys");
if (IS_ERR(dmc1_clk)) {
- clk_put(dmc0_clk);
- clk_put(cpu_clk);
- return PTR_ERR(dmc1_clk);
+ ret = PTR_ERR(dmc1_clk);
+ goto out_dmc1;
}
- if (policy->cpu != 0)
- return -EINVAL;
+ if (policy->cpu != 0) {
+ ret = -EINVAL;
+ goto out_dmc1;
+ }
/*
* check_mem_type : This driver only support LPDDR & LPDDR2.
@@ -445,7 +541,8 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_dmc1;
}
/* Find current refresh counter and frequency each DMC */
@@ -462,6 +559,49 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 40000;
return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+
+out_dmc1:
+ clk_put(dmc0_clk);
+out_dmc0:
+ clk_put(cpu_clk);
+ return ret;
+}
+
+static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ int ret;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ DISABLE_FURTHER_CPUFREQ);
+ if (ret < 0)
+ return NOTIFY_BAD;
+
+ return NOTIFY_OK;
+ case PM_POST_RESTORE:
+ case PM_POST_SUSPEND:
+ cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ ENABLE_FURTHER_CPUFREQ);
+
+ return NOTIFY_OK;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ int ret;
+
+ ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ DISABLE_FURTHER_CPUFREQ);
+ if (ret < 0)
+ return NOTIFY_BAD;
+
+ return NOTIFY_DONE;
}
static struct cpufreq_driver s5pv210_driver = {
@@ -477,8 +617,32 @@ static struct cpufreq_driver s5pv210_driver = {
#endif
};
+static struct notifier_block s5pv210_cpufreq_notifier = {
+ .notifier_call = s5pv210_cpufreq_notifier_event,
+};
+
+static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
+ .notifier_call = s5pv210_cpufreq_reboot_notifier_event,
+};
+
static int __init s5pv210_cpufreq_init(void)
{
+ arm_regulator = regulator_get(NULL, "vddarm");
+ if (IS_ERR(arm_regulator)) {
+ pr_err("failed to get regulator vddarm");
+ return PTR_ERR(arm_regulator);
+ }
+
+ int_regulator = regulator_get(NULL, "vddint");
+ if (IS_ERR(int_regulator)) {
+ pr_err("failed to get regulator vddint");
+ regulator_put(arm_regulator);
+ return PTR_ERR(int_regulator);
+ }
+
+ register_pm_notifier(&s5pv210_cpufreq_notifier);
+ register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
+
return cpufreq_register_driver(&s5pv210_driver);
}
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 18912521a7a5..1d103f997dc2 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -51,6 +51,7 @@ static void crypto4xx_hw_init(struct crypto4xx_device *dev)
union ce_io_threshold io_threshold;
u32 rand_num;
union ce_pe_dma_cfg pe_dma_cfg;
+ u32 device_ctrl;
writel(PPC4XX_BYTE_ORDER, dev->ce_base + CRYPTO4XX_BYTE_ORDER_CFG);
/* setup pe dma, include reset sg, pdr and pe, then release reset */
@@ -84,7 +85,9 @@ static void crypto4xx_hw_init(struct crypto4xx_device *dev)
writel(ring_size.w, dev->ce_base + CRYPTO4XX_RING_SIZE);
ring_ctrl.w = 0;
writel(ring_ctrl.w, dev->ce_base + CRYPTO4XX_RING_CTRL);
- writel(PPC4XX_DC_3DES_EN, dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
+ device_ctrl = readl(dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
+ device_ctrl |= PPC4XX_DC_3DES_EN;
+ writel(device_ctrl, dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
writel(dev->gdr_pa, dev->ce_base + CRYPTO4XX_GATH_RING_BASE);
writel(dev->sdr_pa, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE);
part_ring_size.w = 0;
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 676d957c22b0..4159265b453b 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -62,10 +62,22 @@
#define CAAM_MAX_IV_LENGTH 16
/* length of descriptors text */
-#define DESC_AEAD_SHARED_TEXT_LEN 4
-#define DESC_AEAD_ENCRYPT_TEXT_LEN 21
-#define DESC_AEAD_DECRYPT_TEXT_LEN 24
-#define DESC_AEAD_GIVENCRYPT_TEXT_LEN 27
+#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 3 + CAAM_PTR_SZ * 3)
+
+#define DESC_AEAD_BASE (4 * CAAM_CMD_SZ)
+#define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 16 * CAAM_CMD_SZ)
+#define DESC_AEAD_DEC_LEN (DESC_AEAD_BASE + 21 * CAAM_CMD_SZ)
+#define DESC_AEAD_GIVENC_LEN (DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
+
+#define DESC_ABLKCIPHER_BASE (3 * CAAM_CMD_SZ)
+#define DESC_ABLKCIPHER_ENC_LEN (DESC_ABLKCIPHER_BASE + \
+ 20 * CAAM_CMD_SZ)
+#define DESC_ABLKCIPHER_DEC_LEN (DESC_ABLKCIPHER_BASE + \
+ 15 * CAAM_CMD_SZ)
+
+#define DESC_MAX_USED_BYTES (DESC_AEAD_GIVENC_LEN + \
+ CAAM_MAX_KEY_SIZE)
+#define DESC_MAX_USED_LEN (DESC_MAX_USED_BYTES / CAAM_CMD_SZ)
#ifdef DEBUG
/* for print_hex_dumps with line references */
@@ -76,30 +88,366 @@
#define debug(format, arg...)
#endif
+/* Set DK bit in class 1 operation if shared */
+static inline void append_dec_op1(u32 *desc, u32 type)
+{
+ u32 *jump_cmd, *uncond_jump_cmd;
+
+ jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
+ append_operation(desc, type | OP_ALG_AS_INITFINAL |
+ OP_ALG_DECRYPT);
+ uncond_jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, jump_cmd);
+ append_operation(desc, type | OP_ALG_AS_INITFINAL |
+ OP_ALG_DECRYPT | OP_ALG_AAI_DK);
+ set_jump_tgt_here(desc, uncond_jump_cmd);
+}
+
+/*
+ * Wait for completion of class 1 key loading before allowing
+ * error propagation
+ */
+static inline void append_dec_shr_done(u32 *desc)
+{
+ u32 *jump_cmd;
+
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, jump_cmd);
+ append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+}
+
+/*
+ * For aead functions, read payload and write payload,
+ * both of which are specified in req->src and req->dst
+ */
+static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
+{
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
+ KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
+}
+
+/*
+ * For aead encrypt and decrypt, read iv for both classes
+ */
+static inline void aead_append_ld_iv(u32 *desc, int ivsize)
+{
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | ivsize);
+ append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ivsize);
+}
+
+/*
+ * For ablkcipher encrypt and decrypt, read from req->src and
+ * write to req->dst
+ */
+static inline void ablkcipher_append_src_dst(u32 *desc)
+{
+ append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ); \
+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); \
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | \
+ KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1); \
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF); \
+}
+
+/*
+ * If all data, including src (with assoc and iv) or dst (with iv only) are
+ * contiguous
+ */
+#define GIV_SRC_CONTIG 1
+#define GIV_DST_CONTIG (1 << 1)
+
/*
* per-session context
*/
struct caam_ctx {
struct device *jrdev;
- u32 *sh_desc;
- dma_addr_t shared_desc_phys;
+ u32 sh_desc_enc[DESC_MAX_USED_LEN];
+ u32 sh_desc_dec[DESC_MAX_USED_LEN];
+ u32 sh_desc_givenc[DESC_MAX_USED_LEN];
+ dma_addr_t sh_desc_enc_dma;
+ dma_addr_t sh_desc_dec_dma;
+ dma_addr_t sh_desc_givenc_dma;
u32 class1_alg_type;
u32 class2_alg_type;
u32 alg_op;
- u8 *key;
- dma_addr_t key_phys;
+ u8 key[CAAM_MAX_KEY_SIZE];
+ dma_addr_t key_dma;
unsigned int enckeylen;
unsigned int split_key_len;
unsigned int split_key_pad_len;
unsigned int authsize;
};
-static int aead_authenc_setauthsize(struct crypto_aead *authenc,
+static void append_key_aead(u32 *desc, struct caam_ctx *ctx,
+ int keys_fit_inline)
+{
+ if (keys_fit_inline) {
+ append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key_as_imm(desc, (void *)ctx->key +
+ ctx->split_key_pad_len, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ } else {
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ }
+}
+
+static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
+ int keys_fit_inline)
+{
+ u32 *key_jump_cmd;
+
+ init_sh_desc(desc, HDR_SHARE_WAIT);
+
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ append_key_aead(desc, ctx, keys_fit_inline);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* Propagate errors from shared to job descriptor */
+ append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+}
+
+static int aead_set_sh_desc(struct crypto_aead *aead)
+{
+ struct aead_tfm *tfm = &aead->base.crt_aead;
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ bool keys_fit_inline = 0;
+ u32 *key_jump_cmd, *jump_cmd;
+ u32 geniv, moveiv;
+ u32 *desc;
+
+ if (!ctx->enckeylen || !ctx->authsize)
+ return 0;
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_ENC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = 1;
+
+ /* aead_encrypt shared descriptor */
+ desc = ctx->sh_desc_enc;
+
+ init_sh_desc_key_aead(desc, ctx, keys_fit_inline);
+
+ /* Class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* cryptlen = seqoutlen - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+ /* assoclen + cryptlen = seqinlen - ivsize */
+ append_math_sub_imm_u32(desc, REG2, SEQINLEN, IMM, tfm->ivsize);
+
+ /* assoclen + cryptlen = (assoclen + cryptlen) - cryptlen */
+ append_math_sub(desc, VARSEQINLEN, REG2, REG3, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+ aead_append_ld_iv(desc, tfm->ivsize);
+
+ /* Class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* Read and write cryptlen bytes */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+
+ /* Write ICV */
+ append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+ ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "aead enc shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_DEC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = 1;
+
+ desc = ctx->sh_desc_dec;
+
+ /* aead_decrypt shared descriptor */
+ init_sh_desc(desc, HDR_SHARE_WAIT);
+
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ append_key_aead(desc, ctx, keys_fit_inline);
+
+ /* Only propagate error immediately if shared */
+ jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, key_jump_cmd);
+ append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /* Class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+ /* assoclen + cryptlen = seqinlen - ivsize */
+ append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
+ ctx->authsize + tfm->ivsize)
+ /* assoclen = (assoclen + cryptlen) - cryptlen */
+ append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+
+ aead_append_ld_iv(desc, tfm->ivsize);
+
+ append_dec_op1(desc, ctx->class1_alg_type);
+
+ /* Read and write cryptlen bytes */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG);
+
+ /* Load ICV */
+ append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+ append_dec_shr_done(desc);
+
+ ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "aead dec shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_GIVENC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = 1;
+
+ /* aead_givencrypt shared descriptor */
+ desc = ctx->sh_desc_givenc;
+
+ init_sh_desc_key_aead(desc, ctx, keys_fit_inline);
+
+ /* Generate IV */
+ geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
+ NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
+ NFIFOENTRY_PTYPE_RND | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
+ append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+ append_move(desc, MOVE_SRC_INFIFO |
+ MOVE_DEST_CLASS1CTX | (tfm->ivsize << MOVE_LEN_SHIFT));
+ append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+ /* Copy IV to class 1 context */
+ append_move(desc, MOVE_SRC_CLASS1CTX |
+ MOVE_DEST_OUTFIFO | (tfm->ivsize << MOVE_LEN_SHIFT));
+
+ /* Return to encryption */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* ivsize + cryptlen = seqoutlen - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+ /* assoclen = seqinlen - (ivsize + cryptlen) */
+ append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+
+ /* Copy iv from class 1 ctx to class 2 fifo*/
+ moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
+ NFIFOENTRY_DTYPE_MSG | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
+ append_load_imm_u32(desc, moveiv, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+ append_load_imm_u32(desc, tfm->ivsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM);
+
+ /* Class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* Will write ivsize + cryptlen */
+ append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+ /* Not need to reload iv */
+ append_seq_fifo_load(desc, tfm->ivsize,
+ FIFOLD_CLASS_SKIP);
+
+ /* Will read cryptlen */
+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+
+ /* Write ICV */
+ append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+ ctx->sh_desc_givenc_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "aead givenc shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ return 0;
+}
+
+static int aead_setauthsize(struct crypto_aead *authenc,
unsigned int authsize)
{
struct caam_ctx *ctx = crypto_aead_ctx(authenc);
ctx->authsize = authsize;
+ aead_set_sh_desc(authenc);
return 0;
}
@@ -117,6 +465,7 @@ static void split_key_done(struct device *dev, u32 *desc, u32 err,
#ifdef DEBUG
dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
#endif
+
if (err) {
char tmp[CAAM_ERROR_STR_MAX];
@@ -220,73 +569,7 @@ static u32 gen_split_key(struct caam_ctx *ctx, const u8 *key_in, u32 authkeylen)
return ret;
}
-static int build_sh_desc_ipsec(struct caam_ctx *ctx)
-{
- struct device *jrdev = ctx->jrdev;
- u32 *sh_desc;
- u32 *jump_cmd;
- bool keys_fit_inline = 0;
-
- /*
- * largest Job Descriptor and its Shared Descriptor
- * must both fit into the 64-word Descriptor h/w Buffer
- */
- if ((DESC_AEAD_GIVENCRYPT_TEXT_LEN +
- DESC_AEAD_SHARED_TEXT_LEN) * CAAM_CMD_SZ +
- ctx->split_key_pad_len + ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
- keys_fit_inline = 1;
-
- /* build shared descriptor for this session */
- sh_desc = kmalloc(CAAM_CMD_SZ * DESC_AEAD_SHARED_TEXT_LEN +
- (keys_fit_inline ?
- ctx->split_key_pad_len + ctx->enckeylen :
- CAAM_PTR_SZ * 2), GFP_DMA | GFP_KERNEL);
- if (!sh_desc) {
- dev_err(jrdev, "could not allocate shared descriptor\n");
- return -ENOMEM;
- }
-
- init_sh_desc(sh_desc, HDR_SAVECTX | HDR_SHARE_SERIAL);
-
- jump_cmd = append_jump(sh_desc, CLASS_BOTH | JUMP_TEST_ALL |
- JUMP_COND_SHRD | JUMP_COND_SELF);
-
- /*
- * process keys, starting with class 2/authentication.
- */
- if (keys_fit_inline) {
- append_key_as_imm(sh_desc, ctx->key, ctx->split_key_pad_len,
- ctx->split_key_len,
- CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC);
-
- append_key_as_imm(sh_desc, (void *)ctx->key +
- ctx->split_key_pad_len, ctx->enckeylen,
- ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
- } else {
- append_key(sh_desc, ctx->key_phys, ctx->split_key_len, CLASS_2 |
- KEY_DEST_MDHA_SPLIT | KEY_ENC);
- append_key(sh_desc, ctx->key_phys + ctx->split_key_pad_len,
- ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
- }
-
- /* update jump cmd now that we are at the jump target */
- set_jump_tgt_here(sh_desc, jump_cmd);
-
- ctx->shared_desc_phys = dma_map_single(jrdev, sh_desc,
- desc_bytes(sh_desc),
- DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, ctx->shared_desc_phys)) {
- dev_err(jrdev, "unable to map shared descriptor\n");
- kfree(sh_desc);
- return -ENOMEM;
- }
-
- ctx->sh_desc = sh_desc;
-
- return 0;
-}
-
-static int aead_authenc_setkey(struct crypto_aead *aead,
+static int aead_setkey(struct crypto_aead *aead,
const u8 *key, unsigned int keylen)
{
/* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
@@ -326,27 +609,19 @@ static int aead_authenc_setkey(struct crypto_aead *aead,
print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
#endif
- ctx->key = kmalloc(ctx->split_key_pad_len + enckeylen,
- GFP_KERNEL | GFP_DMA);
- if (!ctx->key) {
- dev_err(jrdev, "could not allocate key output memory\n");
- return -ENOMEM;
- }
ret = gen_split_key(ctx, key, authkeylen);
if (ret) {
- kfree(ctx->key);
goto badkey;
}
/* postpend encryption key to auth split key */
memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen);
- ctx->key_phys = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
enckeylen, DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, ctx->key_phys)) {
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
dev_err(jrdev, "unable to map key i/o memory\n");
- kfree(ctx->key);
return -ENOMEM;
}
#ifdef DEBUG
@@ -357,11 +632,10 @@ static int aead_authenc_setkey(struct crypto_aead *aead,
ctx->enckeylen = enckeylen;
- ret = build_sh_desc_ipsec(ctx);
+ ret = aead_set_sh_desc(aead);
if (ret) {
- dma_unmap_single(jrdev, ctx->key_phys, ctx->split_key_pad_len +
+ dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len +
enckeylen, DMA_TO_DEVICE);
- kfree(ctx->key);
}
return ret;
@@ -370,6 +644,119 @@ badkey:
return -EINVAL;
}
+static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
+ const u8 *key, unsigned int keylen)
+{
+ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+ struct ablkcipher_tfm *tfm = &ablkcipher->base.crt_ablkcipher;
+ struct device *jrdev = ctx->jrdev;
+ int ret = 0;
+ u32 *key_jump_cmd, *jump_cmd;
+ u32 *desc;
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+
+ memcpy(ctx->key, key, keylen);
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ return -ENOMEM;
+ }
+ ctx->enckeylen = keylen;
+
+ /* ablkcipher_encrypt shared descriptor */
+ desc = ctx->sh_desc_enc;
+ init_sh_desc(desc, HDR_SHARE_WAIT);
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ /* Load class1 key only */
+ append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 |
+ KEY_DEST_CLASS_REG);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* Propagate errors from shared to job descriptor */
+ append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+
+ /* Load iv */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+
+ /* Load operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* Perform operation */
+ ablkcipher_append_src_dst(desc);
+
+ ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ablkcipher enc shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+ /* ablkcipher_decrypt shared descriptor */
+ desc = ctx->sh_desc_dec;
+
+ init_sh_desc(desc, HDR_SHARE_WAIT);
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ /* Load class1 key only */
+ append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 |
+ KEY_DEST_CLASS_REG);
+
+ /* For aead, only propagate error immediately if shared */
+ jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, key_jump_cmd);
+ append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /* load IV */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+
+ /* Choose operation */
+ append_dec_op1(desc, ctx->class1_alg_type);
+
+ /* Perform operation */
+ ablkcipher_append_src_dst(desc);
+
+ /* Wait for key to load before allowing propagating error */
+ append_dec_shr_done(desc);
+
+ ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ablkcipher dec shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ return ret;
+}
+
struct link_tbl_entry {
u64 ptr;
u32 len;
@@ -379,64 +766,109 @@ struct link_tbl_entry {
};
/*
- * ipsec_esp_edesc - s/w-extended ipsec_esp descriptor
+ * aead_edesc - s/w-extended aead descriptor
+ * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
* @src_nents: number of segments in input scatterlist
* @dst_nents: number of segments in output scatterlist
- * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
+ * @iv_dma: dma address of iv for checking continuity and link table
* @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
* @link_tbl_bytes: length of dma mapped link_tbl space
* @link_tbl_dma: bus physical mapped address of h/w link table
* @hw_desc: the h/w job descriptor followed by any referenced link tables
*/
-struct ipsec_esp_edesc {
+struct aead_edesc {
int assoc_nents;
int src_nents;
int dst_nents;
+ dma_addr_t iv_dma;
int link_tbl_bytes;
dma_addr_t link_tbl_dma;
struct link_tbl_entry *link_tbl;
u32 hw_desc[0];
};
-static void ipsec_esp_unmap(struct device *dev,
- struct ipsec_esp_edesc *edesc,
- struct aead_request *areq)
-{
- dma_unmap_sg(dev, areq->assoc, edesc->assoc_nents, DMA_TO_DEVICE);
+/*
+ * ablkcipher_edesc - s/w-extended ablkcipher descriptor
+ * @src_nents: number of segments in input scatterlist
+ * @dst_nents: number of segments in output scatterlist
+ * @iv_dma: dma address of iv for checking continuity and link table
+ * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
+ * @link_tbl_bytes: length of dma mapped link_tbl space
+ * @link_tbl_dma: bus physical mapped address of h/w link table
+ * @hw_desc: the h/w job descriptor followed by any referenced link tables
+ */
+struct ablkcipher_edesc {
+ int src_nents;
+ int dst_nents;
+ dma_addr_t iv_dma;
+ int link_tbl_bytes;
+ dma_addr_t link_tbl_dma;
+ struct link_tbl_entry *link_tbl;
+ u32 hw_desc[0];
+};
- if (unlikely(areq->dst != areq->src)) {
- dma_unmap_sg(dev, areq->src, edesc->src_nents,
- DMA_TO_DEVICE);
- dma_unmap_sg(dev, areq->dst, edesc->dst_nents,
- DMA_FROM_DEVICE);
+static void caam_unmap(struct device *dev, struct scatterlist *src,
+ struct scatterlist *dst, int src_nents, int dst_nents,
+ dma_addr_t iv_dma, int ivsize, dma_addr_t link_tbl_dma,
+ int link_tbl_bytes)
+{
+ if (unlikely(dst != src)) {
+ dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
+ dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
} else {
- dma_unmap_sg(dev, areq->src, edesc->src_nents,
- DMA_BIDIRECTIONAL);
+ dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
}
- if (edesc->link_tbl_bytes)
- dma_unmap_single(dev, edesc->link_tbl_dma,
- edesc->link_tbl_bytes,
+ if (iv_dma)
+ dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+ if (link_tbl_bytes)
+ dma_unmap_single(dev, link_tbl_dma, link_tbl_bytes,
DMA_TO_DEVICE);
}
-/*
- * ipsec_esp descriptor callbacks
- */
-static void ipsec_esp_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
+static void aead_unmap(struct device *dev,
+ struct aead_edesc *edesc,
+ struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ int ivsize = crypto_aead_ivsize(aead);
+
+ dma_unmap_sg(dev, req->assoc, edesc->assoc_nents, DMA_TO_DEVICE);
+
+ caam_unmap(dev, req->src, req->dst,
+ edesc->src_nents, edesc->dst_nents,
+ edesc->iv_dma, ivsize, edesc->link_tbl_dma,
+ edesc->link_tbl_bytes);
+}
+
+static void ablkcipher_unmap(struct device *dev,
+ struct ablkcipher_edesc *edesc,
+ struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+
+ caam_unmap(dev, req->src, req->dst,
+ edesc->src_nents, edesc->dst_nents,
+ edesc->iv_dma, ivsize, edesc->link_tbl_dma,
+ edesc->link_tbl_bytes);
+}
+
+static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
void *context)
{
- struct aead_request *areq = context;
- struct ipsec_esp_edesc *edesc;
+ struct aead_request *req = context;
+ struct aead_edesc *edesc;
#ifdef DEBUG
- struct crypto_aead *aead = crypto_aead_reqtfm(areq);
- int ivsize = crypto_aead_ivsize(aead);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
#endif
- edesc = (struct ipsec_esp_edesc *)((char *)desc -
- offsetof(struct ipsec_esp_edesc, hw_desc));
+
+ edesc = (struct aead_edesc *)((char *)desc -
+ offsetof(struct aead_edesc, hw_desc));
if (err) {
char tmp[CAAM_ERROR_STR_MAX];
@@ -444,39 +876,50 @@ static void ipsec_esp_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
}
- ipsec_esp_unmap(jrdev, edesc, areq);
+ aead_unmap(jrdev, edesc, req);
#ifdef DEBUG
print_hex_dump(KERN_ERR, "assoc @"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->assoc),
- areq->assoclen , 1);
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+ req->assoclen , 1);
print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src) - ivsize,
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src) - ivsize,
edesc->src_nents ? 100 : ivsize, 1);
print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src),
- edesc->src_nents ? 100 : areq->cryptlen +
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ edesc->src_nents ? 100 : req->cryptlen +
ctx->authsize + 4, 1);
#endif
kfree(edesc);
- aead_request_complete(areq, err);
+ aead_request_complete(req, err);
}
-static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
+static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
void *context)
{
- struct aead_request *areq = context;
- struct ipsec_esp_edesc *edesc;
+ struct aead_request *req = context;
+ struct aead_edesc *edesc;
#ifdef DEBUG
- struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
#endif
- edesc = (struct ipsec_esp_edesc *)((char *)desc -
- offsetof(struct ipsec_esp_edesc, hw_desc));
+
+ edesc = (struct aead_edesc *)((char *)desc -
+ offsetof(struct aead_edesc, hw_desc));
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
+ ivsize, 1);
+ print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
+ req->cryptlen, 1);
+#endif
if (err) {
char tmp[CAAM_ERROR_STR_MAX];
@@ -484,7 +927,7 @@ static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
}
- ipsec_esp_unmap(jrdev, edesc, areq);
+ aead_unmap(jrdev, edesc, req);
/*
* verify hw auth check passed else return -EBADMSG
@@ -495,255 +938,413 @@ static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
#ifdef DEBUG
print_hex_dump(KERN_ERR, "iphdrout@"xstr(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4,
- ((char *)sg_virt(areq->assoc) - sizeof(struct iphdr)),
- sizeof(struct iphdr) + areq->assoclen +
- ((areq->cryptlen > 1500) ? 1500 : areq->cryptlen) +
+ ((char *)sg_virt(req->assoc) - sizeof(struct iphdr)),
+ sizeof(struct iphdr) + req->assoclen +
+ ((req->cryptlen > 1500) ? 1500 : req->cryptlen) +
ctx->authsize + 36, 1);
if (!err && edesc->link_tbl_bytes) {
- struct scatterlist *sg = sg_last(areq->src, edesc->src_nents);
+ struct scatterlist *sg = sg_last(req->src, edesc->src_nents);
print_hex_dump(KERN_ERR, "sglastout@"xstr(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(sg),
sg->length + ctx->authsize + 16, 1);
}
#endif
+
kfree(edesc);
- aead_request_complete(areq, err);
+ aead_request_complete(req, err);
+}
+
+static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct ablkcipher_request *req = context;
+ struct ablkcipher_edesc *edesc;
+#ifdef DEBUG
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct ablkcipher_edesc *)((char *)desc -
+ offsetof(struct ablkcipher_edesc, hw_desc));
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->info,
+ edesc->src_nents > 1 ? 100 : ivsize, 1);
+ print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
+#endif
+
+ ablkcipher_unmap(jrdev, edesc, req);
+ kfree(edesc);
+
+ ablkcipher_request_complete(req, err);
+}
+
+static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct ablkcipher_request *req = context;
+ struct ablkcipher_edesc *edesc;
+#ifdef DEBUG
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct ablkcipher_edesc *)((char *)desc -
+ offsetof(struct ablkcipher_edesc, hw_desc));
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->info,
+ ivsize, 1);
+ print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
+#endif
+
+ ablkcipher_unmap(jrdev, edesc, req);
+ kfree(edesc);
+
+ ablkcipher_request_complete(req, err);
+}
+
+static void sg_to_link_tbl_one(struct link_tbl_entry *link_tbl_ptr,
+ dma_addr_t dma, u32 len, u32 offset)
+{
+ link_tbl_ptr->ptr = dma;
+ link_tbl_ptr->len = len;
+ link_tbl_ptr->reserved = 0;
+ link_tbl_ptr->buf_pool_id = 0;
+ link_tbl_ptr->offset = offset;
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "link_tbl_ptr@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, link_tbl_ptr,
+ sizeof(struct link_tbl_entry), 1);
+#endif
}
/*
* convert scatterlist to h/w link table format
- * scatterlist must have been previously dma mapped
+ * but does not have final bit; instead, returns last entry
*/
-static void sg_to_link_tbl(struct scatterlist *sg, int sg_count,
- struct link_tbl_entry *link_tbl_ptr, u32 offset)
+static struct link_tbl_entry *sg_to_link_tbl(struct scatterlist *sg,
+ int sg_count, struct link_tbl_entry
+ *link_tbl_ptr, u32 offset)
{
while (sg_count) {
- link_tbl_ptr->ptr = sg_dma_address(sg);
- link_tbl_ptr->len = sg_dma_len(sg);
- link_tbl_ptr->reserved = 0;
- link_tbl_ptr->buf_pool_id = 0;
- link_tbl_ptr->offset = offset;
+ sg_to_link_tbl_one(link_tbl_ptr, sg_dma_address(sg),
+ sg_dma_len(sg), offset);
link_tbl_ptr++;
sg = sg_next(sg);
sg_count--;
}
+ return link_tbl_ptr - 1;
+}
- /* set Final bit (marks end of link table) */
- link_tbl_ptr--;
+/*
+ * convert scatterlist to h/w link table format
+ * scatterlist must have been previously dma mapped
+ */
+static void sg_to_link_tbl_last(struct scatterlist *sg, int sg_count,
+ struct link_tbl_entry *link_tbl_ptr, u32 offset)
+{
+ link_tbl_ptr = sg_to_link_tbl(sg, sg_count, link_tbl_ptr, offset);
link_tbl_ptr->len |= 0x40000000;
}
/*
- * fill in and submit ipsec_esp job descriptor
+ * Fill in aead job descriptor
*/
-static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
- u32 encrypt,
- void (*callback) (struct device *dev, u32 *desc,
- u32 err, void *context))
+static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
+ struct aead_edesc *edesc,
+ struct aead_request *req,
+ bool all_contig, bool encrypt)
{
- struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
- struct device *jrdev = ctx->jrdev;
- u32 *desc = edesc->hw_desc, options;
- int ret, sg_count, assoc_sg_count;
int ivsize = crypto_aead_ivsize(aead);
int authsize = ctx->authsize;
- dma_addr_t ptr, dst_dma, src_dma;
-#ifdef DEBUG
- u32 *sh_desc = ctx->sh_desc;
+ u32 *desc = edesc->hw_desc;
+ u32 out_options = 0, in_options;
+ dma_addr_t dst_dma, src_dma;
+ int len, link_tbl_index = 0;
+#ifdef DEBUG
debug("assoclen %d cryptlen %d authsize %d\n",
- areq->assoclen, areq->cryptlen, authsize);
+ req->assoclen, req->cryptlen, authsize);
print_hex_dump(KERN_ERR, "assoc @"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->assoc),
- areq->assoclen , 1);
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+ req->assoclen , 1);
print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src) - ivsize,
+ DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
edesc->src_nents ? 100 : ivsize, 1);
print_hex_dump(KERN_ERR, "src @"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src),
- edesc->src_nents ? 100 : areq->cryptlen + authsize, 1);
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ edesc->src_nents ? 100 : req->cryptlen, 1);
print_hex_dump(KERN_ERR, "shrdesc@"xstr(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, sh_desc,
desc_bytes(sh_desc), 1);
#endif
- assoc_sg_count = dma_map_sg(jrdev, areq->assoc, edesc->assoc_nents ?: 1,
- DMA_TO_DEVICE);
- if (areq->src == areq->dst)
- sg_count = dma_map_sg(jrdev, areq->src, edesc->src_nents ? : 1,
- DMA_BIDIRECTIONAL);
- else
- sg_count = dma_map_sg(jrdev, areq->src, edesc->src_nents ? : 1,
- DMA_TO_DEVICE);
- /* start auth operation */
- append_operation(desc, ctx->class2_alg_type | OP_ALG_AS_INITFINAL |
- (encrypt ? : OP_ALG_ICV_ON));
+ len = desc_len(sh_desc);
+ init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
- /* Load FIFO with data for Class 2 CHA */
- options = FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG;
- if (!edesc->assoc_nents) {
- ptr = sg_dma_address(areq->assoc);
+ if (all_contig) {
+ src_dma = sg_dma_address(req->assoc);
+ in_options = 0;
} else {
- sg_to_link_tbl(areq->assoc, edesc->assoc_nents,
- edesc->link_tbl, 0);
- ptr = edesc->link_tbl_dma;
- options |= LDST_SGF;
+ src_dma = edesc->link_tbl_dma;
+ link_tbl_index += (edesc->assoc_nents ? : 1) + 1 +
+ (edesc->src_nents ? : 1);
+ in_options = LDST_SGF;
}
- append_fifo_load(desc, ptr, areq->assoclen, options);
-
- /* copy iv from cipher/class1 input context to class2 infifo */
- append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ivsize);
-
- if (!encrypt) {
- u32 *jump_cmd, *uncond_jump_cmd;
-
- /* JUMP if shared */
- jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
+ if (encrypt)
+ append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
+ req->cryptlen - authsize, in_options);
+ else
+ append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
+ req->cryptlen, in_options);
- /* start class 1 (cipher) operation, non-shared version */
- append_operation(desc, ctx->class1_alg_type |
- OP_ALG_AS_INITFINAL);
+ if (likely(req->src == req->dst)) {
+ if (all_contig) {
+ dst_dma = sg_dma_address(req->src);
+ } else {
+ dst_dma = src_dma + sizeof(struct link_tbl_entry) *
+ ((edesc->assoc_nents ? : 1) + 1);
+ out_options = LDST_SGF;
+ }
+ } else {
+ if (!edesc->dst_nents) {
+ dst_dma = sg_dma_address(req->dst);
+ } else {
+ dst_dma = edesc->link_tbl_dma +
+ link_tbl_index *
+ sizeof(struct link_tbl_entry);
+ out_options = LDST_SGF;
+ }
+ }
+ if (encrypt)
+ append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
+ else
+ append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize,
+ out_options);
+}
- uncond_jump_cmd = append_jump(desc, 0);
+/*
+ * Fill in aead givencrypt job descriptor
+ */
+static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
+ struct aead_edesc *edesc,
+ struct aead_request *req,
+ int contig)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
+ int authsize = ctx->authsize;
+ u32 *desc = edesc->hw_desc;
+ u32 out_options = 0, in_options;
+ dma_addr_t dst_dma, src_dma;
+ int len, link_tbl_index = 0;
- set_jump_tgt_here(desc, jump_cmd);
+#ifdef DEBUG
+ debug("assoclen %d cryptlen %d authsize %d\n",
+ req->assoclen, req->cryptlen, authsize);
+ print_hex_dump(KERN_ERR, "assoc @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+ req->assoclen , 1);
+ print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->iv, ivsize, 1);
+ print_hex_dump(KERN_ERR, "src @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ edesc->src_nents > 1 ? 100 : req->cryptlen, 1);
+ print_hex_dump(KERN_ERR, "shrdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sh_desc,
+ desc_bytes(sh_desc), 1);
+#endif
- /* start class 1 (cipher) operation, shared version */
- append_operation(desc, ctx->class1_alg_type |
- OP_ALG_AS_INITFINAL | OP_ALG_AAI_DK);
- set_jump_tgt_here(desc, uncond_jump_cmd);
- } else
- append_operation(desc, ctx->class1_alg_type |
- OP_ALG_AS_INITFINAL | encrypt);
+ len = desc_len(sh_desc);
+ init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
- /* load payload & instruct to class2 to snoop class 1 if encrypting */
- options = 0;
- if (!edesc->src_nents) {
- src_dma = sg_dma_address(areq->src);
+ if (contig & GIV_SRC_CONTIG) {
+ src_dma = sg_dma_address(req->assoc);
+ in_options = 0;
} else {
- sg_to_link_tbl(areq->src, edesc->src_nents, edesc->link_tbl +
- edesc->assoc_nents, 0);
- src_dma = edesc->link_tbl_dma + edesc->assoc_nents *
- sizeof(struct link_tbl_entry);
- options |= LDST_SGF;
+ src_dma = edesc->link_tbl_dma;
+ link_tbl_index += edesc->assoc_nents + 1 + edesc->src_nents;
+ in_options = LDST_SGF;
}
- append_seq_in_ptr(desc, src_dma, areq->cryptlen + authsize, options);
- append_seq_fifo_load(desc, areq->cryptlen, FIFOLD_CLASS_BOTH |
- FIFOLD_TYPE_LASTBOTH |
- (encrypt ? FIFOLD_TYPE_MSG1OUT2
- : FIFOLD_TYPE_MSG));
-
- /* specify destination */
- if (areq->src == areq->dst) {
- dst_dma = src_dma;
+ append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
+ req->cryptlen - authsize, in_options);
+
+ if (contig & GIV_DST_CONTIG) {
+ dst_dma = edesc->iv_dma;
} else {
- sg_count = dma_map_sg(jrdev, areq->dst, edesc->dst_nents ? : 1,
- DMA_FROM_DEVICE);
- if (!edesc->dst_nents) {
- dst_dma = sg_dma_address(areq->dst);
- options = 0;
+ if (likely(req->src == req->dst)) {
+ dst_dma = src_dma + sizeof(struct link_tbl_entry) *
+ edesc->assoc_nents;
+ out_options = LDST_SGF;
} else {
- sg_to_link_tbl(areq->dst, edesc->dst_nents,
- edesc->link_tbl + edesc->assoc_nents +
- edesc->src_nents, 0);
- dst_dma = edesc->link_tbl_dma + (edesc->assoc_nents +
- edesc->src_nents) *
+ dst_dma = edesc->link_tbl_dma +
+ link_tbl_index *
sizeof(struct link_tbl_entry);
- options = LDST_SGF;
+ out_options = LDST_SGF;
}
}
- append_seq_out_ptr(desc, dst_dma, areq->cryptlen + authsize, options);
- append_seq_fifo_store(desc, areq->cryptlen, FIFOST_TYPE_MESSAGE_DATA);
- /* ICV */
- if (encrypt)
- append_seq_store(desc, authsize, LDST_CLASS_2_CCB |
- LDST_SRCDST_BYTE_CONTEXT);
- else
- append_seq_fifo_load(desc, authsize, FIFOLD_CLASS_CLASS2 |
- FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+ append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen, out_options);
+}
+
+/*
+ * Fill in ablkcipher job descriptor
+ */
+static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
+ struct ablkcipher_edesc *edesc,
+ struct ablkcipher_request *req,
+ bool iv_contig)
+{
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+ u32 *desc = edesc->hw_desc;
+ u32 out_options = 0, in_options;
+ dma_addr_t dst_dma, src_dma;
+ int len, link_tbl_index = 0;
#ifdef DEBUG
- debug("job_desc_len %d\n", desc_len(desc));
- print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc) , 1);
- print_hex_dump(KERN_ERR, "jdlinkt@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, edesc->link_tbl,
- edesc->link_tbl_bytes, 1);
+ print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->info,
+ ivsize, 1);
+ print_hex_dump(KERN_ERR, "src @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ edesc->src_nents ? 100 : req->nbytes, 1);
#endif
- ret = caam_jr_enqueue(jrdev, desc, callback, areq);
- if (!ret)
- ret = -EINPROGRESS;
- else {
- ipsec_esp_unmap(jrdev, edesc, areq);
- kfree(edesc);
+ len = desc_len(sh_desc);
+ init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+ if (iv_contig) {
+ src_dma = edesc->iv_dma;
+ in_options = 0;
+ } else {
+ src_dma = edesc->link_tbl_dma;
+ link_tbl_index += (iv_contig ? 0 : 1) + edesc->src_nents;
+ in_options = LDST_SGF;
}
+ append_seq_in_ptr(desc, src_dma, req->nbytes + ivsize, in_options);
- return ret;
+ if (likely(req->src == req->dst)) {
+ if (!edesc->src_nents && iv_contig) {
+ dst_dma = sg_dma_address(req->src);
+ } else {
+ dst_dma = edesc->link_tbl_dma +
+ sizeof(struct link_tbl_entry);
+ out_options = LDST_SGF;
+ }
+ } else {
+ if (!edesc->dst_nents) {
+ dst_dma = sg_dma_address(req->dst);
+ } else {
+ dst_dma = edesc->link_tbl_dma +
+ link_tbl_index * sizeof(struct link_tbl_entry);
+ out_options = LDST_SGF;
+ }
+ }
+ append_seq_out_ptr(desc, dst_dma, req->nbytes, out_options);
}
/*
* derive number of elements in scatterlist
*/
-static int sg_count(struct scatterlist *sg_list, int nbytes, int *chained)
+static int sg_count(struct scatterlist *sg_list, int nbytes)
{
struct scatterlist *sg = sg_list;
int sg_nents = 0;
- *chained = 0;
while (nbytes > 0) {
sg_nents++;
nbytes -= sg->length;
if (!sg_is_last(sg) && (sg + 1)->length == 0)
- *chained = 1;
+ BUG(); /* Not support chaining */
sg = scatterwalk_sg_next(sg);
}
+ if (likely(sg_nents == 1))
+ return 0;
+
return sg_nents;
}
/*
- * allocate and map the ipsec_esp extended descriptor
+ * allocate and map the aead extended descriptor
*/
-static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
- int desc_bytes)
+static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
+ int desc_bytes, bool *all_contig_ptr)
{
- struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
struct device *jrdev = ctx->jrdev;
- gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
- GFP_ATOMIC;
- int assoc_nents, src_nents, dst_nents = 0, chained, link_tbl_bytes;
- struct ipsec_esp_edesc *edesc;
-
- assoc_nents = sg_count(areq->assoc, areq->assoclen, &chained);
- BUG_ON(chained);
- if (likely(assoc_nents == 1))
- assoc_nents = 0;
-
- src_nents = sg_count(areq->src, areq->cryptlen + ctx->authsize,
- &chained);
- BUG_ON(chained);
- if (src_nents == 1)
- src_nents = 0;
-
- if (unlikely(areq->dst != areq->src)) {
- dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize,
- &chained);
- BUG_ON(chained);
- if (dst_nents == 1)
- dst_nents = 0;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ int assoc_nents, src_nents, dst_nents = 0;
+ struct aead_edesc *edesc;
+ dma_addr_t iv_dma = 0;
+ int sgc;
+ bool all_contig = true;
+ int ivsize = crypto_aead_ivsize(aead);
+ int link_tbl_index, link_tbl_len = 0, link_tbl_bytes;
+
+ assoc_nents = sg_count(req->assoc, req->assoclen);
+ src_nents = sg_count(req->src, req->cryptlen);
+
+ if (unlikely(req->dst != req->src))
+ dst_nents = sg_count(req->dst, req->cryptlen);
+
+ sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1,
+ DMA_BIDIRECTIONAL);
+ if (likely(req->src == req->dst)) {
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL);
+ } else {
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE);
+ sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE);
}
- link_tbl_bytes = (assoc_nents + src_nents + dst_nents) *
- sizeof(struct link_tbl_entry);
- debug("link_tbl_bytes %d\n", link_tbl_bytes);
+ /* Check if data are contiguous */
+ iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
+ if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
+ iv_dma || src_nents || iv_dma + ivsize !=
+ sg_dma_address(req->src)) {
+ all_contig = false;
+ assoc_nents = assoc_nents ? : 1;
+ src_nents = src_nents ? : 1;
+ link_tbl_len = assoc_nents + 1 + src_nents;
+ }
+ link_tbl_len += dst_nents;
+
+ link_tbl_bytes = link_tbl_len * sizeof(struct link_tbl_entry);
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct ipsec_esp_edesc) + desc_bytes +
+ edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
link_tbl_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
@@ -753,142 +1354,450 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
edesc->assoc_nents = assoc_nents;
edesc->src_nents = src_nents;
edesc->dst_nents = dst_nents;
- edesc->link_tbl = (void *)edesc + sizeof(struct ipsec_esp_edesc) +
+ edesc->iv_dma = iv_dma;
+ edesc->link_tbl_bytes = link_tbl_bytes;
+ edesc->link_tbl = (void *)edesc + sizeof(struct aead_edesc) +
desc_bytes;
edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
link_tbl_bytes, DMA_TO_DEVICE);
- edesc->link_tbl_bytes = link_tbl_bytes;
+ *all_contig_ptr = all_contig;
+
+ link_tbl_index = 0;
+ if (!all_contig) {
+ sg_to_link_tbl(req->assoc,
+ (assoc_nents ? : 1),
+ edesc->link_tbl +
+ link_tbl_index, 0);
+ link_tbl_index += assoc_nents ? : 1;
+ sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+ iv_dma, ivsize, 0);
+ link_tbl_index += 1;
+ sg_to_link_tbl_last(req->src,
+ (src_nents ? : 1),
+ edesc->link_tbl +
+ link_tbl_index, 0);
+ link_tbl_index += src_nents ? : 1;
+ }
+ if (dst_nents) {
+ sg_to_link_tbl_last(req->dst, dst_nents,
+ edesc->link_tbl + link_tbl_index, 0);
+ }
return edesc;
}
-static int aead_authenc_encrypt(struct aead_request *areq)
+static int aead_encrypt(struct aead_request *req)
{
- struct ipsec_esp_edesc *edesc;
- struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
struct device *jrdev = ctx->jrdev;
- int ivsize = crypto_aead_ivsize(aead);
+ bool all_contig;
u32 *desc;
- dma_addr_t iv_dma;
+ int ret = 0;
+
+ req->cryptlen += ctx->authsize;
/* allocate extended descriptor */
- edesc = ipsec_esp_edesc_alloc(areq, DESC_AEAD_ENCRYPT_TEXT_LEN *
- CAAM_CMD_SZ);
+ edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
+ CAAM_CMD_SZ, &all_contig);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
- desc = edesc->hw_desc;
-
- /* insert shared descriptor pointer */
- init_job_desc_shared(desc, ctx->shared_desc_phys,
- desc_len(ctx->sh_desc), HDR_SHARE_DEFER);
-
- iv_dma = dma_map_single(jrdev, areq->iv, ivsize, DMA_TO_DEVICE);
- /* check dma error */
+ /* Create and submit job descriptor */
+ init_aead_job(ctx->sh_desc_enc, ctx->sh_desc_enc_dma, edesc, req,
+ all_contig, true);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+ desc_bytes(edesc->hw_desc), 1);
+#endif
- append_load(desc, iv_dma, ivsize,
- LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT);
+ desc = edesc->hw_desc;
+ ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
- return ipsec_esp(edesc, areq, OP_ALG_ENCRYPT, ipsec_esp_encrypt_done);
+ return ret;
}
-static int aead_authenc_decrypt(struct aead_request *req)
+static int aead_decrypt(struct aead_request *req)
{
+ struct aead_edesc *edesc;
struct crypto_aead *aead = crypto_aead_reqtfm(req);
- int ivsize = crypto_aead_ivsize(aead);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
struct device *jrdev = ctx->jrdev;
- struct ipsec_esp_edesc *edesc;
+ bool all_contig;
u32 *desc;
- dma_addr_t iv_dma;
-
- req->cryptlen -= ctx->authsize;
+ int ret = 0;
/* allocate extended descriptor */
- edesc = ipsec_esp_edesc_alloc(req, DESC_AEAD_DECRYPT_TEXT_LEN *
- CAAM_CMD_SZ);
+ edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
+ CAAM_CMD_SZ, &all_contig);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "dec src@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ req->cryptlen, 1);
+#endif
+
+ /* Create and submit job descriptor*/
+ init_aead_job(ctx->sh_desc_dec,
+ ctx->sh_desc_dec_dma, edesc, req, all_contig, false);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+ desc_bytes(edesc->hw_desc), 1);
+#endif
+
desc = edesc->hw_desc;
+ ret = caam_jr_enqueue(jrdev, desc, aead_decrypt_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
- /* insert shared descriptor pointer */
- init_job_desc_shared(desc, ctx->shared_desc_phys,
- desc_len(ctx->sh_desc), HDR_SHARE_DEFER);
+ return ret;
+}
- iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
- /* check dma error */
+/*
+ * allocate and map the aead extended descriptor for aead givencrypt
+ */
+static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
+ *greq, int desc_bytes,
+ u32 *contig_ptr)
+{
+ struct aead_request *req = &greq->areq;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ int assoc_nents, src_nents, dst_nents = 0;
+ struct aead_edesc *edesc;
+ dma_addr_t iv_dma = 0;
+ int sgc;
+ u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG;
+ int ivsize = crypto_aead_ivsize(aead);
+ int link_tbl_index, link_tbl_len = 0, link_tbl_bytes;
+
+ assoc_nents = sg_count(req->assoc, req->assoclen);
+ src_nents = sg_count(req->src, req->cryptlen);
- append_load(desc, iv_dma, ivsize,
- LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT);
+ if (unlikely(req->dst != req->src))
+ dst_nents = sg_count(req->dst, req->cryptlen);
- return ipsec_esp(edesc, req, !OP_ALG_ENCRYPT, ipsec_esp_decrypt_done);
+ sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1,
+ DMA_BIDIRECTIONAL);
+ if (likely(req->src == req->dst)) {
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL);
+ } else {
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE);
+ sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE);
+ }
+
+ /* Check if data are contiguous */
+ iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE);
+ if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
+ iv_dma || src_nents || iv_dma + ivsize != sg_dma_address(req->src))
+ contig &= ~GIV_SRC_CONTIG;
+ if (dst_nents || iv_dma + ivsize != sg_dma_address(req->dst))
+ contig &= ~GIV_DST_CONTIG;
+ if (unlikely(req->src != req->dst)) {
+ dst_nents = dst_nents ? : 1;
+ link_tbl_len += 1;
+ }
+ if (!(contig & GIV_SRC_CONTIG)) {
+ assoc_nents = assoc_nents ? : 1;
+ src_nents = src_nents ? : 1;
+ link_tbl_len += assoc_nents + 1 + src_nents;
+ if (likely(req->src == req->dst))
+ contig &= ~GIV_DST_CONTIG;
+ }
+ link_tbl_len += dst_nents;
+
+ link_tbl_bytes = link_tbl_len * sizeof(struct link_tbl_entry);
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
+ link_tbl_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev, "could not allocate extended descriptor\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ edesc->assoc_nents = assoc_nents;
+ edesc->src_nents = src_nents;
+ edesc->dst_nents = dst_nents;
+ edesc->iv_dma = iv_dma;
+ edesc->link_tbl_bytes = link_tbl_bytes;
+ edesc->link_tbl = (void *)edesc + sizeof(struct aead_edesc) +
+ desc_bytes;
+ edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
+ link_tbl_bytes, DMA_TO_DEVICE);
+ *contig_ptr = contig;
+
+ link_tbl_index = 0;
+ if (!(contig & GIV_SRC_CONTIG)) {
+ sg_to_link_tbl(req->assoc, assoc_nents,
+ edesc->link_tbl +
+ link_tbl_index, 0);
+ link_tbl_index += assoc_nents;
+ sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+ iv_dma, ivsize, 0);
+ link_tbl_index += 1;
+ sg_to_link_tbl_last(req->src, src_nents,
+ edesc->link_tbl +
+ link_tbl_index, 0);
+ link_tbl_index += src_nents;
+ }
+ if (unlikely(req->src != req->dst && !(contig & GIV_DST_CONTIG))) {
+ sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+ iv_dma, ivsize, 0);
+ link_tbl_index += 1;
+ sg_to_link_tbl_last(req->dst, dst_nents,
+ edesc->link_tbl + link_tbl_index, 0);
+ }
+
+ return edesc;
}
-static int aead_authenc_givencrypt(struct aead_givcrypt_request *req)
+static int aead_givencrypt(struct aead_givcrypt_request *areq)
{
- struct aead_request *areq = &req->areq;
- struct ipsec_esp_edesc *edesc;
- struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+ struct aead_request *req = &areq->areq;
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
struct device *jrdev = ctx->jrdev;
- int ivsize = crypto_aead_ivsize(aead);
- dma_addr_t iv_dma;
+ u32 contig;
u32 *desc;
+ int ret = 0;
- iv_dma = dma_map_single(jrdev, req->giv, ivsize, DMA_FROM_DEVICE);
-
- debug("%s: giv %p\n", __func__, req->giv);
+ req->cryptlen += ctx->authsize;
/* allocate extended descriptor */
- edesc = ipsec_esp_edesc_alloc(areq, DESC_AEAD_GIVENCRYPT_TEXT_LEN *
- CAAM_CMD_SZ);
+ edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN *
+ CAAM_CMD_SZ, &contig);
+
if (IS_ERR(edesc))
return PTR_ERR(edesc);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "giv src@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ req->cryptlen, 1);
+#endif
+
+ /* Create and submit job descriptor*/
+ init_aead_giv_job(ctx->sh_desc_givenc,
+ ctx->sh_desc_givenc_dma, edesc, req, contig);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+ desc_bytes(edesc->hw_desc), 1);
+#endif
+
desc = edesc->hw_desc;
+ ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
- /* insert shared descriptor pointer */
- init_job_desc_shared(desc, ctx->shared_desc_phys,
- desc_len(ctx->sh_desc), HDR_SHARE_DEFER);
+ return ret;
+}
- /*
- * LOAD IMM Info FIFO
- * to DECO, Last, Padding, Random, Message, 16 bytes
- */
- append_load_imm_u32(desc, NFIFOENTRY_DEST_DECO | NFIFOENTRY_LC1 |
- NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DTYPE_MSG |
- NFIFOENTRY_PTYPE_RND | ivsize,
- LDST_SRCDST_WORD_INFO_FIFO);
+/*
+ * allocate and map the ablkcipher extended descriptor for ablkcipher
+ */
+static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
+ *req, int desc_bytes,
+ bool *iv_contig_out)
+{
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ?
+ GFP_KERNEL : GFP_ATOMIC;
+ int src_nents, dst_nents = 0, link_tbl_bytes;
+ struct ablkcipher_edesc *edesc;
+ dma_addr_t iv_dma = 0;
+ bool iv_contig = false;
+ int sgc;
+ int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+ int link_tbl_index;
+
+ src_nents = sg_count(req->src, req->nbytes);
+
+ if (unlikely(req->dst != req->src))
+ dst_nents = sg_count(req->dst, req->nbytes);
+
+ if (likely(req->src == req->dst)) {
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL);
+ } else {
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE);
+ sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE);
+ }
/*
- * disable info fifo entries since the above serves as the entry
- * this way, the MOVE command won't generate an entry.
- * Note that this isn't required in more recent versions of
- * SEC as a MOVE that doesn't do info FIFO entries is available.
+ * Check if iv can be contiguous with source and destination.
+ * If so, include it. If not, create scatterlist.
*/
- append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+ iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
+ if (!src_nents && iv_dma + ivsize == sg_dma_address(req->src))
+ iv_contig = true;
+ else
+ src_nents = src_nents ? : 1;
+ link_tbl_bytes = ((iv_contig ? 0 : 1) + src_nents + dst_nents) *
+ sizeof(struct link_tbl_entry);
- /* MOVE DECO Alignment -> C1 Context 16 bytes */
- append_move(desc, MOVE_SRC_INFIFO | MOVE_DEST_CLASS1CTX | ivsize);
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kmalloc(sizeof(struct ablkcipher_edesc) + desc_bytes +
+ link_tbl_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev, "could not allocate extended descriptor\n");
+ return ERR_PTR(-ENOMEM);
+ }
- /* re-enable info fifo entries */
- append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+ edesc->src_nents = src_nents;
+ edesc->dst_nents = dst_nents;
+ edesc->link_tbl_bytes = link_tbl_bytes;
+ edesc->link_tbl = (void *)edesc + sizeof(struct ablkcipher_edesc) +
+ desc_bytes;
+
+ link_tbl_index = 0;
+ if (!iv_contig) {
+ sg_to_link_tbl_one(edesc->link_tbl, iv_dma, ivsize, 0);
+ sg_to_link_tbl_last(req->src, src_nents,
+ edesc->link_tbl + 1, 0);
+ link_tbl_index += 1 + src_nents;
+ }
+
+ if (unlikely(dst_nents)) {
+ sg_to_link_tbl_last(req->dst, dst_nents,
+ edesc->link_tbl + link_tbl_index, 0);
+ }
+
+ edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
+ link_tbl_bytes, DMA_TO_DEVICE);
+ edesc->iv_dma = iv_dma;
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ablkcipher link_tbl@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->link_tbl,
+ link_tbl_bytes, 1);
+#endif
+
+ *iv_contig_out = iv_contig;
+ return edesc;
+}
+
+static int ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+ struct ablkcipher_edesc *edesc;
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+ struct device *jrdev = ctx->jrdev;
+ bool iv_contig;
+ u32 *desc;
+ int ret = 0;
+
+ /* allocate extended descriptor */
+ edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
+ CAAM_CMD_SZ, &iv_contig);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
- /* MOVE C1 Context -> OFIFO 16 bytes */
- append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_OUTFIFO | ivsize);
+ /* Create and submit job descriptor*/
+ init_ablkcipher_job(ctx->sh_desc_enc,
+ ctx->sh_desc_enc_dma, edesc, req, iv_contig);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+ desc_bytes(edesc->hw_desc), 1);
+#endif
+ desc = edesc->hw_desc;
+ ret = caam_jr_enqueue(jrdev, desc, ablkcipher_encrypt_done, req);
- append_fifo_store(desc, iv_dma, ivsize, FIFOST_TYPE_MESSAGE_DATA);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ablkcipher_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
- return ipsec_esp(edesc, areq, OP_ALG_ENCRYPT, ipsec_esp_encrypt_done);
+ return ret;
}
+static int ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+ struct ablkcipher_edesc *edesc;
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+ struct device *jrdev = ctx->jrdev;
+ bool iv_contig;
+ u32 *desc;
+ int ret = 0;
+
+ /* allocate extended descriptor */
+ edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
+ CAAM_CMD_SZ, &iv_contig);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Create and submit job descriptor*/
+ init_ablkcipher_job(ctx->sh_desc_dec,
+ ctx->sh_desc_dec_dma, edesc, req, iv_contig);
+ desc = edesc->hw_desc;
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+ desc_bytes(edesc->hw_desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ablkcipher_decrypt_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ablkcipher_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+#define template_aead template_u.aead
+#define template_ablkcipher template_u.ablkcipher
struct caam_alg_template {
char name[CRYPTO_MAX_ALG_NAME];
char driver_name[CRYPTO_MAX_ALG_NAME];
unsigned int blocksize;
- struct aead_alg aead;
+ u32 type;
+ union {
+ struct ablkcipher_alg ablkcipher;
+ struct aead_alg aead;
+ struct blkcipher_alg blkcipher;
+ struct cipher_alg cipher;
+ struct compress_alg compress;
+ struct rng_alg rng;
+ } template_u;
u32 class1_alg_type;
u32 class2_alg_type;
u32 alg_op;
@@ -900,12 +1809,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha1),cbc(aes))",
.driver_name = "authenc-hmac-sha1-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = AES_BLOCK_SIZE,
.maxauthsize = SHA1_DIGEST_SIZE,
@@ -918,12 +1828,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha256),cbc(aes))",
.driver_name = "authenc-hmac-sha256-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = AES_BLOCK_SIZE,
.maxauthsize = SHA256_DIGEST_SIZE,
@@ -937,12 +1848,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha512),cbc(aes))",
.driver_name = "authenc-hmac-sha512-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = AES_BLOCK_SIZE,
.maxauthsize = SHA512_DIGEST_SIZE,
@@ -956,12 +1868,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha1),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = DES3_EDE_BLOCK_SIZE,
.maxauthsize = SHA1_DIGEST_SIZE,
@@ -974,12 +1887,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha256),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = DES3_EDE_BLOCK_SIZE,
.maxauthsize = SHA256_DIGEST_SIZE,
@@ -993,12 +1907,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha512),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = DES3_EDE_BLOCK_SIZE,
.maxauthsize = SHA512_DIGEST_SIZE,
@@ -1012,12 +1927,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha1),cbc(des))",
.driver_name = "authenc-hmac-sha1-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = DES_BLOCK_SIZE,
.maxauthsize = SHA1_DIGEST_SIZE,
@@ -1030,12 +1946,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha256),cbc(des))",
.driver_name = "authenc-hmac-sha256-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = DES_BLOCK_SIZE,
.maxauthsize = SHA256_DIGEST_SIZE,
@@ -1049,12 +1966,13 @@ static struct caam_alg_template driver_algs[] = {
.name = "authenc(hmac(sha512),cbc(des))",
.driver_name = "authenc-hmac-sha512-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
.geniv = "<built-in>",
.ivsize = DES_BLOCK_SIZE,
.maxauthsize = SHA512_DIGEST_SIZE,
@@ -1064,6 +1982,55 @@ static struct caam_alg_template driver_algs[] = {
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
},
+ /* ablkcipher descriptor */
+ {
+ .name = "cbc(aes)",
+ .driver_name = "cbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ },
+ {
+ .name = "cbc(des3_ede)",
+ .driver_name = "cbc-3des-caam",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ },
+ {
+ .name = "cbc(des)",
+ .driver_name = "cbc-des-caam",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ }
};
struct caam_crypto_alg {
@@ -1102,16 +2069,19 @@ static void caam_cra_exit(struct crypto_tfm *tfm)
{
struct caam_ctx *ctx = crypto_tfm_ctx(tfm);
- if (!dma_mapping_error(ctx->jrdev, ctx->shared_desc_phys))
- dma_unmap_single(ctx->jrdev, ctx->shared_desc_phys,
- desc_bytes(ctx->sh_desc), DMA_TO_DEVICE);
- kfree(ctx->sh_desc);
-
- if (!dma_mapping_error(ctx->jrdev, ctx->key_phys))
- dma_unmap_single(ctx->jrdev, ctx->key_phys,
- ctx->split_key_pad_len + ctx->enckeylen,
+ if (ctx->sh_desc_enc_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_enc_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_enc_dma,
+ desc_bytes(ctx->sh_desc_enc), DMA_TO_DEVICE);
+ if (ctx->sh_desc_dec_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_dec_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_dec_dma,
+ desc_bytes(ctx->sh_desc_dec), DMA_TO_DEVICE);
+ if (ctx->sh_desc_givenc_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_givenc_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_givenc_dma,
+ desc_bytes(ctx->sh_desc_givenc),
DMA_TO_DEVICE);
- kfree(ctx->key);
}
static void __exit caam_algapi_exit(void)
@@ -1175,12 +2145,20 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
alg->cra_init = caam_cra_init;
alg->cra_exit = caam_cra_exit;
alg->cra_priority = CAAM_CRA_PRIORITY;
- alg->cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
alg->cra_blocksize = template->blocksize;
alg->cra_alignmask = 0;
- alg->cra_type = &crypto_aead_type;
alg->cra_ctxsize = sizeof(struct caam_ctx);
- alg->cra_u.aead = template->aead;
+ alg->cra_flags = CRYPTO_ALG_ASYNC | template->type;
+ switch (template->type) {
+ case CRYPTO_ALG_TYPE_ABLKCIPHER:
+ alg->cra_type = &crypto_ablkcipher_type;
+ alg->cra_ablkcipher = template->template_ablkcipher;
+ break;
+ case CRYPTO_ALG_TYPE_AEAD:
+ alg->cra_type = &crypto_aead_type;
+ alg->cra_aead = template->template_aead;
+ break;
+ }
t_alg->class1_alg_type = template->class1_alg_type;
t_alg->class2_alg_type = template->class2_alg_type;
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index 950450346f70..d38f2afaa966 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -31,5 +31,6 @@
#include <crypto/aead.h>
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
+#include <crypto/internal/skcipher.h>
#endif /* !defined(CAAM_COMPAT_H) */
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 9009713a3c2e..73988bb7322a 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -52,9 +52,11 @@ static int caam_probe(struct platform_device *pdev)
struct caam_ctrl __iomem *ctrl;
struct caam_full __iomem *topregs;
struct caam_drv_private *ctrlpriv;
- struct caam_perfmon *perfmon;
struct caam_deco **deco;
u32 deconum;
+#ifdef CONFIG_DEBUG_FS
+ struct caam_perfmon *perfmon;
+#endif
ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL);
if (!ctrlpriv)
@@ -164,52 +166,52 @@ static int caam_probe(struct platform_device *pdev)
/* Controller-level - performance monitor counters */
ctrlpriv->ctl_rq_dequeued =
debugfs_create_u64("rq_dequeued",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->req_dequeued);
ctrlpriv->ctl_ob_enc_req =
debugfs_create_u64("ob_rq_encrypted",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->ob_enc_req);
ctrlpriv->ctl_ib_dec_req =
debugfs_create_u64("ib_rq_decrypted",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->ib_dec_req);
ctrlpriv->ctl_ob_enc_bytes =
debugfs_create_u64("ob_bytes_encrypted",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->ob_enc_bytes);
ctrlpriv->ctl_ob_prot_bytes =
debugfs_create_u64("ob_bytes_protected",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->ob_prot_bytes);
ctrlpriv->ctl_ib_dec_bytes =
debugfs_create_u64("ib_bytes_decrypted",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->ib_dec_bytes);
ctrlpriv->ctl_ib_valid_bytes =
debugfs_create_u64("ib_bytes_validated",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->ib_valid_bytes);
/* Controller level - global status values */
ctrlpriv->ctl_faultaddr =
debugfs_create_u64("fault_addr",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->faultaddr);
ctrlpriv->ctl_faultdetail =
debugfs_create_u32("fault_detail",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->faultdetail);
ctrlpriv->ctl_faultstatus =
debugfs_create_u32("fault_status",
- S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+ S_IRUSR | S_IRGRP | S_IROTH,
ctrlpriv->ctl, &perfmon->status);
/* Internal covering keys (useful in non-secure mode only) */
ctrlpriv->ctl_kek_wrap.data = &ctrlpriv->ctrl->kek[0];
ctrlpriv->ctl_kek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
ctrlpriv->ctl_kek = debugfs_create_blob("kek",
- S_IFCHR | S_IRUSR |
+ S_IRUSR |
S_IRGRP | S_IROTH,
ctrlpriv->ctl,
&ctrlpriv->ctl_kek_wrap);
@@ -217,7 +219,7 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->ctl_tkek_wrap.data = &ctrlpriv->ctrl->tkek[0];
ctrlpriv->ctl_tkek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
ctrlpriv->ctl_tkek = debugfs_create_blob("tkek",
- S_IFCHR | S_IRUSR |
+ S_IRUSR |
S_IRGRP | S_IROTH,
ctrlpriv->ctl,
&ctrlpriv->ctl_tkek_wrap);
@@ -225,7 +227,7 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->ctl_tdsk_wrap.data = &ctrlpriv->ctrl->tdsk[0];
ctrlpriv->ctl_tdsk_wrap.size = KEK_KEY_SIZE * sizeof(u32);
ctrlpriv->ctl_tdsk = debugfs_create_blob("tdsk",
- S_IFCHR | S_IRUSR |
+ S_IRUSR |
S_IRGRP | S_IROTH,
ctrlpriv->ctl,
&ctrlpriv->ctl_tdsk_wrap);
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index 46915800c26f..0991323cf3fd 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -9,7 +9,7 @@
#define IMMEDIATE (1 << 23)
#define CAAM_CMD_SZ sizeof(u32)
#define CAAM_PTR_SZ sizeof(dma_addr_t)
-#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * 64)
+#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
#ifdef DEBUG
#define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
@@ -18,6 +18,9 @@
#define PRINT_POS
#endif
+#define SET_OK_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
+ LDST_SRCDST_WORD_DECOCTRL | \
+ (LDOFF_CHG_SHARE_OK_PROP << LDST_OFFSET_SHIFT))
#define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
LDST_SRCDST_WORD_DECOCTRL | \
(LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
@@ -203,3 +206,56 @@ static inline void append_##cmd##_imm_##type(u32 *desc, type immediate, \
append_cmd(desc, immediate); \
}
APPEND_CMD_RAW_IMM(load, LOAD, u32);
+
+/*
+ * Append math command. Only the last part of destination and source need to
+ * be specified
+ */
+#define APPEND_MATH(op, desc, dest, src_0, src_1, len) \
+append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
+ MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32) (len & MATH_LEN_MASK));
+
+#define append_math_add(desc, dest, src0, src1, len) \
+ APPEND_MATH(ADD, desc, dest, src0, src1, len)
+#define append_math_sub(desc, dest, src0, src1, len) \
+ APPEND_MATH(SUB, desc, dest, src0, src1, len)
+#define append_math_add_c(desc, dest, src0, src1, len) \
+ APPEND_MATH(ADDC, desc, dest, src0, src1, len)
+#define append_math_sub_b(desc, dest, src0, src1, len) \
+ APPEND_MATH(SUBB, desc, dest, src0, src1, len)
+#define append_math_and(desc, dest, src0, src1, len) \
+ APPEND_MATH(AND, desc, dest, src0, src1, len)
+#define append_math_or(desc, dest, src0, src1, len) \
+ APPEND_MATH(OR, desc, dest, src0, src1, len)
+#define append_math_xor(desc, dest, src0, src1, len) \
+ APPEND_MATH(XOR, desc, dest, src0, src1, len)
+#define append_math_lshift(desc, dest, src0, src1, len) \
+ APPEND_MATH(LSHIFT, desc, dest, src0, src1, len)
+#define append_math_rshift(desc, dest, src0, src1, len) \
+ APPEND_MATH(RSHIFT, desc, dest, src0, src1, len)
+
+/* Exactly one source is IMM. Data is passed in as u32 value */
+#define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \
+do { \
+ APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \
+ append_cmd(desc, data); \
+} while (0);
+
+#define append_math_add_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data)
+#define append_math_sub_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data)
+#define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data)
+#define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data)
+#define append_math_and_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data)
+#define append_math_or_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data)
+#define append_math_xor_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data)
+#define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data)
+#define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \
+ APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data)
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index ba8f1ea84c5e..6399a8f1938a 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -72,17 +72,20 @@
#define DEFAULT_TIMEOUT_INTERVAL HZ
-#define FLAGS_FINUP 0x0002
-#define FLAGS_FINAL 0x0004
-#define FLAGS_SG 0x0008
-#define FLAGS_SHA1 0x0010
-#define FLAGS_DMA_ACTIVE 0x0020
-#define FLAGS_OUTPUT_READY 0x0040
-#define FLAGS_INIT 0x0100
-#define FLAGS_CPU 0x0200
-#define FLAGS_HMAC 0x0400
-#define FLAGS_ERROR 0x0800
-#define FLAGS_BUSY 0x1000
+/* mostly device flags */
+#define FLAGS_BUSY 0
+#define FLAGS_FINAL 1
+#define FLAGS_DMA_ACTIVE 2
+#define FLAGS_OUTPUT_READY 3
+#define FLAGS_INIT 4
+#define FLAGS_CPU 5
+#define FLAGS_DMA_READY 6
+/* context flags */
+#define FLAGS_FINUP 16
+#define FLAGS_SG 17
+#define FLAGS_SHA1 18
+#define FLAGS_HMAC 19
+#define FLAGS_ERROR 20
#define OP_UPDATE 1
#define OP_FINAL 2
@@ -144,7 +147,6 @@ struct omap_sham_dev {
int dma;
int dma_lch;
struct tasklet_struct done_task;
- struct tasklet_struct queue_task;
unsigned long flags;
struct crypto_queue queue;
@@ -223,7 +225,7 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
if (!hash)
return;
- if (likely(ctx->flags & FLAGS_SHA1)) {
+ if (likely(ctx->flags & BIT(FLAGS_SHA1))) {
/* SHA1 results are in big endian */
for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
hash[i] = be32_to_cpu(in[i]);
@@ -238,7 +240,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
{
clk_enable(dd->iclk);
- if (!(dd->flags & FLAGS_INIT)) {
+ if (!test_bit(FLAGS_INIT, &dd->flags)) {
omap_sham_write_mask(dd, SHA_REG_MASK,
SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
@@ -246,7 +248,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
SHA_REG_SYSSTATUS_RESETDONE))
return -ETIMEDOUT;
- dd->flags |= FLAGS_INIT;
+ set_bit(FLAGS_INIT, &dd->flags);
dd->err = 0;
}
@@ -269,7 +271,7 @@ static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
* Setting ALGO_CONST only for the first iteration
* and CLOSE_HASH only for the last one.
*/
- if (ctx->flags & FLAGS_SHA1)
+ if (ctx->flags & BIT(FLAGS_SHA1))
val |= SHA_REG_CTRL_ALGO;
if (!ctx->digcnt)
val |= SHA_REG_CTRL_ALGO_CONST;
@@ -301,7 +303,9 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
return -ETIMEDOUT;
if (final)
- ctx->flags |= FLAGS_FINAL; /* catch last interrupt */
+ set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */
+
+ set_bit(FLAGS_CPU, &dd->flags);
len32 = DIV_ROUND_UP(length, sizeof(u32));
@@ -334,9 +338,9 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
ctx->digcnt += length;
if (final)
- ctx->flags |= FLAGS_FINAL; /* catch last interrupt */
+ set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */
- dd->flags |= FLAGS_DMA_ACTIVE;
+ set_bit(FLAGS_DMA_ACTIVE, &dd->flags);
omap_start_dma(dd->dma_lch);
@@ -392,7 +396,7 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
return -EINVAL;
}
- ctx->flags &= ~FLAGS_SG;
+ ctx->flags &= ~BIT(FLAGS_SG);
/* next call does not fail... so no unmap in the case of error */
return omap_sham_xmit_dma(dd, ctx->dma_addr, length, final);
@@ -406,7 +410,7 @@ static int omap_sham_update_dma_slow(struct omap_sham_dev *dd)
omap_sham_append_sg(ctx);
- final = (ctx->flags & FLAGS_FINUP) && !ctx->total;
+ final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: %d, final: %d\n",
ctx->bufcnt, ctx->digcnt, final);
@@ -452,7 +456,7 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
length = min(ctx->total, sg->length);
if (sg_is_last(sg)) {
- if (!(ctx->flags & FLAGS_FINUP)) {
+ if (!(ctx->flags & BIT(FLAGS_FINUP))) {
/* not last sg must be SHA1_MD5_BLOCK_SIZE aligned */
tail = length & (SHA1_MD5_BLOCK_SIZE - 1);
/* without finup() we need one block to close hash */
@@ -467,12 +471,12 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
return -EINVAL;
}
- ctx->flags |= FLAGS_SG;
+ ctx->flags |= BIT(FLAGS_SG);
ctx->total -= length;
ctx->offset = length; /* offset where to start slow */
- final = (ctx->flags & FLAGS_FINUP) && !ctx->total;
+ final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
/* next call does not fail... so no unmap in the case of error */
return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final);
@@ -495,7 +499,7 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
omap_stop_dma(dd->dma_lch);
- if (ctx->flags & FLAGS_SG) {
+ if (ctx->flags & BIT(FLAGS_SG)) {
dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
if (ctx->sg->length == ctx->offset) {
ctx->sg = sg_next(ctx->sg);
@@ -537,18 +541,18 @@ static int omap_sham_init(struct ahash_request *req)
crypto_ahash_digestsize(tfm));
if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE)
- ctx->flags |= FLAGS_SHA1;
+ ctx->flags |= BIT(FLAGS_SHA1);
ctx->bufcnt = 0;
ctx->digcnt = 0;
ctx->buflen = BUFLEN;
- if (tctx->flags & FLAGS_HMAC) {
+ if (tctx->flags & BIT(FLAGS_HMAC)) {
struct omap_sham_hmac_ctx *bctx = tctx->base;
memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
- ctx->flags |= FLAGS_HMAC;
+ ctx->flags |= BIT(FLAGS_HMAC);
}
return 0;
@@ -562,9 +566,9 @@ static int omap_sham_update_req(struct omap_sham_dev *dd)
int err;
dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d\n",
- ctx->total, ctx->digcnt, (ctx->flags & FLAGS_FINUP) != 0);
+ ctx->total, ctx->digcnt, (ctx->flags & BIT(FLAGS_FINUP)) != 0);
- if (ctx->flags & FLAGS_CPU)
+ if (ctx->flags & BIT(FLAGS_CPU))
err = omap_sham_update_cpu(dd);
else
err = omap_sham_update_dma_start(dd);
@@ -624,7 +628,7 @@ static int omap_sham_finish(struct ahash_request *req)
if (ctx->digcnt) {
omap_sham_copy_ready_hash(req);
- if (ctx->flags & FLAGS_HMAC)
+ if (ctx->flags & BIT(FLAGS_HMAC))
err = omap_sham_finish_hmac(req);
}
@@ -639,18 +643,23 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
struct omap_sham_dev *dd = ctx->dd;
if (!err) {
- omap_sham_copy_hash(ctx->dd->req, 1);
- if (ctx->flags & FLAGS_FINAL)
+ omap_sham_copy_hash(req, 1);
+ if (test_bit(FLAGS_FINAL, &dd->flags))
err = omap_sham_finish(req);
} else {
- ctx->flags |= FLAGS_ERROR;
+ ctx->flags |= BIT(FLAGS_ERROR);
}
+ /* atomic operation is not needed here */
+ dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
+ BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
clk_disable(dd->iclk);
- dd->flags &= ~FLAGS_BUSY;
if (req->base.complete)
req->base.complete(&req->base, err);
+
+ /* handle new request */
+ tasklet_schedule(&dd->done_task);
}
static int omap_sham_handle_queue(struct omap_sham_dev *dd,
@@ -658,21 +667,20 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
{
struct crypto_async_request *async_req, *backlog;
struct omap_sham_reqctx *ctx;
- struct ahash_request *prev_req;
unsigned long flags;
int err = 0, ret = 0;
spin_lock_irqsave(&dd->lock, flags);
if (req)
ret = ahash_enqueue_request(&dd->queue, req);
- if (dd->flags & FLAGS_BUSY) {
+ if (test_bit(FLAGS_BUSY, &dd->flags)) {
spin_unlock_irqrestore(&dd->lock, flags);
return ret;
}
backlog = crypto_get_backlog(&dd->queue);
async_req = crypto_dequeue_request(&dd->queue);
if (async_req)
- dd->flags |= FLAGS_BUSY;
+ set_bit(FLAGS_BUSY, &dd->flags);
spin_unlock_irqrestore(&dd->lock, flags);
if (!async_req)
@@ -682,16 +690,12 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
backlog->complete(backlog, -EINPROGRESS);
req = ahash_request_cast(async_req);
-
- prev_req = dd->req;
dd->req = req;
-
ctx = ahash_request_ctx(req);
dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n",
ctx->op, req->nbytes);
-
err = omap_sham_hw_init(dd);
if (err)
goto err1;
@@ -712,18 +716,16 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
if (ctx->op == OP_UPDATE) {
err = omap_sham_update_req(dd);
- if (err != -EINPROGRESS && (ctx->flags & FLAGS_FINUP))
+ if (err != -EINPROGRESS && (ctx->flags & BIT(FLAGS_FINUP)))
/* no final() after finup() */
err = omap_sham_final_req(dd);
} else if (ctx->op == OP_FINAL) {
err = omap_sham_final_req(dd);
}
err1:
- if (err != -EINPROGRESS) {
+ if (err != -EINPROGRESS)
/* done_task will not finish it, so do it here */
omap_sham_finish_req(req, err);
- tasklet_schedule(&dd->queue_task);
- }
dev_dbg(dd->dev, "exit, err: %d\n", err);
@@ -752,7 +754,7 @@ static int omap_sham_update(struct ahash_request *req)
ctx->sg = req->src;
ctx->offset = 0;
- if (ctx->flags & FLAGS_FINUP) {
+ if (ctx->flags & BIT(FLAGS_FINUP)) {
if ((ctx->digcnt + ctx->bufcnt + ctx->total) < 9) {
/*
* OMAP HW accel works only with buffers >= 9
@@ -765,7 +767,7 @@ static int omap_sham_update(struct ahash_request *req)
/*
* faster to use CPU for short transfers
*/
- ctx->flags |= FLAGS_CPU;
+ ctx->flags |= BIT(FLAGS_CPU);
}
} else if (ctx->bufcnt + ctx->total < ctx->buflen) {
omap_sham_append_sg(ctx);
@@ -802,9 +804,9 @@ static int omap_sham_final(struct ahash_request *req)
{
struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
- ctx->flags |= FLAGS_FINUP;
+ ctx->flags |= BIT(FLAGS_FINUP);
- if (ctx->flags & FLAGS_ERROR)
+ if (ctx->flags & BIT(FLAGS_ERROR))
return 0; /* uncompleted hash is not needed */
/* OMAP HW accel works only with buffers >= 9 */
@@ -823,7 +825,7 @@ static int omap_sham_finup(struct ahash_request *req)
struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
int err1, err2;
- ctx->flags |= FLAGS_FINUP;
+ ctx->flags |= BIT(FLAGS_FINUP);
err1 = omap_sham_update(req);
if (err1 == -EINPROGRESS || err1 == -EBUSY)
@@ -895,7 +897,7 @@ static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
if (alg_base) {
struct omap_sham_hmac_ctx *bctx = tctx->base;
- tctx->flags |= FLAGS_HMAC;
+ tctx->flags |= BIT(FLAGS_HMAC);
bctx->shash = crypto_alloc_shash(alg_base, 0,
CRYPTO_ALG_NEED_FALLBACK);
if (IS_ERR(bctx->shash)) {
@@ -932,7 +934,7 @@ static void omap_sham_cra_exit(struct crypto_tfm *tfm)
crypto_free_shash(tctx->fallback);
tctx->fallback = NULL;
- if (tctx->flags & FLAGS_HMAC) {
+ if (tctx->flags & BIT(FLAGS_HMAC)) {
struct omap_sham_hmac_ctx *bctx = tctx->base;
crypto_free_shash(bctx->shash);
}
@@ -1036,51 +1038,46 @@ static struct ahash_alg algs[] = {
static void omap_sham_done_task(unsigned long data)
{
struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
- struct ahash_request *req = dd->req;
- struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
- int ready = 0, err = 0;
+ int err = 0;
- if (ctx->flags & FLAGS_OUTPUT_READY) {
- ctx->flags &= ~FLAGS_OUTPUT_READY;
- ready = 1;
+ if (!test_bit(FLAGS_BUSY, &dd->flags)) {
+ omap_sham_handle_queue(dd, NULL);
+ return;
}
- if (dd->flags & FLAGS_DMA_ACTIVE) {
- dd->flags &= ~FLAGS_DMA_ACTIVE;
- omap_sham_update_dma_stop(dd);
- if (!dd->err)
+ if (test_bit(FLAGS_CPU, &dd->flags)) {
+ if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags))
+ goto finish;
+ } else if (test_bit(FLAGS_DMA_READY, &dd->flags)) {
+ if (test_and_clear_bit(FLAGS_DMA_ACTIVE, &dd->flags)) {
+ omap_sham_update_dma_stop(dd);
+ if (dd->err) {
+ err = dd->err;
+ goto finish;
+ }
+ }
+ if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags)) {
+ /* hash or semi-hash ready */
+ clear_bit(FLAGS_DMA_READY, &dd->flags);
err = omap_sham_update_dma_start(dd);
+ if (err != -EINPROGRESS)
+ goto finish;
+ }
}
- err = dd->err ? : err;
-
- if (err != -EINPROGRESS && (ready || err)) {
- dev_dbg(dd->dev, "update done: err: %d\n", err);
- /* finish curent request */
- omap_sham_finish_req(req, err);
- /* start new request */
- omap_sham_handle_queue(dd, NULL);
- }
-}
-
-static void omap_sham_queue_task(unsigned long data)
-{
- struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
+ return;
- omap_sham_handle_queue(dd, NULL);
+finish:
+ dev_dbg(dd->dev, "update done: err: %d\n", err);
+ /* finish curent request */
+ omap_sham_finish_req(dd->req, err);
}
static irqreturn_t omap_sham_irq(int irq, void *dev_id)
{
struct omap_sham_dev *dd = dev_id;
- struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
-
- if (!ctx) {
- dev_err(dd->dev, "unknown interrupt.\n");
- return IRQ_HANDLED;
- }
- if (unlikely(ctx->flags & FLAGS_FINAL))
+ if (unlikely(test_bit(FLAGS_FINAL, &dd->flags)))
/* final -> allow device to go to power-saving mode */
omap_sham_write_mask(dd, SHA_REG_CTRL, 0, SHA_REG_CTRL_LENGTH);
@@ -1088,8 +1085,12 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
SHA_REG_CTRL_OUTPUT_READY);
omap_sham_read(dd, SHA_REG_CTRL);
- ctx->flags |= FLAGS_OUTPUT_READY;
- dd->err = 0;
+ if (!test_bit(FLAGS_BUSY, &dd->flags)) {
+ dev_warn(dd->dev, "Interrupt when no active requests.\n");
+ return IRQ_HANDLED;
+ }
+
+ set_bit(FLAGS_OUTPUT_READY, &dd->flags);
tasklet_schedule(&dd->done_task);
return IRQ_HANDLED;
@@ -1102,9 +1103,10 @@ static void omap_sham_dma_callback(int lch, u16 ch_status, void *data)
if (ch_status != OMAP_DMA_BLOCK_IRQ) {
pr_err("omap-sham DMA error status: 0x%hx\n", ch_status);
dd->err = -EIO;
- dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
+ clear_bit(FLAGS_INIT, &dd->flags);/* request to re-initialize */
}
+ set_bit(FLAGS_DMA_READY, &dd->flags);
tasklet_schedule(&dd->done_task);
}
@@ -1151,7 +1153,6 @@ static int __devinit omap_sham_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&dd->list);
spin_lock_init(&dd->lock);
tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd);
- tasklet_init(&dd->queue_task, omap_sham_queue_task, (unsigned long)dd);
crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH);
dd->irq = -1;
@@ -1260,7 +1261,6 @@ static int __devexit omap_sham_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(algs); i++)
crypto_unregister_ahash(&algs[i]);
tasklet_kill(&dd->done_task);
- tasklet_kill(&dd->queue_task);
iounmap(dd->io_base);
clk_put(dd->iclk);
omap_sham_dma_cleanup(dd);
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 854e2632f9a6..8a0bb417aa11 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1,7 +1,7 @@
/*
* talitos - Freescale Integrated Security Engine (SEC) device driver
*
- * Copyright (c) 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
*
* Scatterlist Crypto API glue code copied from files with the following:
* Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
@@ -282,6 +282,7 @@ static int init_device(struct device *dev)
/**
* talitos_submit - submits a descriptor to the device for processing
* @dev: the SEC device to be used
+ * @ch: the SEC device channel to be used
* @desc: the descriptor to be processed by the device
* @callback: whom to call when processing is complete
* @context: a handle for use by caller (optional)
@@ -290,7 +291,7 @@ static int init_device(struct device *dev)
* callback must check err and feedback in descriptor header
* for device processing status.
*/
-static int talitos_submit(struct device *dev, struct talitos_desc *desc,
+static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
void (*callback)(struct device *dev,
struct talitos_desc *desc,
void *context, int error),
@@ -298,15 +299,9 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
{
struct talitos_private *priv = dev_get_drvdata(dev);
struct talitos_request *request;
- unsigned long flags, ch;
+ unsigned long flags;
int head;
- /* select done notification */
- desc->hdr |= DESC_HDR_DONE_NOTIFY;
-
- /* emulate SEC's round-robin channel fifo polling scheme */
- ch = atomic_inc_return(&priv->last_chan) & (priv->num_channels - 1);
-
spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
@@ -706,6 +701,7 @@ static void talitos_unregister_rng(struct device *dev)
struct talitos_ctx {
struct device *dev;
+ int ch;
__be32 desc_hdr_template;
u8 key[TALITOS_MAX_KEY_SIZE];
u8 iv[TALITOS_MAX_IV_LENGTH];
@@ -1117,7 +1113,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0,
DMA_FROM_DEVICE);
- ret = talitos_submit(dev, desc, callback, areq);
+ ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
if (ret != -EINPROGRESS) {
ipsec_esp_unmap(dev, edesc, areq);
kfree(edesc);
@@ -1382,22 +1378,11 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
const u8 *key, unsigned int keylen)
{
struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
- struct ablkcipher_alg *alg = crypto_ablkcipher_alg(cipher);
-
- if (keylen > TALITOS_MAX_KEY_SIZE)
- goto badkey;
-
- if (keylen < alg->min_keysize || keylen > alg->max_keysize)
- goto badkey;
memcpy(&ctx->key, key, keylen);
ctx->keylen = keylen;
return 0;
-
-badkey:
- crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
- return -EINVAL;
}
static void common_nonsnoop_unmap(struct device *dev,
@@ -1433,7 +1418,6 @@ static void ablkcipher_done(struct device *dev,
static int common_nonsnoop(struct talitos_edesc *edesc,
struct ablkcipher_request *areq,
- u8 *giv,
void (*callback) (struct device *dev,
struct talitos_desc *desc,
void *context, int error))
@@ -1453,7 +1437,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
/* cipher iv */
ivsize = crypto_ablkcipher_ivsize(cipher);
- map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, giv ?: areq->info, 0,
+ map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, areq->info, 0,
DMA_TO_DEVICE);
/* cipher key */
@@ -1524,7 +1508,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
to_talitos_ptr(&desc->ptr[6], 0);
desc->ptr[6].j_extent = 0;
- ret = talitos_submit(dev, desc, callback, areq);
+ ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
if (ret != -EINPROGRESS) {
common_nonsnoop_unmap(dev, edesc, areq);
kfree(edesc);
@@ -1556,7 +1540,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
/* set encrypt */
edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
- return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+ return common_nonsnoop(edesc, areq, ablkcipher_done);
}
static int ablkcipher_decrypt(struct ablkcipher_request *areq)
@@ -1572,7 +1556,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
- return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+ return common_nonsnoop(edesc, areq, ablkcipher_done);
}
static void common_nonsnoop_hash_unmap(struct device *dev,
@@ -1703,7 +1687,7 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
/* last DWORD empty */
desc->ptr[6] = zero_entry;
- ret = talitos_submit(dev, desc, callback, areq);
+ ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
if (ret != -EINPROGRESS) {
common_nonsnoop_hash_unmap(dev, edesc, areq);
kfree(edesc);
@@ -2244,6 +2228,7 @@ static int talitos_cra_init(struct crypto_tfm *tfm)
struct crypto_alg *alg = tfm->__crt_alg;
struct talitos_crypto_alg *talitos_alg;
struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct talitos_private *priv;
if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
talitos_alg = container_of(__crypto_ahash_alg(alg),
@@ -2256,9 +2241,17 @@ static int talitos_cra_init(struct crypto_tfm *tfm)
/* update context with ptr to dev */
ctx->dev = talitos_alg->dev;
+ /* assign SEC channel to tfm in round-robin fashion */
+ priv = dev_get_drvdata(ctx->dev);
+ ctx->ch = atomic_inc_return(&priv->last_chan) &
+ (priv->num_channels - 1);
+
/* copy descriptor header template value */
ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
+ /* select done notification */
+ ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
+
return 0;
}
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 25cf327cd1cb..2e3b3d38c465 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -237,6 +237,13 @@ config MXS_DMA
Support the MXS DMA engine. This engine including APBH-DMA
and APBX-DMA is integrated into Freescale i.MX23/28 chips.
+config EP93XX_DMA
+ bool "Cirrus Logic EP93xx DMA support"
+ depends on ARCH_EP93XX
+ select DMA_ENGINE
+ help
+ Enable support for the Cirrus Logic EP93xx M2P/M2M DMA controller.
+
config DMA_ENGINE
bool
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 836095ab3c5c..30cf3b1f0c5c 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_PL330_DMA) += pl330.o
obj-$(CONFIG_PCH_DMA) += pch_dma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
+obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index af8c0b5ed70f..a92d95eac86b 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h> /* everything... */
+#include <linux/scatterlist.h>
#include <linux/slab.h> /* kmalloc() */
#include <linux/dmaengine.h>
#include <linux/platform_device.h>
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 8bcb15fb959d..48694c34d96b 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -45,6 +45,7 @@
* See Documentation/dmaengine.txt for more details
*/
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index b4f5c32b6a47..765f5ff22304 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
#include <linux/kthread.h>
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
new file mode 100644
index 000000000000..0766c1e53b1d
--- /dev/null
+++ b/drivers/dma/ep93xx_dma.c
@@ -0,0 +1,1355 @@
+/*
+ * Driver for the Cirrus Logic EP93xx DMA Controller
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * DMA M2P implementation is based on the original
+ * arch/arm/mach-ep93xx/dma-m2p.c which has following copyrights:
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ * Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
+ *
+ * This driver is based on dw_dmac and amba-pl08x drivers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <mach/dma.h>
+
+/* M2P registers */
+#define M2P_CONTROL 0x0000
+#define M2P_CONTROL_STALLINT BIT(0)
+#define M2P_CONTROL_NFBINT BIT(1)
+#define M2P_CONTROL_CH_ERROR_INT BIT(3)
+#define M2P_CONTROL_ENABLE BIT(4)
+#define M2P_CONTROL_ICE BIT(6)
+
+#define M2P_INTERRUPT 0x0004
+#define M2P_INTERRUPT_STALL BIT(0)
+#define M2P_INTERRUPT_NFB BIT(1)
+#define M2P_INTERRUPT_ERROR BIT(3)
+
+#define M2P_PPALLOC 0x0008
+#define M2P_STATUS 0x000c
+
+#define M2P_MAXCNT0 0x0020
+#define M2P_BASE0 0x0024
+#define M2P_MAXCNT1 0x0030
+#define M2P_BASE1 0x0034
+
+#define M2P_STATE_IDLE 0
+#define M2P_STATE_STALL 1
+#define M2P_STATE_ON 2
+#define M2P_STATE_NEXT 3
+
+/* M2M registers */
+#define M2M_CONTROL 0x0000
+#define M2M_CONTROL_DONEINT BIT(2)
+#define M2M_CONTROL_ENABLE BIT(3)
+#define M2M_CONTROL_START BIT(4)
+#define M2M_CONTROL_DAH BIT(11)
+#define M2M_CONTROL_SAH BIT(12)
+#define M2M_CONTROL_PW_SHIFT 9
+#define M2M_CONTROL_PW_8 (0 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_16 (1 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_32 (2 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_MASK (3 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_TM_SHIFT 13
+#define M2M_CONTROL_TM_TX (1 << M2M_CONTROL_TM_SHIFT)
+#define M2M_CONTROL_TM_RX (2 << M2M_CONTROL_TM_SHIFT)
+#define M2M_CONTROL_RSS_SHIFT 22
+#define M2M_CONTROL_RSS_SSPRX (1 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_RSS_SSPTX (2 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_RSS_IDE (3 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_NO_HDSK BIT(24)
+#define M2M_CONTROL_PWSC_SHIFT 25
+
+#define M2M_INTERRUPT 0x0004
+#define M2M_INTERRUPT_DONEINT BIT(1)
+
+#define M2M_BCR0 0x0010
+#define M2M_BCR1 0x0014
+#define M2M_SAR_BASE0 0x0018
+#define M2M_SAR_BASE1 0x001c
+#define M2M_DAR_BASE0 0x002c
+#define M2M_DAR_BASE1 0x0030
+
+#define DMA_MAX_CHAN_BYTES 0xffff
+#define DMA_MAX_CHAN_DESCRIPTORS 32
+
+struct ep93xx_dma_engine;
+
+/**
+ * struct ep93xx_dma_desc - EP93xx specific transaction descriptor
+ * @src_addr: source address of the transaction
+ * @dst_addr: destination address of the transaction
+ * @size: size of the transaction (in bytes)
+ * @complete: this descriptor is completed
+ * @txd: dmaengine API descriptor
+ * @tx_list: list of linked descriptors
+ * @node: link used for putting this into a channel queue
+ */
+struct ep93xx_dma_desc {
+ u32 src_addr;
+ u32 dst_addr;
+ size_t size;
+ bool complete;
+ struct dma_async_tx_descriptor txd;
+ struct list_head tx_list;
+ struct list_head node;
+};
+
+/**
+ * struct ep93xx_dma_chan - an EP93xx DMA M2P/M2M channel
+ * @chan: dmaengine API channel
+ * @edma: pointer to to the engine device
+ * @regs: memory mapped registers
+ * @irq: interrupt number of the channel
+ * @clk: clock used by this channel
+ * @tasklet: channel specific tasklet used for callbacks
+ * @lock: lock protecting the fields following
+ * @flags: flags for the channel
+ * @buffer: which buffer to use next (0/1)
+ * @last_completed: last completed cookie value
+ * @active: flattened chain of descriptors currently being processed
+ * @queue: pending descriptors which are handled next
+ * @free_list: list of free descriptors which can be used
+ * @runtime_addr: physical address currently used as dest/src (M2M only). This
+ * is set via %DMA_SLAVE_CONFIG before slave operation is
+ * prepared
+ * @runtime_ctrl: M2M runtime values for the control register.
+ *
+ * As EP93xx DMA controller doesn't support real chained DMA descriptors we
+ * will have slightly different scheme here: @active points to a head of
+ * flattened DMA descriptor chain.
+ *
+ * @queue holds pending transactions. These are linked through the first
+ * descriptor in the chain. When a descriptor is moved to the @active queue,
+ * the first and chained descriptors are flattened into a single list.
+ *
+ * @chan.private holds pointer to &struct ep93xx_dma_data which contains
+ * necessary channel configuration information. For memcpy channels this must
+ * be %NULL.
+ */
+struct ep93xx_dma_chan {
+ struct dma_chan chan;
+ const struct ep93xx_dma_engine *edma;
+ void __iomem *regs;
+ int irq;
+ struct clk *clk;
+ struct tasklet_struct tasklet;
+ /* protects the fields following */
+ spinlock_t lock;
+ unsigned long flags;
+/* Channel is configured for cyclic transfers */
+#define EP93XX_DMA_IS_CYCLIC 0
+
+ int buffer;
+ dma_cookie_t last_completed;
+ struct list_head active;
+ struct list_head queue;
+ struct list_head free_list;
+ u32 runtime_addr;
+ u32 runtime_ctrl;
+};
+
+/**
+ * struct ep93xx_dma_engine - the EP93xx DMA engine instance
+ * @dma_dev: holds the dmaengine device
+ * @m2m: is this an M2M or M2P device
+ * @hw_setup: method which sets the channel up for operation
+ * @hw_shutdown: shuts the channel down and flushes whatever is left
+ * @hw_submit: pushes active descriptor(s) to the hardware
+ * @hw_interrupt: handle the interrupt
+ * @num_channels: number of channels for this instance
+ * @channels: array of channels
+ *
+ * There is one instance of this struct for the M2P channels and one for the
+ * M2M channels. hw_xxx() methods are used to perform operations which are
+ * different on M2M and M2P channels. These methods are called with channel
+ * lock held and interrupts disabled so they cannot sleep.
+ */
+struct ep93xx_dma_engine {
+ struct dma_device dma_dev;
+ bool m2m;
+ int (*hw_setup)(struct ep93xx_dma_chan *);
+ void (*hw_shutdown)(struct ep93xx_dma_chan *);
+ void (*hw_submit)(struct ep93xx_dma_chan *);
+ int (*hw_interrupt)(struct ep93xx_dma_chan *);
+#define INTERRUPT_UNKNOWN 0
+#define INTERRUPT_DONE 1
+#define INTERRUPT_NEXT_BUFFER 2
+
+ size_t num_channels;
+ struct ep93xx_dma_chan channels[];
+};
+
+static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac)
+{
+ return &edmac->chan.dev->device;
+}
+
+static struct ep93xx_dma_chan *to_ep93xx_dma_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct ep93xx_dma_chan, chan);
+}
+
+/**
+ * ep93xx_dma_set_active - set new active descriptor chain
+ * @edmac: channel
+ * @desc: head of the new active descriptor chain
+ *
+ * Sets @desc to be the head of the new active descriptor chain. This is the
+ * chain which is processed next. The active list must be empty before calling
+ * this function.
+ *
+ * Called with @edmac->lock held and interrupts disabled.
+ */
+static void ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac,
+ struct ep93xx_dma_desc *desc)
+{
+ BUG_ON(!list_empty(&edmac->active));
+
+ list_add_tail(&desc->node, &edmac->active);
+
+ /* Flatten the @desc->tx_list chain into @edmac->active list */
+ while (!list_empty(&desc->tx_list)) {
+ struct ep93xx_dma_desc *d = list_first_entry(&desc->tx_list,
+ struct ep93xx_dma_desc, node);
+
+ /*
+ * We copy the callback parameters from the first descriptor
+ * to all the chained descriptors. This way we can call the
+ * callback without having to find out the first descriptor in
+ * the chain. Useful for cyclic transfers.
+ */
+ d->txd.callback = desc->txd.callback;
+ d->txd.callback_param = desc->txd.callback_param;
+
+ list_move_tail(&d->node, &edmac->active);
+ }
+}
+
+/* Called with @edmac->lock held and interrupts disabled */
+static struct ep93xx_dma_desc *
+ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
+{
+ return list_first_entry(&edmac->active, struct ep93xx_dma_desc, node);
+}
+
+/**
+ * ep93xx_dma_advance_active - advances to the next active descriptor
+ * @edmac: channel
+ *
+ * Function advances active descriptor to the next in the @edmac->active and
+ * returns %true if we still have descriptors in the chain to process.
+ * Otherwise returns %false.
+ *
+ * When the channel is in cyclic mode always returns %true.
+ *
+ * Called with @edmac->lock held and interrupts disabled.
+ */
+static bool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac)
+{
+ list_rotate_left(&edmac->active);
+
+ if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
+ return true;
+
+ /*
+ * If txd.cookie is set it means that we are back in the first
+ * descriptor in the chain and hence done with it.
+ */
+ return !ep93xx_dma_get_active(edmac)->txd.cookie;
+}
+
+/*
+ * M2P DMA implementation
+ */
+
+static void m2p_set_control(struct ep93xx_dma_chan *edmac, u32 control)
+{
+ writel(control, edmac->regs + M2P_CONTROL);
+ /*
+ * EP93xx User's Guide states that we must perform a dummy read after
+ * write to the control register.
+ */
+ readl(edmac->regs + M2P_CONTROL);
+}
+
+static int m2p_hw_setup(struct ep93xx_dma_chan *edmac)
+{
+ struct ep93xx_dma_data *data = edmac->chan.private;
+ u32 control;
+
+ writel(data->port & 0xf, edmac->regs + M2P_PPALLOC);
+
+ control = M2P_CONTROL_CH_ERROR_INT | M2P_CONTROL_ICE
+ | M2P_CONTROL_ENABLE;
+ m2p_set_control(edmac, control);
+
+ return 0;
+}
+
+static inline u32 m2p_channel_state(struct ep93xx_dma_chan *edmac)
+{
+ return (readl(edmac->regs + M2P_STATUS) >> 4) & 0x3;
+}
+
+static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
+ u32 control;
+
+ control = readl(edmac->regs + M2P_CONTROL);
+ control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
+ m2p_set_control(edmac, control);
+
+ while (m2p_channel_state(edmac) >= M2P_STATE_ON)
+ cpu_relax();
+
+ m2p_set_control(edmac, 0);
+
+ while (m2p_channel_state(edmac) == M2P_STATE_STALL)
+ cpu_relax();
+}
+
+static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
+{
+ struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+ u32 bus_addr;
+
+ if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_TO_DEVICE)
+ bus_addr = desc->src_addr;
+ else
+ bus_addr = desc->dst_addr;
+
+ if (edmac->buffer == 0) {
+ writel(desc->size, edmac->regs + M2P_MAXCNT0);
+ writel(bus_addr, edmac->regs + M2P_BASE0);
+ } else {
+ writel(desc->size, edmac->regs + M2P_MAXCNT1);
+ writel(bus_addr, edmac->regs + M2P_BASE1);
+ }
+
+ edmac->buffer ^= 1;
+}
+
+static void m2p_hw_submit(struct ep93xx_dma_chan *edmac)
+{
+ u32 control = readl(edmac->regs + M2P_CONTROL);
+
+ m2p_fill_desc(edmac);
+ control |= M2P_CONTROL_STALLINT;
+
+ if (ep93xx_dma_advance_active(edmac)) {
+ m2p_fill_desc(edmac);
+ control |= M2P_CONTROL_NFBINT;
+ }
+
+ m2p_set_control(edmac, control);
+}
+
+static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac)
+{
+ u32 irq_status = readl(edmac->regs + M2P_INTERRUPT);
+ u32 control;
+
+ if (irq_status & M2P_INTERRUPT_ERROR) {
+ struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+
+ /* Clear the error interrupt */
+ writel(1, edmac->regs + M2P_INTERRUPT);
+
+ /*
+ * It seems that there is no easy way of reporting errors back
+ * to client so we just report the error here and continue as
+ * usual.
+ *
+ * Revisit this when there is a mechanism to report back the
+ * errors.
+ */
+ dev_err(chan2dev(edmac),
+ "DMA transfer failed! Details:\n"
+ "\tcookie : %d\n"
+ "\tsrc_addr : 0x%08x\n"
+ "\tdst_addr : 0x%08x\n"
+ "\tsize : %zu\n",
+ desc->txd.cookie, desc->src_addr, desc->dst_addr,
+ desc->size);
+ }
+
+ switch (irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) {
+ case M2P_INTERRUPT_STALL:
+ /* Disable interrupts */
+ control = readl(edmac->regs + M2P_CONTROL);
+ control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
+ m2p_set_control(edmac, control);
+
+ return INTERRUPT_DONE;
+
+ case M2P_INTERRUPT_NFB:
+ if (ep93xx_dma_advance_active(edmac))
+ m2p_fill_desc(edmac);
+
+ return INTERRUPT_NEXT_BUFFER;
+ }
+
+ return INTERRUPT_UNKNOWN;
+}
+
+/*
+ * M2M DMA implementation
+ *
+ * For the M2M transfers we don't use NFB at all. This is because it simply
+ * doesn't work well with memcpy transfers. When you submit both buffers it is
+ * extremely unlikely that you get an NFB interrupt, but it instead reports
+ * DONE interrupt and both buffers are already transferred which means that we
+ * weren't able to update the next buffer.
+ *
+ * So for now we "simulate" NFB by just submitting buffer after buffer
+ * without double buffering.
+ */
+
+static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
+{
+ const struct ep93xx_dma_data *data = edmac->chan.private;
+ u32 control = 0;
+
+ if (!data) {
+ /* This is memcpy channel, nothing to configure */
+ writel(control, edmac->regs + M2M_CONTROL);
+ return 0;
+ }
+
+ switch (data->port) {
+ case EP93XX_DMA_SSP:
+ /*
+ * This was found via experimenting - anything less than 5
+ * causes the channel to perform only a partial transfer which
+ * leads to problems since we don't get DONE interrupt then.
+ */
+ control = (5 << M2M_CONTROL_PWSC_SHIFT);
+ control |= M2M_CONTROL_NO_HDSK;
+
+ if (data->direction == DMA_TO_DEVICE) {
+ control |= M2M_CONTROL_DAH;
+ control |= M2M_CONTROL_TM_TX;
+ control |= M2M_CONTROL_RSS_SSPTX;
+ } else {
+ control |= M2M_CONTROL_SAH;
+ control |= M2M_CONTROL_TM_RX;
+ control |= M2M_CONTROL_RSS_SSPRX;
+ }
+ break;
+
+ case EP93XX_DMA_IDE:
+ /*
+ * This IDE part is totally untested. Values below are taken
+ * from the EP93xx Users's Guide and might not be correct.
+ */
+ control |= M2M_CONTROL_NO_HDSK;
+ control |= M2M_CONTROL_RSS_IDE;
+ control |= M2M_CONTROL_PW_16;
+
+ if (data->direction == DMA_TO_DEVICE) {
+ /* Worst case from the UG */
+ control = (3 << M2M_CONTROL_PWSC_SHIFT);
+ control |= M2M_CONTROL_DAH;
+ control |= M2M_CONTROL_TM_TX;
+ } else {
+ control = (2 << M2M_CONTROL_PWSC_SHIFT);
+ control |= M2M_CONTROL_SAH;
+ control |= M2M_CONTROL_TM_RX;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ writel(control, edmac->regs + M2M_CONTROL);
+ return 0;
+}
+
+static void m2m_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
+ /* Just disable the channel */
+ writel(0, edmac->regs + M2M_CONTROL);
+}
+
+static void m2m_fill_desc(struct ep93xx_dma_chan *edmac)
+{
+ struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+
+ if (edmac->buffer == 0) {
+ writel(desc->src_addr, edmac->regs + M2M_SAR_BASE0);
+ writel(desc->dst_addr, edmac->regs + M2M_DAR_BASE0);
+ writel(desc->size, edmac->regs + M2M_BCR0);
+ } else {
+ writel(desc->src_addr, edmac->regs + M2M_SAR_BASE1);
+ writel(desc->dst_addr, edmac->regs + M2M_DAR_BASE1);
+ writel(desc->size, edmac->regs + M2M_BCR1);
+ }
+
+ edmac->buffer ^= 1;
+}
+
+static void m2m_hw_submit(struct ep93xx_dma_chan *edmac)
+{
+ struct ep93xx_dma_data *data = edmac->chan.private;
+ u32 control = readl(edmac->regs + M2M_CONTROL);
+
+ /*
+ * Since we allow clients to configure PW (peripheral width) we always
+ * clear PW bits here and then set them according what is given in
+ * the runtime configuration.
+ */
+ control &= ~M2M_CONTROL_PW_MASK;
+ control |= edmac->runtime_ctrl;
+
+ m2m_fill_desc(edmac);
+ control |= M2M_CONTROL_DONEINT;
+
+ /*
+ * Now we can finally enable the channel. For M2M channel this must be
+ * done _after_ the BCRx registers are programmed.
+ */
+ control |= M2M_CONTROL_ENABLE;
+ writel(control, edmac->regs + M2M_CONTROL);
+
+ if (!data) {
+ /*
+ * For memcpy channels the software trigger must be asserted
+ * in order to start the memcpy operation.
+ */
+ control |= M2M_CONTROL_START;
+ writel(control, edmac->regs + M2M_CONTROL);
+ }
+}
+
+static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac)
+{
+ u32 control;
+
+ if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_DONEINT))
+ return INTERRUPT_UNKNOWN;
+
+ /* Clear the DONE bit */
+ writel(0, edmac->regs + M2M_INTERRUPT);
+
+ /* Disable interrupts and the channel */
+ control = readl(edmac->regs + M2M_CONTROL);
+ control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_ENABLE);
+ writel(control, edmac->regs + M2M_CONTROL);
+
+ /*
+ * Since we only get DONE interrupt we have to find out ourselves
+ * whether there still is something to process. So we try to advance
+ * the chain an see whether it succeeds.
+ */
+ if (ep93xx_dma_advance_active(edmac)) {
+ edmac->edma->hw_submit(edmac);
+ return INTERRUPT_NEXT_BUFFER;
+ }
+
+ return INTERRUPT_DONE;
+}
+
+/*
+ * DMA engine API implementation
+ */
+
+static struct ep93xx_dma_desc *
+ep93xx_dma_desc_get(struct ep93xx_dma_chan *edmac)
+{
+ struct ep93xx_dma_desc *desc, *_desc;
+ struct ep93xx_dma_desc *ret = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac->lock, flags);
+ list_for_each_entry_safe(desc, _desc, &edmac->free_list, node) {
+ if (async_tx_test_ack(&desc->txd)) {
+ list_del_init(&desc->node);
+
+ /* Re-initialize the descriptor */
+ desc->src_addr = 0;
+ desc->dst_addr = 0;
+ desc->size = 0;
+ desc->complete = false;
+ desc->txd.cookie = 0;
+ desc->txd.callback = NULL;
+ desc->txd.callback_param = NULL;
+
+ ret = desc;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&edmac->lock, flags);
+ return ret;
+}
+
+static void ep93xx_dma_desc_put(struct ep93xx_dma_chan *edmac,
+ struct ep93xx_dma_desc *desc)
+{
+ if (desc) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac->lock, flags);
+ list_splice_init(&desc->tx_list, &edmac->free_list);
+ list_add(&desc->node, &edmac->free_list);
+ spin_unlock_irqrestore(&edmac->lock, flags);
+ }
+}
+
+/**
+ * ep93xx_dma_advance_work - start processing the next pending transaction
+ * @edmac: channel
+ *
+ * If we have pending transactions queued and we are currently idling, this
+ * function takes the next queued transaction from the @edmac->queue and
+ * pushes it to the hardware for execution.
+ */
+static void ep93xx_dma_advance_work(struct ep93xx_dma_chan *edmac)
+{
+ struct ep93xx_dma_desc *new;
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac->lock, flags);
+ if (!list_empty(&edmac->active) || list_empty(&edmac->queue)) {
+ spin_unlock_irqrestore(&edmac->lock, flags);
+ return;
+ }
+
+ /* Take the next descriptor from the pending queue */
+ new = list_first_entry(&edmac->queue, struct ep93xx_dma_desc, node);
+ list_del_init(&new->node);
+
+ ep93xx_dma_set_active(edmac, new);
+
+ /* Push it to the hardware */
+ edmac->edma->hw_submit(edmac);
+ spin_unlock_irqrestore(&edmac->lock, flags);
+}
+
+static void ep93xx_dma_unmap_buffers(struct ep93xx_dma_desc *desc)
+{
+ struct device *dev = desc->txd.chan->device->dev;
+
+ if (!(desc->txd.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ if (desc->txd.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+ dma_unmap_single(dev, desc->src_addr, desc->size,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(dev, desc->src_addr, desc->size,
+ DMA_TO_DEVICE);
+ }
+ if (!(desc->txd.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ if (desc->txd.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+ dma_unmap_single(dev, desc->dst_addr, desc->size,
+ DMA_FROM_DEVICE);
+ else
+ dma_unmap_page(dev, desc->dst_addr, desc->size,
+ DMA_FROM_DEVICE);
+ }
+}
+
+static void ep93xx_dma_tasklet(unsigned long data)
+{
+ struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
+ struct ep93xx_dma_desc *desc, *d;
+ dma_async_tx_callback callback;
+ void *callback_param;
+ LIST_HEAD(list);
+
+ spin_lock_irq(&edmac->lock);
+ desc = ep93xx_dma_get_active(edmac);
+ if (desc->complete) {
+ edmac->last_completed = desc->txd.cookie;
+ list_splice_init(&edmac->active, &list);
+ }
+ spin_unlock_irq(&edmac->lock);
+
+ /* Pick up the next descriptor from the queue */
+ ep93xx_dma_advance_work(edmac);
+
+ callback = desc->txd.callback;
+ callback_param = desc->txd.callback_param;
+
+ /* Now we can release all the chained descriptors */
+ list_for_each_entry_safe(desc, d, &list, node) {
+ /*
+ * For the memcpy channels the API requires us to unmap the
+ * buffers unless requested otherwise.
+ */
+ if (!edmac->chan.private)
+ ep93xx_dma_unmap_buffers(desc);
+
+ ep93xx_dma_desc_put(edmac, desc);
+ }
+
+ if (callback)
+ callback(callback_param);
+}
+
+static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id)
+{
+ struct ep93xx_dma_chan *edmac = dev_id;
+ irqreturn_t ret = IRQ_HANDLED;
+
+ spin_lock(&edmac->lock);
+
+ switch (edmac->edma->hw_interrupt(edmac)) {
+ case INTERRUPT_DONE:
+ ep93xx_dma_get_active(edmac)->complete = true;
+ tasklet_schedule(&edmac->tasklet);
+ break;
+
+ case INTERRUPT_NEXT_BUFFER:
+ if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
+ tasklet_schedule(&edmac->tasklet);
+ break;
+
+ default:
+ dev_warn(chan2dev(edmac), "unknown interrupt!\n");
+ ret = IRQ_NONE;
+ break;
+ }
+
+ spin_unlock(&edmac->lock);
+ return ret;
+}
+
+/**
+ * ep93xx_dma_tx_submit - set the prepared descriptor(s) to be executed
+ * @tx: descriptor to be executed
+ *
+ * Function will execute given descriptor on the hardware or if the hardware
+ * is busy, queue the descriptor to be executed later on. Returns cookie which
+ * can be used to poll the status of the descriptor.
+ */
+static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(tx->chan);
+ struct ep93xx_dma_desc *desc;
+ dma_cookie_t cookie;
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac->lock, flags);
+
+ cookie = edmac->chan.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+
+ desc = container_of(tx, struct ep93xx_dma_desc, txd);
+
+ edmac->chan.cookie = cookie;
+ desc->txd.cookie = cookie;
+
+ /*
+ * If nothing is currently prosessed, we push this descriptor
+ * directly to the hardware. Otherwise we put the descriptor
+ * to the pending queue.
+ */
+ if (list_empty(&edmac->active)) {
+ ep93xx_dma_set_active(edmac, desc);
+ edmac->edma->hw_submit(edmac);
+ } else {
+ list_add_tail(&desc->node, &edmac->queue);
+ }
+
+ spin_unlock_irqrestore(&edmac->lock, flags);
+ return cookie;
+}
+
+/**
+ * ep93xx_dma_alloc_chan_resources - allocate resources for the channel
+ * @chan: channel to allocate resources
+ *
+ * Function allocates necessary resources for the given DMA channel and
+ * returns number of allocated descriptors for the channel. Negative errno
+ * is returned in case of failure.
+ */
+static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+ struct ep93xx_dma_data *data = chan->private;
+ const char *name = dma_chan_name(chan);
+ int ret, i;
+
+ /* Sanity check the channel parameters */
+ if (!edmac->edma->m2m) {
+ if (!data)
+ return -EINVAL;
+ if (data->port < EP93XX_DMA_I2S1 ||
+ data->port > EP93XX_DMA_IRDA)
+ return -EINVAL;
+ if (data->direction != ep93xx_dma_chan_direction(chan))
+ return -EINVAL;
+ } else {
+ if (data) {
+ switch (data->port) {
+ case EP93XX_DMA_SSP:
+ case EP93XX_DMA_IDE:
+ if (data->direction != DMA_TO_DEVICE &&
+ data->direction != DMA_FROM_DEVICE)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (data && data->name)
+ name = data->name;
+
+ ret = clk_enable(edmac->clk);
+ if (ret)
+ return ret;
+
+ ret = request_irq(edmac->irq, ep93xx_dma_interrupt, 0, name, edmac);
+ if (ret)
+ goto fail_clk_disable;
+
+ spin_lock_irq(&edmac->lock);
+ edmac->last_completed = 1;
+ edmac->chan.cookie = 1;
+ ret = edmac->edma->hw_setup(edmac);
+ spin_unlock_irq(&edmac->lock);
+
+ if (ret)
+ goto fail_free_irq;
+
+ for (i = 0; i < DMA_MAX_CHAN_DESCRIPTORS; i++) {
+ struct ep93xx_dma_desc *desc;
+
+ desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+ if (!desc) {
+ dev_warn(chan2dev(edmac), "not enough descriptors\n");
+ break;
+ }
+
+ INIT_LIST_HEAD(&desc->tx_list);
+
+ dma_async_tx_descriptor_init(&desc->txd, chan);
+ desc->txd.flags = DMA_CTRL_ACK;
+ desc->txd.tx_submit = ep93xx_dma_tx_submit;
+
+ ep93xx_dma_desc_put(edmac, desc);
+ }
+
+ return i;
+
+fail_free_irq:
+ free_irq(edmac->irq, edmac);
+fail_clk_disable:
+ clk_disable(edmac->clk);
+
+ return ret;
+}
+
+/**
+ * ep93xx_dma_free_chan_resources - release resources for the channel
+ * @chan: channel
+ *
+ * Function releases all the resources allocated for the given channel.
+ * The channel must be idle when this is called.
+ */
+static void ep93xx_dma_free_chan_resources(struct dma_chan *chan)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+ struct ep93xx_dma_desc *desc, *d;
+ unsigned long flags;
+ LIST_HEAD(list);
+
+ BUG_ON(!list_empty(&edmac->active));
+ BUG_ON(!list_empty(&edmac->queue));
+
+ spin_lock_irqsave(&edmac->lock, flags);
+ edmac->edma->hw_shutdown(edmac);
+ edmac->runtime_addr = 0;
+ edmac->runtime_ctrl = 0;
+ edmac->buffer = 0;
+ list_splice_init(&edmac->free_list, &list);
+ spin_unlock_irqrestore(&edmac->lock, flags);
+
+ list_for_each_entry_safe(desc, d, &list, node)
+ kfree(desc);
+
+ clk_disable(edmac->clk);
+ free_irq(edmac->irq, edmac);
+}
+
+/**
+ * ep93xx_dma_prep_dma_memcpy - prepare a memcpy DMA operation
+ * @chan: channel
+ * @dest: destination bus address
+ * @src: source bus address
+ * @len: size of the transaction
+ * @flags: flags for the descriptor
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+struct dma_async_tx_descriptor *
+ep93xx_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
+ dma_addr_t src, size_t len, unsigned long flags)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+ struct ep93xx_dma_desc *desc, *first;
+ size_t bytes, offset;
+
+ first = NULL;
+ for (offset = 0; offset < len; offset += bytes) {
+ desc = ep93xx_dma_desc_get(edmac);
+ if (!desc) {
+ dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+ goto fail;
+ }
+
+ bytes = min_t(size_t, len - offset, DMA_MAX_CHAN_BYTES);
+
+ desc->src_addr = src + offset;
+ desc->dst_addr = dest + offset;
+ desc->size = bytes;
+
+ if (!first)
+ first = desc;
+ else
+ list_add_tail(&desc->node, &first->tx_list);
+ }
+
+ first->txd.cookie = -EBUSY;
+ first->txd.flags = flags;
+
+ return &first->txd;
+fail:
+ ep93xx_dma_desc_put(edmac, first);
+ return NULL;
+}
+
+/**
+ * ep93xx_dma_prep_slave_sg - prepare a slave DMA operation
+ * @chan: channel
+ * @sgl: list of buffers to transfer
+ * @sg_len: number of entries in @sgl
+ * @dir: direction of tha DMA transfer
+ * @flags: flags for the descriptor
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_data_direction dir,
+ unsigned long flags)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+ struct ep93xx_dma_desc *desc, *first;
+ struct scatterlist *sg;
+ int i;
+
+ if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
+ dev_warn(chan2dev(edmac),
+ "channel was configured with different direction\n");
+ return NULL;
+ }
+
+ if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
+ dev_warn(chan2dev(edmac),
+ "channel is already used for cyclic transfers\n");
+ return NULL;
+ }
+
+ first = NULL;
+ for_each_sg(sgl, sg, sg_len, i) {
+ size_t sg_len = sg_dma_len(sg);
+
+ if (sg_len > DMA_MAX_CHAN_BYTES) {
+ dev_warn(chan2dev(edmac), "too big transfer size %d\n",
+ sg_len);
+ goto fail;
+ }
+
+ desc = ep93xx_dma_desc_get(edmac);
+ if (!desc) {
+ dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+ goto fail;
+ }
+
+ if (dir == DMA_TO_DEVICE) {
+ desc->src_addr = sg_dma_address(sg);
+ desc->dst_addr = edmac->runtime_addr;
+ } else {
+ desc->src_addr = edmac->runtime_addr;
+ desc->dst_addr = sg_dma_address(sg);
+ }
+ desc->size = sg_len;
+
+ if (!first)
+ first = desc;
+ else
+ list_add_tail(&desc->node, &first->tx_list);
+ }
+
+ first->txd.cookie = -EBUSY;
+ first->txd.flags = flags;
+
+ return &first->txd;
+
+fail:
+ ep93xx_dma_desc_put(edmac, first);
+ return NULL;
+}
+
+/**
+ * ep93xx_dma_prep_dma_cyclic - prepare a cyclic DMA operation
+ * @chan: channel
+ * @dma_addr: DMA mapped address of the buffer
+ * @buf_len: length of the buffer (in bytes)
+ * @period_len: lenght of a single period
+ * @dir: direction of the operation
+ *
+ * Prepares a descriptor for cyclic DMA operation. This means that once the
+ * descriptor is submitted, we will be submitting in a @period_len sized
+ * buffers and calling callback once the period has been elapsed. Transfer
+ * terminates only when client calls dmaengine_terminate_all() for this
+ * channel.
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
+ size_t buf_len, size_t period_len,
+ enum dma_data_direction dir)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+ struct ep93xx_dma_desc *desc, *first;
+ size_t offset = 0;
+
+ if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
+ dev_warn(chan2dev(edmac),
+ "channel was configured with different direction\n");
+ return NULL;
+ }
+
+ if (test_and_set_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
+ dev_warn(chan2dev(edmac),
+ "channel is already used for cyclic transfers\n");
+ return NULL;
+ }
+
+ if (period_len > DMA_MAX_CHAN_BYTES) {
+ dev_warn(chan2dev(edmac), "too big period length %d\n",
+ period_len);
+ return NULL;
+ }
+
+ /* Split the buffer into period size chunks */
+ first = NULL;
+ for (offset = 0; offset < buf_len; offset += period_len) {
+ desc = ep93xx_dma_desc_get(edmac);
+ if (!desc) {
+ dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+ goto fail;
+ }
+
+ if (dir == DMA_TO_DEVICE) {
+ desc->src_addr = dma_addr + offset;
+ desc->dst_addr = edmac->runtime_addr;
+ } else {
+ desc->src_addr = edmac->runtime_addr;
+ desc->dst_addr = dma_addr + offset;
+ }
+
+ desc->size = period_len;
+
+ if (!first)
+ first = desc;
+ else
+ list_add_tail(&desc->node, &first->tx_list);
+ }
+
+ first->txd.cookie = -EBUSY;
+
+ return &first->txd;
+
+fail:
+ ep93xx_dma_desc_put(edmac, first);
+ return NULL;
+}
+
+/**
+ * ep93xx_dma_terminate_all - terminate all transactions
+ * @edmac: channel
+ *
+ * Stops all DMA transactions. All descriptors are put back to the
+ * @edmac->free_list and callbacks are _not_ called.
+ */
+static int ep93xx_dma_terminate_all(struct ep93xx_dma_chan *edmac)
+{
+ struct ep93xx_dma_desc *desc, *_d;
+ unsigned long flags;
+ LIST_HEAD(list);
+
+ spin_lock_irqsave(&edmac->lock, flags);
+ /* First we disable and flush the DMA channel */
+ edmac->edma->hw_shutdown(edmac);
+ clear_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags);
+ list_splice_init(&edmac->active, &list);
+ list_splice_init(&edmac->queue, &list);
+ /*
+ * We then re-enable the channel. This way we can continue submitting
+ * the descriptors by just calling ->hw_submit() again.
+ */
+ edmac->edma->hw_setup(edmac);
+ spin_unlock_irqrestore(&edmac->lock, flags);
+
+ list_for_each_entry_safe(desc, _d, &list, node)
+ ep93xx_dma_desc_put(edmac, desc);
+
+ return 0;
+}
+
+static int ep93xx_dma_slave_config(struct ep93xx_dma_chan *edmac,
+ struct dma_slave_config *config)
+{
+ enum dma_slave_buswidth width;
+ unsigned long flags;
+ u32 addr, ctrl;
+
+ if (!edmac->edma->m2m)
+ return -EINVAL;
+
+ switch (config->direction) {
+ case DMA_FROM_DEVICE:
+ width = config->src_addr_width;
+ addr = config->src_addr;
+ break;
+
+ case DMA_TO_DEVICE:
+ width = config->dst_addr_width;
+ addr = config->dst_addr;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ switch (width) {
+ case DMA_SLAVE_BUSWIDTH_1_BYTE:
+ ctrl = 0;
+ break;
+ case DMA_SLAVE_BUSWIDTH_2_BYTES:
+ ctrl = M2M_CONTROL_PW_16;
+ break;
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ ctrl = M2M_CONTROL_PW_32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&edmac->lock, flags);
+ edmac->runtime_addr = addr;
+ edmac->runtime_ctrl = ctrl;
+ spin_unlock_irqrestore(&edmac->lock, flags);
+
+ return 0;
+}
+
+/**
+ * ep93xx_dma_control - manipulate all pending operations on a channel
+ * @chan: channel
+ * @cmd: control command to perform
+ * @arg: optional argument
+ *
+ * Controls the channel. Function returns %0 in case of success or negative
+ * error in case of failure.
+ */
+static int ep93xx_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+ struct dma_slave_config *config;
+
+ switch (cmd) {
+ case DMA_TERMINATE_ALL:
+ return ep93xx_dma_terminate_all(edmac);
+
+ case DMA_SLAVE_CONFIG:
+ config = (struct dma_slave_config *)arg;
+ return ep93xx_dma_slave_config(edmac, config);
+
+ default:
+ break;
+ }
+
+ return -ENOSYS;
+}
+
+/**
+ * ep93xx_dma_tx_status - check if a transaction is completed
+ * @chan: channel
+ * @cookie: transaction specific cookie
+ * @state: state of the transaction is stored here if given
+ *
+ * This function can be used to query state of a given transaction.
+ */
+static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *state)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+ dma_cookie_t last_used, last_completed;
+ enum dma_status ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac->lock, flags);
+ last_used = chan->cookie;
+ last_completed = edmac->last_completed;
+ spin_unlock_irqrestore(&edmac->lock, flags);
+
+ ret = dma_async_is_complete(cookie, last_completed, last_used);
+ dma_set_tx_state(state, last_completed, last_used, 0);
+
+ return ret;
+}
+
+/**
+ * ep93xx_dma_issue_pending - push pending transactions to the hardware
+ * @chan: channel
+ *
+ * When this function is called, all pending transactions are pushed to the
+ * hardware and executed.
+ */
+static void ep93xx_dma_issue_pending(struct dma_chan *chan)
+{
+ ep93xx_dma_advance_work(to_ep93xx_dma_chan(chan));
+}
+
+static int __init ep93xx_dma_probe(struct platform_device *pdev)
+{
+ struct ep93xx_dma_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct ep93xx_dma_engine *edma;
+ struct dma_device *dma_dev;
+ size_t edma_size;
+ int ret, i;
+
+ edma_size = pdata->num_channels * sizeof(struct ep93xx_dma_chan);
+ edma = kzalloc(sizeof(*edma) + edma_size, GFP_KERNEL);
+ if (!edma)
+ return -ENOMEM;
+
+ dma_dev = &edma->dma_dev;
+ edma->m2m = platform_get_device_id(pdev)->driver_data;
+ edma->num_channels = pdata->num_channels;
+
+ INIT_LIST_HEAD(&dma_dev->channels);
+ for (i = 0; i < pdata->num_channels; i++) {
+ const struct ep93xx_dma_chan_data *cdata = &pdata->channels[i];
+ struct ep93xx_dma_chan *edmac = &edma->channels[i];
+
+ edmac->chan.device = dma_dev;
+ edmac->regs = cdata->base;
+ edmac->irq = cdata->irq;
+ edmac->edma = edma;
+
+ edmac->clk = clk_get(NULL, cdata->name);
+ if (IS_ERR(edmac->clk)) {
+ dev_warn(&pdev->dev, "failed to get clock for %s\n",
+ cdata->name);
+ continue;
+ }
+
+ spin_lock_init(&edmac->lock);
+ INIT_LIST_HEAD(&edmac->active);
+ INIT_LIST_HEAD(&edmac->queue);
+ INIT_LIST_HEAD(&edmac->free_list);
+ tasklet_init(&edmac->tasklet, ep93xx_dma_tasklet,
+ (unsigned long)edmac);
+
+ list_add_tail(&edmac->chan.device_node,
+ &dma_dev->channels);
+ }
+
+ dma_cap_zero(dma_dev->cap_mask);
+ dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
+ dma_cap_set(DMA_CYCLIC, dma_dev->cap_mask);
+
+ dma_dev->dev = &pdev->dev;
+ dma_dev->device_alloc_chan_resources = ep93xx_dma_alloc_chan_resources;
+ dma_dev->device_free_chan_resources = ep93xx_dma_free_chan_resources;
+ dma_dev->device_prep_slave_sg = ep93xx_dma_prep_slave_sg;
+ dma_dev->device_prep_dma_cyclic = ep93xx_dma_prep_dma_cyclic;
+ dma_dev->device_control = ep93xx_dma_control;
+ dma_dev->device_issue_pending = ep93xx_dma_issue_pending;
+ dma_dev->device_tx_status = ep93xx_dma_tx_status;
+
+ dma_set_max_seg_size(dma_dev->dev, DMA_MAX_CHAN_BYTES);
+
+ if (edma->m2m) {
+ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+ dma_dev->device_prep_dma_memcpy = ep93xx_dma_prep_dma_memcpy;
+
+ edma->hw_setup = m2m_hw_setup;
+ edma->hw_shutdown = m2m_hw_shutdown;
+ edma->hw_submit = m2m_hw_submit;
+ edma->hw_interrupt = m2m_hw_interrupt;
+ } else {
+ dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
+
+ edma->hw_setup = m2p_hw_setup;
+ edma->hw_shutdown = m2p_hw_shutdown;
+ edma->hw_submit = m2p_hw_submit;
+ edma->hw_interrupt = m2p_hw_interrupt;
+ }
+
+ ret = dma_async_device_register(dma_dev);
+ if (unlikely(ret)) {
+ for (i = 0; i < edma->num_channels; i++) {
+ struct ep93xx_dma_chan *edmac = &edma->channels[i];
+ if (!IS_ERR_OR_NULL(edmac->clk))
+ clk_put(edmac->clk);
+ }
+ kfree(edma);
+ } else {
+ dev_info(dma_dev->dev, "EP93xx M2%s DMA ready\n",
+ edma->m2m ? "M" : "P");
+ }
+
+ return ret;
+}
+
+static struct platform_device_id ep93xx_dma_driver_ids[] = {
+ { "ep93xx-dma-m2p", 0 },
+ { "ep93xx-dma-m2m", 1 },
+ { },
+};
+
+static struct platform_driver ep93xx_dma_driver = {
+ .driver = {
+ .name = "ep93xx-dma",
+ },
+ .id_table = ep93xx_dma_driver_ids,
+};
+
+static int __init ep93xx_dma_module_init(void)
+{
+ return platform_driver_probe(&ep93xx_dma_driver, ep93xx_dma_probe);
+}
+subsys_initcall(ep93xx_dma_module_init);
+
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_DESCRIPTION("EP93xx DMA driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index e18eaabe92b9..d99f71c356b5 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -135,7 +135,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
if (ret)
return ret;
- imx_dma_config_burstlen(imxdmac->imxdma_channel, imxdmac->watermark_level);
+ imx_dma_config_burstlen(imxdmac->imxdma_channel,
+ imxdmac->watermark_level * imxdmac->word_size);
return 0;
default:
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index b6d1455fa936..1ea47db2ff06 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1105,7 +1105,7 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
}
static int __init sdma_get_firmware(struct sdma_engine *sdma,
- const char *cpu_name, int to_version)
+ const char *fw_name)
{
const struct firmware *fw;
char *fwname;
@@ -1114,7 +1114,7 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
const struct sdma_script_start_addrs *addr;
unsigned short *ram_code;
- fwname = kasprintf(GFP_KERNEL, "sdma-%s-to%d.bin", cpu_name, to_version);
+ fwname = kasprintf(GFP_KERNEL, "%s", fw_name);
if (!fwname)
return -ENOMEM;
@@ -1317,7 +1317,7 @@ static int __init sdma_probe(struct platform_device *pdev)
if (pdata->script_addrs)
sdma_add_scripts(sdma, pdata->script_addrs);
- sdma_get_firmware(sdma, pdata->cpu_name, pdata->to_version);
+ sdma_get_firmware(sdma, pdata->fw_name);
sdma->dma_device.dev = &pdev->dev;
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index c1a125e7d1df..fd7d2b308cf2 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 954e334e01bb..06f9f27dbe7c 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1304,8 +1304,7 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
if (!res)
return -ENODEV;
- msp->xor_base = devm_ioremap(&pdev->dev, res->start,
- res->end - res->start + 1);
+ msp->xor_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!msp->xor_base)
return -EBUSY;
@@ -1314,7 +1313,7 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
return -ENODEV;
msp->xor_high_base = devm_ioremap(&pdev->dev, res->start,
- res->end - res->start + 1);
+ resource_size(res));
if (!msp->xor_high_base)
return -EBUSY;
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 8f222d4db7de..29d1addbe0cf 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -6,6 +6,7 @@
* License terms: GNU General Public License (GPL) version 2
*/
+#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index db1df59ae2b6..9a6a274e6925 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -140,7 +140,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
if (of_node_to_nid(np) != priv->node)
continue;
csrow->first_page = r.start >> PAGE_SHIFT;
- csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT;
+ csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
csrow->mtype = MEM_XDR;
csrow->edac_mode = EDAC_SECDED;
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c
index aab970760b75..86ad2eee1201 100644
--- a/drivers/edac/edac_stub.c
+++ b/drivers/edac/edac_stub.c
@@ -14,7 +14,7 @@
*/
#include <linux/module.h>
#include <linux/edac.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/edac.h>
int edac_op_state = EDAC_OPSTATE_INVAL;
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 38ab8e2cd7f4..8af8e864a9cf 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -538,15 +538,15 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op)
/* we only need the error registers */
r.start += 0xe00;
- if (!devm_request_mem_region(&op->dev, r.start,
- r.end - r.start + 1, pdata->name)) {
+ if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
+ pdata->name)) {
printk(KERN_ERR "%s: Error while requesting mem region\n",
__func__);
res = -EBUSY;
goto err;
}
- pdata->l2_vbase = devm_ioremap(&op->dev, r.start, r.end - r.start + 1);
+ pdata->l2_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
if (!pdata->l2_vbase) {
printk(KERN_ERR "%s: Unable to setup L2 err regs\n", __func__);
res = -ENOMEM;
@@ -854,11 +854,11 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci)
mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n");
if (err_detect & DDR_EDE_SBE)
- edac_mc_handle_ce(mci, pfn, err_addr & PAGE_MASK,
+ edac_mc_handle_ce(mci, pfn, err_addr & ~PAGE_MASK,
syndrome, row_index, 0, mci->ctl_name);
if (err_detect & DDR_EDE_MBE)
- edac_mc_handle_ue(mci, pfn, err_addr & PAGE_MASK,
+ edac_mc_handle_ue(mci, pfn, err_addr & ~PAGE_MASK,
row_index, mci->ctl_name);
out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect);
@@ -987,15 +987,15 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op)
goto err;
}
- if (!devm_request_mem_region(&op->dev, r.start,
- r.end - r.start + 1, pdata->name)) {
+ if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
+ pdata->name)) {
printk(KERN_ERR "%s: Error while requesting mem region\n",
__func__);
res = -EBUSY;
goto err;
}
- pdata->mc_vbase = devm_ioremap(&op->dev, r.start, r.end - r.start + 1);
+ pdata->mc_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
if (!pdata->mc_vbase) {
printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
res = -ENOMEM;
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index 0dd0f633b18d..30da70d06a6d 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -45,13 +45,13 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
return 0;
}
-static struct pci_device_id pci_eisa_pci_tbl[] = {
+static struct pci_device_id __initdata pci_eisa_pci_tbl[] = {
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
{ 0, }
};
-static struct pci_driver pci_eisa_driver = {
+static struct pci_driver __initdata pci_eisa_driver = {
.name = "pci_eisa",
.id_table = pci_eisa_pci_tbl,
.probe = pci_eisa_init,
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 29d2423fae6d..85661b060ed7 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -32,7 +32,7 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/byteorder.h>
#include "core.h"
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index b1c11775839c..e6ad3bb6c1a6 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -253,14 +253,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
init_waitqueue_head(&client->wait);
init_waitqueue_head(&client->tx_flush_wait);
INIT_LIST_HEAD(&client->phy_receiver_link);
+ INIT_LIST_HEAD(&client->link);
kref_init(&client->kref);
file->private_data = client;
- mutex_lock(&device->client_list_mutex);
- list_add_tail(&client->link, &device->client_list);
- mutex_unlock(&device->client_list_mutex);
-
return nonseekable_open(inode, file);
}
@@ -451,15 +448,20 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
if (ret != 0)
return -EFAULT;
+ mutex_lock(&client->device->client_list_mutex);
+
client->bus_reset_closure = a->bus_reset_closure;
if (a->bus_reset != 0) {
fill_bus_reset_event(&bus_reset, client);
- if (copy_to_user(u64_to_uptr(a->bus_reset),
- &bus_reset, sizeof(bus_reset)))
- return -EFAULT;
+ ret = copy_to_user(u64_to_uptr(a->bus_reset),
+ &bus_reset, sizeof(bus_reset));
}
+ if (ret == 0 && list_empty(&client->link))
+ list_add_tail(&client->link, &client->device->client_list);
- return 0;
+ mutex_unlock(&client->device->client_list_mutex);
+
+ return ret ? -EFAULT : 0;
}
static int add_client_resource(struct client *client,
@@ -1583,7 +1585,7 @@ static int dispatch_ioctl(struct client *client,
if (_IOC_TYPE(cmd) != '#' ||
_IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
_IOC_SIZE(cmd) > sizeof(buffer))
- return -EINVAL;
+ return -ENOTTY;
if (_IOC_DIR(cmd) == _IOC_READ)
memset(&buffer, 0, _IOC_SIZE(cmd));
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 95a471401892..8ba7f7928f1f 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -38,7 +38,7 @@
#include <linux/string.h>
#include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/byteorder.h>
#include <asm/system.h>
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index 193ed9233144..94d3b494ddfb 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -29,7 +29,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/byteorder.h>
#include <asm/system.h>
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 0fe4e4e6eda7..b45be5767529 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -9,7 +9,7 @@
#include <linux/slab.h>
#include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
struct device;
struct fw_card;
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index b9762d07198d..03a7a85d0424 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -7,6 +7,7 @@
*/
#include <linux/bug.h>
+#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/ethtool.h>
@@ -73,7 +74,7 @@ struct rfc2734_arp {
__be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
__be32 sip; /* Sender's IP Address */
__be32 tip; /* IP Address of requested hw addr */
-} __attribute__((packed));
+} __packed;
/* This header format is specific to this driver implementation. */
#define FWNET_ALEN 8
@@ -81,7 +82,7 @@ struct rfc2734_arp {
struct fwnet_header {
u8 h_dest[FWNET_ALEN]; /* destination address */
__be16 h_proto; /* packet type ID field */
-} __attribute__((packed));
+} __packed;
/* IPv4 and IPv6 encapsulation header */
struct rfc2734_header {
@@ -261,16 +262,16 @@ static int fwnet_header_rebuild(struct sk_buff *skb)
}
static int fwnet_header_cache(const struct neighbour *neigh,
- struct hh_cache *hh)
+ struct hh_cache *hh, __be16 type)
{
struct net_device *net;
struct fwnet_header *h;
- if (hh->hh_type == cpu_to_be16(ETH_P_802_3))
+ if (type == cpu_to_be16(ETH_P_802_3))
return -1;
net = neigh->dev;
h = (struct fwnet_header *)((u8 *)hh->hh_data + 16 - sizeof(*h));
- h->h_proto = hh->hh_type;
+ h->h_proto = type;
memcpy(h->h_dest, neigh->ha, net->addr_len);
hh->hh_len = FWNET_HLEN;
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 0618145376ad..763626b739d1 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -37,7 +37,7 @@
#include <linux/uaccess.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/byteorder.h>
#include "nosy.h"
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index ebb897329c1e..bcf792fac442 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -253,7 +253,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
#define OHCI1394_REGISTER_SIZE 0x800
-#define OHCI_LOOP_COUNT 500
#define OHCI1394_PCI_HCI_Control 0x40
#define SELF_ID_BUF_SIZE 0x800
#define OHCI_TCODE_PHY_PACKET 0x0e
@@ -514,6 +513,12 @@ static inline void flush_writes(const struct fw_ohci *ohci)
reg_read(ohci, OHCI1394_Version);
}
+/*
+ * Beware! read_phy_reg(), write_phy_reg(), update_phy_reg(), and
+ * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex.
+ * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg()
+ * directly. Exceptions are intrinsically serialized contexts like pci_probe.
+ */
static int read_phy_reg(struct fw_ohci *ohci, int addr)
{
u32 val;
@@ -522,6 +527,9 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr)
reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
for (i = 0; i < 3 + 100; i++) {
val = reg_read(ohci, OHCI1394_PhyControl);
+ if (!~val)
+ return -ENODEV; /* Card was ejected. */
+
if (val & OHCI1394_PhyControl_ReadDone)
return OHCI1394_PhyControl_ReadData(val);
@@ -545,6 +553,9 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
OHCI1394_PhyControl_Write(addr, val));
for (i = 0; i < 3 + 100; i++) {
val = reg_read(ohci, OHCI1394_PhyControl);
+ if (!~val)
+ return -ENODEV; /* Card was ejected. */
+
if (!(val & OHCI1394_PhyControl_WritePending))
return 0;
@@ -630,7 +641,6 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
ctx->last_buffer_index = index;
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
- flush_writes(ctx->ohci);
}
static void ar_context_release(struct ar_context *ctx)
@@ -1002,7 +1012,6 @@ static void ar_context_run(struct ar_context *ctx)
reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1);
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
- flush_writes(ctx->ohci);
}
static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
@@ -1202,14 +1211,14 @@ static void context_stop(struct context *ctx)
reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
ctx->running = false;
- flush_writes(ctx->ohci);
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 1000; i++) {
reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
if ((reg & CONTEXT_ACTIVE) == 0)
return;
- mdelay(1);
+ if (i)
+ udelay(10);
}
fw_error("Error: DMA context still active (0x%08x)\n", reg);
}
@@ -1346,12 +1355,10 @@ static int at_context_queue_packet(struct context *ctx,
context_append(ctx, d, z, 4 - z);
- if (ctx->running) {
+ if (ctx->running)
reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
- flush_writes(ohci);
- } else {
+ else
context_run(ctx, 0);
- }
return 0;
}
@@ -1960,14 +1967,18 @@ static irqreturn_t irq_handler(int irq, void *data)
static int software_reset(struct fw_ohci *ohci)
{
+ u32 val;
int i;
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
+ for (i = 0; i < 500; i++) {
+ val = reg_read(ohci, OHCI1394_HCControlSet);
+ if (!~val)
+ return -ENODEV; /* Card was ejected. */
- for (i = 0; i < OHCI_LOOP_COUNT; i++) {
- if ((reg_read(ohci, OHCI1394_HCControlSet) &
- OHCI1394_HCControl_softReset) == 0)
+ if (!(val & OHCI1394_HCControl_softReset))
return 0;
+
msleep(1);
}
@@ -2197,7 +2208,9 @@ static int ohci_enable(struct fw_card *card,
OHCI1394_LinkControl_rcvPhyPkt);
ar_context_run(&ohci->ar_request_ctx);
- ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */
+ ar_context_run(&ohci->ar_response_ctx);
+
+ flush_writes(ohci);
/* We are ready to go, reset bus to finish initialization. */
fw_schedule_bus_reset(&ohci->card, false, true);
@@ -3129,7 +3142,6 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base)
&container_of(base, struct iso_context, base)->context;
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
- flush_writes(ctx->ohci);
}
static const struct fw_card_driver ohci_driver = {
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index fa7f0b3e81dd..68810fd1a59d 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -869,8 +869,6 @@ static __init int gsmi_init(void)
goto out_err;
}
- printk(KERN_INFO "gsmi version " DRIVER_VERSION " loaded\n");
-
/* Register in the firmware directory */
ret = -ENOMEM;
gsmi_kobj = kobject_create_and_add("gsmi", firmware_kobj);
@@ -890,12 +888,13 @@ static __init int gsmi_init(void)
ret = sysfs_create_files(gsmi_kobj, gsmi_attrs);
if (ret) {
printk(KERN_INFO "gsmi: Failed to add attrs");
- goto out_err;
+ goto out_remove_bin_file;
}
- if (register_efivars(&efivars, &efivar_ops, gsmi_kobj)) {
+ ret = register_efivars(&efivars, &efivar_ops, gsmi_kobj);
+ if (ret) {
printk(KERN_INFO "gsmi: Failed to register efivars\n");
- goto out_err;
+ goto out_remove_sysfs_files;
}
register_reboot_notifier(&gsmi_reboot_notifier);
@@ -903,9 +902,15 @@ static __init int gsmi_init(void)
atomic_notifier_chain_register(&panic_notifier_list,
&gsmi_panic_notifier);
+ printk(KERN_INFO "gsmi version " DRIVER_VERSION " loaded\n");
+
return 0;
- out_err:
+out_remove_sysfs_files:
+ sysfs_remove_files(gsmi_kobj, gsmi_attrs);
+out_remove_bin_file:
+ sysfs_remove_bin_file(gsmi_kobj, &eventlog_bin_attr);
+out_err:
kobject_put(gsmi_kobj);
gsmi_buf_free(gsmi_dev.param_buf);
gsmi_buf_free(gsmi_dev.data_buf);
@@ -925,6 +930,8 @@ static void __exit gsmi_exit(void)
&gsmi_panic_notifier);
unregister_efivars(&efivars);
+ sysfs_remove_files(gsmi_kobj, gsmi_attrs);
+ sysfs_remove_bin_file(gsmi_kobj, &eventlog_bin_attr);
kobject_put(gsmi_kobj);
gsmi_buf_free(gsmi_dev.param_buf);
gsmi_buf_free(gsmi_dev.data_buf);
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index ce33f4626957..c811cb107904 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -566,6 +566,11 @@ static mode_t __init ibft_check_initiator_for(void *data, int type)
return rc;
}
+static void ibft_kobj_release(void *data)
+{
+ kfree(data);
+}
+
/*
* Helper function for ibft_register_kobjects.
*/
@@ -595,7 +600,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
ibft_kobj,
ibft_attr_show_initiator,
- ibft_check_initiator_for);
+ ibft_check_initiator_for,
+ ibft_kobj_release);
if (!boot_kobj) {
rc = -ENOMEM;
goto free_ibft_obj;
@@ -610,7 +616,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
ibft_kobj,
ibft_attr_show_nic,
- ibft_check_nic_for);
+ ibft_check_nic_for,
+ ibft_kobj_release);
if (!boot_kobj) {
rc = -ENOMEM;
goto free_ibft_obj;
@@ -625,7 +632,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
ibft_kobj,
ibft_attr_show_target,
- ibft_check_tgt_for);
+ ibft_check_tgt_for,
+ ibft_kobj_release);
if (!boot_kobj) {
rc = -ENOMEM;
goto free_ibft_obj;
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
index c19cd2c39fa6..f10fc521951b 100644
--- a/drivers/firmware/sigma.c
+++ b/drivers/firmware/sigma.c
@@ -11,6 +11,7 @@
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include <linux/sigma.h>
/* Return: 0==OK, <0==error, =1 ==no more actions */
@@ -113,3 +114,5 @@ int process_sigma_firmware(struct i2c_client *client, const char *name)
return ret;
}
EXPORT_SYMBOL(process_sigma_firmware);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2967002a9f82..363498697c2c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -63,33 +63,58 @@ config GPIO_SYSFS
Kernel drivers may also request that a particular GPIO be
exported to userspace; this can be useful when debugging.
+config GPIO_GENERIC
+ tristate
+
# put drivers in the right section, in alphabetical order
+config GPIO_DA9052
+ tristate "Dialog DA9052 GPIO"
+ depends on PMIC_DA9052
+ help
+ Say yes here to enable the GPIO driver for the DA9052 chip.
+
config GPIO_MAX730X
tristate
comment "Memory mapped GPIO drivers:"
-config GPIO_BASIC_MMIO_CORE
- tristate
- help
- Provides core functionality for basic memory-mapped GPIO controllers.
-
-config GPIO_BASIC_MMIO
- tristate "Basic memory-mapped GPIO controllers support"
- select GPIO_BASIC_MMIO_CORE
+config GPIO_GENERIC_PLATFORM
+ tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
+ select GPIO_GENERIC
help
- Say yes here to support basic memory-mapped GPIO controllers.
+ Say yes here to support basic platform_device memory-mapped GPIO controllers.
config GPIO_IT8761E
tristate "IT8761E GPIO support"
help
Say yes here to support GPIO functionality of IT8761E super I/O chip.
+config GPIO_EP93XX
+ def_bool y
+ depends on ARCH_EP93XX
+ select GPIO_GENERIC
+
config GPIO_EXYNOS4
def_bool y
depends on CPU_EXYNOS4210
+config GPIO_MPC5200
+ def_bool y
+ depends on PPC_MPC52xx
+
+config GPIO_MXC
+ def_bool y
+ depends on ARCH_MXC
+ select GPIO_GENERIC
+ select GENERIC_IRQ_CHIP
+
+config GPIO_MXS
+ def_bool y
+ depends on ARCH_MXS
+ select GPIO_GENERIC
+ select GENERIC_IRQ_CHIP
+
config GPIO_PLAT_SAMSUNG
def_bool y
depends on SAMSUNG_GPIOLIB_4BIT
@@ -137,9 +162,6 @@ config GPIO_SCH
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
- This driver can also be built as a module. If so, the module
- will be called sch-gpio.
-
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
depends on MFD_SUPPORT && PCI
@@ -202,9 +224,6 @@ config GPIO_PCA953X
16 bits: pca9535, pca9539, pca9555, tca6416
- This driver can also be built as a module. If so, the module
- will be called pca953x.
-
config GPIO_PCA953X_IRQ
bool "Interrupt controller support for PCA953x"
depends on GPIO_PCA953X=y
@@ -296,17 +315,12 @@ config GPIO_ADP5520
This option enables support for on-chip GPIO found
on Analog Devices ADP5520 PMICs.
- To compile this driver as a module, choose M here: the module will
- be called adp5520-gpio.
-
config GPIO_ADP5588
tristate "ADP5588 I2C GPIO expander"
depends on I2C
help
This option enables support for 18 GPIOs found
on Analog Devices ADP5588 GPIO Expanders.
- To compile this driver as a module, choose M here: the module will be
- called adp5588-gpio.
config GPIO_ADP5588_IRQ
bool "Interrupt controller support for ADP5588"
@@ -398,10 +412,11 @@ config GPIO_MAX7301
GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
config GPIO_MCP23S08
- tristate "Microchip MCP23Sxx I/O expander"
- depends on SPI_MASTER
+ tristate "Microchip MCP23xxx I/O expander"
+ depends on SPI_MASTER || I2C
help
- SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders.
+ SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
+ I/O expanders.
This provides a GPIO interface supporting inputs and outputs.
config GPIO_MC33880
@@ -428,9 +443,6 @@ config GPIO_UCB1400
This enables support for the Philips UCB1400 GPIO pins.
The UCB1400 is an AC97 audio codec.
- To compile this driver as a module, choose M here: the
- module will be called ucb1400_gpio.
-
comment "MODULbus GPIO expanders:"
config GPIO_JANZ_TTL
@@ -441,7 +453,7 @@ config GPIO_JANZ_TTL
This driver provides support for driving the pins in output
mode only. Input mode is not supported.
-config AB8500_GPIO
+config GPIO_AB8500
bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions"
depends on AB8500_CORE && BROKEN
help
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b605f8ec6fbe..720711251391 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,47 +4,56 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += gpiolib.o
-obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o
-obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
-obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o
-obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o
+# Device drivers. Generally keep list sorted alphabetically
+obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
+
+obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
+obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
+obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
+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_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_GPIO_LANGWELL) += gpio-langwell.o
+obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
+obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
+obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
+obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o
+obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
+obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
+obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
+obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
+obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
+obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
+obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
+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_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_GPIO_LANGWELL) += langwell_gpio.o
-obj-$(CONFIG_GPIO_MAX730X) += max730x.o
-obj-$(CONFIG_GPIO_MAX7300) += max7300.o
-obj-$(CONFIG_GPIO_MAX7301) += max7301.o
-obj-$(CONFIG_GPIO_MAX732X) += max732x.o
-obj-$(CONFIG_GPIO_MC33880) += mc33880.o
-obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
-obj-$(CONFIG_GPIO_74X164) += 74x164.o
-obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
-obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
-obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
-obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
-obj-$(CONFIG_GPIO_PL061) += pl061.o
-obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
-obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o
-obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
-obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
-obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
-obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
-obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o
-obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
-obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o
-obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
-obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
-obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
-obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o
-obj-$(CONFIG_GPIO_SCH) += sch_gpio.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_GPIO_TPS65910) += gpio-tps65910.o
+obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_MACH_U300) += gpio-u300.o
-obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
-obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o
-obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o
-obj-$(CONFIG_GPIO_SX150X) += sx150x.o
-obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
-obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o
-obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o
-obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o
+obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
+obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
+obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
+obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
+obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
+obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
+obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
diff --git a/drivers/gpio/74x164.c b/drivers/gpio/gpio-74x164.c
index 84e070219839..ff525c0958dd 100644
--- a/drivers/gpio/74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -16,9 +16,6 @@
#include <linux/gpio.h>
#include <linux/slab.h>
-#define GEN_74X164_GPIO_COUNT 8
-
-
struct gen_74x164_chip {
struct spi_device *spi;
struct gpio_chip gpio_chip;
@@ -26,9 +23,7 @@ struct gen_74x164_chip {
u8 port_config;
};
-static void gen_74x164_set_value(struct gpio_chip *, unsigned, int);
-
-static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc)
+static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
{
return container_of(gc, struct gen_74x164_chip, gpio_chip);
}
@@ -39,16 +34,9 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
&chip->port_config, sizeof(chip->port_config));
}
-static int gen_74x164_direction_output(struct gpio_chip *gc,
- unsigned offset, int val)
-{
- gen_74x164_set_value(gc, offset, val);
- return 0;
-}
-
static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
{
- struct gen_74x164_chip *chip = gpio_to_chip(gc);
+ struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
int ret;
mutex_lock(&chip->lock);
@@ -61,7 +49,7 @@ static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
static void gen_74x164_set_value(struct gpio_chip *gc,
unsigned offset, int val)
{
- struct gen_74x164_chip *chip = gpio_to_chip(gc);
+ struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
mutex_lock(&chip->lock);
if (val)
@@ -73,6 +61,13 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
mutex_unlock(&chip->lock);
}
+static int gen_74x164_direction_output(struct gpio_chip *gc,
+ unsigned offset, int val)
+{
+ gen_74x164_set_value(gc, offset, val);
+ return 0;
+}
+
static int __devinit gen_74x164_probe(struct spi_device *spi)
{
struct gen_74x164_chip *chip;
@@ -104,12 +99,12 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
chip->spi = spi;
- chip->gpio_chip.label = GEN_74X164_DRIVER_NAME,
- chip->gpio_chip.direction_output = gen_74x164_direction_output;
+ chip->gpio_chip.label = spi->modalias;
+ chip->gpio_chip.direction_output = gen_74x164_direction_output;
chip->gpio_chip.get = gen_74x164_get_value;
chip->gpio_chip.set = gen_74x164_set_value;
chip->gpio_chip.base = pdata->base;
- chip->gpio_chip.ngpio = GEN_74X164_GPIO_COUNT;
+ chip->gpio_chip.ngpio = 8;
chip->gpio_chip.can_sleep = 1;
chip->gpio_chip.dev = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE;
@@ -157,7 +152,7 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
static struct spi_driver gen_74x164_driver = {
.driver = {
- .name = GEN_74X164_DRIVER_NAME,
+ .name = "74x164",
.owner = THIS_MODULE,
},
.probe = gen_74x164_probe,
diff --git a/drivers/gpio/ab8500-gpio.c b/drivers/gpio/gpio-ab8500.c
index 970053c89ff7..ed795e64eea7 100644
--- a/drivers/gpio/ab8500-gpio.c
+++ b/drivers/gpio/gpio-ab8500.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
diff --git a/drivers/gpio/adp5520-gpio.c b/drivers/gpio/gpio-adp5520.c
index 9f2781537001..9f2781537001 100644
--- a/drivers/gpio/adp5520-gpio.c
+++ b/drivers/gpio/gpio-adp5520.c
diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/gpio-adp5588.c
index 3525ad918771..3525ad918771 100644
--- a/drivers/gpio/adp5588-gpio.c
+++ b/drivers/gpio/gpio-adp5588.c
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/gpio-bt8xx.c
index aa4f09ad3ced..ec57936aef62 100644
--- a/drivers/gpio/bt8xxgpio.c
+++ b/drivers/gpio/gpio-bt8xx.c
@@ -2,7 +2,7 @@
bt8xx GPIO abuser
- Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (C) 2008 Michael Buesch <m@bues.ch>
Please do _only_ contact the people listed _above_ with issues related to this driver.
All the other people listed below are not related to this driver. Their names
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/gpio-cs5535.c
index 6e16cba56ad2..6e16cba56ad2 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/gpio-cs5535.c
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
new file mode 100644
index 000000000000..038f5eb8b13d
--- /dev/null
+++ b/drivers/gpio/gpio-da9052.c
@@ -0,0 +1,277 @@
+/*
+ * GPIO Driver for Dialog DA9052 PMICs.
+ *
+ * Copyright(c) 2011 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/syscalls.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/reg.h>
+#include <linux/mfd/da9052/pdata.h>
+#include <linux/mfd/da9052/gpio.h>
+
+#define DA9052_INPUT 1
+#define DA9052_OUTPUT_OPENDRAIN 2
+#define DA9052_OUTPUT_PUSHPULL 3
+
+#define DA9052_SUPPLY_VDD_IO1 0
+
+#define DA9052_DEBOUNCING_OFF 0
+#define DA9052_DEBOUNCING_ON 1
+
+#define DA9052_OUTPUT_LOWLEVEL 0
+
+#define DA9052_ACTIVE_LOW 0
+#define DA9052_ACTIVE_HIGH 1
+
+#define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8
+#define DA9052_GPIO_SHIFT_COUNT(no) (no%8)
+#define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0
+#define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F
+#define DA9052_GPIO_NIBBLE_SHIFT 4
+
+struct da9052_gpio {
+ struct da9052 *da9052;
+ struct gpio_chip gp;
+};
+
+static inline struct da9052_gpio *to_da9052_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct da9052_gpio, gp);
+}
+
+static unsigned char da9052_gpio_port_odd(unsigned offset)
+{
+ return offset % 2;
+}
+
+static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+ struct da9052_gpio *gpio = to_da9052_gpio(gc);
+ int da9052_port_direction = 0;
+ int ret;
+
+ ret = da9052_reg_read(gpio->da9052,
+ DA9052_GPIO_0_1_REG + (offset >> 1));
+ if (ret < 0)
+ return ret;
+
+ if (da9052_gpio_port_odd(offset)) {
+ da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN;
+ da9052_port_direction >>= 4;
+ } else {
+ da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN;
+ }
+
+ switch (da9052_port_direction) {
+ case DA9052_INPUT:
+ if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
+ ret = da9052_reg_read(gpio->da9052,
+ DA9052_STATUS_C_REG);
+ else
+ ret = da9052_reg_read(gpio->da9052,
+ DA9052_STATUS_D_REG);
+ if (ret < 0)
+ return ret;
+ if (ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset)))
+ return 1;
+ else
+ return 0;
+ case DA9052_OUTPUT_PUSHPULL:
+ if (da9052_gpio_port_odd(offset))
+ return ret & DA9052_GPIO_ODD_PORT_MODE;
+ else
+ return ret & DA9052_GPIO_EVEN_PORT_MODE;
+ default:
+ return -EINVAL;
+ }
+}
+
+static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+ struct da9052_gpio *gpio = to_da9052_gpio(gc);
+ unsigned char register_value = 0;
+ int ret;
+
+ if (da9052_gpio_port_odd(offset)) {
+ if (value) {
+ register_value = DA9052_GPIO_ODD_PORT_MODE;
+ ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+ DA9052_GPIO_0_1_REG,
+ DA9052_GPIO_ODD_PORT_MODE,
+ register_value);
+ if (ret != 0)
+ dev_err(gpio->da9052->dev,
+ "Failed to updated gpio odd reg,%d",
+ ret);
+ }
+ } else {
+ if (value) {
+ register_value = DA9052_GPIO_EVEN_PORT_MODE;
+ ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+ DA9052_GPIO_0_1_REG,
+ DA9052_GPIO_EVEN_PORT_MODE,
+ register_value);
+ if (ret != 0)
+ dev_err(gpio->da9052->dev,
+ "Failed to updated gpio even reg,%d",
+ ret);
+ }
+ }
+}
+
+static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+ struct da9052_gpio *gpio = to_da9052_gpio(gc);
+ unsigned char register_value;
+ int ret;
+
+ /* Format: function - 2 bits type - 1 bit mode - 1 bit */
+ register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 |
+ DA9052_DEBOUNCING_ON << 3;
+
+ if (da9052_gpio_port_odd(offset))
+ ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+ DA9052_GPIO_0_1_REG,
+ DA9052_GPIO_MASK_UPPER_NIBBLE,
+ (register_value <<
+ DA9052_GPIO_NIBBLE_SHIFT));
+ else
+ ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+ DA9052_GPIO_0_1_REG,
+ DA9052_GPIO_MASK_LOWER_NIBBLE,
+ register_value);
+
+ return ret;
+}
+
+static int da9052_gpio_direction_output(struct gpio_chip *gc,
+ unsigned offset, int value)
+{
+ struct da9052_gpio *gpio = to_da9052_gpio(gc);
+ unsigned char register_value;
+ int ret;
+
+ /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */
+ register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 |
+ value << 3;
+
+ if (da9052_gpio_port_odd(offset))
+ ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+ DA9052_GPIO_0_1_REG,
+ DA9052_GPIO_MASK_UPPER_NIBBLE,
+ (register_value <<
+ DA9052_GPIO_NIBBLE_SHIFT));
+ else
+ ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+ DA9052_GPIO_0_1_REG,
+ DA9052_GPIO_MASK_LOWER_NIBBLE,
+ register_value);
+
+ return ret;
+}
+
+static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+{
+ struct da9052_gpio *gpio = to_da9052_gpio(gc);
+ struct da9052 *da9052 = gpio->da9052;
+
+ return da9052->irq_base + DA9052_IRQ_GPI0 + offset;
+}
+
+static struct gpio_chip reference_gp __devinitdata = {
+ .label = "da9052-gpio",
+ .owner = THIS_MODULE,
+ .get = da9052_gpio_get,
+ .set = da9052_gpio_set,
+ .direction_input = da9052_gpio_direction_input,
+ .direction_output = da9052_gpio_direction_output,
+ .to_irq = da9052_gpio_to_irq,
+ .can_sleep = 1;
+ .ngpio = 16;
+ .base = -1;
+};
+
+static int __devinit da9052_gpio_probe(struct platform_device *pdev)
+{
+ struct da9052_gpio *gpio;
+ struct da9052_pdata *pdata;
+ int ret;
+
+ gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
+ if (gpio == NULL)
+ return -ENOMEM;
+
+ gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
+ pdata = gpio->da9052->dev->platform_data;
+
+ gpio->gp = reference_gp;
+ if (pdata && pdata->gpio_base)
+ gpio->gp.base = pdata->gpio_base;
+
+ ret = gpiochip_add(&gpio->gp);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+ goto err_mem;
+ }
+
+ platform_set_drvdata(pdev, gpio);
+
+ return 0;
+
+err_mem:
+ kfree(gpio);
+ return ret;
+}
+
+static int __devexit da9052_gpio_remove(struct platform_device *pdev)
+{
+ struct da9052_gpio *gpio = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = gpiochip_remove(&gpio->gp);
+ if (ret == 0)
+ kfree(gpio);
+
+ return ret;
+}
+
+static struct platform_driver da9052_gpio_driver = {
+ .probe = da9052_gpio_probe,
+ .remove = __devexit_p(da9052_gpio_remove),
+ .driver = {
+ .name = "da9052-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init da9052_gpio_init(void)
+{
+ return platform_driver_register(&da9052_gpio_driver);
+}
+module_init(da9052_gpio_init);
+
+static void __exit da9052_gpio_exit(void)
+{
+ return platform_driver_unregister(&da9052_gpio_driver);
+}
+module_exit(da9052_gpio_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9052-gpio");
diff --git a/arch/arm/mach-ep93xx/gpio.c b/drivers/gpio/gpio-ep93xx.c
index 415dce37b88c..72fb9c665320 100644
--- a/arch/arm/mach-ep93xx/gpio.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -1,9 +1,8 @@
/*
- * linux/arch/arm/mach-ep93xx/gpio.c
- *
* Generic EP93xx GPIO handling
*
- * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com>
+ * Copyright (c) 2008 Ryan Mallon
+ * Copyright (c) 2011 H Hartley Sweeten <hsweeten@visionengravers.com>
*
* Based on code originally from:
* linux/arch/arm/mach-ep93xx/core.c
@@ -13,17 +12,23 @@
* published by the Free Software Foundation.
*/
-#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/seq_file.h>
+#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/basic_mmio_gpio.h>
#include <mach/hardware.h>
+struct ep93xx_gpio {
+ void __iomem *mmio_base;
+ struct bgpio_chip bgc[8];
+};
+
/*************************************************************************
* Interrupt handling for EP93xx on-chip GPIOs
*************************************************************************/
@@ -225,7 +230,7 @@ static struct irq_chip ep93xx_gpio_irq_chip = {
.irq_set_type = ep93xx_gpio_irq_type,
};
-void __init ep93xx_gpio_init_irq(void)
+static void ep93xx_gpio_init_irq(void)
{
int gpio_irq;
@@ -260,151 +265,141 @@ void __init ep93xx_gpio_init_irq(void)
/*************************************************************************
* gpiolib interface for EP93xx on-chip GPIOs
*************************************************************************/
-struct ep93xx_gpio_chip {
- struct gpio_chip chip;
-
- void __iomem *data_reg;
- void __iomem *data_dir_reg;
+struct ep93xx_gpio_bank {
+ const char *label;
+ int data;
+ int dir;
+ int base;
+ bool has_debounce;
};
-#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
+#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _debounce) \
+ { \
+ .label = _label, \
+ .data = _data, \
+ .dir = _dir, \
+ .base = _base, \
+ .has_debounce = _debounce, \
+ }
+
+static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
+ EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true),
+ EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true),
+ EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false),
+ EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false),
+ EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false),
+ EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true),
+ EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false),
+ EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
+};
-static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
+ unsigned offset, unsigned debounce)
{
- struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
- unsigned long flags;
- u8 v;
+ int gpio = chip->base + offset;
+ int irq = gpio_to_irq(gpio);
+
+ if (irq < 0)
+ return -EINVAL;
- local_irq_save(flags);
- v = __raw_readb(ep93xx_chip->data_dir_reg);
- v &= ~(1 << offset);
- __raw_writeb(v, ep93xx_chip->data_dir_reg);
- local_irq_restore(flags);
+ ep93xx_gpio_int_debounce(irq, debounce ? true : false);
return 0;
}
-static int ep93xx_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int val)
+static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
+ void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
{
- struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
- unsigned long flags;
- int line;
- u8 v;
+ void __iomem *data = mmio_base + bank->data;
+ void __iomem *dir = mmio_base + bank->dir;
+ int err;
- local_irq_save(flags);
+ err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false);
+ if (err)
+ return err;
- /* Set the value */
- v = __raw_readb(ep93xx_chip->data_reg);
- if (val)
- v |= (1 << offset);
- else
- v &= ~(1 << offset);
- __raw_writeb(v, ep93xx_chip->data_reg);
-
- /* Drive as an output */
- line = chip->base + offset;
- if (line <= EP93XX_GPIO_LINE_MAX_IRQ) {
- /* Ports A/B/F */
- ep93xx_gpio_int_mask(line);
- ep93xx_gpio_update_int_params(line >> 3);
- }
+ bgc->gc.label = bank->label;
+ bgc->gc.base = bank->base;
- v = __raw_readb(ep93xx_chip->data_dir_reg);
- v |= (1 << offset);
- __raw_writeb(v, ep93xx_chip->data_dir_reg);
+ if (bank->has_debounce)
+ bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
- local_irq_restore(flags);
-
- return 0;
+ return gpiochip_add(&bgc->gc);
}
-static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
{
- struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
+ struct ep93xx_gpio *ep93xx_gpio;
+ struct resource *res;
+ void __iomem *mmio;
+ int i;
+ int ret;
- return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset));
-}
+ ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
+ if (!ep93xx_gpio)
+ return -ENOMEM;
-static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
- struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
- unsigned long flags;
- u8 v;
-
- local_irq_save(flags);
- v = __raw_readb(ep93xx_chip->data_reg);
- if (val)
- v |= (1 << offset);
- else
- v &= ~(1 << offset);
- __raw_writeb(v, ep93xx_chip->data_reg);
- local_irq_restore(flags);
-}
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENXIO;
+ goto exit_free;
+ }
-static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
- unsigned offset, unsigned debounce)
-{
- int gpio = chip->base + offset;
- int irq = gpio_to_irq(gpio);
+ if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+ ret = -EBUSY;
+ goto exit_free;
+ }
- if (irq < 0)
- return -EINVAL;
+ mmio = ioremap(res->start, resource_size(res));
+ if (!mmio) {
+ ret = -ENXIO;
+ goto exit_release;
+ }
+ ep93xx_gpio->mmio_base = mmio;
- ep93xx_gpio_int_debounce(irq, debounce ? true : false);
+ /* Default all ports to GPIO */
+ ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+ EP93XX_SYSCON_DEVCFG_GONK |
+ EP93XX_SYSCON_DEVCFG_EONIDE |
+ EP93XX_SYSCON_DEVCFG_GONIDE |
+ EP93XX_SYSCON_DEVCFG_HONIDE);
- return 0;
-}
+ for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
+ struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
+ struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
-#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \
- { \
- .chip = { \
- .label = name, \
- .direction_input = ep93xx_gpio_direction_input, \
- .direction_output = ep93xx_gpio_direction_output, \
- .get = ep93xx_gpio_get, \
- .set = ep93xx_gpio_set, \
- .base = base_gpio, \
- .ngpio = 8, \
- }, \
- .data_reg = EP93XX_GPIO_REG(dr), \
- .data_dir_reg = EP93XX_GPIO_REG(ddr), \
+ if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
+ dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
+ bank->label);
}
-static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = {
- EP93XX_GPIO_BANK("A", 0x00, 0x10, 0),
- EP93XX_GPIO_BANK("B", 0x04, 0x14, 8),
- EP93XX_GPIO_BANK("C", 0x08, 0x18, 40),
- EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24),
- EP93XX_GPIO_BANK("E", 0x20, 0x24, 32),
- EP93XX_GPIO_BANK("F", 0x30, 0x34, 16),
- EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48),
- EP93XX_GPIO_BANK("H", 0x40, 0x44, 56),
-};
+ ep93xx_gpio_init_irq();
-void __init ep93xx_gpio_init(void)
-{
- int i;
+ return 0;
- /* Set Ports C, D, E, G, and H for GPIO use */
- ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
- EP93XX_SYSCON_DEVCFG_GONK |
- EP93XX_SYSCON_DEVCFG_EONIDE |
- EP93XX_SYSCON_DEVCFG_GONIDE |
- EP93XX_SYSCON_DEVCFG_HONIDE);
+exit_release:
+ release_mem_region(res->start, resource_size(res));
+exit_free:
+ kfree(ep93xx_gpio);
+ dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret);
+ return ret;
+}
- for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
- struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip;
-
- /*
- * Ports A, B, and F support input debouncing when
- * used as interrupts.
- */
- if (!strcmp(chip->label, "A") ||
- !strcmp(chip->label, "B") ||
- !strcmp(chip->label, "F"))
- chip->set_debounce = ep93xx_gpio_set_debounce;
-
- gpiochip_add(chip);
- }
+static struct platform_driver ep93xx_gpio_driver = {
+ .driver = {
+ .name = "gpio-ep93xx",
+ .owner = THIS_MODULE,
+ },
+ .probe = ep93xx_gpio_probe,
+};
+
+static int __init ep93xx_gpio_init(void)
+{
+ return platform_driver_register(&ep93xx_gpio_driver);
}
+postcore_initcall(ep93xx_gpio_init);
+
+MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com> "
+ "H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_DESCRIPTION("EP93XX GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
index 9029835112e7..d24b337cf1ac 100644
--- a/drivers/gpio/gpio-exynos4.c
+++ b/drivers/gpio/gpio-exynos4.c
@@ -1,10 +1,9 @@
-/* linux/arch/arm/mach-exynos4/gpiolib.c
+/*
+ * EXYNOS4 - GPIOlib support
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * EXYNOS4 - GPIOlib 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.
diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/gpio-generic.c
index 8152e9f516b0..231714def4d2 100644
--- a/drivers/gpio/basic_mmio_gpio.c
+++ b/drivers/gpio/gpio-generic.c
@@ -1,5 +1,5 @@
/*
- * Driver for basic memory-mapped GPIO controllers.
+ * Generic driver for memory-mapped GPIO controllers.
*
* Copyright 2008 MontaVista Software, Inc.
* Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
@@ -404,7 +404,7 @@ int __devinit bgpio_init(struct bgpio_chip *bgc,
}
EXPORT_SYMBOL_GPL(bgpio_init);
-#ifdef CONFIG_GPIO_BASIC_MMIO
+#ifdef CONFIG_GPIO_GENERIC_PLATFORM
static void __iomem *bgpio_map(struct platform_device *pdev,
const char *name,
@@ -541,7 +541,7 @@ static void __exit bgpio_platform_exit(void)
}
module_exit(bgpio_platform_exit);
-#endif /* CONFIG_GPIO_BASIC_MMIO */
+#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/gpio-it8761e.c
index 48fc43c4bdd1..278b81317010 100644
--- a/drivers/gpio/it8761e_gpio.c
+++ b/drivers/gpio/gpio-it8761e.c
@@ -1,5 +1,5 @@
/*
- * it8761_gpio.c - GPIO interface for IT8761E Super I/O chip
+ * GPIO interface for IT8761E Super I/O chip
*
* Author: Denis Turischev <denis@compulab.co.il>
*
diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
index 813ac077e5d7..813ac077e5d7 100644
--- a/drivers/gpio/janz-ttl.c
+++ b/drivers/gpio/gpio-janz-ttl.c
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/gpio-langwell.c
index 644ba1255d3c..d2eb57c60e0e 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -1,4 +1,6 @@
-/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver
+/*
+ * Moorestown platform Langwell chip GPIO driver
+ *
* Copyright (c) 2008 - 2009, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/max7300.c b/drivers/gpio/gpio-max7300.c
index 962f661c18c7..a5ca0ab1b372 100644
--- a/drivers/gpio/max7300.c
+++ b/drivers/gpio/gpio-max7300.c
@@ -1,6 +1,4 @@
/*
- * drivers/gpio/max7300.c
- *
* Copyright (C) 2009 Wolfram Sang, Pengutronix
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/gpio-max7301.c
index 92a100ddef6b..741acfcbe761 100644
--- a/drivers/gpio/max7301.c
+++ b/drivers/gpio/gpio-max7301.c
@@ -1,6 +1,4 @@
/*
- * drivers/gpio/max7301.c
- *
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
* Copyright (C) 2009 Wolfram Sang, Pengutronix
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/gpio-max730x.c
index 94ce773f95f8..05e2dac60b3b 100644
--- a/drivers/gpio/max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -1,6 +1,4 @@
/**
- * drivers/gpio/max7301.c
- *
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
* Copyright (C) 2009 Wolfram Sang, Pengutronix
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/gpio-max732x.c
index ad6951edc16c..9504120812a5 100644
--- a/drivers/gpio/max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -1,5 +1,5 @@
/*
- * max732x.c - I2C Port Expander with 8/16 I/O
+ * MAX732x I2C Port Expander with 8/16 I/O
*
* Copyright (C) 2007 Marvell International Ltd.
* Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/gpio-mc33880.c
index 4ec797593bdb..b3b4652e89ec 100644
--- a/drivers/gpio/mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -1,5 +1,5 @@
/*
- * mc33880.c MC33880 high-side/low-side switch GPIO driver
+ * MC33880 high-side/low-side switch GPIO driver
* Copyright (c) 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 40e076083ec0..1ef46e6c2a2a 100644
--- a/drivers/gpio/mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -1,12 +1,12 @@
/*
- * mcp23s08.c - SPI gpio expander driver
+ * MCP23S08 SPI/GPIO gpio expander driver
*/
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
+#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/spi/mcp23s08.h>
#include <linux/slab.h>
@@ -17,13 +17,13 @@
*/
#define MCP_TYPE_S08 0
#define MCP_TYPE_S17 1
+#define MCP_TYPE_008 2
+#define MCP_TYPE_017 3
/* Registers are all 8 bits wide.
*
* The mcp23s17 has twice as many bits, and can be configured to work
* with either 16 bit registers or with two adjacent 8 bit banks.
- *
- * Also, there are I2C versions of both chips.
*/
#define MCP_IODIR 0x00 /* init/reset: all ones */
#define MCP_IPOL 0x01
@@ -51,7 +51,6 @@ struct mcp23s08_ops {
};
struct mcp23s08 {
- struct spi_device *spi;
u8 addr;
u16 cache[11];
@@ -60,9 +59,8 @@ struct mcp23s08 {
struct gpio_chip chip;
- struct work_struct work;
-
const struct mcp23s08_ops *ops;
+ void *data; /* ops specific data */
};
/* A given spi_device can represent up to eight mcp23sxx chips
@@ -76,6 +74,74 @@ struct mcp23s08_driver_data {
struct mcp23s08 chip[];
};
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_I2C
+
+static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
+{
+ return i2c_smbus_read_byte_data(mcp->data, reg);
+}
+
+static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+ return i2c_smbus_write_byte_data(mcp->data, reg, val);
+}
+
+static int
+mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+ while (n--) {
+ int ret = mcp23008_read(mcp, reg++);
+ if (ret < 0)
+ return ret;
+ *vals++ = ret;
+ }
+
+ return 0;
+}
+
+static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg)
+{
+ return i2c_smbus_read_word_data(mcp->data, reg << 1);
+}
+
+static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+ return i2c_smbus_write_word_data(mcp->data, reg << 1, val);
+}
+
+static int
+mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+ while (n--) {
+ int ret = mcp23017_read(mcp, reg++);
+ if (ret < 0)
+ return ret;
+ *vals++ = ret;
+ }
+
+ return 0;
+}
+
+static const struct mcp23s08_ops mcp23008_ops = {
+ .read = mcp23008_read,
+ .write = mcp23008_write,
+ .read_regs = mcp23008_read_regs,
+};
+
+static const struct mcp23s08_ops mcp23017_ops = {
+ .read = mcp23017_read,
+ .write = mcp23017_write,
+ .read_regs = mcp23017_read_regs,
+};
+
+#endif /* CONFIG_I2C */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SPI_MASTER
+
static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
{
u8 tx[2], rx[1];
@@ -83,7 +149,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
tx[0] = mcp->addr | 0x01;
tx[1] = reg;
- status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
+ status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
return (status < 0) ? status : rx[0];
}
@@ -94,7 +160,7 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
tx[0] = mcp->addr;
tx[1] = reg;
tx[2] = val;
- return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+ return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
}
static int
@@ -109,7 +175,7 @@ mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
tx[1] = reg;
tmp = (u8 *)vals;
- status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n);
+ status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n);
if (status >= 0) {
while (n--)
vals[n] = tmp[n]; /* expand to 16bit */
@@ -124,7 +190,7 @@ static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
tx[0] = mcp->addr | 0x01;
tx[1] = reg << 1;
- status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
+ status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
return (status < 0) ? status : (rx[0] | (rx[1] << 8));
}
@@ -136,7 +202,7 @@ static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
tx[1] = reg << 1;
tx[2] = val;
tx[3] = val >> 8;
- return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+ return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
}
static int
@@ -150,7 +216,7 @@ mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
tx[0] = mcp->addr | 0x01;
tx[1] = reg << 1;
- status = spi_write_then_read(mcp->spi, tx, sizeof tx,
+ status = spi_write_then_read(mcp->data, tx, sizeof tx,
(u8 *)vals, n * 2);
if (status >= 0) {
while (n--)
@@ -172,6 +238,7 @@ static const struct mcp23s08_ops mcp23s17_ops = {
.read_regs = mcp23s17_read_regs,
};
+#endif /* CONFIG_SPI_MASTER */
/*----------------------------------------------------------------------*/
@@ -299,17 +366,16 @@ done:
/*----------------------------------------------------------------------*/
-static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
+static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
+ void *data, unsigned addr,
unsigned type, unsigned base, unsigned pullups)
{
- struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
- struct mcp23s08 *mcp = data->mcp[addr];
- int status;
+ int status;
mutex_init(&mcp->lock);
- mcp->spi = spi;
- mcp->addr = 0x40 | (addr << 1);
+ mcp->data = data;
+ mcp->addr = addr;
mcp->chip.direction_input = mcp23s08_direction_input;
mcp->chip.get = mcp23s08_get;
@@ -317,18 +383,43 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
mcp->chip.set = mcp23s08_set;
mcp->chip.dbg_show = mcp23s08_dbg_show;
- if (type == MCP_TYPE_S17) {
+ switch (type) {
+#ifdef CONFIG_SPI_MASTER
+ case MCP_TYPE_S08:
+ mcp->ops = &mcp23s08_ops;
+ mcp->chip.ngpio = 8;
+ mcp->chip.label = "mcp23s08";
+ break;
+
+ case MCP_TYPE_S17:
mcp->ops = &mcp23s17_ops;
mcp->chip.ngpio = 16;
mcp->chip.label = "mcp23s17";
- } else {
- mcp->ops = &mcp23s08_ops;
+ break;
+#endif /* CONFIG_SPI_MASTER */
+
+#ifdef CONFIG_I2C
+ case MCP_TYPE_008:
+ mcp->ops = &mcp23008_ops;
mcp->chip.ngpio = 8;
- mcp->chip.label = "mcp23s08";
+ mcp->chip.label = "mcp23008";
+ break;
+
+ case MCP_TYPE_017:
+ mcp->ops = &mcp23017_ops;
+ mcp->chip.ngpio = 16;
+ mcp->chip.label = "mcp23017";
+ break;
+#endif /* CONFIG_I2C */
+
+ default:
+ dev_err(dev, "invalid device type (%d)\n", type);
+ return -EINVAL;
}
+
mcp->chip.base = base;
mcp->chip.can_sleep = 1;
- mcp->chip.dev = &spi->dev;
+ mcp->chip.dev = dev;
mcp->chip.owner = THIS_MODULE;
/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
@@ -374,11 +465,98 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
status = gpiochip_add(&mcp->chip);
fail:
if (status < 0)
- dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
- addr, status);
+ dev_dbg(dev, "can't setup chip %d, --> %d\n",
+ addr, status);
return status;
}
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_I2C
+
+static int __devinit mcp230xx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mcp23s08_platform_data *pdata;
+ struct mcp23s08 *mcp;
+ int status;
+
+ pdata = client->dev.platform_data;
+ if (!pdata || !gpio_is_valid(pdata->base)) {
+ dev_dbg(&client->dev, "invalid or missing platform data\n");
+ return -EINVAL;
+ }
+
+ mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
+ if (!mcp)
+ return -ENOMEM;
+
+ status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,
+ id->driver_data, pdata->base,
+ pdata->chip[0].pullups);
+ if (status)
+ goto fail;
+
+ i2c_set_clientdata(client, mcp);
+
+ return 0;
+
+fail:
+ kfree(mcp);
+
+ return status;
+}
+
+static int __devexit mcp230xx_remove(struct i2c_client *client)
+{
+ struct mcp23s08 *mcp = i2c_get_clientdata(client);
+ int status;
+
+ status = gpiochip_remove(&mcp->chip);
+ if (status == 0)
+ kfree(mcp);
+
+ return status;
+}
+
+static const struct i2c_device_id mcp230xx_id[] = {
+ { "mcp23008", MCP_TYPE_008 },
+ { "mcp23017", MCP_TYPE_017 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, mcp230xx_id);
+
+static struct i2c_driver mcp230xx_driver = {
+ .driver = {
+ .name = "mcp230xx",
+ .owner = THIS_MODULE,
+ },
+ .probe = mcp230xx_probe,
+ .remove = __devexit_p(mcp230xx_remove),
+ .id_table = mcp230xx_id,
+};
+
+static int __init mcp23s08_i2c_init(void)
+{
+ return i2c_add_driver(&mcp230xx_driver);
+}
+
+static void mcp23s08_i2c_exit(void)
+{
+ i2c_del_driver(&mcp230xx_driver);
+}
+
+#else
+
+static int __init mcp23s08_i2c_init(void) { return 0; }
+static void mcp23s08_i2c_exit(void) { }
+
+#endif /* CONFIG_I2C */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SPI_MASTER
+
static int mcp23s08_probe(struct spi_device *spi)
{
struct mcp23s08_platform_data *pdata;
@@ -421,7 +599,8 @@ static int mcp23s08_probe(struct spi_device *spi)
continue;
chips--;
data->mcp[addr] = &data->chip[chips];
- status = mcp23s08_probe_one(spi, addr, type, base,
+ status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
+ 0x40 | (addr << 1), type, base,
pdata->chip[addr].pullups);
if (status < 0)
goto fail;
@@ -435,14 +614,6 @@ static int mcp23s08_probe(struct spi_device *spi)
* handled here...
*/
- if (pdata->setup) {
- status = pdata->setup(spi,
- pdata->base, data->ngpio,
- pdata->context);
- if (status < 0)
- dev_dbg(&spi->dev, "setup --> %d\n", status);
- }
-
return 0;
fail:
@@ -462,20 +633,9 @@ fail:
static int mcp23s08_remove(struct spi_device *spi)
{
struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
- struct mcp23s08_platform_data *pdata = spi->dev.platform_data;
unsigned addr;
int status = 0;
- if (pdata->teardown) {
- status = pdata->teardown(spi,
- pdata->base, data->ngpio,
- pdata->context);
- if (status < 0) {
- dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
- return status;
- }
- }
-
for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
int tmp;
@@ -510,20 +670,53 @@ static struct spi_driver mcp23s08_driver = {
},
};
+static int __init mcp23s08_spi_init(void)
+{
+ return spi_register_driver(&mcp23s08_driver);
+}
+
+static void mcp23s08_spi_exit(void)
+{
+ spi_unregister_driver(&mcp23s08_driver);
+}
+
+#else
+
+static int __init mcp23s08_spi_init(void) { return 0; }
+static void mcp23s08_spi_exit(void) { }
+
+#endif /* CONFIG_SPI_MASTER */
+
/*----------------------------------------------------------------------*/
static int __init mcp23s08_init(void)
{
- return spi_register_driver(&mcp23s08_driver);
+ int ret;
+
+ ret = mcp23s08_spi_init();
+ if (ret)
+ goto spi_fail;
+
+ ret = mcp23s08_i2c_init();
+ if (ret)
+ goto i2c_fail;
+
+ return 0;
+
+ i2c_fail:
+ mcp23s08_spi_exit();
+ spi_fail:
+ return ret;
}
-/* register after spi postcore initcall and before
+/* register after spi/i2c postcore initcall and before
* subsys initcalls that may rely on these GPIOs
*/
subsys_initcall(mcp23s08_init);
static void __exit mcp23s08_exit(void)
{
- spi_unregister_driver(&mcp23s08_driver);
+ mcp23s08_spi_exit();
+ mcp23s08_i2c_exit();
}
module_exit(mcp23s08_exit);
diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/gpio-ml-ioh.c
index 1bc621ac3536..a9016f56ed7e 100644
--- a/drivers/gpio/ml_ioh_gpio.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -233,7 +233,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
return 0;
err_gpiochip_add:
- for (; i != 0; i--) {
+ while (--i >= 0) {
chip--;
ret = gpiochip_remove(&chip->gpio);
if (ret)
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/drivers/gpio/gpio-mpc5200.c
index 1757d1db4b51..52d3ed208105 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+++ b/drivers/gpio/gpio-mpc5200.c
@@ -184,15 +184,13 @@ static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
}
static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
- {
- .compatible = "fsl,mpc5200-gpio-wkup",
- },
+ { .compatible = "fsl,mpc5200-gpio-wkup", },
{}
};
static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
.driver = {
- .name = "gpio_wkup",
+ .name = "mpc5200-gpio-wkup",
.owner = THIS_MODULE,
.of_match_table = mpc52xx_wkup_gpiochip_match,
},
@@ -341,15 +339,13 @@ static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev
}
static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
- {
- .compatible = "fsl,mpc5200-gpio",
- },
+ { .compatible = "fsl,mpc5200-gpio", },
{}
};
static struct platform_driver mpc52xx_simple_gpiochip_driver = {
.driver = {
- .name = "gpio",
+ .name = "mpc5200-gpio",
.owner = THIS_MODULE,
.of_match_table = mpc52xx_simple_gpiochip_match,
},
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
new file mode 100644
index 000000000000..4340acae3bd3
--- /dev/null
+++ b/drivers/gpio/gpio-mxc.c
@@ -0,0 +1,460 @@
+/*
+ * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * Based on code from Freescale,
+ * Copyright (C) 2004-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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <asm-generic/bug.h>
+
+enum mxc_gpio_hwtype {
+ IMX1_GPIO, /* runs on i.mx1 */
+ IMX21_GPIO, /* runs on i.mx21 and i.mx27 */
+ IMX31_GPIO, /* runs on all other i.mx */
+};
+
+/* device type dependent stuff */
+struct mxc_gpio_hwdata {
+ unsigned dr_reg;
+ unsigned gdir_reg;
+ unsigned psr_reg;
+ unsigned icr1_reg;
+ unsigned icr2_reg;
+ unsigned imr_reg;
+ unsigned isr_reg;
+ unsigned low_level;
+ unsigned high_level;
+ unsigned rise_edge;
+ unsigned fall_edge;
+};
+
+struct mxc_gpio_port {
+ struct list_head node;
+ void __iomem *base;
+ int irq;
+ int irq_high;
+ int virtual_irq_start;
+ struct bgpio_chip bgc;
+ u32 both_edges;
+};
+
+static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
+ .dr_reg = 0x1c,
+ .gdir_reg = 0x00,
+ .psr_reg = 0x24,
+ .icr1_reg = 0x28,
+ .icr2_reg = 0x2c,
+ .imr_reg = 0x30,
+ .isr_reg = 0x34,
+ .low_level = 0x03,
+ .high_level = 0x02,
+ .rise_edge = 0x00,
+ .fall_edge = 0x01,
+};
+
+static struct mxc_gpio_hwdata imx31_gpio_hwdata = {
+ .dr_reg = 0x00,
+ .gdir_reg = 0x04,
+ .psr_reg = 0x08,
+ .icr1_reg = 0x0c,
+ .icr2_reg = 0x10,
+ .imr_reg = 0x14,
+ .isr_reg = 0x18,
+ .low_level = 0x00,
+ .high_level = 0x01,
+ .rise_edge = 0x02,
+ .fall_edge = 0x03,
+};
+
+static enum mxc_gpio_hwtype mxc_gpio_hwtype;
+static struct mxc_gpio_hwdata *mxc_gpio_hwdata;
+
+#define GPIO_DR (mxc_gpio_hwdata->dr_reg)
+#define GPIO_GDIR (mxc_gpio_hwdata->gdir_reg)
+#define GPIO_PSR (mxc_gpio_hwdata->psr_reg)
+#define GPIO_ICR1 (mxc_gpio_hwdata->icr1_reg)
+#define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg)
+#define GPIO_IMR (mxc_gpio_hwdata->imr_reg)
+#define GPIO_ISR (mxc_gpio_hwdata->isr_reg)
+
+#define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level)
+#define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level)
+#define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge)
+#define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge)
+#define GPIO_INT_NONE 0x4
+
+static struct platform_device_id mxc_gpio_devtype[] = {
+ {
+ .name = "imx1-gpio",
+ .driver_data = IMX1_GPIO,
+ }, {
+ .name = "imx21-gpio",
+ .driver_data = IMX21_GPIO,
+ }, {
+ .name = "imx31-gpio",
+ .driver_data = IMX31_GPIO,
+ }, {
+ /* sentinel */
+ }
+};
+
+static const struct of_device_id mxc_gpio_dt_ids[] = {
+ { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
+ { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
+ { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
+ { /* sentinel */ }
+};
+
+/*
+ * MX2 has one interrupt *for all* gpio ports. The list is used
+ * to save the references to all ports, so that mx2_gpio_irq_handler
+ * can walk through all interrupt status registers.
+ */
+static LIST_HEAD(mxc_gpio_ports);
+
+/* Note: This driver assumes 32 GPIOs are handled in one register */
+
+static int gpio_set_irq_type(struct irq_data *d, u32 type)
+{
+ u32 gpio = irq_to_gpio(d->irq);
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mxc_gpio_port *port = gc->private;
+ u32 bit, val;
+ int edge;
+ void __iomem *reg = port->base;
+
+ port->both_edges &= ~(1 << (gpio & 31));
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ edge = GPIO_INT_RISE_EDGE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ edge = GPIO_INT_FALL_EDGE;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ val = gpio_get_value(gpio);
+ if (val) {
+ edge = GPIO_INT_LOW_LEV;
+ pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
+ } else {
+ edge = GPIO_INT_HIGH_LEV;
+ pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
+ }
+ port->both_edges |= 1 << (gpio & 31);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ edge = GPIO_INT_LOW_LEV;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ edge = GPIO_INT_HIGH_LEV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+ bit = gpio & 0xf;
+ val = readl(reg) & ~(0x3 << (bit << 1));
+ writel(val | (edge << (bit << 1)), reg);
+ writel(1 << (gpio & 0x1f), port->base + GPIO_ISR);
+
+ return 0;
+}
+
+static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
+{
+ void __iomem *reg = port->base;
+ u32 bit, val;
+ int edge;
+
+ reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+ bit = gpio & 0xf;
+ val = readl(reg);
+ edge = (val >> (bit << 1)) & 3;
+ val &= ~(0x3 << (bit << 1));
+ if (edge == GPIO_INT_HIGH_LEV) {
+ edge = GPIO_INT_LOW_LEV;
+ pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
+ } else if (edge == GPIO_INT_LOW_LEV) {
+ edge = GPIO_INT_HIGH_LEV;
+ pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
+ } else {
+ pr_err("mxc: invalid configuration for GPIO %d: %x\n",
+ gpio, edge);
+ return;
+ }
+ writel(val | (edge << (bit << 1)), reg);
+}
+
+/* handle 32 interrupts in one status register */
+static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
+{
+ u32 gpio_irq_no_base = port->virtual_irq_start;
+
+ while (irq_stat != 0) {
+ int irqoffset = fls(irq_stat) - 1;
+
+ if (port->both_edges & (1 << irqoffset))
+ mxc_flip_edge(port, irqoffset);
+
+ generic_handle_irq(gpio_irq_no_base + irqoffset);
+
+ irq_stat &= ~(1 << irqoffset);
+ }
+}
+
+/* MX1 and MX3 has one interrupt *per* gpio port */
+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);
+
+ irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
+
+ mxc_gpio_irq_handler(port, irq_stat);
+}
+
+/* MX2 has one interrupt *for all* gpio ports */
+static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ u32 irq_msk, irq_stat;
+ struct mxc_gpio_port *port;
+
+ /* walk through all interrupt status registers */
+ list_for_each_entry(port, &mxc_gpio_ports, node) {
+ irq_msk = readl(port->base + GPIO_IMR);
+ if (!irq_msk)
+ continue;
+
+ irq_stat = readl(port->base + GPIO_ISR) & irq_msk;
+ if (irq_stat)
+ mxc_gpio_irq_handler(port, irq_stat);
+ }
+}
+
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running, all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param irq interrupt source number
+ * @param enable enable as wake-up if equal to non-zero
+ * @return This function returns 0 on success.
+ */
+static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
+{
+ u32 gpio = irq_to_gpio(d->irq);
+ u32 gpio_idx = gpio & 0x1F;
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mxc_gpio_port *port = gc->private;
+
+ if (enable) {
+ if (port->irq_high && (gpio_idx >= 16))
+ enable_irq_wake(port->irq_high);
+ else
+ enable_irq_wake(port->irq);
+ } else {
+ if (port->irq_high && (gpio_idx >= 16))
+ disable_irq_wake(port->irq_high);
+ else
+ disable_irq_wake(port->irq);
+ }
+
+ return 0;
+}
+
+static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start,
+ port->base, handle_level_irq);
+ gc->private = port;
+
+ ct = gc->chip_types;
+ ct->chip.irq_ack = irq_gc_ack_set_bit;
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->chip.irq_set_type = gpio_set_irq_type;
+ ct->chip.irq_set_wake = gpio_set_wake_irq;
+ ct->regs.ack = GPIO_ISR;
+ ct->regs.mask = GPIO_IMR;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
+ IRQ_NOREQUEST, 0);
+}
+
+static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
+{
+ const struct of_device_id *of_id =
+ of_match_device(mxc_gpio_dt_ids, &pdev->dev);
+ enum mxc_gpio_hwtype hwtype;
+
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ hwtype = pdev->id_entry->driver_data;
+
+ if (mxc_gpio_hwtype) {
+ /*
+ * The driver works with a reasonable presupposition,
+ * that is all gpio ports must be the same type when
+ * running on one soc.
+ */
+ BUG_ON(mxc_gpio_hwtype != hwtype);
+ return;
+ }
+
+ if (hwtype == IMX31_GPIO)
+ mxc_gpio_hwdata = &imx31_gpio_hwdata;
+ else
+ mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata;
+
+ mxc_gpio_hwtype = hwtype;
+}
+
+static int __devinit mxc_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct mxc_gpio_port *port;
+ struct resource *iores;
+ int err;
+
+ mxc_gpio_get_hw(pdev);
+
+ port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores) {
+ err = -ENODEV;
+ goto out_kfree;
+ }
+
+ if (!request_mem_region(iores->start, resource_size(iores),
+ pdev->name)) {
+ err = -EBUSY;
+ goto out_kfree;
+ }
+
+ port->base = ioremap(iores->start, resource_size(iores));
+ if (!port->base) {
+ err = -ENOMEM;
+ goto out_release_mem;
+ }
+
+ port->irq_high = platform_get_irq(pdev, 1);
+ port->irq = platform_get_irq(pdev, 0);
+ if (port->irq < 0) {
+ err = -EINVAL;
+ goto out_iounmap;
+ }
+
+ /* disable the interrupt and clear the status */
+ writel(0, port->base + GPIO_IMR);
+ writel(~0, port->base + GPIO_ISR);
+
+ if (mxc_gpio_hwtype == IMX21_GPIO) {
+ /* setup one handler for all GPIO interrupts */
+ if (pdev->id == 0)
+ irq_set_chained_handler(port->irq,
+ mx2_gpio_irq_handler);
+ } else {
+ /* setup one handler for each entry */
+ irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
+ irq_set_handler_data(port->irq, port);
+ if (port->irq_high > 0) {
+ /* setup handler for GPIO 16 to 31 */
+ irq_set_chained_handler(port->irq_high,
+ mx3_gpio_irq_handler);
+ irq_set_handler_data(port->irq_high, port);
+ }
+ }
+
+ err = bgpio_init(&port->bgc, &pdev->dev, 4,
+ port->base + GPIO_PSR,
+ port->base + GPIO_DR, NULL,
+ port->base + GPIO_GDIR, NULL, false);
+ if (err)
+ goto out_iounmap;
+
+ 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);
+
+ err = gpiochip_add(&port->bgc.gc);
+ if (err)
+ goto out_bgpio_remove;
+
+ /*
+ * In dt case, we use gpio number range dynamically
+ * allocated by gpio core.
+ */
+ port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base :
+ pdev->id * 32);
+
+ /* gpio-mxc can be a generic irq chip */
+ mxc_gpio_init_gc(port);
+
+ list_add_tail(&port->node, &mxc_gpio_ports);
+
+ return 0;
+
+out_bgpio_remove:
+ bgpio_remove(&port->bgc);
+out_iounmap:
+ iounmap(port->base);
+out_release_mem:
+ release_mem_region(iores->start, resource_size(iores));
+out_kfree:
+ kfree(port);
+ dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
+ return err;
+}
+
+static struct platform_driver mxc_gpio_driver = {
+ .driver = {
+ .name = "gpio-mxc",
+ .owner = THIS_MODULE,
+ .of_match_table = mxc_gpio_dt_ids,
+ },
+ .probe = mxc_gpio_probe,
+ .id_table = mxc_gpio_devtype,
+};
+
+static int __init gpio_mxc_init(void)
+{
+ return platform_driver_register(&mxc_gpio_driver);
+}
+postcore_initcall(gpio_mxc_init);
+
+MODULE_AUTHOR("Freescale Semiconductor, "
+ "Daniel Mack <danielncaiaq.de>, "
+ "Juergen Beisert <kernel@pengutronix.de>");
+MODULE_DESCRIPTION("Freescale MXC GPIO");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
new file mode 100644
index 000000000000..af55a8577c2e
--- /dev/null
+++ b/drivers/gpio/gpio-mxs.c
@@ -0,0 +1,289 @@
+/*
+ * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * Based on code from Freescale,
+ * Copyright (C) 2004-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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/basic_mmio_gpio.h>
+#include <mach/mxs.h>
+
+#define MXS_SET 0x4
+#define MXS_CLR 0x8
+
+#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
+#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
+#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
+#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
+#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
+#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
+#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
+#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
+
+#define GPIO_INT_FALL_EDGE 0x0
+#define GPIO_INT_LOW_LEV 0x1
+#define GPIO_INT_RISE_EDGE 0x2
+#define GPIO_INT_HIGH_LEV 0x3
+#define GPIO_INT_LEV_MASK (1 << 0)
+#define GPIO_INT_POL_MASK (1 << 1)
+
+struct mxs_gpio_port {
+ void __iomem *base;
+ int id;
+ int irq;
+ int virtual_irq_start;
+ struct bgpio_chip bgc;
+};
+
+/* Note: This driver assumes 32 GPIOs are handled in one register */
+
+static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
+{
+ u32 gpio = irq_to_gpio(d->irq);
+ u32 pin_mask = 1 << (gpio & 31);
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mxs_gpio_port *port = gc->private;
+ void __iomem *pin_addr;
+ int edge;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ edge = GPIO_INT_RISE_EDGE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ edge = GPIO_INT_FALL_EDGE;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ edge = GPIO_INT_LOW_LEV;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ edge = GPIO_INT_HIGH_LEV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* set level or edge */
+ pin_addr = port->base + PINCTRL_IRQLEV(port->id);
+ if (edge & GPIO_INT_LEV_MASK)
+ writel(pin_mask, pin_addr + MXS_SET);
+ else
+ writel(pin_mask, pin_addr + MXS_CLR);
+
+ /* set polarity */
+ pin_addr = port->base + PINCTRL_IRQPOL(port->id);
+ if (edge & GPIO_INT_POL_MASK)
+ writel(pin_mask, pin_addr + MXS_SET);
+ else
+ writel(pin_mask, pin_addr + MXS_CLR);
+
+ writel(1 << (gpio & 0x1f),
+ port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
+
+ return 0;
+}
+
+/* MXS has one interrupt *per* gpio port */
+static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ u32 irq_stat;
+ struct mxs_gpio_port *port = irq_get_handler_data(irq);
+ u32 gpio_irq_no_base = port->virtual_irq_start;
+
+ desc->irq_data.chip->irq_ack(&desc->irq_data);
+
+ irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) &
+ readl(port->base + PINCTRL_IRQEN(port->id));
+
+ while (irq_stat != 0) {
+ int irqoffset = fls(irq_stat) - 1;
+ generic_handle_irq(gpio_irq_no_base + irqoffset);
+ irq_stat &= ~(1 << irqoffset);
+ }
+}
+
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running, all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param irq interrupt source number
+ * @param enable enable as wake-up if equal to non-zero
+ * @return This function returns 0 on success.
+ */
+static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mxs_gpio_port *port = gc->private;
+
+ if (enable)
+ enable_irq_wake(port->irq);
+ else
+ disable_irq_wake(port->irq);
+
+ return 0;
+}
+
+static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start,
+ port->base, handle_level_irq);
+ gc->private = port;
+
+ ct = gc->chip_types;
+ ct->chip.irq_ack = irq_gc_ack_set_bit;
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->chip.irq_set_type = mxs_gpio_set_irq_type;
+ ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
+ ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR;
+ ct->regs.mask = PINCTRL_IRQEN(port->id);
+
+ irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ struct mxs_gpio_port *port =
+ container_of(bgc, struct mxs_gpio_port, bgc);
+
+ return port->virtual_irq_start + offset;
+}
+
+static int __devinit mxs_gpio_probe(struct platform_device *pdev)
+{
+ static void __iomem *base;
+ struct mxs_gpio_port *port;
+ struct resource *iores = NULL;
+ int err;
+
+ port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ port->id = pdev->id;
+ port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32;
+
+ /*
+ * map memory region only once, as all the gpio ports
+ * share the same one
+ */
+ if (!base) {
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores) {
+ err = -ENODEV;
+ goto out_kfree;
+ }
+
+ if (!request_mem_region(iores->start, resource_size(iores),
+ pdev->name)) {
+ err = -EBUSY;
+ goto out_kfree;
+ }
+
+ base = ioremap(iores->start, resource_size(iores));
+ if (!base) {
+ err = -ENOMEM;
+ goto out_release_mem;
+ }
+ }
+ port->base = base;
+
+ port->irq = platform_get_irq(pdev, 0);
+ if (port->irq < 0) {
+ err = -EINVAL;
+ goto out_iounmap;
+ }
+
+ /*
+ * select the pin interrupt functionality but initially
+ * disable the interrupts
+ */
+ writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id));
+ writel(0, port->base + PINCTRL_IRQEN(port->id));
+
+ /* clear address has to be used to clear IRQSTAT bits */
+ writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
+
+ /* gpio-mxs can be a generic irq chip */
+ mxs_gpio_init_gc(port);
+
+ /* setup one handler for each entry */
+ irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
+ irq_set_handler_data(port->irq, port);
+
+ err = bgpio_init(&port->bgc, &pdev->dev, 4,
+ port->base + PINCTRL_DIN(port->id),
+ port->base + PINCTRL_DOUT(port->id), NULL,
+ port->base + PINCTRL_DOE(port->id), NULL, false);
+ if (err)
+ goto out_iounmap;
+
+ port->bgc.gc.to_irq = mxs_gpio_to_irq;
+ port->bgc.gc.base = port->id * 32;
+
+ err = gpiochip_add(&port->bgc.gc);
+ if (err)
+ goto out_bgpio_remove;
+
+ return 0;
+
+out_bgpio_remove:
+ bgpio_remove(&port->bgc);
+out_iounmap:
+ if (iores)
+ iounmap(port->base);
+out_release_mem:
+ if (iores)
+ release_mem_region(iores->start, resource_size(iores));
+out_kfree:
+ kfree(port);
+ dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
+ return err;
+}
+
+static struct platform_driver mxs_gpio_driver = {
+ .driver = {
+ .name = "gpio-mxs",
+ .owner = THIS_MODULE,
+ },
+ .probe = mxs_gpio_probe,
+};
+
+static int __init mxs_gpio_init(void)
+{
+ return platform_driver_register(&mxs_gpio_driver);
+}
+postcore_initcall(mxs_gpio_init);
+
+MODULE_AUTHOR("Freescale Semiconductor, "
+ "Daniel Mack <danielncaiaq.de>, "
+ "Juergen Beisert <kernel@pengutronix.de>");
+MODULE_DESCRIPTION("Freescale MXS GPIO");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 35bebde23e83..0599854e2217 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -54,6 +54,11 @@ struct gpio_bank {
struct device *dev;
bool dbck_flag;
int stride;
+ u32 width;
+
+ void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable);
+
+ struct omap_gpio_reg_offs *regs;
};
#ifdef CONFIG_ARCH_OMAP3
@@ -79,121 +84,18 @@ static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
*/
static struct gpio_bank *gpio_bank;
-static int bank_width;
-
/* TODO: Analyze removing gpio_bank_count usage from driver code */
int gpio_bank_count;
-static inline struct gpio_bank *get_gpio_bank(int gpio)
-{
- if (cpu_is_omap15xx()) {
- if (OMAP_GPIO_IS_MPUIO(gpio))
- return &gpio_bank[0];
- return &gpio_bank[1];
- }
- if (cpu_is_omap16xx()) {
- if (OMAP_GPIO_IS_MPUIO(gpio))
- return &gpio_bank[0];
- return &gpio_bank[1 + (gpio >> 4)];
- }
- if (cpu_is_omap7xx()) {
- if (OMAP_GPIO_IS_MPUIO(gpio))
- return &gpio_bank[0];
- return &gpio_bank[1 + (gpio >> 5)];
- }
- if (cpu_is_omap24xx())
- return &gpio_bank[gpio >> 5];
- if (cpu_is_omap34xx() || cpu_is_omap44xx())
- return &gpio_bank[gpio >> 5];
- BUG();
- return NULL;
-}
-
-static inline int get_gpio_index(int gpio)
-{
- if (cpu_is_omap7xx())
- return gpio & 0x1f;
- if (cpu_is_omap24xx())
- return gpio & 0x1f;
- if (cpu_is_omap34xx() || cpu_is_omap44xx())
- return gpio & 0x1f;
- return gpio & 0x0f;
-}
-
-static inline int gpio_valid(int gpio)
-{
- if (gpio < 0)
- return -1;
- if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
- if (gpio >= OMAP_MAX_GPIO_LINES + 16)
- return -1;
- return 0;
- }
- if (cpu_is_omap15xx() && gpio < 16)
- return 0;
- if ((cpu_is_omap16xx()) && gpio < 64)
- return 0;
- if (cpu_is_omap7xx() && gpio < 192)
- return 0;
- if (cpu_is_omap2420() && gpio < 128)
- return 0;
- if (cpu_is_omap2430() && gpio < 160)
- return 0;
- if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
- return 0;
- return -1;
-}
-
-static int check_gpio(int gpio)
-{
- if (unlikely(gpio_valid(gpio) < 0)) {
- printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
- dump_stack();
- return -1;
- }
- return 0;
-}
+#define GPIO_INDEX(bank, gpio) (gpio % bank->width)
+#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
{
void __iomem *reg = bank->base;
u32 l;
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
- case METHOD_MPUIO:
- reg += OMAP_MPUIO_IO_CNTL / bank->stride;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_DIR_CONTROL;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_GPIO_1610:
- reg += OMAP1610_GPIO_DIRECTION;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_DIR_CONTROL;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- case METHOD_GPIO_24XX:
- reg += OMAP24XX_GPIO_OE;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
- case METHOD_GPIO_44XX:
- reg += OMAP4_GPIO_OE;
- break;
-#endif
- default:
- WARN_ON(1);
- return;
- }
+ reg += bank->regs->direction;
l = __raw_readl(reg);
if (is_input)
l |= 1 << gpio;
@@ -202,165 +104,48 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
__raw_writel(l, reg);
}
-static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
+
+/* set data out value using dedicate set/clear register */
+static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
{
void __iomem *reg = bank->base;
- u32 l = 0;
+ u32 l = GPIO_BIT(bank, gpio);
+
+ if (enable)
+ reg += bank->regs->set_dataout;
+ else
+ reg += bank->regs->clr_dataout;
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
- case METHOD_MPUIO:
- reg += OMAP_MPUIO_OUTPUT / bank->stride;
- l = __raw_readl(reg);
- if (enable)
- l |= 1 << gpio;
- else
- l &= ~(1 << gpio);
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_DATA_OUTPUT;
- l = __raw_readl(reg);
- if (enable)
- l |= 1 << gpio;
- else
- l &= ~(1 << gpio);
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_GPIO_1610:
- if (enable)
- reg += OMAP1610_GPIO_SET_DATAOUT;
- else
- reg += OMAP1610_GPIO_CLEAR_DATAOUT;
- l = 1 << gpio;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_DATA_OUTPUT;
- l = __raw_readl(reg);
- if (enable)
- l |= 1 << gpio;
- else
- l &= ~(1 << gpio);
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- case METHOD_GPIO_24XX:
- if (enable)
- reg += OMAP24XX_GPIO_SETDATAOUT;
- else
- reg += OMAP24XX_GPIO_CLEARDATAOUT;
- l = 1 << gpio;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
- case METHOD_GPIO_44XX:
- if (enable)
- reg += OMAP4_GPIO_SETDATAOUT;
- else
- reg += OMAP4_GPIO_CLEARDATAOUT;
- l = 1 << gpio;
- break;
-#endif
- default:
- WARN_ON(1);
- return;
- }
__raw_writel(l, reg);
}
-static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
+/* set data out value using mask register */
+static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
{
- void __iomem *reg;
+ void __iomem *reg = bank->base + bank->regs->dataout;
+ u32 gpio_bit = GPIO_BIT(bank, gpio);
+ u32 l;
- if (check_gpio(gpio) < 0)
- return -EINVAL;
- reg = bank->base;
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
- case METHOD_MPUIO:
- reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_DATA_INPUT;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_GPIO_1610:
- reg += OMAP1610_GPIO_DATAIN;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_DATA_INPUT;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- case METHOD_GPIO_24XX:
- reg += OMAP24XX_GPIO_DATAIN;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
- case METHOD_GPIO_44XX:
- reg += OMAP4_GPIO_DATAIN;
- break;
-#endif
- default:
- return -EINVAL;
- }
- return (__raw_readl(reg)
- & (1 << get_gpio_index(gpio))) != 0;
+ l = __raw_readl(reg);
+ if (enable)
+ l |= gpio_bit;
+ else
+ l &= ~gpio_bit;
+ __raw_writel(l, reg);
}
-static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
{
- void __iomem *reg;
+ void __iomem *reg = bank->base + bank->regs->datain;
- if (check_gpio(gpio) < 0)
- return -EINVAL;
- reg = bank->base;
+ return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+}
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
- case METHOD_MPUIO:
- reg += OMAP_MPUIO_OUTPUT / bank->stride;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_DATA_OUTPUT;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_GPIO_1610:
- reg += OMAP1610_GPIO_DATAOUT;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_DATA_OUTPUT;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- case METHOD_GPIO_24XX:
- reg += OMAP24XX_GPIO_DATAOUT;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
- case METHOD_GPIO_44XX:
- reg += OMAP4_GPIO_DATAOUT;
- break;
-#endif
- default:
- return -EINVAL;
- }
+static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+{
+ void __iomem *reg = bank->base + bank->regs->dataout;
- return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
+ return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
}
#define MOD_REG_BIT(reg, bit_mask, set) \
@@ -383,7 +168,7 @@ do { \
static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
unsigned debounce)
{
- void __iomem *reg = bank->base;
+ void __iomem *reg;
u32 val;
u32 l;
@@ -397,21 +182,12 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
else
debounce = (debounce / 0x1f) - 1;
- l = 1 << get_gpio_index(gpio);
-
- if (bank->method == METHOD_GPIO_44XX)
- reg += OMAP4_GPIO_DEBOUNCINGTIME;
- else
- reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
+ l = GPIO_BIT(bank, gpio);
+ reg = bank->base + bank->regs->debounce;
__raw_writel(debounce, reg);
- reg = bank->base;
- if (bank->method == METHOD_GPIO_44XX)
- reg += OMAP4_GPIO_DEBOUNCENABLE;
- else
- reg += OMAP24XX_GPIO_DEBOUNCE_EN;
-
+ reg = bank->base + bank->regs->debounce_en;
val = __raw_readl(reg);
if (debounce) {
@@ -629,9 +405,6 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
else
gpio = d->irq - IH_GPIO_BASE;
- if (check_gpio(gpio) < 0)
- return -EINVAL;
-
if (type & ~IRQ_TYPE_SENSE_MASK)
return -EINVAL;
@@ -642,7 +415,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
bank = irq_data_get_irq_chip_data(d);
spin_lock_irqsave(&bank->lock, flags);
- retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
+ retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type);
spin_unlock_irqrestore(&bank->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -657,195 +430,81 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
- case METHOD_MPUIO:
- /* MPUIO irqstatus is reset by reading the status register,
- * so do nothing here */
- return;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_INT_STATUS;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_GPIO_1610:
- reg += OMAP1610_GPIO_IRQSTATUS1;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_INT_STATUS;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- case METHOD_GPIO_24XX:
- reg += OMAP24XX_GPIO_IRQSTATUS1;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
- case METHOD_GPIO_44XX:
- reg += OMAP4_GPIO_IRQSTATUS0;
- break;
-#endif
- default:
- WARN_ON(1);
- return;
- }
+ reg += bank->regs->irqstatus;
__raw_writel(gpio_mask, reg);
/* Workaround for clearing DSP GPIO interrupts to allow retention */
- if (cpu_is_omap24xx() || cpu_is_omap34xx())
- reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
- else if (cpu_is_omap44xx())
- reg = bank->base + OMAP4_GPIO_IRQSTATUS1;
-
- if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (bank->regs->irqstatus2) {
+ reg = bank->base + bank->regs->irqstatus2;
__raw_writel(gpio_mask, reg);
+ }
/* Flush posted write for the irq status to avoid spurious interrupts */
__raw_readl(reg);
- }
}
static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
{
- _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
+ _clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
}
static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
{
void __iomem *reg = bank->base;
- int inv = 0;
u32 l;
- u32 mask;
-
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
- case METHOD_MPUIO:
- reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
- mask = 0xffff;
- inv = 1;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_INT_MASK;
- mask = 0xffff;
- inv = 1;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_GPIO_1610:
- reg += OMAP1610_GPIO_IRQENABLE1;
- mask = 0xffff;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_INT_MASK;
- mask = 0xffffffff;
- inv = 1;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- case METHOD_GPIO_24XX:
- reg += OMAP24XX_GPIO_IRQENABLE1;
- mask = 0xffffffff;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
- case METHOD_GPIO_44XX:
- reg += OMAP4_GPIO_IRQSTATUSSET0;
- mask = 0xffffffff;
- break;
-#endif
- default:
- WARN_ON(1);
- return 0;
- }
+ u32 mask = (1 << bank->width) - 1;
+ reg += bank->regs->irqenable;
l = __raw_readl(reg);
- if (inv)
+ if (bank->regs->irqenable_inv)
l = ~l;
l &= mask;
return l;
}
-static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
+static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
u32 l;
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
- case METHOD_MPUIO:
- reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
- l = __raw_readl(reg);
- if (enable)
- l &= ~(gpio_mask);
- else
- l |= gpio_mask;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_INT_MASK;
+ if (bank->regs->set_irqenable) {
+ reg += bank->regs->set_irqenable;
+ l = gpio_mask;
+ } else {
+ reg += bank->regs->irqenable;
l = __raw_readl(reg);
- if (enable)
- l &= ~(gpio_mask);
+ if (bank->regs->irqenable_inv)
+ l &= ~gpio_mask;
else
l |= gpio_mask;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_GPIO_1610:
- if (enable)
- reg += OMAP1610_GPIO_SET_IRQENABLE1;
- else
- reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
+ }
+
+ __raw_writel(l, reg);
+}
+
+static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+{
+ void __iomem *reg = bank->base;
+ u32 l;
+
+ if (bank->regs->clr_irqenable) {
+ reg += bank->regs->clr_irqenable;
l = gpio_mask;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_INT_MASK;
+ } else {
+ reg += bank->regs->irqenable;
l = __raw_readl(reg);
- if (enable)
- l &= ~(gpio_mask);
- else
+ if (bank->regs->irqenable_inv)
l |= gpio_mask;
- break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- case METHOD_GPIO_24XX:
- if (enable)
- reg += OMAP24XX_GPIO_SETIRQENABLE1;
- else
- reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
- l = gpio_mask;
- break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
- case METHOD_GPIO_44XX:
- if (enable)
- reg += OMAP4_GPIO_IRQSTATUSSET0;
else
- reg += OMAP4_GPIO_IRQSTATUSCLR0;
- l = gpio_mask;
- break;
-#endif
- default:
- WARN_ON(1);
- return;
+ l &= ~gpio_mask;
}
+
__raw_writel(l, reg);
}
static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
{
- _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
+ _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
}
/*
@@ -858,50 +517,32 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
*/
static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
{
- unsigned long uninitialized_var(flags);
+ u32 gpio_bit = GPIO_BIT(bank, gpio);
+ unsigned long flags;
- switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
- case METHOD_MPUIO:
- case METHOD_GPIO_1610:
- spin_lock_irqsave(&bank->lock, flags);
- if (enable)
- bank->suspend_wakeup |= (1 << gpio);
- else
- bank->suspend_wakeup &= ~(1 << gpio);
- spin_unlock_irqrestore(&bank->lock, flags);
- return 0;
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
- case METHOD_GPIO_24XX:
- case METHOD_GPIO_44XX:
- if (bank->non_wakeup_gpios & (1 << gpio)) {
- printk(KERN_ERR "Unable to modify wakeup on "
- "non-wakeup GPIO%d\n",
- (bank - gpio_bank) * 32 + gpio);
- return -EINVAL;
- }
- spin_lock_irqsave(&bank->lock, flags);
- if (enable)
- bank->suspend_wakeup |= (1 << gpio);
- else
- bank->suspend_wakeup &= ~(1 << gpio);
- spin_unlock_irqrestore(&bank->lock, flags);
- return 0;
-#endif
- default:
- printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
- bank->method);
+ if (bank->non_wakeup_gpios & gpio_bit) {
+ dev_err(bank->dev,
+ "Unable to modify wakeup on non-wakeup GPIO%d\n", gpio);
return -EINVAL;
}
+
+ spin_lock_irqsave(&bank->lock, flags);
+ if (enable)
+ bank->suspend_wakeup |= gpio_bit;
+ else
+ bank->suspend_wakeup &= ~gpio_bit;
+
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ return 0;
}
static void _reset_gpio(struct gpio_bank *bank, int gpio)
{
- _set_gpio_direction(bank, get_gpio_index(gpio), 1);
+ _set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
_set_gpio_irqenable(bank, gpio, 0);
_clear_gpio_irqstatus(bank, gpio);
- _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
+ _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
}
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
@@ -911,10 +552,8 @@ static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
struct gpio_bank *bank;
int retval;
- if (check_gpio(gpio) < 0)
- return -ENODEV;
bank = irq_data_get_irq_chip_data(d);
- retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
+ retval = _set_gpio_wakeup(bank, gpio, enable);
return retval;
}
@@ -1030,31 +669,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
chained_irq_enter(chip, desc);
bank = irq_get_handler_data(irq);
-#ifdef CONFIG_ARCH_OMAP1
- if (bank->method == METHOD_MPUIO)
- isr_reg = bank->base +
- OMAP_MPUIO_GPIO_INT / bank->stride;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
- if (bank->method == METHOD_GPIO_1510)
- isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
- if (bank->method == METHOD_GPIO_1610)
- isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
- if (bank->method == METHOD_GPIO_7XX)
- isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
- if (bank->method == METHOD_GPIO_24XX)
- isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
- if (bank->method == METHOD_GPIO_44XX)
- isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
-#endif
+ isr_reg = bank->base + bank->regs->irqstatus;
if (WARN_ON(!isr_reg))
goto exit;
@@ -1076,9 +691,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
/* clear edge sensitive interrupts before handler(s) are
called so that we don't miss any interrupt occurred while
executing them */
- _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+ _disable_gpio_irqbank(bank, isr_saved & ~level_mask);
_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
- _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask);
/* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */
@@ -1094,7 +709,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
gpio_irq = bank->virtual_irq_start;
for (; isr != 0; isr >>= 1, gpio_irq++) {
- gpio_index = get_gpio_index(irq_to_gpio(gpio_irq));
+ gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq));
if (!(isr & 1))
continue;
@@ -1150,7 +765,7 @@ static void gpio_mask_irq(struct irq_data *d)
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_irqenable(bank, gpio, 0);
- _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
+ _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
spin_unlock_irqrestore(&bank->lock, flags);
}
@@ -1158,13 +773,13 @@ static void gpio_unmask_irq(struct irq_data *d)
{
unsigned int gpio = d->irq - IH_GPIO_BASE;
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
- unsigned int irq_mask = 1 << get_gpio_index(gpio);
+ unsigned int irq_mask = GPIO_BIT(bank, gpio);
u32 trigger = irqd_get_trigger_type(d);
unsigned long flags;
spin_lock_irqsave(&bank->lock, flags);
if (trigger)
- _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
+ _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
/* For level-triggered GPIOs, the clearing must be done after
* the HW source is cleared, thus after the handler has run */
@@ -1191,45 +806,8 @@ static struct irq_chip gpio_irq_chip = {
#ifdef CONFIG_ARCH_OMAP1
-/* MPUIO uses the always-on 32k clock */
-
-static void mpuio_ack_irq(struct irq_data *d)
-{
- /* The ISR is reset automatically, so do nothing here. */
-}
-
-static void mpuio_mask_irq(struct irq_data *d)
-{
- unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
- _set_gpio_irqenable(bank, gpio, 0);
-}
-
-static void mpuio_unmask_irq(struct irq_data *d)
-{
- unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
- _set_gpio_irqenable(bank, gpio, 1);
-}
-
-static struct irq_chip mpuio_irq_chip = {
- .name = "MPUIO",
- .irq_ack = mpuio_ack_irq,
- .irq_mask = mpuio_mask_irq,
- .irq_unmask = mpuio_unmask_irq,
- .irq_set_type = gpio_irq_type,
-#ifdef CONFIG_ARCH_OMAP16XX
- /* REVISIT: assuming only 16xx supports MPUIO wake events */
- .irq_set_wake = gpio_wake_enable,
-#endif
-};
-
-
#define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO)
-
#ifdef CONFIG_ARCH_OMAP16XX
#include <linux/platform_device.h>
@@ -1289,7 +867,7 @@ static struct platform_device omap_mpuio_device = {
static inline void mpuio_init(void)
{
- struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
+ struct gpio_bank *bank = &gpio_bank[0];
platform_set_drvdata(&omap_mpuio_device, bank);
if (platform_driver_register(&omap_mpuio_driver) == 0)
@@ -1302,8 +880,6 @@ static inline void mpuio_init(void) {}
#else
-extern struct irq_chip mpuio_irq_chip;
-
#define bank_is_mpuio(bank) 0
static inline void mpuio_init(void) {}
@@ -1329,31 +905,8 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset)
static int gpio_is_input(struct gpio_bank *bank, int mask)
{
- void __iomem *reg = bank->base;
+ void __iomem *reg = bank->base + bank->regs->direction;
- switch (bank->method) {
- case METHOD_MPUIO:
- reg += OMAP_MPUIO_IO_CNTL / bank->stride;
- break;
- case METHOD_GPIO_1510:
- reg += OMAP1510_GPIO_DIR_CONTROL;
- break;
- case METHOD_GPIO_1610:
- reg += OMAP1610_GPIO_DIRECTION;
- break;
- case METHOD_GPIO_7XX:
- reg += OMAP7XX_GPIO_DIR_CONTROL;
- break;
- case METHOD_GPIO_24XX:
- reg += OMAP24XX_GPIO_OE;
- break;
- case METHOD_GPIO_44XX:
- reg += OMAP4_GPIO_OE;
- break;
- default:
- WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
- return -EINVAL;
- }
return __raw_readl(reg) & mask;
}
@@ -1365,9 +918,9 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
u32 mask;
gpio = chip->base + offset;
- bank = get_gpio_bank(gpio);
+ bank = container_of(chip, struct gpio_bank, chip);
reg = bank->base;
- mask = 1 << get_gpio_index(gpio);
+ mask = GPIO_BIT(bank, gpio);
if (gpio_is_input(bank, mask))
return _get_gpio_datain(bank, gpio);
@@ -1382,7 +935,7 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
- _set_gpio_dataout(bank, offset, value);
+ bank->set_dataout(bank, offset, value);
_set_gpio_direction(bank, offset, 0);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
@@ -1416,7 +969,7 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
- _set_gpio_dataout(bank, offset, value);
+ bank->set_dataout(bank, offset, value);
spin_unlock_irqrestore(&bank->lock, flags);
}
@@ -1432,19 +985,17 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
static void __init omap_gpio_show_rev(struct gpio_bank *bank)
{
+ static bool called;
u32 rev;
- if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
- rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
- else if (cpu_is_omap24xx() || cpu_is_omap34xx())
- rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
- else if (cpu_is_omap44xx())
- rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
- else
+ if (called || bank->regs->revision == USHRT_MAX)
return;
- printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
+ rev = __raw_readw(bank->base + bank->regs->revision);
+ pr_info("OMAP GPIO hardware version %d.%d\n",
(rev >> 4) & 0x0f, rev & 0x0f);
+
+ called = true;
}
/* This lock class tells lockdep that GPIO irqs are in a different
@@ -1526,6 +1077,30 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
}
}
+static __init void
+omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
+ unsigned int num)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
+ handle_simple_irq);
+ ct = gc->chip_types;
+
+ /* NOTE: No ack required, reading IRQ status clears it. */
+ ct->chip.irq_mask = irq_gc_mask_set_bit;
+ ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+ ct->chip.irq_set_type = gpio_irq_type;
+ /* REVISIT: assuming only 16xx supports MPUIO wake events */
+ if (cpu_is_omap16xx())
+ ct->chip.irq_set_wake = gpio_wake_enable,
+
+ ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
+ irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+}
+
static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
{
int j;
@@ -1553,22 +1128,23 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
} else {
bank->chip.label = "gpio";
bank->chip.base = gpio;
- gpio += bank_width;
+ gpio += bank->width;
}
- bank->chip.ngpio = bank_width;
+ bank->chip.ngpio = bank->width;
gpiochip_add(&bank->chip);
for (j = bank->virtual_irq_start;
- j < bank->virtual_irq_start + bank_width; j++) {
+ j < bank->virtual_irq_start + bank->width; j++) {
irq_set_lockdep_class(j, &gpio_lock_class);
irq_set_chip_data(j, bank);
- if (bank_is_mpuio(bank))
- irq_set_chip(j, &mpuio_irq_chip);
- else
+ if (bank_is_mpuio(bank)) {
+ omap_mpuio_alloc_gc(bank, j, bank->width);
+ } else {
irq_set_chip(j, &gpio_irq_chip);
- irq_set_handler(j, handle_simple_irq);
- set_irq_flags(j, IRQF_VALID);
+ irq_set_handler(j, handle_simple_irq);
+ set_irq_flags(j, IRQF_VALID);
+ }
}
irq_set_chained_handler(bank->irq, gpio_irq_handler);
irq_set_handler_data(bank->irq, bank);
@@ -1610,7 +1186,14 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
bank->dev = &pdev->dev;
bank->dbck_flag = pdata->dbck_flag;
bank->stride = pdata->bank_stride;
- bank_width = pdata->bank_width;
+ bank->width = pdata->bank_width;
+
+ bank->regs = pdata->regs;
+
+ if (bank->regs->set_dataout && bank->regs->clr_dataout)
+ bank->set_dataout = _set_gpio_dataout_reg;
+ else
+ bank->set_dataout = _set_gpio_dataout_mask;
spin_lock_init(&bank->lock);
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/gpio-pca953x.c
index 0451d7ac94ac..c43b8ff626a7 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -1,5 +1,5 @@
/*
- * pca953x.c - 4/8/16 bit I/O ports
+ * PCA953x 4/8/16 bit I/O ports
*
* Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
* Copyright (C) 2007 Marvell International Ltd.
@@ -21,7 +21,6 @@
#include <linux/slab.h>
#ifdef CONFIG_OF_GPIO
#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
#endif
#define PCA953X_INPUT 0
@@ -85,7 +84,6 @@ struct pca953x_chip {
#endif
struct i2c_client *client;
- struct pca953x_platform_data *dyn_pdata;
struct gpio_chip gpio_chip;
const char *const *names;
int chip_type;
@@ -437,7 +435,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
do {
level = __ffs(pending);
- generic_handle_irq(level + chip->irq_base);
+ handle_nested_irq(level + chip->irq_base);
pending &= ~(1 << level);
} while (pending);
@@ -446,13 +444,13 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
}
static int pca953x_irq_setup(struct pca953x_chip *chip,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id,
+ int irq_base)
{
struct i2c_client *client = chip->client;
- struct pca953x_platform_data *pdata = client->dev.platform_data;
int ret, offset = 0;
- if (pdata->irq_base != -1
+ if (irq_base != -1
&& (id->driver_data & PCA_INT)) {
int lvl;
@@ -474,15 +472,19 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
* this purpose.
*/
chip->irq_stat &= chip->reg_direction;
- chip->irq_base = pdata->irq_base;
mutex_init(&chip->irq_lock);
+ chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1);
+ if (chip->irq_base < 0)
+ goto out_failed;
+
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
int irq = lvl + chip->irq_base;
+ irq_clear_status_flags(irq, IRQ_NOREQUEST);
irq_set_chip_data(irq, chip);
- irq_set_chip_and_handler(irq, &pca953x_irq_chip,
- handle_simple_irq);
+ irq_set_chip(irq, &pca953x_irq_chip);
+ irq_set_nested_thread(irq, true);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
@@ -493,8 +495,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
ret = request_threaded_irq(client->irq,
NULL,
pca953x_irq_handler,
- IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
dev_name(&client->dev), chip);
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
@@ -514,17 +515,19 @@ out_failed:
static void pca953x_irq_teardown(struct pca953x_chip *chip)
{
- if (chip->irq_base != -1)
+ if (chip->irq_base != -1) {
+ irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
free_irq(chip->client->irq, chip);
+ }
}
#else /* CONFIG_GPIO_PCA953X_IRQ */
static int pca953x_irq_setup(struct pca953x_chip *chip,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id,
+ int irq_base)
{
struct i2c_client *client = chip->client;
- struct pca953x_platform_data *pdata = client->dev.platform_data;
- if (pdata->irq_base != -1 && (id->driver_data & PCA_INT))
+ if (irq_base != -1 && (id->driver_data & PCA_INT))
dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0;
@@ -541,46 +544,39 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip)
#ifdef CONFIG_OF_GPIO
/*
* Translate OpenFirmware node properties into platform_data
+ * WARNING: This is DEPRECATED and will be removed eventually!
*/
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
+void
+pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
{
- struct pca953x_platform_data *pdata;
struct device_node *node;
const __be32 *val;
int size;
node = client->dev.of_node;
if (node == NULL)
- return NULL;
-
- pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
- if (pdata == NULL) {
- dev_err(&client->dev, "Unable to allocate platform_data\n");
- return NULL;
- }
+ return;
- pdata->gpio_base = -1;
+ *gpio_base = -1;
val = of_get_property(node, "linux,gpio-base", &size);
+ WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__);
if (val) {
if (size != sizeof(*val))
dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
node->full_name);
else
- pdata->gpio_base = be32_to_cpup(val);
+ *gpio_base = be32_to_cpup(val);
}
val = of_get_property(node, "polarity", NULL);
+ WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__);
if (val)
- pdata->invert = *val;
-
- return pdata;
+ *invert = *val;
}
#else
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
+void
+pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
{
- return NULL;
}
#endif
@@ -642,6 +638,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
{
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
+ int irq_base=0, invert=0;
int ret = 0;
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
@@ -649,26 +646,22 @@ static int __devinit pca953x_probe(struct i2c_client *client,
return -ENOMEM;
pdata = client->dev.platform_data;
- if (pdata == NULL) {
- pdata = pca953x_get_alt_pdata(client);
- /*
- * Unlike normal platform_data, this is allocated
- * dynamically and must be freed in the driver
- */
- chip->dyn_pdata = pdata;
- }
-
- if (pdata == NULL) {
- dev_dbg(&client->dev, "no platform data\n");
- ret = -EINVAL;
- goto out_failed;
+ if (pdata) {
+ irq_base = pdata->irq_base;
+ chip->gpio_start = pdata->gpio_base;
+ invert = pdata->invert;
+ chip->names = pdata->names;
+ } else {
+ pca953x_get_alt_pdata(client, &chip->gpio_start, &invert);
+#ifdef CONFIG_OF_GPIO
+ /* If I2C node has no interrupts property, disable GPIO interrupts */
+ if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL)
+ irq_base = -1;
+#endif
}
chip->client = client;
- chip->gpio_start = pdata->gpio_base;
-
- chip->names = pdata->names;
chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
mutex_init(&chip->i2c_lock);
@@ -679,13 +672,13 @@ static int __devinit pca953x_probe(struct i2c_client *client,
pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
if (chip->chip_type == PCA953X_TYPE)
- device_pca953x_init(chip, pdata->invert);
+ device_pca953x_init(chip, invert);
else if (chip->chip_type == PCA957X_TYPE)
- device_pca957x_init(chip, pdata->invert);
+ device_pca957x_init(chip, invert);
else
goto out_failed;
- ret = pca953x_irq_setup(chip, id);
+ ret = pca953x_irq_setup(chip, id, irq_base);
if (ret)
goto out_failed;
@@ -693,7 +686,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
if (ret)
goto out_failed_irq;
- if (pdata->setup) {
+ if (pdata && pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0)
@@ -706,7 +699,6 @@ static int __devinit pca953x_probe(struct i2c_client *client,
out_failed_irq:
pca953x_irq_teardown(chip);
out_failed:
- kfree(chip->dyn_pdata);
kfree(chip);
return ret;
}
@@ -717,7 +709,7 @@ static int pca953x_remove(struct i2c_client *client)
struct pca953x_chip *chip = i2c_get_clientdata(client);
int ret = 0;
- if (pdata->teardown) {
+ if (pdata && pdata->teardown) {
ret = pdata->teardown(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0) {
@@ -735,7 +727,6 @@ static int pca953x_remove(struct i2c_client *client)
}
pca953x_irq_teardown(chip);
- kfree(chip->dyn_pdata);
kfree(chip);
return 0;
}
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 879b473aab5a..7369fdda92b0 100644
--- a/drivers/gpio/pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -1,5 +1,5 @@
/*
- * pcf857x - driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
+ * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
*
* Copyright (C) 2007 David Brownell
*
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/gpio-pch.c
index 36919e77c495..36919e77c495 100644
--- a/drivers/gpio/pch_gpio.c
+++ b/drivers/gpio/gpio-pch.c
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/gpio-pl061.c
index 6fcb28cdd862..2c5a18f32bf3 100644
--- a/drivers/gpio/pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -1,7 +1,5 @@
/*
- * linux/drivers/gpio/pl061.c
- *
- * Copyright (C) 2008, 2009 Provigent Ltd.
+ * Copyright (C) 2008, 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 version 2 as
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
index ea37c0461788..ef67f1952a72 100644
--- a/drivers/gpio/gpio-plat-samsung.c
+++ b/drivers/gpio/gpio-plat-samsung.c
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/gpiolib.c
- *
+/*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/gpio-rdc321x.c
index 2762698e0204..2762698e0204 100644
--- a/drivers/gpio/rdc321x-gpio.c
+++ b/drivers/gpio/gpio-rdc321x.c
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
index 2842394b28b5..7f87b0c76e0b 100644
--- a/drivers/gpio/gpio-s5pc100.c
+++ b/drivers/gpio/gpio-s5pc100.c
@@ -1,4 +1,5 @@
-/* linux/arch/arm/mach-s5pc100/gpiolib.c
+/*
+ * S5PC100 - GPIOlib support
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
@@ -6,8 +7,6 @@
* Copyright 2009 Samsung Electronics Co
* Kyungmin Park <kyungmin.park@samsung.com>
*
- * S5PC100 - GPIOlib 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.
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
index 1ba20a703e05..eb12f1602de9 100644
--- a/drivers/gpio/gpio-s5pv210.c
+++ b/drivers/gpio/gpio-s5pv210.c
@@ -1,10 +1,9 @@
-/* linux/arch/arm/mach-s5pv210/gpiolib.c
+/*
+ * S5PV210 - GPIOlib support
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
- * S5PV210 - GPIOlib 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.
diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/gpio-sch.c
index 56060421cdff..163515845494 100644
--- a/drivers/gpio/sch_gpio.c
+++ b/drivers/gpio/gpio-sch.c
@@ -1,5 +1,5 @@
/*
- * sch_gpio.c - GPIO interface for Intel Poulsbo SCH
+ * GPIO interface for Intel Poulsbo SCH
*
* Copyright (c) 2010 CompuLab Ltd
* Author: Denis Turischev <denis@compulab.co.il>
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/gpio-stmpe.c
index 4c980b573328..4c980b573328 100644
--- a/drivers/gpio/stmpe-gpio.c
+++ b/drivers/gpio/gpio-stmpe.c
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/gpio-sx150x.c
index a4f73534394e..a4f73534394e 100644
--- a/drivers/gpio/sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/gpio-tc3589x.c
index 2a82e8999a42..2a82e8999a42 100644
--- a/drivers/gpio/tc3589x-gpio.c
+++ b/drivers/gpio/gpio-tc3589x.c
diff --git a/arch/arm/mach-tegra/gpio.c b/drivers/gpio/gpio-tegra.c
index 919d63837736..747eb40e8afe 100644
--- a/arch/arm/mach-tegra/gpio.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -23,6 +23,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/of.h>
#include <asm/mach/irq.h>
@@ -340,6 +341,15 @@ static int __init tegra_gpio_init(void)
}
}
+#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 */
+
gpiochip_add(&tegra_gpio_chip);
for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/gpio-timberdale.c
index 0265872e57d1..c593bd46bfb6 100644
--- a/drivers/gpio/timbgpio.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -1,5 +1,5 @@
/*
- * timbgpio.c timberdale FPGA GPIO driver
+ * Timberdale FPGA GPIO driver
* Copyright (c) 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/tps65910-gpio.c b/drivers/gpio/gpio-tps65910.c
index 15097ca616d6..b9c1c297669e 100644
--- a/drivers/gpio/tps65910-gpio.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -1,5 +1,5 @@
/*
- * tps65910-gpio.c -- TI TPS6591x
+ * TI TPS6591x GPIO driver
*
* Copyright 2010 Texas Instruments Inc.
*
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/gpio-twl4030.c
index 57635ac35a73..b8b4f228757c 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -1,5 +1,5 @@
/*
- * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips
+ * Access to GPIOs on TWL4030/TPS659x0 chips
*
* Copyright (C) 2006-2007 Texas Instruments, Inc.
* Copyright (C) 2006 MontaVista Software, Inc.
diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c
index d92790140fe5..53e8255cb0ba 100644
--- a/drivers/gpio/gpio-u300.c
+++ b/drivers/gpio/gpio-u300.c
@@ -1,11 +1,8 @@
/*
- *
- * arch/arm/mach-u300/gpio.c
- *
+ * U300 GPIO module.
*
* Copyright (C) 2007-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
- * U300 GPIO module.
* 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)
@@ -581,8 +578,8 @@ static int __init gpio_probe(struct platform_device *pdev)
if (!memres)
goto err_no_resource;
- if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller")
- == NULL) {
+ if (!request_mem_region(memres->start, resource_size(memres),
+ "GPIO Controller")) {
err = -ENODEV;
goto err_no_ioregion;
}
@@ -640,7 +637,7 @@ static int __init gpio_probe(struct platform_device *pdev)
free_irq(gpio_ports[i].irq, &gpio_ports[i]);
iounmap(virtbase);
err_no_ioremap:
- release_mem_region(memres->start, memres->end - memres->start);
+ release_mem_region(memres->start, resource_size(memres));
err_no_ioregion:
err_no_resource:
clk_disable(clk);
@@ -660,7 +657,7 @@ static int __exit gpio_remove(struct platform_device *pdev)
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, memres->end - memres->start);
+ release_mem_region(memres->start, resource_size(memres));
clk_disable(clk);
clk_put(clk);
return 0;
diff --git a/drivers/gpio/ucb1400_gpio.c b/drivers/gpio/gpio-ucb1400.c
index 50e6bd1392ce..50e6bd1392ce 100644
--- a/drivers/gpio/ucb1400_gpio.c
+++ b/drivers/gpio/gpio-ucb1400.c
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/gpio-vr41xx.c
index a365be040b36..98723cb9ac68 100644
--- a/drivers/gpio/vr41xx_giu.c
+++ b/drivers/gpio/gpio-vr41xx.c
@@ -518,7 +518,7 @@ static int __devinit giu_probe(struct platform_device *pdev)
if (!res)
return -EBUSY;
- giu_base = ioremap(res->start, res->end - res->start + 1);
+ giu_base = ioremap(res->start, resource_size(res));
if (!giu_base)
return -ENOMEM;
diff --git a/drivers/gpio/vx855_gpio.c b/drivers/gpio/gpio-vx855.c
index ef5aabd8b8b7..ef5aabd8b8b7 100644
--- a/drivers/gpio/vx855_gpio.c
+++ b/drivers/gpio/gpio-vx855.c
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/gpio-wm831x.c
index 2bcfb0be09ff..deb949e75ec1 100644
--- a/drivers/gpio/wm831x-gpio.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -1,5 +1,5 @@
/*
- * wm831x-gpio.c -- gpiolib support for Wolfson WM831x PMICs
+ * gpiolib support for Wolfson WM831x PMICs
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
diff --git a/drivers/gpio/wm8350-gpiolib.c b/drivers/gpio/gpio-wm8350.c
index 359999290f55..a06af5154838 100644
--- a/drivers/gpio/wm8350-gpiolib.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -1,5 +1,5 @@
/*
- * wm835x-gpiolib.c -- gpiolib support for Wolfson WM835x PMICs
+ * gpiolib support for Wolfson WM835x PMICs
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/gpio-wm8994.c
index c822baacd8fc..96198f3fab73 100644
--- a/drivers/gpio/wm8994-gpio.c
+++ b/drivers/gpio/gpio-wm8994.c
@@ -1,5 +1,5 @@
/*
- * wm8994-gpio.c -- gpiolib support for Wolfson WM8994
+ * gpiolib support for Wolfson WM8994
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/gpio-xilinx.c
index 846fbd5e31bf..846fbd5e31bf 100644
--- a/drivers/gpio/xilinx_gpio.c
+++ b/drivers/gpio/gpio-xilinx.c
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 92369655dca3..f88a9b2c977b 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -560,6 +560,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
mode_changed = true;
} else if (set->fb == NULL) {
mode_changed = true;
+ } else if (set->fb->depth != set->crtc->fb->depth) {
+ mode_changed = true;
+ } else if (set->fb->bits_per_pixel !=
+ set->crtc->fb->bits_per_pixel) {
+ mode_changed = true;
} else
fb_changed = true;
}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 09292193dafe..756af4d7ec74 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -185,8 +185,8 @@ drm_edid_block_valid(u8 *raw_edid)
bad:
if (raw_edid) {
printk(KERN_ERR "Raw EDID:\n");
- print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
- printk(KERN_ERR "\n");
+ print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
+ raw_edid, EDID_LENGTH, false);
}
return 0;
}
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 4012fe423460..186d62eb063b 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -129,7 +129,7 @@ drm_gem_destroy(struct drm_device *dev)
}
/**
- * Initialize an already allocate GEM object of the specified size with
+ * Initialize an already allocated GEM object of the specified size with
* shmfs backing store.
*/
int drm_gem_object_init(struct drm_device *dev,
@@ -151,6 +151,27 @@ int drm_gem_object_init(struct drm_device *dev,
EXPORT_SYMBOL(drm_gem_object_init);
/**
+ * Initialize an already allocated GEM object of the specified size with
+ * no GEM provided backing store. Instead the caller is responsible for
+ * backing the object and handling it.
+ */
+int drm_gem_private_object_init(struct drm_device *dev,
+ struct drm_gem_object *obj, size_t size)
+{
+ BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+
+ obj->dev = dev;
+ obj->filp = NULL;
+
+ kref_init(&obj->refcount);
+ atomic_set(&obj->handle_count, 0);
+ obj->size = size;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_gem_private_object_init);
+
+/**
* Allocate a GEM object of the specified size with shmfs backing store
*/
struct drm_gem_object *
@@ -211,6 +232,8 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
idr_remove(&filp->object_idr, handle);
spin_unlock(&filp->table_lock);
+ if (dev->driver->gem_close_object)
+ dev->driver->gem_close_object(obj, filp);
drm_gem_object_handle_unreference_unlocked(obj);
return 0;
@@ -227,7 +250,8 @@ drm_gem_handle_create(struct drm_file *file_priv,
struct drm_gem_object *obj,
u32 *handlep)
{
- int ret;
+ struct drm_device *dev = obj->dev;
+ int ret;
/*
* Get the user-visible handle using idr.
@@ -248,6 +272,15 @@ again:
return ret;
drm_gem_object_handle_reference(obj);
+
+ if (dev->driver->gem_open_object) {
+ ret = dev->driver->gem_open_object(obj, file_priv);
+ if (ret) {
+ drm_gem_handle_delete(file_priv, *handlep);
+ return ret;
+ }
+ }
+
return 0;
}
EXPORT_SYMBOL(drm_gem_handle_create);
@@ -402,7 +435,12 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
static int
drm_gem_object_release_handle(int id, void *ptr, void *data)
{
+ struct drm_file *file_priv = data;
struct drm_gem_object *obj = ptr;
+ struct drm_device *dev = obj->dev;
+
+ if (dev->driver->gem_close_object)
+ dev->driver->gem_close_object(obj, file_priv);
drm_gem_object_handle_unreference_unlocked(obj);
@@ -418,7 +456,7 @@ void
drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
{
idr_for_each(&file_private->object_idr,
- &drm_gem_object_release_handle, NULL);
+ &drm_gem_object_release_handle, file_private);
idr_remove_all(&file_private->object_idr);
idr_destroy(&file_private->object_idr);
@@ -427,7 +465,8 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
void
drm_gem_object_release(struct drm_gem_object *obj)
{
- fput(obj->filp);
+ if (obj->filp)
+ fput(obj->filp);
}
EXPORT_SYMBOL(drm_gem_object_release);
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index c2d32f20e2fb..ad74fb4dc542 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -994,9 +994,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
{
const char *name;
unsigned int namelen;
- int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+ bool res_specified = false, bpp_specified = false, refresh_specified = false;
unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
- int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
+ bool yres_specified = false, cvt = false, rb = false;
+ bool interlace = false, margins = false, was_digit = false;
int i;
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
@@ -1015,54 +1016,65 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
for (i = namelen-1; i >= 0; i--) {
switch (name[i]) {
case '@':
- namelen = i;
if (!refresh_specified && !bpp_specified &&
- !yres_specified) {
+ !yres_specified && !cvt && !rb && was_digit) {
refresh = simple_strtol(&name[i+1], NULL, 10);
- refresh_specified = 1;
- if (cvt || rb)
- cvt = 0;
+ refresh_specified = true;
+ was_digit = false;
} else
goto done;
break;
case '-':
- namelen = i;
- if (!bpp_specified && !yres_specified) {
+ if (!bpp_specified && !yres_specified && !cvt &&
+ !rb && was_digit) {
bpp = simple_strtol(&name[i+1], NULL, 10);
- bpp_specified = 1;
- if (cvt || rb)
- cvt = 0;
+ bpp_specified = true;
+ was_digit = false;
} else
goto done;
break;
case 'x':
- if (!yres_specified) {
+ if (!yres_specified && was_digit) {
yres = simple_strtol(&name[i+1], NULL, 10);
- yres_specified = 1;
+ yres_specified = true;
+ was_digit = false;
} else
goto done;
case '0' ... '9':
+ was_digit = true;
break;
case 'M':
- if (!yres_specified)
- cvt = 1;
+ if (yres_specified || cvt || was_digit)
+ goto done;
+ cvt = true;
break;
case 'R':
- if (cvt)
- rb = 1;
+ if (yres_specified || cvt || rb || was_digit)
+ goto done;
+ rb = true;
break;
case 'm':
- if (!cvt)
- margins = 1;
+ if (cvt || yres_specified || was_digit)
+ goto done;
+ margins = true;
break;
case 'i':
- if (!cvt)
- interlace = 1;
+ if (cvt || yres_specified || was_digit)
+ goto done;
+ interlace = true;
break;
case 'e':
+ if (yres_specified || bpp_specified || refresh_specified ||
+ was_digit || (force != DRM_FORCE_UNSPECIFIED))
+ goto done;
+
force = DRM_FORCE_ON;
break;
case 'D':
+ if (yres_specified || bpp_specified || refresh_specified ||
+ was_digit || (force != DRM_FORCE_UNSPECIFIED))
+ goto done;
+
if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
(connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
force = DRM_FORCE_ON;
@@ -1070,17 +1082,37 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
force = DRM_FORCE_ON_DIGITAL;
break;
case 'd':
+ if (yres_specified || bpp_specified || refresh_specified ||
+ was_digit || (force != DRM_FORCE_UNSPECIFIED))
+ goto done;
+
force = DRM_FORCE_OFF;
break;
default:
goto done;
}
}
+
if (i < 0 && yres_specified) {
- xres = simple_strtol(name, NULL, 10);
- res_specified = 1;
+ char *ch;
+ xres = simple_strtol(name, &ch, 10);
+ if ((ch != NULL) && (*ch == 'x'))
+ res_specified = true;
+ else
+ i = ch - name;
+ } else if (!yres_specified && was_digit) {
+ /* catch mode that begins with digits but has no 'x' */
+ i = 0;
}
done:
+ if (i >= 0) {
+ printk(KERN_WARNING
+ "parse error at position %i in video mode '%s'\n",
+ i, name);
+ mode->specified = false;
+ return false;
+ }
+
if (res_specified) {
mode->specified = true;
mode->xres = xres;
@@ -1096,9 +1128,10 @@ done:
mode->bpp_specified = true;
mode->bpp = bpp;
}
- mode->rb = rb ? true : false;
- mode->cvt = cvt ? true : false;
- mode->interlace = interlace ? true : false;
+ mode->rb = rb;
+ mode->cvt = cvt;
+ mode->interlace = interlace;
+ mode->margins = margins;
mode->force = force;
return true;
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 7223f06d8e58..2a8b6265ad3d 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -123,14 +123,15 @@ static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *mas
{
int len, ret;
- master->unique_len = 10 + strlen(dev->platformdev->name);
+ master->unique_len = 13 + strlen(dev->platformdev->name);
+ master->unique_size = master->unique_len;
master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
if (master->unique == NULL)
return -ENOMEM;
len = snprintf(master->unique, master->unique_len,
- "platform:%s", dev->platformdev->name);
+ "platform:%s:%02d", dev->platformdev->name, dev->platformdev->id);
if (len > master->unique_len) {
DRM_ERROR("Unique buffer overflowed\n");
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c
index d15e09b0ae0b..7525e0311e59 100644
--- a/drivers/gpu/drm/drm_scatter.c
+++ b/drivers/gpu/drm/drm_scatter.c
@@ -83,30 +83,26 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
if (dev->sg)
return -EINVAL;
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
- memset(entry, 0, sizeof(*entry));
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
entry->pages = pages;
- entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL);
+ entry->pagelist = kcalloc(pages, sizeof(*entry->pagelist), GFP_KERNEL);
if (!entry->pagelist) {
kfree(entry);
return -ENOMEM;
}
- memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
-
- entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL);
+ entry->busaddr = kcalloc(pages, sizeof(*entry->busaddr), GFP_KERNEL);
if (!entry->busaddr) {
kfree(entry->pagelist);
kfree(entry);
return -ENOMEM;
}
- memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
if (!entry->virtual) {
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 0a893f7400fa..e2662497d50f 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -865,7 +865,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
MEMSTAT_VID_SHIFT);
seq_printf(m, "Current P-state: %d\n",
(rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
- } else if (IS_GEN6(dev)) {
+ } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -1123,6 +1123,44 @@ static int i915_emon_status(struct seq_file *m, void *unused)
return 0;
}
+static int i915_ring_freq_table(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
+ int gpu_freq, ia_freq;
+
+ if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
+ seq_printf(m, "unsupported on this chipset\n");
+ return 0;
+ }
+
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
+ if (ret)
+ return ret;
+
+ seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");
+
+ for (gpu_freq = dev_priv->min_delay; gpu_freq <= dev_priv->max_delay;
+ gpu_freq++) {
+ I915_WRITE(GEN6_PCODE_DATA, gpu_freq);
+ I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
+ GEN6_PCODE_READ_MIN_FREQ_TABLE);
+ if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
+ GEN6_PCODE_READY) == 0, 10)) {
+ DRM_ERROR("pcode read of freq table timed out\n");
+ continue;
+ }
+ ia_freq = I915_READ(GEN6_PCODE_DATA);
+ seq_printf(m, "%d\t\t%d\n", gpu_freq * 50, ia_freq * 100);
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
static int i915_gfxec(struct seq_file *m, void *unused)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -1430,6 +1468,7 @@ static struct drm_info_list i915_debugfs_list[] = {
{"i915_inttoext_table", i915_inttoext_table, 0},
{"i915_drpc_info", i915_drpc_info, 0},
{"i915_emon_status", i915_emon_status, 0},
+ {"i915_ring_freq_table", i915_ring_freq_table, 0},
{"i915_gfxec", i915_gfxec, 0},
{"i915_fbc_status", i915_fbc_status, 0},
{"i915_sr_status", i915_sr_status, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 296fbd66f0e1..12712824a6d2 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1073,6 +1073,9 @@ static void i915_setup_compression(struct drm_device *dev, int size)
unsigned long cfb_base;
unsigned long ll_base = 0;
+ /* Just in case the BIOS is doing something questionable. */
+ intel_disable_fbc(dev);
+
compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
if (compressed_fb)
compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
@@ -1099,7 +1102,6 @@ static void i915_setup_compression(struct drm_device *dev, int size)
dev_priv->cfb_size = size;
- intel_disable_fbc(dev);
dev_priv->compressed_fb = compressed_fb;
if (HAS_PCH_SPLIT(dev))
I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index eb91e2dd7914..ce045a8cf82c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -37,38 +37,70 @@
#include <linux/console.h>
#include "drm_crtc_helper.h"
-static int i915_modeset = -1;
+static int i915_modeset __read_mostly = -1;
module_param_named(modeset, i915_modeset, int, 0400);
+MODULE_PARM_DESC(modeset,
+ "Use kernel modesetting [KMS] (0=DRM_I915_KMS from .config, "
+ "1=on, -1=force vga console preference [default])");
-unsigned int i915_fbpercrtc = 0;
+unsigned int i915_fbpercrtc __always_unused = 0;
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
-int i915_panel_ignore_lid = 0;
+int i915_panel_ignore_lid __read_mostly = 0;
module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
+MODULE_PARM_DESC(panel_ignore_lid,
+ "Override lid status (0=autodetect [default], 1=lid open, "
+ "-1=lid closed)");
-unsigned int i915_powersave = 1;
+unsigned int i915_powersave __read_mostly = 1;
module_param_named(powersave, i915_powersave, int, 0600);
+MODULE_PARM_DESC(powersave,
+ "Enable powersavings, fbc, downclocking, etc. (default: true)");
-unsigned int i915_semaphores = 0;
+unsigned int i915_semaphores __read_mostly = 0;
module_param_named(semaphores, i915_semaphores, int, 0600);
+MODULE_PARM_DESC(semaphores,
+ "Use semaphores for inter-ring sync (default: false)");
-unsigned int i915_enable_rc6 = 0;
+unsigned int i915_enable_rc6 __read_mostly = 0;
module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
+MODULE_PARM_DESC(i915_enable_rc6,
+ "Enable power-saving render C-state 6 (default: true)");
-unsigned int i915_enable_fbc = 0;
+unsigned int i915_enable_fbc __read_mostly = 1;
module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
+MODULE_PARM_DESC(i915_enable_fbc,
+ "Enable frame buffer compression for power savings "
+ "(default: false)");
-unsigned int i915_lvds_downclock = 0;
+unsigned int i915_lvds_downclock __read_mostly = 0;
module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
+MODULE_PARM_DESC(lvds_downclock,
+ "Use panel (LVDS/eDP) downclocking for power savings "
+ "(default: false)");
-unsigned int i915_panel_use_ssc = 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)");
-int i915_vbt_sdvo_panel_type = -1;
+int i915_vbt_sdvo_panel_type __read_mostly = -1;
module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
+MODULE_PARM_DESC(vbt_sdvo_panel_type,
+ "Override selection of SDVO panel mode in the VBT "
+ "(default: auto)");
-static bool i915_try_reset = true;
+static bool i915_try_reset __read_mostly = true;
module_param_named(reset, i915_try_reset, bool, 0600);
+MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)");
+
+bool i915_enable_hangcheck __read_mostly = true;
+module_param_named(enable_hangcheck, i915_enable_hangcheck, bool, 0644);
+MODULE_PARM_DESC(enable_hangcheck,
+ "Periodically check GPU activity for detecting hangs. "
+ "WARNING: Disabling this can cause system wide hangs. "
+ "(default: true)");
static struct drm_driver driver;
extern int intel_agp_enabled;
@@ -345,12 +377,17 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
{
- int loop = 500;
- u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
- while (fifo < 20 && loop--) {
- udelay(10);
- fifo = I915_READ_NOTRACE(GT_FIFO_FREE_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--) {
+ udelay(10);
+ fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+ }
+ WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES);
+ dev_priv->gt_fifo_count = fifo;
}
+ dev_priv->gt_fifo_count--;
}
static int i915_drm_freeze(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ce7914c4c044..6867e193d85e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -214,6 +214,8 @@ struct drm_i915_display_funcs {
int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj);
+ int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int x, int y);
/* clock updates for mode set */
/* cursor updates */
/* render clock increase/decrease */
@@ -265,6 +267,7 @@ enum intel_pch {
#define QUIRK_LVDS_SSC_DISABLE (1<<1)
struct intel_fbdev;
+struct intel_fbc_work;
typedef struct drm_i915_private {
struct drm_device *dev;
@@ -275,6 +278,7 @@ typedef struct drm_i915_private {
int relative_constants_mode;
void __iomem *regs;
+ u32 gt_fifo_count;
struct intel_gmbus {
struct i2c_adapter adapter;
@@ -329,11 +333,10 @@ typedef struct drm_i915_private {
uint32_t last_instdone1;
unsigned long cfb_size;
- unsigned long cfb_pitch;
- unsigned long cfb_offset;
- int cfb_fence;
- int cfb_plane;
+ unsigned int cfb_fb;
+ enum plane cfb_plane;
int cfb_y;
+ struct intel_fbc_work *fbc_work;
struct intel_opregion opregion;
@@ -986,15 +989,16 @@ struct drm_i915_file_private {
extern struct drm_ioctl_desc i915_ioctls[];
extern int i915_max_ioctl;
-extern unsigned int i915_fbpercrtc;
-extern int i915_panel_ignore_lid;
-extern unsigned int i915_powersave;
-extern unsigned int i915_semaphores;
-extern unsigned int i915_lvds_downclock;
-extern unsigned int i915_panel_use_ssc;
-extern int i915_vbt_sdvo_panel_type;
-extern unsigned int i915_enable_rc6;
-extern unsigned int i915_enable_fbc;
+extern unsigned int i915_fbpercrtc __always_unused;
+extern int i915_panel_ignore_lid __read_mostly;
+extern unsigned int i915_powersave __read_mostly;
+extern unsigned int i915_semaphores __read_mostly;
+extern unsigned int i915_lvds_downclock __read_mostly;
+extern unsigned int i915_panel_use_ssc __read_mostly;
+extern int i915_vbt_sdvo_panel_type __read_mostly;
+extern unsigned int i915_enable_rc6 __read_mostly;
+extern unsigned int i915_enable_fbc __read_mostly;
+extern bool i915_enable_hangcheck __read_mostly;
extern int i915_suspend(struct drm_device *dev, pm_message_t state);
extern int i915_resume(struct drm_device *dev);
@@ -1164,7 +1168,7 @@ void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
uint32_t read_domains,
uint32_t write_domain);
-int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
int __must_check i915_gem_init_ringbuffer(struct drm_device *dev);
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
void i915_gem_do_init(struct drm_device *dev,
@@ -1183,7 +1187,8 @@ int __must_check
i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
bool write);
int __must_check
-i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
+ u32 alignment,
struct intel_ring_buffer *pipelined);
int i915_gem_attach_phys_object(struct drm_device *dev,
struct drm_i915_gem_object *obj,
@@ -1199,9 +1204,14 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev,
uint32_t size,
int tiling_mode);
+int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
+ enum i915_cache_level cache_level);
+
/* i915_gem_gtt.c */
void i915_gem_restore_gtt_mappings(struct drm_device *dev);
int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
+void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
+ enum i915_cache_level cache_level);
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
/* i915_gem_evict.c */
@@ -1283,12 +1293,8 @@ extern void intel_modeset_init(struct drm_device *dev);
extern void intel_modeset_gem_init(struct drm_device *dev);
extern void intel_modeset_cleanup(struct drm_device *dev);
extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
-extern void i8xx_disable_fbc(struct drm_device *dev);
-extern void g4x_disable_fbc(struct drm_device *dev);
-extern void ironlake_disable_fbc(struct drm_device *dev);
-extern void intel_disable_fbc(struct drm_device *dev);
-extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
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_enable_rc6(struct drm_device *dev);
extern void gen6_set_rps(struct drm_device *dev, u8 val);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a087e1bf0c2f..d1cd8b89f47d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1763,8 +1763,11 @@ i915_add_request(struct intel_ring_buffer *ring,
ring->outstanding_lazy_request = false;
if (!dev_priv->mm.suspended) {
- mod_timer(&dev_priv->hangcheck_timer,
- jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+ if (i915_enable_hangcheck) {
+ mod_timer(&dev_priv->hangcheck_timer,
+ jiffies +
+ msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+ }
if (was_empty)
queue_delayed_work(dev_priv->wq,
&dev_priv->mm.retire_work, HZ);
@@ -2135,6 +2138,30 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
return 0;
}
+static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
+{
+ u32 old_write_domain, old_read_domains;
+
+ /* Act a barrier for all accesses through the GTT */
+ mb();
+
+ /* Force a pagefault for domain tracking on next user access */
+ i915_gem_release_mmap(obj);
+
+ if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
+ return;
+
+ old_read_domains = obj->base.read_domains;
+ old_write_domain = obj->base.write_domain;
+
+ obj->base.read_domains &= ~I915_GEM_DOMAIN_GTT;
+ obj->base.write_domain &= ~I915_GEM_DOMAIN_GTT;
+
+ trace_i915_gem_object_change_domain(obj,
+ old_read_domains,
+ old_write_domain);
+}
+
/**
* Unbinds an object from the GTT aperture.
*/
@@ -2151,23 +2178,28 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
return -EINVAL;
}
- /* blow away mappings if mapped through GTT */
- i915_gem_release_mmap(obj);
-
- /* Move the object to the CPU domain to ensure that
- * any possible CPU writes while it's not in the GTT
- * are flushed when we go to remap it. This will
- * also ensure that all pending GPU writes are finished
- * before we unbind.
- */
- ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+ ret = i915_gem_object_finish_gpu(obj);
if (ret == -ERESTARTSYS)
return ret;
/* Continue on if we fail due to EIO, the GPU is hung so we
* should be safe and we need to cleanup or else we might
* cause memory corruption through use-after-free.
*/
+
+ i915_gem_object_finish_gtt(obj);
+
+ /* Move the object to the CPU domain to ensure that
+ * any possible CPU writes while it's not in the GTT
+ * are flushed when we go to remap it.
+ */
+ if (ret == 0)
+ ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+ if (ret == -ERESTARTSYS)
+ return ret;
if (ret) {
+ /* In the event of a disaster, abandon all caches and
+ * hope for the best.
+ */
i915_gem_clflush_object(obj);
obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
}
@@ -2996,51 +3028,139 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
return 0;
}
+int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
+ enum i915_cache_level cache_level)
+{
+ int ret;
+
+ if (obj->cache_level == cache_level)
+ return 0;
+
+ if (obj->pin_count) {
+ DRM_DEBUG("can not change the cache level of pinned objects\n");
+ return -EBUSY;
+ }
+
+ if (obj->gtt_space) {
+ ret = i915_gem_object_finish_gpu(obj);
+ if (ret)
+ return ret;
+
+ i915_gem_object_finish_gtt(obj);
+
+ /* Before SandyBridge, you could not use tiling or fence
+ * registers with snooped memory, so relinquish any fences
+ * currently pointing to our region in the aperture.
+ */
+ if (INTEL_INFO(obj->base.dev)->gen < 6) {
+ ret = i915_gem_object_put_fence(obj);
+ if (ret)
+ return ret;
+ }
+
+ i915_gem_gtt_rebind_object(obj, cache_level);
+ }
+
+ if (cache_level == I915_CACHE_NONE) {
+ u32 old_read_domains, old_write_domain;
+
+ /* If we're coming from LLC cached, then we haven't
+ * actually been tracking whether the data is in the
+ * CPU cache or not, since we only allow one bit set
+ * in obj->write_domain and have been skipping the clflushes.
+ * Just set it to the CPU cache for now.
+ */
+ WARN_ON(obj->base.write_domain & ~I915_GEM_DOMAIN_CPU);
+ WARN_ON(obj->base.read_domains & ~I915_GEM_DOMAIN_CPU);
+
+ old_read_domains = obj->base.read_domains;
+ old_write_domain = obj->base.write_domain;
+
+ obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+ obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+
+ trace_i915_gem_object_change_domain(obj,
+ old_read_domains,
+ old_write_domain);
+ }
+
+ obj->cache_level = cache_level;
+ return 0;
+}
+
/*
- * Prepare buffer for display plane. Use uninterruptible for possible flush
- * wait, as in modesetting process we're not supposed to be interrupted.
+ * Prepare buffer for display plane (scanout, cursors, etc).
+ * Can be called from an uninterruptible phase (modesetting) and allows
+ * any flushes to be pipelined (for pageflips).
+ *
+ * For the display plane, we want to be in the GTT but out of any write
+ * domains. So in many ways this looks like set_to_gtt_domain() apart from the
+ * ability to pipeline the waits, pinning and any additional subtleties
+ * that may differentiate the display plane from ordinary buffers.
*/
int
-i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
+ u32 alignment,
struct intel_ring_buffer *pipelined)
{
- uint32_t old_read_domains;
+ u32 old_read_domains, old_write_domain;
int ret;
- /* Not valid to be called on unbound objects. */
- if (obj->gtt_space == NULL)
- return -EINVAL;
-
ret = i915_gem_object_flush_gpu_write_domain(obj);
if (ret)
return ret;
-
- /* Currently, we are always called from an non-interruptible context. */
if (pipelined != obj->ring) {
ret = i915_gem_object_wait_rendering(obj);
if (ret)
return ret;
}
+ /* The display engine is not coherent with the LLC cache on gen6. As
+ * a result, we make sure that the pinning that is about to occur is
+ * done with uncached PTEs. This is lowest common denominator for all
+ * chipsets.
+ *
+ * However for gen6+, we could do better by using the GFDT bit instead
+ * of uncaching, which would allow us to flush all the LLC-cached data
+ * with that bit in the PTE to main memory with just one PIPE_CONTROL.
+ */
+ ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
+ if (ret)
+ return ret;
+
+ /* As the user may map the buffer once pinned in the display plane
+ * (e.g. libkms for the bootup splash), we have to ensure that we
+ * always use map_and_fenceable for all scanout buffers.
+ */
+ ret = i915_gem_object_pin(obj, alignment, true);
+ if (ret)
+ return ret;
+
i915_gem_object_flush_cpu_write_domain(obj);
+ old_write_domain = obj->base.write_domain;
old_read_domains = obj->base.read_domains;
+
+ /* It should now be out of any other write domains, and we can update
+ * the domain values for our changes.
+ */
+ BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
trace_i915_gem_object_change_domain(obj,
old_read_domains,
- obj->base.write_domain);
+ old_write_domain);
return 0;
}
int
-i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
+i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
{
int ret;
- if (!obj->active)
+ if ((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0)
return 0;
if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
@@ -3049,6 +3169,9 @@ i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
return ret;
}
+ /* Ensure that we invalidate the GPU's caches and TLBs. */
+ obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
+
return i915_gem_object_wait_rendering(obj);
}
@@ -3575,7 +3698,23 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
obj->base.write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU;
- obj->cache_level = I915_CACHE_NONE;
+ if (IS_GEN6(dev)) {
+ /* On Gen6, we can have the GPU use the LLC (the CPU
+ * cache) for about a 10% performance improvement
+ * compared to uncached. Graphics requests other than
+ * display scanout are coherent with the CPU in
+ * accessing this cache. This means in this mode we
+ * don't need to clflush on the CPU side, and on the
+ * GPU side we only need to flush internal caches to
+ * get data visible to the CPU.
+ *
+ * However, we maintain the display planes as UC, and so
+ * need to rebind when first used as such.
+ */
+ obj->cache_level = I915_CACHE_LLC;
+ } else
+ obj->cache_level = I915_CACHE_NONE;
+
obj->base.driver_private = NULL;
obj->fence_reg = I915_FENCE_REG_NONE;
INIT_LIST_HEAD(&obj->mm_list);
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index e46b645773cf..7a709cd8d543 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -59,24 +59,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
(dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
- unsigned int agp_type =
- cache_level_to_agp_type(dev, obj->cache_level);
-
i915_gem_clflush_object(obj);
-
- if (dev_priv->mm.gtt->needs_dmar) {
- BUG_ON(!obj->sg_list);
-
- intel_gtt_insert_sg_entries(obj->sg_list,
- obj->num_sg,
- obj->gtt_space->start >> PAGE_SHIFT,
- agp_type);
- } else
- intel_gtt_insert_pages(obj->gtt_space->start
- >> PAGE_SHIFT,
- obj->base.size >> PAGE_SHIFT,
- obj->pages,
- agp_type);
+ i915_gem_gtt_rebind_object(obj, obj->cache_level);
}
intel_gtt_chipset_flush();
@@ -110,6 +94,27 @@ int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
return 0;
}
+void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
+ enum i915_cache_level cache_level)
+{
+ struct drm_device *dev = obj->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned int agp_type = cache_level_to_agp_type(dev, cache_level);
+
+ if (dev_priv->mm.gtt->needs_dmar) {
+ BUG_ON(!obj->sg_list);
+
+ intel_gtt_insert_sg_entries(obj->sg_list,
+ obj->num_sg,
+ obj->gtt_space->start >> PAGE_SHIFT,
+ agp_type);
+ } else
+ intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
+ obj->base.size >> PAGE_SHIFT,
+ obj->pages,
+ agp_type);
+}
+
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
{
intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 3b03f85ea627..23d1ae67d279 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -361,10 +361,12 @@ static void notify_ring(struct drm_device *dev,
ring->irq_seqno = seqno;
wake_up_all(&ring->irq_queue);
-
- dev_priv->hangcheck_count = 0;
- mod_timer(&dev_priv->hangcheck_timer,
- jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+ if (i915_enable_hangcheck) {
+ dev_priv->hangcheck_count = 0;
+ mod_timer(&dev_priv->hangcheck_timer,
+ jiffies +
+ msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+ }
}
static void gen6_pm_rps_work(struct work_struct *work)
@@ -1664,6 +1666,9 @@ void i915_hangcheck_elapsed(unsigned long data)
uint32_t acthd, instdone, instdone1;
bool err = false;
+ if (!i915_enable_hangcheck)
+ return;
+
/* If all work is done then ACTHD clearly hasn't advanced. */
if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5d5def756c9e..02db299f621a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -579,6 +579,7 @@
#define DPFC_CTL_PLANEA (0<<30)
#define DPFC_CTL_PLANEB (1<<30)
#define DPFC_CTL_FENCE_EN (1<<29)
+#define DPFC_CTL_PERSISTENT_MODE (1<<25)
#define DPFC_SR_EN (1<<10)
#define DPFC_CTL_LIMIT_1X (0<<6)
#define DPFC_CTL_LIMIT_2X (1<<6)
@@ -3360,6 +3361,7 @@
#define FORCEWAKE_ACK 0x130090
#define GT_FIFO_FREE_ENTRIES 0x120008
+#define GT_FIFO_NUM_RESERVED_ENTRIES 20
#define GEN6_RPNSWREQ 0xA008
#define GEN6_TURBO_DISABLE (1<<31)
@@ -3434,7 +3436,9 @@
#define GEN6_PCODE_MAILBOX 0x138124
#define GEN6_PCODE_READY (1<<31)
#define GEN6_READ_OC_PARAMS 0xc
-#define GEN6_PCODE_WRITE_MIN_FREQ_TABLE 0x9
+#define GEN6_PCODE_WRITE_MIN_FREQ_TABLE 0x8
+#define GEN6_PCODE_READ_MIN_FREQ_TABLE 0x9
#define GEN6_PCODE_DATA 0x138128
+#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 5257cfc34c35..285758603ac8 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -760,15 +760,13 @@ static void i915_restore_display(struct drm_device *dev)
/* FIXME: restore TV & SDVO state */
/* only restore FBC info on the platform that supports FBC*/
+ intel_disable_fbc(dev);
if (I915_HAS_FBC(dev)) {
if (HAS_PCH_SPLIT(dev)) {
- ironlake_disable_fbc(dev);
I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
} else if (IS_GM45(dev)) {
- g4x_disable_fbc(dev);
I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
} else {
- i8xx_disable_fbc(dev);
I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
@@ -878,8 +876,10 @@ int i915_restore_state(struct drm_device *dev)
intel_init_emon(dev);
}
- if (IS_GEN6(dev))
+ if (IS_GEN6(dev)) {
gen6_enable_rps(dev_priv);
+ gen6_update_ring_freq(dev_priv);
+ }
mutex_lock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 927442a11925..61abef8a8119 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -74,7 +74,7 @@ get_blocksize(void *p)
static void
fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
- struct lvds_dvo_timing *dvo_timing)
+ const struct lvds_dvo_timing *dvo_timing)
{
panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
dvo_timing->hactive_lo;
@@ -115,20 +115,75 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
drm_mode_set_name(panel_fixed_mode);
}
+static bool
+lvds_dvo_timing_equal_size(const struct lvds_dvo_timing *a,
+ const struct lvds_dvo_timing *b)
+{
+ if (a->hactive_hi != b->hactive_hi ||
+ a->hactive_lo != b->hactive_lo)
+ return false;
+
+ if (a->hsync_off_hi != b->hsync_off_hi ||
+ a->hsync_off_lo != b->hsync_off_lo)
+ return false;
+
+ if (a->hsync_pulse_width != b->hsync_pulse_width)
+ return false;
+
+ if (a->hblank_hi != b->hblank_hi ||
+ a->hblank_lo != b->hblank_lo)
+ return false;
+
+ if (a->vactive_hi != b->vactive_hi ||
+ a->vactive_lo != b->vactive_lo)
+ return false;
+
+ if (a->vsync_off != b->vsync_off)
+ return false;
+
+ if (a->vsync_pulse_width != b->vsync_pulse_width)
+ return false;
+
+ if (a->vblank_hi != b->vblank_hi ||
+ a->vblank_lo != b->vblank_lo)
+ return false;
+
+ return true;
+}
+
+static const struct lvds_dvo_timing *
+get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
+ const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
+ int index)
+{
+ /*
+ * the size of fp_timing varies on the different platform.
+ * So calculate the DVO timing relative offset in LVDS data
+ * entry to get the DVO timing entry
+ */
+
+ int lfp_data_size =
+ lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
+ lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
+ int dvo_timing_offset =
+ lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
+ lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
+ char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
+
+ return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
+}
+
/* Try to find integrated panel data */
static void
parse_lfp_panel_data(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
- struct bdb_lvds_options *lvds_options;
- struct bdb_lvds_lfp_data *lvds_lfp_data;
- struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
- struct bdb_lvds_lfp_data_entry *entry;
- struct lvds_dvo_timing *dvo_timing;
+ const struct bdb_lvds_options *lvds_options;
+ const struct bdb_lvds_lfp_data *lvds_lfp_data;
+ const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
+ const struct lvds_dvo_timing *panel_dvo_timing;
struct drm_display_mode *panel_fixed_mode;
- int lfp_data_size, dvo_timing_offset;
- int i, temp_downclock;
- struct drm_display_mode *temp_mode;
+ int i, downclock;
lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
if (!lvds_options)
@@ -150,75 +205,44 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
dev_priv->lvds_vbt = 1;
- lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
- lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
- entry = (struct bdb_lvds_lfp_data_entry *)
- ((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
- lvds_options->panel_type));
- dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
- lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
-
- /*
- * the size of fp_timing varies on the different platform.
- * So calculate the DVO timing relative offset in LVDS data
- * entry to get the DVO timing entry
- */
- dvo_timing = (struct lvds_dvo_timing *)
- ((unsigned char *)entry + dvo_timing_offset);
+ panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
+ lvds_lfp_data_ptrs,
+ lvds_options->panel_type);
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
if (!panel_fixed_mode)
return;
- fill_detail_timing_data(panel_fixed_mode, dvo_timing);
+ fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
drm_mode_debug_printmodeline(panel_fixed_mode);
- temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);
- temp_downclock = panel_fixed_mode->clock;
/*
- * enumerate the LVDS panel timing info entry in VBT to check whether
- * the LVDS downclock is found.
+ * Iterate over the LVDS panel timing info to find the lowest clock
+ * for the native resolution.
*/
+ downclock = panel_dvo_timing->clock;
for (i = 0; i < 16; i++) {
- entry = (struct bdb_lvds_lfp_data_entry *)
- ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i));
- dvo_timing = (struct lvds_dvo_timing *)
- ((unsigned char *)entry + dvo_timing_offset);
-
- fill_detail_timing_data(temp_mode, dvo_timing);
-
- if (temp_mode->hdisplay == panel_fixed_mode->hdisplay &&
- temp_mode->hsync_start == panel_fixed_mode->hsync_start &&
- temp_mode->hsync_end == panel_fixed_mode->hsync_end &&
- temp_mode->htotal == panel_fixed_mode->htotal &&
- temp_mode->vdisplay == panel_fixed_mode->vdisplay &&
- temp_mode->vsync_start == panel_fixed_mode->vsync_start &&
- temp_mode->vsync_end == panel_fixed_mode->vsync_end &&
- temp_mode->vtotal == panel_fixed_mode->vtotal &&
- temp_mode->clock < temp_downclock) {
- /*
- * downclock is already found. But we expect
- * to find the lower downclock.
- */
- temp_downclock = temp_mode->clock;
- }
- /* clear it to zero */
- memset(temp_mode, 0, sizeof(*temp_mode));
+ const struct lvds_dvo_timing *dvo_timing;
+
+ dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
+ lvds_lfp_data_ptrs,
+ i);
+ if (lvds_dvo_timing_equal_size(dvo_timing, panel_dvo_timing) &&
+ dvo_timing->clock < downclock)
+ downclock = dvo_timing->clock;
}
- kfree(temp_mode);
- if (temp_downclock < panel_fixed_mode->clock &&
- i915_lvds_downclock) {
+
+ if (downclock < panel_dvo_timing->clock && i915_lvds_downclock) {
dev_priv->lvds_downclock_avail = 1;
- dev_priv->lvds_downclock = temp_downclock;
+ dev_priv->lvds_downclock = downclock * 10;
DRM_DEBUG_KMS("LVDS downclock is found in VBT. "
"Normal Clock %dKHz, downclock %dKHz\n",
- temp_downclock, panel_fixed_mode->clock);
+ panel_fixed_mode->clock, 10*downclock);
}
- return;
}
/* Try to find sdvo panel data */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0f1c799afea1..393a39922e53 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -24,6 +24,7 @@
* Eric Anholt <eric@anholt.net>
*/
+#include <linux/cpufreq.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/i2c.h>
@@ -1157,12 +1158,15 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
reg = TRANSCONF(pipe);
val = I915_READ(reg);
- /*
- * make the BPC in transcoder be consistent with
- * that in pipeconf reg.
- */
- val &= ~PIPE_BPC_MASK;
- val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+
+ if (HAS_PCH_IBX(dev_priv->dev)) {
+ /*
+ * make the BPC in transcoder be consistent with
+ * that in pipeconf reg.
+ */
+ val &= ~PIPE_BPC_MASK;
+ val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+ }
I915_WRITE(reg, val | TRANS_ENABLE);
if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
DRM_ERROR("failed to enable transcoder %d\n", pipe);
@@ -1380,6 +1384,28 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
disable_pch_hdmi(dev_priv, pipe, HDMID);
}
+static void i8xx_disable_fbc(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 fbc_ctl;
+
+ /* Disable compression */
+ fbc_ctl = I915_READ(FBC_CONTROL);
+ if ((fbc_ctl & FBC_CTL_EN) == 0)
+ return;
+
+ fbc_ctl &= ~FBC_CTL_EN;
+ I915_WRITE(FBC_CONTROL, fbc_ctl);
+
+ /* Wait for compressing bit to clear */
+ if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
+ DRM_DEBUG_KMS("FBC idle timed out\n");
+ return;
+ }
+
+ DRM_DEBUG_KMS("disabled FBC\n");
+}
+
static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
{
struct drm_device *dev = crtc->dev;
@@ -1388,36 +1414,25 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
struct drm_i915_gem_object *obj = intel_fb->obj;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int cfb_pitch;
int plane, i;
u32 fbc_ctl, fbc_ctl2;
- if (fb->pitch == dev_priv->cfb_pitch &&
- obj->fence_reg == dev_priv->cfb_fence &&
- intel_crtc->plane == dev_priv->cfb_plane &&
- I915_READ(FBC_CONTROL) & FBC_CTL_EN)
- return;
-
- i8xx_disable_fbc(dev);
-
- dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
-
- if (fb->pitch < dev_priv->cfb_pitch)
- dev_priv->cfb_pitch = fb->pitch;
+ cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
+ if (fb->pitch < cfb_pitch)
+ cfb_pitch = fb->pitch;
/* FBC_CTL wants 64B units */
- dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
- dev_priv->cfb_fence = obj->fence_reg;
- dev_priv->cfb_plane = intel_crtc->plane;
- plane = dev_priv->cfb_plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
+ cfb_pitch = (cfb_pitch / 64) - 1;
+ plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
/* Clear old tags */
for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
I915_WRITE(FBC_TAG + (i * 4), 0);
/* Set it up... */
- fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | plane;
- if (obj->tiling_mode != I915_TILING_NONE)
- fbc_ctl2 |= FBC_CTL_CPU_FENCE;
+ fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
+ fbc_ctl2 |= plane;
I915_WRITE(FBC_CONTROL2, fbc_ctl2);
I915_WRITE(FBC_FENCE_OFF, crtc->y);
@@ -1425,36 +1440,13 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
if (IS_I945GM(dev))
fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
- fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
+ fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
- if (obj->tiling_mode != I915_TILING_NONE)
- fbc_ctl |= dev_priv->cfb_fence;
- I915_WRITE(FBC_CONTROL, fbc_ctl);
-
- DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ",
- dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane);
-}
-
-void i8xx_disable_fbc(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 fbc_ctl;
-
- /* Disable compression */
- fbc_ctl = I915_READ(FBC_CONTROL);
- if ((fbc_ctl & FBC_CTL_EN) == 0)
- return;
-
- fbc_ctl &= ~FBC_CTL_EN;
+ fbc_ctl |= obj->fence_reg;
I915_WRITE(FBC_CONTROL, fbc_ctl);
- /* Wait for compressing bit to clear */
- if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
- DRM_DEBUG_KMS("FBC idle timed out\n");
- return;
- }
-
- DRM_DEBUG_KMS("disabled FBC\n");
+ DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ",
+ cfb_pitch, crtc->y, intel_crtc->plane);
}
static bool i8xx_fbc_enabled(struct drm_device *dev)
@@ -1476,30 +1468,9 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
unsigned long stall_watermark = 200;
u32 dpfc_ctl;
- dpfc_ctl = I915_READ(DPFC_CONTROL);
- if (dpfc_ctl & DPFC_CTL_EN) {
- if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
- dev_priv->cfb_fence == obj->fence_reg &&
- dev_priv->cfb_plane == intel_crtc->plane &&
- dev_priv->cfb_y == crtc->y)
- return;
-
- I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
- intel_wait_for_vblank(dev, intel_crtc->pipe);
- }
-
- dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
- dev_priv->cfb_fence = obj->fence_reg;
- dev_priv->cfb_plane = intel_crtc->plane;
- dev_priv->cfb_y = crtc->y;
-
dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
- if (obj->tiling_mode != I915_TILING_NONE) {
- dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence;
- I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
- } else {
- I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY);
- }
+ dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
+ I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
(stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
@@ -1512,7 +1483,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
}
-void g4x_disable_fbc(struct drm_device *dev)
+static void g4x_disable_fbc(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpfc_ctl;
@@ -1567,32 +1538,12 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
u32 dpfc_ctl;
dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
- if (dpfc_ctl & DPFC_CTL_EN) {
- if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
- dev_priv->cfb_fence == obj->fence_reg &&
- dev_priv->cfb_plane == intel_crtc->plane &&
- dev_priv->cfb_offset == obj->gtt_offset &&
- dev_priv->cfb_y == crtc->y)
- return;
-
- I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
- intel_wait_for_vblank(dev, intel_crtc->pipe);
- }
-
- dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
- dev_priv->cfb_fence = obj->fence_reg;
- dev_priv->cfb_plane = intel_crtc->plane;
- dev_priv->cfb_offset = obj->gtt_offset;
- dev_priv->cfb_y = crtc->y;
-
dpfc_ctl &= DPFC_RESERVED;
dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
- if (obj->tiling_mode != I915_TILING_NONE) {
- dpfc_ctl |= (DPFC_CTL_FENCE_EN | dev_priv->cfb_fence);
- I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
- } else {
- I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY);
- }
+ /* Set persistent mode for front-buffer rendering, ala X. */
+ dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
+ dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg);
+ I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
(stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
@@ -1604,7 +1555,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
if (IS_GEN6(dev)) {
I915_WRITE(SNB_DPFC_CTL_SA,
- SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence);
+ SNB_CPU_FENCE_ENABLE | obj->fence_reg);
I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
sandybridge_blit_fbc_update(dev);
}
@@ -1612,7 +1563,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
}
-void ironlake_disable_fbc(struct drm_device *dev)
+static void ironlake_disable_fbc(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpfc_ctl;
@@ -1644,24 +1595,109 @@ bool intel_fbc_enabled(struct drm_device *dev)
return dev_priv->display.fbc_enabled(dev);
}
-void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void intel_fbc_work_fn(struct work_struct *__work)
{
- struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+ struct intel_fbc_work *work =
+ container_of(to_delayed_work(__work),
+ struct intel_fbc_work, work);
+ struct drm_device *dev = work->crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ mutex_lock(&dev->struct_mutex);
+ if (work == dev_priv->fbc_work) {
+ /* Double check that we haven't switched fb without cancelling
+ * the prior work.
+ */
+ if (work->crtc->fb == work->fb) {
+ dev_priv->display.enable_fbc(work->crtc,
+ work->interval);
+
+ dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane;
+ dev_priv->cfb_fb = work->crtc->fb->base.id;
+ dev_priv->cfb_y = work->crtc->y;
+ }
+
+ dev_priv->fbc_work = NULL;
+ }
+ mutex_unlock(&dev->struct_mutex);
+
+ kfree(work);
+}
+
+static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
+{
+ if (dev_priv->fbc_work == NULL)
+ return;
+
+ DRM_DEBUG_KMS("cancelling pending FBC enable\n");
+
+ /* Synchronisation is provided by struct_mutex and checking of
+ * dev_priv->fbc_work, so we can perform the cancellation
+ * entirely asynchronously.
+ */
+ if (cancel_delayed_work(&dev_priv->fbc_work->work))
+ /* tasklet was killed before being run, clean up */
+ kfree(dev_priv->fbc_work);
+
+ /* Mark the work as no longer wanted so that if it does
+ * wake-up (because the work was already running and waiting
+ * for our mutex), it will discover that is no longer
+ * necessary to run.
+ */
+ dev_priv->fbc_work = NULL;
+}
+
+static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+ struct intel_fbc_work *work;
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
if (!dev_priv->display.enable_fbc)
return;
- dev_priv->display.enable_fbc(crtc, interval);
+ intel_cancel_fbc_work(dev_priv);
+
+ work = kzalloc(sizeof *work, GFP_KERNEL);
+ if (work == NULL) {
+ dev_priv->display.enable_fbc(crtc, interval);
+ return;
+ }
+
+ work->crtc = crtc;
+ work->fb = crtc->fb;
+ work->interval = interval;
+ INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
+
+ dev_priv->fbc_work = work;
+
+ DRM_DEBUG_KMS("scheduling delayed FBC enable\n");
+
+ /* Delay the actual enabling to let pageflipping cease and the
+ * display to settle before starting the compression. Note that
+ * this delay also serves a second purpose: it allows for a
+ * vblank to pass after disabling the FBC before we attempt
+ * to modify the control registers.
+ *
+ * A more complicated solution would involve tracking vblanks
+ * following the termination of the page-flipping sequence
+ * and indeed performing the enable as a co-routine and not
+ * waiting synchronously upon the vblank.
+ */
+ schedule_delayed_work(&work->work, msecs_to_jiffies(50));
}
void intel_disable_fbc(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ intel_cancel_fbc_work(dev_priv);
+
if (!dev_priv->display.disable_fbc)
return;
dev_priv->display.disable_fbc(dev);
+ dev_priv->cfb_plane = -1;
}
/**
@@ -1760,8 +1796,13 @@ static void intel_update_fbc(struct drm_device *dev)
dev_priv->no_fbc_reason = FBC_BAD_PLANE;
goto out_disable;
}
- if (obj->tiling_mode != I915_TILING_X) {
- DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
+
+ /* The use of a CPU fence is mandatory in order to detect writes
+ * by the CPU to the scanout and trigger updates to the FBC.
+ */
+ if (obj->tiling_mode != I915_TILING_X ||
+ obj->fence_reg == I915_FENCE_REG_NONE) {
+ DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n");
dev_priv->no_fbc_reason = FBC_NOT_TILED;
goto out_disable;
}
@@ -1770,6 +1811,44 @@ static void intel_update_fbc(struct drm_device *dev)
if (in_dbg_master())
goto out_disable;
+ /* If the scanout has not changed, don't modify the FBC settings.
+ * Note that we make the fundamental assumption that the fb->obj
+ * cannot be unpinned (and have its GTT offset and fence revoked)
+ * without first being decoupled from the scanout and FBC disabled.
+ */
+ if (dev_priv->cfb_plane == intel_crtc->plane &&
+ dev_priv->cfb_fb == fb->base.id &&
+ dev_priv->cfb_y == crtc->y)
+ return;
+
+ if (intel_fbc_enabled(dev)) {
+ /* We update FBC along two paths, after changing fb/crtc
+ * configuration (modeswitching) and after page-flipping
+ * finishes. For the latter, we know that not only did
+ * we disable the FBC at the start of the page-flip
+ * sequence, but also more than one vblank has passed.
+ *
+ * For the former case of modeswitching, it is possible
+ * to switch between two FBC valid configurations
+ * instantaneously so we do need to disable the FBC
+ * before we can modify its control registers. We also
+ * have to wait for the next vblank for that to take
+ * effect. However, since we delay enabling FBC we can
+ * assume that a vblank has passed since disabling and
+ * that we can safely alter the registers in the deferred
+ * callback.
+ *
+ * In the scenario that we go from a valid to invalid
+ * and then back to valid FBC configuration we have
+ * no strict enforcement that a vblank occurred since
+ * disabling the FBC. However, along all current pipe
+ * disabling paths we do need to wait for a vblank at
+ * some point. And we wait before enabling FBC anyway.
+ */
+ DRM_DEBUG_KMS("disabling active FBC for update\n");
+ intel_disable_fbc(dev);
+ }
+
intel_enable_fbc(crtc, 500);
return;
@@ -1812,14 +1891,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
}
dev_priv->mm.interruptible = false;
- ret = i915_gem_object_pin(obj, alignment, true);
+ ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
if (ret)
goto err_interruptible;
- ret = i915_gem_object_set_to_display_plane(obj, pipelined);
- if (ret)
- goto err_unpin;
-
/* Install a fence for tiled scan-out. Pre-i965 always needs a
* fence, whereas 965+ only requires a fence if using
* framebuffer compression. For simplicity, we always install
@@ -1841,10 +1916,8 @@ err_interruptible:
return ret;
}
-/* Assume fb object is pinned & idle & fenced and just update base pointers */
-static int
-intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
- int x, int y, enum mode_set_atomic state)
+static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int x, int y)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1887,7 +1960,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
break;
default:
- DRM_ERROR("Unknown color depth\n");
+ DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
return -EINVAL;
}
if (INTEL_INFO(dev)->gen >= 4) {
@@ -1897,10 +1970,6 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
dspcntr &= ~DISPPLANE_TILED;
}
- if (HAS_PCH_SPLIT(dev))
- /* must disable */
- dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
-
I915_WRITE(reg, dspcntr);
Start = obj->gtt_offset;
@@ -1917,6 +1986,99 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
I915_WRITE(DSPADDR(plane), Start + Offset);
POSTING_READ(reg);
+ return 0;
+}
+
+static int ironlake_update_plane(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int x, int y)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_framebuffer *intel_fb;
+ struct drm_i915_gem_object *obj;
+ int plane = intel_crtc->plane;
+ unsigned long Start, Offset;
+ u32 dspcntr;
+ u32 reg;
+
+ switch (plane) {
+ case 0:
+ case 1:
+ break;
+ default:
+ DRM_ERROR("Can't update plane %d in SAREA\n", plane);
+ return -EINVAL;
+ }
+
+ intel_fb = to_intel_framebuffer(fb);
+ obj = intel_fb->obj;
+
+ reg = DSPCNTR(plane);
+ dspcntr = I915_READ(reg);
+ /* Mask out pixel format bits in case we change it */
+ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+ switch (fb->bits_per_pixel) {
+ case 8:
+ dspcntr |= DISPPLANE_8BPP;
+ break;
+ case 16:
+ if (fb->depth != 16)
+ return -EINVAL;
+
+ dspcntr |= DISPPLANE_16BPP;
+ break;
+ case 24:
+ case 32:
+ if (fb->depth == 24)
+ dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+ else if (fb->depth == 30)
+ dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
+ else
+ return -EINVAL;
+ break;
+ default:
+ DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ if (obj->tiling_mode != I915_TILING_NONE)
+ dspcntr |= DISPPLANE_TILED;
+ else
+ dspcntr &= ~DISPPLANE_TILED;
+
+ /* must disable */
+ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
+ I915_WRITE(reg, dspcntr);
+
+ Start = obj->gtt_offset;
+ Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
+
+ DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+ Start, Offset, x, y, fb->pitch);
+ I915_WRITE(DSPSTRIDE(plane), fb->pitch);
+ I915_WRITE(DSPSURF(plane), Start);
+ I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
+ I915_WRITE(DSPADDR(plane), Offset);
+ POSTING_READ(reg);
+
+ return 0;
+}
+
+/* Assume fb object is pinned & idle & fenced and just update base pointers */
+static int
+intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int x, int y, enum mode_set_atomic state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret;
+
+ ret = dev_priv->display.update_plane(crtc, fb, x, y);
+ if (ret)
+ return ret;
+
intel_update_fbc(dev);
intel_increase_pllclock(crtc);
@@ -1971,7 +2133,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
* This should only fail upon a hung GPU, in which case we
* can safely continue.
*/
- ret = i915_gem_object_flush_gpu(obj);
+ ret = i915_gem_object_finish_gpu(obj);
(void) ret;
}
@@ -2622,6 +2784,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
/* For PCH DP, enable TRANS_DP_CTL */
if (HAS_PCH_CPT(dev) &&
intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+ u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg);
temp &= ~(TRANS_DP_PORT_SEL_MASK |
@@ -2629,7 +2792,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
TRANS_DP_BPC_MASK);
temp |= (TRANS_DP_OUTPUT_ENABLE |
TRANS_DP_ENH_FRAMING);
- temp |= TRANS_DP_8BPC;
+ temp |= bpc << 9; /* same format but at 11:9 */
if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
@@ -2732,9 +2895,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
intel_disable_plane(dev_priv, plane, pipe);
- if (dev_priv->cfb_plane == plane &&
- dev_priv->display.disable_fbc)
- dev_priv->display.disable_fbc(dev);
+ if (dev_priv->cfb_plane == plane)
+ intel_disable_fbc(dev);
intel_disable_pipe(dev_priv, pipe);
@@ -2898,9 +3060,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_crtc_dpms_overlay(intel_crtc, false);
intel_crtc_update_cursor(crtc, false);
- if (dev_priv->cfb_plane == plane &&
- dev_priv->display.disable_fbc)
- dev_priv->display.disable_fbc(dev);
+ if (dev_priv->cfb_plane == plane)
+ intel_disable_fbc(dev);
intel_disable_plane(dev_priv, plane, pipe);
intel_disable_pipe(dev_priv, pipe);
@@ -4309,6 +4470,133 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
}
+/**
+ * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
+ * @crtc: CRTC structure
+ *
+ * A pipe may be connected to one or more outputs. Based on the depth of the
+ * attached framebuffer, choose a good color depth to use on the pipe.
+ *
+ * If possible, match the pipe depth to the fb depth. In some cases, this
+ * isn't ideal, because the connected output supports a lesser or restricted
+ * set of depths. Resolve that here:
+ * LVDS typically supports only 6bpc, so clamp down in that case
+ * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
+ * Displays may support a restricted set as well, check EDID and clamp as
+ * appropriate.
+ *
+ * RETURNS:
+ * Dithering requirement (i.e. false if display bpc and pipe bpc match,
+ * true if they don't match).
+ */
+static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+ unsigned int *pipe_bpp)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+ unsigned int display_bpc = UINT_MAX, bpc;
+
+ /* Walk the encoders & connectors on this crtc, get min bpc */
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+ if (encoder->crtc != crtc)
+ continue;
+
+ if (intel_encoder->type == INTEL_OUTPUT_LVDS) {
+ unsigned int lvds_bpc;
+
+ if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) ==
+ LVDS_A3_POWER_UP)
+ lvds_bpc = 8;
+ else
+ lvds_bpc = 6;
+
+ if (lvds_bpc < display_bpc) {
+ DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+ display_bpc = lvds_bpc;
+ }
+ continue;
+ }
+
+ if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+ /* Use VBT settings if we have an eDP panel */
+ unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+
+ if (edp_bpc < display_bpc) {
+ DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+ display_bpc = edp_bpc;
+ }
+ continue;
+ }
+
+ /* Not one of the known troublemakers, check the EDID */
+ list_for_each_entry(connector, &dev->mode_config.connector_list,
+ head) {
+ if (connector->encoder != encoder)
+ continue;
+
+ if (connector->display_info.bpc < display_bpc) {
+ DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+ display_bpc = connector->display_info.bpc;
+ }
+ }
+
+ /*
+ * HDMI is either 12 or 8, so if the display lets 10bpc sneak
+ * through, clamp it down. (Note: >12bpc will be caught below.)
+ */
+ if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+ if (display_bpc > 8 && display_bpc < 12) {
+ DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+ display_bpc = 12;
+ } else {
+ DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+ display_bpc = 8;
+ }
+ }
+ }
+
+ /*
+ * We could just drive the pipe at the highest bpc all the time and
+ * enable dithering as needed, but that costs bandwidth. So choose
+ * the minimum value that expresses the full color range of the fb but
+ * also stays within the max display bpc discovered above.
+ */
+
+ switch (crtc->fb->depth) {
+ case 8:
+ bpc = 8; /* since we go through a colormap */
+ break;
+ case 15:
+ case 16:
+ bpc = 6; /* min is 18bpp */
+ break;
+ case 24:
+ bpc = min((unsigned int)8, display_bpc);
+ break;
+ case 30:
+ bpc = min((unsigned int)10, display_bpc);
+ break;
+ case 48:
+ bpc = min((unsigned int)12, display_bpc);
+ break;
+ default:
+ DRM_DEBUG("unsupported depth, assuming 24 bits\n");
+ bpc = min((unsigned int)8, display_bpc);
+ break;
+ }
+
+ DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
+ bpc, display_bpc);
+
+ *pipe_bpp = bpc * 3;
+
+ return display_bpc != bpc;
+}
+
static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
@@ -4721,7 +5009,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
struct fdi_m_n m_n = {0};
u32 temp;
u32 lvds_sync = 0;
- int target_clock, pixel_multiplier, lane, link_bw, bpp, factor;
+ int target_clock, pixel_multiplier, lane, link_bw, factor;
+ unsigned int pipe_bpp;
+ bool dither;
list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
if (encoder->base.crtc != crtc)
@@ -4848,56 +5138,37 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
/* determine panel color depth */
temp = I915_READ(PIPECONF(pipe));
temp &= ~PIPE_BPC_MASK;
- if (is_lvds) {
- /* the BPC will be 6 if it is 18-bit LVDS panel */
- if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
- temp |= PIPE_8BPC;
- else
- temp |= PIPE_6BPC;
- } else if (has_edp_encoder) {
- switch (dev_priv->edp.bpp/3) {
- case 8:
- temp |= PIPE_8BPC;
- break;
- case 10:
- temp |= PIPE_10BPC;
- break;
- case 6:
- temp |= PIPE_6BPC;
- break;
- case 12:
- temp |= PIPE_12BPC;
- break;
- }
- } else
- temp |= PIPE_8BPC;
- I915_WRITE(PIPECONF(pipe), temp);
-
- switch (temp & PIPE_BPC_MASK) {
- case PIPE_8BPC:
- bpp = 24;
+ dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
+ switch (pipe_bpp) {
+ case 18:
+ temp |= PIPE_6BPC;
break;
- case PIPE_10BPC:
- bpp = 30;
+ case 24:
+ temp |= PIPE_8BPC;
break;
- case PIPE_6BPC:
- bpp = 18;
+ case 30:
+ temp |= PIPE_10BPC;
break;
- case PIPE_12BPC:
- bpp = 36;
+ case 36:
+ temp |= PIPE_12BPC;
break;
default:
- DRM_ERROR("unknown pipe bpc value\n");
- bpp = 24;
+ WARN(1, "intel_choose_pipe_bpp returned invalid value\n");
+ temp |= PIPE_8BPC;
+ pipe_bpp = 24;
+ break;
}
+ intel_crtc->bpp = pipe_bpp;
+ I915_WRITE(PIPECONF(pipe), temp);
+
if (!lane) {
/*
* Account for spread spectrum to avoid
* oversubscribing the link. Max center spread
* is 2.5%; use 5% for safety's sake.
*/
- u32 bps = target_clock * bpp * 21 / 20;
+ u32 bps = target_clock * intel_crtc->bpp * 21 / 20;
lane = bps / (link_bw * 8) + 1;
}
@@ -4905,7 +5176,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
if (pixel_multiplier > 1)
link_bw *= pixel_multiplier;
- ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
+ ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
+ &m_n);
/* Ironlake: try to setup display ref clock before DPLL
* enabling. This is only under driver's control after
@@ -5108,14 +5380,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(PCH_LVDS, temp);
}
- /* set the dithering flag and clear for anything other than a panel. */
pipeconf &= ~PIPECONF_DITHER_EN;
pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
- if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) {
+ if ((is_lvds && dev_priv->lvds_dither) || dither) {
pipeconf |= PIPECONF_DITHER_EN;
pipeconf |= PIPECONF_DITHER_TYPE_ST1;
}
-
if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
intel_dp_set_m_n(crtc, mode, adjusted_mode);
} else {
@@ -5435,21 +5705,15 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
goto fail_locked;
}
- ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
- if (ret) {
- DRM_ERROR("failed to pin cursor bo\n");
- goto fail_locked;
- }
-
- ret = i915_gem_object_set_to_gtt_domain(obj, 0);
+ ret = i915_gem_object_pin_to_display_plane(obj, 0, NULL);
if (ret) {
DRM_ERROR("failed to move cursor bo into the GTT\n");
- goto fail_unpin;
+ goto fail_locked;
}
ret = i915_gem_object_put_fence(obj);
if (ret) {
- DRM_ERROR("failed to move cursor bo into the GTT\n");
+ DRM_ERROR("failed to release fence for cursor");
goto fail_unpin;
}
@@ -6152,6 +6416,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
drm_gem_object_unreference(&work->pending_flip_obj->base);
drm_gem_object_unreference(&work->old_fb_obj->base);
+ intel_update_fbc(work->dev);
mutex_unlock(&work->dev->struct_mutex);
kfree(work);
}
@@ -6516,6 +6781,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
if (ret)
goto cleanup_pending;
+ intel_disable_fbc(dev);
mutex_unlock(&dev->struct_mutex);
trace_i915_flip_request(intel_crtc->plane, obj);
@@ -6644,6 +6910,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
intel_crtc_reset(&intel_crtc->base);
intel_crtc->active = true; /* force the pipe off on setup_init_config */
+ intel_crtc->bpp = 24; /* default for pre-Ironlake */
if (HAS_PCH_SPLIT(dev)) {
intel_helper_funcs.prepare = ironlake_crtc_prepare;
@@ -6870,6 +7137,11 @@ int intel_framebuffer_init(struct drm_device *dev,
switch (mode_cmd->bpp) {
case 8:
case 16:
+ /* Only pre-ILK can handle 5:5:5 */
+ if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev))
+ return -EINVAL;
+ break;
+
case 24:
case 32:
break;
@@ -7284,6 +7556,59 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
mutex_unlock(&dev_priv->dev->struct_mutex);
}
+void gen6_update_ring_freq(struct drm_i915_private *dev_priv)
+{
+ int min_freq = 15;
+ int gpu_freq, ia_freq, max_ia_freq;
+ int scaling_factor = 180;
+
+ max_ia_freq = cpufreq_quick_get_max(0);
+ /*
+ * Default to measured freq if none found, PCU will ensure we don't go
+ * over
+ */
+ if (!max_ia_freq)
+ max_ia_freq = tsc_khz;
+
+ /* Convert from kHz to MHz */
+ max_ia_freq /= 1000;
+
+ mutex_lock(&dev_priv->dev->struct_mutex);
+
+ /*
+ * For each potential GPU frequency, load a ring frequency we'd like
+ * to use for memory access. We do this by specifying the IA frequency
+ * the PCU should use as a reference to determine the ring frequency.
+ */
+ for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
+ gpu_freq--) {
+ int diff = dev_priv->max_delay - gpu_freq;
+
+ /*
+ * For GPU frequencies less than 750MHz, just use the lowest
+ * ring freq.
+ */
+ if (gpu_freq < min_freq)
+ ia_freq = 800;
+ else
+ ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
+ ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
+
+ I915_WRITE(GEN6_PCODE_DATA,
+ (ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT) |
+ gpu_freq);
+ I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
+ GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
+ if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
+ GEN6_PCODE_READY) == 0, 10)) {
+ DRM_ERROR("pcode write of freq table timed out\n");
+ continue;
+ }
+ }
+
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+}
+
static void ironlake_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7640,9 +7965,11 @@ static void intel_init_display(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) {
dev_priv->display.dpms = ironlake_crtc_dpms;
dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
+ dev_priv->display.update_plane = ironlake_update_plane;
} else {
dev_priv->display.dpms = i9xx_crtc_dpms;
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
+ dev_priv->display.update_plane = i9xx_update_plane;
}
if (I915_HAS_FBC(dev)) {
@@ -7939,8 +8266,10 @@ void intel_modeset_init(struct drm_device *dev)
intel_init_emon(dev);
}
- if (IS_GEN6(dev))
+ if (IS_GEN6(dev) || IS_GEN7(dev)) {
gen6_enable_rps(dev_priv);
+ gen6_update_ring_freq(dev_priv);
+ }
INIT_WORK(&dev_priv->idle_work, intel_idle_update);
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
@@ -7976,12 +8305,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_increase_pllclock(crtc);
}
- if (dev_priv->display.disable_fbc)
- dev_priv->display.disable_fbc(dev);
+ intel_disable_fbc(dev);
if (IS_IRONLAKE_M(dev))
ironlake_disable_drps(dev);
- if (IS_GEN6(dev))
+ if (IS_GEN6(dev) || IS_GEN7(dev))
gen6_disable_rps(dev);
if (IS_IRONLAKE_M(dev))
@@ -7994,6 +8322,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
drm_irq_uninstall(dev);
cancel_work_sync(&dev_priv->hotplug_work);
+ /* flush any delayed tasks or pending work */
+ flush_scheduled_work();
+
/* Shut off idle work before the crtcs get freed. */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
intel_crtc = to_intel_crtc(crtc);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e2aced6eec4c..f797fb58ba9c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -178,12 +178,14 @@ intel_dp_link_clock(uint8_t link_bw)
static int
intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc = intel_dp->base.base.crtc;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int bpp = 24;
- if (is_edp(intel_dp))
- return (pixel_clock * dev_priv->edp.bpp + 7) / 8;
- else
- return pixel_clock * 3;
+ if (intel_crtc)
+ bpp = intel_crtc->bpp;
+
+ return (pixel_clock * bpp + 7) / 8;
}
static int
@@ -681,7 +683,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_encoder *encoder;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int lane_count = 4, bpp = 24;
+ int lane_count = 4;
struct intel_dp_m_n m_n;
int pipe = intel_crtc->pipe;
@@ -700,7 +702,6 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
break;
} else if (is_edp(intel_dp)) {
lane_count = dev_priv->edp.lanes;
- bpp = dev_priv->edp.bpp;
break;
}
}
@@ -710,7 +711,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
* the number of bytes_per_pixel post-LUT, which we always
* set up for 8-bits of R/G/B, or 3 bytes total.
*/
- intel_dp_compute_m_n(bpp, lane_count,
+ intel_dp_compute_m_n(intel_crtc->bpp, lane_count,
mode->clock, adjusted_mode->clock, &m_n);
if (HAS_PCH_SPLIT(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9ffa61eb4d7e..6e990f9760ef 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -170,6 +170,7 @@ struct intel_crtc {
int16_t cursor_x, cursor_y;
int16_t cursor_width, cursor_height;
bool cursor_visible;
+ unsigned int bpp;
};
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -233,6 +234,13 @@ struct intel_unpin_work {
bool enable_stall_check;
};
+struct intel_fbc_work {
+ struct delayed_work work;
+ struct drm_crtc *crtc;
+ struct drm_framebuffer *fb;
+ int interval;
+};
+
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
@@ -317,6 +325,7 @@ extern void intel_enable_clock_gating(struct drm_device *dev);
extern void ironlake_enable_drps(struct drm_device *dev);
extern void ironlake_disable_drps(struct drm_device *dev);
extern void gen6_enable_rps(struct drm_i915_private *dev_priv);
+extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv);
extern void gen6_disable_rps(struct drm_device *dev);
extern void intel_init_emon(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index aa0a8e83142e..1ed8e6903915 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -124,12 +124,18 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
u32 sdvox;
sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
- sdvox |= intel_hdmi->color_range;
+ if (!HAS_PCH_SPLIT(dev))
+ sdvox |= intel_hdmi->color_range;
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
+ if (intel_crtc->bpp > 24)
+ sdvox |= COLOR_FORMAT_12bpc;
+ else
+ sdvox |= COLOR_FORMAT_8bpc;
+
/* Required on CPT */
if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
sdvox |= HDMI_MODE_SELECT;
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index d2c710422908..b7c5ddb564d1 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -297,19 +297,26 @@ static int intel_opregion_video_event(struct notifier_block *nb,
/* The only video events relevant to opregion are 0x80. These indicate
either a docking event, lid switch or display switch request. In
Linux, these are handled by the dock, button and video drivers.
- We might want to fix the video driver to be opregion-aware in
- future, but right now we just indicate to the firmware that the
- request has been handled */
+ */
struct opregion_acpi *acpi;
+ struct acpi_bus_event *event = data;
+ int ret = NOTIFY_OK;
+
+ if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
+ return NOTIFY_DONE;
if (!system_opregion)
return NOTIFY_DONE;
acpi = system_opregion->acpi;
+
+ if (event->type == 0x80 && !(acpi->cevt & 0x1))
+ ret = NOTIFY_BAD;
+
acpi->csts = 0;
- return NOTIFY_OK;
+ return ret;
}
static struct notifier_block intel_opregion_notifier = {
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 9e2959bc91cd..d36038086826 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -773,14 +773,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (ret != 0)
return ret;
- ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
+ ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
if (ret != 0)
return ret;
- ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
- if (ret != 0)
- goto out_unpin;
-
ret = i915_gem_object_put_fence(new_bo);
if (ret)
goto out_unpin;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 95c4b1429935..e9615685a39c 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -236,7 +236,8 @@ init_pipe_control(struct intel_ring_buffer *ring)
ret = -ENOMEM;
goto err;
}
- obj->cache_level = I915_CACHE_LLC;
+
+ i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
ret = i915_gem_object_pin(obj, 4096, true);
if (ret)
@@ -776,7 +777,8 @@ static int init_status_page(struct intel_ring_buffer *ring)
ret = -ENOMEM;
goto err;
}
- obj->cache_level = I915_CACHE_LLC;
+
+ i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
ret = i915_gem_object_pin(obj, 4096, true);
if (ret != 0) {
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 113e4e7264cd..210d570fd516 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1236,6 +1236,8 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
struct drm_connector *connector)
{
struct drm_encoder *encoder = &intel_tv->base.base;
+ struct drm_crtc *crtc = encoder->crtc;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -1258,6 +1260,10 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
/* Poll for TV detection */
tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
+ if (intel_crtc->pipe == 1)
+ tv_ctl |= TV_ENC_PIPEB_SELECT;
+ else
+ tv_ctl &= ~TV_ENC_PIPEB_SELECT;
tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
tv_dac |= (TVDAC_STATE_CHG_EN |
@@ -1277,26 +1283,26 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
to_intel_crtc(intel_tv->base.base.crtc)->pipe);
type = -1;
- if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) {
- DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
- /*
- * A B C
- * 0 1 1 Composite
- * 1 0 X svideo
- * 0 0 0 Component
- */
- if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
- DRM_DEBUG_KMS("Detected Composite TV connection\n");
- type = DRM_MODE_CONNECTOR_Composite;
- } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
- DRM_DEBUG_KMS("Detected S-Video TV connection\n");
- type = DRM_MODE_CONNECTOR_SVIDEO;
- } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
- DRM_DEBUG_KMS("Detected Component TV connection\n");
- type = DRM_MODE_CONNECTOR_Component;
- } else {
- DRM_DEBUG_KMS("Unrecognised TV connection\n");
- }
+ tv_dac = I915_READ(TV_DAC);
+ DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
+ /*
+ * A B C
+ * 0 1 1 Composite
+ * 1 0 X svideo
+ * 0 0 0 Component
+ */
+ if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
+ DRM_DEBUG_KMS("Detected Composite TV connection\n");
+ type = DRM_MODE_CONNECTOR_Composite;
+ } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
+ DRM_DEBUG_KMS("Detected S-Video TV connection\n");
+ type = DRM_MODE_CONNECTOR_SVIDEO;
+ } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
+ DRM_DEBUG_KMS("Detected Component TV connection\n");
+ type = DRM_MODE_CONNECTOR_Component;
+ } else {
+ DRM_DEBUG_KMS("Unrecognised TV connection\n");
+ type = -1;
}
I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 729d5fd7c88d..b311faba34f8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -135,13 +135,14 @@ static void load_vbios_pramin(struct drm_device *dev, uint8_t *data)
int i;
if (dev_priv->card_type >= NV_50) {
- uint32_t vbios_vram = (nv_rd32(dev, 0x619f04) & ~0xff) << 8;
-
- if (!vbios_vram)
- vbios_vram = (nv_rd32(dev, 0x1700) << 16) + 0xf0000;
+ u64 addr = (u64)(nv_rd32(dev, 0x619f04) & 0xffffff00) << 8;
+ if (!addr) {
+ addr = (u64)nv_rd32(dev, 0x1700) << 16;
+ addr += 0xf0000;
+ }
old_bar0_pramin = nv_rd32(dev, 0x1700);
- nv_wr32(dev, 0x1700, vbios_vram >> 16);
+ nv_wr32(dev, 0x1700, addr >> 16);
}
/* bail if no rom signature */
@@ -5186,7 +5187,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
load_table_ptr = ROM16(bios->data[bitentry->offset]);
if (load_table_ptr == 0x0) {
- NV_ERROR(dev, "Pointer to BIT loadval table invalid\n");
+ NV_DEBUG(dev, "Pointer to BIT loadval table invalid\n");
return -EINVAL;
}
@@ -5965,6 +5966,12 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx)
if (cte->type == DCB_CONNECTOR_HDMI_1)
cte->type = DCB_CONNECTOR_DVI_I;
}
+
+ /* Gigabyte GV-NX86T512H */
+ if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) {
+ if (cte->type == DCB_CONNECTOR_HDMI_1)
+ cte->type = DCB_CONNECTOR_DVI_I;
+ }
}
static const u8 hpd_gpio[16] = {
@@ -6377,6 +6384,37 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
}
}
+ /* Some other twisted XFX board (rhbz#694914)
+ *
+ * The DVI/VGA encoder combo that's supposed to represent the
+ * DVI-I connector actually point at two different ones, and
+ * the HDMI connector ends up paired with the VGA instead.
+ *
+ * Connector table is missing anything for VGA at all, pointing it
+ * an invalid conntab entry 2 so we figure it out ourself.
+ */
+ if (nv_match_device(dev, 0x0615, 0x1682, 0x2605)) {
+ if (idx == 0) {
+ *conn = 0x02002300; /* VGA, connector 2 */
+ *conf = 0x00000028;
+ } else
+ if (idx == 1) {
+ *conn = 0x01010312; /* DVI, connector 0 */
+ *conf = 0x00020030;
+ } else
+ if (idx == 2) {
+ *conn = 0x04020310; /* VGA, connector 0 */
+ *conf = 0x00000028;
+ } else
+ if (idx == 3) {
+ *conn = 0x02021322; /* HDMI, connector 1 */
+ *conf = 0x00020010;
+ } else {
+ *conn = 0x0000000e; /* EOL */
+ *conf = 0x00000000;
+ }
+ }
+
return true;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 2ad49cbf7c8b..890d50e4d682 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -49,16 +49,12 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
DRM_ERROR("bo %p still attached to GEM object\n", bo);
nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
- if (nvbo->vma.node) {
- nouveau_vm_unmap(&nvbo->vma);
- nouveau_vm_put(&nvbo->vma);
- }
kfree(nvbo);
}
static void
nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
- int *align, int *size, int *page_shift)
+ int *align, int *size)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
@@ -82,67 +78,51 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
}
}
} else {
- if (likely(dev_priv->chan_vm)) {
- if (!(flags & TTM_PL_FLAG_TT) && *size > 256 * 1024)
- *page_shift = dev_priv->chan_vm->lpg_shift;
- else
- *page_shift = dev_priv->chan_vm->spg_shift;
- } else {
- *page_shift = 12;
- }
-
- *size = roundup(*size, (1 << *page_shift));
- *align = max((1 << *page_shift), *align);
+ *size = roundup(*size, (1 << nvbo->page_shift));
+ *align = max((1 << nvbo->page_shift), *align);
}
*size = roundup(*size, PAGE_SIZE);
}
int
-nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
- int size, int align, uint32_t flags, uint32_t tile_mode,
- uint32_t tile_flags, struct nouveau_bo **pnvbo)
+nouveau_bo_new(struct drm_device *dev, int size, int align,
+ uint32_t flags, uint32_t tile_mode, uint32_t tile_flags,
+ struct nouveau_bo **pnvbo)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_bo *nvbo;
- int ret = 0, page_shift = 0;
+ int ret;
nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
if (!nvbo)
return -ENOMEM;
INIT_LIST_HEAD(&nvbo->head);
INIT_LIST_HEAD(&nvbo->entry);
+ INIT_LIST_HEAD(&nvbo->vma_list);
nvbo->tile_mode = tile_mode;
nvbo->tile_flags = tile_flags;
nvbo->bo.bdev = &dev_priv->ttm.bdev;
- nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift);
- align >>= PAGE_SHIFT;
-
- if (dev_priv->chan_vm) {
- ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
- NV_MEM_ACCESS_RW, &nvbo->vma);
- if (ret) {
- kfree(nvbo);
- return ret;
- }
+ nvbo->page_shift = 12;
+ if (dev_priv->bar1_vm) {
+ if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024)
+ nvbo->page_shift = dev_priv->bar1_vm->lpg_shift;
}
+ nouveau_bo_fixup_align(nvbo, flags, &align, &size);
nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
nouveau_bo_placement_set(nvbo, flags, 0);
- nvbo->channel = chan;
ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
- ttm_bo_type_device, &nvbo->placement, align, 0,
- false, NULL, size, nouveau_bo_del_ttm);
+ ttm_bo_type_device, &nvbo->placement,
+ align >> PAGE_SHIFT, 0, false, NULL, size,
+ nouveau_bo_del_ttm);
if (ret) {
/* ttm will call nouveau_bo_del_ttm if it fails.. */
return ret;
}
- nvbo->channel = NULL;
- if (nvbo->vma.node)
- nvbo->bo.offset = nvbo->vma.offset;
*pnvbo = nvbo;
return 0;
}
@@ -312,8 +292,6 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
if (ret)
return ret;
- if (nvbo->vma.node)
- nvbo->bo.offset = nvbo->vma.offset;
return 0;
}
@@ -440,7 +418,6 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
TTM_MEMTYPE_FLAG_CMA;
man->available_caching = TTM_PL_MASK_CACHING;
man->default_caching = TTM_PL_FLAG_CACHED;
- man->gpu_offset = dev_priv->gart_info.aper_base;
break;
default:
NV_ERROR(dev, "Unknown GART type: %d\n",
@@ -501,19 +478,12 @@ static int
nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
{
- struct nouveau_mem *old_node = old_mem->mm_node;
- struct nouveau_mem *new_node = new_mem->mm_node;
- struct nouveau_bo *nvbo = nouveau_bo(bo);
+ struct nouveau_mem *node = old_mem->mm_node;
+ u64 src_offset = node->vma[0].offset;
+ u64 dst_offset = node->vma[1].offset;
u32 page_count = new_mem->num_pages;
- u64 src_offset, dst_offset;
int ret;
- src_offset = old_node->tmp_vma.offset;
- if (new_node->tmp_vma.node)
- dst_offset = new_node->tmp_vma.offset;
- else
- dst_offset = nvbo->vma.offset;
-
page_count = new_mem->num_pages;
while (page_count) {
int line_count = (page_count > 2047) ? 2047 : page_count;
@@ -547,19 +517,13 @@ static int
nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
{
- struct nouveau_mem *old_node = old_mem->mm_node;
- struct nouveau_mem *new_node = new_mem->mm_node;
+ struct nouveau_mem *node = old_mem->mm_node;
struct nouveau_bo *nvbo = nouveau_bo(bo);
u64 length = (new_mem->num_pages << PAGE_SHIFT);
- u64 src_offset, dst_offset;
+ u64 src_offset = node->vma[0].offset;
+ u64 dst_offset = node->vma[1].offset;
int ret;
- src_offset = old_node->tmp_vma.offset;
- if (new_node->tmp_vma.node)
- dst_offset = new_node->tmp_vma.offset;
- else
- dst_offset = nvbo->vma.offset;
-
while (length) {
u32 amount, stride, height;
@@ -695,6 +659,27 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
}
static int
+nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
+ struct ttm_mem_reg *mem, struct nouveau_vma *vma)
+{
+ struct nouveau_mem *node = mem->mm_node;
+ int ret;
+
+ ret = nouveau_vm_get(chan->vm, mem->num_pages << PAGE_SHIFT,
+ node->page_shift, NV_MEM_ACCESS_RO, vma);
+ if (ret)
+ return ret;
+
+ if (mem->mem_type == TTM_PL_VRAM)
+ nouveau_vm_map(vma, node);
+ else
+ nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT,
+ node, node->pages);
+
+ return 0;
+}
+
+static int
nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
bool no_wait_reserve, bool no_wait_gpu,
struct ttm_mem_reg *new_mem)
@@ -711,31 +696,20 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
}
- /* create temporary vma for old memory, this will get cleaned
- * up after ttm destroys the ttm_mem_reg
+ /* create temporary vmas for the transfer and attach them to the
+ * old nouveau_mem node, these will get cleaned up after ttm has
+ * destroyed the ttm_mem_reg
*/
if (dev_priv->card_type >= NV_50) {
struct nouveau_mem *node = old_mem->mm_node;
- if (!node->tmp_vma.node) {
- u32 page_shift = nvbo->vma.node->type;
- if (old_mem->mem_type == TTM_PL_TT)
- page_shift = nvbo->vma.vm->spg_shift;
-
- ret = nouveau_vm_get(chan->vm,
- old_mem->num_pages << PAGE_SHIFT,
- page_shift, NV_MEM_ACCESS_RO,
- &node->tmp_vma);
- if (ret)
- goto out;
- }
- if (old_mem->mem_type == TTM_PL_VRAM)
- nouveau_vm_map(&node->tmp_vma, node);
- else {
- nouveau_vm_map_sg(&node->tmp_vma, 0,
- old_mem->num_pages << PAGE_SHIFT,
- node, node->pages);
- }
+ ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]);
+ if (ret)
+ goto out;
+
+ ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]);
+ if (ret)
+ goto out;
}
if (dev_priv->card_type < NV_50)
@@ -762,7 +736,6 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
bool no_wait_reserve, bool no_wait_gpu,
struct ttm_mem_reg *new_mem)
{
- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
struct ttm_placement placement;
struct ttm_mem_reg tmp_mem;
@@ -782,23 +755,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
if (ret)
goto out;
- if (dev_priv->card_type >= NV_50) {
- struct nouveau_bo *nvbo = nouveau_bo(bo);
- struct nouveau_mem *node = tmp_mem.mm_node;
- struct nouveau_vma *vma = &nvbo->vma;
- if (vma->node->type != vma->vm->spg_shift)
- vma = &node->tmp_vma;
- nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT,
- node, node->pages);
- }
-
ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem);
-
- if (dev_priv->card_type >= NV_50) {
- struct nouveau_bo *nvbo = nouveau_bo(bo);
- nouveau_vm_unmap(&nvbo->vma);
- }
-
if (ret)
goto out;
@@ -844,30 +801,22 @@ out:
static void
nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
{
- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
struct nouveau_mem *node = new_mem->mm_node;
struct nouveau_bo *nvbo = nouveau_bo(bo);
- struct nouveau_vma *vma = &nvbo->vma;
- struct nouveau_vm *vm = vma->vm;
-
- if (dev_priv->card_type < NV_50)
- return;
-
- switch (new_mem->mem_type) {
- case TTM_PL_VRAM:
- nouveau_vm_map(vma, node);
- break;
- case TTM_PL_TT:
- if (vma->node->type != vm->spg_shift) {
+ struct nouveau_vma *vma;
+
+ list_for_each_entry(vma, &nvbo->vma_list, head) {
+ if (new_mem->mem_type == TTM_PL_VRAM) {
+ nouveau_vm_map(vma, new_mem->mm_node);
+ } else
+ if (new_mem->mem_type == TTM_PL_TT &&
+ nvbo->page_shift == vma->vm->spg_shift) {
+ nouveau_vm_map_sg(vma, 0, new_mem->
+ num_pages << PAGE_SHIFT,
+ node, node->pages);
+ } else {
nouveau_vm_unmap(vma);
- vma = &node->tmp_vma;
}
- nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT,
- node, node->pages);
- break;
- default:
- nouveau_vm_unmap(&nvbo->vma);
- break;
}
}
@@ -1113,3 +1062,54 @@ struct ttm_bo_driver nouveau_bo_driver = {
.io_mem_free = &nouveau_ttm_io_mem_free,
};
+struct nouveau_vma *
+nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nouveau_vm *vm)
+{
+ struct nouveau_vma *vma;
+ list_for_each_entry(vma, &nvbo->vma_list, head) {
+ if (vma->vm == vm)
+ return vma;
+ }
+
+ return NULL;
+}
+
+int
+nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
+ struct nouveau_vma *vma)
+{
+ const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
+ struct nouveau_mem *node = nvbo->bo.mem.mm_node;
+ int ret;
+
+ ret = nouveau_vm_get(vm, size, nvbo->page_shift,
+ NV_MEM_ACCESS_RW, vma);
+ if (ret)
+ return ret;
+
+ if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+ nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
+ else
+ if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+ nouveau_vm_map_sg(vma, 0, size, node, node->pages);
+
+ list_add_tail(&vma->head, &nvbo->vma_list);
+ vma->refcount = 1;
+ return 0;
+}
+
+void
+nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
+{
+ if (vma->node) {
+ if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) {
+ spin_lock(&nvbo->bo.bdev->fence_lock);
+ ttm_bo_wait(&nvbo->bo, false, false, false);
+ spin_unlock(&nvbo->bo.bdev->fence_lock);
+ nouveau_vm_unmap(vma);
+ }
+
+ nouveau_vm_put(vma);
+ list_del(&vma->head);
+ }
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index a7583a8ddb01..b0d753f45bbd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -27,40 +27,63 @@
#include "nouveau_drv.h"
#include "nouveau_drm.h"
#include "nouveau_dma.h"
+#include "nouveau_ramht.h"
static int
-nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
+nouveau_channel_pushbuf_init(struct nouveau_channel *chan)
{
+ u32 mem = nouveau_vram_pushbuf ? TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT;
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_bo *pb = chan->pushbuf_bo;
- struct nouveau_gpuobj *pushbuf = NULL;
- int ret = 0;
+ int ret;
+
+ /* allocate buffer object */
+ ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo);
+ if (ret)
+ goto out;
+
+ ret = nouveau_bo_pin(chan->pushbuf_bo, mem);
+ if (ret)
+ goto out;
+
+ ret = nouveau_bo_map(chan->pushbuf_bo);
+ if (ret)
+ goto out;
+ /* create DMA object covering the entire memtype where the push
+ * buffer resides, userspace can submit its own push buffers from
+ * anywhere within the same memtype.
+ */
+ chan->pushbuf_base = chan->pushbuf_bo->bo.offset;
if (dev_priv->card_type >= NV_50) {
+ ret = nouveau_bo_vma_add(chan->pushbuf_bo, chan->vm,
+ &chan->pushbuf_vma);
+ if (ret)
+ goto out;
+
if (dev_priv->card_type < NV_C0) {
ret = nouveau_gpuobj_dma_new(chan,
NV_CLASS_DMA_IN_MEMORY, 0,
(1ULL << 40),
NV_MEM_ACCESS_RO,
NV_MEM_TARGET_VM,
- &pushbuf);
+ &chan->pushbuf);
}
- chan->pushbuf_base = pb->bo.offset;
+ chan->pushbuf_base = chan->pushbuf_vma.offset;
} else
- if (pb->bo.mem.mem_type == TTM_PL_TT) {
+ if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_TT) {
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
dev_priv->gart_info.aper_size,
NV_MEM_ACCESS_RO,
- NV_MEM_TARGET_GART, &pushbuf);
- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+ NV_MEM_TARGET_GART,
+ &chan->pushbuf);
} else
if (dev_priv->card_type != NV_04) {
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
dev_priv->fb_available_size,
NV_MEM_ACCESS_RO,
- NV_MEM_TARGET_VRAM, &pushbuf);
- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+ NV_MEM_TARGET_VRAM,
+ &chan->pushbuf);
} else {
/* NV04 cmdbuf hack, from original ddx.. not sure of it's
* exact reason for existing :) PCI access to cmdbuf in
@@ -70,47 +93,22 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
pci_resource_start(dev->pdev, 1),
dev_priv->fb_available_size,
NV_MEM_ACCESS_RO,
- NV_MEM_TARGET_PCI, &pushbuf);
- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+ NV_MEM_TARGET_PCI,
+ &chan->pushbuf);
}
- nouveau_gpuobj_ref(pushbuf, &chan->pushbuf);
- nouveau_gpuobj_ref(NULL, &pushbuf);
- return ret;
-}
-
-static struct nouveau_bo *
-nouveau_channel_user_pushbuf_alloc(struct drm_device *dev)
-{
- struct nouveau_bo *pushbuf = NULL;
- int location, ret;
-
- if (nouveau_vram_pushbuf)
- location = TTM_PL_FLAG_VRAM;
- else
- location = TTM_PL_FLAG_TT;
-
- ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf);
- if (ret) {
- NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret);
- return NULL;
- }
-
- ret = nouveau_bo_pin(pushbuf, location);
- if (ret) {
- NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret);
- nouveau_bo_ref(NULL, &pushbuf);
- return NULL;
- }
-
- ret = nouveau_bo_map(pushbuf);
+out:
if (ret) {
- nouveau_bo_unpin(pushbuf);
- nouveau_bo_ref(NULL, &pushbuf);
- return NULL;
+ NV_ERROR(dev, "error initialising pushbuf: %d\n", ret);
+ nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
+ nouveau_gpuobj_ref(NULL, &chan->pushbuf);
+ if (chan->pushbuf_bo) {
+ nouveau_bo_unmap(chan->pushbuf_bo);
+ nouveau_bo_ref(NULL, &chan->pushbuf_bo);
+ }
}
- return pushbuf;
+ return 0;
}
/* allocates and initializes a fifo for user space consumption */
@@ -121,6 +119,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
struct nouveau_channel *chan;
unsigned long flags;
int ret;
@@ -160,19 +159,14 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
INIT_LIST_HEAD(&chan->nvsw.flip);
INIT_LIST_HEAD(&chan->fence.pending);
- /* Allocate DMA push buffer */
- chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev);
- if (!chan->pushbuf_bo) {
- ret = -ENOMEM;
- NV_ERROR(dev, "pushbuf %d\n", ret);
+ /* setup channel's memory and vm */
+ ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
+ if (ret) {
+ NV_ERROR(dev, "gpuobj %d\n", ret);
nouveau_channel_put(&chan);
return ret;
}
- nouveau_dma_pre_init(chan);
- chan->user_put = 0x40;
- chan->user_get = 0x44;
-
/* Allocate space for per-channel fixed notifier memory */
ret = nouveau_notifier_init_channel(chan);
if (ret) {
@@ -181,21 +175,17 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
return ret;
}
- /* Setup channel's default objects */
- ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
+ /* Allocate DMA push buffer */
+ ret = nouveau_channel_pushbuf_init(chan);
if (ret) {
- NV_ERROR(dev, "gpuobj %d\n", ret);
+ NV_ERROR(dev, "pushbuf %d\n", ret);
nouveau_channel_put(&chan);
return ret;
}
- /* Create a dma object for the push buffer */
- ret = nouveau_channel_pushbuf_ctxdma_init(chan);
- if (ret) {
- NV_ERROR(dev, "pbctxdma %d\n", ret);
- nouveau_channel_put(&chan);
- return ret;
- }
+ nouveau_dma_pre_init(chan);
+ chan->user_put = 0x40;
+ chan->user_get = 0x44;
/* disable the fifo caches */
pfifo->reassign(dev, false);
@@ -220,6 +210,11 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
nouveau_debugfs_channel_init(chan);
NV_DEBUG(dev, "channel %d initialised\n", chan->id);
+ if (fpriv) {
+ spin_lock(&fpriv->lock);
+ list_add(&chan->list, &fpriv->channels);
+ spin_unlock(&fpriv->lock);
+ }
*chan_ret = chan;
return 0;
}
@@ -236,29 +231,23 @@ nouveau_channel_get_unlocked(struct nouveau_channel *ref)
}
struct nouveau_channel *
-nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id)
+nouveau_channel_get(struct drm_file *file_priv, int id)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
struct nouveau_channel *chan;
- unsigned long flags;
-
- if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR))
- return ERR_PTR(-EINVAL);
-
- spin_lock_irqsave(&dev_priv->channels.lock, flags);
- chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]);
- spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
-
- if (unlikely(!chan))
- return ERR_PTR(-EINVAL);
- if (unlikely(file_priv && chan->file_priv != file_priv)) {
- nouveau_channel_put_unlocked(&chan);
- return ERR_PTR(-EINVAL);
+ spin_lock(&fpriv->lock);
+ list_for_each_entry(chan, &fpriv->channels, list) {
+ if (chan->id == id) {
+ chan = nouveau_channel_get_unlocked(chan);
+ spin_unlock(&fpriv->lock);
+ mutex_lock(&chan->mutex);
+ return chan;
+ }
}
+ spin_unlock(&fpriv->lock);
- mutex_lock(&chan->mutex);
- return chan;
+ return ERR_PTR(-EINVAL);
}
void
@@ -312,12 +301,14 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
/* destroy any resources the channel owned */
nouveau_gpuobj_ref(NULL, &chan->pushbuf);
if (chan->pushbuf_bo) {
+ nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
nouveau_bo_unmap(chan->pushbuf_bo);
nouveau_bo_unpin(chan->pushbuf_bo);
nouveau_bo_ref(NULL, &chan->pushbuf_bo);
}
- nouveau_gpuobj_channel_takedown(chan);
+ nouveau_ramht_ref(NULL, &chan->ramht, chan);
nouveau_notifier_takedown_channel(chan);
+ nouveau_gpuobj_channel_takedown(chan);
nouveau_channel_ref(NULL, pchan);
}
@@ -383,10 +374,11 @@ nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)
NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
for (i = 0; i < engine->fifo.channels; i++) {
- chan = nouveau_channel_get(dev, file_priv, i);
+ chan = nouveau_channel_get(file_priv, i);
if (IS_ERR(chan))
continue;
+ list_del(&chan->list);
atomic_dec(&chan->users);
nouveau_channel_put(&chan);
}
@@ -459,10 +451,11 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
struct drm_nouveau_channel_free *req = data;
struct nouveau_channel *chan;
- chan = nouveau_channel_get(dev, file_priv, req->channel);
+ chan = nouveau_channel_get(file_priv, req->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);
+ list_del(&chan->list);
atomic_dec(&chan->users);
nouveau_channel_put(&chan);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 1595d0b6e815..939d4df07777 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -40,7 +40,7 @@
static void nouveau_connector_hotplug(void *, int);
static struct nouveau_encoder *
-find_encoder_by_type(struct drm_connector *connector, int type)
+find_encoder(struct drm_connector *connector, int type)
{
struct drm_device *dev = connector->dev;
struct nouveau_encoder *nv_encoder;
@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector)
struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
if (!dn ||
- !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
- (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
+ !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) ||
+ (nv_encoder = find_encoder(connector, OUTPUT_ANALOG))))
return NULL;
for_each_child_of_node(dn, cn) {
@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
struct drm_device *dev = connector->dev;
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL;
+ struct nouveau_encoder *nv_partner;
struct nouveau_i2c_chan *i2c;
int type;
@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
* same i2c channel so the value returned from ddc_detect
* isn't necessarily correct.
*/
- if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
+ nv_partner = NULL;
+ if (nv_encoder->dcb->type == OUTPUT_TMDS)
+ nv_partner = find_encoder(connector, OUTPUT_ANALOG);
+ if (nv_encoder->dcb->type == OUTPUT_ANALOG)
+ nv_partner = find_encoder(connector, OUTPUT_TMDS);
+
+ if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG &&
+ nv_partner->dcb->type == OUTPUT_TMDS) ||
+ (nv_encoder->dcb->type == OUTPUT_TMDS &&
+ nv_partner->dcb->type == OUTPUT_ANALOG))) {
if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
type = OUTPUT_TMDS;
else
type = OUTPUT_ANALOG;
- nv_encoder = find_encoder_by_type(connector, type);
- if (!nv_encoder) {
- NV_ERROR(dev, "Detected %d encoder on %s, "
- "but no object!\n", type,
- drm_get_connector_name(connector));
- return connector_status_disconnected;
- }
+ nv_encoder = find_encoder(connector, type);
}
nouveau_connector_set_encoder(connector, nv_encoder);
@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
}
detect_analog:
- nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
+ nv_encoder = find_encoder(connector, OUTPUT_ANALOG);
if (!nv_encoder && !nouveau_tv_disable)
- nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
+ nv_encoder = find_encoder(connector, OUTPUT_TV);
if (nv_encoder && force) {
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
struct drm_encoder_helper_funcs *helper =
@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
nv_connector->edid = NULL;
}
- nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+ nv_encoder = find_encoder(connector, OUTPUT_LVDS);
if (!nv_encoder)
return connector_status_disconnected;
@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector)
} else
type = OUTPUT_ANY;
- nv_encoder = find_encoder_by_type(connector, type);
+ nv_encoder = find_encoder(connector, type);
if (!nv_encoder) {
NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
drm_get_connector_name(connector));
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index 568caedd7216..00bc6eaad558 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -167,8 +167,13 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
int delta, int length)
{
struct nouveau_bo *pb = chan->pushbuf_bo;
- uint64_t offset = bo->bo.offset + delta;
+ struct nouveau_vma *vma;
int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
+ u64 offset;
+
+ vma = nouveau_bo_vma_find(bo, chan->vm);
+ BUG_ON(!vma);
+ offset = vma->offset + delta;
BUG_ON(chan->dma.ib_free < 1);
nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 02c6f37d8bd7..b30ddd8d2e2a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -73,7 +73,7 @@ int nouveau_ignorelid = 0;
module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
MODULE_PARM_DESC(noaccel, "Disable all acceleration");
-int nouveau_noaccel = 0;
+int nouveau_noaccel = -1;
module_param_named(noaccel, nouveau_noaccel, int, 0400);
MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
@@ -119,6 +119,10 @@ MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n");
int nouveau_msi;
module_param_named(msi, nouveau_msi, int, 0400);
+MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
+int nouveau_ctxfw;
+module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
+
int nouveau_fbpercrtc;
#if 0
module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
@@ -210,10 +214,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
pfifo->unload_context(dev);
for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
- if (dev_priv->eng[e]) {
- ret = dev_priv->eng[e]->fini(dev, e);
- if (ret)
- goto out_abort;
+ if (!dev_priv->eng[e])
+ continue;
+
+ ret = dev_priv->eng[e]->fini(dev, e, true);
+ if (ret) {
+ NV_ERROR(dev, "... engine %d failed: %d\n", i, ret);
+ goto out_abort;
}
}
@@ -354,7 +361,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT;
+ u32 offset = nv_crtc->cursor.nvbo->bo.offset;
nv_crtc->cursor.set_offset(nv_crtc, offset);
nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
@@ -389,7 +396,9 @@ static struct drm_driver driver = {
.firstopen = nouveau_firstopen,
.lastclose = nouveau_lastclose,
.unload = nouveau_unload,
+ .open = nouveau_open,
.preclose = nouveau_preclose,
+ .postclose = nouveau_postclose,
#if defined(CONFIG_DRM_NOUVEAU_DEBUG)
.debugfs_init = nouveau_debugfs_init,
.debugfs_cleanup = nouveau_debugfs_takedown,
@@ -420,6 +429,8 @@ static struct drm_driver driver = {
.gem_init_object = nouveau_gem_object_new,
.gem_free_object = nouveau_gem_object_del,
+ .gem_open_object = nouveau_gem_object_open,
+ .gem_close_object = nouveau_gem_object_close,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 9c56331941e2..d7d51deb34b6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -46,9 +46,17 @@
#include "ttm/ttm_module.h"
struct nouveau_fpriv {
- struct ttm_object_file *tfile;
+ spinlock_t lock;
+ struct list_head channels;
+ struct nouveau_vm *vm;
};
+static inline struct nouveau_fpriv *
+nouveau_fpriv(struct drm_file *file_priv)
+{
+ return file_priv ? file_priv->driver_priv : NULL;
+}
+
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
#include "nouveau_drm.h"
@@ -69,7 +77,7 @@ struct nouveau_mem {
struct drm_device *dev;
struct nouveau_vma bar_vma;
- struct nouveau_vma tmp_vma;
+ struct nouveau_vma vma[2];
u8 page_shift;
struct drm_mm_node *tag;
@@ -107,7 +115,8 @@ struct nouveau_bo {
struct nouveau_channel *channel;
- struct nouveau_vma vma;
+ struct list_head vma_list;
+ unsigned page_shift;
uint32_t tile_mode;
uint32_t tile_flags;
@@ -176,9 +185,10 @@ struct nouveau_gpuobj {
uint32_t flags;
u32 size;
- u32 pinst;
- u32 cinst;
- u64 vinst;
+ u32 pinst; /* PRAMIN BAR offset */
+ u32 cinst; /* Channel offset */
+ u64 vinst; /* VRAM address */
+ u64 linst; /* VM address */
uint32_t engine;
uint32_t class;
@@ -201,6 +211,7 @@ enum nouveau_channel_mutex_class {
struct nouveau_channel {
struct drm_device *dev;
+ struct list_head list;
int id;
/* references to the channel data structure */
@@ -228,15 +239,18 @@ struct nouveau_channel {
uint32_t sequence;
uint32_t sequence_ack;
atomic_t last_sequence_irq;
+ struct nouveau_vma vma;
} fence;
/* DMA push buffer */
struct nouveau_gpuobj *pushbuf;
struct nouveau_bo *pushbuf_bo;
+ struct nouveau_vma pushbuf_vma;
uint32_t pushbuf_base;
/* Notifier memory */
struct nouveau_bo *notifier_bo;
+ struct nouveau_vma notifier_vma;
struct drm_mm notifier_heap;
/* PFIFO context */
@@ -278,6 +292,7 @@ struct nouveau_channel {
uint32_t sw_subchannel[8];
+ struct nouveau_vma dispc_vma[2];
struct {
struct nouveau_gpuobj *vblsem;
uint32_t vblsem_head;
@@ -297,7 +312,7 @@ struct nouveau_channel {
struct nouveau_exec_engine {
void (*destroy)(struct drm_device *, int engine);
int (*init)(struct drm_device *, int engine);
- int (*fini)(struct drm_device *, int engine);
+ int (*fini)(struct drm_device *, int engine, bool suspend);
int (*context_new)(struct nouveau_channel *, int engine);
void (*context_del)(struct nouveau_channel *, int engine);
int (*object_new)(struct nouveau_channel *, int engine,
@@ -314,7 +329,8 @@ struct nouveau_instmem_engine {
int (*suspend)(struct drm_device *dev);
void (*resume)(struct drm_device *dev);
- int (*get)(struct nouveau_gpuobj *, u32 size, u32 align);
+ int (*get)(struct nouveau_gpuobj *, struct nouveau_channel *,
+ u32 size, u32 align);
void (*put)(struct nouveau_gpuobj *);
int (*map)(struct nouveau_gpuobj *);
void (*unmap)(struct nouveau_gpuobj *);
@@ -445,9 +461,9 @@ struct nouveau_pm_level {
struct nouveau_pm_temp_sensor_constants {
u16 offset_constant;
s16 offset_mult;
- u16 offset_div;
- u16 slope_mult;
- u16 slope_div;
+ s16 offset_div;
+ s16 slope_mult;
+ s16 slope_div;
};
struct nouveau_pm_threshold_temp {
@@ -488,7 +504,10 @@ struct nouveau_pm_engine {
};
struct nouveau_vram_engine {
+ struct nouveau_mm *mm;
+
int (*init)(struct drm_device *);
+ void (*takedown)(struct drm_device *dev);
int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
u32 type, struct nouveau_mem **);
void (*put)(struct drm_device *, struct nouveau_mem **);
@@ -608,6 +627,7 @@ enum nouveau_card_type {
struct drm_nouveau_private {
struct drm_device *dev;
+ bool noaccel;
/* the card type, takes NV_* as values */
enum nouveau_card_type card_type;
@@ -700,7 +720,6 @@ struct drm_nouveau_private {
/* VRAM/fb configuration */
uint64_t vram_size;
uint64_t vram_sys_base;
- u32 vram_rblock_size;
uint64_t fb_phys;
uint64_t fb_available_size;
@@ -784,12 +803,15 @@ extern int nouveau_override_conntype;
extern char *nouveau_perflvl;
extern int nouveau_perflvl_wr;
extern int nouveau_msi;
+extern int nouveau_ctxfw;
extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
extern int nouveau_pci_resume(struct pci_dev *pdev);
/* nouveau_state.c */
+extern int nouveau_open(struct drm_device *, struct drm_file *);
extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
+extern void nouveau_postclose(struct drm_device *, struct drm_file *);
extern int nouveau_load(struct drm_device *, unsigned long flags);
extern int nouveau_firstopen(struct drm_device *);
extern void nouveau_lastclose(struct drm_device *);
@@ -847,7 +869,7 @@ extern int nouveau_channel_alloc(struct drm_device *dev,
extern struct nouveau_channel *
nouveau_channel_get_unlocked(struct nouveau_channel *);
extern struct nouveau_channel *
-nouveau_channel_get(struct drm_device *, struct drm_file *, int id);
+nouveau_channel_get(struct drm_file *, int id);
extern void nouveau_channel_put_unlocked(struct nouveau_channel **);
extern void nouveau_channel_put(struct nouveau_channel **);
extern void nouveau_channel_ref(struct nouveau_channel *chan,
@@ -1120,7 +1142,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *);
/* nv04_graph.c */
extern int nv04_graph_create(struct drm_device *);
-extern void nv04_graph_fifo_access(struct drm_device *, bool);
extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16);
extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
u32 class, u32 mthd, u32 data);
@@ -1169,7 +1190,8 @@ extern int nv04_instmem_init(struct drm_device *);
extern void nv04_instmem_takedown(struct drm_device *);
extern int nv04_instmem_suspend(struct drm_device *);
extern void nv04_instmem_resume(struct drm_device *);
-extern int nv04_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern int nv04_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
+ u32 size, u32 align);
extern void nv04_instmem_put(struct nouveau_gpuobj *);
extern int nv04_instmem_map(struct nouveau_gpuobj *);
extern void nv04_instmem_unmap(struct nouveau_gpuobj *);
@@ -1180,7 +1202,8 @@ extern int nv50_instmem_init(struct drm_device *);
extern void nv50_instmem_takedown(struct drm_device *);
extern int nv50_instmem_suspend(struct drm_device *);
extern void nv50_instmem_resume(struct drm_device *);
-extern int nv50_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern int nv50_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
+ u32 size, u32 align);
extern void nv50_instmem_put(struct nouveau_gpuobj *);
extern int nv50_instmem_map(struct nouveau_gpuobj *);
extern void nv50_instmem_unmap(struct nouveau_gpuobj *);
@@ -1247,10 +1270,9 @@ extern int nv04_crtc_create(struct drm_device *, int index);
/* nouveau_bo.c */
extern struct ttm_bo_driver nouveau_bo_driver;
-extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *,
- int size, int align, uint32_t flags,
- uint32_t tile_mode, uint32_t tile_flags,
- struct nouveau_bo **);
+extern int nouveau_bo_new(struct drm_device *, int size, int align,
+ uint32_t flags, uint32_t tile_mode,
+ uint32_t tile_flags, struct nouveau_bo **);
extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
extern int nouveau_bo_unpin(struct nouveau_bo *);
extern int nouveau_bo_map(struct nouveau_bo *);
@@ -1265,6 +1287,12 @@ extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *);
extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
bool no_wait_reserve, bool no_wait_gpu);
+extern struct nouveau_vma *
+nouveau_bo_vma_find(struct nouveau_bo *, struct nouveau_vm *);
+extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *,
+ struct nouveau_vma *);
+extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *);
+
/* nouveau_fence.c */
struct nouveau_fence;
extern int nouveau_fence_init(struct drm_device *);
@@ -1310,12 +1338,14 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj)
}
/* nouveau_gem.c */
-extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
- int size, int align, uint32_t domain,
- uint32_t tile_mode, uint32_t tile_flags,
- struct nouveau_bo **);
+extern int nouveau_gem_new(struct drm_device *, int size, int align,
+ uint32_t domain, uint32_t tile_mode,
+ uint32_t tile_flags, struct nouveau_bo **);
extern int nouveau_gem_object_new(struct drm_gem_object *);
extern void nouveau_gem_object_del(struct drm_gem_object *);
+extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *);
+extern void nouveau_gem_object_close(struct drm_gem_object *,
+ struct drm_file *);
extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
struct drm_file *);
extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
index a3a88ad00f86..95c843e684bb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fb.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
@@ -30,6 +30,7 @@
struct nouveau_framebuffer {
struct drm_framebuffer base;
struct nouveau_bo *nvbo;
+ struct nouveau_vma vma;
u32 r_dma;
u32 r_format;
u32 r_pitch;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 39aee6d4daf8..14a8627efe4d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -279,6 +279,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
struct fb_info *info;
struct drm_framebuffer *fb;
struct nouveau_framebuffer *nouveau_fb;
+ struct nouveau_channel *chan;
struct nouveau_bo *nvbo;
struct drm_mode_fb_cmd mode_cmd;
struct pci_dev *pdev = dev->pdev;
@@ -296,8 +297,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
size = mode_cmd.pitch * mode_cmd.height;
size = roundup(size, PAGE_SIZE);
- ret = nouveau_gem_new(dev, dev_priv->channel, size, 0,
- NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
+ ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
+ 0, 0x0000, &nvbo);
if (ret) {
NV_ERROR(dev, "failed to allocate framebuffer\n");
goto out;
@@ -318,6 +319,15 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
goto out;
}
+ chan = nouveau_nofbaccel ? NULL : dev_priv->channel;
+ if (chan && dev_priv->card_type >= NV_50) {
+ ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma);
+ if (ret) {
+ NV_ERROR(dev, "failed to map fb into chan: %d\n", ret);
+ chan = NULL;
+ }
+ }
+
mutex_lock(&dev->struct_mutex);
info = framebuffer_alloc(0, device);
@@ -448,6 +458,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
if (nouveau_fb->nvbo) {
nouveau_bo_unmap(nouveau_fb->nvbo);
+ nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
nouveau_fb->nvbo = NULL;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 7347075ca5b8..8d02d875376d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -336,6 +336,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
{
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
struct nouveau_fence *fence = NULL;
+ u64 offset = chan->fence.vma.offset + sema->mem->start;
int ret;
if (dev_priv->chipset < 0x84) {
@@ -345,13 +346,10 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3);
OUT_RING (chan, NvSema);
- OUT_RING (chan, sema->mem->start);
+ OUT_RING (chan, offset);
OUT_RING (chan, 1);
} else
if (dev_priv->chipset < 0xc0) {
- struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
- u64 offset = vma->offset + sema->mem->start;
-
ret = RING_SPACE(chan, 7);
if (ret)
return ret;
@@ -364,9 +362,6 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
OUT_RING (chan, 1);
OUT_RING (chan, 1); /* ACQUIRE_EQ */
} else {
- struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
- u64 offset = vma->offset + sema->mem->start;
-
ret = RING_SPACE(chan, 5);
if (ret)
return ret;
@@ -394,6 +389,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
{
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
struct nouveau_fence *fence = NULL;
+ u64 offset = chan->fence.vma.offset + sema->mem->start;
int ret;
if (dev_priv->chipset < 0x84) {
@@ -403,14 +399,11 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2);
OUT_RING (chan, NvSema);
- OUT_RING (chan, sema->mem->start);
+ OUT_RING (chan, offset);
BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
OUT_RING (chan, 1);
} else
if (dev_priv->chipset < 0xc0) {
- struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
- u64 offset = vma->offset + sema->mem->start;
-
ret = RING_SPACE(chan, 7);
if (ret)
return ret;
@@ -423,9 +416,6 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
OUT_RING (chan, 1);
OUT_RING (chan, 2); /* RELEASE */
} else {
- struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
- u64 offset = vma->offset + sema->mem->start;
-
ret = RING_SPACE(chan, 5);
if (ret)
return ret;
@@ -540,6 +530,12 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
nouveau_gpuobj_ref(NULL, &obj);
if (ret)
return ret;
+ } else {
+ /* map fence bo into channel's vm */
+ ret = nouveau_bo_vma_add(dev_priv->fence.bo, chan->vm,
+ &chan->fence.vma);
+ if (ret)
+ return ret;
}
INIT_LIST_HEAD(&chan->fence.pending);
@@ -551,10 +547,10 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
void
nouveau_fence_channel_fini(struct nouveau_channel *chan)
{
+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
struct nouveau_fence *tmp, *fence;
spin_lock(&chan->fence.lock);
-
list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
fence->signalled = true;
list_del(&fence->entry);
@@ -564,8 +560,9 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
kref_put(&fence->refcount, nouveau_fence_del);
}
-
spin_unlock(&chan->fence.lock);
+
+ nouveau_bo_vma_del(dev_priv->fence.bo, &chan->fence.vma);
}
int
@@ -577,7 +574,7 @@ nouveau_fence_init(struct drm_device *dev)
/* Create a shared VRAM heap for cross-channel sync. */
if (USE_SEMA(dev)) {
- ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM,
+ ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM,
0, 0, &dev_priv->fence.bo);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index b52e46018245..5f0bc57fdaab 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -60,9 +60,71 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
}
int
-nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
- int size, int align, uint32_t domain, uint32_t tile_mode,
- uint32_t tile_flags, struct nouveau_bo **pnvbo)
+nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
+{
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+ struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+ struct nouveau_vma *vma;
+ int ret;
+
+ if (!fpriv->vm)
+ return 0;
+
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ if (ret)
+ return ret;
+
+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+ if (!vma) {
+ vma = kzalloc(sizeof(*vma), GFP_KERNEL);
+ if (!vma) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = nouveau_bo_vma_add(nvbo, fpriv->vm, vma);
+ if (ret) {
+ kfree(vma);
+ goto out;
+ }
+ } else {
+ vma->refcount++;
+ }
+
+out:
+ ttm_bo_unreserve(&nvbo->bo);
+ return ret;
+}
+
+void
+nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
+{
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+ struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+ struct nouveau_vma *vma;
+ int ret;
+
+ if (!fpriv->vm)
+ return;
+
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ if (ret)
+ return;
+
+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+ if (vma) {
+ if (--vma->refcount == 0) {
+ nouveau_bo_vma_del(nvbo, vma);
+ kfree(vma);
+ }
+ }
+ ttm_bo_unreserve(&nvbo->bo);
+}
+
+int
+nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
+ uint32_t tile_mode, uint32_t tile_flags,
+ struct nouveau_bo **pnvbo)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_bo *nvbo;
@@ -76,7 +138,7 @@ nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU)
flags |= TTM_PL_FLAG_SYSTEM;
- ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode,
+ ret = nouveau_bo_new(dev, size, align, flags, tile_mode,
tile_flags, pnvbo);
if (ret)
return ret;
@@ -103,17 +165,28 @@ nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
}
static int
-nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
+nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
+ struct drm_nouveau_gem_info *rep)
{
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+ struct nouveau_vma *vma;
if (nvbo->bo.mem.mem_type == TTM_PL_TT)
rep->domain = NOUVEAU_GEM_DOMAIN_GART;
else
rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
- rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
rep->offset = nvbo->bo.offset;
+ if (fpriv->vm) {
+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+ if (!vma)
+ return -EINVAL;
+
+ rep->offset = vma->offset;
+ }
+
+ rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
rep->map_handle = nvbo->bo.addr_space_offset;
rep->tile_mode = nvbo->tile_mode;
rep->tile_flags = nvbo->tile_flags;
@@ -127,7 +200,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_nouveau_gem_new *req = data;
struct nouveau_bo *nvbo = NULL;
- struct nouveau_channel *chan = NULL;
int ret = 0;
if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
@@ -138,28 +210,21 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
return -EINVAL;
}
- if (req->channel_hint) {
- chan = nouveau_channel_get(dev, file_priv, req->channel_hint);
- if (IS_ERR(chan))
- return PTR_ERR(chan);
- }
-
- ret = nouveau_gem_new(dev, chan, req->info.size, req->align,
+ ret = nouveau_gem_new(dev, req->info.size, req->align,
req->info.domain, req->info.tile_mode,
req->info.tile_flags, &nvbo);
- if (chan)
- nouveau_channel_put(&chan);
if (ret)
return ret;
- ret = nouveau_gem_info(nvbo->gem, &req->info);
- if (ret)
- goto out;
-
ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
+ if (ret == 0) {
+ ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info);
+ if (ret)
+ drm_gem_handle_delete(file_priv, req->info.handle);
+ }
+
/* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(nvbo->gem);
-out:
return ret;
}
@@ -318,6 +383,7 @@ static int
validate_list(struct nouveau_channel *chan, struct list_head *list,
struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
{
+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
(void __force __user *)(uintptr_t)user_pbbo_ptr;
struct drm_device *dev = chan->dev;
@@ -356,24 +422,26 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
return ret;
}
- if (nvbo->bo.offset == b->presumed.offset &&
- ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
- b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
- (nvbo->bo.mem.mem_type == TTM_PL_TT &&
- b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
- continue;
+ if (dev_priv->card_type < NV_50) {
+ if (nvbo->bo.offset == b->presumed.offset &&
+ ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
+ b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
+ (nvbo->bo.mem.mem_type == TTM_PL_TT &&
+ b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
+ continue;
- if (nvbo->bo.mem.mem_type == TTM_PL_TT)
- b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
- else
- b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
- b->presumed.offset = nvbo->bo.offset;
- b->presumed.valid = 0;
- relocs++;
-
- if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
- &b->presumed, sizeof(b->presumed)))
- return -EFAULT;
+ if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+ b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
+ else
+ b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
+ b->presumed.offset = nvbo->bo.offset;
+ b->presumed.valid = 0;
+ relocs++;
+
+ if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
+ &b->presumed, sizeof(b->presumed)))
+ return -EFAULT;
+ }
}
return relocs;
@@ -548,7 +616,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
struct nouveau_fence *fence = NULL;
int i, j, ret = 0, do_reloc = 0;
- chan = nouveau_channel_get(dev, file_priv, req->channel);
+ chan = nouveau_channel_get(file_priv, req->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);
@@ -782,7 +850,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
if (!gem)
return -ENOENT;
- ret = nouveau_gem_info(gem, req);
+ ret = nouveau_gem_info(file_priv, gem, req);
drm_gem_object_unreference_unlocked(gem);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 2ba7265bc967..868c7fd74854 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -79,7 +79,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
int i;
stat = nv_rd32(dev, NV03_PMC_INTR_0);
- if (!stat)
+ if (stat == 0 || stat == ~0)
return IRQ_NONE;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 5ee14d216ce8..f9ae2fc3d6f1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -397,7 +397,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
dma_bits = 40;
} else
- if (0 && drm_pci_device_is_pcie(dev) &&
+ if (0 && pci_is_pcie(dev->pdev) &&
dev_priv->chipset > 0x40 &&
dev_priv->chipset != 0x45) {
if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39)))
@@ -423,38 +423,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
return ret;
}
- /* reserve space at end of VRAM for PRAMIN */
- if (dev_priv->card_type >= NV_50) {
- dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
- } else
- if (dev_priv->card_type >= NV_40) {
- u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
- u32 rsvd;
-
- /* estimate grctx size, the magics come from nv40_grctx.c */
- if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
- else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs;
- else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs;
- else rsvd = 0x4a40 * vs;
- rsvd += 16 * 1024;
- rsvd *= dev_priv->engine.fifo.channels;
-
- /* pciegart table */
- if (drm_pci_device_is_pcie(dev))
- rsvd += 512 * 1024;
-
- /* object storage */
- rsvd += 512 * 1024;
-
- dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
- } else {
- dev_priv->ramin_rsvd_vram = 512 * 1024;
- }
-
- ret = dev_priv->engine.vram.init(dev);
- if (ret)
- return ret;
-
NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
if (dev_priv->vram_sys_base) {
NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
@@ -479,7 +447,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
}
if (dev_priv->card_type < NV_50) {
- ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+ ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM,
0, 0, &dev_priv->vga_ram);
if (ret == 0)
ret = nouveau_bo_pin(dev_priv->vga_ram,
@@ -729,37 +697,31 @@ nouveau_mem_timing_fini(struct drm_device *dev)
}
static int
-nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size)
+nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
{
- struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
- struct nouveau_mm *mm;
- u64 size, block, rsvd;
- int ret;
-
- rsvd = (256 * 1024); /* vga memory */
- size = (p_size << PAGE_SHIFT) - rsvd;
- block = dev_priv->vram_rblock_size;
-
- ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12);
- if (ret)
- return ret;
-
- man->priv = mm;
+ /* nothing to do */
return 0;
}
static int
nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
{
- struct nouveau_mm *mm = man->priv;
- int ret;
+ /* nothing to do */
+ return 0;
+}
- ret = nouveau_mm_fini(&mm);
- if (ret)
- return ret;
+static inline void
+nouveau_mem_node_cleanup(struct nouveau_mem *node)
+{
+ if (node->vma[0].node) {
+ nouveau_vm_unmap(&node->vma[0]);
+ nouveau_vm_put(&node->vma[0]);
+ }
- man->priv = NULL;
- return 0;
+ if (node->vma[1].node) {
+ nouveau_vm_unmap(&node->vma[1]);
+ nouveau_vm_put(&node->vma[1]);
+ }
}
static void
@@ -768,14 +730,9 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
- struct nouveau_mem *node = mem->mm_node;
struct drm_device *dev = dev_priv->dev;
- if (node->tmp_vma.node) {
- nouveau_vm_unmap(&node->tmp_vma);
- nouveau_vm_put(&node->tmp_vma);
- }
-
+ nouveau_mem_node_cleanup(mem->mm_node);
vram->put(dev, (struct nouveau_mem **)&mem->mm_node);
}
@@ -794,7 +751,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
int ret;
if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
- size_nc = 1 << nvbo->vma.node->type;
+ size_nc = 1 << nvbo->page_shift;
ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
mem->page_alignment << PAGE_SHIFT, size_nc,
@@ -804,9 +761,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
return (ret == -ENOSPC) ? 0 : ret;
}
- node->page_shift = 12;
- if (nvbo->vma.node)
- node->page_shift = nvbo->vma.node->type;
+ node->page_shift = nvbo->page_shift;
mem->mm_node = node;
mem->start = node->offset >> PAGE_SHIFT;
@@ -862,15 +817,9 @@ static void
nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem)
{
- struct nouveau_mem *node = mem->mm_node;
-
- if (node->tmp_vma.node) {
- nouveau_vm_unmap(&node->tmp_vma);
- nouveau_vm_put(&node->tmp_vma);
- }
-
+ nouveau_mem_node_cleanup(mem->mm_node);
+ kfree(mem->mm_node);
mem->mm_node = NULL;
- kfree(node);
}
static int
@@ -880,11 +829,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
- struct nouveau_bo *nvbo = nouveau_bo(bo);
- struct nouveau_vma *vma = &nvbo->vma;
- struct nouveau_vm *vm = vma->vm;
struct nouveau_mem *node;
- int ret;
if (unlikely((mem->num_pages << PAGE_SHIFT) >=
dev_priv->gart_info.aper_size))
@@ -893,24 +838,8 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node)
return -ENOMEM;
+ node->page_shift = 12;
- /* This node must be for evicting large-paged VRAM
- * to system memory. Due to a nv50 limitation of
- * not being able to mix large/small pages within
- * the same PDE, we need to create a temporary
- * small-paged VMA for the eviction.
- */
- if (vma->node->type != vm->spg_shift) {
- ret = nouveau_vm_get(vm, (u64)vma->node->length << 12,
- vm->spg_shift, NV_MEM_ACCESS_RW,
- &node->tmp_vma);
- if (ret) {
- kfree(node);
- return ret;
- }
- }
-
- node->page_shift = nvbo->vma.node->type;
mem->mm_node = node;
mem->start = 0;
return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c
index 7609756b6faf..1640dec3b823 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.c
@@ -158,11 +158,18 @@ int
nouveau_mm_fini(struct nouveau_mm **prmm)
{
struct nouveau_mm *rmm = *prmm;
- struct nouveau_mm_node *heap =
+ struct nouveau_mm_node *node, *heap =
list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
- if (!list_is_singular(&rmm->nodes))
+ 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);
+ }
+ WARN_ON(1);
return -EBUSY;
+ }
kfree(heap);
kfree(rmm);
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h
index 1f7483aae9a4..b9c016d21553 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h
@@ -52,6 +52,7 @@ int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
int nv50_vram_init(struct drm_device *);
+void nv50_vram_fini(struct drm_device *);
int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
u32 memtype, struct nouveau_mem **);
void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c
index 5b39718ae1f8..6abdbe6530a7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_notifier.c
+++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c
@@ -34,6 +34,7 @@ int
nouveau_notifier_init_channel(struct nouveau_channel *chan)
{
struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_bo *ntfy = NULL;
uint32_t flags, ttmpl;
int ret;
@@ -46,7 +47,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
ttmpl = TTM_PL_FLAG_TT;
}
- ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
+ ret = nouveau_gem_new(dev, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
if (ret)
return ret;
@@ -58,14 +59,22 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
if (ret)
goto out_err;
+ if (dev_priv->card_type >= NV_50) {
+ ret = nouveau_bo_vma_add(ntfy, chan->vm, &chan->notifier_vma);
+ if (ret)
+ goto out_err;
+ }
+
ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size);
if (ret)
goto out_err;
chan->notifier_bo = ntfy;
out_err:
- if (ret)
+ if (ret) {
+ nouveau_bo_vma_del(ntfy, &chan->notifier_vma);
drm_gem_object_unreference_unlocked(ntfy->gem);
+ }
return ret;
}
@@ -78,6 +87,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
if (!chan->notifier_bo)
return;
+ nouveau_bo_vma_del(chan->notifier_bo, &chan->notifier_vma);
nouveau_bo_unmap(chan->notifier_bo);
mutex_lock(&dev->struct_mutex);
nouveau_bo_unpin(chan->notifier_bo);
@@ -122,10 +132,10 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
target = NV_MEM_TARGET_VRAM;
else
target = NV_MEM_TARGET_GART;
- offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
+ offset = chan->notifier_bo->bo.offset;
} else {
target = NV_MEM_TARGET_VM;
- offset = chan->notifier_bo->vma.offset;
+ offset = chan->notifier_vma.offset;
}
offset += mem->start;
@@ -183,7 +193,7 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
if (unlikely(dev_priv->card_type >= NV_C0))
return -EINVAL;
- chan = nouveau_channel_get(dev, file_priv, na->channel);
+ chan = nouveau_channel_get(file_priv, na->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 8f97016f5b26..159b7c437d3f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -125,7 +125,7 @@ nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid,
int ret = -EINVAL;
spin_lock_irqsave(&dev_priv->channels.lock, flags);
- if (chid > 0 && chid < dev_priv->engine.fifo.channels)
+ if (chid >= 0 && chid < dev_priv->engine.fifo.channels)
chan = dev_priv->channels.ptr[chid];
if (chan)
ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data);
@@ -191,7 +191,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
spin_unlock(&dev_priv->ramin_lock);
- if (chan) {
+ if (!(flags & NVOBJ_FLAG_VM) && chan) {
ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0);
if (ramin)
ramin = drm_mm_get_block(ramin, size, align);
@@ -208,7 +208,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
gpuobj->vinst = ramin->start + chan->ramin->vinst;
gpuobj->node = ramin;
} else {
- ret = instmem->get(gpuobj, size, align);
+ ret = instmem->get(gpuobj, chan, size, align);
if (ret) {
nouveau_gpuobj_ref(NULL, &gpuobj);
return ret;
@@ -690,35 +690,64 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
return 0;
}
+static int
+nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
+{
+ struct drm_device *dev = chan->dev;
+ struct nouveau_gpuobj *pgd = NULL;
+ struct nouveau_vm_pgd *vpgd;
+ int ret, i;
+
+ ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin);
+ if (ret)
+ return ret;
+
+ /* create page directory for this vm if none currently exists,
+ * will be destroyed automagically when last reference to the
+ * vm is removed
+ */
+ if (list_empty(&vm->pgd_list)) {
+ ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd);
+ if (ret)
+ return ret;
+ }
+ nouveau_vm_ref(vm, &chan->vm, pgd);
+ nouveau_gpuobj_ref(NULL, &pgd);
+
+ /* point channel at vm's page directory */
+ vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
+ nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
+ nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
+ nv_wo32(chan->ramin, 0x0208, 0xffffffff);
+ nv_wo32(chan->ramin, 0x020c, 0x000000ff);
+
+ /* map display semaphore buffers into channel's vm */
+ for (i = 0; i < 2; i++) {
+ struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
+
+ ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm,
+ &chan->dispc_vma[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int
nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
uint32_t vram_h, uint32_t tt_h)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv);
+ struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm;
struct nouveau_gpuobj *vram = NULL, *tt = NULL;
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) {
- struct nouveau_vm *vm = dev_priv->chan_vm;
- struct nouveau_vm_pgd *vpgd;
-
- ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0,
- &chan->ramin);
- if (ret)
- return ret;
-
- nouveau_vm_ref(vm, &chan->vm, NULL);
-
- vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
- nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
- nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
- nv_wo32(chan->ramin, 0x0208, 0xffffffff);
- nv_wo32(chan->ramin, 0x020c, 0x000000ff);
- return 0;
- }
+ if (dev_priv->card_type == NV_C0)
+ return nvc0_gpuobj_channel_init(chan, vm);
/* Allocate a chunk of memory for per-channel object storage */
ret = nouveau_gpuobj_channel_init_pramin(chan);
@@ -731,7 +760,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
* - Allocate per-channel page-directory
* - Link with shared channel VM
*/
- if (dev_priv->chan_vm) {
+ if (vm) {
u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
u64 vm_vinst = chan->ramin->vinst + pgd_offs;
u32 vm_pinst = chan->ramin->pinst;
@@ -744,7 +773,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
if (ret)
return ret;
- nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd);
+ nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
}
/* RAMHT */
@@ -768,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
struct nouveau_gpuobj *sem = NULL;
struct nv50_display_crtc *dispc =
&nv50_display(dev)->crtc[i];
- u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
+ u64 offset = dispc->sem.bo->bo.offset;
ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff,
NV_MEM_ACCESS_RW,
@@ -841,13 +870,22 @@ void
nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
{
struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int i;
NV_DEBUG(dev, "ch%d\n", chan->id);
- nouveau_ramht_ref(NULL, &chan->ramht, chan);
+ if (dev_priv->card_type >= NV_50) {
+ struct nv50_display *disp = nv50_display(dev);
+
+ for (i = 0; i < 2; 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);
@@ -909,7 +947,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
if (init->handle == ~0)
return -EINVAL;
- chan = nouveau_channel_get(dev, file_priv, init->channel);
+ chan = nouveau_channel_get(file_priv, init->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);
@@ -936,7 +974,7 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
struct nouveau_channel *chan;
int ret;
- chan = nouveau_channel_get(dev, file_priv, objfree->channel);
+ chan = nouveau_channel_get(file_priv, objfree->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index 82fad914e648..c444cadbf849 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -429,7 +429,7 @@ nouveau_sgdma_init(struct drm_device *dev)
u32 aper_size, align;
int ret;
- if (dev_priv->card_type >= NV_40 && drm_pci_device_is_pcie(dev))
+ if (dev_priv->card_type >= NV_40 && pci_is_pcie(dev->pdev))
aper_size = 512 * 1024 * 1024;
else
aper_size = 64 * 1024 * 1024;
@@ -458,7 +458,7 @@ nouveau_sgdma_init(struct drm_device *dev)
dev_priv->gart_info.type = NOUVEAU_GART_HW;
dev_priv->gart_info.func = &nv50_sgdma_backend;
} else
- if (0 && drm_pci_device_is_pcie(dev) &&
+ if (0 && pci_is_pcie(dev->pdev) &&
dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) {
if (nv44_graph_class(dev)) {
dev_priv->gart_info.func = &nv44_sgdma_backend;
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 731acea865b5..10656e430b44 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -91,6 +91,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clock_pre = nv04_pm_clock_pre;
engine->pm.clock_set = nv04_pm_clock_set;
engine->vram.init = nouveau_mem_detect;
+ engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x10:
@@ -139,6 +140,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clock_pre = nv04_pm_clock_pre;
engine->pm.clock_set = nv04_pm_clock_set;
engine->vram.init = nouveau_mem_detect;
+ engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x20:
@@ -187,6 +189,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clock_pre = nv04_pm_clock_pre;
engine->pm.clock_set = nv04_pm_clock_set;
engine->vram.init = nouveau_mem_detect;
+ engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x30:
@@ -237,6 +240,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.voltage_get = nouveau_voltage_gpio_get;
engine->pm.voltage_set = nouveau_voltage_gpio_set;
engine->vram.init = nouveau_mem_detect;
+ engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x40:
@@ -289,6 +293,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.voltage_set = nouveau_voltage_gpio_set;
engine->pm.temp_get = nv40_temp_get;
engine->vram.init = nouveau_mem_detect;
+ engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x50:
@@ -366,6 +371,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
else
engine->pm.temp_get = nv40_temp_get;
engine->vram.init = nv50_vram_init;
+ engine->vram.takedown = nv50_vram_fini;
engine->vram.get = nv50_vram_new;
engine->vram.put = nv50_vram_del;
engine->vram.flags_valid = nv50_vram_flags_valid;
@@ -411,9 +417,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
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.temp_get = nv84_temp_get;
break;
default:
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
@@ -447,8 +455,8 @@ 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,
- (struct drm_file *)-2, NvDmaFB, NvDmaTT);
+ ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
+ NvDmaFB, NvDmaTT);
if (ret)
return ret;
@@ -527,7 +535,7 @@ nouveau_card_init(struct drm_device *dev)
nouveau_pm_init(dev);
- ret = nouveau_mem_vram_init(dev);
+ ret = engine->vram.init(dev);
if (ret)
goto out_bios;
@@ -539,10 +547,14 @@ nouveau_card_init(struct drm_device *dev)
if (ret)
goto out_gpuobj;
- ret = nouveau_mem_gart_init(dev);
+ ret = nouveau_mem_vram_init(dev);
if (ret)
goto out_instmem;
+ ret = nouveau_mem_gart_init(dev);
+ if (ret)
+ goto out_ttmvram;
+
/* PMC */
ret = engine->mc.init(dev);
if (ret)
@@ -563,7 +575,7 @@ nouveau_card_init(struct drm_device *dev)
if (ret)
goto out_timer;
- if (!nouveau_noaccel) {
+ if (!dev_priv->noaccel) {
switch (dev_priv->card_type) {
case NV_04:
nv04_graph_create(dev);
@@ -675,14 +687,14 @@ out_vblank:
drm_vblank_cleanup(dev);
engine->display.destroy(dev);
out_fifo:
- if (!nouveau_noaccel)
+ if (!dev_priv->noaccel)
engine->fifo.takedown(dev);
out_engine:
- if (!nouveau_noaccel) {
+ if (!dev_priv->noaccel) {
for (e = e - 1; e >= 0; e--) {
if (!dev_priv->eng[e])
continue;
- dev_priv->eng[e]->fini(dev, e);
+ dev_priv->eng[e]->fini(dev, e, false);
dev_priv->eng[e]->destroy(dev,e );
}
}
@@ -696,12 +708,14 @@ out_mc:
engine->mc.takedown(dev);
out_gart:
nouveau_mem_gart_fini(dev);
+out_ttmvram:
+ nouveau_mem_vram_fini(dev);
out_instmem:
engine->instmem.takedown(dev);
out_gpuobj:
nouveau_gpuobj_takedown(dev);
out_vram:
- nouveau_mem_vram_fini(dev);
+ engine->vram.takedown(dev);
out_bios:
nouveau_pm_fini(dev);
nouveau_bios_takedown(dev);
@@ -718,16 +732,21 @@ 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_priv->channel) {
- nouveau_fence_fini(dev);
nouveau_channel_put_unlocked(&dev_priv->channel);
+ nouveau_fence_fini(dev);
}
- if (!nouveau_noaccel) {
+ engine->display.destroy(dev);
+
+ if (!dev_priv->noaccel) {
engine->fifo.takedown(dev);
for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
if (dev_priv->eng[e]) {
- dev_priv->eng[e]->fini(dev, e);
+ dev_priv->eng[e]->fini(dev, e, false);
dev_priv->eng[e]->destroy(dev,e );
}
}
@@ -748,10 +767,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
mutex_unlock(&dev->struct_mutex);
nouveau_mem_gart_fini(dev);
+ nouveau_mem_vram_fini(dev);
engine->instmem.takedown(dev);
nouveau_gpuobj_takedown(dev);
- nouveau_mem_vram_fini(dev);
+ engine->vram.takedown(dev);
nouveau_irq_fini(dev);
drm_vblank_cleanup(dev);
@@ -762,6 +782,41 @@ static void nouveau_card_takedown(struct drm_device *dev)
vga_client_register(dev->pdev, NULL, NULL, NULL);
}
+int
+nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_fpriv *fpriv;
+ int ret;
+
+ fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+ if (unlikely(!fpriv))
+ return -ENOMEM;
+
+ spin_lock_init(&fpriv->lock);
+ INIT_LIST_HEAD(&fpriv->channels);
+
+ if (dev_priv->card_type == NV_50) {
+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
+ &fpriv->vm);
+ if (ret) {
+ kfree(fpriv);
+ return ret;
+ }
+ } else
+ if (dev_priv->card_type >= NV_C0) {
+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+ &fpriv->vm);
+ if (ret) {
+ kfree(fpriv);
+ return ret;
+ }
+ }
+
+ file_priv->driver_priv = fpriv;
+ return 0;
+}
+
/* here a client dies, release the stuff that was allocated for its
* file_priv */
void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
@@ -769,6 +824,14 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
nouveau_channel_cleanup(dev, file_priv);
}
+void
+nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+ nouveau_vm_ref(NULL, &fpriv->vm, NULL);
+ kfree(fpriv);
+}
+
/* first module load, setup the mmio/fb mapping */
/* KMS: we need mmio at load time, not when the first drm client opens. */
int nouveau_firstopen(struct drm_device *dev)
@@ -933,6 +996,25 @@ 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 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.
+ */
+ dev_priv->noaccel = !!nouveau_noaccel;
+ if (nouveau_noaccel == -1) {
+ switch (dev_priv->chipset) {
+ case 0xc1: /* known broken */
+ case 0xc8: /* never tested */
+ NV_INFO(dev, "acceleration disabled by default, pass "
+ "noaccel=0 to force enable\n");
+ dev_priv->noaccel = true;
+ break;
+ default:
+ dev_priv->noaccel = false;
+ break;
+ }
+ }
+
ret = nouveau_remove_conflicting_drivers(dev);
if (ret)
goto err_mmio;
@@ -997,11 +1079,7 @@ void nouveau_lastclose(struct drm_device *dev)
int nouveau_unload(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_engine *engine = &dev_priv->engine;
- drm_kms_helper_poll_fini(dev);
- nouveau_fbcon_fini(dev);
- engine->display.destroy(dev);
nouveau_card_takedown(dev);
iounmap(dev_priv->mmio);
@@ -1031,7 +1109,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
case NOUVEAU_GETPARAM_BUS_TYPE:
if (drm_pci_device_is_agp(dev))
getparam->value = NV_AGP;
- else if (drm_pci_device_is_pcie(dev))
+ else if (pci_is_pcie(dev->pdev))
getparam->value = NV_PCIE;
else
getparam->value = NV_PCI;
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c
index 649b0413b09f..081ca7b03e8a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_temp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_temp.c
@@ -43,7 +43,7 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
/* Set the default sensor's contants */
sensor->offset_constant = 0;
- sensor->offset_mult = 1;
+ sensor->offset_mult = 0;
sensor->offset_div = 1;
sensor->slope_mult = 1;
sensor->slope_div = 1;
@@ -99,6 +99,13 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
sensor->slope_mult = 431;
sensor->slope_div = 10000;
break;
+
+ case 0x67:
+ sensor->offset_mult = -26149;
+ sensor->offset_div = 100;
+ sensor->slope_mult = 484;
+ sensor->slope_div = 10000;
+ break;
}
}
@@ -109,7 +116,7 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
/* Read the entries from the table */
for (i = 0; i < entries; i++) {
- u16 value = ROM16(temp[1]);
+ s16 value = ROM16(temp[1]);
switch (temp[0]) {
case 0x01:
@@ -160,8 +167,8 @@ nv40_sensor_setup(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
- u32 offset = sensor->offset_mult / sensor->offset_div;
- u32 sensor_calibration;
+ s32 offset = sensor->offset_mult / sensor->offset_div;
+ s32 sensor_calibration;
/* set up the sensors */
sensor_calibration = 120 - offset - sensor->offset_constant;
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
index 519a6b4bba46..244fd38fdb84 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
@@ -369,23 +369,26 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
}
static void
-nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
+nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
{
struct nouveau_vm_pgd *vpgd, *tmp;
+ struct nouveau_gpuobj *pgd = NULL;
- if (!pgd)
+ if (!mpgd)
return;
mutex_lock(&vm->mm->mutex);
list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
- if (vpgd->obj != pgd)
- continue;
-
- list_del(&vpgd->head);
- nouveau_gpuobj_ref(NULL, &vpgd->obj);
- kfree(vpgd);
+ if (vpgd->obj == mpgd) {
+ pgd = vpgd->obj;
+ list_del(&vpgd->head);
+ kfree(vpgd);
+ break;
+ }
}
mutex_unlock(&vm->mm->mutex);
+
+ nouveau_gpuobj_ref(NULL, &pgd);
}
static void
@@ -396,8 +399,8 @@ nouveau_vm_del(struct nouveau_vm *vm)
list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
nouveau_vm_unlink(vm, vpgd->obj);
}
- WARN_ON(nouveau_mm_fini(&vm->mm) != 0);
+ nouveau_mm_fini(&vm->mm);
kfree(vm->pgt);
kfree(vm);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index c48a9fc2b47b..579ca8cc223c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -41,6 +41,8 @@ struct nouveau_vm_pgd {
};
struct nouveau_vma {
+ struct list_head head;
+ int refcount;
struct nouveau_vm *vm;
struct nouveau_mm_node *node;
u64 offset;
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index f1a3ae491995..118261d4927a 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -1035,7 +1035,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs);
drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
- ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+ 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);
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c
index 3626ee7db3ba..dbdea8ed3925 100644
--- a/drivers/gpu/drm/nouveau/nv04_graph.c
+++ b/drivers/gpu/drm/nouveau/nv04_graph.c
@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
- nv04_graph_fifo_access(dev, false);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Unload the context if it's the currently active one */
if (nv04_graph_channel(dev) == chan)
nv04_graph_unload_context(dev);
- nv04_graph_fifo_access(dev, true);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */
@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine)
}
static int
-nv04_graph_fini(struct drm_device *dev, int engine)
+nv04_graph_fini(struct drm_device *dev, int engine, bool suspend)
{
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+ return -EBUSY;
+ }
nv04_graph_unload_context(dev);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0;
}
-void
-nv04_graph_fifo_access(struct drm_device *dev, bool enabled)
-{
- if (enabled)
- nv_wr32(dev, NV04_PGRAPH_FIFO,
- nv_rd32(dev, NV04_PGRAPH_FIFO) | 1);
- else
- nv_wr32(dev, NV04_PGRAPH_FIFO,
- nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1);
-}
-
static int
nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
u32 class, u32 mthd, u32 data)
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c
index b8611b955313..c1248e0740a3 100644
--- a/drivers/gpu/drm/nouveau/nv04_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv04_instmem.c
@@ -28,6 +28,31 @@ int nv04_instmem_init(struct drm_device *dev)
/* RAMIN always available */
dev_priv->ramin_available = true;
+ /* Reserve space at end of VRAM for PRAMIN */
+ if (dev_priv->card_type >= NV_40) {
+ u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
+ u32 rsvd;
+
+ /* estimate grctx size, the magics come from nv40_grctx.c */
+ if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
+ else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs;
+ else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs;
+ else rsvd = 0x4a40 * vs;
+ rsvd += 16 * 1024;
+ rsvd *= dev_priv->engine.fifo.channels;
+
+ /* pciegart table */
+ if (pci_is_pcie(dev->pdev))
+ rsvd += 512 * 1024;
+
+ /* object storage */
+ rsvd += 512 * 1024;
+
+ dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
+ } else {
+ dev_priv->ramin_rsvd_vram = 512 * 1024;
+ }
+
/* Setup shared RAMHT */
ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096,
NVOBJ_FLAG_ZERO_ALLOC, &ramht);
@@ -112,7 +137,8 @@ nv04_instmem_resume(struct drm_device *dev)
}
int
-nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
+nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
+ u32 size, u32 align)
{
struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
struct drm_mm_node *ramin = NULL;
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c
index 0930c6cb88e0..7255e4a4d3f3 100644
--- a/drivers/gpu/drm/nouveau/nv10_graph.c
+++ b/drivers/gpu/drm/nouveau/nv10_graph.c
@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
- nv04_graph_fifo_access(dev, true);
- nv04_graph_fifo_access(dev, false);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Restore the FIFO state */
for (i = 0; i < ARRAY_SIZE(fifo); i++)
@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
- nv04_graph_fifo_access(dev, false);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Unload the context if it's the currently active one */
if (nv10_graph_channel(dev) == chan)
nv10_graph_unload_context(dev);
- nv04_graph_fifo_access(dev, true);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */
@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine)
}
static int
-nv10_graph_fini(struct drm_device *dev, int engine)
+nv10_graph_fini(struct drm_device *dev, int engine, bool suspend)
{
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+ return -EBUSY;
+ }
nv10_graph_unload_context(dev);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c
index affc7d7dd029..183e37512ef9 100644
--- a/drivers/gpu/drm/nouveau/nv20_graph.c
+++ b/drivers/gpu/drm/nouveau/nv20_graph.c
@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
- nv04_graph_fifo_access(dev, false);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Unload the context if it's the currently active one */
if (nv10_graph_channel(dev) == chan)
nv20_graph_unload_context(dev);
- nv04_graph_fifo_access(dev, true);
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */
@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine)
}
int
-nv20_graph_fini(struct drm_device *dev, int engine)
+nv20_graph_fini(struct drm_device *dev, int engine, bool suspend)
{
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+ return -EBUSY;
+ }
nv20_graph_unload_context(dev);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0;
@@ -753,6 +758,7 @@ nv20_graph_create(struct drm_device *dev)
break;
default:
NV_ERROR(dev, "PGRAPH: unknown chipset\n");
+ kfree(pgraph);
return 0;
}
} else {
@@ -774,6 +780,7 @@ nv20_graph_create(struct drm_device *dev)
break;
default:
NV_ERROR(dev, "PGRAPH: unknown chipset\n");
+ kfree(pgraph);
return 0;
}
}
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c
index 5beb01b8ace1..ba14a93d8afa 100644
--- a/drivers/gpu/drm/nouveau/nv40_graph.c
+++ b/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -35,89 +35,6 @@ struct nv40_graph_engine {
u32 grctx_size;
};
-static struct nouveau_channel *
-nv40_graph_channel(struct drm_device *dev)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_gpuobj *grctx;
- uint32_t inst;
- int i;
-
- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
- return NULL;
- inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
-
- for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
- if (!dev_priv->channels.ptr[i])
- continue;
-
- grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
- if (grctx && grctx->pinst == inst)
- return dev_priv->channels.ptr[i];
- }
-
- return NULL;
-}
-
-static int
-nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
-{
- uint32_t old_cp, tv = 1000, tmp;
- int i;
-
- old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER);
- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
-
- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310);
- tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
- NV40_PGRAPH_CTXCTL_0310_XFER_LOAD;
- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp);
-
- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304);
- tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX;
- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp);
-
- nouveau_wait_for_idle(dev);
-
- for (i = 0; i < tv; i++) {
- if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0)
- break;
- }
-
- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
-
- if (i == tv) {
- uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT);
- NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save);
- NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n",
- ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT,
- ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK);
- NV_ERROR(dev, "0x40030C = 0x%08x\n",
- nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C));
- return -EBUSY;
- }
-
- return 0;
-}
-
-static int
-nv40_graph_unload_context(struct drm_device *dev)
-{
- uint32_t inst;
- int ret;
-
- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
- return 0;
- inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
-
- ret = nv40_graph_transfer_context(dev, inst, 1);
-
- nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
- return ret;
-}
-
static int
nv40_graph_context_new(struct nouveau_channel *chan, int engine)
{
@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine)
struct nouveau_gpuobj *grctx = chan->engctx[engine];
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ u32 inst = 0x01000000 | (grctx->pinst >> 4);
unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
- nv04_graph_fifo_access(dev, false);
-
- /* Unload the context if it's the currently active one */
- if (nv40_graph_channel(dev) == chan)
- nv40_graph_unload_context(dev);
-
- nv04_graph_fifo_access(dev, true);
+ nv_mask(dev, 0x400720, 0x00000000, 0x00000001);
+ if (nv_rd32(dev, 0x40032c) == inst)
+ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
+ if (nv_rd32(dev, 0x400330) == inst)
+ nv_mask(dev, 0x400330, 0x01000000, 0x00000000);
+ nv_mask(dev, 0x400720, 0x00000001, 0x00000001);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */
@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine)
}
static int
-nv40_graph_fini(struct drm_device *dev, int engine)
+nv40_graph_fini(struct drm_device *dev, int engine, bool suspend)
{
- nv40_graph_unload_context(dev);
+ u32 inst = nv_rd32(dev, 0x40032c);
+ if (inst & 0x01000000) {
+ nv_wr32(dev, 0x400720, 0x00000000);
+ nv_wr32(dev, 0x400784, inst);
+ nv_mask(dev, 0x400310, 0x00000020, 0x00000020);
+ nv_mask(dev, 0x400304, 0x00000001, 0x00000001);
+ if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) {
+ u32 insn = nv_rd32(dev, 0x400308);
+ NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn);
+ }
+ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c
index 6d2af292a2e3..ad03a0e1fc7d 100644
--- a/drivers/gpu/drm/nouveau/nv40_mpeg.c
+++ b/drivers/gpu/drm/nouveau/nv40_mpeg.c
@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine)
}
static int
-nv40_mpeg_fini(struct drm_device *dev, int engine)
+nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
{
/*XXX: context save? */
nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index ebabacf38da9..46ad59ea2185 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -104,7 +104,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
OUT_RING(evo, nv_crtc->lut.depth == 8 ?
NV50_EVO_CRTC_CLUT_MODE_OFF :
NV50_EVO_CRTC_CLUT_MODE_ON);
- OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+ OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8);
if (dev_priv->chipset != 0x50) {
BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
OUT_RING(evo, NvEvoVRAM);
@@ -372,7 +372,7 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
nouveau_bo_unmap(cursor);
- nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT);
+ nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
nv_crtc->cursor.show(nv_crtc, true);
out:
@@ -546,7 +546,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
}
}
- nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT;
+ nv_crtc->fb.offset = fb->nvbo->bo.offset;
nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
@@ -747,7 +747,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
}
nv_crtc->lut.depth = 0;
- ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM,
+ ret = nouveau_bo_new(dev, 4096, 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);
@@ -773,7 +773,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
- ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+ 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);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 08da478ba544..db1a5f4b711d 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -415,8 +415,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/* synchronise with the rendering channel, if necessary */
if (likely(chan)) {
- u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset;
-
ret = RING_SPACE(chan, 10);
if (ret) {
WIND_RING(evo);
@@ -438,6 +436,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
else
OUT_RING (chan, chan->vram_handle);
} else {
+ u64 offset = chan->dispc_vma[nv_crtc->index].offset;
+ offset += dispc->sem.offset;
BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
OUT_RING (chan, upper_32_bits(offset));
OUT_RING (chan, lower_32_bits(offset));
@@ -484,7 +484,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
OUT_RING (evo, 0x00000000);
OUT_RING (evo, 0x00000000);
BEGIN_RING(evo, 0, 0x0800, 5);
- OUT_RING (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+ OUT_RING (evo, nv_fb->nvbo->bo.offset >> 8);
OUT_RING (evo, 0);
OUT_RING (evo, (fb->height << 16) | fb->width);
OUT_RING (evo, nv_fb->r_pitch);
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c
index c8e83c1a4de8..c99d9751880c 100644
--- a/drivers/gpu/drm/nouveau/nv50_evo.c
+++ b/drivers/gpu/drm/nouveau/nv50_evo.c
@@ -38,6 +38,7 @@ nv50_evo_channel_del(struct nouveau_channel **pevo)
return;
*pevo = NULL;
+ nouveau_ramht_ref(NULL, &evo->ramht, evo);
nouveau_gpuobj_channel_takedown(evo);
nouveau_bo_unmap(evo->pushbuf_bo);
nouveau_bo_ref(NULL, &evo->pushbuf_bo);
@@ -116,7 +117,7 @@ nv50_evo_channel_new(struct drm_device *dev, int chid,
evo->user_get = 4;
evo->user_put = 0;
- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
+ ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
&evo->pushbuf_bo);
if (ret == 0)
ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
@@ -153,7 +154,7 @@ nv50_evo_channel_init(struct nouveau_channel *evo)
{
struct drm_device *dev = evo->dev;
int id = evo->id, ret, i;
- u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT;
+ u64 pushbuf = evo->pushbuf_bo->bo.offset;
u32 tmp;
tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id));
@@ -331,16 +332,15 @@ nv50_evo_create(struct drm_device *dev)
if (ret)
goto err;
- ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM,
+ ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
0, 0x0000, &dispc->sem.bo);
if (!ret) {
- offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
-
ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM);
if (!ret)
ret = nouveau_bo_map(dispc->sem.bo);
if (ret)
nouveau_bo_ref(NULL, &dispc->sem.bo);
+ offset = dispc->sem.bo->bo.offset;
}
if (ret)
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index 791ded1c5c6d..dc75a7206524 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -159,7 +159,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
- struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
+ struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
int ret, format;
switch (info->var.bits_per_pixel) {
@@ -247,8 +247,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, info->fix.line_length);
OUT_RING(chan, info->var.xres_virtual);
OUT_RING(chan, info->var.yres_virtual);
- OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
- OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
+ OUT_RING(chan, upper_32_bits(fb->vma.offset));
+ OUT_RING(chan, lower_32_bits(fb->vma.offset));
BEGIN_RING(chan, NvSub2D, 0x0230, 2);
OUT_RING(chan, format);
OUT_RING(chan, 1);
@@ -256,8 +256,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, info->fix.line_length);
OUT_RING(chan, info->var.xres_virtual);
OUT_RING(chan, info->var.yres_virtual);
- OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
- OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
+ OUT_RING(chan, upper_32_bits(fb->vma.offset));
+ OUT_RING(chan, lower_32_bits(fb->vma.offset));
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index e25cbb46789a..d43c46caa76e 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -31,7 +31,6 @@
#include "nouveau_grctx.h"
#include "nouveau_dma.h"
#include "nouveau_vm.h"
-#include "nouveau_ramht.h"
#include "nv50_evo.h"
struct nv50_graph_engine {
@@ -125,7 +124,6 @@ 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);
@@ -255,9 +253,13 @@ nv50_graph_init(struct drm_device *dev, int engine)
}
static int
-nv50_graph_fini(struct drm_device *dev, int engine)
+nv50_graph_fini(struct drm_device *dev, int engine, bool suspend)
{
- NV_DEBUG(dev, "\n");
+ nv_mask(dev, 0x400500, 0x00010001, 0x00000000);
+ if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) {
+ nv_mask(dev, 0x400500, 0x00010001, 0x00010001);
+ return -EBUSY;
+ }
nv50_graph_unload_context(dev);
nv_wr32(dev, 0x40013c, 0x00000000);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
index 4f95a1e5822e..a7c12c94a5a6 100644
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
@@ -305,9 +305,9 @@ struct nv50_gpuobj_node {
u32 align;
};
-
int
-nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
+nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
+ u32 size, u32 align)
{
struct drm_device *dev = gpuobj->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -336,7 +336,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER))
flags |= NV_MEM_ACCESS_SYS;
- ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, flags,
+ ret = nouveau_vm_get(chan->vm, size, 12, flags,
&node->chan_vma);
if (ret) {
vram->put(dev, &node->vram);
@@ -345,7 +345,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
}
nouveau_vm_map(&node->chan_vma, node->vram);
- gpuobj->vinst = node->chan_vma.offset;
+ gpuobj->linst = node->chan_vma.offset;
}
gpuobj->size = size;
diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c
index 1dc5913f78c5..b57a2d180ad2 100644
--- a/drivers/gpu/drm/nouveau/nv50_mpeg.c
+++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c
@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine)
}
static int
-nv50_mpeg_fini(struct drm_device *dev, int engine)
+nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
{
/*XXX: context save for s/r */
nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index c25c59386420..ffe8b483b7b0 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -318,6 +318,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
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:
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
index 1a0dd491a0e4..40b84f22d819 100644
--- a/drivers/gpu/drm/nouveau/nv50_vm.c
+++ b/drivers/gpu/drm/nouveau/nv50_vm.c
@@ -156,7 +156,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
pinstmem->flush(vm->dev);
/* BAR */
- if (vm != dev_priv->chan_vm) {
+ if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) {
nv50_vm_flush_engine(vm->dev, 6);
return;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c
index ffbc3d8cf5be..af32daecd1ed 100644
--- a/drivers/gpu/drm/nouveau/nv50_vram.c
+++ b/drivers/gpu/drm/nouveau/nv50_vram.c
@@ -51,9 +51,7 @@ void
nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
- struct nouveau_mm *mm = man->priv;
+ struct nouveau_mm *mm = dev_priv->engine.vram.mm;
struct nouveau_mm_node *this;
struct nouveau_mem *mem;
@@ -84,9 +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 ttm_bo_device *bdev = &dev_priv->ttm.bdev;
- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
- struct nouveau_mm *mm = man->priv;
+ struct nouveau_mm *mm = dev_priv->engine.vram.mm;
struct nouveau_mm_node *r;
struct nouveau_mem *mem;
int comp = (memtype & 0x300) >> 8;
@@ -190,22 +186,35 @@ int
nv50_vram_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ 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 rblock, length;
dev_priv->vram_size = nv_rd32(dev, 0x10020c);
dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
dev_priv->vram_size &= 0xffffffff00ULL;
- switch (dev_priv->chipset) {
- case 0xaa:
- case 0xac:
- case 0xaf:
+ /* IGPs, no funky reordering happens here, they don't have VRAM */
+ if (dev_priv->chipset == 0xaa ||
+ dev_priv->chipset == 0xac ||
+ dev_priv->chipset == 0xaf) {
dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
- dev_priv->vram_rblock_size = 4096;
- break;
- default:
- dev_priv->vram_rblock_size = nv50_vram_rblock(dev);
- break;
+ rblock = 4096 >> 12;
+ } else {
+ rblock = nv50_vram_rblock(dev) >> 12;
}
- return 0;
+ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+
+ return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock);
+}
+
+void
+nv50_vram_fini(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+
+ nouveau_mm_fini(&vram->mm);
}
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c
index 75b809a51748..edece9c616eb 100644
--- a/drivers/gpu/drm/nouveau/nv84_crypt.c
+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c
@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev)
}
static int
-nv84_crypt_fini(struct drm_device *dev, int engine)
+nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend)
{
nv_wr32(dev, 0x102140, 0x00000000);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c
index b86820a61220..8f356d58e409 100644
--- a/drivers/gpu/drm/nouveau/nva3_copy.c
+++ b/drivers/gpu/drm/nouveau/nva3_copy.c
@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine)
}
static int
-nva3_copy_fini(struct drm_device *dev, int engine)
+nva3_copy_fini(struct drm_device *dev, int engine, bool suspend)
{
nv_mask(dev, 0x104048, 0x00000003, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.c b/drivers/gpu/drm/nouveau/nvc0_copy.c
index 208fa7ab3f42..dddf006f6d88 100644
--- a/drivers/gpu/drm/nouveau/nvc0_copy.c
+++ b/drivers/gpu/drm/nouveau/nvc0_copy.c
@@ -48,14 +48,14 @@ nvc0_copy_context_new(struct nouveau_channel *chan, int engine)
struct nouveau_gpuobj *ctx = NULL;
int ret;
- ret = nouveau_gpuobj_new(dev, NULL, 256, 256,
+ ret = nouveau_gpuobj_new(dev, chan, 256, 256,
NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER |
NVOBJ_FLAG_ZERO_ALLOC, &ctx);
if (ret)
return ret;
- nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->vinst));
- nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->vinst));
+ nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst));
+ nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst));
dev_priv->engine.instmem.flush(dev);
chan->engctx[engine] = ctx;
@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine)
}
static int
-nvc0_copy_fini(struct drm_device *dev, int engine)
+nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend)
{
struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
index 26a996025dd2..08e6b118f021 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fb.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 Red Hat Inc.
+ * 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"),
@@ -23,16 +23,80 @@
*/
#include "drmP.h"
-
+#include "drm.h"
#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+struct nvc0_fb_priv {
+ struct page *r100c10_page;
+ dma_addr_t r100c10;
+};
+
+static void
+nvc0_fb_destroy(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+ struct nvc0_fb_priv *priv = pfb->priv;
+
+ if (priv->r100c10_page) {
+ pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ __free_page(priv->r100c10_page);
+ }
+
+ kfree(priv);
+ pfb->priv = NULL;
+}
+
+static int
+nvc0_fb_create(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+ struct nvc0_fb_priv *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ pfb->priv = priv;
+
+ priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!priv->r100c10_page) {
+ nvc0_fb_destroy(dev);
+ return -ENOMEM;
+ }
+
+ priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0,
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) {
+ nvc0_fb_destroy(dev);
+ return -EFAULT;
+ }
+
+ return 0;
+}
int
nvc0_fb_init(struct drm_device *dev)
{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nvc0_fb_priv *priv;
+ int ret;
+
+ if (!dev_priv->engine.fb.priv) {
+ ret = nvc0_fb_create(dev);
+ if (ret)
+ return ret;
+ }
+ priv = dev_priv->engine.fb.priv;
+
+ nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
return 0;
}
void
nvc0_fb_takedown(struct drm_device *dev)
{
+ nvc0_fb_destroy(dev);
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index fa5d4c234383..a495e48197ca 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -159,7 +159,7 @@ nvc0_fbcon_accel_init(struct fb_info *info)
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
- struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
+ struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
int ret, format;
ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d);
@@ -203,8 +203,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
BEGIN_NVC0(chan, 2, NvSub2D, 0x0000, 1);
OUT_RING (chan, 0x0000902d);
BEGIN_NVC0(chan, 2, NvSub2D, 0x0104, 2);
- OUT_RING (chan, upper_32_bits(chan->notifier_bo->bo.offset));
- OUT_RING (chan, lower_32_bits(chan->notifier_bo->bo.offset));
+ OUT_RING (chan, upper_32_bits(chan->notifier_vma.offset));
+ OUT_RING (chan, lower_32_bits(chan->notifier_vma.offset));
BEGIN_NVC0(chan, 2, NvSub2D, 0x0290, 1);
OUT_RING (chan, 0);
BEGIN_NVC0(chan, 2, NvSub2D, 0x0888, 1);
@@ -249,8 +249,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
OUT_RING (chan, info->fix.line_length);
OUT_RING (chan, info->var.xres_virtual);
OUT_RING (chan, info->var.yres_virtual);
- OUT_RING (chan, upper_32_bits(nvbo->vma.offset));
- OUT_RING (chan, lower_32_bits(nvbo->vma.offset));
+ OUT_RING (chan, upper_32_bits(fb->vma.offset));
+ OUT_RING (chan, lower_32_bits(fb->vma.offset));
BEGIN_NVC0(chan, 2, NvSub2D, 0x0230, 10);
OUT_RING (chan, format);
OUT_RING (chan, 1);
@@ -260,8 +260,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
OUT_RING (chan, info->fix.line_length);
OUT_RING (chan, info->var.xres_virtual);
OUT_RING (chan, info->var.yres_virtual);
- OUT_RING (chan, upper_32_bits(nvbo->vma.offset));
- OUT_RING (chan, lower_32_bits(nvbo->vma.offset));
+ OUT_RING (chan, upper_32_bits(fb->vma.offset));
+ OUT_RING (chan, lower_32_bits(fb->vma.offset));
FIRE_RING (chan);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index fb4f5943e01b..6f9f341c3e86 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -210,10 +210,10 @@ nvc0_fifo_unload_context(struct drm_device *dev)
int i;
for (i = 0; i < 128; i++) {
- if (!(nv_rd32(dev, 0x003004 + (i * 4)) & 1))
+ if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1))
continue;
- nv_mask(dev, 0x003004 + (i * 4), 0x00000001, 0x00000000);
+ nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000);
nv_wr32(dev, 0x002634, i);
if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c
index ca6db204d644..5b2f6f420468 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.c
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c
@@ -28,7 +28,34 @@
#include "nouveau_drv.h"
#include "nouveau_mm.h"
+
#include "nvc0_graph.h"
+#include "nvc0_grhub.fuc.h"
+#include "nvc0_grgpc.fuc.h"
+
+static void
+nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base)
+{
+ NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base,
+ nv_rd32(dev, base + 0x400));
+ NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
+ nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804),
+ nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c));
+ NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
+ nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814),
+ nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c));
+}
+
+static void
+nvc0_graph_ctxctl_debug(struct drm_device *dev)
+{
+ u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff;
+ u32 gpc;
+
+ nvc0_graph_ctxctl_debug_unit(dev, 0x409000);
+ for (gpc = 0; gpc < gpcnr; gpc++)
+ nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000));
+}
static int
nvc0_graph_load_context(struct nouveau_channel *chan)
@@ -72,24 +99,44 @@ nvc0_graph_construct_context(struct nouveau_channel *chan)
if (!ctx)
return -ENOMEM;
- nvc0_graph_load_context(chan);
-
- nv_wo32(grch->grctx, 0x1c, 1);
- nv_wo32(grch->grctx, 0x20, 0);
- nv_wo32(grch->grctx, 0x28, 0);
- nv_wo32(grch->grctx, 0x2c, 0);
- dev_priv->engine.instmem.flush(dev);
-
- ret = nvc0_grctx_generate(chan);
- if (ret) {
- kfree(ctx);
- return ret;
+ if (!nouveau_ctxfw) {
+ nv_wr32(dev, 0x409840, 0x80000000);
+ nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
+ nv_wr32(dev, 0x409504, 0x00000001);
+ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+ NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n");
+ nvc0_graph_ctxctl_debug(dev);
+ ret = -EBUSY;
+ goto err;
+ }
+ } else {
+ nvc0_graph_load_context(chan);
+
+ nv_wo32(grch->grctx, 0x1c, 1);
+ nv_wo32(grch->grctx, 0x20, 0);
+ nv_wo32(grch->grctx, 0x28, 0);
+ nv_wo32(grch->grctx, 0x2c, 0);
+ dev_priv->engine.instmem.flush(dev);
}
- ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
- if (ret) {
- kfree(ctx);
- return ret;
+ ret = nvc0_grctx_generate(chan);
+ if (ret)
+ goto err;
+
+ if (!nouveau_ctxfw) {
+ nv_wr32(dev, 0x409840, 0x80000000);
+ nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
+ nv_wr32(dev, 0x409504, 0x00000002);
+ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+ NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n");
+ nvc0_graph_ctxctl_debug(dev);
+ ret = -EBUSY;
+ goto err;
+ }
+ } else {
+ ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
+ if (ret)
+ goto err;
}
for (i = 0; i < priv->grctx_size; i += 4)
@@ -97,6 +144,10 @@ nvc0_graph_construct_context(struct nouveau_channel *chan)
priv->grctx_vals = ctx;
return 0;
+
+err:
+ kfree(ctx);
+ return ret;
}
static int
@@ -108,50 +159,50 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
int i = 0, gpc, tp, ret;
u32 magic;
- ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, NVOBJ_FLAG_VM,
+ ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
&grch->unk408004);
if (ret)
return ret;
- ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, NVOBJ_FLAG_VM,
+ ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM,
&grch->unk40800c);
if (ret)
return ret;
- ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096,
+ ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096,
NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER,
&grch->unk418810);
if (ret)
return ret;
- ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, NVOBJ_FLAG_VM,
+ ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM,
&grch->mmio);
if (ret)
return ret;
nv_wo32(grch->mmio, i++ * 4, 0x00408004);
- nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+ nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
nv_wo32(grch->mmio, i++ * 4, 0x00408008);
nv_wo32(grch->mmio, i++ * 4, 0x80000018);
nv_wo32(grch->mmio, i++ * 4, 0x0040800c);
- nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+ nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
nv_wo32(grch->mmio, i++ * 4, 0x00408010);
nv_wo32(grch->mmio, i++ * 4, 0x80000000);
nv_wo32(grch->mmio, i++ * 4, 0x00418810);
- nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->vinst >> 12);
+ nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12);
nv_wo32(grch->mmio, i++ * 4, 0x00419848);
- nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->vinst >> 12);
+ nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12);
nv_wo32(grch->mmio, i++ * 4, 0x00419004);
- nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+ nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
nv_wo32(grch->mmio, i++ * 4, 0x00419008);
nv_wo32(grch->mmio, i++ * 4, 0x00000000);
nv_wo32(grch->mmio, i++ * 4, 0x00418808);
- nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+ nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
nv_wo32(grch->mmio, i++ * 4, 0x80000018);
@@ -159,7 +210,7 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
nv_wo32(grch->mmio, i++ * 4, 0x00405830);
nv_wo32(grch->mmio, i++ * 4, magic);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
- for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x02fc) {
+ for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
nv_wo32(grch->mmio, i++ * 4, reg);
nv_wo32(grch->mmio, i++ * 4, magic);
@@ -186,7 +237,7 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
return -ENOMEM;
chan->engctx[NVOBJ_ENGINE_GR] = grch;
- ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256,
+ ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256,
NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC,
&grch->grctx);
if (ret)
@@ -197,8 +248,8 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
if (ret)
goto error;
- nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->vinst) | 4);
- nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->vinst));
+ nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4);
+ nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst));
pinstmem->flush(dev);
if (!priv->grctx_vals) {
@@ -210,15 +261,20 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
for (i = 0; i < priv->grctx_size; i += 4)
nv_wo32(grctx, i, priv->grctx_vals[i / 4]);
- nv_wo32(grctx, 0xf4, 0);
- nv_wo32(grctx, 0xf8, 0);
- nv_wo32(grctx, 0x10, grch->mmio_nr);
- nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst));
- nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst));
- nv_wo32(grctx, 0x1c, 1);
- nv_wo32(grctx, 0x20, 0);
- nv_wo32(grctx, 0x28, 0);
- nv_wo32(grctx, 0x2c, 0);
+ if (!nouveau_ctxfw) {
+ nv_wo32(grctx, 0x00, grch->mmio_nr);
+ nv_wo32(grctx, 0x04, grch->mmio->linst >> 8);
+ } else {
+ nv_wo32(grctx, 0xf4, 0);
+ nv_wo32(grctx, 0xf8, 0);
+ nv_wo32(grctx, 0x10, grch->mmio_nr);
+ nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst));
+ nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst));
+ nv_wo32(grctx, 0x1c, 1);
+ nv_wo32(grctx, 0x20, 0);
+ nv_wo32(grctx, 0x28, 0);
+ nv_wo32(grctx, 0x2c, 0);
+ }
pinstmem->flush(dev);
return 0;
@@ -248,7 +304,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine,
}
static int
-nvc0_graph_fini(struct drm_device *dev, int engine)
+nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend)
{
return 0;
}
@@ -296,6 +352,7 @@ static void
nvc0_graph_init_gpc_0(struct drm_device *dev)
{
struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
+ const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total);
u32 data[TP_MAX / 8];
u8 tpnr[GPC_MAX];
int i, gpc, tpc;
@@ -307,13 +364,6 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)
* 465: 3/4/4/0 4 7
* 470: 3/3/4/4 5 5
* 480: 3/4/4/4 6 6
- *
- * magicgpc918
- * 450: 00200000 00000000001000000000000000000000
- * 460: 00124925 00000000000100100100100100100101
- * 465: 000ba2e9 00000000000010111010001011101001
- * 470: 00092493 00000000000010010010010010010011
- * 480: 00088889 00000000000010001000100010001001
*/
memset(data, 0x00, sizeof(data));
@@ -336,10 +386,10 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)
nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
priv->tp_nr[gpc]);
nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total);
- nv_wr32(dev, GPC_UNIT(gpc, 0x0918), priv->magicgpc918);
+ nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918);
}
- nv_wr32(dev, GPC_BCAST(0x1bd4), priv->magicgpc918);
+ nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
}
@@ -419,8 +469,51 @@ nvc0_graph_init_fuc(struct drm_device *dev, u32 fuc_base,
static int
nvc0_graph_init_ctxctl(struct drm_device *dev)
{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
u32 r000260;
+ int i;
+
+ if (!nouveau_ctxfw) {
+ /* load HUB microcode */
+ r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
+ nv_wr32(dev, 0x4091c0, 0x01000000);
+ for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++)
+ nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]);
+
+ nv_wr32(dev, 0x409180, 0x01000000);
+ for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) {
+ if ((i & 0x3f) == 0)
+ nv_wr32(dev, 0x409188, i >> 6);
+ nv_wr32(dev, 0x409184, nvc0_grhub_code[i]);
+ }
+
+ /* load GPC microcode */
+ nv_wr32(dev, 0x41a1c0, 0x01000000);
+ for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++)
+ nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]);
+
+ nv_wr32(dev, 0x41a180, 0x01000000);
+ for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) {
+ if ((i & 0x3f) == 0)
+ nv_wr32(dev, 0x41a188, i >> 6);
+ nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]);
+ }
+ nv_wr32(dev, 0x000260, r000260);
+
+ /* start HUB ucode running, it'll init the GPCs */
+ nv_wr32(dev, 0x409800, dev_priv->chipset);
+ nv_wr32(dev, 0x40910c, 0x00000000);
+ nv_wr32(dev, 0x409100, 0x00000002);
+ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+ NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n");
+ nvc0_graph_ctxctl_debug(dev);
+ return -EBUSY;
+ }
+
+ priv->grctx_size = nv_rd32(dev, 0x409804);
+ return 0;
+ }
/* load fuc microcode */
r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
@@ -528,6 +621,22 @@ nvc0_graph_isr_chid(struct drm_device *dev, u64 inst)
}
static void
+nvc0_graph_ctxctl_isr(struct drm_device *dev)
+{
+ u32 ustat = nv_rd32(dev, 0x409c18);
+
+ if (ustat & 0x00000001)
+ NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n");
+ if (ustat & 0x00080000)
+ NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n");
+ if (ustat & ~0x00080001)
+ NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat);
+
+ nvc0_graph_ctxctl_debug(dev);
+ nv_wr32(dev, 0x409c20, ustat);
+}
+
+static void
nvc0_graph_isr(struct drm_device *dev)
{
u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12;
@@ -578,11 +687,7 @@ nvc0_graph_isr(struct drm_device *dev)
}
if (stat & 0x00080000) {
- u32 ustat = nv_rd32(dev, 0x409c18);
-
- NV_INFO(dev, "PGRAPH: CTXCTRL ustat 0x%08x\n", ustat);
-
- nv_wr32(dev, 0x409c20, ustat);
+ nvc0_graph_ctxctl_isr(dev);
nv_wr32(dev, 0x400100, 0x00080000);
stat &= ~0x00080000;
}
@@ -606,7 +711,7 @@ nvc0_runk140_isr(struct drm_device *dev)
u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
- NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
+ NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
units &= ~(1 << unit);
}
}
@@ -651,10 +756,12 @@ nvc0_graph_destroy(struct drm_device *dev, int engine)
{
struct nvc0_graph_priv *priv = nv_engine(dev, engine);
- nvc0_graph_destroy_fw(&priv->fuc409c);
- nvc0_graph_destroy_fw(&priv->fuc409d);
- nvc0_graph_destroy_fw(&priv->fuc41ac);
- nvc0_graph_destroy_fw(&priv->fuc41ad);
+ if (nouveau_ctxfw) {
+ nvc0_graph_destroy_fw(&priv->fuc409c);
+ nvc0_graph_destroy_fw(&priv->fuc409d);
+ nvc0_graph_destroy_fw(&priv->fuc41ac);
+ nvc0_graph_destroy_fw(&priv->fuc41ad);
+ }
nouveau_irq_unregister(dev, 12);
nouveau_irq_unregister(dev, 25);
@@ -675,13 +782,10 @@ nvc0_graph_create(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvc0_graph_priv *priv;
int ret, gpc, i;
+ u32 fermi;
- switch (dev_priv->chipset) {
- case 0xc0:
- case 0xc3:
- case 0xc4:
- break;
- default:
+ fermi = nvc0_graph_class(dev);
+ if (!fermi) {
NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
return 0;
}
@@ -701,15 +805,17 @@ nvc0_graph_create(struct drm_device *dev)
nouveau_irq_register(dev, 12, nvc0_graph_isr);
nouveau_irq_register(dev, 25, nvc0_runk140_isr);
- if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
- nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
- nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
- nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
- ret = 0;
- goto error;
+ if (nouveau_ctxfw) {
+ NV_INFO(dev, "PGRAPH: using external firmware\n");
+ if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
+ nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
+ nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
+ nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
+ ret = 0;
+ goto error;
+ }
}
-
ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
if (ret)
goto error;
@@ -735,25 +841,28 @@ nvc0_graph_create(struct drm_device *dev)
case 0xc0:
if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */
priv->magic_not_rop_nr = 0x07;
- /* filled values up to tp_total, the rest 0 */
- priv->magicgpc918 = 0x000ba2e9;
} else
if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */
priv->magic_not_rop_nr = 0x05;
- priv->magicgpc918 = 0x00092493;
} else
if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */
priv->magic_not_rop_nr = 0x06;
- priv->magicgpc918 = 0x00088889;
}
break;
case 0xc3: /* 450, 4/0/0/0, 2 */
priv->magic_not_rop_nr = 0x03;
- priv->magicgpc918 = 0x00200000;
break;
case 0xc4: /* 460, 3/4/0/0, 4 */
priv->magic_not_rop_nr = 0x01;
- priv->magicgpc918 = 0x00124925;
+ break;
+ case 0xc1: /* 2/0/0/0, 1 */
+ priv->magic_not_rop_nr = 0x01;
+ break;
+ case 0xc8: /* 4/4/3/4, 5 */
+ priv->magic_not_rop_nr = 0x06;
+ break;
+ case 0xce: /* 4/4/0/0, 4 */
+ priv->magic_not_rop_nr = 0x03;
break;
}
@@ -763,13 +872,16 @@ nvc0_graph_create(struct drm_device *dev)
priv->tp_nr[3], priv->rop_nr);
/* use 0xc3's values... */
priv->magic_not_rop_nr = 0x03;
- priv->magicgpc918 = 0x00200000;
}
NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
+ if (fermi >= 0x9197)
+ NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */
+ if (fermi >= 0x9297)
+ NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */
NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.fuc b/drivers/gpu/drm/nouveau/nvc0_graph.fuc
new file mode 100644
index 000000000000..2a4b6dc8f9de
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.fuc
@@ -0,0 +1,400 @@
+/* fuc microcode util functions for nvc0 PGRAPH
+ *
+ * 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
+ */
+
+define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)')
+define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))')
+
+ifdef(`include_code', `
+// Error codes
+define(`E_BAD_COMMAND', 0x01)
+define(`E_CMD_OVERFLOW', 0x02)
+
+// Util macros to help with debugging ucode hangs etc
+define(`T_WAIT', 0)
+define(`T_MMCTX', 1)
+define(`T_STRWAIT', 2)
+define(`T_STRINIT', 3)
+define(`T_AUTO', 4)
+define(`T_CHAN', 5)
+define(`T_LOAD', 6)
+define(`T_SAVE', 7)
+define(`T_LCHAN', 8)
+define(`T_LCTXH', 9)
+
+define(`trace_set', `
+ mov $r8 0x83c
+ shl b32 $r8 6
+ clear b32 $r9
+ bset $r9 $1
+ iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7]
+')
+
+define(`trace_clr', `
+ mov $r8 0x85c
+ shl b32 $r8 6
+ clear b32 $r9
+ bset $r9 $1
+ iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7]
+')
+
+// queue_put - add request to queue
+//
+// In : $r13 queue pointer
+// $r14 command
+// $r15 data
+//
+queue_put:
+ // make sure we have space..
+ ld b32 $r8 D[$r13 + 0x0] // GET
+ ld b32 $r9 D[$r13 + 0x4] // PUT
+ xor $r8 8
+ cmpu b32 $r8 $r9
+ bra ne queue_put_next
+ mov $r15 E_CMD_OVERFLOW
+ call error
+ ret
+
+ // store cmd/data on queue
+ queue_put_next:
+ and $r8 $r9 7
+ shl b32 $r8 3
+ add b32 $r8 $r13
+ add b32 $r8 8
+ st b32 D[$r8 + 0x0] $r14
+ st b32 D[$r8 + 0x4] $r15
+
+ // update PUT
+ add b32 $r9 1
+ and $r9 0xf
+ st b32 D[$r13 + 0x4] $r9
+ ret
+
+// queue_get - fetch request from queue
+//
+// In : $r13 queue pointer
+//
+// Out: $p1 clear on success (data available)
+// $r14 command
+// $r15 data
+//
+queue_get:
+ bset $flags $p1
+ ld b32 $r8 D[$r13 + 0x0] // GET
+ ld b32 $r9 D[$r13 + 0x4] // PUT
+ cmpu b32 $r8 $r9
+ bra e queue_get_done
+ // fetch first cmd/data pair
+ and $r9 $r8 7
+ shl b32 $r9 3
+ add b32 $r9 $r13
+ add b32 $r9 8
+ ld b32 $r14 D[$r9 + 0x0]
+ ld b32 $r15 D[$r9 + 0x4]
+
+ // update GET
+ add b32 $r8 1
+ and $r8 0xf
+ st b32 D[$r13 + 0x0] $r8
+ bclr $flags $p1
+queue_get_done:
+ ret
+
+// nv_rd32 - read 32-bit value from nv register
+//
+// In : $r14 register
+// Out: $r15 value
+//
+nv_rd32:
+ mov $r11 0x728
+ shl b32 $r11 6
+ mov b32 $r12 $r14
+ bset $r12 31 // MMIO_CTRL_PENDING
+ iowr I[$r11 + 0x000] $r12 // MMIO_CTRL
+ nv_rd32_wait:
+ iord $r12 I[$r11 + 0x000]
+ xbit $r12 $r12 31
+ bra ne nv_rd32_wait
+ mov $r10 6 // DONE_MMIO_RD
+ call wait_doneo
+ iord $r15 I[$r11 + 0x100] // MMIO_RDVAL
+ ret
+
+// nv_wr32 - write 32-bit value to nv register
+//
+// In : $r14 register
+// $r15 value
+//
+nv_wr32:
+ mov $r11 0x728
+ shl b32 $r11 6
+ iowr I[$r11 + 0x200] $r15 // MMIO_WRVAL
+ mov b32 $r12 $r14
+ bset $r12 31 // MMIO_CTRL_PENDING
+ bset $r12 30 // MMIO_CTRL_WRITE
+ iowr I[$r11 + 0x000] $r12 // MMIO_CTRL
+ nv_wr32_wait:
+ iord $r12 I[$r11 + 0x000]
+ xbit $r12 $r12 31
+ bra ne nv_wr32_wait
+ ret
+
+// (re)set watchdog timer
+//
+// In : $r15 timeout
+//
+watchdog_reset:
+ mov $r8 0x430
+ shl b32 $r8 6
+ bset $r15 31
+ iowr I[$r8 + 0x000] $r15
+ ret
+
+// clear watchdog timer
+watchdog_clear:
+ mov $r8 0x430
+ shl b32 $r8 6
+ iowr I[$r8 + 0x000] $r0
+ ret
+
+// wait_done{z,o} - wait on FUC_DONE bit to become clear/set
+//
+// In : $r10 bit to wait on
+//
+define(`wait_done', `
+$1:
+ trace_set(T_WAIT);
+ mov $r8 0x818
+ shl b32 $r8 6
+ iowr I[$r8 + 0x000] $r10 // CC_SCRATCH[6] = wait bit
+ wait_done_$1:
+ mov $r8 0x400
+ shl b32 $r8 6
+ iord $r8 I[$r8 + 0x000] // DONE
+ xbit $r8 $r8 $r10
+ bra $2 wait_done_$1
+ trace_clr(T_WAIT)
+ ret
+')
+wait_done(wait_donez, ne)
+wait_done(wait_doneo, e)
+
+// mmctx_size - determine size of a mmio list transfer
+//
+// In : $r14 mmio list head
+// $r15 mmio list tail
+// Out: $r15 transfer size (in bytes)
+//
+mmctx_size:
+ clear b32 $r9
+ nv_mmctx_size_loop:
+ ld b32 $r8 D[$r14]
+ shr b32 $r8 26
+ add b32 $r8 1
+ shl b32 $r8 2
+ add b32 $r9 $r8
+ add b32 $r14 4
+ cmpu b32 $r14 $r15
+ bra ne nv_mmctx_size_loop
+ mov b32 $r15 $r9
+ ret
+
+// mmctx_xfer - execute a list of mmio transfers
+//
+// In : $r10 flags
+// bit 0: direction (0 = save, 1 = load)
+// bit 1: set if first transfer
+// bit 2: set if last transfer
+// $r11 base
+// $r12 mmio list head
+// $r13 mmio list tail
+// $r14 multi_stride
+// $r15 multi_mask
+//
+mmctx_xfer:
+ trace_set(T_MMCTX)
+ mov $r8 0x710
+ shl b32 $r8 6
+ clear b32 $r9
+ or $r11 $r11
+ bra e mmctx_base_disabled
+ iowr I[$r8 + 0x000] $r11 // MMCTX_BASE
+ bset $r9 0 // BASE_EN
+ mmctx_base_disabled:
+ or $r14 $r14
+ bra e mmctx_multi_disabled
+ iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE
+ iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK
+ bset $r9 1 // MULTI_EN
+ mmctx_multi_disabled:
+ add b32 $r8 0x100
+
+ xbit $r11 $r10 0
+ shl b32 $r11 16 // DIR
+ bset $r11 12 // QLIMIT = 0x10
+ xbit $r14 $r10 1
+ shl b32 $r14 17
+ or $r11 $r14 // START_TRIGGER
+ iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL
+
+ // loop over the mmio list, and send requests to the hw
+ mmctx_exec_loop:
+ // wait for space in mmctx queue
+ mmctx_wait_free:
+ iord $r14 I[$r8 + 0x000] // MMCTX_CTRL
+ and $r14 0x1f
+ bra e mmctx_wait_free
+
+ // queue up an entry
+ ld b32 $r14 D[$r12]
+ or $r14 $r9
+ iowr I[$r8 + 0x300] $r14
+ add b32 $r12 4
+ cmpu b32 $r12 $r13
+ bra ne mmctx_exec_loop
+
+ xbit $r11 $r10 2
+ bra ne mmctx_stop
+ // wait for queue to empty
+ mmctx_fini_wait:
+ iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
+ and $r11 0x1f
+ cmpu b32 $r11 0x10
+ bra ne mmctx_fini_wait
+ mov $r10 2 // DONE_MMCTX
+ call wait_donez
+ bra mmctx_done
+ mmctx_stop:
+ xbit $r11 $r10 0
+ shl b32 $r11 16 // DIR
+ bset $r11 12 // QLIMIT = 0x10
+ bset $r11 18 // STOP_TRIGGER
+ iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL
+ mmctx_stop_wait:
+ // wait for STOP_TRIGGER to clear
+ iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
+ xbit $r11 $r11 18
+ bra ne mmctx_stop_wait
+ mmctx_done:
+ trace_clr(T_MMCTX)
+ ret
+
+// Wait for DONE_STRAND
+//
+strand_wait:
+ push $r10
+ mov $r10 2
+ call wait_donez
+ pop $r10
+ ret
+
+// unknown - call before issuing strand commands
+//
+strand_pre:
+ mov $r8 0x4afc
+ sethi $r8 0x20000
+ mov $r9 0xc
+ iowr I[$r8] $r9
+ call strand_wait
+ ret
+
+// unknown - call after issuing strand commands
+//
+strand_post:
+ mov $r8 0x4afc
+ sethi $r8 0x20000
+ mov $r9 0xd
+ iowr I[$r8] $r9
+ call strand_wait
+ ret
+
+// Selects strand set?!
+//
+// In: $r14 id
+//
+strand_set:
+ mov $r10 0x4ffc
+ sethi $r10 0x20000
+ sub b32 $r11 $r10 0x500
+ mov $r12 0xf
+ iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf
+ mov $r12 0xb
+ iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb
+ call strand_wait
+ iowr I[$r10 + 0x000] $r14 // 0x93c = <id>
+ mov $r12 0xa
+ iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa
+ call strand_wait
+ ret
+
+// Initialise strand context data
+//
+// In : $r15 context base
+// Out: $r15 context size (in bytes)
+//
+// Strandset(?) 3 hardcoded currently
+//
+strand_ctx_init:
+ trace_set(T_STRINIT)
+ call strand_pre
+ mov $r14 3
+ call strand_set
+ mov $r10 0x46fc
+ sethi $r10 0x20000
+ add b32 $r11 $r10 0x400
+ iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0
+ mov $r12 1
+ iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE
+ call strand_wait
+ sub b32 $r12 $r0 1
+ iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff
+ mov $r12 2
+ iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT
+ call strand_wait
+ call strand_post
+
+ // read the size of each strand, poke the context offset of
+ // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
+ // about it later then.
+ mov $r8 0x880
+ shl b32 $r8 6
+ iord $r9 I[$r8 + 0x000] // STRANDS
+ add b32 $r8 0x2200
+ shr b32 $r14 $r15 8
+ ctx_init_strand_loop:
+ iowr I[$r8 + 0x000] $r14 // STRAND_SAVE_SWBASE
+ iowr I[$r8 + 0x100] $r14 // STRAND_LOAD_SWBASE
+ iord $r10 I[$r8 + 0x200] // STRAND_SIZE
+ shr b32 $r10 6
+ add b32 $r10 1
+ add b32 $r14 $r10
+ add b32 $r8 4
+ sub b32 $r9 1
+ bra ne ctx_init_strand_loop
+
+ shl b32 $r14 8
+ sub b32 $r15 $r14 $r15
+ trace_clr(T_STRINIT)
+ ret
+')
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h
index f5d184e0689d..55689e997286 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.h
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.h
@@ -57,8 +57,7 @@ struct nvc0_graph_priv {
struct nouveau_gpuobj *unk4188b4;
struct nouveau_gpuobj *unk4188b8;
- u8 magic_not_rop_nr;
- u32 magicgpc918;
+ u8 magic_not_rop_nr;
};
struct nvc0_graph_chan {
@@ -72,4 +71,25 @@ struct nvc0_graph_chan {
int nvc0_grctx_generate(struct nouveau_channel *);
+/* nvc0_graph.c uses this also to determine supported chipsets */
+static inline u32
+nvc0_graph_class(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ switch (dev_priv->chipset) {
+ case 0xc0:
+ case 0xc3:
+ case 0xc4:
+ case 0xce: /* guess, mmio trace shows only 0x9097 state */
+ return 0x9097;
+ case 0xc1:
+ return 0x9197;
+ case 0xc8:
+ return 0x9297;
+ default:
+ return 0;
+ }
+}
+
#endif
diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c
index 6df066114133..31018eaf5279 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c
+++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c
@@ -45,6 +45,9 @@ nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data)
static void
nvc0_grctx_generate_9097(struct drm_device *dev)
{
+ u32 fermi = nvc0_graph_class(dev);
+ u32 mthd;
+
nv_mthd(dev, 0x9097, 0x0800, 0x00000000);
nv_mthd(dev, 0x9097, 0x0840, 0x00000000);
nv_mthd(dev, 0x9097, 0x0880, 0x00000000);
@@ -824,134 +827,10 @@ nvc0_grctx_generate_9097(struct drm_device *dev)
nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001);
nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001);
nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001);
- nv_mthd(dev, 0x9097, 0x3400, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3404, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3408, 0x00000000);
- nv_mthd(dev, 0x9097, 0x340c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3410, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3414, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3418, 0x00000000);
- nv_mthd(dev, 0x9097, 0x341c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3420, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3424, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3428, 0x00000000);
- nv_mthd(dev, 0x9097, 0x342c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3430, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3434, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3438, 0x00000000);
- nv_mthd(dev, 0x9097, 0x343c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3440, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3444, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3448, 0x00000000);
- nv_mthd(dev, 0x9097, 0x344c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3450, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3454, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3458, 0x00000000);
- nv_mthd(dev, 0x9097, 0x345c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3460, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3464, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3468, 0x00000000);
- nv_mthd(dev, 0x9097, 0x346c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3470, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3474, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3478, 0x00000000);
- nv_mthd(dev, 0x9097, 0x347c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3480, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3484, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3488, 0x00000000);
- nv_mthd(dev, 0x9097, 0x348c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3490, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3494, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3498, 0x00000000);
- nv_mthd(dev, 0x9097, 0x349c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34a0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34a4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34a8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34ac, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34b0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34b4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34b8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34bc, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34c0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34c4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34c8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34cc, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34d0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34d4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34d8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34dc, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34e0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34e4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34e8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34ec, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34f0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34f4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34f8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x34fc, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3500, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3504, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3508, 0x00000000);
- nv_mthd(dev, 0x9097, 0x350c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3510, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3514, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3518, 0x00000000);
- nv_mthd(dev, 0x9097, 0x351c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3520, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3524, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3528, 0x00000000);
- nv_mthd(dev, 0x9097, 0x352c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3530, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3534, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3538, 0x00000000);
- nv_mthd(dev, 0x9097, 0x353c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3540, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3544, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3548, 0x00000000);
- nv_mthd(dev, 0x9097, 0x354c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3550, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3554, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3558, 0x00000000);
- nv_mthd(dev, 0x9097, 0x355c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3560, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3564, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3568, 0x00000000);
- nv_mthd(dev, 0x9097, 0x356c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3570, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3574, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3578, 0x00000000);
- nv_mthd(dev, 0x9097, 0x357c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3580, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3584, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3588, 0x00000000);
- nv_mthd(dev, 0x9097, 0x358c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3590, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3594, 0x00000000);
- nv_mthd(dev, 0x9097, 0x3598, 0x00000000);
- nv_mthd(dev, 0x9097, 0x359c, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35a0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35a4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35a8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35ac, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35b0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35b4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35b8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35bc, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35c0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35c4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35c8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35cc, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35d0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35d4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35d8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35dc, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35e0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35e4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35e8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35ec, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35f0, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35f4, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35f8, 0x00000000);
- nv_mthd(dev, 0x9097, 0x35fc, 0x00000000);
+ if (fermi == 0x9097) {
+ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+ nv_mthd(dev, 0x9097, mthd, 0x00000000);
+ }
nv_mthd(dev, 0x9097, 0x030c, 0x00000001);
nv_mthd(dev, 0x9097, 0x1944, 0x00000000);
nv_mthd(dev, 0x9097, 0x1514, 0x00000000);
@@ -1321,6 +1200,37 @@ nvc0_grctx_generate_9097(struct drm_device *dev)
}
static void
+nvc0_grctx_generate_9197(struct drm_device *dev)
+{
+ u32 fermi = nvc0_graph_class(dev);
+ u32 mthd;
+
+ if (fermi == 0x9197) {
+ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+ nv_mthd(dev, 0x9197, mthd, 0x00000000);
+ }
+ nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001);
+}
+
+static void
+nvc0_grctx_generate_9297(struct drm_device *dev)
+{
+ u32 fermi = nvc0_graph_class(dev);
+ u32 mthd;
+
+ if (fermi == 0x9297) {
+ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+ nv_mthd(dev, 0x9297, mthd, 0x00000000);
+ }
+ nv_mthd(dev, 0x9297, 0x036c, 0x00000000);
+ nv_mthd(dev, 0x9297, 0x0370, 0x00000000);
+ nv_mthd(dev, 0x9297, 0x07a4, 0x00000000);
+ nv_mthd(dev, 0x9297, 0x07a8, 0x00000000);
+ nv_mthd(dev, 0x9297, 0x0374, 0x00000000);
+ nv_mthd(dev, 0x9297, 0x0378, 0x00000020);
+}
+
+static void
nvc0_grctx_generate_902d(struct drm_device *dev)
{
nv_mthd(dev, 0x902d, 0x0200, 0x000000cf);
@@ -1559,8 +1469,15 @@ nvc0_grctx_generate_unk47xx(struct drm_device *dev)
static void
nvc0_grctx_generate_shaders(struct drm_device *dev)
{
- nv_wr32(dev, 0x405800, 0x078000bf);
- nv_wr32(dev, 0x405830, 0x02180000);
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ if (dev_priv->chipset != 0xc1) {
+ nv_wr32(dev, 0x405800, 0x078000bf);
+ nv_wr32(dev, 0x405830, 0x02180000);
+ } else {
+ nv_wr32(dev, 0x405800, 0x0f8000bf);
+ nv_wr32(dev, 0x405830, 0x02180218);
+ }
nv_wr32(dev, 0x405834, 0x00000000);
nv_wr32(dev, 0x405838, 0x00000000);
nv_wr32(dev, 0x405854, 0x00000000);
@@ -1586,10 +1503,16 @@ nvc0_grctx_generate_unk60xx(struct drm_device *dev)
static void
nvc0_grctx_generate_unk64xx(struct drm_device *dev)
{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
nv_wr32(dev, 0x4064a8, 0x00000000);
nv_wr32(dev, 0x4064ac, 0x00003fff);
nv_wr32(dev, 0x4064b4, 0x00000000);
nv_wr32(dev, 0x4064b8, 0x00000000);
+ if (dev_priv->chipset == 0xc1) {
+ nv_wr32(dev, 0x4064c0, 0x80140078);
+ nv_wr32(dev, 0x4064c4, 0x0086ffff);
+ }
}
static void
@@ -1622,21 +1545,14 @@ static void
nvc0_grctx_generate_rop(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int chipset = dev_priv->chipset;
/* ROPC_BROADCAST */
nv_wr32(dev, 0x408800, 0x02802a3c);
nv_wr32(dev, 0x408804, 0x00000040);
- nv_wr32(dev, 0x408808, 0x0003e00d);
- switch (dev_priv->chipset) {
- case 0xc0:
- nv_wr32(dev, 0x408900, 0x0080b801);
- break;
- case 0xc3:
- case 0xc4:
- nv_wr32(dev, 0x408900, 0x3080b801);
- break;
- }
- nv_wr32(dev, 0x408904, 0x02000001);
+ nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005);
+ nv_wr32(dev, 0x408900, 0x3080b801);
+ nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001);
nv_wr32(dev, 0x408908, 0x00c80929);
nv_wr32(dev, 0x40890c, 0x00000000);
nv_wr32(dev, 0x408980, 0x0000011d);
@@ -1645,6 +1561,8 @@ nvc0_grctx_generate_rop(struct drm_device *dev)
static void
nvc0_grctx_generate_gpc(struct drm_device *dev)
{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int chipset = dev_priv->chipset;
int i;
/* GPC_BROADCAST */
@@ -1676,7 +1594,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
nv_wr32(dev, 0x41880c, 0x00000000);
nv_wr32(dev, 0x418810, 0x00000000);
nv_wr32(dev, 0x418828, 0x00008442);
- nv_wr32(dev, 0x418830, 0x00000001);
+ nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001);
nv_wr32(dev, 0x4188d8, 0x00000008);
nv_wr32(dev, 0x4188e0, 0x01000000);
nv_wr32(dev, 0x4188e8, 0x00000000);
@@ -1684,7 +1602,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
nv_wr32(dev, 0x4188f0, 0x00000000);
nv_wr32(dev, 0x4188f4, 0x00000000);
nv_wr32(dev, 0x4188f8, 0x00000000);
- nv_wr32(dev, 0x4188fc, 0x00100000);
+ nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018);
nv_wr32(dev, 0x41891c, 0x00ff00ff);
nv_wr32(dev, 0x418924, 0x00000000);
nv_wr32(dev, 0x418928, 0x00ffff00);
@@ -1715,6 +1633,8 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
nv_wr32(dev, 0x418c24, 0x00000000);
nv_wr32(dev, 0x418c28, 0x00000000);
nv_wr32(dev, 0x418c2c, 0x00000000);
+ if (chipset == 0xc1)
+ nv_wr32(dev, 0x418c6c, 0x00000001);
nv_wr32(dev, 0x418c80, 0x20200004);
nv_wr32(dev, 0x418c8c, 0x00000001);
nv_wr32(dev, 0x419000, 0x00000780);
@@ -1727,10 +1647,13 @@ static void
nvc0_grctx_generate_tp(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int chipset = dev_priv->chipset;
/* GPC_BROADCAST.TP_BROADCAST */
+ nv_wr32(dev, 0x419818, 0x00000000);
+ nv_wr32(dev, 0x41983c, 0x00038bc7);
nv_wr32(dev, 0x419848, 0x00000000);
- nv_wr32(dev, 0x419864, 0x0000012a);
+ nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129);
nv_wr32(dev, 0x419888, 0x00000000);
nv_wr32(dev, 0x419a00, 0x000001f0);
nv_wr32(dev, 0x419a04, 0x00000001);
@@ -1740,8 +1663,8 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
nv_wr32(dev, 0x419a14, 0x00000200);
nv_wr32(dev, 0x419a1c, 0x00000000);
nv_wr32(dev, 0x419a20, 0x00000800);
- if (dev_priv->chipset != 0xc0)
- nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */
+ if (chipset != 0xc0 && chipset != 0xc8)
+ nv_wr32(dev, 0x00419ac4, 0x0007f440);
nv_wr32(dev, 0x419b00, 0x0a418820);
nv_wr32(dev, 0x419b04, 0x062080e6);
nv_wr32(dev, 0x419b08, 0x020398a4);
@@ -1749,17 +1672,19 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
nv_wr32(dev, 0x419b10, 0x0a418820);
nv_wr32(dev, 0x419b14, 0x000000e6);
nv_wr32(dev, 0x419bd0, 0x00900103);
- nv_wr32(dev, 0x419be0, 0x00000001);
+ nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001);
nv_wr32(dev, 0x419be4, 0x00000000);
nv_wr32(dev, 0x419c00, 0x00000002);
nv_wr32(dev, 0x419c04, 0x00000006);
nv_wr32(dev, 0x419c08, 0x00000002);
nv_wr32(dev, 0x419c20, 0x00000000);
- nv_wr32(dev, 0x419cbc, 0x28137606);
+ nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048
nv_wr32(dev, 0x419ce8, 0x00000000);
nv_wr32(dev, 0x419cf4, 0x00000183);
- nv_wr32(dev, 0x419d20, 0x02180000);
+ nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000);
nv_wr32(dev, 0x419d24, 0x00001fff);
+ if (chipset == 0xc1)
+ nv_wr32(dev, 0x419d44, 0x02180218);
nv_wr32(dev, 0x419e04, 0x00000000);
nv_wr32(dev, 0x419e08, 0x00000000);
nv_wr32(dev, 0x419e0c, 0x00000000);
@@ -1785,11 +1710,11 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
nv_wr32(dev, 0x419e8c, 0x00000000);
nv_wr32(dev, 0x419e90, 0x00000000);
nv_wr32(dev, 0x419e98, 0x00000000);
- if (dev_priv->chipset != 0xc0)
+ if (chipset != 0xc0 && chipset != 0xc8)
nv_wr32(dev, 0x419ee0, 0x00011110);
nv_wr32(dev, 0x419f50, 0x00000000);
nv_wr32(dev, 0x419f54, 0x00000000);
- if (dev_priv->chipset != 0xc0)
+ if (chipset != 0xc0 && chipset != 0xc8)
nv_wr32(dev, 0x419f58, 0x00000000);
}
@@ -1801,6 +1726,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
struct drm_device *dev = chan->dev;
int i, gpc, tp, id;
+ u32 fermi = nvc0_graph_class(dev);
u32 r000260, tmp;
r000260 = nv_rd32(dev, 0x000260);
@@ -1857,10 +1783,11 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
nv_wr32(dev, 0x40587c, 0x00000000);
if (1) {
- const u8 chipset_tp_max[] = { 16, 0, 0, 4, 8 };
+ 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[32];
+ u8 data[TP_MAX];
memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
memset(data, 0x1f, sizeof(data));
@@ -2633,6 +2560,8 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
nv_icmd(dev, 0x0000053f, 0xffff0000);
nv_icmd(dev, 0x00000585, 0x0000003f);
nv_icmd(dev, 0x00000576, 0x00000003);
+ if (dev_priv->chipset == 0xc1)
+ nv_icmd(dev, 0x0000057b, 0x00000059);
nv_icmd(dev, 0x00000586, 0x00000040);
nv_icmd(dev, 0x00000582, 0x00000080);
nv_icmd(dev, 0x00000583, 0x00000080);
@@ -2865,6 +2794,10 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
nv_wr32(dev, 0x404154, 0x00000400);
nvc0_grctx_generate_9097(dev);
+ if (fermi >= 0x9197)
+ nvc0_grctx_generate_9197(dev);
+ if (fermi >= 0x9297)
+ nvc0_grctx_generate_9297(dev);
nvc0_grctx_generate_902d(dev);
nvc0_grctx_generate_9039(dev);
nvc0_grctx_generate_90c0(dev);
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
new file mode 100644
index 000000000000..0ec2add72a76
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
@@ -0,0 +1,474 @@
+/* fuc microcode for nvc0 PGRAPH/GPC
+ *
+ * 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
+ */
+
+/* To build:
+ * m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h
+ */
+
+/* TODO
+ * - bracket certain functions with scratch writes, useful for debugging
+ * - watchdog timer around ctx operations
+ */
+
+.section nvc0_grgpc_data
+include(`nvc0_graph.fuc')
+gpc_id: .b32 0
+gpc_mmio_list_head: .b32 0
+gpc_mmio_list_tail: .b32 0
+
+tpc_count: .b32 0
+tpc_mask: .b32 0
+tpc_mmio_list_head: .b32 0
+tpc_mmio_list_tail: .b32 0
+
+cmd_queue: queue_init
+
+// chipset descriptions
+chipsets:
+.b8 0xc0 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc0_tpc_mmio_tail
+.b8 0xc1 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc1_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc1_tpc_mmio_tail
+.b8 0xc3 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8 0xc4 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8 0xc8 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc0_tpc_mmio_tail
+.b8 0xce 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8 0 0 0 0
+
+// GPC mmio lists
+nvc0_gpc_mmio_head:
+mmctx_data(0x000380, 1)
+mmctx_data(0x000400, 6)
+mmctx_data(0x000450, 9)
+mmctx_data(0x000600, 1)
+mmctx_data(0x000684, 1)
+mmctx_data(0x000700, 5)
+mmctx_data(0x000800, 1)
+mmctx_data(0x000808, 3)
+mmctx_data(0x000828, 1)
+mmctx_data(0x000830, 1)
+mmctx_data(0x0008d8, 1)
+mmctx_data(0x0008e0, 1)
+mmctx_data(0x0008e8, 6)
+mmctx_data(0x00091c, 1)
+mmctx_data(0x000924, 3)
+mmctx_data(0x000b00, 1)
+mmctx_data(0x000b08, 6)
+mmctx_data(0x000bb8, 1)
+mmctx_data(0x000c08, 1)
+mmctx_data(0x000c10, 8)
+mmctx_data(0x000c80, 1)
+mmctx_data(0x000c8c, 1)
+mmctx_data(0x001000, 3)
+mmctx_data(0x001014, 1)
+nvc0_gpc_mmio_tail:
+mmctx_data(0x000c6c, 1);
+nvc1_gpc_mmio_tail:
+
+// TPC mmio lists
+nvc0_tpc_mmio_head:
+mmctx_data(0x000018, 1)
+mmctx_data(0x00003c, 1)
+mmctx_data(0x000048, 1)
+mmctx_data(0x000064, 1)
+mmctx_data(0x000088, 1)
+mmctx_data(0x000200, 6)
+mmctx_data(0x00021c, 2)
+mmctx_data(0x000300, 6)
+mmctx_data(0x0003d0, 1)
+mmctx_data(0x0003e0, 2)
+mmctx_data(0x000400, 3)
+mmctx_data(0x000420, 1)
+mmctx_data(0x0004b0, 1)
+mmctx_data(0x0004e8, 1)
+mmctx_data(0x0004f4, 1)
+mmctx_data(0x000520, 2)
+mmctx_data(0x000604, 4)
+mmctx_data(0x000644, 20)
+mmctx_data(0x000698, 1)
+mmctx_data(0x000750, 2)
+nvc0_tpc_mmio_tail:
+mmctx_data(0x000758, 1)
+mmctx_data(0x0002c4, 1)
+mmctx_data(0x0004bc, 1)
+mmctx_data(0x0006e0, 1)
+nvc3_tpc_mmio_tail:
+mmctx_data(0x000544, 1)
+nvc1_tpc_mmio_tail:
+
+
+.section nvc0_grgpc_code
+bra init
+define(`include_code')
+include(`nvc0_graph.fuc')
+
+// reports an exception to the host
+//
+// In: $r15 error code (see nvc0_graph.fuc)
+//
+error:
+ push $r14
+ mov $r14 -0x67ec // 0x9814
+ sethi $r14 0x400000
+ call nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code
+ add b32 $r14 0x41c
+ mov $r15 1
+ call nv_wr32 // HUB_CTXCTL_INTR_UP_SET
+ pop $r14
+ ret
+
+// GPC fuc initialisation, executed by triggering ucode start, will
+// fall through to main loop after completion.
+//
+// Input:
+// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
+// CC_SCRATCH[1]: context base
+//
+// Output:
+// CC_SCRATCH[0]:
+// 31:31: set to signal completion
+// CC_SCRATCH[1]:
+// 31:0: GPC context size
+//
+init:
+ clear b32 $r0
+ mov $sp $r0
+
+ // enable fifo access
+ mov $r1 0x1200
+ mov $r2 2
+ iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
+
+ // setup i0 handler, and route all interrupts to it
+ mov $r1 ih
+ mov $iv0 $r1
+ mov $r1 0x400
+ iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
+
+ // enable fifo interrupt
+ mov $r2 4
+ iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
+
+ // enable interrupts
+ bset $flags ie0
+
+ // figure out which GPC we are, and how many TPCs we have
+ mov $r1 0x608
+ shl b32 $r1 6
+ iord $r2 I[$r1 + 0x000] // UNITS
+ mov $r3 1
+ and $r2 0x1f
+ shl b32 $r3 $r2
+ sub b32 $r3 1
+ st b32 D[$r0 + tpc_count] $r2
+ st b32 D[$r0 + tpc_mask] $r3
+ add b32 $r1 0x400
+ iord $r2 I[$r1 + 0x000] // MYINDEX
+ st b32 D[$r0 + gpc_id] $r2
+
+ // find context data for this chipset
+ mov $r2 0x800
+ shl b32 $r2 6
+ iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0]
+ mov $r1 chipsets - 12
+ init_find_chipset:
+ add b32 $r1 12
+ ld b32 $r3 D[$r1 + 0x00]
+ cmpu b32 $r3 $r2
+ bra e init_context
+ cmpu b32 $r3 0
+ bra ne init_find_chipset
+ // unknown chipset
+ ret
+
+ // initialise context base, and size tracking
+ init_context:
+ mov $r2 0x800
+ shl b32 $r2 6
+ iord $r2 I[$r2 + 0x100] // CC_SCRATCH[1], initial base
+ clear b32 $r3 // track GPC context size here
+
+ // set mmctx base addresses now so we don't have to do it later,
+ // they don't currently ever change
+ mov $r4 0x700
+ shl b32 $r4 6
+ shr b32 $r5 $r2 8
+ iowr I[$r4 + 0x000] $r5 // MMCTX_SAVE_SWBASE
+ iowr I[$r4 + 0x100] $r5 // MMCTX_LOAD_SWBASE
+
+ // calculate GPC mmio context size, store the chipset-specific
+ // mmio list pointers somewhere we can get at them later without
+ // re-parsing the chipset list
+ clear b32 $r14
+ clear b32 $r15
+ ld b16 $r14 D[$r1 + 4]
+ ld b16 $r15 D[$r1 + 6]
+ st b16 D[$r0 + gpc_mmio_list_head] $r14
+ st b16 D[$r0 + gpc_mmio_list_tail] $r15
+ call mmctx_size
+ add b32 $r2 $r15
+ add b32 $r3 $r15
+
+ // calculate per-TPC mmio context size, store the list pointers
+ ld b16 $r14 D[$r1 + 8]
+ ld b16 $r15 D[$r1 + 10]
+ st b16 D[$r0 + tpc_mmio_list_head] $r14
+ st b16 D[$r0 + tpc_mmio_list_tail] $r15
+ call mmctx_size
+ ld b32 $r14 D[$r0 + tpc_count]
+ mulu $r14 $r15
+ add b32 $r2 $r14
+ add b32 $r3 $r14
+
+ // round up base/size to 256 byte boundary (for strand SWBASE)
+ add b32 $r4 0x1300
+ shr b32 $r3 2
+ iowr I[$r4 + 0x000] $r3 // MMCTX_LOAD_COUNT, wtf for?!?
+ shr b32 $r2 8
+ shr b32 $r3 6
+ add b32 $r2 1
+ add b32 $r3 1
+ shl b32 $r2 8
+ shl b32 $r3 8
+
+ // calculate size of strand context data
+ mov b32 $r15 $r2
+ call strand_ctx_init
+ add b32 $r3 $r15
+
+ // save context size, and tell HUB we're done
+ mov $r1 0x800
+ shl b32 $r1 6
+ iowr I[$r1 + 0x100] $r3 // CC_SCRATCH[1] = context size
+ add b32 $r1 0x800
+ clear b32 $r2
+ bset $r2 31
+ iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000
+
+// Main program loop, very simple, sleeps until woken up by the interrupt
+// handler, pulls a command from the queue and executes its handler
+//
+main:
+ bset $flags $p0
+ sleep $p0
+ mov $r13 cmd_queue
+ call queue_get
+ bra $p1 main
+
+ // 0x0000-0x0003 are all context transfers
+ cmpu b32 $r14 0x04
+ bra nc main_not_ctx_xfer
+ // fetch $flags and mask off $p1/$p2
+ mov $r1 $flags
+ mov $r2 0x0006
+ not b32 $r2
+ and $r1 $r2
+ // set $p1/$p2 according to transfer type
+ shl b32 $r14 1
+ or $r1 $r14
+ mov $flags $r1
+ // transfer context data
+ call ctx_xfer
+ bra main
+
+ main_not_ctx_xfer:
+ shl b32 $r15 $r14 16
+ or $r15 E_BAD_COMMAND
+ call error
+ bra main
+
+// interrupt handler
+ih:
+ push $r8
+ mov $r8 $flags
+ push $r8
+ push $r9
+ push $r10
+ push $r11
+ push $r13
+ push $r14
+ push $r15
+
+ // incoming fifo command?
+ iord $r10 I[$r0 + 0x200] // INTR
+ and $r11 $r10 0x00000004
+ bra e ih_no_fifo
+ // queue incoming fifo command for later processing
+ mov $r11 0x1900
+ mov $r13 cmd_queue
+ iord $r14 I[$r11 + 0x100] // FIFO_CMD
+ iord $r15 I[$r11 + 0x000] // FIFO_DATA
+ call queue_put
+ add b32 $r11 0x400
+ mov $r14 1
+ iowr I[$r11 + 0x000] $r14 // FIFO_ACK
+
+ // ack, and wake up main()
+ ih_no_fifo:
+ iowr I[$r0 + 0x100] $r10 // INTR_ACK
+
+ pop $r15
+ pop $r14
+ pop $r13
+ pop $r11
+ pop $r10
+ pop $r9
+ pop $r8
+ mov $flags $r8
+ pop $r8
+ bclr $flags $p0
+ iret
+
+// Set this GPC's bit in HUB_BAR, used to signal completion of various
+// activities to the HUB fuc
+//
+hub_barrier_done:
+ mov $r15 1
+ ld b32 $r14 D[$r0 + gpc_id]
+ shl b32 $r15 $r14
+ mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET
+ sethi $r14 0x400000
+ call nv_wr32
+ ret
+
+// Disables various things, waits a bit, and re-enables them..
+//
+// Not sure how exactly this helps, perhaps "ENABLE" is not such a
+// good description for the bits we turn off? Anyways, without this,
+// funny things happen.
+//
+ctx_redswitch:
+ mov $r14 0x614
+ shl b32 $r14 6
+ mov $r15 0x020
+ iowr I[$r14] $r15 // GPC_RED_SWITCH = POWER
+ mov $r15 8
+ ctx_redswitch_delay:
+ sub b32 $r15 1
+ bra ne ctx_redswitch_delay
+ mov $r15 0xa20
+ iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER
+ ret
+
+// Transfer GPC context data between GPU and storage area
+//
+// In: $r15 context base address
+// $p1 clear on save, set on load
+// $p2 set if opposite direction done/will be done, so:
+// on save it means: "a load will follow this save"
+// on load it means: "a save preceeded this load"
+//
+ctx_xfer:
+ // set context base address
+ mov $r1 0xa04
+ shl b32 $r1 6
+ iowr I[$r1 + 0x000] $r15// MEM_BASE
+ bra not $p1 ctx_xfer_not_load
+ call ctx_redswitch
+ ctx_xfer_not_load:
+
+ // strands
+ mov $r1 0x4afc
+ sethi $r1 0x20000
+ mov $r2 0xc
+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c
+ call strand_wait
+ mov $r2 0x47fc
+ sethi $r2 0x20000
+ iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00
+ xbit $r2 $flags $p1
+ add b32 $r2 3
+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+
+ // mmio context
+ xbit $r10 $flags $p1 // direction
+ or $r10 2 // first
+ mov $r11 0x0000
+ sethi $r11 0x500000
+ ld b32 $r12 D[$r0 + gpc_id]
+ shl b32 $r12 15
+ add b32 $r11 $r12 // base = NV_PGRAPH_GPCn
+ ld b32 $r12 D[$r0 + gpc_mmio_list_head]
+ ld b32 $r13 D[$r0 + gpc_mmio_list_tail]
+ mov $r14 0 // not multi
+ call mmctx_xfer
+
+ // per-TPC mmio context
+ xbit $r10 $flags $p1 // direction
+ or $r10 4 // last
+ mov $r11 0x4000
+ sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0
+ ld b32 $r12 D[$r0 + gpc_id]
+ shl b32 $r12 15
+ add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0
+ ld b32 $r12 D[$r0 + tpc_mmio_list_head]
+ ld b32 $r13 D[$r0 + tpc_mmio_list_tail]
+ ld b32 $r15 D[$r0 + tpc_mask]
+ mov $r14 0x800 // stride = 0x800
+ call mmctx_xfer
+
+ // wait for strands to finish
+ call strand_wait
+
+ // if load, or a save without a load following, do some
+ // unknown stuff that's done after finishing a block of
+ // strand commands
+ bra $p1 ctx_xfer_post
+ bra not $p2 ctx_xfer_done
+ ctx_xfer_post:
+ mov $r1 0x4afc
+ sethi $r1 0x20000
+ mov $r2 0xd
+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d
+ call strand_wait
+
+ // mark completion in HUB's barrier
+ ctx_xfer_done:
+ call hub_barrier_done
+ ret
+
+.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
new file mode 100644
index 000000000000..1896c898f5ba
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
@@ -0,0 +1,483 @@
+uint32_t nvc0_grgpc_data[] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x000000c0,
+ 0x011000b0,
+ 0x01640114,
+ 0x000000c1,
+ 0x011400b0,
+ 0x01780114,
+ 0x000000c3,
+ 0x011000b0,
+ 0x01740114,
+ 0x000000c4,
+ 0x011000b0,
+ 0x01740114,
+ 0x000000c8,
+ 0x011000b0,
+ 0x01640114,
+ 0x000000ce,
+ 0x011000b0,
+ 0x01740114,
+ 0x00000000,
+ 0x00000380,
+ 0x14000400,
+ 0x20000450,
+ 0x00000600,
+ 0x00000684,
+ 0x10000700,
+ 0x00000800,
+ 0x08000808,
+ 0x00000828,
+ 0x00000830,
+ 0x000008d8,
+ 0x000008e0,
+ 0x140008e8,
+ 0x0000091c,
+ 0x08000924,
+ 0x00000b00,
+ 0x14000b08,
+ 0x00000bb8,
+ 0x00000c08,
+ 0x1c000c10,
+ 0x00000c80,
+ 0x00000c8c,
+ 0x08001000,
+ 0x00001014,
+ 0x00000c6c,
+ 0x00000018,
+ 0x0000003c,
+ 0x00000048,
+ 0x00000064,
+ 0x00000088,
+ 0x14000200,
+ 0x0400021c,
+ 0x14000300,
+ 0x000003d0,
+ 0x040003e0,
+ 0x08000400,
+ 0x00000420,
+ 0x000004b0,
+ 0x000004e8,
+ 0x000004f4,
+ 0x04000520,
+ 0x0c000604,
+ 0x4c000644,
+ 0x00000698,
+ 0x04000750,
+ 0x00000758,
+ 0x000002c4,
+ 0x000004bc,
+ 0x000006e0,
+ 0x00000544,
+};
+
+uint32_t nvc0_grgpc_code[] = {
+ 0x03060ef5,
+ 0x9800d898,
+ 0x86f001d9,
+ 0x0489b808,
+ 0xf00c1bf4,
+ 0x21f502f7,
+ 0x00f802ec,
+ 0xb60798c4,
+ 0x8dbb0384,
+ 0x0880b600,
+ 0x80008e80,
+ 0x90b6018f,
+ 0x0f94f001,
+ 0xf801d980,
+ 0x0131f400,
+ 0x9800d898,
+ 0x89b801d9,
+ 0x210bf404,
+ 0xb60789c4,
+ 0x9dbb0394,
+ 0x0890b600,
+ 0x98009e98,
+ 0x80b6019f,
+ 0x0f84f001,
+ 0xf400d880,
+ 0x00f80132,
+ 0x0728b7f1,
+ 0xb906b4b6,
+ 0xc9f002ec,
+ 0x00bcd01f,
+ 0xc800bccf,
+ 0x1bf41fcc,
+ 0x06a7f0fa,
+ 0x010321f5,
+ 0xf840bfcf,
+ 0x28b7f100,
+ 0x06b4b607,
+ 0xb980bfd0,
+ 0xc9f002ec,
+ 0x1ec9f01f,
+ 0xcf00bcd0,
+ 0xccc800bc,
+ 0xfa1bf41f,
+ 0x87f100f8,
+ 0x84b60430,
+ 0x1ff9f006,
+ 0xf8008fd0,
+ 0x3087f100,
+ 0x0684b604,
+ 0xf80080d0,
+ 0x3c87f100,
+ 0x0684b608,
+ 0x99f094bd,
+ 0x0089d000,
+ 0x081887f1,
+ 0xd00684b6,
+ 0x87f1008a,
+ 0x84b60400,
+ 0x0088cf06,
+ 0xf4888aff,
+ 0x87f1f31b,
+ 0x84b6085c,
+ 0xf094bd06,
+ 0x89d00099,
+ 0xf100f800,
+ 0xb6083c87,
+ 0x94bd0684,
+ 0xd00099f0,
+ 0x87f10089,
+ 0x84b60818,
+ 0x008ad006,
+ 0x040087f1,
+ 0xcf0684b6,
+ 0x8aff0088,
+ 0xf30bf488,
+ 0x085c87f1,
+ 0xbd0684b6,
+ 0x0099f094,
+ 0xf80089d0,
+ 0x9894bd00,
+ 0x85b600e8,
+ 0x0180b61a,
+ 0xbb0284b6,
+ 0xe0b60098,
+ 0x04efb804,
+ 0xb9eb1bf4,
+ 0x00f8029f,
+ 0x083c87f1,
+ 0xbd0684b6,
+ 0x0199f094,
+ 0xf10089d0,
+ 0xb6071087,
+ 0x94bd0684,
+ 0xf405bbfd,
+ 0x8bd0090b,
+ 0x0099f000,
+ 0xf405eefd,
+ 0x8ed00c0b,
+ 0xc08fd080,
+ 0xb70199f0,
+ 0xc8010080,
+ 0xb4b600ab,
+ 0x0cb9f010,
+ 0xb601aec8,
+ 0xbefd11e4,
+ 0x008bd005,
+ 0xf0008ecf,
+ 0x0bf41fe4,
+ 0x00ce98fa,
+ 0xd005e9fd,
+ 0xc0b6c08e,
+ 0x04cdb804,
+ 0xc8e81bf4,
+ 0x1bf402ab,
+ 0x008bcf18,
+ 0xb01fb4f0,
+ 0x1bf410b4,
+ 0x02a7f0f7,
+ 0xf4c921f4,
+ 0xabc81b0e,
+ 0x10b4b600,
+ 0xf00cb9f0,
+ 0x8bd012b9,
+ 0x008bcf00,
+ 0xf412bbc8,
+ 0x87f1fa1b,
+ 0x84b6085c,
+ 0xf094bd06,
+ 0x89d00199,
+ 0xf900f800,
+ 0x02a7f0a0,
+ 0xfcc921f4,
+ 0xf100f8a0,
+ 0xf04afc87,
+ 0x97f00283,
+ 0x0089d00c,
+ 0x020721f5,
+ 0x87f100f8,
+ 0x83f04afc,
+ 0x0d97f002,
+ 0xf50089d0,
+ 0xf8020721,
+ 0xfca7f100,
+ 0x02a3f04f,
+ 0x0500aba2,
+ 0xd00fc7f0,
+ 0xc7f000ac,
+ 0x00bcd00b,
+ 0x020721f5,
+ 0xf000aed0,
+ 0xbcd00ac7,
+ 0x0721f500,
+ 0xf100f802,
+ 0xb6083c87,
+ 0x94bd0684,
+ 0xd00399f0,
+ 0x21f50089,
+ 0xe7f00213,
+ 0x3921f503,
+ 0xfca7f102,
+ 0x02a3f046,
+ 0x0400aba0,
+ 0xf040a0d0,
+ 0xbcd001c7,
+ 0x0721f500,
+ 0x010c9202,
+ 0xf000acd0,
+ 0xbcd002c7,
+ 0x0721f500,
+ 0x2621f502,
+ 0x8087f102,
+ 0x0684b608,
+ 0xb70089cf,
+ 0x95220080,
+ 0x8ed008fe,
+ 0x408ed000,
+ 0xb6808acf,
+ 0xa0b606a5,
+ 0x00eabb01,
+ 0xb60480b6,
+ 0x1bf40192,
+ 0x08e4b6e8,
+ 0xf1f2efbc,
+ 0xb6085c87,
+ 0x94bd0684,
+ 0xd00399f0,
+ 0x00f80089,
+ 0xe7f1e0f9,
+ 0xe3f09814,
+ 0x8d21f440,
+ 0x041ce0b7,
+ 0xf401f7f0,
+ 0xe0fc8d21,
+ 0x04bd00f8,
+ 0xf10004fe,
+ 0xf0120017,
+ 0x12d00227,
+ 0x3e17f100,
+ 0x0010fe04,
+ 0x040017f1,
+ 0xf0c010d0,
+ 0x12d00427,
+ 0x1031f400,
+ 0x060817f1,
+ 0xcf0614b6,
+ 0x37f00012,
+ 0x1f24f001,
+ 0xb60432bb,
+ 0x02800132,
+ 0x04038003,
+ 0x040010b7,
+ 0x800012cf,
+ 0x27f10002,
+ 0x24b60800,
+ 0x0022cf06,
+ 0xb65817f0,
+ 0x13980c10,
+ 0x0432b800,
+ 0xb00b0bf4,
+ 0x1bf40034,
+ 0xf100f8f1,
+ 0xb6080027,
+ 0x22cf0624,
+ 0xf134bd40,
+ 0xb6070047,
+ 0x25950644,
+ 0x0045d008,
+ 0xbd4045d0,
+ 0x58f4bde4,
+ 0x1f58021e,
+ 0x020e4003,
+ 0xf5040f40,
+ 0xbb013d21,
+ 0x3fbb002f,
+ 0x041e5800,
+ 0x40051f58,
+ 0x0f400a0e,
+ 0x3d21f50c,
+ 0x030e9801,
+ 0xbb00effd,
+ 0x3ebb002e,
+ 0x0040b700,
+ 0x0235b613,
+ 0xb60043d0,
+ 0x35b60825,
+ 0x0120b606,
+ 0xb60130b6,
+ 0x34b60824,
+ 0x022fb908,
+ 0x026321f5,
+ 0xf1003fbb,
+ 0xb6080017,
+ 0x13d00614,
+ 0x0010b740,
+ 0xf024bd08,
+ 0x12d01f29,
+ 0x0031f400,
+ 0xf00028f4,
+ 0x21f41cd7,
+ 0xf401f439,
+ 0xf404e4b0,
+ 0x81fe1e18,
+ 0x0627f001,
+ 0x12fd20bd,
+ 0x01e4b604,
+ 0xfe051efd,
+ 0x21f50018,
+ 0x0ef404c3,
+ 0x10ef94d3,
+ 0xf501f5f0,
+ 0xf402ec21,
+ 0x80f9c60e,
+ 0xf90188fe,
+ 0xf990f980,
+ 0xf9b0f9a0,
+ 0xf9e0f9d0,
+ 0x800acff0,
+ 0xf404abc4,
+ 0xb7f11d0b,
+ 0xd7f01900,
+ 0x40becf1c,
+ 0xf400bfcf,
+ 0xb0b70421,
+ 0xe7f00400,
+ 0x00bed001,
+ 0xfc400ad0,
+ 0xfce0fcf0,
+ 0xfcb0fcd0,
+ 0xfc90fca0,
+ 0x0088fe80,
+ 0x32f480fc,
+ 0xf001f800,
+ 0x0e9801f7,
+ 0x04febb00,
+ 0x9418e7f1,
+ 0xf440e3f0,
+ 0x00f88d21,
+ 0x0614e7f1,
+ 0xf006e4b6,
+ 0xefd020f7,
+ 0x08f7f000,
+ 0xf401f2b6,
+ 0xf7f1fd1b,
+ 0xefd00a20,
+ 0xf100f800,
+ 0xb60a0417,
+ 0x1fd00614,
+ 0x0711f400,
+ 0x04a421f5,
+ 0x4afc17f1,
+ 0xf00213f0,
+ 0x12d00c27,
+ 0x0721f500,
+ 0xfc27f102,
+ 0x0223f047,
+ 0xf00020d0,
+ 0x20b6012c,
+ 0x0012d003,
+ 0xf001acf0,
+ 0xb7f002a5,
+ 0x50b3f000,
+ 0xb6000c98,
+ 0xbcbb0fc4,
+ 0x010c9800,
+ 0xf0020d98,
+ 0x21f500e7,
+ 0xacf0015c,
+ 0x04a5f001,
+ 0x4000b7f1,
+ 0x9850b3f0,
+ 0xc4b6000c,
+ 0x00bcbb0f,
+ 0x98050c98,
+ 0x0f98060d,
+ 0x00e7f104,
+ 0x5c21f508,
+ 0x0721f501,
+ 0x0601f402,
+ 0xf11412f4,
+ 0xf04afc17,
+ 0x27f00213,
+ 0x0012d00d,
+ 0x020721f5,
+ 0x048f21f5,
+ 0x000000f8,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
new file mode 100644
index 000000000000..a1a599124cf4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
@@ -0,0 +1,808 @@
+/* fuc microcode for nvc0 PGRAPH/HUB
+ *
+ * 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
+ */
+
+/* To build:
+ * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h
+ */
+
+.section nvc0_grhub_data
+include(`nvc0_graph.fuc')
+gpc_count: .b32 0
+rop_count: .b32 0
+cmd_queue: queue_init
+hub_mmio_list_head: .b32 0
+hub_mmio_list_tail: .b32 0
+
+ctx_current: .b32 0
+
+chipsets:
+.b8 0xc0 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8 0xc1 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc1_hub_mmio_tail
+.b8 0xc3 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8 0xc4 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8 0xc8 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8 0xce 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8 0 0 0 0
+
+nvc0_hub_mmio_head:
+mmctx_data(0x17e91c, 2)
+mmctx_data(0x400204, 2)
+mmctx_data(0x404004, 11)
+mmctx_data(0x404044, 1)
+mmctx_data(0x404094, 14)
+mmctx_data(0x4040d0, 7)
+mmctx_data(0x4040f8, 1)
+mmctx_data(0x404130, 3)
+mmctx_data(0x404150, 3)
+mmctx_data(0x404164, 2)
+mmctx_data(0x404174, 3)
+mmctx_data(0x404200, 8)
+mmctx_data(0x404404, 14)
+mmctx_data(0x404460, 4)
+mmctx_data(0x404480, 1)
+mmctx_data(0x404498, 1)
+mmctx_data(0x404604, 4)
+mmctx_data(0x404618, 32)
+mmctx_data(0x404698, 21)
+mmctx_data(0x4046f0, 2)
+mmctx_data(0x404700, 22)
+mmctx_data(0x405800, 1)
+mmctx_data(0x405830, 3)
+mmctx_data(0x405854, 1)
+mmctx_data(0x405870, 4)
+mmctx_data(0x405a00, 2)
+mmctx_data(0x405a18, 1)
+mmctx_data(0x406020, 1)
+mmctx_data(0x406028, 4)
+mmctx_data(0x4064a8, 2)
+mmctx_data(0x4064b4, 2)
+mmctx_data(0x407804, 1)
+mmctx_data(0x40780c, 6)
+mmctx_data(0x4078bc, 1)
+mmctx_data(0x408000, 7)
+mmctx_data(0x408064, 1)
+mmctx_data(0x408800, 3)
+mmctx_data(0x408900, 4)
+mmctx_data(0x408980, 1)
+nvc0_hub_mmio_tail:
+mmctx_data(0x4064c0, 2)
+nvc1_hub_mmio_tail:
+
+.align 256
+chan_data:
+chan_mmio_count: .b32 0
+chan_mmio_address: .b32 0
+
+.align 256
+xfer_data: .b32 0
+
+.section nvc0_grhub_code
+bra init
+define(`include_code')
+include(`nvc0_graph.fuc')
+
+// reports an exception to the host
+//
+// In: $r15 error code (see nvc0_graph.fuc)
+//
+error:
+ push $r14
+ mov $r14 0x814
+ shl b32 $r14 6
+ iowr I[$r14 + 0x000] $r15 // CC_SCRATCH[5] = error code
+ mov $r14 0xc1c
+ shl b32 $r14 6
+ mov $r15 1
+ iowr I[$r14 + 0x000] $r15 // INTR_UP_SET
+ pop $r14
+ ret
+
+// HUB fuc initialisation, executed by triggering ucode start, will
+// fall through to main loop after completion.
+//
+// Input:
+// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
+//
+// Output:
+// CC_SCRATCH[0]:
+// 31:31: set to signal completion
+// CC_SCRATCH[1]:
+// 31:0: total PGRAPH context size
+//
+init:
+ clear b32 $r0
+ mov $sp $r0
+ mov $xdbase $r0
+
+ // enable fifo access
+ mov $r1 0x1200
+ mov $r2 2
+ iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
+
+ // setup i0 handler, and route all interrupts to it
+ mov $r1 ih
+ mov $iv0 $r1
+ mov $r1 0x400
+ iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
+
+ // route HUB_CHANNEL_SWITCH to fuc interrupt 8
+ mov $r3 0x404
+ shl b32 $r3 6
+ mov $r2 0x2003 // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
+ iowr I[$r3 + 0x000] $r2
+
+ // not sure what these are, route them because NVIDIA does, and
+ // the IRQ handler will signal the host if we ever get one.. we
+ // may find out if/why we need to handle these if so..
+ //
+ mov $r2 0x2004
+ iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
+ mov $r2 0x200b
+ iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
+ mov $r2 0x200c
+ iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
+
+ // enable all INTR_UP interrupts
+ mov $r2 0xc24
+ shl b32 $r2 6
+ not b32 $r3 $r0
+ iowr I[$r2] $r3
+
+ // enable fifo, ctxsw, 9, 10, 15 interrupts
+ mov $r2 -0x78fc // 0x8704
+ sethi $r2 0
+ iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
+
+ // fifo level triggered, rest edge
+ sub b32 $r1 0x100
+ mov $r2 4
+ iowr I[$r1] $r2
+
+ // enable interrupts
+ bset $flags ie0
+
+ // fetch enabled GPC/ROP counts
+ mov $r14 -0x69fc // 0x409604
+ sethi $r14 0x400000
+ call nv_rd32
+ extr $r1 $r15 16:20
+ st b32 D[$r0 + rop_count] $r1
+ and $r15 0x1f
+ st b32 D[$r0 + gpc_count] $r15
+
+ // set BAR_REQMASK to GPC mask
+ mov $r1 1
+ shl b32 $r1 $r15
+ sub b32 $r1 1
+ mov $r2 0x40c
+ shl b32 $r2 6
+ iowr I[$r2 + 0x000] $r1
+ iowr I[$r2 + 0x100] $r1
+
+ // find context data for this chipset
+ mov $r2 0x800
+ shl b32 $r2 6
+ iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0]
+ mov $r15 chipsets - 8
+ init_find_chipset:
+ add b32 $r15 8
+ ld b32 $r3 D[$r15 + 0x00]
+ cmpu b32 $r3 $r2
+ bra e init_context
+ cmpu b32 $r3 0
+ bra ne init_find_chipset
+ // unknown chipset
+ ret
+
+ // context size calculation, reserve first 256 bytes for use by fuc
+ init_context:
+ mov $r1 256
+
+ // calculate size of mmio context data
+ ld b16 $r14 D[$r15 + 4]
+ ld b16 $r15 D[$r15 + 6]
+ sethi $r14 0
+ st b32 D[$r0 + hub_mmio_list_head] $r14
+ st b32 D[$r0 + hub_mmio_list_tail] $r15
+ call mmctx_size
+
+ // set mmctx base addresses now so we don't have to do it later,
+ // they don't (currently) ever change
+ mov $r3 0x700
+ shl b32 $r3 6
+ shr b32 $r4 $r1 8
+ iowr I[$r3 + 0x000] $r4 // MMCTX_SAVE_SWBASE
+ iowr I[$r3 + 0x100] $r4 // MMCTX_LOAD_SWBASE
+ add b32 $r3 0x1300
+ add b32 $r1 $r15
+ shr b32 $r15 2
+ iowr I[$r3 + 0x000] $r15 // MMCTX_LOAD_COUNT, wtf for?!?
+
+ // strands, base offset needs to be aligned to 256 bytes
+ shr b32 $r1 8
+ add b32 $r1 1
+ shl b32 $r1 8
+ mov b32 $r15 $r1
+ call strand_ctx_init
+ add b32 $r1 $r15
+
+ // initialise each GPC in sequence by passing in the offset of its
+ // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which
+ // has previously been uploaded by the host) running.
+ //
+ // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31
+ // when it has completed, and return the size of its context data
+ // in GPCn_CC_SCRATCH[1]
+ //
+ ld b32 $r3 D[$r0 + gpc_count]
+ mov $r4 0x2000
+ sethi $r4 0x500000
+ init_gpc:
+ // setup, and start GPC ucode running
+ add b32 $r14 $r4 0x804
+ mov b32 $r15 $r1
+ call nv_wr32 // CC_SCRATCH[1] = ctx offset
+ add b32 $r14 $r4 0x800
+ mov b32 $r15 $r2
+ call nv_wr32 // CC_SCRATCH[0] = chipset
+ add b32 $r14 $r4 0x10c
+ clear b32 $r15
+ call nv_wr32
+ add b32 $r14 $r4 0x104
+ call nv_wr32 // ENTRY
+ add b32 $r14 $r4 0x100
+ mov $r15 2 // CTRL_START_TRIGGER
+ call nv_wr32 // CTRL
+
+ // wait for it to complete, and adjust context size
+ add b32 $r14 $r4 0x800
+ init_gpc_wait:
+ call nv_rd32
+ xbit $r15 $r15 31
+ bra e init_gpc_wait
+ add b32 $r14 $r4 0x804
+ call nv_rd32
+ add b32 $r1 $r15
+
+ // next!
+ add b32 $r4 0x8000
+ sub b32 $r3 1
+ bra ne init_gpc
+
+ // save context size, and tell host we're ready
+ mov $r2 0x800
+ shl b32 $r2 6
+ iowr I[$r2 + 0x100] $r1 // CC_SCRATCH[1] = context size
+ add b32 $r2 0x800
+ clear b32 $r1
+ bset $r1 31
+ iowr I[$r2 + 0x000] $r1 // CC_SCRATCH[0] |= 0x80000000
+
+// Main program loop, very simple, sleeps until woken up by the interrupt
+// handler, pulls a command from the queue and executes its handler
+//
+main:
+ // sleep until we have something to do
+ bset $flags $p0
+ sleep $p0
+ mov $r13 cmd_queue
+ call queue_get
+ bra $p1 main
+
+ // context switch, requested by GPU?
+ cmpu b32 $r14 0x4001
+ bra ne main_not_ctx_switch
+ trace_set(T_AUTO)
+ mov $r1 0xb00
+ shl b32 $r1 6
+ iord $r2 I[$r1 + 0x100] // CHAN_NEXT
+ iord $r1 I[$r1 + 0x000] // CHAN_CUR
+
+ xbit $r3 $r1 31
+ bra e chsw_no_prev
+ xbit $r3 $r2 31
+ bra e chsw_prev_no_next
+ push $r2
+ mov b32 $r2 $r1
+ trace_set(T_SAVE)
+ bclr $flags $p1
+ bset $flags $p2
+ call ctx_xfer
+ trace_clr(T_SAVE);
+ pop $r2
+ trace_set(T_LOAD);
+ bset $flags $p1
+ call ctx_xfer
+ trace_clr(T_LOAD);
+ bra chsw_done
+ chsw_prev_no_next:
+ push $r2
+ mov b32 $r2 $r1
+ bclr $flags $p1
+ bclr $flags $p2
+ call ctx_xfer
+ pop $r2
+ mov $r1 0xb00
+ shl b32 $r1 6
+ iowr I[$r1] $r2
+ bra chsw_done
+ chsw_no_prev:
+ xbit $r3 $r2 31
+ bra e chsw_done
+ bset $flags $p1
+ bclr $flags $p2
+ call ctx_xfer
+
+ // ack the context switch request
+ chsw_done:
+ mov $r1 0xb0c
+ shl b32 $r1 6
+ mov $r2 1
+ iowr I[$r1 + 0x000] $r2 // 0x409b0c
+ trace_clr(T_AUTO)
+ bra main
+
+ // request to set current channel? (*not* a context switch)
+ main_not_ctx_switch:
+ cmpu b32 $r14 0x0001
+ bra ne main_not_ctx_chan
+ mov b32 $r2 $r15
+ call ctx_chan
+ bra main_done
+
+ // request to store current channel context?
+ main_not_ctx_chan:
+ cmpu b32 $r14 0x0002
+ bra ne main_not_ctx_save
+ trace_set(T_SAVE)
+ bclr $flags $p1
+ bclr $flags $p2
+ call ctx_xfer
+ trace_clr(T_SAVE)
+ bra main_done
+
+ main_not_ctx_save:
+ shl b32 $r15 $r14 16
+ or $r15 E_BAD_COMMAND
+ call error
+ bra main
+
+ main_done:
+ mov $r1 0x820
+ shl b32 $r1 6
+ clear b32 $r2
+ bset $r2 31
+ iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000
+ bra main
+
+// interrupt handler
+ih:
+ push $r8
+ mov $r8 $flags
+ push $r8
+ push $r9
+ push $r10
+ push $r11
+ push $r13
+ push $r14
+ push $r15
+
+ // incoming fifo command?
+ iord $r10 I[$r0 + 0x200] // INTR
+ and $r11 $r10 0x00000004
+ bra e ih_no_fifo
+ // queue incoming fifo command for later processing
+ mov $r11 0x1900
+ mov $r13 cmd_queue
+ iord $r14 I[$r11 + 0x100] // FIFO_CMD
+ iord $r15 I[$r11 + 0x000] // FIFO_DATA
+ call queue_put
+ add b32 $r11 0x400
+ mov $r14 1
+ iowr I[$r11 + 0x000] $r14 // FIFO_ACK
+
+ // context switch request?
+ ih_no_fifo:
+ and $r11 $r10 0x00000100
+ bra e ih_no_ctxsw
+ // enqueue a context switch for later processing
+ mov $r13 cmd_queue
+ mov $r14 0x4001
+ call queue_put
+
+ // anything we didn't handle, bring it to the host's attention
+ ih_no_ctxsw:
+ mov $r11 0x104
+ not b32 $r11
+ and $r11 $r10 $r11
+ bra e ih_no_other
+ mov $r10 0xc1c
+ shl b32 $r10 6
+ iowr I[$r10] $r11 // INTR_UP_SET
+
+ // ack, and wake up main()
+ ih_no_other:
+ iowr I[$r0 + 0x100] $r10 // INTR_ACK
+
+ pop $r15
+ pop $r14
+ pop $r13
+ pop $r11
+ pop $r10
+ pop $r9
+ pop $r8
+ mov $flags $r8
+ pop $r8
+ bclr $flags $p0
+ iret
+
+// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
+ctx_4160s:
+ mov $r14 0x4160
+ sethi $r14 0x400000
+ mov $r15 1
+ call nv_wr32
+ ctx_4160s_wait:
+ call nv_rd32
+ xbit $r15 $r15 4
+ bra e ctx_4160s_wait
+ ret
+
+// Without clearing again at end of xfer, some things cause PGRAPH
+// to hang with STATUS=0x00000007 until it's cleared.. fbcon can
+// still function with it set however...
+ctx_4160c:
+ mov $r14 0x4160
+ sethi $r14 0x400000
+ clear b32 $r15
+ call nv_wr32
+ ret
+
+// Again, not real sure
+//
+// In: $r15 value to set 0x404170 to
+//
+ctx_4170s:
+ mov $r14 0x4170
+ sethi $r14 0x400000
+ or $r15 0x10
+ call nv_wr32
+ ret
+
+// Waits for a ctx_4170s() call to complete
+//
+ctx_4170w:
+ mov $r14 0x4170
+ sethi $r14 0x400000
+ call nv_rd32
+ and $r15 0x10
+ bra ne ctx_4170w
+ ret
+
+// Disables various things, waits a bit, and re-enables them..
+//
+// Not sure how exactly this helps, perhaps "ENABLE" is not such a
+// good description for the bits we turn off? Anyways, without this,
+// funny things happen.
+//
+ctx_redswitch:
+ mov $r14 0x614
+ shl b32 $r14 6
+ mov $r15 0x270
+ iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
+ mov $r15 8
+ ctx_redswitch_delay:
+ sub b32 $r15 1
+ bra ne ctx_redswitch_delay
+ mov $r15 0x770
+ iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
+ ret
+
+// Not a clue what this is for, except that unless the value is 0x10, the
+// strand context is saved (and presumably restored) incorrectly..
+//
+// In: $r15 value to set to (0x00/0x10 are used)
+//
+ctx_86c:
+ mov $r14 0x86c
+ shl b32 $r14 6
+ iowr I[$r14] $r15 // HUB(0x86c) = val
+ mov $r14 -0x75ec
+ sethi $r14 0x400000
+ call nv_wr32 // ROP(0xa14) = val
+ mov $r14 -0x5794
+ sethi $r14 0x410000
+ call nv_wr32 // GPC(0x86c) = val
+ ret
+
+// ctx_load - load's a channel's ctxctl data, and selects its vm
+//
+// In: $r2 channel address
+//
+ctx_load:
+ trace_set(T_CHAN)
+
+ // switch to channel, somewhat magic in parts..
+ mov $r10 12 // DONE_UNK12
+ call wait_donez
+ mov $r1 0xa24
+ shl b32 $r1 6
+ iowr I[$r1 + 0x000] $r0 // 0x409a24
+ mov $r3 0xb00
+ shl b32 $r3 6
+ iowr I[$r3 + 0x100] $r2 // CHAN_NEXT
+ mov $r1 0xa0c
+ shl b32 $r1 6
+ mov $r4 7
+ iowr I[$r1 + 0x000] $r2 // MEM_CHAN
+ iowr I[$r1 + 0x100] $r4 // MEM_CMD
+ ctx_chan_wait_0:
+ iord $r4 I[$r1 + 0x100]
+ and $r4 0x1f
+ bra ne ctx_chan_wait_0
+ iowr I[$r3 + 0x000] $r2 // CHAN_CUR
+
+ // load channel header, fetch PGRAPH context pointer
+ mov $xtargets $r0
+ bclr $r2 31
+ shl b32 $r2 4
+ add b32 $r2 2
+
+ trace_set(T_LCHAN)
+ mov $r1 0xa04
+ shl b32 $r1 6
+ iowr I[$r1 + 0x000] $r2 // MEM_BASE
+ mov $r1 0xa20
+ shl b32 $r1 6
+ mov $r2 0x0002
+ sethi $r2 0x80000000
+ iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram
+ mov $r1 0x10 // chan + 0x0210
+ mov $r2 xfer_data
+ sethi $r2 0x00020000 // 16 bytes
+ xdld $r1 $r2
+ xdwait
+ trace_clr(T_LCHAN)
+
+ // update current context
+ ld b32 $r1 D[$r0 + xfer_data + 4]
+ shl b32 $r1 24
+ ld b32 $r2 D[$r0 + xfer_data + 0]
+ shr b32 $r2 8
+ or $r1 $r2
+ st b32 D[$r0 + ctx_current] $r1
+
+ // set transfer base to start of context, and fetch context header
+ trace_set(T_LCTXH)
+ mov $r2 0xa04
+ shl b32 $r2 6
+ iowr I[$r2 + 0x000] $r1 // MEM_BASE
+ mov $r2 1
+ mov $r1 0xa20
+ shl b32 $r1 6
+ iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm
+ mov $r1 chan_data
+ sethi $r1 0x00060000 // 256 bytes
+ xdld $r0 $r1
+ xdwait
+ trace_clr(T_LCTXH)
+
+ trace_clr(T_CHAN)
+ ret
+
+// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as
+// the active channel for ctxctl, but not actually transfer
+// any context data. intended for use only during initial
+// context construction.
+//
+// In: $r2 channel address
+//
+ctx_chan:
+ call ctx_4160s
+ call ctx_load
+ mov $r10 12 // DONE_UNK12
+ call wait_donez
+ mov $r1 0xa10
+ shl b32 $r1 6
+ mov $r2 5
+ iowr I[$r1 + 0x000] $r2 // MEM_CMD = 5 (???)
+ ctx_chan_wait:
+ iord $r2 I[$r1 + 0x000]
+ or $r2 $r2
+ bra ne ctx_chan_wait
+ call ctx_4160c
+ ret
+
+// Execute per-context state overrides list
+//
+// Only executed on the first load of a channel. Might want to look into
+// removing this and having the host directly modify the channel's context
+// to change this state... The nouveau DRM already builds this list as
+// it's definitely needed for NVIDIA's, so we may as well use it for now
+//
+// Input: $r1 mmio list length
+//
+ctx_mmio_exec:
+ // set transfer base to be the mmio list
+ ld b32 $r3 D[$r0 + chan_mmio_address]
+ mov $r2 0xa04
+ shl b32 $r2 6
+ iowr I[$r2 + 0x000] $r3 // MEM_BASE
+
+ clear b32 $r3
+ ctx_mmio_loop:
+ // fetch next 256 bytes of mmio list if necessary
+ and $r4 $r3 0xff
+ bra ne ctx_mmio_pull
+ mov $r5 xfer_data
+ sethi $r5 0x00060000 // 256 bytes
+ xdld $r3 $r5
+ xdwait
+
+ // execute a single list entry
+ ctx_mmio_pull:
+ ld b32 $r14 D[$r4 + xfer_data + 0x00]
+ ld b32 $r15 D[$r4 + xfer_data + 0x04]
+ call nv_wr32
+
+ // next!
+ add b32 $r3 8
+ sub b32 $r1 1
+ bra ne ctx_mmio_loop
+
+ // set transfer base back to the current context
+ ctx_mmio_done:
+ ld b32 $r3 D[$r0 + ctx_current]
+ iowr I[$r2 + 0x000] $r3 // MEM_BASE
+
+ // disable the mmio list now, we don't need/want to execute it again
+ st b32 D[$r0 + chan_mmio_count] $r0
+ mov $r1 chan_data
+ sethi $r1 0x00060000 // 256 bytes
+ xdst $r0 $r1
+ xdwait
+ ret
+
+// Transfer HUB context data between GPU and storage area
+//
+// In: $r2 channel address
+// $p1 clear on save, set on load
+// $p2 set if opposite direction done/will be done, so:
+// on save it means: "a load will follow this save"
+// on load it means: "a save preceeded this load"
+//
+ctx_xfer:
+ bra not $p1 ctx_xfer_pre
+ bra $p2 ctx_xfer_pre_load
+ ctx_xfer_pre:
+ mov $r15 0x10
+ call ctx_86c
+ call ctx_4160s
+ bra not $p1 ctx_xfer_exec
+
+ ctx_xfer_pre_load:
+ mov $r15 2
+ call ctx_4170s
+ call ctx_4170w
+ call ctx_redswitch
+ clear b32 $r15
+ call ctx_4170s
+ call ctx_load
+
+ // fetch context pointer, and initiate xfer on all GPCs
+ ctx_xfer_exec:
+ ld b32 $r1 D[$r0 + ctx_current]
+ mov $r2 0x414
+ shl b32 $r2 6
+ iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset
+ mov $r14 -0x5b00
+ sethi $r14 0x410000
+ mov b32 $r15 $r1
+ call nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer
+ add b32 $r14 4
+ xbit $r15 $flags $p1
+ xbit $r2 $flags $p2
+ shl b32 $r2 1
+ or $r15 $r2
+ call nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
+
+ // strands
+ mov $r1 0x4afc
+ sethi $r1 0x20000
+ mov $r2 0xc
+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c
+ call strand_wait
+ mov $r2 0x47fc
+ sethi $r2 0x20000
+ iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00
+ xbit $r2 $flags $p1
+ add b32 $r2 3
+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+
+ // mmio context
+ xbit $r10 $flags $p1 // direction
+ or $r10 6 // first, last
+ mov $r11 0 // base = 0
+ ld b32 $r12 D[$r0 + hub_mmio_list_head]
+ ld b32 $r13 D[$r0 + hub_mmio_list_tail]
+ mov $r14 0 // not multi
+ call mmctx_xfer
+
+ // wait for GPCs to all complete
+ mov $r10 8 // DONE_BAR
+ call wait_doneo
+
+ // wait for strand xfer to complete
+ call strand_wait
+
+ // post-op
+ bra $p1 ctx_xfer_post
+ mov $r10 12 // DONE_UNK12
+ call wait_donez
+ mov $r1 0xa10
+ shl b32 $r1 6
+ mov $r2 5
+ iowr I[$r1] $r2 // MEM_CMD
+ ctx_xfer_post_save_wait:
+ iord $r2 I[$r1]
+ or $r2 $r2
+ bra ne ctx_xfer_post_save_wait
+
+ bra $p2 ctx_xfer_done
+ ctx_xfer_post:
+ mov $r15 2
+ call ctx_4170s
+ clear b32 $r15
+ call ctx_86c
+ call strand_post
+ call ctx_4170w
+ clear b32 $r15
+ call ctx_4170s
+
+ bra not $p1 ctx_xfer_no_post_mmio
+ ld b32 $r1 D[$r0 + chan_mmio_count]
+ or $r1 $r1
+ bra e ctx_xfer_no_post_mmio
+ call ctx_mmio_exec
+
+ ctx_xfer_no_post_mmio:
+ call ctx_4160c
+
+ ctx_xfer_done:
+ ret
+
+.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
new file mode 100644
index 000000000000..b3b541b6d044
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
@@ -0,0 +1,838 @@
+uint32_t nvc0_grhub_data[] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x000000c0,
+ 0x012c0090,
+ 0x000000c1,
+ 0x01300090,
+ 0x000000c3,
+ 0x012c0090,
+ 0x000000c4,
+ 0x012c0090,
+ 0x000000c8,
+ 0x012c0090,
+ 0x000000ce,
+ 0x012c0090,
+ 0x00000000,
+ 0x0417e91c,
+ 0x04400204,
+ 0x28404004,
+ 0x00404044,
+ 0x34404094,
+ 0x184040d0,
+ 0x004040f8,
+ 0x08404130,
+ 0x08404150,
+ 0x04404164,
+ 0x08404174,
+ 0x1c404200,
+ 0x34404404,
+ 0x0c404460,
+ 0x00404480,
+ 0x00404498,
+ 0x0c404604,
+ 0x7c404618,
+ 0x50404698,
+ 0x044046f0,
+ 0x54404700,
+ 0x00405800,
+ 0x08405830,
+ 0x00405854,
+ 0x0c405870,
+ 0x04405a00,
+ 0x00405a18,
+ 0x00406020,
+ 0x0c406028,
+ 0x044064a8,
+ 0x044064b4,
+ 0x00407804,
+ 0x1440780c,
+ 0x004078bc,
+ 0x18408000,
+ 0x00408064,
+ 0x08408800,
+ 0x0c408900,
+ 0x00408980,
+ 0x044064c0,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+uint32_t nvc0_grhub_code[] = {
+ 0x03090ef5,
+ 0x9800d898,
+ 0x86f001d9,
+ 0x0489b808,
+ 0xf00c1bf4,
+ 0x21f502f7,
+ 0x00f802ec,
+ 0xb60798c4,
+ 0x8dbb0384,
+ 0x0880b600,
+ 0x80008e80,
+ 0x90b6018f,
+ 0x0f94f001,
+ 0xf801d980,
+ 0x0131f400,
+ 0x9800d898,
+ 0x89b801d9,
+ 0x210bf404,
+ 0xb60789c4,
+ 0x9dbb0394,
+ 0x0890b600,
+ 0x98009e98,
+ 0x80b6019f,
+ 0x0f84f001,
+ 0xf400d880,
+ 0x00f80132,
+ 0x0728b7f1,
+ 0xb906b4b6,
+ 0xc9f002ec,
+ 0x00bcd01f,
+ 0xc800bccf,
+ 0x1bf41fcc,
+ 0x06a7f0fa,
+ 0x010321f5,
+ 0xf840bfcf,
+ 0x28b7f100,
+ 0x06b4b607,
+ 0xb980bfd0,
+ 0xc9f002ec,
+ 0x1ec9f01f,
+ 0xcf00bcd0,
+ 0xccc800bc,
+ 0xfa1bf41f,
+ 0x87f100f8,
+ 0x84b60430,
+ 0x1ff9f006,
+ 0xf8008fd0,
+ 0x3087f100,
+ 0x0684b604,
+ 0xf80080d0,
+ 0x3c87f100,
+ 0x0684b608,
+ 0x99f094bd,
+ 0x0089d000,
+ 0x081887f1,
+ 0xd00684b6,
+ 0x87f1008a,
+ 0x84b60400,
+ 0x0088cf06,
+ 0xf4888aff,
+ 0x87f1f31b,
+ 0x84b6085c,
+ 0xf094bd06,
+ 0x89d00099,
+ 0xf100f800,
+ 0xb6083c87,
+ 0x94bd0684,
+ 0xd00099f0,
+ 0x87f10089,
+ 0x84b60818,
+ 0x008ad006,
+ 0x040087f1,
+ 0xcf0684b6,
+ 0x8aff0088,
+ 0xf30bf488,
+ 0x085c87f1,
+ 0xbd0684b6,
+ 0x0099f094,
+ 0xf80089d0,
+ 0x9894bd00,
+ 0x85b600e8,
+ 0x0180b61a,
+ 0xbb0284b6,
+ 0xe0b60098,
+ 0x04efb804,
+ 0xb9eb1bf4,
+ 0x00f8029f,
+ 0x083c87f1,
+ 0xbd0684b6,
+ 0x0199f094,
+ 0xf10089d0,
+ 0xb6071087,
+ 0x94bd0684,
+ 0xf405bbfd,
+ 0x8bd0090b,
+ 0x0099f000,
+ 0xf405eefd,
+ 0x8ed00c0b,
+ 0xc08fd080,
+ 0xb70199f0,
+ 0xc8010080,
+ 0xb4b600ab,
+ 0x0cb9f010,
+ 0xb601aec8,
+ 0xbefd11e4,
+ 0x008bd005,
+ 0xf0008ecf,
+ 0x0bf41fe4,
+ 0x00ce98fa,
+ 0xd005e9fd,
+ 0xc0b6c08e,
+ 0x04cdb804,
+ 0xc8e81bf4,
+ 0x1bf402ab,
+ 0x008bcf18,
+ 0xb01fb4f0,
+ 0x1bf410b4,
+ 0x02a7f0f7,
+ 0xf4c921f4,
+ 0xabc81b0e,
+ 0x10b4b600,
+ 0xf00cb9f0,
+ 0x8bd012b9,
+ 0x008bcf00,
+ 0xf412bbc8,
+ 0x87f1fa1b,
+ 0x84b6085c,
+ 0xf094bd06,
+ 0x89d00199,
+ 0xf900f800,
+ 0x02a7f0a0,
+ 0xfcc921f4,
+ 0xf100f8a0,
+ 0xf04afc87,
+ 0x97f00283,
+ 0x0089d00c,
+ 0x020721f5,
+ 0x87f100f8,
+ 0x83f04afc,
+ 0x0d97f002,
+ 0xf50089d0,
+ 0xf8020721,
+ 0xfca7f100,
+ 0x02a3f04f,
+ 0x0500aba2,
+ 0xd00fc7f0,
+ 0xc7f000ac,
+ 0x00bcd00b,
+ 0x020721f5,
+ 0xf000aed0,
+ 0xbcd00ac7,
+ 0x0721f500,
+ 0xf100f802,
+ 0xb6083c87,
+ 0x94bd0684,
+ 0xd00399f0,
+ 0x21f50089,
+ 0xe7f00213,
+ 0x3921f503,
+ 0xfca7f102,
+ 0x02a3f046,
+ 0x0400aba0,
+ 0xf040a0d0,
+ 0xbcd001c7,
+ 0x0721f500,
+ 0x010c9202,
+ 0xf000acd0,
+ 0xbcd002c7,
+ 0x0721f500,
+ 0x2621f502,
+ 0x8087f102,
+ 0x0684b608,
+ 0xb70089cf,
+ 0x95220080,
+ 0x8ed008fe,
+ 0x408ed000,
+ 0xb6808acf,
+ 0xa0b606a5,
+ 0x00eabb01,
+ 0xb60480b6,
+ 0x1bf40192,
+ 0x08e4b6e8,
+ 0xf1f2efbc,
+ 0xb6085c87,
+ 0x94bd0684,
+ 0xd00399f0,
+ 0x00f80089,
+ 0xe7f1e0f9,
+ 0xe4b60814,
+ 0x00efd006,
+ 0x0c1ce7f1,
+ 0xf006e4b6,
+ 0xefd001f7,
+ 0xf8e0fc00,
+ 0xfe04bd00,
+ 0x07fe0004,
+ 0x0017f100,
+ 0x0227f012,
+ 0xf10012d0,
+ 0xfe05b917,
+ 0x17f10010,
+ 0x10d00400,
+ 0x0437f1c0,
+ 0x0634b604,
+ 0x200327f1,
+ 0xf10032d0,
+ 0xd0200427,
+ 0x27f10132,
+ 0x32d0200b,
+ 0x0c27f102,
+ 0x0732d020,
+ 0x0c2427f1,
+ 0xb90624b6,
+ 0x23d00003,
+ 0x0427f100,
+ 0x0023f087,
+ 0xb70012d0,
+ 0xf0010012,
+ 0x12d00427,
+ 0x1031f400,
+ 0x9604e7f1,
+ 0xf440e3f0,
+ 0xf1c76821,
+ 0x01018090,
+ 0x801ff4f0,
+ 0x17f0000f,
+ 0x041fbb01,
+ 0xf10112b6,
+ 0xb6040c27,
+ 0x21d00624,
+ 0x4021d000,
+ 0x080027f1,
+ 0xcf0624b6,
+ 0xf7f00022,
+ 0x08f0b654,
+ 0xb800f398,
+ 0x0bf40432,
+ 0x0034b00b,
+ 0xf8f11bf4,
+ 0x0017f100,
+ 0x02fe5801,
+ 0xf003ff58,
+ 0x0e8000e3,
+ 0x150f8014,
+ 0x013d21f5,
+ 0x070037f1,
+ 0x950634b6,
+ 0x34d00814,
+ 0x4034d000,
+ 0x130030b7,
+ 0xb6001fbb,
+ 0x3fd002f5,
+ 0x0815b600,
+ 0xb60110b6,
+ 0x1fb90814,
+ 0x6321f502,
+ 0x001fbb02,
+ 0xf1000398,
+ 0xf0200047,
+ 0x4ea05043,
+ 0x1fb90804,
+ 0x8d21f402,
+ 0x08004ea0,
+ 0xf4022fb9,
+ 0x4ea08d21,
+ 0xf4bd010c,
+ 0xa08d21f4,
+ 0xf401044e,
+ 0x4ea08d21,
+ 0xf7f00100,
+ 0x8d21f402,
+ 0x08004ea0,
+ 0xc86821f4,
+ 0x0bf41fff,
+ 0x044ea0fa,
+ 0x6821f408,
+ 0xb7001fbb,
+ 0xb6800040,
+ 0x1bf40132,
+ 0x0027f1b4,
+ 0x0624b608,
+ 0xb74021d0,
+ 0xbd080020,
+ 0x1f19f014,
+ 0xf40021d0,
+ 0x28f40031,
+ 0x08d7f000,
+ 0xf43921f4,
+ 0xe4b1f401,
+ 0x1bf54001,
+ 0x87f100d1,
+ 0x84b6083c,
+ 0xf094bd06,
+ 0x89d00499,
+ 0x0017f100,
+ 0x0614b60b,
+ 0xcf4012cf,
+ 0x13c80011,
+ 0x7e0bf41f,
+ 0xf41f23c8,
+ 0x20f95a0b,
+ 0xf10212b9,
+ 0xb6083c87,
+ 0x94bd0684,
+ 0xd00799f0,
+ 0x32f40089,
+ 0x0231f401,
+ 0x082921f5,
+ 0x085c87f1,
+ 0xbd0684b6,
+ 0x0799f094,
+ 0xfc0089d0,
+ 0x3c87f120,
+ 0x0684b608,
+ 0x99f094bd,
+ 0x0089d006,
+ 0xf50131f4,
+ 0xf1082921,
+ 0xb6085c87,
+ 0x94bd0684,
+ 0xd00699f0,
+ 0x0ef40089,
+ 0xb920f931,
+ 0x32f40212,
+ 0x0232f401,
+ 0x082921f5,
+ 0x17f120fc,
+ 0x14b60b00,
+ 0x0012d006,
+ 0xc8130ef4,
+ 0x0bf41f23,
+ 0x0131f40d,
+ 0xf50232f4,
+ 0xf1082921,
+ 0xb60b0c17,
+ 0x27f00614,
+ 0x0012d001,
+ 0x085c87f1,
+ 0xbd0684b6,
+ 0x0499f094,
+ 0xf50089d0,
+ 0xb0ff200e,
+ 0x1bf401e4,
+ 0x02f2b90d,
+ 0x07b521f5,
+ 0xb0420ef4,
+ 0x1bf402e4,
+ 0x3c87f12e,
+ 0x0684b608,
+ 0x99f094bd,
+ 0x0089d007,
+ 0xf40132f4,
+ 0x21f50232,
+ 0x87f10829,
+ 0x84b6085c,
+ 0xf094bd06,
+ 0x89d00799,
+ 0x110ef400,
+ 0xf010ef94,
+ 0x21f501f5,
+ 0x0ef502ec,
+ 0x17f1fed1,
+ 0x14b60820,
+ 0xf024bd06,
+ 0x12d01f29,
+ 0xbe0ef500,
+ 0xfe80f9fe,
+ 0x80f90188,
+ 0xa0f990f9,
+ 0xd0f9b0f9,
+ 0xf0f9e0f9,
+ 0xc4800acf,
+ 0x0bf404ab,
+ 0x00b7f11d,
+ 0x08d7f019,
+ 0xcf40becf,
+ 0x21f400bf,
+ 0x00b0b704,
+ 0x01e7f004,
+ 0xe400bed0,
+ 0xf40100ab,
+ 0xd7f00d0b,
+ 0x01e7f108,
+ 0x0421f440,
+ 0x0104b7f1,
+ 0xabffb0bd,
+ 0x0d0bf4b4,
+ 0x0c1ca7f1,
+ 0xd006a4b6,
+ 0x0ad000ab,
+ 0xfcf0fc40,
+ 0xfcd0fce0,
+ 0xfca0fcb0,
+ 0xfe80fc90,
+ 0x80fc0088,
+ 0xf80032f4,
+ 0x60e7f101,
+ 0x40e3f041,
+ 0xf401f7f0,
+ 0x21f48d21,
+ 0x04ffc868,
+ 0xf8fa0bf4,
+ 0x60e7f100,
+ 0x40e3f041,
+ 0x21f4f4bd,
+ 0xf100f88d,
+ 0xf04170e7,
+ 0xf5f040e3,
+ 0x8d21f410,
+ 0xe7f100f8,
+ 0xe3f04170,
+ 0x6821f440,
+ 0xf410f4f0,
+ 0x00f8f31b,
+ 0x0614e7f1,
+ 0xf106e4b6,
+ 0xd00270f7,
+ 0xf7f000ef,
+ 0x01f2b608,
+ 0xf1fd1bf4,
+ 0xd00770f7,
+ 0x00f800ef,
+ 0x086ce7f1,
+ 0xd006e4b6,
+ 0xe7f100ef,
+ 0xe3f08a14,
+ 0x8d21f440,
+ 0xa86ce7f1,
+ 0xf441e3f0,
+ 0x00f88d21,
+ 0x083c87f1,
+ 0xbd0684b6,
+ 0x0599f094,
+ 0xf00089d0,
+ 0x21f40ca7,
+ 0x2417f1c9,
+ 0x0614b60a,
+ 0xf10010d0,
+ 0xb60b0037,
+ 0x32d00634,
+ 0x0c17f140,
+ 0x0614b60a,
+ 0xd00747f0,
+ 0x14d00012,
+ 0x4014cf40,
+ 0xf41f44f0,
+ 0x32d0fa1b,
+ 0x000bfe00,
+ 0xb61f2af0,
+ 0x20b60424,
+ 0x3c87f102,
+ 0x0684b608,
+ 0x99f094bd,
+ 0x0089d008,
+ 0x0a0417f1,
+ 0xd00614b6,
+ 0x17f10012,
+ 0x14b60a20,
+ 0x0227f006,
+ 0x800023f1,
+ 0xf00012d0,
+ 0x27f11017,
+ 0x23f00300,
+ 0x0512fa02,
+ 0x87f103f8,
+ 0x84b6085c,
+ 0xf094bd06,
+ 0x89d00899,
+ 0xc1019800,
+ 0x981814b6,
+ 0x25b6c002,
+ 0x0512fd08,
+ 0xf1160180,
+ 0xb6083c87,
+ 0x94bd0684,
+ 0xd00999f0,
+ 0x27f10089,
+ 0x24b60a04,
+ 0x0021d006,
+ 0xf10127f0,
+ 0xb60a2017,
+ 0x12d00614,
+ 0x0017f100,
+ 0x0613f002,
+ 0xf80501fa,
+ 0x5c87f103,
+ 0x0684b608,
+ 0x99f094bd,
+ 0x0089d009,
+ 0x085c87f1,
+ 0xbd0684b6,
+ 0x0599f094,
+ 0xf80089d0,
+ 0x3121f500,
+ 0xb821f506,
+ 0x0ca7f006,
+ 0xf1c921f4,
+ 0xb60a1017,
+ 0x27f00614,
+ 0x0012d005,
+ 0xfd0012cf,
+ 0x1bf40522,
+ 0x4921f5fa,
+ 0x9800f806,
+ 0x27f18103,
+ 0x24b60a04,
+ 0x0023d006,
+ 0x34c434bd,
+ 0x0f1bf4ff,
+ 0x030057f1,
+ 0xfa0653f0,
+ 0x03f80535,
+ 0x98c04e98,
+ 0x21f4c14f,
+ 0x0830b68d,
+ 0xf40112b6,
+ 0x0398df1b,
+ 0x0023d016,
+ 0xf1800080,
+ 0xf0020017,
+ 0x01fa0613,
+ 0xf803f806,
+ 0x0611f400,
+ 0xf01102f4,
+ 0x21f510f7,
+ 0x21f50698,
+ 0x11f40631,
+ 0x02f7f01c,
+ 0x065721f5,
+ 0x066621f5,
+ 0x067821f5,
+ 0x21f5f4bd,
+ 0x21f50657,
+ 0x019806b8,
+ 0x1427f116,
+ 0x0624b604,
+ 0xf10020d0,
+ 0xf0a500e7,
+ 0x1fb941e3,
+ 0x8d21f402,
+ 0xf004e0b6,
+ 0x2cf001fc,
+ 0x0124b602,
+ 0xf405f2fd,
+ 0x17f18d21,
+ 0x13f04afc,
+ 0x0c27f002,
+ 0xf50012d0,
+ 0xf1020721,
+ 0xf047fc27,
+ 0x20d00223,
+ 0x012cf000,
+ 0xd00320b6,
+ 0xacf00012,
+ 0x06a5f001,
+ 0x9800b7f0,
+ 0x0d98140c,
+ 0x00e7f015,
+ 0x015c21f5,
+ 0xf508a7f0,
+ 0xf5010321,
+ 0xf4020721,
+ 0xa7f02201,
+ 0xc921f40c,
+ 0x0a1017f1,
+ 0xf00614b6,
+ 0x12d00527,
+ 0x0012cf00,
+ 0xf40522fd,
+ 0x02f4fa1b,
+ 0x02f7f032,
+ 0x065721f5,
+ 0x21f5f4bd,
+ 0x21f50698,
+ 0x21f50226,
+ 0xf4bd0666,
+ 0x065721f5,
+ 0x981011f4,
+ 0x11fd8001,
+ 0x070bf405,
+ 0x07df21f5,
+ 0x064921f5,
+ 0x000000f8,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c
index 82357d2df1f4..b701c439c92e 100644
--- a/drivers/gpu/drm/nouveau/nvc0_instmem.c
+++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c
@@ -32,7 +32,6 @@ struct nvc0_instmem_priv {
struct nouveau_channel *bar1;
struct nouveau_gpuobj *bar3_pgd;
struct nouveau_channel *bar3;
- struct nouveau_gpuobj *chan_pgd;
};
int
@@ -181,17 +180,11 @@ nvc0_instmem_init(struct drm_device *dev)
goto error;
/* channel vm */
- ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+ &dev_priv->chan_vm);
if (ret)
goto error;
- ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd);
- if (ret)
- goto error;
-
- nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd);
- nouveau_vm_ref(NULL, &vm, NULL);
-
nvc0_instmem_resume(dev);
return 0;
error:
@@ -211,8 +204,7 @@ nvc0_instmem_takedown(struct drm_device *dev)
nv_wr32(dev, 0x1704, 0x00000000);
nv_wr32(dev, 0x1714, 0x00000000);
- nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd);
- nouveau_gpuobj_ref(NULL, &priv->chan_pgd);
+ nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
nvc0_channel_del(&priv->bar1);
nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c
index a179e6c55afb..9e352944a35a 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vm.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vm.c
@@ -105,7 +105,11 @@ nvc0_vm_flush(struct nouveau_vm *vm)
struct drm_device *dev = vm->dev;
struct nouveau_vm_pgd *vpgd;
unsigned long flags;
- u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5;
+ u32 engine;
+
+ engine = 1;
+ if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm)
+ engine |= 4;
pinstmem->flush(vm->dev);
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
index 67c6ec6f34ea..e45a24d84e98 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vram.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -61,9 +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 ttm_bo_device *bdev = &dev_priv->ttm.bdev;
- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
- struct nouveau_mm *mm = man->priv;
+ struct nouveau_mm *mm = dev_priv->engine.vram.mm;
struct nouveau_mm_node *r;
struct nouveau_mem *mem;
int ret;
@@ -105,9 +103,15 @@ int
nvc0_vram_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ 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;
dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
- dev_priv->vram_rblock_size = 4096;
- return 0;
+
+ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+
+ return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
}
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 9541995e4b21..c742944d3805 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -764,7 +764,7 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc,
}
static void atombios_crtc_program_pll(struct drm_crtc *crtc,
- int crtc_id,
+ u32 crtc_id,
int pll_id,
u32 encoder_mode,
u32 encoder_id,
@@ -851,8 +851,7 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
args.v5.ucPpll = pll_id;
break;
case 6:
- args.v6.ulCrtcPclkFreq.ucCRTC = crtc_id;
- args.v6.ulCrtcPclkFreq.ulPixelClock = cpu_to_le32(clock / 10);
+ args.v6.ulDispEngClkFreq = cpu_to_le32(crtc_id << 24 | clock / 10);
args.v6.ucRefDiv = ref_div;
args.v6.usFbDiv = cpu_to_le16(fb_div);
args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 8c0f9e36ff8e..645b84b3d203 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -627,6 +627,7 @@ struct radeon_dp_link_train_info {
u8 train_set[4];
u8 link_status[DP_LINK_STATUS_SIZE];
u8 tries;
+ bool use_dpencoder;
};
static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
@@ -646,7 +647,7 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
int rtp = 0;
/* set training pattern on the source */
- if (ASIC_IS_DCE4(dp_info->rdev)) {
+ if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) {
switch (tp) {
case DP_TRAINING_PATTERN_1:
rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
@@ -706,7 +707,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp);
/* start training on the source */
- if (ASIC_IS_DCE4(dp_info->rdev))
+ if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
atombios_dig_encoder_setup(dp_info->encoder,
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0);
else
@@ -731,7 +732,7 @@ static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info
DP_TRAINING_PATTERN_DISABLE);
/* disable the training pattern on the source */
- if (ASIC_IS_DCE4(dp_info->rdev))
+ if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
atombios_dig_encoder_setup(dp_info->encoder,
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0);
else
@@ -869,7 +870,8 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *dig_connector;
struct radeon_dp_link_train_info dp_info;
- u8 tmp;
+ int index;
+ u8 tmp, frev, crev;
if (!radeon_encoder->enc_priv)
return;
@@ -884,6 +886,18 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
(dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP))
return;
+ /* DPEncoderService newer than 1.1 can't program properly the
+ * training pattern. When facing such version use the
+ * DIGXEncoderControl (X== 1 | 2)
+ */
+ dp_info.use_dpencoder = true;
+ index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
+ if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) {
+ if (crev > 1) {
+ dp_info.use_dpencoder = false;
+ }
+ }
+
dp_info.enc_id = 0;
if (dig->dig_encoder)
dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 15bd0477a3e8..14dce9f22172 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1382,9 +1382,6 @@ int evergreen_cp_resume(struct radeon_device *rdev)
/* set the wb address wether it's enabled or not */
WREG32(CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
- RB_RPTR_SWAP(2) |
-#endif
((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
@@ -2047,6 +2044,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
rdev->config.evergreen.tile_config |=
((gb_addr_config & 0x30000000) >> 28) << 12;
+ rdev->config.evergreen.backend_map = gb_backend_map;
WREG32(GB_BACKEND_MAP, gb_backend_map);
WREG32(GB_ADDR_CONFIG, gb_addr_config);
WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
@@ -2761,6 +2759,9 @@ int evergreen_irq_process(struct radeon_device *rdev)
return IRQ_NONE;
}
restart_ih:
+ /* Order reading of wptr vs. reading of IH ring data */
+ rmb();
+
/* display interrupts */
evergreen_irq_ack(rdev);
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 23d36417158d..189e86522b5b 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -856,7 +856,6 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
case SQ_PGM_START_PS:
case SQ_PGM_START_HS:
case SQ_PGM_START_LS:
- case GDS_ADDR_BASE:
case SQ_CONST_MEM_BASE:
case SQ_ALU_CONST_CACHE_GS_0:
case SQ_ALU_CONST_CACHE_GS_1:
@@ -946,6 +945,34 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
}
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
break;
+ case SX_MEMORY_EXPORT_BASE:
+ if (p->rdev->family >= CHIP_CAYMAN) {
+ dev_warn(p->dev, "bad SET_CONFIG_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONFIG_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ break;
+ case CAYMAN_SX_SCATTER_EXPORT_BASE:
+ if (p->rdev->family < CHIP_CAYMAN) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ break;
default:
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
return -EINVAL;
@@ -1153,6 +1180,34 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
return r;
}
break;
+ case PACKET3_DISPATCH_DIRECT:
+ if (pkt->count != 3) {
+ DRM_ERROR("bad DISPATCH_DIRECT\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+ return r;
+ }
+ break;
+ case PACKET3_DISPATCH_INDIRECT:
+ if (pkt->count != 1) {
+ DRM_ERROR("bad DISPATCH_INDIRECT\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad DISPATCH_INDIRECT\n");
+ return -EINVAL;
+ }
+ ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+ return r;
+ }
+ break;
case PACKET3_WAIT_REG_MEM:
if (pkt->count != 5) {
DRM_ERROR("bad WAIT_REG_MEM\n");
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index b7b2714f0b32..7363d9dec909 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -351,6 +351,7 @@
#define COLOR_BUFFER_SIZE(x) ((x) << 0)
#define POSITION_BUFFER_SIZE(x) ((x) << 8)
#define SMX_BUFFER_SIZE(x) ((x) << 16)
+#define SX_MEMORY_EXPORT_BASE 0x9010
#define SX_MISC 0x28350
#define CB_PERF_CTR0_SEL_0 0x9A20
@@ -1122,6 +1123,7 @@
#define CAYMAN_PA_SC_AA_CONFIG 0x28BE0
#define CAYMAN_MSAA_NUM_SAMPLES_SHIFT 0
#define CAYMAN_MSAA_NUM_SAMPLES_MASK 0x7
+#define CAYMAN_SX_SCATTER_EXPORT_BASE 0x28358
/* cayman packet3 addition */
#define CAYMAN_PACKET3_DEALLOC_STATE 0x14
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 559dbd412906..44c4750f4518 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -833,6 +833,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)
rdev->config.cayman.tile_config |=
((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
+ rdev->config.cayman.backend_map = gb_backend_map;
WREG32(GB_BACKEND_MAP, gb_backend_map);
WREG32(GB_ADDR_CONFIG, gb_addr_config);
WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index bc54b26cb32f..aa5571b73aa0 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1662,6 +1662,7 @@ void r600_gpu_init(struct radeon_device *rdev)
R6XX_MAX_BACKENDS_MASK) >> 16)),
(cc_rb_backend_disable >> 16));
rdev->config.r600.tile_config = tiling_config;
+ rdev->config.r600.backend_map = backend_map;
tiling_config |= BACKEND_MAP(backend_map);
WREG32(GB_TILING_CONFIG, tiling_config);
WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff);
@@ -2212,9 +2213,6 @@ int r600_cp_resume(struct radeon_device *rdev)
/* set the wb address whether it's enabled or not */
WREG32(CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
- RB_RPTR_SWAP(2) |
-#endif
((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
@@ -2994,10 +2992,6 @@ int r600_irq_init(struct radeon_device *rdev)
/* RPTR_REARM only works if msi's are enabled */
if (rdev->msi_enabled)
ih_cntl |= RPTR_REARM;
-
-#ifdef __BIG_ENDIAN
- ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT);
-#endif
WREG32(IH_CNTL, ih_cntl);
/* force the active interrupt state to all disabled */
@@ -3308,6 +3302,10 @@ int r600_irq_process(struct radeon_device *rdev)
if (!rdev->ih.enabled || rdev->shutdown)
return IRQ_NONE;
+ /* No MSIs, need a dummy read to flush PCI DMAs */
+ if (!rdev->msi_enabled)
+ RREG32(IH_RB_WPTR);
+
wptr = r600_get_ih_wptr(rdev);
rptr = rdev->ih.rptr;
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
@@ -3320,6 +3318,9 @@ int r600_irq_process(struct radeon_device *rdev)
}
restart_ih:
+ /* Order reading of wptr vs. reading of IH ring data */
+ rmb();
+
/* display interrupts */
r600_irq_ack(rdev);
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index c3ab959bdc7c..45fd592f9606 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -1802,8 +1802,8 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
/* Set ring buffer size */
#ifdef __BIG_ENDIAN
RADEON_WRITE(R600_CP_RB_CNTL,
- RADEON_BUF_SWAP_32BIT |
- RADEON_RB_NO_UPDATE |
+ R600_BUF_SWAP_32BIT |
+ R600_RB_NO_UPDATE |
(dev_priv->ring.rptr_update_l2qw << 8) |
dev_priv->ring.size_l2qw);
#else
@@ -1820,15 +1820,15 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
#ifdef __BIG_ENDIAN
RADEON_WRITE(R600_CP_RB_CNTL,
- RADEON_BUF_SWAP_32BIT |
- RADEON_RB_NO_UPDATE |
- RADEON_RB_RPTR_WR_ENA |
+ R600_BUF_SWAP_32BIT |
+ R600_RB_NO_UPDATE |
+ R600_RB_RPTR_WR_ENA |
(dev_priv->ring.rptr_update_l2qw << 8) |
dev_priv->ring.size_l2qw);
#else
RADEON_WRITE(R600_CP_RB_CNTL,
- RADEON_RB_NO_UPDATE |
- RADEON_RB_RPTR_WR_ENA |
+ R600_RB_NO_UPDATE |
+ R600_RB_RPTR_WR_ENA |
(dev_priv->ring.rptr_update_l2qw << 8) |
dev_priv->ring.size_l2qw);
#endif
@@ -1851,13 +1851,8 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
- ((unsigned long) dev->sg->virtual)
+ dev_priv->gart_vm_start;
}
- RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
- (2 << 0) |
-#endif
- (rptr_addr & 0xfffffffc));
- RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI,
- upper_32_bits(rptr_addr));
+ RADEON_WRITE(R600_CP_RB_RPTR_ADDR, (rptr_addr & 0xfffffffc));
+ RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, upper_32_bits(rptr_addr));
#ifdef __BIG_ENDIAN
RADEON_WRITE(R600_CP_RB_CNTL,
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 909bda8dd550..db8ef1905d5f 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -1200,6 +1200,15 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
}
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
break;
+ case SX_MEMORY_EXPORT_BASE:
+ r = r600_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONFIG_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ break;
default:
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index ef0e0e016914..32807baf55e2 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -60,7 +60,7 @@
* are considered as fatal)
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/kref.h>
@@ -1003,6 +1003,7 @@ struct r600_asic {
unsigned tiling_npipes;
unsigned tiling_group_size;
unsigned tile_config;
+ unsigned backend_map;
struct r100_gpu_lockup lockup;
};
@@ -1028,6 +1029,7 @@ struct rv770_asic {
unsigned tiling_npipes;
unsigned tiling_group_size;
unsigned tile_config;
+ unsigned backend_map;
struct r100_gpu_lockup lockup;
};
@@ -1054,6 +1056,7 @@ struct evergreen_asic {
unsigned tiling_npipes;
unsigned tiling_group_size;
unsigned tile_config;
+ unsigned backend_map;
struct r100_gpu_lockup lockup;
};
@@ -1174,7 +1177,7 @@ struct radeon_device {
/* Register mmio */
resource_size_t rmmio_base;
resource_size_t rmmio_size;
- void *rmmio;
+ void __iomem *rmmio;
radeon_rreg_t mc_rreg;
radeon_wreg_t mc_wreg;
radeon_rreg_t pll_rreg;
@@ -1251,20 +1254,20 @@ 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(((void __iomem *)rdev->rmmio) + reg);
+ return readl((rdev->rmmio) + reg);
else {
- writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
- return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ 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, ((void __iomem *)rdev->rmmio) + reg);
+ writel(v, (rdev->rmmio) + reg);
else {
- writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
- writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
+ writel(v, (rdev->rmmio) + RADEON_MM_DATA);
}
}
@@ -1296,10 +1299,10 @@ static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
/*
* Registers read & write functions.
*/
-#define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
-#define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
-#define RREG16(reg) readw(((void __iomem *)rdev->rmmio) + (reg))
-#define WREG16(reg, v) writew(v, ((void __iomem *)rdev->rmmio) + (reg))
+#define RREG8(reg) readb((rdev->rmmio) + (reg))
+#define WREG8(reg, v) writeb(v, (rdev->rmmio) + (reg))
+#define RREG16(reg) readw((rdev->rmmio) + (reg))
+#define WREG16(reg, v) writew(v, (rdev->rmmio) + (reg))
#define RREG32(reg) r100_mm_rreg(rdev, (reg))
#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg)))
#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index b2449629537d..df8218bb83a6 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -625,7 +625,7 @@ static struct radeon_asic r600_asic = {
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &r600_cs_parse,
.copy_blit = &r600_copy_blit,
- .copy_dma = &r600_copy_blit,
+ .copy_dma = NULL,
.copy = &r600_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -672,7 +672,7 @@ static struct radeon_asic rs780_asic = {
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &r600_cs_parse,
.copy_blit = &r600_copy_blit,
- .copy_dma = &r600_copy_blit,
+ .copy_dma = NULL,
.copy = &r600_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -719,7 +719,7 @@ static struct radeon_asic rv770_asic = {
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &r600_cs_parse,
.copy_blit = &r600_copy_blit,
- .copy_dma = &r600_copy_blit,
+ .copy_dma = NULL,
.copy = &r600_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -766,7 +766,7 @@ static struct radeon_asic evergreen_asic = {
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
.copy_blit = &evergreen_copy_blit,
- .copy_dma = &evergreen_copy_blit,
+ .copy_dma = NULL,
.copy = &evergreen_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -813,7 +813,7 @@ static struct radeon_asic sumo_asic = {
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
.copy_blit = &evergreen_copy_blit,
- .copy_dma = &evergreen_copy_blit,
+ .copy_dma = NULL,
.copy = &evergreen_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -860,7 +860,7 @@ static struct radeon_asic btc_asic = {
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
.copy_blit = &evergreen_copy_blit,
- .copy_dma = &evergreen_copy_blit,
+ .copy_dma = NULL,
.copy = &evergreen_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -907,7 +907,7 @@ static struct radeon_asic cayman_asic = {
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
.copy_blit = &evergreen_copy_blit,
- .copy_dma = &evergreen_copy_blit,
+ .copy_dma = NULL,
.copy = &evergreen_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c
index 2d48e7a1474b..dcd0863e31ae 100644
--- a/drivers/gpu/drm/radeon/radeon_clocks.c
+++ b/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -96,7 +96,7 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
* Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
* tree. Hopefully, ATI OF driver is kind enough to fill these
*/
-static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+static bool radeon_read_clocks_OF(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
struct device_node *dp = rdev->pdev->dev.of_node;
@@ -166,7 +166,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
return true;
}
#else
-static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+static bool radeon_read_clocks_OF(struct drm_device *dev)
{
return false;
}
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index e4594676a07c..a74217cd192f 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -779,7 +779,8 @@ void radeon_combios_i2c_init(struct radeon_device *rdev)
}
}
}
- } else if (rdev->family >= CHIP_R200) {
+ } else if ((rdev->family == CHIP_R200) ||
+ (rdev->family >= CHIP_R300)) {
/* 0x68 */
i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 75867792a4e2..045ec59478f9 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -2115,7 +2115,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
if (drm_pci_device_is_agp(dev))
dev_priv->flags |= RADEON_IS_AGP;
- else if (drm_pci_device_is_pcie(dev))
+ else if (pci_is_pcie(dev->pdev))
dev_priv->flags |= RADEON_IS_PCIE;
else
dev_priv->flags |= RADEON_IS_PCI;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f0ddbd..28f4655905bc 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -282,7 +282,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
spin_lock_irqsave(&rdev->ddev->event_lock, flags);
work = radeon_crtc->unpin_work;
if (work == NULL ||
- !radeon_fence_signaled(work->fence)) {
+ (work->fence && !radeon_fence_signaled(work->fence))) {
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
return;
}
@@ -348,7 +348,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
struct radeon_framebuffer *new_radeon_fb;
struct drm_gem_object *obj;
struct radeon_bo *rbo;
- struct radeon_fence *fence;
struct radeon_unpin_work *work;
unsigned long flags;
u32 tiling_flags, pitch_pixels;
@@ -359,16 +358,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
if (work == NULL)
return -ENOMEM;
- r = radeon_fence_create(rdev, &fence);
- if (unlikely(r != 0)) {
- kfree(work);
- DRM_ERROR("flip queue: failed to create fence.\n");
- return -ENOMEM;
- }
work->event = event;
work->rdev = rdev;
work->crtc_id = radeon_crtc->crtc_id;
- work->fence = radeon_fence_ref(fence);
old_radeon_fb = to_radeon_framebuffer(crtc->fb);
new_radeon_fb = to_radeon_framebuffer(fb);
/* schedule unpin of the old buffer */
@@ -377,6 +369,10 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
drm_gem_object_reference(obj);
rbo = gem_to_radeon_bo(obj);
work->old_rbo = rbo;
+ obj = new_radeon_fb->obj;
+ rbo = gem_to_radeon_bo(obj);
+ if (rbo->tbo.sync_obj)
+ work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
INIT_WORK(&work->work, radeon_unpin_work_func);
/* We borrow the event spin lock for protecting unpin_work */
@@ -391,9 +387,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
spin_unlock_irqrestore(&dev->event_lock, flags);
/* pin the new buffer */
- obj = new_radeon_fb->obj;
- rbo = gem_to_radeon_bo(obj);
-
DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
work->old_rbo, rbo);
@@ -461,37 +454,18 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
goto pflip_cleanup1;
}
- /* 32 ought to cover us */
- r = radeon_ring_lock(rdev, 32);
- if (r) {
- DRM_ERROR("failed to lock the ring before flip\n");
- goto pflip_cleanup2;
- }
-
- /* emit the fence */
- radeon_fence_emit(rdev, fence);
/* set the proper interrupt */
radeon_pre_page_flip(rdev, radeon_crtc->crtc_id);
- /* fire the ring */
- radeon_ring_unlock_commit(rdev);
return 0;
-pflip_cleanup2:
- drm_vblank_put(dev, radeon_crtc->crtc_id);
-
pflip_cleanup1:
- r = radeon_bo_reserve(rbo, false);
- if (unlikely(r != 0)) {
+ if (unlikely(radeon_bo_reserve(rbo, false) != 0)) {
DRM_ERROR("failed to reserve new rbo in error path\n");
goto pflip_cleanup;
}
- r = radeon_bo_unpin(rbo);
- if (unlikely(r != 0)) {
- radeon_bo_unreserve(rbo);
- r = -EINVAL;
+ if (unlikely(radeon_bo_unpin(rbo) != 0)) {
DRM_ERROR("failed to unpin new rbo in error path\n");
- goto pflip_cleanup;
}
radeon_bo_unreserve(rbo);
@@ -501,7 +475,7 @@ pflip_cleanup:
unlock_free:
drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
spin_unlock_irqrestore(&dev->event_lock, flags);
- radeon_fence_unref(&fence);
+ radeon_fence_unref(&work->fence);
kfree(work);
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 73dfbe8e5f9e..85f033f19a8a 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -50,10 +50,11 @@
* 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
* 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query
* 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
- * 2.10.0 - fusion 2D tiling
+ * 2.10.0 - fusion 2D tiling, initial compute support for the CS checker
+ * 2.11.0 - backend map
*/
#define KMS_DRIVER_MAJOR 2
-#define KMS_DRIVER_MINOR 10
+#define KMS_DRIVER_MINOR 11
#define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 021d2b6b556f..7fd4e3e5ad5f 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -29,7 +29,7 @@
* Dave Airlie
*/
#include <linux/seq_file.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/kref.h>
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index bd58af658581..be2c1224e68a 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -60,7 +60,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
/* update BUS flag */
if (drm_pci_device_is_agp(dev)) {
flags |= RADEON_IS_AGP;
- } else if (drm_pci_device_is_pcie(dev)) {
+ } else if (pci_is_pcie(dev->pdev)) {
flags |= RADEON_IS_PCIE;
} else {
flags |= RADEON_IS_PCI;
@@ -237,6 +237,19 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
case RADEON_INFO_FUSION_GART_WORKING:
value = 1;
break;
+ case RADEON_INFO_BACKEND_MAP:
+ if (rdev->family >= CHIP_CAYMAN)
+ value = rdev->config.cayman.backend_map;
+ else if (rdev->family >= CHIP_CEDAR)
+ value = rdev->config.evergreen.backend_map;
+ else if (rdev->family >= CHIP_RV770)
+ value = rdev->config.rv770.backend_map;
+ else if (rdev->family >= CHIP_R600)
+ value = rdev->config.r600.backend_map;
+ else {
+ return -EINVAL;
+ }
+ break;
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->request);
return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c
index ed95155c4b1d..988548efea92 100644
--- a/drivers/gpu/drm/radeon/radeon_mem.c
+++ b/drivers/gpu/drm/radeon/radeon_mem.c
@@ -139,7 +139,7 @@ static int init_heap(struct mem_block **heap, int start, int size)
if (!blocks)
return -ENOMEM;
- *heap = kmalloc(sizeof(**heap), GFP_KERNEL);
+ *heap = kzalloc(sizeof(**heap), GFP_KERNEL);
if (!*heap) {
kfree(blocks);
return -ENOMEM;
@@ -150,7 +150,6 @@ static int init_heap(struct mem_block **heap, int start, int size)
blocks->file_priv = NULL;
blocks->next = blocks->prev = *heap;
- memset(*heap, 0, sizeof(**heap));
(*heap)->file_priv = (struct drm_file *) - 1;
(*heap)->next = (*heap)->prev = blocks;
return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index aaa19dc418a0..6fabe89fa6a1 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -594,6 +594,9 @@ int radeon_pm_init(struct radeon_device *rdev)
if (rdev->pm.default_vddc)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
SET_VOLTAGE_TYPE_ASIC_VDDC);
+ if (rdev->pm.default_vddci)
+ radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+ SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
if (rdev->pm.default_mclk)
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index bc44a3d35ec6..b4ce86455707 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -3295,7 +3295,7 @@
# define RADEON_RB_BUFSZ_MASK (0x3f << 0)
# define RADEON_RB_BLKSZ_SHIFT 8
# define RADEON_RB_BLKSZ_MASK (0x3f << 8)
-# define RADEON_BUF_SWAP_32BIT (1 << 17)
+# define RADEON_BUF_SWAP_32BIT (2 << 16)
# define RADEON_MAX_FETCH_SHIFT 18
# define RADEON_MAX_FETCH_MASK (0x3 << 18)
# define RADEON_RB_NO_UPDATE (1 << 27)
diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman
index 0aa8e85a9457..2316977eb924 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/cayman
+++ b/drivers/gpu/drm/radeon/reg_srcs/cayman
@@ -208,6 +208,7 @@ cayman 0x9400
0x0002834C PA_SC_VPORT_ZMAX_15
0x00028350 SX_MISC
0x00028354 SX_SURFACE_SYNC
+0x0002835C SX_SCATTER_EXPORT_SIZE
0x00028380 SQ_VTX_SEMANTIC_0
0x00028384 SQ_VTX_SEMANTIC_1
0x00028388 SQ_VTX_SEMANTIC_2
@@ -432,6 +433,7 @@ cayman 0x9400
0x00028700 SPI_STACK_MGMT
0x00028704 SPI_WAVE_MGMT_1
0x00028708 SPI_WAVE_MGMT_2
+0x00028720 GDS_ADDR_BASE
0x00028724 GDS_ADDR_SIZE
0x00028780 CB_BLEND0_CONTROL
0x00028784 CB_BLEND1_CONTROL
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
index 0e28cae7ea43..161737a28c23 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/evergreen
+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen
@@ -44,6 +44,7 @@ evergreen 0x9400
0x00008E28 SQ_STATIC_THREAD_MGMT_3
0x00008E2C SQ_LDS_RESOURCE_MGMT
0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009014 SX_MEMORY_EXPORT_SIZE
0x00009100 SPI_CONFIG_CNTL
0x0000913C SPI_CONFIG_CNTL_1
0x00009508 TA_CNTL_AUX
@@ -442,7 +443,9 @@ evergreen 0x9400
0x000286EC SPI_COMPUTE_NUM_THREAD_X
0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x00028720 GDS_ADDR_BASE
0x00028724 GDS_ADDR_SIZE
+0x00028728 GDS_ORDERED_WAVE_PER_SE
0x00028780 CB_BLEND0_CONTROL
0x00028784 CB_BLEND1_CONTROL
0x00028788 CB_BLEND2_CONTROL
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600
index ea49752ee99c..0380c5c15f80 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/r600
+++ b/drivers/gpu/drm/radeon/reg_srcs/r600
@@ -429,6 +429,7 @@ r600 0x9400
0x00028438 SX_ALPHA_REF
0x00028410 SX_ALPHA_TEST_CONTROL
0x00028350 SX_MISC
+0x00009014 SX_MEMORY_EXPORT_SIZE
0x00009604 TC_INVALIDATE
0x00009400 TD_FILTER4
0x00009404 TD_FILTER4_1
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 1f5850e473cc..4b5d0e6974a8 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -530,7 +530,7 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
addr = addr & 0xFFFFFFFFFFFFF000ULL;
addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED;
addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
- writeq(addr, ((void __iomem *)ptr) + (i * 8));
+ writeq(addr, ptr + (i * 8));
return 0;
}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 4de51891aa6d..4720d000d440 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -778,6 +778,7 @@ static void rv770_gpu_init(struct radeon_device *rdev)
(cc_rb_backend_disable >> 16));
rdev->config.rv770.tile_config = gb_tiling_config;
+ rdev->config.rv770.backend_map = backend_map;
gb_tiling_config |= BACKEND_MAP(backend_map);
WREG32(GB_TILING_CONFIG, gb_tiling_config);
diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h
index ef940bad63f7..194303c177ad 100644
--- a/drivers/gpu/drm/sis/sis_drv.h
+++ b/drivers/gpu/drm/sis/sis_drv.h
@@ -48,8 +48,8 @@ enum sis_family {
#define SIS_BASE (dev_priv->mmio)
-#define SIS_READ(reg) DRM_READ32(SIS_BASE, reg);
-#define SIS_WRITE(reg, val) DRM_WRITE32(SIS_BASE, reg, val);
+#define SIS_READ(reg) DRM_READ32(SIS_BASE, reg)
+#define SIS_WRITE(reg, val) DRM_WRITE32(SIS_BASE, reg, val)
typedef struct drm_sis_private {
drm_local_map_t *mmio;
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 2e618b5ac465..56619f64b6bf 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -37,7 +37,7 @@
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define TTM_ASSERT_LOCKED(param)
#define TTM_DEBUG(fmt, arg...)
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c
index de41e55a944a..075daf44bce4 100644
--- a/drivers/gpu/drm/ttm/ttm_lock.c
+++ b/drivers/gpu/drm/ttm/ttm_lock.c
@@ -30,7 +30,7 @@
#include "ttm/ttm_lock.h"
#include "ttm/ttm_module.h"
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/sched.h>
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c
index ebddd443d91a..93577f2e2954 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/ttm/ttm_object.c
@@ -55,7 +55,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
struct ttm_object_file {
struct ttm_object_device *tdev;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index d948575717bf..727e93daac3b 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -40,7 +40,7 @@
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "ttm/ttm_bo_driver.h"
#include "ttm/ttm_page_alloc.h"
@@ -355,7 +355,7 @@ restart:
if (nr_free)
goto restart;
- /* Not allowed to fall tough or break because
+ /* Not allowed to fall through or break because
* following context is inside spinlock while we are
* outside here.
*/
@@ -556,7 +556,7 @@ out:
}
/**
- * Fill the given pool if there isn't enough pages and requested number of
+ * Fill the given pool if there aren't enough pages and the requested number of
* pages is small.
*/
static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
@@ -576,8 +576,8 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
pool->fill_lock = true;
- /* If allocation request is small and there is not enough
- * pages in pool we fill the pool first */
+ /* If allocation request is small and there are not enough
+ * pages in a pool we fill the pool up first. */
if (count < _manager->options.small
&& count > pool->npages) {
struct list_head new_pages;
@@ -614,9 +614,9 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
}
/**
- * Cut count nubmer of pages from the pool and put them to return list
+ * Cut 'count' number of pages from the pool and put them on the return list.
*
- * @return count of pages still to allocate to fill the request.
+ * @return count of pages still required to fulfill the request.
*/
static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
struct list_head *pages, int ttm_flags,
@@ -637,7 +637,7 @@ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
goto out;
}
/* find the last pages to include for requested number of pages. Split
- * pool to begin and halves to reduce search space. */
+ * pool to begin and halve it to reduce search space. */
if (count <= pool->npages/2) {
i = 0;
list_for_each(p, &pool->list) {
@@ -651,7 +651,7 @@ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
break;
}
}
- /* Cut count number of pages from pool */
+ /* Cut 'count' number of pages from the pool */
list_cut_position(pages, &pool->list, p);
pool->npages -= count;
count = 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index f1a52f9e7298..07ce02da78a4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -585,11 +585,10 @@ int vmw_overlay_init(struct vmw_private *dev_priv)
return -ENOSYS;
}
- overlay = kmalloc(sizeof(*overlay), GFP_KERNEL);
+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
if (!overlay)
return -ENOMEM;
- memset(overlay, 0, sizeof(*overlay));
mutex_init(&overlay->mutex);
for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
overlay->stream[i].buf = NULL;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 5408b1b7996f..bfe1bcce7f8a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -612,11 +612,9 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
srf->sizes[0].height == 64 &&
srf->format == SVGA3D_A8R8G8B8) {
- srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
- /* clear the image */
- if (srf->snooper.image) {
- memset(srf->snooper.image, 0x00, 64 * 64 * 4);
- } else {
+ /* allocate image area and clear it */
+ srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL);
+ if (!srf->snooper.image) {
DRM_ERROR("Failed to allocate cursor_image\n");
ret = -ENOMEM;
goto out_err1;
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 8a1021f2e319..c72f1c0b5e63 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1171,10 +1171,9 @@ static int vga_arb_open(struct inode *inode, struct file *file)
pr_debug("%s\n", __func__);
- priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
- memset(priv, 0, sizeof(*priv));
spin_lock_init(&priv->lock);
file->private_data = priv;
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 36ca465c00ce..306b15f39c9c 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -172,6 +172,20 @@ config HID_EZKEY
---help---
Support for Ezkey BTC 8193 keyboard.
+config HID_HOLTEK
+ tristate "Holtek On Line Grip based game controller support"
+ depends on USB_HID
+ ---help---
+ Say Y here if you have a Holtek On Line Grip based game controller.
+
+config HOLTEK_FF
+ bool "Holtek On Line Grip force feedback support"
+ depends on HID_HOLTEK
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you have a Holtek On Line Grip based game controller
+ and want to have force feedback support for it.
+
config HID_KEYTOUCH
tristate "Keytouch HID devices"
depends on USB_HID
@@ -322,6 +336,7 @@ config HID_MULTITOUCH
- Stantum multitouch panels
- Touch International Panels
- Unitec Panels
+ - XAT optical touch panels
If unsure, say N.
@@ -435,6 +450,7 @@ config HID_QUANTA
config HID_ROCCAT
tristate "Roccat special event support"
depends on USB_HID
+ select HID_ROCCAT_COMMON
---help---
Support for Roccat special events.
Say Y here if you have a Roccat mouse or keyboard and want OSD or
@@ -442,44 +458,40 @@ config HID_ROCCAT
config HID_ROCCAT_COMMON
tristate
+ depends on HID_ROCCAT
config HID_ROCCAT_ARVO
tristate "Roccat Arvo keyboard support"
depends on USB_HID
- select HID_ROCCAT
- select HID_ROCCAT_COMMON
+ depends on HID_ROCCAT
---help---
Support for Roccat Arvo keyboard.
config HID_ROCCAT_KONE
tristate "Roccat Kone Mouse support"
depends on USB_HID
- select HID_ROCCAT
- select HID_ROCCAT_COMMON
+ depends on HID_ROCCAT
---help---
Support for Roccat Kone mouse.
config HID_ROCCAT_KONEPLUS
tristate "Roccat Kone[+] mouse support"
depends on USB_HID
- select HID_ROCCAT
- select HID_ROCCAT_COMMON
+ depends on HID_ROCCAT
---help---
Support for Roccat Kone[+] mouse.
config HID_ROCCAT_KOVAPLUS
tristate "Roccat Kova[+] mouse support"
depends on USB_HID
- select HID_ROCCAT
- select HID_ROCCAT_COMMON
+ depends on HID_ROCCAT
---help---
Support for Roccat Kova[+] mouse.
config HID_ROCCAT_PYRA
tristate "Roccat Pyra mouse support"
depends on USB_HID
- select HID_ROCCAT
- select HID_ROCCAT_COMMON
+ depends on HID_ROCCAT
---help---
Support for Roccat Pyra mouse.
@@ -495,6 +507,12 @@ config HID_SONY
---help---
Support for Sony PS3 controller.
+config HID_SPEEDLINK
+ tristate "Speedlink VAD Cezanne mouse support"
+ depends on USB_HID
+ ---help---
+ Support for Speedlink Vicious and Divine Cezanne mouse.
+
config HID_SUNPLUS
tristate "Sunplus wireless desktop"
depends on USB_HID
@@ -568,6 +586,12 @@ config HID_WACOM_POWER_SUPPLY
Say Y here if you want to enable power supply status monitoring for
Wacom Bluetooth devices.
+config HID_WIIMOTE
+ tristate "Nintendo Wii Remote support"
+ depends on BT_HIDP
+ ---help---
+ Support for the Nintendo Wii Remote bluetooth device.
+
config HID_ZEROPLUS
tristate "Zeroplus based game controller support"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f8cc4ea7335a..0a0a38e9fd28 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
+obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
obj-$(CONFIG_HID_SONY) += hid-sony.o
+obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
@@ -73,6 +75,7 @@ obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
obj-$(CONFIG_HID_WACOM) += hid-wacom.o
obj-$(CONFIG_HID_WALTOP) += hid-waltop.o
+obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
index b4554288de00..121514149e0b 100644
--- a/drivers/hid/hid-axff.c
+++ b/drivers/hid/hid-axff.c
@@ -154,6 +154,7 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
error = hid_hw_open(hdev);
if (error) {
dev_err(&hdev->dev, "hw open failed\n");
+ hid_hw_stop(hdev);
return error;
}
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6f3289a57888..1a5cf0c9cfca 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1388,6 +1388,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_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) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
@@ -1426,10 +1427,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
@@ -1491,6 +1494,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
{ 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) },
@@ -1499,11 +1503,14 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
{ }
};
@@ -1771,7 +1778,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
- { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
@@ -1912,6 +1918,11 @@ static bool hid_ignore(struct hid_device *hdev)
hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST)
return true;
break;
+ case USB_VENDOR_ID_JESS:
+ if (hdev->product == USB_DEVICE_ID_JESS_YUREX &&
+ hdev->type == HID_TYPE_USBNONE)
+ return true;
+ break;
}
if (hdev->type == HID_TYPE_USBMOUSE &&
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c
index 81877c67caea..a5dc13fe367b 100644
--- a/drivers/hid/hid-emsff.c
+++ b/drivers/hid/hid-emsff.c
@@ -126,7 +126,12 @@ static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err;
}
- emsff_init(hdev);
+ ret = emsff_init(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "force feedback init failed\n");
+ hid_hw_stop(hdev);
+ goto err;
+ }
return 0;
err:
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
new file mode 100644
index 000000000000..91e3a032112b
--- /dev/null
+++ b/drivers/hid/hid-holtekff.c
@@ -0,0 +1,240 @@
+/*
+ * Force feedback support for Holtek On Line Grip based gamepads
+ *
+ * These include at least a Brazilian "Clone Joypad Super Power Fire"
+ * which uses vendor ID 0x1241 and identifies as "HOLTEK On Line Grip".
+ *
+ * Copyright (c) 2011 Anssi Hannula <anssi.hannula@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#ifdef CONFIG_HOLTEK_FF
+#include "usbhid/usbhid.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
+MODULE_DESCRIPTION("Force feedback support for Holtek On Line Grip based devices");
+
+/*
+ * These commands and parameters are currently known:
+ *
+ * byte 0: command id:
+ * 01 set effect parameters
+ * 02 play specified effect
+ * 03 stop specified effect
+ * 04 stop all effects
+ * 06 stop all effects
+ * (the difference between 04 and 06 isn't known; win driver
+ * sends 06,04 on application init, and 06 otherwise)
+ *
+ * Commands 01 and 02 need to be sent as pairs, i.e. you need to send 01
+ * before each 02.
+ *
+ * The rest of the bytes are parameters. Command 01 takes all of them, and
+ * commands 02,03 take only the effect id.
+ *
+ * byte 1:
+ * bits 0-3: effect id:
+ * 1: very strong rumble
+ * 2: periodic rumble, short intervals
+ * 3: very strong rumble
+ * 4: periodic rumble, long intervals
+ * 5: weak periodic rumble, long intervals
+ * 6: weak periodic rumble, short intervals
+ * 7: periodic rumble, short intervals
+ * 8: strong periodic rumble, short intervals
+ * 9: very strong rumble
+ * a: causes an error
+ * b: very strong periodic rumble, very short intervals
+ * c-f: nothing
+ * bit 6: right (weak) motor enabled
+ * bit 7: left (strong) motor enabled
+ *
+ * bytes 2-3: time in milliseconds, big-endian
+ * bytes 5-6: unknown (win driver seems to use at least 10e0 with effect 1
+ * and 0014 with effect 6)
+ * byte 7:
+ * bits 0-3: effect magnitude
+ */
+
+#define HOLTEKFF_MSG_LENGTH 7
+
+static const u8 start_effect_1[] = { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 stop_all4[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 stop_all6[] = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+struct holtekff_device {
+ struct hid_field *field;
+};
+
+static void holtekff_send(struct holtekff_device *holtekff,
+ struct hid_device *hid,
+ const u8 data[HOLTEKFF_MSG_LENGTH])
+{
+ int i;
+
+ for (i = 0; i < HOLTEKFF_MSG_LENGTH; i++) {
+ holtekff->field->value[i] = data[i];
+ }
+
+ dbg_hid("sending %02x %02x %02x %02x %02x %02x %02x\n", data[0],
+ data[1], data[2], data[3], data[4], data[5], data[6]);
+
+ usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT);
+}
+
+static int holtekff_play(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct holtekff_device *holtekff = data;
+ int left, right;
+ /* effect type 1, length 65535 msec */
+ u8 buf[HOLTEKFF_MSG_LENGTH] =
+ { 0x01, 0x01, 0xff, 0xff, 0x10, 0xe0, 0x00 };
+
+ left = effect->u.rumble.strong_magnitude;
+ right = effect->u.rumble.weak_magnitude;
+ dbg_hid("called with 0x%04x 0x%04x\n", left, right);
+
+ if (!left && !right) {
+ holtekff_send(holtekff, hid, stop_all6);
+ return 0;
+ }
+
+ if (left)
+ buf[1] |= 0x80;
+ if (right)
+ buf[1] |= 0x40;
+
+ /* The device takes a single magnitude, so we just sum them up. */
+ buf[6] = min(0xf, (left >> 12) + (right >> 12));
+
+ holtekff_send(holtekff, hid, buf);
+ holtekff_send(holtekff, hid, start_effect_1);
+
+ return 0;
+}
+
+static int holtekff_init(struct hid_device *hid)
+{
+ struct holtekff_device *holtekff;
+ struct hid_report *report;
+ struct hid_input *hidinput = list_entry(hid->inputs.next,
+ struct hid_input, list);
+ struct list_head *report_list =
+ &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct input_dev *dev = hidinput->input;
+ int error;
+
+ if (list_empty(report_list)) {
+ hid_err(hid, "no output report found\n");
+ return -ENODEV;
+ }
+
+ report = list_entry(report_list->next, struct hid_report, list);
+
+ if (report->maxfield < 1 || report->field[0]->report_count != 7) {
+ hid_err(hid, "unexpected output report layout\n");
+ return -ENODEV;
+ }
+
+ holtekff = kzalloc(sizeof(*holtekff), GFP_KERNEL);
+ if (!holtekff)
+ return -ENOMEM;
+
+ set_bit(FF_RUMBLE, dev->ffbit);
+
+ holtekff->field = report->field[0];
+
+ /* initialize the same way as win driver does */
+ holtekff_send(holtekff, hid, stop_all4);
+ holtekff_send(holtekff, hid, stop_all6);
+
+ error = input_ff_create_memless(dev, holtekff, holtekff_play);
+ if (error) {
+ kfree(holtekff);
+ return error;
+ }
+
+ hid_info(hid, "Force feedback for Holtek On Line Grip based devices by Anssi Hannula <anssi.hannula@iki.fi>\n");
+
+ return 0;
+}
+#else
+static inline int holtekff_init(struct hid_device *hid)
+{
+ return 0;
+}
+#endif
+
+static int holtek_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ hid_err(hdev, "parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ hid_err(hdev, "hw start failed\n");
+ goto err;
+ }
+
+ holtekff_init(hdev);
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct hid_device_id holtek_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, holtek_devices);
+
+static struct hid_driver holtek_driver = {
+ .name = "holtek",
+ .id_table = holtek_devices,
+ .probe = holtek_probe,
+};
+
+static int __init holtek_init(void)
+{
+ return hid_register_driver(&holtek_driver);
+}
+
+static void __exit holtek_exit(void)
+{
+ hid_unregister_driver(&holtek_driver);
+}
+
+module_init(holtek_init);
+module_exit(holtek_exit);
+
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index a756ee6c7df5..db63ccf21cc8 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -350,6 +350,9 @@
#define USB_VENDOR_ID_ILITEK 0x222a
#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
+#define USB_VENDOR_ID_HOLTEK 0x1241
+#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
+
#define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
@@ -472,6 +475,8 @@
#define USB_DEVICE_ID_MS_LK6K 0x00f9
#define USB_DEVICE_ID_MS_PRESENTER_8K_BT 0x0701
#define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713
+#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730
+#define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c
#define USB_VENDOR_ID_MOJO 0x8282
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
@@ -495,6 +500,9 @@
#define USB_VENDOR_ID_NEXTWINDOW 0x1926
#define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003
+#define USB_VENDOR_ID_NINTENDO 0x057e
+#define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306
+
#define USB_VENDOR_ID_NTRIG 0x1b96
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003
@@ -630,6 +638,7 @@
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005
+#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064
#define USB_VENDOR_ID_UNITEC 0x227d
#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
@@ -663,6 +672,12 @@
#define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677
#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+#define USB_VENDOR_ID_X_TENSIONS 0x1ae7
+#define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001
+
+#define USB_VENDOR_ID_XAT 0x2505
+#define USB_DEVICE_ID_XAT_CSR 0x0220
+
#define USB_VENDOR_ID_YEALINK 0x6993
#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 21f205f09250..a7f916e8fc32 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -41,6 +41,66 @@
#define LG_FF3 0x1000
#define LG_FF4 0x2000
+/* Size of the original descriptor of the Driving Force Pro wheel */
+#define DFP_RDESC_ORIG_SIZE 97
+
+/* Fixed report descriptor for Logitech Driving Force Pro wheel controller
+ *
+ * The original descriptor hides the separate throttle and brake axes in
+ * a custom vendor usage page, providing only a combined value as
+ * GenericDesktop.Y.
+ * This descriptor removes the combined Y axis and instead reports
+ * separate throttle (Y) and brake (RZ).
+ */
+static __u8 dfp_rdesc_fixed[] = {
+0x05, 0x01, /* Usage Page (Desktop), */
+0x09, 0x04, /* Usage (Joystik), */
+0xA1, 0x01, /* Collection (Application), */
+0xA1, 0x02, /* Collection (Logical), */
+0x95, 0x01, /* Report Count (1), */
+0x75, 0x0E, /* Report Size (14), */
+0x14, /* Logical Minimum (0), */
+0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */
+0x34, /* Physical Minimum (0), */
+0x46, 0xFF, 0x3F, /* Physical Maximum (16383), */
+0x09, 0x30, /* Usage (X), */
+0x81, 0x02, /* Input (Variable), */
+0x95, 0x0E, /* Report Count (14), */
+0x75, 0x01, /* Report Size (1), */
+0x25, 0x01, /* Logical Maximum (1), */
+0x45, 0x01, /* Physical Maximum (1), */
+0x05, 0x09, /* Usage Page (Button), */
+0x19, 0x01, /* Usage Minimum (01h), */
+0x29, 0x0E, /* Usage Maximum (0Eh), */
+0x81, 0x02, /* Input (Variable), */
+0x05, 0x01, /* Usage Page (Desktop), */
+0x95, 0x01, /* Report Count (1), */
+0x75, 0x04, /* Report Size (4), */
+0x25, 0x07, /* Logical Maximum (7), */
+0x46, 0x3B, 0x01, /* Physical Maximum (315), */
+0x65, 0x14, /* Unit (Degrees), */
+0x09, 0x39, /* Usage (Hat Switch), */
+0x81, 0x42, /* Input (Variable, Nullstate), */
+0x65, 0x00, /* Unit, */
+0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+0x46, 0xFF, 0x00, /* Physical Maximum (255), */
+0x75, 0x08, /* Report Size (8), */
+0x81, 0x01, /* Input (Constant), */
+0x09, 0x31, /* Usage (Y), */
+0x81, 0x02, /* Input (Variable), */
+0x09, 0x35, /* Usage (Rz), */
+0x81, 0x02, /* Input (Variable), */
+0x81, 0x01, /* Input (Constant), */
+0xC0, /* End Collection, */
+0xA1, 0x02, /* Collection (Logical), */
+0x09, 0x02, /* Usage (02h), */
+0x95, 0x07, /* Report Count (7), */
+0x91, 0x02, /* Output (Variable), */
+0xC0, /* End Collection, */
+0xC0 /* End Collection */
+};
+
+
/*
* Certain Logitech keyboards send in report #3 keys which are far
* above the logical maximum described in descriptor. This extends
@@ -74,6 +134,18 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
rdesc[47] = 0x95;
rdesc[48] = 0x0B;
}
+
+ switch (hdev->product) {
+ case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+ if (*rsize == DFP_RDESC_ORIG_SIZE) {
+ hid_info(hdev,
+ "fixing up Logitech Driving Force Pro report descriptor\n");
+ rdesc = dfp_rdesc_fixed;
+ *rsize = sizeof(dfp_rdesc_fixed);
+ }
+ break;
+ }
+
return rdesc;
}
@@ -380,7 +452,7 @@ static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
.driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
- .driver_data = LG_FF },
+ .driver_data = LG_NOGET | LG_FF },
{ 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 ),
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 0f6fc54dc196..e5c699b6c6f3 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -23,11 +23,12 @@
#include "hid-ids.h"
-#define MS_HIDINPUT 0x01
-#define MS_ERGONOMY 0x02
-#define MS_PRESENTER 0x04
-#define MS_RDESC 0x08
-#define MS_NOGET 0x10
+#define MS_HIDINPUT 0x01
+#define MS_ERGONOMY 0x02
+#define MS_PRESENTER 0x04
+#define MS_RDESC 0x08
+#define MS_NOGET 0x10
+#define MS_DUPLICATE_USAGES 0x20
/*
* Microsoft Wireless Desktop Receiver (Model 1028) has
@@ -109,6 +110,18 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
+static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if (quirks & MS_DUPLICATE_USAGES)
+ clear_bit(usage->code, *bit);
+
+ return 0;
+}
+
static int ms_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
@@ -179,8 +192,12 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_ERGONOMY | MS_RDESC },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
.driver_data = MS_PRESENTER },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
+ .driver_data = MS_ERGONOMY },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
.driver_data = MS_NOGET },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
+ .driver_data = MS_DUPLICATE_USAGES },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
.driver_data = MS_PRESENTER },
@@ -193,6 +210,7 @@ static struct hid_driver ms_driver = {
.id_table = ms_devices,
.report_fixup = ms_report_fixup,
.input_mapping = ms_input_mapping,
+ .input_mapped = ms_input_mapped,
.event = ms_event,
.probe = ms_probe,
};
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 62cac4dc3b62..58d0e7aaf088 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -727,6 +727,10 @@ static const struct hid_device_id mt_devices[] = {
{ .driver_data = MT_CLS_DEFAULT,
HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
+ /* XAT */
+ { .driver_data = MT_CLS_DEFAULT,
+ HID_USB_DEVICE(USB_VENDOR_ID_XAT,
+ USB_DEVICE_ID_XAT_CSR) },
{ }
};
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index ab19f2905d27..158b389d0fb7 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -44,8 +44,6 @@ struct pk_device {
struct pcmidi_snd *pm; /* pcmidi device context */
};
-struct pcmidi_snd;
-
struct pcmidi_sustain {
unsigned long in_use;
struct pcmidi_snd *pm;
@@ -242,7 +240,7 @@ drop_note:
return;
}
-void pcmidi_sustained_note_release(unsigned long data)
+static void pcmidi_sustained_note_release(unsigned long data)
{
struct pcmidi_sustain *pms = (struct pcmidi_sustain *)data;
@@ -250,7 +248,7 @@ void pcmidi_sustained_note_release(unsigned long data)
pms->in_use = 0;
}
-void init_sustain_timers(struct pcmidi_snd *pm)
+static void init_sustain_timers(struct pcmidi_snd *pm)
{
struct pcmidi_sustain *pms;
unsigned i;
@@ -264,7 +262,7 @@ void init_sustain_timers(struct pcmidi_snd *pm)
}
}
-void stop_sustain_timers(struct pcmidi_snd *pm)
+static void stop_sustain_timers(struct pcmidi_snd *pm)
{
struct pcmidi_sustain *pms;
unsigned i;
@@ -499,7 +497,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data)
return 1;
}
-int pcmidi_handle_report(
+static int pcmidi_handle_report(
struct pcmidi_snd *pm, unsigned report_id, u8 *data, int size)
{
int ret = 0;
@@ -518,7 +516,8 @@ int pcmidi_handle_report(
return ret;
}
-void pcmidi_setup_extra_keys(struct pcmidi_snd *pm, struct input_dev *input)
+static void pcmidi_setup_extra_keys(
+ struct pcmidi_snd *pm, struct input_dev *input)
{
/* reassigned functionality for N/A keys
MY PICTURES => KEY_WORDPROCESSOR
@@ -602,7 +601,7 @@ static struct snd_rawmidi_ops pcmidi_in_ops = {
.trigger = pcmidi_in_trigger
};
-int pcmidi_snd_initialise(struct pcmidi_snd *pm)
+static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
{
static int dev;
struct snd_card *card;
@@ -720,7 +719,7 @@ fail:
return err;
}
-int pcmidi_snd_terminate(struct pcmidi_snd *pm)
+static int pcmidi_snd_terminate(struct pcmidi_snd *pm)
{
if (pm->card) {
stop_sustain_timers(pm);
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
index 2307471d96dc..093bfad00b02 100644
--- a/drivers/hid/hid-roccat-arvo.c
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -39,7 +39,7 @@ static ssize_t arvo_sysfs_show_mode_key(struct device *dev,
int retval;
mutex_lock(&arvo->arvo_lock);
- retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+ retval = roccat_common_receive(usb_dev, ARVO_COMMAND_MODE_KEY,
&temp_buf, sizeof(struct arvo_mode_key));
mutex_unlock(&arvo->arvo_lock);
if (retval)
@@ -67,7 +67,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
temp_buf.state = state;
mutex_lock(&arvo->arvo_lock);
- retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+ retval = roccat_common_send(usb_dev, ARVO_COMMAND_MODE_KEY,
&temp_buf, sizeof(struct arvo_mode_key));
mutex_unlock(&arvo->arvo_lock);
if (retval)
@@ -87,7 +87,7 @@ static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
int retval;
mutex_lock(&arvo->arvo_lock);
- retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+ retval = roccat_common_receive(usb_dev, ARVO_COMMAND_KEY_MASK,
&temp_buf, sizeof(struct arvo_key_mask));
mutex_unlock(&arvo->arvo_lock);
if (retval)
@@ -115,7 +115,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
temp_buf.key_mask = key_mask;
mutex_lock(&arvo->arvo_lock);
- retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+ retval = roccat_common_send(usb_dev, ARVO_COMMAND_KEY_MASK,
&temp_buf, sizeof(struct arvo_key_mask));
mutex_unlock(&arvo->arvo_lock);
if (retval)
@@ -130,7 +130,7 @@ static int arvo_get_actual_profile(struct usb_device *usb_dev)
struct arvo_actual_profile temp_buf;
int retval;
- retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+ retval = roccat_common_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
&temp_buf, sizeof(struct arvo_actual_profile));
if (retval)
@@ -163,11 +163,14 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
if (retval)
return retval;
+ if (profile < 1 || profile > 5)
+ return -EINVAL;
+
temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE;
temp_buf.actual_profile = profile;
mutex_lock(&arvo->arvo_lock);
- retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+ retval = roccat_common_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
&temp_buf, sizeof(struct arvo_actual_profile));
if (!retval) {
arvo->actual_profile = profile;
@@ -225,7 +228,7 @@ static ssize_t arvo_sysfs_write_button(struct file *fp,
loff_t off, size_t count)
{
return arvo_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct arvo_button), ARVO_USB_COMMAND_BUTTON);
+ sizeof(struct arvo_button), ARVO_COMMAND_BUTTON);
}
static ssize_t arvo_sysfs_read_info(struct file *fp,
@@ -233,7 +236,7 @@ static ssize_t arvo_sysfs_read_info(struct file *fp,
loff_t off, size_t count)
{
return arvo_sysfs_read(fp, kobj, buf, off, count,
- sizeof(struct arvo_info), ARVO_USB_COMMAND_INFO);
+ sizeof(struct arvo_info), ARVO_COMMAND_INFO);
}
@@ -399,7 +402,7 @@ static int arvo_raw_event(struct hid_device *hdev,
if (size != 3)
return 0;
- if (arvo->roccat_claimed)
+ if (arvo && arvo->roccat_claimed)
arvo_report_to_chrdev(arvo, data);
return 0;
diff --git a/drivers/hid/hid-roccat-arvo.h b/drivers/hid/hid-roccat-arvo.h
index d284a781c99e..ce8415e4f009 100644
--- a/drivers/hid/hid-roccat-arvo.h
+++ b/drivers/hid/hid-roccat-arvo.h
@@ -46,19 +46,6 @@ enum arvo_commands {
ARVO_COMMAND_ACTUAL_PROFILE = 0x7,
};
-enum arvo_usb_commands {
- ARVO_USB_COMMAND_MODE_KEY = 0x303,
- /*
- * read/write
- * Read uses both index bytes as profile/key indexes
- * Write has index 0, profile/key is determined by payload
- */
- ARVO_USB_COMMAND_BUTTON = 0x304,
- ARVO_USB_COMMAND_INFO = 0x305,
- ARVO_USB_COMMAND_KEY_MASK = 0x306,
- ARVO_USB_COMMAND_ACTUAL_PROFILE = 0x307,
-};
-
struct arvo_special_report {
uint8_t unknown1; /* always 0x01 */
uint8_t event;
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c
index 13b1eb0c8c65..edf898dee28b 100644
--- a/drivers/hid/hid-roccat-common.c
+++ b/drivers/hid/hid-roccat-common.c
@@ -11,10 +11,16 @@
* any later version.
*/
+#include <linux/hid.h>
#include <linux/slab.h>
#include "hid-roccat-common.h"
-int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+static inline uint16_t roccat_common_feature_report(uint8_t report_id)
+{
+ return 0x300 | report_id;
+}
+
+int roccat_common_receive(struct usb_device *usb_dev, uint report_id,
void *data, uint size)
{
char *buf;
@@ -25,9 +31,10 @@ int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
return -ENOMEM;
len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
- USB_REQ_CLEAR_FEATURE,
+ HID_REQ_GET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+ roccat_common_feature_report(report_id),
+ 0, buf, size, USB_CTRL_SET_TIMEOUT);
memcpy(data, buf, size);
kfree(buf);
@@ -35,7 +42,7 @@ int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
}
EXPORT_SYMBOL_GPL(roccat_common_receive);
-int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+int roccat_common_send(struct usb_device *usb_dev, uint report_id,
void const *data, uint size)
{
char *buf;
@@ -48,9 +55,10 @@ int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
memcpy(buf, data, size);
len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
- USB_REQ_SET_CONFIGURATION,
+ HID_REQ_SET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+ roccat_common_feature_report(report_id),
+ 0, buf, size, USB_CTRL_SET_TIMEOUT);
kfree(buf);
return ((len < 0) ? len : ((len != size) ? -EIO : 0));
diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h
index fe45fae05bb9..9a5bc61f9699 100644
--- a/drivers/hid/hid-roccat-common.h
+++ b/drivers/hid/hid-roccat-common.h
@@ -15,9 +15,9 @@
#include <linux/usb.h>
#include <linux/types.h>
-int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+int roccat_common_receive(struct usb_device *usb_dev, uint report_id,
void *data, uint size);
-int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+int roccat_common_send(struct usb_device *usb_dev, uint report_id,
void const *data, uint size);
#endif
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index a57838d15267..2b8f3a31ffb3 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -37,6 +37,47 @@
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+static int kone_receive(struct usb_device *usb_dev, uint usb_command,
+ void *data, uint size)
+{
+ char *buf;
+ int len;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+ HID_REQ_GET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+ usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+ memcpy(data, buf, size);
+ kfree(buf);
+ return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+
+static int kone_send(struct usb_device *usb_dev, uint usb_command,
+ void const *data, uint size)
+{
+ char *buf;
+ int len;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ memcpy(buf, data, size);
+
+ len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+ HID_REQ_SET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+ kfree(buf);
+ return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+
/* kone_class is used for creating sysfs attributes via roccat char device */
static struct class *kone_class;
@@ -68,7 +109,7 @@ static int kone_check_write(struct usb_device *usb_dev)
*/
msleep(80);
- retval = roccat_common_receive(usb_dev,
+ retval = kone_receive(usb_dev,
kone_command_confirm_write, &data, 1);
if (retval)
return retval;
@@ -96,7 +137,7 @@ static int kone_check_write(struct usb_device *usb_dev)
static int kone_get_settings(struct usb_device *usb_dev,
struct kone_settings *buf)
{
- return roccat_common_receive(usb_dev, kone_command_settings, buf,
+ return kone_receive(usb_dev, kone_command_settings, buf,
sizeof(struct kone_settings));
}
@@ -109,7 +150,7 @@ static int kone_set_settings(struct usb_device *usb_dev,
struct kone_settings const *settings)
{
int retval;
- retval = roccat_common_send(usb_dev, kone_command_settings,
+ retval = kone_send(usb_dev, kone_command_settings,
settings, sizeof(struct kone_settings));
if (retval)
return retval;
@@ -182,7 +223,7 @@ static int kone_get_weight(struct usb_device *usb_dev, int *result)
int retval;
uint8_t data;
- retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1);
+ retval = kone_receive(usb_dev, kone_command_weight, &data, 1);
if (retval)
return retval;
@@ -201,7 +242,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
int retval;
uint16_t data;
- retval = roccat_common_receive(usb_dev, kone_command_firmware_version,
+ retval = kone_receive(usb_dev, kone_command_firmware_version,
&data, 2);
if (retval)
return retval;
@@ -384,7 +425,7 @@ static int kone_tcu_command(struct usb_device *usb_dev, int number)
{
unsigned char value;
value = number;
- return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1);
+ return kone_send(usb_dev, kone_command_calibrate, &value, 1);
}
/*
@@ -791,6 +832,9 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
if (size != sizeof(struct kone_mouse_event))
return 0;
+ if (kone == NULL)
+ return 0;
+
/*
* Firmware 1.38 introduced new behaviour for tilt and special buttons.
* Pressed button is reported in each movement event.
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h
index 4109a028e138..64abb5b8a59a 100644
--- a/drivers/hid/hid-roccat-kone.h
+++ b/drivers/hid/hid-roccat-kone.h
@@ -166,7 +166,7 @@ enum kone_mouse_events {
/* osd events are thought to be display on screen */
kone_mouse_event_osd_dpi = 0xa0,
kone_mouse_event_osd_profile = 0xb0,
- /* TODO clarify meaning and occurrence of kone_mouse_event_calibration */
+ /* TODO clarify meaning and occurence of kone_mouse_event_calibration */
kone_mouse_event_calibration = 0xc0,
kone_mouse_event_call_overlong_macro = 0xe0,
/* switch events notify if user changed values with mousebutton click */
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 5b640a7a15a7..59e47770fa10 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -50,7 +50,7 @@ static int koneplus_send_control(struct usb_device *usb_dev, uint value,
control.value = value;
control.request = request;
- return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+ return roccat_common_send(usb_dev, KONEPLUS_COMMAND_CONTROL,
&control, sizeof(struct koneplus_control));
}
@@ -60,7 +60,7 @@ static int koneplus_receive_control_status(struct usb_device *usb_dev)
struct koneplus_control control;
do {
- retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+ retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_CONTROL,
&control, sizeof(struct koneplus_control));
/* check if we get a completely wrong answer */
@@ -120,7 +120,7 @@ static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
static int koneplus_get_info(struct usb_device *usb_dev,
struct koneplus_info *buf)
{
- return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
+ return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_INFO,
buf, sizeof(struct koneplus_info));
}
@@ -134,14 +134,14 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev,
if (retval)
return retval;
- return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+ return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
buf, sizeof(struct koneplus_profile_settings));
}
static int koneplus_set_profile_settings(struct usb_device *usb_dev,
struct koneplus_profile_settings const *settings)
{
- return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+ return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
settings, sizeof(struct koneplus_profile_settings));
}
@@ -155,14 +155,14 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
if (retval)
return retval;
- return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+ return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
buf, sizeof(struct koneplus_profile_buttons));
}
static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
struct koneplus_profile_buttons const *buttons)
{
- return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+ return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
buttons, sizeof(struct koneplus_profile_buttons));
}
@@ -172,7 +172,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev)
struct koneplus_actual_profile buf;
int retval;
- retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
+ retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
&buf, sizeof(struct koneplus_actual_profile));
return retval ? retval : buf.actual_profile;
@@ -187,7 +187,7 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev,
buf.size = sizeof(struct koneplus_actual_profile);
buf.actual_profile = new_profile;
- return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
+ return koneplus_send(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
&buf, sizeof(struct koneplus_actual_profile));
}
@@ -240,12 +240,20 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
return real_size;
}
+static ssize_t koneplus_sysfs_write_talk(struct file *fp,
+ struct kobject *kobj, struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ return koneplus_sysfs_write(fp, kobj, buf, off, count,
+ sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK);
+}
+
static ssize_t koneplus_sysfs_write_macro(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
return koneplus_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO);
+ sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO);
}
static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
@@ -253,7 +261,7 @@ static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
loff_t off, size_t count)
{
return koneplus_sysfs_read(fp, kobj, buf, off, count,
- sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
+ sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
}
static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
@@ -261,7 +269,7 @@ static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
loff_t off, size_t count)
{
return koneplus_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
+ sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
}
static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
@@ -269,7 +277,7 @@ static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
loff_t off, size_t count)
{
return koneplus_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU);
+ sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU);
}
static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
@@ -277,7 +285,7 @@ static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
loff_t off, size_t count)
{
return koneplus_sysfs_read(fp, kobj, buf, off, count,
- sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU);
+ sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU);
}
static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
@@ -423,6 +431,9 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
if (retval)
return retval;
+ if (profile > 4)
+ return -EINVAL;
+
mutex_lock(&koneplus->koneplus_lock);
retval = koneplus_set_actual_profile(usb_dev, profile);
@@ -431,7 +442,7 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
return retval;
}
- koneplus->actual_profile = profile;
+ koneplus_profile_activated(koneplus, profile);
roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE;
roccat_report.data1 = profile + 1;
@@ -557,6 +568,11 @@ static struct bin_attribute koneplus_bin_attributes[] = {
.size = sizeof(struct koneplus_macro),
.write = koneplus_sysfs_write_macro
},
+ {
+ .attr = { .name = "talk", .mode = 0220 },
+ .size = sizeof(struct koneplus_talk),
+ .write = koneplus_sysfs_write_talk
+ },
__ATTR_NULL
};
@@ -738,6 +754,9 @@ static int koneplus_raw_event(struct hid_device *hdev,
!= USB_INTERFACE_PROTOCOL_MOUSE)
return 0;
+ if (koneplus == NULL)
+ return 0;
+
koneplus_keep_values_up_to_date(koneplus, data);
if (koneplus->roccat_claimed)
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h
index c57a376ab8ae..c03332a4fa9a 100644
--- a/drivers/hid/hid-roccat-koneplus.h
+++ b/drivers/hid/hid-roccat-koneplus.h
@@ -14,6 +14,12 @@
#include <linux/types.h>
+struct koneplus_talk {
+ uint8_t command; /* KONEPLUS_COMMAND_TALK */
+ uint8_t size; /* always 0x10 */
+ uint8_t data[14];
+} __packed;
+
/*
* case 1: writes request 80 and reads value 1
*
@@ -137,26 +143,14 @@ enum koneplus_commands {
KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
KONEPLUS_COMMAND_MACRO = 0x8,
KONEPLUS_COMMAND_INFO = 0x9,
+ KONEPLUS_COMMAND_TCU = 0xc,
KONEPLUS_COMMAND_E = 0xe,
KONEPLUS_COMMAND_SENSOR = 0xf,
+ KONEPLUS_COMMAND_TALK = 0x10,
KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b,
KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
};
-enum koneplus_usb_commands {
- KONEPLUS_USB_COMMAND_CONTROL = 0x304,
- KONEPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
- KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
- KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
- KONEPLUS_USB_COMMAND_MACRO = 0x308,
- KONEPLUS_USB_COMMAND_INFO = 0x309,
- KONEPLUS_USB_COMMAND_TCU = 0x30c,
- KONEPLUS_USB_COMMAND_E = 0x30e,
- KONEPLUS_USB_COMMAND_SENSOR = 0x30f,
- KONEPLUS_USB_COMMAND_FIRMWARE_WRITE = 0x31b,
- KONEPLUS_USB_COMMAND_FIRMWARE_WRITE_CONTROL = 0x31c,
-};
-
enum koneplus_mouse_report_numbers {
KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1,
KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
@@ -193,6 +187,7 @@ enum koneplus_mouse_report_button_types {
* data2 = action
*/
KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
+ KONEPLUS_MOUSE_REPORT_TALK = 0xff,
};
enum koneplus_mouse_report_button_action {
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index 984be2f8967e..1f8336e3f584 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -58,7 +58,7 @@ static int kovaplus_send_control(struct usb_device *usb_dev, uint value,
control.value = value;
control.request = request;
- retval = roccat_common_send(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+ retval = roccat_common_send(usb_dev, KOVAPLUS_COMMAND_CONTROL,
&control, sizeof(struct kovaplus_control));
return retval;
@@ -70,7 +70,7 @@ static int kovaplus_receive_control_status(struct usb_device *usb_dev)
struct kovaplus_control control;
do {
- retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+ retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_CONTROL,
&control, sizeof(struct kovaplus_control));
/* check if we get a completely wrong answer */
@@ -90,7 +90,7 @@ static int kovaplus_receive_control_status(struct usb_device *usb_dev)
if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
return -EINVAL;
- hid_err(usb_dev, "kovaplus_receive_control_status: "
+ hid_err(usb_dev, "roccat_common_receive_control_status: "
"unknown response value 0x%x\n", control.value);
return -EINVAL;
} while (1);
@@ -119,7 +119,7 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
static int kovaplus_get_info(struct usb_device *usb_dev,
struct kovaplus_info *buf)
{
- return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_INFO,
+ return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
buf, sizeof(struct kovaplus_info));
}
@@ -133,14 +133,14 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
if (retval)
return retval;
- return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+ return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
buf, sizeof(struct kovaplus_profile_settings));
}
static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
struct kovaplus_profile_settings const *settings)
{
- return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+ return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
settings, sizeof(struct kovaplus_profile_settings));
}
@@ -154,14 +154,14 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
if (retval)
return retval;
- return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+ return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
buf, sizeof(struct kovaplus_profile_buttons));
}
static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
struct kovaplus_profile_buttons const *buttons)
{
- return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+ return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
buttons, sizeof(struct kovaplus_profile_buttons));
}
@@ -171,7 +171,7 @@ static int kovaplus_get_actual_profile(struct usb_device *usb_dev)
struct kovaplus_actual_profile buf;
int retval;
- retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+ retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE,
&buf, sizeof(struct kovaplus_actual_profile));
return retval ? retval : buf.actual_profile;
@@ -186,7 +186,7 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
buf.size = sizeof(struct kovaplus_actual_profile);
buf.actual_profile = new_profile;
- return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+ return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE,
&buf, sizeof(struct kovaplus_actual_profile));
}
@@ -337,7 +337,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
mutex_lock(&kovaplus->kovaplus_lock);
retval = kovaplus_set_actual_profile(usb_dev, profile);
- kovaplus->actual_profile = profile;
+ kovaplus_profile_activated(kovaplus, profile);
mutex_unlock(&kovaplus->kovaplus_lock);
if (retval)
return retval;
@@ -662,6 +662,9 @@ static int kovaplus_raw_event(struct hid_device *hdev,
!= USB_INTERFACE_PROTOCOL_MOUSE)
return 0;
+ if (kovaplus == NULL)
+ return 0;
+
kovaplus_keep_values_up_to_date(kovaplus, data);
if (kovaplus->roccat_claimed)
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h
index ce40607d21c7..fb2aed44a8e0 100644
--- a/drivers/hid/hid-roccat-kovaplus.h
+++ b/drivers/hid/hid-roccat-kovaplus.h
@@ -83,15 +83,6 @@ enum kovaplus_commands {
KOVAPLUS_COMMAND_A = 0xa,
};
-enum kovaplus_usb_commands {
- KOVAPLUS_USB_COMMAND_CONTROL = 0x304,
- KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
- KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
- KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
- KOVAPLUS_USB_COMMAND_INFO = 0x309,
- KOVAPLUS_USB_COMMAND_A = 0x30a,
-};
-
enum kovaplus_mouse_report_numbers {
KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1,
KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 38280c055a19..8140776bd8c5 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -53,7 +53,7 @@ static int pyra_send_control(struct usb_device *usb_dev, int value,
control.value = value;
control.request = request;
- return roccat_common_send(usb_dev, PYRA_USB_COMMAND_CONTROL,
+ return roccat_common_send(usb_dev, PYRA_COMMAND_CONTROL,
&control, sizeof(struct pyra_control));
}
@@ -64,7 +64,7 @@ static int pyra_receive_control_status(struct usb_device *usb_dev)
do {
msleep(10);
- retval = roccat_common_receive(usb_dev, PYRA_USB_COMMAND_CONTROL,
+ retval = roccat_common_receive(usb_dev, PYRA_COMMAND_CONTROL,
&control, sizeof(struct pyra_control));
/* requested too early, try again */
@@ -89,7 +89,7 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
if (retval)
return retval;
- return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS,
+ return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS,
buf, sizeof(struct pyra_profile_settings));
}
@@ -101,20 +101,20 @@ static int pyra_get_profile_buttons(struct usb_device *usb_dev,
PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
if (retval)
return retval;
- return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS,
+ return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS,
buf, sizeof(struct pyra_profile_buttons));
}
static int pyra_get_settings(struct usb_device *usb_dev,
struct pyra_settings *buf)
{
- return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_SETTINGS,
+ return roccat_common_receive(usb_dev, PYRA_COMMAND_SETTINGS,
buf, sizeof(struct pyra_settings));
}
static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
{
- return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_INFO,
+ return roccat_common_receive(usb_dev, PYRA_COMMAND_INFO,
buf, sizeof(struct pyra_info));
}
@@ -131,26 +131,22 @@ static int pyra_send(struct usb_device *usb_dev, uint command,
static int pyra_set_profile_settings(struct usb_device *usb_dev,
struct pyra_profile_settings const *settings)
{
- return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, settings,
+ return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, settings,
sizeof(struct pyra_profile_settings));
}
static int pyra_set_profile_buttons(struct usb_device *usb_dev,
struct pyra_profile_buttons const *buttons)
{
- return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, buttons,
+ return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, buttons,
sizeof(struct pyra_profile_buttons));
}
static int pyra_set_settings(struct usb_device *usb_dev,
struct pyra_settings const *settings)
{
- int retval;
- retval = roccat_common_send(usb_dev, PYRA_USB_COMMAND_SETTINGS, settings,
+ return pyra_send(usb_dev, PYRA_COMMAND_SETTINGS, settings,
sizeof(struct pyra_settings));
- if (retval)
- return retval;
- return pyra_receive_control_status(usb_dev);
}
static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
@@ -641,6 +637,9 @@ static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report,
!= USB_INTERFACE_PROTOCOL_MOUSE)
return 0;
+ if (pyra == NULL)
+ return 0;
+
pyra_keep_values_up_to_date(pyra, data);
if (pyra->roccat_claimed)
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h
index 14cbbe1621e0..0442d7fa2dcf 100644
--- a/drivers/hid/hid-roccat-pyra.h
+++ b/drivers/hid/hid-roccat-pyra.h
@@ -83,15 +83,6 @@ enum pyra_commands {
PYRA_COMMAND_B = 0xb
};
-enum pyra_usb_commands {
- PYRA_USB_COMMAND_CONTROL = 0x304,
- PYRA_USB_COMMAND_SETTINGS = 0x305,
- PYRA_USB_COMMAND_PROFILE_SETTINGS = 0x306,
- PYRA_USB_COMMAND_PROFILE_BUTTONS = 0x307,
- PYRA_USB_COMMAND_INFO = 0x309,
- PYRA_USB_COMMAND_B = 0x30b /* writes 3 bytes */
-};
-
enum pyra_mouse_report_numbers {
PYRA_MOUSE_REPORT_NUMBER_HID = 1,
PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2,
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 936c911fdca6..5cd25bd907f8 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -28,6 +28,12 @@
#define SIXAXIS_CONTROLLER_USB (1 << 1)
#define SIXAXIS_CONTROLLER_BT (1 << 2)
+static const u8 sixaxis_rdesc_fixup[] = {
+ 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
+ 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF,
+ 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02
+};
+
struct sony_sc {
unsigned long quirks;
};
@@ -43,9 +49,37 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n");
rdesc[55] = 0x06;
}
+
+ /* The HID descriptor exposed over BT has a trailing zero byte */
+ if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) ||
+ ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) &&
+ rdesc[83] == 0x75) {
+ hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n");
+ memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup,
+ sizeof(sixaxis_rdesc_fixup));
+ }
return rdesc;
}
+static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
+ __u8 *rd, int size)
+{
+ struct sony_sc *sc = hid_get_drvdata(hdev);
+
+ /* Sixaxis HID report has acclerometers/gyro with MSByte first, this
+ * has to be BYTE_SWAPPED before passing up to joystick interface
+ */
+ if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
+ rd[0] == 0x01 && size == 49) {
+ swap(rd[41], rd[42]);
+ swap(rd[43], rd[44]);
+ swap(rd[45], rd[46]);
+ swap(rd[47], rd[48]);
+ }
+
+ return 0;
+}
+
/*
* The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
* like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
@@ -194,6 +228,7 @@ static struct hid_driver sony_driver = {
.probe = sony_probe,
.remove = sony_remove,
.report_fixup = sony_report_fixup,
+ .raw_event = sony_raw_event
};
static int __init sony_init(void)
diff --git a/drivers/hid/hid-speedlink.c b/drivers/hid/hid-speedlink.c
new file mode 100644
index 000000000000..602013741718
--- /dev/null
+++ b/drivers/hid/hid-speedlink.c
@@ -0,0 +1,89 @@
+/*
+ * HID driver for Speedlink Vicious and Divine Cezanne (USB mouse).
+ * Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from
+ * the HID descriptor.
+ *
+ * Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+
+static const struct hid_device_id speedlink_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)},
+ { }
+};
+
+static int speedlink_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ /*
+ * The Cezanne mouse has a second "keyboard" USB endpoint for it is
+ * able to map keyboard events to the button presses.
+ * It sends a standard keyboard report descriptor, though, whose
+ * LEDs we ignore.
+ */
+ switch (usage->hid & HID_USAGE_PAGE) {
+ case HID_UP_LED:
+ return -1;
+ }
+ return 0;
+}
+
+static int speedlink_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ /* No other conditions due to usage_table. */
+ /* Fix "jumpy" cursor (invalid events sent by device). */
+ if (value == 256)
+ return 1;
+ /* Drop useless distance 0 events (on button clicks etc.) as well */
+ if (value == 0)
+ return 1;
+
+ return 0;
+}
+
+MODULE_DEVICE_TABLE(hid, speedlink_devices);
+
+static const struct hid_usage_id speedlink_grabbed_usages[] = {
+ { HID_GD_X, EV_REL, 0 },
+ { HID_GD_Y, EV_REL, 1 },
+ { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver speedlink_driver = {
+ .name = "speedlink",
+ .id_table = speedlink_devices,
+ .usage_table = speedlink_grabbed_usages,
+ .input_mapping = speedlink_input_mapping,
+ .event = speedlink_event,
+};
+
+static int __init speedlink_init(void)
+{
+ return hid_register_driver(&speedlink_driver);
+}
+
+static void __exit speedlink_exit(void)
+{
+ hid_unregister_driver(&speedlink_driver);
+}
+
+module_init(speedlink_init);
+module_exit(speedlink_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index 05fdc85a76e5..e15732f1a22d 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -343,6 +343,193 @@ static __u8 wp8060u_rdesc_fixed[] = {
};
/*
+ * Original WP1062 report descriptor.
+ *
+ * Only report ID 9 is actually used.
+ *
+ * Usage Page (Digitizer), ; Digitizer (0Dh)
+ * Usage (Pen), ; Pen (02h, application collection)
+ * Collection (Application),
+ * Report ID (7),
+ * Usage (Stylus), ; Stylus (20h, logical collection)
+ * Collection (Physical),
+ * Usage (Tip Switch), ; Tip switch (42h, momentary control)
+ * Usage (Barrel Switch), ; Barrel switch (44h, momentary control)
+ * Usage (Eraser), ; Eraser (45h, momentary control)
+ * Logical Minimum (0),
+ * Logical Maximum (1),
+ * Report Size (1),
+ * Report Count (3),
+ * Input (Variable),
+ * Report Count (3),
+ * Input (Constant, Variable),
+ * Usage (In Range), ; In range (32h, momentary control)
+ * Report Count (1),
+ * Input (Variable),
+ * Report Count (1),
+ * Input (Constant, Variable),
+ * Usage Page (Desktop), ; Generic desktop controls (01h)
+ * Usage (X), ; X (30h, dynamic value)
+ * Report Size (16),
+ * Report Count (1),
+ * Push,
+ * Unit Exponent (13),
+ * Unit (Inch),
+ * Physical Minimum (0),
+ * Physical Maximum (10000),
+ * Logical Maximum (20000),
+ * Input (Variable),
+ * Usage (Y), ; Y (31h, dynamic value)
+ * Physical Maximum (6583),
+ * Logical Maximum (13166),
+ * Input (Variable),
+ * Pop,
+ * Usage Page (Digitizer), ; Digitizer (0Dh)
+ * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value)
+ * Logical Maximum (1023),
+ * Input (Variable),
+ * Report Size (16),
+ * End Collection,
+ * End Collection,
+ * Usage Page (Desktop), ; Generic desktop controls (01h)
+ * Usage (Mouse), ; Mouse (02h, application collection)
+ * Collection (Application),
+ * Report ID (8),
+ * Usage (Pointer), ; Pointer (01h, physical collection)
+ * Collection (Physical),
+ * Usage Page (Button), ; Button (09h)
+ * Usage Minimum (01h),
+ * Usage Maximum (03h),
+ * Logical Minimum (0),
+ * Logical Maximum (1),
+ * Report Count (3),
+ * Report Size (1),
+ * Input (Variable),
+ * Report Count (5),
+ * Input (Constant),
+ * Usage Page (Desktop), ; Generic desktop controls (01h)
+ * Usage (X), ; X (30h, dynamic value)
+ * Usage (Y), ; Y (31h, dynamic value)
+ * Usage (Wheel), ; Wheel (38h, dynamic value)
+ * Usage (00h),
+ * Logical Minimum (-127),
+ * Logical Maximum (127),
+ * Report Size (8),
+ * Report Count (4),
+ * Input (Variable, Relative),
+ * End Collection,
+ * End Collection,
+ * Usage Page (Desktop), ; Generic desktop controls (01h)
+ * Usage (Mouse), ; Mouse (02h, application collection)
+ * Collection (Application),
+ * Report ID (9),
+ * Usage (Pointer), ; Pointer (01h, physical collection)
+ * Collection (Physical),
+ * Usage Page (Button), ; Button (09h)
+ * Usage Minimum (01h),
+ * Usage Maximum (03h),
+ * Logical Minimum (0),
+ * Logical Maximum (1),
+ * Report Count (3),
+ * Report Size (1),
+ * Input (Variable),
+ * Report Count (4),
+ * Input (Constant),
+ * Usage Page (Digitizer), ; Digitizer (0Dh)
+ * Usage (In Range), ; In range (32h, momentary control)
+ * Report Count (1),
+ * Input (Variable),
+ * Usage Page (Desktop), ; Generic desktop controls (01h)
+ * Usage (X), ; X (30h, dynamic value)
+ * Report Size (16),
+ * Report Count (1),
+ * Push,
+ * Unit Exponent (13),
+ * Unit (Inch),
+ * Physical Minimum (0),
+ * Physical Maximum (10000),
+ * Logical Maximum (20000),
+ * Input (Variable),
+ * Usage (Y), ; Y (31h, dynamic value)
+ * Physical Maximum (6583),
+ * Logical Maximum (13166),
+ * Input (Variable),
+ * Pop,
+ * Usage Page (Digitizer), ; Digitizer (0Dh)
+ * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value)
+ * Logical Maximum (1023),
+ * Report Count (1),
+ * Report Size (16),
+ * Input (Variable),
+ * End Collection,
+ * End Collection,
+ * Usage Page (Desktop), ; Generic desktop controls (01h)
+ * Usage (00h),
+ * Collection (Application),
+ * Report ID (4),
+ * Logical Minimum (0),
+ * Logical Maximum (255),
+ * Usage (00h),
+ * Report Size (8),
+ * Report Count (3),
+ * Feature (Variable),
+ * End Collection
+ */
+
+/* Size of the original descriptor of WP1062 tablet */
+#define WP1062_RDESC_ORIG_SIZE 254
+
+/*
+ * Fixed WP1062 report descriptor.
+ *
+ * Removed unused reports, corrected second barrel button usage code, physical
+ * units.
+ */
+static __u8 wp1062_rdesc_fixed[] = {
+ 0x05, 0x0D, /* Usage Page (Digitizer), */
+ 0x09, 0x02, /* Usage (Pen), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x09, /* Report ID (9), */
+ 0x09, 0x20, /* Usage (Stylus), */
+ 0xA0, /* Collection (Physical), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x09, 0x42, /* Usage (Tip Switch), */
+ 0x09, 0x44, /* Usage (Barrel Switch), */
+ 0x09, 0x46, /* Usage (Tablet Pick), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x04, /* Report Count (4), */
+ 0x81, 0x01, /* Input (Constant), */
+ 0x09, 0x32, /* Usage (In Range), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x14, /* Logical Minimum (0), */
+ 0xA4, /* Push, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x55, 0xFD, /* Unit Exponent (-3), */
+ 0x65, 0x13, /* Unit (Inch), */
+ 0x34, /* Physical Minimum (0), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x46, 0x10, 0x27, /* Physical Maximum (10000), */
+ 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x46, 0xB7, 0x19, /* Physical Maximum (6583), */
+ 0x26, 0x6E, 0x33, /* Logical Maximum (13166), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xB4, /* Pop, */
+ 0x09, 0x30, /* Usage (Tip Pressure), */
+ 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0 /* End Collection */
+};
+
+/*
* Original PF1209 report descriptor.
*
* The descriptor is similar to WPXXXXU descriptors, with an addition of a
@@ -584,6 +771,12 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize = sizeof(wp8060u_rdesc_fixed);
}
break;
+ case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062:
+ if (*rsize == WP1062_RDESC_ORIG_SIZE) {
+ rdesc = wp1062_rdesc_fixed;
+ *rsize = sizeof(wp1062_rdesc_fixed);
+ }
+ break;
}
return rdesc;
@@ -598,6 +791,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+ USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
{ }
};
MODULE_DEVICE_TABLE(hid, uclogic_devices);
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
new file mode 100644
index 000000000000..a594383ce03d
--- /dev/null
+++ b/drivers/hid/hid-wiimote.c
@@ -0,0 +1,489 @@
+/*
+ * HID driver for Nintendo Wiimote devices
+ * Copyright (c) 2011 David Herrmann
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify 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/atomic.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include "hid-ids.h"
+
+#define WIIMOTE_VERSION "0.1"
+#define WIIMOTE_NAME "Nintendo Wii Remote"
+#define WIIMOTE_BUFSIZE 32
+
+struct wiimote_buf {
+ __u8 data[HID_MAX_BUFFER_SIZE];
+ size_t size;
+};
+
+struct wiimote_state {
+ spinlock_t lock;
+ __u8 flags;
+};
+
+struct wiimote_data {
+ atomic_t ready;
+ struct hid_device *hdev;
+ struct input_dev *input;
+
+ spinlock_t qlock;
+ __u8 head;
+ __u8 tail;
+ struct wiimote_buf outq[WIIMOTE_BUFSIZE];
+ struct work_struct worker;
+
+ 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_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
+ WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
+
+enum wiiproto_reqs {
+ WIIPROTO_REQ_LED = 0x11,
+ WIIPROTO_REQ_DRM_K = 0x30,
+};
+
+enum wiiproto_keys {
+ WIIPROTO_KEY_LEFT,
+ WIIPROTO_KEY_RIGHT,
+ WIIPROTO_KEY_UP,
+ WIIPROTO_KEY_DOWN,
+ WIIPROTO_KEY_PLUS,
+ WIIPROTO_KEY_MINUS,
+ WIIPROTO_KEY_ONE,
+ WIIPROTO_KEY_TWO,
+ WIIPROTO_KEY_A,
+ WIIPROTO_KEY_B,
+ WIIPROTO_KEY_HOME,
+ WIIPROTO_KEY_COUNT
+};
+
+static __u16 wiiproto_keymap[] = {
+ KEY_LEFT, /* WIIPROTO_KEY_LEFT */
+ KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */
+ KEY_UP, /* WIIPROTO_KEY_UP */
+ KEY_DOWN, /* WIIPROTO_KEY_DOWN */
+ KEY_NEXT, /* WIIPROTO_KEY_PLUS */
+ KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */
+ BTN_1, /* WIIPROTO_KEY_ONE */
+ BTN_2, /* WIIPROTO_KEY_TWO */
+ BTN_A, /* WIIPROTO_KEY_A */
+ BTN_B, /* WIIPROTO_KEY_B */
+ BTN_MODE, /* WIIPROTO_KEY_HOME */
+};
+
+#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
+ dev))
+
+static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
+ size_t count)
+{
+ __u8 *buf;
+ ssize_t ret;
+
+ if (!hdev->hid_output_raw_report)
+ return -ENODEV;
+
+ buf = kmemdup(buffer, count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT);
+
+ kfree(buf);
+ return ret;
+}
+
+static void wiimote_worker(struct work_struct *work)
+{
+ struct wiimote_data *wdata = container_of(work, struct wiimote_data,
+ worker);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->qlock, flags);
+
+ while (wdata->head != wdata->tail) {
+ spin_unlock_irqrestore(&wdata->qlock, flags);
+ wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data,
+ wdata->outq[wdata->tail].size);
+ spin_lock_irqsave(&wdata->qlock, flags);
+
+ wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE;
+ }
+
+ spin_unlock_irqrestore(&wdata->qlock, flags);
+}
+
+static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer,
+ size_t count)
+{
+ unsigned long flags;
+ __u8 newhead;
+
+ if (count > HID_MAX_BUFFER_SIZE) {
+ hid_warn(wdata->hdev, "Sending too large output report\n");
+ return;
+ }
+
+ /*
+ * Copy new request into our output queue and check whether the
+ * queue is full. If it is full, discard this request.
+ * If it is empty we need to start a new worker that will
+ * send out the buffer to the hid device.
+ * If the queue is not empty, then there must be a worker
+ * that is currently sending out our buffer and this worker
+ * will reschedule itself until the queue is empty.
+ */
+
+ spin_lock_irqsave(&wdata->qlock, flags);
+
+ memcpy(wdata->outq[wdata->head].data, buffer, count);
+ wdata->outq[wdata->head].size = count;
+ newhead = (wdata->head + 1) % WIIMOTE_BUFSIZE;
+
+ if (wdata->head == wdata->tail) {
+ wdata->head = newhead;
+ schedule_work(&wdata->worker);
+ } else if (newhead != wdata->tail) {
+ wdata->head = newhead;
+ } else {
+ hid_warn(wdata->hdev, "Output queue is full");
+ }
+
+ spin_unlock_irqrestore(&wdata->qlock, flags);
+}
+
+static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
+{
+ __u8 cmd[2];
+
+ leds &= WIIPROTO_FLAGS_LEDS;
+ if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds)
+ return;
+ wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds;
+
+ cmd[0] = WIIPROTO_REQ_LED;
+ cmd[1] = 0;
+
+ if (leds & WIIPROTO_FLAG_LED1)
+ cmd[1] |= 0x10;
+ if (leds & WIIPROTO_FLAG_LED2)
+ cmd[1] |= 0x20;
+ if (leds & WIIPROTO_FLAG_LED3)
+ cmd[1] |= 0x40;
+ if (leds & WIIPROTO_FLAG_LED4)
+ cmd[1] |= 0x80;
+
+ wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+#define wiifs_led_show_set(num) \
+static ssize_t wiifs_led_show_##num(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct wiimote_data *wdata = dev_to_wii(dev); \
+ unsigned long flags; \
+ int state; \
+ \
+ if (!atomic_read(&wdata->ready)) \
+ return -EBUSY; \
+ \
+ spin_lock_irqsave(&wdata->state.lock, flags); \
+ state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \
+ spin_unlock_irqrestore(&wdata->state.lock, flags); \
+ \
+ return sprintf(buf, "%d\n", state); \
+} \
+static ssize_t wiifs_led_set_##num(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct wiimote_data *wdata = dev_to_wii(dev); \
+ int tmp = simple_strtoul(buf, NULL, 10); \
+ unsigned long flags; \
+ __u8 state; \
+ \
+ if (!atomic_read(&wdata->ready)) \
+ return -EBUSY; \
+ \
+ spin_lock_irqsave(&wdata->state.lock, flags); \
+ \
+ state = wdata->state.flags; \
+ \
+ if (tmp) \
+ wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\
+ else \
+ wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\
+ \
+ spin_unlock_irqrestore(&wdata->state.lock, flags); \
+ \
+ return count; \
+} \
+static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \
+ wiifs_led_set_##num)
+
+wiifs_led_show_set(1);
+wiifs_led_show_set(2);
+wiifs_led_show_set(3);
+wiifs_led_show_set(4);
+
+static int wiimote_input_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+
+ if (!atomic_read(&wdata->ready))
+ return -EBUSY;
+ /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */
+ smp_rmb();
+
+ return 0;
+}
+
+static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
+{
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
+ !!(payload[0] & 0x01));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_RIGHT],
+ !!(payload[0] & 0x02));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_DOWN],
+ !!(payload[0] & 0x04));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_UP],
+ !!(payload[0] & 0x08));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_PLUS],
+ !!(payload[0] & 0x10));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_TWO],
+ !!(payload[1] & 0x01));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_ONE],
+ !!(payload[1] & 0x02));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_B],
+ !!(payload[1] & 0x04));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_A],
+ !!(payload[1] & 0x08));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_MINUS],
+ !!(payload[1] & 0x10));
+ input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_HOME],
+ !!(payload[1] & 0x80));
+ input_sync(wdata->input);
+}
+
+struct wiiproto_handler {
+ __u8 id;
+ size_t size;
+ void (*func)(struct wiimote_data *wdata, const __u8 *payload);
+};
+
+static struct wiiproto_handler handlers[] = {
+ { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
+ { .id = 0 }
+};
+
+static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *raw_data, int size)
+{
+ struct wiimote_data *wdata = hid_get_drvdata(hdev);
+ struct wiiproto_handler *h;
+ int i;
+ unsigned long flags;
+
+ if (!atomic_read(&wdata->ready))
+ return -EBUSY;
+ /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */
+ smp_rmb();
+
+ if (size < 1)
+ return -EINVAL;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+
+ for (i = 0; handlers[i].id; ++i) {
+ h = &handlers[i];
+ if (h->id == raw_data[0] && h->size < size)
+ h->func(wdata, &raw_data[1]);
+ }
+
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static struct wiimote_data *wiimote_create(struct hid_device *hdev)
+{
+ struct wiimote_data *wdata;
+ int i;
+
+ wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
+ if (!wdata)
+ return NULL;
+
+ wdata->input = input_allocate_device();
+ if (!wdata->input) {
+ kfree(wdata);
+ return NULL;
+ }
+
+ wdata->hdev = hdev;
+ hid_set_drvdata(hdev, wdata);
+
+ input_set_drvdata(wdata->input, wdata);
+ wdata->input->event = wiimote_input_event;
+ wdata->input->dev.parent = &wdata->hdev->dev;
+ wdata->input->id.bustype = wdata->hdev->bus;
+ wdata->input->id.vendor = wdata->hdev->vendor;
+ wdata->input->id.product = wdata->hdev->product;
+ wdata->input->id.version = wdata->hdev->version;
+ wdata->input->name = WIIMOTE_NAME;
+
+ set_bit(EV_KEY, wdata->input->evbit);
+ for (i = 0; i < WIIPROTO_KEY_COUNT; ++i)
+ set_bit(wiiproto_keymap[i], wdata->input->keybit);
+
+ spin_lock_init(&wdata->qlock);
+ INIT_WORK(&wdata->worker, wiimote_worker);
+
+ spin_lock_init(&wdata->state.lock);
+
+ return wdata;
+}
+
+static void wiimote_destroy(struct wiimote_data *wdata)
+{
+ kfree(wdata);
+}
+
+static int wiimote_hid_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ struct wiimote_data *wdata;
+ int ret;
+
+ wdata = wiimote_create(hdev);
+ if (!wdata) {
+ hid_err(hdev, "Can't alloc device\n");
+ return -ENOMEM;
+ }
+
+ ret = device_create_file(&hdev->dev, &dev_attr_led1);
+ if (ret)
+ goto err;
+ ret = device_create_file(&hdev->dev, &dev_attr_led2);
+ if (ret)
+ goto err;
+ ret = device_create_file(&hdev->dev, &dev_attr_led3);
+ if (ret)
+ goto err;
+ ret = device_create_file(&hdev->dev, &dev_attr_led4);
+ if (ret)
+ goto err;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ hid_err(hdev, "HID parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+ if (ret) {
+ hid_err(hdev, "HW start failed\n");
+ goto err;
+ }
+
+ ret = input_register_device(wdata->input);
+ if (ret) {
+ hid_err(hdev, "Cannot register input device\n");
+ goto err_stop;
+ }
+
+ /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */
+ smp_wmb();
+ atomic_set(&wdata->ready, 1);
+ hid_info(hdev, "New device registered\n");
+
+ /* by default set led1 after device initialization */
+ spin_lock_irq(&wdata->state.lock);
+ wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1);
+ spin_unlock_irq(&wdata->state.lock);
+
+ return 0;
+
+err_stop:
+ hid_hw_stop(hdev);
+err:
+ input_free_device(wdata->input);
+ device_remove_file(&hdev->dev, &dev_attr_led1);
+ device_remove_file(&hdev->dev, &dev_attr_led2);
+ device_remove_file(&hdev->dev, &dev_attr_led3);
+ device_remove_file(&hdev->dev, &dev_attr_led4);
+ wiimote_destroy(wdata);
+ return ret;
+}
+
+static void wiimote_hid_remove(struct hid_device *hdev)
+{
+ struct wiimote_data *wdata = hid_get_drvdata(hdev);
+
+ hid_info(hdev, "Device removed\n");
+
+ device_remove_file(&hdev->dev, &dev_attr_led1);
+ device_remove_file(&hdev->dev, &dev_attr_led2);
+ device_remove_file(&hdev->dev, &dev_attr_led3);
+ device_remove_file(&hdev->dev, &dev_attr_led4);
+
+ hid_hw_stop(hdev);
+ input_unregister_device(wdata->input);
+
+ cancel_work_sync(&wdata->worker);
+ wiimote_destroy(wdata);
+}
+
+static const struct hid_device_id wiimote_hid_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
+ USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
+
+static struct hid_driver wiimote_hid_driver = {
+ .name = "wiimote",
+ .id_table = wiimote_hid_devices,
+ .probe = wiimote_hid_probe,
+ .remove = wiimote_hid_remove,
+ .raw_event = wiimote_hid_event,
+};
+
+static int __init wiimote_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&wiimote_hid_driver);
+ if (ret)
+ pr_err("Can't register wiimote hid driver\n");
+
+ return ret;
+}
+
+static void __exit wiimote_exit(void)
+{
+ hid_unregister_driver(&wiimote_hid_driver);
+}
+
+module_init(wiimote_init);
+module_exit(wiimote_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
+MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver");
+MODULE_VERSION(WIIMOTE_VERSION);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 38c261a40c74..ad978f5748d3 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1191,6 +1191,8 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
if (intf->cur_altsetting->desc.bInterfaceProtocol ==
USB_INTERFACE_PROTOCOL_MOUSE)
hid->type = HID_TYPE_USBMOUSE;
+ else if (intf->cur_altsetting->desc.bInterfaceProtocol == 0)
+ hid->type = HID_TYPE_USBNONE;
if (dev->manufacturer)
strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5f888f7e7dcb..0598cd22edf2 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1041,8 +1041,13 @@ config SENSORS_SMSC47B397
This driver can also be built as a module. If so, the module
will be called smsc47b397.
+config SENSORS_SCH56XX_COMMON
+ tristate
+ default n
+
config SENSORS_SCH5627
tristate "SMSC SCH5627"
+ select SENSORS_SCH56XX_COMMON
help
If you say yes here you get support for the hardware monitoring
features of the SMSC SCH5627 Super-I/O chip.
@@ -1050,6 +1055,21 @@ config SENSORS_SCH5627
This driver can also be built as a module. If so, the module
will be called sch5627.
+config SENSORS_SCH5636
+ tristate "SMSC SCH5636"
+ select SENSORS_SCH56XX_COMMON
+ help
+ SMSC SCH5636 Super I/O chips include an embedded microcontroller for
+ hardware monitoring solutions, allowing motherboard manufacturers to
+ create their own custom hwmon solution based upon the SCH5636.
+
+ Currently this driver only supports the Fujitsu Theseus SCH5636 based
+ hwmon solution. Say yes here if you want support for the Fujitsu
+ Theseus' hardware monitoring features.
+
+ This driver can also be built as a module. If so, the module
+ will be called sch5636.
+
config SENSORS_ADS1015
tristate "Texas Instruments ADS1015"
depends on I2C
@@ -1142,6 +1162,7 @@ config SENSORS_TWL4030_MADC
config SENSORS_VIA_CPUTEMP
tristate "VIA CPU temperature sensor"
depends on X86
+ select HWMON_VID
help
If you say yes here you get support for the temperature
sensor inside your CPU. Supported are all known variants of
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 28061cfa0cdb..d7995a1d0784 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -95,7 +95,9 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
+obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
+obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o
obj-$(CONFIG_SENSORS_SHT15) += sht15.o
obj-$(CONFIG_SENSORS_SHT21) += sht21.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index ec588026f0a9..131ea8625f08 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -273,7 +273,7 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
#define DIV_FROM_REG(val) (1 << (val))
#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div))))
-#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255));
+#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255))
static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr,
char *buf)
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index c8195a077da3..932da8a5aaf4 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -140,7 +140,11 @@ int vid_from_reg(int val, u8 vrm)
return(val & 0x10 ? 975 - (val & 0xF) * 25 :
1750 - val * 50);
case 13:
+ case 131:
val &= 0x3f;
+ /* Exception for Eden ULV 500 MHz */
+ if (vrm == 131 && val == 0x3f)
+ val++;
return(1708 - val * 16);
case 14: /* Intel Core */
/* compute in uV, round to mV */
@@ -205,11 +209,45 @@ static struct vrm_model vrm_models[] = {
{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nehemiah */
{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M, Eden-N */
{X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0}, /* No information */
- {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7, Esther */
+ {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7-M, C7, Eden (Esther) */
+ {X86_VENDOR_CENTAUR, 0x6, 0xD, ANY, 134}, /* C7-D, C7-M, C7, Eden (Esther) */
{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */
};
+/*
+ * Special case for VIA model D: there are two different possible
+ * VID tables, so we have to figure out first, which one must be
+ * used. This resolves temporary drm value 134 to 14 (Intel Core
+ * 7-bit VID), 13 (Pentium M 6-bit VID) or 131 (Pentium M 6-bit VID
+ * + quirk for Eden ULV 500 MHz).
+ * Note: something similar might be needed for model A, I'm not sure.
+ */
+static u8 get_via_model_d_vrm(void)
+{
+ unsigned int vid, brand, dummy;
+ static const char *brands[4] = {
+ "C7-M", "C7", "Eden", "C7-D"
+ };
+
+ rdmsr(0x198, dummy, vid);
+ vid &= 0xff;
+
+ rdmsr(0x1154, brand, dummy);
+ brand = ((brand >> 4) ^ (brand >> 2)) & 0x03;
+
+ if (vid > 0x3f) {
+ pr_info("Using %d-bit VID table for VIA %s CPU\n",
+ 7, brands[brand]);
+ return 14;
+ } else {
+ pr_info("Using %d-bit VID table for VIA %s CPU\n",
+ 6, brands[brand]);
+ /* Enable quirk for Eden */
+ return brand == 2 ? 131 : 13;
+ }
+}
+
static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
{
int i = 0;
@@ -247,6 +285,8 @@ u8 vid_which_vrm(void)
eff_model += ((eax & 0x000F0000)>>16)<<4;
}
vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
+ if (vrm_ret == 134)
+ vrm_ret = get_via_model_d_vrm();
if (vrm_ret == 0)
pr_info("Unknown VRM version of your x86 CPU\n");
return vrm_ret;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 5f5247750430..d912649fac50 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1172,6 +1172,32 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
}
+
+static ssize_t clear_intrusion(struct device *dev, struct device_attribute
+ *attr, const char *buf, size_t count)
+{
+ struct it87_data *data = dev_get_drvdata(dev);
+ long val;
+ int config;
+
+ if (strict_strtol(buf, 10, &val) < 0 || val != 0)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ config = it87_read_value(data, IT87_REG_CONFIG);
+ if (config < 0) {
+ count = config;
+ } else {
+ config |= 1 << 5;
+ it87_write_value(data, IT87_REG_CONFIG, config);
+ /* Invalidate cache to force re-read */
+ data->valid = 0;
+ }
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
@@ -1188,6 +1214,8 @@ static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6);
static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16);
static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
+static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR,
+ show_alarm, clear_intrusion, 4);
static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1350,6 +1378,7 @@ static struct attribute *it87_attributes[] = {
&sensor_dev_attr_temp3_alarm.dev_attr.attr,
&dev_attr_alarms.attr,
+ &sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
&dev_attr_name.attr,
NULL
};
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 4cb24eafe318..6df0b4681710 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -2,7 +2,7 @@
lm78.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
- Copyright (c) 2007 Jean Delvare <khali@linux-fr.org>
+ Copyright (c) 2007, 2011 Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,23 +26,21 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/ioport.h>
#include <linux/hwmon.h>
#include <linux/hwmon-vid.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/io.h>
-/* ISA device, if found */
-static struct platform_device *pdev;
+#ifdef CONFIG_ISA
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#endif
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned short isa_address = 0x290;
-
enum chips { lm78, lm79 };
/* Many LM78 constants specified below */
@@ -143,50 +141,12 @@ struct lm78_data {
};
-static int lm78_i2c_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int lm78_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int lm78_i2c_remove(struct i2c_client *client);
-
-static int __devinit lm78_isa_probe(struct platform_device *pdev);
-static int __devexit lm78_isa_remove(struct platform_device *pdev);
-
static int lm78_read_value(struct lm78_data *data, u8 reg);
static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value);
static struct lm78_data *lm78_update_device(struct device *dev);
static void lm78_init_device(struct lm78_data *data);
-static const struct i2c_device_id lm78_i2c_id[] = {
- { "lm78", lm78 },
- { "lm79", lm79 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, lm78_i2c_id);
-
-static struct i2c_driver lm78_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "lm78",
- },
- .probe = lm78_i2c_probe,
- .remove = lm78_i2c_remove,
- .id_table = lm78_i2c_id,
- .detect = lm78_i2c_detect,
- .address_list = normal_i2c,
-};
-
-static struct platform_driver lm78_isa_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "lm78",
- },
- .probe = lm78_isa_probe,
- .remove = __devexit_p(lm78_isa_remove),
-};
-
-
/* 7 Voltages */
static ssize_t show_in(struct device *dev, struct device_attribute *da,
char *buf)
@@ -514,6 +474,16 @@ static const struct attribute_group lm78_group = {
.attrs = lm78_attributes,
};
+/*
+ * ISA related code
+ */
+#ifdef CONFIG_ISA
+
+/* ISA device, if found */
+static struct platform_device *pdev;
+
+static unsigned short isa_address = 0x290;
+
/* I2C devices get this name attribute automatically, but for ISA devices
we must create it by ourselves. */
static ssize_t show_name(struct device *dev, struct device_attribute
@@ -525,6 +495,11 @@ static ssize_t show_name(struct device *dev, struct device_attribute
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+static struct lm78_data *lm78_data_if_isa(void)
+{
+ return pdev ? platform_get_drvdata(pdev) : NULL;
+}
+
/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
{
@@ -558,12 +533,24 @@ static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
return 1;
}
+#else /* !CONFIG_ISA */
+
+static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
+{
+ return 0;
+}
+
+static struct lm78_data *lm78_data_if_isa(void)
+{
+ return NULL;
+}
+#endif /* CONFIG_ISA */
static int lm78_i2c_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
int i;
- struct lm78_data *isa = pdev ? platform_get_drvdata(pdev) : NULL;
+ struct lm78_data *isa = lm78_data_if_isa();
const char *client_name;
struct i2c_adapter *adapter = client->adapter;
int address = client->addr;
@@ -663,76 +650,24 @@ static int lm78_i2c_remove(struct i2c_client *client)
return 0;
}
-static int __devinit lm78_isa_probe(struct platform_device *pdev)
-{
- int err;
- struct lm78_data *data;
- struct resource *res;
-
- /* Reserve the ISA region */
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!request_region(res->start + LM78_ADDR_REG_OFFSET, 2, "lm78")) {
- err = -EBUSY;
- goto exit;
- }
-
- if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit_release_region;
- }
- mutex_init(&data->lock);
- data->isa_addr = res->start;
- platform_set_drvdata(pdev, data);
-
- if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) {
- data->type = lm79;
- data->name = "lm79";
- } else {
- data->type = lm78;
- data->name = "lm78";
- }
-
- /* Initialize the LM78 chip */
- lm78_init_device(data);
-
- /* Register sysfs hooks */
- if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
- || (err = device_create_file(&pdev->dev, &dev_attr_name)))
- goto exit_remove_files;
-
- data->hwmon_dev = hwmon_device_register(&pdev->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
- exit_remove_files:
- sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
- device_remove_file(&pdev->dev, &dev_attr_name);
- kfree(data);
- exit_release_region:
- release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
- exit:
- return err;
-}
-
-static int __devexit lm78_isa_remove(struct platform_device *pdev)
-{
- struct lm78_data *data = platform_get_drvdata(pdev);
- struct resource *res;
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
- device_remove_file(&pdev->dev, &dev_attr_name);
- kfree(data);
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
+static const struct i2c_device_id lm78_i2c_id[] = {
+ { "lm78", lm78 },
+ { "lm79", lm79 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm78_i2c_id);
- return 0;
-}
+static struct i2c_driver lm78_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "lm78",
+ },
+ .probe = lm78_i2c_probe,
+ .remove = lm78_i2c_remove,
+ .id_table = lm78_i2c_id,
+ .detect = lm78_i2c_detect,
+ .address_list = normal_i2c,
+};
/* The SMBus locks itself, but ISA access must be locked explicitly!
We don't want to lock the whole ISA bus, so we lock each client
@@ -743,6 +678,7 @@ static int lm78_read_value(struct lm78_data *data, u8 reg)
{
struct i2c_client *client = data->client;
+#ifdef CONFIG_ISA
if (!client) { /* ISA device */
int res;
mutex_lock(&data->lock);
@@ -751,6 +687,7 @@ static int lm78_read_value(struct lm78_data *data, u8 reg)
mutex_unlock(&data->lock);
return res;
} else
+#endif
return i2c_smbus_read_byte_data(client, reg);
}
@@ -765,6 +702,7 @@ static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
{
struct i2c_client *client = data->client;
+#ifdef CONFIG_ISA
if (!client) { /* ISA device */
mutex_lock(&data->lock);
outb_p(reg, data->isa_addr + LM78_ADDR_REG_OFFSET);
@@ -772,6 +710,7 @@ static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
mutex_unlock(&data->lock);
return 0;
} else
+#endif
return i2c_smbus_write_byte_data(client, reg, value);
}
@@ -849,6 +788,88 @@ static struct lm78_data *lm78_update_device(struct device *dev)
return data;
}
+#ifdef CONFIG_ISA
+static int __devinit lm78_isa_probe(struct platform_device *pdev)
+{
+ int err;
+ struct lm78_data *data;
+ struct resource *res;
+
+ /* Reserve the ISA region */
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!request_region(res->start + LM78_ADDR_REG_OFFSET, 2, "lm78")) {
+ err = -EBUSY;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit_release_region;
+ }
+ mutex_init(&data->lock);
+ data->isa_addr = res->start;
+ platform_set_drvdata(pdev, data);
+
+ if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) {
+ data->type = lm79;
+ data->name = "lm79";
+ } else {
+ data->type = lm78;
+ data->name = "lm78";
+ }
+
+ /* Initialize the LM78 chip */
+ lm78_init_device(data);
+
+ /* Register sysfs hooks */
+ if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
+ || (err = device_create_file(&pdev->dev, &dev_attr_name)))
+ goto exit_remove_files;
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove_files;
+ }
+
+ return 0;
+
+ exit_remove_files:
+ sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ kfree(data);
+ exit_release_region:
+ release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
+ exit:
+ return err;
+}
+
+static int __devexit lm78_isa_remove(struct platform_device *pdev)
+{
+ struct lm78_data *data = platform_get_drvdata(pdev);
+ struct resource *res;
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ kfree(data);
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
+
+ return 0;
+}
+
+static struct platform_driver lm78_isa_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "lm78",
+ },
+ .probe = lm78_isa_probe,
+ .remove = __devexit_p(lm78_isa_remove),
+};
+
/* return 1 if a supported chip is found, 0 otherwise */
static int __init lm78_isa_found(unsigned short address)
{
@@ -969,12 +990,10 @@ static int __init lm78_isa_device_add(unsigned short address)
return err;
}
-static int __init sm_lm78_init(void)
+static int __init lm78_isa_register(void)
{
int res;
- /* We register the ISA device first, so that we can skip the
- * registration of an I2C interface to the same device. */
if (lm78_isa_found(isa_address)) {
res = platform_driver_register(&lm78_isa_driver);
if (res)
@@ -986,32 +1005,62 @@ static int __init sm_lm78_init(void)
goto exit_unreg_isa_driver;
}
- res = i2c_add_driver(&lm78_driver);
- if (res)
- goto exit_unreg_isa_device;
-
return 0;
- exit_unreg_isa_device:
- platform_device_unregister(pdev);
exit_unreg_isa_driver:
platform_driver_unregister(&lm78_isa_driver);
exit:
return res;
}
-static void __exit sm_lm78_exit(void)
+static void lm78_isa_unregister(void)
{
if (pdev) {
platform_device_unregister(pdev);
platform_driver_unregister(&lm78_isa_driver);
}
- i2c_del_driver(&lm78_driver);
}
+#else /* !CONFIG_ISA */
+static int __init lm78_isa_register(void)
+{
+ return 0;
+}
+
+static void lm78_isa_unregister(void)
+{
+}
+#endif /* CONFIG_ISA */
+static int __init sm_lm78_init(void)
+{
+ int res;
+
+ /* We register the ISA device first, so that we can skip the
+ * registration of an I2C interface to the same device. */
+ res = lm78_isa_register();
+ if (res)
+ goto exit;
+
+ res = i2c_add_driver(&lm78_driver);
+ if (res)
+ goto exit_unreg_isa_device;
+
+ return 0;
+
+ exit_unreg_isa_device:
+ lm78_isa_unregister();
+ exit:
+ return res;
+}
+
+static void __exit sm_lm78_exit(void)
+{
+ lm78_isa_unregister();
+ i2c_del_driver(&lm78_driver);
+}
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+MODULE_AUTHOR("Frodo Looijaard, Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("LM78/LM79 driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index 14335bbc9bdc..c97b78ef9116 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -38,8 +38,8 @@ struct max1111_data {
struct device *hwmon_dev;
struct spi_message msg;
struct spi_transfer xfer[2];
- uint8_t *tx_buf;
- uint8_t *rx_buf;
+ uint8_t tx_buf[MAX1111_TX_BUF_SIZE];
+ uint8_t rx_buf[MAX1111_RX_BUF_SIZE];
struct mutex drvdata_lock;
/* protect msg, xfer and buffers from multiple access */
};
@@ -131,33 +131,23 @@ static const struct attribute_group max1111_attr_group = {
.attrs = max1111_attributes,
};
-static int setup_transfer(struct max1111_data *data)
+static int __devinit setup_transfer(struct max1111_data *data)
{
struct spi_message *m;
struct spi_transfer *x;
- data->tx_buf = kmalloc(MAX1111_TX_BUF_SIZE, GFP_KERNEL);
- if (!data->tx_buf)
- return -ENOMEM;
-
- data->rx_buf = kmalloc(MAX1111_RX_BUF_SIZE, GFP_KERNEL);
- if (!data->rx_buf) {
- kfree(data->tx_buf);
- return -ENOMEM;
- }
-
m = &data->msg;
x = &data->xfer[0];
spi_message_init(m);
x->tx_buf = &data->tx_buf[0];
- x->len = 1;
+ x->len = MAX1111_TX_BUF_SIZE;
spi_message_add_tail(x, m);
x++;
x->rx_buf = &data->rx_buf[0];
- x->len = 2;
+ x->len = MAX1111_RX_BUF_SIZE;
spi_message_add_tail(x, m);
return 0;
@@ -192,7 +182,7 @@ static int __devinit max1111_probe(struct spi_device *spi)
err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group);
if (err) {
dev_err(&spi->dev, "failed to create attribute group\n");
- goto err_free_all;
+ goto err_free_data;
}
data->hwmon_dev = hwmon_device_register(&spi->dev);
@@ -209,9 +199,6 @@ static int __devinit max1111_probe(struct spi_device *spi)
err_remove:
sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
-err_free_all:
- kfree(data->rx_buf);
- kfree(data->tx_buf);
err_free_data:
kfree(data);
return err;
@@ -224,8 +211,6 @@ static int __devexit max1111_remove(struct spi_device *spi)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
mutex_destroy(&data->drvdata_lock);
- kfree(data->rx_buf);
- kfree(data->tx_buf);
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 3494a4cce414..e3b5c6039c25 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -28,33 +28,15 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/acpi.h>
-#include <linux/delay.h>
+#include "sch56xx-common.h"
#define DRVNAME "sch5627"
#define DEVNAME DRVNAME /* We only support one model */
-#define SIO_SCH5627_EM_LD 0x0C /* Embedded Microcontroller LD */
-#define SIO_UNLOCK_KEY 0x55 /* Key to enable Super-I/O */
-#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
-
-#define SIO_REG_LDSEL 0x07 /* Logical device select */
-#define SIO_REG_DEVID 0x20 /* Device ID */
-#define SIO_REG_ENABLE 0x30 /* Logical device enable */
-#define SIO_REG_ADDR 0x66 /* Logical device address (2 bytes) */
-
-#define SIO_SCH5627_ID 0xC6 /* Chipset ID */
-
-#define REGION_LENGTH 9
-
#define SCH5627_HWMON_ID 0xa5
#define SCH5627_COMPANY_ID 0x5c
#define SCH5627_PRIMARY_ID 0xa0
-#define SCH5627_CMD_READ 0x02
-#define SCH5627_CMD_WRITE 0x03
-
#define SCH5627_REG_BUILD_CODE 0x39
#define SCH5627_REG_BUILD_ID 0x3a
#define SCH5627_REG_HWMON_ID 0x3c
@@ -111,182 +93,6 @@ struct sch5627_data {
u16 in[SCH5627_NO_IN];
};
-static struct platform_device *sch5627_pdev;
-
-/* Super I/O functions */
-static inline int superio_inb(int base, int reg)
-{
- outb(reg, base);
- return inb(base + 1);
-}
-
-static inline int superio_enter(int base)
-{
- /* Don't step on other drivers' I/O space by accident */
- if (!request_muxed_region(base, 2, DRVNAME)) {
- pr_err("I/O address 0x%04x already in use\n", base);
- return -EBUSY;
- }
-
- outb(SIO_UNLOCK_KEY, base);
-
- return 0;
-}
-
-static inline void superio_select(int base, int ld)
-{
- outb(SIO_REG_LDSEL, base);
- outb(ld, base + 1);
-}
-
-static inline void superio_exit(int base)
-{
- outb(SIO_LOCK_KEY, base);
- release_region(base, 2);
-}
-
-static int sch5627_send_cmd(struct sch5627_data *data, u8 cmd, u16 reg, u8 v)
-{
- u8 val;
- int i;
- /*
- * According to SMSC for the commands we use the maximum time for
- * the EM to respond is 15 ms, but testing shows in practice it
- * responds within 15-32 reads, so we first busy poll, and if
- * that fails sleep a bit and try again until we are way past
- * the 15 ms maximum response time.
- */
- const int max_busy_polls = 64;
- const int max_lazy_polls = 32;
-
- /* (Optional) Write-Clear the EC to Host Mailbox Register */
- val = inb(data->addr + 1);
- outb(val, data->addr + 1);
-
- /* Set Mailbox Address Pointer to first location in Region 1 */
- outb(0x00, data->addr + 2);
- outb(0x80, data->addr + 3);
-
- /* Write Request Packet Header */
- outb(cmd, data->addr + 4); /* VREG Access Type read:0x02 write:0x03 */
- outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */
- outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */
-
- /* Write Value field */
- if (cmd == SCH5627_CMD_WRITE)
- outb(v, data->addr + 4);
-
- /* Write Address field */
- outb(reg & 0xff, data->addr + 6);
- outb(reg >> 8, data->addr + 7);
-
- /* Execute the Random Access Command */
- outb(0x01, data->addr); /* Write 01h to the Host-to-EC register */
-
- /* EM Interface Polling "Algorithm" */
- for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
- if (i >= max_busy_polls)
- msleep(1);
- /* Read Interrupt source Register */
- val = inb(data->addr + 8);
- /* Write Clear the interrupt source bits */
- if (val)
- outb(val, data->addr + 8);
- /* Command Completed ? */
- if (val & 0x01)
- break;
- }
- if (i == max_busy_polls + max_lazy_polls) {
- pr_err("Max retries exceeded reading virtual "
- "register 0x%04hx (%d)\n", reg, 1);
- return -EIO;
- }
-
- /*
- * According to SMSC we may need to retry this, but sofar I've always
- * seen this succeed in 1 try.
- */
- for (i = 0; i < max_busy_polls; i++) {
- /* Read EC-to-Host Register */
- val = inb(data->addr + 1);
- /* Command Completed ? */
- if (val == 0x01)
- break;
-
- if (i == 0)
- pr_warn("EC reports: 0x%02x reading virtual register "
- "0x%04hx\n", (unsigned int)val, reg);
- }
- if (i == max_busy_polls) {
- pr_err("Max retries exceeded reading virtual "
- "register 0x%04hx (%d)\n", reg, 2);
- return -EIO;
- }
-
- /*
- * According to the SMSC app note we should now do:
- *
- * Set Mailbox Address Pointer to first location in Region 1 *
- * outb(0x00, data->addr + 2);
- * outb(0x80, data->addr + 3);
- *
- * But if we do that things don't work, so let's not.
- */
-
- /* Read Value field */
- if (cmd == SCH5627_CMD_READ)
- return inb(data->addr + 4);
-
- return 0;
-}
-
-static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg)
-{
- return sch5627_send_cmd(data, SCH5627_CMD_READ, reg, 0);
-}
-
-static int sch5627_write_virtual_reg(struct sch5627_data *data,
- u16 reg, u8 val)
-{
- return sch5627_send_cmd(data, SCH5627_CMD_WRITE, reg, val);
-}
-
-static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg)
-{
- int lsb, msb;
-
- /* Read LSB first, this will cause the matching MSB to be latched */
- lsb = sch5627_read_virtual_reg(data, reg);
- if (lsb < 0)
- return lsb;
-
- msb = sch5627_read_virtual_reg(data, reg + 1);
- if (msb < 0)
- return msb;
-
- return lsb | (msb << 8);
-}
-
-static int sch5627_read_virtual_reg12(struct sch5627_data *data, u16 msb_reg,
- u16 lsn_reg, int high_nibble)
-{
- int msb, lsn;
-
- /* Read MSB first, this will cause the matching LSN to be latched */
- msb = sch5627_read_virtual_reg(data, msb_reg);
- if (msb < 0)
- return msb;
-
- lsn = sch5627_read_virtual_reg(data, lsn_reg);
- if (lsn < 0)
- return lsn;
-
- if (high_nibble)
- return (msb << 4) | (lsn >> 4);
- else
- return (msb << 4) | (lsn & 0x0f);
-}
-
static struct sch5627_data *sch5627_update_device(struct device *dev)
{
struct sch5627_data *data = dev_get_drvdata(dev);
@@ -297,7 +103,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
/* Trigger a Vbat voltage measurement every 5 minutes */
if (time_after(jiffies, data->last_battery + 300 * HZ)) {
- sch5627_write_virtual_reg(data, SCH5627_REG_CTRL,
+ sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL,
data->control | 0x10);
data->last_battery = jiffies;
}
@@ -305,7 +111,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
/* Cache the values for 1 second */
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
for (i = 0; i < SCH5627_NO_TEMPS; i++) {
- val = sch5627_read_virtual_reg12(data,
+ val = sch56xx_read_virtual_reg12(data->addr,
SCH5627_REG_TEMP_MSB[i],
SCH5627_REG_TEMP_LSN[i],
SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
@@ -317,7 +123,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
}
for (i = 0; i < SCH5627_NO_FANS; i++) {
- val = sch5627_read_virtual_reg16(data,
+ val = sch56xx_read_virtual_reg16(data->addr,
SCH5627_REG_FAN[i]);
if (unlikely(val < 0)) {
ret = ERR_PTR(val);
@@ -327,7 +133,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
}
for (i = 0; i < SCH5627_NO_IN; i++) {
- val = sch5627_read_virtual_reg12(data,
+ val = sch56xx_read_virtual_reg12(data->addr,
SCH5627_REG_IN_MSB[i],
SCH5627_REG_IN_LSN[i],
SCH5627_REG_IN_HIGH_NIBBLE[i]);
@@ -355,18 +161,21 @@ static int __devinit sch5627_read_limits(struct sch5627_data *data)
* Note what SMSC calls ABS, is what lm_sensors calls max
* (aka high), and HIGH is what lm_sensors calls crit.
*/
- val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_ABS[i]);
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5627_REG_TEMP_ABS[i]);
if (val < 0)
return val;
data->temp_max[i] = val;
- val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_HIGH[i]);
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5627_REG_TEMP_HIGH[i]);
if (val < 0)
return val;
data->temp_crit[i] = val;
}
for (i = 0; i < SCH5627_NO_FANS; i++) {
- val = sch5627_read_virtual_reg16(data, SCH5627_REG_FAN_MIN[i]);
+ val = sch56xx_read_virtual_reg16(data->addr,
+ SCH5627_REG_FAN_MIN[i]);
if (val < 0)
return val;
data->fan_min[i] = val;
@@ -667,7 +476,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data);
- val = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_ID);
+ val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_HWMON_ID);
if (val < 0) {
err = val;
goto error;
@@ -679,7 +488,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
goto error;
}
- val = sch5627_read_virtual_reg(data, SCH5627_REG_COMPANY_ID);
+ val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_COMPANY_ID);
if (val < 0) {
err = val;
goto error;
@@ -691,7 +500,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
goto error;
}
- val = sch5627_read_virtual_reg(data, SCH5627_REG_PRIMARY_ID);
+ val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_PRIMARY_ID);
if (val < 0) {
err = val;
goto error;
@@ -703,25 +512,28 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
goto error;
}
- build_code = sch5627_read_virtual_reg(data, SCH5627_REG_BUILD_CODE);
+ build_code = sch56xx_read_virtual_reg(data->addr,
+ SCH5627_REG_BUILD_CODE);
if (build_code < 0) {
err = build_code;
goto error;
}
- build_id = sch5627_read_virtual_reg16(data, SCH5627_REG_BUILD_ID);
+ build_id = sch56xx_read_virtual_reg16(data->addr,
+ SCH5627_REG_BUILD_ID);
if (build_id < 0) {
err = build_id;
goto error;
}
- hwmon_rev = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_REV);
+ hwmon_rev = sch56xx_read_virtual_reg(data->addr,
+ SCH5627_REG_HWMON_REV);
if (hwmon_rev < 0) {
err = hwmon_rev;
goto error;
}
- val = sch5627_read_virtual_reg(data, SCH5627_REG_CTRL);
+ val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_CTRL);
if (val < 0) {
err = val;
goto error;
@@ -734,7 +546,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
}
/* Trigger a Vbat voltage measurement, so that we get a valid reading
the first time we read Vbat */
- sch5627_write_virtual_reg(data, SCH5627_REG_CTRL,
+ sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL,
data->control | 0x10);
data->last_battery = jiffies;
@@ -746,6 +558,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
if (err)
goto error;
+ pr_info("found %s chip at %#hx\n", DEVNAME, data->addr);
pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
build_code, build_id, hwmon_rev);
@@ -768,85 +581,6 @@ error:
return err;
}
-static int __init sch5627_find(int sioaddr, unsigned short *address)
-{
- u8 devid;
- int err = superio_enter(sioaddr);
- if (err)
- return err;
-
- devid = superio_inb(sioaddr, SIO_REG_DEVID);
- if (devid != SIO_SCH5627_ID) {
- pr_debug("Unsupported device id: 0x%02x\n",
- (unsigned int)devid);
- err = -ENODEV;
- goto exit;
- }
-
- superio_select(sioaddr, SIO_SCH5627_EM_LD);
-
- if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
- pr_warn("Device not activated\n");
- err = -ENODEV;
- goto exit;
- }
-
- /*
- * Warning the order of the low / high byte is the other way around
- * as on most other superio devices!!
- */
- *address = superio_inb(sioaddr, SIO_REG_ADDR) |
- superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
- if (*address == 0) {
- pr_warn("Base address not set\n");
- err = -ENODEV;
- goto exit;
- }
-
- pr_info("Found %s chip at %#hx\n", DEVNAME, *address);
-exit:
- superio_exit(sioaddr);
- return err;
-}
-
-static int __init sch5627_device_add(unsigned short address)
-{
- struct resource res = {
- .start = address,
- .end = address + REGION_LENGTH - 1,
- .flags = IORESOURCE_IO,
- };
- int err;
-
- sch5627_pdev = platform_device_alloc(DRVNAME, address);
- if (!sch5627_pdev)
- return -ENOMEM;
-
- res.name = sch5627_pdev->name;
- err = acpi_check_resource_conflict(&res);
- if (err)
- goto exit_device_put;
-
- err = platform_device_add_resources(sch5627_pdev, &res, 1);
- if (err) {
- pr_err("Device resource addition failed\n");
- goto exit_device_put;
- }
-
- err = platform_device_add(sch5627_pdev);
- if (err) {
- pr_err("Device addition failed\n");
- goto exit_device_put;
- }
-
- return 0;
-
-exit_device_put:
- platform_device_put(sch5627_pdev);
-
- return err;
-}
-
static struct platform_driver sch5627_driver = {
.driver = {
.owner = THIS_MODULE,
@@ -858,31 +592,11 @@ static struct platform_driver sch5627_driver = {
static int __init sch5627_init(void)
{
- int err = -ENODEV;
- unsigned short address;
-
- if (sch5627_find(0x4e, &address) && sch5627_find(0x2e, &address))
- goto exit;
-
- err = platform_driver_register(&sch5627_driver);
- if (err)
- goto exit;
-
- err = sch5627_device_add(address);
- if (err)
- goto exit_driver;
-
- return 0;
-
-exit_driver:
- platform_driver_unregister(&sch5627_driver);
-exit:
- return err;
+ return platform_driver_register(&sch5627_driver);
}
static void __exit sch5627_exit(void)
{
- platform_device_unregister(sch5627_pdev);
platform_driver_unregister(&sch5627_driver);
}
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
new file mode 100644
index 000000000000..244407aa79fc
--- /dev/null
+++ b/drivers/hwmon/sch5636.c
@@ -0,0 +1,539 @@
+/***************************************************************************
+ * Copyright (C) 2011 Hans de Goede <hdegoede@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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include "sch56xx-common.h"
+
+#define DRVNAME "sch5636"
+#define DEVNAME "theseus" /* We only support one model for now */
+
+#define SCH5636_REG_FUJITSU_ID 0x780
+#define SCH5636_REG_FUJITSU_REV 0x783
+
+#define SCH5636_NO_INS 5
+#define SCH5636_NO_TEMPS 16
+#define SCH5636_NO_FANS 8
+
+static const u16 SCH5636_REG_IN_VAL[SCH5636_NO_INS] = {
+ 0x22, 0x23, 0x24, 0x25, 0x189 };
+static const u16 SCH5636_REG_IN_FACTORS[SCH5636_NO_INS] = {
+ 4400, 1500, 4000, 4400, 16000 };
+static const char * const SCH5636_IN_LABELS[SCH5636_NO_INS] = {
+ "3.3V", "VREF", "VBAT", "3.3AUX", "12V" };
+
+static const u16 SCH5636_REG_TEMP_VAL[SCH5636_NO_TEMPS] = {
+ 0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181,
+ 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C };
+#define SCH5636_REG_TEMP_CTRL(i) (0x790 + (i))
+#define SCH5636_TEMP_WORKING 0x01
+#define SCH5636_TEMP_ALARM 0x02
+#define SCH5636_TEMP_DEACTIVATED 0x80
+
+static const u16 SCH5636_REG_FAN_VAL[SCH5636_NO_FANS] = {
+ 0x2C, 0x2E, 0x30, 0x32, 0x62, 0x64, 0x66, 0x68 };
+#define SCH5636_REG_FAN_CTRL(i) (0x880 + (i))
+/* FAULT in datasheet, but acts as an alarm */
+#define SCH5636_FAN_ALARM 0x04
+#define SCH5636_FAN_NOT_PRESENT 0x08
+#define SCH5636_FAN_DEACTIVATED 0x80
+
+
+struct sch5636_data {
+ unsigned short addr;
+ struct device *hwmon_dev;
+
+ struct mutex update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 in[SCH5636_NO_INS];
+ u8 temp_val[SCH5636_NO_TEMPS];
+ u8 temp_ctrl[SCH5636_NO_TEMPS];
+ u16 fan_val[SCH5636_NO_FANS];
+ u8 fan_ctrl[SCH5636_NO_FANS];
+};
+
+static struct sch5636_data *sch5636_update_device(struct device *dev)
+{
+ struct sch5636_data *data = dev_get_drvdata(dev);
+ struct sch5636_data *ret = data;
+ int i, val;
+
+ mutex_lock(&data->update_lock);
+
+ /* Cache the values for 1 second */
+ if (data->valid && !time_after(jiffies, data->last_updated + HZ))
+ goto abort;
+
+ for (i = 0; i < SCH5636_NO_INS; i++) {
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_IN_VAL[i]);
+ if (unlikely(val < 0)) {
+ ret = ERR_PTR(val);
+ goto abort;
+ }
+ data->in[i] = val;
+ }
+
+ for (i = 0; i < SCH5636_NO_TEMPS; i++) {
+ if (data->temp_ctrl[i] & SCH5636_TEMP_DEACTIVATED)
+ continue;
+
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_TEMP_VAL[i]);
+ if (unlikely(val < 0)) {
+ ret = ERR_PTR(val);
+ goto abort;
+ }
+ data->temp_val[i] = val;
+
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_TEMP_CTRL(i));
+ if (unlikely(val < 0)) {
+ ret = ERR_PTR(val);
+ goto abort;
+ }
+ data->temp_ctrl[i] = val;
+ /* Alarms need to be explicitly write-cleared */
+ if (val & SCH5636_TEMP_ALARM) {
+ sch56xx_write_virtual_reg(data->addr,
+ SCH5636_REG_TEMP_CTRL(i), val);
+ }
+ }
+
+ for (i = 0; i < SCH5636_NO_FANS; i++) {
+ if (data->fan_ctrl[i] & SCH5636_FAN_DEACTIVATED)
+ continue;
+
+ val = sch56xx_read_virtual_reg16(data->addr,
+ SCH5636_REG_FAN_VAL[i]);
+ if (unlikely(val < 0)) {
+ ret = ERR_PTR(val);
+ goto abort;
+ }
+ data->fan_val[i] = val;
+
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_FAN_CTRL(i));
+ if (unlikely(val < 0)) {
+ ret = ERR_PTR(val);
+ goto abort;
+ }
+ data->fan_ctrl[i] = val;
+ /* Alarms need to be explicitly write-cleared */
+ if (val & SCH5636_FAN_ALARM) {
+ sch56xx_write_virtual_reg(data->addr,
+ SCH5636_REG_FAN_CTRL(i), val);
+ }
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+abort:
+ mutex_unlock(&data->update_lock);
+ return ret;
+}
+
+static int reg_to_rpm(u16 reg)
+{
+ if (reg == 0)
+ return -EIO;
+ if (reg == 0xffff)
+ return 0;
+
+ return 5400540 / reg;
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
+}
+
+static ssize_t show_in_value(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct sch5636_data *data = sch5636_update_device(dev);
+ int val;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ val = DIV_ROUND_CLOSEST(
+ data->in[attr->index] * SCH5636_REG_IN_FACTORS[attr->index],
+ 255);
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in_label(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ SCH5636_IN_LABELS[attr->index]);
+}
+
+static ssize_t show_temp_value(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct sch5636_data *data = sch5636_update_device(dev);
+ int val;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ val = (data->temp_val[attr->index] - 64) * 1000;
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_fault(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct sch5636_data *data = sch5636_update_device(dev);
+ int val;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_WORKING) ? 0 : 1;
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct sch5636_data *data = sch5636_update_device(dev);
+ int val;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_ALARM) ? 1 : 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_value(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct sch5636_data *data = sch5636_update_device(dev);
+ int val;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ val = reg_to_rpm(data->fan_val[attr->index]);
+ if (val < 0)
+ return val;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct sch5636_data *data = sch5636_update_device(dev);
+ int val;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ val = (data->fan_ctrl[attr->index] & SCH5636_FAN_NOT_PRESENT) ? 1 : 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct sch5636_data *data = sch5636_update_device(dev);
+ int val;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ val = (data->fan_ctrl[attr->index] & SCH5636_FAN_ALARM) ? 1 : 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static struct sensor_device_attribute sch5636_attr[] = {
+ SENSOR_ATTR(name, 0444, show_name, NULL, 0),
+ SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0),
+ SENSOR_ATTR(in0_label, 0444, show_in_label, NULL, 0),
+ SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1),
+ SENSOR_ATTR(in1_label, 0444, show_in_label, NULL, 1),
+ SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2),
+ SENSOR_ATTR(in2_label, 0444, show_in_label, NULL, 2),
+ SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3),
+ SENSOR_ATTR(in3_label, 0444, show_in_label, NULL, 3),
+ SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4),
+ SENSOR_ATTR(in4_label, 0444, show_in_label, NULL, 4),
+};
+
+static struct sensor_device_attribute sch5636_temp_attr[] = {
+ SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0),
+ SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0),
+ SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0),
+ SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1),
+ SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1),
+ SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1),
+ SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2),
+ SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2),
+ SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2),
+ SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3),
+ SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3),
+ SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3),
+ SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4),
+ SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4),
+ SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4),
+ SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5),
+ SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5),
+ SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5),
+ SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6),
+ SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6),
+ SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6),
+ SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7),
+ SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7),
+ SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7),
+ SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8),
+ SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8),
+ SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8),
+ SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9),
+ SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9),
+ SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9),
+ SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10),
+ SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10),
+ SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10),
+ SENSOR_ATTR(temp12_input, 0444, show_temp_value, NULL, 11),
+ SENSOR_ATTR(temp12_fault, 0444, show_temp_fault, NULL, 11),
+ SENSOR_ATTR(temp12_alarm, 0444, show_temp_alarm, NULL, 11),
+ SENSOR_ATTR(temp13_input, 0444, show_temp_value, NULL, 12),
+ SENSOR_ATTR(temp13_fault, 0444, show_temp_fault, NULL, 12),
+ SENSOR_ATTR(temp13_alarm, 0444, show_temp_alarm, NULL, 12),
+ SENSOR_ATTR(temp14_input, 0444, show_temp_value, NULL, 13),
+ SENSOR_ATTR(temp14_fault, 0444, show_temp_fault, NULL, 13),
+ SENSOR_ATTR(temp14_alarm, 0444, show_temp_alarm, NULL, 13),
+ SENSOR_ATTR(temp15_input, 0444, show_temp_value, NULL, 14),
+ SENSOR_ATTR(temp15_fault, 0444, show_temp_fault, NULL, 14),
+ SENSOR_ATTR(temp15_alarm, 0444, show_temp_alarm, NULL, 14),
+ SENSOR_ATTR(temp16_input, 0444, show_temp_value, NULL, 15),
+ SENSOR_ATTR(temp16_fault, 0444, show_temp_fault, NULL, 15),
+ SENSOR_ATTR(temp16_alarm, 0444, show_temp_alarm, NULL, 15),
+};
+
+static struct sensor_device_attribute sch5636_fan_attr[] = {
+ SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0),
+ SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0),
+ SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0),
+ SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1),
+ SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1),
+ SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1),
+ SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2),
+ SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2),
+ SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2),
+ SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3),
+ SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3),
+ SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3),
+ SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4),
+ SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4),
+ SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4),
+ SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5),
+ SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5),
+ SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5),
+ SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6),
+ SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6),
+ SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6),
+ SENSOR_ATTR(fan8_input, 0444, show_fan_value, NULL, 7),
+ SENSOR_ATTR(fan8_fault, 0444, show_fan_fault, NULL, 7),
+ SENSOR_ATTR(fan8_alarm, 0444, show_fan_alarm, NULL, 7),
+};
+
+static int sch5636_remove(struct platform_device *pdev)
+{
+ struct sch5636_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ if (data->hwmon_dev)
+ hwmon_device_unregister(data->hwmon_dev);
+
+ for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++)
+ device_remove_file(&pdev->dev, &sch5636_attr[i].dev_attr);
+
+ for (i = 0; i < SCH5636_NO_TEMPS * 3; i++)
+ device_remove_file(&pdev->dev,
+ &sch5636_temp_attr[i].dev_attr);
+
+ for (i = 0; i < SCH5636_NO_FANS * 3; i++)
+ device_remove_file(&pdev->dev,
+ &sch5636_fan_attr[i].dev_attr);
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(data);
+
+ return 0;
+}
+
+static int __devinit sch5636_probe(struct platform_device *pdev)
+{
+ struct sch5636_data *data;
+ int i, err, val, revision[2];
+ char id[4];
+
+ data = kzalloc(sizeof(struct sch5636_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+ mutex_init(&data->update_lock);
+ platform_set_drvdata(pdev, data);
+
+ for (i = 0; i < 3; i++) {
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_FUJITSU_ID + i);
+ if (val < 0) {
+ pr_err("Could not read Fujitsu id byte at %#x\n",
+ SCH5636_REG_FUJITSU_ID + i);
+ err = val;
+ goto error;
+ }
+ id[i] = val;
+ }
+ id[i] = '\0';
+
+ if (strcmp(id, "THS")) {
+ pr_err("Unknown Fujitsu id: %02x%02x%02x\n",
+ id[0], id[1], id[2]);
+ err = -ENODEV;
+ goto error;
+ }
+
+ for (i = 0; i < 2; i++) {
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_FUJITSU_REV + i);
+ if (val < 0) {
+ err = val;
+ goto error;
+ }
+ revision[i] = val;
+ }
+ pr_info("Found %s chip at %#hx, revison: %d.%02d\n", DEVNAME,
+ data->addr, revision[0], revision[1]);
+
+ /* Read all temp + fan ctrl registers to determine which are active */
+ for (i = 0; i < SCH5636_NO_TEMPS; i++) {
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_TEMP_CTRL(i));
+ if (unlikely(val < 0)) {
+ err = val;
+ goto error;
+ }
+ data->temp_ctrl[i] = val;
+ }
+
+ for (i = 0; i < SCH5636_NO_FANS; i++) {
+ val = sch56xx_read_virtual_reg(data->addr,
+ SCH5636_REG_FAN_CTRL(i));
+ if (unlikely(val < 0)) {
+ err = val;
+ goto error;
+ }
+ data->fan_ctrl[i] = val;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++) {
+ err = device_create_file(&pdev->dev,
+ &sch5636_attr[i].dev_attr);
+ if (err)
+ goto error;
+ }
+
+ for (i = 0; i < (SCH5636_NO_TEMPS * 3); i++) {
+ if (data->temp_ctrl[i/3] & SCH5636_TEMP_DEACTIVATED)
+ continue;
+
+ err = device_create_file(&pdev->dev,
+ &sch5636_temp_attr[i].dev_attr);
+ if (err)
+ goto error;
+ }
+
+ for (i = 0; i < (SCH5636_NO_FANS * 3); i++) {
+ if (data->fan_ctrl[i/3] & SCH5636_FAN_DEACTIVATED)
+ continue;
+
+ err = device_create_file(&pdev->dev,
+ &sch5636_fan_attr[i].dev_attr);
+ if (err)
+ goto error;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ data->hwmon_dev = NULL;
+ goto error;
+ }
+
+ return 0;
+
+error:
+ sch5636_remove(pdev);
+ return err;
+}
+
+static struct platform_driver sch5636_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = sch5636_probe,
+ .remove = sch5636_remove,
+};
+
+static int __init sch5636_init(void)
+{
+ return platform_driver_register(&sch5636_driver);
+}
+
+static void __exit sch5636_exit(void)
+{
+ platform_driver_unregister(&sch5636_driver);
+}
+
+MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
+
+module_init(sch5636_init);
+module_exit(sch5636_exit);
diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
new file mode 100644
index 000000000000..fac32ee0b10e
--- /dev/null
+++ b/drivers/hwmon/sch56xx-common.c
@@ -0,0 +1,340 @@
+/***************************************************************************
+ * Copyright (C) 2010-2011 Hans de Goede <hdegoede@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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include "sch56xx-common.h"
+
+#define SIO_SCH56XX_LD_EM 0x0C /* Embedded uController Logical Dev */
+#define SIO_UNLOCK_KEY 0x55 /* Key to enable Super-I/O */
+#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
+
+#define SIO_REG_LDSEL 0x07 /* Logical device select */
+#define SIO_REG_DEVID 0x20 /* Device ID */
+#define SIO_REG_ENABLE 0x30 /* Logical device enable */
+#define SIO_REG_ADDR 0x66 /* Logical device address (2 bytes) */
+
+#define SIO_SCH5627_ID 0xC6 /* Chipset ID */
+#define SIO_SCH5636_ID 0xC7 /* Chipset ID */
+
+#define REGION_LENGTH 9
+
+#define SCH56XX_CMD_READ 0x02
+#define SCH56XX_CMD_WRITE 0x03
+
+static struct platform_device *sch56xx_pdev;
+
+/* Super I/O functions */
+static inline int superio_inb(int base, int reg)
+{
+ outb(reg, base);
+ return inb(base + 1);
+}
+
+static inline int superio_enter(int base)
+{
+ /* Don't step on other drivers' I/O space by accident */
+ if (!request_muxed_region(base, 2, "sch56xx")) {
+ pr_err("I/O address 0x%04x already in use\n", base);
+ return -EBUSY;
+ }
+
+ outb(SIO_UNLOCK_KEY, base);
+
+ return 0;
+}
+
+static inline void superio_select(int base, int ld)
+{
+ outb(SIO_REG_LDSEL, base);
+ outb(ld, base + 1);
+}
+
+static inline void superio_exit(int base)
+{
+ outb(SIO_LOCK_KEY, base);
+ release_region(base, 2);
+}
+
+static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
+{
+ u8 val;
+ int i;
+ /*
+ * According to SMSC for the commands we use the maximum time for
+ * the EM to respond is 15 ms, but testing shows in practice it
+ * responds within 15-32 reads, so we first busy poll, and if
+ * that fails sleep a bit and try again until we are way past
+ * the 15 ms maximum response time.
+ */
+ const int max_busy_polls = 64;
+ const int max_lazy_polls = 32;
+
+ /* (Optional) Write-Clear the EC to Host Mailbox Register */
+ val = inb(addr + 1);
+ outb(val, addr + 1);
+
+ /* Set Mailbox Address Pointer to first location in Region 1 */
+ outb(0x00, addr + 2);
+ outb(0x80, addr + 3);
+
+ /* Write Request Packet Header */
+ outb(cmd, addr + 4); /* VREG Access Type read:0x02 write:0x03 */
+ outb(0x01, addr + 5); /* # of Entries: 1 Byte (8-bit) */
+ outb(0x04, addr + 2); /* Mailbox AP to first data entry loc. */
+
+ /* Write Value field */
+ if (cmd == SCH56XX_CMD_WRITE)
+ outb(v, addr + 4);
+
+ /* Write Address field */
+ outb(reg & 0xff, addr + 6);
+ outb(reg >> 8, addr + 7);
+
+ /* Execute the Random Access Command */
+ outb(0x01, addr); /* Write 01h to the Host-to-EC register */
+
+ /* EM Interface Polling "Algorithm" */
+ for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
+ if (i >= max_busy_polls)
+ msleep(1);
+ /* Read Interrupt source Register */
+ val = inb(addr + 8);
+ /* Write Clear the interrupt source bits */
+ if (val)
+ outb(val, addr + 8);
+ /* Command Completed ? */
+ if (val & 0x01)
+ break;
+ }
+ if (i == max_busy_polls + max_lazy_polls) {
+ pr_err("Max retries exceeded reading virtual "
+ "register 0x%04hx (%d)\n", reg, 1);
+ return -EIO;
+ }
+
+ /*
+ * According to SMSC we may need to retry this, but sofar I've always
+ * seen this succeed in 1 try.
+ */
+ for (i = 0; i < max_busy_polls; i++) {
+ /* Read EC-to-Host Register */
+ val = inb(addr + 1);
+ /* Command Completed ? */
+ if (val == 0x01)
+ break;
+
+ if (i == 0)
+ pr_warn("EC reports: 0x%02x reading virtual register "
+ "0x%04hx\n", (unsigned int)val, reg);
+ }
+ if (i == max_busy_polls) {
+ pr_err("Max retries exceeded reading virtual "
+ "register 0x%04hx (%d)\n", reg, 2);
+ return -EIO;
+ }
+
+ /*
+ * According to the SMSC app note we should now do:
+ *
+ * Set Mailbox Address Pointer to first location in Region 1 *
+ * outb(0x00, addr + 2);
+ * outb(0x80, addr + 3);
+ *
+ * But if we do that things don't work, so let's not.
+ */
+
+ /* Read Value field */
+ if (cmd == SCH56XX_CMD_READ)
+ return inb(addr + 4);
+
+ return 0;
+}
+
+int sch56xx_read_virtual_reg(u16 addr, u16 reg)
+{
+ return sch56xx_send_cmd(addr, SCH56XX_CMD_READ, reg, 0);
+}
+EXPORT_SYMBOL(sch56xx_read_virtual_reg);
+
+int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val)
+{
+ return sch56xx_send_cmd(addr, SCH56XX_CMD_WRITE, reg, val);
+}
+EXPORT_SYMBOL(sch56xx_write_virtual_reg);
+
+int sch56xx_read_virtual_reg16(u16 addr, u16 reg)
+{
+ int lsb, msb;
+
+ /* Read LSB first, this will cause the matching MSB to be latched */
+ lsb = sch56xx_read_virtual_reg(addr, reg);
+ if (lsb < 0)
+ return lsb;
+
+ msb = sch56xx_read_virtual_reg(addr, reg + 1);
+ if (msb < 0)
+ return msb;
+
+ return lsb | (msb << 8);
+}
+EXPORT_SYMBOL(sch56xx_read_virtual_reg16);
+
+int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
+ int high_nibble)
+{
+ int msb, lsn;
+
+ /* Read MSB first, this will cause the matching LSN to be latched */
+ msb = sch56xx_read_virtual_reg(addr, msb_reg);
+ if (msb < 0)
+ return msb;
+
+ lsn = sch56xx_read_virtual_reg(addr, lsn_reg);
+ if (lsn < 0)
+ return lsn;
+
+ if (high_nibble)
+ return (msb << 4) | (lsn >> 4);
+ else
+ return (msb << 4) | (lsn & 0x0f);
+}
+EXPORT_SYMBOL(sch56xx_read_virtual_reg12);
+
+static int __init sch56xx_find(int sioaddr, unsigned short *address,
+ const char **name)
+{
+ u8 devid;
+ int err;
+
+ err = superio_enter(sioaddr);
+ if (err)
+ return err;
+
+ devid = superio_inb(sioaddr, SIO_REG_DEVID);
+ switch (devid) {
+ case SIO_SCH5627_ID:
+ *name = "sch5627";
+ break;
+ case SIO_SCH5636_ID:
+ *name = "sch5636";
+ break;
+ default:
+ pr_debug("Unsupported device id: 0x%02x\n",
+ (unsigned int)devid);
+ err = -ENODEV;
+ goto exit;
+ }
+
+ superio_select(sioaddr, SIO_SCH56XX_LD_EM);
+
+ if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+ pr_warn("Device not activated\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+ /*
+ * Warning the order of the low / high byte is the other way around
+ * as on most other superio devices!!
+ */
+ *address = superio_inb(sioaddr, SIO_REG_ADDR) |
+ superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
+ if (*address == 0) {
+ pr_warn("Base address not set\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+exit:
+ superio_exit(sioaddr);
+ return err;
+}
+
+static int __init sch56xx_device_add(unsigned short address, const char *name)
+{
+ struct resource res = {
+ .start = address,
+ .end = address + REGION_LENGTH - 1,
+ .flags = IORESOURCE_IO,
+ };
+ int err;
+
+ sch56xx_pdev = platform_device_alloc(name, address);
+ if (!sch56xx_pdev)
+ return -ENOMEM;
+
+ res.name = sch56xx_pdev->name;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit_device_put;
+
+ err = platform_device_add_resources(sch56xx_pdev, &res, 1);
+ if (err) {
+ pr_err("Device resource addition failed\n");
+ goto exit_device_put;
+ }
+
+ err = platform_device_add(sch56xx_pdev);
+ if (err) {
+ pr_err("Device addition failed\n");
+ goto exit_device_put;
+ }
+
+ return 0;
+
+exit_device_put:
+ platform_device_put(sch56xx_pdev);
+
+ return err;
+}
+
+static int __init sch56xx_init(void)
+{
+ int err;
+ unsigned short address;
+ const char *name;
+
+ err = sch56xx_find(0x4e, &address, &name);
+ if (err)
+ err = sch56xx_find(0x2e, &address, &name);
+ if (err)
+ return err;
+
+ return sch56xx_device_add(address, name);
+}
+
+static void __exit sch56xx_exit(void)
+{
+ platform_device_unregister(sch56xx_pdev);
+}
+
+MODULE_DESCRIPTION("SMSC SCH56xx Hardware Monitoring Common Code");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
+
+module_init(sch56xx_init);
+module_exit(sch56xx_exit);
diff --git a/drivers/hwmon/sch56xx-common.h b/drivers/hwmon/sch56xx-common.h
new file mode 100644
index 000000000000..d5eaf3b9ebf5
--- /dev/null
+++ b/drivers/hwmon/sch56xx-common.h
@@ -0,0 +1,24 @@
+/***************************************************************************
+ * Copyright (C) 2010-2011 Hans de Goede <hdegoede@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; 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. *
+ ***************************************************************************/
+
+int sch56xx_read_virtual_reg(u16 addr, u16 reg);
+int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val);
+int sch56xx_read_virtual_reg16(u16 addr, u16 reg);
+int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
+ int high_nibble);
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index cf4330b352ef..fe4104c6b764 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -32,7 +32,7 @@
#include <linux/sht15.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/* Commands */
#define SHT15_MEASURE_TEMP 0x03
@@ -671,7 +671,7 @@ static ssize_t sht15_show_status(struct device *dev,
* @buf: sysfs buffer to read the new heater state from.
* @count: length of the data.
*
- * Will be called on read access to heater_enable sysfs attribute.
+ * Will be called on write access to heater_enable sysfs attribute.
* Returns number of bytes actually decoded, negative errno on error.
*/
static ssize_t sht15_store_heater(struct device *dev,
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 0d18de424c66..8eac67d769fa 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
#include <linux/sysfs.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
@@ -48,8 +49,10 @@ enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME };
struct via_cputemp_data {
struct device *hwmon_dev;
const char *name;
+ u8 vrm;
u32 id;
- u32 msr;
+ u32 msr_temp;
+ u32 msr_vid;
};
/*
@@ -77,13 +80,27 @@ static ssize_t show_temp(struct device *dev,
u32 eax, edx;
int err;
- err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+ err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx);
if (err)
return -EAGAIN;
return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000);
}
+static ssize_t show_cpu_vid(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct via_cputemp_data *data = dev_get_drvdata(dev);
+ u32 eax, edx;
+ int err;
+
+ err = rdmsr_safe_on_cpu(data->id, data->msr_vid, &eax, &edx);
+ if (err)
+ return -EAGAIN;
+
+ return sprintf(buf, "%d\n", vid_from_reg(~edx & 0x7f, data->vrm));
+}
+
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
SHOW_TEMP);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
@@ -100,6 +117,9 @@ static const struct attribute_group via_cputemp_group = {
.attrs = via_cputemp_attributes,
};
+/* Optional attributes */
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL);
+
static int __devinit via_cputemp_probe(struct platform_device *pdev)
{
struct via_cputemp_data *data;
@@ -122,11 +142,12 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
/* C7 A */
case 0xD:
/* C7 D */
- data->msr = 0x1169;
+ data->msr_temp = 0x1169;
+ data->msr_vid = 0x198;
break;
case 0xF:
/* Nano */
- data->msr = 0x1423;
+ data->msr_temp = 0x1423;
break;
default:
err = -ENODEV;
@@ -134,7 +155,7 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
}
/* test if we can access the TEMPERATURE MSR */
- err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+ err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx);
if (err) {
dev_err(&pdev->dev,
"Unable to access TEMPERATURE MSR, giving up\n");
@@ -147,6 +168,15 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
if (err)
goto exit_free;
+ if (data->msr_vid)
+ data->vrm = vid_which_vrm();
+
+ if (data->vrm) {
+ err = device_create_file(&pdev->dev, &dev_attr_cpu0_vid);
+ if (err)
+ goto exit_remove;
+ }
+
data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
@@ -158,6 +188,8 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
return 0;
exit_remove:
+ if (data->vrm)
+ device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
exit_free:
platform_set_drvdata(pdev, NULL);
@@ -171,6 +203,8 @@ static int __devexit via_cputemp_remove(struct platform_device *pdev)
struct via_cputemp_data *data = platform_get_drvdata(pdev);
hwmon_device_unregister(data->hwmon_dev);
+ if (data->vrm)
+ device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
platform_set_drvdata(pdev, NULL);
kfree(data);
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 30f06e956bfb..5f13c62e64b4 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -7,7 +7,7 @@ menuconfig I2C
depends on HAS_IOMEM
select RT_MUTEXES
---help---
- I2C (pronounce: I-square-C) is a slow serial bus protocol used in
+ I2C (pronounce: I-squared-C) is a slow serial bus protocol used in
many micro controller applications and developed by Philips. SMBus,
or System Management Bus is a subset of the I2C protocol. More
information is contained in the directory <file:Documentation/i2c/>,
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index dd364171f9c5..b6807db7b36f 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -1,23 +1,23 @@
/*
- Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>,
- Philip Edelbrock <phil@netroedge.com>,
- Mark D. Studebaker <mdsxyz123@yahoo.com>,
- Dan Eaton <dan.eaton@rocketlogix.com> and
- Stephen Rousset<stephen.rousset@rocketlogix.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.
+ * Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>,
+ * Philip Edelbrock <phil@netroedge.com>,
+ * Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ * Dan Eaton <dan.eaton@rocketlogix.com> and
+ * Stephen Rousset <stephen.rousset@rocketlogix.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.
*/
/*
@@ -254,8 +254,8 @@ static int ali1535_transaction(struct i2c_adapter *adap)
if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
/* do a clear-on-write */
outb_p(0xFF, SMBHSTSTS);
- if ((temp = inb_p(SMBHSTSTS)) &
- (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
+ temp = inb_p(SMBHSTSTS);
+ if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
/* This is probably going to be correctable only by a
* power reset as one of the bits now appears to be
* stuck */
@@ -267,9 +267,8 @@ static int ali1535_transaction(struct i2c_adapter *adap)
}
} else {
/* check and clear done bit */
- if (temp & ALI1535_STS_DONE) {
+ if (temp & ALI1535_STS_DONE)
outb_p(temp, SMBHSTSTS);
- }
}
/* start the transaction by writing anything to the start register */
@@ -278,7 +277,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
/* We will always wait for a fraction of a second! */
timeout = 0;
do {
- msleep(1);
+ usleep_range(1000, 2000);
temp = inb_p(SMBHSTSTS);
} while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE))
&& (timeout++ < MAX_TIMEOUT));
@@ -325,12 +324,12 @@ static int ali1535_transaction(struct i2c_adapter *adap)
/* take consequent actions for error conditions */
if (!(temp & ALI1535_STS_DONE)) {
/* issue "kill" to reset host controller */
- outb_p(ALI1535_KILL,SMBHSTTYP);
- outb_p(0xFF,SMBHSTSTS);
+ outb_p(ALI1535_KILL, SMBHSTTYP);
+ outb_p(0xFF, SMBHSTSTS);
} else if (temp & ALI1535_STS_ERR) {
/* issue "timeout" to reset all devices on bus */
- outb_p(ALI1535_T_OUT,SMBHSTTYP);
- outb_p(0xFF,SMBHSTSTS);
+ outb_p(ALI1535_T_OUT, SMBHSTTYP);
+ outb_p(0xFF, SMBHSTSTS);
}
return result;
@@ -351,7 +350,7 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
for (timeout = 0;
(timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE);
timeout++) {
- msleep(1);
+ usleep_range(1000, 2000);
temp = inb_p(SMBHSTSTS);
}
if (timeout >= MAX_TIMEOUT)
@@ -480,12 +479,12 @@ static struct i2c_adapter ali1535_adapter = {
.algo = &smbus_algorithm,
};
-static const struct pci_device_id ali1535_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(ali1535_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
{ },
};
-MODULE_DEVICE_TABLE (pci, ali1535_ids);
+MODULE_DEVICE_TABLE(pci, ali1535_ids);
static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index 3a20961bef1e..b1d9cd28d8da 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -662,11 +662,8 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev)
/* register new adapter to i2c module... */
data = of_get_property(ofdev->dev.of_node, "linux,i2c-index", &len);
- if (data && len == 4) {
- cpm->adap.nr = *data;
- result = i2c_add_numbered_adapter(&cpm->adap);
- } else
- result = i2c_add_adapter(&cpm->adap);
+ cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
+ result = i2c_add_numbered_adapter(&cpm->adap);
if (result < 0) {
dev_err(&ofdev->dev, "Unable to register with I2C\n");
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 8abfa4a03ce1..ce1a32b71e47 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -673,32 +673,33 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
/* transfer not completed */
adap->pch_i2c_xfer_in_progress = true;
- pmsg = &msgs[0];
- pmsg->flags |= adap->pch_buff_mode_en;
- status = pmsg->flags;
- pch_dbg(adap,
- "After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
- /* calculate sub address length and message length */
- /* these are applicable only for buffer mode */
- subaddrlen = pmsg->buf[0];
- /* calculate actual message length excluding
- * the sub address fields */
- msglen = (pmsg->len) - (subaddrlen + 1);
- if (status & (I2C_M_RD)) {
- pch_dbg(adap, "invoking pch_i2c_readbytes\n");
- ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
- (i == 0));
- } else {
- pch_dbg(adap, "invoking pch_i2c_writebytes\n");
- ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
- (i == 0));
+ for (i = 0; i < num && ret >= 0; i++) {
+ pmsg = &msgs[i];
+ pmsg->flags |= adap->pch_buff_mode_en;
+ status = pmsg->flags;
+ pch_dbg(adap,
+ "After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
+ /* calculate sub address length and message length */
+ /* these are applicable only for buffer mode */
+ subaddrlen = pmsg->buf[0];
+ /* calculate actual message length excluding
+ * the sub address fields */
+ msglen = (pmsg->len) - (subaddrlen + 1);
+
+ if ((status & (I2C_M_RD)) != false) {
+ ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
+ (i == 0));
+ } else {
+ ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
+ (i == 0));
+ }
}
adap->pch_i2c_xfer_in_progress = false; /* transfer completed */
mutex_unlock(&pch_mutex);
- return ret;
+ return (ret < 0) ? ret : num;
}
/**
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index 3df1bc80f37a..3876a2478bd7 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -227,7 +227,7 @@ static int highlander_i2c_read(struct highlander_i2c_dev *dev)
/*
* The R0P7780LC0011RL FPGA needs a significant delay between
- * data read cycles, otherwise the transciever gets confused and
+ * data read cycles, otherwise the transceiver gets confused and
* garbage is returned when the read is subsequently aborted.
*
* It is not sufficient to wait for BBSY.
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 58a58c7eaa17..1a766cf74f6b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -204,7 +204,7 @@ struct omap_i2c_dev {
u16 errata;
};
-const static u8 reg_map[] = {
+static const u8 reg_map[] = {
[OMAP_I2C_REV_REG] = 0x00,
[OMAP_I2C_IE_REG] = 0x01,
[OMAP_I2C_STAT_REG] = 0x02,
@@ -225,7 +225,7 @@ const static u8 reg_map[] = {
[OMAP_I2C_BUFSTAT_REG] = 0x10,
};
-const static u8 omap4_reg_map[] = {
+static const u8 omap4_reg_map[] = {
[OMAP_I2C_REV_REG] = 0x04,
[OMAP_I2C_IE_REG] = 0x2c,
[OMAP_I2C_STAT_REG] = 0x28,
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index f59224a5c761..d60364650990 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1079,7 +1079,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
* The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters.
*/
- i2c->adap.nr = dev->id != -1 ? dev->id : 0;
+ i2c->adap.nr = dev->id;
snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
i2c->adap.nr);
@@ -1142,10 +1142,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->adap.dev.of_node = dev->dev.of_node;
#endif
- if (i2c_type == REGS_CE4100)
- ret = i2c_add_adapter(&i2c->adap);
- else
- ret = i2c_add_numbered_adapter(&i2c->adap);
+ ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
printk(KERN_INFO "I2C: Failed to add bus\n");
goto eadapt;
diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c
index cb5d01e279c6..c64ba736f480 100644
--- a/drivers/i2c/busses/i2c-s6000.c
+++ b/drivers/i2c/busses/i2c-s6000.c
@@ -341,10 +341,7 @@ static int __devinit s6i2c_probe(struct platform_device *dev)
i2c_wr16(iface, S6_I2C_TXTL, 0);
platform_set_drvdata(dev, iface);
- if (bus_num < 0)
- rc = i2c_add_adapter(p_adap);
- else
- rc = i2c_add_numbered_adapter(p_adap);
+ rc = i2c_add_numbered_adapter(p_adap);
if (rc)
goto err_irq_free;
return 0;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index fb3b4f8f8152..2440b7411978 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/i2c-tegra.h>
+#include <linux/of_i2c.h>
#include <asm/unaligned.h>
@@ -546,6 +547,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
struct resource *iomem;
struct clk *clk;
struct clk *i2c_clk;
+ const unsigned int *prop;
void *base;
int irq;
int ret = 0;
@@ -603,7 +605,17 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->irq = irq;
i2c_dev->cont_id = pdev->id;
i2c_dev->dev = &pdev->dev;
- i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate : 100000;
+
+ i2c_dev->bus_clk_rate = 100000; /* default clock rate */
+ if (pdata) {
+ i2c_dev->bus_clk_rate = pdata->bus_clk_rate;
+
+ } else if (i2c_dev->dev->of_node) { /* if there is a device tree node ... */
+ prop = of_get_property(i2c_dev->dev->of_node,
+ "clock-frequency", NULL);
+ if (prop)
+ i2c_dev->bus_clk_rate = be32_to_cpup(prop);
+ }
if (pdev->id == 3)
i2c_dev->is_dvc = 1;
@@ -633,6 +645,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->adapter.algo = &tegra_i2c_algo;
i2c_dev->adapter.dev.parent = &pdev->dev;
i2c_dev->adapter.nr = pdev->id;
+ i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (ret) {
@@ -640,6 +653,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
goto err_free_irq;
}
+ of_i2c_register_devices(&i2c_dev->adapter);
+
return 0;
err_free_irq:
free_irq(i2c_dev->irq, i2c_dev);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 9a58994ff7ea..131079a3e292 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -925,6 +925,9 @@ EXPORT_SYMBOL(i2c_add_adapter);
* or otherwise built in to the system's mainboard, and where i2c_board_info
* is used to properly configure I2C devices.
*
+ * If the requested bus number is set to -1, then this function will behave
+ * identically to i2c_add_adapter, and will dynamically assign a bus number.
+ *
* If no devices have pre-been declared for this bus, then be sure to
* register the adapter before any dynamically allocated ones. Otherwise
* the required bus ID may not be available.
@@ -940,6 +943,8 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap)
int id;
int status;
+ if (adap->nr == -1) /* -1 means dynamically assign bus id */
+ return i2c_add_adapter(adap);
if (adap->nr & ~MAX_ID_MASK)
return -EINVAL;
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c
index 9e8f4e1b0cc9..712c7904d03e 100644
--- a/drivers/ide/palm_bk3710.c
+++ b/drivers/ide/palm_bk3710.c
@@ -342,7 +342,7 @@ static int __init palm_bk3710_probe(struct platform_device *pdev)
return -ENODEV;
}
- mem_size = mem->end - mem->start + 1;
+ mem_size = resource_size(mem);
if (request_mem_region(mem->start, mem_size, "palm_bk3710") == NULL) {
printk(KERN_ERR "failed to request memory region\n");
return -EBUSY;
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index bed3e39aac96..71c231954972 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -551,10 +551,10 @@ static int __init tx4939ide_probe(struct platform_device *pdev)
return -ENODEV;
if (!devm_request_mem_region(&pdev->dev, res->start,
- res->end - res->start + 1, "tx4938ide"))
+ resource_size(res), "tx4938ide"))
return -EBUSY;
mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start,
- res->end - res->start + 1);
+ resource_size(res));
if (!mapbase)
return -EBUSY;
memset(&hw, 0, sizeof(hw));
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
index 68999137dedf..800a3894af0d 100644
--- a/drivers/ieee802154/Makefile
+++ b/drivers/ieee802154/Makefile
@@ -1,3 +1 @@
obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
-
-ccflags-y := -DDEBUG -DCONFIG_FFD
diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
index a5a49a1baae7..eb0e2ccc79ae 100644
--- a/drivers/ieee802154/fakehard.c
+++ b/drivers/ieee802154/fakehard.c
@@ -370,8 +370,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
return -ENOMEM;
}
- phy->dev.platform_data = dev;
-
memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
dev->addr_len);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8e21d457b899..236ad9a89c0a 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -215,7 +215,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
- neigh_event_send(rt->dst.neighbour, NULL);
+ neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
ret = -ENODATA;
if (neigh)
goto release;
@@ -273,9 +273,10 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
goto put;
}
- neigh = dst->neighbour;
+ neigh = dst_get_neighbour(dst);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
- neigh_event_send(dst->neighbour, NULL);
+ if (neigh)
+ neigh_event_send(neigh, NULL);
ret = -ENODATA;
goto put;
}
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index f9ba7d74dfc0..9353992f9eea 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -302,7 +302,8 @@ static void ib_cache_event(struct ib_event_handler *handler,
event->event == IB_EVENT_LID_CHANGE ||
event->event == IB_EVENT_PKEY_CHANGE ||
event->event == IB_EVENT_SM_CHANGE ||
- event->event == IB_EVENT_CLIENT_REREGISTER) {
+ event->event == IB_EVENT_CLIENT_REREGISTER ||
+ event->event == IB_EVENT_GID_CHANGE) {
work = kmalloc(sizeof *work, GFP_ATOMIC);
if (work) {
INIT_WORK(&work->work, ib_cache_task);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b6a33b3c516d..ca4c5dcd7133 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -359,6 +359,10 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
+ if (dev_ll != IB_LINK_LAYER_INFINIBAND &&
+ id_priv->id.ps == RDMA_PS_IPOIB)
+ return -EINVAL;
+
mutex_lock(&lock);
iboe_addr_get_sgid(dev_addr, &iboe_gid);
memcpy(&gid, dev_addr->src_dev_addr +
@@ -406,11 +410,6 @@ static int cma_disable_callback(struct rdma_id_private *id_priv,
return 0;
}
-static int cma_has_cm_dev(struct rdma_id_private *id_priv)
-{
- return (id_priv->id.device && id_priv->cm_id.ib);
-}
-
struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
void *context, enum rdma_port_space ps,
enum ib_qp_type qp_type)
@@ -920,11 +919,11 @@ void rdma_destroy_id(struct rdma_cm_id *id)
if (id_priv->cma_dev) {
switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+ if (id_priv->cm_id.ib)
ib_destroy_cm_id(id_priv->cm_id.ib);
break;
case RDMA_TRANSPORT_IWARP:
- if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw))
+ if (id_priv->cm_id.iw)
iw_destroy_cm_id(id_priv->cm_id.iw);
break;
default:
@@ -1085,12 +1084,12 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
if (cma_get_net_info(ib_event->private_data, listen_id->ps,
&ip_ver, &port, &src, &dst))
- goto err;
+ return NULL;
id = rdma_create_id(listen_id->event_handler, listen_id->context,
listen_id->ps, ib_event->param.req_rcvd.qp_type);
if (IS_ERR(id))
- goto err;
+ return NULL;
cma_save_net_info(&id->route.addr, &listen_id->route.addr,
ip_ver, port, src, dst);
@@ -1100,7 +1099,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths,
GFP_KERNEL);
if (!rt->path_rec)
- goto destroy_id;
+ goto err;
rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
if (rt->num_paths == 2)
@@ -1114,7 +1113,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr,
&rt->addr.dev_addr);
if (ret)
- goto destroy_id;
+ goto err;
}
rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
@@ -1122,9 +1121,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
id_priv->state = RDMA_CM_CONNECT;
return id_priv;
-destroy_id:
- rdma_destroy_id(id);
err:
+ rdma_destroy_id(id);
return NULL;
}
@@ -1468,13 +1466,15 @@ static int cma_ib_listen(struct rdma_id_private *id_priv)
{
struct ib_cm_compare_data compare_data;
struct sockaddr *addr;
+ struct ib_cm_id *id;
__be64 svc_id;
int ret;
- id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
- id_priv);
- if (IS_ERR(id_priv->cm_id.ib))
- return PTR_ERR(id_priv->cm_id.ib);
+ id = ib_create_cm_id(id_priv->id.device, cma_req_handler, id_priv);
+ if (IS_ERR(id))
+ return PTR_ERR(id);
+
+ id_priv->cm_id.ib = id;
addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
svc_id = cma_get_service_id(id_priv->id.ps, addr);
@@ -1497,12 +1497,15 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog)
{
int ret;
struct sockaddr_in *sin;
+ struct iw_cm_id *id;
+
+ id = iw_create_cm_id(id_priv->id.device,
+ iw_conn_req_handler,
+ id_priv);
+ if (IS_ERR(id))
+ return PTR_ERR(id);
- id_priv->cm_id.iw = iw_create_cm_id(id_priv->id.device,
- iw_conn_req_handler,
- id_priv);
- if (IS_ERR(id_priv->cm_id.iw))
- return PTR_ERR(id_priv->cm_id.iw);
+ id_priv->cm_id.iw = id;
sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
id_priv->cm_id.iw->local_addr = *sin;
@@ -2484,6 +2487,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
{
struct ib_cm_sidr_req_param req;
struct rdma_route *route;
+ struct ib_cm_id *id;
int ret;
req.private_data_len = sizeof(struct cma_hdr) +
@@ -2501,12 +2505,13 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
if (ret)
goto out;
- id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device,
- cma_sidr_rep_handler, id_priv);
- if (IS_ERR(id_priv->cm_id.ib)) {
- ret = PTR_ERR(id_priv->cm_id.ib);
+ id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler,
+ id_priv);
+ if (IS_ERR(id)) {
+ ret = PTR_ERR(id);
goto out;
}
+ id_priv->cm_id.ib = id;
req.path = route->path_rec;
req.service_id = cma_get_service_id(id_priv->id.ps,
@@ -2530,6 +2535,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
struct ib_cm_req_param req;
struct rdma_route *route;
void *private_data;
+ struct ib_cm_id *id;
int offset, ret;
memset(&req, 0, sizeof req);
@@ -2543,12 +2549,12 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
memcpy(private_data + offset, conn_param->private_data,
conn_param->private_data_len);
- id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
- id_priv);
- if (IS_ERR(id_priv->cm_id.ib)) {
- ret = PTR_ERR(id_priv->cm_id.ib);
+ id = ib_create_cm_id(id_priv->id.device, cma_ib_handler, id_priv);
+ if (IS_ERR(id)) {
+ ret = PTR_ERR(id);
goto out;
}
+ id_priv->cm_id.ib = id;
route = &id_priv->id.route;
ret = cma_format_hdr(private_data, id_priv->id.ps, route);
@@ -2577,8 +2583,8 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
out:
- if (ret && !IS_ERR(id_priv->cm_id.ib)) {
- ib_destroy_cm_id(id_priv->cm_id.ib);
+ if (ret && !IS_ERR(id)) {
+ ib_destroy_cm_id(id);
id_priv->cm_id.ib = NULL;
}
@@ -2595,10 +2601,8 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
struct iw_cm_conn_param iw_param;
cm_id = iw_create_cm_id(id_priv->id.device, cma_iw_handler, id_priv);
- if (IS_ERR(cm_id)) {
- ret = PTR_ERR(cm_id);
- goto out;
- }
+ if (IS_ERR(cm_id))
+ return PTR_ERR(cm_id);
id_priv->cm_id.iw = cm_id;
@@ -2622,7 +2626,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
iw_param.qpn = conn_param->qp_num;
ret = iw_cm_connect(cm_id, &iw_param);
out:
- if (ret && !IS_ERR(cm_id)) {
+ if (ret) {
iw_destroy_cm_id(cm_id);
id_priv->cm_id.iw = NULL;
}
@@ -2795,7 +2799,7 @@ int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_has_cm_dev(id_priv))
+ if (!id_priv->cm_id.ib)
return -EINVAL;
switch (id->device->node_type) {
@@ -2817,7 +2821,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_has_cm_dev(id_priv))
+ if (!id_priv->cm_id.ib)
return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) {
@@ -2848,7 +2852,7 @@ int rdma_disconnect(struct rdma_cm_id *id)
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_has_cm_dev(id_priv))
+ if (!id_priv->cm_id.ib)
return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) {
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 4007f721d25d..e711de400a01 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -627,6 +627,9 @@ int ib_modify_device(struct ib_device *device,
int device_modify_mask,
struct ib_device_modify *device_modify)
{
+ if (!device->modify_device)
+ return -ENOSYS;
+
return device->modify_device(device, device_modify_mask,
device_modify);
}
@@ -647,6 +650,9 @@ int ib_modify_port(struct ib_device *device,
u8 port_num, int port_modify_mask,
struct ib_port_modify *port_modify)
{
+ if (!device->modify_port)
+ return -ENOSYS;
+
if (port_num < start_port(device) || port_num > end_port(device))
return -EINVAL;
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index 4a5abaf0a25c..9227f4acd79c 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -148,7 +148,7 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
return netlink_dump_start(nls, skb, nlh,
client->cb_table[op].dump,
- NULL);
+ NULL, 0);
}
}
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 0cfc455630d0..444470a28de2 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -36,6 +36,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/inetdevice.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index aeebc4d37e33..f101bb73be63 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -99,14 +99,6 @@ static int c2_query_port(struct ib_device *ibdev,
return 0;
}
-static int c2_modify_port(struct ib_device *ibdev,
- u8 port, int port_modify_mask,
- struct ib_port_modify *props)
-{
- pr_debug("%s:%u\n", __func__, __LINE__);
- return 0;
-}
-
static int c2_query_pkey(struct ib_device *ibdev,
u8 port, u16 index, u16 * pkey)
{
@@ -817,7 +809,6 @@ int c2_register_device(struct c2_dev *dev)
dev->ibdev.dma_device = &dev->pcidev->dev;
dev->ibdev.query_device = c2_query_device;
dev->ibdev.query_port = c2_query_port;
- dev->ibdev.modify_port = c2_modify_port;
dev->ibdev.query_pkey = c2_query_pkey;
dev->ibdev.query_gid = c2_query_gid;
dev->ibdev.alloc_ucontext = c2_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 0a5008fbebac..17bf9d95463c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1328,6 +1328,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
struct iwch_ep *child_ep, *parent_ep = ctx;
struct cpl_pass_accept_req *req = cplhdr(skb);
unsigned int hwtid = GET_TID(req);
+ struct neighbour *neigh;
struct dst_entry *dst;
struct l2t_entry *l2t;
struct rtable *rt;
@@ -1364,7 +1365,8 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
goto reject;
}
dst = &rt->dst;
- l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
+ neigh = dst_get_neighbour(dst);
+ l2t = t3_l2t_get(tdev, neigh, neigh->dev);
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__);
@@ -1874,10 +1876,11 @@ static int is_loopback_dst(struct iw_cm_id *cm_id)
int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
{
- int err = 0;
struct iwch_dev *h = to_iwch_dev(cm_id->device);
+ struct neighbour *neigh;
struct iwch_ep *ep;
struct rtable *rt;
+ int err = 0;
if (is_loopback_dst(cm_id)) {
err = -ENOSYS;
@@ -1933,9 +1936,10 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
ep->dst = &rt->dst;
+ neigh = dst_get_neighbour(ep->dst);
+
/* get a l2t entry */
- ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
- ep->dst->neighbour->dev);
+ ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 2e2741307af4..c7d9411f2954 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -61,13 +61,6 @@
#include "iwch_user.h"
#include "common.h"
-static int iwch_modify_port(struct ib_device *ibdev,
- u8 port, int port_modify_mask,
- struct ib_port_modify *props)
-{
- return -ENOSYS;
-}
-
static struct ib_ah *iwch_ah_create(struct ib_pd *pd,
struct ib_ah_attr *ah_attr)
{
@@ -1392,7 +1385,6 @@ int iwch_register_device(struct iwch_dev *dev)
dev->ibdev.dma_device = &(dev->rdev.rnic_info.pdev->dev);
dev->ibdev.query_device = iwch_query_device;
dev->ibdev.query_port = iwch_query_port;
- dev->ibdev.modify_port = iwch_modify_port;
dev->ibdev.query_pkey = iwch_query_pkey;
dev->ibdev.query_gid = iwch_query_gid;
dev->ibdev.alloc_ucontext = iwch_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 31fb44085c9b..77f769d9227d 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -1325,6 +1325,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));
struct tid_info *t = dev->rdev.lldi.tids;
unsigned int hwtid = GET_TID(req);
+ struct neighbour *neigh;
struct dst_entry *dst;
struct l2t_entry *l2t;
struct rtable *rt;
@@ -1357,11 +1358,11 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject;
}
dst = &rt->dst;
- if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
+ neigh = dst_get_neighbour(dst);
+ if (neigh->dev->flags & IFF_LOOPBACK) {
pdev = ip_dev_find(&init_net, peer_ip);
BUG_ON(!pdev);
- l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
- pdev, 0);
+ l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0);
mtu = pdev->mtu;
tx_chan = cxgb4_port_chan(pdev);
smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1372,17 +1373,16 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
dev_put(pdev);
} else {
- l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
- dst->neighbour->dev, 0);
+ l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0);
mtu = dst_mtu(dst);
- tx_chan = cxgb4_port_chan(dst->neighbour->dev);
- smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;
+ tx_chan = cxgb4_port_chan(neigh->dev);
+ smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
- txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;
- ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev);
+ txq_idx = cxgb4_port_idx(neigh->dev) * step;
+ ctrlq_idx = cxgb4_port_idx(neigh->dev);
step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
rss_qid = dev->rdev.lldi.rxq_ids[
- cxgb4_port_idx(dst->neighbour->dev) * step];
+ cxgb4_port_idx(neigh->dev) * step];
}
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
@@ -1847,6 +1847,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct c4iw_ep *ep;
struct rtable *rt;
struct net_device *pdev;
+ struct neighbour *neigh;
int step;
if ((conn_param->ord > c4iw_max_read_depth) ||
@@ -1908,14 +1909,15 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
ep->dst = &rt->dst;
+ neigh = dst_get_neighbour(ep->dst);
+
/* get a l2t entry */
- if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
+ if (neigh->dev->flags & IFF_LOOPBACK) {
PDBG("%s LOOPBACK\n", __func__);
pdev = ip_dev_find(&init_net,
cm_id->remote_addr.sin_addr.s_addr);
ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
- ep->dst->neighbour,
- pdev, 0);
+ neigh, pdev, 0);
ep->mtu = pdev->mtu;
ep->tx_chan = cxgb4_port_chan(pdev);
ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1930,20 +1932,18 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
dev_put(pdev);
} else {
ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
- ep->dst->neighbour,
- ep->dst->neighbour->dev, 0);
+ neigh, neigh->dev, 0);
ep->mtu = dst_mtu(ep->dst);
- ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev);
- ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) &
- 0x7F) << 1;
+ 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(ep->dst->neighbour->dev) * step;
- ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev);
+ 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(ep->dst->neighbour->dev) * step];
+ cxgb4_port_idx(neigh->dev) * step];
}
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 0347eed4a167..40c835309e49 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -31,7 +31,7 @@
*/
#include <rdma/ib_umem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "iw_cxgb4.h"
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 5b9e4220ca08..247fe706e7fa 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -58,13 +58,6 @@ static int fastreg_support = 1;
module_param(fastreg_support, int, 0644);
MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=1)");
-static int c4iw_modify_port(struct ib_device *ibdev,
- u8 port, int port_modify_mask,
- struct ib_port_modify *props)
-{
- return -ENOSYS;
-}
-
static struct ib_ah *c4iw_ah_create(struct ib_pd *pd,
struct ib_ah_attr *ah_attr)
{
@@ -456,7 +449,6 @@ int c4iw_register_device(struct c4iw_dev *dev)
dev->ibdev.dma_device = &(dev->rdev.lldi.pdev->dev);
dev->ibdev.query_device = c4iw_query_device;
dev->ibdev.query_port = c4iw_query_port;
- dev->ibdev.modify_port = c4iw_modify_port;
dev->ibdev.query_pkey = c4iw_query_pkey;
dev->ibdev.query_gid = c4iw_query_gid;
dev->ibdev.alloc_ucontext = c4iw_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index 4fb50d58b493..407ff3924150 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/genalloc.h>
+#include <linux/ratelimit.h>
#include "iw_cxgb4.h"
#define RANDOM_SIZE 16
@@ -311,8 +312,8 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
{
unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
- if (!addr && printk_ratelimit())
- printk(KERN_WARNING MOD "%s: Out of PBL memory\n",
+ if (!addr)
+ printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
pci_name(rdev->lldi.pdev));
return (u32)addr;
}
@@ -373,8 +374,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
{
unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6);
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
- if (!addr && printk_ratelimit())
- printk(KERN_WARNING MOD "%s: Out of RQT memory\n",
+ if (!addr)
+ printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
pci_name(rdev->lldi.pdev));
return (u32)addr;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index f09914cccf53..54c0d23bad92 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -58,7 +58,7 @@
#include <linux/cpu.h>
#include <linux/device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/abs_addr.h>
#include <asm/ibmebus.h>
#include <asm/io.h>
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index ee79a2d97b14..8697eca14356 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -40,6 +40,7 @@
#include <linux/highmem.h>
#include <linux/io.h>
#include <linux/jiffies.h>
+#include <linux/cpu.h>
#include <asm/pgtable.h>
#include "ipath_kernel.h"
@@ -1684,17 +1685,19 @@ static int find_best_unit(struct file *fp,
* information. There may be some issues with dual core numbering
* as well. This needs more work prior to release.
*/
- if (!cpumask_empty(&current->cpus_allowed) &&
- !cpumask_full(&current->cpus_allowed)) {
+ if (!cpumask_empty(tsk_cpus_allowed(current)) &&
+ !cpumask_full(tsk_cpus_allowed(current))) {
int ncpus = num_online_cpus(), curcpu = -1, nset = 0;
- for (i = 0; i < ncpus; i++)
- if (cpumask_test_cpu(i, &current->cpus_allowed)) {
+ get_online_cpus();
+ for_each_online_cpu(i)
+ if (cpumask_test_cpu(i, tsk_cpus_allowed(current))) {
ipath_cdbg(PROC, "%s[%u] affinity set for "
"cpu %d/%d\n", current->comm,
current->pid, i, ncpus);
curcpu = i;
nset++;
}
+ put_online_cpus();
if (curcpu != -1 && nset != ncpus) {
if (npresent) {
prefunit = curcpu / (ncpus / npresent);
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index ceb98ee78666..43f2d0424d4f 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -32,6 +32,7 @@
*/
#include <rdma/ib_smi.h>
+#include <rdma/ib_pma.h>
#include "ipath_kernel.h"
#include "ipath_verbs.h"
@@ -789,151 +790,18 @@ static int recv_subn_set_pkeytable(struct ib_smp *smp,
return recv_subn_get_pkeytable(smp, ibdev);
}
-#define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001)
-#define IB_PMA_PORT_SAMPLES_CONTROL cpu_to_be16(0x0010)
-#define IB_PMA_PORT_SAMPLES_RESULT cpu_to_be16(0x0011)
-#define IB_PMA_PORT_COUNTERS cpu_to_be16(0x0012)
-#define IB_PMA_PORT_COUNTERS_EXT cpu_to_be16(0x001D)
-#define IB_PMA_PORT_SAMPLES_RESULT_EXT cpu_to_be16(0x001E)
-
-struct ib_perf {
- u8 base_version;
- u8 mgmt_class;
- u8 class_version;
- u8 method;
- __be16 status;
- __be16 unused;
- __be64 tid;
- __be16 attr_id;
- __be16 resv;
- __be32 attr_mod;
- u8 reserved[40];
- u8 data[192];
-} __attribute__ ((packed));
-
-struct ib_pma_classportinfo {
- u8 base_version;
- u8 class_version;
- __be16 cap_mask;
- u8 reserved[3];
- u8 resp_time_value; /* only lower 5 bits */
- union ib_gid redirect_gid;
- __be32 redirect_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 redirect_lid;
- __be16 redirect_pkey;
- __be32 redirect_qp; /* only lower 24 bits */
- __be32 redirect_qkey;
- union ib_gid trap_gid;
- __be32 trap_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 trap_lid;
- __be16 trap_pkey;
- __be32 trap_hl_qp; /* 8, 24 bits respectively */
- __be32 trap_qkey;
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplescontrol {
- u8 opcode;
- u8 port_select;
- u8 tick;
- u8 counter_width; /* only lower 3 bits */
- __be32 counter_mask0_9; /* 2, 10 * 3, bits */
- __be16 counter_mask10_14; /* 1, 5 * 3, bits */
- u8 sample_mechanisms;
- u8 sample_status; /* only lower 2 bits */
- __be64 option_mask;
- __be64 vendor_mask;
- __be32 sample_start;
- __be32 sample_interval;
- __be16 tag;
- __be16 counter_select[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult_ext {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 extended_width; /* only upper 2 bits */
- __be64 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portcounters {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be16 symbol_error_counter;
- u8 link_error_recovery_counter;
- u8 link_downed_counter;
- __be16 port_rcv_errors;
- __be16 port_rcv_remphys_errors;
- __be16 port_rcv_switch_relay_errors;
- __be16 port_xmit_discards;
- u8 port_xmit_constraint_errors;
- u8 port_rcv_constraint_errors;
- u8 reserved1;
- u8 lli_ebor_errors; /* 4, 4, bits */
- __be16 reserved2;
- __be16 vl15_dropped;
- __be32 port_xmit_data;
- __be32 port_rcv_data;
- __be32 port_xmit_packets;
- __be32 port_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SEL_SYMBOL_ERROR cpu_to_be16(0x0001)
-#define IB_PMA_SEL_LINK_ERROR_RECOVERY cpu_to_be16(0x0002)
-#define IB_PMA_SEL_LINK_DOWNED cpu_to_be16(0x0004)
-#define IB_PMA_SEL_PORT_RCV_ERRORS cpu_to_be16(0x0008)
-#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS cpu_to_be16(0x0010)
-#define IB_PMA_SEL_PORT_XMIT_DISCARDS cpu_to_be16(0x0040)
-#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS cpu_to_be16(0x0200)
-#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS cpu_to_be16(0x0400)
-#define IB_PMA_SEL_PORT_VL15_DROPPED cpu_to_be16(0x0800)
-#define IB_PMA_SEL_PORT_XMIT_DATA cpu_to_be16(0x1000)
-#define IB_PMA_SEL_PORT_RCV_DATA cpu_to_be16(0x2000)
-#define IB_PMA_SEL_PORT_XMIT_PACKETS cpu_to_be16(0x4000)
-#define IB_PMA_SEL_PORT_RCV_PACKETS cpu_to_be16(0x8000)
-
-struct ib_pma_portcounters_ext {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be32 reserved1;
- __be64 port_xmit_data;
- __be64 port_rcv_data;
- __be64 port_xmit_packets;
- __be64 port_rcv_packets;
- __be64 port_unicast_xmit_packets;
- __be64 port_unicast_rcv_packets;
- __be64 port_multicast_xmit_packets;
- __be64 port_multicast_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SELX_PORT_XMIT_DATA cpu_to_be16(0x0001)
-#define IB_PMA_SELX_PORT_RCV_DATA cpu_to_be16(0x0002)
-#define IB_PMA_SELX_PORT_XMIT_PACKETS cpu_to_be16(0x0004)
-#define IB_PMA_SELX_PORT_RCV_PACKETS cpu_to_be16(0x0008)
-#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS cpu_to_be16(0x0010)
-#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS cpu_to_be16(0x0020)
-#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS cpu_to_be16(0x0040)
-#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS cpu_to_be16(0x0080)
-
-static int recv_pma_get_classportinfo(struct ib_perf *pmp)
+static int recv_pma_get_classportinfo(struct ib_pma_mad *pmp)
{
- struct ib_pma_classportinfo *p =
- (struct ib_pma_classportinfo *)pmp->data;
+ struct ib_class_port_info *p =
+ (struct ib_class_port_info *)pmp->data;
memset(pmp->data, 0, sizeof(pmp->data));
- if (pmp->attr_mod != 0)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0)
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
/* Indicate AllPortSelect is valid (only one port anyway) */
- p->cap_mask = cpu_to_be16(1 << 8);
+ p->capability_mask = cpu_to_be16(1 << 8);
p->base_version = 1;
p->class_version = 1;
/*
@@ -957,7 +825,7 @@ static int recv_pma_get_classportinfo(struct ib_perf *pmp)
COUNTER_MASK(1, 3) | \
COUNTER_MASK(1, 4))
-static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+static int recv_pma_get_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -970,9 +838,9 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(port_select != port && port_select != 0xFF))
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
/*
* Ticks are 10x the link transfer period which for 2.5Gbs is 4
* nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample
@@ -1006,7 +874,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+static int recv_pma_set_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -1017,9 +885,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
u8 status;
int ret;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(p->port_select != port && p->port_select != 0xFF)) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -1093,7 +961,7 @@ static u64 get_counter(struct ipath_ibdev *dev,
return ret;
}
-static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
+static int recv_pma_get_portsamplesresult(struct ib_pma_mad *pmp,
struct ib_device *ibdev)
{
struct ib_pma_portsamplesresult *p =
@@ -1118,7 +986,7 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+static int recv_pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev)
{
struct ib_pma_portsamplesresult_ext *p =
@@ -1145,7 +1013,7 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_get_portcounters(struct ib_perf *pmp,
+static int recv_pma_get_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1179,9 +1047,9 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(port_select != port && port_select != 0xFF))
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
if (cntrs.symbol_error_counter > 0xFFFFUL)
p->symbol_error_counter = cpu_to_be16(0xFFFF);
@@ -1216,7 +1084,7 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
cntrs.local_link_integrity_errors = 0xFUL;
if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
cntrs.excessive_buffer_overrun_errors = 0xFUL;
- p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+ p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors;
if (cntrs.vl15_dropped > 0xFFFFUL)
p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1244,7 +1112,7 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
+static int recv_pma_get_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters_ext *p =
@@ -1265,9 +1133,9 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 ||
+ if (pmp->mad_hdr.attr_mod != 0 ||
(port_select != port && port_select != 0xFF))
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
p->port_xmit_data = cpu_to_be64(swords);
p->port_rcv_data = cpu_to_be64(rwords);
@@ -1281,7 +1149,7 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int recv_pma_set_portcounters(struct ib_perf *pmp,
+static int recv_pma_set_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1344,7 +1212,7 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
return recv_pma_get_portcounters(pmp, ibdev, port);
}
-static int recv_pma_set_portcounters_ext(struct ib_perf *pmp,
+static int recv_pma_set_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1518,19 +1386,19 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
struct ib_mad *in_mad,
struct ib_mad *out_mad)
{
- struct ib_perf *pmp = (struct ib_perf *)out_mad;
+ struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
int ret;
*out_mad = *in_mad;
- if (pmp->class_version != 1) {
- pmp->status |= IB_SMP_UNSUP_VERSION;
+ if (pmp->mad_hdr.class_version != 1) {
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
- switch (pmp->method) {
+ switch (pmp->mad_hdr.method) {
case IB_MGMT_METHOD_GET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_CLASS_PORT_INFO:
ret = recv_pma_get_classportinfo(pmp);
goto bail;
@@ -1554,13 +1422,13 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
port_num);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
case IB_MGMT_METHOD_SET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_PORT_SAMPLES_CONTROL:
ret = recv_pma_set_portsamplescontrol(pmp, ibdev,
port_num);
@@ -1574,7 +1442,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
port_num);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -1588,7 +1456,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
ret = IB_MAD_RESULT_SUCCESS;
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METHOD;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD;
ret = reply((struct ib_smp *) pmp);
}
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 57ffa50f509e..f36da994a85a 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -35,6 +35,7 @@
#include <linux/mlx4/cmd.h>
#include <linux/gfp.h>
+#include <rdma/ib_pma.h>
#include "mlx4_ib.h"
@@ -232,7 +233,7 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma
}
}
-int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
struct ib_wc *in_wc, struct ib_grh *in_grh,
struct ib_mad *in_mad, struct ib_mad *out_mad)
{
@@ -302,6 +303,71 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
}
+static void edit_counter(struct mlx4_counter *cnt,
+ struct ib_pma_portcounters *pma_cnt)
+{
+ pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2));
+ pma_cnt->port_rcv_data = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2));
+ pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames));
+ pma_cnt->port_rcv_packets = cpu_to_be32(be64_to_cpu(cnt->rx_frames));
+}
+
+static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+ struct ib_wc *in_wc, struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ int err;
+ u32 inmod = dev->counters[port_num - 1] & 0xffff;
+ u8 mode;
+
+ if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
+ return -EINVAL;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev->dev);
+ if (IS_ERR(mailbox))
+ return IB_MAD_RESULT_FAILURE;
+
+ err = mlx4_cmd_box(dev->dev, 0, mailbox->dma, inmod, 0,
+ MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C);
+ if (err)
+ err = IB_MAD_RESULT_FAILURE;
+ else {
+ memset(out_mad->data, 0, sizeof out_mad->data);
+ mode = ((struct mlx4_counter *)mailbox->buf)->counter_mode;
+ switch (mode & 0xf) {
+ case 0:
+ edit_counter(mailbox->buf,
+ (void *)(out_mad->data + 40));
+ err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
+ break;
+ default:
+ err = IB_MAD_RESULT_FAILURE;
+ }
+ }
+
+ mlx4_free_cmd_mailbox(dev->dev, mailbox);
+
+ return err;
+}
+
+int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+ struct ib_wc *in_wc, struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+ switch (rdma_port_get_link_layer(ibdev, port_num)) {
+ case IB_LINK_LAYER_INFINIBAND:
+ return ib_process_mad(ibdev, mad_flags, port_num, in_wc,
+ in_grh, in_mad, out_mad);
+ case IB_LINK_LAYER_ETHERNET:
+ return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
+ in_grh, in_mad, out_mad);
+ default:
+ return -EINVAL;
+ }
+}
+
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *mad_send_wc)
{
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index fbe1973f77b0..fa643f4f4e28 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -816,7 +816,7 @@ static void update_gids_task(struct work_struct *work)
memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
event.device = &gw->dev->ib_dev;
event.element.port_num = gw->port;
- event.event = IB_EVENT_LID_CHANGE;
+ event.event = IB_EVENT_GID_CHANGE;
ib_dispatch_event(&event);
}
@@ -1098,11 +1098,21 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
if (init_node_data(ibdev))
goto err_map;
+ for (i = 0; i < ibdev->num_ports; ++i) {
+ if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) ==
+ IB_LINK_LAYER_ETHERNET) {
+ err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]);
+ if (err)
+ ibdev->counters[i] = -1;
+ } else
+ ibdev->counters[i] = -1;
+ }
+
spin_lock_init(&ibdev->sm_lock);
mutex_init(&ibdev->cap_mask_mutex);
if (ib_register_device(&ibdev->ib_dev, NULL))
- goto err_map;
+ goto err_counter;
if (mlx4_ib_mad_init(ibdev))
goto err_reg;
@@ -1132,6 +1142,10 @@ err_notif:
err_reg:
ib_unregister_device(&ibdev->ib_dev);
+err_counter:
+ for (; i; --i)
+ mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
+
err_map:
iounmap(ibdev->uar_map);
@@ -1160,7 +1174,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
ibdev->iboe.nb.notifier_call = NULL;
}
iounmap(ibdev->uar_map);
-
+ for (p = 0; p < ibdev->num_ports; ++p)
+ mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
mlx4_CLOSE_PORT(dev, p);
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 2a322f21049f..e4bf2cff8662 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -193,6 +193,7 @@ struct mlx4_ib_dev {
struct mutex cap_mask_mutex;
bool ib_active;
struct mlx4_ib_iboe iboe;
+ int counters[MLX4_MAX_PORTS];
};
static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 2001f20a4361..3a91d9d8dc51 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -893,7 +893,6 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
--path->static_rate;
} else
path->static_rate = 0;
- path->counter_index = 0xff;
if (ah->ah_flags & IB_AH_GRH) {
if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len[port]) {
@@ -1034,6 +1033,15 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
}
}
+ if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
+ if (dev->counters[qp->port - 1] != -1) {
+ context->pri_path.counter_index =
+ dev->counters[qp->port - 1];
+ optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX;
+ } else
+ context->pri_path.counter_index = 0xff;
+ }
+
if (attr_mask & IB_QP_PKEY_INDEX) {
context->pri_path.pkey_index = attr->pkey_index;
optpar |= MLX4_QP_OPTPAR_PKEY_INDEX;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 7bfa2a164955..3082b3b3d620 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -301,6 +301,38 @@ static int mthca_cmd_post(struct mthca_dev *dev,
return err;
}
+
+static int mthca_status_to_errno(u8 status)
+{
+ static const int trans_table[] = {
+ [MTHCA_CMD_STAT_INTERNAL_ERR] = -EIO,
+ [MTHCA_CMD_STAT_BAD_OP] = -EPERM,
+ [MTHCA_CMD_STAT_BAD_PARAM] = -EINVAL,
+ [MTHCA_CMD_STAT_BAD_SYS_STATE] = -ENXIO,
+ [MTHCA_CMD_STAT_BAD_RESOURCE] = -EBADF,
+ [MTHCA_CMD_STAT_RESOURCE_BUSY] = -EBUSY,
+ [MTHCA_CMD_STAT_DDR_MEM_ERR] = -ENOMEM,
+ [MTHCA_CMD_STAT_EXCEED_LIM] = -ENOMEM,
+ [MTHCA_CMD_STAT_BAD_RES_STATE] = -EBADF,
+ [MTHCA_CMD_STAT_BAD_INDEX] = -EBADF,
+ [MTHCA_CMD_STAT_BAD_NVMEM] = -EFAULT,
+ [MTHCA_CMD_STAT_BAD_QPEE_STATE] = -EINVAL,
+ [MTHCA_CMD_STAT_BAD_SEG_PARAM] = -EFAULT,
+ [MTHCA_CMD_STAT_REG_BOUND] = -EBUSY,
+ [MTHCA_CMD_STAT_LAM_NOT_PRE] = -EAGAIN,
+ [MTHCA_CMD_STAT_BAD_PKT] = -EBADMSG,
+ [MTHCA_CMD_STAT_BAD_SIZE] = -ENOMEM,
+ };
+
+ if (status >= ARRAY_SIZE(trans_table) ||
+ (status != MTHCA_CMD_STAT_OK
+ && trans_table[status] == 0))
+ return -EINVAL;
+
+ return trans_table[status];
+}
+
+
static int mthca_cmd_poll(struct mthca_dev *dev,
u64 in_param,
u64 *out_param,
@@ -308,11 +340,11 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
int err = 0;
unsigned long end;
+ u8 status;
down(&dev->cmd.poll_sem);
@@ -341,7 +373,12 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
(u64) be32_to_cpu((__force __be32)
__raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
- *status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+ status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+ if (status) {
+ mthca_dbg(dev, "Command %02x completed with status %02x\n",
+ op, status);
+ err = mthca_status_to_errno(status);
+ }
out:
up(&dev->cmd.poll_sem);
@@ -374,8 +411,7 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
int err = 0;
struct mthca_cmd_context *context;
@@ -407,10 +443,11 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
if (err)
goto out;
- *status = context->status;
- if (*status)
+ if (context->status) {
mthca_dbg(dev, "Command %02x completed with status %02x\n",
- op, *status);
+ op, context->status);
+ err = mthca_status_to_errno(context->status);
+ }
if (out_is_imm)
*out_param = context->out_param;
@@ -432,17 +469,16 @@ static int mthca_cmd_box(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
return mthca_cmd_wait(dev, in_param, &out_param, 0,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
else
return mthca_cmd_poll(dev, in_param, &out_param, 0,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
}
/* Invoke a command with no output parameter */
@@ -451,11 +487,10 @@ static int mthca_cmd(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
return mthca_cmd_box(dev, in_param, 0, in_modifier,
- op_modifier, op, timeout, status);
+ op_modifier, op, timeout);
}
/*
@@ -469,17 +504,16 @@ static int mthca_cmd_imm(struct mthca_dev *dev,
u32 in_modifier,
u8 op_modifier,
u16 op,
- unsigned long timeout,
- u8 *status)
+ unsigned long timeout)
{
if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
return mthca_cmd_wait(dev, in_param, out_param, 1,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
else
return mthca_cmd_poll(dev, in_param, out_param, 1,
in_modifier, op_modifier, op,
- timeout, status);
+ timeout);
}
int mthca_cmd_init(struct mthca_dev *dev)
@@ -596,14 +630,14 @@ void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox)
kfree(mailbox);
}
-int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
+int mthca_SYS_EN(struct mthca_dev *dev)
{
u64 out;
int ret;
- ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D, status);
+ ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D);
- if (*status == MTHCA_CMD_STAT_DDR_MEM_ERR)
+ if (ret == -ENOMEM)
mthca_warn(dev, "SYS_EN DDR error: syn=%x, sock=%d, "
"sladdr=%d, SPD source=%s\n",
(int) (out >> 6) & 0xf, (int) (out >> 4) & 3,
@@ -612,13 +646,13 @@ int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
return ret;
}
-int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status)
+int mthca_SYS_DIS(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C);
}
static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
- u64 virt, u8 *status)
+ u64 virt)
{
struct mthca_mailbox *mailbox;
struct mthca_icm_iter iter;
@@ -666,8 +700,8 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
if (++nent == MTHCA_MAILBOX_SIZE / 16) {
err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
- CMD_TIME_CLASS_B, status);
- if (err || *status)
+ CMD_TIME_CLASS_B);
+ if (err)
goto out;
nent = 0;
}
@@ -676,7 +710,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
if (nent)
err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
switch (op) {
case CMD_MAP_FA:
@@ -696,19 +730,19 @@ out:
return err;
}
-int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
+int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm)
{
- return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1, status);
+ return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1);
}
-int mthca_UNMAP_FA(struct mthca_dev *dev, u8 *status)
+int mthca_UNMAP_FA(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B);
}
-int mthca_RUN_FW(struct mthca_dev *dev, u8 *status)
+int mthca_RUN_FW(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A);
}
static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
@@ -737,7 +771,7 @@ static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n");
}
-int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
+int mthca_QUERY_FW(struct mthca_dev *dev)
{
struct mthca_mailbox *mailbox;
u32 *outbox;
@@ -771,7 +805,7 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_FW,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -843,7 +877,7 @@ out:
return err;
}
-int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
+int mthca_ENABLE_LAM(struct mthca_dev *dev)
{
struct mthca_mailbox *mailbox;
u8 info;
@@ -864,14 +898,11 @@ int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_ENABLE_LAM,
- CMD_TIME_CLASS_C, status);
+ CMD_TIME_CLASS_C);
if (err)
goto out;
- if (*status == MTHCA_CMD_STAT_LAM_NOT_PRE)
- goto out;
-
MTHCA_GET(dev->ddr_start, outbox, ENABLE_LAM_START_OFFSET);
MTHCA_GET(dev->ddr_end, outbox, ENABLE_LAM_END_OFFSET);
MTHCA_GET(info, outbox, ENABLE_LAM_INFO_OFFSET);
@@ -896,12 +927,12 @@ out:
return err;
}
-int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status)
+int mthca_DISABLE_LAM(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C);
}
-int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
+int mthca_QUERY_DDR(struct mthca_dev *dev)
{
struct mthca_mailbox *mailbox;
u8 info;
@@ -922,7 +953,7 @@ int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DDR,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -952,7 +983,7 @@ out:
}
int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
- struct mthca_dev_lim *dev_lim, u8 *status)
+ struct mthca_dev_lim *dev_lim)
{
struct mthca_mailbox *mailbox;
u32 *outbox;
@@ -1028,7 +1059,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DEV_LIM,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -1232,7 +1263,7 @@ static void get_board_id(void *vsd, char *board_id)
}
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
- struct mthca_adapter *adapter, u8 *status)
+ struct mthca_adapter *adapter)
{
struct mthca_mailbox *mailbox;
u32 *outbox;
@@ -1251,7 +1282,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
outbox = mailbox->buf;
err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_ADAPTER,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
if (err)
goto out;
@@ -1275,8 +1306,7 @@ out:
}
int mthca_INIT_HCA(struct mthca_dev *dev,
- struct mthca_init_hca_param *param,
- u8 *status)
+ struct mthca_init_hca_param *param)
{
struct mthca_mailbox *mailbox;
__be32 *inbox;
@@ -1393,7 +1423,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET);
}
- err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, CMD_TIME_CLASS_D, status);
+ err = mthca_cmd(dev, mailbox->dma, 0, 0,
+ CMD_INIT_HCA, CMD_TIME_CLASS_D);
mthca_free_mailbox(dev, mailbox);
return err;
@@ -1401,7 +1432,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
int mthca_INIT_IB(struct mthca_dev *dev,
struct mthca_init_ib_param *param,
- int port, u8 *status)
+ int port)
{
struct mthca_mailbox *mailbox;
u32 *inbox;
@@ -1445,24 +1476,24 @@ int mthca_INIT_IB(struct mthca_dev *dev,
MTHCA_PUT(inbox, param->si_guid, INIT_IB_SI_GUID_OFFSET);
err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_INIT_IB,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
mthca_free_mailbox(dev, mailbox);
return err;
}
-int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status)
+int mthca_CLOSE_IB(struct mthca_dev *dev, int port)
{
- return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A, status);
+ return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A);
}
-int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status)
+int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic)
{
- return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C, status);
+ return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C);
}
int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
- int port, u8 *status)
+ int port)
{
struct mthca_mailbox *mailbox;
u32 *inbox;
@@ -1491,18 +1522,18 @@ int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
MTHCA_PUT(inbox, param->si_guid, SET_IB_SI_GUID_OFFSET);
err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_SET_IB,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
mthca_free_mailbox(dev, mailbox);
return err;
}
-int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *status)
+int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt)
{
- return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt, status);
+ return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt);
}
-int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
+int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt)
{
struct mthca_mailbox *mailbox;
__be64 *inbox;
@@ -1517,7 +1548,7 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
inbox[1] = cpu_to_be64(dma_addr);
err = mthca_cmd(dev, mailbox->dma, 1, 0, CMD_MAP_ICM,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
mthca_free_mailbox(dev, mailbox);
@@ -1528,31 +1559,31 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
return err;
}
-int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status)
+int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count)
{
mthca_dbg(dev, "Unmapping %d pages at %llx from ICM.\n",
page_count, (unsigned long long) virt);
- return mthca_cmd(dev, virt, page_count, 0, CMD_UNMAP_ICM, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, virt, page_count, 0,
+ CMD_UNMAP_ICM, CMD_TIME_CLASS_B);
}
-int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
+int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm)
{
- return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1, status);
+ return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1);
}
-int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status)
+int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B);
}
-int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
- u8 *status)
+int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages)
{
- int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0, 0, CMD_SET_ICM_SIZE,
- CMD_TIME_CLASS_A, status);
+ int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0,
+ 0, CMD_SET_ICM_SIZE, CMD_TIME_CLASS_A);
- if (ret || status)
+ if (ret)
return ret;
/*
@@ -1566,74 +1597,73 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
}
int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status)
+ int mpt_index)
{
return mthca_cmd(dev, mailbox->dma, mpt_index, 0, CMD_SW2HW_MPT,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status)
+ int mpt_index)
{
return mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index,
!mailbox, CMD_HW2SW_MPT,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int num_mtt, u8 *status)
+ int num_mtt)
{
return mthca_cmd(dev, mailbox->dma, num_mtt, 0, CMD_WRITE_MTT,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
-int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status)
+int mthca_SYNC_TPT(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B);
}
int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
- int eq_num, u8 *status)
+ int eq_num)
{
mthca_dbg(dev, "%s mask %016llx for eqn %d\n",
unmap ? "Clearing" : "Setting",
(unsigned long long) event_mask, eq_num);
return mthca_cmd(dev, event_mask, (unmap << 31) | eq_num,
- 0, CMD_MAP_EQ, CMD_TIME_CLASS_B, status);
+ 0, CMD_MAP_EQ, CMD_TIME_CLASS_B);
}
int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status)
+ int eq_num)
{
return mthca_cmd(dev, mailbox->dma, eq_num, 0, CMD_SW2HW_EQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status)
+ int eq_num)
{
return mthca_cmd_box(dev, 0, mailbox->dma, eq_num, 0,
CMD_HW2SW_EQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status)
+ int cq_num)
{
return mthca_cmd(dev, mailbox->dma, cq_num, 0, CMD_SW2HW_CQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status)
+ int cq_num)
{
return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0,
CMD_HW2SW_CQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
-int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
- u8 *status)
+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size)
{
struct mthca_mailbox *mailbox;
__be32 *inbox;
@@ -1657,44 +1687,43 @@ int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
MTHCA_PUT(inbox, lkey, RESIZE_CQ_LKEY_OFFSET);
err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
mthca_free_mailbox(dev, mailbox);
return err;
}
int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status)
+ int srq_num)
{
return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status)
+ int srq_num)
{
return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
CMD_HW2SW_SRQ,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd_box(dev, 0, mailbox->dma, num, 0,
- CMD_QUERY_SRQ, CMD_TIME_CLASS_A, status);
+ CMD_QUERY_SRQ, CMD_TIME_CLASS_A);
}
-int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit)
{
return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
enum ib_qp_state next, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u32 optmask,
- u8 *status)
+ struct mthca_mailbox *mailbox, u32 optmask)
{
static const u16 op[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = {
@@ -1755,7 +1784,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
(!!is_ee << 24) | num, op_mod,
- op[cur][next], CMD_TIME_CLASS_C, status);
+ op[cur][next], CMD_TIME_CLASS_C);
if (0 && mailbox) {
int i;
@@ -1789,21 +1818,20 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
}
err = mthca_cmd(dev, mailbox->dma, optmask | (!!is_ee << 24) | num,
- op_mod, op[cur][next], CMD_TIME_CLASS_C, status);
+ op_mod, op[cur][next], CMD_TIME_CLASS_C);
}
return err;
}
int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd_box(dev, 0, mailbox->dma, (!!is_ee << 24) | num, 0,
- CMD_QUERY_QPEE, CMD_TIME_CLASS_A, status);
+ CMD_QUERY_QPEE, CMD_TIME_CLASS_A);
}
-int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
- u8 *status)
+int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn)
{
u8 op_mod;
@@ -1825,12 +1853,12 @@ int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
}
return mthca_cmd(dev, 0, qpn, op_mod, CMD_CONF_SPECIAL_QP,
- CMD_TIME_CLASS_B, status);
+ CMD_TIME_CLASS_B);
}
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
- void *in_mad, void *response_mad, u8 *status)
+ void *in_mad, void *response_mad)
{
struct mthca_mailbox *inmailbox, *outmailbox;
void *inbox;
@@ -1897,9 +1925,9 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
err = mthca_cmd_box(dev, inmailbox->dma, outmailbox->dma,
in_modifier, op_modifier,
- CMD_MAD_IFC, CMD_TIME_CLASS_C, status);
+ CMD_MAD_IFC, CMD_TIME_CLASS_C);
- if (!err && !*status)
+ if (!err)
memcpy(response_mad, outmailbox->buf, 256);
mthca_free_mailbox(dev, inmailbox);
@@ -1908,33 +1936,33 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
}
int mthca_READ_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd_box(dev, 0, mailbox->dma, index, 0,
- CMD_READ_MGM, CMD_TIME_CLASS_A, status);
+ CMD_READ_MGM, CMD_TIME_CLASS_A);
}
int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status)
+ struct mthca_mailbox *mailbox)
{
return mthca_cmd(dev, mailbox->dma, index, 0, CMD_WRITE_MGM,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
}
int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- u16 *hash, u8 *status)
+ u16 *hash)
{
u64 imm;
int err;
err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH,
- CMD_TIME_CLASS_A, status);
+ CMD_TIME_CLASS_A);
*hash = imm;
return err;
}
-int mthca_NOP(struct mthca_dev *dev, u8 *status)
+int mthca_NOP(struct mthca_dev *dev)
{
- return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100), status);
+ return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100));
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index 6efd3265f248..f952244c54de 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -252,79 +252,74 @@ struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
gfp_t gfp_mask);
void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
-int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
-int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status);
-int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
-int mthca_UNMAP_FA(struct mthca_dev *dev, u8 *status);
-int mthca_RUN_FW(struct mthca_dev *dev, u8 *status);
-int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status);
-int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status);
-int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status);
-int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status);
+int mthca_SYS_EN(struct mthca_dev *dev);
+int mthca_SYS_DIS(struct mthca_dev *dev);
+int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm);
+int mthca_UNMAP_FA(struct mthca_dev *dev);
+int mthca_RUN_FW(struct mthca_dev *dev);
+int mthca_QUERY_FW(struct mthca_dev *dev);
+int mthca_ENABLE_LAM(struct mthca_dev *dev);
+int mthca_DISABLE_LAM(struct mthca_dev *dev);
+int mthca_QUERY_DDR(struct mthca_dev *dev);
int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
- struct mthca_dev_lim *dev_lim, u8 *status);
+ struct mthca_dev_lim *dev_lim);
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
- struct mthca_adapter *adapter, u8 *status);
+ struct mthca_adapter *adapter);
int mthca_INIT_HCA(struct mthca_dev *dev,
- struct mthca_init_hca_param *param,
- u8 *status);
+ struct mthca_init_hca_param *param);
int mthca_INIT_IB(struct mthca_dev *dev,
struct mthca_init_ib_param *param,
- int port, u8 *status);
-int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status);
-int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status);
+ int port);
+int mthca_CLOSE_IB(struct mthca_dev *dev, int port);
+int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic);
int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
- int port, u8 *status);
-int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *status);
-int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status);
-int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status);
-int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
-int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status);
-int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
- u8 *status);
+ int port);
+int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt);
+int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt);
+int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count);
+int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm);
+int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev);
+int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages);
int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status);
+ int mpt_index);
int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int mpt_index, u8 *status);
+ int mpt_index);
int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int num_mtt, u8 *status);
-int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status);
+ int num_mtt);
+int mthca_SYNC_TPT(struct mthca_dev *dev);
int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
- int eq_num, u8 *status);
+ int eq_num);
int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status);
+ int eq_num);
int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int eq_num, u8 *status);
+ int eq_num);
int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status);
+ int cq_num);
int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int cq_num, u8 *status);
-int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
- u8 *status);
+ int cq_num);
+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size);
int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status);
+ int srq_num);
int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- int srq_num, u8 *status);
+ int srq_num);
int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
- struct mthca_mailbox *mailbox, u8 *status);
-int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status);
+ struct mthca_mailbox *mailbox);
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit);
int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
enum ib_qp_state next, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u32 optmask,
- u8 *status);
+ struct mthca_mailbox *mailbox, u32 optmask);
int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u8 *status);
-int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
- u8 *status);
+ struct mthca_mailbox *mailbox);
+int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn);
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
- void *in_mad, void *response_mad, u8 *status);
+ void *in_mad, void *response_mad);
int mthca_READ_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status);
+ struct mthca_mailbox *mailbox);
int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status);
+ struct mthca_mailbox *mailbox);
int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- u16 *hash, u8 *status);
-int mthca_NOP(struct mthca_dev *dev, u8 *status);
+ u16 *hash);
+int mthca_NOP(struct mthca_dev *dev);
#endif /* MTHCA_CMD_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 18ee3fa4b88c..53157b86a1ba 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -779,7 +779,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
struct mthca_mailbox *mailbox;
struct mthca_cq_context *cq_context;
int err = -ENOMEM;
- u8 status;
cq->ibcq.cqe = nent - 1;
cq->is_kernel = !ctx;
@@ -847,19 +846,12 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq_context->state_db = cpu_to_be32(cq->arm_db_index);
}
- err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn, &status);
+ err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn);
if (err) {
mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err);
goto err_out_free_mr;
}
- if (status) {
- mthca_warn(dev, "SW2HW_CQ returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_free_mr;
- }
-
spin_lock_irq(&dev->cq_table.lock);
if (mthca_array_set(&dev->cq_table.cq,
cq->cqn & (dev->limits.num_cqs - 1),
@@ -915,7 +907,6 @@ void mthca_free_cq(struct mthca_dev *dev,
{
struct mthca_mailbox *mailbox;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox)) {
@@ -923,11 +914,9 @@ void mthca_free_cq(struct mthca_dev *dev,
return;
}
- err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn, &status);
+ err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn);
if (err)
mthca_warn(dev, "HW2SW_CQ failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
if (0) {
__be32 *ctx = mailbox->buf;
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 76785c653c13..7c9d35f39d75 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -474,7 +474,6 @@ static int mthca_create_eq(struct mthca_dev *dev,
struct mthca_eq_context *eq_context;
int err = -ENOMEM;
int i;
- u8 status;
eq->dev = dev;
eq->nent = roundup_pow_of_two(max(nent, 2));
@@ -543,15 +542,9 @@ static int mthca_create_eq(struct mthca_dev *dev,
eq_context->intr = intr;
eq_context->lkey = cpu_to_be32(eq->mr.ibmr.lkey);
- err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn, &status);
+ err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn);
if (err) {
- mthca_warn(dev, "SW2HW_EQ failed (%d)\n", err);
- goto err_out_free_mr;
- }
- if (status) {
- mthca_warn(dev, "SW2HW_EQ returned status 0x%02x\n",
- status);
- err = -EINVAL;
+ mthca_warn(dev, "SW2HW_EQ returned %d\n", err);
goto err_out_free_mr;
}
@@ -597,7 +590,6 @@ static void mthca_free_eq(struct mthca_dev *dev,
{
struct mthca_mailbox *mailbox;
int err;
- u8 status;
int npages = (eq->nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) /
PAGE_SIZE;
int i;
@@ -606,11 +598,9 @@ static void mthca_free_eq(struct mthca_dev *dev,
if (IS_ERR(mailbox))
return;
- err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn, &status);
+ err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn);
if (err)
- mthca_warn(dev, "HW2SW_EQ failed (%d)\n", err);
- if (status)
- mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n", status);
+ mthca_warn(dev, "HW2SW_EQ returned %d\n", err);
dev->eq_table.arm_mask &= ~eq->eqn_mask;
@@ -738,7 +728,6 @@ static void mthca_unmap_eq_regs(struct mthca_dev *dev)
int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
{
int ret;
- u8 status;
/*
* We assume that mapping one page is enough for the whole EQ
@@ -757,9 +746,7 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
return -ENOMEM;
}
- ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt, &status);
- if (!ret && status)
- ret = -EINVAL;
+ ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt);
if (ret) {
pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
@@ -771,9 +758,7 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
void mthca_unmap_eq_icm(struct mthca_dev *dev)
{
- u8 status;
-
- mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1, &status);
+ mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1);
pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
__free_page(dev->eq_table.icm_page);
@@ -782,7 +767,6 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev)
int mthca_init_eq_table(struct mthca_dev *dev)
{
int err;
- u8 status;
u8 intr;
int i;
@@ -864,22 +848,16 @@ int mthca_init_eq_table(struct mthca_dev *dev)
}
err = mthca_MAP_EQ(dev, async_mask(dev),
- 0, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, &status);
+ 0, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
if (err)
mthca_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, err);
- if (status)
- mthca_warn(dev, "MAP_EQ for async EQ %d returned status 0x%02x\n",
- dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, status);
err = mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
- 0, dev->eq_table.eq[MTHCA_EQ_CMD].eqn, &status);
+ 0, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
if (err)
mthca_warn(dev, "MAP_EQ for cmd EQ %d failed (%d)\n",
dev->eq_table.eq[MTHCA_EQ_CMD].eqn, err);
- if (status)
- mthca_warn(dev, "MAP_EQ for cmd EQ %d returned status 0x%02x\n",
- dev->eq_table.eq[MTHCA_EQ_CMD].eqn, status);
for (i = 0; i < MTHCA_NUM_EQ; ++i)
if (mthca_is_memfree(dev))
@@ -909,15 +887,14 @@ err_out_free:
void mthca_cleanup_eq_table(struct mthca_dev *dev)
{
- u8 status;
int i;
mthca_free_irqs(dev);
mthca_MAP_EQ(dev, async_mask(dev),
- 1, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, &status);
+ 1, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
- 1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn, &status);
+ 1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
for (i = 0; i < MTHCA_NUM_EQ; ++i)
mthca_free_eq(dev, &dev->eq_table.eq[i]);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 03a59534f59e..b6f7f457fc55 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -201,7 +201,6 @@ int mthca_process_mad(struct ib_device *ibdev,
struct ib_mad *out_mad)
{
int err;
- u8 status;
u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
u16 prev_lid = 0;
struct ib_port_attr pattr;
@@ -252,17 +251,11 @@ int mthca_process_mad(struct ib_device *ibdev,
err = mthca_MAD_IFC(to_mdev(ibdev),
mad_flags & IB_MAD_IGNORE_MKEY,
mad_flags & IB_MAD_IGNORE_BKEY,
- port_num, in_wc, in_grh, in_mad, out_mad,
- &status);
- if (err) {
- mthca_err(to_mdev(ibdev), "MAD_IFC failed\n");
- return IB_MAD_RESULT_FAILURE;
- }
- if (status == MTHCA_CMD_STAT_BAD_PKT)
+ port_num, in_wc, in_grh, in_mad, out_mad);
+ if (err == -EBADMSG)
return IB_MAD_RESULT_SUCCESS;
- if (status) {
- mthca_err(to_mdev(ibdev), "MAD_IFC returned status %02x\n",
- status);
+ else if (err) {
+ mthca_err(to_mdev(ibdev), "MAD_IFC returned %d\n", err);
return IB_MAD_RESULT_FAILURE;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index f24b79b805f2..aa12a533ae9e 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -149,7 +149,7 @@ static int mthca_tune_pci(struct mthca_dev *mdev)
} else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE))
mthca_info(mdev, "No PCI-X capability, not setting RBC.\n");
- if (pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP)) {
+ if (pci_is_pcie(mdev->pdev)) {
if (pcie_set_readrq(mdev->pdev, 4096)) {
mthca_err(mdev, "Couldn't write PCI Express read request, "
"aborting.\n");
@@ -165,19 +165,14 @@ static int mthca_tune_pci(struct mthca_dev *mdev)
static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
{
int err;
- u8 status;
mdev->limits.mtt_seg_size = (1 << log_mtts_per_seg) * 8;
- err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status);
+ err = mthca_QUERY_DEV_LIM(mdev, dev_lim);
if (err) {
- mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_DEV_LIM command returned %d"
+ ", aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "QUERY_DEV_LIM returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
if (dev_lim->min_page_sz > PAGE_SIZE) {
mthca_err(mdev, "HCA minimum page size of %d bigger than "
"kernel PAGE_SIZE of %ld, aborting.\n",
@@ -293,49 +288,32 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
static int mthca_init_tavor(struct mthca_dev *mdev)
{
s64 size;
- u8 status;
int err;
struct mthca_dev_lim dev_lim;
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
- err = mthca_SYS_EN(mdev, &status);
+ err = mthca_SYS_EN(mdev);
if (err) {
- mthca_err(mdev, "SYS_EN command failed, aborting.\n");
+ mthca_err(mdev, "SYS_EN command returned %d, aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "SYS_EN returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
- err = mthca_QUERY_FW(mdev, &status);
+ err = mthca_QUERY_FW(mdev);
if (err) {
- mthca_err(mdev, "QUERY_FW command failed, aborting.\n");
- goto err_disable;
- }
- if (status) {
- mthca_err(mdev, "QUERY_FW returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "QUERY_FW command returned %d,"
+ " aborting.\n", err);
goto err_disable;
}
- err = mthca_QUERY_DDR(mdev, &status);
+ err = mthca_QUERY_DDR(mdev);
if (err) {
- mthca_err(mdev, "QUERY_DDR command failed, aborting.\n");
- goto err_disable;
- }
- if (status) {
- mthca_err(mdev, "QUERY_DDR returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "QUERY_DDR command returned %d, aborting.\n", err);
goto err_disable;
}
err = mthca_dev_lim(mdev, &dev_lim);
if (err) {
- mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_DEV_LIM command returned %d, aborting.\n", err);
goto err_disable;
}
@@ -351,29 +329,22 @@ static int mthca_init_tavor(struct mthca_dev *mdev)
goto err_disable;
}
- err = mthca_INIT_HCA(mdev, &init_hca, &status);
+ err = mthca_INIT_HCA(mdev, &init_hca);
if (err) {
- mthca_err(mdev, "INIT_HCA command failed, aborting.\n");
- goto err_disable;
- }
- if (status) {
- mthca_err(mdev, "INIT_HCA returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
goto err_disable;
}
return 0;
err_disable:
- mthca_SYS_DIS(mdev, &status);
+ mthca_SYS_DIS(mdev);
return err;
}
static int mthca_load_fw(struct mthca_dev *mdev)
{
- u8 status;
int err;
/* FIXME: use HCA-attached memory for FW if present */
@@ -386,31 +357,21 @@ static int mthca_load_fw(struct mthca_dev *mdev)
return -ENOMEM;
}
- err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm, &status);
+ err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm);
if (err) {
- mthca_err(mdev, "MAP_FA command failed, aborting.\n");
- goto err_free;
- }
- if (status) {
- mthca_err(mdev, "MAP_FA returned status 0x%02x, aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "MAP_FA command returned %d, aborting.\n", err);
goto err_free;
}
- err = mthca_RUN_FW(mdev, &status);
+ err = mthca_RUN_FW(mdev);
if (err) {
- mthca_err(mdev, "RUN_FW command failed, aborting.\n");
- goto err_unmap_fa;
- }
- if (status) {
- mthca_err(mdev, "RUN_FW returned status 0x%02x, aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "RUN_FW command returned %d, aborting.\n", err);
goto err_unmap_fa;
}
return 0;
err_unmap_fa:
- mthca_UNMAP_FA(mdev, &status);
+ mthca_UNMAP_FA(mdev);
err_free:
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
@@ -423,19 +384,13 @@ static int mthca_init_icm(struct mthca_dev *mdev,
u64 icm_size)
{
u64 aux_pages;
- u8 status;
int err;
- err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages, &status);
+ err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages);
if (err) {
- mthca_err(mdev, "SET_ICM_SIZE command failed, aborting.\n");
+ mthca_err(mdev, "SET_ICM_SIZE command returned %d, aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "SET_ICM_SIZE returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
mthca_dbg(mdev, "%lld KB of HCA context requires %lld KB aux memory.\n",
(unsigned long long) icm_size >> 10,
@@ -448,14 +403,9 @@ static int mthca_init_icm(struct mthca_dev *mdev,
return -ENOMEM;
}
- err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm, &status);
+ err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm);
if (err) {
- mthca_err(mdev, "MAP_ICM_AUX command failed, aborting.\n");
- goto err_free_aux;
- }
- if (status) {
- mthca_err(mdev, "MAP_ICM_AUX returned status 0x%02x, aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "MAP_ICM_AUX returned %d, aborting.\n", err);
goto err_free_aux;
}
@@ -596,7 +546,7 @@ err_unmap_eq:
mthca_unmap_eq_icm(mdev);
err_unmap_aux:
- mthca_UNMAP_ICM_AUX(mdev, &status);
+ mthca_UNMAP_ICM_AUX(mdev);
err_free_aux:
mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
@@ -606,7 +556,6 @@ err_free_aux:
static void mthca_free_icms(struct mthca_dev *mdev)
{
- u8 status;
mthca_free_icm_table(mdev, mdev->mcg_table.table);
if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
@@ -619,7 +568,7 @@ static void mthca_free_icms(struct mthca_dev *mdev)
mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
mthca_unmap_eq_icm(mdev);
- mthca_UNMAP_ICM_AUX(mdev, &status);
+ mthca_UNMAP_ICM_AUX(mdev);
mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
}
@@ -629,43 +578,32 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
s64 icm_size;
- u8 status;
int err;
- err = mthca_QUERY_FW(mdev, &status);
+ err = mthca_QUERY_FW(mdev);
if (err) {
- mthca_err(mdev, "QUERY_FW command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_FW command failed %d, aborting.\n", err);
return err;
}
- if (status) {
- mthca_err(mdev, "QUERY_FW returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
- }
- err = mthca_ENABLE_LAM(mdev, &status);
- if (err) {
- mthca_err(mdev, "ENABLE_LAM command failed, aborting.\n");
- return err;
- }
- if (status == MTHCA_CMD_STAT_LAM_NOT_PRE) {
+ err = mthca_ENABLE_LAM(mdev);
+ if (err == -EAGAIN) {
mthca_dbg(mdev, "No HCA-attached memory (running in MemFree mode)\n");
mdev->mthca_flags |= MTHCA_FLAG_NO_LAM;
- } else if (status) {
- mthca_err(mdev, "ENABLE_LAM returned status 0x%02x, "
- "aborting.\n", status);
- return -EINVAL;
+ } else if (err) {
+ mthca_err(mdev, "ENABLE_LAM returned %d, aborting.\n", err);
+ return err;
}
err = mthca_load_fw(mdev);
if (err) {
- mthca_err(mdev, "Failed to start FW, aborting.\n");
+ mthca_err(mdev, "Loading FW returned %d, aborting.\n", err);
goto err_disable;
}
err = mthca_dev_lim(mdev, &dev_lim);
if (err) {
- mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ mthca_err(mdev, "QUERY_DEV_LIM returned %d, aborting.\n", err);
goto err_stop_fw;
}
@@ -685,15 +623,9 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
if (err)
goto err_stop_fw;
- err = mthca_INIT_HCA(mdev, &init_hca, &status);
+ err = mthca_INIT_HCA(mdev, &init_hca);
if (err) {
- mthca_err(mdev, "INIT_HCA command failed, aborting.\n");
- goto err_free_icm;
- }
- if (status) {
- mthca_err(mdev, "INIT_HCA returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
goto err_free_icm;
}
@@ -703,37 +635,34 @@ err_free_icm:
mthca_free_icms(mdev);
err_stop_fw:
- mthca_UNMAP_FA(mdev, &status);
+ mthca_UNMAP_FA(mdev);
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
err_disable:
if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
- mthca_DISABLE_LAM(mdev, &status);
+ mthca_DISABLE_LAM(mdev);
return err;
}
static void mthca_close_hca(struct mthca_dev *mdev)
{
- u8 status;
-
- mthca_CLOSE_HCA(mdev, 0, &status);
+ mthca_CLOSE_HCA(mdev, 0);
if (mthca_is_memfree(mdev)) {
mthca_free_icms(mdev);
- mthca_UNMAP_FA(mdev, &status);
+ mthca_UNMAP_FA(mdev);
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
- mthca_DISABLE_LAM(mdev, &status);
+ mthca_DISABLE_LAM(mdev);
} else
- mthca_SYS_DIS(mdev, &status);
+ mthca_SYS_DIS(mdev);
}
static int mthca_init_hca(struct mthca_dev *mdev)
{
- u8 status;
int err;
struct mthca_adapter adapter;
@@ -745,15 +674,9 @@ static int mthca_init_hca(struct mthca_dev *mdev)
if (err)
return err;
- err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
+ err = mthca_QUERY_ADAPTER(mdev, &adapter);
if (err) {
- mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
- goto err_close;
- }
- if (status) {
- mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
+ mthca_err(mdev, "QUERY_ADAPTER command returned %d, aborting.\n", err);
goto err_close;
}
@@ -772,7 +695,6 @@ err_close:
static int mthca_setup_hca(struct mthca_dev *dev)
{
int err;
- u8 status;
MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock);
@@ -833,8 +755,8 @@ static int mthca_setup_hca(struct mthca_dev *dev)
goto err_eq_table_free;
}
- err = mthca_NOP(dev, &status);
- if (err || status) {
+ err = mthca_NOP(dev);
+ if (err) {
if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
mthca_warn(dev, "NOP command failed to generate interrupt "
"(IRQ %d).\n",
@@ -1166,7 +1088,6 @@ err_disable_pdev:
static void __mthca_remove_one(struct pci_dev *pdev)
{
struct mthca_dev *mdev = pci_get_drvdata(pdev);
- u8 status;
int p;
if (mdev) {
@@ -1174,7 +1095,7 @@ static void __mthca_remove_one(struct pci_dev *pdev)
mthca_unregister_device(mdev);
for (p = 1; p <= mdev->limits.num_ports; ++p)
- mthca_CLOSE_IB(mdev, p, &status);
+ mthca_CLOSE_IB(mdev, p);
mthca_cleanup_mcg_table(mdev);
mthca_cleanup_av_table(mdev);
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 515790a606e6..6304ae8f4a6c 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -68,7 +68,6 @@ static int find_mgm(struct mthca_dev *dev,
struct mthca_mgm *mgm = mgm_mailbox->buf;
u8 *mgid;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -77,12 +76,9 @@ static int find_mgm(struct mthca_dev *dev,
memcpy(mgid, gid, 16);
- err = mthca_MGID_HASH(dev, mailbox, hash, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "MGID_HASH returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_MGID_HASH(dev, mailbox, hash);
+ if (err) {
+ mthca_err(dev, "MGID_HASH failed (%d)\n", err);
goto out;
}
@@ -93,12 +89,9 @@ static int find_mgm(struct mthca_dev *dev,
*prev = -1;
do {
- err = mthca_READ_MGM(dev, *index, mgm_mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, *index, mgm_mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM failed (%d)\n", err);
goto out;
}
@@ -134,7 +127,6 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int link = 0;
int i;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -160,12 +152,9 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- err = mthca_READ_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM failed (%d)\n", err);
goto out;
}
memset(mgm, 0, sizeof *mgm);
@@ -189,11 +178,9 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
+ err = mthca_WRITE_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM failed %d\n", err);
err = -EINVAL;
goto out;
}
@@ -201,24 +188,17 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (!link)
goto out;
- err = mthca_READ_MGM(dev, prev, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, prev, mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM failed %d\n", err);
goto out;
}
mgm->next_gid_index = cpu_to_be32(index << 6);
- err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
+ err = mthca_WRITE_MGM(dev, prev, mailbox);
if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
- }
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
out:
if (err && link && index != -1) {
@@ -240,7 +220,6 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int prev, index;
int i, loc;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -275,12 +254,9 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
mgm->qp[loc] = mgm->qp[i - 1];
mgm->qp[i - 1] = 0;
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_WRITE_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
@@ -292,24 +268,17 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
if (amgm_index_to_free) {
err = mthca_READ_MGM(dev, amgm_index_to_free,
- mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n",
- status);
- err = -EINVAL;
+ mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM returned %d\n", err);
goto out;
}
} else
memset(mgm->gid, 0, 16);
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_WRITE_MGM(dev, index, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
if (amgm_index_to_free) {
@@ -319,23 +288,17 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
} else {
/* Remove entry from AMGM */
int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
- err = mthca_READ_MGM(dev, prev, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "READ_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_READ_MGM(dev, prev, mailbox);
+ if (err) {
+ mthca_err(dev, "READ_MGM returned %d\n", err);
goto out;
}
mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
- err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
- if (err)
- goto out;
- if (status) {
- mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_WRITE_MGM(dev, prev, mailbox);
+ if (err) {
+ mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
BUG_ON(index < dev->limits.num_mgms);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 8c2a83732b5d..7d2e42dd6926 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -223,7 +223,6 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
{
int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
int ret = 0;
- u8 status;
mutex_lock(&table->mutex);
@@ -240,8 +239,8 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
goto out;
}
- if (mthca_MAP_ICM(dev, table->icm[i], table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
- &status) || status) {
+ if (mthca_MAP_ICM(dev, table->icm[i],
+ table->virt + i * MTHCA_TABLE_CHUNK_SIZE)) {
mthca_free_icm(dev, table->icm[i], table->coherent);
table->icm[i] = NULL;
ret = -ENOMEM;
@@ -258,7 +257,6 @@ out:
void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
{
int i;
- u8 status;
if (!mthca_is_memfree(dev))
return;
@@ -269,8 +267,7 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o
if (--table->icm[i]->refcount == 0) {
mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
- MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
- &status);
+ MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
mthca_free_icm(dev, table->icm[i], table->coherent);
table->icm[i] = NULL;
}
@@ -366,7 +363,6 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
int num_icm;
unsigned chunk_size;
int i;
- u8 status;
obj_per_chunk = MTHCA_TABLE_CHUNK_SIZE / obj_size;
num_icm = DIV_ROUND_UP(nobj, obj_per_chunk);
@@ -396,8 +392,8 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
__GFP_NOWARN, use_coherent);
if (!table->icm[i])
goto err;
- if (mthca_MAP_ICM(dev, table->icm[i], virt + i * MTHCA_TABLE_CHUNK_SIZE,
- &status) || status) {
+ if (mthca_MAP_ICM(dev, table->icm[i],
+ virt + i * MTHCA_TABLE_CHUNK_SIZE)) {
mthca_free_icm(dev, table->icm[i], table->coherent);
table->icm[i] = NULL;
goto err;
@@ -416,8 +412,7 @@ err:
for (i = 0; i < num_icm; ++i)
if (table->icm[i]) {
mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE,
- MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
- &status);
+ MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
mthca_free_icm(dev, table->icm[i], table->coherent);
}
@@ -429,13 +424,12 @@ err:
void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table)
{
int i;
- u8 status;
for (i = 0; i < table->num_icm; ++i)
if (table->icm[i]) {
- mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
- MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
- &status);
+ mthca_UNMAP_ICM(dev,
+ table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
+ MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
mthca_free_icm(dev, table->icm[i], table->coherent);
}
@@ -454,7 +448,6 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
{
struct page *pages[1];
int ret = 0;
- u8 status;
int i;
if (!mthca_is_memfree(dev))
@@ -494,9 +487,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
}
ret = mthca_MAP_ICM_page(dev, sg_dma_address(&db_tab->page[i].mem),
- mthca_uarc_virt(dev, uar, i), &status);
- if (!ret && status)
- ret = -EINVAL;
+ mthca_uarc_virt(dev, uar, i));
if (ret) {
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
put_page(sg_page(&db_tab->page[i].mem));
@@ -557,14 +548,13 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
struct mthca_user_db_table *db_tab)
{
int i;
- u8 status;
if (!mthca_is_memfree(dev))
return;
for (i = 0; i < dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; ++i) {
if (db_tab->page[i].uvirt) {
- mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status);
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1);
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
put_page(sg_page(&db_tab->page[i].mem));
}
@@ -581,7 +571,6 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
int i, j;
struct mthca_db_page *page;
int ret = 0;
- u8 status;
mutex_lock(&dev->db_tab->mutex);
@@ -644,9 +633,7 @@ alloc:
memset(page->db_rec, 0, MTHCA_ICM_PAGE_SIZE);
ret = mthca_MAP_ICM_page(dev, page->mapping,
- mthca_uarc_virt(dev, &dev->driver_uar, i), &status);
- if (!ret && status)
- ret = -EINVAL;
+ mthca_uarc_virt(dev, &dev->driver_uar, i));
if (ret) {
dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
page->db_rec, page->mapping);
@@ -678,7 +665,6 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
{
int i, j;
struct mthca_db_page *page;
- u8 status;
i = db_index / MTHCA_DB_REC_PER_PAGE;
j = db_index % MTHCA_DB_REC_PER_PAGE;
@@ -694,7 +680,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
if (bitmap_empty(page->used, MTHCA_DB_REC_PER_PAGE) &&
i >= dev->db_tab->max_group1 - 1) {
- mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1);
dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
page->db_rec, page->mapping);
@@ -745,7 +731,6 @@ int mthca_init_db_tab(struct mthca_dev *dev)
void mthca_cleanup_db_tab(struct mthca_dev *dev)
{
int i;
- u8 status;
if (!mthca_is_memfree(dev))
return;
@@ -763,7 +748,7 @@ void mthca_cleanup_db_tab(struct mthca_dev *dev)
if (!bitmap_empty(dev->db_tab->page[i].used, MTHCA_DB_REC_PER_PAGE))
mthca_warn(dev, "Kernel UARC page %d not empty\n", i);
- mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1);
dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
dev->db_tab->page[i].db_rec,
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 44045c8846db..ab876f928a1b 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -257,7 +257,6 @@ static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
struct mthca_mailbox *mailbox;
__be64 *mtt_entry;
int err = 0;
- u8 status;
int i;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -281,17 +280,11 @@ static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
if (i & 1)
mtt_entry[i + 2] = 0;
- err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1, &status);
+ err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1);
if (err) {
mthca_warn(dev, "WRITE_MTT failed (%d)\n", err);
goto out;
}
- if (status) {
- mthca_warn(dev, "WRITE_MTT returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto out;
- }
list_len -= i;
start_index += i;
@@ -441,7 +434,6 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
u32 key;
int i;
int err;
- u8 status;
WARN_ON(buffer_size_shift >= 32);
@@ -497,16 +489,10 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
}
err = mthca_SW2HW_MPT(dev, mailbox,
- key & (dev->limits.num_mpts - 1),
- &status);
+ key & (dev->limits.num_mpts - 1));
if (err) {
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
goto err_out_mailbox;
- } else if (status) {
- mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_mailbox;
}
mthca_free_mailbox(dev, mailbox);
@@ -567,17 +553,12 @@ static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
{
int err;
- u8 status;
err = mthca_HW2SW_MPT(dev, NULL,
key_to_hw_index(dev, mr->ibmr.lkey) &
- (dev->limits.num_mpts - 1),
- &status);
+ (dev->limits.num_mpts - 1));
if (err)
mthca_warn(dev, "HW2SW_MPT failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_MPT returned status 0x%02x\n",
- status);
mthca_free_region(dev, mr->ibmr.lkey);
mthca_free_mtt(dev, mr->mtt);
@@ -590,7 +571,6 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
struct mthca_mailbox *mailbox;
u64 mtt_seg;
u32 key, idx;
- u8 status;
int list_len = mr->attr.max_pages;
int err = -ENOMEM;
int i;
@@ -672,18 +652,11 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
}
err = mthca_SW2HW_MPT(dev, mailbox,
- key & (dev->limits.num_mpts - 1),
- &status);
+ key & (dev->limits.num_mpts - 1));
if (err) {
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
goto err_out_mailbox_free;
}
- if (status) {
- mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_mailbox_free;
- }
mthca_free_mailbox(dev, mailbox);
return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 1e0b4b6074ad..365fe0e14192 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -63,8 +63,6 @@ static int mthca_query_device(struct ib_device *ibdev,
int err = -ENOMEM;
struct mthca_dev *mdev = to_mdev(ibdev);
- u8 status;
-
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
@@ -78,14 +76,9 @@ static int mthca_query_device(struct ib_device *ibdev,
in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
err = mthca_MAD_IFC(mdev, 1, 1,
- 1, NULL, NULL, in_mad, out_mad,
- &status);
+ 1, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
props->device_cap_flags = mdev->device_cap_flags;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
@@ -141,7 +134,6 @@ static int mthca_query_port(struct ib_device *ibdev,
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -155,14 +147,9 @@ static int mthca_query_port(struct ib_device *ibdev,
in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
props->lmc = out_mad->data[34] & 0x7;
@@ -214,7 +201,6 @@ static int mthca_modify_port(struct ib_device *ibdev,
struct mthca_set_ib_param set_ib;
struct ib_port_attr attr;
int err;
- u8 status;
if (mutex_lock_interruptible(&to_mdev(ibdev)->cap_mask_mutex))
return -ERESTARTSYS;
@@ -229,14 +215,9 @@ static int mthca_modify_port(struct ib_device *ibdev,
set_ib.cap_mask = (attr.port_cap_flags | props->set_port_cap_mask) &
~props->clr_port_cap_mask;
- err = mthca_SET_IB(to_mdev(ibdev), &set_ib, port, &status);
+ err = mthca_SET_IB(to_mdev(ibdev), &set_ib, port);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
-
out:
mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex);
return err;
@@ -248,7 +229,6 @@ static int mthca_query_pkey(struct ib_device *ibdev,
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -260,14 +240,9 @@ static int mthca_query_pkey(struct ib_device *ibdev,
in_mad->attr_mod = cpu_to_be32(index / 32);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
*pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]);
@@ -283,7 +258,6 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -295,14 +269,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
memcpy(gid->raw, out_mad->data + 8, 8);
@@ -311,14 +280,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
in_mad->attr_mod = cpu_to_be32(index / 8);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
- port, NULL, NULL, in_mad, out_mad,
- &status);
+ port, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
@@ -800,7 +764,6 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
struct mthca_cq *cq = to_mcq(ibcq);
struct mthca_resize_cq ucmd;
u32 lkey;
- u8 status;
int ret;
if (entries < 1 || entries > dev->limits.max_cqes)
@@ -827,9 +790,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
lkey = ucmd.lkey;
}
- ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status);
- if (status)
- ret = -EINVAL;
+ ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries));
if (ret) {
if (cq->resize_buf) {
@@ -1161,7 +1122,6 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
{
struct ib_fmr *fmr;
int err;
- u8 status;
struct mthca_dev *mdev = NULL;
list_for_each_entry(fmr, fmr_list, list) {
@@ -1182,12 +1142,8 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
list_for_each_entry(fmr, fmr_list, list)
mthca_tavor_fmr_unmap(mdev, to_mfmr(fmr));
- err = mthca_SYNC_TPT(mdev, &status);
- if (err)
- return err;
- if (status)
- return -EINVAL;
- return 0;
+ err = mthca_SYNC_TPT(mdev);
+ return err;
}
static ssize_t show_rev(struct device *device, struct device_attribute *attr,
@@ -1253,7 +1209,6 @@ static int mthca_init_node_data(struct mthca_dev *dev)
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
- u8 status;
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -1264,28 +1219,18 @@ static int mthca_init_node_data(struct mthca_dev *dev)
in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
err = mthca_MAD_IFC(dev, 1, 1,
- 1, NULL, NULL, in_mad, out_mad,
- &status);
+ 1, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
memcpy(dev->ib_dev.node_desc, out_mad->data, 64);
in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
err = mthca_MAD_IFC(dev, 1, 1,
- 1, NULL, NULL, in_mad, out_mad,
- &status);
+ 1, NULL, NULL, in_mad, out_mad);
if (err)
goto out;
- if (status) {
- err = -EINVAL;
- goto out;
- }
if (mthca_is_memfree(dev))
dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index a34c9d38e822..9601049e14d0 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -308,7 +308,6 @@ static void store_attrs(struct mthca_sqp *sqp, const struct ib_qp_attr *attr,
static void init_port(struct mthca_dev *dev, int port)
{
int err;
- u8 status;
struct mthca_init_ib_param param;
memset(&param, 0, sizeof param);
@@ -319,11 +318,9 @@ static void init_port(struct mthca_dev *dev, int port)
param.gid_cap = dev->limits.gid_table_len;
param.pkey_cap = dev->limits.pkey_table_len;
- err = mthca_INIT_IB(dev, &param, port, &status);
+ err = mthca_INIT_IB(dev, &param, port);
if (err)
mthca_warn(dev, "INIT_IB failed, return code %d.\n", err);
- if (status)
- mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
}
static __be32 get_hw_access_flags(struct mthca_qp *qp, const struct ib_qp_attr *attr,
@@ -433,7 +430,6 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
struct mthca_qp_param *qp_param;
struct mthca_qp_context *context;
int mthca_state;
- u8 status;
mutex_lock(&qp->mutex);
@@ -448,12 +444,9 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
goto out;
}
- err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox, &status);
- if (err)
- goto out_mailbox;
- if (status) {
- mthca_warn(dev, "QUERY_QP returned status %02x\n", status);
- err = -EINVAL;
+ err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox);
+ if (err) {
+ mthca_warn(dev, "QUERY_QP failed (%d)\n", err);
goto out_mailbox;
}
@@ -555,7 +548,6 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
struct mthca_qp_param *qp_param;
struct mthca_qp_context *qp_context;
u32 sqd_event = 0;
- u8 status;
int err = -EINVAL;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -781,13 +773,10 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
sqd_event = 1 << 31;
err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
- mailbox, sqd_event, &status);
- if (err)
- goto out_mailbox;
- if (status) {
- mthca_warn(dev, "modify QP %d->%d returned status %02x.\n",
- cur_state, new_state, status);
- err = -EINVAL;
+ mailbox, sqd_event);
+ if (err) {
+ mthca_warn(dev, "modify QP %d->%d returned %d.\n",
+ cur_state, new_state, err);
goto out_mailbox;
}
@@ -817,7 +806,7 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
cur_state != IB_QPS_ERR &&
(new_state == IB_QPS_RESET ||
new_state == IB_QPS_ERR))
- mthca_CLOSE_IB(dev, qp->port, &status);
+ mthca_CLOSE_IB(dev, qp->port);
}
/*
@@ -1429,7 +1418,6 @@ static inline int get_qp_refcount(struct mthca_dev *dev, struct mthca_qp *qp)
void mthca_free_qp(struct mthca_dev *dev,
struct mthca_qp *qp)
{
- u8 status;
struct mthca_cq *send_cq;
struct mthca_cq *recv_cq;
@@ -1454,7 +1442,7 @@ void mthca_free_qp(struct mthca_dev *dev,
if (qp->state != IB_QPS_RESET)
mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0,
- NULL, 0, &status);
+ NULL, 0);
/*
* If this is a userspace QP, the buffers, MR, CQs and so on
@@ -2263,7 +2251,6 @@ void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
int mthca_init_qp_table(struct mthca_dev *dev)
{
int err;
- u8 status;
int i;
spin_lock_init(&dev->qp_table.lock);
@@ -2290,15 +2277,10 @@ int mthca_init_qp_table(struct mthca_dev *dev)
for (i = 0; i < 2; ++i) {
err = mthca_CONF_SPECIAL_QP(dev, i ? IB_QPT_GSI : IB_QPT_SMI,
- dev->qp_table.sqp_start + i * 2,
- &status);
- if (err)
- goto err_out;
- if (status) {
+ dev->qp_table.sqp_start + i * 2);
+ if (err) {
mthca_warn(dev, "CONF_SPECIAL_QP returned "
- "status %02x, aborting.\n",
- status);
- err = -EINVAL;
+ "%d, aborting.\n", err);
goto err_out;
}
}
@@ -2306,7 +2288,7 @@ int mthca_init_qp_table(struct mthca_dev *dev)
err_out:
for (i = 0; i < 2; ++i)
- mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
+ mthca_CONF_SPECIAL_QP(dev, i, 0);
mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
mthca_alloc_cleanup(&dev->qp_table.alloc);
@@ -2317,10 +2299,9 @@ int mthca_init_qp_table(struct mthca_dev *dev)
void mthca_cleanup_qp_table(struct mthca_dev *dev)
{
int i;
- u8 status;
for (i = 0; i < 2; ++i)
- mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
+ mthca_CONF_SPECIAL_QP(dev, i, 0);
mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
mthca_alloc_cleanup(&dev->qp_table.alloc);
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 2a13a163d337..4fa3534ec233 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -113,7 +113,7 @@ int mthca_reset(struct mthca_dev *mdev)
}
hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
- hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);
+ hca_pcie_cap = pci_pcie_cap(mdev->pdev);
if (bridge) {
bridge_header = kmalloc(256, GFP_KERNEL);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 4fabe62aab8a..d22f970480c0 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -200,7 +200,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
struct ib_srq_attr *attr, struct mthca_srq *srq)
{
struct mthca_mailbox *mailbox;
- u8 status;
int ds;
int err;
@@ -266,18 +265,12 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
else
mthca_tavor_init_srq_context(dev, pd, srq, mailbox->buf);
- err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn, &status);
+ err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn);
if (err) {
mthca_warn(dev, "SW2HW_SRQ failed (%d)\n", err);
goto err_out_free_buf;
}
- if (status) {
- mthca_warn(dev, "SW2HW_SRQ returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto err_out_free_buf;
- }
spin_lock_irq(&dev->srq_table.lock);
if (mthca_array_set(&dev->srq_table.srq,
@@ -299,11 +292,9 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
return 0;
err_out_free_srq:
- err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn);
if (err)
mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
err_out_free_buf:
if (!pd->ibpd.uobject)
@@ -340,7 +331,6 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
{
struct mthca_mailbox *mailbox;
int err;
- u8 status;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox)) {
@@ -348,11 +338,9 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
return;
}
- err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn);
if (err)
mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
- else if (status)
- mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
spin_lock_irq(&dev->srq_table.lock);
mthca_array_clear(&dev->srq_table.srq,
@@ -378,8 +366,7 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
{
struct mthca_dev *dev = to_mdev(ibsrq->device);
struct mthca_srq *srq = to_msrq(ibsrq);
- int ret;
- u8 status;
+ int ret = 0;
/* We don't support resizing SRQs (yet?) */
if (attr_mask & IB_SRQ_MAX_WR)
@@ -391,16 +378,11 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
return -EINVAL;
mutex_lock(&srq->mutex);
- ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+ ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit);
mutex_unlock(&srq->mutex);
-
- if (ret)
- return ret;
- if (status)
- return -EINVAL;
}
- return 0;
+ return ret;
}
int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
@@ -410,14 +392,13 @@ int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
struct mthca_mailbox *mailbox;
struct mthca_arbel_srq_context *arbel_ctx;
struct mthca_tavor_srq_context *tavor_ctx;
- u8 status;
int err;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
- err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox, &status);
+ err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox);
if (err)
goto out;
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index e74cdf9ef471..c118663e4437 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -34,7 +34,7 @@
#define TCPOPT_TIMESTAMP 8
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
@@ -1151,7 +1151,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
}
if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
- neigh_event_send(rt->dst.neighbour, NULL);
+ neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
ip_rt_put(rt);
return rc;
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 96fa9a4cafdf..be36cbeae630 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -2917,24 +2917,19 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
goto skip_rx_indicate0;
- if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
- (nesvnic->vlan_grp != NULL)) {
+ if (cqe_misc & NES_NIC_CQE_TAG_VALID) {
vlan_tag = (u16)(le32_to_cpu(
cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
>> 16);
nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
nesvnic->netdev->name, vlan_tag);
- if (nes_use_lro)
- lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
- nesvnic->vlan_grp, vlan_tag, NULL);
- else
- nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
- } else {
- if (nes_use_lro)
- lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
- else
- nes_netif_rx(rx_skb);
+
+ __vlan_hwaccel_put_tag(rx_skb, vlan_tag);
}
+ if (nes_use_lro)
+ lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
+ else
+ netif_receive_skb(rx_skb);
skip_rx_indicate0:
;
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 91594116f947..c3241479ec0e 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1211,7 +1211,6 @@ struct nes_vnic {
/* void *mem; */
struct nes_device *nesdev;
struct net_device *netdev;
- struct vlan_group *vlan_grp;
atomic_t rx_skbs_needed;
atomic_t rx_skb_timer_running;
int budget;
@@ -1357,7 +1356,4 @@ struct nes_terminate_hdr {
#define NES_LINK_RECHECK_DELAY msecs_to_jiffies(50)
#define NES_LINK_RECHECK_MAX 60
-#define nes_vlan_rx vlan_hwaccel_receive_skb
-#define nes_netif_rx netif_receive_skb
-
#endif /* __NES_HW_H */
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index d3a1c41cfd27..9d7ffebff213 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1584,23 +1584,19 @@ static const struct ethtool_ops nes_ethtool_ops = {
.set_pauseparam = nes_netdev_set_pauseparam,
};
-
-static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+static void nes_vlan_mode(struct net_device *netdev, struct nes_device *nesdev, u32 features)
{
- struct nes_vnic *nesvnic = netdev_priv(netdev);
- struct nes_device *nesdev = nesvnic->nesdev;
struct nes_adapter *nesadapter = nesdev->nesadapter;
u32 u32temp;
unsigned long flags;
spin_lock_irqsave(&nesadapter->phy_lock, flags);
- nesvnic->vlan_grp = grp;
nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name);
/* Enable/Disable VLAN Stripping */
u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG);
- if (grp)
+ if (features & NETIF_F_HW_VLAN_RX)
u32temp &= 0xfdffffff;
else
u32temp |= 0x02000000;
@@ -1609,17 +1605,44 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g
spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
}
+static u32 nes_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int nes_set_features(struct net_device *netdev, u32 features)
+{
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_device *nesdev = nesvnic->nesdev;
+ u32 changed = netdev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ nes_vlan_mode(netdev, nesdev, features);
+
+ return 0;
+}
+
static const struct net_device_ops nes_netdev_ops = {
- .ndo_open = nes_netdev_open,
+ .ndo_open = nes_netdev_open,
.ndo_stop = nes_netdev_stop,
- .ndo_start_xmit = nes_netdev_start_xmit,
+ .ndo_start_xmit = nes_netdev_start_xmit,
.ndo_get_stats = nes_netdev_get_stats,
- .ndo_tx_timeout = nes_netdev_tx_timeout,
+ .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_change_mtu = nes_netdev_change_mtu,
.ndo_validate_addr = eth_validate_addr,
- .ndo_vlan_rx_register = nes_netdev_vlan_rx_register,
+ .ndo_fix_features = nes_fix_features,
+ .ndo_set_features = nes_set_features,
};
/**
@@ -1656,7 +1679,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
netdev->ethtool_ops = &nes_ethtool_ops;
netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);
nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");
- netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ netdev->features |= NETIF_F_HW_VLAN_TX;
/* Fill in the port structure */
nesvnic->netdev = netdev;
@@ -1683,7 +1706,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
netdev->dev_addr[5] = (u8)u64temp;
memcpy(netdev->perm_addr, netdev->dev_addr, 6);
- netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
+ netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_HW_VLAN_RX;
if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))
netdev->hw_features |= NETIF_F_TSO;
netdev->features |= netdev->hw_features;
@@ -1815,6 +1839,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
nes_init_phy(nesdev);
}
+ nes_vlan_mode(netdev, nesdev, netdev->features);
+
return netdev;
}
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 95ca93ceedac..9f2f7d4b1197 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -605,16 +605,6 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr
/**
- * nes_modify_port
- */
-static int nes_modify_port(struct ib_device *ibdev, u8 port,
- int port_modify_mask, struct ib_port_modify *props)
-{
- return 0;
-}
-
-
-/**
* nes_query_pkey
*/
static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
@@ -3882,7 +3872,6 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
nesibdev->ibdev.dev.parent = &nesdev->pcidev->dev;
nesibdev->ibdev.query_device = nes_query_device;
nesibdev->ibdev.query_port = nes_query_port;
- nesibdev->ibdev.modify_port = nes_modify_port;
nesibdev->ibdev.query_pkey = nes_query_pkey;
nesibdev->ibdev.query_gid = nes_query_gid;
nesibdev->ibdev.alloc_ucontext = nes_alloc_ucontext;
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 769a1d9da4b7..c9624ea87209 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -1012,6 +1012,8 @@ struct qib_devdata {
u8 psxmitwait_supported;
/* cycle length of PS* counters in HW (in picoseconds) */
u16 psxmitwait_check_rate;
+ /* high volume overflow errors defered to tasklet */
+ struct tasklet_struct error_tasklet;
};
/* hol_state values */
@@ -1433,6 +1435,7 @@ extern struct mutex qib_mutex;
struct qib_hwerror_msgs {
u64 mask;
const char *msg;
+ size_t sz;
};
#define QLOGIC_IB_HWE_MSG(a, b) { .mask = a, .msg = b }
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 406fca50d036..26253039d2c7 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -1527,6 +1527,7 @@ done_chk_sdma:
struct qib_filedata *fd = fp->private_data;
const struct qib_ctxtdata *rcd = fd->rcd;
const struct qib_devdata *dd = rcd->dd;
+ unsigned int weight;
if (dd->flags & QIB_HAS_SEND_DMA) {
fd->pq = qib_user_sdma_queue_create(&dd->pcidev->dev,
@@ -1545,8 +1546,8 @@ done_chk_sdma:
* it just means that sooner or later we don't recommend
* a cpu, and let the scheduler do it's best.
*/
- if (!ret && cpus_weight(current->cpus_allowed) >=
- qib_cpulist_count) {
+ weight = cpumask_weight(tsk_cpus_allowed(current));
+ if (!ret && weight >= qib_cpulist_count) {
int cpu;
cpu = find_first_zero_bit(qib_cpulist,
qib_cpulist_count);
@@ -1554,13 +1555,13 @@ done_chk_sdma:
__set_bit(cpu, qib_cpulist);
fd->rec_cpu_num = cpu;
}
- } else if (cpus_weight(current->cpus_allowed) == 1 &&
- test_bit(first_cpu(current->cpus_allowed),
+ } else if (weight == 1 &&
+ test_bit(cpumask_first(tsk_cpus_allowed(current)),
qib_cpulist))
qib_devinfo(dd->pcidev, "%s PID %u affinity "
"set to cpu %d; already allocated\n",
current->comm, current->pid,
- first_cpu(current->cpus_allowed));
+ cpumask_first(tsk_cpus_allowed(current)));
}
mutex_unlock(&qib_mutex);
@@ -1904,8 +1905,9 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
struct qib_ctxtdata *rcd;
unsigned ctxt;
int ret = 0;
+ unsigned long flags;
- spin_lock(&ppd->dd->uctxt_lock);
+ spin_lock_irqsave(&ppd->dd->uctxt_lock, flags);
for (ctxt = ppd->dd->first_user_ctxt; ctxt < ppd->dd->cfgctxts;
ctxt++) {
rcd = ppd->dd->rcd[ctxt];
@@ -1924,7 +1926,7 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
ret = 1;
break;
}
- spin_unlock(&ppd->dd->uctxt_lock);
+ spin_unlock_irqrestore(&ppd->dd->uctxt_lock, flags);
return ret;
}
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index c765a2eb04cf..e1f947446c2a 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -2434,6 +2434,7 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
int lsb, ret = 0, setforce = 0;
u16 lcmd, licmd;
unsigned long flags;
+ u32 tmp = 0;
switch (which) {
case QIB_IB_CFG_LIDLMC:
@@ -2467,9 +2468,6 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
maskr = IBA7220_IBC_WIDTH_MASK;
lsb = IBA7220_IBC_WIDTH_SHIFT;
setforce = 1;
- spin_lock_irqsave(&ppd->lflags_lock, flags);
- ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
- spin_unlock_irqrestore(&ppd->lflags_lock, flags);
break;
case QIB_IB_CFG_SPD_ENB: /* set allowed Link speeds */
@@ -2643,6 +2641,28 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
goto bail;
}
qib_set_ib_7220_lstate(ppd, lcmd, licmd);
+
+ maskr = IBA7220_IBC_WIDTH_MASK;
+ lsb = IBA7220_IBC_WIDTH_SHIFT;
+ tmp = (ppd->cpspec->ibcddrctrl >> lsb) & maskr;
+ /* If the width active on the chip does not match the
+ * width in the shadow register, write the new active
+ * width to the chip.
+ * We don't have to worry about speed as the speed is taken
+ * care of by set_7220_ibspeed_fast called by ib_updown.
+ */
+ if (ppd->link_width_enabled-1 != tmp) {
+ ppd->cpspec->ibcddrctrl &= ~(maskr << lsb);
+ ppd->cpspec->ibcddrctrl |=
+ (((u64)(ppd->link_width_enabled-1) & maskr) <<
+ lsb);
+ qib_write_kreg(dd, kr_ibcddrctrl,
+ ppd->cpspec->ibcddrctrl);
+ qib_write_kreg(dd, kr_scratch, 0);
+ spin_lock_irqsave(&ppd->lflags_lock, flags);
+ ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
+ spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+ }
goto bail;
case QIB_IB_CFG_HRTBT: /* set Heartbeat off/enable/auto */
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 8ec5237031a0..5ea9ece23b33 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -114,6 +114,10 @@ static ushort qib_singleport;
module_param_named(singleport, qib_singleport, ushort, S_IRUGO);
MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space");
+static ushort qib_krcvq01_no_msi;
+module_param_named(krcvq01_no_msi, qib_krcvq01_no_msi, ushort, S_IRUGO);
+MODULE_PARM_DESC(krcvq01_no_msi, "No MSI for kctx < 2");
+
/*
* Receive header queue sizes
*/
@@ -397,7 +401,6 @@ MODULE_PARM_DESC(txselect, \
#define crp_txdroppedpkt CREG_IDX(TxDroppedPktCnt)
#define crp_txhdrerr CREG_IDX(TxHeadersErrCnt)
#define crp_txlenerr CREG_IDX(TxLenErrCnt)
-#define crp_txlenerr CREG_IDX(TxLenErrCnt)
#define crp_txminmaxlenerr CREG_IDX(TxMaxMinLenErrCnt)
#define crp_txsdmadesc CREG_IDX(TxSDmaDescCnt)
#define crp_txunderrun CREG_IDX(TxUnderrunCnt)
@@ -1107,9 +1110,9 @@ static inline u32 read_7322_creg32_port(const struct qib_pportdata *ppd,
#define AUTONEG_TRIES 3 /* sequential retries to negotiate DDR */
#define HWE_AUTO(fldname) { .mask = SYM_MASK(HwErrMask, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname , .sz = sizeof(#fldname) }
#define HWE_AUTO_P(fldname, port) { .mask = SYM_MASK(HwErrMask, \
- fldname##Mask##_##port), .msg = #fldname }
+ fldname##Mask##_##port), .msg = #fldname , .sz = sizeof(#fldname) }
static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {
HWE_AUTO_P(IBSerdesPClkNotDetect, 1),
HWE_AUTO_P(IBSerdesPClkNotDetect, 0),
@@ -1127,14 +1130,16 @@ static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {
HWE_AUTO_P(IBCBusFromSPCParityErr, 0),
HWE_AUTO(statusValidNoEop),
HWE_AUTO(LATriggered),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
#define E_AUTO(fldname) { .mask = SYM_MASK(ErrMask, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname, .sz = sizeof(#fldname) }
#define E_P_AUTO(fldname) { .mask = SYM_MASK(ErrMask_0, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname, .sz = sizeof(#fldname) }
static const struct qib_hwerror_msgs qib_7322error_msgs[] = {
+ E_AUTO(RcvEgrFullErr),
+ E_AUTO(RcvHdrFullErr),
E_AUTO(ResetNegated),
E_AUTO(HardwareErr),
E_AUTO(InvalidAddrErr),
@@ -1147,9 +1152,7 @@ static const struct qib_hwerror_msgs qib_7322error_msgs[] = {
E_AUTO(SendSpecialTriggerErr),
E_AUTO(SDmaWrongPortErr),
E_AUTO(SDmaBufMaskDuplicateErr),
- E_AUTO(RcvHdrFullErr),
- E_AUTO(RcvEgrFullErr),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
@@ -1159,7 +1162,8 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
/*
* SDmaHaltErr is not really an error, make it clearer;
*/
- {.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted"},
+ {.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted",
+ .sz = 11},
E_P_AUTO(SDmaDescAddrMisalignErr),
E_P_AUTO(SDmaUnexpDataErr),
E_P_AUTO(SDmaMissingDwErr),
@@ -1195,7 +1199,7 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
E_P_AUTO(RcvICRCErr),
E_P_AUTO(RcvVCRCErr),
E_P_AUTO(RcvFormatErr),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
/*
@@ -1203,17 +1207,17 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
* context
*/
#define INTR_AUTO(fldname) { .mask = SYM_MASK(IntMask, fldname##Mask), \
- .msg = #fldname }
+ .msg = #fldname, .sz = sizeof(#fldname) }
/* Below generates "auto-message" for interrupts specific to a port */
#define INTR_AUTO_P(fldname) { .mask = MASK_ACROSS(\
SYM_LSB(IntMask, fldname##Mask##_0), \
SYM_LSB(IntMask, fldname##Mask##_1)), \
- .msg = #fldname "_P" }
+ .msg = #fldname "_P", .sz = sizeof(#fldname "_P") }
/* For some reason, the SerDesTrimDone bits are reversed */
#define INTR_AUTO_PI(fldname) { .mask = MASK_ACROSS(\
SYM_LSB(IntMask, fldname##Mask##_1), \
SYM_LSB(IntMask, fldname##Mask##_0)), \
- .msg = #fldname "_P" }
+ .msg = #fldname "_P", .sz = sizeof(#fldname "_P") }
/*
* Below generates "auto-message" for interrupts specific to a context,
* with ctxt-number appended
@@ -1221,7 +1225,7 @@ static const struct qib_hwerror_msgs qib_7322p_error_msgs[] = {
#define INTR_AUTO_C(fldname) { .mask = MASK_ACROSS(\
SYM_LSB(IntMask, fldname##0IntMask), \
SYM_LSB(IntMask, fldname##17IntMask)), \
- .msg = #fldname "_C"}
+ .msg = #fldname "_C", .sz = sizeof(#fldname "_C") }
static const struct qib_hwerror_msgs qib_7322_intr_msgs[] = {
INTR_AUTO_P(SDmaInt),
@@ -1235,11 +1239,12 @@ static const struct qib_hwerror_msgs qib_7322_intr_msgs[] = {
INTR_AUTO_P(SendDoneInt),
INTR_AUTO(SendBufAvailInt),
INTR_AUTO_C(RcvAvail),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
#define TXSYMPTOM_AUTO_P(fldname) \
- { .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), .msg = #fldname }
+ { .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), \
+ .msg = #fldname, .sz = sizeof(#fldname) }
static const struct qib_hwerror_msgs hdrchk_msgs[] = {
TXSYMPTOM_AUTO_P(NonKeyPacket),
TXSYMPTOM_AUTO_P(GRHFail),
@@ -1248,7 +1253,7 @@ static const struct qib_hwerror_msgs hdrchk_msgs[] = {
TXSYMPTOM_AUTO_P(SLIDFail),
TXSYMPTOM_AUTO_P(RawIPV6),
TXSYMPTOM_AUTO_P(PacketTooSmall),
- { .mask = 0 }
+ { .mask = 0, .sz = 0 }
};
#define IBA7322_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
@@ -1293,7 +1298,7 @@ static void err_decode(char *msg, size_t len, u64 errs,
u64 these, lmask;
int took, multi, n = 0;
- while (msp && msp->mask) {
+ while (errs && msp && msp->mask) {
multi = (msp->mask & (msp->mask - 1));
while (errs & msp->mask) {
these = (errs & msp->mask);
@@ -1304,9 +1309,14 @@ static void err_decode(char *msg, size_t len, u64 errs,
*msg++ = ',';
len--;
}
- took = scnprintf(msg, len, "%s", msp->msg);
+ BUG_ON(!msp->sz);
+ /* msp->sz counts the nul */
+ took = min_t(size_t, msp->sz - (size_t)1, len);
+ memcpy(msg, msp->msg, took);
len -= took;
msg += took;
+ if (len)
+ *msg = '\0';
}
errs &= ~lmask;
if (len && multi) {
@@ -1644,6 +1654,14 @@ done:
return;
}
+static void qib_error_tasklet(unsigned long data)
+{
+ struct qib_devdata *dd = (struct qib_devdata *)data;
+
+ handle_7322_errors(dd);
+ qib_write_kreg(dd, kr_errmask, dd->cspec->errormask);
+}
+
static void reenable_chase(unsigned long opaque)
{
struct qib_pportdata *ppd = (struct qib_pportdata *)opaque;
@@ -2725,8 +2743,10 @@ static noinline void unlikely_7322_intr(struct qib_devdata *dd, u64 istat)
unknown_7322_ibits(dd, istat);
if (istat & QIB_I_GPIO)
unknown_7322_gpio_intr(dd);
- if (istat & QIB_I_C_ERROR)
- handle_7322_errors(dd);
+ if (istat & QIB_I_C_ERROR) {
+ qib_write_kreg(dd, kr_errmask, 0ULL);
+ tasklet_schedule(&dd->error_tasklet);
+ }
if (istat & INT_MASK_P(Err, 0) && dd->rcd[0])
handle_7322_p_errors(dd->rcd[0]->ppd);
if (istat & INT_MASK_P(Err, 1) && dd->rcd[1])
@@ -3125,6 +3145,8 @@ try_intx:
arg = dd->rcd[ctxt];
if (!arg)
continue;
+ if (qib_krcvq01_no_msi && ctxt < 2)
+ continue;
lsb = QIB_I_RCVAVAIL_LSB + ctxt;
handler = qib_7322pintr;
name = QIB_DRV_NAME " (kctx)";
@@ -3159,6 +3181,8 @@ try_intx:
for (i = 0; i < ARRAY_SIZE(redirect); i++)
qib_write_kreg(dd, kr_intredirect + i, redirect[i]);
dd->cspec->main_int_mask = mask;
+ tasklet_init(&dd->error_tasklet, qib_error_tasklet,
+ (unsigned long)dd);
bail:;
}
@@ -6788,6 +6812,10 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev,
(i >= ARRAY_SIZE(irq_table) &&
dd->rcd[i - ARRAY_SIZE(irq_table)]))
actual_cnt++;
+ /* reduce by ctxt's < 2 */
+ if (qib_krcvq01_no_msi)
+ actual_cnt -= dd->num_pports;
+
tabsize = actual_cnt;
dd->cspec->msix_entries = kmalloc(tabsize *
sizeof(struct msix_entry), GFP_KERNEL);
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 8fd3df5bf04d..3b3745f261f0 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -1125,22 +1125,22 @@ static int subn_trap_repress(struct ib_smp *smp, struct ib_device *ibdev,
return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
}
-static int pma_get_classportinfo(struct ib_perf *pmp,
+static int pma_get_classportinfo(struct ib_pma_mad *pmp,
struct ib_device *ibdev)
{
- struct ib_pma_classportinfo *p =
- (struct ib_pma_classportinfo *)pmp->data;
+ struct ib_class_port_info *p =
+ (struct ib_class_port_info *)pmp->data;
struct qib_devdata *dd = dd_from_ibdev(ibdev);
memset(pmp->data, 0, sizeof(pmp->data));
- if (pmp->attr_mod != 0)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0)
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
/* Note that AllPortSelect is not valid */
p->base_version = 1;
p->class_version = 1;
- p->cap_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
+ p->capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
/*
* Set the most significant bit of CM2 to indicate support for
* congestion statistics
@@ -1154,7 +1154,7 @@ static int pma_get_classportinfo(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portsamplescontrol(struct ib_perf *pmp,
+static int pma_get_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -1169,8 +1169,8 @@ static int pma_get_portsamplescontrol(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 || port_select != port) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || port_select != port) {
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
goto bail;
}
spin_lock_irqsave(&ibp->lock, flags);
@@ -1192,7 +1192,7 @@ bail:
return reply((struct ib_smp *) pmp);
}
-static int pma_set_portsamplescontrol(struct ib_perf *pmp,
+static int pma_set_portsamplescontrol(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplescontrol *p =
@@ -1205,8 +1205,8 @@ static int pma_set_portsamplescontrol(struct ib_perf *pmp,
u8 status, xmit_flags;
int ret;
- if (pmp->attr_mod != 0 || p->port_select != port) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || p->port_select != port) {
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -1321,7 +1321,7 @@ static u64 get_cache_hw_sample_counters(struct qib_pportdata *ppd,
return ret;
}
-static int pma_get_portsamplesresult(struct ib_perf *pmp,
+static int pma_get_portsamplesresult(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplesresult *p =
@@ -1360,7 +1360,7 @@ static int pma_get_portsamplesresult(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+static int pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portsamplesresult_ext *p =
@@ -1402,7 +1402,7 @@ static int pma_get_portsamplesresult_ext(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portcounters(struct ib_perf *pmp,
+static int pma_get_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1436,8 +1436,8 @@ static int pma_get_portcounters(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 || port_select != port)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || port_select != port)
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
if (cntrs.symbol_error_counter > 0xFFFFUL)
p->symbol_error_counter = cpu_to_be16(0xFFFF);
@@ -1472,7 +1472,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,
cntrs.local_link_integrity_errors = 0xFUL;
if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
cntrs.excessive_buffer_overrun_errors = 0xFUL;
- p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+ p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors;
if (cntrs.vl15_dropped > 0xFFFFUL)
p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1500,7 +1500,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,
return reply((struct ib_smp *) pmp);
}
-static int pma_get_portcounters_cong(struct ib_perf *pmp,
+static int pma_get_portcounters_cong(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
/* Congestion PMA packets start at offset 24 not 64 */
@@ -1510,7 +1510,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
struct qib_ibport *ibp = to_iport(ibdev, port);
struct qib_pportdata *ppd = ppd_from_ibp(ibp);
struct qib_devdata *dd = dd_from_ppd(ppd);
- u32 port_select = be32_to_cpu(pmp->attr_mod) & 0xFF;
+ u32 port_select = be32_to_cpu(pmp->mad_hdr.attr_mod) & 0xFF;
u64 xmit_wait_counter;
unsigned long flags;
@@ -1519,9 +1519,9 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
* SET method ends up calling this anyway.
*/
if (!dd->psxmitwait_supported)
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
if (port_select != port)
- pmp->status |= IB_SMP_INVALID_FIELD;
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
qib_get_counters(ppd, &cntrs);
spin_lock_irqsave(&ppd->ibport_data.lock, flags);
@@ -1603,7 +1603,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
cntrs.local_link_integrity_errors = 0xFUL;
if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
cntrs.excessive_buffer_overrun_errors = 0xFUL;
- p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+ p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors;
if (cntrs.vl15_dropped > 0xFFFFUL)
p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1613,7 +1613,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
return reply((struct ib_smp *)pmp);
}
-static int pma_get_portcounters_ext(struct ib_perf *pmp,
+static int pma_get_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters_ext *p =
@@ -1626,8 +1626,8 @@ static int pma_get_portcounters_ext(struct ib_perf *pmp,
memset(pmp->data, 0, sizeof(pmp->data));
p->port_select = port_select;
- if (pmp->attr_mod != 0 || port_select != port) {
- pmp->status |= IB_SMP_INVALID_FIELD;
+ if (pmp->mad_hdr.attr_mod != 0 || port_select != port) {
+ pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
goto bail;
}
@@ -1652,7 +1652,7 @@ bail:
return reply((struct ib_smp *) pmp);
}
-static int pma_set_portcounters(struct ib_perf *pmp,
+static int pma_set_portcounters(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1715,14 +1715,14 @@ static int pma_set_portcounters(struct ib_perf *pmp,
return pma_get_portcounters(pmp, ibdev, port);
}
-static int pma_set_portcounters_cong(struct ib_perf *pmp,
+static int pma_set_portcounters_cong(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct qib_ibport *ibp = to_iport(ibdev, port);
struct qib_pportdata *ppd = ppd_from_ibp(ibp);
struct qib_devdata *dd = dd_from_ppd(ppd);
struct qib_verbs_counters cntrs;
- u32 counter_select = (be32_to_cpu(pmp->attr_mod) >> 24) & 0xFF;
+ u32 counter_select = (be32_to_cpu(pmp->mad_hdr.attr_mod) >> 24) & 0xFF;
int ret = 0;
unsigned long flags;
@@ -1766,7 +1766,7 @@ static int pma_set_portcounters_cong(struct ib_perf *pmp,
return ret;
}
-static int pma_set_portcounters_ext(struct ib_perf *pmp,
+static int pma_set_portcounters_ext(struct ib_pma_mad *pmp,
struct ib_device *ibdev, u8 port)
{
struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1959,19 +1959,19 @@ static int process_perf(struct ib_device *ibdev, u8 port,
struct ib_mad *in_mad,
struct ib_mad *out_mad)
{
- struct ib_perf *pmp = (struct ib_perf *)out_mad;
+ struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
int ret;
*out_mad = *in_mad;
- if (pmp->class_version != 1) {
- pmp->status |= IB_SMP_UNSUP_VERSION;
+ if (pmp->mad_hdr.class_version != 1) {
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
- switch (pmp->method) {
+ switch (pmp->mad_hdr.method) {
case IB_MGMT_METHOD_GET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_CLASS_PORT_INFO:
ret = pma_get_classportinfo(pmp, ibdev);
goto bail;
@@ -1994,13 +1994,13 @@ static int process_perf(struct ib_device *ibdev, u8 port,
ret = pma_get_portcounters_cong(pmp, ibdev, port);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
case IB_MGMT_METHOD_SET:
- switch (pmp->attr_id) {
+ switch (pmp->mad_hdr.attr_id) {
case IB_PMA_PORT_SAMPLES_CONTROL:
ret = pma_set_portsamplescontrol(pmp, ibdev, port);
goto bail;
@@ -2014,7 +2014,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,
ret = pma_set_portcounters_cong(pmp, ibdev, port);
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
ret = reply((struct ib_smp *) pmp);
goto bail;
}
@@ -2030,7 +2030,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,
goto bail;
default:
- pmp->status |= IB_SMP_UNSUP_METHOD;
+ pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD;
ret = reply((struct ib_smp *) pmp);
}
diff --git a/drivers/infiniband/hw/qib/qib_mad.h b/drivers/infiniband/hw/qib/qib_mad.h
index 7840ab593bcf..ecc416cdbaaa 100644
--- a/drivers/infiniband/hw/qib/qib_mad.h
+++ b/drivers/infiniband/hw/qib/qib_mad.h
@@ -32,6 +32,8 @@
* SOFTWARE.
*/
+#include <rdma/ib_pma.h>
+
#define IB_SMP_UNSUP_VERSION cpu_to_be16(0x0004)
#define IB_SMP_UNSUP_METHOD cpu_to_be16(0x0008)
#define IB_SMP_UNSUP_METH_ATTR cpu_to_be16(0x000C)
@@ -180,109 +182,8 @@ struct ib_vl_weight_elem {
#define IB_VLARB_HIGHPRI_0_31 3
#define IB_VLARB_HIGHPRI_32_63 4
-/*
- * PMA class portinfo capability mask bits
- */
-#define IB_PMA_CLASS_CAP_ALLPORTSELECT cpu_to_be16(1 << 8)
-#define IB_PMA_CLASS_CAP_EXT_WIDTH cpu_to_be16(1 << 9)
-#define IB_PMA_CLASS_CAP_XMIT_WAIT cpu_to_be16(1 << 12)
-
-#define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001)
-#define IB_PMA_PORT_SAMPLES_CONTROL cpu_to_be16(0x0010)
-#define IB_PMA_PORT_SAMPLES_RESULT cpu_to_be16(0x0011)
-#define IB_PMA_PORT_COUNTERS cpu_to_be16(0x0012)
-#define IB_PMA_PORT_COUNTERS_EXT cpu_to_be16(0x001D)
-#define IB_PMA_PORT_SAMPLES_RESULT_EXT cpu_to_be16(0x001E)
#define IB_PMA_PORT_COUNTERS_CONG cpu_to_be16(0xFF00)
-struct ib_perf {
- u8 base_version;
- u8 mgmt_class;
- u8 class_version;
- u8 method;
- __be16 status;
- __be16 unused;
- __be64 tid;
- __be16 attr_id;
- __be16 resv;
- __be32 attr_mod;
- u8 reserved[40];
- u8 data[192];
-} __attribute__ ((packed));
-
-struct ib_pma_classportinfo {
- u8 base_version;
- u8 class_version;
- __be16 cap_mask;
- u8 reserved[3];
- u8 resp_time_value; /* only lower 5 bits */
- union ib_gid redirect_gid;
- __be32 redirect_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 redirect_lid;
- __be16 redirect_pkey;
- __be32 redirect_qp; /* only lower 24 bits */
- __be32 redirect_qkey;
- union ib_gid trap_gid;
- __be32 trap_tc_sl_fl; /* 8, 4, 20 bits respectively */
- __be16 trap_lid;
- __be16 trap_pkey;
- __be32 trap_hl_qp; /* 8, 24 bits respectively */
- __be32 trap_qkey;
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplescontrol {
- u8 opcode;
- u8 port_select;
- u8 tick;
- u8 counter_width; /* only lower 3 bits */
- __be32 counter_mask0_9; /* 2, 10 * 3, bits */
- __be16 counter_mask10_14; /* 1, 5 * 3, bits */
- u8 sample_mechanisms;
- u8 sample_status; /* only lower 2 bits */
- __be64 option_mask;
- __be64 vendor_mask;
- __be32 sample_start;
- __be32 sample_interval;
- __be16 tag;
- __be16 counter_select[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult_ext {
- __be16 tag;
- __be16 sample_status; /* only lower 2 bits */
- __be32 extended_width; /* only upper 2 bits */
- __be64 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portcounters {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be16 symbol_error_counter;
- u8 link_error_recovery_counter;
- u8 link_downed_counter;
- __be16 port_rcv_errors;
- __be16 port_rcv_remphys_errors;
- __be16 port_rcv_switch_relay_errors;
- __be16 port_xmit_discards;
- u8 port_xmit_constraint_errors;
- u8 port_rcv_constraint_errors;
- u8 reserved1;
- u8 lli_ebor_errors; /* 4, 4, bits */
- __be16 reserved2;
- __be16 vl15_dropped;
- __be32 port_xmit_data;
- __be32 port_rcv_data;
- __be32 port_xmit_packets;
- __be32 port_rcv_packets;
-} __attribute__ ((packed));
-
struct ib_pma_portcounters_cong {
u8 reserved;
u8 reserved1;
@@ -297,7 +198,7 @@ struct ib_pma_portcounters_cong {
u8 port_xmit_constraint_errors;
u8 port_rcv_constraint_errors;
u8 reserved2;
- u8 lli_ebor_errors; /* 4, 4, bits */
+ u8 link_overrun_errors; /* LocalLink: 7:4, BufferOverrun: 3:0 */
__be16 reserved3;
__be16 vl15_dropped;
__be64 port_xmit_data;
@@ -316,49 +217,11 @@ struct ib_pma_portcounters_cong {
/* number of 4nsec cycles equaling 2secs */
#define QIB_CONG_TIMER_PSINTERVAL 0x1DCD64EC
-#define IB_PMA_SEL_SYMBOL_ERROR cpu_to_be16(0x0001)
-#define IB_PMA_SEL_LINK_ERROR_RECOVERY cpu_to_be16(0x0002)
-#define IB_PMA_SEL_LINK_DOWNED cpu_to_be16(0x0004)
-#define IB_PMA_SEL_PORT_RCV_ERRORS cpu_to_be16(0x0008)
-#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS cpu_to_be16(0x0010)
-#define IB_PMA_SEL_PORT_XMIT_DISCARDS cpu_to_be16(0x0040)
-#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS cpu_to_be16(0x0200)
-#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS cpu_to_be16(0x0400)
-#define IB_PMA_SEL_PORT_VL15_DROPPED cpu_to_be16(0x0800)
-#define IB_PMA_SEL_PORT_XMIT_DATA cpu_to_be16(0x1000)
-#define IB_PMA_SEL_PORT_RCV_DATA cpu_to_be16(0x2000)
-#define IB_PMA_SEL_PORT_XMIT_PACKETS cpu_to_be16(0x4000)
-#define IB_PMA_SEL_PORT_RCV_PACKETS cpu_to_be16(0x8000)
-
#define IB_PMA_SEL_CONG_ALL 0x01
#define IB_PMA_SEL_CONG_PORT_DATA 0x02
#define IB_PMA_SEL_CONG_XMIT 0x04
#define IB_PMA_SEL_CONG_ROUTING 0x08
-struct ib_pma_portcounters_ext {
- u8 reserved;
- u8 port_select;
- __be16 counter_select;
- __be32 reserved1;
- __be64 port_xmit_data;
- __be64 port_rcv_data;
- __be64 port_xmit_packets;
- __be64 port_rcv_packets;
- __be64 port_unicast_xmit_packets;
- __be64 port_unicast_rcv_packets;
- __be64 port_multicast_xmit_packets;
- __be64 port_multicast_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SELX_PORT_XMIT_DATA cpu_to_be16(0x0001)
-#define IB_PMA_SELX_PORT_RCV_DATA cpu_to_be16(0x0002)
-#define IB_PMA_SELX_PORT_XMIT_PACKETS cpu_to_be16(0x0004)
-#define IB_PMA_SELX_PORT_RCV_PACKETS cpu_to_be16(0x0008)
-#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS cpu_to_be16(0x0010)
-#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS cpu_to_be16(0x0020)
-#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS cpu_to_be16(0x0040)
-#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS cpu_to_be16(0x0080)
-
/*
* The PortSamplesControl.CounterMasks field is an array of 3 bit fields
* which specify the N'th counter's capabilities. See ch. 16.1.3.2.
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index 891cc2ff5f00..4426782ad288 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -255,7 +255,7 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,
u16 linkstat, speed;
int pos = 0, pose, ret = 1;
- pose = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
+ pose = pci_pcie_cap(dd->pcidev);
if (!pose) {
qib_dev_err(dd, "Can't find PCI Express capability!\n");
/* set up something... */
@@ -509,7 +509,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
qib_devinfo(dd->pcidev, "Parent not root\n");
return 1;
}
- ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+ ppos = pci_pcie_cap(parent);
if (!ppos)
return 1;
if (parent->vendor != 0x8086)
@@ -578,14 +578,14 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
qib_devinfo(dd->pcidev, "Parent not root\n");
goto bail;
}
- ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+ ppos = pci_pcie_cap(parent);
if (ppos) {
pci_read_config_word(parent, ppos + PCI_EXP_DEVCAP, &pcaps);
pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
} else
goto bail;
/* Find out supported and configured values for endpoint (us) */
- epos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
+ epos = pci_pcie_cap(dd->pcidev);
if (epos) {
pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCAP, &ecaps);
pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, &ectl);
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index d50a33fe8bbc..14d129de4320 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -507,6 +507,18 @@ static ssize_t show_nctxts(struct device *device,
dd->first_user_ctxt);
}
+static ssize_t show_nfreectxts(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct qib_ibdev *dev =
+ container_of(device, struct qib_ibdev, ibdev.dev);
+ 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);
+}
+
static ssize_t show_serial(struct device *device,
struct device_attribute *attr, char *buf)
{
@@ -604,6 +616,7 @@ static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL);
+static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);
static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
@@ -617,6 +630,7 @@ static struct device_attribute *qib_attributes[] = {
&dev_attr_board_id,
&dev_attr_version,
&dev_attr_nctxts,
+ &dev_attr_nfreectxts,
&dev_attr_serial,
&dev_attr_boardversion,
&dev_attr_logged_errors,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 7b6985a2e652..b3cc1e062b17 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -45,7 +45,7 @@
#include <net/neighbour.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 86addca9ddf6..43f89ba0a908 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -560,9 +560,11 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
struct ipoib_neigh *neigh;
+ struct neighbour *n;
unsigned long flags;
- neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
+ n = dst_get_neighbour(skb_dst(skb));
+ neigh = ipoib_neigh_alloc(n, skb->dev);
if (!neigh) {
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -571,9 +573,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&priv->lock, flags);
- path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
+ path = __path_find(dev, n->ha + 4);
if (!path) {
- path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
+ path = path_rec_create(dev, n->ha + 4);
if (!path)
goto err_path;
@@ -607,7 +609,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
}
} else {
spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha));
return;
}
} else {
@@ -637,17 +639,20 @@ err_drop:
static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n;
/* Look up path record for unicasts */
- if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
+ n = dst_get_neighbour(dst);
+ if (n->ha[4] != 0xff) {
neigh_add_path(skb, dev);
return;
}
/* Add in the P_Key for multicasts */
- skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
- skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
- ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
+ n->ha[8] = (priv->pkey >> 8) & 0xff;
+ n->ha[9] = priv->pkey & 0xff;
+ ipoib_mcast_send(dev, n->ha + 4, skb);
}
static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -712,18 +717,20 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh;
+ struct neighbour *n;
unsigned long flags;
- if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
- if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
+ n = dst_get_neighbour(skb_dst(skb));
+ if (likely(skb_dst(skb) && n)) {
+ if (unlikely(!*to_ipoib_neigh(n))) {
ipoib_path_lookup(skb, dev);
return NETDEV_TX_OK;
}
- neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
+ neigh = *to_ipoib_neigh(n);
if (unlikely((memcmp(&neigh->dgid.raw,
- skb_dst(skb)->neighbour->ha + 4,
+ n->ha + 4,
sizeof(union ib_gid))) ||
(neigh->dev != dev))) {
spin_lock_irqsave(&priv->lock, flags);
@@ -749,7 +756,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
} else if (neigh->ah) {
- ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+ ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
return NETDEV_TX_OK;
}
@@ -812,6 +819,8 @@ static int ipoib_hard_header(struct sk_buff *skb,
const void *daddr, const void *saddr, unsigned len)
{
struct ipoib_header *header;
+ struct dst_entry *dst;
+ struct neighbour *n;
header = (struct ipoib_header *) skb_push(skb, sizeof *header);
@@ -823,7 +832,11 @@ static int ipoib_hard_header(struct sk_buff *skb,
* destination address onto the front of the skb so we can
* figure out where to send the packet later.
*/
- if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
+ dst = skb_dst(skb);
+ n = NULL;
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if ((!dst || !n) && daddr) {
struct ipoib_pseudoheader *phdr =
(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 3871ac663554..ecea4fe1ed00 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -258,11 +258,15 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
netif_tx_lock_bh(dev);
while (!skb_queue_empty(&mcast->pkt_queue)) {
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n = NULL;
+
netif_tx_unlock_bh(dev);
skb->dev = dev;
-
- if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (!dst || !n) {
/* put pseudoheader back on for next time */
skb_push(skb, sizeof (struct ipoib_pseudoheader));
}
@@ -715,11 +719,13 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
out:
if (mcast && mcast->ah) {
- if (skb_dst(skb) &&
- skb_dst(skb)->neighbour &&
- !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
- struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
- skb->dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n = NULL;
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (n && !*to_ipoib_neigh(n)) {
+ struct ipoib_neigh *neigh = ipoib_neigh_alloc(n,
+ skb->dev);
if (neigh) {
kref_get(&mcast->ah->ref);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 2f02ab0ccc1e..342cbc1bdaae 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -45,6 +45,7 @@
#include <scsi/libiscsi.h>
#include <scsi/scsi_transport_iscsi.h>
+#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/list.h>
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ee165fdcb596..0bfa545675b8 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -39,7 +39,7 @@
#include <linux/random.h>
#include <linux/jiffies.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -2127,6 +2127,8 @@ static ssize_t srp_create_target(struct device *dev,
return -ENOMEM;
target_host->transportt = ib_srp_transport_template;
+ target_host->max_channel = 0;
+ target_host->max_id = 1;
target_host->max_lun = SRP_MAX_LUN;
target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 5b8f59d6c3e8..c351aa421f8f 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -47,7 +47,7 @@ static void gameport_disconnect_port(struct gameport *gameport);
#if defined(__i386__)
-#include <asm/i8253.h>
+#include <linux/i8253.h>
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
#define GET_TIME(x) do { x = get_time_pit(); } while (0)
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 4afe0a3b4884..9882971827e6 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -136,7 +136,7 @@ struct analog_port {
#ifdef __i386__
-#include <asm/i8253.h>
+#include <linux/i8253.h>
#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0)))
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 45dc6aa62ba4..d1bf8724b58f 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -267,7 +267,7 @@ config INPUT_TWL4030_PWRBUTTON
config INPUT_TWL4030_VIBRA
tristate "Support for TWL4030 Vibrator"
depends on TWL4030_CORE
- select TWL4030_CODEC
+ select MFD_TWL4030_AUDIO
select INPUT_FF_MEMLESS
help
This option enables support for TWL4030 Vibrator Driver.
@@ -275,6 +275,17 @@ config INPUT_TWL4030_VIBRA
To compile this driver as a module, choose M here. The module will
be called twl4030_vibra.
+config INPUT_TWL6040_VIBRA
+ tristate "Support for TWL6040 Vibrator"
+ depends on TWL4030_CORE
+ select TWL6040_CORE
+ select INPUT_FF_MEMLESS
+ help
+ This option enables support for TWL6040 Vibrator Driver.
+
+ To compile this driver as a module, choose M here. The module will
+ be called twl6040_vibra.
+
config INPUT_UINPUT
tristate "User level driver support"
help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 38efb2cb182b..4da7c3a60e04 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
+obj-$(CONFIG_INPUT_TWL6040_VIBRA) += twl6040-vibra.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index f080dd31499b..34f4d2e0f50f 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/i8253.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/platform_device.h>
@@ -25,14 +26,6 @@ MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcspkr");
-#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
-/* Use the global PIT lock ! */
-#include <asm/i8253.h>
-#else
-#include <asm/8253pit.h>
-static DEFINE_RAW_SPINLOCK(i8253_lock);
-#endif
-
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
unsigned int count = 0;
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 014dd4ad0d4f..3c1a432c14dc 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -28,7 +28,7 @@
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/i2c/twl.h>
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
#include <linux/input.h>
#include <linux/slab.h>
@@ -67,7 +67,7 @@ static void vibra_enable(struct vibra_info *info)
{
u8 reg;
- twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
+ twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER);
/* turn H-Bridge on */
twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
@@ -75,7 +75,7 @@ static void vibra_enable(struct vibra_info *info)
twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
(reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
- twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL);
+ twl4030_audio_enable_resource(TWL4030_AUDIO_RES_APLL);
info->enabled = true;
}
@@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info)
twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
(reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
- twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
- twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
+ twl4030_audio_disable_resource(TWL4030_AUDIO_RES_APLL);
+ twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
info->enabled = false;
}
@@ -196,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
{
- struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
+ struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
struct vibra_info *info;
int ret;
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
new file mode 100644
index 000000000000..c43002e7ec72
--- /dev/null
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -0,0 +1,423 @@
+/*
+ * twl6040-vibra.c - TWL6040 Vibrator driver
+ *
+ * Author: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * Copyright: (C) 2011 Texas Instruments, Inc.
+ *
+ * Based on twl4030-vibra.c by Henrik Saari <henrik.saari@nokia.com>
+ * Felipe Balbi <felipe.balbi@nokia.com>
+ * Jari Vanhala <ext-javi.vanhala@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+
+#define EFFECT_DIR_180_DEG 0x8000
+
+/* Recommended modulation index 85% */
+#define TWL6040_VIBRA_MOD 85
+
+#define TWL6040_NUM_SUPPLIES 2
+
+struct vibra_info {
+ struct device *dev;
+ struct input_dev *input_dev;
+ struct workqueue_struct *workqueue;
+ struct work_struct play_work;
+ struct mutex mutex;
+ int irq;
+
+ bool enabled;
+ int weak_speed;
+ int strong_speed;
+ int direction;
+
+ unsigned int vibldrv_res;
+ unsigned int vibrdrv_res;
+ unsigned int viblmotor_res;
+ unsigned int vibrmotor_res;
+
+ struct regulator_bulk_data supplies[TWL6040_NUM_SUPPLIES];
+
+ struct twl6040 *twl6040;
+};
+
+static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
+{
+ struct vibra_info *info = data;
+ struct twl6040 *twl6040 = info->twl6040;
+ u8 status;
+
+ status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
+ if (status & TWL6040_VIBLOCDET) {
+ dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
+ twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
+ TWL6040_VIBENAL);
+ }
+ if (status & TWL6040_VIBROCDET) {
+ dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
+ twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
+ TWL6040_VIBENAR);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void twl6040_vibra_enable(struct vibra_info *info)
+{
+ struct twl6040 *twl6040 = info->twl6040;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(info->supplies), info->supplies);
+ if (ret) {
+ dev_err(info->dev, "failed to enable regulators %d\n", ret);
+ return;
+ }
+
+ twl6040_power(info->twl6040, 1);
+ if (twl6040->rev <= 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_reg_write(twl6040, TWL6040_REG_VIBCTLR,
+ TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+ usleep_range(3000, 3500);
+ }
+
+ twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
+ TWL6040_VIBENAL);
+ twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
+ TWL6040_VIBENAR);
+
+ info->enabled = true;
+}
+
+static void twl6040_vibra_disable(struct vibra_info *info)
+{
+ struct twl6040 *twl6040 = info->twl6040;
+
+ twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, 0x00);
+ twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, 0x00);
+ twl6040_power(info->twl6040, 0);
+
+ regulator_bulk_disable(ARRAY_SIZE(info->supplies), info->supplies);
+
+ info->enabled = false;
+}
+
+static u8 twl6040_vibra_code(int vddvib, int vibdrv_res, int motor_res,
+ int speed, int direction)
+{
+ int vpk, max_code;
+ u8 vibdat;
+
+ /* output swing */
+ vpk = (vddvib * motor_res * TWL6040_VIBRA_MOD) /
+ (100 * (vibdrv_res + motor_res));
+
+ /* 50mV per VIBDAT code step */
+ max_code = vpk / 50;
+ if (max_code > TWL6040_VIBDAT_MAX)
+ max_code = TWL6040_VIBDAT_MAX;
+
+ /* scale speed to max allowed code */
+ vibdat = (u8)((speed * max_code) / USHRT_MAX);
+
+ /* 2's complement for direction > 180 degrees */
+ vibdat *= direction;
+
+ return vibdat;
+}
+
+static void twl6040_vibra_set_effect(struct vibra_info *info)
+{
+ struct twl6040 *twl6040 = info->twl6040;
+ u8 vibdatl, vibdatr;
+ int volt;
+
+ /* weak motor */
+ volt = regulator_get_voltage(info->supplies[0].consumer) / 1000;
+ vibdatl = twl6040_vibra_code(volt, info->vibldrv_res,
+ info->viblmotor_res,
+ info->weak_speed, info->direction);
+
+ /* strong motor */
+ volt = regulator_get_voltage(info->supplies[1].consumer) / 1000;
+ vibdatr = twl6040_vibra_code(volt, info->vibrdrv_res,
+ info->vibrmotor_res,
+ info->strong_speed, info->direction);
+
+ twl6040_reg_write(twl6040, TWL6040_REG_VIBDATL, vibdatl);
+ twl6040_reg_write(twl6040, TWL6040_REG_VIBDATR, vibdatr);
+}
+
+static void vibra_play_work(struct work_struct *work)
+{
+ struct vibra_info *info = container_of(work,
+ struct vibra_info, play_work);
+
+ mutex_lock(&info->mutex);
+
+ if (info->weak_speed || info->strong_speed) {
+ if (!info->enabled)
+ twl6040_vibra_enable(info);
+
+ twl6040_vibra_set_effect(info);
+ } else if (info->enabled)
+ twl6040_vibra_disable(info);
+
+ mutex_unlock(&info->mutex);
+}
+
+static int vibra_play(struct input_dev *input, void *data,
+ struct ff_effect *effect)
+{
+ struct vibra_info *info = input_get_drvdata(input);
+ int ret;
+
+ 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;
+
+ ret = queue_work(info->workqueue, &info->play_work);
+ if (!ret) {
+ dev_info(&input->dev, "work is already on queue\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void twl6040_vibra_close(struct input_dev *input)
+{
+ struct vibra_info *info = input_get_drvdata(input);
+
+ cancel_work_sync(&info->play_work);
+
+ mutex_lock(&info->mutex);
+
+ if (info->enabled)
+ twl6040_vibra_disable(info);
+
+ mutex_unlock(&info->mutex);
+}
+
+#if CONFIG_PM_SLEEP
+static int twl6040_vibra_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct vibra_info *info = platform_get_drvdata(pdev);
+
+ mutex_lock(&info->mutex);
+
+ if (info->enabled)
+ twl6040_vibra_disable(info);
+
+ mutex_unlock(&info->mutex);
+
+ return 0;
+}
+
+#endif
+
+static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
+
+static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
+{
+ struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+ struct vibra_info *info;
+ int ret;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "platform_data not available\n");
+ return -EINVAL;
+ }
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ dev_err(&pdev->dev, "couldn't allocate memory\n");
+ return -ENOMEM;
+ }
+
+ info->dev = &pdev->dev;
+ info->twl6040 = dev_get_drvdata(pdev->dev.parent);
+ info->vibldrv_res = pdata->vibldrv_res;
+ info->vibrdrv_res = pdata->vibrdrv_res;
+ info->viblmotor_res = pdata->viblmotor_res;
+ info->vibrmotor_res = pdata->vibrmotor_res;
+ if ((!info->vibldrv_res && !info->viblmotor_res) ||
+ (!info->vibrdrv_res && !info->vibrmotor_res)) {
+ dev_err(info->dev, "invalid vibra driver/motor resistance\n");
+ ret = -EINVAL;
+ goto err_kzalloc;
+ }
+
+ info->irq = platform_get_irq(pdev, 0);
+ if (info->irq < 0) {
+ dev_err(info->dev, "invalid irq\n");
+ ret = -EINVAL;
+ goto err_kzalloc;
+ }
+
+ mutex_init(&info->mutex);
+
+ info->input_dev = input_allocate_device();
+ if (info->input_dev == NULL) {
+ dev_err(info->dev, "couldn't allocate input device\n");
+ ret = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ input_set_drvdata(info->input_dev, info);
+
+ info->input_dev->name = "twl6040:vibrator";
+ info->input_dev->id.version = 1;
+ info->input_dev->dev.parent = pdev->dev.parent;
+ info->input_dev->close = twl6040_vibra_close;
+ __set_bit(FF_RUMBLE, info->input_dev->ffbit);
+
+ ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
+ if (ret < 0) {
+ dev_err(info->dev, "couldn't register vibrator to FF\n");
+ goto err_ialloc;
+ }
+
+ ret = input_register_device(info->input_dev);
+ if (ret < 0) {
+ dev_err(info->dev, "couldn't register input device\n");
+ goto err_iff;
+ }
+
+ platform_set_drvdata(pdev, info);
+
+ ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0,
+ "twl6040_irq_vib", info);
+ if (ret) {
+ dev_err(info->dev, "VIB IRQ request failed: %d\n", ret);
+ goto err_irq;
+ }
+
+ info->supplies[0].supply = "vddvibl";
+ info->supplies[1].supply = "vddvibr";
+ ret = regulator_bulk_get(info->dev, ARRAY_SIZE(info->supplies),
+ info->supplies);
+ if (ret) {
+ dev_err(info->dev, "couldn't get regulators %d\n", ret);
+ goto err_regulator;
+ }
+
+ if (pdata->vddvibl_uV) {
+ ret = regulator_set_voltage(info->supplies[0].consumer,
+ pdata->vddvibl_uV,
+ pdata->vddvibl_uV);
+ if (ret) {
+ dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
+ ret);
+ goto err_voltage;
+ }
+ }
+
+ if (pdata->vddvibr_uV) {
+ ret = regulator_set_voltage(info->supplies[1].consumer,
+ pdata->vddvibr_uV,
+ pdata->vddvibr_uV);
+ if (ret) {
+ dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
+ ret);
+ goto err_voltage;
+ }
+ }
+
+ info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0);
+ if (info->workqueue == NULL) {
+ dev_err(info->dev, "couldn't create workqueue\n");
+ ret = -ENOMEM;
+ goto err_voltage;
+ }
+ INIT_WORK(&info->play_work, vibra_play_work);
+
+ return 0;
+
+err_voltage:
+ regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
+err_regulator:
+ free_irq(info->irq, info);
+err_irq:
+ input_unregister_device(info->input_dev);
+ info->input_dev = NULL;
+err_iff:
+ if (info->input_dev)
+ input_ff_destroy(info->input_dev);
+err_ialloc:
+ input_free_device(info->input_dev);
+err_kzalloc:
+ kfree(info);
+ return ret;
+}
+
+static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
+{
+ struct vibra_info *info = platform_get_drvdata(pdev);
+
+ input_unregister_device(info->input_dev);
+ free_irq(info->irq, info);
+ regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
+ destroy_workqueue(info->workqueue);
+ kfree(info);
+
+ return 0;
+}
+
+static struct platform_driver twl6040_vibra_driver = {
+ .probe = twl6040_vibra_probe,
+ .remove = __devexit_p(twl6040_vibra_remove),
+ .driver = {
+ .name = "twl6040-vibra",
+ .owner = THIS_MODULE,
+ .pm = &twl6040_vibra_pm_ops,
+ },
+};
+
+static int __init twl6040_vibra_init(void)
+{
+ return platform_driver_register(&twl6040_vibra_driver);
+}
+module_init(twl6040_vibra_init);
+
+static void __exit twl6040_vibra_exit(void)
+{
+ platform_driver_unregister(&twl6040_vibra_driver);
+}
+module_exit(twl6040_vibra_exit);
+
+MODULE_ALIAS("platform:twl6040-vibra");
+MODULE_DESCRIPTION("TWL6040 Vibra driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 980af94ba9c8..07a8363f3c5c 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -210,7 +210,7 @@ int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
/*
* Some devices (Synaptics) peform the reset before
* ACKing the reset command, and so it can take a long
- * time before the ACK arrrives.
+ * time before the ACK arrives.
*/
if (ps2_sendbyte(ps2dev, command & 0xff,
command == PS2_CMD_RESET_BAT ? 1000 : 200))
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index d55874e5d1c2..44fc8b4bcd81 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -300,8 +300,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
out:
sa1111_disable_device(ps2if->dev);
- release_mem_region(dev->res.start,
- dev->res.end - dev->res.start + 1);
+ release_mem_region(dev->res.start, resource_size(&dev->res));
free:
sa1111_set_drvdata(dev, NULL);
kfree(ps2if);
@@ -317,8 +316,7 @@ static int __devexit ps2_remove(struct sa1111_dev *dev)
struct ps2if *ps2if = sa1111_get_drvdata(dev);
serio_unregister_port(ps2if->io);
- release_mem_region(dev->res.start,
- dev->res.end - dev->res.start + 1);
+ release_mem_region(dev->res.start, resource_size(&dev->res));
sa1111_set_drvdata(dev, NULL);
kfree(ps2if);
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
new file mode 100644
index 000000000000..b57b3fa492f3
--- /dev/null
+++ b/drivers/iommu/Kconfig
@@ -0,0 +1,110 @@
+# IOMMU_API always gets selected by whoever wants it.
+config IOMMU_API
+ bool
+
+menuconfig IOMMU_SUPPORT
+ bool "IOMMU Hardware Support"
+ default y
+ ---help---
+ Say Y here if you want to compile device drivers for IO Memory
+ Management Units into the kernel. These devices usually allow to
+ remap DMA requests and/or remap interrupts from other devices on the
+ system.
+
+if IOMMU_SUPPORT
+
+# MSM IOMMU support
+config MSM_IOMMU
+ bool "MSM IOMMU Support"
+ depends on ARCH_MSM8X60 || ARCH_MSM8960
+ select IOMMU_API
+ help
+ Support for the IOMMUs found on certain Qualcomm SOCs.
+ These IOMMUs allow virtualization of the address space used by most
+ cores within the multimedia subsystem.
+
+ If unsure, say N here.
+
+config IOMMU_PGTABLES_L2
+ def_bool y
+ depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
+
+# AMD IOMMU support
+config AMD_IOMMU
+ bool "AMD IOMMU support"
+ select SWIOTLB
+ select PCI_MSI
+ select PCI_IOV
+ select IOMMU_API
+ depends on X86_64 && PCI && ACPI
+ ---help---
+ With this option you can enable support for AMD IOMMU hardware in
+ your system. An IOMMU is a hardware component which provides
+ remapping of DMA memory accesses from devices. With an AMD IOMMU you
+ can isolate the the DMA memory of different devices and protect the
+ system from misbehaving device drivers or hardware.
+
+ You can find out if your system has an AMD IOMMU if you look into
+ your BIOS for an option to enable it or if you have an IVRS ACPI
+ table.
+
+config AMD_IOMMU_STATS
+ bool "Export AMD IOMMU statistics to debugfs"
+ depends on AMD_IOMMU
+ select DEBUG_FS
+ ---help---
+ This option enables code in the AMD IOMMU driver to collect various
+ statistics about whats happening in the driver and exports that
+ information to userspace via debugfs.
+ If unsure, say N.
+
+# Intel IOMMU support
+config DMAR
+ bool "Support for DMA Remapping Devices"
+ depends on PCI_MSI && ACPI && (X86 || IA64_GENERIC)
+ select IOMMU_API
+ help
+ DMA remapping (DMAR) devices support enables independent address
+ translations for Direct Memory Access (DMA) from devices.
+ These DMA remapping devices are reported via ACPI tables
+ and include PCI device scope covered by these DMA
+ remapping devices.
+
+config DMAR_DEFAULT_ON
+ def_bool y
+ prompt "Enable DMA Remapping Devices by default"
+ depends on DMAR
+ 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
+ bool "Workaround broken graphics drivers (going away soon)"
+ depends on DMAR && BROKEN && X86
+ ---help---
+ Current Graphics drivers tend to use physical address
+ for DMA and avoid using DMA APIs. Setting this config
+ option permits the IOMMU driver to set a unity map for
+ all the OS-visible memory. Hence the driver can continue
+ to use physical addresses for DMA, at least until this
+ option is removed in the 2.6.32 kernel.
+
+config DMAR_FLOPPY_WA
+ def_bool y
+ depends on DMAR && 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
+ bool "Support for Interrupt Remapping (EXPERIMENTAL)"
+ depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+ ---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.
+
+endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
new file mode 100644
index 000000000000..4d4d77df7cac
--- /dev/null
+++ b/drivers/iommu/Makefile
@@ -0,0 +1,5 @@
+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
diff --git a/arch/x86/kernel/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 7c3a95e54ec5..a14f8dc23462 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -27,13 +27,15 @@
#include <linux/iommu-helper.h>
#include <linux/iommu.h>
#include <linux/delay.h>
+#include <linux/amd-iommu.h>
+#include <asm/msidef.h>
#include <asm/proto.h>
#include <asm/iommu.h>
#include <asm/gart.h>
#include <asm/dma.h>
-#include <asm/amd_iommu_proto.h>
-#include <asm/amd_iommu_types.h>
-#include <asm/amd_iommu.h>
+
+#include "amd_iommu_proto.h"
+#include "amd_iommu_types.h"
#define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
@@ -45,6 +47,10 @@ static DEFINE_RWLOCK(amd_iommu_devtable_lock);
static LIST_HEAD(iommu_pd_list);
static DEFINE_SPINLOCK(iommu_pd_list_lock);
+/* List of all available dev_data structures */
+static LIST_HEAD(dev_data_list);
+static DEFINE_SPINLOCK(dev_data_list_lock);
+
/*
* Domain for untranslated devices - only allocated
* if iommu=pt passed on kernel cmd line.
@@ -68,6 +74,67 @@ static void update_domain(struct protection_domain *domain);
*
****************************************************************************/
+static struct iommu_dev_data *alloc_dev_data(u16 devid)
+{
+ struct iommu_dev_data *dev_data;
+ unsigned long flags;
+
+ dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
+ if (!dev_data)
+ return NULL;
+
+ dev_data->devid = devid;
+ atomic_set(&dev_data->bind, 0);
+
+ spin_lock_irqsave(&dev_data_list_lock, flags);
+ list_add_tail(&dev_data->dev_data_list, &dev_data_list);
+ spin_unlock_irqrestore(&dev_data_list_lock, flags);
+
+ return dev_data;
+}
+
+static void free_dev_data(struct iommu_dev_data *dev_data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev_data_list_lock, flags);
+ list_del(&dev_data->dev_data_list);
+ spin_unlock_irqrestore(&dev_data_list_lock, flags);
+
+ kfree(dev_data);
+}
+
+static struct iommu_dev_data *search_dev_data(u16 devid)
+{
+ struct iommu_dev_data *dev_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev_data_list_lock, flags);
+ list_for_each_entry(dev_data, &dev_data_list, dev_data_list) {
+ if (dev_data->devid == devid)
+ goto out_unlock;
+ }
+
+ dev_data = NULL;
+
+out_unlock:
+ spin_unlock_irqrestore(&dev_data_list_lock, flags);
+
+ return dev_data;
+}
+
+static struct iommu_dev_data *find_dev_data(u16 devid)
+{
+ struct iommu_dev_data *dev_data;
+
+ dev_data = search_dev_data(devid);
+
+ if (dev_data == NULL)
+ dev_data = alloc_dev_data(devid);
+
+ return dev_data;
+}
+
static inline u16 get_device_id(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -138,33 +205,31 @@ static bool check_device(struct device *dev)
static int iommu_init_device(struct device *dev)
{
struct iommu_dev_data *dev_data;
- struct pci_dev *pdev;
- u16 devid, alias;
+ u16 alias;
if (dev->archdata.iommu)
return 0;
- dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
+ dev_data = find_dev_data(get_device_id(dev));
if (!dev_data)
return -ENOMEM;
- dev_data->dev = dev;
+ alias = amd_iommu_alias_table[dev_data->devid];
+ if (alias != dev_data->devid) {
+ struct iommu_dev_data *alias_data;
- devid = get_device_id(dev);
- alias = amd_iommu_alias_table[devid];
- pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
- if (pdev)
- dev_data->alias = &pdev->dev;
- else {
- kfree(dev_data);
- return -ENOTSUPP;
+ alias_data = find_dev_data(alias);
+ if (alias_data == NULL) {
+ pr_err("AMD-Vi: Warning: Unhandled device %s\n",
+ dev_name(dev));
+ free_dev_data(dev_data);
+ return -ENOTSUPP;
+ }
+ dev_data->alias_data = alias_data;
}
- atomic_set(&dev_data->bind, 0);
-
dev->archdata.iommu = dev_data;
-
return 0;
}
@@ -184,11 +249,16 @@ static void iommu_ignore_device(struct device *dev)
static void iommu_uninit_device(struct device *dev)
{
- kfree(dev->archdata.iommu);
+ /*
+ * Nothing to do here - we keep dev_data around for unplugged devices
+ * and reuse it when the device is re-plugged - not doing so would
+ * introduce a ton of races.
+ */
}
void __init amd_iommu_uninit_devices(void)
{
+ struct iommu_dev_data *dev_data, *n;
struct pci_dev *pdev = NULL;
for_each_pci_dev(pdev) {
@@ -198,6 +268,10 @@ void __init amd_iommu_uninit_devices(void)
iommu_uninit_device(&pdev->dev);
}
+
+ /* Free all of our dev_data structures */
+ list_for_each_entry_safe(dev_data, n, &dev_data_list, dev_data_list)
+ free_dev_data(dev_data);
}
int __init amd_iommu_init_devices(void)
@@ -654,19 +728,17 @@ void iommu_flush_all_caches(struct amd_iommu *iommu)
/*
* Command send function for flushing on-device TLB
*/
-static int device_flush_iotlb(struct device *dev, u64 address, size_t size)
+static int device_flush_iotlb(struct iommu_dev_data *dev_data,
+ u64 address, size_t size)
{
- struct pci_dev *pdev = to_pci_dev(dev);
struct amd_iommu *iommu;
struct iommu_cmd cmd;
- u16 devid;
int qdep;
- qdep = pci_ats_queue_depth(pdev);
- devid = get_device_id(dev);
- iommu = amd_iommu_rlookup_table[devid];
+ qdep = dev_data->ats.qdep;
+ iommu = amd_iommu_rlookup_table[dev_data->devid];
- build_inv_iotlb_pages(&cmd, devid, qdep, address, size);
+ build_inv_iotlb_pages(&cmd, dev_data->devid, qdep, address, size);
return iommu_queue_command(iommu, &cmd);
}
@@ -674,23 +746,19 @@ static int device_flush_iotlb(struct device *dev, u64 address, size_t size)
/*
* Command send function for invalidating a device table entry
*/
-static int device_flush_dte(struct device *dev)
+static int device_flush_dte(struct iommu_dev_data *dev_data)
{
struct amd_iommu *iommu;
- struct pci_dev *pdev;
- u16 devid;
int ret;
- pdev = to_pci_dev(dev);
- devid = get_device_id(dev);
- iommu = amd_iommu_rlookup_table[devid];
+ iommu = amd_iommu_rlookup_table[dev_data->devid];
- ret = iommu_flush_dte(iommu, devid);
+ ret = iommu_flush_dte(iommu, dev_data->devid);
if (ret)
return ret;
- if (pci_ats_enabled(pdev))
- ret = device_flush_iotlb(dev, 0, ~0UL);
+ if (dev_data->ats.enabled)
+ ret = device_flush_iotlb(dev_data, 0, ~0UL);
return ret;
}
@@ -721,12 +789,11 @@ static void __domain_flush_pages(struct protection_domain *domain,
}
list_for_each_entry(dev_data, &domain->dev_list, list) {
- struct pci_dev *pdev = to_pci_dev(dev_data->dev);
- if (!pci_ats_enabled(pdev))
+ if (!dev_data->ats.enabled)
continue;
- ret |= device_flush_iotlb(dev_data->dev, address, size);
+ ret |= device_flush_iotlb(dev_data, address, size);
}
WARN_ON(ret);
@@ -778,7 +845,7 @@ static void domain_flush_devices(struct protection_domain *domain)
spin_lock_irqsave(&domain->lock, flags);
list_for_each_entry(dev_data, &domain->dev_list, list)
- device_flush_dte(dev_data->dev);
+ device_flush_dte(dev_data);
spin_unlock_irqrestore(&domain->lock, flags);
}
@@ -1136,7 +1203,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,
{
int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT;
struct amd_iommu *iommu;
- unsigned long i;
+ unsigned long i, old_size;
#ifdef CONFIG_IOMMU_STRESS
populate = false;
@@ -1172,8 +1239,21 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,
}
}
+ old_size = dma_dom->aperture_size;
dma_dom->aperture_size += APERTURE_RANGE_SIZE;
+ /* Reserve address range used for MSI messages */
+ if (old_size < MSI_ADDR_BASE_LO &&
+ dma_dom->aperture_size > MSI_ADDR_BASE_LO) {
+ unsigned long spage;
+ int pages;
+
+ pages = iommu_num_pages(MSI_ADDR_BASE_LO, 0x10000, PAGE_SIZE);
+ spage = MSI_ADDR_BASE_LO >> PAGE_SHIFT;
+
+ dma_ops_reserve_addresses(dma_dom, spage, pages);
+ }
+
/* Initialize the exclusion range if necessary */
for_each_iommu(iommu) {
if (iommu->exclusion_start &&
@@ -1526,44 +1606,33 @@ static void clear_dte_entry(u16 devid)
amd_iommu_apply_erratum_63(devid);
}
-static void do_attach(struct device *dev, struct protection_domain *domain)
+static void do_attach(struct iommu_dev_data *dev_data,
+ struct protection_domain *domain)
{
- struct iommu_dev_data *dev_data;
struct amd_iommu *iommu;
- struct pci_dev *pdev;
- bool ats = false;
- u16 devid;
+ bool ats;
- devid = get_device_id(dev);
- iommu = amd_iommu_rlookup_table[devid];
- dev_data = get_dev_data(dev);
- pdev = to_pci_dev(dev);
-
- if (amd_iommu_iotlb_sup)
- ats = pci_ats_enabled(pdev);
+ iommu = amd_iommu_rlookup_table[dev_data->devid];
+ ats = dev_data->ats.enabled;
/* Update data structures */
dev_data->domain = domain;
list_add(&dev_data->list, &domain->dev_list);
- set_dte_entry(devid, domain, ats);
+ set_dte_entry(dev_data->devid, domain, ats);
/* Do reference counting */
domain->dev_iommu[iommu->index] += 1;
domain->dev_cnt += 1;
/* Flush the DTE entry */
- device_flush_dte(dev);
+ device_flush_dte(dev_data);
}
-static void do_detach(struct device *dev)
+static void do_detach(struct iommu_dev_data *dev_data)
{
- struct iommu_dev_data *dev_data;
struct amd_iommu *iommu;
- u16 devid;
- devid = get_device_id(dev);
- iommu = amd_iommu_rlookup_table[devid];
- dev_data = get_dev_data(dev);
+ iommu = amd_iommu_rlookup_table[dev_data->devid];
/* decrease reference counters */
dev_data->domain->dev_iommu[iommu->index] -= 1;
@@ -1572,52 +1641,46 @@ static void do_detach(struct device *dev)
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
- clear_dte_entry(devid);
+ clear_dte_entry(dev_data->devid);
/* Flush the DTE entry */
- device_flush_dte(dev);
+ device_flush_dte(dev_data);
}
/*
* If a device is not yet associated with a domain, this function does
* assigns it visible for the hardware
*/
-static int __attach_device(struct device *dev,
+static int __attach_device(struct iommu_dev_data *dev_data,
struct protection_domain *domain)
{
- struct iommu_dev_data *dev_data, *alias_data;
int ret;
- dev_data = get_dev_data(dev);
- alias_data = get_dev_data(dev_data->alias);
-
- if (!alias_data)
- return -EINVAL;
-
/* lock domain */
spin_lock(&domain->lock);
- /* Some sanity checks */
- ret = -EBUSY;
- if (alias_data->domain != NULL &&
- alias_data->domain != domain)
- goto out_unlock;
+ if (dev_data->alias_data != NULL) {
+ struct iommu_dev_data *alias_data = dev_data->alias_data;
- if (dev_data->domain != NULL &&
- dev_data->domain != domain)
- goto out_unlock;
+ /* Some sanity checks */
+ ret = -EBUSY;
+ if (alias_data->domain != NULL &&
+ alias_data->domain != domain)
+ goto out_unlock;
- /* Do real assignment */
- if (dev_data->alias != dev) {
- alias_data = get_dev_data(dev_data->alias);
+ if (dev_data->domain != NULL &&
+ dev_data->domain != domain)
+ goto out_unlock;
+
+ /* Do real assignment */
if (alias_data->domain == NULL)
- do_attach(dev_data->alias, domain);
+ do_attach(alias_data, domain);
atomic_inc(&alias_data->bind);
}
if (dev_data->domain == NULL)
- do_attach(dev, domain);
+ do_attach(dev_data, domain);
atomic_inc(&dev_data->bind);
@@ -1639,14 +1702,19 @@ static int attach_device(struct device *dev,
struct protection_domain *domain)
{
struct pci_dev *pdev = to_pci_dev(dev);
+ struct iommu_dev_data *dev_data;
unsigned long flags;
int ret;
- if (amd_iommu_iotlb_sup)
- pci_enable_ats(pdev, PAGE_SHIFT);
+ dev_data = get_dev_data(dev);
+
+ if (amd_iommu_iotlb_sup && pci_enable_ats(pdev, PAGE_SHIFT) == 0) {
+ dev_data->ats.enabled = true;
+ dev_data->ats.qdep = pci_ats_queue_depth(pdev);
+ }
write_lock_irqsave(&amd_iommu_devtable_lock, flags);
- ret = __attach_device(dev, domain);
+ ret = __attach_device(dev_data, domain);
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
/*
@@ -1662,10 +1730,8 @@ static int attach_device(struct device *dev,
/*
* Removes a device from a protection domain (unlocked)
*/
-static void __detach_device(struct device *dev)
+static void __detach_device(struct iommu_dev_data *dev_data)
{
- struct iommu_dev_data *dev_data = get_dev_data(dev);
- struct iommu_dev_data *alias_data;
struct protection_domain *domain;
unsigned long flags;
@@ -1675,14 +1741,15 @@ static void __detach_device(struct device *dev)
spin_lock_irqsave(&domain->lock, flags);
- if (dev_data->alias != dev) {
- alias_data = get_dev_data(dev_data->alias);
+ if (dev_data->alias_data != NULL) {
+ struct iommu_dev_data *alias_data = dev_data->alias_data;
+
if (atomic_dec_and_test(&alias_data->bind))
- do_detach(dev_data->alias);
+ do_detach(alias_data);
}
if (atomic_dec_and_test(&dev_data->bind))
- do_detach(dev);
+ do_detach(dev_data);
spin_unlock_irqrestore(&domain->lock, flags);
@@ -1693,7 +1760,7 @@ static void __detach_device(struct device *dev)
*/
if (iommu_pass_through &&
(dev_data->domain == NULL && domain != pt_domain))
- __attach_device(dev, pt_domain);
+ __attach_device(dev_data, pt_domain);
}
/*
@@ -1701,16 +1768,20 @@ static void __detach_device(struct device *dev)
*/
static void detach_device(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
+ struct iommu_dev_data *dev_data;
unsigned long flags;
+ dev_data = get_dev_data(dev);
+
/* lock device table */
write_lock_irqsave(&amd_iommu_devtable_lock, flags);
- __detach_device(dev);
+ __detach_device(dev_data);
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
- if (amd_iommu_iotlb_sup && pci_ats_enabled(pdev))
- pci_disable_ats(pdev);
+ if (dev_data->ats.enabled) {
+ pci_disable_ats(to_pci_dev(dev));
+ dev_data->ats.enabled = false;
+ }
}
/*
@@ -1719,26 +1790,25 @@ static void detach_device(struct device *dev)
*/
static struct protection_domain *domain_for_device(struct device *dev)
{
- struct protection_domain *dom;
- struct iommu_dev_data *dev_data, *alias_data;
+ struct iommu_dev_data *dev_data;
+ struct protection_domain *dom = NULL;
unsigned long flags;
- u16 devid;
- devid = get_device_id(dev);
dev_data = get_dev_data(dev);
- alias_data = get_dev_data(dev_data->alias);
- if (!alias_data)
- return NULL;
- read_lock_irqsave(&amd_iommu_devtable_lock, flags);
- dom = dev_data->domain;
- if (dom == NULL &&
- alias_data->domain != NULL) {
- __attach_device(dev, alias_data->domain);
- dom = alias_data->domain;
- }
+ if (dev_data->domain)
+ return dev_data->domain;
+
+ if (dev_data->alias_data != NULL) {
+ struct iommu_dev_data *alias_data = dev_data->alias_data;
- read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ read_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ if (alias_data->domain != NULL) {
+ __attach_device(dev_data, alias_data->domain);
+ dom = alias_data->domain;
+ }
+ read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ }
return dom;
}
@@ -1798,7 +1868,6 @@ static int device_change_notifier(struct notifier_block *nb,
goto out;
}
- device_flush_dte(dev);
iommu_completion_wait(iommu);
out:
@@ -1858,11 +1927,8 @@ static void update_device_table(struct protection_domain *domain)
{
struct iommu_dev_data *dev_data;
- list_for_each_entry(dev_data, &domain->dev_list, list) {
- struct pci_dev *pdev = to_pci_dev(dev_data->dev);
- u16 devid = get_device_id(dev_data->dev);
- set_dte_entry(devid, domain, pci_ats_enabled(pdev));
- }
+ list_for_each_entry(dev_data, &domain->dev_list, list)
+ set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
}
static void update_domain(struct protection_domain *domain)
@@ -2497,9 +2563,7 @@ static void cleanup_domain(struct protection_domain *domain)
write_lock_irqsave(&amd_iommu_devtable_lock, flags);
list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {
- struct device *dev = dev_data->dev;
-
- __detach_device(dev);
+ __detach_device(dev_data);
atomic_set(&dev_data->bind, 0);
}
@@ -2605,7 +2669,6 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
if (!iommu)
return;
- device_flush_dte(dev);
iommu_completion_wait(iommu);
}
@@ -2616,16 +2679,13 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
struct iommu_dev_data *dev_data;
struct amd_iommu *iommu;
int ret;
- u16 devid;
if (!check_device(dev))
return -EINVAL;
dev_data = dev->archdata.iommu;
- devid = get_device_id(dev);
-
- iommu = amd_iommu_rlookup_table[devid];
+ iommu = amd_iommu_rlookup_table[dev_data->devid];
if (!iommu)
return -EINVAL;
diff --git a/arch/x86/kernel/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index bfc8453bd98d..82d2410f4205 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -24,14 +24,16 @@
#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/msi.h>
+#include <linux/amd-iommu.h>
#include <asm/pci-direct.h>
-#include <asm/amd_iommu_proto.h>
-#include <asm/amd_iommu_types.h>
-#include <asm/amd_iommu.h>
#include <asm/iommu.h>
#include <asm/gart.h>
#include <asm/x86_init.h>
#include <asm/iommu_table.h>
+
+#include "amd_iommu_proto.h"
+#include "amd_iommu_types.h"
+
/*
* definitions for the ACPI scanning code
*/
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 55d95eb789b3..7ffaa64410b0 100644
--- a/arch/x86/include/asm/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -19,7 +19,7 @@
#ifndef _ASM_X86_AMD_IOMMU_PROTO_H
#define _ASM_X86_AMD_IOMMU_PROTO_H
-#include <asm/amd_iommu_types.h>
+#include "amd_iommu_types.h"
extern int amd_iommu_init_dma_ops(void);
extern int amd_iommu_init_passthrough(void);
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 4c9982995414..5b9c5075e81a 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -310,10 +310,15 @@ struct protection_domain {
*/
struct iommu_dev_data {
struct list_head list; /* For domain->dev_list */
- struct device *dev; /* Device this data belong to */
- struct device *alias; /* The Alias Device */
+ struct list_head dev_data_list; /* For global dev_data_list */
+ struct iommu_dev_data *alias_data;/* The alias dev_data */
struct protection_domain *domain; /* Domain the device is bound to */
atomic_t bind; /* Domain attach reverent count */
+ u16 devid; /* PCI Device ID */
+ struct {
+ bool enabled;
+ int qdep;
+ } ats; /* ATS state */
};
/*
diff --git a/drivers/pci/dmar.c b/drivers/iommu/dmar.c
index 3dc9befa5aec..3dc9befa5aec 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/iommu/dmar.c
diff --git a/drivers/pci/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f02c34d26d1b..c621c98c99da 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -42,7 +42,6 @@
#include <linux/pci-ats.h>
#include <asm/cacheflush.h>
#include <asm/iommu.h>
-#include "pci.h"
#define ROOT_SIZE VTD_PAGE_SIZE
#define CONTEXT_SIZE VTD_PAGE_SIZE
diff --git a/drivers/pci/intr_remapping.c b/drivers/iommu/intr_remapping.c
index 3607faf28a4d..1a89d4a2cadf 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/iommu/intr_remapping.c
@@ -13,7 +13,6 @@
#include "intr_remapping.h"
#include <acpi/acpi.h>
#include <asm/pci-direct.h>
-#include "pci.h"
static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
static struct hpet_scope ir_hpet[MAX_HPET_TBS];
diff --git a/drivers/pci/intr_remapping.h b/drivers/iommu/intr_remapping.h
index 5662fecfee60..5662fecfee60 100644
--- a/drivers/pci/intr_remapping.h
+++ b/drivers/iommu/intr_remapping.h
diff --git a/drivers/base/iommu.c b/drivers/iommu/iommu.c
index 6e6b6a11b3ce..6e6b6a11b3ce 100644
--- a/drivers/base/iommu.c
+++ b/drivers/iommu/iommu.c
diff --git a/drivers/pci/iova.c b/drivers/iommu/iova.c
index c5c274ab5c5a..c5c274ab5c5a 100644
--- a/drivers/pci/iova.c
+++ b/drivers/iommu/iova.c
diff --git a/arch/arm/mach-msm/iommu.c b/drivers/iommu/msm_iommu.c
index 1a584e077c61..1a584e077c61 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/drivers/iommu/msm_iommu.c
diff --git a/arch/arm/mach-msm/iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 8e8fb079852d..8e8fb079852d 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 6dd360734cfd..212efaf9a4e4 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -34,7 +34,7 @@
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/list.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define GIG_VERSION {0, 5, 0, 0}
#define GIG_COMPAT {0, 4, 0, 0}
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 472a2af79446..861b6511f3ee 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index f6f3c87cc7c2..a440d7fff0ad 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -152,6 +152,7 @@
#define HFC_MULTI_VERSION "2.03"
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index b01a7be1300f..3261de18a91e 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -44,6 +44,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
index bc0529ac88a1..6218775ce87d 100644
--- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
@@ -38,6 +38,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 64ecc6f5ffaf..d2ffb1d9b831 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/irqreturn.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mISDNhw.h>
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index db25b6b2ae39..5ef9f11ee74b 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c
index 9e07246bb9e7..4d0d41ea1228 100644
--- a/drivers/isdn/hardware/mISDN/speedfax.c
+++ b/drivers/isdn/hardware/mISDN/speedfax.c
@@ -22,6 +22,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 9e84870b971c..e10e0284533c 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index de1c669c7b13..0a5c42a3f125 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/wait.h>
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index 8b0a7d86b30f..478ebab54ca4 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/kmod.h>
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index 02d9918705dd..aa0b6a6f5ef4 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -155,7 +155,7 @@ struct bsd_db {
#define LAST 255
#define MAXCODE(b) ((1 << (b)) - 1)
-#define BADCODEM1 MAXCODE(MAX_BSD_BITS);
+#define BADCODEM1 MAXCODE(MAX_BSD_BITS)
#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
^ (unsigned long)(prefix))
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 97988111e45a..48e9cc0369b1 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1983,13 +1983,14 @@ isdn_net_rebuild_header(struct sk_buff *skb)
return ret;
}
-static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
+static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
+ __be16 type)
{
const struct net_device *dev = neigh->dev;
isdn_net_local *lp = netdev_priv(dev);
if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
- return eth_header_cache(neigh, hh);
+ return eth_header_cache(neigh, hh, type);
return -1;
}
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 713d43b4e563..b591e726a6fa 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -92,7 +92,7 @@ config LEDS_NET48XX
config LEDS_NET5501
tristate "LED Support for Soekris net5501 series Error LED"
depends on LEDS_TRIGGERS
- depends on X86 && LEDS_GPIO_PLATFORM && GPIO_CS5535
+ depends on X86 && GPIO_CS5535
select LEDS_TRIGGER_DEFAULT_ON
default n
help
@@ -182,23 +182,6 @@ config LEDS_GPIO
defined as platform devices and/or OpenFirmware platform devices.
The code to use these bindings can be selected below.
-config LEDS_GPIO_PLATFORM
- bool "Platform device bindings for GPIO LEDs"
- depends on LEDS_GPIO
- default y
- help
- Let the leds-gpio driver drive LEDs which have been defined as
- platform devices. If you don't know what this means, say yes.
-
-config LEDS_GPIO_OF
- bool "OpenFirmware platform device bindings for GPIO LEDs"
- depends on LEDS_GPIO && OF_DEVICE
- default y
- help
- Let the leds-gpio driver drive LEDs which have been defined as
- of_platform devices. For instance, LEDs which are listed in a "dts"
- file.
-
config LEDS_LP3944
tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
depends on LEDS_CLASS
@@ -382,6 +365,7 @@ config LEDS_NS2
config LEDS_NETXBIG
tristate "LED support for Big Network series LEDs"
depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2
+ depends on LEDS_CLASS
default y
help
This option enable support for LEDs found on the LaCie 2Big
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index b0480c8fbcbf..3d8bc327a68d 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -165,7 +165,7 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
}
/* Code to create from OpenFirmware platform devices */
-#ifdef CONFIG_LEDS_GPIO_OF
+#ifdef CONFIG_OF_GPIO
static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node, *child;
@@ -223,13 +223,13 @@ static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", },
{},
};
-#else
+#else /* CONFIG_OF_GPIO */
static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
{
return NULL;
}
#define of_gpio_leds_match NULL
-#endif
+#endif /* CONFIG_OF_GPIO */
static int __devinit gpio_led_probe(struct platform_device *pdev)
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 4d7ce7631acf..3dd7090a9a9b 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -68,17 +68,16 @@
#define LM3530_ALS2_IMP_SHIFT (4)
/* Zone Boundary Register defaults */
-#define LM3530_DEF_ZB_0 (0x33)
-#define LM3530_DEF_ZB_1 (0x66)
-#define LM3530_DEF_ZB_2 (0x99)
-#define LM3530_DEF_ZB_3 (0xCC)
+#define LM3530_ALS_ZB_MAX (4)
+#define LM3530_ALS_WINDOW_mV (1000)
+#define LM3530_ALS_OFFSET_mV (4)
/* Zone Target Register defaults */
-#define LM3530_DEF_ZT_0 (0x19)
-#define LM3530_DEF_ZT_1 (0x33)
+#define LM3530_DEF_ZT_0 (0x7F)
+#define LM3530_DEF_ZT_1 (0x66)
#define LM3530_DEF_ZT_2 (0x4C)
-#define LM3530_DEF_ZT_3 (0x66)
-#define LM3530_DEF_ZT_4 (0x7F)
+#define LM3530_DEF_ZT_3 (0x33)
+#define LM3530_DEF_ZT_4 (0x19)
struct lm3530_mode_map {
const char *mode;
@@ -150,6 +149,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
u8 als_imp_sel = 0;
u8 brightness;
u8 reg_val[LM3530_REG_MAX];
+ u8 zones[LM3530_ALS_ZB_MAX];
+ u32 als_vmin, als_vmax, als_vstep;
struct lm3530_platform_data *pltfm = drvdata->pdata;
struct i2c_client *client = drvdata->client;
@@ -161,6 +162,26 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
gen_config |= (LM3530_ENABLE_I2C);
if (drvdata->mode == LM3530_BL_MODE_ALS) {
+ if (pltfm->als_vmax == 0) {
+ pltfm->als_vmin = als_vmin = 0;
+ pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV;
+ }
+
+ als_vmin = pltfm->als_vmin;
+ als_vmax = pltfm->als_vmax;
+
+ if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV)
+ pltfm->als_vmax = als_vmax =
+ als_vmin + LM3530_ALS_WINDOW_mV;
+
+ /* n zone boundary makes n+1 zones */
+ als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1);
+
+ for (i = 0; i < LM3530_ALS_ZB_MAX; i++)
+ zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) +
+ als_vstep + (i * als_vstep)) * LED_FULL)
+ / 1000;
+
als_config =
(pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
(LM3530_ENABLE_ALS) |
@@ -169,6 +190,7 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
als_imp_sel =
(pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
(pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
+
}
if (drvdata->mode == LM3530_BL_MODE_PWM)
@@ -190,10 +212,10 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
reg_val[3] = 0x00; /* LM3530_ALS_ZONE_REG */
reg_val[4] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */
reg_val[5] = brightness; /* LM3530_BRT_CTRL_REG */
- reg_val[6] = LM3530_DEF_ZB_0; /* LM3530_ALS_ZB0_REG */
- reg_val[7] = LM3530_DEF_ZB_1; /* LM3530_ALS_ZB1_REG */
- reg_val[8] = LM3530_DEF_ZB_2; /* LM3530_ALS_ZB2_REG */
- reg_val[9] = LM3530_DEF_ZB_3; /* LM3530_ALS_ZB3_REG */
+ reg_val[6] = zones[0]; /* LM3530_ALS_ZB0_REG */
+ reg_val[7] = zones[1]; /* LM3530_ALS_ZB1_REG */
+ reg_val[8] = zones[2]; /* LM3530_ALS_ZB2_REG */
+ reg_val[9] = zones[3]; /* LM3530_ALS_ZB3_REG */
reg_val[10] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */
reg_val[11] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */
reg_val[12] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */
@@ -265,6 +287,24 @@ static void lm3530_brightness_set(struct led_classdev *led_cdev,
}
}
+static ssize_t lm3530_mode_get(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = container_of(
+ dev->parent, struct i2c_client, dev);
+ struct lm3530_data *drvdata = i2c_get_clientdata(client);
+ int i, len = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mode_map); i++)
+ if (drvdata->mode == mode_map[i].mode_val)
+ len += sprintf(buf + len, "[%s] ", mode_map[i].mode);
+ else
+ len += sprintf(buf + len, "%s ", mode_map[i].mode);
+
+ len += sprintf(buf + len, "\n");
+
+ return len;
+}
static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
*attr, const char *buf, size_t size)
@@ -298,8 +338,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
return sizeof(drvdata->mode);
}
-
-static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set);
+static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
static int __devinit lm3530_probe(struct i2c_client *client,
const struct i2c_device_id *id)
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index cc1dc4817fac..9fc122c81f06 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -744,7 +744,7 @@ fail1:
return ret;
}
-static int lp5521_remove(struct i2c_client *client)
+static int __devexit lp5521_remove(struct i2c_client *client)
{
struct lp5521_chip *chip = i2c_get_clientdata(client);
int i;
@@ -775,7 +775,7 @@ static struct i2c_driver lp5521_driver = {
.name = "lp5521",
},
.probe = lp5521_probe,
- .remove = lp5521_remove,
+ .remove = __devexit_p(lp5521_remove),
.id_table = lp5521_id,
};
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
index ab6d18f5c39f..1757396b20b3 100644
--- a/drivers/leds/leds-sunfire.c
+++ b/drivers/leds/leds-sunfire.c
@@ -127,17 +127,19 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
struct led_type *types)
{
struct sunfire_drvdata *p;
- int i, err = -EINVAL;
+ int i, err;
if (pdev->num_resources != 1) {
printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n",
pdev->num_resources);
+ err = -EINVAL;
goto out;
}
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p) {
printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n");
+ err = -ENOMEM;
goto out;
}
@@ -160,14 +162,14 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
dev_set_drvdata(&pdev->dev, p);
- err = 0;
-out:
- return err;
+ return 0;
out_unregister_led_cdevs:
for (i--; i >= 0; i--)
led_classdev_unregister(&p->leds[i].led_cdev);
- goto out;
+ kfree(p);
+out:
+ return err;
}
static int __devexit sunfire_led_generic_remove(struct platform_device *pdev)
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index efa202499e37..2535933c49f8 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -117,7 +117,7 @@ static __init int map_switcher(void)
/*
* Now the Switcher is mapped at the right address, we can't fail!
- * Copy in the compiled-in Switcher code (from <arch>_switcher.S).
+ * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
*/
memcpy(switcher_vma->addr, start_switcher_text,
end_switcher_text - start_switcher_text);
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index daaf86631647..28433a155d67 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -375,11 +375,9 @@ static bool direct_trap(unsigned int num)
/*
* The Host needs to see page faults (for shadow paging and to save the
* fault address), general protection faults (in/out emulation) and
- * device not available (TS handling), invalid opcode fault (kvm hcall),
- * and of course, the hypercall trap.
+ * device not available (TS handling) and of course, the hypercall trap.
*/
- return num != 14 && num != 13 && num != 7 &&
- num != 6 && num != LGUEST_TRAP_ENTRY;
+ return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
}
/*:*/
@@ -429,8 +427,8 @@ void pin_stack_pages(struct lg_cpu *cpu)
/*
* Direct traps also mean that we need to know whenever the Guest wants to use
- * a different kernel stack, so we can change the IDT entries to use that
- * stack. The IDT entries expect a virtual address, so unlike most addresses
+ * a different kernel stack, so we can change the guest TSS to use that
+ * stack. The TSS entries expect a virtual address, so unlike most addresses
* the Guest gives us, the "esp" (stack pointer) value here is virtual, not
* physical.
*
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 9136411fadd5..295df06e6590 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -59,6 +59,8 @@ struct lg_cpu {
struct lguest_pages *last_pages;
+ /* Initialization mode: linear map everything. */
+ bool linear_pages;
int cpu_pgd; /* Which pgd this cpu is currently using */
/* If a hypercall was asked for, this points to the arguments. */
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 69c84a1d88ea..5289ffa2e500 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -109,6 +109,17 @@ static u32 lg_get_features(struct virtio_device *vdev)
}
/*
+ * To notify on reset or feature finalization, we (ab)use the NOTIFY
+ * hypercall, with the descriptor address of the device.
+ */
+static void status_notify(struct virtio_device *vdev)
+{
+ unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
+
+ hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
+}
+
+/*
* The virtio core takes the features the Host offers, and copies the ones
* supported by the driver into the vdev->features array. Once that's all
* sorted out, this routine is called so we can tell the Host which features we
@@ -135,6 +146,9 @@ static void lg_finalize_features(struct virtio_device *vdev)
if (test_bit(i, vdev->features))
out_features[i / 8] |= (1 << (i % 8));
}
+
+ /* Tell Host we've finished with this device's feature negotiation */
+ status_notify(vdev);
}
/* Once they've found a field, getting a copy of it is easy. */
@@ -168,28 +182,21 @@ static u8 lg_get_status(struct virtio_device *vdev)
return to_lgdev(vdev)->desc->status;
}
-/*
- * To notify on status updates, we (ab)use the NOTIFY hypercall, with the
- * descriptor address of the device. A zero status means "reset".
- */
-static void set_status(struct virtio_device *vdev, u8 status)
-{
- unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
-
- /* We set the status. */
- to_lgdev(vdev)->desc->status = status;
- hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
-}
-
static void lg_set_status(struct virtio_device *vdev, u8 status)
{
BUG_ON(!status);
- set_status(vdev, status);
+ to_lgdev(vdev)->desc->status = status;
+
+ /* Tell Host immediately if we failed. */
+ if (status & VIRTIO_CONFIG_S_FAILED)
+ status_notify(vdev);
}
static void lg_reset(struct virtio_device *vdev)
{
- set_status(vdev, 0);
+ /* 0 status means "reset" */
+ to_lgdev(vdev)->desc->status = 0;
+ status_notify(vdev);
}
/*
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 948c547b8e9e..f97e625241ad 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -1,8 +1,10 @@
-/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
- * controls and communicates with the Guest. For example, the first write will
- * tell us the Guest's memory layout and entry point. A read will run the
- * Guest until something happens, such as a signal or the Guest doing a NOTIFY
- * out to the Launcher.
+/*P:200 This contains all the /dev/lguest code, whereby the userspace
+ * launcher controls and communicates with the Guest. For example,
+ * the first write will tell us the Guest's memory layout and entry
+ * point. A read will run the Guest until something happens, such as
+ * a signal or the Guest doing a NOTIFY out to the Launcher. There is
+ * also a way for the Launcher to attach eventfds to particular NOTIFY
+ * values instead of returning from the read() call.
:*/
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
@@ -357,8 +359,8 @@ static int initialize(struct file *file, const unsigned long __user *input)
goto free_eventfds;
/*
- * Initialize the Guest's shadow page tables, using the toplevel
- * address the Launcher gave us. This allocates memory, so can fail.
+ * Initialize the Guest's shadow page tables. This allocates
+ * memory, so can fail.
*/
err = init_guest_pagetable(lg);
if (err)
@@ -516,6 +518,7 @@ static const struct file_operations lguest_fops = {
.read = read,
.llseek = default_llseek,
};
+/*:*/
/*
* This is a textbook example of a "misc" character device. Populate a "struct
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index d21578ee95de..3b62be160a6e 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -17,7 +17,6 @@
#include <linux/percpu.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
-#include <asm/bootparam.h>
#include "lg.h"
/*M:008
@@ -156,7 +155,7 @@ static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
}
/*
- * These functions are just like the above two, except they access the Guest
+ * These functions are just like the above, except they access the Guest
* page tables. Hence they return a Guest address.
*/
static unsigned long gpgd_addr(struct lg_cpu *cpu, unsigned long vaddr)
@@ -196,7 +195,7 @@ static unsigned long gpte_addr(struct lg_cpu *cpu,
#endif
/*:*/
-/*M:014
+/*M:007
* get_pfn is slow: we could probably try to grab batches of pages here as
* an optimization (ie. pre-faulting).
:*/
@@ -325,10 +324,15 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
#endif
/* First step: get the top-level Guest page table entry. */
- gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
- /* Toplevel not present? We can't map it in. */
- if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
- return false;
+ if (unlikely(cpu->linear_pages)) {
+ /* Faking up a linear mapping. */
+ gpgd = __pgd(CHECK_GPGD_MASK);
+ } else {
+ gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
+ /* Toplevel not present? We can't map it in. */
+ if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
+ return false;
+ }
/* Now look at the matching shadow entry. */
spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
@@ -353,10 +357,15 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
}
#ifdef CONFIG_X86_PAE
- gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
- /* Middle level not present? We can't map it in. */
- if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
- return false;
+ if (unlikely(cpu->linear_pages)) {
+ /* Faking up a linear mapping. */
+ gpmd = __pmd(_PAGE_TABLE);
+ } else {
+ gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
+ /* Middle level not present? We can't map it in. */
+ if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
+ return false;
+ }
/* Now look at the matching shadow entry. */
spmd = spmd_addr(cpu, *spgd, vaddr);
@@ -397,8 +406,13 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
gpte_ptr = gpte_addr(cpu, gpgd, vaddr);
#endif
- /* Read the actual PTE value. */
- gpte = lgread(cpu, gpte_ptr, pte_t);
+ if (unlikely(cpu->linear_pages)) {
+ /* Linear? Make up a PTE which points to same page. */
+ gpte = __pte((vaddr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT);
+ } else {
+ /* Read the actual PTE value. */
+ gpte = lgread(cpu, gpte_ptr, pte_t);
+ }
/* If this page isn't in the Guest page tables, we can't page it in. */
if (!(pte_flags(gpte) & _PAGE_PRESENT))
@@ -454,7 +468,8 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
* Finally, we write the Guest PTE entry back: we've set the
* _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags.
*/
- lgwrite(cpu, gpte_ptr, pte_t, gpte);
+ if (likely(!cpu->linear_pages))
+ lgwrite(cpu, gpte_ptr, pte_t, gpte);
/*
* The fault is fixed, the page table is populated, the mapping
@@ -612,6 +627,11 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr)
#ifdef CONFIG_X86_PAE
pmd_t gpmd;
#endif
+
+ /* Still not set up? Just map 1:1. */
+ if (unlikely(cpu->linear_pages))
+ return vaddr;
+
/* First step: get the top-level Guest page table entry. */
gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
/* Toplevel not present? We can't map it in. */
@@ -708,32 +728,6 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
return next;
}
-/*H:430
- * (iv) Switching page tables
- *
- * Now we've seen all the page table setting and manipulation, let's see
- * what happens when the Guest changes page tables (ie. changes the top-level
- * pgdir). This occurs on almost every context switch.
- */
-void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
-{
- int newpgdir, repin = 0;
-
- /* Look to see if we have this one already. */
- newpgdir = find_pgdir(cpu->lg, pgtable);
- /*
- * If not, we allocate or mug an existing one: if it's a fresh one,
- * repin gets set to 1.
- */
- if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
- newpgdir = new_pgdir(cpu, pgtable, &repin);
- /* Change the current pgd index to the new one. */
- cpu->cpu_pgd = newpgdir;
- /* If it was completely blank, we map in the Guest kernel stack */
- if (repin)
- pin_stack_pages(cpu);
-}
-
/*H:470
* Finally, a routine which throws away everything: all PGD entries in all
* the shadow page tables, including the Guest's kernel mappings. This is used
@@ -780,6 +774,44 @@ void guest_pagetable_clear_all(struct lg_cpu *cpu)
/* We need the Guest kernel stack mapped again. */
pin_stack_pages(cpu);
}
+
+/*H:430
+ * (iv) Switching page tables
+ *
+ * Now we've seen all the page table setting and manipulation, let's see
+ * what happens when the Guest changes page tables (ie. changes the top-level
+ * pgdir). This occurs on almost every context switch.
+ */
+void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
+{
+ int newpgdir, repin = 0;
+
+ /*
+ * The very first time they call this, we're actually running without
+ * any page tables; we've been making it up. Throw them away now.
+ */
+ if (unlikely(cpu->linear_pages)) {
+ release_all_pagetables(cpu->lg);
+ cpu->linear_pages = false;
+ /* Force allocation of a new pgdir. */
+ newpgdir = ARRAY_SIZE(cpu->lg->pgdirs);
+ } else {
+ /* Look to see if we have this one already. */
+ newpgdir = find_pgdir(cpu->lg, pgtable);
+ }
+
+ /*
+ * If not, we allocate or mug an existing one: if it's a fresh one,
+ * repin gets set to 1.
+ */
+ if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
+ newpgdir = new_pgdir(cpu, pgtable, &repin);
+ /* Change the current pgd index to the new one. */
+ cpu->cpu_pgd = newpgdir;
+ /* If it was completely blank, we map in the Guest kernel stack */
+ if (repin)
+ pin_stack_pages(cpu);
+}
/*:*/
/*M:009
@@ -919,168 +951,26 @@ void guest_set_pmd(struct lguest *lg, unsigned long pmdp, u32 idx)
}
#endif
-/*H:505
- * To get through boot, we construct simple identity page mappings (which
- * set virtual == physical) and linear mappings which will get the Guest far
- * enough into the boot to create its own. The linear mapping means we
- * simplify the Guest boot, but it makes assumptions about their PAGE_OFFSET,
- * as you'll see.
- *
- * We lay them out of the way, just below the initrd (which is why we need to
- * know its size here).
- */
-static unsigned long setup_pagetables(struct lguest *lg,
- unsigned long mem,
- unsigned long initrd_size)
-{
- pgd_t __user *pgdir;
- pte_t __user *linear;
- unsigned long mem_base = (unsigned long)lg->mem_base;
- unsigned int mapped_pages, i, linear_pages;
-#ifdef CONFIG_X86_PAE
- pmd_t __user *pmds;
- unsigned int j;
- pgd_t pgd;
- pmd_t pmd;
-#else
- unsigned int phys_linear;
-#endif
-
- /*
- * We have mapped_pages frames to map, so we need linear_pages page
- * tables to map them.
- */
- mapped_pages = mem / PAGE_SIZE;
- linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE;
-
- /* We put the toplevel page directory page at the top of memory. */
- pgdir = (pgd_t *)(mem + mem_base - initrd_size - PAGE_SIZE);
-
- /* Now we use the next linear_pages pages as pte pages */
- linear = (void *)pgdir - linear_pages * PAGE_SIZE;
-
-#ifdef CONFIG_X86_PAE
- /*
- * And the single mid page goes below that. We only use one, but
- * that's enough to map 1G, which definitely gets us through boot.
- */
- pmds = (void *)linear - PAGE_SIZE;
-#endif
- /*
- * Linear mapping is easy: put every page's address into the
- * mapping in order.
- */
- for (i = 0; i < mapped_pages; i++) {
- pte_t pte;
- pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER));
- if (copy_to_user(&linear[i], &pte, sizeof(pte)) != 0)
- return -EFAULT;
- }
-
-#ifdef CONFIG_X86_PAE
- /*
- * Make the Guest PMD entries point to the corresponding place in the
- * linear mapping (up to one page worth of PMD).
- */
- for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD;
- i += PTRS_PER_PTE, j++) {
- pmd = pfn_pmd(((unsigned long)&linear[i] - mem_base)/PAGE_SIZE,
- __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
-
- if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0)
- return -EFAULT;
- }
-
- /* One PGD entry, pointing to that PMD page. */
- pgd = __pgd(((unsigned long)pmds - mem_base) | _PAGE_PRESENT);
- /* Copy it in as the first PGD entry (ie. addresses 0-1G). */
- if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0)
- return -EFAULT;
- /*
- * And the other PGD entry to make the linear mapping at PAGE_OFFSET
- */
- if (copy_to_user(&pgdir[KERNEL_PGD_BOUNDARY], &pgd, sizeof(pgd)))
- return -EFAULT;
-#else
- /*
- * The top level points to the linear page table pages above.
- * We setup the identity and linear mappings here.
- */
- phys_linear = (unsigned long)linear - mem_base;
- for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) {
- pgd_t pgd;
- /*
- * Create a PGD entry which points to the right part of the
- * linear PTE pages.
- */
- pgd = __pgd((phys_linear + i * sizeof(pte_t)) |
- (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
-
- /*
- * Copy it into the PGD page at 0 and PAGE_OFFSET.
- */
- if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd))
- || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET)
- + i / PTRS_PER_PTE],
- &pgd, sizeof(pgd)))
- return -EFAULT;
- }
-#endif
-
- /*
- * We return the top level (guest-physical) address: we remember where
- * this is to write it into lguest_data when the Guest initializes.
- */
- return (unsigned long)pgdir - mem_base;
-}
-
/*H:500
* (vii) Setting up the page tables initially.
*
- * When a Guest is first created, the Launcher tells us where the toplevel of
- * its first page table is. We set some things up here:
+ * When a Guest is first created, set initialize a shadow page table which
+ * we will populate on future faults. The Guest doesn't have any actual
+ * pagetables yet, so we set linear_pages to tell demand_page() to fake it
+ * for the moment.
*/
int init_guest_pagetable(struct lguest *lg)
{
- u64 mem;
- u32 initrd_size;
- struct boot_params __user *boot = (struct boot_params *)lg->mem_base;
-#ifdef CONFIG_X86_PAE
- pgd_t *pgd;
- pmd_t *pmd_table;
-#endif
- /*
- * Get the Guest memory size and the ramdisk size from the boot header
- * located at lg->mem_base (Guest address 0).
- */
- if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem))
- || get_user(initrd_size, &boot->hdr.ramdisk_size))
- return -EFAULT;
+ struct lg_cpu *cpu = &lg->cpus[0];
+ int allocated = 0;
- /*
- * We start on the first shadow page table, and give it a blank PGD
- * page.
- */
- lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size);
- if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir))
- return lg->pgdirs[0].gpgdir;
- lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
- if (!lg->pgdirs[0].pgdir)
+ /* lg (and lg->cpus[]) starts zeroed: this allocates a new pgdir */
+ cpu->cpu_pgd = new_pgdir(cpu, 0, &allocated);
+ if (!allocated)
return -ENOMEM;
-#ifdef CONFIG_X86_PAE
- /* For PAE, we also create the initial mid-level. */
- pgd = lg->pgdirs[0].pgdir;
- pmd_table = (pmd_t *) get_zeroed_page(GFP_KERNEL);
- if (!pmd_table)
- return -ENOMEM;
-
- set_pgd(pgd + SWITCHER_PGD_INDEX,
- __pgd(__pa(pmd_table) | _PAGE_PRESENT));
-#endif
-
- /* This is the current page table. */
- lg->cpus[0].cpu_pgd = 0;
+ /* We start with a linear mapping until the initialize. */
+ cpu->linear_pages = true;
return 0;
}
@@ -1095,10 +985,10 @@ void page_table_guest_data_init(struct lg_cpu *cpu)
* of virtual addresses used by the Switcher.
*/
|| put_user(RESERVE_MEM * 1024 * 1024,
- &cpu->lg->lguest_data->reserve_mem)
- || put_user(cpu->lg->pgdirs[0].gpgdir,
- &cpu->lg->lguest_data->pgdir))
+ &cpu->lg->lguest_data->reserve_mem)) {
kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
+ return;
+ }
/*
* In flush_user_mappings() we loop from 0 to
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 9f1659c3d1f3..65af42f2d593 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -269,10 +269,10 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
static int emulate_insn(struct lg_cpu *cpu)
{
u8 insn;
- unsigned int insnlen = 0, in = 0, shift = 0;
+ unsigned int insnlen = 0, in = 0, small_operand = 0;
/*
* The eip contains the *virtual* address of the Guest's instruction:
- * guest_pa just subtracts the Guest's page_offset.
+ * walk the Guest's page tables to find the "physical" address.
*/
unsigned long physaddr = guest_pa(cpu, cpu->regs->eip);
@@ -300,11 +300,10 @@ static int emulate_insn(struct lg_cpu *cpu)
}
/*
- * 0x66 is an "operand prefix". It means it's using the upper 16 bits
- * of the eax register.
+ * 0x66 is an "operand prefix". It means a 16, not 32 bit in/out.
*/
if (insn == 0x66) {
- shift = 16;
+ small_operand = 1;
/* The instruction is 1 byte so far, read the next byte. */
insnlen = 1;
insn = lgread(cpu, physaddr + insnlen, u8);
@@ -340,11 +339,14 @@ static int emulate_insn(struct lg_cpu *cpu)
* traditionally means "there's nothing there".
*/
if (in) {
- /* Lower bit tells is whether it's a 16 or 32 bit access */
- if (insn & 0x1)
- cpu->regs->eax = 0xFFFFFFFF;
- else
- cpu->regs->eax |= (0xFFFF << shift);
+ /* Lower bit tells means it's a 32/16 bit access */
+ if (insn & 0x1) {
+ if (small_operand)
+ cpu->regs->eax |= 0xFFFF;
+ else
+ cpu->regs->eax = 0xFFFFFFFF;
+ } else
+ cpu->regs->eax |= 0xFF;
}
/* Finally, we've "done" the instruction, so move past it. */
cpu->regs->eip += insnlen;
@@ -352,69 +354,6 @@ static int emulate_insn(struct lg_cpu *cpu)
return 1;
}
-/*
- * Our hypercalls mechanism used to be based on direct software interrupts.
- * After Anthony's "Refactor hypercall infrastructure" kvm patch, we decided to
- * change over to using kvm hypercalls.
- *
- * KVM_HYPERCALL is actually a "vmcall" instruction, which generates an invalid
- * opcode fault (fault 6) on non-VT cpus, so the easiest solution seemed to be
- * an *emulation approach*: if the fault was really produced by an hypercall
- * (is_hypercall() does exactly this check), we can just call the corresponding
- * hypercall host implementation function.
- *
- * But these invalid opcode faults are notably slower than software interrupts.
- * So we implemented the *patching (or rewriting) approach*: every time we hit
- * the KVM_HYPERCALL opcode in Guest code, we patch it to the old "int 0x1f"
- * opcode, so next time the Guest calls this hypercall it will use the
- * faster trap mechanism.
- *
- * Matias even benchmarked it to convince you: this shows the average cycle
- * cost of a hypercall. For each alternative solution mentioned above we've
- * made 5 runs of the benchmark:
- *
- * 1) direct software interrupt: 2915, 2789, 2764, 2721, 2898
- * 2) emulation technique: 3410, 3681, 3466, 3392, 3780
- * 3) patching (rewrite) technique: 2977, 2975, 2891, 2637, 2884
- *
- * One two-line function is worth a 20% hypercall speed boost!
- */
-static void rewrite_hypercall(struct lg_cpu *cpu)
-{
- /*
- * This are the opcodes we use to patch the Guest. The opcode for "int
- * $0x1f" is "0xcd 0x1f" but vmcall instruction is 3 bytes long, so we
- * complete the sequence with a NOP (0x90).
- */
- u8 insn[3] = {0xcd, 0x1f, 0x90};
-
- __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
- /*
- * The above write might have caused a copy of that page to be made
- * (if it was read-only). We need to make sure the Guest has
- * up-to-date pagetables. As this doesn't happen often, we can just
- * drop them all.
- */
- guest_pagetable_clear_all(cpu);
-}
-
-static bool is_hypercall(struct lg_cpu *cpu)
-{
- u8 insn[3];
-
- /*
- * This must be the Guest kernel trying to do something.
- * The bottom two bits of the CS segment register are the privilege
- * level.
- */
- if ((cpu->regs->cs & 3) != GUEST_PL)
- return false;
-
- /* Is it a vmcall? */
- __lgread(cpu, insn, guest_pa(cpu, cpu->regs->eip), sizeof(insn));
- return insn[0] == 0x0f && insn[1] == 0x01 && insn[2] == 0xc1;
-}
-
/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
void lguest_arch_handle_trap(struct lg_cpu *cpu)
{
@@ -429,20 +368,6 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
if (emulate_insn(cpu))
return;
}
- /*
- * If KVM is active, the vmcall instruction triggers a General
- * Protection Fault. Normally it triggers an invalid opcode
- * fault (6):
- */
- case 6:
- /*
- * We need to check if ring == GUEST_PL and faulting
- * instruction == vmcall.
- */
- if (is_hypercall(cpu)) {
- rewrite_hypercall(cpu);
- return;
- }
break;
case 14: /* We've intercepted a Page Fault. */
/*
@@ -486,7 +411,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
* These values mean a real interrupt occurred, in which case
* the Host handler has already been run. We just do a
* friendly check if another process should now be run, then
- * return to run the Guest again
+ * return to run the Guest again.
*/
cond_resched();
return;
@@ -536,7 +461,7 @@ void __init lguest_arch_host_init(void)
int i;
/*
- * Most of the i386/switcher.S doesn't care that it's been moved; on
+ * Most of the x86/switcher_32.S doesn't care that it's been moved; on
* Intel, jumps are relative, and it doesn't access any references to
* external code or data.
*
@@ -664,7 +589,7 @@ void __init lguest_arch_host_init(void)
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
}
put_online_cpus();
-};
+}
/*:*/
void __exit lguest_arch_host_fini(void)
@@ -747,8 +672,6 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
/*:*/
/*L:030
- * lguest_arch_setup_regs()
- *
* Most of the Guest's registers are left alone: we used get_zeroed_page() to
* allocate the structure, so they will be 0.
*/
diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
index a271c8218d82..f0e03e7937e3 100644
--- a/drivers/macintosh/nvram.c
+++ b/drivers/macintosh/nvram.c
@@ -21,12 +21,16 @@
static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
{
switch (origin) {
+ case 0:
+ break;
case 1:
offset += file->f_pos;
break;
case 2:
offset += NVRAM_SIZE;
break;
+ default:
+ offset = -1;
}
if (offset < 0)
return -EINVAL;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index c8827ffd85bb..bae6c4e23d3f 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -19,7 +19,7 @@
#include <linux/workqueue.h>
#include <linux/backing-dev.h>
#include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/scatterlist.h>
#include <asm/page.h>
#include <asm/unaligned.h>
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 819e37eaaeba..320401dec104 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -10,7 +10,7 @@
*/
#include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/blkdev.h>
#include <linux/fs.h>
#include <linux/init.h>
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index aa4e570c2cb5..c3547016f0f1 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -19,7 +19,7 @@
#include <linux/time.h>
#include <linux/workqueue.h>
#include <scsi/scsi_dh.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define DM_MSG_PREFIX "multipath"
#define MESG_STR(x) x, sizeof(x)
diff --git a/drivers/md/dm-queue-length.c b/drivers/md/dm-queue-length.c
index f92b6cea9d9c..03a837aa5ce6 100644
--- a/drivers/md/dm-queue-length.c
+++ b/drivers/md/dm-queue-length.c
@@ -20,7 +20,7 @@
#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define DM_MSG_PREFIX "multipath queue-length"
#define QL_MIN_IO 128
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 451c3bb176d2..bfe9c2333cea 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -17,7 +17,7 @@
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define DM_MSG_PREFIX "table"
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index abfb59a61ede..6cd2c313e800 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -213,12 +213,6 @@ static int linear_run (mddev_t *mddev)
return md_integrity_register(mddev);
}
-static void free_conf(struct rcu_head *head)
-{
- linear_conf_t *conf = container_of(head, linear_conf_t, rcu);
- kfree(conf);
-}
-
static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
{
/* Adding a drive to a linear array allows the array to grow.
@@ -247,7 +241,7 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
set_capacity(mddev->gendisk, mddev->array_sectors);
revalidate_disk(mddev->gendisk);
- call_rcu(&oldconf->rcu, free_conf);
+ kfree_rcu(oldconf, rcu);
return 0;
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 91e31e260b4a..dfc9425db70b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6394,16 +6394,11 @@ static void md_seq_stop(struct seq_file *seq, void *v)
mddev_put(mddev);
}
-struct mdstat_info {
- int event;
-};
-
static int md_seq_show(struct seq_file *seq, void *v)
{
mddev_t *mddev = v;
sector_t sectors;
mdk_rdev_t *rdev;
- struct mdstat_info *mi = seq->private;
struct bitmap *bitmap;
if (v == (void*)1) {
@@ -6415,7 +6410,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
spin_unlock(&pers_lock);
seq_printf(seq, "\n");
- mi->event = atomic_read(&md_event_count);
+ seq->poll_event = atomic_read(&md_event_count);
return 0;
}
if (v == (void*)2) {
@@ -6527,26 +6522,21 @@ static const struct seq_operations md_seq_ops = {
static int md_seq_open(struct inode *inode, struct file *file)
{
+ struct seq_file *seq;
int error;
- struct mdstat_info *mi = kmalloc(sizeof(*mi), GFP_KERNEL);
- if (mi == NULL)
- return -ENOMEM;
error = seq_open(file, &md_seq_ops);
if (error)
- kfree(mi);
- else {
- struct seq_file *p = file->private_data;
- p->private = mi;
- mi->event = atomic_read(&md_event_count);
- }
+ return error;
+
+ seq = file->private_data;
+ seq->poll_event = atomic_read(&md_event_count);
return error;
}
static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
{
- struct seq_file *m = filp->private_data;
- struct mdstat_info *mi = m->private;
+ struct seq_file *seq = filp->private_data;
int mask;
poll_wait(filp, &md_event_waiters, wait);
@@ -6554,7 +6544,7 @@ static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
/* always allow read */
mask = POLLIN | POLLRDNORM;
- if (mi->event != atomic_read(&md_event_count))
+ if (seq->poll_event != atomic_read(&md_event_count))
mask |= POLLERR | POLLPRI;
return mask;
}
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 9e2148a19967..437912e49824 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -6,6 +6,7 @@
#ifndef __FLEXCOP_COMMON_H__
#define __FLEXCOP_COMMON_H__
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/mutex.h>
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index b2b0c45f32a9..55e6533f15e9 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -22,6 +22,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c
index 330216febd78..3d7046909009 100644
--- a/drivers/media/dvb/mantis/mantis_ca.c
+++ b/drivers/media/dvb/mantis/mantis_ca.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
index bd400d21b81f..49dbca145bb8 100644
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -21,6 +21,7 @@
#ifndef __MANTIS_COMMON_H
#define __MANTIS_COMMON_H
+#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
index 9f73c2cfc9ea..36f2256ebb0e 100644
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -23,6 +23,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c
index 5772ebb3a69e..672cf4d2462d 100644
--- a/drivers/media/dvb/mantis/mantis_hif.c
+++ b/drivers/media/dvb/mantis/mantis_hif.c
@@ -23,6 +23,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c
index 479086dbb9a8..24fcdc63d6d5 100644
--- a/drivers/media/dvb/mantis/mantis_ioc.c
+++ b/drivers/media/dvb/mantis/mantis_ioc.c
@@ -24,6 +24,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c
index 5cb545b913f6..2f188c089666 100644
--- a/drivers/media/dvb/mantis/mantis_pcmcia.c
+++ b/drivers/media/dvb/mantis/mantis_pcmcia.c
@@ -23,6 +23,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c
index f807c8ba26e4..18340dafa426 100644
--- a/drivers/media/dvb/mantis/mantis_uart.c
+++ b/drivers/media/dvb/mantis/mantis_uart.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <asm/io.h>
#include <linux/signal.h>
#include <linux/sched.h>
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c
index 26bc0cbe84d4..430ae84ce528 100644
--- a/drivers/media/dvb/mantis/mantis_vp1034.c
+++ b/drivers/media/dvb/mantis/mantis_vp1034.c
@@ -21,6 +21,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 7cb79ec685f0..80fb51004461 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -26,6 +26,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index ecd3d0280768..d20168fe4c40 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -42,7 +42,6 @@
#include <linux/bitops.h>
#include <media/rc-core.h>
#include <linux/pci_ids.h>
-#include <linux/delay.h>
#include "ite-cir.h"
diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c
index 9f3bfc1eb240..af9680273ff9 100644
--- a/drivers/media/video/davinci/vpif.c
+++ b/drivers/media/video/davinci/vpif.c
@@ -422,7 +422,7 @@ static int __init vpif_probe(struct platform_device *pdev)
if (!res)
return -ENOENT;
- res_len = res->end - res->start + 1;
+ res_len = resource_size(res);
res = request_mem_region(res->start, res_len, res->name);
if (!res)
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index a27d93b503a5..5f1db46beb4e 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -17,7 +17,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/usb.h>
#include <linux/mutex.h>
#include <linux/i2c.h>
diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c
index d9471928369d..a45d8f098e02 100644
--- a/drivers/media/video/m5mols/m5mols_capture.c
+++ b/drivers/media/video/m5mols/m5mols_capture.c
@@ -22,7 +22,6 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/videodev2.h>
-#include <linux/version.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 4d07c5844402..a647894d3a71 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -129,7 +129,7 @@ module_param(debug, bool, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* list of image formats supported by OMAP2 video pipelines */
-const static struct v4l2_fmtdesc omap_formats[] = {
+static const struct v4l2_fmtdesc omap_formats[] = {
{
/* Note: V4L2 defines RGB565 as:
*
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index f6626e87dbc5..69b60ba5dd7a 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1768,14 +1768,13 @@ static int __devinit omap24xxcam_probe(struct platform_device *pdev)
dev_err(cam->dev, "no mem resource?\n");
goto err;
}
- if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
- pdev->name)) {
+ if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
dev_err(cam->dev,
"cannot reserve camera register I/O region\n");
goto err;
}
cam->mmio_base_phys = mem->start;
- cam->mmio_size = (mem->end - mem->start) + 1;
+ cam->mmio_size = resource_size(mem);
/* map the region */
cam->mmio_base = (unsigned long)
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c
index edd78f8b1baa..d0da11ae19df 100644
--- a/drivers/media/video/tlg2300/pd-dvb.c
+++ b/drivers/media/video/tlg2300/pd-dvb.c
@@ -7,7 +7,7 @@
#include "vendorcmds.h"
#include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index a4db26fa2f53..2c8954ec6859 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -20,7 +20,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "uvcvideo.h"
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index f90ce9fce539..677691c44500 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -19,7 +19,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "uvcvideo.h"
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 543a80395b7f..dde6533e8e6d 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -21,7 +21,7 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 49994793cc77..8244167c8915 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -19,7 +19,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/unaligned.h>
#include <media/v4l2-common.h>
diff --git a/drivers/media/video/videobuf2-memops.c b/drivers/media/video/videobuf2-memops.c
index 5370a3a7ee25..b03c3aea5bea 100644
--- a/drivers/media/video/videobuf2-memops.c
+++ b/drivers/media/video/videobuf2-memops.c
@@ -18,7 +18,6 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/file.h>
-#include <linux/slab.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-memops.h>
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 74fbe56321ff..c8ed7b63fdf5 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -59,7 +59,7 @@
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 090d2a3a6548..a8c08f332da0 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -681,11 +681,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->mem_alloc = 1;
- sb->current_mem_size = 1 + res->end - res->start;
+ sb->current_mem_size = resource_size(res);
sb->current_mem_base = res->start;
osm_info("%s: allocated %llu bytes of PCI memory at "
"0x%016llX.\n", c->name,
- (unsigned long long)(1 + res->end - res->start),
+ (unsigned long long)resource_size(res),
(unsigned long long)res->start);
}
}
@@ -703,11 +703,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->io_alloc = 1;
- sb->current_io_size = 1 + res->end - res->start;
+ sb->current_io_size = resource_size(res);
sb->current_mem_base = res->start;
osm_info("%s: allocated %llu bytes of PCI I/O at "
"0x%016llX.\n", c->name,
- (unsigned long long)(1 + res->end - res->start),
+ (unsigned long long)resource_size(res),
(unsigned long long)res->start);
}
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6ca938a6bf94..37b83eb6d703 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -218,7 +218,7 @@ config TWL4030_POWER
and load scripts controlling which resources are switched off/on
or reset when a sleep, wakeup or warm reset event occurs.
-config TWL4030_CODEC
+config MFD_TWL4030_AUDIO
bool
depends on TWL4030_CORE
select MFD_CORE
@@ -233,6 +233,12 @@ config TWL6030_PWM
Say yes here if you want support for TWL6030 PWM.
This is used to control charging LED brightness.
+config TWL6040_CORE
+ bool
+ depends on TWL4030_CORE && GENERIC_HARDIRQS
+ select MFD_CORE
+ default n
+
config MFD_STMPE
bool "Support STMicroelectronics STMPE"
depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d7d47d2a4c76..22a280fcb705 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -40,8 +40,9 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
-obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
+obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
+obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index ad715bf49cac..71bc835324d8 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -177,7 +177,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)
if (ret)
goto err_resource;
- tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+ tc6387xb->scr = ioremap(rscr->start, resource_size(rscr));
if (!tc6387xb->scr) {
ret = -ENOMEM;
goto err_ioremap;
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index b8f2a4e7f6e7..a2eddc70995c 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -110,7 +110,7 @@
#endif
#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
- defined(CONFIG_SND_SOC_TWL6040) || defined(CONFIG_SND_SOC_TWL6040_MODULE)
+ defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
#define twl_has_codec() true
#else
#define twl_has_codec() false
@@ -815,20 +815,19 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
return PTR_ERR(child);
}
- if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
+ if (twl_has_codec() && pdata->audio && twl_class_is_4030()) {
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
child = add_child(sub_chip_id, "twl4030-audio",
- pdata->codec, sizeof(*pdata->codec),
+ pdata->audio, sizeof(*pdata->audio),
false, 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}
- /* Phoenix codec driver is probed directly atm */
- if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
+ if (twl_has_codec() && pdata->audio && twl_class_is_6030()) {
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
- child = add_child(sub_chip_id, "twl6040-codec",
- pdata->codec, sizeof(*pdata->codec),
+ child = add_child(sub_chip_id, "twl6040",
+ pdata->audio, sizeof(*pdata->audio),
false, 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
new file mode 100644
index 000000000000..ae51ab5d0e5d
--- /dev/null
+++ b/drivers/mfd/twl4030-audio.c
@@ -0,0 +1,277 @@
+/*
+ * MFD driver for twl4030 audio submodule, which contains an audio codec, and
+ * the vibra control.
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright: (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You 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/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl4030-audio.h>
+
+#define TWL4030_AUDIO_CELLS 2
+
+static struct platform_device *twl4030_audio_dev;
+
+struct twl4030_audio_resource {
+ int request_count;
+ u8 reg;
+ u8 mask;
+};
+
+struct twl4030_audio {
+ unsigned int audio_mclk;
+ struct mutex mutex;
+ struct twl4030_audio_resource resource[TWL4030_AUDIO_RES_MAX];
+ struct mfd_cell cells[TWL4030_AUDIO_CELLS];
+};
+
+/*
+ * Modify the resource, the function returns the content of the register
+ * after the modification.
+ */
+static int twl4030_audio_set_resource(enum twl4030_audio_res id, int enable)
+{
+ struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+ u8 val;
+
+ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+ audio->resource[id].reg);
+
+ if (enable)
+ val |= audio->resource[id].mask;
+ else
+ val &= ~audio->resource[id].mask;
+
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ val, audio->resource[id].reg);
+
+ return val;
+}
+
+static inline int twl4030_audio_get_resource(enum twl4030_audio_res id)
+{
+ struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+ u8 val;
+
+ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+ audio->resource[id].reg);
+
+ return val;
+}
+
+/*
+ * Enable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_audio_enable_resource(enum twl4030_audio_res id)
+{
+ struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+ int val;
+
+ if (id >= TWL4030_AUDIO_RES_MAX) {
+ dev_err(&twl4030_audio_dev->dev,
+ "Invalid resource ID (%u)\n", id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&audio->mutex);
+ if (!audio->resource[id].request_count)
+ /* Resource was disabled, enable it */
+ val = twl4030_audio_set_resource(id, 1);
+ else
+ val = twl4030_audio_get_resource(id);
+
+ audio->resource[id].request_count++;
+ mutex_unlock(&audio->mutex);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_enable_resource);
+
+/*
+ * Disable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_audio_disable_resource(unsigned id)
+{
+ struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+ int val;
+
+ if (id >= TWL4030_AUDIO_RES_MAX) {
+ dev_err(&twl4030_audio_dev->dev,
+ "Invalid resource ID (%u)\n", id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&audio->mutex);
+ if (!audio->resource[id].request_count) {
+ dev_err(&twl4030_audio_dev->dev,
+ "Resource has been disabled already (%u)\n", id);
+ mutex_unlock(&audio->mutex);
+ return -EPERM;
+ }
+ audio->resource[id].request_count--;
+
+ if (!audio->resource[id].request_count)
+ /* Resource can be disabled now */
+ val = twl4030_audio_set_resource(id, 0);
+ else
+ val = twl4030_audio_get_resource(id);
+
+ mutex_unlock(&audio->mutex);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_disable_resource);
+
+unsigned int twl4030_audio_get_mclk(void)
+{
+ struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+
+ return audio->audio_mclk;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk);
+
+static int __devinit twl4030_audio_probe(struct platform_device *pdev)
+{
+ struct twl4030_audio *audio;
+ struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+ struct mfd_cell *cell = NULL;
+ int ret, childs = 0;
+ u8 val;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Platform data is missing\n");
+ return -EINVAL;
+ }
+
+ /* Configure APLL_INFREQ and disable APLL if enabled */
+ val = 0;
+ switch (pdata->audio_mclk) {
+ case 19200000:
+ val |= TWL4030_APLL_INFREQ_19200KHZ;
+ break;
+ case 26000000:
+ val |= TWL4030_APLL_INFREQ_26000KHZ;
+ break;
+ case 38400000:
+ val |= TWL4030_APLL_INFREQ_38400KHZ;
+ break;
+ default:
+ dev_err(&pdev->dev, "Invalid audio_mclk\n");
+ return -EINVAL;
+ }
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ val, TWL4030_REG_APLL_CTL);
+
+ audio = kzalloc(sizeof(struct twl4030_audio), GFP_KERNEL);
+ if (!audio)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, audio);
+
+ twl4030_audio_dev = pdev;
+ mutex_init(&audio->mutex);
+ audio->audio_mclk = pdata->audio_mclk;
+
+ /* Codec power */
+ audio->resource[TWL4030_AUDIO_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
+ audio->resource[TWL4030_AUDIO_RES_POWER].mask = TWL4030_CODECPDZ;
+
+ /* PLL */
+ audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL;
+ audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN;
+
+ if (pdata->codec) {
+ cell = &audio->cells[childs];
+ cell->name = "twl4030-codec";
+ cell->platform_data = pdata->codec;
+ cell->pdata_size = sizeof(*pdata->codec);
+ childs++;
+ }
+ if (pdata->vibra) {
+ cell = &audio->cells[childs];
+ cell->name = "twl4030-vibra";
+ cell->platform_data = pdata->vibra;
+ cell->pdata_size = sizeof(*pdata->vibra);
+ childs++;
+ }
+
+ if (childs)
+ ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
+ childs, NULL, 0);
+ else {
+ dev_err(&pdev->dev, "No platform data found for childs\n");
+ ret = -ENODEV;
+ }
+
+ if (!ret)
+ return 0;
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(audio);
+ twl4030_audio_dev = NULL;
+ return ret;
+}
+
+static int __devexit twl4030_audio_remove(struct platform_device *pdev)
+{
+ struct twl4030_audio *audio = platform_get_drvdata(pdev);
+
+ mfd_remove_devices(&pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(audio);
+ twl4030_audio_dev = NULL;
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:twl4030-audio");
+
+static struct platform_driver twl4030_audio_driver = {
+ .probe = twl4030_audio_probe,
+ .remove = __devexit_p(twl4030_audio_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "twl4030-audio",
+ },
+};
+
+static int __devinit twl4030_audio_init(void)
+{
+ return platform_driver_register(&twl4030_audio_driver);
+}
+module_init(twl4030_audio_init);
+
+static void __devexit twl4030_audio_exit(void)
+{
+ platform_driver_unregister(&twl4030_audio_driver);
+}
+module_exit(twl4030_audio_exit);
+
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
deleted file mode 100644
index 2bf4136464c1..000000000000
--- a/drivers/mfd/twl4030-codec.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * MFD driver for twl4030 codec submodule
- *
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright: (C) 2009 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You 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/types.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/twl.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl4030-codec.h>
-
-#define TWL4030_CODEC_CELLS 2
-
-static struct platform_device *twl4030_codec_dev;
-
-struct twl4030_codec_resource {
- int request_count;
- u8 reg;
- u8 mask;
-};
-
-struct twl4030_codec {
- unsigned int audio_mclk;
- struct mutex mutex;
- struct twl4030_codec_resource resource[TWL4030_CODEC_RES_MAX];
- struct mfd_cell cells[TWL4030_CODEC_CELLS];
-};
-
-/*
- * Modify the resource, the function returns the content of the register
- * after the modification.
- */
-static int twl4030_codec_set_resource(enum twl4030_codec_res id, int enable)
-{
- struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
- u8 val;
-
- twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
- codec->resource[id].reg);
-
- if (enable)
- val |= codec->resource[id].mask;
- else
- val &= ~codec->resource[id].mask;
-
- twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
- val, codec->resource[id].reg);
-
- return val;
-}
-
-static inline int twl4030_codec_get_resource(enum twl4030_codec_res id)
-{
- struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
- u8 val;
-
- twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
- codec->resource[id].reg);
-
- return val;
-}
-
-/*
- * Enable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_codec_enable_resource(enum twl4030_codec_res id)
-{
- struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
- int val;
-
- if (id >= TWL4030_CODEC_RES_MAX) {
- dev_err(&twl4030_codec_dev->dev,
- "Invalid resource ID (%u)\n", id);
- return -EINVAL;
- }
-
- mutex_lock(&codec->mutex);
- if (!codec->resource[id].request_count)
- /* Resource was disabled, enable it */
- val = twl4030_codec_set_resource(id, 1);
- else
- val = twl4030_codec_get_resource(id);
-
- codec->resource[id].request_count++;
- mutex_unlock(&codec->mutex);
-
- return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_enable_resource);
-
-/*
- * Disable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_codec_disable_resource(unsigned id)
-{
- struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
- int val;
-
- if (id >= TWL4030_CODEC_RES_MAX) {
- dev_err(&twl4030_codec_dev->dev,
- "Invalid resource ID (%u)\n", id);
- return -EINVAL;
- }
-
- mutex_lock(&codec->mutex);
- if (!codec->resource[id].request_count) {
- dev_err(&twl4030_codec_dev->dev,
- "Resource has been disabled already (%u)\n", id);
- mutex_unlock(&codec->mutex);
- return -EPERM;
- }
- codec->resource[id].request_count--;
-
- if (!codec->resource[id].request_count)
- /* Resource can be disabled now */
- val = twl4030_codec_set_resource(id, 0);
- else
- val = twl4030_codec_get_resource(id);
-
- mutex_unlock(&codec->mutex);
-
- return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_disable_resource);
-
-unsigned int twl4030_codec_get_mclk(void)
-{
- struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-
- return codec->audio_mclk;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_get_mclk);
-
-static int __devinit twl4030_codec_probe(struct platform_device *pdev)
-{
- struct twl4030_codec *codec;
- struct twl4030_codec_data *pdata = pdev->dev.platform_data;
- struct mfd_cell *cell = NULL;
- int ret, childs = 0;
- u8 val;
-
- if (!pdata) {
- dev_err(&pdev->dev, "Platform data is missing\n");
- return -EINVAL;
- }
-
- /* Configure APLL_INFREQ and disable APLL if enabled */
- val = 0;
- switch (pdata->audio_mclk) {
- case 19200000:
- val |= TWL4030_APLL_INFREQ_19200KHZ;
- break;
- case 26000000:
- val |= TWL4030_APLL_INFREQ_26000KHZ;
- break;
- case 38400000:
- val |= TWL4030_APLL_INFREQ_38400KHZ;
- break;
- default:
- dev_err(&pdev->dev, "Invalid audio_mclk\n");
- return -EINVAL;
- }
- twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
- val, TWL4030_REG_APLL_CTL);
-
- codec = kzalloc(sizeof(struct twl4030_codec), GFP_KERNEL);
- if (!codec)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, codec);
-
- twl4030_codec_dev = pdev;
- mutex_init(&codec->mutex);
- codec->audio_mclk = pdata->audio_mclk;
-
- /* Codec power */
- codec->resource[TWL4030_CODEC_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
- codec->resource[TWL4030_CODEC_RES_POWER].mask = TWL4030_CODECPDZ;
-
- /* PLL */
- codec->resource[TWL4030_CODEC_RES_APLL].reg = TWL4030_REG_APLL_CTL;
- codec->resource[TWL4030_CODEC_RES_APLL].mask = TWL4030_APLL_EN;
-
- if (pdata->audio) {
- cell = &codec->cells[childs];
- cell->name = "twl4030-codec";
- cell->platform_data = pdata->audio;
- cell->pdata_size = sizeof(*pdata->audio);
- childs++;
- }
- if (pdata->vibra) {
- cell = &codec->cells[childs];
- cell->name = "twl4030-vibra";
- cell->platform_data = pdata->vibra;
- cell->pdata_size = sizeof(*pdata->vibra);
- childs++;
- }
-
- if (childs)
- ret = mfd_add_devices(&pdev->dev, pdev->id, codec->cells,
- childs, NULL, 0);
- else {
- dev_err(&pdev->dev, "No platform data found for childs\n");
- ret = -ENODEV;
- }
-
- if (!ret)
- return 0;
-
- platform_set_drvdata(pdev, NULL);
- kfree(codec);
- twl4030_codec_dev = NULL;
- return ret;
-}
-
-static int __devexit twl4030_codec_remove(struct platform_device *pdev)
-{
- struct twl4030_codec *codec = platform_get_drvdata(pdev);
-
- mfd_remove_devices(&pdev->dev);
- platform_set_drvdata(pdev, NULL);
- kfree(codec);
- twl4030_codec_dev = NULL;
-
- return 0;
-}
-
-MODULE_ALIAS("platform:twl4030-audio");
-
-static struct platform_driver twl4030_codec_driver = {
- .probe = twl4030_codec_probe,
- .remove = __devexit_p(twl4030_codec_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "twl4030-audio",
- },
-};
-
-static int __devinit twl4030_codec_init(void)
-{
- return platform_driver_register(&twl4030_codec_driver);
-}
-module_init(twl4030_codec_init);
-
-static void __devexit twl4030_codec_exit(void)
-{
- platform_driver_unregister(&twl4030_codec_driver);
-}
-module_exit(twl4030_codec_exit);
-
-MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
new file mode 100644
index 000000000000..24d436c2fe4a
--- /dev/null
+++ b/drivers/mfd/twl6040-core.c
@@ -0,0 +1,620 @@
+/*
+ * MFD driver for TWL6040 audio device
+ *
+ * Authors: Misael Lopez Cruz <misael.lopez@ti.com>
+ * Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ * Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You 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/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl6040.h>
+
+static struct platform_device *twl6040_dev;
+
+int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
+{
+ int ret;
+ 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;
+ }
+ mutex_unlock(&twl6040->io_mutex);
+
+ return val;
+}
+EXPORT_SYMBOL(twl6040_reg_read);
+
+int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
+{
+ int ret;
+
+ mutex_lock(&twl6040->io_mutex);
+ ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+ mutex_unlock(&twl6040->io_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(twl6040_reg_write);
+
+int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+ int ret;
+ u8 val;
+
+ mutex_lock(&twl6040->io_mutex);
+ ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+ if (ret)
+ goto out;
+
+ val |= mask;
+ ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+out:
+ mutex_unlock(&twl6040->io_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(twl6040_set_bits);
+
+int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+ int ret;
+ u8 val;
+
+ mutex_lock(&twl6040->io_mutex);
+ ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+ if (ret)
+ goto out;
+
+ val &= ~mask;
+ ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+out:
+ mutex_unlock(&twl6040->io_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(twl6040_clear_bits);
+
+/* twl6040 codec manual power-up sequence */
+static int twl6040_power_up(struct twl6040 *twl6040)
+{
+ u8 ldoctl, ncpctl, lppllctl;
+ int ret;
+
+ /* enable high-side LDO, reference system and internal oscillator */
+ ldoctl = TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA;
+ ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+ if (ret)
+ return ret;
+ usleep_range(10000, 10500);
+
+ /* enable negative charge pump */
+ ncpctl = TWL6040_NCPENA;
+ ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+ if (ret)
+ goto ncp_err;
+ usleep_range(1000, 1500);
+
+ /* enable low-side LDO */
+ ldoctl |= TWL6040_LSLDOENA;
+ ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+ if (ret)
+ goto lsldo_err;
+ usleep_range(1000, 1500);
+
+ /* enable low-power PLL */
+ lppllctl = TWL6040_LPLLENA;
+ ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+ if (ret)
+ goto lppll_err;
+ usleep_range(5000, 5500);
+
+ /* disable internal oscillator */
+ ldoctl &= ~TWL6040_OSCENA;
+ ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+ if (ret)
+ goto osc_err;
+
+ return 0;
+
+osc_err:
+ lppllctl &= ~TWL6040_LPLLENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+lppll_err:
+ ldoctl &= ~TWL6040_LSLDOENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+lsldo_err:
+ ncpctl &= ~TWL6040_NCPENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+ncp_err:
+ ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+ twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+ return ret;
+}
+
+/* twl6040 manual power-down sequence */
+static void twl6040_power_down(struct twl6040 *twl6040)
+{
+ u8 ncpctl, ldoctl, lppllctl;
+
+ ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
+ ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
+ lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+ /* enable internal oscillator */
+ ldoctl |= TWL6040_OSCENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+ usleep_range(1000, 1500);
+
+ /* disable low-power PLL */
+ lppllctl &= ~TWL6040_LPLLENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+ /* disable low-side LDO */
+ ldoctl &= ~TWL6040_LSLDOENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+ /* disable negative charge pump */
+ ncpctl &= ~TWL6040_NCPENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+
+ /* disable high-side LDO, reference system and internal oscillator */
+ ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+ twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+}
+
+static irqreturn_t twl6040_naudint_handler(int irq, void *data)
+{
+ struct twl6040 *twl6040 = data;
+ u8 intid, status;
+
+ intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+ if (intid & TWL6040_READYINT)
+ complete(&twl6040->ready);
+
+ if (intid & TWL6040_THINT) {
+ status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
+ if (status & TWL6040_TSHUTDET) {
+ dev_warn(&twl6040_dev->dev,
+ "Thermal shutdown, powering-off");
+ twl6040_power(twl6040, 0);
+ } else {
+ dev_warn(&twl6040_dev->dev,
+ "Leaving thermal shutdown, powering-on");
+ twl6040_power(twl6040, 1);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int twl6040_power_up_completion(struct twl6040 *twl6040,
+ int naudint)
+{
+ int time_left;
+ u8 intid;
+
+ time_left = wait_for_completion_timeout(&twl6040->ready,
+ msecs_to_jiffies(144));
+ if (!time_left) {
+ intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+ if (!(intid & TWL6040_READYINT)) {
+ dev_err(&twl6040_dev->dev,
+ "timeout waiting for READYINT\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+int twl6040_power(struct twl6040 *twl6040, int on)
+{
+ int audpwron = twl6040->audpwron;
+ int naudint = twl6040->irq;
+ int ret = 0;
+
+ mutex_lock(&twl6040->mutex);
+
+ if (on) {
+ /* already powered-up */
+ if (twl6040->power_count++)
+ goto out;
+
+ if (gpio_is_valid(audpwron)) {
+ /* use AUDPWRON line */
+ gpio_set_value(audpwron, 1);
+ /* wait for power-up completion */
+ ret = twl6040_power_up_completion(twl6040, naudint);
+ if (ret) {
+ dev_err(&twl6040_dev->dev,
+ "automatic power-down failed\n");
+ twl6040->power_count = 0;
+ goto out;
+ }
+ } else {
+ /* use manual power-up sequence */
+ ret = twl6040_power_up(twl6040);
+ if (ret) {
+ dev_err(&twl6040_dev->dev,
+ "manual power-up failed\n");
+ twl6040->power_count = 0;
+ goto out;
+ }
+ }
+ /* Default PLL configuration after power up */
+ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
+ twl6040->sysclk = 19200000;
+ } else {
+ /* already powered-down */
+ if (!twl6040->power_count) {
+ dev_err(&twl6040_dev->dev,
+ "device is already powered-off\n");
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (--twl6040->power_count)
+ goto out;
+
+ if (gpio_is_valid(audpwron)) {
+ /* use AUDPWRON line */
+ gpio_set_value(audpwron, 0);
+
+ /* power-down sequence latency */
+ usleep_range(500, 700);
+ } else {
+ /* use manual power-down sequence */
+ twl6040_power_down(twl6040);
+ }
+ twl6040->sysclk = 0;
+ }
+
+out:
+ mutex_unlock(&twl6040->mutex);
+ return ret;
+}
+EXPORT_SYMBOL(twl6040_power);
+
+int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
+ unsigned int freq_in, unsigned int freq_out)
+{
+ u8 hppllctl, lppllctl;
+ int ret = 0;
+
+ mutex_lock(&twl6040->mutex);
+
+ hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
+ lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+ switch (pll_id) {
+ case TWL6040_SYSCLK_SEL_LPPLL:
+ /* low-power PLL divider */
+ switch (freq_out) {
+ case 17640000:
+ lppllctl |= TWL6040_LPLLFIN;
+ break;
+ case 19200000:
+ lppllctl &= ~TWL6040_LPLLFIN;
+ break;
+ default:
+ dev_err(&twl6040_dev->dev,
+ "freq_out %d not supported\n", freq_out);
+ ret = -EINVAL;
+ goto pll_out;
+ }
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+ switch (freq_in) {
+ case 32768:
+ lppllctl |= TWL6040_LPLLENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+ lppllctl);
+ mdelay(5);
+ lppllctl &= ~TWL6040_HPLLSEL;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+ lppllctl);
+ hppllctl &= ~TWL6040_HPLLENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+ hppllctl);
+ break;
+ default:
+ dev_err(&twl6040_dev->dev,
+ "freq_in %d not supported\n", freq_in);
+ ret = -EINVAL;
+ goto pll_out;
+ }
+ break;
+ case TWL6040_SYSCLK_SEL_HPPLL:
+ /* high-performance PLL can provide only 19.2 MHz */
+ if (freq_out != 19200000) {
+ dev_err(&twl6040_dev->dev,
+ "freq_out %d not supported\n", freq_out);
+ ret = -EINVAL;
+ goto pll_out;
+ }
+
+ hppllctl &= ~TWL6040_MCLK_MSK;
+
+ switch (freq_in) {
+ case 12000000:
+ /* PLL enabled, active mode */
+ hppllctl |= TWL6040_MCLK_12000KHZ |
+ TWL6040_HPLLENA;
+ break;
+ case 19200000:
+ /*
+ * PLL disabled
+ * (enable PLL if MCLK jitter quality
+ * doesn't meet specification)
+ */
+ hppllctl |= TWL6040_MCLK_19200KHZ;
+ break;
+ case 26000000:
+ /* PLL enabled, active mode */
+ hppllctl |= TWL6040_MCLK_26000KHZ |
+ TWL6040_HPLLENA;
+ break;
+ case 38400000:
+ /* PLL enabled, active mode */
+ hppllctl |= TWL6040_MCLK_38400KHZ |
+ TWL6040_HPLLENA;
+ break;
+ default:
+ dev_err(&twl6040_dev->dev,
+ "freq_in %d not supported\n", freq_in);
+ ret = -EINVAL;
+ goto pll_out;
+ }
+
+ /* enable clock slicer to ensure input waveform is square */
+ hppllctl |= TWL6040_HPLLSQRENA;
+
+ twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
+ usleep_range(500, 700);
+ lppllctl |= TWL6040_HPLLSEL;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+ lppllctl &= ~TWL6040_LPLLENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+ break;
+ default:
+ dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id);
+ ret = -EINVAL;
+ goto pll_out;
+ }
+
+ twl6040->sysclk = freq_out;
+ twl6040->pll = pll_id;
+
+pll_out:
+ mutex_unlock(&twl6040->mutex);
+ return ret;
+}
+EXPORT_SYMBOL(twl6040_set_pll);
+
+int twl6040_get_pll(struct twl6040 *twl6040)
+{
+ if (twl6040->power_count)
+ return twl6040->pll;
+ else
+ return -ENODEV;
+}
+EXPORT_SYMBOL(twl6040_get_pll);
+
+unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
+{
+ return twl6040->sysclk;
+}
+EXPORT_SYMBOL(twl6040_get_sysclk);
+
+static struct resource twl6040_vibra_rsrc[] = {
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource twl6040_codec_rsrc[] = {
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int __devinit twl6040_probe(struct platform_device *pdev)
+{
+ struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+ struct twl6040 *twl6040;
+ struct mfd_cell *cell = NULL;
+ int ret, children = 0;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Platform data is missing\n");
+ return -EINVAL;
+ }
+
+ /* In order to operate correctly we need valid interrupt config */
+ if (!pdata->naudint_irq || !pdata->irq_base) {
+ dev_err(&pdev->dev, "Invalid IRQ configuration\n");
+ return -EINVAL;
+ }
+
+ twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
+ if (!twl6040)
+ return -ENOMEM;
+
+ 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;
+
+ mutex_init(&twl6040->mutex);
+ mutex_init(&twl6040->io_mutex);
+ init_completion(&twl6040->ready);
+
+ twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
+
+ if (gpio_is_valid(twl6040->audpwron)) {
+ ret = gpio_request(twl6040->audpwron, "audpwron");
+ if (ret)
+ goto gpio1_err;
+
+ ret = gpio_direction_output(twl6040->audpwron, 0);
+ if (ret)
+ 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)
+ goto gpio2_err;
+
+ ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
+ NULL, twl6040_naudint_handler, 0,
+ "twl6040_irq_ready", twl6040);
+ if (ret) {
+ dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
+ ret);
+ goto irq_err;
+ }
+
+ /* dual-access registers controlled by I2C only */
+ twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
+
+ if (pdata->codec) {
+ int irq = twl6040->irq_base + TWL6040_IRQ_PLUG;
+
+ cell = &twl6040->cells[children];
+ cell->name = "twl6040-codec";
+ twl6040_codec_rsrc[0].start = irq;
+ twl6040_codec_rsrc[0].end = irq;
+ cell->resources = twl6040_codec_rsrc;
+ cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
+ cell->platform_data = pdata->codec;
+ cell->pdata_size = sizeof(*pdata->codec);
+ children++;
+ }
+
+ if (pdata->vibra) {
+ int irq = twl6040->irq_base + TWL6040_IRQ_VIB;
+
+ cell = &twl6040->cells[children];
+ cell->name = "twl6040-vibra";
+ twl6040_vibra_rsrc[0].start = irq;
+ twl6040_vibra_rsrc[0].end = irq;
+ cell->resources = twl6040_vibra_rsrc;
+ cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
+
+ cell->platform_data = pdata->vibra;
+ cell->pdata_size = sizeof(*pdata->vibra);
+ children++;
+ }
+
+ if (children) {
+ ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
+ children, NULL, 0);
+ if (ret)
+ goto mfd_err;
+ } else {
+ dev_err(&pdev->dev, "No platform data found for children\n");
+ ret = -ENODEV;
+ goto mfd_err;
+ }
+
+ return 0;
+
+mfd_err:
+ free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
+irq_err:
+ twl6040_irq_exit(twl6040);
+gpio2_err:
+ if (gpio_is_valid(twl6040->audpwron))
+ gpio_free(twl6040->audpwron);
+gpio1_err:
+ platform_set_drvdata(pdev, NULL);
+ kfree(twl6040);
+ twl6040_dev = NULL;
+ return ret;
+}
+
+static int __devexit twl6040_remove(struct platform_device *pdev)
+{
+ struct twl6040 *twl6040 = platform_get_drvdata(pdev);
+
+ if (twl6040->power_count)
+ twl6040_power(twl6040, 0);
+
+ if (gpio_is_valid(twl6040->audpwron))
+ gpio_free(twl6040->audpwron);
+
+ free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
+ twl6040_irq_exit(twl6040);
+
+ mfd_remove_devices(&pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(twl6040);
+ twl6040_dev = NULL;
+
+ return 0;
+}
+
+static struct platform_driver twl6040_driver = {
+ .probe = twl6040_probe,
+ .remove = __devexit_p(twl6040_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "twl6040",
+ },
+};
+
+static int __devinit twl6040_init(void)
+{
+ return platform_driver_register(&twl6040_driver);
+}
+module_init(twl6040_init);
+
+static void __devexit twl6040_exit(void)
+{
+ platform_driver_unregister(&twl6040_driver);
+}
+
+module_exit(twl6040_exit);
+
+MODULE_DESCRIPTION("TWL6040 MFD");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl6040");
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
new file mode 100644
index 000000000000..b3f8ddaa28a8
--- /dev/null
+++ b/drivers/mfd/twl6040-irq.c
@@ -0,0 +1,191 @@
+/*
+ * Interrupt controller support for TWL6040
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl6040.h>
+
+struct twl6040_irq_data {
+ int mask;
+ int status;
+};
+
+static struct twl6040_irq_data twl6040_irqs[] = {
+ {
+ .mask = TWL6040_THMSK,
+ .status = TWL6040_THINT,
+ },
+ {
+ .mask = TWL6040_PLUGMSK,
+ .status = TWL6040_PLUGINT | TWL6040_UNPLUGINT,
+ },
+ {
+ .mask = TWL6040_HOOKMSK,
+ .status = TWL6040_HOOKINT,
+ },
+ {
+ .mask = TWL6040_HFMSK,
+ .status = TWL6040_HFINT,
+ },
+ {
+ .mask = TWL6040_VIBMSK,
+ .status = TWL6040_VIBINT,
+ },
+ {
+ .mask = TWL6040_READYMSK,
+ .status = TWL6040_READYINT,
+ },
+};
+
+static inline
+struct twl6040_irq_data *irq_to_twl6040_irq(struct twl6040 *twl6040,
+ int irq)
+{
+ return &twl6040_irqs[irq - twl6040->irq_base];
+}
+
+static void twl6040_irq_lock(struct irq_data *data)
+{
+ struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&twl6040->irq_mutex);
+}
+
+static void twl6040_irq_sync_unlock(struct irq_data *data)
+{
+ struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+
+ /* write back to hardware any change in irq mask */
+ if (twl6040->irq_masks_cur != twl6040->irq_masks_cache) {
+ twl6040->irq_masks_cache = twl6040->irq_masks_cur;
+ twl6040_reg_write(twl6040, TWL6040_REG_INTMR,
+ twl6040->irq_masks_cur);
+ }
+
+ mutex_unlock(&twl6040->irq_mutex);
+}
+
+static void twl6040_irq_enable(struct irq_data *data)
+{
+ struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+ struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
+ data->irq);
+
+ twl6040->irq_masks_cur &= ~irq_data->mask;
+}
+
+static void twl6040_irq_disable(struct irq_data *data)
+{
+ struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+ struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
+ data->irq);
+
+ twl6040->irq_masks_cur |= irq_data->mask;
+}
+
+static struct irq_chip twl6040_irq_chip = {
+ .name = "twl6040",
+ .irq_bus_lock = twl6040_irq_lock,
+ .irq_bus_sync_unlock = twl6040_irq_sync_unlock,
+ .irq_enable = twl6040_irq_enable,
+ .irq_disable = twl6040_irq_disable,
+};
+
+static irqreturn_t twl6040_irq_thread(int irq, void *data)
+{
+ struct twl6040 *twl6040 = data;
+ u8 intid;
+ int i;
+
+ intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+ /* apply masking and report (backwards to handle READYINT first) */
+ for (i = ARRAY_SIZE(twl6040_irqs) - 1; i >= 0; i--) {
+ if (twl6040->irq_masks_cur & twl6040_irqs[i].mask)
+ intid &= ~twl6040_irqs[i].status;
+ if (intid & twl6040_irqs[i].status)
+ handle_nested_irq(twl6040->irq_base + i);
+ }
+
+ /* ack unmasked irqs */
+ twl6040_reg_write(twl6040, TWL6040_REG_INTID, intid);
+
+ return IRQ_HANDLED;
+}
+
+int twl6040_irq_init(struct twl6040 *twl6040)
+{
+ int cur_irq, ret;
+ u8 val;
+
+ mutex_init(&twl6040->irq_mutex);
+
+ /* mask the individual interrupt sources */
+ twl6040->irq_masks_cur = TWL6040_ALLINT_MSK;
+ twl6040->irq_masks_cache = TWL6040_ALLINT_MSK;
+ twl6040_reg_write(twl6040, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK);
+
+ /* Register them with genirq */
+ for (cur_irq = twl6040->irq_base;
+ cur_irq < twl6040->irq_base + ARRAY_SIZE(twl6040_irqs);
+ cur_irq++) {
+ irq_set_chip_data(cur_irq, twl6040);
+ irq_set_chip_and_handler(cur_irq, &twl6040_irq_chip,
+ handle_level_irq);
+ irq_set_nested_thread(cur_irq, 1);
+
+ /* ARM needs us to explicitly flag the IRQ as valid
+ * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ irq_set_noprobe(cur_irq);
+#endif
+ }
+
+ ret = request_threaded_irq(twl6040->irq, NULL, twl6040_irq_thread,
+ IRQF_ONESHOT, "twl6040", twl6040);
+ if (ret) {
+ dev_err(twl6040->dev, "failed to request IRQ %d: %d\n",
+ twl6040->irq, ret);
+ return ret;
+ }
+
+ /* reset interrupts */
+ val = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+ /* interrupts cleared on write */
+ twl6040_clear_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_INTCLRMODE);
+
+ return 0;
+}
+EXPORT_SYMBOL(twl6040_irq_init);
+
+void twl6040_irq_exit(struct twl6040 *twl6040)
+{
+ free_irq(twl6040->irq, twl6040);
+}
+EXPORT_SYMBOL(twl6040_irq_exit);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 4e349cd98bcf..0a4d86c6c4a4 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -245,8 +245,7 @@ config SGI_XP
config CS5535_MFGPT
tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support"
- depends on PCI
- depends on X86
+ depends on PCI && X86 && MFD_CS5535
default n
help
This driver provides access to MFGPT functionality for other
@@ -490,6 +489,15 @@ config PCH_PHUB
To compile this driver as a module, choose M here: the module will
be called pch_phub.
+config USB_SWITCH_FSA9480
+ tristate "FSA9480 USB Switch"
+ depends on I2C
+ help
+ The FSA9480 is a USB port accessory detector and switch.
+ The FSA9480 is fully controlled using I2C and enables USB data,
+ stereo and mono audio, video, microphone and UART data to use
+ a common connector port.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5f03172cc0b5..8f3efb68a141 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
-0bj-$(CONFIG_INTEL_MID_PTI) += pti.o
+obj-$(CONFIG_INTEL_MID_PTI) += pti.o
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
@@ -46,3 +46,4 @@ obj-y += ti-st/
obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
obj-y += lis3lv02d/
obj-y += carma/
+obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 4afffe610f99..769a4e8e10dc 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -95,7 +95,7 @@ static int __init ssc_probe(struct platform_device *pdev)
}
ssc->pdev = pdev;
- ssc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ ssc->regs = ioremap(regs->start, resource_size(regs));
if (!ssc->regs) {
dev_dbg(&pdev->dev, "ioremap failed\n");
retval = -EINVAL;
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
index 0f3fb4f03bdf..28f5aaa19d4a 100644
--- a/drivers/misc/atmel_pwm.c
+++ b/drivers/misc/atmel_pwm.c
@@ -329,7 +329,7 @@ static int __init pwm_probe(struct platform_device *pdev)
p->pdev = pdev;
p->mask = *mp;
p->irq = irq;
- p->base = ioremap(r->start, r->end - r->start + 1);
+ p->base = ioremap(r->start, resource_size(r));
if (!p->base)
goto fail;
p->clk = clk_get(&pdev->dev, "pwm_clk");
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9118613af321..26cf12ca7f50 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -70,4 +70,29 @@ config EEPROM_93CX6
If unsure, say N.
+config EEPROM_93XX46
+ tristate "Microwire EEPROM 93XX46 support"
+ depends on SPI && SYSFS
+ help
+ Driver for the microwire EEPROM chipsets 93xx46x. The driver
+ supports both read and write commands and also the command to
+ erase the whole EEPROM.
+
+ This driver can also be built as a module. If so, the module
+ will be called eeprom_93xx46.
+
+ If unsure, say N.
+
+config EEPROM_DIGSY_MTC_CFG
+ bool "DigsyMTC display configuration EEPROMs device"
+ depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO
+ help
+ This option enables access to display configuration EEPROMs
+ on digsy_mtc board. You have to additionally select Microwire
+ EEPROM 93XX46 driver. sysfs entries will be created for that
+ EEPROM allowing to read/write the configuration data or to
+ erase the whole EEPROM.
+
+ If unsure, say N.
+
endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index df3d68ffa9d1..fc1e81d29267 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_EEPROM_AT25) += at25.o
obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
+obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o
+obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c
new file mode 100644
index 000000000000..66d9e1baeae5
--- /dev/null
+++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c
@@ -0,0 +1,85 @@
+/*
+ * EEPROMs access control driver for display configuration EEPROMs
+ * on DigsyMTC board.
+ *
+ * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.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/gpio.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/eeprom_93xx46.h>
+
+#define GPIO_EEPROM_CLK 216
+#define GPIO_EEPROM_CS 210
+#define GPIO_EEPROM_DI 217
+#define GPIO_EEPROM_DO 249
+#define GPIO_EEPROM_OE 255
+#define EE_SPI_BUS_NUM 1
+
+static void digsy_mtc_op_prepare(void *p)
+{
+ /* enable */
+ gpio_set_value(GPIO_EEPROM_OE, 0);
+}
+
+static void digsy_mtc_op_finish(void *p)
+{
+ /* disable */
+ gpio_set_value(GPIO_EEPROM_OE, 1);
+}
+
+struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = {
+ .flags = EE_ADDR8,
+ .prepare = digsy_mtc_op_prepare,
+ .finish = digsy_mtc_op_finish,
+};
+
+static struct spi_gpio_platform_data eeprom_spi_gpio_data = {
+ .sck = GPIO_EEPROM_CLK,
+ .mosi = GPIO_EEPROM_DI,
+ .miso = GPIO_EEPROM_DO,
+ .num_chipselect = 1,
+};
+
+static struct platform_device digsy_mtc_eeprom = {
+ .name = "spi_gpio",
+ .id = EE_SPI_BUS_NUM,
+ .dev = {
+ .platform_data = &eeprom_spi_gpio_data,
+ },
+};
+
+static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = {
+ {
+ .modalias = "93xx46",
+ .max_speed_hz = 1000000,
+ .bus_num = EE_SPI_BUS_NUM,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ .controller_data = (void *)GPIO_EEPROM_CS,
+ .platform_data = &digsy_mtc_eeprom_data,
+ },
+};
+
+static int __init digsy_mtc_eeprom_devices_init(void)
+{
+ int ret;
+
+ ret = gpio_request_one(GPIO_EEPROM_OE, GPIOF_OUT_INIT_HIGH,
+ "93xx46 EEPROMs OE");
+ if (ret) {
+ pr_err("can't request gpio %d\n", GPIO_EEPROM_OE);
+ return ret;
+ }
+ spi_register_board_info(digsy_mtc_eeprom_info,
+ ARRAY_SIZE(digsy_mtc_eeprom_info));
+ return platform_device_register(&digsy_mtc_eeprom);
+}
+device_initcall(digsy_mtc_eeprom_devices_init);
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
new file mode 100644
index 000000000000..0c7ebb1e19e5
--- /dev/null
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -0,0 +1,410 @@
+/*
+ * Driver for 93xx46 EEPROMs
+ *
+ * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.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/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
+#include <linux/eeprom_93xx46.h>
+
+#define OP_START 0x4
+#define OP_WRITE (OP_START | 0x1)
+#define OP_READ (OP_START | 0x2)
+#define ADDR_EWDS 0x00
+#define ADDR_ERAL 0x20
+#define ADDR_EWEN 0x30
+
+struct eeprom_93xx46_dev {
+ struct spi_device *spi;
+ struct eeprom_93xx46_platform_data *pdata;
+ struct bin_attribute bin;
+ struct mutex lock;
+ int addrlen;
+};
+
+static ssize_t
+eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct eeprom_93xx46_dev *edev;
+ struct device *dev;
+ struct spi_message m;
+ struct spi_transfer t[2];
+ int bits, ret;
+ u16 cmd_addr;
+
+ dev = container_of(kobj, struct device, kobj);
+ edev = dev_get_drvdata(dev);
+
+ if (unlikely(off >= edev->bin.size))
+ return 0;
+ if ((off + count) > edev->bin.size)
+ count = edev->bin.size - off;
+ if (unlikely(!count))
+ return count;
+
+ cmd_addr = OP_READ << edev->addrlen;
+
+ if (edev->addrlen == 7) {
+ cmd_addr |= off & 0x7f;
+ bits = 10;
+ } else {
+ cmd_addr |= off & 0x3f;
+ bits = 9;
+ }
+
+ dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n",
+ cmd_addr, edev->spi->max_speed_hz);
+
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
+
+ t[0].tx_buf = (char *)&cmd_addr;
+ t[0].len = 2;
+ t[0].bits_per_word = bits;
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+ t[1].len = count;
+ t[1].bits_per_word = 8;
+ spi_message_add_tail(&t[1], &m);
+
+ mutex_lock(&edev->lock);
+
+ if (edev->pdata->prepare)
+ edev->pdata->prepare(edev);
+
+ ret = spi_sync(edev->spi, &m);
+ /* have to wait at least Tcsl ns */
+ ndelay(250);
+ if (ret) {
+ dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n",
+ count, (int)off, ret);
+ }
+
+ if (edev->pdata->finish)
+ edev->pdata->finish(edev);
+
+ mutex_unlock(&edev->lock);
+ return ret ? : count;
+}
+
+static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
+{
+ struct spi_message m;
+ struct spi_transfer t;
+ int bits, ret;
+ u16 cmd_addr;
+
+ cmd_addr = OP_START << edev->addrlen;
+ if (edev->addrlen == 7) {
+ cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1;
+ bits = 10;
+ } else {
+ cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS);
+ bits = 9;
+ }
+
+ dev_dbg(&edev->spi->dev, "ew cmd 0x%04x\n", cmd_addr);
+
+ spi_message_init(&m);
+ memset(&t, 0, sizeof(t));
+
+ t.tx_buf = &cmd_addr;
+ t.len = 2;
+ t.bits_per_word = bits;
+ spi_message_add_tail(&t, &m);
+
+ mutex_lock(&edev->lock);
+
+ if (edev->pdata->prepare)
+ edev->pdata->prepare(edev);
+
+ ret = spi_sync(edev->spi, &m);
+ /* have to wait at least Tcsl ns */
+ ndelay(250);
+ if (ret)
+ dev_err(&edev->spi->dev, "erase/write %sable error %d\n",
+ is_on ? "en" : "dis", ret);
+
+ if (edev->pdata->finish)
+ edev->pdata->finish(edev);
+
+ mutex_unlock(&edev->lock);
+ return ret;
+}
+
+static ssize_t
+eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
+ const char *buf, unsigned off)
+{
+ struct spi_message m;
+ struct spi_transfer t[2];
+ int bits, data_len, ret;
+ u16 cmd_addr;
+
+ cmd_addr = OP_WRITE << edev->addrlen;
+
+ if (edev->addrlen == 7) {
+ cmd_addr |= off & 0x7f;
+ bits = 10;
+ data_len = 1;
+ } else {
+ cmd_addr |= off & 0x3f;
+ bits = 9;
+ data_len = 2;
+ }
+
+ dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr);
+
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
+
+ t[0].tx_buf = (char *)&cmd_addr;
+ t[0].len = 2;
+ t[0].bits_per_word = bits;
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+ t[1].len = data_len;
+ t[1].bits_per_word = 8;
+ spi_message_add_tail(&t[1], &m);
+
+ ret = spi_sync(edev->spi, &m);
+ /* have to wait program cycle time Twc ms */
+ mdelay(6);
+ return ret;
+}
+
+static ssize_t
+eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct eeprom_93xx46_dev *edev;
+ struct device *dev;
+ int i, ret, step = 1;
+
+ dev = container_of(kobj, struct device, kobj);
+ edev = dev_get_drvdata(dev);
+
+ if (unlikely(off >= edev->bin.size))
+ return 0;
+ if ((off + count) > edev->bin.size)
+ count = edev->bin.size - off;
+ if (unlikely(!count))
+ return count;
+
+ /* only write even number of bytes on 16-bit devices */
+ if (edev->addrlen == 6) {
+ step = 2;
+ count &= ~1;
+ }
+
+ /* erase/write enable */
+ ret = eeprom_93xx46_ew(edev, 1);
+ if (ret)
+ return ret;
+
+ mutex_lock(&edev->lock);
+
+ if (edev->pdata->prepare)
+ edev->pdata->prepare(edev);
+
+ for (i = 0; i < count; i += step) {
+ ret = eeprom_93xx46_write_word(edev, &buf[i], off + i);
+ if (ret) {
+ dev_err(&edev->spi->dev, "write failed at %d: %d\n",
+ (int)off + i, ret);
+ break;
+ }
+ }
+
+ if (edev->pdata->finish)
+ edev->pdata->finish(edev);
+
+ mutex_unlock(&edev->lock);
+
+ /* erase/write disable */
+ eeprom_93xx46_ew(edev, 0);
+ return ret ? : count;
+}
+
+static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
+{
+ struct eeprom_93xx46_platform_data *pd = edev->pdata;
+ struct spi_message m;
+ struct spi_transfer t;
+ int bits, ret;
+ u16 cmd_addr;
+
+ cmd_addr = OP_START << edev->addrlen;
+ if (edev->addrlen == 7) {
+ cmd_addr |= ADDR_ERAL << 1;
+ bits = 10;
+ } else {
+ cmd_addr |= ADDR_ERAL;
+ bits = 9;
+ }
+
+ spi_message_init(&m);
+ memset(&t, 0, sizeof(t));
+
+ t.tx_buf = &cmd_addr;
+ t.len = 2;
+ t.bits_per_word = bits;
+ spi_message_add_tail(&t, &m);
+
+ mutex_lock(&edev->lock);
+
+ if (edev->pdata->prepare)
+ edev->pdata->prepare(edev);
+
+ ret = spi_sync(edev->spi, &m);
+ if (ret)
+ dev_err(&edev->spi->dev, "erase error %d\n", ret);
+ /* have to wait erase cycle time Tec ms */
+ mdelay(6);
+
+ if (pd->finish)
+ pd->finish(edev);
+
+ mutex_unlock(&edev->lock);
+ return ret;
+}
+
+static ssize_t eeprom_93xx46_store_erase(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev);
+ int erase = 0, ret;
+
+ sscanf(buf, "%d", &erase);
+ if (erase) {
+ ret = eeprom_93xx46_ew(edev, 1);
+ if (ret)
+ return ret;
+ ret = eeprom_93xx46_eral(edev);
+ if (ret)
+ return ret;
+ ret = eeprom_93xx46_ew(edev, 0);
+ if (ret)
+ return ret;
+ }
+ return count;
+}
+static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
+
+static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
+{
+ struct eeprom_93xx46_platform_data *pd;
+ struct eeprom_93xx46_dev *edev;
+ int err;
+
+ pd = spi->dev.platform_data;
+ if (!pd) {
+ dev_err(&spi->dev, "missing platform data\n");
+ return -ENODEV;
+ }
+
+ edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+ if (!edev)
+ return -ENOMEM;
+
+ if (pd->flags & EE_ADDR8)
+ edev->addrlen = 7;
+ else if (pd->flags & EE_ADDR16)
+ edev->addrlen = 6;
+ else {
+ dev_err(&spi->dev, "unspecified address type\n");
+ err = -EINVAL;
+ goto fail;
+ }
+
+ mutex_init(&edev->lock);
+
+ edev->spi = spi_dev_get(spi);
+ edev->pdata = pd;
+
+ sysfs_bin_attr_init(&edev->bin);
+ edev->bin.attr.name = "eeprom";
+ edev->bin.attr.mode = S_IRUSR;
+ edev->bin.read = eeprom_93xx46_bin_read;
+ edev->bin.size = 128;
+ if (!(pd->flags & EE_READONLY)) {
+ edev->bin.write = eeprom_93xx46_bin_write;
+ edev->bin.attr.mode |= S_IWUSR;
+ }
+
+ err = sysfs_create_bin_file(&spi->dev.kobj, &edev->bin);
+ if (err)
+ goto fail;
+
+ dev_info(&spi->dev, "%d-bit eeprom %s\n",
+ (pd->flags & EE_ADDR8) ? 8 : 16,
+ (pd->flags & EE_READONLY) ? "(readonly)" : "");
+
+ if (!(pd->flags & EE_READONLY)) {
+ if (device_create_file(&spi->dev, &dev_attr_erase))
+ dev_err(&spi->dev, "can't create erase interface\n");
+ }
+
+ dev_set_drvdata(&spi->dev, edev);
+ return 0;
+fail:
+ kfree(edev);
+ return err;
+}
+
+static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
+{
+ struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
+
+ if (!(edev->pdata->flags & EE_READONLY))
+ device_remove_file(&spi->dev, &dev_attr_erase);
+
+ sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin);
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(edev);
+ return 0;
+}
+
+static struct spi_driver eeprom_93xx46_driver = {
+ .driver = {
+ .name = "93xx46",
+ .owner = THIS_MODULE,
+ },
+ .probe = eeprom_93xx46_probe,
+ .remove = __devexit_p(eeprom_93xx46_remove),
+};
+
+static int __init eeprom_93xx46_init(void)
+{
+ return spi_register_driver(&eeprom_93xx46_driver);
+}
+module_init(eeprom_93xx46_init);
+
+static void __exit eeprom_93xx46_exit(void)
+{
+ spi_unregister_driver(&eeprom_93xx46_driver);
+}
+module_exit(eeprom_93xx46_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_ALIAS("spi:93xx46");
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
new file mode 100644
index 000000000000..5325a7e70dcf
--- /dev/null
+++ b/drivers/misc/fsa9480.c
@@ -0,0 +1,557 @@
+/*
+ * fsa9480.c - FSA9480 micro USB switch device driver
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Wonguk Jeong <wonguk.jeong@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/module.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_data/fsa9480.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+/* FSA9480 I2C registers */
+#define FSA9480_REG_DEVID 0x01
+#define FSA9480_REG_CTRL 0x02
+#define FSA9480_REG_INT1 0x03
+#define FSA9480_REG_INT2 0x04
+#define FSA9480_REG_INT1_MASK 0x05
+#define FSA9480_REG_INT2_MASK 0x06
+#define FSA9480_REG_ADC 0x07
+#define FSA9480_REG_TIMING1 0x08
+#define FSA9480_REG_TIMING2 0x09
+#define FSA9480_REG_DEV_T1 0x0a
+#define FSA9480_REG_DEV_T2 0x0b
+#define FSA9480_REG_BTN1 0x0c
+#define FSA9480_REG_BTN2 0x0d
+#define FSA9480_REG_CK 0x0e
+#define FSA9480_REG_CK_INT1 0x0f
+#define FSA9480_REG_CK_INT2 0x10
+#define FSA9480_REG_CK_INTMASK1 0x11
+#define FSA9480_REG_CK_INTMASK2 0x12
+#define FSA9480_REG_MANSW1 0x13
+#define FSA9480_REG_MANSW2 0x14
+
+/* Control */
+#define CON_SWITCH_OPEN (1 << 4)
+#define CON_RAW_DATA (1 << 3)
+#define CON_MANUAL_SW (1 << 2)
+#define CON_WAIT (1 << 1)
+#define CON_INT_MASK (1 << 0)
+#define CON_MASK (CON_SWITCH_OPEN | CON_RAW_DATA | \
+ CON_MANUAL_SW | CON_WAIT)
+
+/* Device Type 1 */
+#define DEV_USB_OTG (1 << 7)
+#define DEV_DEDICATED_CHG (1 << 6)
+#define DEV_USB_CHG (1 << 5)
+#define DEV_CAR_KIT (1 << 4)
+#define DEV_UART (1 << 3)
+#define DEV_USB (1 << 2)
+#define DEV_AUDIO_2 (1 << 1)
+#define DEV_AUDIO_1 (1 << 0)
+
+#define DEV_T1_USB_MASK (DEV_USB_OTG | DEV_USB)
+#define DEV_T1_UART_MASK (DEV_UART)
+#define DEV_T1_CHARGER_MASK (DEV_DEDICATED_CHG | DEV_USB_CHG)
+
+/* Device Type 2 */
+#define DEV_AV (1 << 6)
+#define DEV_TTY (1 << 5)
+#define DEV_PPD (1 << 4)
+#define DEV_JIG_UART_OFF (1 << 3)
+#define DEV_JIG_UART_ON (1 << 2)
+#define DEV_JIG_USB_OFF (1 << 1)
+#define DEV_JIG_USB_ON (1 << 0)
+
+#define DEV_T2_USB_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON)
+#define DEV_T2_UART_MASK (DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
+#define DEV_T2_JIG_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON | \
+ DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
+
+/*
+ * Manual Switch
+ * D- [7:5] / D+ [4:2]
+ * 000: Open all / 001: USB / 010: AUDIO / 011: UART / 100: V_AUDIO
+ */
+#define SW_VAUDIO ((4 << 5) | (4 << 2))
+#define SW_UART ((3 << 5) | (3 << 2))
+#define SW_AUDIO ((2 << 5) | (2 << 2))
+#define SW_DHOST ((1 << 5) | (1 << 2))
+#define SW_AUTO ((0 << 5) | (0 << 2))
+
+/* Interrupt 1 */
+#define INT_DETACH (1 << 1)
+#define INT_ATTACH (1 << 0)
+
+struct fsa9480_usbsw {
+ struct i2c_client *client;
+ struct fsa9480_platform_data *pdata;
+ int dev1;
+ int dev2;
+ int mansw;
+};
+
+static struct fsa9480_usbsw *chip;
+
+static int fsa9480_write_reg(struct i2c_client *client,
+ int reg, int value)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, reg, value);
+
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ return ret;
+}
+
+static int fsa9480_read_reg(struct i2c_client *client, int reg)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ return ret;
+}
+
+static int fsa9480_read_irq(struct i2c_client *client, int *value)
+{
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client,
+ FSA9480_REG_INT1, 2, (u8 *)value);
+ *value &= 0xffff;
+
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ return ret;
+}
+
+static void fsa9480_set_switch(const char *buf)
+{
+ struct fsa9480_usbsw *usbsw = chip;
+ struct i2c_client *client = usbsw->client;
+ unsigned int value;
+ unsigned int path = 0;
+
+ value = fsa9480_read_reg(client, FSA9480_REG_CTRL);
+
+ if (!strncmp(buf, "VAUDIO", 6)) {
+ path = SW_VAUDIO;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "UART", 4)) {
+ path = SW_UART;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "AUDIO", 5)) {
+ path = SW_AUDIO;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "DHOST", 5)) {
+ path = SW_DHOST;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "AUTO", 4)) {
+ path = SW_AUTO;
+ value |= CON_MANUAL_SW;
+ } else {
+ printk(KERN_ERR "Wrong command\n");
+ return;
+ }
+
+ usbsw->mansw = path;
+ fsa9480_write_reg(client, FSA9480_REG_MANSW1, path);
+ fsa9480_write_reg(client, FSA9480_REG_CTRL, value);
+}
+
+static ssize_t fsa9480_get_switch(char *buf)
+{
+ struct fsa9480_usbsw *usbsw = chip;
+ struct i2c_client *client = usbsw->client;
+ unsigned int value;
+
+ value = fsa9480_read_reg(client, FSA9480_REG_MANSW1);
+
+ if (value == SW_VAUDIO)
+ return sprintf(buf, "VAUDIO\n");
+ else if (value == SW_UART)
+ return sprintf(buf, "UART\n");
+ else if (value == SW_AUDIO)
+ return sprintf(buf, "AUDIO\n");
+ else if (value == SW_DHOST)
+ return sprintf(buf, "DHOST\n");
+ else if (value == SW_AUTO)
+ return sprintf(buf, "AUTO\n");
+ else
+ return sprintf(buf, "%x", value);
+}
+
+static ssize_t fsa9480_show_device(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev);
+ struct i2c_client *client = usbsw->client;
+ int dev1, dev2;
+
+ dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
+ dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
+
+ if (!dev1 && !dev2)
+ return sprintf(buf, "NONE\n");
+
+ /* USB */
+ if (dev1 & DEV_T1_USB_MASK || dev2 & DEV_T2_USB_MASK)
+ return sprintf(buf, "USB\n");
+
+ /* UART */
+ if (dev1 & DEV_T1_UART_MASK || dev2 & DEV_T2_UART_MASK)
+ return sprintf(buf, "UART\n");
+
+ /* CHARGER */
+ if (dev1 & DEV_T1_CHARGER_MASK)
+ return sprintf(buf, "CHARGER\n");
+
+ /* JIG */
+ if (dev2 & DEV_T2_JIG_MASK)
+ return sprintf(buf, "JIG\n");
+
+ return sprintf(buf, "UNKNOWN\n");
+}
+
+static ssize_t fsa9480_show_manualsw(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return fsa9480_get_switch(buf);
+
+}
+
+static ssize_t fsa9480_set_manualsw(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ fsa9480_set_switch(buf);
+
+ return count;
+}
+
+static DEVICE_ATTR(device, S_IRUGO, fsa9480_show_device, NULL);
+static DEVICE_ATTR(switch, S_IRUGO | S_IWUSR,
+ fsa9480_show_manualsw, fsa9480_set_manualsw);
+
+static struct attribute *fsa9480_attributes[] = {
+ &dev_attr_device.attr,
+ &dev_attr_switch.attr,
+ NULL
+};
+
+static const struct attribute_group fsa9480_group = {
+ .attrs = fsa9480_attributes,
+};
+
+static void fsa9480_detect_dev(struct fsa9480_usbsw *usbsw, int intr)
+{
+ int val1, val2, ctrl;
+ struct fsa9480_platform_data *pdata = usbsw->pdata;
+ struct i2c_client *client = usbsw->client;
+
+ val1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
+ val2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
+ ctrl = fsa9480_read_reg(client, FSA9480_REG_CTRL);
+
+ dev_info(&client->dev, "intr: 0x%x, dev1: 0x%x, dev2: 0x%x\n",
+ intr, val1, val2);
+
+ if (!intr)
+ goto out;
+
+ if (intr & INT_ATTACH) { /* Attached */
+ /* USB */
+ if (val1 & DEV_T1_USB_MASK || val2 & DEV_T2_USB_MASK) {
+ if (pdata->usb_cb)
+ pdata->usb_cb(FSA9480_ATTACHED);
+
+ if (usbsw->mansw) {
+ fsa9480_write_reg(client,
+ FSA9480_REG_MANSW1, usbsw->mansw);
+ }
+ }
+
+ /* UART */
+ if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) {
+ if (pdata->uart_cb)
+ pdata->uart_cb(FSA9480_ATTACHED);
+
+ if (!(ctrl & CON_MANUAL_SW)) {
+ fsa9480_write_reg(client,
+ FSA9480_REG_MANSW1, SW_UART);
+ }
+ }
+
+ /* CHARGER */
+ if (val1 & DEV_T1_CHARGER_MASK) {
+ if (pdata->charger_cb)
+ pdata->charger_cb(FSA9480_ATTACHED);
+ }
+
+ /* JIG */
+ if (val2 & DEV_T2_JIG_MASK) {
+ if (pdata->jig_cb)
+ pdata->jig_cb(FSA9480_ATTACHED);
+ }
+ } else if (intr & INT_DETACH) { /* Detached */
+ /* USB */
+ if (usbsw->dev1 & DEV_T1_USB_MASK ||
+ usbsw->dev2 & DEV_T2_USB_MASK) {
+ if (pdata->usb_cb)
+ pdata->usb_cb(FSA9480_DETACHED);
+ }
+
+ /* UART */
+ if (usbsw->dev1 & DEV_T1_UART_MASK ||
+ usbsw->dev2 & DEV_T2_UART_MASK) {
+ if (pdata->uart_cb)
+ pdata->uart_cb(FSA9480_DETACHED);
+ }
+
+ /* CHARGER */
+ if (usbsw->dev1 & DEV_T1_CHARGER_MASK) {
+ if (pdata->charger_cb)
+ pdata->charger_cb(FSA9480_DETACHED);
+ }
+
+ /* JIG */
+ if (usbsw->dev2 & DEV_T2_JIG_MASK) {
+ if (pdata->jig_cb)
+ pdata->jig_cb(FSA9480_DETACHED);
+ }
+ }
+
+ usbsw->dev1 = val1;
+ usbsw->dev2 = val2;
+
+out:
+ ctrl &= ~CON_INT_MASK;
+ fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl);
+}
+
+static irqreturn_t fsa9480_irq_handler(int irq, void *data)
+{
+ struct fsa9480_usbsw *usbsw = data;
+ struct i2c_client *client = usbsw->client;
+ int intr;
+
+ /* clear interrupt */
+ fsa9480_read_irq(client, &intr);
+
+ /* device detection */
+ fsa9480_detect_dev(usbsw, intr);
+
+ return IRQ_HANDLED;
+}
+
+static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
+{
+ struct fsa9480_platform_data *pdata = usbsw->pdata;
+ struct i2c_client *client = usbsw->client;
+ int ret;
+ int intr;
+ unsigned int ctrl = CON_MASK;
+
+ /* clear interrupt */
+ fsa9480_read_irq(client, &intr);
+
+ /* unmask interrupt (attach/detach only) */
+ fsa9480_write_reg(client, FSA9480_REG_INT1_MASK, 0xfc);
+ fsa9480_write_reg(client, FSA9480_REG_INT2_MASK, 0x1f);
+
+ usbsw->mansw = fsa9480_read_reg(client, FSA9480_REG_MANSW1);
+
+ if (usbsw->mansw)
+ ctrl &= ~CON_MANUAL_SW; /* Manual Switching Mode */
+
+ fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl);
+
+ if (pdata && pdata->cfg_gpio)
+ pdata->cfg_gpio();
+
+ if (client->irq) {
+ ret = request_threaded_irq(client->irq, NULL,
+ fsa9480_irq_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "fsa9480 micro USB", usbsw);
+ if (ret) {
+ dev_err(&client->dev, "failed to reqeust IRQ\n");
+ return ret;
+ }
+
+ device_init_wakeup(&client->dev, pdata->wakeup);
+ }
+
+ return 0;
+}
+
+static int __devinit fsa9480_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct fsa9480_usbsw *usbsw;
+ int ret = 0;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+ usbsw = kzalloc(sizeof(struct fsa9480_usbsw), GFP_KERNEL);
+ if (!usbsw) {
+ dev_err(&client->dev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ usbsw->client = client;
+ usbsw->pdata = client->dev.platform_data;
+
+ chip = usbsw;
+
+ i2c_set_clientdata(client, usbsw);
+
+ ret = fsa9480_irq_init(usbsw);
+ if (ret)
+ goto fail1;
+
+ ret = sysfs_create_group(&client->dev.kobj, &fsa9480_group);
+ if (ret) {
+ dev_err(&client->dev,
+ "failed to create fsa9480 attribute group\n");
+ goto fail2;
+ }
+
+ /* ADC Detect Time: 500ms */
+ fsa9480_write_reg(client, FSA9480_REG_TIMING1, 0x6);
+
+ if (chip->pdata->reset_cb)
+ chip->pdata->reset_cb();
+
+ /* device detection */
+ fsa9480_detect_dev(usbsw, INT_ATTACH);
+
+ pm_runtime_set_active(&client->dev);
+
+ return 0;
+
+fail2:
+ if (client->irq)
+ free_irq(client->irq, NULL);
+fail1:
+ i2c_set_clientdata(client, NULL);
+ kfree(usbsw);
+ return ret;
+}
+
+static int __devexit fsa9480_remove(struct i2c_client *client)
+{
+ struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+ if (client->irq)
+ free_irq(client->irq, NULL);
+ i2c_set_clientdata(client, NULL);
+
+ sysfs_remove_group(&client->dev.kobj, &fsa9480_group);
+ device_init_wakeup(&client->dev, 0);
+ kfree(usbsw);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int fsa9480_suspend(struct i2c_client *client, pm_message_t state)
+{
+ struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+ struct fsa9480_platform_data *pdata = usbsw->pdata;
+
+ if (device_may_wakeup(&client->dev) && client->irq)
+ enable_irq_wake(client->irq);
+
+ if (pdata->usb_power)
+ pdata->usb_power(0);
+
+ return 0;
+}
+
+static int fsa9480_resume(struct i2c_client *client)
+{
+ struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+ int dev1, dev2;
+
+ if (device_may_wakeup(&client->dev) && client->irq)
+ disable_irq_wake(client->irq);
+
+ /*
+ * Clear Pending interrupt. Note that detect_dev does what
+ * the interrupt handler does. So, we don't miss pending and
+ * we reenable interrupt if there is one.
+ */
+ fsa9480_read_reg(client, FSA9480_REG_INT1);
+ fsa9480_read_reg(client, FSA9480_REG_INT2);
+
+ dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
+ dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
+
+ /* device detection */
+ fsa9480_detect_dev(usbsw, (dev1 || dev2) ? INT_ATTACH : INT_DETACH);
+
+ return 0;
+}
+
+#else
+
+#define fsa9480_suspend NULL
+#define fsa9480_resume NULL
+
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id fsa9480_id[] = {
+ {"fsa9480", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, fsa9480_id);
+
+static struct i2c_driver fsa9480_i2c_driver = {
+ .driver = {
+ .name = "fsa9480",
+ },
+ .probe = fsa9480_probe,
+ .remove = __devexit_p(fsa9480_remove),
+ .resume = fsa9480_resume,
+ .suspend = fsa9480_suspend,
+ .id_table = fsa9480_id,
+};
+
+static int __init fsa9480_init(void)
+{
+ return i2c_add_driver(&fsa9480_i2c_driver);
+}
+module_init(fsa9480_init);
+
+static void __exit fsa9480_exit(void)
+{
+ i2c_del_driver(&fsa9480_i2c_driver);
+}
+module_exit(fsa9480_exit);
+
+MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
+MODULE_DESCRIPTION("FSA9480 USB Switch driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 5fe79df44838..0fd7e77bee29 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -686,6 +686,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
}
if (id->driver_data == 1) { /* EG20T PCH */
+ const char *board_name;
+
retval = sysfs_create_file(&pdev->dev.kobj,
&dev_attr_pch_mac.attr);
if (retval)
@@ -701,7 +703,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
CLKCFG_CANCLK_MASK);
/* quirk for CM-iTC board */
- if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
+ board_name = dmi_get_system_info(DMI_BOARD_NAME);
+ if (board_name && strstr(board_name, "CM-iTC"))
pch_phub_read_modify_write_reg(chip,
(unsigned int)CLKCFG_REG_OFFSET,
CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV |
@@ -732,6 +735,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
* Device8(GbE)
*/
iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14);
+ /* set the interrupt delay value */
+ iowrite32(0x25, chip->pch_phub_base_address + 0x140);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
@@ -749,8 +754,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
* Device6(SATA 2):f
*/
iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14);
- /* set the interrupt delay value */
- iowrite32(0x25, chip->pch_phub_base_address + 0x140);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index b05db55c8c8e..21b28fc6d912 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -26,7 +26,7 @@
#include <linux/sched.h>
#include <linux/mutex.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#define PHANTOM_VERSION "n0.9.8"
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index 374dfcfccd07..8653bd0b1a33 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -146,45 +146,54 @@ static void pti_write_to_aperture(struct pti_masterchannel *mc,
/**
* pti_control_frame_built_and_sent()- control frame build and send function.
*
- * @mc: The master / channel structure on which the function
- * built a control frame.
+ * @mc: The master / channel structure on which the function
+ * built a control frame.
+ * @thread_name: The thread name associated with the master / channel or
+ * 'NULL' if using the 'current' global variable.
*
* To be able to post process the PTI contents on host side, a control frame
* is added before sending any PTI content. So the host side knows on
* each PTI frame the name of the thread using a dedicated master / channel.
- * The thread name is retrieved from the 'current' global variable.
+ * The thread name is retrieved from 'current' global variable if 'thread_name'
+ * is 'NULL', else it is retrieved from 'thread_name' parameter.
* This function builds this frame and sends it to a master ID CONTROL_ID.
* The overhead is only 32 bytes since the driver only writes to HW
* in 32 byte chunks.
*/
-
-static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc)
+static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc,
+ const char *thread_name)
{
struct pti_masterchannel mccontrol = {.master = CONTROL_ID,
.channel = 0};
+ const char *thread_name_p;
const char *control_format = "%3d %3d %s";
u8 control_frame[CONTROL_FRAME_LEN];
- /*
- * Since we access the comm member in current's task_struct,
- * we only need to be as large as what 'comm' in that
- * structure is.
- */
- char comm[TASK_COMM_LEN];
+ if (!thread_name) {
+ /*
+ * Since we access the comm member in current's task_struct,
+ * we only need to be as large as what 'comm' in that
+ * structure is.
+ */
+ char comm[TASK_COMM_LEN];
- if (!in_interrupt())
- get_task_comm(comm, current);
- else
- strncpy(comm, "Interrupt", TASK_COMM_LEN);
+ if (!in_interrupt())
+ get_task_comm(comm, current);
+ else
+ strncpy(comm, "Interrupt", TASK_COMM_LEN);
- /* Absolutely ensure our buffer is zero terminated. */
- comm[TASK_COMM_LEN-1] = 0;
+ /* Absolutely ensure our buffer is zero terminated. */
+ comm[TASK_COMM_LEN-1] = 0;
+ thread_name_p = comm;
+ } else {
+ thread_name_p = thread_name;
+ }
mccontrol.channel = pti_control_channel;
pti_control_channel = (pti_control_channel + 1) & 0x7f;
snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master,
- mc->channel, comm);
+ mc->channel, thread_name_p);
pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame));
}
@@ -206,18 +215,20 @@ static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
const unsigned char *buf,
int len)
{
- pti_control_frame_built_and_sent(mc);
+ pti_control_frame_built_and_sent(mc, NULL);
pti_write_to_aperture(mc, (u8 *)buf, len);
}
/**
* get_id()- Allocate a master and channel ID.
*
- * @id_array: an array of bits representing what channel
- * id's are allocated for writing.
- * @max_ids: The max amount of available write IDs to use.
- * @base_id: The starting SW channel ID, based on the Intel
- * PTI arch.
+ * @id_array: an array of bits representing what channel
+ * id's are allocated for writing.
+ * @max_ids: The max amount of available write IDs to use.
+ * @base_id: The starting SW channel ID, based on the Intel
+ * PTI arch.
+ * @thread_name: The thread name associated with the master / channel or
+ * 'NULL' if using the 'current' global variable.
*
* Returns:
* pti_masterchannel struct with master, channel ID address
@@ -227,7 +238,10 @@ static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
* channel id. The bit is one if the id is taken and 0 if free. For
* every master there are 128 channel id's.
*/
-static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
+static struct pti_masterchannel *get_id(u8 *id_array,
+ int max_ids,
+ int base_id,
+ const char *thread_name)
{
struct pti_masterchannel *mc;
int i, j, mask;
@@ -257,7 +271,7 @@ static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
mc->master = base_id;
mc->channel = ((i & 0xf)<<3) + j;
/* write new master Id / channel Id allocation to channel control */
- pti_control_frame_built_and_sent(mc);
+ pti_control_frame_built_and_sent(mc, thread_name);
return mc;
}
@@ -273,18 +287,22 @@ static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
* a master, channel ID address
* to write to PTI HW.
*
- * @type: 0- request Application master, channel aperture ID write address.
- * 1- request OS master, channel aperture ID write
- * address.
- * 2- request Modem master, channel aperture ID
- * write address.
- * Other values, error.
+ * @type: 0- request Application master, channel aperture ID
+ * write address.
+ * 1- request OS master, channel aperture ID write
+ * address.
+ * 2- request Modem master, channel aperture ID
+ * write address.
+ * Other values, error.
+ * @thread_name: The thread name associated with the master / channel or
+ * 'NULL' if using the 'current' global variable.
*
* Returns:
* pti_masterchannel struct
* 0 for error
*/
-struct pti_masterchannel *pti_request_masterchannel(u8 type)
+struct pti_masterchannel *pti_request_masterchannel(u8 type,
+ const char *thread_name)
{
struct pti_masterchannel *mc;
@@ -293,15 +311,18 @@ struct pti_masterchannel *pti_request_masterchannel(u8 type)
switch (type) {
case 0:
- mc = get_id(drv_data->ia_app, MAX_APP_IDS, APP_BASE_ID);
+ mc = get_id(drv_data->ia_app, MAX_APP_IDS,
+ APP_BASE_ID, thread_name);
break;
case 1:
- mc = get_id(drv_data->ia_os, MAX_OS_IDS, OS_BASE_ID);
+ mc = get_id(drv_data->ia_os, MAX_OS_IDS,
+ OS_BASE_ID, thread_name);
break;
case 2:
- mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS, MODEM_BASE_ID);
+ mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS,
+ MODEM_BASE_ID, thread_name);
break;
default:
mc = NULL;
@@ -445,9 +466,9 @@ static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp)
}
/**
- * pti_tty_intstall()- Used to set up specific master-channels
- * to tty ports for organizational purposes when
- * tracing viewed from debuging tools.
+ * pti_tty_install()- Used to set up specific master-channels
+ * to tty ports for organizational purposes when
+ * tracing viewed from debuging tools.
*
* @driver: tty driver information.
* @tty: tty struct containing pti information.
@@ -472,9 +493,9 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENOMEM;
if (idx == PTITTY_MINOR_START)
- pti_tty_data->mc = pti_request_masterchannel(0);
+ pti_tty_data->mc = pti_request_masterchannel(0, NULL);
else
- pti_tty_data->mc = pti_request_masterchannel(2);
+ pti_tty_data->mc = pti_request_masterchannel(2, NULL);
if (pti_tty_data->mc == NULL) {
kfree(pti_tty_data);
@@ -563,7 +584,7 @@ static int pti_char_open(struct inode *inode, struct file *filp)
* before assigning the value to filp->private_data.
* Slightly easier to debug if this driver needs debugging.
*/
- mc = pti_request_masterchannel(0);
+ mc = pti_request_masterchannel(0, NULL);
if (mc == NULL)
return -ENOMEM;
filp->private_data = mc;
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 6df5a55da110..053d36caf955 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -45,7 +45,7 @@
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.2-k");
+MODULE_VERSION("1.2.1.3-k");
MODULE_ALIAS("dmi:*:svnVMware*:*");
MODULE_ALIAS("vmware_vmmemctl");
MODULE_LICENSE("GPL");
@@ -215,7 +215,6 @@ struct vmballoon {
};
static struct vmballoon balloon;
-static struct workqueue_struct *vmballoon_wq;
/*
* Send "start" command to the host, communicating supported version
@@ -674,7 +673,12 @@ static void vmballoon_work(struct work_struct *work)
vmballoon_deflate(b);
}
- queue_delayed_work(vmballoon_wq, dwork, round_jiffies_relative(HZ));
+ /*
+ * We are using a freezable workqueue so that balloon operations are
+ * stopped while the system transitions to/from sleep/hibernation.
+ */
+ queue_delayed_work(system_freezable_wq,
+ dwork, round_jiffies_relative(HZ));
}
/*
@@ -785,12 +789,6 @@ static int __init vmballoon_init(void)
if (x86_hyper != &x86_hyper_vmware)
return -ENODEV;
- vmballoon_wq = create_freezable_workqueue("vmmemctl");
- if (!vmballoon_wq) {
- pr_err("failed to create workqueue\n");
- return -ENOMEM;
- }
-
INIT_LIST_HEAD(&balloon.pages);
INIT_LIST_HEAD(&balloon.refused_pages);
@@ -805,34 +803,27 @@ static int __init vmballoon_init(void)
*/
if (!vmballoon_send_start(&balloon)) {
pr_err("failed to send start command to the host\n");
- error = -EIO;
- goto fail;
+ return -EIO;
}
if (!vmballoon_send_guest_id(&balloon)) {
pr_err("failed to send guest ID to the host\n");
- error = -EIO;
- goto fail;
+ return -EIO;
}
error = vmballoon_debugfs_init(&balloon);
if (error)
- goto fail;
+ return error;
- queue_delayed_work(vmballoon_wq, &balloon.dwork, 0);
+ queue_delayed_work(system_freezable_wq, &balloon.dwork, 0);
return 0;
-
-fail:
- destroy_workqueue(vmballoon_wq);
- return error;
}
module_init(vmballoon_init);
static void __exit vmballoon_exit(void)
{
cancel_delayed_work_sync(&balloon.dwork);
- destroy_workqueue(vmballoon_wq);
vmballoon_debugfs_exit(&balloon);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index f85e42224559..1ff5486213fb 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -106,6 +106,16 @@ struct mmc_blk_data {
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_ABORT,
+};
+
module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
@@ -427,14 +437,6 @@ static const struct block_device_operations mmc_bdops = {
#endif
};
-struct mmc_blk_request {
- struct mmc_request mrq;
- struct mmc_command sbc;
- struct mmc_command cmd;
- struct mmc_command stop;
- struct mmc_data data;
-};
-
static inline int mmc_blk_part_switch(struct mmc_card *card,
struct mmc_blk_data *md)
{
@@ -525,7 +527,20 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
return result;
}
-static u32 get_card_status(struct mmc_card *card, struct request *req)
+static int send_stop(struct mmc_card *card, u32 *status)
+{
+ struct mmc_command cmd = {0};
+ int err;
+
+ cmd.opcode = MMC_STOP_TRANSMISSION;
+ cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+ err = mmc_wait_for_cmd(card->host, &cmd, 5);
+ if (err == 0)
+ *status = cmd.resp[0];
+ return err;
+}
+
+static int get_card_status(struct mmc_card *card, u32 *status, int retries)
{
struct mmc_command cmd = {0};
int err;
@@ -534,11 +549,141 @@ static u32 get_card_status(struct mmc_card *card, struct request *req)
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);
+ err = mmc_wait_for_cmd(card->host, &cmd, retries);
+ if (err == 0)
+ *status = cmd.resp[0];
+ return err;
+}
+
+#define ERR_RETRY 2
+#define ERR_ABORT 1
+#define ERR_CONTINUE 0
+
+static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
+ bool status_valid, u32 status)
+{
+ switch (error) {
+ case -EILSEQ:
+ /* response crc error, retry the r/w cmd */
+ pr_err("%s: %s sending %s command, card status %#x\n",
+ req->rq_disk->disk_name, "response CRC error",
+ name, status);
+ return ERR_RETRY;
+
+ case -ETIMEDOUT:
+ pr_err("%s: %s sending %s command, card status %#x\n",
+ req->rq_disk->disk_name, "timed out", name, status);
+
+ /* If the status cmd initially failed, retry the r/w cmd */
+ if (!status_valid)
+ return ERR_RETRY;
+
+ /*
+ * If it was a r/w cmd crc error, or illegal command
+ * (eg, issued in wrong state) then retry - we should
+ * have corrected the state problem above.
+ */
+ if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND))
+ return ERR_RETRY;
+
+ /* Otherwise abort the command */
+ return ERR_ABORT;
+
+ default:
+ /* We don't understand the error code the driver gave us */
+ pr_err("%s: unknown error %d sending read/write command, card status %#x\n",
+ req->rq_disk->disk_name, error, status);
+ return ERR_ABORT;
+ }
+}
+
+/*
+ * Initial r/w and stop cmd error recovery.
+ * We don't know whether the card received the r/w cmd or not, so try to
+ * restore things back to a sane state. Essentially, we do this as follows:
+ * - Obtain card status. If the first attempt to obtain card status fails,
+ * the status word will reflect the failed status cmd, not the failed
+ * r/w cmd. If we fail to obtain card status, it suggests we can no
+ * longer communicate with the card.
+ * - Check the card state. If the card received the cmd but there was a
+ * transient problem with the response, it might still be in a data transfer
+ * mode. Try to send it a stop command. If this fails, we can't recover.
+ * - If the r/w cmd failed due to a response CRC error, it was probably
+ * transient, so retry the cmd.
+ * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry.
+ * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or
+ * illegal cmd, retry.
+ * 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)
+{
+ bool prev_cmd_status_valid = true;
+ u32 status, stop_status = 0;
+ int err, retry;
+
+ /*
+ * Try to get card status which indicates both the card state
+ * and why there was no response. If the first attempt fails,
+ * we can't be sure the returned status is for the r/w command.
+ */
+ for (retry = 2; retry >= 0; retry--) {
+ err = get_card_status(card, &status, 0);
+ if (!err)
+ break;
+
+ prev_cmd_status_valid = false;
+ pr_err("%s: error %d sending status command, %sing\n",
+ req->rq_disk->disk_name, err, retry ? "retry" : "abort");
+ }
+
+ /* We couldn't get a response from the card. Give up. */
if (err)
- printk(KERN_ERR "%s: error %d sending status command",
- req->rq_disk->disk_name, err);
- return cmd.resp[0];
+ return ERR_ABORT;
+
+ /*
+ * Check the current card state. If it is in some data transfer
+ * mode, tell it to stop (and hopefully transition back to TRAN.)
+ */
+ if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
+ R1_CURRENT_STATE(status) == R1_STATE_RCV) {
+ err = send_stop(card, &stop_status);
+ if (err)
+ pr_err("%s: error %d sending stop command\n",
+ req->rq_disk->disk_name, err);
+
+ /*
+ * If the stop cmd also timed out, the card is probably
+ * not present, so abort. Other errors are bad news too.
+ */
+ if (err)
+ return ERR_ABORT;
+ }
+
+ /* Check for set block count errors */
+ if (brq->sbc.error)
+ return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error,
+ prev_cmd_status_valid, status);
+
+ /* Check for r/w command errors */
+ if (brq->cmd.error)
+ return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error,
+ prev_cmd_status_valid, status);
+
+ /* 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,
+ brq->cmd.resp[0], status);
+
+ /*
+ * Subsitute in our own stop status as this will give the error
+ * state which happened during the execution of the r/w command.
+ */
+ if (stop_status) {
+ brq->stop.resp[0] = stop_status;
+ brq->stop.error = 0;
+ }
+ return ERR_CONTINUE;
}
static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
@@ -669,240 +814,324 @@ static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
}
}
-static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
+#define CMD_ERRORS \
+ (R1_OUT_OF_RANGE | /* Command argument out of range */ \
+ R1_ADDRESS_ERROR | /* Misaligned address */ \
+ R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\
+ R1_WP_VIOLATION | /* Tried to write to protected block */ \
+ R1_CC_ERROR | /* Card controller error */ \
+ R1_ERROR) /* General/unknown error */
+
+static int mmc_blk_err_check(struct mmc_card *card,
+ struct mmc_async_req *areq)
{
- struct mmc_blk_data *md = mq->data;
- struct mmc_card *card = md->queue.card;
- struct mmc_blk_request brq;
- int ret = 1, disable_multi = 0;
+ 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;
/*
- * Reliable writes are used to implement Forced Unit Access and
- * REQ_META accesses, and are supported only on MMCs.
+ * sbc.error indicates a problem with the set block count
+ * command. No data will have been transferred.
+ *
+ * cmd.error indicates a problem with the r/w command. No
+ * data will have been transferred.
+ *
+ * stop.error indicates a problem with the stop command. Data
+ * may have been transferred, or may still be transferring.
*/
- bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
- (req->cmd_flags & REQ_META)) &&
- (rq_data_dir(req) == WRITE) &&
- (md->flags & MMC_BLK_REL_WR);
+ if (brq->sbc.error || brq->cmd.error || brq->stop.error) {
+ switch (mmc_blk_cmd_recovery(card, req, brq)) {
+ case ERR_RETRY:
+ return MMC_BLK_RETRY;
+ case ERR_ABORT:
+ return MMC_BLK_ABORT;
+ case ERR_CONTINUE:
+ break;
+ }
+ }
- do {
- struct mmc_command cmd = {0};
- u32 readcmd, writecmd, status = 0;
-
- memset(&brq, 0, sizeof(struct mmc_blk_request));
- brq.mrq.cmd = &brq.cmd;
- brq.mrq.data = &brq.data;
-
- brq.cmd.arg = blk_rq_pos(req);
- if (!mmc_card_blockaddr(card))
- brq.cmd.arg <<= 9;
- brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- brq.data.blksz = 512;
- brq.stop.opcode = MMC_STOP_TRANSMISSION;
- brq.stop.arg = 0;
- brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
- brq.data.blocks = blk_rq_sectors(req);
+ /*
+ * Check for errors relating to the execution of the
+ * initial command - such as address errors. No data
+ * has been transferred.
+ */
+ if (brq->cmd.resp[0] & CMD_ERRORS) {
+ pr_err("%s: r/w command failed, status = %#x\n",
+ req->rq_disk->disk_name, brq->cmd.resp[0]);
+ return MMC_BLK_ABORT;
+ }
- /*
- * The block layer doesn't support all sector count
- * restrictions, so we need to be prepared for too big
- * requests.
- */
- if (brq.data.blocks > card->host->max_blk_count)
- brq.data.blocks = card->host->max_blk_count;
+ /*
+ * Everything else is either success, or a data error of some
+ * kind. If it was a write, we may have transitioned to
+ * program mode, which we have to wait for it to complete.
+ */
+ if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
+ u32 status;
+ do {
+ int err = get_card_status(card, &status, 5);
+ if (err) {
+ printk(KERN_ERR "%s: error %d requesting status\n",
+ req->rq_disk->disk_name, err);
+ return MMC_BLK_CMD_ERR;
+ }
+ /*
+ * Some cards mishandle the status bits,
+ * so make sure to check both the busy
+ * indication and the card state.
+ */
+ } while (!(status & R1_READY_FOR_DATA) ||
+ (R1_CURRENT_STATE(status) == R1_STATE_PRG));
+ }
- /*
- * 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.error) {
+ pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
+ req->rq_disk->disk_name, brq->data.error,
+ (unsigned)blk_rq_pos(req),
+ (unsigned)blk_rq_sectors(req),
+ brq->cmd.resp[0], brq->stop.resp[0]);
- if (brq.data.blocks > 1 || do_rel_wr) {
- /* SPI multiblock writes terminate using a special
- * token, not a STOP_TRANSMISSION request.
- */
- if (!mmc_host_is_spi(card->host) ||
- rq_data_dir(req) == READ)
- brq.mrq.stop = &brq.stop;
- readcmd = MMC_READ_MULTIPLE_BLOCK;
- writecmd = MMC_WRITE_MULTIPLE_BLOCK;
- } else {
- brq.mrq.stop = NULL;
- readcmd = MMC_READ_SINGLE_BLOCK;
- writecmd = MMC_WRITE_BLOCK;
- }
if (rq_data_dir(req) == READ) {
- brq.cmd.opcode = readcmd;
- brq.data.flags |= MMC_DATA_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;
+ }
+ return MMC_BLK_DATA_ERR;
} else {
- brq.cmd.opcode = writecmd;
- brq.data.flags |= MMC_DATA_WRITE;
+ return MMC_BLK_CMD_ERR;
}
+ }
- if (do_rel_wr)
- mmc_apply_rel_rw(&brq, card, req);
+ if (ret == MMC_BLK_SUCCESS &&
+ blk_rq_bytes(req) != brq->data.bytes_xfered)
+ ret = MMC_BLK_PARTIAL;
- /*
- * Pre-defined multi-block transfers are preferable to
- * open ended-ones (and necessary for reliable writes).
- * However, it is not sufficient to just send CMD23,
- * and avoid the final CMD12, as on an error condition
- * CMD12 (stop) needs to be sent anyway. This, coupled
- * with Auto-CMD23 enhancements provided by some
- * hosts, means that the complexity of dealing
- * with this is best left to the host. If CMD23 is
- * supported by card and host, we'll fill sbc in and let
- * the host deal with handling it correctly. This means
- * that for hosts that don't expose MMC_CAP_CMD23, no
- * change of behavior will be observed.
- *
- * N.B: Some MMC cards experience perf degradation.
- * We'll avoid using CMD23-bounded multiblock writes for
- * these, while retaining features like reliable writes.
- */
+ return ret;
+}
- if ((md->flags & MMC_BLK_CMD23) &&
- mmc_op_multi(brq.cmd.opcode) &&
- (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
- brq.sbc.opcode = MMC_SET_BLOCK_COUNT;
- brq.sbc.arg = brq.data.blocks |
- (do_rel_wr ? (1 << 31) : 0);
- brq.sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
- brq.mrq.sbc = &brq.sbc;
- }
+static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
+ struct mmc_card *card,
+ int disable_multi,
+ struct mmc_queue *mq)
+{
+ u32 readcmd, writecmd;
+ struct mmc_blk_request *brq = &mqrq->brq;
+ struct request *req = mqrq->req;
+ struct mmc_blk_data *md = mq->data;
- mmc_set_data_timeout(&brq.data, card);
+ /*
+ * Reliable writes are used to implement Forced Unit Access and
+ * REQ_META accesses, and are supported only on MMCs.
+ */
+ bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
+ (req->cmd_flags & REQ_META)) &&
+ (rq_data_dir(req) == WRITE) &&
+ (md->flags & MMC_BLK_REL_WR);
- brq.data.sg = mq->sg;
- brq.data.sg_len = mmc_queue_map_sg(mq);
+ memset(brq, 0, sizeof(struct mmc_blk_request));
+ brq->mrq.cmd = &brq->cmd;
+ brq->mrq.data = &brq->data;
- /*
- * Adjust the sg list so it is the same size as the
- * request.
+ brq->cmd.arg = blk_rq_pos(req);
+ if (!mmc_card_blockaddr(card))
+ brq->cmd.arg <<= 9;
+ brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+ brq->data.blksz = 512;
+ brq->stop.opcode = MMC_STOP_TRANSMISSION;
+ brq->stop.arg = 0;
+ brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+ brq->data.blocks = blk_rq_sectors(req);
+
+ /*
+ * The block layer doesn't support all sector count
+ * restrictions, so we need to be prepared for too big
+ * requests.
+ */
+ 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 || do_rel_wr) {
+ /* SPI multiblock writes terminate using a special
+ * token, not a STOP_TRANSMISSION request.
*/
- if (brq.data.blocks != blk_rq_sectors(req)) {
- int i, data_size = brq.data.blocks << 9;
- struct scatterlist *sg;
-
- for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
- data_size -= sg->length;
- if (data_size <= 0) {
- sg->length += data_size;
- i++;
- break;
- }
- }
- brq.data.sg_len = i;
- }
+ if (!mmc_host_is_spi(card->host) ||
+ rq_data_dir(req) == READ)
+ brq->mrq.stop = &brq->stop;
+ readcmd = MMC_READ_MULTIPLE_BLOCK;
+ writecmd = MMC_WRITE_MULTIPLE_BLOCK;
+ } else {
+ brq->mrq.stop = NULL;
+ readcmd = MMC_READ_SINGLE_BLOCK;
+ writecmd = MMC_WRITE_BLOCK;
+ }
+ if (rq_data_dir(req) == READ) {
+ brq->cmd.opcode = readcmd;
+ brq->data.flags |= MMC_DATA_READ;
+ } else {
+ brq->cmd.opcode = writecmd;
+ brq->data.flags |= MMC_DATA_WRITE;
+ }
- mmc_queue_bounce_pre(mq);
+ if (do_rel_wr)
+ mmc_apply_rel_rw(brq, card, req);
- mmc_wait_for_req(card->host, &brq.mrq);
+ /*
+ * Pre-defined multi-block transfers are preferable to
+ * open ended-ones (and necessary for reliable writes).
+ * However, it is not sufficient to just send CMD23,
+ * and avoid the final CMD12, as on an error condition
+ * CMD12 (stop) needs to be sent anyway. This, coupled
+ * with Auto-CMD23 enhancements provided by some
+ * hosts, means that the complexity of dealing
+ * with this is best left to the host. If CMD23 is
+ * supported by card and host, we'll fill sbc in and let
+ * the host deal with handling it correctly. This means
+ * that for hosts that don't expose MMC_CAP_CMD23, no
+ * change of behavior will be observed.
+ *
+ * N.B: Some MMC cards experience perf degradation.
+ * We'll avoid using CMD23-bounded multiblock writes for
+ * these, while retaining features like reliable writes.
+ */
- mmc_queue_bounce_post(mq);
+ if ((md->flags & MMC_BLK_CMD23) &&
+ mmc_op_multi(brq->cmd.opcode) &&
+ (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
+ brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
+ brq->sbc.arg = brq->data.blocks |
+ (do_rel_wr ? (1 << 31) : 0);
+ brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
+ brq->mrq.sbc = &brq->sbc;
+ }
- /*
- * Check for errors here, but don't jump to cmd_err
- * until later as we need to wait for the card to leave
- * programming mode even when things go wrong.
- */
- if (brq.sbc.error || brq.cmd.error ||
- brq.data.error || brq.stop.error) {
- if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
- /* Redo read one sector at a time */
- printk(KERN_WARNING "%s: retrying using single "
- "block read\n", req->rq_disk->disk_name);
- disable_multi = 1;
- continue;
- }
- status = get_card_status(card, req);
- }
+ mmc_set_data_timeout(&brq->data, card);
- if (brq.sbc.error) {
- printk(KERN_ERR "%s: error %d sending SET_BLOCK_COUNT "
- "command, response %#x, card status %#x\n",
- req->rq_disk->disk_name, brq.sbc.error,
- brq.sbc.resp[0], status);
- }
+ brq->data.sg = mqrq->sg;
+ brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
- if (brq.cmd.error) {
- printk(KERN_ERR "%s: error %d sending read/write "
- "command, response %#x, card status %#x\n",
- req->rq_disk->disk_name, brq.cmd.error,
- brq.cmd.resp[0], status);
+ /*
+ * Adjust the sg list so it is the same size as the
+ * request.
+ */
+ if (brq->data.blocks != blk_rq_sectors(req)) {
+ int i, data_size = brq->data.blocks << 9;
+ struct scatterlist *sg;
+
+ for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
+ data_size -= sg->length;
+ if (data_size <= 0) {
+ sg->length += data_size;
+ i++;
+ break;
+ }
}
+ brq->data.sg_len = i;
+ }
- if (brq.data.error) {
- if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
- /* 'Stop' response contains card status */
- status = brq.mrq.stop->resp[0];
- printk(KERN_ERR "%s: error %d transferring data,"
- " sector %u, nr %u, card status %#x\n",
- req->rq_disk->disk_name, brq.data.error,
- (unsigned)blk_rq_pos(req),
- (unsigned)blk_rq_sectors(req), status);
- }
+ mqrq->mmc_active.mrq = &brq->mrq;
+ mqrq->mmc_active.err_check = mmc_blk_err_check;
- if (brq.stop.error) {
- printk(KERN_ERR "%s: error %d sending stop command, "
- "response %#x, card status %#x\n",
- req->rq_disk->disk_name, brq.stop.error,
- brq.stop.resp[0], status);
- }
+ mmc_queue_bounce_pre(mqrq);
+}
- if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
- do {
- int err;
-
- cmd.opcode = MMC_SEND_STATUS;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- err = mmc_wait_for_cmd(card->host, &cmd, 5);
- if (err) {
- printk(KERN_ERR "%s: error %d requesting status\n",
- req->rq_disk->disk_name, err);
- goto cmd_err;
- }
- /*
- * Some cards mishandle the status bits,
- * so make sure to check both the busy
- * indication and the card state.
- */
- } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
- (R1_CURRENT_STATE(cmd.resp[0]) == 7));
-
-#if 0
- if (cmd.resp[0] & ~0x00000900)
- printk(KERN_ERR "%s: status = %08x\n",
- req->rq_disk->disk_name, cmd.resp[0]);
- if (mmc_decode_status(cmd.resp))
- goto cmd_err;
-#endif
- }
+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;
+ enum mmc_blk_status status;
+ struct mmc_queue_req *mq_rq;
+ struct request *req;
+ struct mmc_async_req *areq;
+
+ if (!rqc && !mq->mqrq_prev->req)
+ return 0;
- if (brq.cmd.error || brq.stop.error || brq.data.error) {
- if (rq_data_dir(req) == READ) {
+ do {
+ if (rqc) {
+ mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+ areq = &mq->mqrq_cur->mmc_active;
+ } else
+ areq = NULL;
+ areq = mmc_start_req(card->host, areq, (int *) &status);
+ if (!areq)
+ return 0;
+
+ mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
+ brq = &mq_rq->brq;
+ req = mq_rq->req;
+ mmc_queue_bounce_post(mq_rq);
+
+ switch (status) {
+ case MMC_BLK_SUCCESS:
+ case MMC_BLK_PARTIAL:
+ /*
+ * A block was successfully transferred.
+ */
+ spin_lock_irq(&md->lock);
+ ret = __blk_end_request(req, 0,
+ brq->data.bytes_xfered);
+ spin_unlock_irq(&md->lock);
+ if (status == MMC_BLK_SUCCESS && ret) {
/*
- * After an error, we redo I/O one sector at a
- * time, so we only reach here after trying to
- * read a single sector.
+ * 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.
*/
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, -EIO, brq.data.blksz);
- spin_unlock_irq(&md->lock);
- continue;
+ printk(KERN_ERR "%s BUG rq_tot %d d_xfer %d\n",
+ __func__, blk_rq_bytes(req),
+ brq->data.bytes_xfered);
+ rqc = NULL;
+ goto cmd_abort;
}
+ break;
+ case MMC_BLK_CMD_ERR:
goto cmd_err;
+ case MMC_BLK_RETRY_SINGLE:
+ disable_multi = 1;
+ break;
+ case MMC_BLK_RETRY:
+ if (retry++ < 5)
+ break;
+ case MMC_BLK_ABORT:
+ goto cmd_abort;
+ case MMC_BLK_DATA_ERR:
+ /*
+ * After an error, we redo I/O one sector at a
+ * time, so we only reach here after trying to
+ * read a single sector.
+ */
+ spin_lock_irq(&md->lock);
+ ret = __blk_end_request(req, -EIO,
+ brq->data.blksz);
+ spin_unlock_irq(&md->lock);
+ if (!ret)
+ goto start_new_req;
+ break;
}
- /*
- * A block was successfully transferred.
- */
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
- spin_unlock_irq(&md->lock);
+ if (ret) {
+ /*
+ * In case of a none complete request
+ * prepare it again and resend.
+ */
+ mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq);
+ mmc_start_req(card->host, &mq_rq->mmc_active, NULL);
+ }
} while (ret);
return 1;
@@ -927,15 +1156,22 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
}
} else {
spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
+ ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
spin_unlock_irq(&md->lock);
}
+ cmd_abort:
spin_lock_irq(&md->lock);
while (ret)
ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
spin_unlock_irq(&md->lock);
+ start_new_req:
+ if (rqc) {
+ mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+ mmc_start_req(card->host, &mq->mqrq_cur->mmc_active, NULL);
+ }
+
return 0;
}
@@ -945,26 +1181,37 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
- mmc_claim_host(card->host);
+ if (req && !mq->mqrq_prev->req)
+ /* claim host only for the first request */
+ mmc_claim_host(card->host);
+
ret = mmc_blk_part_switch(card, md);
if (ret) {
ret = 0;
goto out;
}
- if (req->cmd_flags & REQ_DISCARD) {
+ if (req && req->cmd_flags & REQ_DISCARD) {
+ /* complete ongoing async transfer before issuing discard */
+ if (card->host->areq)
+ mmc_blk_issue_rw_rq(mq, NULL);
if (req->cmd_flags & REQ_SECURE)
ret = mmc_blk_issue_secdiscard_rq(mq, req);
else
ret = mmc_blk_issue_discard_rq(mq, req);
- } else if (req->cmd_flags & REQ_FLUSH) {
+ } else if (req && req->cmd_flags & REQ_FLUSH) {
+ /* complete ongoing async transfer before issuing flush */
+ if (card->host->areq)
+ mmc_blk_issue_rw_rq(mq, NULL);
ret = mmc_blk_issue_flush(mq, req);
} else {
ret = mmc_blk_issue_rw_rq(mq, req);
}
out:
- mmc_release_host(card->host);
+ if (!req)
+ /* release host only when there are no more requests */
+ mmc_release_host(card->host);
return ret;
}
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 233cdfae92f4..006a5e9f8ab8 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -148,6 +148,27 @@ struct mmc_test_card {
struct mmc_test_general_result *gr;
};
+enum mmc_test_prep_media {
+ MMC_TEST_PREP_NONE = 0,
+ MMC_TEST_PREP_WRITE_FULL = 1 << 0,
+ MMC_TEST_PREP_ERASE = 1 << 1,
+};
+
+struct mmc_test_multiple_rw {
+ unsigned int *sg_len;
+ unsigned int *bs;
+ unsigned int len;
+ unsigned int size;
+ bool do_write;
+ bool do_nonblock_req;
+ enum mmc_test_prep_media prepare;
+};
+
+struct mmc_test_async_req {
+ struct mmc_async_req areq;
+ struct mmc_test_card *test;
+};
+
/*******************************************************************/
/* General helper functions */
/*******************************************************************/
@@ -367,21 +388,26 @@ out_free:
* Map memory into a scatterlist. Optionally allow the same memory to be
* mapped more than once.
*/
-static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz,
+static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long size,
struct scatterlist *sglist, int repeat,
unsigned int max_segs, unsigned int max_seg_sz,
- unsigned int *sg_len)
+ unsigned int *sg_len, int min_sg_len)
{
struct scatterlist *sg = NULL;
unsigned int i;
+ unsigned long sz = size;
sg_init_table(sglist, max_segs);
+ if (min_sg_len > max_segs)
+ min_sg_len = max_segs;
*sg_len = 0;
do {
for (i = 0; i < mem->cnt; i++) {
unsigned long len = PAGE_SIZE << mem->arr[i].order;
+ if (min_sg_len && (size / min_sg_len < len))
+ len = ALIGN(size / min_sg_len, 512);
if (len > sz)
len = sz;
if (len > max_seg_sz)
@@ -554,11 +580,12 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
printk(KERN_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)\n",
+ "%u.%02u IOPS, sg_len %d)\n",
mmc_hostname(test->card->host), count, sectors, count,
sectors >> 1, (sectors & 1 ? ".5" : ""),
(unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
- rate / 1000, rate / 1024, iops / 100, iops % 100);
+ rate / 1000, rate / 1024, iops / 100, iops % 100,
+ test->area.sg_len);
mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
}
@@ -661,7 +688,7 @@ static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test,
* Checks that a normal transfer didn't have any errors
*/
static int mmc_test_check_result(struct mmc_test_card *test,
- struct mmc_request *mrq)
+ struct mmc_request *mrq)
{
int ret;
@@ -685,6 +712,17 @@ static int mmc_test_check_result(struct mmc_test_card *test,
return ret;
}
+static int mmc_test_check_result_async(struct mmc_card *card,
+ struct mmc_async_req *areq)
+{
+ struct mmc_test_async_req *test_async =
+ container_of(areq, struct mmc_test_async_req, areq);
+
+ mmc_test_wait_busy(test_async->test);
+
+ return mmc_test_check_result(test_async->test, areq->mrq);
+}
+
/*
* Checks that a "short transfer" behaved as expected
*/
@@ -720,6 +758,85 @@ static int mmc_test_check_broken_result(struct mmc_test_card *test,
}
/*
+ * Tests nonblock transfer with certain parameters
+ */
+static void mmc_test_nonblock_reset(struct mmc_request *mrq,
+ struct mmc_command *cmd,
+ struct mmc_command *stop,
+ struct mmc_data *data)
+{
+ memset(mrq, 0, sizeof(struct mmc_request));
+ memset(cmd, 0, sizeof(struct mmc_command));
+ memset(data, 0, sizeof(struct mmc_data));
+ memset(stop, 0, sizeof(struct mmc_command));
+
+ mrq->cmd = cmd;
+ mrq->data = data;
+ mrq->stop = stop;
+}
+static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
+ struct scatterlist *sg, unsigned sg_len,
+ unsigned dev_addr, unsigned blocks,
+ unsigned blksz, int write, int count)
+{
+ struct mmc_request mrq1;
+ struct mmc_command cmd1;
+ struct mmc_command stop1;
+ struct mmc_data data1;
+
+ struct mmc_request mrq2;
+ struct mmc_command cmd2;
+ struct mmc_command stop2;
+ struct mmc_data data2;
+
+ struct mmc_test_async_req test_areq[2];
+ struct mmc_async_req *done_areq;
+ struct mmc_async_req *cur_areq = &test_areq[0].areq;
+ struct mmc_async_req *other_areq = &test_areq[1].areq;
+ int i;
+ int ret;
+
+ test_areq[0].test = test;
+ test_areq[1].test = test;
+
+ mmc_test_nonblock_reset(&mrq1, &cmd1, &stop1, &data1);
+ mmc_test_nonblock_reset(&mrq2, &cmd2, &stop2, &data2);
+
+ cur_areq->mrq = &mrq1;
+ cur_areq->err_check = mmc_test_check_result_async;
+ other_areq->mrq = &mrq2;
+ other_areq->err_check = mmc_test_check_result_async;
+
+ for (i = 0; i < count; i++) {
+ mmc_test_prepare_mrq(test, cur_areq->mrq, sg, sg_len, dev_addr,
+ blocks, blksz, write);
+ done_areq = mmc_start_req(test->card->host, cur_areq, &ret);
+
+ if (ret || (!done_areq && i > 0))
+ goto err;
+
+ if (done_areq) {
+ if (done_areq->mrq == &mrq2)
+ mmc_test_nonblock_reset(&mrq2, &cmd2,
+ &stop2, &data2);
+ else
+ mmc_test_nonblock_reset(&mrq1, &cmd1,
+ &stop1, &data1);
+ }
+ done_areq = cur_areq;
+ cur_areq = other_areq;
+ other_areq = done_areq;
+ dev_addr += blocks;
+ }
+
+ done_areq = mmc_start_req(test->card->host, NULL, &ret);
+
+ return ret;
+err:
+ return ret;
+}
+
+/*
* Tests a basic transfer with certain parameters
*/
static int mmc_test_simple_transfer(struct mmc_test_card *test,
@@ -1302,7 +1419,7 @@ static int mmc_test_no_highmem(struct mmc_test_card *test)
* Map sz bytes so that it can be transferred.
*/
static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
- int max_scatter)
+ int max_scatter, int min_sg_len)
{
struct mmc_test_area *t = &test->area;
int err;
@@ -1315,7 +1432,7 @@ static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
&t->sg_len);
} else {
err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs,
- t->max_seg_sz, &t->sg_len);
+ t->max_seg_sz, &t->sg_len, min_sg_len);
}
if (err)
printk(KERN_INFO "%s: Failed to map sg list\n",
@@ -1336,14 +1453,17 @@ static int mmc_test_area_transfer(struct mmc_test_card *test,
}
/*
- * Map and transfer bytes.
+ * Map and transfer bytes for multiple transfers.
*/
-static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
- unsigned int dev_addr, int write, int max_scatter,
- int timed)
+static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz,
+ unsigned int dev_addr, int write,
+ int max_scatter, int timed, int count,
+ bool nonblock, int min_sg_len)
{
struct timespec ts1, ts2;
- int ret;
+ int ret = 0;
+ int i;
+ struct mmc_test_area *t = &test->area;
/*
* In the case of a maximally scattered transfer, the maximum transfer
@@ -1361,14 +1481,21 @@ static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
sz = max_tfr;
}
- ret = mmc_test_area_map(test, sz, max_scatter);
+ ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len);
if (ret)
return ret;
if (timed)
getnstimeofday(&ts1);
+ if (nonblock)
+ ret = mmc_test_nonblock_transfer(test, t->sg, t->sg_len,
+ dev_addr, t->blocks, 512, write, count);
+ else
+ for (i = 0; i < count && ret == 0; i++) {
+ ret = mmc_test_area_transfer(test, dev_addr, write);
+ dev_addr += sz >> 9;
+ }
- ret = mmc_test_area_transfer(test, dev_addr, write);
if (ret)
return ret;
@@ -1376,11 +1503,19 @@ static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
getnstimeofday(&ts2);
if (timed)
- mmc_test_print_rate(test, sz, &ts1, &ts2);
+ mmc_test_print_avg_rate(test, sz, count, &ts1, &ts2);
return 0;
}
+static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
+ unsigned int dev_addr, int write, int max_scatter,
+ int timed)
+{
+ return mmc_test_area_io_seq(test, sz, dev_addr, write, max_scatter,
+ timed, 1, false, 0);
+}
+
/*
* Write the test area entirely.
*/
@@ -1954,6 +2089,245 @@ static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
return mmc_test_large_seq_perf(test, 1);
}
+static int mmc_test_rw_multiple(struct mmc_test_card *test,
+ struct mmc_test_multiple_rw *tdata,
+ unsigned int reqsize, unsigned int size,
+ int min_sg_len)
+{
+ unsigned int dev_addr;
+ struct mmc_test_area *t = &test->area;
+ int ret = 0;
+
+ /* Set up test area */
+ if (size > mmc_test_capacity(test->card) / 2 * 512)
+ size = mmc_test_capacity(test->card) / 2 * 512;
+ if (reqsize > t->max_tfr)
+ reqsize = t->max_tfr;
+ dev_addr = mmc_test_capacity(test->card) / 4;
+ if ((dev_addr & 0xffff0000))
+ dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
+ else
+ dev_addr &= 0xfffff800; /* Round to 1MiB boundary */
+ if (!dev_addr)
+ goto err;
+
+ if (reqsize > size)
+ return 0;
+
+ /* prepare test area */
+ if (mmc_can_erase(test->card) &&
+ tdata->prepare & MMC_TEST_PREP_ERASE) {
+ ret = mmc_erase(test->card, dev_addr,
+ size / 512, MMC_SECURE_ERASE_ARG);
+ if (ret)
+ ret = mmc_erase(test->card, dev_addr,
+ size / 512, MMC_ERASE_ARG);
+ if (ret)
+ goto err;
+ }
+
+ /* Run test */
+ ret = mmc_test_area_io_seq(test, reqsize, dev_addr,
+ tdata->do_write, 0, 1, size / reqsize,
+ tdata->do_nonblock_req, min_sg_len);
+ if (ret)
+ goto err;
+
+ return ret;
+ err:
+ printk(KERN_INFO "[%s] error\n", __func__);
+ return ret;
+}
+
+static int mmc_test_rw_multiple_size(struct mmc_test_card *test,
+ struct mmc_test_multiple_rw *rw)
+{
+ int ret = 0;
+ int i;
+ void *pre_req = test->card->host->ops->pre_req;
+ void *post_req = test->card->host->ops->post_req;
+
+ 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");
+ return -EINVAL;
+ }
+
+ for (i = 0 ; i < rw->len && ret == 0; i++) {
+ ret = mmc_test_rw_multiple(test, rw, rw->bs[i], rw->size, 0);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+static int mmc_test_rw_multiple_sg_len(struct mmc_test_card *test,
+ struct mmc_test_multiple_rw *rw)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0 ; i < rw->len && ret == 0; i++) {
+ ret = mmc_test_rw_multiple(test, rw, 512*1024, rw->size,
+ rw->sg_len[i]);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+/*
+ * Multiple blocking write 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_write_blocking_perf(struct mmc_test_card *test)
+{
+ unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+ 1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+ struct mmc_test_multiple_rw test_data = {
+ .bs = bs,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(bs),
+ .do_write = true,
+ .do_nonblock_req = false,
+ .prepare = MMC_TEST_PREP_ERASE,
+ };
+
+ return mmc_test_rw_multiple_size(test, &test_data);
+};
+
+/*
+ * Multiple non-blocking write 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_write_nonblock_perf(struct mmc_test_card *test)
+{
+ unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+ 1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+ struct mmc_test_multiple_rw test_data = {
+ .bs = bs,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(bs),
+ .do_write = true,
+ .do_nonblock_req = true,
+ .prepare = MMC_TEST_PREP_ERASE,
+ };
+
+ return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple blocking read 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_read_blocking_perf(struct mmc_test_card *test)
+{
+ unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+ 1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+ struct mmc_test_multiple_rw test_data = {
+ .bs = bs,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(bs),
+ .do_write = false,
+ .do_nonblock_req = false,
+ .prepare = MMC_TEST_PREP_NONE,
+ };
+
+ return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple non-blocking read 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_read_nonblock_perf(struct mmc_test_card *test)
+{
+ unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+ 1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+ struct mmc_test_multiple_rw test_data = {
+ .bs = bs,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(bs),
+ .do_write = false,
+ .do_nonblock_req = true,
+ .prepare = MMC_TEST_PREP_NONE,
+ };
+
+ return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple blocking write 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_wr_blocking_perf(struct mmc_test_card *test)
+{
+ unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+ 1 << 7, 1 << 8, 1 << 9};
+ struct mmc_test_multiple_rw test_data = {
+ .sg_len = sg_len,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(sg_len),
+ .do_write = true,
+ .do_nonblock_req = false,
+ .prepare = MMC_TEST_PREP_ERASE,
+ };
+
+ return mmc_test_rw_multiple_sg_len(test, &test_data);
+};
+
+/*
+ * Multiple non-blocking write 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_wr_nonblock_perf(struct mmc_test_card *test)
+{
+ unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+ 1 << 7, 1 << 8, 1 << 9};
+ struct mmc_test_multiple_rw test_data = {
+ .sg_len = sg_len,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(sg_len),
+ .do_write = true,
+ .do_nonblock_req = true,
+ .prepare = MMC_TEST_PREP_ERASE,
+ };
+
+ return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
+/*
+ * Multiple blocking read 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_r_blocking_perf(struct mmc_test_card *test)
+{
+ unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+ 1 << 7, 1 << 8, 1 << 9};
+ struct mmc_test_multiple_rw test_data = {
+ .sg_len = sg_len,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(sg_len),
+ .do_write = false,
+ .do_nonblock_req = false,
+ .prepare = MMC_TEST_PREP_NONE,
+ };
+
+ return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
+/*
+ * Multiple non-blocking read 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
+{
+ unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+ 1 << 7, 1 << 8, 1 << 9};
+ struct mmc_test_multiple_rw test_data = {
+ .sg_len = sg_len,
+ .size = TEST_AREA_MAX_SIZE,
+ .len = ARRAY_SIZE(sg_len),
+ .do_write = false,
+ .do_nonblock_req = true,
+ .prepare = MMC_TEST_PREP_NONE,
+ };
+
+ return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
static const struct mmc_test_case mmc_test_cases[] = {
{
.name = "Basic write (no data verification)",
@@ -2221,6 +2595,61 @@ static const struct mmc_test_case mmc_test_cases[] = {
.cleanup = mmc_test_area_cleanup,
},
+ {
+ .name = "Write performance with blocking req 4k to 4MB",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_mult_write_blocking_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
+ {
+ .name = "Write performance with non-blocking req 4k to 4MB",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_mult_write_nonblock_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
+ {
+ .name = "Read performance with blocking req 4k to 4MB",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_mult_read_blocking_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
+ {
+ .name = "Read performance with non-blocking req 4k to 4MB",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_mult_read_nonblock_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
+ {
+ .name = "Write performance blocking req 1 to 512 sg elems",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_sglen_wr_blocking_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
+ {
+ .name = "Write performance non-blocking req 1 to 512 sg elems",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_sglen_wr_nonblock_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
+ {
+ .name = "Read performance blocking req 1 to 512 sg elems",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_sglen_r_blocking_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
+ {
+ .name = "Read performance non-blocking req 1 to 512 sg elems",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_profile_sglen_r_nonblock_perf,
+ .cleanup = mmc_test_area_cleanup,
+ },
};
static DEFINE_MUTEX(mmc_test_lock);
@@ -2445,6 +2874,32 @@ static const struct file_operations mmc_test_fops_test = {
.release = single_release,
};
+static int mtf_testlist_show(struct seq_file *sf, void *data)
+{
+ int i;
+
+ mutex_lock(&mmc_test_lock);
+
+ for (i = 0; i < ARRAY_SIZE(mmc_test_cases); i++)
+ seq_printf(sf, "%d:\t%s\n", i+1, mmc_test_cases[i].name);
+
+ mutex_unlock(&mmc_test_lock);
+
+ return 0;
+}
+
+static int mtf_testlist_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mtf_testlist_show, inode->i_private);
+}
+
+static const struct file_operations mmc_test_fops_testlist = {
+ .open = mtf_testlist_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static void mmc_test_free_file_test(struct mmc_card *card)
{
struct mmc_test_dbgfs_file *df, *dfs;
@@ -2476,7 +2931,18 @@ static int mmc_test_register_file_test(struct mmc_card *card)
if (IS_ERR_OR_NULL(file)) {
dev_err(&card->dev,
- "Can't create file. Perhaps debugfs is disabled.\n");
+ "Can't create test. Perhaps debugfs is disabled.\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ if (card->debugfs_root)
+ file = debugfs_create_file("testlist", S_IRUGO,
+ card->debugfs_root, card, &mmc_test_fops_testlist);
+
+ if (IS_ERR_OR_NULL(file)) {
+ dev_err(&card->dev,
+ "Can't create testlist. Perhaps debugfs is disabled.\n");
ret = -ENODEV;
goto err;
}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 6413afa318d2..45fb362e3f01 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -52,14 +52,18 @@ static int mmc_queue_thread(void *d)
down(&mq->thread_sem);
do {
struct request *req = NULL;
+ struct mmc_queue_req *tmp;
spin_lock_irq(q->queue_lock);
set_current_state(TASK_INTERRUPTIBLE);
req = blk_fetch_request(q);
- mq->req = req;
+ mq->mqrq_cur->req = req;
spin_unlock_irq(q->queue_lock);
- if (!req) {
+ if (req || mq->mqrq_prev->req) {
+ set_current_state(TASK_RUNNING);
+ mq->issue_fn(mq, req);
+ } else {
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
break;
@@ -67,11 +71,14 @@ static int mmc_queue_thread(void *d)
up(&mq->thread_sem);
schedule();
down(&mq->thread_sem);
- continue;
}
- set_current_state(TASK_RUNNING);
- mq->issue_fn(mq, req);
+ /* Current request becomes previous request and vice versa. */
+ mq->mqrq_prev->brq.mrq.data = NULL;
+ mq->mqrq_prev->req = NULL;
+ tmp = mq->mqrq_prev;
+ mq->mqrq_prev = mq->mqrq_cur;
+ mq->mqrq_cur = tmp;
} while (1);
up(&mq->thread_sem);
@@ -97,10 +104,46 @@ static void mmc_request(struct request_queue *q)
return;
}
- if (!mq->req)
+ if (!mq->mqrq_cur->req && !mq->mqrq_prev->req)
wake_up_process(mq->thread);
}
+struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
+{
+ struct scatterlist *sg;
+
+ sg = kmalloc(sizeof(struct scatterlist)*sg_len, GFP_KERNEL);
+ if (!sg)
+ *err = -ENOMEM;
+ else {
+ *err = 0;
+ sg_init_table(sg, sg_len);
+ }
+
+ return sg;
+}
+
+static void mmc_queue_setup_discard(struct request_queue *q,
+ struct mmc_card *card)
+{
+ unsigned max_discard;
+
+ max_discard = mmc_calc_max_discard(card);
+ if (!max_discard)
+ return;
+
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+ q->limits.max_discard_sectors = max_discard;
+ if (card->erased_byte == 0)
+ q->limits.discard_zeroes_data = 1;
+ q->limits.discard_granularity = card->pref_erase << 9;
+ /* 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))
+ queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q);
+}
+
/**
* mmc_init_queue - initialise a queue structure.
* @mq: mmc queue
@@ -116,6 +159,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
struct mmc_host *host = card->host;
u64 limit = BLK_BOUNCE_HIGH;
int ret;
+ struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
+ struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
limit = *mmc_dev(host)->dma_mask;
@@ -125,21 +170,16 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
if (!mq->queue)
return -ENOMEM;
+ memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur));
+ memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev));
+ mq->mqrq_cur = mqrq_cur;
+ mq->mqrq_prev = mqrq_prev;
mq->queue->queuedata = mq;
- mq->req = NULL;
blk_queue_prep_rq(mq->queue, mmc_prep_request);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
- if (mmc_can_erase(card)) {
- queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue);
- mq->queue->limits.max_discard_sectors = UINT_MAX;
- if (card->erased_byte == 0)
- mq->queue->limits.discard_zeroes_data = 1;
- mq->queue->limits.discard_granularity = card->pref_erase << 9;
- if (mmc_can_secure_erase_trim(card))
- queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD,
- mq->queue);
- }
+ if (mmc_can_erase(card))
+ mmc_queue_setup_discard(mq->queue, card);
#ifdef CONFIG_MMC_BLOCK_BOUNCE
if (host->max_segs == 1) {
@@ -155,53 +195,64 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
bouncesz = host->max_blk_count * 512;
if (bouncesz > 512) {
- mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
- if (!mq->bounce_buf) {
+ mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+ if (!mqrq_cur->bounce_buf) {
+ printk(KERN_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 "
- "allocate bounce buffer\n",
+ "allocate bounce prev buffer\n",
mmc_card_name(card));
+ kfree(mqrq_cur->bounce_buf);
+ mqrq_cur->bounce_buf = NULL;
}
}
- if (mq->bounce_buf) {
+ if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) {
blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
blk_queue_max_segments(mq->queue, bouncesz / 512);
blk_queue_max_segment_size(mq->queue, bouncesz);
- mq->sg = kmalloc(sizeof(struct scatterlist),
- GFP_KERNEL);
- if (!mq->sg) {
- ret = -ENOMEM;
+ mqrq_cur->sg = mmc_alloc_sg(1, &ret);
+ if (ret)
goto cleanup_queue;
- }
- sg_init_table(mq->sg, 1);
- mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
- bouncesz / 512, GFP_KERNEL);
- if (!mq->bounce_sg) {
- ret = -ENOMEM;
+ mqrq_cur->bounce_sg =
+ mmc_alloc_sg(bouncesz / 512, &ret);
+ if (ret)
+ goto cleanup_queue;
+
+ mqrq_prev->sg = mmc_alloc_sg(1, &ret);
+ if (ret)
+ goto cleanup_queue;
+
+ mqrq_prev->bounce_sg =
+ mmc_alloc_sg(bouncesz / 512, &ret);
+ if (ret)
goto cleanup_queue;
- }
- sg_init_table(mq->bounce_sg, bouncesz / 512);
}
}
#endif
- if (!mq->bounce_buf) {
+ if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) {
blk_queue_bounce_limit(mq->queue, limit);
blk_queue_max_hw_sectors(mq->queue,
min(host->max_blk_count, host->max_req_size / 512));
blk_queue_max_segments(mq->queue, host->max_segs);
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
- mq->sg = kmalloc(sizeof(struct scatterlist) *
- host->max_segs, GFP_KERNEL);
- if (!mq->sg) {
- ret = -ENOMEM;
+ mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret);
+ if (ret)
+ goto cleanup_queue;
+
+
+ mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret);
+ if (ret)
goto cleanup_queue;
- }
- sg_init_table(mq->sg, host->max_segs);
}
sema_init(&mq->thread_sem, 1);
@@ -216,16 +267,22 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
return 0;
free_bounce_sg:
- if (mq->bounce_sg)
- kfree(mq->bounce_sg);
- mq->bounce_sg = NULL;
+ kfree(mqrq_cur->bounce_sg);
+ mqrq_cur->bounce_sg = NULL;
+ kfree(mqrq_prev->bounce_sg);
+ mqrq_prev->bounce_sg = NULL;
+
cleanup_queue:
- if (mq->sg)
- kfree(mq->sg);
- mq->sg = NULL;
- if (mq->bounce_buf)
- kfree(mq->bounce_buf);
- mq->bounce_buf = NULL;
+ kfree(mqrq_cur->sg);
+ mqrq_cur->sg = NULL;
+ kfree(mqrq_cur->bounce_buf);
+ mqrq_cur->bounce_buf = NULL;
+
+ kfree(mqrq_prev->sg);
+ mqrq_prev->sg = NULL;
+ kfree(mqrq_prev->bounce_buf);
+ mqrq_prev->bounce_buf = NULL;
+
blk_cleanup_queue(mq->queue);
return ret;
}
@@ -234,6 +291,8 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
{
struct request_queue *q = mq->queue;
unsigned long flags;
+ struct mmc_queue_req *mqrq_cur = mq->mqrq_cur;
+ struct mmc_queue_req *mqrq_prev = mq->mqrq_prev;
/* Make sure the queue isn't suspended, as that will deadlock */
mmc_queue_resume(mq);
@@ -247,16 +306,23 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
blk_start_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags);
- if (mq->bounce_sg)
- kfree(mq->bounce_sg);
- mq->bounce_sg = NULL;
+ kfree(mqrq_cur->bounce_sg);
+ mqrq_cur->bounce_sg = NULL;
- kfree(mq->sg);
- mq->sg = NULL;
+ kfree(mqrq_cur->sg);
+ mqrq_cur->sg = NULL;
- if (mq->bounce_buf)
- kfree(mq->bounce_buf);
- mq->bounce_buf = NULL;
+ kfree(mqrq_cur->bounce_buf);
+ mqrq_cur->bounce_buf = NULL;
+
+ kfree(mqrq_prev->bounce_sg);
+ mqrq_prev->bounce_sg = NULL;
+
+ kfree(mqrq_prev->sg);
+ mqrq_prev->sg = NULL;
+
+ kfree(mqrq_prev->bounce_buf);
+ mqrq_prev->bounce_buf = NULL;
mq->card = NULL;
}
@@ -309,27 +375,27 @@ void mmc_queue_resume(struct mmc_queue *mq)
/*
* Prepare the sg list(s) to be handed of to the host driver
*/
-unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
+unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
{
unsigned int sg_len;
size_t buflen;
struct scatterlist *sg;
int i;
- if (!mq->bounce_buf)
- return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
+ if (!mqrq->bounce_buf)
+ return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg);
- BUG_ON(!mq->bounce_sg);
+ BUG_ON(!mqrq->bounce_sg);
- sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
+ sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg);
- mq->bounce_sg_len = sg_len;
+ mqrq->bounce_sg_len = sg_len;
buflen = 0;
- for_each_sg(mq->bounce_sg, sg, sg_len, i)
+ for_each_sg(mqrq->bounce_sg, sg, sg_len, i)
buflen += sg->length;
- sg_init_one(mq->sg, mq->bounce_buf, buflen);
+ sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen);
return 1;
}
@@ -338,31 +404,30 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
* If writing, bounce the data to the buffer before the request
* is sent to the host driver
*/
-void mmc_queue_bounce_pre(struct mmc_queue *mq)
+void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
{
- if (!mq->bounce_buf)
+ if (!mqrq->bounce_buf)
return;
- if (rq_data_dir(mq->req) != WRITE)
+ if (rq_data_dir(mqrq->req) != WRITE)
return;
- sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len,
- mq->bounce_buf, mq->sg[0].length);
+ sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
+ mqrq->bounce_buf, mqrq->sg[0].length);
}
/*
* If reading, bounce the data from the buffer after the request
* has been handled by the host driver
*/
-void mmc_queue_bounce_post(struct mmc_queue *mq)
+void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
{
- if (!mq->bounce_buf)
+ if (!mqrq->bounce_buf)
return;
- if (rq_data_dir(mq->req) != READ)
+ if (rq_data_dir(mqrq->req) != READ)
return;
- sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len,
- mq->bounce_buf, mq->sg[0].length);
+ sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
+ mqrq->bounce_buf, mqrq->sg[0].length);
}
-
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 6223ef8dc9cd..d2a1eb4b9f9f 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -4,19 +4,35 @@
struct request;
struct task_struct;
+struct mmc_blk_request {
+ struct mmc_request mrq;
+ struct mmc_command sbc;
+ struct mmc_command cmd;
+ struct mmc_command stop;
+ struct mmc_data data;
+};
+
+struct mmc_queue_req {
+ struct request *req;
+ struct mmc_blk_request brq;
+ struct scatterlist *sg;
+ char *bounce_buf;
+ struct scatterlist *bounce_sg;
+ unsigned int bounce_sg_len;
+ struct mmc_async_req mmc_active;
+};
+
struct mmc_queue {
struct mmc_card *card;
struct task_struct *thread;
struct semaphore thread_sem;
unsigned int flags;
- struct request *req;
int (*issue_fn)(struct mmc_queue *, struct request *);
void *data;
struct request_queue *queue;
- struct scatterlist *sg;
- char *bounce_buf;
- struct scatterlist *bounce_sg;
- unsigned int bounce_sg_len;
+ struct mmc_queue_req mqrq[2];
+ struct mmc_queue_req *mqrq_cur;
+ struct mmc_queue_req *mqrq_prev;
};
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
@@ -25,8 +41,9 @@ extern void mmc_cleanup_queue(struct mmc_queue *);
extern void mmc_queue_suspend(struct mmc_queue *);
extern void mmc_queue_resume(struct mmc_queue *);
-extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
-extern void mmc_queue_bounce_pre(struct mmc_queue *);
-extern void mmc_queue_bounce_post(struct mmc_queue *);
+extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
+ struct mmc_queue_req *);
+extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
+extern void mmc_queue_bounce_post(struct mmc_queue_req *);
#endif
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7843efe22359..89bdeaec7182 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -23,6 +23,7 @@
#include <linux/log2.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
+#include <linux/suspend.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -198,9 +199,109 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
static void mmc_wait_done(struct mmc_request *mrq)
{
- complete(mrq->done_data);
+ complete(&mrq->completion);
}
+static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+ init_completion(&mrq->completion);
+ mrq->done = mmc_wait_done;
+ mmc_start_request(host, mrq);
+}
+
+static void mmc_wait_for_req_done(struct mmc_host *host,
+ struct mmc_request *mrq)
+{
+ wait_for_completion(&mrq->completion);
+}
+
+/**
+ * mmc_pre_req - Prepare for a new request
+ * @host: MMC host to prepare command
+ * @mrq: MMC request to prepare for
+ * @is_first_req: true if there is no previous started request
+ * that may run in parellel to this call, otherwise false
+ *
+ * mmc_pre_req() is called in prior to mmc_start_req() to let
+ * host prepare for the new request. Preparation of a request may be
+ * performed while another request is running on the host.
+ */
+static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
+ bool is_first_req)
+{
+ if (host->ops->pre_req)
+ host->ops->pre_req(host, mrq, is_first_req);
+}
+
+/**
+ * mmc_post_req - Post process a completed request
+ * @host: MMC host to post process command
+ * @mrq: MMC request to post process for
+ * @err: Error, if non zero, clean up any resources made in pre_req
+ *
+ * Let the host post process a completed request. Post processing of
+ * a request may be performed while another reuqest is running.
+ */
+static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
+ int err)
+{
+ if (host->ops->post_req)
+ host->ops->post_req(host, mrq, err);
+}
+
+/**
+ * mmc_start_req - start a non-blocking request
+ * @host: MMC host to start command
+ * @areq: async request to start
+ * @error: out parameter returns 0 for success, otherwise non zero
+ *
+ * Start a new MMC custom command request for a host.
+ * If there is on ongoing async request wait for completion
+ * of that request and start the new one and return.
+ * Does not wait for the new request to complete.
+ *
+ * Returns the completed request, NULL in case of none completed.
+ * Wait for the an ongoing request (previoulsy started) to complete and
+ * return the completed request. If there is no ongoing request, NULL
+ * is returned without waiting. NULL is not an error condition.
+ */
+struct mmc_async_req *mmc_start_req(struct mmc_host *host,
+ struct mmc_async_req *areq, int *error)
+{
+ int err = 0;
+ struct mmc_async_req *data = host->areq;
+
+ /* Prepare a new request */
+ if (areq)
+ mmc_pre_req(host, areq->mrq, !host->areq);
+
+ if (host->areq) {
+ mmc_wait_for_req_done(host, host->areq->mrq);
+ err = host->areq->err_check(host->card, host->areq);
+ if (err) {
+ mmc_post_req(host, host->areq->mrq, 0);
+ if (areq)
+ mmc_post_req(host, areq->mrq, -EINVAL);
+
+ host->areq = NULL;
+ goto out;
+ }
+ }
+
+ if (areq)
+ __mmc_start_req(host, areq->mrq);
+
+ if (host->areq)
+ mmc_post_req(host, host->areq->mrq, 0);
+
+ host->areq = areq;
+ out:
+ if (error)
+ *error = err;
+ return data;
+}
+EXPORT_SYMBOL(mmc_start_req);
+
/**
* mmc_wait_for_req - start a request and wait for completion
* @host: MMC host to start command
@@ -212,16 +313,9 @@ static void mmc_wait_done(struct mmc_request *mrq)
*/
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
- DECLARE_COMPLETION_ONSTACK(complete);
-
- mrq->done_data = &complete;
- mrq->done = mmc_wait_done;
-
- mmc_start_request(host, mrq);
-
- wait_for_completion(&complete);
+ __mmc_start_req(host, mrq);
+ mmc_wait_for_req_done(host, mrq);
}
-
EXPORT_SYMBOL(mmc_wait_for_req);
/**
@@ -1516,6 +1610,82 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
}
EXPORT_SYMBOL(mmc_erase_group_aligned);
+static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,
+ unsigned int arg)
+{
+ struct mmc_host *host = card->host;
+ unsigned int max_discard, x, y, qty = 0, max_qty, timeout;
+ unsigned int last_timeout = 0;
+
+ if (card->erase_shift)
+ max_qty = UINT_MAX >> card->erase_shift;
+ else if (mmc_card_sd(card))
+ max_qty = UINT_MAX;
+ else
+ max_qty = UINT_MAX / card->erase_size;
+
+ /* Find the largest qty with an OK timeout */
+ do {
+ y = 0;
+ for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {
+ timeout = mmc_erase_timeout(card, arg, qty + x);
+ if (timeout > host->max_discard_to)
+ break;
+ if (timeout < last_timeout)
+ break;
+ last_timeout = timeout;
+ y = x;
+ }
+ qty += y;
+ } while (y);
+
+ if (!qty)
+ return 0;
+
+ if (qty == 1)
+ return 1;
+
+ /* Convert qty to sectors */
+ if (card->erase_shift)
+ max_discard = --qty << card->erase_shift;
+ else if (mmc_card_sd(card))
+ max_discard = qty;
+ else
+ max_discard = --qty * card->erase_size;
+
+ return max_discard;
+}
+
+unsigned int mmc_calc_max_discard(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ unsigned int max_discard, max_trim;
+
+ if (!host->max_discard_to)
+ return UINT_MAX;
+
+ /*
+ * Without erase_group_def set, MMC erase timeout depends on clock
+ * frequence which can change. In that case, the best choice is
+ * just the preferred erase size.
+ */
+ if (mmc_card_mmc(card) && !(card->ext_csd.erase_group_def & 1))
+ return card->pref_erase;
+
+ max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
+ if (mmc_can_trim(card)) {
+ max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG);
+ if (max_trim < max_discard)
+ max_discard = max_trim;
+ } else if (max_discard < card->erase_size) {
+ max_discard = 0;
+ }
+ pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n",
+ mmc_hostname(host), max_discard, host->max_discard_to);
+ return max_discard;
+}
+EXPORT_SYMBOL(mmc_calc_max_discard);
+
int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
{
struct mmc_command cmd = {0};
@@ -1663,6 +1833,10 @@ int mmc_power_save_host(struct mmc_host *host)
{
int ret = 0;
+#ifdef CONFIG_MMC_DEBUG
+ pr_info("%s: %s: powering down\n", mmc_hostname(host), __func__);
+#endif
+
mmc_bus_get(host);
if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
@@ -1685,6 +1859,10 @@ int mmc_power_restore_host(struct mmc_host *host)
{
int ret;
+#ifdef CONFIG_MMC_DEBUG
+ pr_info("%s: %s: powering up\n", mmc_hostname(host), __func__);
+#endif
+
mmc_bus_get(host);
if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ff2774128aa9..633975ff2bb3 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -409,52 +409,62 @@ out:
static int sd_select_driver_type(struct mmc_card *card, u8 *status)
{
- int host_drv_type = 0, card_drv_type = 0;
+ int host_drv_type = SD_DRIVER_TYPE_B;
+ int card_drv_type = SD_DRIVER_TYPE_B;
+ int drive_strength;
int err;
/*
* If the host doesn't support any of the Driver Types A,C or D,
- * default Driver Type B is used.
+ * or there is no board specific handler then default Driver
+ * Type B is used.
*/
if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
| MMC_CAP_DRIVER_TYPE_D)))
return 0;
- if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) {
- host_drv_type = MMC_SET_DRIVER_TYPE_A;
- if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
- card_drv_type = MMC_SET_DRIVER_TYPE_A;
- else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
- card_drv_type = MMC_SET_DRIVER_TYPE_B;
- else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
- card_drv_type = MMC_SET_DRIVER_TYPE_C;
- } else if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) {
- host_drv_type = MMC_SET_DRIVER_TYPE_C;
- if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
- card_drv_type = MMC_SET_DRIVER_TYPE_C;
- } else if (!(card->host->caps & MMC_CAP_DRIVER_TYPE_D)) {
- /*
- * If we are here, that means only the default driver type
- * B is supported by the host.
- */
- host_drv_type = MMC_SET_DRIVER_TYPE_B;
- if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
- card_drv_type = MMC_SET_DRIVER_TYPE_B;
- else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
- card_drv_type = MMC_SET_DRIVER_TYPE_C;
- }
+ if (!card->host->ops->select_drive_strength)
+ return 0;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_A)
+ host_drv_type |= SD_DRIVER_TYPE_A;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_C)
+ host_drv_type |= SD_DRIVER_TYPE_C;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_D)
+ host_drv_type |= SD_DRIVER_TYPE_D;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
+ card_drv_type |= SD_DRIVER_TYPE_A;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
+ card_drv_type |= SD_DRIVER_TYPE_C;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D)
+ card_drv_type |= SD_DRIVER_TYPE_D;
+
+ /*
+ * The drive strength that the hardware can support
+ * depends on the board design. Pass the appropriate
+ * information and let the hardware specific code
+ * return what is possible given the options
+ */
+ drive_strength = card->host->ops->select_drive_strength(
+ card->sw_caps.uhs_max_dtr,
+ host_drv_type, card_drv_type);
- err = mmc_sd_switch(card, 1, 2, card_drv_type, status);
+ err = mmc_sd_switch(card, 1, 2, drive_strength, status);
if (err)
return err;
- if ((status[15] & 0xF) != card_drv_type) {
- printk(KERN_WARNING "%s: Problem setting driver strength!\n",
+ if ((status[15] & 0xF) != drive_strength) {
+ printk(KERN_WARNING "%s: Problem setting drive strength!\n",
mmc_hostname(card->host));
return 0;
}
- mmc_set_driver_type(card->host, host_drv_type);
+ mmc_set_driver_type(card->host, drive_strength);
return 0;
}
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index d2565df8a7fb..e4e6822d09e3 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -167,11 +167,8 @@ static int sdio_bus_remove(struct device *dev)
int ret = 0;
/* Make sure card is powered before invoking ->remove() */
- if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
- ret = pm_runtime_get_sync(dev);
- if (ret < 0)
- goto out;
- }
+ if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
+ pm_runtime_get_sync(dev);
drv->remove(func);
@@ -191,7 +188,6 @@ static int sdio_bus_remove(struct device *dev)
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_sync(dev);
-out:
return ret;
}
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 56dbf3f6ad08..8c87096531e9 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -81,28 +81,32 @@ config MMC_RICOH_MMC
If unsure, say Y.
-config MMC_SDHCI_OF
- tristate "SDHCI support on OpenFirmware platforms"
- depends on MMC_SDHCI && OF
+config MMC_SDHCI_PLTFM
+ tristate "SDHCI platform and OF driver helper"
+ depends on MMC_SDHCI
help
- This selects the OF support for Secure Digital Host Controller
- Interfaces.
+ This selects the common helper functions support for Secure Digital
+ Host Controller Interface based platform and OF drivers.
+
+ If you have a controller with this interface, say Y or M here.
If unsure, say N.
config MMC_SDHCI_OF_ESDHC
- bool "SDHCI OF support for the Freescale eSDHC controller"
- depends on MMC_SDHCI_OF
+ tristate "SDHCI OF support for the Freescale eSDHC controller"
+ depends on MMC_SDHCI_PLTFM
depends on PPC_OF
select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
help
This selects the Freescale eSDHC controller support.
+ If you have a controller with this interface, say Y or M here.
+
If unsure, say N.
config MMC_SDHCI_OF_HLWD
- bool "SDHCI OF support for the Nintendo Wii SDHCI controllers"
- depends on MMC_SDHCI_OF
+ tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
+ depends on MMC_SDHCI_PLTFM
depends on PPC_OF
select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
help
@@ -110,40 +114,36 @@ config MMC_SDHCI_OF_HLWD
found in the "Hollywood" chipset of the Nintendo Wii video game
console.
- If unsure, say N.
-
-config MMC_SDHCI_PLTFM
- tristate "SDHCI support on the platform specific bus"
- depends on MMC_SDHCI
- help
- This selects the platform specific bus support for Secure Digital Host
- Controller Interface.
-
If you have a controller with this interface, say Y or M here.
If unsure, say N.
config MMC_SDHCI_CNS3XXX
- bool "SDHCI support on the Cavium Networks CNS3xxx SoC"
+ tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
depends on ARCH_CNS3XXX
depends on MMC_SDHCI_PLTFM
help
This selects the SDHCI support for CNS3xxx System-on-Chip devices.
+ If you have a controller with this interface, say Y or M here.
+
If unsure, say N.
config MMC_SDHCI_ESDHC_IMX
- bool "SDHCI platform support for the Freescale eSDHC i.MX controller"
- depends on MMC_SDHCI_PLTFM && (ARCH_MX25 || ARCH_MX35 || ARCH_MX5)
+ tristate "SDHCI platform support for the Freescale eSDHC i.MX controller"
+ depends on ARCH_MX25 || ARCH_MX35 || ARCH_MX5
+ 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.
+ If you have a controller with this interface, say Y or M here.
+
If unsure, say N.
config MMC_SDHCI_DOVE
- bool "SDHCI support on Marvell's Dove SoC"
+ tristate "SDHCI support on Marvell's Dove SoC"
depends on ARCH_DOVE
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
@@ -151,11 +151,14 @@ config MMC_SDHCI_DOVE
This selects the Secure Digital Host Controller Interface in
Marvell's Dove SoC.
+ If you have a controller with this interface, say Y or M here.
+
If unsure, say N.
config MMC_SDHCI_TEGRA
- bool "SDHCI platform support for the Tegra SD/MMC Controller"
- depends on MMC_SDHCI_PLTFM && ARCH_TEGRA
+ tristate "SDHCI platform support for the Tegra SD/MMC Controller"
+ depends on ARCH_TEGRA
+ depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
help
This selects the Tegra SD/MMC controller. If you have a Tegra
@@ -178,14 +181,28 @@ config MMC_SDHCI_S3C
If unsure, say N.
-config MMC_SDHCI_PXA
- tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
- depends on ARCH_PXA || ARCH_MMP
+config MMC_SDHCI_PXAV3
+ tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
+ depends on CLKDEV_LOOKUP
select MMC_SDHCI
- select MMC_SDHCI_IO_ACCESSORS
+ select MMC_SDHCI_PLTFM
+ default CPU_MMP2
+ help
+ This selects the Marvell(R) PXAV3 SD Host Controller.
+ If you have a MMP2 platform with SD Host Controller
+ and a card slot, say Y or M here.
+
+ If unsure, say N.
+
+config MMC_SDHCI_PXAV2
+ tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
+ depends on CLKDEV_LOOKUP
+ select MMC_SDHCI
+ select MMC_SDHCI_PLTFM
+ default CPU_PXA910
help
- This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
- If you have a PXA168/PXA910/MMP2 platform with SD Host Controller
+ This selects the Marvell(R) PXAV2 SD Host Controller.
+ If you have a PXA9XX platform with SD Host Controller
and a card slot, say Y or M here.
If unsure, say N.
@@ -281,13 +298,12 @@ config MMC_ATMELMCI
endchoice
config MMC_ATMELMCI_DMA
- bool "Atmel MCI DMA support (EXPERIMENTAL)"
- depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL
+ bool "Atmel MCI DMA support"
+ depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE
help
Say Y here to have the Atmel MCI driver use a DMA engine to
do data transfers and thus increase the throughput and
- reduce the CPU utilization. Note that this is highly
- experimental and may cause the driver to lock up.
+ reduce the CPU utilization.
If unsure, say N.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 58a5cf73d6e9..b4b83f302e32 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,7 +9,8 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
-obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o
+obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
+obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
@@ -31,9 +32,7 @@ obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o
tmio_mmc_core-y := tmio_mmc_pio.o
-ifneq ($(CONFIG_MMC_SDHI),n)
-tmio_mmc_core-y += tmio_mmc_dma.o
-endif
+tmio_mmc_core-$(subst m,y,$(CONFIG_MMC_SDHI)) += tmio_mmc_dma.o
obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
@@ -44,17 +43,13 @@ obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
obj-$(CONFIG_MMC_VUB300) += vub300.o
obj-$(CONFIG_MMC_USHC) += ushc.o
-obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o
-sdhci-platform-y := sdhci-pltfm.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
-
-obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
-sdhci-of-y := sdhci-of-core.o
-sdhci-of-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
-sdhci-of-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
+obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
+obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
+obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
+obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
+obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
+obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
+obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
ifeq ($(CONFIG_CB710_DEBUG),y)
CFLAGS-cb710-mmc += -DDEBUG
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index d3e6a962f423..a4aa3af86fed 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -77,7 +77,8 @@
#include <mach/board.h>
#include <mach/cpu.h>
-#include <mach/at91_mci.h>
+
+#include "at91_mci.h"
#define DRIVER_NAME "at91_mci"
diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/drivers/mmc/host/at91_mci.h
index 02182c16a022..eec3a6b1c2bc 100644
--- a/arch/arm/mach-at91/include/mach/at91_mci.h
+++ b/drivers/mmc/host/at91_mci.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91/include/mach/at91_mci.h
+ * drivers/mmc/host/at91_mci.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index aa8039f473c4..fa8cae1d7005 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -203,6 +203,7 @@ struct atmel_mci_slot {
#define ATMCI_CARD_PRESENT 0
#define ATMCI_CARD_NEED_INIT 1
#define ATMCI_SHUTDOWN 2
+#define ATMCI_SUSPENDED 3
int detect_pin;
int wp_pin;
@@ -1878,10 +1879,72 @@ static int __exit atmci_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+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++) {
+ struct atmel_mci_slot *slot = host->slot[i];
+ int ret;
+
+ if (!slot)
+ continue;
+ ret = mmc_suspend_host(slot->mmc);
+ if (ret < 0) {
+ while (--i >= 0) {
+ slot = host->slot[i];
+ if (slot
+ && test_bit(ATMCI_SUSPENDED, &slot->flags)) {
+ mmc_resume_host(host->slot[i]->mmc);
+ clear_bit(ATMCI_SUSPENDED, &slot->flags);
+ }
+ }
+ return ret;
+ } else {
+ set_bit(ATMCI_SUSPENDED, &slot->flags);
+ }
+ }
+
+ return 0;
+}
+
+static int atmci_resume(struct device *dev)
+{
+ struct atmel_mci *host = dev_get_drvdata(dev);
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ struct atmel_mci_slot *slot = host->slot[i];
+ int err;
+
+ slot = host->slot[i];
+ if (!slot)
+ continue;
+ if (!test_bit(ATMCI_SUSPENDED, &slot->flags))
+ continue;
+ err = mmc_resume_host(slot->mmc);
+ if (err < 0)
+ ret = err;
+ else
+ clear_bit(ATMCI_SUSPENDED, &slot->flags);
+ }
+
+ return ret;
+}
+static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume);
+#define ATMCI_PM_OPS (&atmci_pm)
+#else
+#define ATMCI_PM_OPS NULL
+#endif
+
static struct platform_driver atmci_driver = {
.remove = __exit_p(atmci_remove),
.driver = {
.name = "atmel_mci",
+ .pm = ATMCI_PM_OPS,
},
};
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 66dcddb9c205..77f0b6b1681d 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -33,6 +33,7 @@
#include <linux/mmc/dw_mmc.h>
#include <linux/bitops.h>
#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
#include "dw_mmc.h"
@@ -100,6 +101,8 @@ struct dw_mci_slot {
int last_detect_state;
};
+static struct workqueue_struct *dw_mci_card_workqueue;
+
#if defined(CONFIG_DEBUG_FS)
static int dw_mci_req_show(struct seq_file *s, void *v)
{
@@ -284,7 +287,7 @@ static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data)
/* DMA interface functions */
static void dw_mci_stop_dma(struct dw_mci *host)
{
- if (host->use_dma) {
+ if (host->using_dma) {
host->dma_ops->stop(host);
host->dma_ops->cleanup(host);
} else {
@@ -432,6 +435,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
unsigned int i, direction, sg_len;
u32 temp;
+ host->using_dma = 0;
+
/* If we don't have a channel, we can't do DMA */
if (!host->use_dma)
return -ENODEV;
@@ -451,6 +456,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
return -EINVAL;
}
+ host->using_dma = 1;
+
if (data->flags & MMC_DATA_READ)
direction = DMA_FROM_DEVICE;
else
@@ -489,14 +496,18 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
host->sg = NULL;
host->data = data;
+ if (data->flags & MMC_DATA_READ)
+ host->dir_status = DW_MCI_RECV_STATUS;
+ else
+ host->dir_status = DW_MCI_SEND_STATUS;
+
if (dw_mci_submit_data_dma(host, data)) {
host->sg = data->sg;
host->pio_offset = 0;
- if (data->flags & MMC_DATA_READ)
- host->dir_status = DW_MCI_RECV_STATUS;
- else
- host->dir_status = DW_MCI_SEND_STATUS;
+ host->part_buf_start = 0;
+ host->part_buf_count = 0;
+ mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR);
temp = mci_readl(host, INTMASK);
temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR;
mci_writel(host, INTMASK, temp);
@@ -574,7 +585,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
}
/* Set the current slot bus width */
- mci_writel(host, CTYPE, slot->ctype);
+ mci_writel(host, CTYPE, (slot->ctype << slot->id));
}
static void dw_mci_start_request(struct dw_mci *host,
@@ -624,13 +635,13 @@ static void dw_mci_start_request(struct dw_mci *host,
host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
}
+/* must be called with host->lock held */
static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot,
struct mmc_request *mrq)
{
dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n",
host->state);
- spin_lock_bh(&host->lock);
slot->mrq = mrq;
if (host->state == STATE_IDLE) {
@@ -639,8 +650,6 @@ static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot,
} else {
list_add_tail(&slot->queue_node, &host->queue);
}
-
- spin_unlock_bh(&host->lock);
}
static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -650,14 +659,23 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
WARN_ON(slot->mrq);
+ /*
+ * The check for card presence and queueing of the request must be
+ * atomic, otherwise the card could be removed in between and the
+ * request wouldn't fail until another card was inserted.
+ */
+ spin_lock_bh(&host->lock);
+
if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) {
+ spin_unlock_bh(&host->lock);
mrq->cmd->error = -ENOMEDIUM;
mmc_request_done(mmc, mrq);
return;
}
- /* We don't support multiple blocks of weird lengths. */
dw_mci_queue_request(host, slot, mrq);
+
+ spin_unlock_bh(&host->lock);
}
static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -831,7 +849,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
struct mmc_command *cmd;
enum dw_mci_state state;
enum dw_mci_state prev_state;
- u32 status;
+ u32 status, ctrl;
spin_lock(&host->lock);
@@ -891,13 +909,19 @@ static void dw_mci_tasklet_func(unsigned long priv)
if (status & DW_MCI_DATA_ERROR_FLAGS) {
if (status & SDMMC_INT_DTO) {
- dev_err(&host->pdev->dev,
- "data timeout error\n");
data->error = -ETIMEDOUT;
} else if (status & SDMMC_INT_DCRC) {
- dev_err(&host->pdev->dev,
- "data CRC error\n");
data->error = -EILSEQ;
+ } else if (status & SDMMC_INT_EBE &&
+ host->dir_status ==
+ DW_MCI_SEND_STATUS) {
+ /*
+ * No data CRC status was returned.
+ * The number of bytes transferred will
+ * be exaggerated in PIO mode.
+ */
+ data->bytes_xfered = 0;
+ data->error = -ETIMEDOUT;
} else {
dev_err(&host->pdev->dev,
"data FIFO error "
@@ -905,6 +929,16 @@ static void dw_mci_tasklet_func(unsigned long priv)
status);
data->error = -EIO;
}
+ /*
+ * After an error, there may be data lingering
+ * in the FIFO, so reset it - doing so
+ * generates a block interrupt, hence setting
+ * the scatter-gather pointer to NULL.
+ */
+ host->sg = NULL;
+ ctrl = mci_readl(host, CTRL);
+ ctrl |= SDMMC_CTRL_FIFO_RESET;
+ mci_writel(host, CTRL, ctrl);
} else {
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;
@@ -946,84 +980,278 @@ unlock:
}
-static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
+/* push final bytes to part_buf, only use during push */
+static void dw_mci_set_part_bytes(struct dw_mci *host, void *buf, int cnt)
{
- u16 *pdata = (u16 *)buf;
+ memcpy((void *)&host->part_buf, buf, cnt);
+ host->part_buf_count = cnt;
+}
- WARN_ON(cnt % 2 != 0);
+/* append bytes to part_buf, only use during push */
+static int dw_mci_push_part_bytes(struct dw_mci *host, void *buf, int cnt)
+{
+ cnt = min(cnt, (1 << host->data_shift) - host->part_buf_count);
+ memcpy((void *)&host->part_buf + host->part_buf_count, buf, cnt);
+ host->part_buf_count += cnt;
+ return cnt;
+}
- cnt = cnt >> 1;
- while (cnt > 0) {
- mci_writew(host, DATA, *pdata++);
- cnt--;
+/* pull first bytes from part_buf, only use during pull */
+static int dw_mci_pull_part_bytes(struct dw_mci *host, void *buf, int cnt)
+{
+ cnt = min(cnt, (int)host->part_buf_count);
+ if (cnt) {
+ memcpy(buf, (void *)&host->part_buf + host->part_buf_start,
+ cnt);
+ host->part_buf_count -= cnt;
+ host->part_buf_start += cnt;
}
+ return cnt;
}
-static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
+/* pull final bytes from the part_buf, assuming it's just been filled */
+static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt)
{
- u16 *pdata = (u16 *)buf;
+ memcpy(buf, &host->part_buf, cnt);
+ host->part_buf_start = cnt;
+ host->part_buf_count = (1 << host->data_shift) - cnt;
+}
- WARN_ON(cnt % 2 != 0);
+static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
+{
+ /* try and push anything in the part_buf */
+ if (unlikely(host->part_buf_count)) {
+ int len = dw_mci_push_part_bytes(host, buf, cnt);
+ buf += len;
+ cnt -= len;
+ if (!sg_next(host->sg) || host->part_buf_count == 2) {
+ mci_writew(host, DATA, host->part_buf16);
+ host->part_buf_count = 0;
+ }
+ }
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (unlikely((unsigned long)buf & 0x1)) {
+ while (cnt >= 2) {
+ u16 aligned_buf[64];
+ int len = min(cnt & -2, (int)sizeof(aligned_buf));
+ int items = len >> 1;
+ int i;
+ /* memcpy from input buffer into aligned buffer */
+ memcpy(aligned_buf, buf, len);
+ buf += len;
+ cnt -= len;
+ /* push data from aligned buffer into fifo */
+ for (i = 0; i < items; ++i)
+ mci_writew(host, DATA, aligned_buf[i]);
+ }
+ } else
+#endif
+ {
+ u16 *pdata = buf;
+ for (; cnt >= 2; cnt -= 2)
+ mci_writew(host, DATA, *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);
+ }
+}
- cnt = cnt >> 1;
- while (cnt > 0) {
- *pdata++ = mci_readw(host, DATA);
- cnt--;
+static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
+{
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (unlikely((unsigned long)buf & 0x1)) {
+ while (cnt >= 2) {
+ /* pull data from fifo into aligned buffer */
+ u16 aligned_buf[64];
+ int len = min(cnt & -2, (int)sizeof(aligned_buf));
+ int items = len >> 1;
+ int i;
+ for (i = 0; i < items; ++i)
+ aligned_buf[i] = mci_readw(host, DATA);
+ /* memcpy from aligned buffer into output buffer */
+ memcpy(buf, aligned_buf, len);
+ buf += len;
+ cnt -= len;
+ }
+ } else
+#endif
+ {
+ u16 *pdata = buf;
+ for (; cnt >= 2; cnt -= 2)
+ *pdata++ = mci_readw(host, DATA);
+ buf = pdata;
+ }
+ if (cnt) {
+ host->part_buf16 = mci_readw(host, DATA);
+ dw_mci_pull_final_bytes(host, buf, cnt);
}
}
static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
{
- u32 *pdata = (u32 *)buf;
-
- WARN_ON(cnt % 4 != 0);
- WARN_ON((unsigned long)pdata & 0x3);
-
- cnt = cnt >> 2;
- while (cnt > 0) {
- mci_writel(host, DATA, *pdata++);
- cnt--;
+ /* try and push anything in the part_buf */
+ if (unlikely(host->part_buf_count)) {
+ int len = dw_mci_push_part_bytes(host, buf, cnt);
+ buf += len;
+ cnt -= len;
+ if (!sg_next(host->sg) || host->part_buf_count == 4) {
+ mci_writel(host, DATA, host->part_buf32);
+ host->part_buf_count = 0;
+ }
+ }
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (unlikely((unsigned long)buf & 0x3)) {
+ while (cnt >= 4) {
+ u32 aligned_buf[32];
+ int len = min(cnt & -4, (int)sizeof(aligned_buf));
+ int items = len >> 2;
+ int i;
+ /* memcpy from input buffer into aligned buffer */
+ memcpy(aligned_buf, buf, len);
+ buf += len;
+ cnt -= len;
+ /* push data from aligned buffer into fifo */
+ for (i = 0; i < items; ++i)
+ mci_writel(host, DATA, aligned_buf[i]);
+ }
+ } else
+#endif
+ {
+ u32 *pdata = buf;
+ for (; cnt >= 4; cnt -= 4)
+ mci_writel(host, DATA, *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);
}
}
static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
{
- u32 *pdata = (u32 *)buf;
-
- WARN_ON(cnt % 4 != 0);
- WARN_ON((unsigned long)pdata & 0x3);
-
- cnt = cnt >> 2;
- while (cnt > 0) {
- *pdata++ = mci_readl(host, DATA);
- cnt--;
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (unlikely((unsigned long)buf & 0x3)) {
+ while (cnt >= 4) {
+ /* pull data from fifo into aligned buffer */
+ u32 aligned_buf[32];
+ int len = min(cnt & -4, (int)sizeof(aligned_buf));
+ int items = len >> 2;
+ int i;
+ for (i = 0; i < items; ++i)
+ aligned_buf[i] = mci_readl(host, DATA);
+ /* memcpy from aligned buffer into output buffer */
+ memcpy(buf, aligned_buf, len);
+ buf += len;
+ cnt -= len;
+ }
+ } else
+#endif
+ {
+ u32 *pdata = buf;
+ for (; cnt >= 4; cnt -= 4)
+ *pdata++ = mci_readl(host, DATA);
+ buf = pdata;
+ }
+ if (cnt) {
+ host->part_buf32 = mci_readl(host, DATA);
+ dw_mci_pull_final_bytes(host, buf, cnt);
}
}
static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
{
- u64 *pdata = (u64 *)buf;
-
- WARN_ON(cnt % 8 != 0);
-
- cnt = cnt >> 3;
- while (cnt > 0) {
- mci_writeq(host, DATA, *pdata++);
- cnt--;
+ /* try and push anything in the part_buf */
+ if (unlikely(host->part_buf_count)) {
+ int len = dw_mci_push_part_bytes(host, buf, cnt);
+ buf += len;
+ cnt -= len;
+ if (!sg_next(host->sg) || host->part_buf_count == 8) {
+ mci_writew(host, DATA, host->part_buf);
+ host->part_buf_count = 0;
+ }
+ }
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (unlikely((unsigned long)buf & 0x7)) {
+ while (cnt >= 8) {
+ u64 aligned_buf[16];
+ int len = min(cnt & -8, (int)sizeof(aligned_buf));
+ int items = len >> 3;
+ int i;
+ /* memcpy from input buffer into aligned buffer */
+ memcpy(aligned_buf, buf, len);
+ buf += len;
+ cnt -= len;
+ /* push data from aligned buffer into fifo */
+ for (i = 0; i < items; ++i)
+ mci_writeq(host, DATA, aligned_buf[i]);
+ }
+ } else
+#endif
+ {
+ u64 *pdata = buf;
+ for (; cnt >= 8; cnt -= 8)
+ mci_writeq(host, DATA, *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);
}
}
static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
{
- u64 *pdata = (u64 *)buf;
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (unlikely((unsigned long)buf & 0x7)) {
+ while (cnt >= 8) {
+ /* pull data from fifo into aligned buffer */
+ u64 aligned_buf[16];
+ int len = min(cnt & -8, (int)sizeof(aligned_buf));
+ int items = len >> 3;
+ int i;
+ for (i = 0; i < items; ++i)
+ aligned_buf[i] = mci_readq(host, DATA);
+ /* memcpy from aligned buffer into output buffer */
+ memcpy(buf, aligned_buf, len);
+ buf += len;
+ cnt -= len;
+ }
+ } else
+#endif
+ {
+ u64 *pdata = buf;
+ for (; cnt >= 8; cnt -= 8)
+ *pdata++ = mci_readq(host, DATA);
+ buf = pdata;
+ }
+ if (cnt) {
+ host->part_buf = mci_readq(host, DATA);
+ dw_mci_pull_final_bytes(host, buf, cnt);
+ }
+}
- WARN_ON(cnt % 8 != 0);
+static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
+{
+ int len;
- cnt = cnt >> 3;
- while (cnt > 0) {
- *pdata++ = mci_readq(host, DATA);
- cnt--;
- }
+ /* get remaining partial bytes */
+ len = dw_mci_pull_part_bytes(host, buf, cnt);
+ if (unlikely(len == cnt))
+ return;
+ buf += len;
+ cnt -= len;
+
+ /* get the rest of the data */
+ host->pull_data(host, buf, cnt);
}
static void dw_mci_read_data_pio(struct dw_mci *host)
@@ -1037,9 +1265,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
unsigned int nbytes = 0, len;
do {
- len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift;
+ len = host->part_buf_count +
+ (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift);
if (offset + len <= sg->length) {
- host->pull_data(host, (void *)(buf + offset), len);
+ dw_mci_pull_data(host, (void *)(buf + offset), len);
offset += len;
nbytes += len;
@@ -1055,8 +1284,8 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
}
} else {
unsigned int remaining = sg->length - offset;
- host->pull_data(host, (void *)(buf + offset),
- remaining);
+ dw_mci_pull_data(host, (void *)(buf + offset),
+ remaining);
nbytes += remaining;
flush_dcache_page(sg_page(sg));
@@ -1066,7 +1295,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
offset = len - remaining;
buf = sg_virt(sg);
- host->pull_data(host, buf, offset);
+ dw_mci_pull_data(host, buf, offset);
nbytes += offset;
}
@@ -1083,7 +1312,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
return;
}
} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
- len = SDMMC_GET_FCNT(mci_readl(host, STATUS));
host->pio_offset = offset;
data->bytes_xfered += nbytes;
return;
@@ -1105,8 +1333,9 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
unsigned int nbytes = 0, len;
do {
- len = SDMMC_FIFO_SZ -
- (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift);
+ len = ((host->fifo_depth -
+ SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift)
+ - host->part_buf_count;
if (offset + len <= sg->length) {
host->push_data(host, (void *)(buf + offset), len);
@@ -1151,10 +1380,8 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
return;
}
} while (status & SDMMC_INT_TXDR); /* if TXDR write again */
-
host->pio_offset = offset;
data->bytes_xfered += nbytes;
-
return;
done:
@@ -1202,7 +1429,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
host->cmd_status = status;
smp_wmb();
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
- tasklet_schedule(&host->tasklet);
}
if (pending & DW_MCI_DATA_ERROR_FLAGS) {
@@ -1211,7 +1437,9 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
host->data_status = status;
smp_wmb();
set_bit(EVENT_DATA_ERROR, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC |
+ SDMMC_INT_SBE | SDMMC_INT_EBE)))
+ tasklet_schedule(&host->tasklet);
}
if (pending & SDMMC_INT_DATA_OVER) {
@@ -1229,13 +1457,13 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
if (pending & SDMMC_INT_RXDR) {
mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
- if (host->sg)
+ if (host->dir_status == DW_MCI_RECV_STATUS && host->sg)
dw_mci_read_data_pio(host);
}
if (pending & SDMMC_INT_TXDR) {
mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
- if (host->sg)
+ if (host->dir_status == DW_MCI_SEND_STATUS && host->sg)
dw_mci_write_data_pio(host);
}
@@ -1246,7 +1474,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
if (pending & SDMMC_INT_CD) {
mci_writel(host, RINTSTS, SDMMC_INT_CD);
- tasklet_schedule(&host->card_tasklet);
+ queue_work(dw_mci_card_workqueue, &host->card_work);
}
} while (pass_count++ < 5);
@@ -1265,9 +1493,9 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void dw_mci_tasklet_card(unsigned long data)
+static void dw_mci_work_routine_card(struct work_struct *work)
{
- struct dw_mci *host = (struct dw_mci *)data;
+ struct dw_mci *host = container_of(work, struct dw_mci, card_work);
int i;
for (i = 0; i < host->num_slots; i++) {
@@ -1279,22 +1507,21 @@ static void dw_mci_tasklet_card(unsigned long data)
present = dw_mci_get_cd(mmc);
while (present != slot->last_detect_state) {
- spin_lock(&host->lock);
-
dev_dbg(&slot->mmc->class_dev, "card %s\n",
present ? "inserted" : "removed");
+ /* Power up slot (before spin_lock, may sleep) */
+ if (present != 0 && host->pdata->setpower)
+ host->pdata->setpower(slot->id, mmc->ocr_avail);
+
+ spin_lock_bh(&host->lock);
+
/* Card change detected */
slot->last_detect_state = present;
- /* Power up slot */
- if (present != 0) {
- if (host->pdata->setpower)
- host->pdata->setpower(slot->id,
- mmc->ocr_avail);
-
+ /* Mark card as present if applicable */
+ if (present != 0)
set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
- }
/* Clean up queue if present */
mrq = slot->mrq;
@@ -1344,8 +1571,6 @@ static void dw_mci_tasklet_card(unsigned long data)
/* Power down slot */
if (present == 0) {
- if (host->pdata->setpower)
- host->pdata->setpower(slot->id, 0);
clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
/*
@@ -1367,7 +1592,12 @@ static void dw_mci_tasklet_card(unsigned long data)
}
- spin_unlock(&host->lock);
+ spin_unlock_bh(&host->lock);
+
+ /* Power down slot (after spin_unlock, may sleep) */
+ if (present == 0 && host->pdata->setpower)
+ host->pdata->setpower(slot->id, 0);
+
present = dw_mci_get_cd(mmc);
}
@@ -1467,7 +1697,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
* Card may have been plugged in prior to boot so we
* need to run the detect tasklet
*/
- tasklet_schedule(&host->card_tasklet);
+ queue_work(dw_mci_card_workqueue, &host->card_work);
return 0;
}
@@ -1595,7 +1825,7 @@ static int dw_mci_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&host->queue);
ret = -ENOMEM;
- host->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ host->regs = ioremap(regs->start, resource_size(regs));
if (!host->regs)
goto err_freehost;
@@ -1645,8 +1875,19 @@ static int dw_mci_probe(struct platform_device *pdev)
* FIFO threshold settings RxMark = fifo_size / 2 - 1,
* Tx Mark = fifo_size / 2 DMA Size = 8
*/
- fifo_size = mci_readl(host, FIFOTH);
- fifo_size = (fifo_size >> 16) & 0x7ff;
+ if (!host->pdata->fifo_depth) {
+ /*
+ * Power-on value of RX_WMark is FIFO_DEPTH-1, but this may
+ * have been overwritten by the bootloader, just like we're
+ * about to do, so if you know the value for your hardware, you
+ * should put it in the platform data.
+ */
+ fifo_size = mci_readl(host, FIFOTH);
+ fifo_size = 1 + ((fifo_size >> 16) & 0x7ff);
+ } else {
+ fifo_size = host->pdata->fifo_depth;
+ }
+ host->fifo_depth = fifo_size;
host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
((fifo_size/2) << 0));
mci_writel(host, FIFOTH, host->fifoth_val);
@@ -1656,12 +1897,15 @@ static int dw_mci_probe(struct platform_device *pdev)
mci_writel(host, CLKSRC, 0);
tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
- tasklet_init(&host->card_tasklet,
- dw_mci_tasklet_card, (unsigned long)host);
+ dw_mci_card_workqueue = alloc_workqueue("dw-mci-card",
+ WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1);
+ if (!dw_mci_card_workqueue)
+ goto err_dmaunmap;
+ INIT_WORK(&host->card_work, dw_mci_work_routine_card);
ret = request_irq(irq, dw_mci_interrupt, 0, "dw-mci", host);
if (ret)
- goto err_dmaunmap;
+ goto err_workqueue;
platform_set_drvdata(pdev, host);
@@ -1690,7 +1934,9 @@ static int dw_mci_probe(struct platform_device *pdev)
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
dev_info(&pdev->dev, "DW MMC controller at irq %d, "
- "%d bit host data width\n", irq, width);
+ "%d bit host data width, "
+ "%u deep fifo\n",
+ irq, width, fifo_size);
if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n");
@@ -1705,6 +1951,9 @@ err_init_slot:
}
free_irq(irq, host);
+err_workqueue:
+ destroy_workqueue(dw_mci_card_workqueue);
+
err_dmaunmap:
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);
@@ -1744,6 +1993,7 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
mci_writel(host, CLKSRC, 0);
free_irq(platform_get_irq(pdev, 0), host);
+ destroy_workqueue(dw_mci_card_workqueue);
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
if (host->use_dma && host->dma_ops->exit)
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 23c662af5616..027d37735394 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -118,7 +118,6 @@
#define SDMMC_CMD_INDX(n) ((n) & 0x1F)
/* Status register defines */
#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF)
-#define SDMMC_FIFO_SZ 32
/* Internal DMAC interrupt defines */
#define SDMMC_IDMAC_INT_AI BIT(9)
#define SDMMC_IDMAC_INT_NI BIT(8)
@@ -134,22 +133,22 @@
/* Register access macros */
#define mci_readl(dev, reg) \
- __raw_readl(dev->regs + SDMMC_##reg)
+ __raw_readl((dev)->regs + SDMMC_##reg)
#define mci_writel(dev, reg, value) \
- __raw_writel((value), dev->regs + SDMMC_##reg)
+ __raw_writel((value), (dev)->regs + SDMMC_##reg)
/* 16-bit FIFO access macros */
#define mci_readw(dev, reg) \
- __raw_readw(dev->regs + SDMMC_##reg)
+ __raw_readw((dev)->regs + SDMMC_##reg)
#define mci_writew(dev, reg, value) \
- __raw_writew((value), dev->regs + SDMMC_##reg)
+ __raw_writew((value), (dev)->regs + SDMMC_##reg)
/* 64-bit FIFO access macros */
#ifdef readq
#define mci_readq(dev, reg) \
- __raw_readq(dev->regs + SDMMC_##reg)
+ __raw_readq((dev)->regs + SDMMC_##reg)
#define mci_writeq(dev, reg, value) \
- __raw_writeq((value), dev->regs + SDMMC_##reg)
+ __raw_writeq((value), (dev)->regs + SDMMC_##reg)
#else
/*
* Dummy readq implementation for architectures that don't define it.
@@ -160,9 +159,9 @@
* rest of the code free from ifdefs.
*/
#define mci_readq(dev, reg) \
- (*(volatile u64 __force *)(dev->regs + SDMMC_##reg))
+ (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg))
#define mci_writeq(dev, reg, value) \
- (*(volatile u64 __force *)(dev->regs + SDMMC_##reg) = value)
+ (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value))
#endif
#endif /* _DW_MMC_H_ */
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index fe140724a02e..56e9a4168264 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -226,6 +226,9 @@ static void __devinit mmci_dma_setup(struct mmci_host *host)
return;
}
+ /* initialize pre request cookie */
+ host->next_data.cookie = 1;
+
/* Try to acquire a generic DMA engine slave channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
@@ -335,7 +338,8 @@ static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
dir = DMA_FROM_DEVICE;
}
- dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
+ if (!data->host_cookie)
+ dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
/*
* Use of DMA with scatter-gather is impossible.
@@ -353,7 +357,8 @@ static void mmci_dma_data_error(struct mmci_host *host)
dmaengine_terminate_all(host->dma_current);
}
-static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
+ struct mmci_host_next *next)
{
struct variant_data *variant = host->variant;
struct dma_slave_config conf = {
@@ -364,13 +369,20 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
.src_maxburst = variant->fifohalfsize >> 2, /* # of words */
.dst_maxburst = variant->fifohalfsize >> 2, /* # of words */
};
- struct mmc_data *data = host->data;
struct dma_chan *chan;
struct dma_device *device;
struct dma_async_tx_descriptor *desc;
int nr_sg;
- host->dma_current = NULL;
+ /* Check if next job is already prepared */
+ if (data->host_cookie && !next &&
+ host->dma_current && host->dma_desc_current)
+ return 0;
+
+ if (!next) {
+ host->dma_current = NULL;
+ host->dma_desc_current = NULL;
+ }
if (data->flags & MMC_DATA_READ) {
conf.direction = DMA_FROM_DEVICE;
@@ -385,7 +397,7 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
return -EINVAL;
/* If less than or equal to the fifo size, don't bother with DMA */
- if (host->size <= variant->fifosize)
+ if (data->blksz * data->blocks <= variant->fifosize)
return -EINVAL;
device = chan->device;
@@ -399,14 +411,38 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
if (!desc)
goto unmap_exit;
- /* Okay, go for it. */
- host->dma_current = chan;
+ if (next) {
+ next->dma_chan = chan;
+ next->dma_desc = desc;
+ } else {
+ host->dma_current = chan;
+ host->dma_desc_current = desc;
+ }
+
+ return 0;
+
+ unmap_exit:
+ if (!next)
+ dmaengine_terminate_all(chan);
+ dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
+ return -ENOMEM;
+}
+
+static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+{
+ int ret;
+ struct mmc_data *data = host->data;
+ ret = mmci_dma_prep_data(host, host->data, NULL);
+ if (ret)
+ return ret;
+
+ /* Okay, go for it. */
dev_vdbg(mmc_dev(host->mmc),
"Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
data->sg_len, data->blksz, data->blocks, data->flags);
- dmaengine_submit(desc);
- dma_async_issue_pending(chan);
+ dmaengine_submit(host->dma_desc_current);
+ dma_async_issue_pending(host->dma_current);
datactrl |= MCI_DPSM_DMAENABLE;
@@ -421,14 +457,90 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
host->base + MMCIMASK0);
return 0;
+}
-unmap_exit:
- dmaengine_terminate_all(chan);
- dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
- return -ENOMEM;
+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"
+ " host->next_data.cookie %d\n",
+ __func__, data->host_cookie, host->next_data.cookie);
+ data->host_cookie = 0;
+ }
+
+ if (!data->host_cookie)
+ return;
+
+ host->dma_desc_current = next->dma_desc;
+ host->dma_current = next->dma_chan;
+
+ next->dma_desc = NULL;
+ next->dma_chan = NULL;
+}
+
+static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq,
+ bool is_first_req)
+{
+ struct mmci_host *host = mmc_priv(mmc);
+ struct mmc_data *data = mrq->data;
+ struct mmci_host_next *nd = &host->next_data;
+
+ if (!data)
+ return;
+
+ if (data->host_cookie) {
+ data->host_cookie = 0;
+ return;
+ }
+
+ /* if config for dma */
+ if (((data->flags & MMC_DATA_WRITE) && host->dma_tx_channel) ||
+ ((data->flags & MMC_DATA_READ) && host->dma_rx_channel)) {
+ if (mmci_dma_prep_data(host, data, nd))
+ data->host_cookie = 0;
+ else
+ data->host_cookie = ++nd->cookie < 0 ? 1 : nd->cookie;
+ }
+}
+
+static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq,
+ int err)
+{
+ struct mmci_host *host = mmc_priv(mmc);
+ struct mmc_data *data = mrq->data;
+ struct dma_chan *chan;
+ enum dma_data_direction dir;
+
+ if (!data)
+ return;
+
+ if (data->flags & MMC_DATA_READ) {
+ dir = DMA_FROM_DEVICE;
+ chan = host->dma_rx_channel;
+ } else {
+ dir = DMA_TO_DEVICE;
+ chan = host->dma_tx_channel;
+ }
+
+
+ /* if config for dma */
+ if (chan) {
+ if (err)
+ dmaengine_terminate_all(chan);
+ if (err || data->host_cookie)
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, dir);
+ mrq->data->host_cookie = 0;
+ }
}
+
#else
/* Blank functions if the DMA engine is not available */
+static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
+{
+}
static inline void mmci_dma_setup(struct mmci_host *host)
{
}
@@ -449,6 +561,10 @@ static inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datac
{
return -ENOSYS;
}
+
+#define mmci_pre_request NULL
+#define mmci_post_request NULL
+
#endif
static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
@@ -872,6 +988,9 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->mrq = mrq;
+ if (mrq->data)
+ mmci_get_next_data(host, mrq->data);
+
if (mrq->data && mrq->data->flags & MMC_DATA_READ)
mmci_start_data(host, mrq->data);
@@ -986,6 +1105,8 @@ static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
static const struct mmc_host_ops mmci_ops = {
.request = mmci_request,
+ .pre_req = mmci_pre_request,
+ .post_req = mmci_post_request,
.set_ios = mmci_set_ios,
.get_ro = mmci_get_ro,
.get_cd = mmci_get_cd,
@@ -1063,7 +1184,15 @@ static int __devinit mmci_probe(struct amba_device *dev,
}
mmc->ops = &mmci_ops;
- mmc->f_min = (host->mclk + 511) / 512;
+ /*
+ * The ARM and ST versions of the block have slightly different
+ * clock divider equations which means that the minimum divider
+ * differs too.
+ */
+ if (variant->st_clkdiv)
+ mmc->f_min = DIV_ROUND_UP(host->mclk, 257);
+ else
+ mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
/*
* If the platform data supplies a maximum operating
* frequency, this takes precedence. Else, we fall back
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 2164e8c6476c..79e4143ab9df 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -166,6 +166,12 @@ struct clk;
struct variant_data;
struct dma_chan;
+struct mmci_host_next {
+ struct dma_async_tx_descriptor *dma_desc;
+ struct dma_chan *dma_chan;
+ s32 cookie;
+};
+
struct mmci_host {
phys_addr_t phybase;
void __iomem *base;
@@ -203,6 +209,8 @@ struct mmci_host {
struct dma_chan *dma_current;
struct dma_chan *dma_rx_channel;
struct dma_chan *dma_tx_channel;
+ struct dma_async_tx_descriptor *dma_desc_current;
+ struct mmci_host_next next_data;
#define dma_inprogress(host) ((host)->dma_current)
#else
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index cc20e0259325..14aa213b00da 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -715,13 +715,13 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
int burstlen, ret;
/*
- * use burstlen of 64 in 4 bit mode (--> reg value 0)
- * use burstlen of 16 in 1 bit mode (--> reg value 16)
+ * use burstlen of 64 (16 words) in 4 bit mode (--> reg value 0)
+ * use burstlen of 16 (4 words) in 1 bit mode (--> reg value 16)
*/
if (ios->bus_width == MMC_BUS_WIDTH_4)
- burstlen = 64;
- else
burstlen = 16;
+ else
+ burstlen = 4;
if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
host->burstlen = burstlen;
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 99d39a6a1032..d513d47364d0 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -564,40 +564,38 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
{
- unsigned int ssp_rate, bit_rate;
- u32 div1, div2;
+ unsigned int ssp_clk, ssp_sck;
+ u32 clock_divide, clock_rate;
u32 val;
- ssp_rate = clk_get_rate(host->clk);
+ ssp_clk = clk_get_rate(host->clk);
- for (div1 = 2; div1 < 254; div1 += 2) {
- div2 = ssp_rate / rate / div1;
- if (div2 < 0x100)
+ for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
+ clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
+ clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
+ if (clock_rate <= 255)
break;
}
- if (div1 >= 254) {
+ if (clock_divide > 254) {
dev_err(mmc_dev(host->mmc),
"%s: cannot set clock to %d\n", __func__, rate);
return;
}
- if (div2 == 0)
- bit_rate = ssp_rate / div1;
- else
- bit_rate = ssp_rate / div1 / div2;
+ ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
val = readl(host->base + HW_SSP_TIMING);
val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
- val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE);
- val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE);
+ val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
+ val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
writel(val, host->base + HW_SSP_TIMING);
- host->clk_rate = bit_rate;
+ host->clk_rate = ssp_sck;
dev_dbg(mmc_dev(host->mmc),
- "%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n",
- __func__, div1, div2, ssp_rate, bit_rate, rate);
+ "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
+ __func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
}
static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index dedf3dab8a3b..21e4a799df48 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
@@ -33,6 +34,7 @@
#include <linux/semaphore.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
#include <plat/dma.h>
#include <mach/hardware.h>
#include <plat/board.h>
@@ -116,15 +118,13 @@
#define OMAP_MMC4_DEVID 3
#define OMAP_MMC5_DEVID 4
+#define MMC_AUTOSUSPEND_DELAY 100
#define MMC_TIMEOUT_MS 20
#define OMAP_MMC_MASTER_CLOCK 96000000
+#define OMAP_MMC_MIN_CLOCK 400000
+#define OMAP_MMC_MAX_CLOCK 52000000
#define DRIVER_NAME "omap_hsmmc"
-/* Timeouts for entering power saving states on inactivity, msec */
-#define OMAP_MMC_DISABLED_TIMEOUT 100
-#define OMAP_MMC_SLEEP_TIMEOUT 1000
-#define OMAP_MMC_OFF_TIMEOUT 8000
-
/*
* One controller can have multiple slots, like on some omap boards using
* omap.c controller driver. Luckily this is not currently done on any known
@@ -141,6 +141,11 @@
#define OMAP_HSMMC_WRITE(base, reg, val) \
__raw_writel((val), (base) + OMAP_HSMMC_##reg)
+struct omap_hsmmc_next {
+ unsigned int dma_len;
+ s32 cookie;
+};
+
struct omap_hsmmc_host {
struct device *dev;
struct mmc_host *mmc;
@@ -148,7 +153,6 @@ struct omap_hsmmc_host {
struct mmc_command *cmd;
struct mmc_data *data;
struct clk *fclk;
- struct clk *iclk;
struct clk *dbclk;
/*
* vcc == configured supply
@@ -184,6 +188,7 @@ struct omap_hsmmc_host {
int reqs_blocked;
int use_reg;
int req_in_progress;
+ struct omap_hsmmc_next next_data;
struct omap_mmc_platform_data *pdata;
};
@@ -548,6 +553,15 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
}
/*
+ * Start clock to the card
+ */
+static void omap_hsmmc_start_clock(struct omap_hsmmc_host *host)
+{
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+}
+
+/*
* Stop clock to the card
*/
static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
@@ -584,6 +598,81 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
}
+/* Calculate divisor for the given clock frequency */
+static u16 calc_divisor(struct mmc_ios *ios)
+{
+ u16 dsor = 0;
+
+ if (ios->clock) {
+ dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock);
+ if (dsor > 250)
+ dsor = 250;
+ }
+
+ return dsor;
+}
+
+static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+{
+ struct mmc_ios *ios = &host->mmc->ios;
+ unsigned long regval;
+ unsigned long timeout;
+
+ dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+
+ omap_hsmmc_stop_clock(host);
+
+ regval = OMAP_HSMMC_READ(host->base, SYSCTL);
+ regval = regval & ~(CLKD_MASK | DTO_MASK);
+ regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+
+ /* Wait till the ICS bit is set */
+ timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
+ while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
+ && time_before(jiffies, timeout))
+ cpu_relax();
+
+ omap_hsmmc_start_clock(host);
+}
+
+static void omap_hsmmc_set_bus_width(struct omap_hsmmc_host *host)
+{
+ struct mmc_ios *ios = &host->mmc->ios;
+ u32 con;
+
+ con = OMAP_HSMMC_READ(host->base, CON);
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_8:
+ OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
+ break;
+ case MMC_BUS_WIDTH_4:
+ OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
+ break;
+ case MMC_BUS_WIDTH_1:
+ OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
+ break;
+ }
+}
+
+static void omap_hsmmc_set_bus_mode(struct omap_hsmmc_host *host)
+{
+ struct mmc_ios *ios = &host->mmc->ios;
+ u32 con;
+
+ con = OMAP_HSMMC_READ(host->base, CON);
+ if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+ OMAP_HSMMC_WRITE(host->base, CON, con | OD);
+ else
+ OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
+}
+
#ifdef CONFIG_PM
/*
@@ -595,8 +684,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
struct mmc_ios *ios = &host->mmc->ios;
struct omap_mmc_platform_data *pdata = host->pdata;
int context_loss = 0;
- u32 hctl, capa, con;
- u16 dsor = 0;
+ u32 hctl, capa;
unsigned long timeout;
if (pdata->get_context_loss_count) {
@@ -658,54 +746,12 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
if (host->power_mode == MMC_POWER_OFF)
goto out;
- con = OMAP_HSMMC_READ(host->base, CON);
- switch (ios->bus_width) {
- case MMC_BUS_WIDTH_8:
- OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
- break;
- case MMC_BUS_WIDTH_4:
- OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
- OMAP_HSMMC_WRITE(host->base, HCTL,
- OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
- break;
- case MMC_BUS_WIDTH_1:
- OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
- OMAP_HSMMC_WRITE(host->base, HCTL,
- OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
- break;
- }
-
- if (ios->clock) {
- dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
- if (dsor < 1)
- dsor = 1;
-
- if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
- dsor++;
-
- if (dsor > 250)
- dsor = 250;
- }
-
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
- OMAP_HSMMC_WRITE(host->base, SYSCTL, (dsor << 6) | (DTO << 16));
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+ omap_hsmmc_set_bus_width(host);
- timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
- while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
- && time_before(jiffies, timeout))
- ;
+ omap_hsmmc_set_clock(host);
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+ omap_hsmmc_set_bus_mode(host);
- con = OMAP_HSMMC_READ(host->base, CON);
- if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
- OMAP_HSMMC_WRITE(host->base, CON, con | OD);
- else
- OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
out:
host->context_loss = context_loss;
@@ -973,14 +1019,14 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
* Readable error output
*/
#ifdef CONFIG_MMC_DEBUG
-static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
+static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status)
{
/* --- means reserved bit without definition at documentation */
static const char *omap_hsmmc_status_bits[] = {
- "CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
- "OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
- "CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
- "---", "---", "---", "CERR", "CERR", "BADA", "---", "---", "---"
+ "CC" , "TC" , "BGE", "---", "BWR" , "BRR" , "---" , "---" ,
+ "CIRQ", "OBI" , "---", "---", "---" , "---" , "---" , "ERRI",
+ "CTO" , "CCRC", "CEB", "CIE", "DTO" , "DCRC", "DEB" , "---" ,
+ "ACE" , "---" , "---", "---", "CERR", "BADA", "---" , "---"
};
char res[256];
char *buf = res;
@@ -997,6 +1043,11 @@ static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
dev_dbg(mmc_dev(host->mmc), "%s\n", res);
}
+#else
+static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host,
+ u32 status)
+{
+}
#endif /* CONFIG_MMC_DEBUG */
/*
@@ -1055,9 +1106,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
if (status & ERR) {
-#ifdef CONFIG_MMC_DEBUG
- omap_hsmmc_report_irq(host, status);
-#endif
+ omap_hsmmc_dbg_report_irq(host, status);
if ((status & CMD_TIMEOUT) ||
(status & CMD_CRC)) {
if (host->cmd) {
@@ -1155,8 +1204,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
int ret;
/* Disable the clocks */
- clk_disable(host->fclk);
- clk_disable(host->iclk);
+ pm_runtime_put_sync(host->dev);
if (host->got_dbclk)
clk_disable(host->dbclk);
@@ -1167,8 +1215,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
if (!ret)
ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1,
vdd);
- clk_enable(host->iclk);
- clk_enable(host->fclk);
+ pm_runtime_get_sync(host->dev);
if (host->got_dbclk)
clk_enable(host->dbclk);
@@ -1322,7 +1369,7 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host,
static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
{
struct omap_hsmmc_host *host = cb_data;
- struct mmc_data *data = host->mrq->data;
+ struct mmc_data *data;
int dma_ch, req_in_progress;
if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
@@ -1337,6 +1384,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
return;
}
+ data = host->mrq->data;
host->dma_sg_idx++;
if (host->dma_sg_idx < host->dma_len) {
/* Fire up the next transfer. */
@@ -1346,8 +1394,9 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
return;
}
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- omap_hsmmc_get_dma_dir(host, data));
+ if (!data->host_cookie)
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+ omap_hsmmc_get_dma_dir(host, data));
req_in_progress = host->req_in_progress;
dma_ch = host->dma_ch;
@@ -1365,6 +1414,45 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
}
}
+static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
+ struct mmc_data *data,
+ struct omap_hsmmc_next *next)
+{
+ int dma_len;
+
+ if (!next && data->host_cookie &&
+ data->host_cookie != host->next_data.cookie) {
+ printk(KERN_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;
+ }
+
+ /* Check if next job is already prepared */
+ if (next ||
+ (!next && data->host_cookie != host->next_data.cookie)) {
+ dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len,
+ omap_hsmmc_get_dma_dir(host, data));
+
+ } else {
+ dma_len = host->next_data.dma_len;
+ host->next_data.dma_len = 0;
+ }
+
+
+ if (dma_len == 0)
+ return -EINVAL;
+
+ if (next) {
+ next->dma_len = dma_len;
+ data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
+ } else
+ host->dma_len = dma_len;
+
+ return 0;
+}
+
/*
* Routine to configure and start DMA for the MMC card
*/
@@ -1398,9 +1486,10 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
mmc_hostname(host->mmc), ret);
return ret;
}
+ ret = omap_hsmmc_pre_dma_transfer(host, data, NULL);
+ if (ret)
+ return ret;
- host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
- data->sg_len, omap_hsmmc_get_dma_dir(host, data));
host->dma_ch = dma_ch;
host->dma_sg_idx = 0;
@@ -1480,6 +1569,35 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
return 0;
}
+static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ int err)
+{
+ struct omap_hsmmc_host *host = mmc_priv(mmc);
+ struct mmc_data *data = mrq->data;
+
+ if (host->use_dma) {
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+ omap_hsmmc_get_dma_dir(host, data));
+ data->host_cookie = 0;
+ }
+}
+
+static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ bool is_first_req)
+{
+ struct omap_hsmmc_host *host = mmc_priv(mmc);
+
+ if (mrq->data->host_cookie) {
+ mrq->data->host_cookie = 0;
+ return ;
+ }
+
+ if (host->use_dma)
+ if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
+ &host->next_data))
+ mrq->data->host_cookie = 0;
+}
+
/*
* Request function. for read/write operation
*/
@@ -1528,13 +1646,9 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct omap_hsmmc_host *host = mmc_priv(mmc);
- u16 dsor = 0;
- unsigned long regval;
- unsigned long timeout;
- u32 con;
int do_send_init_stream = 0;
- mmc_host_enable(host->mmc);
+ pm_runtime_get_sync(host->dev);
if (ios->power_mode != host->power_mode) {
switch (ios->power_mode) {
@@ -1557,22 +1671,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
/* FIXME: set registers based only on changes to ios */
- con = OMAP_HSMMC_READ(host->base, CON);
- switch (mmc->ios.bus_width) {
- case MMC_BUS_WIDTH_8:
- OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
- break;
- case MMC_BUS_WIDTH_4:
- OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
- OMAP_HSMMC_WRITE(host->base, HCTL,
- OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
- break;
- case MMC_BUS_WIDTH_1:
- OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
- OMAP_HSMMC_WRITE(host->base, HCTL,
- OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
- break;
- }
+ omap_hsmmc_set_bus_width(host);
if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
/* Only MMC1 can interface at 3V without some flavor
@@ -1592,47 +1691,14 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
}
- if (ios->clock) {
- dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
- if (dsor < 1)
- dsor = 1;
-
- if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
- dsor++;
-
- if (dsor > 250)
- dsor = 250;
- }
- omap_hsmmc_stop_clock(host);
- regval = OMAP_HSMMC_READ(host->base, SYSCTL);
- regval = regval & ~(CLKD_MASK);
- regval = regval | (dsor << 6) | (DTO << 16);
- OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
-
- /* Wait till the ICS bit is set */
- timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
- while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
- && time_before(jiffies, timeout))
- msleep(1);
-
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+ omap_hsmmc_set_clock(host);
if (do_send_init_stream)
send_init_stream(host);
- con = OMAP_HSMMC_READ(host->base, CON);
- if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
- OMAP_HSMMC_WRITE(host->base, CON, con | OD);
- else
- OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
+ omap_hsmmc_set_bus_mode(host);
- if (host->power_mode == MMC_POWER_OFF)
- mmc_host_disable(host->mmc);
- else
- mmc_host_lazy_disable(host->mmc);
+ pm_runtime_put_autosuspend(host->dev);
}
static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -1688,230 +1754,12 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
set_sd_bus_power(host);
}
-/*
- * Dynamic power saving handling, FSM:
- * ENABLED -> DISABLED -> CARDSLEEP / REGSLEEP -> OFF
- * ^___________| | |
- * |______________________|______________________|
- *
- * ENABLED: mmc host is fully functional
- * DISABLED: fclk is off
- * CARDSLEEP: fclk is off, card is asleep, voltage regulator is asleep
- * REGSLEEP: fclk is off, voltage regulator is asleep
- * OFF: fclk is off, voltage regulator is off
- *
- * Transition handlers return the timeout for the next state transition
- * or negative error.
- */
-
-enum {ENABLED = 0, DISABLED, CARDSLEEP, REGSLEEP, OFF};
-
-/* Handler for [ENABLED -> DISABLED] transition */
-static int omap_hsmmc_enabled_to_disabled(struct omap_hsmmc_host *host)
-{
- omap_hsmmc_context_save(host);
- clk_disable(host->fclk);
- host->dpm_state = DISABLED;
-
- dev_dbg(mmc_dev(host->mmc), "ENABLED -> DISABLED\n");
-
- if (host->power_mode == MMC_POWER_OFF)
- return 0;
-
- return OMAP_MMC_SLEEP_TIMEOUT;
-}
-
-/* Handler for [DISABLED -> REGSLEEP / CARDSLEEP] transition */
-static int omap_hsmmc_disabled_to_sleep(struct omap_hsmmc_host *host)
-{
- int err, new_state;
-
- if (!mmc_try_claim_host(host->mmc))
- return 0;
-
- clk_enable(host->fclk);
- omap_hsmmc_context_restore(host);
- if (mmc_card_can_sleep(host->mmc)) {
- err = mmc_card_sleep(host->mmc);
- if (err < 0) {
- clk_disable(host->fclk);
- mmc_release_host(host->mmc);
- return err;
- }
- new_state = CARDSLEEP;
- } else {
- new_state = REGSLEEP;
- }
- if (mmc_slot(host).set_sleep)
- mmc_slot(host).set_sleep(host->dev, host->slot_id, 1, 0,
- new_state == CARDSLEEP);
- /* FIXME: turn off bus power and perhaps interrupts too */
- clk_disable(host->fclk);
- host->dpm_state = new_state;
-
- mmc_release_host(host->mmc);
-
- dev_dbg(mmc_dev(host->mmc), "DISABLED -> %s\n",
- host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
-
- if (mmc_slot(host).no_off)
- return 0;
-
- if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
- mmc_slot(host).card_detect ||
- (mmc_slot(host).get_cover_state &&
- mmc_slot(host).get_cover_state(host->dev, host->slot_id)))
- return OMAP_MMC_OFF_TIMEOUT;
-
- return 0;
-}
-
-/* Handler for [REGSLEEP / CARDSLEEP -> OFF] transition */
-static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
-{
- if (!mmc_try_claim_host(host->mmc))
- return 0;
-
- if (mmc_slot(host).no_off)
- return 0;
-
- if (!((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
- mmc_slot(host).card_detect ||
- (mmc_slot(host).get_cover_state &&
- mmc_slot(host).get_cover_state(host->dev, host->slot_id)))) {
- mmc_release_host(host->mmc);
- return 0;
- }
-
- mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
- host->vdd = 0;
- host->power_mode = MMC_POWER_OFF;
-
- dev_dbg(mmc_dev(host->mmc), "%s -> OFF\n",
- host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
-
- host->dpm_state = OFF;
-
- mmc_release_host(host->mmc);
-
- return 0;
-}
-
-/* Handler for [DISABLED -> ENABLED] transition */
-static int omap_hsmmc_disabled_to_enabled(struct omap_hsmmc_host *host)
-{
- int err;
-
- err = clk_enable(host->fclk);
- if (err < 0)
- return err;
-
- omap_hsmmc_context_restore(host);
- host->dpm_state = ENABLED;
-
- dev_dbg(mmc_dev(host->mmc), "DISABLED -> ENABLED\n");
-
- return 0;
-}
-
-/* Handler for [SLEEP -> ENABLED] transition */
-static int omap_hsmmc_sleep_to_enabled(struct omap_hsmmc_host *host)
-{
- if (!mmc_try_claim_host(host->mmc))
- return 0;
-
- clk_enable(host->fclk);
- omap_hsmmc_context_restore(host);
- if (mmc_slot(host).set_sleep)
- mmc_slot(host).set_sleep(host->dev, host->slot_id, 0,
- host->vdd, host->dpm_state == CARDSLEEP);
- if (mmc_card_can_sleep(host->mmc))
- mmc_card_awake(host->mmc);
-
- dev_dbg(mmc_dev(host->mmc), "%s -> ENABLED\n",
- host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
-
- host->dpm_state = ENABLED;
-
- mmc_release_host(host->mmc);
-
- return 0;
-}
-
-/* Handler for [OFF -> ENABLED] transition */
-static int omap_hsmmc_off_to_enabled(struct omap_hsmmc_host *host)
-{
- clk_enable(host->fclk);
-
- omap_hsmmc_context_restore(host);
- omap_hsmmc_conf_bus_power(host);
- mmc_power_restore_host(host->mmc);
-
- host->dpm_state = ENABLED;
-
- dev_dbg(mmc_dev(host->mmc), "OFF -> ENABLED\n");
-
- return 0;
-}
-
-/*
- * Bring MMC host to ENABLED from any other PM state.
- */
-static int omap_hsmmc_enable(struct mmc_host *mmc)
-{
- struct omap_hsmmc_host *host = mmc_priv(mmc);
-
- switch (host->dpm_state) {
- case DISABLED:
- return omap_hsmmc_disabled_to_enabled(host);
- case CARDSLEEP:
- case REGSLEEP:
- return omap_hsmmc_sleep_to_enabled(host);
- case OFF:
- return omap_hsmmc_off_to_enabled(host);
- default:
- dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n");
- return -EINVAL;
- }
-}
-
-/*
- * Bring MMC host in PM state (one level deeper).
- */
-static int omap_hsmmc_disable(struct mmc_host *mmc, int lazy)
-{
- struct omap_hsmmc_host *host = mmc_priv(mmc);
-
- switch (host->dpm_state) {
- case ENABLED: {
- int delay;
-
- delay = omap_hsmmc_enabled_to_disabled(host);
- if (lazy || delay < 0)
- return delay;
- return 0;
- }
- case DISABLED:
- return omap_hsmmc_disabled_to_sleep(host);
- case CARDSLEEP:
- case REGSLEEP:
- return omap_hsmmc_sleep_to_off(host);
- default:
- dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n");
- return -EINVAL;
- }
-}
-
static int omap_hsmmc_enable_fclk(struct mmc_host *mmc)
{
struct omap_hsmmc_host *host = mmc_priv(mmc);
- int err;
- err = clk_enable(host->fclk);
- if (err)
- return err;
- dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n");
- omap_hsmmc_context_restore(host);
+ pm_runtime_get_sync(host->dev);
+
return 0;
}
@@ -1919,26 +1767,17 @@ static int omap_hsmmc_disable_fclk(struct mmc_host *mmc, int lazy)
{
struct omap_hsmmc_host *host = mmc_priv(mmc);
- omap_hsmmc_context_save(host);
- clk_disable(host->fclk);
- dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n");
+ pm_runtime_mark_last_busy(host->dev);
+ pm_runtime_put_autosuspend(host->dev);
+
return 0;
}
static const struct mmc_host_ops omap_hsmmc_ops = {
.enable = omap_hsmmc_enable_fclk,
.disable = omap_hsmmc_disable_fclk,
- .request = omap_hsmmc_request,
- .set_ios = omap_hsmmc_set_ios,
- .get_cd = omap_hsmmc_get_cd,
- .get_ro = omap_hsmmc_get_ro,
- .init_card = omap_hsmmc_init_card,
- /* NYET -- enable_sdio_irq */
-};
-
-static const struct mmc_host_ops omap_hsmmc_ps_ops = {
- .enable = omap_hsmmc_enable,
- .disable = omap_hsmmc_disable,
+ .post_req = omap_hsmmc_post_req,
+ .pre_req = omap_hsmmc_pre_req,
.request = omap_hsmmc_request,
.set_ios = omap_hsmmc_set_ios,
.get_cd = omap_hsmmc_get_cd,
@@ -1968,15 +1807,12 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
host->dpm_state, mmc->nesting_cnt,
host->context_loss, context_loss);
- if (host->suspended || host->dpm_state == OFF) {
+ if (host->suspended) {
seq_printf(s, "host suspended, can't read registers\n");
return 0;
}
- if (clk_enable(host->fclk) != 0) {
- seq_printf(s, "can't read the regs\n");
- return 0;
- }
+ pm_runtime_get_sync(host->dev);
seq_printf(s, "SYSCONFIG:\t0x%08x\n",
OMAP_HSMMC_READ(host->base, SYSCONFIG));
@@ -1993,7 +1829,8 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
seq_printf(s, "CAPA:\t\t0x%08x\n",
OMAP_HSMMC_READ(host->base, CAPA));
- clk_disable(host->fclk);
+ pm_runtime_mark_last_busy(host->dev);
+ pm_runtime_put_autosuspend(host->dev);
return 0;
}
@@ -2077,14 +1914,12 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
host->mapbase = res->start;
host->base = ioremap(host->mapbase, SZ_4K);
host->power_mode = MMC_POWER_OFF;
+ host->next_data.cookie = 1;
platform_set_drvdata(pdev, host);
INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect);
- if (mmc_slot(host).power_saving)
- mmc->ops = &omap_hsmmc_ps_ops;
- else
- mmc->ops = &omap_hsmmc_ops;
+ mmc->ops = &omap_hsmmc_ops;
/*
* If regulator_disable can only put vcc_aux to sleep then there is
@@ -2093,44 +1928,26 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
if (mmc_slot(host).vcc_aux_disable_is_sleep)
mmc_slot(host).no_off = 1;
- mmc->f_min = 400000;
- mmc->f_max = 52000000;
+ mmc->f_min = OMAP_MMC_MIN_CLOCK;
+ mmc->f_max = OMAP_MMC_MAX_CLOCK;
spin_lock_init(&host->irq_lock);
- host->iclk = clk_get(&pdev->dev, "ick");
- if (IS_ERR(host->iclk)) {
- ret = PTR_ERR(host->iclk);
- host->iclk = NULL;
- goto err1;
- }
host->fclk = clk_get(&pdev->dev, "fck");
if (IS_ERR(host->fclk)) {
ret = PTR_ERR(host->fclk);
host->fclk = NULL;
- clk_put(host->iclk);
goto err1;
}
omap_hsmmc_context_save(host);
mmc->caps |= MMC_CAP_DISABLE;
- mmc_set_disable_delay(mmc, OMAP_MMC_DISABLED_TIMEOUT);
- /* we start off in DISABLED state */
- host->dpm_state = DISABLED;
- if (clk_enable(host->iclk) != 0) {
- clk_put(host->iclk);
- clk_put(host->fclk);
- goto err1;
- }
-
- if (mmc_host_enable(host->mmc) != 0) {
- clk_disable(host->iclk);
- clk_put(host->iclk);
- clk_put(host->fclk);
- goto err1;
- }
+ pm_runtime_enable(host->dev);
+ pm_runtime_get_sync(host->dev);
+ pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(host->dev);
if (cpu_is_omap2430()) {
host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
@@ -2240,8 +2057,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
omap_hsmmc_disable_irq(host);
- mmc_host_lazy_disable(host->mmc);
-
omap_hsmmc_protect_card(host);
mmc_add_host(mmc);
@@ -2259,6 +2074,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
}
omap_hsmmc_debugfs(mmc);
+ pm_runtime_mark_last_busy(host->dev);
+ pm_runtime_put_autosuspend(host->dev);
return 0;
@@ -2274,10 +2091,9 @@ err_reg:
err_irq_cd_init:
free_irq(host->irq, host);
err_irq:
- mmc_host_disable(host->mmc);
- clk_disable(host->iclk);
+ pm_runtime_mark_last_busy(host->dev);
+ pm_runtime_put_autosuspend(host->dev);
clk_put(host->fclk);
- clk_put(host->iclk);
if (host->got_dbclk) {
clk_disable(host->dbclk);
clk_put(host->dbclk);
@@ -2299,7 +2115,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
struct resource *res;
if (host) {
- mmc_host_enable(host->mmc);
+ pm_runtime_get_sync(host->dev);
mmc_remove_host(host->mmc);
if (host->use_reg)
omap_hsmmc_reg_put(host);
@@ -2310,10 +2126,9 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
free_irq(mmc_slot(host).card_detect_irq, host);
flush_work_sync(&host->mmc_carddetect_work);
- mmc_host_disable(host->mmc);
- clk_disable(host->iclk);
+ pm_runtime_put_sync(host->dev);
+ pm_runtime_disable(host->dev);
clk_put(host->fclk);
- clk_put(host->iclk);
if (host->got_dbclk) {
clk_disable(host->dbclk);
clk_put(host->dbclk);
@@ -2343,6 +2158,7 @@ static int omap_hsmmc_suspend(struct device *dev)
return 0;
if (host) {
+ pm_runtime_get_sync(host->dev);
host->suspended = 1;
if (host->pdata->suspend) {
ret = host->pdata->suspend(&pdev->dev,
@@ -2357,13 +2173,11 @@ static int omap_hsmmc_suspend(struct device *dev)
}
cancel_work_sync(&host->mmc_carddetect_work);
ret = mmc_suspend_host(host->mmc);
- mmc_host_enable(host->mmc);
+
if (ret == 0) {
omap_hsmmc_disable_irq(host);
OMAP_HSMMC_WRITE(host->base, HCTL,
OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
- mmc_host_disable(host->mmc);
- clk_disable(host->iclk);
if (host->got_dbclk)
clk_disable(host->dbclk);
} else {
@@ -2375,9 +2189,8 @@ static int omap_hsmmc_suspend(struct device *dev)
dev_dbg(mmc_dev(host->mmc),
"Unmask interrupt failed\n");
}
- mmc_host_disable(host->mmc);
}
-
+ pm_runtime_put_sync(host->dev);
}
return ret;
}
@@ -2393,14 +2206,7 @@ static int omap_hsmmc_resume(struct device *dev)
return 0;
if (host) {
- ret = clk_enable(host->iclk);
- if (ret)
- goto clk_en_err;
-
- if (mmc_host_enable(host->mmc) != 0) {
- clk_disable(host->iclk);
- goto clk_en_err;
- }
+ pm_runtime_get_sync(host->dev);
if (host->got_dbclk)
clk_enable(host->dbclk);
@@ -2421,15 +2227,12 @@ static int omap_hsmmc_resume(struct device *dev)
if (ret == 0)
host->suspended = 0;
- mmc_host_lazy_disable(host->mmc);
+ pm_runtime_mark_last_busy(host->dev);
+ pm_runtime_put_autosuspend(host->dev);
}
return ret;
-clk_en_err:
- dev_dbg(mmc_dev(host->mmc),
- "Failed to enable MMC clocks during resume\n");
- return ret;
}
#else
@@ -2437,9 +2240,33 @@ clk_en_err:
#define omap_hsmmc_resume NULL
#endif
+static int omap_hsmmc_runtime_suspend(struct device *dev)
+{
+ struct omap_hsmmc_host *host;
+
+ host = platform_get_drvdata(to_platform_device(dev));
+ omap_hsmmc_context_save(host);
+ dev_dbg(mmc_dev(host->mmc), "disabled\n");
+
+ return 0;
+}
+
+static int omap_hsmmc_runtime_resume(struct device *dev)
+{
+ struct omap_hsmmc_host *host;
+
+ host = platform_get_drvdata(to_platform_device(dev));
+ omap_hsmmc_context_restore(host);
+ dev_dbg(mmc_dev(host->mmc), "enabled\n");
+
+ return 0;
+}
+
static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
.suspend = omap_hsmmc_suspend,
.resume = omap_hsmmc_resume,
+ .runtime_suspend = omap_hsmmc_runtime_suspend,
+ .runtime_resume = omap_hsmmc_runtime_resume,
};
static struct platform_driver omap_hsmmc_driver = {
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index 9ebd1d7759dc..4b920b7621cf 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -15,9 +15,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-pltfm.h>
#include <mach/cns3xxx.h>
-#include "sdhci.h"
#include "sdhci-pltfm.h"
static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host)
@@ -86,7 +84,7 @@ static struct sdhci_ops sdhci_cns3xxx_ops = {
.set_clock = sdhci_cns3xxx_set_clock,
};
-struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
+static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
.ops = &sdhci_cns3xxx_ops,
.quirks = SDHCI_QUIRK_BROKEN_DMA |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -95,3 +93,43 @@ struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_NONSTANDARD_CLOCK,
};
+
+static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
+}
+
+static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static struct platform_driver sdhci_cns3xxx_driver = {
+ .driver = {
+ .name = "sdhci-cns3xxx",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_cns3xxx_probe,
+ .remove = __devexit_p(sdhci_cns3xxx_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_cns3xxx_init(void)
+{
+ return platform_driver_register(&sdhci_cns3xxx_driver);
+}
+module_init(sdhci_cns3xxx_init);
+
+static void __exit sdhci_cns3xxx_exit(void)
+{
+ platform_driver_unregister(&sdhci_cns3xxx_driver);
+}
+module_exit(sdhci_cns3xxx_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for CNS3xxx");
+MODULE_AUTHOR("Scott Shu, "
+ "Anton Vorontsov <avorontsov@mvista.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 2aeef4ffed8c..f2d29dca4420 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -22,7 +22,6 @@
#include <linux/io.h>
#include <linux/mmc/host.h>
-#include "sdhci.h"
#include "sdhci-pltfm.h"
static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
@@ -61,10 +60,50 @@ static struct sdhci_ops sdhci_dove_ops = {
.read_l = sdhci_dove_readl,
};
-struct sdhci_pltfm_data sdhci_dove_pdata = {
+static struct sdhci_pltfm_data sdhci_dove_pdata = {
.ops = &sdhci_dove_ops,
.quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
SDHCI_QUIRK_NO_BUSY_IRQ |
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_FORCE_DMA,
};
+
+static int __devinit sdhci_dove_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+}
+
+static int __devexit sdhci_dove_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static struct platform_driver sdhci_dove_driver = {
+ .driver = {
+ .name = "sdhci-dove",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_dove_probe,
+ .remove = __devexit_p(sdhci_dove_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_dove_init(void)
+{
+ return platform_driver_register(&sdhci_dove_driver);
+}
+module_init(sdhci_dove_init);
+
+static void __exit sdhci_dove_exit(void)
+{
+ platform_driver_unregister(&sdhci_dove_driver);
+}
+module_exit(sdhci_dove_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Dove");
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, "
+ "Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a19967d0bfc4..710b706f4fcf 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -18,12 +18,10 @@
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-pltfm.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
#include <mach/hardware.h>
#include <mach/esdhc.h>
-#include "sdhci.h"
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -31,7 +29,7 @@
#define SDHCI_VENDOR_SPEC 0xC0
#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
-#define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0)
+#define ESDHC_FLAG_GPIO_FOR_CD (1 << 0)
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
* "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -67,14 +65,14 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
u32 val = readl(host->ioaddr + reg);
if (unlikely((reg == SDHCI_PRESENT_STATE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
+ && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
struct esdhc_platform_data *boarddata =
host->mmc->parent->platform_data;
if (boarddata && gpio_is_valid(boarddata->cd_gpio)
&& gpio_get_value(boarddata->cd_gpio))
/* no card, if a valid gpio says so... */
- val &= SDHCI_CARD_PRESENT;
+ val &= ~SDHCI_CARD_PRESENT;
else
/* ... in all other cases assume card is present */
val |= SDHCI_CARD_PRESENT;
@@ -89,7 +87,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
struct pltfm_imx_data *imx_data = pltfm_host->priv;
if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
+ && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
/*
* these interrupts won't work with a custom card_detect gpio
* (only applied to mx25/35)
@@ -191,16 +189,6 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk) / 256 / 16;
}
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
- struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
-
- if (boarddata && gpio_is_valid(boarddata->wp_gpio))
- return gpio_get_value(boarddata->wp_gpio);
- else
- return -ENOSYS;
-}
-
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@@ -212,6 +200,24 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_min_clock = esdhc_pltfm_get_min_clock,
};
+static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+ | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+ /* ADMA has issues. Might be fixable */
+ .ops = &sdhci_esdhc_ops,
+};
+
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+ struct esdhc_platform_data *boarddata =
+ host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ else
+ return -ENOSYS;
+}
+
static irqreturn_t cd_irq(int irq, void *data)
{
struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -220,30 +226,35 @@ static irqreturn_t cd_irq(int irq, void *data)
return IRQ_HANDLED;
};
-static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
+static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_host *host;
+ struct esdhc_platform_data *boarddata;
struct clk *clk;
int err;
struct pltfm_imx_data *imx_data;
+ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ pltfm_host = sdhci_priv(host);
+
+ imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+ if (!imx_data)
+ return -ENOMEM;
+ pltfm_host->priv = imx_data;
+
clk = clk_get(mmc_dev(host->mmc), NULL);
if (IS_ERR(clk)) {
dev_err(mmc_dev(host->mmc), "clk err\n");
- return PTR_ERR(clk);
+ err = PTR_ERR(clk);
+ goto err_clk_get;
}
clk_enable(clk);
pltfm_host->clk = clk;
- imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
- if (!imx_data) {
- clk_disable(pltfm_host->clk);
- clk_put(pltfm_host->clk);
- return -ENOMEM;
- }
- pltfm_host->priv = imx_data;
-
if (!cpu_is_mx25())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
@@ -257,6 +268,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
+ boarddata = host->mmc->parent->platform_data;
if (boarddata) {
err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
if (err) {
@@ -284,11 +296,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
goto no_card_detect_irq;
}
- imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
+ imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
/* Now we have a working card_detect again */
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
+ err = sdhci_add_host(host);
+ if (err)
+ goto err_add_host;
+
return 0;
no_card_detect_irq:
@@ -297,14 +313,23 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
boarddata->cd_gpio = err;
not_supported:
kfree(imx_data);
- return 0;
+ err_add_host:
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+ err_clk_get:
+ sdhci_pltfm_free(pdev);
+ return err;
}
-static void esdhc_pltfm_exit(struct sdhci_host *host)
+static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+ sdhci_remove_host(host, dead);
if (boarddata && gpio_is_valid(boarddata->wp_gpio))
gpio_free(boarddata->wp_gpio);
@@ -319,13 +344,37 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
kfree(imx_data);
+
+ sdhci_pltfm_free(pdev);
+
+ return 0;
}
-struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
- .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
- | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
- /* ADMA has issues. Might be fixable */
- .ops = &sdhci_esdhc_ops,
- .init = esdhc_pltfm_init,
- .exit = esdhc_pltfm_exit,
+static struct platform_driver sdhci_esdhc_imx_driver = {
+ .driver = {
+ .name = "sdhci-esdhc-imx",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_esdhc_imx_probe,
+ .remove = __devexit_p(sdhci_esdhc_imx_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
};
+
+static int __init sdhci_esdhc_imx_init(void)
+{
+ return platform_driver_register(&sdhci_esdhc_imx_driver);
+}
+module_init(sdhci_esdhc_imx_init);
+
+static void __exit sdhci_esdhc_imx_exit(void)
+{
+ platform_driver_unregister(&sdhci_esdhc_imx_driver);
+}
+module_exit(sdhci_esdhc_imx_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
deleted file mode 100644
index 60e4186a4345..000000000000
--- a/drivers/mmc/host/sdhci-of-core.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * OpenFirmware bindings for Secure Digital Host Controller Interface.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- * Anton Vorontsov <avorontsov@ru.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.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/mmc/host.h>
-#ifdef CONFIG_PPC
-#include <asm/machdep.h>
-#endif
-#include "sdhci-of.h"
-#include "sdhci.h"
-
-#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
-
-/*
- * These accessors are designed for big endian hosts doing I/O to
- * little endian controllers incorporating a 32-bit hardware byte swapper.
- */
-
-u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
-{
- return in_be32(host->ioaddr + reg);
-}
-
-u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
-{
- return in_be16(host->ioaddr + (reg ^ 0x2));
-}
-
-u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
-{
- return in_8(host->ioaddr + (reg ^ 0x3));
-}
-
-void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
-{
- out_be32(host->ioaddr + reg, val);
-}
-
-void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
-{
- struct sdhci_of_host *of_host = sdhci_priv(host);
- int base = reg & ~0x3;
- int shift = (reg & 0x2) * 8;
-
- switch (reg) {
- case SDHCI_TRANSFER_MODE:
- /*
- * Postpone this write, we must do it together with a
- * command write that is down below.
- */
- of_host->xfer_mode_shadow = val;
- return;
- case SDHCI_COMMAND:
- sdhci_be32bs_writel(host, val << 16 | of_host->xfer_mode_shadow,
- SDHCI_TRANSFER_MODE);
- return;
- }
- clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
-}
-
-void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
-{
- int base = reg & ~0x3;
- int shift = (reg & 0x3) * 8;
-
- clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
-}
-#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
-
-#ifdef CONFIG_PM
-
-static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state)
-{
- struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
- return mmc_suspend_host(host->mmc);
-}
-
-static int sdhci_of_resume(struct platform_device *ofdev)
-{
- struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
- return mmc_resume_host(host->mmc);
-}
-
-#else
-
-#define sdhci_of_suspend NULL
-#define sdhci_of_resume NULL
-
-#endif
-
-static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
-{
- if (of_get_property(np, "sdhci,wp-inverted", NULL))
- return true;
-
- /* Old device trees don't have the wp-inverted property. */
-#ifdef CONFIG_PPC
- return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
-#else
- return false;
-#endif
-}
-
-static const struct of_device_id sdhci_of_match[];
-static int __devinit sdhci_of_probe(struct platform_device *ofdev)
-{
- const struct of_device_id *match;
- struct device_node *np = ofdev->dev.of_node;
- struct sdhci_of_data *sdhci_of_data;
- struct sdhci_host *host;
- struct sdhci_of_host *of_host;
- const __be32 *clk;
- int size;
- int ret;
-
- match = of_match_device(sdhci_of_match, &ofdev->dev);
- if (!match)
- return -EINVAL;
- sdhci_of_data = match->data;
-
- if (!of_device_is_available(np))
- return -ENODEV;
-
- host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
- if (IS_ERR(host))
- return -ENOMEM;
-
- of_host = sdhci_priv(host);
- dev_set_drvdata(&ofdev->dev, host);
-
- host->ioaddr = of_iomap(np, 0);
- if (!host->ioaddr) {
- ret = -ENOMEM;
- goto err_addr_map;
- }
-
- host->irq = irq_of_parse_and_map(np, 0);
- if (!host->irq) {
- ret = -EINVAL;
- goto err_no_irq;
- }
-
- host->hw_name = dev_name(&ofdev->dev);
- if (sdhci_of_data) {
- host->quirks = sdhci_of_data->quirks;
- host->ops = &sdhci_of_data->ops;
- }
-
- if (of_get_property(np, "sdhci,auto-cmd12", NULL))
- host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
-
-
- if (of_get_property(np, "sdhci,1-bit-only", NULL))
- host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
-
- if (sdhci_of_wp_inverted(np))
- host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-
- clk = of_get_property(np, "clock-frequency", &size);
- if (clk && size == sizeof(*clk) && *clk)
- of_host->clock = be32_to_cpup(clk);
-
- ret = sdhci_add_host(host);
- if (ret)
- goto err_add_host;
-
- return 0;
-
-err_add_host:
- irq_dispose_mapping(host->irq);
-err_no_irq:
- iounmap(host->ioaddr);
-err_addr_map:
- sdhci_free_host(host);
- return ret;
-}
-
-static int __devexit sdhci_of_remove(struct platform_device *ofdev)
-{
- struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
- sdhci_remove_host(host, 0);
- sdhci_free_host(host);
- irq_dispose_mapping(host->irq);
- iounmap(host->ioaddr);
- return 0;
-}
-
-static const struct of_device_id sdhci_of_match[] = {
-#ifdef CONFIG_MMC_SDHCI_OF_ESDHC
- { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },
- { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, },
- { .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },
-#endif
-#ifdef CONFIG_MMC_SDHCI_OF_HLWD
- { .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd, },
-#endif
- { .compatible = "generic-sdhci", },
- {},
-};
-MODULE_DEVICE_TABLE(of, sdhci_of_match);
-
-static struct platform_driver sdhci_of_driver = {
- .driver = {
- .name = "sdhci-of",
- .owner = THIS_MODULE,
- .of_match_table = sdhci_of_match,
- },
- .probe = sdhci_of_probe,
- .remove = __devexit_p(sdhci_of_remove),
- .suspend = sdhci_of_suspend,
- .resume = sdhci_of_resume,
-};
-
-static int __init sdhci_of_init(void)
-{
- return platform_driver_register(&sdhci_of_driver);
-}
-module_init(sdhci_of_init);
-
-static void __exit sdhci_of_exit(void)
-{
- platform_driver_unregister(&sdhci_of_driver);
-}
-module_exit(sdhci_of_exit);
-
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver");
-MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
- "Anton Vorontsov <avorontsov@ru.mvista.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index ba40d6d035c7..fe604df65011 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -16,8 +16,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/mmc/host.h>
-#include "sdhci-of.h"
-#include "sdhci.h"
+#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
static u16 esdhc_readw(struct sdhci_host *host, int reg)
@@ -60,32 +59,83 @@ static int esdhc_of_enable_dma(struct sdhci_host *host)
static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
{
- struct sdhci_of_host *of_host = sdhci_priv(host);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- return of_host->clock;
+ return pltfm_host->clock;
}
static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
{
- struct sdhci_of_host *of_host = sdhci_priv(host);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- return of_host->clock / 256 / 16;
+ return pltfm_host->clock / 256 / 16;
}
-struct sdhci_of_data sdhci_esdhc = {
+static struct sdhci_ops sdhci_esdhc_ops = {
+ .read_l = sdhci_be32bs_readl,
+ .read_w = esdhc_readw,
+ .read_b = sdhci_be32bs_readb,
+ .write_l = sdhci_be32bs_writel,
+ .write_w = esdhc_writew,
+ .write_b = esdhc_writeb,
+ .set_clock = esdhc_set_clock,
+ .enable_dma = esdhc_of_enable_dma,
+ .get_max_clock = esdhc_of_get_max_clock,
+ .get_min_clock = esdhc_of_get_min_clock,
+};
+
+static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
/* card detection could be handled via GPIO */
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
| SDHCI_QUIRK_NO_CARD_NO_RESET,
- .ops = {
- .read_l = sdhci_be32bs_readl,
- .read_w = esdhc_readw,
- .read_b = sdhci_be32bs_readb,
- .write_l = sdhci_be32bs_writel,
- .write_w = esdhc_writew,
- .write_b = esdhc_writeb,
- .set_clock = esdhc_set_clock,
- .enable_dma = esdhc_of_enable_dma,
- .get_max_clock = esdhc_of_get_max_clock,
- .get_min_clock = esdhc_of_get_min_clock,
+ .ops = &sdhci_esdhc_ops,
+};
+
+static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
+}
+
+static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static const struct of_device_id sdhci_esdhc_of_match[] = {
+ { .compatible = "fsl,mpc8379-esdhc" },
+ { .compatible = "fsl,mpc8536-esdhc" },
+ { .compatible = "fsl,esdhc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
+
+static struct platform_driver sdhci_esdhc_driver = {
+ .driver = {
+ .name = "sdhci-esdhc",
+ .owner = THIS_MODULE,
+ .of_match_table = sdhci_esdhc_of_match,
},
+ .probe = sdhci_esdhc_probe,
+ .remove = __devexit_p(sdhci_esdhc_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
};
+
+static int __init sdhci_esdhc_init(void)
+{
+ return platform_driver_register(&sdhci_esdhc_driver);
+}
+module_init(sdhci_esdhc_init);
+
+static void __exit sdhci_esdhc_exit(void)
+{
+ platform_driver_unregister(&sdhci_esdhc_driver);
+}
+module_exit(sdhci_esdhc_exit);
+
+MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC");
+MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
+ "Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 68ddb7546ae2..735be131dca9 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -21,8 +21,7 @@
#include <linux/delay.h>
#include <linux/mmc/host.h>
-#include "sdhci-of.h"
-#include "sdhci.h"
+#include "sdhci-pltfm.h"
/*
* Ops and quirks for the Nintendo Wii SDHCI controllers.
@@ -51,15 +50,63 @@ static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg)
udelay(SDHCI_HLWD_WRITE_DELAY);
}
-struct sdhci_of_data sdhci_hlwd = {
+static struct sdhci_ops sdhci_hlwd_ops = {
+ .read_l = sdhci_be32bs_readl,
+ .read_w = sdhci_be32bs_readw,
+ .read_b = sdhci_be32bs_readb,
+ .write_l = sdhci_hlwd_writel,
+ .write_w = sdhci_hlwd_writew,
+ .write_b = sdhci_hlwd_writeb,
+};
+
+static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_32BIT_DMA_SIZE,
- .ops = {
- .read_l = sdhci_be32bs_readl,
- .read_w = sdhci_be32bs_readw,
- .read_b = sdhci_be32bs_readb,
- .write_l = sdhci_hlwd_writel,
- .write_w = sdhci_hlwd_writew,
- .write_b = sdhci_hlwd_writeb,
+ .ops = &sdhci_hlwd_ops,
+};
+
+static int __devinit sdhci_hlwd_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
+}
+
+static int __devexit sdhci_hlwd_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static const struct of_device_id sdhci_hlwd_of_match[] = {
+ { .compatible = "nintendo,hollywood-sdhci" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_hlwd_of_match);
+
+static struct platform_driver sdhci_hlwd_driver = {
+ .driver = {
+ .name = "sdhci-hlwd",
+ .owner = THIS_MODULE,
+ .of_match_table = sdhci_hlwd_of_match,
},
+ .probe = sdhci_hlwd_probe,
+ .remove = __devexit_p(sdhci_hlwd_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
};
+
+static int __init sdhci_hlwd_init(void)
+{
+ return platform_driver_register(&sdhci_hlwd_driver);
+}
+module_init(sdhci_hlwd_init);
+
+static void __exit sdhci_hlwd_exit(void)
+{
+ platform_driver_unregister(&sdhci_hlwd_driver);
+}
+module_exit(sdhci_hlwd_exit);
+
+MODULE_DESCRIPTION("Nintendo Wii SDHCI OF driver");
+MODULE_AUTHOR("The GameCube Linux Team, Albert Herranz");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of.h b/drivers/mmc/host/sdhci-of.h
deleted file mode 100644
index ad09ad9915d8..000000000000
--- a/drivers/mmc/host/sdhci-of.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * OpenFirmware bindings for Secure Digital Host Controller Interface.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- * Anton Vorontsov <avorontsov@ru.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 __SDHCI_OF_H
-#define __SDHCI_OF_H
-
-#include <linux/types.h>
-#include "sdhci.h"
-
-struct sdhci_of_data {
- unsigned int quirks;
- struct sdhci_ops ops;
-};
-
-struct sdhci_of_host {
- unsigned int clock;
- u16 xfer_mode_shadow;
-};
-
-extern u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg);
-extern u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg);
-extern u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg);
-extern void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg);
-extern void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg);
-extern void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg);
-
-extern struct sdhci_of_data sdhci_esdhc;
-extern struct sdhci_of_data sdhci_hlwd;
-
-#endif /* __SDHCI_OF_H */
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 936bbca19c0a..26c528648f3c 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -143,6 +143,12 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
};
+static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot)
+{
+ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+ return 0;
+}
+
/*
* ADMA operation is disabled for Moorestown platform due to
* hardware bugs.
@@ -157,8 +163,15 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip)
return 0;
}
+static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
+{
+ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+ return 0;
+}
+
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,
};
static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
@@ -170,8 +183,13 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
};
-static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc_sdio = {
+static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
+ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+};
+
+static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .probe_slot = mfd_emmc_probe_slot,
};
/* O2Micro extra registers */
@@ -682,7 +700,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.device = PCI_DEVICE_ID_INTEL_MFD_SDIO1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sdio,
},
{
@@ -690,7 +708,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.device = PCI_DEVICE_ID_INTEL_MFD_SDIO2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sdio,
},
{
@@ -698,7 +716,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.device = PCI_DEVICE_ID_INTEL_MFD_EMMC0,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc,
},
{
@@ -706,7 +724,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.device = PCI_DEVICE_ID_INTEL_MFD_EMMC1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc,
},
{
@@ -789,8 +807,34 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
return 0;
}
+static int sdhci_pci_8bit_width(struct sdhci_host *host, int width)
+{
+ u8 ctrl;
+
+ ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+
+ switch (width) {
+ case MMC_BUS_WIDTH_8:
+ ctrl |= SDHCI_CTRL_8BITBUS;
+ ctrl &= ~SDHCI_CTRL_4BITBUS;
+ break;
+ case MMC_BUS_WIDTH_4:
+ ctrl |= SDHCI_CTRL_4BITBUS;
+ ctrl &= ~SDHCI_CTRL_8BITBUS;
+ break;
+ default:
+ ctrl &= ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_4BITBUS);
+ break;
+ }
+
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
+ return 0;
+}
+
static struct sdhci_ops sdhci_pci_ops = {
.enable_dma = sdhci_pci_enable_dma,
+ .platform_8bit_width = sdhci_pci_8bit_width,
};
/*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index dbab0407f4b6..71c0ce1f6db0 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -2,6 +2,12 @@
* sdhci-pltfm.c Support for SDHCI platform devices
* Copyright (c) 2009 Intel Corporation
*
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ * Anton Vorontsov <avorontsov@ru.mvista.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.
@@ -22,48 +28,66 @@
* Inspired by sdhci-pci.c, by Pierre Ossman
*/
-#include <linux/delay.h>
-#include <linux/highmem.h>
-#include <linux/mod_devicetable.h>
-#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#ifdef CONFIG_PPC
+#include <asm/machdep.h>
+#endif
+#include "sdhci-pltfm.h"
-#include <linux/mmc/host.h>
+static struct sdhci_ops sdhci_pltfm_ops = {
+};
-#include <linux/io.h>
-#include <linux/mmc/sdhci-pltfm.h>
+#ifdef CONFIG_OF
+static bool sdhci_of_wp_inverted(struct device_node *np)
+{
+ if (of_get_property(np, "sdhci,wp-inverted", NULL))
+ return true;
-#include "sdhci.h"
-#include "sdhci-pltfm.h"
+ /* Old device trees don't have the wp-inverted property. */
+#ifdef CONFIG_PPC
+ return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
+#else
+ return false;
+#endif /* CONFIG_PPC */
+}
+
+void sdhci_get_of_property(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ const __be32 *clk;
+ int size;
-/*****************************************************************************\
- * *
- * SDHCI core callbacks *
- * *
-\*****************************************************************************/
+ if (of_device_is_available(np)) {
+ if (of_get_property(np, "sdhci,auto-cmd12", NULL))
+ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
-static struct sdhci_ops sdhci_pltfm_ops = {
-};
+ if (of_get_property(np, "sdhci,1-bit-only", NULL))
+ host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
-/*****************************************************************************\
- * *
- * Device probing/removal *
- * *
-\*****************************************************************************/
+ if (sdhci_of_wp_inverted(np))
+ host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
+ clk = of_get_property(np, "clock-frequency", &size);
+ if (clk && size == sizeof(*clk) && *clk)
+ pltfm_host->clock = be32_to_cpup(clk);
+ }
+}
+#else
+void sdhci_get_of_property(struct platform_device *pdev) {}
+#endif /* CONFIG_OF */
+EXPORT_SYMBOL_GPL(sdhci_get_of_property);
+
+struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata)
{
- const struct platform_device_id *platid = platform_get_device_id(pdev);
- struct sdhci_pltfm_data *pdata;
struct sdhci_host *host;
struct sdhci_pltfm_host *pltfm_host;
struct resource *iomem;
int ret;
- if (platid && platid->driver_data)
- pdata = (void *)platid->driver_data;
- else
- pdata = pdev->dev.platform_data;
-
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!iomem) {
ret = -ENOMEM;
@@ -71,8 +95,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
}
if (resource_size(iomem) < 0x100)
- dev_err(&pdev->dev, "Invalid iomem size. You may "
- "experience problems.\n");
+ dev_err(&pdev->dev, "Invalid iomem size!\n");
/* Some PCI-based MFD need the parent here */
if (pdev->dev.parent != &platform_bus)
@@ -87,7 +110,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
- host->hw_name = "platform";
+ host->hw_name = dev_name(&pdev->dev);
if (pdata && pdata->ops)
host->ops = pdata->ops;
else
@@ -110,126 +133,95 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
goto err_remap;
}
- if (pdata && pdata->init) {
- ret = pdata->init(host, pdata);
- if (ret)
- goto err_plat_init;
- }
-
- ret = sdhci_add_host(host);
- if (ret)
- goto err_add_host;
-
platform_set_drvdata(pdev, host);
- return 0;
+ return host;
-err_add_host:
- if (pdata && pdata->exit)
- pdata->exit(host);
-err_plat_init:
- iounmap(host->ioaddr);
err_remap:
release_mem_region(iomem->start, resource_size(iomem));
err_request:
sdhci_free_host(host);
err:
- printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret);
- return ret;
+ dev_err(&pdev->dev, "%s failed %d\n", __func__, ret);
+ return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_init);
-static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
+void sdhci_pltfm_free(struct platform_device *pdev)
{
- struct sdhci_pltfm_data *pdata = pdev->dev.platform_data;
struct sdhci_host *host = platform_get_drvdata(pdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- int dead;
- u32 scratch;
-
- dead = 0;
- scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
- if (scratch == (u32)-1)
- dead = 1;
- sdhci_remove_host(host, dead);
- if (pdata && pdata->exit)
- pdata->exit(host);
iounmap(host->ioaddr);
release_mem_region(iomem->start, resource_size(iomem));
sdhci_free_host(host);
platform_set_drvdata(pdev, NULL);
+}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_free);
- return 0;
+int sdhci_pltfm_register(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata)
+{
+ struct sdhci_host *host;
+ int ret = 0;
+
+ host = sdhci_pltfm_init(pdev, pdata);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ sdhci_get_of_property(pdev);
+
+ ret = sdhci_add_host(host);
+ if (ret)
+ sdhci_pltfm_free(pdev);
+
+ return ret;
}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_register);
-static const struct platform_device_id sdhci_pltfm_ids[] = {
- { "sdhci", },
-#ifdef CONFIG_MMC_SDHCI_CNS3XXX
- { "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
- { "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_DOVE
- { "sdhci-dove", (kernel_ulong_t)&sdhci_dove_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_TEGRA
- { "sdhci-tegra", (kernel_ulong_t)&sdhci_tegra_pdata },
-#endif
- { },
-};
-MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids);
+int sdhci_pltfm_unregister(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+ sdhci_remove_host(host, dead);
+ sdhci_pltfm_free(pdev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister);
#ifdef CONFIG_PM
-static int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
+int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
{
struct sdhci_host *host = platform_get_drvdata(dev);
return sdhci_suspend_host(host, state);
}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);
-static int sdhci_pltfm_resume(struct platform_device *dev)
+int sdhci_pltfm_resume(struct platform_device *dev)
{
struct sdhci_host *host = platform_get_drvdata(dev);
return sdhci_resume_host(host);
}
-#else
-#define sdhci_pltfm_suspend NULL
-#define sdhci_pltfm_resume NULL
+EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);
#endif /* CONFIG_PM */
-static struct platform_driver sdhci_pltfm_driver = {
- .driver = {
- .name = "sdhci",
- .owner = THIS_MODULE,
- },
- .probe = sdhci_pltfm_probe,
- .remove = __devexit_p(sdhci_pltfm_remove),
- .id_table = sdhci_pltfm_ids,
- .suspend = sdhci_pltfm_suspend,
- .resume = sdhci_pltfm_resume,
-};
-
-/*****************************************************************************\
- * *
- * Driver init/exit *
- * *
-\*****************************************************************************/
-
-static int __init sdhci_drv_init(void)
+static int __init sdhci_pltfm_drv_init(void)
{
- return platform_driver_register(&sdhci_pltfm_driver);
+ pr_info("sdhci-pltfm: SDHCI platform and OF driver helper\n");
+
+ return 0;
}
+module_init(sdhci_pltfm_drv_init);
-static void __exit sdhci_drv_exit(void)
+static void __exit sdhci_pltfm_drv_exit(void)
{
- platform_driver_unregister(&sdhci_pltfm_driver);
}
+module_exit(sdhci_pltfm_drv_exit);
-module_init(sdhci_drv_init);
-module_exit(sdhci_drv_exit);
-
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_DESCRIPTION("SDHCI platform and OF driver helper");
+MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index 2b37016ad0ac..3a9fc3f40840 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -12,17 +12,95 @@
#define _DRIVERS_MMC_SDHCI_PLTFM_H
#include <linux/clk.h>
-#include <linux/types.h>
-#include <linux/mmc/sdhci-pltfm.h>
+#include <linux/platform_device.h>
+#include "sdhci.h"
+
+struct sdhci_pltfm_data {
+ struct sdhci_ops *ops;
+ unsigned int quirks;
+};
struct sdhci_pltfm_host {
struct clk *clk;
void *priv; /* to handle quirks across io-accessor calls */
+
+ /* migrate from sdhci_of_host */
+ unsigned int clock;
+ u16 xfer_mode_shadow;
};
-extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;
-extern struct sdhci_pltfm_data sdhci_esdhc_imx_pdata;
-extern struct sdhci_pltfm_data sdhci_dove_pdata;
-extern struct sdhci_pltfm_data sdhci_tegra_pdata;
+#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+/*
+ * These accessors are designed for big endian hosts doing I/O to
+ * little endian controllers incorporating a 32-bit hardware byte swapper.
+ */
+static inline u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
+{
+ return in_be32(host->ioaddr + reg);
+}
+
+static inline u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
+{
+ return in_be16(host->ioaddr + (reg ^ 0x2));
+}
+
+static inline u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
+{
+ return in_8(host->ioaddr + (reg ^ 0x3));
+}
+
+static inline void sdhci_be32bs_writel(struct sdhci_host *host,
+ u32 val, int reg)
+{
+ out_be32(host->ioaddr + reg, val);
+}
+
+static inline void sdhci_be32bs_writew(struct sdhci_host *host,
+ u16 val, int reg)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ int base = reg & ~0x3;
+ int shift = (reg & 0x2) * 8;
+
+ switch (reg) {
+ case SDHCI_TRANSFER_MODE:
+ /*
+ * Postpone this write, we must do it together with a
+ * command write that is down below.
+ */
+ pltfm_host->xfer_mode_shadow = val;
+ return;
+ case SDHCI_COMMAND:
+ sdhci_be32bs_writel(host,
+ val << 16 | pltfm_host->xfer_mode_shadow,
+ SDHCI_TRANSFER_MODE);
+ return;
+ }
+ clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
+}
+
+static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+ int base = reg & ~0x3;
+ int shift = (reg & 0x3) * 8;
+
+ clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
+}
+#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
+
+extern void sdhci_get_of_property(struct platform_device *pdev);
+
+extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata);
+extern void sdhci_pltfm_free(struct platform_device *pdev);
+
+extern int sdhci_pltfm_register(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata);
+extern int sdhci_pltfm_unregister(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+extern int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state);
+extern int sdhci_pltfm_resume(struct platform_device *dev);
+#endif
#endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
deleted file mode 100644
index 089c9a68b7b1..000000000000
--- a/drivers/mmc/host/sdhci-pxa.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/* linux/drivers/mmc/host/sdhci-pxa.c
- *
- * Copyright (C) 2010 Marvell International Ltd.
- * Zhangfei Gao <zhangfei.gao@marvell.com>
- * Kevin Wang <dwang4@marvell.com>
- * Mingwei Wang <mwwang@marvell.com>
- * Philip Rakity <prakity@marvell.com>
- * Mark Brown <markb@marvell.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.
- */
-
-/* Supports:
- * SDHCI support for MMP2/PXA910/PXA168
- *
- * Refer to sdhci-s3c.c.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <plat/sdhci.h>
-#include "sdhci.h"
-
-#define DRIVER_NAME "sdhci-pxa"
-
-#define SD_FIFO_PARAM 0x104
-#define DIS_PAD_SD_CLK_GATE 0x400
-
-struct sdhci_pxa {
- struct sdhci_host *host;
- struct sdhci_pxa_platdata *pdata;
- struct clk *clk;
- struct resource *res;
-
- u8 clk_enable;
-};
-
-/*****************************************************************************\
- * *
- * SDHCI core callbacks *
- * *
-\*****************************************************************************/
-static void set_clock(struct sdhci_host *host, unsigned int clock)
-{
- struct sdhci_pxa *pxa = sdhci_priv(host);
- u32 tmp = 0;
-
- if (clock == 0) {
- if (pxa->clk_enable) {
- clk_disable(pxa->clk);
- pxa->clk_enable = 0;
- }
- } else {
- if (0 == pxa->clk_enable) {
- if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
- tmp = readl(host->ioaddr + SD_FIFO_PARAM);
- tmp |= DIS_PAD_SD_CLK_GATE;
- writel(tmp, host->ioaddr + SD_FIFO_PARAM);
- }
- clk_enable(pxa->clk);
- pxa->clk_enable = 1;
- }
- }
-}
-
-static int set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
-{
- u16 ctrl_2;
-
- /*
- * Set V18_EN -- UHS modes do not work without this.
- * does not change signaling voltage
- */
- ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
- /* Select Bus Speed Mode for host */
- ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
- switch (uhs) {
- case MMC_TIMING_UHS_SDR12:
- ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
- break;
- case MMC_TIMING_UHS_SDR25:
- ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
- break;
- case MMC_TIMING_UHS_SDR50:
- ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
- break;
- case MMC_TIMING_UHS_SDR104:
- ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
- break;
- case MMC_TIMING_UHS_DDR50:
- ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
- break;
- }
-
- sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
- pr_debug("%s:%s uhs = %d, ctrl_2 = %04X\n",
- __func__, mmc_hostname(host->mmc), uhs, ctrl_2);
-
- return 0;
-}
-
-static struct sdhci_ops sdhci_pxa_ops = {
- .set_uhs_signaling = set_uhs_signaling,
- .set_clock = set_clock,
-};
-
-/*****************************************************************************\
- * *
- * Device probing/removal *
- * *
-\*****************************************************************************/
-
-static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
-{
- struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
- struct device *dev = &pdev->dev;
- struct sdhci_host *host = NULL;
- struct resource *iomem = NULL;
- struct sdhci_pxa *pxa = NULL;
- int ret, irq;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "no irq specified\n");
- return irq;
- }
-
- iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!iomem) {
- dev_err(dev, "no memory specified\n");
- return -ENOENT;
- }
-
- host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
- if (IS_ERR(host)) {
- dev_err(dev, "failed to alloc host\n");
- return PTR_ERR(host);
- }
-
- pxa = sdhci_priv(host);
- pxa->host = host;
- pxa->pdata = pdata;
- pxa->clk_enable = 0;
-
- pxa->clk = clk_get(dev, "PXA-SDHCLK");
- if (IS_ERR(pxa->clk)) {
- dev_err(dev, "failed to get io clock\n");
- ret = PTR_ERR(pxa->clk);
- goto out;
- }
-
- pxa->res = request_mem_region(iomem->start, resource_size(iomem),
- mmc_hostname(host->mmc));
- if (!pxa->res) {
- dev_err(&pdev->dev, "cannot request region\n");
- ret = -EBUSY;
- goto out;
- }
-
- host->ioaddr = ioremap(iomem->start, resource_size(iomem));
- if (!host->ioaddr) {
- dev_err(&pdev->dev, "failed to remap registers\n");
- ret = -ENOMEM;
- goto out;
- }
-
- host->hw_name = "MMC";
- host->ops = &sdhci_pxa_ops;
- host->irq = irq;
- host->quirks = SDHCI_QUIRK_BROKEN_ADMA
- | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
- | SDHCI_QUIRK_32BIT_DMA_ADDR
- | SDHCI_QUIRK_32BIT_DMA_SIZE
- | SDHCI_QUIRK_32BIT_ADMA_SIZE
- | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
-
- if (pdata->quirks)
- host->quirks |= pdata->quirks;
-
- /* enable 1/8V DDR capable */
- host->mmc->caps |= MMC_CAP_1_8V_DDR;
-
- /* If slot design supports 8 bit data, indicate this to MMC. */
- if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
- host->mmc->caps |= MMC_CAP_8_BIT_DATA;
-
- ret = sdhci_add_host(host);
- if (ret) {
- dev_err(&pdev->dev, "failed to add host\n");
- goto out;
- }
-
- if (pxa->pdata->max_speed)
- host->mmc->f_max = pxa->pdata->max_speed;
-
- platform_set_drvdata(pdev, host);
-
- return 0;
-out:
- if (host) {
- clk_put(pxa->clk);
- if (host->ioaddr)
- iounmap(host->ioaddr);
- if (pxa->res)
- release_mem_region(pxa->res->start,
- resource_size(pxa->res));
- sdhci_free_host(host);
- }
-
- return ret;
-}
-
-static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
-{
- struct sdhci_host *host = platform_get_drvdata(pdev);
- struct sdhci_pxa *pxa = sdhci_priv(host);
- int dead = 0;
- u32 scratch;
-
- if (host) {
- scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
- if (scratch == (u32)-1)
- dead = 1;
-
- sdhci_remove_host(host, dead);
-
- if (host->ioaddr)
- iounmap(host->ioaddr);
- if (pxa->res)
- release_mem_region(pxa->res->start,
- resource_size(pxa->res));
- if (pxa->clk_enable) {
- clk_disable(pxa->clk);
- pxa->clk_enable = 0;
- }
- clk_put(pxa->clk);
-
- sdhci_free_host(host);
- platform_set_drvdata(pdev, NULL);
- }
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int sdhci_pxa_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct sdhci_host *host = platform_get_drvdata(dev);
-
- return sdhci_suspend_host(host, state);
-}
-
-static int sdhci_pxa_resume(struct platform_device *dev)
-{
- struct sdhci_host *host = platform_get_drvdata(dev);
-
- return sdhci_resume_host(host);
-}
-#else
-#define sdhci_pxa_suspend NULL
-#define sdhci_pxa_resume NULL
-#endif
-
-static struct platform_driver sdhci_pxa_driver = {
- .probe = sdhci_pxa_probe,
- .remove = __devexit_p(sdhci_pxa_remove),
- .suspend = sdhci_pxa_suspend,
- .resume = sdhci_pxa_resume,
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-/*****************************************************************************\
- * *
- * Driver init/exit *
- * *
-\*****************************************************************************/
-
-static int __init sdhci_pxa_init(void)
-{
- return platform_driver_register(&sdhci_pxa_driver);
-}
-
-static void __exit sdhci_pxa_exit(void)
-{
- platform_driver_unregister(&sdhci_pxa_driver);
-}
-
-module_init(sdhci_pxa_init);
-module_exit(sdhci_pxa_exit);
-
-MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
-MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
new file mode 100644
index 000000000000..38f58994f79a
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ * Kevin Wang <dwang4@marvell.com>
+ * Jun Nie <njun@marvell.com>
+ * Qiming Wu <wuqm@marvell.com>
+ * Philip Rakity <prakity@marvell.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/err.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_data/pxa_sdhci.h>
+#include <linux/slab.h>
+#include "sdhci.h"
+#include "sdhci-pltfm.h"
+
+#define SD_FIFO_PARAM 0xe0
+#define DIS_PAD_SD_CLK_GATE 0x0400 /* Turn on/off Dynamic SD Clock Gating */
+#define CLK_GATE_ON 0x0200 /* Disable/enable Clock Gate */
+#define CLK_GATE_CTL 0x0100 /* Clock Gate Control */
+#define CLK_GATE_SETTING_BITS (DIS_PAD_SD_CLK_GATE | \
+ CLK_GATE_ON | CLK_GATE_CTL)
+
+#define SD_CLOCK_BURST_SIZE_SETUP 0xe6
+#define SDCLK_SEL_SHIFT 8
+#define SDCLK_SEL_MASK 0x3
+#define SDCLK_DELAY_SHIFT 10
+#define SDCLK_DELAY_MASK 0x3c
+
+#define SD_CE_ATA_2 0xea
+#define MMC_CARD 0x1000
+#define MMC_WIDTH 0x0100
+
+static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
+{
+ struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+
+ if (mask == SDHCI_RESET_ALL) {
+ u16 tmp = 0;
+
+ /*
+ * tune timing of read data/command when crc error happen
+ * no performance impact
+ */
+ if (pdata->clk_delay_sel == 1) {
+ tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+
+ tmp &= ~(SDCLK_DELAY_MASK << SDCLK_DELAY_SHIFT);
+ tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
+ << SDCLK_DELAY_SHIFT;
+ tmp &= ~(SDCLK_SEL_MASK << SDCLK_SEL_SHIFT);
+ tmp |= (1 & SDCLK_SEL_MASK) << SDCLK_SEL_SHIFT;
+
+ writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+ }
+
+ if (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);
+ } else {
+ tmp = readw(host->ioaddr + SD_FIFO_PARAM);
+ tmp &= ~CLK_GATE_SETTING_BITS;
+ tmp |= CLK_GATE_SETTING_BITS;
+ writew(tmp, host->ioaddr + SD_FIFO_PARAM);
+ }
+ }
+}
+
+static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
+{
+ u8 ctrl;
+ u16 tmp;
+
+ ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+ tmp = readw(host->ioaddr + SD_CE_ATA_2);
+ if (width == MMC_BUS_WIDTH_8) {
+ ctrl &= ~SDHCI_CTRL_4BITBUS;
+ tmp |= MMC_CARD | MMC_WIDTH;
+ } else {
+ tmp &= ~(MMC_CARD | MMC_WIDTH);
+ if (width == MMC_BUS_WIDTH_4)
+ ctrl |= SDHCI_CTRL_4BITBUS;
+ else
+ ctrl &= ~SDHCI_CTRL_4BITBUS;
+ }
+ writew(tmp, host->ioaddr + SD_CE_ATA_2);
+ writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+
+ return 0;
+}
+
+static u32 pxav2_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return clk_get_rate(pltfm_host->clk);
+}
+
+static struct sdhci_ops pxav2_sdhci_ops = {
+ .get_max_clock = pxav2_get_max_clock,
+ .platform_reset_exit = pxav2_set_private_registers,
+ .platform_8bit_width = pxav2_mmc_set_width,
+};
+
+static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
+{
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct sdhci_host *host = NULL;
+ struct sdhci_pxa *pxa = NULL;
+ int ret;
+ struct clk *clk;
+
+ pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+ if (!pxa)
+ return -ENOMEM;
+
+ host = sdhci_pltfm_init(pdev, NULL);
+ if (IS_ERR(host)) {
+ kfree(pxa);
+ return PTR_ERR(host);
+ }
+ pltfm_host = sdhci_priv(host);
+ pltfm_host->priv = pxa;
+
+ clk = clk_get(dev, "PXA-SDHCLK");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "failed to get io clock\n");
+ ret = PTR_ERR(clk);
+ goto err_clk_get;
+ }
+ pltfm_host->clk = clk;
+ clk_enable(clk);
+
+ host->quirks = SDHCI_QUIRK_BROKEN_ADMA
+ | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
+ | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
+
+ if (pdata) {
+ if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
+ /* on-chip device */
+ host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+ }
+
+ /* If slot design supports 8 bit data, indicate this to MMC. */
+ if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
+ host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+
+ if (pdata->quirks)
+ host->quirks |= pdata->quirks;
+ if (pdata->host_caps)
+ host->mmc->caps |= pdata->host_caps;
+ if (pdata->pm_caps)
+ host->mmc->pm_caps |= pdata->pm_caps;
+ }
+
+ host->ops = &pxav2_sdhci_ops;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add host\n");
+ goto err_add_host;
+ }
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+
+err_add_host:
+ clk_disable(clk);
+ clk_put(clk);
+err_clk_get:
+ sdhci_pltfm_free(pdev);
+ kfree(pxa);
+ return ret;
+}
+
+static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_pxa *pxa = pltfm_host->priv;
+
+ sdhci_remove_host(host, 1);
+
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+ sdhci_pltfm_free(pdev);
+ kfree(pxa);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver sdhci_pxav2_driver = {
+ .driver = {
+ .name = "sdhci-pxav2",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_pxav2_probe,
+ .remove = __devexit_p(sdhci_pxav2_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+static int __init sdhci_pxav2_init(void)
+{
+ return platform_driver_register(&sdhci_pxav2_driver);
+}
+
+static void __exit sdhci_pxav2_exit(void)
+{
+ platform_driver_unregister(&sdhci_pxav2_driver);
+}
+
+module_init(sdhci_pxav2_init);
+module_exit(sdhci_pxav2_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for pxav2");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
new file mode 100644
index 000000000000..4198dbbc5c20
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ * Kevin Wang <dwang4@marvell.com>
+ * Mingwei Wang <mwwang@marvell.com>
+ * Philip Rakity <prakity@marvell.com>
+ * Mark Brown <markb@marvell.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/err.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_data/pxa_sdhci.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "sdhci.h"
+#include "sdhci-pltfm.h"
+
+#define SD_CLOCK_BURST_SIZE_SETUP 0x10A
+#define SDCLK_SEL 0x100
+#define SDCLK_DELAY_SHIFT 9
+#define SDCLK_DELAY_MASK 0x1f
+
+#define SD_CFG_FIFO_PARAM 0x100
+#define SDCFG_GEN_PAD_CLK_ON (1<<6)
+#define SDCFG_GEN_PAD_CLK_CNT_MASK 0xFF
+#define SDCFG_GEN_PAD_CLK_CNT_SHIFT 24
+
+#define SD_SPI_MODE 0x108
+#define SD_CE_ATA_1 0x10C
+
+#define SD_CE_ATA_2 0x10E
+#define SDCE_MISC_INT (1<<2)
+#define SDCE_MISC_INT_EN (1<<1)
+
+static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
+{
+ struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+
+ if (mask == SDHCI_RESET_ALL) {
+ /*
+ * tune timing of read data/command when crc error happen
+ * no performance impact
+ */
+ if (pdata && 0 != pdata->clk_delay_cycles) {
+ u16 tmp;
+
+ tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+ tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
+ << SDCLK_DELAY_SHIFT;
+ tmp |= SDCLK_SEL;
+ writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+ }
+ }
+}
+
+#define MAX_WAIT_COUNT 5
+static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_pxa *pxa = pltfm_host->priv;
+ u16 tmp;
+ int count;
+
+ if (pxa->power_mode == MMC_POWER_UP
+ && power_mode == MMC_POWER_ON) {
+
+ dev_dbg(mmc_dev(host->mmc),
+ "%s: slot->power_mode = %d,"
+ "ios->power_mode = %d\n",
+ __func__,
+ pxa->power_mode,
+ power_mode);
+
+ /* set we want notice of when 74 clocks are sent */
+ tmp = readw(host->ioaddr + SD_CE_ATA_2);
+ tmp |= SDCE_MISC_INT_EN;
+ writew(tmp, host->ioaddr + SD_CE_ATA_2);
+
+ /* start sending the 74 clocks */
+ tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
+ tmp |= SDCFG_GEN_PAD_CLK_ON;
+ writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
+
+ /* slowest speed is about 100KHz or 10usec per clock */
+ udelay(740);
+ count = 0;
+
+ while (count++ < MAX_WAIT_COUNT) {
+ if ((readw(host->ioaddr + SD_CE_ATA_2)
+ & SDCE_MISC_INT) == 0)
+ break;
+ udelay(10);
+ }
+
+ if (count == MAX_WAIT_COUNT)
+ dev_warn(mmc_dev(host->mmc), "74 clock interrupt not cleared\n");
+
+ /* clear the interrupt bit if posted */
+ tmp = readw(host->ioaddr + SD_CE_ATA_2);
+ tmp |= SDCE_MISC_INT;
+ writew(tmp, host->ioaddr + SD_CE_ATA_2);
+ }
+ pxa->power_mode = power_mode;
+}
+
+static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+{
+ u16 ctrl_2;
+
+ /*
+ * Set V18_EN -- UHS modes do not work without this.
+ * does not change signaling voltage
+ */
+ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+ /* Select Bus Speed Mode for host */
+ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ switch (uhs) {
+ case MMC_TIMING_UHS_SDR12:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+ break;
+ case MMC_TIMING_UHS_SDR25:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+ break;
+ case MMC_TIMING_UHS_SDR50:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
+ break;
+ case MMC_TIMING_UHS_SDR104:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
+ break;
+ case MMC_TIMING_UHS_DDR50:
+ ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
+ break;
+ }
+
+ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+ dev_dbg(mmc_dev(host->mmc),
+ "%s uhs = %d, ctrl_2 = %04X\n",
+ __func__, uhs, ctrl_2);
+
+ return 0;
+}
+
+static struct sdhci_ops pxav3_sdhci_ops = {
+ .platform_reset_exit = pxav3_set_private_registers,
+ .set_uhs_signaling = pxav3_set_uhs_signaling,
+ .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
+};
+
+static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
+{
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct sdhci_host *host = NULL;
+ struct sdhci_pxa *pxa = NULL;
+ int ret;
+ struct clk *clk;
+
+ pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+ if (!pxa)
+ return -ENOMEM;
+
+ host = sdhci_pltfm_init(pdev, NULL);
+ if (IS_ERR(host)) {
+ kfree(pxa);
+ return PTR_ERR(host);
+ }
+ pltfm_host = sdhci_priv(host);
+ pltfm_host->priv = pxa;
+
+ clk = clk_get(dev, "PXA-SDHCLK");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "failed to get io clock\n");
+ ret = PTR_ERR(clk);
+ goto err_clk_get;
+ }
+ pltfm_host->clk = clk;
+ clk_enable(clk);
+
+ host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
+ | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
+
+ /* enable 1/8V DDR capable */
+ host->mmc->caps |= MMC_CAP_1_8V_DDR;
+
+ if (pdata) {
+ if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
+ /* on-chip device */
+ host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+ }
+
+ /* If slot design supports 8 bit data, indicate this to MMC. */
+ if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
+ host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+
+ if (pdata->quirks)
+ host->quirks |= pdata->quirks;
+ if (pdata->host_caps)
+ host->mmc->caps |= pdata->host_caps;
+ if (pdata->pm_caps)
+ host->mmc->pm_caps |= pdata->pm_caps;
+ }
+
+ host->ops = &pxav3_sdhci_ops;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add host\n");
+ goto err_add_host;
+ }
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+
+err_add_host:
+ clk_disable(clk);
+ clk_put(clk);
+err_clk_get:
+ sdhci_pltfm_free(pdev);
+ kfree(pxa);
+ return ret;
+}
+
+static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_pxa *pxa = pltfm_host->priv;
+
+ sdhci_remove_host(host, 1);
+
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+ sdhci_pltfm_free(pdev);
+ kfree(pxa);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver sdhci_pxav3_driver = {
+ .driver = {
+ .name = "sdhci-pxav3",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_pxav3_probe,
+ .remove = __devexit_p(sdhci_pxav3_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+static int __init sdhci_pxav3_init(void)
+{
+ return platform_driver_register(&sdhci_pxav3_driver);
+}
+
+static void __exit sdhci_pxav3_exit(void)
+{
+ platform_driver_unregister(&sdhci_pxav3_driver);
+}
+
+module_init(sdhci_pxav3_init);
+module_exit(sdhci_pxav3_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for pxav3");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 69e3ee321eb5..460ffaf0f6d7 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -612,16 +612,14 @@ static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
{
struct sdhci_host *host = platform_get_drvdata(dev);
- sdhci_suspend_host(host, pm);
- return 0;
+ return sdhci_suspend_host(host, pm);
}
static int sdhci_s3c_resume(struct platform_device *dev)
{
struct sdhci_host *host = platform_get_drvdata(dev);
- sdhci_resume_host(host);
- return 0;
+ return sdhci_resume_host(host);
}
#else
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 343c97edba32..18b0bd31de78 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -24,7 +24,6 @@
#include <mach/gpio.h>
#include <mach/sdhci.h>
-#include "sdhci.h"
#include "sdhci-pltfm.h"
static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
@@ -116,20 +115,42 @@ static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
return 0;
}
+static struct sdhci_ops tegra_sdhci_ops = {
+ .get_ro = tegra_sdhci_get_ro,
+ .read_l = tegra_sdhci_readl,
+ .read_w = tegra_sdhci_readw,
+ .write_l = tegra_sdhci_writel,
+ .platform_8bit_width = tegra_sdhci_8bit,
+};
+
+static struct sdhci_pltfm_data sdhci_tegra_pdata = {
+ .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+ SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_NO_HISPD_BIT |
+ SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
+ .ops = &tegra_sdhci_ops,
+};
-static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
- struct sdhci_pltfm_data *pdata)
+static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+ struct sdhci_pltfm_host *pltfm_host;
struct tegra_sdhci_platform_data *plat;
+ struct sdhci_host *host;
struct clk *clk;
int rc;
+ host = sdhci_pltfm_init(pdev, &sdhci_tegra_pdata);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ pltfm_host = sdhci_priv(host);
+
plat = pdev->dev.platform_data;
+
if (plat == NULL) {
dev_err(mmc_dev(host->mmc), "missing platform data\n");
- return -ENXIO;
+ rc = -ENXIO;
+ goto err_no_plat;
}
if (gpio_is_valid(plat->power_gpio)) {
@@ -137,7 +158,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate power gpio\n");
- goto out;
+ goto err_power_req;
}
tegra_gpio_enable(plat->power_gpio);
gpio_direction_output(plat->power_gpio, 1);
@@ -148,7 +169,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate cd gpio\n");
- goto out_power;
+ goto err_cd_req;
}
tegra_gpio_enable(plat->cd_gpio);
gpio_direction_input(plat->cd_gpio);
@@ -159,7 +180,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc), "request irq error\n");
- goto out_cd;
+ goto err_cd_irq_req;
}
}
@@ -169,7 +190,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate wp gpio\n");
- goto out_irq;
+ goto err_wp_req;
}
tegra_gpio_enable(plat->wp_gpio);
gpio_direction_input(plat->wp_gpio);
@@ -179,7 +200,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (IS_ERR(clk)) {
dev_err(mmc_dev(host->mmc), "clk err\n");
rc = PTR_ERR(clk);
- goto out_wp;
+ goto err_clk_get;
}
clk_enable(clk);
pltfm_host->clk = clk;
@@ -189,38 +210,47 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (plat->is_8bit)
host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+ rc = sdhci_add_host(host);
+ if (rc)
+ goto err_add_host;
+
return 0;
-out_wp:
+err_add_host:
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+err_clk_get:
if (gpio_is_valid(plat->wp_gpio)) {
tegra_gpio_disable(plat->wp_gpio);
gpio_free(plat->wp_gpio);
}
-
-out_irq:
+err_wp_req:
if (gpio_is_valid(plat->cd_gpio))
free_irq(gpio_to_irq(plat->cd_gpio), host);
-out_cd:
+err_cd_irq_req:
if (gpio_is_valid(plat->cd_gpio)) {
tegra_gpio_disable(plat->cd_gpio);
gpio_free(plat->cd_gpio);
}
-
-out_power:
+err_cd_req:
if (gpio_is_valid(plat->power_gpio)) {
tegra_gpio_disable(plat->power_gpio);
gpio_free(plat->power_gpio);
}
-
-out:
+err_power_req:
+err_no_plat:
+ sdhci_pltfm_free(pdev);
return rc;
}
-static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
+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 platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
struct tegra_sdhci_platform_data *plat;
+ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+ sdhci_remove_host(host, dead);
plat = pdev->dev.platform_data;
@@ -242,22 +272,37 @@ static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
+
+ sdhci_pltfm_free(pdev);
+
+ return 0;
}
-static struct sdhci_ops tegra_sdhci_ops = {
- .get_ro = tegra_sdhci_get_ro,
- .read_l = tegra_sdhci_readl,
- .read_w = tegra_sdhci_readw,
- .write_l = tegra_sdhci_writel,
- .platform_8bit_width = tegra_sdhci_8bit,
+static struct platform_driver sdhci_tegra_driver = {
+ .driver = {
+ .name = "sdhci-tegra",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_tegra_probe,
+ .remove = __devexit_p(sdhci_tegra_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
};
-struct sdhci_pltfm_data sdhci_tegra_pdata = {
- .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
- SDHCI_QUIRK_SINGLE_POWER_WRITE |
- SDHCI_QUIRK_NO_HISPD_BIT |
- SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
- .ops = &tegra_sdhci_ops,
- .init = tegra_sdhci_pltfm_init,
- .exit = tegra_sdhci_pltfm_exit,
-};
+static int __init sdhci_tegra_init(void)
+{
+ return platform_driver_register(&sdhci_tegra_driver);
+}
+module_init(sdhci_tegra_init);
+
+static void __exit sdhci_tegra_exit(void)
+{
+ platform_driver_unregister(&sdhci_tegra_driver);
+}
+module_exit(sdhci_tegra_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Tegra");
+MODULE_AUTHOR(" Google, Inc.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 58d5436ff649..c31a3343340d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
{
- u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
+ u32 present, irqs;
if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
return;
+ present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+ SDHCI_CARD_PRESENT;
+ irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
+
if (enable)
sdhci_unmask_irqs(host, irqs);
else
@@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
mmc_hostname(host->mmc), intmask);
if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+ u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+ SDHCI_CARD_PRESENT;
+
+ /*
+ * There is a observation on i.mx esdhc. INSERT bit will be
+ * immediately set again when it gets cleared, if a card is
+ * inserted. We have to mask the irq to prevent interrupt
+ * storm which will freeze the system. And the REMOVE gets
+ * the same situation.
+ *
+ * More testing are needed here to ensure it works for other
+ * platforms though.
+ */
+ sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
+ SDHCI_INT_CARD_REMOVE);
+ sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
+ SDHCI_INT_CARD_INSERT);
+
sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
- SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+ SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+ intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
tasklet_schedule(&host->card_tasklet);
}
- intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-
if (intmask & SDHCI_INT_CMD_MASK) {
sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
SDHCI_INT_STATUS);
@@ -2488,6 +2509,11 @@ int sdhci_add_host(struct sdhci_host *host)
} else
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
+ if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
+ mmc->max_discard_to = (1 << 27) / (mmc->f_max / 1000);
+ else
+ mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+
mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 14f8edbaa195..557886bee9ce 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -175,6 +175,7 @@ struct sh_mmcif_host {
enum mmcif_state state;
spinlock_t lock;
bool power;
+ bool card_present;
/* DMA support */
struct dma_chan *chan_rx;
@@ -877,23 +878,23 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_unlock_irqrestore(&host->lock, flags);
if (ios->power_mode == MMC_POWER_UP) {
- if (p->set_pwr)
- p->set_pwr(host->pd, ios->power_mode);
- if (!host->power) {
+ if (!host->card_present) {
/* See if we also get DMA */
sh_mmcif_request_dma(host, host->pd->dev.platform_data);
- pm_runtime_get_sync(&host->pd->dev);
- host->power = true;
+ host->card_present = true;
}
} else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
/* clock stop */
sh_mmcif_clock_control(host, 0);
if (ios->power_mode == MMC_POWER_OFF) {
- if (host->power) {
- pm_runtime_put(&host->pd->dev);
+ if (host->card_present) {
sh_mmcif_release_dma(host);
- host->power = false;
+ host->card_present = false;
}
+ }
+ if (host->power) {
+ pm_runtime_put(&host->pd->dev);
+ host->power = false;
if (p->down_pwr)
p->down_pwr(host->pd);
}
@@ -901,8 +902,16 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
return;
}
- if (ios->clock)
+ if (ios->clock) {
+ if (!host->power) {
+ if (p->set_pwr)
+ p->set_pwr(host->pd, ios->power_mode);
+ pm_runtime_get_sync(&host->pd->dev);
+ host->power = true;
+ sh_mmcif_sync_reset(host);
+ }
sh_mmcif_clock_control(host, ios->clock);
+ }
host->bus_width = ios->bus_width;
host->state = STATE_IDLE;
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index ce500f03df85..774f6439d7ce 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -26,6 +26,7 @@
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h>
#include <linux/sh_dma.h>
+#include <linux/delay.h>
#include "tmio_mmc.h"
@@ -55,6 +56,39 @@ static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
return -ENOSYS;
}
+static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
+{
+ int timeout = 1000;
+
+ while (--timeout && !(sd_ctrl_read16(host, CTL_STATUS2) & (1 << 13)))
+ udelay(1);
+
+ if (!timeout) {
+ dev_warn(host->pdata->dev, "timeout waiting for SD bus idle\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr)
+{
+ switch (addr)
+ {
+ case CTL_SD_CMD:
+ case CTL_STOP_INTERNAL_ACTION:
+ case CTL_XFER_BLK_COUNT:
+ case CTL_SD_CARD_CLK_CTL:
+ case CTL_SD_XFER_LEN:
+ case CTL_SD_MEM_CARD_OPT:
+ case CTL_TRANSACTION_CTL:
+ case CTL_DMA_ENABLE:
+ return sh_mobile_sdhi_wait_idle(host);
+ }
+
+ return 0;
+}
+
static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
{
struct sh_mobile_sdhi *priv;
@@ -86,6 +120,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
mmc_data->hclk = clk_get_rate(priv->clk);
mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+ if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT)
+ mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
if (p) {
mmc_data->flags = p->tmio_flags;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 8260bc2c34e3..eeaf64391fbe 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -18,8 +18,10 @@
#include <linux/highmem.h>
#include <linux/mmc/tmio.h>
+#include <linux/mutex.h>
#include <linux/pagemap.h>
#include <linux/spinlock.h>
+#include <linux/scatterlist.h>
/* Definitions for values the CTRL_SDIO_STATUS register can take. */
#define TMIO_SDIO_STAT_IOIRQ 0x0001
@@ -52,6 +54,8 @@ struct tmio_mmc_host {
void (*set_clk_div)(struct platform_device *host, int state);
int pm_error;
+ /* recognise system-wide suspend in runtime PM methods */
+ bool pm_global;
/* pio related stuff */
struct scatterlist *sg_ptr;
@@ -73,8 +77,11 @@ struct tmio_mmc_host {
/* Track lost interrupts */
struct delayed_work delayed_reset_work;
- spinlock_t lock;
+ struct work_struct done;
+
+ spinlock_t lock; /* protect host private data */
unsigned long last_req_ts;
+ struct mutex ios_lock; /* protect set_ios() context */
};
int tmio_mmc_host_probe(struct tmio_mmc_host **host,
@@ -103,6 +110,7 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
+void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable);
void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
void tmio_mmc_release_dma(struct tmio_mmc_host *host);
#else
@@ -111,6 +119,10 @@ static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
{
}
+static inline void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+{
+}
+
static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
struct tmio_mmc_data *pdata)
{
@@ -134,4 +146,44 @@ int tmio_mmc_host_resume(struct device *dev);
int tmio_mmc_host_runtime_suspend(struct device *dev);
int tmio_mmc_host_runtime_resume(struct device *dev);
+static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
+{
+ return readw(host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
+ u16 *buf, int count)
+{
+ readsw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
+{
+ return readw(host->ctl + (addr << host->bus_shift)) |
+ readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
+}
+
+static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
+{
+ /* If there is a hook and it returns non-zero then there
+ * is an error and the write should be skipped
+ */
+ if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr))
+ return;
+ writew(val, host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
+ u16 *buf, int count)
+{
+ writesw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
+{
+ writew(val, host->ctl + (addr << host->bus_shift));
+ writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
+}
+
+
#endif
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
index 25f1ad6cbe09..86f259cdfcbc 100644
--- a/drivers/mmc/host/tmio_mmc_dma.c
+++ b/drivers/mmc/host/tmio_mmc_dma.c
@@ -11,6 +11,7 @@
*/
#include <linux/device.h>
+#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
@@ -22,11 +23,14 @@
#define TMIO_MMC_MIN_DMA_LEN 8
-static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
{
+ if (!host->chan_tx || !host->chan_rx)
+ return;
+
#if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE)
/* Switch DMA mode on or off - SuperH specific? */
- writew(enable ? 2 : 0, host->ctl + (0xd8 << host->bus_shift));
+ sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? 2 : 0);
#endif
}
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 0b09e8239aa0..1f16357e7301 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -46,40 +46,6 @@
#include "tmio_mmc.h"
-static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
-{
- return readw(host->ctl + (addr << host->bus_shift));
-}
-
-static void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
- u16 *buf, int count)
-{
- readsw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
-{
- return readw(host->ctl + (addr << host->bus_shift)) |
- readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
-}
-
-static void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
-{
- writew(val, host->ctl + (addr << host->bus_shift));
-}
-
-static void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
- u16 *buf, int count)
-{
- writesw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
-{
- writew(val, host->ctl + (addr << host->bus_shift));
- writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
-}
-
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);
@@ -284,10 +250,16 @@ static void tmio_mmc_reset_work(struct work_struct *work)
/* called with host->lock held, interrupts disabled */
static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
{
- struct mmc_request *mrq = host->mrq;
+ struct mmc_request *mrq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
- if (!mrq)
+ mrq = host->mrq;
+ if (IS_ERR_OR_NULL(mrq)) {
+ spin_unlock_irqrestore(&host->lock, flags);
return;
+ }
host->cmd = NULL;
host->data = NULL;
@@ -296,11 +268,18 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
cancel_delayed_work(&host->delayed_reset_work);
host->mrq = NULL;
+ spin_unlock_irqrestore(&host->lock, flags);
- /* FIXME: mmc_request_done() can schedule! */
mmc_request_done(host->mmc, mrq);
}
+static void tmio_mmc_done_work(struct work_struct *work)
+{
+ struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
+ done);
+ tmio_mmc_finish_request(host);
+}
+
/* These are the bitmasks the tmio chip requires to implement the MMC response
* types. Note that R1 and R6 are the same in this scheme. */
#define APP_CMD 0x0040
@@ -467,7 +446,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
BUG();
}
- tmio_mmc_finish_request(host);
+ schedule_work(&host->done);
}
static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
@@ -557,7 +536,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
tasklet_schedule(&host->dma_issue);
}
} else {
- tmio_mmc_finish_request(host);
+ schedule_work(&host->done);
}
out:
@@ -567,6 +546,7 @@ out:
irqreturn_t tmio_mmc_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, irq_mask, status;
unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
@@ -588,13 +568,13 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
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(host->mmc, 0);
+ tmio_mmc_enable_sdio_irq(mmc, 0);
goto out;
}
- if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
+ if (mmc->caps & MMC_CAP_SDIO_IRQ &&
sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
- mmc_signal_sdio_irq(host->mmc);
+ mmc_signal_sdio_irq(mmc);
if (sdio_ireg)
goto out;
@@ -603,58 +583,49 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
pr_debug_status(status);
pr_debug_status(ireg);
- if (!ireg) {
- tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask);
-
- pr_warning("tmio_mmc: Spurious irq, disabling! "
- "0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
- pr_debug_status(status);
-
+ /* Card insert / remove attempts */
+ if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
+ tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
+ TMIO_STAT_CARD_REMOVE);
+ if ((((ireg & TMIO_STAT_CARD_REMOVE) && mmc->card) ||
+ ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) &&
+ !work_pending(&mmc->detect.work))
+ mmc_detect_change(host->mmc, msecs_to_jiffies(100));
goto out;
}
- while (ireg) {
- /* Card insert / remove attempts */
- if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
- tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
- TMIO_STAT_CARD_REMOVE);
- mmc_detect_change(host->mmc, msecs_to_jiffies(100));
- }
-
- /* CRC and other errors */
-/* if (ireg & TMIO_STAT_ERR_IRQ)
- * handled |= tmio_error_irq(host, irq, stat);
+ /* CRC and other errors */
+/* if (ireg & TMIO_STAT_ERR_IRQ)
+ * handled |= tmio_error_irq(host, irq, stat);
*/
- /* 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);
- }
-
- /* 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);
- }
-
- /* Data transfer completion */
- if (ireg & TMIO_STAT_DATAEND) {
- tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
- tmio_mmc_data_irq(host);
- }
+ /* 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;
+ }
- /* Check status - keep going until we've handled it all */
- status = sd_ctrl_read32(host, CTL_STATUS);
- irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
- ireg = status & TMIO_MASK_IRQ & ~irq_mask;
+ /* 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;
+ }
- pr_debug("Status at end of loop: %08x\n", status);
- pr_debug_status(status);
+ /* Data transfer completion */
+ if (ireg & TMIO_STAT_DATAEND) {
+ tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
+ tmio_mmc_data_irq(host);
+ goto out;
}
- pr_debug("MMC IRQ end\n");
+
+ 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);
out:
return IRQ_HANDLED;
@@ -749,6 +720,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct tmio_mmc_data *pdata = host->pdata;
unsigned long flags;
+ mutex_lock(&host->ios_lock);
+
spin_lock_irqsave(&host->lock, flags);
if (host->mrq) {
if (IS_ERR(host->mrq)) {
@@ -764,6 +737,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->mrq->cmd->opcode, host->last_req_ts, jiffies);
}
spin_unlock_irqrestore(&host->lock, flags);
+
+ mutex_unlock(&host->ios_lock);
return;
}
@@ -771,33 +746,30 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_unlock_irqrestore(&host->lock, flags);
- if (ios->clock)
- tmio_mmc_set_clock(host, ios->clock);
-
- /* Power sequence - OFF -> UP -> ON */
- if (ios->power_mode == MMC_POWER_UP) {
- if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && !pdata->power) {
+ /*
+ * pdata->power == false only if COLD_CD is available, otherwise only
+ * in short time intervals during probing or resuming
+ */
+ if (ios->power_mode == MMC_POWER_ON && ios->clock) {
+ if (!pdata->power) {
pm_runtime_get_sync(&host->pdev->dev);
pdata->power = true;
}
+ tmio_mmc_set_clock(host, ios->clock);
/* power up SD bus */
if (host->set_pwr)
host->set_pwr(host->pdev, 1);
- } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
- /* power down SD bus */
- if (ios->power_mode == MMC_POWER_OFF) {
- if (host->set_pwr)
- host->set_pwr(host->pdev, 0);
- if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) &&
- pdata->power) {
- pdata->power = false;
- pm_runtime_put(&host->pdev->dev);
- }
- }
- tmio_mmc_clk_stop(host);
- } else {
/* start bus clock */
tmio_mmc_clk_start(host);
+ } else if (ios->power_mode != MMC_POWER_UP) {
+ if (host->set_pwr)
+ host->set_pwr(host->pdev, 0);
+ if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) &&
+ pdata->power) {
+ pdata->power = false;
+ pm_runtime_put(&host->pdev->dev);
+ }
+ tmio_mmc_clk_stop(host);
}
switch (ios->bus_width) {
@@ -817,6 +789,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
current->comm, task_pid_nr(current),
ios->clock, ios->power_mode);
host->mrq = NULL;
+
+ mutex_unlock(&host->ios_lock);
}
static int tmio_mmc_get_ro(struct mmc_host *mmc)
@@ -913,16 +887,20 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
tmio_mmc_enable_sdio_irq(mmc, 0);
spin_lock_init(&_host->lock);
+ mutex_init(&_host->ios_lock);
/* Init delayed work for request timeouts */
INIT_DELAYED_WORK(&_host->delayed_reset_work, tmio_mmc_reset_work);
+ INIT_WORK(&_host->done, tmio_mmc_done_work);
/* See if we also get DMA */
tmio_mmc_request_dma(_host, pdata);
/* We have to keep the device powered for its card detection to work */
- if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD))
+ if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) {
+ pdata->power = true;
pm_runtime_get_noresume(&pdev->dev);
+ }
mmc_add_host(mmc);
@@ -963,6 +941,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
pm_runtime_get_sync(&pdev->dev);
mmc_remove_host(host->mmc);
+ cancel_work_sync(&host->done);
cancel_delayed_work_sync(&host->delayed_reset_work);
tmio_mmc_release_dma(host);
@@ -998,11 +977,16 @@ int tmio_mmc_host_resume(struct device *dev)
/* The MMC core will perform the complete set up */
host->pdata->power = false;
+ host->pm_global = true;
if (!host->pm_error)
pm_runtime_get_sync(dev);
- tmio_mmc_reset(mmc_priv(mmc));
- tmio_mmc_request_dma(host, host->pdata);
+ if (host->pm_global) {
+ /* Runtime PM resume callback didn't run */
+ tmio_mmc_reset(host);
+ tmio_mmc_enable_dma(host, true);
+ host->pm_global = false;
+ }
return mmc_resume_host(mmc);
}
@@ -1023,12 +1007,15 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
struct tmio_mmc_data *pdata = host->pdata;
tmio_mmc_reset(host);
+ tmio_mmc_enable_dma(host, true);
if (pdata->power) {
/* Only entered after a card-insert interrupt */
- tmio_mmc_set_ios(mmc, &mmc->ios);
+ if (!mmc->card)
+ tmio_mmc_set_ios(mmc, &mmc->ios);
mmc_detect_change(mmc, msecs_to_jiffies(100));
}
+ host->pm_global = false;
return 0;
}
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index d4455ffbefd8..e8f6e65183d7 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -1625,8 +1625,8 @@ static void __vub300_command_response(struct vub300_mmc_host *vub300,
cmd->error = respretval;
} else if (cmd->error) {
/*
- * the error occured sending the command
- * or recieving the response
+ * the error occurred sending the command
+ * or receiving the response
*/
} else if (vub300->command_out_urb->status) {
vub300->usb_transport_fail = vub300->command_out_urb->status;
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 1e2c430aaad2..83e80c65d6e7 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -5,7 +5,7 @@
*
* Copyright © 2009 Bluewater Systems Ltd
* Author: Andre Renaud <andre@bluewatersys.com>
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
*
* Based on m25p80.c
*
@@ -498,5 +498,5 @@ module_exit(sst25l_exit);
MODULE_DESCRIPTION("MTD SPI driver for SST25L Flash chips");
MODULE_AUTHOR("Andre Renaud <andre@bluewatersys.com>, "
- "Ryan Mallon <ryan@bluewatersys.com>");
+ "Ryan Mallon");
MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index d4297a97e100..67815eed2f00 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -142,7 +142,7 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
state->map.write = bfin_flash_write;
state->map.copy_to = bfin_flash_copy_to;
state->map.bankwidth = pdata->width;
- state->map.size = memory->end - memory->start + 1;
+ state->map.size = resource_size(memory);
state->map.virt = (void __iomem *)memory->start;
state->map.phys = memory->start;
state->map.map_priv_1 = (unsigned long)state;
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index c00b9175ba9e..1594a802631d 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -155,7 +155,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
if (!plat)
return -ENODEV;
- window_size = dev->resource->end - dev->resource->start + 1;
+ window_size = resource_size(dev->resource);
dev_info(&dev->dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n",
ixp_data->nr_banks, ((u32)window_size >> 20));
@@ -194,16 +194,17 @@ static int ixp2000_flash_probe(struct platform_device *dev)
info->map.copy_to = ixp2000_flash_copy_to;
info->res = request_mem_region(dev->resource->start,
- dev->resource->end - dev->resource->start + 1,
- dev_name(&dev->dev));
+ resource_size(dev->resource),
+ dev_name(&dev->dev));
if (!info->res) {
dev_err(&dev->dev, "Could not reserve memory region\n");
err = -ENOMEM;
goto Error;
}
- info->map.map_priv_1 = (unsigned long) ioremap(dev->resource->start,
- dev->resource->end - dev->resource->start + 1);
+ info->map.map_priv_1 =
+ (unsigned long)ioremap(dev->resource->start,
+ resource_size(dev->resource));
if (!info->map.map_priv_1) {
dev_err(&dev->dev, "Failed to ioremap flash region\n");
err = -EIO;
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index f59d62f74d44..7ae137d4b998 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -70,7 +70,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
info->map.name = (char *) flash->name;
info->map.bankwidth = flash->width;
info->map.phys = res->start;
- info->map.size = res->end - res->start + 1;
+ info->map.size = resource_size(res);
info->parts = flash->parts;
info->nr_parts = flash->nr_parts;
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3f92731a5b9e..f1af2228a1b1 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1192,7 +1192,7 @@ err_unregister_chdev:
static void __exit cleanup_mtdchar(void)
{
unregister_mtd_user(&mtdchar_notifier);
- mntput(mtd_inode_mnt);
+ kern_unmount(mtd_inode_mnt);
unregister_filesystem(&mtd_inodefs_type);
__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
}
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index b300705d41cb..55da20ccc7a8 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -22,6 +22,7 @@
*
*/
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -513,7 +514,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
host->io_phys = (dma_addr_t)mem->start;
- host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
+ host->io_base = ioremap(mem->start, resource_size(mem));
if (host->io_base == NULL) {
printk(KERN_ERR "atmel_nand: ioremap failed\n");
res = -EIO;
@@ -547,7 +548,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if (no_ecc)
nand_chip->ecc.mode = NAND_ECC_NONE;
if (hard_ecc && regs) {
- host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
+ host->ecc = ioremap(regs->start, resource_size(regs));
if (host->ecc == NULL) {
printk(KERN_ERR "atmel_nand: ioremap failed\n");
res = -EIO;
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index 9ec280738a9a..8c569e454dc5 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -380,7 +380,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
return -ENXIO;
/* map physical address */
- bcm_umi_io_base = ioremap(r->start, r->end - r->start + 1);
+ bcm_umi_io_base = ioremap(r->start, resource_size(r));
if (!bcm_umi_io_base) {
printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 2f7c930872f9..eb1fbac63eb6 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -713,7 +713,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
}
regs_paddr = res.start;
- regs_size = res.end - res.start + 1;
+ regs_size = resource_size(&res);
if (!devm_request_mem_region(dev, regs_paddr, regs_size, DRV_NAME)) {
dev_err(dev, "Error requesting memory region!\n");
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 65626c1c446d..6c3fb5ab20f5 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -953,10 +953,14 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (!ubi->peb_buf2)
goto out_free;
+ err = ubi_debugging_init_dev(ubi);
+ if (err)
+ goto out_free;
+
err = attach_by_scanning(ubi);
if (err) {
dbg_err("failed to attach by scanning, error %d", err);
- goto out_free;
+ goto out_debugging;
}
if (ubi->autoresize_vol_id != -1) {
@@ -969,12 +973,16 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (err)
goto out_detach;
+ err = ubi_debugfs_init_dev(ubi);
+ if (err)
+ goto out_uif;
+
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
if (IS_ERR(ubi->bgt_thread)) {
err = PTR_ERR(ubi->bgt_thread);
ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
err);
- goto out_uif;
+ goto out_debugfs;
}
ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
@@ -1008,12 +1016,18 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
return ubi_num;
+out_debugfs:
+ ubi_debugfs_exit_dev(ubi);
out_uif:
+ get_device(&ubi->dev);
+ ubi_assert(ref);
uif_close(ubi);
out_detach:
ubi_wl_close(ubi);
free_internal_volumes(ubi);
vfree(ubi->vtbl);
+out_debugging:
+ ubi_debugging_exit_dev(ubi);
out_free:
vfree(ubi->peb_buf1);
vfree(ubi->peb_buf2);
@@ -1080,11 +1094,13 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
*/
get_device(&ubi->dev);
+ ubi_debugfs_exit_dev(ubi);
uif_close(ubi);
ubi_wl_close(ubi);
free_internal_volumes(ubi);
vfree(ubi->vtbl);
put_mtd_device(ubi->mtd);
+ ubi_debugging_exit_dev(ubi);
vfree(ubi->peb_buf1);
vfree(ubi->peb_buf2);
ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
@@ -1199,6 +1215,11 @@ static int __init ubi_init(void)
if (!ubi_wl_entry_slab)
goto out_dev_unreg;
+ err = ubi_debugfs_init();
+ if (err)
+ goto out_slab;
+
+
/* Attach MTD devices */
for (i = 0; i < mtd_devs; i++) {
struct mtd_dev_param *p = &mtd_dev_param[i];
@@ -1247,6 +1268,8 @@ out_detach:
ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
mutex_unlock(&ubi_devices_mutex);
}
+ ubi_debugfs_exit();
+out_slab:
kmem_cache_destroy(ubi_wl_entry_slab);
out_dev_unreg:
misc_deregister(&ubi_ctrl_cdev);
@@ -1270,6 +1293,7 @@ static void __exit ubi_exit(void)
ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
mutex_unlock(&ubi_devices_mutex);
}
+ ubi_debugfs_exit();
kmem_cache_destroy(ubi_wl_entry_slab);
misc_deregister(&ubi_ctrl_cdev);
class_remove_file(ubi_class, &ubi_version);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 191f3bb3c41a..3320a50ba4f0 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -189,12 +189,16 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
return new_offset;
}
-static int vol_cdev_fsync(struct file *file, int datasync)
+static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
struct ubi_volume_desc *desc = file->private_data;
struct ubi_device *ubi = desc->vol->ubi;
-
- return ubi_sync(ubi->ubi_num);
+ struct inode *inode = file->f_path.dentry->d_inode;
+ int err;
+ mutex_lock(&inode->i_mutex);
+ err = ubi_sync(ubi->ubi_num);
+ mutex_unlock(&inode->i_mutex);
+ return err;
}
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 2224cbe41ddf..ab80c0debac8 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -27,17 +27,9 @@
#ifdef CONFIG_MTD_UBI_DEBUG
#include "ubi.h"
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-unsigned int ubi_chk_flags;
-unsigned int ubi_tst_flags;
-
-module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
-module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(debug_chks, "Debug check flags");
-MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
/**
* ubi_dbg_dump_ec_hdr - dump an erase counter header.
@@ -239,4 +231,261 @@ out:
return;
}
+/**
+ * ubi_debugging_init_dev - initialize debugging for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function initializes debugging-related data for UBI device @ubi.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubi_debugging_init_dev(struct ubi_device *ubi)
+{
+ ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL);
+ if (!ubi->dbg)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * ubi_debugging_exit_dev - free debugging data for an UBI device.
+ * @ubi: UBI device description object
+ */
+void ubi_debugging_exit_dev(struct ubi_device *ubi)
+{
+ kfree(ubi->dbg);
+}
+
+/*
+ * Root directory for UBI stuff in debugfs. Contains sub-directories which
+ * contain the stuff specific to particular UBI devices.
+ */
+static struct dentry *dfs_rootdir;
+
+/**
+ * ubi_debugfs_init - create UBI debugfs directory.
+ *
+ * Create UBI debugfs directory. Returns zero in case of success and a negative
+ * error code in case of failure.
+ */
+int ubi_debugfs_init(void)
+{
+ dfs_rootdir = debugfs_create_dir("ubi", NULL);
+ if (IS_ERR_OR_NULL(dfs_rootdir)) {
+ int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
+
+ ubi_err("cannot create \"ubi\" debugfs directory, error %d\n",
+ err);
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * ubi_debugfs_exit - remove UBI debugfs directory.
+ */
+void ubi_debugfs_exit(void)
+{
+ debugfs_remove(dfs_rootdir);
+}
+
+/* Read an UBI debugfs file */
+static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long ubi_num = (unsigned long)file->private_data;
+ struct dentry *dent = file->f_path.dentry;
+ struct ubi_device *ubi;
+ struct ubi_debug_info *d;
+ char buf[3];
+ int val;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+ d = ubi->dbg;
+
+ if (dent == d->dfs_chk_gen)
+ val = d->chk_gen;
+ else if (dent == d->dfs_chk_io)
+ val = d->chk_io;
+ else if (dent == d->dfs_disable_bgt)
+ val = d->disable_bgt;
+ else if (dent == d->dfs_emulate_bitflips)
+ val = d->emulate_bitflips;
+ else if (dent == d->dfs_emulate_io_failures)
+ val = d->emulate_io_failures;
+ else {
+ count = -EINVAL;
+ goto out;
+ }
+
+ if (val)
+ buf[0] = '1';
+ else
+ buf[0] = '0';
+ buf[1] = '\n';
+ buf[2] = 0x00;
+
+ count = simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+
+out:
+ ubi_put_device(ubi);
+ return count;
+}
+
+/* Write an UBI debugfs file */
+static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long ubi_num = (unsigned long)file->private_data;
+ struct dentry *dent = file->f_path.dentry;
+ struct ubi_device *ubi;
+ struct ubi_debug_info *d;
+ size_t buf_size;
+ char buf[8];
+ int val;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+ d = ubi->dbg;
+
+ buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size)) {
+ count = -EFAULT;
+ goto out;
+ }
+
+ if (buf[0] == '1')
+ val = 1;
+ else if (buf[0] == '0')
+ val = 0;
+ else {
+ count = -EINVAL;
+ goto out;
+ }
+
+ if (dent == d->dfs_chk_gen)
+ d->chk_gen = val;
+ else if (dent == d->dfs_chk_io)
+ d->chk_io = val;
+ else if (dent == d->dfs_disable_bgt)
+ d->disable_bgt = val;
+ else if (dent == d->dfs_emulate_bitflips)
+ d->emulate_bitflips = val;
+ else if (dent == d->dfs_emulate_io_failures)
+ d->emulate_io_failures = val;
+ else
+ count = -EINVAL;
+
+out:
+ ubi_put_device(ubi);
+ return count;
+}
+
+static int default_open(struct inode *inode, struct file *file)
+{
+ if (inode->i_private)
+ file->private_data = inode->i_private;
+
+ return 0;
+}
+
+/* File operations for all UBI debugfs files */
+static const struct file_operations dfs_fops = {
+ .read = dfs_file_read,
+ .write = dfs_file_write,
+ .open = default_open,
+ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function creates all debugfs files for UBI device @ubi. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+int ubi_debugfs_init_dev(struct ubi_device *ubi)
+{
+ int err, n;
+ unsigned long ubi_num = ubi->ubi_num;
+ const char *fname;
+ struct dentry *dent;
+ struct ubi_debug_info *d = ubi->dbg;
+
+ n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
+ ubi->ubi_num);
+ if (n == UBI_DFS_DIR_LEN) {
+ /* The array size is too small */
+ fname = UBI_DFS_DIR_NAME;
+ dent = ERR_PTR(-EINVAL);
+ goto out;
+ }
+
+ fname = d->dfs_dir_name;
+ dent = debugfs_create_dir(fname, dfs_rootdir);
+ if (IS_ERR_OR_NULL(dent))
+ goto out;
+ d->dfs_dir = dent;
+
+ fname = "chk_gen";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_gen = dent;
+
+ fname = "chk_io";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_io = dent;
+
+ fname = "tst_disable_bgt";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_disable_bgt = dent;
+
+ fname = "tst_emulate_bitflips";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_emulate_bitflips = dent;
+
+ fname = "tst_emulate_io_failures";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_emulate_io_failures = dent;
+
+ return 0;
+
+out_remove:
+ debugfs_remove_recursive(d->dfs_dir);
+out:
+ err = dent ? PTR_ERR(dent) : -ENODEV;
+ ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+ fname, err);
+ return err;
+}
+
+/**
+ * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
+ * @ubi: UBI device description object
+ */
+void ubi_debugfs_exit_dev(struct ubi_device *ubi)
+{
+ debugfs_remove_recursive(ubi->dbg->dfs_dir);
+}
+
#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 3f1a09c5c438..65b5b76cc379 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -21,14 +21,6 @@
#ifndef __UBI_DEBUG_H__
#define __UBI_DEBUG_H__
-struct ubi_ec_hdr;
-struct ubi_vid_hdr;
-struct ubi_volume;
-struct ubi_vtbl_record;
-struct ubi_scan_volume;
-struct ubi_scan_leb;
-struct ubi_mkvol_req;
-
#ifdef CONFIG_MTD_UBI_DEBUG
#include <linux/random.h>
@@ -71,86 +63,103 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
-
-extern unsigned int ubi_chk_flags;
-
-/*
- * Debugging check flags.
- *
- * UBI_CHK_GEN: general checks
- * UBI_CHK_IO: check writes and erases
- */
-enum {
- UBI_CHK_GEN = 0x1,
- UBI_CHK_IO = 0x2,
-};
-
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
int offset, int len);
-
-extern unsigned int ubi_tst_flags;
+int ubi_debugging_init_dev(struct ubi_device *ubi);
+void ubi_debugging_exit_dev(struct ubi_device *ubi);
+int ubi_debugfs_init(void);
+void ubi_debugfs_exit(void);
+int ubi_debugfs_init_dev(struct ubi_device *ubi);
+void ubi_debugfs_exit_dev(struct ubi_device *ubi);
/*
- * Special testing flags.
+ * The UBI debugfs directory name pattern and maximum name length (3 for "ubi"
+ * + 2 for the number plus 1 for the trailing zero byte.
+ */
+#define UBI_DFS_DIR_NAME "ubi%d"
+#define UBI_DFS_DIR_LEN (3 + 2 + 1)
+
+/**
+ * struct ubi_debug_info - debugging information for an UBI device.
*
- * UBIFS_TST_DISABLE_BGT: disable the background thread
- * UBI_TST_EMULATE_BITFLIPS: emulate bit-flips
- * UBI_TST_EMULATE_WRITE_FAILURES: emulate write failures
- * UBI_TST_EMULATE_ERASE_FAILURES: emulate erase failures
+ * @chk_gen: if UBI general extra checks are enabled
+ * @chk_io: if UBI I/O extra checks are enabled
+ * @disable_bgt: disable the background task for testing purposes
+ * @emulate_bitflips: emulate bit-flips for testing purposes
+ * @emulate_io_failures: emulate write/erase failures for testing purposes
+ * @dfs_dir_name: name of debugfs directory containing files of this UBI device
+ * @dfs_dir: direntry object of the UBI device debugfs directory
+ * @dfs_chk_gen: debugfs knob to enable UBI general extra checks
+ * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks
+ * @dfs_disable_bgt: debugfs knob to disable the background task
+ * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips
+ * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures
*/
-enum {
- UBI_TST_DISABLE_BGT = 0x1,
- UBI_TST_EMULATE_BITFLIPS = 0x2,
- UBI_TST_EMULATE_WRITE_FAILURES = 0x4,
- UBI_TST_EMULATE_ERASE_FAILURES = 0x8,
+struct ubi_debug_info {
+ unsigned int chk_gen:1;
+ unsigned int chk_io:1;
+ unsigned int disable_bgt:1;
+ unsigned int emulate_bitflips:1;
+ unsigned int emulate_io_failures:1;
+ char dfs_dir_name[UBI_DFS_DIR_LEN + 1];
+ struct dentry *dfs_dir;
+ struct dentry *dfs_chk_gen;
+ struct dentry *dfs_chk_io;
+ struct dentry *dfs_disable_bgt;
+ struct dentry *dfs_emulate_bitflips;
+ struct dentry *dfs_emulate_io_failures;
};
/**
* ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ * @ubi: UBI device description object
*
* Returns non-zero if the UBI background thread is disabled for testing
* purposes.
*/
-static inline int ubi_dbg_is_bgt_disabled(void)
+static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
{
- return ubi_tst_flags & UBI_TST_DISABLE_BGT;
+ return ubi->dbg->disable_bgt;
}
/**
* ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
+ * @ubi: UBI device description object
*
* Returns non-zero if a bit-flip should be emulated, otherwise returns zero.
*/
-static inline int ubi_dbg_is_bitflip(void)
+static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_BITFLIPS)
+ if (ubi->dbg->emulate_bitflips)
return !(random32() % 200);
return 0;
}
/**
* ubi_dbg_is_write_failure - if it is time to emulate a write failure.
+ * @ubi: UBI device description object
*
* Returns non-zero if a write failure should be emulated, otherwise returns
* zero.
*/
-static inline int ubi_dbg_is_write_failure(void)
+static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_WRITE_FAILURES)
+ if (ubi->dbg->emulate_io_failures)
return !(random32() % 500);
return 0;
}
/**
* ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
+ * @ubi: UBI device description object
*
* Returns non-zero if an erase failure should be emulated, otherwise returns
* zero.
*/
-static inline int ubi_dbg_is_erase_failure(void)
+static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_ERASE_FAILURES)
+ if (ubi->dbg->emulate_io_failures)
return !(random32() % 400);
return 0;
}
@@ -201,11 +210,6 @@ static inline void ubi_dbg_dump_flash(struct ubi_device *ubi,
static inline void
ubi_dbg_print_hex_dump(const char *l, const char *ps, int pt, int r,
int g, const void *b, size_t len, bool a) { return; }
-
-static inline int ubi_dbg_is_bgt_disabled(void) { return 0; }
-static inline int ubi_dbg_is_bitflip(void) { return 0; }
-static inline int ubi_dbg_is_write_failure(void) { return 0; }
-static inline int ubi_dbg_is_erase_failure(void) { return 0; }
static inline int ubi_dbg_check_all_ff(struct ubi_device *ubi,
int pnum, int offset,
int len) { return 0; }
@@ -213,5 +217,20 @@ static inline int ubi_dbg_check_write(struct ubi_device *ubi,
const void *buf, int pnum,
int offset, int len) { return 0; }
+static inline int ubi_debugging_init_dev(struct ubi_device *ubi) { return 0; }
+static inline void ubi_debugging_exit_dev(struct ubi_device *ubi) { return; }
+static inline int ubi_debugfs_init(void) { return 0; }
+static inline void ubi_debugfs_exit(void) { return; }
+static inline int ubi_debugfs_init_dev(struct ubi_device *ubi) { return 0; }
+static inline void ubi_debugfs_exit_dev(struct ubi_device *ubi) { return; }
+
+static inline int
+ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) { return 0; }
+static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) { return 0; }
+static inline int
+ubi_dbg_is_write_failure(const struct ubi_device *ubi) { return 0; }
+static inline int
+ubi_dbg_is_erase_failure(const struct ubi_device *ubi) { return 0; }
+
#endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8c1b1c7bc4a7..6ba55c235873 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -212,7 +212,7 @@ retry:
} else {
ubi_assert(len == read);
- if (ubi_dbg_is_bitflip()) {
+ if (ubi_dbg_is_bitflip(ubi)) {
dbg_gen("bit-flip (emulated)");
err = UBI_IO_BITFLIPS;
}
@@ -281,7 +281,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
return err;
}
- if (ubi_dbg_is_write_failure()) {
+ if (ubi_dbg_is_write_failure(ubi)) {
dbg_err("cannot write %d bytes to PEB %d:%d "
"(emulated)", len, pnum, offset);
ubi_dbg_dump_stack();
@@ -396,7 +396,7 @@ retry:
if (err)
return err;
- if (ubi_dbg_is_erase_failure()) {
+ if (ubi_dbg_is_erase_failure(ubi)) {
dbg_err("cannot erase PEB %d (emulated)", pnum);
return -EIO;
}
@@ -1146,7 +1146,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
{
int err;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
err = ubi_io_is_bad(ubi, pnum);
@@ -1173,7 +1173,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
int err;
uint32_t magic;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
magic = be32_to_cpu(ec_hdr->magic);
@@ -1211,7 +1211,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
uint32_t crc, hdr_crc;
struct ubi_ec_hdr *ec_hdr;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1255,7 +1255,7 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
int err;
uint32_t magic;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
magic = be32_to_cpu(vid_hdr->magic);
@@ -1296,7 +1296,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
struct ubi_vid_hdr *vid_hdr;
void *p;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
@@ -1348,7 +1348,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
void *buf1;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
@@ -1412,7 +1412,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
void *buf;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 2135a53732ff..a3a198f9b98d 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -1347,7 +1347,7 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
struct ubi_scan_leb *seb, *last_seb;
uint8_t *buf;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
/*
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index c6c22295898e..dc64c767fd21 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -44,7 +44,6 @@
#include "ubi-media.h"
#include "scan.h"
-#include "debug.h"
/* Maximum number of supported UBI devices */
#define UBI_MAX_DEVICES 32
@@ -390,6 +389,8 @@ struct ubi_wl_entry;
* @peb_buf2: another buffer of PEB size used for different purposes
* @buf_mutex: protects @peb_buf1 and @peb_buf2
* @ckvol_mutex: serializes static volume checking when opening
+ *
+ * @dbg: debugging information for this UBI device
*/
struct ubi_device {
struct cdev cdev;
@@ -472,8 +473,12 @@ struct ubi_device {
void *peb_buf2;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
+
+ struct ubi_debug_info *dbg;
};
+#include "debug.h"
+
extern struct kmem_cache *ubi_wl_entry_slab;
extern const struct file_operations ubi_ctrl_cdev_operations;
extern const struct file_operations ubi_cdev_operations;
@@ -662,6 +667,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
if (!ubi->ro_mode) {
ubi->ro_mode = 1;
ubi_warn("switch to read-only mode");
+ ubi_dbg_dump_stack();
}
}
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 366eb70219a6..97e093d19672 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -871,7 +871,7 @@ static int paranoid_check_volumes(struct ubi_device *ubi)
{
int i, err = 0;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
for (i = 0; i < ubi->vtbl_slots; i++) {
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index fd3bf770f518..4b50a3029b84 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -307,8 +307,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
{
int err, tries = 0;
static struct ubi_vid_hdr *vid_hdr;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *new_seb, *old_seb = NULL;
+ struct ubi_scan_leb *new_seb;
ubi_msg("create volume table (copy #%d)", copy + 1);
@@ -316,15 +315,6 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
if (!vid_hdr)
return -ENOMEM;
- /*
- * Check if there is a logical eraseblock which would have to contain
- * this volume table copy was found during scanning. It has to be wiped
- * out.
- */
- sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);
- if (sv)
- old_seb = ubi_scan_find_seb(sv, copy);
-
retry:
new_seb = ubi_scan_get_free_peb(ubi, si);
if (IS_ERR(new_seb)) {
@@ -351,8 +341,8 @@ retry:
goto write_error;
/*
- * And add it to the scanning information. Don't delete the old
- * @old_seb as it will be deleted and freed in 'ubi_scan_add_used()'.
+ * And add it to the scanning information. Don't delete the old version
+ * of this LEB as it will be deleted and freed in 'ubi_scan_add_used()'.
*/
err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec,
vid_hdr, 0);
@@ -876,7 +866,7 @@ out_free:
*/
static void paranoid_vtbl_check(const struct ubi_device *ubi)
{
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return;
if (vtbl_check(ubi, ubi->vtbl)) {
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index ff2c4956eeff..42c684cf3688 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1,4 +1,5 @@
/*
+ * @ubi: UBI device description object
* Copyright (c) International Business Machines Corp., 2006
*
* This program is free software; you can redistribute it and/or modify
@@ -163,12 +164,14 @@ struct ubi_work {
#ifdef CONFIG_MTD_UBI_DEBUG
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
+static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e,
struct rb_root *root);
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e);
+static int paranoid_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e);
#else
#define paranoid_check_ec(ubi, pnum, ec) 0
-#define paranoid_check_in_wl_tree(e, root)
+#define paranoid_check_in_wl_tree(ubi, e, root)
#define paranoid_check_in_pq(ubi, e) 0
#endif
@@ -449,7 +452,7 @@ retry:
BUG();
}
- paranoid_check_in_wl_tree(e, &ubi->free);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->free);
/*
* Move the physical eraseblock to the protection queue where it will
@@ -613,7 +616,7 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
list_add_tail(&wrk->list, &ubi->works);
ubi_assert(ubi->works_count >= 0);
ubi->works_count += 1;
- if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled())
+ if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
wake_up_process(ubi->bgt_thread);
spin_unlock(&ubi->wl_lock);
}
@@ -712,7 +715,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
e1->ec, e2->ec);
goto out_cancel;
}
- paranoid_check_in_wl_tree(e1, &ubi->used);
+ paranoid_check_in_wl_tree(ubi, e1, &ubi->used);
rb_erase(&e1->u.rb, &ubi->used);
dbg_wl("move PEB %d EC %d to PEB %d EC %d",
e1->pnum, e1->ec, e2->pnum, e2->ec);
@@ -721,12 +724,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
scrubbing = 1;
e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- paranoid_check_in_wl_tree(e1, &ubi->scrub);
+ paranoid_check_in_wl_tree(ubi, e1, &ubi->scrub);
rb_erase(&e1->u.rb, &ubi->scrub);
dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
}
- paranoid_check_in_wl_tree(e2, &ubi->free);
+ paranoid_check_in_wl_tree(ubi, e2, &ubi->free);
rb_erase(&e2->u.rb, &ubi->free);
ubi->move_from = e1;
ubi->move_to = e2;
@@ -1169,13 +1172,13 @@ retry:
return 0;
} else {
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(e, &ubi->used);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else if (in_wl_tree(e, &ubi->scrub)) {
- paranoid_check_in_wl_tree(e, &ubi->scrub);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->scrub);
rb_erase(&e->u.rb, &ubi->scrub);
} else if (in_wl_tree(e, &ubi->erroneous)) {
- paranoid_check_in_wl_tree(e, &ubi->erroneous);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->erroneous);
rb_erase(&e->u.rb, &ubi->erroneous);
ubi->erroneous_peb_count -= 1;
ubi_assert(ubi->erroneous_peb_count >= 0);
@@ -1242,7 +1245,7 @@ retry:
}
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(e, &ubi->used);
+ paranoid_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else {
int err;
@@ -1364,7 +1367,7 @@ int ubi_thread(void *u)
spin_lock(&ubi->wl_lock);
if (list_empty(&ubi->works) || ubi->ro_mode ||
- !ubi->thread_enabled || ubi_dbg_is_bgt_disabled()) {
+ !ubi->thread_enabled || ubi_dbg_is_bgt_disabled(ubi)) {
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock(&ubi->wl_lock);
schedule();
@@ -1579,7 +1582,7 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
long long read_ec;
struct ubi_ec_hdr *ec_hdr;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1609,16 +1612,18 @@ out_free:
/**
* paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
+ * @ubi: UBI device description object
* @e: the wear-leveling entry to check
* @root: the root of the tree
*
* This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
* is not.
*/
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
+static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e,
struct rb_root *root)
{
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
if (in_wl_tree(e, root))
@@ -1638,12 +1643,13 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
*
* This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
*/
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
+static int paranoid_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e)
{
struct ubi_wl_entry *p;
int i;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 5b732988d493..84e68f1b9adf 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -49,6 +49,7 @@ static const char version[] =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 903bcb3ef5bd..60b35fb5f524 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -594,7 +594,6 @@ static void lance_load_multicast (struct net_device *dev)
volatile struct lance_init_block *ib = lp->init_block;
volatile u16 *mcast_table = (u16 *)&ib->filter;
struct netdev_hw_addr *ha;
- char *addrs;
u32 crc;
/* set all multicast bits */
@@ -609,13 +608,7 @@ static void lance_load_multicast (struct net_device *dev)
/* Add addresses */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- /* multicast address? */
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc = crc >> 26;
mcast_table [crc >> 4] |= 1 << (crc & 0xf);
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 10c45051caea..cc4c210a91f8 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -60,6 +60,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
@@ -77,17 +78,6 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-/* VLAN tagging feature enable/disable */
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define CP_VLAN_TAG_USED 1
-#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
- do { (tx_desc)->opts2 = cpu_to_le32(vlan_tag_value); } while (0)
-#else
-#define CP_VLAN_TAG_USED 0
-#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
- do { (tx_desc)->opts2 = 0; } while (0)
-#endif
-
/* These identify the driver base version and may not be removed. */
static char version[] =
DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -355,9 +345,6 @@ struct cp_private {
unsigned rx_buf_sz;
unsigned wol_enabled : 1; /* Is Wake-on-LAN enabled? */
-#if CP_VLAN_TAG_USED
- struct vlan_group *vlgrp;
-#endif
dma_addr_t ring_dma;
struct mii_if_info mii_if;
@@ -422,24 +409,6 @@ static struct {
};
-#if CP_VLAN_TAG_USED
-static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
- struct cp_private *cp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&cp->lock, flags);
- cp->vlgrp = grp;
- if (grp)
- cp->cpcmd |= RxVlanOn;
- else
- cp->cpcmd &= ~RxVlanOn;
-
- cpw16(CpCmd, cp->cpcmd);
- spin_unlock_irqrestore(&cp->lock, flags);
-}
-#endif /* CP_VLAN_TAG_USED */
-
static inline void cp_set_rxbufsize (struct cp_private *cp)
{
unsigned int mtu = cp->dev->mtu;
@@ -454,18 +423,17 @@ static inline void cp_set_rxbufsize (struct cp_private *cp)
static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
struct cp_desc *desc)
{
+ u32 opts2 = le32_to_cpu(desc->opts2);
+
skb->protocol = eth_type_trans (skb, cp->dev);
cp->dev->stats.rx_packets++;
cp->dev->stats.rx_bytes += skb->len;
-#if CP_VLAN_TAG_USED
- if (cp->vlgrp && (desc->opts2 & cpu_to_le32(RxVlanTagged))) {
- vlan_hwaccel_receive_skb(skb, cp->vlgrp,
- swab16(le32_to_cpu(desc->opts2) & 0xffff));
- } else
-#endif
- netif_receive_skb(skb);
+ if (opts2 & RxVlanTagged)
+ __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
+
+ napi_gro_receive(&cp->napi, skb);
}
static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
@@ -729,6 +697,12 @@ static void cp_tx (struct cp_private *cp)
netif_wake_queue(cp->dev);
}
+static inline u32 cp_tx_vlan_tag(struct sk_buff *skb)
+{
+ return vlan_tx_tag_present(skb) ?
+ TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
+}
+
static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
struct net_device *dev)
{
@@ -736,9 +710,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
unsigned entry;
u32 eor, flags;
unsigned long intr_flags;
-#if CP_VLAN_TAG_USED
- u32 vlan_tag = 0;
-#endif
+ __le32 opts2;
int mss = 0;
spin_lock_irqsave(&cp->lock, intr_flags);
@@ -751,15 +723,12 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
-#if CP_VLAN_TAG_USED
- if (vlan_tx_tag_present(skb))
- vlan_tag = TxVlanTag | swab16(vlan_tx_tag_get(skb));
-#endif
-
entry = cp->tx_head;
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
mss = skb_shinfo(skb)->gso_size;
+ opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
+
if (skb_shinfo(skb)->nr_frags == 0) {
struct cp_desc *txd = &cp->tx_ring[entry];
u32 len;
@@ -767,7 +736,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
len = skb->len;
mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
- CP_VLAN_TX_TAG(txd, vlan_tag);
+ txd->opts2 = opts2;
txd->addr = cpu_to_le64(mapping);
wmb();
@@ -838,7 +807,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
ctrl |= LastFrag;
txd = &cp->tx_ring[entry];
- CP_VLAN_TX_TAG(txd, vlan_tag);
+ txd->opts2 = opts2;
txd->addr = cpu_to_le64(mapping);
wmb();
@@ -850,7 +819,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
}
txd = &cp->tx_ring[first_entry];
- CP_VLAN_TX_TAG(txd, vlan_tag);
+ txd->opts2 = opts2;
txd->addr = cpu_to_le64(first_mapping);
wmb();
@@ -1430,6 +1399,11 @@ static int cp_set_features(struct net_device *dev, u32 features)
else
cp->cpcmd &= ~RxChkSum;
+ if (features & NETIF_F_HW_VLAN_RX)
+ cp->cpcmd |= RxVlanOn;
+ else
+ cp->cpcmd &= ~RxVlanOn;
+
cpw16_f(CpCmd, cp->cpcmd);
spin_unlock_irqrestore(&cp->lock, flags);
@@ -1817,9 +1791,6 @@ static const struct net_device_ops cp_netdev_ops = {
.ndo_start_xmit = cp_start_xmit,
.ndo_tx_timeout = cp_tx_timeout,
.ndo_set_features = cp_set_features,
-#if CP_VLAN_TAG_USED
- .ndo_vlan_rx_register = cp_vlan_rx_register,
-#endif
#ifdef BROKEN
.ndo_change_mtu = cp_change_mtu,
#endif
@@ -1948,15 +1919,16 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->ethtool_ops = &cp_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
-#if CP_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
/* disabled by default until verified */
- dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
+ dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+ NETIF_F_HIGHDMA;
dev->irq = pdev->irq;
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index e3bad8247fd1..c2672c692d6f 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -100,6 +100,7 @@
#include <linux/compiler.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 3d9e8fb4fbee..58a12e4c78f9 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -9,6 +9,7 @@
#include <linux/if_ether.h>
#include <linux/ioport.h>
+#include <linux/irqreturn.h>
#include <linux/skbuff.h>
#define TX_PAGES 12 /* Two Tx slots */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 93359fab240e..8d0314dbd946 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1934,13 +1934,6 @@ config DECLANCE
DEC (now Compaq) based on the AMD Lance chipset, including the
DEPCA series. (This chipset is better known via the NE2100 cards.)
-config 68360_ENET
- bool "Motorola 68360 ethernet controller"
- depends on M68360
- help
- Say Y here if you want to use the built-in ethernet controller of
- the Motorola 68360 processor.
-
config FEC
bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
@@ -2115,7 +2108,6 @@ config E1000
config E1000E
tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
- select CRC32
depends on PCI && (!SPARC32 || BROKEN)
select CRC32
---help---
@@ -2197,15 +2189,6 @@ config IGBVF
source "drivers/net/ixp2000/Kconfig"
-config MYRI_SBUS
- tristate "MyriCOM Gigabit Ethernet support"
- depends on SBUS
- help
- This driver supports MyriCOM Sbus gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called myri_sbus. This is recommended.
-
config NS83820
tristate "National Semiconductor DP83820 support"
depends on PCI
@@ -2282,7 +2265,7 @@ config SIS190
will be called sis190. This is recommended.
config SKGE
- tristate "New SysKonnect GigaEthernet support"
+ tristate "Marvell Yukon Gigabit Ethernet support"
depends on PCI
select CRC32
---help---
@@ -2298,7 +2281,7 @@ config SKGE
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 Yukon2-based adapters.
+ 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.
@@ -2313,8 +2296,17 @@ config SKGE_DEBUG
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 "SysKonnect Yukon2 support"
+ tristate "Marvell Yukon 2 support"
depends on PCI
select CRC32
---help---
@@ -2324,7 +2316,7 @@ config SKY2
88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
There is companion driver for the older Marvell Yukon and
- Genesis based adapters: skge.
+ SysKonnect Genesis based adapters: skge.
To compile this driver as a module, choose M here: the module
will be called sky2. This is recommended.
@@ -2561,6 +2553,15 @@ config PCH_GBE
ML7223 is companion chip for Intel Atom E6xx series.
ML7223 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
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 776a478e6296..b7622c3745fa 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -59,7 +59,6 @@ obj-$(CONFIG_HAPPYMEAL) += sunhme.o
obj-$(CONFIG_SUNLANCE) += sunlance.o
obj-$(CONFIG_SUNQE) += sunqe.o
obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
obj-$(CONFIG_CASSINI) += cassini.o
obj-$(CONFIG_SUNVNET) += sunvnet.o
@@ -128,7 +127,6 @@ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
endif
-obj-$(CONFIG_68360_ENET) += 68360enet.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_EL2) += 3c503.o 8390p.o
obj-$(CONFIG_NE2000) += ne.o 8390p.o
@@ -148,6 +146,7 @@ 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
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index deaa8bc16cf8..e1e1b07d9b8d 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -37,6 +37,11 @@
* both 10BASE-2 (thin coax) and AUI (DB-15) connectors
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+/*#define DEBUG*/
+/*#define TEST_HITS*/
+
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -58,29 +63,22 @@
#include "a2065.h"
-
- /*
- * Transmit/Receive Ring Definitions
- */
+/* Transmit/Receive Ring Definitions */
#define LANCE_LOG_TX_BUFFERS (2)
#define LANCE_LOG_RX_BUFFERS (4)
-#define TX_RING_SIZE (1<<LANCE_LOG_TX_BUFFERS)
-#define RX_RING_SIZE (1<<LANCE_LOG_RX_BUFFERS)
+#define TX_RING_SIZE (1 << LANCE_LOG_TX_BUFFERS)
+#define RX_RING_SIZE (1 << LANCE_LOG_RX_BUFFERS)
-#define TX_RING_MOD_MASK (TX_RING_SIZE-1)
-#define RX_RING_MOD_MASK (RX_RING_SIZE-1)
+#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
+#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
#define PKT_BUF_SIZE (1544)
#define RX_BUFF_SIZE PKT_BUF_SIZE
#define TX_BUFF_SIZE PKT_BUF_SIZE
-
- /*
- * Layout of the Lance's RAM Buffer
- */
-
+/* Layout of the Lance's RAM Buffer */
struct lance_init_block {
unsigned short mode; /* Pre-set mode (reg. 15) */
@@ -97,14 +95,11 @@ struct lance_init_block {
struct lance_rx_desc brx_ring[RX_RING_SIZE];
struct lance_tx_desc btx_ring[TX_RING_SIZE];
- char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
- char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+ char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
+ char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE];
};
-
- /*
- * Private Device Data
- */
+/* Private Device Data */
struct lance_private {
char *name;
@@ -129,21 +124,14 @@ struct lance_private {
struct timer_list multicast_timer;
};
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
- lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\
- lp->tx_old - lp->tx_new-1)
-
-
#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
/* Load the CSR registers */
-static void load_csrs (struct lance_private *lp)
+static void load_csrs(struct lance_private *lp)
{
volatile struct lance_regs *ll = lp->ll;
volatile struct lance_init_block *aib = lp->lance_init_block;
- int leptr;
-
- leptr = LANCE_ADDR (aib);
+ int leptr = LANCE_ADDR(aib);
ll->rap = LE_CSR1;
ll->rdp = (leptr & 0xFFFF);
@@ -156,19 +144,16 @@ static void load_csrs (struct lance_private *lp)
ll->rap = LE_CSR0;
}
-#define ZERO 0
-
/* Setup the Lance Rx and Tx rings */
-static void lance_init_ring (struct net_device *dev)
+static void lance_init_ring(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
- volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
+ volatile struct lance_init_block *aib = lp->lance_init_block;
+ /* for LANCE_ADDR computations */
int leptr;
int i;
- aib = lp->lance_init_block;
-
/* Lock out other processes while setting up hardware */
netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
@@ -179,41 +164,38 @@ static void lance_init_ring (struct net_device *dev)
/* Copy the ethernet address to the lance init block
* Note that on the sparc you need to swap the ethernet address.
*/
- ib->phys_addr [0] = dev->dev_addr [1];
- ib->phys_addr [1] = dev->dev_addr [0];
- ib->phys_addr [2] = dev->dev_addr [3];
- ib->phys_addr [3] = dev->dev_addr [2];
- ib->phys_addr [4] = dev->dev_addr [5];
- ib->phys_addr [5] = dev->dev_addr [4];
-
- if (ZERO)
- printk(KERN_DEBUG "TX rings:\n");
+ ib->phys_addr[0] = dev->dev_addr[1];
+ ib->phys_addr[1] = dev->dev_addr[0];
+ ib->phys_addr[2] = dev->dev_addr[3];
+ ib->phys_addr[3] = dev->dev_addr[2];
+ ib->phys_addr[4] = dev->dev_addr[5];
+ ib->phys_addr[5] = dev->dev_addr[4];
/* Setup the Tx ring entries */
- for (i = 0; i <= (1<<lp->lance_log_tx_bufs); i++) {
+ netdev_dbg(dev, "TX rings:\n");
+ for (i = 0; i <= 1 << lp->lance_log_tx_bufs; i++) {
leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
- ib->btx_ring [i].tmd0 = leptr;
- ib->btx_ring [i].tmd1_hadr = leptr >> 16;
- ib->btx_ring [i].tmd1_bits = 0;
- ib->btx_ring [i].length = 0xf000; /* The ones required by tmd2 */
- ib->btx_ring [i].misc = 0;
- if (i < 3 && ZERO)
- printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr);
+ ib->btx_ring[i].tmd0 = leptr;
+ ib->btx_ring[i].tmd1_hadr = leptr >> 16;
+ ib->btx_ring[i].tmd1_bits = 0;
+ ib->btx_ring[i].length = 0xf000; /* The ones required by tmd2 */
+ ib->btx_ring[i].misc = 0;
+ if (i < 3)
+ netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
}
/* Setup the Rx ring entries */
- if (ZERO)
- printk(KERN_DEBUG "RX rings:\n");
- for (i = 0; i < (1<<lp->lance_log_rx_bufs); i++) {
+ netdev_dbg(dev, "RX rings:\n");
+ for (i = 0; i < 1 << lp->lance_log_rx_bufs; i++) {
leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
- ib->brx_ring [i].rmd0 = leptr;
- ib->brx_ring [i].rmd1_hadr = leptr >> 16;
- ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
- ib->brx_ring [i].length = -RX_BUFF_SIZE | 0xf000;
- ib->brx_ring [i].mblength = 0;
- if (i < 3 && ZERO)
- printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr);
+ ib->brx_ring[i].rmd0 = leptr;
+ ib->brx_ring[i].rmd1_hadr = leptr >> 16;
+ ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
+ ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000;
+ ib->brx_ring[i].mblength = 0;
+ if (i < 3)
+ netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
}
/* Setup the initialization block */
@@ -222,22 +204,20 @@ static void lance_init_ring (struct net_device *dev)
leptr = LANCE_ADDR(&aib->brx_ring);
ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
ib->rx_ptr = leptr;
- if (ZERO)
- printk(KERN_DEBUG "RX ptr: %8.8x\n", leptr);
+ netdev_dbg(dev, "RX ptr: %08x\n", leptr);
/* Setup tx descriptor pointer */
leptr = LANCE_ADDR(&aib->btx_ring);
ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
ib->tx_ptr = leptr;
- if (ZERO)
- printk(KERN_DEBUG "TX ptr: %8.8x\n", leptr);
+ netdev_dbg(dev, "TX ptr: %08x\n", leptr);
/* Clear the multicast filter */
- ib->filter [0] = 0;
- ib->filter [1] = 0;
+ ib->filter[0] = 0;
+ ib->filter[1] = 0;
}
-static int init_restart_lance (struct lance_private *lp)
+static int init_restart_lance(struct lance_private *lp)
{
volatile struct lance_regs *ll = lp->ll;
int i;
@@ -249,8 +229,7 @@ static int init_restart_lance (struct lance_private *lp)
for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++)
barrier();
if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
- printk(KERN_ERR "LANCE unopened after %d ticks, csr0=%4.4x.\n",
- i, ll->rdp);
+ pr_err("unopened after %d ticks, csr0=%04x\n", i, ll->rdp);
return -EIO;
}
@@ -261,7 +240,7 @@ static int init_restart_lance (struct lance_private *lp)
return 0;
}
-static int lance_rx (struct net_device *dev)
+static int lance_rx(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
@@ -271,22 +250,24 @@ static int lance_rx (struct net_device *dev)
#ifdef TEST_HITS
int i;
- printk(KERN_DEBUG "[");
+ char buf[RX_RING_SIZE + 1];
+
for (i = 0; i < RX_RING_SIZE; i++) {
+ char r1_own = ib->brx_ring[i].rmd1_bits & LE_R1_OWN;
if (i == lp->rx_new)
- printk ("%s",
- ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
+ buf[i] = r1_own ? '_' : 'X';
else
- printk ("%s",
- ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
+ buf[i] = r1_own ? '.' : '1';
}
- printk ("]\n");
+ buf[RX_RING_SIZE] = 0;
+
+ pr_debug("RxRing TestHits: [%s]\n", buf);
#endif
- ll->rdp = LE_C0_RINT|LE_C0_INEA;
- for (rd = &ib->brx_ring [lp->rx_new];
+ ll->rdp = LE_C0_RINT | LE_C0_INEA;
+ for (rd = &ib->brx_ring[lp->rx_new];
!((bits = rd->rmd1_bits) & LE_R1_OWN);
- rd = &ib->brx_ring [lp->rx_new]) {
+ rd = &ib->brx_ring[lp->rx_new]) {
/* We got an incomplete frame? */
if ((bits & LE_R1_POK) != LE_R1_POK) {
@@ -297,18 +278,22 @@ static int lance_rx (struct net_device *dev)
/* Count only the end frame as a rx error,
* not the beginning
*/
- if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
- if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
- if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
- if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
- if (bits & LE_R1_EOP) dev->stats.rx_errors++;
+ if (bits & LE_R1_BUF)
+ dev->stats.rx_fifo_errors++;
+ if (bits & LE_R1_CRC)
+ dev->stats.rx_crc_errors++;
+ if (bits & LE_R1_OFL)
+ dev->stats.rx_over_errors++;
+ if (bits & LE_R1_FRA)
+ dev->stats.rx_frame_errors++;
+ if (bits & LE_R1_EOP)
+ dev->stats.rx_errors++;
} else {
int len = (rd->mblength & 0xfff) - 4;
- struct sk_buff *skb = dev_alloc_skb (len+2);
+ struct sk_buff *skb = dev_alloc_skb(len + 2);
if (!skb) {
- printk(KERN_WARNING "%s: Memory squeeze, "
- "deferring packet.\n", dev->name);
+ netdev_warn(dev, "Memory squeeze, deferring packet\n");
dev->stats.rx_dropped++;
rd->mblength = 0;
rd->rmd1_bits = LE_R1_OWN;
@@ -316,13 +301,13 @@ static int lance_rx (struct net_device *dev)
return 0;
}
- skb_reserve (skb, 2); /* 16 byte align */
- skb_put (skb, len); /* make room */
+ skb_reserve(skb, 2); /* 16 byte align */
+ skb_put(skb, len); /* make room */
skb_copy_to_linear_data(skb,
- (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
- len);
- skb->protocol = eth_type_trans (skb, dev);
- netif_rx (skb);
+ (unsigned char *)&ib->rx_buf[lp->rx_new][0],
+ len);
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
}
@@ -335,7 +320,7 @@ static int lance_rx (struct net_device *dev)
return 0;
}
-static int lance_tx (struct net_device *dev)
+static int lance_tx(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
@@ -350,7 +335,7 @@ static int lance_tx (struct net_device *dev)
j = lp->tx_old;
for (i = j; i != lp->tx_new; i = j) {
- td = &ib->btx_ring [i];
+ td = &ib->btx_ring[i];
/* If we hit a packet not owned by us, stop */
if (td->tmd1_bits & LE_T1_OWN)
@@ -360,45 +345,44 @@ static int lance_tx (struct net_device *dev)
status = td->misc;
dev->stats.tx_errors++;
- if (status & LE_T3_RTY) dev->stats.tx_aborted_errors++;
- if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
+ if (status & LE_T3_RTY)
+ dev->stats.tx_aborted_errors++;
+ if (status & LE_T3_LCOL)
+ dev->stats.tx_window_errors++;
if (status & LE_T3_CLOS) {
dev->stats.tx_carrier_errors++;
if (lp->auto_select) {
lp->tpe = 1 - lp->tpe;
- printk(KERN_ERR "%s: Carrier Lost, "
- "trying %s\n", dev->name,
- lp->tpe?"TPE":"AUI");
+ netdev_err(dev, "Carrier Lost, trying %s\n",
+ lp->tpe ? "TPE" : "AUI");
/* Stop the lance */
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- lance_init_ring (dev);
- load_csrs (lp);
- init_restart_lance (lp);
+ lance_init_ring(dev);
+ load_csrs(lp);
+ init_restart_lance(lp);
return 0;
}
}
- /* buffer errors and underflows turn off the transmitter */
- /* Restart the adapter */
- if (status & (LE_T3_BUF|LE_T3_UFL)) {
+ /* buffer errors and underflows turn off
+ * the transmitter, so restart the adapter
+ */
+ if (status & (LE_T3_BUF | LE_T3_UFL)) {
dev->stats.tx_fifo_errors++;
- printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, "
- "restarting\n", dev->name);
+ netdev_err(dev, "Tx: ERR_BUF|ERR_UFL, restarting\n");
/* Stop the lance */
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- lance_init_ring (dev);
- load_csrs (lp);
- init_restart_lance (lp);
+ lance_init_ring(dev);
+ load_csrs(lp);
+ init_restart_lance(lp);
return 0;
}
} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
- /*
- * So we don't count the packet more than once.
- */
+ /* So we don't count the packet more than once. */
td->tmd1_bits &= ~(LE_T1_POK);
/* One collision before packet was sent. */
@@ -419,17 +403,19 @@ static int lance_tx (struct net_device *dev)
return 0;
}
-static irqreturn_t lance_interrupt (int irq, void *dev_id)
+static int lance_tx_buffs_avail(struct lance_private *lp)
{
- struct net_device *dev;
- struct lance_private *lp;
- volatile struct lance_regs *ll;
- int csr0;
-
- dev = (struct net_device *) dev_id;
+ if (lp->tx_old <= lp->tx_new)
+ return lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new;
+ return lp->tx_old - lp->tx_new - 1;
+}
- lp = netdev_priv(dev);
- ll = lp->ll;
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct lance_private *lp = netdev_priv(dev);
+ volatile struct lance_regs *ll = lp->ll;
+ int csr0;
ll->rap = LE_CSR0; /* LANCE Controller Status */
csr0 = ll->rdp;
@@ -438,19 +424,19 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id)
return IRQ_NONE; /* been generated by the Lance. */
/* Acknowledge all the interrupt sources ASAP */
- ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|
+ ll->rdp = csr0 & ~(LE_C0_INEA | LE_C0_TDMD | LE_C0_STOP | LE_C0_STRT |
LE_C0_INIT);
- if ((csr0 & LE_C0_ERR)) {
+ if (csr0 & LE_C0_ERR) {
/* Clear the error condition */
- ll->rdp = LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA;
+ ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | LE_C0_INEA;
}
if (csr0 & LE_C0_RINT)
- lance_rx (dev);
+ lance_rx(dev);
if (csr0 & LE_C0_TINT)
- lance_tx (dev);
+ lance_tx(dev);
/* Log misc errors. */
if (csr0 & LE_C0_BABL)
@@ -458,22 +444,22 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id)
if (csr0 & LE_C0_MISS)
dev->stats.rx_errors++; /* Missed a Rx frame. */
if (csr0 & LE_C0_MERR) {
- printk(KERN_ERR "%s: Bus master arbitration failure, status "
- "%4.4x.\n", dev->name, csr0);
+ netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+ csr0);
/* Restart the chip. */
ll->rdp = LE_C0_STRT;
}
- if (netif_queue_stopped(dev) && TX_BUFFS_AVAIL > 0)
+ if (netif_queue_stopped(dev) && lance_tx_buffs_avail(lp) > 0)
netif_wake_queue(dev);
ll->rap = LE_CSR0;
- ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|
- LE_C0_IDON|LE_C0_INEA;
+ ll->rdp = (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR |
+ LE_C0_IDON | LE_C0_INEA);
return IRQ_HANDLED;
}
-static int lance_open (struct net_device *dev)
+static int lance_open(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -486,17 +472,18 @@ static int lance_open (struct net_device *dev)
/* Install the Interrupt handler */
ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, IRQF_SHARED,
dev->name, dev);
- if (ret) return ret;
+ if (ret)
+ return ret;
- load_csrs (lp);
- lance_init_ring (dev);
+ load_csrs(lp);
+ lance_init_ring(dev);
netif_start_queue(dev);
- return init_restart_lance (lp);
+ return init_restart_lance(lp);
}
-static int lance_close (struct net_device *dev)
+static int lance_close(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -512,7 +499,7 @@ static int lance_close (struct net_device *dev)
return 0;
}
-static inline int lance_reset (struct net_device *dev)
+static inline int lance_reset(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -522,16 +509,15 @@ static inline int lance_reset (struct net_device *dev)
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- load_csrs (lp);
+ load_csrs(lp);
- lance_init_ring (dev);
+ lance_init_ring(dev);
dev->trans_start = jiffies; /* prevent tx timeout */
netif_start_queue(dev);
- status = init_restart_lance (lp);
-#ifdef DEBUG_DRIVER
- printk(KERN_DEBUG "Lance restart=%d\n", status);
-#endif
+ status = init_restart_lance(lp);
+ netdev_dbg(dev, "Lance restart=%d\n", status);
+
return status;
}
@@ -540,14 +526,13 @@ static void lance_tx_timeout(struct net_device *dev)
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
- printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
- dev->name, ll->rdp);
+ netdev_err(dev, "transmit timed out, status %04x, reset\n", ll->rdp);
lance_reset(dev);
netif_wake_queue(dev);
}
-static netdev_tx_t lance_start_xmit (struct sk_buff *skb,
- struct net_device *dev)
+static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -562,33 +547,33 @@ static netdev_tx_t lance_start_xmit (struct sk_buff *skb,
local_irq_save(flags);
- if (!TX_BUFFS_AVAIL){
+ if (!lance_tx_buffs_avail(lp)) {
local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
-#ifdef DEBUG_DRIVER
+#ifdef DEBUG
/* dump the packet */
print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
16, 1, skb->data, 64, true);
#endif
entry = lp->tx_new & lp->tx_ring_mod_mask;
- ib->btx_ring [entry].length = (-skblen) | 0xf000;
- ib->btx_ring [entry].misc = 0;
+ ib->btx_ring[entry].length = (-skblen) | 0xf000;
+ ib->btx_ring[entry].misc = 0;
- skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen);
+ skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
/* Now, give the packet to the lance */
- ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+ ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
dev->stats.tx_bytes += skblen;
- if (TX_BUFFS_AVAIL <= 0)
+ if (lance_tx_buffs_avail(lp) <= 0)
netif_stop_queue(dev);
/* Kick the lance: transmit now */
ll->rdp = LE_C0_INEA | LE_C0_TDMD;
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
local_irq_restore(flags);
@@ -596,40 +581,33 @@ static netdev_tx_t lance_start_xmit (struct sk_buff *skb,
}
/* taken from the depca driver */
-static void lance_load_multicast (struct net_device *dev)
+static void lance_load_multicast(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
volatile u16 *mcast_table = (u16 *)&ib->filter;
struct netdev_hw_addr *ha;
- char *addrs;
u32 crc;
/* set all multicast bits */
- if (dev->flags & IFF_ALLMULTI){
- ib->filter [0] = 0xffffffff;
- ib->filter [1] = 0xffffffff;
+ if (dev->flags & IFF_ALLMULTI) {
+ ib->filter[0] = 0xffffffff;
+ ib->filter[1] = 0xffffffff;
return;
}
/* clear the multicast filter */
- ib->filter [0] = 0;
- ib->filter [1] = 0;
+ ib->filter[0] = 0;
+ ib->filter[1] = 0;
/* Add addresses */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- /* multicast address? */
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc = crc >> 26;
- mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+ mcast_table[crc >> 4] |= 1 << (crc & 0xf);
}
}
-static void lance_set_multicast (struct net_device *dev)
+static void lance_set_multicast(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
@@ -648,16 +626,16 @@ static void lance_set_multicast (struct net_device *dev)
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- lance_init_ring (dev);
+ lance_init_ring(dev);
if (dev->flags & IFF_PROMISC) {
ib->mode |= LE_MO_PROM;
} else {
ib->mode &= ~LE_MO_PROM;
- lance_load_multicast (dev);
+ lance_load_multicast(dev);
}
- load_csrs (lp);
- init_restart_lance (lp);
+ load_csrs(lp);
+ init_restart_lance(lp);
netif_wake_queue(dev);
}
@@ -697,14 +675,12 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
{
struct net_device *dev;
struct lance_private *priv;
- unsigned long board, base_addr, mem_start;
+ unsigned long board = z->resource.start;
+ unsigned long base_addr = board + A2065_LANCE;
+ unsigned long mem_start = board + A2065_RAM;
struct resource *r1, *r2;
int err;
- board = z->resource.start;
- base_addr = board+A2065_LANCE;
- mem_start = board+A2065_RAM;
-
r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
"Am7990");
if (!r1)
@@ -735,12 +711,12 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0x9f;
}
- dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
- dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
+ dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+ dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
dev->base_addr = ZTWO_VADDR(base_addr);
dev->mem_start = ZTWO_VADDR(mem_start);
- dev->mem_end = dev->mem_start+A2065_RAM_SIZE;
+ dev->mem_end = dev->mem_start + A2065_RAM_SIZE;
priv->ll = (volatile struct lance_regs *)dev->base_addr;
priv->init_block = (struct lance_init_block *)dev->mem_start;
@@ -760,7 +736,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
init_timer(&priv->multicast_timer);
priv->multicast_timer.data = (unsigned long) dev;
priv->multicast_timer.function =
- (void (*)(unsigned long)) &lance_set_multicast;
+ (void (*)(unsigned long))lance_set_multicast;
err = register_netdev(dev);
if (err) {
@@ -771,8 +747,8 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
}
zorro_set_drvdata(z, dev);
- printk(KERN_INFO "%s: A2065 at 0x%08lx, Ethernet Address "
- "%pM\n", dev->name, board, dev->dev_addr);
+ netdev_info(dev, "A2065 at 0x%08lx, Ethernet Address %pM\n",
+ board, dev->dev_addr);
return 0;
}
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 5181e9322119..f07b2e980fbc 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -32,6 +32,7 @@ static const char version[] =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/io.h>
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index d7c1bfe4b6ec..536038b22710 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -69,10 +69,7 @@
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
-
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#include <linux/if_vlan.h>
-#endif
#ifdef SIOCETHTOOL
#include <linux/ethtool.h>
@@ -171,15 +168,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
#define BOARD_IDX_STATIC 0
#define BOARD_IDX_OVERFLOW -1
-#if (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) && \
- defined(NETIF_F_HW_VLAN_RX)
-#define ACENIC_DO_VLAN 1
-#define ACE_RCB_VLAN_FLAG RCB_FLG_VLAN_ASSIST
-#else
-#define ACENIC_DO_VLAN 0
-#define ACE_RCB_VLAN_FLAG 0
-#endif
-
#include "acenic.h"
/*
@@ -465,9 +453,6 @@ static const struct net_device_ops ace_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ace_set_mac_addr,
.ndo_change_mtu = ace_change_mtu,
-#if ACENIC_DO_VLAN
- .ndo_vlan_rx_register = ace_vlan_rx_register,
-#endif
};
static int __devinit acenic_probe_one(struct pci_dev *pdev,
@@ -491,9 +476,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
ap->name = pci_name(pdev);
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-#if ACENIC_DO_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
dev->watchdog_timeo = 5*HZ;
@@ -1248,7 +1231,7 @@ static int __devinit ace_init(struct net_device *dev)
set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
info->rx_std_ctrl.max_len = ACE_STD_BUFSIZE;
info->rx_std_ctrl.flags =
- RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
+ RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
memset(ap->rx_std_ring, 0,
RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1264,7 +1247,7 @@ static int __devinit ace_init(struct net_device *dev)
(sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
info->rx_jumbo_ctrl.max_len = 0;
info->rx_jumbo_ctrl.flags =
- RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
+ RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
memset(ap->rx_jumbo_ring, 0,
RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1286,7 +1269,7 @@ static int __devinit ace_init(struct net_device *dev)
RX_JUMBO_RING_ENTRIES))));
info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
info->rx_mini_ctrl.flags =
- RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|ACE_RCB_VLAN_FLAG;
+ RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|RCB_FLG_VLAN_ASSIST;
for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
ap->rx_mini_ring[i].flags =
@@ -1332,7 +1315,7 @@ static int __devinit ace_init(struct net_device *dev)
}
info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap);
- tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
+ tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
/*
* The Tigon I does not like having the TX ring in host memory ;-(
@@ -1674,7 +1657,7 @@ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
struct rx_desc *rd;
dma_addr_t mapping;
- skb = alloc_skb(ACE_STD_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC);
+ skb = dev_alloc_skb(ACE_STD_BUFSIZE + NET_IP_ALIGN);
if (!skb)
break;
@@ -1735,7 +1718,7 @@ static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs)
struct rx_desc *rd;
dma_addr_t mapping;
- skb = alloc_skb(ACE_MINI_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC);
+ skb = dev_alloc_skb(ACE_MINI_BUFSIZE + NET_IP_ALIGN);
if (!skb)
break;
@@ -1791,7 +1774,7 @@ static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs)
struct rx_desc *rd;
dma_addr_t mapping;
- skb = alloc_skb(ACE_JUMBO_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC);
+ skb = dev_alloc_skb(ACE_JUMBO_BUFSIZE + NET_IP_ALIGN);
if (!skb)
break;
@@ -2038,12 +2021,9 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
}
/* send it up */
-#if ACENIC_DO_VLAN
- if (ap->vlgrp && (bd_flags & BD_FLG_VLAN_TAG)) {
- vlan_hwaccel_rx(skb, ap->vlgrp, retdesc->vlan);
- } else
-#endif
- netif_rx(skb);
+ if ((bd_flags & BD_FLG_VLAN_TAG))
+ __vlan_hwaccel_put_tag(skb, retdesc->vlan);
+ netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += retdesc->size;
@@ -2262,24 +2242,6 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-
-#if ACENIC_DO_VLAN
-static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
- struct ace_private *ap = netdev_priv(dev);
- unsigned long flags;
-
- local_irq_save(flags);
- ace_mask_irq(dev);
-
- ap->vlgrp = grp;
-
- ace_unmask_irq(dev);
- local_irq_restore(flags);
-}
-#endif /* ACENIC_DO_VLAN */
-
-
static int ace_open(struct net_device *dev)
{
struct ace_private *ap = netdev_priv(dev);
@@ -2449,16 +2411,12 @@ ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr,
writel(addr >> 32, &io->addr.addrhi);
writel(addr & 0xffffffff, &io->addr.addrlo);
writel(flagsize, &io->flagsize);
-#if ACENIC_DO_VLAN
writel(vlan_tag, &io->vlanres);
-#endif
} else {
desc->addr.addrhi = addr >> 32;
desc->addr.addrlo = addr;
desc->flagsize = flagsize;
-#if ACENIC_DO_VLAN
desc->vlanres = vlan_tag;
-#endif
}
}
@@ -2486,12 +2444,10 @@ restart:
flagsize = (skb->len << 16) | (BD_FLG_END);
if (skb->ip_summed == CHECKSUM_PARTIAL)
flagsize |= BD_FLG_TCP_UDP_SUM;
-#if ACENIC_DO_VLAN
if (vlan_tx_tag_present(skb)) {
flagsize |= BD_FLG_VLAN_TAG;
vlan_tag = vlan_tx_tag_get(skb);
}
-#endif
desc = ap->tx_ring + idx;
idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
@@ -2509,12 +2465,10 @@ restart:
flagsize = (skb_headlen(skb) << 16);
if (skb->ip_summed == CHECKSUM_PARTIAL)
flagsize |= BD_FLG_TCP_UDP_SUM;
-#if ACENIC_DO_VLAN
if (vlan_tx_tag_present(skb)) {
flagsize |= BD_FLG_VLAN_TAG;
vlan_tag = vlan_tx_tag_get(skb);
}
-#endif
ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize, vlan_tag);
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 0681da7e8753..f67dc9b0eb80 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -1,5 +1,6 @@
#ifndef _ACENIC_H_
#define _ACENIC_H_
+#include <linux/interrupt.h>
/*
@@ -664,10 +665,6 @@ struct ace_private
struct rx_desc *rx_mini_ring;
struct rx_desc *rx_return_ring;
-#if ACENIC_DO_VLAN
- struct vlan_group *vlgrp;
-#endif
-
int tasklet_pending, jumbo;
struct tasklet_struct ace_tasklet;
@@ -789,8 +786,5 @@ static void ace_free_descriptors(struct net_device *dev);
static void ace_init_cleanup(struct net_device *dev);
static struct net_device_stats *ace_get_stats(struct net_device *dev);
static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
-#if ACENIC_DO_VLAN
-static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp);
-#endif
#endif /* _ACENIC_H_ */
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 241b185e6569..78002ef9c0e5 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -75,6 +75,7 @@ Revision History:
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -660,15 +661,6 @@ static void amd8111e_free_ring(struct amd8111e_priv* lp)
}
}
-#if AMD8111E_VLAN_TAG_USED
-/*
-This is the receive indication function for packets with vlan tag.
-*/
-static int amd8111e_vlan_rx(struct amd8111e_priv *lp, struct sk_buff *skb, u16 vlan_tag)
-{
- return vlan_hwaccel_receive_skb(skb, lp->vlgrp,vlan_tag);
-}
-#endif
/*
This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb.
@@ -763,7 +755,7 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
#if AMD8111E_VLAN_TAG_USED
vtag = status & TT_MASK;
/*MAC will strip vlan tag*/
- if(lp->vlgrp != NULL && vtag !=0)
+ if (vtag != 0)
min_pkt_len =MIN_PKT_LEN - 4;
else
#endif
@@ -798,12 +790,12 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
skb->protocol = eth_type_trans(skb, dev);
#if AMD8111E_VLAN_TAG_USED
- if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){
- amd8111e_vlan_rx(lp, skb,
- le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info));
- } else
+ if (vtag == TT_VLAN_TAGGED){
+ u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info);
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
+ }
#endif
- netif_receive_skb(skb);
+ netif_receive_skb(skb);
/*COAL update rx coalescing parameters*/
lp->coal_conf.rx_packets++;
lp->coal_conf.rx_bytes += pkt_len;
@@ -1597,16 +1589,6 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
return err;
}
-#if AMD8111E_VLAN_TAG_USED
-static void amd8111e_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
- struct amd8111e_priv *lp = netdev_priv(dev);
- spin_lock_irq(&lp->lock);
- lp->vlgrp = grp;
- spin_unlock_irq(&lp->lock);
-}
-#endif
-
static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
{
writel( VAL1|MPPLBA, lp->mmio + CMD3);
@@ -1821,9 +1803,6 @@ static const struct net_device_ops amd8111e_netdev_ops = {
.ndo_set_mac_address = amd8111e_set_mac_address,
.ndo_do_ioctl = amd8111e_ioctl,
.ndo_change_mtu = amd8111e_change_mtu,
-#if AMD8111E_VLAN_TAG_USED
- .ndo_vlan_rx_register = amd8111e_vlan_rx_register,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = amd8111e_poll,
#endif
@@ -1958,7 +1937,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
IPG_CONVERGE_JIFFIES;
lp->ipg_data.ipg = DEFAULT_IPG;
lp->ipg_data.ipg_state = CSTATE;
- };
+ }
/* display driver and device information */
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index b5926af03a7e..2ff2e7a12dd0 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
@@ -783,9 +783,6 @@ struct amd8111e_priv{
struct net_device *next;
int mii;
struct mii_if_info mii_if;
-#if AMD8111E_VLAN_TAG_USED
- struct vlan_group *vlgrp;
-#endif
char opened;
unsigned int drv_rx_errors;
struct amd8111e_coalesce_conf coal_conf;
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index 2fe60f168108..547737340cbb 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <asm/system.h>
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index e69eead12ec7..34ffb5422628 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -652,9 +652,9 @@ static int do_write(struct net_device *dev, void *cbuf, int cbuflen,
int ret;
if(i) {
- qels[i].cbuf = (unsigned char *) cbuf;
+ qels[i].cbuf = cbuf;
qels[i].cbuflen = cbuflen;
- qels[i].dbuf = (unsigned char *) dbuf;
+ qels[i].dbuf = dbuf;
qels[i].dbuflen = dbuflen;
qels[i].QWrite = 1;
qels[i].mailbox = i; /* this should be initted rather */
@@ -676,9 +676,9 @@ static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
int ret;
if(i) {
- qels[i].cbuf = (unsigned char *) cbuf;
+ qels[i].cbuf = cbuf;
qels[i].cbuflen = cbuflen;
- qels[i].dbuf = (unsigned char *) dbuf;
+ qels[i].dbuf = dbuf;
qels[i].dbuflen = dbuflen;
qels[i].QWrite = 0;
qels[i].mailbox = i; /* this should be initted rather */
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 9efbbbae47ca..25197b698dd6 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -32,6 +32,7 @@
#include <linux/netdevice.h>
#include <linux/bootmem.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/arcdevice.h>
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 37272827ee55..45c61a2c5fbd 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -34,6 +34,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bootmem.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 48a1dbf01e60..d427493997b6 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -34,6 +34,7 @@
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index c9e459400ff9..7bfb91f32857 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index eb27976dab37..487d780ebbdf 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -33,6 +33,7 @@
#include <linux/netdevice.h>
#include <linux/bootmem.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/arcdevice.h>
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index f3b46f71e293..b80fbe40aa0e 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index b7f45cd756a2..7ed78f402042 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -34,6 +34,9 @@
* - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+/*#define DEBUG*/
+
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
@@ -54,802 +57,734 @@
#include "ariadne.h"
-
#ifdef ARIADNE_DEBUG
int ariadne_debug = ARIADNE_DEBUG;
#else
int ariadne_debug = 1;
#endif
+/* Macros to Fix Endianness problems */
- /*
- * Macros to Fix Endianness problems
- */
-
- /* Swap the Bytes in a WORD */
-#define swapw(x) (((x>>8)&0x00ff)|((x<<8)&0xff00))
- /* Get the Low BYTE in a WORD */
-#define lowb(x) (x&0xff)
- /* Get the Swapped High WORD in a LONG */
-#define swhighw(x) ((((x)>>8)&0xff00)|(((x)>>24)&0x00ff))
- /* Get the Swapped Low WORD in a LONG */
-#define swloww(x) ((((x)<<8)&0xff00)|(((x)>>8)&0x00ff))
+/* Swap the Bytes in a WORD */
+#define swapw(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
+/* Get the Low BYTE in a WORD */
+#define lowb(x) (x & 0xff)
+/* Get the Swapped High WORD in a LONG */
+#define swhighw(x) ((((x) >> 8) & 0xff00) | (((x) >> 24) & 0x00ff))
+/* Get the Swapped Low WORD in a LONG */
+#define swloww(x) ((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))
-
- /*
- * Transmit/Receive Ring Definitions
- */
+/* Transmit/Receive Ring Definitions */
#define TX_RING_SIZE 5
#define RX_RING_SIZE 16
#define PKT_BUF_SIZE 1520
-
- /*
- * Private Device Data
- */
+/* Private Device Data */
struct ariadne_private {
- volatile struct TDRE *tx_ring[TX_RING_SIZE];
- volatile struct RDRE *rx_ring[RX_RING_SIZE];
- volatile u_short *tx_buff[TX_RING_SIZE];
- volatile u_short *rx_buff[RX_RING_SIZE];
- int cur_tx, cur_rx; /* The next free ring entry */
- int dirty_tx; /* The ring entries to be free()ed. */
- char tx_full;
+ volatile struct TDRE *tx_ring[TX_RING_SIZE];
+ volatile struct RDRE *rx_ring[RX_RING_SIZE];
+ volatile u_short *tx_buff[TX_RING_SIZE];
+ volatile u_short *rx_buff[RX_RING_SIZE];
+ int cur_tx, cur_rx; /* The next free ring entry */
+ int dirty_tx; /* The ring entries to be free()ed */
+ char tx_full;
};
-
- /*
- * Structure Created in the Ariadne's RAM Buffer
- */
+/* Structure Created in the Ariadne's RAM Buffer */
struct lancedata {
- struct TDRE tx_ring[TX_RING_SIZE];
- struct RDRE rx_ring[RX_RING_SIZE];
- u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
- u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
+ struct TDRE tx_ring[TX_RING_SIZE];
+ struct RDRE rx_ring[RX_RING_SIZE];
+ u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
+ u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
};
-static int ariadne_open(struct net_device *dev);
-static void ariadne_init_ring(struct net_device *dev);
-static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
- struct net_device *dev);
-static void ariadne_tx_timeout(struct net_device *dev);
-static int ariadne_rx(struct net_device *dev);
-static void ariadne_reset(struct net_device *dev);
-static irqreturn_t ariadne_interrupt(int irq, void *data);
-static int ariadne_close(struct net_device *dev);
-static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-
static void memcpyw(volatile u_short *dest, u_short *src, int len)
{
- while (len >= 2) {
- *(dest++) = *(src++);
- len -= 2;
- }
- if (len == 1)
- *dest = (*(u_char *)src)<<8;
+ while (len >= 2) {
+ *(dest++) = *(src++);
+ len -= 2;
+ }
+ if (len == 1)
+ *dest = (*(u_char *)src) << 8;
}
+static void ariadne_init_ring(struct net_device *dev)
+{
+ struct ariadne_private *priv = netdev_priv(dev);
+ volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
+ int i;
-static int __devinit ariadne_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent);
-static void __devexit ariadne_remove_one(struct zorro_dev *z);
-
-
-static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
- { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
+ netif_stop_queue(dev);
-static struct zorro_driver ariadne_driver = {
- .name = "ariadne",
- .id_table = ariadne_zorro_tbl,
- .probe = ariadne_init_one,
- .remove = __devexit_p(ariadne_remove_one),
-};
+ priv->tx_full = 0;
+ priv->cur_rx = priv->cur_tx = 0;
+ priv->dirty_tx = 0;
+
+ /* Set up TX Ring */
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ volatile struct TDRE *t = &lancedata->tx_ring[i];
+ t->TMD0 = swloww(ARIADNE_RAM +
+ offsetof(struct lancedata, tx_buff[i]));
+ t->TMD1 = swhighw(ARIADNE_RAM +
+ offsetof(struct lancedata, tx_buff[i])) |
+ TF_STP | TF_ENP;
+ t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
+ t->TMD3 = 0;
+ priv->tx_ring[i] = &lancedata->tx_ring[i];
+ priv->tx_buff[i] = lancedata->tx_buff[i];
+ netdev_dbg(dev, "TX Entry %2d at %p, Buf at %p\n",
+ i, &lancedata->tx_ring[i], lancedata->tx_buff[i]);
+ }
-static const struct net_device_ops ariadne_netdev_ops = {
- .ndo_open = ariadne_open,
- .ndo_stop = ariadne_close,
- .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_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
-};
+ /* Set up RX Ring */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ volatile struct RDRE *r = &lancedata->rx_ring[i];
+ r->RMD0 = swloww(ARIADNE_RAM +
+ offsetof(struct lancedata, rx_buff[i]));
+ r->RMD1 = swhighw(ARIADNE_RAM +
+ offsetof(struct lancedata, rx_buff[i])) |
+ RF_OWN;
+ r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
+ r->RMD3 = 0x0000;
+ priv->rx_ring[i] = &lancedata->rx_ring[i];
+ priv->rx_buff[i] = lancedata->rx_buff[i];
+ netdev_dbg(dev, "RX Entry %2d at %p, Buf at %p\n",
+ i, &lancedata->rx_ring[i], lancedata->rx_buff[i]);
+ }
+}
-static int __devinit ariadne_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int ariadne_rx(struct net_device *dev)
{
- unsigned long board = z->resource.start;
- unsigned long base_addr = board+ARIADNE_LANCE;
- unsigned long mem_start = board+ARIADNE_RAM;
- struct resource *r1, *r2;
- struct net_device *dev;
- struct ariadne_private *priv;
- int err;
-
- r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
- if (!r1)
- return -EBUSY;
- r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
- if (!r2) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- return -EBUSY;
- }
-
- dev = alloc_etherdev(sizeof(struct ariadne_private));
- if (dev == NULL) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- release_mem_region(mem_start, ARIADNE_RAM_SIZE);
- return -ENOMEM;
- }
-
- priv = netdev_priv(dev);
-
- r1->name = dev->name;
- r2->name = dev->name;
-
- dev->dev_addr[0] = 0x00;
- dev->dev_addr[1] = 0x60;
- dev->dev_addr[2] = 0x30;
- dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
- dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
- dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
- dev->base_addr = ZTWO_VADDR(base_addr);
- dev->mem_start = ZTWO_VADDR(mem_start);
- dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
-
- dev->netdev_ops = &ariadne_netdev_ops;
- dev->watchdog_timeo = 5*HZ;
-
- err = register_netdev(dev);
- if (err) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- release_mem_region(mem_start, ARIADNE_RAM_SIZE);
- free_netdev(dev);
- return err;
- }
- zorro_set_drvdata(z, dev);
+ struct ariadne_private *priv = netdev_priv(dev);
+ int entry = priv->cur_rx % RX_RING_SIZE;
+ int i;
- printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n",
- dev->name, board, dev->dev_addr);
+ /* If we own the next entry, it's a new packet. Send it up */
+ while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
+ int status = lowb(priv->rx_ring[entry]->RMD1);
+
+ if (status != (RF_STP | RF_ENP)) { /* There was an error */
+ /* There is a tricky error noted by
+ * John Murphy <murf@perftech.com> to Russ Nelson:
+ * Even with full-sized buffers it's possible for a
+ * jabber packet to use two buffers, with only the
+ * last correctly noting the error
+ */
+ /* Only count a general error at the end of a packet */
+ if (status & RF_ENP)
+ dev->stats.rx_errors++;
+ if (status & RF_FRAM)
+ dev->stats.rx_frame_errors++;
+ if (status & RF_OFLO)
+ dev->stats.rx_over_errors++;
+ if (status & RF_CRC)
+ dev->stats.rx_crc_errors++;
+ if (status & RF_BUFF)
+ dev->stats.rx_fifo_errors++;
+ priv->rx_ring[entry]->RMD1 &= 0xff00 | RF_STP | RF_ENP;
+ } else {
+ /* Malloc up new buffer, compatible with net-3 */
+ short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_len + 2);
+ if (skb == NULL) {
+ netdev_warn(dev, "Memory squeeze, deferring packet\n");
+ for (i = 0; i < RX_RING_SIZE; i++)
+ if (lowb(priv->rx_ring[(entry + i) % RX_RING_SIZE]->RMD1) & RF_OWN)
+ break;
+
+ if (i > RX_RING_SIZE - 2) {
+ dev->stats.rx_dropped++;
+ priv->rx_ring[entry]->RMD1 |= RF_OWN;
+ priv->cur_rx++;
+ }
+ break;
+ }
+
+
+ skb_reserve(skb, 2); /* 16 byte align */
+ skb_put(skb, pkt_len); /* Make room */
+ skb_copy_to_linear_data(skb,
+ (const void *)priv->rx_buff[entry],
+ pkt_len);
+ skb->protocol = eth_type_trans(skb, dev);
+ netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ ((u_short *)skb->data)[6],
+ skb->data + 6, skb->data,
+ (int)skb->data, (int)skb->len);
+
+ netif_rx(skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
+ }
- return 0;
-}
+ priv->rx_ring[entry]->RMD1 |= RF_OWN;
+ entry = (++priv->cur_rx) % RX_RING_SIZE;
+ }
+ priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
-static int ariadne_open(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- u_short in;
- u_long version;
- int i;
-
- /* Reset the LANCE */
- in = lance->Reset;
-
- /* Stop the LANCE */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = STOP;
-
- /* Check the LANCE version */
- lance->RAP = CSR88; /* Chip ID */
- version = swapw(lance->RDP);
- lance->RAP = CSR89; /* Chip ID */
- version |= swapw(lance->RDP)<<16;
- if ((version & 0x00000fff) != 0x00000003) {
- printk(KERN_WARNING "ariadne_open: Couldn't find AMD Ethernet Chip\n");
- return -EAGAIN;
- }
- if ((version & 0x0ffff000) != 0x00003000) {
- printk(KERN_WARNING "ariadne_open: Couldn't find Am79C960 (Wrong part "
- "number = %ld)\n", (version & 0x0ffff000)>>12);
- return -EAGAIN;
- }
-#if 0
- printk(KERN_DEBUG "ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n",
- (version & 0xf0000000)>>28);
-#endif
+ /* We should check that at least two ring entries are free.
+ * If not, we should free one and mark stats->rx_dropped++
+ */
- ariadne_init_ring(dev);
-
- /* Miscellaneous Stuff */
- lance->RAP = CSR3; /* Interrupt Masks and Deferral Control */
- lance->RDP = 0x0000;
- lance->RAP = CSR4; /* Test and Features Control */
- lance->RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM;
-
- /* Set the Multicast Table */
- lance->RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */
- lance->RDP = 0x0000;
- lance->RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */
- lance->RDP = 0x0000;
- lance->RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */
- lance->RDP = 0x0000;
- lance->RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */
- lance->RDP = 0x0000;
-
- /* Set the Ethernet Hardware Address */
- lance->RAP = CSR12; /* Physical Address Register, PADR[15:0] */
- lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
- lance->RAP = CSR13; /* Physical Address Register, PADR[31:16] */
- lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
- lance->RAP = CSR14; /* Physical Address Register, PADR[47:32] */
- lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
-
- /* Set the Init Block Mode */
- lance->RAP = CSR15; /* Mode Register */
- lance->RDP = 0x0000;
-
- /* Set the Transmit Descriptor Ring Pointer */
- lance->RAP = CSR30; /* Base Address of Transmit Ring */
- lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
- lance->RAP = CSR31; /* Base Address of transmit Ring */
- lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
-
- /* Set the Receive Descriptor Ring Pointer */
- lance->RAP = CSR24; /* Base Address of Receive Ring */
- lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
- lance->RAP = CSR25; /* Base Address of Receive Ring */
- lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
-
- /* Set the Number of RX and TX Ring Entries */
- lance->RAP = CSR76; /* Receive Ring Length */
- lance->RDP = swapw(((u_short)-RX_RING_SIZE));
- lance->RAP = CSR78; /* Transmit Ring Length */
- lance->RDP = swapw(((u_short)-TX_RING_SIZE));
-
- /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
- lance->RAP = ISACSR2; /* Miscellaneous Configuration */
- lance->IDP = ASEL;
-
- /* LED Control */
- lance->RAP = ISACSR5; /* LED1 Status */
- lance->IDP = PSE|XMTE;
- lance->RAP = ISACSR6; /* LED2 Status */
- lance->IDP = PSE|COLE;
- lance->RAP = ISACSR7; /* LED3 Status */
- lance->IDP = PSE|RCVE;
-
- netif_start_queue(dev);
-
- i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
- dev->name, dev);
- if (i) return i;
-
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|STRT;
-
- return 0;
+ return 0;
}
-
-static void ariadne_init_ring(struct net_device *dev)
+static irqreturn_t ariadne_interrupt(int irq, void *data)
{
- struct ariadne_private *priv = netdev_priv(dev);
- volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
- int i;
-
- netif_stop_queue(dev);
-
- priv->tx_full = 0;
- priv->cur_rx = priv->cur_tx = 0;
- priv->dirty_tx = 0;
-
- /* Set up TX Ring */
- for (i = 0; i < TX_RING_SIZE; i++) {
- volatile struct TDRE *t = &lancedata->tx_ring[i];
- t->TMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i]));
- t->TMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i])) |
- TF_STP | TF_ENP;
- t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
- t->TMD3 = 0;
- priv->tx_ring[i] = &lancedata->tx_ring[i];
- priv->tx_buff[i] = lancedata->tx_buff[i];
-#if 0
- printk(KERN_DEBUG "TX Entry %2d at %p, Buf at %p\n", i,
- &lancedata->tx_ring[i], lancedata->tx_buff[i]);
-#endif
- }
-
- /* Set up RX Ring */
- for (i = 0; i < RX_RING_SIZE; i++) {
- volatile struct RDRE *r = &lancedata->rx_ring[i];
- r->RMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i]));
- r->RMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i])) |
- RF_OWN;
- r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
- r->RMD3 = 0x0000;
- priv->rx_ring[i] = &lancedata->rx_ring[i];
- priv->rx_buff[i] = lancedata->rx_buff[i];
-#if 0
- printk(KERN_DEBUG "RX Entry %2d at %p, Buf at %p\n", i,
- &lancedata->rx_ring[i], lancedata->rx_buff[i]);
+ struct net_device *dev = (struct net_device *)data;
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ struct ariadne_private *priv;
+ int csr0, boguscnt;
+ int handled = 0;
+
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+
+ if (!(lance->RDP & INTR)) /* Check if any interrupt has been */
+ return IRQ_NONE; /* generated by the board */
+
+ priv = netdev_priv(dev);
+
+ boguscnt = 10;
+ while ((csr0 = lance->RDP) & (ERR | RINT | TINT) && --boguscnt >= 0) {
+ /* Acknowledge all of the current interrupt sources ASAP */
+ lance->RDP = csr0 & ~(INEA | TDMD | STOP | STRT | INIT);
+
+#ifdef DEBUG
+ if (ariadne_debug > 5) {
+ netdev_dbg(dev, "interrupt csr0=%#02x new csr=%#02x [",
+ csr0, lance->RDP);
+ if (csr0 & INTR)
+ pr_cont(" INTR");
+ if (csr0 & INEA)
+ pr_cont(" INEA");
+ if (csr0 & RXON)
+ pr_cont(" RXON");
+ if (csr0 & TXON)
+ pr_cont(" TXON");
+ if (csr0 & TDMD)
+ pr_cont(" TDMD");
+ if (csr0 & STOP)
+ pr_cont(" STOP");
+ if (csr0 & STRT)
+ pr_cont(" STRT");
+ if (csr0 & INIT)
+ pr_cont(" INIT");
+ if (csr0 & ERR)
+ pr_cont(" ERR");
+ if (csr0 & BABL)
+ pr_cont(" BABL");
+ if (csr0 & CERR)
+ pr_cont(" CERR");
+ if (csr0 & MISS)
+ pr_cont(" MISS");
+ if (csr0 & MERR)
+ pr_cont(" MERR");
+ if (csr0 & RINT)
+ pr_cont(" RINT");
+ if (csr0 & TINT)
+ pr_cont(" TINT");
+ if (csr0 & IDON)
+ pr_cont(" IDON");
+ pr_cont(" ]\n");
+ }
#endif
- }
-}
+ if (csr0 & RINT) { /* Rx interrupt */
+ handled = 1;
+ ariadne_rx(dev);
+ }
-static int ariadne_close(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
+ if (csr0 & TINT) { /* Tx-done interrupt */
+ int dirty_tx = priv->dirty_tx;
+
+ handled = 1;
+ while (dirty_tx < priv->cur_tx) {
+ int entry = dirty_tx % TX_RING_SIZE;
+ int status = lowb(priv->tx_ring[entry]->TMD1);
+
+ if (status & TF_OWN)
+ break; /* It still hasn't been Txed */
+
+ priv->tx_ring[entry]->TMD1 &= 0xff00;
+
+ if (status & TF_ERR) {
+ /* There was an major error, log it */
+ int err_status = priv->tx_ring[entry]->TMD3;
+ dev->stats.tx_errors++;
+ if (err_status & EF_RTRY)
+ dev->stats.tx_aborted_errors++;
+ if (err_status & EF_LCAR)
+ dev->stats.tx_carrier_errors++;
+ if (err_status & EF_LCOL)
+ dev->stats.tx_window_errors++;
+ if (err_status & EF_UFLO) {
+ /* Ackk! On FIFO errors the Tx unit is turned off! */
+ dev->stats.tx_fifo_errors++;
+ /* Remove this verbosity later! */
+ netdev_err(dev, "Tx FIFO error! Status %04x\n",
+ csr0);
+ /* Restart the chip */
+ lance->RDP = STRT;
+ }
+ } else {
+ if (status & (TF_MORE | TF_ONE))
+ dev->stats.collisions++;
+ dev->stats.tx_packets++;
+ }
+ dirty_tx++;
+ }
- netif_stop_queue(dev);
+#ifndef final_version
+ if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
+ netdev_err(dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n",
+ dirty_tx, priv->cur_tx,
+ priv->tx_full);
+ dirty_tx += TX_RING_SIZE;
+ }
+#endif
- lance->RAP = CSR112; /* Missed Frame Count */
- dev->stats.rx_missed_errors = swapw(lance->RDP);
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ if (priv->tx_full && netif_queue_stopped(dev) &&
+ dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
+ /* The ring is no longer full */
+ priv->tx_full = 0;
+ netif_wake_queue(dev);
+ }
- if (ariadne_debug > 1) {
- printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
- dev->name, lance->RDP);
- printk(KERN_DEBUG "%s: %lu packets missed\n", dev->name,
- dev->stats.rx_missed_errors);
- }
+ priv->dirty_tx = dirty_tx;
+ }
- /* We stop the LANCE here -- it occasionally polls memory if we don't. */
- lance->RDP = STOP;
+ /* Log misc errors */
+ if (csr0 & BABL) {
+ handled = 1;
+ dev->stats.tx_errors++; /* Tx babble */
+ }
+ if (csr0 & MISS) {
+ handled = 1;
+ dev->stats.rx_errors++; /* Missed a Rx frame */
+ }
+ if (csr0 & MERR) {
+ handled = 1;
+ netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+ csr0);
+ /* Restart the chip */
+ lance->RDP = STRT;
+ }
+ }
- free_irq(IRQ_AMIGA_PORTS, dev);
+ /* Clear any other interrupt, and set interrupt enable */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | BABL | CERR | MISS | MERR | IDON;
- return 0;
-}
+ if (ariadne_debug > 4)
+ netdev_dbg(dev, "exiting interrupt, csr%d=%#04x\n",
+ lance->RAP, lance->RDP);
+ return IRQ_RETVAL(handled);
+}
-static inline void ariadne_reset(struct net_device *dev)
+static int ariadne_open(struct net_device *dev)
{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = STOP;
- ariadne_init_ring(dev);
- lance->RDP = INEA|STRT;
- netif_start_queue(dev);
-}
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ u_short in;
+ u_long version;
+ int i;
+ /* Reset the LANCE */
+ in = lance->Reset;
+
+ /* Stop the LANCE */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = STOP;
+
+ /* Check the LANCE version */
+ lance->RAP = CSR88; /* Chip ID */
+ version = swapw(lance->RDP);
+ lance->RAP = CSR89; /* Chip ID */
+ version |= swapw(lance->RDP) << 16;
+ if ((version & 0x00000fff) != 0x00000003) {
+ pr_warn("Couldn't find AMD Ethernet Chip\n");
+ return -EAGAIN;
+ }
+ if ((version & 0x0ffff000) != 0x00003000) {
+ pr_warn("Couldn't find Am79C960 (Wrong part number = %ld)\n",
+ (version & 0x0ffff000) >> 12);
+ return -EAGAIN;
+ }
-static irqreturn_t ariadne_interrupt(int irq, void *data)
-{
- struct net_device *dev = (struct net_device *)data;
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- struct ariadne_private *priv;
- int csr0, boguscnt;
- int handled = 0;
+ netdev_dbg(dev, "Am79C960 (PCnet-ISA) Revision %ld\n",
+ (version & 0xf0000000) >> 28);
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ ariadne_init_ring(dev);
- if (!(lance->RDP & INTR)) /* Check if any interrupt has been */
- return IRQ_NONE; /* generated by the board. */
+ /* Miscellaneous Stuff */
+ lance->RAP = CSR3; /* Interrupt Masks and Deferral Control */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR4; /* Test and Features Control */
+ lance->RDP = DPOLL | APAD_XMT | MFCOM | RCVCCOM | TXSTRTM | JABM;
- priv = netdev_priv(dev);
+ /* Set the Multicast Table */
+ lance->RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */
+ lance->RDP = 0x0000;
- boguscnt = 10;
- while ((csr0 = lance->RDP) & (ERR|RINT|TINT) && --boguscnt >= 0) {
- /* Acknowledge all of the current interrupt sources ASAP. */
- lance->RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
+ /* Set the Ethernet Hardware Address */
+ lance->RAP = CSR12; /* Physical Address Register, PADR[15:0] */
+ lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
+ lance->RAP = CSR13; /* Physical Address Register, PADR[31:16] */
+ lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
+ lance->RAP = CSR14; /* Physical Address Register, PADR[47:32] */
+ lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
-#if 0
- if (ariadne_debug > 5) {
- printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.",
- dev->name, csr0, lance->RDP);
- printk("[");
- if (csr0 & INTR)
- printk(" INTR");
- if (csr0 & INEA)
- printk(" INEA");
- if (csr0 & RXON)
- printk(" RXON");
- if (csr0 & TXON)
- printk(" TXON");
- if (csr0 & TDMD)
- printk(" TDMD");
- if (csr0 & STOP)
- printk(" STOP");
- if (csr0 & STRT)
- printk(" STRT");
- if (csr0 & INIT)
- printk(" INIT");
- if (csr0 & ERR)
- printk(" ERR");
- if (csr0 & BABL)
- printk(" BABL");
- if (csr0 & CERR)
- printk(" CERR");
- if (csr0 & MISS)
- printk(" MISS");
- if (csr0 & MERR)
- printk(" MERR");
- if (csr0 & RINT)
- printk(" RINT");
- if (csr0 & TINT)
- printk(" TINT");
- if (csr0 & IDON)
- printk(" IDON");
- printk(" ]\n");
- }
-#endif
+ /* Set the Init Block Mode */
+ lance->RAP = CSR15; /* Mode Register */
+ lance->RDP = 0x0000;
- if (csr0 & RINT) { /* Rx interrupt */
- handled = 1;
- ariadne_rx(dev);
- }
+ /* Set the Transmit Descriptor Ring Pointer */
+ lance->RAP = CSR30; /* Base Address of Transmit Ring */
+ lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+ lance->RAP = CSR31; /* Base Address of transmit Ring */
+ lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+
+ /* Set the Receive Descriptor Ring Pointer */
+ lance->RAP = CSR24; /* Base Address of Receive Ring */
+ lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+ lance->RAP = CSR25; /* Base Address of Receive Ring */
+ lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+
+ /* Set the Number of RX and TX Ring Entries */
+ lance->RAP = CSR76; /* Receive Ring Length */
+ lance->RDP = swapw(((u_short)-RX_RING_SIZE));
+ lance->RAP = CSR78; /* Transmit Ring Length */
+ lance->RDP = swapw(((u_short)-TX_RING_SIZE));
+
+ /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
+ lance->RAP = ISACSR2; /* Miscellaneous Configuration */
+ lance->IDP = ASEL;
+
+ /* LED Control */
+ lance->RAP = ISACSR5; /* LED1 Status */
+ lance->IDP = PSE|XMTE;
+ lance->RAP = ISACSR6; /* LED2 Status */
+ lance->IDP = PSE|COLE;
+ lance->RAP = ISACSR7; /* LED3 Status */
+ lance->IDP = PSE|RCVE;
+
+ netif_start_queue(dev);
+
+ i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (i)
+ return i;
+
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | STRT;
+
+ return 0;
+}
- if (csr0 & TINT) { /* Tx-done interrupt */
- int dirty_tx = priv->dirty_tx;
-
- handled = 1;
- while (dirty_tx < priv->cur_tx) {
- int entry = dirty_tx % TX_RING_SIZE;
- int status = lowb(priv->tx_ring[entry]->TMD1);
-
- if (status & TF_OWN)
- break; /* It still hasn't been Txed */
-
- priv->tx_ring[entry]->TMD1 &= 0xff00;
-
- if (status & TF_ERR) {
- /* There was an major error, log it. */
- int err_status = priv->tx_ring[entry]->TMD3;
- dev->stats.tx_errors++;
- if (err_status & EF_RTRY)
- dev->stats.tx_aborted_errors++;
- if (err_status & EF_LCAR)
- dev->stats.tx_carrier_errors++;
- if (err_status & EF_LCOL)
- dev->stats.tx_window_errors++;
- if (err_status & EF_UFLO) {
- /* Ackk! On FIFO errors the Tx unit is turned off! */
- dev->stats.tx_fifo_errors++;
- /* Remove this verbosity later! */
- printk(KERN_ERR "%s: Tx FIFO error! Status %4.4x.\n",
- dev->name, csr0);
- /* Restart the chip. */
- lance->RDP = STRT;
- }
- } else {
- if (status & (TF_MORE|TF_ONE))
- dev->stats.collisions++;
- dev->stats.tx_packets++;
- }
- dirty_tx++;
- }
+static int ariadne_close(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-#ifndef final_version
- if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
- printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d, "
- "full=%d.\n", dirty_tx, priv->cur_tx, priv->tx_full);
- dirty_tx += TX_RING_SIZE;
- }
-#endif
+ netif_stop_queue(dev);
- if (priv->tx_full && netif_queue_stopped(dev) &&
- dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
- /* The ring is no longer full. */
- priv->tx_full = 0;
- netif_wake_queue(dev);
- }
+ lance->RAP = CSR112; /* Missed Frame Count */
+ dev->stats.rx_missed_errors = swapw(lance->RDP);
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- priv->dirty_tx = dirty_tx;
+ if (ariadne_debug > 1) {
+ netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
+ lance->RDP);
+ netdev_dbg(dev, "%lu packets missed\n",
+ dev->stats.rx_missed_errors);
}
- /* Log misc errors. */
- if (csr0 & BABL) {
- handled = 1;
- dev->stats.tx_errors++; /* Tx babble. */
- }
- if (csr0 & MISS) {
- handled = 1;
- dev->stats.rx_errors++; /* Missed a Rx frame. */
- }
- if (csr0 & MERR) {
- handled = 1;
- printk(KERN_ERR "%s: Bus master arbitration failure, status "
- "%4.4x.\n", dev->name, csr0);
- /* Restart the chip. */
- lance->RDP = STRT;
- }
- }
+ /* We stop the LANCE here -- it occasionally polls memory if we don't */
+ lance->RDP = STOP;
- /* Clear any other interrupt, and set interrupt enable. */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|BABL|CERR|MISS|MERR|IDON;
+ free_irq(IRQ_AMIGA_PORTS, dev);
-#if 0
- if (ariadne_debug > 4)
- printk(KERN_DEBUG "%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name,
- lance->RAP, lance->RDP);
-#endif
- return IRQ_RETVAL(handled);
+ return 0;
}
+static inline void ariadne_reset(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = STOP;
+ ariadne_init_ring(dev);
+ lance->RDP = INEA | STRT;
+ netif_start_queue(dev);
+}
static void ariadne_tx_timeout(struct net_device *dev)
{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
- printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n",
- dev->name, lance->RDP);
- ariadne_reset(dev);
- netif_wake_queue(dev);
+ netdev_err(dev, "transmit timed out, status %04x, resetting\n",
+ lance->RDP);
+ ariadne_reset(dev);
+ netif_wake_queue(dev);
}
-
static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct ariadne_private *priv = netdev_priv(dev);
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- int entry;
- unsigned long flags;
- int len = skb->len;
-
-#if 0
- if (ariadne_debug > 3) {
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- printk(KERN_DEBUG "%s: ariadne_start_xmit() called, csr0 %4.4x.\n",
- dev->name, lance->RDP);
- lance->RDP = 0x0000;
- }
-#endif
-
- /* FIXME: is the 79C960 new enough to do its own padding right ? */
- if (skb->len < ETH_ZLEN)
- {
- if (skb_padto(skb, ETH_ZLEN))
- return NETDEV_TX_OK;
- len = ETH_ZLEN;
- }
-
- /* Fill in a Tx ring entry */
+ struct ariadne_private *priv = netdev_priv(dev);
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ int entry;
+ unsigned long flags;
+ int len = skb->len;
#if 0
-{
- printk(KERN_DEBUG "TX pkt type 0x%04x from %pM to %pM "
- " data 0x%08x len %d\n",
- ((u_short *)skb->data)[6],
- skb->data + 6, skb->data,
- (int)skb->data, (int)skb->len);
-}
+ if (ariadne_debug > 3) {
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ netdev_dbg(dev, "%s: csr0 %04x\n", __func__, lance->RDP);
+ lance->RDP = 0x0000;
+ }
#endif
- local_irq_save(flags);
-
- entry = priv->cur_tx % TX_RING_SIZE;
-
- /* Caution: the write order is important here, set the base address with
- the "ownership" bits last. */
-
- priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
- priv->tx_ring[entry]->TMD3 = 0x0000;
- memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
-
-#if 0
- {
- int i, len;
-
- len = skb->len > 64 ? 64 : skb->len;
- len >>= 1;
- for (i = 0; i < len; i += 8) {
- int j;
- printk(KERN_DEBUG "%04x:", i);
- for (j = 0; (j < 8) && ((i+j) < len); j++) {
- if (!(j & 1))
- printk(" ");
- printk("%04x", priv->tx_buff[entry][i+j]);
- }
- printk("\n");
+ /* FIXME: is the 79C960 new enough to do its own padding right ? */
+ if (skb->len < ETH_ZLEN) {
+ if (skb_padto(skb, ETH_ZLEN))
+ return NETDEV_TX_OK;
+ len = ETH_ZLEN;
}
- }
-#endif
- priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP;
+ /* Fill in a Tx ring entry */
- dev_kfree_skb(skb);
+ netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ ((u_short *)skb->data)[6],
+ skb->data + 6, skb->data,
+ (int)skb->data, (int)skb->len);
- priv->cur_tx++;
- if ((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) {
+ local_irq_save(flags);
-#if 0
- printk(KERN_DEBUG "*** Subtracting TX_RING_SIZE from cur_tx (%d) and "
- "dirty_tx (%d)\n", priv->cur_tx, priv->dirty_tx);
-#endif
+ entry = priv->cur_tx % TX_RING_SIZE;
- priv->cur_tx -= TX_RING_SIZE;
- priv->dirty_tx -= TX_RING_SIZE;
- }
- dev->stats.tx_bytes += len;
+ /* Caution: the write order is important here, set the base address with
+ the "ownership" bits last */
- /* Trigger an immediate send poll. */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|TDMD;
+ priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
+ priv->tx_ring[entry]->TMD3 = 0x0000;
+ memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
- if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) != 0) {
- netif_stop_queue(dev);
- priv->tx_full = 1;
- }
- local_irq_restore(flags);
+#ifdef DEBUG
+ print_hex_dump(KERN_DEBUG, "tx_buff: ", DUMP_PREFIX_OFFSET, 16, 1,
+ (void *)priv->tx_buff[entry],
+ skb->len > 64 ? 64 : skb->len, true);
+#endif
- return NETDEV_TX_OK;
-}
+ priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 & 0xff00)
+ | TF_OWN | TF_STP | TF_ENP;
+ dev_kfree_skb(skb);
-static int ariadne_rx(struct net_device *dev)
-{
- struct ariadne_private *priv = netdev_priv(dev);
- int entry = priv->cur_rx % RX_RING_SIZE;
- int i;
-
- /* If we own the next entry, it's a new packet. Send it up. */
- while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
- int status = lowb(priv->rx_ring[entry]->RMD1);
-
- if (status != (RF_STP|RF_ENP)) { /* There was an error. */
- /* There is a tricky error noted by John Murphy,
- <murf@perftech.com> to Russ Nelson: Even with full-sized
- buffers it's possible for a jabber packet to use two
- buffers, with only the last correctly noting the error. */
- if (status & RF_ENP)
- /* Only count a general error at the end of a packet.*/
- dev->stats.rx_errors++;
- if (status & RF_FRAM)
- dev->stats.rx_frame_errors++;
- if (status & RF_OFLO)
- dev->stats.rx_over_errors++;
- if (status & RF_CRC)
- dev->stats.rx_crc_errors++;
- if (status & RF_BUFF)
- dev->stats.rx_fifo_errors++;
- priv->rx_ring[entry]->RMD1 &= 0xff00|RF_STP|RF_ENP;
- } else {
- /* Malloc up new buffer, compatible with net-3. */
- short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(pkt_len+2);
- if (skb == NULL) {
- printk(KERN_WARNING "%s: Memory squeeze, deferring packet.\n",
- dev->name);
- for (i = 0; i < RX_RING_SIZE; i++)
- if (lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN)
- break;
-
- if (i > RX_RING_SIZE-2) {
- dev->stats.rx_dropped++;
- priv->rx_ring[entry]->RMD1 |= RF_OWN;
- priv->cur_rx++;
- }
- break;
- }
+ priv->cur_tx++;
+ if ((priv->cur_tx >= TX_RING_SIZE) &&
+ (priv->dirty_tx >= TX_RING_SIZE)) {
+ netdev_dbg(dev, "*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
+ priv->cur_tx, priv->dirty_tx);
- skb_reserve(skb,2); /* 16 byte align */
- skb_put(skb,pkt_len); /* Make room */
- skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
- skb->protocol=eth_type_trans(skb,dev);
-#if 0
-{
- printk(KERN_DEBUG "RX pkt type 0x%04x from ",
- ((u_short *)skb->data)[6]);
- {
- u_char *ptr = &((u_char *)skb->data)[6];
- printk("%pM", ptr);
- }
- printk(" to ");
- {
- u_char *ptr = (u_char *)skb->data;
- printk("%pM", ptr);
- }
- printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
-}
-#endif
-
- netif_rx(skb);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += pkt_len;
+ priv->cur_tx -= TX_RING_SIZE;
+ priv->dirty_tx -= TX_RING_SIZE;
}
+ dev->stats.tx_bytes += len;
- priv->rx_ring[entry]->RMD1 |= RF_OWN;
- entry = (++priv->cur_rx) % RX_RING_SIZE;
- }
+ /* Trigger an immediate send poll */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | TDMD;
- priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
-
- /* We should check that at least two ring entries are free. If not,
- we should free one and mark stats->rx_dropped++. */
+ if (lowb(priv->tx_ring[(entry + 1) % TX_RING_SIZE]->TMD1) != 0) {
+ netif_stop_queue(dev);
+ priv->tx_full = 1;
+ }
+ local_irq_restore(flags);
- return 0;
+ return NETDEV_TX_OK;
}
-
static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- short saved_addr;
- unsigned long flags;
-
- local_irq_save(flags);
- saved_addr = lance->RAP;
- lance->RAP = CSR112; /* Missed Frame Count */
- dev->stats.rx_missed_errors = swapw(lance->RDP);
- lance->RAP = saved_addr;
- local_irq_restore(flags);
-
- return &dev->stats;
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ short saved_addr;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ saved_addr = lance->RAP;
+ lance->RAP = CSR112; /* Missed Frame Count */
+ dev->stats.rx_missed_errors = swapw(lance->RDP);
+ lance->RAP = saved_addr;
+ local_irq_restore(flags);
+
+ return &dev->stats;
}
-
/* Set or clear the multicast filter for this adaptor.
- num_addrs == -1 Promiscuous mode, receive all packets
- num_addrs == 0 Normal mode, clear multicast list
- num_addrs > 0 Multicast mode, receive normal and MC packets, and do
- best-effort filtering.
+ * num_addrs == -1 Promiscuous mode, receive all packets
+ * num_addrs == 0 Normal mode, clear multicast list
+ * num_addrs > 0 Multicast mode, receive normal and MC packets,
+ * and do best-effort filtering.
*/
static void set_multicast_list(struct net_device *dev)
{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
- if (!netif_running(dev))
- return;
+ if (!netif_running(dev))
+ return;
- netif_stop_queue(dev);
+ netif_stop_queue(dev);
- /* We take the simple way out and always enable promiscuous mode. */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = STOP; /* Temporarily stop the lance. */
- ariadne_init_ring(dev);
+ /* We take the simple way out and always enable promiscuous mode */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = STOP; /* Temporarily stop the lance */
+ ariadne_init_ring(dev);
- if (dev->flags & IFF_PROMISC) {
- lance->RAP = CSR15; /* Mode Register */
- lance->RDP = PROM; /* Set promiscuous mode */
- } else {
- short multicast_table[4];
- int num_addrs = netdev_mc_count(dev);
- int i;
- /* We don't use the multicast table, but rely on upper-layer filtering. */
- memset(multicast_table, (num_addrs == 0) ? 0 : -1,
- sizeof(multicast_table));
- for (i = 0; i < 4; i++) {
- lance->RAP = CSR8+(i<<8); /* Logical Address Filter */
- lance->RDP = swapw(multicast_table[i]);
+ if (dev->flags & IFF_PROMISC) {
+ lance->RAP = CSR15; /* Mode Register */
+ lance->RDP = PROM; /* Set promiscuous mode */
+ } else {
+ short multicast_table[4];
+ int num_addrs = netdev_mc_count(dev);
+ int i;
+ /* We don't use the multicast table,
+ * but rely on upper-layer filtering
+ */
+ memset(multicast_table, (num_addrs == 0) ? 0 : -1,
+ sizeof(multicast_table));
+ for (i = 0; i < 4; i++) {
+ lance->RAP = CSR8 + (i << 8);
+ /* Logical Address Filter */
+ lance->RDP = swapw(multicast_table[i]);
+ }
+ lance->RAP = CSR15; /* Mode Register */
+ lance->RDP = 0x0000; /* Unset promiscuous mode */
}
- lance->RAP = CSR15; /* Mode Register */
- lance->RDP = 0x0000; /* Unset promiscuous mode */
- }
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|STRT|IDON; /* Resume normal operation. */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | STRT | IDON;/* Resume normal operation */
- netif_wake_queue(dev);
+ netif_wake_queue(dev);
}
static void __devexit ariadne_remove_one(struct zorro_dev *z)
{
- struct net_device *dev = zorro_get_drvdata(z);
+ struct net_device *dev = zorro_get_drvdata(z);
- unregister_netdev(dev);
- release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
- release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
- free_netdev(dev);
+ unregister_netdev(dev);
+ release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
+ release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
+ free_netdev(dev);
}
+static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
+
+static const struct net_device_ops ariadne_netdev_ops = {
+ .ndo_open = ariadne_open,
+ .ndo_stop = ariadne_close,
+ .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_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+};
+
+static int __devinit ariadne_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
+{
+ unsigned long board = z->resource.start;
+ unsigned long base_addr = board + ARIADNE_LANCE;
+ unsigned long mem_start = board + ARIADNE_RAM;
+ struct resource *r1, *r2;
+ struct net_device *dev;
+ struct ariadne_private *priv;
+ int err;
+
+ r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
+ if (!r1)
+ return -EBUSY;
+ r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
+ if (!r2) {
+ release_mem_region(base_addr, sizeof(struct Am79C960));
+ return -EBUSY;
+ }
+
+ dev = alloc_etherdev(sizeof(struct ariadne_private));
+ if (dev == NULL) {
+ release_mem_region(base_addr, sizeof(struct Am79C960));
+ release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+ return -ENOMEM;
+ }
+
+ priv = netdev_priv(dev);
+
+ r1->name = dev->name;
+ r2->name = dev->name;
+
+ dev->dev_addr[0] = 0x00;
+ dev->dev_addr[1] = 0x60;
+ dev->dev_addr[2] = 0x30;
+ dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+ dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
+ dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
+ dev->base_addr = ZTWO_VADDR(base_addr);
+ dev->mem_start = ZTWO_VADDR(mem_start);
+ dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
+
+ dev->netdev_ops = &ariadne_netdev_ops;
+ dev->watchdog_timeo = 5 * HZ;
+
+ err = register_netdev(dev);
+ if (err) {
+ release_mem_region(base_addr, sizeof(struct Am79C960));
+ release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+ free_netdev(dev);
+ return err;
+ }
+ zorro_set_drvdata(z, dev);
+
+ netdev_info(dev, "Ariadne at 0x%08lx, Ethernet Address %pM\n",
+ board, dev->dev_addr);
+
+ return 0;
+}
+
+static struct zorro_driver ariadne_driver = {
+ .name = "ariadne",
+ .id_table = ariadne_zorro_tbl,
+ .probe = ariadne_init_one,
+ .remove = __devexit_p(ariadne_remove_one),
+};
+
static int __init ariadne_init_module(void)
{
- return zorro_register_driver(&ariadne_driver);
+ return zorro_register_driver(&ariadne_driver);
}
static void __exit ariadne_cleanup_module(void)
{
- zorro_unregister_driver(&ariadne_driver);
+ zorro_unregister_driver(&ariadne_driver);
}
module_init(ariadne_init_module);
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 7b3e23f38913..52fe21e1e2cd 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -199,17 +199,15 @@ am79c961_ramtest(struct net_device *dev, unsigned int val)
static void am79c961_mc_hash(char *addr, u16 *hash)
{
- if (addr[0] & 0x01) {
- int idx, bit;
- u32 crc;
+ int idx, bit;
+ u32 crc;
- crc = ether_crc_le(ETH_ALEN, addr);
+ crc = ether_crc_le(ETH_ALEN, addr);
- idx = crc >> 30;
- bit = (crc >> 26) & 15;
+ idx = crc >> 30;
+ bit = (crc >> 26) & 15;
- hash[idx] |= 1 << bit;
- }
+ hash[idx] |= 1 << bit;
}
static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index e07b314ed8fd..29dc43523cec 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 0b46b8ea0e80..4317af8d2f0a 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -19,6 +19,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index a7b0caa18179..c827a6097d02 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -16,11 +16,13 @@
* Vincent Sanders <vince@simtec.co.uk>
*/
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
index 925929d764ca..ca70e16b6e2c 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/atl1c/atl1c.h
@@ -22,8 +22,8 @@
#ifndef _ATL1C_H_
#define _ATL1C_H_
-#include <linux/version.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -555,7 +555,6 @@ struct atl1c_smb {
struct atl1c_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
- struct vlan_group *vlgrp;
struct napi_struct napi;
struct atl1c_hw hw;
struct atl1c_hw_stats hw_stats;
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 1269ba5d6e56..972244218408 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -411,29 +411,29 @@ static void atl1c_set_multi(struct net_device *netdev)
}
}
-static void atl1c_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+static void __atl1c_vlan_mode(u32 features, u32 *mac_ctrl_data)
+{
+ if (features & NETIF_F_HW_VLAN_RX) {
+ /* enable VLAN tag insert/strip */
+ *mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+ } else {
+ /* disable VLAN tag insert/strip */
+ *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+ }
+}
+
+static void atl1c_vlan_mode(struct net_device *netdev, u32 features)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev = adapter->pdev;
u32 mac_ctrl_data = 0;
if (netif_msg_pktdata(adapter))
- dev_dbg(&pdev->dev, "atl1c_vlan_rx_register\n");
+ dev_dbg(&pdev->dev, "atl1c_vlan_mode\n");
atl1c_irq_disable(adapter);
-
- adapter->vlgrp = grp;
AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data);
-
- if (grp) {
- /* enable VLAN tag insert/strip */
- mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
- } else {
- /* disable VLAN tag insert/strip */
- mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
- }
-
+ __atl1c_vlan_mode(features, &mac_ctrl_data);
AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
atl1c_irq_enable(adapter);
}
@@ -443,9 +443,10 @@ static void atl1c_restore_vlan(struct atl1c_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
if (netif_msg_pktdata(adapter))
- dev_dbg(&pdev->dev, "atl1c_restore_vlan !");
- atl1c_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ dev_dbg(&pdev->dev, "atl1c_restore_vlan\n");
+ atl1c_vlan_mode(adapter->netdev, adapter->netdev->features);
}
+
/*
* atl1c_set_mac - Change the Ethernet Address of the NIC
* @netdev: network interface device structure
@@ -483,12 +484,31 @@ static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
static u32 atl1c_fix_features(struct net_device *netdev, u32 features)
{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
if (netdev->mtu > MAX_TSO_FRAME_SIZE)
features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
return features;
}
+static int atl1c_set_features(struct net_device *netdev, u32 features)
+{
+ u32 changed = netdev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ atl1c_vlan_mode(netdev, features);
+
+ return 0;
+}
+
/*
* atl1c_change_mtu - Change the Maximum Transfer Unit
* @netdev: network interface device structure
@@ -1433,8 +1453,7 @@ static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
MAC_CTRL_PRMLEN_SHIFT);
- if (adapter->vlgrp)
- mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+ __atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
mac_ctrl_data |= MAC_CTRL_BC_EN;
if (netdev->flags & IFF_PROMISC)
@@ -1878,14 +1897,14 @@ rrs_checked:
skb_put(skb, length - ETH_FCS_LEN);
skb->protocol = eth_type_trans(skb, netdev);
atl1c_rx_checksum(adapter, skb, rrs);
- if (unlikely(adapter->vlgrp) && rrs->word3 & RRS_VLAN_INS) {
+ if (rrs->word3 & RRS_VLAN_INS) {
u16 vlan;
AT_TAG_TO_VLAN(rrs->vlan_tag, vlan);
vlan = le16_to_cpu(vlan);
- vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vlan);
- } else
- netif_receive_skb(skb);
+ __vlan_hwaccel_put_tag(skb, vlan);
+ }
+ netif_receive_skb(skb);
(*work_done)++;
count++;
@@ -2507,8 +2526,7 @@ static int atl1c_suspend(struct device *dev)
/* clear phy interrupt */
atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
/* Config MAC Ctrl register */
- if (adapter->vlgrp)
- mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+ __atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
/* magic packet maybe Broadcast&multicast&Unicast frame */
if (wufc & AT_WUFC_MAG)
@@ -2581,14 +2599,14 @@ static const struct net_device_ops atl1c_netdev_ops = {
.ndo_stop = atl1c_close,
.ndo_validate_addr = eth_validate_addr,
.ndo_start_xmit = atl1c_xmit_frame,
- .ndo_set_mac_address = atl1c_set_mac_addr,
+ .ndo_set_mac_address = atl1c_set_mac_addr,
.ndo_set_multicast_list = atl1c_set_multi,
.ndo_change_mtu = atl1c_change_mtu,
.ndo_fix_features = atl1c_fix_features,
+ .ndo_set_features = atl1c_set_features,
.ndo_do_ioctl = atl1c_ioctl,
.ndo_tx_timeout = atl1c_tx_timeout,
.ndo_get_stats = atl1c_get_stats,
- .ndo_vlan_rx_register = atl1c_vlan_rx_register,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = atl1c_netpoll,
#endif
@@ -2607,11 +2625,11 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
/* TODO: add when ready */
netdev->hw_features = NETIF_F_SG |
NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX |
+ NETIF_F_HW_VLAN_RX |
NETIF_F_TSO |
NETIF_F_TSO6;
netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_RX;
+ NETIF_F_HW_VLAN_TX;
return 0;
}
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
index 490d3b38e0cb..829b5ad71d0d 100644
--- a/drivers/net/atl1e/atl1e.h
+++ b/drivers/net/atl1e/atl1e.h
@@ -23,8 +23,8 @@
#ifndef _ATL1E_H_
#define _ATL1E_H_
-#include <linux/version.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -433,7 +433,6 @@ struct atl1e_rx_ring {
struct atl1e_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
- struct vlan_group *vlgrp;
struct napi_struct napi;
struct mii_if_info mii; /* MII interface info */
struct atl1e_hw hw;
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 86a912283134..d8d411998fa3 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -313,8 +313,18 @@ static void atl1e_set_multi(struct net_device *netdev)
}
}
-static void atl1e_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+static void __atl1e_vlan_mode(u32 features, u32 *mac_ctrl_data)
+{
+ if (features & NETIF_F_HW_VLAN_RX) {
+ /* enable VLAN tag insert/strip */
+ *mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+ } else {
+ /* disable VLAN tag insert/strip */
+ *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+ }
+}
+
+static void atl1e_vlan_mode(struct net_device *netdev, u32 features)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
u32 mac_ctrl_data = 0;
@@ -322,18 +332,8 @@ static void atl1e_vlan_rx_register(struct net_device *netdev,
netdev_dbg(adapter->netdev, "%s\n", __func__);
atl1e_irq_disable(adapter);
-
- adapter->vlgrp = grp;
mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL);
-
- if (grp) {
- /* enable VLAN tag insert/strip */
- mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
- } else {
- /* disable VLAN tag insert/strip */
- mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
- }
-
+ __atl1e_vlan_mode(features, &mac_ctrl_data);
AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
atl1e_irq_enable(adapter);
}
@@ -341,8 +341,9 @@ static void atl1e_vlan_rx_register(struct net_device *netdev,
static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
{
netdev_dbg(adapter->netdev, "%s\n", __func__);
- atl1e_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ atl1e_vlan_mode(adapter->netdev, adapter->netdev->features);
}
+
/*
* atl1e_set_mac - Change the Ethernet Address of the NIC
* @netdev: network interface device structure
@@ -369,6 +370,30 @@ static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
return 0;
}
+static u32 atl1e_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int atl1e_set_features(struct net_device *netdev, u32 features)
+{
+ u32 changed = netdev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ atl1e_vlan_mode(netdev, features);
+
+ return 0;
+}
+
/*
* atl1e_change_mtu - Change the Maximum Transfer Unit
* @netdev: network interface device structure
@@ -800,8 +825,7 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
/* Init TPD Ring */
tx_ring->dma = roundup(adapter->ring_dma, 8);
offset = tx_ring->dma - adapter->ring_dma;
- tx_ring->desc = (struct atl1e_tpd_desc *)
- (adapter->ring_vir_addr + offset);
+ tx_ring->desc = adapter->ring_vir_addr + offset;
size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL);
if (tx_ring->tx_buffer == NULL) {
@@ -827,7 +851,7 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
/* Init CMB dma address */
tx_ring->cmb_dma = adapter->ring_dma + offset;
- tx_ring->cmb = (u32 *)(adapter->ring_vir_addr + offset);
+ tx_ring->cmb = adapter->ring_vir_addr + offset;
offset += sizeof(u32);
for (i = 0; i < adapter->num_rx_queues; i++) {
@@ -1040,8 +1064,7 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
value |= (((u32)adapter->hw.preamble_len &
MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
- if (adapter->vlgrp)
- value |= MAC_CTRL_RMV_VLAN;
+ __atl1e_vlan_mode(netdev->features, &value);
value |= MAC_CTRL_BC_EN;
if (netdev->flags & IFF_PROMISC)
@@ -1424,19 +1447,16 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
skb->protocol = eth_type_trans(skb, netdev);
atl1e_rx_checksum(adapter, skb, prrs);
- if (unlikely(adapter->vlgrp &&
- (prrs->pkt_flag & RRS_IS_VLAN_TAG))) {
+ if (prrs->pkt_flag & RRS_IS_VLAN_TAG) {
u16 vlan_tag = (prrs->vtag >> 4) |
((prrs->vtag & 7) << 13) |
((prrs->vtag & 8) << 9);
netdev_dbg(netdev,
"RXD VLAN TAG<RRD>=0x%04x\n",
prrs->vtag);
- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- vlan_tag);
- } else {
- netif_receive_skb(skb);
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
}
+ netif_receive_skb(skb);
skip_pkt:
/* skip current packet whether it's ok or not. */
@@ -1812,7 +1832,7 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb,
tpd = atl1e_get_tpd(adapter);
- if (unlikely(vlan_tx_tag_present(skb))) {
+ if (vlan_tx_tag_present(skb)) {
u16 vlan_tag = vlan_tx_tag_get(skb);
u16 atl1e_vlan_tag;
@@ -2094,8 +2114,7 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
MAC_CTRL_PRMLEN_MASK) <<
MAC_CTRL_PRMLEN_SHIFT);
- if (adapter->vlgrp)
- mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+ __atl1e_vlan_mode(netdev->features, &mac_ctrl_data);
/* magic packet maybe Broadcast&multicast&Unicast frame */
if (wufc & AT_WUFC_MAG)
@@ -2196,10 +2215,11 @@ static const struct net_device_ops atl1e_netdev_ops = {
.ndo_set_multicast_list = atl1e_set_multi,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = atl1e_set_mac_addr,
+ .ndo_fix_features = atl1e_fix_features,
+ .ndo_set_features = atl1e_set_features,
.ndo_change_mtu = atl1e_change_mtu,
.ndo_do_ioctl = atl1e_ioctl,
.ndo_tx_timeout = atl1e_tx_timeout,
- .ndo_vlan_rx_register = atl1e_vlan_rx_register,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = atl1e_netpoll,
#endif
@@ -2218,9 +2238,9 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
atl1e_set_ethtool_ops(netdev);
netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
- NETIF_F_HW_VLAN_TX;
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_RX | NETIF_F_LLTX;
+ NETIF_F_HW_VLAN_RX;
+ netdev->features = netdev->hw_features | NETIF_F_LLTX |
+ NETIF_F_HW_VLAN_TX;
return 0;
}
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index cd5789ff3726..97e6954304ea 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -44,7 +44,7 @@
* SMP torture testing
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/byteorder.h>
#include <linux/compiler.h>
@@ -1285,8 +1285,7 @@ static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
value |= (((u32) adapter->hw.preamble_len
& MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
/* vlan */
- if (adapter->vlgrp)
- value |= MAC_CTRL_RMV_VLAN;
+ __atlx_vlan_mode(netdev->features, &value);
/* rx checksum
if (adapter->rx_csum)
value |= MAC_CTRL_RX_CHKSUM_EN;
@@ -2023,13 +2022,14 @@ rrd_ok:
atl1_rx_checksum(adapter, rrd, skb);
skb->protocol = eth_type_trans(skb, adapter->netdev);
- if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+ if (rrd->pkt_flg & PACKET_FLAG_VLAN_INS) {
u16 vlan_tag = (rrd->vlan_tag >> 4) |
((rrd->vlan_tag & 7) << 13) |
((rrd->vlan_tag & 8) << 9);
- vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
- } else
- netif_rx(skb);
+
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
+ }
+ netif_rx(skb);
/* let protocol layer free skb */
buffer_info->skb = NULL;
@@ -2783,8 +2783,7 @@ static int atl1_suspend(struct device *dev)
ctrl |= MAC_CTRL_DUPLX;
ctrl |= (((u32)adapter->hw.preamble_len &
MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
- if (adapter->vlgrp)
- ctrl |= MAC_CTRL_RMV_VLAN;
+ __atlx_vlan_mode(netdev->features, &ctrl);
if (wufc & ATLX_WUFC_MAG)
ctrl |= MAC_CTRL_BC_EN;
iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
@@ -2874,9 +2873,10 @@ static const struct net_device_ops atl1_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = atl1_set_mac,
.ndo_change_mtu = atl1_change_mtu,
+ .ndo_fix_features = atlx_fix_features,
+ .ndo_set_features = atlx_set_features,
.ndo_do_ioctl = atlx_ioctl,
.ndo_tx_timeout = atlx_tx_timeout,
- .ndo_vlan_rx_register = atlx_vlan_rx_register,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = atl1_poll_controller,
#endif
@@ -2984,7 +2984,8 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
netdev->features |= NETIF_F_SG;
netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
- netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO;
+ netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO |
+ NETIF_F_HW_VLAN_RX;
/* is this valid? see atl1_setup_mac_ctrl() */
netdev->features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
index 68de8cbfb3ec..109d6da8be97 100644
--- a/drivers/net/atlx/atl1.h
+++ b/drivers/net/atlx/atl1.h
@@ -753,7 +753,6 @@ struct atl1_adapter {
struct pci_dev *pdev;
struct atl1_sft_stats soft_stats;
- struct vlan_group *vlgrp;
u32 rx_buffer_len;
u32 wol;
u16 link_speed;
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 16249e9b6b95..d4f7dda39721 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -20,7 +20,7 @@
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/crc32.h>
#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
@@ -311,8 +311,7 @@ static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter)
adapter->txd_dma = adapter->ring_dma ;
offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0;
adapter->txd_dma += offset;
- adapter->txd_ring = (struct tx_pkt_header *) (adapter->ring_vir_addr +
- offset);
+ adapter->txd_ring = adapter->ring_vir_addr + offset;
/* Init TXS Ring */
adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size;
@@ -362,36 +361,59 @@ static inline void atl2_irq_disable(struct atl2_adapter *adapter)
synchronize_irq(adapter->pdev->irq);
}
-#ifdef NETIF_F_HW_VLAN_TX
-static void atl2_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+static void __atl2_vlan_mode(u32 features, u32 *ctrl)
+{
+ if (features & NETIF_F_HW_VLAN_RX) {
+ /* enable VLAN tag insert/strip */
+ *ctrl |= MAC_CTRL_RMV_VLAN;
+ } else {
+ /* disable VLAN tag insert/strip */
+ *ctrl &= ~MAC_CTRL_RMV_VLAN;
+ }
+}
+
+static void atl2_vlan_mode(struct net_device *netdev, u32 features)
{
struct atl2_adapter *adapter = netdev_priv(netdev);
u32 ctrl;
atl2_irq_disable(adapter);
- adapter->vlgrp = grp;
- if (grp) {
- /* enable VLAN tag insert/strip */
- ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
- ctrl |= MAC_CTRL_RMV_VLAN;
- ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
- } else {
- /* disable VLAN tag insert/strip */
- ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
- ctrl &= ~MAC_CTRL_RMV_VLAN;
- ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
- }
+ ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
+ __atl2_vlan_mode(features, &ctrl);
+ ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
atl2_irq_enable(adapter);
}
static void atl2_restore_vlan(struct atl2_adapter *adapter)
{
- atl2_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ atl2_vlan_mode(adapter->netdev, adapter->netdev->features);
+}
+
+static u32 atl2_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int atl2_set_features(struct net_device *netdev, u32 features)
+{
+ u32 changed = netdev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ atl2_vlan_mode(netdev, features);
+
+ return 0;
}
-#endif
static void atl2_intr_rx(struct atl2_adapter *adapter)
{
@@ -425,14 +447,13 @@ static void atl2_intr_rx(struct atl2_adapter *adapter)
memcpy(skb->data, rxd->packet, rx_size);
skb_put(skb, rx_size);
skb->protocol = eth_type_trans(skb, netdev);
-#ifdef NETIF_F_HW_VLAN_TX
- if (adapter->vlgrp && (rxd->status.vlan)) {
+ if (rxd->status.vlan) {
u16 vlan_tag = (rxd->status.vtag>>4) |
((rxd->status.vtag&7) << 13) |
((rxd->status.vtag&8) << 9);
- vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
- } else
-#endif
+
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
+ }
netif_rx(skb);
netdev->stats.rx_bytes += rx_size;
netdev->stats.rx_packets++;
@@ -705,9 +726,7 @@ static int atl2_open(struct net_device *netdev)
atl2_set_multi(netdev);
init_ring_ptrs(adapter);
-#ifdef NETIF_F_HW_VLAN_TX
atl2_restore_vlan(adapter);
-#endif
if (atl2_configure(adapter)) {
err = -EIO;
@@ -1083,9 +1102,7 @@ static int atl2_up(struct atl2_adapter *adapter)
atl2_set_multi(netdev);
init_ring_ptrs(adapter);
-#ifdef NETIF_F_HW_VLAN_TX
atl2_restore_vlan(adapter);
-#endif
if (atl2_configure(adapter)) {
err = -EIO;
@@ -1146,8 +1163,7 @@ static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter)
MAC_CTRL_PRMLEN_SHIFT);
/* vlan */
- if (adapter->vlgrp)
- value |= MAC_CTRL_RMV_VLAN;
+ __atl2_vlan_mode(netdev->features, &value);
/* filter mode */
value |= MAC_CTRL_BC_EN;
@@ -1313,9 +1329,10 @@ static const struct net_device_ops atl2_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = atl2_set_mac,
.ndo_change_mtu = atl2_change_mtu,
+ .ndo_fix_features = atl2_fix_features,
+ .ndo_set_features = atl2_set_features,
.ndo_do_ioctl = atl2_ioctl,
.ndo_tx_timeout = atl2_tx_timeout,
- .ndo_vlan_rx_register = atl2_vlan_rx_register,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = atl2_poll_controller,
#endif
@@ -1411,7 +1428,7 @@ static int __devinit atl2_probe(struct pci_dev *pdev,
err = -EIO;
- netdev->hw_features = NETIF_F_SG;
+ netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_RX;
netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
/* Init PHY as early as possible due to power saving issue */
diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h
index 927e4de6474d..bf9016ebdd9b 100644
--- a/drivers/net/atlx/atl2.h
+++ b/drivers/net/atlx/atl2.h
@@ -25,7 +25,7 @@
#ifndef _ATL2_H_
#define _ATL2_H_
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/netdevice.h>
#ifndef _ATL2_HW_H_
@@ -453,9 +453,6 @@ struct atl2_adapter {
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
-#ifdef NETIF_F_HW_VLAN_TX
- struct vlan_group *vlgrp;
-#endif
u32 wol;
u16 link_speed;
u16 link_duplex;
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
index afb7f7dd1bb1..aabcf4b5745a 100644
--- a/drivers/net/atlx/atlx.c
+++ b/drivers/net/atlx/atlx.c
@@ -211,8 +211,18 @@ static void atlx_link_chg_task(struct work_struct *work)
spin_unlock_irqrestore(&adapter->lock, flags);
}
-static void atlx_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+static void __atlx_vlan_mode(u32 features, u32 *ctrl)
+{
+ if (features & NETIF_F_HW_VLAN_RX) {
+ /* enable VLAN tag insert/strip */
+ *ctrl |= MAC_CTRL_RMV_VLAN;
+ } else {
+ /* disable VLAN tag insert/strip */
+ *ctrl &= ~MAC_CTRL_RMV_VLAN;
+ }
+}
+
+static void atlx_vlan_mode(struct net_device *netdev, u32 features)
{
struct atlx_adapter *adapter = netdev_priv(netdev);
unsigned long flags;
@@ -220,27 +230,40 @@ static void atlx_vlan_rx_register(struct net_device *netdev,
spin_lock_irqsave(&adapter->lock, flags);
/* atlx_irq_disable(adapter); FIXME: confirm/remove */
- adapter->vlgrp = grp;
-
- if (grp) {
- /* enable VLAN tag insert/strip */
- ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
- ctrl |= MAC_CTRL_RMV_VLAN;
- iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
- } else {
- /* disable VLAN tag insert/strip */
- ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
- ctrl &= ~MAC_CTRL_RMV_VLAN;
- iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
- }
-
+ ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+ __atlx_vlan_mode(features, &ctrl);
+ iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
/* atlx_irq_enable(adapter); FIXME */
spin_unlock_irqrestore(&adapter->lock, flags);
}
static void atlx_restore_vlan(struct atlx_adapter *adapter)
{
- atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
+}
+
+static u32 atlx_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int atlx_set_features(struct net_device *netdev, u32 features)
+{
+ u32 changed = netdev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ atlx_vlan_mode(netdev, features);
+
+ return 0;
}
#endif /* ATLX_C */
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index a69331e06b8d..41ea84e3f69c 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -5,7 +5,7 @@
* Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
* Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
* Copyright (C) 2006 Broadcom Corporation.
- * Copyright (C) 2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2007 Michael Buesch <m@bues.ch>
*
* Distribute under GPL.
*/
@@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/ssb/ssb.h>
#include <linux/slab.h>
@@ -38,6 +39,7 @@
#define DRV_MODULE_NAME "b44"
#define DRV_MODULE_VERSION "2.0"
+#define DRV_DESCRIPTION "Broadcom 44xx/47xx 10/100 PCI ethernet driver"
#define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \
@@ -90,11 +92,8 @@
#define B44_ETHIPV6UDP_HLEN 62
#define B44_ETHIPV4UDP_HLEN 42
-static char version[] __devinitdata =
- DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION "\n";
-
MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller");
-MODULE_DESCRIPTION("Broadcom 44xx/47xx 10/100 PCI ethernet driver");
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -609,7 +608,7 @@ static void b44_tx(struct b44 *bp)
skb->len,
DMA_TO_DEVICE);
rp->skb = NULL;
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
}
bp->tx_cons = cons;
@@ -2129,16 +2128,13 @@ static const struct net_device_ops b44_netdev_ops = {
static int __devinit b44_init_one(struct ssb_device *sdev,
const struct ssb_device_id *ent)
{
- static int b44_version_printed = 0;
struct net_device *dev;
struct b44 *bp;
int err;
instance++;
- if (b44_version_printed++ == 0)
- pr_info("%s", version);
-
+ pr_info_once("%s version %s\n", DRV_DESCRIPTION, DRV_MODULE_VERSION);
dev = alloc_etherdev(sizeof(*bp));
if (!dev) {
@@ -2224,8 +2220,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
if (b44_phy_reset(bp) < 0)
bp->phy_addr = B44_PHY_ADDR_NO_PHY;
- netdev_info(dev, "Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n",
- dev->dev_addr);
+ netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
return 0;
@@ -2335,7 +2330,7 @@ static struct ssb_driver b44_ssb_driver = {
.resume = b44_resume,
};
-static inline int b44_pci_init(void)
+static inline int __init b44_pci_init(void)
{
int err = 0;
#ifdef CONFIG_B44_PCI
@@ -2344,7 +2339,7 @@ static inline int b44_pci_init(void)
return err;
}
-static inline void b44_pci_exit(void)
+static inline void __exit b44_pci_exit(void)
{
#ifdef CONFIG_B44_PCI
ssb_pcihost_unregister(&b44_pci_driver);
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index f1573d492e90..1d9b9858067c 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/etherdevice.h>
@@ -1646,7 +1647,7 @@ static int __devinit bcm_enet_probe(struct platform_device *pdev)
if (ret)
goto out;
- iomem_size = res_mem->end - res_mem->start + 1;
+ iomem_size = resource_size(res_mem);
if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
ret = -EBUSY;
goto out;
@@ -1861,7 +1862,7 @@ static int __devexit bcm_enet_remove(struct platform_device *pdev)
/* release device resources */
iounmap(priv->base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
/* disable hw block clocks */
if (priv->phy_clk) {
@@ -1897,7 +1898,7 @@ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
if (!res)
return -ENODEV;
- iomem_size = res->end - res->start + 1;
+ iomem_size = resource_size(res);
if (!request_mem_region(res->start, iomem_size, "bcm63xx_enet_dma"))
return -EBUSY;
@@ -1915,7 +1916,7 @@ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
iounmap(bcm_enet_shared_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
return 0;
}
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index a7db870d1641..c85768cd1b18 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -20,7 +20,6 @@
#include <linux/pci.h>
#include <linux/etherdevice.h>
-#include <linux/version.h>
#include <linux/delay.h>
#include <net/tcp.h>
#include <net/ip.h>
@@ -87,6 +86,7 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
+#define MAX_TX_QS 8
#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
@@ -170,7 +170,6 @@ 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_events; /* number of tx completion events */
u32 be_tx_compl; /* number of tx completion entries processed */
ulong be_tx_jiffies;
u64 be_tx_bytes;
@@ -184,6 +183,7 @@ struct be_tx_obj {
struct be_queue_info cq;
/* Remember the skbs that were transmitted */
struct sk_buff *sent_skb_list[TX_Q_LEN];
+ struct be_tx_stats stats;
};
/* Struct to remember the pages posted for rx frags */
@@ -199,6 +199,7 @@ struct be_rx_stats {
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;
@@ -319,8 +320,8 @@ struct be_adapter {
/* TX Rings */
struct be_eq_obj tx_eq;
- struct be_tx_obj tx_obj;
- struct be_tx_stats tx_stats;
+ struct be_tx_obj tx_obj[MAX_TX_QS];
+ u8 num_tx_qs;
u32 cache_line_break[8];
@@ -332,7 +333,6 @@ struct be_adapter {
u8 eq_next_idx;
struct be_drv_stats drv_stats;
- struct vlan_group *vlan_grp;
u16 vlans_added;
u16 max_vlans; /* Number of vlans supported */
u8 vlan_tag[VLAN_N_VID];
@@ -391,7 +391,7 @@ struct be_adapter {
extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
-#define tx_stats(adapter) (&adapter->tx_stats)
+#define tx_stats(txo) (&txo->stats)
#define rx_stats(rxo) (&rxo->stats)
#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops)
@@ -405,6 +405,10 @@ extern const struct ethtool_ops be_ethtool_ops;
for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
i++, rxo++)
+#define for_all_tx_queues(adapter, txo, i) \
+ for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \
+ i++, txo++)
+
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 81654ae16c63..054fa67bc4e3 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -106,14 +106,24 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
netdev_stats_update(adapter);
adapter->stats_cmd_sent = false;
}
- } else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) &&
- (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) {
- extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
- CQE_STATUS_EXTD_MASK;
- dev_warn(&adapter->pdev->dev,
- "Error in cmd completion - opcode %d, compl %d, extd %d\n",
- compl->tag0, compl_status, extd_status);
+ } else {
+ if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
+ compl_status == MCC_STATUS_ILLEGAL_REQUEST)
+ goto done;
+
+ if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
+ dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
+ "permitted to execute this cmd (opcode %d)\n",
+ compl->tag0);
+ } else {
+ extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
+ CQE_STATUS_EXTD_MASK;
+ dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
+ "status %d, extd-status %d\n",
+ compl->tag0, compl_status, extd_status);
+ }
}
+done:
return compl_status;
}
@@ -799,12 +809,12 @@ static u32 be_encoded_q_len(int q_len)
return len_encoded;
}
-int be_cmd_mccq_create(struct be_adapter *adapter,
+int be_cmd_mccq_ext_create(struct be_adapter *adapter,
struct be_queue_info *mccq,
struct be_queue_info *cq)
{
struct be_mcc_wrb *wrb;
- struct be_cmd_req_mcc_create *req;
+ struct be_cmd_req_mcc_ext_create *req;
struct be_dma_mem *q_mem = &mccq->dma_mem;
void *ctxt;
int status;
@@ -859,6 +869,67 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
return status;
}
+int be_cmd_mccq_org_create(struct be_adapter *adapter,
+ struct be_queue_info *mccq,
+ struct be_queue_info *cq)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_mcc_create *req;
+ struct be_dma_mem *q_mem = &mccq->dma_mem;
+ void *ctxt;
+ int status;
+
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(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));
+
+ req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+
+ AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
+ AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
+ be_encoded_q_len(mccq->len));
+ AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
+
+ be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+ be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+ status = be_mbox_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
+ mccq->id = le16_to_cpu(resp->id);
+ mccq->created = true;
+ }
+
+ mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+int be_cmd_mccq_create(struct be_adapter *adapter,
+ struct be_queue_info *mccq,
+ struct be_queue_info *cq)
+{
+ int status;
+
+ status = be_cmd_mccq_ext_create(adapter, mccq, cq);
+ if (status && !lancer_chip(adapter)) {
+ dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
+ "or newer to avoid conflicting priorities between NIC "
+ "and FCoE traffic");
+ status = be_cmd_mccq_org_create(adapter, mccq, cq);
+ }
+ return status;
+}
+
int be_cmd_txq_create(struct be_adapter *adapter,
struct be_queue_info *txq,
struct be_queue_info *cq)
@@ -913,7 +984,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,
return status;
}
-/* Uses mbox */
+/* Uses MCC */
int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
@@ -923,10 +994,13 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_dma_mem *q_mem = &rxq->dma_mem;
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,
@@ -943,7 +1017,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
req->max_frame_size = cpu_to_le16(max_frame_size);
req->rss_queue = cpu_to_le32(rss);
- status = be_mbox_notify_wait(adapter);
+ status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
rxq->id = le16_to_cpu(resp->id);
@@ -951,8 +1025,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
*rss_id = resp->rss_id;
}
- mutex_unlock(&adapter->mbox_lock);
-
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1007,9 +1081,40 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
req->id = cpu_to_le16(q->id);
status = be_mbox_notify_wait(adapter);
+ if (!status)
+ q->created = false;
mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+/* Uses MCC */
+int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_q_destroy *req;
+ int status;
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = embedded_payload(wrb);
+
+ be_wrb_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));
+ req->id = cpu_to_le16(q->id);
+
+ status = be_mcc_notify_wait(adapter);
+ if (!status)
+ q->created = false;
+
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -2273,8 +2378,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
status = be_mbox_notify_wait(adapter);
if (!status) {
- attribs = (struct mgmt_controller_attrib *)( attribs_cmd.va +
- sizeof(struct be_cmd_resp_hdr));
+ attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
adapter->hba_port_num = attribs->hba_attribs.phy_port;
}
@@ -2286,7 +2390,7 @@ err:
}
/* Uses mbox */
-int be_cmd_check_native_mode(struct be_adapter *adapter)
+int be_cmd_req_native_mode(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_set_func_cap *req;
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 8148cc66cbe9..8e4d48824fe9 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -51,17 +51,12 @@ struct be_mcc_wrb {
/* Completion Status */
enum {
- MCC_STATUS_SUCCESS = 0x0,
-/* The client does not have sufficient privileges to execute the command */
- MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1,
-/* A parameter in the command was invalid. */
- MCC_STATUS_INVALID_PARAMETER = 0x2,
-/* There are insufficient chip resources to execute the command */
- MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3,
-/* The command is completing because the queue was getting flushed */
- MCC_STATUS_QUEUE_FLUSHING = 0x4,
-/* The command is completing with a DMA error */
- MCC_STATUS_DMA_FAILED = 0x5,
+ MCC_STATUS_SUCCESS = 0,
+ MCC_STATUS_FAILED = 1,
+ MCC_STATUS_ILLEGAL_REQUEST = 2,
+ MCC_STATUS_ILLEGAL_FIELD = 3,
+ MCC_STATUS_INSUFFICIENT_BUFFER = 4,
+ MCC_STATUS_UNAUTHORIZED_REQUEST = 5,
MCC_STATUS_NOT_SUPPORTED = 66
};
@@ -434,6 +429,14 @@ struct be_cmd_req_mcc_create {
struct be_cmd_req_hdr hdr;
u16 num_pages;
u16 cq_id;
+ u8 context[sizeof(struct amap_mcc_context_be) / 8];
+ struct phys_addr pages[8];
+} __packed;
+
+struct be_cmd_req_mcc_ext_create {
+ struct be_cmd_req_hdr hdr;
+ u16 num_pages;
+ u16 cq_id;
u32 async_event_bitmap[1];
u8 context[sizeof(struct amap_mcc_context_be) / 8];
struct phys_addr pages[8];
@@ -1479,6 +1482,8 @@ extern int be_cmd_rxq_create(struct be_adapter *adapter,
u32 rss, u8 *rss_id);
extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type);
+extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
+ struct be_queue_info *q);
extern int be_cmd_link_status_query(struct be_adapter *adapter,
bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom);
extern int be_cmd_reset(struct be_adapter *adapter);
@@ -1540,7 +1545,7 @@ 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);
extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
-extern int be_cmd_check_native_mode(struct be_adapter *adapter);
+extern int be_cmd_req_native_mode(struct be_adapter *adapter);
extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index facfe3ca5c40..7fd8130d86ea 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -52,12 +52,7 @@ static const struct be_ethtool_stat et_stats[] = {
{NETSTAT_INFO(tx_errors)},
{NETSTAT_INFO(rx_dropped)},
{NETSTAT_INFO(tx_dropped)},
- {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_events)},
- {DRVSTAT_TX_INFO(be_tx_compl)},
+ {DRVSTAT_INFO(be_tx_events)},
{DRVSTAT_INFO(rx_crc_errors)},
{DRVSTAT_INFO(rx_alignment_symbol_errors)},
{DRVSTAT_INFO(rx_pause_frames)},
@@ -107,10 +102,21 @@ static const struct be_ethtool_stat et_rx_stats[] = {
{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)}
};
#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
+/* Stats related to multi TX queues */
+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)}
+};
+#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
+
static const char et_self_tests[][ETH_GSTRING_LEN] = {
"MAC Loopback test",
"PHY Loopback test",
@@ -253,17 +259,15 @@ 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;
+ int i, j, base;
for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
switch (et_stats[i].type) {
case NETSTAT:
p = &netdev->stats;
break;
- case DRVSTAT_TX:
- p = &adapter->tx_stats;
- break;
case DRVSTAT:
p = &adapter->drv_stats;
break;
@@ -274,6 +278,7 @@ be_get_ethtool_stats(struct net_device *netdev,
*(u64 *)p: *(u32 *)p;
}
+ 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) {
@@ -285,11 +290,21 @@ be_get_ethtool_stats(struct net_device *netdev,
rxo->q.id;
break;
}
- data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] =
+ data[base + j * ETHTOOL_RXSTATS_NUM + i] =
(et_rx_stats[i].size == sizeof(u64)) ?
*(u64 *)p: *(u32 *)p;
}
}
+
+ 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;
+ }
+ }
}
static void
@@ -312,6 +327,13 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
data += ETH_GSTRING_LEN;
}
}
+ for (i = 0; i < adapter->num_tx_qs; i++) {
+ for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) {
+ sprintf(data, "txq%d: %s", i,
+ et_tx_stats[j].desc);
+ data += ETH_GSTRING_LEN;
+ }
+ }
break;
case ETH_SS_TEST:
for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
@@ -331,7 +353,8 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
return ETHTOOL_TESTS_NUM;
case ETH_SS_STATS:
return ETHTOOL_STATS_NUM +
- adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
+ adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM +
+ adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM;
default:
return -EINVAL;
}
@@ -386,7 +409,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
}
status = be_cmd_get_phy_info(adapter, &phy_cmd);
if (!status) {
- resp = (struct be_cmd_resp_get_phy_info *) phy_cmd.va;
+ resp = phy_cmd.va;
intf_type = le16_to_cpu(resp->interface_type);
switch (intf_type) {
@@ -457,10 +480,10 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
struct be_adapter *adapter = netdev_priv(netdev);
ring->rx_max_pending = adapter->rx_obj[0].q.len;
- ring->tx_max_pending = adapter->tx_obj.q.len;
+ ring->tx_max_pending = adapter->tx_obj[0].q.len;
ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
- ring->tx_pending = atomic_read(&adapter->tx_obj.q.used);
+ ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used);
}
static void
@@ -690,7 +713,7 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);
if (!status) {
- resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va;
+ resp = eeprom_cmd.va;
memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
}
dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index a485f7fdaf37..c411bb1845fd 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -33,10 +33,6 @@ module_param(num_vfs, uint, S_IRUGO);
MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
-static bool multi_rxq = true;
-module_param(multi_rxq, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(multi_rxq, "Multi Rx Queue support. Enabled by default");
-
static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
@@ -48,7 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
};
MODULE_DEVICE_TABLE(pci, be_dev_ids);
/* UE Status Low CSR */
-static char *ue_status_low_desc[] = {
+static const char * const ue_status_low_desc[] = {
"CEV",
"CTX",
"DBUF",
@@ -83,7 +79,7 @@ static char *ue_status_low_desc[] = {
"MPU_INTPEND"
};
/* UE Status High CSR */
-static char *ue_status_hi_desc[] = {
+static const char * const ue_status_hi_desc[] = {
"LPCMEMHOST",
"MGMT_MAC",
"PCS0ONLINE",
@@ -107,7 +103,7 @@ static char *ue_status_hi_desc[] = {
"HOST7",
"HOST8",
"HOST9",
- "NETC"
+ "NETC",
"Unknown",
"Unknown",
"Unknown",
@@ -362,8 +358,8 @@ static void populate_lancer_stats(struct be_adapter *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_lo,
- pport_stats->rx_pause_frames_hi);
+ 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 =
@@ -427,31 +423,40 @@ void netdev_stats_update(struct be_adapter *adapter)
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;
int i;
- memset(dev_stats, 0, sizeof(*dev_stats));
for_all_rx_queues(adapter, rxo, i) {
- dev_stats->rx_packets += rx_stats(rxo)->rx_pkts;
- dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes;
- dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+ 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_stats =
+ struct be_erx_stats_v1 *erx =
be_erx_stats_from_cmd(adapter);
- dev_stats->rx_dropped +=
- erx_stats->rx_drops_no_fragments[rxo->q.id];
+ drops += erx->rx_drops_no_fragments[rxo->q.id];
}
} else {
- struct be_erx_stats_v0 *erx_stats =
+ struct be_erx_stats_v0 *erx =
be_erx_stats_from_cmd(adapter);
- dev_stats->rx_dropped +=
- erx_stats->rx_drops_no_fragments[rxo->q.id];
+ drops += erx->rx_drops_no_fragments[rxo->q.id];
}
}
+ dev_stats->rx_packets = pkts;
+ dev_stats->rx_bytes = bytes;
+ dev_stats->multicast = mcast;
+ dev_stats->rx_dropped = drops;
- dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts;
- dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes;
+ pkts = bytes = 0;
+ for_all_tx_queues(adapter, txo, i) {
+ pkts += tx_stats(txo)->be_tx_pkts;
+ bytes += tx_stats(txo)->be_tx_bytes;
+ }
+ dev_stats->tx_packets = pkts;
+ dev_stats->tx_bytes = bytes;
/* bad pkts received */
dev_stats->rx_errors = drvs->rx_crc_errors +
@@ -554,9 +559,9 @@ static u32 be_calc_rate(u64 bytes, unsigned long ticks)
return rate;
}
-static void be_tx_rate_update(struct be_adapter *adapter)
+static void be_tx_rate_update(struct be_tx_obj *txo)
{
- struct be_tx_stats *stats = tx_stats(adapter);
+ struct be_tx_stats *stats = tx_stats(txo);
ulong now = jiffies;
/* Wrapped around? */
@@ -575,10 +580,11 @@ static void be_tx_rate_update(struct be_adapter *adapter)
}
}
-static void be_tx_stats_update(struct be_adapter *adapter,
+static void be_tx_stats_update(struct be_tx_obj *txo,
u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
{
- struct be_tx_stats *stats = tx_stats(adapter);
+ struct be_tx_stats *stats = tx_stats(txo);
+
stats->be_tx_reqs++;
stats->be_tx_wrbs += wrb_cnt;
stats->be_tx_bytes += copied;
@@ -648,7 +654,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1);
}
- if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1);
vlan_tag = vlan_tx_tag_get(skb);
vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
@@ -682,14 +688,13 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
}
}
-static int make_tx_wrbs(struct be_adapter *adapter,
+static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb)
{
dma_addr_t busaddr;
int i, copied = 0;
struct device *dev = &adapter->pdev->dev;
struct sk_buff *first_skb = skb;
- struct be_queue_info *txq = &adapter->tx_obj.q;
struct be_eth_wrb *wrb;
struct be_eth_hdr_wrb *hdr;
bool map_single = false;
@@ -753,19 +758,19 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_tx_obj *tx_obj = &adapter->tx_obj;
- struct be_queue_info *txq = &tx_obj->q;
+ struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
+ struct be_queue_info *txq = &txo->q;
u32 wrb_cnt = 0, copied = 0;
u32 start = txq->head;
bool dummy_wrb, stopped = false;
wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
- copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
+ copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);
if (copied) {
/* record the sent skb in the sent_skb table */
- BUG_ON(tx_obj->sent_skb_list[start]);
- tx_obj->sent_skb_list[start] = skb;
+ BUG_ON(txo->sent_skb_list[start]);
+ txo->sent_skb_list[start] = skb;
/* Ensure txq has space for the next skb; Else stop the queue
* *BEFORE* ringing the tx doorbell, so that we serialze the
@@ -774,13 +779,13 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
atomic_add(wrb_cnt, &txq->used);
if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=
txq->len) {
- netif_stop_queue(netdev);
+ netif_stop_subqueue(netdev, skb_get_queue_mapping(skb));
stopped = true;
}
be_txq_notify(adapter, txq->id, wrb_cnt);
- be_tx_stats_update(adapter, wrb_cnt, copied,
+ be_tx_stats_update(txo, wrb_cnt, copied,
skb_shinfo(skb)->gso_segs, stopped);
} else {
txq->head = start;
@@ -842,13 +847,6 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
return status;
}
-static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
-{
- struct be_adapter *adapter = netdev_priv(netdev);
-
- adapter->vlan_grp = grp;
-}
-
static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
{
struct be_adapter *adapter = netdev_priv(netdev);
@@ -867,7 +865,6 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
struct be_adapter *adapter = netdev_priv(netdev);
adapter->vlans_added--;
- vlan_group_set_device(adapter->vlan_grp, vid, NULL);
if (!be_physfn(adapter))
return;
@@ -1177,8 +1174,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);
if (unlikely(!skb)) {
- if (net_ratelimit())
- dev_warn(&adapter->pdev->dev, "skb alloc failed\n");
+ rxo->stats.rx_dropped++;
be_rx_compl_discard(adapter, rxo, rxcp);
return;
}
@@ -1196,16 +1192,10 @@ static void be_rx_compl_process(struct be_adapter *adapter,
skb->rxhash = rxcp->rss_hash;
- if (unlikely(rxcp->vlanf)) {
- if (!adapter->vlan_grp || adapter->vlans_added == 0) {
- kfree_skb(skb);
- return;
- }
- vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
- rxcp->vlan_tag);
- } else {
- netif_receive_skb(skb);
- }
+ if (unlikely(rxcp->vlanf))
+ __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
+
+ netif_receive_skb(skb);
}
/* Process the RX completion indicated by rxcp when GRO is enabled */
@@ -1259,11 +1249,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
if (adapter->netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
- if (likely(!rxcp->vlanf))
- napi_gro_frags(&eq_obj->napi);
- else
- vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp,
- rxcp->vlan_tag);
+ if (unlikely(rxcp->vlanf))
+ __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
+
+ napi_gro_frags(&eq_obj->napi);
}
static void be_parse_rx_compl_v1(struct be_adapter *adapter,
@@ -1459,11 +1448,12 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)
return txcp;
}
-static u16 be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
+static u16 be_tx_compl_process(struct be_adapter *adapter,
+ struct be_tx_obj *txo, u16 last_index)
{
- struct be_queue_info *txq = &adapter->tx_obj.q;
+ struct be_queue_info *txq = &txo->q;
struct be_eth_wrb *wrb;
- struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
+ struct sk_buff **sent_skbs = txo->sent_skb_list;
struct sk_buff *sent_skb;
u16 cur_index, num_wrbs = 1; /* account for hdr wrb */
bool unmap_skb_hdr = true;
@@ -1504,7 +1494,8 @@ static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
}
static int event_handle(struct be_adapter *adapter,
- struct be_eq_obj *eq_obj)
+ struct be_eq_obj *eq_obj,
+ bool rearm)
{
struct be_eq_entry *eqe;
u16 num = 0;
@@ -1517,7 +1508,10 @@ static int event_handle(struct be_adapter *adapter,
/* Deal with any spurious interrupts that come
* without events
*/
- be_eq_notify(adapter, eq_obj->q.id, true, true, num);
+ if (!num)
+ rearm = true;
+
+ be_eq_notify(adapter, eq_obj->q.id, rearm, true, num);
if (num)
napi_schedule(&eq_obj->napi);
@@ -1563,15 +1557,17 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
memset(page_info, 0, sizeof(*page_info));
}
BUG_ON(atomic_read(&rxq->used));
+ rxq->tail = rxq->head = 0;
}
-static void be_tx_compl_clean(struct be_adapter *adapter)
+static void be_tx_compl_clean(struct be_adapter *adapter,
+ struct be_tx_obj *txo)
{
- struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
- struct be_queue_info *txq = &adapter->tx_obj.q;
+ struct be_queue_info *tx_cq = &txo->cq;
+ struct be_queue_info *txq = &txo->q;
struct be_eth_tx_compl *txcp;
u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0;
- struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
+ struct sk_buff **sent_skbs = txo->sent_skb_list;
struct sk_buff *sent_skb;
bool dummy_wrb;
@@ -1580,7 +1576,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
while ((txcp = be_tx_compl_get(tx_cq))) {
end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
wrb_index, txcp);
- num_wrbs += be_tx_compl_process(adapter, end_idx);
+ num_wrbs += be_tx_compl_process(adapter, txo, end_idx);
cmpl++;
}
if (cmpl) {
@@ -1607,7 +1603,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
index_adv(&end_idx,
wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
txq->len);
- num_wrbs = be_tx_compl_process(adapter, end_idx);
+ num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
atomic_sub(num_wrbs, &txq->used);
}
}
@@ -1666,16 +1662,20 @@ err:
static void be_tx_queues_destroy(struct be_adapter *adapter)
{
struct be_queue_info *q;
+ struct be_tx_obj *txo;
+ u8 i;
- q = &adapter->tx_obj.q;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
- be_queue_free(adapter, q);
+ for_all_tx_queues(adapter, txo, i) {
+ q = &txo->q;
+ if (q->created)
+ be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
+ be_queue_free(adapter, q);
- q = &adapter->tx_obj.cq;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_CQ);
- be_queue_free(adapter, q);
+ q = &txo->cq;
+ if (q->created)
+ be_cmd_q_destroy(adapter, q, QTYPE_CQ);
+ be_queue_free(adapter, q);
+ }
/* Clear any residual events */
be_eq_clean(adapter, &adapter->tx_eq);
@@ -1686,56 +1686,48 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
be_queue_free(adapter, q);
}
+/* One TX event queue is shared by all TX compl qs */
static int be_tx_queues_create(struct be_adapter *adapter)
{
struct be_queue_info *eq, *q, *cq;
+ struct be_tx_obj *txo;
+ u8 i;
adapter->tx_eq.max_eqd = 0;
adapter->tx_eq.min_eqd = 0;
adapter->tx_eq.cur_eqd = 96;
adapter->tx_eq.enable_aic = false;
- /* Alloc Tx Event queue */
+
eq = &adapter->tx_eq.q;
- if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry)))
+ if (be_queue_alloc(adapter, eq, EVNT_Q_LEN,
+ sizeof(struct be_eq_entry)))
return -1;
- /* Ask BE to create Tx Event queue */
if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
- goto tx_eq_free;
-
+ goto err;
adapter->tx_eq.eq_idx = adapter->eq_next_idx++;
-
- /* Alloc TX eth compl queue */
- cq = &adapter->tx_obj.cq;
- if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
+ for_all_tx_queues(adapter, txo, i) {
+ cq = &txo->cq;
+ if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
sizeof(struct be_eth_tx_compl)))
- goto tx_eq_destroy;
+ goto err;
- /* Ask BE to create Tx eth compl queue */
- if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
- goto tx_cq_free;
+ if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
+ goto err;
- /* Alloc TX eth queue */
- q = &adapter->tx_obj.q;
- if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb)))
- goto tx_cq_destroy;
+ q = &txo->q;
+ if (be_queue_alloc(adapter, q, TX_Q_LEN,
+ sizeof(struct be_eth_wrb)))
+ goto err;
- /* Ask BE to create Tx eth queue */
- if (be_cmd_txq_create(adapter, q, cq))
- goto tx_q_free;
+ if (be_cmd_txq_create(adapter, q, cq))
+ goto err;
+ }
return 0;
-tx_q_free:
- be_queue_free(adapter, q);
-tx_cq_destroy:
- be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
-tx_cq_free:
- be_queue_free(adapter, cq);
-tx_eq_destroy:
- be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
-tx_eq_free:
- be_queue_free(adapter, eq);
+err:
+ be_tx_queues_destroy(adapter);
return -1;
}
@@ -1746,36 +1738,23 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
int i;
for_all_rx_queues(adapter, rxo, i) {
- q = &rxo->q;
- if (q->created) {
- be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
- /* After the rxq is invalidated, wait for a grace time
- * of 1ms for all dma to end and the flush compl to
- * arrive
- */
- mdelay(1);
- be_rx_q_clean(adapter, rxo);
- }
- be_queue_free(adapter, q);
+ be_queue_free(adapter, &rxo->q);
q = &rxo->cq;
if (q->created)
be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
- /* Clear any residual events */
q = &rxo->rx_eq.q;
- if (q->created) {
- be_eq_clean(adapter, &rxo->rx_eq);
+ if (q->created)
be_cmd_q_destroy(adapter, q, QTYPE_EQ);
- }
be_queue_free(adapter, q);
}
}
static u32 be_num_rxqs_want(struct be_adapter *adapter)
{
- if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
+ if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
!adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
return 1 + MAX_RSS_QS; /* one default non-RSS queue */
} else {
@@ -1827,30 +1806,14 @@ static int be_rx_queues_create(struct be_adapter *adapter)
rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
if (rc)
goto err;
- /* Rx Q */
+
+ /* Rx Q - will be created in be_open() */
q = &rxo->q;
rc = be_queue_alloc(adapter, q, RX_Q_LEN,
sizeof(struct be_eth_rx_d));
if (rc)
goto err;
- rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
- BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle,
- (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
- if (rc)
- goto err;
- }
-
- if (be_multi_rxq(adapter)) {
- u8 rsstable[MAX_RSS_QS];
-
- for_all_rss_queues(adapter, rxo, i)
- rsstable[i] = rxo->rss_id;
-
- rc = be_cmd_rss_config(adapter, rsstable,
- adapter->num_rx_qs - 1);
- if (rc)
- goto err;
}
return 0;
@@ -1876,10 +1839,10 @@ static irqreturn_t be_intx(int irq, void *dev)
if (lancer_chip(adapter)) {
if (event_peek(&adapter->tx_eq))
- tx = event_handle(adapter, &adapter->tx_eq);
+ tx = event_handle(adapter, &adapter->tx_eq, false);
for_all_rx_queues(adapter, rxo, i) {
if (event_peek(&rxo->rx_eq))
- rx |= event_handle(adapter, &rxo->rx_eq);
+ rx |= event_handle(adapter, &rxo->rx_eq, true);
}
if (!(tx || rx))
@@ -1892,11 +1855,11 @@ static irqreturn_t be_intx(int irq, void *dev)
return IRQ_NONE;
if ((1 << adapter->tx_eq.eq_idx & isr))
- event_handle(adapter, &adapter->tx_eq);
+ event_handle(adapter, &adapter->tx_eq, false);
for_all_rx_queues(adapter, rxo, i) {
if ((1 << rxo->rx_eq.eq_idx & isr))
- event_handle(adapter, &rxo->rx_eq);
+ event_handle(adapter, &rxo->rx_eq, true);
}
}
@@ -1908,7 +1871,7 @@ static irqreturn_t be_msix_rx(int irq, void *dev)
struct be_rx_obj *rxo = dev;
struct be_adapter *adapter = rxo->adapter;
- event_handle(adapter, &rxo->rx_eq);
+ event_handle(adapter, &rxo->rx_eq, true);
return IRQ_HANDLED;
}
@@ -1917,7 +1880,7 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
{
struct be_adapter *adapter = dev;
- event_handle(adapter, &adapter->tx_eq);
+ event_handle(adapter, &adapter->tx_eq, false);
return IRQ_HANDLED;
}
@@ -1978,45 +1941,48 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
struct be_adapter *adapter =
container_of(tx_eq, struct be_adapter, tx_eq);
- struct be_queue_info *txq = &adapter->tx_obj.q;
- struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
+ struct be_tx_obj *txo;
struct be_eth_tx_compl *txcp;
- int tx_compl = 0, mcc_compl, status = 0;
- u16 end_idx, num_wrbs = 0;
+ int tx_compl, mcc_compl, status = 0;
+ u8 i;
+ u16 num_wrbs;
+
+ for_all_tx_queues(adapter, txo, i) {
+ tx_compl = 0;
+ num_wrbs = 0;
+ while ((txcp = be_tx_compl_get(&txo->cq))) {
+ num_wrbs += be_tx_compl_process(adapter, txo,
+ AMAP_GET_BITS(struct amap_eth_tx_compl,
+ wrb_index, txcp));
+ tx_compl++;
+ }
+ if (tx_compl) {
+ be_cq_notify(adapter, txo->cq.id, true, tx_compl);
- while ((txcp = be_tx_compl_get(tx_cq))) {
- end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
- wrb_index, txcp);
- num_wrbs += be_tx_compl_process(adapter, end_idx);
- tx_compl++;
+ atomic_sub(num_wrbs, &txo->q.used);
+
+ /* As Tx wrbs have been freed up, wake up netdev queue
+ * if it was stopped due to lack of tx wrbs. */
+ if (__netif_subqueue_stopped(adapter->netdev, i) &&
+ atomic_read(&txo->q.used) < txo->q.len / 2) {
+ netif_wake_subqueue(adapter->netdev, i);
+ }
+
+ adapter->drv_stats.be_tx_events++;
+ txo->stats.be_tx_compl += tx_compl;
+ }
}
mcc_compl = be_process_mcc(adapter, &status);
- napi_complete(napi);
-
if (mcc_compl) {
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl);
}
- if (tx_compl) {
- be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl);
-
- atomic_sub(num_wrbs, &txq->used);
-
- /* As Tx wrbs have been freed up, wake up netdev queue if
- * it was stopped due to lack of tx wrbs.
- */
- if (netif_queue_stopped(adapter->netdev) &&
- atomic_read(&txq->used) < txq->len / 2) {
- netif_wake_queue(adapter->netdev);
- }
-
- tx_stats(adapter)->be_tx_events++;
- tx_stats(adapter)->be_tx_compl += tx_compl;
- }
+ napi_complete(napi);
+ be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
return 1;
}
@@ -2065,6 +2031,7 @@ 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))
@@ -2092,7 +2059,9 @@ static void be_worker(struct work_struct *work)
else
be_cmd_get_stats(adapter, &adapter->stats_cmd);
}
- be_tx_rate_update(adapter);
+
+ for_all_tx_queues(adapter, txo, i)
+ be_tx_rate_update(txo);
for_all_rx_queues(adapter, rxo, i) {
be_rx_rate_update(rxo);
@@ -2290,10 +2259,36 @@ done:
adapter->isr_registered = false;
}
+static void be_rx_queues_clear(struct be_adapter *adapter)
+{
+ struct be_queue_info *q;
+ struct be_rx_obj *rxo;
+ int i;
+
+ for_all_rx_queues(adapter, rxo, i) {
+ q = &rxo->q;
+ if (q->created) {
+ be_cmd_rxq_destroy(adapter, q);
+ /* After the rxq is invalidated, wait for a grace time
+ * of 1ms for all dma to end and the flush compl to
+ * arrive
+ */
+ mdelay(1);
+ be_rx_q_clean(adapter, rxo);
+ }
+
+ /* Clear any residual events */
+ q = &rxo->rx_eq.q;
+ if (q->created)
+ be_eq_clean(adapter, &rxo->rx_eq);
+ }
+}
+
static int be_close(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
struct be_rx_obj *rxo;
+ struct be_tx_obj *txo;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
int vec, i;
@@ -2311,10 +2306,11 @@ static int be_close(struct net_device *netdev)
napi_disable(&tx_eq->napi);
if (lancer_chip(adapter)) {
- be_cq_notify(adapter, adapter->tx_obj.cq.id, false, 0);
be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
for_all_rx_queues(adapter, rxo, i)
be_cq_notify(adapter, rxo->cq.id, false, 0);
+ for_all_tx_queues(adapter, txo, i)
+ be_cq_notify(adapter, txo->cq.id, false, 0);
}
if (msix_enabled(adapter)) {
@@ -2333,8 +2329,43 @@ static int be_close(struct net_device *netdev)
/* Wait for all pending tx completions to arrive so that
* all tx skbs are freed.
*/
- be_tx_compl_clean(adapter);
+ for_all_tx_queues(adapter, txo, i)
+ be_tx_compl_clean(adapter, txo);
+
+ be_rx_queues_clear(adapter);
+ return 0;
+}
+
+static int be_rx_queues_setup(struct be_adapter *adapter)
+{
+ struct be_rx_obj *rxo;
+ int rc, i;
+ u8 rsstable[MAX_RSS_QS];
+
+ for_all_rx_queues(adapter, rxo, i) {
+ rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
+ rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE,
+ adapter->if_handle,
+ (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
+ if (rc)
+ return rc;
+ }
+
+ if (be_multi_rxq(adapter)) {
+ for_all_rss_queues(adapter, rxo, i)
+ rsstable[i] = rxo->rss_id;
+ rc = be_cmd_rss_config(adapter, rsstable,
+ adapter->num_rx_qs - 1);
+ if (rc)
+ return rc;
+ }
+
+ /* First time posting */
+ for_all_rx_queues(adapter, rxo, i) {
+ be_post_rx_frags(rxo, GFP_KERNEL);
+ napi_enable(&rxo->rx_eq.napi);
+ }
return 0;
}
@@ -2348,10 +2379,10 @@ static int be_open(struct net_device *netdev)
u8 mac_speed;
u16 link_speed;
- for_all_rx_queues(adapter, rxo, i) {
- be_post_rx_frags(rxo, GFP_KERNEL);
- napi_enable(&rxo->rx_eq.napi);
- }
+ status = be_rx_queues_setup(adapter);
+ if (status)
+ goto err;
+
napi_enable(&tx_eq->napi);
be_irq_register(adapter);
@@ -2480,6 +2511,8 @@ static int be_setup(struct be_adapter *adapter)
int status;
u8 mac[ETH_ALEN];
+ be_cmd_req_native_mode(adapter);
+
cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST;
@@ -2539,6 +2572,9 @@ static int be_setup(struct be_adapter *adapter)
if (status != 0)
goto tx_qs_destroy;
+ /* Allow all priorities by default. A GRP5 evt may modify this */
+ adapter->vlan_prio_bmap = 0xff;
+
status = be_mcc_queues_create(adapter);
if (status != 0)
goto rx_qs_destroy;
@@ -2584,6 +2620,8 @@ static int be_clear(struct be_adapter *adapter)
be_cmd_if_destroy(adapter, adapter->if_handle, 0);
+ adapter->be3_native = 0;
+
/* tell fw we're done with firing cmds */
be_cmd_fw_clean(adapter);
return 0;
@@ -2901,7 +2939,6 @@ static struct net_device_ops be_netdev_ops = {
.ndo_set_mac_address = be_mac_addr_set,
.ndo_change_mtu = be_change_mtu,
.ndo_validate_addr = eth_validate_addr,
- .ndo_vlan_rx_register = be_vlan_register,
.ndo_vlan_rx_add_vid = be_vlan_add_vid,
.ndo_vlan_rx_kill_vid = be_vlan_rem_vid,
.ndo_set_vf_mac = be_set_vf_mac,
@@ -2925,12 +2962,9 @@ static void be_netdev_init(struct net_device *netdev)
netdev->features |= netdev->hw_features |
NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
- netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO |
+ netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
- if (lancer_chip(adapter))
- netdev->vlan_features |= NETIF_F_TSO6;
-
netdev->flags |= IFF_MULTICAST;
/* Default settings for Rx and Tx flow control */
@@ -3185,7 +3219,16 @@ static int be_get_config(struct be_adapter *adapter)
if (status)
return status;
- be_cmd_check_native_mode(adapter);
+ 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;
}
@@ -3288,7 +3331,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
goto disable_dev;
pci_set_master(pdev);
- netdev = alloc_etherdev(sizeof(struct be_adapter));
+ netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS);
if (netdev == NULL) {
status = -ENOMEM;
goto rel_reg;
@@ -3360,6 +3403,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto stats_clean;
+ /* The INTR bit may be set in the card when probed by a kdump kernel
+ * after a crash.
+ */
+ if (!lancer_chip(adapter))
+ be_intr_set(adapter, false);
+
be_msix_enable(adapter);
INIT_DELAYED_WORK(&adapter->work, be_worker);
@@ -3396,6 +3445,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
}
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;
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index a1b8c8b8010b..45e45e8d3d66 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -7,6 +7,7 @@
* May 1999, Al Viro: proper release of /proc/net/bmac entry, switched to
* dynamic procfs inode.
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -1014,7 +1015,6 @@ static void bmac_set_multicast(struct net_device *dev)
static void bmac_set_multicast(struct net_device *dev)
{
struct netdev_hw_addr *ha;
- char *addrs;
int i;
unsigned short rx_cfg;
u32 crc;
@@ -1038,12 +1038,7 @@ static void bmac_set_multicast(struct net_device *dev)
for(i = 0; i < 4; i++) hash_table[i] = 0;
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- if(!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (crc & 0xf);
}
diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/bna/bfa_cee.c
index f7b789a3b217..39e5ab9fde59 100644
--- a/drivers/net/bna/bfa_cee.c
+++ b/drivers/net/bna/bfa_cee.c
@@ -223,44 +223,56 @@ bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m)
}
/**
- * bfa_cee_hbfail()
+ * bfa_cee_notify()
*
* @brief CEE module heart-beat failure handler.
+ * @brief CEE module IOC event handler.
*
- * @param[in] Pointer to the CEE module data structure.
+ * @param[in] IOC event type
*
* @return void
*/
static void
-bfa_cee_hbfail(void *arg)
+bfa_cee_notify(void *arg, enum bfa_ioc_event event)
{
struct bfa_cee *cee;
cee = (struct bfa_cee *) arg;
- if (cee->get_attr_pending == true) {
- cee->get_attr_status = BFA_STATUS_FAILED;
- cee->get_attr_pending = false;
- if (cee->cbfn.get_attr_cbfn) {
- cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
- BFA_STATUS_FAILED);
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ if (cee->get_attr_pending == true) {
+ cee->get_attr_status = BFA_STATUS_FAILED;
+ cee->get_attr_pending = false;
+ if (cee->cbfn.get_attr_cbfn) {
+ cee->cbfn.get_attr_cbfn(
+ cee->cbfn.get_attr_cbarg,
+ BFA_STATUS_FAILED);
+ }
}
- }
- if (cee->get_stats_pending == true) {
- cee->get_stats_status = BFA_STATUS_FAILED;
- cee->get_stats_pending = false;
- if (cee->cbfn.get_stats_cbfn) {
- cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
- BFA_STATUS_FAILED);
+ if (cee->get_stats_pending == true) {
+ cee->get_stats_status = BFA_STATUS_FAILED;
+ cee->get_stats_pending = false;
+ if (cee->cbfn.get_stats_cbfn) {
+ cee->cbfn.get_stats_cbfn(
+ cee->cbfn.get_stats_cbarg,
+ BFA_STATUS_FAILED);
+ }
}
- }
- if (cee->reset_stats_pending == true) {
- cee->reset_stats_status = BFA_STATUS_FAILED;
- cee->reset_stats_pending = false;
- if (cee->cbfn.reset_stats_cbfn) {
- cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
- BFA_STATUS_FAILED);
+ if (cee->reset_stats_pending == true) {
+ cee->reset_stats_status = BFA_STATUS_FAILED;
+ cee->reset_stats_pending = false;
+ if (cee->cbfn.reset_stats_cbfn) {
+ cee->cbfn.reset_stats_cbfn(
+ cee->cbfn.reset_stats_cbarg,
+ BFA_STATUS_FAILED);
+ }
}
+ break;
+
+ default:
+ break;
}
}
@@ -286,6 +298,7 @@ bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc,
cee->ioc = ioc;
bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
- bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
- bfa_nw_ioc_hbfail_register(cee->ioc, &cee->hbfail);
+ bfa_q_qe_init(&cee->ioc_notify);
+ bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee);
+ bfa_nw_ioc_notify_register(cee->ioc, &cee->ioc_notify);
}
diff --git a/drivers/net/bna/bfa_cee.h b/drivers/net/bna/bfa_cee.h
index 20543d15b64f..58d54e98d595 100644
--- a/drivers/net/bna/bfa_cee.h
+++ b/drivers/net/bna/bfa_cee.h
@@ -25,7 +25,6 @@
typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, enum bfa_status status);
typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, enum bfa_status status);
typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, enum bfa_status status);
-typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, enum bfa_status status);
struct bfa_cee_cbfn {
bfa_cee_get_attr_cbfn_t get_attr_cbfn;
@@ -45,7 +44,7 @@ struct bfa_cee {
enum bfa_status get_stats_status;
enum bfa_status reset_stats_status;
struct bfa_cee_cbfn cbfn;
- struct bfa_ioc_hbfail_notify hbfail;
+ struct bfa_ioc_notify ioc_notify;
struct bfa_cee_attr *attr;
struct bfa_cee_stats *stats;
struct bfa_dma attr_dma;
diff --git a/drivers/net/bna/bfa_sm.h b/drivers/net/bna/bfa_cs.h
index 46462c49b6f9..3da1a946ccdd 100644
--- a/drivers/net/bna/bfa_sm.h
+++ b/drivers/net/bna/bfa_cs.h
@@ -11,20 +11,24 @@
* General Public License for more details.
*/
/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*/
/**
- * @file bfasm.h State machine defines
+ * @file bfa_cs.h BFA common services
*/
-#ifndef __BFA_SM_H__
-#define __BFA_SM_H__
+#ifndef __BFA_CS_H__
+#define __BFA_CS_H__
#include "cna.h"
+/**
+ * @ BFA state machine interfaces
+ */
+
typedef void (*bfa_sm_t)(void *sm, int event);
/**
@@ -33,7 +37,7 @@ typedef void (*bfa_sm_t)(void *sm, int event);
* otype - object type, eg. struct bfa_ioc
* etype - object type, eg. enum ioc_event
*/
-#define bfa_sm_state_decl(oc, st, otype, etype) \
+#define bfa_sm_state_decl(oc, st, otype, etype) \
static void oc ## _sm_ ## st(otype * fsm, etype event)
#define bfa_sm_set_state(_sm, _state) ((_sm)->sm = (bfa_sm_t)(_state))
@@ -49,7 +53,7 @@ struct bfa_sm_table {
int state; /*!< state machine encoding */
char *name; /*!< state name for display */
};
-#define BFA_SM(_sm) ((bfa_sm_t)(_sm))
+#define BFA_SM(_sm) ((bfa_sm_t)(_sm))
/**
* State machine with entry actions.
@@ -62,18 +66,18 @@ typedef void (*bfa_fsm_t)(void *fsm, int event);
* otype - object type, eg. struct bfa_ioc
* etype - object type, eg. enum ioc_event
*/
-#define bfa_fsm_state_decl(oc, st, otype, etype) \
- static void oc ## _sm_ ## st(otype * fsm, etype event); \
+#define bfa_fsm_state_decl(oc, st, otype, etype) \
+ static void oc ## _sm_ ## st(otype * fsm, etype event); \
static void oc ## _sm_ ## st ## _entry(otype * fsm)
-#define bfa_fsm_set_state(_fsm, _state) do { \
- (_fsm)->fsm = (bfa_fsm_t)(_state); \
- _state ## _entry(_fsm); \
+#define bfa_fsm_set_state(_fsm, _state) do { \
+ (_fsm)->fsm = (bfa_fsm_t)(_state); \
+ _state ## _entry(_fsm); \
} while (0)
#define bfa_fsm_send_event(_fsm, _event) ((_fsm)->fsm((_fsm), (_event)))
#define bfa_fsm_get_state(_fsm) ((_fsm)->fsm)
-#define bfa_fsm_cmp_state(_fsm, _state) \
+#define bfa_fsm_cmp_state(_fsm, _state) \
((_fsm)->fsm == (bfa_fsm_t)(_state))
static inline int
@@ -85,4 +89,52 @@ bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm)
i++;
return smt[i].state;
}
-#endif
+
+/**
+ * @ Generic wait counter.
+ */
+
+typedef void (*bfa_wc_resume_t) (void *cbarg);
+
+struct bfa_wc {
+ bfa_wc_resume_t wc_resume;
+ void *wc_cbarg;
+ int wc_count;
+};
+
+static inline void
+bfa_wc_up(struct bfa_wc *wc)
+{
+ wc->wc_count++;
+}
+
+static inline void
+bfa_wc_down(struct bfa_wc *wc)
+{
+ wc->wc_count--;
+ if (wc->wc_count == 0)
+ wc->wc_resume(wc->wc_cbarg);
+}
+
+/**
+ * Initialize a waiting counter.
+ */
+static inline void
+bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+{
+ wc->wc_resume = wc_resume;
+ wc->wc_cbarg = wc_cbarg;
+ wc->wc_count = 0;
+ bfa_wc_up(wc);
+}
+
+/**
+ * Wait for counter to reach zero
+ */
+static inline void
+bfa_wc_wait(struct bfa_wc *wc)
+{
+ bfa_wc_down(wc);
+}
+
+#endif /* __BFA_CS_H__ */
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index 2ea0dfe1cedc..b080b3698f48 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -80,7 +80,7 @@ struct bfa_adapter_attr {
enum {
BFA_IOC_DRIVER_LEN = 16,
- BFA_IOC_CHIP_REV_LEN = 8,
+ BFA_IOC_CHIP_REV_LEN = 8,
};
/**
@@ -153,6 +153,7 @@ struct bfa_ioc_drv_stats {
u32 enable_reqs;
u32 disable_replies;
u32 enable_replies;
+ u32 rsvd;
};
/**
@@ -174,7 +175,7 @@ enum bfa_ioc_type {
*/
struct bfa_ioc_attr {
enum bfa_ioc_type ioc_type;
- enum bfa_ioc_state state; /*!< IOC state */
+ enum bfa_ioc_state state; /*!< IOC state */
struct bfa_adapter_attr adapter_attr; /*!< HBA attributes */
struct bfa_ioc_driver_attr driver_attr; /*!< driver attr */
struct bfa_ioc_pci_attr pci_attr;
diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/bna/bfa_defs_mfg_comm.h
index fdd677618361..885ef3afdd4e 100644
--- a/drivers/net/bna/bfa_defs_mfg_comm.h
+++ b/drivers/net/bna/bfa_defs_mfg_comm.h
@@ -192,14 +192,14 @@ do { \
* VPD vendor tag
*/
enum {
- BFA_MFG_VPD_UNKNOWN = 0, /*!< vendor unknown */
- BFA_MFG_VPD_IBM = 1, /*!< vendor IBM */
- BFA_MFG_VPD_HP = 2, /*!< vendor HP */
- BFA_MFG_VPD_DELL = 3, /*!< vendor DELL */
- BFA_MFG_VPD_PCI_IBM = 0x08, /*!< PCI VPD IBM */
- BFA_MFG_VPD_PCI_HP = 0x10, /*!< PCI VPD HP */
- BFA_MFG_VPD_PCI_DELL = 0x20, /*!< PCI VPD DELL */
- BFA_MFG_VPD_PCI_BRCD = 0xf8, /*!< PCI VPD Brocade */
+ BFA_MFG_VPD_UNKNOWN = 0, /*!< vendor unknown */
+ BFA_MFG_VPD_IBM = 1, /*!< vendor IBM */
+ BFA_MFG_VPD_HP = 2, /*!< vendor HP */
+ BFA_MFG_VPD_DELL = 3, /*!< vendor DELL */
+ BFA_MFG_VPD_PCI_IBM = 0x08, /*!< PCI VPD IBM */
+ BFA_MFG_VPD_PCI_HP = 0x10, /*!< PCI VPD HP */
+ BFA_MFG_VPD_PCI_DELL = 0x20, /*!< PCI VPD DELL */
+ BFA_MFG_VPD_PCI_BRCD = 0xf8, /*!< PCI VPD Brocade */
};
/**
@@ -212,8 +212,8 @@ struct bfa_mfg_vpd {
u8 vpd_sig[3]; /*!< characters 'V', 'P', 'D' */
u8 chksum; /*!< u8 checksum */
u8 vendor; /*!< vendor */
- u8 len; /*!< vpd data length excluding header */
- u8 rsv;
+ u8 len; /*!< vpd data length excluding header */
+ u8 rsv;
u8 data[BFA_MFG_VPD_LEN]; /*!< vpd data */
};
diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/bna/bfa_defs_status.h
index af951126375c..7c5fe6c2e80e 100644
--- a/drivers/net/bna/bfa_defs_status.h
+++ b/drivers/net/bna/bfa_defs_status.h
@@ -25,95 +25,95 @@
* comments are supported
*/
enum bfa_status {
- BFA_STATUS_OK = 0,
- BFA_STATUS_FAILED = 1,
- BFA_STATUS_EINVAL = 2,
- BFA_STATUS_ENOMEM = 3,
- BFA_STATUS_ENOSYS = 4,
- BFA_STATUS_ETIMER = 5,
- BFA_STATUS_EPROTOCOL = 6,
- BFA_STATUS_ENOFCPORTS = 7,
- BFA_STATUS_NOFLASH = 8,
- BFA_STATUS_BADFLASH = 9,
- BFA_STATUS_SFP_UNSUPP = 10,
+ BFA_STATUS_OK = 0,
+ BFA_STATUS_FAILED = 1,
+ BFA_STATUS_EINVAL = 2,
+ BFA_STATUS_ENOMEM = 3,
+ BFA_STATUS_ENOSYS = 4,
+ BFA_STATUS_ETIMER = 5,
+ BFA_STATUS_EPROTOCOL = 6,
+ BFA_STATUS_ENOFCPORTS = 7,
+ BFA_STATUS_NOFLASH = 8,
+ BFA_STATUS_BADFLASH = 9,
+ BFA_STATUS_SFP_UNSUPP = 10,
BFA_STATUS_UNKNOWN_VFID = 11,
BFA_STATUS_DATACORRUPTED = 12,
- BFA_STATUS_DEVBUSY = 13,
- BFA_STATUS_ABORTED = 14,
- BFA_STATUS_NODEV = 15,
- BFA_STATUS_HDMA_FAILED = 16,
+ BFA_STATUS_DEVBUSY = 13,
+ BFA_STATUS_ABORTED = 14,
+ BFA_STATUS_NODEV = 15,
+ BFA_STATUS_HDMA_FAILED = 16,
BFA_STATUS_FLASH_BAD_LEN = 17,
BFA_STATUS_UNKNOWN_LWWN = 18,
BFA_STATUS_UNKNOWN_RWWN = 19,
- BFA_STATUS_FCPT_LS_RJT = 20,
+ BFA_STATUS_FCPT_LS_RJT = 20,
BFA_STATUS_VPORT_EXISTS = 21,
- BFA_STATUS_VPORT_MAX = 22,
+ BFA_STATUS_VPORT_MAX = 22,
BFA_STATUS_UNSUPP_SPEED = 23,
- BFA_STATUS_INVLD_DFSZ = 24,
- BFA_STATUS_CNFG_FAILED = 25,
- BFA_STATUS_CMD_NOTSUPP = 26,
- BFA_STATUS_NO_ADAPTER = 27,
- BFA_STATUS_LINKDOWN = 28,
- BFA_STATUS_FABRIC_RJT = 29,
+ BFA_STATUS_INVLD_DFSZ = 24,
+ BFA_STATUS_CNFG_FAILED = 25,
+ BFA_STATUS_CMD_NOTSUPP = 26,
+ BFA_STATUS_NO_ADAPTER = 27,
+ BFA_STATUS_LINKDOWN = 28,
+ BFA_STATUS_FABRIC_RJT = 29,
BFA_STATUS_UNKNOWN_VWWN = 30,
BFA_STATUS_NSLOGIN_FAILED = 31,
- BFA_STATUS_NO_RPORTS = 32,
+ BFA_STATUS_NO_RPORTS = 32,
BFA_STATUS_NSQUERY_FAILED = 33,
BFA_STATUS_PORT_OFFLINE = 34,
BFA_STATUS_RPORT_OFFLINE = 35,
BFA_STATUS_TGTOPEN_FAILED = 36,
- BFA_STATUS_BAD_LUNS = 37,
- BFA_STATUS_IO_FAILURE = 38,
- BFA_STATUS_NO_FABRIC = 39,
- BFA_STATUS_EBADF = 40,
- BFA_STATUS_EINTR = 41,
- BFA_STATUS_EIO = 42,
- BFA_STATUS_ENOTTY = 43,
- BFA_STATUS_ENXIO = 44,
- BFA_STATUS_EFOPEN = 45,
+ BFA_STATUS_BAD_LUNS = 37,
+ BFA_STATUS_IO_FAILURE = 38,
+ BFA_STATUS_NO_FABRIC = 39,
+ BFA_STATUS_EBADF = 40,
+ BFA_STATUS_EINTR = 41,
+ BFA_STATUS_EIO = 42,
+ BFA_STATUS_ENOTTY = 43,
+ BFA_STATUS_ENXIO = 44,
+ BFA_STATUS_EFOPEN = 45,
BFA_STATUS_VPORT_WWN_BP = 46,
BFA_STATUS_PORT_NOT_DISABLED = 47,
- BFA_STATUS_BADFRMHDR = 48,
- BFA_STATUS_BADFRMSZ = 49,
- BFA_STATUS_MISSINGFRM = 50,
- BFA_STATUS_LINKTIMEOUT = 51,
+ BFA_STATUS_BADFRMHDR = 48,
+ BFA_STATUS_BADFRMSZ = 49,
+ BFA_STATUS_MISSINGFRM = 50,
+ BFA_STATUS_LINKTIMEOUT = 51,
BFA_STATUS_NO_FCPIM_NEXUS = 52,
BFA_STATUS_CHECKSUM_FAIL = 53,
- BFA_STATUS_GZME_FAILED = 54,
+ BFA_STATUS_GZME_FAILED = 54,
BFA_STATUS_SCSISTART_REQD = 55,
- BFA_STATUS_IOC_FAILURE = 56,
- BFA_STATUS_INVALID_WWN = 57,
- BFA_STATUS_MISMATCH = 58,
- BFA_STATUS_IOC_ENABLED = 59,
+ BFA_STATUS_IOC_FAILURE = 56,
+ BFA_STATUS_INVALID_WWN = 57,
+ BFA_STATUS_MISMATCH = 58,
+ BFA_STATUS_IOC_ENABLED = 59,
BFA_STATUS_ADAPTER_ENABLED = 60,
- BFA_STATUS_IOC_NON_OP = 61,
+ BFA_STATUS_IOC_NON_OP = 61,
BFA_STATUS_ADDR_MAP_FAILURE = 62,
- BFA_STATUS_SAME_NAME = 63,
- BFA_STATUS_PENDING = 64,
- BFA_STATUS_8G_SPD = 65,
- BFA_STATUS_4G_SPD = 66,
+ BFA_STATUS_SAME_NAME = 63,
+ BFA_STATUS_PENDING = 64,
+ BFA_STATUS_8G_SPD = 65,
+ BFA_STATUS_4G_SPD = 66,
BFA_STATUS_AD_IS_ENABLE = 67,
- BFA_STATUS_EINVAL_TOV = 68,
+ BFA_STATUS_EINVAL_TOV = 68,
BFA_STATUS_EINVAL_QDEPTH = 69,
BFA_STATUS_VERSION_FAIL = 70,
- BFA_STATUS_DIAG_BUSY = 71,
- BFA_STATUS_BEACON_ON = 72,
- BFA_STATUS_BEACON_OFF = 73,
- BFA_STATUS_LBEACON_ON = 74,
- BFA_STATUS_LBEACON_OFF = 75,
+ BFA_STATUS_DIAG_BUSY = 71,
+ BFA_STATUS_BEACON_ON = 72,
+ BFA_STATUS_BEACON_OFF = 73,
+ BFA_STATUS_LBEACON_ON = 74,
+ BFA_STATUS_LBEACON_OFF = 75,
BFA_STATUS_PORT_NOT_INITED = 76,
BFA_STATUS_RPSC_ENABLED = 77,
- BFA_STATUS_ENOFSAVE = 78,
- BFA_STATUS_BAD_FILE = 79,
- BFA_STATUS_RLIM_EN = 80,
- BFA_STATUS_RLIM_DIS = 81,
- BFA_STATUS_IOC_DISABLED = 82,
- BFA_STATUS_ADAPTER_DISABLED = 83,
- BFA_STATUS_BIOS_DISABLED = 84,
- BFA_STATUS_AUTH_ENABLED = 85,
- BFA_STATUS_AUTH_DISABLED = 86,
- BFA_STATUS_ERROR_TRL_ENABLED = 87,
- BFA_STATUS_ERROR_QOS_ENABLED = 88,
+ BFA_STATUS_ENOFSAVE = 78,
+ BFA_STATUS_BAD_FILE = 79,
+ BFA_STATUS_RLIM_EN = 80,
+ BFA_STATUS_RLIM_DIS = 81,
+ BFA_STATUS_IOC_DISABLED = 82,
+ BFA_STATUS_ADAPTER_DISABLED = 83,
+ BFA_STATUS_BIOS_DISABLED = 84,
+ BFA_STATUS_AUTH_ENABLED = 85,
+ BFA_STATUS_AUTH_DISABLED = 86,
+ BFA_STATUS_ERROR_TRL_ENABLED = 87,
+ BFA_STATUS_ERROR_QOS_ENABLED = 88,
BFA_STATUS_NO_SFP_DEV = 89,
BFA_STATUS_MEMTEST_FAILED = 90,
BFA_STATUS_INVALID_DEVID = 91,
@@ -190,7 +190,7 @@ enum bfa_status {
BFA_STATUS_FLASH_CKFAIL = 162,
BFA_STATUS_TRUNK_UNSUPP = 163,
BFA_STATUS_TRUNK_ENABLED = 164,
- BFA_STATUS_TRUNK_DISABLED = 165,
+ BFA_STATUS_TRUNK_DISABLED = 165,
BFA_STATUS_TRUNK_ERROR_TRL_ENABLED = 166,
BFA_STATUS_BOOT_CODE_UPDATED = 167,
BFA_STATUS_BOOT_VERSION = 168,
@@ -198,8 +198,8 @@ enum bfa_status {
BFA_STATUS_INVALID_CARDTYPE = 170,
BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 171,
BFA_STATUS_IM_VLAN_OVER_TEAM_DELETE_FAILED = 172,
- BFA_STATUS_ETHBOOT_ENABLED = 173,
- BFA_STATUS_ETHBOOT_DISABLED = 174,
+ BFA_STATUS_ETHBOOT_ENABLED = 173,
+ BFA_STATUS_ETHBOOT_DISABLED = 174,
BFA_STATUS_IOPROFILE_OFF = 175,
BFA_STATUS_NO_PORT_INSTANCE = 176,
BFA_STATUS_BOOT_CODE_TIMEDOUT = 177,
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index fcb9bb3169e0..126b0aac9f94 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -58,6 +58,7 @@ static bool bfa_nw_auto_recover = true;
/*
* forward declarations
*/
+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);
@@ -68,9 +69,10 @@ static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);
static void bfa_ioc_recover(struct bfa_ioc *ioc);
static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
+static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
@@ -107,7 +109,7 @@ enum ioc_event {
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_PFAILED = 9, /*!< 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 */
@@ -156,7 +158,7 @@ enum iocpf_event {
IOCPF_E_ENABLE = 1, /*!< IOCPF enable request */
IOCPF_E_DISABLE = 2, /*!< IOCPF disable request */
IOCPF_E_STOP = 3, /*!< stop on driver detach */
- IOCPF_E_FWREADY = 4, /*!< f/w initialization done */
+ IOCPF_E_FWREADY = 4, /*!< f/w initialization done */
IOCPF_E_FWRSP_ENABLE = 5, /*!< enable f/w response */
IOCPF_E_FWRSP_DISABLE = 6, /*!< disable f/w response */
IOCPF_E_FAIL = 7, /*!< failure notice by ioc sm */
@@ -239,7 +241,7 @@ bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -272,7 +274,7 @@ bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -294,12 +296,12 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
/* !!! 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);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_initfail(ioc);
break;
@@ -316,7 +318,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -344,14 +346,14 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
del_timer(&ioc->ioc_timer);
/* 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);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_getattrfail(ioc);
break;
@@ -364,7 +366,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -387,7 +389,7 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
bfa_ioc_hb_stop(ioc);
/* !!! fall through !!! */
@@ -398,12 +400,12 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
else
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_fail(ioc);
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -434,7 +436,7 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -465,7 +467,7 @@ bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -485,13 +487,13 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
- case IOC_E_PFAILED:
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
/**
* Initialization retry failed.
*/
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- if (event != IOC_E_PFAILED)
+ if (event != IOC_E_PFFAILED)
bfa_iocpf_initfail(ioc);
break;
@@ -512,7 +514,7 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -546,7 +548,7 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -579,7 +581,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(iocpf->ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -589,6 +591,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
{
+ bfa_ioc_hw_sem_init(iocpf->ioc);
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -631,7 +634,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -675,7 +678,7 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -714,7 +717,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -762,7 +765,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -813,7 +816,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -856,7 +859,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -898,7 +901,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -927,7 +930,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -937,6 +940,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
{
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_ioc_pf_disabled(iocpf->ioc);
}
@@ -957,7 +961,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -1009,7 +1013,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -1038,7 +1042,7 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -1053,7 +1057,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
/**
* Flush any queued up mailbox requests.
*/
- bfa_ioc_mbox_hbfail(iocpf->ioc);
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -1093,7 +1097,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -1115,7 +1119,7 @@ bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
break;
default:
- bfa_sm_fault(iocpf->ioc, event);
+ bfa_sm_fault(event);
}
}
@@ -1123,23 +1127,28 @@ bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
* BFA IOC private functions
*/
+/**
+ * Notify common modules registered for notification.
+ */
static void
-bfa_ioc_disable_comp(struct bfa_ioc *ioc)
+bfa_ioc_event_notify(struct bfa_ioc *ioc, enum bfa_ioc_event event)
{
+ struct bfa_ioc_notify *notify;
struct list_head *qe;
- struct bfa_ioc_hbfail_notify *notify;
-
- ioc->cbfn->disable_cbfn(ioc->bfa);
- /**
- * Notify common modules registered for notification.
- */
- list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify *) qe;
- notify->cbfn(notify->cbarg);
+ list_for_each(qe, &ioc->notify_q) {
+ notify = (struct bfa_ioc_notify *)qe;
+ notify->cbfn(notify->cbarg, event);
}
}
+static void
+bfa_ioc_disable_comp(struct bfa_ioc *ioc)
+{
+ ioc->cbfn->disable_cbfn(ioc->bfa);
+ bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
+}
+
bool
bfa_nw_ioc_sem_get(void __iomem *sem_reg)
{
@@ -1169,6 +1178,29 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg)
}
static void
+bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)
+{
+ struct bfi_ioc_image_hdr fwhdr;
+ u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ if (fwstate == BFI_IOC_UNINIT)
+ return;
+
+ bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+
+ if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+ return;
+
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+
+ /*
+ * Try to lock and then unlock the semaphore.
+ */
+ readl(ioc->ioc_regs.ioc_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+}
+
+static void
bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
{
u32 r32;
@@ -1638,7 +1670,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
* Cleanup any pending requests.
*/
static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc *ioc)
{
struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
struct bfa_mbox_cmd *cmd;
@@ -1650,17 +1682,11 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
static void
bfa_ioc_fail_notify(struct bfa_ioc *ioc)
{
- struct list_head *qe;
- struct bfa_ioc_hbfail_notify *notify;
-
/**
* Notify driver and common modules registered for notification.
*/
ioc->cbfn->hbfail_cbfn(ioc->bfa);
- list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify *) qe;
- notify->cbfn(notify->cbarg);
- }
+ bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
}
static void
@@ -1684,7 +1710,7 @@ bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
static void
bfa_ioc_pf_failed(struct bfa_ioc *ioc)
{
- bfa_fsm_send_event(ioc, IOC_E_PFAILED);
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
}
static void
@@ -1839,7 +1865,7 @@ bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
ioc->iocpf.ioc = ioc;
bfa_ioc_mbox_attach(ioc);
- INIT_LIST_HEAD(&ioc->hb_notify_q);
+ INIT_LIST_HEAD(&ioc->notify_q);
bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
bfa_fsm_send_event(ioc, IOC_E_RESET);
@@ -1969,6 +1995,8 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
* mailbox is free -- queue command to firmware
*/
bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+
+ return;
}
/**
@@ -2001,18 +2029,30 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
void
bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)
{
+ bfa_ioc_stats(ioc, ioc_hbfails);
+ bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
bfa_fsm_send_event(ioc, IOC_E_HWERROR);
}
/**
+ * return true if IOC is disabled
+ */
+bool
+bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc)
+{
+ return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
+ bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
+}
+
+/**
* Add to IOC heartbeat failure notification queue. To be used by common
* modules such as cee, port, diag.
*/
void
-bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
- struct bfa_ioc_hbfail_notify *notify)
+bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
+ struct bfa_ioc_notify *notify)
{
- list_add_tail(&notify->qe, &ioc->hb_notify_q);
+ list_add_tail(&notify->qe, &ioc->notify_q);
}
#define BFA_MFG_NAME "Brocade"
@@ -2217,6 +2257,7 @@ bfa_ioc_recover(struct bfa_ioc *ioc)
{
pr_crit("Heart Beat of IOC has failed\n");
bfa_ioc_stats(ioc, ioc_hbfails);
+ bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index bd48abee781f..bda866ba6e90 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -19,7 +19,7 @@
#ifndef __BFA_IOC_H__
#define __BFA_IOC_H__
-#include "bfa_sm.h"
+#include "bfa_cs.h"
#include "bfi.h"
#include "cna.h"
@@ -97,9 +97,12 @@ struct bfa_ioc_regs {
/**
* IOC Mailbox structures
*/
+typedef void (*bfa_mbox_cmd_cbfn_t)(void *cbarg);
struct bfa_mbox_cmd {
struct list_head qe;
- u32 msg[BFI_IOC_MSGSZ];
+ bfa_mbox_cmd_cbfn_t cbfn;
+ void *cbarg;
+ u32 msg[BFI_IOC_MSGSZ];
};
/**
@@ -130,6 +133,23 @@ struct bfa_ioc_cbfn {
};
/**
+ * IOC event notification mechanism.
+ */
+enum bfa_ioc_event {
+ BFA_IOC_E_ENABLED = 1,
+ BFA_IOC_E_DISABLED = 2,
+ BFA_IOC_E_FAILED = 3,
+};
+
+typedef void (*bfa_ioc_notify_cbfn_t)(void *, enum bfa_ioc_event);
+
+struct bfa_ioc_notify {
+ struct list_head qe;
+ bfa_ioc_notify_cbfn_t cbfn;
+ void *cbarg;
+};
+
+/**
* Heartbeat failure notification queue element.
*/
struct bfa_ioc_hbfail_notify {
@@ -141,7 +161,7 @@ struct bfa_ioc_hbfail_notify {
/**
* Initialize a heartbeat failure notification structure
*/
-#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do { \
+#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do { \
(__notify)->cbfn = (__cbfn); \
(__notify)->cbarg = (__cbarg); \
} while (0)
@@ -155,25 +175,25 @@ struct bfa_iocpf {
struct bfa_ioc {
bfa_fsm_t fsm;
- struct bfa *bfa;
- struct bfa_pcidev pcidev;
- struct timer_list ioc_timer;
- struct timer_list iocpf_timer;
- struct timer_list sem_timer;
+ struct bfa *bfa;
+ struct bfa_pcidev pcidev;
+ struct timer_list ioc_timer;
+ struct timer_list iocpf_timer;
+ struct timer_list sem_timer;
struct timer_list hb_timer;
u32 hb_count;
- struct list_head hb_notify_q;
+ struct list_head notify_q;
void *dbg_fwsave;
int dbg_fwsave_len;
bool dbg_fwsave_once;
enum bfi_mclass ioc_mc;
- struct bfa_ioc_regs ioc_regs;
+ 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 */
+ bool stats_busy; /*!< outstanding stats */
u8 port_id;
struct bfa_dma attr_dma;
@@ -217,9 +237,11 @@ struct bfa_ioc_hwif {
BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++)
+#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)->ctdev) ? \
(((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \
BFI_IMAGE_CB_FC)
#define BFA_IOC_FW_SMEM_SIZE(__ioc) \
@@ -263,9 +285,10 @@ void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
void bfa_nw_ioc_disable(struct bfa_ioc *ioc);
void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
+bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc);
void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
-void bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
- struct bfa_ioc_hbfail_notify *notify);
+void bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
+ struct bfa_ioc_notify *notify);
bool bfa_nw_ioc_sem_get(void __iomem *sem_reg);
void bfa_nw_ioc_sem_release(void __iomem *sem_reg);
void bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc);
diff --git a/drivers/net/bna/bfa_wc.h b/drivers/net/bna/bfa_wc.h
deleted file mode 100644
index d0e4caee67b0..000000000000
--- a/drivers/net/bna/bfa_wc.h
+++ /dev/null
@@ -1,69 +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 bfa_wc.h Generic wait counter.
- */
-
-#ifndef __BFA_WC_H__
-#define __BFA_WC_H__
-
-typedef void (*bfa_wc_resume_t) (void *cbarg);
-
-struct bfa_wc {
- bfa_wc_resume_t wc_resume;
- void *wc_cbarg;
- int wc_count;
-};
-
-static inline void
-bfa_wc_up(struct bfa_wc *wc)
-{
- wc->wc_count++;
-}
-
-static inline void
-bfa_wc_down(struct bfa_wc *wc)
-{
- wc->wc_count--;
- if (wc->wc_count == 0)
- wc->wc_resume(wc->wc_cbarg);
-}
-
-/**
- * Initialize a waiting counter.
- */
-static inline void
-bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
-{
- wc->wc_resume = wc_resume;
- wc->wc_cbarg = wc_cbarg;
- wc->wc_count = 0;
- bfa_wc_up(wc);
-}
-
-/**
- * Wait for counter to reach zero
- */
-static inline void
-bfa_wc_wait(struct bfa_wc *wc)
-{
- bfa_wc_down(wc);
-}
-
-#endif
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index 6050379526f7..088211c2724f 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -51,13 +51,13 @@ struct bfi_mhdr {
};
#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \
- (_mh).msg_class = (_mc); \
+ (_mh).msg_class = (_mc); \
(_mh).msg_id = (_op); \
(_mh).mtag.h2i.lpu_id = (_lpuid); \
} while (0)
#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \
- (_mh).msg_class = (_mc); \
+ (_mh).msg_class = (_mc); \
(_mh).msg_id = (_op); \
(_mh).mtag.i2htok = (_i2htok); \
} while (0)
@@ -66,7 +66,7 @@ struct bfi_mhdr {
* Message opcodes: 0-127 to firmware, 128-255 to host
*/
#define BFI_I2H_OPCODE_BASE 128
-#define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE)
+#define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE)
/**
****************************************************************************
@@ -186,7 +186,7 @@ enum bfi_mclass {
#define BFI_BOOT_TYPE_OFF 8
#define BFI_BOOT_LOADER_OFF 12
-#define BFI_BOOT_TYPE_NORMAL 0
+#define BFI_BOOT_TYPE_NORMAL 0
#define BFI_BOOT_TYPE_FLASH 1
#define BFI_BOOT_TYPE_MEMTEST 2
@@ -211,9 +211,9 @@ enum bfi_ioc_h2i_msgs {
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_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),
};
@@ -289,6 +289,12 @@ struct bfi_ioc_image_hdr {
u32 md5sum[BFI_IOC_MD5SUM_SZ];
};
+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
*/
diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index a287f89b0289..21e9155d6e56 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -13,7 +13,7 @@
#ifndef __BNA_H__
#define __BNA_H__
-#include "bfa_wc.h"
+#include "bfa_cs.h"
#include "bfa_ioc.h"
#include "cna.h"
#include "bfi_ll.h"
@@ -88,7 +88,7 @@ do { \
} while (0)
#define containing_rec(addr, type, field) \
- ((type *)((unsigned char *)(addr) - \
+ ((type *)((unsigned char *)(addr) - \
(unsigned char *)(&((type *)0)->field)))
#define BNA_TXQ_WI_NEEDED(_vectors) (((_vectors) + 3) >> 2)
@@ -101,8 +101,8 @@ do { \
{ \
unsigned int page_index; /* index within a page */ \
void *page_addr; \
- page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1); \
- (_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index); \
+ page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1); \
+ (_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index); \
page_addr = (_qpt_ptr)[((_qe_idx) >> BNA_TXQ_PAGE_INDEX_MAX_SHIFT)];\
(_qe_ptr) = &((struct bna_txq_entry *)(page_addr))[page_index]; \
}
@@ -166,25 +166,25 @@ do { \
(((_q_ptr)->q.producer_index + (_num)) & \
((_q_ptr)->q.q_depth - 1))
-#define BNA_Q_CI_ADD(_q_ptr, _num) \
+#define BNA_Q_CI_ADD(_q_ptr, _num) \
(_q_ptr)->q.consumer_index = \
- (((_q_ptr)->q.consumer_index + (_num)) \
+ (((_q_ptr)->q.consumer_index + (_num)) \
& ((_q_ptr)->q.q_depth - 1))
#define BNA_Q_FREE_COUNT(_q_ptr) \
(BNA_QE_FREE_CNT(&((_q_ptr)->q), (_q_ptr)->q.q_depth))
-#define BNA_Q_IN_USE_COUNT(_q_ptr) \
+#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_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)
+#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) \
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
index 53b14169e363..cb2594c564dc 100644
--- a/drivers/net/bna/bna_ctrl.c
+++ b/drivers/net/bna/bna_ctrl.c
@@ -16,8 +16,7 @@
* www.brocade.com
*/
#include "bna.h"
-#include "bfa_sm.h"
-#include "bfa_wc.h"
+#include "bfa_cs.h"
static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status);
@@ -380,7 +379,7 @@ bna_llport_sm_stopped(struct bna_llport *llport,
break;
default:
- bfa_sm_fault(llport->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -409,7 +408,7 @@ bna_llport_sm_down(struct bna_llport *llport,
break;
default:
- bfa_sm_fault(llport->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -455,7 +454,7 @@ bna_llport_sm_up_resp_wait(struct bna_llport *llport,
break;
default:
- bfa_sm_fault(llport->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -497,7 +496,7 @@ bna_llport_sm_down_resp_wait(struct bna_llport *llport,
break;
default:
- bfa_sm_fault(llport->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -526,7 +525,7 @@ bna_llport_sm_up(struct bna_llport *llport,
break;
default:
- bfa_sm_fault(llport->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -563,7 +562,7 @@ bna_llport_sm_last_resp_wait(struct bna_llport *llport,
break;
default:
- bfa_sm_fault(llport->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -916,7 +915,7 @@ bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event)
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -956,7 +955,7 @@ bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event)
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1001,7 +1000,7 @@ bna_port_sm_pause_init_wait(struct bna_port *port,
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1022,7 +1021,7 @@ bna_port_sm_last_resp_wait(struct bna_port *port,
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1061,7 +1060,7 @@ bna_port_sm_started(struct bna_port *port,
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1086,7 +1085,7 @@ bna_port_sm_pause_cfg_wait(struct bna_port *port,
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1111,7 +1110,7 @@ bna_port_sm_rx_stop_wait(struct bna_port *port,
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1136,7 +1135,7 @@ bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event)
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1161,7 +1160,7 @@ bna_port_sm_chld_stop_wait(struct bna_port *port,
break;
default:
- bfa_sm_fault(port->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1472,7 +1471,7 @@ bna_device_sm_stopped(struct bna_device *device,
break;
default:
- bfa_sm_fault(device->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1512,7 +1511,7 @@ bna_device_sm_ioc_ready_wait(struct bna_device *device,
break;
default:
- bfa_sm_fault(device->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1542,7 +1541,7 @@ bna_device_sm_ready(struct bna_device *device, enum bna_device_event event)
break;
default:
- bfa_sm_fault(device->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1568,7 +1567,7 @@ bna_device_sm_port_stop_wait(struct bna_device *device,
break;
default:
- bfa_sm_fault(device->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1589,7 +1588,7 @@ bna_device_sm_ioc_disable_wait(struct bna_device *device,
break;
default:
- bfa_sm_fault(device->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1622,7 +1621,7 @@ bna_device_sm_failed(struct bna_device *device,
break;
default:
- bfa_sm_fault(device->bna, event);
+ bfa_sm_fault(event);
}
}
diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h
index 6cb89692f5c1..cad233da843a 100644
--- a/drivers/net/bna/bna_hw.h
+++ b/drivers/net/bna/bna_hw.h
@@ -67,7 +67,7 @@ static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] = \
/**
* There are 2 free RIT segment pools:
- * Pool1: 192 segments of 1 RIT entry each
+ * Pool1: 192 segments of 1 RIT entry each
* Pool2: 1 segment of 64 RIT entry
*/
#define BFI_RIT_SEG_POOL1_SIZE 192
@@ -357,14 +357,14 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
* To clear set the value to 0.
* Range : 0x20 to 0x5c
*/
-#define PSS_SEM_LOCK_REG(_num) \
+#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) \
+#define PSS_SEM_STATUS_REG(_num) \
(PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
/**
@@ -1044,7 +1044,7 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
__LPU12HOST_MBOX1_STATUS_BITS))
#define BNA_IS_MBOX_INTR(_intr_status) \
- ((_intr_status) & \
+ ((_intr_status) & \
(__LPU02HOST_MBOX0_STATUS_BITS | \
__LPU02HOST_MBOX1_STATUS_BITS | \
__LPU12HOST_MBOX0_STATUS_BITS | \
@@ -1070,11 +1070,11 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
__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 | \
+ ((_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) \
@@ -1087,9 +1087,9 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
#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); \
+ __LPU02HOST_MBOX1_STATUS_BITS | \
+ __LPU12HOST_MBOX0_STATUS_BITS | \
+ __LPU12HOST_MBOX1_STATUS_BITS); \
} while (0)
#define BNA_INTR_STATUS_ERR_CLR(_intr_status) \
@@ -1107,7 +1107,7 @@ do { \
writel(0xffffffff, (_bna)->regs.fn_int_mask);\
}
-#define bna_intx_enable(bna, new_mask) \
+#define bna_intx_enable(bna, new_mask) \
writel((new_mask), (bna)->regs.fn_int_mask)
#define bna_mbox_intr_disable(bna) \
@@ -1179,18 +1179,18 @@ do {\
#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_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_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))
@@ -1199,30 +1199,30 @@ do {\
* 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_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_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_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_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_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_MCAST (1 << 17)
+#define BNA_CQ_EF_BCAST (1 << 18)
+#define BNA_CQ_EF_REMOTE (1 << 19)
#define BNA_CQ_EF_LOCAL (1 << 20)
@@ -1257,10 +1257,10 @@ enum ib_flags {
};
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)
+ 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),
@@ -1298,7 +1298,7 @@ struct bna_txq_mem {
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 */
+ 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 */
@@ -1326,7 +1326,7 @@ struct bna_rxq_mem {
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 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];
@@ -1426,8 +1426,8 @@ struct bna_dma_addr {
};
struct bna_txq_wi_vector {
- u16 reserved;
- u16 length; /* Only 14 LSB are valid */
+ u16 reserved;
+ u16 length; /* Only 14 LSB are valid */
struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
};
@@ -1465,7 +1465,7 @@ struct bna_txq_entry {
} hdr;
struct bna_txq_wi_vector vector[4];
};
-#define wi_hdr hdr.wi
+#define wi_hdr hdr.wi
#define wi_ext_hdr hdr.wi_ext
/* RxQ Entry Structure */
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
index 380085cc3088..f0983c832447 100644
--- a/drivers/net/bna/bna_txrx.c
+++ b/drivers/net/bna/bna_txrx.c
@@ -16,7 +16,7 @@
* www.brocade.com
*/
#include "bna.h"
-#include "bfa_sm.h"
+#include "bfa_cs.h"
#include "bfi.h"
/**
@@ -569,7 +569,7 @@ bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
break;
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -627,7 +627,7 @@ bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
break;
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -678,7 +678,7 @@ bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
break;
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -724,7 +724,7 @@ bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
break;
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -734,7 +734,7 @@ 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
+ * cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
*/
}
@@ -761,7 +761,7 @@ bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
break;
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -771,7 +771,7 @@ 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
+ * start_wait -> stop_wait on RXF_E_STOP event
*/
}
@@ -815,7 +815,7 @@ bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
break;
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -851,7 +851,7 @@ bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
* any other event during these states
*/
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -887,7 +887,7 @@ bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
* any other event during these states
*/
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -907,7 +907,7 @@ bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
break;
default:
- bfa_sm_fault(rxf->rx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -1898,7 +1898,7 @@ static void bna_rx_sm_stopped(struct bna_rx *rx,
/* no-op */
break;
default:
- bfa_sm_fault(rx->bna, event);
+ bfa_sm_fault(event);
break;
}
@@ -1946,7 +1946,7 @@ static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
bfa_fsm_set_state(rx, bna_rx_sm_started);
break;
default:
- bfa_sm_fault(rx->bna, event);
+ bfa_sm_fault(event);
break;
}
}
@@ -1981,7 +1981,7 @@ bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
break;
default:
- bfa_sm_fault(rx->bna, event);
+ bfa_sm_fault(event);
break;
}
}
@@ -2011,7 +2011,7 @@ bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
bna_rxf_fail(&rx->rxf);
break;
default:
- bfa_sm_fault(rx->bna, event);
+ bfa_sm_fault(event);
break;
}
@@ -2064,7 +2064,7 @@ bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
bfa_fsm_set_state(rx, bna_rx_sm_stopped);
break;
default:
- bfa_sm_fault(rx->bna, event);
+ bfa_sm_fault(event);
break;
}
}
@@ -3216,7 +3216,7 @@ bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
break;
default:
- bfa_sm_fault(tx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -3261,7 +3261,7 @@ bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
break;
default:
- bfa_sm_fault(tx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -3294,7 +3294,7 @@ bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
break;
default:
- bfa_sm_fault(tx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -3335,7 +3335,7 @@ bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
break;
default:
- bfa_sm_fault(tx->bna, event);
+ bfa_sm_fault(event);
}
}
@@ -3355,7 +3355,7 @@ bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event)
break;
default:
- bfa_sm_fault(tx->bna, event);
+ bfa_sm_fault(event);
}
}
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
index b9c134f7ad31..2f89cb235248 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/bna/bna_types.h
@@ -50,12 +50,12 @@ enum bna_status {
};
enum bna_cleanup_type {
- BNA_HARD_CLEANUP = 0,
- BNA_SOFT_CLEANUP = 1
+ BNA_HARD_CLEANUP = 0,
+ BNA_SOFT_CLEANUP = 1
};
enum bna_cb_status {
- BNA_CB_SUCCESS = 0,
+ BNA_CB_SUCCESS = 0,
BNA_CB_FAIL = 1,
BNA_CB_INTERRUPT = 2,
BNA_CB_BUSY = 3,
@@ -72,8 +72,8 @@ enum bna_res_type {
};
enum bna_mem_type {
- BNA_MEM_T_KVA = 1,
- BNA_MEM_T_DMA = 2
+ BNA_MEM_T_KVA = 1,
+ BNA_MEM_T_DMA = 2
};
enum bna_intr_type {
@@ -82,10 +82,10 @@ enum bna_intr_type {
};
enum bna_res_req_type {
- BNA_RES_MEM_T_COM = 0,
- BNA_RES_MEM_T_ATTR = 1,
- BNA_RES_MEM_T_FWTRC = 2,
- BNA_RES_MEM_T_STATS = 3,
+ BNA_RES_MEM_T_COM = 0,
+ 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,
@@ -107,9 +107,9 @@ enum bna_res_req_type {
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_QPT = 2,
BNA_TX_RES_MEM_T_SWQPT = 3,
- BNA_TX_RES_MEM_T_PAGE = 4,
+ BNA_TX_RES_MEM_T_PAGE = 4,
BNA_TX_RES_INTR_T_TXCMPL = 5,
BNA_TX_RES_T_MAX,
};
@@ -158,14 +158,14 @@ enum bna_rx_type {
};
enum bna_rxp_type {
- BNA_RXP_SINGLE = 1,
- BNA_RXP_SLR = 2,
- BNA_RXP_HDS = 3
+ BNA_RXP_SINGLE = 1,
+ BNA_RXP_SLR = 2,
+ BNA_RXP_HDS = 3
};
enum bna_rxmode {
- BNA_RXMODE_PROMISC = 1,
- BNA_RXMODE_ALLMULTI = 2
+ BNA_RXMODE_PROMISC = 1,
+ BNA_RXMODE_ALLMULTI = 2
};
enum bna_rx_event {
@@ -202,7 +202,7 @@ enum bna_rxf_oper_state {
};
enum bna_rxf_flags {
- BNA_RXF_FL_STOP_PENDING = 0x01,
+ BNA_RXF_FL_STOP_PENDING = 0x01,
BNA_RXF_FL_FAILED = 0x02,
BNA_RXF_FL_RSS_CONFIG_PENDING = 0x04,
BNA_RXF_FL_OPERSTATE_CHANGED = 0x08,
@@ -244,11 +244,11 @@ enum bna_port_type {
enum bna_link_status {
BNA_LINK_DOWN = 0,
BNA_LINK_UP = 1,
- BNA_CEE_UP = 2
+ BNA_CEE_UP = 2
};
enum bna_llport_flags {
- BNA_LLPORT_F_ADMIN_UP = 1,
+ BNA_LLPORT_F_ADMIN_UP = 1,
BNA_LLPORT_F_PORT_ENABLED = 2,
BNA_LLPORT_F_RX_STARTED = 4
};
@@ -304,7 +304,7 @@ struct bna_mem_descr {
struct bna_mem_info {
enum bna_mem_type mem_type;
u32 len;
- u32 num;
+ u32 num;
u32 align_sz; /* 0/1 = no alignment */
struct bna_mem_descr *mdl;
void *cookie; /* For bnad to unmap dma later */
@@ -371,10 +371,10 @@ struct bna_mbox_qe {
struct list_head qe;
struct bfa_mbox_cmd cmd;
- u32 cmd_len;
+ u32 cmd_len;
/* Callback for port, tx, rx, rxf */
void (*cbfn)(void *arg, int status);
- void *cbarg;
+ void *cbarg;
};
struct bna_mbox_mod {
@@ -480,7 +480,7 @@ struct bna_ib_dbell {
/* Interrupt timer configuration */
struct bna_ib_config {
- u8 coalescing_timeo; /* Unit is 5usec. */
+ u8 coalescing_timeo; /* Unit is 5usec. */
int interpkt_count;
int interpkt_timeo;
@@ -576,8 +576,8 @@ struct bna_txq {
struct bna_tx *tx;
- u64 tx_packets;
- u64 tx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
};
/* TxF structure (hardware Tx Function) */
@@ -739,10 +739,10 @@ struct bna_rxq {
struct bna_rxp *rxp;
struct bna_rx *rx;
- u64 rx_packets;
+ u64 rx_packets;
u64 rx_bytes;
- u64 rx_packets_with_error;
- u64 rxbuf_alloc_failed;
+ u64 rx_packets_with_error;
+ u64 rxbuf_alloc_failed;
};
/* RxQ pair */
@@ -902,7 +902,7 @@ struct bna_rxf {
* callback for:
* bna_rxf_ucast_set()
* bna_rxf_{ucast/mcast}_add(),
- * bna_rxf_{ucast/mcast}_del(),
+ * bna_rxf_{ucast/mcast}_del(),
* bna_rxf_mode_set()
*/
void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx,
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 44e219c910da..8e35b2596f93 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -15,6 +15,7 @@
* All rights reserved
* www.brocade.com
*/
+#include <linux/bitops.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
@@ -58,7 +59,7 @@ static const u8 bnad_bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
#define BNAD_GET_MBOX_IRQ(_bnad) \
(((_bnad)->cfg_flags & BNAD_CF_MSIX) ? \
- ((_bnad)->msix_table[(_bnad)->msix_num - 1].vector) : \
+ ((_bnad)->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector) : \
((_bnad)->pcidev->irq))
#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth) \
@@ -110,10 +111,10 @@ static void
bnad_free_all_txbufs(struct bnad *bnad,
struct bna_tcb *tcb)
{
- u32 unmap_cons;
+ u32 unmap_cons;
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
struct bnad_skb_unmap *unmap_array;
- struct sk_buff *skb = NULL;
+ struct sk_buff *skb = NULL;
int i;
unmap_array = unmap_q->unmap_array;
@@ -163,11 +164,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 sent_packets = 0, sent_bytes = 0;
+ u16 wis, unmap_cons, updated_hw_cons;
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
struct bnad_skb_unmap *unmap_array;
- struct sk_buff *skb;
+ struct sk_buff *skb;
int i;
/*
@@ -245,7 +246,7 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
{
struct bnad *bnad = (struct bnad *)bnad_ptr;
struct bna_tcb *tcb;
- u32 acked = 0;
+ u32 acked = 0;
int i, j;
for (i = 0; i < bnad->num_tx; i++) {
@@ -386,14 +387,12 @@ 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);
}
- skb = alloc_skb(rcb->rxq->buffer_size + NET_IP_ALIGN,
- GFP_ATOMIC);
+ skb = netdev_alloc_skb_ip_align(bnad->netdev,
+ rcb->rxq->buffer_size);
if (unlikely(!skb)) {
BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
goto finishing;
}
- skb->dev = bnad->netdev;
- skb_reserve(skb, NET_IP_ALIGN);
unmap_array[unmap_prod].skb = skb;
dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
rcb->rxq->buffer_size,
@@ -516,24 +515,16 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
rcb->rxq->rx_bytes += skb->len;
skb->protocol = eth_type_trans(skb, bnad->netdev);
- if (bnad->vlan_grp && (flags & BNA_CQ_EF_VLAN)) {
- struct bnad_rx_ctrl *rx_ctrl =
- (struct bnad_rx_ctrl *)ccb->ctrl;
- if (skb->ip_summed == CHECKSUM_UNNECESSARY)
- vlan_gro_receive(&rx_ctrl->napi, bnad->vlan_grp,
- ntohs(cmpl->vlan_tag), skb);
- else
- vlan_hwaccel_receive_skb(skb,
- bnad->vlan_grp,
- ntohs(cmpl->vlan_tag));
-
- } else { /* Not VLAN tagged/stripped */
- struct bnad_rx_ctrl *rx_ctrl =
- (struct bnad_rx_ctrl *)ccb->ctrl;
- if (skb->ip_summed == CHECKSUM_UNNECESSARY)
- napi_gro_receive(&rx_ctrl->napi, skb);
- else
- netif_receive_skb(skb);
+ 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;
+ napi_gro_receive(&rx_ctrl->napi, skb);
+ } else {
+ netif_receive_skb(skb);
}
next:
@@ -1110,10 +1101,10 @@ static int
bnad_mbox_irq_alloc(struct bnad *bnad,
struct bna_intr_info *intr_info)
{
- int err = 0;
- unsigned long irq_flags = 0, flags;
+ int err = 0;
+ unsigned long irq_flags, flags;
u32 irq;
- irq_handler_t irq_handler;
+ irq_handler_t irq_handler;
/* Mbox should use only 1 vector */
@@ -1124,18 +1115,18 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
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->msix_num - 1].vector;
+ 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->msix_num - 1;
+ 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;
- /* intr_info->idl.vector = 0 ? */
}
+
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- flags = irq_flags;
sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
/*
@@ -1146,7 +1137,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
- err = request_irq(irq, irq_handler, flags,
+ err = request_irq(irq, irq_handler, irq_flags,
bnad->mbox_irq_name, bnad);
if (err) {
@@ -1187,11 +1178,12 @@ bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
switch (src) {
case BNAD_INTR_TX:
- vector_start = txrx_id;
+ vector_start = BNAD_MAILBOX_MSIX_VECTORS + txrx_id;
break;
case BNAD_INTR_RX:
- vector_start = bnad->num_tx * bnad->num_txq_per_tx +
+ vector_start = BNAD_MAILBOX_MSIX_VECTORS +
+ (bnad->num_tx * bnad->num_txq_per_tx) +
txrx_id;
break;
@@ -1212,11 +1204,11 @@ bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
switch (src) {
case BNAD_INTR_TX:
- intr_info->idl[0].vector = 0x1; /* Bit mask : Tx IB */
+ intr_info->idl[0].vector = BNAD_INTX_TX_IB_BITMASK;
break;
case BNAD_INTR_RX:
- intr_info->idl[0].vector = 0x2; /* Bit mask : Rx IB */
+ intr_info->idl[0].vector = BNAD_INTX_RX_IB_BITMASK;
break;
}
}
@@ -1455,7 +1447,7 @@ bnad_iocpf_sem_timeout(unsigned long data)
/*
* All timer routines use bnad->bna_lock to protect against
* the following race, which may occur in case of no locking:
- * Time CPU m CPU n
+ * Time CPU m CPU n
* 0 1 = test_bit
* 1 clear_bit
* 2 del_timer_sync
@@ -1920,7 +1912,7 @@ void
bnad_rx_coalescing_timeo_set(struct bnad *bnad)
{
struct bnad_rx_info *rx_info;
- int i;
+ int i;
for (i = 0; i < bnad->num_rx; i++) {
rx_info = &bnad->rx_info[i];
@@ -1983,19 +1975,14 @@ bnad_enable_default_bcast(struct bnad *bnad)
static void
bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
{
- u16 vlan_id;
+ u16 vid;
unsigned long flags;
- if (!bnad->vlan_grp)
- return;
-
BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1)));
- for (vlan_id = 0; vlan_id < VLAN_N_VID; vlan_id++) {
- if (!vlan_group_get_device(bnad->vlan_grp, vlan_id))
- continue;
+ 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, vlan_id);
+ bna_rx_vlan_add(bnad->rx_info[rx_id].rx, vid);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
}
@@ -2088,7 +2075,7 @@ bnad_mbox_irq_sync(struct bnad *bnad)
spin_lock_irqsave(&bnad->bna_lock, flags);
if (bnad->cfg_flags & BNAD_CF_MSIX)
- irq = bnad->msix_table[bnad->msix_num - 1].vector;
+ irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
else
irq = bnad->pcidev->irq;
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -2439,18 +2426,18 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct bnad *bnad = netdev_priv(netdev);
- u16 txq_prod, vlan_tag = 0;
- u32 unmap_prod, wis, wis_used, wi_range;
- u32 vectors, vect_id, i, acked;
+ 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;
+ int err;
struct bnad_tx_info *tx_info;
struct bna_tcb *tcb;
struct bnad_unmap_q *unmap_q;
- dma_addr_t dma_addr;
+ dma_addr_t dma_addr;
struct bna_txq_entry *txqent;
- bna_txq_wi_ctrl_flag_t flags;
+ bna_txq_wi_ctrl_flag_t flags;
if (unlikely
(skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
@@ -2798,17 +2785,6 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu)
}
static void
-bnad_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *vlan_grp)
-{
- struct bnad *bnad = netdev_priv(netdev);
-
- mutex_lock(&bnad->conf_mutex);
- bnad->vlan_grp = vlan_grp;
- mutex_unlock(&bnad->conf_mutex);
-}
-
-static void
bnad_vlan_rx_add_vid(struct net_device *netdev,
unsigned short vid)
{
@@ -2822,6 +2798,7 @@ bnad_vlan_rx_add_vid(struct net_device *netdev,
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_vlan_add(bnad->rx_info[0].rx, vid);
+ set_bit(vid, bnad->active_vlans);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
mutex_unlock(&bnad->conf_mutex);
@@ -2840,6 +2817,7 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev,
mutex_lock(&bnad->conf_mutex);
spin_lock_irqsave(&bnad->bna_lock, flags);
+ clear_bit(vid, bnad->active_vlans);
bna_rx_vlan_del(bnad->rx_info[0].rx, vid);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -2889,7 +2867,6 @@ static const struct net_device_ops bnad_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = bnad_set_mac_address,
.ndo_change_mtu = bnad_change_mtu,
- .ndo_vlan_rx_register = bnad_vlan_rx_register,
.ndo_vlan_rx_add_vid = bnad_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bnad_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3056,8 +3033,8 @@ static int __devinit
bnad_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pcidev_id)
{
- bool using_dac = false;
- int err;
+ bool using_dac = false;
+ int err;
struct bnad *bnad;
struct bna *bna;
struct net_device *netdev;
@@ -3089,7 +3066,7 @@ bnad_pci_probe(struct pci_dev *pdev,
/*
* PCI initialization
- * Output : using_dac = 1 for 64 bit DMA
+ * Output : using_dac = 1 for 64 bit DMA
* = 0 for 32 bit DMA
*/
err = bnad_pci_init(bnad, pdev, &using_dac);
@@ -3232,7 +3209,7 @@ bnad_pci_remove(struct pci_dev *pdev)
free_netdev(netdev);
}
-static const struct pci_device_id bnad_pci_id_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(bnad_pci_id_table) = {
{
PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
PCI_DEVICE_ID_BROCADE_CT),
@@ -3255,7 +3232,8 @@ bnad_module_init(void)
{
int err;
- pr_info("Brocade 10G Ethernet driver\n");
+ pr_info("Brocade 10G Ethernet driver - version: %s\n",
+ BNAD_VERSION);
bfa_nw_ioc_auto_recover(bnad_ioc_auto_recover);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index ccdabad0a40c..458eb30371b5 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -24,6 +24,7 @@
#include <linux/etherdevice.h>
#include <linux/mutex.h>
#include <linux/firmware.h>
+#include <linux/if_vlan.h>
/* Fix for IA64 */
#include <asm/checksum.h>
@@ -67,10 +68,13 @@ struct bnad_rx_ctrl {
#define BNAD_VERSION "2.3.2.3"
+#define BNAD_MAILBOX_MSIX_INDEX 0
#define BNAD_MAILBOX_MSIX_VECTORS 1
+#define BNAD_INTX_TX_IB_BITMASK 0x1
+#define BNAD_INTX_RX_IB_BITMASK 0x2
-#define BNAD_STATS_TIMER_FREQ 1000 /* in msecs */
-#define BNAD_DIM_TIMER_FREQ 1000 /* in msecs */
+#define BNAD_STATS_TIMER_FREQ 1000 /* in msecs */
+#define BNAD_DIM_TIMER_FREQ 1000 /* in msecs */
#define BNAD_MAX_Q_DEPTH 0x10000
#define BNAD_MIN_Q_DEPTH 0x200
@@ -101,12 +105,12 @@ enum bnad_intr_source {
enum bnad_link_state {
BNAD_LS_DOWN = 0,
- BNAD_LS_UP = 1
+ BNAD_LS_UP = 1
};
struct bnad_completion {
- struct completion ioc_comp;
- struct completion ucast_comp;
+ struct completion ioc_comp;
+ struct completion ucast_comp;
struct completion mcast_comp;
struct completion tx_comp;
struct completion rx_comp;
@@ -124,7 +128,7 @@ struct bnad_completion {
/* Tx Rx Control Stats */
struct bnad_drv_stats {
- u64 netif_queue_stop;
+ u64 netif_queue_stop;
u64 netif_queue_wakeup;
u64 netif_queue_stopped;
u64 tso4;
@@ -187,7 +191,7 @@ struct bnad_skb_unmap {
struct bnad_unmap_q {
u32 producer_index;
u32 consumer_index;
- u32 q_depth;
+ u32 q_depth;
/* This should be the last one */
struct bnad_skb_unmap unmap_array[1];
};
@@ -210,13 +214,13 @@ struct bnad_unmap_q {
#define BNAD_RF_RX_SHUTDOWN_DELAYED 7
struct bnad {
- struct net_device *netdev;
+ 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 vlan_group *vlan_grp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
/*
* These q numbers are global only because
* they are used to calculate MSIx vectors.
@@ -244,7 +248,7 @@ struct bnad {
u32 cfg_flags;
unsigned long run_flags;
- struct pci_dev *pcidev;
+ struct pci_dev *pcidev;
u64 mmio_start;
u64 mmio_len;
@@ -277,7 +281,7 @@ struct bnad {
struct bnad_diag *diag;
char adapter_name[BNAD_NAME_LEN];
- char port_name[BNAD_NAME_LEN];
+ char port_name[BNAD_NAME_LEN];
char mbox_irq_name[BNAD_NAME_LEN];
};
@@ -285,7 +289,7 @@ struct bnad {
* EXTERN VARIABLES
*/
extern struct firmware *bfi_fw;
-extern u32 bnad_rxqs_per_cq;
+extern u32 bnad_rxqs_per_cq;
/*
* EXTERN PROTOTYPES
@@ -331,7 +335,7 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
}
#define bnad_dim_timer_running(_bnad) \
- (((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && \
+ (((_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/bna/bnad_ethtool.c
index 3330cd78da2c..fea07f19a5db 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -295,7 +295,7 @@ get_regs(struct bnad *bnad, u32 * regs)
u32 reg_addr;
unsigned long flags;
-#define BNAD_GET_REG(addr) \
+#define BNAD_GET_REG(addr) \
do { \
if (regs) \
regs[num++] = readl(bnad->bar0 + (addr)); \
diff --git a/drivers/net/bna/cna.h b/drivers/net/bna/cna.h
index bbd39dc65972..a679e038747b 100644
--- a/drivers/net/bna/cna.h
+++ b/drivers/net/bna/cna.h
@@ -19,7 +19,6 @@
#ifndef __CNA_H__
#define __CNA_H__
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -34,7 +33,7 @@
#include <linux/list.h>
-#define bfa_sm_fault(__mod, __event) do { \
+#define bfa_sm_fault(__event) do { \
pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \
__event); \
} while (0)
@@ -74,7 +73,7 @@ typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t;
bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
bfa_q_qe_init(*((struct list_head **) _qe)); \
} else { \
- *((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+ *((struct list_head **)(_qe)) = NULL; \
} \
}
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 57d3293c65bd..4b2b57018a02 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -56,8 +56,8 @@
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
-#define DRV_MODULE_VERSION "2.1.6"
-#define DRV_MODULE_RELDATE "Mar 7, 2011"
+#define DRV_MODULE_VERSION "2.1.11"
+#define DRV_MODULE_RELDATE "July 20, 2011"
#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-6.2.1.fw"
#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-6.0.15.fw"
#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-6.2.1a.fw"
@@ -385,6 +385,9 @@ static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops,
if (cp->drv_state & CNIC_DRV_STATE_REGD)
return -EBUSY;
+ if (!bnx2_reg_rd_ind(bp, BNX2_FW_MAX_ISCSI_CONN))
+ return -ENODEV;
+
bp->cnic_data = data;
rcu_assign_pointer(bp->cnic_ops, ops);
@@ -416,6 +419,9 @@ struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
struct bnx2 *bp = netdev_priv(dev);
struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+ if (!cp->max_iscsi_conn)
+ return NULL;
+
cp->drv_owner = THIS_MODULE;
cp->chip_id = bp->chip_id;
cp->pdev = bp->pdev;
@@ -2440,6 +2446,48 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
return 0;
}
+static void
+bnx2_dump_mcp_state(struct bnx2 *bp)
+{
+ struct net_device *dev = bp->dev;
+ u32 mcp_p0, mcp_p1;
+
+ netdev_err(dev, "<--- start MCP states dump --->\n");
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ mcp_p0 = BNX2_MCP_STATE_P0;
+ mcp_p1 = BNX2_MCP_STATE_P1;
+ } else {
+ mcp_p0 = BNX2_MCP_STATE_P0_5708;
+ mcp_p1 = BNX2_MCP_STATE_P1_5708;
+ }
+ netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
+ bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1));
+ netdev_err(dev, "DEBUG: MCP mode[%08x] state[%08x] evt_mask[%08x]\n",
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_MODE),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_STATE),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_EVENT_MASK));
+ netdev_err(dev, "DEBUG: pc[%08x] pc[%08x] instr[%08x]\n",
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_INSTRUCTION));
+ netdev_err(dev, "DEBUG: shmem states:\n");
+ netdev_err(dev, "DEBUG: drv_mb[%08x] fw_mb[%08x] link_status[%08x]",
+ bnx2_shmem_rd(bp, BNX2_DRV_MB),
+ bnx2_shmem_rd(bp, BNX2_FW_MB),
+ bnx2_shmem_rd(bp, BNX2_LINK_STATUS));
+ pr_cont(" drv_pulse_mb[%08x]\n", bnx2_shmem_rd(bp, BNX2_DRV_PULSE_MB));
+ netdev_err(dev, "DEBUG: dev_info_signature[%08x] reset_type[%08x]",
+ bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE),
+ bnx2_shmem_rd(bp, BNX2_BC_STATE_RESET_TYPE));
+ pr_cont(" condition[%08x]\n",
+ bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION));
+ DP_SHMEM_LINE(bp, 0x3cc);
+ DP_SHMEM_LINE(bp, 0x3dc);
+ DP_SHMEM_LINE(bp, 0x3ec);
+ netdev_err(dev, "DEBUG: 0x3fc[%08x]\n", bnx2_shmem_rd(bp, 0x3fc));
+ netdev_err(dev, "<--- end MCP states dump --->\n");
+}
+
static int
bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
{
@@ -2468,13 +2516,14 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
/* If we timed out, inform the firmware that this is the case. */
if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
- if (!silent)
- pr_err("fw sync timeout, reset code = %x\n", msg_data);
-
msg_data &= ~BNX2_DRV_MSG_CODE;
msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
+ if (!silent) {
+ pr_err("fw sync timeout, reset code = %x\n", msg_data);
+ bnx2_dump_mcp_state(bp);
+ }
return -EBUSY;
}
@@ -6293,6 +6342,7 @@ static void
bnx2_reset_task(struct work_struct *work)
{
struct bnx2 *bp = container_of(work, struct bnx2, reset_task);
+ int rc;
rtnl_lock();
if (!netif_running(bp->dev)) {
@@ -6302,7 +6352,14 @@ bnx2_reset_task(struct work_struct *work)
bnx2_netif_stop(bp, true);
- bnx2_init_nic(bp, 1);
+ rc = bnx2_init_nic(bp, 1);
+ if (rc) {
+ netdev_err(bp->dev, "failed to reset NIC, closing\n");
+ bnx2_napi_enable(bp);
+ dev_close(bp->dev);
+ rtnl_unlock();
+ return;
+ }
atomic_set(&bp->intr_sem, 1);
bnx2_netif_start(bp, true);
@@ -6313,7 +6370,7 @@ static void
bnx2_dump_state(struct bnx2 *bp)
{
struct net_device *dev = bp->dev;
- u32 mcp_p0, mcp_p1, val1, val2;
+ u32 val1, val2;
pci_read_config_dword(bp->pdev, PCI_COMMAND, &val1);
netdev_err(dev, "DEBUG: intr_sem[%x] PCI_CMD[%08x]\n",
@@ -6326,15 +6383,6 @@ bnx2_dump_state(struct bnx2 *bp)
REG_RD(bp, BNX2_EMAC_RX_STATUS));
netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n",
REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- mcp_p0 = BNX2_MCP_STATE_P0;
- mcp_p1 = BNX2_MCP_STATE_P1;
- } else {
- mcp_p0 = BNX2_MCP_STATE_P0_5708;
- mcp_p1 = BNX2_MCP_STATE_P1_5708;
- }
- netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
- bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1));
netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
if (bp->flags & BNX2_FLAG_USING_MSIX)
@@ -6348,6 +6396,7 @@ bnx2_tx_timeout(struct net_device *dev)
struct bnx2 *bp = netdev_priv(dev);
bnx2_dump_state(bp);
+ bnx2_dump_mcp_state(bp);
/* This allows the netif to be shutdown gracefully before resetting */
schedule_work(&bp->reset_task);
@@ -6532,8 +6581,6 @@ bnx2_close(struct net_device *dev)
{
struct bnx2 *bp = netdev_priv(dev);
- cancel_work_sync(&bp->reset_task);
-
bnx2_disable_int_sync(bp);
bnx2_napi_disable(bp);
del_timer_sync(&bp->timer);
@@ -7908,9 +7955,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) {
- dev_err(&pdev->dev,
- "Cannot find PCIE capability, aborting\n");
+ if (!pci_is_pcie(pdev)) {
+ dev_err(&pdev->dev, "Not PCIE, aborting\n");
rc = -EIO;
goto err_out_unmap;
}
@@ -8051,7 +8097,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->fw_version[j++] = ' ';
for (i = 0; i < 3 && j < 28; i++) {
reg = bnx2_reg_rd_ind(bp, addr + i * 4);
- reg = swab32(reg);
+ reg = be32_to_cpu(reg);
memcpy(&bp->fw_version[j], &reg, 4);
j += 4;
}
@@ -8177,6 +8223,12 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->timer.data = (unsigned long) bp;
bp->timer.function = bnx2_timer;
+#ifdef BCM_CNIC
+ if (bnx2_shmem_rd(bp, BNX2_ISCSI_INITIATOR) & BNX2_ISCSI_INITIATOR_EN)
+ bp->cnic_eth_dev.max_iscsi_conn =
+ (bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) &
+ BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT;
+#endif
pci_save_state(pdev);
return 0;
@@ -8358,6 +8410,7 @@ bnx2_remove_one(struct pci_dev *pdev)
unregister_netdev(dev);
del_timer_sync(&bp->timer);
+ cancel_work_sync(&bp->reset_task);
if (bp->mips_firmware)
release_firmware(bp->mips_firmware);
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index bf371f6fe154..fc50d4267df8 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -7368,6 +7368,21 @@ struct bnx2_rv2p_fw_file {
#define BNX2_RPHY_SERDES_LINK 0x374
#define BNX2_RPHY_COPPER_LINK 0x378
+#define BNX2_ISCSI_INITIATOR 0x3dc
+#define BNX2_ISCSI_INITIATOR_EN 0x00080000
+
+#define BNX2_ISCSI_MAX_CONN 0x3e4
+#define BNX2_ISCSI_MAX_CONN_MASK 0xffff0000
+#define BNX2_ISCSI_MAX_CONN_SHIFT 16
+
#define HOST_VIEW_SHMEM_BASE 0x167c00
+#define DP_SHMEM_LINE(bp, offset) \
+ netdev_err(bp->dev, "DEBUG: %08x: %08x %08x %08x %08x\n", \
+ offset, \
+ bnx2_shmem_rd(bp, offset), \
+ bnx2_shmem_rd(bp, offset + 4), \
+ bnx2_shmem_rd(bp, offset + 8), \
+ bnx2_shmem_rd(bp, offset + 12))
+
#endif
diff --git a/drivers/net/bnx2x/Makefile b/drivers/net/bnx2x/Makefile
index bb83a2961273..48fbdd48f88f 100644
--- a/drivers/net/bnx2x/Makefile
+++ b/drivers/net/bnx2x/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_BNX2X) += bnx2x.o
-bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o
+bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 668a578c49e9..c423504a755f 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -14,6 +14,7 @@
#ifndef BNX2X_H
#define BNX2X_H
#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
#include <linux/types.h>
/* compilation time flags */
@@ -22,14 +23,10 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.62.12-0"
-#define DRV_MODULE_RELDATE "2011/03/20"
+#define DRV_MODULE_VERSION "1.70.00-0"
+#define DRV_MODULE_RELDATE "2011/06/13"
#define BNX2X_BC_VER 0x040200
-#define BNX2X_MULTI_QUEUE
-
-#define BNX2X_NEW_NAPI
-
#if defined(CONFIG_DCB)
#define BCM_DCBNL
#endif
@@ -47,11 +44,12 @@
#endif
#include <linux/mdio.h>
-#include <linux/pci.h>
+
#include "bnx2x_reg.h"
#include "bnx2x_fw_defs.h"
#include "bnx2x_hsi.h"
#include "bnx2x_link.h"
+#include "bnx2x_sp.h"
#include "bnx2x_dcb.h"
#include "bnx2x_stats.h"
@@ -80,6 +78,12 @@ do { \
##__args); \
} while (0)
+#define DP_CONT(__mask, __fmt, __args...) \
+do { \
+ if (bp->msg_enable & (__mask)) \
+ pr_cont(__fmt, ##__args); \
+} while (0)
+
/* errors debug print */
#define BNX2X_DBG_ERR(__fmt, __args...) \
do { \
@@ -111,9 +115,12 @@ do { \
dev_info(&bp->pdev->dev, __fmt, ##__args); \
} while (0)
-void bnx2x_panic_dump(struct bnx2x *bp);
+#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"); \
@@ -233,22 +240,22 @@ void bnx2x_panic_dump(struct bnx2x *bp);
*
*/
/* iSCSI L2 */
-#define BNX2X_ISCSI_ETH_CL_ID 17
-#define BNX2X_ISCSI_ETH_CID 17
+#define BNX2X_ISCSI_ETH_CL_ID_IDX 1
+#define BNX2X_ISCSI_ETH_CID 49
/* FCoE L2 */
-#define BNX2X_FCOE_ETH_CL_ID 18
-#define BNX2X_FCOE_ETH_CID 18
+#define BNX2X_FCOE_ETH_CL_ID_IDX 2
+#define BNX2X_FCOE_ETH_CID 50
/** Additional rings budgeting */
#ifdef BCM_CNIC
-#define CNIC_CONTEXT_USE 1
-#define FCOE_CONTEXT_USE 1
+#define CNIC_PRESENT 1
+#define FCOE_PRESENT 1
#else
-#define CNIC_CONTEXT_USE 0
-#define FCOE_CONTEXT_USE 0
+#define CNIC_PRESENT 0
+#define FCOE_PRESENT 0
#endif /* BCM_CNIC */
-#define NONE_ETH_CONTEXT_USE (FCOE_CONTEXT_USE)
+#define NON_ETH_CONTEXT_USE (FCOE_PRESENT)
#define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
@@ -256,8 +263,35 @@ void bnx2x_panic_dump(struct bnx2x *bp);
#define SM_RX_ID 0
#define SM_TX_ID 1
-/* fast path */
+/* defines for multiple tx priority indices */
+#define FIRST_TX_ONLY_COS_INDEX 1
+#define FIRST_TX_COS_INDEX 0
+
+/* defines for decodeing the fastpath index and the cos index out of the
+ * transmission queue index
+ */
+#define MAX_TXQS_PER_COS FP_SB_MAX_E1x
+
+#define TXQ_TO_FP(txq_index) ((txq_index) % MAX_TXQS_PER_COS)
+#define TXQ_TO_COS(txq_index) ((txq_index) / MAX_TXQS_PER_COS)
+
+/* rules for calculating the cids of tx-only connections */
+#define CID_TO_FP(cid) ((cid) % MAX_TXQS_PER_COS)
+#define CID_COS_TO_TX_ONLY_CID(cid, cos) (cid + cos * MAX_TXQS_PER_COS)
+
+/* fp index inside class of service range */
+#define FP_COS_TO_TXQ(fp, cos) ((fp)->index + cos * MAX_TXQS_PER_COS)
+
+/*
+ * 0..15 eth cos0
+ * 16..31 eth cos1 if applicable
+ * 32..47 eth cos2 If applicable
+ * fcoe queue follows eth queues (16, 32, 48 depending on cos)
+ */
+#define MAX_ETH_TXQ_IDX(bp) (MAX_TXQS_PER_COS * (bp)->max_cos)
+#define FCOE_TXQ_IDX(bp) (MAX_ETH_TXQ_IDX(bp))
+/* fast path */
struct sw_rx_bd {
struct sk_buff *skb;
DEFINE_DMA_UNMAP_ADDR(mapping);
@@ -283,44 +317,73 @@ union db_prod {
/* MC hsi */
-#define BCM_PAGE_SHIFT 12
-#define BCM_PAGE_SIZE (1 << BCM_PAGE_SHIFT)
-#define BCM_PAGE_MASK (~(BCM_PAGE_SIZE - 1))
+#define BCM_PAGE_SHIFT 12
+#define BCM_PAGE_SIZE (1 << BCM_PAGE_SHIFT)
+#define BCM_PAGE_MASK (~(BCM_PAGE_SIZE - 1))
#define BCM_PAGE_ALIGN(addr) (((addr) + BCM_PAGE_SIZE - 1) & BCM_PAGE_MASK)
-#define PAGES_PER_SGE_SHIFT 0
-#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
-#define SGE_PAGE_SIZE PAGE_SIZE
-#define SGE_PAGE_SHIFT PAGE_SHIFT
-#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
+#define PAGES_PER_SGE_SHIFT 0
+#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
+#define SGE_PAGE_SIZE PAGE_SIZE
+#define SGE_PAGE_SHIFT PAGE_SHIFT
+#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
/* SGE ring related macros */
-#define NUM_RX_SGE_PAGES 2
+#define NUM_RX_SGE_PAGES 2
#define RX_SGE_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
-#define MAX_RX_SGE_CNT (RX_SGE_CNT - 2)
+#define MAX_RX_SGE_CNT (RX_SGE_CNT - 2)
/* RX_SGE_CNT is promised to be a power of 2 */
-#define RX_SGE_MASK (RX_SGE_CNT - 1)
-#define NUM_RX_SGE (RX_SGE_CNT * NUM_RX_SGE_PAGES)
-#define MAX_RX_SGE (NUM_RX_SGE - 1)
+#define RX_SGE_MASK (RX_SGE_CNT - 1)
+#define NUM_RX_SGE (RX_SGE_CNT * NUM_RX_SGE_PAGES)
+#define MAX_RX_SGE (NUM_RX_SGE - 1)
#define NEXT_SGE_IDX(x) ((((x) & RX_SGE_MASK) == \
(MAX_RX_SGE_CNT - 1)) ? (x) + 3 : (x) + 1)
-#define RX_SGE(x) ((x) & MAX_RX_SGE)
+#define RX_SGE(x) ((x) & MAX_RX_SGE)
+
+/* Manipulate a bit vector defined as an array of u64 */
-/* SGE producer mask related macros */
/* Number of bits in one sge_mask array element */
-#define RX_SGE_MASK_ELEM_SZ 64
-#define RX_SGE_MASK_ELEM_SHIFT 6
-#define RX_SGE_MASK_ELEM_MASK ((u64)RX_SGE_MASK_ELEM_SZ - 1)
+#define BIT_VEC64_ELEM_SZ 64
+#define BIT_VEC64_ELEM_SHIFT 6
+#define BIT_VEC64_ELEM_MASK ((u64)BIT_VEC64_ELEM_SZ - 1)
+
+
+#define __BIT_VEC64_SET_BIT(el, bit) \
+ do { \
+ el = ((el) | ((u64)0x1 << (bit))); \
+ } while (0)
+
+#define __BIT_VEC64_CLEAR_BIT(el, bit) \
+ do { \
+ el = ((el) & (~((u64)0x1 << (bit)))); \
+ } while (0)
+
+
+#define BIT_VEC64_SET_BIT(vec64, idx) \
+ __BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
+ (idx) & BIT_VEC64_ELEM_MASK)
+
+#define BIT_VEC64_CLEAR_BIT(vec64, idx) \
+ __BIT_VEC64_CLEAR_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
+ (idx) & BIT_VEC64_ELEM_MASK)
+
+#define BIT_VEC64_TEST_BIT(vec64, idx) \
+ (((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT] >> \
+ ((idx) & BIT_VEC64_ELEM_MASK)) & 0x1)
/* Creates a bitmask of all ones in less significant bits.
idx - index of the most significant bit in the created mask */
-#define RX_SGE_ONES_MASK(idx) \
- (((u64)0x1 << (((idx) & RX_SGE_MASK_ELEM_MASK) + 1)) - 1)
-#define RX_SGE_MASK_ELEM_ONE_MASK ((u64)(~0))
+#define BIT_VEC64_ONES_MASK(idx) \
+ (((u64)0x1 << (((idx) & BIT_VEC64_ELEM_MASK) + 1)) - 1)
+#define BIT_VEC64_ELEM_ONE_MASK ((u64)(~0))
+
+/*******************************************************/
+
+
/* Number of u64 elements in SGE mask array */
#define RX_SGE_MASK_LEN ((NUM_RX_SGE_PAGES * RX_SGE_CNT) / \
- RX_SGE_MASK_ELEM_SZ)
+ BIT_VEC64_ELEM_SZ)
#define RX_SGE_MASK_LEN_MASK (RX_SGE_MASK_LEN - 1)
#define NEXT_SGE_MASK_ELEM(el) (((el) + 1) & RX_SGE_MASK_LEN_MASK)
@@ -331,7 +394,53 @@ union host_hc_status_block {
struct host_hc_status_block_e2 *e2_sb;
};
+struct bnx2x_agg_info {
+ /*
+ * First aggregation buffer is an skb, the following - are pages.
+ * We will preallocate the skbs for each aggregation when
+ * we open the interface and will replace the BD at the consumer
+ * with this one when we receive the TPA_START CQE in order to
+ * keep the Rx BD ring consistent.
+ */
+ struct sw_rx_bd first_buf;
+ u8 tpa_state;
+#define BNX2X_TPA_START 1
+#define BNX2X_TPA_STOP 2
+#define BNX2X_TPA_ERROR 3
+ u8 placement_offset;
+ u16 parsing_flags;
+ u16 vlan_tag;
+ u16 len_on_bd;
+};
+
+#define Q_STATS_OFFSET32(stat_name) \
+ (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
+
+struct bnx2x_fp_txdata {
+
+ struct sw_tx_bd *tx_buf_ring;
+
+ union eth_tx_bd_types *tx_desc_ring;
+ dma_addr_t tx_desc_mapping;
+
+ u32 cid;
+
+ union db_prod tx_db;
+
+ u16 tx_pkt_prod;
+ u16 tx_pkt_cons;
+ u16 tx_bd_prod;
+ u16 tx_bd_cons;
+
+ unsigned long tx_pkt;
+
+ __le16 *tx_cons_sb;
+
+ int txq_index;
+};
+
struct bnx2x_fastpath {
+ struct bnx2x *bp; /* parent */
#define BNX2X_NAPI_WEIGHT 128
struct napi_struct napi;
@@ -346,10 +455,8 @@ struct bnx2x_fastpath {
dma_addr_t status_blk_mapping;
- struct sw_tx_bd *tx_buf_ring;
-
- union eth_tx_bd_types *tx_desc_ring;
- dma_addr_t tx_desc_mapping;
+ u8 max_cos; /* actual number of active tx coses */
+ struct bnx2x_fp_txdata txdata[BNX2X_MULTI_TX_COS];
struct sw_rx_bd *rx_buf_ring; /* BDs mappings ring */
struct sw_rx_page *rx_page_ring; /* SGE pages mappings ring */
@@ -366,32 +473,15 @@ struct bnx2x_fastpath {
u64 sge_mask[RX_SGE_MASK_LEN];
- int state;
-#define BNX2X_FP_STATE_CLOSED 0
-#define BNX2X_FP_STATE_IRQ 0x80000
-#define BNX2X_FP_STATE_OPENING 0x90000
-#define BNX2X_FP_STATE_OPEN 0xa0000
-#define BNX2X_FP_STATE_HALTING 0xb0000
-#define BNX2X_FP_STATE_HALTED 0xc0000
-#define BNX2X_FP_STATE_TERMINATING 0xd0000
-#define BNX2X_FP_STATE_TERMINATED 0xe0000
+ u32 cid;
+
+ __le16 fp_hc_idx;
u8 index; /* number in fp array */
u8 cl_id; /* eth client id */
u8 cl_qzone_id;
u8 fw_sb_id; /* status block number in FW */
u8 igu_sb_id; /* status block number in HW */
- u32 cid;
-
- union db_prod tx_db;
-
- u16 tx_pkt_prod;
- u16 tx_pkt_cons;
- u16 tx_bd_prod;
- u16 tx_bd_cons;
- __le16 *tx_cons_sb;
-
- __le16 fp_hc_idx;
u16 rx_bd_prod;
u16 rx_bd_cons;
@@ -401,24 +491,19 @@ struct bnx2x_fastpath {
/* The last maximal completed SGE */
u16 last_max_sge;
__le16 *rx_cons_sb;
-
- unsigned long tx_pkt,
- rx_pkt,
+ unsigned long rx_pkt,
rx_calls;
/* TPA related */
- struct sw_rx_bd tpa_pool[ETH_MAX_AGGREGATION_QUEUES_E1H];
- u8 tpa_state[ETH_MAX_AGGREGATION_QUEUES_E1H];
-#define BNX2X_TPA_START 1
-#define BNX2X_TPA_STOP 2
+ struct bnx2x_agg_info tpa_info[ETH_MAX_AGGREGATION_QUEUES_E1H_E2];
u8 disable_tpa;
#ifdef BNX2X_STOP_ON_ERROR
u64 tpa_queue_used;
#endif
- struct tstorm_per_client_stats old_tclient;
- struct ustorm_per_client_stats old_uclient;
- struct xstorm_per_client_stats old_xclient;
+ struct tstorm_per_queue_stats old_tclient;
+ struct ustorm_per_queue_stats old_uclient;
+ struct xstorm_per_queue_stats old_xclient;
struct bnx2x_eth_q_stats eth_q_stats;
/* The size is calculated using the following:
@@ -427,7 +512,13 @@ struct bnx2x_fastpath {
4 (for the digits and to make it DWORD aligned) */
#define FP_NAME_SIZE (sizeof(((struct net_device *)0)->name) + 8)
char name[FP_NAME_SIZE];
- struct bnx2x *bp; /* parent */
+
+ /* MACs object */
+ struct bnx2x_vlan_mac_obj mac_obj;
+
+ /* Queue State object */
+ struct bnx2x_queue_sp_obj q_obj;
+
};
#define bnx2x_fp(bp, nr, var) (bp->fp[nr].var)
@@ -435,11 +526,17 @@ struct bnx2x_fastpath {
/* Use 2500 as a mini-jumbo MTU for FCoE */
#define BNX2X_FCOE_MINI_JUMBO_MTU 2500
-#ifdef BCM_CNIC
-/* FCoE L2 `fastpath' is right after the eth entries */
+/* FCoE L2 `fastpath' entry is right after the eth entries */
#define FCOE_IDX BNX2X_NUM_ETH_QUEUES(bp)
#define bnx2x_fcoe_fp(bp) (&bp->fp[FCOE_IDX])
#define bnx2x_fcoe(bp, var) (bnx2x_fcoe_fp(bp)->var)
+#define bnx2x_fcoe_tx(bp, var) (bnx2x_fcoe_fp(bp)-> \
+ txdata[FIRST_TX_COS_INDEX].var)
+
+
+#define IS_ETH_FP(fp) (fp->index < \
+ BNX2X_NUM_ETH_QUEUES(fp->bp))
+#ifdef BCM_CNIC
#define IS_FCOE_FP(fp) (fp->index == FCOE_IDX)
#define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX)
#else
@@ -449,77 +546,68 @@ struct bnx2x_fastpath {
/* MC hsi */
-#define MAX_FETCH_BD 13 /* HW max BDs per packet */
-#define RX_COPY_THRESH 92
+#define MAX_FETCH_BD 13 /* HW max BDs per packet */
+#define RX_COPY_THRESH 92
-#define NUM_TX_RINGS 16
+#define NUM_TX_RINGS 16
#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_tx_bd_types))
-#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
-#define NUM_TX_BD (TX_DESC_CNT * NUM_TX_RINGS)
-#define MAX_TX_BD (NUM_TX_BD - 1)
-#define MAX_TX_AVAIL (MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
-#define INIT_JUMBO_TX_RING_SIZE MAX_TX_AVAIL
-#define INIT_TX_RING_SIZE MAX_TX_AVAIL
+#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+#define NUM_TX_BD (TX_DESC_CNT * NUM_TX_RINGS)
+#define MAX_TX_BD (NUM_TX_BD - 1)
+#define MAX_TX_AVAIL (MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
#define NEXT_TX_IDX(x) ((((x) & MAX_TX_DESC_CNT) == \
(MAX_TX_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
-#define TX_BD(x) ((x) & MAX_TX_BD)
-#define TX_BD_POFF(x) ((x) & MAX_TX_DESC_CNT)
+#define TX_BD(x) ((x) & MAX_TX_BD)
+#define TX_BD_POFF(x) ((x) & MAX_TX_DESC_CNT)
/* The RX BD ring is special, each bd is 8 bytes but the last one is 16 */
-#define NUM_RX_RINGS 8
+#define NUM_RX_RINGS 8
#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
-#define MAX_RX_DESC_CNT (RX_DESC_CNT - 2)
-#define RX_DESC_MASK (RX_DESC_CNT - 1)
-#define NUM_RX_BD (RX_DESC_CNT * NUM_RX_RINGS)
-#define MAX_RX_BD (NUM_RX_BD - 1)
-#define MAX_RX_AVAIL (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
-#define MIN_RX_SIZE_TPA 72
-#define MIN_RX_SIZE_NONTPA 10
-#define INIT_JUMBO_RX_RING_SIZE MAX_RX_AVAIL
-#define INIT_RX_RING_SIZE MAX_RX_AVAIL
+#define MAX_RX_DESC_CNT (RX_DESC_CNT - 2)
+#define RX_DESC_MASK (RX_DESC_CNT - 1)
+#define NUM_RX_BD (RX_DESC_CNT * NUM_RX_RINGS)
+#define MAX_RX_BD (NUM_RX_BD - 1)
+#define MAX_RX_AVAIL (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
+#define MIN_RX_AVAIL 128
+
+#define MIN_RX_SIZE_TPA_HW (CHIP_IS_E1(bp) ? \
+ ETH_MIN_RX_CQES_WITH_TPA_E1 : \
+ ETH_MIN_RX_CQES_WITH_TPA_E1H_E2)
+#define MIN_RX_SIZE_NONTPA_HW ETH_MIN_RX_CQES_WITHOUT_TPA
+#define MIN_RX_SIZE_TPA (max_t(u32, MIN_RX_SIZE_TPA_HW, MIN_RX_AVAIL))
+#define MIN_RX_SIZE_NONTPA (max_t(u32, MIN_RX_SIZE_NONTPA_HW,\
+ MIN_RX_AVAIL))
+
#define NEXT_RX_IDX(x) ((((x) & RX_DESC_MASK) == \
(MAX_RX_DESC_CNT - 1)) ? (x) + 3 : (x) + 1)
-#define RX_BD(x) ((x) & MAX_RX_BD)
+#define RX_BD(x) ((x) & MAX_RX_BD)
-/* As long as CQE is 4 times bigger than BD entry we have to allocate
- 4 times more pages for CQ ring in order to keep it balanced with
- BD ring */
-#define NUM_RCQ_RINGS (NUM_RX_RINGS * 4)
+/*
+ * As long as CQE is X times bigger than BD entry we have to allocate X times
+ * more pages for CQ ring in order to keep it balanced with BD ring
+ */
+#define CQE_BD_REL (sizeof(union eth_rx_cqe) / sizeof(struct eth_rx_bd))
+#define NUM_RCQ_RINGS (NUM_RX_RINGS * CQE_BD_REL)
#define RCQ_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
-#define MAX_RCQ_DESC_CNT (RCQ_DESC_CNT - 1)
-#define NUM_RCQ_BD (RCQ_DESC_CNT * NUM_RCQ_RINGS)
-#define MAX_RCQ_BD (NUM_RCQ_BD - 1)
-#define MAX_RCQ_AVAIL (MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
+#define MAX_RCQ_DESC_CNT (RCQ_DESC_CNT - 1)
+#define NUM_RCQ_BD (RCQ_DESC_CNT * NUM_RCQ_RINGS)
+#define MAX_RCQ_BD (NUM_RCQ_BD - 1)
+#define MAX_RCQ_AVAIL (MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
#define NEXT_RCQ_IDX(x) ((((x) & MAX_RCQ_DESC_CNT) == \
(MAX_RCQ_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
-#define RCQ_BD(x) ((x) & MAX_RCQ_BD)
+#define RCQ_BD(x) ((x) & MAX_RCQ_BD)
/* This is needed for determining of last_max */
-#define SUB_S16(a, b) (s16)((s16)(a) - (s16)(b))
+#define SUB_S16(a, b) (s16)((s16)(a) - (s16)(b))
+#define SUB_S32(a, b) (s32)((s32)(a) - (s32)(b))
-#define __SGE_MASK_SET_BIT(el, bit) \
- do { \
- el = ((el) | ((u64)0x1 << (bit))); \
- } while (0)
-
-#define __SGE_MASK_CLEAR_BIT(el, bit) \
- do { \
- el = ((el) & (~((u64)0x1 << (bit)))); \
- } while (0)
-
-#define SGE_MASK_SET_BIT(fp, idx) \
- __SGE_MASK_SET_BIT(fp->sge_mask[(idx) >> RX_SGE_MASK_ELEM_SHIFT], \
- ((idx) & RX_SGE_MASK_ELEM_MASK))
-
-#define SGE_MASK_CLEAR_BIT(fp, idx) \
- __SGE_MASK_CLEAR_BIT(fp->sge_mask[(idx) >> RX_SGE_MASK_ELEM_SHIFT], \
- ((idx) & RX_SGE_MASK_ELEM_MASK))
+#define BNX2X_SWCID_SHIFT 17
+#define BNX2X_SWCID_MASK ((0x1 << BNX2X_SWCID_SHIFT) - 1)
/* used on a CID received from the HW */
-#define SW_CID(x) (le32_to_cpu(x) & \
- (COMMON_RAMROD_ETH_RX_CQE_CID >> 7))
+#define SW_CID(x) (le32_to_cpu(x) & BNX2X_SWCID_MASK)
#define CQE_CMD(x) (le32_to_cpu(x) >> \
COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT)
@@ -529,6 +617,9 @@ struct bnx2x_fastpath {
#define BNX2X_DB_MIN_SHIFT 3 /* 8 bytes */
#define BNX2X_DB_SHIFT 7 /* 128 bytes*/
+#if (BNX2X_DB_SHIFT < BNX2X_DB_MIN_SHIFT)
+#error "Min DB doorbell stride is 8"
+#endif
#define DPM_TRIGER_TYPE 0x40
#define DOORBELL(bp, cid, val) \
do { \
@@ -557,13 +648,11 @@ struct bnx2x_fastpath {
/* stuff added to make the code fit 80Col */
-
-#define CQE_TYPE(cqe_fp_flags) ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
-
-#define TPA_TYPE_START ETH_FAST_PATH_RX_CQE_START_FLG
-#define TPA_TYPE_END ETH_FAST_PATH_RX_CQE_END_FLG
-#define TPA_TYPE(cqe_fp_flags) ((cqe_fp_flags) & \
- (TPA_TYPE_START | TPA_TYPE_END))
+#define CQE_TYPE(cqe_fp_flags) ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
+#define CQE_TYPE_START(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_START_AGG)
+#define CQE_TYPE_STOP(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_STOP_AGG)
+#define CQE_TYPE_SLOW(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_RAMROD)
+#define CQE_TYPE_FAST(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_FASTPATH)
#define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
@@ -590,15 +679,38 @@ struct bnx2x_fastpath {
#define BNX2X_RX_SUM_FIX(cqe) \
BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
-#define U_SB_ETH_RX_CQ_INDEX 1
-#define U_SB_ETH_RX_BD_INDEX 2
-#define C_SB_ETH_TX_CQ_INDEX 5
+
+#define FP_USB_FUNC_OFF \
+ offsetof(struct cstorm_status_block_u, func)
+#define FP_CSB_FUNC_OFF \
+ offsetof(struct cstorm_status_block_c, func)
+
+#define HC_INDEX_TOE_RX_CQ_CONS 0 /* Formerly Ustorm TOE CQ index */
+ /* (HC_INDEX_U_TOE_RX_CQ_CONS) */
+#define HC_INDEX_ETH_RX_CQ_CONS 1 /* Formerly Ustorm ETH CQ index */
+ /* (HC_INDEX_U_ETH_RX_CQ_CONS) */
+#define HC_INDEX_ETH_RX_BD_CONS 2 /* Formerly Ustorm ETH BD index */
+ /* (HC_INDEX_U_ETH_RX_BD_CONS) */
+
+#define HC_INDEX_TOE_TX_CQ_CONS 4 /* Formerly Cstorm TOE CQ index */
+ /* (HC_INDEX_C_TOE_TX_CQ_CONS) */
+#define HC_INDEX_ETH_TX_CQ_CONS_COS0 5 /* Formerly Cstorm ETH CQ index */
+ /* (HC_INDEX_C_ETH_TX_CQ_CONS) */
+#define HC_INDEX_ETH_TX_CQ_CONS_COS1 6 /* Formerly Cstorm ETH CQ index */
+ /* (HC_INDEX_C_ETH_TX_CQ_CONS) */
+#define HC_INDEX_ETH_TX_CQ_CONS_COS2 7 /* Formerly Cstorm ETH CQ index */
+ /* (HC_INDEX_C_ETH_TX_CQ_CONS) */
+
+#define HC_INDEX_ETH_FIRST_TX_CQ_CONS HC_INDEX_ETH_TX_CQ_CONS_COS0
+
#define BNX2X_RX_SB_INDEX \
- (&fp->sb_index_values[U_SB_ETH_RX_CQ_INDEX])
+ (&fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS])
-#define BNX2X_TX_SB_INDEX \
- (&fp->sb_index_values[C_SB_ETH_TX_CQ_INDEX])
+#define BNX2X_TX_SB_INDEX_BASE BNX2X_TX_SB_INDEX_COS0
+
+#define BNX2X_TX_SB_INDEX_COS0 \
+ (&fp->sb_index_values[HC_INDEX_ETH_TX_CQ_CONS_COS0])
/* end of fast path */
@@ -615,41 +727,74 @@ struct bnx2x_common {
#define CHIP_NUM_57711 0x164f
#define CHIP_NUM_57711E 0x1650
#define CHIP_NUM_57712 0x1662
-#define CHIP_NUM_57712E 0x1663
+#define CHIP_NUM_57712_MF 0x1663
+#define CHIP_NUM_57713 0x1651
+#define CHIP_NUM_57713E 0x1652
+#define CHIP_NUM_57800 0x168a
+#define CHIP_NUM_57800_MF 0x16a5
+#define CHIP_NUM_57810 0x168e
+#define CHIP_NUM_57810_MF 0x16ae
+#define CHIP_NUM_57840 0x168d
+#define CHIP_NUM_57840_MF 0x16ab
#define CHIP_IS_E1(bp) (CHIP_NUM(bp) == CHIP_NUM_57710)
#define CHIP_IS_57711(bp) (CHIP_NUM(bp) == CHIP_NUM_57711)
#define CHIP_IS_57711E(bp) (CHIP_NUM(bp) == CHIP_NUM_57711E)
#define CHIP_IS_57712(bp) (CHIP_NUM(bp) == CHIP_NUM_57712)
-#define CHIP_IS_57712E(bp) (CHIP_NUM(bp) == CHIP_NUM_57712E)
+#define CHIP_IS_57712_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57712_MF)
+#define CHIP_IS_57800(bp) (CHIP_NUM(bp) == CHIP_NUM_57800)
+#define CHIP_IS_57800_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57800_MF)
+#define CHIP_IS_57810(bp) (CHIP_NUM(bp) == CHIP_NUM_57810)
+#define CHIP_IS_57810_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57810_MF)
+#define CHIP_IS_57840(bp) (CHIP_NUM(bp) == CHIP_NUM_57840)
+#define CHIP_IS_57840_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57840_MF)
#define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \
CHIP_IS_57711E(bp))
#define CHIP_IS_E2(bp) (CHIP_IS_57712(bp) || \
- CHIP_IS_57712E(bp))
+ CHIP_IS_57712_MF(bp))
+#define CHIP_IS_E3(bp) (CHIP_IS_57800(bp) || \
+ CHIP_IS_57800_MF(bp) || \
+ CHIP_IS_57810(bp) || \
+ CHIP_IS_57810_MF(bp) || \
+ CHIP_IS_57840(bp) || \
+ CHIP_IS_57840_MF(bp))
#define CHIP_IS_E1x(bp) (CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
-#define IS_E1H_OFFSET (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp))
-
-#define CHIP_REV(bp) (bp->common.chip_id & 0x0000f000)
-#define CHIP_REV_Ax 0x00000000
+#define USES_WARPCORE(bp) (CHIP_IS_E3(bp))
+#define IS_E1H_OFFSET (!CHIP_IS_E1(bp))
+
+#define CHIP_REV_SHIFT 12
+#define CHIP_REV_MASK (0xF << CHIP_REV_SHIFT)
+#define CHIP_REV_VAL(bp) (bp->common.chip_id & CHIP_REV_MASK)
+#define CHIP_REV_Ax (0x0 << CHIP_REV_SHIFT)
+#define CHIP_REV_Bx (0x1 << CHIP_REV_SHIFT)
/* assume maximum 5 revisions */
-#define CHIP_REV_IS_SLOW(bp) (CHIP_REV(bp) > 0x00005000)
+#define CHIP_REV_IS_SLOW(bp) (CHIP_REV_VAL(bp) > 0x00005000)
/* Emul versions are A=>0xe, B=>0xc, C=>0xa, D=>8, E=>6 */
#define CHIP_REV_IS_EMUL(bp) ((CHIP_REV_IS_SLOW(bp)) && \
- !(CHIP_REV(bp) & 0x00001000))
+ !(CHIP_REV_VAL(bp) & 0x00001000))
/* FPGA versions are A=>0xf, B=>0xd, C=>0xb, D=>9, E=>7 */
#define CHIP_REV_IS_FPGA(bp) ((CHIP_REV_IS_SLOW(bp)) && \
- (CHIP_REV(bp) & 0x00001000))
+ (CHIP_REV_VAL(bp) & 0x00001000))
#define CHIP_TIME(bp) ((CHIP_REV_IS_EMUL(bp)) ? 2000 : \
((CHIP_REV_IS_FPGA(bp)) ? 200 : 1))
#define CHIP_METAL(bp) (bp->common.chip_id & 0x00000ff0)
#define CHIP_BOND_ID(bp) (bp->common.chip_id & 0x0000000f)
-#define CHIP_PARITY_ENABLED(bp) (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp))
+#define CHIP_REV_SIM(bp) (((CHIP_REV_MASK - CHIP_REV_VAL(bp)) >>\
+ (CHIP_REV_SHIFT + 1)) \
+ << CHIP_REV_SHIFT)
+#define CHIP_REV(bp) (CHIP_REV_IS_SLOW(bp) ? \
+ CHIP_REV_SIM(bp) :\
+ CHIP_REV_VAL(bp))
+#define CHIP_IS_E3B0(bp) (CHIP_IS_E3(bp) && \
+ (CHIP_REV(bp) == CHIP_REV_Bx))
+#define CHIP_IS_E3A0(bp) (CHIP_IS_E3(bp) && \
+ (CHIP_REV(bp) == CHIP_REV_Ax))
int flash_size;
-#define NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */
-#define NVRAM_TIMEOUT_COUNT 30000
-#define NVRAM_PAGE_SIZE 256
+#define BNX2X_NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */
+#define BNX2X_NVRAM_TIMEOUT_COUNT 30000
+#define BNX2X_NVRAM_PAGE_SIZE 256
u32 shmem_base;
u32 shmem2_base;
@@ -666,7 +811,7 @@ struct bnx2x_common {
#define INT_BLOCK_MODE_NORMAL 0
#define INT_BLOCK_MODE_BW_COMP 2
#define CHIP_INT_MODE_IS_NBC(bp) \
- (CHIP_IS_E2(bp) && \
+ (!CHIP_IS_E1x(bp) && \
!((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
#define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
@@ -712,19 +857,15 @@ struct bnx2x_port {
/* end of port */
-/* e1h Classification CAM line allocations */
-enum {
- CAM_ETH_LINE = 0,
- CAM_ISCSI_ETH_LINE,
- CAM_FIP_ETH_LINE,
- CAM_FIP_MCAST_LINE,
- CAM_MAX_PF_LINE = CAM_FIP_MCAST_LINE
-};
-/* number of MACs per function in NIG memory - used for SI mode */
-#define NIG_LLH_FUNC_MEM_SIZE 16
-/* number of entries in NIG_REG_LLHX_FUNC_MEM */
-#define NIG_LLH_FUNC_MEM_MAX_OFFSET 8
+#define STATS_OFFSET32(stat_name) \
+ (offsetof(struct bnx2x_eth_stats, stat_name) / 4)
+/* slow path */
+
+/* slow path work-queue */
+extern struct workqueue_struct *bnx2x_wq;
+
+#define BNX2X_MAX_NUM_OF_VFS 64
#define BNX2X_VF_ID_INVALID 0xFF
/*
@@ -749,27 +890,10 @@ enum {
* L2 queue is supported. the cid for the FCoE L2 queue is always X.
*/
-#define FP_SB_MAX_E1x 16 /* fast-path interrupt contexts E1x */
-#define FP_SB_MAX_E2 16 /* fast-path interrupt contexts E2 */
-
-/*
- * cid_cnt paramter below refers to the value returned by
- * 'bnx2x_get_l2_cid_count()' routine
- */
-
-/*
- * The number of FP context allocated by the driver == max number of regular
- * L2 queues + 1 for the FCoE L2 queue
- */
-#define L2_FP_COUNT(cid_cnt) ((cid_cnt) - CNIC_CONTEXT_USE)
-
-/*
- * The number of FP-SB allocated by the driver == max number of regular L2
- * queues + 1 for the CNIC which also consumes an FP-SB
- */
-#define FP_SB_COUNT(cid_cnt) ((cid_cnt) - FCOE_CONTEXT_USE)
-#define NUM_IGU_SB_REQUIRED(cid_cnt) \
- (FP_SB_COUNT(cid_cnt) - NONE_ETH_CONTEXT_USE)
+/* fast-path interrupt contexts E1x */
+#define FP_SB_MAX_E1x 16
+/* fast-path interrupt contexts E2 */
+#define FP_SB_MAX_E2 HC_SB_MAX_SB_E2
union cdu_context {
struct eth_context eth;
@@ -778,7 +902,7 @@ union cdu_context {
/* CDU host DB constants */
#define CDU_ILT_PAGE_SZ_HW 3
-#define CDU_ILT_PAGE_SZ (4096 << CDU_ILT_PAGE_SZ_HW) /* 32K */
+#define CDU_ILT_PAGE_SZ (8192 << CDU_ILT_PAGE_SZ_HW) /* 64K */
#define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
#ifdef BCM_CNIC
@@ -788,38 +912,63 @@ union cdu_context {
#define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
#endif
-#define QM_ILT_PAGE_SZ_HW 3
-#define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 32K */
+#define QM_ILT_PAGE_SZ_HW 0
+#define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
#define QM_CID_ROUND 1024
#ifdef BCM_CNIC
/* TM (timers) host DB constants */
-#define TM_ILT_PAGE_SZ_HW 2
-#define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 16K */
+#define TM_ILT_PAGE_SZ_HW 0
+#define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
/* #define TM_CONN_NUM (CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
#define TM_CONN_NUM 1024
#define TM_ILT_SZ (8 * TM_CONN_NUM)
#define TM_ILT_LINES DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
/* SRC (Searcher) host DB constants */
-#define SRC_ILT_PAGE_SZ_HW 3
-#define SRC_ILT_PAGE_SZ (4096 << SRC_ILT_PAGE_SZ_HW) /* 32K */
+#define SRC_ILT_PAGE_SZ_HW 0
+#define SRC_ILT_PAGE_SZ (4096 << SRC_ILT_PAGE_SZ_HW) /* 4K */
#define SRC_HASH_BITS 10
#define SRC_CONN_NUM (1 << SRC_HASH_BITS) /* 1024 */
#define SRC_ILT_SZ (sizeof(struct src_ent) * SRC_CONN_NUM)
#define SRC_T2_SZ SRC_ILT_SZ
#define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
+
#endif
-#define MAX_DMAE_C 8
+#define MAX_DMAE_C 8
/* DMA memory not used in fastpath */
struct bnx2x_slowpath {
- struct eth_stats_query fw_stats;
- struct mac_configuration_cmd mac_config;
- struct mac_configuration_cmd mcast_config;
- struct mac_configuration_cmd uc_mac_config;
- struct client_init_ramrod_data client_init_data;
+ union {
+ struct mac_configuration_cmd e1x;
+ struct eth_classify_rules_ramrod_data e2;
+ } mac_rdata;
+
+
+ union {
+ struct tstorm_eth_mac_filter_config e1x;
+ struct eth_filter_rules_ramrod_data e2;
+ } rx_mode_rdata;
+
+ union {
+ struct mac_configuration_cmd e1;
+ struct eth_multicast_rules_ramrod_data e2;
+ } mcast_rdata;
+
+ struct eth_rss_update_ramrod_data rss_rdata;
+
+ /* Queue State related ramrods are always sent under rtnl_lock */
+ union {
+ struct client_init_ramrod_data init_data;
+ struct client_update_ramrod_data update_data;
+ } q_rdata;
+
+ union {
+ struct function_start_data func_start;
+ /* pfc configuration for DCBX ramrod */
+ struct flow_control_configuration pfc_config;
+ } func_rdata;
/* used by dmae command executer */
struct dmae_command dmae[MAX_DMAE_C];
@@ -833,8 +982,6 @@ struct bnx2x_slowpath {
u32 wb_comp;
u32 wb_data[4];
- /* pfc configuration for DCBX ramrod */
- struct flow_control_configuration pfc_config;
};
#define bnx2x_sp(bp, var) (&bp->slowpath->var)
@@ -846,7 +993,7 @@ struct bnx2x_slowpath {
#define MAX_DYNAMIC_ATTN_GRPS 8
struct attn_route {
- u32 sig[5];
+ u32 sig[5];
};
struct iro {
@@ -866,13 +1013,15 @@ struct hw_context {
/* forward */
struct bnx2x_ilt;
-typedef enum {
+
+enum bnx2x_recovery_state {
BNX2X_RECOVERY_DONE,
BNX2X_RECOVERY_INIT,
BNX2X_RECOVERY_WAIT,
-} bnx2x_recovery_state_t;
+ BNX2X_RECOVERY_FAILED
+};
-/**
+/*
* Event queue (EQ or event ring) MC hsi
* NUM_EQ_PAGES and EQ_DESC_CNT_PAGE must be power of 2
*/
@@ -910,6 +1059,31 @@ enum {
BNX2X_LINK_REPORT_TX_FC_ON,
};
+enum {
+ BNX2X_PORT_QUERY_IDX,
+ BNX2X_PF_QUERY_IDX,
+ BNX2X_FIRST_QUEUE_QUERY_IDX,
+};
+
+struct bnx2x_fw_stats_req {
+ struct stats_query_header hdr;
+ struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
+};
+
+struct bnx2x_fw_stats_data {
+ struct stats_counter storm_counters;
+ struct per_port_stats port;
+ struct per_pf_stats pf;
+ struct per_queue_stats queue_stats[1];
+};
+
+/* Public slow path states */
+enum {
+ BNX2X_SP_RTNL_SETUP_TC,
+ BNX2X_SP_RTNL_TX_TIMEOUT,
+};
+
+
struct bnx2x {
/* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure
@@ -919,19 +1093,28 @@ struct bnx2x {
void __iomem *doorbells;
u16 db_size;
+ u8 pf_num; /* absolute PF number */
+ u8 pfid; /* per-path PF number */
+ int base_fw_ndsb; /**/
+#define BP_PATH(bp) (CHIP_IS_E1x(bp) ? 0 : (bp->pf_num & 1))
+#define BP_PORT(bp) (bp->pfid & 1)
+#define BP_FUNC(bp) (bp->pfid)
+#define BP_ABS_FUNC(bp) (bp->pf_num)
+#define BP_E1HVN(bp) (bp->pfid >> 1)
+#define BP_VN(bp) (BP_E1HVN(bp)) /*remove when approved*/
+#define BP_L_ID(bp) (BP_E1HVN(bp) << 2)
+#define BP_FW_MB_IDX(bp) (BP_PORT(bp) +\
+ BP_VN(bp) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2 : 1))
+
struct net_device *dev;
struct pci_dev *pdev;
- struct iro *iro_arr;
+ const struct iro *iro_arr;
#define IRO (bp->iro_arr)
- atomic_t intr_sem;
-
- bnx2x_recovery_state_t recovery_state;
+ enum bnx2x_recovery_state recovery_state;
int is_leader;
struct msix_entry *msix_table;
-#define INT_MODE_INTx 1
-#define INT_MODE_MSI 2
int tx_ring_size;
@@ -944,7 +1127,8 @@ struct bnx2x {
/* Max supported alignment is 256 (8 shift) */
#define BNX2X_RX_ALIGN_SHIFT ((L1_CACHE_SHIFT < 8) ? \
L1_CACHE_SHIFT : 8)
-#define BNX2X_RX_ALIGN (1 << BNX2X_RX_ALIGN_SHIFT)
+ /* FW use 2 Cache lines Alignment for start packet and size */
+#define BNX2X_FW_RX_ALIGN (2 << BNX2X_RX_ALIGN_SHIFT)
#define BNX2X_PXP_DRAM_ALIGN (BNX2X_RX_ALIGN_SHIFT - 5)
struct host_sp_status_block *def_status_blk;
@@ -974,10 +1158,12 @@ struct bnx2x {
__le16 *eq_cons_sb;
atomic_t eq_spq_left; /* COMMON_XXX ramrods credit */
- /* Flags for marking that there is a STAT_QUERY or
- SET_MAC ramrod pending */
- int stats_pending;
- int set_mac_pending;
+
+
+ /* Counter for marking that there is a STAT_QUERY ramrod pending */
+ u16 stats_pending;
+ /* Counter for completed statistics ramrods */
+ u16 stats_comp;
/* End of fields used in the performance code paths */
@@ -985,54 +1171,35 @@ struct bnx2x {
int msg_enable;
u32 flags;
-#define PCIX_FLAG 1
-#define PCI_32BIT_FLAG 2
-#define ONE_PORT_FLAG 4
-#define NO_WOL_FLAG 8
-#define USING_DAC_FLAG 0x10
-#define USING_MSIX_FLAG 0x20
-#define USING_MSI_FLAG 0x40
-
-#define TPA_ENABLE_FLAG 0x80
-#define NO_MCP_FLAG 0x100
-#define DISABLE_MSI_FLAG 0x200
+#define PCIX_FLAG (1 << 0)
+#define PCI_32BIT_FLAG (1 << 1)
+#define ONE_PORT_FLAG (1 << 2)
+#define NO_WOL_FLAG (1 << 3)
+#define USING_DAC_FLAG (1 << 4)
+#define USING_MSIX_FLAG (1 << 5)
+#define USING_MSI_FLAG (1 << 6)
+#define DISABLE_MSI_FLAG (1 << 7)
+#define TPA_ENABLE_FLAG (1 << 8)
+#define NO_MCP_FLAG (1 << 9)
+
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
-#define MF_FUNC_DIS 0x1000
-#define FCOE_MACS_SET 0x2000
-#define NO_FCOE_FLAG 0x4000
-#define NO_ISCSI_OOO_FLAG 0x8000
-#define NO_ISCSI_FLAG 0x10000
+#define MF_FUNC_DIS (1 << 11)
+#define OWN_CNIC_IRQ (1 << 12)
+#define NO_ISCSI_OOO_FLAG (1 << 13)
+#define NO_ISCSI_FLAG (1 << 14)
+#define NO_FCOE_FLAG (1 << 15)
-#define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG)
#define NO_ISCSI(bp) ((bp)->flags & NO_ISCSI_FLAG)
#define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG)
-
- int pf_num; /* absolute PF number */
- int pfid; /* per-path PF number */
- int base_fw_ndsb;
-#define BP_PATH(bp) (!CHIP_IS_E2(bp) ? \
- 0 : (bp->pf_num & 1))
-#define BP_PORT(bp) (bp->pfid & 1)
-#define BP_FUNC(bp) (bp->pfid)
-#define BP_ABS_FUNC(bp) (bp->pf_num)
-#define BP_E1HVN(bp) (bp->pfid >> 1)
-#define BP_VN(bp) (CHIP_MODE_IS_4_PORT(bp) ? \
- 0 : BP_E1HVN(bp))
-#define BP_L_ID(bp) (BP_E1HVN(bp) << 2)
-#define BP_FW_MB_IDX(bp) (BP_PORT(bp) +\
- BP_VN(bp) * (CHIP_IS_E1x(bp) ? 2 : 1))
-
-#ifdef BCM_CNIC
-#define BCM_CNIC_CID_START 16
-#define BCM_ISCSI_ETH_CL_ID 17
-#endif
+#define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG)
int pm_cap;
- int pcie_cap;
int mrrs;
struct delayed_work sp_task;
- struct delayed_work reset_task;
+ struct delayed_work sp_rtnl_task;
+
+ struct delayed_work period_task;
struct timer_list timer;
int current_interval;
@@ -1052,9 +1219,9 @@ struct bnx2x {
struct cmng_struct_per_port cmng;
u32 vn_weight_sum;
-
u32 mf_config[E1HVN_MAX];
u32 mf2_config[E2_FUNC_MAX];
+ u32 path_has_ovlan; /* E3 */
u16 mf_ov;
u8 mf_mode;
#define IS_MF(bp) (bp->mf_mode != 0)
@@ -1079,33 +1246,24 @@ struct bnx2x {
u32 lin_cnt;
- int state;
+ u16 state;
#define BNX2X_STATE_CLOSED 0
#define BNX2X_STATE_OPENING_WAIT4_LOAD 0x1000
#define BNX2X_STATE_OPENING_WAIT4_PORT 0x2000
#define BNX2X_STATE_OPEN 0x3000
#define BNX2X_STATE_CLOSING_WAIT4_HALT 0x4000
#define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000
-#define BNX2X_STATE_CLOSING_WAIT4_UNLOAD 0x6000
-#define BNX2X_STATE_FUNC_STARTED 0x7000
+
#define BNX2X_STATE_DIAG 0xe000
#define BNX2X_STATE_ERROR 0xf000
int multi_mode;
+#define BNX2X_MAX_PRIORITY 8
+#define BNX2X_MAX_ENTRIES_PER_PRI 16
+#define BNX2X_MAX_COS 3
+#define BNX2X_MAX_TX_COS 2
int num_queues;
int disable_tpa;
- int int_mode;
- u32 *rx_indir_table;
-
- struct tstorm_eth_mac_filter_config mac_filters;
-#define BNX2X_ACCEPT_NONE 0x0000
-#define BNX2X_ACCEPT_UNICAST 0x0001
-#define BNX2X_ACCEPT_MULTICAST 0x0002
-#define BNX2X_ACCEPT_ALL_UNICAST 0x0004
-#define BNX2X_ACCEPT_ALL_MULTICAST 0x0008
-#define BNX2X_ACCEPT_BROADCAST 0x0010
-#define BNX2X_ACCEPT_UNMATCHED_UCAST 0x0020
-#define BNX2X_PROMISCUOUS_MODE 0x10000
u32 rx_mode;
#define BNX2X_RX_MODE_NONE 0
@@ -1113,7 +1271,6 @@ struct bnx2x {
#define BNX2X_RX_MODE_ALLMULTI 2
#define BNX2X_RX_MODE_PROMISC 3
#define BNX2X_MAX_MULTICAST 64
-#define BNX2X_MAX_EMUL_MULTI 16
u8 igu_dsb_id;
u8 igu_base_sb;
@@ -1122,16 +1279,53 @@ struct bnx2x {
struct bnx2x_slowpath *slowpath;
dma_addr_t slowpath_mapping;
+
+ /* Total number of FW statistics requests */
+ u8 fw_stats_num;
+
+ /*
+ * This is a memory buffer that will contain both statistics
+ * ramrod request and data.
+ */
+ void *fw_stats;
+ dma_addr_t fw_stats_mapping;
+
+ /*
+ * FW statistics request shortcut (points at the
+ * beginning of fw_stats buffer).
+ */
+ struct bnx2x_fw_stats_req *fw_stats_req;
+ dma_addr_t fw_stats_req_mapping;
+ int fw_stats_req_sz;
+
+ /*
+ * FW statistics data shortcut (points at the begining of
+ * fw_stats buffer + fw_stats_req_sz).
+ */
+ struct bnx2x_fw_stats_data *fw_stats_data;
+ dma_addr_t fw_stats_data_mapping;
+ int fw_stats_data_sz;
+
struct hw_context context;
struct bnx2x_ilt *ilt;
#define BP_ILT(bp) ((bp)->ilt)
-#define ILT_MAX_LINES 128
+#define ILT_MAX_LINES 256
+/*
+ * Maximum supported number of RSS queues: number of IGU SBs minus one that goes
+ * to CNIC.
+ */
+#define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_PRESENT)
- int l2_cid_count;
-#define L2_ILT_LINES(bp) (DIV_ROUND_UP((bp)->l2_cid_count, \
- ILT_PAGE_CIDS))
-#define BNX2X_DB_SIZE(bp) ((bp)->l2_cid_count * (1 << BNX2X_DB_SHIFT))
+/*
+ * Maximum CID count that might be required by the bnx2x:
+ * Max Tss * Max_Tx_Multi_Cos + CNIC L2 Clients (FCoE and iSCSI related)
+ */
+#define BNX2X_L2_CID_COUNT(bp) (MAX_TXQS_PER_COS * BNX2X_MULTI_TX_COS +\
+ NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+#define L2_ILT_LINES(bp) (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
+ ILT_PAGE_CIDS))
+#define BNX2X_DB_SIZE(bp) (BNX2X_L2_CID_COUNT(bp) * (1 << BNX2X_DB_SHIFT))
int qm_cid_count;
@@ -1148,16 +1342,18 @@ struct bnx2x {
struct cnic_eth_dev cnic_eth_dev;
union host_hc_status_block cnic_sb;
dma_addr_t cnic_sb_mapping;
-#define CNIC_SB_ID(bp) ((bp)->base_fw_ndsb + BP_L_ID(bp))
-#define CNIC_IGU_SB_ID(bp) ((bp)->igu_base_sb)
struct eth_spe *cnic_kwq;
struct eth_spe *cnic_kwq_prod;
struct eth_spe *cnic_kwq_cons;
struct eth_spe *cnic_kwq_last;
u16 cnic_kwq_pending;
u16 cnic_spq_pending;
- struct mutex cnic_mutex;
u8 fip_mac[ETH_ALEN];
+ struct mutex cnic_mutex;
+ struct bnx2x_vlan_mac_obj iscsi_l2_mac_obj;
+
+ /* Start index of the "special" (CNIC related) L2 cleints */
+ u8 cnic_base_cl_id;
#endif
int dmae_ready;
@@ -1194,6 +1390,8 @@ struct bnx2x {
u16 *init_ops_offsets;
/* Data blob - has 32 bit granularity */
u32 *init_data;
+ u32 init_mode_flags;
+#define INIT_MODE_FLAGS(bp) (bp->init_mode_flags)
/* Zipped PRAM blobs - raw data */
const u8 *tsem_int_table_data;
const u8 *tsem_pram_data;
@@ -1215,10 +1413,9 @@ struct bnx2x {
#define INIT_CSEM_INT_TABLE_DATA(bp) (bp->csem_int_table_data)
#define INIT_CSEM_PRAM_DATA(bp) (bp->csem_pram_data)
+#define PHY_FW_VER_LEN 20
char fw_ver[32];
const struct firmware *firmware;
- /* LLDP params */
- struct bnx2x_config_lldp_params lldp_config_params;
/* DCB support on/off */
u16 dcb_state;
@@ -1235,59 +1432,56 @@ struct bnx2x {
bool dcbx_mode_uset;
struct bnx2x_config_dcbx_params dcbx_config_params;
-
struct bnx2x_dcbx_port_params dcbx_port_params;
int dcb_version;
- /* DCBX Negotiation results */
+ /* CAM credit pools */
+ struct bnx2x_credit_pool_obj macs_pool;
+
+ /* RX_MODE object */
+ struct bnx2x_rx_mode_obj rx_mode_obj;
+
+ /* MCAST object */
+ struct bnx2x_mcast_obj mcast_obj;
+
+ /* RSS configuration object */
+ struct bnx2x_rss_config_obj rss_conf_obj;
+
+ /* Function State controlling object */
+ struct bnx2x_func_sp_obj func_obj;
+
+ unsigned long sp_state;
+
+ /* operation indication for the sp_rtnl task */
+ unsigned long sp_rtnl_state;
+
+ /* DCBX Negotation results */
struct dcbx_features dcbx_local_feat;
u32 dcbx_error;
+
#ifdef BCM_DCBNL
struct dcbx_features dcbx_remote_feat;
u32 dcbx_remote_flags;
#endif
u32 pending_max;
-};
-/**
- * Init queue/func interface
- */
-/* queue init flags */
-#define QUEUE_FLG_TPA 0x0001
-#define QUEUE_FLG_CACHE_ALIGN 0x0002
-#define QUEUE_FLG_STATS 0x0004
-#define QUEUE_FLG_OV 0x0008
-#define QUEUE_FLG_VLAN 0x0010
-#define QUEUE_FLG_COS 0x0020
-#define QUEUE_FLG_HC 0x0040
-#define QUEUE_FLG_DHC 0x0080
-#define QUEUE_FLG_OOO 0x0100
-
-#define QUEUE_DROP_IP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR
-#define QUEUE_DROP_TCP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR
-#define QUEUE_DROP_TTL0 TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0
-#define QUEUE_DROP_UDP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR
-
-
-
-/* rss capabilities */
-#define RSS_IPV4_CAP 0x0001
-#define RSS_IPV4_TCP_CAP 0x0002
-#define RSS_IPV6_CAP 0x0004
-#define RSS_IPV6_TCP_CAP 0x0008
+ /* multiple tx classes of service */
+ u8 max_cos;
-#define BNX2X_NUM_QUEUES(bp) (bp->num_queues)
-#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NONE_ETH_CONTEXT_USE)
+ /* priority to cos mapping */
+ u8 prio_to_cos[8];
+};
-/* ethtool statistics are displayed for all regular ethernet queues and the
- * fcoe L2 queue if not disabled
- */
-#define BNX2X_NUM_STAT_QUEUES(bp) (NO_FCOE(bp) ? BNX2X_NUM_ETH_QUEUES(bp) : \
- (BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE))
+/* Tx queues may be less or equal to Rx queues */
+extern int num_queues;
+#define BNX2X_NUM_QUEUES(bp) (bp->num_queues)
+#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE)
+#define BNX2X_NUM_RX_QUEUES(bp) BNX2X_NUM_QUEUES(bp)
#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1)
-#define BNX2X_MAX_QUEUES(bp) (bp->igu_sb_cnt - CNIC_CONTEXT_USE)
+#define BNX2X_MAX_QUEUES(bp) BNX2X_MAX_RSS_COUNT(bp)
+/* #define is_eth_multi(bp) (BNX2X_NUM_ETH_QUEUES(bp) > 1) */
#define RSS_IPV4_CAP_MASK \
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
@@ -1302,107 +1496,15 @@ struct bnx2x {
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
/* func init flags */
-#define FUNC_FLG_STATS 0x0001
-#define FUNC_FLG_TPA 0x0002
-#define FUNC_FLG_SPQ 0x0004
-#define FUNC_FLG_LEADING 0x0008 /* PF only */
-
-struct rxq_pause_params {
- u16 bd_th_lo;
- u16 bd_th_hi;
- u16 rcq_th_lo;
- u16 rcq_th_hi;
- u16 sge_th_lo; /* valid iff QUEUE_FLG_TPA */
- u16 sge_th_hi; /* valid iff QUEUE_FLG_TPA */
- u16 pri_map;
-};
+#define FUNC_FLG_RSS 0x0001
+#define FUNC_FLG_STATS 0x0002
+/* removed FUNC_FLG_UNMATCHED 0x0004 */
+#define FUNC_FLG_TPA 0x0008
+#define FUNC_FLG_SPQ 0x0010
+#define FUNC_FLG_LEADING 0x0020 /* PF only */
-struct bnx2x_rxq_init_params {
- /* cxt*/
- struct eth_context *cxt;
-
- /* dma */
- dma_addr_t dscr_map;
- dma_addr_t sge_map;
- dma_addr_t rcq_map;
- dma_addr_t rcq_np_map;
-
- u16 flags;
- u16 drop_flags;
- u16 mtu;
- u16 buf_sz;
- u16 fw_sb_id;
- u16 cl_id;
- u16 spcl_id;
- u16 cl_qzone_id;
-
- /* valid iff QUEUE_FLG_STATS */
- u16 stat_id;
-
- /* valid iff QUEUE_FLG_TPA */
- u16 tpa_agg_sz;
- u16 sge_buf_sz;
- u16 max_sges_pkt;
-
- /* valid iff QUEUE_FLG_CACHE_ALIGN */
- u8 cache_line_log;
-
- u8 sb_cq_index;
- u32 cid;
-
- /* desired interrupts per sec. valid iff QUEUE_FLG_HC */
- u32 hc_rate;
-};
-
-struct bnx2x_txq_init_params {
- /* cxt*/
- struct eth_context *cxt;
-
- /* dma */
- dma_addr_t dscr_map;
-
- u16 flags;
- u16 fw_sb_id;
- u8 sb_cq_index;
- u8 cos; /* valid iff QUEUE_FLG_COS */
- u16 stat_id; /* valid iff QUEUE_FLG_STATS */
- u16 traffic_type;
- u32 cid;
- u16 hc_rate; /* desired interrupts per sec.*/
- /* valid iff QUEUE_FLG_HC */
-
-};
-
-struct bnx2x_client_ramrod_params {
- int *pstate;
- int state;
- u16 index;
- u16 cl_id;
- u32 cid;
- u8 poll;
-#define CLIENT_IS_FCOE 0x01
-#define CLIENT_IS_LEADING_RSS 0x02
- u8 flags;
-};
-
-struct bnx2x_client_init_params {
- struct rxq_pause_params pause;
- struct bnx2x_rxq_init_params rxq_params;
- struct bnx2x_txq_init_params txq_params;
- struct bnx2x_client_ramrod_params ramrod_params;
-};
-
-struct bnx2x_rss_params {
- int mode;
- u16 cap;
- u16 result_mask;
-};
struct bnx2x_func_init_params {
-
- /* rss */
- struct bnx2x_rss_params *rss; /* valid iff FUNC_FLG_RSS */
-
/* dma */
dma_addr_t fw_stat_map; /* valid iff FUNC_FLG_STATS */
dma_addr_t spq_map; /* valid iff FUNC_FLG_SPQ */
@@ -1414,42 +1516,40 @@ struct bnx2x_func_init_params {
};
#define for_each_eth_queue(bp, var) \
- for (var = 0; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
+ for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
#define for_each_nondefault_eth_queue(bp, var) \
- for (var = 1; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
-
-#define for_each_napi_queue(bp, var) \
- for (var = 0; \
- var < BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE; var++) \
- if (skip_queue(bp, var)) \
- continue; \
- else
+ for ((var) = 1; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
#define for_each_queue(bp, var) \
- for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_queue(bp, var)) \
continue; \
else
+/* Skip forwarding FP */
#define for_each_rx_queue(bp, var) \
- for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_rx_queue(bp, var)) \
continue; \
else
+/* Skip OOO FP */
#define for_each_tx_queue(bp, var) \
- for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_tx_queue(bp, var)) \
continue; \
else
#define for_each_nondefault_queue(bp, var) \
- for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++) \
+ for ((var) = 1; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_queue(bp, var)) \
continue; \
else
+#define for_each_cos_in_tx_queue(fp, var) \
+ for ((var) = 0; (var) < (fp)->max_cos; (var)++)
+
/* skip rx queue
* if FCOE l2 support is disabled and this is the fcoe L2 queue
*/
@@ -1462,11 +1562,66 @@ struct bnx2x_func_init_params {
#define skip_queue(bp, idx) (NO_FCOE(bp) && IS_FCOE_IDX(idx))
-#define WAIT_RAMROD_POLL 0x01
-#define WAIT_RAMROD_COMMON 0x02
+
+
+/**
+ * bnx2x_set_mac_one - configure a single MAC address
+ *
+ * @bp: driver handle
+ * @mac: MAC to configure
+ * @obj: MAC object handle
+ * @set: if 'true' add a new MAC, otherwise - delete
+ * @mac_type: the type of the MAC to configure (e.g. ETH, UC list)
+ * @ramrod_flags: RAMROD_XXX flags (e.g. RAMROD_CONT, RAMROD_COMP_WAIT)
+ *
+ * Configures one MAC according to provided parameters or continues the
+ * execution of previously scheduled commands if RAMROD_CONT is set in
+ * ramrod_flags.
+ *
+ * Returns zero if operation has successfully completed, a positive value if the
+ * operation has been successfully scheduled and a negative - if a requested
+ * operations has failed.
+ */
+int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
+ struct bnx2x_vlan_mac_obj *obj, bool set,
+ int mac_type, unsigned long *ramrod_flags);
+/**
+ * Deletes all MACs configured for the specific MAC object.
+ *
+ * @param bp Function driver instance
+ * @param mac_obj MAC object to cleanup
+ *
+ * @return zero if all MACs were cleaned
+ */
+
+/**
+ * bnx2x_del_all_macs - delete all MACs configured for the specific MAC object
+ *
+ * @bp: driver handle
+ * @mac_obj: MAC object handle
+ * @mac_type: type of the MACs to clear (BNX2X_XXX_MAC)
+ * @wait_for_comp: if 'true' block until completion
+ *
+ * Deletes all MACs of the specific type (e.g. ETH, UC list).
+ *
+ * Returns zero if operation has successfully completed, a positive value if the
+ * operation has been successfully scheduled and a negative - if a requested
+ * operations has failed.
+ */
+int bnx2x_del_all_macs(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ int mac_type, bool wait_for_comp);
+
+/* Init Function API */
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p);
+int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
+int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
+int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode);
+int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
void bnx2x_read_mf_cfg(struct bnx2x *bp);
+
/* dmae */
void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
@@ -1477,22 +1632,12 @@ u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode);
u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
bool with_comp, u8 comp_type);
-int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
-int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
void bnx2x_calc_fc_adv(struct bnx2x *bp);
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
- u32 data_hi, u32 data_lo, int common);
-
-/* Clears multicast and unicast list configuration in the chip. */
-void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp);
-void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp);
-void bnx2x_invalidate_uc_list(struct bnx2x *bp);
-
+ u32 data_hi, u32 data_lo, int cmd_type);
void bnx2x_update_coalesce(struct bnx2x *bp);
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
int wait)
@@ -1648,7 +1793,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
/* must be used on a CID before placing it on a HW ring */
#define HW_CID(bp, x) ((BP_PORT(bp) << 23) | \
- (BP_E1HVN(bp) << 17) | (x))
+ (BP_E1HVN(bp) << BNX2X_SWCID_SHIFT) | \
+ (x))
#define SP_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_spe))
#define MAX_SP_DESC_CNT (SP_DESC_CNT - 1)
@@ -1718,12 +1864,14 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
(AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT | \
- AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT)
+ AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT)
#define HW_PRTY_ASSERT_SET_0 (AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR |\
- AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR)
+ AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR)
#define HW_INTERRUT_ASSERT_SET_1 \
(AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT | \
@@ -1736,17 +1884,22 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT)
-#define HW_PRTY_ASSERT_SET_1 (AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR |\
+#define HW_PRTY_ASSERT_SET_1 (AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR | \
- AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR)
+ AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR)
#define HW_INTERRUT_ASSERT_SET_2 \
(AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT | \
@@ -1758,6 +1911,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR)
@@ -1766,6 +1920,9 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
+#define HW_PRTY_ASSERT_SET_4 (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)
+
#define RSS_FLAGS(bp) \
(TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY | \
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY | \
@@ -1775,6 +1932,30 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
#define MULTI_MASK 0x7f
+
+#define DEF_USB_FUNC_OFF offsetof(struct cstorm_def_status_block_u, func)
+#define DEF_CSB_FUNC_OFF offsetof(struct cstorm_def_status_block_c, func)
+#define DEF_XSB_FUNC_OFF offsetof(struct xstorm_def_status_block, func)
+#define DEF_TSB_FUNC_OFF offsetof(struct tstorm_def_status_block, func)
+
+#define DEF_USB_IGU_INDEX_OFF \
+ offsetof(struct cstorm_def_status_block_u, igu_index)
+#define DEF_CSB_IGU_INDEX_OFF \
+ offsetof(struct cstorm_def_status_block_c, igu_index)
+#define DEF_XSB_IGU_INDEX_OFF \
+ offsetof(struct xstorm_def_status_block, igu_index)
+#define DEF_TSB_IGU_INDEX_OFF \
+ offsetof(struct tstorm_def_status_block, igu_index)
+
+#define DEF_USB_SEGMENT_OFF \
+ offsetof(struct cstorm_def_status_block_u, segment)
+#define DEF_CSB_SEGMENT_OFF \
+ offsetof(struct cstorm_def_status_block_c, segment)
+#define DEF_XSB_SEGMENT_OFF \
+ offsetof(struct xstorm_def_status_block, segment)
+#define DEF_TSB_SEGMENT_OFF \
+ offsetof(struct tstorm_def_status_block, segment)
+
#define BNX2X_SP_DSB_INDEX \
(&bp->def_status_blk->sp_sb.\
index_values[HC_SP_INDEX_ETH_DEF_CONS])
@@ -1786,7 +1967,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
} while (0)
#define GET_FLAG(value, mask) \
- (((value) &= (mask)) >> (mask##_SHIFT))
+ (((value) & (mask)) >> (mask##_SHIFT))
#define GET_FIELD(value, fname) \
(((value) & (fname##_MASK)) >> (fname##_SHIFT))
@@ -1821,15 +2002,13 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define HC_SEG_ACCESS_ATTN 4
#define HC_SEG_ACCESS_NORM 0 /*Driver decision 0-1*/
-#ifdef BNX2X_MAIN
-#define BNX2X_EXTERN
-#else
-#define BNX2X_EXTERN extern
-#endif
-
-BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
-
-extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
-void bnx2x_push_indir_table(struct bnx2x *bp);
+static const u32 dmae_reg_go_c[] = {
+ DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
+ DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
+ DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
+ DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
+};
+void bnx2x_set_ethtool_ops(struct net_device *netdev);
+void bnx2x_notify_link_changed(struct bnx2x *bp);
#endif /* bnx2x.h */
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 289044332ed8..5b0dba6d4efa 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -17,16 +17,17 @@
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
#include <linux/ip.h>
#include <net/ipv6.h>
#include <net/ip6_checksum.h>
#include <linux/firmware.h>
#include <linux/prefetch.h>
#include "bnx2x_cmn.h"
-
#include "bnx2x_init.h"
+#include "bnx2x_sp.h"
+
-static int bnx2x_setup_irqs(struct bnx2x *bp);
/**
* bnx2x_bz_fp - zero content of the fastpath structure.
@@ -46,6 +47,25 @@ static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
/* Restore the NAPI object as it has been already initialized */
fp->napi = orig_napi;
+
+ fp->bp = bp;
+ fp->index = index;
+ if (IS_ETH_FP(fp))
+ fp->max_cos = bp->max_cos;
+ else
+ /* Special queues support only one CoS */
+ fp->max_cos = 1;
+
+ /*
+ * set the tpa flag for each queue. The tpa flag determines the queue
+ * minimal size so it must be set prior to queue memory allocation
+ */
+ fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0);
+
+#ifdef BCM_CNIC
+ /* We don't want TPA on FCoE, FWD and OOO L2 rings */
+ bnx2x_fcoe(bp, disable_tpa) = 1;
+#endif
}
/**
@@ -71,13 +91,15 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)
to_fp->napi = orig_napi;
}
+int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
+
/* free skb in the packet ring at pos idx
* return idx of last bd freed
*/
-static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
u16 idx)
{
- struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx];
+ struct sw_tx_bd *tx_buf = &txdata->tx_buf_ring[idx];
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_bd *tx_data_bd;
struct sk_buff *skb = tx_buf->skb;
@@ -87,15 +109,16 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* prefetch skb end pointer to speedup dev_kfree_skb() */
prefetch(&skb->end);
- DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n",
- idx, tx_buf, skb);
+ DP(BNX2X_MSG_FP, "fp[%d]: pkt_idx %d buff @(%p)->skb %p\n",
+ txdata->txq_index, idx, tx_buf, skb);
/* unmap first bd */
DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx);
- tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd;
+ tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd;
dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
+
nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
#ifdef BNX2X_STOP_ON_ERROR
if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) {
@@ -122,7 +145,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
while (nbd > 0) {
DP(BNX2X_MSG_OFF, "free frag bd_idx %d\n", bd_idx);
- tx_data_bd = &fp->tx_desc_ring[bd_idx].reg_bd;
+ tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
dma_unmap_page(&bp->pdev->dev, BD_UNMAP_ADDR(tx_data_bd),
BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE);
if (--nbd)
@@ -138,20 +161,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
return new_cons;
}
-int bnx2x_tx_int(struct bnx2x_fastpath *fp)
+int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata)
{
- struct bnx2x *bp = fp->bp;
struct netdev_queue *txq;
- u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons;
+ u16 hw_cons, sw_cons, bd_cons = txdata->tx_bd_cons;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return -1;
#endif
- txq = netdev_get_tx_queue(bp->dev, fp->index);
- hw_cons = le16_to_cpu(*fp->tx_cons_sb);
- sw_cons = fp->tx_pkt_cons;
+ txq = netdev_get_tx_queue(bp->dev, txdata->txq_index);
+ hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
+ sw_cons = txdata->tx_pkt_cons;
while (sw_cons != hw_cons) {
u16 pkt_cons;
@@ -160,20 +182,23 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp)
DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u sw_cons %u "
" pkt_cons %u\n",
- fp->index, hw_cons, sw_cons, pkt_cons);
+ txdata->txq_index, hw_cons, sw_cons, pkt_cons);
- bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons);
+ bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons);
sw_cons++;
}
- fp->tx_pkt_cons = sw_cons;
- fp->tx_bd_cons = bd_cons;
+ txdata->tx_pkt_cons = sw_cons;
+ txdata->tx_bd_cons = bd_cons;
/* Need to make the tx_bd_cons update visible to start_xmit()
* before checking for netif_tx_queue_stopped(). Without the
* memory barrier, there is a small possibility that
* start_xmit() will miss it and cause the queue to be stopped
* forever.
+ * On the other hand we need an rmb() here to ensure the proper
+ * ordering of bit testing in the following
+ * netif_tx_queue_stopped(txq) call.
*/
smp_mb();
@@ -192,7 +217,7 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp)
if ((netif_tx_queue_stopped(txq)) &&
(bp->state == BNX2X_STATE_OPEN) &&
- (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3))
+ (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3))
netif_tx_wake_queue(txq);
__netif_tx_unlock(txq);
@@ -225,7 +250,7 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
/* First mark all used pages */
for (i = 0; i < sge_len; i++)
- SGE_MASK_CLEAR_BIT(fp,
+ BIT_VEC64_CLEAR_BIT(fp->sge_mask,
RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i])));
DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n",
@@ -237,8 +262,8 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
last_max = RX_SGE(fp->last_max_sge);
- last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT;
- first_elem = RX_SGE(fp->rx_sge_prod) >> RX_SGE_MASK_ELEM_SHIFT;
+ last_elem = last_max >> BIT_VEC64_ELEM_SHIFT;
+ first_elem = RX_SGE(fp->rx_sge_prod) >> BIT_VEC64_ELEM_SHIFT;
/* If ring is not full */
if (last_elem + 1 != first_elem)
@@ -249,8 +274,8 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
if (likely(fp->sge_mask[i]))
break;
- fp->sge_mask[i] = RX_SGE_MASK_ELEM_ONE_MASK;
- delta += RX_SGE_MASK_ELEM_SZ;
+ fp->sge_mask[i] = BIT_VEC64_ELEM_ONE_MASK;
+ delta += BIT_VEC64_ELEM_SZ;
}
if (delta > 0) {
@@ -265,33 +290,56 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
}
static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
- struct sk_buff *skb, u16 cons, u16 prod)
+ struct sk_buff *skb, u16 cons, u16 prod,
+ struct eth_fast_path_rx_cqe *cqe)
{
struct bnx2x *bp = fp->bp;
struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
dma_addr_t mapping;
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+ struct sw_rx_bd *first_buf = &tpa_info->first_buf;
- /* move empty skb from pool to prod and map it */
- prod_rx_buf->skb = fp->tpa_pool[queue].skb;
- mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data,
- fp->rx_buf_size, DMA_FROM_DEVICE);
- dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
-
- /* move partial skb from cons to pool (don't unmap yet) */
- fp->tpa_pool[queue] = *cons_rx_buf;
-
- /* mark bin state as start - print error if current state != stop */
- if (fp->tpa_state[queue] != BNX2X_TPA_STOP)
+ /* print error if current state != stop */
+ if (tpa_info->tpa_state != BNX2X_TPA_STOP)
BNX2X_ERR("start of bin not in stop [%d]\n", queue);
- fp->tpa_state[queue] = BNX2X_TPA_START;
+ /* Try to map an empty skb from the aggregation info */
+ mapping = dma_map_single(&bp->pdev->dev,
+ first_buf->skb->data,
+ fp->rx_buf_size, DMA_FROM_DEVICE);
+ /*
+ * ...if it fails - move the skb from the consumer to the producer
+ * and set the current aggregation state as ERROR to drop it
+ * when TPA_STOP arrives.
+ */
+
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ /* Move the BD from the consumer to the producer */
+ bnx2x_reuse_rx_skb(fp, cons, prod);
+ tpa_info->tpa_state = BNX2X_TPA_ERROR;
+ return;
+ }
+ /* move empty skb from pool to prod */
+ prod_rx_buf->skb = first_buf->skb;
+ dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
/* point prod_bd to new skb */
prod_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
prod_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
+ /* move partial skb from cons to pool (don't unmap yet) */
+ *first_buf = *cons_rx_buf;
+
+ /* mark bin state as START */
+ tpa_info->parsing_flags =
+ le16_to_cpu(cqe->pars_flags.flags);
+ tpa_info->vlan_tag = le16_to_cpu(cqe->vlan_tag);
+ tpa_info->tpa_state = BNX2X_TPA_START;
+ tpa_info->len_on_bd = le16_to_cpu(cqe->len_on_bd);
+ tpa_info->placement_offset = cqe->placement_offset;
+
#ifdef BNX2X_STOP_ON_ERROR
fp->tpa_queue_used |= (1 << queue);
#ifdef _ASM_GENERIC_INT_L64_H
@@ -322,10 +370,17 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
u16 len_on_bd)
{
- /* TPA arrgregation won't have an IP options and TCP options
- * other than timestamp.
+ /*
+ * TPA arrgregation won't have either IP options or TCP options
+ * other than timestamp or IPv6 extension headers.
*/
- u16 hdrs_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr);
+ u16 hdrs_len = ETH_HLEN + sizeof(struct tcphdr);
+
+ if (GET_FLAG(parsing_flags, PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) ==
+ PRS_FLAG_OVERETH_IPV6)
+ hdrs_len += sizeof(struct ipv6hdr);
+ else /* IPv4 */
+ hdrs_len += sizeof(struct iphdr);
/* Check if there was a TCP timestamp, if there is it's will
@@ -340,30 +395,30 @@ static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
}
static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- struct sk_buff *skb,
- struct eth_fast_path_rx_cqe *fp_cqe,
- u16 cqe_idx, u16 parsing_flags)
+ u16 queue, struct sk_buff *skb,
+ struct eth_end_agg_rx_cqe *cqe,
+ u16 cqe_idx)
{
struct sw_rx_page *rx_pg, old_rx_pg;
- u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd);
u32 i, frag_len, frag_size, pages;
int err;
int j;
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+ u16 len_on_bd = tpa_info->len_on_bd;
- frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd;
+ frag_size = le16_to_cpu(cqe->pkt_len) - len_on_bd;
pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT;
/* This is needed in order to enable forwarding support */
if (frag_size)
- skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp, parsing_flags,
- len_on_bd);
+ skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp,
+ tpa_info->parsing_flags, len_on_bd);
#ifdef BNX2X_STOP_ON_ERROR
if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) {
BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
pages, cqe_idx);
- BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n",
- fp_cqe->pkt_len, len_on_bd);
+ BNX2X_ERR("cqe->pkt_len = %d\n", cqe->pkt_len);
bnx2x_panic();
return -EINVAL;
}
@@ -371,8 +426,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* Run through the SGL and compose the fragmented skb */
for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) {
- u16 sge_idx =
- RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[j]));
+ u16 sge_idx = RX_SGE(le16_to_cpu(cqe->sgl_or_raw_data.sgl[j]));
/* FW gives the indices of the SGE as if the ring is an array
(meaning that "next" element will consume 2 indices) */
@@ -407,13 +461,28 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
}
static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- u16 queue, int pad, int len, union eth_rx_cqe *cqe,
+ u16 queue, struct eth_end_agg_rx_cqe *cqe,
u16 cqe_idx)
{
- struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue];
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+ struct sw_rx_bd *rx_buf = &tpa_info->first_buf;
+ u8 pad = tpa_info->placement_offset;
+ u16 len = tpa_info->len_on_bd;
struct sk_buff *skb = rx_buf->skb;
/* alloc new skb */
- struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
+ struct sk_buff *new_skb;
+ u8 old_tpa_state = tpa_info->tpa_state;
+
+ tpa_info->tpa_state = BNX2X_TPA_STOP;
+
+ /* If we there was an error during the handling of the TPA_START -
+ * drop this aggregation.
+ */
+ if (old_tpa_state == BNX2X_TPA_ERROR)
+ goto drop;
+
+ /* Try to allocate the new skb */
+ new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
/* Unmap skb in the pool anyway, as we are going to change
pool entry status to BNX2X_TPA_STOP even if new skb allocation
@@ -422,11 +491,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
fp->rx_buf_size, DMA_FROM_DEVICE);
if (likely(new_skb)) {
- /* fix ip xsum and give it to the stack */
- /* (no need to map the new skb) */
- u16 parsing_flags =
- le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags);
-
prefetch(skb);
prefetch(((char *)(skb)) + L1_CACHE_BYTES);
@@ -446,21 +510,9 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
skb->protocol = eth_type_trans(skb, bp->dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- {
- struct iphdr *iph;
-
- iph = (struct iphdr *)skb->data;
- iph->check = 0;
- iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
- }
-
- if (!bnx2x_fill_frag_skb(bp, fp, skb,
- &cqe->fast_path_cqe, cqe_idx,
- parsing_flags)) {
- if (parsing_flags & PARSING_FLAGS_VLAN)
- __vlan_hwaccel_put_tag(skb,
- le16_to_cpu(cqe->fast_path_cqe.
- vlan_tag));
+ if (!bnx2x_fill_frag_skb(bp, fp, queue, skb, cqe, cqe_idx)) {
+ if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN)
+ __vlan_hwaccel_put_tag(skb, tpa_info->vlan_tag);
napi_gro_receive(&fp->napi, skb);
} else {
DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages"
@@ -470,16 +522,16 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* put new skb in bin */
- fp->tpa_pool[queue].skb = new_skb;
+ rx_buf->skb = new_skb;
- } else {
- /* else drop the packet and keep the buffer in the bin */
- DP(NETIF_MSG_RX_STATUS,
- "Failed to allocate new skb - dropping packet!\n");
- fp->eth_q_stats.rx_skb_alloc_failed++;
+ return;
}
- fp->tpa_state[queue] = BNX2X_TPA_STOP;
+drop:
+ /* drop the packet and keep the buffer in the bin */
+ DP(NETIF_MSG_RX_STATUS,
+ "Failed to allocate or map a new skb - dropping packet!\n");
+ fp->eth_q_stats.rx_skb_alloc_failed++;
}
/* Set Toeplitz hash value in the skb using the value from the
@@ -533,9 +585,16 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
struct sw_rx_bd *rx_buf = NULL;
struct sk_buff *skb;
union eth_rx_cqe *cqe;
+ struct eth_fast_path_rx_cqe *cqe_fp;
u8 cqe_fp_flags;
+ enum eth_rx_cqe_type cqe_fp_type;
u16 len, pad;
+#ifdef BNX2X_STOP_ON_ERROR
+ if (unlikely(bp->panic))
+ return 0;
+#endif
+
comp_ring_cons = RCQ_BD(sw_comp_cons);
bd_prod = RX_BD(bd_prod);
bd_cons = RX_BD(bd_cons);
@@ -548,17 +607,18 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
PAGE_SIZE + 1));
cqe = &fp->rx_comp_ring[comp_ring_cons];
- cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
+ cqe_fp = &cqe->fast_path_cqe;
+ cqe_fp_flags = cqe_fp->type_error_flags;
+ cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x"
" queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags),
- cqe_fp_flags, cqe->fast_path_cqe.status_flags,
- le32_to_cpu(cqe->fast_path_cqe.rss_hash_result),
- le16_to_cpu(cqe->fast_path_cqe.vlan_tag),
- le16_to_cpu(cqe->fast_path_cqe.pkt_len));
+ cqe_fp_flags, cqe_fp->status_flags,
+ le32_to_cpu(cqe_fp->rss_hash_result),
+ le16_to_cpu(cqe_fp->vlan_tag), le16_to_cpu(cqe_fp->pkt_len));
/* is this a slowpath msg? */
- if (unlikely(CQE_TYPE(cqe_fp_flags))) {
+ if (unlikely(CQE_TYPE_SLOW(cqe_fp_type))) {
bnx2x_sp_event(fp, cqe);
goto next_cqe;
@@ -567,61 +627,59 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
rx_buf = &fp->rx_buf_ring[bd_cons];
skb = rx_buf->skb;
prefetch(skb);
- len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
- pad = cqe->fast_path_cqe.placement_offset;
- /* - If CQE is marked both TPA_START and TPA_END it is
- * a non-TPA CQE.
- * - FP CQE will always have either TPA_START or/and
- * TPA_STOP flags set.
- */
- if ((!fp->disable_tpa) &&
- (TPA_TYPE(cqe_fp_flags) !=
- (TPA_TYPE_START | TPA_TYPE_END))) {
- u16 queue = cqe->fast_path_cqe.queue_index;
+ if (!CQE_TYPE_FAST(cqe_fp_type)) {
+#ifdef BNX2X_STOP_ON_ERROR
+ /* sanity check */
+ if (fp->disable_tpa &&
+ (CQE_TYPE_START(cqe_fp_type) ||
+ CQE_TYPE_STOP(cqe_fp_type)))
+ BNX2X_ERR("START/STOP packet while "
+ "disable_tpa type %x\n",
+ CQE_TYPE(cqe_fp_type));
+#endif
- if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_START) {
+ if (CQE_TYPE_START(cqe_fp_type)) {
+ u16 queue = cqe_fp->queue_index;
DP(NETIF_MSG_RX_STATUS,
"calling tpa_start on queue %d\n",
queue);
bnx2x_tpa_start(fp, queue, skb,
- bd_cons, bd_prod);
+ bd_cons, bd_prod,
+ cqe_fp);
- /* Set Toeplitz hash for an LRO skb */
+ /* Set Toeplitz hash for LRO skb */
bnx2x_set_skb_rxhash(bp, cqe, skb);
goto next_rx;
- } else { /* TPA_STOP */
+
+ } else {
+ u16 queue =
+ cqe->end_agg_cqe.queue_index;
DP(NETIF_MSG_RX_STATUS,
"calling tpa_stop on queue %d\n",
queue);
- if (!BNX2X_RX_SUM_FIX(cqe))
- BNX2X_ERR("STOP on none TCP "
- "data\n");
-
- /* This is a size of the linear data
- on this skb */
- len = le16_to_cpu(cqe->fast_path_cqe.
- len_on_bd);
- bnx2x_tpa_stop(bp, fp, queue, pad,
- len, cqe, comp_ring_cons);
+ bnx2x_tpa_stop(bp, fp, queue,
+ &cqe->end_agg_cqe,
+ comp_ring_cons);
#ifdef BNX2X_STOP_ON_ERROR
if (bp->panic)
return 0;
#endif
- bnx2x_update_sge_prod(fp,
- &cqe->fast_path_cqe);
+ bnx2x_update_sge_prod(fp, cqe_fp);
goto next_cqe;
}
}
-
- dma_sync_single_for_device(&bp->pdev->dev,
+ /* non TPA */
+ len = le16_to_cpu(cqe_fp->pkt_len);
+ pad = cqe_fp->placement_offset;
+ dma_sync_single_for_cpu(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
- pad + RX_COPY_THRESH,
- DMA_FROM_DEVICE);
+ pad + RX_COPY_THRESH,
+ DMA_FROM_DEVICE);
prefetch(((char *)(skb)) + L1_CACHE_BYTES);
/* is this an error packet? */
@@ -640,8 +698,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
(len <= RX_COPY_THRESH)) {
struct sk_buff *new_skb;
- new_skb = netdev_alloc_skb(bp->dev,
- len + pad);
+ new_skb = netdev_alloc_skb(bp->dev, len + pad);
if (new_skb == NULL) {
DP(NETIF_MSG_RX_ERR,
"ERROR packet dropped "
@@ -687,6 +744,7 @@ reuse_rx:
skb_checksum_none_assert(skb);
if (bp->dev->features & NETIF_F_RXCSUM) {
+
if (likely(BNX2X_RX_CSUM_OK(cqe)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
@@ -696,10 +754,10 @@ reuse_rx:
skb_record_rx_queue(skb, fp->index);
- if (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
- PARSING_FLAGS_VLAN)
+ if (le16_to_cpu(cqe_fp->pars_flags.flags) &
+ PARSING_FLAGS_VLAN)
__vlan_hwaccel_put_tag(skb,
- le16_to_cpu(cqe->fast_path_cqe.vlan_tag));
+ le16_to_cpu(cqe_fp->vlan_tag));
napi_gro_receive(&fp->napi, skb);
@@ -737,12 +795,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
{
struct bnx2x_fastpath *fp = fp_cookie;
struct bnx2x *bp = fp->bp;
-
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return IRQ_HANDLED;
- }
+ u8 cos;
DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB "
"[fp %d fw_sd %d igusb %d]\n",
@@ -756,7 +809,10 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
/* Handle Rx and Tx according to MSI-X vector */
prefetch(fp->rx_cons_sb);
- prefetch(fp->tx_cons_sb);
+
+ for_each_cos_in_tx_queue(fp, cos)
+ prefetch(fp->txdata[cos].tx_cons_sb);
+
prefetch(&fp->sb_running_index[SM_RX_ID]);
napi_schedule(&bnx2x_fp(bp, fp->index, napi));
@@ -931,7 +987,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
- ETH_MAX_AGGREGATION_QUEUES_E1H;
+ ETH_MAX_AGGREGATION_QUEUES_E1H_E2;
u16 ring_prod;
int i, j;
@@ -943,11 +999,16 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
"mtu %d rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
if (!fp->disable_tpa) {
- /* Fill the per-aggregation pool */
+ /* Fill the per-aggregtion pool */
for (i = 0; i < max_agg_queues; i++) {
- fp->tpa_pool[i].skb =
- netdev_alloc_skb(bp->dev, fp->rx_buf_size);
- if (!fp->tpa_pool[i].skb) {
+ struct bnx2x_agg_info *tpa_info =
+ &fp->tpa_info[i];
+ struct sw_rx_bd *first_buf =
+ &tpa_info->first_buf;
+
+ first_buf->skb = netdev_alloc_skb(bp->dev,
+ fp->rx_buf_size);
+ if (!first_buf->skb) {
BNX2X_ERR("Failed to allocate TPA "
"skb pool for queue[%d] - "
"disabling TPA on this "
@@ -956,10 +1017,8 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
fp->disable_tpa = 1;
break;
}
- dma_unmap_addr_set((struct sw_rx_bd *)
- &bp->fp->tpa_pool[i],
- mapping, 0);
- fp->tpa_state[i] = BNX2X_TPA_STOP;
+ dma_unmap_addr_set(first_buf, mapping, 0);
+ tpa_info->tpa_state = BNX2X_TPA_STOP;
}
/* "next page" elements initialization */
@@ -975,13 +1034,13 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
BNX2X_ERR("was only able to allocate "
"%d rx sges\n", i);
- BNX2X_ERR("disabling TPA for"
- " queue[%d]\n", j);
+ BNX2X_ERR("disabling TPA for "
+ "queue[%d]\n", j);
/* Cleanup already allocated elements */
- bnx2x_free_rx_sge_range(bp,
- fp, ring_prod);
- bnx2x_free_tpa_pool(bp,
- fp, max_agg_queues);
+ bnx2x_free_rx_sge_range(bp, fp,
+ ring_prod);
+ bnx2x_free_tpa_pool(bp, fp,
+ max_agg_queues);
fp->disable_tpa = 1;
ring_prod = 0;
break;
@@ -1009,7 +1068,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
if (j != 0)
continue;
- if (!CHIP_IS_E2(bp)) {
+ if (CHIP_IS_E1(bp)) {
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
U64_LO(fp->rx_comp_mapping));
@@ -1023,17 +1082,22 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
static void bnx2x_free_tx_skbs(struct bnx2x *bp)
{
int i;
+ u8 cos;
for_each_tx_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
+ for_each_cos_in_tx_queue(fp, cos) {
+ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
- u16 bd_cons = fp->tx_bd_cons;
- u16 sw_prod = fp->tx_pkt_prod;
- u16 sw_cons = fp->tx_pkt_cons;
+ u16 bd_cons = txdata->tx_bd_cons;
+ u16 sw_prod = txdata->tx_pkt_prod;
+ u16 sw_cons = txdata->tx_pkt_cons;
- while (sw_cons != sw_prod) {
- bd_cons = bnx2x_free_tx_pkt(bp, fp, TX_BD(sw_cons));
- sw_cons++;
+ while (sw_cons != sw_prod) {
+ bd_cons = bnx2x_free_tx_pkt(bp, txdata,
+ TX_BD(sw_cons));
+ sw_cons++;
+ }
}
}
}
@@ -1053,7 +1117,6 @@ static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp)
if (skb == NULL)
continue;
-
dma_unmap_single(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE);
@@ -1075,7 +1138,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
if (!fp->disable_tpa)
bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ?
ETH_MAX_AGGREGATION_QUEUES_E1 :
- ETH_MAX_AGGREGATION_QUEUES_E1H);
+ ETH_MAX_AGGREGATION_QUEUES_E1H_E2);
}
}
@@ -1102,30 +1165,43 @@ void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value)
}
}
-static void bnx2x_free_msix_irqs(struct bnx2x *bp)
+/**
+ * bnx2x_free_msix_irqs - free previously requested MSI-X IRQ vectors
+ *
+ * @bp: driver handle
+ * @nvecs: number of vectors to be released
+ */
+static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
{
- int i, offset = 1;
+ int i, offset = 0;
- free_irq(bp->msix_table[0].vector, bp->dev);
+ if (nvecs == offset)
+ return;
+ free_irq(bp->msix_table[offset].vector, bp->dev);
DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
- bp->msix_table[0].vector);
-
+ bp->msix_table[offset].vector);
+ offset++;
#ifdef BCM_CNIC
+ if (nvecs == offset)
+ return;
offset++;
#endif
+
for_each_eth_queue(bp, i) {
- DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq "
- "state %x\n", i, bp->msix_table[i + offset].vector,
- bnx2x_fp(bp, i, state));
+ if (nvecs == offset)
+ return;
+ DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d "
+ "irq\n", i, bp->msix_table[offset].vector);
- free_irq(bp->msix_table[i + offset].vector, &bp->fp[i]);
+ free_irq(bp->msix_table[offset++].vector, &bp->fp[i]);
}
}
void bnx2x_free_irq(struct bnx2x *bp)
{
if (bp->flags & USING_MSIX_FLAG)
- bnx2x_free_msix_irqs(bp);
+ bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
+ CNIC_PRESENT + 1);
else if (bp->flags & USING_MSI_FLAG)
free_irq(bp->pdev->irq, bp->dev);
else
@@ -1147,6 +1223,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
msix_vec++;
#endif
+ /* We need separate vectors for ETH queues only (not FCoE) */
for_each_eth_queue(bp, i) {
bp->msix_table[msix_vec].entry = msix_vec;
DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
@@ -1154,7 +1231,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
msix_vec++;
}
- req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_CONTEXT_USE + 1;
+ req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1;
rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
@@ -1198,9 +1275,10 @@ int bnx2x_enable_msix(struct bnx2x *bp)
static int bnx2x_req_msix_irqs(struct bnx2x *bp)
{
- int i, rc, offset = 1;
+ int i, rc, offset = 0;
- rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0,
+ rc = request_irq(bp->msix_table[offset++].vector,
+ bnx2x_msix_sp_int, 0,
bp->dev->name, bp->dev);
if (rc) {
BNX2X_ERR("request sp irq failed\n");
@@ -1218,17 +1296,17 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
rc = request_irq(bp->msix_table[offset].vector,
bnx2x_msix_fp_int, 0, fp->name, fp);
if (rc) {
- BNX2X_ERR("request fp #%d irq failed rc %d\n", i, rc);
- bnx2x_free_msix_irqs(bp);
+ BNX2X_ERR("request fp #%d irq (%d) failed rc %d\n", i,
+ bp->msix_table[offset].vector, rc);
+ bnx2x_free_msix_irqs(bp, offset);
return -EBUSY;
}
offset++;
- fp->state = BNX2X_FP_STATE_IRQ;
}
i = BNX2X_NUM_ETH_QUEUES(bp);
- offset = 1 + CNIC_CONTEXT_USE;
+ offset = 1 + CNIC_PRESENT;
netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d"
" ... fp[%d] %d\n",
bp->msix_table[0].vector,
@@ -1264,42 +1342,56 @@ static int bnx2x_req_irq(struct bnx2x *bp)
rc = request_irq(bp->pdev->irq, bnx2x_interrupt, flags,
bp->dev->name, bp->dev);
- if (!rc)
- bnx2x_fp(bp, 0, state) = BNX2X_FP_STATE_IRQ;
-
return rc;
}
-static void bnx2x_napi_enable(struct bnx2x *bp)
+static inline int bnx2x_setup_irqs(struct bnx2x *bp)
+{
+ int rc = 0;
+ if (bp->flags & USING_MSIX_FLAG) {
+ rc = bnx2x_req_msix_irqs(bp);
+ if (rc)
+ return rc;
+ } else {
+ bnx2x_ack_int(bp);
+ rc = bnx2x_req_irq(bp);
+ if (rc) {
+ BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc);
+ return rc;
+ }
+ if (bp->flags & USING_MSI_FLAG) {
+ bp->dev->irq = bp->pdev->irq;
+ netdev_info(bp->dev, "using MSI IRQ %d\n",
+ bp->pdev->irq);
+ }
+ }
+
+ return 0;
+}
+
+static inline void bnx2x_napi_enable(struct bnx2x *bp)
{
int i;
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
}
-static void bnx2x_napi_disable(struct bnx2x *bp)
+static inline void bnx2x_napi_disable(struct bnx2x *bp)
{
int i;
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
}
void bnx2x_netif_start(struct bnx2x *bp)
{
- int intr_sem;
-
- intr_sem = atomic_dec_and_test(&bp->intr_sem);
- smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
- if (intr_sem) {
- if (netif_running(bp->dev)) {
- bnx2x_napi_enable(bp);
- bnx2x_int_enable(bp);
- if (bp->state == BNX2X_STATE_OPEN)
- netif_tx_wake_all_queues(bp->dev);
- }
+ if (netif_running(bp->dev)) {
+ bnx2x_napi_enable(bp);
+ bnx2x_int_enable(bp);
+ if (bp->state == BNX2X_STATE_OPEN)
+ netif_tx_wake_all_queues(bp->dev);
}
}
@@ -1307,13 +1399,12 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
{
bnx2x_int_disable_sync(bp, disable_hw);
bnx2x_napi_disable(bp);
- netif_tx_disable(bp->dev);
}
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
{
-#ifdef BCM_CNIC
struct bnx2x *bp = netdev_priv(dev);
+#ifdef BCM_CNIC
if (NO_FCOE(bp))
return skb_tx_hash(dev, skb);
else {
@@ -1330,13 +1421,12 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
/* If ethertype is FCoE or FIP - use FCoE ring */
if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
- return bnx2x_fcoe(bp, index);
+ return bnx2x_fcoe_tx(bp, txq_index);
}
#endif
/* Select a none-FCoE queue: if FCoE is enabled, exclude FCoE L2 ring
*/
- return __skb_tx_hash(dev, skb,
- dev->real_num_tx_queues - FCOE_CONTEXT_USE);
+ return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
}
void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -1355,40 +1445,38 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
}
/* Add special queues */
- bp->num_queues += NONE_ETH_CONTEXT_USE;
+ bp->num_queues += NON_ETH_CONTEXT_USE;
}
-#ifdef BCM_CNIC
-static inline void bnx2x_set_fcoe_eth_macs(struct bnx2x *bp)
+static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
{
+ int rc, tx, rx;
+
+ tx = MAX_TXQS_PER_COS * bp->max_cos;
+ rx = BNX2X_NUM_ETH_QUEUES(bp);
+
+/* account for fcoe queue */
+#ifdef BCM_CNIC
if (!NO_FCOE(bp)) {
- if (!IS_MF_SD(bp))
- bnx2x_set_fip_eth_mac_addr(bp, 1);
- bnx2x_set_all_enode_macs(bp, 1);
- bp->flags |= FCOE_MACS_SET;
+ rx += FCOE_PRESENT;
+ tx += FCOE_PRESENT;
}
-}
#endif
-static void bnx2x_release_firmware(struct bnx2x *bp)
-{
- kfree(bp->init_ops_offsets);
- kfree(bp->init_ops);
- kfree(bp->init_data);
- release_firmware(bp->firmware);
-}
-
-static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
-{
- int rc, num = bp->num_queues;
+ rc = netif_set_real_num_tx_queues(bp->dev, tx);
+ if (rc) {
+ BNX2X_ERR("Failed to set real number of Tx queues: %d\n", rc);
+ return rc;
+ }
+ rc = netif_set_real_num_rx_queues(bp->dev, rx);
+ if (rc) {
+ BNX2X_ERR("Failed to set real number of Rx queues: %d\n", rc);
+ return rc;
+ }
-#ifdef BCM_CNIC
- if (NO_FCOE(bp))
- num -= FCOE_CONTEXT_USE;
+ DP(NETIF_MSG_DRV, "Setting real num queues to (tx, rx) (%d, %d)\n",
+ tx, rx);
-#endif
- netif_set_real_num_tx_queues(bp->dev, num);
- rc = netif_set_real_num_rx_queues(bp->dev, num);
return rc;
}
@@ -1409,27 +1497,198 @@ static inline void bnx2x_set_rx_buf_size(struct bnx2x *bp)
*/
fp->rx_buf_size =
BNX2X_FCOE_MINI_JUMBO_MTU + ETH_OVREHEAD +
- BNX2X_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+ BNX2X_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
else
fp->rx_buf_size =
- bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
- IP_HEADER_ALIGNMENT_PADDING;
+ bp->dev->mtu + ETH_OVREHEAD +
+ BNX2X_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+ }
+}
+
+static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
+{
+ int i;
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+ u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
+
+ /*
+ * Prepare the inital contents fo the indirection table if RSS is
+ * enabled
+ */
+ if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
+ for (i = 0; i < sizeof(ind_table); i++)
+ ind_table[i] =
+ bp->fp->cl_id + (i % num_eth_queues);
+ }
+
+ /*
+ * For 57710 and 57711 SEARCHER configuration (rss_keys) is
+ * per-port, so if explicit configuration is needed , do it only
+ * for a PMF.
+ *
+ * For 57712 and newer on the other hand it's a per-function
+ * configuration.
+ */
+ return bnx2x_config_rss_pf(bp, ind_table,
+ bp->port.pmf || !CHIP_IS_E1x(bp));
+}
+
+int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash)
+{
+ struct bnx2x_config_rss_params params = {0};
+ int i;
+
+ /* Although RSS is meaningless when there is a single HW queue we
+ * still need it enabled in order to have HW Rx hash generated.
+ *
+ * if (!is_eth_multi(bp))
+ * bp->multi_mode = ETH_RSS_MODE_DISABLED;
+ */
+
+ params.rss_obj = &bp->rss_conf_obj;
+
+ __set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
+
+ /* RSS mode */
+ switch (bp->multi_mode) {
+ case ETH_RSS_MODE_DISABLED:
+ __set_bit(BNX2X_RSS_MODE_DISABLED, &params.rss_flags);
+ break;
+ case ETH_RSS_MODE_REGULAR:
+ __set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
+ break;
+ case ETH_RSS_MODE_VLAN_PRI:
+ __set_bit(BNX2X_RSS_MODE_VLAN_PRI, &params.rss_flags);
+ break;
+ case ETH_RSS_MODE_E1HOV_PRI:
+ __set_bit(BNX2X_RSS_MODE_E1HOV_PRI, &params.rss_flags);
+ break;
+ case ETH_RSS_MODE_IP_DSCP:
+ __set_bit(BNX2X_RSS_MODE_IP_DSCP, &params.rss_flags);
+ break;
+ default:
+ BNX2X_ERR("Unknown multi_mode: %d\n", bp->multi_mode);
+ return -EINVAL;
+ }
+
+ /* If RSS is enabled */
+ if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
+ /* RSS configuration */
+ __set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
+ __set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
+ __set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
+ __set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
+
+ /* Hash bits */
+ params.rss_result_mask = MULTI_MASK;
+
+ memcpy(params.ind_table, ind_table, sizeof(params.ind_table));
+
+ if (config_hash) {
+ /* RSS keys */
+ for (i = 0; i < sizeof(params.rss_key) / 4; i++)
+ params.rss_key[i] = random32();
+
+ __set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
+ }
+ }
+
+ return bnx2x_config_rss(bp, &params);
+}
+
+static inline int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
+{
+ struct bnx2x_func_state_params func_params = {0};
+
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_HW_INIT;
+
+ func_params.params.hw_init.load_phase = load_code;
+
+ return bnx2x_func_state_change(bp, &func_params);
+}
+
+/*
+ * Cleans the object that have internal lists without sending
+ * ramrods. Should be run when interrutps are disabled.
+ */
+static void bnx2x_squeeze_objects(struct bnx2x *bp)
+{
+ int rc;
+ unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
+ struct bnx2x_mcast_ramrod_params rparam = {0};
+ struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
+
+ /***************** Cleanup MACs' object first *************************/
+
+ /* Wait for completion of requested */
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+ /* Perform a dry cleanup */
+ __set_bit(RAMROD_DRV_CLR_ONLY, &ramrod_flags);
+
+ /* Clean ETH primary MAC */
+ __set_bit(BNX2X_ETH_MAC, &vlan_mac_flags);
+ rc = mac_obj->delete_all(bp, &bp->fp->mac_obj, &vlan_mac_flags,
+ &ramrod_flags);
+ if (rc != 0)
+ BNX2X_ERR("Failed to clean ETH MACs: %d\n", rc);
+
+ /* Cleanup UC list */
+ vlan_mac_flags = 0;
+ __set_bit(BNX2X_UC_LIST_MAC, &vlan_mac_flags);
+ rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags,
+ &ramrod_flags);
+ if (rc != 0)
+ BNX2X_ERR("Failed to clean UC list MACs: %d\n", rc);
+
+ /***************** Now clean mcast object *****************************/
+ rparam.mcast_obj = &bp->mcast_obj;
+ __set_bit(RAMROD_DRV_CLR_ONLY, &rparam.ramrod_flags);
+
+ /* Add a DEL command... */
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+ if (rc < 0)
+ BNX2X_ERR("Failed to add a new DEL command to a multi-cast "
+ "object: %d\n", rc);
+
+ /* ...and wait until all pending commands are cleared */
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
+ while (rc != 0) {
+ if (rc < 0) {
+ BNX2X_ERR("Failed to clean multi-cast object: %d\n",
+ rc);
+ return;
+ }
+
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
}
}
+#ifndef BNX2X_STOP_ON_ERROR
+#define LOAD_ERROR_EXIT(bp, label) \
+ do { \
+ (bp)->state = BNX2X_STATE_ERROR; \
+ goto label; \
+ } while (0)
+#else
+#define LOAD_ERROR_EXIT(bp, label) \
+ do { \
+ (bp)->state = BNX2X_STATE_ERROR; \
+ (bp)->panic = 1; \
+ return -EBUSY; \
+ } while (0)
+#endif
+
/* must be called with rtnl_lock */
int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
+ int port = BP_PORT(bp);
u32 load_code;
int i, rc;
- /* Set init arrays */
- rc = bnx2x_init_firmware(bp);
- if (rc) {
- BNX2X_ERR("Error loading firmware\n");
- return rc;
- }
-
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return -EPERM;
@@ -1447,24 +1706,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* must be called before memory allocation and HW init */
bnx2x_ilt_set_info(bp);
- /* zero fastpath structures preserving invariants like napi which are
- * allocated only once
+ /*
+ * Zero fastpath structures preserving invariants like napi, which are
+ * allocated only once, fp index, max_cos, bp pointer.
+ * Also set fp->disable_tpa.
*/
for_each_queue(bp, i)
bnx2x_bz_fp(bp, i);
+
/* Set the receive queues buffer size */
bnx2x_set_rx_buf_size(bp);
- for_each_queue(bp, i)
- bnx2x_fp(bp, i, disable_tpa) =
- ((bp->flags & TPA_ENABLE_FLAG) == 0);
-
-#ifdef BCM_CNIC
- /* We don't want TPA on FCoE L2 ring */
- bnx2x_fcoe(bp, disable_tpa) = 1;
-#endif
-
if (bnx2x_alloc_mem(bp))
return -ENOMEM;
@@ -1475,31 +1728,36 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_set_real_num_queues(bp);
if (rc) {
BNX2X_ERR("Unable to set real_num_queues\n");
- goto load_error0;
+ LOAD_ERROR_EXIT(bp, load_error0);
}
+ /* configure multi cos mappings in kernel.
+ * this configuration may be overriden by a multi class queue discipline
+ * or by a dcbx negotiation result.
+ */
+ bnx2x_setup_tc(bp->dev, bp->max_cos);
+
bnx2x_napi_enable(bp);
/* Send LOAD_REQUEST command to MCP
- Returns the type of LOAD command:
- if it is the first port to be initialized
- common blocks should be initialized, otherwise - not
- */
+ * Returns the type of LOAD command:
+ * if it is the first port to be initialized
+ * common blocks should be initialized, otherwise - not
+ */
if (!BP_NOMCP(bp)) {
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
- goto load_error1;
+ LOAD_ERROR_EXIT(bp, load_error1);
}
if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
rc = -EBUSY; /* other port in diagnostic mode */
- goto load_error1;
+ LOAD_ERROR_EXIT(bp, load_error1);
}
} else {
int path = BP_PATH(bp);
- int port = BP_PORT(bp);
DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d] %d, %d, %d\n",
path, load_count[path][0], load_count[path][1],
@@ -1519,36 +1777,60 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
(load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
- (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
+ (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) {
bp->port.pmf = 1;
- else
+ /*
+ * We need the barrier to ensure the ordering between the
+ * writing to bp->port.pmf here and reading it from the
+ * bnx2x_periodic_task().
+ */
+ smp_mb();
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+ } else
bp->port.pmf = 0;
+
DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+ /* Init Function state controlling object */
+ bnx2x__init_func_obj(bp);
+
/* Initialize HW */
rc = bnx2x_init_hw(bp, load_code);
if (rc) {
BNX2X_ERR("HW init failed, aborting\n");
bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
- goto load_error2;
+ LOAD_ERROR_EXIT(bp, load_error2);
}
/* Connect to IRQs */
rc = bnx2x_setup_irqs(bp);
if (rc) {
bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
- goto load_error2;
+ LOAD_ERROR_EXIT(bp, load_error2);
}
/* Setup NIC internals and enable interrupts */
bnx2x_nic_init(bp, load_code);
+ /* Init per-function objects */
+ bnx2x_init_bp_objs(bp);
+
if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
(load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) &&
- (bp->common.shmem2_base))
- SHMEM2_WR(bp, dcc_support,
- (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
- SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+ (bp->common.shmem2_base)) {
+ if (SHMEM2_HAS(bp, dcc_support))
+ SHMEM2_WR(bp, dcc_support,
+ (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
+ SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+ }
+
+ bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
+ rc = bnx2x_func_start(bp);
+ if (rc) {
+ BNX2X_ERR("Function start failed!\n");
+ bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
+ LOAD_ERROR_EXIT(bp, load_error3);
+ }
/* Send LOAD_DONE command to MCP */
if (!BP_NOMCP(bp)) {
@@ -1556,74 +1838,38 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
- goto load_error3;
+ LOAD_ERROR_EXIT(bp, load_error3);
}
}
- bnx2x_dcbx_init(bp);
-
- bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
-
- rc = bnx2x_func_start(bp);
- if (rc) {
- BNX2X_ERR("Function start failed!\n");
-#ifndef BNX2X_STOP_ON_ERROR
- goto load_error3;
-#else
- bp->panic = 1;
- return -EBUSY;
-#endif
- }
-
- rc = bnx2x_setup_client(bp, &bp->fp[0], 1 /* Leading */);
+ rc = bnx2x_setup_leading(bp);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
-#ifndef BNX2X_STOP_ON_ERROR
- goto load_error3;
-#else
- bp->panic = 1;
- return -EBUSY;
-#endif
- }
-
- if (!CHIP_IS_E1(bp) &&
- (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED)) {
- DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
- bp->flags |= MF_FUNC_DIS;
+ LOAD_ERROR_EXIT(bp, load_error3);
}
#ifdef BCM_CNIC
/* Enable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1);
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
#endif
for_each_nondefault_queue(bp, i) {
- rc = bnx2x_setup_client(bp, &bp->fp[i], 0);
+ rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
if (rc)
-#ifdef BCM_CNIC
- goto load_error4;
-#else
- goto load_error3;
-#endif
+ LOAD_ERROR_EXIT(bp, load_error4);
}
+ rc = bnx2x_init_rss_pf(bp);
+ if (rc)
+ LOAD_ERROR_EXIT(bp, load_error4);
+
/* Now when Clients are configured we are ready to work */
bp->state = BNX2X_STATE_OPEN;
-#ifdef BCM_CNIC
- bnx2x_set_fcoe_eth_macs(bp);
-#endif
-
- bnx2x_set_eth_mac(bp, 1);
-
- /* Clear MC configuration */
- if (CHIP_IS_E1(bp))
- bnx2x_invalidate_e1_mc_list(bp);
- else
- bnx2x_invalidate_e1h_mc_list(bp);
-
- /* Clear UC lists configuration */
- bnx2x_invalidate_uc_list(bp);
+ /* Configure a ucast MAC */
+ rc = bnx2x_set_eth_mac(bp, true);
+ if (rc)
+ LOAD_ERROR_EXIT(bp, load_error4);
if (bp->pending_max) {
bnx2x_update_max_mf_config(bp, bp->pending_max);
@@ -1633,15 +1879,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode);
- /* Initialize Rx filtering */
+ /* Start fast path */
+
+ /* Initialize Rx filter. */
+ netif_addr_lock_bh(bp->dev);
bnx2x_set_rx_mode(bp->dev);
+ netif_addr_unlock_bh(bp->dev);
- /* Start fast path */
+ /* Start the Tx */
switch (load_mode) {
case LOAD_NORMAL:
/* Tx queue should be only reenabled */
netif_tx_wake_all_queues(bp->dev);
- /* Initialize the receive filter. */
break;
case LOAD_OPEN:
@@ -1670,18 +1919,28 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
#endif
bnx2x_inc_load_cnt(bp);
- bnx2x_release_firmware(bp);
+ /* Wait for all pending SP commands to complete */
+ if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
+ BNX2X_ERR("Timeout waiting for SP elements to complete\n");
+ bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+ return -EBUSY;
+ }
+ bnx2x_dcbx_init(bp);
return 0;
-#ifdef BCM_CNIC
+#ifndef BNX2X_STOP_ON_ERROR
load_error4:
+#ifdef BCM_CNIC
/* Disable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 0);
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
#endif
load_error3:
bnx2x_int_disable_sync(bp, 1);
+ /* Clean queueable objects */
+ bnx2x_squeeze_objects(bp);
+
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
for_each_rx_queue(bp, i)
@@ -1701,42 +1960,52 @@ load_error1:
load_error0:
bnx2x_free_mem(bp);
- bnx2x_release_firmware(bp);
-
return rc;
+#endif /* ! BNX2X_STOP_ON_ERROR */
}
/* must be called with rtnl_lock */
int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
{
int i;
-
- if (bp->state == BNX2X_STATE_CLOSED) {
- /* Interface has been removed - nothing to recover */
+ bool global = false;
+
+ if ((bp->state == BNX2X_STATE_CLOSED) ||
+ (bp->state == BNX2X_STATE_ERROR)) {
+ /* We can get here if the driver has been unloaded
+ * during parity error recovery and is either waiting for a
+ * leader to complete or for other functions to unload and
+ * then ifdown has been issued. In this case we want to
+ * unload and let other functions to complete a recovery
+ * process.
+ */
bp->recovery_state = BNX2X_RECOVERY_DONE;
bp->is_leader = 0;
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08);
- smp_wmb();
+ bnx2x_release_leader_lock(bp);
+ smp_mb();
+
+ DP(NETIF_MSG_HW, "Releasing a leadership...\n");
return -EINVAL;
}
+ /* Stop Tx */
+ bnx2x_tx_disable(bp);
+
#ifdef BCM_CNIC
bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
#endif
bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
+ smp_mb();
- /* Set "drop all" */
bp->rx_mode = BNX2X_RX_MODE_NONE;
- bnx2x_set_storm_rx_mode(bp);
-
- /* Stop Tx */
- bnx2x_tx_disable(bp);
del_timer_sync(&bp->timer);
- SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
- (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
+ /* Set ALWAYS_ALIVE bit in shmem */
+ bp->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE;
+
+ bnx2x_drv_pulse(bp);
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
@@ -1744,13 +2013,38 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
if (unload_mode != UNLOAD_RECOVERY)
bnx2x_chip_cleanup(bp, unload_mode);
else {
- /* Disable HW interrupts, NAPI and Tx */
+ /* Send the UNLOAD_REQUEST to the MCP */
+ bnx2x_send_unload_req(bp, unload_mode);
+
+ /*
+ * Prevent transactions to host from the functions on the
+ * engine that doesn't reset global blocks in case of global
+ * attention once gloabl blocks are reset and gates are opened
+ * (the engine which leader will perform the recovery
+ * last).
+ */
+ if (!CHIP_IS_E1x(bp))
+ bnx2x_pf_disable(bp);
+
+ /* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1);
/* Release IRQs */
bnx2x_free_irq(bp);
+
+ /* Report UNLOAD_DONE to MCP */
+ bnx2x_send_unload_done(bp);
}
+ /*
+ * At this stage no more interrupts will arrive so we may safly clean
+ * the queueable objects here in case they failed to get cleaned so far.
+ */
+ bnx2x_squeeze_objects(bp);
+
+ /* There should be no more pending SP commands at this stage */
+ bp->sp_state = 0;
+
bp->port.pmf = 0;
/* Free SKBs, SGEs, TPA pool and driver internals */
@@ -1762,17 +2056,24 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->state = BNX2X_STATE_CLOSED;
+ /* Check if there are pending parity attentions. If there are - set
+ * RECOVERY_IN_PROGRESS.
+ */
+ if (bnx2x_chk_parity_attn(bp, &global, false)) {
+ bnx2x_set_reset_in_progress(bp);
+
+ /* Set RESET_IS_GLOBAL if needed */
+ if (global)
+ bnx2x_set_reset_global(bp);
+ }
+
+
/* The last driver must disable a "close the gate" if there is no
* parity attention or "process kill" pending.
*/
- if ((!bnx2x_dec_load_cnt(bp)) && (!bnx2x_chk_parity_attn(bp)) &&
- bnx2x_reset_is_done(bp))
+ if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
bnx2x_disable_close_the_gate(bp);
- /* Reset MCP mail box sequence if there is on going recovery */
- if (unload_mode == UNLOAD_RECOVERY)
- bp->fw_seq = 0;
-
return 0;
}
@@ -1834,6 +2135,7 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
int bnx2x_poll(struct napi_struct *napi, int budget)
{
int work_done = 0;
+ u8 cos;
struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
napi);
struct bnx2x *bp = fp->bp;
@@ -1846,8 +2148,10 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
}
#endif
- if (bnx2x_has_tx_work(fp))
- bnx2x_tx_int(fp);
+ for_each_cos_in_tx_queue(fp, cos)
+ if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
+ bnx2x_tx_int(bp, &fp->txdata[cos]);
+
if (bnx2x_has_rx_work(fp)) {
work_done += bnx2x_rx_int(fp, budget - work_done);
@@ -1909,7 +2213,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
* in Other Operating Systems(TM)
*/
static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
- struct bnx2x_fastpath *fp,
+ struct bnx2x_fp_txdata *txdata,
struct sw_tx_bd *tx_buf,
struct eth_tx_start_bd **tx_bd, u16 hlen,
u16 bd_prod, int nbd)
@@ -1930,7 +2234,7 @@ static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
/* now get a new data BD
* (after the pbd) and fill it */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- d_tx_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
+ d_tx_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
mapping = HILO_U64(le32_to_cpu(h_tx_bd->addr_hi),
le32_to_cpu(h_tx_bd->addr_lo)) + hlen;
@@ -2148,6 +2452,22 @@ static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
sizeof(struct udphdr) - skb->data;
}
+static inline void bnx2x_set_sbd_csum(struct bnx2x *bp, struct sk_buff *skb,
+ struct eth_tx_start_bd *tx_start_bd, u32 xmit_type)
+{
+ tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
+
+ if (xmit_type & XMIT_CSUM_V4)
+ tx_start_bd->bd_flags.as_bitfield |=
+ ETH_TX_BD_FLAGS_IP_CSUM;
+ else
+ tx_start_bd->bd_flags.as_bitfield |=
+ ETH_TX_BD_FLAGS_IPV6;
+
+ if (!(xmit_type & XMIT_CSUM_TCP))
+ tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IS_UDP;
+}
+
/**
* bnx2x_set_pbd_csum - update PBD with checksum and return header length
*
@@ -2210,16 +2530,18 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
+
struct bnx2x_fastpath *fp;
struct netdev_queue *txq;
+ struct bnx2x_fp_txdata *txdata;
struct sw_tx_bd *tx_buf;
- struct eth_tx_start_bd *tx_start_bd;
+ struct eth_tx_start_bd *tx_start_bd, *first_bd;
struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
u32 pbd_e2_parsing_data = 0;
u16 pkt_prod, bd_prod;
- int nbd, fp_index;
+ int nbd, txq_index, fp_index, txdata_index;
dma_addr_t mapping;
u32 xmit_type = bnx2x_xmit_type(bp, skb);
int i;
@@ -2233,12 +2555,43 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
#endif
- fp_index = skb_get_queue_mapping(skb);
- txq = netdev_get_tx_queue(dev, fp_index);
+ txq_index = skb_get_queue_mapping(skb);
+ txq = netdev_get_tx_queue(dev, txq_index);
+ BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT);
+
+ /* decode the fastpath index and the cos index from the txq */
+ fp_index = TXQ_TO_FP(txq_index);
+ txdata_index = TXQ_TO_COS(txq_index);
+
+#ifdef BCM_CNIC
+ /*
+ * Override the above for the FCoE queue:
+ * - FCoE fp entry is right after the ETH entries.
+ * - FCoE L2 queue uses bp->txdata[0] only.
+ */
+ if (unlikely(!NO_FCOE(bp) && (txq_index ==
+ bnx2x_fcoe_tx(bp, txq_index)))) {
+ fp_index = FCOE_IDX;
+ txdata_index = 0;
+ }
+#endif
+
+ /* enable this debug print to view the transmission queue being used
+ DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d",
+ txq_index, fp_index, txdata_index); */
+
+ /* locate the fastpath and the txdata */
fp = &bp->fp[fp_index];
+ txdata = &fp->txdata[txdata_index];
- if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) {
+ /* 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",
+ txdata->cid, fp_index, txdata_index, txdata, fp); */
+
+ if (unlikely(bnx2x_tx_avail(bp, txdata) <
+ (skb_shinfo(skb)->nr_frags + 3))) {
fp->eth_q_stats.driver_xoff++;
netif_tx_stop_queue(txq);
BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
@@ -2247,7 +2600,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
DP(NETIF_MSG_TX_QUEUED, "queue[%d]: SKB: summed %x protocol %x "
"protocol(%x,%x) gso type %x xmit_type %x\n",
- fp_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
+ txq_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
eth = (struct ethhdr *)skb->data;
@@ -2275,7 +2628,15 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
#endif
-
+ /* Map skb linear data for DMA */
+ mapping = dma_map_single(&bp->pdev->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ DP(NETIF_MSG_TX_QUEUED, "SKB mapping failed - "
+ "silently dropping this SKB\n");
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
/*
Please read carefully. First we use one BD which we mark as start,
then we have a parsing info BD (used for TSO or xsum),
@@ -2285,12 +2646,19 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
And above all, all pdb sizes are in words - NOT DWORDS!
*/
- pkt_prod = fp->tx_pkt_prod++;
- bd_prod = TX_BD(fp->tx_bd_prod);
+ /* get current pkt produced now - advance it just before sending packet
+ * since mapping of pages may fail and cause packet to be dropped
+ */
+ pkt_prod = txdata->tx_pkt_prod;
+ bd_prod = TX_BD(txdata->tx_bd_prod);
- /* get a tx_buf and first BD */
- tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)];
- tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd;
+ /* get a tx_buf and first BD
+ * tx_start_bd may be changed during SPLIT,
+ * but first_bd will always stay first
+ */
+ tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
+ tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
+ first_bd = tx_start_bd;
tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_ETH_ADDR_TYPE,
@@ -2300,13 +2668,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1);
/* remember the first BD of the packet */
- tx_buf->first_bd = fp->tx_bd_prod;
+ tx_buf->first_bd = txdata->tx_bd_prod;
tx_buf->skb = skb;
tx_buf->flags = 0;
DP(NETIF_MSG_TX_QUEUED,
"sending pkt %u @%p next_idx %u bd %u @%p\n",
- pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd);
+ pkt_prod, tx_buf, txdata->tx_pkt_prod, bd_prod, tx_start_bd);
if (vlan_tx_tag_present(skb)) {
tx_start_bd->vlan_or_ethertype =
@@ -2319,31 +2687,33 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- if (xmit_type & XMIT_CSUM) {
- tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
-
- if (xmit_type & XMIT_CSUM_V4)
- tx_start_bd->bd_flags.as_bitfield |=
- ETH_TX_BD_FLAGS_IP_CSUM;
- else
- tx_start_bd->bd_flags.as_bitfield |=
- ETH_TX_BD_FLAGS_IPV6;
-
- if (!(xmit_type & XMIT_CSUM_TCP))
- tx_start_bd->bd_flags.as_bitfield |=
- ETH_TX_BD_FLAGS_IS_UDP;
- }
+ if (xmit_type & XMIT_CSUM)
+ bnx2x_set_sbd_csum(bp, skb, tx_start_bd, xmit_type);
- if (CHIP_IS_E2(bp)) {
- pbd_e2 = &fp->tx_desc_ring[bd_prod].parse_bd_e2;
+ if (!CHIP_IS_E1x(bp)) {
+ pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
/* Set PBD in checksum offload case */
if (xmit_type & XMIT_CSUM)
hlen = bnx2x_set_pbd_csum_e2(bp, skb,
&pbd_e2_parsing_data,
xmit_type);
+ if (IS_MF_SI(bp)) {
+ /*
+ * fill in the MAC addresses in the PBD - for local
+ * switching
+ */
+ bnx2x_set_fw_mac_addr(&pbd_e2->src_mac_addr_hi,
+ &pbd_e2->src_mac_addr_mid,
+ &pbd_e2->src_mac_addr_lo,
+ eth->h_source);
+ bnx2x_set_fw_mac_addr(&pbd_e2->dst_mac_addr_hi,
+ &pbd_e2->dst_mac_addr_mid,
+ &pbd_e2->dst_mac_addr_lo,
+ eth->h_dest);
+ }
} else {
- pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
+ pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
/* Set PBD in checksum offload case */
if (xmit_type & XMIT_CSUM)
@@ -2351,15 +2721,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
- /* Map skb linear data for DMA */
- mapping = dma_map_single(&bp->pdev->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
-
/* Setup the data pointer of the first BD of the packet */
tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
- nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */
- tx_start_bd->nbd = cpu_to_le16(nbd);
+ nbd = 2; /* start_bd + pbd + frags (updated when pages are mapped) */
tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
pkt_size = tx_start_bd->nbytes;
@@ -2380,9 +2745,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO;
if (unlikely(skb_headlen(skb) > hlen))
- bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
- hlen, bd_prod, ++nbd);
- if (CHIP_IS_E2(bp))
+ bd_prod = bnx2x_tx_split(bp, txdata, tx_buf,
+ &tx_start_bd, hlen,
+ bd_prod, ++nbd);
+ if (!CHIP_IS_E1x(bp))
bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
xmit_type);
else
@@ -2401,19 +2767,35 @@ 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);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+
+ DP(NETIF_MSG_TX_QUEUED, "Unable to map page - "
+ "dropping packet...\n");
+
+ /* we need unmap all buffers already mapped
+ * for this SKB;
+ * first_bd->nbd need to be properly updated
+ * before call to bnx2x_free_tx_pkt
+ */
+ first_bd->nbd = cpu_to_le16(nbd);
+ bnx2x_free_tx_pkt(bp, txdata,
+ TX_BD(txdata->tx_pkt_prod));
+ return NETDEV_TX_OK;
+ }
+
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- tx_data_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
+ tx_data_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
if (total_pkt_bd == NULL)
- total_pkt_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
-
- mapping = dma_map_page(&bp->pdev->dev, frag->page,
- frag->page_offset,
- frag->size, DMA_TO_DEVICE);
+ total_pkt_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
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);
+ nbd++;
DP(NETIF_MSG_TX_QUEUED,
"frag %d bd @%p addr (%x:%x) nbytes %d\n",
@@ -2423,6 +2805,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
DP(NETIF_MSG_TX_QUEUED, "last bd @%p\n", tx_data_bd);
+ /* update with actual num BDs */
+ first_bd->nbd = cpu_to_le16(nbd);
+
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
/* now send a tx doorbell, counting the next BD
@@ -2431,6 +2816,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (TX_BD_POFF(bd_prod) < nbd)
nbd++;
+ /* total_pkt_bytes should be set on the first data BD if
+ * it's not an LSO packet and there is more than one
+ * data BD. In this case pkt_size is limited by an MTU value.
+ * However we prefer to set it for an LSO packet (while we don't
+ * have to) in order to save some CPU cycles in a none-LSO
+ * case, when we much more care about them.
+ */
if (total_pkt_bd != NULL)
total_pkt_bd->total_pkt_bytes = pkt_size;
@@ -2451,6 +2843,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
pbd_e2->parsing_data);
DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod);
+ txdata->tx_pkt_prod++;
/*
* Make sure that the BD data is updated before updating the producer
* since FW might read the BD right after the producer is updated.
@@ -2460,16 +2853,16 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
wmb();
- fp->tx_db.data.prod += nbd;
+ txdata->tx_db.data.prod += nbd;
barrier();
- DOORBELL(bp, fp->cid, fp->tx_db.raw);
+ DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
mmiowb();
- fp->tx_bd_prod += nbd;
+ txdata->tx_bd_prod += nbd;
- if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
+ if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 3)) {
netif_tx_stop_queue(txq);
/* paired memory barrier is in bnx2x_tx_int(), we have to keep
@@ -2478,34 +2871,110 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
smp_mb();
fp->eth_q_stats.driver_xoff++;
- if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)
+ if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3)
netif_tx_wake_queue(txq);
}
- fp->tx_pkt++;
+ txdata->tx_pkt++;
return NETDEV_TX_OK;
}
+/**
+ * bnx2x_setup_tc - routine to configure net_device for multi tc
+ *
+ * @netdev: net device to configure
+ * @tc: number of traffic classes to enable
+ *
+ * callback connected to the ndo_setup_tc function pointer
+ */
+int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
+{
+ int cos, prio, count, offset;
+ struct bnx2x *bp = netdev_priv(dev);
+
+ /* setup tc must be called under rtnl lock */
+ ASSERT_RTNL();
+
+ /* no traffic classes requested. aborting */
+ if (!num_tc) {
+ netdev_reset_tc(dev);
+ return 0;
+ }
+
+ /* 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",
+ 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",
+ num_tc);
+ return -EINVAL;
+ }
+
+ /* 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",
+ prio, bp->prio_to_cos[prio]);
+ }
+
+
+ /* Use this configuration to diffrentiate tc0 from other COSes
+ 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);
+ 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);
+ } */
+
+ /* configure traffic class to transmission queue mapping */
+ for (cos = 0; cos < bp->max_cos; cos++) {
+ 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",
+ cos, offset, count);
+ }
+
+ return 0;
+}
+
/* called with rtnl_lock */
int bnx2x_change_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
struct bnx2x *bp = netdev_priv(dev);
+ int rc = 0;
if (!is_valid_ether_addr((u8 *)(addr->sa_data)))
return -EINVAL;
+ if (netif_running(dev)) {
+ rc = bnx2x_set_eth_mac(bp, false);
+ if (rc)
+ return rc;
+ }
+
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
if (netif_running(dev))
- bnx2x_set_eth_mac(bp, 1);
+ rc = bnx2x_set_eth_mac(bp, true);
- return 0;
+ return rc;
}
static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
{
union host_hc_status_block *sb = &bnx2x_fp(bp, fp_index, status_blk);
struct bnx2x_fastpath *fp = &bp->fp[fp_index];
+ u8 cos;
/* Common */
#ifdef BCM_CNIC
@@ -2516,7 +2985,7 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
} else {
#endif
/* status blocks */
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
BNX2X_PCI_FREE(sb->e2_sb,
bnx2x_fp(bp, fp_index,
status_blk_mapping),
@@ -2554,10 +3023,18 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
/* Tx */
if (!skip_tx_queue(bp, fp_index)) {
/* fastpath tx rings: tx_buf tx_desc */
- BNX2X_FREE(bnx2x_fp(bp, fp_index, tx_buf_ring));
- BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, tx_desc_ring),
- bnx2x_fp(bp, fp_index, tx_desc_mapping),
- sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+ for_each_cos_in_tx_queue(fp, cos) {
+ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
+
+ DP(BNX2X_MSG_SP,
+ "freeing tx memory of fp %d cos %d cid %d",
+ fp_index, cos, txdata->cid);
+
+ BNX2X_FREE(txdata->tx_buf_ring);
+ BNX2X_PCI_FREE(txdata->tx_desc_ring,
+ txdata->tx_desc_mapping,
+ sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+ }
}
/* end of fastpath */
}
@@ -2572,7 +3049,7 @@ void bnx2x_free_fp_mem(struct bnx2x *bp)
static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
{
union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
bnx2x_fp(bp, index, sb_index_values) =
(__le16 *)status_blk.e2_sb->sb.index_values;
bnx2x_fp(bp, index, sb_running_index) =
@@ -2590,26 +3067,24 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
union host_hc_status_block *sb;
struct bnx2x_fastpath *fp = &bp->fp[index];
int ring_size = 0;
+ u8 cos;
/* if rx_ring_size specified - use it */
int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size :
- MAX_RX_AVAIL/bp->num_queues;
+ MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
/* allocate at least number of buffers required by FW */
- rx_ring_size = max_t(int, fp->disable_tpa ? MIN_RX_SIZE_NONTPA :
+ rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
MIN_RX_SIZE_TPA,
rx_ring_size);
- bnx2x_fp(bp, index, bp) = bp;
- bnx2x_fp(bp, index, index) = index;
-
/* Common */
sb = &bnx2x_fp(bp, index, status_blk);
#ifdef BCM_CNIC
if (!IS_FCOE_IDX(index)) {
#endif
/* status blocks */
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
BNX2X_PCI_ALLOC(sb->e2_sb,
&bnx2x_fp(bp, index, status_blk_mapping),
sizeof(struct host_hc_status_block_e2));
@@ -2620,16 +3095,29 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
#ifdef BCM_CNIC
}
#endif
- set_sb_shortcuts(bp, index);
+
+ /* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
+ * set shortcuts for it.
+ */
+ if (!IS_FCOE_IDX(index))
+ set_sb_shortcuts(bp, index);
/* Tx */
if (!skip_tx_queue(bp, index)) {
/* fastpath tx rings: tx_buf tx_desc */
- BNX2X_ALLOC(bnx2x_fp(bp, index, tx_buf_ring),
+ for_each_cos_in_tx_queue(fp, cos) {
+ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
+
+ DP(BNX2X_MSG_SP, "allocating tx memory of "
+ "fp %d cos %d",
+ index, cos);
+
+ BNX2X_ALLOC(txdata->tx_buf_ring,
sizeof(struct sw_tx_bd) * NUM_TX_BD);
- BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, tx_desc_ring),
- &bnx2x_fp(bp, index, tx_desc_mapping),
+ BNX2X_PCI_ALLOC(txdata->tx_desc_ring,
+ &txdata->tx_desc_mapping,
sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+ }
}
/* Rx */
@@ -2672,7 +3160,7 @@ alloc_mem_err:
index, ring_size);
/* FW will drop all packets if queue is not big enough,
* In these cases we disable the queue
- * Min size diferent for TPA and non-TPA queues
+ * Min size is different for OOO, TPA and non-TPA queues
*/
if (ring_size < (fp->disable_tpa ?
MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) {
@@ -2690,17 +3178,24 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
/**
* 1. Allocate FP for leading - fatal if error
* 2. {CNIC} Allocate FCoE FP - fatal if error
- * 3. Allocate RSS - fix number of queues if error
+ * 3. {CNIC} Allocate OOO + FWD - disable OOO if error
+ * 4. Allocate RSS - fix number of queues if error
*/
/* leading */
if (bnx2x_alloc_fp_mem_at(bp, 0))
return -ENOMEM;
+
#ifdef BCM_CNIC
- /* FCoE */
- if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX))
- return -ENOMEM;
+ if (!NO_FCOE(bp))
+ /* FCoE */
+ if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX))
+ /* we will fail load process instead of mark
+ * NO_FCOE_FLAG
+ */
+ return -ENOMEM;
#endif
+
/* RSS */
for_each_nondefault_eth_queue(bp, i)
if (bnx2x_alloc_fp_mem_at(bp, i))
@@ -2718,7 +3213,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
* FCOE_IDX < FWD_IDX < OOO_IDX
*/
- /* move FCoE fp */
+ /* move FCoE fp even NO_FCOE_FLAG is on */
bnx2x_move_fp(bp, FCOE_IDX, FCOE_IDX - delta);
#endif
bp->num_queues -= delta;
@@ -2729,30 +3224,6 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
return 0;
}
-static int bnx2x_setup_irqs(struct bnx2x *bp)
-{
- int rc = 0;
- if (bp->flags & USING_MSIX_FLAG) {
- rc = bnx2x_req_msix_irqs(bp);
- if (rc)
- return rc;
- } else {
- bnx2x_ack_int(bp);
- rc = bnx2x_req_irq(bp);
- if (rc) {
- BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc);
- return rc;
- }
- if (bp->flags & USING_MSI_FLAG) {
- bp->dev->irq = bp->pdev->irq;
- netdev_info(bp->dev, "using MSI IRQ %d\n",
- bp->pdev->irq);
- }
- }
-
- return 0;
-}
-
void bnx2x_free_mem_bp(struct bnx2x *bp)
{
kfree(bp->fp);
@@ -2765,16 +3236,23 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
struct bnx2x_fastpath *fp;
struct msix_entry *tbl;
struct bnx2x_ilt *ilt;
+ int msix_table_size = 0;
+
+ /*
+ * The biggest MSI-X table we might need is as a maximum number of fast
+ * path IGU SBs plus default SB (for PF).
+ */
+ msix_table_size = bp->igu_sb_cnt + 1;
- /* fp array */
- fp = kzalloc(L2_FP_COUNT(bp->l2_cid_count)*sizeof(*fp), GFP_KERNEL);
+ /* fp array: RSS plus CNIC related L2 queues */
+ fp = kzalloc((BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE) *
+ sizeof(*fp), GFP_KERNEL);
if (!fp)
goto alloc_err;
bp->fp = fp;
/* msix table */
- tbl = kzalloc((FP_SB_COUNT(bp->l2_cid_count) + 1) * sizeof(*tbl),
- GFP_KERNEL);
+ tbl = kzalloc(msix_table_size * sizeof(*tbl), GFP_KERNEL);
if (!tbl)
goto alloc_err;
bp->msix_table = tbl;
@@ -2792,7 +3270,7 @@ alloc_err:
}
-static int bnx2x_reload_if_running(struct net_device *dev)
+int bnx2x_reload_if_running(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -2803,6 +3281,78 @@ static int bnx2x_reload_if_running(struct net_device *dev)
return bnx2x_nic_load(bp, LOAD_NORMAL);
}
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp)
+{
+ u32 sel_phy_idx = 0;
+ if (bp->link_params.num_phys <= 1)
+ return INT_PHY;
+
+ if (bp->link_vars.link_up) {
+ sel_phy_idx = EXT_PHY1;
+ /* In case link is SERDES, check if the EXT_PHY2 is the one */
+ if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
+ (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
+ sel_phy_idx = EXT_PHY2;
+ } else {
+
+ switch (bnx2x_phy_selection(&bp->link_params)) {
+ case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+ sel_phy_idx = EXT_PHY1;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+ sel_phy_idx = EXT_PHY2;
+ break;
+ }
+ }
+
+ return sel_phy_idx;
+
+}
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
+{
+ u32 sel_phy_idx = bnx2x_get_cur_phy_idx(bp);
+ /*
+ * The selected actived PHY is always after swapping (in case PHY
+ * swapping is enabled). So when swapping is enabled, we need to reverse
+ * the configuration
+ */
+
+ if (bp->link_params.multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
+ if (sel_phy_idx == EXT_PHY1)
+ sel_phy_idx = EXT_PHY2;
+ else if (sel_phy_idx == EXT_PHY2)
+ sel_phy_idx = EXT_PHY1;
+ }
+ return LINK_CONFIG_IDX(sel_phy_idx);
+}
+
+#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
+{
+ struct bnx2x *bp = netdev_priv(dev);
+ struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+ switch (type) {
+ case NETDEV_FCOE_WWNN:
+ *wwn = HILO_U64(cp->fcoe_wwn_node_name_hi,
+ cp->fcoe_wwn_node_name_lo);
+ break;
+ case NETDEV_FCOE_WWPN:
+ *wwn = HILO_U64(cp->fcoe_wwn_port_name_hi,
+ cp->fcoe_wwn_port_name_lo);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
+
/* called with rtnl_lock */
int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -2882,8 +3432,13 @@ void bnx2x_tx_timeout(struct net_device *dev)
if (!bp->panic)
bnx2x_panic();
#endif
+
+ smp_mb__before_clear_bit();
+ set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state);
+ smp_mb__after_clear_bit();
+
/* This allows the netif to be shutdown gracefully before resetting */
- schedule_delayed_work(&bp->reset_task, 0);
+ schedule_delayed_work(&bp->sp_rtnl_task, 0);
}
int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -2954,3 +3509,57 @@ int bnx2x_resume(struct pci_dev *pdev)
return rc;
}
+
+
+void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
+ u32 cid)
+{
+ /* ustorm cxt validation */
+ cxt->ustorm_ag_context.cdu_usage =
+ CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
+ CDU_REGION_NUMBER_UCM_AG, ETH_CONNECTION_TYPE);
+ /* xcontext validation */
+ cxt->xstorm_ag_context.cdu_reserved =
+ CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
+ CDU_REGION_NUMBER_XCM_AG, ETH_CONNECTION_TYPE);
+}
+
+static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
+ u8 fw_sb_id, u8 sb_index,
+ u8 ticks)
+{
+
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index);
+ REG_WR8(bp, addr, ticks);
+ DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
+ port, fw_sb_id, sb_index, ticks);
+}
+
+static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
+ u16 fw_sb_id, u8 sb_index,
+ u8 disable)
+{
+ u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index);
+ u16 flags = REG_RD16(bp, addr);
+ /* clear and set */
+ flags &= ~HC_INDEX_DATA_HC_ENABLED;
+ flags |= enable_flag;
+ REG_WR16(bp, addr, flags);
+ DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
+ port, fw_sb_id, sb_index, disable);
+}
+
+void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
+ u8 sb_index, u8 disable, u16 usec)
+{
+ int port = BP_PORT(bp);
+ u8 ticks = usec / BNX2X_BTR;
+
+ storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
+
+ disable = disable ? 1 : (usec ? 0 : 1);
+ storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
+}
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index 1a3545bd8a92..223bfeebc597 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -18,11 +18,15 @@
#define BNX2X_CMN_H
#include <linux/types.h>
+#include <linux/pci.h>
#include <linux/netdevice.h>
#include "bnx2x.h"
+/* This is used as a replacement for an MCP if it's not present */
+extern int load_count[2][3]; /* per-path: 0-common, 1-port0, 2-port1 */
+
extern int num_queues;
/************************ Macros ********************************/
@@ -61,6 +65,73 @@ extern int num_queues;
/*********************** Interfaces ****************************
* Functions that need to be implemented by each driver version
*/
+/* Init */
+
+/**
+ * bnx2x_send_unload_req - request unload mode from the MCP.
+ *
+ * @bp: driver handle
+ * @unload_mode: requested function's unload mode
+ *
+ * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
+ */
+u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode);
+
+/**
+ * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
+ *
+ * @bp: driver handle
+ */
+void bnx2x_send_unload_done(struct bnx2x *bp);
+
+/**
+ * bnx2x_config_rss_pf - configure RSS parameters.
+ *
+ * @bp: driver handle
+ * @ind_table: indirection table to configure
+ * @config_hash: re-configure RSS hash keys configuration
+ */
+int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash);
+
+/**
+ * bnx2x__init_func_obj - init function object
+ *
+ * @bp: driver handle
+ *
+ * Initializes the Function Object with the appropriate
+ * parameters which include a function slow path driver
+ * interface.
+ */
+void bnx2x__init_func_obj(struct bnx2x *bp);
+
+/**
+ * bnx2x_setup_queue - setup eth queue.
+ *
+ * @bp: driver handle
+ * @fp: pointer to the fastpath structure
+ * @leading: boolean
+ *
+ */
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ bool leading);
+
+/**
+ * bnx2x_setup_leading - bring up a leading eth queue.
+ *
+ * @bp: driver handle
+ */
+int bnx2x_setup_leading(struct bnx2x *bp);
+
+/**
+ * bnx2x_fw_command - send the MCP a request
+ *
+ * @bp: driver handle
+ * @command: request
+ * @param: request's parameter
+ *
+ * block until there is a reply
+ */
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
/**
* bnx2x_initial_phy_init - initialize link parameters structure variables.
@@ -88,6 +159,32 @@ void bnx2x_link_set(struct bnx2x *bp);
u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
/**
+ * bnx2x_drv_pulse - write driver pulse to shmem
+ *
+ * @bp: driver handle
+ *
+ * writes the value in bp->fw_drv_pulse_wr_seq to drv_pulse mbox
+ * in the shmem.
+ */
+void bnx2x_drv_pulse(struct bnx2x *bp);
+
+/**
+ * bnx2x_igu_ack_sb - update IGU with current SB value
+ *
+ * @bp: driver handle
+ * @igu_sb_id: SB id
+ * @segment: SB segment
+ * @index: SB index
+ * @op: SB operation
+ * @update: is HW update required
+ */
+void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+ u16 index, u8 op, u8 update);
+
+/* Disable transactions from chip to host */
+void bnx2x_pf_disable(struct bnx2x *bp);
+
+/**
* bnx2x__link_status_update - handles link status change.
*
* @bp: driver handle
@@ -165,21 +262,6 @@ void bnx2x_int_enable(struct bnx2x *bp);
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
/**
- * bnx2x_init_firmware - loads device firmware
- *
- * @bp: driver handle
- */
-int bnx2x_init_firmware(struct bnx2x *bp);
-
-/**
- * bnx2x_init_hw - init HW blocks according to current initialization stage.
- *
- * @bp: driver handle
- * @load_code: COMMON, PORT or FUNCTION
- */
-int bnx2x_init_hw(struct bnx2x *bp, u32 load_code);
-
-/**
* bnx2x_nic_init - init driver internals.
*
* @bp: driver handle
@@ -207,16 +289,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp);
void bnx2x_free_mem(struct bnx2x *bp);
/**
- * bnx2x_setup_client - setup eth client.
- *
- * @bp: driver handle
- * @fp: pointer to fastpath structure
- * @is_leading: boolean
- */
-int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- int is_leading);
-
-/**
* bnx2x_set_num_queues - set number of queues according to mode.
*
* @bp: driver handle
@@ -252,36 +324,21 @@ int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource);
int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource);
/**
- * bnx2x_set_eth_mac - configure eth MAC address in the HW
- *
- * @bp: driver handle
- * @set: set or clear
- *
- * Configures according to the value in netdev->dev_addr.
- */
-void bnx2x_set_eth_mac(struct bnx2x *bp, int set);
-
-#ifdef BCM_CNIC
-/**
- * bnx2x_set_fip_eth_mac_addr - Set/Clear FIP MAC(s)
+ * bnx2x_release_leader_lock - release recovery leader lock
*
* @bp: driver handle
- * @set: set or clear the CAM entry
- *
- * Used next enties in the CAM after the ETH MAC(s).
- * This function will wait until the ramdord completion returns.
- * Return 0 if cussess, -ENODEV if ramrod doesn't return.
*/
-int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set);
+int bnx2x_release_leader_lock(struct bnx2x *bp);
/**
- * bnx2x_set_all_enode_macs - Set/Clear ALL_ENODE mcast MAC.
+ * bnx2x_set_eth_mac - configure eth MAC address in the HW
*
* @bp: driver handle
* @set: set or clear
+ *
+ * Configures according to the value in netdev->dev_addr.
*/
-int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set);
-#endif
+int bnx2x_set_eth_mac(struct bnx2x *bp, bool set);
/**
* bnx2x_set_rx_mode - set MAC filtering configurations.
@@ -289,6 +346,8 @@ int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set);
* @dev: netdevice
*
* called with netif_tx_lock from dev_mcast.c
+ * If bp->state is OPEN, should be called with
+ * netif_addr_lock_bh()
*/
void bnx2x_set_rx_mode(struct net_device *dev);
@@ -296,25 +355,38 @@ void bnx2x_set_rx_mode(struct net_device *dev);
* bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW.
*
* @bp: driver handle
+ *
+ * If bp->state is OPEN, should be called with
+ * netif_addr_lock_bh().
*/
void bnx2x_set_storm_rx_mode(struct bnx2x *bp);
+/**
+ * bnx2x_set_q_rx_mode - configures rx_mode for a single queue.
+ *
+ * @bp: driver handle
+ * @cl_id: client id
+ * @rx_mode_flags: rx mode configuration
+ * @rx_accept_flags: rx accept configuration
+ * @tx_accept_flags: tx accept configuration (tx switch)
+ * @ramrod_flags: ramrod configuration
+ */
+void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
+ unsigned long rx_mode_flags,
+ unsigned long rx_accept_flags,
+ unsigned long tx_accept_flags,
+ unsigned long ramrod_flags);
+
/* Parity errors related */
void bnx2x_inc_load_cnt(struct bnx2x *bp);
u32 bnx2x_dec_load_cnt(struct bnx2x *bp);
-bool bnx2x_chk_parity_attn(struct bnx2x *bp);
-bool bnx2x_reset_is_done(struct bnx2x *bp);
+bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
+bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
+void bnx2x_set_reset_in_progress(struct bnx2x *bp);
+void bnx2x_set_reset_global(struct bnx2x *bp);
void bnx2x_disable_close_the_gate(struct bnx2x *bp);
/**
- * bnx2x_stats_handle - perform statistics handling according to event.
- *
- * @bp: driver handle
- * @event: bnx2x_stats_event
- */
-void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
-
-/**
* bnx2x_sp_event - handle ramrods completion.
*
* @fp: fastpath handle for the event
@@ -323,15 +395,6 @@ void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
/**
- * bnx2x_func_start - init function
- *
- * @bp: driver handle
- *
- * Must be called before sending CLIENT_SETUP for the first client.
- */
-int bnx2x_func_start(struct bnx2x *bp);
-
-/**
* bnx2x_ilt_set_info - prepare ILT configurations.
*
* @bp: driver handle
@@ -362,6 +425,10 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
* @value: new value
*/
void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
+/* Error handling */
+void bnx2x_panic_dump(struct bnx2x *bp);
+
+void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
/* dev_close main block */
int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
@@ -372,16 +439,25 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
/* hard_xmit callback */
netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
+/* setup_tc callback */
+int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
+
/* select_queue callback */
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
+/* reload helper */
+int bnx2x_reload_if_running(struct net_device *dev);
+
int bnx2x_change_mac_addr(struct net_device *dev, void *p);
/* NAPI poll Rx part */
int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
+void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod);
+
/* NAPI poll Tx part */
-int bnx2x_tx_int(struct bnx2x_fastpath *fp);
+int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata);
/* suspend/resume callbacks */
int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
@@ -392,7 +468,6 @@ void bnx2x_free_irq(struct bnx2x *bp);
void bnx2x_free_fp_mem(struct bnx2x *bp);
int bnx2x_alloc_fp_mem(struct bnx2x *bp);
-
void bnx2x_init_rx_rings(struct bnx2x *bp);
void bnx2x_free_skbs(struct bnx2x *bp);
void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
@@ -447,6 +522,17 @@ 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))
+/**
+ * bnx2x_fcoe_get_wwn - return the requested WWN value for this port
+ *
+ * @dev: net_device
+ * @wwn: output buffer
+ * @type: WWN type: NETDEV_FCOE_WWNN (node) or NETDEV_FCOE_WWPN (port)
+ *
+ */
+int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type);
+#endif
u32 bnx2x_fix_features(struct net_device *dev, u32 features);
int bnx2x_set_features(struct net_device *dev, u32 features);
@@ -457,19 +543,20 @@ int bnx2x_set_features(struct net_device *dev, u32 features);
*/
void bnx2x_tx_timeout(struct net_device *dev);
+/*********************** Inlines **********************************/
+/*********************** Fast path ********************************/
static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
{
barrier(); /* status block is written to by the chip */
fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID];
}
-static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
- struct bnx2x_fastpath *fp,
- u16 bd_prod, u16 rx_comp_prod,
- u16 rx_sge_prod)
+static inline void bnx2x_update_rx_prod_gen(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, u16 bd_prod,
+ u16 rx_comp_prod, u16 rx_sge_prod, u32 start)
{
struct ustorm_eth_rx_producers rx_prods = {0};
- int i;
+ u32 i;
/* Update producers */
rx_prods.bd_prod = bd_prod;
@@ -486,10 +573,8 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
*/
wmb();
- for (i = 0; i < sizeof(struct ustorm_eth_rx_producers)/4; i++)
- REG_WR(bp,
- BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset + i*4,
- ((u32 *)&rx_prods)[i]);
+ for (i = 0; i < sizeof(rx_prods)/4; i++)
+ REG_WR(bp, start + i*4, ((u32 *)&rx_prods)[i]);
mmiowb(); /* keep prod updates ordered */
@@ -519,7 +604,7 @@ static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
barrier();
}
-static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
+static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
u8 idu_sb_id, bool is_Pf)
{
u32 data, ctl, cnt = 100;
@@ -527,7 +612,7 @@ static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
u32 sb_bit = 1 << (idu_sb_id%32);
- u32 func_encode = BP_FUNC(bp) |
+ u32 func_encode = func |
((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
@@ -590,15 +675,6 @@ static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
barrier();
}
-static inline void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
- u16 index, u8 op, u8 update)
-{
- u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
-
- bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
- igu_addr);
-}
-
static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
u16 index, u8 op, u8 update)
{
@@ -653,21 +729,22 @@ static inline u16 bnx2x_ack_int(struct bnx2x *bp)
return bnx2x_igu_ack_int(bp);
}
-static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
+static inline int bnx2x_has_tx_work_unload(struct bnx2x_fp_txdata *txdata)
{
/* Tell compiler that consumer and producer can change */
barrier();
- return fp->tx_pkt_prod != fp->tx_pkt_cons;
+ return txdata->tx_pkt_prod != txdata->tx_pkt_cons;
}
-static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
+static inline u16 bnx2x_tx_avail(struct bnx2x *bp,
+ struct bnx2x_fp_txdata *txdata)
{
s16 used;
u16 prod;
u16 cons;
- prod = fp->tx_bd_prod;
- cons = fp->tx_bd_cons;
+ prod = txdata->tx_bd_prod;
+ cons = txdata->tx_bd_cons;
/* NUM_TX_RINGS = number of "next-page" entries
It will be used as a threshold */
@@ -675,21 +752,30 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
#ifdef BNX2X_STOP_ON_ERROR
WARN_ON(used < 0);
- WARN_ON(used > fp->bp->tx_ring_size);
- WARN_ON((fp->bp->tx_ring_size - used) > MAX_TX_AVAIL);
+ WARN_ON(used > bp->tx_ring_size);
+ WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL);
#endif
- return (s16)(fp->bp->tx_ring_size) - used;
+ return (s16)(bp->tx_ring_size) - used;
}
-static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
+static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata)
{
u16 hw_cons;
/* Tell compiler that status block fields can change */
barrier();
- hw_cons = le16_to_cpu(*fp->tx_cons_sb);
- return hw_cons != fp->tx_pkt_cons;
+ hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
+ return hw_cons != txdata->tx_pkt_cons;
+}
+
+static inline bool bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
+{
+ u8 cos;
+ for_each_cos_in_tx_queue(fp, cos)
+ if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
+ return true;
+ return false;
}
static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
@@ -705,7 +791,7 @@ static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
}
/**
- * disables tx from stack point of view
+ * bnx2x_tx_disable - disables tx from stack point of view
*
* @bp: driver handle
*/
@@ -740,7 +826,7 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp)
int i;
/* Add NAPI objects */
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, BNX2X_NAPI_WEIGHT);
}
@@ -749,7 +835,7 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp)
{
int i;
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
}
@@ -779,7 +865,7 @@ static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
int idx = RX_SGE_CNT * i - 1;
for (j = 0; j < 2; j++) {
- SGE_MASK_CLEAR_BIT(fp, idx);
+ BIT_VEC64_CLEAR_BIT(fp->sge_mask, idx);
idx--;
}
}
@@ -789,7 +875,7 @@ static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
{
/* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
memset(fp->sge_mask, 0xff,
- (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
+ (NUM_RX_SGE >> BIT_VEC64_ELEM_SHIFT)*sizeof(u64));
/* Clear the two last indices in the page to 1:
these are the indices that correspond to the "next" element,
@@ -861,22 +947,69 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
u16 cons, u16 prod)
{
- struct bnx2x *bp = fp->bp;
struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons];
struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
- dma_sync_single_for_device(&bp->pdev->dev,
- dma_unmap_addr(cons_rx_buf, mapping),
- RX_COPY_THRESH, DMA_FROM_DEVICE);
-
- prod_rx_buf->skb = cons_rx_buf->skb;
dma_unmap_addr_set(prod_rx_buf, mapping,
dma_unmap_addr(cons_rx_buf, mapping));
+ prod_rx_buf->skb = cons_rx_buf->skb;
*prod_bd = *cons_bd;
}
+/************************* Init ******************************************/
+
+/**
+ * bnx2x_func_start - init function
+ *
+ * @bp: driver handle
+ *
+ * Must be called before sending CLIENT_SETUP for the first client.
+ */
+static inline int bnx2x_func_start(struct bnx2x *bp)
+{
+ struct bnx2x_func_state_params func_params = {0};
+ struct bnx2x_func_start_params *start_params =
+ &func_params.params.start;
+
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_START;
+
+ /* Function parameters */
+ start_params->mf_mode = bp->mf_mode;
+ start_params->sd_vlan_tag = bp->mf_ov;
+ if (CHIP_IS_E1x(bp))
+ start_params->network_cos_mode = OVERRIDE_COS;
+ else
+ start_params->network_cos_mode = STATIC_COS;
+
+ return bnx2x_func_state_change(bp, &func_params);
+}
+
+
+/**
+ * bnx2x_set_fw_mac_addr - fill in a MAC address in FW format
+ *
+ * @fw_hi: pointer to upper part
+ * @fw_mid: pointer to middle part
+ * @fw_lo: pointer to lower part
+ * @mac: pointer to MAC address
+ */
+static inline void bnx2x_set_fw_mac_addr(u16 *fw_hi, u16 *fw_mid, u16 *fw_lo,
+ u8 *mac)
+{
+ ((u8 *)fw_hi)[0] = mac[1];
+ ((u8 *)fw_hi)[1] = mac[0];
+ ((u8 *)fw_mid)[0] = mac[3];
+ ((u8 *)fw_mid)[1] = mac[2];
+ ((u8 *)fw_lo)[0] = mac[5];
+ ((u8 *)fw_lo)[1] = mac[4];
+}
+
static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
struct bnx2x_fastpath *fp, int last)
{
@@ -895,57 +1028,58 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
int i;
for (i = 0; i < last; i++) {
- struct sw_rx_bd *rx_buf = &(fp->tpa_pool[i]);
- struct sk_buff *skb = rx_buf->skb;
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i];
+ struct sw_rx_bd *first_buf = &tpa_info->first_buf;
+ struct sk_buff *skb = first_buf->skb;
if (skb == NULL) {
DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i);
continue;
}
-
- if (fp->tpa_state[i] == BNX2X_TPA_START)
+ if (tpa_info->tpa_state == BNX2X_TPA_START)
dma_unmap_single(&bp->pdev->dev,
- dma_unmap_addr(rx_buf, mapping),
+ dma_unmap_addr(first_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE);
-
dev_kfree_skb(skb);
- rx_buf->skb = NULL;
+ first_buf->skb = NULL;
}
}
-static inline void bnx2x_init_tx_ring_one(struct bnx2x_fastpath *fp)
+static inline void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
{
int i;
for (i = 1; i <= NUM_TX_RINGS; i++) {
struct eth_tx_next_bd *tx_next_bd =
- &fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
+ &txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
tx_next_bd->addr_hi =
- cpu_to_le32(U64_HI(fp->tx_desc_mapping +
+ cpu_to_le32(U64_HI(txdata->tx_desc_mapping +
BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
tx_next_bd->addr_lo =
- cpu_to_le32(U64_LO(fp->tx_desc_mapping +
+ cpu_to_le32(U64_LO(txdata->tx_desc_mapping +
BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
}
- SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
- fp->tx_db.data.zero_fill1 = 0;
- fp->tx_db.data.prod = 0;
+ SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
+ txdata->tx_db.data.zero_fill1 = 0;
+ txdata->tx_db.data.prod = 0;
- fp->tx_pkt_prod = 0;
- fp->tx_pkt_cons = 0;
- fp->tx_bd_prod = 0;
- fp->tx_bd_cons = 0;
- fp->tx_pkt = 0;
+ txdata->tx_pkt_prod = 0;
+ txdata->tx_pkt_cons = 0;
+ txdata->tx_bd_prod = 0;
+ txdata->tx_bd_cons = 0;
+ txdata->tx_pkt = 0;
}
static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
{
int i;
+ u8 cos;
for_each_tx_queue(bp, i)
- bnx2x_init_tx_ring_one(&bp->fp[i]);
+ for_each_cos_in_tx_queue(&bp->fp[i], cos)
+ bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]);
}
static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
@@ -1038,31 +1172,220 @@ static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
return i - fp->eth_q_stats.rx_skb_alloc_failed;
}
+/* Statistics ID are global per chip/path, while Client IDs for E1x are per
+ * port.
+ */
+static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
+{
+ if (!CHIP_IS_E1x(fp->bp))
+ return fp->cl_id;
+ else
+ return fp->cl_id + BP_PORT(fp->bp) * FP_SB_MAX_E1x;
+}
+
+static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp,
+ bnx2x_obj_type obj_type)
+{
+ struct bnx2x *bp = fp->bp;
+
+ /* Configure classification DBs */
+ bnx2x_init_mac_obj(bp, &fp->mac_obj, fp->cl_id, fp->cid,
+ BP_FUNC(bp), bnx2x_sp(bp, mac_rdata),
+ bnx2x_sp_mapping(bp, mac_rdata),
+ BNX2X_FILTER_MAC_PENDING,
+ &bp->sp_state, obj_type,
+ &bp->macs_pool);
+}
+
+/**
+ * bnx2x_get_path_func_num - get number of active functions
+ *
+ * @bp: driver handle
+ *
+ * Calculates the number of active (not hidden) functions on the
+ * current path.
+ */
+static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp)
+{
+ u8 func_num = 0, i;
+
+ /* 57710 has only one function per-port */
+ if (CHIP_IS_E1(bp))
+ return 1;
+
+ /* Calculate a number of functions enabled on the current
+ * PATH/PORT.
+ */
+ if (CHIP_REV_IS_SLOW(bp)) {
+ if (IS_MF(bp))
+ func_num = 4;
+ else
+ func_num = 2;
+ } else {
+ for (i = 0; i < E1H_FUNC_MAX / 2; i++) {
+ u32 func_config =
+ MF_CFG_RD(bp,
+ func_mf_config[BP_PORT(bp) + 2 * i].
+ config);
+ func_num +=
+ ((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1);
+ }
+ }
+
+ WARN_ON(!func_num);
+
+ return func_num;
+}
+
+static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
+{
+ /* RX_MODE controlling object */
+ bnx2x_init_rx_mode_obj(bp, &bp->rx_mode_obj);
+
+ /* multicast configuration controlling object */
+ bnx2x_init_mcast_obj(bp, &bp->mcast_obj, bp->fp->cl_id, bp->fp->cid,
+ BP_FUNC(bp), BP_FUNC(bp),
+ bnx2x_sp(bp, mcast_rdata),
+ bnx2x_sp_mapping(bp, mcast_rdata),
+ BNX2X_FILTER_MCAST_PENDING, &bp->sp_state,
+ BNX2X_OBJ_TYPE_RX);
+
+ /* Setup CAM credit pools */
+ bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp),
+ bnx2x_get_path_func_num(bp));
+
+ /* RSS configuration object */
+ bnx2x_init_rss_config_obj(bp, &bp->rss_conf_obj, bp->fp->cl_id,
+ bp->fp->cid, BP_FUNC(bp), BP_FUNC(bp),
+ bnx2x_sp(bp, rss_rdata),
+ bnx2x_sp_mapping(bp, rss_rdata),
+ BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state,
+ BNX2X_OBJ_TYPE_RX);
+}
+
+static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
+{
+ if (CHIP_IS_E1x(fp->bp))
+ return fp->cl_id + BP_PORT(fp->bp) * ETH_MAX_RX_CLIENTS_E1H;
+ else
+ return fp->cl_id;
+}
+
+static inline u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
+{
+ struct bnx2x *bp = fp->bp;
+
+ if (!CHIP_IS_E1x(bp))
+ return USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id);
+ else
+ return USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+}
+
+static inline void bnx2x_init_txdata(struct bnx2x *bp,
+ struct bnx2x_fp_txdata *txdata, u32 cid, int txq_index,
+ __le16 *tx_cons_sb)
+{
+ txdata->cid = cid;
+ txdata->txq_index = txq_index;
+ txdata->tx_cons_sb = tx_cons_sb;
+
+ DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d",
+ txdata->cid, txdata->txq_index);
+}
+
#ifdef BCM_CNIC
+static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
+{
+ return bp->cnic_base_cl_id + cl_idx +
+ (bp->pf_num >> 1) * NON_ETH_CONTEXT_USE;
+}
+
+static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp)
+{
+
+ /* the 'first' id is allocated for the cnic */
+ return bp->base_fw_ndsb;
+}
+
+static inline u8 bnx2x_cnic_igu_sb_id(struct bnx2x *bp)
+{
+ return bp->igu_base_sb;
+}
+
+
static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
{
- bnx2x_fcoe(bp, cl_id) = BNX2X_FCOE_ETH_CL_ID +
- BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
+ struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
+ unsigned long q_type = 0;
+
+ bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
+ BNX2X_FCOE_ETH_CL_ID_IDX);
+ /** Current BNX2X_FCOE_ETH_CID deffinition implies not more than
+ * 16 ETH clients per function when CNIC is enabled!
+ *
+ * Fix it ASAP!!!
+ */
bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID;
bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
- bnx2x_fcoe(bp, bp) = bp;
- bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
- bnx2x_fcoe(bp, index) = FCOE_IDX;
bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
- bnx2x_fcoe(bp, tx_cons_sb) = BNX2X_FCOE_L2_TX_INDEX;
+
+ 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);
+
/* qZone id equals to FW (per path) client id */
- bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fcoe(bp, cl_id) +
- BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
- ETH_MAX_RX_CLIENTS_E1H);
+ bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
/* init shortcut */
- bnx2x_fcoe(bp, ustorm_rx_prods_offset) = CHIP_IS_E2(bp) ?
- USTORM_RX_PRODS_E2_OFFSET(bnx2x_fcoe(bp, cl_qzone_id)) :
- USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), bnx2x_fcoe_fp(bp)->cl_id);
+ bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
+ bnx2x_rx_ustorm_prods_offset(fp);
+
+ /* Configure Queue State object */
+ __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
+ __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
+ /* No multi-CoS for FCoE L2 client */
+ BUG_ON(fp->max_cos != 1);
+
+ bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, &fp->cid, 1,
+ BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
+ bnx2x_sp_mapping(bp, q_rdata), q_type);
+
+ DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d "
+ "igu_sb %d\n",
+ fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
+ fp->igu_sb_id);
}
#endif
+static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
+ struct bnx2x_fp_txdata *txdata)
+{
+ int cnt = 1000;
+
+ while (bnx2x_has_tx_work_unload(txdata)) {
+ if (!cnt) {
+ BNX2X_ERR("timeout waiting for queue[%d]: "
+ "txdata->tx_pkt_prod(%d) != txdata->tx_pkt_cons(%d)\n",
+ txdata->txq_index, txdata->tx_pkt_prod,
+ txdata->tx_pkt_cons);
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+ return -EBUSY;
+#else
+ break;
+#endif
+ }
+ cnt--;
+ usleep_range(1000, 1000);
+ }
+
+ return 0;
+}
+
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+
static inline void __storm_memset_struct(struct bnx2x *bp,
u32 addr, size_t size, u32 *data)
{
@@ -1071,42 +1394,78 @@ static inline void __storm_memset_struct(struct bnx2x *bp,
REG_WR(bp, addr + (i * 4), data[i]);
}
-static inline void storm_memset_mac_filters(struct bnx2x *bp,
- struct tstorm_eth_mac_filter_config *mac_filters,
- u16 abs_fid)
+static inline void storm_memset_func_cfg(struct bnx2x *bp,
+ struct tstorm_eth_function_common_config *tcfg,
+ u16 abs_fid)
{
- size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+ size_t size = sizeof(struct tstorm_eth_function_common_config);
u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_MAC_FILTER_CONFIG_OFFSET(abs_fid);
+ TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
- __storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+ __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
}
static inline void storm_memset_cmng(struct bnx2x *bp,
struct cmng_struct_per_port *cmng,
u8 port)
{
- size_t size =
- sizeof(struct rate_shaping_vars_per_port) +
- sizeof(struct fairness_vars_per_port) +
- sizeof(struct safc_struct_per_port) +
- sizeof(struct pfc_struct_per_port);
+ size_t size = sizeof(struct cmng_struct_per_port);
u32 addr = BAR_XSTRORM_INTMEM +
XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
__storm_memset_struct(bp, addr, size, (u32 *)cmng);
+}
- addr += size + 4 /* SKIP DCB+LLFC */;
- size = sizeof(struct cmng_struct_per_port) -
- size /* written */ - 4 /*skipped*/;
+/**
+ * bnx2x_wait_sp_comp - wait for the outstanding SP commands.
+ *
+ * @bp: driver handle
+ * @mask: bits that need to be cleared
+ */
+static inline bool bnx2x_wait_sp_comp(struct bnx2x *bp, unsigned long mask)
+{
+ int tout = 5000; /* Wait for 5 secs tops */
+
+ while (tout--) {
+ smp_mb();
+ netif_addr_lock_bh(bp->dev);
+ if (!(bp->sp_state & mask)) {
+ netif_addr_unlock_bh(bp->dev);
+ return true;
+ }
+ netif_addr_unlock_bh(bp->dev);
+
+ usleep_range(1000, 1000);
+ }
+
+ smp_mb();
- __storm_memset_struct(bp, addr, size,
- (u32 *)(cmng->traffic_type_to_priority_cos));
+ netif_addr_lock_bh(bp->dev);
+ if (bp->sp_state & mask) {
+ BNX2X_ERR("Filtering completion timed out. sp_state 0x%lx, "
+ "mask 0x%lx\n", bp->sp_state, mask);
+ netif_addr_unlock_bh(bp->dev);
+ return false;
+ }
+ netif_addr_unlock_bh(bp->dev);
+
+ return true;
}
-/* HW Lock for shared dual port PHYs */
+/**
+ * bnx2x_set_ctx_validation - set CDU context validation values
+ *
+ * @bp: driver handle
+ * @cxt: context of the connection on the host memory
+ * @cid: SW CID of the connection to be configured
+ */
+void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
+ u32 cid);
+
+void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
+ u8 sb_index, u8 disable, u16 usec);
void bnx2x_acquire_phy_lock(struct bnx2x *bp);
void bnx2x_release_phy_lock(struct bnx2x *bp);
diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c
index 410a49e571ac..a4ea35f6a456 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/bnx2x/bnx2x_dcb.c
@@ -19,20 +19,18 @@
#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/errno.h>
-#ifdef BCM_DCBNL
-#include <linux/dcbnl.h>
-#endif
+#include <linux/rtnetlink.h>
+#include <net/dcbnl.h>
#include "bnx2x.h"
#include "bnx2x_cmn.h"
#include "bnx2x_dcb.h"
-
/* forward declarations of dcbx related functions */
-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
+static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
+static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
u32 *set_configuration_ets_pg,
u32 *pri_pg_tbl);
@@ -47,34 +45,56 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
struct cos_help_data *cos_data,
u32 *pg_pri_orginal_spread,
struct dcbx_ets_feature *ets);
-static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp);
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
+ struct bnx2x_func_tx_start_params*);
+
+/* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
+static void bnx2x_read_data(struct bnx2x *bp, u32 *buff,
+ u32 addr, u32 len)
+{
+ int i;
+ for (i = 0; i < len; i += 4, buff++)
+ *buff = REG_RD(bp, addr + i);
+}
+static void bnx2x_write_data(struct bnx2x *bp, u32 *buff,
+ u32 addr, u32 len)
+{
+ int i;
+ for (i = 0; i < len; i += 4, buff++)
+ REG_WR(bp, addr + i, *buff);
+}
static void bnx2x_pfc_set(struct bnx2x *bp)
{
struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
u32 pri_bit, val = 0;
- u8 pri;
+ int i;
- /* Tx COS configuration */
- if (bp->dcbx_port_params.ets.cos_params[0].pauseable)
- pfc_params.rx_cos0_priority_mask =
- bp->dcbx_port_params.ets.cos_params[0].pri_bitmask;
- if (bp->dcbx_port_params.ets.cos_params[1].pauseable)
- pfc_params.rx_cos1_priority_mask =
- bp->dcbx_port_params.ets.cos_params[1].pri_bitmask;
+ pfc_params.num_of_rx_cos_priority_mask =
+ bp->dcbx_port_params.ets.num_of_cos;
+ /* Tx COS configuration */
+ for (i = 0; i < bp->dcbx_port_params.ets.num_of_cos; i++)
+ /*
+ * We configure only the pauseable bits (non pauseable aren't
+ * configured at all) it's done to avoid false pauses from
+ * network
+ */
+ pfc_params.rx_cos_priority_mask[i] =
+ bp->dcbx_port_params.ets.cos_params[i].pri_bitmask
+ & DCBX_PFC_PRI_PAUSE_MASK(bp);
- /**
+ /*
* Rx COS configuration
* Changing PFC RX configuration .
* In RX COS0 will always be configured to lossy and COS1 to lossless
*/
- for (pri = 0 ; pri < MAX_PFC_PRIORITIES ; pri++) {
- pri_bit = 1 << pri;
+ for (i = 0 ; i < MAX_PFC_PRIORITIES ; i++) {
+ pri_bit = 1 << i;
if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
- val |= 1 << (pri * 4);
+ val |= 1 << (i * 4);
}
pfc_params.pkt_priority_to_cos = val;
@@ -200,7 +220,11 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
- if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) {
+ if (GET_FLAGS(error, DCBX_LOCAL_APP_MISMATCH))
+ DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_MISMATCH\n");
+
+ if (app->enabled &&
+ !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR | DCBX_LOCAL_APP_MISMATCH)) {
bp->dcbx_port_params.app.enabled = true;
@@ -253,12 +277,11 @@ static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
/* Clean up old settings of ets on COS */
- for (i = 0; i < E2_NUM_OF_COS ; i++) {
-
+ for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params) ; i++) {
cos_params[i].pauseable = false;
- cos_params[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
+ cos_params[i].strict = BNX2X_DCBX_STRICT_INVALID;
cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
- cos_params[i].pri_bitmask = DCBX_PFC_PRI_GET_NON_PAUSE(bp, 0);
+ cos_params[i].pri_bitmask = 0;
}
if (bp->dcbx_port_params.app.enabled &&
@@ -296,7 +319,7 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
if (bp->dcbx_port_params.app.enabled &&
- !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) &&
+ !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH) &&
pfc->enabled) {
bp->dcbx_port_params.pfc.enabled = true;
bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
@@ -308,6 +331,32 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
}
}
+/* maps unmapped priorities to to the same COS as L2 */
+static void bnx2x_dcbx_map_nw(struct bnx2x *bp)
+{
+ int i;
+ u32 unmapped = (1 << MAX_PFC_PRIORITIES) - 1; /* all ones */
+ u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+ u32 nw_prio = 1 << ttp[LLFC_TRAFFIC_TYPE_NW];
+ struct bnx2x_dcbx_cos_params *cos_params =
+ bp->dcbx_port_params.ets.cos_params;
+
+ /* get unmapped priorities by clearing mapped bits */
+ for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
+ unmapped &= ~(1 << ttp[i]);
+
+ /* find cos for nw prio and extend it with unmapped */
+ for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params); i++) {
+ 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_params[i].pri_bitmask |= unmapped;
+ break;
+ }
+ }
+}
+
static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
struct dcbx_features *features,
u32 error)
@@ -317,6 +366,8 @@ static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
+
+ bnx2x_dcbx_map_nw(bp);
}
#define DCBX_LOCAL_MIB_MAX_TRY_READ (100)
@@ -325,8 +376,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
u32 offset,
int read_mib_type)
{
- int max_try_read = 0, i;
- u32 *buff, mib_size, prefix_seq_num, suffix_seq_num;
+ int max_try_read = 0;
+ u32 mib_size, prefix_seq_num, suffix_seq_num;
struct lldp_remote_mib *remote_mib ;
struct lldp_local_mib *local_mib;
@@ -345,9 +396,7 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
offset += BP_PORT(bp) * mib_size;
do {
- buff = base_mib_addr;
- for (i = 0; i < mib_size; i += 4, buff++)
- *buff = REG_RD(bp, offset + i);
+ bnx2x_read_data(bp, base_mib_addr, offset, mib_size);
max_try_read++;
@@ -378,60 +427,50 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
{
- if (CHIP_IS_E2(bp)) {
- if (BP_PORT(bp)) {
- BNX2X_ERR("4 port mode is not supported");
- return;
- }
+ if (bp->dcbx_port_params.pfc.enabled &&
+ !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+ /*
+ * 1. Fills up common PFC structures if required
+ * 2. Configure NIG, MAC and BRB via the elink
+ */
+ bnx2x_pfc_set(bp);
+ else
+ bnx2x_pfc_clear(bp);
+}
- if (bp->dcbx_port_params.pfc.enabled)
+static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+{
+ struct bnx2x_func_state_params func_params = {0};
- /* 1. Fills up common PFC structures if required.*/
- /* 2. Configure NIG, MAC and BRB via the elink:
- * elink must first check if BMAC is not in reset
- * and only then configures the BMAC
- * Or, configure EMAC.
- */
- bnx2x_pfc_set(bp);
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_TX_STOP;
- else
- bnx2x_pfc_clear(bp);
- }
+ DP(NETIF_MSG_LINK, "STOP TRAFFIC\n");
+ return bnx2x_func_state_change(bp, &func_params);
}
-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
{
- DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n");
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
- 0 /* connectionless */,
- 0 /* dataHi is zero */,
- 0 /* dataLo is zero */,
- 1 /* common */);
-}
+ struct bnx2x_func_state_params func_params = {0};
+ struct bnx2x_func_tx_start_params *tx_params =
+ &func_params.params.tx_start;
-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
-{
- bnx2x_pfc_fw_struct_e2(bp);
- DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
- 0, /* connectionless */
- U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
- U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
- 1 /* commmon */);
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_TX_START;
+
+ bnx2x_dcbx_fw_struct(bp, tx_params);
+
+ DP(NETIF_MSG_LINK, "START TRAFFIC\n");
+ return bnx2x_func_state_change(bp, &func_params);
}
-static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
+static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
{
struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
- u8 status = 0;
-
- bnx2x_ets_disabled(&bp->link_params);
-
- if (!ets->enabled)
- return;
+ int rc = 0;
- if ((ets->num_of_cos == 0) || (ets->num_of_cos > E2_NUM_OF_COS)) {
- BNX2X_ERR("illegal num of cos= %x", ets->num_of_cos);
+ if (ets->num_of_cos == 0 || ets->num_of_cos > DCBX_COS_MAX_NUM_E2) {
+ BNX2X_ERR("Illegal number of COSes %d\n", ets->num_of_cos);
return;
}
@@ -440,9 +479,9 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
return;
/* sanity */
- if (((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[0].strict) &&
+ if (((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[0].strict) &&
(DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
- ((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[1].strict) &&
+ ((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[1].strict) &&
(DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
BNX2X_ERR("all COS should have at least bw_limit or strict"
"ets->cos_params[0].strict= %x"
@@ -474,17 +513,71 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
} else {
- if (ets->cos_params[0].strict == BNX2X_DCBX_COS_HIGH_STRICT)
- status = bnx2x_ets_strict(&bp->link_params, 0);
+ if (ets->cos_params[0].strict == BNX2X_DCBX_STRICT_COS_HIGHEST)
+ rc = bnx2x_ets_strict(&bp->link_params, 0);
else if (ets->cos_params[1].strict
- == BNX2X_DCBX_COS_HIGH_STRICT)
- status = bnx2x_ets_strict(&bp->link_params, 1);
-
- if (status)
+ == BNX2X_DCBX_STRICT_COS_HIGHEST)
+ rc = bnx2x_ets_strict(&bp->link_params, 1);
+ if (rc)
BNX2X_ERR("update_ets_params failed\n");
}
}
+/*
+ * In E3B0 the configuration may have more than 2 COS.
+ */
+void bnx2x_dcbx_update_ets_config(struct bnx2x *bp)
+{
+ struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
+ struct bnx2x_ets_params ets_params = { 0 };
+ u8 i;
+
+ ets_params.num_of_cos = ets->num_of_cos;
+
+ for (i = 0; i < ets->num_of_cos; i++) {
+ /* COS is SP */
+ if (ets->cos_params[i].strict != BNX2X_DCBX_STRICT_INVALID) {
+ if (ets->cos_params[i].bw_tbl != DCBX_INVALID_COS_BW) {
+ BNX2X_ERR("COS can't be not BW and not SP\n");
+ return;
+ }
+
+ ets_params.cos[i].state = bnx2x_cos_state_strict;
+ ets_params.cos[i].params.sp_params.pri =
+ ets->cos_params[i].strict;
+ } else { /* COS is BW */
+ if (ets->cos_params[i].bw_tbl == DCBX_INVALID_COS_BW) {
+ BNX2X_ERR("COS can't be not BW and not SP\n");
+ return;
+ }
+ ets_params.cos[i].state = bnx2x_cos_state_bw;
+ ets_params.cos[i].params.bw_params.bw =
+ (u8)ets->cos_params[i].bw_tbl;
+ }
+ }
+
+ /* Configure the ETS in HW */
+ if (bnx2x_ets_e3b0_config(&bp->link_params, &bp->link_vars,
+ &ets_params)) {
+ BNX2X_ERR("bnx2x_ets_e3b0_config failed\n");
+ bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
+ }
+}
+
+static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
+{
+ bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
+
+ if (!bp->dcbx_port_params.ets.enabled ||
+ (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+ return;
+
+ if (CHIP_IS_E3B0(bp))
+ bnx2x_dcbx_update_ets_config(bp);
+ else
+ bnx2x_dcbx_2cos_limit_update_ets_config(bp);
+}
+
#ifdef BCM_DCBNL
static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x *bp)
{
@@ -527,6 +620,7 @@ static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
return -EINVAL;
}
+
rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
DCBX_READ_LOCAL_MIB);
@@ -563,15 +657,6 @@ u8 bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry *ent)
DCB_APP_IDTYPE_ETHTYPE;
}
-static inline
-void bnx2x_dcbx_invalidate_local_apps(struct bnx2x *bp)
-{
- int i;
- for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
- bp->dcbx_local_feat.app.app_pri_tbl[i].appBitfield &=
- ~DCBX_APP_ENTRY_VALID;
-}
-
int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
{
int i, err = 0;
@@ -597,32 +682,50 @@ int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
}
#endif
-void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
+static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
{
- switch (state) {
- case BNX2X_DCBX_STATE_NEG_RECEIVED:
-#ifdef BCM_CNIC
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
- struct cnic_ops *c_ops;
- struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
- bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
- cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
- cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;
-
- rcu_read_lock();
- c_ops = rcu_dereference(bp->cnic_ops);
- if (c_ops) {
- bnx2x_cnic_notify(bp, CNIC_CTL_STOP_ISCSI_CMD);
- rcu_read_unlock();
- return;
+ if (SHMEM2_HAS(bp, drv_flags)) {
+ u32 drv_flags;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+ drv_flags = SHMEM2_RD(bp, drv_flags);
+
+ if (set)
+ SET_FLAGS(drv_flags, flags);
+ else
+ RESET_FLAGS(drv_flags, flags);
+
+ SHMEM2_WR(bp, drv_flags, drv_flags);
+ DP(NETIF_MSG_HW, "drv_flags 0x%08x\n", drv_flags);
+ bnx2x_release_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+ }
+}
+
+static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp)
+{
+ u8 prio, cos;
+ for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++) {
+ for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
+ if (bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask
+ & (1 << prio)) {
+ bp->prio_to_cos[prio] = cos;
+ DP(NETIF_MSG_LINK,
+ "tx_mapping %d --> %d\n", prio, cos);
}
- rcu_read_unlock();
}
+ }
- /* fall through if no CNIC initialized */
- case BNX2X_DCBX_STATE_ISCSI_STOPPED:
-#endif
+ /* setup tc must be called under rtnl lock, but we can't take it here
+ * as we are handling an attetntion on a work queue which must be
+ * flushed at some rtnl-locked contexts (e.g. if down)
+ */
+ if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
+ schedule_delayed_work(&bp->sp_rtnl_task, 0);
+}
+void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
+{
+ switch (state) {
+ case BNX2X_DCBX_STATE_NEG_RECEIVED:
{
DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
#ifdef BCM_DCBNL
@@ -646,102 +749,53 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
bp->dcbx_error);
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
-#ifdef BCM_DCBNL
- /**
- * Add new app tlvs to dcbnl
- */
- bnx2x_dcbnl_update_applist(bp, false);
-#endif
- bnx2x_dcbx_stop_hw_tx(bp);
- return;
- }
- /* fall through */
+ /* mark DCBX result for PMF migration */
+ bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 1);
#ifdef BCM_DCBNL
/**
- * Invalidate the local app tlvs if they are not added
- * to the dcbnl app list to avoid deleting them from
- * the list later on
+ * Add new app tlvs to dcbnl
*/
- bnx2x_dcbx_invalidate_local_apps(bp);
+ bnx2x_dcbnl_update_applist(bp, false);
#endif
+ bnx2x_dcbx_stop_hw_tx(bp);
+
+ /* reconfigure the netdevice with the results of the new
+ * dcbx negotiation.
+ */
+ bnx2x_dcbx_update_tc_mapping(bp);
+
+ return;
}
case BNX2X_DCBX_STATE_TX_PAUSED:
DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
bnx2x_pfc_set_pfc(bp);
bnx2x_dcbx_update_ets_params(bp);
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
- bnx2x_dcbx_resume_hw_tx(bp);
- return;
- }
- /* fall through */
+ bnx2x_dcbx_resume_hw_tx(bp);
+ return;
case BNX2X_DCBX_STATE_TX_RELEASED:
DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD)
- bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
-
+ bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
+#ifdef BCM_DCBNL
+ /*
+ * Send a notification for the new negotiated parameters
+ */
+ dcbnl_cee_notify(bp->dev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
+#endif
return;
default:
BNX2X_ERR("Unknown DCBX_STATE\n");
}
}
-
-#define LLDP_STATS_OFFSET(bp) (BP_PORT(bp)*\
- sizeof(struct lldp_dcbx_stat))
-
-/* calculate struct offset in array according to chip information */
-#define LLDP_PARAMS_OFFSET(bp) (BP_PORT(bp)*sizeof(struct lldp_params))
-
#define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \
BP_PORT(bp)*sizeof(struct lldp_admin_mib))
-static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
- u32 dcbx_lldp_params_offset)
-{
- struct lldp_params lldp_params = {0};
- u32 i = 0, *buff = NULL;
- u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
-
- DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
-
- if ((bp->lldp_config_params.overwrite_settings ==
- BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
- /* Read the data first */
- buff = (u32 *)&lldp_params;
- for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
- *buff = REG_RD(bp, (offset + i));
-
- lldp_params.msg_tx_hold =
- (u8)bp->lldp_config_params.msg_tx_hold;
- lldp_params.msg_fast_tx_interval =
- (u8)bp->lldp_config_params.msg_fast_tx;
- lldp_params.tx_crd_max =
- (u8)bp->lldp_config_params.tx_credit_max;
- lldp_params.msg_tx_interval =
- (u8)bp->lldp_config_params.msg_tx_interval;
- lldp_params.tx_fast =
- (u8)bp->lldp_config_params.tx_fast;
-
- /* Write the data.*/
- buff = (u32 *)&lldp_params;
- for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
- REG_WR(bp, (offset + i) , *buff);
-
-
- } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
- bp->lldp_config_params.overwrite_settings)
- bp->lldp_config_params.overwrite_settings =
- BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
-}
-
static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
u32 dcbx_lldp_params_offset)
{
struct lldp_admin_mib admin_mib;
u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
- u32 *buff;
u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
/*shortcuts*/
@@ -749,18 +803,18 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
- buff = (u32 *)&admin_mib;
+
/* Read the data first */
- for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
- *buff = REG_RD(bp, (offset + i));
+ bnx2x_read_data(bp, (u32 *)&admin_mib, offset,
+ sizeof(struct lldp_admin_mib));
if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
else
RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
- if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
- dp->overwrite_settings)) {
+ if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) {
+
RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
admin_mib.ver_cfg_flags |=
(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
@@ -856,19 +910,17 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
af->app.default_pri = (u8)dp->admin_default_priority;
- } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
- dp->overwrite_settings)
- dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
+ }
/* Write the data. */
- buff = (u32 *)&admin_mib;
- for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
- REG_WR(bp, (offset + i), *buff);
+ bnx2x_write_data(bp, (u32 *)&admin_mib, offset,
+ sizeof(struct lldp_admin_mib));
+
}
void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
{
- if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
bp->dcb_state = dcb_on;
bp->dcbx_enabled = dcbx_enabled;
} else {
@@ -966,7 +1018,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
bp->dcb_state, bp->port.pmf);
- if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
+ if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
dcbx_lldp_params_offset =
SHMEM2_RD(bp, dcbx_lldp_params_offset);
@@ -974,56 +1026,21 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
dcbx_lldp_params_offset);
- if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
- bnx2x_dcbx_lldp_updated_params(bp,
- dcbx_lldp_params_offset);
+ bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0);
+ if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
bnx2x_dcbx_admin_mib_updated_params(bp,
dcbx_lldp_params_offset);
- /* set default configuration BC has */
- bnx2x_dcbx_set_params(bp,
- BNX2X_DCBX_STATE_NEG_RECEIVED);
-
+ /* Let HW start negotiation */
bnx2x_fw_command(bp,
DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
}
}
}
-
-void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp)
-{
- struct priority_cos pricos[MAX_PFC_TRAFFIC_TYPES];
- u32 i = 0, addr;
- memset(pricos, 0, sizeof(pricos));
- /* Default initialization */
- for (i = 0; i < MAX_PFC_TRAFFIC_TYPES; i++)
- pricos[i].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
-
- /* Store per port struct to internal memory */
- addr = BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
- offsetof(struct cmng_struct_per_port,
- traffic_type_to_priority_cos);
- __storm_memset_struct(bp, addr, sizeof(pricos), (u32 *)pricos);
-
-
- /* LLFC disabled.*/
- REG_WR8(bp , BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
- offsetof(struct cmng_struct_per_port, llfc_mode),
- LLFC_MODE_NONE);
-
- /* DCBX disabled.*/
- REG_WR8(bp , BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
- offsetof(struct cmng_struct_per_port, dcb_enabled),
- DCB_DISABLED);
-}
-
static void
bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
- struct flow_control_configuration *pfc_fw_cfg)
+ struct bnx2x_func_tx_start_params *pfc_fw_cfg)
{
u8 pri = 0;
u8 cos = 0;
@@ -1171,7 +1188,7 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
/* If we join a group and one is strict
* than the bw rulls */
cos_data->data[entry].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
if ((0 == cos_data->data[0].pri_join_mask) &&
(0 == cos_data->data[1].pri_join_mask))
@@ -1183,7 +1200,7 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
#define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1))))
#endif
-static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
+static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x *bp,
struct pg_help_data *pg_help_data,
struct cos_help_data *cos_data,
u32 pri_join_mask,
@@ -1263,14 +1280,16 @@ static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
cos_data->data[0].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
cos_data->data[1].strict =
- BNX2X_DCBX_COS_LOW_STRICT;
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+ BNX2X_DCBX_STRICT_COS_HIGHEST);
} else {
cos_data->data[0].strict =
- BNX2X_DCBX_COS_LOW_STRICT;
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+ BNX2X_DCBX_STRICT_COS_HIGHEST);
cos_data->data[1].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
/* Pauseable */
cos_data->data[0].pausable = true;
@@ -1306,13 +1325,16 @@ static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
* and that with the highest priority
* gets the highest strict priority in the arbiter.
*/
- cos_data->data[0].strict = BNX2X_DCBX_COS_LOW_STRICT;
- cos_data->data[1].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+ cos_data->data[0].strict =
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+ BNX2X_DCBX_STRICT_COS_HIGHEST);
+ cos_data->data[1].strict =
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
}
}
-static void bnx2x_dcbx_two_pg_to_cos_params(
+static void bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
struct bnx2x *bp,
struct pg_help_data *pg_help_data,
struct dcbx_ets_feature *ets,
@@ -1322,7 +1344,7 @@ static void bnx2x_dcbx_two_pg_to_cos_params(
u8 num_of_dif_pri)
{
u8 i = 0;
- u8 pg[E2_NUM_OF_COS] = {0};
+ u8 pg[DCBX_COS_MAX_NUM_E2] = { 0 };
/* If there are both pauseable and non-pauseable priorities,
* the pauseable priorities go to the first queue and
@@ -1378,16 +1400,68 @@ static void bnx2x_dcbx_two_pg_to_cos_params(
}
/* There can be only one strict pg */
- for (i = 0 ; i < E2_NUM_OF_COS; i++) {
+ for (i = 0 ; i < ARRAY_SIZE(pg); i++) {
if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
cos_data->data[i].cos_bw =
DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
else
- cos_data->data[i].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+ cos_data->data[i].strict =
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
}
-static void bnx2x_dcbx_three_pg_to_cos_params(
+static int bnx2x_dcbx_join_pgs(
+ struct bnx2x *bp,
+ struct dcbx_ets_feature *ets,
+ struct pg_help_data *pg_help_data,
+ u8 required_num_of_pg)
+{
+ u8 entry_joined = pg_help_data->num_of_pg - 1;
+ u8 entry_removed = entry_joined + 1;
+ u8 pg_joined = 0;
+
+ if (required_num_of_pg == 0 || ARRAY_SIZE(pg_help_data->data)
+ <= pg_help_data->num_of_pg) {
+
+ BNX2X_ERR("required_num_of_pg can't be zero\n");
+ return -EINVAL;
+ }
+
+ while (required_num_of_pg < pg_help_data->num_of_pg) {
+ entry_joined = pg_help_data->num_of_pg - 2;
+ entry_removed = entry_joined + 1;
+ /* protect index */
+ entry_removed %= ARRAY_SIZE(pg_help_data->data);
+
+ pg_help_data->data[entry_joined].pg_priority |=
+ pg_help_data->data[entry_removed].pg_priority;
+
+ pg_help_data->data[entry_joined].num_of_dif_pri +=
+ pg_help_data->data[entry_removed].num_of_dif_pri;
+
+ if (pg_help_data->data[entry_joined].pg == DCBX_STRICT_PRI_PG ||
+ pg_help_data->data[entry_removed].pg == DCBX_STRICT_PRI_PG)
+ /* Entries joined strict priority rules */
+ pg_help_data->data[entry_joined].pg =
+ DCBX_STRICT_PRI_PG;
+ else {
+ /* Entries can be joined join BW */
+ pg_joined = DCBX_PG_BW_GET(ets->pg_bw_tbl,
+ pg_help_data->data[entry_joined].pg) +
+ DCBX_PG_BW_GET(ets->pg_bw_tbl,
+ pg_help_data->data[entry_removed].pg);
+
+ DCBX_PG_BW_SET(ets->pg_bw_tbl,
+ pg_help_data->data[entry_joined].pg, pg_joined);
+ }
+ /* Joined the entries */
+ pg_help_data->num_of_pg--;
+ }
+
+ return 0;
+}
+
+static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
struct bnx2x *bp,
struct pg_help_data *pg_help_data,
struct dcbx_ets_feature *ets,
@@ -1459,102 +1533,271 @@ static void bnx2x_dcbx_three_pg_to_cos_params(
/* If we join a group and one is strict
* than the bw rulls */
cos_data->data[1].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
}
}
}
-static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
+static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp,
struct pg_help_data *help_data,
struct dcbx_ets_feature *ets,
- u32 *pg_pri_orginal_spread)
+ struct cos_help_data *cos_data,
+ u32 *pg_pri_orginal_spread,
+ u32 pri_join_mask,
+ u8 num_of_dif_pri)
{
- struct cos_help_data cos_data ;
- u8 i = 0;
- u32 pri_join_mask = 0;
- u8 num_of_dif_pri = 0;
-
- memset(&cos_data, 0, sizeof(cos_data));
- /* Validate the pg value */
- for (i = 0; i < help_data->num_of_pg ; i++) {
- if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
- DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
- BNX2X_ERR("Invalid pg[%d] data %x\n", i,
- help_data->data[i].pg);
- pri_join_mask |= help_data->data[i].pg_priority;
- num_of_dif_pri += help_data->data[i].num_of_dif_pri;
- }
- /* default settings */
- cos_data.num_of_cos = 2;
- for (i = 0; i < E2_NUM_OF_COS ; i++) {
- cos_data.data[i].pri_join_mask = pri_join_mask;
- cos_data.data[i].pausable = false;
- cos_data.data[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
- cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
- }
+ /* default E2 settings */
+ cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2;
switch (help_data->num_of_pg) {
case 1:
-
- bxn2x_dcbx_single_pg_to_cos_params(
+ bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(
bp,
help_data,
- &cos_data,
+ cos_data,
pri_join_mask,
num_of_dif_pri);
break;
case 2:
- bnx2x_dcbx_two_pg_to_cos_params(
+ bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
bp,
help_data,
ets,
- &cos_data,
+ cos_data,
pg_pri_orginal_spread,
pri_join_mask,
num_of_dif_pri);
break;
case 3:
- bnx2x_dcbx_three_pg_to_cos_params(
+ bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
bp,
help_data,
ets,
- &cos_data,
+ cos_data,
pg_pri_orginal_spread,
pri_join_mask,
num_of_dif_pri);
-
break;
default:
BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
bnx2x_dcbx_ets_disabled_entry_data(bp,
- &cos_data, pri_join_mask);
+ cos_data, pri_join_mask);
+ }
+}
+
+static int bnx2x_dcbx_spread_strict_pri(struct bnx2x *bp,
+ struct cos_help_data *cos_data,
+ u8 entry,
+ u8 num_spread_of_entries,
+ u8 strict_app_pris)
+{
+ u8 strict_pri = BNX2X_DCBX_STRICT_COS_HIGHEST;
+ u8 num_of_app_pri = MAX_PFC_PRIORITIES;
+ u8 app_pri_bit = 0;
+
+ while (num_spread_of_entries && num_of_app_pri > 0) {
+ app_pri_bit = 1 << (num_of_app_pri - 1);
+ if (app_pri_bit & strict_app_pris) {
+ struct cos_entry_help_data *data = &cos_data->
+ data[entry];
+ num_spread_of_entries--;
+ if (num_spread_of_entries == 0) {
+ /* last entry needed put all the entries left */
+ data->cos_bw = DCBX_INVALID_COS_BW;
+ data->strict = strict_pri;
+ data->pri_join_mask = strict_app_pris;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+ } else {
+ strict_app_pris &= ~app_pri_bit;
+
+ data->cos_bw = DCBX_INVALID_COS_BW;
+ data->strict = strict_pri;
+ data->pri_join_mask = app_pri_bit;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+ }
+
+ strict_pri =
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(strict_pri);
+ entry++;
+ }
+
+ num_of_app_pri--;
+ }
+
+ if (num_spread_of_entries)
+ return -EINVAL;
+
+ return 0;
+}
+
+static u8 bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x *bp,
+ struct cos_help_data *cos_data,
+ u8 entry,
+ u8 num_spread_of_entries,
+ u8 strict_app_pris)
+{
+
+ if (bnx2x_dcbx_spread_strict_pri(bp, cos_data, entry,
+ num_spread_of_entries,
+ strict_app_pris)) {
+ struct cos_entry_help_data *data = &cos_data->
+ data[entry];
+ /* Fill BW entry */
+ data->cos_bw = DCBX_INVALID_COS_BW;
+ data->strict = BNX2X_DCBX_STRICT_COS_HIGHEST;
+ data->pri_join_mask = strict_app_pris;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+ return 1;
+ }
+
+ return num_spread_of_entries;
+}
+
+static void bnx2x_dcbx_cee_fill_cos_params(struct bnx2x *bp,
+ struct pg_help_data *help_data,
+ struct dcbx_ets_feature *ets,
+ struct cos_help_data *cos_data,
+ u32 pri_join_mask)
+
+{
+ u8 need_num_of_entries = 0;
+ u8 i = 0;
+ u8 entry = 0;
+
+ /*
+ * if the number of requested PG-s in CEE is greater than 3
+ * then the results are not determined since this is a violation
+ * of the standard.
+ */
+ if (help_data->num_of_pg > DCBX_COS_MAX_NUM_E3B0) {
+ if (bnx2x_dcbx_join_pgs(bp, ets, help_data,
+ DCBX_COS_MAX_NUM_E3B0)) {
+ BNX2X_ERR("Unable to reduce the number of PGs -"
+ "we will disables ETS\n");
+ bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data,
+ pri_join_mask);
+ return;
+ }
+ }
+
+ for (i = 0 ; i < help_data->num_of_pg; i++) {
+ struct pg_entry_help_data *pg = &help_data->data[i];
+ if (pg->pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
+ struct cos_entry_help_data *data = &cos_data->
+ data[entry];
+ /* Fill BW entry */
+ data->cos_bw = DCBX_PG_BW_GET(ets->pg_bw_tbl, pg->pg);
+ data->strict = BNX2X_DCBX_STRICT_INVALID;
+ data->pri_join_mask = pg->pg_priority;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+
+ entry++;
+ } else {
+ need_num_of_entries = min_t(u8,
+ (u8)pg->num_of_dif_pri,
+ (u8)DCBX_COS_MAX_NUM_E3B0 -
+ help_data->num_of_pg + 1);
+ /*
+ * If there are still VOQ-s which have no associated PG,
+ * then associate these VOQ-s to PG15. These PG-s will
+ * be used for SP between priorities on PG15.
+ */
+ entry += bnx2x_dcbx_cee_fill_strict_pri(bp, cos_data,
+ entry, need_num_of_entries, pg->pg_priority);
+ }
}
+ /* the entry will represent the number of COSes used */
+ cos_data->num_of_cos = entry;
+}
+static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
+ struct pg_help_data *help_data,
+ struct dcbx_ets_feature *ets,
+ u32 *pg_pri_orginal_spread)
+{
+ struct cos_help_data cos_data;
+ u8 i = 0;
+ u32 pri_join_mask = 0;
+ u8 num_of_dif_pri = 0;
+
+ memset(&cos_data, 0, sizeof(cos_data));
+
+ /* Validate the pg value */
+ for (i = 0; i < help_data->num_of_pg ; i++) {
+ if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
+ DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
+ BNX2X_ERR("Invalid pg[%d] data %x\n", i,
+ help_data->data[i].pg);
+ pri_join_mask |= help_data->data[i].pg_priority;
+ num_of_dif_pri += help_data->data[i].num_of_dif_pri;
+ }
+
+ /* defaults */
+ cos_data.num_of_cos = 1;
+ for (i = 0; i < ARRAY_SIZE(cos_data.data); i++) {
+ cos_data.data[i].pri_join_mask = 0;
+ cos_data.data[i].pausable = false;
+ cos_data.data[i].strict = BNX2X_DCBX_STRICT_INVALID;
+ cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
+ }
+
+ if (CHIP_IS_E3B0(bp))
+ bnx2x_dcbx_cee_fill_cos_params(bp, help_data, ets,
+ &cos_data, pri_join_mask);
+ else /* E2 + E3A0 */
+ bnx2x_dcbx_2cos_limit_cee_fill_cos_params(bp,
+ help_data, ets,
+ &cos_data,
+ pg_pri_orginal_spread,
+ pri_join_mask,
+ num_of_dif_pri);
+
for (i = 0; i < cos_data.num_of_cos ; i++) {
- struct bnx2x_dcbx_cos_params *params =
+ struct bnx2x_dcbx_cos_params *p =
&bp->dcbx_port_params.ets.cos_params[i];
- params->pauseable = cos_data.data[i].pausable;
- params->strict = cos_data.data[i].strict;
- params->bw_tbl = cos_data.data[i].cos_bw;
- if (params->pauseable) {
- params->pri_bitmask =
- DCBX_PFC_PRI_GET_PAUSE(bp,
- cos_data.data[i].pri_join_mask);
+ p->strict = cos_data.data[i].strict;
+ p->bw_tbl = cos_data.data[i].cos_bw;
+ p->pri_bitmask = cos_data.data[i].pri_join_mask;
+ p->pauseable = cos_data.data[i].pausable;
+
+ /* sanity */
+ if (p->bw_tbl != DCBX_INVALID_COS_BW ||
+ p->strict != BNX2X_DCBX_STRICT_INVALID) {
+ if (p->pri_bitmask == 0)
+ BNX2X_ERR("Invalid pri_bitmask for %d\n", i);
+
+ if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp)) {
+
+ if (p->pauseable &&
+ DCBX_PFC_PRI_GET_NON_PAUSE(bp,
+ p->pri_bitmask) != 0)
+ BNX2X_ERR("Inconsistent config for "
+ "pausable COS %d\n", i);
+
+ if (!p->pauseable &&
+ DCBX_PFC_PRI_GET_PAUSE(bp,
+ p->pri_bitmask) != 0)
+ BNX2X_ERR("Inconsistent config for "
+ "nonpausable COS %d\n", i);
+ }
+ }
+
+ if (p->pauseable)
DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
i, cos_data.data[i].pri_join_mask);
- } else {
- params->pri_bitmask =
- DCBX_PFC_PRI_GET_NON_PAUSE(bp,
- cos_data.data[i].pri_join_mask);
+ else
DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
"0x%x\n",
i, cos_data.data[i].pri_join_mask);
- }
}
bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
@@ -1574,30 +1817,26 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
}
}
-static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
+ struct bnx2x_func_tx_start_params *pfc_fw_cfg)
{
- struct flow_control_configuration *pfc_fw_cfg = NULL;
u16 pri_bit = 0;
u8 cos = 0, pri = 0;
struct priority_cos *tt2cos;
u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
- pfc_fw_cfg = (struct flow_control_configuration *)
- bnx2x_sp(bp, pfc_config);
- memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration));
+ memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
+
+ /* to disable DCB - the structure must be zeroed */
+ if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)
+ return;
/*shortcut*/
tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
/* Fw version should be incremented each update */
pfc_fw_cfg->dcb_version = ++bp->dcb_version;
- pfc_fw_cfg->dcb_enabled = DCB_ENABLED;
-
- /* Default initialization */
- for (pri = 0; pri < MAX_PFC_TRAFFIC_TYPES ; pri++) {
- tt2cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
- tt2cos[pri].cos = 0;
- }
+ pfc_fw_cfg->dcb_enabled = 1;
/* Fill priority parameters */
for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
@@ -1605,14 +1844,37 @@ static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
pri_bit = 1 << tt2cos[pri].priority;
/* Fill COS parameters based on COS calculated to
- * make it more generally for future use */
+ * make it more general for future use */
for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
if (bp->dcbx_port_params.ets.cos_params[cos].
pri_bitmask & pri_bit)
tt2cos[pri].cos = cos;
}
+
+ /* we never want the FW to add a 0 vlan tag */
+ pfc_fw_cfg->dont_add_pri_0_en = 1;
+
bnx2x_dcbx_print_cos_params(bp, pfc_fw_cfg);
}
+
+void bnx2x_dcbx_pmf_update(struct bnx2x *bp)
+{
+ /* if we need to syncronize DCBX result from prev PMF
+ * read it from shmem and update bp accordingly
+ */
+ if (SHMEM2_HAS(bp, drv_flags) &&
+ GET_FLAGS(SHMEM2_RD(bp, drv_flags), DRV_FLAGS_DCB_CONFIGURED)) {
+ /* Read neg results if dcbx is in the FW */
+ if (bnx2x_dcbx_read_shmem_neg_results(bp))
+ return;
+
+ bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+ bp->dcbx_error);
+ bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+ bp->dcbx_error);
+ }
+}
+
/* DCB netlink */
#ifdef BCM_DCBNL
@@ -1879,10 +2141,12 @@ static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
if (bp->dcb_state) {
switch (tcid) {
case DCB_NUMTCS_ATTR_PG:
- *num = E2_NUM_OF_COS;
+ *num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
+ DCBX_COS_MAX_NUM_E2;
break;
case DCB_NUMTCS_ATTR_PFC:
- *num = E2_NUM_OF_COS;
+ *num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
+ DCBX_COS_MAX_NUM_E2;
break;
default:
rval = -EINVAL;
diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h
index bed369d67e02..2c6a3bca6f28 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.h
+++ b/drivers/net/bnx2x/bnx2x_dcb.h
@@ -27,22 +27,30 @@ struct bnx2x_dcbx_app_params {
u32 traffic_type_priority[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
};
-#define E2_NUM_OF_COS 2
-#define BNX2X_DCBX_COS_NOT_STRICT 0
-#define BNX2X_DCBX_COS_LOW_STRICT 1
-#define BNX2X_DCBX_COS_HIGH_STRICT 2
+#define DCBX_COS_MAX_NUM_E2 DCBX_E2E3_MAX_NUM_COS
+/* bnx2x currently limits numbers of supported COSes to 3 to be extended to 6 */
+#define BNX2X_MAX_COS_SUPPORT 3
+#define DCBX_COS_MAX_NUM_E3B0 BNX2X_MAX_COS_SUPPORT
+#define DCBX_COS_MAX_NUM BNX2X_MAX_COS_SUPPORT
struct bnx2x_dcbx_cos_params {
u32 bw_tbl;
u32 pri_bitmask;
+ /*
+ * strict priority: valid values are 0..5; 0 is highest priority.
+ * There can't be two COSes with the same priority.
+ */
u8 strict;
+#define BNX2X_DCBX_STRICT_INVALID DCBX_COS_MAX_NUM
+#define BNX2X_DCBX_STRICT_COS_HIGHEST 0
+#define BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(sp) ((sp) + 1)
u8 pauseable;
};
struct bnx2x_dcbx_pg_params {
u32 enabled;
u8 num_of_cos; /* valid COS entries */
- struct bnx2x_dcbx_cos_params cos_params[E2_NUM_OF_COS];
+ struct bnx2x_dcbx_cos_params cos_params[DCBX_COS_MAX_NUM];
};
struct bnx2x_dcbx_pfc_params {
@@ -60,6 +68,8 @@ struct bnx2x_dcbx_port_params {
#define BNX2X_DCBX_OVERWRITE_SETTINGS_DISABLE 0
#define BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE 1
#define BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID (BNX2X_DCBX_CONFIG_INV_VALUE)
+#define BNX2X_IS_ETS_ENABLED(bp) ((bp)->dcb_state == BNX2X_DCB_STATE_ON &&\
+ (bp)->dcbx_port_params.ets.enabled)
struct bnx2x_config_lldp_params {
u32 overwrite_settings;
@@ -132,7 +142,7 @@ struct cos_entry_help_data {
};
struct cos_help_data {
- struct cos_entry_help_data data[E2_NUM_OF_COS];
+ struct cos_entry_help_data data[DCBX_COS_MAX_NUM];
u8 num_of_cos;
};
@@ -148,6 +158,8 @@ struct cos_help_data {
((pg_pri) & (DCBX_PFC_PRI_PAUSE_MASK(bp)))
#define DCBX_PFC_PRI_GET_NON_PAUSE(bp, pg_pri) \
(DCBX_PFC_PRI_NON_PAUSE_MASK(bp) & (pg_pri))
+#define DCBX_IS_PFC_PRI_SOME_PAUSE(bp, pg_pri) \
+ (0 != DCBX_PFC_PRI_GET_PAUSE(bp, pg_pri))
#define IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pg_pri) \
(pg_pri == DCBX_PFC_PRI_GET_PAUSE((bp), (pg_pri)))
#define IS_DCBX_PFC_PRI_ONLY_NON_PAUSE(bp, pg_pri)\
@@ -170,22 +182,18 @@ struct pg_help_data {
/* forward DCB/PFC related declarations */
struct bnx2x;
-void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp);
void bnx2x_dcbx_update(struct work_struct *work);
void bnx2x_dcbx_init_params(struct bnx2x *bp);
void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled);
enum {
BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1,
-#ifdef BCM_CNIC
- BNX2X_DCBX_STATE_ISCSI_STOPPED,
-#endif
BNX2X_DCBX_STATE_TX_PAUSED,
BNX2X_DCBX_STATE_TX_RELEASED
};
void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
-
+void bnx2x_dcbx_pmf_update(struct bnx2x *bp);
/* DCB netlink */
#ifdef BCM_DCBNL
extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
diff --git a/drivers/net/bnx2x/bnx2x_dump.h b/drivers/net/bnx2x/bnx2x_dump.h
index fb3ff7c4d7ca..b983825d0ee9 100644
--- a/drivers/net/bnx2x/bnx2x_dump.h
+++ b/drivers/net/bnx2x/bnx2x_dump.h
@@ -25,34 +25,94 @@
/*definitions */
-#define XSTORM_WAITP_ADDR 0x2b8a80
-#define TSTORM_WAITP_ADDR 0x1b8a80
-#define USTORM_WAITP_ADDR 0x338a80
-#define CSTORM_WAITP_ADDR 0x238a80
-#define TSTORM_CAM_MODE 0x1B1440
+#define XSTORM_WAITP_ADDR 0x2b8a80
+#define TSTORM_WAITP_ADDR 0x1b8a80
+#define USTORM_WAITP_ADDR 0x338a80
+#define CSTORM_WAITP_ADDR 0x238a80
+#define TSTORM_CAM_MODE 0x1B1440
+
+#define MAX_TIMER_PENDING 200
+#define TIMER_SCAN_DONT_CARE 0xFF
+#define RI_E1 0x1
+#define RI_E1H 0x2
+#define RI_E2 0x4
+#define RI_E3 0x8
+#define RI_E3B0 0x10
+#define RI_ONLINE 0x100
+#define RI_OFFLINE 0x0
+#define RI_PATH0_DUMP 0x200
+#define RI_PATH1_DUMP 0x400
-#define MAX_TIMER_PENDING 200
-#define TIMER_SCAN_DONT_CARE 0xFF
-#define RI_E1 0x1
-#define RI_E1H 0x2
-#define RI_E2 0x4
-#define RI_ONLINE 0x100
-#define RI_PATH0_DUMP 0x200
-#define RI_PATH1_DUMP 0x400
-#define RI_E1_OFFLINE (RI_E1)
#define RI_E1_ONLINE (RI_E1 | RI_ONLINE)
-#define RI_E1H_OFFLINE (RI_E1H)
#define RI_E1H_ONLINE (RI_E1H | RI_ONLINE)
-#define RI_E2_OFFLINE (RI_E2)
-#define RI_E2_ONLINE (RI_E2 | RI_ONLINE)
-#define RI_E1E1H_OFFLINE (RI_E1 | RI_E1H)
#define RI_E1E1H_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
-#define RI_E1HE2_OFFLINE (RI_E2 | RI_E1H)
-#define RI_E1HE2_ONLINE (RI_E2 | RI_E1H | RI_ONLINE)
-#define RI_E1E2_OFFLINE (RI_E2 | RI_E1)
-#define RI_E1E2_ONLINE (RI_E2 | RI_E1 | RI_ONLINE)
-#define RI_ALL_OFFLINE (RI_E1 | RI_E1H | RI_E2)
-#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
+#define RI_E2_ONLINE (RI_E2 | RI_ONLINE)
+#define RI_E1E2_ONLINE (RI_E1 | RI_E2 | RI_ONLINE)
+#define RI_E1HE2_ONLINE (RI_E1H | RI_E2 | RI_ONLINE)
+#define RI_E1E1HE2_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
+#define RI_E3_ONLINE (RI_E3 | RI_ONLINE)
+#define RI_E1E3_ONLINE (RI_E1 | RI_E3 | RI_ONLINE)
+#define RI_E1HE3_ONLINE (RI_E1H | RI_E3 | RI_ONLINE)
+#define RI_E1E1HE3_ONLINE (RI_E1 | RI_E1H | RI_E3 | RI_ONLINE)
+#define RI_E2E3_ONLINE (RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E1E2E3_ONLINE (RI_E1 | RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E1HE2E3_ONLINE (RI_E1H | RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E1E1HE2E3_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E3B0_ONLINE (RI_E3B0 | RI_ONLINE)
+#define RI_E1E3B0_ONLINE (RI_E1 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE3B0_ONLINE (RI_E1H | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE3B0_ONLINE (RI_E1 | RI_E1H | RI_E3B0 | RI_ONLINE)
+#define RI_E2E3B0_ONLINE (RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E2E3B0_ONLINE (RI_E1 | RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE2E3B0_ONLINE (RI_E1H | RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE2E3B0_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E3E3B0_ONLINE (RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E3E3B0_ONLINE (RI_E1 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE3E3B0_ONLINE (RI_E1H | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE3E3B0_ONLINE (RI_E1 | RI_E1H | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E2E3E3B0_ONLINE (RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E2E3E3B0_ONLINE (RI_E1 | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE2E3E3B0_ONLINE (RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE2E3E3B0_ONLINE \
+ (RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1_OFFLINE (RI_E1 | RI_OFFLINE)
+#define RI_E1H_OFFLINE (RI_E1H | RI_OFFLINE)
+#define RI_E1E1H_OFFLINE (RI_E1 | RI_E1H | RI_OFFLINE)
+#define RI_E2_OFFLINE (RI_E2 | RI_OFFLINE)
+#define RI_E1E2_OFFLINE (RI_E1 | RI_E2 | RI_OFFLINE)
+#define RI_E1HE2_OFFLINE (RI_E1H | RI_E2 | RI_OFFLINE)
+#define RI_E1E1HE2_OFFLINE (RI_E1 | RI_E1H | RI_E2 | RI_OFFLINE)
+#define RI_E3_OFFLINE (RI_E3 | RI_OFFLINE)
+#define RI_E1E3_OFFLINE (RI_E1 | RI_E3 | RI_OFFLINE)
+#define RI_E1HE3_OFFLINE (RI_E1H | RI_E3 | RI_OFFLINE)
+#define RI_E1E1HE3_OFFLINE (RI_E1 | RI_E1H | RI_E3 | RI_OFFLINE)
+#define RI_E2E3_OFFLINE (RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E1E2E3_OFFLINE (RI_E1 | RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E1HE2E3_OFFLINE (RI_E1H | RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E1E1HE2E3_OFFLINE (RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E3B0_OFFLINE (RI_E3B0 | RI_OFFLINE)
+#define RI_E1E3B0_OFFLINE (RI_E1 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE3B0_OFFLINE (RI_E1H | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE3B0_OFFLINE (RI_E1 | RI_E1H | RI_E3B0 | RI_OFFLINE)
+#define RI_E2E3B0_OFFLINE (RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E2E3B0_OFFLINE (RI_E1 | RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE2E3B0_OFFLINE (RI_E1H | RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE2E3B0_OFFLINE (RI_E1 | RI_E1H | RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E3E3B0_OFFLINE (RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E3E3B0_OFFLINE (RI_E1 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE3E3B0_OFFLINE (RI_E1H | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE3E3B0_OFFLINE (RI_E1 | RI_E1H | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E2E3E3B0_OFFLINE (RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E2E3E3B0_OFFLINE (RI_E1 | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE2E3E3B0_OFFLINE (RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE2E3E3B0_OFFLINE \
+ (RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_ALL_ONLINE RI_E1E1HE2E3E3B0_ONLINE
+#define RI_ALL_OFFLINE RI_E1E1HE2E3E3B0_OFFLINE
+
+#define DBG_DMP_TRACE_BUFFER_SIZE 0x800
+#define DBG_DMP_TRACE_BUFFER_OFFSET(shmem0_offset) \
+ ((shmem0_offset) - DBG_DMP_TRACE_BUFFER_SIZE)
struct dump_sign {
u32 time_stamp;
@@ -86,628 +146,1011 @@ struct wreg_addr {
u16 info;
};
-#define REGS_COUNT 834
-static const struct reg_addr reg_addrs[REGS_COUNT] = {
- { 0x2000, 341, RI_ALL_ONLINE }, { 0x2800, 103, RI_ALL_ONLINE },
- { 0x3000, 287, RI_ALL_ONLINE }, { 0x3800, 331, RI_ALL_ONLINE },
- { 0x8800, 6, RI_ALL_ONLINE }, { 0x8818, 1, RI_E1HE2_ONLINE },
- { 0x9000, 164, RI_E2_ONLINE }, { 0x9400, 33, RI_E2_ONLINE },
- { 0xa000, 27, RI_ALL_ONLINE }, { 0xa06c, 1, RI_E1E1H_ONLINE },
- { 0xa070, 71, RI_ALL_ONLINE }, { 0xa18c, 4, RI_E1E1H_ONLINE },
- { 0xa19c, 62, RI_ALL_ONLINE }, { 0xa294, 2, RI_E1E1H_ONLINE },
- { 0xa29c, 56, RI_ALL_ONLINE }, { 0xa39c, 7, RI_E1HE2_ONLINE },
- { 0xa3c0, 3, RI_E1HE2_ONLINE }, { 0xa3d0, 1, RI_E1HE2_ONLINE },
- { 0xa3d8, 1, RI_E1HE2_ONLINE }, { 0xa3e0, 1, RI_E1HE2_ONLINE },
- { 0xa3e8, 1, RI_E1HE2_ONLINE }, { 0xa3f0, 1, RI_E1HE2_ONLINE },
- { 0xa3f8, 1, RI_E1HE2_ONLINE }, { 0xa400, 43, RI_ALL_ONLINE },
- { 0xa4ac, 2, RI_E1E1H_ONLINE }, { 0xa4b4, 1, RI_ALL_ONLINE },
- { 0xa4b8, 2, RI_E1E1H_ONLINE }, { 0xa4c0, 3, RI_ALL_ONLINE },
- { 0xa4cc, 5, RI_E1E1H_ONLINE }, { 0xa4e0, 9, RI_ALL_ONLINE },
- { 0xa504, 1, RI_E1E1H_ONLINE }, { 0xa508, 3, RI_ALL_ONLINE },
- { 0xa518, 1, RI_ALL_ONLINE }, { 0xa520, 1, RI_ALL_ONLINE },
- { 0xa528, 1, RI_ALL_ONLINE }, { 0xa530, 1, RI_ALL_ONLINE },
- { 0xa538, 1, RI_ALL_ONLINE }, { 0xa540, 1, RI_ALL_ONLINE },
- { 0xa548, 1, RI_E1E1H_ONLINE }, { 0xa550, 1, RI_E1E1H_ONLINE },
- { 0xa558, 1, RI_E1E1H_ONLINE }, { 0xa560, 1, RI_E1E1H_ONLINE },
- { 0xa568, 1, RI_E1E1H_ONLINE }, { 0xa570, 1, RI_ALL_ONLINE },
- { 0xa580, 1, RI_ALL_ONLINE }, { 0xa590, 1, RI_ALL_ONLINE },
- { 0xa5a0, 1, RI_ALL_ONLINE }, { 0xa5c0, 1, RI_ALL_ONLINE },
- { 0xa5e0, 1, RI_E1HE2_ONLINE }, { 0xa5e8, 1, RI_E1HE2_ONLINE },
- { 0xa5f0, 1, RI_E1HE2_ONLINE }, { 0xa5f8, 10, RI_E1HE2_ONLINE },
- { 0xa620, 111, RI_E2_ONLINE }, { 0xa800, 51, RI_E2_ONLINE },
- { 0xa8d4, 4, RI_E2_ONLINE }, { 0xa8e8, 1, RI_E2_ONLINE },
- { 0xa8f0, 1, RI_E2_ONLINE }, { 0x10000, 236, RI_ALL_ONLINE },
- { 0x10400, 57, RI_ALL_ONLINE }, { 0x104e8, 2, RI_ALL_ONLINE },
- { 0x104f4, 2, RI_ALL_ONLINE }, { 0x10500, 146, RI_ALL_ONLINE },
- { 0x10750, 2, RI_ALL_ONLINE }, { 0x10760, 2, RI_ALL_ONLINE },
- { 0x10770, 2, RI_ALL_ONLINE }, { 0x10780, 2, RI_ALL_ONLINE },
- { 0x10790, 2, RI_ALL_ONLINE }, { 0x107a0, 2, RI_ALL_ONLINE },
- { 0x107b0, 2, RI_ALL_ONLINE }, { 0x107c0, 2, RI_ALL_ONLINE },
- { 0x107d0, 2, RI_ALL_ONLINE }, { 0x107e0, 2, RI_ALL_ONLINE },
- { 0x10880, 2, RI_ALL_ONLINE }, { 0x10900, 2, RI_ALL_ONLINE },
- { 0x16000, 26, RI_E1HE2_ONLINE }, { 0x16070, 18, RI_E1HE2_ONLINE },
- { 0x160c0, 27, RI_E1HE2_ONLINE }, { 0x16140, 1, RI_E1HE2_ONLINE },
- { 0x16160, 1, RI_E1HE2_ONLINE }, { 0x16180, 2, RI_E1HE2_ONLINE },
- { 0x161c0, 2, RI_E1HE2_ONLINE }, { 0x16204, 5, RI_E1HE2_ONLINE },
- { 0x18000, 1, RI_E1HE2_ONLINE }, { 0x18008, 1, RI_E1HE2_ONLINE },
- { 0x18010, 35, RI_E2_ONLINE }, { 0x180a4, 2, RI_E2_ONLINE },
- { 0x180c0, 191, RI_E2_ONLINE }, { 0x18440, 1, RI_E2_ONLINE },
- { 0x18460, 1, RI_E2_ONLINE }, { 0x18480, 2, RI_E2_ONLINE },
- { 0x184c0, 2, RI_E2_ONLINE }, { 0x18500, 15, RI_E2_ONLINE },
- { 0x20000, 24, RI_ALL_ONLINE }, { 0x20060, 8, RI_ALL_ONLINE },
- { 0x20080, 94, RI_ALL_ONLINE }, { 0x201f8, 1, RI_E1E1H_ONLINE },
- { 0x201fc, 1, RI_ALL_ONLINE }, { 0x20200, 1, RI_E1E1H_ONLINE },
- { 0x20204, 1, RI_ALL_ONLINE }, { 0x20208, 1, RI_E1E1H_ONLINE },
- { 0x2020c, 39, RI_ALL_ONLINE }, { 0x202c8, 1, RI_E2_ONLINE },
- { 0x202d8, 4, RI_E2_ONLINE }, { 0x20400, 2, RI_ALL_ONLINE },
- { 0x2040c, 8, RI_ALL_ONLINE }, { 0x2042c, 18, RI_E1HE2_ONLINE },
- { 0x20480, 1, RI_ALL_ONLINE }, { 0x20500, 1, RI_ALL_ONLINE },
- { 0x20600, 1, RI_ALL_ONLINE }, { 0x28000, 1, RI_ALL_ONLINE },
- { 0x28004, 8191, RI_ALL_OFFLINE }, { 0x30000, 1, RI_ALL_ONLINE },
- { 0x30004, 16383, RI_ALL_OFFLINE }, { 0x40000, 98, RI_ALL_ONLINE },
- { 0x401a8, 8, RI_E1HE2_ONLINE }, { 0x401c8, 1, RI_E1H_ONLINE },
- { 0x401cc, 2, RI_E1HE2_ONLINE }, { 0x401d4, 2, RI_E2_ONLINE },
- { 0x40200, 4, RI_ALL_ONLINE }, { 0x40220, 18, RI_E2_ONLINE },
- { 0x40400, 43, RI_ALL_ONLINE }, { 0x404cc, 3, RI_E1HE2_ONLINE },
- { 0x404e0, 1, RI_E2_ONLINE }, { 0x40500, 2, RI_ALL_ONLINE },
- { 0x40510, 2, RI_ALL_ONLINE }, { 0x40520, 2, RI_ALL_ONLINE },
- { 0x40530, 2, RI_ALL_ONLINE }, { 0x40540, 2, RI_ALL_ONLINE },
- { 0x40550, 10, RI_E2_ONLINE }, { 0x40610, 2, RI_E2_ONLINE },
- { 0x42000, 164, RI_ALL_ONLINE }, { 0x422c0, 4, RI_E2_ONLINE },
- { 0x422d4, 5, RI_E1HE2_ONLINE }, { 0x422e8, 1, RI_E2_ONLINE },
- { 0x42400, 49, RI_ALL_ONLINE }, { 0x424c8, 38, RI_ALL_ONLINE },
- { 0x42568, 2, RI_ALL_ONLINE }, { 0x42640, 5, RI_E2_ONLINE },
- { 0x42800, 1, RI_ALL_ONLINE }, { 0x50000, 1, RI_ALL_ONLINE },
- { 0x50004, 19, RI_ALL_ONLINE }, { 0x50050, 8, RI_ALL_ONLINE },
- { 0x50070, 88, RI_ALL_ONLINE }, { 0x501f0, 4, RI_E1HE2_ONLINE },
- { 0x50200, 2, RI_ALL_ONLINE }, { 0x5020c, 7, RI_ALL_ONLINE },
- { 0x50228, 6, RI_E1HE2_ONLINE }, { 0x50240, 1, RI_ALL_ONLINE },
- { 0x50280, 1, RI_ALL_ONLINE }, { 0x50300, 1, RI_E2_ONLINE },
- { 0x5030c, 1, RI_E2_ONLINE }, { 0x50318, 1, RI_E2_ONLINE },
- { 0x5031c, 1, RI_E2_ONLINE }, { 0x50320, 2, RI_E2_ONLINE },
- { 0x52000, 1, RI_ALL_ONLINE }, { 0x54000, 1, RI_ALL_ONLINE },
- { 0x54004, 3327, RI_ALL_OFFLINE }, { 0x58000, 1, RI_ALL_ONLINE },
- { 0x58004, 8191, RI_E1E1H_OFFLINE }, { 0x60000, 26, RI_ALL_ONLINE },
- { 0x60068, 8, RI_E1E1H_ONLINE }, { 0x60088, 12, RI_ALL_ONLINE },
- { 0x600b8, 9, RI_E1E1H_ONLINE }, { 0x600dc, 1, RI_ALL_ONLINE },
- { 0x600e0, 5, RI_E1E1H_ONLINE }, { 0x600f4, 1, RI_ALL_ONLINE },
- { 0x600f8, 1, RI_E1E1H_ONLINE }, { 0x600fc, 8, RI_ALL_ONLINE },
- { 0x6013c, 24, RI_E1H_ONLINE }, { 0x6019c, 2, RI_E2_ONLINE },
- { 0x601ac, 18, RI_E2_ONLINE }, { 0x60200, 1, RI_ALL_ONLINE },
- { 0x60204, 2, RI_ALL_OFFLINE }, { 0x60210, 13, RI_E2_ONLINE },
- { 0x61000, 1, RI_ALL_ONLINE }, { 0x61004, 511, RI_ALL_OFFLINE },
- { 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 8184, RI_ALL_OFFLINE },
- { 0x85000, 3, RI_ALL_ONLINE }, { 0x8501c, 7, RI_ALL_ONLINE },
- { 0x85048, 1, RI_ALL_ONLINE }, { 0x85200, 32, RI_ALL_ONLINE },
- { 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2_ONLINE },
- { 0xc1800, 2, RI_ALL_ONLINE }, { 0xc2000, 164, RI_ALL_ONLINE },
- { 0xc22c0, 5, RI_E2_ONLINE }, { 0xc22d8, 4, RI_E2_ONLINE },
- { 0xc2400, 49, RI_ALL_ONLINE }, { 0xc24c8, 38, RI_ALL_ONLINE },
- { 0xc2568, 2, RI_ALL_ONLINE }, { 0xc2600, 1, RI_ALL_ONLINE },
- { 0xc4000, 165, RI_ALL_ONLINE }, { 0xc42d8, 2, RI_E2_ONLINE },
- { 0xc42e0, 7, RI_E1HE2_ONLINE }, { 0xc42fc, 1, RI_E2_ONLINE },
- { 0xc4400, 51, RI_ALL_ONLINE }, { 0xc44d0, 38, RI_ALL_ONLINE },
- { 0xc4570, 2, RI_ALL_ONLINE }, { 0xc4578, 5, RI_E2_ONLINE },
- { 0xc4600, 1, RI_ALL_ONLINE }, { 0xd0000, 19, RI_ALL_ONLINE },
- { 0xd004c, 8, RI_ALL_ONLINE }, { 0xd006c, 91, RI_ALL_ONLINE },
- { 0xd01fc, 1, RI_E2_ONLINE }, { 0xd0200, 2, RI_ALL_ONLINE },
- { 0xd020c, 7, RI_ALL_ONLINE }, { 0xd0228, 18, RI_E1HE2_ONLINE },
- { 0xd0280, 1, RI_ALL_ONLINE }, { 0xd0300, 1, RI_ALL_ONLINE },
- { 0xd0400, 1, RI_ALL_ONLINE }, { 0xd4000, 1, RI_ALL_ONLINE },
- { 0xd4004, 2559, RI_ALL_OFFLINE }, { 0xd8000, 1, RI_ALL_ONLINE },
- { 0xd8004, 8191, RI_ALL_OFFLINE }, { 0xe0000, 21, RI_ALL_ONLINE },
- { 0xe0054, 8, RI_ALL_ONLINE }, { 0xe0074, 49, RI_ALL_ONLINE },
- { 0xe0138, 1, RI_E1E1H_ONLINE }, { 0xe013c, 35, RI_ALL_ONLINE },
- { 0xe01f4, 2, RI_E2_ONLINE }, { 0xe0200, 2, RI_ALL_ONLINE },
- { 0xe020c, 8, RI_ALL_ONLINE }, { 0xe022c, 18, RI_E1HE2_ONLINE },
- { 0xe0280, 1, RI_ALL_ONLINE }, { 0xe0300, 1, RI_ALL_ONLINE },
- { 0xe1000, 1, RI_ALL_ONLINE }, { 0xe2000, 1, RI_ALL_ONLINE },
- { 0xe2004, 2047, RI_ALL_OFFLINE }, { 0xf0000, 1, RI_ALL_ONLINE },
- { 0xf0004, 16383, RI_ALL_OFFLINE }, { 0x101000, 12, RI_ALL_ONLINE },
- { 0x101050, 1, RI_E1HE2_ONLINE }, { 0x101054, 3, RI_E2_ONLINE },
- { 0x101100, 1, RI_ALL_ONLINE }, { 0x101800, 8, RI_ALL_ONLINE },
- { 0x102000, 18, RI_ALL_ONLINE }, { 0x102068, 6, RI_E2_ONLINE },
- { 0x102080, 17, RI_ALL_ONLINE }, { 0x1020c8, 8, RI_E1H_ONLINE },
- { 0x1020e8, 9, RI_E2_ONLINE }, { 0x102400, 1, RI_ALL_ONLINE },
- { 0x103000, 26, RI_ALL_ONLINE }, { 0x103098, 5, RI_E1HE2_ONLINE },
- { 0x1030ac, 10, RI_E2_ONLINE }, { 0x1030d8, 8, RI_E2_ONLINE },
- { 0x103400, 1, RI_E2_ONLINE }, { 0x103404, 135, RI_E2_OFFLINE },
- { 0x103800, 8, RI_ALL_ONLINE }, { 0x104000, 63, RI_ALL_ONLINE },
- { 0x10411c, 16, RI_E2_ONLINE }, { 0x104200, 17, RI_ALL_ONLINE },
- { 0x104400, 64, RI_ALL_ONLINE }, { 0x104500, 192, RI_ALL_OFFLINE },
- { 0x104800, 64, RI_ALL_ONLINE }, { 0x104900, 192, RI_ALL_OFFLINE },
- { 0x105000, 256, RI_ALL_ONLINE }, { 0x105400, 768, RI_ALL_OFFLINE },
- { 0x107000, 7, RI_E2_ONLINE }, { 0x108000, 33, RI_E1E1H_ONLINE },
- { 0x1080ac, 5, RI_E1H_ONLINE }, { 0x108100, 5, RI_E1E1H_ONLINE },
- { 0x108120, 5, RI_E1E1H_ONLINE }, { 0x108200, 74, RI_E1E1H_ONLINE },
- { 0x108400, 74, RI_E1E1H_ONLINE }, { 0x108800, 152, RI_E1E1H_ONLINE },
- { 0x110000, 111, RI_E2_ONLINE }, { 0x110200, 4, RI_E2_ONLINE },
- { 0x120000, 2, RI_ALL_ONLINE }, { 0x120008, 4, RI_ALL_ONLINE },
- { 0x120018, 3, RI_ALL_ONLINE }, { 0x120024, 4, RI_ALL_ONLINE },
- { 0x120034, 3, RI_ALL_ONLINE }, { 0x120040, 4, RI_ALL_ONLINE },
- { 0x120050, 3, RI_ALL_ONLINE }, { 0x12005c, 4, RI_ALL_ONLINE },
- { 0x12006c, 3, RI_ALL_ONLINE }, { 0x120078, 4, RI_ALL_ONLINE },
- { 0x120088, 3, RI_ALL_ONLINE }, { 0x120094, 4, RI_ALL_ONLINE },
- { 0x1200a4, 3, RI_ALL_ONLINE }, { 0x1200b0, 4, RI_ALL_ONLINE },
- { 0x1200c0, 3, RI_ALL_ONLINE }, { 0x1200cc, 4, RI_ALL_ONLINE },
- { 0x1200dc, 3, RI_ALL_ONLINE }, { 0x1200e8, 4, RI_ALL_ONLINE },
- { 0x1200f8, 3, RI_ALL_ONLINE }, { 0x120104, 4, RI_ALL_ONLINE },
- { 0x120114, 1, RI_ALL_ONLINE }, { 0x120118, 22, RI_ALL_ONLINE },
- { 0x120170, 2, RI_E1E1H_ONLINE }, { 0x120178, 243, RI_ALL_ONLINE },
- { 0x120544, 4, RI_E1E1H_ONLINE }, { 0x120554, 7, RI_ALL_ONLINE },
- { 0x12059c, 6, RI_E1HE2_ONLINE }, { 0x1205b4, 1, RI_E1HE2_ONLINE },
- { 0x1205b8, 16, RI_E1HE2_ONLINE }, { 0x1205f8, 4, RI_E2_ONLINE },
- { 0x120618, 1, RI_E2_ONLINE }, { 0x12061c, 20, RI_E1HE2_ONLINE },
- { 0x12066c, 11, RI_E1HE2_ONLINE }, { 0x120698, 5, RI_E2_ONLINE },
- { 0x1206b0, 76, RI_E2_ONLINE }, { 0x1207fc, 1, RI_E2_ONLINE },
- { 0x120808, 66, RI_ALL_ONLINE }, { 0x120910, 7, RI_E2_ONLINE },
- { 0x120930, 9, RI_E2_ONLINE }, { 0x120a00, 2, RI_ALL_ONLINE },
- { 0x122000, 2, RI_ALL_ONLINE }, { 0x122008, 2046, RI_E1_OFFLINE },
- { 0x128000, 2, RI_E1HE2_ONLINE }, { 0x128008, 6142, RI_E1HE2_OFFLINE },
- { 0x130000, 35, RI_E2_ONLINE }, { 0x130100, 29, RI_E2_ONLINE },
- { 0x130180, 1, RI_E2_ONLINE }, { 0x130200, 1, RI_E2_ONLINE },
- { 0x130280, 1, RI_E2_ONLINE }, { 0x130300, 5, RI_E2_ONLINE },
- { 0x130380, 1, RI_E2_ONLINE }, { 0x130400, 1, RI_E2_ONLINE },
- { 0x130480, 5, RI_E2_ONLINE }, { 0x130800, 72, RI_E2_ONLINE },
- { 0x131000, 136, RI_E2_ONLINE }, { 0x132000, 148, RI_E2_ONLINE },
- { 0x134000, 544, RI_E2_ONLINE }, { 0x140000, 64, RI_ALL_ONLINE },
- { 0x140100, 5, RI_E1E1H_ONLINE }, { 0x140114, 45, RI_ALL_ONLINE },
- { 0x140200, 6, RI_ALL_ONLINE }, { 0x140220, 4, RI_E2_ONLINE },
- { 0x140240, 4, RI_E2_ONLINE }, { 0x140260, 4, RI_E2_ONLINE },
- { 0x140280, 4, RI_E2_ONLINE }, { 0x1402a0, 4, RI_E2_ONLINE },
- { 0x1402c0, 4, RI_E2_ONLINE }, { 0x1402e0, 13, RI_E2_ONLINE },
- { 0x144000, 4, RI_E1E1H_ONLINE }, { 0x148000, 4, RI_E1E1H_ONLINE },
- { 0x14c000, 4, RI_E1E1H_ONLINE }, { 0x150000, 4, RI_E1E1H_ONLINE },
- { 0x154000, 4, RI_E1E1H_ONLINE }, { 0x158000, 4, RI_E1E1H_ONLINE },
- { 0x15c000, 2, RI_E1HE2_ONLINE }, { 0x15c008, 5, RI_E1H_ONLINE },
- { 0x15c020, 27, RI_E2_ONLINE }, { 0x15c090, 13, RI_E2_ONLINE },
- { 0x15c0c8, 34, RI_E2_ONLINE }, { 0x161000, 7, RI_ALL_ONLINE },
- { 0x16103c, 2, RI_E2_ONLINE }, { 0x161800, 2, RI_ALL_ONLINE },
- { 0x164000, 60, RI_ALL_ONLINE }, { 0x164110, 2, RI_E1HE2_ONLINE },
- { 0x164118, 15, RI_E2_ONLINE }, { 0x164200, 1, RI_ALL_ONLINE },
- { 0x164208, 1, RI_ALL_ONLINE }, { 0x164210, 1, RI_ALL_ONLINE },
- { 0x164218, 1, RI_ALL_ONLINE }, { 0x164220, 1, RI_ALL_ONLINE },
- { 0x164228, 1, RI_ALL_ONLINE }, { 0x164230, 1, RI_ALL_ONLINE },
- { 0x164238, 1, RI_ALL_ONLINE }, { 0x164240, 1, RI_ALL_ONLINE },
- { 0x164248, 1, RI_ALL_ONLINE }, { 0x164250, 1, RI_ALL_ONLINE },
- { 0x164258, 1, RI_ALL_ONLINE }, { 0x164260, 1, RI_ALL_ONLINE },
- { 0x164270, 2, RI_ALL_ONLINE }, { 0x164280, 2, RI_ALL_ONLINE },
- { 0x164800, 2, RI_ALL_ONLINE }, { 0x165000, 2, RI_ALL_ONLINE },
- { 0x166000, 164, RI_ALL_ONLINE }, { 0x1662cc, 7, RI_E2_ONLINE },
- { 0x166400, 49, RI_ALL_ONLINE }, { 0x1664c8, 38, RI_ALL_ONLINE },
- { 0x166568, 2, RI_ALL_ONLINE }, { 0x166570, 5, RI_E2_ONLINE },
- { 0x166800, 1, RI_ALL_ONLINE }, { 0x168000, 137, RI_ALL_ONLINE },
- { 0x168224, 2, RI_E1E1H_ONLINE }, { 0x16822c, 29, RI_ALL_ONLINE },
- { 0x1682a0, 12, RI_E1E1H_ONLINE }, { 0x1682d0, 12, RI_ALL_ONLINE },
- { 0x168300, 2, RI_E1E1H_ONLINE }, { 0x168308, 68, RI_ALL_ONLINE },
- { 0x168418, 2, RI_E1E1H_ONLINE }, { 0x168420, 6, RI_ALL_ONLINE },
- { 0x168800, 19, RI_ALL_ONLINE }, { 0x168900, 1, RI_ALL_ONLINE },
- { 0x168a00, 128, RI_ALL_ONLINE }, { 0x16a000, 1, RI_ALL_ONLINE },
- { 0x16a004, 1535, RI_ALL_OFFLINE }, { 0x16c000, 1, RI_ALL_ONLINE },
- { 0x16c004, 1535, RI_ALL_OFFLINE }, { 0x16e000, 16, RI_E1H_ONLINE },
- { 0x16e040, 8, RI_E2_ONLINE }, { 0x16e100, 1, RI_E1H_ONLINE },
- { 0x16e200, 2, RI_E1H_ONLINE }, { 0x16e400, 161, RI_E1H_ONLINE },
- { 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 12, RI_E1H_ONLINE },
- { 0x16e6bc, 4, RI_E1HE2_ONLINE }, { 0x16e6cc, 4, RI_E1H_ONLINE },
- { 0x16e6e0, 12, RI_E2_ONLINE }, { 0x16e768, 17, RI_E2_ONLINE },
- { 0x170000, 24, RI_ALL_ONLINE }, { 0x170060, 4, RI_E1E1H_ONLINE },
- { 0x170070, 65, RI_ALL_ONLINE }, { 0x170194, 11, RI_E2_ONLINE },
- { 0x1701c4, 1, RI_E2_ONLINE }, { 0x1701cc, 7, RI_E2_ONLINE },
- { 0x1701ec, 1, RI_E2_ONLINE }, { 0x1701f4, 1, RI_E2_ONLINE },
- { 0x170200, 4, RI_ALL_ONLINE }, { 0x170214, 1, RI_ALL_ONLINE },
- { 0x170218, 77, RI_E2_ONLINE }, { 0x170400, 64, RI_E2_ONLINE },
- { 0x178000, 1, RI_ALL_ONLINE }, { 0x180000, 61, RI_ALL_ONLINE },
- { 0x18013c, 2, RI_E1HE2_ONLINE }, { 0x180200, 58, RI_ALL_ONLINE },
- { 0x180340, 4, RI_ALL_ONLINE }, { 0x180380, 1, RI_E2_ONLINE },
- { 0x180388, 1, RI_E2_ONLINE }, { 0x180390, 1, RI_E2_ONLINE },
- { 0x180398, 1, RI_E2_ONLINE }, { 0x1803a0, 5, RI_E2_ONLINE },
- { 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_E1E1H_OFFLINE },
- { 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE },
- { 0x1a0000, 1, RI_ALL_ONLINE }, { 0x1a0004, 5631, RI_ALL_OFFLINE },
- { 0x1a5800, 2560, RI_E1HE2_OFFLINE }, { 0x1a8000, 1, RI_ALL_ONLINE },
- { 0x1a8004, 8191, RI_E1HE2_OFFLINE }, { 0x1b0000, 1, RI_ALL_ONLINE },
- { 0x1b0004, 15, RI_E1H_OFFLINE }, { 0x1b0040, 1, RI_E1HE2_ONLINE },
- { 0x1b0044, 239, RI_E1H_OFFLINE }, { 0x1b0400, 1, RI_ALL_ONLINE },
- { 0x1b0404, 255, RI_E1H_OFFLINE }, { 0x1b0800, 1, RI_ALL_ONLINE },
- { 0x1b0840, 1, RI_E1HE2_ONLINE }, { 0x1b0c00, 1, RI_ALL_ONLINE },
- { 0x1b1000, 1, RI_ALL_ONLINE }, { 0x1b1040, 1, RI_E1HE2_ONLINE },
- { 0x1b1400, 1, RI_ALL_ONLINE }, { 0x1b1440, 1, RI_E1HE2_ONLINE },
- { 0x1b1480, 1, RI_E1HE2_ONLINE }, { 0x1b14c0, 1, RI_E1HE2_ONLINE },
- { 0x1b1800, 128, RI_ALL_OFFLINE }, { 0x1b1c00, 128, RI_ALL_OFFLINE },
- { 0x1b2000, 1, RI_ALL_ONLINE }, { 0x1b2400, 1, RI_E1HE2_ONLINE },
- { 0x1b2404, 5631, RI_E2_OFFLINE }, { 0x1b8000, 1, RI_ALL_ONLINE },
- { 0x1b8040, 1, RI_ALL_ONLINE }, { 0x1b8080, 1, RI_ALL_ONLINE },
- { 0x1b80c0, 1, RI_ALL_ONLINE }, { 0x1b8100, 1, RI_ALL_ONLINE },
- { 0x1b8140, 1, RI_ALL_ONLINE }, { 0x1b8180, 1, RI_ALL_ONLINE },
- { 0x1b81c0, 1, RI_ALL_ONLINE }, { 0x1b8200, 1, RI_ALL_ONLINE },
- { 0x1b8240, 1, RI_ALL_ONLINE }, { 0x1b8280, 1, RI_ALL_ONLINE },
- { 0x1b82c0, 1, RI_ALL_ONLINE }, { 0x1b8300, 1, RI_ALL_ONLINE },
- { 0x1b8340, 1, RI_ALL_ONLINE }, { 0x1b8380, 1, RI_ALL_ONLINE },
- { 0x1b83c0, 1, RI_ALL_ONLINE }, { 0x1b8400, 1, RI_ALL_ONLINE },
- { 0x1b8440, 1, RI_ALL_ONLINE }, { 0x1b8480, 1, RI_ALL_ONLINE },
- { 0x1b84c0, 1, RI_ALL_ONLINE }, { 0x1b8500, 1, RI_ALL_ONLINE },
- { 0x1b8540, 1, RI_ALL_ONLINE }, { 0x1b8580, 1, RI_ALL_ONLINE },
- { 0x1b85c0, 19, RI_E2_ONLINE }, { 0x1b8800, 1, RI_ALL_ONLINE },
- { 0x1b8840, 1, RI_ALL_ONLINE }, { 0x1b8880, 1, RI_ALL_ONLINE },
- { 0x1b88c0, 1, RI_ALL_ONLINE }, { 0x1b8900, 1, RI_ALL_ONLINE },
- { 0x1b8940, 1, RI_ALL_ONLINE }, { 0x1b8980, 1, RI_ALL_ONLINE },
- { 0x1b89c0, 1, RI_ALL_ONLINE }, { 0x1b8a00, 1, RI_ALL_ONLINE },
- { 0x1b8a40, 1, RI_ALL_ONLINE }, { 0x1b8a80, 1, RI_ALL_ONLINE },
- { 0x1b8ac0, 1, RI_ALL_ONLINE }, { 0x1b8b00, 1, RI_ALL_ONLINE },
- { 0x1b8b40, 1, RI_ALL_ONLINE }, { 0x1b8b80, 1, RI_ALL_ONLINE },
- { 0x1b8bc0, 1, RI_ALL_ONLINE }, { 0x1b8c00, 1, RI_ALL_ONLINE },
- { 0x1b8c40, 1, RI_ALL_ONLINE }, { 0x1b8c80, 1, RI_ALL_ONLINE },
- { 0x1b8cc0, 1, RI_ALL_ONLINE }, { 0x1b8cc4, 1, RI_E2_ONLINE },
- { 0x1b8d00, 1, RI_ALL_ONLINE }, { 0x1b8d40, 1, RI_ALL_ONLINE },
- { 0x1b8d80, 1, RI_ALL_ONLINE }, { 0x1b8dc0, 1, RI_ALL_ONLINE },
- { 0x1b8e00, 1, RI_ALL_ONLINE }, { 0x1b8e40, 1, RI_ALL_ONLINE },
- { 0x1b8e80, 1, RI_ALL_ONLINE }, { 0x1b8e84, 1, RI_E2_ONLINE },
- { 0x1b8ec0, 1, RI_E1HE2_ONLINE }, { 0x1b8f00, 1, RI_E1HE2_ONLINE },
- { 0x1b8f40, 1, RI_E1HE2_ONLINE }, { 0x1b8f80, 1, RI_E1HE2_ONLINE },
- { 0x1b8fc0, 1, RI_E1HE2_ONLINE }, { 0x1b8fc4, 2, RI_E2_ONLINE },
- { 0x1b8fd0, 6, RI_E2_ONLINE }, { 0x1b9000, 1, RI_E2_ONLINE },
- { 0x1b9040, 3, RI_E2_ONLINE }, { 0x1b9400, 14, RI_E2_ONLINE },
- { 0x1b943c, 19, RI_E2_ONLINE }, { 0x1b9490, 10, RI_E2_ONLINE },
- { 0x1c0000, 2, RI_ALL_ONLINE }, { 0x200000, 65, RI_ALL_ONLINE },
- { 0x20014c, 2, RI_E1HE2_ONLINE }, { 0x200200, 58, RI_ALL_ONLINE },
- { 0x200340, 4, RI_ALL_ONLINE }, { 0x200380, 1, RI_E2_ONLINE },
- { 0x200388, 1, RI_E2_ONLINE }, { 0x200390, 1, RI_E2_ONLINE },
- { 0x200398, 1, RI_E2_ONLINE }, { 0x2003a0, 1, RI_E2_ONLINE },
- { 0x2003a8, 2, RI_E2_ONLINE }, { 0x200400, 1, RI_ALL_ONLINE },
- { 0x200404, 255, RI_E1E1H_OFFLINE }, { 0x202000, 4, RI_ALL_ONLINE },
- { 0x202010, 2044, RI_ALL_OFFLINE }, { 0x220000, 1, RI_ALL_ONLINE },
- { 0x220004, 5631, RI_ALL_OFFLINE }, { 0x225800, 2560, RI_E1HE2_OFFLINE},
- { 0x228000, 1, RI_ALL_ONLINE }, { 0x228004, 8191, RI_E1HE2_OFFLINE },
- { 0x230000, 1, RI_ALL_ONLINE }, { 0x230004, 15, RI_E1H_OFFLINE },
- { 0x230040, 1, RI_E1HE2_ONLINE }, { 0x230044, 239, RI_E1H_OFFLINE },
- { 0x230400, 1, RI_ALL_ONLINE }, { 0x230404, 255, RI_E1H_OFFLINE },
- { 0x230800, 1, RI_ALL_ONLINE }, { 0x230840, 1, RI_E1HE2_ONLINE },
- { 0x230c00, 1, RI_ALL_ONLINE }, { 0x231000, 1, RI_ALL_ONLINE },
- { 0x231040, 1, RI_E1HE2_ONLINE }, { 0x231400, 1, RI_ALL_ONLINE },
- { 0x231440, 1, RI_E1HE2_ONLINE }, { 0x231480, 1, RI_E1HE2_ONLINE },
- { 0x2314c0, 1, RI_E1HE2_ONLINE }, { 0x231800, 128, RI_ALL_OFFLINE },
- { 0x231c00, 128, RI_ALL_OFFLINE }, { 0x232000, 1, RI_ALL_ONLINE },
- { 0x232400, 1, RI_E1HE2_ONLINE }, { 0x232404, 5631, RI_E2_OFFLINE },
- { 0x238000, 1, RI_ALL_ONLINE }, { 0x238040, 1, RI_ALL_ONLINE },
- { 0x238080, 1, RI_ALL_ONLINE }, { 0x2380c0, 1, RI_ALL_ONLINE },
- { 0x238100, 1, RI_ALL_ONLINE }, { 0x238140, 1, RI_ALL_ONLINE },
- { 0x238180, 1, RI_ALL_ONLINE }, { 0x2381c0, 1, RI_ALL_ONLINE },
- { 0x238200, 1, RI_ALL_ONLINE }, { 0x238240, 1, RI_ALL_ONLINE },
- { 0x238280, 1, RI_ALL_ONLINE }, { 0x2382c0, 1, RI_ALL_ONLINE },
- { 0x238300, 1, RI_ALL_ONLINE }, { 0x238340, 1, RI_ALL_ONLINE },
- { 0x238380, 1, RI_ALL_ONLINE }, { 0x2383c0, 1, RI_ALL_ONLINE },
- { 0x238400, 1, RI_ALL_ONLINE }, { 0x238440, 1, RI_ALL_ONLINE },
- { 0x238480, 1, RI_ALL_ONLINE }, { 0x2384c0, 1, RI_ALL_ONLINE },
- { 0x238500, 1, RI_ALL_ONLINE }, { 0x238540, 1, RI_ALL_ONLINE },
- { 0x238580, 1, RI_ALL_ONLINE }, { 0x2385c0, 19, RI_E2_ONLINE },
- { 0x238800, 1, RI_ALL_ONLINE }, { 0x238840, 1, RI_ALL_ONLINE },
- { 0x238880, 1, RI_ALL_ONLINE }, { 0x2388c0, 1, RI_ALL_ONLINE },
- { 0x238900, 1, RI_ALL_ONLINE }, { 0x238940, 1, RI_ALL_ONLINE },
- { 0x238980, 1, RI_ALL_ONLINE }, { 0x2389c0, 1, RI_ALL_ONLINE },
- { 0x238a00, 1, RI_ALL_ONLINE }, { 0x238a40, 1, RI_ALL_ONLINE },
- { 0x238a80, 1, RI_ALL_ONLINE }, { 0x238ac0, 1, RI_ALL_ONLINE },
- { 0x238b00, 1, RI_ALL_ONLINE }, { 0x238b40, 1, RI_ALL_ONLINE },
- { 0x238b80, 1, RI_ALL_ONLINE }, { 0x238bc0, 1, RI_ALL_ONLINE },
- { 0x238c00, 1, RI_ALL_ONLINE }, { 0x238c40, 1, RI_ALL_ONLINE },
- { 0x238c80, 1, RI_ALL_ONLINE }, { 0x238cc0, 1, RI_ALL_ONLINE },
- { 0x238cc4, 1, RI_E2_ONLINE }, { 0x238d00, 1, RI_ALL_ONLINE },
- { 0x238d40, 1, RI_ALL_ONLINE }, { 0x238d80, 1, RI_ALL_ONLINE },
- { 0x238dc0, 1, RI_ALL_ONLINE }, { 0x238e00, 1, RI_ALL_ONLINE },
- { 0x238e40, 1, RI_ALL_ONLINE }, { 0x238e80, 1, RI_ALL_ONLINE },
- { 0x238e84, 1, RI_E2_ONLINE }, { 0x238ec0, 1, RI_E1HE2_ONLINE },
- { 0x238f00, 1, RI_E1HE2_ONLINE }, { 0x238f40, 1, RI_E1HE2_ONLINE },
- { 0x238f80, 1, RI_E1HE2_ONLINE }, { 0x238fc0, 1, RI_E1HE2_ONLINE },
- { 0x238fc4, 2, RI_E2_ONLINE }, { 0x238fd0, 6, RI_E2_ONLINE },
- { 0x239000, 1, RI_E2_ONLINE }, { 0x239040, 3, RI_E2_ONLINE },
- { 0x240000, 2, RI_ALL_ONLINE }, { 0x280000, 65, RI_ALL_ONLINE },
- { 0x28014c, 2, RI_E1HE2_ONLINE }, { 0x280200, 58, RI_ALL_ONLINE },
- { 0x280340, 4, RI_ALL_ONLINE }, { 0x280380, 1, RI_E2_ONLINE },
- { 0x280388, 1, RI_E2_ONLINE }, { 0x280390, 1, RI_E2_ONLINE },
- { 0x280398, 1, RI_E2_ONLINE }, { 0x2803a0, 1, RI_E2_ONLINE },
- { 0x2803a8, 2, RI_E2_ONLINE }, { 0x280400, 1, RI_ALL_ONLINE },
- { 0x280404, 255, RI_E1E1H_OFFLINE }, { 0x282000, 4, RI_ALL_ONLINE },
- { 0x282010, 2044, RI_ALL_OFFLINE }, { 0x2a0000, 1, RI_ALL_ONLINE },
- { 0x2a0004, 5631, RI_ALL_OFFLINE }, { 0x2a5800, 2560, RI_E1HE2_OFFLINE},
- { 0x2a8000, 1, RI_ALL_ONLINE }, { 0x2a8004, 8191, RI_E1HE2_OFFLINE },
- { 0x2b0000, 1, RI_ALL_ONLINE }, { 0x2b0004, 15, RI_E1H_OFFLINE },
- { 0x2b0040, 1, RI_E1HE2_ONLINE }, { 0x2b0044, 239, RI_E1H_OFFLINE },
- { 0x2b0400, 1, RI_ALL_ONLINE }, { 0x2b0404, 255, RI_E1H_OFFLINE },
- { 0x2b0800, 1, RI_ALL_ONLINE }, { 0x2b0840, 1, RI_E1HE2_ONLINE },
- { 0x2b0c00, 1, RI_ALL_ONLINE }, { 0x2b1000, 1, RI_ALL_ONLINE },
- { 0x2b1040, 1, RI_E1HE2_ONLINE }, { 0x2b1400, 1, RI_ALL_ONLINE },
- { 0x2b1440, 1, RI_E1HE2_ONLINE }, { 0x2b1480, 1, RI_E1HE2_ONLINE },
- { 0x2b14c0, 1, RI_E1HE2_ONLINE }, { 0x2b1800, 128, RI_ALL_OFFLINE },
- { 0x2b1c00, 128, RI_ALL_OFFLINE }, { 0x2b2000, 1, RI_ALL_ONLINE },
- { 0x2b2400, 1, RI_E1HE2_ONLINE }, { 0x2b2404, 5631, RI_E2_OFFLINE },
- { 0x2b8000, 1, RI_ALL_ONLINE }, { 0x2b8040, 1, RI_ALL_ONLINE },
- { 0x2b8080, 1, RI_ALL_ONLINE }, { 0x2b80c0, 1, RI_ALL_ONLINE },
- { 0x2b8100, 1, RI_ALL_ONLINE }, { 0x2b8140, 1, RI_ALL_ONLINE },
- { 0x2b8180, 1, RI_ALL_ONLINE }, { 0x2b81c0, 1, RI_ALL_ONLINE },
- { 0x2b8200, 1, RI_ALL_ONLINE }, { 0x2b8240, 1, RI_ALL_ONLINE },
- { 0x2b8280, 1, RI_ALL_ONLINE }, { 0x2b82c0, 1, RI_ALL_ONLINE },
- { 0x2b8300, 1, RI_ALL_ONLINE }, { 0x2b8340, 1, RI_ALL_ONLINE },
- { 0x2b8380, 1, RI_ALL_ONLINE }, { 0x2b83c0, 1, RI_ALL_ONLINE },
- { 0x2b8400, 1, RI_ALL_ONLINE }, { 0x2b8440, 1, RI_ALL_ONLINE },
- { 0x2b8480, 1, RI_ALL_ONLINE }, { 0x2b84c0, 1, RI_ALL_ONLINE },
- { 0x2b8500, 1, RI_ALL_ONLINE }, { 0x2b8540, 1, RI_ALL_ONLINE },
- { 0x2b8580, 1, RI_ALL_ONLINE }, { 0x2b85c0, 19, RI_E2_ONLINE },
- { 0x2b8800, 1, RI_ALL_ONLINE }, { 0x2b8840, 1, RI_ALL_ONLINE },
- { 0x2b8880, 1, RI_ALL_ONLINE }, { 0x2b88c0, 1, RI_ALL_ONLINE },
- { 0x2b8900, 1, RI_ALL_ONLINE }, { 0x2b8940, 1, RI_ALL_ONLINE },
- { 0x2b8980, 1, RI_ALL_ONLINE }, { 0x2b89c0, 1, RI_ALL_ONLINE },
- { 0x2b8a00, 1, RI_ALL_ONLINE }, { 0x2b8a40, 1, RI_ALL_ONLINE },
- { 0x2b8a80, 1, RI_ALL_ONLINE }, { 0x2b8ac0, 1, RI_ALL_ONLINE },
- { 0x2b8b00, 1, RI_ALL_ONLINE }, { 0x2b8b40, 1, RI_ALL_ONLINE },
- { 0x2b8b80, 1, RI_ALL_ONLINE }, { 0x2b8bc0, 1, RI_ALL_ONLINE },
- { 0x2b8c00, 1, RI_ALL_ONLINE }, { 0x2b8c40, 1, RI_ALL_ONLINE },
- { 0x2b8c80, 1, RI_ALL_ONLINE }, { 0x2b8cc0, 1, RI_ALL_ONLINE },
- { 0x2b8cc4, 1, RI_E2_ONLINE }, { 0x2b8d00, 1, RI_ALL_ONLINE },
- { 0x2b8d40, 1, RI_ALL_ONLINE }, { 0x2b8d80, 1, RI_ALL_ONLINE },
- { 0x2b8dc0, 1, RI_ALL_ONLINE }, { 0x2b8e00, 1, RI_ALL_ONLINE },
- { 0x2b8e40, 1, RI_ALL_ONLINE }, { 0x2b8e80, 1, RI_ALL_ONLINE },
- { 0x2b8e84, 1, RI_E2_ONLINE }, { 0x2b8ec0, 1, RI_E1HE2_ONLINE },
- { 0x2b8f00, 1, RI_E1HE2_ONLINE }, { 0x2b8f40, 1, RI_E1HE2_ONLINE },
- { 0x2b8f80, 1, RI_E1HE2_ONLINE }, { 0x2b8fc0, 1, RI_E1HE2_ONLINE },
- { 0x2b8fc4, 2, RI_E2_ONLINE }, { 0x2b8fd0, 6, RI_E2_ONLINE },
- { 0x2b9000, 1, RI_E2_ONLINE }, { 0x2b9040, 3, RI_E2_ONLINE },
- { 0x2b9400, 14, RI_E2_ONLINE }, { 0x2b943c, 19, RI_E2_ONLINE },
- { 0x2b9490, 10, RI_E2_ONLINE }, { 0x2c0000, 2, RI_ALL_ONLINE },
- { 0x300000, 65, RI_ALL_ONLINE }, { 0x30014c, 2, RI_E1HE2_ONLINE },
- { 0x300200, 58, RI_ALL_ONLINE }, { 0x300340, 4, RI_ALL_ONLINE },
- { 0x300380, 1, RI_E2_ONLINE }, { 0x300388, 1, RI_E2_ONLINE },
- { 0x300390, 1, RI_E2_ONLINE }, { 0x300398, 1, RI_E2_ONLINE },
- { 0x3003a0, 1, RI_E2_ONLINE }, { 0x3003a8, 2, RI_E2_ONLINE },
- { 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_E1E1H_OFFLINE },
- { 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE },
- { 0x320000, 1, RI_ALL_ONLINE }, { 0x320004, 5631, RI_ALL_OFFLINE },
- { 0x325800, 2560, RI_E1HE2_OFFLINE }, { 0x328000, 1, RI_ALL_ONLINE },
- { 0x328004, 8191, RI_E1HE2_OFFLINE }, { 0x330000, 1, RI_ALL_ONLINE },
- { 0x330004, 15, RI_E1H_OFFLINE }, { 0x330040, 1, RI_E1HE2_ONLINE },
- { 0x330044, 239, RI_E1H_OFFLINE }, { 0x330400, 1, RI_ALL_ONLINE },
- { 0x330404, 255, RI_E1H_OFFLINE }, { 0x330800, 1, RI_ALL_ONLINE },
- { 0x330840, 1, RI_E1HE2_ONLINE }, { 0x330c00, 1, RI_ALL_ONLINE },
- { 0x331000, 1, RI_ALL_ONLINE }, { 0x331040, 1, RI_E1HE2_ONLINE },
- { 0x331400, 1, RI_ALL_ONLINE }, { 0x331440, 1, RI_E1HE2_ONLINE },
- { 0x331480, 1, RI_E1HE2_ONLINE }, { 0x3314c0, 1, RI_E1HE2_ONLINE },
- { 0x331800, 128, RI_ALL_OFFLINE }, { 0x331c00, 128, RI_ALL_OFFLINE },
- { 0x332000, 1, RI_ALL_ONLINE }, { 0x332400, 1, RI_E1HE2_ONLINE },
- { 0x332404, 5631, RI_E2_OFFLINE }, { 0x338000, 1, RI_ALL_ONLINE },
- { 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
- { 0x3380c0, 1, RI_ALL_ONLINE }, { 0x338100, 1, RI_ALL_ONLINE },
- { 0x338140, 1, RI_ALL_ONLINE }, { 0x338180, 1, RI_ALL_ONLINE },
- { 0x3381c0, 1, RI_ALL_ONLINE }, { 0x338200, 1, RI_ALL_ONLINE },
- { 0x338240, 1, RI_ALL_ONLINE }, { 0x338280, 1, RI_ALL_ONLINE },
- { 0x3382c0, 1, RI_ALL_ONLINE }, { 0x338300, 1, RI_ALL_ONLINE },
- { 0x338340, 1, RI_ALL_ONLINE }, { 0x338380, 1, RI_ALL_ONLINE },
- { 0x3383c0, 1, RI_ALL_ONLINE }, { 0x338400, 1, RI_ALL_ONLINE },
- { 0x338440, 1, RI_ALL_ONLINE }, { 0x338480, 1, RI_ALL_ONLINE },
- { 0x3384c0, 1, RI_ALL_ONLINE }, { 0x338500, 1, RI_ALL_ONLINE },
- { 0x338540, 1, RI_ALL_ONLINE }, { 0x338580, 1, RI_ALL_ONLINE },
- { 0x3385c0, 19, RI_E2_ONLINE }, { 0x338800, 1, RI_ALL_ONLINE },
- { 0x338840, 1, RI_ALL_ONLINE }, { 0x338880, 1, RI_ALL_ONLINE },
- { 0x3388c0, 1, RI_ALL_ONLINE }, { 0x338900, 1, RI_ALL_ONLINE },
- { 0x338940, 1, RI_ALL_ONLINE }, { 0x338980, 1, RI_ALL_ONLINE },
- { 0x3389c0, 1, RI_ALL_ONLINE }, { 0x338a00, 1, RI_ALL_ONLINE },
- { 0x338a40, 1, RI_ALL_ONLINE }, { 0x338a80, 1, RI_ALL_ONLINE },
- { 0x338ac0, 1, RI_ALL_ONLINE }, { 0x338b00, 1, RI_ALL_ONLINE },
- { 0x338b40, 1, RI_ALL_ONLINE }, { 0x338b80, 1, RI_ALL_ONLINE },
- { 0x338bc0, 1, RI_ALL_ONLINE }, { 0x338c00, 1, RI_ALL_ONLINE },
- { 0x338c40, 1, RI_ALL_ONLINE }, { 0x338c80, 1, RI_ALL_ONLINE },
- { 0x338cc0, 1, RI_ALL_ONLINE }, { 0x338cc4, 1, RI_E2_ONLINE },
- { 0x338d00, 1, RI_ALL_ONLINE }, { 0x338d40, 1, RI_ALL_ONLINE },
- { 0x338d80, 1, RI_ALL_ONLINE }, { 0x338dc0, 1, RI_ALL_ONLINE },
- { 0x338e00, 1, RI_ALL_ONLINE }, { 0x338e40, 1, RI_ALL_ONLINE },
- { 0x338e80, 1, RI_ALL_ONLINE }, { 0x338e84, 1, RI_E2_ONLINE },
- { 0x338ec0, 1, RI_E1HE2_ONLINE }, { 0x338f00, 1, RI_E1HE2_ONLINE },
- { 0x338f40, 1, RI_E1HE2_ONLINE }, { 0x338f80, 1, RI_E1HE2_ONLINE },
- { 0x338fc0, 1, RI_E1HE2_ONLINE }, { 0x338fc4, 2, RI_E2_ONLINE },
- { 0x338fd0, 6, RI_E2_ONLINE }, { 0x339000, 1, RI_E2_ONLINE },
- { 0x339040, 3, RI_E2_ONLINE }, { 0x340000, 2, RI_ALL_ONLINE },
-};
-
-#define IDLE_REGS_COUNT 237
-static const struct reg_addr idle_addrs[IDLE_REGS_COUNT] = {
- { 0x2104, 1, RI_ALL_ONLINE }, { 0x2110, 2, RI_ALL_ONLINE },
- { 0x211c, 8, RI_ALL_ONLINE }, { 0x2814, 1, RI_ALL_ONLINE },
- { 0x281c, 2, RI_ALL_ONLINE }, { 0x2854, 1, RI_ALL_ONLINE },
- { 0x285c, 1, RI_ALL_ONLINE }, { 0x9010, 7, RI_E2_ONLINE },
- { 0x9030, 1, RI_E2_ONLINE }, { 0x9068, 16, RI_E2_ONLINE },
- { 0x9230, 2, RI_E2_ONLINE }, { 0x9244, 1, RI_E2_ONLINE },
- { 0x9298, 1, RI_E2_ONLINE }, { 0x92a8, 1, RI_E2_ONLINE },
- { 0xa38c, 1, RI_ALL_ONLINE }, { 0xa3c4, 1, RI_E1HE2_ONLINE },
- { 0xa408, 1, RI_ALL_ONLINE }, { 0xa42c, 12, RI_ALL_ONLINE },
- { 0xa600, 5, RI_E1HE2_ONLINE }, { 0xa618, 1, RI_E1HE2_ONLINE },
- { 0xa714, 1, RI_E2_ONLINE }, { 0xa720, 1, RI_E2_ONLINE },
- { 0xa750, 1, RI_E2_ONLINE }, { 0xc09c, 1, RI_E1E1H_ONLINE },
- { 0x103b0, 1, RI_ALL_ONLINE }, { 0x103c0, 1, RI_ALL_ONLINE },
- { 0x103d0, 1, RI_E1H_ONLINE }, { 0x183bc, 1, RI_E2_ONLINE },
- { 0x183cc, 1, RI_E2_ONLINE }, { 0x2021c, 11, RI_ALL_ONLINE },
- { 0x202a8, 1, RI_ALL_ONLINE }, { 0x202b8, 1, RI_ALL_ONLINE },
- { 0x20404, 1, RI_ALL_ONLINE }, { 0x2040c, 2, RI_ALL_ONLINE },
- { 0x2041c, 2, RI_ALL_ONLINE }, { 0x40154, 14, RI_ALL_ONLINE },
- { 0x40198, 1, RI_ALL_ONLINE }, { 0x404ac, 1, RI_ALL_ONLINE },
- { 0x404bc, 1, RI_ALL_ONLINE }, { 0x42290, 1, RI_ALL_ONLINE },
- { 0x422a0, 1, RI_ALL_ONLINE }, { 0x422b0, 1, RI_ALL_ONLINE },
- { 0x42548, 1, RI_ALL_ONLINE }, { 0x42550, 1, RI_ALL_ONLINE },
- { 0x42558, 1, RI_ALL_ONLINE }, { 0x50160, 8, RI_ALL_ONLINE },
- { 0x501d0, 1, RI_ALL_ONLINE }, { 0x501e0, 1, RI_ALL_ONLINE },
- { 0x50204, 1, RI_ALL_ONLINE }, { 0x5020c, 2, RI_ALL_ONLINE },
- { 0x5021c, 1, RI_ALL_ONLINE }, { 0x60090, 1, RI_ALL_ONLINE },
- { 0x6011c, 1, RI_ALL_ONLINE }, { 0x6012c, 1, RI_ALL_ONLINE },
- { 0xc101c, 1, RI_ALL_ONLINE }, { 0xc102c, 1, RI_ALL_ONLINE },
- { 0xc2290, 1, RI_ALL_ONLINE }, { 0xc22a0, 1, RI_ALL_ONLINE },
- { 0xc22b0, 1, RI_ALL_ONLINE }, { 0xc2548, 1, RI_ALL_ONLINE },
- { 0xc2550, 1, RI_ALL_ONLINE }, { 0xc2558, 1, RI_ALL_ONLINE },
- { 0xc4294, 1, RI_ALL_ONLINE }, { 0xc42a4, 1, RI_ALL_ONLINE },
- { 0xc42b4, 1, RI_ALL_ONLINE }, { 0xc4550, 1, RI_ALL_ONLINE },
- { 0xc4558, 1, RI_ALL_ONLINE }, { 0xc4560, 1, RI_ALL_ONLINE },
- { 0xd016c, 8, RI_ALL_ONLINE }, { 0xd01d8, 1, RI_ALL_ONLINE },
- { 0xd01e8, 1, RI_ALL_ONLINE }, { 0xd0204, 1, RI_ALL_ONLINE },
- { 0xd020c, 3, RI_ALL_ONLINE }, { 0xe0154, 8, RI_ALL_ONLINE },
- { 0xe01c8, 1, RI_ALL_ONLINE }, { 0xe01d8, 1, RI_ALL_ONLINE },
- { 0xe0204, 1, RI_ALL_ONLINE }, { 0xe020c, 2, RI_ALL_ONLINE },
- { 0xe021c, 2, RI_ALL_ONLINE }, { 0x101014, 1, RI_ALL_ONLINE },
- { 0x101030, 1, RI_ALL_ONLINE }, { 0x101040, 1, RI_ALL_ONLINE },
- { 0x102058, 1, RI_ALL_ONLINE }, { 0x102080, 16, RI_ALL_ONLINE },
- { 0x103004, 2, RI_ALL_ONLINE }, { 0x103068, 1, RI_ALL_ONLINE },
- { 0x103078, 1, RI_ALL_ONLINE }, { 0x103088, 1, RI_ALL_ONLINE },
- { 0x10309c, 2, RI_E1HE2_ONLINE }, { 0x1030b8, 2, RI_E2_ONLINE },
- { 0x1030cc, 1, RI_E2_ONLINE }, { 0x1030e0, 1, RI_E2_ONLINE },
- { 0x104004, 1, RI_ALL_ONLINE }, { 0x104018, 1, RI_ALL_ONLINE },
- { 0x104020, 1, RI_ALL_ONLINE }, { 0x10403c, 1, RI_ALL_ONLINE },
- { 0x1040fc, 1, RI_ALL_ONLINE }, { 0x10410c, 1, RI_ALL_ONLINE },
- { 0x104400, 64, RI_ALL_ONLINE }, { 0x104800, 64, RI_ALL_ONLINE },
- { 0x105000, 256, RI_ALL_ONLINE }, { 0x108094, 1, RI_E1E1H_ONLINE },
- { 0x1201b0, 2, RI_ALL_ONLINE }, { 0x12032c, 1, RI_ALL_ONLINE },
- { 0x12036c, 3, RI_ALL_ONLINE }, { 0x120408, 2, RI_ALL_ONLINE },
- { 0x120414, 15, RI_ALL_ONLINE }, { 0x120478, 2, RI_ALL_ONLINE },
- { 0x12052c, 1, RI_ALL_ONLINE }, { 0x120564, 3, RI_ALL_ONLINE },
- { 0x12057c, 1, RI_ALL_ONLINE }, { 0x12058c, 1, RI_ALL_ONLINE },
- { 0x120608, 1, RI_E1HE2_ONLINE }, { 0x120738, 1, RI_E2_ONLINE },
- { 0x120778, 2, RI_E2_ONLINE }, { 0x120808, 3, RI_ALL_ONLINE },
- { 0x120818, 1, RI_ALL_ONLINE }, { 0x120820, 1, RI_ALL_ONLINE },
- { 0x120828, 1, RI_ALL_ONLINE }, { 0x120830, 1, RI_ALL_ONLINE },
- { 0x120838, 1, RI_ALL_ONLINE }, { 0x120840, 1, RI_ALL_ONLINE },
- { 0x120848, 1, RI_ALL_ONLINE }, { 0x120850, 1, RI_ALL_ONLINE },
- { 0x120858, 1, RI_ALL_ONLINE }, { 0x120860, 1, RI_ALL_ONLINE },
- { 0x120868, 1, RI_ALL_ONLINE }, { 0x120870, 1, RI_ALL_ONLINE },
- { 0x120878, 1, RI_ALL_ONLINE }, { 0x120880, 1, RI_ALL_ONLINE },
- { 0x120888, 1, RI_ALL_ONLINE }, { 0x120890, 1, RI_ALL_ONLINE },
- { 0x120898, 1, RI_ALL_ONLINE }, { 0x1208a0, 1, RI_ALL_ONLINE },
- { 0x1208a8, 1, RI_ALL_ONLINE }, { 0x1208b0, 1, RI_ALL_ONLINE },
- { 0x1208b8, 1, RI_ALL_ONLINE }, { 0x1208c0, 1, RI_ALL_ONLINE },
- { 0x1208c8, 1, RI_ALL_ONLINE }, { 0x1208d0, 1, RI_ALL_ONLINE },
- { 0x1208d8, 1, RI_ALL_ONLINE }, { 0x1208e0, 1, RI_ALL_ONLINE },
- { 0x1208e8, 1, RI_ALL_ONLINE }, { 0x1208f0, 1, RI_ALL_ONLINE },
- { 0x1208f8, 1, RI_ALL_ONLINE }, { 0x120900, 1, RI_ALL_ONLINE },
- { 0x120908, 1, RI_ALL_ONLINE }, { 0x120940, 5, RI_E2_ONLINE },
- { 0x130030, 1, RI_E2_ONLINE }, { 0x13004c, 3, RI_E2_ONLINE },
- { 0x130064, 2, RI_E2_ONLINE }, { 0x13009c, 1, RI_E2_ONLINE },
- { 0x130130, 1, RI_E2_ONLINE }, { 0x13016c, 1, RI_E2_ONLINE },
- { 0x130300, 1, RI_E2_ONLINE }, { 0x130480, 1, RI_E2_ONLINE },
- { 0x14005c, 2, RI_ALL_ONLINE }, { 0x1400d0, 2, RI_ALL_ONLINE },
- { 0x1400e0, 1, RI_ALL_ONLINE }, { 0x1401c8, 1, RI_ALL_ONLINE },
- { 0x140200, 6, RI_ALL_ONLINE }, { 0x16101c, 1, RI_ALL_ONLINE },
- { 0x16102c, 1, RI_ALL_ONLINE }, { 0x164014, 2, RI_ALL_ONLINE },
- { 0x1640f0, 1, RI_ALL_ONLINE }, { 0x166290, 1, RI_ALL_ONLINE },
- { 0x1662a0, 1, RI_ALL_ONLINE }, { 0x1662b0, 1, RI_ALL_ONLINE },
- { 0x166548, 1, RI_ALL_ONLINE }, { 0x166550, 1, RI_ALL_ONLINE },
- { 0x166558, 1, RI_ALL_ONLINE }, { 0x168000, 1, RI_ALL_ONLINE },
- { 0x168008, 1, RI_ALL_ONLINE }, { 0x168010, 1, RI_ALL_ONLINE },
- { 0x168018, 1, RI_ALL_ONLINE }, { 0x168028, 2, RI_ALL_ONLINE },
- { 0x168058, 4, RI_ALL_ONLINE }, { 0x168070, 1, RI_ALL_ONLINE },
- { 0x168238, 1, RI_ALL_ONLINE }, { 0x1682d0, 2, RI_ALL_ONLINE },
- { 0x1682e0, 1, RI_ALL_ONLINE }, { 0x168300, 2, RI_E1E1H_ONLINE },
- { 0x168308, 65, RI_ALL_ONLINE }, { 0x168410, 2, RI_ALL_ONLINE },
- { 0x168438, 1, RI_ALL_ONLINE }, { 0x168448, 1, RI_ALL_ONLINE },
- { 0x168a00, 128, RI_ALL_ONLINE }, { 0x16e200, 128, RI_E1H_ONLINE },
- { 0x16e404, 2, RI_E1H_ONLINE }, { 0x16e584, 64, RI_E1H_ONLINE },
- { 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 4, RI_E1H_ONLINE },
- { 0x16e6fc, 4, RI_E2_ONLINE }, { 0x1700a4, 1, RI_ALL_ONLINE },
- { 0x1700ac, 2, RI_ALL_ONLINE }, { 0x1700c0, 1, RI_ALL_ONLINE },
- { 0x170174, 1, RI_ALL_ONLINE }, { 0x170184, 1, RI_ALL_ONLINE },
- { 0x1800f4, 1, RI_ALL_ONLINE }, { 0x180104, 1, RI_ALL_ONLINE },
- { 0x180114, 1, RI_ALL_ONLINE }, { 0x180124, 1, RI_ALL_ONLINE },
- { 0x18026c, 1, RI_ALL_ONLINE }, { 0x1802a0, 1, RI_ALL_ONLINE },
- { 0x1b8000, 1, RI_ALL_ONLINE }, { 0x1b8040, 1, RI_ALL_ONLINE },
- { 0x1b8080, 1, RI_ALL_ONLINE }, { 0x1b80c0, 1, RI_ALL_ONLINE },
- { 0x200104, 1, RI_ALL_ONLINE }, { 0x200114, 1, RI_ALL_ONLINE },
- { 0x200124, 1, RI_ALL_ONLINE }, { 0x200134, 1, RI_ALL_ONLINE },
- { 0x20026c, 1, RI_ALL_ONLINE }, { 0x2002a0, 1, RI_ALL_ONLINE },
- { 0x238000, 1, RI_ALL_ONLINE }, { 0x238040, 1, RI_ALL_ONLINE },
- { 0x238080, 1, RI_ALL_ONLINE }, { 0x2380c0, 1, RI_ALL_ONLINE },
- { 0x280104, 1, RI_ALL_ONLINE }, { 0x280114, 1, RI_ALL_ONLINE },
- { 0x280124, 1, RI_ALL_ONLINE }, { 0x280134, 1, RI_ALL_ONLINE },
- { 0x28026c, 1, RI_ALL_ONLINE }, { 0x2802a0, 1, RI_ALL_ONLINE },
- { 0x2b8000, 1, RI_ALL_ONLINE }, { 0x2b8040, 1, RI_ALL_ONLINE },
- { 0x2b8080, 1, RI_ALL_ONLINE }, { 0x300104, 1, RI_ALL_ONLINE },
- { 0x300114, 1, RI_ALL_ONLINE }, { 0x300124, 1, RI_ALL_ONLINE },
- { 0x300134, 1, RI_ALL_ONLINE }, { 0x30026c, 1, RI_ALL_ONLINE },
- { 0x3002a0, 1, RI_ALL_ONLINE }, { 0x338000, 1, RI_ALL_ONLINE },
- { 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
- { 0x3380c0, 1, RI_ALL_ONLINE }
-};
-
-#define WREGS_COUNT_E1 1
-static const u32 read_reg_e1_0[] = { 0x1b1000 };
-
-static const struct wreg_addr wreg_addrs_e1[WREGS_COUNT_E1] = {
- { 0x1b0c00, 192, 1, read_reg_e1_0, RI_E1_OFFLINE }
-};
-
-#define WREGS_COUNT_E1H 1
-static const u32 read_reg_e1h_0[] = { 0x1b1040, 0x1b1000 };
-
-static const struct wreg_addr wreg_addrs_e1h[WREGS_COUNT_E1H] = {
- { 0x1b0c00, 256, 2, read_reg_e1h_0, RI_E1H_OFFLINE }
+static const struct reg_addr reg_addrs[] = {
+ { 0x2000, 341, RI_ALL_ONLINE },
+ { 0x2800, 103, RI_ALL_ONLINE },
+ { 0x3000, 287, RI_ALL_ONLINE },
+ { 0x3800, 331, RI_ALL_ONLINE },
+ { 0x8800, 6, RI_ALL_ONLINE },
+ { 0x8818, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x9000, 147, RI_E2E3E3B0_ONLINE },
+ { 0x924c, 1, RI_E2_ONLINE },
+ { 0x9250, 16, RI_E2E3E3B0_ONLINE },
+ { 0x9400, 33, RI_E2E3E3B0_ONLINE },
+ { 0x9484, 5, RI_E3E3B0_ONLINE },
+ { 0xa000, 27, RI_ALL_ONLINE },
+ { 0xa06c, 1, RI_E1E1H_ONLINE },
+ { 0xa070, 71, RI_ALL_ONLINE },
+ { 0xa18c, 4, RI_E1E1H_ONLINE },
+ { 0xa19c, 62, RI_ALL_ONLINE },
+ { 0xa294, 2, RI_E1E1H_ONLINE },
+ { 0xa29c, 2, RI_ALL_ONLINE },
+ { 0xa2a4, 2, RI_E1E1HE2_ONLINE },
+ { 0xa2ac, 52, RI_ALL_ONLINE },
+ { 0xa39c, 7, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa3b8, 2, RI_E3E3B0_ONLINE },
+ { 0xa3c0, 3, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa3d0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa3d8, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa3e0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa3e8, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa3f0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa3f8, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa400, 40, RI_ALL_ONLINE },
+ { 0xa4a0, 1, RI_E1E1HE2_ONLINE },
+ { 0xa4a4, 2, RI_ALL_ONLINE },
+ { 0xa4ac, 2, RI_E1E1H_ONLINE },
+ { 0xa4b4, 1, RI_E1E1HE2_ONLINE },
+ { 0xa4b8, 2, RI_E1E1H_ONLINE },
+ { 0xa4c0, 3, RI_ALL_ONLINE },
+ { 0xa4cc, 5, RI_E1E1H_ONLINE },
+ { 0xa4e0, 3, RI_ALL_ONLINE },
+ { 0xa4fc, 2, RI_ALL_ONLINE },
+ { 0xa504, 1, RI_E1E1H_ONLINE },
+ { 0xa508, 3, RI_ALL_ONLINE },
+ { 0xa518, 1, RI_ALL_ONLINE },
+ { 0xa520, 1, RI_ALL_ONLINE },
+ { 0xa528, 1, RI_ALL_ONLINE },
+ { 0xa530, 1, RI_ALL_ONLINE },
+ { 0xa538, 1, RI_ALL_ONLINE },
+ { 0xa540, 1, RI_ALL_ONLINE },
+ { 0xa548, 1, RI_E1E1H_ONLINE },
+ { 0xa550, 1, RI_E1E1H_ONLINE },
+ { 0xa558, 1, RI_E1E1H_ONLINE },
+ { 0xa560, 1, RI_E1E1H_ONLINE },
+ { 0xa568, 1, RI_E1E1H_ONLINE },
+ { 0xa570, 1, RI_ALL_ONLINE },
+ { 0xa580, 1, RI_ALL_ONLINE },
+ { 0xa590, 1, RI_ALL_ONLINE },
+ { 0xa5a0, 1, RI_E1E1HE2_ONLINE },
+ { 0xa5c0, 1, RI_ALL_ONLINE },
+ { 0xa5e0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa5e8, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa5f0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa5f8, 1, RI_E1HE2_ONLINE },
+ { 0xa5fc, 9, RI_E1HE2E3E3B0_ONLINE },
+ { 0xa620, 6, RI_E2E3E3B0_ONLINE },
+ { 0xa638, 20, RI_E2_ONLINE },
+ { 0xa688, 42, RI_E2E3E3B0_ONLINE },
+ { 0xa730, 1, RI_E2_ONLINE },
+ { 0xa734, 2, RI_E2E3E3B0_ONLINE },
+ { 0xa73c, 4, RI_E2_ONLINE },
+ { 0xa74c, 5, RI_E2E3E3B0_ONLINE },
+ { 0xa760, 5, RI_E2_ONLINE },
+ { 0xa774, 7, RI_E2E3E3B0_ONLINE },
+ { 0xa790, 15, RI_E2_ONLINE },
+ { 0xa7cc, 4, RI_E2E3E3B0_ONLINE },
+ { 0xa7e0, 6, RI_E3E3B0_ONLINE },
+ { 0xa800, 18, RI_E2_ONLINE },
+ { 0xa848, 33, RI_E2E3E3B0_ONLINE },
+ { 0xa8cc, 2, RI_E3E3B0_ONLINE },
+ { 0xa8d4, 4, RI_E2E3E3B0_ONLINE },
+ { 0xa8e4, 1, RI_E3E3B0_ONLINE },
+ { 0xa8e8, 1, RI_E2E3E3B0_ONLINE },
+ { 0xa8f0, 1, RI_E2E3E3B0_ONLINE },
+ { 0xa8f8, 30, RI_E3E3B0_ONLINE },
+ { 0xa974, 73, RI_E3E3B0_ONLINE },
+ { 0xac30, 1, RI_E3E3B0_ONLINE },
+ { 0xac40, 1, RI_E3E3B0_ONLINE },
+ { 0xac50, 1, RI_E3E3B0_ONLINE },
+ { 0xac60, 1, RI_E3B0_ONLINE },
+ { 0x10000, 9, RI_ALL_ONLINE },
+ { 0x10024, 1, RI_E1E1HE2_ONLINE },
+ { 0x10028, 5, RI_ALL_ONLINE },
+ { 0x1003c, 6, RI_E1E1HE2_ONLINE },
+ { 0x10054, 20, RI_ALL_ONLINE },
+ { 0x100a4, 4, RI_E1E1HE2_ONLINE },
+ { 0x100b4, 11, RI_ALL_ONLINE },
+ { 0x100e0, 4, RI_E1E1HE2_ONLINE },
+ { 0x100f0, 8, RI_ALL_ONLINE },
+ { 0x10110, 6, RI_E1E1HE2_ONLINE },
+ { 0x10128, 110, RI_ALL_ONLINE },
+ { 0x102e0, 4, RI_E1E1HE2_ONLINE },
+ { 0x102f0, 18, RI_ALL_ONLINE },
+ { 0x10338, 20, RI_E1E1HE2_ONLINE },
+ { 0x10388, 10, RI_ALL_ONLINE },
+ { 0x10400, 6, RI_E1E1HE2_ONLINE },
+ { 0x10418, 6, RI_ALL_ONLINE },
+ { 0x10430, 10, RI_E1E1HE2_ONLINE },
+ { 0x10458, 22, RI_ALL_ONLINE },
+ { 0x104b0, 12, RI_E1E1HE2_ONLINE },
+ { 0x104e0, 1, RI_ALL_ONLINE },
+ { 0x104e8, 2, RI_ALL_ONLINE },
+ { 0x104f4, 2, RI_ALL_ONLINE },
+ { 0x10500, 146, RI_ALL_ONLINE },
+ { 0x10750, 2, RI_E1E1HE2_ONLINE },
+ { 0x10760, 2, RI_E1E1HE2_ONLINE },
+ { 0x10770, 2, RI_E1E1HE2_ONLINE },
+ { 0x10780, 2, RI_E1E1HE2_ONLINE },
+ { 0x10790, 2, RI_ALL_ONLINE },
+ { 0x107a0, 2, RI_E1E1HE2_ONLINE },
+ { 0x107b0, 2, RI_E1E1HE2_ONLINE },
+ { 0x107c0, 2, RI_E1E1HE2_ONLINE },
+ { 0x107d0, 2, RI_E1E1HE2_ONLINE },
+ { 0x107e0, 2, RI_ALL_ONLINE },
+ { 0x10880, 2, RI_ALL_ONLINE },
+ { 0x10900, 2, RI_ALL_ONLINE },
+ { 0x16000, 1, RI_E1HE2_ONLINE },
+ { 0x16004, 25, RI_E1HE2E3E3B0_ONLINE },
+ { 0x16070, 8, RI_E1HE2E3E3B0_ONLINE },
+ { 0x16090, 4, RI_E1HE2E3_ONLINE },
+ { 0x160a0, 6, RI_E1HE2E3E3B0_ONLINE },
+ { 0x160c0, 7, RI_E1HE2E3E3B0_ONLINE },
+ { 0x160dc, 2, RI_E1HE2_ONLINE },
+ { 0x160e4, 10, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1610c, 2, RI_E1HE2_ONLINE },
+ { 0x16114, 6, RI_E1HE2E3E3B0_ONLINE },
+ { 0x16140, 48, RI_E1HE2E3E3B0_ONLINE },
+ { 0x16204, 5, RI_E1HE2E3E3B0_ONLINE },
+ { 0x18000, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x18008, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x18010, 35, RI_E2E3E3B0_ONLINE },
+ { 0x180a4, 2, RI_E2E3E3B0_ONLINE },
+ { 0x180c0, 9, RI_E2E3E3B0_ONLINE },
+ { 0x180e4, 1, RI_E2E3_ONLINE },
+ { 0x180e8, 2, RI_E2E3E3B0_ONLINE },
+ { 0x180f0, 1, RI_E2E3_ONLINE },
+ { 0x180f4, 79, RI_E2E3E3B0_ONLINE },
+ { 0x18230, 1, RI_E2E3_ONLINE },
+ { 0x18234, 2, RI_E2E3E3B0_ONLINE },
+ { 0x1823c, 1, RI_E2E3_ONLINE },
+ { 0x18240, 13, RI_E2E3E3B0_ONLINE },
+ { 0x18274, 1, RI_E2_ONLINE },
+ { 0x18278, 81, RI_E2E3E3B0_ONLINE },
+ { 0x18440, 63, RI_E2E3E3B0_ONLINE },
+ { 0x18570, 42, RI_E3E3B0_ONLINE },
+ { 0x18618, 25, RI_E3B0_ONLINE },
+ { 0x18680, 44, RI_E3B0_ONLINE },
+ { 0x18748, 12, RI_E3B0_ONLINE },
+ { 0x18788, 1, RI_E3B0_ONLINE },
+ { 0x1879c, 6, RI_E3B0_ONLINE },
+ { 0x187c4, 51, RI_E3B0_ONLINE },
+ { 0x18a00, 48, RI_E3B0_ONLINE },
+ { 0x20000, 24, RI_ALL_ONLINE },
+ { 0x20060, 8, RI_ALL_ONLINE },
+ { 0x20080, 94, RI_ALL_ONLINE },
+ { 0x201f8, 1, RI_E1E1H_ONLINE },
+ { 0x201fc, 1, RI_ALL_ONLINE },
+ { 0x20200, 1, RI_E1E1H_ONLINE },
+ { 0x20204, 1, RI_ALL_ONLINE },
+ { 0x20208, 1, RI_E1E1H_ONLINE },
+ { 0x2020c, 39, RI_ALL_ONLINE },
+ { 0x202c8, 1, RI_E2E3E3B0_ONLINE },
+ { 0x202d8, 4, RI_E2E3E3B0_ONLINE },
+ { 0x202f0, 1, RI_E3B0_ONLINE },
+ { 0x20400, 2, RI_ALL_ONLINE },
+ { 0x2040c, 8, RI_ALL_ONLINE },
+ { 0x2042c, 18, RI_E1HE2E3E3B0_ONLINE },
+ { 0x20480, 1, RI_ALL_ONLINE },
+ { 0x20500, 1, RI_ALL_ONLINE },
+ { 0x20600, 1, RI_ALL_ONLINE },
+ { 0x28000, 1, RI_ALL_ONLINE },
+ { 0x28004, 8191, RI_ALL_OFFLINE },
+ { 0x30000, 1, RI_ALL_ONLINE },
+ { 0x30004, 16383, RI_ALL_OFFLINE },
+ { 0x40000, 98, RI_ALL_ONLINE },
+ { 0x401a8, 8, RI_E1HE2E3E3B0_ONLINE },
+ { 0x401c8, 1, RI_E1H_ONLINE },
+ { 0x401cc, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x401d4, 2, RI_E2E3E3B0_ONLINE },
+ { 0x40200, 4, RI_ALL_ONLINE },
+ { 0x40220, 6, RI_E2E3E3B0_ONLINE },
+ { 0x40238, 8, RI_E2E3_ONLINE },
+ { 0x40258, 4, RI_E2E3E3B0_ONLINE },
+ { 0x40268, 2, RI_E3E3B0_ONLINE },
+ { 0x40270, 17, RI_E3B0_ONLINE },
+ { 0x40400, 43, RI_ALL_ONLINE },
+ { 0x404cc, 3, RI_E1HE2E3E3B0_ONLINE },
+ { 0x404e0, 1, RI_E2E3E3B0_ONLINE },
+ { 0x40500, 2, RI_ALL_ONLINE },
+ { 0x40510, 2, RI_ALL_ONLINE },
+ { 0x40520, 2, RI_ALL_ONLINE },
+ { 0x40530, 2, RI_ALL_ONLINE },
+ { 0x40540, 2, RI_ALL_ONLINE },
+ { 0x40550, 10, RI_E2E3E3B0_ONLINE },
+ { 0x40610, 2, RI_E2E3E3B0_ONLINE },
+ { 0x42000, 164, RI_ALL_ONLINE },
+ { 0x422c0, 4, RI_E2E3E3B0_ONLINE },
+ { 0x422d4, 5, RI_E1HE2E3E3B0_ONLINE },
+ { 0x422e8, 1, RI_E2E3E3B0_ONLINE },
+ { 0x42400, 49, RI_ALL_ONLINE },
+ { 0x424c8, 38, RI_ALL_ONLINE },
+ { 0x42568, 2, RI_ALL_ONLINE },
+ { 0x42640, 5, RI_E2E3E3B0_ONLINE },
+ { 0x42800, 1, RI_ALL_ONLINE },
+ { 0x50000, 1, RI_ALL_ONLINE },
+ { 0x50004, 19, RI_ALL_ONLINE },
+ { 0x50050, 8, RI_ALL_ONLINE },
+ { 0x50070, 88, RI_ALL_ONLINE },
+ { 0x501f0, 4, RI_E1HE2E3E3B0_ONLINE },
+ { 0x50200, 2, RI_ALL_ONLINE },
+ { 0x5020c, 7, RI_ALL_ONLINE },
+ { 0x50228, 6, RI_E1HE2E3E3B0_ONLINE },
+ { 0x50240, 1, RI_ALL_ONLINE },
+ { 0x50280, 1, RI_ALL_ONLINE },
+ { 0x50300, 1, RI_E2E3E3B0_ONLINE },
+ { 0x5030c, 1, RI_E2E3E3B0_ONLINE },
+ { 0x50318, 1, RI_E2E3E3B0_ONLINE },
+ { 0x5031c, 1, RI_E2E3E3B0_ONLINE },
+ { 0x50320, 2, RI_E2E3E3B0_ONLINE },
+ { 0x50330, 1, RI_E3B0_ONLINE },
+ { 0x52000, 1, RI_ALL_ONLINE },
+ { 0x54000, 1, RI_ALL_ONLINE },
+ { 0x54004, 3327, RI_ALL_OFFLINE },
+ { 0x58000, 1, RI_ALL_ONLINE },
+ { 0x58004, 8191, RI_E1E1H_OFFLINE },
+ { 0x60000, 26, RI_ALL_ONLINE },
+ { 0x60068, 8, RI_E1E1H_ONLINE },
+ { 0x60088, 12, RI_ALL_ONLINE },
+ { 0x600b8, 9, RI_E1E1H_ONLINE },
+ { 0x600dc, 1, RI_ALL_ONLINE },
+ { 0x600e0, 5, RI_E1E1H_ONLINE },
+ { 0x600f4, 1, RI_E1E1HE2_ONLINE },
+ { 0x600f8, 1, RI_E1E1H_ONLINE },
+ { 0x600fc, 8, RI_ALL_ONLINE },
+ { 0x6013c, 24, RI_E1H_ONLINE },
+ { 0x6019c, 2, RI_E2E3E3B0_ONLINE },
+ { 0x601ac, 18, RI_E2E3E3B0_ONLINE },
+ { 0x60200, 1, RI_ALL_ONLINE },
+ { 0x60204, 2, RI_ALL_OFFLINE },
+ { 0x60210, 13, RI_E2E3E3B0_ONLINE },
+ { 0x60244, 16, RI_E3B0_ONLINE },
+ { 0x61000, 1, RI_ALL_ONLINE },
+ { 0x61004, 511, RI_ALL_OFFLINE },
+ { 0x61800, 512, RI_E3E3B0_OFFLINE },
+ { 0x70000, 8, RI_ALL_ONLINE },
+ { 0x70020, 8184, RI_ALL_OFFLINE },
+ { 0x78000, 8192, RI_E3E3B0_OFFLINE },
+ { 0x85000, 3, RI_ALL_ONLINE },
+ { 0x8501c, 7, RI_ALL_ONLINE },
+ { 0x85048, 1, RI_ALL_ONLINE },
+ { 0x85200, 32, RI_ALL_ONLINE },
+ { 0xb0000, 16384, RI_E1H_ONLINE },
+ { 0xc1000, 7, RI_ALL_ONLINE },
+ { 0xc103c, 2, RI_E2E3E3B0_ONLINE },
+ { 0xc1800, 2, RI_ALL_ONLINE },
+ { 0xc2000, 164, RI_ALL_ONLINE },
+ { 0xc22c0, 5, RI_E2E3E3B0_ONLINE },
+ { 0xc22d8, 4, RI_E2E3E3B0_ONLINE },
+ { 0xc2400, 49, RI_ALL_ONLINE },
+ { 0xc24c8, 38, RI_ALL_ONLINE },
+ { 0xc2568, 2, RI_ALL_ONLINE },
+ { 0xc2600, 1, RI_ALL_ONLINE },
+ { 0xc4000, 165, RI_ALL_ONLINE },
+ { 0xc42d8, 2, RI_E2E3E3B0_ONLINE },
+ { 0xc42e0, 7, RI_E1HE2E3E3B0_ONLINE },
+ { 0xc42fc, 1, RI_E2E3E3B0_ONLINE },
+ { 0xc4400, 51, RI_ALL_ONLINE },
+ { 0xc44d0, 38, RI_ALL_ONLINE },
+ { 0xc4570, 2, RI_ALL_ONLINE },
+ { 0xc4578, 5, RI_E2E3E3B0_ONLINE },
+ { 0xc4600, 1, RI_ALL_ONLINE },
+ { 0xd0000, 19, RI_ALL_ONLINE },
+ { 0xd004c, 8, RI_ALL_ONLINE },
+ { 0xd006c, 91, RI_ALL_ONLINE },
+ { 0xd01fc, 1, RI_E2E3E3B0_ONLINE },
+ { 0xd0200, 2, RI_ALL_ONLINE },
+ { 0xd020c, 7, RI_ALL_ONLINE },
+ { 0xd0228, 18, RI_E1HE2E3E3B0_ONLINE },
+ { 0xd0280, 1, RI_ALL_ONLINE },
+ { 0xd0300, 1, RI_ALL_ONLINE },
+ { 0xd0400, 1, RI_ALL_ONLINE },
+ { 0xd0818, 1, RI_E3B0_ONLINE },
+ { 0xd4000, 1, RI_ALL_ONLINE },
+ { 0xd4004, 2559, RI_ALL_OFFLINE },
+ { 0xd8000, 1, RI_ALL_ONLINE },
+ { 0xd8004, 8191, RI_ALL_OFFLINE },
+ { 0xe0000, 21, RI_ALL_ONLINE },
+ { 0xe0054, 8, RI_ALL_ONLINE },
+ { 0xe0074, 49, RI_ALL_ONLINE },
+ { 0xe0138, 1, RI_E1E1H_ONLINE },
+ { 0xe013c, 35, RI_ALL_ONLINE },
+ { 0xe01f4, 1, RI_E2_ONLINE },
+ { 0xe01f8, 1, RI_E2E3E3B0_ONLINE },
+ { 0xe0200, 2, RI_ALL_ONLINE },
+ { 0xe020c, 8, RI_ALL_ONLINE },
+ { 0xe022c, 18, RI_E1HE2E3E3B0_ONLINE },
+ { 0xe0280, 1, RI_ALL_ONLINE },
+ { 0xe0300, 1, RI_ALL_ONLINE },
+ { 0xe0400, 1, RI_E3B0_ONLINE },
+ { 0xe1000, 1, RI_ALL_ONLINE },
+ { 0xe2000, 1, RI_ALL_ONLINE },
+ { 0xe2004, 2047, RI_ALL_OFFLINE },
+ { 0xf0000, 1, RI_ALL_ONLINE },
+ { 0xf0004, 16383, RI_ALL_OFFLINE },
+ { 0x101000, 12, RI_ALL_ONLINE },
+ { 0x101050, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x101054, 3, RI_E2E3E3B0_ONLINE },
+ { 0x101100, 1, RI_ALL_ONLINE },
+ { 0x101800, 8, RI_ALL_ONLINE },
+ { 0x102000, 18, RI_ALL_ONLINE },
+ { 0x102068, 6, RI_E2E3E3B0_ONLINE },
+ { 0x102080, 17, RI_ALL_ONLINE },
+ { 0x1020c8, 8, RI_E1H_ONLINE },
+ { 0x1020e8, 9, RI_E2E3E3B0_ONLINE },
+ { 0x102400, 1, RI_ALL_ONLINE },
+ { 0x103000, 26, RI_ALL_ONLINE },
+ { 0x103098, 5, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1030ac, 2, RI_E2E3E3B0_ONLINE },
+ { 0x1030b4, 1, RI_E2_ONLINE },
+ { 0x1030b8, 7, RI_E2E3E3B0_ONLINE },
+ { 0x1030d8, 8, RI_E2E3E3B0_ONLINE },
+ { 0x103400, 1, RI_E2E3E3B0_ONLINE },
+ { 0x103404, 135, RI_E2E3E3B0_OFFLINE },
+ { 0x103800, 8, RI_ALL_ONLINE },
+ { 0x104000, 63, RI_ALL_ONLINE },
+ { 0x10411c, 16, RI_E2E3E3B0_ONLINE },
+ { 0x104200, 17, RI_ALL_ONLINE },
+ { 0x104400, 64, RI_ALL_ONLINE },
+ { 0x104500, 192, RI_ALL_OFFLINE },
+ { 0x104800, 64, RI_ALL_ONLINE },
+ { 0x104900, 192, RI_ALL_OFFLINE },
+ { 0x105000, 256, RI_ALL_ONLINE },
+ { 0x105400, 768, RI_ALL_OFFLINE },
+ { 0x107000, 7, RI_E2E3E3B0_ONLINE },
+ { 0x10701c, 1, RI_E3E3B0_ONLINE },
+ { 0x108000, 33, RI_E1E1H_ONLINE },
+ { 0x1080ac, 5, RI_E1H_ONLINE },
+ { 0x108100, 5, RI_E1E1H_ONLINE },
+ { 0x108120, 5, RI_E1E1H_ONLINE },
+ { 0x108200, 74, RI_E1E1H_ONLINE },
+ { 0x108400, 74, RI_E1E1H_ONLINE },
+ { 0x108800, 152, RI_E1E1H_ONLINE },
+ { 0x110000, 111, RI_E2E3E3B0_ONLINE },
+ { 0x1101dc, 1, RI_E3E3B0_ONLINE },
+ { 0x110200, 4, RI_E2E3E3B0_ONLINE },
+ { 0x120000, 2, RI_ALL_ONLINE },
+ { 0x120008, 4, RI_ALL_ONLINE },
+ { 0x120018, 3, RI_ALL_ONLINE },
+ { 0x120024, 4, RI_ALL_ONLINE },
+ { 0x120034, 3, RI_ALL_ONLINE },
+ { 0x120040, 4, RI_ALL_ONLINE },
+ { 0x120050, 3, RI_ALL_ONLINE },
+ { 0x12005c, 4, RI_ALL_ONLINE },
+ { 0x12006c, 3, RI_ALL_ONLINE },
+ { 0x120078, 4, RI_ALL_ONLINE },
+ { 0x120088, 3, RI_ALL_ONLINE },
+ { 0x120094, 4, RI_ALL_ONLINE },
+ { 0x1200a4, 3, RI_ALL_ONLINE },
+ { 0x1200b0, 4, RI_ALL_ONLINE },
+ { 0x1200c0, 3, RI_ALL_ONLINE },
+ { 0x1200cc, 4, RI_ALL_ONLINE },
+ { 0x1200dc, 3, RI_ALL_ONLINE },
+ { 0x1200e8, 4, RI_ALL_ONLINE },
+ { 0x1200f8, 3, RI_ALL_ONLINE },
+ { 0x120104, 4, RI_ALL_ONLINE },
+ { 0x120114, 1, RI_ALL_ONLINE },
+ { 0x120118, 22, RI_ALL_ONLINE },
+ { 0x120170, 2, RI_E1E1H_ONLINE },
+ { 0x120178, 243, RI_ALL_ONLINE },
+ { 0x120544, 4, RI_E1E1H_ONLINE },
+ { 0x120554, 6, RI_ALL_ONLINE },
+ { 0x12059c, 6, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1205b4, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1205b8, 15, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1205f4, 1, RI_E1HE2_ONLINE },
+ { 0x1205f8, 4, RI_E2E3E3B0_ONLINE },
+ { 0x120618, 1, RI_E2E3E3B0_ONLINE },
+ { 0x12061c, 20, RI_E1HE2E3E3B0_ONLINE },
+ { 0x12066c, 11, RI_E1HE2E3E3B0_ONLINE },
+ { 0x120698, 3, RI_E2E3E3B0_ONLINE },
+ { 0x1206a4, 1, RI_E2_ONLINE },
+ { 0x1206a8, 1, RI_E2E3E3B0_ONLINE },
+ { 0x1206b0, 75, RI_E2E3E3B0_ONLINE },
+ { 0x1207dc, 1, RI_E2_ONLINE },
+ { 0x1207fc, 1, RI_E2E3E3B0_ONLINE },
+ { 0x12080c, 65, RI_ALL_ONLINE },
+ { 0x120910, 7, RI_E2E3E3B0_ONLINE },
+ { 0x120930, 9, RI_E2E3E3B0_ONLINE },
+ { 0x12095c, 37, RI_E3E3B0_ONLINE },
+ { 0x120a00, 2, RI_E1E1HE2_ONLINE },
+ { 0x120b00, 1, RI_E3E3B0_ONLINE },
+ { 0x122000, 2, RI_ALL_ONLINE },
+ { 0x122008, 2046, RI_E1_OFFLINE },
+ { 0x128000, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x128008, 6142, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x130000, 35, RI_E2E3E3B0_ONLINE },
+ { 0x130100, 29, RI_E2E3E3B0_ONLINE },
+ { 0x130180, 1, RI_E2E3E3B0_ONLINE },
+ { 0x130200, 1, RI_E2E3E3B0_ONLINE },
+ { 0x130280, 1, RI_E2E3E3B0_ONLINE },
+ { 0x130300, 5, RI_E2E3E3B0_ONLINE },
+ { 0x130380, 1, RI_E2E3E3B0_ONLINE },
+ { 0x130400, 1, RI_E2E3E3B0_ONLINE },
+ { 0x130480, 5, RI_E2E3E3B0_ONLINE },
+ { 0x130800, 72, RI_E2E3E3B0_ONLINE },
+ { 0x131000, 136, RI_E2E3E3B0_ONLINE },
+ { 0x132000, 148, RI_E2E3E3B0_ONLINE },
+ { 0x134000, 544, RI_E2E3E3B0_ONLINE },
+ { 0x140000, 1, RI_ALL_ONLINE },
+ { 0x140004, 9, RI_E1E1HE2E3_ONLINE },
+ { 0x140028, 8, RI_ALL_ONLINE },
+ { 0x140048, 10, RI_E1E1HE2E3_ONLINE },
+ { 0x140070, 1, RI_ALL_ONLINE },
+ { 0x140074, 10, RI_E1E1HE2E3_ONLINE },
+ { 0x14009c, 1, RI_ALL_ONLINE },
+ { 0x1400a0, 5, RI_E1E1HE2E3_ONLINE },
+ { 0x1400b4, 7, RI_ALL_ONLINE },
+ { 0x1400d0, 10, RI_E1E1HE2E3_ONLINE },
+ { 0x1400f8, 2, RI_ALL_ONLINE },
+ { 0x140100, 5, RI_E1E1H_ONLINE },
+ { 0x140114, 5, RI_E1E1HE2E3_ONLINE },
+ { 0x140128, 7, RI_ALL_ONLINE },
+ { 0x140144, 9, RI_E1E1HE2E3_ONLINE },
+ { 0x140168, 8, RI_ALL_ONLINE },
+ { 0x140188, 3, RI_E1E1HE2E3_ONLINE },
+ { 0x140194, 13, RI_ALL_ONLINE },
+ { 0x140200, 6, RI_E1E1HE2E3_ONLINE },
+ { 0x140220, 4, RI_E2E3_ONLINE },
+ { 0x140240, 4, RI_E2E3_ONLINE },
+ { 0x140260, 4, RI_E2E3_ONLINE },
+ { 0x140280, 4, RI_E2E3_ONLINE },
+ { 0x1402a0, 4, RI_E2E3_ONLINE },
+ { 0x1402c0, 4, RI_E2E3_ONLINE },
+ { 0x1402e0, 2, RI_E2E3_ONLINE },
+ { 0x1402e8, 2, RI_E2E3E3B0_ONLINE },
+ { 0x1402f0, 9, RI_E2E3_ONLINE },
+ { 0x140314, 44, RI_E3B0_ONLINE },
+ { 0x1403d0, 70, RI_E3B0_ONLINE },
+ { 0x144000, 4, RI_E1E1H_ONLINE },
+ { 0x148000, 4, RI_E1E1H_ONLINE },
+ { 0x14c000, 4, RI_E1E1H_ONLINE },
+ { 0x150000, 4, RI_E1E1H_ONLINE },
+ { 0x154000, 4, RI_E1E1H_ONLINE },
+ { 0x158000, 4, RI_E1E1H_ONLINE },
+ { 0x15c000, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x15c008, 5, RI_E1H_ONLINE },
+ { 0x15c020, 8, RI_E2E3E3B0_ONLINE },
+ { 0x15c040, 1, RI_E2E3_ONLINE },
+ { 0x15c044, 2, RI_E2E3E3B0_ONLINE },
+ { 0x15c04c, 8, RI_E2E3_ONLINE },
+ { 0x15c06c, 8, RI_E2E3E3B0_ONLINE },
+ { 0x15c090, 13, RI_E2E3E3B0_ONLINE },
+ { 0x15c0c8, 24, RI_E2E3E3B0_ONLINE },
+ { 0x15c128, 2, RI_E2E3_ONLINE },
+ { 0x15c130, 8, RI_E2E3E3B0_ONLINE },
+ { 0x15c150, 2, RI_E3E3B0_ONLINE },
+ { 0x15c158, 2, RI_E3_ONLINE },
+ { 0x15c160, 149, RI_E3B0_ONLINE },
+ { 0x161000, 7, RI_ALL_ONLINE },
+ { 0x16103c, 2, RI_E2E3E3B0_ONLINE },
+ { 0x161800, 2, RI_ALL_ONLINE },
+ { 0x162000, 54, RI_E3E3B0_ONLINE },
+ { 0x162200, 60, RI_E3E3B0_ONLINE },
+ { 0x162400, 54, RI_E3E3B0_ONLINE },
+ { 0x162600, 60, RI_E3E3B0_ONLINE },
+ { 0x162800, 54, RI_E3E3B0_ONLINE },
+ { 0x162a00, 60, RI_E3E3B0_ONLINE },
+ { 0x162c00, 54, RI_E3E3B0_ONLINE },
+ { 0x162e00, 60, RI_E3E3B0_ONLINE },
+ { 0x164000, 60, RI_ALL_ONLINE },
+ { 0x164110, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x164118, 15, RI_E2E3E3B0_ONLINE },
+ { 0x164200, 1, RI_ALL_ONLINE },
+ { 0x164208, 1, RI_ALL_ONLINE },
+ { 0x164210, 1, RI_ALL_ONLINE },
+ { 0x164218, 1, RI_ALL_ONLINE },
+ { 0x164220, 1, RI_ALL_ONLINE },
+ { 0x164228, 1, RI_ALL_ONLINE },
+ { 0x164230, 1, RI_ALL_ONLINE },
+ { 0x164238, 1, RI_ALL_ONLINE },
+ { 0x164240, 1, RI_ALL_ONLINE },
+ { 0x164248, 1, RI_ALL_ONLINE },
+ { 0x164250, 1, RI_ALL_ONLINE },
+ { 0x164258, 1, RI_ALL_ONLINE },
+ { 0x164260, 1, RI_ALL_ONLINE },
+ { 0x164270, 2, RI_ALL_ONLINE },
+ { 0x164280, 2, RI_ALL_ONLINE },
+ { 0x164800, 2, RI_ALL_ONLINE },
+ { 0x165000, 2, RI_ALL_ONLINE },
+ { 0x166000, 164, RI_ALL_ONLINE },
+ { 0x1662cc, 7, RI_E2E3E3B0_ONLINE },
+ { 0x166400, 49, RI_ALL_ONLINE },
+ { 0x1664c8, 38, RI_ALL_ONLINE },
+ { 0x166568, 2, RI_ALL_ONLINE },
+ { 0x166570, 5, RI_E2E3E3B0_ONLINE },
+ { 0x166800, 1, RI_ALL_ONLINE },
+ { 0x168000, 137, RI_ALL_ONLINE },
+ { 0x168224, 2, RI_E1E1H_ONLINE },
+ { 0x16822c, 29, RI_ALL_ONLINE },
+ { 0x1682a0, 12, RI_E1E1H_ONLINE },
+ { 0x1682d0, 12, RI_ALL_ONLINE },
+ { 0x168300, 2, RI_E1E1H_ONLINE },
+ { 0x168308, 68, RI_ALL_ONLINE },
+ { 0x168418, 2, RI_E1E1H_ONLINE },
+ { 0x168420, 6, RI_ALL_ONLINE },
+ { 0x168800, 19, RI_ALL_ONLINE },
+ { 0x168900, 1, RI_ALL_ONLINE },
+ { 0x168a00, 128, RI_ALL_ONLINE },
+ { 0x16a000, 1, RI_ALL_ONLINE },
+ { 0x16a004, 1535, RI_ALL_OFFLINE },
+ { 0x16c000, 1, RI_ALL_ONLINE },
+ { 0x16c004, 1535, RI_ALL_OFFLINE },
+ { 0x16e000, 16, RI_E1H_ONLINE },
+ { 0x16e040, 8, RI_E2E3E3B0_ONLINE },
+ { 0x16e100, 1, RI_E1H_ONLINE },
+ { 0x16e200, 2, RI_E1H_ONLINE },
+ { 0x16e400, 161, RI_E1H_ONLINE },
+ { 0x16e684, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x16e68c, 12, RI_E1H_ONLINE },
+ { 0x16e6bc, 4, RI_E1HE2E3E3B0_ONLINE },
+ { 0x16e6cc, 4, RI_E1H_ONLINE },
+ { 0x16e6e0, 2, RI_E2E3E3B0_ONLINE },
+ { 0x16e6e8, 5, RI_E2E3_ONLINE },
+ { 0x16e6fc, 5, RI_E2E3E3B0_ONLINE },
+ { 0x16e768, 17, RI_E2E3E3B0_ONLINE },
+ { 0x16e7ac, 12, RI_E3B0_ONLINE },
+ { 0x170000, 24, RI_ALL_ONLINE },
+ { 0x170060, 4, RI_E1E1H_ONLINE },
+ { 0x170070, 65, RI_ALL_ONLINE },
+ { 0x170194, 11, RI_E2E3E3B0_ONLINE },
+ { 0x1701c4, 1, RI_E2E3E3B0_ONLINE },
+ { 0x1701cc, 7, RI_E2E3E3B0_ONLINE },
+ { 0x1701e8, 1, RI_E3E3B0_ONLINE },
+ { 0x1701ec, 1, RI_E2E3E3B0_ONLINE },
+ { 0x1701f4, 1, RI_E2E3E3B0_ONLINE },
+ { 0x170200, 4, RI_ALL_ONLINE },
+ { 0x170214, 1, RI_ALL_ONLINE },
+ { 0x170218, 77, RI_E2E3E3B0_ONLINE },
+ { 0x170400, 64, RI_E2E3E3B0_ONLINE },
+ { 0x178000, 1, RI_ALL_ONLINE },
+ { 0x180000, 61, RI_ALL_ONLINE },
+ { 0x18013c, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x180200, 58, RI_ALL_ONLINE },
+ { 0x180340, 4, RI_ALL_ONLINE },
+ { 0x180380, 1, RI_E2E3E3B0_ONLINE },
+ { 0x180388, 1, RI_E2E3E3B0_ONLINE },
+ { 0x180390, 1, RI_E2E3E3B0_ONLINE },
+ { 0x180398, 1, RI_E2E3E3B0_ONLINE },
+ { 0x1803a0, 5, RI_E2E3E3B0_ONLINE },
+ { 0x1803b4, 2, RI_E3E3B0_ONLINE },
+ { 0x180400, 1, RI_ALL_ONLINE },
+ { 0x180404, 255, RI_E1E1H_OFFLINE },
+ { 0x181000, 4, RI_ALL_ONLINE },
+ { 0x181010, 1020, RI_ALL_OFFLINE },
+ { 0x182000, 4, RI_E3E3B0_ONLINE },
+ { 0x1a0000, 1, RI_ALL_ONLINE },
+ { 0x1a0004, 5631, RI_ALL_OFFLINE },
+ { 0x1a5800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x1a8000, 1, RI_ALL_ONLINE },
+ { 0x1a8004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x1b0000, 1, RI_ALL_ONLINE },
+ { 0x1b0004, 15, RI_E1H_OFFLINE },
+ { 0x1b0040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b0044, 239, RI_E1H_OFFLINE },
+ { 0x1b0400, 1, RI_ALL_ONLINE },
+ { 0x1b0404, 255, RI_E1H_OFFLINE },
+ { 0x1b0800, 1, RI_ALL_ONLINE },
+ { 0x1b0840, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b0c00, 1, RI_ALL_ONLINE },
+ { 0x1b1000, 1, RI_ALL_ONLINE },
+ { 0x1b1040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b1400, 1, RI_ALL_ONLINE },
+ { 0x1b1440, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b1480, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b14c0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b1800, 128, RI_ALL_OFFLINE },
+ { 0x1b1c00, 128, RI_ALL_OFFLINE },
+ { 0x1b2000, 1, RI_ALL_ONLINE },
+ { 0x1b2400, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b2404, 5631, RI_E2E3E3B0_OFFLINE },
+ { 0x1b8000, 1, RI_ALL_ONLINE },
+ { 0x1b8040, 1, RI_ALL_ONLINE },
+ { 0x1b8080, 1, RI_ALL_ONLINE },
+ { 0x1b80c0, 1, RI_ALL_ONLINE },
+ { 0x1b8100, 1, RI_ALL_ONLINE },
+ { 0x1b8140, 1, RI_ALL_ONLINE },
+ { 0x1b8180, 1, RI_ALL_ONLINE },
+ { 0x1b81c0, 1, RI_ALL_ONLINE },
+ { 0x1b8200, 1, RI_ALL_ONLINE },
+ { 0x1b8240, 1, RI_ALL_ONLINE },
+ { 0x1b8280, 1, RI_ALL_ONLINE },
+ { 0x1b82c0, 1, RI_ALL_ONLINE },
+ { 0x1b8300, 1, RI_ALL_ONLINE },
+ { 0x1b8340, 1, RI_ALL_ONLINE },
+ { 0x1b8380, 1, RI_ALL_ONLINE },
+ { 0x1b83c0, 1, RI_ALL_ONLINE },
+ { 0x1b8400, 1, RI_ALL_ONLINE },
+ { 0x1b8440, 1, RI_ALL_ONLINE },
+ { 0x1b8480, 1, RI_ALL_ONLINE },
+ { 0x1b84c0, 1, RI_ALL_ONLINE },
+ { 0x1b8500, 1, RI_ALL_ONLINE },
+ { 0x1b8540, 1, RI_ALL_ONLINE },
+ { 0x1b8580, 1, RI_ALL_ONLINE },
+ { 0x1b85c0, 19, RI_E2E3E3B0_ONLINE },
+ { 0x1b8800, 1, RI_ALL_ONLINE },
+ { 0x1b8840, 1, RI_ALL_ONLINE },
+ { 0x1b8880, 1, RI_ALL_ONLINE },
+ { 0x1b88c0, 1, RI_ALL_ONLINE },
+ { 0x1b8900, 1, RI_ALL_ONLINE },
+ { 0x1b8940, 1, RI_ALL_ONLINE },
+ { 0x1b8980, 1, RI_ALL_ONLINE },
+ { 0x1b89c0, 1, RI_ALL_ONLINE },
+ { 0x1b8a00, 1, RI_ALL_ONLINE },
+ { 0x1b8a40, 1, RI_ALL_ONLINE },
+ { 0x1b8a80, 1, RI_ALL_ONLINE },
+ { 0x1b8ac0, 1, RI_ALL_ONLINE },
+ { 0x1b8b00, 1, RI_ALL_ONLINE },
+ { 0x1b8b40, 1, RI_ALL_ONLINE },
+ { 0x1b8b80, 1, RI_ALL_ONLINE },
+ { 0x1b8bc0, 1, RI_ALL_ONLINE },
+ { 0x1b8c00, 1, RI_ALL_ONLINE },
+ { 0x1b8c40, 1, RI_ALL_ONLINE },
+ { 0x1b8c80, 1, RI_ALL_ONLINE },
+ { 0x1b8cc0, 1, RI_ALL_ONLINE },
+ { 0x1b8cc4, 1, RI_E2E3E3B0_ONLINE },
+ { 0x1b8d00, 1, RI_ALL_ONLINE },
+ { 0x1b8d40, 1, RI_ALL_ONLINE },
+ { 0x1b8d80, 1, RI_ALL_ONLINE },
+ { 0x1b8dc0, 1, RI_ALL_ONLINE },
+ { 0x1b8e00, 1, RI_ALL_ONLINE },
+ { 0x1b8e40, 1, RI_ALL_ONLINE },
+ { 0x1b8e80, 1, RI_ALL_ONLINE },
+ { 0x1b8e84, 1, RI_E2E3E3B0_ONLINE },
+ { 0x1b8ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b8f00, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b8f40, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b8f80, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b8fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x1b8fc4, 2, RI_E2E3E3B0_ONLINE },
+ { 0x1b8fd0, 6, RI_E2E3E3B0_ONLINE },
+ { 0x1b8fe8, 2, RI_E3E3B0_ONLINE },
+ { 0x1b9000, 1, RI_E2E3E3B0_ONLINE },
+ { 0x1b9040, 3, RI_E2E3E3B0_ONLINE },
+ { 0x1b905c, 1, RI_E3E3B0_ONLINE },
+ { 0x1b9064, 1, RI_E3B0_ONLINE },
+ { 0x1b9080, 10, RI_E3B0_ONLINE },
+ { 0x1b9400, 14, RI_E2E3E3B0_ONLINE },
+ { 0x1b943c, 19, RI_E2E3E3B0_ONLINE },
+ { 0x1b9490, 10, RI_E2E3E3B0_ONLINE },
+ { 0x1c0000, 2, RI_ALL_ONLINE },
+ { 0x200000, 65, RI_ALL_ONLINE },
+ { 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x200200, 58, RI_ALL_ONLINE },
+ { 0x200340, 4, RI_ALL_ONLINE },
+ { 0x200380, 1, RI_E2E3E3B0_ONLINE },
+ { 0x200388, 1, RI_E2E3E3B0_ONLINE },
+ { 0x200390, 1, RI_E2E3E3B0_ONLINE },
+ { 0x200398, 1, RI_E2E3E3B0_ONLINE },
+ { 0x2003a0, 1, RI_E2E3E3B0_ONLINE },
+ { 0x2003a8, 2, RI_E2E3E3B0_ONLINE },
+ { 0x200400, 1, RI_ALL_ONLINE },
+ { 0x200404, 255, RI_E1E1H_OFFLINE },
+ { 0x202000, 4, RI_ALL_ONLINE },
+ { 0x202010, 2044, RI_ALL_OFFLINE },
+ { 0x204000, 4, RI_E3E3B0_ONLINE },
+ { 0x220000, 1, RI_ALL_ONLINE },
+ { 0x220004, 5631, RI_ALL_OFFLINE },
+ { 0x225800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x228000, 1, RI_ALL_ONLINE },
+ { 0x228004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x230000, 1, RI_ALL_ONLINE },
+ { 0x230004, 15, RI_E1H_OFFLINE },
+ { 0x230040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x230044, 239, RI_E1H_OFFLINE },
+ { 0x230400, 1, RI_ALL_ONLINE },
+ { 0x230404, 255, RI_E1H_OFFLINE },
+ { 0x230800, 1, RI_ALL_ONLINE },
+ { 0x230840, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x230c00, 1, RI_ALL_ONLINE },
+ { 0x231000, 1, RI_ALL_ONLINE },
+ { 0x231040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x231400, 1, RI_ALL_ONLINE },
+ { 0x231440, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x231480, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2314c0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x231800, 128, RI_ALL_OFFLINE },
+ { 0x231c00, 128, RI_ALL_OFFLINE },
+ { 0x232000, 1, RI_ALL_ONLINE },
+ { 0x232400, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x232404, 5631, RI_E2E3E3B0_OFFLINE },
+ { 0x238000, 1, RI_ALL_ONLINE },
+ { 0x238040, 1, RI_ALL_ONLINE },
+ { 0x238080, 1, RI_ALL_ONLINE },
+ { 0x2380c0, 1, RI_ALL_ONLINE },
+ { 0x238100, 1, RI_ALL_ONLINE },
+ { 0x238140, 1, RI_ALL_ONLINE },
+ { 0x238180, 1, RI_ALL_ONLINE },
+ { 0x2381c0, 1, RI_ALL_ONLINE },
+ { 0x238200, 1, RI_ALL_ONLINE },
+ { 0x238240, 1, RI_ALL_ONLINE },
+ { 0x238280, 1, RI_ALL_ONLINE },
+ { 0x2382c0, 1, RI_ALL_ONLINE },
+ { 0x238300, 1, RI_ALL_ONLINE },
+ { 0x238340, 1, RI_ALL_ONLINE },
+ { 0x238380, 1, RI_ALL_ONLINE },
+ { 0x2383c0, 1, RI_ALL_ONLINE },
+ { 0x238400, 1, RI_ALL_ONLINE },
+ { 0x238440, 1, RI_ALL_ONLINE },
+ { 0x238480, 1, RI_ALL_ONLINE },
+ { 0x2384c0, 1, RI_ALL_ONLINE },
+ { 0x238500, 1, RI_ALL_ONLINE },
+ { 0x238540, 1, RI_ALL_ONLINE },
+ { 0x238580, 1, RI_ALL_ONLINE },
+ { 0x2385c0, 19, RI_E2E3E3B0_ONLINE },
+ { 0x238800, 1, RI_ALL_ONLINE },
+ { 0x238840, 1, RI_ALL_ONLINE },
+ { 0x238880, 1, RI_ALL_ONLINE },
+ { 0x2388c0, 1, RI_ALL_ONLINE },
+ { 0x238900, 1, RI_ALL_ONLINE },
+ { 0x238940, 1, RI_ALL_ONLINE },
+ { 0x238980, 1, RI_ALL_ONLINE },
+ { 0x2389c0, 1, RI_ALL_ONLINE },
+ { 0x238a00, 1, RI_ALL_ONLINE },
+ { 0x238a40, 1, RI_ALL_ONLINE },
+ { 0x238a80, 1, RI_ALL_ONLINE },
+ { 0x238ac0, 1, RI_ALL_ONLINE },
+ { 0x238b00, 1, RI_ALL_ONLINE },
+ { 0x238b40, 1, RI_ALL_ONLINE },
+ { 0x238b80, 1, RI_ALL_ONLINE },
+ { 0x238bc0, 1, RI_ALL_ONLINE },
+ { 0x238c00, 1, RI_ALL_ONLINE },
+ { 0x238c40, 1, RI_ALL_ONLINE },
+ { 0x238c80, 1, RI_ALL_ONLINE },
+ { 0x238cc0, 1, RI_ALL_ONLINE },
+ { 0x238cc4, 1, RI_E2E3E3B0_ONLINE },
+ { 0x238d00, 1, RI_ALL_ONLINE },
+ { 0x238d40, 1, RI_ALL_ONLINE },
+ { 0x238d80, 1, RI_ALL_ONLINE },
+ { 0x238dc0, 1, RI_ALL_ONLINE },
+ { 0x238e00, 1, RI_ALL_ONLINE },
+ { 0x238e40, 1, RI_ALL_ONLINE },
+ { 0x238e80, 1, RI_ALL_ONLINE },
+ { 0x238e84, 1, RI_E2E3E3B0_ONLINE },
+ { 0x238ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x238f00, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x238f40, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x238f80, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x238fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x238fc4, 2, RI_E2E3E3B0_ONLINE },
+ { 0x238fd0, 6, RI_E2E3E3B0_ONLINE },
+ { 0x238fe8, 2, RI_E3E3B0_ONLINE },
+ { 0x239000, 1, RI_E2E3E3B0_ONLINE },
+ { 0x239040, 3, RI_E2E3E3B0_ONLINE },
+ { 0x23905c, 1, RI_E3E3B0_ONLINE },
+ { 0x239064, 1, RI_E3B0_ONLINE },
+ { 0x239080, 10, RI_E3B0_ONLINE },
+ { 0x240000, 2, RI_ALL_ONLINE },
+ { 0x280000, 65, RI_ALL_ONLINE },
+ { 0x28014c, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x280200, 58, RI_ALL_ONLINE },
+ { 0x280340, 4, RI_ALL_ONLINE },
+ { 0x280380, 1, RI_E2E3E3B0_ONLINE },
+ { 0x280388, 1, RI_E2E3E3B0_ONLINE },
+ { 0x280390, 1, RI_E2E3E3B0_ONLINE },
+ { 0x280398, 1, RI_E2E3E3B0_ONLINE },
+ { 0x2803a0, 1, RI_E2E3E3B0_ONLINE },
+ { 0x2803a8, 2, RI_E2E3E3B0_ONLINE },
+ { 0x280400, 1, RI_ALL_ONLINE },
+ { 0x280404, 255, RI_E1E1H_OFFLINE },
+ { 0x282000, 4, RI_ALL_ONLINE },
+ { 0x282010, 2044, RI_ALL_OFFLINE },
+ { 0x284000, 4, RI_E3E3B0_ONLINE },
+ { 0x2a0000, 1, RI_ALL_ONLINE },
+ { 0x2a0004, 5631, RI_ALL_OFFLINE },
+ { 0x2a5800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x2a8000, 1, RI_ALL_ONLINE },
+ { 0x2a8004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x2b0000, 1, RI_ALL_ONLINE },
+ { 0x2b0004, 15, RI_E1H_OFFLINE },
+ { 0x2b0040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b0044, 239, RI_E1H_OFFLINE },
+ { 0x2b0400, 1, RI_ALL_ONLINE },
+ { 0x2b0404, 255, RI_E1H_OFFLINE },
+ { 0x2b0800, 1, RI_ALL_ONLINE },
+ { 0x2b0840, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b0c00, 1, RI_ALL_ONLINE },
+ { 0x2b1000, 1, RI_ALL_ONLINE },
+ { 0x2b1040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b1400, 1, RI_ALL_ONLINE },
+ { 0x2b1440, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b1480, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b14c0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b1800, 128, RI_ALL_OFFLINE },
+ { 0x2b1c00, 128, RI_ALL_OFFLINE },
+ { 0x2b2000, 1, RI_ALL_ONLINE },
+ { 0x2b2400, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b2404, 5631, RI_E2E3E3B0_OFFLINE },
+ { 0x2b8000, 1, RI_ALL_ONLINE },
+ { 0x2b8040, 1, RI_ALL_ONLINE },
+ { 0x2b8080, 1, RI_ALL_ONLINE },
+ { 0x2b80c0, 1, RI_ALL_ONLINE },
+ { 0x2b8100, 1, RI_ALL_ONLINE },
+ { 0x2b8140, 1, RI_ALL_ONLINE },
+ { 0x2b8180, 1, RI_ALL_ONLINE },
+ { 0x2b81c0, 1, RI_ALL_ONLINE },
+ { 0x2b8200, 1, RI_ALL_ONLINE },
+ { 0x2b8240, 1, RI_ALL_ONLINE },
+ { 0x2b8280, 1, RI_ALL_ONLINE },
+ { 0x2b82c0, 1, RI_ALL_ONLINE },
+ { 0x2b8300, 1, RI_ALL_ONLINE },
+ { 0x2b8340, 1, RI_ALL_ONLINE },
+ { 0x2b8380, 1, RI_ALL_ONLINE },
+ { 0x2b83c0, 1, RI_ALL_ONLINE },
+ { 0x2b8400, 1, RI_ALL_ONLINE },
+ { 0x2b8440, 1, RI_ALL_ONLINE },
+ { 0x2b8480, 1, RI_ALL_ONLINE },
+ { 0x2b84c0, 1, RI_ALL_ONLINE },
+ { 0x2b8500, 1, RI_ALL_ONLINE },
+ { 0x2b8540, 1, RI_ALL_ONLINE },
+ { 0x2b8580, 1, RI_ALL_ONLINE },
+ { 0x2b85c0, 19, RI_E2E3E3B0_ONLINE },
+ { 0x2b8800, 1, RI_ALL_ONLINE },
+ { 0x2b8840, 1, RI_ALL_ONLINE },
+ { 0x2b8880, 1, RI_ALL_ONLINE },
+ { 0x2b88c0, 1, RI_ALL_ONLINE },
+ { 0x2b8900, 1, RI_ALL_ONLINE },
+ { 0x2b8940, 1, RI_ALL_ONLINE },
+ { 0x2b8980, 1, RI_ALL_ONLINE },
+ { 0x2b89c0, 1, RI_ALL_ONLINE },
+ { 0x2b8a00, 1, RI_ALL_ONLINE },
+ { 0x2b8a40, 1, RI_ALL_ONLINE },
+ { 0x2b8a80, 1, RI_ALL_ONLINE },
+ { 0x2b8ac0, 1, RI_ALL_ONLINE },
+ { 0x2b8b00, 1, RI_ALL_ONLINE },
+ { 0x2b8b40, 1, RI_ALL_ONLINE },
+ { 0x2b8b80, 1, RI_ALL_ONLINE },
+ { 0x2b8bc0, 1, RI_ALL_ONLINE },
+ { 0x2b8c00, 1, RI_ALL_ONLINE },
+ { 0x2b8c40, 1, RI_ALL_ONLINE },
+ { 0x2b8c80, 1, RI_ALL_ONLINE },
+ { 0x2b8cc0, 1, RI_ALL_ONLINE },
+ { 0x2b8cc4, 1, RI_E2E3E3B0_ONLINE },
+ { 0x2b8d00, 1, RI_ALL_ONLINE },
+ { 0x2b8d40, 1, RI_ALL_ONLINE },
+ { 0x2b8d80, 1, RI_ALL_ONLINE },
+ { 0x2b8dc0, 1, RI_ALL_ONLINE },
+ { 0x2b8e00, 1, RI_ALL_ONLINE },
+ { 0x2b8e40, 1, RI_ALL_ONLINE },
+ { 0x2b8e80, 1, RI_ALL_ONLINE },
+ { 0x2b8e84, 1, RI_E2E3E3B0_ONLINE },
+ { 0x2b8ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b8f00, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b8f40, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b8f80, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b8fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x2b8fc4, 2, RI_E2E3E3B0_ONLINE },
+ { 0x2b8fd0, 6, RI_E2E3E3B0_ONLINE },
+ { 0x2b8fe8, 2, RI_E3E3B0_ONLINE },
+ { 0x2b9000, 1, RI_E2E3E3B0_ONLINE },
+ { 0x2b9040, 3, RI_E2E3E3B0_ONLINE },
+ { 0x2b905c, 1, RI_E3E3B0_ONLINE },
+ { 0x2b9064, 1, RI_E3B0_ONLINE },
+ { 0x2b9080, 10, RI_E3B0_ONLINE },
+ { 0x2b9400, 14, RI_E2E3E3B0_ONLINE },
+ { 0x2b943c, 19, RI_E2E3E3B0_ONLINE },
+ { 0x2b9490, 10, RI_E2E3E3B0_ONLINE },
+ { 0x2c0000, 2, RI_ALL_ONLINE },
+ { 0x300000, 65, RI_ALL_ONLINE },
+ { 0x30014c, 2, RI_E1HE2E3E3B0_ONLINE },
+ { 0x300200, 58, RI_ALL_ONLINE },
+ { 0x300340, 4, RI_ALL_ONLINE },
+ { 0x300380, 1, RI_E2E3E3B0_ONLINE },
+ { 0x300388, 1, RI_E2E3E3B0_ONLINE },
+ { 0x300390, 1, RI_E2E3E3B0_ONLINE },
+ { 0x300398, 1, RI_E2E3E3B0_ONLINE },
+ { 0x3003a0, 1, RI_E2E3E3B0_ONLINE },
+ { 0x3003a8, 2, RI_E2E3E3B0_ONLINE },
+ { 0x300400, 1, RI_ALL_ONLINE },
+ { 0x300404, 255, RI_E1E1H_OFFLINE },
+ { 0x302000, 4, RI_ALL_ONLINE },
+ { 0x302010, 2044, RI_ALL_OFFLINE },
+ { 0x304000, 4, RI_E3E3B0_ONLINE },
+ { 0x320000, 1, RI_ALL_ONLINE },
+ { 0x320004, 5631, RI_ALL_OFFLINE },
+ { 0x325800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x328000, 1, RI_ALL_ONLINE },
+ { 0x328004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+ { 0x330000, 1, RI_ALL_ONLINE },
+ { 0x330004, 15, RI_E1H_OFFLINE },
+ { 0x330040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x330044, 239, RI_E1H_OFFLINE },
+ { 0x330400, 1, RI_ALL_ONLINE },
+ { 0x330404, 255, RI_E1H_OFFLINE },
+ { 0x330800, 1, RI_ALL_ONLINE },
+ { 0x330840, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x330c00, 1, RI_ALL_ONLINE },
+ { 0x331000, 1, RI_ALL_ONLINE },
+ { 0x331040, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x331400, 1, RI_ALL_ONLINE },
+ { 0x331440, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x331480, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x3314c0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x331800, 128, RI_ALL_OFFLINE },
+ { 0x331c00, 128, RI_ALL_OFFLINE },
+ { 0x332000, 1, RI_ALL_ONLINE },
+ { 0x332400, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x332404, 5631, RI_E2E3E3B0_OFFLINE },
+ { 0x338000, 1, RI_ALL_ONLINE },
+ { 0x338040, 1, RI_ALL_ONLINE },
+ { 0x338080, 1, RI_ALL_ONLINE },
+ { 0x3380c0, 1, RI_ALL_ONLINE },
+ { 0x338100, 1, RI_ALL_ONLINE },
+ { 0x338140, 1, RI_ALL_ONLINE },
+ { 0x338180, 1, RI_ALL_ONLINE },
+ { 0x3381c0, 1, RI_ALL_ONLINE },
+ { 0x338200, 1, RI_ALL_ONLINE },
+ { 0x338240, 1, RI_ALL_ONLINE },
+ { 0x338280, 1, RI_ALL_ONLINE },
+ { 0x3382c0, 1, RI_ALL_ONLINE },
+ { 0x338300, 1, RI_ALL_ONLINE },
+ { 0x338340, 1, RI_ALL_ONLINE },
+ { 0x338380, 1, RI_ALL_ONLINE },
+ { 0x3383c0, 1, RI_ALL_ONLINE },
+ { 0x338400, 1, RI_ALL_ONLINE },
+ { 0x338440, 1, RI_ALL_ONLINE },
+ { 0x338480, 1, RI_ALL_ONLINE },
+ { 0x3384c0, 1, RI_ALL_ONLINE },
+ { 0x338500, 1, RI_ALL_ONLINE },
+ { 0x338540, 1, RI_ALL_ONLINE },
+ { 0x338580, 1, RI_ALL_ONLINE },
+ { 0x3385c0, 19, RI_E2E3E3B0_ONLINE },
+ { 0x338800, 1, RI_ALL_ONLINE },
+ { 0x338840, 1, RI_ALL_ONLINE },
+ { 0x338880, 1, RI_ALL_ONLINE },
+ { 0x3388c0, 1, RI_ALL_ONLINE },
+ { 0x338900, 1, RI_ALL_ONLINE },
+ { 0x338940, 1, RI_ALL_ONLINE },
+ { 0x338980, 1, RI_ALL_ONLINE },
+ { 0x3389c0, 1, RI_ALL_ONLINE },
+ { 0x338a00, 1, RI_ALL_ONLINE },
+ { 0x338a40, 1, RI_ALL_ONLINE },
+ { 0x338a80, 1, RI_ALL_ONLINE },
+ { 0x338ac0, 1, RI_ALL_ONLINE },
+ { 0x338b00, 1, RI_ALL_ONLINE },
+ { 0x338b40, 1, RI_ALL_ONLINE },
+ { 0x338b80, 1, RI_ALL_ONLINE },
+ { 0x338bc0, 1, RI_ALL_ONLINE },
+ { 0x338c00, 1, RI_ALL_ONLINE },
+ { 0x338c40, 1, RI_ALL_ONLINE },
+ { 0x338c80, 1, RI_ALL_ONLINE },
+ { 0x338cc0, 1, RI_ALL_ONLINE },
+ { 0x338cc4, 1, RI_E2E3E3B0_ONLINE },
+ { 0x338d00, 1, RI_ALL_ONLINE },
+ { 0x338d40, 1, RI_ALL_ONLINE },
+ { 0x338d80, 1, RI_ALL_ONLINE },
+ { 0x338dc0, 1, RI_ALL_ONLINE },
+ { 0x338e00, 1, RI_ALL_ONLINE },
+ { 0x338e40, 1, RI_ALL_ONLINE },
+ { 0x338e80, 1, RI_ALL_ONLINE },
+ { 0x338e84, 1, RI_E2E3E3B0_ONLINE },
+ { 0x338ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x338f00, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x338f40, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x338f80, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x338fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+ { 0x338fc4, 2, RI_E2E3E3B0_ONLINE },
+ { 0x338fd0, 6, RI_E2E3E3B0_ONLINE },
+ { 0x338fe8, 2, RI_E3E3B0_ONLINE },
+ { 0x339000, 1, RI_E2E3E3B0_ONLINE },
+ { 0x339040, 3, RI_E2E3E3B0_ONLINE },
+ { 0x33905c, 1, RI_E3E3B0_ONLINE },
+ { 0x339064, 1, RI_E3B0_ONLINE },
+ { 0x339080, 10, RI_E3B0_ONLINE },
+ { 0x340000, 2, RI_ALL_ONLINE },
};
+#define REGS_COUNT ARRAY_SIZE(reg_addrs)
-#define WREGS_COUNT_E2 1
-static const u32 read_reg_e2_0[] = { 0x1b1040, 0x1b1000 };
-
-static const struct wreg_addr wreg_addrs_e2[WREGS_COUNT_E2] = {
- { 0x1b0c00, 128, 2, read_reg_e2_0, RI_E2_OFFLINE }
-};
-
-static const struct dump_sign dump_sign_all = { 0x4d18b0a4, 0x60010, 0x3a };
-
-#define TIMER_REGS_COUNT_E1 2
-
-static const u32 timer_status_regs_e1[TIMER_REGS_COUNT_E1] = {
- 0x164014, 0x164018 };
-static const u32 timer_scan_regs_e1[TIMER_REGS_COUNT_E1] = {
- 0x1640d0, 0x1640d4 };
-
-#define TIMER_REGS_COUNT_E1H 2
+static const struct dump_sign dump_sign_all = { 0x4e23fde1, 0x70017, 0x3a };
-static const u32 timer_status_regs_e1h[TIMER_REGS_COUNT_E1H] = {
- 0x164014, 0x164018 };
-static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] = {
- 0x1640d0, 0x1640d4 };
+static const u32 page_vals_e2[] = { 0, 128 };
+#define PAGE_MODE_VALUES_E2 ARRAY_SIZE(page_vals_e2)
-#define TIMER_REGS_COUNT_E2 2
+static const u32 page_write_regs_e2[] = { 328476 };
+#define PAGE_WRITE_REGS_E2 ARRAY_SIZE(page_write_regs_e2)
-static const u32 timer_status_regs_e2[TIMER_REGS_COUNT_E2] = {
- 0x164014, 0x164018 };
-static const u32 timer_scan_regs_e2[TIMER_REGS_COUNT_E2] = {
- 0x1640d0, 0x1640d4 };
-
-#define PAGE_MODE_VALUES_E1 0
-
-#define PAGE_READ_REGS_E1 0
-
-#define PAGE_WRITE_REGS_E1 0
-
-static const u32 page_vals_e1[] = { 0 };
-
-static const u32 page_write_regs_e1[] = { 0 };
-
-static const struct reg_addr page_read_regs_e1[] = { { 0x0, 0, RI_E1_ONLINE } };
-
-#define PAGE_MODE_VALUES_E1H 0
-
-#define PAGE_READ_REGS_E1H 0
-
-#define PAGE_WRITE_REGS_E1H 0
-
-static const u32 page_vals_e1h[] = { 0 };
-
-static const u32 page_write_regs_e1h[] = { 0 };
-
-static const struct reg_addr page_read_regs_e1h[] = {
- { 0x0, 0, RI_E1H_ONLINE } };
-
-#define PAGE_MODE_VALUES_E2 2
-
-#define PAGE_READ_REGS_E2 1
-
-#define PAGE_WRITE_REGS_E2 1
+static const struct reg_addr page_read_regs_e2[] = {
+ { 0x58000, 4608, RI_E2_ONLINE } };
+#define PAGE_READ_REGS_E2 ARRAY_SIZE(page_read_regs_e2)
-static const u32 page_vals_e2[PAGE_MODE_VALUES_E2] = { 0, 128 };
+static const u32 page_vals_e3[] = { 0, 128 };
+#define PAGE_MODE_VALUES_E3 ARRAY_SIZE(page_vals_e3)
-static const u32 page_write_regs_e2[PAGE_WRITE_REGS_E2] = { 328476 };
+static const u32 page_write_regs_e3[] = { 328476 };
+#define PAGE_WRITE_REGS_E3 ARRAY_SIZE(page_write_regs_e3)
-static const struct reg_addr page_read_regs_e2[PAGE_READ_REGS_E2] = {
- { 0x58000, 4608, RI_E2_ONLINE } };
+static const struct reg_addr page_read_regs_e3[] = {
+ { 0x58000, 4608, RI_E3E3B0_ONLINE } };
+#define PAGE_READ_REGS_E3 ARRAY_SIZE(page_read_regs_e3)
#endif /* BNX2X_DUMP_H */
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 727fe89ff37f..221863059dae 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -25,6 +25,7 @@
#include "bnx2x_cmn.h"
#include "bnx2x_dump.h"
#include "bnx2x_init.h"
+#include "bnx2x_sp.h"
/* Note: in the format strings below %s is replaced by the queue-name which is
* either its index or 'fcoe' for the fcoe queue. Make sure the format string
@@ -37,8 +38,6 @@ static const struct {
char string[ETH_GSTRING_LEN];
} bnx2x_q_stats_arr[] = {
/* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%s]: rx_bytes" },
- { Q_STATS_OFFSET32(error_bytes_received_hi),
- 8, "[%s]: rx_error_bytes" },
{ Q_STATS_OFFSET32(total_unicast_packets_received_hi),
8, "[%s]: rx_ucast_packets" },
{ Q_STATS_OFFSET32(total_multicast_packets_received_hi),
@@ -52,13 +51,18 @@ static const struct {
4, "[%s]: rx_skb_alloc_discard" },
{ Q_STATS_OFFSET32(hw_csum_err), 4, "[%s]: rx_csum_offload_errors" },
-/* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%s]: tx_bytes" },
- { Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
+ { Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%s]: tx_bytes" },
+/* 10 */{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
8, "[%s]: tx_ucast_packets" },
{ Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi),
8, "[%s]: tx_mcast_packets" },
{ Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
- 8, "[%s]: tx_bcast_packets" }
+ 8, "[%s]: tx_bcast_packets" },
+ { Q_STATS_OFFSET32(total_tpa_aggregations_hi),
+ 8, "[%s]: tpa_aggregations" },
+ { Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi),
+ 8, "[%s]: tpa_aggregated_frames"},
+ { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"}
};
#define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
@@ -98,8 +102,8 @@ static const struct {
8, STATS_FLAGS_BOTH, "rx_discards" },
{ STATS_OFFSET32(mac_filter_discard),
4, STATS_FLAGS_PORT, "rx_filtered_packets" },
- { STATS_OFFSET32(xxoverflow_discard),
- 4, STATS_FLAGS_PORT, "rx_fw_discards" },
+ { STATS_OFFSET32(mf_tag_discard),
+ 4, STATS_FLAGS_PORT, "rx_mf_tag_discard" },
{ STATS_OFFSET32(brb_drop_hi),
8, STATS_FLAGS_PORT, "rx_brb_discard" },
{ STATS_OFFSET32(brb_truncate_hi),
@@ -158,10 +162,43 @@ static const struct {
{ STATS_OFFSET32(etherstatspktsover1522octets_hi),
8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" },
{ STATS_OFFSET32(pause_frames_sent_hi),
- 8, STATS_FLAGS_PORT, "tx_pause_frames" }
+ 8, STATS_FLAGS_PORT, "tx_pause_frames" },
+ { STATS_OFFSET32(total_tpa_aggregations_hi),
+ 8, STATS_FLAGS_FUNC, "tpa_aggregations" },
+ { STATS_OFFSET32(total_tpa_aggregated_frames_hi),
+ 8, STATS_FLAGS_FUNC, "tpa_aggregated_frames"},
+ { STATS_OFFSET32(total_tpa_bytes_hi),
+ 8, STATS_FLAGS_FUNC, "tpa_bytes"}
};
#define BNX2X_NUM_STATS ARRAY_SIZE(bnx2x_stats_arr)
+static int bnx2x_get_port_type(struct bnx2x *bp)
+{
+ int port_type;
+ u32 phy_idx = bnx2x_get_cur_phy_idx(bp);
+ switch (bp->link_params.phy[phy_idx].media_type) {
+ case ETH_PHY_SFP_FIBER:
+ case ETH_PHY_XFP_FIBER:
+ case ETH_PHY_KR:
+ case ETH_PHY_CX4:
+ port_type = PORT_FIBRE;
+ break;
+ case ETH_PHY_DA_TWINAX:
+ port_type = PORT_DA;
+ break;
+ case ETH_PHY_BASE_T:
+ port_type = PORT_TP;
+ break;
+ case ETH_PHY_NOT_PRESENT:
+ port_type = PORT_NONE;
+ break;
+ case ETH_PHY_UNSPECIFIED:
+ default:
+ port_type = PORT_OTHER;
+ break;
+ }
+ return port_type;
+}
static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
@@ -188,12 +225,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (IS_MF(bp))
ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
- if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
- cmd->port = PORT_TP;
- else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
- cmd->port = PORT_FIBRE;
- else
- BNX2X_ERR("XGXS PHY Failure detected\n");
+ cmd->port = bnx2x_get_port_type(bp);
cmd->phy_address = bp->mdio.prtad;
cmd->transceiver = XCVR_INTERNAL;
@@ -468,78 +500,179 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
#define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
#define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
#define IS_E2_ONLINE(info) (((info) & RI_E2_ONLINE) == RI_E2_ONLINE)
+#define IS_E3_ONLINE(info) (((info) & RI_E3_ONLINE) == RI_E3_ONLINE)
+#define IS_E3B0_ONLINE(info) (((info) & RI_E3B0_ONLINE) == RI_E3B0_ONLINE)
+
+static inline bool bnx2x_is_reg_online(struct bnx2x *bp,
+ const struct reg_addr *reg_info)
+{
+ if (CHIP_IS_E1(bp))
+ return IS_E1_ONLINE(reg_info->info);
+ else if (CHIP_IS_E1H(bp))
+ return IS_E1H_ONLINE(reg_info->info);
+ else if (CHIP_IS_E2(bp))
+ return IS_E2_ONLINE(reg_info->info);
+ else if (CHIP_IS_E3A0(bp))
+ return IS_E3_ONLINE(reg_info->info);
+ else if (CHIP_IS_E3B0(bp))
+ return IS_E3B0_ONLINE(reg_info->info);
+ else
+ return false;
+}
+
+/******* Paged registers info selectors ********/
+static inline const u32 *__bnx2x_get_page_addr_ar(struct bnx2x *bp)
+{
+ if (CHIP_IS_E2(bp))
+ return page_vals_e2;
+ else if (CHIP_IS_E3(bp))
+ return page_vals_e3;
+ else
+ return NULL;
+}
+
+static inline u32 __bnx2x_get_page_reg_num(struct bnx2x *bp)
+{
+ if (CHIP_IS_E2(bp))
+ return PAGE_MODE_VALUES_E2;
+ else if (CHIP_IS_E3(bp))
+ return PAGE_MODE_VALUES_E3;
+ else
+ return 0;
+}
+
+static inline const u32 *__bnx2x_get_page_write_ar(struct bnx2x *bp)
+{
+ if (CHIP_IS_E2(bp))
+ return page_write_regs_e2;
+ else if (CHIP_IS_E3(bp))
+ return page_write_regs_e3;
+ else
+ return NULL;
+}
+
+static inline u32 __bnx2x_get_page_write_num(struct bnx2x *bp)
+{
+ if (CHIP_IS_E2(bp))
+ return PAGE_WRITE_REGS_E2;
+ else if (CHIP_IS_E3(bp))
+ return PAGE_WRITE_REGS_E3;
+ else
+ return 0;
+}
+
+static inline const struct reg_addr *__bnx2x_get_page_read_ar(struct bnx2x *bp)
+{
+ if (CHIP_IS_E2(bp))
+ return page_read_regs_e2;
+ else if (CHIP_IS_E3(bp))
+ return page_read_regs_e3;
+ else
+ return NULL;
+}
+
+static inline u32 __bnx2x_get_page_read_num(struct bnx2x *bp)
+{
+ if (CHIP_IS_E2(bp))
+ return PAGE_READ_REGS_E2;
+ else if (CHIP_IS_E3(bp))
+ return PAGE_READ_REGS_E3;
+ else
+ return 0;
+}
+
+static inline int __bnx2x_get_regs_len(struct bnx2x *bp)
+{
+ int num_pages = __bnx2x_get_page_reg_num(bp);
+ int page_write_num = __bnx2x_get_page_write_num(bp);
+ const struct reg_addr *page_read_addr = __bnx2x_get_page_read_ar(bp);
+ int page_read_num = __bnx2x_get_page_read_num(bp);
+ int regdump_len = 0;
+ int i, j, k;
+
+ for (i = 0; i < REGS_COUNT; i++)
+ if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
+ regdump_len += reg_addrs[i].size;
+
+ for (i = 0; i < num_pages; i++)
+ for (j = 0; j < page_write_num; j++)
+ for (k = 0; k < page_read_num; k++)
+ if (bnx2x_is_reg_online(bp, &page_read_addr[k]))
+ regdump_len += page_read_addr[k].size;
+
+ return regdump_len;
+}
static int bnx2x_get_regs_len(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
int regdump_len = 0;
- int i, j, k;
- if (CHIP_IS_E1(bp)) {
- for (i = 0; i < REGS_COUNT; i++)
- if (IS_E1_ONLINE(reg_addrs[i].info))
- regdump_len += reg_addrs[i].size;
-
- for (i = 0; i < WREGS_COUNT_E1; i++)
- if (IS_E1_ONLINE(wreg_addrs_e1[i].info))
- regdump_len += wreg_addrs_e1[i].size *
- (1 + wreg_addrs_e1[i].read_regs_count);
-
- } else if (CHIP_IS_E1H(bp)) {
- for (i = 0; i < REGS_COUNT; i++)
- if (IS_E1H_ONLINE(reg_addrs[i].info))
- regdump_len += reg_addrs[i].size;
-
- for (i = 0; i < WREGS_COUNT_E1H; i++)
- if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info))
- regdump_len += wreg_addrs_e1h[i].size *
- (1 + wreg_addrs_e1h[i].read_regs_count);
- } else if (CHIP_IS_E2(bp)) {
- for (i = 0; i < REGS_COUNT; i++)
- if (IS_E2_ONLINE(reg_addrs[i].info))
- regdump_len += reg_addrs[i].size;
-
- for (i = 0; i < WREGS_COUNT_E2; i++)
- if (IS_E2_ONLINE(wreg_addrs_e2[i].info))
- regdump_len += wreg_addrs_e2[i].size *
- (1 + wreg_addrs_e2[i].read_regs_count);
-
- for (i = 0; i < PAGE_MODE_VALUES_E2; i++)
- for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
- for (k = 0; k < PAGE_READ_REGS_E2; k++)
- if (IS_E2_ONLINE(page_read_regs_e2[k].
- info))
- regdump_len +=
- page_read_regs_e2[k].size;
- }
- }
+ regdump_len = __bnx2x_get_regs_len(bp);
regdump_len *= 4;
regdump_len += sizeof(struct dump_hdr);
return regdump_len;
}
-static inline void bnx2x_read_pages_regs_e2(struct bnx2x *bp, u32 *p)
+/**
+ * bnx2x_read_pages_regs - read "paged" registers
+ *
+ * @bp device handle
+ * @p output buffer
+ *
+ * Reads "paged" memories: memories that may only be read by first writing to a
+ * specific address ("write address") and then reading from a specific address
+ * ("read address"). There may be more than one write address per "page" and
+ * more than one read address per write address.
+ */
+static inline void bnx2x_read_pages_regs(struct bnx2x *bp, u32 *p)
{
u32 i, j, k, n;
-
- for (i = 0; i < PAGE_MODE_VALUES_E2; i++) {
- for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
- REG_WR(bp, page_write_regs_e2[j], page_vals_e2[i]);
- for (k = 0; k < PAGE_READ_REGS_E2; k++)
- if (IS_E2_ONLINE(page_read_regs_e2[k].info))
+ /* addresses of the paged registers */
+ const u32 *page_addr = __bnx2x_get_page_addr_ar(bp);
+ /* number of paged registers */
+ int num_pages = __bnx2x_get_page_reg_num(bp);
+ /* write addresses */
+ const u32 *write_addr = __bnx2x_get_page_write_ar(bp);
+ /* number of write addresses */
+ int write_num = __bnx2x_get_page_write_num(bp);
+ /* read addresses info */
+ const struct reg_addr *read_addr = __bnx2x_get_page_read_ar(bp);
+ /* number of read addresses */
+ int read_num = __bnx2x_get_page_read_num(bp);
+
+ for (i = 0; i < num_pages; i++) {
+ for (j = 0; j < write_num; j++) {
+ REG_WR(bp, write_addr[j], page_addr[i]);
+ for (k = 0; k < read_num; k++)
+ if (bnx2x_is_reg_online(bp, &read_addr[k]))
for (n = 0; n <
- page_read_regs_e2[k].size; n++)
+ read_addr[k].size; n++)
*p++ = REG_RD(bp,
- page_read_regs_e2[k].addr + n*4);
+ read_addr[k].addr + n*4);
}
}
}
+static inline void __bnx2x_get_regs(struct bnx2x *bp, u32 *p)
+{
+ u32 i, j;
+
+ /* Read the regular registers */
+ for (i = 0; i < REGS_COUNT; i++)
+ if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
+ for (j = 0; j < reg_addrs[i].size; j++)
+ *p++ = REG_RD(bp, reg_addrs[i].addr + j*4);
+
+ /* Read "paged" registes */
+ bnx2x_read_pages_regs(bp, p);
+}
+
static void bnx2x_get_regs(struct net_device *dev,
struct ethtool_regs *regs, void *_p)
{
- u32 *p = _p, i, j;
+ u32 *p = _p;
struct bnx2x *bp = netdev_priv(dev);
struct dump_hdr dump_hdr = {0};
@@ -566,44 +699,21 @@ static void bnx2x_get_regs(struct net_device *dev,
dump_hdr.info = RI_E1_ONLINE;
else if (CHIP_IS_E1H(bp))
dump_hdr.info = RI_E1H_ONLINE;
- else if (CHIP_IS_E2(bp))
+ else if (!CHIP_IS_E1x(bp))
dump_hdr.info = RI_E2_ONLINE |
(BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP);
memcpy(p, &dump_hdr, sizeof(struct dump_hdr));
p += dump_hdr.hdr_size + 1;
- if (CHIP_IS_E1(bp)) {
- for (i = 0; i < REGS_COUNT; i++)
- if (IS_E1_ONLINE(reg_addrs[i].info))
- for (j = 0; j < reg_addrs[i].size; j++)
- *p++ = REG_RD(bp,
- reg_addrs[i].addr + j*4);
-
- } else if (CHIP_IS_E1H(bp)) {
- for (i = 0; i < REGS_COUNT; i++)
- if (IS_E1H_ONLINE(reg_addrs[i].info))
- for (j = 0; j < reg_addrs[i].size; j++)
- *p++ = REG_RD(bp,
- reg_addrs[i].addr + j*4);
-
- } else if (CHIP_IS_E2(bp)) {
- for (i = 0; i < REGS_COUNT; i++)
- if (IS_E2_ONLINE(reg_addrs[i].info))
- for (j = 0; j < reg_addrs[i].size; j++)
- *p++ = REG_RD(bp,
- reg_addrs[i].addr + j*4);
-
- bnx2x_read_pages_regs_e2(bp, p);
- }
+ /* Actually read the registers */
+ __bnx2x_get_regs(bp, p);
+
/* Re-enable parity attentions */
bnx2x_clear_blocks_parity(bp);
- if (CHIP_PARITY_ENABLED(bp))
- bnx2x_enable_blocks_parity(bp);
+ bnx2x_enable_blocks_parity(bp);
}
-#define PHY_FW_VER_LEN 20
-
static void bnx2x_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -682,8 +792,12 @@ static void bnx2x_set_msglevel(struct net_device *dev, u32 level)
{
struct bnx2x *bp = netdev_priv(dev);
- if (capable(CAP_NET_ADMIN))
+ if (capable(CAP_NET_ADMIN)) {
+ /* dump MCP trace */
+ if (level & BNX2X_MSG_MCP)
+ bnx2x_fw_dump_lvl(bp, KERN_INFO);
bp->msg_enable = level;
+ }
}
static int bnx2x_nway_reset(struct net_device *dev)
@@ -725,7 +839,7 @@ static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
u32 val = 0;
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -756,7 +870,7 @@ static int bnx2x_release_nvram_lock(struct bnx2x *bp)
u32 val = 0;
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -824,7 +938,7 @@ static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -947,7 +1061,7 @@ static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val,
REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -1051,9 +1165,9 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
while ((written_so_far < buf_size) && (rc == 0)) {
if (written_so_far == (buf_size - sizeof(u32)))
cmd_flags |= MCPR_NVM_COMMAND_LAST;
- else if (((offset + 4) % NVRAM_PAGE_SIZE) == 0)
+ else if (((offset + 4) % BNX2X_NVRAM_PAGE_SIZE) == 0)
cmd_flags |= MCPR_NVM_COMMAND_LAST;
- else if ((offset % NVRAM_PAGE_SIZE) == 0)
+ else if ((offset % BNX2X_NVRAM_PAGE_SIZE) == 0)
cmd_flags |= MCPR_NVM_COMMAND_FIRST;
memcpy(&val, data_buf, 4);
@@ -1212,7 +1326,6 @@ static int bnx2x_set_ringparam(struct net_device *dev,
struct ethtool_ringparam *ering)
{
struct bnx2x *bp = netdev_priv(dev);
- int rc = 0;
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
printk(KERN_ERR "Handling parity error recovery. Try again later\n");
@@ -1229,12 +1342,7 @@ static int bnx2x_set_ringparam(struct net_device *dev,
bp->rx_ring_size = ering->rx_pending;
bp->tx_ring_size = ering->tx_pending;
- if (netif_running(dev)) {
- bnx2x_nic_unload(bp, UNLOAD_NORMAL);
- rc = bnx2x_nic_load(bp, LOAD_NORMAL);
- }
-
- return rc;
+ return bnx2x_reload_if_running(dev);
}
static void bnx2x_get_pauseparam(struct net_device *dev,
@@ -1313,60 +1421,129 @@ static const struct {
{ "idle check (online)" }
};
+enum {
+ BNX2X_CHIP_E1_OFST = 0,
+ BNX2X_CHIP_E1H_OFST,
+ BNX2X_CHIP_E2_OFST,
+ BNX2X_CHIP_E3_OFST,
+ BNX2X_CHIP_E3B0_OFST,
+ BNX2X_CHIP_MAX_OFST
+};
+
+#define BNX2X_CHIP_MASK_E1 (1 << BNX2X_CHIP_E1_OFST)
+#define BNX2X_CHIP_MASK_E1H (1 << BNX2X_CHIP_E1H_OFST)
+#define BNX2X_CHIP_MASK_E2 (1 << BNX2X_CHIP_E2_OFST)
+#define BNX2X_CHIP_MASK_E3 (1 << BNX2X_CHIP_E3_OFST)
+#define BNX2X_CHIP_MASK_E3B0 (1 << BNX2X_CHIP_E3B0_OFST)
+
+#define BNX2X_CHIP_MASK_ALL ((1 << BNX2X_CHIP_MAX_OFST) - 1)
+#define BNX2X_CHIP_MASK_E1X (BNX2X_CHIP_MASK_E1 | BNX2X_CHIP_MASK_E1H)
+
static int bnx2x_test_registers(struct bnx2x *bp)
{
int idx, i, rc = -ENODEV;
- u32 wr_val = 0;
+ u32 wr_val = 0, hw;
int port = BP_PORT(bp);
static const struct {
+ u32 hw;
u32 offset0;
u32 offset1;
u32 mask;
} reg_tbl[] = {
-/* 0 */ { BRB1_REG_PAUSE_LOW_THRESHOLD_0, 4, 0x000003ff },
- { DORQ_REG_DB_ADDR0, 4, 0xffffffff },
- { HC_REG_AGG_INT_0, 4, 0x000003ff },
- { PBF_REG_MAC_IF0_ENABLE, 4, 0x00000001 },
- { PBF_REG_P0_INIT_CRD, 4, 0x000007ff },
- { PRS_REG_CID_PORT_0, 4, 0x00ffffff },
- { PXP2_REG_PSWRQ_CDU0_L2P, 4, 0x000fffff },
- { PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
- { PXP2_REG_PSWRQ_TM0_L2P, 4, 0x000fffff },
- { PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
-/* 10 */ { PXP2_REG_PSWRQ_TSDM0_L2P, 4, 0x000fffff },
- { QM_REG_CONNNUM_0, 4, 0x000fffff },
- { TM_REG_LIN0_MAX_ACTIVE_CID, 4, 0x0003ffff },
- { SRC_REG_KEYRSS0_0, 40, 0xffffffff },
- { SRC_REG_KEYRSS0_7, 40, 0xffffffff },
- { XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
- { XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 },
- { XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff },
- { NIG_REG_LLH0_T_BIT, 4, 0x00000001 },
- { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
-/* 20 */ { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
- { NIG_REG_XCM0_OUT_EN, 4, 0x00000001 },
- { NIG_REG_BRB0_OUT_EN, 4, 0x00000001 },
- { NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 },
- { NIG_REG_LLH0_ACPI_PAT_6_LEN, 68, 0x000000ff },
- { NIG_REG_LLH0_ACPI_PAT_0_CRC, 68, 0xffffffff },
- { NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff },
- { NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff },
- { NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 },
- { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
-/* 30 */ { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
- { NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff },
- { NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 },
- { NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 },
- { NIG_REG_STATUS_INTERRUPT_PORT0, 4, 0x07ffffff },
- { NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 },
- { NIG_REG_SERDES0_CTRL_PHY_ADDR, 16, 0x0000001f },
-
- { 0xffffffff, 0, 0x00000000 }
+/* 0 */ { BNX2X_CHIP_MASK_ALL,
+ BRB1_REG_PAUSE_LOW_THRESHOLD_0, 4, 0x000003ff },
+ { BNX2X_CHIP_MASK_ALL,
+ DORQ_REG_DB_ADDR0, 4, 0xffffffff },
+ { BNX2X_CHIP_MASK_E1X,
+ HC_REG_AGG_INT_0, 4, 0x000003ff },
+ { BNX2X_CHIP_MASK_ALL,
+ PBF_REG_MAC_IF0_ENABLE, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2 | BNX2X_CHIP_MASK_E3,
+ PBF_REG_P0_INIT_CRD, 4, 0x000007ff },
+ { BNX2X_CHIP_MASK_E3B0,
+ PBF_REG_INIT_CRD_Q0, 4, 0x000007ff },
+ { BNX2X_CHIP_MASK_ALL,
+ PRS_REG_CID_PORT_0, 4, 0x00ffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_PSWRQ_CDU0_L2P, 4, 0x000fffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_PSWRQ_TM0_L2P, 4, 0x000fffff },
+/* 10 */ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_PSWRQ_TSDM0_L2P, 4, 0x000fffff },
+ { BNX2X_CHIP_MASK_ALL,
+ QM_REG_CONNNUM_0, 4, 0x000fffff },
+ { BNX2X_CHIP_MASK_ALL,
+ TM_REG_LIN0_MAX_ACTIVE_CID, 4, 0x0003ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ SRC_REG_KEYRSS0_0, 40, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ SRC_REG_KEYRSS0_7, 40, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 },
+ { BNX2X_CHIP_MASK_ALL,
+ XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_T_BIT, 4, 0x00000001 },
+/* 20 */ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_XCM0_OUT_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_BRB0_OUT_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_ACPI_PAT_6_LEN, 68, 0x000000ff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_ACPI_PAT_0_CRC, 68, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 },
+/* 30 */ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001},
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_STATUS_INTERRUPT_PORT0, 4, 0x07ffffff },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_SERDES0_CTRL_PHY_ADDR, 16, 0x0000001f },
+
+ { BNX2X_CHIP_MASK_ALL, 0xffffffff, 0, 0x00000000 }
};
if (!netif_running(bp->dev))
return rc;
+ if (CHIP_IS_E1(bp))
+ hw = BNX2X_CHIP_MASK_E1;
+ else if (CHIP_IS_E1H(bp))
+ hw = BNX2X_CHIP_MASK_E1H;
+ else if (CHIP_IS_E2(bp))
+ hw = BNX2X_CHIP_MASK_E2;
+ else if (CHIP_IS_E3B0(bp))
+ hw = BNX2X_CHIP_MASK_E3B0;
+ else /* e3 A0 */
+ hw = BNX2X_CHIP_MASK_E3;
+
/* Repeat the test twice:
First by writing 0x00000000, second by writing 0xffffffff */
for (idx = 0; idx < 2; idx++) {
@@ -1382,8 +1559,7 @@ static int bnx2x_test_registers(struct bnx2x *bp)
for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
u32 offset, mask, save_val, val;
- if (CHIP_IS_E2(bp) &&
- reg_tbl[i].offset0 == HC_REG_AGG_INT_0)
+ if (!(hw & reg_tbl[i].hw))
continue;
offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
@@ -1400,7 +1576,7 @@ static int bnx2x_test_registers(struct bnx2x *bp)
/* verify value is as expected */
if ((val & mask) != (wr_val & mask)) {
- DP(NETIF_MSG_PROBE,
+ DP(NETIF_MSG_HW,
"offset 0x%x: val 0x%x != 0x%x mask 0x%x\n",
offset, val, wr_val, mask);
goto test_reg_exit;
@@ -1417,7 +1593,7 @@ test_reg_exit:
static int bnx2x_test_memory(struct bnx2x *bp)
{
int i, j, rc = -ENODEV;
- u32 val;
+ u32 val, index;
static const struct {
u32 offset;
int size;
@@ -1432,32 +1608,44 @@ static int bnx2x_test_memory(struct bnx2x *bp)
{ 0xffffffff, 0 }
};
+
static const struct {
char *name;
u32 offset;
- u32 e1_mask;
- u32 e1h_mask;
- u32 e2_mask;
+ u32 hw_mask[BNX2X_CHIP_MAX_OFST];
} prty_tbl[] = {
- { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0, 0 },
- { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2, 0 },
- { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0, 0 },
- { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0, 0 },
- { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0, 0 },
- { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0, 0 },
-
- { NULL, 0xffffffff, 0, 0, 0 }
+ { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS,
+ {0x3ffc0, 0, 0, 0} },
+ { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS,
+ {0x2, 0x2, 0, 0} },
+ { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS,
+ {0, 0, 0, 0} },
+ { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS,
+ {0x3ffc0, 0, 0, 0} },
+ { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS,
+ {0x3ffc0, 0, 0, 0} },
+ { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS,
+ {0x3ffc1, 0, 0, 0} },
+
+ { NULL, 0xffffffff, {0, 0, 0, 0} }
};
if (!netif_running(bp->dev))
return rc;
+ if (CHIP_IS_E1(bp))
+ index = BNX2X_CHIP_E1_OFST;
+ else if (CHIP_IS_E1H(bp))
+ index = BNX2X_CHIP_E1H_OFST;
+ else if (CHIP_IS_E2(bp))
+ index = BNX2X_CHIP_E2_OFST;
+ else /* e3 */
+ index = BNX2X_CHIP_E3_OFST;
+
/* pre-Check the parity status */
for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
val = REG_RD(bp, prty_tbl[i].offset);
- if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
- (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
- (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+ if (val & ~(prty_tbl[i].hw_mask[index])) {
DP(NETIF_MSG_HW,
"%s is 0x%x\n", prty_tbl[i].name, val);
goto test_mem_exit;
@@ -1472,9 +1660,7 @@ static int bnx2x_test_memory(struct bnx2x *bp)
/* Check the parity status */
for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
val = REG_RD(bp, prty_tbl[i].offset);
- if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
- (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
- (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+ if (val & ~(prty_tbl[i].hw_mask[index])) {
DP(NETIF_MSG_HW,
"%s is 0x%x\n", prty_tbl[i].name, val);
goto test_mem_exit;
@@ -1491,28 +1677,33 @@ static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
{
int cnt = 1400;
- if (link_up)
+ if (link_up) {
while (bnx2x_link_test(bp, is_serdes) && cnt--)
- msleep(10);
+ msleep(20);
+
+ if (cnt <= 0 && bnx2x_link_test(bp, is_serdes))
+ DP(NETIF_MSG_LINK, "Timeout waiting for link up\n");
+ }
}
-static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
+static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
{
unsigned int pkt_size, num_pkts, i;
struct sk_buff *skb;
unsigned char *packet;
struct bnx2x_fastpath *fp_rx = &bp->fp[0];
struct bnx2x_fastpath *fp_tx = &bp->fp[0];
+ struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
u16 tx_start_idx, tx_idx;
u16 rx_start_idx, rx_idx;
- u16 pkt_prod, bd_prod;
+ u16 pkt_prod, bd_prod, rx_comp_cons;
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
dma_addr_t mapping;
union eth_rx_cqe *cqe;
- u8 cqe_fp_flags;
+ u8 cqe_fp_flags, cqe_fp_type;
struct sw_rx_bd *rx_buf;
u16 len;
int rc = -ENODEV;
@@ -1524,7 +1715,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
return -EINVAL;
break;
case BNX2X_MAC_LOOPBACK:
- bp->link_params.loopback_mode = LOOPBACK_BMAC;
+ bp->link_params.loopback_mode = CHIP_IS_E3(bp) ?
+ LOOPBACK_XMAC : LOOPBACK_BMAC;
bnx2x_phy_init(&bp->link_params, &bp->link_vars);
break;
default:
@@ -1545,22 +1737,28 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
memset(packet + 2*ETH_ALEN, 0x77, (ETH_HLEN - 2*ETH_ALEN));
for (i = ETH_HLEN; i < pkt_size; i++)
packet[i] = (unsigned char) (i & 0xff);
+ mapping = dma_map_single(&bp->pdev->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ rc = -ENOMEM;
+ dev_kfree_skb(skb);
+ BNX2X_ERR("Unable to map SKB\n");
+ goto test_loopback_exit;
+ }
/* send the loopback packet */
num_pkts = 0;
- tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
+ tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb);
rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
- pkt_prod = fp_tx->tx_pkt_prod++;
- tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)];
- tx_buf->first_bd = fp_tx->tx_bd_prod;
+ pkt_prod = txdata->tx_pkt_prod++;
+ tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
+ tx_buf->first_bd = txdata->tx_bd_prod;
tx_buf->skb = skb;
tx_buf->flags = 0;
- bd_prod = TX_BD(fp_tx->tx_bd_prod);
- tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd;
- mapping = dma_map_single(&bp->pdev->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
+ bd_prod = TX_BD(txdata->tx_bd_prod);
+ tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
@@ -1577,26 +1775,27 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x;
- pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2;
+ pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
+ pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
wmb();
- fp_tx->tx_db.data.prod += 2;
+ txdata->tx_db.data.prod += 2;
barrier();
- DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw);
+ DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
mmiowb();
+ barrier();
num_pkts++;
- fp_tx->tx_bd_prod += 2; /* start + pbd */
+ txdata->tx_bd_prod += 2; /* start + pbd */
udelay(100);
- tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
+ tx_idx = le16_to_cpu(*txdata->tx_cons_sb);
if (tx_idx != tx_start_idx + num_pkts)
goto test_loopback_exit;
@@ -1610,7 +1809,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
* bnx2x_tx_int()), as both are taking netif_tx_lock().
*/
local_bh_disable();
- bnx2x_tx_int(fp_tx);
+ bnx2x_tx_int(bp, txdata);
local_bh_enable();
}
@@ -1618,9 +1817,11 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
if (rx_idx != rx_start_idx + num_pkts)
goto test_loopback_exit;
- cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)];
+ rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons);
+ cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)];
cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
- if (CQE_TYPE(cqe_fp_flags) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
+ cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
+ if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
goto test_loopback_rx_exit;
len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
@@ -1628,6 +1829,9 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
goto test_loopback_rx_exit;
rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)];
+ dma_sync_single_for_cpu(&bp->pdev->dev,
+ dma_unmap_addr(rx_buf, mapping),
+ fp_rx->rx_buf_size, DMA_FROM_DEVICE);
skb = rx_buf->skb;
skb_reserve(skb, cqe->fast_path_cqe.placement_offset);
for (i = ETH_HLEN; i < pkt_size; i++)
@@ -1653,7 +1857,7 @@ test_loopback_exit:
return rc;
}
-static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
+static int bnx2x_test_loopback(struct bnx2x *bp)
{
int rc = 0, res;
@@ -1666,13 +1870,13 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
bnx2x_netif_stop(bp, 1);
bnx2x_acquire_phy_lock(bp);
- res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK, link_up);
+ res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK);
if (res) {
DP(NETIF_MSG_PROBE, " PHY loopback failed (res %d)\n", res);
rc |= BNX2X_PHY_LOOPBACK_FAILED;
}
- res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up);
+ res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK);
if (res) {
DP(NETIF_MSG_PROBE, " MAC loopback failed (res %d)\n", res);
rc |= BNX2X_MAC_LOOPBACK_FAILED;
@@ -1744,39 +1948,20 @@ test_nvram_exit:
return rc;
}
+/* Send an EMPTY ramrod on the first queue */
static int bnx2x_test_intr(struct bnx2x *bp)
{
- struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
- int i, rc;
+ struct bnx2x_queue_state_params params = {0};
if (!netif_running(bp->dev))
return -ENODEV;
- config->hdr.length = 0;
- if (CHIP_IS_E1(bp))
- config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
- else
- config->hdr.offset = BP_FUNC(bp);
- config->hdr.client_id = bp->fp->cl_id;
- config->hdr.reserved1 = 0;
-
- bp->set_mac_pending = 1;
- smp_wmb();
- rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mac_config)),
- U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
- if (rc == 0) {
- for (i = 0; i < 10; i++) {
- if (!bp->set_mac_pending)
- break;
- smp_rmb();
- msleep_interruptible(10);
- }
- if (i == 10)
- rc = -ENODEV;
- }
+ params.q_obj = &bp->fp->q_obj;
+ params.cmd = BNX2X_Q_CMD_EMPTY;
- return rc;
+ __set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
+
+ return bnx2x_queue_state_change(bp, &params);
}
static void bnx2x_self_test(struct net_device *dev,
@@ -1815,7 +2000,7 @@ static void bnx2x_self_test(struct net_device *dev,
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_DIAG);
/* wait until link state is restored */
- bnx2x_wait_for_link(bp, link_up, is_serdes);
+ bnx2x_wait_for_link(bp, 1, is_serdes);
if (bnx2x_test_registers(bp) != 0) {
buf[0] = 1;
@@ -1826,7 +2011,7 @@ static void bnx2x_self_test(struct net_device *dev,
etest->flags |= ETH_TEST_FL_FAILED;
}
- buf[2] = bnx2x_test_loopback(bp, link_up);
+ buf[2] = bnx2x_test_loopback(bp);
if (buf[2] != 0)
etest->flags |= ETH_TEST_FL_FAILED;
@@ -1864,6 +2049,14 @@ static void bnx2x_self_test(struct net_device *dev,
#define IS_MF_MODE_STAT(bp) \
(IS_MF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
+/* ethtool statistics are displayed for all regular ethernet queues and the
+ * fcoe L2 queue if not disabled
+ */
+static inline int bnx2x_num_stat_queues(struct bnx2x *bp)
+{
+ return BNX2X_NUM_ETH_QUEUES(bp);
+}
+
static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -1872,7 +2065,7 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
switch (stringset) {
case ETH_SS_STATS:
if (is_multi(bp)) {
- num_stats = BNX2X_NUM_STAT_QUEUES(bp) *
+ num_stats = bnx2x_num_stat_queues(bp) *
BNX2X_NUM_Q_STATS;
if (!IS_MF_MODE_STAT(bp))
num_stats += BNX2X_NUM_STATS;
@@ -1905,14 +2098,9 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
case ETH_SS_STATS:
if (is_multi(bp)) {
k = 0;
- for_each_napi_queue(bp, i) {
+ for_each_eth_queue(bp, i) {
memset(queue_name, 0, sizeof(queue_name));
-
- if (IS_FCOE_IDX(i))
- sprintf(queue_name, "fcoe");
- else
- sprintf(queue_name, "%d", i);
-
+ sprintf(queue_name, "%d", i);
for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
snprintf(buf + (k + j)*ETH_GSTRING_LEN,
ETH_GSTRING_LEN,
@@ -1951,7 +2139,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
if (is_multi(bp)) {
k = 0;
- for_each_napi_queue(bp, i) {
+ for_each_eth_queue(bp, i) {
hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
if (bnx2x_q_stats_arr[j].size == 0) {
@@ -2069,14 +2257,30 @@ static int bnx2x_get_rxfh_indir(struct net_device *dev,
{
struct bnx2x *bp = netdev_priv(dev);
size_t copy_size =
- min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
+ min_t(size_t, indir->size, T_ETH_INDIRECTION_TABLE_SIZE);
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+ size_t i;
if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
return -EOPNOTSUPP;
- indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
- memcpy(indir->ring_index, bp->rx_indir_table,
- copy_size * sizeof(bp->rx_indir_table[0]));
+ /* Get the current configuration of the RSS indirection table */
+ bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
+
+ /*
+ * We can't use a memcpy() as an internal storage of an
+ * indirection table is a u8 array while indir->ring_index
+ * points to an array of u32.
+ *
+ * Indirection table contains the FW Client IDs, so we need to
+ * align the returned table to the Client ID of the leading RSS
+ * queue.
+ */
+ for (i = 0; i < copy_size; i++)
+ indir->ring_index[i] = ind_table[i] - bp->fp->cl_id;
+
+ indir->size = T_ETH_INDIRECTION_TABLE_SIZE;
+
return 0;
}
@@ -2085,21 +2289,33 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev,
{
struct bnx2x *bp = netdev_priv(dev);
size_t i;
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+ u32 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
return -EOPNOTSUPP;
- /* Validate size and indices */
- if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
+ /* validate the size */
+ if (indir->size != T_ETH_INDIRECTION_TABLE_SIZE)
return -EINVAL;
- for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
- if (indir->ring_index[i] >= BNX2X_NUM_ETH_QUEUES(bp))
+
+ for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
+ /* validate the indices */
+ if (indir->ring_index[i] >= num_eth_queues)
return -EINVAL;
+ /*
+ * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy()
+ * as an internal storage of an indirection table is a u8 array
+ * while indir->ring_index points to an array of u32.
+ *
+ * Indirection table contains the FW Client IDs, so we need to
+ * align the received table to the Client ID of the leading RSS
+ * queue
+ */
+ ind_table[i] = indir->ring_index[i] + bp->fp->cl_id;
+ }
- memcpy(bp->rx_indir_table, indir->ring_index,
- indir->size * sizeof(bp->rx_indir_table[0]));
- bnx2x_push_indir_table(bp);
- return 0;
+ return bnx2x_config_rss_pf(bp, ind_table, false);
}
static const struct ethtool_ops bnx2x_ethtool_ops = {
diff --git a/drivers/net/bnx2x/bnx2x_fw_defs.h b/drivers/net/bnx2x/bnx2x_fw_defs.h
index 9fe367836a57..998652a1b858 100644
--- a/drivers/net/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/bnx2x/bnx2x_fw_defs.h
@@ -10,249 +10,221 @@
#ifndef BNX2X_FW_DEFS_H
#define BNX2X_FW_DEFS_H
-#define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[142].base)
+#define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[148].base)
#define CSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[141].base + ((assertListEntry) * IRO[141].m1))
-#define CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[144].base + ((pfId) * IRO[144].m1))
+ (IRO[147].base + ((assertListEntry) * IRO[147].m1))
#define CSTORM_EVENT_RING_DATA_OFFSET(pfId) \
- (IRO[149].base + (((pfId)>>1) * IRO[149].m1) + (((pfId)&1) * \
- IRO[149].m2))
+ (IRO[153].base + (((pfId)>>1) * IRO[153].m1) + (((pfId)&1) * \
+ IRO[153].m2))
#define CSTORM_EVENT_RING_PROD_OFFSET(pfId) \
- (IRO[150].base + (((pfId)>>1) * IRO[150].m1) + (((pfId)&1) * \
- IRO[150].m2))
+ (IRO[154].base + (((pfId)>>1) * IRO[154].m1) + (((pfId)&1) * \
+ IRO[154].m2))
#define CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(funcId) \
- (IRO[156].base + ((funcId) * IRO[156].m1))
+ (IRO[159].base + ((funcId) * IRO[159].m1))
#define CSTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[146].base + ((funcId) * IRO[146].m1))
-#define CSTORM_FUNCTION_MODE_OFFSET (IRO[153].base)
-#define CSTORM_IGU_MODE_OFFSET (IRO[154].base)
+ (IRO[149].base + ((funcId) * IRO[149].m1))
+#define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
#define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
- (IRO[311].base + ((pfId) * IRO[311].m1))
+ (IRO[315].base + ((pfId) * IRO[315].m1))
#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
- (IRO[312].base + ((pfId) * IRO[312].m1))
- #define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
- (IRO[304].base + ((pfId) * IRO[304].m1) + ((iscsiEqId) * \
- IRO[304].m2))
- #define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
- (IRO[306].base + ((pfId) * IRO[306].m1) + ((iscsiEqId) * \
- IRO[306].m2))
- #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
- (IRO[305].base + ((pfId) * IRO[305].m1) + ((iscsiEqId) * \
- IRO[305].m2))
- #define \
- CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
- (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * \
- IRO[307].m2))
- #define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
- (IRO[303].base + ((pfId) * IRO[303].m1) + ((iscsiEqId) * \
- IRO[303].m2))
- #define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
- (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * \
- IRO[309].m2))
- #define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
- (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * \
- IRO[308].m2))
+ (IRO[316].base + ((pfId) * IRO[316].m1))
+#define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
+ (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
+#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
+ (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
+ (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
+ (IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
+#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
+ (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * IRO[307].m2))
+#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
+ (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
+#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
+ (IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
#define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
- (IRO[310].base + ((pfId) * IRO[310].m1))
+ (IRO[314].base + ((pfId) * IRO[314].m1))
#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[302].base + ((pfId) * IRO[302].m1))
+ (IRO[306].base + ((pfId) * IRO[306].m1))
#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[301].base + ((pfId) * IRO[301].m1))
+ (IRO[305].base + ((pfId) * IRO[305].m1))
#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[300].base + ((pfId) * IRO[300].m1))
-#define CSTORM_PATH_ID_OFFSET (IRO[159].base)
+ (IRO[304].base + ((pfId) * IRO[304].m1))
+#define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[151].base + ((funcId) * IRO[151].m1))
#define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
- (IRO[137].base + ((pfId) * IRO[137].m1))
+ (IRO[142].base + ((pfId) * IRO[142].m1))
+#define CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(pfId) \
+ (IRO[143].base + ((pfId) * IRO[143].m1))
#define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \
- (IRO[136].base + ((pfId) * IRO[136].m1))
-#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[136].size)
+ (IRO[141].base + ((pfId) * IRO[141].m1))
+#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[141].size)
#define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \
- (IRO[138].base + ((pfId) * IRO[138].m1))
-#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[138].size)
-#define CSTORM_STATS_FLAGS_OFFSET(pfId) \
- (IRO[143].base + ((pfId) * IRO[143].m1))
+ (IRO[144].base + ((pfId) * IRO[144].m1))
+#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[144].size)
+#define CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(sbId, hcIndex) \
+ (IRO[136].base + ((sbId) * IRO[136].m1) + ((hcIndex) * IRO[136].m2))
#define CSTORM_STATUS_BLOCK_DATA_OFFSET(sbId) \
- (IRO[129].base + ((sbId) * IRO[129].m1))
+ (IRO[133].base + ((sbId) * IRO[133].m1))
+#define CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(sbId) \
+ (IRO[134].base + ((sbId) * IRO[134].m1))
+#define CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(sbId, hcIndex) \
+ (IRO[135].base + ((sbId) * IRO[135].m1) + ((hcIndex) * IRO[135].m2))
#define CSTORM_STATUS_BLOCK_OFFSET(sbId) \
- (IRO[128].base + ((sbId) * IRO[128].m1))
-#define CSTORM_STATUS_BLOCK_SIZE (IRO[128].size)
-#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
(IRO[132].base + ((sbId) * IRO[132].m1))
-#define CSTORM_SYNC_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_STATUS_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
+ (IRO[137].base + ((sbId) * IRO[137].m1))
+#define CSTORM_SYNC_BLOCK_SIZE (IRO[137].size)
#define CSTORM_VF_PF_CHANNEL_STATE_OFFSET(vfId) \
- (IRO[151].base + ((vfId) * IRO[151].m1))
+ (IRO[155].base + ((vfId) * IRO[155].m1))
#define CSTORM_VF_PF_CHANNEL_VALID_OFFSET(vfId) \
- (IRO[152].base + ((vfId) * IRO[152].m1))
+ (IRO[156].base + ((vfId) * IRO[156].m1))
#define CSTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[147].base + ((funcId) * IRO[147].m1))
-#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[199].base)
+ (IRO[150].base + ((funcId) * IRO[150].m1))
+#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[204].base)
#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
- (IRO[198].base + ((pfId) * IRO[198].m1))
-#define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[99].base)
+ (IRO[203].base + ((pfId) * IRO[203].m1))
+#define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[102].base)
#define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[98].base + ((assertListEntry) * IRO[98].m1))
- #define TSTORM_CLIENT_CONFIG_OFFSET(portId, clientId) \
- (IRO[197].base + ((portId) * IRO[197].m1) + ((clientId) * \
- IRO[197].m2))
-#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[104].base)
+ (IRO[101].base + ((assertListEntry) * IRO[101].m1))
+#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[107].base)
#define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \
- (IRO[105].base)
-#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[96].base + ((pfId) * IRO[96].m1))
-#define TSTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[101].base + ((funcId) * IRO[101].m1))
+ (IRO[108].base)
#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \
- (IRO[195].base + ((pfId) * IRO[195].m1))
-#define TSTORM_FUNCTION_MODE_OFFSET (IRO[103].base)
-#define TSTORM_INDIRECTION_TABLE_OFFSET(pfId) \
- (IRO[91].base + ((pfId) * IRO[91].m1))
-#define TSTORM_INDIRECTION_TABLE_SIZE (IRO[91].size)
- #define \
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfId, iscsiConBufPblEntry) \
- (IRO[260].base + ((pfId) * IRO[260].m1) + ((iscsiConBufPblEntry) \
- * IRO[260].m2))
+ (IRO[201].base + ((pfId) * IRO[201].m1))
+#define TSTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[103].base + ((funcId) * IRO[103].m1))
#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
- (IRO[264].base + ((pfId) * IRO[264].m1))
+ (IRO[271].base + ((pfId) * IRO[271].m1))
#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
- (IRO[265].base + ((pfId) * IRO[265].m1))
+ (IRO[272].base + ((pfId) * IRO[272].m1))
#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
- (IRO[266].base + ((pfId) * IRO[266].m1))
+ (IRO[273].base + ((pfId) * IRO[273].m1))
#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
- (IRO[267].base + ((pfId) * IRO[267].m1))
+ (IRO[274].base + ((pfId) * IRO[274].m1))
#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[263].base + ((pfId) * IRO[263].m1))
+ (IRO[270].base + ((pfId) * IRO[270].m1))
#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[262].base + ((pfId) * IRO[262].m1))
+ (IRO[269].base + ((pfId) * IRO[269].m1))
#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[261].base + ((pfId) * IRO[261].m1))
+ (IRO[268].base + ((pfId) * IRO[268].m1))
#define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
- (IRO[259].base + ((pfId) * IRO[259].m1))
+ (IRO[267].base + ((pfId) * IRO[267].m1))
#define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
- (IRO[269].base + ((pfId) * IRO[269].m1))
+ (IRO[276].base + ((pfId) * IRO[276].m1))
#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
- (IRO[256].base + ((pfId) * IRO[256].m1))
+ (IRO[263].base + ((pfId) * IRO[263].m1))
#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
- (IRO[257].base + ((pfId) * IRO[257].m1))
+ (IRO[264].base + ((pfId) * IRO[264].m1))
+#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
+ (IRO[265].base + ((pfId) * IRO[265].m1))
#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
- (IRO[258].base + ((pfId) * IRO[258].m1))
+ (IRO[266].base + ((pfId) * IRO[266].m1))
#define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
- (IRO[196].base + ((pfId) * IRO[196].m1))
- #define TSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, tStatCntId) \
- (IRO[100].base + ((portId) * IRO[100].m1) + ((tStatCntId) * \
- IRO[100].m2))
-#define TSTORM_STATS_FLAGS_OFFSET(pfId) \
- (IRO[95].base + ((pfId) * IRO[95].m1))
+ (IRO[202].base + ((pfId) * IRO[202].m1))
+#define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[105].base + ((funcId) * IRO[105].m1))
#define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
- (IRO[211].base + ((pfId) * IRO[211].m1))
+ (IRO[216].base + ((pfId) * IRO[216].m1))
#define TSTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[102].base + ((funcId) * IRO[102].m1))
-#define USTORM_AGG_DATA_OFFSET (IRO[201].base)
-#define USTORM_AGG_DATA_SIZE (IRO[201].size)
-#define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[170].base)
+ (IRO[104].base + ((funcId) * IRO[104].m1))
+#define USTORM_AGG_DATA_OFFSET (IRO[206].base)
+#define USTORM_AGG_DATA_SIZE (IRO[206].size)
+#define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[177].base)
#define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[169].base + ((assertListEntry) * IRO[169].m1))
+ (IRO[176].base + ((assertListEntry) * IRO[176].m1))
+#define USTORM_CQE_PAGE_NEXT_OFFSET(portId, clientId) \
+ (IRO[205].base + ((portId) * IRO[205].m1) + ((clientId) * \
+ IRO[205].m2))
#define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
- (IRO[178].base + ((portId) * IRO[178].m1))
-#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[172].base + ((pfId) * IRO[172].m1))
+ (IRO[183].base + ((portId) * IRO[183].m1))
#define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
- (IRO[313].base + ((pfId) * IRO[313].m1))
+ (IRO[317].base + ((pfId) * IRO[317].m1))
#define USTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[174].base + ((funcId) * IRO[174].m1))
-#define USTORM_FUNCTION_MODE_OFFSET (IRO[177].base)
+ (IRO[178].base + ((funcId) * IRO[178].m1))
#define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
- (IRO[277].base + ((pfId) * IRO[277].m1))
+ (IRO[281].base + ((pfId) * IRO[281].m1))
#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
- (IRO[278].base + ((pfId) * IRO[278].m1))
-#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
(IRO[282].base + ((pfId) * IRO[282].m1))
+#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
+ (IRO[286].base + ((pfId) * IRO[286].m1))
#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
- (IRO[279].base + ((pfId) * IRO[279].m1))
+ (IRO[283].base + ((pfId) * IRO[283].m1))
#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[275].base + ((pfId) * IRO[275].m1))
+ (IRO[279].base + ((pfId) * IRO[279].m1))
#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[274].base + ((pfId) * IRO[274].m1))
+ (IRO[278].base + ((pfId) * IRO[278].m1))
#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[273].base + ((pfId) * IRO[273].m1))
+ (IRO[277].base + ((pfId) * IRO[277].m1))
#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
- (IRO[276].base + ((pfId) * IRO[276].m1))
-#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
(IRO[280].base + ((pfId) * IRO[280].m1))
+#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
+ (IRO[284].base + ((pfId) * IRO[284].m1))
#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
- (IRO[281].base + ((pfId) * IRO[281].m1))
+ (IRO[285].base + ((pfId) * IRO[285].m1))
#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
- (IRO[176].base + ((pfId) * IRO[176].m1))
- #define USTORM_PER_COUNTER_ID_STATS_OFFSET(portId, uStatCntId) \
- (IRO[173].base + ((portId) * IRO[173].m1) + ((uStatCntId) * \
- IRO[173].m2))
- #define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
- (IRO[204].base + ((portId) * IRO[204].m1) + ((clientId) * \
- IRO[204].m2))
+ (IRO[182].base + ((pfId) * IRO[182].m1))
+#define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[180].base + ((funcId) * IRO[180].m1))
+#define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
+ (IRO[209].base + ((portId) * IRO[209].m1) + ((clientId) * \
+ IRO[209].m2))
#define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \
- (IRO[205].base + ((qzoneId) * IRO[205].m1))
-#define USTORM_STATS_FLAGS_OFFSET(pfId) \
- (IRO[171].base + ((pfId) * IRO[171].m1))
-#define USTORM_TPA_BTR_OFFSET (IRO[202].base)
-#define USTORM_TPA_BTR_SIZE (IRO[202].size)
+ (IRO[210].base + ((qzoneId) * IRO[210].m1))
+#define USTORM_TPA_BTR_OFFSET (IRO[207].base)
+#define USTORM_TPA_BTR_SIZE (IRO[207].size)
#define USTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[175].base + ((funcId) * IRO[175].m1))
-#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[59].base)
-#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[58].base)
-#define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[54].base)
+ (IRO[179].base + ((funcId) * IRO[179].m1))
+#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[67].base)
+#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[66].base)
+#define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[51].base)
#define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[53].base + ((assertListEntry) * IRO[53].m1))
+ (IRO[50].base + ((assertListEntry) * IRO[50].m1))
#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \
- (IRO[47].base + ((portId) * IRO[47].m1))
-#define XSTORM_E1HOV_OFFSET(pfId) \
- (IRO[55].base + ((pfId) * IRO[55].m1))
-#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[45].base + ((pfId) * IRO[45].m1))
+ (IRO[43].base + ((portId) * IRO[43].m1))
#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \
- (IRO[49].base + ((pfId) * IRO[49].m1))
+ (IRO[45].base + ((pfId) * IRO[45].m1))
#define XSTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[51].base + ((funcId) * IRO[51].m1))
-#define XSTORM_FUNCTION_MODE_OFFSET (IRO[56].base)
+ (IRO[47].base + ((funcId) * IRO[47].m1))
#define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
- (IRO[290].base + ((pfId) * IRO[290].m1))
+ (IRO[294].base + ((pfId) * IRO[294].m1))
#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
- (IRO[293].base + ((pfId) * IRO[293].m1))
+ (IRO[297].base + ((pfId) * IRO[297].m1))
#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
- (IRO[294].base + ((pfId) * IRO[294].m1))
+ (IRO[298].base + ((pfId) * IRO[298].m1))
#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
- (IRO[295].base + ((pfId) * IRO[295].m1))
+ (IRO[299].base + ((pfId) * IRO[299].m1))
#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
- (IRO[296].base + ((pfId) * IRO[296].m1))
+ (IRO[300].base + ((pfId) * IRO[300].m1))
#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
- (IRO[297].base + ((pfId) * IRO[297].m1))
+ (IRO[301].base + ((pfId) * IRO[301].m1))
#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
- (IRO[298].base + ((pfId) * IRO[298].m1))
+ (IRO[302].base + ((pfId) * IRO[302].m1))
#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
- (IRO[299].base + ((pfId) * IRO[299].m1))
+ (IRO[303].base + ((pfId) * IRO[303].m1))
#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[289].base + ((pfId) * IRO[289].m1))
+ (IRO[293].base + ((pfId) * IRO[293].m1))
#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[288].base + ((pfId) * IRO[288].m1))
+ (IRO[292].base + ((pfId) * IRO[292].m1))
#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[287].base + ((pfId) * IRO[287].m1))
+ (IRO[291].base + ((pfId) * IRO[291].m1))
#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
- (IRO[292].base + ((pfId) * IRO[292].m1))
+ (IRO[296].base + ((pfId) * IRO[296].m1))
#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
- (IRO[291].base + ((pfId) * IRO[291].m1))
+ (IRO[295].base + ((pfId) * IRO[295].m1))
#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
- (IRO[286].base + ((pfId) * IRO[286].m1))
+ (IRO[290].base + ((pfId) * IRO[290].m1))
#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
- (IRO[285].base + ((pfId) * IRO[285].m1))
+ (IRO[289].base + ((pfId) * IRO[289].m1))
#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
- (IRO[284].base + ((pfId) * IRO[284].m1))
+ (IRO[288].base + ((pfId) * IRO[288].m1))
#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
- (IRO[283].base + ((pfId) * IRO[283].m1))
-#define XSTORM_PATH_ID_OFFSET (IRO[65].base)
- #define XSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, xStatCntId) \
- (IRO[50].base + ((portId) * IRO[50].m1) + ((xStatCntId) * \
- IRO[50].m2))
+ (IRO[287].base + ((pfId) * IRO[287].m1))
#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
- (IRO[48].base + ((pfId) * IRO[48].m1))
+ (IRO[44].base + ((pfId) * IRO[44].m1))
+#define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[49].base + ((funcId) * IRO[49].m1))
#define XSTORM_SPQ_DATA_OFFSET(funcId) \
(IRO[32].base + ((funcId) * IRO[32].m1))
#define XSTORM_SPQ_DATA_SIZE (IRO[32].size)
@@ -260,42 +232,37 @@
(IRO[30].base + ((funcId) * IRO[30].m1))
#define XSTORM_SPQ_PROD_OFFSET(funcId) \
(IRO[31].base + ((funcId) * IRO[31].m1))
-#define XSTORM_STATS_FLAGS_OFFSET(pfId) \
- (IRO[43].base + ((pfId) * IRO[43].m1))
#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(portId) \
- (IRO[206].base + ((portId) * IRO[206].m1))
+ (IRO[211].base + ((portId) * IRO[211].m1))
#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(portId) \
- (IRO[207].base + ((portId) * IRO[207].m1))
+ (IRO[212].base + ((portId) * IRO[212].m1))
#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfId) \
- (IRO[209].base + (((pfId)>>1) * IRO[209].m1) + (((pfId)&1) * \
- IRO[209].m2))
+ (IRO[214].base + (((pfId)>>1) * IRO[214].m1) + (((pfId)&1) * \
+ IRO[214].m2))
#define XSTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[52].base + ((funcId) * IRO[52].m1))
+ (IRO[48].base + ((funcId) * IRO[48].m1))
#define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
-/* RSS hash types */
-#define DEFAULT_HASH_TYPE 0
-#define IPV4_HASH_TYPE 1
-#define TCP_IPV4_HASH_TYPE 2
-#define IPV6_HASH_TYPE 3
-#define TCP_IPV6_HASH_TYPE 4
-#define VLAN_PRI_HASH_TYPE 5
-#define E1HOV_PRI_HASH_TYPE 6
-#define DSCP_HASH_TYPE 7
+/**
+* This file defines HSI constants for the ETH flow
+*/
+#ifdef _EVEREST_MICROCODE
+#include "Microcode\Generated\DataTypes\eth_rx_bd.h"
+#include "Microcode\Generated\DataTypes\eth_tx_bd.h"
+#include "Microcode\Generated\DataTypes\eth_rx_cqe.h"
+#include "Microcode\Generated\DataTypes\eth_rx_sge.h"
+#include "Microcode\Generated\DataTypes\eth_rx_cqe_next_page.h"
+#endif
/* Ethernet Ring parameters */
#define X_ETH_LOCAL_RING_SIZE 13
-#define FIRST_BD_IN_PKT 0
+#define FIRST_BD_IN_PKT 0
#define PARSE_BD_INDEX 1
#define NUM_OF_ETH_BDS_IN_PAGE ((PAGE_SIZE)/(STRUCT_SIZE(eth_tx_bd)/8))
#define U_ETH_NUM_OF_SGES_TO_FETCH 8
#define U_ETH_MAX_SGES_FOR_PACKET 3
-/*Tx params*/
-#define X_ETH_NO_VLAN 0
-#define X_ETH_OUTBAND_VLAN 1
-#define X_ETH_INBAND_VLAN 2
/* Rx ring params */
#define U_ETH_LOCAL_BD_RING_SIZE 8
#define U_ETH_LOCAL_SGE_RING_SIZE 10
@@ -311,79 +278,64 @@
#define U_ETH_BDS_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_bd)/8))
#define U_ETH_SGES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_sge)/8))
-#define U_ETH_BDS_PER_PAGE_MASK (U_ETH_BDS_PER_PAGE-1)
-#define U_ETH_CQE_PER_PAGE_MASK (TU_ETH_CQES_PER_PAGE-1)
+#define U_ETH_BDS_PER_PAGE_MASK (U_ETH_BDS_PER_PAGE-1)
+#define U_ETH_CQE_PER_PAGE_MASK (TU_ETH_CQES_PER_PAGE-1)
#define U_ETH_SGES_PER_PAGE_MASK (U_ETH_SGES_PER_PAGE-1)
#define U_ETH_UNDEFINED_Q 0xFF
-/* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_ETH_UNUSED 0
-#define RAMROD_CMD_ID_ETH_CLIENT_SETUP 1
-#define RAMROD_CMD_ID_ETH_UPDATE 2
-#define RAMROD_CMD_ID_ETH_HALT 3
-#define RAMROD_CMD_ID_ETH_FORWARD_SETUP 4
-#define RAMROD_CMD_ID_ETH_ACTIVATE 5
-#define RAMROD_CMD_ID_ETH_DEACTIVATE 6
-#define RAMROD_CMD_ID_ETH_EMPTY 7
-#define RAMROD_CMD_ID_ETH_TERMINATE 8
-
-/* command values for set mac command */
-#define T_ETH_MAC_COMMAND_SET 0
-#define T_ETH_MAC_COMMAND_INVALIDATE 1
-
#define T_ETH_INDIRECTION_TABLE_SIZE 128
+#define T_ETH_RSS_KEY 10
+#define ETH_NUM_OF_RSS_ENGINES_E2 72
+
+#define FILTER_RULES_COUNT 16
+#define MULTICAST_RULES_COUNT 16
+#define CLASSIFY_RULES_COUNT 16
/*The CRC32 seed, that is used for the hash(reduction) multicast address */
-#define T_ETH_CRC32_HASH_SEED 0x00000000
+#define ETH_CRC32_HASH_SEED 0x00000000
+
+#define ETH_CRC32_HASH_BIT_SIZE (8)
+#define ETH_CRC32_HASH_MASK EVAL((1<<ETH_CRC32_HASH_BIT_SIZE)-1)
/* Maximal L2 clients supported */
#define ETH_MAX_RX_CLIENTS_E1 18
#define ETH_MAX_RX_CLIENTS_E1H 28
+#define ETH_MAX_RX_CLIENTS_E2 152
+
+/* Maximal statistics client Ids */
+#define MAX_STAT_COUNTER_ID_E1 36
+#define MAX_STAT_COUNTER_ID_E1H 56
+#define MAX_STAT_COUNTER_ID_E2 140
+
+#define MAX_MAC_CREDIT_E1 192 /* Per Chip */
+#define MAX_MAC_CREDIT_E1H 256 /* Per Chip */
+#define MAX_MAC_CREDIT_E2 272 /* Per Path */
+#define MAX_VLAN_CREDIT_E1 0 /* Per Chip */
+#define MAX_VLAN_CREDIT_E1H 0 /* Per Chip */
+#define MAX_VLAN_CREDIT_E2 272 /* Per Path */
-#define MAX_STAT_COUNTER_ID ETH_MAX_RX_CLIENTS_E1H
/* Maximal aggregation queues supported */
#define ETH_MAX_AGGREGATION_QUEUES_E1 32
-#define ETH_MAX_AGGREGATION_QUEUES_E1H 64
+#define ETH_MAX_AGGREGATION_QUEUES_E1H_E2 64
-/* ETH RSS modes */
-#define ETH_RSS_MODE_DISABLED 0
-#define ETH_RSS_MODE_REGULAR 1
-#define ETH_RSS_MODE_VLAN_PRI 2
-#define ETH_RSS_MODE_E1HOV_PRI 3
-#define ETH_RSS_MODE_IP_DSCP 4
-#define ETH_RSS_MODE_E2_INTEG 5
+#define ETH_NUM_OF_MCAST_BINS 256
+#define ETH_NUM_OF_MCAST_ENGINES_E2 72
-/* ETH vlan filtering modes */
-#define ETH_VLAN_FILTER_ANY_VLAN 0 /* Don't filter by vlan */
-#define ETH_VLAN_FILTER_SPECIFIC_VLAN \
- 1 /* Only the vlan_id is allowed */
-#define ETH_VLAN_FILTER_CLASSIFY \
- 2 /* vlan will be added to CAM for classification */
+#define ETH_MIN_RX_CQES_WITHOUT_TPA (MAX_RAMRODS_PER_PORT + 3)
+#define ETH_MIN_RX_CQES_WITH_TPA_E1 \
+ (ETH_MAX_AGGREGATION_QUEUES_E1 + ETH_MIN_RX_CQES_WITHOUT_TPA)
+#define ETH_MIN_RX_CQES_WITH_TPA_E1H_E2 \
+ (ETH_MAX_AGGREGATION_QUEUES_E1H_E2 + ETH_MIN_RX_CQES_WITHOUT_TPA)
-/* Fast path CQE selection */
-#define ETH_FP_CQE_REGULAR 0
-#define ETH_FP_CQE_SGL 1
-#define ETH_FP_CQE_RAW 2
+#define DISABLE_STATISTIC_COUNTER_ID_VALUE 0
/**
-* This file defines HSI constants common to all microcode flows
-*/
-
-/* Connection types */
-#define ETH_CONNECTION_TYPE 0
-#define TOE_CONNECTION_TYPE 1
-#define RDMA_CONNECTION_TYPE 2
-#define ISCSI_CONNECTION_TYPE 3
-#define FCOE_CONNECTION_TYPE 4
-#define RESERVED_CONNECTION_TYPE_0 5
-#define RESERVED_CONNECTION_TYPE_1 6
-#define RESERVED_CONNECTION_TYPE_2 7
-#define NONE_CONNECTION_TYPE 8
-
+ * This file defines HSI constants common to all microcode flows
+ */
#define PROTOCOL_STATE_BIT_OFFSET 6
@@ -391,25 +343,9 @@
#define TOE_STATE (TOE_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
#define RDMA_STATE (RDMA_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
-/* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_COMMON_FUNCTION_START 1
-#define RAMROD_CMD_ID_COMMON_FUNCTION_STOP 2
-#define RAMROD_CMD_ID_COMMON_CFC_DEL 3
-#define RAMROD_CMD_ID_COMMON_CFC_DEL_WB 4
-#define RAMROD_CMD_ID_COMMON_SET_MAC 5
-#define RAMROD_CMD_ID_COMMON_STAT_QUERY 6
-#define RAMROD_CMD_ID_COMMON_STOP_TRAFFIC 7
-#define RAMROD_CMD_ID_COMMON_START_TRAFFIC 8
-
/* microcode fixed page page size 4K (chains and ring segments) */
#define MC_PAGE_SIZE 4096
-
-/* Host coalescing constants */
-#define HC_IGU_BC_MODE 0
-#define HC_IGU_NBC_MODE 1
-/* Host coalescing constants. E1 includes E1H as well */
-
/* Number of indices per slow-path SB */
#define HC_SP_SB_MAX_INDICES 16
@@ -418,30 +354,17 @@
#define HC_SB_MAX_INDICES_E2 8
#define HC_SB_MAX_SB_E1X 32
-#define HC_SB_MAX_SB_E2 136
+#define HC_SB_MAX_SB_E2 136
#define HC_SP_SB_ID 0xde
-#define HC_REGULAR_SEGMENT 0
-#define HC_DEFAULT_SEGMENT 1
#define HC_SB_MAX_SM 2
#define HC_SB_MAX_DYNAMIC_INDICES 4
-#define HC_FUNCTION_DISABLED 0xff
-/* used by the driver to get the SB offset */
-#define USTORM_ID 0
-#define CSTORM_ID 1
-#define XSTORM_ID 2
-#define TSTORM_ID 3
-#define ATTENTION_ID 4
/* max number of slow path commands per port */
#define MAX_RAMRODS_PER_PORT 8
-/* values for RX ETH CQE type field */
-#define RX_ETH_CQE_TYPE_ETH_FASTPATH 0
-#define RX_ETH_CQE_TYPE_ETH_RAMROD 1
-
/**** DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
@@ -451,7 +374,7 @@
#define XSEMI_CLK1_RESUL_CHIP (1e-3)
-#define SDM_TIMER_TICK_RESUL_CHIP (4*(1e-6))
+#define SDM_TIMER_TICK_RESUL_CHIP (4 * (1e-6))
/**** END DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
@@ -460,72 +383,28 @@
#define FW_LOG_LIST_SIZE 50
-#define NUM_OF_PROTOCOLS 4
#define NUM_OF_SAFC_BITS 16
#define MAX_COS_NUMBER 4
-
-#define FAIRNESS_COS_WRR_MODE 0
-#define FAIRNESS_COS_ETS_MODE 1
-
-
-/* Priority Flow Control (PFC) */
+#define MAX_TRAFFIC_TYPES 8
#define MAX_PFC_PRIORITIES 8
-#define MAX_PFC_TRAFFIC_TYPES 8
-
-/* Available Traffic Types for Link Layer Flow Control */
-#define LLFC_TRAFFIC_TYPE_NW 0
-#define LLFC_TRAFFIC_TYPE_FCOE 1
-#define LLFC_TRAFFIC_TYPE_ISCSI 2
- /***************** START OF E2 INTEGRATION \
- CODE***************************************/
-#define LLFC_TRAFFIC_TYPE_NW_COS1_E2INTEG 3
- /***************** END OF E2 INTEGRATION \
- CODE***************************************/
-#define LLFC_TRAFFIC_TYPE_MAX 4
/* used by array traffic_type_to_priority[] to mark traffic type \
that is not mapped to priority*/
#define LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED 0xFF
-#define LLFC_MODE_NONE 0
-#define LLFC_MODE_PFC 1
-#define LLFC_MODE_SAFC 2
-
-#define DCB_DISABLED 0
-#define DCB_ENABLED 1
-#define UNKNOWN_ADDRESS 0
-#define UNICAST_ADDRESS 1
-#define MULTICAST_ADDRESS 2
-#define BROADCAST_ADDRESS 3
+#define C_ERES_PER_PAGE \
+ (PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
+#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
-#define SINGLE_FUNCTION 0
-#define MULTI_FUNCTION_SD 1
-#define MULTI_FUNCTION_SI 2
+#define STATS_QUERY_CMD_COUNT 16
-#define IP_V4 0
-#define IP_V6 1
+#define NIV_LIST_TABLE_SIZE 4096
+#define INVALID_VNIC_ID 0xFF
-#define C_ERES_PER_PAGE \
- (PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
-#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
-#define EVENT_RING_OPCODE_VF_PF_CHANNEL 0
-#define EVENT_RING_OPCODE_FUNCTION_START 1
-#define EVENT_RING_OPCODE_FUNCTION_STOP 2
-#define EVENT_RING_OPCODE_CFC_DEL 3
-#define EVENT_RING_OPCODE_CFC_DEL_WB 4
-#define EVENT_RING_OPCODE_SET_MAC 5
-#define EVENT_RING_OPCODE_STAT_QUERY 6
-#define EVENT_RING_OPCODE_STOP_TRAFFIC 7
-#define EVENT_RING_OPCODE_START_TRAFFIC 8
-#define EVENT_RING_OPCODE_FORWARD_SETUP 9
-
-#define VF_PF_CHANNEL_STATE_READY 0
-#define VF_PF_CHANNEL_STATE_WAITING_FOR_ACK 1
-
-#define VF_PF_CHANNEL_STATE_MAX_NUMBER 2
+#define UNDEF_IRO 0x80000000
#endif /* BNX2X_FW_DEFS_H */
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h
index cdf19fe7c7f6..06727f32e505 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/bnx2x/bnx2x_hsi.h
@@ -11,7 +11,7 @@
#include "bnx2x_fw_defs.h"
-#define FW_ENCODE_32BIT_PATTERN 0x1e1e1e1e
+#define FW_ENCODE_32BIT_PATTERN 0x1e1e1e1e
struct license_key {
u32 reserved[6];
@@ -33,201 +33,366 @@ struct license_key {
u32 reserved_b[4];
};
-#define PORT_0 0
-#define PORT_1 1
-#define PORT_MAX 2
+
+#define PORT_0 0
+#define PORT_1 1
+#define PORT_MAX 2
/****************************************************************************
- * Shared HW configuration *
+ * Shared HW configuration *
****************************************************************************/
-struct shared_hw_cfg { /* NVRAM Offset */
+#define PIN_CFG_NA 0x00000000
+#define PIN_CFG_GPIO0_P0 0x00000001
+#define PIN_CFG_GPIO1_P0 0x00000002
+#define PIN_CFG_GPIO2_P0 0x00000003
+#define PIN_CFG_GPIO3_P0 0x00000004
+#define PIN_CFG_GPIO0_P1 0x00000005
+#define PIN_CFG_GPIO1_P1 0x00000006
+#define PIN_CFG_GPIO2_P1 0x00000007
+#define PIN_CFG_GPIO3_P1 0x00000008
+#define PIN_CFG_EPIO0 0x00000009
+#define PIN_CFG_EPIO1 0x0000000a
+#define PIN_CFG_EPIO2 0x0000000b
+#define PIN_CFG_EPIO3 0x0000000c
+#define PIN_CFG_EPIO4 0x0000000d
+#define PIN_CFG_EPIO5 0x0000000e
+#define PIN_CFG_EPIO6 0x0000000f
+#define PIN_CFG_EPIO7 0x00000010
+#define PIN_CFG_EPIO8 0x00000011
+#define PIN_CFG_EPIO9 0x00000012
+#define PIN_CFG_EPIO10 0x00000013
+#define PIN_CFG_EPIO11 0x00000014
+#define PIN_CFG_EPIO12 0x00000015
+#define PIN_CFG_EPIO13 0x00000016
+#define PIN_CFG_EPIO14 0x00000017
+#define PIN_CFG_EPIO15 0x00000018
+#define PIN_CFG_EPIO16 0x00000019
+#define PIN_CFG_EPIO17 0x0000001a
+#define PIN_CFG_EPIO18 0x0000001b
+#define PIN_CFG_EPIO19 0x0000001c
+#define PIN_CFG_EPIO20 0x0000001d
+#define PIN_CFG_EPIO21 0x0000001e
+#define PIN_CFG_EPIO22 0x0000001f
+#define PIN_CFG_EPIO23 0x00000020
+#define PIN_CFG_EPIO24 0x00000021
+#define PIN_CFG_EPIO25 0x00000022
+#define PIN_CFG_EPIO26 0x00000023
+#define PIN_CFG_EPIO27 0x00000024
+#define PIN_CFG_EPIO28 0x00000025
+#define PIN_CFG_EPIO29 0x00000026
+#define PIN_CFG_EPIO30 0x00000027
+#define PIN_CFG_EPIO31 0x00000028
+
+/* EPIO definition */
+#define EPIO_CFG_NA 0x00000000
+#define EPIO_CFG_EPIO0 0x00000001
+#define EPIO_CFG_EPIO1 0x00000002
+#define EPIO_CFG_EPIO2 0x00000003
+#define EPIO_CFG_EPIO3 0x00000004
+#define EPIO_CFG_EPIO4 0x00000005
+#define EPIO_CFG_EPIO5 0x00000006
+#define EPIO_CFG_EPIO6 0x00000007
+#define EPIO_CFG_EPIO7 0x00000008
+#define EPIO_CFG_EPIO8 0x00000009
+#define EPIO_CFG_EPIO9 0x0000000a
+#define EPIO_CFG_EPIO10 0x0000000b
+#define EPIO_CFG_EPIO11 0x0000000c
+#define EPIO_CFG_EPIO12 0x0000000d
+#define EPIO_CFG_EPIO13 0x0000000e
+#define EPIO_CFG_EPIO14 0x0000000f
+#define EPIO_CFG_EPIO15 0x00000010
+#define EPIO_CFG_EPIO16 0x00000011
+#define EPIO_CFG_EPIO17 0x00000012
+#define EPIO_CFG_EPIO18 0x00000013
+#define EPIO_CFG_EPIO19 0x00000014
+#define EPIO_CFG_EPIO20 0x00000015
+#define EPIO_CFG_EPIO21 0x00000016
+#define EPIO_CFG_EPIO22 0x00000017
+#define EPIO_CFG_EPIO23 0x00000018
+#define EPIO_CFG_EPIO24 0x00000019
+#define EPIO_CFG_EPIO25 0x0000001a
+#define EPIO_CFG_EPIO26 0x0000001b
+#define EPIO_CFG_EPIO27 0x0000001c
+#define EPIO_CFG_EPIO28 0x0000001d
+#define EPIO_CFG_EPIO29 0x0000001e
+#define EPIO_CFG_EPIO30 0x0000001f
+#define EPIO_CFG_EPIO31 0x00000020
+
+
+struct shared_hw_cfg { /* NVRAM Offset */
/* Up to 16 bytes of NULL-terminated string */
- u8 part_num[16]; /* 0x104 */
+ u8 part_num[16]; /* 0x104 */
+
+ u32 config; /* 0x114 */
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_MASK 0x00000001
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT 0
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V 0x00000000
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V 0x00000001
+ #define SHARED_HW_CFG_MCP_RST_ON_CORE_RST_EN 0x00000002
- u32 config; /* 0x114 */
-#define SHARED_HW_CFG_MDIO_VOLTAGE_MASK 0x00000001
-#define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT 0
-#define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V 0x00000000
-#define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V 0x00000001
-#define SHARED_HW_CFG_MCP_RST_ON_CORE_RST_EN 0x00000002
+ #define SHARED_HW_CFG_PORT_SWAP 0x00000004
-#define SHARED_HW_CFG_PORT_SWAP 0x00000004
+ #define SHARED_HW_CFG_BEACON_WOL_EN 0x00000008
-#define SHARED_HW_CFG_BEACON_WOL_EN 0x00000008
+ #define SHARED_HW_CFG_PCIE_GEN3_DISABLED 0x00000000
+ #define SHARED_HW_CFG_PCIE_GEN3_ENABLED 0x00000010
-#define SHARED_HW_CFG_MFW_SELECT_MASK 0x00000700
-#define SHARED_HW_CFG_MFW_SELECT_SHIFT 8
+ #define SHARED_HW_CFG_MFW_SELECT_MASK 0x00000700
+ #define SHARED_HW_CFG_MFW_SELECT_SHIFT 8
/* Whatever MFW found in NVM
(if multiple found, priority order is: NC-SI, UMP, IPMI) */
-#define SHARED_HW_CFG_MFW_SELECT_DEFAULT 0x00000000
-#define SHARED_HW_CFG_MFW_SELECT_NC_SI 0x00000100
-#define SHARED_HW_CFG_MFW_SELECT_UMP 0x00000200
-#define SHARED_HW_CFG_MFW_SELECT_IPMI 0x00000300
+ #define SHARED_HW_CFG_MFW_SELECT_DEFAULT 0x00000000
+ #define SHARED_HW_CFG_MFW_SELECT_NC_SI 0x00000100
+ #define SHARED_HW_CFG_MFW_SELECT_UMP 0x00000200
+ #define SHARED_HW_CFG_MFW_SELECT_IPMI 0x00000300
/* Use SPIO4 as an arbiter between: 0-NC_SI, 1-IPMI
(can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI 0x00000400
+ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI 0x00000400
/* Use SPIO4 as an arbiter between: 0-UMP, 1-IPMI
(can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI 0x00000500
+ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI 0x00000500
/* Use SPIO4 as an arbiter between: 0-NC-SI, 1-UMP
(can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP 0x00000600
-
-#define SHARED_HW_CFG_LED_MODE_MASK 0x000f0000
-#define SHARED_HW_CFG_LED_MODE_SHIFT 16
-#define SHARED_HW_CFG_LED_MAC1 0x00000000
-#define SHARED_HW_CFG_LED_PHY1 0x00010000
-#define SHARED_HW_CFG_LED_PHY2 0x00020000
-#define SHARED_HW_CFG_LED_PHY3 0x00030000
-#define SHARED_HW_CFG_LED_MAC2 0x00040000
-#define SHARED_HW_CFG_LED_PHY4 0x00050000
-#define SHARED_HW_CFG_LED_PHY5 0x00060000
-#define SHARED_HW_CFG_LED_PHY6 0x00070000
-#define SHARED_HW_CFG_LED_MAC3 0x00080000
-#define SHARED_HW_CFG_LED_PHY7 0x00090000
-#define SHARED_HW_CFG_LED_PHY9 0x000a0000
-#define SHARED_HW_CFG_LED_PHY11 0x000b0000
-#define SHARED_HW_CFG_LED_MAC4 0x000c0000
-#define SHARED_HW_CFG_LED_PHY8 0x000d0000
-#define SHARED_HW_CFG_LED_EXTPHY1 0x000e0000
-
-
-#define SHARED_HW_CFG_AN_ENABLE_MASK 0x3f000000
-#define SHARED_HW_CFG_AN_ENABLE_SHIFT 24
-#define SHARED_HW_CFG_AN_ENABLE_CL37 0x01000000
-#define SHARED_HW_CFG_AN_ENABLE_CL73 0x02000000
-#define SHARED_HW_CFG_AN_ENABLE_BAM 0x04000000
-#define SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION 0x08000000
-#define SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT 0x10000000
-#define SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY 0x20000000
-
- u32 config2; /* 0x118 */
+ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP 0x00000600
+
+ #define SHARED_HW_CFG_LED_MODE_MASK 0x000f0000
+ #define SHARED_HW_CFG_LED_MODE_SHIFT 16
+ #define SHARED_HW_CFG_LED_MAC1 0x00000000
+ #define SHARED_HW_CFG_LED_PHY1 0x00010000
+ #define SHARED_HW_CFG_LED_PHY2 0x00020000
+ #define SHARED_HW_CFG_LED_PHY3 0x00030000
+ #define SHARED_HW_CFG_LED_MAC2 0x00040000
+ #define SHARED_HW_CFG_LED_PHY4 0x00050000
+ #define SHARED_HW_CFG_LED_PHY5 0x00060000
+ #define SHARED_HW_CFG_LED_PHY6 0x00070000
+ #define SHARED_HW_CFG_LED_MAC3 0x00080000
+ #define SHARED_HW_CFG_LED_PHY7 0x00090000
+ #define SHARED_HW_CFG_LED_PHY9 0x000a0000
+ #define SHARED_HW_CFG_LED_PHY11 0x000b0000
+ #define SHARED_HW_CFG_LED_MAC4 0x000c0000
+ #define SHARED_HW_CFG_LED_PHY8 0x000d0000
+ #define SHARED_HW_CFG_LED_EXTPHY1 0x000e0000
+
+
+ #define SHARED_HW_CFG_AN_ENABLE_MASK 0x3f000000
+ #define SHARED_HW_CFG_AN_ENABLE_SHIFT 24
+ #define SHARED_HW_CFG_AN_ENABLE_CL37 0x01000000
+ #define SHARED_HW_CFG_AN_ENABLE_CL73 0x02000000
+ #define SHARED_HW_CFG_AN_ENABLE_BAM 0x04000000
+ #define SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION 0x08000000
+ #define SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT 0x10000000
+ #define SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY 0x20000000
+
+ #define SHARED_HW_CFG_SRIOV_MASK 0x40000000
+ #define SHARED_HW_CFG_SRIOV_DISABLED 0x00000000
+ #define SHARED_HW_CFG_SRIOV_ENABLED 0x40000000
+
+ #define SHARED_HW_CFG_ATC_MASK 0x80000000
+ #define SHARED_HW_CFG_ATC_DISABLED 0x00000000
+ #define SHARED_HW_CFG_ATC_ENABLED 0x80000000
+
+ u32 config2; /* 0x118 */
/* one time auto detect grace period (in sec) */
-#define SHARED_HW_CFG_GRACE_PERIOD_MASK 0x000000ff
-#define SHARED_HW_CFG_GRACE_PERIOD_SHIFT 0
+ #define SHARED_HW_CFG_GRACE_PERIOD_MASK 0x000000ff
+ #define SHARED_HW_CFG_GRACE_PERIOD_SHIFT 0
-#define SHARED_HW_CFG_PCIE_GEN2_ENABLED 0x00000100
+ #define SHARED_HW_CFG_PCIE_GEN2_ENABLED 0x00000100
+ #define SHARED_HW_CFG_PCIE_GEN2_DISABLED 0x00000000
/* The default value for the core clock is 250MHz and it is
achieved by setting the clock change to 4 */
-#define SHARED_HW_CFG_CLOCK_CHANGE_MASK 0x00000e00
-#define SHARED_HW_CFG_CLOCK_CHANGE_SHIFT 9
+ #define SHARED_HW_CFG_CLOCK_CHANGE_MASK 0x00000e00
+ #define SHARED_HW_CFG_CLOCK_CHANGE_SHIFT 9
-#define SHARED_HW_CFG_SMBUS_TIMING_100KHZ 0x00000000
-#define SHARED_HW_CFG_SMBUS_TIMING_400KHZ 0x00001000
+ #define SHARED_HW_CFG_SMBUS_TIMING_MASK 0x00001000
+ #define SHARED_HW_CFG_SMBUS_TIMING_100KHZ 0x00000000
+ #define SHARED_HW_CFG_SMBUS_TIMING_400KHZ 0x00001000
-#define SHARED_HW_CFG_HIDE_PORT1 0x00002000
+ #define SHARED_HW_CFG_HIDE_PORT1 0x00002000
- /* The fan failure mechanism is usually related to the PHY type
- since the power consumption of the board is determined by the PHY.
- Currently, fan is required for most designs with SFX7101, BCM8727
- and BCM8481. If a fan is not required for a board which uses one
- of those PHYs, this field should be set to "Disabled". If a fan is
- required for a different PHY type, this option should be set to
- "Enabled".
- The fan failure indication is expected on
- SPIO5 */
-#define SHARED_HW_CFG_FAN_FAILURE_MASK 0x00180000
-#define SHARED_HW_CFG_FAN_FAILURE_SHIFT 19
-#define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE 0x00000000
-#define SHARED_HW_CFG_FAN_FAILURE_DISABLED 0x00080000
-#define SHARED_HW_CFG_FAN_FAILURE_ENABLED 0x00100000
-
- /* Set the MDC/MDIO access for the first external phy */
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK 0x1C000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT 26
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE 0x00000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0 0x04000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1 0x08000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH 0x0c000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED 0x10000000
-
- /* Set the MDC/MDIO access for the second external phy */
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK 0xE0000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT 29
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE 0x00000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0 0x20000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1 0x40000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH 0x60000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED 0x80000000
- u32 power_dissipated; /* 0x11c */
-#define SHARED_HW_CFG_POWER_DIS_CMN_MASK 0xff000000
-#define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT 24
-
-#define SHARED_HW_CFG_POWER_MGNT_SCALE_MASK 0x00ff0000
-#define SHARED_HW_CFG_POWER_MGNT_SCALE_SHIFT 16
-#define SHARED_HW_CFG_POWER_MGNT_UNKNOWN_SCALE 0x00000000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_1_WATT 0x00010000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_01_WATT 0x00020000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_001_WATT 0x00030000
-
- u32 ump_nc_si_config; /* 0x120 */
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK 0x00000003
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT 0
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC 0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY 0x00000001
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII 0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII 0x00000002
-
-#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_MASK 0x00000f00
-#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_SHIFT 8
-
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_MASK 0x00ff0000
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_SHIFT 16
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_NONE 0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_BCM5221 0x00010000
-
- u32 board; /* 0x124 */
-#define SHARED_HW_CFG_BOARD_REV_MASK 0x00FF0000
-#define SHARED_HW_CFG_BOARD_REV_SHIFT 16
-
-#define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK 0x0F000000
-#define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT 24
-
-#define SHARED_HW_CFG_BOARD_MINOR_VER_MASK 0xF0000000
-#define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT 28
-
- u32 reserved; /* 0x128 */
+ #define SHARED_HW_CFG_WOL_CAPABLE_MASK 0x00004000
+ #define SHARED_HW_CFG_WOL_CAPABLE_DISABLED 0x00000000
+ #define SHARED_HW_CFG_WOL_CAPABLE_ENABLED 0x00004000
+ /* Output low when PERST is asserted */
+ #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_MASK 0x00008000
+ #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_DISABLED 0x00000000
+ #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_ENABLED 0x00008000
+
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_MASK 0x00070000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_SHIFT 16
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_HW 0x00000000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_0DB 0x00010000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_3_5DB 0x00020000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_6_0DB 0x00030000
+
+ /* The fan failure mechanism is usually related to the PHY type
+ since the power consumption of the board is determined by the PHY.
+ Currently, fan is required for most designs with SFX7101, BCM8727
+ and BCM8481. If a fan is not required for a board which uses one
+ of those PHYs, this field should be set to "Disabled". If a fan is
+ required for a different PHY type, this option should be set to
+ "Enabled". The fan failure indication is expected on SPIO5 */
+ #define SHARED_HW_CFG_FAN_FAILURE_MASK 0x00180000
+ #define SHARED_HW_CFG_FAN_FAILURE_SHIFT 19
+ #define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE 0x00000000
+ #define SHARED_HW_CFG_FAN_FAILURE_DISABLED 0x00080000
+ #define SHARED_HW_CFG_FAN_FAILURE_ENABLED 0x00100000
+
+ /* ASPM Power Management support */
+ #define SHARED_HW_CFG_ASPM_SUPPORT_MASK 0x00600000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_SHIFT 21
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_ENABLED 0x00000000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_DISABLED 0x00200000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L1_DISABLED 0x00400000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_DISABLED 0x00600000
+
+ /* The value of PM_TL_IGNORE_REQS (bit0) in PCI register
+ tl_control_0 (register 0x2800) */
+ #define SHARED_HW_CFG_PREVENT_L1_ENTRY_MASK 0x00800000
+ #define SHARED_HW_CFG_PREVENT_L1_ENTRY_DISABLED 0x00000000
+ #define SHARED_HW_CFG_PREVENT_L1_ENTRY_ENABLED 0x00800000
+
+ #define SHARED_HW_CFG_PORT_MODE_MASK 0x01000000
+ #define SHARED_HW_CFG_PORT_MODE_2 0x00000000
+ #define SHARED_HW_CFG_PORT_MODE_4 0x01000000
+
+ #define SHARED_HW_CFG_PATH_SWAP_MASK 0x02000000
+ #define SHARED_HW_CFG_PATH_SWAP_DISABLED 0x00000000
+ #define SHARED_HW_CFG_PATH_SWAP_ENABLED 0x02000000
+
+ /* Set the MDC/MDIO access for the first external phy */
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK 0x1C000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT 26
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE 0x00000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0 0x04000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1 0x08000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH 0x0c000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED 0x10000000
+
+ /* Set the MDC/MDIO access for the second external phy */
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK 0xE0000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT 29
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE 0x00000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0 0x20000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1 0x40000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH 0x60000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED 0x80000000
+
+
+ u32 power_dissipated; /* 0x11c */
+ #define SHARED_HW_CFG_POWER_MGNT_SCALE_MASK 0x00ff0000
+ #define SHARED_HW_CFG_POWER_MGNT_SCALE_SHIFT 16
+ #define SHARED_HW_CFG_POWER_MGNT_UNKNOWN_SCALE 0x00000000
+ #define SHARED_HW_CFG_POWER_MGNT_DOT_1_WATT 0x00010000
+ #define SHARED_HW_CFG_POWER_MGNT_DOT_01_WATT 0x00020000
+ #define SHARED_HW_CFG_POWER_MGNT_DOT_001_WATT 0x00030000
+
+ #define SHARED_HW_CFG_POWER_DIS_CMN_MASK 0xff000000
+ #define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT 24
+
+ u32 ump_nc_si_config; /* 0x120 */
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK 0x00000003
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT 0
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC 0x00000000
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY 0x00000001
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII 0x00000000
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII 0x00000002
+
+ #define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_MASK 0x00000f00
+ #define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_SHIFT 8
+
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_MASK 0x00ff0000
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_SHIFT 16
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_NONE 0x00000000
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_BCM5221 0x00010000
+
+ u32 board; /* 0x124 */
+ #define SHARED_HW_CFG_E3_I2C_MUX0_MASK 0x0000003F
+ #define SHARED_HW_CFG_E3_I2C_MUX0_SHIFT 0
+ #define SHARED_HW_CFG_E3_I2C_MUX1_MASK 0x00000FC0
+ #define SHARED_HW_CFG_E3_I2C_MUX1_SHIFT 6
+ /* Use the PIN_CFG_XXX defines on top */
+ #define SHARED_HW_CFG_BOARD_REV_MASK 0x00ff0000
+ #define SHARED_HW_CFG_BOARD_REV_SHIFT 16
+
+ #define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK 0x0f000000
+ #define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT 24
+
+ #define SHARED_HW_CFG_BOARD_MINOR_VER_MASK 0xf0000000
+ #define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT 28
+
+ u32 wc_lane_config; /* 0x128 */
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_MASK 0x0000FFFF
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_SHIFT 0
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_32103210 0x00001b1b
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_32100123 0x00001be4
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_01233210 0x0000e41b
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_01230123 0x0000e4e4
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000FF
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000FF00
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8
+
+ /* TX lane Polarity swap */
+ #define SHARED_HW_CFG_TX_LANE0_POL_FLIP_ENABLED 0x00010000
+ #define SHARED_HW_CFG_TX_LANE1_POL_FLIP_ENABLED 0x00020000
+ #define SHARED_HW_CFG_TX_LANE2_POL_FLIP_ENABLED 0x00040000
+ #define SHARED_HW_CFG_TX_LANE3_POL_FLIP_ENABLED 0x00080000
+ /* TX lane Polarity swap */
+ #define SHARED_HW_CFG_RX_LANE0_POL_FLIP_ENABLED 0x00100000
+ #define SHARED_HW_CFG_RX_LANE1_POL_FLIP_ENABLED 0x00200000
+ #define SHARED_HW_CFG_RX_LANE2_POL_FLIP_ENABLED 0x00400000
+ #define SHARED_HW_CFG_RX_LANE3_POL_FLIP_ENABLED 0x00800000
+
+ /* Selects the port layout of the board */
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_MASK 0x0F000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_SHIFT 24
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_01 0x00000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_10 0x01000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_0123 0x02000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_1032 0x03000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_2301 0x04000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_3210 0x05000000
};
/****************************************************************************
- * Port HW configuration *
+ * Port HW configuration *
****************************************************************************/
-struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
+struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
u32 pci_id;
-#define PORT_HW_CFG_PCI_VENDOR_ID_MASK 0xffff0000
-#define PORT_HW_CFG_PCI_DEVICE_ID_MASK 0x0000ffff
+ #define PORT_HW_CFG_PCI_VENDOR_ID_MASK 0xffff0000
+ #define PORT_HW_CFG_PCI_DEVICE_ID_MASK 0x0000ffff
u32 pci_sub_id;
-#define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK 0xffff0000
-#define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK 0x0000ffff
+ #define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK 0xffff0000
+ #define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK 0x0000ffff
u32 power_dissipated;
-#define PORT_HW_CFG_POWER_DIS_D3_MASK 0xff000000
-#define PORT_HW_CFG_POWER_DIS_D3_SHIFT 24
-#define PORT_HW_CFG_POWER_DIS_D2_MASK 0x00ff0000
-#define PORT_HW_CFG_POWER_DIS_D2_SHIFT 16
-#define PORT_HW_CFG_POWER_DIS_D1_MASK 0x0000ff00
-#define PORT_HW_CFG_POWER_DIS_D1_SHIFT 8
-#define PORT_HW_CFG_POWER_DIS_D0_MASK 0x000000ff
-#define PORT_HW_CFG_POWER_DIS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_DIS_D0_MASK 0x000000ff
+ #define PORT_HW_CFG_POWER_DIS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_DIS_D1_MASK 0x0000ff00
+ #define PORT_HW_CFG_POWER_DIS_D1_SHIFT 8
+ #define PORT_HW_CFG_POWER_DIS_D2_MASK 0x00ff0000
+ #define PORT_HW_CFG_POWER_DIS_D2_SHIFT 16
+ #define PORT_HW_CFG_POWER_DIS_D3_MASK 0xff000000
+ #define PORT_HW_CFG_POWER_DIS_D3_SHIFT 24
u32 power_consumed;
-#define PORT_HW_CFG_POWER_CONS_D3_MASK 0xff000000
-#define PORT_HW_CFG_POWER_CONS_D3_SHIFT 24
-#define PORT_HW_CFG_POWER_CONS_D2_MASK 0x00ff0000
-#define PORT_HW_CFG_POWER_CONS_D2_SHIFT 16
-#define PORT_HW_CFG_POWER_CONS_D1_MASK 0x0000ff00
-#define PORT_HW_CFG_POWER_CONS_D1_SHIFT 8
-#define PORT_HW_CFG_POWER_CONS_D0_MASK 0x000000ff
-#define PORT_HW_CFG_POWER_CONS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_CONS_D0_MASK 0x000000ff
+ #define PORT_HW_CFG_POWER_CONS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_CONS_D1_MASK 0x0000ff00
+ #define PORT_HW_CFG_POWER_CONS_D1_SHIFT 8
+ #define PORT_HW_CFG_POWER_CONS_D2_MASK 0x00ff0000
+ #define PORT_HW_CFG_POWER_CONS_D2_SHIFT 16
+ #define PORT_HW_CFG_POWER_CONS_D3_MASK 0xff000000
+ #define PORT_HW_CFG_POWER_CONS_D3_SHIFT 24
u32 mac_upper;
-#define PORT_HW_CFG_UPPERMAC_MASK 0x0000ffff
-#define PORT_HW_CFG_UPPERMAC_SHIFT 0
+ #define PORT_HW_CFG_UPPERMAC_MASK 0x0000ffff
+ #define PORT_HW_CFG_UPPERMAC_SHIFT 0
u32 mac_lower;
u32 iscsi_mac_upper; /* Upper 16 bits are always zeroes */
@@ -237,642 +402,807 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
u32 rdma_mac_lower;
u32 serdes_config;
-#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK 0x0000FFFF
-#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT 0
-
-#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK 0xFFFF0000
-#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT 16
-
-
- u32 Reserved0[3]; /* 0x158 */
- /* Controls the TX laser of the SFP+ module */
- u32 sfp_ctrl; /* 0x164 */
-#define PORT_HW_CFG_TX_LASER_MASK 0x000000FF
-#define PORT_HW_CFG_TX_LASER_SHIFT 0
-#define PORT_HW_CFG_TX_LASER_MDIO 0x00000000
-#define PORT_HW_CFG_TX_LASER_GPIO0 0x00000001
-#define PORT_HW_CFG_TX_LASER_GPIO1 0x00000002
-#define PORT_HW_CFG_TX_LASER_GPIO2 0x00000003
-#define PORT_HW_CFG_TX_LASER_GPIO3 0x00000004
-
- /* Controls the fault module LED of the SFP+ */
-#define PORT_HW_CFG_FAULT_MODULE_LED_MASK 0x0000FF00
-#define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT 8
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0 0x00000000
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1 0x00000100
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2 0x00000200
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3 0x00000300
-#define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED 0x00000400
- u32 Reserved01[12]; /* 0x158 */
- /* for external PHY, or forced mode or during AN */
- u16 xgxs_config_rx[4]; /* 0x198 */
-
- u16 xgxs_config_tx[4]; /* 0x1A0 */
-
- u32 Reserved1[56]; /* 0x1A8 */
- u32 default_cfg; /* 0x288 */
-#define PORT_HW_CFG_GPIO0_CONFIG_MASK 0x00000003
-#define PORT_HW_CFG_GPIO0_CONFIG_SHIFT 0
-#define PORT_HW_CFG_GPIO0_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO0_CONFIG_LOW 0x00000001
-#define PORT_HW_CFG_GPIO0_CONFIG_HIGH 0x00000002
-#define PORT_HW_CFG_GPIO0_CONFIG_INPUT 0x00000003
-
-#define PORT_HW_CFG_GPIO1_CONFIG_MASK 0x0000000C
-#define PORT_HW_CFG_GPIO1_CONFIG_SHIFT 2
-#define PORT_HW_CFG_GPIO1_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO1_CONFIG_LOW 0x00000004
-#define PORT_HW_CFG_GPIO1_CONFIG_HIGH 0x00000008
-#define PORT_HW_CFG_GPIO1_CONFIG_INPUT 0x0000000c
-
-#define PORT_HW_CFG_GPIO2_CONFIG_MASK 0x00000030
-#define PORT_HW_CFG_GPIO2_CONFIG_SHIFT 4
-#define PORT_HW_CFG_GPIO2_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO2_CONFIG_LOW 0x00000010
-#define PORT_HW_CFG_GPIO2_CONFIG_HIGH 0x00000020
-#define PORT_HW_CFG_GPIO2_CONFIG_INPUT 0x00000030
-
-#define PORT_HW_CFG_GPIO3_CONFIG_MASK 0x000000C0
-#define PORT_HW_CFG_GPIO3_CONFIG_SHIFT 6
-#define PORT_HW_CFG_GPIO3_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO3_CONFIG_LOW 0x00000040
-#define PORT_HW_CFG_GPIO3_CONFIG_HIGH 0x00000080
-#define PORT_HW_CFG_GPIO3_CONFIG_INPUT 0x000000c0
+ #define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK 0x0000ffff
+ #define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT 0
+
+ #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK 0xffff0000
+ #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT 16
+
+
+ /* Default values: 2P-64, 4P-32 */
+ u32 pf_config; /* 0x158 */
+ #define PORT_HW_CFG_PF_NUM_VF_MASK 0x0000007F
+ #define PORT_HW_CFG_PF_NUM_VF_SHIFT 0
+
+ /* Default values: 17 */
+ #define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_MASK 0x00007F00
+ #define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_SHIFT 8
+
+ #define PORT_HW_CFG_ENABLE_FLR_MASK 0x00010000
+ #define PORT_HW_CFG_FLR_ENABLED 0x00010000
+
+ u32 vf_config; /* 0x15C */
+ #define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_MASK 0x0000007F
+ #define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_SHIFT 0
+
+ #define PORT_HW_CFG_VF_PCI_DEVICE_ID_MASK 0xFFFF0000
+ #define PORT_HW_CFG_VF_PCI_DEVICE_ID_SHIFT 16
+
+ u32 mf_pci_id; /* 0x160 */
+ #define PORT_HW_CFG_MF_PCI_DEVICE_ID_MASK 0x0000FFFF
+ #define PORT_HW_CFG_MF_PCI_DEVICE_ID_SHIFT 0
+
+ /* Controls the TX laser of the SFP+ module */
+ u32 sfp_ctrl; /* 0x164 */
+ #define PORT_HW_CFG_TX_LASER_MASK 0x000000FF
+ #define PORT_HW_CFG_TX_LASER_SHIFT 0
+ #define PORT_HW_CFG_TX_LASER_MDIO 0x00000000
+ #define PORT_HW_CFG_TX_LASER_GPIO0 0x00000001
+ #define PORT_HW_CFG_TX_LASER_GPIO1 0x00000002
+ #define PORT_HW_CFG_TX_LASER_GPIO2 0x00000003
+ #define PORT_HW_CFG_TX_LASER_GPIO3 0x00000004
+
+ /* Controls the fault module LED of the SFP+ */
+ #define PORT_HW_CFG_FAULT_MODULE_LED_MASK 0x0000FF00
+ #define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT 8
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0 0x00000000
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1 0x00000100
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2 0x00000200
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3 0x00000300
+ #define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED 0x00000400
+
+ /* The output pin TX_DIS that controls the TX laser of the SFP+
+ module. Use the PIN_CFG_XXX defines on top */
+ u32 e3_sfp_ctrl; /* 0x168 */
+ #define PORT_HW_CFG_E3_TX_LASER_MASK 0x000000FF
+ #define PORT_HW_CFG_E3_TX_LASER_SHIFT 0
+
+ /* The output pin for SFPP_TYPE which turns on the Fault module LED */
+ #define PORT_HW_CFG_E3_FAULT_MDL_LED_MASK 0x0000FF00
+ #define PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT 8
+
+ /* The input pin MOD_ABS that indicates whether SFP+ module is
+ present or not. Use the PIN_CFG_XXX defines on top */
+ #define PORT_HW_CFG_E3_MOD_ABS_MASK 0x00FF0000
+ #define PORT_HW_CFG_E3_MOD_ABS_SHIFT 16
+
+ /* The output pin PWRDIS_SFP_X which disable the power of the SFP+
+ module. Use the PIN_CFG_XXX defines on top */
+ #define PORT_HW_CFG_E3_PWR_DIS_MASK 0xFF000000
+ #define PORT_HW_CFG_E3_PWR_DIS_SHIFT 24
/*
- * When KR link is required to be set to force which is not
- * KR-compliant, this parameter determine what is the trigger for it.
- * When GPIO is selected, low input will force the speed. Currently
- * default speed is 1G. In the future, it may be widen to select the
- * forced speed in with another parameter. Note when force-1G is
- * enabled, it override option 56: Link Speed option.
+ * The input pin which signals module transmit fault. Use the
+ * PIN_CFG_XXX defines on top
*/
-#define PORT_HW_CFG_FORCE_KR_ENABLER_MASK 0x00000F00
-#define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT 8
-#define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED 0x00000000
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0 0x00000100
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0 0x00000200
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0 0x00000300
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0 0x00000400
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1 0x00000500
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1 0x00000600
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1 0x00000700
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1 0x00000800
-#define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED 0x00000900
- /* Enable to determine with which GPIO to reset the external phy */
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK 0x000F0000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT 16
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE 0x00000000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0 0x00010000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0 0x00020000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0 0x00030000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0 0x00040000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1 0x00050000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1 0x00060000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1 0x00070000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1 0x00080000
+ u32 e3_cmn_pin_cfg; /* 0x16C */
+ #define PORT_HW_CFG_E3_TX_FAULT_MASK 0x000000FF
+ #define PORT_HW_CFG_E3_TX_FAULT_SHIFT 0
+
+ /* The output pin which reset the PHY. Use the PIN_CFG_XXX defines on
+ top */
+ #define PORT_HW_CFG_E3_PHY_RESET_MASK 0x0000FF00
+ #define PORT_HW_CFG_E3_PHY_RESET_SHIFT 8
+
+ /*
+ * The output pin which powers down the PHY. Use the PIN_CFG_XXX
+ * defines on top
+ */
+ #define PORT_HW_CFG_E3_PWR_DOWN_MASK 0x00FF0000
+ #define PORT_HW_CFG_E3_PWR_DOWN_SHIFT 16
+
+ /* The output pin values BSC_SEL which selects the I2C for this port
+ in the I2C Mux */
+ #define PORT_HW_CFG_E3_I2C_MUX0_MASK 0x01000000
+ #define PORT_HW_CFG_E3_I2C_MUX1_MASK 0x02000000
+
+
+ /*
+ * The input pin I_FAULT which indicate over-current has occurred.
+ * Use the PIN_CFG_XXX defines on top
+ */
+ u32 e3_cmn_pin_cfg1; /* 0x170 */
+ #define PORT_HW_CFG_E3_OVER_CURRENT_MASK 0x000000FF
+ #define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT 0
+ u32 reserved0[7]; /* 0x174 */
+
+ u32 aeu_int_mask; /* 0x190 */
+
+ u32 media_type; /* 0x194 */
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK 0x000000FF
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT 0
+
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK 0x0000FF00
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT 8
+
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK 0x00FF0000
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT 16
+
+ /* 4 times 16 bits for all 4 lanes. In case external PHY is present
+ (not direct mode), those values will not take effect on the 4 XGXS
+ lanes. For some external PHYs (such as 8706 and 8726) the values
+ will be used to configure the external PHY in those cases, not
+ all 4 values are needed. */
+ u16 xgxs_config_rx[4]; /* 0x198 */
+ u16 xgxs_config_tx[4]; /* 0x1A0 */
+
+ /* For storing FCOE mac on shared memory */
+ u32 fcoe_fip_mac_upper;
+ #define PORT_HW_CFG_FCOE_UPPERMAC_MASK 0x0000ffff
+ #define PORT_HW_CFG_FCOE_UPPERMAC_SHIFT 0
+ u32 fcoe_fip_mac_lower;
+
+ u32 fcoe_wwn_port_name_upper;
+ u32 fcoe_wwn_port_name_lower;
+
+ u32 fcoe_wwn_node_name_upper;
+ u32 fcoe_wwn_node_name_lower;
+
+ u32 Reserved1[49]; /* 0x1C0 */
+
+ /* Enable RJ45 magjack pair swapping on 10GBase-T PHY (0=default),
+ 84833 only */
+ u32 xgbt_phy_cfg; /* 0x284 */
+ #define PORT_HW_CFG_RJ45_PAIR_SWAP_MASK 0x000000FF
+ #define PORT_HW_CFG_RJ45_PAIR_SWAP_SHIFT 0
+
+ u32 default_cfg; /* 0x288 */
+ #define PORT_HW_CFG_GPIO0_CONFIG_MASK 0x00000003
+ #define PORT_HW_CFG_GPIO0_CONFIG_SHIFT 0
+ #define PORT_HW_CFG_GPIO0_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO0_CONFIG_LOW 0x00000001
+ #define PORT_HW_CFG_GPIO0_CONFIG_HIGH 0x00000002
+ #define PORT_HW_CFG_GPIO0_CONFIG_INPUT 0x00000003
+
+ #define PORT_HW_CFG_GPIO1_CONFIG_MASK 0x0000000C
+ #define PORT_HW_CFG_GPIO1_CONFIG_SHIFT 2
+ #define PORT_HW_CFG_GPIO1_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO1_CONFIG_LOW 0x00000004
+ #define PORT_HW_CFG_GPIO1_CONFIG_HIGH 0x00000008
+ #define PORT_HW_CFG_GPIO1_CONFIG_INPUT 0x0000000c
+
+ #define PORT_HW_CFG_GPIO2_CONFIG_MASK 0x00000030
+ #define PORT_HW_CFG_GPIO2_CONFIG_SHIFT 4
+ #define PORT_HW_CFG_GPIO2_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO2_CONFIG_LOW 0x00000010
+ #define PORT_HW_CFG_GPIO2_CONFIG_HIGH 0x00000020
+ #define PORT_HW_CFG_GPIO2_CONFIG_INPUT 0x00000030
+
+ #define PORT_HW_CFG_GPIO3_CONFIG_MASK 0x000000C0
+ #define PORT_HW_CFG_GPIO3_CONFIG_SHIFT 6
+ #define PORT_HW_CFG_GPIO3_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO3_CONFIG_LOW 0x00000040
+ #define PORT_HW_CFG_GPIO3_CONFIG_HIGH 0x00000080
+ #define PORT_HW_CFG_GPIO3_CONFIG_INPUT 0x000000c0
+
+ /* When KR link is required to be set to force which is not
+ KR-compliant, this parameter determine what is the trigger for it.
+ When GPIO is selected, low input will force the speed. Currently
+ default speed is 1G. In the future, it may be widen to select the
+ forced speed in with another parameter. Note when force-1G is
+ enabled, it override option 56: Link Speed option. */
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_MASK 0x00000F00
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT 8
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED 0x00000000
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0 0x00000100
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0 0x00000200
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0 0x00000300
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0 0x00000400
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1 0x00000500
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1 0x00000600
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1 0x00000700
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1 0x00000800
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED 0x00000900
+ /* Enable to determine with which GPIO to reset the external phy */
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK 0x000F0000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT 16
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE 0x00000000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0 0x00010000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0 0x00020000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0 0x00030000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0 0x00040000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1 0x00050000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1 0x00060000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1 0x00070000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1 0x00080000
+
/* Enable BAM on KR */
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED 0x00000000
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED 0x00100000
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED 0x00000000
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED 0x00100000
/* Enable Common Mode Sense */
-#define PORT_HW_CFG_ENABLE_CMS_MASK 0x00200000
-#define PORT_HW_CFG_ENABLE_CMS_SHIFT 21
-#define PORT_HW_CFG_ENABLE_CMS_DISABLED 0x00000000
-#define PORT_HW_CFG_ENABLE_CMS_ENABLED 0x00200000
+ #define PORT_HW_CFG_ENABLE_CMS_MASK 0x00200000
+ #define PORT_HW_CFG_ENABLE_CMS_SHIFT 21
+ #define PORT_HW_CFG_ENABLE_CMS_DISABLED 0x00000000
+ #define PORT_HW_CFG_ENABLE_CMS_ENABLED 0x00200000
+
+ /* Enable RJ45 magjack pair swapping on 10GBase-T PHY, 84833 only */
+ #define PORT_HW_CFG_RJ45_PR_SWP_MASK 0x00400000
+ #define PORT_HW_CFG_RJ45_PR_SWP_SHIFT 22
+ #define PORT_HW_CFG_RJ45_PR_SWP_DISABLED 0x00000000
+ #define PORT_HW_CFG_RJ45_PR_SWP_ENABLED 0x00400000
+
+ /* Determine the Serdes electrical interface */
+ #define PORT_HW_CFG_NET_SERDES_IF_MASK 0x0F000000
+ #define PORT_HW_CFG_NET_SERDES_IF_SHIFT 24
+ #define PORT_HW_CFG_NET_SERDES_IF_SGMII 0x00000000
+ #define PORT_HW_CFG_NET_SERDES_IF_XFI 0x01000000
+ #define PORT_HW_CFG_NET_SERDES_IF_SFI 0x02000000
+ #define PORT_HW_CFG_NET_SERDES_IF_KR 0x03000000
+ #define PORT_HW_CFG_NET_SERDES_IF_DXGXS 0x04000000
+ #define PORT_HW_CFG_NET_SERDES_IF_KR2 0x05000000
+
u32 speed_capability_mask2; /* 0x28C */
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__ 0x00000002
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___ 0x00000004
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G 0x00000020
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12G 0x00000080
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12_DOT_5G 0x00000100
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_13G 0x00000200
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_15G 0x00000400
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_16G 0x00000800
-
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__ 0x00020000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___ 0x00040000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G 0x00200000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12G 0x00800000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12_DOT_5G 0x01000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_13G 0x02000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_15G 0x04000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_16G 0x08000000
-
- /* In the case where two media types (e.g. copper and fiber) are
- present and electrically active at the same time, PHY Selection
- will determine which of the two PHYs will be designated as the
- Active PHY and used for a connection to the network. */
- u32 multi_phy_config; /* 0x290 */
-#define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007
-#define PORT_HW_CFG_PHY_SELECTION_SHIFT 0
-#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000
-#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001
-#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002
-#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
-#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
-
- /* When enabled, all second phy nvram parameters will be swapped
- with the first phy parameters */
-#define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008
-#define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3
-#define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000
-#define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008
-
-
- /* Address of the second external phy */
- u32 external_phy_config2; /* 0x294 */
-#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF
-#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0
-
- /* The second XGXS external PHY type */
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071 0x00000100
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072 0x00000200
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073 0x00000300
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705 0x00000400
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706 0x00000500
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726 0x00000600
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481 0x00000700
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727 0x00000900
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC 0x00000a00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
-
- /* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
- 8706, 8726 and 8727) not all 4 values are needed. */
- u16 xgxs_config2_rx[4]; /* 0x296 */
- u16 xgxs_config2_tx[4]; /* 0x2A0 */
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3__ 0x00000002
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3___ 0x00000004
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G 0x00000020
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_20G 0x00000080
+
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0__ 0x00020000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0___ 0x00040000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G 0x00200000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_20G 0x00800000
+
+
+ /* In the case where two media types (e.g. copper and fiber) are
+ present and electrically active at the same time, PHY Selection
+ will determine which of the two PHYs will be designated as the
+ Active PHY and used for a connection to the network. */
+ u32 multi_phy_config; /* 0x290 */
+ #define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007
+ #define PORT_HW_CFG_PHY_SELECTION_SHIFT 0
+ #define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000
+ #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001
+ #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002
+ #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
+ #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
+
+ /* When enabled, all second phy nvram parameters will be swapped
+ with the first phy parameters */
+ #define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008
+ #define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3
+ #define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000
+ #define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008
+
+
+ /* Address of the second external phy */
+ u32 external_phy_config2; /* 0x294 */
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0
+
+ /* The second XGXS external PHY type */
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071 0x00000100
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072 0x00000200
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073 0x00000300
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705 0x00000400
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706 0x00000500
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726 0x00000600
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481 0x00000700
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727 0x00000900
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC 0x00000a00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00
+ #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_FAILURE 0x0000fd00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
+
+
+ /* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
+ 8706, 8726 and 8727) not all 4 values are needed. */
+ u16 xgxs_config2_rx[4]; /* 0x296 */
+ u16 xgxs_config2_tx[4]; /* 0x2A0 */
u32 lane_config;
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff
-#define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 0
-
-#define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000ff
-#define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0
-#define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000ff00
-#define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK 0x0000c000
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT 14
- /* AN and forced */
-#define PORT_HW_CFG_LANE_SWAP_CFG_01230123 0x00001b1b
- /* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_01233210 0x00001be4
- /* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_31203120 0x0000d8d8
- /* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_32103210 0x0000e4e4
- /* Indicate whether to swap the external phy polarity */
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK 0x00010000
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED 0x00000000
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED 0x00010000
+ #define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff
+ #define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 0
+ /* AN and forced */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_01230123 0x00001b1b
+ /* forced only */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_01233210 0x00001be4
+ /* forced only */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_31203120 0x0000d8d8
+ /* forced only */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_32103210 0x0000e4e4
+ #define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000ff
+ #define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0
+ #define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000ff00
+ #define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8
+ #define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK 0x0000c000
+ #define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT 14
+
+ /* Indicate whether to swap the external phy polarity */
+ #define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK 0x00010000
+ #define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED 0x00000000
+ #define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED 0x00010000
+
u32 external_phy_config;
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK 0xff000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT 24
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT 0x00000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482 0x01000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN 0xff000000
-
-#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK 0x00ff0000
-#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT 16
-
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK 0x0000ff00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT 8
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT 0x00000000
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071 0x00000100
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072 0x00000200
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073 0x00000300
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705 0x00000400
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 0x00000500
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726 0x00000600
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 0x00000900
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC 0x00000a00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823 0x00000b00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833 0x00000d00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
-
-#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK 0x000000ff
-#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT 0
+ #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK 0x000000ff
+ #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT 0
+
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK 0x0000ff00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT 8
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT 0x00000000
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071 0x00000100
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072 0x00000200
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073 0x00000300
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705 0x00000400
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 0x00000500
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726 0x00000600
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 0x00000900
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC 0x00000a00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823 0x00000b00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54640 0x00000c00
+ #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_DIRECT_WC 0x0000fc00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
+
+ #define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK 0x00ff0000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT 16
+
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK 0xff000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT 24
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT 0x00000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482 0x01000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD 0x02000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN 0xff000000
u32 speed_capability_mask;
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK 0xffff0000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT 16
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL 0x00010000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF 0x00020000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF 0x00040000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL 0x00080000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G 0x00100000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G 0x00200000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G 0x00400000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_12G 0x00800000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_12_5G 0x01000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_13G 0x02000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_15G 0x04000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_16G 0x08000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED 0xf0000000
-
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK 0x0000ffff
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT 0
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL 0x00000001
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF 0x00000002
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF 0x00000004
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL 0x00000008
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G 0x00000010
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G 0x00000020
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G 0x00000040
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_12G 0x00000080
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_12_5G 0x00000100
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_13G 0x00000200
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_15G 0x00000400
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_16G 0x00000800
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED 0x0000f000
-
- u32 reserved[2];
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK 0x0000ffff
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT 0
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL 0x00000001
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF 0x00000002
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF 0x00000004
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL 0x00000008
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G 0x00000010
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G 0x00000020
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G 0x00000040
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_20G 0x00000080
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED 0x0000f000
+
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK 0xffff0000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT 16
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL 0x00010000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF 0x00020000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF 0x00040000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL 0x00080000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G 0x00100000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G 0x00200000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G 0x00400000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_20G 0x00800000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED 0xf0000000
+
+ /* A place to hold the original MAC address as a backup */
+ u32 backup_mac_upper; /* 0x2B4 */
+ u32 backup_mac_lower; /* 0x2B8 */
};
/****************************************************************************
- * Shared Feature configuration *
+ * Shared Feature configuration *
****************************************************************************/
-struct shared_feat_cfg { /* NVRAM Offset */
+struct shared_feat_cfg { /* NVRAM Offset */
+
+ u32 config; /* 0x450 */
+ #define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001
+
+ /* Use NVRAM values instead of HW default values */
+ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_MASK \
+ 0x00000002
+ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED \
+ 0x00000000
+ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED \
+ 0x00000002
- u32 config; /* 0x450 */
-#define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001
+ #define SHARED_FEAT_CFG_NCSI_ID_METHOD_MASK 0x00000008
+ #define SHARED_FEAT_CFG_NCSI_ID_METHOD_SPIO 0x00000000
+ #define SHARED_FEAT_CFG_NCSI_ID_METHOD_NVRAM 0x00000008
- /* Use the values from options 47 and 48 instead of the HW default
- values */
-#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED 0x00000000
-#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED 0x00000002
+ #define SHARED_FEAT_CFG_NCSI_ID_MASK 0x00000030
+ #define SHARED_FEAT_CFG_NCSI_ID_SHIFT 4
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK 0x00000700
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT 8
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED 0x00000000
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF 0x00000100
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4 0x00000200
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT 0x00000300
+ /* Override the OTP back to single function mode. When using GPIO,
+ high means only SF, 0 is according to CLP configuration */
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK 0x00000700
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT 8
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED 0x00000000
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF 0x00000100
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4 0x00000200
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT 0x00000300
+
+ /* The interval in seconds between sending LLDP packets. Set to zero
+ to disable the feature */
+ #define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_MASK 0x00ff0000
+ #define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_SHIFT 16
+
+ /* The assigned device type ID for LLDP usage */
+ #define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_MASK 0xff000000
+ #define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_SHIFT 24
};
/****************************************************************************
- * Port Feature configuration *
+ * Port Feature configuration *
****************************************************************************/
-struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
+struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
u32 config;
-#define PORT_FEATURE_BAR1_SIZE_MASK 0x0000000f
-#define PORT_FEATURE_BAR1_SIZE_SHIFT 0
-#define PORT_FEATURE_BAR1_SIZE_DISABLED 0x00000000
-#define PORT_FEATURE_BAR1_SIZE_64K 0x00000001
-#define PORT_FEATURE_BAR1_SIZE_128K 0x00000002
-#define PORT_FEATURE_BAR1_SIZE_256K 0x00000003
-#define PORT_FEATURE_BAR1_SIZE_512K 0x00000004
-#define PORT_FEATURE_BAR1_SIZE_1M 0x00000005
-#define PORT_FEATURE_BAR1_SIZE_2M 0x00000006
-#define PORT_FEATURE_BAR1_SIZE_4M 0x00000007
-#define PORT_FEATURE_BAR1_SIZE_8M 0x00000008
-#define PORT_FEATURE_BAR1_SIZE_16M 0x00000009
-#define PORT_FEATURE_BAR1_SIZE_32M 0x0000000a
-#define PORT_FEATURE_BAR1_SIZE_64M 0x0000000b
-#define PORT_FEATURE_BAR1_SIZE_128M 0x0000000c
-#define PORT_FEATURE_BAR1_SIZE_256M 0x0000000d
-#define PORT_FEATURE_BAR1_SIZE_512M 0x0000000e
-#define PORT_FEATURE_BAR1_SIZE_1G 0x0000000f
-#define PORT_FEATURE_BAR2_SIZE_MASK 0x000000f0
-#define PORT_FEATURE_BAR2_SIZE_SHIFT 4
-#define PORT_FEATURE_BAR2_SIZE_DISABLED 0x00000000
-#define PORT_FEATURE_BAR2_SIZE_64K 0x00000010
-#define PORT_FEATURE_BAR2_SIZE_128K 0x00000020
-#define PORT_FEATURE_BAR2_SIZE_256K 0x00000030
-#define PORT_FEATURE_BAR2_SIZE_512K 0x00000040
-#define PORT_FEATURE_BAR2_SIZE_1M 0x00000050
-#define PORT_FEATURE_BAR2_SIZE_2M 0x00000060
-#define PORT_FEATURE_BAR2_SIZE_4M 0x00000070
-#define PORT_FEATURE_BAR2_SIZE_8M 0x00000080
-#define PORT_FEATURE_BAR2_SIZE_16M 0x00000090
-#define PORT_FEATURE_BAR2_SIZE_32M 0x000000a0
-#define PORT_FEATURE_BAR2_SIZE_64M 0x000000b0
-#define PORT_FEATURE_BAR2_SIZE_128M 0x000000c0
-#define PORT_FEATURE_BAR2_SIZE_256M 0x000000d0
-#define PORT_FEATURE_BAR2_SIZE_512M 0x000000e0
-#define PORT_FEATURE_BAR2_SIZE_1G 0x000000f0
-#define PORT_FEATURE_EN_SIZE_MASK 0x07000000
-#define PORT_FEATURE_EN_SIZE_SHIFT 24
-#define PORT_FEATURE_WOL_ENABLED 0x01000000
-#define PORT_FEATURE_MBA_ENABLED 0x02000000
-#define PORT_FEATURE_MFW_ENABLED 0x04000000
-
- /* Reserved bits: 28-29 */
- /* Check the optic vendor via i2c against a list of approved modules
- in a separate nvram image */
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK 0xE0000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT 29
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT 0x00000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER 0x20000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG 0x40000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN 0x60000000
-
+ #define PORT_FEATURE_BAR1_SIZE_MASK 0x0000000f
+ #define PORT_FEATURE_BAR1_SIZE_SHIFT 0
+ #define PORT_FEATURE_BAR1_SIZE_DISABLED 0x00000000
+ #define PORT_FEATURE_BAR1_SIZE_64K 0x00000001
+ #define PORT_FEATURE_BAR1_SIZE_128K 0x00000002
+ #define PORT_FEATURE_BAR1_SIZE_256K 0x00000003
+ #define PORT_FEATURE_BAR1_SIZE_512K 0x00000004
+ #define PORT_FEATURE_BAR1_SIZE_1M 0x00000005
+ #define PORT_FEATURE_BAR1_SIZE_2M 0x00000006
+ #define PORT_FEATURE_BAR1_SIZE_4M 0x00000007
+ #define PORT_FEATURE_BAR1_SIZE_8M 0x00000008
+ #define PORT_FEATURE_BAR1_SIZE_16M 0x00000009
+ #define PORT_FEATURE_BAR1_SIZE_32M 0x0000000a
+ #define PORT_FEATURE_BAR1_SIZE_64M 0x0000000b
+ #define PORT_FEATURE_BAR1_SIZE_128M 0x0000000c
+ #define PORT_FEATURE_BAR1_SIZE_256M 0x0000000d
+ #define PORT_FEATURE_BAR1_SIZE_512M 0x0000000e
+ #define PORT_FEATURE_BAR1_SIZE_1G 0x0000000f
+ #define PORT_FEATURE_BAR2_SIZE_MASK 0x000000f0
+ #define PORT_FEATURE_BAR2_SIZE_SHIFT 4
+ #define PORT_FEATURE_BAR2_SIZE_DISABLED 0x00000000
+ #define PORT_FEATURE_BAR2_SIZE_64K 0x00000010
+ #define PORT_FEATURE_BAR2_SIZE_128K 0x00000020
+ #define PORT_FEATURE_BAR2_SIZE_256K 0x00000030
+ #define PORT_FEATURE_BAR2_SIZE_512K 0x00000040
+ #define PORT_FEATURE_BAR2_SIZE_1M 0x00000050
+ #define PORT_FEATURE_BAR2_SIZE_2M 0x00000060
+ #define PORT_FEATURE_BAR2_SIZE_4M 0x00000070
+ #define PORT_FEATURE_BAR2_SIZE_8M 0x00000080
+ #define PORT_FEATURE_BAR2_SIZE_16M 0x00000090
+ #define PORT_FEATURE_BAR2_SIZE_32M 0x000000a0
+ #define PORT_FEATURE_BAR2_SIZE_64M 0x000000b0
+ #define PORT_FEATURE_BAR2_SIZE_128M 0x000000c0
+ #define PORT_FEATURE_BAR2_SIZE_256M 0x000000d0
+ #define PORT_FEATURE_BAR2_SIZE_512M 0x000000e0
+ #define PORT_FEATURE_BAR2_SIZE_1G 0x000000f0
+
+ #define PORT_FEAT_CFG_DCBX_MASK 0x00000100
+ #define PORT_FEAT_CFG_DCBX_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_DCBX_ENABLED 0x00000100
+
+ #define PORT_FEAT_CFG_AUTOGREEN_MASK 0x00000200
+ #define PORT_FEAT_CFG_AUTOGREEN_SHIFT 9
+ #define PORT_FEAT_CFG_AUTOGREEN_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_AUTOGREEN_ENABLED 0x00000200
+
+ #define PORT_FEATURE_EN_SIZE_MASK 0x0f000000
+ #define PORT_FEATURE_EN_SIZE_SHIFT 24
+ #define PORT_FEATURE_WOL_ENABLED 0x01000000
+ #define PORT_FEATURE_MBA_ENABLED 0x02000000
+ #define PORT_FEATURE_MFW_ENABLED 0x04000000
+
+ /* Advertise expansion ROM even if MBA is disabled */
+ #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_MASK 0x08000000
+ #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_ENABLED 0x08000000
+
+ /* Check the optic vendor via i2c against a list of approved modules
+ in a separate nvram image */
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK 0xe0000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT 29
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT \
+ 0x00000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER \
+ 0x20000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG 0x40000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN 0x60000000
u32 wol_config;
/* Default is used when driver sets to "auto" mode */
-#define PORT_FEATURE_WOL_DEFAULT_MASK 0x00000003
-#define PORT_FEATURE_WOL_DEFAULT_SHIFT 0
-#define PORT_FEATURE_WOL_DEFAULT_DISABLE 0x00000000
-#define PORT_FEATURE_WOL_DEFAULT_MAGIC 0x00000001
-#define PORT_FEATURE_WOL_DEFAULT_ACPI 0x00000002
-#define PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x00000003
-#define PORT_FEATURE_WOL_RES_PAUSE_CAP 0x00000004
-#define PORT_FEATURE_WOL_RES_ASYM_PAUSE_CAP 0x00000008
-#define PORT_FEATURE_WOL_ACPI_UPON_MGMT 0x00000010
+ #define PORT_FEATURE_WOL_DEFAULT_MASK 0x00000003
+ #define PORT_FEATURE_WOL_DEFAULT_SHIFT 0
+ #define PORT_FEATURE_WOL_DEFAULT_DISABLE 0x00000000
+ #define PORT_FEATURE_WOL_DEFAULT_MAGIC 0x00000001
+ #define PORT_FEATURE_WOL_DEFAULT_ACPI 0x00000002
+ #define PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x00000003
+ #define PORT_FEATURE_WOL_RES_PAUSE_CAP 0x00000004
+ #define PORT_FEATURE_WOL_RES_ASYM_PAUSE_CAP 0x00000008
+ #define PORT_FEATURE_WOL_ACPI_UPON_MGMT 0x00000010
u32 mba_config;
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x00000003
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT 0
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0x00000000
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 0x00000001
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 0x00000002
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB 0x00000003
-#define PORT_FEATURE_MBA_RES_PAUSE_CAP 0x00000100
-#define PORT_FEATURE_MBA_RES_ASYM_PAUSE_CAP 0x00000200
-#define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x00000400
-#define PORT_FEATURE_MBA_HOTKEY_CTRL_S 0x00000000
-#define PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x00000800
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0x000ff000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT 12
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0x00000000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x00001000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x00002000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x00003000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x00004000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x00005000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x00006000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x00007000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x00008000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0x00009000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0x0000a000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0x0000b000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0x0000c000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0x0000d000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0x0000e000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M 0x0000f000
-#define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0x00f00000
-#define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT 20
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x03000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT 24
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0x00000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x01000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x02000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x03000000
-#define PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_SHIFT 26
-#define PORT_FEATURE_MBA_LINK_SPEED_AUTO 0x00000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10HD 0x04000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10FD 0x08000000
-#define PORT_FEATURE_MBA_LINK_SPEED_100HD 0x0c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_100FD 0x10000000
-#define PORT_FEATURE_MBA_LINK_SPEED_1GBPS 0x14000000
-#define PORT_FEATURE_MBA_LINK_SPEED_2_5GBPS 0x18000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_CX4 0x1c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_KX4 0x20000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_KR 0x24000000
-#define PORT_FEATURE_MBA_LINK_SPEED_12GBPS 0x28000000
-#define PORT_FEATURE_MBA_LINK_SPEED_12_5GBPS 0x2c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_13GBPS 0x30000000
-#define PORT_FEATURE_MBA_LINK_SPEED_15GBPS 0x34000000
-#define PORT_FEATURE_MBA_LINK_SPEED_16GBPS 0x38000000
-
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x00000007
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT 0
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0x00000000
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 0x00000001
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 0x00000002
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB 0x00000003
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_FCOE_BOOT 0x00000004
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_NONE 0x00000007
+
+ #define PORT_FEATURE_MBA_BOOT_RETRY_MASK 0x00000038
+ #define PORT_FEATURE_MBA_BOOT_RETRY_SHIFT 3
+
+ #define PORT_FEATURE_MBA_RES_PAUSE_CAP 0x00000100
+ #define PORT_FEATURE_MBA_RES_ASYM_PAUSE_CAP 0x00000200
+ #define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x00000400
+ #define PORT_FEATURE_MBA_HOTKEY_MASK 0x00000800
+ #define PORT_FEATURE_MBA_HOTKEY_CTRL_S 0x00000000
+ #define PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x00000800
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0x000ff000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT 12
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0x00000000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x00001000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x00002000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x00003000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x00004000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x00005000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x00006000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x00007000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x00008000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0x00009000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0x0000a000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0x0000b000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0x0000c000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0x0000d000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0x0000e000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M 0x0000f000
+ #define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0x00f00000
+ #define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT 20
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x03000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT 24
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0x00000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x01000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x02000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x03000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_SHIFT 26
+ #define PORT_FEATURE_MBA_LINK_SPEED_AUTO 0x00000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_10HD 0x04000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_10FD 0x08000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_100HD 0x0c000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_100FD 0x10000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_1GBPS 0x14000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_2_5GBPS 0x18000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_CX4 0x1c000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_20GBPS 0x20000000
u32 bmc_config;
-#define PORT_FEATURE_BMC_LINK_OVERRIDE_DEFAULT 0x00000000
-#define PORT_FEATURE_BMC_LINK_OVERRIDE_EN 0x00000001
+ #define PORT_FEATURE_BMC_LINK_OVERRIDE_MASK 0x00000001
+ #define PORT_FEATURE_BMC_LINK_OVERRIDE_DEFAULT 0x00000000
+ #define PORT_FEATURE_BMC_LINK_OVERRIDE_EN 0x00000001
u32 mba_vlan_cfg;
-#define PORT_FEATURE_MBA_VLAN_TAG_MASK 0x0000ffff
-#define PORT_FEATURE_MBA_VLAN_TAG_SHIFT 0
-#define PORT_FEATURE_MBA_VLAN_EN 0x00010000
+ #define PORT_FEATURE_MBA_VLAN_TAG_MASK 0x0000ffff
+ #define PORT_FEATURE_MBA_VLAN_TAG_SHIFT 0
+ #define PORT_FEATURE_MBA_VLAN_EN 0x00010000
u32 resource_cfg;
-#define PORT_FEATURE_RESOURCE_CFG_VALID 0x00000001
-#define PORT_FEATURE_RESOURCE_CFG_DIAG 0x00000002
-#define PORT_FEATURE_RESOURCE_CFG_L2 0x00000004
-#define PORT_FEATURE_RESOURCE_CFG_ISCSI 0x00000008
-#define PORT_FEATURE_RESOURCE_CFG_RDMA 0x00000010
+ #define PORT_FEATURE_RESOURCE_CFG_VALID 0x00000001
+ #define PORT_FEATURE_RESOURCE_CFG_DIAG 0x00000002
+ #define PORT_FEATURE_RESOURCE_CFG_L2 0x00000004
+ #define PORT_FEATURE_RESOURCE_CFG_ISCSI 0x00000008
+ #define PORT_FEATURE_RESOURCE_CFG_RDMA 0x00000010
u32 smbus_config;
- /* Obsolete */
-#define PORT_FEATURE_SMBUS_EN 0x00000001
-#define PORT_FEATURE_SMBUS_ADDR_MASK 0x000000fe
-#define PORT_FEATURE_SMBUS_ADDR_SHIFT 1
-
- u32 reserved1;
+ #define PORT_FEATURE_SMBUS_ADDR_MASK 0x000000fe
+ #define PORT_FEATURE_SMBUS_ADDR_SHIFT 1
+
+ u32 vf_config;
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_MASK 0x0000000f
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_SHIFT 0
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_4K 0x00000001
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_8K 0x00000002
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_16K 0x00000003
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_32K 0x00000004
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_64K 0x00000005
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_128K 0x00000006
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_256K 0x00000007
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_512K 0x00000008
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_1M 0x00000009
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_2M 0x0000000a
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_4M 0x0000000b
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_8M 0x0000000c
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_16M 0x0000000d
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_32M 0x0000000e
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_64M 0x0000000f
u32 link_config; /* Used as HW defaults for the driver */
-#define PORT_FEATURE_CONNECTED_SWITCH_MASK 0x03000000
-#define PORT_FEATURE_CONNECTED_SWITCH_SHIFT 24
- /* (forced) low speed switch (< 10G) */
-#define PORT_FEATURE_CON_SWITCH_1G_SWITCH 0x00000000
- /* (forced) high speed switch (>= 10G) */
-#define PORT_FEATURE_CON_SWITCH_10G_SWITCH 0x01000000
-#define PORT_FEATURE_CON_SWITCH_AUTO_DETECT 0x02000000
-#define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT 0x03000000
-
-#define PORT_FEATURE_LINK_SPEED_MASK 0x000f0000
-#define PORT_FEATURE_LINK_SPEED_SHIFT 16
-#define PORT_FEATURE_LINK_SPEED_AUTO 0x00000000
-#define PORT_FEATURE_LINK_SPEED_10M_FULL 0x00010000
-#define PORT_FEATURE_LINK_SPEED_10M_HALF 0x00020000
-#define PORT_FEATURE_LINK_SPEED_100M_HALF 0x00030000
-#define PORT_FEATURE_LINK_SPEED_100M_FULL 0x00040000
-#define PORT_FEATURE_LINK_SPEED_1G 0x00050000
-#define PORT_FEATURE_LINK_SPEED_2_5G 0x00060000
-#define PORT_FEATURE_LINK_SPEED_10G_CX4 0x00070000
-#define PORT_FEATURE_LINK_SPEED_10G_KX4 0x00080000
-#define PORT_FEATURE_LINK_SPEED_10G_KR 0x00090000
-#define PORT_FEATURE_LINK_SPEED_12G 0x000a0000
-#define PORT_FEATURE_LINK_SPEED_12_5G 0x000b0000
-#define PORT_FEATURE_LINK_SPEED_13G 0x000c0000
-#define PORT_FEATURE_LINK_SPEED_15G 0x000d0000
-#define PORT_FEATURE_LINK_SPEED_16G 0x000e0000
-
-#define PORT_FEATURE_FLOW_CONTROL_MASK 0x00000700
-#define PORT_FEATURE_FLOW_CONTROL_SHIFT 8
-#define PORT_FEATURE_FLOW_CONTROL_AUTO 0x00000000
-#define PORT_FEATURE_FLOW_CONTROL_TX 0x00000100
-#define PORT_FEATURE_FLOW_CONTROL_RX 0x00000200
-#define PORT_FEATURE_FLOW_CONTROL_BOTH 0x00000300
-#define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400
+ #define PORT_FEATURE_CONNECTED_SWITCH_MASK 0x03000000
+ #define PORT_FEATURE_CONNECTED_SWITCH_SHIFT 24
+ /* (forced) low speed switch (< 10G) */
+ #define PORT_FEATURE_CON_SWITCH_1G_SWITCH 0x00000000
+ /* (forced) high speed switch (>= 10G) */
+ #define PORT_FEATURE_CON_SWITCH_10G_SWITCH 0x01000000
+ #define PORT_FEATURE_CON_SWITCH_AUTO_DETECT 0x02000000
+ #define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT 0x03000000
+
+ #define PORT_FEATURE_LINK_SPEED_MASK 0x000f0000
+ #define PORT_FEATURE_LINK_SPEED_SHIFT 16
+ #define PORT_FEATURE_LINK_SPEED_AUTO 0x00000000
+ #define PORT_FEATURE_LINK_SPEED_10M_FULL 0x00010000
+ #define PORT_FEATURE_LINK_SPEED_10M_HALF 0x00020000
+ #define PORT_FEATURE_LINK_SPEED_100M_HALF 0x00030000
+ #define PORT_FEATURE_LINK_SPEED_100M_FULL 0x00040000
+ #define PORT_FEATURE_LINK_SPEED_1G 0x00050000
+ #define PORT_FEATURE_LINK_SPEED_2_5G 0x00060000
+ #define PORT_FEATURE_LINK_SPEED_10G_CX4 0x00070000
+ #define PORT_FEATURE_LINK_SPEED_20G 0x00080000
+
+ #define PORT_FEATURE_FLOW_CONTROL_MASK 0x00000700
+ #define PORT_FEATURE_FLOW_CONTROL_SHIFT 8
+ #define PORT_FEATURE_FLOW_CONTROL_AUTO 0x00000000
+ #define PORT_FEATURE_FLOW_CONTROL_TX 0x00000100
+ #define PORT_FEATURE_FLOW_CONTROL_RX 0x00000200
+ #define PORT_FEATURE_FLOW_CONTROL_BOTH 0x00000300
+ #define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400
/* The default for MCP link configuration,
- uses the same defines as link_config */
+ uses the same defines as link_config */
u32 mfw_wol_link_cfg;
+
/* The default for the driver of the second external phy,
- uses the same defines as link_config */
- u32 link_config2; /* 0x47C */
+ uses the same defines as link_config */
+ u32 link_config2; /* 0x47C */
/* The default for MCP of the second external phy,
- uses the same defines as link_config */
- u32 mfw_wol_link_cfg2; /* 0x480 */
+ uses the same defines as link_config */
+ u32 mfw_wol_link_cfg2; /* 0x480 */
- u32 Reserved2[17]; /* 0x484 */
+ u32 Reserved2[17]; /* 0x484 */
};
/****************************************************************************
- * Device Information *
+ * Device Information *
****************************************************************************/
-struct shm_dev_info { /* size */
+struct shm_dev_info { /* size */
u32 bc_rev; /* 8 bits each: major, minor, build */ /* 4 */
- struct shared_hw_cfg shared_hw_config; /* 40 */
+ struct shared_hw_cfg shared_hw_config; /* 40 */
- struct port_hw_cfg port_hw_config[PORT_MAX]; /* 400*2=800 */
+ struct port_hw_cfg port_hw_config[PORT_MAX]; /* 400*2=800 */
- struct shared_feat_cfg shared_feature_config; /* 4 */
+ struct shared_feat_cfg shared_feature_config; /* 4 */
- struct port_feat_cfg port_feature_config[PORT_MAX];/* 116*2=232 */
+ struct port_feat_cfg port_feature_config[PORT_MAX];/* 116*2=232 */
};
-#define FUNC_0 0
-#define FUNC_1 1
-#define FUNC_2 2
-#define FUNC_3 3
-#define FUNC_4 4
-#define FUNC_5 5
-#define FUNC_6 6
-#define FUNC_7 7
-#define E1_FUNC_MAX 2
-#define E1H_FUNC_MAX 8
-#define E2_FUNC_MAX 4 /* per path */
-
-#define VN_0 0
-#define VN_1 1
-#define VN_2 2
-#define VN_3 3
-#define E1VN_MAX 1
-#define E1HVN_MAX 4
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+ #error "Missing either LITTLE_ENDIAN or BIG_ENDIAN definition."
+#endif
-#define E2_VF_MAX 64
+#define FUNC_0 0
+#define FUNC_1 1
+#define FUNC_2 2
+#define FUNC_3 3
+#define FUNC_4 4
+#define FUNC_5 5
+#define FUNC_6 6
+#define FUNC_7 7
+#define E1_FUNC_MAX 2
+#define E1H_FUNC_MAX 8
+#define E2_FUNC_MAX 4 /* per path */
+
+#define VN_0 0
+#define VN_1 1
+#define VN_2 2
+#define VN_3 3
+#define E1VN_MAX 1
+#define E1HVN_MAX 4
+
+#define E2_VF_MAX 64 /* HC_REG_VF_CONFIGURATION_SIZE */
/* This value (in milliseconds) determines the frequency of the driver
* issuing the PULSE message code. The firmware monitors this periodic
* pulse to determine when to switch to an OS-absent mode. */
-#define DRV_PULSE_PERIOD_MS 250
+#define DRV_PULSE_PERIOD_MS 250
/* This value (in milliseconds) determines how long the driver should
* wait for an acknowledgement from the firmware before timing out. Once
* the firmware has timed out, the driver will assume there is no firmware
* running and there won't be any firmware-driver synchronization during a
* driver reset. */
-#define FW_ACK_TIME_OUT_MS 5000
+#define FW_ACK_TIME_OUT_MS 5000
-#define FW_ACK_POLL_TIME_MS 1
+#define FW_ACK_POLL_TIME_MS 1
-#define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
+#define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
/* LED Blink rate that will achieve ~15.9Hz */
-#define LED_BLINK_RATE_VAL 480
+#define LED_BLINK_RATE_VAL 480
/****************************************************************************
- * Driver <-> FW Mailbox *
+ * Driver <-> FW Mailbox *
****************************************************************************/
struct drv_port_mb {
u32 link_status;
/* Driver should update this field on any link change event */
-#define LINK_STATUS_LINK_FLAG_MASK 0x00000001
-#define LINK_STATUS_LINK_UP 0x00000001
-#define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E
-#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE (0<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10THD (1<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD (2<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD (3<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100T4 (4<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD (5<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD (6<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD (7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD (8<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD (9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD (9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD (10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD (10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GTFD (11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GXFD (11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD (12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD (12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GTFD (13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GXFD (13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GTFD (14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GXFD (14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GTFD (15<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GXFD (15<<1)
-
-#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK 0x00000020
-#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020
-
-#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040
-#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK 0x00000080
-#define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080
-
-#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200
-#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400
-#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE 0x00000800
-#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE 0x00001000
-#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE 0x00002000
-#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE 0x00004000
-#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE 0x00008000
-
-#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK 0x00010000
-#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00010000
-
-#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK 0x00020000
-#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00020000
-
-#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000
-#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0<<18)
-#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE (1<<18)
-#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2<<18)
-#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3<<18)
-
-#define LINK_STATUS_SERDES_LINK 0x00100000
-
-#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE 0x00200000
-#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE 0x00400000
-#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000
-#define LINK_STATUS_LINK_PARTNER_12GXFD_CAPABLE 0x01000000
-#define LINK_STATUS_LINK_PARTNER_12_5GXFD_CAPABLE 0x02000000
-#define LINK_STATUS_LINK_PARTNER_13GXFD_CAPABLE 0x04000000
-#define LINK_STATUS_LINK_PARTNER_15GXFD_CAPABLE 0x08000000
-#define LINK_STATUS_LINK_PARTNER_16GXFD_CAPABLE 0x10000000
+ #define LINK_STATUS_LINK_FLAG_MASK 0x00000001
+ #define LINK_STATUS_LINK_UP 0x00000001
+ #define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E
+ #define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE (0<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10THD (1<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10TFD (2<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD (3<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_100T4 (4<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD (5<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_1000THD (6<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (7<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD (7<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_2500THD (8<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD (9<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD (9<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD (10<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD (10<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_20GTFD (11<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_20GXFD (11<<1)
+
+ #define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK 0x00000020
+ #define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020
+
+ #define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040
+ #define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK 0x00000080
+ #define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080
+
+ #define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200
+ #define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400
+ #define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE 0x00000800
+ #define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE 0x00001000
+ #define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE 0x00002000
+ #define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE 0x00004000
+ #define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE 0x00008000
+
+ #define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK 0x00010000
+ #define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00010000
+
+ #define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK 0x00020000
+ #define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00020000
+
+ #define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000
+ #define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0<<18)
+ #define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE (1<<18)
+ #define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2<<18)
+ #define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3<<18)
+
+ #define LINK_STATUS_SERDES_LINK 0x00100000
+
+ #define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE 0x00200000
+ #define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE 0x00400000
+ #define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000
+ #define LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE 0x10000000
+
+ #define LINK_STATUS_PFC_ENABLED 0x20000000
u32 port_stx;
@@ -887,138 +1217,159 @@ struct drv_port_mb {
struct drv_func_mb {
u32 drv_mb_header;
-#define DRV_MSG_CODE_MASK 0xffff0000
-#define DRV_MSG_CODE_LOAD_REQ 0x10000000
-#define DRV_MSG_CODE_LOAD_DONE 0x11000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN 0x20000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000
-#define DRV_MSG_CODE_UNLOAD_DONE 0x21000000
-#define DRV_MSG_CODE_DCC_OK 0x30000000
-#define DRV_MSG_CODE_DCC_FAILURE 0x31000000
-#define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000
-#define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000
-#define DRV_MSG_CODE_VALIDATE_KEY 0x70000000
-#define DRV_MSG_CODE_GET_CURR_KEY 0x80000000
-#define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000
-#define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000
-#define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000
- /*
- * The optic module verification commands require bootcode
- * v5.0.6 or later
- */
-#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000
-#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006
+ #define DRV_MSG_CODE_MASK 0xffff0000
+ #define DRV_MSG_CODE_LOAD_REQ 0x10000000
+ #define DRV_MSG_CODE_LOAD_DONE 0x11000000
+ #define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN 0x20000000
+ #define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000
+ #define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000
+ #define DRV_MSG_CODE_UNLOAD_DONE 0x21000000
+ #define DRV_MSG_CODE_DCC_OK 0x30000000
+ #define DRV_MSG_CODE_DCC_FAILURE 0x31000000
+ #define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000
+ #define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000
+ #define DRV_MSG_CODE_VALIDATE_KEY 0x70000000
+ #define DRV_MSG_CODE_GET_CURR_KEY 0x80000000
+ #define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000
+ #define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000
+ #define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000
/*
- * The specific optic module verification command requires bootcode
- * v5.2.12 or later
+ * The optic module verification command requires bootcode
+ * v5.0.6 or later, te specific optic module verification command
+ * requires bootcode v5.2.12 or later
*/
-#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000
-#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234
+ #define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000
+ #define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006
+ #define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000
+ #define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234
+ #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014
-#define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG 0xb0000000
-#define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000
-#define DRV_MSG_CODE_SET_MF_BW 0xe0000000
-#define REQ_BC_VER_4_SET_MF_BW 0x00060202
-#define DRV_MSG_CODE_SET_MF_BW_ACK 0xe1000000
-#define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
-#define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
-#define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000
-#define BIOS_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
+ #define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG 0xb0000000
+ #define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000
-#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
+ #define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000
+
+ #define DRV_MSG_CODE_SET_MF_BW 0xe0000000
+ #define REQ_BC_VER_4_SET_MF_BW 0x00060202
+ #define DRV_MSG_CODE_SET_MF_BW_ACK 0xe1000000
+
+ #define DRV_MSG_CODE_LINK_STATUS_CHANGED 0x01000000
+
+ #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
+ #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
+ #define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000
+ #define BIOS_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
+
+ #define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 drv_mb_param;
+ #define DRV_MSG_CODE_SET_MF_BW_MIN_MASK 0x00ff0000
+ #define DRV_MSG_CODE_SET_MF_BW_MAX_MASK 0xff000000
u32 fw_mb_header;
-#define FW_MSG_CODE_MASK 0xffff0000
-#define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000
-#define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000
-#define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000
- /* Load common chip is supported from bc 6.0.0 */
-#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP 0x00060000
-#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP 0x10130000
-#define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000
-#define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000
-#define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000
-#define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000
-#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000
-#define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000
-#define FW_MSG_CODE_DCC_DONE 0x30100000
-#define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000
-#define FW_MSG_CODE_DIAG_REFUSE 0x50200000
-#define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000
-#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS 0x70100000
-#define FW_MSG_CODE_VALIDATE_KEY_FAILURE 0x70200000
-#define FW_MSG_CODE_GET_KEY_DONE 0x80100000
-#define FW_MSG_CODE_NO_KEY 0x80f00000
-#define FW_MSG_CODE_LIC_INFO_NOT_READY 0x80f80000
-#define FW_MSG_CODE_L2B_PRAM_LOADED 0x90100000
-#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE 0x90210000
-#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x90220000
-#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x90230000
-#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x90240000
-#define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS 0xa0100000
-#define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000
-#define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000
-
-#define FW_MSG_CODE_LIC_CHALLENGE 0xff010000
-#define FW_MSG_CODE_LIC_RESPONSE 0xff020000
-#define FW_MSG_CODE_VIRT_MAC_PRIM 0xff030000
-#define FW_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
-
-#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff
+ #define FW_MSG_CODE_MASK 0xffff0000
+ #define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000
+ #define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000
+ #define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000
+ /* Load common chip is supported from bc 6.0.0 */
+ #define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP 0x00060000
+ #define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP 0x10130000
+
+ #define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000
+ #define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000
+ #define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000
+ #define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000
+ #define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000
+ #define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000
+ #define FW_MSG_CODE_DCC_DONE 0x30100000
+ #define FW_MSG_CODE_LLDP_DONE 0x40100000
+ #define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000
+ #define FW_MSG_CODE_DIAG_REFUSE 0x50200000
+ #define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000
+ #define FW_MSG_CODE_VALIDATE_KEY_SUCCESS 0x70100000
+ #define FW_MSG_CODE_VALIDATE_KEY_FAILURE 0x70200000
+ #define FW_MSG_CODE_GET_KEY_DONE 0x80100000
+ #define FW_MSG_CODE_NO_KEY 0x80f00000
+ #define FW_MSG_CODE_LIC_INFO_NOT_READY 0x80f80000
+ #define FW_MSG_CODE_L2B_PRAM_LOADED 0x90100000
+ #define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE 0x90210000
+ #define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x90220000
+ #define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x90230000
+ #define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x90240000
+ #define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS 0xa0100000
+ #define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000
+ #define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000
+ #define FW_MSG_CODE_VF_DISABLED_DONE 0xb0000000
+
+ #define FW_MSG_CODE_SET_MF_BW_SENT 0xe0000000
+ #define FW_MSG_CODE_SET_MF_BW_DONE 0xe1000000
+
+ #define FW_MSG_CODE_LINK_CHANGED_ACK 0x01100000
+
+ #define FW_MSG_CODE_LIC_CHALLENGE 0xff010000
+ #define FW_MSG_CODE_LIC_RESPONSE 0xff020000
+ #define FW_MSG_CODE_VIRT_MAC_PRIM 0xff030000
+ #define FW_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
+
+ #define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 fw_mb_param;
u32 drv_pulse_mb;
-#define DRV_PULSE_SEQ_MASK 0x00007fff
-#define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000
- /* The system time is in the format of
- * (year-2001)*12*32 + month*32 + day. */
-#define DRV_PULSE_ALWAYS_ALIVE 0x00008000
- /* Indicate to the firmware not to go into the
+ #define DRV_PULSE_SEQ_MASK 0x00007fff
+ #define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000
+ /*
+ * The system time is in the format of
+ * (year-2001)*12*32 + month*32 + day.
+ */
+ #define DRV_PULSE_ALWAYS_ALIVE 0x00008000
+ /*
+ * Indicate to the firmware not to go into the
* OS-absent when it is not getting driver pulse.
- * This is used for debugging as well for PXE(MBA). */
+ * This is used for debugging as well for PXE(MBA).
+ */
u32 mcp_pulse_mb;
-#define MCP_PULSE_SEQ_MASK 0x00007fff
-#define MCP_PULSE_ALWAYS_ALIVE 0x00008000
+ #define MCP_PULSE_SEQ_MASK 0x00007fff
+ #define MCP_PULSE_ALWAYS_ALIVE 0x00008000
/* Indicates to the driver not to assert due to lack
* of MCP response */
-#define MCP_EVENT_MASK 0xffff0000
-#define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000
+ #define MCP_EVENT_MASK 0xffff0000
+ #define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000
u32 iscsi_boot_signature;
u32 iscsi_boot_block_offset;
u32 drv_status;
-#define DRV_STATUS_PMF 0x00000001
-#define DRV_STATUS_SET_MF_BW 0x00000004
-
-#define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00
-#define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100
-#define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION 0x00000200
-#define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS 0x00000400
-#define DRV_STATUS_DCC_RESERVED1 0x00000800
-#define DRV_STATUS_DCC_SET_PROTOCOL 0x00001000
-#define DRV_STATUS_DCC_SET_PRIORITY 0x00002000
-#define DRV_STATUS_DCBX_EVENT_MASK 0x000f0000
-#define DRV_STATUS_DCBX_NEGOTIATION_RESULTS 0x00010000
+ #define DRV_STATUS_PMF 0x00000001
+ #define DRV_STATUS_VF_DISABLED 0x00000002
+ #define DRV_STATUS_SET_MF_BW 0x00000004
+ #define DRV_STATUS_LINK_EVENT 0x00000008
+
+ #define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00
+ #define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100
+ #define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION 0x00000200
+ #define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS 0x00000400
+ #define DRV_STATUS_DCC_RESERVED1 0x00000800
+ #define DRV_STATUS_DCC_SET_PROTOCOL 0x00001000
+ #define DRV_STATUS_DCC_SET_PRIORITY 0x00002000
+
+ #define DRV_STATUS_DCBX_EVENT_MASK 0x000f0000
+ #define DRV_STATUS_DCBX_NEGOTIATION_RESULTS 0x00010000
u32 virt_mac_upper;
-#define VIRT_MAC_SIGN_MASK 0xffff0000
-#define VIRT_MAC_SIGNATURE 0x564d0000
+ #define VIRT_MAC_SIGN_MASK 0xffff0000
+ #define VIRT_MAC_SIGNATURE 0x564d0000
u32 virt_mac_lower;
};
/****************************************************************************
- * Management firmware state *
+ * Management firmware state *
****************************************************************************/
/* Allocate 440 bytes for management firmware */
-#define MGMTFW_STATE_WORD_SIZE 110
+#define MGMTFW_STATE_WORD_SIZE 110
struct mgmtfw_state {
u32 opaque[MGMTFW_STATE_WORD_SIZE];
@@ -1026,25 +1377,25 @@ struct mgmtfw_state {
/****************************************************************************
- * Multi-Function configuration *
+ * Multi-Function configuration *
****************************************************************************/
struct shared_mf_cfg {
u32 clp_mb;
-#define SHARED_MF_CLP_SET_DEFAULT 0x00000000
+ #define SHARED_MF_CLP_SET_DEFAULT 0x00000000
/* set by CLP */
-#define SHARED_MF_CLP_EXIT 0x00000001
+ #define SHARED_MF_CLP_EXIT 0x00000001
/* set by MCP */
-#define SHARED_MF_CLP_EXIT_DONE 0x00010000
+ #define SHARED_MF_CLP_EXIT_DONE 0x00010000
};
struct port_mf_cfg {
- u32 dynamic_cfg; /* device control channel */
-#define PORT_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
-#define PORT_MF_CFG_E1HOV_TAG_SHIFT 0
-#define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK
+ u32 dynamic_cfg; /* device control channel */
+ #define PORT_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
+ #define PORT_MF_CFG_E1HOV_TAG_SHIFT 0
+ #define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK
u32 reserved[3];
@@ -1055,57 +1406,58 @@ struct func_mf_cfg {
u32 config;
/* E/R/I/D */
/* function 0 of each port cannot be hidden */
-#define FUNC_MF_CFG_FUNC_HIDE 0x00000001
+ #define FUNC_MF_CFG_FUNC_HIDE 0x00000001
-#define FUNC_MF_CFG_PROTOCOL_MASK 0x00000007
-#define FUNC_MF_CFG_PROTOCOL_ETHERNET 0x00000002
-#define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA 0x00000004
-#define FUNC_MF_CFG_PROTOCOL_ISCSI 0x00000006
-#define FUNC_MF_CFG_PROTOCOL_DEFAULT\
- FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA
+ #define FUNC_MF_CFG_PROTOCOL_MASK 0x00000006
+ #define FUNC_MF_CFG_PROTOCOL_FCOE 0x00000000
+ #define FUNC_MF_CFG_PROTOCOL_ETHERNET 0x00000002
+ #define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA 0x00000004
+ #define FUNC_MF_CFG_PROTOCOL_ISCSI 0x00000006
+ #define FUNC_MF_CFG_PROTOCOL_DEFAULT \
+ FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA
-#define FUNC_MF_CFG_FUNC_DISABLED 0x00000008
+ #define FUNC_MF_CFG_FUNC_DISABLED 0x00000008
+ #define FUNC_MF_CFG_FUNC_DELETED 0x00000010
/* PRI */
/* 0 - low priority, 3 - high priority */
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK 0x00000300
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT 8
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT 0x00000000
+ #define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK 0x00000300
+ #define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT 8
+ #define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT 0x00000000
/* MINBW, MAXBW */
/* value range - 0..100, increments in 100Mbps */
-#define FUNC_MF_CFG_MIN_BW_MASK 0x00ff0000
-#define FUNC_MF_CFG_MIN_BW_SHIFT 16
-#define FUNC_MF_CFG_MIN_BW_DEFAULT 0x00000000
-#define FUNC_MF_CFG_MAX_BW_MASK 0xff000000
-#define FUNC_MF_CFG_MAX_BW_SHIFT 24
-#define FUNC_MF_CFG_MAX_BW_DEFAULT 0x64000000
-
- u32 mac_upper; /* MAC */
-#define FUNC_MF_CFG_UPPERMAC_MASK 0x0000ffff
-#define FUNC_MF_CFG_UPPERMAC_SHIFT 0
-#define FUNC_MF_CFG_UPPERMAC_DEFAULT FUNC_MF_CFG_UPPERMAC_MASK
+ #define FUNC_MF_CFG_MIN_BW_MASK 0x00ff0000
+ #define FUNC_MF_CFG_MIN_BW_SHIFT 16
+ #define FUNC_MF_CFG_MIN_BW_DEFAULT 0x00000000
+ #define FUNC_MF_CFG_MAX_BW_MASK 0xff000000
+ #define FUNC_MF_CFG_MAX_BW_SHIFT 24
+ #define FUNC_MF_CFG_MAX_BW_DEFAULT 0x64000000
+
+ u32 mac_upper; /* MAC */
+ #define FUNC_MF_CFG_UPPERMAC_MASK 0x0000ffff
+ #define FUNC_MF_CFG_UPPERMAC_SHIFT 0
+ #define FUNC_MF_CFG_UPPERMAC_DEFAULT FUNC_MF_CFG_UPPERMAC_MASK
u32 mac_lower;
-#define FUNC_MF_CFG_LOWERMAC_DEFAULT 0xffffffff
+ #define FUNC_MF_CFG_LOWERMAC_DEFAULT 0xffffffff
u32 e1hov_tag; /* VNI */
-#define FUNC_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
-#define FUNC_MF_CFG_E1HOV_TAG_SHIFT 0
-#define FUNC_MF_CFG_E1HOV_TAG_DEFAULT FUNC_MF_CFG_E1HOV_TAG_MASK
+ #define FUNC_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
+ #define FUNC_MF_CFG_E1HOV_TAG_SHIFT 0
+ #define FUNC_MF_CFG_E1HOV_TAG_DEFAULT FUNC_MF_CFG_E1HOV_TAG_MASK
u32 reserved[2];
-
};
/* This structure is not applicable and should not be accessed on 57711 */
struct func_ext_cfg {
u32 func_cfg;
-#define MACP_FUNC_CFG_FLAGS_MASK 0x000000FF
-#define MACP_FUNC_CFG_FLAGS_SHIFT 0
-#define MACP_FUNC_CFG_FLAGS_ENABLED 0x00000001
-#define MACP_FUNC_CFG_FLAGS_ETHERNET 0x00000002
-#define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD 0x00000004
-#define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD 0x00000008
+ #define MACP_FUNC_CFG_FLAGS_MASK 0x000000FF
+ #define MACP_FUNC_CFG_FLAGS_SHIFT 0
+ #define MACP_FUNC_CFG_FLAGS_ENABLED 0x00000001
+ #define MACP_FUNC_CFG_FLAGS_ETHERNET 0x00000002
+ #define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD 0x00000004
+ #define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD 0x00000008
u32 iscsi_mac_addr_upper;
u32 iscsi_mac_addr_lower;
@@ -1120,73 +1472,99 @@ struct func_ext_cfg {
u32 fcoe_wwn_node_name_lower;
u32 preserve_data;
-#define MF_FUNC_CFG_PRESERVE_L2_MAC (1<<0)
-#define MF_FUNC_CFG_PRESERVE_ISCSI_MAC (1<<1)
-#define MF_FUNC_CFG_PRESERVE_FCOE_MAC (1<<2)
-#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P (1<<3)
-#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N (1<<4)
+ #define MF_FUNC_CFG_PRESERVE_L2_MAC (1<<0)
+ #define MF_FUNC_CFG_PRESERVE_ISCSI_MAC (1<<1)
+ #define MF_FUNC_CFG_PRESERVE_FCOE_MAC (1<<2)
+ #define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P (1<<3)
+ #define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N (1<<4)
+ #define MF_FUNC_CFG_PRESERVE_TX_BW (1<<5)
};
struct mf_cfg {
- struct shared_mf_cfg shared_mf_config;
- struct port_mf_cfg port_mf_config[PORT_MAX];
- struct func_mf_cfg func_mf_config[E1H_FUNC_MAX];
-
- struct func_ext_cfg func_ext_config[E1H_FUNC_MAX];
-};
-
+ struct shared_mf_cfg shared_mf_config; /* 0x4 */
+ struct port_mf_cfg port_mf_config[PORT_MAX]; /* 0x10 * 2 = 0x20 */
+ /* for all chips, there are 8 mf functions */
+ struct func_mf_cfg func_mf_config[E1H_FUNC_MAX]; /* 0x18 * 8 = 0xc0 */
+ /*
+ * Extended configuration per function - this array does not exist and
+ * should not be accessed on 57711
+ */
+ struct func_ext_cfg func_ext_config[E1H_FUNC_MAX]; /* 0x28 * 8 = 0x140*/
+}; /* 0x224 */
/****************************************************************************
- * Shared Memory Region *
+ * Shared Memory Region *
****************************************************************************/
-struct shmem_region { /* SharedMem Offset (size) */
+struct shmem_region { /* SharedMem Offset (size) */
- u32 validity_map[PORT_MAX]; /* 0x0 (4*2 = 0x8) */
-#define SHR_MEM_FORMAT_REV_ID ('A'<<24)
-#define SHR_MEM_FORMAT_REV_MASK 0xff000000
+ u32 validity_map[PORT_MAX]; /* 0x0 (4*2 = 0x8) */
+ #define SHR_MEM_FORMAT_REV_MASK 0xff000000
+ #define SHR_MEM_FORMAT_REV_ID ('A'<<24)
/* validity bits */
-#define SHR_MEM_VALIDITY_PCI_CFG 0x00100000
-#define SHR_MEM_VALIDITY_MB 0x00200000
-#define SHR_MEM_VALIDITY_DEV_INFO 0x00400000
-#define SHR_MEM_VALIDITY_RESERVED 0x00000007
+ #define SHR_MEM_VALIDITY_PCI_CFG 0x00100000
+ #define SHR_MEM_VALIDITY_MB 0x00200000
+ #define SHR_MEM_VALIDITY_DEV_INFO 0x00400000
+ #define SHR_MEM_VALIDITY_RESERVED 0x00000007
/* One licensing bit should be set */
-#define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038
-#define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008
-#define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010
-#define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020
+ #define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038
+ #define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008
+ #define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010
+ #define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020
/* Active MFW */
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI 0x00000040
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 0x00000080
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI 0x000000c0
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE 0x000001c0
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK 0x000001c0
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK 0x000001c0
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI 0x00000040
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 0x00000080
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI 0x000000c0
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE 0x000001c0
- struct shm_dev_info dev_info; /* 0x8 (0x438) */
+ struct shm_dev_info dev_info; /* 0x8 (0x438) */
- struct license_key drv_lic_key[PORT_MAX]; /* 0x440 (52*2=0x68) */
+ struct license_key drv_lic_key[PORT_MAX]; /* 0x440 (52*2=0x68) */
/* FW information (for internal FW use) */
- u32 fw_info_fio_offset; /* 0x4a8 (0x4) */
- struct mgmtfw_state mgmtfw_state; /* 0x4ac (0x1b8) */
+ u32 fw_info_fio_offset; /* 0x4a8 (0x4) */
+ struct mgmtfw_state mgmtfw_state; /* 0x4ac (0x1b8) */
+
+ struct drv_port_mb port_mb[PORT_MAX]; /* 0x664 (16*2=0x20) */
- struct drv_port_mb port_mb[PORT_MAX]; /* 0x664 (16*2=0x20) */
- struct drv_func_mb func_mb[]; /* 0x684
- (44*2/4/8=0x58/0xb0/0x160) */
+#ifdef BMAPI
+ /* This is a variable length array */
+ /* the number of function depends on the chip type */
+ struct drv_func_mb func_mb[1]; /* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
+#else
+ /* the number of function depends on the chip type */
+ struct drv_func_mb func_mb[]; /* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
+#endif /* BMAPI */
}; /* 57710 = 0x6dc | 57711 = 0x7E4 | 57712 = 0x734 */
+/****************************************************************************
+ * Shared Memory 2 Region *
+ ****************************************************************************/
+/* The fw_flr_ack is actually built in the following way: */
+/* 8 bit: PF ack */
+/* 64 bit: VF ack */
+/* 8 bit: ios_dis_ack */
+/* In order to maintain endianity in the mailbox hsi, we want to keep using */
+/* u32. The fw must have the VF right after the PF since this is how it */
+/* access arrays(it expects always the VF to reside after the PF, and that */
+/* makes the calculation much easier for it. ) */
+/* In order to answer both limitations, and keep the struct small, the code */
+/* will abuse the structure defined here to achieve the actual partition */
+/* above */
+/****************************************************************************/
struct fw_flr_ack {
- u32 pf_ack;
- u32 vf_ack[1];
- u32 iov_dis_ack;
+ u32 pf_ack;
+ u32 vf_ack[1];
+ u32 iov_dis_ack;
};
struct fw_flr_mb {
- u32 aggint;
- u32 opgen_addr;
- struct fw_flr_ack ack;
+ u32 aggint;
+ u32 opgen_addr;
+ struct fw_flr_ack ack;
};
/**** SUPPORT FOR SHMEM ARRRAYS ***
@@ -1210,36 +1588,36 @@ struct fw_flr_mb {
*
* SHMEM_ARRAY_BITPOS(i, 4, 4) defines the stadard ordering:
*
- * | | | |
- * 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
- * | | | |
+ * | | | |
+ * 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+ * | | | |
*
* SHMEM_ARRAY_BITPOS(i, 4, 8) defines a flip ordering per byte:
*
- * | | | |
- * 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 |
- * | | | |
+ * | | | |
+ * 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 |
+ * | | | |
*
* SHMEM_ARRAY_BITPOS(i, 4, 16) defines a flip ordering per word:
*
- * | | | |
- * 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 |
- * | | | |
+ * | | | |
+ * 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 |
+ * | | | |
*/
#define SHMEM_ARRAY_BITPOS(i, eb, fb) \
((((32/(fb)) - 1 - ((i)/((fb)/(eb))) % (32/(fb))) * (fb)) + \
(((i)%((fb)/(eb))) * (eb)))
-#define SHMEM_ARRAY_GET(a, i, eb, fb) \
+#define SHMEM_ARRAY_GET(a, i, eb, fb) \
((a[SHMEM_ARRAY_ENTRY(i, eb)] >> SHMEM_ARRAY_BITPOS(i, eb, fb)) & \
SHMEM_ARRAY_MASK(eb))
-#define SHMEM_ARRAY_SET(a, i, eb, fb, val) \
+#define SHMEM_ARRAY_SET(a, i, eb, fb, val) \
do { \
a[SHMEM_ARRAY_ENTRY(i, eb)] &= ~(SHMEM_ARRAY_MASK(eb) << \
- SHMEM_ARRAY_BITPOS(i, eb, fb)); \
+ SHMEM_ARRAY_BITPOS(i, eb, fb)); \
a[SHMEM_ARRAY_ENTRY(i, eb)] |= (((val) & SHMEM_ARRAY_MASK(eb)) << \
- SHMEM_ARRAY_BITPOS(i, eb, fb)); \
+ SHMEM_ARRAY_BITPOS(i, eb, fb)); \
} while (0)
@@ -1263,23 +1641,30 @@ do { \
#define ISCSI_APP_IDX 1
#define PREDEFINED_APP_IDX_MAX 2
+
+/* Big/Little endian have the same representation. */
struct dcbx_ets_feature {
+ /*
+ * For Admin MIB - is this feature supported by the
+ * driver | For Local MIB - should this feature be enabled.
+ */
u32 enabled;
u32 pg_bw_tbl[2];
u32 pri_pg_tbl[1];
};
+/* Driver structure in LE */
struct dcbx_pfc_feature {
#ifdef __BIG_ENDIAN
u8 pri_en_bitmap;
-#define DCBX_PFC_PRI_0 0x01
-#define DCBX_PFC_PRI_1 0x02
-#define DCBX_PFC_PRI_2 0x04
-#define DCBX_PFC_PRI_3 0x08
-#define DCBX_PFC_PRI_4 0x10
-#define DCBX_PFC_PRI_5 0x20
-#define DCBX_PFC_PRI_6 0x40
-#define DCBX_PFC_PRI_7 0x80
+ #define DCBX_PFC_PRI_0 0x01
+ #define DCBX_PFC_PRI_1 0x02
+ #define DCBX_PFC_PRI_2 0x04
+ #define DCBX_PFC_PRI_3 0x08
+ #define DCBX_PFC_PRI_4 0x10
+ #define DCBX_PFC_PRI_5 0x20
+ #define DCBX_PFC_PRI_6 0x40
+ #define DCBX_PFC_PRI_7 0x80
u8 pfc_caps;
u8 reserved;
u8 enabled;
@@ -1288,39 +1673,41 @@ struct dcbx_pfc_feature {
u8 reserved;
u8 pfc_caps;
u8 pri_en_bitmap;
-#define DCBX_PFC_PRI_0 0x01
-#define DCBX_PFC_PRI_1 0x02
-#define DCBX_PFC_PRI_2 0x04
-#define DCBX_PFC_PRI_3 0x08
-#define DCBX_PFC_PRI_4 0x10
-#define DCBX_PFC_PRI_5 0x20
-#define DCBX_PFC_PRI_6 0x40
-#define DCBX_PFC_PRI_7 0x80
+ #define DCBX_PFC_PRI_0 0x01
+ #define DCBX_PFC_PRI_1 0x02
+ #define DCBX_PFC_PRI_2 0x04
+ #define DCBX_PFC_PRI_3 0x08
+ #define DCBX_PFC_PRI_4 0x10
+ #define DCBX_PFC_PRI_5 0x20
+ #define DCBX_PFC_PRI_6 0x40
+ #define DCBX_PFC_PRI_7 0x80
#endif
};
struct dcbx_app_priority_entry {
#ifdef __BIG_ENDIAN
- u16 app_id;
- u8 pri_bitmap;
- u8 appBitfield;
-#define DCBX_APP_ENTRY_VALID 0x01
-#define DCBX_APP_ENTRY_SF_MASK 0x30
-#define DCBX_APP_ENTRY_SF_SHIFT 4
-#define DCBX_APP_SF_ETH_TYPE 0x10
-#define DCBX_APP_SF_PORT 0x20
+ u16 app_id;
+ u8 pri_bitmap;
+ u8 appBitfield;
+ #define DCBX_APP_ENTRY_VALID 0x01
+ #define DCBX_APP_ENTRY_SF_MASK 0x30
+ #define DCBX_APP_ENTRY_SF_SHIFT 4
+ #define DCBX_APP_SF_ETH_TYPE 0x10
+ #define DCBX_APP_SF_PORT 0x20
#elif defined(__LITTLE_ENDIAN)
u8 appBitfield;
-#define DCBX_APP_ENTRY_VALID 0x01
-#define DCBX_APP_ENTRY_SF_MASK 0x30
-#define DCBX_APP_ENTRY_SF_SHIFT 4
-#define DCBX_APP_SF_ETH_TYPE 0x10
-#define DCBX_APP_SF_PORT 0x20
- u8 pri_bitmap;
- u16 app_id;
+ #define DCBX_APP_ENTRY_VALID 0x01
+ #define DCBX_APP_ENTRY_SF_MASK 0x30
+ #define DCBX_APP_ENTRY_SF_SHIFT 4
+ #define DCBX_APP_SF_ETH_TYPE 0x10
+ #define DCBX_APP_SF_PORT 0x20
+ u8 pri_bitmap;
+ u16 app_id;
#endif
};
+
+/* FW structure in BE */
struct dcbx_app_priority_feature {
#ifdef __BIG_ENDIAN
u8 reserved;
@@ -1336,302 +1723,403 @@ struct dcbx_app_priority_feature {
struct dcbx_app_priority_entry app_pri_tbl[DCBX_MAX_APP_PROTOCOL];
};
+/* FW structure in BE */
struct dcbx_features {
+ /* PG feature */
struct dcbx_ets_feature ets;
+ /* PFC feature */
struct dcbx_pfc_feature pfc;
+ /* APP feature */
struct dcbx_app_priority_feature app;
};
+/* LLDP protocol parameters */
+/* FW structure in BE */
struct lldp_params {
#ifdef __BIG_ENDIAN
- u8 msg_fast_tx_interval;
- u8 msg_tx_hold;
- u8 msg_tx_interval;
- u8 admin_status;
-#define LLDP_TX_ONLY 0x01
-#define LLDP_RX_ONLY 0x02
-#define LLDP_TX_RX 0x03
-#define LLDP_DISABLED 0x04
- u8 reserved1;
- u8 tx_fast;
- u8 tx_crd_max;
- u8 tx_crd;
+ u8 msg_fast_tx_interval;
+ u8 msg_tx_hold;
+ u8 msg_tx_interval;
+ u8 admin_status;
+ #define LLDP_TX_ONLY 0x01
+ #define LLDP_RX_ONLY 0x02
+ #define LLDP_TX_RX 0x03
+ #define LLDP_DISABLED 0x04
+ u8 reserved1;
+ u8 tx_fast;
+ u8 tx_crd_max;
+ u8 tx_crd;
#elif defined(__LITTLE_ENDIAN)
- u8 admin_status;
-#define LLDP_TX_ONLY 0x01
-#define LLDP_RX_ONLY 0x02
-#define LLDP_TX_RX 0x03
-#define LLDP_DISABLED 0x04
- u8 msg_tx_interval;
- u8 msg_tx_hold;
- u8 msg_fast_tx_interval;
- u8 tx_crd;
- u8 tx_crd_max;
- u8 tx_fast;
- u8 reserved1;
+ u8 admin_status;
+ #define LLDP_TX_ONLY 0x01
+ #define LLDP_RX_ONLY 0x02
+ #define LLDP_TX_RX 0x03
+ #define LLDP_DISABLED 0x04
+ u8 msg_tx_interval;
+ u8 msg_tx_hold;
+ u8 msg_fast_tx_interval;
+ u8 tx_crd;
+ u8 tx_crd_max;
+ u8 tx_fast;
+ u8 reserved1;
#endif
-#define REM_CHASSIS_ID_STAT_LEN 4
-#define REM_PORT_ID_STAT_LEN 4
+ #define REM_CHASSIS_ID_STAT_LEN 4
+ #define REM_PORT_ID_STAT_LEN 4
+ /* Holds remote Chassis ID TLV header, subtype and 9B of payload. */
u32 peer_chassis_id[REM_CHASSIS_ID_STAT_LEN];
+ /* Holds remote Port ID TLV header, subtype and 9B of payload. */
u32 peer_port_id[REM_PORT_ID_STAT_LEN];
};
struct lldp_dcbx_stat {
-#define LOCAL_CHASSIS_ID_STAT_LEN 2
-#define LOCAL_PORT_ID_STAT_LEN 2
+ #define LOCAL_CHASSIS_ID_STAT_LEN 2
+ #define LOCAL_PORT_ID_STAT_LEN 2
+ /* Holds local Chassis ID 8B payload of constant subtype 4. */
u32 local_chassis_id[LOCAL_CHASSIS_ID_STAT_LEN];
+ /* Holds local Port ID 8B payload of constant subtype 3. */
u32 local_port_id[LOCAL_PORT_ID_STAT_LEN];
+ /* Number of DCBX frames transmitted. */
u32 num_tx_dcbx_pkts;
+ /* Number of DCBX frames received. */
u32 num_rx_dcbx_pkts;
};
+/* ADMIN MIB - DCBX local machine default configuration. */
struct lldp_admin_mib {
- u32 ver_cfg_flags;
-#define DCBX_ETS_CONFIG_TX_ENABLED 0x00000001
-#define DCBX_PFC_CONFIG_TX_ENABLED 0x00000002
-#define DCBX_APP_CONFIG_TX_ENABLED 0x00000004
-#define DCBX_ETS_RECO_TX_ENABLED 0x00000008
-#define DCBX_ETS_RECO_VALID 0x00000010
-#define DCBX_ETS_WILLING 0x00000020
-#define DCBX_PFC_WILLING 0x00000040
-#define DCBX_APP_WILLING 0x00000080
-#define DCBX_VERSION_CEE 0x00000100
-#define DCBX_VERSION_IEEE 0x00000200
-#define DCBX_DCBX_ENABLED 0x00000400
-#define DCBX_CEE_VERSION_MASK 0x0000f000
-#define DCBX_CEE_VERSION_SHIFT 12
-#define DCBX_CEE_MAX_VERSION_MASK 0x000f0000
-#define DCBX_CEE_MAX_VERSION_SHIFT 16
- struct dcbx_features features;
-};
-
+ u32 ver_cfg_flags;
+ #define DCBX_ETS_CONFIG_TX_ENABLED 0x00000001
+ #define DCBX_PFC_CONFIG_TX_ENABLED 0x00000002
+ #define DCBX_APP_CONFIG_TX_ENABLED 0x00000004
+ #define DCBX_ETS_RECO_TX_ENABLED 0x00000008
+ #define DCBX_ETS_RECO_VALID 0x00000010
+ #define DCBX_ETS_WILLING 0x00000020
+ #define DCBX_PFC_WILLING 0x00000040
+ #define DCBX_APP_WILLING 0x00000080
+ #define DCBX_VERSION_CEE 0x00000100
+ #define DCBX_VERSION_IEEE 0x00000200
+ #define DCBX_DCBX_ENABLED 0x00000400
+ #define DCBX_CEE_VERSION_MASK 0x0000f000
+ #define DCBX_CEE_VERSION_SHIFT 12
+ #define DCBX_CEE_MAX_VERSION_MASK 0x000f0000
+ #define DCBX_CEE_MAX_VERSION_SHIFT 16
+ struct dcbx_features features;
+};
+
+/* REMOTE MIB - remote machine DCBX configuration. */
struct lldp_remote_mib {
u32 prefix_seq_num;
u32 flags;
-#define DCBX_ETS_TLV_RX 0x00000001
-#define DCBX_PFC_TLV_RX 0x00000002
-#define DCBX_APP_TLV_RX 0x00000004
-#define DCBX_ETS_RX_ERROR 0x00000010
-#define DCBX_PFC_RX_ERROR 0x00000020
-#define DCBX_APP_RX_ERROR 0x00000040
-#define DCBX_ETS_REM_WILLING 0x00000100
-#define DCBX_PFC_REM_WILLING 0x00000200
-#define DCBX_APP_REM_WILLING 0x00000400
-#define DCBX_REMOTE_ETS_RECO_VALID 0x00001000
+ #define DCBX_ETS_TLV_RX 0x00000001
+ #define DCBX_PFC_TLV_RX 0x00000002
+ #define DCBX_APP_TLV_RX 0x00000004
+ #define DCBX_ETS_RX_ERROR 0x00000010
+ #define DCBX_PFC_RX_ERROR 0x00000020
+ #define DCBX_APP_RX_ERROR 0x00000040
+ #define DCBX_ETS_REM_WILLING 0x00000100
+ #define DCBX_PFC_REM_WILLING 0x00000200
+ #define DCBX_APP_REM_WILLING 0x00000400
+ #define DCBX_REMOTE_ETS_RECO_VALID 0x00001000
+ #define DCBX_REMOTE_MIB_VALID 0x00002000
struct dcbx_features features;
u32 suffix_seq_num;
};
+/* LOCAL MIB - operational DCBX configuration - transmitted on Tx LLDPDU. */
struct lldp_local_mib {
u32 prefix_seq_num;
+ /* Indicates if there is mismatch with negotiation results. */
u32 error;
-#define DCBX_LOCAL_ETS_ERROR 0x00000001
-#define DCBX_LOCAL_PFC_ERROR 0x00000002
-#define DCBX_LOCAL_APP_ERROR 0x00000004
-#define DCBX_LOCAL_PFC_MISMATCH 0x00000010
-#define DCBX_LOCAL_APP_MISMATCH 0x00000020
+ #define DCBX_LOCAL_ETS_ERROR 0x00000001
+ #define DCBX_LOCAL_PFC_ERROR 0x00000002
+ #define DCBX_LOCAL_APP_ERROR 0x00000004
+ #define DCBX_LOCAL_PFC_MISMATCH 0x00000010
+ #define DCBX_LOCAL_APP_MISMATCH 0x00000020
+ #define DCBX_REMOTE_MIB_ERROR 0x00000040
struct dcbx_features features;
u32 suffix_seq_num;
};
/***END OF DCBX STRUCTURES DECLARATIONS***/
+struct ncsi_oem_fcoe_features {
+ u32 fcoe_features1;
+ #define FCOE_FEATURES1_IOS_PER_CONNECTION_MASK 0x0000FFFF
+ #define FCOE_FEATURES1_IOS_PER_CONNECTION_OFFSET 0
+
+ #define FCOE_FEATURES1_LOGINS_PER_PORT_MASK 0xFFFF0000
+ #define FCOE_FEATURES1_LOGINS_PER_PORT_OFFSET 16
+
+ u32 fcoe_features2;
+ #define FCOE_FEATURES2_EXCHANGES_MASK 0x0000FFFF
+ #define FCOE_FEATURES2_EXCHANGES_OFFSET 0
+
+ #define FCOE_FEATURES2_NPIV_WWN_PER_PORT_MASK 0xFFFF0000
+ #define FCOE_FEATURES2_NPIV_WWN_PER_PORT_OFFSET 16
+
+ u32 fcoe_features3;
+ #define FCOE_FEATURES3_TARGETS_SUPPORTED_MASK 0x0000FFFF
+ #define FCOE_FEATURES3_TARGETS_SUPPORTED_OFFSET 0
+
+ #define FCOE_FEATURES3_OUTSTANDING_COMMANDS_MASK 0xFFFF0000
+ #define FCOE_FEATURES3_OUTSTANDING_COMMANDS_OFFSET 16
+
+ u32 fcoe_features4;
+ #define FCOE_FEATURES4_FEATURE_SETTINGS_MASK 0x0000000F
+ #define FCOE_FEATURES4_FEATURE_SETTINGS_OFFSET 0
+};
+
+struct ncsi_oem_data {
+ u32 driver_version[4];
+ struct ncsi_oem_fcoe_features ncsi_oem_fcoe_features;
+};
+
struct shmem2_region {
- u32 size;
-
- u32 dcc_support;
-#define SHMEM_DCC_SUPPORT_NONE 0x00000000
-#define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV 0x00000001
-#define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV 0x00000004
-#define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV 0x00000008
-#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040
-#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080
-#define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE
- u32 ext_phy_fw_version2[PORT_MAX];
+ u32 size; /* 0x0000 */
+
+ u32 dcc_support; /* 0x0004 */
+ #define SHMEM_DCC_SUPPORT_NONE 0x00000000
+ #define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV 0x00000001
+ #define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV 0x00000004
+ #define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV 0x00000008
+ #define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040
+ #define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080
+
+ u32 ext_phy_fw_version2[PORT_MAX]; /* 0x0008 */
/*
* For backwards compatibility, if the mf_cfg_addr does not exist
* (the size filed is smaller than 0xc) the mf_cfg resides at the
* end of struct shmem_region
- */
- u32 mf_cfg_addr;
-#define SHMEM_MF_CFG_ADDR_NONE 0x00000000
-
- struct fw_flr_mb flr_mb;
- u32 dcbx_lldp_params_offset;
-#define SHMEM_LLDP_DCBX_PARAMS_NONE 0x00000000
- u32 dcbx_neg_res_offset;
-#define SHMEM_DCBX_NEG_RES_NONE 0x00000000
- u32 dcbx_remote_mib_offset;
-#define SHMEM_DCBX_REMOTE_MIB_NONE 0x00000000
+ */
+ u32 mf_cfg_addr; /* 0x0010 */
+ #define SHMEM_MF_CFG_ADDR_NONE 0x00000000
+
+ struct fw_flr_mb flr_mb; /* 0x0014 */
+ u32 dcbx_lldp_params_offset; /* 0x0028 */
+ #define SHMEM_LLDP_DCBX_PARAMS_NONE 0x00000000
+ u32 dcbx_neg_res_offset; /* 0x002c */
+ #define SHMEM_DCBX_NEG_RES_NONE 0x00000000
+ u32 dcbx_remote_mib_offset; /* 0x0030 */
+ #define SHMEM_DCBX_REMOTE_MIB_NONE 0x00000000
/*
* The other shmemX_base_addr holds the other path's shmem address
* required for example in case of common phy init, or for path1 to know
* the address of mcp debug trace which is located in offset from shmem
* of path0
*/
- u32 other_shmem_base_addr;
- u32 other_shmem2_base_addr;
- u32 reserved1[E2_VF_MAX / 32];
- u32 reserved2[E2_FUNC_MAX][E2_VF_MAX / 32];
- u32 dcbx_lldp_dcbx_stat_offset;
-#define SHMEM_LLDP_DCBX_STAT_NONE 0x00000000
+ u32 other_shmem_base_addr; /* 0x0034 */
+ u32 other_shmem2_base_addr; /* 0x0038 */
+ /*
+ * mcp_vf_disabled is set by the MCP to indicate the driver about VFs
+ * which were disabled/flred
+ */
+ u32 mcp_vf_disabled[E2_VF_MAX / 32]; /* 0x003c */
+
+ /*
+ * drv_ack_vf_disabled is set by the PF driver to ack handled disabled
+ * VFs
+ */
+ u32 drv_ack_vf_disabled[E2_FUNC_MAX][E2_VF_MAX / 32]; /* 0x0044 */
+
+ u32 dcbx_lldp_dcbx_stat_offset; /* 0x0064 */
+ #define SHMEM_LLDP_DCBX_STAT_NONE 0x00000000
+
+ /*
+ * edebug_driver_if field is used to transfer messages between edebug
+ * app to the driver through shmem2.
+ *
+ * message format:
+ * bits 0-2 - function number / instance of driver to perform request
+ * bits 3-5 - op code / is_ack?
+ * bits 6-63 - data
+ */
+ u32 edebug_driver_if[2]; /* 0x0068 */
+ #define EDEBUG_DRIVER_IF_OP_CODE_GET_PHYS_ADDR 1
+ #define EDEBUG_DRIVER_IF_OP_CODE_GET_BUS_ADDR 2
+ #define EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT 3
+
+ u32 nvm_retain_bitmap_addr; /* 0x0070 */
+
+ u32 reserved1; /* 0x0074 */
+
+ u32 reserved2[E2_FUNC_MAX];
+
+ u32 reserved3[E2_FUNC_MAX];/* 0x0088 */
+ u32 reserved4[E2_FUNC_MAX];/* 0x0098 */
+
+ u32 swim_base_addr; /* 0x0108 */
+ u32 swim_funcs;
+ u32 swim_main_cb;
+
+ u32 reserved5[2];
+
+ /* generic flags controlled by the driver */
+ u32 drv_flags;
+ #define DRV_FLAGS_DCB_CONFIGURED 0x1
+
+ /* pointer to extended dev_info shared data copied from nvm image */
+ u32 extended_dev_info_shared_addr;
+ u32 ncsi_oem_data_addr;
+
+ u32 ocsd_host_addr;
+ u32 ocbb_host_addr;
+ u32 ocsd_req_update_interval;
};
struct emac_stats {
- u32 rx_stat_ifhcinoctets;
- u32 rx_stat_ifhcinbadoctets;
- u32 rx_stat_etherstatsfragments;
- u32 rx_stat_ifhcinucastpkts;
- u32 rx_stat_ifhcinmulticastpkts;
- u32 rx_stat_ifhcinbroadcastpkts;
- u32 rx_stat_dot3statsfcserrors;
- u32 rx_stat_dot3statsalignmenterrors;
- u32 rx_stat_dot3statscarriersenseerrors;
- u32 rx_stat_xonpauseframesreceived;
- u32 rx_stat_xoffpauseframesreceived;
- u32 rx_stat_maccontrolframesreceived;
- u32 rx_stat_xoffstateentered;
- u32 rx_stat_dot3statsframestoolong;
- u32 rx_stat_etherstatsjabbers;
- u32 rx_stat_etherstatsundersizepkts;
- u32 rx_stat_etherstatspkts64octets;
- u32 rx_stat_etherstatspkts65octetsto127octets;
- u32 rx_stat_etherstatspkts128octetsto255octets;
- u32 rx_stat_etherstatspkts256octetsto511octets;
- u32 rx_stat_etherstatspkts512octetsto1023octets;
- u32 rx_stat_etherstatspkts1024octetsto1522octets;
- u32 rx_stat_etherstatspktsover1522octets;
-
- u32 rx_stat_falsecarriererrors;
-
- u32 tx_stat_ifhcoutoctets;
- u32 tx_stat_ifhcoutbadoctets;
- u32 tx_stat_etherstatscollisions;
- u32 tx_stat_outxonsent;
- u32 tx_stat_outxoffsent;
- u32 tx_stat_flowcontroldone;
- u32 tx_stat_dot3statssinglecollisionframes;
- u32 tx_stat_dot3statsmultiplecollisionframes;
- u32 tx_stat_dot3statsdeferredtransmissions;
- u32 tx_stat_dot3statsexcessivecollisions;
- u32 tx_stat_dot3statslatecollisions;
- u32 tx_stat_ifhcoutucastpkts;
- u32 tx_stat_ifhcoutmulticastpkts;
- u32 tx_stat_ifhcoutbroadcastpkts;
- u32 tx_stat_etherstatspkts64octets;
- u32 tx_stat_etherstatspkts65octetsto127octets;
- u32 tx_stat_etherstatspkts128octetsto255octets;
- u32 tx_stat_etherstatspkts256octetsto511octets;
- u32 tx_stat_etherstatspkts512octetsto1023octets;
- u32 tx_stat_etherstatspkts1024octetsto1522octets;
- u32 tx_stat_etherstatspktsover1522octets;
- u32 tx_stat_dot3statsinternalmactransmiterrors;
+ u32 rx_stat_ifhcinoctets;
+ u32 rx_stat_ifhcinbadoctets;
+ u32 rx_stat_etherstatsfragments;
+ u32 rx_stat_ifhcinucastpkts;
+ u32 rx_stat_ifhcinmulticastpkts;
+ u32 rx_stat_ifhcinbroadcastpkts;
+ u32 rx_stat_dot3statsfcserrors;
+ u32 rx_stat_dot3statsalignmenterrors;
+ u32 rx_stat_dot3statscarriersenseerrors;
+ u32 rx_stat_xonpauseframesreceived;
+ u32 rx_stat_xoffpauseframesreceived;
+ u32 rx_stat_maccontrolframesreceived;
+ u32 rx_stat_xoffstateentered;
+ u32 rx_stat_dot3statsframestoolong;
+ u32 rx_stat_etherstatsjabbers;
+ u32 rx_stat_etherstatsundersizepkts;
+ u32 rx_stat_etherstatspkts64octets;
+ u32 rx_stat_etherstatspkts65octetsto127octets;
+ u32 rx_stat_etherstatspkts128octetsto255octets;
+ u32 rx_stat_etherstatspkts256octetsto511octets;
+ u32 rx_stat_etherstatspkts512octetsto1023octets;
+ u32 rx_stat_etherstatspkts1024octetsto1522octets;
+ u32 rx_stat_etherstatspktsover1522octets;
+
+ u32 rx_stat_falsecarriererrors;
+
+ u32 tx_stat_ifhcoutoctets;
+ u32 tx_stat_ifhcoutbadoctets;
+ u32 tx_stat_etherstatscollisions;
+ u32 tx_stat_outxonsent;
+ u32 tx_stat_outxoffsent;
+ u32 tx_stat_flowcontroldone;
+ u32 tx_stat_dot3statssinglecollisionframes;
+ u32 tx_stat_dot3statsmultiplecollisionframes;
+ u32 tx_stat_dot3statsdeferredtransmissions;
+ u32 tx_stat_dot3statsexcessivecollisions;
+ u32 tx_stat_dot3statslatecollisions;
+ u32 tx_stat_ifhcoutucastpkts;
+ u32 tx_stat_ifhcoutmulticastpkts;
+ u32 tx_stat_ifhcoutbroadcastpkts;
+ u32 tx_stat_etherstatspkts64octets;
+ u32 tx_stat_etherstatspkts65octetsto127octets;
+ u32 tx_stat_etherstatspkts128octetsto255octets;
+ u32 tx_stat_etherstatspkts256octetsto511octets;
+ u32 tx_stat_etherstatspkts512octetsto1023octets;
+ u32 tx_stat_etherstatspkts1024octetsto1522octets;
+ u32 tx_stat_etherstatspktsover1522octets;
+ u32 tx_stat_dot3statsinternalmactransmiterrors;
};
struct bmac1_stats {
- u32 tx_stat_gtpkt_lo;
- u32 tx_stat_gtpkt_hi;
- u32 tx_stat_gtxpf_lo;
- u32 tx_stat_gtxpf_hi;
- u32 tx_stat_gtfcs_lo;
- u32 tx_stat_gtfcs_hi;
- u32 tx_stat_gtmca_lo;
- u32 tx_stat_gtmca_hi;
- u32 tx_stat_gtbca_lo;
- u32 tx_stat_gtbca_hi;
- u32 tx_stat_gtfrg_lo;
- u32 tx_stat_gtfrg_hi;
- u32 tx_stat_gtovr_lo;
- u32 tx_stat_gtovr_hi;
- u32 tx_stat_gt64_lo;
- u32 tx_stat_gt64_hi;
- u32 tx_stat_gt127_lo;
- u32 tx_stat_gt127_hi;
- u32 tx_stat_gt255_lo;
- u32 tx_stat_gt255_hi;
- u32 tx_stat_gt511_lo;
- u32 tx_stat_gt511_hi;
- u32 tx_stat_gt1023_lo;
- u32 tx_stat_gt1023_hi;
- u32 tx_stat_gt1518_lo;
- u32 tx_stat_gt1518_hi;
- u32 tx_stat_gt2047_lo;
- u32 tx_stat_gt2047_hi;
- u32 tx_stat_gt4095_lo;
- u32 tx_stat_gt4095_hi;
- u32 tx_stat_gt9216_lo;
- u32 tx_stat_gt9216_hi;
- u32 tx_stat_gt16383_lo;
- u32 tx_stat_gt16383_hi;
- u32 tx_stat_gtmax_lo;
- u32 tx_stat_gtmax_hi;
- u32 tx_stat_gtufl_lo;
- u32 tx_stat_gtufl_hi;
- u32 tx_stat_gterr_lo;
- u32 tx_stat_gterr_hi;
- u32 tx_stat_gtbyt_lo;
- u32 tx_stat_gtbyt_hi;
-
- u32 rx_stat_gr64_lo;
- u32 rx_stat_gr64_hi;
- u32 rx_stat_gr127_lo;
- u32 rx_stat_gr127_hi;
- u32 rx_stat_gr255_lo;
- u32 rx_stat_gr255_hi;
- u32 rx_stat_gr511_lo;
- u32 rx_stat_gr511_hi;
- u32 rx_stat_gr1023_lo;
- u32 rx_stat_gr1023_hi;
- u32 rx_stat_gr1518_lo;
- u32 rx_stat_gr1518_hi;
- u32 rx_stat_gr2047_lo;
- u32 rx_stat_gr2047_hi;
- u32 rx_stat_gr4095_lo;
- u32 rx_stat_gr4095_hi;
- u32 rx_stat_gr9216_lo;
- u32 rx_stat_gr9216_hi;
- u32 rx_stat_gr16383_lo;
- u32 rx_stat_gr16383_hi;
- u32 rx_stat_grmax_lo;
- u32 rx_stat_grmax_hi;
- u32 rx_stat_grpkt_lo;
- u32 rx_stat_grpkt_hi;
- u32 rx_stat_grfcs_lo;
- u32 rx_stat_grfcs_hi;
- u32 rx_stat_grmca_lo;
- u32 rx_stat_grmca_hi;
- u32 rx_stat_grbca_lo;
- u32 rx_stat_grbca_hi;
- u32 rx_stat_grxcf_lo;
- u32 rx_stat_grxcf_hi;
- u32 rx_stat_grxpf_lo;
- u32 rx_stat_grxpf_hi;
- u32 rx_stat_grxuo_lo;
- u32 rx_stat_grxuo_hi;
- u32 rx_stat_grjbr_lo;
- u32 rx_stat_grjbr_hi;
- u32 rx_stat_grovr_lo;
- u32 rx_stat_grovr_hi;
- u32 rx_stat_grflr_lo;
- u32 rx_stat_grflr_hi;
- u32 rx_stat_grmeg_lo;
- u32 rx_stat_grmeg_hi;
- u32 rx_stat_grmeb_lo;
- u32 rx_stat_grmeb_hi;
- u32 rx_stat_grbyt_lo;
- u32 rx_stat_grbyt_hi;
- u32 rx_stat_grund_lo;
- u32 rx_stat_grund_hi;
- u32 rx_stat_grfrg_lo;
- u32 rx_stat_grfrg_hi;
- u32 rx_stat_grerb_lo;
- u32 rx_stat_grerb_hi;
- u32 rx_stat_grfre_lo;
- u32 rx_stat_grfre_hi;
- u32 rx_stat_gripj_lo;
- u32 rx_stat_gripj_hi;
+ u32 tx_stat_gtpkt_lo;
+ u32 tx_stat_gtpkt_hi;
+ u32 tx_stat_gtxpf_lo;
+ u32 tx_stat_gtxpf_hi;
+ u32 tx_stat_gtfcs_lo;
+ u32 tx_stat_gtfcs_hi;
+ u32 tx_stat_gtmca_lo;
+ u32 tx_stat_gtmca_hi;
+ u32 tx_stat_gtbca_lo;
+ u32 tx_stat_gtbca_hi;
+ u32 tx_stat_gtfrg_lo;
+ u32 tx_stat_gtfrg_hi;
+ u32 tx_stat_gtovr_lo;
+ u32 tx_stat_gtovr_hi;
+ u32 tx_stat_gt64_lo;
+ u32 tx_stat_gt64_hi;
+ u32 tx_stat_gt127_lo;
+ u32 tx_stat_gt127_hi;
+ u32 tx_stat_gt255_lo;
+ u32 tx_stat_gt255_hi;
+ u32 tx_stat_gt511_lo;
+ u32 tx_stat_gt511_hi;
+ u32 tx_stat_gt1023_lo;
+ u32 tx_stat_gt1023_hi;
+ u32 tx_stat_gt1518_lo;
+ u32 tx_stat_gt1518_hi;
+ u32 tx_stat_gt2047_lo;
+ u32 tx_stat_gt2047_hi;
+ u32 tx_stat_gt4095_lo;
+ u32 tx_stat_gt4095_hi;
+ u32 tx_stat_gt9216_lo;
+ u32 tx_stat_gt9216_hi;
+ u32 tx_stat_gt16383_lo;
+ u32 tx_stat_gt16383_hi;
+ u32 tx_stat_gtmax_lo;
+ u32 tx_stat_gtmax_hi;
+ u32 tx_stat_gtufl_lo;
+ u32 tx_stat_gtufl_hi;
+ u32 tx_stat_gterr_lo;
+ u32 tx_stat_gterr_hi;
+ u32 tx_stat_gtbyt_lo;
+ u32 tx_stat_gtbyt_hi;
+
+ u32 rx_stat_gr64_lo;
+ u32 rx_stat_gr64_hi;
+ u32 rx_stat_gr127_lo;
+ u32 rx_stat_gr127_hi;
+ u32 rx_stat_gr255_lo;
+ u32 rx_stat_gr255_hi;
+ u32 rx_stat_gr511_lo;
+ u32 rx_stat_gr511_hi;
+ u32 rx_stat_gr1023_lo;
+ u32 rx_stat_gr1023_hi;
+ u32 rx_stat_gr1518_lo;
+ u32 rx_stat_gr1518_hi;
+ u32 rx_stat_gr2047_lo;
+ u32 rx_stat_gr2047_hi;
+ u32 rx_stat_gr4095_lo;
+ u32 rx_stat_gr4095_hi;
+ u32 rx_stat_gr9216_lo;
+ u32 rx_stat_gr9216_hi;
+ u32 rx_stat_gr16383_lo;
+ u32 rx_stat_gr16383_hi;
+ u32 rx_stat_grmax_lo;
+ u32 rx_stat_grmax_hi;
+ u32 rx_stat_grpkt_lo;
+ u32 rx_stat_grpkt_hi;
+ u32 rx_stat_grfcs_lo;
+ u32 rx_stat_grfcs_hi;
+ u32 rx_stat_grmca_lo;
+ u32 rx_stat_grmca_hi;
+ u32 rx_stat_grbca_lo;
+ u32 rx_stat_grbca_hi;
+ u32 rx_stat_grxcf_lo;
+ u32 rx_stat_grxcf_hi;
+ u32 rx_stat_grxpf_lo;
+ u32 rx_stat_grxpf_hi;
+ u32 rx_stat_grxuo_lo;
+ u32 rx_stat_grxuo_hi;
+ u32 rx_stat_grjbr_lo;
+ u32 rx_stat_grjbr_hi;
+ u32 rx_stat_grovr_lo;
+ u32 rx_stat_grovr_hi;
+ u32 rx_stat_grflr_lo;
+ u32 rx_stat_grflr_hi;
+ u32 rx_stat_grmeg_lo;
+ u32 rx_stat_grmeg_hi;
+ u32 rx_stat_grmeb_lo;
+ u32 rx_stat_grmeb_hi;
+ u32 rx_stat_grbyt_lo;
+ u32 rx_stat_grbyt_hi;
+ u32 rx_stat_grund_lo;
+ u32 rx_stat_grund_hi;
+ u32 rx_stat_grfrg_lo;
+ u32 rx_stat_grfrg_hi;
+ u32 rx_stat_grerb_lo;
+ u32 rx_stat_grerb_hi;
+ u32 rx_stat_grfre_lo;
+ u32 rx_stat_grfre_hi;
+ u32 rx_stat_gripj_lo;
+ u32 rx_stat_gripj_hi;
};
struct bmac2_stats {
@@ -1750,187 +2238,316 @@ struct bmac2_stats {
u32 rx_stat_gripj_hi;
};
+struct mstat_stats {
+ struct {
+ /* OTE MSTAT on E3 has a bug where this register's contents are
+ * actually tx_gtxpok + tx_gtxpf + (possibly)tx_gtxpp
+ */
+ u32 tx_gtxpok_lo;
+ u32 tx_gtxpok_hi;
+ u32 tx_gtxpf_lo;
+ u32 tx_gtxpf_hi;
+ u32 tx_gtxpp_lo;
+ u32 tx_gtxpp_hi;
+ u32 tx_gtfcs_lo;
+ u32 tx_gtfcs_hi;
+ u32 tx_gtuca_lo;
+ u32 tx_gtuca_hi;
+ u32 tx_gtmca_lo;
+ u32 tx_gtmca_hi;
+ u32 tx_gtgca_lo;
+ u32 tx_gtgca_hi;
+ u32 tx_gtpkt_lo;
+ u32 tx_gtpkt_hi;
+ u32 tx_gt64_lo;
+ u32 tx_gt64_hi;
+ u32 tx_gt127_lo;
+ u32 tx_gt127_hi;
+ u32 tx_gt255_lo;
+ u32 tx_gt255_hi;
+ u32 tx_gt511_lo;
+ u32 tx_gt511_hi;
+ u32 tx_gt1023_lo;
+ u32 tx_gt1023_hi;
+ u32 tx_gt1518_lo;
+ u32 tx_gt1518_hi;
+ u32 tx_gt2047_lo;
+ u32 tx_gt2047_hi;
+ u32 tx_gt4095_lo;
+ u32 tx_gt4095_hi;
+ u32 tx_gt9216_lo;
+ u32 tx_gt9216_hi;
+ u32 tx_gt16383_lo;
+ u32 tx_gt16383_hi;
+ u32 tx_gtufl_lo;
+ u32 tx_gtufl_hi;
+ u32 tx_gterr_lo;
+ u32 tx_gterr_hi;
+ u32 tx_gtbyt_lo;
+ u32 tx_gtbyt_hi;
+ u32 tx_collisions_lo;
+ u32 tx_collisions_hi;
+ u32 tx_singlecollision_lo;
+ u32 tx_singlecollision_hi;
+ u32 tx_multiplecollisions_lo;
+ u32 tx_multiplecollisions_hi;
+ u32 tx_deferred_lo;
+ u32 tx_deferred_hi;
+ u32 tx_excessivecollisions_lo;
+ u32 tx_excessivecollisions_hi;
+ u32 tx_latecollisions_lo;
+ u32 tx_latecollisions_hi;
+ } stats_tx;
+
+ struct {
+ u32 rx_gr64_lo;
+ u32 rx_gr64_hi;
+ u32 rx_gr127_lo;
+ u32 rx_gr127_hi;
+ u32 rx_gr255_lo;
+ u32 rx_gr255_hi;
+ u32 rx_gr511_lo;
+ u32 rx_gr511_hi;
+ u32 rx_gr1023_lo;
+ u32 rx_gr1023_hi;
+ u32 rx_gr1518_lo;
+ u32 rx_gr1518_hi;
+ u32 rx_gr2047_lo;
+ u32 rx_gr2047_hi;
+ u32 rx_gr4095_lo;
+ u32 rx_gr4095_hi;
+ u32 rx_gr9216_lo;
+ u32 rx_gr9216_hi;
+ u32 rx_gr16383_lo;
+ u32 rx_gr16383_hi;
+ u32 rx_grpkt_lo;
+ u32 rx_grpkt_hi;
+ u32 rx_grfcs_lo;
+ u32 rx_grfcs_hi;
+ u32 rx_gruca_lo;
+ u32 rx_gruca_hi;
+ u32 rx_grmca_lo;
+ u32 rx_grmca_hi;
+ u32 rx_grbca_lo;
+ u32 rx_grbca_hi;
+ u32 rx_grxpf_lo;
+ u32 rx_grxpf_hi;
+ u32 rx_grxpp_lo;
+ u32 rx_grxpp_hi;
+ u32 rx_grxuo_lo;
+ u32 rx_grxuo_hi;
+ u32 rx_grovr_lo;
+ u32 rx_grovr_hi;
+ u32 rx_grxcf_lo;
+ u32 rx_grxcf_hi;
+ u32 rx_grflr_lo;
+ u32 rx_grflr_hi;
+ u32 rx_grpok_lo;
+ u32 rx_grpok_hi;
+ u32 rx_grbyt_lo;
+ u32 rx_grbyt_hi;
+ u32 rx_grund_lo;
+ u32 rx_grund_hi;
+ u32 rx_grfrg_lo;
+ u32 rx_grfrg_hi;
+ u32 rx_grerb_lo;
+ u32 rx_grerb_hi;
+ u32 rx_grfre_lo;
+ u32 rx_grfre_hi;
+
+ u32 rx_alignmenterrors_lo;
+ u32 rx_alignmenterrors_hi;
+ u32 rx_falsecarrier_lo;
+ u32 rx_falsecarrier_hi;
+ u32 rx_llfcmsgcnt_lo;
+ u32 rx_llfcmsgcnt_hi;
+ } stats_rx;
+};
+
union mac_stats {
- struct emac_stats emac_stats;
- struct bmac1_stats bmac1_stats;
- struct bmac2_stats bmac2_stats;
+ struct emac_stats emac_stats;
+ struct bmac1_stats bmac1_stats;
+ struct bmac2_stats bmac2_stats;
+ struct mstat_stats mstat_stats;
};
struct mac_stx {
- /* in_bad_octets */
- u32 rx_stat_ifhcinbadoctets_hi;
- u32 rx_stat_ifhcinbadoctets_lo;
-
- /* out_bad_octets */
- u32 tx_stat_ifhcoutbadoctets_hi;
- u32 tx_stat_ifhcoutbadoctets_lo;
-
- /* crc_receive_errors */
- u32 rx_stat_dot3statsfcserrors_hi;
- u32 rx_stat_dot3statsfcserrors_lo;
- /* alignment_errors */
- u32 rx_stat_dot3statsalignmenterrors_hi;
- u32 rx_stat_dot3statsalignmenterrors_lo;
- /* carrier_sense_errors */
- u32 rx_stat_dot3statscarriersenseerrors_hi;
- u32 rx_stat_dot3statscarriersenseerrors_lo;
- /* false_carrier_detections */
- u32 rx_stat_falsecarriererrors_hi;
- u32 rx_stat_falsecarriererrors_lo;
-
- /* runt_packets_received */
- u32 rx_stat_etherstatsundersizepkts_hi;
- u32 rx_stat_etherstatsundersizepkts_lo;
- /* jabber_packets_received */
- u32 rx_stat_dot3statsframestoolong_hi;
- u32 rx_stat_dot3statsframestoolong_lo;
-
- /* error_runt_packets_received */
- u32 rx_stat_etherstatsfragments_hi;
- u32 rx_stat_etherstatsfragments_lo;
- /* error_jabber_packets_received */
- u32 rx_stat_etherstatsjabbers_hi;
- u32 rx_stat_etherstatsjabbers_lo;
-
- /* control_frames_received */
- u32 rx_stat_maccontrolframesreceived_hi;
- u32 rx_stat_maccontrolframesreceived_lo;
- u32 rx_stat_bmac_xpf_hi;
- u32 rx_stat_bmac_xpf_lo;
- u32 rx_stat_bmac_xcf_hi;
- u32 rx_stat_bmac_xcf_lo;
-
- /* xoff_state_entered */
- u32 rx_stat_xoffstateentered_hi;
- u32 rx_stat_xoffstateentered_lo;
- /* pause_xon_frames_received */
- u32 rx_stat_xonpauseframesreceived_hi;
- u32 rx_stat_xonpauseframesreceived_lo;
- /* pause_xoff_frames_received */
- u32 rx_stat_xoffpauseframesreceived_hi;
- u32 rx_stat_xoffpauseframesreceived_lo;
- /* pause_xon_frames_transmitted */
- u32 tx_stat_outxonsent_hi;
- u32 tx_stat_outxonsent_lo;
- /* pause_xoff_frames_transmitted */
- u32 tx_stat_outxoffsent_hi;
- u32 tx_stat_outxoffsent_lo;
- /* flow_control_done */
- u32 tx_stat_flowcontroldone_hi;
- u32 tx_stat_flowcontroldone_lo;
-
- /* ether_stats_collisions */
- u32 tx_stat_etherstatscollisions_hi;
- u32 tx_stat_etherstatscollisions_lo;
- /* single_collision_transmit_frames */
- u32 tx_stat_dot3statssinglecollisionframes_hi;
- u32 tx_stat_dot3statssinglecollisionframes_lo;
- /* multiple_collision_transmit_frames */
- u32 tx_stat_dot3statsmultiplecollisionframes_hi;
- u32 tx_stat_dot3statsmultiplecollisionframes_lo;
- /* deferred_transmissions */
- u32 tx_stat_dot3statsdeferredtransmissions_hi;
- u32 tx_stat_dot3statsdeferredtransmissions_lo;
- /* excessive_collision_frames */
- u32 tx_stat_dot3statsexcessivecollisions_hi;
- u32 tx_stat_dot3statsexcessivecollisions_lo;
- /* late_collision_frames */
- u32 tx_stat_dot3statslatecollisions_hi;
- u32 tx_stat_dot3statslatecollisions_lo;
-
- /* frames_transmitted_64_bytes */
- u32 tx_stat_etherstatspkts64octets_hi;
- u32 tx_stat_etherstatspkts64octets_lo;
- /* frames_transmitted_65_127_bytes */
- u32 tx_stat_etherstatspkts65octetsto127octets_hi;
- u32 tx_stat_etherstatspkts65octetsto127octets_lo;
- /* frames_transmitted_128_255_bytes */
- u32 tx_stat_etherstatspkts128octetsto255octets_hi;
- u32 tx_stat_etherstatspkts128octetsto255octets_lo;
- /* frames_transmitted_256_511_bytes */
- u32 tx_stat_etherstatspkts256octetsto511octets_hi;
- u32 tx_stat_etherstatspkts256octetsto511octets_lo;
- /* frames_transmitted_512_1023_bytes */
- u32 tx_stat_etherstatspkts512octetsto1023octets_hi;
- u32 tx_stat_etherstatspkts512octetsto1023octets_lo;
- /* frames_transmitted_1024_1522_bytes */
- u32 tx_stat_etherstatspkts1024octetsto1522octets_hi;
- u32 tx_stat_etherstatspkts1024octetsto1522octets_lo;
- /* frames_transmitted_1523_9022_bytes */
- u32 tx_stat_etherstatspktsover1522octets_hi;
- u32 tx_stat_etherstatspktsover1522octets_lo;
- u32 tx_stat_bmac_2047_hi;
- u32 tx_stat_bmac_2047_lo;
- u32 tx_stat_bmac_4095_hi;
- u32 tx_stat_bmac_4095_lo;
- u32 tx_stat_bmac_9216_hi;
- u32 tx_stat_bmac_9216_lo;
- u32 tx_stat_bmac_16383_hi;
- u32 tx_stat_bmac_16383_lo;
-
- /* internal_mac_transmit_errors */
- u32 tx_stat_dot3statsinternalmactransmiterrors_hi;
- u32 tx_stat_dot3statsinternalmactransmiterrors_lo;
-
- /* if_out_discards */
- u32 tx_stat_bmac_ufl_hi;
- u32 tx_stat_bmac_ufl_lo;
-};
-
-
-#define MAC_STX_IDX_MAX 2
+ /* in_bad_octets */
+ u32 rx_stat_ifhcinbadoctets_hi;
+ u32 rx_stat_ifhcinbadoctets_lo;
+
+ /* out_bad_octets */
+ u32 tx_stat_ifhcoutbadoctets_hi;
+ u32 tx_stat_ifhcoutbadoctets_lo;
+
+ /* crc_receive_errors */
+ u32 rx_stat_dot3statsfcserrors_hi;
+ u32 rx_stat_dot3statsfcserrors_lo;
+ /* alignment_errors */
+ u32 rx_stat_dot3statsalignmenterrors_hi;
+ u32 rx_stat_dot3statsalignmenterrors_lo;
+ /* carrier_sense_errors */
+ u32 rx_stat_dot3statscarriersenseerrors_hi;
+ u32 rx_stat_dot3statscarriersenseerrors_lo;
+ /* false_carrier_detections */
+ u32 rx_stat_falsecarriererrors_hi;
+ u32 rx_stat_falsecarriererrors_lo;
+
+ /* runt_packets_received */
+ u32 rx_stat_etherstatsundersizepkts_hi;
+ u32 rx_stat_etherstatsundersizepkts_lo;
+ /* jabber_packets_received */
+ u32 rx_stat_dot3statsframestoolong_hi;
+ u32 rx_stat_dot3statsframestoolong_lo;
+
+ /* error_runt_packets_received */
+ u32 rx_stat_etherstatsfragments_hi;
+ u32 rx_stat_etherstatsfragments_lo;
+ /* error_jabber_packets_received */
+ u32 rx_stat_etherstatsjabbers_hi;
+ u32 rx_stat_etherstatsjabbers_lo;
+
+ /* control_frames_received */
+ u32 rx_stat_maccontrolframesreceived_hi;
+ u32 rx_stat_maccontrolframesreceived_lo;
+ u32 rx_stat_mac_xpf_hi;
+ u32 rx_stat_mac_xpf_lo;
+ u32 rx_stat_mac_xcf_hi;
+ u32 rx_stat_mac_xcf_lo;
+
+ /* xoff_state_entered */
+ u32 rx_stat_xoffstateentered_hi;
+ u32 rx_stat_xoffstateentered_lo;
+ /* pause_xon_frames_received */
+ u32 rx_stat_xonpauseframesreceived_hi;
+ u32 rx_stat_xonpauseframesreceived_lo;
+ /* pause_xoff_frames_received */
+ u32 rx_stat_xoffpauseframesreceived_hi;
+ u32 rx_stat_xoffpauseframesreceived_lo;
+ /* pause_xon_frames_transmitted */
+ u32 tx_stat_outxonsent_hi;
+ u32 tx_stat_outxonsent_lo;
+ /* pause_xoff_frames_transmitted */
+ u32 tx_stat_outxoffsent_hi;
+ u32 tx_stat_outxoffsent_lo;
+ /* flow_control_done */
+ u32 tx_stat_flowcontroldone_hi;
+ u32 tx_stat_flowcontroldone_lo;
+
+ /* ether_stats_collisions */
+ u32 tx_stat_etherstatscollisions_hi;
+ u32 tx_stat_etherstatscollisions_lo;
+ /* single_collision_transmit_frames */
+ u32 tx_stat_dot3statssinglecollisionframes_hi;
+ u32 tx_stat_dot3statssinglecollisionframes_lo;
+ /* multiple_collision_transmit_frames */
+ u32 tx_stat_dot3statsmultiplecollisionframes_hi;
+ u32 tx_stat_dot3statsmultiplecollisionframes_lo;
+ /* deferred_transmissions */
+ u32 tx_stat_dot3statsdeferredtransmissions_hi;
+ u32 tx_stat_dot3statsdeferredtransmissions_lo;
+ /* excessive_collision_frames */
+ u32 tx_stat_dot3statsexcessivecollisions_hi;
+ u32 tx_stat_dot3statsexcessivecollisions_lo;
+ /* late_collision_frames */
+ u32 tx_stat_dot3statslatecollisions_hi;
+ u32 tx_stat_dot3statslatecollisions_lo;
+
+ /* frames_transmitted_64_bytes */
+ u32 tx_stat_etherstatspkts64octets_hi;
+ u32 tx_stat_etherstatspkts64octets_lo;
+ /* frames_transmitted_65_127_bytes */
+ u32 tx_stat_etherstatspkts65octetsto127octets_hi;
+ u32 tx_stat_etherstatspkts65octetsto127octets_lo;
+ /* frames_transmitted_128_255_bytes */
+ u32 tx_stat_etherstatspkts128octetsto255octets_hi;
+ u32 tx_stat_etherstatspkts128octetsto255octets_lo;
+ /* frames_transmitted_256_511_bytes */
+ u32 tx_stat_etherstatspkts256octetsto511octets_hi;
+ u32 tx_stat_etherstatspkts256octetsto511octets_lo;
+ /* frames_transmitted_512_1023_bytes */
+ u32 tx_stat_etherstatspkts512octetsto1023octets_hi;
+ u32 tx_stat_etherstatspkts512octetsto1023octets_lo;
+ /* frames_transmitted_1024_1522_bytes */
+ u32 tx_stat_etherstatspkts1024octetsto1522octets_hi;
+ u32 tx_stat_etherstatspkts1024octetsto1522octets_lo;
+ /* frames_transmitted_1523_9022_bytes */
+ u32 tx_stat_etherstatspktsover1522octets_hi;
+ u32 tx_stat_etherstatspktsover1522octets_lo;
+ u32 tx_stat_mac_2047_hi;
+ u32 tx_stat_mac_2047_lo;
+ u32 tx_stat_mac_4095_hi;
+ u32 tx_stat_mac_4095_lo;
+ u32 tx_stat_mac_9216_hi;
+ u32 tx_stat_mac_9216_lo;
+ u32 tx_stat_mac_16383_hi;
+ u32 tx_stat_mac_16383_lo;
+
+ /* internal_mac_transmit_errors */
+ u32 tx_stat_dot3statsinternalmactransmiterrors_hi;
+ u32 tx_stat_dot3statsinternalmactransmiterrors_lo;
+
+ /* if_out_discards */
+ u32 tx_stat_mac_ufl_hi;
+ u32 tx_stat_mac_ufl_lo;
+};
+
+
+#define MAC_STX_IDX_MAX 2
struct host_port_stats {
- u32 host_port_stats_start;
+ u32 host_port_stats_start;
- struct mac_stx mac_stx[MAC_STX_IDX_MAX];
+ struct mac_stx mac_stx[MAC_STX_IDX_MAX];
- u32 brb_drop_hi;
- u32 brb_drop_lo;
+ u32 brb_drop_hi;
+ u32 brb_drop_lo;
- u32 host_port_stats_end;
+ u32 host_port_stats_end;
};
struct host_func_stats {
- u32 host_func_stats_start;
+ u32 host_func_stats_start;
- u32 total_bytes_received_hi;
- u32 total_bytes_received_lo;
+ u32 total_bytes_received_hi;
+ u32 total_bytes_received_lo;
- u32 total_bytes_transmitted_hi;
- u32 total_bytes_transmitted_lo;
+ u32 total_bytes_transmitted_hi;
+ u32 total_bytes_transmitted_lo;
- u32 total_unicast_packets_received_hi;
- u32 total_unicast_packets_received_lo;
+ u32 total_unicast_packets_received_hi;
+ u32 total_unicast_packets_received_lo;
- u32 total_multicast_packets_received_hi;
- u32 total_multicast_packets_received_lo;
+ u32 total_multicast_packets_received_hi;
+ u32 total_multicast_packets_received_lo;
- u32 total_broadcast_packets_received_hi;
- u32 total_broadcast_packets_received_lo;
+ u32 total_broadcast_packets_received_hi;
+ u32 total_broadcast_packets_received_lo;
- u32 total_unicast_packets_transmitted_hi;
- u32 total_unicast_packets_transmitted_lo;
+ u32 total_unicast_packets_transmitted_hi;
+ u32 total_unicast_packets_transmitted_lo;
- u32 total_multicast_packets_transmitted_hi;
- u32 total_multicast_packets_transmitted_lo;
+ u32 total_multicast_packets_transmitted_hi;
+ u32 total_multicast_packets_transmitted_lo;
- u32 total_broadcast_packets_transmitted_hi;
- u32 total_broadcast_packets_transmitted_lo;
+ u32 total_broadcast_packets_transmitted_hi;
+ u32 total_broadcast_packets_transmitted_lo;
- u32 valid_bytes_received_hi;
- u32 valid_bytes_received_lo;
+ u32 valid_bytes_received_hi;
+ u32 valid_bytes_received_lo;
- u32 host_func_stats_end;
+ u32 host_func_stats_end;
};
+/* VIC definitions */
+#define VICSTATST_UIF_INDEX 2
-#define BCM_5710_FW_MAJOR_VERSION 6
-#define BCM_5710_FW_MINOR_VERSION 2
-#define BCM_5710_FW_REVISION_VERSION 9
-#define BCM_5710_FW_ENGINEERING_VERSION 0
+#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_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
@@ -1948,6 +2565,115 @@ struct atten_sp_status_block {
/*
+ * The eth aggregative context of Cstorm
+ */
+struct cstorm_eth_ag_context {
+ u32 __reserved0[10];
+};
+
+
+/*
+ * dmae command structure
+ */
+struct dmae_command {
+ u32 opcode;
+#define DMAE_COMMAND_SRC (0x1<<0)
+#define DMAE_COMMAND_SRC_SHIFT 0
+#define DMAE_COMMAND_DST (0x3<<1)
+#define DMAE_COMMAND_DST_SHIFT 1
+#define DMAE_COMMAND_C_DST (0x1<<3)
+#define DMAE_COMMAND_C_DST_SHIFT 3
+#define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4)
+#define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4
+#define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5)
+#define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5
+#define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6)
+#define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6
+#define DMAE_COMMAND_ENDIANITY (0x3<<9)
+#define DMAE_COMMAND_ENDIANITY_SHIFT 9
+#define DMAE_COMMAND_PORT (0x1<<11)
+#define DMAE_COMMAND_PORT_SHIFT 11
+#define DMAE_COMMAND_CRC_RESET (0x1<<12)
+#define DMAE_COMMAND_CRC_RESET_SHIFT 12
+#define DMAE_COMMAND_SRC_RESET (0x1<<13)
+#define DMAE_COMMAND_SRC_RESET_SHIFT 13
+#define DMAE_COMMAND_DST_RESET (0x1<<14)
+#define DMAE_COMMAND_DST_RESET_SHIFT 14
+#define DMAE_COMMAND_E1HVN (0x3<<15)
+#define DMAE_COMMAND_E1HVN_SHIFT 15
+#define DMAE_COMMAND_DST_VN (0x3<<17)
+#define DMAE_COMMAND_DST_VN_SHIFT 17
+#define DMAE_COMMAND_C_FUNC (0x1<<19)
+#define DMAE_COMMAND_C_FUNC_SHIFT 19
+#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
+#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
+#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
+#define DMAE_COMMAND_RESERVED0_SHIFT 22
+ u32 src_addr_lo;
+ u32 src_addr_hi;
+ u32 dst_addr_lo;
+ u32 dst_addr_hi;
+#if defined(__BIG_ENDIAN)
+ u16 opcode_iov;
+#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
+#define DMAE_COMMAND_SRC_VFID_SHIFT 0
+#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
+#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
+#define DMAE_COMMAND_RESERVED1 (0x1<<7)
+#define DMAE_COMMAND_RESERVED1_SHIFT 7
+#define DMAE_COMMAND_DST_VFID (0x3F<<8)
+#define DMAE_COMMAND_DST_VFID_SHIFT 8
+#define DMAE_COMMAND_DST_VFPF (0x1<<14)
+#define DMAE_COMMAND_DST_VFPF_SHIFT 14
+#define DMAE_COMMAND_RESERVED2 (0x1<<15)
+#define DMAE_COMMAND_RESERVED2_SHIFT 15
+ u16 len;
+#elif defined(__LITTLE_ENDIAN)
+ u16 len;
+ u16 opcode_iov;
+#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
+#define DMAE_COMMAND_SRC_VFID_SHIFT 0
+#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
+#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
+#define DMAE_COMMAND_RESERVED1 (0x1<<7)
+#define DMAE_COMMAND_RESERVED1_SHIFT 7
+#define DMAE_COMMAND_DST_VFID (0x3F<<8)
+#define DMAE_COMMAND_DST_VFID_SHIFT 8
+#define DMAE_COMMAND_DST_VFPF (0x1<<14)
+#define DMAE_COMMAND_DST_VFPF_SHIFT 14
+#define DMAE_COMMAND_RESERVED2 (0x1<<15)
+#define DMAE_COMMAND_RESERVED2_SHIFT 15
+#endif
+ u32 comp_addr_lo;
+ u32 comp_addr_hi;
+ u32 comp_val;
+ u32 crc32;
+ u32 crc32_c;
+#if defined(__BIG_ENDIAN)
+ u16 crc16_c;
+ u16 crc16;
+#elif defined(__LITTLE_ENDIAN)
+ u16 crc16;
+ u16 crc16_c;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 reserved3;
+ u16 crc_t10;
+#elif defined(__LITTLE_ENDIAN)
+ u16 crc_t10;
+ u16 reserved3;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 xsum8;
+ u16 xsum16;
+#elif defined(__LITTLE_ENDIAN)
+ u16 xsum16;
+ u16 xsum8;
+#endif
+};
+
+
+/*
* common data for all protocols
*/
struct doorbell_hdr {
@@ -1963,33 +2689,29 @@ struct doorbell_hdr {
};
/*
- * doorbell message sent to the chip
- */
-struct doorbell {
-#if defined(__BIG_ENDIAN)
- u16 zero_fill2;
- u8 zero_fill1;
- struct doorbell_hdr header;
-#elif defined(__LITTLE_ENDIAN)
- struct doorbell_hdr header;
- u8 zero_fill1;
- u16 zero_fill2;
-#endif
-};
-
-
-/*
- * doorbell message sent to the chip
+ * Ethernet doorbell
*/
-struct doorbell_set_prod {
+struct eth_tx_doorbell {
#if defined(__BIG_ENDIAN)
- u16 prod;
- u8 zero_fill1;
- struct doorbell_hdr header;
+ u16 npackets;
+ u8 params;
+#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
+#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
+#define ETH_TX_DOORBELL_SPARE (0x1<<7)
+#define ETH_TX_DOORBELL_SPARE_SHIFT 7
+ struct doorbell_hdr hdr;
#elif defined(__LITTLE_ENDIAN)
- struct doorbell_hdr header;
- u8 zero_fill1;
- u16 prod;
+ struct doorbell_hdr hdr;
+ u8 params;
+#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
+#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
+#define ETH_TX_DOORBELL_SPARE (0x1<<7)
+#define ETH_TX_DOORBELL_SPARE_SHIFT 7
+ u16 npackets;
#endif
};
@@ -2000,7 +2722,7 @@ struct doorbell_set_prod {
struct hc_status_block_e1x {
__le16 index_values[HC_SB_MAX_INDICES_E1X];
__le16 running_index[HC_SB_MAX_SM];
- u32 rsrv;
+ __le32 rsrv[11];
};
/*
@@ -2017,7 +2739,7 @@ struct host_hc_status_block_e1x {
struct hc_status_block_e2 {
__le16 index_values[HC_SB_MAX_INDICES_E2];
__le16 running_index[HC_SB_MAX_SM];
- u32 reserved;
+ __le32 reserved[11];
};
/*
@@ -2138,6 +2860,16 @@ union igu_consprod_reg {
/*
+ * Igu control commands
+ */
+enum igu_ctrl_cmd {
+ IGU_CTRL_CMD_TYPE_RD,
+ IGU_CTRL_CMD_TYPE_WR,
+ MAX_IGU_CTRL_CMD
+};
+
+
+/*
* Control register for the IGU command register
*/
struct igu_ctrl_reg {
@@ -2156,6 +2888,29 @@ struct igu_ctrl_reg {
/*
+ * Igu interrupt command
+ */
+enum igu_int_cmd {
+ IGU_INT_ENABLE,
+ IGU_INT_DISABLE,
+ IGU_INT_NOP,
+ IGU_INT_NOP2,
+ MAX_IGU_INT_CMD
+};
+
+
+/*
+ * Igu segments
+ */
+enum igu_seg_access {
+ IGU_SEG_ACCESS_NORM,
+ IGU_SEG_ACCESS_DEF,
+ IGU_SEG_ACCESS_ATTN,
+ MAX_IGU_SEG_ACCESS
+};
+
+
+/*
* Parser parsing flags field
*/
struct parsing_flags {
@@ -2189,94 +2944,46 @@ struct parsing_flags {
};
-struct regpair {
- __le32 lo;
- __le32 hi;
+/*
+ * Parsing flags for TCP ACK type
+ */
+enum prs_flags_ack_type {
+ PRS_FLAG_PUREACK_PIGGY,
+ PRS_FLAG_PUREACK_PURE,
+ MAX_PRS_FLAGS_ACK_TYPE
};
/*
- * dmae command structure
+ * Parsing flags for Ethernet address type
*/
-struct dmae_command {
- u32 opcode;
-#define DMAE_COMMAND_SRC (0x1<<0)
-#define DMAE_COMMAND_SRC_SHIFT 0
-#define DMAE_COMMAND_DST (0x3<<1)
-#define DMAE_COMMAND_DST_SHIFT 1
-#define DMAE_COMMAND_C_DST (0x1<<3)
-#define DMAE_COMMAND_C_DST_SHIFT 3
-#define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4)
-#define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5)
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6)
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6
-#define DMAE_COMMAND_ENDIANITY (0x3<<9)
-#define DMAE_COMMAND_ENDIANITY_SHIFT 9
-#define DMAE_COMMAND_PORT (0x1<<11)
-#define DMAE_COMMAND_PORT_SHIFT 11
-#define DMAE_COMMAND_CRC_RESET (0x1<<12)
-#define DMAE_COMMAND_CRC_RESET_SHIFT 12
-#define DMAE_COMMAND_SRC_RESET (0x1<<13)
-#define DMAE_COMMAND_SRC_RESET_SHIFT 13
-#define DMAE_COMMAND_DST_RESET (0x1<<14)
-#define DMAE_COMMAND_DST_RESET_SHIFT 14
-#define DMAE_COMMAND_E1HVN (0x3<<15)
-#define DMAE_COMMAND_E1HVN_SHIFT 15
-#define DMAE_COMMAND_DST_VN (0x3<<17)
-#define DMAE_COMMAND_DST_VN_SHIFT 17
-#define DMAE_COMMAND_C_FUNC (0x1<<19)
-#define DMAE_COMMAND_C_FUNC_SHIFT 19
-#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
-#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
-#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
-#define DMAE_COMMAND_RESERVED0_SHIFT 22
- u32 src_addr_lo;
- u32 src_addr_hi;
- u32 dst_addr_lo;
- u32 dst_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u16 len;
-#elif defined(__LITTLE_ENDIAN)
- u16 len;
- u16 reserved1;
-#endif
- u32 comp_addr_lo;
- u32 comp_addr_hi;
- u32 comp_val;
- u32 crc32;
- u32 crc32_c;
-#if defined(__BIG_ENDIAN)
- u16 crc16_c;
- u16 crc16;
-#elif defined(__LITTLE_ENDIAN)
- u16 crc16;
- u16 crc16_c;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 reserved3;
- u16 crc_t10;
-#elif defined(__LITTLE_ENDIAN)
- u16 crc_t10;
- u16 reserved3;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 xsum8;
- u16 xsum16;
-#elif defined(__LITTLE_ENDIAN)
- u16 xsum16;
- u16 xsum8;
-#endif
+enum prs_flags_eth_addr_type {
+ PRS_FLAG_ETHTYPE_NON_UNICAST,
+ PRS_FLAG_ETHTYPE_UNICAST,
+ MAX_PRS_FLAGS_ETH_ADDR_TYPE
};
-struct double_regpair {
- u32 regpair0_lo;
- u32 regpair0_hi;
- u32 regpair1_lo;
- u32 regpair1_hi;
+/*
+ * Parsing flags for over-ethernet protocol
+ */
+enum prs_flags_over_eth {
+ PRS_FLAG_OVERETH_UNKNOWN,
+ PRS_FLAG_OVERETH_IPV4,
+ PRS_FLAG_OVERETH_IPV6,
+ PRS_FLAG_OVERETH_LLCSNAP_UNKNOWN,
+ MAX_PRS_FLAGS_OVER_ETH
+};
+
+
+/*
+ * Parsing flags for over-IP protocol
+ */
+enum prs_flags_over_ip {
+ PRS_FLAG_OVERIP_UNKNOWN,
+ PRS_FLAG_OVERIP_TCP,
+ PRS_FLAG_OVERIP_UDP,
+ MAX_PRS_FLAGS_OVER_IP
};
@@ -2297,54 +3004,23 @@ struct sdm_op_gen {
#define SDM_OP_GEN_RESERVED_SHIFT 17
};
-/*
- * The eth Rx Buffer Descriptor
- */
-struct eth_rx_bd {
- __le32 addr_lo;
- __le32 addr_hi;
-};
/*
- * The eth Rx SGE Descriptor
- */
-struct eth_rx_sge {
- __le32 addr_lo;
- __le32 addr_hi;
-};
-
-
-
-/*
- * The eth storm context of Ustorm
- */
-struct ustorm_eth_st_context {
- u32 reserved0[48];
-};
-
-/*
- * The eth storm context of Tstorm
+ * Timers connection context
*/
-struct tstorm_eth_st_context {
- u32 __reserved0[28];
+struct timers_block_context {
+ u32 __reserved_0;
+ u32 __reserved_1;
+ u32 __reserved_2;
+ u32 flags;
+#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
+#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
+#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
+#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
+#define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
+#define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
};
-/*
- * The eth aggregative context of Xstorm
- */
-struct xstorm_eth_ag_context {
- u32 reserved0;
-#if defined(__BIG_ENDIAN)
- u8 cdu_reserved;
- u8 reserved2;
- u16 reserved1;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved1;
- u8 reserved2;
- u8 cdu_reserved;
-#endif
- u32 reserved3[30];
-};
/*
* The eth aggregative context of Tstorm
@@ -2355,14 +3031,6 @@ struct tstorm_eth_ag_context {
/*
- * The eth aggregative context of Cstorm
- */
-struct cstorm_eth_ag_context {
- u32 __reserved0[10];
-};
-
-
-/*
* The eth aggregative context of Ustorm
*/
struct ustorm_eth_ag_context {
@@ -2379,229 +3047,81 @@ struct ustorm_eth_ag_context {
u32 __reserved3[6];
};
-/*
- * Timers connection context
- */
-struct timers_block_context {
- u32 __reserved_0;
- u32 __reserved_1;
- u32 __reserved_2;
- u32 flags;
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
-};
/*
- * structure for easy accessibility to assembler
- */
-struct eth_tx_bd_flags {
- u8 as_bitfield;
-#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0)
-#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0
-#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1)
-#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1
-#define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2)
-#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2
-#define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
-#define ETH_TX_BD_FLAGS_START_BD_SHIFT 4
-#define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5)
-#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5
-#define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6)
-#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6
-#define ETH_TX_BD_FLAGS_IPV6 (0x1<<7)
-#define ETH_TX_BD_FLAGS_IPV6_SHIFT 7
-};
-
-/*
- * The eth Tx Buffer Descriptor
- */
-struct eth_tx_start_bd {
- __le32 addr_lo;
- __le32 addr_hi;
- __le16 nbd;
- __le16 nbytes;
- __le16 vlan_or_ethertype;
- struct eth_tx_bd_flags bd_flags;
- u8 general_data;
-#define ETH_TX_START_BD_HDR_NBDS (0x3F<<0)
-#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
-#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
-#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
-};
-
-/*
- * Tx regular BD structure
- */
-struct eth_tx_bd {
- __le32 addr_lo;
- __le32 addr_hi;
- __le16 total_pkt_bytes;
- __le16 nbytes;
- u8 reserved[4];
-};
-
-/*
- * Tx parsing BD structure for ETH E1/E1h
- */
-struct eth_tx_parse_bd_e1x {
- u8 global_data;
-#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0)
-#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0
-#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4)
-#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4
-#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
-#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
-#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6)
-#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6
-#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7
- u8 tcp_flags;
-#define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0)
-#define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0
-#define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1)
-#define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1
-#define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2)
-#define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2
-#define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3)
-#define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3
-#define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4
-#define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5)
-#define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5
-#define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6)
-#define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6
-#define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7
- u8 ip_hlen_w;
- s8 reserved;
- __le16 total_hlen_w;
- __le16 tcp_pseudo_csum;
- __le16 lso_mss;
- __le16 ip_id;
- __le32 tcp_send_seq;
-};
-
-/*
- * Tx parsing BD structure for ETH E2
+ * The eth aggregative context of Xstorm
*/
-struct eth_tx_parse_bd_e2 {
- __le16 dst_mac_addr_lo;
- __le16 dst_mac_addr_mid;
- __le16 dst_mac_addr_hi;
- __le16 src_mac_addr_lo;
- __le16 src_mac_addr_mid;
- __le16 src_mac_addr_hi;
- __le32 parsing_data;
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
-#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
-#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
-#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
-#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
+struct xstorm_eth_ag_context {
+ u32 reserved0;
+#if defined(__BIG_ENDIAN)
+ u8 cdu_reserved;
+ u8 reserved2;
+ u16 reserved1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 reserved1;
+ u8 reserved2;
+ u8 cdu_reserved;
+#endif
+ u32 reserved3[30];
};
-/*
- * The last BD in the BD memory will hold a pointer to the next BD memory
- */
-struct eth_tx_next_bd {
- __le32 addr_lo;
- __le32 addr_hi;
- u8 reserved[8];
-};
/*
- * union for 4 Bd types
+ * doorbell message sent to the chip
*/
-union eth_tx_bd_types {
- struct eth_tx_start_bd start_bd;
- struct eth_tx_bd reg_bd;
- struct eth_tx_parse_bd_e1x parse_bd_e1x;
- struct eth_tx_parse_bd_e2 parse_bd_e2;
- struct eth_tx_next_bd next_bd;
+struct doorbell {
+#if defined(__BIG_ENDIAN)
+ u16 zero_fill2;
+ u8 zero_fill1;
+ struct doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct doorbell_hdr header;
+ u8 zero_fill1;
+ u16 zero_fill2;
+#endif
};
/*
- * The eth storm context of Xstorm
+ * doorbell message sent to the chip
*/
-struct xstorm_eth_st_context {
- u32 reserved0[60];
+struct doorbell_set_prod {
+#if defined(__BIG_ENDIAN)
+ u16 prod;
+ u8 zero_fill1;
+ struct doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct doorbell_hdr header;
+ u8 zero_fill1;
+ u16 prod;
+#endif
};
-/*
- * The eth storm context of Cstorm
- */
-struct cstorm_eth_st_context {
- u32 __reserved0[4];
-};
-/*
- * Ethernet connection context
- */
-struct eth_context {
- struct ustorm_eth_st_context ustorm_st_context;
- struct tstorm_eth_st_context tstorm_st_context;
- struct xstorm_eth_ag_context xstorm_ag_context;
- struct tstorm_eth_ag_context tstorm_ag_context;
- struct cstorm_eth_ag_context cstorm_ag_context;
- struct ustorm_eth_ag_context ustorm_ag_context;
- struct timers_block_context timers_context;
- struct xstorm_eth_st_context xstorm_st_context;
- struct cstorm_eth_st_context cstorm_st_context;
+struct regpair {
+ __le32 lo;
+ __le32 hi;
};
/*
- * Ethernet doorbell
+ * Classify rule opcodes in E2/E3
*/
-struct eth_tx_doorbell {
-#if defined(__BIG_ENDIAN)
- u16 npackets;
- u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
- struct doorbell_hdr hdr;
-#elif defined(__LITTLE_ENDIAN)
- struct doorbell_hdr hdr;
- u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
- u16 npackets;
-#endif
+enum classify_rule {
+ CLASSIFY_RULE_OPCODE_MAC,
+ CLASSIFY_RULE_OPCODE_VLAN,
+ CLASSIFY_RULE_OPCODE_PAIR,
+ MAX_CLASSIFY_RULE
};
/*
- * client init fc data
+ * Classify rule types in E2/E3
*/
-struct client_init_fc_data {
- __le16 cqe_pause_thr_low;
- __le16 cqe_pause_thr_high;
- __le16 bd_pause_thr_low;
- __le16 bd_pause_thr_high;
- __le16 sge_pause_thr_low;
- __le16 sge_pause_thr_high;
- __le16 rx_cos_mask;
- u8 safc_group_num;
- u8 safc_group_en_flg;
- u8 traffic_type;
- u8 reserved0;
- __le16 reserved1;
- __le32 reserved2;
+enum classify_rule_action_type {
+ CLASSIFY_RULE_REMOVE,
+ CLASSIFY_RULE_ADD,
+ MAX_CLASSIFY_RULE_ACTION_TYPE
};
@@ -2615,8 +3135,12 @@ struct client_init_general_data {
u8 is_fcoe_flg;
u8 activate_flg;
u8 sp_client_id;
- __le16 reserved0;
- __le32 reserved1[2];
+ __le16 mtu;
+ u8 statistics_zero_flg;
+ u8 func_id;
+ u8 cos;
+ u8 traffic_type;
+ u32 reserved0;
};
@@ -2624,7 +3148,13 @@ struct client_init_general_data {
* client init rx data
*/
struct client_init_rx_data {
- u8 tpa_en_flg;
+ u8 tpa_en;
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4 (0x1<<0)
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4_SHIFT 0
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6 (0x1<<1)
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6_SHIFT 1
+#define CLIENT_INIT_RX_DATA_RESERVED5 (0x3F<<2)
+#define CLIENT_INIT_RX_DATA_RESERVED5_SHIFT 2
u8 vmqueue_mode_en_flg;
u8 extra_data_over_sgl_en_flg;
u8 cache_line_alignment_log_size;
@@ -2639,17 +3169,46 @@ struct client_init_rx_data {
u8 outer_vlan_removal_enable_flg;
u8 status_block_id;
u8 rx_sb_index_number;
- u8 reserved0[3];
- __le16 bd_buff_size;
+ u8 reserved0;
+ u8 max_tpa_queues;
+ u8 silent_vlan_removal_flg;
+ __le16 max_bytes_on_bd;
__le16 sge_buff_size;
- __le16 mtu;
+ u8 approx_mcast_engine_id;
+ u8 rss_engine_id;
struct regpair bd_page_base;
struct regpair sge_page_base;
struct regpair cqe_page_base;
u8 is_leading_rss;
u8 is_approx_mcast;
__le16 max_agg_size;
- __le32 reserved2[3];
+ __le16 state;
+#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL (0x1<<0)
+#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL_SHIFT 0
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL (0x1<<1)
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL_SHIFT 1
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED (0x1<<2)
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED_SHIFT 2
+#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL (0x1<<3)
+#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL_SHIFT 3
+#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL (0x1<<4)
+#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL_SHIFT 4
+#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL (0x1<<5)
+#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL_SHIFT 5
+#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN (0x1<<6)
+#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN_SHIFT 6
+#define CLIENT_INIT_RX_DATA_RESERVED2 (0x1FF<<7)
+#define CLIENT_INIT_RX_DATA_RESERVED2_SHIFT 7
+ __le16 cqe_pause_thr_low;
+ __le16 cqe_pause_thr_high;
+ __le16 bd_pause_thr_low;
+ __le16 bd_pause_thr_high;
+ __le16 sge_pause_thr_low;
+ __le16 sge_pause_thr_high;
+ __le16 rx_cos_mask;
+ __le16 silent_vlan_value;
+ __le16 silent_vlan_mask;
+ __le32 reserved6[2];
};
/*
@@ -2659,11 +3218,25 @@ struct client_init_tx_data {
u8 enforce_security_flg;
u8 tx_status_block_id;
u8 tx_sb_index_number;
- u8 reserved0;
- __le16 mtu;
- __le16 reserved1;
+ u8 tss_leading_client_id;
+ u8 tx_switching_flg;
+ u8 anti_spoofing_flg;
+ __le16 default_vlan;
struct regpair tx_bd_page_base;
- __le32 reserved2[2];
+ __le16 state;
+#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL (0x1<<0)
+#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL_SHIFT 0
+#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL (0x1<<1)
+#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL_SHIFT 1
+#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL (0x1<<2)
+#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL_SHIFT 2
+#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN (0x1<<3)
+#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN_SHIFT 3
+#define CLIENT_INIT_TX_DATA_RESERVED1 (0xFFF<<4)
+#define CLIENT_INIT_TX_DATA_RESERVED1_SHIFT 4
+ u8 default_vlan_flg;
+ u8 reserved2;
+ __le32 reserved3;
};
/*
@@ -2673,7 +3246,146 @@ struct client_init_ramrod_data {
struct client_init_general_data general;
struct client_init_rx_data rx;
struct client_init_tx_data tx;
- struct client_init_fc_data fc;
+};
+
+
+/*
+ * client update ramrod data
+ */
+struct client_update_ramrod_data {
+ u8 client_id;
+ u8 func_id;
+ u8 inner_vlan_removal_enable_flg;
+ u8 inner_vlan_removal_change_flg;
+ u8 outer_vlan_removal_enable_flg;
+ u8 outer_vlan_removal_change_flg;
+ u8 anti_spoofing_enable_flg;
+ u8 anti_spoofing_change_flg;
+ u8 activate_flg;
+ u8 activate_change_flg;
+ __le16 default_vlan;
+ u8 default_vlan_enable_flg;
+ u8 default_vlan_change_flg;
+ __le16 silent_vlan_value;
+ __le16 silent_vlan_mask;
+ u8 silent_vlan_removal_flg;
+ u8 silent_vlan_change_flg;
+ __le32 echo;
+};
+
+
+/*
+ * The eth storm context of Cstorm
+ */
+struct cstorm_eth_st_context {
+ u32 __reserved0[4];
+};
+
+
+struct double_regpair {
+ u32 regpair0_lo;
+ u32 regpair0_hi;
+ u32 regpair1_lo;
+ u32 regpair1_hi;
+};
+
+
+/*
+ * Ethernet address typesm used in ethernet tx BDs
+ */
+enum eth_addr_type {
+ UNKNOWN_ADDRESS,
+ UNICAST_ADDRESS,
+ MULTICAST_ADDRESS,
+ BROADCAST_ADDRESS,
+ MAX_ETH_ADDR_TYPE
+};
+
+
+/*
+ *
+ */
+struct eth_classify_cmd_header {
+ u8 cmd_general_data;
+#define ETH_CLASSIFY_CMD_HEADER_RX_CMD (0x1<<0)
+#define ETH_CLASSIFY_CMD_HEADER_RX_CMD_SHIFT 0
+#define ETH_CLASSIFY_CMD_HEADER_TX_CMD (0x1<<1)
+#define ETH_CLASSIFY_CMD_HEADER_TX_CMD_SHIFT 1
+#define ETH_CLASSIFY_CMD_HEADER_OPCODE (0x3<<2)
+#define ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT 2
+#define ETH_CLASSIFY_CMD_HEADER_IS_ADD (0x1<<4)
+#define ETH_CLASSIFY_CMD_HEADER_IS_ADD_SHIFT 4
+#define ETH_CLASSIFY_CMD_HEADER_RESERVED0 (0x7<<5)
+#define ETH_CLASSIFY_CMD_HEADER_RESERVED0_SHIFT 5
+ u8 func_id;
+ u8 client_id;
+ u8 reserved1;
+};
+
+
+/*
+ * header for eth classification config ramrod
+ */
+struct eth_classify_header {
+ u8 rule_cnt;
+ u8 reserved0;
+ __le16 reserved1;
+ __le32 echo;
+};
+
+
+/*
+ * Command for adding/removing a MAC classification rule
+ */
+struct eth_classify_mac_cmd {
+ struct eth_classify_cmd_header header;
+ __le32 reserved0;
+ __le16 mac_lsb;
+ __le16 mac_mid;
+ __le16 mac_msb;
+ __le16 reserved1;
+};
+
+
+/*
+ * Command for adding/removing a MAC-VLAN pair classification rule
+ */
+struct eth_classify_pair_cmd {
+ struct eth_classify_cmd_header header;
+ __le32 reserved0;
+ __le16 mac_lsb;
+ __le16 mac_mid;
+ __le16 mac_msb;
+ __le16 vlan;
+};
+
+
+/*
+ * Command for adding/removing a VLAN classification rule
+ */
+struct eth_classify_vlan_cmd {
+ struct eth_classify_cmd_header header;
+ __le32 reserved0;
+ __le32 reserved1;
+ __le16 reserved2;
+ __le16 vlan;
+};
+
+/*
+ * union for eth classification rule
+ */
+union eth_classify_rule_cmd {
+ struct eth_classify_mac_cmd mac;
+ struct eth_classify_vlan_cmd vlan;
+ struct eth_classify_pair_cmd pair;
+};
+
+/*
+ * parameters for eth classification configuration ramrod
+ */
+struct eth_classify_rules_ramrod_data {
+ struct eth_classify_header header;
+ union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
};
@@ -2681,8 +3393,45 @@ struct client_init_ramrod_data {
* The data contain client ID need to the ramrod
*/
struct eth_common_ramrod_data {
- u32 client_id;
- u32 reserved1;
+ __le32 client_id;
+ __le32 reserved1;
+};
+
+
+/*
+ * The eth storm context of Ustorm
+ */
+struct ustorm_eth_st_context {
+ u32 reserved0[52];
+};
+
+/*
+ * The eth storm context of Tstorm
+ */
+struct tstorm_eth_st_context {
+ u32 __reserved0[28];
+};
+
+/*
+ * The eth storm context of Xstorm
+ */
+struct xstorm_eth_st_context {
+ u32 reserved0[60];
+};
+
+/*
+ * Ethernet connection context
+ */
+struct eth_context {
+ struct ustorm_eth_st_context ustorm_st_context;
+ struct tstorm_eth_st_context tstorm_st_context;
+ struct xstorm_eth_ag_context xstorm_ag_context;
+ struct tstorm_eth_ag_context tstorm_ag_context;
+ struct cstorm_eth_ag_context cstorm_ag_context;
+ struct ustorm_eth_ag_context ustorm_ag_context;
+ struct timers_block_context timers_context;
+ struct xstorm_eth_st_context xstorm_st_context;
+ struct cstorm_eth_st_context cstorm_st_context;
};
@@ -2695,24 +3444,47 @@ union eth_sgl_or_raw_data {
};
/*
+ * eth FP end aggregation CQE parameters struct
+ */
+struct eth_end_agg_rx_cqe {
+ u8 type_error_flags;
+#define ETH_END_AGG_RX_CQE_TYPE (0x3<<0)
+#define ETH_END_AGG_RX_CQE_TYPE_SHIFT 0
+#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL (0x1<<2)
+#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL_SHIFT 2
+#define ETH_END_AGG_RX_CQE_RESERVED0 (0x1F<<3)
+#define ETH_END_AGG_RX_CQE_RESERVED0_SHIFT 3
+ u8 reserved1;
+ u8 queue_index;
+ u8 reserved2;
+ __le32 timestamp_delta;
+ __le16 num_of_coalesced_segs;
+ __le16 pkt_len;
+ u8 pure_ack_count;
+ u8 reserved3;
+ __le16 reserved4;
+ union eth_sgl_or_raw_data sgl_or_raw_data;
+ __le32 reserved5[8];
+};
+
+
+/*
* regular eth FP CQE parameters struct
*/
struct eth_fast_path_rx_cqe {
u8 type_error_flags;
-#define ETH_FAST_PATH_RX_CQE_TYPE (0x1<<0)
+#define ETH_FAST_PATH_RX_CQE_TYPE (0x3<<0)
#define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT 0
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<1)
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 1
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<2)
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 2
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<3)
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 3
-#define ETH_FAST_PATH_RX_CQE_START_FLG (0x1<<4)
-#define ETH_FAST_PATH_RX_CQE_START_FLG_SHIFT 4
-#define ETH_FAST_PATH_RX_CQE_END_FLG (0x1<<5)
-#define ETH_FAST_PATH_RX_CQE_END_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x3<<6)
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 6
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x1<<2)
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 2
+#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<3)
+#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 3
+#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<4)
+#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 4
+#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<5)
+#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 5
+#define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6)
+#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6
u8 status_flags;
#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
@@ -2726,39 +3498,108 @@ struct eth_fast_path_rx_cqe {
#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6
#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7)
#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7
- u8 placement_offset;
u8 queue_index;
+ u8 placement_offset;
__le32 rss_hash_result;
__le16 vlan_tag;
__le16 pkt_len;
__le16 len_on_bd;
struct parsing_flags pars_flags;
union eth_sgl_or_raw_data sgl_or_raw_data;
+ __le32 reserved1[8];
};
/*
- * The data for RSS setup ramrod
+ * Command for setting classification flags for a client
+ */
+struct eth_filter_rules_cmd {
+ u8 cmd_general_data;
+#define ETH_FILTER_RULES_CMD_RX_CMD (0x1<<0)
+#define ETH_FILTER_RULES_CMD_RX_CMD_SHIFT 0
+#define ETH_FILTER_RULES_CMD_TX_CMD (0x1<<1)
+#define ETH_FILTER_RULES_CMD_TX_CMD_SHIFT 1
+#define ETH_FILTER_RULES_CMD_RESERVED0 (0x3F<<2)
+#define ETH_FILTER_RULES_CMD_RESERVED0_SHIFT 2
+ u8 func_id;
+ u8 client_id;
+ u8 reserved1;
+ __le16 state;
+#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL (0x1<<0)
+#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL_SHIFT 0
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL (0x1<<1)
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL_SHIFT 1
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED (0x1<<2)
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED_SHIFT 2
+#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL (0x1<<3)
+#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL_SHIFT 3
+#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL (0x1<<4)
+#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL_SHIFT 4
+#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL (0x1<<5)
+#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL_SHIFT 5
+#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN (0x1<<6)
+#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN_SHIFT 6
+#define ETH_FILTER_RULES_CMD_RESERVED2 (0x1FF<<7)
+#define ETH_FILTER_RULES_CMD_RESERVED2_SHIFT 7
+ __le16 reserved3;
+ struct regpair reserved4;
+};
+
+
+/*
+ * parameters for eth classification filters ramrod
+ */
+struct eth_filter_rules_ramrod_data {
+ struct eth_classify_header header;
+ struct eth_filter_rules_cmd rules[FILTER_RULES_COUNT];
+};
+
+
+/*
+ * parameters for eth classification configuration ramrod
+ */
+struct eth_general_rules_ramrod_data {
+ struct eth_classify_header header;
+ union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
+};
+
+
+/*
+ * The data for Halt ramrod
*/
struct eth_halt_ramrod_data {
- u32 client_id;
- u32 reserved0;
+ __le32 client_id;
+ __le32 reserved0;
};
+
/*
- * The data for statistics query ramrod
+ * Command for setting multicast classification for a client
*/
-struct common_query_ramrod_data {
-#if defined(__BIG_ENDIAN)
- u8 reserved0;
- u8 collect_port;
- u16 drv_counter;
-#elif defined(__LITTLE_ENDIAN)
- u16 drv_counter;
- u8 collect_port;
- u8 reserved0;
-#endif
- u32 ctr_id_vector;
+struct eth_multicast_rules_cmd {
+ u8 cmd_general_data;
+#define ETH_MULTICAST_RULES_CMD_RX_CMD (0x1<<0)
+#define ETH_MULTICAST_RULES_CMD_RX_CMD_SHIFT 0
+#define ETH_MULTICAST_RULES_CMD_TX_CMD (0x1<<1)
+#define ETH_MULTICAST_RULES_CMD_TX_CMD_SHIFT 1
+#define ETH_MULTICAST_RULES_CMD_IS_ADD (0x1<<2)
+#define ETH_MULTICAST_RULES_CMD_IS_ADD_SHIFT 2
+#define ETH_MULTICAST_RULES_CMD_RESERVED0 (0x1F<<3)
+#define ETH_MULTICAST_RULES_CMD_RESERVED0_SHIFT 3
+ u8 func_id;
+ u8 bin_id;
+ u8 engine_id;
+ __le32 reserved2;
+ struct regpair reserved3;
+};
+
+
+/*
+ * parameters for multicast classification ramrod
+ */
+struct eth_multicast_rules_ramrod_data {
+ struct eth_classify_header header;
+ struct eth_multicast_rules_cmd rules[MULTICAST_RULES_COUNT];
};
@@ -2779,16 +3620,86 @@ union eth_ramrod_data {
/*
+ * RSS toeplitz hash type, as reported in CQE
+ */
+enum eth_rss_hash_type {
+ DEFAULT_HASH_TYPE,
+ IPV4_HASH_TYPE,
+ TCP_IPV4_HASH_TYPE,
+ IPV6_HASH_TYPE,
+ TCP_IPV6_HASH_TYPE,
+ VLAN_PRI_HASH_TYPE,
+ E1HOV_PRI_HASH_TYPE,
+ DSCP_HASH_TYPE,
+ MAX_ETH_RSS_HASH_TYPE
+};
+
+
+/*
+ * Ethernet RSS mode
+ */
+enum eth_rss_mode {
+ ETH_RSS_MODE_DISABLED,
+ ETH_RSS_MODE_REGULAR,
+ ETH_RSS_MODE_VLAN_PRI,
+ ETH_RSS_MODE_E1HOV_PRI,
+ ETH_RSS_MODE_IP_DSCP,
+ MAX_ETH_RSS_MODE
+};
+
+
+/*
+ * parameters for RSS update ramrod (E2)
+ */
+struct eth_rss_update_ramrod_data {
+ u8 rss_engine_id;
+ u8 capabilities;
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY (0x1<<0)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY_SHIFT 0
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY (0x1<<1)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY_SHIFT 1
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY (0x1<<2)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY_SHIFT 2
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY (0x1<<3)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY_SHIFT 3
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY (0x1<<4)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY_SHIFT 4
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY (0x1<<5)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY_SHIFT 5
+#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<6)
+#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 6
+#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0 (0x1<<7)
+#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0_SHIFT 7
+ u8 rss_result_mask;
+ u8 rss_mode;
+ __le32 __reserved2;
+ u8 indirection_table[T_ETH_INDIRECTION_TABLE_SIZE];
+ __le32 rss_key[T_ETH_RSS_KEY];
+ __le32 echo;
+ __le32 reserved3;
+};
+
+
+/*
+ * The eth Rx Buffer Descriptor
+ */
+struct eth_rx_bd {
+ __le32 addr_lo;
+ __le32 addr_hi;
+};
+
+
+/*
* Eth Rx Cqe structure- general structure for ramrods
*/
struct common_ramrod_eth_rx_cqe {
u8 ramrod_type;
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x1<<0)
+#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x3<<0)
#define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<1)
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 1
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x3F<<2)
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 2
+#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<2)
+#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 2
+#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x1F<<3)
+#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 3
u8 conn_type;
__le16 reserved1;
__le32 conn_and_cmd_data;
@@ -2797,7 +3708,8 @@ struct common_ramrod_eth_rx_cqe {
#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID (0xFF<<24)
#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT 24
struct ramrod_data protocol_data;
- __le32 reserved2[4];
+ __le32 echo;
+ __le32 reserved2[11];
};
/*
@@ -2806,7 +3718,7 @@ struct common_ramrod_eth_rx_cqe {
struct eth_rx_cqe_next_page {
__le32 addr_lo;
__le32 addr_hi;
- __le32 reserved[6];
+ __le32 reserved[14];
};
/*
@@ -2816,6 +3728,38 @@ union eth_rx_cqe {
struct eth_fast_path_rx_cqe fast_path_cqe;
struct common_ramrod_eth_rx_cqe ramrod_cqe;
struct eth_rx_cqe_next_page next_page_cqe;
+ struct eth_end_agg_rx_cqe end_agg_cqe;
+};
+
+
+/*
+ * Values for RX ETH CQE type field
+ */
+enum eth_rx_cqe_type {
+ RX_ETH_CQE_TYPE_ETH_FASTPATH,
+ RX_ETH_CQE_TYPE_ETH_RAMROD,
+ RX_ETH_CQE_TYPE_ETH_START_AGG,
+ RX_ETH_CQE_TYPE_ETH_STOP_AGG,
+ MAX_ETH_RX_CQE_TYPE
+};
+
+
+/*
+ * Type of SGL/Raw field in ETH RX fast path CQE
+ */
+enum eth_rx_fp_sel {
+ ETH_FP_CQE_REGULAR,
+ ETH_FP_CQE_RAW,
+ MAX_ETH_RX_FP_SEL
+};
+
+
+/*
+ * The eth Rx SGE Descriptor
+ */
+struct eth_rx_sge {
+ __le32 addr_lo;
+ __le32 addr_hi;
};
@@ -2837,14 +3781,18 @@ struct spe_hdr {
};
/*
- * Ethernet slow path element
+ * specific data for ethernet slow path element
*/
union eth_specific_data {
u8 protocol_data[8];
+ struct regpair client_update_ramrod_data;
struct regpair client_init_ramrod_init_data;
struct eth_halt_ramrod_data halt_ramrod_data;
struct regpair update_data_addr;
struct eth_common_ramrod_data common_ramrod_data;
+ struct regpair classify_cfg_addr;
+ struct regpair filter_cfg_addr;
+ struct regpair mcast_cfg_addr;
};
/*
@@ -2857,94 +3805,202 @@ struct eth_spe {
/*
- * array of 13 bds as appears in the eth xstorm context
+ * Ethernet command ID for slow path elements
*/
-struct eth_tx_bds_array {
- union eth_tx_bd_types bds[13];
+enum eth_spqe_cmd_id {
+ RAMROD_CMD_ID_ETH_UNUSED,
+ RAMROD_CMD_ID_ETH_CLIENT_SETUP,
+ RAMROD_CMD_ID_ETH_HALT,
+ RAMROD_CMD_ID_ETH_FORWARD_SETUP,
+ RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP,
+ RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
+ RAMROD_CMD_ID_ETH_EMPTY,
+ RAMROD_CMD_ID_ETH_TERMINATE,
+ RAMROD_CMD_ID_ETH_TPA_UPDATE,
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES,
+ RAMROD_CMD_ID_ETH_FILTER_RULES,
+ RAMROD_CMD_ID_ETH_MULTICAST_RULES,
+ RAMROD_CMD_ID_ETH_RSS_UPDATE,
+ RAMROD_CMD_ID_ETH_SET_MAC,
+ MAX_ETH_SPQE_CMD_ID
};
/*
- * Common configuration parameters per function in Tstorm
+ * eth tpa update command
*/
-struct tstorm_eth_function_common_config {
-#if defined(__BIG_ENDIAN)
- u8 reserved1;
- u8 rss_result_mask;
- u16 config_flags;
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 config_flags;
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
- u8 rss_result_mask;
- u8 reserved1;
-#endif
- u16 vlan_id[2];
+enum eth_tpa_update_command {
+ TPA_UPDATE_NONE_COMMAND,
+ TPA_UPDATE_ENABLE_COMMAND,
+ TPA_UPDATE_DISABLE_COMMAND,
+ MAX_ETH_TPA_UPDATE_COMMAND
};
+
/*
- * RSS idirection table update configuration
+ * Tx regular BD structure
*/
-struct rss_update_config {
-#if defined(__BIG_ENDIAN)
- u16 toe_rss_bitmap;
- u16 flags;
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
-#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
-#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
-#elif defined(__LITTLE_ENDIAN)
- u16 flags;
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
-#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
-#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
- u16 toe_rss_bitmap;
-#endif
- u32 reserved1;
+struct eth_tx_bd {
+ __le32 addr_lo;
+ __le32 addr_hi;
+ __le16 total_pkt_bytes;
+ __le16 nbytes;
+ u8 reserved[4];
+};
+
+
+/*
+ * structure for easy accessibility to assembler
+ */
+struct eth_tx_bd_flags {
+ u8 as_bitfield;
+#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0)
+#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0
+#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1)
+#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1
+#define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2)
+#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2
+#define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
+#define ETH_TX_BD_FLAGS_START_BD_SHIFT 4
+#define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5)
+#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5
+#define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6)
+#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6
+#define ETH_TX_BD_FLAGS_IPV6 (0x1<<7)
+#define ETH_TX_BD_FLAGS_IPV6_SHIFT 7
+};
+
+/*
+ * The eth Tx Buffer Descriptor
+ */
+struct eth_tx_start_bd {
+ __le32 addr_lo;
+ __le32 addr_hi;
+ __le16 nbd;
+ __le16 nbytes;
+ __le16 vlan_or_ethertype;
+ struct eth_tx_bd_flags bd_flags;
+ u8 general_data;
+#define ETH_TX_START_BD_HDR_NBDS (0xF<<0)
+#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
+#define ETH_TX_START_BD_FORCE_VLAN_MODE (0x1<<4)
+#define ETH_TX_START_BD_FORCE_VLAN_MODE_SHIFT 4
+#define ETH_TX_START_BD_RESREVED (0x1<<5)
+#define ETH_TX_START_BD_RESREVED_SHIFT 5
+#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
+#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
+};
+
+/*
+ * Tx parsing BD structure for ETH E1/E1h
+ */
+struct eth_tx_parse_bd_e1x {
+ u8 global_data;
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0)
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7
+ u8 tcp_flags;
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0)
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1)
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1
+#define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2)
+#define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3)
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7
+ u8 ip_hlen_w;
+ s8 reserved;
+ __le16 total_hlen_w;
+ __le16 tcp_pseudo_csum;
+ __le16 lso_mss;
+ __le16 ip_id;
+ __le32 tcp_send_seq;
+};
+
+/*
+ * Tx parsing BD structure for ETH E2
+ */
+struct eth_tx_parse_bd_e2 {
+ __le16 dst_mac_addr_lo;
+ __le16 dst_mac_addr_mid;
+ __le16 dst_mac_addr_hi;
+ __le16 src_mac_addr_lo;
+ __le16 src_mac_addr_mid;
+ __le16 src_mac_addr_hi;
+ __le32 parsing_data;
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
+#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
+#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
+};
+
+/*
+ * The last BD in the BD memory will hold a pointer to the next BD memory
+ */
+struct eth_tx_next_bd {
+ __le32 addr_lo;
+ __le32 addr_hi;
+ u8 reserved[8];
+};
+
+/*
+ * union for 4 Bd types
+ */
+union eth_tx_bd_types {
+ struct eth_tx_start_bd start_bd;
+ struct eth_tx_bd reg_bd;
+ struct eth_tx_parse_bd_e1x parse_bd_e1x;
+ struct eth_tx_parse_bd_e2 parse_bd_e2;
+ struct eth_tx_next_bd next_bd;
+};
+
+/*
+ * array of 13 bds as appears in the eth xstorm context
+ */
+struct eth_tx_bds_array {
+ union eth_tx_bd_types bds[13];
};
+
/*
- * parameters for eth update ramrod
+ * VLAN mode on TX BDs
*/
-struct eth_update_ramrod_data {
- struct tstorm_eth_function_common_config func_config;
- u8 indirectionTable[128];
- struct rss_update_config rss_config;
+enum eth_tx_vlan_type {
+ X_ETH_NO_VLAN,
+ X_ETH_OUTBAND_VLAN,
+ X_ETH_INBAND_VLAN,
+ X_ETH_FW_ADDED_VLAN,
+ MAX_ETH_TX_VLAN_TYPE
+};
+
+
+/*
+ * Ethernet VLAN filtering mode in E1x
+ */
+enum eth_vlan_filter_mode {
+ ETH_VLAN_FILTER_ANY_VLAN,
+ ETH_VLAN_FILTER_SPECIFIC_VLAN,
+ ETH_VLAN_FILTER_CLASSIFY,
+ MAX_ETH_VLAN_FILTER_MODE
};
@@ -2954,9 +4010,8 @@ struct eth_update_ramrod_data {
struct mac_configuration_hdr {
u8 length;
u8 offset;
- u16 client_id;
- u16 echo;
- u16 reserved1;
+ __le16 client_id;
+ __le32 echo;
};
/*
@@ -2981,8 +4036,8 @@ struct mac_configuration_entry {
#define MAC_CONFIGURATION_ENTRY_BROADCAST_SHIFT 5
#define MAC_CONFIGURATION_ENTRY_RESERVED1 (0x3<<6)
#define MAC_CONFIGURATION_ENTRY_RESERVED1_SHIFT 6
- u16 reserved0;
- u32 clients_bit_vector;
+ __le16 reserved0;
+ __le32 clients_bit_vector;
};
/*
@@ -2995,6 +4050,36 @@ struct mac_configuration_cmd {
/*
+ * Set-MAC command type (in E1x)
+ */
+enum set_mac_action_type {
+ T_ETH_MAC_COMMAND_INVALIDATE,
+ T_ETH_MAC_COMMAND_SET,
+ MAX_SET_MAC_ACTION_TYPE
+};
+
+
+/*
+ * tpa update ramrod data
+ */
+struct tpa_update_ramrod_data {
+ u8 update_ipv4;
+ u8 update_ipv6;
+ u8 client_id;
+ u8 max_tpa_queues;
+ u8 max_sges_for_packet;
+ u8 complete_on_both_clients;
+ __le16 reserved1;
+ __le16 sge_buff_size;
+ __le16 max_agg_size;
+ __le32 sge_page_base_lo;
+ __le32 sge_page_base_hi;
+ __le16 sge_pause_thr_low;
+ __le16 sge_pause_thr_high;
+};
+
+
+/*
* approximate-match multicast filtering for E1H per function in Tstorm
*/
struct tstorm_eth_approximate_match_multicast_filtering {
@@ -3003,35 +4088,50 @@ struct tstorm_eth_approximate_match_multicast_filtering {
/*
+ * Common configuration parameters per function in Tstorm
+ */
+struct tstorm_eth_function_common_config {
+ __le16 config_flags;
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<7)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 7
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0xFF<<8)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 8
+ u8 rss_result_mask;
+ u8 reserved1;
+ __le16 vlan_id[2];
+};
+
+
+/*
* MAC filtering configuration parameters per port in Tstorm
*/
struct tstorm_eth_mac_filter_config {
- u32 ucast_drop_all;
- u32 ucast_accept_all;
- u32 mcast_drop_all;
- u32 mcast_accept_all;
- u32 bcast_drop_all;
- u32 bcast_accept_all;
- u32 vlan_filter[2];
- u32 unmatched_unicast;
- u32 reserved;
+ __le32 ucast_drop_all;
+ __le32 ucast_accept_all;
+ __le32 mcast_drop_all;
+ __le32 mcast_accept_all;
+ __le32 bcast_accept_all;
+ __le32 vlan_filter[2];
+ __le32 unmatched_unicast;
};
/*
- * common flag to indicate existence of TPA.
+ * tx only queue init ramrod data
*/
-struct tstorm_eth_tpa_exist {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 reserved0;
- u8 tpa_exist;
-#elif defined(__LITTLE_ENDIAN)
- u8 tpa_exist;
- u8 reserved0;
- u16 reserved1;
-#endif
- u32 reserved2;
+struct tx_queue_init_ramrod_data {
+ struct client_init_general_data general;
+ struct client_init_tx_data tx;
};
@@ -3061,10 +4161,8 @@ struct ustorm_eth_rx_producers {
*/
struct cfc_del_event_data {
u32 cid;
- u8 error;
- u8 reserved0;
- u16 reserved1;
- u32 reserved2;
+ u32 reserved0;
+ u32 reserved1;
};
@@ -3072,22 +4170,18 @@ struct cfc_del_event_data {
* per-port SAFC demo variables
*/
struct cmng_flags_per_port {
- u8 con_number[NUM_OF_PROTOCOLS];
u32 cmng_enables;
#define CMNG_FLAGS_PER_PORT_FAIRNESS_VN (0x1<<0)
#define CMNG_FLAGS_PER_PORT_FAIRNESS_VN_SHIFT 0
#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN (0x1<<1)
#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN_SHIFT 1
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_PROTOCOL (0x1<<2)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_PROTOCOL_SHIFT 2
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL (0x1<<3)
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL_SHIFT 3
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<4)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 4
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<5)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 5
-#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0x3FFFFFF<<6)
-#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 6
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<2)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 2
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<3)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 3
+#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0xFFFFFFF<<4)
+#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 4
+ u32 __reserved1;
};
@@ -3106,6 +4200,7 @@ struct fairness_vars_per_port {
u32 upper_bound;
u32 fair_threshold;
u32 fairness_timeout;
+ u32 reserved0;
};
/*
@@ -3122,65 +4217,65 @@ struct safc_struct_per_port {
u16 __reserved1;
#endif
u8 cos_to_traffic_types[MAX_COS_NUMBER];
- u32 __reserved2;
u16 cos_to_pause_mask[NUM_OF_SAFC_BITS];
};
/*
- * per-port PFC variables
+ * Per-port congestion management variables
*/
-struct pfc_struct_per_port {
- u8 priority_to_traffic_types[MAX_PFC_PRIORITIES];
-#if defined(__BIG_ENDIAN)
- u16 pfc_pause_quanta_in_nanosec;
- u8 __reserved0;
- u8 priority_non_pausable_mask;
-#elif defined(__LITTLE_ENDIAN)
- u8 priority_non_pausable_mask;
- u8 __reserved0;
- u16 pfc_pause_quanta_in_nanosec;
-#endif
+struct cmng_struct_per_port {
+ struct rate_shaping_vars_per_port rs_vars;
+ struct fairness_vars_per_port fair_vars;
+ struct safc_struct_per_port safc_vars;
+ struct cmng_flags_per_port flags;
};
+
/*
- * Priority and cos
+ * Protocol-common command ID for slow path elements
*/
-struct priority_cos {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 cos;
- u8 priority;
-#elif defined(__LITTLE_ENDIAN)
- u8 priority;
- u8 cos;
- u16 reserved1;
-#endif
- u32 reserved2;
+enum common_spqe_cmd_id {
+ RAMROD_CMD_ID_COMMON_UNUSED,
+ RAMROD_CMD_ID_COMMON_FUNCTION_START,
+ RAMROD_CMD_ID_COMMON_FUNCTION_STOP,
+ RAMROD_CMD_ID_COMMON_CFC_DEL,
+ RAMROD_CMD_ID_COMMON_CFC_DEL_WB,
+ RAMROD_CMD_ID_COMMON_STAT_QUERY,
+ RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
+ RAMROD_CMD_ID_COMMON_START_TRAFFIC,
+ RAMROD_CMD_ID_COMMON_RESERVED1,
+ RAMROD_CMD_ID_COMMON_RESERVED2,
+ MAX_COMMON_SPQE_CMD_ID
};
+
/*
- * Per-port congestion management variables
+ * Per-protocol connection types
*/
-struct cmng_struct_per_port {
- struct rate_shaping_vars_per_port rs_vars;
- struct fairness_vars_per_port fair_vars;
- struct safc_struct_per_port safc_vars;
- struct pfc_struct_per_port pfc_vars;
-#if defined(__BIG_ENDIAN)
- u16 __reserved1;
- u8 dcb_enabled;
- u8 llfc_mode;
-#elif defined(__LITTLE_ENDIAN)
- u8 llfc_mode;
- u8 dcb_enabled;
- u16 __reserved1;
-#endif
- struct priority_cos
- traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
- struct cmng_flags_per_port flags;
+enum connection_type {
+ ETH_CONNECTION_TYPE,
+ TOE_CONNECTION_TYPE,
+ RDMA_CONNECTION_TYPE,
+ ISCSI_CONNECTION_TYPE,
+ FCOE_CONNECTION_TYPE,
+ RESERVED_CONNECTION_TYPE_0,
+ RESERVED_CONNECTION_TYPE_1,
+ RESERVED_CONNECTION_TYPE_2,
+ NONE_CONNECTION_TYPE,
+ MAX_CONNECTION_TYPE
};
+/*
+ * Cos modes
+ */
+enum cos_mode {
+ OVERRIDE_COS,
+ STATIC_COS,
+ FW_WRR,
+ MAX_COS_MODE
+};
+
/*
* Dynamic HC counters set by the driver
@@ -3197,126 +4292,174 @@ struct cstorm_queue_zone_data {
struct regpair reserved[2];
};
+
/*
- * Dynamic host coalescing init parameters
+ * Vf-PF channel data in cstorm ram (non-triggered zone)
*/
-struct dynamic_hc_config {
- u32 threshold[3];
- u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
- u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
- u8 hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES];
- u8 hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES];
- u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
+struct vf_pf_channel_zone_data {
+ u32 msg_addr_lo;
+ u32 msg_addr_hi;
};
-
/*
- * Protocol-common statistics collected by the Xstorm (per client)
+ * zone for VF non-triggered data
*/
-struct xstorm_per_client_stats {
- __le32 reserved0;
- __le32 unicast_pkts_sent;
- struct regpair unicast_bytes_sent;
- struct regpair multicast_bytes_sent;
- __le32 multicast_pkts_sent;
- __le32 broadcast_pkts_sent;
- struct regpair broadcast_bytes_sent;
- __le16 stats_counter;
- __le16 reserved1;
- __le32 reserved2;
+struct non_trigger_vf_zone {
+ struct vf_pf_channel_zone_data vf_pf_channel;
};
/*
- * Common statistics collected by the Xstorm (per port)
+ * Vf-PF channel trigger zone in cstorm ram
*/
-struct xstorm_common_stats {
- struct xstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
+struct vf_pf_channel_zone_trigger {
+ u8 addr_valid;
};
/*
- * Protocol-common statistics collected by the Tstorm (per port)
+ * zone that triggers the in-bound interrupt
*/
-struct tstorm_per_port_stats {
- __le32 mac_filter_discard;
- __le32 xxoverflow_discard;
- __le32 brb_truncate_discard;
- __le32 mac_discard;
+struct trigger_vf_zone {
+#if defined(__BIG_ENDIAN)
+ u16 reserved1;
+ u8 reserved0;
+ struct vf_pf_channel_zone_trigger vf_pf_channel;
+#elif defined(__LITTLE_ENDIAN)
+ struct vf_pf_channel_zone_trigger vf_pf_channel;
+ u8 reserved0;
+ u16 reserved1;
+#endif
+ u32 reserved2;
};
/*
- * Protocol-common statistics collected by the Tstorm (per client)
+ * zone B per-VF data
*/
-struct tstorm_per_client_stats {
- struct regpair rcv_unicast_bytes;
- struct regpair rcv_broadcast_bytes;
- struct regpair rcv_multicast_bytes;
- struct regpair rcv_error_bytes;
- __le32 checksum_discard;
- __le32 packets_too_big_discard;
- __le32 rcv_unicast_pkts;
- __le32 rcv_broadcast_pkts;
- __le32 rcv_multicast_pkts;
- __le32 no_buff_discard;
- __le32 ttl0_discard;
- __le16 stats_counter;
- __le16 reserved0;
+struct cstorm_vf_zone_data {
+ struct non_trigger_vf_zone non_trigger;
+ struct trigger_vf_zone trigger;
};
+
/*
- * Protocol-common statistics collected by the Tstorm
+ * Dynamic host coalescing init parameters, per state machine
*/
-struct tstorm_common_stats {
- struct tstorm_per_port_stats port_statistics;
- struct tstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
+struct dynamic_hc_sm_config {
+ u32 threshold[3];
+ u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
};
/*
- * Protocol-common statistics collected by the Ustorm (per client)
+ * Dynamic host coalescing init parameters
*/
-struct ustorm_per_client_stats {
- struct regpair ucast_no_buff_bytes;
- struct regpair mcast_no_buff_bytes;
- struct regpair bcast_no_buff_bytes;
- __le32 ucast_no_buff_pkts;
- __le32 mcast_no_buff_pkts;
- __le32 bcast_no_buff_pkts;
- __le16 stats_counter;
- __le16 reserved0;
+struct dynamic_hc_config {
+ struct dynamic_hc_sm_config sm_config[HC_SB_MAX_SM];
+};
+
+
+struct e2_integ_data {
+#if defined(__BIG_ENDIAN)
+ u8 flags;
+#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
+#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
+#define E2_INTEG_DATA_LB_TX (0x1<<1)
+#define E2_INTEG_DATA_LB_TX_SHIFT 1
+#define E2_INTEG_DATA_COS_TX (0x1<<2)
+#define E2_INTEG_DATA_COS_TX_SHIFT 2
+#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
+#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
+#define E2_INTEG_DATA_RESERVED (0x7<<5)
+#define E2_INTEG_DATA_RESERVED_SHIFT 5
+ u8 cos;
+ u8 voq;
+ u8 pbf_queue;
+#elif defined(__LITTLE_ENDIAN)
+ u8 pbf_queue;
+ u8 voq;
+ u8 cos;
+ u8 flags;
+#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
+#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
+#define E2_INTEG_DATA_LB_TX (0x1<<1)
+#define E2_INTEG_DATA_LB_TX_SHIFT 1
+#define E2_INTEG_DATA_COS_TX (0x1<<2)
+#define E2_INTEG_DATA_COS_TX_SHIFT 2
+#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
+#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
+#define E2_INTEG_DATA_RESERVED (0x7<<5)
+#define E2_INTEG_DATA_RESERVED_SHIFT 5
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 reserved3;
+ u8 reserved2;
+ u8 ramEn;
+#elif defined(__LITTLE_ENDIAN)
+ u8 ramEn;
+ u8 reserved2;
+ u16 reserved3;
+#endif
};
+
/*
- * Protocol-common statistics collected by the Ustorm
+ * set mac event data
*/
-struct ustorm_common_stats {
- struct ustorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
+struct eth_event_data {
+ u32 echo;
+ u32 reserved0;
+ u32 reserved1;
};
+
/*
- * Eth statistics query structure for the eth_stats_query ramrod
+ * pf-vf event data
*/
-struct eth_stats_query {
- struct xstorm_common_stats xstorm_common;
- struct tstorm_common_stats tstorm_common;
- struct ustorm_common_stats ustorm_common;
+struct vf_pf_event_data {
+ u8 vf_id;
+ u8 reserved0;
+ u16 reserved1;
+ u32 msg_addr_lo;
+ u32 msg_addr_hi;
};
+/*
+ * VF FLR event data
+ */
+struct vf_flr_event_data {
+ u8 vf_id;
+ u8 reserved0;
+ u16 reserved1;
+ u32 reserved2;
+ u32 reserved3;
+};
/*
- * set mac event data
+ * malicious VF event data
*/
-struct set_mac_event_data {
- u16 echo;
- u16 reserved0;
- u32 reserved1;
+struct malicious_vf_event_data {
+ u8 vf_id;
+ u8 reserved0;
+ u16 reserved1;
u32 reserved2;
+ u32 reserved3;
};
/*
* union for all event ring message types
*/
union event_data {
- struct set_mac_event_data set_mac_event;
+ struct vf_pf_event_data vf_pf_event;
+ struct eth_event_data eth_event;
struct cfc_del_event_data cfc_del_event;
+ struct vf_flr_event_data vf_flr_event;
+ struct malicious_vf_event_data malicious_vf_event;
};
@@ -3343,7 +4486,7 @@ struct event_ring_data {
*/
struct event_ring_msg {
u8 opcode;
- u8 reserved0;
+ u8 error;
u16 reserved1;
union event_data data;
};
@@ -3366,32 +4509,82 @@ union event_ring_elem {
/*
+ * Common event ring opcodes
+ */
+enum event_ring_opcode {
+ EVENT_RING_OPCODE_VF_PF_CHANNEL,
+ EVENT_RING_OPCODE_FUNCTION_START,
+ EVENT_RING_OPCODE_FUNCTION_STOP,
+ EVENT_RING_OPCODE_CFC_DEL,
+ EVENT_RING_OPCODE_CFC_DEL_WB,
+ EVENT_RING_OPCODE_STAT_QUERY,
+ EVENT_RING_OPCODE_STOP_TRAFFIC,
+ EVENT_RING_OPCODE_START_TRAFFIC,
+ EVENT_RING_OPCODE_VF_FLR,
+ EVENT_RING_OPCODE_MALICIOUS_VF,
+ EVENT_RING_OPCODE_FORWARD_SETUP,
+ EVENT_RING_OPCODE_RSS_UPDATE_RULES,
+ EVENT_RING_OPCODE_RESERVED1,
+ EVENT_RING_OPCODE_RESERVED2,
+ EVENT_RING_OPCODE_SET_MAC,
+ EVENT_RING_OPCODE_CLASSIFICATION_RULES,
+ EVENT_RING_OPCODE_FILTERS_RULES,
+ EVENT_RING_OPCODE_MULTICAST_RULES,
+ MAX_EVENT_RING_OPCODE
+};
+
+
+/*
+ * Modes for fairness algorithm
+ */
+enum fairness_mode {
+ FAIRNESS_COS_WRR_MODE,
+ FAIRNESS_COS_ETS_MODE,
+ MAX_FAIRNESS_MODE
+};
+
+
+/*
* per-vnic fairness variables
*/
struct fairness_vars_per_vn {
u32 cos_credit_delta[MAX_COS_NUMBER];
- u32 protocol_credit_delta[NUM_OF_PROTOCOLS];
u32 vn_credit_delta;
u32 __reserved0;
};
/*
+ * Priority and cos
+ */
+struct priority_cos {
+ u8 priority;
+ u8 cos;
+ __le16 reserved1;
+};
+
+/*
* The data for flow control configuration
*/
struct flow_control_configuration {
- struct priority_cos
- traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 dcb_version;
- u8 dcb_enabled;
-#elif defined(__LITTLE_ENDIAN)
+ struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
u8 dcb_enabled;
u8 dcb_version;
- u16 reserved1;
-#endif
- u32 reserved2;
+ u8 dont_add_pri_0_en;
+ u8 reserved1;
+ __le32 reserved2;
+};
+
+
+/*
+ *
+ */
+struct function_start_data {
+ __le16 function_mode;
+ __le16 sd_vlan_tag;
+ u16 reserved;
+ u8 path_id;
+ u8 network_cos_mode;
};
@@ -3504,13 +4697,13 @@ struct hc_sb_data {
struct pci_entity p_func;
#if defined(__BIG_ENDIAN)
u8 rsrv0;
+ u8 state;
u8 dhc_qzone_id;
- u8 __dynamic_hc_level;
u8 same_igu_sb_1b;
#elif defined(__LITTLE_ENDIAN)
u8 same_igu_sb_1b;
- u8 __dynamic_hc_level;
u8 dhc_qzone_id;
+ u8 state;
u8 rsrv0;
#endif
struct regpair rsrv1[2];
@@ -3518,18 +4711,30 @@ struct hc_sb_data {
/*
+ * Segment types for host coaslescing
+ */
+enum hc_segment {
+ HC_REGULAR_SEGMENT,
+ HC_DEFAULT_SEGMENT,
+ MAX_HC_SEGMENT
+};
+
+
+/*
* The fast-path status block meta-data
*/
struct hc_sp_status_block_data {
struct regpair host_sb_addr;
#if defined(__BIG_ENDIAN)
- u16 rsrv;
+ u8 rsrv1;
+ u8 state;
u8 igu_seg_id;
u8 igu_sb_id;
#elif defined(__LITTLE_ENDIAN)
u8 igu_sb_id;
u8 igu_seg_id;
- u16 rsrv;
+ u8 state;
+ u8 rsrv1;
#endif
struct pci_entity p_func;
};
@@ -3554,6 +4759,129 @@ struct hc_status_block_data_e2 {
/*
+ * IGU block operartion modes (in Everest2)
+ */
+enum igu_mode {
+ HC_IGU_BC_MODE,
+ HC_IGU_NBC_MODE,
+ MAX_IGU_MODE
+};
+
+
+/*
+ * IP versions
+ */
+enum ip_ver {
+ IP_V4,
+ IP_V6,
+ MAX_IP_VER
+};
+
+
+/*
+ * Multi-function modes
+ */
+enum mf_mode {
+ SINGLE_FUNCTION,
+ MULTI_FUNCTION_SD,
+ MULTI_FUNCTION_SI,
+ MULTI_FUNCTION_RESERVED,
+ MAX_MF_MODE
+};
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per pf)
+ */
+struct tstorm_per_pf_stats {
+ struct regpair rcv_error_bytes;
+};
+
+/*
+ *
+ */
+struct per_pf_stats {
+ struct tstorm_per_pf_stats tstorm_pf_statistics;
+};
+
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per port)
+ */
+struct tstorm_per_port_stats {
+ __le32 mac_discard;
+ __le32 mac_filter_discard;
+ __le32 brb_truncate_discard;
+ __le32 mf_tag_discard;
+ __le32 packet_drop;
+ __le32 reserved;
+};
+
+/*
+ *
+ */
+struct per_port_stats {
+ struct tstorm_per_port_stats tstorm_port_statistics;
+};
+
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per client)
+ */
+struct tstorm_per_queue_stats {
+ struct regpair rcv_ucast_bytes;
+ __le32 rcv_ucast_pkts;
+ __le32 checksum_discard;
+ struct regpair rcv_bcast_bytes;
+ __le32 rcv_bcast_pkts;
+ __le32 pkts_too_big_discard;
+ struct regpair rcv_mcast_bytes;
+ __le32 rcv_mcast_pkts;
+ __le32 ttl0_discard;
+ __le16 no_buff_discard;
+ __le16 reserved0;
+ __le32 reserved1;
+};
+
+/*
+ * Protocol-common statistics collected by the Ustorm (per client)
+ */
+struct ustorm_per_queue_stats {
+ struct regpair ucast_no_buff_bytes;
+ struct regpair mcast_no_buff_bytes;
+ struct regpair bcast_no_buff_bytes;
+ __le32 ucast_no_buff_pkts;
+ __le32 mcast_no_buff_pkts;
+ __le32 bcast_no_buff_pkts;
+ __le32 coalesced_pkts;
+ struct regpair coalesced_bytes;
+ __le32 coalesced_events;
+ __le32 coalesced_aborts;
+};
+
+/*
+ * Protocol-common statistics collected by the Xstorm (per client)
+ */
+struct xstorm_per_queue_stats {
+ struct regpair ucast_bytes_sent;
+ struct regpair mcast_bytes_sent;
+ struct regpair bcast_bytes_sent;
+ __le32 ucast_pkts_sent;
+ __le32 mcast_pkts_sent;
+ __le32 bcast_pkts_sent;
+ __le32 error_drop_pkts;
+};
+
+/*
+ *
+ */
+struct per_queue_stats {
+ struct tstorm_per_queue_stats tstorm_queue_statistics;
+ struct ustorm_per_queue_stats ustorm_queue_statistics;
+ struct xstorm_per_queue_stats xstorm_queue_statistics;
+};
+
+
+/*
* FW version stored in first line of pram
*/
struct pram_fw_version {
@@ -3582,7 +4910,6 @@ union protocol_common_specific_data {
u8 protocol_data[8];
struct regpair phy_address;
struct regpair mac_config_addr;
- struct common_query_ramrod_data query_ramrod_data;
};
/*
@@ -3613,7 +4940,6 @@ struct rate_shaping_counter {
* per-vnic rate shaping variables
*/
struct rate_shaping_vars_per_vn {
- struct rate_shaping_counter protocol_counters[NUM_OF_PROTOCOLS];
struct rate_shaping_counter vn_counter;
};
@@ -3628,39 +4954,100 @@ struct slow_path_element {
/*
- * eth/toe flags that indicate if to query
+ * Protocol-common statistics counter
*/
-struct stats_indication_flags {
- u32 collect_eth;
- u32 collect_toe;
+struct stats_counter {
+ __le16 xstats_counter;
+ __le16 reserved0;
+ __le32 reserved1;
+ __le16 tstats_counter;
+ __le16 reserved2;
+ __le32 reserved3;
+ __le16 ustats_counter;
+ __le16 reserved4;
+ __le32 reserved5;
+ __le16 cstats_counter;
+ __le16 reserved6;
+ __le32 reserved7;
};
/*
- * per-port PFC variables
+ *
*/
-struct storm_pfc_struct_per_port {
-#if defined(__BIG_ENDIAN)
- u16 mid_mac_addr;
- u16 msb_mac_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 msb_mac_addr;
- u16 mid_mac_addr;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 pfc_pause_quanta_in_nanosec;
- u16 lsb_mac_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 lsb_mac_addr;
- u16 pfc_pause_quanta_in_nanosec;
-#endif
+struct stats_query_entry {
+ u8 kind;
+ u8 index;
+ __le16 funcID;
+ __le32 reserved;
+ struct regpair address;
};
/*
- * Per-port congestion management variables
+ * statistic command
*/
-struct storm_cmng_struct_per_port {
- struct storm_pfc_struct_per_port pfc_vars;
+struct stats_query_cmd_group {
+ struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
+};
+
+
+/*
+ * statistic command header
+ */
+struct stats_query_header {
+ u8 cmd_num;
+ u8 reserved0;
+ __le16 drv_stats_counter;
+ __le32 reserved1;
+ struct regpair stats_counters_addrs;
+};
+
+
+/*
+ * Types of statistcis query entry
+ */
+enum stats_query_type {
+ STATS_TYPE_QUEUE,
+ STATS_TYPE_PORT,
+ STATS_TYPE_PF,
+ STATS_TYPE_TOE,
+ STATS_TYPE_FCOE,
+ MAX_STATS_QUERY_TYPE
+};
+
+
+/*
+ * Indicate of the function status block state
+ */
+enum status_block_state {
+ SB_DISABLED,
+ SB_ENABLED,
+ SB_CLEANED,
+ MAX_STATUS_BLOCK_STATE
+};
+
+
+/*
+ * Storm IDs (including attentions for IGU related enums)
+ */
+enum storm_id {
+ USTORM_ID,
+ CSTORM_ID,
+ XSTORM_ID,
+ TSTORM_ID,
+ ATTENTION_ID,
+ MAX_STORM_ID
+};
+
+
+/*
+ * Taffic types used in ETS and flow control algorithms
+ */
+enum traffic_type {
+ LLFC_TRAFFIC_TYPE_NW,
+ LLFC_TRAFFIC_TYPE_FCOE,
+ LLFC_TRAFFIC_TYPE_ISCSI,
+ MAX_TRAFFIC_TYPE
};
@@ -3715,6 +5102,16 @@ struct vf_pf_channel_data {
/*
+ * State of VF-PF channel
+ */
+enum vf_pf_channel_state {
+ VF_PF_CHANNEL_STATE_READY,
+ VF_PF_CHANNEL_STATE_WAITING_FOR_ACK,
+ MAX_VF_PF_CHANNEL_STATE
+};
+
+
+/*
* zone A per-queue data
*/
struct xstorm_queue_zone_data {
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h
index d5399206f66e..4d748e77d1ac 100644
--- a/drivers/net/bnx2x/bnx2x_init.h
+++ b/drivers/net/bnx2x/bnx2x_init.h
@@ -15,98 +15,34 @@
#ifndef BNX2X_INIT_H
#define BNX2X_INIT_H
-/* RAM0 size in bytes */
-#define STORM_INTMEM_SIZE_E1 0x5800
-#define STORM_INTMEM_SIZE_E1H 0x10000
-#define STORM_INTMEM_SIZE(bp) ((CHIP_IS_E1(bp) ? STORM_INTMEM_SIZE_E1 : \
- STORM_INTMEM_SIZE_E1H) / 4)
-
-
/* Init operation types and structures */
-/* Common for both E1 and E1H */
-#define OP_RD 0x1 /* read single register */
-#define OP_WR 0x2 /* write single register */
-#define OP_IW 0x3 /* write single register using mailbox */
-#define OP_SW 0x4 /* copy a string to the device */
-#define OP_SI 0x5 /* copy a string using mailbox */
-#define OP_ZR 0x6 /* clear memory */
-#define OP_ZP 0x7 /* unzip then copy with DMAE */
-#define OP_WR_64 0x8 /* write 64 bit pattern */
-#define OP_WB 0x9 /* copy a string using DMAE */
-
-/* FPGA and EMUL specific operations */
-#define OP_WR_EMUL 0xa /* write single register on Emulation */
-#define OP_WR_FPGA 0xb /* write single register on FPGA */
-#define OP_WR_ASIC 0xc /* write single register on ASIC */
-
-/* Init stages */
-/* Never reorder stages !!! */
-#define COMMON_STAGE 0
-#define PORT0_STAGE 1
-#define PORT1_STAGE 2
-#define FUNC0_STAGE 3
-#define FUNC1_STAGE 4
-#define FUNC2_STAGE 5
-#define FUNC3_STAGE 6
-#define FUNC4_STAGE 7
-#define FUNC5_STAGE 8
-#define FUNC6_STAGE 9
-#define FUNC7_STAGE 10
-#define STAGE_IDX_MAX 11
-
-#define STAGE_START 0
-#define STAGE_END 1
-
-
-/* Indices of blocks */
-#define PRS_BLOCK 0
-#define SRCH_BLOCK 1
-#define TSDM_BLOCK 2
-#define TCM_BLOCK 3
-#define BRB1_BLOCK 4
-#define TSEM_BLOCK 5
-#define PXPCS_BLOCK 6
-#define EMAC0_BLOCK 7
-#define EMAC1_BLOCK 8
-#define DBU_BLOCK 9
-#define MISC_BLOCK 10
-#define DBG_BLOCK 11
-#define NIG_BLOCK 12
-#define MCP_BLOCK 13
-#define UPB_BLOCK 14
-#define CSDM_BLOCK 15
-#define USDM_BLOCK 16
-#define CCM_BLOCK 17
-#define UCM_BLOCK 18
-#define USEM_BLOCK 19
-#define CSEM_BLOCK 20
-#define XPB_BLOCK 21
-#define DQ_BLOCK 22
-#define TIMERS_BLOCK 23
-#define XSDM_BLOCK 24
-#define QM_BLOCK 25
-#define PBF_BLOCK 26
-#define XCM_BLOCK 27
-#define XSEM_BLOCK 28
-#define CDU_BLOCK 29
-#define DMAE_BLOCK 30
-#define PXP_BLOCK 31
-#define CFC_BLOCK 32
-#define HC_BLOCK 33
-#define PXP2_BLOCK 34
-#define MISC_AEU_BLOCK 35
-#define PGLUE_B_BLOCK 36
-#define IGU_BLOCK 37
-#define ATC_BLOCK 38
-#define QM_4PORT_BLOCK 39
-#define XSEM_4PORT_BLOCK 40
+enum {
+ OP_RD = 0x1, /* read a single register */
+ OP_WR, /* write a single register */
+ OP_SW, /* copy a string to the device */
+ OP_ZR, /* clear memory */
+ OP_ZP, /* unzip then copy with DMAE */
+ OP_WR_64, /* write 64 bit pattern */
+ OP_WB, /* copy a string using DMAE */
+ OP_WB_ZR, /* Clear a string using DMAE or indirect-wr */
+ /* Skip the following ops if all of the init modes don't match */
+ OP_IF_MODE_OR,
+ /* Skip the following ops if any of the init modes don't match */
+ OP_IF_MODE_AND,
+ OP_MAX
+};
+enum {
+ STAGE_START,
+ STAGE_END,
+};
/* Returns the index of start or end of a specific block stage in ops array*/
#define BLOCK_OPS_IDX(block, stage, end) \
- (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
+ (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
+/* structs for the various opcodes */
struct raw_op {
u32 op:8;
u32 offset:24;
@@ -116,7 +52,7 @@ struct raw_op {
struct op_read {
u32 op:8;
u32 offset:24;
- u32 pad;
+ u32 val;
};
struct op_write {
@@ -125,15 +61,15 @@ struct op_write {
u32 val;
};
-struct op_string_write {
+struct op_arr_write {
u32 op:8;
u32 offset:24;
-#ifdef __LITTLE_ENDIAN
- u16 data_off;
- u16 data_len;
-#else /* __BIG_ENDIAN */
+#ifdef __BIG_ENDIAN
u16 data_len;
u16 data_off;
+#else /* __LITTLE_ENDIAN */
+ u16 data_off;
+ u16 data_len;
#endif
};
@@ -143,14 +79,209 @@ struct op_zero {
u32 len;
};
+struct op_if_mode {
+ u32 op:8;
+ u32 cmd_offset:24;
+ u32 mode_bit_map;
+};
+
+
union init_op {
struct op_read read;
struct op_write write;
- struct op_string_write str_wr;
+ struct op_arr_write arr_wr;
struct op_zero zero;
struct raw_op raw;
+ struct op_if_mode if_mode;
+};
+
+
+/* Init Phases */
+enum {
+ PHASE_COMMON,
+ PHASE_PORT0,
+ PHASE_PORT1,
+ PHASE_PF0,
+ PHASE_PF1,
+ PHASE_PF2,
+ PHASE_PF3,
+ PHASE_PF4,
+ PHASE_PF5,
+ PHASE_PF6,
+ PHASE_PF7,
+ NUM_OF_INIT_PHASES
};
+/* Init Modes */
+enum {
+ MODE_ASIC = 0x00000001,
+ MODE_FPGA = 0x00000002,
+ MODE_EMUL = 0x00000004,
+ MODE_E2 = 0x00000008,
+ MODE_E3 = 0x00000010,
+ MODE_PORT2 = 0x00000020,
+ MODE_PORT4 = 0x00000040,
+ MODE_SF = 0x00000080,
+ MODE_MF = 0x00000100,
+ MODE_MF_SD = 0x00000200,
+ MODE_MF_SI = 0x00000400,
+ MODE_MF_NIV = 0x00000800,
+ MODE_E3_A0 = 0x00001000,
+ MODE_E3_B0 = 0x00002000,
+ MODE_COS3 = 0x00004000,
+ MODE_COS6 = 0x00008000,
+ MODE_LITTLE_ENDIAN = 0x00010000,
+ MODE_BIG_ENDIAN = 0x00020000,
+};
+
+/* Init Blocks */
+enum {
+ BLOCK_ATC,
+ BLOCK_BRB1,
+ BLOCK_CCM,
+ BLOCK_CDU,
+ BLOCK_CFC,
+ BLOCK_CSDM,
+ BLOCK_CSEM,
+ BLOCK_DBG,
+ BLOCK_DMAE,
+ BLOCK_DORQ,
+ BLOCK_HC,
+ BLOCK_IGU,
+ BLOCK_MISC,
+ BLOCK_NIG,
+ BLOCK_PBF,
+ BLOCK_PGLUE_B,
+ BLOCK_PRS,
+ BLOCK_PXP2,
+ BLOCK_PXP,
+ BLOCK_QM,
+ BLOCK_SRC,
+ BLOCK_TCM,
+ BLOCK_TM,
+ BLOCK_TSDM,
+ BLOCK_TSEM,
+ BLOCK_UCM,
+ BLOCK_UPB,
+ BLOCK_USDM,
+ BLOCK_USEM,
+ BLOCK_XCM,
+ BLOCK_XPB,
+ BLOCK_XSDM,
+ BLOCK_XSEM,
+ BLOCK_MISC_AEU,
+ NUM_OF_INIT_BLOCKS
+};
+
+/* QM queue numbers */
+#define BNX2X_ETH_Q 0
+#define BNX2X_TOE_Q 3
+#define BNX2X_TOE_ACK_Q 6
+#define BNX2X_ISCSI_Q 9
+#define BNX2X_ISCSI_ACK_Q 11
+#define BNX2X_FCOE_Q 10
+
+/* Vnics per mode */
+#define BNX2X_PORT2_MODE_NUM_VNICS 4
+#define BNX2X_PORT4_MODE_NUM_VNICS 2
+
+/* COS offset for port1 in E3 B0 4port mode */
+#define BNX2X_E3B0_PORT1_COS_OFFSET 3
+
+/* QM Register addresses */
+#define BNX2X_Q_VOQ_REG_ADDR(pf_q_num)\
+ (QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
+#define BNX2X_VOQ_Q_REG_ADDR(cos, pf_q_num)\
+ (QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
+#define BNX2X_Q_CMDQ_REG_ADDR(pf_q_num)\
+ (QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
+
+/* extracts the QM queue number for the specified port and vnic */
+#define BNX2X_PF_Q_NUM(q_num, port, vnic)\
+ ((((port) << 1) | (vnic)) * 16 + (q_num))
+
+
+/* Maps the specified queue to the specified COS */
+static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
+{
+ /* find current COS mapping */
+ u32 curr_cos = REG_RD(bp, QM_REG_QVOQIDX_0 + q_num * 4);
+
+ /* check if queue->COS mapping has changed */
+ if (curr_cos != new_cos) {
+ u32 num_vnics = BNX2X_PORT2_MODE_NUM_VNICS;
+ u32 reg_addr, reg_bit_map, vnic;
+
+ /* update parameters for 4port mode */
+ if (INIT_MODE_FLAGS(bp) & MODE_PORT4) {
+ num_vnics = BNX2X_PORT4_MODE_NUM_VNICS;
+ if (BP_PORT(bp)) {
+ curr_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
+ new_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
+ }
+ }
+
+ /* change queue mapping for each VNIC */
+ for (vnic = 0; vnic < num_vnics; vnic++) {
+ u32 pf_q_num =
+ BNX2X_PF_Q_NUM(q_num, BP_PORT(bp), vnic);
+ u32 q_bit_map = 1 << (pf_q_num & 0x1f);
+
+ /* overwrite queue->VOQ mapping */
+ REG_WR(bp, BNX2X_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
+
+ /* clear queue bit from current COS bit map */
+ reg_addr = BNX2X_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
+ reg_bit_map = REG_RD(bp, reg_addr);
+ REG_WR(bp, reg_addr, reg_bit_map & (~q_bit_map));
+
+ /* set queue bit in new COS bit map */
+ reg_addr = BNX2X_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
+ reg_bit_map = REG_RD(bp, reg_addr);
+ REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
+
+ /* set/clear queue bit in command-queue bit map
+ (E2/E3A0 only, valid COS values are 0/1) */
+ if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
+ reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
+ reg_bit_map = REG_RD(bp, reg_addr);
+ q_bit_map = 1 << (2 * (pf_q_num & 0xf));
+ reg_bit_map = new_cos ?
+ (reg_bit_map | q_bit_map) :
+ (reg_bit_map & (~q_bit_map));
+ REG_WR(bp, reg_addr, reg_bit_map);
+ }
+ }
+ }
+}
+
+/* Configures the QM according to the specified per-traffic-type COSes */
+static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
+ struct priority_cos *traffic_cos)
+{
+ bnx2x_map_q_cos(bp, BNX2X_FCOE_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
+ bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
+ bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
+ if (mode != STATIC_COS) {
+ /* required only in backward compatible COS mode */
+ bnx2x_map_q_cos(bp, BNX2X_ETH_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+ bnx2x_map_q_cos(bp, BNX2X_TOE_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+ bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+ }
+}
+
+
+/* Returns the index of start or end of a specific block stage in ops array*/
+#define BLOCK_OPS_IDX(block, stage, end) \
+ (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
+
+
#define INITOP_SET 0 /* set the HW directly */
#define INITOP_CLEAR 1 /* clear the HW directly */
#define INITOP_INIT 2 /* set the init-value array */
@@ -195,25 +326,25 @@ struct src_ent {
/****************************************************************************
* Parity configuration
****************************************************************************/
-#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2) \
+#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \
{ \
block##_REG_##block##_PRTY_MASK, \
block##_REG_##block##_PRTY_STS_CLR, \
- en_mask, {m1, m1h, m2}, #block \
+ en_mask, {m1, m1h, m2, m3}, #block \
}
-#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2) \
+#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \
{ \
block##_REG_##block##_PRTY_MASK_0, \
block##_REG_##block##_PRTY_STS_CLR_0, \
- en_mask, {m1, m1h, m2}, #block"_0" \
+ en_mask, {m1, m1h, m2, m3}, #block"_0" \
}
-#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2) \
+#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \
{ \
block##_REG_##block##_PRTY_MASK_1, \
block##_REG_##block##_PRTY_STS_CLR_1, \
- en_mask, {m1, m1h, m2}, #block"_1" \
+ en_mask, {m1, m1h, m2, m3}, #block"_1" \
}
static const struct {
@@ -224,6 +355,7 @@ static const struct {
u32 e1; /* 57710 */
u32 e1h; /* 57711 */
u32 e2; /* 57712 */
+ u32 e3; /* 578xx */
} reg_mask; /* Register mask (all valid bits) */
char name[7]; /* Block's longest name is 6 characters long
* (name + suffix)
@@ -241,39 +373,56 @@ static const struct {
/* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't
* want to handle "system kill" flow at the moment.
*/
- BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff),
- BLOCK_PRTY_INFO_0(PXP2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
- BLOCK_PRTY_INFO_1(PXP2, 0x7ff, 0x7f, 0x7f, 0x7ff),
- BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0),
- BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff),
- BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1),
- BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff),
- BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3),
+ BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff,
+ 0x7ffffff),
+ BLOCK_PRTY_INFO_0(PXP2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff),
+ BLOCK_PRTY_INFO_1(PXP2, 0x1ffffff, 0x7f, 0x7f, 0x7ff, 0x1ffffff),
+ BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0, 0),
+ BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0, 0),
+ BLOCK_PRTY_INFO_0(NIG, 0xffffffff, 0, 0, 0xffffffff, 0xffffffff),
+ BLOCK_PRTY_INFO_1(NIG, 0xffff, 0, 0, 0xff, 0xffff),
+ BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff, 0x7ff),
+ BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1, 0x1),
+ BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff, 0xfff),
+ BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0, 0x1f, 0x1f),
+ BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0, 0x3, 0x3),
+ BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3, 0x3),
{GRCBASE_UPB + PB_REG_PB_PRTY_MASK,
- GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0,
- {0xf, 0xf, 0xf}, "UPB"},
+ GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf,
+ {0xf, 0xf, 0xf, 0xf}, "UPB"},
{GRCBASE_XPB + PB_REG_PB_PRTY_MASK,
GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0,
- {0xf, 0xf, 0xf}, "XPB"},
- BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7),
- BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f),
- BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf),
- BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1),
- BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf),
- BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf),
- BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff),
- BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff),
- BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
- BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff),
- BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
- BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
- BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f),
- BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
- BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f),
- BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
- BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f),
- BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
- BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f),
+ {0xf, 0xf, 0xf, 0xf}, "XPB"},
+ BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7, 0x7),
+ BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f, 0x1f),
+ BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf, 0x3f),
+ BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1, 0x1),
+ BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf, 0xf),
+ BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf, 0xf),
+ BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff, 0xff),
+ BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffff, 0xfffffff),
+ BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f, 0x7f),
+ BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+ BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+ BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+ BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+ BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
+ BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
+ BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
+ BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff),
+ BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff),
+ BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
+ BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff),
+ BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
+ BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff),
+ BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
+ BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff),
+ BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
};
@@ -324,8 +473,10 @@ static inline u32 bnx2x_parity_reg_mask(struct bnx2x *bp, int idx)
return bnx2x_blocks_parity_data[idx].reg_mask.e1;
else if (CHIP_IS_E1H(bp))
return bnx2x_blocks_parity_data[idx].reg_mask.e1h;
- else
+ else if (CHIP_IS_E2(bp))
return bnx2x_blocks_parity_data[idx].reg_mask.e2;
+ else /* CHIP_IS_E3 */
+ return bnx2x_blocks_parity_data[idx].reg_mask.e3;
}
static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp)
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h
index aafd0232393f..7ec1724753ad 100644
--- a/drivers/net/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/bnx2x/bnx2x_init_ops.h
@@ -15,13 +15,39 @@
#ifndef BNX2X_INIT_OPS_H
#define BNX2X_INIT_OPS_H
+
+#ifndef BP_ILT
+#define BP_ILT(bp) NULL
+#endif
+
+#ifndef BP_FUNC
+#define BP_FUNC(bp) 0
+#endif
+
+#ifndef BP_PORT
+#define BP_PORT(bp) 0
+#endif
+
+#ifndef BNX2X_ILT_FREE
+#define BNX2X_ILT_FREE(x, y, sz)
+#endif
+
+#ifndef BNX2X_ILT_ZALLOC
+#define BNX2X_ILT_ZALLOC(x, y, sz)
+#endif
+
+#ifndef ILOG2
+#define ILOG2(x) x
+#endif
+
static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
-static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
- u32 addr, u32 len);
+static void bnx2x_write_dmae_phys_len(struct bnx2x *bp,
+ dma_addr_t phys_addr, u32 addr,
+ u32 len);
-static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len)
+static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len)
{
u32 i;
@@ -29,24 +55,32 @@ static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
REG_WR(bp, addr + i*4, data[i]);
}
-static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len)
+static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
- REG_WR_IND(bp, addr + i*4, data[i]);
+ bnx2x_reg_wr_ind(bp, addr + i*4, data[i]);
}
-static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
+static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len,
+ u8 wb)
{
if (bp->dmae_ready)
bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ else if (wb)
+ /*
+ * Wide bus registers with no dmae need to be written
+ * using indirect write.
+ */
+ bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
else
bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
}
-static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
+static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill,
+ u32 len, u8 wb)
{
u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4));
u32 buf_len32 = buf_len/4;
@@ -57,12 +91,20 @@ static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
- bnx2x_write_big_buf(bp, addr + i*4, cur_len);
+ bnx2x_write_big_buf(bp, addr + i*4, cur_len, wb);
}
}
-static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len64)
+static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
+{
+ if (bp->dmae_ready)
+ bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ else
+ bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
+}
+
+static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len64)
{
u32 buf_len32 = FW_BUF_SIZE/4;
u32 len = len64*2;
@@ -82,7 +124,7 @@ static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
- bnx2x_write_big_buf(bp, addr + i*4, cur_len);
+ bnx2x_write_big_buf_wb(bp, addr + i*4, cur_len);
}
}
@@ -100,7 +142,8 @@ static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
#define IF_IS_PRAM_ADDR(base, addr) \
if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
-static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
+static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr,
+ const u8 *data)
{
IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
data = INIT_TSEM_INT_TABLE_DATA(bp);
@@ -129,31 +172,17 @@ static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
return data;
}
-static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
+static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len)
{
if (bp->dmae_ready)
- bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);
else
- bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
-}
-
-static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len)
-{
- const u32 *old_data = data;
-
- data = (const u32 *)bnx2x_sel_blob(bp, addr, (const u8 *)data);
-
- if (bp->dmae_ready) {
- if (old_data != data)
- VIRT_WR_DMAE_LEN(bp, data, addr, len, 1);
- else
- VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);
- } else
bnx2x_init_ind_wr(bp, addr, data, len);
}
-static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi)
+static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo,
+ u32 val_hi)
{
u32 wb_write[2];
@@ -161,8 +190,8 @@ static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi)
wb_write[1] = val_hi;
REG_WR_DMAE_LEN(bp, reg, wb_write, 2);
}
-
-static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
+static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len,
+ u32 blob_off)
{
const u8 *data = NULL;
int rc;
@@ -186,39 +215,33 @@ static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
{
u16 op_start =
- INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_START)];
+ INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,
+ STAGE_START)];
u16 op_end =
- INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_END)];
+ INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,
+ STAGE_END)];
union init_op *op;
- int hw_wr;
- u32 i, op_type, addr, len;
+ u32 op_idx, op_type, addr, len;
const u32 *data, *data_base;
/* If empty block */
if (op_start == op_end)
return;
- if (CHIP_REV_IS_FPGA(bp))
- hw_wr = OP_WR_FPGA;
- else if (CHIP_REV_IS_EMUL(bp))
- hw_wr = OP_WR_EMUL;
- else
- hw_wr = OP_WR_ASIC;
-
data_base = INIT_DATA(bp);
- for (i = op_start; i < op_end; i++) {
-
- op = (union init_op *)&(INIT_OPS(bp)[i]);
+ for (op_idx = op_start; op_idx < op_end; op_idx++) {
- op_type = op->str_wr.op;
- addr = op->str_wr.offset;
- len = op->str_wr.data_len;
- data = data_base + op->str_wr.data_off;
-
- /* HW/EMUL specific */
- if ((op_type > OP_WB) && (op_type == hw_wr))
- op_type = OP_WR;
+ op = (union init_op *)&(INIT_OPS(bp)[op_idx]);
+ /* Get generic data */
+ op_type = op->raw.op;
+ addr = op->raw.offset;
+ /* Get data that's used for OP_SW, OP_WB, OP_FW, OP_ZP and
+ * OP_WR64 (we assume that op_arr_write and op_write have the
+ * same structure).
+ */
+ len = op->arr_wr.data_len;
+ data = data_base + op->arr_wr.data_off;
switch (op_type) {
case OP_RD:
@@ -233,21 +256,39 @@ static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
case OP_WB:
bnx2x_init_wr_wb(bp, addr, data, len);
break;
- case OP_SI:
- bnx2x_init_ind_wr(bp, addr, data, len);
- break;
case OP_ZR:
- bnx2x_init_fill(bp, addr, 0, op->zero.len);
+ bnx2x_init_fill(bp, addr, 0, op->zero.len, 0);
+ break;
+ case OP_WB_ZR:
+ bnx2x_init_fill(bp, addr, 0, op->zero.len, 1);
break;
case OP_ZP:
bnx2x_init_wr_zp(bp, addr, len,
- op->str_wr.data_off);
+ op->arr_wr.data_off);
break;
case OP_WR_64:
bnx2x_init_wr_64(bp, addr, data, len);
break;
+ case OP_IF_MODE_AND:
+ /* if any of the flags doesn't match, skip the
+ * conditional block.
+ */
+ if ((INIT_MODE_FLAGS(bp) &
+ op->if_mode.mode_bit_map) !=
+ op->if_mode.mode_bit_map)
+ op_idx += op->if_mode.cmd_offset;
+ break;
+ case OP_IF_MODE_OR:
+ /* if all the flags don't match, skip the conditional
+ * block.
+ */
+ if ((INIT_MODE_FLAGS(bp) &
+ op->if_mode.mode_bit_map) == 0)
+ op_idx += op->if_mode.cmd_offset;
+ break;
default:
- /* happens whenever an op is of a diff HW */
+ /* Should never get here! */
+
break;
}
}
@@ -417,7 +458,8 @@ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {
PXP2_REG_RQ_BW_WR_UBOUND30}
};
-static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
+static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order,
+ int w_order)
{
u32 val, i;
@@ -491,19 +533,21 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))
REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
- if (CHIP_IS_E2(bp))
+ if (CHIP_IS_E3(bp))
+ REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x4 << w_order));
+ else if (CHIP_IS_E2(bp))
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));
else
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
- if (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1(bp)) {
/* MPS w_order optimal TH presently TH
* 128 0 0 2
* 256 1 1 3
* >=512 2 2 3
*/
/* DMAE is special */
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1H(bp)) {
/* E2 can use optimal TH */
val = w_order;
REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);
@@ -557,8 +601,8 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
#define ILT_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44)))
#define ILT_RANGE(f, l) (((l) << 10) | f)
-static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line,
- u32 size, u8 memop)
+static int bnx2x_ilt_line_mem_op(struct bnx2x *bp,
+ struct ilt_line *line, u32 size, u8 memop)
{
if (memop == ILT_MEMOP_FREE) {
BNX2X_ILT_FREE(line->page, line->page_mapping, line->size);
@@ -572,7 +616,8 @@ static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line,
}
-static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, u8 memop)
+static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
+ u8 memop)
{
int i, rc;
struct bnx2x_ilt *ilt = BP_ILT(bp);
@@ -617,8 +662,8 @@ static void bnx2x_ilt_line_wr(struct bnx2x *bp, int abs_idx,
bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping));
}
-static void bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt,
- int idx, u8 initop)
+static void bnx2x_ilt_line_init_op(struct bnx2x *bp,
+ struct bnx2x_ilt *ilt, int idx, u8 initop)
{
dma_addr_t null_mapping;
int abs_idx = ilt->start_line + idx;
@@ -733,7 +778,7 @@ static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
}
static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
- u32 psz_reg, u8 initop)
+ u32 psz_reg, u8 initop)
{
struct bnx2x_ilt *ilt = BP_ILT(bp);
struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
@@ -848,7 +893,8 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
/* Initialize T2 */
for (i = 0; i < src_cid_count-1; i++)
- t2[i].next = (u64)(t2_mapping + (i+1)*sizeof(struct src_ent));
+ t2[i].next = (u64)(t2_mapping +
+ (i+1)*sizeof(struct src_ent));
/* tell the searcher where the T2 table is */
REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index 076e11f5769f..bcd8f0038628 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -25,6 +25,8 @@
#include <linux/mutex.h>
#include "bnx2x.h"
+#include "bnx2x_cmn.h"
+
/********************************************************/
#define ETH_HLEN 14
@@ -35,6 +37,13 @@
#define ETH_MAX_JUMBO_PACKET_SIZE 9600
#define MDIO_ACCESS_TIMEOUT 1000
#define BMAC_CONTROL_RX_ENABLE 2
+#define WC_LANE_MAX 4
+#define I2C_SWITCH_WIDTH 2
+#define I2C_BSC0 0
+#define I2C_BSC1 1
+#define I2C_WA_RETRY_CNT 3
+#define MCPR_IMC_COMMAND_READ_OP 1
+#define MCPR_IMC_COMMAND_WRITE_OP 2
/***********************************************************/
/* Shortcut definitions */
@@ -103,16 +112,13 @@
MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
#define GP_STATUS_10G_CX4 \
MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
-#define GP_STATUS_12G_HIG \
- MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
-#define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
-#define GP_STATUS_13G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
-#define GP_STATUS_15G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
-#define GP_STATUS_16G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
#define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
#define GP_STATUS_10G_KX4 \
MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
-
+#define GP_STATUS_10G_KR MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR
+#define GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
+#define GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
+#define GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
#define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
#define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
#define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
@@ -126,20 +132,10 @@
#define LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
#define LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
#define LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
-#define LINK_12GTFD LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
-#define LINK_12GXFD LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
-#define LINK_12_5GTFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
-#define LINK_12_5GXFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
-#define LINK_13GTFD LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
-#define LINK_13GXFD LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
-#define LINK_15GTFD LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
-#define LINK_15GXFD LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
-#define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
-#define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
-
-#define PHY_XGXS_FLAG 0x1
-#define PHY_SGMII_FLAG 0x2
-#define PHY_SERDES_FLAG 0x4
+#define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
+#define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
+
+
/* */
#define SFP_EEPROM_CON_TYPE_ADDR 0x2
@@ -165,8 +161,104 @@
#define EDC_MODE_PASSIVE_DAC 0x0055
+/* BRB thresholds for E2*/
+#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE 170
+#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE 250
+#define PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 90
+
+#define PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE 250
+
+/* BRB thresholds for E3A0 */
+#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE 290
+#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE 410
+#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 170
+
+#define PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE 410
+
+
+/* BRB thresholds for E3B0 2 port mode*/
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE 1025
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE 1025
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 1025
+
+#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE 1025
+
+/* only for E3B0*/
+#define PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR 1025
+#define PFC_E3B0_2P_BRB_FULL_LB_XON_THR 1025
+
+/* Lossy +Lossless GUARANTIED == GUART */
+#define PFC_E3B0_2P_MIX_PAUSE_LB_GUART 284
+/* Lossless +Lossless*/
+#define PFC_E3B0_2P_PAUSE_LB_GUART 236
+/* Lossy +Lossy*/
+#define PFC_E3B0_2P_NON_PAUSE_LB_GUART 342
+
+/* Lossy +Lossless*/
+#define PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART 284
+/* Lossless +Lossless*/
+#define PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART 236
+/* Lossy +Lossy*/
+#define PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART 336
+#define PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST 80
+
+#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART 0
+#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST 0
+
+/* BRB thresholds for E3B0 4 port mode */
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE 304
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE 384
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 304
+
+#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE 384
+
+
+/* only for E3B0*/
+#define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR 304
+#define PFC_E3B0_4P_BRB_FULL_LB_XON_THR 384
+#define PFC_E3B0_4P_LB_GUART 120
+
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART 120
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST 80
+
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART 80
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST 120
+
+#define DCBX_INVALID_COS (0xFF)
+
#define ETS_BW_LIMIT_CREDIT_UPPER_BOUND (0x5000)
#define ETS_BW_LIMIT_CREDIT_WEIGHT (0x5000)
+#define ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS (1360)
+#define ETS_E3B0_NIG_MIN_W_VAL_20GBPS (2720)
+#define ETS_E3B0_PBF_MIN_W_VAL (10000)
+
+#define MAX_PACKET_SIZE (9700)
+#define WC_UC_TIMEOUT 100
+
/**********************************************************/
/* INTERFACE */
/**********************************************************/
@@ -202,14 +294,86 @@ static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
}
/******************************************************************/
+/* EPIO/GPIO section */
+/******************************************************************/
+static void bnx2x_get_epio(struct bnx2x *bp, u32 epio_pin, u32 *en)
+{
+ u32 epio_mask, gp_oenable;
+ *en = 0;
+ /* Sanity check */
+ if (epio_pin > 31) {
+ DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to get\n", epio_pin);
+ return;
+ }
+
+ epio_mask = 1 << epio_pin;
+ /* Set this EPIO to output */
+ gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
+ REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask);
+
+ *en = (REG_RD(bp, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin;
+}
+static void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en)
+{
+ u32 epio_mask, gp_output, gp_oenable;
+
+ /* Sanity check */
+ if (epio_pin > 31) {
+ DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to set\n", epio_pin);
+ return;
+ }
+ DP(NETIF_MSG_LINK, "Setting EPIO pin %d to %d\n", epio_pin, en);
+ epio_mask = 1 << epio_pin;
+ /* Set this EPIO to output */
+ gp_output = REG_RD(bp, MCP_REG_MCPR_GP_OUTPUTS);
+ if (en)
+ gp_output |= epio_mask;
+ else
+ gp_output &= ~epio_mask;
+
+ REG_WR(bp, MCP_REG_MCPR_GP_OUTPUTS, gp_output);
+
+ /* Set the value for this EPIO */
+ gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
+ REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable | epio_mask);
+}
+
+static void bnx2x_set_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 val)
+{
+ if (pin_cfg == PIN_CFG_NA)
+ return;
+ if (pin_cfg >= PIN_CFG_EPIO0) {
+ bnx2x_set_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
+ } else {
+ u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
+ u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
+ bnx2x_set_gpio(bp, gpio_num, (u8)val, gpio_port);
+ }
+}
+
+static u32 bnx2x_get_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 *val)
+{
+ if (pin_cfg == PIN_CFG_NA)
+ return -EINVAL;
+ if (pin_cfg >= PIN_CFG_EPIO0) {
+ bnx2x_get_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
+ } else {
+ u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
+ u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
+ *val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
+ }
+ return 0;
+
+}
+/******************************************************************/
/* ETS section */
/******************************************************************/
-void bnx2x_ets_disabled(struct link_params *params)
+static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
{
/* ETS disabled configuration*/
struct bnx2x *bp = params->bp;
- DP(NETIF_MSG_LINK, "ETS disabled configuration\n");
+ DP(NETIF_MSG_LINK, "ETS E2E3 disabled configuration\n");
/*
* mapping between entry priority to client number (0,1,2 -debug and
@@ -262,7 +426,756 @@ void bnx2x_ets_disabled(struct link_params *params)
/* Defines the number of consecutive slots for the strict priority */
REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
}
+/******************************************************************************
+* Description:
+* Getting min_w_val will be set according to line speed .
+*.
+******************************************************************************/
+static u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
+{
+ u32 min_w_val = 0;
+ /* Calculate min_w_val.*/
+ if (vars->link_up) {
+ if (SPEED_20000 == vars->line_speed)
+ min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
+ else
+ min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
+ } else
+ min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
+ /**
+ * If the link isn't up (static configuration for example ) The
+ * link will be according to 20GBPS.
+ */
+ return min_w_val;
+}
+/******************************************************************************
+* Description:
+* Getting credit upper bound form min_w_val.
+*.
+******************************************************************************/
+static u32 bnx2x_ets_get_credit_upper_bound(const u32 min_w_val)
+{
+ const u32 credit_upper_bound = (u32)MAXVAL((150 * min_w_val),
+ MAX_PACKET_SIZE);
+ return credit_upper_bound;
+}
+/******************************************************************************
+* Description:
+* Set credit upper bound for NIG.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_set_credit_upper_bound_nig(
+ const struct link_params *params,
+ const u32 min_w_val)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u32 credit_upper_bound =
+ bnx2x_ets_get_credit_upper_bound(min_w_val);
+
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
+
+ if (0 == port) {
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
+ credit_upper_bound);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
+ credit_upper_bound);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8,
+ credit_upper_bound);
+ }
+}
+/******************************************************************************
+* Description:
+* Will return the NIG ETS registers to init values.Except
+* credit_upper_bound.
+* That isn't used in this configuration (No WFQ is enabled) and will be
+* configured acording to spec
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
+ const struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u32 min_w_val = bnx2x_ets_get_min_w_val_nig(vars);
+ /**
+ * mapping between entry priority to client number (0,1,2 -debug and
+ * management clients, 3 - COS0 client, 4 - COS1, ... 8 -
+ * COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
+ * reset value or init tool
+ */
+ if (port) {
+ REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB, 0x543210);
+ REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB, 0x0);
+ } else {
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB, 0x76543210);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB, 0x8);
+ }
+ /**
+ * For strict priority entries defines the number of consecutive
+ * slots for the highest priority.
+ */
+ /* TODO_ETS - Should be done by reset value or init tool */
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS :
+ NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
+ /**
+ * mapping between the CREDIT_WEIGHT registers and actual client
+ * numbers
+ */
+ /* TODO_ETS - Should be done by reset value or init tool */
+ if (port) {
+ /*Port 1 has 6 COS*/
+ REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB, 0x210543);
+ REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x0);
+ } else {
+ /*Port 0 has 9 COS*/
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB,
+ 0x43210876);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x5);
+ }
+
+ /**
+ * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+ * as strict. Bits 0,1,2 - debug and management entries, 3 -
+ * COS0 entry, 4 - COS1 entry.
+ * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
+ * bit4 bit3 bit2 bit1 bit0
+ * MCP and debug are strict
+ */
+ if (port)
+ REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT, 0x3f);
+ else
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1ff);
+ /* defines which entries (clients) are subjected to WFQ arbitration */
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
+ NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
+
+ /**
+ * Please notice the register address are note continuous and a
+ * for here is note appropriate.In 2 port mode port0 only COS0-5
+ * can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
+ * port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
+ * are never used for WFQ
+ */
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
+ if (0 == port) {
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
+ }
+
+ bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val);
+}
+/******************************************************************************
+* Description:
+* Set credit upper bound for PBF.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
+ const struct link_params *params,
+ const u32 min_w_val)
+{
+ struct bnx2x *bp = params->bp;
+ const u32 credit_upper_bound =
+ bnx2x_ets_get_credit_upper_bound(min_w_val);
+ const u8 port = params->port;
+ u32 base_upper_bound = 0;
+ u8 max_cos = 0;
+ u8 i = 0;
+ /**
+ * In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
+ * port mode port1 has COS0-2 that can be used for WFQ.
+ */
+ if (0 == port) {
+ base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
+ } else {
+ base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P1;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
+ }
+
+ for (i = 0; i < max_cos; i++)
+ REG_WR(bp, base_upper_bound + (i << 2), credit_upper_bound);
+}
+
+/******************************************************************************
+* Description:
+* Will return the PBF ETS registers to init values.Except
+* credit_upper_bound.
+* That isn't used in this configuration (No WFQ is enabled) and will be
+* configured acording to spec
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
+ u8 i = 0;
+ u32 base_weight = 0;
+ u8 max_cos = 0;
+
+ /**
+ * mapping between entry priority to client number 0 - COS0
+ * client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
+ * TODO_ETS - Should be done by reset value or init tool
+ */
+ if (port)
+ /* 0x688 (|011|0 10|00 1|000) */
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , 0x688);
+ else
+ /* (10 1|100 |011|0 10|00 1|000) */
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , 0x2C688);
+
+ /* TODO_ETS - Should be done by reset value or init tool */
+ if (port)
+ /* 0x688 (|011|0 10|00 1|000)*/
+ REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1, 0x688);
+ else
+ /* 0x2C688 (10 1|100 |011|0 10|00 1|000) */
+ REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0, 0x2C688);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 :
+ PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 , 0x100);
+
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , 0);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 , 0);
+ /**
+ * In 2 port mode port0 has COS0-5 that can be used for WFQ.
+ * In 4 port mode port1 has COS0-2 that can be used for WFQ.
+ */
+ if (0 == port) {
+ base_weight = PBF_REG_COS0_WEIGHT_P0;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
+ } else {
+ base_weight = PBF_REG_COS0_WEIGHT_P1;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
+ }
+
+ for (i = 0; i < max_cos; i++)
+ REG_WR(bp, base_weight + (0x4 * i), 0);
+
+ bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
+}
+/******************************************************************************
+* Description:
+* E3B0 disable will return basicly the values to init values.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_disabled(const struct link_params *params,
+ const struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+
+ if (!CHIP_IS_E3B0(bp)) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
+ "\n");
+ return -EINVAL;
+ }
+
+ bnx2x_ets_e3b0_nig_disabled(params, vars);
+
+ bnx2x_ets_e3b0_pbf_disabled(params);
+
+ return 0;
+}
+/******************************************************************************
+* Description:
+* Disable will return basicly the values to init values.
+*.
+******************************************************************************/
+int bnx2x_ets_disabled(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ int bnx2x_status = 0;
+
+ if ((CHIP_IS_E2(bp)) || (CHIP_IS_E3A0(bp)))
+ bnx2x_ets_e2e3a0_disabled(params);
+ else if (CHIP_IS_E3B0(bp))
+ bnx2x_status = bnx2x_ets_e3b0_disabled(params, vars);
+ else {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_disabled - chip not supported\n");
+ return -EINVAL;
+ }
+
+ return bnx2x_status;
+}
+
+/******************************************************************************
+* Description
+* Set the COS mappimg to SP and BW until this point all the COS are not
+* set as SP or BW.
+******************************************************************************/
+static int bnx2x_ets_e3b0_cli_map(const struct link_params *params,
+ const struct bnx2x_ets_params *ets_params,
+ const u8 cos_sp_bitmap,
+ const u8 cos_bw_bitmap)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u8 nig_cli_sp_bitmap = 0x7 | (cos_sp_bitmap << 3);
+ const u8 pbf_cli_sp_bitmap = cos_sp_bitmap;
+ const u8 nig_cli_subject2wfq_bitmap = cos_bw_bitmap << 3;
+ const u8 pbf_cli_subject2wfq_bitmap = cos_bw_bitmap;
+
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT :
+ NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, nig_cli_sp_bitmap);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , pbf_cli_sp_bitmap);
+
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
+ NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ,
+ nig_cli_subject2wfq_bitmap);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0,
+ pbf_cli_subject2wfq_bitmap);
+
+ return 0;
+}
+
+/******************************************************************************
+* Description:
+* This function is needed because NIG ARB_CREDIT_WEIGHT_X are
+* not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
+******************************************************************************/
+static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
+ const u8 cos_entry,
+ const u32 min_w_val_nig,
+ const u32 min_w_val_pbf,
+ const u16 total_bw,
+ const u8 bw,
+ const u8 port)
+{
+ u32 nig_reg_adress_crd_weight = 0;
+ u32 pbf_reg_adress_crd_weight = 0;
+ /* Calculate and set BW for this COS*/
+ const u32 cos_bw_nig = (bw * min_w_val_nig) / total_bw;
+ const u32 cos_bw_pbf = (bw * min_w_val_pbf) / total_bw;
+
+ switch (cos_entry) {
+ case 0:
+ nig_reg_adress_crd_weight =
+ (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
+ break;
+ case 1:
+ nig_reg_adress_crd_weight = (port) ?
+ NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
+ break;
+ case 2:
+ nig_reg_adress_crd_weight = (port) ?
+ NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
+
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
+ break;
+ case 3:
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight =
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
+ pbf_reg_adress_crd_weight =
+ PBF_REG_COS3_WEIGHT_P0;
+ break;
+ case 4:
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight =
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
+ pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
+ break;
+ case 5:
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight =
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
+ pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
+ break;
+ }
+
+ REG_WR(bp, nig_reg_adress_crd_weight, cos_bw_nig);
+
+ REG_WR(bp, pbf_reg_adress_crd_weight, cos_bw_pbf);
+
+ return 0;
+}
+/******************************************************************************
+* Description:
+* Calculate the total BW.A value of 0 isn't legal.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_get_total_bw(
+ const struct link_params *params,
+ const struct bnx2x_ets_params *ets_params,
+ u16 *total_bw)
+{
+ struct bnx2x *bp = params->bp;
+ u8 cos_idx = 0;
+
+ *total_bw = 0 ;
+ /* Calculate total BW requested */
+ for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
+ if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
+
+ if (0 == ets_params->cos[cos_idx].params.bw_params.bw) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
+ "was set to 0\n");
+ return -EINVAL;
+ }
+ *total_bw +=
+ ets_params->cos[cos_idx].params.bw_params.bw;
+ }
+ }
+
+ /*Check taotl 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");
+ return -EINVAL;
+ }
+ 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.
+ */
+ }
+ return 0;
+}
+
+/******************************************************************************
+* Description:
+* Invalidate all the sp_pri_to_cos.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
+{
+ u8 pri = 0;
+ for (pri = 0; pri < DCBX_MAX_NUM_COS; pri++)
+ sp_pri_to_cos[pri] = DCBX_INVALID_COS;
+}
+/******************************************************************************
+* Description:
+* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
+* according to sp_pri_to_cos.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
+ u8 *sp_pri_to_cos, const u8 pri,
+ const u8 cos_entry)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+ DCBX_E3B0_MAX_NUM_COS_PORT0;
+
+ 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"
+ "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"
+ "parameter Illegal strict priority\n");
+ return -EINVAL;
+ }
+
+ sp_pri_to_cos[pri] = cos_entry;
+ return 0;
+
+}
+
+/******************************************************************************
+* Description:
+* Returns the correct value according to COS and priority in
+* the sp_pri_cli register.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
+ const u8 pri_set,
+ const u8 pri_offset,
+ const u8 entry_size)
+{
+ u64 pri_cli_nig = 0;
+ pri_cli_nig = ((u64)(cos + cos_offset)) << (entry_size *
+ (pri_set + pri_offset));
+
+ return pri_cli_nig;
+}
+/******************************************************************************
+* Description:
+* Returns the correct value according to COS and priority in the
+* sp_pri_cli register for NIG.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
+{
+ /* MCP Dbg0 and dbg1 are always with higher strict pri*/
+ const u8 nig_cos_offset = 3;
+ const u8 nig_pri_offset = 3;
+
+ return bnx2x_e3b0_sp_get_pri_cli_reg(cos, nig_cos_offset, pri_set,
+ nig_pri_offset, 4);
+
+}
+/******************************************************************************
+* Description:
+* Returns the correct value according to COS and priority in the
+* sp_pri_cli register for PBF.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
+{
+ const u8 pbf_cos_offset = 0;
+ const u8 pbf_pri_offset = 0;
+
+ return bnx2x_e3b0_sp_get_pri_cli_reg(cos, pbf_cos_offset, pri_set,
+ pbf_pri_offset, 3);
+
+}
+
+/******************************************************************************
+* Description:
+* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
+* according to sp_pri_to_cos.(which COS has higher priority)
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
+ u8 *sp_pri_to_cos)
+{
+ struct bnx2x *bp = params->bp;
+ u8 i = 0;
+ const u8 port = params->port;
+ /* MCP Dbg0 and dbg1 are always with higher strict pri*/
+ u64 pri_cli_nig = 0x210;
+ u32 pri_cli_pbf = 0x0;
+ u8 pri_set = 0;
+ u8 pri_bitmask = 0;
+ const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+ DCBX_E3B0_MAX_NUM_COS_PORT0;
+
+ u8 cos_bit_to_set = (1 << max_num_of_cos) - 1;
+
+ /* Set all the strict priority first */
+ for (i = 0; i < max_num_of_cos; i++) {
+ if (DCBX_INVALID_COS != sp_pri_to_cos[i]) {
+ if (DCBX_MAX_NUM_COS <= sp_pri_to_cos[i]) {
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
+ "invalid cos entry\n");
+ return -EINVAL;
+ }
+
+ pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
+ sp_pri_to_cos[i], pri_set);
+
+ pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
+ sp_pri_to_cos[i], pri_set);
+ pri_bitmask = 1 << sp_pri_to_cos[i];
+ /* COS is used remove it from bitmap.*/
+ if (0 == (pri_bitmask & cos_bit_to_set)) {
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
+ "invalid There can't be two COS's with"
+ " the same strict pri\n");
+ return -EINVAL;
+ }
+ cos_bit_to_set &= ~pri_bitmask;
+ pri_set++;
+ }
+ }
+
+ /* Set all the Non strict priority i= COS*/
+ for (i = 0; i < max_num_of_cos; i++) {
+ pri_bitmask = 1 << i;
+ /* Check if COS was already used for SP */
+ if (pri_bitmask & cos_bit_to_set) {
+ /* COS wasn't used for SP */
+ pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
+ i, pri_set);
+
+ pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
+ i, pri_set);
+ /* COS is used remove it from bitmap.*/
+ cos_bit_to_set &= ~pri_bitmask;
+ pri_set++;
+ }
+ }
+
+ if (pri_set != max_num_of_cos) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_set_pri_cli_reg not all "
+ "entries were set\n");
+ return -EINVAL;
+ }
+
+ if (port) {
+ /* Only 6 usable clients*/
+ REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB,
+ (u32)pri_cli_nig);
+
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , pri_cli_pbf);
+ } else {
+ /* Only 9 usable clients*/
+ const u32 pri_cli_nig_lsb = (u32) (pri_cli_nig);
+ const u32 pri_cli_nig_msb = (u32) ((pri_cli_nig >> 32) & 0xF);
+
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB,
+ pri_cli_nig_lsb);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB,
+ pri_cli_nig_msb);
+
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , pri_cli_pbf);
+ }
+ return 0;
+}
+
+/******************************************************************************
+* Description:
+* Configure the COS to ETS according to BW and SP settings.
+******************************************************************************/
+int bnx2x_ets_e3b0_config(const struct link_params *params,
+ const struct link_vars *vars,
+ const struct bnx2x_ets_params *ets_params)
+{
+ struct bnx2x *bp = params->bp;
+ int bnx2x_status = 0;
+ const u8 port = params->port;
+ u16 total_bw = 0;
+ const u32 min_w_val_nig = bnx2x_ets_get_min_w_val_nig(vars);
+ const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
+ u8 cos_bw_bitmap = 0;
+ u8 cos_sp_bitmap = 0;
+ u8 sp_pri_to_cos[DCBX_MAX_NUM_COS] = {0};
+ const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+ DCBX_E3B0_MAX_NUM_COS_PORT0;
+ u8 cos_entry = 0;
+
+ if (!CHIP_IS_E3B0(bp)) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
+ "\n");
+ return -EINVAL;
+ }
+
+ if ((ets_params->num_of_cos > max_num_of_cos)) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config the number of COS "
+ "isn't supported\n");
+ return -EINVAL;
+ }
+
+ /* Prepare sp strict priority parameters*/
+ bnx2x_ets_e3b0_sp_pri_to_cos_init(sp_pri_to_cos);
+
+ /* Prepare BW parameters*/
+ 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");
+ return -EINVAL;
+ }
+
+ /**
+ * Upper bound is set according to current link speed (min_w_val
+ * should be the same for upper bound and COS credit val).
+ */
+ bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
+ bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
+
+
+ for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
+ if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
+ cos_bw_bitmap |= (1 << cos_entry);
+ /**
+ * The function also sets the BW in HW(not the mappin
+ * yet)
+ */
+ bnx2x_status = bnx2x_ets_e3b0_set_cos_bw(
+ bp, cos_entry, min_w_val_nig, min_w_val_pbf,
+ total_bw,
+ ets_params->cos[cos_entry].params.bw_params.bw,
+ port);
+ } else if (bnx2x_cos_state_strict ==
+ ets_params->cos[cos_entry].state){
+ cos_sp_bitmap |= (1 << cos_entry);
+
+ bnx2x_status = bnx2x_ets_e3b0_sp_pri_to_cos_set(
+ params,
+ sp_pri_to_cos,
+ ets_params->cos[cos_entry].params.sp_params.pri,
+ cos_entry);
+
+ } else {
+ 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");
+ return bnx2x_status;
+ }
+ }
+
+ /* Set SP register (which COS has higher priority) */
+ bnx2x_status = bnx2x_ets_e3b0_sp_set_pri_cli_reg(params,
+ sp_pri_to_cos);
+
+ if (0 != bnx2x_status) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config set_pri_cli_reg "
+ "failed\n");
+ return bnx2x_status;
+ }
+
+ /* Set client mapping of BW and strict */
+ bnx2x_status = bnx2x_ets_e3b0_cli_map(params, ets_params,
+ cos_sp_bitmap,
+ cos_bw_bitmap);
+
+ if (0 != bnx2x_status) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config SP failed\n");
+ return bnx2x_status;
+ }
+ return 0;
+}
static void bnx2x_ets_bw_limit_common(const struct link_params *params)
{
/* ETS disabled configuration */
@@ -342,7 +1255,7 @@ void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
REG_WR(bp, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
}
-u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
+int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
{
/* ETS disabled configuration*/
struct bnx2x *bp = params->bp;
@@ -388,24 +1301,64 @@ u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
/* PFC section */
/******************************************************************/
-static void bnx2x_bmac2_get_pfc_stat(struct link_params *params,
- u32 pfc_frames_sent[2],
- u32 pfc_frames_received[2])
+static void bnx2x_update_pfc_xmac(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
- /* Read pfc statistic */
struct bnx2x *bp = params->bp;
- u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
- NIG_REG_INGRESS_BMAC0_MEM;
+ u32 xmac_base;
+ u32 pause_val, pfc0_val, pfc1_val;
- DP(NETIF_MSG_LINK, "pfc statistic read from BMAC\n");
+ /* XMAC base adrr */
+ xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
- REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_STAT_GTPP,
- pfc_frames_sent, 2);
+ /* Initialize pause and pfc registers */
+ pause_val = 0x18000;
+ pfc0_val = 0xFFFF8000;
+ pfc1_val = 0x2;
- REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_STAT_GRPP,
- pfc_frames_received, 2);
+ /* No PFC support */
+ if (!(params->feature_config_flags &
+ FEATURE_CONFIG_PFC_ENABLED)) {
+ /*
+ * RX flow control - Process pause frame in receive direction
+ */
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+ pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN;
+
+ /*
+ * TX flow control - Send pause packet when buffer is full
+ */
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+ pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN;
+ } else {/* PFC support */
+ pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
+ XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
+ XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
+ XMAC_PFC_CTRL_HI_REG_TX_PFC_EN;
+ }
+
+ /* Write pause and PFC registers */
+ REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
+ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
+ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
+
+
+ /* Set MAC address for source TX Pause/PFC frames */
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_LO,
+ ((params->mac_addr[2] << 24) |
+ (params->mac_addr[3] << 16) |
+ (params->mac_addr[4] << 8) |
+ (params->mac_addr[5])));
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_HI,
+ ((params->mac_addr[0] << 8) |
+ (params->mac_addr[1])));
+
+ udelay(30);
}
+
+
static void bnx2x_emac_get_pfc_stat(struct link_params *params,
u32 pfc_frames_sent[2],
u32 pfc_frames_received[2])
@@ -437,33 +1390,54 @@ static void bnx2x_emac_get_pfc_stat(struct link_params *params,
pfc_frames_sent[0] = val_xon + val_xoff;
}
+/* Read pfc statistic*/
void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
u32 pfc_frames_sent[2],
u32 pfc_frames_received[2])
{
/* Read pfc statistic */
struct bnx2x *bp = params->bp;
- u32 val = 0;
+
DP(NETIF_MSG_LINK, "pfc statistic\n");
if (!vars->link_up)
return;
- val = REG_RD(bp, MISC_REG_RESET_REG_2);
- if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
- == 0) {
- DP(NETIF_MSG_LINK, "About to read stats from EMAC\n");
+ if (MAC_TYPE_EMAC == vars->mac_type) {
+ DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
pfc_frames_received);
- } else {
- DP(NETIF_MSG_LINK, "About to read stats from BMAC\n");
- bnx2x_bmac2_get_pfc_stat(params, pfc_frames_sent,
- pfc_frames_received);
}
}
/******************************************************************/
/* MAC/PBF section */
/******************************************************************/
+static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
+{
+ u32 mode, emac_base;
+ /**
+ * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
+ * (a value of 49==0x31) and make sure that the AUTO poll is off
+ */
+
+ if (CHIP_IS_E2(bp))
+ emac_base = GRCBASE_EMAC0;
+ else
+ emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+ mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
+ mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
+ EMAC_MDIO_MODE_CLOCK_CNT);
+ if (USES_WARPCORE(bp))
+ mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+ else
+ mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+
+ mode |= (EMAC_MDIO_MODE_CLAUSE_45);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
+
+ udelay(40);
+}
+
static void bnx2x_emac_init(struct link_params *params,
struct link_vars *vars)
{
@@ -495,7 +1469,7 @@ static void bnx2x_emac_init(struct link_params *params,
}
timeout--;
} while (val & EMAC_MODE_RESET);
-
+ bnx2x_set_mdio_clk(bp, params->chip_id, port);
/* Set mac address */
val = ((params->mac_addr[0] << 8) |
params->mac_addr[1]);
@@ -508,9 +1482,246 @@ static void bnx2x_emac_init(struct link_params *params,
EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
}
-static u8 bnx2x_emac_enable(struct link_params *params,
+static void bnx2x_set_xumac_nig(struct link_params *params,
+ u16 tx_pause_en,
+ u8 enable)
+{
+ struct bnx2x *bp = params->bp;
+
+ REG_WR(bp, params->port ? NIG_REG_P1_MAC_IN_EN : NIG_REG_P0_MAC_IN_EN,
+ enable);
+ REG_WR(bp, params->port ? NIG_REG_P1_MAC_OUT_EN : NIG_REG_P0_MAC_OUT_EN,
+ enable);
+ REG_WR(bp, params->port ? NIG_REG_P1_MAC_PAUSE_OUT_EN :
+ NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en);
+}
+
+static void bnx2x_umac_enable(struct link_params *params,
struct link_vars *vars, u8 lb)
{
+ u32 val;
+ u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+ struct bnx2x *bp = params->bp;
+ /* Reset UMAC */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
+ usleep_range(1000, 1000);
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
+
+ DP(NETIF_MSG_LINK, "enabling UMAC\n");
+
+ /**
+ * This register determines on which events the MAC will assert
+ * error on the i/f to the NIG along w/ EOP.
+ */
+
+ /**
+ * BD REG_WR(bp, NIG_REG_P0_MAC_RSV_ERR_MASK +
+ * params->port*0x14, 0xfffff.
+ */
+ /* This register opens the gate for the UMAC despite its name */
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
+
+ val = UMAC_COMMAND_CONFIG_REG_PROMIS_EN |
+ UMAC_COMMAND_CONFIG_REG_PAD_EN |
+ UMAC_COMMAND_CONFIG_REG_SW_RESET |
+ UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK;
+ switch (vars->line_speed) {
+ case SPEED_10:
+ val |= (0<<2);
+ break;
+ case SPEED_100:
+ val |= (1<<2);
+ break;
+ case SPEED_1000:
+ val |= (2<<2);
+ break;
+ case SPEED_2500:
+ val |= (3<<2);
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Invalid speed for UMAC %d\n",
+ vars->line_speed);
+ break;
+ }
+ REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+ udelay(50);
+
+ /* Set MAC address for source TX Pause/PFC frames (under SW reset) */
+ REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR0,
+ ((params->mac_addr[2] << 24) |
+ (params->mac_addr[3] << 16) |
+ (params->mac_addr[4] << 8) |
+ (params->mac_addr[5])));
+ REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR1,
+ ((params->mac_addr[0] << 8) |
+ (params->mac_addr[1])));
+
+ /* Enable RX and TX */
+ val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN;
+ val |= UMAC_COMMAND_CONFIG_REG_TX_ENA |
+ UMAC_COMMAND_CONFIG_REG_RX_ENA;
+ REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+ udelay(50);
+
+ /* Remove SW Reset */
+ val &= ~UMAC_COMMAND_CONFIG_REG_SW_RESET;
+
+ /* Check loopback mode */
+ if (lb)
+ val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA;
+ REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+
+ /*
+ * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+ * length used by the MAC receive logic to check frames.
+ */
+ REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
+ bnx2x_set_xumac_nig(params,
+ ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
+ vars->mac_type = MAC_TYPE_UMAC;
+
+}
+
+static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
+{
+ u32 port4mode_ovwr_val;
+ /* Check 4-port override enabled */
+ port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
+ if (port4mode_ovwr_val & (1<<0)) {
+ /* Return 4-port mode override value */
+ return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
+ }
+ /* Return 4-port mode from input pin */
+ return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
+}
+
+/* Define the XMAC mode */
+static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
+{
+ u32 is_port4mode = bnx2x_is_4_port_mode(bp);
+
+ /**
+ * In 4-port mode, need to set the mode only once, so if XMAC is
+ * already out of reset, it means the mode has already been set,
+ * and it must not* reset the XMAC again, since it controls both
+ * ports of the path
+ **/
+
+ if (is_port4mode && (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");
+ return;
+ }
+
+ /* Hard reset */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ MISC_REGISTERS_RESET_REG_2_XMAC);
+ usleep_range(1000, 1000);
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ MISC_REGISTERS_RESET_REG_2_XMAC);
+ if (is_port4mode) {
+ DP(NETIF_MSG_LINK, "Init XMAC to 2 ports x 10G per path\n");
+
+ /* Set the number of ports on the system side to up to 2 */
+ REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 1);
+
+ /* Set the number of ports on the Warp Core to 10G */
+ REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
+ } else {
+ /* 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");
+ /* 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");
+ /* Set the number of ports on the Warp Core to 20G */
+ REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 1);
+ }
+ }
+ /* Soft reset */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
+ usleep_range(1000, 1000);
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
+
+}
+
+static void bnx2x_xmac_disable(struct link_params *params)
+{
+ u8 port = params->port;
+ struct bnx2x *bp = params->bp;
+ u32 xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+ if (REG_RD(bp, MISC_REG_RESET_REG_2) &
+ MISC_REGISTERS_RESET_REG_2_XMAC) {
+ 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);
+ }
+}
+
+static int bnx2x_xmac_enable(struct link_params *params,
+ struct link_vars *vars, u8 lb)
+{
+ u32 val, xmac_base;
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "enabling XMAC\n");
+
+ xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+ bnx2x_xmac_init(bp, vars->line_speed);
+
+ /*
+ * This register determines on which events the MAC will assert
+ * error on the i/f to the NIG along w/ EOP.
+ */
+
+ /*
+ * This register tells the NIG whether to send traffic to UMAC
+ * or XMAC
+ */
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
+
+ /* Set Max packet size */
+ REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
+
+ /* CRC append for Tx packets */
+ REG_WR(bp, xmac_base + XMAC_REG_TX_CTRL, 0xC800);
+
+ /* update PFC */
+ bnx2x_update_pfc_xmac(params, vars, 0);
+
+ /* Enable TX and RX */
+ val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
+
+ /* Check loopback mode */
+ if (lb)
+ val |= XMAC_CTRL_REG_CORE_LOCAL_LPBK;
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL, val);
+ bnx2x_set_xumac_nig(params,
+ ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
+
+ vars->mac_type = MAC_TYPE_XMAC;
+
+ return 0;
+}
+static int bnx2x_emac_enable(struct link_params *params,
+ struct link_vars *vars, u8 lb)
+{
struct bnx2x *bp = params->bp;
u8 port = params->port;
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
@@ -760,95 +1971,398 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
}
-static void bnx2x_update_pfc_brb(struct link_params *params,
- struct link_vars *vars,
- struct bnx2x_nig_brb_pfc_port_params *pfc_params)
+
+/* PFC BRB internal port configuration params */
+struct bnx2x_pfc_brb_threshold_val {
+ u32 pause_xoff;
+ u32 pause_xon;
+ u32 full_xoff;
+ u32 full_xon;
+};
+
+struct bnx2x_pfc_brb_e3b0_val {
+ u32 full_lb_xoff_th;
+ u32 full_lb_xon_threshold;
+ u32 lb_guarantied;
+ u32 mac_0_class_t_guarantied;
+ u32 mac_0_class_t_guarantied_hyst;
+ u32 mac_1_class_t_guarantied;
+ u32 mac_1_class_t_guarantied_hyst;
+};
+
+struct bnx2x_pfc_brb_th_val {
+ struct bnx2x_pfc_brb_threshold_val pauseable_th;
+ struct bnx2x_pfc_brb_threshold_val non_pauseable_th;
+};
+static int bnx2x_pfc_brb_get_config_params(
+ struct link_params *params,
+ struct bnx2x_pfc_brb_th_val *config_val)
{
struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting PFC BRB configuration\n");
+ if (CHIP_IS_E2(bp)) {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ } else if (CHIP_IS_E3A0(bp)) {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ } else if (CHIP_IS_E3B0(bp)) {
+ if (params->phy[INT_PHY].flags &
+ FLAGS_4_PORT_MODE) {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ } else {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ }
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void bnx2x_pfc_brb_get_e3b0_config_params(struct link_params *params,
+ struct bnx2x_pfc_brb_e3b0_val
+ *e3b0_val,
+ u32 cos0_pauseable,
+ u32 cos1_pauseable)
+{
+ if (params->phy[INT_PHY].flags & FLAGS_4_PORT_MODE) {
+ e3b0_val->full_lb_xoff_th =
+ PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR;
+ e3b0_val->full_lb_xon_threshold =
+ PFC_E3B0_4P_BRB_FULL_LB_XON_THR;
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_4P_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART;
+ e3b0_val->mac_0_class_t_guarantied_hyst =
+ PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST;
+ e3b0_val->mac_1_class_t_guarantied =
+ PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART;
+ e3b0_val->mac_1_class_t_guarantied_hyst =
+ PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST;
+ } else {
+ e3b0_val->full_lb_xoff_th =
+ PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR;
+ e3b0_val->full_lb_xon_threshold =
+ PFC_E3B0_2P_BRB_FULL_LB_XON_THR;
+ e3b0_val->mac_0_class_t_guarantied_hyst =
+ PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST;
+ e3b0_val->mac_1_class_t_guarantied =
+ PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART;
+ e3b0_val->mac_1_class_t_guarantied_hyst =
+ PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST;
+
+ if (cos0_pauseable != cos1_pauseable) {
+ /* nonpauseable= Lossy + pauseable = Lossless*/
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_2P_MIX_PAUSE_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART;
+ } else if (cos0_pauseable) {
+ /* Lossless +Lossless*/
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_2P_PAUSE_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART;
+ } else {
+ /* Lossy +Lossy*/
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_2P_NON_PAUSE_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART;
+ }
+ }
+}
+static int bnx2x_update_pfc_brb(struct link_params *params,
+ struct link_vars *vars,
+ struct bnx2x_nig_brb_pfc_port_params
+ *pfc_params)
+{
+ struct bnx2x *bp = params->bp;
+ struct bnx2x_pfc_brb_th_val config_val = { {0} };
+ struct bnx2x_pfc_brb_threshold_val *reg_th_config =
+ &config_val.pauseable_th;
+ struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0};
int set_pfc = params->feature_config_flags &
FEATURE_CONFIG_PFC_ENABLED;
+ int bnx2x_status = 0;
+ u8 port = params->port;
/* default - pause configuration */
- u32 pause_xoff_th = PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
- u32 pause_xon_th = PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
- u32 full_xoff_th = PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
- u32 full_xon_th = PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
+ reg_th_config = &config_val.pauseable_th;
+ bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val);
+ if (0 != bnx2x_status)
+ return bnx2x_status;
if (set_pfc && pfc_params)
/* First COS */
- if (!pfc_params->cos0_pauseable) {
- pause_xoff_th =
- PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
- pause_xon_th =
- PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
- full_xoff_th =
- PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
- full_xon_th =
- PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
- }
+ if (!pfc_params->cos0_pauseable)
+ reg_th_config = &config_val.non_pauseable_th;
/*
* The number of free blocks below which the pause signal to class 0
* of MAC #n is asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , pause_xoff_th);
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 :
+ BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 ,
+ reg_th_config->pause_xoff);
/*
* The number of free blocks above which the pause signal to class 0
* of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , pause_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XON_THRESHOLD_1 :
+ BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , reg_th_config->pause_xon);
/*
* The number of free blocks below which the full signal to class 0
* of MAC #n is asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , full_xoff_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_0_XOFF_THRESHOLD_1 :
+ BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , reg_th_config->full_xoff);
/*
* The number of free blocks above which the full signal to class 0
* of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_0_XON_THRESHOLD_0 , full_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 :
+ BRB1_REG_FULL_0_XON_THRESHOLD_0 , reg_th_config->full_xon);
if (set_pfc && pfc_params) {
/* Second COS */
- if (pfc_params->cos1_pauseable) {
- pause_xoff_th =
- PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
- pause_xon_th =
- PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
- full_xoff_th =
- PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
- full_xon_th =
- PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
- } else {
- pause_xoff_th =
- PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
- pause_xon_th =
- PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
- full_xoff_th =
- PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
- full_xon_th =
- PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
- }
+ if (pfc_params->cos1_pauseable)
+ reg_th_config = &config_val.pauseable_th;
+ else
+ reg_th_config = &config_val.non_pauseable_th;
/*
* The number of free blocks below which the pause signal to
* class 1 of MAC #n is asserted. n=0,1
- */
- REG_WR(bp, BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, pause_xoff_th);
+ **/
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
+ BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
+ reg_th_config->pause_xoff);
/*
* The number of free blocks above which the pause signal to
* class 1 of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_PAUSE_1_XON_THRESHOLD_0, pause_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
+ BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
+ reg_th_config->pause_xon);
/*
* The number of free blocks below which the full signal to
* class 1 of MAC #n is asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_1_XOFF_THRESHOLD_0, full_xoff_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
+ BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
+ reg_th_config->full_xoff);
/*
* The number of free blocks above which the full signal to
* class 1 of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_1_XON_THRESHOLD_0, full_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
+ BRB1_REG_FULL_1_XON_THRESHOLD_0,
+ reg_th_config->full_xon);
+
+
+ if (CHIP_IS_E3B0(bp)) {
+ /*Should be done by init tool */
+ /*
+ * BRB_empty_for_dup = BRB1_REG_BRB_EMPTY_THRESHOLD
+ * reset value
+ * 944
+ */
+
+ /**
+ * The hysteresis on the guarantied buffer space for the Lb port
+ * before signaling XON.
+ **/
+ REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST, 80);
+
+ bnx2x_pfc_brb_get_e3b0_config_params(
+ params,
+ &e3b0_val,
+ pfc_params->cos0_pauseable,
+ pfc_params->cos1_pauseable);
+ /**
+ * The number of free blocks below which the full signal to the
+ * LB port is asserted.
+ */
+ REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
+ e3b0_val.full_lb_xoff_th);
+ /**
+ * The number of free blocks above which the full signal to the
+ * LB port is de-asserted.
+ */
+ REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
+ e3b0_val.full_lb_xon_threshold);
+ /**
+ * The number of blocks guarantied for the MAC #n port. n=0,1
+ */
+
+ /*The number of blocks guarantied for the LB port.*/
+ REG_WR(bp, BRB1_REG_LB_GUARANTIED,
+ e3b0_val.lb_guarantied);
+
+ /**
+ * The number of blocks guarantied for the MAC #n port.
+ */
+ REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
+ 2 * e3b0_val.mac_0_class_t_guarantied);
+ REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
+ 2 * e3b0_val.mac_1_class_t_guarantied);
+ /**
+ * The number of blocks guarantied for class #t in MAC0. t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
+ e3b0_val.mac_0_class_t_guarantied);
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
+ e3b0_val.mac_0_class_t_guarantied);
+ /**
+ * The hysteresis on the guarantied buffer space for class in
+ * MAC0. t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
+ e3b0_val.mac_0_class_t_guarantied_hyst);
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
+ e3b0_val.mac_0_class_t_guarantied_hyst);
+
+ /**
+ * The number of blocks guarantied for class #t in MAC1.t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
+ e3b0_val.mac_1_class_t_guarantied);
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
+ e3b0_val.mac_1_class_t_guarantied);
+ /**
+ * The hysteresis on the guarantied buffer space for class #t
+ * in MAC1. t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
+ e3b0_val.mac_1_class_t_guarantied_hyst);
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
+ e3b0_val.mac_1_class_t_guarantied_hyst);
+
+ }
+
+ }
+
+ return bnx2x_status;
+}
+
+/******************************************************************************
+* Description:
+* This function is needed because NIG ARB_CREDIT_WEIGHT_X are
+* not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
+******************************************************************************/
+int bnx2x_pfc_nig_rx_priority_mask(struct bnx2x *bp,
+ u8 cos_entry,
+ u32 priority_mask, u8 port)
+{
+ u32 nig_reg_rx_priority_mask_add = 0;
+
+ switch (cos_entry) {
+ case 0:
+ nig_reg_rx_priority_mask_add = (port) ?
+ NIG_REG_P1_RX_COS0_PRIORITY_MASK :
+ NIG_REG_P0_RX_COS0_PRIORITY_MASK;
+ break;
+ case 1:
+ nig_reg_rx_priority_mask_add = (port) ?
+ NIG_REG_P1_RX_COS1_PRIORITY_MASK :
+ NIG_REG_P0_RX_COS1_PRIORITY_MASK;
+ break;
+ case 2:
+ nig_reg_rx_priority_mask_add = (port) ?
+ NIG_REG_P1_RX_COS2_PRIORITY_MASK :
+ NIG_REG_P0_RX_COS2_PRIORITY_MASK;
+ break;
+ case 3:
+ if (port)
+ return -EINVAL;
+ nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS3_PRIORITY_MASK;
+ break;
+ case 4:
+ if (port)
+ return -EINVAL;
+ nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS4_PRIORITY_MASK;
+ break;
+ case 5:
+ if (port)
+ return -EINVAL;
+ nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS5_PRIORITY_MASK;
+ break;
}
+
+ REG_WR(bp, nig_reg_rx_priority_mask_add, priority_mask);
+
+ return 0;
+}
+static void bnx2x_update_mng(struct link_params *params, u32 link_status)
+{
+ struct bnx2x *bp = params->bp;
+
+ REG_WR(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ port_mb[params->port].link_status), link_status);
}
static void bnx2x_update_pfc_nig(struct link_params *params,
@@ -858,9 +2372,9 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
u32 pkt_priority_to_cos = 0;
- u32 val;
struct bnx2x *bp = params->bp;
- int port = params->port;
+ u8 port = params->port;
+
int set_pfc = params->feature_config_flags &
FEATURE_CONFIG_PFC_ENABLED;
DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
@@ -881,6 +2395,9 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
pause_enable = 0;
llfc_out_en = 0;
llfc_enable = 0;
+ if (CHIP_IS_E3(bp))
+ ppp_enable = 0;
+ else
ppp_enable = 1;
xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
@@ -899,6 +2416,9 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
xcm0_out_en = 1;
}
+ if (CHIP_IS_E3(bp))
+ REG_WR(bp, port ? NIG_REG_BRB1_PAUSE_IN_EN :
+ NIG_REG_BRB0_PAUSE_IN_EN, pause_enable);
REG_WR(bp, port ? NIG_REG_LLFC_OUT_EN_1 :
NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
REG_WR(bp, port ? NIG_REG_LLFC_ENABLE_1 :
@@ -920,30 +2440,13 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
/* HW PFC TX enable */
REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
- /* 0x2 = BMAC, 0x1= EMAC */
- switch (vars->mac_type) {
- case MAC_TYPE_EMAC:
- val = 1;
- break;
- case MAC_TYPE_BMAC:
- val = 0;
- break;
- default:
- val = 0;
- break;
- }
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT, val);
-
if (nig_params) {
+ u8 i = 0;
pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
- REG_WR(bp, port ? NIG_REG_P1_RX_COS0_PRIORITY_MASK :
- NIG_REG_P0_RX_COS0_PRIORITY_MASK,
- nig_params->rx_cos0_priority_mask);
-
- REG_WR(bp, port ? NIG_REG_P1_RX_COS1_PRIORITY_MASK :
- NIG_REG_P0_RX_COS1_PRIORITY_MASK,
- nig_params->rx_cos1_priority_mask);
+ for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++)
+ bnx2x_pfc_nig_rx_priority_mask(bp, i,
+ nig_params->rx_cos_priority_mask[i], port);
REG_WR(bp, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
@@ -958,8 +2461,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
pkt_priority_to_cos);
}
-
-void bnx2x_update_pfc(struct link_params *params,
+int bnx2x_update_pfc(struct link_params *params,
struct link_vars *vars,
struct bnx2x_nig_brb_pfc_port_params *pfc_params)
{
@@ -970,41 +2472,59 @@ void bnx2x_update_pfc(struct link_params *params,
*/
u32 val;
struct bnx2x *bp = params->bp;
+ int bnx2x_status = 0;
+ u8 bmac_loopback = (params->loopback_mode == LOOPBACK_BMAC);
+
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+ vars->link_status |= LINK_STATUS_PFC_ENABLED;
+ else
+ vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
+
+ bnx2x_update_mng(params, vars->link_status);
/* update NIG params */
bnx2x_update_pfc_nig(params, vars, pfc_params);
/* update BRB params */
- bnx2x_update_pfc_brb(params, vars, pfc_params);
+ bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params);
+ if (0 != bnx2x_status)
+ return bnx2x_status;
if (!vars->link_up)
- return;
-
- val = REG_RD(bp, MISC_REG_RESET_REG_2);
- if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
- == 0) {
- DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
- bnx2x_emac_enable(params, vars, 0);
- return;
- }
+ return bnx2x_status;
DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
- if (CHIP_IS_E2(bp))
- bnx2x_update_pfc_bmac2(params, vars, 0);
- else
- bnx2x_update_pfc_bmac1(params, vars);
+ if (CHIP_IS_E3(bp))
+ bnx2x_update_pfc_xmac(params, vars, 0);
+ else {
+ val = REG_RD(bp, MISC_REG_RESET_REG_2);
+ if ((val &
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
+ == 0) {
+ DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
+ bnx2x_emac_enable(params, vars, 0);
+ return bnx2x_status;
+ }
- val = 0;
- if ((params->feature_config_flags &
- FEATURE_CONFIG_PFC_ENABLED) ||
- (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
- val = 1;
- REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
+ if (CHIP_IS_E2(bp))
+ bnx2x_update_pfc_bmac2(params, vars, bmac_loopback);
+ else
+ bnx2x_update_pfc_bmac1(params, vars);
+
+ val = 0;
+ if ((params->feature_config_flags &
+ FEATURE_CONFIG_PFC_ENABLED) ||
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
+ val = 1;
+ REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
+ }
+ return bnx2x_status;
}
-static u8 bnx2x_bmac1_enable(struct link_params *params,
- struct link_vars *vars,
- u8 is_lb)
+
+static int bnx2x_bmac1_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -1063,12 +2583,18 @@ static u8 bnx2x_bmac1_enable(struct link_params *params,
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
wb_data, 2);
+ if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
+ REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS,
+ wb_data, 2);
+ if (wb_data[0] > 0)
+ return -ESRCH;
+ }
return 0;
}
-static u8 bnx2x_bmac2_enable(struct link_params *params,
- struct link_vars *vars,
- u8 is_lb)
+static int bnx2x_bmac2_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -1128,14 +2654,25 @@ static u8 bnx2x_bmac2_enable(struct link_params *params,
udelay(30);
bnx2x_update_pfc_bmac2(params, vars, is_lb);
+ if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
+ REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT,
+ wb_data, 2);
+ if (wb_data[0] > 0) {
+ DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n",
+ wb_data[0]);
+ return -ESRCH;
+ }
+ }
+
return 0;
}
-static u8 bnx2x_bmac_enable(struct link_params *params,
- struct link_vars *vars,
- u8 is_lb)
+static int bnx2x_bmac_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
- u8 rc, port = params->port;
+ int rc = 0;
+ u8 port = params->port;
struct bnx2x *bp = params->bp;
u32 val;
/* reset and unreset the BigMac */
@@ -1173,16 +2710,6 @@ static u8 bnx2x_bmac_enable(struct link_params *params,
return rc;
}
-
-static void bnx2x_update_mng(struct link_params *params, u32 link_status)
-{
- struct bnx2x *bp = params->bp;
-
- REG_WR(bp, params->shmem_base +
- offsetof(struct shmem_region,
- port_mb[params->port].link_status), link_status);
-}
-
static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
{
u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
@@ -1218,8 +2745,8 @@ static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
}
}
-static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
- u32 line_speed)
+static int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
+ u32 line_speed)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -1269,18 +2796,6 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
case SPEED_10000:
init_crd = thresh + 553 - 22;
break;
-
- case SPEED_12000:
- init_crd = thresh + 664 - 22;
- break;
-
- case SPEED_13000:
- init_crd = thresh + 742 - 22;
- break;
-
- case SPEED_16000:
- init_crd = thresh + 778 - 22;
- break;
default:
DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
line_speed);
@@ -1349,31 +2864,23 @@ static u32 bnx2x_get_emac_base(struct bnx2x *bp,
}
/******************************************************************/
-/* CL45 access functions */
+/* CL22 access functions */
/******************************************************************/
-static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
- u8 devad, u16 reg, u16 val)
+static int bnx2x_cl22_write(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 reg, u16 val)
{
- u32 tmp, saved_mode;
- u8 i, rc = 0;
- /*
- * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
- * (a value of 49==0x31) and make sure that the AUTO poll is off
- */
-
- saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
- EMAC_MDIO_MODE_CLOCK_CNT);
- tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
- (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
- REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- udelay(40);
+ u32 tmp, mode;
+ u8 i;
+ int rc = 0;
+ /* Switch to CL22 */
+ mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
+ mode & ~EMAC_MDIO_MODE_CLAUSE_45);
/* address */
-
- tmp = ((phy->addr << 21) | (devad << 16) | reg |
- EMAC_MDIO_COMM_COMMAND_ADDRESS |
+ tmp = ((phy->addr << 21) | (reg << 16) | val |
+ EMAC_MDIO_COMM_COMMAND_WRITE_22 |
EMAC_MDIO_COMM_START_BUSY);
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
@@ -1388,57 +2895,60 @@ static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
}
if (tmp & EMAC_MDIO_COMM_START_BUSY) {
DP(NETIF_MSG_LINK, "write phy register failed\n");
- netdev_err(bp->dev, "MDC/MDIO access timeout\n");
rc = -EFAULT;
- } else {
- /* data */
- tmp = ((phy->addr << 21) | (devad << 16) | val |
- EMAC_MDIO_COMM_COMMAND_WRITE_45 |
- EMAC_MDIO_COMM_START_BUSY);
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+ }
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
+ return rc;
+}
- for (i = 0; i < 50; i++) {
- udelay(10);
+static int bnx2x_cl22_read(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 reg, u16 *ret_val)
+{
+ u32 val, mode;
+ u16 i;
+ int rc = 0;
- tmp = REG_RD(bp, phy->mdio_ctrl +
- EMAC_REG_EMAC_MDIO_COMM);
- if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
- udelay(5);
- break;
- }
- }
- if (tmp & EMAC_MDIO_COMM_START_BUSY) {
- DP(NETIF_MSG_LINK, "write phy register failed\n");
- netdev_err(bp->dev, "MDC/MDIO access timeout\n");
- rc = -EFAULT;
+ /* Switch to CL22 */
+ mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
+ mode & ~EMAC_MDIO_MODE_CLAUSE_45);
+
+ /* address */
+ val = ((phy->addr << 21) | (reg << 16) |
+ EMAC_MDIO_COMM_COMMAND_READ_22 |
+ EMAC_MDIO_COMM_START_BUSY);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+ if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
+ *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
+ udelay(5);
+ break;
}
}
+ if (val & EMAC_MDIO_COMM_START_BUSY) {
+ DP(NETIF_MSG_LINK, "read phy register failed\n");
- /* Restore the saved mode */
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
-
+ *ret_val = 0;
+ rc = -EFAULT;
+ }
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
return rc;
}
-static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
- u8 devad, u16 reg, u16 *ret_val)
+/******************************************************************/
+/* CL45 access functions */
+/******************************************************************/
+static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 *ret_val)
{
- u32 val, saved_mode;
+ u32 val;
u16 i;
- u8 rc = 0;
- /*
- * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
- * (a value of 49==0x31) and make sure that the AUTO poll is off
- */
-
- saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
- EMAC_MDIO_MODE_CLOCK_CNT));
- val |= (EMAC_MDIO_MODE_CLAUSE_45 |
- (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
- REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- udelay(40);
+ int rc = 0;
/* address */
val = ((phy->addr << 21) | (devad << 16) | reg |
@@ -1460,7 +2970,6 @@ static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
netdev_err(bp->dev, "MDC/MDIO access timeout\n");
*ret_val = 0;
rc = -EFAULT;
-
} else {
/* data */
val = ((phy->addr << 21) | (devad << 16) |
@@ -1485,15 +2994,214 @@ static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
rc = -EFAULT;
}
}
+ /* Work around for E3 A0 */
+ if (phy->flags & FLAGS_MDC_MDIO_WA) {
+ phy->flags ^= FLAGS_DUMMY_READ;
+ if (phy->flags & FLAGS_DUMMY_READ) {
+ u16 temp_val;
+ bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
+ }
+ }
+
+ return rc;
+}
+
+static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 val)
+{
+ u32 tmp;
+ u8 i;
+ int rc = 0;
+
+ /* address */
+
+ tmp = ((phy->addr << 21) | (devad << 16) | reg |
+ EMAC_MDIO_COMM_COMMAND_ADDRESS |
+ EMAC_MDIO_COMM_START_BUSY);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+ if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+ break;
+ }
+ }
+ if (tmp & EMAC_MDIO_COMM_START_BUSY) {
+ DP(NETIF_MSG_LINK, "write phy register failed\n");
+ netdev_err(bp->dev, "MDC/MDIO access timeout\n");
+ rc = -EFAULT;
+
+ } else {
+ /* data */
+ tmp = ((phy->addr << 21) | (devad << 16) | val |
+ EMAC_MDIO_COMM_COMMAND_WRITE_45 |
+ EMAC_MDIO_COMM_START_BUSY);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ tmp = REG_RD(bp, phy->mdio_ctrl +
+ EMAC_REG_EMAC_MDIO_COMM);
+ if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+ break;
+ }
+ }
+ if (tmp & EMAC_MDIO_COMM_START_BUSY) {
+ DP(NETIF_MSG_LINK, "write phy register failed\n");
+ netdev_err(bp->dev, "MDC/MDIO access timeout\n");
+ rc = -EFAULT;
+ }
+ }
+ /* Work around for E3 A0 */
+ if (phy->flags & FLAGS_MDC_MDIO_WA) {
+ phy->flags ^= FLAGS_DUMMY_READ;
+ if (phy->flags & FLAGS_DUMMY_READ) {
+ u16 temp_val;
+ bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
+ }
+ }
+
+ return rc;
+}
+
- /* Restore the saved mode */
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
+/******************************************************************/
+/* BSC access functions from E3 */
+/******************************************************************/
+static void bnx2x_bsc_module_sel(struct link_params *params)
+{
+ int idx;
+ u32 board_cfg, sfp_ctrl;
+ u32 i2c_pins[I2C_SWITCH_WIDTH], i2c_val[I2C_SWITCH_WIDTH];
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+ /* Read I2C output PINs */
+ board_cfg = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.shared_hw_config.board));
+ i2c_pins[I2C_BSC0] = board_cfg & SHARED_HW_CFG_E3_I2C_MUX0_MASK;
+ i2c_pins[I2C_BSC1] = (board_cfg & SHARED_HW_CFG_E3_I2C_MUX1_MASK) >>
+ SHARED_HW_CFG_E3_I2C_MUX1_SHIFT;
+
+ /* Read I2C output value */
+ sfp_ctrl = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg));
+ i2c_val[I2C_BSC0] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX0_MASK) > 0;
+ i2c_val[I2C_BSC1] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX1_MASK) > 0;
+ DP(NETIF_MSG_LINK, "Setting BSC switch\n");
+ for (idx = 0; idx < I2C_SWITCH_WIDTH; idx++)
+ bnx2x_set_cfg_pin(bp, i2c_pins[idx], i2c_val[idx]);
+}
+
+static int bnx2x_bsc_read(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 sl_devid,
+ u16 sl_addr,
+ u8 lc_addr,
+ u8 xfer_cnt,
+ u32 *data_array)
+{
+ u32 val, i;
+ int rc = 0;
+ struct bnx2x *bp = params->bp;
+
+ if ((sl_devid != 0xa0) && (sl_devid != 0xa2)) {
+ DP(NETIF_MSG_LINK, "invalid sl_devid 0x%x\n", sl_devid);
+ return -EINVAL;
+ }
+
+ if (xfer_cnt > 16) {
+ DP(NETIF_MSG_LINK, "invalid xfer_cnt %d. Max is 16 bytes\n",
+ xfer_cnt);
+ return -EINVAL;
+ }
+ bnx2x_bsc_module_sel(params);
+
+ xfer_cnt = 16 - lc_addr;
+
+ /* enable the engine */
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ val |= MCPR_IMC_COMMAND_ENABLE;
+ REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+ /* program slave device ID */
+ val = (sl_devid << 16) | sl_addr;
+ REG_WR(bp, MCP_REG_MCPR_IMC_SLAVE_CONTROL, val);
+
+ /* start xfer with 0 byte to update the address pointer ???*/
+ val = (MCPR_IMC_COMMAND_ENABLE) |
+ (MCPR_IMC_COMMAND_WRITE_OP <<
+ MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
+ (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0);
+ REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+ /* poll for completion */
+ i = 0;
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
+ udelay(10);
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ if (i++ > 1000) {
+ DP(NETIF_MSG_LINK, "wr 0 byte timed out after %d try\n",
+ i);
+ rc = -EFAULT;
+ break;
+ }
+ }
+ if (rc == -EFAULT)
+ return rc;
+
+ /* start xfer with read op */
+ val = (MCPR_IMC_COMMAND_ENABLE) |
+ (MCPR_IMC_COMMAND_READ_OP <<
+ MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
+ (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) |
+ (xfer_cnt);
+ REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+ /* poll for completion */
+ i = 0;
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
+ udelay(10);
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ if (i++ > 1000) {
+ DP(NETIF_MSG_LINK, "rd op timed out after %d try\n", i);
+ rc = -EFAULT;
+ break;
+ }
+ }
+ if (rc == -EFAULT)
+ return rc;
+ for (i = (lc_addr >> 2); i < 4; i++) {
+ data_array[i] = REG_RD(bp, (MCP_REG_MCPR_IMC_DATAREG0 + i*4));
+#ifdef __BIG_ENDIAN
+ data_array[i] = ((data_array[i] & 0x000000ff) << 24) |
+ ((data_array[i] & 0x0000ff00) << 8) |
+ ((data_array[i] & 0x00ff0000) >> 8) |
+ ((data_array[i] & 0xff000000) >> 24);
+#endif
+ }
return rc;
}
-u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 *ret_val)
+static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 or_val)
+{
+ u16 val;
+ bnx2x_cl45_read(bp, phy, devad, reg, &val);
+ bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
+}
+
+int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 *ret_val)
{
u8 phy_index;
/*
@@ -1510,8 +3218,8 @@ u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
return -EINVAL;
}
-u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 val)
+int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 val)
{
u8 phy_index;
/*
@@ -1527,9 +3235,62 @@ u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
}
return -EINVAL;
}
+static u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ u8 lane = 0;
+ struct bnx2x *bp = params->bp;
+ u32 path_swap, path_swap_ovr;
+ u8 path, port;
+
+ path = BP_PATH(bp);
+ port = params->port;
+
+ if (bnx2x_is_4_port_mode(bp)) {
+ u32 port_swap, port_swap_ovr;
+
+ /*figure out path swap value */
+ path_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR);
+ if (path_swap_ovr & 0x1)
+ path_swap = (path_swap_ovr & 0x2);
+ else
+ path_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP);
+
+ if (path_swap)
+ path = path ^ 1;
-static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
- struct bnx2x_phy *phy)
+ /*figure out port swap value */
+ port_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR);
+ if (port_swap_ovr & 0x1)
+ port_swap = (port_swap_ovr & 0x2);
+ else
+ port_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP);
+
+ if (port_swap)
+ port = port ^ 1;
+
+ lane = (port<<1) + path;
+ } else { /* two port mode - no port swap */
+
+ /*figure out path swap value */
+ path_swap_ovr =
+ REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
+ if (path_swap_ovr & 0x1) {
+ path_swap = (path_swap_ovr & 0x2);
+ } else {
+ path_swap =
+ REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP);
+ }
+ if (path_swap)
+ path = path ^ 1;
+
+ lane = path << 1 ;
+ }
+ return lane;
+}
+
+static void bnx2x_set_aer_mmd(struct link_params *params,
+ struct bnx2x_phy *phy)
{
u32 ser_lane;
u16 offset, aer_val;
@@ -1538,20 +3299,28 @@ static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
- offset = phy->addr + ser_lane;
- if (CHIP_IS_E2(bp))
+ offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
+ (phy->addr + ser_lane) : 0;
+
+ if (USES_WARPCORE(bp)) {
+ aer_val = bnx2x_get_warpcore_lane(phy, params);
+ /*
+ * In Dual-lane mode, two lanes are joined together,
+ * so in order to configure them, the AER broadcast method is
+ * used here.
+ * 0x200 is the broadcast address for lanes 0,1
+ * 0x201 is the broadcast address for lanes 2,3
+ */
+ if (phy->flags & FLAGS_WC_DUAL_MODE)
+ aer_val = (aer_val >> 1) | 0x200;
+ } else if (CHIP_IS_E2(bp))
aer_val = 0x3800 + offset - 1;
else
aer_val = 0x3800 + offset;
+ DP(NETIF_MSG_LINK, "Set AER to 0x%x\n", aer_val);
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, aer_val);
-}
-static void bnx2x_set_aer_mmd_serdes(struct bnx2x *bp,
- struct bnx2x_phy *phy)
-{
- CL22_WR_OVER_CL45(bp, phy,
- MDIO_REG_BANK_AER_BLOCK,
- MDIO_AER_BLOCK_AER_REG, 0x3800);
+
}
/******************************************************************/
@@ -1611,20 +3380,979 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
params->phy[INT_PHY].def_md_devad);
}
+static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
+ struct link_params *params, u16 *ieee_fc)
+{
+ struct bnx2x *bp = params->bp;
+ *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
+ /**
+ * resolve pause mode and advertisement Please refer to Table
+ * 28B-3 of the 802.3ab-1999 spec
+ */
+
+ switch (phy->req_flow_ctrl) {
+ case BNX2X_FLOW_CTRL_AUTO:
+ if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ else
+ *ieee_fc |=
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+ break;
+
+ case BNX2X_FLOW_CTRL_TX:
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+ break;
+
+ case BNX2X_FLOW_CTRL_RX:
+ case BNX2X_FLOW_CTRL_BOTH:
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ break;
+
+ case BNX2X_FLOW_CTRL_NONE:
+ default:
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
+ break;
+ }
+ DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
+}
+
+static void set_phy_vars(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 actual_phy_idx, phy_index, link_cfg_idx;
+ u8 phy_config_swapped = params->multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+ for (phy_index = INT_PHY; phy_index < params->num_phys;
+ phy_index++) {
+ link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+ actual_phy_idx = phy_index;
+ if (phy_config_swapped) {
+ if (phy_index == EXT_PHY1)
+ actual_phy_idx = EXT_PHY2;
+ else if (phy_index == EXT_PHY2)
+ actual_phy_idx = EXT_PHY1;
+ }
+ params->phy[actual_phy_idx].req_flow_ctrl =
+ params->req_flow_ctrl[link_cfg_idx];
+
+ params->phy[actual_phy_idx].req_line_speed =
+ params->req_line_speed[link_cfg_idx];
+
+ params->phy[actual_phy_idx].speed_cap_mask =
+ params->speed_cap_mask[link_cfg_idx];
+
+ params->phy[actual_phy_idx].req_duplex =
+ params->req_duplex[link_cfg_idx];
+
+ if (params->req_line_speed[link_cfg_idx] ==
+ SPEED_AUTO_NEG)
+ vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
+
+ DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
+ " speed_cap_mask %x\n",
+ params->phy[actual_phy_idx].req_flow_ctrl,
+ params->phy[actual_phy_idx].req_line_speed,
+ params->phy[actual_phy_idx].speed_cap_mask);
+ }
+}
+
+static void bnx2x_ext_phy_set_pause(struct link_params *params,
+ struct bnx2x_phy *phy,
+ struct link_vars *vars)
+{
+ u16 val;
+ struct bnx2x *bp = params->bp;
+ /* read modify write pause advertizing */
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
+
+ val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
+
+ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+ val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+ }
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+ val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
+ }
+ DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
+}
+
+static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
+{ /* LD LP */
+ switch (pause_result) { /* ASYM P ASYM P */
+ case 0xb: /* 1 0 1 1 */
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
+ break;
+
+ case 0xe: /* 1 1 1 0 */
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
+ break;
+
+ case 0x5: /* 0 1 0 1 */
+ case 0x7: /* 0 1 1 1 */
+ case 0xd: /* 1 1 0 1 */
+ case 0xf: /* 1 1 1 1 */
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
+ break;
+
+ default:
+ break;
+ }
+ if (pause_result & (1<<0))
+ vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
+ if (pause_result & (1<<1))
+ vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
+}
+
+static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 ld_pause; /* local */
+ u16 lp_pause; /* link partner */
+ u16 pause_result;
+ u8 ret = 0;
+ /* read twice */
+
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+ if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+ vars->flow_ctrl = phy->req_flow_ctrl;
+ else if (phy->req_line_speed != SPEED_AUTO_NEG)
+ vars->flow_ctrl = params->req_fc_auto_adv;
+ else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+ ret = 1;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
+ bnx2x_cl22_read(bp, phy,
+ 0x4, &ld_pause);
+ bnx2x_cl22_read(bp, phy,
+ 0x5, &lp_pause);
+ } else {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+ }
+ pause_result = (ld_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
+ pause_result |= (lp_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
+ DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
+ pause_result);
+ bnx2x_pause_resolve(vars, pause_result);
+ }
+ return ret;
+}
+/******************************************************************/
+/* Warpcore section */
+/******************************************************************/
+/* The init_internal_warpcore should mirror the xgxs,
+ * i.e. reset the lane (if needed), set aer for the
+ * init configuration, and set/clear SGMII flag. Internal
+ * phy init is done purely in phy_init stage.
+ */
+static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars) {
+ u16 val16 = 0, lane, bam37 = 0;
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
+ /* Check adding advertisement for 1G KX */
+ if (((vars->line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+ (vars->line_speed == SPEED_1000)) {
+ u16 sd_digital;
+ val16 |= (1<<5);
+
+ /* Enable CL37 1G Parallel Detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &sd_digital);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ (sd_digital | 0x1));
+
+ DP(NETIF_MSG_LINK, "Advertize 1G\n");
+ }
+ if (((vars->line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
+ (vars->line_speed == SPEED_10000)) {
+ /* Check adding advertisement for 10G KR */
+ val16 |= (1<<7);
+ /* Enable 10G Parallel Detect */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
+
+ DP(NETIF_MSG_LINK, "Advertize 10G\n");
+ }
+
+ /* Set Transmit PMD settings */
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+ ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
+ 0x03f0);
+ 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,
+ MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+
+ /* Enable CL37 BAM */
+ if (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[params->port].default_cfg)) &
+ PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, &bam37);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, bam37 | 1);
+ DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n");
+ }
+
+ /* 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);
+
+ 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);
+}
+
+static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val;
+
+ /* Disable Autoneg */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7);
+
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_PAR_DET_10G_CTRL, 0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00);
+
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL3_UP1, 0x1);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC7, 0xa);
+
+ /* Disable CL36 PCS Tx */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0);
+
+ /* Double Wide Single Data Rate @ pll rate */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF);
+
+ /* Leave cl72 training enable, needed for KR */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
+ 0x2);
+
+ /* Leave CL72 enabled */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+ &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+ val | 0x3800);
+
+ /* Set speed via PMA/PMD register */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
+
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB);
+
+ /*Enable encoded forced speed */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
+
+ /* Turn TX scramble payload only the 64/66 scrambler */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX66_CONTROL, 0x9);
+
+ /* Turn RX scramble payload only the 64/66 scrambler */
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, 0xF9);
+
+ /* set and clear loopback to cause a reset to 64/66 decoder */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
+
+}
+
+static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u8 is_xfi)
+{
+ struct bnx2x *bp = params->bp;
+ u16 misc1_val, tap_val, tx_driver_val, lane, val;
+ /* Hold rxSeqStart */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val | 0x8000));
+
+ /* Hold tx_fifo_reset */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, (val | 0x1));
+
+ /* Disable CL73 AN */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
+
+ /* Disable 100FX Enable and Auto-Detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL1, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
+
+ /* Disable 100FX Idle detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL3, (val | 0x0080));
+
+ /* Set Block address to Remote PHY & Clear forced_speed[5] */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
+
+ /* Turn off auto-detect & fiber mode */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+ (val & 0xFFEE));
+
+ /* Set filter_force_link, disable_false_link and parallel_detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ ((val | 0x0006) & 0xFFFE));
+
+ /* Set XFI / SFI */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, &misc1_val);
+
+ misc1_val &= ~(0x1f);
+
+ if (is_xfi) {
+ misc1_val |= 0x5;
+ tap_val = ((0x08 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+ (0x37 << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+ (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+ tx_driver_val =
+ ((0x00 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x03 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+
+ } else {
+ misc1_val |= 0x9;
+ tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+ (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+ (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+ tx_driver_val =
+ ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+ }
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
+
+ /* Set Transmit PMD settings */
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX_FIR_TAP,
+ tap_val | MDIO_WC_REG_TX_FIR_TAP_ENABLE);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+ tx_driver_val);
+
+ /* Enable fiber mode, enable and invert sig_det */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, val | 0xd);
+
+ /* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, val | 0x8080);
+
+ /* 10G XFI Full Duplex */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
+
+ /* Release tx_fifo_reset */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
+
+ /* Release rxSeqStart */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
+}
+
+static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
+ struct bnx2x_phy *phy)
+{
+ DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
+}
+
+static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 lane)
+{
+ /* Rx0 anaRxControl1G */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90);
+
+ /* Rx2 anaRxControl1G */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW0, 0xE070);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW1, 0xC0D0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW2, 0xA0B0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW3, 0x8090);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0);
+
+ /* Serdes Digital Misc1 */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008);
+
+ /* Serdes Digital4 Misc3 */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, 0x8088);
+
+ /* Set Transmit PMD settings */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX_FIR_TAP,
+ ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+ (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+ (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET) |
+ MDIO_WC_REG_TX_FIR_TAP_ENABLE));
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+ ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+}
+
+static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u8 fiber_mode)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16, digctrl_kx1, digctrl_kx2;
+ u8 lane;
+
+ lane = bnx2x_get_warpcore_lane(phy, params);
+
+ /* Clear XFI clock comp in non-10G single lane mode. */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
+
+ if (phy->req_line_speed == SPEED_AUTO_NEG) {
+ /* SGMII Autoneg */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
+ val16 | 0x1000);
+ DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
+ } else {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ val16 &= 0xcfbf;
+ switch (phy->req_line_speed) {
+ case SPEED_10:
+ break;
+ case SPEED_100:
+ val16 |= 0x2000;
+ break;
+ case SPEED_1000:
+ val16 |= 0x0040;
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Speed not supported: 0x%x"
+ "\n", phy->req_line_speed);
+ return;
+ }
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ val16 |= 0x0100;
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16);
+
+ DP(NETIF_MSG_LINK, "set SGMII force speed %d\n",
+ phy->req_line_speed);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ DP(NETIF_MSG_LINK, " (readback) %x\n", val16);
+ }
+
+ /* SGMII Slave mode and disable signal detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &digctrl_kx1);
+ if (fiber_mode)
+ digctrl_kx1 = 1;
+ else
+ digctrl_kx1 &= 0xff4a;
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+ digctrl_kx1);
+
+ /* Turn off parallel detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &digctrl_kx2);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ (digctrl_kx2 & ~(1<<2)));
+
+ /* Re-enable parallel detect */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ (digctrl_kx2 | (1<<2)));
+
+ /* Enable autodet */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+ (digctrl_kx1 | 0x10));
+}
+
+static void bnx2x_warpcore_reset_lane(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 reset)
+{
+ u16 val;
+ /* Take lane out of reset after configuration is finished */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC6, &val);
+ if (reset)
+ val |= 0xC000;
+ else
+ val &= 0x3FFF;
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC6, val);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC6, &val);
+}
+
+
+ /* Clear SFI/XFI link settings registers */
+static void bnx2x_warpcore_clear_regs(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 lane)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16;
+
+ /* Set XFI clock comp as default. */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, val16 | (3<<13));
+
+ bnx2x_warpcore_reset_lane(bp, phy, 1);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL1, 0x014a);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL3, 0x0800);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, 0x8008);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x0195);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x0007);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x0002);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6000);
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX_FIR_TAP, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane, 0x0990);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x0140);
+ bnx2x_warpcore_reset_lane(bp, phy, 0);
+}
+
+static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
+ u32 chip_id,
+ u32 shmem_base, u8 port,
+ u8 *gpio_num, u8 *gpio_port)
+{
+ u32 cfg_pin;
+ *gpio_num = 0;
+ *gpio_port = 0;
+ if (CHIP_IS_E3(bp)) {
+ cfg_pin = (REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_E3_MOD_ABS_MASK) >>
+ PORT_HW_CFG_E3_MOD_ABS_SHIFT;
+
+ /*
+ * Should not happen. This function called upon interrupt
+ * triggered by GPIO ( since EPIO can only generate interrupts
+ * to MCP).
+ * So if this function was called and none of the GPIOs was set,
+ * it means the shit hit the fan.
+ */
+ 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);
+ return -EINVAL;
+ }
+
+ *gpio_num = (cfg_pin - PIN_CFG_GPIO0_P0) & 0x3;
+ *gpio_port = (cfg_pin - PIN_CFG_GPIO0_P0) >> 2;
+ } else {
+ *gpio_num = MISC_REGISTERS_GPIO_3;
+ *gpio_port = port;
+ }
+ DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
+ return 0;
+}
+
+static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 gpio_num, gpio_port;
+ u32 gpio_val;
+ if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id,
+ params->shmem_base, params->port,
+ &gpio_num, &gpio_port) != 0)
+ return 0;
+ gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
+
+ /* Call the handling function in case module is detected */
+ if (gpio_val == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u32 serdes_net_if;
+ u8 fiber_mode;
+ u16 lane = bnx2x_get_warpcore_lane(phy, params);
+ serdes_net_if = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[params->port].default_cfg)) &
+ PORT_HW_CFG_NET_SERDES_IF_MASK);
+ DP(NETIF_MSG_LINK, "Begin Warpcore init, link_speed %d, "
+ "serdes_net_if = 0x%x\n",
+ vars->line_speed, serdes_net_if);
+ bnx2x_set_aer_mmd(params, phy);
+
+ vars->phy_flags |= PHY_XGXS_FLAG;
+ if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) ||
+ (phy->req_line_speed &&
+ ((phy->req_line_speed == SPEED_100) ||
+ (phy->req_line_speed == SPEED_10)))) {
+ vars->phy_flags |= PHY_SGMII_FLAG;
+ DP(NETIF_MSG_LINK, "Setting SGMII mode\n");
+ bnx2x_warpcore_clear_regs(phy, params, lane);
+ bnx2x_warpcore_set_sgmii_speed(phy, params, 0);
+ } else {
+ switch (serdes_net_if) {
+ case PORT_HW_CFG_NET_SERDES_IF_KR:
+ /* Enable KR Auto Neg */
+ if (params->loopback_mode == LOOPBACK_NONE)
+ bnx2x_warpcore_enable_AN_KR(phy, params, vars);
+ else {
+ DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n");
+ bnx2x_warpcore_set_10G_KR(phy, params, vars);
+ }
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_XFI:
+ bnx2x_warpcore_clear_regs(phy, params, lane);
+ if (vars->line_speed == SPEED_10000) {
+ DP(NETIF_MSG_LINK, "Setting 10G XFI\n");
+ bnx2x_warpcore_set_10G_XFI(phy, params, 1);
+ } else {
+ if (SINGLE_MEDIA_DIRECT(params)) {
+ DP(NETIF_MSG_LINK, "1G Fiber\n");
+ fiber_mode = 1;
+ } else {
+ DP(NETIF_MSG_LINK, "10/100/1G SGMII\n");
+ fiber_mode = 0;
+ }
+ bnx2x_warpcore_set_sgmii_speed(phy,
+ params,
+ fiber_mode);
+ }
+
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_SFI:
+
+ bnx2x_warpcore_clear_regs(phy, params, lane);
+ if (vars->line_speed == SPEED_10000) {
+ DP(NETIF_MSG_LINK, "Setting 10G SFI\n");
+ bnx2x_warpcore_set_10G_XFI(phy, params, 0);
+ } else if (vars->line_speed == SPEED_1000) {
+ DP(NETIF_MSG_LINK, "Setting 1G Fiber\n");
+ bnx2x_warpcore_set_sgmii_speed(phy, params, 1);
+ }
+ /* Issue Module detection */
+ if (bnx2x_is_sfp_module_plugged(phy, params))
+ bnx2x_sfp_module_detection(phy, params);
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
+ if (vars->line_speed != SPEED_20000) {
+ DP(NETIF_MSG_LINK, "Speed not supported yet\n");
+ return;
+ }
+ DP(NETIF_MSG_LINK, "Setting 20G DXGXS\n");
+ bnx2x_warpcore_set_20G_DXGXS(bp, phy, lane);
+ /* Issue Module detection */
+
+ bnx2x_sfp_module_detection(phy, params);
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_KR2:
+ if (vars->line_speed != SPEED_20000) {
+ DP(NETIF_MSG_LINK, "Speed not supported yet\n");
+ return;
+ }
+ DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
+ bnx2x_warpcore_set_20G_KR2(bp, phy);
+ break;
+
+ default:
+ DP(NETIF_MSG_LINK, "Unsupported Serdes Net Interface "
+ "0x%x\n", serdes_net_if);
+ return;
+ }
+ }
+
+ /* Take lane out of reset after configuration is finished */
+ bnx2x_warpcore_reset_lane(bp, phy, 0);
+ DP(NETIF_MSG_LINK, "Exit config init\n");
+}
+
+static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 tx_en)
+{
+ struct bnx2x *bp = params->bp;
+ u32 cfg_pin;
+ u8 port = params->port;
+
+ cfg_pin = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_TX_LASER_MASK;
+ /* Set the !tx_en since this pin is DISABLE_TX_LASER */
+ DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
+ /* For 20G, the expected pin to be used is 3 pins after the current */
+
+ bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
+ if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
+ bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
+}
+
+static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16;
+ bnx2x_sfp_e3_set_transmitter(params, phy, 0);
+ bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+ bnx2x_set_aer_mmd(params, phy);
+ /* Global register */
+ bnx2x_warpcore_reset_lane(bp, phy, 1);
+
+ /* Clear loopback settings (if any) */
+ /* 10G & 20G */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
+ 0xBFFF);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
+
+ /* Update those 1-copy registers */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+ /* Enable 1G MDIO (1-copy) */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ val16 & ~0x10);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+ val16 & 0xff00);
+
+}
+
+static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16;
+ u32 lane;
+ DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
+ params->loopback_mode, phy->req_line_speed);
+
+ if (phy->req_line_speed < SPEED_10000) {
+ /* 10/100/1000 */
+
+ /* Update those 1-copy registers */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+ /* Enable 1G MDIO (1-copy) */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ val16 | 0x10);
+ /* Set 1G loopback based on lane (1-copy) */
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+ val16 | (1<<lane));
+
+ /* Switch back to 4-copy registers */
+ bnx2x_set_aer_mmd(params, phy);
+ /* Global loopback, not recommended. */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
+ 0x4000);
+ } else {
+ /* 10G & 20G */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
+ 0x4000);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 | 0x1);
+ }
+}
+
void bnx2x_link_status_update(struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u8 link_10g;
+ u8 link_10g_plus;
u8 port = params->port;
+ u32 sync_offset, media_types;
+ /* Update PHY configuration */
+ set_phy_vars(params, vars);
vars->link_status = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region,
port_mb[port].link_status));
vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-
+ vars->phy_flags = PHY_XGXS_FLAG;
if (vars->link_up) {
DP(NETIF_MSG_LINK, "phy link up\n");
@@ -1664,27 +4392,9 @@ void bnx2x_link_status_update(struct link_params *params,
case LINK_10GTFD:
vars->line_speed = SPEED_10000;
break;
-
- case LINK_12GTFD:
- vars->line_speed = SPEED_12000;
- break;
-
- case LINK_12_5GTFD:
- vars->line_speed = SPEED_12500;
- break;
-
- case LINK_13GTFD:
- vars->line_speed = SPEED_13000;
+ case LINK_20GTFD:
+ vars->line_speed = SPEED_20000;
break;
-
- case LINK_15GTFD:
- vars->line_speed = SPEED_15000;
- break;
-
- case LINK_16GTFD:
- vars->line_speed = SPEED_16000;
- break;
-
default:
break;
}
@@ -1705,19 +4415,24 @@ void bnx2x_link_status_update(struct link_params *params,
} else {
vars->phy_flags &= ~PHY_SGMII_FLAG;
}
-
+ if (vars->line_speed &&
+ USES_WARPCORE(bp) &&
+ (vars->line_speed == SPEED_1000))
+ vars->phy_flags |= PHY_SGMII_FLAG;
/* anything 10 and over uses the bmac */
- link_10g = ((vars->line_speed == SPEED_10000) ||
- (vars->line_speed == SPEED_12000) ||
- (vars->line_speed == SPEED_12500) ||
- (vars->line_speed == SPEED_13000) ||
- (vars->line_speed == SPEED_15000) ||
- (vars->line_speed == SPEED_16000));
- if (link_10g)
- vars->mac_type = MAC_TYPE_BMAC;
- else
- vars->mac_type = MAC_TYPE_EMAC;
+ link_10g_plus = (vars->line_speed >= SPEED_10000);
+ if (link_10g_plus) {
+ if (USES_WARPCORE(bp))
+ vars->mac_type = MAC_TYPE_XMAC;
+ else
+ vars->mac_type = MAC_TYPE_BMAC;
+ } else {
+ if (USES_WARPCORE(bp))
+ vars->mac_type = MAC_TYPE_UMAC;
+ else
+ vars->mac_type = MAC_TYPE_EMAC;
+ }
} else { /* link down */
DP(NETIF_MSG_LINK, "phy link down\n");
@@ -1731,8 +4446,40 @@ void bnx2x_link_status_update(struct link_params *params,
vars->mac_type = MAC_TYPE_NONE;
}
- DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
- vars->link_status, vars->phy_link_up);
+ /* Sync media type */
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].media_type);
+ media_types = REG_RD(bp, sync_offset);
+
+ params->phy[INT_PHY].media_type =
+ (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >>
+ PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT;
+ params->phy[EXT_PHY1].media_type =
+ (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >>
+ PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT;
+ params->phy[EXT_PHY2].media_type =
+ (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >>
+ PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
+ DP(NETIF_MSG_LINK, "media_types = 0x%x\n", media_types);
+
+ /* Sync AEU offset */
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].aeu_int_mask);
+
+ vars->aeu_int_mask = REG_RD(bp, sync_offset);
+
+ /* Sync PFC status */
+ if (vars->link_status & LINK_STATUS_PFC_ENABLED)
+ params->feature_config_flags |=
+ FEATURE_CONFIG_PFC_ENABLED;
+ else
+ params->feature_config_flags &=
+ ~FEATURE_CONFIG_PFC_ENABLED;
+
+ DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n",
+ vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
vars->line_speed, vars->duplex, vars->flow_ctrl);
}
@@ -1759,9 +4506,9 @@ static void bnx2x_set_master_ln(struct link_params *params,
(new_master_ln | ser_lane));
}
-static u8 bnx2x_reset_unicore(struct link_params *params,
- struct bnx2x_phy *phy,
- u8 set_serdes)
+static int bnx2x_reset_unicore(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 set_serdes)
{
struct bnx2x *bp = params->bp;
u16 mii_control;
@@ -2048,9 +4795,6 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
if (vars->line_speed == SPEED_10000)
reg_val |=
MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
- if (vars->line_speed == SPEED_13000)
- reg_val |=
- MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
}
CL22_WR_OVER_CL45(bp, phy,
@@ -2059,8 +4803,8 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
}
-static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
- struct link_params *params)
+static void bnx2x_set_brcm_cl37_advertisement(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 val = 0;
@@ -2081,44 +4825,9 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
MDIO_OVER_1G_UP3, 0x400);
}
-static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
- struct link_params *params, u16 *ieee_fc)
-{
- struct bnx2x *bp = params->bp;
- *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
- /*
- * Resolve pause mode and advertisement.
- * Please refer to Table 28B-3 of the 802.3ab-1999 spec
- */
-
- switch (phy->req_flow_ctrl) {
- case BNX2X_FLOW_CTRL_AUTO:
- if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
- else
- *ieee_fc |=
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
- break;
- case BNX2X_FLOW_CTRL_TX:
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
- break;
-
- case BNX2X_FLOW_CTRL_RX:
- case BNX2X_FLOW_CTRL_BOTH:
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
- break;
-
- case BNX2X_FLOW_CTRL_NONE:
- default:
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
- break;
- }
- DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
-}
-
-static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 ieee_fc)
+static void bnx2x_set_ieee_aneg_advertisement(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 ieee_fc)
{
struct bnx2x *bp = params->bp;
u16 val;
@@ -2252,35 +4961,8 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
* link management
*/
-static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
-{ /* LD LP */
- switch (pause_result) { /* ASYM P ASYM P */
- case 0xb: /* 1 0 1 1 */
- vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
- break;
-
- case 0xe: /* 1 1 1 0 */
- vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
- break;
-
- case 0x5: /* 0 1 0 1 */
- case 0x7: /* 0 1 1 1 */
- case 0xd: /* 1 1 0 1 */
- case 0xf: /* 1 1 1 1 */
- vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
- break;
-
- default:
- break;
- }
- if (pause_result & (1<<0))
- vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
- if (pause_result & (1<<1))
- vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
-}
-
-static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
- struct link_params *params)
+static int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 pd_10g, status2_1000x;
@@ -2383,7 +5065,7 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u16 rx_status, ustat_val, cl37_fsm_recieved;
+ u16 rx_status, ustat_val, cl37_fsm_received;
DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
/* Step 1: Make sure signal is detected */
CL22_RD_OVER_CL45(bp, phy,
@@ -2421,15 +5103,15 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
CL22_RD_OVER_CL45(bp, phy,
MDIO_REG_BANK_REMOTE_PHY,
MDIO_REMOTE_PHY_MISC_RX_STATUS,
- &cl37_fsm_recieved);
- if ((cl37_fsm_recieved &
+ &cl37_fsm_received);
+ if ((cl37_fsm_received &
(MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
(MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
"misc_rx_status(0x8330) = 0x%x\n",
- cl37_fsm_recieved);
+ cl37_fsm_received);
return;
}
/*
@@ -2462,45 +5144,25 @@ static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
vars->link_status |=
LINK_STATUS_PARALLEL_DETECTION_USED;
}
-
-static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
+static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
struct link_params *params,
- struct link_vars *vars)
+ struct link_vars *vars,
+ u16 is_link_up,
+ u16 speed_mask,
+ u16 is_duplex)
{
struct bnx2x *bp = params->bp;
- u16 new_line_speed, gp_status;
- u8 rc = 0;
-
- /* Read gp_status */
- CL22_RD_OVER_CL45(bp, phy,
- MDIO_REG_BANK_GP_STATUS,
- MDIO_GP_STATUS_TOP_AN_STATUS1,
- &gp_status);
-
if (phy->req_line_speed == SPEED_AUTO_NEG)
vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
- if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
- DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
- gp_status);
+ if (is_link_up) {
+ DP(NETIF_MSG_LINK, "phy link up\n");
vars->phy_link_up = 1;
vars->link_status |= LINK_STATUS_LINK_UP;
- if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
- vars->duplex = DUPLEX_FULL;
- else
- vars->duplex = DUPLEX_HALF;
-
- if (SINGLE_MEDIA_DIRECT(params)) {
- bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
- if (phy->req_line_speed == SPEED_AUTO_NEG)
- bnx2x_xgxs_an_resolve(phy, params, vars,
- gp_status);
- }
-
- switch (gp_status & GP_STATUS_SPEED_MASK) {
+ switch (speed_mask) {
case GP_STATUS_10M:
- new_line_speed = SPEED_10;
+ vars->line_speed = SPEED_10;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_10TFD;
else
@@ -2508,7 +5170,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
break;
case GP_STATUS_100M:
- new_line_speed = SPEED_100;
+ vars->line_speed = SPEED_100;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_100TXFD;
else
@@ -2517,7 +5179,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
case GP_STATUS_1G:
case GP_STATUS_1G_KX:
- new_line_speed = SPEED_1000;
+ vars->line_speed = SPEED_1000;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_1000TFD;
else
@@ -2525,7 +5187,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
break;
case GP_STATUS_2_5G:
- new_line_speed = SPEED_2500;
+ vars->line_speed = SPEED_2500;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_2500TFD;
else
@@ -2536,50 +5198,28 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
case GP_STATUS_6G:
DP(NETIF_MSG_LINK,
"link speed unsupported gp_status 0x%x\n",
- gp_status);
+ speed_mask);
return -EINVAL;
case GP_STATUS_10G_KX4:
case GP_STATUS_10G_HIG:
case GP_STATUS_10G_CX4:
- new_line_speed = SPEED_10000;
+ case GP_STATUS_10G_KR:
+ case GP_STATUS_10G_SFI:
+ case GP_STATUS_10G_XFI:
+ vars->line_speed = SPEED_10000;
vars->link_status |= LINK_10GTFD;
break;
-
- case GP_STATUS_12G_HIG:
- new_line_speed = SPEED_12000;
- vars->link_status |= LINK_12GTFD;
- break;
-
- case GP_STATUS_12_5G:
- new_line_speed = SPEED_12500;
- vars->link_status |= LINK_12_5GTFD;
- break;
-
- case GP_STATUS_13G:
- new_line_speed = SPEED_13000;
- vars->link_status |= LINK_13GTFD;
+ case GP_STATUS_20G_DXGXS:
+ vars->line_speed = SPEED_20000;
+ vars->link_status |= LINK_20GTFD;
break;
-
- case GP_STATUS_15G:
- new_line_speed = SPEED_15000;
- vars->link_status |= LINK_15GTFD;
- break;
-
- case GP_STATUS_16G:
- new_line_speed = SPEED_16000;
- vars->link_status |= LINK_16GTFD;
- break;
-
default:
DP(NETIF_MSG_LINK,
"link speed unsupported gp_status 0x%x\n",
- gp_status);
+ speed_mask);
return -EINVAL;
}
-
- vars->line_speed = new_line_speed;
-
} else { /* link_down */
DP(NETIF_MSG_LINK, "phy link down\n");
@@ -2588,7 +5228,47 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
vars->duplex = DUPLEX_FULL;
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->mac_type = MAC_TYPE_NONE;
+ }
+ DP(NETIF_MSG_LINK, " phy_link_up %x line_speed %d\n",
+ vars->phy_link_up, vars->line_speed);
+ return 0;
+}
+
+static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+
+ struct bnx2x *bp = params->bp;
+
+ u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
+ int rc = 0;
+ /* Read gp_status */
+ CL22_RD_OVER_CL45(bp, phy,
+ MDIO_REG_BANK_GP_STATUS,
+ MDIO_GP_STATUS_TOP_AN_STATUS1,
+ &gp_status);
+ if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
+ duplex = DUPLEX_FULL;
+ if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)
+ link_up = 1;
+ speed_mask = gp_status & GP_STATUS_SPEED_MASK;
+ DP(NETIF_MSG_LINK, "gp_status 0x%x, is_link_up %d, speed_mask 0x%x\n",
+ gp_status, link_up, speed_mask);
+ rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, speed_mask,
+ duplex);
+ if (rc == -EINVAL)
+ return rc;
+
+ if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
+ if (SINGLE_MEDIA_DIRECT(params)) {
+ bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
+ if (phy->req_line_speed == SPEED_AUTO_NEG)
+ bnx2x_xgxs_an_resolve(phy, params, vars,
+ gp_status);
+ }
+ } else { /* link_down */
if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
SINGLE_MEDIA_DIRECT(params)) {
/* Check signal is detected */
@@ -2596,13 +5276,86 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
}
}
- DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n",
- gp_status, vars->phy_link_up, vars->line_speed);
DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
vars->duplex, vars->flow_ctrl, vars->link_status);
return rc;
}
+static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+
+ struct bnx2x *bp = params->bp;
+
+ u8 lane;
+ u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
+ int rc = 0;
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ /* Read gp_status */
+ if (phy->req_line_speed > SPEED_10000) {
+ u16 temp_link_up;
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ 1, &temp_link_up);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ 1, &link_up);
+ DP(NETIF_MSG_LINK, "PCS RX link status = 0x%x-->0x%x\n",
+ temp_link_up, link_up);
+ link_up &= (1<<2);
+ if (link_up)
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ } else {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
+ DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
+ /* Check for either KR or generic link up. */
+ gp_status1 = ((gp_status1 >> 8) & 0xf) |
+ ((gp_status1 >> 12) & 0xf);
+ link_up = gp_status1 & (1 << lane);
+ if (link_up && SINGLE_MEDIA_DIRECT(params)) {
+ u16 pd, gp_status4;
+ if (phy->req_line_speed == SPEED_AUTO_NEG) {
+ /* Check Autoneg complete */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_4,
+ &gp_status4);
+ if (gp_status4 & ((1<<12)<<lane))
+ vars->link_status |=
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+
+ /* Check parallel detect used */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_PAR_DET_10G_STATUS,
+ &pd);
+ if (pd & (1<<15))
+ vars->link_status |=
+ LINK_STATUS_PARALLEL_DETECTION_USED;
+ }
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ }
+ }
+
+ if (lane < 2) {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
+ } else {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_3, &gp_speed);
+ }
+ DP(NETIF_MSG_LINK, "lane %d gp_speed 0x%x\n", lane, gp_speed);
+
+ if ((lane & 1) == 0)
+ gp_speed <<= 8;
+ gp_speed &= 0x3f00;
+
+
+ rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
+ duplex);
+
+ DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
+ vars->duplex, vars->flow_ctrl, vars->link_status);
+ return rc;
+}
static void bnx2x_set_gmii_tx_driver(struct link_params *params)
{
struct bnx2x *bp = params->bp;
@@ -2642,8 +5395,8 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
}
}
-static u8 bnx2x_emac_program(struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_emac_program(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -2713,9 +5466,9 @@ static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
}
}
-static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_xgxs_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
@@ -2742,11 +5495,11 @@ static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "not SGMII, AN\n");
/* AN enabled */
- bnx2x_set_brcm_cl37_advertisment(phy, params);
+ bnx2x_set_brcm_cl37_advertisement(phy, params);
/* program duplex & pause advertisement (for aneg) */
- bnx2x_set_ieee_aneg_advertisment(phy, params,
- vars->ieee_fc);
+ bnx2x_set_ieee_aneg_advertisement(phy, params,
+ vars->ieee_fc);
/* enable autoneg */
bnx2x_set_autoneg(phy, params, vars, enable_cl73);
@@ -2762,29 +5515,12 @@ static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
}
}
-static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
-{
- u8 rc;
- vars->phy_flags |= PHY_SGMII_FLAG;
- bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
- bnx2x_set_aer_mmd_serdes(params->bp, phy);
- rc = bnx2x_reset_unicore(params, phy, 1);
- /* reset the SerDes and wait for reset bit return low */
- if (rc != 0)
- return rc;
- bnx2x_set_aer_mmd_serdes(params->bp, phy);
-
- return rc;
-}
-
-static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
+static int bnx2x_prepare_xgxs(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars)
{
- u8 rc;
- vars->phy_flags = PHY_XGXS_FLAG;
+ int rc;
+ vars->phy_flags |= PHY_XGXS_FLAG;
if ((phy->req_line_speed &&
((phy->req_line_speed == SPEED_100) ||
(phy->req_line_speed == SPEED_10))) ||
@@ -2792,26 +5528,28 @@ static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
(phy->speed_cap_mask >=
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
(phy->speed_cap_mask <
- PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
- ))
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+ (phy->type == PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD))
vars->phy_flags |= PHY_SGMII_FLAG;
else
vars->phy_flags &= ~PHY_SGMII_FLAG;
bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
- bnx2x_set_aer_mmd_xgxs(params, phy);
- bnx2x_set_master_ln(params, phy);
+ bnx2x_set_aer_mmd(params, phy);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+ bnx2x_set_master_ln(params, phy);
rc = bnx2x_reset_unicore(params, phy, 0);
/* reset the SerDes and wait for reset bit return low */
if (rc != 0)
return rc;
- bnx2x_set_aer_mmd_xgxs(params, phy);
-
+ bnx2x_set_aer_mmd(params, phy);
/* setting the masterLn_def again after the reset */
- bnx2x_set_master_ln(params, phy);
- bnx2x_set_swap_lanes(params, phy);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
+ bnx2x_set_master_ln(params, phy);
+ bnx2x_set_swap_lanes(params, phy);
+ }
return rc;
}
@@ -2823,8 +5561,13 @@ static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
u16 cnt, ctrl;
/* Wait for soft reset to get cleared up to 1 sec */
for (cnt = 0; cnt < 1000; cnt++) {
- bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
+ bnx2x_cl22_read(bp, phy,
+ MDIO_PMA_REG_CTRL, &ctrl);
+ else
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, &ctrl);
if (!(ctrl & (1<<15)))
break;
msleep(1);
@@ -2845,7 +5588,11 @@ static void bnx2x_link_int_enable(struct link_params *params)
struct bnx2x *bp = params->bp;
/* Setting the status to report on link up for either XGXS or SerDes */
- if (params->switch_cfg == SWITCH_CFG_10G) {
+ if (CHIP_IS_E3(bp)) {
+ mask = NIG_MASK_XGXS0_LINK_STATUS;
+ if (!(SINGLE_MEDIA_DIRECT(params)))
+ mask |= NIG_MASK_MI_INT;
+ } else if (params->switch_cfg == SWITCH_CFG_10G) {
mask = (NIG_MASK_XGXS0_LINK10G |
NIG_MASK_XGXS0_LINK_STATUS);
DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
@@ -2918,11 +5665,11 @@ static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
}
static void bnx2x_link_int_ack(struct link_params *params,
- struct link_vars *vars, u8 is_10g)
+ struct link_vars *vars, u8 is_10g_plus)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
-
+ u32 mask;
/*
* First reset all status we assume only one line will be
* change at a time
@@ -2932,47 +5679,34 @@ static void bnx2x_link_int_ack(struct link_params *params,
NIG_STATUS_XGXS0_LINK_STATUS |
NIG_STATUS_SERDES0_LINK_STATUS));
if (vars->phy_link_up) {
- if (is_10g) {
- /*
- * Disable the 10G link interrupt by writing 1 to the
- * status register
- */
- DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- NIG_STATUS_XGXS0_LINK10G);
-
- } else if (params->switch_cfg == SWITCH_CFG_10G) {
- /*
- * Disable the link interrupt by writing 1 to the
- * relevant lane in the status register
- */
- u32 ser_lane = ((params->lane_config &
+ if (USES_WARPCORE(bp))
+ mask = NIG_STATUS_XGXS0_LINK_STATUS;
+ else {
+ if (is_10g_plus)
+ mask = NIG_STATUS_XGXS0_LINK10G;
+ else if (params->switch_cfg == SWITCH_CFG_10G) {
+ /*
+ * Disable the link interrupt by writing 1 to
+ * the relevant lane in the status register
+ */
+ u32 ser_lane =
+ ((params->lane_config &
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
-
- DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n",
- vars->line_speed);
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- ((1 << ser_lane) <<
- NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
-
- } else { /* SerDes */
- DP(NETIF_MSG_LINK, "SerDes phy link up\n");
- /*
- * Disable the link interrupt by writing 1 to the status
- * register
- */
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- NIG_STATUS_SERDES0_LINK_STATUS);
+ mask = ((1 << ser_lane) <<
+ NIG_STATUS_XGXS0_LINK_STATUS_SIZE);
+ } else
+ mask = NIG_STATUS_SERDES0_LINK_STATUS;
}
-
+ DP(NETIF_MSG_LINK, "Ack link up interrupt with mask 0x%x\n",
+ mask);
+ bnx2x_bits_en(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
+ mask);
}
}
-static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
+static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
{
u8 *str_ptr = str;
u32 mask = 0xf0000000;
@@ -3011,19 +5745,19 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
}
-static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
{
str[0] = '\0';
(*len)--;
return 0;
}
-u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
- u8 *version, u16 len)
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
+ u8 *version, u16 len)
{
struct bnx2x *bp;
u32 spirom_ver = 0;
- u8 status = 0;
+ int status = 0;
u8 *ver_p = version;
u16 remain_len = len;
if (version == NULL || params == NULL)
@@ -3065,15 +5799,18 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
if (phy->req_line_speed != SPEED_1000) {
- u32 md_devad;
+ u32 md_devad = 0;
DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
- /* change the uni_phy_addr in the nig */
- md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
- port*0x18));
+ if (!CHIP_IS_E3(bp)) {
+ /* change the uni_phy_addr in the nig */
+ md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
+ port*0x18));
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+ 0x5);
+ }
bnx2x_cl45_write(bp, phy,
5,
@@ -3088,10 +5825,13 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
0x6041);
msleep(200);
/* set aer mmd back */
- bnx2x_set_aer_mmd_xgxs(params, phy);
+ bnx2x_set_aer_mmd(params, phy);
- /* and md_devad */
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, md_devad);
+ if (!CHIP_IS_E3(bp)) {
+ /* and md_devad */
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+ md_devad);
+ }
} else {
u16 mii_ctrl;
DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
@@ -3107,12 +5847,13 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
}
}
-u8 bnx2x_set_led(struct link_params *params,
- struct link_vars *vars, u8 mode, u32 speed)
+int bnx2x_set_led(struct link_params *params,
+ struct link_vars *vars, u8 mode, u32 speed)
{
u8 port = params->port;
u16 hw_led_mode = params->hw_led_mode;
- u8 rc = 0, phy_idx;
+ int rc = 0;
+ u8 phy_idx;
u32 tmp;
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
struct bnx2x *bp = params->bp;
@@ -3146,8 +5887,10 @@ u8 bnx2x_set_led(struct link_params *params,
if (!vars->link_up)
break;
case LED_MODE_ON:
- if (params->phy[EXT_PHY1].type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 &&
+ if (((params->phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
+ (params->phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722)) &&
CHIP_IS_E2(bp) && params->num_phys == 2) {
/*
* This is a work-around for E2+8727 Configurations
@@ -3162,7 +5905,9 @@ u8 bnx2x_set_led(struct link_params *params,
(tmp | EMAC_LED_OVERRIDE));
return rc;
}
- } else if (SINGLE_MEDIA_DIRECT(params)) {
+ } else if (SINGLE_MEDIA_DIRECT(params) &&
+ (CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp))) {
/*
* This is a work-around for HW issue found when link
* is up in CL73
@@ -3214,21 +5959,49 @@ u8 bnx2x_set_led(struct link_params *params,
* This function comes to reflect the actual link state read DIRECTLY from the
* HW
*/
-u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
- u8 is_serdes)
+int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+ u8 is_serdes)
{
struct bnx2x *bp = params->bp;
u16 gp_status = 0, phy_index = 0;
u8 ext_phy_link_up = 0, serdes_phy_type;
struct link_vars temp_vars;
-
- CL22_RD_OVER_CL45(bp, &params->phy[INT_PHY],
+ struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
+
+ if (CHIP_IS_E3(bp)) {
+ u16 link_up;
+ if (params->req_line_speed[LINK_CONFIG_IDX(INT_PHY)]
+ > SPEED_10000) {
+ /* Check 20G link */
+ bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+ 1, &link_up);
+ bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+ 1, &link_up);
+ link_up &= (1<<2);
+ } else {
+ /* Check 10G link and below*/
+ u8 lane = bnx2x_get_warpcore_lane(int_phy, params);
+ bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_1,
+ &gp_status);
+ gp_status = ((gp_status >> 8) & 0xf) |
+ ((gp_status >> 12) & 0xf);
+ link_up = gp_status & (1 << lane);
+ }
+ if (!link_up)
+ return -ESRCH;
+ } else {
+ CL22_RD_OVER_CL45(bp, int_phy,
MDIO_REG_BANK_GP_STATUS,
MDIO_GP_STATUS_TOP_AN_STATUS1,
&gp_status);
/* link is up only if both local phy and external phy are up */
if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
return -ESRCH;
+ }
+ /* In XGXS loopback mode, do not check external PHY */
+ if (params->loopback_mode == LOOPBACK_XGXS)
+ return 0;
switch (params->num_phys) {
case 1:
@@ -3245,7 +6018,9 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
serdes_phy_type = ((params->phy[phy_index].media_type ==
ETH_PHY_SFP_FIBER) ||
(params->phy[phy_index].media_type ==
- ETH_PHY_XFP_FIBER));
+ ETH_PHY_XFP_FIBER) ||
+ (params->phy[phy_index].media_type ==
+ ETH_PHY_DA_TWINAX));
if (is_serdes != serdes_phy_type)
continue;
@@ -3263,10 +6038,10 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
return -ESRCH;
}
-static u8 bnx2x_link_initialize(struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_link_initialize(struct link_params *params,
+ struct link_vars *vars)
{
- u8 rc = 0;
+ int rc = 0;
u8 phy_index, non_ext_phy;
struct bnx2x *bp = params->bp;
/*
@@ -3282,12 +6057,8 @@ static u8 bnx2x_link_initialize(struct link_params *params,
* (no external phys), or this board has external phy which requires
* to first.
*/
-
- if (params->phy[INT_PHY].config_init)
- params->phy[INT_PHY].config_init(
- &params->phy[INT_PHY],
- params, vars);
-
+ if (!USES_WARPCORE(bp))
+ bnx2x_prepare_xgxs(&params->phy[INT_PHY], params, vars);
/* init ext phy and enable link state int */
non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
(params->loopback_mode == LOOPBACK_XGXS));
@@ -3296,13 +6067,22 @@ static u8 bnx2x_link_initialize(struct link_params *params,
(params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
(params->loopback_mode == LOOPBACK_EXT_PHY)) {
struct bnx2x_phy *phy = &params->phy[INT_PHY];
- if (vars->line_speed == SPEED_AUTO_NEG)
+ if (vars->line_speed == SPEED_AUTO_NEG &&
+ (CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp)))
bnx2x_set_parallel_detection(phy, params);
- bnx2x_init_internal_phy(phy, params, vars);
+ if (params->phy[INT_PHY].config_init)
+ params->phy[INT_PHY].config_init(phy,
+ params,
+ vars);
}
/* Init external phy*/
- if (!non_ext_phy)
+ if (non_ext_phy) {
+ if (params->phy[INT_PHY].supported &
+ SUPPORTED_FIBRE)
+ vars->link_status |= LINK_STATUS_SERDES_LINK;
+ } else {
for (phy_index = EXT_PHY1; phy_index < params->num_phys;
phy_index++) {
/*
@@ -3311,17 +6091,22 @@ static u8 bnx2x_link_initialize(struct link_params *params,
* need to initialize the first phy, since they are
* connected.
*/
+ if (params->phy[phy_index].supported &
+ SUPPORTED_FIBRE)
+ vars->link_status |= LINK_STATUS_SERDES_LINK;
+
if (phy_index == EXT_PHY2 &&
(bnx2x_phy_selection(params) ==
PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
- DP(NETIF_MSG_LINK, "Ignoring second phy\n");
+ DP(NETIF_MSG_LINK, "Not initializing"
+ " second phy\n");
continue;
}
params->phy[phy_index].config_init(
&params->phy[phy_index],
params, vars);
}
-
+ }
/* Reset the interrupt indication after phy was initialized */
bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
params->port*4,
@@ -3329,6 +6114,7 @@ static u8 bnx2x_link_initialize(struct link_params *params,
NIG_STATUS_XGXS0_LINK_STATUS |
NIG_STATUS_SERDES0_LINK_STATUS |
NIG_MASK_MI_INT));
+ bnx2x_update_mng(params, vars->link_status);
return rc;
}
@@ -3359,20 +6145,25 @@ static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "reset external PHY\n");
}
-static u8 bnx2x_update_link_down(struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_update_link_down(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
-
+ vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG;
/* indicate no mac active */
vars->mac_type = MAC_TYPE_NONE;
/* update shared memory */
- vars->link_status = 0;
+ vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
+ LINK_STATUS_LINK_UP |
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
+ LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
+ LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
+ LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK);
vars->line_speed = 0;
bnx2x_update_mng(params, vars->link_status);
@@ -3380,26 +6171,34 @@ static u8 bnx2x_update_link_down(struct link_params *params,
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
/* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
msleep(10);
-
- /* reset BigMac */
- bnx2x_bmac_rx_disable(bp, params->port);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ /* reset BigMac/Xmac */
+ if (CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp)) {
+ bnx2x_bmac_rx_disable(bp, params->port);
+ REG_WR(bp, GRCBASE_MISC +
+ MISC_REGISTERS_RESET_REG_2_CLEAR,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+ }
+ if (CHIP_IS_E3(bp))
+ bnx2x_xmac_disable(params);
+
return 0;
}
-static u8 bnx2x_update_link_up(struct link_params *params,
- struct link_vars *vars,
- u8 link_10g)
+static int bnx2x_update_link_up(struct link_params *params,
+ struct link_vars *vars,
+ u8 link_10g)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
- u8 rc = 0;
+ int rc = 0;
vars->link_status |= LINK_STATUS_LINK_UP;
+ vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
vars->link_status |=
@@ -3408,25 +6207,48 @@ static u8 bnx2x_update_link_up(struct link_params *params,
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
vars->link_status |=
LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
-
- if (link_10g) {
- bnx2x_bmac_enable(params, vars, 0);
+ if (USES_WARPCORE(bp)) {
+ if (link_10g) {
+ if (bnx2x_xmac_enable(params, vars, 0) ==
+ -ESRCH) {
+ DP(NETIF_MSG_LINK, "Found errors on XMAC\n");
+ vars->link_up = 0;
+ vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+ vars->link_status &= ~LINK_STATUS_LINK_UP;
+ }
+ } else
+ bnx2x_umac_enable(params, vars, 0);
bnx2x_set_led(params, vars,
- LED_MODE_OPER, SPEED_10000);
- } else {
- rc = bnx2x_emac_program(params, vars);
+ LED_MODE_OPER, vars->line_speed);
+ }
+ if ((CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp))) {
+ if (link_10g) {
+ if (bnx2x_bmac_enable(params, vars, 0) ==
+ -ESRCH) {
+ DP(NETIF_MSG_LINK, "Found errors on BMAC\n");
+ vars->link_up = 0;
+ vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+ vars->link_status &= ~LINK_STATUS_LINK_UP;
+ }
- bnx2x_emac_enable(params, vars, 0);
+ bnx2x_set_led(params, vars,
+ LED_MODE_OPER, SPEED_10000);
+ } else {
+ rc = bnx2x_emac_program(params, vars);
+ bnx2x_emac_enable(params, vars, 0);
- /* AN complete? */
- if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
- && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
- SINGLE_MEDIA_DIRECT(params))
- bnx2x_set_gmii_tx_driver(params);
+ /* AN complete? */
+ if ((vars->link_status &
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+ && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
+ SINGLE_MEDIA_DIRECT(params))
+ bnx2x_set_gmii_tx_driver(params);
+ }
}
/* PBF - link up */
- if (!(CHIP_IS_E2(bp)))
+ if (CHIP_IS_E1x(bp))
rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
vars->line_speed);
@@ -3451,17 +6273,18 @@ static u8 bnx2x_update_link_up(struct link_params *params,
* external phy needs to be up, and at least one of the 2
* external phy link must be up.
*/
-u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
+int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
struct link_vars phy_vars[MAX_PHYS];
u8 port = params->port;
- u8 link_10g, phy_index;
- u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
+ u8 link_10g_plus, phy_index;
+ u8 ext_phy_link_up = 0, cur_link_up;
+ int rc = 0;
u8 is_mi_int = 0;
u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
u8 active_external_phy = INT_PHY;
- vars->link_status = 0;
+ vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
for (phy_index = INT_PHY; phy_index < params->num_phys;
phy_index++) {
phy_vars[phy_index].flow_ctrl = 0;
@@ -3470,8 +6293,12 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
phy_vars[phy_index].duplex = DUPLEX_FULL;
phy_vars[phy_index].phy_link_up = 0;
phy_vars[phy_index].link_up = 0;
+ phy_vars[phy_index].fault_detected = 0;
}
+ if (USES_WARPCORE(bp))
+ bnx2x_set_aer_mmd(params, &params->phy[INT_PHY]);
+
DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
port, (vars->phy_flags & PHY_XGXS_FLAG),
REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
@@ -3488,13 +6315,14 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
/* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
/*
* Step 1:
* Check external link change only for external phys, and apply
* priority selection between them in case the link on both phys
- * is up. Note that the instead of the common vars, a temporary
+ * is up. Note that instead of the common vars, a temporary
* vars argument is used since each phy may have different link/
* speed/duplex result
*/
@@ -3601,6 +6429,8 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
if (params->phy[active_external_phy].supported &
SUPPORTED_FIBRE)
vars->link_status |= LINK_STATUS_SERDES_LINK;
+ else
+ vars->link_status &= ~LINK_STATUS_SERDES_LINK;
DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
active_external_phy);
}
@@ -3640,14 +6470,9 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
}
/* anything 10 and over uses the bmac */
- link_10g = ((vars->line_speed == SPEED_10000) ||
- (vars->line_speed == SPEED_12000) ||
- (vars->line_speed == SPEED_12500) ||
- (vars->line_speed == SPEED_13000) ||
- (vars->line_speed == SPEED_15000) ||
- (vars->line_speed == SPEED_16000));
+ link_10g_plus = (vars->line_speed >= SPEED_10000);
- bnx2x_link_int_ack(params, vars, link_10g);
+ bnx2x_link_int_ack(params, vars, link_10g_plus);
/*
* In case external phy link is up, and internal link is down
@@ -3671,21 +6496,24 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
vars->phy_flags |= PHY_SGMII_FLAG;
else
vars->phy_flags &= ~PHY_SGMII_FLAG;
- bnx2x_init_internal_phy(&params->phy[INT_PHY],
- params,
+
+ if (params->phy[INT_PHY].config_init)
+ params->phy[INT_PHY].config_init(
+ &params->phy[INT_PHY], params,
vars);
}
}
/*
* Link is up only if both local phy and external phy (in case of
- * non-direct board) are up
+ * non-direct board) are up and no fault detected on active PHY.
*/
vars->link_up = (vars->phy_link_up &&
(ext_phy_link_up ||
- SINGLE_MEDIA_DIRECT(params)));
+ SINGLE_MEDIA_DIRECT(params)) &&
+ (phy_vars[active_external_phy].fault_detected == 0));
if (vars->link_up)
- rc = bnx2x_update_link_up(params, vars, link_10g);
+ rc = bnx2x_update_link_up(params, vars, link_10g_plus);
else
rc = bnx2x_update_link_down(params, vars);
@@ -3729,69 +6557,6 @@ static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
phy->ver_addr);
}
-static void bnx2x_ext_phy_set_pause(struct link_params *params,
- struct bnx2x_phy *phy,
- struct link_vars *vars)
-{
- u16 val;
- struct bnx2x *bp = params->bp;
- /* read modify write pause advertizing */
- bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
-
- val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
-
- /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
- bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
- val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
- }
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
- val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
- }
- DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
- bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
-}
-
-static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
-{
- struct bnx2x *bp = params->bp;
- u16 ld_pause; /* local */
- u16 lp_pause; /* link partner */
- u16 pause_result;
- u8 ret = 0;
- /* read twice */
-
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
- if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
- vars->flow_ctrl = phy->req_flow_ctrl;
- else if (phy->req_line_speed != SPEED_AUTO_NEG)
- vars->flow_ctrl = params->req_fc_auto_adv;
- else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
- ret = 1;
- bnx2x_cl45_read(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV_PAUSE, &ld_pause);
- bnx2x_cl45_read(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
- pause_result = (ld_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
- pause_result |= (lp_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
- DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
- pause_result);
- bnx2x_pause_resolve(vars, pause_result);
- }
- return ret;
-}
-
static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
struct bnx2x_phy *phy,
struct link_vars *vars)
@@ -3845,13 +6610,13 @@ static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
pause_result);
}
}
-static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
- struct bnx2x_phy *phy,
- u8 port)
+static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 port)
{
u32 count = 0;
u16 fw_ver1, fw_msgout;
- u8 rc = 0;
+ int rc = 0;
/* Boot port from external ROM */
/* EDC grst */
@@ -3926,7 +6691,7 @@ static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
/******************************************************************/
/* BCM8073 PHY SECTION */
/******************************************************************/
-static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
+static int bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
{
/* This is only required for 8073A1, version 102 only */
u16 val;
@@ -3952,7 +6717,7 @@ static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
return 1;
}
-static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
+static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
{
u16 val, cnt, cnt1 ;
@@ -4059,9 +6824,9 @@ static void bnx2x_8073_set_pause_cl37(struct link_params *params,
msleep(500);
}
-static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8073_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u16 val = 0, tmp1;
@@ -4081,9 +6846,9 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
/* enable LASI */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2));
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1<<2));
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x0004);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x0004);
bnx2x_8073_set_pause_cl37(params, phy, vars);
@@ -4091,7 +6856,7 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
@@ -4225,7 +6990,7 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
u16 an1000_status = 0;
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
@@ -4241,7 +7006,7 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
/* Check the LASI */
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
@@ -4367,9 +7132,9 @@ static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
/******************************************************************/
/* BCM8705 PHY SECTION */
/******************************************************************/
-static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8705_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "init 8705\n");
@@ -4430,6 +7195,30 @@ static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
/******************************************************************/
/* SFP+ module Section */
/******************************************************************/
+static void bnx2x_set_disable_pmd_transmit(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 pmd_dis)
+{
+ struct bnx2x *bp = params->bp;
+ /*
+ * Disable transmitter only for bootcodes which can enable it afterwards
+ * (for D3 link)
+ */
+ if (pmd_dis) {
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED)
+ DP(NETIF_MSG_LINK, "Disabling PMD transmitter\n");
+ else {
+ DP(NETIF_MSG_LINK, "NOT disabling PMD transmitter\n");
+ return;
+ }
+ } else
+ DP(NETIF_MSG_LINK, "Enabling PMD transmitter\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_DISABLE, pmd_dis);
+}
+
static u8 bnx2x_get_gpio_port(struct link_params *params)
{
u8 gpio_port;
@@ -4443,9 +7232,10 @@ static u8 bnx2x_get_gpio_port(struct link_params *params)
swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
return gpio_port ^ (swap_val && swap_override);
}
-static void bnx2x_sfp_set_transmitter(struct link_params *params,
- struct bnx2x_phy *phy,
- u8 tx_en)
+
+static void bnx2x_sfp_e1e2_set_transmitter(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 tx_en)
{
u16 val;
u8 port = params->port;
@@ -4500,9 +7290,21 @@ static void bnx2x_sfp_set_transmitter(struct link_params *params,
}
}
-static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 addr, u8 byte_cnt, u8 *o_buf)
+static void bnx2x_sfp_set_transmitter(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 tx_en)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting SFP+ transmitter to %d\n", tx_en);
+ if (CHIP_IS_E3(bp))
+ bnx2x_sfp_e3_set_transmitter(params, phy, tx_en);
+ else
+ bnx2x_sfp_e1e2_set_transmitter(params, phy, tx_en);
+}
+
+static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 addr, u8 byte_cnt, u8 *o_buf)
{
struct bnx2x *bp = params->bp;
u16 val = 0;
@@ -4566,9 +7368,45 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
return -EINVAL;
}
-static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 addr, u8 byte_cnt, u8 *o_buf)
+static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 addr, u8 byte_cnt,
+ u8 *o_buf)
+{
+ int rc = 0;
+ u8 i, j = 0, cnt = 0;
+ u32 data_array[4];
+ u16 addr32;
+ struct bnx2x *bp = params->bp;
+ /*DP(NETIF_MSG_LINK, "bnx2x_direct_read_sfp_module_eeprom:"
+ " 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");
+ return -EINVAL;
+ }
+
+ /* 4 byte aligned address */
+ addr32 = addr & (~0x3);
+ do {
+ rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
+ data_array);
+ } while ((rc != 0) && (++cnt < I2C_WA_RETRY_CNT));
+
+ if (rc == 0) {
+ for (i = (addr - addr32); i < byte_cnt + (addr - addr32); i++) {
+ o_buf[j] = *((u8 *)data_array + i);
+ j++;
+ }
+ }
+
+ return rc;
+}
+
+static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 addr, u8 byte_cnt, u8 *o_buf)
{
struct bnx2x *bp = params->bp;
u16 val, i;
@@ -4653,27 +7491,39 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
return -EINVAL;
}
-u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params, u16 addr,
- u8 byte_cnt, u8 *o_buf)
+int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params, u16 addr,
+ u8 byte_cnt, u8 *o_buf)
{
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
- return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
- byte_cnt, o_buf);
- else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
- return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
- byte_cnt, o_buf);
- return -EINVAL;
+ int rc = -EINVAL;
+ switch (phy->type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ rc = bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
+ byte_cnt, o_buf);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+ rc = bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
+ byte_cnt, o_buf);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+ rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
+ byte_cnt, o_buf);
+ break;
+ }
+ return rc;
}
-static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 *edc_mode)
+static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 *edc_mode)
{
struct bnx2x *bp = params->bp;
+ u32 sync_offset = 0, phy_idx, media_types;
u8 val, check_limiting_mode = 0;
*edc_mode = EDC_MODE_LIMITING;
+ phy->media_type = ETH_PHY_UNSPECIFIED;
/* First check for copper cable */
if (bnx2x_read_sfp_module_eeprom(phy,
params,
@@ -4688,7 +7538,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
case SFP_EEPROM_CON_TYPE_VAL_COPPER:
{
u8 copper_module_type;
-
+ phy->media_type = ETH_PHY_DA_TWINAX;
/*
* Check if its active cable (includes SFP+ module)
* of passive cable
@@ -4697,8 +7547,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
params,
SFP_EEPROM_FC_TX_TECH_ADDR,
1,
- &copper_module_type) !=
- 0) {
+ &copper_module_type) != 0) {
DP(NETIF_MSG_LINK,
"Failed to read copper-cable-type"
" from SFP+ EEPROM\n");
@@ -4723,6 +7572,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
break;
}
case SFP_EEPROM_CON_TYPE_VAL_LC:
+ phy->media_type = ETH_PHY_SFP_FIBER;
DP(NETIF_MSG_LINK, "Optic module detected\n");
check_limiting_mode = 1;
break;
@@ -4731,7 +7581,22 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
val);
return -EINVAL;
}
-
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].media_type);
+ media_types = REG_RD(bp, sync_offset);
+ /* Update media type for non-PMF sync */
+ for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
+ if (&(params->phy[phy_idx]) == phy) {
+ media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+ media_types |= ((phy->media_type &
+ PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+ break;
+ }
+ }
+ REG_WR(bp, sync_offset, media_types);
if (check_limiting_mode) {
u8 options[SFP_EEPROM_OPTIONS_SIZE];
if (bnx2x_read_sfp_module_eeprom(phy,
@@ -4755,8 +7620,8 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
* This function read the relevant field from the module (SFP+), and verify it
* is compliant with this board
*/
-static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
- struct link_params *params)
+static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u32 val, cmd;
@@ -4825,8 +7690,8 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
return -EINVAL;
}
-static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
- struct link_params *params)
+static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
+ struct link_params *params)
{
u8 val;
@@ -4858,8 +7723,8 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
* In the GPIO register, bit 4 is use to determine if the GPIOs are
* operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
* output
- * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
- * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
+ * Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0
+ * Bits 8-9 determine the GPIOs value for INPUT in case bit 4 val is 1
* where the 1st bit is the over-current(only input), and 2nd bit is
* for power( only output )
*
@@ -4868,15 +7733,14 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
*/
if (phy->flags & FLAGS_NOC)
return;
- if (!(phy->flags &
- FLAGS_NOC) && is_power_up)
+ if (is_power_up)
val = (1<<4);
else
/*
* Set GPIO control to OUTPUT, and set the power bit
* to according to the is_power_up
*/
- val = ((!(is_power_up)) << 1);
+ val = (1<<1);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
@@ -4884,9 +7748,9 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
val);
}
-static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
- struct bnx2x_phy *phy,
- u16 edc_mode)
+static int bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
{
u16 cur_limiting_mode;
@@ -4934,9 +7798,9 @@ static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
return 0;
}
-static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
- struct bnx2x_phy *phy,
- u16 edc_mode)
+static int bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
{
u16 phy_identifier;
u16 rom_ver2_val;
@@ -4989,7 +7853,7 @@ static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
}
}
-static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+static void bnx2x_set_e1e2_module_fault_led(struct link_params *params,
u8 gpio_mode)
{
struct bnx2x *bp = params->bp;
@@ -5021,12 +7885,146 @@ static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
}
}
-static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
- struct link_params *params)
+static void bnx2x_set_e3_module_fault_led(struct link_params *params,
+ u8 gpio_mode)
+{
+ u32 pin_cfg;
+ u8 port = params->port;
+ struct bnx2x *bp = params->bp;
+ pin_cfg = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_E3_FAULT_MDL_LED_MASK) >>
+ PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT;
+ DP(NETIF_MSG_LINK, "Setting Fault LED to %d using pin cfg %d\n",
+ gpio_mode, pin_cfg);
+ bnx2x_set_cfg_pin(bp, pin_cfg, gpio_mode);
+}
+
+static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+ u8 gpio_mode)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting SFP+ module fault LED to %d\n", gpio_mode);
+ if (CHIP_IS_E3(bp)) {
+ /*
+ * Low ==> if SFP+ module is supported otherwise
+ * High ==> if SFP+ module is not on the approved vendor list
+ */
+ bnx2x_set_e3_module_fault_led(params, gpio_mode);
+ } else
+ bnx2x_set_e1e2_module_fault_led(params, gpio_mode);
+}
+
+static void bnx2x_warpcore_power_module(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 power)
+{
+ u32 pin_cfg;
+ struct bnx2x *bp = params->bp;
+
+ pin_cfg = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_E3_PWR_DIS_MASK) >>
+ PORT_HW_CFG_E3_PWR_DIS_SHIFT;
+
+ if (pin_cfg == PIN_CFG_NA)
+ return;
+ DP(NETIF_MSG_LINK, "Setting SFP+ module power to %d using pin cfg %d\n",
+ power, pin_cfg);
+ /*
+ * Low ==> corresponding SFP+ module is powered
+ * high ==> the SFP+ module is powered down
+ */
+ bnx2x_set_cfg_pin(bp, pin_cfg, power ^ 1);
+}
+
+static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ bnx2x_warpcore_power_module(params, phy, 0);
+}
+
+static void bnx2x_power_sfp_module(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 power)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting SFP+ power to %x\n", power);
+
+ switch (phy->type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+ bnx2x_8727_power_module(params->bp, phy, power);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+ bnx2x_warpcore_power_module(params, phy, power);
+ break;
+ default:
+ break;
+ }
+}
+static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
+{
+ u16 val = 0;
+ u16 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
+ struct bnx2x *bp = params->bp;
+
+ u8 lane = bnx2x_get_warpcore_lane(phy, params);
+ /* This is a global register which controls all lanes */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
+ val &= ~(0xf << (lane << 2));
+
+ switch (edc_mode) {
+ case EDC_MODE_LINEAR:
+ case EDC_MODE_LIMITING:
+ mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
+ break;
+ case EDC_MODE_PASSIVE_DAC:
+ mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
+ break;
+ default:
+ break;
+ }
+
+ val |= (mode << (lane << 2));
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, val);
+ /* A must read */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
+
+
+}
+
+static void bnx2x_set_limiting_mode(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
+{
+ switch (phy->type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ bnx2x_8726_set_limiting_mode(params->bp, phy, edc_mode);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+ bnx2x_8727_set_limiting_mode(params->bp, phy, edc_mode);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+ bnx2x_warpcore_set_limiting_mode(params, phy, edc_mode);
+ break;
+ }
+}
+
+int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 edc_mode;
- u8 rc = 0;
+ int rc = 0;
u32 val = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
@@ -5034,7 +8032,8 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
params->port);
-
+ /* Power up module */
+ bnx2x_power_sfp_module(params, phy, 1);
if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
return -EINVAL;
@@ -5046,12 +8045,11 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
bnx2x_set_sfp_module_fault_led(params,
MISC_REGISTERS_GPIO_HIGH);
- if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
- ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
- PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
- /* Shutdown SFP+ module */
+ /* Check if need to power down the SFP+ module */
+ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN) {
DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
- bnx2x_8727_power_module(bp, phy, 0);
+ bnx2x_power_sfp_module(params, phy, 0);
return rc;
}
} else {
@@ -5059,18 +8057,12 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
}
- /* power up the SFP module */
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
- bnx2x_8727_power_module(bp, phy, 1);
-
/*
* Check and set limiting mode / LRM mode on 8726. On 8727 it
* is done automatically
*/
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
- bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
- else
- bnx2x_8727_set_limiting_mode(bp, phy, edc_mode);
+ bnx2x_set_limiting_mode(params, phy, edc_mode);
+
/*
* Enable transmit for this module if the module is approved, or
* if unapproved modules should also enable the Tx laser
@@ -5088,23 +8080,33 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
void bnx2x_handle_module_detect_int(struct link_params *params)
{
struct bnx2x *bp = params->bp;
- struct bnx2x_phy *phy = &params->phy[EXT_PHY1];
+ struct bnx2x_phy *phy;
u32 gpio_val;
- u8 port = params->port;
+ u8 gpio_num, gpio_port;
+ if (CHIP_IS_E3(bp))
+ phy = &params->phy[INT_PHY];
+ else
+ phy = &params->phy[EXT_PHY1];
+
+ if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
+ params->port, &gpio_num, &gpio_port) ==
+ -EINVAL) {
+ DP(NETIF_MSG_LINK, "Failed to get MOD_ABS interrupt config\n");
+ return;
+ }
/* Set valid module led off */
bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
/* Get current gpio val reflecting module plugged in / out*/
- gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
+ gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
/* Call the handling function in case module is detected */
if (gpio_val == 0) {
-
- bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
+ bnx2x_power_sfp_module(params, phy, 1);
+ bnx2x_set_gpio_int(bp, gpio_num,
MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
- port);
-
+ gpio_port);
if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
bnx2x_sfp_module_detection(phy, params);
else
@@ -5115,13 +8117,14 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
port_feature_config[params->port].
config));
- bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
+ bnx2x_set_gpio_int(bp, gpio_num,
MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
- port);
+ gpio_port);
/*
* Module was plugged out.
* Disable transmit for this module
*/
+ phy->media_type = ETH_PHY_NOT_PRESENT;
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
bnx2x_sfp_set_transmitter(params, phy, 0);
@@ -5129,6 +8132,29 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
}
/******************************************************************/
+/* Used by 8706 and 8727 */
+/******************************************************************/
+static void bnx2x_sfp_mask_fault(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 alarm_status_offset,
+ u16 alarm_ctrl_offset)
+{
+ u16 alarm_status, val;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, alarm_status_offset,
+ &alarm_status);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, alarm_status_offset,
+ &alarm_status);
+ /* Mask or enable the fault event. */
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, &val);
+ if (alarm_status & (1<<0))
+ val &= ~(1<<0);
+ else
+ val |= (1<<0);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, val);
+}
+/******************************************************************/
/* common BCM8706/BCM8726 PHY SECTION */
/******************************************************************/
static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
@@ -5141,12 +8167,16 @@ static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
/* Clear RX Alarm*/
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
+
+ bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
+ MDIO_PMA_LASI_TXCTRL);
+
/* clear LASI indication*/
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
bnx2x_cl45_read(bp, phy,
@@ -5173,6 +8203,17 @@ static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
bnx2x_ext_phy_resolve_fc(phy, params, vars);
vars->duplex = DUPLEX_FULL;
}
+
+ /* Capture 10G link fault. Read twice to clear stale value. */
+ if (vars->line_speed == SPEED_10000) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+ if (val1 & (1<<0))
+ vars->fault_detected = 1;
+ }
+
return link_up;
}
@@ -5186,6 +8227,10 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
u32 tx_en_mode;
u16 cnt, val, tmp1;
struct bnx2x *bp = params->bp;
+
+ /* SPF+ PHY: Set flag to check for Tx error */
+ vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
/* HW reset */
@@ -5228,7 +8273,11 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
+ 0);
+ /* Arm LASI for link and Tx fault. */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 3);
} else {
/* Force 1Gbps using autoneg with 1G advertisement */
@@ -5251,10 +8300,10 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
0x0400);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
0x0004);
}
bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
@@ -5281,9 +8330,9 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
return 0;
}
-static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8706_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
return bnx2x_8706_8726_read_status(phy, params, vars);
}
@@ -5358,15 +8407,16 @@ static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
}
-static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u32 val;
- u32 swap_val, swap_override, aeu_gpio_mask, offset;
DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
+ /* SPF+ PHY: Set flag to check for Tx error */
+ vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
bnx2x_wait_reset_complete(bp, phy, params);
@@ -5387,9 +8437,9 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x5);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x5);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
0x400);
} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask &
@@ -5415,14 +8465,14 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
* change
*/
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x4);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
0x400);
} else { /* Default 10G. Set only LASI control */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 1);
}
/* Set TX PreEmphasis if needed */
@@ -5443,30 +8493,6 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
phy->tx_preemphasis[1]);
}
- /* Set GPIO3 to trigger SFP+ module insertion/removal */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
-
- /* The GPIO should be swapped if the swap register is set and active */
- swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
- swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-
- /* Select function upon port-swap configuration */
- if (params->port == 0) {
- offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
- aeu_gpio_mask = (swap_val && swap_override) ?
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
- } else {
- offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
- aeu_gpio_mask = (swap_val && swap_override) ?
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
- }
- val = REG_RD(bp, offset);
- /* add GPIO3 to group */
- val |= aeu_gpio_mask;
- REG_WR(bp, offset, val);
return 0;
}
@@ -5548,9 +8574,9 @@ static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
}
-static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
u32 tx_en_mode;
u16 tmp1, val, mod_abs, tmp2;
@@ -5559,18 +8585,24 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
+ /* SPF+ PHY: Set flag to check for Tx error */
+ vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
bnx2x_wait_reset_complete(bp, phy, params);
rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
- lasi_ctrl_val = 0x0004;
+ /* Should be 0x6 to enable XS on Tx side. */
+ lasi_ctrl_val = 0x0006;
DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
/* enable LASI */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
rx_alarm_ctrl_val);
-
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
+ 0);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, lasi_ctrl_val);
/*
* Initially configure MOD_ABS to interrupt when module is
@@ -5590,6 +8622,9 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+ /* Enable/Disable PHY transmitter output */
+ bnx2x_set_disable_pmd_transmit(params, phy, 0);
+
/* Make MOD_ABS give interrupt on change */
bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
&val);
@@ -5612,7 +8647,7 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
/* Set option 1G speed */
if (phy->req_line_speed == SPEED_1000) {
@@ -5730,7 +8765,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
/* Module is absent */
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
* presence event
@@ -5752,7 +8787,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
*/
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
} else {
/* Module is present */
@@ -5781,7 +8816,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
*/
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
@@ -5805,26 +8840,29 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
- u8 link_up = 0;
+ u8 link_up = 0, oc_port = params->port;
u16 link_status = 0;
u16 rx_alarm_status, lasi_ctrl, val1;
/* If PHY is not initialized, do not check link status */
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
&lasi_ctrl);
if (!lasi_ctrl)
return 0;
- /* Check the LASI */
+ /* Check the LASI on Rx */
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT,
&rx_alarm_status);
vars->line_speed = 0;
DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n", rx_alarm_status);
+ bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
+ MDIO_PMA_LASI_TXCTRL);
+
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
@@ -5843,8 +8881,10 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
&val1);
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", params->port);
+ " 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"
@@ -5852,11 +8892,11 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
" Please remove the SFP+ module and"
" restart the system to clear this"
" error.\n",
- params->port);
+ oc_port);
/* Disable all RX_ALARMs except for mod_abs */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
+ MDIO_PMA_LASI_RXCTRL, (1<<5));
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
@@ -5869,7 +8909,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
/* Clear RX alarm */
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
return 0;
}
} /* Over current check */
@@ -5879,7 +8919,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
bnx2x_8727_handle_mod_abs(phy, params);
/* Enable all mod_abs and link detection bits */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
((1<<5) | (1<<2)));
}
DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
@@ -5915,6 +8955,20 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "port %x: External link is down\n",
params->port);
}
+
+ /* Capture 10G link fault. */
+ if (vars->line_speed == SPEED_10000) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+
+ if (val1 & (1<<0)) {
+ vars->fault_detected = 1;
+ }
+ }
+
if (link_up) {
bnx2x_ext_phy_resolve_fc(phy, params, vars);
vars->duplex = DUPLEX_FULL;
@@ -5945,10 +8999,14 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
struct link_params *params)
{
struct bnx2x *bp = params->bp;
+
+ /* Enable/Disable PHY transmitter output */
+ bnx2x_set_disable_pmd_transmit(params, phy, 1);
+
/* Disable Transmitter */
bnx2x_sfp_set_transmitter(params, phy, 0);
/* Clear LASI */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0);
}
@@ -5958,111 +9016,106 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
struct link_params *params)
{
- u16 val, fw_ver1, fw_ver2, cnt, adj;
+ u16 val, fw_ver1, fw_ver2, cnt;
+ u8 port;
struct bnx2x *bp = params->bp;
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = -1;
+ port = params->port;
/* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0014);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, 0x0000);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, 0x0300);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x0009);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
if (val & 1)
break;
udelay(5);
}
if (cnt == 100) {
DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
- bnx2x_save_spirom_version(bp, params->port, 0,
+ bnx2x_save_spirom_version(bp, port, 0,
phy->ver_addr);
return;
}
/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0000);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x000A);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
if (val & 1)
break;
udelay(5);
}
if (cnt == 100) {
DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
- bnx2x_save_spirom_version(bp, params->port, 0,
+ bnx2x_save_spirom_version(bp, port, 0,
phy->ver_addr);
return;
}
/* lower 16 bits of the register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, &fw_ver1);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
/* upper 16 bits of register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, &fw_ver2);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
- bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
+ bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
phy->ver_addr);
}
static void bnx2x_848xx_set_led(struct bnx2x *bp,
struct bnx2x_phy *phy)
{
- u16 val, adj;
-
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = -1;
+ u16 val;
/* PHYC_CTL_LED_CTL */
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LINK_SIGNAL + adj, &val);
+ MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
val &= 0xFE00;
val |= 0x0092;
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LINK_SIGNAL + adj, val);
+ MDIO_PMA_REG_8481_LINK_SIGNAL, val);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED1_MASK + adj,
+ MDIO_PMA_REG_8481_LED1_MASK,
0x80);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED2_MASK + adj,
+ MDIO_PMA_REG_8481_LED2_MASK,
0x18);
/* Select activity source by Tx and Rx, as suggested by PHY AE */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_MASK + adj,
+ MDIO_PMA_REG_8481_LED3_MASK,
0x0006);
/* Select the closest activity blink rate to that in 10/100/1000 */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_BLINK + adj,
+ MDIO_PMA_REG_8481_LED3_BLINK,
0);
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, &val);
+ MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, val);
+ MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
/* 'Interrupt Mask' */
bnx2x_cl45_write(bp, phy,
@@ -6070,12 +9123,19 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
0xFFFB, 0xFFFD);
}
-static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u16 autoneg_val, an_1000_val, an_10_100_val;
+ u16 tmp_req_line_speed;
+
+ tmp_req_line_speed = phy->req_line_speed;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ if (phy->req_line_speed == SPEED_10000)
+ phy->req_line_speed = SPEED_AUTO_NEG;
+
/*
* This phy uses the NIG latch mechanism since link indication
* arrives through its LED4 and not via its LASI signal, so we
@@ -6122,11 +9182,14 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
an_1000_val);
- /* set 10 speed advertisement */
+ /* set 100 speed advertisement */
if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) &&
+ (phy->supported &
+ (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full)))) {
an_10_100_val |= (1<<7);
/* Enable autoneg and restart autoneg for legacy speeds */
autoneg_val |= (1<<9 | 1<<12);
@@ -6137,9 +9200,12 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
}
/* set 10 speed advertisement */
if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
- (phy->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) &&
+ (phy->supported &
+ (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full)))) {
an_10_100_val |= (1<<5);
autoneg_val |= (1<<9 | 1<<12);
if (phy->req_duplex == DUPLEX_FULL)
@@ -6148,7 +9214,10 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
}
/* Only 10/100 are allowed to work in FORCE mode */
- if (phy->req_line_speed == SPEED_100) {
+ if ((phy->req_line_speed == SPEED_100) &&
+ (phy->supported &
+ (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full))) {
autoneg_val |= (1<<13);
/* Enabled AUTO-MDIX when autoneg is disabled */
bnx2x_cl45_write(bp, phy,
@@ -6156,7 +9225,10 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
(1<<15 | 1<<9 | 7<<0));
DP(NETIF_MSG_LINK, "Setting 100M force\n");
}
- if (phy->req_line_speed == SPEED_10) {
+ if ((phy->req_line_speed == SPEED_10) &&
+ (phy->supported &
+ (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full))) {
/* Enabled AUTO-MDIX when autoneg is disabled */
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
@@ -6179,10 +9251,10 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
(phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
(phy->req_line_speed == SPEED_10000)) {
- DP(NETIF_MSG_LINK, "Advertising 10G\n");
- /* Restart autoneg for 10G*/
+ DP(NETIF_MSG_LINK, "Advertising 10G\n");
+ /* Restart autoneg for 10G*/
- bnx2x_cl45_write(bp, phy,
+ bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
0x3200);
} else if (phy->req_line_speed != SPEED_10 &&
@@ -6195,12 +9267,14 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
/* Save spirom version */
bnx2x_save_848xx_spirom_version(phy, params);
+ phy->req_line_speed = tmp_req_line_speed;
+
return 0;
}
-static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
/* Restore normal power mode*/
@@ -6215,33 +9289,200 @@ static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
return bnx2x_848xx_cmn_config_init(phy, params, vars);
}
-static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+
+#define PHY84833_HDSHK_WAIT 300
+static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ u32 idx;
+ u32 pair_swap;
+ u16 val;
+ u16 data;
+ struct bnx2x *bp = params->bp;
+ /* Do pair swap */
+
+ /* Check for configuration. */
+ pair_swap = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
+ PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
+
+ if (pair_swap == 0)
+ return 0;
+
+ data = (u16)pair_swap;
+
+ /* Write CMD_OPEN_OVERRIDE to STATUS reg */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2,
+ PHY84833_CMD_OPEN_OVERRIDE);
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+ break;
+ msleep(1);
+ }
+ if (idx >= PHY84833_HDSHK_WAIT) {
+ DP(NETIF_MSG_LINK, "Pairswap: FW not ready.\n");
+ return -EINVAL;
+ }
+
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG4,
+ data);
+ /* Issue pair swap command */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG0,
+ PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE);
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if ((val == PHY84833_CMD_COMPLETE_PASS) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR))
+ break;
+ msleep(1);
+ }
+ if ((idx >= PHY84833_HDSHK_WAIT) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR)) {
+ DP(NETIF_MSG_LINK, "Pairswap: override failed.\n");
+ return -EINVAL;
+ }
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2,
+ PHY84833_CMD_CLEAR_COMPLETE);
+ DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data);
+ return 0;
+}
+
+
+static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 chip_id)
+{
+ u32 reset_pin[2];
+ u32 idx;
+ u8 reset_gpios;
+ if (CHIP_IS_E3(bp)) {
+ /* Assume that these will be GPIOs, not EPIOs. */
+ for (idx = 0; idx < 2; idx++) {
+ /* Map config param to register bit. */
+ reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[0].e3_cmn_pin_cfg));
+ reset_pin[idx] = (reset_pin[idx] &
+ PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+ PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+ reset_pin[idx] -= PIN_CFG_GPIO0_P0;
+ reset_pin[idx] = (1 << reset_pin[idx]);
+ }
+ reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
+ } else {
+ /* E2, look from diff place of shmem. */
+ for (idx = 0; idx < 2; idx++) {
+ reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[0].default_cfg));
+ reset_pin[idx] &= PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK;
+ reset_pin[idx] -= PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0;
+ reset_pin[idx] >>= PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT;
+ reset_pin[idx] = (1 << reset_pin[idx]);
+ }
+ reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
+ }
+
+ return reset_gpios;
+}
+
+static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 reset_gpios;
+ u32 other_shmem_base_addr = REG_RD(bp, params->shmem2_base +
+ offsetof(struct shmem2_region,
+ other_shmem_base_addr));
+
+ u32 shmem_base_path[2];
+ shmem_base_path[0] = params->shmem_base;
+ shmem_base_path[1] = other_shmem_base_addr;
+
+ reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path,
+ params->chip_id);
+
+ bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+ udelay(10);
+ DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n",
+ reset_gpios);
+
+ return 0;
+}
+
+static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 chip_id)
+{
+ u8 reset_gpios;
+
+ reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
+
+ bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+ udelay(10);
+ bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+ msleep(800);
+ DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
+ reset_gpios);
+
+ return 0;
+}
+
+#define PHY84833_CONSTANT_LATENCY 1193
+static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 port, initialize = 1;
- u16 val, adj;
+ u16 val;
u16 temp;
- u32 actual_phy_selection, cms_enable;
- u8 rc = 0;
-
- /* This is just for MDIO_CTL_REG_84823_MEDIA register. */
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = 3;
+ u32 actual_phy_selection, cms_enable, idx;
+ int rc = 0;
msleep(1);
- if (CHIP_IS_E2(bp))
+
+ if (!(CHIP_IS_E1(bp)))
port = BP_PATH(bp);
else
port = params->port;
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- port);
+
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+ port);
+ } else {
+ /* MDIO reset */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, 0x8000);
+ /* Bring PHY out of super isolate mode */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+ val &= ~MDIO_84833_SUPER_ISOLATE;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+ }
+
bnx2x_wait_reset_complete(bp, phy, params);
+
/* Wait for GPHY to come out of reset */
msleep(50);
+
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ bnx2x_84833_pair_swap_cfg(phy, params, vars);
+
/*
* BCM84823 requires that XGXS links up first @ 10G for normal behavior
*/
@@ -6254,14 +9495,20 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
/* Set dual-media configuration according to configuration */
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_MEDIA + adj, &val);
+ MDIO_CTL_REG_84823_MEDIA, &val);
val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
- val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI |
- MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L;
+
+ if (CHIP_IS_E3(bp)) {
+ val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
+ MDIO_CTL_REG_84823_MEDIA_LINE_MASK);
+ } else {
+ val |= (MDIO_CTL_REG_84823_CTRL_MAC_XFI |
+ MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L);
+ }
actual_phy_selection = bnx2x_phy_selection(params);
@@ -6287,28 +9534,90 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_MEDIA + adj, val);
+ MDIO_CTL_REG_84823_MEDIA, val);
DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
params->multi_phy_config, val);
+ /* AutogrEEEn */
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
+ /* Ensure that f/w is ready */
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+ break;
+ usleep_range(1000, 1000);
+ }
+ if (idx >= PHY84833_HDSHK_WAIT) {
+ DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n");
+ return -EINVAL;
+ }
+
+ /* Select EEE mode */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG3,
+ 0x2);
+
+ /* Set Idle and Latency */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG4,
+ PHY84833_CONSTANT_LATENCY + 1);
+
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_DATA3_REG,
+ PHY84833_CONSTANT_LATENCY + 1);
+
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_DATA4_REG,
+ PHY84833_CONSTANT_LATENCY);
+
+ /* Send EEE instruction to command register */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG0,
+ PHY84833_DIAG_CMD_SET_EEE_MODE);
+
+ /* Ensure that the command has completed */
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if ((val == PHY84833_CMD_COMPLETE_PASS) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR))
+ break;
+ usleep_range(1000, 1000);
+ }
+ if ((idx >= PHY84833_HDSHK_WAIT) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR)) {
+ DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n");
+ return -EINVAL;
+ }
+
+ /* Reset command handler */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2,
+ PHY84833_CMD_CLEAR_COMPLETE);
+ }
+
if (initialize)
rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
else
bnx2x_save_848xx_spirom_version(phy, params);
- cms_enable = REG_RD(bp, params->shmem_base +
+ /* 84833 PHY has a better feature and doesn't need to support this. */
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+ cms_enable = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region,
dev_info.port_hw_config[params->port].default_cfg)) &
PORT_HW_CFG_ENABLE_CMS_MASK;
- bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
- if (cms_enable)
- val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
- else
- val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
- bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_USER_CTRL_REG, val);
-
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
+ if (cms_enable)
+ val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
+ else
+ val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_CTL_REG_84823_USER_CTRL_REG, val);
+ }
return rc;
}
@@ -6318,20 +9627,16 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u16 val, val1, val2, adj;
+ u16 val, val1, val2;
u8 link_up = 0;
- /* Reg offset adjustment for 84833 */
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = -1;
/* Check 10G-BaseT link status */
/* Check PMD signal ok */
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD, 0xFFFA, &val1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL + adj,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
&val2);
DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
@@ -6403,9 +9708,10 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
return link_up;
}
-static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
+
+static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
{
- u8 status = 0;
+ int status = 0;
u32 spirom_ver;
spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
status = bnx2x_format_ver(spirom_ver, str, len);
@@ -6435,13 +9741,27 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
u8 port;
- if (CHIP_IS_E2(bp))
+ u16 val16;
+
+ if (!(CHIP_IS_E1(bp)))
port = BP_PATH(bp);
else
port = params->port;
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_OUTPUT_LOW,
- port);
+
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW,
+ port);
+ } else {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_CTL_DEVAD,
+ 0x400f, &val16);
+ /* Put to low power mode on newer FW */
+ if ((val16 & 0x303f) > 0x1009)
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, 0x800);
+ }
}
static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
@@ -6449,11 +9769,17 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
u16 val;
+ u8 port;
+
+ if (!(CHIP_IS_E1(bp)))
+ port = BP_PATH(bp);
+ else
+ port = params->port;
switch (mode) {
case LED_MODE_OFF:
- DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", params->port);
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6489,7 +9815,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
case LED_MODE_FRONT_PANEL_OFF:
DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
- params->port);
+ port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6524,7 +9850,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
break;
case LED_MODE_ON:
- DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", params->port);
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6571,7 +9897,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
case LED_MODE_OPER:
- DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", params->port);
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6633,7 +9959,388 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
}
break;
}
+
+ /*
+ * This is a workaround for E3+84833 until autoneg
+ * restart is fixed in f/w
+ */
+ if (CHIP_IS_E3(bp)) {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_1, &val);
+ }
+}
+
+/******************************************************************/
+/* 54618SE PHY SECTION */
+/******************************************************************/
+static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port;
+ u16 autoneg_val, an_1000_val, an_10_100_val, fc_val, temp;
+ u32 cfg_pin;
+
+ DP(NETIF_MSG_LINK, "54618SE cfg init\n");
+ usleep_range(1000, 1000);
+
+ /* This works with E3 only, no need to check the chip
+ before determining the port. */
+ port = params->port;
+
+ cfg_pin = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
+ PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+ PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+
+ /* Drive pin high to bring the GPHY out of reset. */
+ bnx2x_set_cfg_pin(bp, cfg_pin, 1);
+
+ /* wait for GPHY to reset */
+ msleep(50);
+
+ /* reset phy */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_PMA_REG_CTRL, 0x8000);
+ bnx2x_wait_reset_complete(bp, phy, params);
+
+ /*wait for GPHY to reset */
+ msleep(50);
+
+ /* Configure LED4: set to INTR (0x6). */
+ /* Accessing shadow register 0xe. */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_LED_SEL2);
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ &temp);
+ temp &= ~(0xf << 4);
+ temp |= (0x6 << 4);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
+ /* Configure INTR based on link status change. */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_INTR_MASK,
+ ~MDIO_REG_INTR_MASK_LINK_STATUS);
+
+ /* Flip the signal detect polarity (set 0x1c.0x1e[8]). */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_AUTO_DET_MED);
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ &temp);
+ temp |= MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD;
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
+
+ /* Set up fc */
+ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ fc_val = 0;
+ if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
+ fc_val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+
+ if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
+ fc_val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
+
+ /* read all advertisement */
+ bnx2x_cl22_read(bp, phy,
+ 0x09,
+ &an_1000_val);
+
+ bnx2x_cl22_read(bp, phy,
+ 0x04,
+ &an_10_100_val);
+
+ bnx2x_cl22_read(bp, phy,
+ MDIO_PMA_REG_CTRL,
+ &autoneg_val);
+
+ /* Disable forced speed */
+ autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
+ an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<10) |
+ (1<<11));
+
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+ (phy->req_line_speed == SPEED_1000)) {
+ an_1000_val |= (1<<8);
+ autoneg_val |= (1<<9 | 1<<12);
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_1000_val |= (1<<9);
+ DP(NETIF_MSG_LINK, "Advertising 1G\n");
+ } else
+ an_1000_val &= ~((1<<8) | (1<<9));
+
+ bnx2x_cl22_write(bp, phy,
+ 0x09,
+ an_1000_val);
+ bnx2x_cl22_read(bp, phy,
+ 0x09,
+ &an_1000_val);
+
+ /* set 100 speed advertisement */
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+ an_10_100_val |= (1<<7);
+ /* Enable autoneg and restart autoneg for legacy speeds */
+ autoneg_val |= (1<<9 | 1<<12);
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<8);
+ DP(NETIF_MSG_LINK, "Advertising 100M\n");
+ }
+
+ /* set 10 speed advertisement */
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+ an_10_100_val |= (1<<5);
+ autoneg_val |= (1<<9 | 1<<12);
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<6);
+ DP(NETIF_MSG_LINK, "Advertising 10M\n");
+ }
+
+ /* Only 10/100 are allowed to work in FORCE mode */
+ if (phy->req_line_speed == SPEED_100) {
+ autoneg_val |= (1<<13);
+ /* Enabled AUTO-MDIX when autoneg is disabled */
+ bnx2x_cl22_write(bp, phy,
+ 0x18,
+ (1<<15 | 1<<9 | 7<<0));
+ DP(NETIF_MSG_LINK, "Setting 100M force\n");
+ }
+ if (phy->req_line_speed == SPEED_10) {
+ /* Enabled AUTO-MDIX when autoneg is disabled */
+ bnx2x_cl22_write(bp, phy,
+ 0x18,
+ (1<<15 | 1<<9 | 7<<0));
+ DP(NETIF_MSG_LINK, "Setting 10M force\n");
+ }
+
+ /* Check if we should turn on Auto-GrEEEn */
+ bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &temp);
+ if (temp == MDIO_REG_GPHY_ID_54618SE) {
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
+ temp = 6;
+ DP(NETIF_MSG_LINK, "Enabling Auto-GrEEEn\n");
+ } else {
+ temp = 0;
+ DP(NETIF_MSG_LINK, "Disabling Auto-GrEEEn\n");
+ }
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG, MDIO_AN_DEVAD);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ MDIO_REG_GPHY_EEE_ADV);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG,
+ (0x1 << 14) | MDIO_AN_DEVAD);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ temp);
+ }
+
+ bnx2x_cl22_write(bp, phy,
+ 0x04,
+ an_10_100_val | fc_val);
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ autoneg_val |= (1<<8);
+
+ bnx2x_cl22_write(bp, phy,
+ MDIO_PMA_REG_CTRL, autoneg_val);
+
+ 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)
+{
+ struct bnx2x *bp = params->bp;
+ u32 cfg_pin;
+ u8 port;
+
+ /* This works with E3 only, no need to check the chip
+ before determining the port. */
+ port = params->port;
+ cfg_pin = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
+ PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+ PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+
+ /* Drive pin low to put GPHY in reset. */
+ bnx2x_set_cfg_pin(bp, cfg_pin, 0);
+}
+
+static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val;
+ u8 link_up = 0;
+ u16 legacy_status, legacy_speed;
+
+ /* Get speed operation status */
+ bnx2x_cl22_read(bp, phy,
+ 0x19,
+ &legacy_status);
+ DP(NETIF_MSG_LINK, "54618SE read_status: 0x%x\n", legacy_status);
+
+ /* Read status to clear the PHY interrupt. */
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_INTR_STATUS,
+ &val);
+
+ link_up = ((legacy_status & (1<<2)) == (1<<2));
+
+ if (link_up) {
+ legacy_speed = (legacy_status & (7<<8));
+ if (legacy_speed == (7<<8)) {
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_FULL;
+ } else if (legacy_speed == (6<<8)) {
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_HALF;
+ } else if (legacy_speed == (5<<8)) {
+ vars->line_speed = SPEED_100;
+ vars->duplex = DUPLEX_FULL;
+ }
+ /* Omitting 100Base-T4 for now */
+ else if (legacy_speed == (3<<8)) {
+ vars->line_speed = SPEED_100;
+ vars->duplex = DUPLEX_HALF;
+ } else if (legacy_speed == (2<<8)) {
+ vars->line_speed = SPEED_10;
+ vars->duplex = DUPLEX_FULL;
+ } else if (legacy_speed == (1<<8)) {
+ vars->line_speed = SPEED_10;
+ vars->duplex = DUPLEX_HALF;
+ } 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));
+
+ /* Check legacy speed AN resolution */
+ bnx2x_cl22_read(bp, phy,
+ 0x01,
+ &val);
+ if (val & (1<<5))
+ vars->link_status |=
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+ bnx2x_cl22_read(bp, phy,
+ 0x06,
+ &val);
+ if ((val & (1<<0)) == 0)
+ vars->link_status |=
+ LINK_STATUS_PARALLEL_DETECTION_USED;
+
+ DP(NETIF_MSG_LINK, "BCM54618SE: link speed is %d\n",
+ vars->line_speed);
+
+ /* Report whether EEE is resolved. */
+ bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &val);
+ if (val == MDIO_REG_GPHY_ID_54618SE) {
+ if (vars->link_status &
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+ val = 0;
+ else {
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG,
+ MDIO_AN_DEVAD);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ MDIO_REG_GPHY_EEE_RESOLVED);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG,
+ (0x1 << 14) | MDIO_AN_DEVAD);
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ &val);
+ }
+ DP(NETIF_MSG_LINK, "EEE resolution: 0x%x\n", val);
+ }
+
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ }
+ return link_up;
}
+
+static void bnx2x_54618se_config_loopback(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val;
+ u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+
+ DP(NETIF_MSG_LINK, "2PMA/PMD ext_phy_loopback: 54618se\n");
+
+ /* Enable master/slave manual mmode and set to master */
+ /* mii write 9 [bits set 11 12] */
+ bnx2x_cl22_write(bp, phy, 0x09, 3<<11);
+
+ /* forced 1G and disable autoneg */
+ /* set val [mii read 0] */
+ /* set val [expr $val & [bits clear 6 12 13]] */
+ /* set val [expr $val | [bits set 6 8]] */
+ /* mii write 0 $val */
+ bnx2x_cl22_read(bp, phy, 0x00, &val);
+ val &= ~((1<<6) | (1<<12) | (1<<13));
+ val |= (1<<6) | (1<<8);
+ bnx2x_cl22_write(bp, phy, 0x00, val);
+
+ /* Set external loopback and Tx using 6dB coding */
+ /* mii write 0x18 7 */
+ /* set val [mii read 0x18] */
+ /* mii write 0x18 [expr $val | [bits set 10 15]] */
+ bnx2x_cl22_write(bp, phy, 0x18, 7);
+ bnx2x_cl22_read(bp, phy, 0x18, &val);
+ bnx2x_cl22_write(bp, phy, 0x18, val | (1<<10) | (1<<15));
+
+ /* This register opens the gate for the UMAC despite its name */
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
+
+ /*
+ * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+ * length used by the MAC receive logic to check frames.
+ */
+ REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
+}
+
/******************************************************************/
/* SFX7101 PHY SECTION */
/******************************************************************/
@@ -6646,9 +10353,9 @@ static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
}
-static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_7101_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
u16 fw_ver1, fw_ver2, val;
struct bnx2x *bp = params->bp;
@@ -6662,7 +10369,7 @@ static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
bnx2x_wait_reset_complete(bp, phy, params);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x1);
DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
@@ -6694,9 +10401,9 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
u8 link_up;
u16 val1, val2;
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
val2, val1);
bnx2x_cl45_read(bp, phy,
@@ -6721,8 +10428,7 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
return link_up;
}
-
-static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+static int bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
{
if (*len < 5)
return -EINVAL;
@@ -6800,9 +10506,8 @@ static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
static struct bnx2x_phy phy_null = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
.addr = 0,
- .flags = FLAGS_INIT_XGXS_FIRST,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6827,9 +10532,8 @@ static struct bnx2x_phy phy_null = {
static struct bnx2x_phy phy_serdes = {
.type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
- .flags = 0,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6843,14 +10547,14 @@ static struct bnx2x_phy phy_serdes = {
SUPPORTED_Autoneg |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_UNSPECIFIED,
+ .media_type = ETH_PHY_BASE_T,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
.speed_cap_mask = 0,
.req_duplex = 0,
.rsrv = 0,
- .config_init = (config_init_t)bnx2x_init_serdes,
+ .config_init = (config_init_t)bnx2x_xgxs_config_init,
.read_status = (read_status_t)bnx2x_link_settings_status,
.link_reset = (link_reset_t)bnx2x_int_link_reset,
.config_loopback = (config_loopback_t)NULL,
@@ -6863,9 +10567,8 @@ static struct bnx2x_phy phy_serdes = {
static struct bnx2x_phy phy_xgxs = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
- .flags = 0,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6880,14 +10583,14 @@ static struct bnx2x_phy phy_xgxs = {
SUPPORTED_Autoneg |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_UNSPECIFIED,
+ .media_type = ETH_PHY_CX4,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
.speed_cap_mask = 0,
.req_duplex = 0,
.rsrv = 0,
- .config_init = (config_init_t)bnx2x_init_xgxs,
+ .config_init = (config_init_t)bnx2x_xgxs_config_init,
.read_status = (read_status_t)bnx2x_link_settings_status,
.link_reset = (link_reset_t)bnx2x_int_link_reset,
.config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
@@ -6896,13 +10599,49 @@ static struct bnx2x_phy phy_xgxs = {
.set_link_led = (set_link_led_t)NULL,
.phy_specific_func = (phy_specific_func_t)NULL
};
+static struct bnx2x_phy phy_warpcore = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
+ .addr = 0xff,
+ .def_md_devad = 0,
+ .flags = FLAGS_HW_LOCK_REQUIRED,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_20000baseKR2_Full |
+ SUPPORTED_20000baseMLD2_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_UNSPECIFIED,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ /* req_duplex = */0,
+ /* rsrv = */0,
+ .config_init = (config_init_t)bnx2x_warpcore_config_init,
+ .read_status = (read_status_t)bnx2x_warpcore_read_status,
+ .link_reset = (link_reset_t)bnx2x_warpcore_link_reset,
+ .config_loopback = (config_loopback_t)bnx2x_set_warpcore_loopback,
+ .format_fw_ver = (format_fw_ver_t)NULL,
+ .hw_reset = (hw_reset_t)bnx2x_warpcore_hw_reset,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
static struct bnx2x_phy phy_7101 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
.addr = 0xff,
- .flags = FLAGS_FAN_FAILURE_DET_REQ,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6930,9 +10669,8 @@ static struct bnx2x_phy phy_7101 = {
static struct bnx2x_phy phy_8073 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
.addr = 0xff,
- .flags = FLAGS_HW_LOCK_REQUIRED,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_HW_LOCK_REQUIRED,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6943,7 +10681,7 @@ static struct bnx2x_phy phy_8073 = {
SUPPORTED_Autoneg |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_UNSPECIFIED,
+ .media_type = ETH_PHY_KR,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
@@ -6962,9 +10700,8 @@ static struct bnx2x_phy phy_8073 = {
static struct bnx2x_phy phy_8705 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
.addr = 0xff,
- .flags = FLAGS_INIT_XGXS_FIRST,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6991,9 +10728,8 @@ static struct bnx2x_phy phy_8705 = {
static struct bnx2x_phy phy_8706 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
.addr = 0xff,
- .flags = FLAGS_INIT_XGXS_FIRST,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7022,10 +10758,9 @@ static struct bnx2x_phy phy_8706 = {
static struct bnx2x_phy phy_8726 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = (FLAGS_HW_LOCK_REQUIRED |
FLAGS_INIT_XGXS_FIRST),
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7035,7 +10770,7 @@ static struct bnx2x_phy phy_8726 = {
SUPPORTED_FIBRE |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_SFP_FIBER,
+ .media_type = ETH_PHY_NOT_PRESENT,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
@@ -7055,9 +10790,8 @@ static struct bnx2x_phy phy_8726 = {
static struct bnx2x_phy phy_8727 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
.addr = 0xff,
- .flags = FLAGS_FAN_FAILURE_DET_REQ,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7066,7 +10800,7 @@ static struct bnx2x_phy phy_8727 = {
SUPPORTED_FIBRE |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_SFP_FIBER,
+ .media_type = ETH_PHY_NOT_PRESENT,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
@@ -7085,10 +10819,9 @@ static struct bnx2x_phy phy_8727 = {
static struct bnx2x_phy phy_8481 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = FLAGS_FAN_FAILURE_DET_REQ |
FLAGS_REARM_LATCH_SIGNAL,
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7122,10 +10855,9 @@ static struct bnx2x_phy phy_8481 = {
static struct bnx2x_phy phy_84823 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = FLAGS_FAN_FAILURE_DET_REQ |
FLAGS_REARM_LATCH_SIGNAL,
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7159,16 +10891,13 @@ static struct bnx2x_phy phy_84823 = {
static struct bnx2x_phy phy_84833 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = FLAGS_FAN_FAILURE_DET_REQ |
FLAGS_REARM_LATCH_SIGNAL,
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
- .supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
+ .supported = (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_10000baseT_Full |
@@ -7188,11 +10917,44 @@ static struct bnx2x_phy phy_84833 = {
.link_reset = (link_reset_t)bnx2x_848x3_link_reset,
.config_loopback = (config_loopback_t)NULL,
.format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
- .hw_reset = (hw_reset_t)NULL,
+ .hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy,
.set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
.phy_specific_func = (phy_specific_func_t)NULL
};
+static struct bnx2x_phy phy_54618se = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
+ .addr = 0xff,
+ .def_md_devad = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_BASE_T,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ /* req_duplex = */0,
+ /* rsrv = */0,
+ .config_init = (config_init_t)bnx2x_54618se_config_init,
+ .read_status = (read_status_t)bnx2x_54618se_read_status,
+ .link_reset = (link_reset_t)bnx2x_54618se_link_reset,
+ .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,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
/*****************************************************************/
/* */
/* Populate the phy according. Main function: bnx2x_populate_phy */
@@ -7259,8 +11021,8 @@ static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
return ext_phy_config;
}
-static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
- struct bnx2x_phy *phy)
+static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
+ struct bnx2x_phy *phy)
{
u32 phy_addr;
u32 chip_id;
@@ -7269,22 +11031,105 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
dev_info.port_feature_config[port].link_config)) &
PORT_FEATURE_CONNECTED_SWITCH_MASK);
chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
- switch (switch_cfg) {
- case SWITCH_CFG_1G:
+ DP(NETIF_MSG_LINK, ":chip_id = 0x%x\n", chip_id);
+ if (USES_WARPCORE(bp)) {
+ u32 serdes_net_if;
phy_addr = REG_RD(bp,
- NIG_REG_SERDES0_CTRL_PHY_ADDR +
- port * 0x10);
- *phy = phy_serdes;
- break;
- case SWITCH_CFG_10G:
- phy_addr = REG_RD(bp,
- NIG_REG_XGXS0_CTRL_PHY_ADDR +
- port * 0x18);
- *phy = phy_xgxs;
- break;
- default:
- DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
- return -EINVAL;
+ MISC_REG_WC0_CTRL_PHY_ADDR);
+ *phy = phy_warpcore;
+ if (REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR) == 0x3)
+ phy->flags |= FLAGS_4_PORT_MODE;
+ else
+ phy->flags &= ~FLAGS_4_PORT_MODE;
+ /* Check Dual mode */
+ serdes_net_if = (REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[port].default_cfg)) &
+ PORT_HW_CFG_NET_SERDES_IF_MASK);
+ /*
+ * Set the appropriate supported and flags indications per
+ * interface type of the chip
+ */
+ switch (serdes_net_if) {
+ case PORT_HW_CFG_NET_SERDES_IF_SGMII:
+ phy->supported &= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ phy->media_type = ETH_PHY_BASE_T;
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_XFI:
+ phy->media_type = ETH_PHY_XFP_FIBER;
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_SFI:
+ phy->supported &= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ phy->media_type = ETH_PHY_SFP_FIBER;
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_KR:
+ phy->media_type = ETH_PHY_KR;
+ phy->supported &= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
+ phy->media_type = ETH_PHY_KR;
+ phy->flags |= FLAGS_WC_DUAL_MODE;
+ phy->supported &= (SUPPORTED_20000baseMLD2_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_KR2:
+ phy->media_type = ETH_PHY_KR;
+ phy->flags |= FLAGS_WC_DUAL_MODE;
+ phy->supported &= (SUPPORTED_20000baseKR2_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
+ serdes_net_if);
+ break;
+ }
+
+ /*
+ * Enable MDC/MDIO work-around for E3 A0 since free running MDC
+ * was not set as expected. For B0, ECO will be enabled so there
+ * won't be an issue there
+ */
+ if (CHIP_REV(bp) == CHIP_REV_Ax)
+ phy->flags |= FLAGS_MDC_MDIO_WA;
+ } else {
+ switch (switch_cfg) {
+ case SWITCH_CFG_1G:
+ phy_addr = REG_RD(bp,
+ NIG_REG_SERDES0_CTRL_PHY_ADDR +
+ port * 0x10);
+ *phy = phy_serdes;
+ break;
+ case SWITCH_CFG_10G:
+ phy_addr = REG_RD(bp,
+ NIG_REG_XGXS0_CTRL_PHY_ADDR +
+ port * 0x18);
+ *phy = phy_xgxs;
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
+ return -EINVAL;
+ }
}
phy->addr = (u8)phy_addr;
phy->mdio_ctrl = bnx2x_get_emac_base(bp,
@@ -7302,12 +11147,12 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
return 0;
}
-static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
- u8 phy_index,
- u32 shmem_base,
- u32 shmem2_base,
- u8 port,
- struct bnx2x_phy *phy)
+static int bnx2x_populate_ext_phy(struct bnx2x *bp,
+ u8 phy_index,
+ u32 shmem_base,
+ u32 shmem2_base,
+ u8 port,
+ struct bnx2x_phy *phy)
{
u32 ext_phy_config, phy_type, config2;
u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
@@ -7336,6 +11181,7 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
*phy = phy_8727;
phy->flags |= FLAGS_NOC;
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
*phy = phy_8727;
@@ -7349,6 +11195,9 @@ static u8 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_BCM54618SE:
+ *phy = phy_54618se;
+ break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
*phy = phy_7101;
break;
@@ -7410,10 +11259,10 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
return 0;
}
-static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
- u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
+static int bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
+ u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
{
- u8 status = 0;
+ int status = 0;
phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
if (phy_index == INT_PHY)
return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
@@ -7527,10 +11376,10 @@ u32 bnx2x_phy_selection(struct link_params *params)
}
-u8 bnx2x_phy_probe(struct link_params *params)
+int bnx2x_phy_probe(struct link_params *params)
{
u8 phy_index, actual_phy_idx, link_cfg_idx;
- u32 phy_config_swapped;
+ u32 phy_config_swapped, sync_offset, media_types;
struct bnx2x *bp = params->bp;
struct bnx2x_phy *phy;
params->num_phys = 0;
@@ -7567,6 +11416,26 @@ u8 bnx2x_phy_probe(struct link_params *params)
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
break;
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].media_type);
+ media_types = REG_RD(bp, sync_offset);
+
+ /*
+ * Update media type for non-PMF sync only for the first time
+ * In case the media type changes afterwards, it will be updated
+ * using the update_status function
+ */
+ if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+ actual_phy_idx))) == 0) {
+ media_types |= ((phy->media_type &
+ PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+ actual_phy_idx));
+ }
+ REG_WR(bp, sync_offset, media_types);
+
bnx2x_phy_def_cfg(params, phy, phy_index);
params->num_phys++;
}
@@ -7575,77 +11444,10 @@ u8 bnx2x_phy_probe(struct link_params *params)
return 0;
}
-static void set_phy_vars(struct link_params *params)
-{
- struct bnx2x *bp = params->bp;
- u8 actual_phy_idx, phy_index, link_cfg_idx;
- u8 phy_config_swapped = params->multi_phy_config &
- PORT_HW_CFG_PHY_SWAPPED_ENABLED;
- for (phy_index = INT_PHY; phy_index < params->num_phys;
- phy_index++) {
- link_cfg_idx = LINK_CONFIG_IDX(phy_index);
- actual_phy_idx = phy_index;
- if (phy_config_swapped) {
- if (phy_index == EXT_PHY1)
- actual_phy_idx = EXT_PHY2;
- else if (phy_index == EXT_PHY2)
- actual_phy_idx = EXT_PHY1;
- }
- params->phy[actual_phy_idx].req_flow_ctrl =
- params->req_flow_ctrl[link_cfg_idx];
-
- params->phy[actual_phy_idx].req_line_speed =
- params->req_line_speed[link_cfg_idx];
-
- params->phy[actual_phy_idx].speed_cap_mask =
- params->speed_cap_mask[link_cfg_idx];
-
- params->phy[actual_phy_idx].req_duplex =
- params->req_duplex[link_cfg_idx];
-
- DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
- " speed_cap_mask %x\n",
- params->phy[actual_phy_idx].req_flow_ctrl,
- params->phy[actual_phy_idx].req_line_speed,
- params->phy[actual_phy_idx].speed_cap_mask);
- }
-}
-
-u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
+void bnx2x_init_bmac_loopback(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- DP(NETIF_MSG_LINK, "Phy Initialization started\n");
- DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
- params->req_line_speed[0], params->req_flow_ctrl[0]);
- DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
- params->req_line_speed[1], params->req_flow_ctrl[1]);
- vars->link_status = 0;
- vars->phy_link_up = 0;
- vars->link_up = 0;
- vars->line_speed = 0;
- vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->mac_type = MAC_TYPE_NONE;
- vars->phy_flags = 0;
-
- /* disable attentions */
- bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
- (NIG_MASK_XGXS0_LINK_STATUS |
- NIG_MASK_XGXS0_LINK10G |
- NIG_MASK_SERDES0_LINK_STATUS |
- NIG_MASK_MI_INT));
-
- bnx2x_emac_init(params, vars);
-
- if (params->num_phys == 0) {
- DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
- return -EINVAL;
- }
- set_phy_vars(params);
-
- DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
- if (params->loopback_mode == LOOPBACK_BMAC) {
-
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
@@ -7660,9 +11462,12 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_bmac_enable(params, vars, 1);
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
- } else if (params->loopback_mode == LOOPBACK_EMAC) {
-
+void bnx2x_init_emac_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
vars->link_up = 1;
vars->line_speed = SPEED_1000;
vars->duplex = DUPLEX_FULL;
@@ -7676,29 +11481,81 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_emac_enable(params, vars, 1);
bnx2x_emac_program(params, vars);
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
- } else if ((params->loopback_mode == LOOPBACK_XGXS) ||
- (params->loopback_mode == LOOPBACK_EXT_PHY)) {
+void bnx2x_init_xmac_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ vars->link_up = 1;
+ if (!params->req_line_speed[0])
+ vars->line_speed = SPEED_10000;
+ else
+ vars->line_speed = params->req_line_speed[0];
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_XMAC;
+ vars->phy_flags = PHY_XGXS_FLAG;
+ /*
+ * Set WC to loopback mode since link is required to provide clock
+ * to the XMAC in 20G mode
+ */
+ if (vars->line_speed == SPEED_20000) {
+ bnx2x_set_aer_mmd(params, &params->phy[0]);
+ bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
+ params->phy[INT_PHY].config_loopback(
+ &params->phy[INT_PHY],
+ params);
+ }
+ bnx2x_xmac_enable(params, vars, 1);
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
+
+void bnx2x_init_umac_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ vars->link_up = 1;
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_UMAC;
+ vars->phy_flags = PHY_XGXS_FLAG;
+ bnx2x_umac_enable(params, vars, 1);
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
+
+void bnx2x_init_xgxs_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
vars->link_up = 1;
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->duplex = DUPLEX_FULL;
- if (params->req_line_speed[0] == SPEED_1000) {
+ if (params->req_line_speed[0] == SPEED_1000)
vars->line_speed = SPEED_1000;
- vars->mac_type = MAC_TYPE_EMAC;
- } else {
+ else
vars->line_speed = SPEED_10000;
- vars->mac_type = MAC_TYPE_BMAC;
- }
+ if (!USES_WARPCORE(bp))
bnx2x_xgxs_deassert(params);
- bnx2x_link_initialize(params, vars);
+ bnx2x_link_initialize(params, vars);
- if (params->req_line_speed[0] == SPEED_1000) {
+ if (params->req_line_speed[0] == SPEED_1000) {
+ if (USES_WARPCORE(bp))
+ bnx2x_umac_enable(params, vars, 0);
+ else {
bnx2x_emac_program(params, vars);
bnx2x_emac_enable(params, vars, 0);
- } else
+ }
+ } else {
+ if (USES_WARPCORE(bp))
+ bnx2x_xmac_enable(params, vars, 0);
+ else
bnx2x_bmac_enable(params, vars, 0);
+ }
+
if (params->loopback_mode == LOOPBACK_XGXS) {
/* set 10G XGXS loopback */
params->phy[INT_PHY].config_loopback(
@@ -7718,24 +11575,76 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
}
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
- bnx2x_set_led(params, vars,
- LED_MODE_OPER, vars->line_speed);
- } else
- /* No loopback */
- {
- if (params->switch_cfg == SWITCH_CFG_10G)
- bnx2x_xgxs_deassert(params);
- else
- bnx2x_serdes_deassert(bp, params->port);
+ bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
+}
+int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Phy Initialization started\n");
+ DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
+ params->req_line_speed[0], params->req_flow_ctrl[0]);
+ DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
+ params->req_line_speed[1], params->req_flow_ctrl[1]);
+ vars->link_status = 0;
+ vars->phy_link_up = 0;
+ vars->link_up = 0;
+ vars->line_speed = 0;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_NONE;
+ vars->phy_flags = 0;
+
+ /* disable attentions */
+ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
+ (NIG_MASK_XGXS0_LINK_STATUS |
+ NIG_MASK_XGXS0_LINK10G |
+ NIG_MASK_SERDES0_LINK_STATUS |
+ NIG_MASK_MI_INT));
+
+ bnx2x_emac_init(params, vars);
+
+ if (params->num_phys == 0) {
+ DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
+ return -EINVAL;
+ }
+ set_phy_vars(params, vars);
+
+ DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
+ switch (params->loopback_mode) {
+ case LOOPBACK_BMAC:
+ bnx2x_init_bmac_loopback(params, vars);
+ break;
+ case LOOPBACK_EMAC:
+ bnx2x_init_emac_loopback(params, vars);
+ break;
+ case LOOPBACK_XMAC:
+ bnx2x_init_xmac_loopback(params, vars);
+ break;
+ case LOOPBACK_UMAC:
+ bnx2x_init_umac_loopback(params, vars);
+ break;
+ case LOOPBACK_XGXS:
+ case LOOPBACK_EXT_PHY:
+ bnx2x_init_xgxs_loopback(params, vars);
+ break;
+ default:
+ if (!CHIP_IS_E3(bp)) {
+ if (params->switch_cfg == SWITCH_CFG_10G)
+ bnx2x_xgxs_deassert(params);
+ else
+ bnx2x_serdes_deassert(bp, params->port);
+ }
bnx2x_link_initialize(params, vars);
msleep(30);
bnx2x_link_int_enable(params);
+ break;
}
return 0;
}
-u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
- u8 reset_ext_phy)
+
+int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
+ u8 reset_ext_phy)
{
struct bnx2x *bp = params->bp;
u8 phy_index, port = params->port, clear_latch_ind = 0;
@@ -7753,14 +11662,19 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
/* disable nig egress interface */
- REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp)) {
+ REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+ }
/* Stop BigMac rx */
- bnx2x_bmac_rx_disable(bp, port);
-
+ if (!CHIP_IS_E3(bp))
+ bnx2x_bmac_rx_disable(bp, port);
+ else
+ bnx2x_xmac_disable(params);
/* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
msleep(10);
/* The PHY reset is controlled by GPIO 1
@@ -7796,21 +11710,22 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
/* disable nig ingress interface */
- REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
- REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
- REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp)) {
+ REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
+ REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
+ }
vars->link_up = 0;
+ vars->phy_flags = 0;
return 0;
}
/****************************************************************************/
/* Common function */
/****************************************************************************/
-static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
- u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 chip_id)
+static int bnx2x_8073_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
struct bnx2x_phy phy[PORT_MAX];
struct bnx2x_phy *phy_blk[PORT_MAX];
@@ -7826,14 +11741,14 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
- if (CHIP_IS_E2(bp)) {
- shmem_base = shmem_base_path[port];
- shmem2_base = shmem2_base_path[port];
- port_of_path = 0;
- } else {
+ if (CHIP_IS_E1x(bp)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
+ } else {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
+ port_of_path = 0;
}
/* Extract the ext phy address for the port */
@@ -7877,10 +11792,10 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
/* PART2 - Download firmware to both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
- if (CHIP_IS_E2(bp))
- port_of_path = 0;
- else
+ if (CHIP_IS_E1x(bp))
port_of_path = port;
+ else
+ port_of_path = 0;
DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
phy_blk[port]->addr);
@@ -7933,10 +11848,10 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
}
return 0;
}
-static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
- u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 chip_id)
+static int bnx2x_8726_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
u32 val;
s8 port;
@@ -7954,12 +11869,12 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
- if (CHIP_IS_E2(bp)) {
- shmem_base = shmem_base_path[port];
- shmem2_base = shmem2_base_path[port];
- } else {
+ if (CHIP_IS_E1x(bp)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
+ } else {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
}
/* Extract the ext phy address for the port */
if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
@@ -8027,10 +11942,11 @@ static void bnx2x_get_ext_phy_reset_gpio(struct bnx2x *bp, u32 shmem_base,
break;
}
}
-static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
- u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 chip_id)
+
+static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
s8 port, reset_gpio;
u32 swap_val, swap_override;
@@ -8067,14 +11983,14 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
- if (CHIP_IS_E2(bp)) {
- shmem_base = shmem_base_path[port];
- shmem2_base = shmem2_base_path[port];
- port_of_path = 0;
- } else {
+ if (CHIP_IS_E1x(bp)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
+ } else {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
+ port_of_path = 0;
}
/* Extract the ext phy address for the port */
@@ -8109,25 +12025,29 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
}
/* PART2 - Download firmware to both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
- if (CHIP_IS_E2(bp))
- port_of_path = 0;
- else
+ if (CHIP_IS_E1x(bp))
port_of_path = port;
+ else
+ port_of_path = 0;
DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
phy_blk[port]->addr);
if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
port_of_path))
return -EINVAL;
+ /* Disable PHY transmitter output */
+ bnx2x_cl45_write(bp, phy_blk[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_DISABLE, 1);
}
return 0;
}
-static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 ext_phy_type, u32 chip_id)
+static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 ext_phy_type, u32 chip_id)
{
- u8 rc = 0;
+ int rc = 0;
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
@@ -8135,7 +12055,7 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
shmem2_base_path,
phy_index, chip_id);
break;
-
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
@@ -8152,6 +12072,13 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
shmem2_base_path,
phy_index, chip_id);
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+ /*
+ * GPIO3's are linked, and so both need to be toggled
+ * to obtain required 2us pulse.
+ */
+ rc = bnx2x_84833_common_init_phy(bp, shmem_base_path, chip_id);
+ break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
rc = -EINVAL;
break;
@@ -8169,15 +12096,21 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
return rc;
}
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
- u32 shmem2_base_path[], u32 chip_id)
+int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u32 chip_id)
{
- u8 rc = 0;
- u32 phy_ver;
- u8 phy_index;
+ int rc = 0;
+ u32 phy_ver, val;
+ u8 phy_index = 0;
u32 ext_phy_type, ext_phy_config;
+ bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
+ bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
DP(NETIF_MSG_LINK, "Begin common phy init\n");
-
+ if (CHIP_IS_E3(bp)) {
+ /* Enable EPIO */
+ val = REG_RD(bp, MISC_REG_GEN_PURP_HWG);
+ REG_WR(bp, MISC_REG_GEN_PURP_HWG, val | 1);
+ }
/* Check if common init was already done */
phy_ver = REG_RD(bp, shmem_base_path[0] +
offsetof(struct shmem_region,
@@ -8203,6 +12136,135 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
return rc;
}
+static void bnx2x_check_over_curr(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u32 cfg_pin;
+ u8 port = params->port;
+ u32 pin_val;
+
+ cfg_pin = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg1)) &
+ PORT_HW_CFG_E3_OVER_CURRENT_MASK) >>
+ PORT_HW_CFG_E3_OVER_CURRENT_SHIFT;
+
+ /* Ignore check if no external input PIN available */
+ if (bnx2x_get_cfg_pin(bp, cfg_pin, &pin_val) != 0)
+ return;
+
+ if (!pin_val) {
+ if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) {
+ netdev_err(bp->dev, "Error: Power fault on Port %d has"
+ " been detected and the power to "
+ "that SFP+ module has been removed"
+ " to prevent failure of the card."
+ " Please remove the SFP+ module and"
+ " restart the system to clear this"
+ " error.\n",
+ params->port);
+ vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
+ }
+ } else
+ vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
+}
+
+static void bnx2x_analyze_link_error(struct link_params *params,
+ struct link_vars *vars, u32 lss_status)
+{
+ struct bnx2x *bp = params->bp;
+ /* Compare new value with previous value */
+ u8 led_mode;
+ u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
+
+ /*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n",
+ vars->link_up,
+ half_open_conn, lss_status);*/
+
+ if ((lss_status ^ half_open_conn) == 0)
+ return;
+
+ /* If values differ */
+ DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up,
+ half_open_conn, lss_status);
+
+ /*
+ * a. Update shmem->link_status accordingly
+ * b. Update link_vars->link_up
+ */
+ if (lss_status) {
+ vars->link_status &= ~LINK_STATUS_LINK_UP;
+ vars->link_up = 0;
+ vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+ /*
+ * Set LED mode to off since the PHY doesn't know about these
+ * errors
+ */
+ led_mode = LED_MODE_OFF;
+ } else {
+ vars->link_status |= LINK_STATUS_LINK_UP;
+ vars->link_up = 1;
+ vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+ led_mode = LED_MODE_OPER;
+ }
+ /* Update the LED according to the link state */
+ bnx2x_set_led(params, vars, led_mode, SPEED_10000);
+
+ /* Update link status in the shared memory */
+ bnx2x_update_mng(params, vars->link_status);
+
+ /* C. Trigger General Attention */
+ vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
+ bnx2x_notify_link_changed(bp);
+}
+
+static void bnx2x_check_half_open_conn(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u32 lss_status = 0;
+ u32 mac_base;
+ /* In case link status is physically up @ 10G do */
+ if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+ return;
+
+ if (!CHIP_IS_E3(bp) &&
+ (REG_RD(bp, MISC_REG_RESET_REG_2) &
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) {
+ /* Check E1X / E2 BMAC */
+ u32 lss_status_reg;
+ u32 wb_data[2];
+ mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
+ NIG_REG_INGRESS_BMAC0_MEM;
+ /* Read BIGMAC_REGISTER_RX_LSS_STATUS */
+ if (CHIP_IS_E2(bp))
+ lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT;
+ else
+ lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS;
+
+ REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
+ lss_status = (wb_data[0] > 0);
+
+ bnx2x_analyze_link_error(params, vars, lss_status);
+ }
+}
+
+void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ if (!params) {
+ DP(NETIF_MSG_LINK, "Ininitliazed params !\n");
+ return;
+ }
+ /* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x
+ RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed,
+ REG_RD(bp, MISC_REG_RESET_REG_2)); */
+ bnx2x_check_half_open_conn(params, vars);
+ if (CHIP_IS_E3(bp))
+ bnx2x_check_over_curr(params, vars);
+}
+
u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
{
u8 phy_index;
@@ -8245,7 +12307,15 @@ u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
void bnx2x_hw_reset_phy(struct link_params *params)
{
u8 phy_index;
- for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+ struct bnx2x *bp = params->bp;
+ bnx2x_update_mng(params, 0);
+ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
+ (NIG_MASK_XGXS0_LINK_STATUS |
+ NIG_MASK_XGXS0_LINK10G |
+ NIG_MASK_SERDES0_LINK_STATUS |
+ NIG_MASK_MI_INT));
+
+ for (phy_index = INT_PHY; phy_index < MAX_PHYS;
phy_index++) {
if (params->phy[phy_index].hw_reset) {
params->phy[phy_index].hw_reset(
@@ -8255,3 +12325,72 @@ void bnx2x_hw_reset_phy(struct link_params *params)
}
}
}
+
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+ u32 chip_id, u32 shmem_base, u32 shmem2_base,
+ u8 port)
+{
+ u8 gpio_num = 0xff, gpio_port = 0xff, phy_index;
+ u32 val;
+ u32 offset, aeu_mask, swap_val, swap_override, sync_offset;
+ if (CHIP_IS_E3(bp)) {
+ if (bnx2x_get_mod_abs_int_cfg(bp, chip_id,
+ shmem_base,
+ port,
+ &gpio_num,
+ &gpio_port) != 0)
+ return;
+ } else {
+ struct bnx2x_phy phy;
+ for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+ phy_index++) {
+ if (bnx2x_populate_phy(bp, phy_index, shmem_base,
+ shmem2_base, port, &phy)
+ != 0) {
+ DP(NETIF_MSG_LINK, "populate phy failed\n");
+ return;
+ }
+ if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
+ gpio_num = MISC_REGISTERS_GPIO_3;
+ gpio_port = port;
+ break;
+ }
+ }
+ }
+
+ if (gpio_num == 0xff)
+ return;
+
+ /* Set GPIO3 to trigger SFP+ module insertion/removal */
+ bnx2x_set_gpio(bp, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port);
+
+ swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+ swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+ gpio_port ^= (swap_val && swap_override);
+
+ vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 <<
+ (gpio_num + (gpio_port << 2));
+
+ sync_offset = shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].aeu_int_mask);
+ REG_WR(bp, sync_offset, vars->aeu_int_mask);
+
+ DP(NETIF_MSG_LINK, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x\n",
+ gpio_num, gpio_port, vars->aeu_int_mask);
+
+ if (port == 0)
+ offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
+ else
+ offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
+
+ /* Open appropriate AEU for interrupts */
+ aeu_mask = REG_RD(bp, offset);
+ aeu_mask |= vars->aeu_int_mask;
+ REG_WR(bp, offset, aeu_mask);
+
+ /* Enable the GPIO to trigger interrupt */
+ val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
+ val |= 1 << (gpio_num + (gpio_port << 2));
+ REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
+}
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h
index 92f36b6950dc..6a7708d5da37 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/bnx2x/bnx2x_link.h
@@ -33,12 +33,13 @@
#define BNX2X_FLOW_CTRL_BOTH PORT_FEATURE_FLOW_CONTROL_BOTH
#define BNX2X_FLOW_CTRL_NONE PORT_FEATURE_FLOW_CONTROL_NONE
+#define NET_SERDES_IF_XFI 1
+#define NET_SERDES_IF_SFI 2
+#define NET_SERDES_IF_KR 3
+#define NET_SERDES_IF_DXGXS 4
+
#define SPEED_AUTO_NEG 0
-#define SPEED_12000 12000
-#define SPEED_12500 12500
-#define SPEED_13000 13000
-#define SPEED_15000 15000
-#define SPEED_16000 16000
+#define SPEED_20000 20000
#define SFP_EEPROM_VENDOR_NAME_ADDR 0x14
#define SFP_EEPROM_VENDOR_NAME_SIZE 16
@@ -46,6 +47,12 @@
#define SFP_EEPROM_VENDOR_OUI_SIZE 3
#define SFP_EEPROM_PART_NO_ADDR 0x28
#define SFP_EEPROM_PART_NO_SIZE 16
+#define SFP_EEPROM_REVISION_ADDR 0x38
+#define SFP_EEPROM_REVISION_SIZE 4
+#define SFP_EEPROM_SERIAL_ADDR 0x44
+#define SFP_EEPROM_SERIAL_SIZE 16
+#define SFP_EEPROM_DATE_ADDR 0x54 /* ASCII YYMMDD */
+#define SFP_EEPROM_DATE_SIZE 6
#define PWR_FLT_ERR_MSG_LEN 250
#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
@@ -62,25 +69,26 @@
#define SINGLE_MEDIA(params) (params->num_phys == 2)
/* Dual Media board contains two external phy with different media */
#define DUAL_MEDIA(params) (params->num_phys == 3)
+
+#define FW_PARAM_PHY_ADDR_MASK 0x000000FF
+#define FW_PARAM_PHY_TYPE_MASK 0x0000FF00
+#define FW_PARAM_MDIO_CTRL_MASK 0xFFFF0000
#define FW_PARAM_MDIO_CTRL_OFFSET 16
+#define FW_PARAM_PHY_ADDR(fw_param) (fw_param & \
+ FW_PARAM_PHY_ADDR_MASK)
+#define FW_PARAM_PHY_TYPE(fw_param) (fw_param & \
+ FW_PARAM_PHY_TYPE_MASK)
+#define FW_PARAM_MDIO_CTRL(fw_param) ((fw_param & \
+ FW_PARAM_MDIO_CTRL_MASK) >> \
+ FW_PARAM_MDIO_CTRL_OFFSET)
#define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
-#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE 170
-#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE 0
-
-#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE 250
-#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE 0
-
-#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE 10
-#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE 90
-
-#define PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE 50
-#define PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE 250
#define PFC_BRB_FULL_LB_XOFF_THRESHOLD 170
#define PFC_BRB_FULL_LB_XON_THRESHOLD 250
+#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))
/***********************************************************/
/* Structs */
/***********************************************************/
@@ -121,8 +129,8 @@ struct bnx2x_phy {
/* Loaded during init */
u8 addr;
-
- u8 flags;
+ u8 def_md_devad;
+ u16 flags;
/* Require HW lock */
#define FLAGS_HW_LOCK_REQUIRED (1<<0)
/* No Over-Current detection */
@@ -131,11 +139,13 @@ struct bnx2x_phy {
#define FLAGS_FAN_FAILURE_DET_REQ (1<<2)
/* Initialize first the XGXS and only then the phy itself */
#define FLAGS_INIT_XGXS_FIRST (1<<3)
+#define FLAGS_WC_DUAL_MODE (1<<4)
+#define FLAGS_4_PORT_MODE (1<<5)
#define FLAGS_REARM_LATCH_SIGNAL (1<<6)
#define FLAGS_SFP_NOT_APPROVED (1<<7)
+#define FLAGS_MDC_MDIO_WA (1<<8)
+#define FLAGS_DUMMY_READ (1<<9)
- u8 def_md_devad;
- u8 reserved;
/* preemphasis values for the rx side */
u16 rx_preemphasis[4];
@@ -153,6 +163,8 @@ struct bnx2x_phy {
#define ETH_PHY_XFP_FIBER 0x2
#define ETH_PHY_DA_TWINAX 0x3
#define ETH_PHY_BASE_T 0x4
+#define ETH_PHY_KR 0xf0
+#define ETH_PHY_CX4 0xf1
#define ETH_PHY_NOT_PRESENT 0xff
/* The address in which version is located*/
@@ -238,6 +250,8 @@ struct link_params {
#define FEATURE_CONFIG_PFC_ENABLED (1<<1)
#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2)
#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
+#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9)
+#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10)
/* Will be populated during common init */
struct bnx2x_phy phy[MAX_PHYS];
@@ -257,11 +271,19 @@ struct link_params {
/* Output parameters */
struct link_vars {
u8 phy_flags;
+#define PHY_XGXS_FLAG (1<<0)
+#define PHY_SGMII_FLAG (1<<1)
+#define PHY_PHYSICAL_LINK_FLAG (1<<2)
+#define PHY_HALF_OPEN_CONN_FLAG (1<<3)
+#define PHY_OVER_CURRENT_FLAG (1<<4)
+#define PHY_TX_ERROR_CHECK_FLAG (1<<5)
u8 mac_type;
#define MAC_TYPE_NONE 0
#define MAC_TYPE_EMAC 1
#define MAC_TYPE_BMAC 2
+#define MAC_TYPE_UMAC 3
+#define MAC_TYPE_XMAC 4
u8 phy_link_up; /* internal phy link indication */
u8 link_up;
@@ -274,45 +296,52 @@ struct link_vars {
/* The same definitions as the shmem parameter */
u32 link_status;
+ u8 fault_detected;
+ u8 rsrv1;
+ u16 periodic_flags;
+#define PERIODIC_FLAGS_LINK_EVENT 0x0001
+
+ u32 aeu_int_mask;
};
/***********************************************************/
/* Functions */
/***********************************************************/
-u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output);
+int bnx2x_phy_init(struct link_params *params, struct link_vars *vars);
/* Reset the link. Should be called when driver or interface goes down
Before calling phy firmware upgrade, the reset_ext_phy should be set
to 0 */
-u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
- u8 reset_ext_phy);
+int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
+ u8 reset_ext_phy);
/* bnx2x_link_update should be called upon link interrupt */
-u8 bnx2x_link_update(struct link_params *input, struct link_vars *output);
+int bnx2x_link_update(struct link_params *params, struct link_vars *vars);
/* use the following phy functions to read/write from external_phy
In order to use it to read/write internal phy registers, use
DEFAULT_PHY_DEV_ADDR as devad, and (_bank + (_addr & 0xf)) as
the register */
-u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 *ret_val);
+int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 *ret_val);
+
+int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 val);
-u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 val);
/* Reads the link_status from the shmem,
and update the link vars accordingly */
void bnx2x_link_status_update(struct link_params *input,
struct link_vars *output);
/* returns string representing the fw_version of the external phy */
-u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
- u8 *version, u16 len);
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
+ u8 *version, u16 len);
/* Set/Unset the led
Basically, the CLC takes care of the led for the link, but in case one needs
to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
blink the led, and LED_MODE_OFF to set the led off.*/
-u8 bnx2x_set_led(struct link_params *params, struct link_vars *vars,
- u8 mode, u32 speed);
+int bnx2x_set_led(struct link_params *params,
+ struct link_vars *vars, u8 mode, u32 speed);
#define LED_MODE_OFF 0
#define LED_MODE_ON 1
#define LED_MODE_OPER 2
@@ -324,12 +353,12 @@ void bnx2x_handle_module_detect_int(struct link_params *params);
/* Get the actual link status. In case it returns 0, link is up,
otherwise link is down*/
-u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars,
- u8 is_serdes);
+int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+ u8 is_serdes);
/* One-time initialization for external phy after power up */
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
- u32 shmem2_base_path[], u32 chip_id);
+int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u32 chip_id);
/* Reset the external PHY using GPIO */
void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
@@ -338,9 +367,9 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
/* Read "byte_cnt" bytes from address "addr" from the SFP+ EEPROM */
-u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params, u16 addr,
- u8 byte_cnt, u8 *o_buf);
+int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params, u16 addr,
+ u8 byte_cnt, u8 *o_buf);
void bnx2x_hw_reset_phy(struct link_params *params);
@@ -352,11 +381,28 @@ u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
u32 bnx2x_phy_selection(struct link_params *params);
/* Probe the phys on board, and populate them in "params" */
-u8 bnx2x_phy_probe(struct link_params *params);
+int bnx2x_phy_probe(struct link_params *params);
+
/* Checks if fan failure detection is required on one of the phys on board */
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 port);
+
+
+/* DCBX structs */
+
+/* Number of maximum COS per chip */
+#define DCBX_E2E3_MAX_NUM_COS (2)
+#define DCBX_E3B0_MAX_NUM_COS_PORT0 (6)
+#define DCBX_E3B0_MAX_NUM_COS_PORT1 (3)
+#define DCBX_E3B0_MAX_NUM_COS ( \
+ MAXVAL(DCBX_E3B0_MAX_NUM_COS_PORT0, \
+ DCBX_E3B0_MAX_NUM_COS_PORT1))
+
+#define DCBX_MAX_NUM_COS ( \
+ MAXVAL(DCBX_E3B0_MAX_NUM_COS, \
+ DCBX_E2E3_MAX_NUM_COS))
+
/* PFC port configuration params */
struct bnx2x_nig_brb_pfc_port_params {
/* NIG */
@@ -364,8 +410,8 @@ struct bnx2x_nig_brb_pfc_port_params {
u32 llfc_out_en;
u32 llfc_enable;
u32 pkt_priority_to_cos;
- u32 rx_cos0_priority_mask;
- u32 rx_cos1_priority_mask;
+ u8 num_of_rx_cos_priority_mask;
+ u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
u32 llfc_high_priority_classes;
u32 llfc_low_priority_classes;
/* BRB */
@@ -373,27 +419,74 @@ struct bnx2x_nig_brb_pfc_port_params {
u32 cos1_pauseable;
};
+
+/* ETS port configuration params */
+struct bnx2x_ets_bw_params {
+ u8 bw;
+};
+
+struct bnx2x_ets_sp_params {
+ /**
+ * valid values are 0 - 5. 0 is highest strict priority.
+ * There can't be two COS's with the same pri.
+ */
+ u8 pri;
+};
+
+enum bnx2x_cos_state {
+ bnx2x_cos_state_strict = 0,
+ bnx2x_cos_state_bw = 1,
+};
+
+struct bnx2x_ets_cos_params {
+ enum bnx2x_cos_state state ;
+ union {
+ struct bnx2x_ets_bw_params bw_params;
+ struct bnx2x_ets_sp_params sp_params;
+ } params;
+};
+
+struct bnx2x_ets_params {
+ u8 num_of_cos; /* Number of valid COS entries*/
+ struct bnx2x_ets_cos_params cos[DCBX_MAX_NUM_COS];
+};
+
/**
* Used to update the PFC attributes in EMAC, BMAC, NIG and BRB
* when link is already up
*/
-void bnx2x_update_pfc(struct link_params *params,
+int bnx2x_update_pfc(struct link_params *params,
struct link_vars *vars,
struct bnx2x_nig_brb_pfc_port_params *pfc_params);
/* Used to configure the ETS to disable */
-void bnx2x_ets_disabled(struct link_params *params);
+int bnx2x_ets_disabled(struct link_params *params,
+ struct link_vars *vars);
/* Used to configure the ETS to BW limited */
void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
const u32 cos1_bw);
/* Used to configure the ETS to strict */
-u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
+int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
+
+/* Configure the COS to ETS according to BW and SP settings.*/
+int bnx2x_ets_e3b0_config(const struct link_params *params,
+ const struct link_vars *vars,
+ const struct bnx2x_ets_params *ets_params);
/* Read pfc statistic*/
void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
u32 pfc_frames_sent[2],
u32 pfc_frames_received[2]);
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+ u32 chip_id, u32 shmem_base, u32 shmem2_base,
+ u8 port);
+
+int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+ struct link_params *params);
+
+void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
+
#endif /* BNX2X_LINK_H */
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 74be989f51c5..150709111548 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -39,6 +39,7 @@
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
+#include <net/ipv6.h>
#include <net/tcp.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
@@ -51,12 +52,12 @@
#include <linux/stringify.h>
#include <linux/vmalloc.h>
-#define BNX2X_MAIN
#include "bnx2x.h"
#include "bnx2x_init.h"
#include "bnx2x_init_ops.h"
#include "bnx2x_cmn.h"
#include "bnx2x_dcb.h"
+#include "bnx2x_sp.h"
#include <linux/firmware.h>
#include "bnx2x_fw_file_hdr.h"
@@ -74,12 +75,14 @@
#define TX_TIMEOUT (5*HZ)
static char version[] __devinitdata =
- "Broadcom NetXtreme II 5771x 10Gigabit Ethernet Driver "
+ "Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Eliezer Tamir");
MODULE_DESCRIPTION("Broadcom NetXtreme II "
- "BCM57710/57711/57711E/57712/57712E Driver");
+ "BCM57710/57711/57711E/"
+ "57712/57712_MF/57800/57800_MF/57810/57810_MF/"
+ "57840/57840_MF Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
MODULE_FIRMWARE(FW_FILE_NAME_E1);
@@ -100,9 +103,11 @@ static int disable_tpa;
module_param(disable_tpa, int, 0);
MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
+#define INT_MODE_INTx 1
+#define INT_MODE_MSI 2
static int int_mode;
module_param(int_mode, int, 0);
-MODULE_PARM_DESC(int_mode, " Force interrupt mode other then MSI-X "
+MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
"(1 INT#x; 2 MSI)");
static int dropless_fc;
@@ -121,37 +126,87 @@ static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, " Default debug msglevel");
-static struct workqueue_struct *bnx2x_wq;
-#ifdef BCM_CNIC
-static u8 ALL_ENODE_MACS[] = {0x01, 0x10, 0x18, 0x01, 0x00, 0x01};
-#endif
+
+struct workqueue_struct *bnx2x_wq;
enum bnx2x_board_type {
BCM57710 = 0,
- BCM57711 = 1,
- BCM57711E = 2,
- BCM57712 = 3,
- BCM57712E = 4
+ BCM57711,
+ BCM57711E,
+ BCM57712,
+ BCM57712_MF,
+ BCM57800,
+ BCM57800_MF,
+ BCM57810,
+ BCM57810_MF,
+ BCM57840,
+ BCM57840_MF
};
/* indexed by board_type, above */
static struct {
char *name;
} board_info[] __devinitdata = {
- { "Broadcom NetXtreme II BCM57710 XGb" },
- { "Broadcom NetXtreme II BCM57711 XGb" },
- { "Broadcom NetXtreme II BCM57711E XGb" },
- { "Broadcom NetXtreme II BCM57712 XGb" },
- { "Broadcom NetXtreme II BCM57712E XGb" }
+ { "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
+ { "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
+ { "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
+ { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" },
+ { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" },
+ { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
+ { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57840 10/20 Gigabit "
+ "Ethernet Multi Function"}
};
+#ifndef PCI_DEVICE_ID_NX2_57710
+#define PCI_DEVICE_ID_NX2_57710 CHIP_NUM_57710
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57711
+#define PCI_DEVICE_ID_NX2_57711 CHIP_NUM_57711
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57711E
+#define PCI_DEVICE_ID_NX2_57711E CHIP_NUM_57711E
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57712
+#define PCI_DEVICE_ID_NX2_57712 CHIP_NUM_57712
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57712_MF
+#define PCI_DEVICE_ID_NX2_57712_MF CHIP_NUM_57712_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57800
+#define PCI_DEVICE_ID_NX2_57800 CHIP_NUM_57800
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57800_MF
+#define PCI_DEVICE_ID_NX2_57800_MF CHIP_NUM_57800_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57810
+#define PCI_DEVICE_ID_NX2_57810 CHIP_NUM_57810
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57810_MF
+#define PCI_DEVICE_ID_NX2_57810_MF CHIP_NUM_57810_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57840
+#define PCI_DEVICE_ID_NX2_57840 CHIP_NUM_57840
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57840_MF
+#define PCI_DEVICE_ID_NX2_57840_MF CHIP_NUM_57840_MF
+#endif
static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712), BCM57712 },
- { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712E), BCM57712E },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712_MF), BCM57712_MF },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800), BCM57800 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800_MF), BCM57800_MF },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810), BCM57810 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_MF), BCM57810_MF },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840), BCM57840 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF },
{ 0 }
};
@@ -168,48 +223,6 @@ static inline void __storm_memset_dma_mapping(struct bnx2x *bp,
REG_WR(bp, addr + 4, U64_HI(mapping));
}
-static inline void __storm_memset_fill(struct bnx2x *bp,
- u32 addr, size_t size, u32 val)
-{
- int i;
- for (i = 0; i < size/4; i++)
- REG_WR(bp, addr + (i * 4), val);
-}
-
-static inline void storm_memset_ustats_zero(struct bnx2x *bp,
- u8 port, u16 stat_id)
-{
- size_t size = sizeof(struct ustorm_per_client_stats);
-
- u32 addr = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
- __storm_memset_fill(bp, addr, size, 0);
-}
-
-static inline void storm_memset_tstats_zero(struct bnx2x *bp,
- u8 port, u16 stat_id)
-{
- size_t size = sizeof(struct tstorm_per_client_stats);
-
- u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
- __storm_memset_fill(bp, addr, size, 0);
-}
-
-static inline void storm_memset_xstats_zero(struct bnx2x *bp,
- u8 port, u16 stat_id)
-{
- size_t size = sizeof(struct xstorm_per_client_stats);
-
- u32 addr = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
- __storm_memset_fill(bp, addr, size, 0);
-}
-
-
static inline void storm_memset_spq_addr(struct bnx2x *bp,
dma_addr_t mapping, u16 abs_fid)
{
@@ -219,103 +232,6 @@ static inline void storm_memset_spq_addr(struct bnx2x *bp,
__storm_memset_dma_mapping(bp, addr, mapping);
}
-static inline void storm_memset_ov(struct bnx2x *bp, u16 ov, u16 abs_fid)
-{
- REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(abs_fid), ov);
-}
-
-static inline void storm_memset_func_cfg(struct bnx2x *bp,
- struct tstorm_eth_function_common_config *tcfg,
- u16 abs_fid)
-{
- size_t size = sizeof(struct tstorm_eth_function_common_config);
-
- u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
-}
-
-static inline void storm_memset_xstats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_tstats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_ustats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_cstats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_xstats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_XSTRORM_INTMEM +
- XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_tstats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_ustats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_USTRORM_INTMEM +
- USTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_cstats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_CSTRORM_INTMEM +
- CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
u16 pf_id)
{
@@ -360,45 +276,6 @@ static inline void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod,
REG_WR16(bp, addr, eq_prod);
}
-static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
- u16 fw_sb_id, u8 sb_index,
- u8 ticks)
-{
-
- int index_offset = CHIP_IS_E2(bp) ?
- offsetof(struct hc_status_block_data_e2, index_data) :
- offsetof(struct hc_status_block_data_e1x, index_data);
- u32 addr = BAR_CSTRORM_INTMEM +
- CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
- index_offset +
- sizeof(struct hc_index_data)*sb_index +
- offsetof(struct hc_index_data, timeout);
- REG_WR8(bp, addr, ticks);
- DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
- port, fw_sb_id, sb_index, ticks);
-}
-static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
- u16 fw_sb_id, u8 sb_index,
- u8 disable)
-{
- u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
- int index_offset = CHIP_IS_E2(bp) ?
- offsetof(struct hc_status_block_data_e2, index_data) :
- offsetof(struct hc_status_block_data_e1x, index_data);
- u32 addr = BAR_CSTRORM_INTMEM +
- CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
- index_offset +
- sizeof(struct hc_index_data)*sb_index +
- offsetof(struct hc_index_data, flags);
- u16 flags = REG_RD16(bp, addr);
- /* clear and set */
- flags &= ~HC_INDEX_DATA_HC_ENABLED;
- flags |= enable_flag;
- REG_WR16(bp, addr, flags);
- DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
- port, fw_sb_id, sb_index, disable);
-}
-
/* used only at init
* locking is done by mcp
*/
@@ -492,13 +369,6 @@ static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae,
}
-const u32 dmae_reg_go_c[] = {
- DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
- DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
- DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
- DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
-};
-
/* copy command into DMAE command memory and set DMAE command go */
void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx)
{
@@ -579,7 +449,11 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
- /* lock the dmae channel */
+ /*
+ * Lock the dmae channel. Disable BHs to prevent a dead-lock
+ * as long as this code is called both from syscall context and
+ * from ndo_set_rx_mode() flow that may be called from BH.
+ */
spin_lock_bh(&bp->dmae_lock);
/* reset completion */
@@ -834,9 +708,9 @@ static int bnx2x_mc_assert(struct bnx2x *bp)
return rc;
}
-static void bnx2x_fw_dump(struct bnx2x *bp)
+void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
{
- u32 addr;
+ u32 addr, val;
u32 mark, offset;
__be32 data[9];
int word;
@@ -845,6 +719,14 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
BNX2X_ERR("NO MCP - can not dump\n");
return;
}
+ netdev_printk(lvl, bp->dev, "bc %d.%d.%d\n",
+ (bp->common.bc_ver & 0xff0000) >> 16,
+ (bp->common.bc_ver & 0xff00) >> 8,
+ (bp->common.bc_ver & 0xff));
+
+ val = REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER);
+ if (val == REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER))
+ printk("%s" "MCP PC at 0x%x\n", lvl, val);
if (BP_PATH(bp) == 0)
trace_shmem_base = bp->common.shmem_base;
@@ -854,9 +736,9 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
mark = REG_RD(bp, addr);
mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
+ ((mark + 0x3) & ~0x3) - 0x08000000;
- pr_err("begin fw dump (mark 0x%x)\n", mark);
+ printk("%s" "begin fw dump (mark 0x%x)\n", lvl, mark);
- pr_err("");
+ printk("%s", lvl);
for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
for (word = 0; word < 8; word++)
data[word] = htonl(REG_RD(bp, offset + 4*word));
@@ -869,7 +751,12 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
data[8] = 0x0;
pr_cont("%s", (char *)data);
}
- pr_err("end of fw dump\n");
+ printk("%s" "end of fw dump\n", lvl);
+}
+
+static inline void bnx2x_fw_dump(struct bnx2x *bp)
+{
+ bnx2x_fw_dump_lvl(bp, KERN_ERR);
}
void bnx2x_panic_dump(struct bnx2x *bp)
@@ -880,6 +767,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
int func = BP_FUNC(bp);
#ifdef BNX2X_STOP_ON_ERROR
u16 start = 0, end = 0;
+ u8 cos;
#endif
bp->stats_state = STATS_STATE_DISABLED;
@@ -890,9 +778,9 @@ void bnx2x_panic_dump(struct bnx2x *bp)
/* Indices */
/* Common */
BNX2X_ERR("def_idx(0x%x) def_att_idx(0x%x) attn_state(0x%x)"
- " spq_prod_idx(0x%x)\n",
- bp->def_idx, bp->def_att_idx,
- bp->attn_state, bp->spq_prod_idx);
+ " spq_prod_idx(0x%x) next_stats_cnt(0x%x)\n",
+ bp->def_idx, bp->def_att_idx, bp->attn_state,
+ bp->spq_prod_idx, bp->stats_counter);
BNX2X_ERR("DSB: attn bits(0x%x) ack(0x%x) id(0x%x) idx(0x%x)\n",
bp->def_status_blk->atten_status_block.attn_bits,
bp->def_status_blk->atten_status_block.attn_bits_ack,
@@ -909,15 +797,17 @@ void bnx2x_panic_dump(struct bnx2x *bp)
CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
i*sizeof(u32));
- pr_cont("igu_sb_id(0x%x) igu_seg_id (0x%x) "
+ 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)\n",
+ "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,
sp_sb_data.p_func.vnic_id,
sp_sb_data.p_func.vf_id,
- sp_sb_data.p_func.vf_valid);
+ sp_sb_data.p_func.vf_valid,
+ sp_sb_data.state);
for_each_eth_queue(bp, i) {
@@ -926,15 +816,16 @@ void bnx2x_panic_dump(struct bnx2x *bp)
struct hc_status_block_data_e2 sb_data_e2;
struct hc_status_block_data_e1x sb_data_e1x;
struct hc_status_block_sm *hc_sm_p =
- CHIP_IS_E2(bp) ?
- sb_data_e2.common.state_machine :
- sb_data_e1x.common.state_machine;
+ CHIP_IS_E1x(bp) ?
+ sb_data_e1x.common.state_machine :
+ sb_data_e2.common.state_machine;
struct hc_index_data *hc_index_p =
- CHIP_IS_E2(bp) ?
- sb_data_e2.index_data :
- sb_data_e1x.index_data;
- int data_size;
+ CHIP_IS_E1x(bp) ?
+ sb_data_e1x.index_data :
+ sb_data_e2.index_data;
+ u8 data_size, cos;
u32 *sb_data_p;
+ struct bnx2x_fp_txdata txdata;
/* Rx */
BNX2X_ERR("fp%d: rx_bd_prod(0x%x) rx_bd_cons(0x%x)"
@@ -949,14 +840,20 @@ void bnx2x_panic_dump(struct bnx2x *bp)
le16_to_cpu(fp->fp_hc_idx));
/* Tx */
- BNX2X_ERR("fp%d: tx_pkt_prod(0x%x) tx_pkt_cons(0x%x)"
- " tx_bd_prod(0x%x) tx_bd_cons(0x%x)"
- " *tx_cons_sb(0x%x)\n",
- i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
- fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
+ for_each_cos_in_tx_queue(fp, cos)
+ {
+ txdata = fp->txdata[cos];
+ BNX2X_ERR("fp%d: tx_pkt_prod(0x%x) tx_pkt_cons(0x%x)"
+ " tx_bd_prod(0x%x) tx_bd_cons(0x%x)"
+ " *tx_cons_sb(0x%x)\n",
+ i, txdata.tx_pkt_prod,
+ txdata.tx_pkt_cons, txdata.tx_bd_prod,
+ txdata.tx_bd_cons,
+ le16_to_cpu(*txdata.tx_cons_sb));
+ }
- loop = CHIP_IS_E2(bp) ?
- HC_SB_MAX_INDICES_E2 : HC_SB_MAX_INDICES_E1X;
+ loop = CHIP_IS_E1x(bp) ?
+ HC_SB_MAX_INDICES_E1X : HC_SB_MAX_INDICES_E2;
/* host sb data */
@@ -976,35 +873,39 @@ void bnx2x_panic_dump(struct bnx2x *bp)
fp->sb_index_values[j],
(j == loop - 1) ? ")" : " ");
/* fw sb data */
- data_size = CHIP_IS_E2(bp) ?
- sizeof(struct hc_status_block_data_e2) :
- sizeof(struct hc_status_block_data_e1x);
+ data_size = CHIP_IS_E1x(bp) ?
+ sizeof(struct hc_status_block_data_e1x) :
+ sizeof(struct hc_status_block_data_e2);
data_size /= sizeof(u32);
- sb_data_p = CHIP_IS_E2(bp) ?
- (u32 *)&sb_data_e2 :
- (u32 *)&sb_data_e1x;
+ sb_data_p = CHIP_IS_E1x(bp) ?
+ (u32 *)&sb_data_e1x :
+ (u32 *)&sb_data_e2;
/* copy sb data in here */
for (j = 0; j < data_size; j++)
*(sb_data_p + j) = REG_RD(bp, BAR_CSTRORM_INTMEM +
CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) +
j * sizeof(u32));
- if (CHIP_IS_E2(bp)) {
- pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) "
- "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n",
+ if (!CHIP_IS_E1x(bp)) {
+ pr_cont("pf_id(0x%x) vf_id(0x%x) vf_valid(0x%x) "
+ "vnic_id(0x%x) same_igu_sb_1b(0x%x) "
+ "state(0x%x)\n",
sb_data_e2.common.p_func.pf_id,
sb_data_e2.common.p_func.vf_id,
sb_data_e2.common.p_func.vf_valid,
sb_data_e2.common.p_func.vnic_id,
- sb_data_e2.common.same_igu_sb_1b);
+ sb_data_e2.common.same_igu_sb_1b,
+ sb_data_e2.common.state);
} else {
- pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) "
- "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n",
+ pr_cont("pf_id(0x%x) vf_id(0x%x) vf_valid(0x%x) "
+ "vnic_id(0x%x) same_igu_sb_1b(0x%x) "
+ "state(0x%x)\n",
sb_data_e1x.common.p_func.pf_id,
sb_data_e1x.common.p_func.vf_id,
sb_data_e1x.common.p_func.vf_valid,
sb_data_e1x.common.p_func.vnic_id,
- sb_data_e1x.common.same_igu_sb_1b);
+ sb_data_e1x.common.same_igu_sb_1b,
+ sb_data_e1x.common.state);
}
/* SB_SMs data */
@@ -1068,23 +969,31 @@ void bnx2x_panic_dump(struct bnx2x *bp)
/* Tx */
for_each_tx_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
+ for_each_cos_in_tx_queue(fp, cos) {
+ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
+
+ start = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) - 10);
+ end = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) + 245);
+ for (j = start; j != end; j = TX_BD(j + 1)) {
+ struct sw_tx_bd *sw_bd =
+ &txdata->tx_buf_ring[j];
+
+ BNX2X_ERR("fp%d: txdata %d, "
+ "packet[%x]=[%p,%x]\n",
+ i, cos, j, sw_bd->skb,
+ sw_bd->first_bd);
+ }
- start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10);
- end = TX_BD(le16_to_cpu(*fp->tx_cons_sb) + 245);
- for (j = start; j != end; j = TX_BD(j + 1)) {
- struct sw_tx_bd *sw_bd = &fp->tx_buf_ring[j];
-
- BNX2X_ERR("fp%d: packet[%x]=[%p,%x]\n",
- i, j, sw_bd->skb, sw_bd->first_bd);
- }
-
- start = TX_BD(fp->tx_bd_cons - 10);
- end = TX_BD(fp->tx_bd_cons + 254);
- for (j = start; j != end; j = TX_BD(j + 1)) {
- u32 *tx_bd = (u32 *)&fp->tx_desc_ring[j];
+ start = TX_BD(txdata->tx_bd_cons - 10);
+ end = TX_BD(txdata->tx_bd_cons + 254);
+ for (j = start; j != end; j = TX_BD(j + 1)) {
+ u32 *tx_bd = (u32 *)&txdata->tx_desc_ring[j];
- BNX2X_ERR("fp%d: tx_bd[%x]=[%x:%x:%x:%x]\n",
- i, j, tx_bd[0], tx_bd[1], tx_bd[2], tx_bd[3]);
+ BNX2X_ERR("fp%d: txdata %d, tx_bd[%x]="
+ "[%x:%x:%x:%x]\n",
+ i, cos, j, tx_bd[0], tx_bd[1],
+ tx_bd[2], tx_bd[3]);
+ }
}
}
#endif
@@ -1093,6 +1002,373 @@ void bnx2x_panic_dump(struct bnx2x *bp)
BNX2X_ERR("end crash dump -----------------\n");
}
+/*
+ * FLR Support for E2
+ *
+ * bnx2x_pf_flr_clnup() is called during nic_load in the per function HW
+ * initialization.
+ */
+#define FLR_WAIT_USEC 10000 /* 10 miliseconds */
+#define FLR_WAIT_INTERAVAL 50 /* usec */
+#define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERAVAL) /* 200 */
+
+struct pbf_pN_buf_regs {
+ int pN;
+ u32 init_crd;
+ u32 crd;
+ u32 crd_freed;
+};
+
+struct pbf_pN_cmd_regs {
+ int pN;
+ u32 lines_occup;
+ u32 lines_freed;
+};
+
+static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp,
+ struct pbf_pN_buf_regs *regs,
+ u32 poll_count)
+{
+ u32 init_crd, crd, crd_start, crd_freed, crd_freed_start;
+ u32 cur_cnt = poll_count;
+
+ crd_freed = crd_freed_start = REG_RD(bp, regs->crd_freed);
+ crd = crd_start = REG_RD(bp, regs->crd);
+ init_crd = REG_RD(bp, regs->init_crd);
+
+ DP(BNX2X_MSG_SP, "INIT CREDIT[%d] : %x\n", regs->pN, init_crd);
+ DP(BNX2X_MSG_SP, "CREDIT[%d] : s:%x\n", regs->pN, crd);
+ DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: s:%x\n", regs->pN, crd_freed);
+
+ while ((crd != init_crd) && ((u32)SUB_S32(crd_freed, crd_freed_start) <
+ (init_crd - crd_start))) {
+ if (cur_cnt--) {
+ udelay(FLR_WAIT_INTERAVAL);
+ crd = REG_RD(bp, regs->crd);
+ crd_freed = REG_RD(bp, regs->crd_freed);
+ } else {
+ DP(BNX2X_MSG_SP, "PBF tx buffer[%d] timed out\n",
+ regs->pN);
+ DP(BNX2X_MSG_SP, "CREDIT[%d] : c:%x\n",
+ regs->pN, crd);
+ DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: c:%x\n",
+ regs->pN, crd_freed);
+ break;
+ }
+ }
+ DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF tx buffer[%d]\n",
+ poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+}
+
+static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
+ struct pbf_pN_cmd_regs *regs,
+ u32 poll_count)
+{
+ u32 occup, to_free, freed, freed_start;
+ u32 cur_cnt = poll_count;
+
+ occup = to_free = REG_RD(bp, regs->lines_occup);
+ freed = freed_start = REG_RD(bp, regs->lines_freed);
+
+ DP(BNX2X_MSG_SP, "OCCUPANCY[%d] : s:%x\n", regs->pN, occup);
+ DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n", regs->pN, freed);
+
+ while (occup && ((u32)SUB_S32(freed, freed_start) < to_free)) {
+ if (cur_cnt--) {
+ udelay(FLR_WAIT_INTERAVAL);
+ occup = REG_RD(bp, regs->lines_occup);
+ freed = REG_RD(bp, regs->lines_freed);
+ } else {
+ DP(BNX2X_MSG_SP, "PBF cmd queue[%d] timed out\n",
+ regs->pN);
+ DP(BNX2X_MSG_SP, "OCCUPANCY[%d] : s:%x\n",
+ regs->pN, occup);
+ DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n",
+ regs->pN, freed);
+ break;
+ }
+ }
+ DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF cmd queue[%d]\n",
+ poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+}
+
+static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
+ u32 expected, u32 poll_count)
+{
+ u32 cur_cnt = poll_count;
+ u32 val;
+
+ while ((val = REG_RD(bp, reg)) != expected && cur_cnt--)
+ udelay(FLR_WAIT_INTERAVAL);
+
+ return val;
+}
+
+static inline int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x *bp, u32 reg,
+ char *msg, u32 poll_cnt)
+{
+ u32 val = bnx2x_flr_clnup_reg_poll(bp, reg, 0, poll_cnt);
+ if (val != 0) {
+ BNX2X_ERR("%s usage count=%d\n", msg, val);
+ return 1;
+ }
+ return 0;
+}
+
+static u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp)
+{
+ /* adjust polling timeout */
+ if (CHIP_REV_IS_EMUL(bp))
+ return FLR_POLL_CNT * 2000;
+
+ if (CHIP_REV_IS_FPGA(bp))
+ return FLR_POLL_CNT * 120;
+
+ return FLR_POLL_CNT;
+}
+
+static void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count)
+{
+ struct pbf_pN_cmd_regs cmd_regs[] = {
+ {0, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_OCCUPANCY_Q0 :
+ PBF_REG_P0_TQ_OCCUPANCY,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_LINES_FREED_CNT_Q0 :
+ PBF_REG_P0_TQ_LINES_FREED_CNT},
+ {1, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_OCCUPANCY_Q1 :
+ PBF_REG_P1_TQ_OCCUPANCY,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_LINES_FREED_CNT_Q1 :
+ PBF_REG_P1_TQ_LINES_FREED_CNT},
+ {4, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_OCCUPANCY_LB_Q :
+ PBF_REG_P4_TQ_OCCUPANCY,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_LINES_FREED_CNT_LB_Q :
+ PBF_REG_P4_TQ_LINES_FREED_CNT}
+ };
+
+ struct pbf_pN_buf_regs buf_regs[] = {
+ {0, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INIT_CRD_Q0 :
+ PBF_REG_P0_INIT_CRD ,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_CREDIT_Q0 :
+ PBF_REG_P0_CREDIT,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 :
+ PBF_REG_P0_INTERNAL_CRD_FREED_CNT},
+ {1, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INIT_CRD_Q1 :
+ PBF_REG_P1_INIT_CRD,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_CREDIT_Q1 :
+ PBF_REG_P1_CREDIT,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 :
+ PBF_REG_P1_INTERNAL_CRD_FREED_CNT},
+ {4, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INIT_CRD_LB_Q :
+ PBF_REG_P4_INIT_CRD,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_CREDIT_LB_Q :
+ PBF_REG_P4_CREDIT,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q :
+ PBF_REG_P4_INTERNAL_CRD_FREED_CNT},
+ };
+
+ int i;
+
+ /* Verify the command queues are flushed P0, P1, P4 */
+ for (i = 0; i < ARRAY_SIZE(cmd_regs); i++)
+ bnx2x_pbf_pN_cmd_flushed(bp, &cmd_regs[i], poll_count);
+
+
+ /* Verify the transmission buffers are flushed P0, P1, P4 */
+ for (i = 0; i < ARRAY_SIZE(buf_regs); i++)
+ bnx2x_pbf_pN_buf_flushed(bp, &buf_regs[i], poll_count);
+}
+
+#define OP_GEN_PARAM(param) \
+ (((param) << SDM_OP_GEN_COMP_PARAM_SHIFT) & SDM_OP_GEN_COMP_PARAM)
+
+#define OP_GEN_TYPE(type) \
+ (((type) << SDM_OP_GEN_COMP_TYPE_SHIFT) & SDM_OP_GEN_COMP_TYPE)
+
+#define OP_GEN_AGG_VECT(index) \
+ (((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX)
+
+
+static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
+ u32 poll_cnt)
+{
+ struct sdm_op_gen op_gen = {0};
+
+ u32 comp_addr = BAR_CSTRORM_INTMEM +
+ CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func);
+ int ret = 0;
+
+ if (REG_RD(bp, comp_addr)) {
+ BNX2X_ERR("Cleanup complete is not 0\n");
+ return 1;
+ }
+
+ op_gen.command |= OP_GEN_PARAM(XSTORM_AGG_INT_FINAL_CLEANUP_INDEX);
+ op_gen.command |= OP_GEN_TYPE(XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE);
+ op_gen.command |= OP_GEN_AGG_VECT(clnup_func);
+ op_gen.command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT;
+
+ DP(BNX2X_MSG_SP, "FW Final cleanup\n");
+ REG_WR(bp, XSDM_REG_OPERATION_GEN, op_gen.command);
+
+ if (bnx2x_flr_clnup_reg_poll(bp, comp_addr, 1, poll_cnt) != 1) {
+ BNX2X_ERR("FW final cleanup did not succeed\n");
+ ret = 1;
+ }
+ /* Zero completion for nxt FLR */
+ REG_WR(bp, comp_addr, 0);
+
+ return ret;
+}
+
+static inline u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
+{
+ int pos;
+ u16 status;
+
+ pos = pci_pcie_cap(dev);
+ if (!pos)
+ return false;
+
+ pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+ return status & PCI_EXP_DEVSTA_TRPND;
+}
+
+/* PF FLR specific routines
+*/
+static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt)
+{
+
+ /* wait for CFC PF usage-counter to zero (includes all the VFs) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ CFC_REG_NUM_LCIDS_INSIDE_PF,
+ "CFC PF usage counter timed out",
+ poll_cnt))
+ return 1;
+
+
+ /* Wait for DQ PF usage-counter to zero (until DQ cleanup) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ DORQ_REG_PF_USAGE_CNT,
+ "DQ PF usage counter timed out",
+ poll_cnt))
+ return 1;
+
+ /* Wait for QM PF usage-counter to zero (until DQ cleanup) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ QM_REG_PF_USG_CNT_0 + 4*BP_FUNC(bp),
+ "QM PF usage counter timed out",
+ poll_cnt))
+ return 1;
+
+ /* Wait for Timer PF usage-counters to zero (until DQ cleanup) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ TM_REG_LIN0_VNIC_UC + 4*BP_PORT(bp),
+ "Timers VNIC usage counter timed out",
+ poll_cnt))
+ return 1;
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ TM_REG_LIN0_NUM_SCANS + 4*BP_PORT(bp),
+ "Timers NUM_SCANS usage counter timed out",
+ poll_cnt))
+ return 1;
+
+ /* Wait DMAE PF usage counter to zero */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ dmae_reg_go_c[INIT_DMAE_C(bp)],
+ "DMAE dommand register timed out",
+ poll_cnt))
+ return 1;
+
+ return 0;
+}
+
+static void bnx2x_hw_enable_status(struct bnx2x *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, CFC_REG_WEAK_ENABLE_PF);
+ DP(BNX2X_MSG_SP, "CFC_REG_WEAK_ENABLE_PF is 0x%x\n", val);
+
+ val = REG_RD(bp, PBF_REG_DISABLE_PF);
+ DP(BNX2X_MSG_SP, "PBF_REG_DISABLE_PF is 0x%x\n", val);
+
+ val = REG_RD(bp, IGU_REG_PCI_PF_MSI_EN);
+ DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSI_EN is 0x%x\n", val);
+
+ val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_EN);
+ DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_EN is 0x%x\n", val);
+
+ val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_FUNC_MASK);
+ DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_FUNC_MASK is 0x%x\n", val);
+
+ val = REG_RD(bp, PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR);
+ DP(BNX2X_MSG_SP, "PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR is 0x%x\n", val);
+
+ val = REG_RD(bp, PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR);
+ DP(BNX2X_MSG_SP, "PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR is 0x%x\n", val);
+
+ val = REG_RD(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
+ DP(BNX2X_MSG_SP, "PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER is 0x%x\n",
+ val);
+}
+
+static int bnx2x_pf_flr_clnup(struct bnx2x *bp)
+{
+ u32 poll_cnt = bnx2x_flr_clnup_poll_count(bp);
+
+ DP(BNX2X_MSG_SP, "Cleanup after FLR PF[%d]\n", BP_ABS_FUNC(bp));
+
+ /* Re-enable PF target read access */
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
+
+ /* Poll HW usage counters */
+ if (bnx2x_poll_hw_usage_counters(bp, poll_cnt))
+ return -EBUSY;
+
+ /* Zero the igu 'trailing edge' and 'leading edge' */
+
+ /* Send the FW cleanup command */
+ if (bnx2x_send_final_clnup(bp, (u8)BP_FUNC(bp), poll_cnt))
+ return -EBUSY;
+
+ /* ATC cleanup */
+
+ /* Verify TX hw is flushed */
+ bnx2x_tx_hw_flushed(bp, poll_cnt);
+
+ /* Wait 100ms (not adjusted according to platform) */
+ msleep(100);
+
+ /* Verify no pending pci transactions */
+ if (bnx2x_is_pcie_pending(bp->pdev))
+ BNX2X_ERR("PCIE Transactions still pending\n");
+
+ /* Debug */
+ bnx2x_hw_enable_status(bp);
+
+ /*
+ * Master enable - Due to WB DMAE writes performed before this
+ * register is re-initialized as part of the regular function init
+ */
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
+
+ return 0;
+}
+
static void bnx2x_hc_int_enable(struct bnx2x *bp)
{
int port = BP_PORT(bp);
@@ -1273,7 +1549,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp)
BNX2X_ERR("BUG! proper val not read from IGU!\n");
}
-static void bnx2x_int_disable(struct bnx2x *bp)
+void bnx2x_int_disable(struct bnx2x *bp)
{
if (bp->common.int_block == INT_BLOCK_HC)
bnx2x_hc_int_disable(bp);
@@ -1286,10 +1562,6 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
int i, offset;
- /* disable interrupt handling */
- atomic_inc(&bp->intr_sem);
- smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
if (disable_hw)
/* prevent the HW from sending interrupts */
bnx2x_int_disable(bp);
@@ -1302,12 +1574,13 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
offset++;
#endif
for_each_eth_queue(bp, i)
- synchronize_irq(bp->msix_table[i + offset].vector);
+ synchronize_irq(bp->msix_table[offset++].vector);
} else
synchronize_irq(bp->pdev->irq);
/* make sure sp_task is not running */
cancel_delayed_work(&bp->sp_task);
+ cancel_delayed_work(&bp->period_task);
flush_workqueue(bnx2x_wq);
}
@@ -1351,59 +1624,129 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource)
return false;
}
+/**
+ * bnx2x_get_leader_lock_resource - get the recovery leader resource id
+ *
+ * @bp: driver handle
+ *
+ * Returns the recovery leader resource id according to the engine this function
+ * belongs to. Currently only only 2 engines is supported.
+ */
+static inline int bnx2x_get_leader_lock_resource(struct bnx2x *bp)
+{
+ if (BP_PATH(bp))
+ return HW_LOCK_RESOURCE_RECOVERY_LEADER_1;
+ else
+ return HW_LOCK_RESOURCE_RECOVERY_LEADER_0;
+}
+
+/**
+ * bnx2x_trylock_leader_lock- try to aquire a leader lock.
+ *
+ * @bp: driver handle
+ *
+ * Tries to aquire a leader lock for cuurent engine.
+ */
+static inline bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
+{
+ return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
+}
+
#ifdef BCM_CNIC
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid);
+static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err);
#endif
-void bnx2x_sp_event(struct bnx2x_fastpath *fp,
- union eth_rx_cqe *rr_cqe)
+void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
{
struct bnx2x *bp = fp->bp;
int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data);
int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data);
+ enum bnx2x_queue_cmd drv_cmd = BNX2X_Q_CMD_MAX;
+ struct bnx2x_queue_sp_obj *q_obj = &fp->q_obj;
DP(BNX2X_MSG_SP,
"fp %d cid %d got ramrod #%d state is %x type is %d\n",
fp->index, cid, command, bp->state,
rr_cqe->ramrod_cqe.ramrod_type);
- switch (command | fp->state) {
- case (RAMROD_CMD_ID_ETH_CLIENT_SETUP | BNX2X_FP_STATE_OPENING):
- DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n", cid);
- fp->state = BNX2X_FP_STATE_OPEN;
+ switch (command) {
+ case (RAMROD_CMD_ID_ETH_CLIENT_UPDATE):
+ DP(BNX2X_MSG_SP, "got UPDATE ramrod. CID %d\n", cid);
+ drv_cmd = BNX2X_Q_CMD_UPDATE;
break;
- case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING):
- DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid);
- fp->state = BNX2X_FP_STATE_HALTED;
+ case (RAMROD_CMD_ID_ETH_CLIENT_SETUP):
+ DP(BNX2X_MSG_SP, "got MULTI[%d] setup ramrod\n", cid);
+ drv_cmd = BNX2X_Q_CMD_SETUP;
break;
- case (RAMROD_CMD_ID_ETH_TERMINATE | BNX2X_FP_STATE_TERMINATING):
- DP(NETIF_MSG_IFDOWN, "got MULTI[%d] teminate ramrod\n", cid);
- fp->state = BNX2X_FP_STATE_TERMINATED;
+ case (RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP):
+ DP(NETIF_MSG_IFUP, "got MULTI[%d] tx-only setup ramrod\n", cid);
+ drv_cmd = BNX2X_Q_CMD_SETUP_TX_ONLY;
break;
- default:
- BNX2X_ERR("unexpected MC reply (%d) "
- "fp[%d] state is %x\n",
- command, fp->index, fp->state);
+ case (RAMROD_CMD_ID_ETH_HALT):
+ DP(BNX2X_MSG_SP, "got MULTI[%d] halt ramrod\n", cid);
+ drv_cmd = BNX2X_Q_CMD_HALT;
break;
+
+ case (RAMROD_CMD_ID_ETH_TERMINATE):
+ DP(BNX2X_MSG_SP, "got MULTI[%d] teminate ramrod\n", cid);
+ drv_cmd = BNX2X_Q_CMD_TERMINATE;
+ break;
+
+ case (RAMROD_CMD_ID_ETH_EMPTY):
+ DP(BNX2X_MSG_SP, "got MULTI[%d] empty ramrod\n", cid);
+ drv_cmd = BNX2X_Q_CMD_EMPTY;
+ break;
+
+ default:
+ BNX2X_ERR("unexpected MC reply (%d) on fp[%d]\n",
+ command, fp->index);
+ return;
}
+ if ((drv_cmd != BNX2X_Q_CMD_MAX) &&
+ q_obj->complete_cmd(bp, q_obj, drv_cmd))
+ /* q_obj->complete_cmd() failure means that this was
+ * an unexpected completion.
+ *
+ * In this case we don't want to increase the bp->spq_left
+ * because apparently we haven't sent this command the first
+ * place.
+ */
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+#else
+ return;
+#endif
+
smp_mb__before_atomic_inc();
atomic_inc(&bp->cq_spq_left);
- /* push the change in fp->state and towards the memory */
- smp_wmb();
+ /* push the change in bp->spq_left and towards the memory */
+ smp_mb__after_atomic_inc();
+
+ DP(BNX2X_MSG_SP, "bp->cq_spq_left %x\n", atomic_read(&bp->cq_spq_left));
return;
}
+void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod)
+{
+ u32 start = BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset;
+
+ bnx2x_update_rx_prod_gen(bp, fp, bd_prod, rx_comp_prod, rx_sge_prod,
+ start);
+}
+
irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
{
struct bnx2x *bp = netdev_priv(dev_instance);
u16 status = bnx2x_ack_int(bp);
u16 mask;
int i;
+ u8 cos;
/* Return here if interrupt is shared and it's not for us */
if (unlikely(status == 0)) {
@@ -1412,12 +1755,6 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
}
DP(NETIF_MSG_INTR, "got an interrupt status 0x%x\n", status);
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return IRQ_HANDLED;
- }
-
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return IRQ_HANDLED;
@@ -1426,11 +1763,12 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- mask = 0x2 << (fp->index + CNIC_CONTEXT_USE);
+ mask = 0x2 << (fp->index + CNIC_PRESENT);
if (status & mask) {
- /* Handle Rx and Tx according to SB id */
+ /* Handle Rx or Tx according to SB id */
prefetch(fp->rx_cons_sb);
- prefetch(fp->tx_cons_sb);
+ for_each_cos_in_tx_queue(fp, cos)
+ prefetch(fp->txdata[cos].tx_cons_sb);
prefetch(&fp->sb_running_index[SM_RX_ID]);
napi_schedule(&bnx2x_fp(bp, fp->index, napi));
status &= ~mask;
@@ -1442,11 +1780,13 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
if (status & (mask | 0x1)) {
struct cnic_ops *c_ops = NULL;
- rcu_read_lock();
- c_ops = rcu_dereference(bp->cnic_ops);
- if (c_ops)
- c_ops->cnic_handler(bp->cnic_data, NULL);
- rcu_read_unlock();
+ if (likely(bp->state == BNX2X_STATE_OPEN)) {
+ rcu_read_lock();
+ c_ops = rcu_dereference(bp->cnic_ops);
+ if (c_ops)
+ c_ops->cnic_handler(bp->cnic_data, NULL);
+ rcu_read_unlock();
+ }
status &= ~mask;
}
@@ -1467,9 +1807,6 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
return IRQ_HANDLED;
}
-/* end of fast path */
-
-
/* Link */
/*
@@ -1521,6 +1858,11 @@ int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource)
return -EAGAIN;
}
+int bnx2x_release_leader_lock(struct bnx2x *bp)
+{
+ return bnx2x_release_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
+}
+
int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource)
{
u32 lock_status;
@@ -1641,6 +1983,53 @@ int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
return 0;
}
+int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode)
+{
+ u32 gpio_reg = 0;
+ int rc = 0;
+
+ /* Any port swapping should be handled by caller. */
+
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+ /* read GPIO and mask except the float bits */
+ gpio_reg = REG_RD(bp, MISC_REG_GPIO);
+ gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS);
+ gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_CLR_POS);
+ gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_SET_POS);
+
+ switch (mode) {
+ case MISC_REGISTERS_GPIO_OUTPUT_LOW:
+ DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output low\n", pins);
+ /* set CLR */
+ gpio_reg |= (pins << MISC_REGISTERS_GPIO_CLR_POS);
+ break;
+
+ case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
+ DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output high\n", pins);
+ /* set SET */
+ gpio_reg |= (pins << MISC_REGISTERS_GPIO_SET_POS);
+ break;
+
+ case MISC_REGISTERS_GPIO_INPUT_HI_Z:
+ DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> input\n", pins);
+ /* set FLOAT */
+ gpio_reg |= (pins << MISC_REGISTERS_GPIO_FLOAT_POS);
+ break;
+
+ default:
+ BNX2X_ERR("Invalid GPIO mode assignment %d\n", mode);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc == 0)
+ REG_WR(bp, MISC_REG_GPIO, gpio_reg);
+
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+
+ return rc;
+}
+
int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
{
/* The GPIO should be swapped if swap register is set and active */
@@ -1733,45 +2122,6 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
return 0;
}
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
-{
- u32 sel_phy_idx = 0;
- if (bp->link_vars.link_up) {
- sel_phy_idx = EXT_PHY1;
- /* In case link is SERDES, check if the EXT_PHY2 is the one */
- if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
- (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
- sel_phy_idx = EXT_PHY2;
- } else {
-
- switch (bnx2x_phy_selection(&bp->link_params)) {
- case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
- case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
- case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
- sel_phy_idx = EXT_PHY1;
- break;
- case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
- case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
- sel_phy_idx = EXT_PHY2;
- break;
- }
- }
- /*
- * The selected actived PHY is always after swapping (in case PHY
- * swapping is enabled). So when swapping is enabled, we need to reverse
- * the configuration
- */
-
- if (bp->link_params.multi_phy_config &
- PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
- if (sel_phy_idx == EXT_PHY1)
- sel_phy_idx = EXT_PHY2;
- else if (sel_phy_idx == EXT_PHY2)
- sel_phy_idx = EXT_PHY1;
- }
- return LINK_CONFIG_IDX(sel_phy_idx);
-}
-
void bnx2x_calc_fc_adv(struct bnx2x *bp)
{
u8 cfg_idx = bnx2x_get_link_cfg_idx(bp);
@@ -1804,10 +2154,12 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
u8 rc;
int cfx_idx = bnx2x_get_link_cfg_idx(bp);
u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
- /* Initialize link parameters structure variables */
- /* It is recommended to turn off RX FC for jumbo frames
- for better performance */
- if ((CHIP_IS_E1x(bp)) && (bp->dev->mtu > 5000))
+ /*
+ * Initialize link parameters structure variables
+ * It is recommended to turn off RX FC for jumbo frames
+ * for better performance
+ */
+ if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000))
bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
else
bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
@@ -1815,8 +2167,18 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
bnx2x_acquire_phy_lock(bp);
if (load_mode == LOAD_DIAG) {
- bp->link_params.loopback_mode = LOOPBACK_XGXS;
- bp->link_params.req_line_speed[cfx_idx] = SPEED_10000;
+ struct link_params *lp = &bp->link_params;
+ lp->loopback_mode = LOOPBACK_XGXS;
+ /* do PHY loopback at 10G speed, if possible */
+ if (lp->req_line_speed[cfx_idx] < SPEED_10000) {
+ if (lp->speed_cap_mask[cfx_idx] &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+ lp->req_line_speed[cfx_idx] =
+ SPEED_10000;
+ else
+ lp->req_line_speed[cfx_idx] =
+ SPEED_1000;
+ }
}
rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
@@ -1828,7 +2190,8 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) {
bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
bnx2x_link_report(bp);
- }
+ } else
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
return rc;
}
@@ -1942,8 +2305,12 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
bp->vn_weight_sum += vn_min_rate;
}
- /* ... only if all min rates are zeros - disable fairness */
- if (all_zero) {
+ /* if ETS or all min rates are zeros - disable fairness */
+ if (BNX2X_IS_ETS_ENABLED(bp)) {
+ bp->cmng.flags.cmng_enables &=
+ ~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
+ DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n");
+ } else if (all_zero) {
bp->cmng.flags.cmng_enables &=
~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
@@ -2144,11 +2511,11 @@ static void bnx2x_link_attn(struct bnx2x *bp)
pause_enabled);
}
- if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
+ if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
struct host_port_stats *pstats;
pstats = bnx2x_sp(bp, port_stats);
- /* reset old bmac stats */
+ /* reset old mac stats */
memset(&(pstats->mac_stx[0]), 0,
sizeof(struct mac_stx));
}
@@ -2198,12 +2565,23 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
bp->port.pmf = 1;
DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+ /*
+ * We need the mb() to ensure the ordering between the writing to
+ * bp->port.pmf here and reading it from the bnx2x_periodic_task().
+ */
+ smp_mb();
+
+ /* queue a periodic task */
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+
+ bnx2x_dcbx_pmf_update(bp);
+
/* enable nig attention */
val = (0xff0f | (1 << (BP_E1HVN(bp) + 4)));
if (bp->common.int_block == INT_BLOCK_HC) {
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
- } else if (CHIP_IS_E2(bp)) {
+ } else if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
}
@@ -2233,7 +2611,8 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param);
SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq));
- DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
+ DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB param 0x%08x\n",
+ (command | seq), param);
do {
/* let the FW do it's magic ... */
@@ -2264,182 +2643,118 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
static u8 stat_counter_valid(struct bnx2x *bp, struct bnx2x_fastpath *fp)
{
#ifdef BCM_CNIC
- if (IS_FCOE_FP(fp) && IS_MF(bp))
+ /* Statistics are not supported for CNIC Clients at the moment */
+ if (IS_FCOE_FP(fp))
return false;
#endif
return true;
}
-/* must be called under rtnl_lock */
-static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters)
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
{
- u32 mask = (1 << cl_id);
-
- /* initial seeting is BNX2X_ACCEPT_NONE */
- u8 drop_all_ucast = 1, drop_all_bcast = 1, drop_all_mcast = 1;
- u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
- u8 unmatched_unicast = 0;
-
- if (filters & BNX2X_ACCEPT_UNMATCHED_UCAST)
- unmatched_unicast = 1;
+ if (CHIP_IS_E1x(bp)) {
+ struct tstorm_eth_function_common_config tcfg = {0};
- if (filters & BNX2X_PROMISCUOUS_MODE) {
- /* promiscious - accept all, drop none */
- drop_all_ucast = drop_all_bcast = drop_all_mcast = 0;
- accp_all_ucast = accp_all_bcast = accp_all_mcast = 1;
- if (IS_MF_SI(bp)) {
- /*
- * SI mode defines to accept in promiscuos mode
- * only unmatched packets
- */
- unmatched_unicast = 1;
- accp_all_ucast = 0;
- }
- }
- if (filters & BNX2X_ACCEPT_UNICAST) {
- /* accept matched ucast */
- drop_all_ucast = 0;
+ storm_memset_func_cfg(bp, &tcfg, p->func_id);
}
- if (filters & BNX2X_ACCEPT_MULTICAST)
- /* accept matched mcast */
- drop_all_mcast = 0;
- if (filters & BNX2X_ACCEPT_ALL_UNICAST) {
- /* accept all mcast */
- drop_all_ucast = 0;
- accp_all_ucast = 1;
- }
- if (filters & BNX2X_ACCEPT_ALL_MULTICAST) {
- /* accept all mcast */
- drop_all_mcast = 0;
- accp_all_mcast = 1;
- }
- if (filters & BNX2X_ACCEPT_BROADCAST) {
- /* accept (all) bcast */
- drop_all_bcast = 0;
- accp_all_bcast = 1;
- }
-
- bp->mac_filters.ucast_drop_all = drop_all_ucast ?
- bp->mac_filters.ucast_drop_all | mask :
- bp->mac_filters.ucast_drop_all & ~mask;
-
- bp->mac_filters.mcast_drop_all = drop_all_mcast ?
- bp->mac_filters.mcast_drop_all | mask :
- bp->mac_filters.mcast_drop_all & ~mask;
-
- bp->mac_filters.bcast_drop_all = drop_all_bcast ?
- bp->mac_filters.bcast_drop_all | mask :
- bp->mac_filters.bcast_drop_all & ~mask;
-
- bp->mac_filters.ucast_accept_all = accp_all_ucast ?
- bp->mac_filters.ucast_accept_all | mask :
- bp->mac_filters.ucast_accept_all & ~mask;
-
- bp->mac_filters.mcast_accept_all = accp_all_mcast ?
- bp->mac_filters.mcast_accept_all | mask :
- bp->mac_filters.mcast_accept_all & ~mask;
-
- bp->mac_filters.bcast_accept_all = accp_all_bcast ?
- bp->mac_filters.bcast_accept_all | mask :
- bp->mac_filters.bcast_accept_all & ~mask;
+ /* Enable the function in the FW */
+ storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
+ storm_memset_func_en(bp, p->func_id, 1);
- bp->mac_filters.unmatched_unicast = unmatched_unicast ?
- bp->mac_filters.unmatched_unicast | mask :
- bp->mac_filters.unmatched_unicast & ~mask;
+ /* spq */
+ if (p->func_flgs & FUNC_FLG_SPQ) {
+ storm_memset_spq_addr(bp, p->spq_map, p->func_id);
+ REG_WR(bp, XSEM_REG_FAST_MEMORY +
+ XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
+ }
}
-static void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
+/**
+ * bnx2x_get_tx_only_flags - Return common flags
+ *
+ * @bp device handle
+ * @fp queue handle
+ * @zero_stats TRUE if statistics zeroing is needed
+ *
+ * Return the flags that are common for the Tx-only and not normal connections.
+ */
+static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp,
+ bool zero_stats)
{
- struct tstorm_eth_function_common_config tcfg = {0};
- u16 rss_flgs;
-
- /* tpa */
- if (p->func_flgs & FUNC_FLG_TPA)
- tcfg.config_flags |=
- TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
-
- /* set rss flags */
- rss_flgs = (p->rss->mode <<
- TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT);
-
- if (p->rss->cap & RSS_IPV4_CAP)
- rss_flgs |= RSS_IPV4_CAP_MASK;
- if (p->rss->cap & RSS_IPV4_TCP_CAP)
- rss_flgs |= RSS_IPV4_TCP_CAP_MASK;
- if (p->rss->cap & RSS_IPV6_CAP)
- rss_flgs |= RSS_IPV6_CAP_MASK;
- if (p->rss->cap & RSS_IPV6_TCP_CAP)
- rss_flgs |= RSS_IPV6_TCP_CAP_MASK;
+ unsigned long flags = 0;
- tcfg.config_flags |= rss_flgs;
- tcfg.rss_result_mask = p->rss->result_mask;
+ /* PF driver will always initialize the Queue to an ACTIVE state */
+ __set_bit(BNX2X_Q_FLG_ACTIVE, &flags);
- storm_memset_func_cfg(bp, &tcfg, p->func_id);
-
- /* Enable the function in the FW */
- storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
- storm_memset_func_en(bp, p->func_id, 1);
+ /* tx only connections collect statistics (on the same index as the
+ * parent connection). The statistics are zeroed when the parent
+ * connection is initialized.
+ */
+ if (stat_counter_valid(bp, fp)) {
+ __set_bit(BNX2X_Q_FLG_STATS, &flags);
+ if (zero_stats)
+ __set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
+ }
- /* statistics */
- if (p->func_flgs & FUNC_FLG_STATS) {
- struct stats_indication_flags stats_flags = {0};
- stats_flags.collect_eth = 1;
+ return flags;
+}
- storm_memset_xstats_flags(bp, &stats_flags, p->func_id);
- storm_memset_xstats_addr(bp, p->fw_stat_map, p->func_id);
+static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp,
+ bool leading)
+{
+ unsigned long flags = 0;
- storm_memset_tstats_flags(bp, &stats_flags, p->func_id);
- storm_memset_tstats_addr(bp, p->fw_stat_map, p->func_id);
+ /* calculate other queue flags */
+ if (IS_MF_SD(bp))
+ __set_bit(BNX2X_Q_FLG_OV, &flags);
- storm_memset_ustats_flags(bp, &stats_flags, p->func_id);
- storm_memset_ustats_addr(bp, p->fw_stat_map, p->func_id);
+ if (IS_FCOE_FP(fp))
+ __set_bit(BNX2X_Q_FLG_FCOE, &flags);
- storm_memset_cstats_flags(bp, &stats_flags, p->func_id);
- storm_memset_cstats_addr(bp, p->fw_stat_map, p->func_id);
+ if (!fp->disable_tpa) {
+ __set_bit(BNX2X_Q_FLG_TPA, &flags);
+ __set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
}
- /* spq */
- if (p->func_flgs & FUNC_FLG_SPQ) {
- storm_memset_spq_addr(bp, p->spq_map, p->func_id);
- REG_WR(bp, XSEM_REG_FAST_MEMORY +
- XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
+ if (leading) {
+ __set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags);
+ __set_bit(BNX2X_Q_FLG_MCAST, &flags);
}
-}
-static inline u16 bnx2x_get_cl_flags(struct bnx2x *bp,
- struct bnx2x_fastpath *fp)
-{
- u16 flags = 0;
+ /* Always set HW VLAN stripping */
+ __set_bit(BNX2X_Q_FLG_VLAN, &flags);
- /* calculate queue flags */
- flags |= QUEUE_FLG_CACHE_ALIGN;
- flags |= QUEUE_FLG_HC;
- flags |= IS_MF_SD(bp) ? QUEUE_FLG_OV : 0;
- flags |= QUEUE_FLG_VLAN;
- DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
+ return flags | bnx2x_get_common_flags(bp, fp, true);
+}
- if (!fp->disable_tpa)
- flags |= QUEUE_FLG_TPA;
+static void bnx2x_pf_q_prep_general(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct bnx2x_general_setup_params *gen_init,
+ u8 cos)
+{
+ gen_init->stat_id = bnx2x_stats_id(fp);
+ gen_init->spcl_id = fp->cl_id;
- flags = stat_counter_valid(bp, fp) ?
- (flags | QUEUE_FLG_STATS) : (flags & ~QUEUE_FLG_STATS);
+ /* Always use mini-jumbo MTU for FCoE L2 ring */
+ if (IS_FCOE_FP(fp))
+ gen_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
+ else
+ gen_init->mtu = bp->dev->mtu;
- return flags;
+ gen_init->cos = cos;
}
-static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
+static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
struct bnx2x_fastpath *fp, struct rxq_pause_params *pause,
- struct bnx2x_rxq_init_params *rxq_init)
+ struct bnx2x_rxq_setup_params *rxq_init)
{
- u16 max_sge = 0;
+ u8 max_sge = 0;
u16 sge_sz = 0;
u16 tpa_agg_size = 0;
- /* calculate queue flags */
- u16 flags = bnx2x_get_cl_flags(bp, fp);
-
if (!fp->disable_tpa) {
pause->sge_th_hi = 250;
pause->sge_th_lo = 150;
@@ -2460,80 +2775,74 @@ static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
pause->bd_th_lo = 250;
pause->rcq_th_hi = 350;
pause->rcq_th_lo = 250;
- pause->sge_th_hi = 0;
- pause->sge_th_lo = 0;
+
pause->pri_map = 1;
}
/* rxq setup */
- rxq_init->flags = flags;
- rxq_init->cxt = &bp->context.vcxt[fp->cid].eth;
rxq_init->dscr_map = fp->rx_desc_mapping;
rxq_init->sge_map = fp->rx_sge_mapping;
rxq_init->rcq_map = fp->rx_comp_mapping;
rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
- /* Always use mini-jumbo MTU for FCoE L2 ring */
- if (IS_FCOE_FP(fp))
- rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
- else
- rxq_init->mtu = bp->dev->mtu;
+ /* This should be a maximum number of data bytes that may be
+ * placed on the BD (not including paddings).
+ */
+ rxq_init->buf_sz = fp->rx_buf_size - BNX2X_FW_RX_ALIGN -
+ IP_HEADER_ALIGNMENT_PADDING;
- rxq_init->buf_sz = fp->rx_buf_size;
rxq_init->cl_qzone_id = fp->cl_qzone_id;
- rxq_init->cl_id = fp->cl_id;
- rxq_init->spcl_id = fp->cl_id;
- rxq_init->stat_id = fp->cl_id;
rxq_init->tpa_agg_sz = tpa_agg_size;
rxq_init->sge_buf_sz = sge_sz;
rxq_init->max_sges_pkt = max_sge;
+ rxq_init->rss_engine_id = BP_FUNC(bp);
+
+ /* Maximum number or simultaneous TPA aggregation for this Queue.
+ *
+ * For PF Clients it should be the maximum avaliable number.
+ * VF driver(s) may want to define it to a smaller value.
+ */
+ rxq_init->max_tpa_queues =
+ (CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
+ ETH_MAX_AGGREGATION_QUEUES_E1H_E2);
+
rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT;
rxq_init->fw_sb_id = fp->fw_sb_id;
if (IS_FCOE_FP(fp))
rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS;
else
- rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
-
- rxq_init->cid = HW_CID(bp, fp->cid);
-
- rxq_init->hc_rate = bp->rx_ticks ? (1000000 / bp->rx_ticks) : 0;
+ rxq_init->sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS;
}
-static void bnx2x_pf_tx_cl_prep(struct bnx2x *bp,
- struct bnx2x_fastpath *fp, struct bnx2x_txq_init_params *txq_init)
+static void bnx2x_pf_tx_q_prep(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct bnx2x_txq_setup_params *txq_init,
+ u8 cos)
{
- u16 flags = bnx2x_get_cl_flags(bp, fp);
-
- txq_init->flags = flags;
- txq_init->cxt = &bp->context.vcxt[fp->cid].eth;
- txq_init->dscr_map = fp->tx_desc_mapping;
- txq_init->stat_id = fp->cl_id;
- txq_init->cid = HW_CID(bp, fp->cid);
- txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX;
+ txq_init->dscr_map = fp->txdata[cos].tx_desc_mapping;
+ txq_init->sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS + cos;
txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW;
txq_init->fw_sb_id = fp->fw_sb_id;
+ /*
+ * set the tss leading client id for TX classfication ==
+ * leading RSS client id
+ */
+ txq_init->tss_leading_cl_id = bnx2x_fp(bp, 0, cl_id);
+
if (IS_FCOE_FP(fp)) {
txq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS;
txq_init->traffic_type = LLFC_TRAFFIC_TYPE_FCOE;
}
-
- txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0;
}
static void bnx2x_pf_init(struct bnx2x *bp)
{
struct bnx2x_func_init_params func_init = {0};
- struct bnx2x_rss_params rss = {0};
struct event_ring_data eq_data = { {0} };
u16 flags;
- /* pf specific setups */
- if (!CHIP_IS_E1(bp))
- storm_memset_ov(bp, bp->mf_ov, BP_FUNC(bp));
-
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
/* reset IGU PF statistics: MSIX + ATTN */
/* PF */
REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
@@ -2551,27 +2860,14 @@ static void bnx2x_pf_init(struct bnx2x *bp)
/* function setup flags */
flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
- if (CHIP_IS_E1x(bp))
- flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
- else
- flags |= FUNC_FLG_TPA;
-
- /* function setup */
-
- /**
- * Although RSS is meaningless when there is a single HW queue we
- * still need it enabled in order to have HW Rx hash generated.
+ /* This flag is relevant for E1x only.
+ * E2 doesn't have a TPA configuration in a function level.
*/
- rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP |
- RSS_IPV6_CAP | RSS_IPV6_TCP_CAP);
- rss.mode = bp->multi_mode;
- rss.result_mask = MULTI_MASK;
- func_init.rss = &rss;
+ flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
func_init.func_flgs = flags;
func_init.pf_id = BP_FUNC(bp);
func_init.func_id = BP_FUNC(bp);
- func_init.fw_stat_map = bnx2x_sp_mapping(bp, fw_stats);
func_init.spq_map = bp->spq_mapping;
func_init.spq_prod = bp->spq_prod_idx;
@@ -2580,11 +2876,11 @@ static void bnx2x_pf_init(struct bnx2x *bp)
memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
/*
- Congestion management values depend on the link rate
- There is no active link so initial link rate is set to 10 Gbps.
- When the link comes up The congestion management values are
- re-calculated according to the actual link rate.
- */
+ * Congestion management values depend on the link rate
+ * There is no active link so initial link rate is set to 10 Gbps.
+ * When the link comes up The congestion management values are
+ * re-calculated according to the actual link rate.
+ */
bp->link_vars.line_speed = SPEED_10000;
bnx2x_cmng_fns_init(bp, true, bnx2x_get_cmng_fns_mode(bp));
@@ -2592,10 +2888,6 @@ static void bnx2x_pf_init(struct bnx2x *bp)
if (bp->port.pmf)
storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
- /* no rx until link is up */
- bp->rx_mode = BNX2X_RX_MODE_NONE;
- bnx2x_set_storm_rx_mode(bp);
-
/* init Event Queue */
eq_data.base_addr.hi = U64_HI(bp->eq_mapping);
eq_data.base_addr.lo = U64_LO(bp->eq_mapping);
@@ -2610,11 +2902,9 @@ static void bnx2x_e1h_disable(struct bnx2x *bp)
{
int port = BP_PORT(bp);
- netif_tx_disable(bp->dev);
+ bnx2x_tx_disable(bp);
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
-
- netif_carrier_off(bp->dev);
}
static void bnx2x_e1h_enable(struct bnx2x *bp)
@@ -2709,20 +2999,60 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
- /* Make sure that BD data is updated before writing the producer */
- wmb();
+ /*
+ * Make sure that BD data is updated before writing the producer:
+ * BD data is written to the memory, the producer is read from the
+ * memory, thus we need a full memory barrier to ensure the ordering.
+ */
+ mb();
REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
bp->spq_prod_idx);
mmiowb();
}
-/* the slow path queue is odd since completions arrive on the fastpath ring */
+/**
+ * bnx2x_is_contextless_ramrod - check if the current command ends on EQ
+ *
+ * @cmd: command to check
+ * @cmd_type: command type
+ */
+static inline bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type)
+{
+ if ((cmd_type == NONE_CONNECTION_TYPE) ||
+ (cmd == RAMROD_CMD_ID_ETH_FORWARD_SETUP) ||
+ (cmd == RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES) ||
+ (cmd == RAMROD_CMD_ID_ETH_FILTER_RULES) ||
+ (cmd == RAMROD_CMD_ID_ETH_MULTICAST_RULES) ||
+ (cmd == RAMROD_CMD_ID_ETH_SET_MAC) ||
+ (cmd == RAMROD_CMD_ID_ETH_RSS_UPDATE))
+ return true;
+ else
+ return false;
+
+}
+
+
+/**
+ * bnx2x_sp_post - place a single command on an SP ring
+ *
+ * @bp: driver handle
+ * @command: command to place (e.g. SETUP, FILTER_RULES, etc.)
+ * @cid: SW CID the command is related to
+ * @data_hi: command private data address (high 32 bits)
+ * @data_lo: command private data address (low 32 bits)
+ * @cmd_type: command type (e.g. NONE, ETH)
+ *
+ * SP data is handled as if it's always an address pair, thus data fields are
+ * not swapped to little endian in upper functions. Instead this function swaps
+ * data as if it's two u32 fields.
+ */
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
- u32 data_hi, u32 data_lo, int common)
+ u32 data_hi, u32 data_lo, int cmd_type)
{
struct eth_spe *spe;
u16 type;
+ bool common = bnx2x_is_contextless_ramrod(command, cmd_type);
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -2752,17 +3082,7 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
HW_CID(bp, cid));
- if (common)
- /* Common ramrods:
- * FUNC_START, FUNC_STOP, CFC_DEL, STATS, SET_MAC
- * TRAFFIC_STOP, TRAFFIC_START
- */
- type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
- & SPE_HDR_CONN_TYPE;
- else
- /* ETH ramrods: SETUP, HALT */
- type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
- & SPE_HDR_CONN_TYPE;
+ type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
SPE_HDR_FUNCTION_ID);
@@ -2772,25 +3092,23 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
spe->data.update_data_addr.hi = cpu_to_le32(data_hi);
spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
- /* stats ramrod has it's own slot on the spq */
- if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) {
- /* It's ok if the actual decrement is issued towards the memory
- * somewhere between the spin_lock and spin_unlock. Thus no
- * more explict memory barrier is needed.
- */
- if (common)
- atomic_dec(&bp->eq_spq_left);
- else
- atomic_dec(&bp->cq_spq_left);
- }
+ /*
+ * It's ok if the actual decrement is issued towards the memory
+ * somewhere between the spin_lock and spin_unlock. Thus no
+ * more explict memory barrier is needed.
+ */
+ if (common)
+ atomic_dec(&bp->eq_spq_left);
+ else
+ atomic_dec(&bp->cq_spq_left);
DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
- "SPQE[%x] (%x:%x) command %d hw_cid %x data (%x:%x) "
- "type(0x%x) left (ETH, COMMON) (%x,%x)\n",
+ "SPQE[%x] (%x:%x) (cmd, common?) (%d,%d) hw_cid %x data (%x:%x) "
+ "type(0x%x) left (CQ, EQ) (%x,%x)\n",
bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
(u32)(U64_LO(bp->spq_mapping) +
- (void *)bp->spq_prod_bd - (void *)bp->spq), command,
+ (void *)bp->spq_prod_bd - (void *)bp->spq), command, common,
HW_CID(bp, cid), data_hi, data_lo, type,
atomic_read(&bp->cq_spq_left), atomic_read(&bp->eq_spq_left));
@@ -2893,9 +3211,15 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
/* save nig interrupt mask */
nig_mask = REG_RD(bp, nig_int_mask_addr);
- REG_WR(bp, nig_int_mask_addr, 0);
- bnx2x_link_attn(bp);
+ /* If nig_mask is not set, no need to call the update
+ * function.
+ */
+ if (nig_mask) {
+ REG_WR(bp, nig_int_mask_addr, 0);
+
+ bnx2x_link_attn(bp);
+ }
/* handle unicore attn? */
}
@@ -3000,8 +3324,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
bnx2x_fan_failure(bp);
}
- if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 |
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1)) {
+ if ((attn & bp->link_vars.aeu_int_mask) && bp->port.pmf) {
bnx2x_acquire_phy_lock(bp);
bnx2x_handle_module_detect_int(&bp->link_params);
bnx2x_release_phy_lock(bp);
@@ -3064,13 +3387,13 @@ static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
}
if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
-
val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
- BNX2X_ERR("PXP hw attention 0x%x\n", val);
+ BNX2X_ERR("PXP hw attention-0 0x%x\n", val);
/* RQ_USDMDP_FIFO_OVERFLOW */
if (val & 0x18000)
BNX2X_ERR("FATAL error from PXP\n");
- if (CHIP_IS_E2(bp)) {
+
+ if (!CHIP_IS_E1x(bp)) {
val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_1);
BNX2X_ERR("PXP hw attention-1 0x%x\n", val);
}
@@ -3118,20 +3441,31 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
bnx2x_pmf_update(bp);
- /* Always call it here: bnx2x_link_report() will
- * prevent the link indication duplication.
- */
- bnx2x__link_status_update(bp);
-
if (bp->port.pmf &&
(val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) &&
bp->dcbx_enabled > 0)
/* start dcbx state machine */
bnx2x_dcbx_set_params(bp,
BNX2X_DCBX_STATE_NEG_RECEIVED);
+ if (bp->link_vars.periodic_flags &
+ PERIODIC_FLAGS_LINK_EVENT) {
+ /* sync with link */
+ bnx2x_acquire_phy_lock(bp);
+ bp->link_vars.periodic_flags &=
+ ~PERIODIC_FLAGS_LINK_EVENT;
+ bnx2x_release_phy_lock(bp);
+ if (IS_MF(bp))
+ bnx2x_link_sync_notify(bp);
+ bnx2x_link_report(bp);
+ }
+ /* Always call it here: bnx2x_link_report() will
+ * prevent the link indication duplication.
+ */
+ bnx2x__link_status_update(bp);
} else if (attn & BNX2X_MC_ASSERT_BITS) {
BNX2X_ERR("MC assert!\n");
+ bnx2x_mc_assert(bp);
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0);
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_9, 0);
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_8, 0);
@@ -3164,72 +3498,185 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
}
}
-#define BNX2X_MISC_GEN_REG MISC_REG_GENERIC_POR_1
-#define LOAD_COUNTER_BITS 16 /* Number of bits for load counter */
-#define LOAD_COUNTER_MASK (((u32)0x1 << LOAD_COUNTER_BITS) - 1)
-#define RESET_DONE_FLAG_MASK (~LOAD_COUNTER_MASK)
-#define RESET_DONE_FLAG_SHIFT LOAD_COUNTER_BITS
+/*
+ * Bits map:
+ * 0-7 - Engine0 load counter.
+ * 8-15 - Engine1 load counter.
+ * 16 - Engine0 RESET_IN_PROGRESS bit.
+ * 17 - Engine1 RESET_IN_PROGRESS bit.
+ * 18 - Engine0 ONE_IS_LOADED. Set when there is at least one active function
+ * on the engine
+ * 19 - Engine1 ONE_IS_LOADED.
+ * 20 - Chip reset flow bit. When set none-leader must wait for both engines
+ * leader to complete (check for both RESET_IN_PROGRESS bits and not for
+ * just the one belonging to its engine).
+ *
+ */
+#define BNX2X_RECOVERY_GLOB_REG MISC_REG_GENERIC_POR_1
+
+#define BNX2X_PATH0_LOAD_CNT_MASK 0x000000ff
+#define BNX2X_PATH0_LOAD_CNT_SHIFT 0
+#define BNX2X_PATH1_LOAD_CNT_MASK 0x0000ff00
+#define BNX2X_PATH1_LOAD_CNT_SHIFT 8
+#define BNX2X_PATH0_RST_IN_PROG_BIT 0x00010000
+#define BNX2X_PATH1_RST_IN_PROG_BIT 0x00020000
+#define BNX2X_GLOBAL_RESET_BIT 0x00040000
/*
+ * Set the GLOBAL_RESET bit.
+ *
+ * Should be run under rtnl lock
+ */
+void bnx2x_set_reset_global(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT);
+ barrier();
+ mmiowb();
+}
+
+/*
+ * Clear the GLOBAL_RESET bit.
+ *
+ * Should be run under rtnl lock
+ */
+static inline void bnx2x_clear_reset_global(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT));
+ barrier();
+ mmiowb();
+}
+
+/*
+ * Checks the GLOBAL_RESET bit.
+ *
* should be run under rtnl lock
*/
+static inline bool bnx2x_reset_is_global(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val);
+ return (val & BNX2X_GLOBAL_RESET_BIT) ? true : false;
+}
+
+/*
+ * Clear RESET_IN_PROGRESS bit for the current engine.
+ *
+ * Should be run under rtnl lock
+ */
static inline void bnx2x_set_reset_done(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- val &= ~(1 << RESET_DONE_FLAG_SHIFT);
- REG_WR(bp, BNX2X_MISC_GEN_REG, val);
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 bit = BP_PATH(bp) ?
+ BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+
+ /* Clear the bit */
+ val &= ~bit;
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
}
/*
+ * Set RESET_IN_PROGRESS for the current engine.
+ *
* should be run under rtnl lock
*/
-static inline void bnx2x_set_reset_in_progress(struct bnx2x *bp)
+void bnx2x_set_reset_in_progress(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- val |= (1 << 16);
- REG_WR(bp, BNX2X_MISC_GEN_REG, val);
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 bit = BP_PATH(bp) ?
+ BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+
+ /* Set the bit */
+ val |= bit;
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
}
/*
+ * Checks the RESET_IN_PROGRESS bit for the given engine.
* should be run under rtnl lock
*/
-bool bnx2x_reset_is_done(struct bnx2x *bp)
+bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val);
- return (val & RESET_DONE_FLAG_MASK) ? false : true;
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 bit = engine ?
+ BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+
+ /* return false if bit is set */
+ return (val & bit) ? false : true;
}
/*
+ * Increment the load counter for the current engine.
+ *
* should be run under rtnl lock
*/
-inline void bnx2x_inc_load_cnt(struct bnx2x *bp)
+void bnx2x_inc_load_cnt(struct bnx2x *bp)
{
- u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG);
+ u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK;
+ u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+ BNX2X_PATH0_LOAD_CNT_SHIFT;
DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
- val1 = ((val & LOAD_COUNTER_MASK) + 1) & LOAD_COUNTER_MASK;
- REG_WR(bp, BNX2X_MISC_GEN_REG, (val & RESET_DONE_FLAG_MASK) | val1);
+ /* get the current counter value */
+ val1 = (val & mask) >> shift;
+
+ /* increment... */
+ val1++;
+
+ /* clear the old value */
+ val &= ~mask;
+
+ /* set the new one */
+ val |= ((val1 << shift) & mask);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
}
-/*
- * should be run under rtnl lock
+/**
+ * bnx2x_dec_load_cnt - decrement the load counter
+ *
+ * @bp: driver handle
+ *
+ * Should be run under rtnl lock.
+ * Decrements the load counter for the current engine. Returns
+ * the new counter value.
*/
u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
{
- u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG);
+ u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK;
+ u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+ BNX2X_PATH0_LOAD_CNT_SHIFT;
DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
- val1 = ((val & LOAD_COUNTER_MASK) - 1) & LOAD_COUNTER_MASK;
- REG_WR(bp, BNX2X_MISC_GEN_REG, (val & RESET_DONE_FLAG_MASK) | val1);
+ /* get the current counter value */
+ val1 = (val & mask) >> shift;
+
+ /* decrement... */
+ val1--;
+
+ /* clear the old value */
+ val &= ~mask;
+
+ /* set the new one */
+ val |= ((val1 << shift) & mask);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
@@ -3237,17 +3684,39 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
}
/*
+ * Read the load counter for the current engine.
+ *
* should be run under rtnl lock
*/
-static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp)
+static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
{
- return REG_RD(bp, BNX2X_MISC_GEN_REG) & LOAD_COUNTER_MASK;
+ u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK);
+ u32 shift = (engine ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+ BNX2X_PATH0_LOAD_CNT_SHIFT);
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ DP(NETIF_MSG_HW, "GLOB_REG=0x%08x\n", val);
+
+ val = (val & mask) >> shift;
+
+ DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val);
+
+ return val;
}
+/*
+ * Reset the load counter for the current engine.
+ *
+ * should be run under rtnl lock
+ */
static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- REG_WR(bp, BNX2X_MISC_GEN_REG, val & (~LOAD_COUNTER_MASK));
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask));
}
static inline void _print_next_block(int idx, const char *blk)
@@ -3257,7 +3726,8 @@ static inline void _print_next_block(int idx, const char *blk)
pr_cont("%s", blk);
}
-static inline int bnx2x_print_blocks_with_parity0(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
+ bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3266,19 +3736,33 @@ static inline int bnx2x_print_blocks_with_parity0(u32 sig, int par_num)
if (sig & cur_bit) {
switch (cur_bit) {
case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
- _print_next_block(par_num++, "BRB");
+ if (print)
+ _print_next_block(par_num++, "BRB");
break;
case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
- _print_next_block(par_num++, "PARSER");
+ if (print)
+ _print_next_block(par_num++, "PARSER");
break;
case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
- _print_next_block(par_num++, "TSDM");
+ if (print)
+ _print_next_block(par_num++, "TSDM");
break;
case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
- _print_next_block(par_num++, "SEARCHER");
+ if (print)
+ _print_next_block(par_num++,
+ "SEARCHER");
+ break;
+ case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "TCM");
break;
case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
- _print_next_block(par_num++, "TSEMI");
+ if (print)
+ _print_next_block(par_num++, "TSEMI");
+ break;
+ case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "XPB");
break;
}
@@ -3290,7 +3774,8 @@ static inline int bnx2x_print_blocks_with_parity0(u32 sig, int par_num)
return par_num;
}
-static inline int bnx2x_print_blocks_with_parity1(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
+ bool *global, bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3298,38 +3783,72 @@ static inline int bnx2x_print_blocks_with_parity1(u32 sig, int par_num)
cur_bit = ((u32)0x1 << i);
if (sig & cur_bit) {
switch (cur_bit) {
- case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
- _print_next_block(par_num++, "PBCLIENT");
+ case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "PBF");
break;
case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR:
- _print_next_block(par_num++, "QM");
+ if (print)
+ _print_next_block(par_num++, "QM");
+ break;
+ case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "TM");
break;
case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR:
- _print_next_block(par_num++, "XSDM");
+ if (print)
+ _print_next_block(par_num++, "XSDM");
+ break;
+ case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "XCM");
break;
case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR:
- _print_next_block(par_num++, "XSEMI");
+ if (print)
+ _print_next_block(par_num++, "XSEMI");
break;
case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR:
- _print_next_block(par_num++, "DOORBELLQ");
+ if (print)
+ _print_next_block(par_num++,
+ "DOORBELLQ");
+ break;
+ case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "NIG");
break;
case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR:
- _print_next_block(par_num++, "VAUX PCI CORE");
+ if (print)
+ _print_next_block(par_num++,
+ "VAUX PCI CORE");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR:
- _print_next_block(par_num++, "DEBUG");
+ if (print)
+ _print_next_block(par_num++, "DEBUG");
break;
case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR:
- _print_next_block(par_num++, "USDM");
+ if (print)
+ _print_next_block(par_num++, "USDM");
+ break;
+ case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "UCM");
break;
case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR:
- _print_next_block(par_num++, "USEMI");
+ if (print)
+ _print_next_block(par_num++, "USEMI");
break;
case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR:
- _print_next_block(par_num++, "UPB");
+ if (print)
+ _print_next_block(par_num++, "UPB");
break;
case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR:
- _print_next_block(par_num++, "CSDM");
+ if (print)
+ _print_next_block(par_num++, "CSDM");
+ break;
+ case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "CCM");
break;
}
@@ -3341,7 +3860,8 @@ static inline int bnx2x_print_blocks_with_parity1(u32 sig, int par_num)
return par_num;
}
-static inline int bnx2x_print_blocks_with_parity2(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
+ bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3350,26 +3870,37 @@ static inline int bnx2x_print_blocks_with_parity2(u32 sig, int par_num)
if (sig & cur_bit) {
switch (cur_bit) {
case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
- _print_next_block(par_num++, "CSEMI");
+ if (print)
+ _print_next_block(par_num++, "CSEMI");
break;
case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
- _print_next_block(par_num++, "PXP");
+ if (print)
+ _print_next_block(par_num++, "PXP");
break;
case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
- _print_next_block(par_num++,
+ if (print)
+ _print_next_block(par_num++,
"PXPPCICLOCKCLIENT");
break;
case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
- _print_next_block(par_num++, "CFC");
+ if (print)
+ _print_next_block(par_num++, "CFC");
break;
case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
- _print_next_block(par_num++, "CDU");
+ if (print)
+ _print_next_block(par_num++, "CDU");
+ break;
+ case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "DMAE");
break;
case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
- _print_next_block(par_num++, "IGU");
+ if (print)
+ _print_next_block(par_num++, "IGU");
break;
case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
- _print_next_block(par_num++, "MISC");
+ if (print)
+ _print_next_block(par_num++, "MISC");
break;
}
@@ -3381,7 +3912,8 @@ static inline int bnx2x_print_blocks_with_parity2(u32 sig, int par_num)
return par_num;
}
-static inline int bnx2x_print_blocks_with_parity3(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
+ bool *global, bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3390,16 +3922,54 @@ static inline int bnx2x_print_blocks_with_parity3(u32 sig, int par_num)
if (sig & cur_bit) {
switch (cur_bit) {
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY:
- _print_next_block(par_num++, "MCP ROM");
+ if (print)
+ _print_next_block(par_num++, "MCP ROM");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY:
- _print_next_block(par_num++, "MCP UMP RX");
+ if (print)
+ _print_next_block(par_num++,
+ "MCP UMP RX");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY:
- _print_next_block(par_num++, "MCP UMP TX");
+ if (print)
+ _print_next_block(par_num++,
+ "MCP UMP TX");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY:
- _print_next_block(par_num++, "MCP SCPAD");
+ if (print)
+ _print_next_block(par_num++,
+ "MCP SCPAD");
+ *global = true;
+ break;
+ }
+
+ /* Clear the bit */
+ sig &= ~cur_bit;
+ }
+ }
+
+ return par_num;
+}
+
+static inline int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
+ bool print)
+{
+ int i = 0;
+ u32 cur_bit = 0;
+ for (i = 0; sig; i++) {
+ cur_bit = ((u32)0x1 << i);
+ if (sig & cur_bit) {
+ switch (cur_bit) {
+ case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "PGLUE_B");
+ break;
+ case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "ATC");
break;
}
@@ -3411,38 +3981,55 @@ static inline int bnx2x_print_blocks_with_parity3(u32 sig, int par_num)
return par_num;
}
-static inline bool bnx2x_parity_attn(struct bnx2x *bp, u32 sig0, u32 sig1,
- u32 sig2, u32 sig3)
+static inline bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
+ u32 *sig)
{
- if ((sig0 & HW_PRTY_ASSERT_SET_0) || (sig1 & HW_PRTY_ASSERT_SET_1) ||
- (sig2 & HW_PRTY_ASSERT_SET_2) || (sig3 & HW_PRTY_ASSERT_SET_3)) {
+ if ((sig[0] & HW_PRTY_ASSERT_SET_0) ||
+ (sig[1] & HW_PRTY_ASSERT_SET_1) ||
+ (sig[2] & HW_PRTY_ASSERT_SET_2) ||
+ (sig[3] & HW_PRTY_ASSERT_SET_3) ||
+ (sig[4] & HW_PRTY_ASSERT_SET_4)) {
int par_num = 0;
DP(NETIF_MSG_HW, "Was parity error: HW block parity attention: "
- "[0]:0x%08x [1]:0x%08x "
- "[2]:0x%08x [3]:0x%08x\n",
- sig0 & HW_PRTY_ASSERT_SET_0,
- sig1 & HW_PRTY_ASSERT_SET_1,
- sig2 & HW_PRTY_ASSERT_SET_2,
- sig3 & HW_PRTY_ASSERT_SET_3);
- printk(KERN_ERR"%s: Parity errors detected in blocks: ",
- bp->dev->name);
- par_num = bnx2x_print_blocks_with_parity0(
- sig0 & HW_PRTY_ASSERT_SET_0, par_num);
- par_num = bnx2x_print_blocks_with_parity1(
- sig1 & HW_PRTY_ASSERT_SET_1, par_num);
- par_num = bnx2x_print_blocks_with_parity2(
- sig2 & HW_PRTY_ASSERT_SET_2, par_num);
- par_num = bnx2x_print_blocks_with_parity3(
- sig3 & HW_PRTY_ASSERT_SET_3, par_num);
- printk("\n");
+ "[0]:0x%08x [1]:0x%08x [2]:0x%08x [3]:0x%08x "
+ "[4]:0x%08x\n",
+ sig[0] & HW_PRTY_ASSERT_SET_0,
+ sig[1] & HW_PRTY_ASSERT_SET_1,
+ sig[2] & HW_PRTY_ASSERT_SET_2,
+ sig[3] & HW_PRTY_ASSERT_SET_3,
+ sig[4] & HW_PRTY_ASSERT_SET_4);
+ if (print)
+ netdev_err(bp->dev,
+ "Parity errors detected in blocks: ");
+ par_num = bnx2x_check_blocks_with_parity0(
+ sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print);
+ par_num = bnx2x_check_blocks_with_parity1(
+ sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print);
+ par_num = bnx2x_check_blocks_with_parity2(
+ sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print);
+ par_num = bnx2x_check_blocks_with_parity3(
+ sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print);
+ par_num = bnx2x_check_blocks_with_parity4(
+ sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print);
+
+ if (print)
+ pr_cont("\n");
+
return true;
} else
return false;
}
-bool bnx2x_chk_parity_attn(struct bnx2x *bp)
+/**
+ * bnx2x_chk_parity_attn - checks for parity attentions.
+ *
+ * @bp: driver handle
+ * @global: true if there was a global attention
+ * @print: show parity attention in syslog
+ */
+bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
{
- struct attn_route attn;
+ struct attn_route attn = { {0} };
int port = BP_PORT(bp);
attn.sig[0] = REG_RD(bp,
@@ -3458,8 +4045,12 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp)
MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 +
port*4);
- return bnx2x_parity_attn(bp, attn.sig[0], attn.sig[1], attn.sig[2],
- attn.sig[3]);
+ if (!CHIP_IS_E1x(bp))
+ attn.sig[4] = REG_RD(bp,
+ MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 +
+ port*4);
+
+ return bnx2x_parity_attn(bp, global, print, attn.sig);
}
@@ -3538,21 +4129,25 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
u32 reg_addr;
u32 val;
u32 aeu_mask;
+ bool global = false;
/* need to take HW lock because MCP or other port might also
try to handle this event */
bnx2x_acquire_alr(bp);
- if (CHIP_PARITY_ENABLED(bp) && bnx2x_chk_parity_attn(bp)) {
+ if (bnx2x_chk_parity_attn(bp, &global, true)) {
+#ifndef BNX2X_STOP_ON_ERROR
bp->recovery_state = BNX2X_RECOVERY_INIT;
- bnx2x_set_reset_in_progress(bp);
- schedule_delayed_work(&bp->reset_task, 0);
+ schedule_delayed_work(&bp->sp_rtnl_task, 0);
/* Disable HW interrupts */
bnx2x_int_disable(bp);
- bnx2x_release_alr(bp);
/* In case of parity errors don't handle attentions so that
* other function would "see" parity errors.
*/
+#else
+ bnx2x_panic();
+#endif
+ bnx2x_release_alr(bp);
return;
}
@@ -3560,7 +4155,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4);
attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
attn.sig[4] =
REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port*4);
else
@@ -3656,6 +4251,15 @@ static void bnx2x_attn_int(struct bnx2x *bp)
bnx2x_attn_int_deasserted(bp, deasserted);
}
+void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+ u16 index, u8 op, u8 update)
+{
+ u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
+
+ bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
+ igu_addr);
+}
+
static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
{
/* No memory barriers */
@@ -3667,6 +4271,8 @@ static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
union event_ring_elem *elem)
{
+ u8 err = elem->message.error;
+
if (!bp->cnic_eth_dev.starting_cid ||
(cid < bp->cnic_eth_dev.starting_cid &&
cid != bp->cnic_eth_dev.iscsi_l2_cid))
@@ -3674,16 +4280,123 @@ static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
DP(BNX2X_MSG_SP, "got delete ramrod for CNIC CID %d\n", cid);
- if (unlikely(elem->message.data.cfc_del_event.error)) {
+ if (unlikely(err)) {
+
BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
cid);
bnx2x_panic_dump(bp);
}
- bnx2x_cnic_cfc_comp(bp, cid);
+ bnx2x_cnic_cfc_comp(bp, cid, err);
return 0;
}
#endif
+static inline void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
+{
+ struct bnx2x_mcast_ramrod_params rparam;
+ int rc;
+
+ memset(&rparam, 0, sizeof(rparam));
+
+ rparam.mcast_obj = &bp->mcast_obj;
+
+ netif_addr_lock_bh(bp->dev);
+
+ /* Clear pending state for the last command */
+ bp->mcast_obj.raw.clear_pending(&bp->mcast_obj.raw);
+
+ /* If there are pending mcast commands - send them */
+ if (bp->mcast_obj.check_pending(&bp->mcast_obj)) {
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
+ if (rc < 0)
+ BNX2X_ERR("Failed to send pending mcast commands: %d\n",
+ rc);
+ }
+
+ netif_addr_unlock_bh(bp->dev);
+}
+
+static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp,
+ union event_ring_elem *elem)
+{
+ unsigned long ramrod_flags = 0;
+ int rc = 0;
+ u32 cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK;
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj;
+
+ /* Always push next commands out, don't wait here */
+ __set_bit(RAMROD_CONT, &ramrod_flags);
+
+ switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
+ case BNX2X_FILTER_MAC_PENDING:
+#ifdef BCM_CNIC
+ if (cid == BNX2X_ISCSI_ETH_CID)
+ vlan_mac_obj = &bp->iscsi_l2_mac_obj;
+ else
+#endif
+ 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.
+ */
+ bnx2x_handle_mcast_eqe(bp);
+ return;
+ default:
+ BNX2X_ERR("Unsupported classification command: %d\n",
+ elem->message.data.eth_event.echo);
+ return;
+ }
+
+ rc = vlan_mac_obj->complete(bp, vlan_mac_obj, elem, &ramrod_flags);
+
+ if (rc < 0)
+ BNX2X_ERR("Failed to schedule new commands: %d\n", rc);
+ else if (rc > 0)
+ DP(BNX2X_MSG_SP, "Scheduled next pending commands...\n");
+
+}
+
+#ifdef BCM_CNIC
+static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
+#endif
+
+static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
+{
+ netif_addr_lock_bh(bp->dev);
+
+ clear_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
+
+ /* Send rx_mode command again if was requested */
+ if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state))
+ bnx2x_set_storm_rx_mode(bp);
+#ifdef BCM_CNIC
+ else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED,
+ &bp->sp_state))
+ bnx2x_set_iscsi_eth_rx_mode(bp, true);
+ else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
+ &bp->sp_state))
+ bnx2x_set_iscsi_eth_rx_mode(bp, false);
+#endif
+
+ netif_addr_unlock_bh(bp->dev);
+}
+
+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);
+#ifdef BCM_CNIC
+ if (cid == BNX2X_FCOE_ETH_CID)
+ return &bnx2x_fcoe(bp, q_obj);
+ else
+#endif
+ return &bnx2x_fp(bp, CID_TO_FP(cid), q_obj);
+}
+
static void bnx2x_eq_int(struct bnx2x *bp)
{
u16 hw_cons, sw_cons, sw_prod;
@@ -3691,6 +4404,9 @@ static void bnx2x_eq_int(struct bnx2x *bp)
u32 cid;
u8 opcode;
int spqe_cnt = 0;
+ struct bnx2x_queue_sp_obj *q_obj;
+ struct bnx2x_func_sp_obj *f_obj = &bp->func_obj;
+ struct bnx2x_raw_obj *rss_raw = &bp->rss_conf_obj.raw;
hw_cons = le16_to_cpu(*bp->eq_cons_sb);
@@ -3709,7 +4425,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
sw_cons = bp->eq_cons;
sw_prod = bp->eq_prod;
- DP(BNX2X_MSG_SP, "EQ: hw_cons %u sw_cons %u bp->cq_spq_left %u\n",
+ DP(BNX2X_MSG_SP, "EQ: hw_cons %u sw_cons %u bp->eq_spq_left %x\n",
hw_cons, sw_cons, atomic_read(&bp->eq_spq_left));
for (; sw_cons != hw_cons;
@@ -3725,9 +4441,10 @@ static void bnx2x_eq_int(struct bnx2x *bp)
/* handle eq element */
switch (opcode) {
case EVENT_RING_OPCODE_STAT_QUERY:
- DP(NETIF_MSG_TIMER, "got statistics comp event\n");
+ DP(NETIF_MSG_TIMER, "got statistics comp event %d\n",
+ bp->stats_comp++);
/* nothing to do with stats comp */
- continue;
+ goto next_spqe;
case EVENT_RING_OPCODE_CFC_DEL:
/* handle according to cid range */
@@ -3735,60 +4452,100 @@ static void bnx2x_eq_int(struct bnx2x *bp)
* we may want to verify here that the bp state is
* HALTING
*/
- DP(NETIF_MSG_IFDOWN,
+ DP(BNX2X_MSG_SP,
"got delete ramrod for MULTI[%d]\n", cid);
#ifdef BCM_CNIC
if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
goto next_spqe;
- if (cid == BNX2X_FCOE_ETH_CID)
- bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
- else
#endif
- bnx2x_fp(bp, cid, state) =
- BNX2X_FP_STATE_CLOSED;
+ q_obj = bnx2x_cid_to_q_obj(bp, cid);
+
+ if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
+ break;
+
+
goto next_spqe;
case EVENT_RING_OPCODE_STOP_TRAFFIC:
- DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n");
+ DP(BNX2X_MSG_SP, "got STOP TRAFFIC\n");
+ if (f_obj->complete_cmd(bp, f_obj,
+ BNX2X_F_CMD_TX_STOP))
+ break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED);
goto next_spqe;
+
case EVENT_RING_OPCODE_START_TRAFFIC:
- DP(NETIF_MSG_IFUP, "got START TRAFFIC\n");
+ DP(BNX2X_MSG_SP, "got START TRAFFIC\n");
+ if (f_obj->complete_cmd(bp, f_obj,
+ BNX2X_F_CMD_TX_START))
+ break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
goto next_spqe;
+ case EVENT_RING_OPCODE_FUNCTION_START:
+ DP(BNX2X_MSG_SP, "got FUNC_START ramrod\n");
+ if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_START))
+ break;
+
+ goto next_spqe;
+
+ case EVENT_RING_OPCODE_FUNCTION_STOP:
+ DP(BNX2X_MSG_SP, "got FUNC_STOP ramrod\n");
+ if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_STOP))
+ break;
+
+ goto next_spqe;
}
switch (opcode | bp->state) {
- case (EVENT_RING_OPCODE_FUNCTION_START |
+ case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
BNX2X_STATE_OPENING_WAIT4_PORT):
- DP(NETIF_MSG_IFUP, "got setup ramrod\n");
- bp->state = BNX2X_STATE_FUNC_STARTED;
+ cid = elem->message.data.eth_event.echo &
+ BNX2X_SWCID_MASK;
+ DP(BNX2X_MSG_SP, "got RSS_UPDATE ramrod. CID %d\n",
+ cid);
+ rss_raw->clear_pending(rss_raw);
break;
- case (EVENT_RING_OPCODE_FUNCTION_STOP |
+ case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
+ case (EVENT_RING_OPCODE_SET_MAC |
+ BNX2X_STATE_CLOSING_WAIT4_HALT):
+ case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+ BNX2X_STATE_DIAG):
+ case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got halt ramrod\n");
- bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
+ DP(BNX2X_MSG_SP, "got (un)set mac ramrod\n");
+ bnx2x_handle_classification_eqe(bp, elem);
break;
- case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
- case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
- DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
- if (elem->message.data.set_mac_event.echo)
- bp->set_mac_pending = 0;
+ case (EVENT_RING_OPCODE_MULTICAST_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_MULTICAST_RULES |
+ BNX2X_STATE_DIAG):
+ case (EVENT_RING_OPCODE_MULTICAST_RULES |
+ BNX2X_STATE_CLOSING_WAIT4_HALT):
+ DP(BNX2X_MSG_SP, "got mcast ramrod\n");
+ bnx2x_handle_mcast_eqe(bp);
break;
- case (EVENT_RING_OPCODE_SET_MAC |
+ case (EVENT_RING_OPCODE_FILTERS_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_FILTERS_RULES |
+ BNX2X_STATE_DIAG):
+ case (EVENT_RING_OPCODE_FILTERS_RULES |
BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
- if (elem->message.data.set_mac_event.echo)
- bp->set_mac_pending = 0;
+ DP(BNX2X_MSG_SP, "got rx_mode ramrod\n");
+ bnx2x_handle_rx_mode_eqe(bp);
break;
default:
/* unknown event log error and continue */
- BNX2X_ERR("Unknown EQ event %d\n",
- elem->message.opcode);
+ BNX2X_ERR("Unknown EQ event %d, bp->state 0x%x\n",
+ elem->message.opcode, bp->state);
}
next_spqe:
spqe_cnt++;
@@ -3811,12 +4568,6 @@ static void bnx2x_sp_task(struct work_struct *work)
struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
u16 status;
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return;
- }
-
status = bnx2x_update_dsb_idx(bp);
/* if (status == 0) */
/* BNX2X_ERR("spurious slowpath interrupt!\n"); */
@@ -3835,8 +4586,15 @@ static void bnx2x_sp_task(struct work_struct *work)
struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
if ((!NO_FCOE(bp)) &&
- (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp)))
+ (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
+ /*
+ * Prevent local bottom-halves from running as
+ * we are going to change the local NAPI list.
+ */
+ local_bh_disable();
napi_schedule(&bnx2x_fcoe(bp, napi));
+ local_bh_enable();
+ }
#endif
/* Handle EQ completions */
bnx2x_eq_int(bp);
@@ -3860,12 +4618,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
struct net_device *dev = dev_instance;
struct bnx2x *bp = netdev_priv(dev);
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return IRQ_HANDLED;
- }
-
bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0,
IGU_INT_DISABLE, 0);
@@ -3892,20 +4644,27 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
/* end of slow path */
+
+void bnx2x_drv_pulse(struct bnx2x *bp)
+{
+ SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
+ bp->fw_drv_pulse_wr_seq);
+}
+
+
static void bnx2x_timer(unsigned long data)
{
+ u8 cos;
struct bnx2x *bp = (struct bnx2x *) data;
if (!netif_running(bp->dev))
return;
- if (atomic_read(&bp->intr_sem) != 0)
- goto timer_restart;
-
if (poll) {
struct bnx2x_fastpath *fp = &bp->fp[0];
- bnx2x_tx_int(fp);
+ for_each_cos_in_tx_queue(fp, cos)
+ bnx2x_tx_int(bp, &fp->txdata[cos]);
bnx2x_rx_int(fp, 1000);
}
@@ -3918,7 +4677,7 @@ static void bnx2x_timer(unsigned long data)
bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
/* TBD - add SYSTEM_TIME */
drv_pulse = bp->fw_drv_pulse_wr_seq;
- SHMEM_WR(bp, func_mb[mb_idx].drv_pulse_mb, drv_pulse);
+ bnx2x_drv_pulse(bp);
mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
MCP_PULSE_SEQ_MASK);
@@ -3936,7 +4695,6 @@ static void bnx2x_timer(unsigned long data)
if (bp->state == BNX2X_STATE_OPEN)
bnx2x_stats_handle(bp, STATS_EVENT_UPDATE);
-timer_restart:
mod_timer(&bp->timer, jiffies + bp->current_interval);
}
@@ -3982,18 +4740,16 @@ static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
struct hc_status_block_data_e1x sb_data_e1x;
/* disable the function first */
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
- sb_data_e2.common.p_func.pf_id = HC_FUNCTION_DISABLED;
- sb_data_e2.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sb_data_e2.common.state = SB_DISABLED;
sb_data_e2.common.p_func.vf_valid = false;
sb_data_p = (u32 *)&sb_data_e2;
data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
} else {
memset(&sb_data_e1x, 0,
sizeof(struct hc_status_block_data_e1x));
- sb_data_e1x.common.p_func.pf_id = HC_FUNCTION_DISABLED;
- sb_data_e1x.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sb_data_e1x.common.state = SB_DISABLED;
sb_data_e1x.common.p_func.vf_valid = false;
sb_data_p = (u32 *)&sb_data_e1x;
data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
@@ -4027,8 +4783,7 @@ static inline void bnx2x_zero_sp_sb(struct bnx2x *bp)
struct hc_sp_status_block_data sp_sb_data;
memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
- sp_sb_data.p_func.pf_id = HC_FUNCTION_DISABLED;
- sp_sb_data.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sp_sb_data.state = SB_DISABLED;
sp_sb_data.p_func.vf_valid = false;
bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
@@ -4071,8 +4826,9 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
bnx2x_zero_fp_sb(bp, fw_sb_id);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
+ sb_data_e2.common.state = SB_ENABLED;
sb_data_e2.common.p_func.pf_id = BP_FUNC(bp);
sb_data_e2.common.p_func.vf_id = vfid;
sb_data_e2.common.p_func.vf_valid = vf_valid;
@@ -4086,6 +4842,7 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
} else {
memset(&sb_data_e1x, 0,
sizeof(struct hc_status_block_data_e1x));
+ sb_data_e1x.common.state = SB_ENABLED;
sb_data_e1x.common.p_func.pf_id = BP_FUNC(bp);
sb_data_e1x.common.p_func.vf_id = 0xff;
sb_data_e1x.common.p_func.vf_valid = false;
@@ -4109,25 +4866,20 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
}
-static void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u16 fw_sb_id,
- u8 sb_index, u8 disable, u16 usec)
-{
- int port = BP_PORT(bp);
- u8 ticks = usec / BNX2X_BTR;
-
- storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
-
- disable = disable ? 1 : (usec ? 0 : 1);
- storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
-}
-
-static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u16 fw_sb_id,
+static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u8 fw_sb_id,
u16 tx_usec, u16 rx_usec)
{
- bnx2x_update_coalesce_sb_index(bp, fw_sb_id, U_SB_ETH_RX_CQ_INDEX,
+ bnx2x_update_coalesce_sb_index(bp, fw_sb_id, HC_INDEX_ETH_RX_CQ_CONS,
false, rx_usec);
- bnx2x_update_coalesce_sb_index(bp, fw_sb_id, C_SB_ETH_TX_CQ_INDEX,
- false, tx_usec);
+ bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
+ HC_INDEX_ETH_TX_CQ_CONS_COS0, false,
+ tx_usec);
+ bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
+ HC_INDEX_ETH_TX_CQ_CONS_COS1, false,
+ tx_usec);
+ bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
+ HC_INDEX_ETH_TX_CQ_CONS_COS2, false,
+ tx_usec);
}
static void bnx2x_init_def_sb(struct bnx2x *bp)
@@ -4168,7 +4920,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
bp->attn_group[index].sig[sindex] =
REG_RD(bp, reg_offset + sindex*0x4 + 0x10*index);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
/*
* enable5 is separate from the rest of the registers,
* and therefore the address skip is 4
@@ -4186,7 +4938,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
REG_WR(bp, reg_offset, U64_LO(section));
REG_WR(bp, reg_offset + 4, U64_HI(section));
- } else if (CHIP_IS_E2(bp)) {
+ } else if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section));
REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section));
}
@@ -4196,6 +4948,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
bnx2x_zero_sp_sb(bp);
+ sp_sb_data.state = SB_ENABLED;
sp_sb_data.host_sb_addr.lo = U64_LO(section);
sp_sb_data.host_sb_addr.hi = U64_HI(section);
sp_sb_data.igu_sb_id = igu_sp_sb_index;
@@ -4206,9 +4959,6 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
- bp->stats_pending = 0;
- bp->set_mac_pending = 0;
-
bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0);
}
@@ -4254,146 +5004,129 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
}
-void bnx2x_push_indir_table(struct bnx2x *bp)
+
+/* called with netif_addr_lock_bh() */
+void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
+ unsigned long rx_mode_flags,
+ unsigned long rx_accept_flags,
+ unsigned long tx_accept_flags,
+ unsigned long ramrod_flags)
{
- int func = BP_FUNC(bp);
- int i;
+ struct bnx2x_rx_mode_ramrod_params ramrod_param;
+ int rc;
- if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
- return;
+ memset(&ramrod_param, 0, sizeof(ramrod_param));
- for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
- REG_WR8(bp, BAR_TSTRORM_INTMEM +
- TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
- bp->fp->cl_id + bp->rx_indir_table[i]);
-}
+ /* Prepare ramrod parameters */
+ ramrod_param.cid = 0;
+ ramrod_param.cl_id = cl_id;
+ ramrod_param.rx_mode_obj = &bp->rx_mode_obj;
+ ramrod_param.func_id = BP_FUNC(bp);
-static void bnx2x_init_ind_table(struct bnx2x *bp)
-{
- int i;
+ ramrod_param.pstate = &bp->sp_state;
+ ramrod_param.state = BNX2X_FILTER_RX_MODE_PENDING;
+
+ ramrod_param.rdata = bnx2x_sp(bp, rx_mode_rdata);
+ ramrod_param.rdata_mapping = bnx2x_sp_mapping(bp, rx_mode_rdata);
+
+ set_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
+
+ ramrod_param.ramrod_flags = ramrod_flags;
+ ramrod_param.rx_mode_flags = rx_mode_flags;
- for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
- bp->rx_indir_table[i] = i % BNX2X_NUM_ETH_QUEUES(bp);
+ ramrod_param.rx_accept_flags = rx_accept_flags;
+ ramrod_param.tx_accept_flags = tx_accept_flags;
- bnx2x_push_indir_table(bp);
+ rc = bnx2x_config_rx_mode(bp, &ramrod_param);
+ if (rc < 0) {
+ BNX2X_ERR("Set rx_mode %d failed\n", bp->rx_mode);
+ return;
+ }
}
+/* called with netif_addr_lock_bh() */
void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
{
- int mode = bp->rx_mode;
- int port = BP_PORT(bp);
- u16 cl_id;
- u32 def_q_filters = 0;
+ unsigned long rx_mode_flags = 0, ramrod_flags = 0;
+ unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
- /* All but management unicast packets should pass to the host as well */
- u32 llh_mask =
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST |
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST |
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN |
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN;
-
- switch (mode) {
- case BNX2X_RX_MODE_NONE: /* no Rx */
- def_q_filters = BNX2X_ACCEPT_NONE;
#ifdef BCM_CNIC
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
- }
-#endif
- break;
+ if (!NO_FCOE(bp))
- case BNX2X_RX_MODE_NORMAL:
- def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
- BNX2X_ACCEPT_MULTICAST;
-#ifdef BCM_CNIC
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id,
- BNX2X_ACCEPT_UNICAST |
- BNX2X_ACCEPT_MULTICAST);
- }
+ /* Configure rx_mode of FCoE Queue */
+ __set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags);
#endif
- break;
- case BNX2X_RX_MODE_ALLMULTI:
- def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
- BNX2X_ACCEPT_ALL_MULTICAST;
-#ifdef BCM_CNIC
+ switch (bp->rx_mode) {
+ case BNX2X_RX_MODE_NONE:
/*
- * Prevent duplication of multicast packets by configuring FCoE
- * L2 Client to receive only matched unicast frames.
+ * 'drop all' supersedes any accept flags that may have been
+ * passed to the function.
*/
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id,
- BNX2X_ACCEPT_UNICAST);
- }
-#endif
break;
+ case BNX2X_RX_MODE_NORMAL:
+ __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_MULTICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
+ /* internal switching mode */
+ __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_MULTICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+ break;
+ case BNX2X_RX_MODE_ALLMULTI:
+ __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
+
+ /* internal switching mode */
+ __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+ break;
case BNX2X_RX_MODE_PROMISC:
- def_q_filters |= BNX2X_PROMISCUOUS_MODE;
-#ifdef BCM_CNIC
- /*
- * Prevent packets duplication by configuring DROP_ALL for FCoE
- * L2 Client.
+ /* According to deffinition of SI mode, iface in promisc mode
+ * should receive matched and unmatched (in resolution of port)
+ * unicast packets.
*/
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
- }
-#endif
- /* pass management unicast packets as well */
- llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
- break;
+ __set_bit(BNX2X_ACCEPT_UNMATCHED, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
+
+ /* internal switching mode */
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+ if (IS_MF_SI(bp))
+ __set_bit(BNX2X_ACCEPT_ALL_UNICAST, &tx_accept_flags);
+ else
+ __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
- default:
- BNX2X_ERR("BAD rx mode (%d)\n", mode);
break;
+ default:
+ BNX2X_ERR("Unknown rx_mode: %d\n", bp->rx_mode);
+ return;
}
- cl_id = BP_L_ID(bp);
- bnx2x_rxq_set_mac_filters(bp, cl_id, def_q_filters);
-
- REG_WR(bp,
- (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
- NIG_REG_LLH0_BRB1_DRV_MASK), llh_mask);
+ if (bp->rx_mode != BNX2X_RX_MODE_NONE) {
+ __set_bit(BNX2X_ACCEPT_ANY_VLAN, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ANY_VLAN, &tx_accept_flags);
+ }
- DP(NETIF_MSG_IFUP, "rx mode %d\n"
- "drop_ucast 0x%x\ndrop_mcast 0x%x\ndrop_bcast 0x%x\n"
- "accp_ucast 0x%x\naccp_mcast 0x%x\naccp_bcast 0x%x\n"
- "unmatched_ucast 0x%x\n", mode,
- bp->mac_filters.ucast_drop_all,
- bp->mac_filters.mcast_drop_all,
- bp->mac_filters.bcast_drop_all,
- bp->mac_filters.ucast_accept_all,
- bp->mac_filters.mcast_accept_all,
- bp->mac_filters.bcast_accept_all,
- bp->mac_filters.unmatched_unicast
- );
+ __set_bit(RAMROD_RX, &ramrod_flags);
+ __set_bit(RAMROD_TX, &ramrod_flags);
- storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+ bnx2x_set_q_rx_mode(bp, bp->fp->cl_id, rx_mode_flags, rx_accept_flags,
+ tx_accept_flags, ramrod_flags);
}
static void bnx2x_init_internal_common(struct bnx2x *bp)
{
int i;
- if (!CHIP_IS_E1(bp)) {
-
- /* xstorm needs to know whether to add ovlan to packets or not,
- * in switch-independent we'll write 0 to here... */
- REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- }
-
if (IS_MF_SI(bp))
/*
* In switch independent mode, the TSTORM needs to accept
@@ -4402,25 +5135,22 @@ static void bnx2x_init_internal_common(struct bnx2x *bp)
*/
REG_WR8(bp, BAR_TSTRORM_INTMEM +
TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2);
+ else if (!CHIP_IS_E1(bp)) /* 57710 doesn't support MF */
+ REG_WR8(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 0);
/* Zero this manually as its initialization is
currently missing in the initTool */
for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_AGG_DATA_OFFSET + i * 4, 0);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET,
CHIP_INT_MODE_IS_BC(bp) ?
HC_IGU_BC_MODE : HC_IGU_NBC_MODE);
}
}
-static void bnx2x_init_internal_port(struct bnx2x *bp)
-{
- /* port */
- bnx2x_dcb_init_intmem_pfc(bp);
-}
-
static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
{
switch (load_code) {
@@ -4430,7 +5160,7 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
/* no break */
case FW_MSG_CODE_DRV_LOAD_PORT:
- bnx2x_init_internal_port(bp);
+ /* nothing to do */
/* no break */
case FW_MSG_CODE_DRV_LOAD_FUNCTION:
@@ -4444,31 +5174,70 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
}
}
-static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx)
+static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp)
{
- struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
+ return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT;
+}
- fp->state = BNX2X_FP_STATE_CLOSED;
+static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
+{
+ return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT;
+}
+
+static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
+{
+ if (CHIP_IS_E1x(fp->bp))
+ return BP_L_ID(fp->bp) + fp->index;
+ else /* We want Client ID to be the same as IGU SB ID for 57712 */
+ return bnx2x_fp_igu_sb_id(fp);
+}
+
+static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx)
+{
+ struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
+ u8 cos;
+ unsigned long q_type = 0;
+ u32 cids[BNX2X_MULTI_TX_COS] = { 0 };
fp->cid = fp_idx;
- fp->cl_id = BP_L_ID(bp) + fp_idx;
- fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE;
- fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE;
+ fp->cl_id = bnx2x_fp_cl_id(fp);
+ fp->fw_sb_id = bnx2x_fp_fw_sb_id(fp);
+ fp->igu_sb_id = bnx2x_fp_igu_sb_id(fp);
/* qZone id equals to FW (per path) client id */
- fp->cl_qzone_id = fp->cl_id +
- BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
- ETH_MAX_RX_CLIENTS_E1H);
+ fp->cl_qzone_id = bnx2x_fp_qzone_id(fp);
+
/* init shortcut */
- fp->ustorm_rx_prods_offset = CHIP_IS_E2(bp) ?
- USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id) :
- USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+ fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp);
/* Setup SB indicies */
fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
- fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
+
+ /* Configure Queue State object */
+ __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
+ __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
+
+ BUG_ON(fp->max_cos > BNX2X_MULTI_TX_COS);
+
+ /* init tx data */
+ for_each_cos_in_tx_queue(fp, cos) {
+ bnx2x_init_txdata(bp, &fp->txdata[cos],
+ CID_COS_TO_TX_ONLY_CID(fp->cid, cos),
+ FP_COS_TO_TXQ(fp, cos),
+ BNX2X_TX_SB_INDEX_BASE + cos);
+ cids[cos] = fp->txdata[cos].cid;
+ }
+
+ bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, cids, fp->max_cos,
+ BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
+ bnx2x_sp_mapping(bp, q_rdata), q_type);
+
+ /**
+ * Configure classification DBs: Always enable Tx switching
+ */
+ bnx2x_init_vlan_mac_fp_objs(fp, BNX2X_OBJ_TYPE_RX_TX);
DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) "
"cl_id %d fw_sb %d igu_sb %d\n",
- fp_idx, bp, fp->status_blk.e1x_sb, fp->cl_id, fp->fw_sb_id,
+ fp_idx, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
fp->igu_sb_id);
bnx2x_init_sb(bp, fp->status_blk_mapping, BNX2X_VF_ID_INVALID, false,
fp->fw_sb_id, fp->igu_sb_id);
@@ -4481,17 +5250,21 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
int i;
for_each_eth_queue(bp, i)
- bnx2x_init_fp_sb(bp, i);
+ bnx2x_init_eth_fp(bp, i);
#ifdef BCM_CNIC
if (!NO_FCOE(bp))
bnx2x_init_fcoe_fp(bp);
bnx2x_init_sb(bp, bp->cnic_sb_mapping,
BNX2X_VF_ID_INVALID, false,
- CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp));
+ bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp));
#endif
+ /* Initialize MOD_ABS interrupts */
+ bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
+ bp->common.shmem_base, bp->common.shmem2_base,
+ BP_PORT(bp));
/* ensure status block indices were read */
rmb();
@@ -4503,12 +5276,8 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
bnx2x_init_eq_ring(bp);
bnx2x_init_internal(bp, load_code);
bnx2x_pf_init(bp);
- bnx2x_init_ind_table(bp);
bnx2x_stats_init(bp);
- /* At this point, we are ready for interrupts */
- atomic_set(&bp->intr_sem, 0);
-
/* flush all before enabling interrupts */
mb();
mmiowb();
@@ -4711,8 +5480,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
msleep(50);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
msleep(50);
- bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
DP(NETIF_MSG_HW, "part2\n");
@@ -4776,8 +5545,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
msleep(50);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
msleep(50);
- bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
#ifndef BCM_CNIC
/* set NIC mode */
REG_WR(bp, PRS_REG_NIC_MODE, 1);
@@ -4797,7 +5566,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
{
REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
else
REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
@@ -4831,7 +5600,7 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
if (CHIP_REV_IS_FPGA(bp))
REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
- else if (CHIP_IS_E2(bp))
+ else if (!CHIP_IS_E1x(bp))
REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
(PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
| PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
@@ -4844,7 +5613,11 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0);
REG_WR(bp, TCM_REG_TCM_INT_MASK, 0);
/* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */
-/* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0); */
+
+ if (!CHIP_IS_E1x(bp))
+ /* enable VFC attentions: bits 11 and 12, bits 31:13 reserved */
+ REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0x07ff);
+
REG_WR(bp, CDU_REG_CDU_INT_MASK, 0);
REG_WR(bp, DMAE_REG_DMAE_INT_MASK, 0);
/* REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
@@ -4853,10 +5626,24 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
static void bnx2x_reset_common(struct bnx2x *bp)
{
+ u32 val = 0x1400;
+
/* reset_common */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
0xd3ffff7f);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
+
+ if (CHIP_IS_E3(bp)) {
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+ }
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, val);
+}
+
+static void bnx2x_setup_dmae(struct bnx2x *bp)
+{
+ bp->dmae_ready = 0;
+ spin_lock_init(&bp->dmae_lock);
}
static void bnx2x_init_pxp(struct bnx2x *bp)
@@ -4865,7 +5652,7 @@ static void bnx2x_init_pxp(struct bnx2x *bp)
int r_order, w_order;
pci_read_config_word(bp->pdev,
- bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
+ pci_pcie_cap(bp->pdev) + PCI_EXP_DEVCTL, &devctl);
DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
if (bp->mrrs == -1)
@@ -4973,7 +5760,7 @@ static void bnx2x_pretend_func(struct bnx2x *bp, u8 pretend_func_num)
DP(NETIF_MSG_HW, "Pretending to func %d\n", pretend_func_num);
}
-static void bnx2x_pf_disable(struct bnx2x *bp)
+void bnx2x_pf_disable(struct bnx2x *bp)
{
u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
val &= ~IGU_PF_CONF_FUNC_EN;
@@ -4983,22 +5770,48 @@ static void bnx2x_pf_disable(struct bnx2x *bp)
REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0);
}
-static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
+static inline void bnx2x__common_init_phy(struct bnx2x *bp)
+{
+ u32 shmem_base[2], shmem2_base[2];
+ shmem_base[0] = bp->common.shmem_base;
+ shmem2_base[0] = bp->common.shmem2_base;
+ if (!CHIP_IS_E1x(bp)) {
+ shmem_base[1] =
+ SHMEM2_RD(bp, other_shmem_base_addr);
+ shmem2_base[1] =
+ SHMEM2_RD(bp, other_shmem2_base_addr);
+ }
+ bnx2x_acquire_phy_lock(bp);
+ bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
+ bp->common.chip_id);
+ bnx2x_release_phy_lock(bp);
+}
+
+/**
+ * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
+ *
+ * @bp: driver handle
+ */
+static int bnx2x_init_hw_common(struct bnx2x *bp)
{
- u32 val, i;
+ u32 val;
DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_ABS_FUNC(bp));
bnx2x_reset_common(bp);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
- bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE);
- if (!CHIP_IS_E1(bp))
- REG_WR(bp, MISC_REG_E1HMF_MODE, IS_MF(bp));
+ val = 0xfffc;
+ if (CHIP_IS_E3(bp)) {
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+ }
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val);
+
+ bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON);
- if (CHIP_IS_E2(bp)) {
- u8 fid;
+ if (!CHIP_IS_E1x(bp)) {
+ u8 abs_func_id;
/**
* 4-port mode or 2-port mode we need to turn of master-enable
@@ -5007,29 +5820,30 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
* for all functions on the given path, this means 0,2,4,6 for
* path 0 and 1,3,5,7 for path 1
*/
- for (fid = BP_PATH(bp); fid < E2_FUNC_MAX*2; fid += 2) {
- if (fid == BP_ABS_FUNC(bp)) {
+ for (abs_func_id = BP_PATH(bp);
+ abs_func_id < E2_FUNC_MAX*2; abs_func_id += 2) {
+ if (abs_func_id == BP_ABS_FUNC(bp)) {
REG_WR(bp,
PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER,
1);
continue;
}
- bnx2x_pretend_func(bp, fid);
+ bnx2x_pretend_func(bp, abs_func_id);
/* clear pf enable */
bnx2x_pf_disable(bp);
bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
}
}
- bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PXP, PHASE_COMMON);
if (CHIP_IS_E1(bp)) {
/* enable HW interrupt from PXP on USDM overflow
bit 16 on INT_MASK_0 */
REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
}
- bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
bnx2x_init_pxp(bp);
#ifdef __BIG_ENDIAN
@@ -5072,7 +5886,69 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
* This needs to be done by the first PF that is loaded in a path
* (i.e. common phase)
*/
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
+/* In E2 there is a bug in the timers block that can cause function 6 / 7
+ * (i.e. vnic3) to start even if it is marked as "scan-off".
+ * This occurs when a different function (func2,3) is being marked
+ * as "scan-off". Real-life scenario for example: if a driver is being
+ * load-unloaded while func6,7 are down. This will cause the timer to access
+ * the ilt, translate to a logical address and send a request to read/write.
+ * Since the ilt for the function that is down is not valid, this will cause
+ * a translation error which is unrecoverable.
+ * The Workaround is intended to make sure that when this happens nothing fatal
+ * will occur. The workaround:
+ * 1. First PF driver which loads on a path will:
+ * a. After taking the chip out of reset, by using pretend,
+ * it will write "0" to the following registers of
+ * the other vnics.
+ * REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
+ * REG_WR(pdev, CFC_REG_WEAK_ENABLE_PF,0);
+ * REG_WR(pdev, CFC_REG_STRONG_ENABLE_PF,0);
+ * And for itself it will write '1' to
+ * PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER to enable
+ * dmae-operations (writing to pram for example.)
+ * note: can be done for only function 6,7 but cleaner this
+ * way.
+ * b. Write zero+valid to the entire ILT.
+ * c. Init the first_timers_ilt_entry, last_timers_ilt_entry of
+ * VNIC3 (of that port). The range allocated will be the
+ * entire ILT. This is needed to prevent ILT range error.
+ * 2. Any PF driver load flow:
+ * a. ILT update with the physical addresses of the allocated
+ * logical pages.
+ * b. Wait 20msec. - note that this timeout is needed to make
+ * sure there are no requests in one of the PXP internal
+ * queues with "old" ILT addresses.
+ * c. PF enable in the PGLC.
+ * d. Clear the was_error of the PF in the PGLC. (could have
+ * occured while driver was down)
+ * e. PF enable in the CFC (WEAK + STRONG)
+ * f. Timers scan enable
+ * 3. PF driver unload flow:
+ * a. Clear the Timers scan_en.
+ * b. Polling for scan_on=0 for that PF.
+ * c. Clear the PF enable bit in the PXP.
+ * d. Clear the PF enable in the CFC (WEAK + STRONG)
+ * e. Write zero+valid to all ILT entries (The valid bit must
+ * stay set)
+ * f. If this is VNIC 3 of a port then also init
+ * first_timers_ilt_entry to zero and last_timers_ilt_entry
+ * to the last enrty in the ILT.
+ *
+ * Notes:
+ * Currently the PF error in the PGLC is non recoverable.
+ * In the future the there will be a recovery routine for this error.
+ * Currently attention is masked.
+ * Having an MCP lock on the load/unload process does not guarantee that
+ * there is no Timer disable during Func6/7 enable. This is because the
+ * Timers scan is currently being cleared by the MCP on FLR.
+ * Step 2.d can be done only for PF6/7 and the driver can also check if
+ * there is error before clearing it. But the flow above is simpler and
+ * more general.
+ * All ILT entries are written by zero+valid and not just PF6/7
+ * ILT entries since in the future the ILT entries allocation for
+ * PF-s might be dynamic.
+ */
struct ilt_client_info ilt_cli;
struct bnx2x_ilt ilt;
memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
@@ -5086,7 +5962,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
/* Step 1: set zeroes to all ilt page entries with valid bit on
* Step 2: set the timers first/last ilt entry to point
* to the entire range to prevent ILT range error for 3rd/4th
- * vnic (this code assumes existence of the vnic)
+ * vnic (this code assumes existance of the vnic)
*
* both steps performed by call to bnx2x_ilt_client_init_op()
* with dummy TM client
@@ -5107,12 +5983,12 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
int factor = CHIP_REV_IS_EMUL(bp) ? 1000 :
(CHIP_REV_IS_FPGA(bp) ? 400 : 0);
- bnx2x_init_block(bp, PGLUE_B_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PGLUE_B, PHASE_COMMON);
- bnx2x_init_block(bp, ATC_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_ATC, PHASE_COMMON);
/* let the HW do it's magic ... */
do {
@@ -5126,26 +6002,27 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
}
}
- bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_DMAE, PHASE_COMMON);
/* clean the DMAE memory */
bp->dmae_ready = 1;
- bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
+ bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8, 1);
+
+ bnx2x_init_block(bp, BLOCK_TCM, PHASE_COMMON);
- bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_UCM, PHASE_COMMON);
+
+ bnx2x_init_block(bp, BLOCK_CCM, PHASE_COMMON);
+
+ bnx2x_init_block(bp, BLOCK_XCM, PHASE_COMMON);
bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
- bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_QM, PHASE_COMMON);
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, QM_4PORT_BLOCK, COMMON_STAGE);
/* QM queues pointers table */
bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET);
@@ -5155,57 +6032,51 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
REG_WR(bp, QM_REG_SOFT_RESET, 0);
#ifdef BCM_CNIC
- bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
#endif
- bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
-
- if (!CHIP_REV_IS_SLOW(bp)) {
+ if (!CHIP_REV_IS_SLOW(bp))
/* enable hw interrupt from doorbell Q */
REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
- }
- bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
- if (CHIP_MODE_IS_4_PORT(bp)) {
- REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD, 248);
- REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD, 328);
- }
+ bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
- bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
-#ifndef BCM_CNIC
- /* set NIC mode */
- REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
+
if (!CHIP_IS_E1(bp))
- REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF_SD(bp));
+ REG_WR(bp, PRS_REG_E1HOV_MODE, bp->path_has_ovlan);
- if (CHIP_IS_E2(bp)) {
- /* Bit-map indicating which L2 hdrs may appear after the
- basic Ethernet header */
- int has_ovlan = IS_MF_SD(bp);
- REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
- REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
- }
+ if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3B0(bp))
+ /* Bit-map indicating which L2 hdrs may appear
+ * after the basic Ethernet header
+ */
+ REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC,
+ bp->path_has_ovlan ? 7 : 6);
- bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_TSDM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_CSDM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_USDM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_XSDM, PHASE_COMMON);
- bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, USEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
+ if (!CHIP_IS_E1x(bp)) {
+ /* reset VFC memories */
+ REG_WR(bp, TSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
+ VFC_MEMORIES_RST_REG_CAM_RST |
+ VFC_MEMORIES_RST_REG_RAM_RST);
+ REG_WR(bp, XSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
+ VFC_MEMORIES_RST_REG_CAM_RST |
+ VFC_MEMORIES_RST_REG_RAM_RST);
- bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE);
+ msleep(20);
+ }
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, XSEM_4PORT_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_TSEM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_USEM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_CSEM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_XSEM, PHASE_COMMON);
/* sync semi rtc */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
@@ -5213,21 +6084,18 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
0x80000000);
- bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_UPB, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_XPB, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_PBF, PHASE_COMMON);
- if (CHIP_IS_E2(bp)) {
- int has_ovlan = IS_MF_SD(bp);
- REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
- REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
- }
+ if (!CHIP_IS_E1x(bp))
+ REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC,
+ bp->path_has_ovlan ? 7 : 6);
REG_WR(bp, SRC_REG_SOFT_RST, 1);
- for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4)
- REG_WR(bp, i, random32());
- bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON);
+
#ifdef BCM_CNIC
REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
@@ -5248,11 +6116,11 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
"of cdu_context(%ld)\n",
(long)sizeof(union cdu_context));
- bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_CDU, PHASE_COMMON);
val = (4 << 24) + (0 << 12) + 1024;
REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
- bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_CFC, PHASE_COMMON);
REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
/* enable context validation interrupt from CFC */
REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
@@ -5260,20 +6128,19 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
/* set the thresholds to prevent CFC/CDU race */
REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
- bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_HC, PHASE_COMMON);
- if (CHIP_IS_E2(bp) && BP_NOMCP(bp))
+ if (!CHIP_IS_E1x(bp) && BP_NOMCP(bp))
REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x36);
- bnx2x_init_block(bp, IGU_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_IGU, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_MISC_AEU, PHASE_COMMON);
- bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
/* Reset PCIE errors for debug */
REG_WR(bp, 0x2814, 0xffffffff);
REG_WR(bp, 0x3820, 0xffffffff);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_CONTROL_5,
(PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 |
PXPCS_TL_CONTROL_5_ERR_UNSPPORT));
@@ -5287,21 +6154,15 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5));
}
- bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
-
- bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_NIG, PHASE_COMMON);
if (!CHIP_IS_E1(bp)) {
- REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
- REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp));
- }
- if (CHIP_IS_E2(bp)) {
- /* Bit-map indicating which L2 hdrs may appear after the
- basic Ethernet header */
- REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF_SD(bp) ? 7 : 6));
+ /* in E3 this done in per-port section */
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
}
+ if (CHIP_IS_E1H(bp))
+ /* not applicable for E2 (and above ...) */
+ REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp));
if (CHIP_REV_IS_SLOW(bp))
msleep(200);
@@ -5343,127 +6204,136 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
bnx2x_enable_blocks_attention(bp);
- if (CHIP_PARITY_ENABLED(bp))
- bnx2x_enable_blocks_parity(bp);
+ bnx2x_enable_blocks_parity(bp);
if (!BP_NOMCP(bp)) {
- /* In E2 2-PORT mode, same ext phy is used for the two paths */
- if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
- CHIP_IS_E1x(bp)) {
- u32 shmem_base[2], shmem2_base[2];
- shmem_base[0] = bp->common.shmem_base;
- shmem2_base[0] = bp->common.shmem2_base;
- if (CHIP_IS_E2(bp)) {
- shmem_base[1] =
- SHMEM2_RD(bp, other_shmem_base_addr);
- shmem2_base[1] =
- SHMEM2_RD(bp, other_shmem2_base_addr);
- }
- bnx2x_acquire_phy_lock(bp);
- bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
- bp->common.chip_id);
- bnx2x_release_phy_lock(bp);
- }
+ if (CHIP_IS_E1x(bp))
+ bnx2x__common_init_phy(bp);
} else
BNX2X_ERR("Bootcode is missing - can not initialize link\n");
return 0;
}
+/**
+ * bnx2x_init_hw_common_chip - init HW at the COMMON_CHIP phase.
+ *
+ * @bp: driver handle
+ */
+static int bnx2x_init_hw_common_chip(struct bnx2x *bp)
+{
+ int rc = bnx2x_init_hw_common(bp);
+
+ if (rc)
+ return rc;
+
+ /* In E2 2-PORT mode, same ext phy is used for the two paths */
+ if (!BP_NOMCP(bp))
+ bnx2x__common_init_phy(bp);
+
+ return 0;
+}
+
static int bnx2x_init_hw_port(struct bnx2x *bp)
{
int port = BP_PORT(bp);
- int init_stage = port ? PORT1_STAGE : PORT0_STAGE;
+ int init_phase = port ? PHASE_PORT1 : PHASE_PORT0;
u32 low, high;
u32 val;
+ bnx2x__link_reset(bp);
+
DP(BNX2X_MSG_MCP, "starting port init port %d\n", port);
REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
- bnx2x_init_block(bp, PXP_BLOCK, init_stage);
- bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_MISC, init_phase);
+ bnx2x_init_block(bp, BLOCK_PXP, init_phase);
+ bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
/* Timers bug workaround: disables the pf_master bit in pglue at
* common phase, we need to enable it here before any dmae access are
* attempted. Therefore we manually added the enable-master to the
* port phase (it also happens in the function phase)
*/
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
- bnx2x_init_block(bp, TCM_BLOCK, init_stage);
- bnx2x_init_block(bp, UCM_BLOCK, init_stage);
- bnx2x_init_block(bp, CCM_BLOCK, init_stage);
- bnx2x_init_block(bp, XCM_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_ATC, init_phase);
+ bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
+ bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
+ bnx2x_init_block(bp, BLOCK_QM, init_phase);
+
+ bnx2x_init_block(bp, BLOCK_TCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_UCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XCM, init_phase);
/* QM cid (connection) count */
bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
#ifdef BCM_CNIC
- bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_TM, init_phase);
REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
#endif
- bnx2x_init_block(bp, DQ_BLOCK, init_stage);
-
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, QM_4PORT_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
- bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
- if (CHIP_REV_IS_SLOW(bp) && CHIP_IS_E1(bp)) {
- /* no pause for emulation and FPGA */
- low = 0;
- high = 513;
- } else {
- if (IS_MF(bp))
- low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
- else if (bp->dev->mtu > 4096) {
- if (bp->flags & ONE_PORT_FLAG)
- low = 160;
- else {
- val = bp->dev->mtu;
- /* (24*1024 + val*4)/256 */
- low = 96 + (val/64) +
- ((val % 64) ? 1 : 0);
- }
- } else
- low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
- high = low + 56; /* 14*1024/256 */
- }
+ bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
+ if (IS_MF(bp))
+ low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
+ else if (bp->dev->mtu > 4096) {
+ if (bp->flags & ONE_PORT_FLAG)
+ low = 160;
+ else {
+ val = bp->dev->mtu;
+ /* (24*1024 + val*4)/256 */
+ low = 96 + (val/64) +
+ ((val % 64) ? 1 : 0);
+ }
+ } else
+ low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
+ high = low + 56; /* 14*1024/256 */
REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
}
- if (CHIP_MODE_IS_4_PORT(bp)) {
- REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 + port*8, 248);
- REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 + port*8, 328);
- REG_WR(bp, (BP_PORT(bp) ? BRB1_REG_MAC_GUARANTIED_1 :
- BRB1_REG_MAC_GUARANTIED_0), 40);
- }
+ if (CHIP_MODE_IS_4_PORT(bp))
+ REG_WR(bp, (BP_PORT(bp) ?
+ BRB1_REG_MAC_GUARANTIED_1 :
+ BRB1_REG_MAC_GUARANTIED_0), 40);
- bnx2x_init_block(bp, PRS_BLOCK, init_stage);
- bnx2x_init_block(bp, TSDM_BLOCK, init_stage);
- bnx2x_init_block(bp, CSDM_BLOCK, init_stage);
- bnx2x_init_block(bp, USDM_BLOCK, init_stage);
- bnx2x_init_block(bp, XSDM_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_PRS, init_phase);
+ if (CHIP_IS_E3B0(bp))
+ /* Ovlan exists only if we are in multi-function +
+ * switch-dependent mode, in switch-independent there
+ * is no ovlan headers
+ */
+ REG_WR(bp, BP_PORT(bp) ?
+ PRS_REG_HDRS_AFTER_BASIC_PORT_1 :
+ PRS_REG_HDRS_AFTER_BASIC_PORT_0,
+ (bp->path_has_ovlan ? 7 : 6));
- bnx2x_init_block(bp, TSEM_BLOCK, init_stage);
- bnx2x_init_block(bp, USEM_BLOCK, init_stage);
- bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
- bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, XSEM_4PORT_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
- bnx2x_init_block(bp, UPB_BLOCK, init_stage);
- bnx2x_init_block(bp, XPB_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
- bnx2x_init_block(bp, PBF_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_UPB, init_phase);
+ bnx2x_init_block(bp, BLOCK_XPB, init_phase);
- if (!CHIP_IS_E2(bp)) {
+ bnx2x_init_block(bp, BLOCK_PBF, init_phase);
+
+ if (CHIP_IS_E1x(bp)) {
/* configure PBF to work without PAUSE mtu 9000 */
REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
@@ -5479,20 +6349,20 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
}
#ifdef BCM_CNIC
- bnx2x_init_block(bp, SRCH_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_SRC, init_phase);
#endif
- bnx2x_init_block(bp, CDU_BLOCK, init_stage);
- bnx2x_init_block(bp, CFC_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_CDU, init_phase);
+ bnx2x_init_block(bp, BLOCK_CFC, init_phase);
if (CHIP_IS_E1(bp)) {
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
}
- bnx2x_init_block(bp, HC_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_HC, init_phase);
- bnx2x_init_block(bp, IGU_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_IGU, init_phase);
- bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
/* init aeu_mask_attn_func_0/1:
* - SF mode: bits 3-7 are masked. only bits 0-2 are in use
* - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
@@ -5502,22 +6372,31 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
val |= CHIP_IS_E1(bp) ? 0 : 0x10;
REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val);
- bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
- bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
- bnx2x_init_block(bp, EMAC1_BLOCK, init_stage);
- bnx2x_init_block(bp, DBU_BLOCK, init_stage);
- bnx2x_init_block(bp, DBG_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_NIG, init_phase);
- bnx2x_init_block(bp, NIG_BLOCK, init_stage);
+ if (!CHIP_IS_E1x(bp)) {
+ /* Bit-map indicating which L2 hdrs may appear after the
+ * basic Ethernet header
+ */
+ REG_WR(bp, BP_PORT(bp) ?
+ NIG_REG_P1_HDRS_AFTER_BASIC :
+ NIG_REG_P0_HDRS_AFTER_BASIC,
+ IS_MF_SD(bp) ? 7 : 6);
- REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
+ if (CHIP_IS_E3(bp))
+ REG_WR(bp, BP_PORT(bp) ?
+ NIG_REG_LLH1_MF_MODE :
+ NIG_REG_LLH_MF_MODE, IS_MF(bp));
+ }
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
if (!CHIP_IS_E1(bp)) {
/* 0x2 disable mf_ov, 0x1 enable */
REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
(IS_MF_SD(bp) ? 0x1 : 0x2));
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
val = 0;
switch (bp->mf_mode) {
case MULTI_FUNCTION_SD:
@@ -5538,17 +6417,16 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
}
}
- bnx2x_init_block(bp, MCP_BLOCK, init_stage);
- bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
- if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
- bp->common.shmem2_base, port)) {
+
+ /* If SPIO5 is set to generate interrupts, enable it for this port */
+ val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
+ if (val & (1 << MISC_REGISTERS_SPIO_5)) {
u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
val = REG_RD(bp, reg_addr);
val |= AEU_INPUTS_ATTN_BITS_SPIO5;
REG_WR(bp, reg_addr, val);
}
- bnx2x__link_reset(bp);
return 0;
}
@@ -5567,7 +6445,7 @@ static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
{
- bnx2x_igu_clear_sb_gen(bp, idu_sb_id, true /*PF*/);
+ bnx2x_igu_clear_sb_gen(bp, BP_FUNC(bp), idu_sb_id, true /*PF*/);
}
static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
@@ -5581,6 +6459,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
{
int port = BP_PORT(bp);
int func = BP_FUNC(bp);
+ int init_phase = PHASE_PF0 + func;
struct bnx2x_ilt *ilt = BP_ILT(bp);
u16 cdu_ilt_start;
u32 addr, val;
@@ -5589,6 +6468,10 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
DP(BNX2X_MSG_MCP, "starting func init func %d\n", func);
+ /* FLR cleanup - hmmm */
+ if (!CHIP_IS_E1x(bp))
+ bnx2x_pf_flr_clnup(bp);
+
/* set MSI reconfigure capability */
if (bp->common.int_block == INT_BLOCK_HC) {
addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
@@ -5597,6 +6480,9 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
REG_WR(bp, addr, val);
}
+ bnx2x_init_block(bp, BLOCK_PXP, init_phase);
+ bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
+
ilt = BP_ILT(bp);
cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start;
@@ -5622,7 +6508,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
REG_WR(bp, PRS_REG_NIC_MODE, 1);
#endif /* BCM_CNIC */
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
u32 pf_conf = IGU_PF_CONF_FUNC_EN;
/* Turn on a single ISR mode in IGU if driver is going to use
@@ -5649,58 +6535,55 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
bp->dmae_ready = 1;
- bnx2x_init_block(bp, PGLUE_B_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func);
- bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
-
- if (CHIP_IS_E2(bp)) {
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_PATH_ID_OFFSET,
- BP_PATH(bp));
- REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_PATH_ID_OFFSET,
- BP_PATH(bp));
- }
-
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, XSEM_4PORT_BLOCK, FUNC0_STAGE + func);
-
- if (CHIP_IS_E2(bp))
+ bnx2x_init_block(bp, BLOCK_ATC, init_phase);
+ bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
+ bnx2x_init_block(bp, BLOCK_NIG, init_phase);
+ bnx2x_init_block(bp, BLOCK_SRC, init_phase);
+ bnx2x_init_block(bp, BLOCK_MISC, init_phase);
+ bnx2x_init_block(bp, BLOCK_TCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_UCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
+
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, QM_REG_PF_EN, 1);
- bnx2x_init_block(bp, QM_BLOCK, FUNC0_STAGE + func);
-
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, QM_4PORT_BLOCK, FUNC0_STAGE + func);
-
- bnx2x_init_block(bp, TIMERS_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DQ_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, BRB1_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, PRS_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TSDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CSDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, USDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XSDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, UPB_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XPB_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, PBF_BLOCK, FUNC0_STAGE + func);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp)) {
+ REG_WR(bp, TSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ REG_WR(bp, USEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ REG_WR(bp, CSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ REG_WR(bp, XSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ }
+ bnx2x_init_block(bp, BLOCK_QM, init_phase);
+
+ bnx2x_init_block(bp, BLOCK_TM, init_phase);
+ bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
+ bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+ bnx2x_init_block(bp, BLOCK_PRS, init_phase);
+ bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_UPB, init_phase);
+ bnx2x_init_block(bp, BLOCK_XPB, init_phase);
+ bnx2x_init_block(bp, BLOCK_PBF, init_phase);
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PBF_REG_DISABLE_PF, 0);
- bnx2x_init_block(bp, CDU_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_CDU, init_phase);
- bnx2x_init_block(bp, CFC_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_CFC, init_phase);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 1);
if (IS_MF(bp)) {
@@ -5708,7 +6591,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->mf_ov);
}
- bnx2x_init_block(bp, MISC_AEU_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
/* HC init per function */
if (bp->common.int_block == INT_BLOCK_HC) {
@@ -5718,21 +6601,21 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
}
- bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_HC, init_phase);
} else {
int num_segs, sb_idx, prod_offset;
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
}
- bnx2x_init_block(bp, IGU_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_IGU, init_phase);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
int dsb_idx = 0;
/**
* Producer memory:
@@ -5827,13 +6710,6 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
REG_WR(bp, 0x2114, 0xffffffff);
REG_WR(bp, 0x2120, 0xffffffff);
- bnx2x_init_block(bp, EMAC0_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, EMAC1_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DBU_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DBG_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, MCP_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DMAE_BLOCK, FUNC0_STAGE + func);
-
if (CHIP_IS_E1x(bp)) {
main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/
main_mem_base = HC_REG_MAIN_MEMORY +
@@ -5859,65 +6735,26 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
REG_RD(bp, main_mem_prty_clr);
}
+#ifdef BNX2X_STOP_ON_ERROR
+ /* Enable STORMs SP logging */
+ REG_WR8(bp, BAR_USTRORM_INTMEM +
+ USTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+ REG_WR8(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+ REG_WR8(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+#endif
+
bnx2x_phy_probe(&bp->link_params);
return 0;
}
-int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
-{
- int rc = 0;
-
- DP(BNX2X_MSG_MCP, "function %d load_code %x\n",
- BP_ABS_FUNC(bp), load_code);
-
- bp->dmae_ready = 0;
- spin_lock_init(&bp->dmae_lock);
-
- switch (load_code) {
- case FW_MSG_CODE_DRV_LOAD_COMMON:
- case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
- rc = bnx2x_init_hw_common(bp, load_code);
- if (rc)
- goto init_hw_err;
- /* no break */
-
- case FW_MSG_CODE_DRV_LOAD_PORT:
- rc = bnx2x_init_hw_port(bp);
- if (rc)
- goto init_hw_err;
- /* no break */
-
- case FW_MSG_CODE_DRV_LOAD_FUNCTION:
- rc = bnx2x_init_hw_func(bp);
- if (rc)
- goto init_hw_err;
- break;
-
- default:
- BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
- break;
- }
-
- if (!BP_NOMCP(bp)) {
- int mb_idx = BP_FW_MB_IDX(bp);
-
- bp->fw_drv_pulse_wr_seq =
- (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
- DRV_PULSE_SEQ_MASK);
- DP(BNX2X_MSG_MCP, "drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
- }
-
-init_hw_err:
- bnx2x_gunzip_end(bp);
-
- return rc;
-}
void bnx2x_free_mem(struct bnx2x *bp)
{
- bnx2x_gunzip_end(bp);
-
/* fastpath */
bnx2x_free_fp_mem(bp);
/* end of fastpath */
@@ -5925,6 +6762,9 @@ void bnx2x_free_mem(struct bnx2x *bp)
BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
sizeof(struct host_sp_status_block));
+ BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
+ bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+
BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
sizeof(struct bnx2x_slowpath));
@@ -5936,7 +6776,7 @@ void bnx2x_free_mem(struct bnx2x *bp)
BNX2X_FREE(bp->ilt->lines);
#ifdef BCM_CNIC
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
sizeof(struct host_hc_status_block_e2));
else
@@ -5950,18 +6790,67 @@ void bnx2x_free_mem(struct bnx2x *bp)
BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
BCM_PAGE_SIZE * NUM_EQ_PAGES);
+}
+
+static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
+{
+ int num_groups;
+
+ /* number of eth_queues */
+ u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp);
+
+ /* Total number of FW statistics requests =
+ * 1 for port stats + 1 for PF stats + num_eth_queues */
+ bp->fw_stats_num = 2 + num_queue_stats;
+
- BNX2X_FREE(bp->rx_indir_table);
+ /* Request is built from stats_query_header and an array of
+ * stats_query_cmd_group each of which contains
+ * STATS_QUERY_CMD_COUNT rules. The real number or requests is
+ * configured in the stats_query_header.
+ */
+ num_groups = (2 + num_queue_stats) / STATS_QUERY_CMD_COUNT +
+ (((2 + num_queue_stats) % STATS_QUERY_CMD_COUNT) ? 1 : 0);
+
+ bp->fw_stats_req_sz = sizeof(struct stats_query_header) +
+ num_groups * sizeof(struct stats_query_cmd_group);
+
+ /* Data for statistics requests + stats_conter
+ *
+ * stats_counter holds per-STORM counters that are incremented
+ * when STORM has finished with the current request.
+ */
+ bp->fw_stats_data_sz = sizeof(struct per_port_stats) +
+ sizeof(struct per_pf_stats) +
+ sizeof(struct per_queue_stats) * num_queue_stats +
+ sizeof(struct stats_counter);
+
+ BNX2X_PCI_ALLOC(bp->fw_stats, &bp->fw_stats_mapping,
+ bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+
+ /* Set shortcuts */
+ bp->fw_stats_req = (struct bnx2x_fw_stats_req *)bp->fw_stats;
+ bp->fw_stats_req_mapping = bp->fw_stats_mapping;
+
+ bp->fw_stats_data = (struct bnx2x_fw_stats_data *)
+ ((u8 *)bp->fw_stats + bp->fw_stats_req_sz);
+
+ bp->fw_stats_data_mapping = bp->fw_stats_mapping +
+ bp->fw_stats_req_sz;
+ return 0;
+
+alloc_mem_err:
+ BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
+ bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+ return -ENOMEM;
}
int bnx2x_alloc_mem(struct bnx2x *bp)
{
- if (bnx2x_gunzip_init(bp))
- return -ENOMEM;
-
#ifdef BCM_CNIC
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
+ /* size = the status block + ramrod buffers */
BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
sizeof(struct host_hc_status_block_e2));
else
@@ -5979,7 +6868,11 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
sizeof(struct bnx2x_slowpath));
- bp->context.size = sizeof(union cdu_context) * bp->l2_cid_count;
+ /* Allocated memory for FW statistics */
+ if (bnx2x_alloc_fw_stats_mem(bp))
+ goto alloc_mem_err;
+
+ bp->context.size = sizeof(union cdu_context) * BNX2X_L2_CID_COUNT(bp);
BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping,
bp->context.size);
@@ -5996,8 +6889,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
BCM_PAGE_SIZE * NUM_EQ_PAGES);
- BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) *
- TSTORM_INDIRECTION_TABLE_SIZE);
/* fastpath */
/* need to be done at the end, since it's self adjusting to amount
@@ -6015,629 +6906,75 @@ alloc_mem_err:
/*
* Init service functions
*/
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
- int *state_p, int flags);
-
-int bnx2x_func_start(struct bnx2x *bp)
-{
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, 0, 0, 1);
-
- /* Wait for completion */
- return bnx2x_wait_ramrod(bp, BNX2X_STATE_FUNC_STARTED, 0, &(bp->state),
- WAIT_RAMROD_COMMON);
-}
-
-static int bnx2x_func_stop(struct bnx2x *bp)
-{
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, 1);
-
- /* Wait for completion */
- return bnx2x_wait_ramrod(bp, BNX2X_STATE_CLOSING_WAIT4_UNLOAD,
- 0, &(bp->state), WAIT_RAMROD_COMMON);
-}
-
-/**
- * bnx2x_set_mac_addr_gen - set a MAC in a CAM for a few L2 Clients for E1x chips
- *
- * @bp: driver handle
- * @set: set or clear an entry (1 or 0)
- * @mac: pointer to a buffer containing a MAC
- * @cl_bit_vec: bit vector of clients to register a MAC for
- * @cam_offset: offset in a CAM to use
- * @is_bcast: is the set MAC a broadcast address (for E1 only)
- */
-static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
- u32 cl_bit_vec, u8 cam_offset,
- u8 is_bcast)
-{
- struct mac_configuration_cmd *config =
- (struct mac_configuration_cmd *)bnx2x_sp(bp, mac_config);
- int ramrod_flags = WAIT_RAMROD_COMMON;
-
- bp->set_mac_pending = 1;
-
- config->hdr.length = 1;
- config->hdr.offset = cam_offset;
- config->hdr.client_id = 0xff;
- /* Mark the single MAC configuration ramrod as opposed to a
- * UC/MC list configuration).
- */
- config->hdr.echo = 1;
-
- /* primary MAC */
- config->config_table[0].msb_mac_addr =
- swab16(*(u16 *)&mac[0]);
- config->config_table[0].middle_mac_addr =
- swab16(*(u16 *)&mac[2]);
- config->config_table[0].lsb_mac_addr =
- swab16(*(u16 *)&mac[4]);
- config->config_table[0].clients_bit_vector =
- cpu_to_le32(cl_bit_vec);
- config->config_table[0].vlan_id = 0;
- config->config_table[0].pf_id = BP_FUNC(bp);
- if (set)
- SET_FLAG(config->config_table[0].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_SET);
- else
- SET_FLAG(config->config_table[0].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
-
- if (is_bcast)
- SET_FLAG(config->config_table[0].flags,
- MAC_CONFIGURATION_ENTRY_BROADCAST, 1);
-
- DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x) PF_ID %d CLID mask %d\n",
- (set ? "setting" : "clearing"),
- config->config_table[0].msb_mac_addr,
- config->config_table[0].middle_mac_addr,
- config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
-
- mb();
-
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mac_config)),
- U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
-
- /* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, ramrod_flags);
-}
-
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
- int *state_p, int flags)
-{
- /* can take a while if any port is running */
- int cnt = 5000;
- u8 poll = flags & WAIT_RAMROD_POLL;
- u8 common = flags & WAIT_RAMROD_COMMON;
-
- DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
- poll ? "polling" : "waiting", state, idx);
-
- might_sleep();
- while (cnt--) {
- if (poll) {
- if (common)
- bnx2x_eq_int(bp);
- else {
- bnx2x_rx_int(bp->fp, 10);
- /* if index is different from 0
- * the reply for some commands will
- * be on the non default queue
- */
- if (idx)
- bnx2x_rx_int(&bp->fp[idx], 10);
- }
- }
-
- mb(); /* state is changed by bnx2x_sp_event() */
- if (*state_p == state) {
-#ifdef BNX2X_STOP_ON_ERROR
- DP(NETIF_MSG_IFUP, "exit (cnt %d)\n", 5000 - cnt);
-#endif
- return 0;
- }
-
- msleep(1);
-
- if (bp->panic)
- return -EIO;
- }
-
- /* timeout! */
- BNX2X_ERR("timeout %s for state %x on IDX [%d]\n",
- poll ? "polling" : "waiting", state, idx);
-#ifdef BNX2X_STOP_ON_ERROR
- bnx2x_panic();
-#endif
-
- return -EBUSY;
-}
-
-static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
-{
- if (CHIP_IS_E1H(bp))
- return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
- else if (CHIP_MODE_IS_4_PORT(bp))
- return E2_FUNC_MAX * rel_offset + BP_FUNC(bp);
- else
- return E2_FUNC_MAX * rel_offset + BP_VN(bp);
-}
-
-/**
- * LLH CAM line allocations: currently only iSCSI and ETH macs are
- * relevant. In addition, current implementation is tuned for a
- * single ETH MAC.
- */
-enum {
- LLH_CAM_ISCSI_ETH_LINE = 0,
- LLH_CAM_ETH_LINE,
- LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE
-};
-
-static void bnx2x_set_mac_in_nig(struct bnx2x *bp,
- int set,
- unsigned char *dev_addr,
- int index)
-{
- u32 wb_data[2];
- u32 mem_offset, ena_offset, mem_index;
- /**
- * indexes mapping:
- * 0..7 - goes to MEM
- * 8..15 - goes to MEM2
- */
-
- if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
- return;
-
- /* calculate memory start offset according to the mapping
- * and index in the memory */
- if (index < NIG_LLH_FUNC_MEM_MAX_OFFSET) {
- mem_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
- NIG_REG_LLH0_FUNC_MEM;
- ena_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
- NIG_REG_LLH0_FUNC_MEM_ENABLE;
- mem_index = index;
- } else {
- mem_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2 :
- NIG_REG_P0_LLH_FUNC_MEM2;
- ena_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE :
- NIG_REG_P0_LLH_FUNC_MEM2_ENABLE;
- mem_index = index - NIG_LLH_FUNC_MEM_MAX_OFFSET;
- }
-
- if (set) {
- /* LLH_FUNC_MEM is a u64 WB register */
- mem_offset += 8*mem_index;
-
- wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
- (dev_addr[4] << 8) | dev_addr[5]);
- wb_data[1] = ((dev_addr[0] << 8) | dev_addr[1]);
- REG_WR_DMAE(bp, mem_offset, wb_data, 2);
- }
-
- /* enable/disable the entry */
- REG_WR(bp, ena_offset + 4*mem_index, set);
-
-}
-
-void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
+int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
+ struct bnx2x_vlan_mac_obj *obj, bool set,
+ int mac_type, unsigned long *ramrod_flags)
{
- u8 cam_offset = (CHIP_IS_E1(bp) ? (BP_PORT(bp) ? 32 : 0) :
- bnx2x_e1h_cam_offset(bp, CAM_ETH_LINE));
+ int rc;
+ struct bnx2x_vlan_mac_ramrod_params ramrod_param;
- /* networking MAC */
- bnx2x_set_mac_addr_gen(bp, set, bp->dev->dev_addr,
- (1 << bp->fp->cl_id), cam_offset , 0);
+ memset(&ramrod_param, 0, sizeof(ramrod_param));
- bnx2x_set_mac_in_nig(bp, set, bp->dev->dev_addr, LLH_CAM_ETH_LINE);
+ /* Fill general parameters */
+ ramrod_param.vlan_mac_obj = obj;
+ ramrod_param.ramrod_flags = *ramrod_flags;
- if (CHIP_IS_E1(bp)) {
- /* broadcast MAC */
- static const u8 bcast[ETH_ALEN] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
- bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
- }
-}
+ /* Fill a user request section if needed */
+ if (!test_bit(RAMROD_CONT, ramrod_flags)) {
+ memcpy(ramrod_param.user_req.u.mac.mac, mac, ETH_ALEN);
-static inline u8 bnx2x_e1_cam_mc_offset(struct bnx2x *bp)
-{
- return CHIP_REV_IS_SLOW(bp) ?
- (BNX2X_MAX_EMUL_MULTI * (1 + BP_PORT(bp))) :
- (BNX2X_MAX_MULTICAST * (1 + BP_PORT(bp)));
-}
+ __set_bit(mac_type, &ramrod_param.user_req.vlan_mac_flags);
-/* set mc list, do not wait as wait implies sleep and
- * set_rx_mode can be invoked from non-sleepable context.
- *
- * Instead we use the same ramrod data buffer each time we need
- * to configure a list of addresses, and use the fact that the
- * list of MACs is changed in an incremental way and that the
- * function is called under the netif_addr_lock. A temporary
- * inconsistent CAM configuration (possible in case of a very fast
- * sequence of add/del/add on the host side) will shortly be
- * restored by the handler of the last ramrod.
- */
-static int bnx2x_set_e1_mc_list(struct bnx2x *bp)
-{
- int i = 0, old;
- struct net_device *dev = bp->dev;
- u8 offset = bnx2x_e1_cam_mc_offset(bp);
- struct netdev_hw_addr *ha;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
-
- if (netdev_mc_count(dev) > BNX2X_MAX_MULTICAST)
- return -EINVAL;
-
- netdev_for_each_mc_addr(ha, dev) {
- /* copy mac */
- config_cmd->config_table[i].msb_mac_addr =
- swab16(*(u16 *)&bnx2x_mc_addr(ha)[0]);
- config_cmd->config_table[i].middle_mac_addr =
- swab16(*(u16 *)&bnx2x_mc_addr(ha)[2]);
- config_cmd->config_table[i].lsb_mac_addr =
- swab16(*(u16 *)&bnx2x_mc_addr(ha)[4]);
-
- config_cmd->config_table[i].vlan_id = 0;
- config_cmd->config_table[i].pf_id = BP_FUNC(bp);
- config_cmd->config_table[i].clients_bit_vector =
- cpu_to_le32(1 << BP_L_ID(bp));
-
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_SET);
-
- DP(NETIF_MSG_IFUP,
- "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
- config_cmd->config_table[i].msb_mac_addr,
- config_cmd->config_table[i].middle_mac_addr,
- config_cmd->config_table[i].lsb_mac_addr);
- i++;
- }
- old = config_cmd->hdr.length;
- if (old > i) {
- for (; i < old; i++) {
- if (CAM_IS_INVALID(config_cmd->
- config_table[i])) {
- /* already invalidated */
- break;
- }
- /* invalidate */
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
- }
+ /* Set the command: ADD or DEL */
+ if (set)
+ ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+ else
+ ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_DEL;
}
- wmb();
-
- config_cmd->hdr.length = i;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* Mark that this ramrod doesn't use bp->set_mac_pending for
- * synchronization.
- */
- config_cmd->hdr.echo = 0;
-
- mb();
-
- return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-}
-
-void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp)
-{
- int i;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
- int ramrod_flags = WAIT_RAMROD_COMMON;
- u8 offset = bnx2x_e1_cam_mc_offset(bp);
-
- for (i = 0; i < BNX2X_MAX_MULTICAST; i++)
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
-
- wmb();
-
- config_cmd->hdr.length = BNX2X_MAX_MULTICAST;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* We'll wait for a completion this time... */
- config_cmd->hdr.echo = 1;
-
- bp->set_mac_pending = 1;
-
- mb();
-
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-
- /* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
- ramrod_flags);
-
+ rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+ if (rc < 0)
+ BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del"));
+ return rc;
}
-/* Accept one or more multicasts */
-static int bnx2x_set_e1h_mc_list(struct bnx2x *bp)
+int bnx2x_del_all_macs(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ int mac_type, bool wait_for_comp)
{
- struct net_device *dev = bp->dev;
- struct netdev_hw_addr *ha;
- u32 mc_filter[MC_HASH_SIZE];
- u32 crc, bit, regidx;
- int i;
-
- memset(mc_filter, 0, 4 * MC_HASH_SIZE);
-
- netdev_for_each_mc_addr(ha, dev) {
- DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
- bnx2x_mc_addr(ha));
-
- crc = crc32c_le(0, bnx2x_mc_addr(ha),
- ETH_ALEN);
- bit = (crc >> 24) & 0xff;
- regidx = bit >> 5;
- bit &= 0x1f;
- mc_filter[regidx] |= (1 << bit);
- }
+ int rc;
+ unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
- for (i = 0; i < MC_HASH_SIZE; i++)
- REG_WR(bp, MC_HASH_OFFSET(bp, i),
- mc_filter[i]);
+ /* Wait for completion of requested */
+ if (wait_for_comp)
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
- return 0;
-}
+ /* Set the mac type of addresses we want to clear */
+ __set_bit(mac_type, &vlan_mac_flags);
-void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp)
-{
- int i;
+ rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags, &ramrod_flags);
+ if (rc < 0)
+ BNX2X_ERR("Failed to delete MACs: %d\n", rc);
- for (i = 0; i < MC_HASH_SIZE; i++)
- REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+ return rc;
}
-#ifdef BCM_CNIC
-/**
- * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
- *
- * @bp: driver handle
- * @set: set or clear the CAM entry
- *
- * This function will wait until the ramdord completion returns.
- * Return 0 if success, -ENODEV if ramrod doesn't return.
- */
-static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set)
+int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
{
- u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) :
- bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE));
- u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID +
- BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
- u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
- u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
+ unsigned long ramrod_flags = 0;
- /* Send a SET_MAC ramrod */
- bnx2x_set_mac_addr_gen(bp, set, iscsi_mac, cl_bit_vec,
- cam_offset, 0);
+ DP(NETIF_MSG_IFUP, "Adding Eth MAC\n");
- bnx2x_set_mac_in_nig(bp, set, iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
-
- return 0;
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+ /* Eth MAC is set on RSS leading client (fp[0]) */
+ return bnx2x_set_mac_one(bp, bp->dev->dev_addr, &bp->fp->mac_obj, set,
+ BNX2X_ETH_MAC, &ramrod_flags);
}
-/**
- * bnx2x_set_fip_eth_mac_addr - set FCoE L2 MAC(s)
- *
- * @bp: driver handle
- * @set: set or clear the CAM entry
- *
- * This function will wait until the ramrod completion returns.
- * Returns 0 if success, -ENODEV if ramrod doesn't return.
- */
-int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set)
-{
- u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
- /**
- * CAM allocation for E1H
- * eth unicasts: by func number
- * iscsi: by func number
- * fip unicast: by func number
- * fip multicast: by func number
- */
- bnx2x_set_mac_addr_gen(bp, set, bp->fip_mac,
- cl_bit_vec, bnx2x_e1h_cam_offset(bp, CAM_FIP_ETH_LINE), 0);
-
- return 0;
-}
-
-int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set)
+int bnx2x_setup_leading(struct bnx2x *bp)
{
- u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
-
- /**
- * CAM allocation for E1H
- * eth unicasts: by func number
- * iscsi: by func number
- * fip unicast: by func number
- * fip multicast: by func number
- */
- bnx2x_set_mac_addr_gen(bp, set, ALL_ENODE_MACS, cl_bit_vec,
- bnx2x_e1h_cam_offset(bp, CAM_FIP_MCAST_LINE), 0);
-
- return 0;
-}
-#endif
-
-static void bnx2x_fill_cl_init_data(struct bnx2x *bp,
- struct bnx2x_client_init_params *params,
- u8 activate,
- struct client_init_ramrod_data *data)
-{
- /* Clear the buffer */
- memset(data, 0, sizeof(*data));
-
- /* general */
- data->general.client_id = params->rxq_params.cl_id;
- data->general.statistics_counter_id = params->rxq_params.stat_id;
- data->general.statistics_en_flg =
- (params->rxq_params.flags & QUEUE_FLG_STATS) ? 1 : 0;
- data->general.is_fcoe_flg =
- (params->ramrod_params.flags & CLIENT_IS_FCOE) ? 1 : 0;
- data->general.activate_flg = activate;
- data->general.sp_client_id = params->rxq_params.spcl_id;
-
- /* Rx data */
- data->rx.tpa_en_flg =
- (params->rxq_params.flags & QUEUE_FLG_TPA) ? 1 : 0;
- data->rx.vmqueue_mode_en_flg = 0;
- data->rx.cache_line_alignment_log_size =
- params->rxq_params.cache_line_log;
- data->rx.enable_dynamic_hc =
- (params->rxq_params.flags & QUEUE_FLG_DHC) ? 1 : 0;
- data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt;
- data->rx.client_qzone_id = params->rxq_params.cl_qzone_id;
- data->rx.max_agg_size = params->rxq_params.tpa_agg_sz;
-
- /* We don't set drop flags */
- data->rx.drop_ip_cs_err_flg = 0;
- data->rx.drop_tcp_cs_err_flg = 0;
- data->rx.drop_ttl0_flg = 0;
- data->rx.drop_udp_cs_err_flg = 0;
-
- data->rx.inner_vlan_removal_enable_flg =
- (params->rxq_params.flags & QUEUE_FLG_VLAN) ? 1 : 0;
- data->rx.outer_vlan_removal_enable_flg =
- (params->rxq_params.flags & QUEUE_FLG_OV) ? 1 : 0;
- data->rx.status_block_id = params->rxq_params.fw_sb_id;
- data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index;
- data->rx.bd_buff_size = cpu_to_le16(params->rxq_params.buf_sz);
- data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz);
- data->rx.mtu = cpu_to_le16(params->rxq_params.mtu);
- data->rx.bd_page_base.lo =
- cpu_to_le32(U64_LO(params->rxq_params.dscr_map));
- data->rx.bd_page_base.hi =
- cpu_to_le32(U64_HI(params->rxq_params.dscr_map));
- data->rx.sge_page_base.lo =
- cpu_to_le32(U64_LO(params->rxq_params.sge_map));
- data->rx.sge_page_base.hi =
- cpu_to_le32(U64_HI(params->rxq_params.sge_map));
- data->rx.cqe_page_base.lo =
- cpu_to_le32(U64_LO(params->rxq_params.rcq_map));
- data->rx.cqe_page_base.hi =
- cpu_to_le32(U64_HI(params->rxq_params.rcq_map));
- data->rx.is_leading_rss =
- (params->ramrod_params.flags & CLIENT_IS_LEADING_RSS) ? 1 : 0;
- data->rx.is_approx_mcast = data->rx.is_leading_rss;
-
- /* Tx data */
- data->tx.enforce_security_flg = 0; /* VF specific */
- data->tx.tx_status_block_id = params->txq_params.fw_sb_id;
- data->tx.tx_sb_index_number = params->txq_params.sb_cq_index;
- data->tx.mtu = 0; /* VF specific */
- data->tx.tx_bd_page_base.lo =
- cpu_to_le32(U64_LO(params->txq_params.dscr_map));
- data->tx.tx_bd_page_base.hi =
- cpu_to_le32(U64_HI(params->txq_params.dscr_map));
-
- /* flow control data */
- data->fc.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo);
- data->fc.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi);
- data->fc.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo);
- data->fc.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi);
- data->fc.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo);
- data->fc.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi);
- data->fc.rx_cos_mask = cpu_to_le16(params->pause.pri_map);
-
- data->fc.safc_group_num = params->txq_params.cos;
- data->fc.safc_group_en_flg =
- (params->txq_params.flags & QUEUE_FLG_COS) ? 1 : 0;
- data->fc.traffic_type =
- (params->ramrod_params.flags & CLIENT_IS_FCOE) ?
- LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
-}
-
-static inline void bnx2x_set_ctx_validation(struct eth_context *cxt, u32 cid)
-{
- /* ustorm cxt validation */
- cxt->ustorm_ag_context.cdu_usage =
- CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_UCM_AG,
- ETH_CONNECTION_TYPE);
- /* xcontext validation */
- cxt->xstorm_ag_context.cdu_reserved =
- CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_XCM_AG,
- ETH_CONNECTION_TYPE);
-}
-
-static int bnx2x_setup_fw_client(struct bnx2x *bp,
- struct bnx2x_client_init_params *params,
- u8 activate,
- struct client_init_ramrod_data *data,
- dma_addr_t data_mapping)
-{
- u16 hc_usec;
- int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
- int ramrod_flags = 0, rc;
-
- /* HC and context validation values */
- hc_usec = params->txq_params.hc_rate ?
- 1000000 / params->txq_params.hc_rate : 0;
- bnx2x_update_coalesce_sb_index(bp,
- params->txq_params.fw_sb_id,
- params->txq_params.sb_cq_index,
- !(params->txq_params.flags & QUEUE_FLG_HC),
- hc_usec);
-
- *(params->ramrod_params.pstate) = BNX2X_FP_STATE_OPENING;
-
- hc_usec = params->rxq_params.hc_rate ?
- 1000000 / params->rxq_params.hc_rate : 0;
- bnx2x_update_coalesce_sb_index(bp,
- params->rxq_params.fw_sb_id,
- params->rxq_params.sb_cq_index,
- !(params->rxq_params.flags & QUEUE_FLG_HC),
- hc_usec);
-
- bnx2x_set_ctx_validation(params->rxq_params.cxt,
- params->rxq_params.cid);
-
- /* zero stats */
- if (params->txq_params.flags & QUEUE_FLG_STATS)
- storm_memset_xstats_zero(bp, BP_PORT(bp),
- params->txq_params.stat_id);
-
- if (params->rxq_params.flags & QUEUE_FLG_STATS) {
- storm_memset_ustats_zero(bp, BP_PORT(bp),
- params->rxq_params.stat_id);
- storm_memset_tstats_zero(bp, BP_PORT(bp),
- params->rxq_params.stat_id);
- }
-
- /* Fill the ramrod data */
- bnx2x_fill_cl_init_data(bp, params, activate, data);
-
- /* SETUP ramrod.
- *
- * bnx2x_sp_post() takes a spin_lock thus no other explict memory
- * barrier except from mmiowb() is needed to impose a
- * proper ordering of memory operations.
- */
- mmiowb();
-
-
- bnx2x_sp_post(bp, ramrod, params->ramrod_params.cid,
- U64_HI(data_mapping), U64_LO(data_mapping), 0);
-
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, params->ramrod_params.state,
- params->ramrod_params.index,
- params->ramrod_params.pstate,
- ramrod_flags);
- return rc;
+ return bnx2x_setup_queue(bp, &bp->fp[0], 1);
}
/**
@@ -6647,16 +6984,14 @@ static int bnx2x_setup_fw_client(struct bnx2x *bp,
*
* In case of MSI-X it will also try to enable MSI-X.
*/
-static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
+static void __devinit bnx2x_set_int_mode(struct bnx2x *bp)
{
- int rc = 0;
-
- switch (bp->int_mode) {
+ switch (int_mode) {
case INT_MODE_MSI:
bnx2x_enable_msi(bp);
/* falling through... */
case INT_MODE_INTx:
- bp->num_queues = 1 + NONE_ETH_CONTEXT_USE;
+ bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
break;
default:
@@ -6670,8 +7005,7 @@ static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
* so try to enable MSI-X with the requested number of fp's
* and fallback to MSI or legacy INTx with one fp
*/
- rc = bnx2x_enable_msix(bp);
- if (rc) {
+ if (bnx2x_enable_msix(bp)) {
/* failed to enable MSI-X */
if (bp->multi_mode)
DP(NETIF_MSG_IFUP,
@@ -6679,17 +7013,15 @@ static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
"enable MSI-X (%d), "
"set number of queues to %d\n",
bp->num_queues,
- 1 + NONE_ETH_CONTEXT_USE);
- bp->num_queues = 1 + NONE_ETH_CONTEXT_USE;
+ 1 + NON_ETH_CONTEXT_USE);
+ bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
+ /* Try to enable MSI */
if (!(bp->flags & DISABLE_MSI_FLAG))
bnx2x_enable_msi(bp);
}
-
break;
}
-
- return rc;
}
/* must be called prioir to any HW initializations */
@@ -6713,7 +7045,7 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
ilt_client->page_size = CDU_ILT_PAGE_SZ;
ilt_client->flags = ILT_CLIENT_SKIP_MEM;
ilt_client->start = line;
- line += L2_ILT_LINES(bp);
+ line += bnx2x_cid_ilt_lines(bp);
#ifdef BCM_CNIC
line += CNIC_ILT_LINES;
#endif
@@ -6793,92 +7125,258 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
#else
ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
#endif
+ BUG_ON(line > ILT_MAX_LINES);
+}
+
+/**
+ * bnx2x_pf_q_prep_init - prepare INIT transition parameters
+ *
+ * @bp: driver handle
+ * @fp: pointer to fastpath
+ * @init_params: pointer to parameters structure
+ *
+ * parameters configured:
+ * - HC configuration
+ * - Queue's CDU context
+ */
+static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params)
+{
+
+ u8 cos;
+ /* FCoE Queue uses Default SB, thus has no HC capabilities */
+ if (!IS_FCOE_FP(fp)) {
+ __set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags);
+ __set_bit(BNX2X_Q_FLG_HC, &init_params->tx.flags);
+
+ /* If HC is supporterd, enable host coalescing in the transition
+ * to INIT state.
+ */
+ __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->rx.flags);
+ __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->tx.flags);
+
+ /* HC rate */
+ init_params->rx.hc_rate = bp->rx_ticks ?
+ (1000000 / bp->rx_ticks) : 0;
+ init_params->tx.hc_rate = bp->tx_ticks ?
+ (1000000 / bp->tx_ticks) : 0;
+
+ /* FW SB ID */
+ init_params->rx.fw_sb_id = init_params->tx.fw_sb_id =
+ fp->fw_sb_id;
+
+ /*
+ * CQ index among the SB indices: FCoE clients uses the default
+ * SB, therefore it's different.
+ */
+ init_params->rx.sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS;
+ init_params->tx.sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS;
+ }
+
+ /* 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",
+ fp->index, init_params->max_cos);
+
+ /* set the context pointers queue object */
+ for (cos = FIRST_TX_COS_INDEX; cos < init_params->max_cos; cos++)
+ init_params->cxts[cos] =
+ &bp->context.vcxt[fp->txdata[cos].cid].eth;
}
-int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- int is_leading)
+int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ struct bnx2x_queue_state_params *q_params,
+ struct bnx2x_queue_setup_tx_only_params *tx_only_params,
+ int tx_index, bool leading)
{
- struct bnx2x_client_init_params params = { {0} };
+ memset(tx_only_params, 0, sizeof(*tx_only_params));
+
+ /* Set the command */
+ q_params->cmd = BNX2X_Q_CMD_SETUP_TX_ONLY;
+
+ /* Set tx-only QUEUE flags: don't zero statistics */
+ tx_only_params->flags = bnx2x_get_common_flags(bp, fp, false);
+
+ /* choose the index of the cid to send the slow path on */
+ tx_only_params->cid_index = tx_index;
+
+ /* Set general TX_ONLY_SETUP parameters */
+ bnx2x_pf_q_prep_general(bp, fp, &tx_only_params->gen_params, tx_index);
+
+ /* Set Tx TX_ONLY_SETUP parameters */
+ bnx2x_pf_tx_q_prep(bp, fp, &tx_only_params->txq_params, tx_index);
+
+ 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",
+ 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);
+
+ /* send the ramrod */
+ return bnx2x_queue_state_change(bp, q_params);
+}
+
+
+/**
+ * bnx2x_setup_queue - setup queue
+ *
+ * @bp: driver handle
+ * @fp: pointer to fastpath
+ * @leading: is leading
+ *
+ * This function performs 2 steps in a Queue state machine
+ * actually: 1) RESET->INIT 2) INIT->SETUP
+ */
+
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ bool leading)
+{
+ struct bnx2x_queue_state_params q_params = {0};
+ struct bnx2x_queue_setup_params *setup_params =
+ &q_params.params.setup;
+ struct bnx2x_queue_setup_tx_only_params *tx_only_params =
+ &q_params.params.tx_only;
int rc;
+ u8 tx_index;
+
+ DP(BNX2X_MSG_SP, "setting up queue %d", fp->index);
/* reset IGU state skip FCoE L2 queue */
if (!IS_FCOE_FP(fp))
bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
IGU_INT_ENABLE, 0);
- params.ramrod_params.pstate = &fp->state;
- params.ramrod_params.state = BNX2X_FP_STATE_OPEN;
- params.ramrod_params.index = fp->index;
- params.ramrod_params.cid = fp->cid;
+ q_params.q_obj = &fp->q_obj;
+ /* We want to wait for completion in this context */
+ __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-#ifdef BCM_CNIC
- if (IS_FCOE_FP(fp))
- params.ramrod_params.flags |= CLIENT_IS_FCOE;
+ /* Prepare the INIT parameters */
+ bnx2x_pf_q_prep_init(bp, fp, &q_params.params.init);
-#endif
+ /* Set the command */
+ q_params.cmd = BNX2X_Q_CMD_INIT;
- if (is_leading)
- params.ramrod_params.flags |= CLIENT_IS_LEADING_RSS;
+ /* Change the state to INIT */
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc) {
+ BNX2X_ERR("Queue(%d) INIT failed\n", fp->index);
+ return rc;
+ }
- bnx2x_pf_rx_cl_prep(bp, fp, &params.pause, &params.rxq_params);
+ DP(BNX2X_MSG_SP, "init complete");
- bnx2x_pf_tx_cl_prep(bp, fp, &params.txq_params);
- rc = bnx2x_setup_fw_client(bp, &params, 1,
- bnx2x_sp(bp, client_init_data),
- bnx2x_sp_mapping(bp, client_init_data));
- return rc;
-}
+ /* Now move the Queue to the SETUP state... */
+ memset(setup_params, 0, sizeof(*setup_params));
-static int bnx2x_stop_fw_client(struct bnx2x *bp,
- struct bnx2x_client_ramrod_params *p)
-{
- int rc;
+ /* Set QUEUE flags */
+ setup_params->flags = bnx2x_get_q_flags(bp, fp, leading);
- int poll_flag = p->poll ? WAIT_RAMROD_POLL : 0;
+ /* Set general SETUP parameters */
+ bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params,
+ FIRST_TX_COS_INDEX);
- /* halt the connection */
- *p->pstate = BNX2X_FP_STATE_HALTING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, p->cid, 0,
- p->cl_id, 0);
+ bnx2x_pf_rx_q_prep(bp, fp, &setup_params->pause_params,
+ &setup_params->rxq_params);
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, p->index,
- p->pstate, poll_flag);
- if (rc) /* timeout */
- return rc;
+ bnx2x_pf_tx_q_prep(bp, fp, &setup_params->txq_params,
+ FIRST_TX_COS_INDEX);
+
+ /* Set the command */
+ q_params.cmd = BNX2X_Q_CMD_SETUP;
- *p->pstate = BNX2X_FP_STATE_TERMINATING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, p->cid, 0,
- p->cl_id, 0);
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_TERMINATED, p->index,
- p->pstate, poll_flag);
- if (rc) /* timeout */
+ /* Change the state to SETUP */
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc) {
+ BNX2X_ERR("Queue(%d) SETUP failed\n", fp->index);
return rc;
+ }
+ /* loop through the relevant tx-only indices */
+ for (tx_index = FIRST_TX_ONLY_COS_INDEX;
+ tx_index < fp->max_cos;
+ tx_index++) {
- /* delete cfc entry */
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, p->cid, 0, 0, 1);
+ /* prepare and send tx-only ramrod*/
+ rc = bnx2x_setup_tx_only(bp, fp, &q_params,
+ tx_only_params, tx_index, leading);
+ if (rc) {
+ BNX2X_ERR("Queue(%d.%d) TX_ONLY_SETUP failed\n",
+ fp->index, tx_index);
+ return rc;
+ }
+ }
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, p->index,
- p->pstate, WAIT_RAMROD_COMMON);
return rc;
}
-static int bnx2x_stop_client(struct bnx2x *bp, int index)
+static int bnx2x_stop_queue(struct bnx2x *bp, int index)
{
- struct bnx2x_client_ramrod_params client_stop = {0};
struct bnx2x_fastpath *fp = &bp->fp[index];
+ struct bnx2x_fp_txdata *txdata;
+ struct bnx2x_queue_state_params q_params = {0};
+ int rc, tx_index;
+
+ DP(BNX2X_MSG_SP, "stopping queue %d cid %d", index, fp->cid);
+
+ q_params.q_obj = &fp->q_obj;
+ /* We want to wait for completion in this context */
+ __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+
+
+ /* close tx-only connections */
+ for (tx_index = FIRST_TX_ONLY_COS_INDEX;
+ tx_index < fp->max_cos;
+ tx_index++){
- client_stop.index = index;
- client_stop.cid = fp->cid;
- client_stop.cl_id = fp->cl_id;
- client_stop.pstate = &(fp->state);
- client_stop.poll = 0;
+ /* ascertain this is a normal queue*/
+ txdata = &fp->txdata[tx_index];
- return bnx2x_stop_fw_client(bp, &client_stop);
+ DP(BNX2X_MSG_SP, "stopping tx-only queue %d",
+ txdata->txq_index);
+
+ /* send halt terminate on tx-only connection */
+ q_params.cmd = BNX2X_Q_CMD_TERMINATE;
+ memset(&q_params.params.terminate, 0,
+ sizeof(q_params.params.terminate));
+ q_params.params.terminate.cid_index = tx_index;
+
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc)
+ return rc;
+
+ /* send halt terminate on tx-only connection */
+ q_params.cmd = BNX2X_Q_CMD_CFC_DEL;
+ memset(&q_params.params.cfc_del, 0,
+ sizeof(q_params.params.cfc_del));
+ q_params.params.cfc_del.cid_index = tx_index;
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc)
+ return rc;
+ }
+ /* Stop the primary connection: */
+ /* ...halt the connection */
+ q_params.cmd = BNX2X_Q_CMD_HALT;
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc)
+ return rc;
+
+ /* ...terminate the connection */
+ q_params.cmd = BNX2X_Q_CMD_TERMINATE;
+ memset(&q_params.params.terminate, 0,
+ sizeof(q_params.params.terminate));
+ q_params.params.terminate.cid_index = FIRST_TX_COS_INDEX;
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc)
+ return rc;
+ /* ...delete cfc entry */
+ q_params.cmd = BNX2X_Q_CMD_CFC_DEL;
+ memset(&q_params.params.cfc_del, 0,
+ sizeof(q_params.params.cfc_del));
+ q_params.params.cfc_del.cid_index = FIRST_TX_COS_INDEX;
+ return bnx2x_queue_state_change(bp, &q_params);
}
@@ -6887,12 +7385,6 @@ static void bnx2x_reset_func(struct bnx2x *bp)
int port = BP_PORT(bp);
int func = BP_FUNC(bp);
int i;
- int pfunc_offset_fp = offsetof(struct hc_sb_data, p_func) +
- (CHIP_IS_E2(bp) ?
- offsetof(struct hc_status_block_data_e2, common) :
- offsetof(struct hc_status_block_data_e1x, common));
- int pfunc_offset_sp = offsetof(struct hc_sp_status_block_data, p_func);
- int pfid_offset = offsetof(struct pci_entity, pf_id);
/* Disable the function in the FW */
REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0);
@@ -6903,20 +7395,21 @@ static void bnx2x_reset_func(struct bnx2x *bp)
/* FP SBs */
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- REG_WR8(bp,
- BAR_CSTRORM_INTMEM +
- CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id)
- + pfunc_offset_fp + pfid_offset,
- HC_FUNCTION_DISABLED);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id),
+ SB_DISABLED);
}
+#ifdef BCM_CNIC
+ /* CNIC SB */
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)),
+ SB_DISABLED);
+#endif
/* SP SB */
- REG_WR8(bp,
- BAR_CSTRORM_INTMEM +
- CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
- pfunc_offset_sp + pfid_offset,
- HC_FUNCTION_DISABLED);
-
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func),
+ SB_DISABLED);
for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++)
REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func),
@@ -6950,7 +7443,7 @@ static void bnx2x_reset_func(struct bnx2x *bp)
/* Timers workaround bug for E2: if this is vnic-3,
* we need to set the entire ilt range for this timers.
*/
- if (CHIP_IS_E2(bp) && BP_VN(bp) == 3) {
+ if (!CHIP_IS_E1x(bp) && BP_VN(bp) == 3) {
struct ilt_client_info ilt_cli;
/* use dummy TM client */
memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
@@ -6962,7 +7455,7 @@ static void bnx2x_reset_func(struct bnx2x *bp)
}
/* this assumes that reset_port() called before reset_func()*/
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
bnx2x_pf_disable(bp);
bp->dmae_ready = 0;
@@ -6973,6 +7466,9 @@ static void bnx2x_reset_port(struct bnx2x *bp)
int port = BP_PORT(bp);
u32 val;
+ /* Reset physical Link */
+ bnx2x__link_reset(bp);
+
REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
/* Do not rcv packets to BRB */
@@ -6994,92 +7490,66 @@ static void bnx2x_reset_port(struct bnx2x *bp)
/* TODO: Close Doorbell port? */
}
-static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
+static inline int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code)
{
- DP(BNX2X_MSG_MCP, "function %d reset_code %x\n",
- BP_ABS_FUNC(bp), reset_code);
+ struct bnx2x_func_state_params func_params = {0};
- switch (reset_code) {
- case FW_MSG_CODE_DRV_UNLOAD_COMMON:
- bnx2x_reset_port(bp);
- bnx2x_reset_func(bp);
- bnx2x_reset_common(bp);
- break;
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
- case FW_MSG_CODE_DRV_UNLOAD_PORT:
- bnx2x_reset_port(bp);
- bnx2x_reset_func(bp);
- break;
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_HW_RESET;
- case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
- bnx2x_reset_func(bp);
- break;
+ func_params.params.hw_init.load_phase = load_code;
- default:
- BNX2X_ERR("Unknown reset_code (0x%x) from MCP\n", reset_code);
- break;
- }
+ return bnx2x_func_state_change(bp, &func_params);
}
-#ifdef BCM_CNIC
-static inline void bnx2x_del_fcoe_eth_macs(struct bnx2x *bp)
+static inline int bnx2x_func_stop(struct bnx2x *bp)
{
- if (bp->flags & FCOE_MACS_SET) {
- if (!IS_MF_SD(bp))
- bnx2x_set_fip_eth_mac_addr(bp, 0);
-
- bnx2x_set_all_enode_macs(bp, 0);
-
- bp->flags &= ~FCOE_MACS_SET;
- }
-}
-#endif
-
-void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
-{
- int port = BP_PORT(bp);
- u32 reset_code = 0;
- int i, cnt, rc;
-
- /* Wait until tx fastpath tasks complete */
- for_each_tx_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
+ struct bnx2x_func_state_params func_params = {0};
+ int rc;
- cnt = 1000;
- while (bnx2x_has_tx_work_unload(fp)) {
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_STOP;
- if (!cnt) {
- BNX2X_ERR("timeout waiting for queue[%d]\n",
- i);
+ /*
+ * Try to stop the function the 'good way'. If fails (in case
+ * of a parity error during bnx2x_chip_cleanup()) and we are
+ * not in a debug mode, perform a state transaction in order to
+ * enable further HW_RESET transaction.
+ */
+ rc = bnx2x_func_state_change(bp, &func_params);
+ if (rc) {
#ifdef BNX2X_STOP_ON_ERROR
- bnx2x_panic();
- return -EBUSY;
+ return rc;
#else
- break;
+ BNX2X_ERR("FUNC_STOP ramrod failed. Running a dry "
+ "transaction\n");
+ __set_bit(RAMROD_DRV_CLR_ONLY, &func_params.ramrod_flags);
+ return bnx2x_func_state_change(bp, &func_params);
#endif
- }
- cnt--;
- msleep(1);
- }
}
- /* Give HW time to discard old tx messages */
- msleep(1);
-
- bnx2x_set_eth_mac(bp, 0);
- bnx2x_invalidate_uc_list(bp);
-
- if (CHIP_IS_E1(bp))
- bnx2x_invalidate_e1_mc_list(bp);
- else {
- bnx2x_invalidate_e1h_mc_list(bp);
- REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
- }
+ return 0;
+}
-#ifdef BCM_CNIC
- bnx2x_del_fcoe_eth_macs(bp);
-#endif
+/**
+ * bnx2x_send_unload_req - request unload mode from the MCP.
+ *
+ * @bp: driver handle
+ * @unload_mode: requested function's unload mode
+ *
+ * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
+ */
+u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
+{
+ u32 reset_code = 0;
+ int port = BP_PORT(bp);
+ /* Select the UNLOAD request mode */
if (unload_mode == UNLOAD_NORMAL)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
@@ -7106,54 +7576,215 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
} else
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
+ /* Send the request to the MCP */
+ if (!BP_NOMCP(bp))
+ reset_code = bnx2x_fw_command(bp, reset_code, 0);
+ else {
+ int path = BP_PATH(bp);
+
+ DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d] "
+ "%d, %d, %d\n",
+ path, load_count[path][0], load_count[path][1],
+ load_count[path][2]);
+ load_count[path][0]--;
+ load_count[path][1 + port]--;
+ DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d] "
+ "%d, %d, %d\n",
+ path, load_count[path][0], load_count[path][1],
+ load_count[path][2]);
+ if (load_count[path][0] == 0)
+ reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
+ else if (load_count[path][1 + port] == 0)
+ reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
+ else
+ reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
+ }
+
+ return reset_code;
+}
+
+/**
+ * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
+ *
+ * @bp: driver handle
+ */
+void bnx2x_send_unload_done(struct bnx2x *bp)
+{
+ /* Report UNLOAD_DONE to MCP */
+ if (!BP_NOMCP(bp))
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+}
+
+static inline int bnx2x_func_wait_started(struct bnx2x *bp)
+{
+ int tout = 50;
+ int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
+
+ if (!bp->port.pmf)
+ return 0;
+
+ /*
+ * (assumption: No Attention from MCP at this stage)
+ * PMF probably in the middle of TXdisable/enable transaction
+ * 1. Sync IRS for default SB
+ * 2. Sync SP queue - this guarantes us that attention handling started
+ * 3. Wait, that TXdisable/enable transaction completes
+ *
+ * 1+2 guranty that if DCBx attention was scheduled it already changed
+ * pending bit of transaction from STARTED-->TX_STOPPED, if we alredy
+ * received complettion for the transaction the state is TX_STOPPED.
+ * State will return to STARTED after completion of TX_STOPPED-->STARTED
+ * transaction.
+ */
+
+ /* make sure default SB ISR is done */
+ if (msix)
+ synchronize_irq(bp->msix_table[0].vector);
+ else
+ synchronize_irq(bp->pdev->irq);
+
+ flush_workqueue(bnx2x_wq);
+
+ while (bnx2x_func_get_state(bp, &bp->func_obj) !=
+ BNX2X_F_STATE_STARTED && tout--)
+ msleep(20);
+
+ if (bnx2x_func_get_state(bp, &bp->func_obj) !=
+ BNX2X_F_STATE_STARTED) {
+#ifdef BNX2X_STOP_ON_ERROR
+ return -EBUSY;
+#else
+ /*
+ * Failed to complete the transaction in a "good way"
+ * Force both transactions with CLR bit
+ */
+ struct bnx2x_func_state_params func_params = {0};
+
+ DP(BNX2X_MSG_SP, "Hmmm... unexpected function state! "
+ "Forcing STARTED-->TX_ST0PPED-->STARTED\n");
+
+ func_params.f_obj = &bp->func_obj;
+ __set_bit(RAMROD_DRV_CLR_ONLY,
+ &func_params.ramrod_flags);
+
+ /* STARTED-->TX_ST0PPED */
+ func_params.cmd = BNX2X_F_CMD_TX_STOP;
+ bnx2x_func_state_change(bp, &func_params);
+
+ /* TX_ST0PPED-->STARTED */
+ func_params.cmd = BNX2X_F_CMD_TX_START;
+ return bnx2x_func_state_change(bp, &func_params);
+#endif
+ }
+
+ return 0;
+}
+
+void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
+{
+ int port = BP_PORT(bp);
+ int i, rc = 0;
+ u8 cos;
+ struct bnx2x_mcast_ramrod_params rparam = {0};
+ u32 reset_code;
+
+ /* Wait until tx fastpath tasks complete */
+ for_each_tx_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+
+ for_each_cos_in_tx_queue(fp, cos)
+ rc = bnx2x_clean_tx_queue(bp, &fp->txdata[cos]);
+#ifdef BNX2X_STOP_ON_ERROR
+ if (rc)
+ return;
+#endif
+ }
+
+ /* Give HW time to discard old tx messages */
+ usleep_range(1000, 1000);
+
+ /* Clean all ETH MACs */
+ rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_ETH_MAC, false);
+ if (rc < 0)
+ BNX2X_ERR("Failed to delete all ETH macs: %d\n", rc);
+
+ /* Clean up UC list */
+ rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_UC_LIST_MAC,
+ true);
+ if (rc < 0)
+ BNX2X_ERR("Failed to schedule DEL commands for UC MACs list: "
+ "%d\n", rc);
+
+ /* Disable LLH */
+ if (!CHIP_IS_E1(bp))
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+
+ /* Set "drop all" (stop Rx).
+ * We need to take a netif_addr_lock() here in order to prevent
+ * a race between the completion code and this code.
+ */
+ netif_addr_lock_bh(bp->dev);
+ /* Schedule the rx_mode command */
+ if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
+ set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+ else
+ bnx2x_set_storm_rx_mode(bp);
+
+ /* Cleanup multicast configuration */
+ rparam.mcast_obj = &bp->mcast_obj;
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+ if (rc < 0)
+ BNX2X_ERR("Failed to send DEL multicast command: %d\n", rc);
+
+ netif_addr_unlock_bh(bp->dev);
+
+
+
+ /*
+ * Send the UNLOAD_REQUEST to the MCP. This will return if
+ * this function should perform FUNC, PORT or COMMON HW
+ * reset.
+ */
+ reset_code = bnx2x_send_unload_req(bp, unload_mode);
+
+ /*
+ * (assumption: No Attention from MCP at this stage)
+ * PMF probably in the middle of TXdisable/enable transaction
+ */
+ rc = bnx2x_func_wait_started(bp);
+ if (rc) {
+ BNX2X_ERR("bnx2x_func_wait_started failed\n");
+#ifdef BNX2X_STOP_ON_ERROR
+ return;
+#endif
+ }
+
/* Close multi and leading connections
- Completions for ramrods are collected in a synchronous way */
+ * Completions for ramrods are collected in a synchronous way
+ */
for_each_queue(bp, i)
-
- if (bnx2x_stop_client(bp, i))
+ if (bnx2x_stop_queue(bp, i))
#ifdef BNX2X_STOP_ON_ERROR
return;
#else
goto unload_error;
#endif
+ /* If SP settings didn't get completed so far - something
+ * very wrong has happen.
+ */
+ if (!bnx2x_wait_sp_comp(bp, ~0x0UL))
+ BNX2X_ERR("Hmmm... Common slow path ramrods got stuck!\n");
+#ifndef BNX2X_STOP_ON_ERROR
+unload_error:
+#endif
rc = bnx2x_func_stop(bp);
if (rc) {
BNX2X_ERR("Function stop failed!\n");
#ifdef BNX2X_STOP_ON_ERROR
return;
-#else
- goto unload_error;
#endif
}
-#ifndef BNX2X_STOP_ON_ERROR
-unload_error:
-#endif
- if (!BP_NOMCP(bp))
- reset_code = bnx2x_fw_command(bp, reset_code, 0);
- else {
- DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d] "
- "%d, %d, %d\n", BP_PATH(bp),
- load_count[BP_PATH(bp)][0],
- load_count[BP_PATH(bp)][1],
- load_count[BP_PATH(bp)][2]);
- load_count[BP_PATH(bp)][0]--;
- load_count[BP_PATH(bp)][1 + port]--;
- DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d] "
- "%d, %d, %d\n", BP_PATH(bp),
- load_count[BP_PATH(bp)][0], load_count[BP_PATH(bp)][1],
- load_count[BP_PATH(bp)][2]);
- if (load_count[BP_PATH(bp)][0] == 0)
- reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
- else if (load_count[BP_PATH(bp)][1 + port] == 0)
- reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
- else
- reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
- }
-
- if ((reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) ||
- (reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT))
- bnx2x__link_reset(bp);
/* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1);
@@ -7162,12 +7793,13 @@ unload_error:
bnx2x_free_irq(bp);
/* Reset the chip */
- bnx2x_reset_chip(bp, reset_code);
+ rc = bnx2x_reset_hw(bp, reset_code);
+ if (rc)
+ BNX2X_ERR("HW_RESET failed\n");
- /* Report UNLOAD_DONE to MCP */
- if (!BP_NOMCP(bp))
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+ /* Report UNLOAD_DONE to MCP */
+ bnx2x_send_unload_done(bp);
}
void bnx2x_disable_close_the_gate(struct bnx2x *bp)
@@ -7184,7 +7816,7 @@ void bnx2x_disable_close_the_gate(struct bnx2x *bp)
val = REG_RD(bp, addr);
val &= ~(0x300);
REG_WR(bp, addr, val);
- } else if (CHIP_IS_E1H(bp)) {
+ } else {
val = REG_RD(bp, MISC_REG_AEU_GENERAL_MASK);
val &= ~(MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK |
MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK);
@@ -7195,24 +7827,37 @@ void bnx2x_disable_close_the_gate(struct bnx2x *bp)
/* Close gates #2, #3 and #4: */
static void bnx2x_set_234_gates(struct bnx2x *bp, bool close)
{
- u32 val, addr;
+ u32 val;
/* Gates #2 and #4a are closed/opened for "not E1" only */
if (!CHIP_IS_E1(bp)) {
/* #4 */
- val = REG_RD(bp, PXP_REG_HST_DISCARD_DOORBELLS);
- REG_WR(bp, PXP_REG_HST_DISCARD_DOORBELLS,
- close ? (val | 0x1) : (val & (~(u32)1)));
+ REG_WR(bp, PXP_REG_HST_DISCARD_DOORBELLS, !!close);
/* #2 */
- val = REG_RD(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES);
- REG_WR(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES,
- close ? (val | 0x1) : (val & (~(u32)1)));
+ REG_WR(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES, !!close);
}
/* #3 */
- addr = BP_PORT(bp) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
- val = REG_RD(bp, addr);
- REG_WR(bp, addr, (!close) ? (val | 0x1) : (val & (~(u32)1)));
+ if (CHIP_IS_E1x(bp)) {
+ /* Prevent interrupts from HC on both ports */
+ val = REG_RD(bp, HC_REG_CONFIG_1);
+ REG_WR(bp, HC_REG_CONFIG_1,
+ (!close) ? (val | HC_CONFIG_1_REG_BLOCK_DISABLE_1) :
+ (val & ~(u32)HC_CONFIG_1_REG_BLOCK_DISABLE_1));
+
+ val = REG_RD(bp, HC_REG_CONFIG_0);
+ REG_WR(bp, HC_REG_CONFIG_0,
+ (!close) ? (val | HC_CONFIG_0_REG_BLOCK_DISABLE_0) :
+ (val & ~(u32)HC_CONFIG_0_REG_BLOCK_DISABLE_0));
+ } else {
+ /* Prevent incomming interrupts in IGU */
+ val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+
+ REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION,
+ (!close) ?
+ (val | IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE) :
+ (val & ~(u32)IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE));
+ }
DP(NETIF_MSG_HW, "%s gates #2, #3 and #4\n",
close ? "closing" : "opening");
@@ -7330,7 +7975,6 @@ static void bnx2x_pxp_prep(struct bnx2x *bp)
if (!CHIP_IS_E1(bp)) {
REG_WR(bp, PXP2_REG_RD_START_INIT, 0);
REG_WR(bp, PXP2_REG_RQ_RBC_DONE, 0);
- REG_WR(bp, PXP2_REG_RQ_CFG_DONE, 0);
mmiowb();
}
}
@@ -7345,46 +7989,133 @@ static void bnx2x_pxp_prep(struct bnx2x *bp)
* - GRC
* - RBCN, RBCP
*/
-static void bnx2x_process_kill_chip_reset(struct bnx2x *bp)
+static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
{
u32 not_reset_mask1, reset_mask1, not_reset_mask2, reset_mask2;
+ u32 global_bits2, stay_reset2;
+
+ /*
+ * Bits that have to be set in reset_mask2 if we want to reset 'global'
+ * (per chip) blocks.
+ */
+ global_bits2 =
+ MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU |
+ MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE;
+ /* Don't reset the following blocks */
not_reset_mask1 =
MISC_REGISTERS_RESET_REG_1_RST_HC |
MISC_REGISTERS_RESET_REG_1_RST_PXPV |
MISC_REGISTERS_RESET_REG_1_RST_PXP;
not_reset_mask2 =
- MISC_REGISTERS_RESET_REG_2_RST_MDIO |
+ MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO |
MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE |
MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE |
MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE |
MISC_REGISTERS_RESET_REG_2_RST_RBCN |
MISC_REGISTERS_RESET_REG_2_RST_GRC |
MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE |
- MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B;
+ MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B |
+ MISC_REGISTERS_RESET_REG_2_RST_ATC |
+ MISC_REGISTERS_RESET_REG_2_PGLC;
+ /*
+ * Keep the following blocks in reset:
+ * - all xxMACs are handled by the bnx2x_link code.
+ */
+ stay_reset2 =
+ MISC_REGISTERS_RESET_REG_2_RST_BMAC0 |
+ MISC_REGISTERS_RESET_REG_2_RST_BMAC1 |
+ MISC_REGISTERS_RESET_REG_2_RST_EMAC0 |
+ MISC_REGISTERS_RESET_REG_2_RST_EMAC1 |
+ MISC_REGISTERS_RESET_REG_2_UMAC0 |
+ MISC_REGISTERS_RESET_REG_2_UMAC1 |
+ MISC_REGISTERS_RESET_REG_2_XMAC |
+ MISC_REGISTERS_RESET_REG_2_XMAC_SOFT;
+
+ /* Full reset masks according to the chip */
reset_mask1 = 0xffffffff;
if (CHIP_IS_E1(bp))
reset_mask2 = 0xffff;
- else
+ else if (CHIP_IS_E1H(bp))
reset_mask2 = 0x1ffff;
+ else if (CHIP_IS_E2(bp))
+ reset_mask2 = 0xfffff;
+ else /* CHIP_IS_E3 */
+ reset_mask2 = 0x3ffffff;
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
- reset_mask1 & (~not_reset_mask1));
+ /* Don't reset global blocks unless we need to */
+ if (!global)
+ reset_mask2 &= ~global_bits2;
+
+ /*
+ * In case of attention in the QM, we need to reset PXP
+ * (MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR) before QM
+ * because otherwise QM reset would release 'close the gates' shortly
+ * before resetting the PXP, then the PSWRQ would send a write
+ * request to PGLUE. Then when PXP is reset, PGLUE would try to
+ * read the payload data from PSWWR, but PSWWR would not
+ * respond. The write queue in PGLUE would stuck, dmae commands
+ * would not return. Therefore it's important to reset the second
+ * reset register (containing the
+ * MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR bit) before the
+ * first one (containing the MISC_REGISTERS_RESET_REG_1_RST_QM
+ * bit).
+ */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
reset_mask2 & (~not_reset_mask2));
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+ reset_mask1 & (~not_reset_mask1));
+
+ barrier();
+ mmiowb();
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ reset_mask2 & (~stay_reset2));
+
barrier();
mmiowb();
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, reset_mask1);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, reset_mask2);
mmiowb();
}
-static int bnx2x_process_kill(struct bnx2x *bp)
+/**
+ * bnx2x_er_poll_igu_vq - poll for pending writes bit.
+ * It should get cleared in no more than 1s.
+ *
+ * @bp: driver handle
+ *
+ * It should get cleared in no more than 1s. Returns 0 if
+ * pending writes bit gets cleared.
+ */
+static int bnx2x_er_poll_igu_vq(struct bnx2x *bp)
+{
+ u32 cnt = 1000;
+ u32 pend_bits = 0;
+
+ do {
+ pend_bits = REG_RD(bp, IGU_REG_PENDING_BITS_STATUS);
+
+ if (pend_bits == 0)
+ break;
+
+ usleep_range(1000, 1000);
+ } while (cnt-- > 0);
+
+ if (cnt <= 0) {
+ BNX2X_ERR("Still pending IGU requests pend_bits=%x!\n",
+ pend_bits);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int bnx2x_process_kill(struct bnx2x *bp, bool global)
{
int cnt = 1000;
u32 val = 0;
@@ -7403,7 +8134,7 @@ static int bnx2x_process_kill(struct bnx2x *bp)
((port_is_idle_1 & 0x1) == 0x1) &&
(pgl_exp_rom2 == 0xffffffff))
break;
- msleep(1);
+ usleep_range(1000, 1000);
} while (cnt-- > 0);
if (cnt <= 0) {
@@ -7423,6 +8154,11 @@ static int bnx2x_process_kill(struct bnx2x *bp)
/* Close gates #2, #3 and #4 */
bnx2x_set_234_gates(bp, true);
+ /* Poll for IGU VQs for 57712 and newer chips */
+ if (!CHIP_IS_E1x(bp) && bnx2x_er_poll_igu_vq(bp))
+ return -EAGAIN;
+
+
/* TBD: Indicate that "process kill" is in progress to MCP */
/* Clear "unprepared" bit */
@@ -7435,25 +8171,28 @@ static int bnx2x_process_kill(struct bnx2x *bp)
/* Wait for 1ms to empty GLUE and PCI-E core queues,
* PSWHST, GRC and PSWRD Tetris buffer.
*/
- msleep(1);
+ usleep_range(1000, 1000);
/* Prepare to chip reset: */
/* MCP */
- bnx2x_reset_mcp_prep(bp, &val);
+ if (global)
+ bnx2x_reset_mcp_prep(bp, &val);
/* PXP */
bnx2x_pxp_prep(bp);
barrier();
/* reset the chip */
- bnx2x_process_kill_chip_reset(bp);
+ bnx2x_process_kill_chip_reset(bp, global);
barrier();
/* Recover after reset: */
/* MCP */
- if (bnx2x_reset_mcp_comp(bp, val))
+ if (global && bnx2x_reset_mcp_comp(bp, val))
return -EAGAIN;
+ /* TBD: Add resetting the NO_MCP mode DB here */
+
/* PXP */
bnx2x_pxp_prep(bp);
@@ -7466,43 +8205,85 @@ static int bnx2x_process_kill(struct bnx2x *bp)
return 0;
}
-static int bnx2x_leader_reset(struct bnx2x *bp)
+int bnx2x_leader_reset(struct bnx2x *bp)
{
int rc = 0;
+ bool global = bnx2x_reset_is_global(bp);
+
/* Try to recover after the failure */
- if (bnx2x_process_kill(bp)) {
- printk(KERN_ERR "%s: Something bad had happen! Aii!\n",
- bp->dev->name);
+ if (bnx2x_process_kill(bp, global)) {
+ netdev_err(bp->dev, "Something bad had happen on engine %d! "
+ "Aii!\n", BP_PATH(bp));
rc = -EAGAIN;
goto exit_leader_reset;
}
- /* Clear "reset is in progress" bit and update the driver state */
+ /*
+ * Clear RESET_IN_PROGRES and RESET_GLOBAL bits and update the driver
+ * state.
+ */
bnx2x_set_reset_done(bp);
- bp->recovery_state = BNX2X_RECOVERY_DONE;
+ if (global)
+ bnx2x_clear_reset_global(bp);
exit_leader_reset:
bp->is_leader = 0;
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08);
- smp_wmb();
+ bnx2x_release_leader_lock(bp);
+ smp_mb();
return rc;
}
-/* Assumption: runs under rtnl lock. This together with the fact
- * that it's called only from bnx2x_reset_task() ensure that it
+static inline void bnx2x_recovery_failed(struct bnx2x *bp)
+{
+ netdev_err(bp->dev, "Recovery has failed. Power cycle is needed.\n");
+
+ /* Disconnect this device */
+ netif_device_detach(bp->dev);
+
+ /*
+ * Block ifup for all function on this engine until "process kill"
+ * or power cycle.
+ */
+ bnx2x_set_reset_in_progress(bp);
+
+ /* Shut down the power */
+ bnx2x_set_power_state(bp, PCI_D3hot);
+
+ bp->recovery_state = BNX2X_RECOVERY_FAILED;
+
+ smp_mb();
+}
+
+/*
+ * Assumption: runs under rtnl lock. This together with the fact
+ * that it's called only from bnx2x_sp_rtnl() ensure that it
* will never be called when netif_running(bp->dev) is false.
*/
static void bnx2x_parity_recover(struct bnx2x *bp)
{
+ bool global = false;
+
DP(NETIF_MSG_HW, "Handling parity\n");
while (1) {
switch (bp->recovery_state) {
case BNX2X_RECOVERY_INIT:
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n");
+ bnx2x_chk_parity_attn(bp, &global, false);
+
/* Try to get a LEADER_LOCK HW lock */
- if (bnx2x_trylock_hw_lock(bp,
- HW_LOCK_RESOURCE_RESERVED_08))
+ if (bnx2x_trylock_leader_lock(bp)) {
+ bnx2x_set_reset_in_progress(bp);
+ /*
+ * Check if there is a global attention and if
+ * there was a global attention, set the global
+ * reset bit.
+ */
+
+ if (global)
+ bnx2x_set_reset_global(bp);
+
bp->is_leader = 1;
+ }
/* Stop the driver */
/* If interface has been removed - break */
@@ -7510,21 +8291,47 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
return;
bp->recovery_state = BNX2X_RECOVERY_WAIT;
- /* Ensure "is_leader" and "recovery_state"
- * update values are seen on other CPUs
+
+ /*
+ * Reset MCP command sequence number and MCP mail box
+ * sequence as we are going to reset the MCP.
+ */
+ if (global) {
+ bp->fw_seq = 0;
+ bp->fw_drv_pulse_wr_seq = 0;
+ }
+
+ /* Ensure "is_leader", MCP command sequence and
+ * "recovery_state" update values are seen on other
+ * CPUs.
*/
- smp_wmb();
+ smp_mb();
break;
case BNX2X_RECOVERY_WAIT:
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
if (bp->is_leader) {
- u32 load_counter = bnx2x_get_load_cnt(bp);
- if (load_counter) {
+ int other_engine = BP_PATH(bp) ? 0 : 1;
+ u32 other_load_counter =
+ bnx2x_get_load_cnt(bp, other_engine);
+ u32 load_counter =
+ bnx2x_get_load_cnt(bp, BP_PATH(bp));
+ global = bnx2x_reset_is_global(bp);
+
+ /*
+ * In case of a parity in a global block, let
+ * the first leader that performs a
+ * leader_reset() reset the global blocks in
+ * order to clear global attentions. Otherwise
+ * the the gates will remain closed for that
+ * engine.
+ */
+ if (load_counter ||
+ (global && other_load_counter)) {
/* Wait until all other functions get
* down.
*/
- schedule_delayed_work(&bp->reset_task,
+ schedule_delayed_work(&bp->sp_rtnl_task,
HZ/10);
return;
} else {
@@ -7533,37 +8340,27 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
* normal. In any case it's an exit
* point for a leader.
*/
- if (bnx2x_leader_reset(bp) ||
- bnx2x_nic_load(bp, LOAD_NORMAL)) {
- printk(KERN_ERR"%s: Recovery "
- "has failed. Power cycle is "
- "needed.\n", bp->dev->name);
- /* Disconnect this device */
- netif_device_detach(bp->dev);
- /* Block ifup for all function
- * of this ASIC until
- * "process kill" or power
- * cycle.
- */
- bnx2x_set_reset_in_progress(bp);
- /* Shut down the power */
- bnx2x_set_power_state(bp,
- PCI_D3hot);
+ if (bnx2x_leader_reset(bp)) {
+ bnx2x_recovery_failed(bp);
return;
}
- return;
+ /* If we are here, means that the
+ * leader has succeeded and doesn't
+ * want to be a leader any more. Try
+ * to continue as a none-leader.
+ */
+ break;
}
} else { /* non-leader */
- if (!bnx2x_reset_is_done(bp)) {
+ if (!bnx2x_reset_is_done(bp, BP_PATH(bp))) {
/* Try to get a LEADER_LOCK HW lock as
* long as a former leader may have
* been unloaded by the user or
* released a leadership by another
* reason.
*/
- if (bnx2x_trylock_hw_lock(bp,
- HW_LOCK_RESOURCE_RESERVED_08)) {
+ if (bnx2x_trylock_leader_lock(bp)) {
/* I'm a leader now! Restart a
* switch case.
*/
@@ -7571,18 +8368,30 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
break;
}
- schedule_delayed_work(&bp->reset_task,
+ schedule_delayed_work(&bp->sp_rtnl_task,
HZ/10);
return;
- } else { /* A leader has completed
- * the "process kill". It's an exit
- * point for a non-leader.
- */
- bnx2x_nic_load(bp, LOAD_NORMAL);
- bp->recovery_state =
- BNX2X_RECOVERY_DONE;
- smp_wmb();
+ } else {
+ /*
+ * If there was a global attention, wait
+ * for it to be cleared.
+ */
+ if (bnx2x_reset_is_global(bp)) {
+ schedule_delayed_work(
+ &bp->sp_rtnl_task,
+ HZ/10);
+ return;
+ }
+
+ if (bnx2x_nic_load(bp, LOAD_NORMAL))
+ bnx2x_recovery_failed(bp);
+ else {
+ bp->recovery_state =
+ BNX2X_RECOVERY_DONE;
+ smp_mb();
+ }
+
return;
}
}
@@ -7595,35 +8404,92 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
/* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is
* scheduled on a general queue in order to prevent a dead lock.
*/
-static void bnx2x_reset_task(struct work_struct *work)
+static void bnx2x_sp_rtnl_task(struct work_struct *work)
{
- struct bnx2x *bp = container_of(work, struct bnx2x, reset_task.work);
-
-#ifdef BNX2X_STOP_ON_ERROR
- BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
- " so reset not done to allow debug dump,\n"
- KERN_ERR " you will need to reboot when done\n");
- return;
-#endif
+ struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work);
rtnl_lock();
if (!netif_running(bp->dev))
- goto reset_task_exit;
+ goto sp_rtnl_exit;
+
+ /* if stop on error is defined no recovery flows should be executed */
+#ifdef BNX2X_STOP_ON_ERROR
+ BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined "
+ "so reset not done to allow debug dump,\n"
+ "you will need to reboot when done\n");
+ goto sp_rtnl_not_reset;
+#endif
+
+ if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) {
+ /*
+ * Clear all pending SP commands as we are going to reset the
+ * function anyway.
+ */
+ bp->sp_rtnl_state = 0;
+ smp_mb();
- if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE))
bnx2x_parity_recover(bp);
- else {
+
+ goto sp_rtnl_exit;
+ }
+
+ if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state)) {
+ /*
+ * Clear all pending SP commands as we are going to reset the
+ * function anyway.
+ */
+ bp->sp_rtnl_state = 0;
+ smp_mb();
+
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_NORMAL);
+
+ goto sp_rtnl_exit;
}
+#ifdef BNX2X_STOP_ON_ERROR
+sp_rtnl_not_reset:
+#endif
+ if (test_and_clear_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
+ bnx2x_setup_tc(bp->dev, bp->dcbx_port_params.ets.num_of_cos);
-reset_task_exit:
+sp_rtnl_exit:
rtnl_unlock();
}
/* end of nic load/unload */
+static void bnx2x_period_task(struct work_struct *work)
+{
+ struct bnx2x *bp = container_of(work, struct bnx2x, period_task.work);
+
+ if (!netif_running(bp->dev))
+ goto period_task_exit;
+
+ if (CHIP_REV_IS_SLOW(bp)) {
+ BNX2X_ERR("period task called on emulation, ignoring\n");
+ goto period_task_exit;
+ }
+
+ bnx2x_acquire_phy_lock(bp);
+ /*
+ * The barrier is needed to ensure the ordering between the writing to
+ * the bp->port.pmf in the bnx2x_nic_load() or bnx2x_pmf_update() and
+ * the reading here.
+ */
+ smp_mb();
+ if (bp->port.pmf) {
+ bnx2x_period_func(&bp->link_params, &bp->link_vars);
+
+ /* Re-queue task in 1 sec */
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 1*HZ);
+ }
+
+ bnx2x_release_phy_lock(bp);
+period_task_exit:
+ return;
+}
+
/*
* Init service functions
*/
@@ -7681,8 +8547,8 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
/* save our pf_num */
int orig_pf_num = bp->pf_num;
- u32 swap_en;
- u32 swap_val;
+ int port;
+ u32 swap_en, swap_val, value;
/* clear the UNDI indication */
REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
@@ -7717,21 +8583,19 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
bnx2x_undi_int_disable(bp);
+ port = BP_PORT(bp);
/* close input traffic and wait for it */
/* Do not rcv packets to BRB */
- REG_WR(bp,
- (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK :
- NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
+ REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
+ NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
/* Do not direct rcv packets that are not for MCP to
* the BRB */
- REG_WR(bp,
- (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_NOT_MCP :
- NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
+ REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
+ NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
/* clear AEU */
- REG_WR(bp,
- (BP_PORT(bp) ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
- MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
+ REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
+ MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
msleep(10);
/* save NIG port swap info */
@@ -7741,9 +8605,17 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
REG_WR(bp,
GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
0xd3ffffff);
+
+ value = 0x1400;
+ if (CHIP_IS_E3(bp)) {
+ value |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+ value |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+ }
+
REG_WR(bp,
GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
- 0x1403);
+ value);
+
/* take the NIG out of reset and restore swap values */
REG_WR(bp,
GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
@@ -7784,7 +8656,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
/* Set doorbell size */
bp->db_size = (1 << BNX2X_DB_SHIFT);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
if ((val & 1) == 0)
val = REG_RD(bp, MISC_REG_PORT4MODE_EN);
@@ -7804,16 +8676,6 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
bp->pfid = bp->pf_num; /* 0..7 */
}
- /*
- * set base FW non-default (fast path) status block id, this value is
- * used to initialize the fw_sb_id saved on the fp/queue structure to
- * determine the id used by the FW.
- */
- if (CHIP_IS_E1x(bp))
- bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x;
- else /* E2 */
- bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E2;
-
bp->link_params.chip_id = bp->common.chip_id;
BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
@@ -7825,13 +8687,15 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
}
val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
- bp->common.flash_size = (NVRAM_1MB_SIZE <<
+ bp->common.flash_size = (BNX2X_NVRAM_1MB_SIZE <<
(val & MCPR_NVM_CFG4_FLASH_SIZE));
BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
bp->common.flash_size, bp->common.flash_size);
bnx2x_init_shmem(bp);
+
+
bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ?
MISC_REG_GENERIC_CR_1 :
MISC_REG_GENERIC_CR_0));
@@ -7880,6 +8744,10 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
(val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
+ bp->link_params.feature_config_flags |=
+ (val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
+ FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
+
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG;
@@ -7904,14 +8772,11 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
int vn = BP_E1HVN(bp);
int igu_sb_id;
u32 val;
- u8 fid;
+ u8 fid, igu_sb_cnt = 0;
bp->igu_base_sb = 0xff;
- bp->igu_sb_cnt = 0;
if (CHIP_INT_MODE_IS_BC(bp)) {
- bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
- NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
-
+ igu_sb_cnt = bp->igu_sb_cnt;
bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) *
FP_SB_MAX_E1x;
@@ -7937,13 +8802,21 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
else {
if (bp->igu_base_sb == 0xff)
bp->igu_base_sb = igu_sb_id;
- bp->igu_sb_cnt++;
+ igu_sb_cnt++;
}
}
}
- bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
- NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
- if (bp->igu_sb_cnt == 0)
+
+#ifdef CONFIG_PCI_MSI
+ /*
+ * It's expected that number of CAM entries for this functions is equal
+ * to the number evaluated based on the MSI-X table size. We want a
+ * harsh warning if these values are different!
+ */
+ WARN_ON(bp->igu_sb_cnt != igu_sb_cnt);
+#endif
+
+ if (igu_sb_cnt == 0)
BNX2X_ERR("CAM configuration error\n");
}
@@ -7991,24 +8864,25 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
return;
}
- switch (switch_cfg) {
- case SWITCH_CFG_1G:
- bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
- port*0x10);
- BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
- break;
-
- case SWITCH_CFG_10G:
- bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
- port*0x18);
- BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
- break;
-
- default:
- BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
- bp->port.link_config[0]);
- return;
+ if (CHIP_IS_E3(bp))
+ bp->port.phy_addr = REG_RD(bp, MISC_REG_WC0_CTRL_PHY_ADDR);
+ else {
+ switch (switch_cfg) {
+ case SWITCH_CFG_1G:
+ bp->port.phy_addr = REG_RD(
+ bp, NIG_REG_SERDES0_CTRL_PHY_ADDR + port*0x10);
+ break;
+ case SWITCH_CFG_10G:
+ bp->port.phy_addr = REG_RD(
+ bp, NIG_REG_XGXS0_CTRL_PHY_ADDR + port*0x18);
+ break;
+ default:
+ BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
+ bp->port.link_config[0]);
+ return;
+ }
}
+ BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
/* mask what we support according to speed_cap_mask per configuration */
for (idx = 0; idx < cfg_size; idx++) {
if (!(bp->link_params.speed_cap_mask[idx] &
@@ -8089,7 +8963,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
(ADVERTISED_10baseT_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8108,7 +8982,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
(ADVERTISED_10baseT_Half |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8126,7 +9000,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
(ADVERTISED_100baseT_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8146,7 +9020,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
(ADVERTISED_100baseT_Half |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8164,7 +9038,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
(ADVERTISED_1000baseT_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8182,7 +9056,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
(ADVERTISED_2500baseX_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8192,8 +9066,6 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
break;
case PORT_FEATURE_LINK_SPEED_10G_CX4:
- case PORT_FEATURE_LINK_SPEED_10G_KX4:
- case PORT_FEATURE_LINK_SPEED_10G_KR:
if (bp->port.supported[idx] &
SUPPORTED_10000baseT_Full) {
bp->link_params.req_line_speed[idx] =
@@ -8202,7 +9074,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
(ADVERTISED_10000baseT_Full |
ADVERTISED_FIBRE);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8210,11 +9082,14 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
return;
}
break;
+ case PORT_FEATURE_LINK_SPEED_20G:
+ bp->link_params.req_line_speed[idx] = SPEED_20000;
+ break;
default:
- BNX2X_ERROR("NVRAM config error. "
- "BAD link speed link_config 0x%x\n",
- link_config);
+ BNX2X_ERR("NVRAM config error. "
+ "BAD link speed link_config 0x%x\n",
+ link_config);
bp->link_params.req_line_speed[idx] =
SPEED_AUTO_NEG;
bp->port.advertising[idx] =
@@ -8325,10 +9200,13 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
#ifdef BCM_CNIC
static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
{
+ int port = BP_PORT(bp);
+ int func = BP_ABS_FUNC(bp);
+
u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
- drv_lic_key[BP_PORT(bp)].max_iscsi_conn);
+ drv_lic_key[port].max_iscsi_conn);
u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
- drv_lic_key[BP_PORT(bp)].max_fcoe_conn);
+ drv_lic_key[port].max_fcoe_conn);
/* Get the number of maximum allowed iSCSI and FCoE connections */
bp->cnic_eth_dev.max_iscsi_conn =
@@ -8339,11 +9217,59 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
(max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
BNX2X_MAX_FCOE_INIT_CONN_SHIFT;
+ /* Read the WWN: */
+ if (!IS_MF(bp)) {
+ /* Port info */
+ bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].
+ fcoe_wwn_port_name_upper);
+ bp->cnic_eth_dev.fcoe_wwn_port_name_lo =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].
+ fcoe_wwn_port_name_lower);
+
+ /* Node info */
+ bp->cnic_eth_dev.fcoe_wwn_node_name_hi =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].
+ fcoe_wwn_node_name_upper);
+ bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].
+ fcoe_wwn_node_name_lower);
+ } else if (!IS_MF_SD(bp)) {
+ u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
+
+ /*
+ * Read the WWN info only if the FCoE feature is enabled for
+ * this function.
+ */
+ if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
+ /* Port info */
+ bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
+ MF_CFG_RD(bp, func_ext_config[func].
+ fcoe_wwn_port_name_upper);
+ bp->cnic_eth_dev.fcoe_wwn_port_name_lo =
+ MF_CFG_RD(bp, func_ext_config[func].
+ fcoe_wwn_port_name_lower);
+
+ /* Node info */
+ bp->cnic_eth_dev.fcoe_wwn_node_name_hi =
+ MF_CFG_RD(bp, func_ext_config[func].
+ fcoe_wwn_node_name_upper);
+ bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
+ MF_CFG_RD(bp, func_ext_config[func].
+ fcoe_wwn_node_name_lower);
+ }
+ }
+
BNX2X_DEV_INFO("max_iscsi_conn 0x%x max_fcoe_conn 0x%x\n",
bp->cnic_eth_dev.max_iscsi_conn,
bp->cnic_eth_dev.max_fcoe_conn);
- /* If mamimum allowed number of connections is zero -
+ /*
+ * If maximum allowed number of connections is zero -
* disable the feature.
*/
if (!bp->cnic_eth_dev.max_iscsi_conn)
@@ -8364,6 +9290,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
u8 *fip_mac = bp->fip_mac;
#endif
+ /* Zero primary MAC configuration */
+ memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
if (BP_NOMCP(bp)) {
BNX2X_ERROR("warning: random MAC workaround active\n");
random_ether_addr(bp->dev->dev_addr);
@@ -8385,9 +9314,10 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
iscsi_mac_addr_upper);
val = MF_CFG_RD(bp, func_ext_config[func].
iscsi_mac_addr_lower);
- BNX2X_DEV_INFO("Read iSCSI MAC: "
- "0x%x:0x%04x\n", val2, val);
bnx2x_set_mac_buf(iscsi_mac, val, val2);
+ BNX2X_DEV_INFO("Read iSCSI MAC: "
+ BNX2X_MAC_FMT"\n",
+ BNX2X_MAC_PRN_LIST(iscsi_mac));
} else
bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
@@ -8396,9 +9326,10 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
fcoe_mac_addr_upper);
val = MF_CFG_RD(bp, func_ext_config[func].
fcoe_mac_addr_lower);
- BNX2X_DEV_INFO("Read FCoE MAC to "
- "0x%x:0x%04x\n", val2, val);
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));
} else
bp->flags |= NO_FCOE_FLAG;
@@ -8416,6 +9347,12 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
val = SHMEM_RD(bp, dev_info.port_hw_config[port].
iscsi_mac_lower);
bnx2x_set_mac_buf(iscsi_mac, val, val2);
+
+ val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
+ fcoe_fip_mac_upper);
+ val = SHMEM_RD(bp, dev_info.port_hw_config[port].
+ fcoe_fip_mac_lower);
+ bnx2x_set_mac_buf(fip_mac, val, val2);
#endif
}
@@ -8423,13 +9360,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
#ifdef BCM_CNIC
- /* Set the FCoE MAC in modes other then MF_SI */
- if (!CHIP_IS_E1x(bp)) {
- if (IS_MF_SD(bp))
- memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
- else if (!IS_MF(bp))
- memcpy(fip_mac, iscsi_mac, ETH_ALEN);
- }
+ /* Set the FCoE MAC in MF_SD mode */
+ if (!CHIP_IS_E1x(bp) && IS_MF_SD(bp))
+ memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
/* Disable iSCSI if MAC configuration is
* invalid.
@@ -8447,6 +9380,13 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
memset(bp->fip_mac, 0, ETH_ALEN);
}
#endif
+
+ 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 "
+ "the appropriate network interface\n",
+ BNX2X_MAC_PRN_LIST(bp->dev->dev_addr));
}
static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
@@ -8458,27 +9398,66 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
bnx2x_get_common_hwinfo(bp);
+ /*
+ * initialize IGU parameters
+ */
if (CHIP_IS_E1x(bp)) {
bp->common.int_block = INT_BLOCK_HC;
bp->igu_dsb_id = DEF_SB_IGU_ID;
bp->igu_base_sb = 0;
- bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
- NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
} else {
bp->common.int_block = INT_BLOCK_IGU;
val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+
if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
- DP(NETIF_MSG_PROBE, "IGU Backward Compatible Mode\n");
+ int tout = 5000;
+
+ BNX2X_DEV_INFO("FORCING Normal Mode\n");
+
+ val &= ~(IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN);
+ REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION, val);
+ REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x7f);
+
+ while (tout && REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
+ tout--;
+ usleep_range(1000, 1000);
+ }
+
+ if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
+ dev_err(&bp->pdev->dev,
+ "FORCING Normal Mode failed!!!\n");
+ return -EPERM;
+ }
+ }
+
+ if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
+ BNX2X_DEV_INFO("IGU Backward Compatible Mode\n");
bp->common.int_block |= INT_BLOCK_MODE_BW_COMP;
} else
- DP(NETIF_MSG_PROBE, "IGU Normal Mode\n");
+ BNX2X_DEV_INFO("IGU Normal Mode\n");
bnx2x_get_igu_cam_info(bp);
}
- DP(NETIF_MSG_PROBE, "igu_dsb_id %d igu_base_sb %d igu_sb_cnt %d\n",
- bp->igu_dsb_id, bp->igu_base_sb, bp->igu_sb_cnt);
+
+ /*
+ * set base FW non-default (fast path) status block id, this value is
+ * used to initialize the fw_sb_id saved on the fp/queue structure to
+ * determine the id used by the FW.
+ */
+ if (CHIP_IS_E1x(bp))
+ bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x + BP_L_ID(bp);
+ else /*
+ * 57712 - we currently use one FW SB per IGU SB (Rx and Tx of
+ * the same queue are indicated on the same IGU SB). So we prefer
+ * FW and IGU SBs to be the same value.
+ */
+ bp->base_fw_ndsb = bp->igu_base_sb;
+
+ BNX2X_DEV_INFO("igu_dsb_id %d igu_base_sb %d igu_sb_cnt %d\n"
+ "base_fw_ndsb %d\n", bp->igu_dsb_id, bp->igu_base_sb,
+ bp->igu_sb_cnt, bp->base_fw_ndsb);
/*
* Initialize MF configuration
@@ -8489,10 +9468,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
vn = BP_E1HVN(bp);
if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
- DP(NETIF_MSG_PROBE,
- "shmem2base 0x%x, size %d, mfcfg offset %d\n",
- bp->common.shmem2_base, SHMEM2_RD(bp, size),
- (u32)offsetof(struct shmem2_region, mf_cfg_addr));
+ BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n",
+ bp->common.shmem2_base, SHMEM2_RD(bp, size),
+ (u32)offsetof(struct shmem2_region, mf_cfg_addr));
+
if (SHMEM2_HAS(bp, mf_cfg_addr))
bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr);
else
@@ -8523,8 +9502,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
bp->mf_config[vn] = MF_CFG_RD(bp,
func_mf_config[func].config);
} else
- DP(NETIF_MSG_PROBE, "illegal MAC "
- "address for SI\n");
+ BNX2X_DEV_INFO("illegal MAC address "
+ "for SI\n");
break;
case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED:
/* get OV configuration */
@@ -8537,14 +9516,12 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
bp->mf_config[vn] = MF_CFG_RD(bp,
func_mf_config[func].config);
} else
- DP(NETIF_MSG_PROBE, "illegal OV for "
- "SD\n");
+ BNX2X_DEV_INFO("illegal OV for SD\n");
break;
default:
/* Unknown configuration: reset mf_config */
bp->mf_config[vn] = 0;
- DP(NETIF_MSG_PROBE, "Unknown MF mode 0x%x\n",
- val);
+ BNX2X_DEV_INFO("unkown MF mode 0x%x\n", val);
}
}
@@ -8557,13 +9534,16 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
FUNC_MF_CFG_E1HOV_TAG_MASK;
if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
bp->mf_ov = val;
- BNX2X_DEV_INFO("MF OV for func %d is %d"
- " (0x%04x)\n", func,
- bp->mf_ov, bp->mf_ov);
+ bp->path_has_ovlan = true;
+
+ BNX2X_DEV_INFO("MF OV for func %d is %d "
+ "(0x%04x)\n", func, bp->mf_ov,
+ bp->mf_ov);
} else {
- BNX2X_ERR("No valid MF OV for func %d,"
- " aborting\n", func);
- rc = -EPERM;
+ dev_err(&bp->pdev->dev,
+ "No valid MF OV for func %d, "
+ "aborting\n", func);
+ return -EPERM;
}
break;
case MULTI_FUNCTION_SI:
@@ -8572,31 +9552,40 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
break;
default:
if (vn) {
- BNX2X_ERR("VN %d in single function mode,"
- " aborting\n", vn);
- rc = -EPERM;
+ dev_err(&bp->pdev->dev,
+ "VN %d is in a single function mode, "
+ "aborting\n", vn);
+ return -EPERM;
}
break;
}
+ /* check if other port on the path needs ovlan:
+ * Since MF configuration is shared between ports
+ * Possible mixed modes are only
+ * {SF, SI} {SF, SD} {SD, SF} {SI, SF}
+ */
+ if (CHIP_MODE_IS_4_PORT(bp) &&
+ !bp->path_has_ovlan &&
+ !IS_MF(bp) &&
+ bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) {
+ u8 other_port = !BP_PORT(bp);
+ u8 other_func = BP_PATH(bp) + 2*other_port;
+ val = MF_CFG_RD(bp,
+ func_mf_config[other_func].e1hov_tag);
+ if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
+ bp->path_has_ovlan = true;
+ }
}
/* adjust igu_sb_cnt to MF for E1x */
if (CHIP_IS_E1x(bp) && IS_MF(bp))
bp->igu_sb_cnt /= E1HVN_MAX;
- /*
- * adjust E2 sb count: to be removed when FW will support
- * more then 16 L2 clients
- */
-#define MAX_L2_CLIENTS 16
- if (CHIP_IS_E2(bp))
- bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
- MAX_L2_CLIENTS / (IS_MF(bp) ? 4 : 1));
+ /* port info */
+ bnx2x_get_port_hwinfo(bp);
if (!BP_NOMCP(bp)) {
- bnx2x_get_port_hwinfo(bp);
-
bp->fw_seq =
(SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
@@ -8610,6 +9599,16 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
bnx2x_get_cnic_info(bp);
#endif
+ /* Get current FW pulse sequence */
+ if (!BP_NOMCP(bp)) {
+ int mb_idx = BP_FW_MB_IDX(bp);
+
+ bp->fw_drv_pulse_wr_seq =
+ (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
+ DRV_PULSE_SEQ_MASK);
+ BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
+ }
+
return rc;
}
@@ -8677,16 +9676,59 @@ out_not_found:
return;
}
+static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
+{
+ u32 flags = 0;
+
+ if (CHIP_REV_IS_FPGA(bp))
+ SET_FLAGS(flags, MODE_FPGA);
+ else if (CHIP_REV_IS_EMUL(bp))
+ SET_FLAGS(flags, MODE_EMUL);
+ else
+ SET_FLAGS(flags, MODE_ASIC);
+
+ if (CHIP_MODE_IS_4_PORT(bp))
+ SET_FLAGS(flags, MODE_PORT4);
+ else
+ SET_FLAGS(flags, MODE_PORT2);
+
+ if (CHIP_IS_E2(bp))
+ SET_FLAGS(flags, MODE_E2);
+ else if (CHIP_IS_E3(bp)) {
+ SET_FLAGS(flags, MODE_E3);
+ if (CHIP_REV(bp) == CHIP_REV_Ax)
+ SET_FLAGS(flags, MODE_E3_A0);
+ else /*if (CHIP_REV(bp) == CHIP_REV_Bx)*/
+ SET_FLAGS(flags, MODE_E3_B0 | MODE_COS3);
+ }
+
+ if (IS_MF(bp)) {
+ SET_FLAGS(flags, MODE_MF);
+ switch (bp->mf_mode) {
+ case MULTI_FUNCTION_SD:
+ SET_FLAGS(flags, MODE_MF_SD);
+ break;
+ case MULTI_FUNCTION_SI:
+ SET_FLAGS(flags, MODE_MF_SI);
+ break;
+ }
+ } else
+ SET_FLAGS(flags, MODE_SF);
+
+#if defined(__LITTLE_ENDIAN)
+ SET_FLAGS(flags, MODE_LITTLE_ENDIAN);
+#else /*(__BIG_ENDIAN)*/
+ SET_FLAGS(flags, MODE_BIG_ENDIAN);
+#endif
+ INIT_MODE_FLAGS(bp) = flags;
+}
+
static int __devinit bnx2x_init_bp(struct bnx2x *bp)
{
int func;
int timer_interval;
int rc;
- /* Disable interrupt handling until HW is initialized */
- atomic_set(&bp->intr_sem, 1);
- smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
mutex_init(&bp->port.phy_mutex);
mutex_init(&bp->fw_mb_mutex);
spin_lock_init(&bp->stats_lock);
@@ -8695,12 +9737,17 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
#endif
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
- INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task);
-
+ INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
+ INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
rc = bnx2x_get_hwinfo(bp);
+ if (rc)
+ return rc;
- if (!rc)
- rc = bnx2x_alloc_mem_bp(bp);
+ bnx2x_set_modes_bitmap(bp);
+
+ rc = bnx2x_alloc_mem_bp(bp);
+ if (rc)
+ return rc;
bnx2x_read_fwinfo(bp);
@@ -8718,7 +9765,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
"must load devices in order!\n");
bp->multi_mode = multi_mode;
- bp->int_mode = int_mode;
/* Set TPA flags */
if (disable_tpa) {
@@ -8754,6 +9800,21 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
bnx2x_dcbx_init_params(bp);
+#ifdef BCM_CNIC
+ if (CHIP_IS_E1x(bp))
+ bp->cnic_base_cl_id = FP_SB_MAX_E1x;
+ else
+ bp->cnic_base_cl_id = FP_SB_MAX_E2;
+#endif
+
+ /* multiple tx priority */
+ if (CHIP_IS_E1x(bp))
+ bp->max_cos = BNX2X_MULTI_TX_COS_E1X;
+ if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp))
+ bp->max_cos = BNX2X_MULTI_TX_COS_E2_E3A0;
+ if (CHIP_IS_E3B0(bp))
+ bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
+
return rc;
}
@@ -8762,49 +9823,70 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
* General service functions
****************************************************************************/
+/*
+ * net_device service functions
+ */
+
/* called with rtnl_lock */
static int bnx2x_open(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
+ bool global = false;
+ int other_engine = BP_PATH(bp) ? 0 : 1;
+ u32 other_load_counter, load_counter;
netif_carrier_off(dev);
bnx2x_set_power_state(bp, PCI_D0);
- if (!bnx2x_reset_is_done(bp)) {
+ other_load_counter = bnx2x_get_load_cnt(bp, other_engine);
+ load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp));
+
+ /*
+ * If parity had happen during the unload, then attentions
+ * and/or RECOVERY_IN_PROGRES may still be set. In this case we
+ * want the first function loaded on the current engine to
+ * complete the recovery.
+ */
+ if (!bnx2x_reset_is_done(bp, BP_PATH(bp)) ||
+ bnx2x_chk_parity_attn(bp, &global, true))
do {
- /* Reset MCP mail box sequence if there is on going
- * recovery
+ /*
+ * If there are attentions and they are in a global
+ * blocks, set the GLOBAL_RESET bit regardless whether
+ * it will be this function that will complete the
+ * recovery or not.
*/
- bp->fw_seq = 0;
+ if (global)
+ bnx2x_set_reset_global(bp);
- /* If it's the first function to load and reset done
- * is still not cleared it may mean that. We don't
- * check the attention state here because it may have
- * already been cleared by a "common" reset but we
- * shell proceed with "process kill" anyway.
+ /*
+ * Only the first function on the current engine should
+ * try to recover in open. In case of attentions in
+ * global blocks only the first in the chip should try
+ * to recover.
*/
- if ((bnx2x_get_load_cnt(bp) == 0) &&
- bnx2x_trylock_hw_lock(bp,
- HW_LOCK_RESOURCE_RESERVED_08) &&
- (!bnx2x_leader_reset(bp))) {
- DP(NETIF_MSG_HW, "Recovered in open\n");
+ if ((!load_counter &&
+ (!global || !other_load_counter)) &&
+ bnx2x_trylock_leader_lock(bp) &&
+ !bnx2x_leader_reset(bp)) {
+ netdev_info(bp->dev, "Recovered in open\n");
break;
}
+ /* recovery has failed... */
bnx2x_set_power_state(bp, PCI_D3hot);
+ bp->recovery_state = BNX2X_RECOVERY_FAILED;
- printk(KERN_ERR"%s: Recovery flow hasn't been properly"
+ netdev_err(bp->dev, "Recovery flow hasn't been properly"
" completed yet. Try again later. If u still see this"
" message after a few retries then power cycle is"
- " required.\n", bp->dev->name);
+ " required.\n");
return -EAGAIN;
} while (0);
- }
bp->recovery_state = BNX2X_RECOVERY_DONE;
-
return bnx2x_nic_load(bp, LOAD_OPEN);
}
@@ -8815,198 +9897,126 @@ static int bnx2x_close(struct net_device *dev)
/* Unload the driver, release IRQs */
bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+
+ /* Power off */
bnx2x_set_power_state(bp, PCI_D3hot);
return 0;
}
-#define E1_MAX_UC_LIST 29
-#define E1H_MAX_UC_LIST 30
-#define E2_MAX_UC_LIST 14
-static inline u8 bnx2x_max_uc_list(struct bnx2x *bp)
+static inline int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p)
{
- if (CHIP_IS_E1(bp))
- return E1_MAX_UC_LIST;
- else if (CHIP_IS_E1H(bp))
- return E1H_MAX_UC_LIST;
- else
- return E2_MAX_UC_LIST;
-}
+ int mc_count = netdev_mc_count(bp->dev);
+ struct bnx2x_mcast_list_elem *mc_mac =
+ kzalloc(sizeof(*mc_mac) * mc_count, GFP_ATOMIC);
+ struct netdev_hw_addr *ha;
+ if (!mc_mac)
+ return -ENOMEM;
-static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp)
-{
- if (CHIP_IS_E1(bp))
- /* CAM Entries for Port0:
- * 0 - prim ETH MAC
- * 1 - BCAST MAC
- * 2 - iSCSI L2 ring ETH MAC
- * 3-31 - UC MACs
- *
- * Port1 entries are allocated the same way starting from
- * entry 32.
- */
- return 3 + 32 * BP_PORT(bp);
- else if (CHIP_IS_E1H(bp)) {
- /* CAM Entries:
- * 0-7 - prim ETH MAC for each function
- * 8-15 - iSCSI L2 ring ETH MAC for each function
- * 16 till 255 UC MAC lists for each function
- *
- * Remark: There is no FCoE support for E1H, thus FCoE related
- * MACs are not considered.
- */
- return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) +
- bnx2x_max_uc_list(bp) * BP_FUNC(bp);
- } else {
- /* CAM Entries (there is a separate CAM per engine):
- * 0-4 - prim ETH MAC for each function
- * 4-7 - iSCSI L2 ring ETH MAC for each function
- * 8-11 - FIP ucast L2 MAC for each function
- * 12-15 - ALL_ENODE_MACS mcast MAC for each function
- * 16 till 71 UC MAC lists for each function
- */
- u8 func_idx =
- (CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp));
+ INIT_LIST_HEAD(&p->mcast_list);
- return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) +
- bnx2x_max_uc_list(bp) * func_idx;
+ netdev_for_each_mc_addr(ha, bp->dev) {
+ mc_mac->mac = bnx2x_mc_addr(ha);
+ list_add_tail(&mc_mac->link, &p->mcast_list);
+ mc_mac++;
}
+
+ p->mcast_list_len = mc_count;
+
+ return 0;
+}
+
+static inline void bnx2x_free_mcast_macs_list(
+ struct bnx2x_mcast_ramrod_params *p)
+{
+ struct bnx2x_mcast_list_elem *mc_mac =
+ list_first_entry(&p->mcast_list, struct bnx2x_mcast_list_elem,
+ link);
+
+ WARN_ON(!mc_mac);
+ kfree(mc_mac);
}
-/* set uc list, do not wait as wait implies sleep and
- * set_rx_mode can be invoked from non-sleepable context.
+/**
+ * bnx2x_set_uc_list - configure a new unicast MACs list.
+ *
+ * @bp: driver handle
*
- * Instead we use the same ramrod data buffer each time we need
- * to configure a list of addresses, and use the fact that the
- * list of MACs is changed in an incremental way and that the
- * function is called under the netif_addr_lock. A temporary
- * inconsistent CAM configuration (possible in case of very fast
- * sequence of add/del/add on the host side) will shortly be
- * restored by the handler of the last ramrod.
+ * We will use zero (0) as a MAC type for these MACs.
*/
-static int bnx2x_set_uc_list(struct bnx2x *bp)
+static inline int bnx2x_set_uc_list(struct bnx2x *bp)
{
- int i = 0, old;
+ int rc;
struct net_device *dev = bp->dev;
- u8 offset = bnx2x_uc_list_cam_offset(bp);
struct netdev_hw_addr *ha;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+ struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
+ unsigned long ramrod_flags = 0;
- if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp))
- return -EINVAL;
+ /* First schedule a cleanup up of old configuration */
+ rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, false);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to schedule DELETE operations: %d\n", rc);
+ return rc;
+ }
netdev_for_each_uc_addr(ha, dev) {
- /* copy mac */
- config_cmd->config_table[i].msb_mac_addr =
- swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]);
- config_cmd->config_table[i].middle_mac_addr =
- swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]);
- config_cmd->config_table[i].lsb_mac_addr =
- swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]);
-
- config_cmd->config_table[i].vlan_id = 0;
- config_cmd->config_table[i].pf_id = BP_FUNC(bp);
- config_cmd->config_table[i].clients_bit_vector =
- cpu_to_le32(1 << BP_L_ID(bp));
-
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_SET);
-
- DP(NETIF_MSG_IFUP,
- "setting UCAST[%d] (%04x:%04x:%04x)\n", i,
- config_cmd->config_table[i].msb_mac_addr,
- config_cmd->config_table[i].middle_mac_addr,
- config_cmd->config_table[i].lsb_mac_addr);
-
- i++;
-
- /* Set uc MAC in NIG */
- bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha),
- LLH_CAM_ETH_LINE + i);
- }
- old = config_cmd->hdr.length;
- if (old > i) {
- for (; i < old; i++) {
- if (CAM_IS_INVALID(config_cmd->
- config_table[i])) {
- /* already invalidated */
- break;
- }
- /* invalidate */
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
+ rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,
+ BNX2X_UC_LIST_MAC, &ramrod_flags);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to schedule ADD operations: %d\n",
+ rc);
+ return rc;
}
}
- wmb();
-
- config_cmd->hdr.length = i;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* Mark that this ramrod doesn't use bp->set_mac_pending for
- * synchronization.
- */
- config_cmd->hdr.echo = 0;
-
- mb();
-
- return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-
+ /* Execute the pending commands */
+ __set_bit(RAMROD_CONT, &ramrod_flags);
+ return bnx2x_set_mac_one(bp, NULL, mac_obj, false /* don't care */,
+ BNX2X_UC_LIST_MAC, &ramrod_flags);
}
-void bnx2x_invalidate_uc_list(struct bnx2x *bp)
+static inline int bnx2x_set_mc_list(struct bnx2x *bp)
{
- int i;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
- int ramrod_flags = WAIT_RAMROD_COMMON;
- u8 offset = bnx2x_uc_list_cam_offset(bp);
- u8 max_list_size = bnx2x_max_uc_list(bp);
-
- for (i = 0; i < max_list_size; i++) {
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
- bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i);
- }
-
- wmb();
+ struct net_device *dev = bp->dev;
+ struct bnx2x_mcast_ramrod_params rparam = {0};
+ int rc = 0;
- config_cmd->hdr.length = max_list_size;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* We'll wait for a completion this time... */
- config_cmd->hdr.echo = 1;
+ rparam.mcast_obj = &bp->mcast_obj;
- bp->set_mac_pending = 1;
+ /* first, clear all configured multicast MACs */
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to clear multicast "
+ "configuration: %d\n", rc);
+ return rc;
+ }
- mb();
+ /* then, configure a new MACs list */
+ if (netdev_mc_count(dev)) {
+ rc = bnx2x_init_mcast_macs_list(bp, &rparam);
+ if (rc) {
+ BNX2X_ERR("Failed to create multicast MACs "
+ "list: %d\n", rc);
+ return rc;
+ }
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+ /* Now add the new MACs */
+ rc = bnx2x_config_mcast(bp, &rparam,
+ BNX2X_MCAST_CMD_ADD);
+ if (rc < 0)
+ BNX2X_ERR("Failed to set a new multicast "
+ "configuration: %d\n", rc);
- /* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
- ramrod_flags);
+ bnx2x_free_mcast_macs_list(&rparam);
+ }
+ return rc;
}
-static inline int bnx2x_set_mc_list(struct bnx2x *bp)
-{
- /* some multicasts */
- if (CHIP_IS_E1(bp)) {
- return bnx2x_set_e1_mc_list(bp);
- } else { /* E1H and newer */
- return bnx2x_set_e1h_mc_list(bp);
- }
-}
-/* called with netif_tx_lock from dev_mcast.c */
+/* If bp->state is OPEN, should be called with netif_addr_lock_bh() */
void bnx2x_set_rx_mode(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -9017,23 +10027,31 @@ void bnx2x_set_rx_mode(struct net_device *dev)
return;
}
- DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags);
+ DP(NETIF_MSG_IFUP, "dev->flags = %x\n", bp->dev->flags);
if (dev->flags & IFF_PROMISC)
rx_mode = BNX2X_RX_MODE_PROMISC;
- else if (dev->flags & IFF_ALLMULTI)
+ else if ((dev->flags & IFF_ALLMULTI) ||
+ ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
+ CHIP_IS_E1(bp)))
rx_mode = BNX2X_RX_MODE_ALLMULTI;
else {
/* some multicasts */
- if (bnx2x_set_mc_list(bp))
+ if (bnx2x_set_mc_list(bp) < 0)
rx_mode = BNX2X_RX_MODE_ALLMULTI;
- /* some unicasts */
- if (bnx2x_set_uc_list(bp))
+ if (bnx2x_set_uc_list(bp) < 0)
rx_mode = BNX2X_RX_MODE_PROMISC;
}
bp->rx_mode = rx_mode;
+
+ /* Schedule the rx_mode command */
+ if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
+ set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+ return;
+ }
+
bnx2x_set_storm_rx_mode(bp);
}
@@ -9122,10 +10140,35 @@ static const struct net_device_ops bnx2x_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2x,
#endif
+ .ndo_setup_tc = bnx2x_setup_tc,
+
+#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+ .ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn,
+#endif
};
+static inline int bnx2x_set_coherency_mask(struct bnx2x *bp)
+{
+ struct device *dev = &bp->pdev->dev;
+
+ if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
+ bp->flags |= USING_DAC_FLAG;
+ if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
+ dev_err(dev, "dma_set_coherent_mask failed, "
+ "aborting\n");
+ return -EIO;
+ }
+ } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) {
+ dev_err(dev, "System does not support DMA, aborting\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
- struct net_device *dev)
+ struct net_device *dev,
+ unsigned long board_type)
{
struct bnx2x *bp;
int rc;
@@ -9179,29 +10222,15 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
goto err_out_release;
}
- bp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (bp->pcie_cap == 0) {
- dev_err(&bp->pdev->dev,
- "Cannot find PCI Express capability, aborting\n");
+ if (!pci_is_pcie(pdev)) {
+ dev_err(&bp->pdev->dev, "Not PCI Express, aborting\n");
rc = -EIO;
goto err_out_release;
}
- if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) == 0) {
- bp->flags |= USING_DAC_FLAG;
- if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)) != 0) {
- dev_err(&bp->pdev->dev, "dma_set_coherent_mask"
- " failed, aborting\n");
- rc = -EIO;
- goto err_out_release;
- }
-
- } else if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
- dev_err(&bp->pdev->dev,
- "System does not support DMA, aborting\n");
- rc = -EIO;
+ rc = bnx2x_set_coherency_mask(bp);
+ if (rc)
goto err_out_release;
- }
dev->mem_start = pci_resource_start(pdev, 0);
dev->base_addr = dev->mem_start;
@@ -9217,16 +10246,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
goto err_out_release;
}
- bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
- min_t(u64, BNX2X_DB_SIZE(bp),
- pci_resource_len(pdev, 2)));
- if (!bp->doorbells) {
- dev_err(&bp->pdev->dev,
- "Cannot map doorbell space, aborting\n");
- rc = -ENOMEM;
- goto err_out_unmap;
- }
-
bnx2x_set_power_state(bp, PCI_D0);
/* clean indirect addresses */
@@ -9237,6 +10256,15 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0);
+ /*
+ * Enable internal target-read (in case we are probed after PF FLR).
+ * Must be done prior to any BAR read access. Only for 57712 and up
+ */
+ if (board_type != BCM57710 &&
+ board_type != BCM57711 &&
+ board_type != BCM57711E)
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
+
/* Reset the load counter */
bnx2x_clear_load_cnt(bp);
@@ -9273,16 +10301,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
return 0;
-err_out_unmap:
- if (bp->regview) {
- iounmap(bp->regview);
- bp->regview = NULL;
- }
- if (bp->doorbells) {
- iounmap(bp->doorbells);
- bp->doorbells = NULL;
- }
-
err_out_release:
if (atomic_read(&pdev->enable_cnt) == 1)
pci_release_regions(pdev);
@@ -9451,7 +10469,7 @@ int bnx2x_init_firmware(struct bnx2x *bp)
fw_file_name = FW_FILE_NAME_E1;
else if (CHIP_IS_E1H(bp))
fw_file_name = FW_FILE_NAME_E1H;
- else if (CHIP_IS_E2(bp))
+ else if (!CHIP_IS_E1x(bp))
fw_file_name = FW_FILE_NAME_E2;
else {
BNX2X_ERR("Unsupported chip revision\n");
@@ -9519,9 +10537,47 @@ request_firmware_exit:
return rc;
}
-static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count)
+static void bnx2x_release_firmware(struct bnx2x *bp)
{
- int cid_count = L2_FP_COUNT(l2_cid_count);
+ kfree(bp->init_ops_offsets);
+ kfree(bp->init_ops);
+ kfree(bp->init_data);
+ release_firmware(bp->firmware);
+}
+
+
+static struct bnx2x_func_sp_drv_ops bnx2x_func_sp_drv = {
+ .init_hw_cmn_chip = bnx2x_init_hw_common_chip,
+ .init_hw_cmn = bnx2x_init_hw_common,
+ .init_hw_port = bnx2x_init_hw_port,
+ .init_hw_func = bnx2x_init_hw_func,
+
+ .reset_hw_cmn = bnx2x_reset_common,
+ .reset_hw_port = bnx2x_reset_port,
+ .reset_hw_func = bnx2x_reset_func,
+
+ .gunzip_init = bnx2x_gunzip_init,
+ .gunzip_end = bnx2x_gunzip_end,
+
+ .init_fw = bnx2x_init_firmware,
+ .release_fw = bnx2x_release_firmware,
+};
+
+void bnx2x__init_func_obj(struct bnx2x *bp)
+{
+ /* Prepare DMAE related driver resources */
+ bnx2x_setup_dmae(bp);
+
+ bnx2x_init_func_obj(bp, &bp->func_obj,
+ bnx2x_sp(bp, func_rdata),
+ bnx2x_sp_mapping(bp, func_rdata),
+ &bnx2x_func_sp_drv);
+}
+
+/* must be called after sriov-enable */
+static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp)
+{
+ int cid_count = BNX2X_L2_CID_COUNT(bp);
#ifdef BCM_CNIC
cid_count += CNIC_CID_MAX;
@@ -9529,24 +10585,74 @@ static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count)
return roundup(cid_count, QM_CID_ROUND);
}
+/**
+ * bnx2x_get_num_none_def_sbs - return the number of none default SBs
+ *
+ * @dev: pci device
+ *
+ */
+static inline int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
+{
+ int pos;
+ u16 control;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+
+ /*
+ * If MSI-X is not supported - return number of SBs needed to support
+ * one fast path queue: one FP queue + SB for CNIC
+ */
+ if (!pos)
+ return 1 + CNIC_PRESENT;
+
+ /*
+ * The value in the PCI configuration space is the index of the last
+ * entry, namely one less than the actual size of the table, which is
+ * exactly what we want to return from this function: number of all SBs
+ * without the default SB.
+ */
+ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &control);
+ return control & PCI_MSIX_FLAGS_QSIZE;
+}
+
static int __devinit bnx2x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct net_device *dev = NULL;
struct bnx2x *bp;
int pcie_width, pcie_speed;
- int rc, cid_count;
+ int rc, max_non_def_sbs;
+ int rx_count, tx_count, rss_count;
+ /*
+ * An estimated maximum supported CoS number according to the chip
+ * version.
+ * We will try to roughly estimate the maximum number of CoSes this chip
+ * may support in order to minimize the memory allocated for Tx
+ * netdev_queue's. This number will be accurately calculated during the
+ * initialization of bp->max_cos based on the chip versions AND chip
+ * revision in the bnx2x_init_bp().
+ */
+ u8 max_cos_est = 0;
switch (ent->driver_data) {
case BCM57710:
case BCM57711:
case BCM57711E:
- cid_count = FP_SB_MAX_E1x;
+ max_cos_est = BNX2X_MULTI_TX_COS_E1X;
break;
case BCM57712:
- case BCM57712E:
- cid_count = FP_SB_MAX_E2;
+ case BCM57712_MF:
+ max_cos_est = BNX2X_MULTI_TX_COS_E2_E3A0;
+ break;
+
+ case BCM57800:
+ case BCM57800_MF:
+ case BCM57810:
+ case BCM57810_MF:
+ case BCM57840:
+ case BCM57840_MF:
+ max_cos_est = BNX2X_MULTI_TX_COS_E3B0;
break;
default:
@@ -9555,38 +10661,77 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
return -ENODEV;
}
- cid_count += NONE_ETH_CONTEXT_USE + CNIC_CONTEXT_USE;
+ max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev);
+
+ /* !!! FIXME !!!
+ * Do not allow the maximum SB count to grow above 16
+ * since Special CIDs starts from 16*BNX2X_MULTI_TX_COS=48.
+ * We will use the FP_SB_MAX_E1x macro for this matter.
+ */
+ max_non_def_sbs = min_t(int, FP_SB_MAX_E1x, max_non_def_sbs);
+
+ WARN_ON(!max_non_def_sbs);
+
+ /* Maximum number of RSS queues: one IGU SB goes to CNIC */
+ rss_count = max_non_def_sbs - CNIC_PRESENT;
+
+ /* Maximum number of netdev Rx queues: RSS + FCoE L2 */
+ rx_count = rss_count + FCOE_PRESENT;
+
+ /*
+ * Maximum number of netdev Tx queues:
+ * Maximum TSS queues * Maximum supported number of CoS + FCoE L2
+ */
+ tx_count = MAX_TXQS_PER_COS * max_cos_est + FCOE_PRESENT;
/* dev zeroed in init_etherdev */
- dev = alloc_etherdev_mq(sizeof(*bp), cid_count);
+ dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count);
if (!dev) {
dev_err(&pdev->dev, "Cannot allocate net device\n");
return -ENOMEM;
}
bp = netdev_priv(dev);
- bp->msg_enable = debug;
- pci_set_drvdata(pdev, dev);
+ DP(NETIF_MSG_DRV, "Allocated netdev with %d tx and %d rx queues\n",
+ tx_count, rx_count);
- bp->l2_cid_count = cid_count;
+ bp->igu_sb_cnt = max_non_def_sbs;
+ bp->msg_enable = debug;
+ pci_set_drvdata(pdev, dev);
- rc = bnx2x_init_dev(pdev, dev);
+ rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
if (rc < 0) {
free_netdev(dev);
return rc;
}
+ DP(NETIF_MSG_DRV, "max_non_def_sbs %d", max_non_def_sbs);
+
rc = bnx2x_init_bp(bp);
if (rc)
goto init_one_exit;
+ /*
+ * Map doorbels here as we need the real value of bp->max_cos which
+ * is initialized in bnx2x_init_bp().
+ */
+ bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
+ min_t(u64, BNX2X_DB_SIZE(bp),
+ pci_resource_len(pdev, 2)));
+ if (!bp->doorbells) {
+ dev_err(&bp->pdev->dev,
+ "Cannot map doorbell space, aborting\n");
+ rc = -ENOMEM;
+ goto init_one_exit;
+ }
+
/* calc qm_cid_count */
- bp->qm_cid_count = bnx2x_set_qm_cid_count(bp, cid_count);
+ bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
#ifdef BCM_CNIC
- /* disable FCOE L2 queue for E1x*/
- if (CHIP_IS_E1x(bp))
+ /* disable FCOE L2 queue for E1x and E3*/
+ if (CHIP_IS_E1x(bp) || CHIP_IS_E3(bp))
bp->flags |= NO_FCOE_FLAG;
#endif
@@ -9686,7 +10831,7 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
bnx2x_set_power_state(bp, PCI_D3hot);
/* Make sure RESET task is not scheduled before continuing */
- cancel_delayed_work_sync(&bp->reset_task);
+ cancel_delayed_work_sync(&bp->sp_rtnl_task);
if (bp->regview)
iounmap(bp->regview);
@@ -9713,12 +10858,17 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
bp->rx_mode = BNX2X_RX_MODE_NONE;
+#ifdef BCM_CNIC
+ bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+#endif
+ /* Stop Tx */
+ bnx2x_tx_disable(bp);
+
bnx2x_netif_stop(bp, 0);
- netif_carrier_off(bp->dev);
del_timer_sync(&bp->timer);
- bp->stats_state = STATS_STATE_DISABLED;
- DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
+
+ bnx2x_stats_handle(bp, STATS_EVENT_STOP);
/* Release IRQs */
bnx2x_free_irq(bp);
@@ -9733,6 +10883,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
bp->state = BNX2X_STATE_CLOSED;
+ netif_carrier_off(bp->dev);
+
return 0;
}
@@ -9845,8 +10997,8 @@ static void bnx2x_io_resume(struct pci_dev *pdev)
struct bnx2x *bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- printk(KERN_ERR "Handling parity error recovery. "
- "Try again later\n");
+ netdev_err(bp->dev, "Handling parity error recovery. "
+ "Try again later\n");
return;
}
@@ -9905,10 +11057,33 @@ static void __exit bnx2x_cleanup(void)
destroy_workqueue(bnx2x_wq);
}
+void bnx2x_notify_link_changed(struct bnx2x *bp)
+{
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + BP_FUNC(bp)*sizeof(u32), 1);
+}
+
module_init(bnx2x_init);
module_exit(bnx2x_cleanup);
#ifdef BCM_CNIC
+/**
+ * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
+ *
+ * @bp: driver handle
+ * @set: set or clear the CAM entry
+ *
+ * This function will wait until the ramdord completion returns.
+ * Return 0 if success, -ENODEV if ramrod doesn't return.
+ */
+static inline int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp)
+{
+ unsigned long ramrod_flags = 0;
+
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+ return bnx2x_set_mac_one(bp, bp->cnic_eth_dev.iscsi_mac,
+ &bp->iscsi_l2_mac_obj, true,
+ BNX2X_ISCSI_ETH_MAC, &ramrod_flags);
+}
/* count denotes the number of new completions we have seen */
static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
@@ -9929,23 +11104,22 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
u16 type = (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
& SPE_HDR_CONN_TYPE) >>
SPE_HDR_CONN_TYPE_SHIFT;
+ u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->hdr.conn_and_cmd_data)
+ >> SPE_HDR_CMD_ID_SHIFT) & 0xff;
/* Set validation for iSCSI L2 client before sending SETUP
* ramrod
*/
if (type == ETH_CONNECTION_TYPE) {
- u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->
- hdr.conn_and_cmd_data) >>
- SPE_HDR_CMD_ID_SHIFT) & 0xff;
-
if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP)
- bnx2x_set_ctx_validation(&bp->context.
- vcxt[BNX2X_ISCSI_ETH_CID].eth,
- HW_CID(bp, BNX2X_ISCSI_ETH_CID));
+ bnx2x_set_ctx_validation(bp, &bp->context.
+ vcxt[BNX2X_ISCSI_ETH_CID].eth,
+ BNX2X_ISCSI_ETH_CID);
}
- /* There may be not more than 8 L2 and not more than 8 L5 SPEs
- * We also check that the number of outstanding
+ /*
+ * There may be not more than 8 L2, not more than 8 L5 SPEs
+ * and in the air. We also check that number of outstanding
* COMMON ramrods is not more than the EQ and SPQ can
* accommodate.
*/
@@ -10071,18 +11245,61 @@ int bnx2x_cnic_notify(struct bnx2x *bp, int cmd)
return bnx2x_cnic_ctl_send(bp, &ctl);
}
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid)
+static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err)
{
- struct cnic_ctl_info ctl;
+ struct cnic_ctl_info ctl = {0};
/* first we tell CNIC and only then we count this as a completion */
ctl.cmd = CNIC_CTL_COMPLETION_CMD;
ctl.data.comp.cid = cid;
+ ctl.data.comp.error = err;
bnx2x_cnic_ctl_send_bh(bp, &ctl);
bnx2x_cnic_sp_post(bp, 0);
}
+
+/* Called with netif_addr_lock_bh() taken.
+ * Sets an rx_mode config for an iSCSI ETH client.
+ * Doesn't block.
+ * Completion should be checked outside.
+ */
+static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start)
+{
+ unsigned long accept_flags = 0, ramrod_flags = 0;
+ u8 cl_id = bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
+ int sched_state = BNX2X_FILTER_ISCSI_ETH_STOP_SCHED;
+
+ if (start) {
+ /* Start accepting on iSCSI L2 ring. Accept all multicasts
+ * because it's the only way for UIO Queue to accept
+ * multicasts (in non-promiscuous mode only one Queue per
+ * function will receive multicast packets (leading in our
+ * case).
+ */
+ __set_bit(BNX2X_ACCEPT_UNICAST, &accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags);
+ __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+ /* Clear STOP_PENDING bit if START is requested */
+ clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &bp->sp_state);
+
+ sched_state = BNX2X_FILTER_ISCSI_ETH_START_SCHED;
+ } else
+ /* Clear START_PENDING bit if STOP is requested */
+ clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &bp->sp_state);
+
+ if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
+ set_bit(sched_state, &bp->sp_state);
+ else {
+ __set_bit(RAMROD_RX, &ramrod_flags);
+ bnx2x_set_q_rx_mode(bp, cl_id, 0, accept_flags, 0,
+ ramrod_flags);
+ }
+}
+
+
static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -10106,45 +11323,65 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
/* rtnl_lock is held. */
case DRV_CTL_START_L2_CMD: {
- u32 cli = ctl->data.ring.client_id;
-
- /* Clear FCoE FIP and ALL ENODE MACs addresses first */
- bnx2x_del_fcoe_eth_macs(bp);
+ struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+ unsigned long sp_bits = 0;
+
+ /* Configure the iSCSI classification object */
+ bnx2x_init_mac_obj(bp, &bp->iscsi_l2_mac_obj,
+ cp->iscsi_l2_client_id,
+ cp->iscsi_l2_cid, BP_FUNC(bp),
+ bnx2x_sp(bp, mac_rdata),
+ bnx2x_sp_mapping(bp, mac_rdata),
+ BNX2X_FILTER_MAC_PENDING,
+ &bp->sp_state, BNX2X_OBJ_TYPE_RX,
+ &bp->macs_pool);
/* Set iSCSI MAC address */
- bnx2x_set_iscsi_eth_mac_addr(bp, 1);
+ rc = bnx2x_set_iscsi_eth_mac_addr(bp);
+ if (rc)
+ break;
mmiowb();
barrier();
- /* Start accepting on iSCSI L2 ring. Accept all multicasts
- * because it's the only way for UIO Client to accept
- * multicasts (in non-promiscuous mode only one Client per
- * function will receive multicast packets (leading in our
- * case).
- */
- bnx2x_rxq_set_mac_filters(bp, cli,
- BNX2X_ACCEPT_UNICAST |
- BNX2X_ACCEPT_BROADCAST |
- BNX2X_ACCEPT_ALL_MULTICAST);
- storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+ /* Start accepting on iSCSI L2 ring */
+
+ netif_addr_lock_bh(dev);
+ bnx2x_set_iscsi_eth_rx_mode(bp, true);
+ netif_addr_unlock_bh(dev);
+
+ /* bits to wait on */
+ __set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
+ __set_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &sp_bits);
+
+ if (!bnx2x_wait_sp_comp(bp, sp_bits))
+ BNX2X_ERR("rx_mode completion timed out!\n");
break;
}
/* rtnl_lock is held. */
case DRV_CTL_STOP_L2_CMD: {
- u32 cli = ctl->data.ring.client_id;
+ unsigned long sp_bits = 0;
/* Stop accepting on iSCSI L2 ring */
- bnx2x_rxq_set_mac_filters(bp, cli, BNX2X_ACCEPT_NONE);
- storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+ netif_addr_lock_bh(dev);
+ bnx2x_set_iscsi_eth_rx_mode(bp, false);
+ netif_addr_unlock_bh(dev);
+
+ /* bits to wait on */
+ __set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
+ __set_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &sp_bits);
+
+ if (!bnx2x_wait_sp_comp(bp, sp_bits))
+ BNX2X_ERR("rx_mode completion timed out!\n");
mmiowb();
barrier();
/* Unset iSCSI L2 MAC */
- bnx2x_set_iscsi_eth_mac_addr(bp, 0);
+ rc = bnx2x_del_all_macs(bp, &bp->iscsi_l2_mac_obj,
+ BNX2X_ISCSI_ETH_MAC, true);
break;
}
case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: {
@@ -10156,11 +11393,6 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
break;
}
- case DRV_CTL_ISCSI_STOPPED_CMD: {
- bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_ISCSI_STOPPED);
- break;
- }
-
default:
BNX2X_ERR("unknown command %x\n", ctl->cmd);
rc = -EINVAL;
@@ -10181,13 +11413,13 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp)
cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
}
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e2_sb;
else
cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e1x_sb;
- cp->irq_arr[0].status_blk_num = CNIC_SB_ID(bp);
- cp->irq_arr[0].status_blk_num2 = CNIC_IGU_SB_ID(bp);
+ cp->irq_arr[0].status_blk_num = bnx2x_cnic_fw_sb_id(bp);
+ cp->irq_arr[0].status_blk_num2 = bnx2x_cnic_igu_sb_id(bp);
cp->irq_arr[1].status_blk = bp->def_status_blk;
cp->irq_arr[1].status_blk_num = DEF_SB_ID;
cp->irq_arr[1].status_blk_num2 = DEF_SB_IGU_ID;
@@ -10204,9 +11436,6 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
if (ops == NULL)
return -EINVAL;
- if (atomic_read(&bp->intr_sem) != 0)
- return -EBUSY;
-
bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!bp->cnic_kwq)
return -ENOMEM;
@@ -10221,7 +11450,7 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
bp->cnic_data = data;
cp->num_irq = 0;
- cp->drv_state = CNIC_DRV_STATE_REGD;
+ cp->drv_state |= CNIC_DRV_STATE_REGD;
cp->iro_arr = bp->iro_arr;
bnx2x_setup_cnic_irq_info(bp);
@@ -10275,8 +11504,8 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
cp->drv_register_cnic = bnx2x_register_cnic;
cp->drv_unregister_cnic = bnx2x_unregister_cnic;
cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID;
- cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID +
- BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
+ cp->iscsi_l2_client_id =
+ bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
if (NO_ISCSI_OOO(bp))
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h
index 86bba25d2d3f..02461fef8751 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/bnx2x/bnx2x_reg.h
@@ -32,7 +32,11 @@
/* [R 1] ATC initalization done */
#define ATC_REG_ATC_INIT_DONE 0x1100bc
/* [RC 6] Interrupt register #0 read clear */
-#define ATC_REG_ATC_INT_STS_CLR 0x1101c0
+#define ATC_REG_ATC_INT_STS_CLR 0x1101c0
+/* [RW 5] Parity mask register #0 read/write */
+#define ATC_REG_ATC_PRTY_MASK 0x1101d8
+/* [RC 5] Parity register #0 read clear */
+#define ATC_REG_ATC_PRTY_STS_CLR 0x1101d0
/* [RW 19] Interrupt mask register #0 read/write */
#define BRB1_REG_BRB1_INT_MASK 0x60128
/* [R 19] Interrupt register #0 read */
@@ -54,16 +58,20 @@
/* [RW 10] The number of free blocks below which the full signal to class 0
* is asserted */
#define BRB1_REG_FULL_0_XOFF_THRESHOLD_0 0x601d0
-/* [RW 10] The number of free blocks above which the full signal to class 0
+#define BRB1_REG_FULL_0_XOFF_THRESHOLD_1 0x60230
+/* [RW 11] The number of free blocks above which the full signal to class 0
* is de-asserted */
#define BRB1_REG_FULL_0_XON_THRESHOLD_0 0x601d4
-/* [RW 10] The number of free blocks below which the full signal to class 1
+#define BRB1_REG_FULL_0_XON_THRESHOLD_1 0x60234
+/* [RW 11] The number of free blocks below which the full signal to class 1
* is asserted */
#define BRB1_REG_FULL_1_XOFF_THRESHOLD_0 0x601d8
-/* [RW 10] The number of free blocks above which the full signal to class 1
+#define BRB1_REG_FULL_1_XOFF_THRESHOLD_1 0x60238
+/* [RW 11] The number of free blocks above which the full signal to class 1
* is de-asserted */
#define BRB1_REG_FULL_1_XON_THRESHOLD_0 0x601dc
-/* [RW 10] The number of free blocks below which the full signal to the LB
+#define BRB1_REG_FULL_1_XON_THRESHOLD_1 0x6023c
+/* [RW 11] The number of free blocks below which the full signal to the LB
* port is asserted */
#define BRB1_REG_FULL_LB_XOFF_THRESHOLD 0x601e0
/* [RW 10] The number of free blocks above which the full signal to the LB
@@ -75,15 +83,49 @@
/* [RW 10] The number of free blocks below which the High_llfc signal to
interface #n is asserted. */
#define BRB1_REG_HIGH_LLFC_LOW_THRESHOLD_0 0x6013c
-/* [RW 23] LL RAM data. */
-#define BRB1_REG_LL_RAM 0x61000
+/* [RW 11] The number of blocks guarantied for the LB port */
+#define BRB1_REG_LB_GUARANTIED 0x601ec
+/* [RW 11] The hysteresis on the guarantied buffer space for the Lb port
+ * before signaling XON. */
+#define BRB1_REG_LB_GUARANTIED_HYST 0x60264
+/* [RW 24] LL RAM data. */
+#define BRB1_REG_LL_RAM 0x61000
/* [RW 10] The number of free blocks above which the Low_llfc signal to
interface #n is de-asserted. */
#define BRB1_REG_LOW_LLFC_HIGH_THRESHOLD_0 0x6016c
/* [RW 10] The number of free blocks below which the Low_llfc signal to
interface #n is asserted. */
#define BRB1_REG_LOW_LLFC_LOW_THRESHOLD_0 0x6015c
-/* [RW 10] The number of blocks guarantied for the MAC port */
+/* [RW 11] The number of blocks guarantied for class 0 in MAC 0. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED 0x60244
+/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST 0x60254
+/* [RW 11] The number of blocks guarantied for class 1 in MAC 0. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED 0x60248
+/* [RW 11] The hysteresis on the guarantied buffer space for class 1in MAC 0
+ * before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST 0x60258
+/* [RW 11] The number of blocks guarantied for class 0in MAC1.The register
+ * is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED 0x6024c
+/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST 0x6025c
+/* [RW 11] The number of blocks guarantied for class 1 in MAC 1. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED 0x60250
+/* [RW 11] The hysteresis on the guarantied buffer space for class 1 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST 0x60260
+/* [RW 11] The number of blocks guarantied for the MAC port. The register is
+ * applicable only when per_class_guaranty_mode is reset. */
#define BRB1_REG_MAC_GUARANTIED_0 0x601e8
#define BRB1_REG_MAC_GUARANTIED_1 0x60240
/* [R 24] The number of full blocks. */
@@ -100,15 +142,19 @@
/* [RW 10] The number of free blocks below which the pause signal to class 0
* is asserted */
#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 0x601c0
-/* [RW 10] The number of free blocks above which the pause signal to class 0
+#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 0x60220
+/* [RW 11] The number of free blocks above which the pause signal to class 0
* is de-asserted */
#define BRB1_REG_PAUSE_0_XON_THRESHOLD_0 0x601c4
-/* [RW 10] The number of free blocks below which the pause signal to class 1
+#define BRB1_REG_PAUSE_0_XON_THRESHOLD_1 0x60224
+/* [RW 11] The number of free blocks below which the pause signal to class 1
* is asserted */
#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0 0x601c8
-/* [RW 10] The number of free blocks above which the pause signal to class 1
+#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 0x60228
+/* [RW 11] The number of free blocks above which the pause signal to class 1
* is de-asserted */
#define BRB1_REG_PAUSE_1_XON_THRESHOLD_0 0x601cc
+#define BRB1_REG_PAUSE_1_XON_THRESHOLD_1 0x6022c
/* [RW 10] Write client 0: De-assert pause threshold. Not Functional */
#define BRB1_REG_PAUSE_HIGH_THRESHOLD_0 0x60078
#define BRB1_REG_PAUSE_HIGH_THRESHOLD_1 0x6007c
@@ -325,7 +371,7 @@
mechanism. The fields are: [5:0] - message length; [12:6] - message
pointer; 18:13] - next pointer. */
#define CCM_REG_XX_DESCR_TABLE 0xd0300
-#define CCM_REG_XX_DESCR_TABLE_SIZE 36
+#define CCM_REG_XX_DESCR_TABLE_SIZE 24
/* [R 7] Used to read the value of XX protection Free counter. */
#define CCM_REG_XX_FREE 0xd0184
/* [RW 6] Initial value for the credit counter; responsible for fulfilling
@@ -422,6 +468,7 @@
#define CFC_REG_NUM_LCIDS_ALLOC 0x104020
/* [R 9] Number of Arriving LCIDs in Link List Block */
#define CFC_REG_NUM_LCIDS_ARRIVING 0x104004
+#define CFC_REG_NUM_LCIDS_INSIDE_PF 0x104120
/* [R 9] Number of Leaving LCIDs in Link List Block */
#define CFC_REG_NUM_LCIDS_LEAVING 0x104018
#define CFC_REG_WEAK_ENABLE_PF 0x104124
@@ -783,6 +830,7 @@
/* [RW 3] The number of simultaneous outstanding requests to Context Fetch
Interface. */
#define DORQ_REG_OUTST_REQ 0x17003c
+#define DORQ_REG_PF_USAGE_CNT 0x1701d0
#define DORQ_REG_REGN 0x170038
/* [R 4] Current value of response A counter credit. Initial credit is
configured through write to ~dorq_registers_rsp_init_crd.rsp_init_crd
@@ -802,10 +850,12 @@
/* [RW 28] TCM Header when both ULP and TCP context is loaded. */
#define DORQ_REG_SHRT_CMHEAD 0x170054
#define HC_CONFIG_0_REG_ATTN_BIT_EN_0 (0x1<<4)
+#define HC_CONFIG_0_REG_BLOCK_DISABLE_0 (0x1<<0)
#define HC_CONFIG_0_REG_INT_LINE_EN_0 (0x1<<3)
#define HC_CONFIG_0_REG_MSI_ATTN_EN_0 (0x1<<7)
#define HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 (0x1<<2)
-#define HC_CONFIG_0_REG_SINGLE_ISR_EN_0 (0x1<<1)
+#define HC_CONFIG_0_REG_SINGLE_ISR_EN_0 (0x1<<1)
+#define HC_CONFIG_1_REG_BLOCK_DISABLE_1 (0x1<<0)
#define HC_REG_AGG_INT_0 0x108050
#define HC_REG_AGG_INT_1 0x108054
#define HC_REG_ATTN_BIT 0x108120
@@ -844,6 +894,7 @@
#define HC_REG_VQID_0 0x108008
#define HC_REG_VQID_1 0x10800c
#define IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN (0x1<<1)
+#define IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE (0x1<<0)
#define IGU_REG_ATTENTION_ACK_BITS 0x130108
/* [R 4] Debug: attn_fsm */
#define IGU_REG_ATTN_FSM 0x130054
@@ -933,6 +984,14 @@
* clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
#define IGU_REG_WRITE_DONE_PENDING 0x130480
#define MCP_A_REG_MCPR_SCRATCH 0x3a0000
+#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c
+#define MCP_REG_MCPR_GP_INPUTS 0x800c0
+#define MCP_REG_MCPR_GP_OENABLE 0x800c8
+#define MCP_REG_MCPR_GP_OUTPUTS 0x800c4
+#define MCP_REG_MCPR_IMC_COMMAND 0x85900
+#define MCP_REG_MCPR_IMC_DATAREG0 0x85920
+#define MCP_REG_MCPR_IMC_SLAVE_CONTROL 0x85904
+#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c
#define MCP_REG_MCPR_NVM_ACCESS_ENABLE 0x86424
#define MCP_REG_MCPR_NVM_ADDR 0x8640c
#define MCP_REG_MCPR_NVM_CFG4 0x8642c
@@ -1429,11 +1488,37 @@
/* [RW 1] e1hmf for WOL. If clr WOL signal o the PXP will be send on bit 0
only. */
#define MISC_REG_E1HMF_MODE 0xa5f8
+/* [R 1] Status of four port mode path swap input pin. */
+#define MISC_REG_FOUR_PORT_PATH_SWAP 0xa75c
+/* [RW 2] 4 port path swap overwrite.[0] - Overwrite control; if it is 0 -
+ the path_swap output is equal to 4 port mode path swap input pin; if it
+ is 1 - the path_swap output is equal to bit[1] of this register; [1] -
+ Overwrite value. If bit[0] of this register is 1 this is the value that
+ receives the path_swap output. Reset on Hard reset. */
+#define MISC_REG_FOUR_PORT_PATH_SWAP_OVWR 0xa738
+/* [R 1] Status of 4 port mode port swap input pin. */
+#define MISC_REG_FOUR_PORT_PORT_SWAP 0xa754
+/* [RW 2] 4 port port swap overwrite.[0] - Overwrite control; if it is 0 -
+ the port_swap output is equal to 4 port mode port swap input pin; if it
+ is 1 - the port_swap output is equal to bit[1] of this register; [1] -
+ Overwrite value. If bit[0] of this register is 1 this is the value that
+ receives the port_swap output. Reset on Hard reset. */
+#define MISC_REG_FOUR_PORT_PORT_SWAP_OVWR 0xa734
/* [RW 32] Debug only: spare RW register reset by core reset */
#define MISC_REG_GENERIC_CR_0 0xa460
#define MISC_REG_GENERIC_CR_1 0xa464
/* [RW 32] Debug only: spare RW register reset by por reset */
#define MISC_REG_GENERIC_POR_1 0xa474
+/* [RW 32] Bit[0]: EPIO MODE SEL: Setting this bit to 1 will allow SW/FW to
+ use all of the 32 Extended GPIO pins. Without setting this bit; an EPIO
+ can not be configured as an output. Each output has its output enable in
+ the MCP register space; but this bit needs to be set to make use of that.
+ Bit[3:1] spare. Bit[4]: WCVTMON_PWRDN: Powerdown for Warpcore VTMON. When
+ set to 1 - Powerdown. Bit[5]: WCVTMON_RESETB: Reset for Warpcore VTMON.
+ When set to 0 - vTMON is in reset. Bit[6]: setting this bit will change
+ the i/o to an output and will drive the TimeSync output. Bit[31:7]:
+ spare. Global register. Reset by hard reset. */
+#define MISC_REG_GEN_PURP_HWG 0xa9a0
/* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
these bits is written as a '1'; the corresponding SPIO bit will turn off
it's drivers and become an input. This is the reset state of all GPIO
@@ -1636,6 +1721,14 @@
in this register. address 0 - timer 1; address 1 - timer 2, ... address 7 -
timer 8 */
#define MISC_REG_SW_TIMER_VAL 0xa5c0
+/* [R 1] Status of two port mode path swap input pin. */
+#define MISC_REG_TWO_PORT_PATH_SWAP 0xa758
+/* [RW 2] 2 port swap overwrite.[0] - Overwrite control; if it is 0 - the
+ path_swap output is equal to 2 port mode path swap input pin; if it is 1
+ - the path_swap output is equal to bit[1] of this register; [1] -
+ Overwrite value. If bit[0] of this register is 1 this is the value that
+ receives the path_swap output. Reset on Hard reset. */
+#define MISC_REG_TWO_PORT_PATH_SWAP_OVWR 0xa72c
/* [RW 1] Set by the MCP to remember if one or more of the drivers is/are
loaded; 0-prepare; -unprepare */
#define MISC_REG_UNPREPARED 0xa424
@@ -1644,6 +1737,36 @@
#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN (0x1<<4)
#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST (0x1<<2)
#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN (0x1<<3)
+/* [RW 5] MDIO PHY Address. The WC uses this address to determine whether or
+ * not it is the recipient of the message on the MDIO interface. The value
+ * is compared to the value on ctrl_md_devad. Drives output
+ * misc_xgxs0_phy_addr. Global register. */
+#define MISC_REG_WC0_CTRL_PHY_ADDR 0xa9cc
+/* [RW 2] XMAC Core port mode. Indicates the number of ports on the system
+ side. This should be less than or equal to phy_port_mode; if some of the
+ ports are not used. This enables reduction of frequency on the core side.
+ This is a strap input for the XMAC_MP core. 00 - Single Port Mode; 01 -
+ Dual Port Mode; 10 - Tri Port Mode; 11 - Quad Port Mode. This is a strap
+ input for the XMAC_MP core; and should be changed only while reset is
+ held low. Reset on Hard reset. */
+#define MISC_REG_XMAC_CORE_PORT_MODE 0xa964
+/* [RW 2] XMAC PHY port mode. Indicates the number of ports on the Warp
+ Core. This is a strap input for the XMAC_MP core. 00 - Single Port Mode;
+ 01 - Dual Port Mode; 1x - Quad Port Mode; This is a strap input for the
+ XMAC_MP core; and should be changed only while reset is held low. Reset
+ on Hard reset. */
+#define MISC_REG_XMAC_PHY_PORT_MODE 0xa960
+/* [RW 32] 1 [47] Packet Size = 64 Write to this register write bits 31:0.
+ * Reads from this register will clear bits 31:0. */
+#define MSTAT_REG_RX_STAT_GR64_LO 0x200
+/* [RW 32] 1 [00] Tx Good Packet Count Write to this register write bits
+ * 31:0. Reads from this register will clear bits 31:0. */
+#define MSTAT_REG_TX_STAT_GTXPOK_LO 0
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST (0x1<<0)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST (0x1<<1)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN (0x1<<4)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST (0x1<<2)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN (0x1<<3)
#define NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN (0x1<<0)
#define NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN (0x1<<0)
#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT (0x1<<0)
@@ -1837,6 +1960,10 @@
#define NIG_REG_LLH1_FUNC_MEM 0x161c0
#define NIG_REG_LLH1_FUNC_MEM_ENABLE 0x16160
#define NIG_REG_LLH1_FUNC_MEM_SIZE 16
+/* [RW 1] When this bit is set; the LLH will classify the packet before
+ * sending it to the BRB or calculating WoL on it. This bit controls port 1
+ * only. The legacy llh_multi_function_mode bit controls port 0. */
+#define NIG_REG_LLH1_MF_MODE 0x18614
/* [RW 8] init credit counter for port1 in LLH */
#define NIG_REG_LLH1_XCM_INIT_CREDIT 0x10564
#define NIG_REG_LLH1_XCM_MASK 0x10134
@@ -1858,11 +1985,25 @@
/* [R 32] Interrupt register #0 read */
#define NIG_REG_NIG_INT_STS_0 0x103b0
#define NIG_REG_NIG_INT_STS_1 0x103c0
+/* [R 32] Legacy E1 and E1H location for parity error mask register. */
+#define NIG_REG_NIG_PRTY_MASK 0x103dc
+/* [RW 32] Parity mask register #0 read/write */
+#define NIG_REG_NIG_PRTY_MASK_0 0x183c8
+#define NIG_REG_NIG_PRTY_MASK_1 0x183d8
/* [R 32] Legacy E1 and E1H location for parity error status register. */
#define NIG_REG_NIG_PRTY_STS 0x103d0
/* [R 32] Parity register #0 read */
#define NIG_REG_NIG_PRTY_STS_0 0x183bc
#define NIG_REG_NIG_PRTY_STS_1 0x183cc
+/* [R 32] Legacy E1 and E1H location for parity error status clear register. */
+#define NIG_REG_NIG_PRTY_STS_CLR 0x103d4
+/* [RC 32] Parity register #0 read clear */
+#define NIG_REG_NIG_PRTY_STS_CLR_0 0x183c0
+#define NIG_REG_NIG_PRTY_STS_CLR_1 0x183d0
+#define MCPR_IMC_COMMAND_ENABLE (1L<<31)
+#define MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT 16
+#define MCPR_IMC_COMMAND_OPERATION_BITSHIFT 28
+#define MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT 8
/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
* Ethernet header. */
#define NIG_REG_P0_HDRS_AFTER_BASIC 0x18038
@@ -1872,6 +2013,12 @@
#define NIG_REG_P0_HWPFC_ENABLE 0x18078
#define NIG_REG_P0_LLH_FUNC_MEM2 0x18480
#define NIG_REG_P0_LLH_FUNC_MEM2_ENABLE 0x18440
+/* [RW 1] Input enable for RX MAC interface. */
+#define NIG_REG_P0_MAC_IN_EN 0x185ac
+/* [RW 1] Output enable for TX MAC interface */
+#define NIG_REG_P0_MAC_OUT_EN 0x185b0
+/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
+#define NIG_REG_P0_MAC_PAUSE_OUT_EN 0x185b4
/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
* future expansion) each priorty is to be mapped to. Bits 3:0 specify the
* COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
@@ -1888,11 +2035,52 @@
* than one bit may be set; allowing multiple priorities to be mapped to one
* COS. */
#define NIG_REG_P0_RX_COS1_PRIORITY_MASK 0x1805c
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
+ * priority is mapped to COS 2 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS2_PRIORITY_MASK 0x186b0
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 3. A
+ * priority is mapped to COS 3 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS3_PRIORITY_MASK 0x186b4
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 4. A
+ * priority is mapped to COS 4 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS4_PRIORITY_MASK 0x186b8
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 5. A
+ * priority is mapped to COS 5 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS5_PRIORITY_MASK 0x186bc
+/* [R 1] RX FIFO for receiving data from MAC is empty. */
/* [RW 15] Specify which of the credit registers the client is to be mapped
* to. Bits[2:0] are for client 0; bits [14:12] are for client 4. For
* clients that are not subject to WFQ credit blocking - their
* specifications here are not used. */
#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP 0x180f0
+/* [RW 32] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB 0x18688
+/* [RW 4] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB 0x1868c
/* [RW 5] Specify whether the client competes directly in the strict
* priority arbiter. The bits are mapped according to client ID (client IDs
* are defined in tx_arb_priority_client). Default value is set to enable
@@ -1907,10 +2095,24 @@
* reach. */
#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0 0x1810c
#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1 0x18110
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2 0x18114
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3 0x18118
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4 0x1811c
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5 0x186a0
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6 0x186a4
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7 0x186a8
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8 0x186ac
/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
* when it is time to increment. */
#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0 0x180f8
#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1 0x180fc
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2 0x18100
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3 0x18104
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4 0x18108
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5 0x18690
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6 0x18694
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7 0x18698
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8 0x1869c
/* [RW 12] Specify the number of strict priority arbitration slots between
* two round-robin arbitration slots to avoid starvation. A value of 0 means
* no strict priority cycles - the strict priority with anti-starvation
@@ -1925,8 +2127,36 @@
* for management at priority 0; debug traffic at priorities 1 and 2; COS0
* traffic at priority 3; and COS1 traffic at priority 4. */
#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT 0x180e4
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define NIG_REG_P1_HDRS_AFTER_BASIC 0x1818c
#define NIG_REG_P1_LLH_FUNC_MEM2 0x184c0
#define NIG_REG_P1_LLH_FUNC_MEM2_ENABLE 0x18460
+/* [RW 32] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. This register specifies bits 31:0 of the 36-bit
+ * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ * client; bits [35-32] are for priority 8 client. The clients are assigned
+ * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ * accommodate the 9 input clients to ETS arbiter. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB 0x18680
+/* [RW 4] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. This register specifies bits 35:32 of the 36-bit
+ * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ * client; bits [35-32] are for priority 8 client. The clients are assigned
+ * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ * accommodate the 9 input clients to ETS arbiter. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB 0x18684
+#define NIG_REG_P1_MAC_IN_EN 0x185c0
+/* [RW 1] Output enable for TX MAC interface */
+#define NIG_REG_P1_MAC_OUT_EN 0x185c4
+/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
+#define NIG_REG_P1_MAC_PAUSE_OUT_EN 0x185c8
/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
* future expansion) each priorty is to be mapped to. Bits 3:0 specify the
* COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
@@ -1943,6 +2173,105 @@
* than one bit may be set; allowing multiple priorities to be mapped to one
* COS. */
#define NIG_REG_P1_RX_COS1_PRIORITY_MASK 0x181b0
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
+ * priority is mapped to COS 2 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P1_RX_COS2_PRIORITY_MASK 0x186f8
+/* [R 1] RX FIFO for receiving data from MAC is empty. */
+#define NIG_REG_P1_RX_MACFIFO_EMPTY 0x1858c
+/* [R 1] TLLH FIFO is empty. */
+#define NIG_REG_P1_TLLH_FIFO_EMPTY 0x18338
+/* [RW 32] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. Note also that there are
+ * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
+ * credit registers 0-5 are valid. This register should be configured
+ * appropriately before enabling WFQ. */
+#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB 0x186e8
+/* [RW 4] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. Note also that there are
+ * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
+ * credit registers 0-5 are valid. This register should be configured
+ * appropriately before enabling WFQ. */
+#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB 0x186ec
+/* [RW 9] Specify whether the client competes directly in the strict
+ * priority arbiter. The bits are mapped according to client ID (client IDs
+ * are defined in tx_arb_priority_client2): 0-management; 1-debug traffic
+ * from this port; 2-debug traffic from other port; 3-COS0 traffic; 4-COS1
+ * traffic; 5-COS2 traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic.
+ * Default value is set to enable strict priorities for all clients. */
+#define NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT 0x18234
+/* [RW 9] Specify whether the client is subject to WFQ credit blocking. The
+ * bits are mapped according to client ID (client IDs are defined in
+ * tx_arb_priority_client2): 0-management; 1-debug traffic from this port;
+ * 2-debug traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2
+ * traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. Default value is
+ * 0 for not using WFQ credit blocking. */
+#define NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ 0x18238
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 0x18258
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 0x1825c
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 0x18260
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 0x18264
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 0x18268
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 0x186f4
+/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
+ * when it is time to increment. */
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 0x18244
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 0x18248
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 0x1824c
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 0x18250
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 0x18254
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 0x186f0
+/* [RW 12] Specify the number of strict priority arbitration slots between
+ two round-robin arbitration slots to avoid starvation. A value of 0 means
+ no strict priority cycles - the strict priority with anti-starvation
+ arbiter becomes a round-robin arbiter. */
+#define NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS 0x18240
+/* [RW 32] Specify the client number to be assigned to each priority of the
+ strict priority arbiter. This register specifies bits 31:0 of the 36-bit
+ value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ client; bits [35-32] are for priority 8 client. The clients are assigned
+ the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ accommodate the 9 input clients to ETS arbiter. Note that this register
+ is the same as the one for port 0, except that port 1 only has COS 0-2
+ traffic. There is no traffic for COS 3-5 of port 1. */
+#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB 0x186e0
+/* [RW 4] Specify the client number to be assigned to each priority of the
+ strict priority arbiter. This register specifies bits 35:32 of the 36-bit
+ value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ client; bits [35-32] are for priority 8 client. The clients are assigned
+ the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ accommodate the 9 input clients to ETS arbiter. Note that this register
+ is the same as the one for port 0, except that port 1 only has COS 0-2
+ traffic. There is no traffic for COS 3-5 of port 1. */
+#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB 0x186e4
+/* [R 1] TX FIFO for transmitting data to MAC is empty. */
+#define NIG_REG_P1_TX_MACFIFO_EMPTY 0x18594
+/* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
+ forwarded to the host. */
+#define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY 0x182b8
+/* [RW 32] Specify the upper bound that credit register 0 is allowed to
+ * reach. */
/* [RW 1] Pause enable for port0. This register may get 1 only when
~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same
port */
@@ -2026,12 +2355,45 @@
#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE 18
/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter. */
#define PBF_REG_COS0_UPPER_BOUND 0x15c05c
+/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
+ * of port 0. */
+#define PBF_REG_COS0_UPPER_BOUND_P0 0x15c2cc
+/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
+ * of port 1. */
+#define PBF_REG_COS0_UPPER_BOUND_P1 0x15c2e4
/* [RW 31] The weight of COS0 in the ETS command arbiter. */
#define PBF_REG_COS0_WEIGHT 0x15c054
+/* [RW 31] The weight of COS0 in port 0 ETS command arbiter. */
+#define PBF_REG_COS0_WEIGHT_P0 0x15c2a8
+/* [RW 31] The weight of COS0 in port 1 ETS command arbiter. */
+#define PBF_REG_COS0_WEIGHT_P1 0x15c2c0
/* [RW 31] The upper bound of the weight of COS1 in the ETS command arbiter. */
#define PBF_REG_COS1_UPPER_BOUND 0x15c060
/* [RW 31] The weight of COS1 in the ETS command arbiter. */
#define PBF_REG_COS1_WEIGHT 0x15c058
+/* [RW 31] The weight of COS1 in port 0 ETS command arbiter. */
+#define PBF_REG_COS1_WEIGHT_P0 0x15c2ac
+/* [RW 31] The weight of COS1 in port 1 ETS command arbiter. */
+#define PBF_REG_COS1_WEIGHT_P1 0x15c2c4
+/* [RW 31] The weight of COS2 in port 0 ETS command arbiter. */
+#define PBF_REG_COS2_WEIGHT_P0 0x15c2b0
+/* [RW 31] The weight of COS2 in port 1 ETS command arbiter. */
+#define PBF_REG_COS2_WEIGHT_P1 0x15c2c8
+/* [RW 31] The weight of COS3 in port 0 ETS command arbiter. */
+#define PBF_REG_COS3_WEIGHT_P0 0x15c2b4
+/* [RW 31] The weight of COS4 in port 0 ETS command arbiter. */
+#define PBF_REG_COS4_WEIGHT_P0 0x15c2b8
+/* [RW 31] The weight of COS5 in port 0 ETS command arbiter. */
+#define PBF_REG_COS5_WEIGHT_P0 0x15c2bc
+/* [R 11] Current credit for the LB queue in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_LB_Q 0x140338
+/* [R 11] Current credit for queue 0 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_Q0 0x14033c
+/* [R 11] Current credit for queue 1 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_Q1 0x140340
/* [RW 1] Disable processing further tasks from port 0 (after ending the
current task in process). */
#define PBF_REG_DISABLE_NEW_TASK_PROC_P0 0x14005c
@@ -2042,6 +2404,52 @@
current task in process). */
#define PBF_REG_DISABLE_NEW_TASK_PROC_P4 0x14006c
#define PBF_REG_DISABLE_PF 0x1402e8
+/* [RW 18] For port 0: For each client that is subject to WFQ (the
+ * corresponding bit is 1); indicates to which of the credit registers this
+ * client is mapped. For clients which are not credit blocked; their mapping
+ * is dont care. */
+#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0 0x15c288
+/* [RW 9] For port 1: For each client that is subject to WFQ (the
+ * corresponding bit is 1); indicates to which of the credit registers this
+ * client is mapped. For clients which are not credit blocked; their mapping
+ * is dont care. */
+#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1 0x15c28c
+/* [RW 6] For port 0: Bit per client to indicate if the client competes in
+ * the strict priority arbiter directly (corresponding bit = 1); or first
+ * goes to the RR arbiter (corresponding bit = 0); and then competes in the
+ * lowest priority in the strict-priority arbiter. */
+#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 0x15c278
+/* [RW 3] For port 1: Bit per client to indicate if the client competes in
+ * the strict priority arbiter directly (corresponding bit = 1); or first
+ * goes to the RR arbiter (corresponding bit = 0); and then competes in the
+ * lowest priority in the strict-priority arbiter. */
+#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 0x15c27c
+/* [RW 6] For port 0: Bit per client to indicate if the client is subject to
+ * WFQ credit blocking (corresponding bit = 1). */
+#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 0x15c280
+/* [RW 3] For port 0: Bit per client to indicate if the client is subject to
+ * WFQ credit blocking (corresponding bit = 1). */
+#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 0x15c284
+/* [RW 16] For port 0: The number of strict priority arbitration slots
+ * between 2 RR arbitration slots. A value of 0 means no strict priority
+ * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
+ * arbiter. */
+#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 0x15c2a0
+/* [RW 16] For port 1: The number of strict priority arbitration slots
+ * between 2 RR arbitration slots. A value of 0 means no strict priority
+ * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
+ * arbiter. */
+#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 0x15c2a4
+/* [RW 18] For port 0: Indicates which client is connected to each priority
+ * in the strict-priority arbiter. Priority 0 is the highest priority, and
+ * priority 5 is the lowest; to which the RR output is connected to (this is
+ * not configurable). */
+#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 0x15c270
+/* [RW 9] For port 1: Indicates which client is connected to each priority
+ * in the strict-priority arbiter. Priority 0 is the highest priority, and
+ * priority 5 is the lowest; to which the RR output is connected to (this is
+ * not configurable). */
+#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 0x15c274
/* [RW 1] Indicates that ETS is performed between the COSes in the command
* arbiter. If reset strict priority w/ anti-starvation will be performed
* w/o WFQ. */
@@ -2049,14 +2457,25 @@
/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
* Ethernet header. */
#define PBF_REG_HDRS_AFTER_BASIC 0x15c0a8
-/* [RW 1] Indicates which COS is conncted to the highest priority in the
- * command arbiter. */
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
+#define PBF_REG_HDRS_AFTER_TAG_0 0x15c0b8
+/* [R 1] Removed for E3 B0 - Indicates which COS is conncted to the highest
+ * priority in the command arbiter. */
#define PBF_REG_HIGH_PRIORITY_COS_NUM 0x15c04c
#define PBF_REG_IF_ENABLE_REG 0x140044
/* [RW 1] Init bit. When set the initial credits are copied to the credit
registers (except the port credits). Should be set and then reset after
the configuration of the block has ended. */
#define PBF_REG_INIT 0x140000
+/* [RW 11] Initial credit for the LB queue in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_LB_Q 0x15c248
+/* [RW 11] Initial credit for queue 0 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_Q0 0x15c230
+/* [RW 11] Initial credit for queue 1 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_Q1 0x15c234
/* [RW 1] Init bit for port 0. When set the initial credit of port 0 is
copied to the credit register. Should be set and then reset after the
configuration of the port has ended. */
@@ -2069,6 +2488,15 @@
copied to the credit register. Should be set and then reset after the
configuration of the port has ended. */
#define PBF_REG_INIT_P4 0x14000c
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * the LB queue. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q 0x140354
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * queue 0. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 0x140358
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * queue 1. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 0x14035c
/* [RW 1] Enable for mac interface 0. */
#define PBF_REG_MAC_IF0_ENABLE 0x140030
/* [RW 1] Enable for mac interface 1. */
@@ -2089,24 +2517,49 @@
/* [RW 11] Initial credit for port 0 in the tx port buffers in 16 byte
lines. */
#define PBF_REG_P0_INIT_CRD 0x1400d0
-/* [RW 1] Indication that pause is enabled for port 0. */
-#define PBF_REG_P0_PAUSE_ENABLE 0x140014
-/* [R 8] Number of tasks in port 0 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 0. Reset upon init. */
+#define PBF_REG_P0_INTERNAL_CRD_FREED_CNT 0x140308
+/* [R 1] Removed for E3 B0 - Indication that pause is enabled for port 0. */
+#define PBF_REG_P0_PAUSE_ENABLE 0x140014
+/* [R 8] Removed for E3 B0 - Number of tasks in port 0 task queue. */
#define PBF_REG_P0_TASK_CNT 0x140204
-/* [R 11] Current credit for port 1 in the tx port buffers in 16 byte lines. */
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 0. Reset upon init. */
+#define PBF_REG_P0_TQ_LINES_FREED_CNT 0x1402f0
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 0. */
+#define PBF_REG_P0_TQ_OCCUPANCY 0x1402fc
+/* [R 11] Removed for E3 B0 - Current credit for port 1 in the tx port
+ * buffers in 16 byte lines. */
#define PBF_REG_P1_CREDIT 0x140208
-/* [RW 11] Initial credit for port 1 in the tx port buffers in 16 byte
- lines. */
+/* [R 11] Removed for E3 B0 - Initial credit for port 0 in the tx port
+ * buffers in 16 byte lines. */
#define PBF_REG_P1_INIT_CRD 0x1400d4
-/* [R 8] Number of tasks in port 1 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 1. Reset upon init. */
+#define PBF_REG_P1_INTERNAL_CRD_FREED_CNT 0x14030c
+/* [R 8] Removed for E3 B0 - Number of tasks in port 1 task queue. */
#define PBF_REG_P1_TASK_CNT 0x14020c
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 1. Reset upon init. */
+#define PBF_REG_P1_TQ_LINES_FREED_CNT 0x1402f4
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 1. */
+#define PBF_REG_P1_TQ_OCCUPANCY 0x140300
/* [R 11] Current credit for port 4 in the tx port buffers in 16 byte lines. */
#define PBF_REG_P4_CREDIT 0x140210
/* [RW 11] Initial credit for port 4 in the tx port buffers in 16 byte
lines. */
#define PBF_REG_P4_INIT_CRD 0x1400e0
-/* [R 8] Number of tasks in port 4 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 4. Reset upon init. */
+#define PBF_REG_P4_INTERNAL_CRD_FREED_CNT 0x140310
+/* [R 8] Removed for E3 B0 - Number of tasks in port 4 task queue. */
#define PBF_REG_P4_TASK_CNT 0x140214
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 4. Reset upon init. */
+#define PBF_REG_P4_TQ_LINES_FREED_CNT 0x1402f8
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 4. */
+#define PBF_REG_P4_TQ_OCCUPANCY 0x140304
/* [RW 5] Interrupt mask register #0 read/write */
#define PBF_REG_PBF_INT_MASK 0x1401d4
/* [R 5] Interrupt register #0 read */
@@ -2115,6 +2568,27 @@
#define PBF_REG_PBF_PRTY_MASK 0x1401e4
/* [RC 20] Parity register #0 read clear */
#define PBF_REG_PBF_PRTY_STS_CLR 0x1401dc
+/* [RW 16] The Ethernet type value for L2 tag 0 */
+#define PBF_REG_TAG_ETHERTYPE_0 0x15c090
+/* [RW 4] The length of the info field for L2 tag 0. The length is between
+ * 2B and 14B; in 2B granularity */
+#define PBF_REG_TAG_LEN_0 0x15c09c
+/* [R 32] Cyclic counter for number of 8 byte lines freed from the LB task
+ * queue. Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_LB_Q 0x14038c
+/* [R 32] Cyclic counter for number of 8 byte lines freed from the task
+ * queue 0. Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_Q0 0x140390
+/* [R 32] Cyclic counter for number of 8 byte lines freed from task queue 1.
+ * Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_Q1 0x140394
+/* [R 13] Number of 8 bytes lines occupied in the task queue of the LB
+ * queue. */
+#define PBF_REG_TQ_OCCUPANCY_LB_Q 0x1403a8
+/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 0. */
+#define PBF_REG_TQ_OCCUPANCY_Q0 0x1403ac
+/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 1. */
+#define PBF_REG_TQ_OCCUPANCY_Q1 0x1403b0
#define PB_REG_CONTROL 0
/* [RW 2] Interrupt mask register #0 read/write */
#define PB_REG_PB_INT_MASK 0x28
@@ -2206,8 +2680,12 @@
#define PGLUE_B_REG_PGLUE_B_INT_STS 0x9298
/* [RC 9] Interrupt register #0 read clear */
#define PGLUE_B_REG_PGLUE_B_INT_STS_CLR 0x929c
+/* [RW 2] Parity mask register #0 read/write */
+#define PGLUE_B_REG_PGLUE_B_PRTY_MASK 0x92b4
/* [R 2] Parity register #0 read */
#define PGLUE_B_REG_PGLUE_B_PRTY_STS 0x92a8
+/* [RC 2] Parity register #0 read clear */
+#define PGLUE_B_REG_PGLUE_B_PRTY_STS_CLR 0x92ac
/* [R 13] Details of first request received with error. [2:0] - PFID. [3] -
* VF_VALID. [9:4] - VFID. [11:10] - Error Code - 0 - Indicates Completion
* Timeout of a User Tx non-posted request. 1 - unsupported request. 2 -
@@ -2444,10 +2922,24 @@
/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
* Ethernet header. */
#define PRS_REG_HDRS_AFTER_BASIC 0x40238
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header for port 0 packets. */
+#define PRS_REG_HDRS_AFTER_BASIC_PORT_0 0x40270
+#define PRS_REG_HDRS_AFTER_BASIC_PORT_1 0x40290
+/* [R 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
+#define PRS_REG_HDRS_AFTER_TAG_0 0x40248
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 for
+ * port 0 packets */
+#define PRS_REG_HDRS_AFTER_TAG_0_PORT_0 0x40280
+#define PRS_REG_HDRS_AFTER_TAG_0_PORT_1 0x402a0
/* [RW 4] The increment value to send in the CFC load request message */
#define PRS_REG_INC_VALUE 0x40048
/* [RW 6] Bit-map indicating which headers must appear in the packet */
#define PRS_REG_MUST_HAVE_HDRS 0x40254
+/* [RW 6] Bit-map indicating which headers must appear in the packet for
+ * port 0 packets */
+#define PRS_REG_MUST_HAVE_HDRS_PORT_0 0x4028c
+#define PRS_REG_MUST_HAVE_HDRS_PORT_1 0x402ac
#define PRS_REG_NIC_MODE 0x40138
/* [RW 8] The 8-bit event ID for cases where there is no match on the
connection. Used in packet start message to TCM. */
@@ -2496,6 +2988,11 @@
#define PRS_REG_SERIAL_NUM_STATUS_MSB 0x40158
/* [R 4] debug only: SRC current credit. Transaction based. */
#define PRS_REG_SRC_CURRENT_CREDIT 0x4016c
+/* [RW 16] The Ethernet type value for L2 tag 0 */
+#define PRS_REG_TAG_ETHERTYPE_0 0x401d4
+/* [RW 4] The length of the info field for L2 tag 0. The length is between
+ * 2B and 14B; in 2B granularity */
+#define PRS_REG_TAG_LEN_0 0x4022c
/* [R 8] debug only: TCM current credit. Cycle based. */
#define PRS_REG_TCM_CURRENT_CREDIT 0x40160
/* [R 8] debug only: TSDM current credit. Transaction based. */
@@ -3080,6 +3577,7 @@
#define QM_REG_BYTECREDITAFULLTHR 0x168094
/* [RW 4] The initial credit for interface */
#define QM_REG_CMINITCRD_0 0x1680cc
+#define QM_REG_BYTECRDCMDQ_0 0x16e6e8
#define QM_REG_CMINITCRD_1 0x1680d0
#define QM_REG_CMINITCRD_2 0x1680d4
#define QM_REG_CMINITCRD_3 0x1680d8
@@ -3170,7 +3668,10 @@
/* [RW 2] The PCI attributes field used in the PCI request. */
#define QM_REG_PCIREQAT 0x168054
#define QM_REG_PF_EN 0x16e70c
-/* [R 16] The byte credit of port 0 */
+/* [R 24] The number of tasks stored in the QM for the PF. only even
+ * functions are valid in E2 (odd I registers will be hard wired to 0) */
+#define QM_REG_PF_USG_CNT_0 0x16e040
+/* [R 16] NOT USED */
#define QM_REG_PORT0BYTECRD 0x168300
/* [R 16] The byte credit of port 1 */
#define QM_REG_PORT1BYTECRD 0x168304
@@ -3725,7 +4226,7 @@
mechanism. The fields are: [5:0] - length of the message; 15:6] - message
pointer; 20:16] - next pointer. */
#define TCM_REG_XX_DESCR_TABLE 0x50280
-#define TCM_REG_XX_DESCR_TABLE_SIZE 32
+#define TCM_REG_XX_DESCR_TABLE_SIZE 29
/* [R 6] Use to read the value of XX protection Free counter. */
#define TCM_REG_XX_FREE 0x50178
/* [RW 6] Initial value for the credit counter; responsible for fulfilling
@@ -3782,6 +4283,8 @@
#define TM_REG_LIN0_LOGIC_ADDR 0x164240
/* [RW 18] Linear0 Max active cid (in banks of 32 entries). */
#define TM_REG_LIN0_MAX_ACTIVE_CID 0x164048
+/* [ST 16] Linear0 Number of scans counter. */
+#define TM_REG_LIN0_NUM_SCANS 0x1640a0
/* [WB 64] Linear0 phy address. */
#define TM_REG_LIN0_PHY_ADDR 0x164270
/* [RW 1] Linear0 physical address valid. */
@@ -3789,6 +4292,7 @@
#define TM_REG_LIN0_SCAN_ON 0x1640d0
/* [RW 24] Linear0 array scan timeout. */
#define TM_REG_LIN0_SCAN_TIME 0x16403c
+#define TM_REG_LIN0_VNIC_UC 0x164128
/* [RW 32] Linear1 logic address. */
#define TM_REG_LIN1_LOGIC_ADDR 0x164250
/* [WB 64] Linear1 phy address. */
@@ -4175,6 +4679,8 @@
#define UCM_REG_UCM_INT_MASK 0xe01d4
/* [R 11] Interrupt register #0 read */
#define UCM_REG_UCM_INT_STS 0xe01c8
+/* [RW 27] Parity mask register #0 read/write */
+#define UCM_REG_UCM_PRTY_MASK 0xe01e4
/* [R 27] Parity register #0 read */
#define UCM_REG_UCM_PRTY_STS 0xe01d8
/* [RC 27] Parity register #0 read clear */
@@ -4248,7 +4754,7 @@
mechanism. The fields are:[5:0] - message length; 14:6] - message
pointer; 19:15] - next pointer. */
#define UCM_REG_XX_DESCR_TABLE 0xe0280
-#define UCM_REG_XX_DESCR_TABLE_SIZE 32
+#define UCM_REG_XX_DESCR_TABLE_SIZE 27
/* [R 6] Use to read the XX protection Free counter. */
#define UCM_REG_XX_FREE 0xe016c
/* [RW 6] Initial value for the credit counter; responsible for fulfilling
@@ -4265,6 +4771,23 @@
The fields are: [4:0] - tail pointer; 10:5] - Link List size; 15:11] -
header pointer. */
#define UCM_REG_XX_TABLE 0xe0300
+#define UMAC_COMMAND_CONFIG_REG_LOOP_ENA (0x1<<15)
+#define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK (0x1<<24)
+#define UMAC_COMMAND_CONFIG_REG_PAD_EN (0x1<<5)
+#define UMAC_COMMAND_CONFIG_REG_PROMIS_EN (0x1<<4)
+#define UMAC_COMMAND_CONFIG_REG_RX_ENA (0x1<<1)
+#define UMAC_COMMAND_CONFIG_REG_SW_RESET (0x1<<13)
+#define UMAC_COMMAND_CONFIG_REG_TX_ENA (0x1<<0)
+#define UMAC_REG_COMMAND_CONFIG 0x8
+/* [RW 32] Register Bit 0 refers to Bit 16 of the MAC address; Bit 1 refers
+ * to bit 17 of the MAC address etc. */
+#define UMAC_REG_MAC_ADDR0 0xc
+/* [RW 16] Register Bit 0 refers to Bit 0 of the MAC address; Register Bit 1
+ * refers to Bit 1 of the MAC address etc. Bits 16 to 31 are reserved. */
+#define UMAC_REG_MAC_ADDR1 0x10
+/* [RW 14] Defines a 14-Bit maximum frame length used by the MAC receive
+ * logic to check frames. */
+#define UMAC_REG_MAXFR 0x14
/* [RW 8] The event id for aggregated interrupt 0 */
#define USDM_REG_AGG_INT_EVENT_0 0xc4038
#define USDM_REG_AGG_INT_EVENT_1 0xc403c
@@ -4696,8 +5219,13 @@
#define XCM_REG_XCM_INT_MASK 0x202b4
/* [R 14] Interrupt register #0 read */
#define XCM_REG_XCM_INT_STS 0x202a8
+/* [RW 30] Parity mask register #0 read/write */
+#define XCM_REG_XCM_PRTY_MASK 0x202c4
/* [R 30] Parity register #0 read */
#define XCM_REG_XCM_PRTY_STS 0x202b8
+/* [RC 30] Parity register #0 read clear */
+#define XCM_REG_XCM_PRTY_STS_CLR 0x202bc
+
/* [RW 4] The size of AG context region 0 in REG-pairs. Designates the MS
REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
Is used to determine the number of the AG context REG-pairs written back;
@@ -4772,6 +5300,34 @@
#define XCM_REG_XX_MSG_NUM 0x20428
/* [RW 8] The Event ID; sent to the STORM in case of XX overflow. */
#define XCM_REG_XX_OVFL_EVNT_ID 0x20058
+#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS (0x1<<0)
+#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS (0x1<<1)
+#define XMAC_CTRL_REG_CORE_LOCAL_LPBK (0x1<<3)
+#define XMAC_CTRL_REG_RX_EN (0x1<<1)
+#define XMAC_CTRL_REG_SOFT_RESET (0x1<<6)
+#define XMAC_CTRL_REG_TX_EN (0x1<<0)
+#define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN (0x1<<18)
+#define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN (0x1<<17)
+#define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN (0x1<<0)
+#define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN (0x1<<3)
+#define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN (0x1<<4)
+#define XMAC_PFC_CTRL_HI_REG_TX_PFC_EN (0x1<<5)
+#define XMAC_REG_CLEAR_RX_LSS_STATUS 0x60
+#define XMAC_REG_CTRL 0
+/* [RW 16] Upper 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
+ * packets transmitted by the MAC */
+#define XMAC_REG_CTRL_SA_HI 0x2c
+/* [RW 32] Lower 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
+ * packets transmitted by the MAC */
+#define XMAC_REG_CTRL_SA_LO 0x28
+#define XMAC_REG_PAUSE_CTRL 0x68
+#define XMAC_REG_PFC_CTRL 0x70
+#define XMAC_REG_PFC_CTRL_HI 0x74
+#define XMAC_REG_RX_LSS_STATUS 0x58
+/* [RW 14] Maximum packet size in receive direction; exclusive of preamble &
+ * CRC in strip mode */
+#define XMAC_REG_RX_MAX_SIZE 0x40
+#define XMAC_REG_TX_CTRL 0x20
/* [RW 16] Indirect access to the XX table of the XX protection mechanism.
The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] -
header pointer. */
@@ -4846,6 +5402,10 @@
#define XSDM_REG_NUM_OF_Q9_CMD 0x166268
/* [RW 13] The start address in the internal RAM for queue counters */
#define XSDM_REG_Q_COUNTER_START_ADDR 0x166010
+/* [W 17] Generate an operation after completion; bit-16 is
+ * AggVectIdx_valid; bits 15:8 are AggVectIdx; bits 7:5 are the TRIG and
+ * bits 4:0 are the T124Param[4:0] */
+#define XSDM_REG_OPERATION_GEN 0x1664c4
/* [R 1] pxp_ctrl rd_data fifo empty in sdm_dma_rsp block */
#define XSDM_REG_RSP_PXP_CTRL_RDATA_EMPTY 0x166548
/* [R 1] parser fifo empty in sdm_sync block */
@@ -5019,6 +5579,7 @@
#define BIGMAC_REGISTER_CNT_MAX_SIZE (0x05<<3)
#define BIGMAC_REGISTER_RX_CONTROL (0x21<<3)
#define BIGMAC_REGISTER_RX_LLFC_MSG_FLDS (0x46<<3)
+#define BIGMAC_REGISTER_RX_LSS_STATUS (0x43<<3)
#define BIGMAC_REGISTER_RX_MAX_SIZE (0x23<<3)
#define BIGMAC_REGISTER_RX_STAT_GR64 (0x26<<3)
#define BIGMAC_REGISTER_RX_STAT_GRIPJ (0x42<<3)
@@ -5034,6 +5595,7 @@
#define BIGMAC2_REGISTER_PFC_CONTROL (0x06<<3)
#define BIGMAC2_REGISTER_RX_CONTROL (0x3A<<3)
#define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS (0x62<<3)
+#define BIGMAC2_REGISTER_RX_LSS_STAT (0x3E<<3)
#define BIGMAC2_REGISTER_RX_MAX_SIZE (0x3C<<3)
#define BIGMAC2_REGISTER_RX_STAT_GR64 (0x40<<3)
#define BIGMAC2_REGISTER_RX_STAT_GRIPJ (0x5f<<3)
@@ -5052,7 +5614,9 @@
#define EMAC_LED_OVERRIDE (1L<<0)
#define EMAC_LED_TRAFFIC (1L<<6)
#define EMAC_MDIO_COMM_COMMAND_ADDRESS (0L<<26)
+#define EMAC_MDIO_COMM_COMMAND_READ_22 (2L<<26)
#define EMAC_MDIO_COMM_COMMAND_READ_45 (3L<<26)
+#define EMAC_MDIO_COMM_COMMAND_WRITE_22 (1L<<26)
#define EMAC_MDIO_COMM_COMMAND_WRITE_45 (1L<<26)
#define EMAC_MDIO_COMM_DATA (0xffffL<<0)
#define EMAC_MDIO_COMM_START_BUSY (1L<<29)
@@ -5128,16 +5692,30 @@
#define MISC_REGISTERS_RESET_REG_1_RST_PXPV (0x1<<27)
#define MISC_REGISTERS_RESET_REG_1_SET 0x584
#define MISC_REGISTERS_RESET_REG_2_CLEAR 0x598
+#define MISC_REGISTERS_RESET_REG_2_MSTAT0 (0x1<<24)
+#define MISC_REGISTERS_RESET_REG_2_MSTAT1 (0x1<<25)
+#define MISC_REGISTERS_RESET_REG_2_PGLC (0x1<<19)
+#define MISC_REGISTERS_RESET_REG_2_RST_ATC (0x1<<17)
#define MISC_REGISTERS_RESET_REG_2_RST_BMAC0 (0x1<<0)
+#define MISC_REGISTERS_RESET_REG_2_RST_BMAC1 (0x1<<1)
+#define MISC_REGISTERS_RESET_REG_2_RST_EMAC0 (0x1<<2)
#define MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE (0x1<<14)
+#define MISC_REGISTERS_RESET_REG_2_RST_EMAC1 (0x1<<3)
#define MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE (0x1<<15)
#define MISC_REGISTERS_RESET_REG_2_RST_GRC (0x1<<4)
#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B (0x1<<6)
+#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE (0x1<<8)
+#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU (0x1<<7)
#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE (0x1<<5)
#define MISC_REGISTERS_RESET_REG_2_RST_MDIO (0x1<<13)
#define MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE (0x1<<11)
+#define MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO (0x1<<13)
#define MISC_REGISTERS_RESET_REG_2_RST_RBCN (0x1<<9)
#define MISC_REGISTERS_RESET_REG_2_SET 0x594
+#define MISC_REGISTERS_RESET_REG_2_UMAC0 (0x1<<20)
+#define MISC_REGISTERS_RESET_REG_2_UMAC1 (0x1<<21)
+#define MISC_REGISTERS_RESET_REG_2_XMAC (0x1<<22)
+#define MISC_REGISTERS_RESET_REG_2_XMAC_SOFT (0x1<<23)
#define MISC_REGISTERS_RESET_REG_3_CLEAR 0x5a8
#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ (0x1<<1)
#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN (0x1<<2)
@@ -5160,74 +5738,86 @@
#define MISC_REGISTERS_SPIO_OUTPUT_HIGH 1
#define MISC_REGISTERS_SPIO_OUTPUT_LOW 0
#define MISC_REGISTERS_SPIO_SET_POS 8
+#define HW_LOCK_DRV_FLAGS 10
#define HW_LOCK_MAX_RESOURCE_VALUE 31
#define HW_LOCK_RESOURCE_GPIO 1
#define HW_LOCK_RESOURCE_MDIO 0
-#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
-#define HW_LOCK_RESOURCE_RESERVED_08 8
+#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
+#define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8
+#define HW_LOCK_RESOURCE_RECOVERY_LEADER_1 9
#define HW_LOCK_RESOURCE_SPIO 2
#define HW_LOCK_RESOURCE_UNDI 5
-#define PRS_FLAG_OVERETH_IPV4 1
-#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4)
-#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5)
-#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (1<<18)
-#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT (1<<31)
-#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT (1<<9)
-#define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR (1<<8)
-#define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT (1<<7)
-#define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR (1<<6)
-#define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT (1<<29)
-#define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR (1<<28)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT (1<<1)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR (1<<0)
-#define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR (1<<18)
-#define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT (1<<11)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT (1<<13)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR (1<<12)
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 (1<<5)
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 (1<<9)
-#define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR (1<<12)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY (1<<28)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY (1<<31)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY (1<<29)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY (1<<30)
-#define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT (1<<15)
-#define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR (1<<14)
-#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR (1<<20)
-#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR (1<<0)
-#define AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT (1<<31)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT (0x1<<2)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR (0x1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT (1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR (1<<2)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT (1<<5)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR (1<<4)
-#define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT (1<<3)
-#define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR (1<<2)
-#define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR (1<<22)
-#define AEU_INPUTS_ATTN_BITS_SPIO5 (1<<15)
-#define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT (1<<27)
-#define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT (1<<5)
-#define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT (1<<25)
-#define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR (1<<24)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT (1<<29)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR (1<<28)
-#define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT (1<<23)
-#define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT (1<<27)
-#define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR (1<<26)
-#define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT (1<<21)
-#define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR (1<<20)
-#define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT (1<<25)
-#define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR (1<<24)
-#define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR (1<<16)
-#define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT (1<<9)
-#define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT (1<<7)
-#define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR (1<<6)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT (1<<11)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR (1<<10)
+#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (0x1<<18)
+#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT (0x1<<9)
+#define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR (0x1<<8)
+#define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT (0x1<<7)
+#define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR (0x1<<6)
+#define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT (0x1<<1)
+#define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR (0x1<<0)
+#define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR (0x1<<18)
+#define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT (0x1<<11)
+#define AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR (0x1<<10)
+#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT (0x1<<13)
+#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR (0x1<<12)
+#define AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR (0x1<<12)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT (0x1<<15)
+#define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR (0x1<<14)
+#define AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR (0x1<<14)
+#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR (0x1<<20)
+#define AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR (0x1<<0)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR (0x1<<22)
+#define AEU_INPUTS_ATTN_BITS_SPIO5 (0x1<<15)
+#define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT (0x1<<27)
+#define AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR (0x1<<26)
+#define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT (0x1<<25)
+#define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR (0x1<<24)
+#define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT (0x1<<23)
+#define AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR (0x1<<22)
+#define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT (0x1<<27)
+#define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR (0x1<<26)
+#define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT (0x1<<21)
+#define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR (0x1<<20)
+#define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT (0x1<<25)
+#define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR (0x1<<24)
+#define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR (0x1<<16)
+#define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT (0x1<<9)
+#define AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR (0x1<<8)
+#define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT (0x1<<7)
+#define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR (0x1<<6)
+#define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT (0x1<<11)
+#define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR (0x1<<10)
+
+#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 (0x1<<9)
+
#define RESERVED_GENERAL_ATTENTION_BIT_0 0
-#define EVEREST_GEN_ATTN_IN_USE_MASK 0x3ffe0
+#define EVEREST_GEN_ATTN_IN_USE_MASK 0x7ffe0
#define EVEREST_LATCHED_ATTN_IN_USE_MASK 0xffe00000
#define RESERVED_GENERAL_ATTENTION_BIT_6 6
@@ -5317,7 +5907,13 @@
#define GRCBASE_HC 0x108000
#define GRCBASE_PXP2 0x120000
#define GRCBASE_PBF 0x140000
+#define GRCBASE_UMAC0 0x160000
+#define GRCBASE_UMAC1 0x160400
#define GRCBASE_XPB 0x161000
+#define GRCBASE_MSTAT0 0x162000
+#define GRCBASE_MSTAT1 0x162800
+#define GRCBASE_XMAC0 0x163000
+#define GRCBASE_XMAC1 0x163800
#define GRCBASE_TIMERS 0x164000
#define GRCBASE_XSDM 0x166000
#define GRCBASE_QM 0x168000
@@ -5883,6 +6479,10 @@
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G 0x0C00
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX 0x0D00
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4 0x0E00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR 0x0F00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI 0x1B00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS 0x1E00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI 0x1F00
#define MDIO_REG_BANK_10G_PARALLEL_DETECT 0x8130
@@ -6032,15 +6632,11 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_PMA_REG_CTRL 0x0
#define MDIO_PMA_REG_STATUS 0x1
#define MDIO_PMA_REG_10G_CTRL2 0x7
+#define MDIO_PMA_REG_TX_DISABLE 0x0009
#define MDIO_PMA_REG_RX_SD 0xa
/*bcm*/
#define MDIO_PMA_REG_BCM_CTRL 0x0096
#define MDIO_PMA_REG_FEC_CTRL 0x00ab
-#define MDIO_PMA_REG_RX_ALARM_CTRL 0x9000
-#define MDIO_PMA_REG_LASI_CTRL 0x9002
-#define MDIO_PMA_REG_RX_ALARM 0x9003
-#define MDIO_PMA_REG_TX_ALARM 0x9004
-#define MDIO_PMA_REG_LASI_STATUS 0x9005
#define MDIO_PMA_REG_PHY_IDENTIFIER 0xc800
#define MDIO_PMA_REG_DIGITAL_CTRL 0xc808
#define MDIO_PMA_REG_DIGITAL_STATUS 0xc809
@@ -6201,6 +6797,169 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_PMA_REG_84823_CTL_LED_CTL_1 0xa8e3
#define MDIO_PMA_REG_84823_LED3_STRETCH_EN 0x0080
+/* BCM84833 only */
+#define MDIO_84833_TOP_CFG_XGPHY_STRAP1 0x401a
+#define MDIO_84833_SUPER_ISOLATE 0x8000
+/* These are mailbox register set used by 84833. */
+#define MDIO_84833_TOP_CFG_SCRATCH_REG0 0x4005
+#define MDIO_84833_TOP_CFG_SCRATCH_REG1 0x4006
+#define MDIO_84833_TOP_CFG_SCRATCH_REG2 0x4007
+#define MDIO_84833_TOP_CFG_SCRATCH_REG3 0x4008
+#define MDIO_84833_TOP_CFG_SCRATCH_REG4 0x4009
+#define MDIO_84833_TOP_CFG_DATA3_REG 0x4011
+#define MDIO_84833_TOP_CFG_DATA4_REG 0x4012
+
+/* Mailbox command set used by 84833. */
+#define PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE 0x2
+/* Mailbox status set used by 84833. */
+#define PHY84833_CMD_RECEIVED 0x0001
+#define PHY84833_CMD_IN_PROGRESS 0x0002
+#define PHY84833_CMD_COMPLETE_PASS 0x0004
+#define PHY84833_CMD_COMPLETE_ERROR 0x0008
+#define PHY84833_CMD_OPEN_FOR_CMDS 0x0010
+#define PHY84833_CMD_SYSTEM_BOOT 0x0020
+#define PHY84833_CMD_NOT_OPEN_FOR_CMDS 0x0040
+#define PHY84833_CMD_CLEAR_COMPLETE 0x0080
+#define PHY84833_CMD_OPEN_OVERRIDE 0xa5a5
+
+
+/* 84833 F/W Feature Commands */
+#define PHY84833_DIAG_CMD_GET_EEE_MODE 0x27
+#define PHY84833_DIAG_CMD_SET_EEE_MODE 0x28
+
+/* Warpcore clause 45 addressing */
+#define MDIO_WC_DEVAD 0x3
+#define MDIO_WC_REG_IEEE0BLK_MIICNTL 0x0
+#define MDIO_WC_REG_IEEE0BLK_AUTONEGNP 0x7
+#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT0 0x10
+#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1 0x11
+#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150 0x96
+#define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL 0x8000
+#define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1 0x800e
+#define MDIO_WC_REG_XGXSBLK1_DESKEW 0x8010
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL0 0x8015
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL1 0x8016
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL2 0x8017
+#define MDIO_WC_REG_TX0_ANA_CTRL0 0x8061
+#define MDIO_WC_REG_TX1_ANA_CTRL0 0x8071
+#define MDIO_WC_REG_TX2_ANA_CTRL0 0x8081
+#define MDIO_WC_REG_TX3_ANA_CTRL0 0x8091
+#define MDIO_WC_REG_TX0_TX_DRIVER 0x8067
+#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET 0x04
+#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_MASK 0x00f0
+#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET 0x08
+#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_MASK 0x0f00
+#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET 0x0c
+#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_MASK 0x7000
+#define MDIO_WC_REG_TX1_TX_DRIVER 0x8077
+#define MDIO_WC_REG_TX2_TX_DRIVER 0x8087
+#define MDIO_WC_REG_TX3_TX_DRIVER 0x8097
+#define MDIO_WC_REG_RX0_ANARXCONTROL1G 0x80b9
+#define MDIO_WC_REG_RX2_ANARXCONTROL1G 0x80d9
+#define MDIO_WC_REG_RX0_PCI_CTRL 0x80ba
+#define MDIO_WC_REG_RX1_PCI_CTRL 0x80ca
+#define MDIO_WC_REG_RX2_PCI_CTRL 0x80da
+#define MDIO_WC_REG_RX3_PCI_CTRL 0x80ea
+#define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G 0x8104
+#define MDIO_WC_REG_XGXS_STATUS3 0x8129
+#define MDIO_WC_REG_PAR_DET_10G_STATUS 0x8130
+#define MDIO_WC_REG_PAR_DET_10G_CTRL 0x8131
+#define MDIO_WC_REG_XGXS_X2_CONTROL2 0x8141
+#define MDIO_WC_REG_XGXS_RX_LN_SWAP1 0x816B
+#define MDIO_WC_REG_XGXS_TX_LN_SWAP1 0x8169
+#define MDIO_WC_REG_GP2_STATUS_GP_2_0 0x81d0
+#define MDIO_WC_REG_GP2_STATUS_GP_2_1 0x81d1
+#define MDIO_WC_REG_GP2_STATUS_GP_2_2 0x81d2
+#define MDIO_WC_REG_GP2_STATUS_GP_2_3 0x81d3
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4 0x81d4
+#define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP 0x81EE
+#define MDIO_WC_REG_UC_INFO_B1_VERSION 0x81F0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE 0x81F2
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE0_OFFSET 0x0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT 0x0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_OPT_LR 0x1
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC 0x2
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_XLAUI 0x3
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_LONG_CH_6G 0x4
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE1_OFFSET 0x4
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE2_OFFSET 0x8
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE3_OFFSET 0xc
+#define MDIO_WC_REG_UC_INFO_B1_CRC 0x81FE
+#define MDIO_WC_REG_DSC_SMC 0x8213
+#define MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0 0x821e
+#define MDIO_WC_REG_TX_FIR_TAP 0x82e2
+#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET 0x00
+#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_MASK 0x000f
+#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET 0x04
+#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_MASK 0x03f0
+#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET 0x0a
+#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK 0x7c00
+#define MDIO_WC_REG_TX_FIR_TAP_ENABLE 0x8000
+#define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL 0x82e3
+#define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL 0x82e6
+#define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL 0x82e7
+#define MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL 0x82e8
+#define MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL 0x82ec
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1 0x8300
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2 0x8301
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3 0x8302
+#define MDIO_WC_REG_SERDESDIGITAL_STATUS1000X1 0x8304
+#define MDIO_WC_REG_SERDESDIGITAL_MISC1 0x8308
+#define MDIO_WC_REG_SERDESDIGITAL_MISC2 0x8309
+#define MDIO_WC_REG_DIGITAL3_UP1 0x8329
+#define MDIO_WC_REG_DIGITAL4_MISC3 0x833c
+#define MDIO_WC_REG_DIGITAL5_MISC6 0x8345
+#define MDIO_WC_REG_DIGITAL5_MISC7 0x8349
+#define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED 0x834e
+#define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL 0x8350
+#define MDIO_WC_REG_CL49_USERB0_CTRL 0x8368
+#define MDIO_WC_REG_TX66_CONTROL 0x83b0
+#define MDIO_WC_REG_RX66_CONTROL 0x83c0
+#define MDIO_WC_REG_RX66_SCW0 0x83c2
+#define MDIO_WC_REG_RX66_SCW1 0x83c3
+#define MDIO_WC_REG_RX66_SCW2 0x83c4
+#define MDIO_WC_REG_RX66_SCW3 0x83c5
+#define MDIO_WC_REG_RX66_SCW0_MASK 0x83c6
+#define MDIO_WC_REG_RX66_SCW1_MASK 0x83c7
+#define MDIO_WC_REG_RX66_SCW2_MASK 0x83c8
+#define MDIO_WC_REG_RX66_SCW3_MASK 0x83c9
+#define MDIO_WC_REG_FX100_CTRL1 0x8400
+#define MDIO_WC_REG_FX100_CTRL3 0x8402
+
+#define MDIO_WC_REG_MICROBLK_CMD 0xffc2
+#define MDIO_WC_REG_MICROBLK_DL_STATUS 0xffc5
+#define MDIO_WC_REG_MICROBLK_CMD3 0xffcc
+
+#define MDIO_WC_REG_AERBLK_AER 0xffde
+#define MDIO_WC_REG_COMBO_IEEE0_MIICTRL 0xffe0
+#define MDIO_WC_REG_COMBO_IEEE0_MIIISTAT 0xffe1
+
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET 0x810A
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET_RX_BITSHIFT 0
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET_TX_BITSHIFT 4
+
+#define MDIO_WC0_XGXS_BLK6_XGXS_X2_CONTROL2 0x8141
+
+#define DIGITAL5_ACTUAL_SPEED_TX_MASK 0x003f
+
+/* 54618se */
+#define MDIO_REG_GPHY_PHYID_LSB 0x3
+#define MDIO_REG_GPHY_ID_54618SE 0x5cd5
+#define MDIO_REG_GPHY_CL45_ADDR_REG 0xd
+#define MDIO_REG_GPHY_CL45_DATA_REG 0xe
+#define MDIO_REG_GPHY_EEE_ADV 0x3c
+#define MDIO_REG_GPHY_EEE_1G (0x1 << 2)
+#define MDIO_REG_GPHY_EEE_100 (0x1 << 1)
+#define MDIO_REG_GPHY_EEE_RESOLVED 0x803e
+#define MDIO_REG_INTR_STATUS 0x1a
+#define MDIO_REG_INTR_MASK 0x1b
+#define MDIO_REG_INTR_MASK_LINK_STATUS (0x1 << 1)
+#define MDIO_REG_GPHY_SHADOW 0x1c
+#define MDIO_REG_GPHY_SHADOW_LED_SEL2 (0x0e << 10)
+#define MDIO_REG_GPHY_SHADOW_WR_ENA (0x1 << 15)
+#define MDIO_REG_GPHY_SHADOW_AUTO_DET_MED (0x1e << 10)
+#define MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD (0x1 << 8)
+
#define IGU_FUNC_BASE 0x0400
#define IGU_ADDR_MSIX 0x0000
@@ -6217,11 +6976,6 @@ Theotherbitsarereservedandshouldbezero*/
#define IGU_ADDR_MSI_ADDR_HI 0x0212
#define IGU_ADDR_MSI_DATA 0x0213
-#define IGU_INT_ENABLE 0
-#define IGU_INT_DISABLE 1
-#define IGU_INT_NOP 2
-#define IGU_INT_NOP2 3
-
#define IGU_USE_REGISTER_ustorm_type_0_sb_cleanup 0
#define IGU_USE_REGISTER_ustorm_type_1_sb_cleanup 1
#define IGU_USE_REGISTER_cstorm_type_0_sb_cleanup 2
@@ -6292,15 +7046,6 @@ Theotherbitsarereservedandshouldbezero*/
#define IGU_BC_BASE_DSB_PROD 128
#define IGU_NORM_BASE_DSB_PROD 136
-#define IGU_CTRL_CMD_TYPE_WR\
- 1
-#define IGU_CTRL_CMD_TYPE_RD\
- 0
-
-#define IGU_SEG_ACCESS_NORM 0
-#define IGU_SEG_ACCESS_DEF 1
-#define IGU_SEG_ACCESS_ATTN 2
-
/* FID (if VF - [6] = 0; [5:0] = VF number; if PF - [6] = 1; \
[5:2] = 0; [1:0] = PF number) */
#define IGU_FID_ENCODE_IS_PF (0x1<<6)
diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c
new file mode 100644
index 000000000000..df52f110c6c5
--- /dev/null
+++ b/drivers/net/bnx2x/bnx2x_sp.c
@@ -0,0 +1,5692 @@
+/* bnx2x_sp.c: Broadcom Everest network driver.
+ *
+ * Copyright 2011 Broadcom Corporation
+ *
+ * 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.gnu.org/licenses/old-licenses/gpl-2.0.html (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.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov
+ *
+ */
+#include <linux/module.h>
+#include <linux/crc32.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32c.h>
+#include "bnx2x.h"
+#include "bnx2x_cmn.h"
+#include "bnx2x_sp.h"
+
+#define BNX2X_MAX_EMUL_MULTI 16
+
+/**** Exe Queue interfaces ****/
+
+/**
+ * bnx2x_exe_queue_init - init the Exe Queue object
+ *
+ * @o: poiter to the object
+ * @exe_len: length
+ * @owner: poiter to the owner
+ * @validate: validate function pointer
+ * @optimize: optimize function pointer
+ * @exec: execute function pointer
+ * @get: get function pointer
+ */
+static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o,
+ int exe_len,
+ union bnx2x_qable_obj *owner,
+ exe_q_validate validate,
+ exe_q_optimize optimize,
+ exe_q_execute exec,
+ exe_q_get get)
+{
+ memset(o, 0, sizeof(*o));
+
+ INIT_LIST_HEAD(&o->exe_queue);
+ INIT_LIST_HEAD(&o->pending_comp);
+
+ spin_lock_init(&o->lock);
+
+ o->exe_chunk_len = exe_len;
+ o->owner = owner;
+
+ /* Owner specific callbacks */
+ o->validate = validate;
+ o->optimize = optimize;
+ o->execute = exec;
+ o->get = get;
+
+ DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk "
+ "length of %d\n", exe_len);
+}
+
+static inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp,
+ struct bnx2x_exeq_elem *elem)
+{
+ DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n");
+ kfree(elem);
+}
+
+static inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o)
+{
+ struct bnx2x_exeq_elem *elem;
+ int cnt = 0;
+
+ spin_lock_bh(&o->lock);
+
+ list_for_each_entry(elem, &o->exe_queue, link)
+ cnt++;
+
+ spin_unlock_bh(&o->lock);
+
+ return cnt;
+}
+
+/**
+ * bnx2x_exe_queue_add - add a new element to the execution queue
+ *
+ * @bp: driver handle
+ * @o: queue
+ * @cmd: new command to add
+ * @restore: true - do not optimize the command
+ *
+ * If the element is optimized or is illegal, frees it.
+ */
+static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ bool restore)
+{
+ int rc;
+
+ spin_lock_bh(&o->lock);
+
+ if (!restore) {
+ /* Try to cancel this element queue */
+ rc = o->optimize(bp, o->owner, elem);
+ if (rc)
+ goto free_and_exit;
+
+ /* Check if this request is ok */
+ rc = o->validate(bp, o->owner, elem);
+ if (rc) {
+ BNX2X_ERR("Preamble failed: %d\n", rc);
+ goto free_and_exit;
+ }
+ }
+
+ /* If so, add it to the execution queue */
+ list_add_tail(&elem->link, &o->exe_queue);
+
+ spin_unlock_bh(&o->lock);
+
+ return 0;
+
+free_and_exit:
+ bnx2x_exe_queue_free_elem(bp, elem);
+
+ spin_unlock_bh(&o->lock);
+
+ return rc;
+
+}
+
+static inline void __bnx2x_exe_queue_reset_pending(
+ struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o)
+{
+ struct bnx2x_exeq_elem *elem;
+
+ while (!list_empty(&o->pending_comp)) {
+ elem = list_first_entry(&o->pending_comp,
+ struct bnx2x_exeq_elem, link);
+
+ list_del(&elem->link);
+ bnx2x_exe_queue_free_elem(bp, elem);
+ }
+}
+
+static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o)
+{
+
+ spin_lock_bh(&o->lock);
+
+ __bnx2x_exe_queue_reset_pending(bp, o);
+
+ spin_unlock_bh(&o->lock);
+
+}
+
+/**
+ * bnx2x_exe_queue_step - execute one execution chunk atomically
+ *
+ * @bp: driver handle
+ * @o: queue
+ * @ramrod_flags: flags
+ *
+ * (Atomicy is ensured using the exe_queue->lock).
+ */
+static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_exeq_elem *elem, spacer;
+ int cur_len = 0, rc;
+
+ memset(&spacer, 0, sizeof(spacer));
+
+ spin_lock_bh(&o->lock);
+
+ /*
+ * Next step should not be performed until the current is finished,
+ * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
+ * properly clear object internals without sending any command to the FW
+ * which also implies there won't be any completion to clear the
+ * 'pending' list.
+ */
+ if (!list_empty(&o->pending_comp)) {
+ if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
+ DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
+ "resetting pending_comp\n");
+ __bnx2x_exe_queue_reset_pending(bp, o);
+ } else {
+ spin_unlock_bh(&o->lock);
+ return 1;
+ }
+ }
+
+ /*
+ * Run through the pending commands list and create a next
+ * execution chunk.
+ */
+ while (!list_empty(&o->exe_queue)) {
+ elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem,
+ link);
+ WARN_ON(!elem->cmd_len);
+
+ if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
+ cur_len += elem->cmd_len;
+ /*
+ * Prevent from both lists being empty when moving an
+ * element. This will allow the call of
+ * bnx2x_exe_queue_empty() without locking.
+ */
+ list_add_tail(&spacer.link, &o->pending_comp);
+ mb();
+ list_del(&elem->link);
+ list_add_tail(&elem->link, &o->pending_comp);
+ list_del(&spacer.link);
+ } else
+ break;
+ }
+
+ /* Sanity check */
+ if (!cur_len) {
+ spin_unlock_bh(&o->lock);
+ return 0;
+ }
+
+ rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
+ if (rc < 0)
+ /*
+ * In case of an error return the commands back to the queue
+ * and reset the pending_comp.
+ */
+ list_splice_init(&o->pending_comp, &o->exe_queue);
+ else if (!rc)
+ /*
+ * If zero is returned, means there are no outstanding pending
+ * completions and we may dismiss the pending list.
+ */
+ __bnx2x_exe_queue_reset_pending(bp, o);
+
+ spin_unlock_bh(&o->lock);
+ return rc;
+}
+
+static inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o)
+{
+ bool empty = list_empty(&o->exe_queue);
+
+ /* Don't reorder!!! */
+ mb();
+
+ return empty && list_empty(&o->pending_comp);
+}
+
+static inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem(
+ struct bnx2x *bp)
+{
+ DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n");
+ return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC);
+}
+
+/************************ raw_obj functions ***********************************/
+static bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o)
+{
+ return !!test_bit(o->state, o->pstate);
+}
+
+static void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(o->state, o->pstate);
+ smp_mb__after_clear_bit();
+}
+
+static void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o)
+{
+ smp_mb__before_clear_bit();
+ set_bit(o->state, o->pstate);
+ smp_mb__after_clear_bit();
+}
+
+/**
+ * bnx2x_state_wait - wait until the given bit(state) is cleared
+ *
+ * @bp: device handle
+ * @state: state which is to be cleared
+ * @state_p: state buffer
+ *
+ */
+static inline int bnx2x_state_wait(struct bnx2x *bp, int state,
+ unsigned long *pstate)
+{
+ /* can take a while if any port is running */
+ int cnt = 5000;
+
+
+ if (CHIP_REV_IS_EMUL(bp))
+ cnt *= 20;
+
+ DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state);
+
+ might_sleep();
+ while (cnt--) {
+ if (!test_bit(state, pstate)) {
+#ifdef BNX2X_STOP_ON_ERROR
+ DP(BNX2X_MSG_SP, "exit (cnt %d)\n", 5000 - cnt);
+#endif
+ return 0;
+ }
+
+ usleep_range(1000, 1000);
+
+ if (bp->panic)
+ return -EIO;
+ }
+
+ /* timeout! */
+ BNX2X_ERR("timeout waiting for state %d\n", state);
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+#endif
+
+ return -EBUSY;
+}
+
+static int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw)
+{
+ return bnx2x_state_wait(bp, raw->state, raw->pstate);
+}
+
+/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
+/* credit handling callbacks */
+static bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ WARN_ON(!mp);
+
+ return mp->get_entry(mp, offset);
+}
+
+static bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ WARN_ON(!mp);
+
+ return mp->get(mp, 1);
+}
+
+static bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ WARN_ON(!vp);
+
+ return vp->get_entry(vp, offset);
+}
+
+static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ WARN_ON(!vp);
+
+ return vp->get(vp, 1);
+}
+
+static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ if (!mp->get(mp, 1))
+ return false;
+
+ if (!vp->get(vp, 1)) {
+ mp->put(mp, 1);
+ return false;
+ }
+
+ return true;
+}
+
+static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ return mp->put_entry(mp, offset);
+}
+
+static bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ return mp->put(mp, 1);
+}
+
+static bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ return vp->put_entry(vp, offset);
+}
+
+static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ return vp->put(vp, 1);
+}
+
+static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ if (!mp->put(mp, 1))
+ return false;
+
+ if (!vp->put(vp, 1)) {
+ mp->get(mp, 1);
+ return false;
+ }
+
+ return true;
+}
+
+/* check_add() callbacks */
+static int bnx2x_check_mac_add(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ if (!is_valid_ether_addr(data->mac.mac))
+ return -EINVAL;
+
+ /* Check if a requested MAC already exists */
+ list_for_each_entry(pos, &o->head, link)
+ if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
+ return -EEXIST;
+
+ return 0;
+}
+
+static int bnx2x_check_vlan_add(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if (data->vlan.vlan == pos->u.vlan.vlan)
+ return -EEXIST;
+
+ return 0;
+}
+
+static int bnx2x_check_vlan_mac_add(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
+ (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
+ ETH_ALEN)))
+ return -EEXIST;
+
+ return 0;
+}
+
+
+/* check_del() callbacks */
+static struct bnx2x_vlan_mac_registry_elem *
+ bnx2x_check_mac_del(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_vlan_mac_registry_elem *
+ bnx2x_check_vlan_del(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if (data->vlan.vlan == pos->u.vlan.vlan)
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_vlan_mac_registry_elem *
+ bnx2x_check_vlan_mac_del(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
+ (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
+ ETH_ALEN)))
+ return pos;
+
+ return NULL;
+}
+
+/* check_move() callback */
+static bool bnx2x_check_move(struct bnx2x_vlan_mac_obj *src_o,
+ struct bnx2x_vlan_mac_obj *dst_o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+ int rc;
+
+ /* Check if we can delete the requested configuration from the first
+ * object.
+ */
+ pos = src_o->check_del(src_o, data);
+
+ /* check if configuration can be added */
+ rc = dst_o->check_add(dst_o, data);
+
+ /* If this classification can not be added (is already set)
+ * or can't be deleted - return an error.
+ */
+ if (rc || !pos)
+ return false;
+
+ return true;
+}
+
+static bool bnx2x_check_move_always_err(
+ struct bnx2x_vlan_mac_obj *src_o,
+ struct bnx2x_vlan_mac_obj *dst_o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ return false;
+}
+
+
+static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ u8 rx_tx_flag = 0;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
+
+ return rx_tx_flag;
+}
+
+/* LLH CAM line allocations */
+enum {
+ LLH_CAM_ISCSI_ETH_LINE = 0,
+ LLH_CAM_ETH_LINE,
+ LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2
+};
+
+static inline void bnx2x_set_mac_in_nig(struct bnx2x *bp,
+ bool add, unsigned char *dev_addr, int index)
+{
+ u32 wb_data[2];
+ u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
+ NIG_REG_LLH0_FUNC_MEM;
+
+ if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
+ return;
+
+ DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
+ (add ? "ADD" : "DELETE"), index);
+
+ if (add) {
+ /* LLH_FUNC_MEM is a u64 WB register */
+ reg_offset += 8*index;
+
+ wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
+ (dev_addr[4] << 8) | dev_addr[5]);
+ wb_data[1] = ((dev_addr[0] << 8) | dev_addr[1]);
+
+ REG_WR_DMAE(bp, reg_offset, wb_data, 2);
+ }
+
+ REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
+ NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
+}
+
+/**
+ * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
+ *
+ * @bp: device handle
+ * @o: queue for which we want to configure this rule
+ * @add: if true the command is an ADD command, DEL otherwise
+ * @opcode: CLASSIFY_RULE_OPCODE_XXX
+ * @hdr: pointer to a header to setup
+ *
+ */
+static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, bool add, int opcode,
+ struct eth_classify_cmd_header *hdr)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ hdr->client_id = raw->cl_id;
+ hdr->func_id = raw->func_id;
+
+ /* Rx or/and Tx (internal switching) configuration ? */
+ hdr->cmd_general_data |=
+ bnx2x_vlan_mac_get_rx_tx_flag(o);
+
+ if (add)
+ hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
+
+ hdr->cmd_general_data |=
+ (opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
+}
+
+/**
+ * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
+ *
+ * @cid: connection id
+ * @type: BNX2X_FILTER_XXX_PENDING
+ * @hdr: poiter to header to setup
+ * @rule_cnt:
+ *
+ * currently we always configure one rule and echo field to contain a CID and an
+ * opcode type.
+ */
+static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
+ struct eth_classify_header *hdr, int rule_cnt)
+{
+ hdr->echo = (cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT);
+ hdr->rule_cnt = (u8)rule_cnt;
+}
+
+
+/* hw_config() callbacks */
+static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct eth_classify_rules_ramrod_data *data =
+ (struct eth_classify_rules_ramrod_data *)(raw->rdata);
+ int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
+ union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+ bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+ unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
+ u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
+
+ /*
+ * Set LLH CAM entry: currently only iSCSI and ETH macs are
+ * relevant. In addition, current implementation is tuned for a
+ * single ETH MAC.
+ *
+ * When multiple unicast ETH MACs PF configuration in switch
+ * independent mode is required (NetQ, multiple netdev MACs,
+ * etc.), consider better utilisation of 8 per function MAC
+ * entries in the LLH register. There is also
+ * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
+ * total number of CAM entries to 16.
+ *
+ * Currently we won't configure NIG for MACs other than a primary ETH
+ * MAC and iSCSI L2 MAC.
+ *
+ * If this MAC is moving from one Queue to another, no need to change
+ * NIG configuration.
+ */
+ if (cmd != BNX2X_VLAN_MAC_MOVE) {
+ if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags))
+ bnx2x_set_mac_in_nig(bp, add, mac,
+ LLH_CAM_ISCSI_ETH_LINE);
+ else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags))
+ bnx2x_set_mac_in_nig(bp, add, mac, LLH_CAM_ETH_LINE);
+ }
+
+ /* Reset the ramrod data buffer for the first rule */
+ if (rule_idx == 0)
+ memset(data, 0, sizeof(*data));
+
+ /* Setup a command header */
+ 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);
+
+ /* Set a MAC itself */
+ bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
+ &rule_entry->mac.mac_mid,
+ &rule_entry->mac.mac_lsb, mac);
+
+ /* MOVE: Add a rule that will add this MAC to the target Queue */
+ if (cmd == BNX2X_VLAN_MAC_MOVE) {
+ rule_entry++;
+ rule_cnt++;
+
+ /* Setup ramrod data */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+ elem->cmd_data.vlan_mac.target_obj,
+ true, CLASSIFY_RULE_OPCODE_MAC,
+ &rule_entry->mac.header);
+
+ /* Set a MAC itself */
+ bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
+ &rule_entry->mac.mac_mid,
+ &rule_entry->mac.mac_lsb, mac);
+ }
+
+ /* Set the ramrod data header */
+ /* TODO: take this to the higher level in order to prevent multiple
+ writing */
+ bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+ rule_cnt);
+}
+
+/**
+ * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
+ *
+ * @bp: device handle
+ * @o: queue
+ * @type:
+ * @cam_offset: offset in cam memory
+ * @hdr: pointer to a header to setup
+ *
+ * E1/E1H
+ */
+static inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, int type, int cam_offset,
+ struct mac_configuration_hdr *hdr)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+
+ hdr->length = 1;
+ hdr->offset = (u8)cam_offset;
+ hdr->client_id = 0xff;
+ hdr->echo = ((r->cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT));
+}
+
+static inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac,
+ u16 vlan_id, struct mac_configuration_entry *cfg_entry)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ u32 cl_bit_vec = (1 << r->cl_id);
+
+ cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec);
+ cfg_entry->pf_id = r->func_id;
+ cfg_entry->vlan_id = cpu_to_le16(vlan_id);
+
+ if (add) {
+ SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_SET);
+ SET_FLAG(cfg_entry->flags,
+ MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode);
+
+ /* Set a MAC in a ramrod data */
+ bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
+ &cfg_entry->middle_mac_addr,
+ &cfg_entry->lsb_mac_addr, mac);
+ } else
+ SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+}
+
+static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add,
+ u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config)
+{
+ struct mac_configuration_entry *cfg_entry = &config->config_table[0];
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset,
+ &config->hdr);
+ 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);
+}
+
+/**
+ * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ * @elem: bnx2x_exeq_elem
+ * @rule_idx: rule_idx
+ * @cam_offset: cam_offset
+ */
+static void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct mac_configuration_cmd *config =
+ (struct mac_configuration_cmd *)(raw->rdata);
+ /*
+ * 57710 and 57711 do not support MOVE command,
+ * so it's either ADD or DEL
+ */
+ bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+ true : false;
+
+ /* Reset the ramrod data buffer */
+ memset(config, 0, sizeof(*config));
+
+ bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_MAC_PENDING,
+ cam_offset, add,
+ elem->cmd_data.vlan_mac.u.mac.mac, 0,
+ ETH_VLAN_FILTER_ANY_VLAN, config);
+}
+
+static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct eth_classify_rules_ramrod_data *data =
+ (struct eth_classify_rules_ramrod_data *)(raw->rdata);
+ int rule_cnt = rule_idx + 1;
+ union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+ int cmd = elem->cmd_data.vlan_mac.cmd;
+ bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+ u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
+
+ /* Reset the ramrod data buffer for the first rule */
+ if (rule_idx == 0)
+ memset(data, 0, sizeof(*data));
+
+ /* Set a rule header */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN,
+ &rule_entry->vlan.header);
+
+ DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"),
+ vlan);
+
+ /* Set a VLAN itself */
+ rule_entry->vlan.vlan = cpu_to_le16(vlan);
+
+ /* MOVE: Add a rule that will add this MAC to the target Queue */
+ if (cmd == BNX2X_VLAN_MAC_MOVE) {
+ rule_entry++;
+ rule_cnt++;
+
+ /* Setup ramrod data */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+ elem->cmd_data.vlan_mac.target_obj,
+ true, CLASSIFY_RULE_OPCODE_VLAN,
+ &rule_entry->vlan.header);
+
+ /* Set a VLAN itself */
+ rule_entry->vlan.vlan = cpu_to_le16(vlan);
+ }
+
+ /* Set the ramrod data header */
+ /* TODO: take this to the higher level in order to prevent multiple
+ writing */
+ bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+ rule_cnt);
+}
+
+static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ int rule_idx, int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct eth_classify_rules_ramrod_data *data =
+ (struct eth_classify_rules_ramrod_data *)(raw->rdata);
+ int rule_cnt = rule_idx + 1;
+ union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+ int cmd = elem->cmd_data.vlan_mac.cmd;
+ bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+ u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
+ u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
+
+
+ /* Reset the ramrod data buffer for the first rule */
+ if (rule_idx == 0)
+ memset(data, 0, sizeof(*data));
+
+ /* Set a rule header */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
+ &rule_entry->pair.header);
+
+ /* Set VLAN and MAC themselvs */
+ rule_entry->pair.vlan = cpu_to_le16(vlan);
+ bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
+ &rule_entry->pair.mac_mid,
+ &rule_entry->pair.mac_lsb, mac);
+
+ /* MOVE: Add a rule that will add this MAC to the target Queue */
+ if (cmd == BNX2X_VLAN_MAC_MOVE) {
+ rule_entry++;
+ rule_cnt++;
+
+ /* Setup ramrod data */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+ elem->cmd_data.vlan_mac.target_obj,
+ true, CLASSIFY_RULE_OPCODE_PAIR,
+ &rule_entry->pair.header);
+
+ /* Set a VLAN itself */
+ rule_entry->pair.vlan = cpu_to_le16(vlan);
+ bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
+ &rule_entry->pair.mac_mid,
+ &rule_entry->pair.mac_lsb, mac);
+ }
+
+ /* Set the ramrod data header */
+ /* TODO: take this to the higher level in order to prevent multiple
+ writing */
+ bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+ rule_cnt);
+}
+
+/**
+ * bnx2x_set_one_vlan_mac_e1h -
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ * @elem: bnx2x_exeq_elem
+ * @rule_idx: rule_idx
+ * @cam_offset: cam_offset
+ */
+static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ int rule_idx, int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct mac_configuration_cmd *config =
+ (struct mac_configuration_cmd *)(raw->rdata);
+ /*
+ * 57710 and 57711 do not support MOVE command,
+ * so it's either ADD or DEL
+ */
+ bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+ true : false;
+
+ /* Reset the ramrod data buffer */
+ memset(config, 0, sizeof(*config));
+
+ bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
+ cam_offset, add,
+ elem->cmd_data.vlan_mac.u.vlan_mac.mac,
+ elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
+ ETH_VLAN_FILTER_CLASSIFY, config);
+}
+
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
+ *
+ * @bp: device handle
+ * @p: command parameters
+ * @ppos: pointer to the cooky
+ *
+ * reconfigure next MAC/VLAN/VLAN-MAC element from the
+ * previously configured elements list.
+ *
+ * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is taken
+ * into an account
+ *
+ * pointer to the cooky - that should be given back in the next call to make
+ * function handle the next element. If *ppos is set to NULL it will restart the
+ * iterator. If returned *ppos == NULL this means that the last element has been
+ * handled.
+ *
+ */
+static int bnx2x_vlan_mac_restore(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p,
+ struct bnx2x_vlan_mac_registry_elem **ppos)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+ struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+
+ /* If list is empty - there is nothing to do here */
+ if (list_empty(&o->head)) {
+ *ppos = NULL;
+ return 0;
+ }
+
+ /* make a step... */
+ if (*ppos == NULL)
+ *ppos = list_first_entry(&o->head,
+ struct bnx2x_vlan_mac_registry_elem,
+ link);
+ else
+ *ppos = list_next_entry(*ppos, link);
+
+ pos = *ppos;
+
+ /* If it's the last step - return NULL */
+ if (list_is_last(&pos->link, &o->head))
+ *ppos = NULL;
+
+ /* Prepare a 'user_req' */
+ memcpy(&p->user_req.u, &pos->u, sizeof(pos->u));
+
+ /* Set the command */
+ p->user_req.cmd = BNX2X_VLAN_MAC_ADD;
+
+ /* Set vlan_mac_flags */
+ p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
+
+ /* Set a restore bit */
+ __set_bit(RAMROD_RESTORE, &p->ramrod_flags);
+
+ return bnx2x_config_vlan_mac(bp, p);
+}
+
+/*
+ * bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
+ * pointer to an element with a specific criteria and NULL if such an element
+ * hasn't been found.
+ */
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_mac(
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem *pos;
+ struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
+
+ /* Check pending for execution commands */
+ list_for_each_entry(pos, &o->exe_queue, link)
+ if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data,
+ sizeof(*data)) &&
+ (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem *pos;
+ struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
+
+ /* Check pending for execution commands */
+ list_for_each_entry(pos, &o->exe_queue, link)
+ if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data,
+ sizeof(*data)) &&
+ (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem *pos;
+ struct bnx2x_vlan_mac_ramrod_data *data =
+ &elem->cmd_data.vlan_mac.u.vlan_mac;
+
+ /* Check pending for execution commands */
+ list_for_each_entry(pos, &o->exe_queue, link)
+ if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
+ sizeof(*data)) &&
+ (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+ return pos;
+
+ return NULL;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
+ *
+ * @bp: device handle
+ * @qo: bnx2x_qable_obj
+ * @elem: bnx2x_exeq_elem
+ *
+ * Checks that the requested configuration can be added. If yes and if
+ * requested, consume CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ *
+ */
+static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ int rc;
+
+ /* Check the registry */
+ rc = o->check_add(o, &elem->cmd_data.vlan_mac.u);
+ if (rc) {
+ DP(BNX2X_MSG_SP, "ADD command is not allowed considering "
+ "current registry state\n");
+ return rc;
+ }
+
+ /*
+ * Check if there is a pending ADD command for this
+ * MAC/VLAN/VLAN-MAC. Return an error if there is.
+ */
+ if (exeq->get(exeq, elem)) {
+ DP(BNX2X_MSG_SP, "There is a pending ADD command already\n");
+ return -EEXIST;
+ }
+
+ /*
+ * TODO: Check the pending MOVE from other objects where this
+ * object is a destination object.
+ */
+
+ /* Consume the credit if not requested not to */
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ o->get_credit(o)))
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed
+ *
+ * @bp: device handle
+ * @qo: quable object to check
+ * @elem: element that needs to be deleted
+ *
+ * Checks that the requested configuration can be deleted. If yes and if
+ * requested, returns a CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ */
+static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+ struct bnx2x_vlan_mac_registry_elem *pos;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ struct bnx2x_exeq_elem query_elem;
+
+ /* If this classification can not be deleted (doesn't exist)
+ * - return a BNX2X_EXIST.
+ */
+ pos = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+ if (!pos) {
+ DP(BNX2X_MSG_SP, "DEL command is not allowed considering "
+ "current registry state\n");
+ return -EEXIST;
+ }
+
+ /*
+ * Check if there are pending DEL or MOVE commands for this
+ * MAC/VLAN/VLAN-MAC. Return an error if so.
+ */
+ memcpy(&query_elem, elem, sizeof(query_elem));
+
+ /* Check for MOVE commands */
+ query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE;
+ if (exeq->get(exeq, &query_elem)) {
+ BNX2X_ERR("There is a pending MOVE command already\n");
+ return -EINVAL;
+ }
+
+ /* Check for DEL commands */
+ if (exeq->get(exeq, elem)) {
+ DP(BNX2X_MSG_SP, "There is a pending DEL command already\n");
+ return -EEXIST;
+ }
+
+ /* Return the credit to the credit pool if not requested not to */
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ o->put_credit(o))) {
+ BNX2X_ERR("Failed to return a credit\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed
+ *
+ * @bp: device handle
+ * @qo: quable object to check (source)
+ * @elem: element that needs to be moved
+ *
+ * Checks that the requested configuration can be moved. If yes and if
+ * requested, returns a CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ */
+static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac;
+ struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
+ struct bnx2x_exeq_elem query_elem;
+ struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
+ struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
+
+ /*
+ * Check if we can perform this operation based on the current registry
+ * state.
+ */
+ if (!src_o->check_move(src_o, dest_o, &elem->cmd_data.vlan_mac.u)) {
+ DP(BNX2X_MSG_SP, "MOVE command is not allowed considering "
+ "current registry state\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Check if there is an already pending DEL or MOVE command for the
+ * source object or ADD command for a destination object. Return an
+ * error if so.
+ */
+ memcpy(&query_elem, elem, sizeof(query_elem));
+
+ /* Check DEL on source */
+ query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
+ if (src_exeq->get(src_exeq, &query_elem)) {
+ BNX2X_ERR("There is a pending DEL command on the source "
+ "queue already\n");
+ return -EINVAL;
+ }
+
+ /* Check MOVE on source */
+ if (src_exeq->get(src_exeq, elem)) {
+ DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n");
+ return -EEXIST;
+ }
+
+ /* Check ADD on destination */
+ query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
+ if (dest_exeq->get(dest_exeq, &query_elem)) {
+ BNX2X_ERR("There is a pending ADD command on the "
+ "destination queue already\n");
+ return -EINVAL;
+ }
+
+ /* Consume the credit if not requested not to */
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ dest_o->get_credit(dest_o)))
+ return -EINVAL;
+
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ src_o->put_credit(src_o))) {
+ /* return the credit taken from dest... */
+ dest_o->put_credit(dest_o);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ switch (elem->cmd_data.vlan_mac.cmd) {
+ case BNX2X_VLAN_MAC_ADD:
+ return bnx2x_validate_vlan_mac_add(bp, qo, elem);
+ case BNX2X_VLAN_MAC_DEL:
+ return bnx2x_validate_vlan_mac_del(bp, qo, elem);
+ case BNX2X_VLAN_MAC_MOVE:
+ return bnx2x_validate_vlan_mac_move(bp, qo, elem);
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ *
+ */
+static int bnx2x_wait_vlan_mac(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o)
+{
+ int cnt = 5000, rc;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ while (cnt--) {
+ /* Wait for the current command to complete */
+ rc = raw->wait_comp(bp, raw);
+ if (rc)
+ return rc;
+
+ /* Wait until there are no pending commands */
+ if (!bnx2x_exe_queue_empty(exeq))
+ usleep_range(1000, 1000);
+ else
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+/**
+ * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ * @cqe:
+ * @cont: if true schedule next execution chunk
+ *
+ */
+static int bnx2x_complete_vlan_mac(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ union event_ring_elem *cqe,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ int rc;
+
+ /* Reset pending list */
+ bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
+
+ /* Clear pending */
+ r->clear_pending(r);
+
+ /* If ramrod failed this is most likely a SW bug */
+ if (cqe->message.error)
+ return -EINVAL;
+
+ /* Run the next bulk of pending commands if requeted */
+ if (test_bit(RAMROD_CONT, ramrod_flags)) {
+ rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* If there is more work to do return PENDING */
+ if (!bnx2x_exe_queue_empty(&o->exe_queue))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands.
+ *
+ * @bp: device handle
+ * @o: bnx2x_qable_obj
+ * @elem: bnx2x_exeq_elem
+ */
+static int bnx2x_optimize_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem query, *pos;
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+
+ memcpy(&query, elem, sizeof(query));
+
+ switch (elem->cmd_data.vlan_mac.cmd) {
+ case BNX2X_VLAN_MAC_ADD:
+ query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
+ break;
+ case BNX2X_VLAN_MAC_DEL:
+ query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
+ break;
+ default:
+ /* Don't handle anything other than ADD or DEL */
+ return 0;
+ }
+
+ /* If we found the appropriate element - delete it */
+ pos = exeq->get(exeq, &query);
+ if (pos) {
+
+ /* Return the credit of the optimized command */
+ if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
+ if ((query.cmd_data.vlan_mac.cmd ==
+ BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) {
+ BNX2X_ERR("Failed to return the credit for the "
+ "optimized ADD command\n");
+ return -EINVAL;
+ } else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
+ BNX2X_ERR("Failed to recover the credit from "
+ "the optimized DEL command\n");
+ return -EINVAL;
+ }
+ }
+
+ DP(BNX2X_MSG_SP, "Optimizing %s command\n",
+ (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+ "ADD" : "DEL");
+
+ list_del(&pos->link);
+ bnx2x_exe_queue_free_elem(bp, pos);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * bnx2x_vlan_mac_get_registry_elem - prepare a registry element
+ *
+ * @bp: device handle
+ * @o:
+ * @elem:
+ * @restore:
+ * @re:
+ *
+ * prepare a registry element according to the current command request.
+ */
+static inline int bnx2x_vlan_mac_get_registry_elem(
+ struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ bool restore,
+ struct bnx2x_vlan_mac_registry_elem **re)
+{
+ int cmd = elem->cmd_data.vlan_mac.cmd;
+ struct bnx2x_vlan_mac_registry_elem *reg_elem;
+
+ /* Allocate a new registry element if needed. */
+ if (!restore &&
+ ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) {
+ reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC);
+ if (!reg_elem)
+ return -ENOMEM;
+
+ /* Get a new CAM offset */
+ if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
+ /*
+ * This shell never happen, because we have checked the
+ * CAM availiability in the 'validate'.
+ */
+ WARN_ON(1);
+ kfree(reg_elem);
+ return -EINVAL;
+ }
+
+ DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset);
+
+ /* Set a VLAN-MAC data */
+ memcpy(&reg_elem->u, &elem->cmd_data.vlan_mac.u,
+ sizeof(reg_elem->u));
+
+ /* Copy the flags (needed for DEL and RESTORE flows) */
+ reg_elem->vlan_mac_flags =
+ elem->cmd_data.vlan_mac.vlan_mac_flags;
+ } else /* DEL, RESTORE */
+ reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+
+ *re = reg_elem;
+ return 0;
+}
+
+/**
+ * bnx2x_execute_vlan_mac - execute vlan mac command
+ *
+ * @bp: device handle
+ * @qo:
+ * @exe_chunk:
+ * @ramrod_flags:
+ *
+ * go and send a ramrod!
+ */
+static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct list_head *exe_chunk,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_exeq_elem *elem;
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+ int rc, idx = 0;
+ bool restore = test_bit(RAMROD_RESTORE, ramrod_flags);
+ bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags);
+ struct bnx2x_vlan_mac_registry_elem *reg_elem;
+ int cmd;
+
+ /*
+ * If DRIVER_ONLY execution is requested, cleanup a registry
+ * and exit. Otherwise send a ramrod to FW.
+ */
+ if (!drv_only) {
+ WARN_ON(r->check_pending(r));
+
+ /* Set pending */
+ r->set_pending(r);
+
+ /* Fill tha ramrod data */
+ list_for_each_entry(elem, exe_chunk, link) {
+ cmd = elem->cmd_data.vlan_mac.cmd;
+ /*
+ * We will add to the target object in MOVE command, so
+ * change the object for a CAM search.
+ */
+ if (cmd == BNX2X_VLAN_MAC_MOVE)
+ cam_obj = elem->cmd_data.vlan_mac.target_obj;
+ else
+ cam_obj = o;
+
+ rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj,
+ elem, restore,
+ &reg_elem);
+ if (rc)
+ goto error_exit;
+
+ WARN_ON(!reg_elem);
+
+ /* Push a new entry into the registry */
+ if (!restore &&
+ ((cmd == BNX2X_VLAN_MAC_ADD) ||
+ (cmd == BNX2X_VLAN_MAC_MOVE)))
+ list_add(&reg_elem->link, &cam_obj->head);
+
+ /* Configure a single command in a ramrod data buffer */
+ o->set_one_rule(bp, o, elem, idx,
+ reg_elem->cam_offset);
+
+ /* MOVE command consumes 2 entries in the ramrod data */
+ if (cmd == BNX2X_VLAN_MAC_MOVE)
+ idx += 2;
+ else
+ idx++;
+ }
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
+ U64_HI(r->rdata_mapping),
+ U64_LO(r->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ goto error_exit;
+ }
+
+ /* Now, when we are done with the ramrod - clean up the registry */
+ list_for_each_entry(elem, exe_chunk, link) {
+ cmd = elem->cmd_data.vlan_mac.cmd;
+ if ((cmd == BNX2X_VLAN_MAC_DEL) ||
+ (cmd == BNX2X_VLAN_MAC_MOVE)) {
+ reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+
+ WARN_ON(!reg_elem);
+
+ o->put_cam_offset(o, reg_elem->cam_offset);
+ list_del(&reg_elem->link);
+ kfree(reg_elem);
+ }
+ }
+
+ if (!drv_only)
+ return 1;
+ else
+ return 0;
+
+error_exit:
+ r->clear_pending(r);
+
+ /* Cleanup a registry in case of a failure */
+ list_for_each_entry(elem, exe_chunk, link) {
+ cmd = elem->cmd_data.vlan_mac.cmd;
+
+ if (cmd == BNX2X_VLAN_MAC_MOVE)
+ cam_obj = elem->cmd_data.vlan_mac.target_obj;
+ else
+ cam_obj = o;
+
+ /* Delete all newly added above entries */
+ if (!restore &&
+ ((cmd == BNX2X_VLAN_MAC_ADD) ||
+ (cmd == BNX2X_VLAN_MAC_MOVE))) {
+ reg_elem = o->check_del(cam_obj,
+ &elem->cmd_data.vlan_mac.u);
+ if (reg_elem) {
+ list_del(&reg_elem->link);
+ kfree(reg_elem);
+ }
+ }
+ }
+
+ return rc;
+}
+
+static inline int bnx2x_vlan_mac_push_new_cmd(
+ struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p)
+{
+ struct bnx2x_exeq_elem *elem;
+ struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+ bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags);
+
+ /* Allocate the execution queue element */
+ elem = bnx2x_exe_queue_alloc_elem(bp);
+ if (!elem)
+ return -ENOMEM;
+
+ /* Set the command 'length' */
+ switch (p->user_req.cmd) {
+ case BNX2X_VLAN_MAC_MOVE:
+ elem->cmd_len = 2;
+ break;
+ default:
+ elem->cmd_len = 1;
+ }
+
+ /* Fill the object specific info */
+ memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
+
+ /* Try to add a new command to the pending list */
+ return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore);
+}
+
+/**
+ * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
+ *
+ * @bp: device handle
+ * @p:
+ *
+ */
+int bnx2x_config_vlan_mac(
+ struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p)
+{
+ int rc = 0;
+ struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+ unsigned long *ramrod_flags = &p->ramrod_flags;
+ bool cont = test_bit(RAMROD_CONT, ramrod_flags);
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ /*
+ * Add new elements to the execution list for commands that require it.
+ */
+ if (!cont) {
+ rc = bnx2x_vlan_mac_push_new_cmd(bp, p);
+ if (rc)
+ return rc;
+ }
+
+ /*
+ * If nothing will be executed further in this iteration we want to
+ * return PENDING if there are pending commands
+ */
+ if (!bnx2x_exe_queue_empty(&o->exe_queue))
+ rc = 1;
+
+ if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
+ DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
+ "clearing a pending bit.\n");
+ raw->clear_pending(raw);
+ }
+
+ /* Execute commands if required */
+ if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
+ test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
+ rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+ if (rc < 0)
+ return rc;
+ }
+
+ /*
+ * RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
+ * then user want to wait until the last command is done.
+ */
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
+ /*
+ * Wait maximum for the current exe_queue length iterations plus
+ * one (for the current pending command).
+ */
+ int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
+
+ while (!bnx2x_exe_queue_empty(&o->exe_queue) &&
+ max_iterations--) {
+
+ /* Wait for the current command to complete */
+ rc = raw->wait_comp(bp, raw);
+ if (rc)
+ return rc;
+
+ /* Make a next step */
+ rc = bnx2x_exe_queue_step(bp, &o->exe_queue,
+ ramrod_flags);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+ }
+
+ return rc;
+}
+
+
+
+/**
+ * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
+ *
+ * @bp: device handle
+ * @o:
+ * @vlan_mac_flags:
+ * @ramrod_flags: execution flags to be used for this deletion
+ *
+ * if the last operation has completed successfully and there are no
+ * moreelements left, positive value if the last operation has completed
+ * successfully and there are more previously configured elements, negative
+ * value is current operation has failed.
+ */
+static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ unsigned long *vlan_mac_flags,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos = NULL;
+ int rc = 0;
+ struct bnx2x_vlan_mac_ramrod_params p;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+
+ /* Clear pending commands first */
+
+ spin_lock_bh(&exeq->lock);
+
+ list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
+ if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
+ *vlan_mac_flags)
+ list_del(&exeq_pos->link);
+ }
+
+ spin_unlock_bh(&exeq->lock);
+
+ /* Prepare a command request */
+ memset(&p, 0, sizeof(p));
+ p.vlan_mac_obj = o;
+ p.ramrod_flags = *ramrod_flags;
+ p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
+
+ /*
+ * Add all but the last VLAN-MAC to the execution queue without actually
+ * execution anything.
+ */
+ __clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
+ __clear_bit(RAMROD_EXEC, &p.ramrod_flags);
+ __clear_bit(RAMROD_CONT, &p.ramrod_flags);
+
+ list_for_each_entry(pos, &o->head, link) {
+ if (pos->vlan_mac_flags == *vlan_mac_flags) {
+ p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
+ memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
+ rc = bnx2x_config_vlan_mac(bp, &p);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to add a new DEL command\n");
+ return rc;
+ }
+ }
+ }
+
+ p.ramrod_flags = *ramrod_flags;
+ __set_bit(RAMROD_CONT, &p.ramrod_flags);
+
+ return bnx2x_config_vlan_mac(bp, &p);
+}
+
+static inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id,
+ u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type)
+{
+ raw->func_id = func_id;
+ raw->cid = cid;
+ raw->cl_id = cl_id;
+ raw->rdata = rdata;
+ raw->rdata_mapping = rdata_mapping;
+ raw->state = state;
+ raw->pstate = pstate;
+ raw->obj_type = type;
+ raw->check_pending = bnx2x_raw_check_pending;
+ raw->clear_pending = bnx2x_raw_clear_pending;
+ raw->set_pending = bnx2x_raw_set_pending;
+ raw->wait_comp = bnx2x_raw_wait;
+}
+
+static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool,
+ struct bnx2x_credit_pool_obj *vlans_pool)
+{
+ INIT_LIST_HEAD(&o->head);
+
+ o->macs_pool = macs_pool;
+ o->vlans_pool = vlans_pool;
+
+ o->delete_all = bnx2x_vlan_mac_del_all;
+ o->restore = bnx2x_vlan_mac_restore;
+ o->complete = bnx2x_complete_vlan_mac;
+ o->wait = bnx2x_wait_vlan_mac;
+
+ bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
+ state, pstate, type);
+}
+
+
+void bnx2x_init_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool)
+{
+ union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj;
+
+ bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type,
+ macs_pool, NULL);
+
+ /* CAM credit pool handling */
+ mac_obj->get_credit = bnx2x_get_credit_mac;
+ mac_obj->put_credit = bnx2x_put_credit_mac;
+ mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
+ mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
+
+ if (CHIP_IS_E1x(bp)) {
+ mac_obj->set_one_rule = bnx2x_set_one_mac_e1x;
+ mac_obj->check_del = bnx2x_check_mac_del;
+ mac_obj->check_add = bnx2x_check_mac_add;
+ mac_obj->check_move = bnx2x_check_move_always_err;
+ mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &mac_obj->exe_queue, 1, qable_obj,
+ bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_mac);
+ } else {
+ mac_obj->set_one_rule = bnx2x_set_one_mac_e2;
+ mac_obj->check_del = bnx2x_check_mac_del;
+ mac_obj->check_add = bnx2x_check_mac_add;
+ mac_obj->check_move = bnx2x_check_move;
+ mac_obj->ramrod_cmd =
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
+ qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_mac);
+ }
+}
+
+void bnx2x_init_vlan_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *vlans_pool)
+{
+ union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj;
+
+ bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type, NULL,
+ vlans_pool);
+
+ vlan_obj->get_credit = bnx2x_get_credit_vlan;
+ vlan_obj->put_credit = bnx2x_put_credit_vlan;
+ vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan;
+ vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan;
+
+ if (CHIP_IS_E1x(bp)) {
+ BNX2X_ERR("Do not support chips others than E2 and newer\n");
+ BUG();
+ } else {
+ vlan_obj->set_one_rule = bnx2x_set_one_vlan_e2;
+ vlan_obj->check_del = bnx2x_check_vlan_del;
+ vlan_obj->check_add = bnx2x_check_vlan_add;
+ vlan_obj->check_move = bnx2x_check_move;
+ vlan_obj->ramrod_cmd =
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
+ qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_vlan);
+ }
+}
+
+void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool,
+ struct bnx2x_credit_pool_obj *vlans_pool)
+{
+ union bnx2x_qable_obj *qable_obj =
+ (union bnx2x_qable_obj *)vlan_mac_obj;
+
+ bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type,
+ macs_pool, vlans_pool);
+
+ /* CAM pool handling */
+ vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
+ vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
+ /*
+ * CAM offset is relevant for 57710 and 57711 chips only which have a
+ * single CAM for both MACs and VLAN-MAC pairs. So the offset
+ * will be taken from MACs' pool object only.
+ */
+ vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
+ vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
+
+ if (CHIP_IS_E1(bp)) {
+ BNX2X_ERR("Do not support chips others than E2\n");
+ BUG();
+ } else if (CHIP_IS_E1H(bp)) {
+ vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e1h;
+ vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del;
+ vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add;
+ vlan_mac_obj->check_move = bnx2x_check_move_always_err;
+ vlan_mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &vlan_mac_obj->exe_queue, 1, qable_obj,
+ bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_vlan_mac);
+ } else {
+ vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e2;
+ vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del;
+ vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add;
+ vlan_mac_obj->check_move = bnx2x_check_move;
+ vlan_mac_obj->ramrod_cmd =
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &vlan_mac_obj->exe_queue,
+ CLASSIFY_RULES_COUNT,
+ qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_vlan_mac);
+ }
+
+}
+
+/* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
+static inline void __storm_memset_mac_filters(struct bnx2x *bp,
+ struct tstorm_eth_mac_filter_config *mac_filters,
+ u16 pf_id)
+{
+ size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+
+ u32 addr = BAR_TSTRORM_INTMEM +
+ TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+}
+
+static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ /* update the bp MAC filter structure */
+ u32 mask = (1 << p->cl_id);
+
+ struct tstorm_eth_mac_filter_config *mac_filters =
+ (struct tstorm_eth_mac_filter_config *)p->rdata;
+
+ /* initial seeting is drop-all */
+ u8 drop_all_ucast = 1, drop_all_mcast = 1;
+ u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
+ u8 unmatched_unicast = 0;
+
+ /* In e1x there we only take into account rx acceot flag since tx switching
+ * isn't enabled. */
+ if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
+ /* accept matched ucast */
+ drop_all_ucast = 0;
+
+ if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags))
+ /* accept matched mcast */
+ drop_all_mcast = 0;
+
+ if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
+ /* accept all mcast */
+ drop_all_ucast = 0;
+ accp_all_ucast = 1;
+ }
+ if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
+ /* accept all mcast */
+ drop_all_mcast = 0;
+ accp_all_mcast = 1;
+ }
+ if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags))
+ /* accept (all) bcast */
+ accp_all_bcast = 1;
+ if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags))
+ /* accept unmatched unicasts */
+ unmatched_unicast = 1;
+
+ mac_filters->ucast_drop_all = drop_all_ucast ?
+ mac_filters->ucast_drop_all | mask :
+ mac_filters->ucast_drop_all & ~mask;
+
+ mac_filters->mcast_drop_all = drop_all_mcast ?
+ mac_filters->mcast_drop_all | mask :
+ mac_filters->mcast_drop_all & ~mask;
+
+ mac_filters->ucast_accept_all = accp_all_ucast ?
+ mac_filters->ucast_accept_all | mask :
+ mac_filters->ucast_accept_all & ~mask;
+
+ mac_filters->mcast_accept_all = accp_all_mcast ?
+ mac_filters->mcast_accept_all | mask :
+ mac_filters->mcast_accept_all & ~mask;
+
+ mac_filters->bcast_accept_all = accp_all_bcast ?
+ mac_filters->bcast_accept_all | mask :
+ mac_filters->bcast_accept_all & ~mask;
+
+ mac_filters->unmatched_unicast = unmatched_unicast ?
+ mac_filters->unmatched_unicast | mask :
+ mac_filters->unmatched_unicast & ~mask;
+
+ DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
+ "accp_mcast 0x%x\naccp_bcast 0x%x\n",
+ mac_filters->ucast_drop_all,
+ mac_filters->mcast_drop_all,
+ mac_filters->ucast_accept_all,
+ mac_filters->mcast_accept_all,
+ mac_filters->bcast_accept_all);
+
+ /* write the MAC filter structure*/
+ __storm_memset_mac_filters(bp, mac_filters, p->func_id);
+
+ /* The operation is completed */
+ clear_bit(p->state, p->pstate);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+/* Setup ramrod data */
+static inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,
+ struct eth_classify_header *hdr,
+ u8 rule_cnt)
+{
+ hdr->echo = cid;
+ hdr->rule_cnt = rule_cnt;
+}
+
+static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
+ unsigned long accept_flags,
+ struct eth_filter_rules_cmd *cmd,
+ bool clear_accept_all)
+{
+ u16 state;
+
+ /* start with 'drop-all' */
+ state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
+ ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+
+ if (accept_flags) {
+ if (test_bit(BNX2X_ACCEPT_UNICAST, &accept_flags))
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+
+ if (test_bit(BNX2X_ACCEPT_MULTICAST, &accept_flags))
+ state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+
+ if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &accept_flags)) {
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+ state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
+ }
+
+ if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags)) {
+ state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+ }
+ if (test_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags))
+ state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
+
+ if (test_bit(BNX2X_ACCEPT_UNMATCHED, &accept_flags)) {
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+ state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
+ }
+ if (test_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags))
+ state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
+ }
+
+ /* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
+ if (clear_accept_all) {
+ state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
+ }
+
+ cmd->state = cpu_to_le16(state);
+
+}
+
+static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ struct eth_filter_rules_ramrod_data *data = p->rdata;
+ int rc;
+ u8 rule_idx = 0;
+
+ /* Reset the ramrod data buffer */
+ memset(data, 0, sizeof(*data));
+
+ /* Setup ramrod data */
+
+ /* Tx (internal switching) */
+ if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = p->cl_id;
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_TX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
+ &(data->rules[rule_idx++]), false);
+ }
+
+ /* Rx */
+ if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = p->cl_id;
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_RX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
+ &(data->rules[rule_idx++]), false);
+ }
+
+
+ /*
+ * If FCoE Queue configuration has been requested configure the Rx and
+ * internal switching modes for this queue in separate rules.
+ *
+ * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
+ * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
+ */
+ if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
+ /* Tx (internal switching) */
+ if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_TX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
+ &(data->rules[rule_idx++]),
+ true);
+ }
+
+ /* Rx */
+ if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_RX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
+ &(data->rules[rule_idx++]),
+ true);
+ }
+ }
+
+ /*
+ * Set the ramrod header (most importantly - number of rules to
+ * configure).
+ */
+ bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
+
+ DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, "
+ "tx_accept_flags 0x%lx\n",
+ data->header.rule_cnt, p->rx_accept_flags,
+ p->tx_accept_flags);
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
+ U64_HI(p->rdata_mapping),
+ U64_LO(p->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ return rc;
+
+ /* Ramrod completion is pending */
+ return 1;
+}
+
+static int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ return bnx2x_state_wait(bp, p->state, p->pstate);
+}
+
+static int bnx2x_empty_rx_mode_wait(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ /* Do nothing */
+ return 0;
+}
+
+int bnx2x_config_rx_mode(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ int rc;
+
+ /* Configure the new classification in the chip */
+ rc = p->rx_mode_obj->config_rx_mode(bp, p);
+ if (rc < 0)
+ return rc;
+
+ /* Wait for a ramrod completion if was requested */
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
+ rc = p->rx_mode_obj->wait_comp(bp, p);
+ if (rc)
+ return rc;
+ }
+
+ return rc;
+}
+
+void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
+ struct bnx2x_rx_mode_obj *o)
+{
+ if (CHIP_IS_E1x(bp)) {
+ o->wait_comp = bnx2x_empty_rx_mode_wait;
+ o->config_rx_mode = bnx2x_set_rx_mode_e1x;
+ } else {
+ o->wait_comp = bnx2x_wait_rx_mode_comp_e2;
+ o->config_rx_mode = bnx2x_set_rx_mode_e2;
+ }
+}
+
+/********************* Multicast verbs: SET, CLEAR ****************************/
+static inline u8 bnx2x_mcast_bin_from_mac(u8 *mac)
+{
+ return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff;
+}
+
+struct bnx2x_mcast_mac_elem {
+ struct list_head link;
+ u8 mac[ETH_ALEN];
+ u8 pad[2]; /* For a natural alignment of the following buffer */
+};
+
+struct bnx2x_pending_mcast_cmd {
+ struct list_head link;
+ int type; /* BNX2X_MCAST_CMD_X */
+ union {
+ struct list_head macs_head;
+ u32 macs_num; /* Needed for DEL command */
+ int next_bin; /* Needed for RESTORE flow with aprox match */
+ } data;
+
+ bool done; /* set to true, when the command has been handled,
+ * practically used in 57712 handling only, where one pending
+ * command may be handled in a few operations. As long as for
+ * other chips every operation handling is completed in a
+ * single ramrod, there is no need to utilize this field.
+ */
+};
+
+static int bnx2x_mcast_wait(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o)
+{
+ if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
+ o->raw.wait_comp(bp, &o->raw))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ int total_sz;
+ struct bnx2x_pending_mcast_cmd *new_cmd;
+ struct bnx2x_mcast_mac_elem *cur_mac = NULL;
+ struct bnx2x_mcast_list_elem *pos;
+ int macs_list_len = ((cmd == BNX2X_MCAST_CMD_ADD) ?
+ p->mcast_list_len : 0);
+
+ /* If the command is empty ("handle pending commands only"), break */
+ if (!p->mcast_list_len)
+ return 0;
+
+ total_sz = sizeof(*new_cmd) +
+ macs_list_len * sizeof(struct bnx2x_mcast_mac_elem);
+
+ /* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
+ new_cmd = kzalloc(total_sz, GFP_ATOMIC);
+
+ if (!new_cmd)
+ return -ENOMEM;
+
+ DP(BNX2X_MSG_SP, "About to enqueue a new %d command. "
+ "macs_list_len=%d\n", cmd, macs_list_len);
+
+ INIT_LIST_HEAD(&new_cmd->data.macs_head);
+
+ new_cmd->type = cmd;
+ new_cmd->done = false;
+
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ cur_mac = (struct bnx2x_mcast_mac_elem *)
+ ((u8 *)new_cmd + sizeof(*new_cmd));
+
+ /* Push the MACs of the current command into the pendig command
+ * MACs list: FIFO
+ */
+ list_for_each_entry(pos, &p->mcast_list, link) {
+ memcpy(cur_mac->mac, pos->mac, ETH_ALEN);
+ list_add_tail(&cur_mac->link, &new_cmd->data.macs_head);
+ cur_mac++;
+ }
+
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ new_cmd->data.macs_num = p->mcast_list_len;
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ new_cmd->data.next_bin = 0;
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+ }
+
+ /* Push the new pending command to the tail of the pending list: FIFO */
+ list_add_tail(&new_cmd->link, &o->pending_cmds_head);
+
+ o->set_sched(o);
+
+ return 1;
+}
+
+/**
+ * bnx2x_mcast_get_next_bin - get the next set bin (index)
+ *
+ * @o:
+ * @last: index to start looking from (including)
+ *
+ * returns the next found (set) bin or a negative value if none is found.
+ */
+static inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last)
+{
+ int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
+
+ for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) {
+ if (o->registry.aprox_match.vec[i])
+ for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
+ int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
+ if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
+ vec, cur_bit)) {
+ return cur_bit;
+ }
+ }
+ inner_start = 0;
+ }
+
+ /* None found */
+ return -1;
+}
+
+/**
+ * bnx2x_mcast_clear_first_bin - find the first set bin and clear it
+ *
+ * @o:
+ *
+ * returns the index of the found bin or -1 if none is found
+ */
+static inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o)
+{
+ int cur_bit = bnx2x_mcast_get_next_bin(o, 0);
+
+ if (cur_bit >= 0)
+ BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
+
+ return cur_bit;
+}
+
+static inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ u8 rx_tx_flag = 0;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
+
+ return rx_tx_flag;
+}
+
+static void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, int idx,
+ union bnx2x_mcast_config_data *cfg_data,
+ int cmd)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ struct eth_multicast_rules_ramrod_data *data =
+ (struct eth_multicast_rules_ramrod_data *)(r->rdata);
+ u8 func_id = r->func_id;
+ u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o);
+ int bin;
+
+ if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE))
+ rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
+
+ data->rules[idx].cmd_general_data |= rx_tx_add_flag;
+
+ /* Get a bin and update a bins' vector */
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ bin = bnx2x_mcast_bin_from_mac(cfg_data->mac);
+ BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ /* If there were no more bins to clear
+ * (bnx2x_mcast_clear_first_bin() returns -1) then we would
+ * clear any (0xff) bin.
+ * See bnx2x_mcast_validate_e2() for explanation when it may
+ * happen.
+ */
+ bin = bnx2x_mcast_clear_first_bin(o);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ bin = cfg_data->bin;
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return;
+ }
+
+ DP(BNX2X_MSG_SP, "%s bin %d\n",
+ ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
+ "Setting" : "Clearing"), bin);
+
+ data->rules[idx].bin_id = (u8)bin;
+ data->rules[idx].func_id = func_id;
+ data->rules[idx].engine_id = o->engine_id;
+}
+
+/**
+ * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry
+ *
+ * @bp: device handle
+ * @o:
+ * @start_bin: index in the registry to start from (including)
+ * @rdata_idx: index in the ramrod data to start from
+ *
+ * returns last handled bin index or -1 if all bins have been handled
+ */
+static inline int bnx2x_mcast_handle_restore_cmd_e2(
+ struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin,
+ int *rdata_idx)
+{
+ int cur_bin, cnt = *rdata_idx;
+ union bnx2x_mcast_config_data cfg_data = {0};
+
+ /* go through the registry and configure the bins from it */
+ for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
+ cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) {
+
+ cfg_data.bin = (u8)cur_bin;
+ o->set_one_rule(bp, o, cnt, &cfg_data,
+ BNX2X_MCAST_CMD_RESTORE);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin);
+
+ /* Break if we reached the maximum number
+ * of rules.
+ */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ *rdata_idx = cnt;
+
+ return cur_bin;
+}
+
+static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+ int *line_idx)
+{
+ struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
+ int cnt = *line_idx;
+ union bnx2x_mcast_config_data cfg_data = {0};
+
+ list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
+ link) {
+
+ cfg_data.mac = &pmac_pos->mac[0];
+ o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+
+ list_del(&pmac_pos->link);
+
+ /* Break if we reached the maximum number
+ * of rules.
+ */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ *line_idx = cnt;
+
+ /* if no more MACs to configure - we are done */
+ if (list_empty(&cmd_pos->data.macs_head))
+ cmd_pos->done = true;
+}
+
+static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+ int *line_idx)
+{
+ int cnt = *line_idx;
+
+ while (cmd_pos->data.macs_num) {
+ o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type);
+
+ cnt++;
+
+ cmd_pos->data.macs_num--;
+
+ DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
+ cmd_pos->data.macs_num, cnt);
+
+ /* Break if we reached the maximum
+ * number of rules.
+ */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ *line_idx = cnt;
+
+ /* If we cleared all bins - we are done */
+ if (!cmd_pos->data.macs_num)
+ cmd_pos->done = true;
+}
+
+static inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+ int *line_idx)
+{
+ cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin,
+ line_idx);
+
+ if (cmd_pos->data.next_bin < 0)
+ /* If o->set_restore returned -1 we are done */
+ cmd_pos->done = true;
+ else
+ /* Start from the next bin next time */
+ cmd_pos->data.next_bin++;
+}
+
+static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p)
+{
+ struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
+ int cnt = 0;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+ list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head,
+ link) {
+ switch (cmd_pos->type) {
+ case BNX2X_MCAST_CMD_ADD:
+ bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos,
+ &cnt);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
+ return -EINVAL;
+ }
+
+ /* If the command has been completed - remove it from the list
+ * and free the memory
+ */
+ if (cmd_pos->done) {
+ list_del(&cmd_pos->link);
+ kfree(cmd_pos);
+ }
+
+ /* Break if we reached the maximum number of rules */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ return cnt;
+}
+
+static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+ int *line_idx)
+{
+ struct bnx2x_mcast_list_elem *mlist_pos;
+ union bnx2x_mcast_config_data cfg_data = {0};
+ int cnt = *line_idx;
+
+ list_for_each_entry(mlist_pos, &p->mcast_list, link) {
+ cfg_data.mac = mlist_pos->mac;
+ o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(mlist_pos->mac));
+ }
+
+ *line_idx = cnt;
+}
+
+static inline void bnx2x_mcast_hdl_del(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+ int *line_idx)
+{
+ int cnt = *line_idx, i;
+
+ for (i = 0; i < p->mcast_list_len; i++) {
+ o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n",
+ p->mcast_list_len - i - 1);
+ }
+
+ *line_idx = cnt;
+}
+
+/**
+ * bnx2x_mcast_handle_current_cmd -
+ *
+ * @bp: device handle
+ * @p:
+ * @cmd:
+ * @start_cnt: first line in the ramrod data that may be used
+ *
+ * This function is called iff there is enough place for the current command in
+ * the ramrod data.
+ * Returns number of lines filled in the ramrod data in total.
+ */
+static inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd,
+ int start_cnt)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ int cnt = start_cnt;
+
+ DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
+
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ bnx2x_mcast_hdl_add(bp, o, p, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ bnx2x_mcast_hdl_del(bp, o, p, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ o->hdl_restore(bp, o, 0, &cnt);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+ }
+
+ /* The current command has been handled */
+ p->mcast_list_len = 0;
+
+ return cnt;
+}
+
+static int bnx2x_mcast_validate_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ int reg_sz = o->get_registry_size(o);
+
+ switch (cmd) {
+ /* DEL command deletes all currently configured MACs */
+ case BNX2X_MCAST_CMD_DEL:
+ o->set_registry_size(o, 0);
+ /* Don't break */
+
+ /* RESTORE command will restore the entire multicast configuration */
+ case BNX2X_MCAST_CMD_RESTORE:
+ /* Here we set the approximate amount of work to do, which in
+ * fact may be only less as some MACs in postponed ADD
+ * command(s) scheduled before this command may fall into
+ * the same bin and the actual number of bins set in the
+ * registry would be less than we estimated here. See
+ * bnx2x_mcast_set_one_rule_e2() for further details.
+ */
+ p->mcast_list_len = reg_sz;
+ break;
+
+ case BNX2X_MCAST_CMD_ADD:
+ case BNX2X_MCAST_CMD_CONT:
+ /* Here we assume that all new MACs will fall into new bins.
+ * However we will correct the real registry size after we
+ * handle all pending commands.
+ */
+ o->set_registry_size(o, reg_sz + p->mcast_list_len);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+
+ }
+
+ /* Increase the total number of MACs pending to be configured */
+ o->total_pending_num += p->mcast_list_len;
+
+ return 0;
+}
+
+static void bnx2x_mcast_revert_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_bins)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+ o->set_registry_size(o, old_num_bins);
+ o->total_pending_num -= p->mcast_list_len;
+}
+
+/**
+ * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values
+ *
+ * @bp: device handle
+ * @p:
+ * @len: number of rules to handle
+ */
+static inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ u8 len)
+{
+ struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
+ struct eth_multicast_rules_ramrod_data *data =
+ (struct eth_multicast_rules_ramrod_data *)(r->rdata);
+
+ data->header.echo = ((r->cid & BNX2X_SWCID_MASK) |
+ (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
+ data->header.rule_cnt = len;
+}
+
+/**
+ * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins
+ *
+ * @bp: device handle
+ * @o:
+ *
+ * Recalculate the actual number of set bins in the registry using Brian
+ * Kernighan's algorithm: it's execution complexity is as a number of set bins.
+ *
+ * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1().
+ */
+static inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o)
+{
+ int i, cnt = 0;
+ u64 elem;
+
+ for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) {
+ elem = o->registry.aprox_match.vec[i];
+ for (; elem; cnt++)
+ elem &= elem - 1;
+ }
+
+ o->set_registry_size(o, cnt);
+
+ return 0;
+}
+
+static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_raw_obj *raw = &p->mcast_obj->raw;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct eth_multicast_rules_ramrod_data *data =
+ (struct eth_multicast_rules_ramrod_data *)(raw->rdata);
+ int cnt = 0, rc;
+
+ /* Reset the ramrod data buffer */
+ memset(data, 0, sizeof(*data));
+
+ cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p);
+
+ /* If there are no more pending commands - clear SCHEDULED state */
+ if (list_empty(&o->pending_cmds_head))
+ o->clear_sched(o);
+
+ /* The below may be true iff there was enough room in ramrod
+ * data for all pending commands and for the current
+ * command. Otherwise the current command would have been added
+ * to the pending commands and p->mcast_list_len would have been
+ * zeroed.
+ */
+ if (p->mcast_list_len > 0)
+ cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt);
+
+ /* We've pulled out some MACs - update the total number of
+ * outstanding.
+ */
+ o->total_pending_num -= cnt;
+
+ /* send a ramrod */
+ WARN_ON(o->total_pending_num < 0);
+ WARN_ON(cnt > o->max_cmd_len);
+
+ bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt);
+
+ /* Update a registry size if there are no more pending operations.
+ *
+ * We don't want to change the value of the registry size if there are
+ * pending operations because we want it to always be equal to the
+ * exact or the approximate number (see bnx2x_mcast_validate_e2()) of
+ * set bins after the last requested operation in order to properly
+ * evaluate the size of the next DEL/RESTORE operation.
+ *
+ * Note that we update the registry itself during command(s) handling
+ * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we
+ * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
+ * with a limited amount of update commands (per MAC/bin) and we don't
+ * know in this scope what the actual state of bins configuration is
+ * going to be after this ramrod.
+ */
+ if (!o->total_pending_num)
+ bnx2x_mcast_refresh_registry_e2(bp, o);
+
+ /*
+ * If CLEAR_ONLY was requested - don't send a ramrod and clear
+ * RAMROD_PENDING status immediately.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+ raw->clear_pending(raw);
+ return 0;
+ } else {
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
+ raw->cid, U64_HI(raw->rdata_mapping),
+ U64_LO(raw->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ return rc;
+
+ /* Ramrod completion is pending */
+ return 1;
+ }
+}
+
+static int bnx2x_mcast_validate_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ /* Mark, that there is a work to do */
+ if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE))
+ p->mcast_list_len = 1;
+
+ return 0;
+}
+
+static void bnx2x_mcast_revert_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_bins)
+{
+ /* Do nothing */
+}
+
+#define BNX2X_57711_SET_MC_FILTER(filter, bit) \
+do { \
+ (filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
+} while (0)
+
+static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o,
+ struct bnx2x_mcast_ramrod_params *p,
+ u32 *mc_filter)
+{
+ struct bnx2x_mcast_list_elem *mlist_pos;
+ int bit;
+
+ list_for_each_entry(mlist_pos, &p->mcast_list, link) {
+ 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);
+
+ /* bookkeeping... */
+ BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
+ bit);
+ }
+}
+
+static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+ u32 *mc_filter)
+{
+ int bit;
+
+ for (bit = bnx2x_mcast_get_next_bin(o, 0);
+ bit >= 0;
+ bit = bnx2x_mcast_get_next_bin(o, bit + 1)) {
+ BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
+ DP(BNX2X_MSG_SP, "About to set bin %d\n", bit);
+ }
+}
+
+/* On 57711 we write the multicast MACs' aproximate match
+ * table by directly into the TSTORM's internal RAM. So we don't
+ * really need to handle any tricks to make it work.
+ */
+static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ int i;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+
+ /* If CLEAR_ONLY has been requested - clear the registry
+ * and clear a pending bit.
+ */
+ if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+ u32 mc_filter[MC_HASH_SIZE] = {0};
+
+ /* Set the multicast filter bits before writing it into
+ * the internal memory.
+ */
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ DP(BNX2X_MSG_SP, "Invalidating multicast "
+ "MACs configuration\n");
+
+ /* clear the registry */
+ memset(o->registry.aprox_match.vec, 0,
+ sizeof(o->registry.aprox_match.vec));
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+ }
+
+ /* Set the mcast filter in the internal memory */
+ for (i = 0; i < MC_HASH_SIZE; i++)
+ REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]);
+ } else
+ /* clear the registry */
+ memset(o->registry.aprox_match.vec, 0,
+ sizeof(o->registry.aprox_match.vec));
+
+ /* We are done */
+ r->clear_pending(r);
+
+ return 0;
+}
+
+static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ int reg_sz = o->get_registry_size(o);
+
+ switch (cmd) {
+ /* DEL command deletes all currently configured MACs */
+ case BNX2X_MCAST_CMD_DEL:
+ o->set_registry_size(o, 0);
+ /* Don't break */
+
+ /* RESTORE command will restore the entire multicast configuration */
+ case BNX2X_MCAST_CMD_RESTORE:
+ p->mcast_list_len = reg_sz;
+ DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
+ cmd, p->mcast_list_len);
+ break;
+
+ case BNX2X_MCAST_CMD_ADD:
+ case BNX2X_MCAST_CMD_CONT:
+ /* Multicast MACs on 57710 are configured as unicast MACs and
+ * there is only a limited number of CAM entries for that
+ * matter.
+ */
+ if (p->mcast_list_len > o->max_cmd_len) {
+ BNX2X_ERR("Can't configure more than %d multicast MACs"
+ "on 57710\n", o->max_cmd_len);
+ return -EINVAL;
+ }
+ /* Every configured MAC should be cleared if DEL command is
+ * called. Only the last ADD command is relevant as long as
+ * every ADD commands overrides the previous configuration.
+ */
+ DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
+ if (p->mcast_list_len > 0)
+ o->set_registry_size(o, p->mcast_list_len);
+
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+
+ }
+
+ /* We want to ensure that commands are executed one by one for 57710.
+ * Therefore each none-empty command will consume o->max_cmd_len.
+ */
+ if (p->mcast_list_len)
+ o->total_pending_num += o->max_cmd_len;
+
+ return 0;
+}
+
+static void bnx2x_mcast_revert_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_macs)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+ o->set_registry_size(o, old_num_macs);
+
+ /* If current command hasn't been handled yet and we are
+ * here means that it's meant to be dropped and we have to
+ * update the number of outstandling MACs accordingly.
+ */
+ if (p->mcast_list_len)
+ o->total_pending_num -= o->max_cmd_len;
+}
+
+static void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, int idx,
+ union bnx2x_mcast_config_data *cfg_data,
+ int cmd)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(r->rdata);
+
+ /* copy mac */
+ if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) {
+ bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
+ &data->config_table[idx].middle_mac_addr,
+ &data->config_table[idx].lsb_mac_addr,
+ cfg_data->mac);
+
+ data->config_table[idx].vlan_id = 0;
+ data->config_table[idx].pf_id = r->func_id;
+ data->config_table[idx].clients_bit_vector =
+ cpu_to_le32(1 << r->cl_id);
+
+ SET_FLAG(data->config_table[idx].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_SET);
+ }
+}
+
+/**
+ * bnx2x_mcast_set_rdata_hdr_e1 - set header values in mac_configuration_cmd
+ *
+ * @bp: device handle
+ * @p:
+ * @len: number of rules to handle
+ */
+static inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ u8 len)
+{
+ struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(r->rdata);
+
+ u8 offset = (CHIP_REV_IS_SLOW(bp) ?
+ BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) :
+ BNX2X_MAX_MULTICAST*(1 + r->func_id));
+
+ data->hdr.offset = offset;
+ data->hdr.client_id = 0xff;
+ data->hdr.echo = ((r->cid & BNX2X_SWCID_MASK) |
+ (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
+ data->hdr.length = len;
+}
+
+/**
+ * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710
+ *
+ * @bp: device handle
+ * @o:
+ * @start_idx: index in the registry to start from
+ * @rdata_idx: index in the ramrod data to start from
+ *
+ * restore command for 57710 is like all other commands - always a stand alone
+ * command - start_idx and rdata_idx will always be 0. This function will always
+ * succeed.
+ * returns -1 to comply with 57712 variant.
+ */
+static inline int bnx2x_mcast_handle_restore_cmd_e1(
+ struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx,
+ int *rdata_idx)
+{
+ struct bnx2x_mcast_mac_elem *elem;
+ int i = 0;
+ union bnx2x_mcast_config_data cfg_data = {0};
+
+ /* go through the registry and configure the MACs from it. */
+ list_for_each_entry(elem, &o->registry.exact_match.macs, link) {
+ cfg_data.mac = &elem->mac[0];
+ o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE);
+
+ i++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(cfg_data.mac));
+ }
+
+ *rdata_idx = i;
+
+ return -1;
+}
+
+
+static inline int bnx2x_mcast_handle_pending_cmds_e1(
+ struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
+{
+ struct bnx2x_pending_mcast_cmd *cmd_pos;
+ struct bnx2x_mcast_mac_elem *pmac_pos;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ union bnx2x_mcast_config_data cfg_data = {0};
+ int cnt = 0;
+
+
+ /* If nothing to be done - return */
+ if (list_empty(&o->pending_cmds_head))
+ return 0;
+
+ /* Handle the first command */
+ cmd_pos = list_first_entry(&o->pending_cmds_head,
+ struct bnx2x_pending_mcast_cmd, link);
+
+ switch (cmd_pos->type) {
+ case BNX2X_MCAST_CMD_ADD:
+ list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) {
+ cfg_data.mac = &pmac_pos->mac[0];
+ o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+ }
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ cnt = cmd_pos->data.macs_num;
+ DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ o->hdl_restore(bp, o, 0, &cnt);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
+ return -EINVAL;
+ }
+
+ list_del(&cmd_pos->link);
+ kfree(cmd_pos);
+
+ return cnt;
+}
+
+/**
+ * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr().
+ *
+ * @fw_hi:
+ * @fw_mid:
+ * @fw_lo:
+ * @mac:
+ */
+static inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
+ __le16 *fw_lo, u8 *mac)
+{
+ mac[1] = ((u8 *)fw_hi)[0];
+ mac[0] = ((u8 *)fw_hi)[1];
+ mac[3] = ((u8 *)fw_mid)[0];
+ mac[2] = ((u8 *)fw_mid)[1];
+ mac[5] = ((u8 *)fw_lo)[0];
+ mac[4] = ((u8 *)fw_lo)[1];
+}
+
+/**
+ * bnx2x_mcast_refresh_registry_e1 -
+ *
+ * @bp: device handle
+ * @cnt:
+ *
+ * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
+ * and update the registry correspondingly: if ADD - allocate a memory and add
+ * the entries to the registry (list), if DELETE - clear the registry and free
+ * the memory.
+ */
+static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct bnx2x_mcast_mac_elem *elem;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(raw->rdata);
+
+ /* If first entry contains a SET bit - the command was ADD,
+ * otherwise - DEL_ALL
+ */
+ if (GET_FLAG(data->config_table[0].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
+ int i, len = data->hdr.length;
+
+ /* Break if it was a RESTORE command */
+ if (!list_empty(&o->registry.exact_match.macs))
+ return 0;
+
+ elem = kzalloc(sizeof(*elem)*len, GFP_ATOMIC);
+ if (!elem) {
+ BNX2X_ERR("Failed to allocate registry memory\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < len; i++, elem++) {
+ bnx2x_get_fw_mac_addr(
+ &data->config_table[i].msb_mac_addr,
+ &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));
+ list_add_tail(&elem->link,
+ &o->registry.exact_match.macs);
+ }
+ } else {
+ elem = list_first_entry(&o->registry.exact_match.macs,
+ struct bnx2x_mcast_mac_elem, link);
+ DP(BNX2X_MSG_SP, "Deleting a registry\n");
+ kfree(elem);
+ INIT_LIST_HEAD(&o->registry.exact_match.macs);
+ }
+
+ return 0;
+}
+
+static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(raw->rdata);
+ int cnt = 0, i, rc;
+
+ /* Reset the ramrod data buffer */
+ memset(data, 0, sizeof(*data));
+
+ /* First set all entries as invalid */
+ for (i = 0; i < o->max_cmd_len ; i++)
+ SET_FLAG(data->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+
+ /* Handle pending commands first */
+ cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p);
+
+ /* If there are no more pending commands - clear SCHEDULED state */
+ if (list_empty(&o->pending_cmds_head))
+ o->clear_sched(o);
+
+ /* The below may be true iff there were no pending commands */
+ if (!cnt)
+ cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0);
+
+ /* For 57710 every command has o->max_cmd_len length to ensure that
+ * commands are done one at a time.
+ */
+ o->total_pending_num -= o->max_cmd_len;
+
+ /* send a ramrod */
+
+ WARN_ON(cnt > o->max_cmd_len);
+
+ /* Set ramrod header (in particular, a number of entries to update) */
+ bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt);
+
+ /* update a registry: we need the registry contents to be always up
+ * to date in order to be able to execute a RESTORE opcode. Here
+ * we use the fact that for 57710 we sent one command at a time
+ * hence we may take the registry update out of the command handling
+ * and do it in a simpler way here.
+ */
+ rc = bnx2x_mcast_refresh_registry_e1(bp, o);
+ if (rc)
+ return rc;
+
+ /*
+ * If CLEAR_ONLY was requested - don't send a ramrod and clear
+ * RAMROD_PENDING status immediately.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+ raw->clear_pending(raw);
+ return 0;
+ } else {
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
+ U64_HI(raw->rdata_mapping),
+ U64_LO(raw->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ return rc;
+
+ /* Ramrod completion is pending */
+ return 1;
+ }
+
+}
+
+static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
+{
+ return o->registry.exact_match.num_macs_set;
+}
+
+static int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o)
+{
+ return o->registry.aprox_match.num_bins_set;
+}
+
+static void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o,
+ int n)
+{
+ o->registry.exact_match.num_macs_set = n;
+}
+
+static void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o,
+ int n)
+{
+ o->registry.aprox_match.num_bins_set = n;
+}
+
+int bnx2x_config_mcast(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+ int rc = 0, old_reg_size;
+
+ /* This is needed to recover number of currently configured mcast macs
+ * in case of failure.
+ */
+ old_reg_size = o->get_registry_size(o);
+
+ /* Do some calculations and checks */
+ rc = o->validate(bp, p, cmd);
+ if (rc)
+ return rc;
+
+ /* Return if there is no work to do */
+ if ((!p->mcast_list_len) && (!o->check_sched(o)))
+ return 0;
+
+ DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d "
+ "o->max_cmd_len=%d\n", o->total_pending_num,
+ p->mcast_list_len, o->max_cmd_len);
+
+ /* Enqueue the current command to the pending list if we can't complete
+ * it in the current iteration
+ */
+ if (r->check_pending(r) ||
+ ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
+ rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd);
+ if (rc < 0)
+ goto error_exit1;
+
+ /* As long as the current command is in a command list we
+ * don't need to handle it separately.
+ */
+ p->mcast_list_len = 0;
+ }
+
+ if (!r->check_pending(r)) {
+
+ /* Set 'pending' state */
+ r->set_pending(r);
+
+ /* Configure the new classification in the chip */
+ rc = o->config_mcast(bp, p, cmd);
+ if (rc < 0)
+ goto error_exit2;
+
+ /* Wait for a ramrod completion if was requested */
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
+ rc = o->wait_comp(bp, o);
+ }
+
+ return rc;
+
+error_exit2:
+ r->clear_pending(r);
+
+error_exit1:
+ o->revert(bp, p, old_reg_size);
+
+ return rc;
+}
+
+static void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(o->sched_state, o->raw.pstate);
+ smp_mb__after_clear_bit();
+}
+
+static void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o)
+{
+ smp_mb__before_clear_bit();
+ set_bit(o->sched_state, o->raw.pstate);
+ smp_mb__after_clear_bit();
+}
+
+static bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o)
+{
+ return !!test_bit(o->sched_state, o->raw.pstate);
+}
+
+static bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o)
+{
+ return o->raw.check_pending(&o->raw) || o->check_sched(o);
+}
+
+void bnx2x_init_mcast_obj(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *mcast_obj,
+ u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
+ u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate, bnx2x_obj_type type)
+{
+ memset(mcast_obj, 0, sizeof(*mcast_obj));
+
+ bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
+ rdata, rdata_mapping, state, pstate, type);
+
+ mcast_obj->engine_id = engine_id;
+
+ INIT_LIST_HEAD(&mcast_obj->pending_cmds_head);
+
+ mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED;
+ mcast_obj->check_sched = bnx2x_mcast_check_sched;
+ mcast_obj->set_sched = bnx2x_mcast_set_sched;
+ mcast_obj->clear_sched = bnx2x_mcast_clear_sched;
+
+ if (CHIP_IS_E1(bp)) {
+ mcast_obj->config_mcast = bnx2x_mcast_setup_e1;
+ mcast_obj->enqueue_cmd = bnx2x_mcast_enqueue_cmd;
+ mcast_obj->hdl_restore =
+ bnx2x_mcast_handle_restore_cmd_e1;
+ mcast_obj->check_pending = bnx2x_mcast_check_pending;
+
+ if (CHIP_REV_IS_SLOW(bp))
+ mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI;
+ else
+ mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST;
+
+ mcast_obj->wait_comp = bnx2x_mcast_wait;
+ mcast_obj->set_one_rule = bnx2x_mcast_set_one_rule_e1;
+ mcast_obj->validate = bnx2x_mcast_validate_e1;
+ mcast_obj->revert = bnx2x_mcast_revert_e1;
+ mcast_obj->get_registry_size =
+ bnx2x_mcast_get_registry_size_exact;
+ mcast_obj->set_registry_size =
+ bnx2x_mcast_set_registry_size_exact;
+
+ /* 57710 is the only chip that uses the exact match for mcast
+ * at the moment.
+ */
+ INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs);
+
+ } else if (CHIP_IS_E1H(bp)) {
+ mcast_obj->config_mcast = bnx2x_mcast_setup_e1h;
+ mcast_obj->enqueue_cmd = NULL;
+ mcast_obj->hdl_restore = NULL;
+ mcast_obj->check_pending = bnx2x_mcast_check_pending;
+
+ /* 57711 doesn't send a ramrod, so it has unlimited credit
+ * for one command.
+ */
+ mcast_obj->max_cmd_len = -1;
+ mcast_obj->wait_comp = bnx2x_mcast_wait;
+ mcast_obj->set_one_rule = NULL;
+ mcast_obj->validate = bnx2x_mcast_validate_e1h;
+ mcast_obj->revert = bnx2x_mcast_revert_e1h;
+ mcast_obj->get_registry_size =
+ bnx2x_mcast_get_registry_size_aprox;
+ mcast_obj->set_registry_size =
+ bnx2x_mcast_set_registry_size_aprox;
+ } else {
+ mcast_obj->config_mcast = bnx2x_mcast_setup_e2;
+ mcast_obj->enqueue_cmd = bnx2x_mcast_enqueue_cmd;
+ mcast_obj->hdl_restore =
+ bnx2x_mcast_handle_restore_cmd_e2;
+ mcast_obj->check_pending = bnx2x_mcast_check_pending;
+ /* TODO: There should be a proper HSI define for this number!!!
+ */
+ mcast_obj->max_cmd_len = 16;
+ mcast_obj->wait_comp = bnx2x_mcast_wait;
+ mcast_obj->set_one_rule = bnx2x_mcast_set_one_rule_e2;
+ mcast_obj->validate = bnx2x_mcast_validate_e2;
+ mcast_obj->revert = bnx2x_mcast_revert_e2;
+ mcast_obj->get_registry_size =
+ bnx2x_mcast_get_registry_size_aprox;
+ mcast_obj->set_registry_size =
+ bnx2x_mcast_set_registry_size_aprox;
+ }
+}
+
+/*************************** Credit handling **********************************/
+
+/**
+ * atomic_add_ifless - add if the result is less than a given value.
+ *
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...if (v + a) is less than u.
+ *
+ * returns true if (v + a) was less than u, and false otherwise.
+ *
+ */
+static inline bool __atomic_add_ifless(atomic_t *v, int a, int u)
+{
+ int c, old;
+
+ c = atomic_read(v);
+ for (;;) {
+ if (unlikely(c + a >= u))
+ return false;
+
+ old = atomic_cmpxchg((v), c, c + a);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+
+ return true;
+}
+
+/**
+ * atomic_dec_ifmoe - dec if the result is more or equal than a given value.
+ *
+ * @v: pointer of type atomic_t
+ * @a: the amount to dec from v...
+ * @u: ...if (v - a) is more or equal than u.
+ *
+ * returns true if (v - a) was more or equal than u, and false
+ * otherwise.
+ */
+static inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u)
+{
+ int c, old;
+
+ c = atomic_read(v);
+ for (;;) {
+ if (unlikely(c - a < u))
+ return false;
+
+ old = atomic_cmpxchg((v), c, c - a);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+
+ return true;
+}
+
+static bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt)
+{
+ bool rc;
+
+ smp_mb();
+ rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
+ smp_mb();
+
+ return rc;
+}
+
+static bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt)
+{
+ bool rc;
+
+ smp_mb();
+
+ /* Don't let to refill if credit + cnt > pool_sz */
+ rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
+
+ smp_mb();
+
+ return rc;
+}
+
+static int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o)
+{
+ int cur_credit;
+
+ smp_mb();
+ cur_credit = atomic_read(&o->credit);
+
+ return cur_credit;
+}
+
+static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
+ int cnt)
+{
+ return true;
+}
+
+
+static bool bnx2x_credit_pool_get_entry(
+ struct bnx2x_credit_pool_obj *o,
+ int *offset)
+{
+ int idx, vec, i;
+
+ *offset = -1;
+
+ /* Find "internal cam-offset" then add to base for this object... */
+ for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) {
+
+ /* Skip the current vector if there are no free entries in it */
+ if (!o->pool_mirror[vec])
+ continue;
+
+ /* If we've got here we are going to find a free entry */
+ for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0;
+ i < BIT_VEC64_ELEM_SZ; idx++, i++)
+
+ if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
+ /* Got one!! */
+ BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
+ *offset = o->base_pool_offset + idx;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool bnx2x_credit_pool_put_entry(
+ struct bnx2x_credit_pool_obj *o,
+ int offset)
+{
+ if (offset < o->base_pool_offset)
+ return false;
+
+ offset -= o->base_pool_offset;
+
+ if (offset >= o->pool_sz)
+ return false;
+
+ /* Return the entry to the pool */
+ BIT_VEC64_SET_BIT(o->pool_mirror, offset);
+
+ return true;
+}
+
+static bool bnx2x_credit_pool_put_entry_always_true(
+ struct bnx2x_credit_pool_obj *o,
+ int offset)
+{
+ return true;
+}
+
+static bool bnx2x_credit_pool_get_entry_always_true(
+ struct bnx2x_credit_pool_obj *o,
+ int *offset)
+{
+ *offset = -1;
+ return true;
+}
+/**
+ * bnx2x_init_credit_pool - initialize credit pool internals.
+ *
+ * @p:
+ * @base: Base entry in the CAM to use.
+ * @credit: pool size.
+ *
+ * If base is negative no CAM entries handling will be performed.
+ * If credit is negative pool operations will always succeed (unlimited pool).
+ *
+ */
+static inline void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
+ int base, int credit)
+{
+ /* Zero the object first */
+ memset(p, 0, sizeof(*p));
+
+ /* Set the table to all 1s */
+ memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
+
+ /* Init a pool as full */
+ atomic_set(&p->credit, credit);
+
+ /* The total poll size */
+ p->pool_sz = credit;
+
+ p->base_pool_offset = base;
+
+ /* Commit the change */
+ smp_mb();
+
+ p->check = bnx2x_credit_pool_check;
+
+ /* if pool credit is negative - disable the checks */
+ if (credit >= 0) {
+ p->put = bnx2x_credit_pool_put;
+ p->get = bnx2x_credit_pool_get;
+ p->put_entry = bnx2x_credit_pool_put_entry;
+ p->get_entry = bnx2x_credit_pool_get_entry;
+ } else {
+ p->put = bnx2x_credit_pool_always_true;
+ p->get = bnx2x_credit_pool_always_true;
+ p->put_entry = bnx2x_credit_pool_put_entry_always_true;
+ p->get_entry = bnx2x_credit_pool_get_entry_always_true;
+ }
+
+ /* If base is negative - disable entries handling */
+ if (base < 0) {
+ p->put_entry = bnx2x_credit_pool_put_entry_always_true;
+ p->get_entry = bnx2x_credit_pool_get_entry_always_true;
+ }
+}
+
+void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p, u8 func_id,
+ u8 func_num)
+{
+/* TODO: this will be defined in consts as well... */
+#define BNX2X_CAM_SIZE_EMUL 5
+
+ int cam_sz;
+
+ if (CHIP_IS_E1(bp)) {
+ /* In E1, Multicast is saved in cam... */
+ if (!CHIP_REV_IS_SLOW(bp))
+ cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST;
+ else
+ cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI;
+
+ bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
+
+ } else if (CHIP_IS_E1H(bp)) {
+ /* CAM credit is equaly divided between all active functions
+ * on the PORT!.
+ */
+ if ((func_num > 0)) {
+ if (!CHIP_REV_IS_SLOW(bp))
+ cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
+ else
+ cam_sz = BNX2X_CAM_SIZE_EMUL;
+ bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
+ } else {
+ /* this should never happen! Block MAC operations. */
+ bnx2x_init_credit_pool(p, 0, 0);
+ }
+
+ } else {
+
+ /*
+ * CAM credit is equaly divided between all active functions
+ * on the PATH.
+ */
+ if ((func_num > 0)) {
+ if (!CHIP_REV_IS_SLOW(bp))
+ cam_sz = (MAX_MAC_CREDIT_E2 / func_num);
+ else
+ cam_sz = BNX2X_CAM_SIZE_EMUL;
+
+ /*
+ * No need for CAM entries handling for 57712 and
+ * newer.
+ */
+ bnx2x_init_credit_pool(p, -1, cam_sz);
+ } else {
+ /* this should never happen! Block MAC operations. */
+ bnx2x_init_credit_pool(p, 0, 0);
+ }
+
+ }
+}
+
+void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p,
+ u8 func_id,
+ u8 func_num)
+{
+ if (CHIP_IS_E1x(bp)) {
+ /*
+ * There is no VLAN credit in HW on 57710 and 57711 only
+ * MAC / MAC-VLAN can be set
+ */
+ bnx2x_init_credit_pool(p, 0, -1);
+ } else {
+ /*
+ * CAM credit is equaly divided between all active functions
+ * on the PATH.
+ */
+ if (func_num > 0) {
+ int credit = MAX_VLAN_CREDIT_E2 / func_num;
+ bnx2x_init_credit_pool(p, func_id * credit, credit);
+ } else
+ /* this should never happen! Block VLAN operations. */
+ bnx2x_init_credit_pool(p, 0, 0);
+ }
+}
+
+/****************** RSS Configuration ******************/
+/**
+ * bnx2x_debug_print_ind_table - prints the indirection table configuration.
+ *
+ * @bp: driver hanlde
+ * @p: pointer to rss configuration
+ *
+ * Prints it when NETIF_MSG_IFUP debug level is configured.
+ */
+static inline void bnx2x_debug_print_ind_table(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p)
+{
+ int i;
+
+ DP(BNX2X_MSG_SP, "Setting indirection table to:\n");
+ DP(BNX2X_MSG_SP, "0x0000: ");
+ for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
+ DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]);
+
+ /* Print 4 bytes in a line */
+ if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) &&
+ (((i + 1) & 0x3) == 0)) {
+ DP_CONT(BNX2X_MSG_SP, "\n");
+ DP(BNX2X_MSG_SP, "0x%04x: ", i + 1);
+ }
+ }
+
+ DP_CONT(BNX2X_MSG_SP, "\n");
+}
+
+/**
+ * bnx2x_setup_rss - configure RSS
+ *
+ * @bp: device handle
+ * @p: rss configuration
+ *
+ * sends on UPDATE ramrod for that matter.
+ */
+static int bnx2x_setup_rss(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p)
+{
+ struct bnx2x_rss_config_obj *o = p->rss_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+ struct eth_rss_update_ramrod_data *data =
+ (struct eth_rss_update_ramrod_data *)(r->rdata);
+ u8 rss_mode = 0;
+ int rc;
+
+ memset(data, 0, sizeof(*data));
+
+ DP(BNX2X_MSG_SP, "Configuring RSS\n");
+
+ /* Set an echo field */
+ data->echo = (r->cid & BNX2X_SWCID_MASK) |
+ (r->state << BNX2X_SWCID_SHIFT);
+
+ /* RSS mode */
+ if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_DISABLED;
+ else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_REGULAR;
+ else if (test_bit(BNX2X_RSS_MODE_VLAN_PRI, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_VLAN_PRI;
+ else if (test_bit(BNX2X_RSS_MODE_E1HOV_PRI, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_E1HOV_PRI;
+ else if (test_bit(BNX2X_RSS_MODE_IP_DSCP, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_IP_DSCP;
+
+ data->rss_mode = rss_mode;
+
+ DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode);
+
+ /* RSS capabilities */
+ if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
+
+ if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
+
+ if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
+
+ if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
+
+ /* Hashing mask */
+ data->rss_result_mask = p->rss_result_mask;
+
+ /* RSS engine ID */
+ data->rss_engine_id = o->engine_id;
+
+ DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id);
+
+ /* Indirection table */
+ memcpy(data->indirection_table, p->ind_table,
+ T_ETH_INDIRECTION_TABLE_SIZE);
+
+ /* Remember the last configuration */
+ memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
+
+ /* Print the indirection table */
+ if (netif_msg_ifup(bp))
+ bnx2x_debug_print_ind_table(bp, p);
+
+ /* RSS keys */
+ if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
+ memcpy(&data->rss_key[0], &p->rss_key[0],
+ sizeof(data->rss_key));
+ data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
+ }
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
+ U64_HI(r->rdata_mapping),
+ U64_LO(r->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+
+ if (rc < 0)
+ return rc;
+
+ return 1;
+}
+
+void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
+ u8 *ind_table)
+{
+ memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
+}
+
+int bnx2x_config_rss(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p)
+{
+ int rc;
+ struct bnx2x_rss_config_obj *o = p->rss_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+
+ /* Do nothing if only driver cleanup was requested */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+ return 0;
+
+ r->set_pending(r);
+
+ rc = o->config_rss(bp, p);
+ if (rc < 0) {
+ r->clear_pending(r);
+ return rc;
+ }
+
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
+ rc = r->wait_comp(bp, r);
+
+ return rc;
+}
+
+
+void bnx2x_init_rss_config_obj(struct bnx2x *bp,
+ struct bnx2x_rss_config_obj *rss_obj,
+ u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
+ void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate,
+ bnx2x_obj_type type)
+{
+ bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type);
+
+ rss_obj->engine_id = engine_id;
+ rss_obj->config_rss = bnx2x_setup_rss;
+}
+
+/********************** Queue state object ***********************************/
+
+/**
+ * bnx2x_queue_state_change - perform Queue state change transition
+ *
+ * @bp: device handle
+ * @params: parameters to perform the transition
+ *
+ * returns 0 in case of successfully completed transition, negative error
+ * code in case of failure, positive (EBUSY) value if there is a completion
+ * to that is still pending (possible only if RAMROD_COMP_WAIT is
+ * not set in params->ramrod_flags for asynchronous commands).
+ *
+ */
+int bnx2x_queue_state_change(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ int rc, pending_bit;
+ unsigned long *pending = &o->pending;
+
+ /* Check that the requested transition is legal */
+ if (o->check_transition(bp, o, params))
+ return -EINVAL;
+
+ /* Set "pending" bit */
+ pending_bit = o->set_pending(o, params);
+
+ /* Don't send a command if only driver cleanup was requested */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags))
+ o->complete_cmd(bp, o, pending_bit);
+ else {
+ /* Send a ramrod */
+ rc = o->send_cmd(bp, params);
+ if (rc) {
+ o->next_state = BNX2X_Q_STATE_MAX;
+ clear_bit(pending_bit, pending);
+ smp_mb__after_clear_bit();
+ return rc;
+ }
+
+ if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
+ rc = o->wait_comp(bp, o, pending_bit);
+ if (rc)
+ return rc;
+
+ return 0;
+ }
+ }
+
+ return !!test_bit(pending_bit, pending);
+}
+
+
+static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
+ struct bnx2x_queue_state_params *params)
+{
+ enum bnx2x_queue_cmd cmd = params->cmd, bit;
+
+ /* ACTIVATE and DEACTIVATE commands are implemented on top of
+ * UPDATE command.
+ */
+ if ((cmd == BNX2X_Q_CMD_ACTIVATE) ||
+ (cmd == BNX2X_Q_CMD_DEACTIVATE))
+ bit = BNX2X_Q_CMD_UPDATE;
+ else
+ bit = cmd;
+
+ set_bit(bit, &obj->pending);
+ return bit;
+}
+
+static int bnx2x_queue_wait_comp(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd cmd)
+{
+ return bnx2x_state_wait(bp, cmd, &o->pending);
+}
+
+/**
+ * bnx2x_queue_comp_cmd - complete the state change command.
+ *
+ * @bp: device handle
+ * @o:
+ * @cmd:
+ *
+ * Checks that the arrived completion is expected.
+ */
+static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd cmd)
+{
+ unsigned long cur_pending = o->pending;
+
+ if (!test_and_clear_bit(cmd, &cur_pending)) {
+ BNX2X_ERR("Bad MC reply %d for queue %d in state %d "
+ "pending 0x%lx, next_state %d\n", cmd,
+ o->cids[BNX2X_PRIMARY_CID_INDEX],
+ o->state, cur_pending, o->next_state);
+ return -EINVAL;
+ }
+
+ if (o->next_tx_only >= o->max_cos)
+ /* >= becuase tx only must always be smaller than cos since the
+ * primary connection suports COS 0
+ */
+ BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
+ o->next_tx_only, o->max_cos);
+
+ DP(BNX2X_MSG_SP, "Completing command %d for queue %d, "
+ "setting state to %d\n", cmd,
+ 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",
+ o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
+
+ o->state = o->next_state;
+ o->num_tx_only = o->next_tx_only;
+ o->next_state = BNX2X_Q_STATE_MAX;
+
+ /* It's important that o->state and o->next_state are
+ * updated before o->pending.
+ */
+ wmb();
+
+ clear_bit(cmd, &o->pending);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *cmd_params,
+ struct client_init_ramrod_data *data)
+{
+ struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
+
+ /* Rx data */
+
+ /* IPv6 TPA supported for E2 and above only */
+ data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->flags) *
+ CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
+}
+
+static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_general_setup_params *params,
+ struct client_init_general_data *gen_data,
+ unsigned long *flags)
+{
+ gen_data->client_id = o->cl_id;
+
+ if (test_bit(BNX2X_Q_FLG_STATS, flags)) {
+ gen_data->statistics_counter_id =
+ params->stat_id;
+ gen_data->statistics_en_flg = 1;
+ gen_data->statistics_zero_flg =
+ test_bit(BNX2X_Q_FLG_ZERO_STATS, flags);
+ } else
+ gen_data->statistics_counter_id =
+ DISABLE_STATISTIC_COUNTER_ID_VALUE;
+
+ gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags);
+ gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags);
+ gen_data->sp_client_id = params->spcl_id;
+ gen_data->mtu = cpu_to_le16(params->mtu);
+ gen_data->func_id = o->func_id;
+
+
+ gen_data->cos = params->cos;
+
+ gen_data->traffic_type =
+ 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",
+ gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
+}
+
+static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_txq_setup_params *params,
+ struct client_init_tx_data *tx_data,
+ unsigned long *flags)
+{
+ tx_data->enforce_security_flg =
+ test_bit(BNX2X_Q_FLG_TX_SEC, flags);
+ tx_data->default_vlan =
+ cpu_to_le16(params->default_vlan);
+ tx_data->default_vlan_flg =
+ test_bit(BNX2X_Q_FLG_DEF_VLAN, flags);
+ tx_data->tx_switching_flg =
+ test_bit(BNX2X_Q_FLG_TX_SWITCH, flags);
+ tx_data->anti_spoofing_flg =
+ test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags);
+ tx_data->tx_status_block_id = params->fw_sb_id;
+ tx_data->tx_sb_index_number = params->sb_cq_index;
+ tx_data->tss_leading_client_id = params->tss_leading_cl_id;
+
+ tx_data->tx_bd_page_base.lo =
+ cpu_to_le32(U64_LO(params->dscr_map));
+ tx_data->tx_bd_page_base.hi =
+ cpu_to_le32(U64_HI(params->dscr_map));
+
+ /* Don't configure any Tx switching mode during queue SETUP */
+ tx_data->state = 0;
+}
+
+static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o,
+ struct rxq_pause_params *params,
+ struct client_init_rx_data *rx_data)
+{
+ /* flow control data */
+ rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo);
+ rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi);
+ rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo);
+ rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi);
+ rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo);
+ rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi);
+ rx_data->rx_cos_mask = cpu_to_le16(params->pri_map);
+}
+
+static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_rxq_setup_params *params,
+ struct client_init_rx_data *rx_data,
+ unsigned long *flags)
+{
+ /* Rx data */
+ rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) *
+ CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
+ rx_data->vmqueue_mode_en_flg = 0;
+
+ rx_data->cache_line_alignment_log_size =
+ params->cache_line_log;
+ rx_data->enable_dynamic_hc =
+ test_bit(BNX2X_Q_FLG_DHC, flags);
+ rx_data->max_sges_for_packet = params->max_sges_pkt;
+ rx_data->client_qzone_id = params->cl_qzone_id;
+ rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz);
+
+ /* Always start in DROP_ALL mode */
+ rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
+ CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
+
+ /* We don't set drop flags */
+ rx_data->drop_ip_cs_err_flg = 0;
+ rx_data->drop_tcp_cs_err_flg = 0;
+ rx_data->drop_ttl0_flg = 0;
+ rx_data->drop_udp_cs_err_flg = 0;
+ rx_data->inner_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_FLG_VLAN, flags);
+ rx_data->outer_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_FLG_OV, flags);
+ rx_data->status_block_id = params->fw_sb_id;
+ rx_data->rx_sb_index_number = params->sb_cq_index;
+ rx_data->max_tpa_queues = params->max_tpa_queues;
+ rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz);
+ rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz);
+ rx_data->bd_page_base.lo =
+ cpu_to_le32(U64_LO(params->dscr_map));
+ rx_data->bd_page_base.hi =
+ cpu_to_le32(U64_HI(params->dscr_map));
+ rx_data->sge_page_base.lo =
+ cpu_to_le32(U64_LO(params->sge_map));
+ rx_data->sge_page_base.hi =
+ cpu_to_le32(U64_HI(params->sge_map));
+ rx_data->cqe_page_base.lo =
+ cpu_to_le32(U64_LO(params->rcq_map));
+ rx_data->cqe_page_base.hi =
+ cpu_to_le32(U64_HI(params->rcq_map));
+ rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags);
+
+ if (test_bit(BNX2X_Q_FLG_MCAST, flags)) {
+ rx_data->approx_mcast_engine_id = o->func_id;
+ rx_data->is_approx_mcast = 1;
+ }
+
+ rx_data->rss_engine_id = params->rss_engine_id;
+
+ /* silent vlan removal */
+ rx_data->silent_vlan_removal_flg =
+ test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags);
+ rx_data->silent_vlan_value =
+ cpu_to_le16(params->silent_removal_value);
+ rx_data->silent_vlan_mask =
+ cpu_to_le16(params->silent_removal_mask);
+
+}
+
+/* initialize the general, tx and rx parts of a queue object */
+static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *cmd_params,
+ struct client_init_ramrod_data *data)
+{
+ bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
+ &cmd_params->params.setup.gen_params,
+ &data->general,
+ &cmd_params->params.setup.flags);
+
+ bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
+ &cmd_params->params.setup.txq_params,
+ &data->tx,
+ &cmd_params->params.setup.flags);
+
+ bnx2x_q_fill_init_rx_data(cmd_params->q_obj,
+ &cmd_params->params.setup.rxq_params,
+ &data->rx,
+ &cmd_params->params.setup.flags);
+
+ bnx2x_q_fill_init_pause_data(cmd_params->q_obj,
+ &cmd_params->params.setup.pause_params,
+ &data->rx);
+}
+
+/* initialize the general and tx parts of a tx-only queue object */
+static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *cmd_params,
+ struct tx_queue_init_ramrod_data *data)
+{
+ bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
+ &cmd_params->params.tx_only.gen_params,
+ &data->general,
+ &cmd_params->params.tx_only.flags);
+
+ bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
+ &cmd_params->params.tx_only.txq_params,
+ &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],
+ data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi);
+}
+
+/**
+ * bnx2x_q_init - init HW/FW queue
+ *
+ * @bp: device handle
+ * @params:
+ *
+ * HW/FW initial Queue configuration:
+ * - HC: Rx and Tx
+ * - CDU context validation
+ *
+ */
+static inline int bnx2x_q_init(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct bnx2x_queue_init_params *init = &params->params.init;
+ u16 hc_usec;
+ u8 cos;
+
+ /* Tx HC configuration */
+ if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) &&
+ test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) {
+ hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
+
+ bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id,
+ init->tx.sb_cq_index,
+ !test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags),
+ hc_usec);
+ }
+
+ /* Rx HC configuration */
+ if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) &&
+ test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) {
+ hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
+
+ bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id,
+ init->rx.sb_cq_index,
+ !test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags),
+ hc_usec);
+ }
+
+ /* Set CDU context validation values */
+ for (cos = 0; cos < o->max_cos; cos++) {
+ DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d",
+ o->cids[cos], cos);
+ DP(BNX2X_MSG_SP, "context pointer %p", init->cxts[cos]);
+ bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
+ }
+
+ /* As no ramrod is sent, complete the command immediately */
+ o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT);
+
+ mmiowb();
+ smp_mb();
+
+ return 0;
+}
+
+static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct client_init_ramrod_data *rdata =
+ (struct client_init_ramrod_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+
+ /* Clear the ramrod data */
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data */
+ bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct client_init_ramrod_data *rdata =
+ (struct client_init_ramrod_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+
+ /* Clear the ramrod data */
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data */
+ bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
+ bnx2x_q_fill_setup_data_e2(bp, params, rdata);
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct tx_queue_init_ramrod_data *rdata =
+ (struct tx_queue_init_ramrod_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP;
+ struct bnx2x_queue_setup_tx_only_params *tx_only_params =
+ &params->params.tx_only;
+ u8 cid_index = tx_only_params->cid_index;
+
+
+ if (cid_index >= o->max_cos) {
+ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+ o->cl_id, cid_index);
+ return -EINVAL;
+ }
+
+ DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d",
+ tx_only_params->gen_params.cos,
+ tx_only_params->gen_params.spcl_id);
+
+ /* Clear the ramrod data */
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data */
+ 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",
+ o->cids[cid_index],
+ rdata->general.client_id,
+ rdata->general.sp_client_id, rdata->general.cos);
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static void bnx2x_q_fill_update_data(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *obj,
+ struct bnx2x_queue_update_params *params,
+ struct client_update_ramrod_data *data)
+{
+ /* Client ID of the client to update */
+ data->client_id = obj->cl_id;
+
+ /* Function ID of the client to update */
+ data->func_id = obj->func_id;
+
+ /* Default VLAN value */
+ data->default_vlan = cpu_to_le16(params->def_vlan);
+
+ /* Inner VLAN stripping */
+ data->inner_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, &params->update_flags);
+ data->inner_vlan_removal_change_flg =
+ test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
+ &params->update_flags);
+
+ /* Outer VLAN sripping */
+ data->outer_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, &params->update_flags);
+ data->outer_vlan_removal_change_flg =
+ test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
+ &params->update_flags);
+
+ /* Drop packets that have source MAC that doesn't belong to this
+ * Queue.
+ */
+ data->anti_spoofing_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, &params->update_flags);
+ data->anti_spoofing_change_flg =
+ test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, &params->update_flags);
+
+ /* Activate/Deactivate */
+ data->activate_flg =
+ test_bit(BNX2X_Q_UPDATE_ACTIVATE, &params->update_flags);
+ data->activate_change_flg =
+ test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &params->update_flags);
+
+ /* Enable default VLAN */
+ data->default_vlan_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, &params->update_flags);
+ data->default_vlan_change_flg =
+ test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+ &params->update_flags);
+
+ /* silent vlan removal */
+ data->silent_vlan_change_flg =
+ test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+ &params->update_flags);
+ data->silent_vlan_removal_flg =
+ test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, &params->update_flags);
+ data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
+ data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
+}
+
+static inline int bnx2x_q_send_update(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct client_update_ramrod_data *rdata =
+ (struct client_update_ramrod_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ struct bnx2x_queue_update_params *update_params =
+ &params->params.update;
+ u8 cid_index = update_params->cid_index;
+
+ if (cid_index >= o->max_cos) {
+ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+ o->cl_id, cid_index);
+ return -EINVAL;
+ }
+
+
+ /* Clear the ramrod data */
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data */
+ bnx2x_q_fill_update_data(bp, o, update_params, rdata);
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
+ o->cids[cid_index], U64_HI(data_mapping),
+ U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+/**
+ * bnx2x_q_send_deactivate - send DEACTIVATE command
+ *
+ * @bp: device handle
+ * @params:
+ *
+ * implemented using the UPDATE command.
+ */
+static inline int bnx2x_q_send_deactivate(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_update_params *update = &params->params.update;
+
+ memset(update, 0, sizeof(*update));
+
+ __set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
+
+ return bnx2x_q_send_update(bp, params);
+}
+
+/**
+ * bnx2x_q_send_activate - send ACTIVATE command
+ *
+ * @bp: device handle
+ * @params:
+ *
+ * implemented using the UPDATE command.
+ */
+static inline int bnx2x_q_send_activate(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_update_params *update = &params->params.update;
+
+ memset(update, 0, sizeof(*update));
+
+ __set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags);
+ __set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
+
+ return bnx2x_q_send_update(bp, params);
+}
+
+static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ /* TODO: Not implemented yet. */
+ return -1;
+}
+
+static inline int bnx2x_q_send_halt(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT,
+ o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id,
+ ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ u8 cid_idx = params->params.cfc_del.cid_index;
+
+ if (cid_idx >= o->max_cos) {
+ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+ o->cl_id, cid_idx);
+ return -EINVAL;
+ }
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL,
+ o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_terminate(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ u8 cid_index = params->params.terminate.cid_index;
+
+ if (cid_index >= o->max_cos) {
+ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+ o->cl_id, cid_index);
+ return -EINVAL;
+ }
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE,
+ o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_empty(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY,
+ o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0,
+ ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_Q_CMD_INIT:
+ return bnx2x_q_init(bp, params);
+ case BNX2X_Q_CMD_SETUP_TX_ONLY:
+ return bnx2x_q_send_setup_tx_only(bp, params);
+ case BNX2X_Q_CMD_DEACTIVATE:
+ return bnx2x_q_send_deactivate(bp, params);
+ case BNX2X_Q_CMD_ACTIVATE:
+ return bnx2x_q_send_activate(bp, params);
+ case BNX2X_Q_CMD_UPDATE:
+ return bnx2x_q_send_update(bp, params);
+ case BNX2X_Q_CMD_UPDATE_TPA:
+ return bnx2x_q_send_update_tpa(bp, params);
+ case BNX2X_Q_CMD_HALT:
+ return bnx2x_q_send_halt(bp, params);
+ case BNX2X_Q_CMD_CFC_DEL:
+ return bnx2x_q_send_cfc_del(bp, params);
+ case BNX2X_Q_CMD_TERMINATE:
+ return bnx2x_q_send_terminate(bp, params);
+ case BNX2X_Q_CMD_EMPTY:
+ return bnx2x_q_send_empty(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_Q_CMD_SETUP:
+ return bnx2x_q_send_setup_e1x(bp, params);
+ case BNX2X_Q_CMD_INIT:
+ case BNX2X_Q_CMD_SETUP_TX_ONLY:
+ case BNX2X_Q_CMD_DEACTIVATE:
+ case BNX2X_Q_CMD_ACTIVATE:
+ case BNX2X_Q_CMD_UPDATE:
+ case BNX2X_Q_CMD_UPDATE_TPA:
+ case BNX2X_Q_CMD_HALT:
+ case BNX2X_Q_CMD_CFC_DEL:
+ case BNX2X_Q_CMD_TERMINATE:
+ case BNX2X_Q_CMD_EMPTY:
+ return bnx2x_queue_send_cmd_cmn(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_Q_CMD_SETUP:
+ return bnx2x_q_send_setup_e2(bp, params);
+ case BNX2X_Q_CMD_INIT:
+ case BNX2X_Q_CMD_SETUP_TX_ONLY:
+ case BNX2X_Q_CMD_DEACTIVATE:
+ case BNX2X_Q_CMD_ACTIVATE:
+ case BNX2X_Q_CMD_UPDATE:
+ case BNX2X_Q_CMD_UPDATE_TPA:
+ case BNX2X_Q_CMD_HALT:
+ case BNX2X_Q_CMD_CFC_DEL:
+ case BNX2X_Q_CMD_TERMINATE:
+ case BNX2X_Q_CMD_EMPTY:
+ return bnx2x_queue_send_cmd_cmn(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+/**
+ * bnx2x_queue_chk_transition - check state machine of a regular Queue
+ *
+ * @bp: device handle
+ * @o:
+ * @params:
+ *
+ * (not Forwarding)
+ * It both checks if the requested command is legal in a current
+ * state and, if it's legal, sets a `next_state' in the object
+ * that will be used in the completion flow to set the `state'
+ * of the object.
+ *
+ * returns 0 if a requested command is a legal transition,
+ * -EINVAL otherwise.
+ */
+static int bnx2x_queue_chk_transition(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_queue_state_params *params)
+{
+ enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX;
+ enum bnx2x_queue_cmd cmd = params->cmd;
+ struct bnx2x_queue_update_params *update_params =
+ &params->params.update;
+ u8 next_tx_only = o->num_tx_only;
+
+ /*
+ * Forget all pending for completion commands if a driver only state
+ * transition has been requested.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+ o->pending = 0;
+ o->next_state = BNX2X_Q_STATE_MAX;
+ }
+
+ /*
+ * Don't allow a next state transition if we are in the middle of
+ * the previous one.
+ */
+ if (o->pending)
+ return -EBUSY;
+
+ switch (state) {
+ case BNX2X_Q_STATE_RESET:
+ if (cmd == BNX2X_Q_CMD_INIT)
+ next_state = BNX2X_Q_STATE_INITIALIZED;
+
+ break;
+ case BNX2X_Q_STATE_INITIALIZED:
+ if (cmd == BNX2X_Q_CMD_SETUP) {
+ if (test_bit(BNX2X_Q_FLG_ACTIVE,
+ &params->params.setup.flags))
+ next_state = BNX2X_Q_STATE_ACTIVE;
+ else
+ next_state = BNX2X_Q_STATE_INACTIVE;
+ }
+
+ break;
+ case BNX2X_Q_STATE_ACTIVE:
+ if (cmd == BNX2X_Q_CMD_DEACTIVATE)
+ next_state = BNX2X_Q_STATE_INACTIVE;
+
+ else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+ (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+ next_state = BNX2X_Q_STATE_ACTIVE;
+
+ else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
+ next_state = BNX2X_Q_STATE_MULTI_COS;
+ next_tx_only = 1;
+ }
+
+ else if (cmd == BNX2X_Q_CMD_HALT)
+ next_state = BNX2X_Q_STATE_STOPPED;
+
+ else if (cmd == BNX2X_Q_CMD_UPDATE) {
+ /* If "active" state change is requested, update the
+ * state accordingly.
+ */
+ if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+ &update_params->update_flags) &&
+ !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+ &update_params->update_flags))
+ next_state = BNX2X_Q_STATE_INACTIVE;
+ else
+ next_state = BNX2X_Q_STATE_ACTIVE;
+ }
+
+ break;
+ case BNX2X_Q_STATE_MULTI_COS:
+ if (cmd == BNX2X_Q_CMD_TERMINATE)
+ next_state = BNX2X_Q_STATE_MCOS_TERMINATED;
+
+ else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
+ next_state = BNX2X_Q_STATE_MULTI_COS;
+ next_tx_only = o->num_tx_only + 1;
+ }
+
+ else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+ (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+ next_state = BNX2X_Q_STATE_MULTI_COS;
+
+ else if (cmd == BNX2X_Q_CMD_UPDATE) {
+ /* If "active" state change is requested, update the
+ * state accordingly.
+ */
+ if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+ &update_params->update_flags) &&
+ !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+ &update_params->update_flags))
+ next_state = BNX2X_Q_STATE_INACTIVE;
+ else
+ next_state = BNX2X_Q_STATE_MULTI_COS;
+ }
+
+ break;
+ case BNX2X_Q_STATE_MCOS_TERMINATED:
+ if (cmd == BNX2X_Q_CMD_CFC_DEL) {
+ next_tx_only = o->num_tx_only - 1;
+ if (next_tx_only == 0)
+ next_state = BNX2X_Q_STATE_ACTIVE;
+ else
+ next_state = BNX2X_Q_STATE_MULTI_COS;
+ }
+
+ break;
+ case BNX2X_Q_STATE_INACTIVE:
+ if (cmd == BNX2X_Q_CMD_ACTIVATE)
+ next_state = BNX2X_Q_STATE_ACTIVE;
+
+ else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+ (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+ next_state = BNX2X_Q_STATE_INACTIVE;
+
+ else if (cmd == BNX2X_Q_CMD_HALT)
+ next_state = BNX2X_Q_STATE_STOPPED;
+
+ else if (cmd == BNX2X_Q_CMD_UPDATE) {
+ /* If "active" state change is requested, update the
+ * state accordingly.
+ */
+ if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+ &update_params->update_flags) &&
+ test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+ &update_params->update_flags)){
+ if (o->num_tx_only == 0)
+ next_state = BNX2X_Q_STATE_ACTIVE;
+ else /* tx only queues exist for this queue */
+ next_state = BNX2X_Q_STATE_MULTI_COS;
+ } else
+ next_state = BNX2X_Q_STATE_INACTIVE;
+ }
+
+ break;
+ case BNX2X_Q_STATE_STOPPED:
+ if (cmd == BNX2X_Q_CMD_TERMINATE)
+ next_state = BNX2X_Q_STATE_TERMINATED;
+
+ break;
+ case BNX2X_Q_STATE_TERMINATED:
+ if (cmd == BNX2X_Q_CMD_CFC_DEL)
+ next_state = BNX2X_Q_STATE_RESET;
+
+ break;
+ default:
+ BNX2X_ERR("Illegal state: %d\n", state);
+ }
+
+ /* Transition is assured */
+ if (next_state != BNX2X_Q_STATE_MAX) {
+ DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n",
+ state, cmd, next_state);
+ o->next_state = next_state;
+ o->next_tx_only = next_tx_only;
+ return 0;
+ }
+
+ DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd);
+
+ return -EINVAL;
+}
+
+void bnx2x_init_queue_obj(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *obj,
+ u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id,
+ void *rdata,
+ dma_addr_t rdata_mapping, unsigned long type)
+{
+ memset(obj, 0, sizeof(*obj));
+
+ /* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */
+ BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt);
+
+ memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt);
+ obj->max_cos = cid_cnt;
+ obj->cl_id = cl_id;
+ obj->func_id = func_id;
+ obj->rdata = rdata;
+ obj->rdata_mapping = rdata_mapping;
+ obj->type = type;
+ obj->next_state = BNX2X_Q_STATE_MAX;
+
+ if (CHIP_IS_E1x(bp))
+ obj->send_cmd = bnx2x_queue_send_cmd_e1x;
+ else
+ obj->send_cmd = bnx2x_queue_send_cmd_e2;
+
+ obj->check_transition = bnx2x_queue_chk_transition;
+
+ obj->complete_cmd = bnx2x_queue_comp_cmd;
+ obj->wait_comp = bnx2x_queue_wait_comp;
+ obj->set_pending = bnx2x_queue_set_pending;
+}
+
+void bnx2x_queue_set_cos_cid(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *obj,
+ u32 cid, u8 index)
+{
+ obj->cids[index] = cid;
+}
+
+/********************** Function state object *********************************/
+enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o)
+{
+ /* in the middle of transaction - return INVALID state */
+ if (o->pending)
+ return BNX2X_F_STATE_MAX;
+
+ /*
+ * unsure the order of reading of o->pending and o->state
+ * o->pending should be read first
+ */
+ rmb();
+
+ return o->state;
+}
+
+static int bnx2x_func_wait_comp(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd)
+{
+ return bnx2x_state_wait(bp, cmd, &o->pending);
+}
+
+/**
+ * bnx2x_func_state_change_comp - complete the state machine transition
+ *
+ * @bp: device handle
+ * @o:
+ * @cmd:
+ *
+ * Called on state change transition. Completes the state
+ * machine transition only - no HW interaction.
+ */
+static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd)
+{
+ unsigned long cur_pending = o->pending;
+
+ if (!test_and_clear_bit(cmd, &cur_pending)) {
+ BNX2X_ERR("Bad MC reply %d for func %d in state %d "
+ "pending 0x%lx, next_state %d\n", cmd, BP_FUNC(bp),
+ o->state, cur_pending, o->next_state);
+ return -EINVAL;
+ }
+
+ 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;
+
+ /* It's important that o->state and o->next_state are
+ * updated before o->pending.
+ */
+ wmb();
+
+ clear_bit(cmd, &o->pending);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+/**
+ * bnx2x_func_comp_cmd - complete the state change command
+ *
+ * @bp: device handle
+ * @o:
+ * @cmd:
+ *
+ * Checks that the arrived completion is expected.
+ */
+static int bnx2x_func_comp_cmd(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd)
+{
+ /* Complete the state machine part first, check if it's a
+ * legal completion.
+ */
+ int rc = bnx2x_func_state_change_comp(bp, o, cmd);
+ return rc;
+}
+
+/**
+ * bnx2x_func_chk_transition - perform function state machine transition
+ *
+ * @bp: device handle
+ * @o:
+ * @params:
+ *
+ * It both checks if the requested command is legal in a current
+ * state and, if it's legal, sets a `next_state' in the object
+ * that will be used in the completion flow to set the `state'
+ * of the object.
+ *
+ * returns 0 if a requested command is a legal transition,
+ * -EINVAL otherwise.
+ */
+static int bnx2x_func_chk_transition(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ struct bnx2x_func_state_params *params)
+{
+ enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
+ enum bnx2x_func_cmd cmd = params->cmd;
+
+ /*
+ * Forget all pending for completion commands if a driver only state
+ * transition has been requested.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+ o->pending = 0;
+ o->next_state = BNX2X_F_STATE_MAX;
+ }
+
+ /*
+ * Don't allow a next state transition if we are in the middle of
+ * the previous one.
+ */
+ if (o->pending)
+ return -EBUSY;
+
+ switch (state) {
+ case BNX2X_F_STATE_RESET:
+ if (cmd == BNX2X_F_CMD_HW_INIT)
+ next_state = BNX2X_F_STATE_INITIALIZED;
+
+ break;
+ case BNX2X_F_STATE_INITIALIZED:
+ if (cmd == BNX2X_F_CMD_START)
+ next_state = BNX2X_F_STATE_STARTED;
+
+ else if (cmd == BNX2X_F_CMD_HW_RESET)
+ next_state = BNX2X_F_STATE_RESET;
+
+ break;
+ case BNX2X_F_STATE_STARTED:
+ if (cmd == BNX2X_F_CMD_STOP)
+ next_state = BNX2X_F_STATE_INITIALIZED;
+ else if (cmd == BNX2X_F_CMD_TX_STOP)
+ next_state = BNX2X_F_STATE_TX_STOPPED;
+
+ break;
+ case BNX2X_F_STATE_TX_STOPPED:
+ if (cmd == BNX2X_F_CMD_TX_START)
+ next_state = BNX2X_F_STATE_STARTED;
+
+ break;
+ default:
+ BNX2X_ERR("Unknown state: %d\n", state);
+ }
+
+ /* Transition is assured */
+ if (next_state != BNX2X_F_STATE_MAX) {
+ DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n",
+ state, cmd, next_state);
+ o->next_state = next_state;
+ return 0;
+ }
+
+ DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n",
+ state, cmd);
+
+ return -EINVAL;
+}
+
+/**
+ * bnx2x_func_init_func - performs HW init at function stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
+ * HW blocks.
+ */
+static inline int bnx2x_func_init_func(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ return drv->init_hw_func(bp);
+}
+
+/**
+ * bnx2x_func_init_port - performs HW init at port stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
+ * FUNCTION-only HW blocks.
+ *
+ */
+static inline int bnx2x_func_init_port(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ int rc = drv->init_hw_port(bp);
+ if (rc)
+ return rc;
+
+ return bnx2x_func_init_func(bp, drv);
+}
+
+/**
+ * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
+ * PORT-only and FUNCTION-only HW blocks.
+ */
+static inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ int rc = drv->init_hw_cmn_chip(bp);
+ if (rc)
+ return rc;
+
+ return bnx2x_func_init_port(bp, drv);
+}
+
+/**
+ * bnx2x_func_init_cmn - performs HW init at common stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
+ * PORT-only and FUNCTION-only HW blocks.
+ */
+static inline int bnx2x_func_init_cmn(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ int rc = drv->init_hw_cmn(bp);
+ if (rc)
+ return rc;
+
+ return bnx2x_func_init_port(bp, drv);
+}
+
+static int bnx2x_func_hw_init(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ u32 load_code = params->params.hw_init.load_phase;
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ const struct bnx2x_func_sp_drv_ops *drv = o->drv;
+ int rc = 0;
+
+ DP(BNX2X_MSG_SP, "function %d load_code %x\n",
+ BP_ABS_FUNC(bp), load_code);
+
+ /* Prepare buffers for unzipping the FW */
+ rc = drv->gunzip_init(bp);
+ if (rc)
+ return rc;
+
+ /* Prepare FW */
+ rc = drv->init_fw(bp);
+ if (rc) {
+ BNX2X_ERR("Error loading firmware\n");
+ goto fw_init_err;
+ }
+
+ /* Handle the beginning of COMMON_XXX pases separatelly... */
+ switch (load_code) {
+ case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
+ rc = bnx2x_func_init_cmn_chip(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ case FW_MSG_CODE_DRV_LOAD_COMMON:
+ rc = bnx2x_func_init_cmn(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ case FW_MSG_CODE_DRV_LOAD_PORT:
+ rc = bnx2x_func_init_port(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ case FW_MSG_CODE_DRV_LOAD_FUNCTION:
+ rc = bnx2x_func_init_func(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ default:
+ BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
+ rc = -EINVAL;
+ }
+
+init_hw_err:
+ drv->release_fw(bp);
+
+fw_init_err:
+ drv->gunzip_end(bp);
+
+ /* In case of success, complete the comand immediatelly: no ramrods
+ * have been sent.
+ */
+ if (!rc)
+ o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT);
+
+ return rc;
+}
+
+/**
+ * bnx2x_func_reset_func - reset HW at function stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
+ * FUNCTION-only HW blocks.
+ */
+static inline void bnx2x_func_reset_func(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ drv->reset_hw_func(bp);
+}
+
+/**
+ * bnx2x_func_reset_port - reser HW at port stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
+ * FUNCTION-only and PORT-only HW blocks.
+ *
+ * !!!IMPORTANT!!!
+ *
+ * It's important to call reset_port before reset_func() as the last thing
+ * reset_func does is pf_disable() thus disabling PGLUE_B, which
+ * makes impossible any DMAE transactions.
+ */
+static inline void bnx2x_func_reset_port(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ drv->reset_hw_port(bp);
+ bnx2x_func_reset_func(bp, drv);
+}
+
+/**
+ * bnx2x_func_reset_cmn - reser HW at common stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
+ * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
+ * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
+ */
+static inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ bnx2x_func_reset_port(bp, drv);
+ drv->reset_hw_cmn(bp);
+}
+
+
+static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ u32 reset_phase = params->params.hw_reset.reset_phase;
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ const struct bnx2x_func_sp_drv_ops *drv = o->drv;
+
+ DP(BNX2X_MSG_SP, "function %d reset_phase %x\n", BP_ABS_FUNC(bp),
+ reset_phase);
+
+ switch (reset_phase) {
+ case FW_MSG_CODE_DRV_UNLOAD_COMMON:
+ bnx2x_func_reset_cmn(bp, drv);
+ break;
+ case FW_MSG_CODE_DRV_UNLOAD_PORT:
+ bnx2x_func_reset_port(bp, drv);
+ break;
+ case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
+ bnx2x_func_reset_func(bp, drv);
+ break;
+ default:
+ BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n",
+ reset_phase);
+ break;
+ }
+
+ /* Complete the comand immediatelly: no ramrods have been sent. */
+ o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
+
+ return 0;
+}
+
+static inline int bnx2x_func_send_start(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ struct function_start_data *rdata =
+ (struct function_start_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ struct bnx2x_func_start_params *start_params = &params->params.start;
+
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data with provided parameters */
+ rdata->function_mode = cpu_to_le16(start_params->mf_mode);
+ rdata->sd_vlan_tag = start_params->sd_vlan_tag;
+ rdata->path_id = BP_PATH(bp);
+ rdata->network_cos_mode = start_params->network_cos_mode;
+
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_func_send_stop(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0,
+ NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
+ NONE_CONNECTION_TYPE);
+}
+static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ struct flow_control_configuration *rdata =
+ (struct flow_control_configuration *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ struct bnx2x_func_tx_start_params *tx_start_params =
+ &params->params.tx_start;
+ int i;
+
+ memset(rdata, 0, sizeof(*rdata));
+
+ rdata->dcb_enabled = tx_start_params->dcb_enabled;
+ rdata->dcb_version = tx_start_params->dcb_version;
+ rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
+
+ for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
+ rdata->traffic_type_to_priority_cos[i] =
+ tx_start_params->traffic_type_to_priority_cos[i];
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
+static int bnx2x_func_send_cmd(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_F_CMD_HW_INIT:
+ return bnx2x_func_hw_init(bp, params);
+ case BNX2X_F_CMD_START:
+ return bnx2x_func_send_start(bp, params);
+ case BNX2X_F_CMD_STOP:
+ return bnx2x_func_send_stop(bp, params);
+ case BNX2X_F_CMD_HW_RESET:
+ return bnx2x_func_hw_reset(bp, params);
+ case BNX2X_F_CMD_TX_STOP:
+ return bnx2x_func_send_tx_stop(bp, params);
+ case BNX2X_F_CMD_TX_START:
+ return bnx2x_func_send_tx_start(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+void bnx2x_init_func_obj(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *obj,
+ void *rdata, dma_addr_t rdata_mapping,
+ struct bnx2x_func_sp_drv_ops *drv_iface)
+{
+ memset(obj, 0, sizeof(*obj));
+
+ mutex_init(&obj->one_pending_mutex);
+
+ obj->rdata = rdata;
+ obj->rdata_mapping = rdata_mapping;
+
+ obj->send_cmd = bnx2x_func_send_cmd;
+ obj->check_transition = bnx2x_func_chk_transition;
+ obj->complete_cmd = bnx2x_func_comp_cmd;
+ obj->wait_comp = bnx2x_func_wait_comp;
+
+ obj->drv = drv_iface;
+}
+
+/**
+ * bnx2x_func_state_change - perform Function state change transition
+ *
+ * @bp: device handle
+ * @params: parameters to perform the transaction
+ *
+ * returns 0 in case of successfully completed transition,
+ * negative error code in case of failure, positive
+ * (EBUSY) value if there is a completion to that is
+ * still pending (possible only if RAMROD_COMP_WAIT is
+ * not set in params->ramrod_flags for asynchronous
+ * commands).
+ */
+int bnx2x_func_state_change(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ int rc;
+ enum bnx2x_func_cmd cmd = params->cmd;
+ unsigned long *pending = &o->pending;
+
+ mutex_lock(&o->one_pending_mutex);
+
+ /* Check that the requested transition is legal */
+ if (o->check_transition(bp, o, params)) {
+ mutex_unlock(&o->one_pending_mutex);
+ return -EINVAL;
+ }
+
+ /* Set "pending" bit */
+ set_bit(cmd, pending);
+
+ /* Don't send a command if only driver cleanup was requested */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+ bnx2x_func_state_change_comp(bp, o, cmd);
+ mutex_unlock(&o->one_pending_mutex);
+ } else {
+ /* Send a ramrod */
+ rc = o->send_cmd(bp, params);
+
+ mutex_unlock(&o->one_pending_mutex);
+
+ if (rc) {
+ o->next_state = BNX2X_F_STATE_MAX;
+ clear_bit(cmd, pending);
+ smp_mb__after_clear_bit();
+ return rc;
+ }
+
+ if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
+ rc = o->wait_comp(bp, o, cmd);
+ if (rc)
+ return rc;
+
+ return 0;
+ }
+ }
+
+ return !!test_bit(cmd, pending);
+}
diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h
new file mode 100644
index 000000000000..9a517c2e9f1b
--- /dev/null
+++ b/drivers/net/bnx2x/bnx2x_sp.h
@@ -0,0 +1,1297 @@
+/* bnx2x_sp.h: Broadcom Everest network driver.
+ *
+ * Copyright 2011 Broadcom Corporation
+ *
+ * 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.gnu.org/licenses/old-licenses/gpl-2.0.html (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.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov
+ *
+ */
+#ifndef BNX2X_SP_VERBS
+#define BNX2X_SP_VERBS
+
+struct bnx2x;
+struct eth_context;
+
+/* Bits representing general command's configuration */
+enum {
+ RAMROD_TX,
+ RAMROD_RX,
+ /* Wait until all pending commands complete */
+ RAMROD_COMP_WAIT,
+ /* Don't send a ramrod, only update a registry */
+ RAMROD_DRV_CLR_ONLY,
+ /* Configure HW according to the current object state */
+ RAMROD_RESTORE,
+ /* Execute the next command now */
+ RAMROD_EXEC,
+ /*
+ * Don't add a new command and continue execution of posponed
+ * commands. If not set a new command will be added to the
+ * pending commands list.
+ */
+ RAMROD_CONT,
+};
+
+typedef enum {
+ BNX2X_OBJ_TYPE_RX,
+ BNX2X_OBJ_TYPE_TX,
+ BNX2X_OBJ_TYPE_RX_TX,
+} bnx2x_obj_type;
+
+/* Filtering states */
+enum {
+ BNX2X_FILTER_MAC_PENDING,
+ BNX2X_FILTER_VLAN_PENDING,
+ BNX2X_FILTER_VLAN_MAC_PENDING,
+ BNX2X_FILTER_RX_MODE_PENDING,
+ BNX2X_FILTER_RX_MODE_SCHED,
+ BNX2X_FILTER_ISCSI_ETH_START_SCHED,
+ BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
+ BNX2X_FILTER_FCOE_ETH_START_SCHED,
+ BNX2X_FILTER_FCOE_ETH_STOP_SCHED,
+ BNX2X_FILTER_MCAST_PENDING,
+ BNX2X_FILTER_MCAST_SCHED,
+ BNX2X_FILTER_RSS_CONF_PENDING,
+};
+
+struct bnx2x_raw_obj {
+ u8 func_id;
+
+ /* Queue params */
+ u8 cl_id;
+ u32 cid;
+
+ /* Ramrod data buffer params */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /* Ramrod state params */
+ int state; /* "ramrod is pending" state bit */
+ unsigned long *pstate; /* pointer to state buffer */
+
+ bnx2x_obj_type obj_type;
+
+ int (*wait_comp)(struct bnx2x *bp,
+ struct bnx2x_raw_obj *o);
+
+ bool (*check_pending)(struct bnx2x_raw_obj *o);
+ void (*clear_pending)(struct bnx2x_raw_obj *o);
+ void (*set_pending)(struct bnx2x_raw_obj *o);
+};
+
+/************************* VLAN-MAC commands related parameters ***************/
+struct bnx2x_mac_ramrod_data {
+ u8 mac[ETH_ALEN];
+};
+
+struct bnx2x_vlan_ramrod_data {
+ u16 vlan;
+};
+
+struct bnx2x_vlan_mac_ramrod_data {
+ u8 mac[ETH_ALEN];
+ u16 vlan;
+};
+
+union bnx2x_classification_ramrod_data {
+ struct bnx2x_mac_ramrod_data mac;
+ struct bnx2x_vlan_ramrod_data vlan;
+ struct bnx2x_vlan_mac_ramrod_data vlan_mac;
+};
+
+/* VLAN_MAC commands */
+enum bnx2x_vlan_mac_cmd {
+ BNX2X_VLAN_MAC_ADD,
+ BNX2X_VLAN_MAC_DEL,
+ BNX2X_VLAN_MAC_MOVE,
+};
+
+struct bnx2x_vlan_mac_data {
+ /* Requested command: BNX2X_VLAN_MAC_XX */
+ enum bnx2x_vlan_mac_cmd cmd;
+ /*
+ * used to contain the data related vlan_mac_flags bits from
+ * ramrod parameters.
+ */
+ unsigned long vlan_mac_flags;
+
+ /* Needed for MOVE command */
+ struct bnx2x_vlan_mac_obj *target_obj;
+
+ union bnx2x_classification_ramrod_data u;
+};
+
+/*************************** Exe Queue obj ************************************/
+union bnx2x_exe_queue_cmd_data {
+ struct bnx2x_vlan_mac_data vlan_mac;
+
+ struct {
+ /* TODO */
+ } mcast;
+};
+
+struct bnx2x_exeq_elem {
+ struct list_head link;
+
+ /* Length of this element in the exe_chunk. */
+ int cmd_len;
+
+ union bnx2x_exe_queue_cmd_data cmd_data;
+};
+
+union bnx2x_qable_obj;
+
+union bnx2x_exeq_comp_elem {
+ union event_ring_elem *elem;
+};
+
+struct bnx2x_exe_queue_obj;
+
+typedef int (*exe_q_validate)(struct bnx2x *bp,
+ union bnx2x_qable_obj *o,
+ struct bnx2x_exeq_elem *elem);
+
+/**
+ * @return positive is entry was optimized, 0 - if not, negative
+ * in case of an error.
+ */
+typedef int (*exe_q_optimize)(struct bnx2x *bp,
+ union bnx2x_qable_obj *o,
+ struct bnx2x_exeq_elem *elem);
+typedef int (*exe_q_execute)(struct bnx2x *bp,
+ union bnx2x_qable_obj *o,
+ struct list_head *exe_chunk,
+ unsigned long *ramrod_flags);
+typedef struct bnx2x_exeq_elem *
+ (*exe_q_get)(struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem);
+
+struct bnx2x_exe_queue_obj {
+ /*
+ * Commands pending for an execution.
+ */
+ struct list_head exe_queue;
+
+ /*
+ * Commands pending for an completion.
+ */
+ struct list_head pending_comp;
+
+ spinlock_t lock;
+
+ /* Maximum length of commands' list for one execution */
+ int exe_chunk_len;
+
+ union bnx2x_qable_obj *owner;
+
+ /****** Virtual functions ******/
+ /**
+ * Called before commands execution for commands that are really
+ * going to be executed (after 'optimize').
+ *
+ * Must run under exe_queue->lock
+ */
+ exe_q_validate validate;
+
+
+ /**
+ * This will try to cancel the current pending commands list
+ * considering the new command.
+ *
+ * Must run under exe_queue->lock
+ */
+ exe_q_optimize optimize;
+
+ /**
+ * Run the next commands chunk (owner specific).
+ */
+ exe_q_execute execute;
+
+ /**
+ * Return the exe_queue element containing the specific command
+ * if any. Otherwise return NULL.
+ */
+ exe_q_get get;
+};
+/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
+/*
+ * Element in the VLAN_MAC registry list having all currenty configured
+ * rules.
+ */
+struct bnx2x_vlan_mac_registry_elem {
+ struct list_head link;
+
+ /*
+ * Used to store the cam offset used for the mac/vlan/vlan-mac.
+ * Relevant for 57710 and 57711 only. VLANs and MACs share the
+ * same CAM for these chips.
+ */
+ int cam_offset;
+
+ /* Needed for DEL and RESTORE flows */
+ unsigned long vlan_mac_flags;
+
+ union bnx2x_classification_ramrod_data u;
+};
+
+/* Bits representing VLAN_MAC commands specific flags */
+enum {
+ BNX2X_UC_LIST_MAC,
+ BNX2X_ETH_MAC,
+ BNX2X_ISCSI_ETH_MAC,
+ BNX2X_NETQ_ETH_MAC,
+ BNX2X_DONT_CONSUME_CAM_CREDIT,
+ BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
+};
+
+struct bnx2x_vlan_mac_ramrod_params {
+ /* Object to run the command from */
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj;
+
+ /* General command flags: COMP_WAIT, etc. */
+ unsigned long ramrod_flags;
+
+ /* Command specific configuration request */
+ struct bnx2x_vlan_mac_data user_req;
+};
+
+struct bnx2x_vlan_mac_obj {
+ struct bnx2x_raw_obj raw;
+
+ /* Bookkeeping list: will prevent the addition of already existing
+ * entries.
+ */
+ struct list_head head;
+
+ /* TODO: Add it's initialization in the init functions */
+ struct bnx2x_exe_queue_obj exe_queue;
+
+ /* MACs credit pool */
+ struct bnx2x_credit_pool_obj *macs_pool;
+
+ /* VLANs credit pool */
+ struct bnx2x_credit_pool_obj *vlans_pool;
+
+ /* RAMROD command to be used */
+ int ramrod_cmd;
+
+ /**
+ * Checks if ADD-ramrod with the given params may be performed.
+ *
+ * @return zero if the element may be added
+ */
+
+ int (*check_add)(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data);
+
+ /**
+ * Checks if DEL-ramrod with the given params may be performed.
+ *
+ * @return true if the element may be deleted
+ */
+ struct bnx2x_vlan_mac_registry_elem *
+ (*check_del)(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data);
+
+ /**
+ * Checks if DEL-ramrod with the given params may be performed.
+ *
+ * @return true if the element may be deleted
+ */
+ bool (*check_move)(struct bnx2x_vlan_mac_obj *src_o,
+ struct bnx2x_vlan_mac_obj *dst_o,
+ union bnx2x_classification_ramrod_data *data);
+
+ /**
+ * Update the relevant credit object(s) (consume/return
+ * correspondingly).
+ */
+ bool (*get_credit)(struct bnx2x_vlan_mac_obj *o);
+ bool (*put_credit)(struct bnx2x_vlan_mac_obj *o);
+ bool (*get_cam_offset)(struct bnx2x_vlan_mac_obj *o, int *offset);
+ bool (*put_cam_offset)(struct bnx2x_vlan_mac_obj *o, int offset);
+
+ /**
+ * Configures one rule in the ramrod data buffer.
+ */
+ void (*set_one_rule)(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset);
+
+ /**
+ * Delete all configured elements having the given
+ * vlan_mac_flags specification. Assumes no pending for
+ * execution commands. Will schedule all all currently
+ * configured MACs/VLANs/VLAN-MACs matching the vlan_mac_flags
+ * specification for deletion and will use the given
+ * ramrod_flags for the last DEL operation.
+ *
+ * @param bp
+ * @param o
+ * @param ramrod_flags RAMROD_XX flags
+ *
+ * @return 0 if the last operation has completed successfully
+ * and there are no more elements left, positive value
+ * if there are pending for completion commands,
+ * negative value in case of failure.
+ */
+ int (*delete_all)(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ unsigned long *vlan_mac_flags,
+ unsigned long *ramrod_flags);
+
+ /**
+ * Reconfigures the next MAC/VLAN/VLAN-MAC element from the previously
+ * configured elements list.
+ *
+ * @param bp
+ * @param p Command parameters (RAMROD_COMP_WAIT bit in
+ * ramrod_flags is only taken into an account)
+ * @param ppos a pointer to the cooky that should be given back in the
+ * next call to make function handle the next element. If
+ * *ppos is set to NULL it will restart the iterator.
+ * If returned *ppos == NULL this means that the last
+ * element has been handled.
+ *
+ * @return int
+ */
+ int (*restore)(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p,
+ struct bnx2x_vlan_mac_registry_elem **ppos);
+
+ /**
+ * Should be called on a completion arival.
+ *
+ * @param bp
+ * @param o
+ * @param cqe Completion element we are handling
+ * @param ramrod_flags if RAMROD_CONT is set the next bulk of
+ * pending commands will be executed.
+ * RAMROD_DRV_CLR_ONLY and RAMROD_RESTORE
+ * may also be set if needed.
+ *
+ * @return 0 if there are neither pending nor waiting for
+ * completion commands. Positive value if there are
+ * pending for execution or for completion commands.
+ * Negative value in case of an error (including an
+ * error in the cqe).
+ */
+ int (*complete)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
+ union event_ring_elem *cqe,
+ unsigned long *ramrod_flags);
+
+ /**
+ * Wait for completion of all commands. Don't schedule new ones,
+ * just wait. It assumes that the completion code will schedule
+ * for new commands.
+ */
+ int (*wait)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o);
+};
+
+/** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
+
+/* RX_MODE ramrod spesial flags: set in rx_mode_flags field in
+ * a bnx2x_rx_mode_ramrod_params.
+ */
+enum {
+ BNX2X_RX_MODE_FCOE_ETH,
+ BNX2X_RX_MODE_ISCSI_ETH,
+};
+
+enum {
+ BNX2X_ACCEPT_UNICAST,
+ BNX2X_ACCEPT_MULTICAST,
+ BNX2X_ACCEPT_ALL_UNICAST,
+ BNX2X_ACCEPT_ALL_MULTICAST,
+ BNX2X_ACCEPT_BROADCAST,
+ BNX2X_ACCEPT_UNMATCHED,
+ BNX2X_ACCEPT_ANY_VLAN
+};
+
+struct bnx2x_rx_mode_ramrod_params {
+ struct bnx2x_rx_mode_obj *rx_mode_obj;
+ unsigned long *pstate;
+ int state;
+ u8 cl_id;
+ u32 cid;
+ u8 func_id;
+ unsigned long ramrod_flags;
+ unsigned long rx_mode_flags;
+
+ /*
+ * rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to
+ * a tstorm_eth_mac_filter_config (e1x).
+ */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /* Rx mode settings */
+ unsigned long rx_accept_flags;
+
+ /* internal switching settings */
+ unsigned long tx_accept_flags;
+};
+
+struct bnx2x_rx_mode_obj {
+ int (*config_rx_mode)(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p);
+
+ int (*wait_comp)(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p);
+};
+
+/********************** Set multicast group ***********************************/
+
+struct bnx2x_mcast_list_elem {
+ struct list_head link;
+ u8 *mac;
+};
+
+union bnx2x_mcast_config_data {
+ u8 *mac;
+ u8 bin; /* used in a RESTORE flow */
+};
+
+struct bnx2x_mcast_ramrod_params {
+ struct bnx2x_mcast_obj *mcast_obj;
+
+ /* Relevant options are RAMROD_COMP_WAIT and RAMROD_DRV_CLR_ONLY */
+ unsigned long ramrod_flags;
+
+ struct list_head mcast_list; /* list of struct bnx2x_mcast_list_elem */
+ /** TODO:
+ * - rename it to macs_num.
+ * - Add a new command type for handling pending commands
+ * (remove "zero semantics").
+ *
+ * Length of mcast_list. If zero and ADD_CONT command - post
+ * pending commands.
+ */
+ int mcast_list_len;
+};
+
+enum {
+ BNX2X_MCAST_CMD_ADD,
+ BNX2X_MCAST_CMD_CONT,
+ BNX2X_MCAST_CMD_DEL,
+ BNX2X_MCAST_CMD_RESTORE,
+};
+
+struct bnx2x_mcast_obj {
+ struct bnx2x_raw_obj raw;
+
+ union {
+ struct {
+ #define BNX2X_MCAST_BINS_NUM 256
+ #define BNX2X_MCAST_VEC_SZ (BNX2X_MCAST_BINS_NUM / 64)
+ u64 vec[BNX2X_MCAST_VEC_SZ];
+
+ /** Number of BINs to clear. Should be updated
+ * immediately when a command arrives in order to
+ * properly create DEL commands.
+ */
+ int num_bins_set;
+ } aprox_match;
+
+ struct {
+ struct list_head macs;
+ int num_macs_set;
+ } exact_match;
+ } registry;
+
+ /* Pending commands */
+ struct list_head pending_cmds_head;
+
+ /* A state that is set in raw.pstate, when there are pending commands */
+ int sched_state;
+
+ /* Maximal number of mcast MACs configured in one command */
+ int max_cmd_len;
+
+ /* Total number of currently pending MACs to configure: both
+ * in the pending commands list and in the current command.
+ */
+ int total_pending_num;
+
+ u8 engine_id;
+
+ /**
+ * @param cmd command to execute (BNX2X_MCAST_CMD_X, see above)
+ */
+ int (*config_mcast)(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+ /**
+ * Fills the ramrod data during the RESTORE flow.
+ *
+ * @param bp
+ * @param o
+ * @param start_idx Registry index to start from
+ * @param rdata_idx Index in the ramrod data to start from
+ *
+ * @return -1 if we handled the whole registry or index of the last
+ * handled registry element.
+ */
+ int (*hdl_restore)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
+ int start_bin, int *rdata_idx);
+
+ int (*enqueue_cmd)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+ void (*set_one_rule)(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, int idx,
+ union bnx2x_mcast_config_data *cfg_data, int cmd);
+
+ /** Checks if there are more mcast MACs to be set or a previous
+ * command is still pending.
+ */
+ bool (*check_pending)(struct bnx2x_mcast_obj *o);
+
+ /**
+ * Set/Clear/Check SCHEDULED state of the object
+ */
+ void (*set_sched)(struct bnx2x_mcast_obj *o);
+ void (*clear_sched)(struct bnx2x_mcast_obj *o);
+ bool (*check_sched)(struct bnx2x_mcast_obj *o);
+
+ /* Wait until all pending commands complete */
+ int (*wait_comp)(struct bnx2x *bp, struct bnx2x_mcast_obj *o);
+
+ /**
+ * Handle the internal object counters needed for proper
+ * commands handling. Checks that the provided parameters are
+ * feasible.
+ */
+ int (*validate)(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+ /**
+ * Restore the values of internal counters in case of a failure.
+ */
+ void (*revert)(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_bins);
+
+ int (*get_registry_size)(struct bnx2x_mcast_obj *o);
+ void (*set_registry_size)(struct bnx2x_mcast_obj *o, int n);
+};
+
+/*************************** Credit handling **********************************/
+struct bnx2x_credit_pool_obj {
+
+ /* Current amount of credit in the pool */
+ atomic_t credit;
+
+ /* Maximum allowed credit. put() will check against it. */
+ int pool_sz;
+
+ /*
+ * Allocate a pool table statically.
+ *
+ * Currently the mamimum allowed size is MAX_MAC_CREDIT_E2(272)
+ *
+ * The set bit in the table will mean that the entry is available.
+ */
+#define BNX2X_POOL_VEC_SIZE (MAX_MAC_CREDIT_E2 / 64)
+ u64 pool_mirror[BNX2X_POOL_VEC_SIZE];
+
+ /* Base pool offset (initialized differently */
+ int base_pool_offset;
+
+ /**
+ * Get the next free pool entry.
+ *
+ * @return true if there was a free entry in the pool
+ */
+ bool (*get_entry)(struct bnx2x_credit_pool_obj *o, int *entry);
+
+ /**
+ * Return the entry back to the pool.
+ *
+ * @return true if entry is legal and has been successfully
+ * returned to the pool.
+ */
+ bool (*put_entry)(struct bnx2x_credit_pool_obj *o, int entry);
+
+ /**
+ * Get the requested amount of credit from the pool.
+ *
+ * @param cnt Amount of requested credit
+ * @return true if the operation is successful
+ */
+ bool (*get)(struct bnx2x_credit_pool_obj *o, int cnt);
+
+ /**
+ * Returns the credit to the pool.
+ *
+ * @param cnt Amount of credit to return
+ * @return true if the operation is successful
+ */
+ bool (*put)(struct bnx2x_credit_pool_obj *o, int cnt);
+
+ /**
+ * Reads the current amount of credit.
+ */
+ int (*check)(struct bnx2x_credit_pool_obj *o);
+};
+
+/*************************** RSS configuration ********************************/
+enum {
+ /* RSS_MODE bits are mutually exclusive */
+ BNX2X_RSS_MODE_DISABLED,
+ BNX2X_RSS_MODE_REGULAR,
+ BNX2X_RSS_MODE_VLAN_PRI,
+ BNX2X_RSS_MODE_E1HOV_PRI,
+ BNX2X_RSS_MODE_IP_DSCP,
+
+ BNX2X_RSS_SET_SRCH, /* Setup searcher, E1x specific flag */
+
+ BNX2X_RSS_IPV4,
+ BNX2X_RSS_IPV4_TCP,
+ BNX2X_RSS_IPV6,
+ BNX2X_RSS_IPV6_TCP,
+};
+
+struct bnx2x_config_rss_params {
+ struct bnx2x_rss_config_obj *rss_obj;
+
+ /* may have RAMROD_COMP_WAIT set only */
+ unsigned long ramrod_flags;
+
+ /* BNX2X_RSS_X bits */
+ unsigned long rss_flags;
+
+ /* Number hash bits to take into an account */
+ u8 rss_result_mask;
+
+ /* Indirection table */
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
+
+ /* RSS hash values */
+ u32 rss_key[10];
+
+ /* valid only iff BNX2X_RSS_UPDATE_TOE is set */
+ u16 toe_rss_bitmap;
+};
+
+struct bnx2x_rss_config_obj {
+ struct bnx2x_raw_obj raw;
+
+ /* RSS engine to use */
+ u8 engine_id;
+
+ /* Last configured indirection table */
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
+
+ int (*config_rss)(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p);
+};
+
+/*********************** Queue state update ***********************************/
+
+/* UPDATE command options */
+enum {
+ BNX2X_Q_UPDATE_IN_VLAN_REM,
+ BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
+ BNX2X_Q_UPDATE_OUT_VLAN_REM,
+ BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
+ BNX2X_Q_UPDATE_ANTI_SPOOF,
+ BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG,
+ BNX2X_Q_UPDATE_ACTIVATE,
+ BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+ BNX2X_Q_UPDATE_DEF_VLAN_EN,
+ BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+ BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+ BNX2X_Q_UPDATE_SILENT_VLAN_REM
+};
+
+/* Allowed Queue states */
+enum bnx2x_q_state {
+ BNX2X_Q_STATE_RESET,
+ BNX2X_Q_STATE_INITIALIZED,
+ BNX2X_Q_STATE_ACTIVE,
+ BNX2X_Q_STATE_MULTI_COS,
+ BNX2X_Q_STATE_MCOS_TERMINATED,
+ BNX2X_Q_STATE_INACTIVE,
+ BNX2X_Q_STATE_STOPPED,
+ BNX2X_Q_STATE_TERMINATED,
+ BNX2X_Q_STATE_FLRED,
+ BNX2X_Q_STATE_MAX,
+};
+
+/* Allowed commands */
+enum bnx2x_queue_cmd {
+ BNX2X_Q_CMD_INIT,
+ BNX2X_Q_CMD_SETUP,
+ BNX2X_Q_CMD_SETUP_TX_ONLY,
+ BNX2X_Q_CMD_DEACTIVATE,
+ BNX2X_Q_CMD_ACTIVATE,
+ BNX2X_Q_CMD_UPDATE,
+ BNX2X_Q_CMD_UPDATE_TPA,
+ BNX2X_Q_CMD_HALT,
+ BNX2X_Q_CMD_CFC_DEL,
+ BNX2X_Q_CMD_TERMINATE,
+ BNX2X_Q_CMD_EMPTY,
+ BNX2X_Q_CMD_MAX,
+};
+
+/* queue SETUP + INIT flags */
+enum {
+ BNX2X_Q_FLG_TPA,
+ BNX2X_Q_FLG_TPA_IPV6,
+ BNX2X_Q_FLG_STATS,
+ BNX2X_Q_FLG_ZERO_STATS,
+ BNX2X_Q_FLG_ACTIVE,
+ BNX2X_Q_FLG_OV,
+ BNX2X_Q_FLG_VLAN,
+ BNX2X_Q_FLG_COS,
+ BNX2X_Q_FLG_HC,
+ BNX2X_Q_FLG_HC_EN,
+ BNX2X_Q_FLG_DHC,
+ BNX2X_Q_FLG_FCOE,
+ BNX2X_Q_FLG_LEADING_RSS,
+ BNX2X_Q_FLG_MCAST,
+ BNX2X_Q_FLG_DEF_VLAN,
+ BNX2X_Q_FLG_TX_SWITCH,
+ BNX2X_Q_FLG_TX_SEC,
+ BNX2X_Q_FLG_ANTI_SPOOF,
+ BNX2X_Q_FLG_SILENT_VLAN_REM
+};
+
+/* Queue type options: queue type may be a compination of below. */
+enum bnx2x_q_type {
+ /** TODO: Consider moving both these flags into the init()
+ * ramrod params.
+ */
+ BNX2X_Q_TYPE_HAS_RX,
+ BNX2X_Q_TYPE_HAS_TX,
+};
+
+#define BNX2X_PRIMARY_CID_INDEX 0
+#define BNX2X_MULTI_TX_COS_E1X 1
+#define BNX2X_MULTI_TX_COS_E2_E3A0 2
+#define BNX2X_MULTI_TX_COS_E3B0 3
+#define BNX2X_MULTI_TX_COS BNX2X_MULTI_TX_COS_E3B0
+
+
+struct bnx2x_queue_init_params {
+ struct {
+ unsigned long flags;
+ u16 hc_rate;
+ u8 fw_sb_id;
+ u8 sb_cq_index;
+ } tx;
+
+ struct {
+ unsigned long flags;
+ u16 hc_rate;
+ u8 fw_sb_id;
+ u8 sb_cq_index;
+ } rx;
+
+ /* CID context in the host memory */
+ struct eth_context *cxts[BNX2X_MULTI_TX_COS];
+
+ /* maximum number of cos supported by hardware */
+ u8 max_cos;
+};
+
+struct bnx2x_queue_terminate_params {
+ /* index within the tx_only cids of this queue object */
+ u8 cid_index;
+};
+
+struct bnx2x_queue_cfc_del_params {
+ /* index within the tx_only cids of this queue object */
+ u8 cid_index;
+};
+
+struct bnx2x_queue_update_params {
+ unsigned long update_flags; /* BNX2X_Q_UPDATE_XX bits */
+ u16 def_vlan;
+ u16 silent_removal_value;
+ u16 silent_removal_mask;
+/* index within the tx_only cids of this queue object */
+ u8 cid_index;
+};
+
+struct rxq_pause_params {
+ u16 bd_th_lo;
+ u16 bd_th_hi;
+ u16 rcq_th_lo;
+ u16 rcq_th_hi;
+ u16 sge_th_lo; /* valid iff BNX2X_Q_FLG_TPA */
+ u16 sge_th_hi; /* valid iff BNX2X_Q_FLG_TPA */
+ u16 pri_map;
+};
+
+/* general */
+struct bnx2x_general_setup_params {
+ /* valid iff BNX2X_Q_FLG_STATS */
+ u8 stat_id;
+
+ u8 spcl_id;
+ u16 mtu;
+ u8 cos;
+};
+
+struct bnx2x_rxq_setup_params {
+ /* dma */
+ dma_addr_t dscr_map;
+ dma_addr_t sge_map;
+ dma_addr_t rcq_map;
+ dma_addr_t rcq_np_map;
+
+ u16 drop_flags;
+ u16 buf_sz;
+ u8 fw_sb_id;
+ u8 cl_qzone_id;
+
+ /* valid iff BNX2X_Q_FLG_TPA */
+ u16 tpa_agg_sz;
+ u16 sge_buf_sz;
+ u8 max_sges_pkt;
+ u8 max_tpa_queues;
+ u8 rss_engine_id;
+
+ u8 cache_line_log;
+
+ u8 sb_cq_index;
+
+ /* valid iff BXN2X_Q_FLG_SILENT_VLAN_REM */
+ u16 silent_removal_value;
+ u16 silent_removal_mask;
+};
+
+struct bnx2x_txq_setup_params {
+ /* dma */
+ dma_addr_t dscr_map;
+
+ u8 fw_sb_id;
+ u8 sb_cq_index;
+ u8 cos; /* valid iff BNX2X_Q_FLG_COS */
+ u16 traffic_type;
+ /* equals to the leading rss client id, used for TX classification*/
+ u8 tss_leading_cl_id;
+
+ /* valid iff BNX2X_Q_FLG_DEF_VLAN */
+ u16 default_vlan;
+};
+
+struct bnx2x_queue_setup_params {
+ struct bnx2x_general_setup_params gen_params;
+ struct bnx2x_txq_setup_params txq_params;
+ struct bnx2x_rxq_setup_params rxq_params;
+ struct rxq_pause_params pause_params;
+ unsigned long flags;
+};
+
+struct bnx2x_queue_setup_tx_only_params {
+ struct bnx2x_general_setup_params gen_params;
+ struct bnx2x_txq_setup_params txq_params;
+ unsigned long flags;
+ /* index within the tx_only cids of this queue object */
+ u8 cid_index;
+};
+
+struct bnx2x_queue_state_params {
+ struct bnx2x_queue_sp_obj *q_obj;
+
+ /* Current command */
+ enum bnx2x_queue_cmd cmd;
+
+ /* may have RAMROD_COMP_WAIT set only */
+ unsigned long ramrod_flags;
+
+ /* Params according to the current command */
+ union {
+ struct bnx2x_queue_update_params update;
+ struct bnx2x_queue_setup_params setup;
+ struct bnx2x_queue_init_params init;
+ struct bnx2x_queue_setup_tx_only_params tx_only;
+ struct bnx2x_queue_terminate_params terminate;
+ struct bnx2x_queue_cfc_del_params cfc_del;
+ } params;
+};
+
+struct bnx2x_queue_sp_obj {
+ u32 cids[BNX2X_MULTI_TX_COS];
+ u8 cl_id;
+ u8 func_id;
+
+ /*
+ * number of traffic classes supported by queue.
+ * The primary connection of the queue suppotrs the first traffic
+ * class. Any further traffic class is suppoted by a tx-only
+ * connection.
+ *
+ * Therefore max_cos is also a number of valid entries in the cids
+ * array.
+ */
+ u8 max_cos;
+ u8 num_tx_only, next_tx_only;
+
+ enum bnx2x_q_state state, next_state;
+
+ /* bits from enum bnx2x_q_type */
+ unsigned long type;
+
+ /* BNX2X_Q_CMD_XX bits. This object implements "one
+ * pending" paradigm but for debug and tracing purposes it's
+ * more convinient to have different bits for different
+ * commands.
+ */
+ unsigned long pending;
+
+ /* Buffer to use as a ramrod data and its mapping */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /**
+ * Performs one state change according to the given parameters.
+ *
+ * @return 0 in case of success and negative value otherwise.
+ */
+ int (*send_cmd)(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params);
+
+ /**
+ * Sets the pending bit according to the requested transition.
+ */
+ int (*set_pending)(struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_queue_state_params *params);
+
+ /**
+ * Checks that the requested state transition is legal.
+ */
+ int (*check_transition)(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_queue_state_params *params);
+
+ /**
+ * Completes the pending command.
+ */
+ int (*complete_cmd)(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd);
+
+ int (*wait_comp)(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd cmd);
+};
+
+/********************** Function state update *********************************/
+/* Allowed Function states */
+enum bnx2x_func_state {
+ BNX2X_F_STATE_RESET,
+ BNX2X_F_STATE_INITIALIZED,
+ BNX2X_F_STATE_STARTED,
+ BNX2X_F_STATE_TX_STOPPED,
+ BNX2X_F_STATE_MAX,
+};
+
+/* Allowed Function commands */
+enum bnx2x_func_cmd {
+ BNX2X_F_CMD_HW_INIT,
+ BNX2X_F_CMD_START,
+ BNX2X_F_CMD_STOP,
+ BNX2X_F_CMD_HW_RESET,
+ BNX2X_F_CMD_TX_STOP,
+ BNX2X_F_CMD_TX_START,
+ BNX2X_F_CMD_MAX,
+};
+
+struct bnx2x_func_hw_init_params {
+ /* A load phase returned by MCP.
+ *
+ * May be:
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
+ * FW_MSG_CODE_DRV_LOAD_COMMON
+ * FW_MSG_CODE_DRV_LOAD_PORT
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION
+ */
+ u32 load_phase;
+};
+
+struct bnx2x_func_hw_reset_params {
+ /* A load phase returned by MCP.
+ *
+ * May be:
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
+ * FW_MSG_CODE_DRV_LOAD_COMMON
+ * FW_MSG_CODE_DRV_LOAD_PORT
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION
+ */
+ u32 reset_phase;
+};
+
+struct bnx2x_func_start_params {
+ /* Multi Function mode:
+ * - Single Function
+ * - Switch Dependent
+ * - Switch Independent
+ */
+ u16 mf_mode;
+
+ /* Switch Dependent mode outer VLAN tag */
+ u16 sd_vlan_tag;
+
+ /* Function cos mode */
+ u8 network_cos_mode;
+};
+
+struct bnx2x_func_tx_start_params {
+ struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
+ u8 dcb_enabled;
+ u8 dcb_version;
+ u8 dont_add_pri_0_en;
+};
+
+struct bnx2x_func_state_params {
+ struct bnx2x_func_sp_obj *f_obj;
+
+ /* Current command */
+ enum bnx2x_func_cmd cmd;
+
+ /* may have RAMROD_COMP_WAIT set only */
+ unsigned long ramrod_flags;
+
+ /* Params according to the current command */
+ union {
+ struct bnx2x_func_hw_init_params hw_init;
+ struct bnx2x_func_hw_reset_params hw_reset;
+ struct bnx2x_func_start_params start;
+ struct bnx2x_func_tx_start_params tx_start;
+ } params;
+};
+
+struct bnx2x_func_sp_drv_ops {
+ /* Init tool + runtime initialization:
+ * - Common Chip
+ * - Common (per Path)
+ * - Port
+ * - Function phases
+ */
+ int (*init_hw_cmn_chip)(struct bnx2x *bp);
+ int (*init_hw_cmn)(struct bnx2x *bp);
+ int (*init_hw_port)(struct bnx2x *bp);
+ int (*init_hw_func)(struct bnx2x *bp);
+
+ /* Reset Function HW: Common, Port, Function phases. */
+ void (*reset_hw_cmn)(struct bnx2x *bp);
+ void (*reset_hw_port)(struct bnx2x *bp);
+ void (*reset_hw_func)(struct bnx2x *bp);
+
+ /* Init/Free GUNZIP resources */
+ int (*gunzip_init)(struct bnx2x *bp);
+ void (*gunzip_end)(struct bnx2x *bp);
+
+ /* Prepare/Release FW resources */
+ int (*init_fw)(struct bnx2x *bp);
+ void (*release_fw)(struct bnx2x *bp);
+};
+
+struct bnx2x_func_sp_obj {
+ enum bnx2x_func_state state, next_state;
+
+ /* BNX2X_FUNC_CMD_XX bits. This object implements "one
+ * pending" paradigm but for debug and tracing purposes it's
+ * more convinient to have different bits for different
+ * commands.
+ */
+ unsigned long pending;
+
+ /* Buffer to use as a ramrod data and its mapping */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /* this mutex validates that when pending flag is taken, the next
+ * ramrod to be sent will be the one set the pending bit
+ */
+ struct mutex one_pending_mutex;
+
+ /* Driver interface */
+ struct bnx2x_func_sp_drv_ops *drv;
+
+ /**
+ * Performs one state change according to the given parameters.
+ *
+ * @return 0 in case of success and negative value otherwise.
+ */
+ int (*send_cmd)(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params);
+
+ /**
+ * Checks that the requested state transition is legal.
+ */
+ int (*check_transition)(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ struct bnx2x_func_state_params *params);
+
+ /**
+ * Completes the pending command.
+ */
+ int (*complete_cmd)(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd);
+
+ int (*wait_comp)(struct bnx2x *bp, struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd);
+};
+
+/********************** Interfaces ********************************************/
+/* Queueable objects set */
+union bnx2x_qable_obj {
+ struct bnx2x_vlan_mac_obj vlan_mac;
+};
+/************** Function state update *********/
+void bnx2x_init_func_obj(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *obj,
+ void *rdata, dma_addr_t rdata_mapping,
+ struct bnx2x_func_sp_drv_ops *drv_iface);
+
+int bnx2x_func_state_change(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params);
+
+enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o);
+/******************* Queue State **************/
+void bnx2x_init_queue_obj(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids,
+ u8 cid_cnt, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, unsigned long type);
+
+int bnx2x_queue_state_change(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params);
+
+/********************* VLAN-MAC ****************/
+void bnx2x_init_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool);
+
+void bnx2x_init_vlan_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *vlans_pool);
+
+void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool,
+ struct bnx2x_credit_pool_obj *vlans_pool);
+
+int bnx2x_config_vlan_mac(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p);
+
+int bnx2x_vlan_mac_move(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p,
+ struct bnx2x_vlan_mac_obj *dest_o);
+
+/********************* RX MODE ****************/
+
+void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
+ struct bnx2x_rx_mode_obj *o);
+
+/**
+ * Send and RX_MODE ramrod according to the provided parameters.
+ *
+ * @param bp
+ * @param p Command parameters
+ *
+ * @return 0 - if operation was successfull and there is no pending completions,
+ * positive number - if there are pending completions,
+ * negative - if there were errors
+ */
+int bnx2x_config_rx_mode(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p);
+
+/****************** MULTICASTS ****************/
+
+void bnx2x_init_mcast_obj(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *mcast_obj,
+ u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
+ u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate,
+ bnx2x_obj_type type);
+
+/**
+ * Configure multicast MACs list. May configure a new list
+ * provided in p->mcast_list (BNX2X_MCAST_CMD_ADD), clean up
+ * (BNX2X_MCAST_CMD_DEL) or restore (BNX2X_MCAST_CMD_RESTORE) a current
+ * configuration, continue to execute the pending commands
+ * (BNX2X_MCAST_CMD_CONT).
+ *
+ * If previous command is still pending or if number of MACs to
+ * configure is more that maximum number of MACs in one command,
+ * the current command will be enqueued to the tail of the
+ * pending commands list.
+ *
+ * @param bp
+ * @param p
+ * @param command to execute: BNX2X_MCAST_CMD_X
+ *
+ * @return 0 is operation was sucessfull and there are no pending completions,
+ * negative if there were errors, positive if there are pending
+ * completions.
+ */
+int bnx2x_config_mcast(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+/****************** CREDIT POOL ****************/
+void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p, u8 func_id,
+ u8 func_num);
+void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p, u8 func_id,
+ u8 func_num);
+
+
+/****************** RSS CONFIGURATION ****************/
+void bnx2x_init_rss_config_obj(struct bnx2x *bp,
+ struct bnx2x_rss_config_obj *rss_obj,
+ u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
+ void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate,
+ bnx2x_obj_type type);
+
+/**
+ * Updates RSS configuration according to provided parameters.
+ *
+ * @param bp
+ * @param p
+ *
+ * @return 0 in case of success
+ */
+int bnx2x_config_rss(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p);
+
+/**
+ * Return the current ind_table configuration.
+ *
+ * @param bp
+ * @param ind_table buffer to fill with the current indirection
+ * table content. Should be at least
+ * T_ETH_INDIRECTION_TABLE_SIZE bytes long.
+ */
+void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
+ u8 *ind_table);
+
+#endif /* BNX2X_SP_VERBS */
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c
index e535bfa08945..771f6803b238 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/bnx2x/bnx2x_stats.c
@@ -14,120 +14,11 @@
* Statistics and Link management by Yitchak Gertner
*
*/
-#include "bnx2x_cmn.h"
#include "bnx2x_stats.h"
+#include "bnx2x_cmn.h"
-/* Statistics */
-/****************************************************************************
-* Macros
-****************************************************************************/
-
-/* sum[hi:lo] += add[hi:lo] */
-#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
- do { \
- s_lo += a_lo; \
- s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
- } while (0)
-
-/* difference = minuend - subtrahend */
-#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
- do { \
- if (m_lo < s_lo) { \
- /* underflow */ \
- d_hi = m_hi - s_hi; \
- if (d_hi > 0) { \
- /* we can 'loan' 1 */ \
- d_hi--; \
- d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
- } else { \
- /* m_hi <= s_hi */ \
- d_hi = 0; \
- d_lo = 0; \
- } \
- } else { \
- /* m_lo >= s_lo */ \
- if (m_hi < s_hi) { \
- d_hi = 0; \
- d_lo = 0; \
- } else { \
- /* m_hi >= s_hi */ \
- d_hi = m_hi - s_hi; \
- d_lo = m_lo - s_lo; \
- } \
- } \
- } while (0)
-
-#define UPDATE_STAT64(s, t) \
- do { \
- DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \
- diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \
- pstats->mac_stx[0].t##_hi = new->s##_hi; \
- pstats->mac_stx[0].t##_lo = new->s##_lo; \
- ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \
- pstats->mac_stx[1].t##_lo, diff.lo); \
- } while (0)
-
-#define UPDATE_STAT64_NIG(s, t) \
- do { \
- DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \
- diff.lo, new->s##_lo, old->s##_lo); \
- ADD_64(estats->t##_hi, diff.hi, \
- estats->t##_lo, diff.lo); \
- } while (0)
-
-/* sum[hi:lo] += add */
-#define ADD_EXTEND_64(s_hi, s_lo, a) \
- do { \
- s_lo += a; \
- s_hi += (s_lo < a) ? 1 : 0; \
- } while (0)
-
-#define UPDATE_EXTEND_STAT(s) \
- do { \
- ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \
- pstats->mac_stx[1].s##_lo, \
- new->s); \
- } while (0)
-
-#define UPDATE_EXTEND_TSTAT(s, t) \
- do { \
- diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \
- old_tclient->s = tclient->s; \
- ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
-
-#define UPDATE_EXTEND_USTAT(s, t) \
- do { \
- diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
- old_uclient->s = uclient->s; \
- ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
-
-#define UPDATE_EXTEND_XSTAT(s, t) \
- do { \
- diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \
- old_xclient->s = xclient->s; \
- ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
-
-/* minuend -= subtrahend */
-#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
- do { \
- DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \
- } while (0)
-
-/* minuend[hi:lo] -= subtrahend */
-#define SUB_EXTEND_64(m_hi, m_lo, s) \
- do { \
- SUB_64(m_hi, 0, m_lo, s); \
- } while (0)
-
-#define SUB_EXTEND_USTAT(s, t) \
- do { \
- diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
- SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
+/* Statistics */
/*
* General service functions
@@ -149,12 +40,16 @@ static inline long bnx2x_hilo(u32 *hiref)
* Init service functions
*/
-
+/* Post the next statistics ramrod. Protect it with the spin in
+ * order to ensure the strict order between statistics ramrods
+ * (each ramrod has a sequence number passed in a
+ * bp->fw_stats_req->hdr.drv_stats_counter and ramrods must be
+ * sent in order).
+ */
static void bnx2x_storm_stats_post(struct bnx2x *bp)
{
if (!bp->stats_pending) {
- struct common_query_ramrod_data ramrod_data = {0};
- int i, rc;
+ int rc;
spin_lock_bh(&bp->stats_lock);
@@ -163,14 +58,19 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
return;
}
- ramrod_data.drv_counter = bp->stats_counter++;
- ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
- for_each_eth_queue(bp, i)
- ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id);
+ bp->fw_stats_req->hdr.drv_stats_counter =
+ cpu_to_le16(bp->stats_counter++);
+ DP(NETIF_MSG_TIMER, "Sending statistics ramrod %d\n",
+ bp->fw_stats_req->hdr.drv_stats_counter);
+
+
+
+ /* send FW stats ramrod */
rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
- ((u32 *)&ramrod_data)[1],
- ((u32 *)&ramrod_data)[0], 1);
+ U64_HI(bp->fw_stats_req_mapping),
+ U64_LO(bp->fw_stats_req_mapping),
+ NONE_CONNECTION_TYPE);
if (rc == 0)
bp->stats_pending = 1;
@@ -230,7 +130,7 @@ static int bnx2x_stats_comp(struct bnx2x *bp)
break;
}
cnt--;
- msleep(1);
+ usleep_range(1000, 1000);
}
return 1;
}
@@ -338,69 +238,8 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
true, DMAE_COMP_GRC);
- if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
-
- mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM :
- NIG_REG_INGRESS_BMAC0_MEM);
-
- /* BIGMAC_REGISTER_TX_STAT_GTPKT ..
- BIGMAC_REGISTER_TX_STAT_GTBYT */
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
- if (CHIP_IS_E1x(bp)) {
- dmae->src_addr_lo = (mac_addr +
- BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
- dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
- BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
- } else {
- dmae->src_addr_lo = (mac_addr +
- BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
- dmae->len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
- BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
- }
-
- dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
-
- /* BIGMAC_REGISTER_RX_STAT_GR64 ..
- BIGMAC_REGISTER_RX_STAT_GRIPJ */
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
- dmae->src_addr_hi = 0;
- if (CHIP_IS_E1x(bp)) {
- dmae->src_addr_lo = (mac_addr +
- BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
- dmae->dst_addr_lo =
- U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac1_stats, rx_stat_gr64_lo));
- dmae->dst_addr_hi =
- U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac1_stats, rx_stat_gr64_lo));
- dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
- BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
- } else {
- dmae->src_addr_lo =
- (mac_addr + BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
- dmae->dst_addr_lo =
- U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac2_stats, rx_stat_gr64_lo));
- dmae->dst_addr_hi =
- U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac2_stats, rx_stat_gr64_lo));
- dmae->len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
- BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
- }
-
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
-
- } else if (bp->link_vars.mac_type == MAC_TYPE_EMAC) {
-
+ /* EMAC is special */
+ if (bp->link_vars.mac_type == MAC_TYPE_EMAC) {
mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0);
/* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/
@@ -445,46 +284,122 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
dmae->comp_addr_hi = 0;
dmae->comp_val = 1;
+ } else {
+ u32 tx_src_addr_lo, rx_src_addr_lo;
+ u16 rx_len, tx_len;
+
+ /* configure the params according to MAC type */
+ switch (bp->link_vars.mac_type) {
+ case MAC_TYPE_BMAC:
+ mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM :
+ NIG_REG_INGRESS_BMAC0_MEM);
+
+ /* BIGMAC_REGISTER_TX_STAT_GTPKT ..
+ BIGMAC_REGISTER_TX_STAT_GTBYT */
+ if (CHIP_IS_E1x(bp)) {
+ tx_src_addr_lo = (mac_addr +
+ BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+ tx_len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
+ BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+ rx_src_addr_lo = (mac_addr +
+ BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+ rx_len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
+ BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+ } else {
+ tx_src_addr_lo = (mac_addr +
+ BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+ tx_len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
+ BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+ rx_src_addr_lo = (mac_addr +
+ BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+ rx_len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
+ BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+ }
+ break;
+
+ case MAC_TYPE_UMAC: /* handled by MSTAT */
+ case MAC_TYPE_XMAC: /* handled by MSTAT */
+ default:
+ mac_addr = port ? GRCBASE_MSTAT1 : GRCBASE_MSTAT0;
+ tx_src_addr_lo = (mac_addr +
+ MSTAT_REG_TX_STAT_GTXPOK_LO) >> 2;
+ rx_src_addr_lo = (mac_addr +
+ MSTAT_REG_RX_STAT_GR64_LO) >> 2;
+ tx_len = sizeof(bp->slowpath->
+ mac_stats.mstat_stats.stats_tx) >> 2;
+ rx_len = sizeof(bp->slowpath->
+ mac_stats.mstat_stats.stats_rx) >> 2;
+ break;
+ }
+
+ /* TX stats */
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_lo = tx_src_addr_lo;
+ dmae->src_addr_hi = 0;
+ dmae->len = tx_len;
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
+
+ /* RX stats */
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_hi = 0;
+ dmae->src_addr_lo = rx_src_addr_lo;
+ dmae->dst_addr_lo =
+ U64_LO(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
+ dmae->dst_addr_hi =
+ U64_HI(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
+ dmae->len = rx_len;
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
}
/* NIG */
+ if (!CHIP_IS_E3(bp)) {
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
+ NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
+ dmae->src_addr_hi = 0;
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt0_lo));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt0_lo));
+ dmae->len = (2*sizeof(u32)) >> 2;
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
+
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
+ NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
+ dmae->src_addr_hi = 0;
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt1_lo));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt1_lo));
+ dmae->len = (2*sizeof(u32)) >> 2;
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
+ }
+
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
+ dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+ true, DMAE_COMP_PCI);
dmae->src_addr_lo = (port ? NIG_REG_STAT1_BRB_DISCARD :
NIG_REG_STAT0_BRB_DISCARD) >> 2;
dmae->src_addr_hi = 0;
dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats));
dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats));
dmae->len = (sizeof(struct nig_stats) - 4*sizeof(u32)) >> 2;
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
- dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
- NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
- dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt0_lo));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt0_lo));
- dmae->len = (2*sizeof(u32)) >> 2;
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
-
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
- true, DMAE_COMP_PCI);
- dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
- NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
- dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt1_lo));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt1_lo));
- dmae->len = (2*sizeof(u32)) >> 2;
dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
dmae->comp_val = DMAE_COMP_VAL;
@@ -566,7 +481,8 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
- UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
+
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
@@ -580,13 +496,13 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
tx_stat_etherstatspkts512octetsto1023octets);
UPDATE_STAT64(tx_stat_gt1518,
tx_stat_etherstatspkts1024octetsto1522octets);
- UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
- UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
- UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
- UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+ UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
+ UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
+ UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
+ UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
UPDATE_STAT64(tx_stat_gterr,
tx_stat_dot3statsinternalmactransmiterrors);
- UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+ UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
} else {
struct bmac2_stats *new = bnx2x_sp(bp, mac_stats.bmac2_stats);
@@ -600,7 +516,7 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
- UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
@@ -614,19 +530,96 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
tx_stat_etherstatspkts512octetsto1023octets);
UPDATE_STAT64(tx_stat_gt1518,
tx_stat_etherstatspkts1024octetsto1522octets);
- UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
- UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
- UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
- UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+ UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
+ UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
+ UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
+ UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
UPDATE_STAT64(tx_stat_gterr,
tx_stat_dot3statsinternalmactransmiterrors);
- UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+ UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
}
estats->pause_frames_received_hi =
- pstats->mac_stx[1].rx_stat_bmac_xpf_hi;
+ pstats->mac_stx[1].rx_stat_mac_xpf_hi;
estats->pause_frames_received_lo =
- pstats->mac_stx[1].rx_stat_bmac_xpf_lo;
+ pstats->mac_stx[1].rx_stat_mac_xpf_lo;
+
+ estats->pause_frames_sent_hi =
+ pstats->mac_stx[1].tx_stat_outxoffsent_hi;
+ estats->pause_frames_sent_lo =
+ pstats->mac_stx[1].tx_stat_outxoffsent_lo;
+}
+
+static void bnx2x_mstat_stats_update(struct bnx2x *bp)
+{
+ struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
+ struct bnx2x_eth_stats *estats = &bp->eth_stats;
+
+ struct mstat_stats *new = bnx2x_sp(bp, mac_stats.mstat_stats);
+
+ ADD_STAT64(stats_rx.rx_grerb, rx_stat_ifhcinbadoctets);
+ ADD_STAT64(stats_rx.rx_grfcs, rx_stat_dot3statsfcserrors);
+ ADD_STAT64(stats_rx.rx_grund, rx_stat_etherstatsundersizepkts);
+ ADD_STAT64(stats_rx.rx_grovr, rx_stat_dot3statsframestoolong);
+ ADD_STAT64(stats_rx.rx_grfrg, rx_stat_etherstatsfragments);
+ ADD_STAT64(stats_rx.rx_grxcf, rx_stat_maccontrolframesreceived);
+ ADD_STAT64(stats_rx.rx_grxpf, rx_stat_xoffstateentered);
+ ADD_STAT64(stats_rx.rx_grxpf, rx_stat_mac_xpf);
+ ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_outxoffsent);
+ ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_flowcontroldone);
+
+
+ ADD_STAT64(stats_tx.tx_gt64, tx_stat_etherstatspkts64octets);
+ ADD_STAT64(stats_tx.tx_gt127,
+ tx_stat_etherstatspkts65octetsto127octets);
+ ADD_STAT64(stats_tx.tx_gt255,
+ tx_stat_etherstatspkts128octetsto255octets);
+ ADD_STAT64(stats_tx.tx_gt511,
+ tx_stat_etherstatspkts256octetsto511octets);
+ ADD_STAT64(stats_tx.tx_gt1023,
+ tx_stat_etherstatspkts512octetsto1023octets);
+ ADD_STAT64(stats_tx.tx_gt1518,
+ tx_stat_etherstatspkts1024octetsto1522octets);
+ ADD_STAT64(stats_tx.tx_gt2047, tx_stat_mac_2047);
+
+ ADD_STAT64(stats_tx.tx_gt4095, tx_stat_mac_4095);
+ ADD_STAT64(stats_tx.tx_gt9216, tx_stat_mac_9216);
+ ADD_STAT64(stats_tx.tx_gt16383, tx_stat_mac_16383);
+
+ ADD_STAT64(stats_tx.tx_gterr,
+ tx_stat_dot3statsinternalmactransmiterrors);
+ ADD_STAT64(stats_tx.tx_gtufl, tx_stat_mac_ufl);
+
+ ADD_64(estats->etherstatspkts1024octetsto1522octets_hi,
+ new->stats_tx.tx_gt1518_hi,
+ estats->etherstatspkts1024octetsto1522octets_lo,
+ new->stats_tx.tx_gt1518_lo);
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt2047_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt2047_lo);
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt4095_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt4095_lo);
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt9216_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt9216_lo);
+
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt16383_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt16383_lo);
+
+ estats->pause_frames_received_hi =
+ pstats->mac_stx[1].rx_stat_mac_xpf_hi;
+ estats->pause_frames_received_lo =
+ pstats->mac_stx[1].rx_stat_mac_xpf_lo;
estats->pause_frames_sent_hi =
pstats->mac_stx[1].tx_stat_outxoffsent_hi;
@@ -702,15 +695,26 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp)
u32 hi;
} diff;
- if (bp->link_vars.mac_type == MAC_TYPE_BMAC)
+ switch (bp->link_vars.mac_type) {
+ case MAC_TYPE_BMAC:
bnx2x_bmac_stats_update(bp);
+ break;
- else if (bp->link_vars.mac_type == MAC_TYPE_EMAC)
+ case MAC_TYPE_EMAC:
bnx2x_emac_stats_update(bp);
+ break;
+
+ case MAC_TYPE_UMAC:
+ case MAC_TYPE_XMAC:
+ bnx2x_mstat_stats_update(bp);
+ break;
- else { /* unreached */
+ case MAC_TYPE_NONE: /* unreached */
BNX2X_ERR("stats updated by DMAE but no MAC active\n");
return -1;
+
+ default: /* unreached */
+ BNX2X_ERR("Unknown MAC type\n");
}
ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo,
@@ -718,9 +722,12 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp)
ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo,
new->brb_truncate - old->brb_truncate);
- UPDATE_STAT64_NIG(egress_mac_pkt0,
+ if (!CHIP_IS_E3(bp)) {
+ UPDATE_STAT64_NIG(egress_mac_pkt0,
etherstatspkts1024octetsto1522octets);
- UPDATE_STAT64_NIG(egress_mac_pkt1, etherstatspktsover1522octets);
+ UPDATE_STAT64_NIG(egress_mac_pkt1,
+ etherstatspktsover1522octets);
+ }
memcpy(old, new, sizeof(struct nig_stats));
@@ -746,11 +753,13 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp)
static int bnx2x_storm_stats_update(struct bnx2x *bp)
{
- struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
struct tstorm_per_port_stats *tport =
- &stats->tstorm_common.port_statistics;
+ &bp->fw_stats_data->port.tstorm_port_statistics;
+ struct tstorm_per_pf_stats *tfunc =
+ &bp->fw_stats_data->pf.tstorm_pf_statistics;
struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
struct bnx2x_eth_stats *estats = &bp->eth_stats;
+ struct stats_counter *counters = &bp->fw_stats_data->storm_counters;
int i;
u16 cur_stats_counter;
@@ -761,6 +770,35 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
cur_stats_counter = bp->stats_counter - 1;
spin_unlock_bh(&bp->stats_lock);
+ /* are storm stats valid? */
+ if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by xstorm"
+ " xstorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->xstats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
+ if (le16_to_cpu(counters->ustats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by ustorm"
+ " ustorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->ustats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
+ if (le16_to_cpu(counters->cstats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by cstorm"
+ " cstorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->cstats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
+ if (le16_to_cpu(counters->tstats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by tstorm"
+ " tstorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->tstats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
memcpy(&(fstats->total_bytes_received_hi),
&(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
sizeof(struct host_func_stats) - 2*sizeof(u32));
@@ -770,94 +808,84 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
estats->etherstatsoverrsizepkts_lo = 0;
estats->no_buff_discard_hi = 0;
estats->no_buff_discard_lo = 0;
+ estats->total_tpa_aggregations_hi = 0;
+ estats->total_tpa_aggregations_lo = 0;
+ estats->total_tpa_aggregated_frames_hi = 0;
+ estats->total_tpa_aggregated_frames_lo = 0;
+ estats->total_tpa_bytes_hi = 0;
+ estats->total_tpa_bytes_lo = 0;
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- int cl_id = fp->cl_id;
- struct tstorm_per_client_stats *tclient =
- &stats->tstorm_common.client_statistics[cl_id];
- struct tstorm_per_client_stats *old_tclient = &fp->old_tclient;
- struct ustorm_per_client_stats *uclient =
- &stats->ustorm_common.client_statistics[cl_id];
- struct ustorm_per_client_stats *old_uclient = &fp->old_uclient;
- struct xstorm_per_client_stats *xclient =
- &stats->xstorm_common.client_statistics[cl_id];
- struct xstorm_per_client_stats *old_xclient = &fp->old_xclient;
+ struct tstorm_per_queue_stats *tclient =
+ &bp->fw_stats_data->queue_stats[i].
+ tstorm_queue_statistics;
+ struct tstorm_per_queue_stats *old_tclient = &fp->old_tclient;
+ struct ustorm_per_queue_stats *uclient =
+ &bp->fw_stats_data->queue_stats[i].
+ ustorm_queue_statistics;
+ struct ustorm_per_queue_stats *old_uclient = &fp->old_uclient;
+ struct xstorm_per_queue_stats *xclient =
+ &bp->fw_stats_data->queue_stats[i].
+ xstorm_queue_statistics;
+ struct xstorm_per_queue_stats *old_xclient = &fp->old_xclient;
struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
u32 diff;
- /* are storm stats valid? */
- if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) {
- DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"
- " xstorm counter (0x%x) != stats_counter (0x%x)\n",
- i, xclient->stats_counter, cur_stats_counter + 1);
- return -1;
- }
- if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) {
- DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"
- " tstorm counter (0x%x) != stats_counter (0x%x)\n",
- i, tclient->stats_counter, cur_stats_counter + 1);
- return -2;
- }
- if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) {
- DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"
- " ustorm counter (0x%x) != stats_counter (0x%x)\n",
- i, uclient->stats_counter, cur_stats_counter + 1);
- return -4;
- }
+ DP(BNX2X_MSG_STATS, "queue[%d]: ucast_sent 0x%x, "
+ "bcast_sent 0x%x mcast_sent 0x%x\n",
+ i, xclient->ucast_pkts_sent,
+ xclient->bcast_pkts_sent, xclient->mcast_pkts_sent);
+
+ DP(BNX2X_MSG_STATS, "---------------\n");
+
+ qstats->total_broadcast_bytes_received_hi =
+ le32_to_cpu(tclient->rcv_bcast_bytes.hi);
+ qstats->total_broadcast_bytes_received_lo =
+ le32_to_cpu(tclient->rcv_bcast_bytes.lo);
+ qstats->total_multicast_bytes_received_hi =
+ le32_to_cpu(tclient->rcv_mcast_bytes.hi);
+ qstats->total_multicast_bytes_received_lo =
+ le32_to_cpu(tclient->rcv_mcast_bytes.lo);
+
+ qstats->total_unicast_bytes_received_hi =
+ le32_to_cpu(tclient->rcv_ucast_bytes.hi);
+ qstats->total_unicast_bytes_received_lo =
+ le32_to_cpu(tclient->rcv_ucast_bytes.lo);
+
+ /*
+ * sum to total_bytes_received all
+ * unicast/multicast/broadcast
+ */
qstats->total_bytes_received_hi =
- le32_to_cpu(tclient->rcv_broadcast_bytes.hi);
+ qstats->total_broadcast_bytes_received_hi;
qstats->total_bytes_received_lo =
- le32_to_cpu(tclient->rcv_broadcast_bytes.lo);
+ qstats->total_broadcast_bytes_received_lo;
ADD_64(qstats->total_bytes_received_hi,
- le32_to_cpu(tclient->rcv_multicast_bytes.hi),
+ qstats->total_multicast_bytes_received_hi,
qstats->total_bytes_received_lo,
- le32_to_cpu(tclient->rcv_multicast_bytes.lo));
+ qstats->total_multicast_bytes_received_lo);
ADD_64(qstats->total_bytes_received_hi,
- le32_to_cpu(tclient->rcv_unicast_bytes.hi),
+ qstats->total_unicast_bytes_received_hi,
qstats->total_bytes_received_lo,
- le32_to_cpu(tclient->rcv_unicast_bytes.lo));
-
- SUB_64(qstats->total_bytes_received_hi,
- le32_to_cpu(uclient->bcast_no_buff_bytes.hi),
- qstats->total_bytes_received_lo,
- le32_to_cpu(uclient->bcast_no_buff_bytes.lo));
-
- SUB_64(qstats->total_bytes_received_hi,
- le32_to_cpu(uclient->mcast_no_buff_bytes.hi),
- qstats->total_bytes_received_lo,
- le32_to_cpu(uclient->mcast_no_buff_bytes.lo));
-
- SUB_64(qstats->total_bytes_received_hi,
- le32_to_cpu(uclient->ucast_no_buff_bytes.hi),
- qstats->total_bytes_received_lo,
- le32_to_cpu(uclient->ucast_no_buff_bytes.lo));
+ qstats->total_unicast_bytes_received_lo);
qstats->valid_bytes_received_hi =
qstats->total_bytes_received_hi;
qstats->valid_bytes_received_lo =
qstats->total_bytes_received_lo;
- qstats->error_bytes_received_hi =
- le32_to_cpu(tclient->rcv_error_bytes.hi);
- qstats->error_bytes_received_lo =
- le32_to_cpu(tclient->rcv_error_bytes.lo);
-
- ADD_64(qstats->total_bytes_received_hi,
- qstats->error_bytes_received_hi,
- qstats->total_bytes_received_lo,
- qstats->error_bytes_received_lo);
- UPDATE_EXTEND_TSTAT(rcv_unicast_pkts,
+ UPDATE_EXTEND_TSTAT(rcv_ucast_pkts,
total_unicast_packets_received);
- UPDATE_EXTEND_TSTAT(rcv_multicast_pkts,
+ UPDATE_EXTEND_TSTAT(rcv_mcast_pkts,
total_multicast_packets_received);
- UPDATE_EXTEND_TSTAT(rcv_broadcast_pkts,
+ UPDATE_EXTEND_TSTAT(rcv_bcast_pkts,
total_broadcast_packets_received);
- UPDATE_EXTEND_TSTAT(packets_too_big_discard,
+ UPDATE_EXTEND_TSTAT(pkts_too_big_discard,
etherstatsoverrsizepkts);
UPDATE_EXTEND_TSTAT(no_buff_discard, no_buff_discard);
@@ -871,30 +899,78 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
UPDATE_EXTEND_USTAT(mcast_no_buff_pkts, no_buff_discard);
UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard);
+ qstats->total_broadcast_bytes_transmitted_hi =
+ le32_to_cpu(xclient->bcast_bytes_sent.hi);
+ qstats->total_broadcast_bytes_transmitted_lo =
+ le32_to_cpu(xclient->bcast_bytes_sent.lo);
+
+ qstats->total_multicast_bytes_transmitted_hi =
+ le32_to_cpu(xclient->mcast_bytes_sent.hi);
+ qstats->total_multicast_bytes_transmitted_lo =
+ le32_to_cpu(xclient->mcast_bytes_sent.lo);
+
+ qstats->total_unicast_bytes_transmitted_hi =
+ le32_to_cpu(xclient->ucast_bytes_sent.hi);
+ qstats->total_unicast_bytes_transmitted_lo =
+ le32_to_cpu(xclient->ucast_bytes_sent.lo);
+ /*
+ * sum to total_bytes_transmitted all
+ * unicast/multicast/broadcast
+ */
qstats->total_bytes_transmitted_hi =
- le32_to_cpu(xclient->unicast_bytes_sent.hi);
+ qstats->total_unicast_bytes_transmitted_hi;
qstats->total_bytes_transmitted_lo =
- le32_to_cpu(xclient->unicast_bytes_sent.lo);
+ qstats->total_unicast_bytes_transmitted_lo;
ADD_64(qstats->total_bytes_transmitted_hi,
- le32_to_cpu(xclient->multicast_bytes_sent.hi),
+ qstats->total_broadcast_bytes_transmitted_hi,
qstats->total_bytes_transmitted_lo,
- le32_to_cpu(xclient->multicast_bytes_sent.lo));
+ qstats->total_broadcast_bytes_transmitted_lo);
ADD_64(qstats->total_bytes_transmitted_hi,
- le32_to_cpu(xclient->broadcast_bytes_sent.hi),
+ qstats->total_multicast_bytes_transmitted_hi,
qstats->total_bytes_transmitted_lo,
- le32_to_cpu(xclient->broadcast_bytes_sent.lo));
+ qstats->total_multicast_bytes_transmitted_lo);
- UPDATE_EXTEND_XSTAT(unicast_pkts_sent,
+ UPDATE_EXTEND_XSTAT(ucast_pkts_sent,
total_unicast_packets_transmitted);
- UPDATE_EXTEND_XSTAT(multicast_pkts_sent,
+ UPDATE_EXTEND_XSTAT(mcast_pkts_sent,
total_multicast_packets_transmitted);
- UPDATE_EXTEND_XSTAT(broadcast_pkts_sent,
+ UPDATE_EXTEND_XSTAT(bcast_pkts_sent,
total_broadcast_packets_transmitted);
- old_tclient->checksum_discard = tclient->checksum_discard;
- old_tclient->ttl0_discard = tclient->ttl0_discard;
+ UPDATE_EXTEND_TSTAT(checksum_discard,
+ total_packets_received_checksum_discarded);
+ UPDATE_EXTEND_TSTAT(ttl0_discard,
+ total_packets_received_ttl0_discarded);
+
+ UPDATE_EXTEND_XSTAT(error_drop_pkts,
+ total_transmitted_dropped_packets_error);
+
+ /* TPA aggregations completed */
+ UPDATE_EXTEND_USTAT(coalesced_events, total_tpa_aggregations);
+ /* Number of network frames aggregated by TPA */
+ UPDATE_EXTEND_USTAT(coalesced_pkts,
+ total_tpa_aggregated_frames);
+ /* Total number of bytes in completed TPA aggregations */
+ qstats->total_tpa_bytes_lo =
+ le32_to_cpu(uclient->coalesced_bytes.lo);
+ qstats->total_tpa_bytes_hi =
+ le32_to_cpu(uclient->coalesced_bytes.hi);
+
+ /* TPA stats per-function */
+ ADD_64(estats->total_tpa_aggregations_hi,
+ qstats->total_tpa_aggregations_hi,
+ estats->total_tpa_aggregations_lo,
+ qstats->total_tpa_aggregations_lo);
+ ADD_64(estats->total_tpa_aggregated_frames_hi,
+ qstats->total_tpa_aggregated_frames_hi,
+ estats->total_tpa_aggregated_frames_lo,
+ qstats->total_tpa_aggregated_frames_lo);
+ ADD_64(estats->total_tpa_bytes_hi,
+ qstats->total_tpa_bytes_hi,
+ estats->total_tpa_bytes_lo,
+ qstats->total_tpa_bytes_lo);
ADD_64(fstats->total_bytes_received_hi,
qstats->total_bytes_received_hi,
@@ -933,10 +1009,6 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
fstats->valid_bytes_received_lo,
qstats->valid_bytes_received_lo);
- ADD_64(estats->error_bytes_received_hi,
- qstats->error_bytes_received_hi,
- estats->error_bytes_received_lo,
- qstats->error_bytes_received_lo);
ADD_64(estats->etherstatsoverrsizepkts_hi,
qstats->etherstatsoverrsizepkts_hi,
estats->etherstatsoverrsizepkts_lo,
@@ -950,9 +1022,19 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
fstats->total_bytes_received_lo,
estats->rx_stat_ifhcinbadoctets_lo);
+ ADD_64(fstats->total_bytes_received_hi,
+ tfunc->rcv_error_bytes.hi,
+ fstats->total_bytes_received_lo,
+ tfunc->rcv_error_bytes.lo);
+
memcpy(estats, &(fstats->total_bytes_received_hi),
sizeof(struct host_func_stats) - 2*sizeof(u32));
+ ADD_64(estats->error_bytes_received_hi,
+ tfunc->rcv_error_bytes.hi,
+ estats->error_bytes_received_lo,
+ tfunc->rcv_error_bytes.lo);
+
ADD_64(estats->etherstatsoverrsizepkts_hi,
estats->rx_stat_dot3statsframestoolong_hi,
estats->etherstatsoverrsizepkts_lo,
@@ -965,8 +1047,8 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
if (bp->port.pmf) {
estats->mac_filter_discard =
le32_to_cpu(tport->mac_filter_discard);
- estats->xxoverflow_discard =
- le32_to_cpu(tport->xxoverflow_discard);
+ estats->mf_tag_discard =
+ le32_to_cpu(tport->mf_tag_discard);
estats->brb_truncate_discard =
le32_to_cpu(tport->brb_truncate_discard);
estats->mac_discard = le32_to_cpu(tport->mac_discard);
@@ -1023,7 +1105,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp)
nstats->rx_frame_errors =
bnx2x_hilo(&estats->rx_stat_dot3statsalignmenterrors_hi);
nstats->rx_fifo_errors = bnx2x_hilo(&estats->no_buff_discard_hi);
- nstats->rx_missed_errors = estats->xxoverflow_discard;
+ nstats->rx_missed_errors = 0;
nstats->rx_errors = nstats->rx_length_errors +
nstats->rx_over_errors +
@@ -1065,10 +1147,27 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp)
}
}
+static bool bnx2x_edebug_stats_stopped(struct bnx2x *bp)
+{
+ u32 val;
+
+ if (SHMEM2_HAS(bp, edebug_driver_if[1])) {
+ val = SHMEM2_RD(bp, edebug_driver_if[1]);
+
+ if (val == EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT)
+ return true;
+ }
+
+ return false;
+}
+
static void bnx2x_stats_update(struct bnx2x *bp)
{
u32 *stats_comp = bnx2x_sp(bp, stats_comp);
+ if (bnx2x_edebug_stats_stopped(bp))
+ return;
+
if (*stats_comp != DMAE_COMP_VAL)
return;
@@ -1086,10 +1185,9 @@ static void bnx2x_stats_update(struct bnx2x *bp)
if (netif_msg_timer(bp)) {
struct bnx2x_eth_stats *estats = &bp->eth_stats;
- int i;
+ int i, cos;
- printk(KERN_DEBUG "%s: brb drops %u brb truncate %u\n",
- bp->dev->name,
+ netdev_dbg(bp->dev, "brb drops %u brb truncate %u\n",
estats->brb_drop_lo, estats->brb_truncate_lo);
for_each_eth_queue(bp, i) {
@@ -1108,20 +1206,32 @@ static void bnx2x_stats_update(struct bnx2x *bp)
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
+ struct bnx2x_fp_txdata *txdata;
struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
- struct netdev_queue *txq =
- netdev_get_tx_queue(bp->dev, i);
-
- printk(KERN_DEBUG "%s: tx avail(%4u) *tx_cons_sb(%u)"
- " tx pkt(%lu) tx calls (%lu)"
- " %s (Xoff events %u)\n",
- fp->name, bnx2x_tx_avail(fp),
- le16_to_cpu(*fp->tx_cons_sb),
- bnx2x_hilo(&qstats->
- total_unicast_packets_transmitted_hi),
- fp->tx_pkt,
- (netif_tx_queue_stopped(txq) ? "Xoff" : "Xon"),
- qstats->driver_xoff);
+ 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);
+
+ 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")
+ );
+ }
}
}
@@ -1149,6 +1259,7 @@ static void bnx2x_port_stats_stop(struct bnx2x *bp)
else
dmae->opcode = bnx2x_dmae_opcode_add_comp(
opcode, DMAE_COMP_PCI);
+
dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
dmae->dst_addr_lo = bp->port.port_stx >> 2;
@@ -1235,13 +1346,9 @@ static const struct {
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
{
enum bnx2x_stats_state state;
-
if (unlikely(bp->panic))
return;
-
bnx2x_stats_stm[bp->stats_state][event].action(bp);
-
- /* Protect a state change flow */
spin_lock_bh(&bp->stats_lock);
state = bp->stats_state;
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
@@ -1297,7 +1404,7 @@ static void bnx2x_func_stats_base_init(struct bnx2x *bp)
func_stx = bp->func_stx;
for (vn = VN_0; vn < vn_max; vn++) {
- int mb_idx = !CHIP_IS_E2(bp) ? 2*vn + BP_PORT(bp) : vn;
+ int mb_idx = CHIP_IS_E1x(bp) ? 2*vn + BP_PORT(bp) : vn;
bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
bnx2x_func_stats_init(bp);
@@ -1339,12 +1446,97 @@ static void bnx2x_func_stats_base_update(struct bnx2x *bp)
bnx2x_stats_comp(bp);
}
+/**
+ * This function will prepare the statistics ramrod data the way
+ * we will only have to increment the statistics counter and
+ * send the ramrod each time we have to.
+ *
+ * @param bp
+ */
+static inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp)
+{
+ int i;
+ struct stats_query_header *stats_hdr = &bp->fw_stats_req->hdr;
+
+ dma_addr_t cur_data_offset;
+ struct stats_query_entry *cur_query_entry;
+
+ stats_hdr->cmd_num = bp->fw_stats_num;
+ stats_hdr->drv_stats_counter = 0;
+
+ /* storm_counters struct contains the counters of completed
+ * statistics requests per storm which are incremented by FW
+ * each time it completes hadning a statistics ramrod. We will
+ * check these counters in the timer handler and discard a
+ * (statistics) ramrod completion.
+ */
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, storm_counters);
+
+ stats_hdr->stats_counters_addrs.hi =
+ cpu_to_le32(U64_HI(cur_data_offset));
+ stats_hdr->stats_counters_addrs.lo =
+ cpu_to_le32(U64_LO(cur_data_offset));
+
+ /* prepare to the first stats ramrod (will be completed with
+ * the counters equal to zero) - init counters to somethig different.
+ */
+ memset(&bp->fw_stats_data->storm_counters, 0xff,
+ sizeof(struct stats_counter));
+
+ /**** Port FW statistics data ****/
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, port);
+
+ cur_query_entry = &bp->fw_stats_req->query[BNX2X_PORT_QUERY_IDX];
+
+ cur_query_entry->kind = STATS_TYPE_PORT;
+ /* For port query index is a DONT CARE */
+ cur_query_entry->index = BP_PORT(bp);
+ /* For port query funcID is a DONT CARE */
+ cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+ cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
+ cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
+
+ /**** PF FW statistics data ****/
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, pf);
+
+ cur_query_entry = &bp->fw_stats_req->query[BNX2X_PF_QUERY_IDX];
+
+ cur_query_entry->kind = STATS_TYPE_PF;
+ /* For PF query index is a DONT CARE */
+ cur_query_entry->index = BP_PORT(bp);
+ cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+ cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
+ cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
+
+ /**** Clients' queries ****/
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, queue_stats);
+
+ for_each_eth_queue(bp, i) {
+ cur_query_entry =
+ &bp->fw_stats_req->
+ query[BNX2X_FIRST_QUEUE_QUERY_IDX + i];
+
+ cur_query_entry->kind = STATS_TYPE_QUEUE;
+ cur_query_entry->index = bnx2x_stats_id(&bp->fp[i]);
+ cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+ cur_query_entry->address.hi =
+ cpu_to_le32(U64_HI(cur_data_offset));
+ cur_query_entry->address.lo =
+ cpu_to_le32(U64_LO(cur_data_offset));
+
+ cur_data_offset += sizeof(struct per_queue_stats);
+ }
+}
+
void bnx2x_stats_init(struct bnx2x *bp)
{
- int port = BP_PORT(bp);
+ int /*abs*/port = BP_PORT(bp);
int mb_idx = BP_FW_MB_IDX(bp);
int i;
- struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
bp->stats_pending = 0;
bp->executer_idx = 0;
@@ -1362,45 +1554,35 @@ void bnx2x_stats_init(struct bnx2x *bp)
DP(BNX2X_MSG_STATS, "port_stx 0x%x func_stx 0x%x\n",
bp->port.port_stx, bp->func_stx);
+ port = BP_PORT(bp);
/* port stats */
memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
bp->port.old_nig_stats.brb_discard =
REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
bp->port.old_nig_stats.brb_truncate =
REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
- REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
- &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
- REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
- &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
+ if (!CHIP_IS_E3(bp)) {
+ REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
+ &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
+ REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
+ &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
+ }
/* function stats */
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- memset(&fp->old_tclient, 0,
- sizeof(struct tstorm_per_client_stats));
- memset(&fp->old_uclient, 0,
- sizeof(struct ustorm_per_client_stats));
- memset(&fp->old_xclient, 0,
- sizeof(struct xstorm_per_client_stats));
- memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
+ memset(&fp->old_tclient, 0, sizeof(fp->old_tclient));
+ memset(&fp->old_uclient, 0, sizeof(fp->old_uclient));
+ memset(&fp->old_xclient, 0, sizeof(fp->old_xclient));
+ memset(&fp->eth_q_stats, 0, sizeof(fp->eth_q_stats));
}
- /* FW stats are currently collected for ETH clients only */
- for_each_eth_queue(bp, i) {
- /* Set initial stats counter in the stats ramrod data to -1 */
- int cl_id = bp->fp[i].cl_id;
-
- stats->xstorm_common.client_statistics[cl_id].
- stats_counter = 0xffff;
- stats->ustorm_common.client_statistics[cl_id].
- stats_counter = 0xffff;
- stats->tstorm_common.client_statistics[cl_id].
- stats_counter = 0xffff;
- }
+ /* Prepare statistics ramrod data */
+ bnx2x_prep_fw_stats_req(bp);
- memset(&bp->dev->stats, 0, sizeof(struct net_device_stats));
- memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats));
+ memset(&bp->dev->stats, 0, sizeof(bp->dev->stats));
+ memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
bp->stats_state = STATS_STATE_DISABLED;
diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/bnx2x/bnx2x_stats.h
index 45d14d8bc1aa..5d8ce2f6afef 100644
--- a/drivers/net/bnx2x/bnx2x_stats.h
+++ b/drivers/net/bnx2x/bnx2x_stats.h
@@ -14,48 +14,11 @@
* Statistics and Link management by Yitchak Gertner
*
*/
-
#ifndef BNX2X_STATS_H
#define BNX2X_STATS_H
#include <linux/types.h>
-struct bnx2x_eth_q_stats {
- u32 total_bytes_received_hi;
- u32 total_bytes_received_lo;
- u32 total_bytes_transmitted_hi;
- u32 total_bytes_transmitted_lo;
- u32 total_unicast_packets_received_hi;
- u32 total_unicast_packets_received_lo;
- u32 total_multicast_packets_received_hi;
- u32 total_multicast_packets_received_lo;
- u32 total_broadcast_packets_received_hi;
- u32 total_broadcast_packets_received_lo;
- u32 total_unicast_packets_transmitted_hi;
- u32 total_unicast_packets_transmitted_lo;
- u32 total_multicast_packets_transmitted_hi;
- u32 total_multicast_packets_transmitted_lo;
- u32 total_broadcast_packets_transmitted_hi;
- u32 total_broadcast_packets_transmitted_lo;
- u32 valid_bytes_received_hi;
- u32 valid_bytes_received_lo;
-
- u32 error_bytes_received_hi;
- u32 error_bytes_received_lo;
- u32 etherstatsoverrsizepkts_hi;
- u32 etherstatsoverrsizepkts_lo;
- u32 no_buff_discard_hi;
- u32 no_buff_discard_lo;
-
- u32 driver_xoff;
- u32 rx_err_discard_pkt;
- u32 rx_skb_alloc_failed;
- u32 hw_csum_err;
-};
-
-#define Q_STATS_OFFSET32(stat_name) \
- (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
-
struct nig_stats {
u32 brb_discard;
u32 brb_packet;
@@ -212,7 +175,7 @@ struct bnx2x_eth_stats {
u32 brb_truncate_lo;
u32 mac_filter_discard;
- u32 xxoverflow_discard;
+ u32 mf_tag_discard;
u32 brb_truncate_discard;
u32 mac_discard;
@@ -222,16 +185,197 @@ struct bnx2x_eth_stats {
u32 hw_csum_err;
u32 nig_timer_max;
+
+ /* TPA */
+ u32 total_tpa_aggregations_hi;
+ u32 total_tpa_aggregations_lo;
+ u32 total_tpa_aggregated_frames_hi;
+ u32 total_tpa_aggregated_frames_lo;
+ u32 total_tpa_bytes_hi;
+ u32 total_tpa_bytes_lo;
+};
+
+
+struct bnx2x_eth_q_stats {
+ u32 total_unicast_bytes_received_hi;
+ u32 total_unicast_bytes_received_lo;
+ u32 total_broadcast_bytes_received_hi;
+ u32 total_broadcast_bytes_received_lo;
+ u32 total_multicast_bytes_received_hi;
+ u32 total_multicast_bytes_received_lo;
+ u32 total_bytes_received_hi;
+ u32 total_bytes_received_lo;
+ u32 total_unicast_bytes_transmitted_hi;
+ u32 total_unicast_bytes_transmitted_lo;
+ u32 total_broadcast_bytes_transmitted_hi;
+ u32 total_broadcast_bytes_transmitted_lo;
+ u32 total_multicast_bytes_transmitted_hi;
+ u32 total_multicast_bytes_transmitted_lo;
+ u32 total_bytes_transmitted_hi;
+ u32 total_bytes_transmitted_lo;
+ u32 total_unicast_packets_received_hi;
+ u32 total_unicast_packets_received_lo;
+ u32 total_multicast_packets_received_hi;
+ u32 total_multicast_packets_received_lo;
+ u32 total_broadcast_packets_received_hi;
+ u32 total_broadcast_packets_received_lo;
+ u32 total_unicast_packets_transmitted_hi;
+ u32 total_unicast_packets_transmitted_lo;
+ u32 total_multicast_packets_transmitted_hi;
+ u32 total_multicast_packets_transmitted_lo;
+ u32 total_broadcast_packets_transmitted_hi;
+ u32 total_broadcast_packets_transmitted_lo;
+ u32 valid_bytes_received_hi;
+ u32 valid_bytes_received_lo;
+
+ u32 etherstatsoverrsizepkts_hi;
+ u32 etherstatsoverrsizepkts_lo;
+ u32 no_buff_discard_hi;
+ u32 no_buff_discard_lo;
+
+ u32 driver_xoff;
+ u32 rx_err_discard_pkt;
+ u32 rx_skb_alloc_failed;
+ u32 hw_csum_err;
+
+ u32 total_packets_received_checksum_discarded_hi;
+ u32 total_packets_received_checksum_discarded_lo;
+ u32 total_packets_received_ttl0_discarded_hi;
+ u32 total_packets_received_ttl0_discarded_lo;
+ u32 total_transmitted_dropped_packets_error_hi;
+ u32 total_transmitted_dropped_packets_error_lo;
+
+ /* TPA */
+ u32 total_tpa_aggregations_hi;
+ u32 total_tpa_aggregations_lo;
+ u32 total_tpa_aggregated_frames_hi;
+ u32 total_tpa_aggregated_frames_lo;
+ u32 total_tpa_bytes_hi;
+ u32 total_tpa_bytes_lo;
};
-#define STATS_OFFSET32(stat_name) \
- (offsetof(struct bnx2x_eth_stats, stat_name) / 4)
+/****************************************************************************
+* Macros
+****************************************************************************/
+
+/* sum[hi:lo] += add[hi:lo] */
+#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
+ do { \
+ s_lo += a_lo; \
+ s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
+ } while (0)
+
+/* difference = minuend - subtrahend */
+#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
+ do { \
+ if (m_lo < s_lo) { \
+ /* underflow */ \
+ d_hi = m_hi - s_hi; \
+ if (d_hi > 0) { \
+ /* we can 'loan' 1 */ \
+ d_hi--; \
+ d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
+ } else { \
+ /* m_hi <= s_hi */ \
+ d_hi = 0; \
+ d_lo = 0; \
+ } \
+ } else { \
+ /* m_lo >= s_lo */ \
+ if (m_hi < s_hi) { \
+ d_hi = 0; \
+ d_lo = 0; \
+ } else { \
+ /* m_hi >= s_hi */ \
+ d_hi = m_hi - s_hi; \
+ d_lo = m_lo - s_lo; \
+ } \
+ } \
+ } while (0)
+
+#define UPDATE_STAT64(s, t) \
+ do { \
+ DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \
+ diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \
+ pstats->mac_stx[0].t##_hi = new->s##_hi; \
+ pstats->mac_stx[0].t##_lo = new->s##_lo; \
+ ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \
+ pstats->mac_stx[1].t##_lo, diff.lo); \
+ } while (0)
+
+#define UPDATE_STAT64_NIG(s, t) \
+ do { \
+ DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \
+ diff.lo, new->s##_lo, old->s##_lo); \
+ ADD_64(estats->t##_hi, diff.hi, \
+ estats->t##_lo, diff.lo); \
+ } while (0)
+
+/* sum[hi:lo] += add */
+#define ADD_EXTEND_64(s_hi, s_lo, a) \
+ do { \
+ s_lo += a; \
+ s_hi += (s_lo < a) ? 1 : 0; \
+ } while (0)
+
+#define ADD_STAT64(diff, t) \
+ do { \
+ ADD_64(pstats->mac_stx[1].t##_hi, new->diff##_hi, \
+ pstats->mac_stx[1].t##_lo, new->diff##_lo); \
+ } while (0)
+
+#define UPDATE_EXTEND_STAT(s) \
+ do { \
+ ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \
+ pstats->mac_stx[1].s##_lo, \
+ new->s); \
+ } while (0)
+
+#define UPDATE_EXTEND_TSTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \
+ old_tclient->s = tclient->s; \
+ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+#define UPDATE_EXTEND_USTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
+ old_uclient->s = uclient->s; \
+ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+#define UPDATE_EXTEND_XSTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \
+ old_xclient->s = xclient->s; \
+ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+/* minuend -= subtrahend */
+#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
+ do { \
+ DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \
+ } while (0)
+
+/* minuend[hi:lo] -= subtrahend */
+#define SUB_EXTEND_64(m_hi, m_lo, s) \
+ do { \
+ SUB_64(m_hi, 0, m_lo, s); \
+ } while (0)
+
+#define SUB_EXTEND_USTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
+ SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
-/* Forward declaration */
+/* forward */
struct bnx2x;
void bnx2x_stats_init(struct bnx2x *bp);
-extern const u32 dmae_reg_go_c[];
+void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
#endif /* BNX2X_STATS_H */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c7537abca4f2..a047eb973e3b 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -262,7 +262,7 @@ static inline u32 __get_agg_selection_mode(struct port *port)
if (bond == NULL)
return BOND_AD_STABLE;
- return BOND_AD_INFO(bond).agg_select_mode;
+ return bond->params.ad_select;
}
/**
@@ -1859,7 +1859,6 @@ static void ad_marker_response_received(struct bond_marker *marker,
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
{
BOND_AD_INFO(bond).agg_select_timer = timeout;
- BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select;
}
static u16 aggregator_identifier;
@@ -1868,11 +1867,10 @@ static u16 aggregator_identifier;
* bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
* @bond: bonding struct to work on
* @tick_resolution: tick duration (millisecond resolution)
- * @lacp_fast: boolean. whether fast periodic should be used
*
* Can be called only after the mac address of the bond is set.
*/
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
{
// check that the bond is not initialized yet
if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
@@ -1880,7 +1878,6 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas
aggregator_identifier = 0;
- BOND_AD_INFO(bond).lacp_fast = lacp_fast;
BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
@@ -1918,7 +1915,7 @@ int bond_3ad_bind_slave(struct slave *slave)
// port initialization
port = &(SLAVE_AD_INFO(slave).port);
- ad_initialize_port(port, BOND_AD_INFO(bond).lacp_fast);
+ ad_initialize_port(port, bond->params.lacp_fast);
port->slave = slave;
port->actor_port_number = SLAVE_AD_INFO(slave).id;
@@ -2345,8 +2342,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
*/
int bond_3ad_set_carrier(struct bonding *bond)
{
- if (__get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator))) {
- if (!netif_carrier_ok(bond->dev)) {
+ struct aggregator *active;
+
+ active = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
+ if (active) {
+ /* are enough slaves available to consider link up? */
+ if (active->num_of_ports < bond->params.min_links) {
+ if (netif_carrier_ok(bond->dev)) {
+ netif_carrier_off(bond->dev);
+ return 1;
+ }
+ } else if (!netif_carrier_ok(bond->dev)) {
netif_carrier_on(bond->dev);
return 1;
}
@@ -2473,3 +2479,34 @@ void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
read_unlock(&bond->lock);
}
+
+/*
+ * When modify lacp_rate parameter via sysfs,
+ * update actor_oper_port_state of each port.
+ *
+ * Hold slave->state_machine_lock,
+ * so we can modify port->actor_oper_port_state,
+ * no matter bond is up or down.
+ */
+void bond_3ad_update_lacp_rate(struct bonding *bond)
+{
+ int i;
+ struct slave *slave;
+ struct port *port = NULL;
+ int lacp_fast;
+
+ read_lock(&bond->lock);
+ lacp_fast = bond->params.lacp_fast;
+
+ bond_for_each_slave(bond, slave, i) {
+ port = &(SLAVE_AD_INFO(slave).port);
+ __get_state_machine_lock(port);
+ if (lacp_fast)
+ port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
+ else
+ port->actor_oper_port_state &= ~AD_STATE_LACP_TIMEOUT;
+ __release_state_machine_lock(port);
+ }
+
+ read_unlock(&bond->lock);
+}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 0ee3f1632c46..235b2cc58b28 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -253,11 +253,6 @@ struct ad_system {
struct ad_bond_info {
struct ad_system system; /* 802.3ad system structure */
u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes
- u32 agg_select_mode; // Mode of selection of active aggregator(bandwidth/count)
- int lacp_fast; /* whether fast periodic tx should be
- * requested
- */
- struct timer_list ad_timer;
};
struct ad_slave_info {
@@ -269,7 +264,7 @@ struct ad_slave_info {
};
// ================= AD Exported functions to the main bonding code ==================
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
@@ -282,5 +277,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond);
+void bond_3ad_update_lacp_rate(struct bonding *bond);
#endif //__BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 2df9276720a0..7f8b20a34ee3 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -635,7 +635,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
client_info->ntt = 0;
}
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
if (!vlan_get_tag(skb, &client_info->vlan_id))
client_info->tag = 1;
}
@@ -847,7 +847,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
skb->priority = TC_PRIO_CONTROL;
skb->dev = slave->dev;
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
struct vlan_entry *vlan;
vlan = bond_next_vlan(bond,
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
index 84fbd4ebd778..027a0ee7d85b 100644
--- a/drivers/net/bonding/bond_ipv6.c
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -183,10 +183,10 @@ static int bond_inet6addr_event(struct notifier_block *this,
}
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- if (!bond->vlgrp)
- continue;
- vlan_dev = vlan_group_get_device(bond->vlgrp,
- vlan->vlan_id);
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
+ rcu_read_unlock();
if (vlan_dev == event_dev) {
switch (event) {
case NETDEV_UP:
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 63c22b0bb5ad..02842d05c11f 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -98,6 +98,7 @@ static char *mode;
static char *primary;
static char *primary_reselect;
static char *lacp_rate;
+static int min_links;
static char *ad_select;
static char *xmit_hash_policy;
static int arp_interval = BOND_LINK_ARP_INTERV;
@@ -150,6 +151,9 @@ module_param(ad_select, charp, 0);
MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic; "
"0 for stable (default), 1 for bandwidth, "
"2 for count");
+module_param(min_links, int, 0);
+MODULE_PARM_DESC(min_links, "Minimum number of available links before turning on carrier");
+
module_param(xmit_hash_policy, charp, 0);
MODULE_PARM_DESC(xmit_hash_policy, "balance-xor and 802.3ad hashing method; "
"0 for layer 2 (default), 1 for layer 3+4, "
@@ -329,16 +333,6 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
kfree(vlan);
- if (list_empty(&bond->vlan_list) &&
- (bond->slave_cnt == 0)) {
- /* Last VLAN removed and no slaves, so
- * restore block on adding VLANs. This will
- * be removed once new slaves that are not
- * VLAN challenged will be added.
- */
- bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
- }
-
res = 0;
goto out;
}
@@ -414,9 +408,8 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
}
/*
- * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid
- * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a
- * lock because:
+ * In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid,
+ * We don't protect the slave list iteration with a lock because:
* a. This operation is performed in IOCTL context,
* b. The operation is protected by the RTNL semaphore in the 8021q code,
* c. Holding a lock with BH disabled while directly calling a base driver
@@ -432,33 +425,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
*/
/**
- * bond_vlan_rx_register - Propagates registration to slaves
- * @bond_dev: bonding net device that got called
- * @grp: vlan group being registered
- */
-static void bond_vlan_rx_register(struct net_device *bond_dev,
- struct vlan_group *grp)
-{
- struct bonding *bond = netdev_priv(bond_dev);
- struct slave *slave;
- int i;
-
- write_lock_bh(&bond->lock);
- bond->vlgrp = grp;
- write_unlock_bh(&bond->lock);
-
- bond_for_each_slave(bond, slave, i) {
- struct net_device *slave_dev = slave->dev;
- const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-
- if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_ops->ndo_vlan_rx_register) {
- slave_ops->ndo_vlan_rx_register(slave_dev, grp);
- }
- }
-}
-
-/**
* bond_vlan_rx_add_vid - Propagates adding an id to slaves
* @bond_dev: bonding net device that got called
* @vid: vlan id being added
@@ -495,7 +461,6 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
- struct net_device *vlan_dev;
int i, res;
bond_for_each_slave(bond, slave, i) {
@@ -504,12 +469,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
slave_ops->ndo_vlan_rx_kill_vid) {
- /* Save and then restore vlan_dev in the grp array,
- * since the slave's driver might clear it.
- */
- vlan_dev = vlan_group_get_device(bond->vlgrp, vid);
slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid);
- vlan_group_set_device(bond->vlgrp, vid, vlan_dev);
}
}
@@ -525,13 +485,6 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla
struct vlan_entry *vlan;
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
- if (!bond->vlgrp)
- return;
-
- if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_ops->ndo_vlan_rx_register)
- slave_ops->ndo_vlan_rx_register(slave_dev, bond->vlgrp);
-
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
!(slave_ops->ndo_vlan_rx_add_vid))
return;
@@ -545,30 +498,16 @@ static void bond_del_vlans_from_slave(struct bonding *bond,
{
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
struct vlan_entry *vlan;
- struct net_device *vlan_dev;
-
- if (!bond->vlgrp)
- return;
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
!(slave_ops->ndo_vlan_rx_kill_vid))
- goto unreg;
+ return;
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
if (!vlan->vlan_id)
continue;
- /* Save and then restore vlan_dev in the grp array,
- * since the slave's driver might clear it.
- */
- vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
- vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev);
}
-
-unreg:
- if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_ops->ndo_vlan_rx_register)
- slave_ops->ndo_vlan_rx_register(slave_dev, NULL);
}
/*------------------------------- Link status -------------------------------*/
@@ -634,15 +573,8 @@ static int bond_update_speed_duplex(struct slave *slave)
return -1;
slave_speed = ethtool_cmd_speed(&etool);
- switch (slave_speed) {
- case SPEED_10:
- case SPEED_100:
- case SPEED_1000:
- case SPEED_10000:
- break;
- default:
+ if (slave_speed == 0 || slave_speed == ((__u32) -1))
return -1;
- }
switch (etool.duplex) {
case DUPLEX_FULL:
@@ -849,13 +781,13 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
__bond_resend_igmp_join_requests(bond->dev);
/* rejoin all groups on vlan devices */
- if (bond->vlgrp) {
- list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- vlan_dev = vlan_group_get_device(bond->vlgrp,
- vlan->vlan_id);
- if (vlan_dev)
- __bond_resend_igmp_join_requests(vlan_dev);
- }
+ list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
+ rcu_read_unlock();
+ if (vlan_dev)
+ __bond_resend_igmp_join_requests(vlan_dev);
}
if (--bond->igmp_retrans > 0)
@@ -1570,7 +1502,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* no need to lock since we're protected by rtnl_lock */
if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
bond_dev->name, slave_dev->name, bond_dev->name);
return -EPERM;
@@ -1856,8 +1788,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* Initialize AD with the number of times that the AD timer is called in 1 second
* can be called only after the mac address of the bond is set
*/
- bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
- bond->params.lacp_fast);
+ bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
} else {
SLAVE_AD_INFO(new_slave).id =
SLAVE_AD_INFO(new_slave->prev).id + 1;
@@ -2079,7 +2010,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
*/
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
bond_dev->name, bond_dev->name);
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
@@ -2261,7 +2192,7 @@ static int bond_release_all(struct net_device *bond_dev)
*/
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
- if (bond->vlgrp) {
+ if (bond_vlan_used(bond)) {
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
bond_dev->name, bond_dev->name);
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
@@ -2699,7 +2630,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
if (!targets[i])
break;
pr_debug("basa: target %x\n", targets[i]);
- if (!bond->vlgrp) {
+ if (!bond_vlan_used(bond)) {
pr_debug("basa: empty vlan: arp_send\n");
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
bond->master_ip, 0);
@@ -2734,7 +2665,10 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
vlan_id = 0;
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
+ rcu_read_unlock();
if (vlan_dev == rt->dst.dev) {
vlan_id = vlan->vlan_id;
pr_debug("basa: vlan match on %s %d\n",
@@ -3395,9 +3329,8 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
}
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- if (!bond->vlgrp)
- continue;
- vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
+ vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan->vlan_id);
if (vlan_dev == event_dev) {
switch (event) {
case NETDEV_UP:
@@ -3456,7 +3389,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
int layer4_xor = 0;
if (skb->protocol == htons(ETH_P_IP)) {
- if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
+ if (!ip_is_fragment(iph) &&
(iph->protocol == IPPROTO_TCP ||
iph->protocol == IPPROTO_UDP)) {
layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
@@ -4349,10 +4282,9 @@ static const struct net_device_ops bond_netdev_ops = {
.ndo_do_ioctl = bond_do_ioctl,
.ndo_set_multicast_list = bond_set_multicast_list,
.ndo_change_mtu = bond_change_mtu,
- .ndo_set_mac_address = bond_set_mac_address,
+ .ndo_set_mac_address = bond_set_mac_address,
.ndo_neigh_setup = bond_neigh_setup,
- .ndo_vlan_rx_register = bond_vlan_rx_register,
- .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
+ .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_netpoll_setup = bond_netpoll_setup,
@@ -4816,6 +4748,7 @@ static int bond_check_params(struct bond_params *params)
params->tx_queues = tx_queues;
params->all_slaves_active = all_slaves_active;
params->resend_igmp = resend_igmp;
+ params->min_links = min_links;
if (primary) {
strncpy(params->primary, primary, IFNAMSIZ);
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index c97307ddd1c9..95de93b90386 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -125,6 +125,7 @@ static void bond_info_show_master(struct seq_file *seq)
seq_puts(seq, "\n802.3ad info\n");
seq_printf(seq, "LACP rate: %s\n",
(bond->params.lacp_fast) ? "fast" : "slow");
+ seq_printf(seq, "Min links: %d\n", bond->params.min_links);
seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
ad_select_tbl[bond->params.ad_select].modename);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 88fcb25e554a..b60835f58650 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -804,6 +804,7 @@ static ssize_t bonding_store_lacp(struct device *d,
if ((new_value == 1) || (new_value == 0)) {
bond->params.lacp_fast = new_value;
+ bond_3ad_update_lacp_rate(bond);
pr_info("%s: Setting LACP rate to %s (%d).\n",
bond->dev->name, bond_lacp_tbl[new_value].modename,
new_value);
@@ -818,6 +819,38 @@ out:
static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
bonding_show_lacp, bonding_store_lacp);
+static ssize_t bonding_show_min_links(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.min_links);
+}
+
+static ssize_t bonding_store_min_links(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bonding *bond = to_bond(d);
+ int ret;
+ unsigned int new_value;
+
+ ret = kstrtouint(buf, 0, &new_value);
+ if (ret < 0) {
+ pr_err("%s: Ignoring invalid min links value %s.\n",
+ bond->dev->name, buf);
+ return ret;
+ }
+
+ pr_info("%s: Setting min links value to %u\n",
+ bond->dev->name, new_value);
+ bond->params.min_links = new_value;
+ return count;
+}
+static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR,
+ bonding_show_min_links, bonding_store_min_links);
+
static ssize_t bonding_show_ad_select(struct device *d,
struct device_attribute *attr,
char *buf)
@@ -1600,6 +1633,7 @@ static struct attribute *per_bond_attrs[] = {
&dev_attr_queue_id.attr,
&dev_attr_all_slaves_active.attr,
&dev_attr_resend_igmp.attr,
+ &dev_attr_min_links.attr,
NULL,
};
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ea1d005be92d..43526a2d275c 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -147,6 +147,7 @@ struct bond_params {
int updelay;
int downdelay;
int lacp_fast;
+ unsigned int min_links;
int ad_select;
char primary[IFNAMSIZ];
int primary_reselect;
@@ -239,8 +240,6 @@ struct bonding {
struct alb_bond_info alb_info;
struct bond_params params;
struct list_head vlan_list;
- struct vlan_group *vlgrp;
- struct packet_type arp_mon_pt;
struct workqueue_struct *wq;
struct delayed_work mii_work;
struct delayed_work arp_work;
@@ -253,6 +252,11 @@ struct bonding {
#endif /* CONFIG_DEBUG_FS */
};
+static inline bool bond_vlan_used(struct bonding *bond)
+{
+ return !list_empty(&bond->vlan_list);
+}
+
#define bond_slave_get_rcu(dev) \
((struct slave *) rcu_dereference(dev->rx_handler_data))
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index 6e99d80ec409..a9b759add187 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -201,7 +201,7 @@ extern void ppp_unregister_compressor (struct compressor *cp);
#define LAST 255
#define MAXCODE(b) ((1 << (b)) - 1)
-#define BADCODEM1 MAXCODE(MAX_BSD_BITS);
+#define BADCODEM1 MAXCODE(MAX_BSD_BITS)
#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
^ (unsigned long)(prefix))
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 09ed3f42d673..abf4d7a9dcce 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -38,3 +38,12 @@ config CAIF_SHM
default n
---help---
The CAIF shared memory protocol driver for the STE UX5500 platform.
+
+config CAIF_HSI
+ tristate "CAIF HSI transport driver"
+ depends on CAIF
+ default n
+ ---help---
+ The caif low level driver for CAIF over HSI.
+ Be aware that if you enable this then you also need to
+ enable a low-level HSI driver.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 9560b9d624bd..91dff861560f 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -10,3 +10,6 @@ obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
# Shared memory
caif_shm-objs := caif_shmcore.o caif_shm_u5500.o
obj-$(CONFIG_CAIF_SHM) += caif_shm.o
+
+# HSI interface
+obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
new file mode 100644
index 000000000000..b41c2fced0a7
--- /dev/null
+++ b/drivers/net/caif/caif_hsi.c
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author: Daniel Martensson / daniel.martensson@stericsson.com
+ * Dmitry.Tarnyagin / dmitry.tarnyagin@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/if_arp.h>
+#include <linux/timer.h>
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_hsi.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>");
+MODULE_DESCRIPTION("CAIF HSI driver");
+
+/* Returns the number of padding bytes for alignment. */
+#define PAD_POW2(x, pow) ((((x)&((pow)-1)) == 0) ? 0 :\
+ (((pow)-((x)&((pow)-1)))))
+
+/*
+ * HSI padding options.
+ * Warning: must be a base of 2 (& operation used) and can not be zero !
+ */
+static int hsi_head_align = 4;
+module_param(hsi_head_align, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_head_align, "HSI head alignment.");
+
+static int hsi_tail_align = 4;
+module_param(hsi_tail_align, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_tail_align, "HSI tail alignment.");
+
+/*
+ * HSI link layer flowcontrol thresholds.
+ * Warning: A high threshold value migth increase throughput but it will at
+ * the same time prevent channel prioritization and increase the risk of
+ * flooding the modem. The high threshold should be above the low.
+ */
+static int hsi_high_threshold = 100;
+module_param(hsi_high_threshold, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_high_threshold, "HSI high threshold (FLOW OFF).");
+
+static int hsi_low_threshold = 50;
+module_param(hsi_low_threshold, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_low_threshold, "HSI high threshold (FLOW ON).");
+
+#define ON 1
+#define OFF 0
+
+/*
+ * Threshold values for the HSI packet queue. Flowcontrol will be asserted
+ * when the number of packets exceeds HIGH_WATER_MARK. It will not be
+ * de-asserted before the number of packets drops below LOW_WATER_MARK.
+ */
+#define LOW_WATER_MARK hsi_low_threshold
+#define HIGH_WATER_MARK hsi_high_threshold
+
+static LIST_HEAD(cfhsi_list);
+static spinlock_t cfhsi_list_lock;
+
+static void cfhsi_inactivity_tout(unsigned long arg)
+{
+ struct cfhsi *cfhsi = (struct cfhsi *)arg;
+
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ /* Schedule power down work queue. */
+ if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ queue_work(cfhsi->wq, &cfhsi->wake_down_work);
+}
+
+static void cfhsi_abort_tx(struct cfhsi *cfhsi)
+{
+ struct sk_buff *skb;
+
+ for (;;) {
+ spin_lock_bh(&cfhsi->lock);
+ skb = skb_dequeue(&cfhsi->qhead);
+ if (!skb)
+ break;
+
+ cfhsi->ndev->stats.tx_errors++;
+ cfhsi->ndev->stats.tx_dropped++;
+ spin_unlock_bh(&cfhsi->lock);
+ kfree_skb(skb);
+ }
+ cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+ if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ mod_timer(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+ spin_unlock_bh(&cfhsi->lock);
+}
+
+static int cfhsi_flush_fifo(struct cfhsi *cfhsi)
+{
+ char buffer[32]; /* Any reasonable value */
+ size_t fifo_occupancy;
+ int ret;
+
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+
+ ret = cfhsi->dev->cfhsi_wake_up(cfhsi->dev);
+ if (ret) {
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't wake up HSI interface: %d.\n",
+ __func__, ret);
+ return ret;
+ }
+
+ do {
+ ret = cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+ &fifo_occupancy);
+ if (ret) {
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't get FIFO occupancy: %d.\n",
+ __func__, ret);
+ break;
+ } else if (!fifo_occupancy)
+ /* No more data, exitting normally */
+ break;
+
+ fifo_occupancy = min(sizeof(buffer), fifo_occupancy);
+ set_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits);
+ ret = cfhsi->dev->cfhsi_rx(buffer, fifo_occupancy,
+ cfhsi->dev);
+ if (ret) {
+ clear_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits);
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't read data: %d.\n",
+ __func__, ret);
+ break;
+ }
+
+ ret = 5 * HZ;
+ wait_event_interruptible_timeout(cfhsi->flush_fifo_wait,
+ !test_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits), ret);
+
+ if (ret < 0) {
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't wait for flush complete: %d.\n",
+ __func__, ret);
+ break;
+ } else if (!ret) {
+ ret = -ETIMEDOUT;
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: timeout waiting for flush complete.\n",
+ __func__);
+ break;
+ }
+ } while (1);
+
+ cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+
+ return ret;
+}
+
+static int cfhsi_tx_frm(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+ int nfrms = 0;
+ int pld_len = 0;
+ struct sk_buff *skb;
+ u8 *pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+
+ skb = skb_dequeue(&cfhsi->qhead);
+ if (!skb)
+ return 0;
+
+ /* Check if we can embed a CAIF frame. */
+ if (skb->len < CFHSI_MAX_EMB_FRM_SZ) {
+ struct caif_payload_info *info;
+ int hpad = 0;
+ int tpad = 0;
+
+ /* Calculate needed head alignment and tail alignment. */
+ info = (struct caif_payload_info *)&skb->cb;
+
+ hpad = 1 + PAD_POW2((info->hdr_len + 1), hsi_head_align);
+ tpad = PAD_POW2((skb->len + hpad), hsi_tail_align);
+
+ /* Check if frame still fits with added alignment. */
+ if ((skb->len + hpad + tpad) <= CFHSI_MAX_EMB_FRM_SZ) {
+ u8 *pemb = desc->emb_frm;
+ desc->offset = CFHSI_DESC_SHORT_SZ;
+ *pemb = (u8)(hpad - 1);
+ pemb += hpad;
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.tx_packets++;
+ cfhsi->ndev->stats.tx_bytes += skb->len;
+
+ /* Copy in embedded CAIF frame. */
+ skb_copy_bits(skb, 0, pemb, skb->len);
+ consume_skb(skb);
+ skb = NULL;
+ }
+ } else
+ /* Clear offset. */
+ desc->offset = 0;
+
+ /* Create payload CAIF frames. */
+ pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+ while (nfrms < CFHSI_MAX_PKTS) {
+ struct caif_payload_info *info;
+ int hpad = 0;
+ int tpad = 0;
+
+ if (!skb)
+ skb = skb_dequeue(&cfhsi->qhead);
+
+ if (!skb)
+ break;
+
+ /* Calculate needed head alignment and tail alignment. */
+ info = (struct caif_payload_info *)&skb->cb;
+
+ hpad = 1 + PAD_POW2((info->hdr_len + 1), hsi_head_align);
+ tpad = PAD_POW2((skb->len + hpad), hsi_tail_align);
+
+ /* Fill in CAIF frame length in descriptor. */
+ desc->cffrm_len[nfrms] = hpad + skb->len + tpad;
+
+ /* Fill head padding information. */
+ *pfrm = (u8)(hpad - 1);
+ pfrm += hpad;
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.tx_packets++;
+ cfhsi->ndev->stats.tx_bytes += skb->len;
+
+ /* Copy in CAIF frame. */
+ skb_copy_bits(skb, 0, pfrm, skb->len);
+
+ /* Update payload length. */
+ pld_len += desc->cffrm_len[nfrms];
+
+ /* Update frame pointer. */
+ pfrm += skb->len + tpad;
+ consume_skb(skb);
+ skb = NULL;
+
+ /* Update number of frames. */
+ nfrms++;
+ }
+
+ /* Unused length fields should be zero-filled (according to SPEC). */
+ while (nfrms < CFHSI_MAX_PKTS) {
+ desc->cffrm_len[nfrms] = 0x0000;
+ nfrms++;
+ }
+
+ /* Check if we can piggy-back another descriptor. */
+ skb = skb_peek(&cfhsi->qhead);
+ if (skb)
+ desc->header |= CFHSI_PIGGY_DESC;
+ else
+ desc->header &= ~CFHSI_PIGGY_DESC;
+
+ return CFHSI_DESC_SZ + pld_len;
+}
+
+static void cfhsi_tx_done_work(struct work_struct *work)
+{
+ 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__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ desc = (struct cfhsi_desc *)cfhsi->tx_buf;
+
+ do {
+ /*
+ * Send flow on if flow off has been previously signalled
+ * and number of packets is below low water mark.
+ */
+ spin_lock_bh(&cfhsi->lock);
+ if (cfhsi->flow_off_sent &&
+ cfhsi->qhead.qlen <= cfhsi->q_low_mark &&
+ cfhsi->cfdev.flowctrl) {
+
+ cfhsi->flow_off_sent = 0;
+ cfhsi->cfdev.flowctrl(cfhsi->ndev, ON);
+ }
+ 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;
+ }
+
+ /* Set up new transfer. */
+ res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+ __func__, res);
+ }
+ } while (res < 0);
+}
+
+static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ queue_work(cfhsi->wq, &cfhsi->tx_done_work);
+}
+
+static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+ int xfer_sz = 0;
+ int nfrms = 0;
+ u16 *plen = NULL;
+ u8 *pfrm = NULL;
+
+ if ((desc->header & ~CFHSI_PIGGY_DESC) ||
+ (desc->offset > CFHSI_MAX_EMB_FRM_SZ)) {
+ dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
+ __func__);
+ return 0;
+ }
+
+ /* Check for embedded CAIF frame. */
+ if (desc->offset) {
+ struct sk_buff *skb;
+ u8 *dst = NULL;
+ int len = 0, retries = 0;
+ pfrm = ((u8 *)desc) + desc->offset;
+
+ /* Remove offset padding. */
+ pfrm += *pfrm + 1;
+
+ /* Read length of CAIF frame (little endian). */
+ len = *pfrm;
+ len |= ((*(pfrm+1)) << 8) & 0xFF00;
+ len += 2; /* Add FCS fields. */
+
+
+ /* 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;
+ }
+ }
+ caif_assert(skb != NULL);
+
+ dst = skb_put(skb, len);
+ memcpy(dst, pfrm, len);
+
+ skb->protocol = htons(ETH_P_CAIF);
+ skb_reset_mac_header(skb);
+ skb->dev = cfhsi->ndev;
+
+ /*
+ * We are called from a arch specific platform device.
+ * Unfortunately we don't know what context we're
+ * running in.
+ */
+ if (in_interrupt())
+ netif_rx(skb);
+ else
+ netif_rx_ni(skb);
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.rx_packets++;
+ cfhsi->ndev->stats.rx_bytes += len;
+ }
+
+drop_frame:
+ /* Calculate transfer length. */
+ plen = desc->cffrm_len;
+ while (nfrms < CFHSI_MAX_PKTS && *plen) {
+ xfer_sz += *plen;
+ plen++;
+ nfrms++;
+ }
+
+ /* Check for piggy-backed descriptor. */
+ if (desc->header & CFHSI_PIGGY_DESC)
+ xfer_sz += CFHSI_DESC_SZ;
+
+ if (xfer_sz % 4) {
+ dev_err(&cfhsi->ndev->dev,
+ "%s: Invalid payload len: %d, ignored.\n",
+ __func__, xfer_sz);
+ xfer_sz = 0;
+ }
+
+ return xfer_sz;
+}
+
+static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+ int rx_sz = 0;
+ int nfrms = 0;
+ u16 *plen = NULL;
+ u8 *pfrm = NULL;
+
+ /* Sanity check header and offset. */
+ if (WARN_ON((desc->header & ~CFHSI_PIGGY_DESC) ||
+ (desc->offset > CFHSI_MAX_EMB_FRM_SZ))) {
+ dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Set frame pointer to start of payload. */
+ pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+ plen = desc->cffrm_len;
+ 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;
+ }
+
+ /* CAIF frame starts after head padding. */
+ pcffrm = pfrm + *pfrm + 1;
+
+ /* Read length of CAIF frame (little endian). */
+ len = *pcffrm;
+ len |= ((*(pcffrm + 1)) << 8) & 0xFF00;
+ len += 2; /* Add FCS fields. */
+
+ /* 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;
+ }
+ }
+ caif_assert(skb != NULL);
+
+ dst = skb_put(skb, len);
+ memcpy(dst, pcffrm, len);
+
+ skb->protocol = htons(ETH_P_CAIF);
+ skb_reset_mac_header(skb);
+ skb->dev = cfhsi->ndev;
+
+ /*
+ * We're called from a platform device,
+ * and don't know the context we're running in.
+ */
+ if (in_interrupt())
+ netif_rx(skb);
+ else
+ netif_rx_ni(skb);
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.rx_packets++;
+ cfhsi->ndev->stats.rx_bytes += len;
+
+drop_frame:
+ pfrm += *plen;
+ rx_sz += *plen;
+ plen++;
+ nfrms++;
+ }
+
+ return rx_sz;
+}
+
+static void cfhsi_rx_done_work(struct work_struct *work)
+{
+ 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__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ /* Update inactivity timer if pending. */
+ mod_timer_pending(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+
+ if (cfhsi->rx_state == CFHSI_RX_STATE_DESC) {
+ desc_pld_len = cfhsi_rx_desc(desc, cfhsi);
+ } else {
+ int pld_len;
+
+ pld_len = cfhsi_rx_pld(desc, cfhsi);
+
+ 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);
+
+ /* Extract piggy-backed descriptor. */
+ desc_pld_len = cfhsi_rx_desc(piggy_desc, cfhsi);
+
+ /*
+ * Copy needed information from the piggy-backed
+ * descriptor to the descriptor in the start.
+ */
+ memcpy((u8 *)desc, (u8 *)piggy_desc,
+ CFHSI_DESC_SHORT_SZ);
+ }
+ }
+
+ if (desc_pld_len) {
+ cfhsi->rx_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_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. */
+ 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);
+ cfhsi->ndev->stats.rx_errors++;
+ cfhsi->ndev->stats.rx_dropped++;
+ }
+ }
+}
+
+static void cfhsi_rx_done_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ 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);
+}
+
+static void cfhsi_wake_up(struct work_struct *work)
+{
+ struct cfhsi *cfhsi = NULL;
+ int res;
+ int len;
+ long ret;
+
+ cfhsi = container_of(work, struct cfhsi, wake_up_work);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ if (unlikely(test_bit(CFHSI_AWAKE, &cfhsi->bits))) {
+ /* It happenes when wakeup is requested by
+ * both ends at the same time. */
+ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+ return;
+ }
+
+ /* Activate wake line. */
+ cfhsi->dev->cfhsi_wake_up(cfhsi->dev);
+
+ dev_dbg(&cfhsi->ndev->dev, "%s: Start waiting.\n",
+ __func__);
+
+ /* Wait for acknowledge. */
+ ret = CFHSI_WAKEUP_TOUT;
+ wait_event_interruptible_timeout(cfhsi->wake_up_wait,
+ test_bit(CFHSI_WAKE_UP_ACK,
+ &cfhsi->bits), ret);
+ if (unlikely(ret < 0)) {
+ /* Interrupted by signal. */
+ dev_info(&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) {
+ /* Wakeup timeout */
+ dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+ __func__);
+ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+ cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+ return;
+ }
+ dev_dbg(&cfhsi->ndev->dev, "%s: Woken.\n",
+ __func__);
+
+ /* Clear power up bit. */
+ set_bit(CFHSI_AWAKE, &cfhsi->bits);
+ 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);
+ }
+ }
+
+ /* Clear power up acknowledment. */
+ clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+
+ spin_lock_bh(&cfhsi->lock);
+
+ /* Resume transmit if queue is not empty. */
+ if (!skb_peek(&cfhsi->qhead)) {
+ dev_dbg(&cfhsi->ndev->dev, "%s: Peer wake, start timer.\n",
+ __func__);
+ /* Start inactivity timer. */
+ mod_timer(&cfhsi->timer,
+ jiffies + CFHSI_INACTIVITY_TOUT);
+ spin_unlock_bh(&cfhsi->lock);
+ return;
+ }
+
+ dev_dbg(&cfhsi->ndev->dev, "%s: Host wake.\n",
+ __func__);
+
+ spin_unlock_bh(&cfhsi->lock);
+
+ /* Create HSI frame. */
+ len = cfhsi_tx_frm((struct cfhsi_desc *)cfhsi->tx_buf, cfhsi);
+
+ if (likely(len > 0)) {
+ /* Set up new transfer. */
+ res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+ __func__, res);
+ cfhsi_abort_tx(cfhsi);
+ }
+ } else {
+ dev_err(&cfhsi->ndev->dev,
+ "%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;
+
+ cfhsi = container_of(work, struct cfhsi, wake_down_work);
+ 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 = wait_event_interruptible_timeout(cfhsi->wake_down_wait,
+ test_bit(CFHSI_WAKE_DOWN_ACK,
+ &cfhsi->bits),
+ ret);
+ if (ret < 0) {
+ /* Interrupted by signal. */
+ dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+ __func__, ret);
+ return;
+ } else if (!ret) {
+ /* Timeout */
+ dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+ __func__);
+ }
+
+ /* Clear power down acknowledment. */
+ clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+ 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;
+
+ 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_wake_up_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi = NULL;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ set_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+ wake_up_interruptible(&cfhsi->wake_up_wait);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ /* Schedule wake up work queue if the peer initiates. */
+ if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+ queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+}
+
+static void cfhsi_wake_down_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi = NULL;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ /* Initiating low power is only permitted by the host (us). */
+ set_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+ wake_up_interruptible(&cfhsi->wake_down_wait);
+}
+
+static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct cfhsi *cfhsi = NULL;
+ int start_xfer = 0;
+ int timer_active;
+
+ if (!dev)
+ return -EINVAL;
+
+ cfhsi = netdev_priv(dev);
+
+ spin_lock_bh(&cfhsi->lock);
+
+ skb_queue_tail(&cfhsi->qhead, skb);
+
+ /* Sanity check; xmit should not be called after unregister_netdev */
+ if (WARN_ON(test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))) {
+ spin_unlock_bh(&cfhsi->lock);
+ cfhsi_abort_tx(cfhsi);
+ return -EINVAL;
+ }
+
+ /* Send flow off if number of packets is above high water mark. */
+ if (!cfhsi->flow_off_sent &&
+ cfhsi->qhead.qlen > cfhsi->q_high_mark &&
+ cfhsi->cfdev.flowctrl) {
+ cfhsi->flow_off_sent = 1;
+ cfhsi->cfdev.flowctrl(cfhsi->ndev, OFF);
+ }
+
+ if (cfhsi->tx_state == CFHSI_TX_STATE_IDLE) {
+ cfhsi->tx_state = CFHSI_TX_STATE_XFER;
+ start_xfer = 1;
+ }
+
+ spin_unlock_bh(&cfhsi->lock);
+
+ if (!start_xfer)
+ 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 */
+
+ if (timer_active) {
+ struct cfhsi_desc *desc = (struct cfhsi_desc *)cfhsi->tx_buf;
+ int len;
+ int res;
+
+ /* Create HSI frame. */
+ len = cfhsi_tx_frm(desc, cfhsi);
+ BUG_ON(!len);
+
+ /* Set up new transfer. */
+ res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+ __func__, res);
+ cfhsi_abort_tx(cfhsi);
+ }
+ } else {
+ /* Schedule wake up work queue if the we initiate. */
+ if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+ queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+ }
+
+ return 0;
+}
+
+static int cfhsi_open(struct net_device *dev)
+{
+ netif_wake_queue(dev);
+
+ return 0;
+}
+
+static int cfhsi_close(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static const struct net_device_ops cfhsi_ops = {
+ .ndo_open = cfhsi_open,
+ .ndo_stop = cfhsi_close,
+ .ndo_start_xmit = cfhsi_xmit
+};
+
+static void cfhsi_setup(struct net_device *dev)
+{
+ struct cfhsi *cfhsi = netdev_priv(dev);
+ dev->features = 0;
+ dev->netdev_ops = &cfhsi_ops;
+ dev->type = ARPHRD_CAIF;
+ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ dev->mtu = CFHSI_MAX_PAYLOAD_SZ;
+ dev->tx_queue_len = 0;
+ dev->destructor = free_netdev;
+ skb_queue_head_init(&cfhsi->qhead);
+ cfhsi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
+ cfhsi->cfdev.use_frag = false;
+ cfhsi->cfdev.use_stx = false;
+ cfhsi->cfdev.use_fcs = false;
+ cfhsi->ndev = dev;
+}
+
+int cfhsi_probe(struct platform_device *pdev)
+{
+ struct cfhsi *cfhsi = NULL;
+ struct net_device *ndev;
+ struct cfhsi_dev *dev;
+ int res;
+
+ ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
+ if (!ndev) {
+ dev_err(&pdev->dev, "%s: alloc_netdev failed.\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ cfhsi = netdev_priv(ndev);
+ cfhsi->ndev = ndev;
+ cfhsi->pdev = pdev;
+
+ /* Initialize state vaiables. */
+ cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+ cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+
+ /* Set flow info */
+ cfhsi->flow_off_sent = 0;
+ cfhsi->q_low_mark = LOW_WATER_MARK;
+ cfhsi->q_high_mark = HIGH_WATER_MARK;
+
+ /* Assign the HSI device. */
+ dev = (struct cfhsi_dev *)pdev->dev.platform_data;
+ cfhsi->dev = dev;
+
+ /* Assign the driver to this HSI device. */
+ dev->drv = &cfhsi->drv;
+
+ /*
+ * Allocate a TX buffer with the size of a HSI packet descriptors
+ * and the necessary room for CAIF payload frames.
+ */
+ 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;
+ }
+
+ /*
+ * Allocate a RX buffer with the size of two HSI packet descriptors and
+ * the necessary room for CAIF payload frames.
+ */
+ 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. */
+ cfhsi->rx_ptr = cfhsi->rx_buf;
+ cfhsi->rx_len = CFHSI_DESC_SZ;
+
+ /* Initialize spin locks. */
+ spin_lock_init(&cfhsi->lock);
+
+ /* Set up the driver. */
+ cfhsi->drv.tx_done_cb = cfhsi_tx_done_cb;
+ cfhsi->drv.rx_done_cb = cfhsi_rx_done_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);
+
+ /* 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);
+ if (!cfhsi->wq) {
+ dev_err(&ndev->dev, "%s: Failed to create work queue.\n",
+ __func__);
+ res = -ENODEV;
+ goto err_create_wq;
+ }
+
+ /* Initialize wait queues. */
+ init_waitqueue_head(&cfhsi->wake_up_wait);
+ init_waitqueue_head(&cfhsi->wake_down_wait);
+ init_waitqueue_head(&cfhsi->flush_fifo_wait);
+
+ /* Setup the inactivity timer. */
+ init_timer(&cfhsi->timer);
+ cfhsi->timer.data = (unsigned long)cfhsi;
+ cfhsi->timer.function = cfhsi_inactivity_tout;
+
+ /* Add CAIF HSI device to list. */
+ spin_lock(&cfhsi_list_lock);
+ list_add_tail(&cfhsi->list, &cfhsi_list);
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Activate HSI interface. */
+ res = cfhsi->dev->cfhsi_up(cfhsi->dev);
+ if (res) {
+ dev_err(&cfhsi->ndev->dev,
+ "%s: can't activate HSI interface: %d.\n",
+ __func__, res);
+ goto err_activate;
+ }
+
+ /* Flush FIFO */
+ res = cfhsi_flush_fifo(cfhsi);
+ if (res) {
+ dev_err(&ndev->dev, "%s: Can't flush FIFO: %d.\n",
+ __func__, res);
+ 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) {
+ dev_err(&ndev->dev, "%s: Registration error: %d.\n",
+ __func__, res);
+ goto err_net_reg;
+ }
+
+ netif_stop_queue(ndev);
+
+ return res;
+
+ err_net_reg:
+ cfhsi->dev->cfhsi_down(cfhsi->dev);
+ err_activate:
+ destroy_workqueue(cfhsi->wq);
+ err_create_wq:
+ kfree(cfhsi->rx_buf);
+ err_alloc_rx:
+ kfree(cfhsi->tx_buf);
+ err_alloc_tx:
+ free_netdev(ndev);
+
+ return res;
+}
+
+static void cfhsi_shutdown(struct cfhsi *cfhsi, bool remove_platform_dev)
+{
+ u8 *tx_buf, *rx_buf;
+
+ /* Stop TXing */
+ netif_tx_stop_all_queues(cfhsi->ndev);
+
+ /* 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
+ del_timer_sync(&cfhsi->timer);
+#else
+ del_timer(&cfhsi->timer);
+#endif /* CONFIG_SMP */
+
+ /* Cancel pending RX request (if any) */
+ cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
+
+ /* Flush again and destroy workqueue */
+ destroy_workqueue(cfhsi->wq);
+
+ /* Store bufferes: will be freed later. */
+ tx_buf = cfhsi->tx_buf;
+ rx_buf = cfhsi->rx_buf;
+
+ /* Flush transmit queues. */
+ cfhsi_abort_tx(cfhsi);
+
+ /* Deactivate interface */
+ cfhsi->dev->cfhsi_down(cfhsi->dev);
+
+ /* Finally unregister the network device. */
+ unregister_netdev(cfhsi->ndev);
+
+ /* Free buffers. */
+ kfree(tx_buf);
+ kfree(rx_buf);
+}
+
+int cfhsi_remove(struct platform_device *pdev)
+{
+ struct list_head *list_node;
+ struct list_head *n;
+ struct cfhsi *cfhsi = NULL;
+ struct cfhsi_dev *dev;
+
+ dev = (struct cfhsi_dev *)pdev->dev.platform_data;
+ spin_lock(&cfhsi_list_lock);
+ list_for_each_safe(list_node, n, &cfhsi_list) {
+ cfhsi = list_entry(list_node, struct cfhsi, list);
+ /* Find the corresponding device. */
+ if (cfhsi->dev == dev) {
+ /* Remove from list. */
+ list_del(list_node);
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Shutdown driver. */
+ cfhsi_shutdown(cfhsi, false);
+
+ return 0;
+ }
+ }
+ spin_unlock(&cfhsi_list_lock);
+ return -ENODEV;
+}
+
+struct platform_driver cfhsi_plat_drv = {
+ .probe = cfhsi_probe,
+ .remove = cfhsi_remove,
+ .driver = {
+ .name = "cfhsi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static void __exit cfhsi_exit_module(void)
+{
+ struct list_head *list_node;
+ struct list_head *n;
+ struct cfhsi *cfhsi = NULL;
+
+ spin_lock(&cfhsi_list_lock);
+ list_for_each_safe(list_node, n, &cfhsi_list) {
+ cfhsi = list_entry(list_node, struct cfhsi, list);
+
+ /* Remove from list. */
+ list_del(list_node);
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Shutdown driver. */
+ cfhsi_shutdown(cfhsi, true);
+
+ spin_lock(&cfhsi_list_lock);
+ }
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Unregister platform driver. */
+ platform_driver_unregister(&cfhsi_plat_drv);
+}
+
+static int __init cfhsi_init_module(void)
+{
+ int result;
+
+ /* Initialize spin lock. */
+ spin_lock_init(&cfhsi_list_lock);
+
+ /* Register platform driver. */
+ result = platform_driver_register(&cfhsi_plat_drv);
+ if (result) {
+ printk(KERN_ERR "Could not register platform HSI driver: %d.\n",
+ result);
+ goto err_dev_register;
+ }
+
+ return result;
+
+ err_dev_register:
+ return result;
+}
+
+module_init(cfhsi_init_module);
+module_exit(cfhsi_exit_module);
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 3df0c0f8b8bf..23406e62c0b0 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -4,8 +4,8 @@
* License terms: GNU General Public License (GPL) version 2
*/
+#include <linux/hardirq.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/types.h>
diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c
index 5f771ab712c4..89d76b7b325a 100644
--- a/drivers/net/caif/caif_shm_u5500.c
+++ b/drivers/net/caif/caif_shm_u5500.c
@@ -7,7 +7,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c
index 731aa1193770..d4b26fb24ed9 100644
--- a/drivers/net/caif/caif_shmcore.c
+++ b/drivers/net/caif/caif_shmcore.c
@@ -134,7 +134,7 @@ int caif_shmdrv_rx_cb(u32 mbx_msg, void *priv)
u32 avail_emptybuff = 0;
unsigned long flags = 0;
- pshm_drv = (struct shmdrv_layer *)priv;
+ pshm_drv = priv;
/* Check for received buffers. */
if (mbx_msg & SHM_FULL_MASK) {
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 57e639373815..0f8defc73307 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -5,7 +5,6 @@
* License terms: GNU General Public License (GPL) version 2.
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c
index b009e03cda9e..e139e133fc79 100644
--- a/drivers/net/caif/caif_spi_slave.c
+++ b/drivers/net/caif/caif_spi_slave.c
@@ -4,7 +4,6 @@
* Author: Daniel Martensson / Daniel.Martensson@stericsson.com
* License terms: GNU General Public License (GPL) version 2.
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 754df5ef1729..f6c98fb4a517 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -4,7 +4,6 @@ menu "CAN Device Drivers"
config CAN_VCAN
tristate "Virtual Local CAN Interface (vcan)"
depends on CAN
- default N
---help---
Similar to the network loopback devices, vcan offers a
virtual local CAN interface.
@@ -15,7 +14,6 @@ config CAN_VCAN
config CAN_SLCAN
tristate "Serial / USB serial CAN Adaptors (slcan)"
depends on CAN
- default N
---help---
CAN driver for several 'low cost' CAN interfaces that are attached
via serial lines or via USB-to-serial adapters using the LAWICEL
@@ -58,9 +56,10 @@ config CAN_CALC_BITTIMING
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
- depends on CAN_DEV && ARCH_AT91SAM9263
+ depends on CAN_DEV && (ARCH_AT91SAM9263 || ARCH_AT91SAM9X5)
---help---
- This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+ This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
+ and AT91SAM9X5 processors.
config CAN_TI_HECC
depends on CAN_DEV && ARCH_OMAP3
@@ -124,7 +123,6 @@ source "drivers/net/can/softing/Kconfig"
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
depends on CAN
- default N
---help---
Say Y here if you want the CAN device drivers to produce a bunch of
debug messages to the system log. Select this if you are having
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 74efb5a2ad41..121ede663e20 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -41,32 +41,7 @@
#include <mach/board.h>
-#define AT91_NAPI_WEIGHT 11
-
-/*
- * RX/TX Mailbox split
- * don't dare to touch
- */
-#define AT91_MB_RX_NUM 11
-#define AT91_MB_TX_SHIFT 2
-
-#define AT91_MB_RX_FIRST 1
-#define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
-
-#define AT91_MB_RX_MASK(i) ((1 << (i)) - 1)
-#define AT91_MB_RX_SPLIT 8
-#define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1)
-#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
- ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
-
-#define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT)
-#define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1)
-#define AT91_MB_TX_LAST (AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1)
-
-#define AT91_NEXT_PRIO_SHIFT (AT91_MB_TX_SHIFT)
-#define AT91_NEXT_PRIO_MASK (0xf << AT91_MB_TX_SHIFT)
-#define AT91_NEXT_MB_MASK (AT91_MB_TX_NUM - 1)
-#define AT91_NEXT_MASK ((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK)
+#define AT91_MB_MASK(i) ((1 << (i)) - 1)
/* Common registers */
enum at91_reg {
@@ -128,12 +103,6 @@ enum at91_mb_mode {
};
/* Interrupt mask bits */
-#define AT91_IRQ_MB_RX ((1 << (AT91_MB_RX_LAST + 1)) \
- - (1 << AT91_MB_RX_FIRST))
-#define AT91_IRQ_MB_TX ((1 << (AT91_MB_TX_LAST + 1)) \
- - (1 << AT91_MB_TX_FIRST))
-#define AT91_IRQ_MB_ALL (AT91_IRQ_MB_RX | AT91_IRQ_MB_TX)
-
#define AT91_IRQ_ERRA (1 << 16)
#define AT91_IRQ_WARN (1 << 17)
#define AT91_IRQ_ERRP (1 << 18)
@@ -156,22 +125,51 @@ enum at91_mb_mode {
#define AT91_IRQ_ALL (0x1fffffff)
+enum at91_devtype {
+ AT91_DEVTYPE_SAM9263,
+ AT91_DEVTYPE_SAM9X5,
+};
+
+struct at91_devtype_data {
+ unsigned int rx_first;
+ unsigned int rx_split;
+ unsigned int rx_last;
+ unsigned int tx_shift;
+ enum at91_devtype type;
+};
+
struct at91_priv {
- struct can_priv can; /* must be the first member! */
- struct net_device *dev;
- struct napi_struct napi;
+ struct can_priv can; /* must be the first member! */
+ struct net_device *dev;
+ struct napi_struct napi;
- void __iomem *reg_base;
+ void __iomem *reg_base;
- u32 reg_sr;
- unsigned int tx_next;
- unsigned int tx_echo;
- unsigned int rx_next;
+ u32 reg_sr;
+ unsigned int tx_next;
+ unsigned int tx_echo;
+ unsigned int rx_next;
+ struct at91_devtype_data devtype_data;
- struct clk *clk;
- struct at91_can_data *pdata;
+ struct clk *clk;
+ struct at91_can_data *pdata;
- canid_t mb0_id;
+ canid_t mb0_id;
+};
+
+static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
+ [AT91_DEVTYPE_SAM9263] = {
+ .rx_first = 1,
+ .rx_split = 8,
+ .rx_last = 11,
+ .tx_shift = 2,
+ },
+ [AT91_DEVTYPE_SAM9X5] = {
+ .rx_first = 0,
+ .rx_split = 4,
+ .rx_last = 5,
+ .tx_shift = 1,
+ },
};
static struct can_bittiming_const at91_bittiming_const = {
@@ -186,19 +184,111 @@ static struct can_bittiming_const at91_bittiming_const = {
.brp_inc = 1,
};
-static inline int get_tx_next_mb(const struct at91_priv *priv)
+#define AT91_IS(_model) \
+static inline int at91_is_sam##_model(const struct at91_priv *priv) \
+{ \
+ return priv->devtype_data.type == AT91_DEVTYPE_SAM##_model; \
+}
+
+AT91_IS(9263);
+AT91_IS(9X5);
+
+static inline unsigned int get_mb_rx_first(const struct at91_priv *priv)
+{
+ return priv->devtype_data.rx_first;
+}
+
+static inline unsigned int get_mb_rx_last(const struct at91_priv *priv)
+{
+ return priv->devtype_data.rx_last;
+}
+
+static inline unsigned int get_mb_rx_split(const struct at91_priv *priv)
+{
+ return priv->devtype_data.rx_split;
+}
+
+static inline unsigned int get_mb_rx_num(const struct at91_priv *priv)
+{
+ return get_mb_rx_last(priv) - get_mb_rx_first(priv) + 1;
+}
+
+static inline unsigned int get_mb_rx_low_last(const struct at91_priv *priv)
+{
+ return get_mb_rx_split(priv) - 1;
+}
+
+static inline unsigned int get_mb_rx_low_mask(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_rx_split(priv)) &
+ ~AT91_MB_MASK(get_mb_rx_first(priv));
+}
+
+static inline unsigned int get_mb_tx_shift(const struct at91_priv *priv)
+{
+ return priv->devtype_data.tx_shift;
+}
+
+static inline unsigned int get_mb_tx_num(const struct at91_priv *priv)
+{
+ return 1 << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_mb_tx_first(const struct at91_priv *priv)
+{
+ return get_mb_rx_last(priv) + 1;
+}
+
+static inline unsigned int get_mb_tx_last(const struct at91_priv *priv)
+{
+ return get_mb_tx_first(priv) + get_mb_tx_num(priv) - 1;
+}
+
+static inline unsigned int get_next_prio_shift(const struct at91_priv *priv)
+{
+ return get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_prio_mask(const struct at91_priv *priv)
+{
+ return 0xf << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_mb_mask(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_tx_shift(priv));
+}
+
+static inline unsigned int get_next_mask(const struct at91_priv *priv)
+{
+ return get_next_mb_mask(priv) | get_next_prio_mask(priv);
+}
+
+static inline unsigned int get_irq_mb_rx(const struct at91_priv *priv)
{
- return (priv->tx_next & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+ return AT91_MB_MASK(get_mb_rx_last(priv) + 1) &
+ ~AT91_MB_MASK(get_mb_rx_first(priv));
}
-static inline int get_tx_next_prio(const struct at91_priv *priv)
+static inline unsigned int get_irq_mb_tx(const struct at91_priv *priv)
{
- return (priv->tx_next >> AT91_NEXT_PRIO_SHIFT) & 0xf;
+ return AT91_MB_MASK(get_mb_tx_last(priv) + 1) &
+ ~AT91_MB_MASK(get_mb_tx_first(priv));
}
-static inline int get_tx_echo_mb(const struct at91_priv *priv)
+static inline unsigned int get_tx_next_mb(const struct at91_priv *priv)
{
- return (priv->tx_echo & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+ return (priv->tx_next & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
+}
+
+static inline unsigned int get_tx_next_prio(const struct at91_priv *priv)
+{
+ return (priv->tx_next >> get_next_prio_shift(priv)) & 0xf;
+}
+
+static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv)
+{
+ return (priv->tx_echo & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
}
static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
@@ -259,29 +349,29 @@ static void at91_setup_mailboxes(struct net_device *dev)
* overflow.
*/
reg_mid = at91_can_id_to_reg_mid(priv->mb0_id);
- for (i = 0; i < AT91_MB_RX_FIRST; i++) {
+ for (i = 0; i < get_mb_rx_first(priv); i++) {
set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);
at91_write(priv, AT91_MID(i), reg_mid);
at91_write(priv, AT91_MCR(i), 0x0); /* clear dlc */
}
- for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
+ for (i = get_mb_rx_first(priv); i < get_mb_rx_last(priv); i++)
set_mb_mode(priv, i, AT91_MB_MODE_RX);
- set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
+ set_mb_mode(priv, get_mb_rx_last(priv), AT91_MB_MODE_RX_OVRWR);
/* reset acceptance mask and id register */
- for (i = AT91_MB_RX_FIRST; i <= AT91_MB_RX_LAST; i++) {
- at91_write(priv, AT91_MAM(i), 0x0 );
+ for (i = get_mb_rx_first(priv); i <= get_mb_rx_last(priv); i++) {
+ at91_write(priv, AT91_MAM(i), 0x0);
at91_write(priv, AT91_MID(i), AT91_MID_MIDE);
}
/* The last 4 mailboxes are used for transmitting. */
- for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++)
+ for (i = get_mb_tx_first(priv); i <= get_mb_tx_last(priv); i++)
set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
/* Reset tx and rx helper pointers */
priv->tx_next = priv->tx_echo = 0;
- priv->rx_next = AT91_MB_RX_FIRST;
+ priv->rx_next = get_mb_rx_first(priv);
}
static int at91_set_bittiming(struct net_device *dev)
@@ -336,7 +426,7 @@ static void at91_chip_start(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* Enable interrupts */
- reg_ier = AT91_IRQ_MB_RX | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
+ reg_ier = get_irq_mb_rx(priv) | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
at91_write(priv, AT91_IER, reg_ier);
}
@@ -375,8 +465,8 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
* mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits
* encode the mailbox number, the upper 4 bits the mailbox priority:
*
- * priv->tx_next = (prio << AT91_NEXT_PRIO_SHIFT) ||
- * (mb - AT91_MB_TX_FIRST);
+ * priv->tx_next = (prio << get_next_prio_shift(priv)) |
+ * (mb - get_mb_tx_first(priv));
*
*/
static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -417,7 +507,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_bytes += cf->can_dlc;
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
- can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST);
+ can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv));
/*
* we have to stop the queue and deliver all messages in case
@@ -430,7 +520,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
priv->tx_next++;
if (!(at91_read(priv, AT91_MSR(get_tx_next_mb(priv))) &
AT91_MSR_MRDY) ||
- (priv->tx_next & AT91_NEXT_MASK) == 0)
+ (priv->tx_next & get_next_mask(priv)) == 0)
netif_stop_queue(dev);
/* Enable interrupt for this mailbox */
@@ -447,7 +537,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static inline void at91_activate_rx_low(const struct at91_priv *priv)
{
- u32 mask = AT91_MB_RX_LOW_MASK;
+ u32 mask = get_mb_rx_low_mask(priv);
at91_write(priv, AT91_TCR, mask);
}
@@ -513,17 +603,19 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,
cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;
reg_msr = at91_read(priv, AT91_MSR(mb));
- if (reg_msr & AT91_MSR_MRTR)
- cf->can_id |= CAN_RTR_FLAG;
cf->can_dlc = get_can_dlc((reg_msr >> 16) & 0xf);
- *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
- *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+ if (reg_msr & AT91_MSR_MRTR)
+ cf->can_id |= CAN_RTR_FLAG;
+ else {
+ *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
+ *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+ }
/* allow RX of extended frames */
at91_write(priv, AT91_MID(mb), AT91_MID_MIDE);
- if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI))
+ if (unlikely(mb == get_mb_rx_last(priv) && reg_msr & AT91_MSR_MMI))
at91_rx_overflow_err(dev);
}
@@ -561,8 +653,9 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
*
* Theory of Operation:
*
- * 11 of the 16 mailboxes on the chip are reserved for RX. we split
- * them into 2 groups. The lower group holds 7 and upper 4 mailboxes.
+ * About 3/4 of the mailboxes (get_mb_rx_first()...get_mb_rx_last())
+ * on the chip are reserved for RX. We split them into 2 groups. The
+ * lower group ranges from get_mb_rx_first() to get_mb_rx_low_last().
*
* Like it or not, but the chip always saves a received CAN message
* into the first free mailbox it finds (starting with the
@@ -610,23 +703,23 @@ static int at91_poll_rx(struct net_device *dev, int quota)
unsigned int mb;
int received = 0;
- if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
- reg_sr & AT91_MB_RX_LOW_MASK)
+ if (priv->rx_next > get_mb_rx_low_last(priv) &&
+ reg_sr & get_mb_rx_low_mask(priv))
netdev_info(dev,
"order of incoming frames cannot be guaranteed\n");
again:
- for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next);
- mb < AT91_MB_RX_LAST + 1 && quota > 0;
+ for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next);
+ mb < get_mb_tx_first(priv) && quota > 0;
reg_sr = at91_read(priv, AT91_SR),
- mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) {
+ mb = find_next_bit(addr, get_mb_tx_first(priv), ++priv->rx_next)) {
at91_read_msg(dev, mb);
/* reactivate mailboxes */
- if (mb == AT91_MB_RX_LOW_LAST)
+ if (mb == get_mb_rx_low_last(priv))
/* all lower mailboxed, if just finished it */
at91_activate_rx_low(priv);
- else if (mb > AT91_MB_RX_LOW_LAST)
+ else if (mb > get_mb_rx_low_last(priv))
/* only the mailbox we read */
at91_activate_rx_mb(priv, mb);
@@ -635,9 +728,9 @@ static int at91_poll_rx(struct net_device *dev, int quota)
}
/* upper group completed, look again in lower */
- if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
- quota > 0 && mb > AT91_MB_RX_LAST) {
- priv->rx_next = AT91_MB_RX_FIRST;
+ if (priv->rx_next > get_mb_rx_low_last(priv) &&
+ quota > 0 && mb > get_mb_rx_last(priv)) {
+ priv->rx_next = get_mb_rx_first(priv);
goto again;
}
@@ -720,7 +813,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
u32 reg_sr = at91_read(priv, AT91_SR);
int work_done = 0;
- if (reg_sr & AT91_IRQ_MB_RX)
+ if (reg_sr & get_irq_mb_rx(priv))
work_done += at91_poll_rx(dev, quota - work_done);
/*
@@ -734,7 +827,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
if (work_done < quota) {
/* enable IRQs for frame errors and all mailboxes >= rx_next */
u32 reg_ier = AT91_IRQ_ERR_FRAME;
- reg_ier |= AT91_IRQ_MB_RX & ~AT91_MB_RX_MASK(priv->rx_next);
+ reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);
napi_complete(napi);
at91_write(priv, AT91_IER, reg_ier);
@@ -783,7 +876,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
if (likely(reg_msr & AT91_MSR_MRDY &&
~reg_msr & AT91_MSR_MABT)) {
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
- can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST);
+ can_get_echo_skb(dev, mb - get_mb_tx_first(priv));
dev->stats.tx_packets++;
}
}
@@ -793,8 +886,8 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
* we get a TX int for the last can frame directly before a
* wrap around.
*/
- if ((priv->tx_next & AT91_NEXT_MASK) != 0 ||
- (priv->tx_echo & AT91_NEXT_MASK) == 0)
+ if ((priv->tx_next & get_next_mask(priv)) != 0 ||
+ (priv->tx_echo & get_next_mask(priv)) == 0)
netif_wake_queue(dev);
}
@@ -906,6 +999,29 @@ static void at91_irq_err_state(struct net_device *dev,
at91_write(priv, AT91_IER, reg_ier);
}
+static int at91_get_state_by_bec(const struct net_device *dev,
+ enum can_state *state)
+{
+ struct can_berr_counter bec;
+ int err;
+
+ err = at91_get_berr_counter(dev, &bec);
+ if (err)
+ return err;
+
+ if (bec.txerr < 96 && bec.rxerr < 96)
+ *state = CAN_STATE_ERROR_ACTIVE;
+ else if (bec.txerr < 128 && bec.rxerr < 128)
+ *state = CAN_STATE_ERROR_WARNING;
+ else if (bec.txerr < 256 && bec.rxerr < 256)
+ *state = CAN_STATE_ERROR_PASSIVE;
+ else
+ *state = CAN_STATE_BUS_OFF;
+
+ return 0;
+}
+
+
static void at91_irq_err(struct net_device *dev)
{
struct at91_priv *priv = netdev_priv(dev);
@@ -913,21 +1029,28 @@ static void at91_irq_err(struct net_device *dev)
struct can_frame *cf;
enum can_state new_state;
u32 reg_sr;
+ int err;
- reg_sr = at91_read(priv, AT91_SR);
-
- /* we need to look at the unmasked reg_sr */
- if (unlikely(reg_sr & AT91_IRQ_BOFF))
- new_state = CAN_STATE_BUS_OFF;
- else if (unlikely(reg_sr & AT91_IRQ_ERRP))
- new_state = CAN_STATE_ERROR_PASSIVE;
- else if (unlikely(reg_sr & AT91_IRQ_WARN))
- new_state = CAN_STATE_ERROR_WARNING;
- else if (likely(reg_sr & AT91_IRQ_ERRA))
- new_state = CAN_STATE_ERROR_ACTIVE;
- else {
- netdev_err(dev, "BUG! hardware in undefined state\n");
- return;
+ if (at91_is_sam9263(priv)) {
+ reg_sr = at91_read(priv, AT91_SR);
+
+ /* we need to look at the unmasked reg_sr */
+ if (unlikely(reg_sr & AT91_IRQ_BOFF))
+ new_state = CAN_STATE_BUS_OFF;
+ else if (unlikely(reg_sr & AT91_IRQ_ERRP))
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ else if (unlikely(reg_sr & AT91_IRQ_WARN))
+ new_state = CAN_STATE_ERROR_WARNING;
+ else if (likely(reg_sr & AT91_IRQ_ERRA))
+ new_state = CAN_STATE_ERROR_ACTIVE;
+ else {
+ netdev_err(dev, "BUG! hardware in undefined state\n");
+ return;
+ }
+ } else {
+ err = at91_get_state_by_bec(dev, &new_state);
+ if (err)
+ return;
}
/* state hasn't changed */
@@ -968,19 +1091,19 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
handled = IRQ_HANDLED;
/* Receive or error interrupt? -> napi */
- if (reg_sr & (AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME)) {
+ if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {
/*
* The error bits are clear on read,
* save for later use.
*/
priv->reg_sr = reg_sr;
at91_write(priv, AT91_IDR,
- AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME);
+ get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME);
napi_schedule(&priv->napi);
}
/* Transmission complete interrupt */
- if (reg_sr & AT91_IRQ_MB_TX)
+ if (reg_sr & get_irq_mb_tx(priv))
at91_irq_tx(dev, reg_sr);
at91_irq_err(dev);
@@ -1123,6 +1246,8 @@ static struct attribute_group at91_sysfs_attr_group = {
static int __devinit at91_can_probe(struct platform_device *pdev)
{
+ const struct at91_devtype_data *devtype_data;
+ enum at91_devtype devtype;
struct net_device *dev;
struct at91_priv *priv;
struct resource *res;
@@ -1130,6 +1255,9 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
void __iomem *addr;
int err, irq;
+ devtype = pdev->id_entry->driver_data;
+ devtype_data = &at91_devtype_data[devtype];
+
clk = clk_get(&pdev->dev, "can_clk");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "no clock defined\n");
@@ -1157,7 +1285,8 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
goto exit_release;
}
- dev = alloc_candev(sizeof(struct at91_priv), AT91_MB_TX_NUM);
+ dev = alloc_candev(sizeof(struct at91_priv),
+ 1 << devtype_data->tx_shift);
if (!dev) {
err = -ENOMEM;
goto exit_iounmap;
@@ -1166,7 +1295,6 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
dev->netdev_ops = &at91_netdev_ops;
dev->irq = irq;
dev->flags |= IFF_ECHO;
- dev->sysfs_groups[0] = &at91_sysfs_attr_group;
priv = netdev_priv(dev);
priv->can.clock.freq = clk_get_rate(clk);
@@ -1174,13 +1302,18 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
priv->can.do_set_mode = at91_set_mode;
priv->can.do_get_berr_counter = at91_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
- priv->reg_base = addr;
priv->dev = dev;
+ priv->reg_base = addr;
+ priv->devtype_data = *devtype_data;
+ priv->devtype_data.type = devtype;
priv->clk = clk;
priv->pdata = pdev->dev.platform_data;
priv->mb0_id = 0x7ff;
- netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
+ netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv));
+
+ if (at91_is_sam9263(priv))
+ dev->sysfs_groups[0] = &at91_sysfs_attr_group;
dev_set_drvdata(&pdev->dev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -1230,13 +1363,26 @@ static int __devexit at91_can_remove(struct platform_device *pdev)
return 0;
}
+static const struct platform_device_id at91_can_id_table[] = {
+ {
+ .name = "at91_can",
+ .driver_data = AT91_DEVTYPE_SAM9263,
+ }, {
+ .name = "at91sam9x5_can",
+ .driver_data = AT91_DEVTYPE_SAM9X5,
+ }, {
+ /* sentinel */
+ }
+};
+
static struct platform_driver at91_can_driver = {
- .probe = at91_can_probe,
- .remove = __devexit_p(at91_can_remove),
- .driver = {
- .name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
+ .probe = at91_can_probe,
+ .remove = __devexit_p(at91_can_remove),
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
},
+ .id_table = at91_can_id_table,
};
static int __init at91_can_module_init(void)
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index b6e890d28366..a1c5abc38cd2 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -79,8 +79,8 @@ static int bfin_can_set_bittiming(struct net_device *dev)
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
timing |= SAM;
- bfin_write16(&reg->clock, clk);
- bfin_write16(&reg->timing, timing);
+ bfin_write(&reg->clock, clk);
+ bfin_write(&reg->timing, timing);
dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n",
clk, timing);
@@ -96,16 +96,16 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
int i;
/* disable interrupts */
- bfin_write16(&reg->mbim1, 0);
- bfin_write16(&reg->mbim2, 0);
- bfin_write16(&reg->gim, 0);
+ bfin_write(&reg->mbim1, 0);
+ bfin_write(&reg->mbim2, 0);
+ bfin_write(&reg->gim, 0);
/* reset can and enter configuration mode */
- bfin_write16(&reg->control, SRS | CCR);
+ bfin_write(&reg->control, SRS | CCR);
SSYNC();
- bfin_write16(&reg->control, CCR);
+ bfin_write(&reg->control, CCR);
SSYNC();
- while (!(bfin_read16(&reg->control) & CCA)) {
+ while (!(bfin_read(&reg->control) & CCA)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -119,33 +119,33 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
* by writing to CAN Mailbox Configuration Registers 1 and 2
* For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
*/
- bfin_write16(&reg->mc1, 0);
- bfin_write16(&reg->mc2, 0);
+ bfin_write(&reg->mc1, 0);
+ bfin_write(&reg->mc2, 0);
/* Set Mailbox Direction */
- bfin_write16(&reg->md1, 0xFFFF); /* mailbox 1-16 are RX */
- bfin_write16(&reg->md2, 0); /* mailbox 17-32 are TX */
+ bfin_write(&reg->md1, 0xFFFF); /* mailbox 1-16 are RX */
+ bfin_write(&reg->md2, 0); /* mailbox 17-32 are TX */
/* RECEIVE_STD_CHL */
for (i = 0; i < 2; i++) {
- bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
- bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
- bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
- bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
- bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
+ bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
+ bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
+ bfin_write(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
+ bfin_write(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
+ bfin_write(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
}
/* RECEIVE_EXT_CHL */
for (i = 0; i < 2; i++) {
- bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
- bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
- bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
- bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
- bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
+ bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
+ bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
+ bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
+ bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
+ bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
}
- bfin_write16(&reg->mc2, BIT(TRANSMIT_CHL - 16));
- bfin_write16(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+ bfin_write(&reg->mc2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
SSYNC();
priv->can.state = CAN_STATE_STOPPED;
@@ -160,9 +160,9 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
/*
* leave configuration mode
*/
- bfin_write16(&reg->control, bfin_read16(&reg->control) & ~CCR);
+ bfin_write(&reg->control, bfin_read(&reg->control) & ~CCR);
- while (bfin_read16(&reg->status) & CCA) {
+ while (bfin_read(&reg->status) & CCA) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -174,25 +174,25 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
/*
* clear _All_ tx and rx interrupts
*/
- bfin_write16(&reg->mbtif1, 0xFFFF);
- bfin_write16(&reg->mbtif2, 0xFFFF);
- bfin_write16(&reg->mbrif1, 0xFFFF);
- bfin_write16(&reg->mbrif2, 0xFFFF);
+ bfin_write(&reg->mbtif1, 0xFFFF);
+ bfin_write(&reg->mbtif2, 0xFFFF);
+ bfin_write(&reg->mbrif1, 0xFFFF);
+ bfin_write(&reg->mbrif2, 0xFFFF);
/*
* clear global interrupt status register
*/
- bfin_write16(&reg->gis, 0x7FF); /* overwrites with '1' */
+ bfin_write(&reg->gis, 0x7FF); /* overwrites with '1' */
/*
* Initialize Interrupts
* - set bits in the mailbox interrupt mask register
* - global interrupt mask
*/
- bfin_write16(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
- bfin_write16(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+ bfin_write(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
- bfin_write16(&reg->gim, EPIM | BOIM | RMLIM);
+ bfin_write(&reg->gim, EPIM | BOIM | RMLIM);
SSYNC();
}
@@ -242,37 +242,28 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* fill id */
if (id & CAN_EFF_FLAG) {
- bfin_write16(&reg->chl[TRANSMIT_CHL].id0, id);
- if (id & CAN_RTR_FLAG)
- writew(((id & 0x1FFF0000) >> 16) | IDE | AME | RTR,
- &reg->chl[TRANSMIT_CHL].id1);
- else
- writew(((id & 0x1FFF0000) >> 16) | IDE | AME,
- &reg->chl[TRANSMIT_CHL].id1);
-
- } else {
- if (id & CAN_RTR_FLAG)
- writew((id << 2) | AME | RTR,
- &reg->chl[TRANSMIT_CHL].id1);
- else
- bfin_write16(&reg->chl[TRANSMIT_CHL].id1,
- (id << 2) | AME);
- }
+ bfin_write(&reg->chl[TRANSMIT_CHL].id0, id);
+ val = ((id & 0x1FFF0000) >> 16) | IDE;
+ } else
+ val = (id << 2);
+ if (id & CAN_RTR_FLAG)
+ val |= RTR;
+ bfin_write(&reg->chl[TRANSMIT_CHL].id1, val | AME);
/* fill payload */
for (i = 0; i < 8; i += 2) {
val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
((6 - i) < dlc ? (data[6 - i] << 8) : 0);
- bfin_write16(&reg->chl[TRANSMIT_CHL].data[i], val);
+ bfin_write(&reg->chl[TRANSMIT_CHL].data[i], val);
}
/* fill data length code */
- bfin_write16(&reg->chl[TRANSMIT_CHL].dlc, dlc);
+ bfin_write(&reg->chl[TRANSMIT_CHL].dlc, dlc);
can_put_echo_skb(skb, dev, 0);
/* set transmit request */
- bfin_write16(&reg->trs2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(&reg->trs2, BIT(TRANSMIT_CHL - 16));
return 0;
}
@@ -295,26 +286,26 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc)
/* get id */
if (isrc & BIT(RECEIVE_EXT_CHL)) {
/* extended frame format (EFF) */
- cf->can_id = ((bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id1)
+ cf->can_id = ((bfin_read(&reg->chl[RECEIVE_EXT_CHL].id1)
& 0x1FFF) << 16)
- + bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id0);
+ + bfin_read(&reg->chl[RECEIVE_EXT_CHL].id0);
cf->can_id |= CAN_EFF_FLAG;
obj = RECEIVE_EXT_CHL;
} else {
/* standard frame format (SFF) */
- cf->can_id = (bfin_read16(&reg->chl[RECEIVE_STD_CHL].id1)
+ cf->can_id = (bfin_read(&reg->chl[RECEIVE_STD_CHL].id1)
& 0x1ffc) >> 2;
obj = RECEIVE_STD_CHL;
}
- if (bfin_read16(&reg->chl[obj].id1) & RTR)
+ if (bfin_read(&reg->chl[obj].id1) & RTR)
cf->can_id |= CAN_RTR_FLAG;
/* get data length code */
- cf->can_dlc = get_can_dlc(bfin_read16(&reg->chl[obj].dlc) & 0xF);
+ cf->can_dlc = get_can_dlc(bfin_read(&reg->chl[obj].dlc) & 0xF);
/* get payload */
for (i = 0; i < 8; i += 2) {
- val = bfin_read16(&reg->chl[obj].data[i]);
+ val = bfin_read(&reg->chl[obj].data[i]);
cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
}
@@ -368,7 +359,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
state == CAN_STATE_ERROR_PASSIVE)) {
- u16 cec = bfin_read16(&reg->cec);
+ u16 cec = bfin_read(&reg->cec);
u8 rxerr = cec;
u8 txerr = cec >> 8;
@@ -419,23 +410,23 @@ irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
struct net_device_stats *stats = &dev->stats;
u16 status, isrc;
- if ((irq == priv->tx_irq) && bfin_read16(&reg->mbtif2)) {
+ if ((irq == priv->tx_irq) && bfin_read(&reg->mbtif2)) {
/* transmission complete interrupt */
- bfin_write16(&reg->mbtif2, 0xFFFF);
+ bfin_write(&reg->mbtif2, 0xFFFF);
stats->tx_packets++;
- stats->tx_bytes += bfin_read16(&reg->chl[TRANSMIT_CHL].dlc);
+ stats->tx_bytes += bfin_read(&reg->chl[TRANSMIT_CHL].dlc);
can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
- } else if ((irq == priv->rx_irq) && bfin_read16(&reg->mbrif1)) {
+ } else if ((irq == priv->rx_irq) && bfin_read(&reg->mbrif1)) {
/* receive interrupt */
- isrc = bfin_read16(&reg->mbrif1);
- bfin_write16(&reg->mbrif1, 0xFFFF);
+ isrc = bfin_read(&reg->mbrif1);
+ bfin_write(&reg->mbrif1, 0xFFFF);
bfin_can_rx(dev, isrc);
- } else if ((irq == priv->err_irq) && bfin_read16(&reg->gis)) {
+ } else if ((irq == priv->err_irq) && bfin_read(&reg->gis)) {
/* error interrupt */
- isrc = bfin_read16(&reg->gis);
- status = bfin_read16(&reg->esr);
- bfin_write16(&reg->gis, 0x7FF);
+ isrc = bfin_read(&reg->gis);
+ status = bfin_read(&reg->esr);
+ bfin_write(&reg->gis, 0x7FF);
bfin_can_err(dev, isrc, status);
} else {
return IRQ_NONE;
@@ -640,9 +631,9 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
if (netif_running(dev)) {
/* enter sleep mode */
- bfin_write16(&reg->control, bfin_read16(&reg->control) | SMR);
+ bfin_write(&reg->control, bfin_read(&reg->control) | SMR);
SSYNC();
- while (!(bfin_read16(&reg->intr) & SMACK)) {
+ while (!(bfin_read(&reg->intr) & SMACK)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -663,7 +654,7 @@ static int bfin_can_resume(struct platform_device *pdev)
if (netif_running(dev)) {
/* leave sleep mode */
- bfin_write16(&reg->intr, 0);
+ bfin_write(&reg->intr, 0);
SSYNC();
}
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 7e5cc0bd913d..536bda072a16 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -26,7 +26,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -34,7 +33,6 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/list.h>
-#include <linux/delay.h>
#include <linux/io.h>
#include <linux/can.h>
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index cc90824f2c9c..0b5c6f8bdd34 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -20,7 +20,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -28,7 +27,6 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/list.h>
-#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index d0f8c7e67e7d..9bf1116e5b5e 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -208,7 +208,7 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt)
return 0;
}
-int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
+static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
{
struct can_priv *priv = netdev_priv(dev);
int err;
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index f1942cab35f6..32778d56d330 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -22,6 +22,7 @@
#include <linux/can/error.h>
#include <linux/mfd/janz.h>
+#include <asm/io.h>
/* the DPM has 64k of memory, organized into 256x 256 byte pages */
#define DPM_NUM_PAGES 256
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index de8e778f6832..78bd4ecac140 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -47,6 +47,7 @@
#ifndef SJA1000_DEV_H
#define SJA1000_DEV_H
+#include <linux/irqreturn.h>
#include <linux/can/dev.h>
#include <linux/can/platform/sja1000.h>
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 9793df6e3455..cee6ba2b8b58 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -38,6 +38,7 @@
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
+#include <linux/io.h>
#include <linux/can/dev.h>
#include <linux/of_platform.h>
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 1b49df6b2470..f523f1cc5142 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -56,6 +56,7 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/can.h>
static __initdata const char banner[] =
@@ -95,10 +96,6 @@ struct slcan {
unsigned long flags; /* Flag values/ mode etc */
#define SLF_INUSE 0 /* Channel in use */
#define SLF_ERROR 1 /* Parity, etc. error */
-
- unsigned char leased;
- dev_t line;
- pid_t pid;
};
static struct net_device **slcan_devs;
@@ -142,21 +139,6 @@ static struct net_device **slcan_devs;
* STANDARD SLCAN DECAPSULATION *
************************************************************************/
-static int asc2nibble(char c)
-{
-
- if ((c >= '0') && (c <= '9'))
- return c - '0';
-
- if ((c >= 'A') && (c <= 'F'))
- return c - 'A' + 10;
-
- if ((c >= 'a') && (c <= 'f'))
- return c - 'a' + 10;
-
- return 16; /* error */
-}
-
/* Send one completely decapsulated can_frame to the network layer */
static void slc_bump(struct slcan *sl)
{
@@ -195,18 +177,16 @@ static void slc_bump(struct slcan *sl)
*(u64 *) (&cf.data) = 0; /* clear payload */
for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
-
- tmp = asc2nibble(sl->rbuff[dlc_pos++]);
- if (tmp > 0x0F)
+ tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
+ if (tmp < 0)
return;
cf.data[i] = (tmp << 4);
- tmp = asc2nibble(sl->rbuff[dlc_pos++]);
- if (tmp > 0x0F)
+ tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
+ if (tmp < 0)
return;
cf.data[i] |= tmp;
}
-
skb = dev_alloc_skb(sizeof(struct can_frame));
if (!skb)
return;
@@ -462,7 +442,7 @@ static void slc_sync(void)
break;
sl = netdev_priv(dev);
- if (sl->tty || sl->leased)
+ if (sl->tty)
continue;
if (dev->flags & IFF_UP)
dev_close(dev);
@@ -473,12 +453,10 @@ static void slc_sync(void)
static struct slcan *slc_alloc(dev_t line)
{
int i;
+ char name[IFNAMSIZ];
struct net_device *dev = NULL;
struct slcan *sl;
- if (slcan_devs == NULL)
- return NULL; /* Master array missing ! */
-
for (i = 0; i < maxdev; i++) {
dev = slcan_devs[i];
if (dev == NULL)
@@ -490,25 +468,12 @@ static struct slcan *slc_alloc(dev_t line)
if (i >= maxdev)
return NULL;
- if (dev) {
- sl = netdev_priv(dev);
- if (test_bit(SLF_INUSE, &sl->flags)) {
- unregister_netdevice(dev);
- dev = NULL;
- slcan_devs[i] = NULL;
- }
- }
-
- if (!dev) {
- char name[IFNAMSIZ];
- sprintf(name, "slcan%d", i);
-
- dev = alloc_netdev(sizeof(*sl), name, slc_setup);
- if (!dev)
- return NULL;
- dev->base_addr = i;
- }
+ sprintf(name, "slcan%d", i);
+ dev = alloc_netdev(sizeof(*sl), name, slc_setup);
+ if (!dev)
+ return NULL;
+ dev->base_addr = i;
sl = netdev_priv(dev);
/* Initialize channel control data */
@@ -565,8 +530,6 @@ static int slcan_open(struct tty_struct *tty)
sl->tty = tty;
tty->disc_data = sl;
- sl->line = tty_devnum(tty);
- sl->pid = current->pid;
if (!test_bit(SLF_INUSE, &sl->flags)) {
/* Perform the low-level SLCAN initialization. */
@@ -617,8 +580,6 @@ static void slcan_close(struct tty_struct *tty)
tty->disc_data = NULL;
sl->tty = NULL;
- if (!sl->leased)
- sl->line = 0;
/* Flush network side */
unregister_netdev(sl->dev);
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
index b520784fb197..310596175676 100644
--- a/drivers/net/can/softing/softing_fw.c
+++ b/drivers/net/can/softing/softing_fw.c
@@ -20,6 +20,7 @@
#include <linux/firmware.h>
#include <linux/sched.h>
#include <asm/div64.h>
+#include <asm/io.h>
#include "softing.h"
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index 60a49e5a2a53..09a8b86cf1ac 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -17,10 +17,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "softing.h"
@@ -799,7 +799,7 @@ static __devinit int softing_pdev_probe(struct platform_device *pdev)
if (!pres)
goto platform_resource_failed;
card->dpram_phys = pres->start;
- card->dpram_size = pres->end - pres->start + 1;
+ card->dpram_size = resource_size(pres);
card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size);
if (!card->dpram) {
dev_alert(&card->pdev->dev, "dpram ioremap failed\n");
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 22ce03e55b83..646c86bcc545 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -75,6 +75,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/ioport.h>
#include <linux/pci.h>
@@ -97,7 +98,7 @@
#include <net/checksum.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/byteorder.h>
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h
index c26d863e1697..5ccbed1784d2 100644
--- a/drivers/net/chelsio/common.h
+++ b/drivers/net/chelsio/common.h
@@ -240,8 +240,6 @@ struct adapter {
struct work_struct ext_intr_handler_task;
struct adapter_params params;
- struct vlan_group *vlan_grp;
-
/* Terminator modules. */
struct sge *sge;
struct peespi *espi;
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index b422d83f5343..3edbbc4c5112 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -263,6 +263,8 @@ static int cxgb_open(struct net_device *dev)
if (!other_ports && adapter->params.stats_update_period)
schedule_mac_stats_update(adapter,
adapter->params.stats_update_period);
+
+ t1_vlan_mode(adapter, dev->features);
return 0;
}
@@ -849,19 +851,30 @@ static int t1_set_mac_addr(struct net_device *dev, void *p)
return 0;
}
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-static void t1_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
+static u32 t1_fix_features(struct net_device *dev, u32 features)
{
- struct adapter *adapter = dev->ml_priv;
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
- spin_lock_irq(&adapter->async_lock);
- adapter->vlan_grp = grp;
- t1_set_vlan_accel(adapter, grp != NULL);
- spin_unlock_irq(&adapter->async_lock);
+ return features;
}
-#endif
+static int t1_set_features(struct net_device *dev, u32 features)
+{
+ u32 changed = dev->features ^ features;
+ struct adapter *adapter = dev->ml_priv;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ t1_vlan_mode(adapter, features);
+
+ return 0;
+}
#ifdef CONFIG_NET_POLL_CONTROLLER
static void t1_netpoll(struct net_device *dev)
{
@@ -955,9 +968,8 @@ static const struct net_device_ops cxgb_netdev_ops = {
.ndo_do_ioctl = t1_ioctl,
.ndo_change_mtu = t1_change_mtu,
.ndo_set_mac_address = t1_set_mac_addr,
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
- .ndo_vlan_rx_register = t1_vlan_rx_register,
-#endif
+ .ndo_fix_features = t1_fix_features,
+ .ndo_set_features = t1_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = t1_netpoll,
#endif
@@ -1080,10 +1092,9 @@ static int __devinit init_one(struct pci_dev *pdev,
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
if (vlan_tso_capable(adapter)) {
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
netdev->features |=
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
+ netdev->hw_features |= NETIF_F_HW_VLAN_RX;
/* T204: disable TSO */
if (!(is_T2(adapter)) || bi->port_number != 4) {
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 58380d240619..e9a03fffef15 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -742,13 +742,14 @@ static inline void setup_ring_params(struct adapter *adapter, u64 addr,
/*
* Enable/disable VLAN acceleration.
*/
-void t1_set_vlan_accel(struct adapter *adapter, int on_off)
+void t1_vlan_mode(struct adapter *adapter, u32 features)
{
struct sge *sge = adapter->sge;
- sge->sge_control &= ~F_VLAN_XTRACT;
- if (on_off)
+ if (features & NETIF_F_HW_VLAN_RX)
sge->sge_control |= F_VLAN_XTRACT;
+ else
+ sge->sge_control &= ~F_VLAN_XTRACT;
if (adapter->open_device_map) {
writel(sge->sge_control, adapter->regs + A_SG_CONTROL);
readl(adapter->regs + A_SG_CONTROL); /* flush */
@@ -1397,12 +1398,11 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
} else
skb_checksum_none_assert(skb);
- if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
+ if (p->vlan_valid) {
st->vlan_xtract++;
- vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
- ntohs(p->vlan));
- } else
- netif_receive_skb(skb);
+ __vlan_hwaccel_put_tag(skb, ntohs(p->vlan));
+ }
+ netif_receive_skb(skb);
}
/*
@@ -1875,13 +1875,11 @@ netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
cpl->iff = dev->if_port;
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
if (vlan_tx_tag_present(skb)) {
cpl->vlan_valid = 1;
cpl->vlan = htons(vlan_tx_tag_get(skb));
st->vlan_insert++;
} else
-#endif
cpl->vlan_valid = 0;
send:
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 00cc37fc1f6f..e03980bcdd65 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -79,7 +79,7 @@ irqreturn_t t1_interrupt(int irq, void *cookie);
int t1_poll(struct napi_struct *, int);
netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
-void t1_set_vlan_accel(struct adapter *adapter, int on_off);
+void t1_vlan_mode(struct adapter *adapter, u32 features);
void t1_sge_start(struct sge *);
void t1_sge_stop(struct sge *);
int t1_sge_intr_error_handler(struct sge *);
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 11a92afdf982..94a2e541006d 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -1,6 +1,6 @@
/* cnic.c: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 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
@@ -28,6 +28,7 @@
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/prefetch.h>
+#include <linux/random.h>
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define BCM_VLAN 1
#endif
@@ -327,7 +328,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
msleep(100);
retry++;
}
- return 0;
+ return rc;
}
static void cnic_cm_upcall(struct cnic_local *, struct cnic_sock *, u8);
@@ -605,11 +606,12 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
}
EXPORT_SYMBOL(cnic_unregister_driver);
-static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id)
+static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id,
+ u32 next)
{
id_tbl->start = start_id;
id_tbl->max = size;
- id_tbl->next = 0;
+ id_tbl->next = next;
spin_lock_init(&id_tbl->lock);
id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);
if (!id_tbl->table)
@@ -835,7 +837,6 @@ static void cnic_free_resc(struct cnic_dev *dev)
cp->ctx_blks = 0;
cnic_free_dma(dev, &cp->gbl_buf_info);
- cnic_free_dma(dev, &cp->conn_buf_info);
cnic_free_dma(dev, &cp->kwq_info);
cnic_free_dma(dev, &cp->kwq_16_data_info);
cnic_free_dma(dev, &cp->kcq2.dma);
@@ -899,24 +900,56 @@ static int cnic_alloc_context(struct cnic_dev *dev)
return 0;
}
-static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info)
+static u16 cnic_bnx2_next_idx(u16 idx)
+{
+ return idx + 1;
+}
+
+static u16 cnic_bnx2_hw_idx(u16 idx)
+{
+ return idx;
+}
+
+static u16 cnic_bnx2x_next_idx(u16 idx)
{
- int err, i, is_bnx2 = 0;
+ idx++;
+ if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
+ idx++;
+
+ return idx;
+}
+
+static u16 cnic_bnx2x_hw_idx(u16 idx)
+{
+ if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
+ idx++;
+ return idx;
+}
+
+static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info,
+ bool use_pg_tbl)
+{
+ int err, i, use_page_tbl = 0;
struct kcqe **kcq;
- if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags))
- is_bnx2 = 1;
+ if (use_pg_tbl)
+ use_page_tbl = 1;
- err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, is_bnx2);
+ err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, use_page_tbl);
if (err)
return err;
kcq = (struct kcqe **) info->dma.pg_arr;
info->kcq = kcq;
- if (is_bnx2)
+ info->next_idx = cnic_bnx2_next_idx;
+ info->hw_idx = cnic_bnx2_hw_idx;
+ if (use_pg_tbl)
return 0;
+ info->next_idx = cnic_bnx2x_next_idx;
+ info->hw_idx = cnic_bnx2x_hw_idx;
+
for (i = 0; i < KCQ_PAGE_CNT; i++) {
struct bnx2x_bd_chain_next *next =
(struct bnx2x_bd_chain_next *) &kcq[i][MAX_KCQE_CNT];
@@ -1059,7 +1092,7 @@ static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
goto error;
cp->kwq = (struct kwqe **) cp->kwq_info.pg_arr;
- ret = cnic_alloc_kcq(dev, &cp->kcq1);
+ ret = cnic_alloc_kcq(dev, &cp->kcq1, true);
if (ret)
goto error;
@@ -1139,25 +1172,17 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
cp->iro_arr = ethdev->iro_arr;
- cp->max_cid_space = MAX_ISCSI_TBL_SZ + BNX2X_FCOE_NUM_CONNECTIONS;
+ cp->max_cid_space = MAX_ISCSI_TBL_SZ;
cp->iscsi_start_cid = start_cid;
cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;
cp->fcoe_init_cid = ethdev->fcoe_init_cid;
if (!cp->fcoe_init_cid)
cp->fcoe_init_cid = 0x10;
}
- if (start_cid < BNX2X_ISCSI_START_CID) {
- u32 delta = BNX2X_ISCSI_START_CID - start_cid;
-
- cp->iscsi_start_cid = BNX2X_ISCSI_START_CID;
- cp->fcoe_start_cid += delta;
- cp->max_cid_space += delta;
- }
-
cp->iscsi_tbl = kzalloc(sizeof(struct cnic_iscsi) * MAX_ISCSI_TBL_SZ,
GFP_KERNEL);
if (!cp->iscsi_tbl)
@@ -1195,22 +1220,16 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
j++;
}
- ret = cnic_alloc_kcq(dev, &cp->kcq1);
+ ret = cnic_alloc_kcq(dev, &cp->kcq1, false);
if (ret)
goto error;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
- ret = cnic_alloc_kcq(dev, &cp->kcq2);
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ ret = cnic_alloc_kcq(dev, &cp->kcq2, true);
if (ret)
goto error;
}
- pages = PAGE_ALIGN(BNX2X_ISCSI_NUM_CONNECTIONS *
- BNX2X_ISCSI_CONN_BUF_SIZE) / PAGE_SIZE;
- ret = cnic_alloc_dma(dev, &cp->conn_buf_info, pages, 1);
- if (ret)
- goto error;
-
pages = PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / PAGE_SIZE;
ret = cnic_alloc_dma(dev, &cp->gbl_buf_info, pages, 0);
if (ret)
@@ -1577,6 +1596,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
struct iscsi_context *ictx;
struct regpair context_addr;
int i, j, n = 2, n_max;
+ u8 port = CNIC_PORT(cp);
ctx->ctx_flags = 0;
if (!req2->num_additional_wqes)
@@ -1628,6 +1648,17 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA;
ictx->xstorm_st_context.iscsi.flags.flags |=
XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T;
+ ictx->xstorm_st_context.common.ethernet.reserved_vlan_type =
+ ETH_P_8021Q;
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
+ cp->port_mode == CHIP_2_PORT_MODE) {
+
+ port = 0;
+ }
+ ictx->xstorm_st_context.common.flags =
+ 1 << XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT;
+ ictx->xstorm_st_context.common.flags =
+ port << XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT;
ictx->tstorm_st_context.iscsi.hdr_bytes_2_fetch = ISCSI_HEADER_SIZE;
/* TSTORM requires the base address of RQ DB & not PTE */
@@ -1843,8 +1874,11 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
hw_cid, NONE_CONNECTION_TYPE, &l5_data);
- if (ret == 0)
+ if (ret == 0) {
wait_event(ctx->waitq, ctx->wait_cond);
+ if (unlikely(test_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags)))
+ return -EBUSY;
+ }
return ret;
}
@@ -1879,8 +1913,10 @@ static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
skip_cfc_delete:
cnic_free_bnx2x_conn_resc(dev, l5_cid);
- atomic_dec(&cp->iscsi_conn);
- clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ if (!ret) {
+ atomic_dec(&cp->iscsi_conn);
+ clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ }
destroy_reply:
memset(&kcqe, 0, sizeof(kcqe));
@@ -1939,8 +1975,6 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
tstorm_buf->ka_interval = kwqe3->ka_interval;
tstorm_buf->ka_max_probe_count = kwqe3->ka_max_probe_count;
}
- tstorm_buf->rcv_buf = kwqe3->rcv_buf;
- tstorm_buf->snd_buf = kwqe3->snd_buf;
tstorm_buf->max_rt_time = 0xffffffff;
}
@@ -1969,15 +2003,14 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[4]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
+ TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
+ TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[2]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 2,
- mac[1]);
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[1]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 3,
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[0]);
}
@@ -2156,7 +2189,7 @@ static int cnic_bnx2x_fcoe_stat(struct cnic_dev *dev, struct kwqe *kwqe)
memset(fcoe_stat, 0, sizeof(*fcoe_stat));
memcpy(&fcoe_stat->stat_kwqe, req, sizeof(*req));
- ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT, cid,
+ ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT_FUNC, cid,
FCOE_CONNECTION_TYPE, &l5_data);
return ret;
}
@@ -2201,12 +2234,9 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
memcpy(&fcoe_init->init_kwqe1, req1, sizeof(*req1));
memcpy(&fcoe_init->init_kwqe2, req2, sizeof(*req2));
memcpy(&fcoe_init->init_kwqe3, req3, sizeof(*req3));
- fcoe_init->eq_addr.lo = cp->kcq2.dma.pg_map_arr[0] & 0xffffffff;
- fcoe_init->eq_addr.hi = (u64) cp->kcq2.dma.pg_map_arr[0] >> 32;
- fcoe_init->eq_next_page_addr.lo =
- cp->kcq2.dma.pg_map_arr[1] & 0xffffffff;
- fcoe_init->eq_next_page_addr.hi =
- (u64) cp->kcq2.dma.pg_map_arr[1] >> 32;
+ fcoe_init->eq_pbl_base.lo = cp->kcq2.dma.pgtbl_map & 0xffffffff;
+ fcoe_init->eq_pbl_base.hi = (u64) cp->kcq2.dma.pgtbl_map >> 32;
+ fcoe_init->eq_pbl_size = cp->kcq2.dma.num_pages;
fcoe_init->sb_num = cp->status_blk_num;
fcoe_init->eq_prod = MAX_KCQ_IDX;
@@ -2214,7 +2244,7 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
cp->kcq2.sw_prod_idx = 0;
cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
- ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT, cid,
+ ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT_FUNC, cid,
FCOE_CONNECTION_TYPE, &l5_data);
*work = 3;
return ret;
@@ -2418,6 +2448,30 @@ static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
return ret;
}
+static void cnic_bnx2x_delete_wait(struct cnic_dev *dev, u32 start_cid)
+{
+ struct cnic_local *cp = dev->cnic_priv;
+ u32 i;
+
+ for (i = start_cid; i < cp->max_cid_space; i++) {
+ struct cnic_context *ctx = &cp->ctx_tbl[i];
+ int j;
+
+ while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+ msleep(10);
+
+ for (j = 0; j < 5; j++) {
+ if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+ break;
+ msleep(20);
+ }
+
+ if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+ netdev_warn(dev->netdev, "CID %x not deleted\n",
+ ctx->cid);
+ }
+}
+
static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
{
struct fcoe_kwqe_destroy *req;
@@ -2426,11 +2480,13 @@ static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
int ret;
u32 cid;
+ cnic_bnx2x_delete_wait(dev, MAX_ISCSI_TBL_SZ);
+
req = (struct fcoe_kwqe_destroy *) kwqe;
cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
memset(&l5_data, 0, sizeof(l5_data));
- ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY, cid,
+ ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY_FUNC, cid,
FCOE_CONNECTION_TYPE, &l5_data);
return ret;
}
@@ -2511,7 +2567,7 @@ static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev,
if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
return -EAGAIN; /* bnx2 is down */
- if (BNX2X_CHIP_NUM(cp->chip_id) == BNX2X_CHIP_NUM_57710)
+ if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
return -EINVAL;
for (i = 0; i < num_wqes; ) {
@@ -2651,32 +2707,6 @@ end:
cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);
}
-static u16 cnic_bnx2_next_idx(u16 idx)
-{
- return idx + 1;
-}
-
-static u16 cnic_bnx2_hw_idx(u16 idx)
-{
- return idx;
-}
-
-static u16 cnic_bnx2x_next_idx(u16 idx)
-{
- idx++;
- if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
- idx++;
-
- return idx;
-}
-
-static u16 cnic_bnx2x_hw_idx(u16 idx)
-{
- if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
- idx++;
- return idx;
-}
-
static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
{
struct cnic_local *cp = dev->cnic_priv;
@@ -2687,12 +2717,12 @@ static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
i = ri = last = info->sw_prod_idx;
ri &= MAX_KCQ_IDX;
hw_prod = *info->hw_prod_idx_ptr;
- hw_prod = cp->hw_idx(hw_prod);
+ hw_prod = info->hw_idx(hw_prod);
while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {
kcqe = &info->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
cp->completed_kcq[kcqe_cnt++] = kcqe;
- i = cp->next_idx(i);
+ i = info->next_idx(i);
ri = i & MAX_KCQ_IDX;
if (likely(!(kcqe->kcqe_op_flag & KCQE_FLAGS_NEXT))) {
last_cnt = kcqe_cnt;
@@ -2778,13 +2808,10 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)
/* Tell compiler that status_blk fields can change. */
barrier();
- if (status_idx != *cp->kcq1.status_idx_ptr) {
- status_idx = (u16) *cp->kcq1.status_idx_ptr;
- /* status block index must be read first */
- rmb();
- cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
- } else
- break;
+ status_idx = (u16) *cp->kcq1.status_idx_ptr;
+ /* status block index must be read first */
+ rmb();
+ cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
}
CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
@@ -2908,8 +2935,6 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)
/* Tell compiler that sblk fields can change. */
barrier();
- if (last_status == *info->status_idx_ptr)
- break;
last_status = *info->status_idx_ptr;
/* status block index must be read before reading the KCQ */
@@ -2933,7 +2958,7 @@ static void cnic_service_bnx2x_bh(unsigned long data)
CNIC_WR16(dev, cp->kcq1.io_addr,
cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
- if (!BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
status_idx, IGU_INT_ENABLE, 1);
break;
@@ -3052,13 +3077,21 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info)
break;
}
case CNIC_CTL_COMPLETION_CMD: {
- u32 cid = BNX2X_SW_CID(info->data.comp.cid);
+ struct cnic_ctl_completion *comp = &info->data.comp;
+ u32 cid = BNX2X_SW_CID(comp->cid);
u32 l5_cid;
struct cnic_local *cp = dev->cnic_priv;
if (cnic_get_l5_cid(cp, cid, &l5_cid) == 0) {
struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
+ if (unlikely(comp->error)) {
+ set_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags);
+ netdev_err(dev->netdev,
+ "CID %x CFC delete comp error %x\n",
+ cid, comp->error);
+ }
+
ctx->wait_cond = 1;
wake_up(&ctx->waitq);
}
@@ -3772,7 +3805,13 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
break;
case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED:
- cnic_cm_upcall(cp, csk, opcode);
+ /* after we already sent CLOSE_REQ */
+ if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) &&
+ !test_bit(SK_F_OFFLD_COMPLETE, &csk->flags) &&
+ csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)
+ cp->close_conn(csk, L4_KCQE_OPCODE_VALUE_RESET_COMP);
+ else
+ cnic_cm_upcall(cp, csk, opcode);
break;
}
csk_put(csk);
@@ -3803,14 +3842,17 @@ static void cnic_cm_free_mem(struct cnic_dev *dev)
static int cnic_cm_alloc_mem(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ u32 port_id;
cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ,
GFP_KERNEL);
if (!cp->csk_tbl)
return -ENOMEM;
+ port_id = random32();
+ port_id %= CNIC_LOCAL_PORT_RANGE;
if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE,
- CNIC_LOCAL_PORT_MIN)) {
+ CNIC_LOCAL_PORT_MIN, port_id)) {
cnic_cm_free_mem(dev);
return -ENOMEM;
}
@@ -3826,12 +3868,14 @@ static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode)
}
/* 1. If event opcode matches the expected event in csk->state
- * 2. If the expected event is CLOSE_COMP, we accept any event
+ * 2. If the expected event is CLOSE_COMP or RESET_COMP, we accept any
+ * event
* 3. If the expected event is 0, meaning the connection was never
* never established, we accept the opcode from cm_abort.
*/
if (opcode == csk->state || csk->state == 0 ||
- csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP) {
+ csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP ||
+ csk->state == L4_KCQE_OPCODE_VALUE_RESET_COMP) {
if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) {
if (csk->state == 0)
csk->state = opcode;
@@ -3865,7 +3909,7 @@ static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev)
{
u32 seed;
- get_random_bytes(&seed, 4);
+ seed = random32();
cnic_ctx_wr(dev, 45, 0, seed);
return 0;
}
@@ -3912,7 +3956,6 @@ static void cnic_close_bnx2x_conn(struct cnic_sock *csk, u32 opcode)
static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
- int i;
if (!cp->ctx_tbl)
return;
@@ -3920,16 +3963,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
if (!netif_running(dev->netdev))
return;
- for (i = 0; i < cp->max_cid_space; i++) {
- struct cnic_context *ctx = &cp->ctx_tbl[i];
-
- while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
- msleep(10);
-
- if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
- netdev_warn(dev->netdev, "CID %x not deleted\n",
- ctx->cid);
- }
+ cnic_bnx2x_delete_wait(dev, 0);
cancel_delayed_work(&cp->delete_task);
flush_workqueue(cnic_wq);
@@ -3992,6 +4026,7 @@ static void cnic_delete_task(struct work_struct *work)
for (i = 0; i < cp->max_cid_space; i++) {
struct cnic_context *ctx = &cp->ctx_tbl[i];
+ int err;
if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) ||
!test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
@@ -4005,13 +4040,15 @@ static void cnic_delete_task(struct work_struct *work)
if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
continue;
- cnic_bnx2x_destroy_ramrod(dev, i);
+ err = cnic_bnx2x_destroy_ramrod(dev, i);
cnic_free_bnx2x_conn_resc(dev, i);
- if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
- atomic_dec(&cp->iscsi_conn);
+ if (!err) {
+ if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
+ atomic_dec(&cp->iscsi_conn);
- clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ }
}
if (need_resched)
@@ -4218,14 +4255,6 @@ static void cnic_enable_bnx2_int(struct cnic_dev *dev)
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
}
-static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev)
-{
- u32 max_conn;
-
- max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN);
- dev->max_iscsi_conn = max_conn;
-}
-
static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
@@ -4291,7 +4320,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
cnic_ctx_wr(dev, cid_addr, offset1, val);
- txbd = (struct tx_bd *) udev->l2_ring;
+ txbd = udev->l2_ring;
buf_map = udev->l2_buf_map;
for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
@@ -4350,7 +4379,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
- rxbd = (struct rx_bd *) (udev->l2_ring + BCM_PAGE_SIZE);
+ rxbd = udev->l2_ring + BCM_PAGE_SIZE;
for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
int n = (i % cp->l2_rx_ring_size) + 1;
@@ -4550,8 +4579,6 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
return err;
}
- cnic_get_bnx2_iscsi_info(dev);
-
return 0;
}
@@ -4617,7 +4644,7 @@ static void cnic_enable_bnx2x_int(struct cnic_dev *dev)
CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
offsetof(struct hc_status_block_data_e1x, index_data) +
sizeof(struct hc_index_data)*HC_INDEX_ISCSI_EQ_CONS +
- offsetof(struct hc_index_data, timeout), 64 / 12);
+ offsetof(struct hc_index_data, timeout), 64 / 4);
cnic_storm_memset_hc_disable(dev, sb_id, HC_INDEX_ISCSI_EQ_CONS, 0);
}
@@ -4633,7 +4660,6 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring;
dma_addr_t buf_map, ring_map = udev->l2_ring_map;
struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
- int port = CNIC_PORT(cp);
int i;
u32 cli = cp->ethdev->iscsi_l2_client_id;
u32 val;
@@ -4674,10 +4700,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
/* reset xstorm per client statistics */
if (cli < MAX_STAT_COUNTER_ID) {
- val = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ data->general.statistics_zero_flg = 1;
+ data->general.statistics_en_flg = 1;
+ data->general.statistics_counter_id = cli;
}
cp->tx_cons_ptr =
@@ -4695,7 +4720,6 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
(udev->l2_ring + (2 * BCM_PAGE_SIZE));
struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
int i;
- int port = CNIC_PORT(cp);
u32 cli = cp->ethdev->iscsi_l2_client_id;
int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
u32 val;
@@ -4703,10 +4727,10 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
/* General data */
data->general.client_id = cli;
- data->general.statistics_en_flg = 1;
- data->general.statistics_counter_id = cli;
data->general.activate_flg = 1;
data->general.sp_client_id = cli;
+ data->general.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+ data->general.func_id = cp->pfid;
for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
@@ -4740,23 +4764,12 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
data->rx.status_block_id = BNX2X_DEF_SB_ID;
data->rx.cache_line_alignment_log_size = L1_CACHE_SHIFT;
- data->rx.bd_buff_size = cpu_to_le16(cp->l2_single_buf_size);
- data->rx.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+ data->rx.max_bytes_on_bd = cpu_to_le16(cp->l2_single_buf_size);
data->rx.outer_vlan_removal_enable_flg = 1;
-
- /* reset tstorm and ustorm per client statistics */
- if (cli < MAX_STAT_COUNTER_ID) {
- val = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
-
- val = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
- }
+ data->rx.silent_vlan_removal_flg = 1;
+ data->rx.silent_vlan_value = 0;
+ data->rx.silent_vlan_mask = 0xffff;
cp->rx_cons_ptr =
&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
@@ -4772,7 +4785,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
cp->kcq1.sw_prod_idx = 0;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
cp->kcq1.hw_prod_idx_ptr =
@@ -4788,7 +4801,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
&sb->sb.running_index[SM_RX_ID];
}
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
cp->kcq2.io_addr = BAR_USTRORM_INTMEM +
@@ -4805,10 +4818,12 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
struct cnic_eth_dev *ethdev = cp->ethdev;
- int func = CNIC_FUNC(cp), ret, i;
+ int func = CNIC_FUNC(cp), ret;
u32 pfid;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ cp->port_mode = CHIP_PORT_MODE_NONE;
+
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
if (!(val & 1))
@@ -4816,25 +4831,28 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
else
val = (val >> 1) & 1;
- if (val)
+ if (val) {
+ cp->port_mode = CHIP_4_PORT_MODE;
cp->pfid = func >> 1;
- else
+ } else {
+ cp->port_mode = CHIP_2_PORT_MODE;
cp->pfid = func & 0x6;
+ }
} else {
cp->pfid = func;
}
pfid = cp->pfid;
ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
- cp->iscsi_start_cid);
+ cp->iscsi_start_cid, 0);
if (ret)
return -ENOMEM;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,
BNX2X_FCOE_NUM_CONNECTIONS,
- cp->fcoe_start_cid);
+ cp->fcoe_start_cid, 0);
if (ret)
return -ENOMEM;
@@ -4868,15 +4886,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfid, 0),
HC_INDEX_ISCSI_EQ_CONS);
- for (i = 0; i < cp->conn_buf_info.num_pages; i++) {
- CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i),
- cp->conn_buf_info.pgtbl[2 * i]);
- CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i) + 4,
- cp->conn_buf_info.pgtbl[(2 * i) + 1]);
- }
-
CNIC_WR(dev, BAR_USTRORM_INTMEM +
USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid),
cp->gbl_buf_info.pg_map_arr[0] & 0xffffffff);
@@ -4915,7 +4924,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
struct client_init_ramrod_data *data;
union l5cm_specific_data l5_data;
struct ustorm_eth_rx_producers rx_prods = {0};
- u32 off, i;
+ u32 off, i, *cid_ptr;
rx_prods.bd_prod = 0;
rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT;
@@ -4924,7 +4933,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
off = BAR_USTRORM_INTMEM +
- (BNX2X_CHIP_IS_E2(cp->chip_id) ?
+ (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ?
USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
@@ -4934,6 +4943,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
data = udev->l2_buf;
+ cid_ptr = udev->l2_buf + 12;
memset(data, 0, sizeof(*data));
@@ -4958,12 +4968,15 @@ static void cnic_init_rings(struct cnic_dev *dev)
"iSCSI CLIENT_SETUP did not complete\n");
cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
cnic_ring_ctl(dev, cid, cli, 1);
+ *cid_ptr = cid;
}
}
static void cnic_shutdown_rings(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_uio_dev *udev = cp->udev;
+ void *rx_ring;
if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
return;
@@ -4971,7 +4984,6 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
cnic_shutdown_bnx2_rx_ring(dev);
} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
- struct cnic_local *cp = dev->cnic_priv;
u32 cli = cp->ethdev->iscsi_l2_client_id;
u32 cid = cp->ethdev->iscsi_l2_cid;
union l5cm_specific_data l5_data;
@@ -5001,6 +5013,8 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
msleep(10);
}
clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
+ rx_ring = udev->l2_ring + BCM_PAGE_SIZE;
+ memset(rx_ring, 0, BCM_PAGE_SIZE);
}
static int cnic_register_netdev(struct cnic_dev *dev)
@@ -5217,6 +5231,8 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
cdev->pcidev = pdev;
cp->chip_id = ethdev->chip_id;
+ cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
+
cp->cnic_ops = &cnic_bnx2_ops;
cp->start_hw = cnic_start_bnx2_hw;
cp->stop_hw = cnic_stop_bnx2_hw;
@@ -5228,8 +5244,6 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
cp->enable_int = cnic_enable_bnx2_int;
cp->disable_int_sync = cnic_disable_bnx2_int_sync;
cp->close_conn = cnic_close_bnx2_conn;
- cp->next_idx = cnic_bnx2_next_idx;
- cp->hw_idx = cnic_bnx2_hw_idx;
return cdev;
cnic_err:
@@ -5274,7 +5288,7 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI))
cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
- if (BNX2X_CHIP_IS_E2(cp->chip_id) &&
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
!(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
@@ -5290,13 +5304,11 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
cp->stop_cm = cnic_cm_stop_bnx2x_hw;
cp->enable_int = cnic_enable_bnx2x_int;
cp->disable_int_sync = cnic_disable_bnx2x_int_sync;
- if (BNX2X_CHIP_IS_E2(cp->chip_id))
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
cp->ack_int = cnic_ack_bnx2x_e2_msix;
else
cp->ack_int = cnic_ack_bnx2x_msix;
cp->close_conn = cnic_close_bnx2x_conn;
- cp->next_idx = cnic_bnx2x_next_idx;
- cp->hw_idx = cnic_bnx2x_hw_idx;
return cdev;
}
@@ -5322,6 +5334,27 @@ static struct cnic_dev *is_cnic_dev(struct net_device *dev)
return cdev;
}
+static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event,
+ u16 vlan_id)
+{
+ int if_type;
+
+ rcu_read_lock();
+ for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
+ struct cnic_ulp_ops *ulp_ops;
+ void *ctx;
+
+ ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
+ if (!ulp_ops || !ulp_ops->indicate_netevent)
+ continue;
+
+ ctx = cp->ulp_handle[if_type];
+
+ ulp_ops->indicate_netevent(ctx, event, vlan_id);
+ }
+ rcu_read_unlock();
+}
+
/**
* netdev event handler
*/
@@ -5330,12 +5363,11 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
{
struct net_device *netdev = ptr;
struct cnic_dev *dev;
- int if_type;
int new_dev = 0;
dev = cnic_from_netdev(netdev);
- if (!dev && (event == NETDEV_REGISTER || event == NETDEV_UP)) {
+ if (!dev && (event == NETDEV_REGISTER || netif_running(netdev))) {
/* Check for the hot-plug device */
dev = is_cnic_dev(netdev);
if (dev) {
@@ -5351,7 +5383,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
else if (event == NETDEV_UNREGISTER)
cnic_ulp_exit(dev);
- if (event == NETDEV_UP) {
+ if (event == NETDEV_UP || (new_dev && netif_running(netdev))) {
if (cnic_register_netdev(dev) != 0) {
cnic_put(dev);
goto done;
@@ -5360,20 +5392,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
cnic_ulp_start(dev);
}
- rcu_read_lock();
- for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
- struct cnic_ulp_ops *ulp_ops;
- void *ctx;
-
- ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
- if (!ulp_ops || !ulp_ops->indicate_netevent)
- continue;
-
- ctx = cp->ulp_handle[if_type];
-
- ulp_ops->indicate_netevent(ctx, event);
- }
- rcu_read_unlock();
+ cnic_rcv_netevent(cp, event, 0);
if (event == NETDEV_GOING_DOWN) {
cnic_ulp_stop(dev);
@@ -5389,6 +5408,19 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
goto done;
}
cnic_put(dev);
+ } else {
+ struct net_device *realdev;
+ u16 vid;
+
+ vid = cnic_get_vlan(netdev, &realdev);
+ if (realdev) {
+ dev = cnic_from_netdev(realdev);
+ if (dev) {
+ vid |= VLAN_TAG_PRESENT;
+ cnic_rcv_netevent(dev->cnic_priv, event, vid);
+ cnic_put(dev);
+ }
+ }
}
done:
return NOTIFY_DONE;
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 3367a6d3a774..7a2928f82d40 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -1,6 +1,6 @@
/* cnic.h: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 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
@@ -68,11 +68,6 @@
#define BNX2_PG_CTX_MAP 0x1a0034
#define BNX2_ISCSI_CTX_MAP 0x1a0074
-struct cnic_redirect_entry {
- struct dst_entry *old_dst;
- struct dst_entry *new_dst;
-};
-
#define MAX_COMPLETED_KCQE 64
#define MAX_CNIC_L5_CONTEXT 256
@@ -171,6 +166,7 @@ struct cnic_context {
unsigned long ctx_flags;
#define CTX_FL_OFFLD_START 0
#define CTX_FL_DELETE_WAIT 1
+#define CTX_FL_CID_ERROR 2
u8 ulp_proto_id;
union {
struct cnic_iscsi *iscsi;
@@ -185,6 +181,9 @@ struct kcq_info {
u16 sw_prod_idx;
u16 *status_idx_ptr;
u32 io_addr;
+
+ u16 (*next_idx)(u16);
+ u16 (*hw_idx)(u16);
};
struct iro {
@@ -242,7 +241,7 @@ struct cnic_local {
u16 rx_cons;
u16 tx_cons;
- struct iro *iro_arr;
+ const struct iro *iro_arr;
#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
struct cnic_dma kwq_info;
@@ -283,7 +282,6 @@ struct cnic_local {
struct cnic_sock *csk_tbl;
struct cnic_id_tbl csk_port_tbl;
- struct cnic_dma conn_buf_info;
struct cnic_dma gbl_buf_info;
struct cnic_iscsi *iscsi_tbl;
@@ -317,6 +315,11 @@ struct cnic_local {
u32 chip_id;
int func;
u32 pfid;
+ u8 port_mode;
+#define CHIP_4_PORT_MODE 0
+#define CHIP_2_PORT_MODE 1
+#define CHIP_PORT_MODE_NONE 2
+
u32 shmem_base;
struct cnic_ops *cnic_ops;
@@ -332,8 +335,6 @@ struct cnic_local {
void (*disable_int_sync)(struct cnic_dev *);
void (*ack_int)(struct cnic_dev *);
void (*close_conn)(struct cnic_sock *, u32 opcode);
- u16 (*next_idx)(u16);
- u16 (*hw_idx)(u16);
};
struct bnx2x_bd_chain_next {
@@ -368,7 +369,6 @@ struct bnx2x_bd_chain_next {
#define BNX2X_ISCSI_MAX_PENDING_R2TS 4
#define BNX2X_ISCSI_R2TQE_SIZE 8
#define BNX2X_ISCSI_HQ_BD_SIZE 64
-#define BNX2X_ISCSI_CONN_BUF_SIZE 64
#define BNX2X_ISCSI_GLB_BUF_SIZE 64
#define BNX2X_ISCSI_PBL_NOT_CACHED 0xff
#define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED 0xff
@@ -384,6 +384,9 @@ struct bnx2x_bd_chain_next {
#define BNX2X_CHIP_NUM_57712E 0x1663
#define BNX2X_CHIP_NUM_57713 0x1651
#define BNX2X_CHIP_NUM_57713E 0x1652
+#define BNX2X_CHIP_NUM_57800 0x168a
+#define BNX2X_CHIP_NUM_57810 0x168e
+#define BNX2X_CHIP_NUM_57840 0x168d
#define BNX2X_CHIP_NUM(x) (x >> 16)
#define BNX2X_CHIP_IS_57710(x) \
@@ -402,9 +405,19 @@ struct bnx2x_bd_chain_next {
(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713)
#define BNX2X_CHIP_IS_57713E(x) \
(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E)
+#define BNX2X_CHIP_IS_57800(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57800)
+#define BNX2X_CHIP_IS_57810(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57810)
+#define BNX2X_CHIP_IS_57840(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57840)
#define BNX2X_CHIP_IS_E2(x) \
(BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \
BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x))
+#define BNX2X_CHIP_IS_E3(x) \
+ (BNX2X_CHIP_IS_57800(x) || BNX2X_CHIP_IS_57810(x) || \
+ BNX2X_CHIP_IS_57840(x))
+#define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x))
#define IS_E1H_OFFSET BNX2X_CHIP_IS_E1H(cp->chip_id)
@@ -441,8 +454,8 @@ struct bnx2x_bd_chain_next {
#define CNIC_PORT(cp) ((cp)->pfid & 1)
#define CNIC_FUNC(cp) ((cp)->func)
-#define CNIC_PATH(cp) (!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
- (CNIC_FUNC(cp) & 1))
+#define CNIC_PATH(cp) (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? \
+ 0 : (CNIC_FUNC(cp) & 1))
#define CNIC_E1HVN(cp) ((cp)->pfid >> 1)
#define BNX2X_HW_CID(cp, x) ((CNIC_PORT(cp) << 23) | \
@@ -451,10 +464,15 @@ struct bnx2x_bd_chain_next {
#define BNX2X_SW_CID(x) (x & 0x1ffff)
#define BNX2X_CL_QZONE_ID(cp, cli) \
- (cli + (CNIC_PORT(cp) * (BNX2X_CHIP_IS_E2(cp->chip_id) ?\
- ETH_MAX_RX_CLIENTS_E2 : \
- ETH_MAX_RX_CLIENTS_E1H)))
+ (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? cli : \
+ cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
+
+#ifndef MAX_STAT_COUNTER_ID
+#define MAX_STAT_COUNTER_ID \
+ (BNX2X_CHIP_IS_E1H((cp)->chip_id) ? MAX_STAT_COUNTER_ID_E1H : \
+ ((BNX2X_CHIP_IS_E2_PLUS((cp)->chip_id)) ? MAX_STAT_COUNTER_ID_E2 :\
+ MAX_STAT_COUNTER_ID_E1))
+#endif
-#define TCP_TSTORM_OOO_DROP_AND_PROC_ACK (0<<4)
#endif
diff --git a/drivers/net/cnic_defs.h b/drivers/net/cnic_defs.h
index fdbc00415603..e47d21076767 100644
--- a/drivers/net/cnic_defs.h
+++ b/drivers/net/cnic_defs.h
@@ -1,7 +1,7 @@
/* cnic.c: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2009 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
@@ -45,13 +45,13 @@
#define FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION (0x20)
#define FCOE_KCQE_OPCODE_FCOE_ERROR (0x21)
-#define FCOE_RAMROD_CMD_ID_INIT (FCOE_KCQE_OPCODE_INIT_FUNC)
-#define FCOE_RAMROD_CMD_ID_DESTROY (FCOE_KCQE_OPCODE_DESTROY_FUNC)
+#define FCOE_RAMROD_CMD_ID_INIT_FUNC (FCOE_KCQE_OPCODE_INIT_FUNC)
+#define FCOE_RAMROD_CMD_ID_DESTROY_FUNC (FCOE_KCQE_OPCODE_DESTROY_FUNC)
+#define FCOE_RAMROD_CMD_ID_STAT_FUNC (FCOE_KCQE_OPCODE_STAT_FUNC)
#define FCOE_RAMROD_CMD_ID_OFFLOAD_CONN (FCOE_KCQE_OPCODE_OFFLOAD_CONN)
#define FCOE_RAMROD_CMD_ID_ENABLE_CONN (FCOE_KCQE_OPCODE_ENABLE_CONN)
#define FCOE_RAMROD_CMD_ID_DISABLE_CONN (FCOE_KCQE_OPCODE_DISABLE_CONN)
#define FCOE_RAMROD_CMD_ID_DESTROY_CONN (FCOE_KCQE_OPCODE_DESTROY_CONN)
-#define FCOE_RAMROD_CMD_ID_STAT (FCOE_KCQE_OPCODE_STAT_FUNC)
#define FCOE_RAMROD_CMD_ID_TERMINATE_CONN (0x81)
#define FCOE_KWQE_OPCODE_INIT1 (0)
@@ -641,20 +641,20 @@ struct cstorm_iscsi_ag_context {
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF (0x3<<14)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_SHIFT 14
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<14)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 14
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN (0x1<<19)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN_SHIFT 19
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN (0x1<<20)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN_SHIFT 20
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN (0x1<<21)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN_SHIFT 21
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN (0x1<<22)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN_SHIFT 22
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<19)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 19
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN (0x1<<20)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN_SHIFT 20
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<21)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 21
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<22)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 22
#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
@@ -694,573 +694,667 @@ struct cstorm_iscsi_ag_context {
#endif
#if defined(__BIG_ENDIAN)
u16 __reserved64;
- u16 __cq_u_prod0;
+ u16 cq_u_prod;
#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod0;
+ u16 cq_u_prod;
u16 __reserved64;
#endif
u32 __cq_u_prod1;
#if defined(__BIG_ENDIAN)
u16 __agg_vars3;
- u16 __cq_u_prod2;
+ u16 cq_u_pend;
#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod2;
+ u16 cq_u_pend;
u16 __agg_vars3;
#endif
#if defined(__BIG_ENDIAN)
u16 __aux2_th;
- u16 __cq_u_prod3;
+ u16 aux2_val;
#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod3;
+ u16 aux2_val;
u16 __aux2_th;
#endif
};
/*
- * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and used in FCoE context section
+ * The fcoe extra aggregative context section of Tstorm
*/
-struct ustorm_fcoe_params {
-#if defined(__BIG_ENDIAN)
- u16 fcoe_conn_id;
- u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
-#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
-#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
-#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
-#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
-#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
-#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
-#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
-#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
- u16 fcoe_conn_id;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 hc_csdm_byte_en;
- u8 func_id;
- u8 port_id;
- u8 vnic_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 vnic_id;
- u8 port_id;
- u8 func_id;
- u8 hc_csdm_byte_en;
-#endif
+struct tstorm_fcoe_extra_ag_context_section {
+ u32 __agg_val1;
#if defined(__BIG_ENDIAN)
- u16 rx_total_conc_seqs;
- u16 rx_max_fc_pay_len;
+ u8 __tcp_agg_vars2;
+ u8 __agg_val3;
+ u16 __agg_val2;
#elif defined(__LITTLE_ENDIAN)
- u16 rx_max_fc_pay_len;
- u16 rx_total_conc_seqs;
+ u16 __agg_val2;
+ u8 __agg_val3;
+ u8 __tcp_agg_vars2;
#endif
#if defined(__BIG_ENDIAN)
- u16 ox_id;
- u16 rx_max_conc_seqs;
+ u16 __agg_val5;
+ u8 __agg_val6;
+ u8 __tcp_agg_vars3;
#elif defined(__LITTLE_ENDIAN)
- u16 rx_max_conc_seqs;
- u16 ox_id;
+ u8 __tcp_agg_vars3;
+ u8 __agg_val6;
+ u16 __agg_val5;
#endif
+ u32 __lcq_prod;
+ u32 rtt_seq;
+ u32 rtt_time;
+ u32 __reserved66;
+ u32 wnd_right_edge;
+ u32 tcp_agg_vars1;
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
+ u32 snd_max;
+ u32 __lcq_cons;
+ u32 __reserved2;
};
/*
- * FCoE 16-bits index structure
- */
-struct fcoe_idx16_fields {
- u16 fields;
-#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
-#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
-#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
-#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
-};
-
-/*
- * FCoE 16-bits index union
- */
-union fcoe_idx16_field_union {
- struct fcoe_idx16_fields fields;
- u16 val;
-};
-
-/*
- * 4 regs size
+ * The fcoe aggregative context of Tstorm
*/
-struct fcoe_bd_ctx {
- u32 buf_addr_hi;
- u32 buf_addr_lo;
+struct tstorm_fcoe_ag_context {
#if defined(__BIG_ENDIAN)
- u16 rsrv0;
- u16 buf_len;
+ u16 ulp_credit;
+ u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+ u8 state;
#elif defined(__LITTLE_ENDIAN)
- u16 buf_len;
- u16 rsrv0;
+ u8 state;
+ u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+ u16 ulp_credit;
#endif
#if defined(__BIG_ENDIAN)
- u16 rsrv1;
- u16 flags;
+ u16 __agg_val4;
+ u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
#elif defined(__LITTLE_ENDIAN)
- u16 flags;
- u16 rsrv1;
+ u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+ u16 __agg_val4;
#endif
+ struct tstorm_fcoe_extra_ag_context_section __extra_section;
};
+
+
/*
- * Parameters required for placement according to SGL
+ * The tcp aggregative context section of Tstorm
*/
-struct ustorm_fcoe_data_place {
+struct tstorm_tcp_tcp_ag_context_section {
+ u32 __agg_val1;
#if defined(__BIG_ENDIAN)
- u16 cached_sge_off;
- u8 cached_num_sges;
- u8 cached_sge_idx;
+ u8 __tcp_agg_vars2;
+ u8 __agg_val3;
+ u16 __agg_val2;
#elif defined(__LITTLE_ENDIAN)
- u8 cached_sge_idx;
- u8 cached_num_sges;
- u16 cached_sge_off;
+ u16 __agg_val2;
+ u8 __agg_val3;
+ u8 __tcp_agg_vars2;
#endif
- struct fcoe_bd_ctx cached_sge[3];
-};
-
-struct fcoe_task_ctx_entry_txwr_rxrd {
#if defined(__BIG_ENDIAN)
- u16 verify_tx_seq;
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+ u16 __agg_val5;
+ u8 __agg_val6;
+ u8 __tcp_agg_vars3;
#elif defined(__LITTLE_ENDIAN)
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u16 verify_tx_seq;
+ u8 __tcp_agg_vars3;
+ u8 __agg_val6;
+ u16 __agg_val5;
#endif
+ u32 snd_nxt;
+ u32 rtt_seq;
+ u32 rtt_time;
+ u32 __reserved66;
+ u32 wnd_right_edge;
+ u32 tcp_agg_vars1;
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN (0x1<<9)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN_SHIFT 9
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
+ u32 snd_max;
+ u32 snd_una;
+ u32 __reserved2;
};
-struct fcoe_fcp_cmd_payload {
- u32 opaque[8];
-};
-
-struct fcoe_fc_hdr {
-#if defined(__BIG_ENDIAN)
- u8 cs_ctl;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 cs_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 r_ctl;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 r_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 seq_id;
- u8 df_ctl;
- u16 seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 seq_cnt;
- u8 df_ctl;
- u8 seq_id;
-#endif
+/*
+ * The iscsi aggregative context of Tstorm
+ */
+struct tstorm_iscsi_ag_context {
#if defined(__BIG_ENDIAN)
- u8 type;
- u8 f_ctl[3];
+ u16 ulp_credit;
+ u8 agg_vars1;
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
+ u8 state;
#elif defined(__LITTLE_ENDIAN)
- u8 f_ctl[3];
- u8 type;
+ u8 state;
+ u8 agg_vars1;
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
+ u16 ulp_credit;
#endif
- u32 parameters;
#if defined(__BIG_ENDIAN)
- u16 ox_id;
- u16 rx_id;
+ u16 __agg_val4;
+ u16 agg_vars2;
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
#elif defined(__LITTLE_ENDIAN)
- u16 rx_id;
- u16 ox_id;
+ u16 agg_vars2;
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+ u16 __agg_val4;
#endif
+ struct tstorm_tcp_tcp_ag_context_section tcp;
};
-struct fcoe_fc_frame {
- struct fcoe_fc_hdr fc_hdr;
- u32 reserved0[2];
-};
-
-union fcoe_cmd_flow_info {
- struct fcoe_fcp_cmd_payload fcp_cmd_payload;
- struct fcoe_fc_frame mp_fc_frame;
-};
-
-struct fcoe_read_flow_info {
- struct fcoe_fc_hdr fc_data_in_hdr;
- u32 reserved[2];
-};
-
-struct fcoe_fcp_xfr_rdy_payload {
- u32 burst_len;
- u32 data_ro;
-};
-
-struct fcoe_write_flow_info {
- struct fcoe_fc_hdr fc_data_out_hdr;
- struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
-};
-
-struct fcoe_fcp_rsp_flags {
- u8 flags;
-#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
-#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
-#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
-#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
-#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
-#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
-#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
-#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
-};
-
-struct fcoe_fcp_rsp_payload {
- struct regpair reserved0;
- u32 fcp_resid;
-#if defined(__BIG_ENDIAN)
- u16 retry_delay_timer;
- struct fcoe_fcp_rsp_flags fcp_flags;
- u8 scsi_status_code;
-#elif defined(__LITTLE_ENDIAN)
- u8 scsi_status_code;
- struct fcoe_fcp_rsp_flags fcp_flags;
- u16 retry_delay_timer;
-#endif
- u32 fcp_rsp_len;
- u32 fcp_sns_len;
-};
-/*
- * Fixed size structure in order to plant it in Union structure
- */
-struct fcoe_fcp_rsp_union {
- struct fcoe_fcp_rsp_payload payload;
- struct regpair reserved0;
-};
/*
- * Fixed size structure in order to plant it in Union structure
+ * The fcoe aggregative context of Ustorm
*/
-struct fcoe_abts_rsp_union {
- u32 r_ctl;
- u32 abts_rsp_payload[7];
-};
-
-union fcoe_rsp_flow_info {
- struct fcoe_fcp_rsp_union fcp_rsp;
- struct fcoe_abts_rsp_union abts_rsp;
-};
-
-struct fcoe_cleanup_flow_info {
+struct ustorm_fcoe_ag_context {
#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u16 task_id;
+ u8 __aux_counter_flags;
+ u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 state;
#elif defined(__LITTLE_ENDIAN)
- u16 task_id;
- u16 reserved1;
+ u8 state;
+ u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 __aux_counter_flags;
#endif
- u32 reserved2[7];
-};
-
-/*
- * 32 bytes used for general purposes
- */
-union fcoe_general_task_ctx {
- union fcoe_cmd_flow_info cmd_info;
- struct fcoe_read_flow_info read_info;
- struct fcoe_write_flow_info write_info;
- union fcoe_rsp_flow_info rsp_info;
- struct fcoe_cleanup_flow_info cleanup_info;
- u32 comp_info[8];
-};
-
-struct fcoe_s_stat_ctx {
- u8 flags;
-#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
-#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
-#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
-#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
-#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
-#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
-#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
-#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
-#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
-#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
-#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
-#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
-#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
-#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
-};
-
-/*
- * Common section. Both TX and RX processing might write and read from it in different flows
- */
-struct fcoe_task_ctx_entry_tx_rx_cmn {
- u32 data_2_trns;
- union fcoe_general_task_ctx general;
-#if defined(__BIG_ENDIAN)
- u16 tx_low_seq_cnt;
- struct fcoe_s_stat_ctx tx_s_stat;
- u8 tx_seq_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 tx_seq_id;
- struct fcoe_s_stat_ctx tx_s_stat;
- u16 tx_low_seq_cnt;
-#endif
- u32 common_flags;
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
-};
-
-struct fcoe_task_ctx_entry_rxwr_txrd {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
- u16 rx_id;
-#endif
-};
-
-struct fcoe_seq_ctx {
-#if defined(__BIG_ENDIAN)
- u16 low_seq_cnt;
- struct fcoe_s_stat_ctx s_stat;
- u8 seq_id;
+#if defined(__BIG_ENDIAN)
+ u8 cdu_usage;
+ u8 agg_misc2;
+ u16 pbf_tx_seq_ack;
#elif defined(__LITTLE_ENDIAN)
- u8 seq_id;
- struct fcoe_s_stat_ctx s_stat;
- u16 low_seq_cnt;
+ u16 pbf_tx_seq_ack;
+ u8 agg_misc2;
+ u8 cdu_usage;
#endif
+ u32 agg_misc4;
#if defined(__BIG_ENDIAN)
- u16 err_seq_cnt;
- u16 high_seq_cnt;
+ u8 agg_val3_th;
+ u8 agg_val3;
+ u16 agg_misc3;
#elif defined(__LITTLE_ENDIAN)
- u16 high_seq_cnt;
- u16 err_seq_cnt;
+ u16 agg_misc3;
+ u8 agg_val3;
+ u8 agg_val3_th;
#endif
- u32 low_exp_ro;
- u32 high_exp_ro;
-};
-
-struct fcoe_single_sge_ctx {
- struct regpair cur_buf_addr;
+ u32 expired_task_id;
+ u32 agg_misc4_th;
#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 cur_buf_rem;
+ u16 cq_prod;
+ u16 cq_cons;
#elif defined(__LITTLE_ENDIAN)
- u16 cur_buf_rem;
- u16 reserved0;
+ u16 cq_cons;
+ u16 cq_prod;
#endif
-};
-
-struct fcoe_mul_sges_ctx {
- struct regpair cur_sge_addr;
#if defined(__BIG_ENDIAN)
- u8 sgl_size;
- u8 cur_sge_idx;
- u16 cur_sge_off;
+ u16 __reserved2;
+ u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+ u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
#elif defined(__LITTLE_ENDIAN)
- u16 cur_sge_off;
- u8 cur_sge_idx;
- u8 sgl_size;
+ u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+ u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+ u16 __reserved2;
#endif
};
-union fcoe_sgl_ctx {
- struct fcoe_single_sge_ctx single_sge;
- struct fcoe_mul_sges_ctx mul_sges;
-};
-
-struct fcoe_task_ctx_entry_rx_only {
- struct fcoe_seq_ctx seq_ctx;
- struct fcoe_seq_ctx ooo_seq_ctx;
- u32 rsrv3;
- union fcoe_sgl_ctx sgl_ctx;
-};
-
-struct ustorm_fcoe_task_ctx_entry_rd {
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
- struct fcoe_task_ctx_entry_rx_only rx_wr;
- u32 reserved;
-};
/*
- * Ustorm FCoE Storm Context
+ * The iscsi aggregative context of Ustorm
*/
-struct ustorm_fcoe_st_context {
- struct ustorm_fcoe_params fcoe_params;
- struct regpair task_addr;
- struct regpair cq_base_addr;
- struct regpair rq_pbl_base;
- struct regpair rq_cur_page_addr;
- struct regpair confq_pbl_base_addr;
- struct regpair conn_db_base;
- struct regpair xfrq_base_addr;
- struct regpair lcq_base_addr;
+struct ustorm_iscsi_ag_context {
#if defined(__BIG_ENDIAN)
- union fcoe_idx16_field_union rq_cons;
- union fcoe_idx16_field_union rq_prod;
+ u8 __aux_counter_flags;
+ u8 agg_vars2;
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 agg_vars1;
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 state;
#elif defined(__LITTLE_ENDIAN)
- union fcoe_idx16_field_union rq_prod;
- union fcoe_idx16_field_union rq_cons;
+ u8 state;
+ u8 agg_vars1;
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 agg_vars2;
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 __aux_counter_flags;
#endif
#if defined(__BIG_ENDIAN)
- u16 xfrq_prod;
- u16 cq_cons;
+ u8 cdu_usage;
+ u8 agg_misc2;
+ u16 __cq_local_comp_itt_val;
#elif defined(__LITTLE_ENDIAN)
- u16 cq_cons;
- u16 xfrq_prod;
+ u16 __cq_local_comp_itt_val;
+ u8 agg_misc2;
+ u8 cdu_usage;
#endif
+ u32 agg_misc4;
#if defined(__BIG_ENDIAN)
- u16 lcq_cons;
- u16 hc_cram_address;
+ u8 agg_val3_th;
+ u8 agg_val3;
+ u16 agg_misc3;
#elif defined(__LITTLE_ENDIAN)
- u16 hc_cram_address;
- u16 lcq_cons;
+ u16 agg_misc3;
+ u8 agg_val3;
+ u8 agg_val3_th;
#endif
+ u32 agg_val1;
+ u32 agg_misc4_th;
#if defined(__BIG_ENDIAN)
- u16 sq_xfrq_lcq_confq_size;
- u16 confq_prod;
+ u16 agg_val2_th;
+ u16 agg_val2;
#elif defined(__LITTLE_ENDIAN)
- u16 confq_prod;
- u16 sq_xfrq_lcq_confq_size;
+ u16 agg_val2;
+ u16 agg_val2_th;
#endif
#if defined(__BIG_ENDIAN)
- u8 hc_csdm_agg_int;
- u8 flags;
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
-#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
-#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
- u8 available_rqes;
- u8 sp_q_flush_cnt;
+ u16 __reserved2;
+ u8 decision_rules;
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
+ u8 decision_rule_enable_bits;
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
#elif defined(__LITTLE_ENDIAN)
- u8 sp_q_flush_cnt;
- u8 available_rqes;
- u8 flags;
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
-#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
-#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
- u8 hc_csdm_agg_int;
+ u8 decision_rule_enable_bits;
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+ u8 decision_rules;
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
+ u16 __reserved2;
#endif
- struct ustorm_fcoe_data_place data_place;
- struct ustorm_fcoe_task_ctx_entry_rd tce;
};
-/*
- * The FCoE non-aggregative context of Tstorm
- */
-struct tstorm_fcoe_st_context {
- struct regpair reserved0;
- struct regpair reserved1;
-};
/*
* The fcoe aggregative context section of Xstorm
@@ -1272,8 +1366,8 @@ struct xstorm_fcoe_extra_ag_context_section {
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
@@ -1288,20 +1382,20 @@ struct xstorm_fcoe_extra_ag_context_section {
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
#endif
- u32 __task_addr_lo;
- u32 __task_addr_hi;
+ u32 snd_nxt;
+ u32 tx_wnd;
u32 __reserved55;
- u32 __tx_prods;
+ u32 local_adv_wnd;
#if defined(__BIG_ENDIAN)
u8 __agg_val8_th;
- u8 __agg_val8;
+ u8 __tx_dest;
u16 tcp_agg_vars2;
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57_SHIFT 0
@@ -1317,8 +1411,8 @@ struct xstorm_fcoe_extra_ag_context_section {
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -1327,8 +1421,8 @@ struct xstorm_fcoe_extra_ag_context_section {
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
#elif defined(__LITTLE_ENDIAN)
u16 tcp_agg_vars2;
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
@@ -1345,8 +1439,8 @@ struct xstorm_fcoe_extra_ag_context_section {
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -1355,9 +1449,9 @@ struct xstorm_fcoe_extra_ag_context_section {
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
- u8 __agg_val8;
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
+ u8 __tx_dest;
u8 __agg_val8_th;
#endif
u32 __sq_base_addr_lo;
@@ -1591,9 +1685,9 @@ struct xstorm_fcoe_ag_context {
#if defined(__BIG_ENDIAN)
u8 __reserved1;
u8 __agg_val6_th;
- u16 __confq_tx_prod;
+ u16 __agg_val9;
#elif defined(__LITTLE_ENDIAN)
- u16 __confq_tx_prod;
+ u16 __agg_val9;
u8 __agg_val6_th;
u8 __reserved1;
#endif
@@ -1605,16 +1699,16 @@ struct xstorm_fcoe_ag_context {
u16 confq_cons;
#endif
u32 agg_vars8;
-#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX (0xFFFFFF<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX_SHIFT 0
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2_SHIFT 0
#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3_SHIFT 24
#if defined(__BIG_ENDIAN)
- u16 ox_id;
+ u16 agg_misc0;
u16 sq_prod;
#elif defined(__LITTLE_ENDIAN)
u16 sq_prod;
- u16 ox_id;
+ u16 agg_misc0;
#endif
#if defined(__BIG_ENDIAN)
u8 agg_val3;
@@ -1628,332 +1722,1685 @@ struct xstorm_fcoe_ag_context {
u8 agg_val3;
#endif
#if defined(__BIG_ENDIAN)
- u16 __pbf_tx_seq_ack;
+ u16 __agg_misc1;
u16 agg_limit1;
#elif defined(__LITTLE_ENDIAN)
u16 agg_limit1;
- u16 __pbf_tx_seq_ack;
+ u16 __agg_misc1;
#endif
u32 completion_seq;
u32 confq_pbl_base_lo;
u32 confq_pbl_base_hi;
};
+
+
/*
- * The fcoe extra aggregative context section of Tstorm
+ * The tcp aggregative context section of Xstorm
*/
-struct tstorm_fcoe_extra_ag_context_section {
- u32 __agg_val1;
+struct xstorm_tcp_tcp_ag_context_section {
#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars2;
- u8 __agg_val3;
- u16 __agg_val2;
+ u8 tcp_agg_vars1;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
+ u8 __da_cnt;
+ u16 mss;
#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val2;
- u8 __agg_val3;
- u8 __tcp_agg_vars2;
+ u16 mss;
+ u8 __da_cnt;
+ u8 tcp_agg_vars1;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
#endif
+ u32 snd_nxt;
+ u32 tx_wnd;
+ u32 snd_una;
+ u32 local_adv_wnd;
#if defined(__BIG_ENDIAN)
- u16 __agg_val5;
- u8 __agg_val6;
+ u8 __agg_val8_th;
+ u8 __tx_dest;
+ u16 tcp_agg_vars2;
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
+#elif defined(__LITTLE_ENDIAN)
+ u16 tcp_agg_vars2;
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
+ u8 __tx_dest;
+ u8 __agg_val8_th;
+#endif
+ u32 ack_to_far_end;
+ u32 rto_timer;
+ u32 ka_timer;
+ u32 ts_to_echo;
+#if defined(__BIG_ENDIAN)
+ u16 __agg_val7_th;
+ u16 __agg_val7;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __agg_val7;
+ u16 __agg_val7_th;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 __tcp_agg_vars5;
+ u8 __tcp_agg_vars4;
u8 __tcp_agg_vars3;
+ u8 __force_pure_ack_cnt;
#elif defined(__LITTLE_ENDIAN)
+ u8 __force_pure_ack_cnt;
u8 __tcp_agg_vars3;
- u8 __agg_val6;
- u16 __agg_val5;
+ u8 __tcp_agg_vars4;
+ u8 __tcp_agg_vars5;
+#endif
+ u32 tcp_agg_vars6;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN (0x1<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN (0x1<<1)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN_SHIFT 1
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN (0x1<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN_SHIFT 2
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<3)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 3
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG (0x1<<4)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG (0x1<<5)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG_SHIFT 5
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF (0x3<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF (0x3<<8)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_SHIFT 8
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF (0x3<<10)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_SHIFT 10
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF (0x3<<12)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_SHIFT 12
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_SHIFT 14
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF (0x3<<16)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF_SHIFT 16
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF (0x3<<18)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF_SHIFT 18
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF (0x3<<20)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF_SHIFT 20
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF (0x3<<22)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF_SHIFT 22
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF (0x3<<24)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF_SHIFT 24
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG (0x1<<26)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG_SHIFT 26
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71 (0x1<<27)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71_SHIFT 27
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY (0x1<<28)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY_SHIFT 28
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG (0x1<<29)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG_SHIFT 29
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG (0x1<<30)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG_SHIFT 30
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG (0x1<<31)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG_SHIFT 31
+#if defined(__BIG_ENDIAN)
+ u16 __agg_misc6;
+ u16 __tcp_agg_vars7;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __tcp_agg_vars7;
+ u16 __agg_misc6;
+#endif
+ u32 __agg_val10;
+ u32 __agg_val10_th;
+#if defined(__BIG_ENDIAN)
+ u16 __reserved3;
+ u8 __reserved2;
+ u8 __da_only_cnt;
+#elif defined(__LITTLE_ENDIAN)
+ u8 __da_only_cnt;
+ u8 __reserved2;
+ u16 __reserved3;
#endif
- u32 __lcq_prod;
- u32 rtt_seq;
- u32 rtt_time;
- u32 __reserved66;
- u32 wnd_right_edge;
- u32 tcp_agg_vars1;
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
- u32 snd_max;
- u32 __lcq_cons;
- u32 __reserved2;
};
/*
- * The fcoe aggregative context of Tstorm
+ * The iscsi aggregative context of Xstorm
*/
-struct tstorm_fcoe_ag_context {
+struct xstorm_iscsi_ag_context {
#if defined(__BIG_ENDIAN)
- u16 ulp_credit;
+ u16 agg_val1;
u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
u8 state;
#elif defined(__LITTLE_ENDIAN)
u8 state;
u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
- u16 ulp_credit;
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
+ u16 agg_val1;
#endif
#if defined(__BIG_ENDIAN)
- u16 __agg_val4;
- u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+ u8 cdu_reserved;
+ u8 __agg_vars4;
+ u8 agg_vars3;
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+ u8 agg_vars2;
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
#elif defined(__LITTLE_ENDIAN)
- u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
- u16 __agg_val4;
+ u8 agg_vars2;
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+ u8 agg_vars3;
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+ u8 __agg_vars4;
+ u8 cdu_reserved;
#endif
- struct tstorm_fcoe_extra_ag_context_section __extra_section;
+ u32 more_to_send;
+#if defined(__BIG_ENDIAN)
+ u16 agg_vars5;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+ u16 sq_cons;
+#elif defined(__LITTLE_ENDIAN)
+ u16 sq_cons;
+ u16 agg_vars5;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+#endif
+ struct xstorm_tcp_tcp_ag_context_section tcp;
+#if defined(__BIG_ENDIAN)
+ u16 agg_vars7;
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
+ u8 agg_val3_th;
+ u8 agg_vars6;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+#elif defined(__LITTLE_ENDIAN)
+ u8 agg_vars6;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+ u8 agg_val3_th;
+ u16 agg_vars7;
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __agg_val11_th;
+ u16 __gen_data;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __gen_data;
+ u16 __agg_val11_th;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 __reserved1;
+ u8 __agg_val6_th;
+ u16 __agg_val9;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __agg_val9;
+ u8 __agg_val6_th;
+ u8 __reserved1;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 hq_prod;
+ u16 hq_cons;
+#elif defined(__LITTLE_ENDIAN)
+ u16 hq_cons;
+ u16 hq_prod;
+#endif
+ u32 agg_vars8;
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3_SHIFT 24
+#if defined(__BIG_ENDIAN)
+ u16 r2tq_prod;
+ u16 sq_prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 sq_prod;
+ u16 r2tq_prod;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 agg_val3;
+ u8 agg_val6;
+ u8 agg_val5_th;
+ u8 agg_val5;
+#elif defined(__LITTLE_ENDIAN)
+ u8 agg_val5;
+ u8 agg_val5_th;
+ u8 agg_val6;
+ u8 agg_val3;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __agg_misc1;
+ u16 agg_limit1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_limit1;
+ u16 __agg_misc1;
+#endif
+ u32 hq_cons_tcp_seq;
+ u32 exp_stat_sn;
+ u32 rst_seq_num;
};
+
/*
- * The fcoe aggregative context of Ustorm
+ * The L5cm aggregative context of XStorm
*/
-struct ustorm_fcoe_ag_context {
+struct xstorm_l5cm_ag_context {
#if defined(__BIG_ENDIAN)
- u8 __aux_counter_flags;
- u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u16 agg_val1;
u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
u8 state;
#elif defined(__LITTLE_ENDIAN)
u8 state;
u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
- u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
- u8 __aux_counter_flags;
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
+ u16 agg_val1;
#endif
#if defined(__BIG_ENDIAN)
- u8 cdu_usage;
- u8 agg_misc2;
- u16 pbf_tx_seq_ack;
+ u8 cdu_reserved;
+ u8 __agg_vars4;
+ u8 agg_vars3;
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+ u8 agg_vars2;
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
#elif defined(__LITTLE_ENDIAN)
- u16 pbf_tx_seq_ack;
- u8 agg_misc2;
- u8 cdu_usage;
+ u8 agg_vars2;
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
+ u8 agg_vars3;
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+ u8 __agg_vars4;
+ u8 cdu_reserved;
#endif
- u32 agg_misc4;
+ u32 more_to_send;
+#if defined(__BIG_ENDIAN)
+ u16 agg_vars5;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+ u16 agg_val4_th;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_val4_th;
+ u16 agg_vars5;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+#endif
+ struct xstorm_tcp_tcp_ag_context_section tcp;
#if defined(__BIG_ENDIAN)
+ u16 agg_vars7;
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
u8 agg_val3_th;
+ u8 agg_vars6;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+#elif defined(__LITTLE_ENDIAN)
+ u8 agg_vars6;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+ u8 agg_val3_th;
+ u16 agg_vars7;
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __agg_val11_th;
+ u16 __gen_data;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __gen_data;
+ u16 __agg_val11_th;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 __reserved1;
+ u8 __agg_val6_th;
+ u16 __agg_val9;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __agg_val9;
+ u8 __agg_val6_th;
+ u8 __reserved1;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 agg_val2_th;
+ u16 agg_val2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_val2;
+ u16 agg_val2_th;
+#endif
+ u32 agg_vars8;
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3_SHIFT 24
+#if defined(__BIG_ENDIAN)
+ u16 agg_misc0;
+ u16 agg_val4;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_val4;
+ u16 agg_misc0;
+#endif
+#if defined(__BIG_ENDIAN)
u8 agg_val3;
- u16 agg_misc3;
+ u8 agg_val6;
+ u8 agg_val5_th;
+ u8 agg_val5;
#elif defined(__LITTLE_ENDIAN)
- u16 agg_misc3;
+ u8 agg_val5;
+ u8 agg_val5_th;
+ u8 agg_val6;
u8 agg_val3;
- u8 agg_val3_th;
#endif
- u32 expired_task_id;
- u32 agg_misc4_th;
#if defined(__BIG_ENDIAN)
- u16 cq_prod;
+ u16 __agg_misc1;
+ u16 agg_limit1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_limit1;
+ u16 __agg_misc1;
+#endif
+ u32 completion_seq;
+ u32 agg_misc4;
+ u32 rst_seq_num;
+};
+
+/*
+ * ABTS info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_abts_info {
+ __le16 aborted_task_id;
+ __le16 reserved0;
+ __le32 reserved1;
+};
+
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_abts_rsp_union {
+ u8 r_ctl;
+ u8 rsrv[3];
+ __le32 abts_rsp_payload[7];
+};
+
+
+/*
+ * 4 regs size $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_bd_ctx {
+ __le32 buf_addr_hi;
+ __le32 buf_addr_lo;
+ __le16 buf_len;
+ __le16 rsrv0;
+ __le16 flags;
+ __le16 rsrv1;
+};
+
+
+/*
+ * FCoE cached sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cached_sge_ctx {
+ struct regpair cur_buf_addr;
+ __le16 cur_buf_rem;
+ __le16 second_buf_rem;
+ struct regpair second_buf_addr;
+};
+
+
+/*
+ * Cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cleanup_info {
+ __le16 cleaned_task_id;
+ __le16 rolled_tx_seq_cnt;
+ __le32 rolled_tx_data_offset;
+};
+
+
+/*
+ * Fcp RSP flags $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_rsp_flags {
+ u8 flags;
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
+};
+
+/*
+ * Fcp RSP payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_rsp_payload {
+ struct regpair reserved0;
+ __le32 fcp_resid;
+ u8 scsi_status_code;
+ struct fcoe_fcp_rsp_flags fcp_flags;
+ __le16 retry_delay_timer;
+ __le32 fcp_rsp_len;
+ __le32 fcp_sns_len;
+};
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_rsp_union {
+ struct fcoe_fcp_rsp_payload payload;
+ struct regpair reserved0;
+};
+
+/*
+ * FC header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_hdr {
+ u8 s_id[3];
+ u8 cs_ctl;
+ u8 d_id[3];
+ u8 r_ctl;
+ __le16 seq_cnt;
+ u8 df_ctl;
+ u8 seq_id;
+ u8 f_ctl[3];
+ u8 type;
+ __le32 parameters;
+ __le16 rx_id;
+ __le16 ox_id;
+};
+
+/*
+ * FC header union $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mp_rsp_union {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 mp_payload_len;
+ __le32 rsrv;
+};
+
+/*
+ * Completion information $$KEEP_ENDIANNESS$$
+ */
+union fcoe_comp_flow_info {
+ struct fcoe_fcp_rsp_union fcp_rsp;
+ struct fcoe_abts_rsp_union abts_rsp;
+ struct fcoe_mp_rsp_union mp_rsp;
+ __le32 opaque[8];
+};
+
+
+/*
+ * External ABTS info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_abts_info {
+ __le32 rsrv0[6];
+ struct fcoe_abts_info ctx;
+};
+
+
+/*
+ * External cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_cleanup_info {
+ __le32 rsrv0[6];
+ struct fcoe_cleanup_info ctx;
+};
+
+
+/*
+ * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fw_tx_seq_ctx {
+ __le32 data_offset;
+ __le16 seq_cnt;
+ __le16 rsrv0;
+};
+
+/*
+ * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_fw_tx_seq_ctx {
+ __le32 rsrv0[6];
+ struct fcoe_fw_tx_seq_ctx ctx;
+};
+
+
+/*
+ * FCoE multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mul_sges_ctx {
+ struct regpair cur_sge_addr;
+ __le16 cur_sge_off;
+ u8 cur_sge_idx;
+ u8 sgl_size;
+};
+
+/*
+ * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_mul_sges_ctx {
+ struct fcoe_mul_sges_ctx mul_sgl;
+ struct regpair rsrv0;
+};
+
+
+/*
+ * FCP CMD payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_cmd_payload {
+ __le32 opaque[8];
+};
+
+
+
+
+
+/*
+ * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_xfr_rdy_payload {
+ __le32 burst_len;
+ __le32 data_ro;
+};
+
+
+/*
+ * FC frame $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_frame {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 reserved0[2];
+};
+
+
+
+
+/*
+ * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
+ */
+union fcoe_kcqe_params {
+ __le32 reserved0[4];
+};
+
+/*
+ * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kcqe {
+ __le32 fcoe_conn_id;
+ __le32 completion_status;
+ __le32 fcoe_conn_context_id;
+ union fcoe_kcqe_params params;
+ __le16 qe_self_seq;
+ u8 op_code;
+ u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+};
+
+
+
+/*
+ * FCoE KWQE header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_header {
+ u8 op_code;
+ u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+};
+
+/*
+ * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init1 {
+ __le16 num_tasks;
+ struct fcoe_kwqe_header hdr;
+ __le32 task_list_pbl_addr_lo;
+ __le32 task_list_pbl_addr_hi;
+ __le32 dummy_buffer_addr_lo;
+ __le32 dummy_buffer_addr_hi;
+ __le16 sq_num_wqes;
+ __le16 rq_num_wqes;
+ __le16 rq_buffer_log_size;
+ __le16 cq_num_wqes;
+ __le16 mtu;
+ u8 num_sessions_log;
+ u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+};
+
+/*
+ * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init2 {
+ u8 hsi_major_version;
+ u8 hsi_minor_version;
+ struct fcoe_kwqe_header hdr;
+ __le32 hash_tbl_pbl_addr_lo;
+ __le32 hash_tbl_pbl_addr_hi;
+ __le32 t2_hash_tbl_addr_lo;
+ __le32 t2_hash_tbl_addr_hi;
+ __le32 t2_ptr_hash_tbl_addr_lo;
+ __le32 t2_ptr_hash_tbl_addr_hi;
+ __le32 free_list_count;
+};
+
+/*
+ * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init3 {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 error_bit_map_lo;
+ __le32 error_bit_map_hi;
+ u8 perf_config;
+ u8 reserved21[3];
+ __le32 reserved2[4];
+};
+
+/*
+ * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload1 {
+ __le16 fcoe_conn_id;
+ struct fcoe_kwqe_header hdr;
+ __le32 sq_addr_lo;
+ __le32 sq_addr_hi;
+ __le32 rq_pbl_addr_lo;
+ __le32 rq_pbl_addr_hi;
+ __le32 rq_first_pbe_addr_lo;
+ __le32 rq_first_pbe_addr_hi;
+ __le16 rq_prod;
+ __le16 reserved0;
+};
+
+/*
+ * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload2 {
+ __le16 tx_max_fc_pay_len;
+ struct fcoe_kwqe_header hdr;
+ __le32 cq_addr_lo;
+ __le32 cq_addr_hi;
+ __le32 xferq_addr_lo;
+ __le32 xferq_addr_hi;
+ __le32 conn_db_addr_lo;
+ __le32 conn_db_addr_hi;
+ __le32 reserved1;
+};
+
+/*
+ * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload3 {
+ __le16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+ struct fcoe_kwqe_header hdr;
+ u8 s_id[3];
+ u8 tx_max_conc_seqs_c3;
+ u8 d_id[3];
+ u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+ __le32 reserved;
+ __le32 confq_first_pbe_addr_lo;
+ __le32 confq_first_pbe_addr_hi;
+ __le16 tx_total_conc_seqs;
+ __le16 rx_max_fc_pay_len;
+ __le16 rx_total_conc_seqs;
+ u8 rx_max_conc_seqs_c3;
+ u8 rx_open_seqs_exch_c3;
+};
+
+/*
+ * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload4 {
+ u8 e_d_tov_timer_val;
+ u8 reserved2;
+ struct fcoe_kwqe_header hdr;
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
+ u8 dst_mac_addr_hi[2];
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ __le32 lcq_addr_lo;
+ __le32 lcq_addr_hi;
+ __le32 confq_pbl_base_addr_lo;
+ __le32 confq_pbl_base_addr_hi;
+};
+
+/*
+ * FCoE connection enable request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_enable_disable {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
+ u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ u8 dst_mac_addr_hi[2];
+ __le16 reserved1;
+ u8 s_id[3];
+ u8 vlan_flag;
+ u8 d_id[3];
+ u8 reserved3;
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved4;
+};
+
+/*
+ * FCoE connection destroy request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_destroy {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved1[5];
+};
+
+/*
+ * FCoe destroy request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_destroy {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 reserved1[7];
+};
+
+/*
+ * FCoe statistics request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_stat {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 stat_params_addr_lo;
+ __le32 stat_params_addr_hi;
+ __le32 reserved1[5];
+};
+
+/*
+ * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
+ */
+union fcoe_kwqe {
+ struct fcoe_kwqe_init1 init1;
+ struct fcoe_kwqe_init2 init2;
+ struct fcoe_kwqe_init3 init3;
+ struct fcoe_kwqe_conn_offload1 conn_offload1;
+ struct fcoe_kwqe_conn_offload2 conn_offload2;
+ struct fcoe_kwqe_conn_offload3 conn_offload3;
+ struct fcoe_kwqe_conn_offload4 conn_offload4;
+ struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
+ struct fcoe_kwqe_conn_destroy conn_destroy;
+ struct fcoe_kwqe_destroy destroy;
+ struct fcoe_kwqe_stat statistics;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * TX SGL context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_sgl_union_ctx {
+ struct fcoe_cached_sge_ctx cached_sge;
+ struct fcoe_ext_mul_sges_ctx sgl;
+ __le32 opaque[5];
+};
+
+/*
+ * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_read_flow_info {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0[3];
+};
+
+
+/*
+ * Fcoe stat context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_s_stat_ctx {
+ u8 flags;
+#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
+#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
+#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
+#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
+#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
+#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
+#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
+#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
+};
+
+/*
+ * Fcoe rx seq context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_seq_ctx {
+ u8 seq_id;
+ struct fcoe_s_stat_ctx s_stat;
+ __le16 seq_cnt;
+ __le32 low_exp_ro;
+ __le32 high_exp_ro;
+};
+
+
+/*
+ * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_rx_wr_union_ctx {
+ struct fcoe_read_flow_info read_info;
+ union fcoe_comp_flow_info comp_info;
+ __le32 opaque[8];
+};
+
+
+
+/*
+ * FCoE SQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_sqe {
+ __le16 wqe;
+#define FCOE_SQE_TASK_ID (0x7FFF<<0)
+#define FCOE_SQE_TASK_ID_SHIFT 0
+#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+
+/*
+ * 14 regs $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_only {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0;
+};
+
+/*
+ * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
+ */
+union fcoe_tx_wr_rx_rd_union_ctx {
+ struct fcoe_fc_frame tx_frame;
+ struct fcoe_fcp_cmd_payload fcp_cmd;
+ struct fcoe_ext_cleanup_info cleanup;
+ struct fcoe_ext_abts_info abts;
+ struct fcoe_ext_fw_tx_seq_ctx tx_seq;
+ __le32 opaque[8];
+};
+
+/*
+ * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd_const {
+ u8 init_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
+ u8 tx_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+ __le16 rsrv3;
+ __le32 verify_tx_seq;
+};
+
+/*
+ * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd {
+ union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
+ struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
+};
+
+/*
+ * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_const {
+ __le32 data_2_trns;
+ __le32 init_flags;
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
+};
+
+/*
+ * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_var {
+ __le16 rx_flags;
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
+ __le16 rx_id;
+ struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
+};
+
+/*
+ * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd {
+ struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
+ struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
+};
+
+/*
+ * tce_rx_only $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_only {
+ struct fcoe_rx_seq_ctx rx_seq_ctx;
+ union fcoe_rx_wr_union_ctx union_ctx;
+};
+
+/*
+ * task_ctx_entry $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_task_ctx_entry {
+ struct fcoe_tce_tx_only txwr_only;
+ struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+ struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+ struct fcoe_tce_rx_only rxwr_only;
+};
+
+
+
+
+
+
+
+
+
+
+/*
+ * FCoE XFRQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_xfrqe {
+ __le16 wqe;
+#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
+#define FCOE_XFRQE_TASK_ID_SHIFT 0
+#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * Cached SGEs $$KEEP_ENDIANNESS$$
+ */
+struct common_fcoe_sgl {
+ struct fcoe_bd_ctx sge[3];
+};
+
+
+/*
+ * FCoE SQ\XFRQ element
+ */
+struct fcoe_cached_wqe {
+ struct fcoe_sqe sqe;
+ struct fcoe_xfrqe xfrqe;
+};
+
+
+/*
+ * FCoE connection enable\disable params passed by driver to FW in FCoE enable
+ * ramrod $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_conn_enable_disable_ramrod_params {
+ struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
+};
+
+
+/*
+ * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_conn_offload_ramrod_params {
+ struct fcoe_kwqe_conn_offload1 offload_kwqe1;
+ struct fcoe_kwqe_conn_offload2 offload_kwqe2;
+ struct fcoe_kwqe_conn_offload3 offload_kwqe3;
+ struct fcoe_kwqe_conn_offload4 offload_kwqe4;
+};
+
+
+struct ustorm_fcoe_mng_ctx {
+#if defined(__BIG_ENDIAN)
+ u8 mid_seq_proc_flag;
+ u8 tce_in_cam_flag;
+ u8 tce_on_ior_flag;
+ u8 en_cached_tce_flag;
+#elif defined(__LITTLE_ENDIAN)
+ u8 en_cached_tce_flag;
+ u8 tce_on_ior_flag;
+ u8 tce_in_cam_flag;
+ u8 mid_seq_proc_flag;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 tce_cam_addr;
+ u8 cached_conn_flag;
+ u16 rsrv0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rsrv0;
+ u8 cached_conn_flag;
+ u8 tce_cam_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 dma_tce_ram_addr;
+ u16 tce_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 tce_ram_addr;
+ u16 dma_tce_ram_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 ox_id;
+ u16 wr_done_seq;
+#elif defined(__LITTLE_ENDIAN)
+ u16 wr_done_seq;
+ u16 ox_id;
+#endif
+ struct regpair task_addr;
+};
+
+/*
+ * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and
+ * used in FCoE context section
+ */
+struct ustorm_fcoe_params {
+#if defined(__BIG_ENDIAN)
+ u16 fcoe_conn_id;
+ u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+ u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
+ u16 fcoe_conn_id;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 hc_csdm_byte_en;
+ u8 func_id;
+ u8 port_id;
+ u8 vnic_id;
+#elif defined(__LITTLE_ENDIAN)
+ u8 vnic_id;
+ u8 port_id;
+ u8 func_id;
+ u8 hc_csdm_byte_en;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 rx_total_conc_seqs;
+ u16 rx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rx_max_fc_pay_len;
+ u16 rx_total_conc_seqs;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 task_pbe_idx_off;
+ u8 task_in_page_log_size;
+ u16 rx_max_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rx_max_conc_seqs;
+ u8 task_in_page_log_size;
+ u8 task_pbe_idx_off;
+#endif
+};
+
+/*
+ * FCoE 16-bits index structure
+ */
+struct fcoe_idx16_fields {
+ u16 fields;
+#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
+#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
+#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
+#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
+};
+
+/*
+ * FCoE 16-bits index union
+ */
+union fcoe_idx16_field_union {
+ struct fcoe_idx16_fields fields;
+ u16 val;
+};
+
+/*
+ * Parameters required for placement according to SGL
+ */
+struct ustorm_fcoe_data_place_mng {
+#if defined(__BIG_ENDIAN)
+ u16 sge_off;
+ u8 num_sges;
+ u8 sge_idx;
+#elif defined(__LITTLE_ENDIAN)
+ u8 sge_idx;
+ u8 num_sges;
+ u16 sge_off;
+#endif
+};
+
+/*
+ * Parameters required for placement according to SGL
+ */
+struct ustorm_fcoe_data_place {
+ struct ustorm_fcoe_data_place_mng cached_mng;
+ struct fcoe_bd_ctx cached_sge[2];
+};
+
+/*
+ * TX processing shall write and RX processing shall read from this section
+ */
+union fcoe_u_tce_tx_wr_rx_rd_union {
+ struct fcoe_abts_info abts;
+ struct fcoe_cleanup_info cleanup;
+ struct fcoe_fw_tx_seq_ctx tx_seq_ctx;
+ u32 opaque[2];
+};
+
+/*
+ * TX processing shall write and RX processing shall read from this section
+ */
+struct fcoe_u_tce_tx_wr_rx_rd {
+ union fcoe_u_tce_tx_wr_rx_rd_union union_ctx;
+ struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
+};
+
+struct ustorm_fcoe_tce {
+ struct fcoe_u_tce_tx_wr_rx_rd txwr_rxrd;
+ struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+ struct fcoe_tce_rx_only rxwr;
+};
+
+struct ustorm_fcoe_cache_ctx {
+ u32 rsrv0;
+ struct ustorm_fcoe_data_place data_place;
+ struct ustorm_fcoe_tce tce;
+};
+
+/*
+ * Ustorm FCoE Storm Context
+ */
+struct ustorm_fcoe_st_context {
+ struct ustorm_fcoe_mng_ctx mng_ctx;
+ struct ustorm_fcoe_params fcoe_params;
+ struct regpair cq_base_addr;
+ struct regpair rq_pbl_base;
+ struct regpair rq_cur_page_addr;
+ struct regpair confq_pbl_base_addr;
+ struct regpair conn_db_base;
+ struct regpair xfrq_base_addr;
+ struct regpair lcq_base_addr;
+#if defined(__BIG_ENDIAN)
+ union fcoe_idx16_field_union rq_cons;
+ union fcoe_idx16_field_union rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+ union fcoe_idx16_field_union rq_prod;
+ union fcoe_idx16_field_union rq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 xfrq_prod;
u16 cq_cons;
#elif defined(__LITTLE_ENDIAN)
u16 cq_cons;
- u16 cq_prod;
+ u16 xfrq_prod;
#endif
#if defined(__BIG_ENDIAN)
- u16 __reserved2;
- u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
- u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+ u16 lcq_cons;
+ u16 hc_cram_address;
#elif defined(__LITTLE_ENDIAN)
- u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
- u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
- u16 __reserved2;
+ u16 hc_cram_address;
+ u16 lcq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 sq_xfrq_lcq_confq_size;
+ u16 confq_prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 confq_prod;
+ u16 sq_xfrq_lcq_confq_size;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 hc_csdm_agg_int;
+ u8 rsrv2;
+ u8 available_rqes;
+ u8 sp_q_flush_cnt;
+#elif defined(__LITTLE_ENDIAN)
+ u8 sp_q_flush_cnt;
+ u8 available_rqes;
+ u8 rsrv2;
+ u8 hc_csdm_agg_int;
#endif
+#if defined(__BIG_ENDIAN)
+ u16 num_pend_tasks;
+ u16 pbf_ack_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 pbf_ack_ram_addr;
+ u16 num_pend_tasks;
+#endif
+ struct ustorm_fcoe_cache_ctx cache_ctx;
+};
+
+/*
+ * The FCoE non-aggregative context of Tstorm
+ */
+struct tstorm_fcoe_st_context {
+ struct regpair reserved0;
+ struct regpair reserved1;
};
/*
@@ -2023,86 +3470,106 @@ struct xstorm_fcoe_context_flags {
#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q_SHIFT 0
#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ (0x1<<2)
#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ_SHIFT 2
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED (0x1<<3)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED_SHIFT 3
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ (0x1<<3)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ_SHIFT 3
#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT (0x1<<4)
#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT_SHIFT 4
#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE (0x1<<5)
#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE_SHIFT 5
#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE (0x1<<6)
#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE_SHIFT 6
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED (0x1<<7)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED_SHIFT 7
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN (0x1<<7)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN_SHIFT 7
};
-/*
- * FCoE SQ element
- */
-struct fcoe_sqe {
- u16 wqe;
-#define FCOE_SQE_TASK_ID (0x7FFF<<0)
-#define FCOE_SQE_TASK_ID_SHIFT 0
-#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
-#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
-};
-
-/*
- * FCoE XFRQ element
- */
-struct fcoe_xfrqe {
- u16 wqe;
-#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
-#define FCOE_XFRQE_TASK_ID_SHIFT 0
-#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
-#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
+struct xstorm_fcoe_tce {
+ struct fcoe_tce_tx_only txwr;
+ struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
};
/*
- * FCoE SQ\XFRQ element
+ * FCP_DATA parameters required for transmission
*/
-struct fcoe_cached_wqe {
+struct xstorm_fcoe_fcp_data {
+ u32 io_rem;
#if defined(__BIG_ENDIAN)
- struct fcoe_xfrqe xfrqe;
- struct fcoe_sqe sqe;
+ u16 cached_sge_off;
+ u8 cached_num_sges;
+ u8 cached_sge_idx;
#elif defined(__LITTLE_ENDIAN)
- struct fcoe_sqe sqe;
- struct fcoe_xfrqe xfrqe;
+ u8 cached_sge_idx;
+ u8 cached_num_sges;
+ u16 cached_sge_off;
+#endif
+ u32 buf_addr_hi_0;
+ u32 buf_addr_lo_0;
+#if defined(__BIG_ENDIAN)
+ u16 num_of_pending_tasks;
+ u16 buf_len_0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 buf_len_0;
+ u16 num_of_pending_tasks;
+#endif
+ u32 buf_addr_hi_1;
+ u32 buf_addr_lo_1;
+#if defined(__BIG_ENDIAN)
+ u16 task_pbe_idx_off;
+ u16 buf_len_1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 buf_len_1;
+ u16 task_pbe_idx_off;
+#endif
+ u32 buf_addr_hi_2;
+ u32 buf_addr_lo_2;
+#if defined(__BIG_ENDIAN)
+ u16 ox_id;
+ u16 buf_len_2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 buf_len_2;
+ u16 ox_id;
#endif
};
-struct fcoe_task_ctx_entry_tx_only {
- union fcoe_sgl_ctx sgl_ctx;
+/*
+ * vlan configuration
+ */
+struct xstorm_fcoe_vlan_conf {
+ u8 vlan_conf;
+#define XSTORM_FCOE_VLAN_CONF_PRIORITY (0x7<<0)
+#define XSTORM_FCOE_VLAN_CONF_PRIORITY_SHIFT 0
+#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG (0x1<<3)
+#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG_SHIFT 3
+#define XSTORM_FCOE_VLAN_CONF_RESERVED (0xF<<4)
+#define XSTORM_FCOE_VLAN_CONF_RESERVED_SHIFT 4
};
-struct xstorm_fcoe_task_ctx_entry_rd {
- struct fcoe_task_ctx_entry_tx_only tx_wr;
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
+/*
+ * FCoE 16-bits vlan structure
+ */
+struct fcoe_vlan_fields {
+ u16 fields;
+#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
+#define FCOE_VLAN_FIELDS_VID_SHIFT 0
+#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
+#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
+#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
+#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
};
/*
- * Cached SGEs
+ * FCoE 16-bits vlan union
*/
-struct common_fcoe_sgl {
- struct fcoe_bd_ctx sge[2];
+union fcoe_vlan_field_union {
+ struct fcoe_vlan_fields fields;
+ u16 val;
};
/*
- * FCP_DATA parameters required for transmission
+ * FCoE 16-bits vlan, vif union
*/
-struct xstorm_fcoe_fcp_data {
- u32 io_rem;
-#if defined(__BIG_ENDIAN)
- u16 cached_sge_off;
- u8 cached_num_sges;
- u8 cached_sge_idx;
-#elif defined(__LITTLE_ENDIAN)
- u8 cached_sge_idx;
- u8 cached_num_sges;
- u16 cached_sge_off;
-#endif
- struct common_fcoe_sgl cached_sgl;
+union fcoe_vlan_vif_field_union {
+ union fcoe_vlan_field_union vlan;
+ u16 vif;
};
/*
@@ -2110,18 +3577,18 @@ struct xstorm_fcoe_fcp_data {
*/
struct xstorm_fcoe_context_section {
#if defined(__BIG_ENDIAN)
- u8 vlan_flag;
+ u8 cs_ctl;
u8 s_id[3];
#elif defined(__LITTLE_ENDIAN)
u8 s_id[3];
- u8 vlan_flag;
+ u8 cs_ctl;
#endif
#if defined(__BIG_ENDIAN)
- u8 func_id;
+ u8 rctl;
u8 d_id[3];
#elif defined(__LITTLE_ENDIAN)
u8 d_id[3];
- u8 func_id;
+ u8 rctl;
#endif
#if defined(__BIG_ENDIAN)
u16 sq_xfrq_lcq_confq_size;
@@ -2133,56 +3600,84 @@ struct xstorm_fcoe_context_section {
u32 lcq_prod;
#if defined(__BIG_ENDIAN)
u8 port_id;
- u8 tx_max_conc_seqs_c3;
+ u8 func_id;
u8 seq_id;
struct xstorm_fcoe_context_flags tx_flags;
#elif defined(__LITTLE_ENDIAN)
struct xstorm_fcoe_context_flags tx_flags;
u8 seq_id;
- u8 tx_max_conc_seqs_c3;
+ u8 func_id;
u8 port_id;
#endif
#if defined(__BIG_ENDIAN)
- u16 verify_tx_seq;
+ u16 mtu;
u8 func_mode;
u8 vnic_id;
#elif defined(__LITTLE_ENDIAN)
u8 vnic_id;
u8 func_mode;
- u16 verify_tx_seq;
+ u16 mtu;
#endif
struct regpair confq_curr_page_addr;
struct fcoe_cached_wqe cached_wqe[8];
struct regpair lcq_base_addr;
- struct xstorm_fcoe_task_ctx_entry_rd tce;
+ struct xstorm_fcoe_tce tce;
struct xstorm_fcoe_fcp_data fcp_data;
#if defined(__BIG_ENDIAN)
+ u8 tx_max_conc_seqs_c3;
+ u8 vlan_flag;
+ u8 dcb_val;
+ u8 data_pb_cmd_size;
+#elif defined(__LITTLE_ENDIAN)
+ u8 data_pb_cmd_size;
+ u8 dcb_val;
+ u8 vlan_flag;
+ u8 tx_max_conc_seqs_c3;
+#endif
+#if defined(__BIG_ENDIAN)
u16 fcoe_tx_stat_params_ram_addr;
- u16 cmng_port_ram_addr;
+ u16 fcoe_tx_fc_seq_ram_addr;
#elif defined(__LITTLE_ENDIAN)
- u16 cmng_port_ram_addr;
+ u16 fcoe_tx_fc_seq_ram_addr;
u16 fcoe_tx_stat_params_ram_addr;
#endif
#if defined(__BIG_ENDIAN)
- u8 fcp_cmd_pb_cmd_size;
+ u8 fcp_cmd_line_credit;
u8 eth_hdr_size;
u16 pbf_addr;
#elif defined(__LITTLE_ENDIAN)
u16 pbf_addr;
u8 eth_hdr_size;
- u8 fcp_cmd_pb_cmd_size;
+ u8 fcp_cmd_line_credit;
#endif
#if defined(__BIG_ENDIAN)
- u8 reserved2[2];
+ union fcoe_vlan_vif_field_union multi_func_val;
+ u8 page_log_size;
+ struct xstorm_fcoe_vlan_conf orig_vlan_conf;
+#elif defined(__LITTLE_ENDIAN)
+ struct xstorm_fcoe_vlan_conf orig_vlan_conf;
+ u8 page_log_size;
+ union fcoe_vlan_vif_field_union multi_func_val;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 fcp_cmd_frame_size;
+ u16 pbf_addr_ff;
+#elif defined(__LITTLE_ENDIAN)
+ u16 pbf_addr_ff;
+ u16 fcp_cmd_frame_size;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 vlan_num;
u8 cos;
- u8 dcb_version;
+ u8 cache_xfrq_cons;
+ u8 cache_sq_cons;
#elif defined(__LITTLE_ENDIAN)
- u8 dcb_version;
+ u8 cache_sq_cons;
+ u8 cache_xfrq_cons;
u8 cos;
- u8 reserved2[2];
+ u8 vlan_num;
#endif
- u32 reserved3;
- struct regpair reserved4[2];
+ u32 verify_tx_seq;
};
/*
@@ -2207,6 +3702,181 @@ struct fcoe_context {
};
/*
+ * FCoE init params passed by driver to FW in FCoE init ramrod
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_init_ramrod_params {
+ struct fcoe_kwqe_init1 init_kwqe1;
+ struct fcoe_kwqe_init2 init_kwqe2;
+ struct fcoe_kwqe_init3 init_kwqe3;
+ struct regpair eq_pbl_base;
+ __le32 eq_pbl_size;
+ __le32 reserved2;
+ __le16 eq_prod;
+ __le16 sb_num;
+ u8 sb_id;
+ u8 reserved0;
+ __le16 reserved1;
+};
+
+/*
+ * FCoE statistics params buffer passed by driver to FW in FCoE statistics
+ * ramrod $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_stat_ramrod_params {
+ struct fcoe_kwqe_stat stat_kwqe;
+};
+
+/*
+ * CQ DB CQ producer and pending completion counter
+ */
+struct iscsi_cq_db_prod_pnd_cmpltn_cnt {
+#if defined(__BIG_ENDIAN)
+ u16 cntr;
+ u16 prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 prod;
+ u16 cntr;
+#endif
+};
+
+/*
+ * CQ DB pending completion ITT array
+ */
+struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr {
+ struct iscsi_cq_db_prod_pnd_cmpltn_cnt prod_pend_comp[8];
+};
+
+/*
+ * Cstorm CQ sequence to notify array, updated by driver
+ */
+struct iscsi_cq_db_sqn_2_notify_arr {
+ u16 sqn[8];
+};
+
+/*
+ * Cstorm iSCSI Storm Context
+ */
+struct cstorm_iscsi_st_context {
+ struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr cq_c_prod_pend_comp_ctr_arr;
+ struct iscsi_cq_db_sqn_2_notify_arr cq_c_prod_sqn_arr;
+ struct iscsi_cq_db_sqn_2_notify_arr cq_c_sqn_2_notify_arr;
+ struct regpair hq_pbl_base;
+ struct regpair hq_curr_pbe;
+ struct regpair task_pbl_base;
+ struct regpair cq_db_base;
+#if defined(__BIG_ENDIAN)
+ u16 hq_bd_itt;
+ u16 iscsi_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+ u16 iscsi_conn_id;
+ u16 hq_bd_itt;
+#endif
+ u32 hq_bd_data_segment_len;
+ u32 hq_bd_buffer_offset;
+#if defined(__BIG_ENDIAN)
+ u8 rsrv;
+ u8 cq_proc_en_bit_map;
+ u8 cq_pend_comp_itt_valid_bit_map;
+ u8 hq_bd_opcode;
+#elif defined(__LITTLE_ENDIAN)
+ u8 hq_bd_opcode;
+ u8 cq_pend_comp_itt_valid_bit_map;
+ u8 cq_proc_en_bit_map;
+ u8 rsrv;
+#endif
+ u32 hq_tcp_seq;
+#if defined(__BIG_ENDIAN)
+ u16 flags;
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
+ u16 hq_cons;
+#elif defined(__LITTLE_ENDIAN)
+ u16 hq_cons;
+ u16 flags;
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
+#endif
+ struct regpair rsrv1;
+};
+
+
+/*
+ * SCSI read/write SQ WQE
+ */
+struct iscsi_cmd_pdu_hdr_little_endian {
+#if defined(__BIG_ENDIAN)
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u16 rsrv0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u8 opcode;
+#endif
+ u32 data_fields;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 expected_data_transfer_length;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 scsi_command_block[4];
+};
+
+
+/*
+ * Buffer per connection, used in Tstorm
+ */
+struct iscsi_conn_buf {
+ struct regpair reserved[8];
+};
+
+
+/*
* iSCSI context region, used only in iSCSI
*/
struct ustorm_iscsi_rq_db {
@@ -2271,11 +3941,13 @@ struct ustorm_iscsi_placement_db {
u32 local_sge_1_address_hi;
u32 local_sge_1_address_lo;
#if defined(__BIG_ENDIAN)
- u16 reserved6;
+ u8 exp_padding_2b;
+ u8 nal_len_3b;
u16 local_sge_1_size;
#elif defined(__LITTLE_ENDIAN)
u16 local_sge_1_size;
- u16 reserved6;
+ u8 nal_len_3b;
+ u8 exp_padding_2b;
#endif
#if defined(__BIG_ENDIAN)
u8 sgl_size;
@@ -2300,12 +3972,8 @@ struct ustorm_iscsi_placement_db {
u32 nal;
#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE (0xFFFFFF<<0)
#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_PADDING_2B (0x3<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_PADDING_2B_SHIFT 24
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B (0x7<<26)
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B_SHIFT 26
-#define USTORM_ISCSI_PLACEMENT_DB_NAL_LEN_3B (0x7<<29)
-#define USTORM_ISCSI_PLACEMENT_DB_NAL_LEN_3B_SHIFT 29
+#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B (0xFF<<24)
+#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B_SHIFT 24
};
/*
@@ -2509,7 +4177,13 @@ struct tstorm_tcp_st_context_section {
u16 vlan_id;
u16 lsb_mac_address;
#endif
- u32 msb_mac_address;
+#if defined(__BIG_ENDIAN)
+ u16 msb_mac_address;
+ u16 mid_mac_address;
+#elif defined(__LITTLE_ENDIAN)
+ u16 mid_mac_address;
+ u16 msb_mac_address;
+#endif
u32 rightmost_received_seq;
};
@@ -2534,13 +4208,7 @@ struct iscsi_term_vars {
* iSCSI context region, used only in iSCSI
*/
struct tstorm_iscsi_st_context_section {
-#if defined(__BIG_ENDIAN)
- u16 rem_tcp_data_len;
- u16 brb_offset;
-#elif defined(__LITTLE_ENDIAN)
- u16 brb_offset;
- u16 rem_tcp_data_len;
-#endif
+ u32 nalPayload;
u32 b2nh;
#if defined(__BIG_ENDIAN)
u16 rq_cons;
@@ -2555,8 +4223,10 @@ struct tstorm_iscsi_st_context_section {
#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV (0x7<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
u8 hdr_bytes_2_fetch;
#elif defined(__LITTLE_ENDIAN)
u8 hdr_bytes_2_fetch;
@@ -2571,18 +4241,20 @@ struct tstorm_iscsi_st_context_section {
#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV (0x7<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
u16 rq_cons;
#endif
struct regpair rq_db_phy_addr;
#if defined(__BIG_ENDIAN)
struct iscsi_term_vars term_vars;
- u8 scratchpad_idx;
+ u8 rsrv1;
u16 iscsi_conn_id;
#elif defined(__LITTLE_ENDIAN)
u16 iscsi_conn_id;
- u8 scratchpad_idx;
+ u8 rsrv1;
struct iscsi_term_vars term_vars;
#endif
u32 process_nxt;
@@ -2597,724 +4269,6 @@ struct tstorm_iscsi_st_context {
};
/*
- * The tcp aggregative context section of Xstorm
- */
-struct xstorm_tcp_tcp_ag_context_section {
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars1;
- u8 __da_cnt;
- u16 mss;
-#elif defined(__LITTLE_ENDIAN)
- u16 mss;
- u8 __da_cnt;
- u8 __tcp_agg_vars1;
-#endif
- u32 snd_nxt;
- u32 tx_wnd;
- u32 snd_una;
- u32 local_adv_wnd;
-#if defined(__BIG_ENDIAN)
- u8 __agg_val8_th;
- u8 __agg_val8;
- u16 tcp_agg_vars2;
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN_SHIFT 7
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
-#elif defined(__LITTLE_ENDIAN)
- u16 tcp_agg_vars2;
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN_SHIFT 7
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
- u8 __agg_val8;
- u8 __agg_val8_th;
-#endif
- u32 ack_to_far_end;
- u32 rto_timer;
- u32 ka_timer;
- u32 ts_to_echo;
-#if defined(__BIG_ENDIAN)
- u16 __agg_val7_th;
- u16 __agg_val7;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val7;
- u16 __agg_val7_th;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars5;
- u8 __tcp_agg_vars4;
- u8 __tcp_agg_vars3;
- u8 __force_pure_ack_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u8 __force_pure_ack_cnt;
- u8 __tcp_agg_vars3;
- u8 __tcp_agg_vars4;
- u8 __tcp_agg_vars5;
-#endif
- u32 tcp_agg_vars6;
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN (0x1<<0)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_EN (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_EN_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG_SHIFT 4
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG (0x1<<5)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF (0x3<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF (0x3<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_SHIFT 14
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF (0x3<<16)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF_SHIFT 16
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF (0x3<<18)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF_SHIFT 18
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF (0x3<<20)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF_SHIFT 20
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF (0x3<<22)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF_SHIFT 22
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF (0x3<<24)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF_SHIFT 24
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG (0x1<<26)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG_SHIFT 26
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71 (0x1<<27)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71_SHIFT 27
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY (0x1<<28)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY_SHIFT 28
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG (0x1<<29)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG_SHIFT 29
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG (0x1<<30)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG_SHIFT 30
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG (0x1<<31)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG_SHIFT 31
-#if defined(__BIG_ENDIAN)
- u16 __agg_misc6;
- u16 __tcp_agg_vars7;
-#elif defined(__LITTLE_ENDIAN)
- u16 __tcp_agg_vars7;
- u16 __agg_misc6;
-#endif
- u32 __agg_val10;
- u32 __agg_val10_th;
-#if defined(__BIG_ENDIAN)
- u16 __reserved3;
- u8 __reserved2;
- u8 __da_only_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u8 __da_only_cnt;
- u8 __reserved2;
- u16 __reserved3;
-#endif
-};
-
-/*
- * The iscsi aggregative context of Xstorm
- */
-struct xstorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
- u16 agg_val1;
- u8 agg_vars1;
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
- u8 state;
-#elif defined(__LITTLE_ENDIAN)
- u8 state;
- u8 agg_vars1;
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
- u16 agg_val1;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 cdu_reserved;
- u8 __agg_vars4;
- u8 agg_vars3;
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
- u8 agg_vars2;
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
- u8 agg_vars2;
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
- u8 agg_vars3;
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
- u8 __agg_vars4;
- u8 cdu_reserved;
-#endif
- u32 more_to_send;
-#if defined(__BIG_ENDIAN)
- u16 agg_vars5;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
- u16 sq_cons;
-#elif defined(__LITTLE_ENDIAN)
- u16 sq_cons;
- u16 agg_vars5;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
-#endif
- struct xstorm_tcp_tcp_ag_context_section tcp;
-#if defined(__BIG_ENDIAN)
- u16 agg_vars7;
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
- u8 agg_val3_th;
- u8 agg_vars6;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
-#elif defined(__LITTLE_ENDIAN)
- u8 agg_vars6;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
- u8 agg_val3_th;
- u16 agg_vars7;
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val11_th;
- u16 __gen_data;
-#elif defined(__LITTLE_ENDIAN)
- u16 __gen_data;
- u16 __agg_val11_th;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __reserved1;
- u8 __agg_val6_th;
- u16 __agg_val9;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val9;
- u8 __agg_val6_th;
- u8 __reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 hq_prod;
- u16 hq_cons;
-#elif defined(__LITTLE_ENDIAN)
- u16 hq_cons;
- u16 hq_prod;
-#endif
- u32 agg_vars8;
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3_SHIFT 24
-#if defined(__BIG_ENDIAN)
- u16 r2tq_prod;
- u16 sq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 sq_prod;
- u16 r2tq_prod;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 agg_val3;
- u8 agg_val6;
- u8 agg_val5_th;
- u8 agg_val5;
-#elif defined(__LITTLE_ENDIAN)
- u8 agg_val5;
- u8 agg_val5_th;
- u8 agg_val6;
- u8 agg_val3;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_misc1;
- u16 agg_limit1;
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_limit1;
- u16 __agg_misc1;
-#endif
- u32 hq_cons_tcp_seq;
- u32 exp_stat_sn;
- u32 rst_seq_num;
-};
-
-/*
- * The tcp aggregative context section of Tstorm
- */
-struct tstorm_tcp_tcp_ag_context_section {
- u32 __agg_val1;
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars2;
- u8 __agg_val3;
- u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val2;
- u8 __agg_val3;
- u8 __tcp_agg_vars2;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val5;
- u8 __agg_val6;
- u8 __tcp_agg_vars3;
-#elif defined(__LITTLE_ENDIAN)
- u8 __tcp_agg_vars3;
- u8 __agg_val6;
- u16 __agg_val5;
-#endif
- u32 snd_nxt;
- u32 rtt_seq;
- u32 rtt_time;
- u32 __reserved66;
- u32 wnd_right_edge;
- u32 tcp_agg_vars1;
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN (0x1<<9)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN_SHIFT 9
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
- u32 snd_max;
- u32 snd_una;
- u32 __reserved2;
-};
-
-/*
- * The iscsi aggregative context of Tstorm
- */
-struct tstorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
- u16 ulp_credit;
- u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
- u8 state;
-#elif defined(__LITTLE_ENDIAN)
- u8 state;
- u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
- u16 ulp_credit;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val4;
- u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
- u16 __agg_val4;
-#endif
- struct tstorm_tcp_tcp_ag_context_section tcp;
-};
-
-/*
- * The iscsi aggregative context of Ustorm
- */
-struct ustorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
- u8 __aux_counter_flags;
- u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
- u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
- u8 state;
-#elif defined(__LITTLE_ENDIAN)
- u8 state;
- u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
- u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
- u8 __aux_counter_flags;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 cdu_usage;
- u8 agg_misc2;
- u16 __cq_local_comp_itt_val;
-#elif defined(__LITTLE_ENDIAN)
- u16 __cq_local_comp_itt_val;
- u8 agg_misc2;
- u8 cdu_usage;
-#endif
- u32 agg_misc4;
-#if defined(__BIG_ENDIAN)
- u8 agg_val3_th;
- u8 agg_val3;
- u16 agg_misc3;
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_misc3;
- u8 agg_val3;
- u8 agg_val3_th;
-#endif
- u32 agg_val1;
- u32 agg_misc4_th;
-#if defined(__BIG_ENDIAN)
- u16 agg_val2_th;
- u16 agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_val2;
- u16 agg_val2_th;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __reserved2;
- u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
- u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
- u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
- u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
- u16 __reserved2;
-#endif
-};
-
-/*
* Ethernet context section, shared in TOE, RDMA and ISCSI
*/
struct xstorm_eth_context_section {
@@ -3509,7 +4463,27 @@ struct xstorm_tcp_context_section {
u16 window_scaling_factor;
u16 pseudo_csum;
#endif
- u32 reserved2;
+#if defined(__BIG_ENDIAN)
+ u16 reserved2;
+ u8 statistics_counter_id;
+ u8 statistics_params;
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
+#elif defined(__LITTLE_ENDIAN)
+ u8 statistics_params;
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
+ u8 statistics_counter_id;
+ u16 reserved2;
+#endif
u32 ts_time_diff;
u32 __next_timer_expir;
};
@@ -3522,29 +4496,31 @@ struct xstorm_common_context_section {
union xstorm_ip_context_section_types ip_union;
struct xstorm_tcp_context_section tcp;
#if defined(__BIG_ENDIAN)
- u16 reserved;
- u8 statistics_params;
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
+ u8 __dcb_val;
+ u8 flags;
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
+ u8 reserved;
u8 ip_version_1b;
#elif defined(__LITTLE_ENDIAN)
u8 ip_version_1b;
- u8 statistics_params;
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
- u16 reserved;
+ u8 reserved;
+ u8 flags;
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
+ u8 __dcb_val;
#endif
};
@@ -3682,99 +4658,6 @@ struct xstorm_iscsi_st_context {
};
/*
- * CQ DB CQ producer and pending completion counter
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt {
-#if defined(__BIG_ENDIAN)
- u16 cntr;
- u16 prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 prod;
- u16 cntr;
-#endif
-};
-
-/*
- * CQ DB pending completion ITT array
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr {
- struct iscsi_cq_db_prod_pnd_cmpltn_cnt prod_pend_comp[8];
-};
-
-/*
- * Cstorm CQ sequence to notify array, updated by driver
- */
-struct iscsi_cq_db_sqn_2_notify_arr {
- u16 sqn[8];
-};
-
-/*
- * Cstorm iSCSI Storm Context
- */
-struct cstorm_iscsi_st_context {
- struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr cq_c_prod_pend_comp_ctr_arr;
- struct iscsi_cq_db_sqn_2_notify_arr cq_c_prod_sqn_arr;
- struct iscsi_cq_db_sqn_2_notify_arr cq_c_sqn_2_notify_arr;
- struct regpair hq_pbl_base;
- struct regpair hq_curr_pbe;
- struct regpair task_pbl_base;
- struct regpair cq_db_base;
-#if defined(__BIG_ENDIAN)
- u16 hq_bd_itt;
- u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 iscsi_conn_id;
- u16 hq_bd_itt;
-#endif
- u32 hq_bd_data_segment_len;
- u32 hq_bd_buffer_offset;
-#if defined(__BIG_ENDIAN)
- u8 timer_entry_idx;
- u8 cq_proc_en_bit_map;
- u8 cq_pend_comp_itt_valid_bit_map;
- u8 hq_bd_opcode;
-#elif defined(__LITTLE_ENDIAN)
- u8 hq_bd_opcode;
- u8 cq_pend_comp_itt_valid_bit_map;
- u8 cq_proc_en_bit_map;
- u8 timer_entry_idx;
-#endif
- u32 hq_tcp_seq;
-#if defined(__BIG_ENDIAN)
- u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
- u16 hq_cons;
-#elif defined(__LITTLE_ENDIAN)
- u16 hq_cons;
- u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
-#endif
- struct regpair rsrv1;
-};
-
-/*
* Iscsi connection context
*/
struct iscsi_context {
@@ -3791,583 +4674,388 @@ struct iscsi_context {
struct cstorm_iscsi_st_context cstorm_st_context;
};
-/*
- * FCoE KCQ CQE parameters
- */
-union fcoe_kcqe_params {
- u32 reserved0[4];
-};
/*
- * FCoE KCQ CQE
+ * PDU header of an iSCSI DATA-OUT
*/
-struct fcoe_kcqe {
- u32 fcoe_conn_id;
- u32 completion_status;
- u32 fcoe_conn_context_id;
- union fcoe_kcqe_params params;
+struct iscsi_data_pdu_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
- u8 op_code;
- u16 qe_self_seq;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 qe_self_seq;
- u8 op_code;
- u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u8 opcode;
#endif
+ u32 data_fields;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 ttt;
+ u32 rsrv2;
+ u32 exp_stat_sn;
+ u32 rsrv3;
+ u32 data_sn;
+ u32 buffer_offset;
+ u32 rsrv4;
};
-/*
- * FCoE KWQE header
- */
-struct fcoe_kwqe_header {
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
- u8 op_code;
-#elif defined(__LITTLE_ENDIAN)
- u8 op_code;
- u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-#endif
-};
/*
- * FCoE firmware init request 1
+ * PDU header of an iSCSI login request
*/
-struct fcoe_kwqe_init1 {
+struct iscsi_login_req_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 num_tasks;
-#elif defined(__LITTLE_ENDIAN)
- u16 num_tasks;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 task_list_pbl_addr_lo;
- u32 task_list_pbl_addr_hi;
- u32 dummy_buffer_addr_lo;
- u32 dummy_buffer_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rq_num_wqes;
- u16 sq_num_wqes;
-#elif defined(__LITTLE_ENDIAN)
- u16 sq_num_wqes;
- u16 rq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 cq_num_wqes;
- u16 rq_buffer_log_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_buffer_log_size;
- u16 cq_num_wqes;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
+ u8 version_max;
+ u8 version_min;
+#elif defined(__LITTLE_ENDIAN)
+ u8 version_min;
+ u8 version_max;
+ u8 op_attr;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
+ u8 opcode;
#endif
+ u32 data_fields;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ u32 isid_lo;
#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
- u8 num_sessions_log;
- u16 mtu;
+ u16 isid_hi;
+ u16 tsih;
#elif defined(__LITTLE_ENDIAN)
- u16 mtu;
- u8 num_sessions_log;
- u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+ u16 tsih;
+ u16 isid_hi;
#endif
-};
-
-/*
- * FCoE firmware init request 2
- */
-struct fcoe_kwqe_init2 {
+ u32 itt;
#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
+ u16 cid;
+ u16 rsrv1;
#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
+ u16 rsrv1;
+ u16 cid;
#endif
- u32 hash_tbl_pbl_addr_lo;
- u32 hash_tbl_pbl_addr_hi;
- u32 t2_hash_tbl_addr_lo;
- u32 t2_hash_tbl_addr_hi;
- u32 t2_ptr_hash_tbl_addr_lo;
- u32 t2_ptr_hash_tbl_addr_hi;
- u32 free_list_count;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv2[4];
};
/*
- * FCoE firmware init request 3
+ * PDU header of an iSCSI logout request
*/
-struct fcoe_kwqe_init3 {
+struct iscsi_logout_req_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u8 opcode;
#endif
- u32 error_bit_map_lo;
- u32 error_bit_map_hi;
+ u32 data_fields;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ u32 rsrv2[2];
+ u32 itt;
#if defined(__BIG_ENDIAN)
- u8 reserved21[3];
- u8 cached_session_enable;
+ u16 cid;
+ u16 rsrv1;
#elif defined(__LITTLE_ENDIAN)
- u8 cached_session_enable;
- u8 reserved21[3];
+ u16 rsrv1;
+ u16 cid;
#endif
- u32 reserved2[4];
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv3[4];
};
/*
- * FCoE connection offload request 1
+ * PDU header of an iSCSI TMF request
*/
-struct fcoe_kwqe_conn_offload1 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 fcoe_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 fcoe_conn_id;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 sq_addr_lo;
- u32 sq_addr_hi;
- u32 rq_pbl_addr_lo;
- u32 rq_pbl_addr_hi;
- u32 rq_first_pbe_addr_lo;
- u32 rq_first_pbe_addr_hi;
+struct iscsi_tmf_req_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 rq_prod;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 rq_prod;
- u16 reserved0;
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u8 opcode;
#endif
+ u32 data_fields;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 referenced_task_tag;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 ref_cmd_sn;
+ u32 exp_data_sn;
+ u32 rsrv2[2];
};
/*
- * FCoE connection offload request 2
+ * PDU header of an iSCSI Text request
*/
-struct fcoe_kwqe_conn_offload2 {
+struct iscsi_text_req_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 tx_max_fc_pay_len;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 tx_max_fc_pay_len;
- struct fcoe_kwqe_header hdr;
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
+ u8 opcode;
#endif
- u32 cq_addr_lo;
- u32 cq_addr_hi;
- u32 xferq_addr_lo;
- u32 xferq_addr_hi;
- u32 conn_db_addr_lo;
- u32 conn_db_addr_hi;
- u32 reserved1;
+ u32 data_fields;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 ttt;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv3[4];
};
/*
- * FCoE connection offload request 3
+ * PDU header of an iSCSI Nop-Out
*/
-struct fcoe_kwqe_conn_offload3 {
+struct iscsi_nop_out_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
- struct fcoe_kwqe_header hdr;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 tx_max_conc_seqs_c3;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 tx_max_conc_seqs_c3;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-#endif
- u32 reserved;
- u32 confq_first_pbe_addr_lo;
- u32 confq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rx_max_fc_pay_len;
- u16 tx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_total_conc_seqs;
- u16 rx_max_fc_pay_len;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 rx_open_seqs_exch_c3;
- u8 rx_max_conc_seqs_c3;
- u16 rx_total_conc_seqs;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 rx_total_conc_seqs;
- u8 rx_max_conc_seqs_c3;
- u8 rx_open_seqs_exch_c3;
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
+ u8 opcode;
#endif
+ u32 data_fields;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 ttt;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv3[4];
};
/*
- * FCoE connection offload request 4
+ * iscsi pdu headers in little endian form.
*/
-struct fcoe_kwqe_conn_offload4 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u8 reserved2;
- u8 e_d_tov_timer_val;
-#elif defined(__LITTLE_ENDIAN)
- u8 e_d_tov_timer_val;
- u8 reserved2;
- struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u8 dst_mac_addr_hi16[2];
-#endif
- u8 dst_mac_addr_lo32[4];
- u32 lcq_addr_lo;
- u32 lcq_addr_hi;
- u32 confq_pbl_base_addr_lo;
- u32 confq_pbl_base_addr_hi;
+union iscsi_pdu_headers_little_endian {
+ u32 fullHeaderSize[12];
+ struct iscsi_cmd_pdu_hdr_little_endian command_pdu_hdr;
+ struct iscsi_data_pdu_hdr_little_endian data_out_pdu_hdr;
+ struct iscsi_login_req_hdr_little_endian login_req_pdu_hdr;
+ struct iscsi_logout_req_hdr_little_endian logout_req_pdu_hdr;
+ struct iscsi_tmf_req_hdr_little_endian tmf_req_pdu_hdr;
+ struct iscsi_text_req_hdr_little_endian text_req_pdu_hdr;
+ struct iscsi_nop_out_hdr_little_endian nop_out_pdu_hdr;
};
-/*
- * FCoE connection enable request
- */
-struct fcoe_kwqe_conn_enable_disable {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-#endif
- u8 dst_mac_addr_lo32[4];
+struct iscsi_hq_bd {
+ union iscsi_pdu_headers_little_endian pdu_header;
#if defined(__BIG_ENDIAN)
u16 reserved1;
- u8 dst_mac_addr_hi16[2];
+ u16 lcl_cmp_flg;
#elif defined(__LITTLE_ENDIAN)
- u8 dst_mac_addr_hi16[2];
+ u16 lcl_cmp_flg;
u16 reserved1;
#endif
+ u32 sgl_base_lo;
+ u32 sgl_base_hi;
#if defined(__BIG_ENDIAN)
- u8 vlan_flag;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 vlan_flag;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 reserved3;
- u8 d_id[3];
+ u8 sgl_size;
+ u8 sge_index;
+ u16 sge_offset;
#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 reserved3;
+ u16 sge_offset;
+ u8 sge_index;
+ u8 sgl_size;
#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved4;
};
-/*
- * FCoE connection destroy request
- */
-struct fcoe_kwqe_conn_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved1[5];
-};
/*
- * FCoe destroy request
+ * CQE data for L2 OOO connection $$KEEP_ENDIANNESS$$
*/
-struct fcoe_kwqe_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 reserved1[7];
+struct iscsi_l2_ooo_data {
+ __le32 iscsi_cid;
+ u8 drop_isle;
+ u8 drop_size;
+ u8 ooo_opcode;
+ u8 ooo_isle;
+ u8 reserved[8];
};
-/*
- * FCoe statistics request
- */
-struct fcoe_kwqe_stat {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 stat_params_addr_lo;
- u32 stat_params_addr_hi;
- u32 reserved1[5];
-};
-/*
- * FCoE KWQ WQE
- */
-union fcoe_kwqe {
- struct fcoe_kwqe_init1 init1;
- struct fcoe_kwqe_init2 init2;
- struct fcoe_kwqe_init3 init3;
- struct fcoe_kwqe_conn_offload1 conn_offload1;
- struct fcoe_kwqe_conn_offload2 conn_offload2;
- struct fcoe_kwqe_conn_offload3 conn_offload3;
- struct fcoe_kwqe_conn_offload4 conn_offload4;
- struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
- struct fcoe_kwqe_conn_destroy conn_destroy;
- struct fcoe_kwqe_destroy destroy;
- struct fcoe_kwqe_stat statistics;
-};
-struct fcoe_task_ctx_entry {
- struct fcoe_task_ctx_entry_tx_only tx_wr_only;
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
- struct fcoe_task_ctx_entry_rx_only rx_wr_only;
- u32 reserved[4];
-};
-/*
- * FCoE connection enable\disable params passed by driver to FW in FCoE enable ramrod
- */
-struct fcoe_conn_enable_disable_ramrod_params {
- struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
-};
-/*
- * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
- */
-struct fcoe_conn_offload_ramrod_params {
- struct fcoe_kwqe_conn_offload1 offload_kwqe1;
- struct fcoe_kwqe_conn_offload2 offload_kwqe2;
- struct fcoe_kwqe_conn_offload3 offload_kwqe3;
- struct fcoe_kwqe_conn_offload4 offload_kwqe4;
+struct iscsi_task_context_entry_xuc_c_write_only {
+ u32 total_data_acked;
};
-/*
- * FCoE init params passed by driver to FW in FCoE init ramrod
- */
-struct fcoe_init_ramrod_params {
- struct fcoe_kwqe_init1 init_kwqe1;
- struct fcoe_kwqe_init2 init_kwqe2;
- struct fcoe_kwqe_init3 init_kwqe3;
- struct regpair eq_addr;
- struct regpair eq_next_page_addr;
+struct iscsi_task_context_r2t_table_entry {
+ u32 ttt;
+ u32 desired_data_len;
+};
+
+struct iscsi_task_context_entry_xuc_u_write_only {
+ u32 exp_r2t_sn;
+ struct iscsi_task_context_r2t_table_entry r2t_table[4];
#if defined(__BIG_ENDIAN)
- u16 sb_num;
- u16 eq_prod;
+ u16 data_in_count;
+ u8 cq_id;
+ u8 valid_1b;
#elif defined(__LITTLE_ENDIAN)
- u16 eq_prod;
- u16 sb_num;
+ u8 valid_1b;
+ u8 cq_id;
+ u16 data_in_count;
#endif
+};
+
+struct iscsi_task_context_entry_xuc {
+ struct iscsi_task_context_entry_xuc_c_write_only write_c;
+ u32 exp_data_transfer_len;
+ struct iscsi_task_context_entry_xuc_x_write_only write_x;
+ u32 lun_lo;
+ struct iscsi_task_context_entry_xuc_xu_write_both write_xu;
+ u32 lun_hi;
+ struct iscsi_task_context_entry_xuc_u_write_only write_u;
+};
+
+struct iscsi_task_context_entry_u {
+ u32 exp_r2t_buff_offset;
+ u32 rem_rcv_len;
+ u32 exp_data_sn;
+};
+
+struct iscsi_task_context_entry {
+ struct iscsi_task_context_entry_x tce_x;
#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 reserved0;
- u8 sb_id;
+ u16 data_out_count;
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u8 sb_id;
- u8 reserved0;
- u16 reserved1;
+ u16 rsrv0;
+ u16 data_out_count;
#endif
+ struct iscsi_task_context_entry_xuc tce_xuc;
+ struct iscsi_task_context_entry_u tce_u;
+ u32 rsrv1[7];
};
-/*
- * FCoE statistics params buffer passed by driver to FW in FCoE statistics ramrod
- */
-struct fcoe_stat_ramrod_params {
- struct fcoe_kwqe_stat stat_kwqe;
-};
-/*
- * FCoE 16-bits vlan structure
- */
-struct fcoe_vlan_fields {
- u16 fields;
-#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
-#define FCOE_VLAN_FIELDS_VID_SHIFT 0
-#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
-#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
-#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
-#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
-};
-/*
- * FCoE 16-bits vlan union
- */
-union fcoe_vlan_field_union {
- struct fcoe_vlan_fields fields;
- u16 val;
-};
-/*
- * Parameters used for Class 2 verifications
- */
-struct ustorm_fcoe_c2_params {
-#if defined(__BIG_ENDIAN)
- u16 e2e_credit;
- u16 con_seq;
-#elif defined(__LITTLE_ENDIAN)
- u16 con_seq;
- u16 e2e_credit;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 ackq_prod;
- u16 open_seq_per_exch;
-#elif defined(__LITTLE_ENDIAN)
- u16 open_seq_per_exch;
- u16 ackq_prod;
-#endif
- struct regpair ackq_pbl_base;
- struct regpair ackq_cur_seg;
-};
-/*
- * Parameters used for Class 2 verifications
- */
-struct xstorm_fcoe_c2_params {
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u8 ackq_x_prod;
- u8 max_conc_seqs_c2;
-#elif defined(__LITTLE_ENDIAN)
- u8 max_conc_seqs_c2;
- u8 ackq_x_prod;
- u16 reserved0;
-#endif
- struct regpair ackq_pbl_base;
- struct regpair ackq_cur_seg;
+struct iscsi_task_context_entry_xuc_x_init_only {
+ struct regpair lun;
+ u32 exp_data_transfer_len;
};
-/*
- * Buffer per connection, used in Tstorm
- */
-struct iscsi_conn_buf {
- struct regpair reserved[8];
-};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
* ipv6 structure
@@ -4379,6 +5067,8 @@ struct ip_v6_addr {
u32 ip_addr_hi_hi;
};
+
+
/*
* l5cm- connection identification params
*/
@@ -4460,8 +5150,7 @@ struct l5cm_xstorm_conn_buffer {
* l5cm-tstorm connection buffer
*/
struct l5cm_tstorm_conn_buffer {
- u32 snd_buf;
- u32 rcv_buf;
+ u32 rsrv1[2];
#if defined(__BIG_ENDIAN)
u16 params;
#define L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE (0x1<<0)
@@ -4493,6 +5182,72 @@ struct l5cm_active_conn_buffer {
struct l5cm_tstorm_conn_buffer tstorm_conn_buffer;
};
+
+
+/*
+ * The l5cm opaque buffer passed in add new connection ramrod passive side
+ */
+struct l5cm_hash_input_string {
+ u32 __opaque1;
+#if defined(__BIG_ENDIAN)
+ u16 __opaque3;
+ u16 __opaque2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __opaque2;
+ u16 __opaque3;
+#endif
+ struct ip_v6_addr __opaque4;
+ struct ip_v6_addr __opaque5;
+ u32 __opaque6;
+ u32 __opaque7[5];
+};
+
+
+/*
+ * syn cookie component
+ */
+struct l5cm_syn_cookie_comp {
+ u32 __opaque;
+};
+
+/*
+ * data related to listeners of a TCP port
+ */
+struct l5cm_port_listener_data {
+ u8 params;
+#define L5CM_PORT_LISTENER_DATA_ENABLE (0x1<<0)
+#define L5CM_PORT_LISTENER_DATA_ENABLE_SHIFT 0
+#define L5CM_PORT_LISTENER_DATA_IP_INDEX (0xF<<1)
+#define L5CM_PORT_LISTENER_DATA_IP_INDEX_SHIFT 1
+#define L5CM_PORT_LISTENER_DATA_NET_FILTER (0x1<<5)
+#define L5CM_PORT_LISTENER_DATA_NET_FILTER_SHIFT 5
+#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE (0x1<<6)
+#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE_SHIFT 6
+#define L5CM_PORT_LISTENER_DATA_MPA_MODE (0x1<<7)
+#define L5CM_PORT_LISTENER_DATA_MPA_MODE_SHIFT 7
+};
+
+/*
+ * Opaque structure passed from U to X when final ack arrives
+ */
+struct l5cm_opaque_buf {
+ u32 __opaque1;
+ u32 __opaque2;
+ u32 __opaque3;
+ u32 __opaque4;
+ struct l5cm_syn_cookie_comp __opaque5;
+#if defined(__BIG_ENDIAN)
+ u16 rsrv2;
+ u8 rsrv;
+ struct l5cm_port_listener_data __opaque6;
+#elif defined(__LITTLE_ENDIAN)
+ struct l5cm_port_listener_data __opaque6;
+ u8 rsrv;
+ u16 rsrv2;
+#endif
+};
+
+
/*
* l5cm slow path element
*/
@@ -4501,6 +5256,109 @@ struct l5cm_packet_size {
u32 rsrv;
};
+
+/*
+ * The final-ack union structure in PCS entry after final ack arrived
+ */
+struct l5cm_pcse_ack {
+ struct l5cm_xstorm_conn_buffer tx_socket_params;
+ struct l5cm_opaque_buf opaque_buf;
+ struct l5cm_tstorm_conn_buffer rx_socket_params;
+};
+
+
+/*
+ * The syn union structure in PCS entry after syn arrived
+ */
+struct l5cm_pcse_syn {
+ struct l5cm_opaque_buf opaque_buf;
+ u32 rsrv[12];
+};
+
+
+/*
+ * pcs entry data for passive connections
+ */
+struct l5cm_pcs_attributes {
+#if defined(__BIG_ENDIAN)
+ u16 pcs_id;
+ u8 status;
+ u8 flags;
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
+#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
+#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+ u8 flags;
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
+#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
+#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
+ u8 status;
+ u16 pcs_id;
+#endif
+};
+
+
+union l5cm_seg_params {
+ struct l5cm_pcse_syn syn_seg_params;
+ struct l5cm_pcse_ack ack_seg_params;
+};
+
+/*
+ * pcs entry data for passive connections
+ */
+struct l5cm_pcs_hdr {
+ struct l5cm_hash_input_string hash_input_string;
+ struct l5cm_conn_addr_params conn_addr_buf;
+ u32 cid;
+ u32 hash_result;
+ union l5cm_seg_params seg_params;
+ struct l5cm_pcs_attributes att;
+#if defined(__BIG_ENDIAN)
+ u16 rsrv;
+ u16 rx_seg_size;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rx_seg_size;
+ u16 rsrv;
+#endif
+};
+
+/*
+ * pcs entry for passive connections
+ */
+struct l5cm_pcs_entry {
+ struct l5cm_pcs_hdr hdr;
+ u8 rx_segment[1516];
+};
+
+
+
+
/*
* l5cm connection parameters
*/
@@ -4535,6 +5393,29 @@ struct l5cm_spe {
union l5cm_specific_data data;
};
+
+
+
+/*
+ * Termination variables
+ */
+struct l5cm_term_vars {
+ u8 BitMap;
+#define L5CM_TERM_VARS_TCP_STATE (0xF<<0)
+#define L5CM_TERM_VARS_TCP_STATE_SHIFT 0
+#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
+#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
+#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
+#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
+#define L5CM_TERM_VARS_TERM_ON_CHIP (0x1<<6)
+#define L5CM_TERM_VARS_TERM_ON_CHIP_SHIFT 6
+#define L5CM_TERM_VARS_RSRV (0x1<<7)
+#define L5CM_TERM_VARS_RSRV_SHIFT 7
+};
+
+
+
+
/*
* Tstorm Tcp flags
*/
@@ -4550,6 +5431,7 @@ struct tstorm_l5cm_tcp_flags {
#define TSTORM_L5CM_TCP_FLAGS_RSRV1_SHIFT 14
};
+
/*
* Xstorm Tcp flags
*/
@@ -4565,4 +5447,38 @@ struct xstorm_l5cm_tcp_flags {
#define XSTORM_L5CM_TCP_FLAGS_RSRV_SHIFT 3
};
-#endif /* CNIC_DEFS_H */
+
+
+/*
+ * Out-of-order states
+ */
+enum tcp_ooo_event {
+ TCP_EVENT_ADD_PEN = 0,
+ TCP_EVENT_ADD_NEW_ISLE = 1,
+ TCP_EVENT_ADD_ISLE_RIGHT = 2,
+ TCP_EVENT_ADD_ISLE_LEFT = 3,
+ TCP_EVENT_JOIN = 4,
+ TCP_EVENT_NOP = 5,
+ MAX_TCP_OOO_EVENT
+};
+
+
+/*
+ * OOO support modes
+ */
+enum tcp_tstorm_ooo {
+ TCP_TSTORM_OOO_DROP_AND_PROC_ACK = 0,
+ TCP_TSTORM_OOO_SEND_PURE_ACK = 1,
+ TCP_TSTORM_OOO_SUPPORTED = 2,
+ MAX_TCP_TSTORM_OOO
+};
+
+
+
+
+
+
+
+
+
+#endif /* __5710_HSI_CNIC_LE__ */
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index fdd8e46a9050..79443e0dbf96 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
#ifndef CNIC_IF_H
#define CNIC_IF_H
-#define CNIC_MODULE_VERSION "2.2.14"
-#define CNIC_MODULE_RELDATE "Mar 30, 2011"
+#define CNIC_MODULE_VERSION "2.5.7"
+#define CNIC_MODULE_RELDATE "July 20, 2011"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
@@ -99,6 +99,8 @@ struct kcqe {
struct cnic_ctl_completion {
u32 cid;
+ u8 opcode;
+ u8 error;
};
struct cnic_ctl_info {
@@ -169,7 +171,7 @@ struct cnic_eth_dev {
struct pci_dev *pdev;
void __iomem *io_base;
void __iomem *io_base2;
- void *iro_arr;
+ const void *iro_arr;
u32 ctx_tbl_offset;
u32 ctx_tbl_len;
@@ -179,6 +181,11 @@ struct cnic_eth_dev {
u32 max_fcoe_conn;
u32 max_rdma_conn;
u32 fcoe_init_cid;
+ u32 fcoe_wwn_port_name_hi;
+ u32 fcoe_wwn_port_name_lo;
+ u32 fcoe_wwn_node_name_hi;
+ u32 fcoe_wwn_node_name_lo;
+
u16 iscsi_l2_client_id;
u16 iscsi_l2_cid;
u8 iscsi_mac[ETH_ALEN];
@@ -311,7 +318,7 @@ struct cnic_ulp_ops {
void (*cnic_stop)(void *ulp_ctx);
void (*indicate_kcqes)(void *ulp_ctx, struct kcqe *cqes[],
u32 num_cqes);
- void (*indicate_netevent)(void *ulp_ctx, unsigned long event);
+ void (*indicate_netevent)(void *ulp_ctx, unsigned long event, u16 vid);
void (*cm_connect_complete)(struct cnic_sock *);
void (*cm_close_complete)(struct cnic_sock *);
void (*cm_abort_complete)(struct cnic_sock *);
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fec939f8f65f..e0638cb4b07c 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
@@ -39,7 +40,7 @@
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/gpio.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 7300de5a1426..8b395b537330 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -45,7 +45,6 @@
#include "t3cdev.h"
#include <asm/io.h>
-struct vlan_group;
struct adapter;
struct sge_qset;
struct port_info;
@@ -66,7 +65,6 @@ struct iscsi_config {
struct port_info {
struct adapter *adapter;
- struct vlan_group *vlan_grp;
struct sge_qset *qs;
u8 port_id;
u8 nqsets;
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 056ee8c831f1..df01b6343241 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -367,7 +367,6 @@ struct vpd_params {
struct pci_params {
unsigned int vpd_cap_addr;
- unsigned int pcie_cap_addr;
unsigned short speed;
unsigned char width;
unsigned char variant;
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 9081ce037149..93b41a7ac175 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -2532,25 +2532,51 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
}
}
-static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+static void cxgb_vlan_mode(struct net_device *dev, u32 features)
{
struct port_info *pi = netdev_priv(dev);
struct adapter *adapter = pi->adapter;
- pi->vlan_grp = grp;
- if (adapter->params.rev > 0)
- t3_set_vlan_accel(adapter, 1 << pi->port_id, grp != NULL);
- else {
+ if (adapter->params.rev > 0) {
+ t3_set_vlan_accel(adapter, 1 << pi->port_id,
+ features & NETIF_F_HW_VLAN_RX);
+ } else {
/* single control for all ports */
- unsigned int i, have_vlans = 0;
+ unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
+
for_each_port(adapter, i)
- have_vlans |= adap2pinfo(adapter, i)->vlan_grp != NULL;
+ have_vlans |=
+ adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
t3_set_vlan_accel(adapter, 1, have_vlans);
}
t3_synchronize_rx(adapter, pi);
}
+static u32 cxgb_fix_features(struct net_device *dev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int cxgb_set_features(struct net_device *dev, u32 features)
+{
+ u32 changed = dev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ cxgb_vlan_mode(dev, features);
+
+ return 0;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void cxgb_netpoll(struct net_device *dev)
{
@@ -3131,7 +3157,8 @@ static const struct net_device_ops cxgb_netdev_ops = {
.ndo_do_ioctl = cxgb_ioctl,
.ndo_change_mtu = cxgb_change_mtu,
.ndo_set_mac_address = cxgb_set_mac_addr,
- .ndo_vlan_rx_register = vlan_rx_register,
+ .ndo_fix_features = cxgb_fix_features,
+ .ndo_set_features = cxgb_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cxgb_netpoll,
#endif
@@ -3263,9 +3290,8 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->mem_start = mmio_start;
netdev->mem_end = mmio_start + mmio_len - 1;
netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
- NETIF_F_TSO | NETIF_F_RXCSUM;
- netdev->features |= netdev->hw_features |
- NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX;
+ netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_TX;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
@@ -3329,6 +3355,9 @@ static int __devinit init_one(struct pci_dev *pdev,
err = sysfs_create_group(&adapter->port[0]->dev.kobj,
&cxgb3_attr_group);
+ for_each_port(adapter, i)
+ cxgb_vlan_mode(adapter->port[i], adapter->port[i]->features);
+
print_port_info(adapter, ai);
return 0;
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index 862804f32b6e..805076c54f1b 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -34,7 +34,7 @@
#include <linux/slab.h>
#include <net/neighbour.h>
#include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/proc_fs.h>
#include <linux/if_vlan.h>
#include <net/netevent.h>
@@ -176,16 +176,13 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
int i;
for_each_port(adapter, i) {
- struct vlan_group *grp;
struct net_device *dev = adapter->port[i];
- const struct port_info *p = netdev_priv(dev);
if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
if (vlan && vlan != VLAN_VID_MASK) {
- grp = p->vlan_grp;
- dev = NULL;
- if (grp)
- dev = vlan_group_get_device(grp, vlan);
+ rcu_read_lock();
+ dev = __vlan_find_dev_deep(dev, vlan);
+ rcu_read_unlock();
} else if (netif_is_bond_slave(dev)) {
while (dev->master)
dev = dev->master;
@@ -567,7 +564,7 @@ static void t3_process_tid_release_list(struct work_struct *work)
while (td->tid_release_list) {
struct t3c_tid_entry *p = td->tid_release_list;
- td->tid_release_list = (struct t3c_tid_entry *)p->ctx;
+ td->tid_release_list = p->ctx;
spin_unlock_bh(&td->tid_release_lock);
skb = alloc_skb(sizeof(struct cpl_tid_release),
@@ -971,7 +968,7 @@ static int nb_callback(struct notifier_block *self, unsigned long event,
case (NETEVENT_REDIRECT):{
struct netevent_redirect *nr = ctx;
cxgb_redirect(nr->old, nr->new);
- cxgb_neigh_update(nr->new->neighbour);
+ cxgb_neigh_update(dst_get_neighbour(nr->new));
break;
}
default:
@@ -1116,8 +1113,8 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
struct l2t_entry *e;
struct t3c_tid_entry *te;
- olddev = old->neighbour->dev;
- newdev = new->neighbour->dev;
+ olddev = dst_get_neighbour(old)->dev;
+ newdev = dst_get_neighbour(new)->dev;
if (!is_offloading(olddev))
return;
if (!is_offloading(newdev)) {
@@ -1134,7 +1131,7 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
}
/* Add new L2T entry */
- e = t3_l2t_get(tdev, new->neighbour, newdev);
+ e = t3_l2t_get(tdev, dst_get_neighbour(new), newdev);
if (!e) {
printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
__func__);
diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/cxgb3/l2t.h
index fd3eb07e3f40..7a12d52ed4fc 100644
--- a/drivers/net/cxgb3/l2t.h
+++ b/drivers/net/cxgb3/l2t.h
@@ -34,7 +34,7 @@
#include <linux/spinlock.h>
#include "t3cdev.h"
-#include <asm/atomic.h>
+#include <linux/atomic.h>
enum {
L2T_STATE_VALID, /* entry is up to date */
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 76bf5892b962..d6fa1777a343 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -2028,28 +2028,11 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
skb_checksum_none_assert(skb);
skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
- if (unlikely(p->vlan_valid)) {
- struct vlan_group *grp = pi->vlan_grp;
-
+ if (p->vlan_valid) {
qs->port_stats[SGE_PSTAT_VLANEX]++;
- if (likely(grp))
- if (lro)
- vlan_gro_receive(&qs->napi, grp,
- ntohs(p->vlan), skb);
- else {
- if (unlikely(pi->iscsic.flags)) {
- unsigned short vtag = ntohs(p->vlan) &
- VLAN_VID_MASK;
- skb->dev = vlan_group_get_device(grp,
- vtag);
- cxgb3_process_iscsi_prov_pack(pi, skb);
- }
- __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan),
- rq->polling);
- }
- else
- dev_kfree_skb_any(skb);
- } else if (rq->polling) {
+ __vlan_hwaccel_put_tag(skb, ntohs(p->vlan));
+ }
+ if (rq->polling) {
if (lro)
napi_gro_receive(&qs->napi, skb);
else {
@@ -2147,14 +2130,8 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
- if (unlikely(cpl->vlan_valid)) {
- struct vlan_group *grp = pi->vlan_grp;
-
- if (likely(grp != NULL)) {
- vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan));
- return;
- }
- }
+ if (cpl->vlan_valid)
+ __vlan_hwaccel_put_tag(skb, ntohs(cpl->vlan));
napi_gro_frags(&qs->napi);
}
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index c688421da9c7..44ac2f40b644 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -3290,22 +3290,20 @@ static void config_pcie(struct adapter *adap)
unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
pci_read_config_word(adap->pdev,
- adap->params.pci.pcie_cap_addr + PCI_EXP_DEVCTL,
+ adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
&val);
pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
pci_read_config_word(adap->pdev, 0x2, &devid);
if (devid == 0x37) {
pci_write_config_word(adap->pdev,
- adap->params.pci.pcie_cap_addr +
- PCI_EXP_DEVCTL,
+ adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
val & ~PCI_EXP_DEVCTL_READRQ &
~PCI_EXP_DEVCTL_PAYLOAD);
pldsize = 0;
}
- pci_read_config_word(adap->pdev,
- adap->params.pci.pcie_cap_addr + PCI_EXP_LNKCTL,
+ pci_read_config_word(adap->pdev, adap->pdev->pcie_cap + PCI_EXP_LNKCTL,
&val);
fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0));
@@ -3429,12 +3427,11 @@ static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
static unsigned short speed_map[] = { 33, 66, 100, 133 };
u32 pci_mode, pcie_cap;
- pcie_cap = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ pcie_cap = pci_pcie_cap(adapter->pdev);
if (pcie_cap) {
u16 val;
p->variant = PCI_VARIANT_PCIE;
- p->pcie_cap_addr = pcie_cap;
pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA,
&val);
p->width = (val >> 4) & 0x3f;
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
index be55e9ae74d1..705713b56636 100644
--- a/drivers/net/cxgb3/t3cdev.h
+++ b/drivers/net/cxgb3/t3cdev.h
@@ -33,7 +33,7 @@
#define _T3CDEV_H_
#include <linux/list.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h
index bc9982a4c1f4..223a7f72343b 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/cxgb4/cxgb4.h
@@ -276,7 +276,6 @@ enum {
};
struct adapter;
-struct vlan_group;
struct sge_rspq;
struct port_info {
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 7e3cfbe89e3b..c9957b7f17b5 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -3704,7 +3704,7 @@ static int __devinit init_one(struct pci_dev *pdev,
if (err) {
dev_warn(&pdev->dev, "only %d net devices registered\n", i);
err = 0;
- };
+ }
if (cxgb4_debugfs_root) {
adapter->debugfs_root = debugfs_create_dir(pci_name(pdev),
diff --git a/drivers/net/cxgb4/cxgb4_uld.h b/drivers/net/cxgb4/cxgb4_uld.h
index 1b48c0170145..b1d39b8d141a 100644
--- a/drivers/net/cxgb4/cxgb4_uld.h
+++ b/drivers/net/cxgb4/cxgb4_uld.h
@@ -38,7 +38,7 @@
#include <linux/cache.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/* CPL message priority levels */
enum {
diff --git a/drivers/net/cxgb4/l2t.h b/drivers/net/cxgb4/l2t.h
index 7bd8f42378ff..02b31d0c6410 100644
--- a/drivers/net/cxgb4/l2t.h
+++ b/drivers/net/cxgb4/l2t.h
@@ -37,7 +37,7 @@
#include <linux/spinlock.h>
#include <linux/if_ether.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
struct adapter;
struct l2t_data;
diff --git a/drivers/net/cxgb4vf/adapter.h b/drivers/net/cxgb4vf/adapter.h
index 4fd821aadc8a..594334d5c711 100644
--- a/drivers/net/cxgb4vf/adapter.h
+++ b/drivers/net/cxgb4vf/adapter.h
@@ -40,6 +40,7 @@
#ifndef __CXGB4VF_ADAPTER_H__
#define __CXGB4VF_ADAPTER_H__
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
@@ -91,7 +92,6 @@ struct sge_rspq;
*/
struct port_info {
struct adapter *adapter; /* our adapter */
- struct vlan_group *vlan_grp; /* out VLAN group */
u16 viid; /* virtual interface ID */
s16 xact_addr_filt; /* index of our MAC address filter */
u16 rss_size; /* size of VI's RSS table slice */
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c
index e71c08e547e4..ec799139dfe2 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/cxgb4vf/cxgb4vf_main.c
@@ -33,7 +33,6 @@
* SOFTWARE.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -210,18 +209,8 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok)
* ======================
*/
-/*
- * Record our new VLAN Group and enable/disable hardware VLAN Tag extraction
- * based on whether the specified VLAN Group pointer is NULL or not.
- */
-static void cxgb4vf_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
-{
- struct port_info *pi = netdev_priv(dev);
- pi->vlan_grp = grp;
- t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1, grp != NULL, 0);
-}
+
/*
* Perform the MAC and PHY actions needed to enable a "port" (Virtual
@@ -234,9 +223,9 @@ static int link_start(struct net_device *dev)
/*
* We do not set address filters and promiscuity here, the stack does
- * that step explicitly.
+ * that step explicitly. Enable vlan accel.
*/
- ret = t4vf_set_rxmode(pi->adapter, pi->viid, dev->mtu, -1, -1, -1, -1,
+ ret = t4vf_set_rxmode(pi->adapter, pi->viid, dev->mtu, -1, -1, -1, 1,
true);
if (ret == 0) {
ret = t4vf_change_mac(pi->adapter, pi->viid,
@@ -1103,6 +1092,32 @@ static int cxgb4vf_change_mtu(struct net_device *dev, int new_mtu)
return ret;
}
+static u32 cxgb4vf_fix_features(struct net_device *dev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int cxgb4vf_set_features(struct net_device *dev, u32 features)
+{
+ struct port_info *pi = netdev_priv(dev);
+ u32 changed = dev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1,
+ features & NETIF_F_HW_VLAN_TX, 0);
+
+ return 0;
+}
+
/*
* Change the devices MAC address.
*/
@@ -2422,7 +2437,6 @@ static int __devinit enable_msix(struct adapter *adapter)
return err;
}
-#ifdef HAVE_NET_DEVICE_OPS
static const struct net_device_ops cxgb4vf_netdev_ops = {
.ndo_open = cxgb4vf_open,
.ndo_stop = cxgb4vf_stop,
@@ -2433,12 +2447,12 @@ static const struct net_device_ops cxgb4vf_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = cxgb4vf_do_ioctl,
.ndo_change_mtu = cxgb4vf_change_mtu,
- .ndo_vlan_rx_register = cxgb4vf_vlan_rx_register,
+ .ndo_fix_features = cxgb4vf_fix_features,
+ .ndo_set_features = cxgb4vf_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cxgb4vf_poll_controller,
#endif
};
-#endif
/*
* "Probe" a device: initialize a device and construct all kernel and driver
@@ -2603,31 +2617,15 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM;
+ NETIF_F_HW_VLAN_RX | NETIF_F_RXCSUM;
netdev->vlan_features = NETIF_F_SG | TSO_FLAGS |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_HIGHDMA;
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_RX;
+ netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_TX;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
-#ifdef HAVE_NET_DEVICE_OPS
netdev->netdev_ops = &cxgb4vf_netdev_ops;
-#else
- netdev->vlan_rx_register = cxgb4vf_vlan_rx_register;
- netdev->open = cxgb4vf_open;
- netdev->stop = cxgb4vf_stop;
- netdev->hard_start_xmit = t4vf_eth_xmit;
- netdev->get_stats = cxgb4vf_get_stats;
- netdev->set_rx_mode = cxgb4vf_set_rxmode;
- netdev->do_ioctl = cxgb4vf_do_ioctl;
- netdev->change_mtu = cxgb4vf_change_mtu;
- netdev->set_mac_address = cxgb4vf_set_mac_addr;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = cxgb4vf_poll_controller;
-#endif
-#endif
SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
/*
diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c
index 5fd75fdaa631..cffb328c46c3 100644
--- a/drivers/net/cxgb4vf/sge.c
+++ b/drivers/net/cxgb4vf/sge.c
@@ -1491,20 +1491,10 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(skb, rxq->rspq.idx);
- if (unlikely(pkt->vlan_ex)) {
- struct port_info *pi = netdev_priv(rxq->rspq.netdev);
- struct vlan_group *grp = pi->vlan_grp;
-
- rxq->stats.vlan_ex++;
- if (likely(grp)) {
- ret = vlan_gro_frags(&rxq->rspq.napi, grp,
- be16_to_cpu(pkt->vlan));
- goto stats;
- }
- }
+ if (pkt->vlan_ex)
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(pkt->vlan));
ret = napi_gro_frags(&rxq->rspq.napi);
-stats:
if (ret == GRO_HELD)
rxq->stats.lro_pkts++;
else if (ret == GRO_MERGED || ret == GRO_MERGED_FREE)
@@ -1525,7 +1515,6 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
const struct pkt_gl *gl)
{
struct sk_buff *skb;
- struct port_info *pi;
const struct cpl_rx_pkt *pkt = (void *)&rsp[1];
bool csum_ok = pkt->csum_calc && !pkt->err_vec;
struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
@@ -1553,7 +1542,6 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
__skb_pull(skb, PKTSHIFT);
skb->protocol = eth_type_trans(skb, rspq->netdev);
skb_record_rx_queue(skb, rspq->idx);
- pi = netdev_priv(skb->dev);
rxq->stats.pkts++;
if (csum_ok && (rspq->netdev->features & NETIF_F_RXCSUM) &&
@@ -1569,20 +1557,12 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
} else
skb_checksum_none_assert(skb);
- /*
- * Deliver the packet to the stack.
- */
- if (unlikely(pkt->vlan_ex)) {
- struct vlan_group *grp = pi->vlan_grp;
-
+ if (pkt->vlan_ex) {
rxq->stats.vlan_ex++;
- if (likely(grp))
- vlan_hwaccel_receive_skb(skb, grp,
- be16_to_cpu(pkt->vlan));
- else
- dev_kfree_skb_any(skb);
- } else
- netif_receive_skb(skb);
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(pkt->vlan));
+ }
+
+ netif_receive_skb(skb);
return 0;
}
diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/cxgb4vf/t4vf_hw.c
index 192db226ec7f..fe3fd3dad6f7 100644
--- a/drivers/net/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/cxgb4vf/t4vf_hw.c
@@ -33,7 +33,6 @@
* SOFTWARE.
*/
-#include <linux/version.h>
#include <linux/pci.h>
#include "t4vf_common.h"
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
index ae47f23ba930..dca9d3369cdd 100644
--- a/drivers/net/davinci_cpdma.c
+++ b/drivers/net/davinci_cpdma.c
@@ -167,7 +167,7 @@ cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
} else {
pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
GFP_KERNEL);
- pool->iomap = (void __force __iomem *)pool->cpumap;
+ pool->iomap = pool->cpumap;
pool->hw_addr = pool->phys;
}
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index dcc4a170b0f3..3f451e4d8361 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -48,7 +48,6 @@
#include <linux/highmem.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
@@ -1083,6 +1082,8 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
goto fail_tx;
}
+ skb_tx_timestamp(skb);
+
ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
GFP_KERNEL);
if (unlikely(ret_code != 0)) {
@@ -1489,14 +1490,14 @@ static void emac_adjust_link(struct net_device *ndev)
*/
static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
{
- dev_warn(&ndev->dev, "DaVinci EMAC: ioctl not supported\n");
+ struct emac_priv *priv = netdev_priv(ndev);
if (!(netif_running(ndev)))
return -EINVAL;
/* TODO: Add phy read and write and private statistics get feature */
- return -EOPNOTSUPP;
+ return phy_mii_ioctl(priv->phydev, ifrq, cmd);
}
static int match_first_device(struct device *dev, void *data)
@@ -1821,7 +1822,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
}
priv->emac_base_phys = res->start + pdata->ctrl_reg_offset;
- size = res->end - res->start + 1;
+ size = resource_size(res);
if (!request_mem_region(res->start, size, ndev->name)) {
dev_err(&pdev->dev, "failed request_mem_region() for regs\n");
rc = -ENXIO;
@@ -1926,7 +1927,7 @@ no_irq_res:
cpdma_ctlr_destroy(priv->dma);
no_dma:
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
iounmap(priv->remap_addr);
probe_quit:
@@ -1960,7 +1961,7 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
cpdma_chan_destroy(priv->rxchan);
cpdma_ctlr_destroy(priv->dma);
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
unregister_netdev(ndev);
iounmap(priv->remap_addr);
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 219eb5ad5c12..d5598f6584a3 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -326,15 +326,18 @@ static void load_csrs(struct lance_private *lp)
*/
static void cp_to_buf(const int type, void *to, const void *from, int len)
{
- unsigned short *tp, *fp, clen;
- unsigned char *rtp, *rfp;
+ unsigned short *tp;
+ const unsigned short *fp;
+ unsigned short clen;
+ unsigned char *rtp;
+ const unsigned char *rfp;
if (type == PMAD_LANCE) {
memcpy(to, from, len);
} else if (type == PMAX_LANCE) {
clen = len >> 1;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
@@ -342,8 +345,8 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
}
clen = len & 1;
- rtp = (unsigned char *) tp;
- rfp = (unsigned char *) fp;
+ rtp = tp;
+ rfp = fp;
while (clen--) {
*rtp++ = *rfp++;
}
@@ -352,8 +355,8 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
* copy 16 Byte chunks
*/
clen = len >> 4;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
*tp++ = *fp++;
@@ -382,15 +385,18 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
static void cp_from_buf(const int type, void *to, const void *from, int len)
{
- unsigned short *tp, *fp, clen;
- unsigned char *rtp, *rfp;
+ unsigned short *tp;
+ const unsigned short *fp;
+ unsigned short clen;
+ unsigned char *rtp;
+ const unsigned char *rfp;
if (type == PMAD_LANCE) {
memcpy(to, from, len);
} else if (type == PMAX_LANCE) {
clen = len >> 1;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
fp++;
@@ -398,8 +404,8 @@ static void cp_from_buf(const int type, void *to, const void *from, int len)
clen = len & 1;
- rtp = (unsigned char *) tp;
- rfp = (unsigned char *) fp;
+ rtp = tp;
+ rfp = fp;
while (clen--) {
*rtp++ = *rfp++;
@@ -410,8 +416,8 @@ static void cp_from_buf(const int type, void *to, const void *from, int len)
* copy 16 Byte chunks
*/
clen = len >> 4;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
*tp++ = *fp++;
@@ -940,7 +946,6 @@ static void lance_load_multicast(struct net_device *dev)
struct lance_private *lp = netdev_priv(dev);
volatile u16 *ib = (volatile u16 *)dev->mem_start;
struct netdev_hw_addr *ha;
- char *addrs;
u32 crc;
/* set all multicast bits */
@@ -959,13 +964,7 @@ static void lance_load_multicast(struct net_device *dev)
/* Add addresses */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- /* multicast address? */
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(ETH_ALEN, addrs);
+ crc = ether_crc_le(ETH_ALEN, ha->addr);
crc = crc >> 26;
*lib_ptr(ib, filter[crc >> 4], lp->type) |= 1 << (crc & 0xf);
}
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 8b0084d17c8c..f2015a851977 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -708,11 +708,11 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
/* Tx & Rx descriptors (aligned to a quadword boundary) */
offset = (offset + DEPCA_ALIGN) & ~DEPCA_ALIGN;
- lp->rx_ring = (struct depca_rx_desc __iomem *) (lp->sh_mem + offset);
+ lp->rx_ring = lp->sh_mem + offset;
lp->rx_ring_offset = offset;
offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
- lp->tx_ring = (struct depca_tx_desc __iomem *) (lp->sh_mem + offset);
+ lp->tx_ring = lp->sh_mem + offset;
lp->tx_ring_offset = offset;
offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
@@ -1073,13 +1073,13 @@ static int depca_rx(struct net_device *dev)
i = DEPCA_PKT_STAT_SZ;
}
}
- if (buf[0] & 0x01) { /* Multicast/Broadcast */
- if ((*(s16 *) & buf[0] == -1) && (*(s16 *) & buf[2] == -1) && (*(s16 *) & buf[4] == -1)) {
+ if (is_multicast_ether_addr(buf)) {
+ if (is_broadcast_ether_addr(buf)) {
lp->pktStats.broadcast++;
} else {
lp->pktStats.multicast++;
}
- } else if ((*(s16 *) & buf[0] == *(s16 *) & dev->dev_addr[0]) && (*(s16 *) & buf[2] == *(s16 *) & dev->dev_addr[2]) && (*(s16 *) & buf[4] == *(s16 *) & dev->dev_addr[4])) {
+ } else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
lp->pktStats.unicast++;
}
@@ -1270,7 +1270,6 @@ static void SetMulticastFilter(struct net_device *dev)
{
struct depca_private *lp = netdev_priv(dev);
struct netdev_hw_addr *ha;
- char *addrs;
int i, j, bit, byte;
u16 hashcode;
u32 crc;
@@ -1285,19 +1284,15 @@ static void SetMulticastFilter(struct net_device *dev)
}
/* Add multicast addresses */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
- if ((*addrs & 0x01) == 1) { /* multicast address? */
- crc = ether_crc(ETH_ALEN, addrs);
- hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */
- for (j = 0; j < 5; j++) { /* ... in reverse order. */
- hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
- }
-
-
- byte = hashcode >> 3; /* bit[3-5] -> byte in filter */
- bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
- lp->init_block.mcast_table[byte] |= bit;
+ crc = ether_crc(ETH_ALEN, ha->addr);
+ hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */
+ for (j = 0; j < 5; j++) { /* ... in reverse order. */
+ hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
}
+
+ byte = hashcode >> 3; /* bit[3-5] -> byte in filter */
+ bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
+ lp->init_block.mcast_table[byte] |= bit;
}
}
}
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 23179dbcedd2..ed73e4a93508 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -221,13 +221,13 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_iounmap;
- np->tx_ring = (struct netdev_desc *) ring_space;
+ np->tx_ring = ring_space;
np->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent (pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- np->rx_ring = (struct netdev_desc *) ring_space;
+ np->rx_ring = ring_space;
np->rx_ring_dma = ring_dma;
/* Parse eeprom data */
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index ee597e676ee5..8ef31dc4704d 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -24,6 +24,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
@@ -534,21 +535,35 @@ static int dm9000_set_eeprom(struct net_device *dev,
board_info_t *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
- int i;
+ int done;
/* EEPROM access is aligned to two bytes */
- if ((len & 1) != 0 || (offset & 1) != 0)
- return -EINVAL;
-
if (dm->flags & DM9000_PLATF_NO_EEPROM)
return -ENOENT;
if (ee->magic != DM_EEPROM_MAGIC)
return -EINVAL;
- for (i = 0; i < len; i += 2)
- dm9000_write_eeprom(dm, (offset + i) / 2, data + i);
+ while (len > 0) {
+ if (len & 1 || offset & 1) {
+ int which = offset & 1;
+ u8 tmp[2];
+
+ dm9000_read_eeprom(dm, offset / 2, tmp);
+ tmp[which] = *data;
+ dm9000_write_eeprom(dm, offset / 2, tmp);
+
+ done = 1;
+ } else {
+ dm9000_write_eeprom(dm, offset / 2, data);
+ done = 2;
+ }
+
+ data += done;
+ offset += done;
+ len -= done;
+ }
return 0;
}
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 8318ea06cb6d..c1063d1540c2 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/dma-mapping.h>
@@ -587,6 +588,8 @@ static netdev_tx_t dnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
dnet_writel(bp, irq_enable, INTR_ENB);
}
+ skb_tx_timestamp(skb);
+
/* free the buffer */
dev_kfree_skb(skb);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index e336c7937f05..c1352c60c299 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -149,6 +149,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 8676899120c3..24f41da8c4be 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -215,7 +215,7 @@ struct e1000_adapter {
struct timer_list tx_fifo_stall_timer;
struct timer_list watchdog_timer;
struct timer_list phy_info_timer;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 mng_vlan_id;
u32 bd_number;
u32 rx_buffer_len;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index ec0fa426cce2..c5f0f04219f3 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -290,69 +290,6 @@ static int e1000_set_pauseparam(struct net_device *netdev,
return retval;
}
-static u32 e1000_get_rx_csum(struct net_device *netdev)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- return adapter->rx_csum;
-}
-
-static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- adapter->rx_csum = data;
-
- if (netif_running(netdev))
- e1000_reinit_locked(adapter);
- else
- e1000_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)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
-
- if (hw->mac_type < e1000_82543) {
- if (!data)
- return -EINVAL;
- return 0;
- }
-
- 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);
- struct e1000_hw *hw = &adapter->hw;
-
- if ((hw->mac_type < e1000_82544) ||
- (hw->mac_type == e1000_82547))
- return data ? -EINVAL : 0;
-
- if (data)
- netdev->features |= NETIF_F_TSO;
- else
- netdev->features &= ~NETIF_F_TSO;
-
- netdev->features &= ~NETIF_F_TSO6;
-
- e_info(probe, "TSO is %s\n", data ? "Enabled" : "Disabled");
- adapter->tso_force = true;
- return 0;
-}
-
static u32 e1000_get_msglevel(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1905,12 +1842,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,
- .set_sg = ethtool_op_set_sg,
- .set_tso = e1000_set_tso,
.self_test = e1000_diag_test,
.get_strings = e1000_get_strings,
.set_phys_id = e1000_set_phys_id,
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 7501d977d992..1698622af434 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -3080,7 +3080,6 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{
u32 ctrl, ctrl_ext;
u32 led_ctrl;
- s32 ret_val;
e_dbg("e1000_phy_hw_reset");
@@ -3126,11 +3125,7 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
}
/* Wait for FW to finish PHY configuration. */
- ret_val = e1000_get_phy_cfg_done(hw);
- if (ret_val != E1000_SUCCESS)
- return ret_val;
-
- return ret_val;
+ return e1000_get_phy_cfg_done(hw);
}
/**
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 76e8af00d86d..f97afda941d7 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -30,6 +30,8 @@
#include <net/ip6_checksum.h>
#include <linux/io.h>
#include <linux/prefetch.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
/* Intel Media SOC GbE MDIO physical base address */
static unsigned long ce4100_gbe_mdio_base_phy;
@@ -166,7 +168,8 @@ static void e1000_smartspeed(struct e1000_adapter *adapter);
static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
struct sk_buff *skb);
-static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+static bool e1000_vlan_used(struct e1000_adapter *adapter);
+static void e1000_vlan_mode(struct net_device *netdev, u32 features);
static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
static void e1000_restore_vlan(struct e1000_adapter *adapter);
@@ -330,21 +333,24 @@ static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
u16 vid = hw->mng_cookie.vlan_id;
u16 old_vid = adapter->mng_vlan_id;
- if (adapter->vlgrp) {
- if (!vlan_group_get_device(adapter->vlgrp, vid)) {
- if (hw->mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
- e1000_vlan_rx_add_vid(netdev, vid);
- adapter->mng_vlan_id = vid;
- } else
- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
- (vid != old_vid) &&
- !vlan_group_get_device(adapter->vlgrp, old_vid))
- e1000_vlan_rx_kill_vid(netdev, old_vid);
- } else
+ if (!e1000_vlan_used(adapter))
+ return;
+
+ if (!test_bit(vid, adapter->active_vlans)) {
+ if (hw->mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
+ e1000_vlan_rx_add_vid(netdev, vid);
adapter->mng_vlan_id = vid;
+ } else {
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+ }
+ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
+ !test_bit(old_vid, adapter->active_vlans))
+ e1000_vlan_rx_kill_vid(netdev, old_vid);
+ } else {
+ adapter->mng_vlan_id = vid;
}
}
@@ -797,6 +803,41 @@ static int e1000_is_need_ioport(struct pci_dev *pdev)
}
}
+static u32 e1000_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+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_HW_VLAN_RX)
+ e1000_vlan_mode(netdev, features);
+
+ if (!(changed & NETIF_F_RXCSUM))
+ return 0;
+
+ adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+
+ if (netif_running(netdev))
+ e1000_reinit_locked(adapter);
+ else
+ e1000_reset(adapter);
+
+ return 0;
+}
+
static const struct net_device_ops e1000_netdev_ops = {
.ndo_open = e1000_open,
.ndo_stop = e1000_close,
@@ -804,17 +845,17 @@ static const struct net_device_ops e1000_netdev_ops = {
.ndo_get_stats = e1000_get_stats,
.ndo_set_rx_mode = e1000_set_rx_mode,
.ndo_set_mac_address = e1000_set_mac,
- .ndo_tx_timeout = e1000_tx_timeout,
+ .ndo_tx_timeout = e1000_tx_timeout,
.ndo_change_mtu = e1000_change_mtu,
.ndo_do_ioctl = e1000_ioctl,
.ndo_validate_addr = eth_validate_addr,
-
- .ndo_vlan_rx_register = e1000_vlan_rx_register,
.ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = e1000_netpoll,
#endif
+ .ndo_fix_features = e1000_fix_features,
+ .ndo_set_features = e1000_set_features,
};
/**
@@ -1016,16 +1057,19 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
}
if (hw->mac_type >= e1000_82543) {
- netdev->features = NETIF_F_SG |
+ netdev->hw_features = NETIF_F_SG |
NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX |
- NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_RX;
+ netdev->features = NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_FILTER;
}
if ((hw->mac_type >= e1000_82544) &&
(hw->mac_type != e1000_82547))
- netdev->features |= NETIF_F_TSO;
+ netdev->hw_features |= NETIF_F_TSO;
+
+ netdev->features |= netdev->hw_features;
+ netdev->hw_features |= NETIF_F_RXCSUM;
if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
@@ -1175,6 +1219,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (err)
goto err_register;
+ e1000_vlan_mode(netdev, netdev->features);
+
/* print bus type/speed/width info */
e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
@@ -1419,8 +1465,7 @@ static int e1000_close(struct net_device *netdev)
* the same ID is registered on the host OS (let 8021q kill it) */
if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- !(adapter->vlgrp &&
- vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
+ !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) {
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
}
@@ -2211,7 +2256,7 @@ static void e1000_set_rx_mode(struct net_device *netdev)
else
rctl &= ~E1000_RCTL_MPE;
/* Enable VLAN filter if there is a VLAN */
- if (adapter->vlgrp)
+ if (e1000_vlan_used(adapter))
rctl |= E1000_RCTL_VFE;
}
@@ -2357,13 +2402,16 @@ bool e1000_has_link(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
bool link_active = false;
- /* get_link_status is set on LSC (link status) interrupt or
- * rx sequence error interrupt. get_link_status will stay
- * false until the e1000_check_for_link establishes link
- * for copper adapters ONLY
+ /* get_link_status is set on LSC (link status) interrupt or rx
+ * sequence error interrupt (except on intel ce4100).
+ * get_link_status will stay false until the
+ * e1000_check_for_link establishes link for copper adapters
+ * ONLY
*/
switch (hw->media_type) {
case e1000_media_type_copper:
+ if (hw->mac_type == e1000_ce4100)
+ hw->get_link_status = 1;
if (hw->get_link_status) {
e1000_check_for_link(hw);
link_active = !hw->get_link_status;
@@ -3158,7 +3206,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
}
}
- if (unlikely(vlan_tx_tag_present(skb))) {
+ if (vlan_tx_tag_present(skb)) {
tx_flags |= E1000_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
@@ -3713,12 +3761,12 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
{
skb->protocol = eth_type_trans(skb, adapter->netdev);
- if ((unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))))
- vlan_gro_receive(&adapter->napi, adapter->vlgrp,
- le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK,
- skb);
- else
- napi_gro_receive(&adapter->napi, skb);
+ if (status & E1000_RXD_STAT_VP) {
+ u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+
+ __vlan_hwaccel_put_tag(skb, vid);
+ }
+ napi_gro_receive(&adapter->napi, skb);
}
/**
@@ -4501,46 +4549,61 @@ void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
outl(value, port);
}
-static void e1000_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+static bool e1000_vlan_used(struct e1000_adapter *adapter)
+{
+ u16 vid;
+
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ return true;
+ return false;
+}
+
+static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
+ bool filter_on)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- u32 ctrl, rctl;
+ u32 rctl;
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_disable(adapter);
- adapter->vlgrp = grp;
-
- if (grp) {
- /* enable VLAN tag insert/strip */
- ctrl = er32(CTRL);
- ctrl |= E1000_CTRL_VME;
- ew32(CTRL, ctrl);
+ if (filter_on) {
/* enable VLAN receive filtering */
rctl = er32(RCTL);
rctl &= ~E1000_RCTL_CFIEN;
- if (!(netdev->flags & IFF_PROMISC))
+ if (!(adapter->netdev->flags & IFF_PROMISC))
rctl |= E1000_RCTL_VFE;
ew32(RCTL, rctl);
e1000_update_mng_vlan(adapter);
} else {
- /* disable VLAN tag insert/strip */
- ctrl = er32(CTRL);
- ctrl &= ~E1000_CTRL_VME;
- ew32(CTRL, ctrl);
-
/* disable VLAN receive filtering */
rctl = er32(RCTL);
rctl &= ~E1000_RCTL_VFE;
ew32(RCTL, rctl);
+ }
- if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) {
- e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- }
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ e1000_irq_enable(adapter);
+}
+
+static void e1000_vlan_mode(struct net_device *netdev, u32 features)
+{
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 ctrl;
+
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ e1000_irq_disable(adapter);
+
+ ctrl = er32(CTRL);
+ if (features & NETIF_F_HW_VLAN_RX) {
+ /* enable VLAN tag insert/strip */
+ ctrl |= E1000_CTRL_VME;
+ } else {
+ /* disable VLAN tag insert/strip */
+ ctrl &= ~E1000_CTRL_VME;
}
+ ew32(CTRL, ctrl);
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_enable(adapter);
@@ -4556,11 +4619,17 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
(vid == adapter->mng_vlan_id))
return;
+
+ if (!e1000_vlan_used(adapter))
+ e1000_vlan_filter_on_off(adapter, true);
+
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
vfta |= (1 << (vid & 0x1F));
e1000_write_vfta(hw, index, vfta);
+
+ set_bit(vid, adapter->active_vlans);
}
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -4571,7 +4640,6 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_disable(adapter);
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_enable(adapter);
@@ -4580,20 +4648,23 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
vfta &= ~(1 << (vid & 0x1F));
e1000_write_vfta(hw, index, vfta);
+
+ clear_bit(vid, adapter->active_vlans);
+
+ if (!e1000_vlan_used(adapter))
+ e1000_vlan_filter_on_off(adapter, false);
}
static void e1000_restore_vlan(struct e1000_adapter *adapter)
{
- e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ u16 vid;
- if (adapter->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
- e1000_vlan_rx_add_vid(adapter->netdev, vid);
- }
- }
+ if (!e1000_vlan_used(adapter))
+ return;
+
+ e1000_vlan_filter_on_off(adapter, true);
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ e1000_vlan_rx_add_vid(adapter->netdev, vid);
}
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 8295f2192439..480f2592f8a5 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -431,8 +431,6 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
adapter->flags &= ~FLAG_HAS_WOL;
break;
case e1000_82573:
- case e1000_82574:
- case e1000_82583:
if (pdev->device == E1000_DEV_ID_82573L) {
adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
adapter->max_hw_frame_size = DEFAULT_JUMBO;
@@ -2104,10 +2102,11 @@ struct e1000_info e1000_82583_info = {
| FLAG_RX_CSUM_ENABLED
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
+ | FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_CTRLEXT_ON_LOAD,
.flags2 = FLAG2_DISABLE_ASPM_L0S,
.pba = 32,
- .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN,
+ .max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
.mac_ops = &e82571_mac_ops,
.phy_ops = &e82_phy_ops_bm,
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 9549879e66a0..638d175792cf 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -104,6 +104,7 @@ struct e1000_info;
(((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)))
/* PHY Wakeup Registers and defines */
+#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17)
#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0)
#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
@@ -122,20 +123,21 @@ struct e1000_info;
#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
-#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */
-#define HV_SCC_LOWER PHY_REG(778, 17)
-#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */
-#define HV_ECOL_LOWER PHY_REG(778, 19)
-#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */
-#define HV_MCC_LOWER PHY_REG(778, 21)
-#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */
-#define HV_LATECOL_LOWER PHY_REG(778, 24)
-#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */
-#define HV_COLC_LOWER PHY_REG(778, 26)
-#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */
-#define HV_DC_LOWER PHY_REG(778, 28)
-#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */
-#define HV_TNCRS_LOWER PHY_REG(778, 30)
+#define HV_STATS_PAGE 778
+#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
+#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17)
+#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
+#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19)
+#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
+#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21)
+#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
+#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
+#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
+#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26)
+#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
+#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28)
+#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
+#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30)
#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */
@@ -197,11 +199,6 @@ enum e1000_boards {
board_pch2lan,
};
-struct e1000_queue_stats {
- u64 packets;
- u64 bytes;
-};
-
struct e1000_ps_page {
struct page *page;
u64 dma; /* must be u64 - written to hw */
@@ -255,8 +252,6 @@ struct e1000_ring {
int set_itr;
struct sk_buff *rx_skb_top;
-
- struct e1000_queue_stats stats;
};
/* PHY register snapshot values */
@@ -339,7 +334,7 @@ struct e1000_adapter {
int *work_done, int work_to_do)
____cacheline_aligned_in_smp;
void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- int cleaned_count);
+ int cleaned_count, gfp_t gfp);
struct e1000_ring *rx_ring;
u32 rx_int_delay;
@@ -533,7 +528,8 @@ extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
bool state);
extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
-extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+extern void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw);
+extern void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
@@ -584,6 +580,7 @@ extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw);
extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw);
extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw);
extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw);
+extern s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page);
extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
u16 *data);
@@ -604,6 +601,10 @@ extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id);
extern s32 e1000e_determine_phy_address(struct e1000_hw *hw);
extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
+ u16 *phy_reg);
+extern s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
+ u16 *phy_reg);
extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
@@ -624,9 +625,13 @@ extern s32 e1000e_check_downshift(struct e1000_hw *hw);
extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
u16 *data);
+extern s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
+ u16 *data);
extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
u16 data);
+extern s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
+ u16 data);
extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
extern s32 e1000_check_polarity_82577(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index f4bbeb22f51f..c0ecb2d9fdb7 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -836,6 +836,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
struct e1000_mac_info *mac = &hw->mac;
u32 reg_data;
s32 ret_val;
+ u16 kum_reg_data;
u16 i;
e1000_initialize_hw_bits_80003es2lan(hw);
@@ -861,6 +862,13 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
/* Setup link and flow control */
ret_val = e1000e_setup_link(hw);
+ /* Disable IBIST slave mode (far-end loopback) */
+ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &kum_reg_data);
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+
/* Set the transmit descriptor write-back policy */
reg_data = er32(TXDCTL(0));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 859d0d3af6c9..cb1a3623253e 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -28,6 +28,7 @@
/* ethtool support for e1000 */
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 6c2fa8327f5c..29670397079b 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -246,6 +246,7 @@ enum e1e_registers {
#define BM_WUC_ENABLE_REG 17
#define BM_WUC_ENABLE_BIT (1 << 2)
#define BM_WUC_HOST_WU_BIT (1 << 4)
+#define BM_WUC_ME_WU_BIT (1 << 5)
#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
@@ -312,6 +313,7 @@ enum e1e_registers {
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
+#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002
@@ -777,7 +779,21 @@ struct e1000_mac_operations {
s32 (*read_mac_addr)(struct e1000_hw *);
};
-/* Function pointers for the PHY. */
+/*
+ * When to use various PHY register access functions:
+ *
+ * Func Caller
+ * Function Does Does When to use
+ * ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * X_reg L,P,A n/a for simple PHY reg accesses
+ * X_reg_locked P,A L for multiple accesses of different regs
+ * on different pages
+ * X_reg_page A L,P for multiple accesses of different regs
+ * on the same page
+ *
+ * Where X=[read|write], L=locking, P=sets page, A=register access
+ *
+ */
struct e1000_phy_operations {
s32 (*acquire)(struct e1000_hw *);
s32 (*cfg_on_link_up)(struct e1000_hw *);
@@ -788,14 +804,17 @@ struct e1000_phy_operations {
s32 (*get_cfg_done)(struct e1000_hw *hw);
s32 (*get_cable_length)(struct e1000_hw *);
s32 (*get_info)(struct e1000_hw *);
+ s32 (*set_page)(struct e1000_hw *, u16);
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
+ s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *);
void (*release)(struct e1000_hw *);
s32 (*reset)(struct e1000_hw *);
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_reg)(struct e1000_hw *, u32, u16);
s32 (*write_reg_locked)(struct e1000_hw *, u32, u16);
+ s32 (*write_reg_page)(struct e1000_hw *, u32, u16);
void (*power_up)(struct e1000_hw *);
void (*power_down)(struct e1000_hw *);
};
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 3369d1f6a39c..c1752124f3cd 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -275,6 +275,19 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
#define ew16flash(reg,val) __ew16flash(hw, (reg), (val))
#define ew32flash(reg,val) __ew32flash(hw, (reg), (val))
+static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
+{
+ u32 ctrl;
+
+ ctrl = er32(CTRL);
+ ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
+ ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
+ ew32(CTRL, ctrl);
+ udelay(10);
+ ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+ ew32(CTRL, ctrl);
+}
+
/**
* e1000_init_phy_params_pchlan - Initialize PHY function pointers
* @hw: pointer to the HW structure
@@ -284,18 +297,21 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- u32 ctrl, fwsm;
+ u32 fwsm;
s32 ret_val = 0;
phy->addr = 1;
phy->reset_delay_us = 100;
+ phy->ops.set_page = e1000_set_page_igp;
phy->ops.read_reg = e1000_read_phy_reg_hv;
phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
+ phy->ops.read_reg_page = e1000_read_phy_reg_page_hv;
phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.write_reg = e1000_write_phy_reg_hv;
phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
+ phy->ops.write_reg_page = e1000_write_phy_reg_page_hv;
phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
@@ -308,13 +324,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
*/
fwsm = er32(FWSM);
if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
- ctrl = er32(CTRL);
- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
- ew32(CTRL, ctrl);
- udelay(10);
- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
- ew32(CTRL, ctrl);
+ e1000_toggle_lanphypc_value_ich8lan(hw);
msleep(50);
/*
@@ -882,8 +892,13 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
u32 extcnf_ctrl;
extcnf_ctrl = er32(EXTCNF_CTRL);
- extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
- ew32(EXTCNF_CTRL, extcnf_ctrl);
+
+ if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) {
+ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
+ } else {
+ e_dbg("Semaphore unexpectedly released by sw/fw/hw\n");
+ }
mutex_unlock(&swflag_mutex);
}
@@ -1376,14 +1391,11 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
goto out;
- ret_val = hw->phy.ops.read_reg_locked(hw,
- PHY_REG(BM_PORT_CTRL_PAGE, 17),
- &phy_data);
+ ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
if (ret_val)
goto release;
- ret_val = hw->phy.ops.write_reg_locked(hw,
- PHY_REG(BM_PORT_CTRL_PAGE, 17),
- phy_data & 0x00FF);
+ ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
+ phy_data & 0x00FF);
release:
hw->phy.ops.release(hw);
out:
@@ -1397,17 +1409,36 @@ out:
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
{
u32 mac_reg;
- u16 i;
+ u16 i, phy_reg = 0;
+ s32 ret_val;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+ if (ret_val)
+ goto release;
/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
mac_reg = er32(RAL(i));
- e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
+ (u16)((mac_reg >> 16) & 0xFFFF));
+
mac_reg = er32(RAH(i));
- e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
+ (u16)((mac_reg & E1000_RAH_AV)
+ >> 16));
}
+
+ e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
}
/**
@@ -1726,9 +1757,12 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
break;
}
- /* Dummy read to clear the phy wakeup bit after lcd reset */
- if (hw->mac.type >= e1000_pchlan)
- e1e_rphy(hw, BM_WUC, &reg);
+ /* Clear the host wakeup bit after lcd reset */
+ if (hw->mac.type >= e1000_pchlan) {
+ e1e_rphy(hw, BM_PORT_GEN_CFG, &reg);
+ reg &= ~BM_WUC_HOST_WU_BIT;
+ e1e_wphy(hw, BM_PORT_GEN_CFG, reg);
+ }
/* Configure the LCD with the extended configuration region in NVM */
ret_val = e1000_sw_lcd_config_ich8lan(hw);
@@ -3059,7 +3093,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
msleep(20);
if (!ret_val)
- e1000_release_swflag_ich8lan(hw);
+ mutex_unlock(&swflag_mutex);
if (ctrl & E1000_CTRL_PHY_RST) {
ret_val = hw->phy.ops.get_cfg_done(hw);
@@ -3127,11 +3161,13 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
/*
* The 82578 Rx buffer will stall if wakeup is enabled in host and
- * the ME. Reading the BM_WUC register will clear the host wakeup bit.
+ * the ME. Disable wakeup by clearing the host wakeup bit.
* Reset the phy after disabling host wakeup to reset the Rx buffer.
*/
if (hw->phy.type == e1000_phy_82578) {
- e1e_rphy(hw, BM_WUC, &i);
+ e1e_rphy(hw, BM_PORT_GEN_CFG, &i);
+ i &= ~BM_WUC_HOST_WU_BIT;
+ e1e_wphy(hw, BM_PORT_GEN_CFG, i);
ret_val = e1000_phy_hw_reset_ich8lan(hw);
if (ret_val)
return ret_val;
@@ -3586,17 +3622,16 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
}
/**
- * e1000e_disable_gig_wol_ich8lan - disable gig during WoL
+ * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
* @hw: pointer to the HW structure
*
* During S0 to Sx transition, it is possible the link remains at gig
* instead of negotiating to a lower speed. Before going to Sx, set
* 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
- * to a lower speed.
- *
- * Should only be called for applicable parts.
+ * to a lower speed. For PCH and newer parts, the OEM bits PHY register
+ * (LED, GbE disable and LPLU configurations) also needs to be written.
**/
-void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
u32 phy_ctrl;
s32 ret_val;
@@ -3616,6 +3651,60 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
}
/**
+ * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
+ * @hw: pointer to the HW structure
+ *
+ * During Sx to S0 transitions on non-managed devices or managed devices
+ * on which PHY resets are not blocked, if the PHY registers cannot be
+ * accessed properly by the s/w toggle the LANPHYPC value to power cycle
+ * the PHY.
+ **/
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
+{
+ u32 fwsm;
+
+ if (hw->mac.type != e1000_pch2lan)
+ return;
+
+ fwsm = er32(FWSM);
+ if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) {
+ u16 phy_id1, phy_id2;
+ s32 ret_val;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to acquire PHY semaphore in resume\n");
+ return;
+ }
+
+ /* Test access to the PHY registers by reading the ID regs */
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
+ if (ret_val)
+ goto release;
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
+ if (ret_val)
+ goto release;
+
+ if (hw->phy.id == ((u32)(phy_id1 << 16) |
+ (u32)(phy_id2 & PHY_REVISION_MASK)))
+ goto release;
+
+ e1000_toggle_lanphypc_value_ich8lan(hw);
+
+ hw->phy.ops.release(hw);
+ msleep(50);
+ e1000_phy_hw_reset(hw);
+ msleep(50);
+ return;
+ }
+
+release:
+ hw->phy.ops.release(hw);
+
+ return;
+}
+
+/**
* e1000_cleanup_led_ich8lan - Restore the default LED operation
* @hw: pointer to the HW structure
*
@@ -3832,6 +3921,7 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
{
u16 phy_data;
+ s32 ret_val;
e1000e_clear_hw_cntrs_base(hw);
@@ -3853,20 +3943,29 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) {
- e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
- e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
- e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
- e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
- e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
- e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
- e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
- e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
- e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
- e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
- e1e_rphy(hw, HV_DC_UPPER, &phy_data);
- e1e_rphy(hw, HV_DC_LOWER, &phy_data);
- e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
- e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+ ret_val = hw->phy.ops.set_page(hw,
+ HV_STATS_PAGE << IGP_PAGE_SHIFT);
+ if (ret_val)
+ goto release;
+ hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
+release:
+ hw->phy.ops.release(hw);
}
}
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index dd8ab05b5590..65580b405942 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -56,7 +56,7 @@ s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
struct e1000_adapter *adapter = hw->adapter;
u16 pcie_link_status, cap_offset;
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ cap_offset = adapter->pdev->pcie_cap;
if (!cap_offset) {
bus->width = e1000_bus_width_unknown;
} else {
@@ -220,7 +220,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
}
/* if multicast bit is set, the alternate address will not be used */
- if (alt_mac_addr[0] & 0x01) {
+ if (is_multicast_ether_addr(alt_mac_addr)) {
e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
goto out;
}
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 3310c3d477d7..4353ad56cf16 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
@@ -53,9 +54,9 @@
#include "e1000.h"
-#define DRV_EXTRAVERSION "-k2"
+#define DRV_EXTRAVERSION "-k"
-#define DRV_VERSION "1.3.10" DRV_EXTRAVERSION
+#define DRV_VERSION "1.3.16" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -522,7 +523,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
* @adapter: address of board private structure
**/
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- int cleaned_count)
+ int cleaned_count, gfp_t gfp)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -543,7 +544,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
goto map_skb;
}
- skb = netdev_alloc_skb_ip_align(netdev, bufsz);
+ skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp);
if (!skb) {
/* Better luck next round */
adapter->alloc_rx_buff_failed++;
@@ -588,7 +589,7 @@ map_skb:
* @adapter: address of board private structure
**/
static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- int cleaned_count)
+ int cleaned_count, gfp_t gfp)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -614,7 +615,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
continue;
}
if (!ps_page->page) {
- ps_page->page = alloc_page(GFP_ATOMIC);
+ ps_page->page = alloc_page(gfp);
if (!ps_page->page) {
adapter->alloc_rx_buff_failed++;
goto no_buffers;
@@ -640,8 +641,9 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
cpu_to_le64(ps_page->dma);
}
- skb = netdev_alloc_skb_ip_align(netdev,
- adapter->rx_ps_bsize0);
+ skb = __netdev_alloc_skb_ip_align(netdev,
+ adapter->rx_ps_bsize0,
+ gfp);
if (!skb) {
adapter->alloc_rx_buff_failed++;
@@ -691,7 +693,7 @@ no_buffers:
**/
static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
- int cleaned_count)
+ int cleaned_count, gfp_t gfp)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -712,7 +714,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
goto check_page;
}
- skb = netdev_alloc_skb_ip_align(netdev, bufsz);
+ skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp);
if (unlikely(!skb)) {
/* Better luck next round */
adapter->alloc_rx_buff_failed++;
@@ -723,7 +725,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
check_page:
/* allocate a new page if necessary */
if (!buffer_info->page) {
- buffer_info->page = alloc_page(GFP_ATOMIC);
+ buffer_info->page = alloc_page(gfp);
if (unlikely(!buffer_info->page)) {
adapter->alloc_rx_buff_failed++;
break;
@@ -887,7 +889,8 @@ next_desc:
/* return some buffers to hardware, one at a time is too slow */
if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
- adapter->alloc_rx_buf(adapter, cleaned_count);
+ adapter->alloc_rx_buf(adapter, cleaned_count,
+ GFP_ATOMIC);
cleaned_count = 0;
}
@@ -899,7 +902,7 @@ next_desc:
cleaned_count = e1000_desc_unused(rx_ring);
if (cleaned_count)
- adapter->alloc_rx_buf(adapter, cleaned_count);
+ adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
@@ -1229,7 +1232,8 @@ next_desc:
/* return some buffers to hardware, one at a time is too slow */
if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
- adapter->alloc_rx_buf(adapter, cleaned_count);
+ adapter->alloc_rx_buf(adapter, cleaned_count,
+ GFP_ATOMIC);
cleaned_count = 0;
}
@@ -1243,7 +1247,7 @@ next_desc:
cleaned_count = e1000_desc_unused(rx_ring);
if (cleaned_count)
- adapter->alloc_rx_buf(adapter, cleaned_count);
+ adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
@@ -1410,7 +1414,8 @@ next_desc:
/* return some buffers to hardware, one at a time is too slow */
if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
- adapter->alloc_rx_buf(adapter, cleaned_count);
+ adapter->alloc_rx_buf(adapter, cleaned_count,
+ GFP_ATOMIC);
cleaned_count = 0;
}
@@ -1422,7 +1427,7 @@ next_desc:
cleaned_count = e1000_desc_unused(rx_ring);
if (cleaned_count)
- adapter->alloc_rx_buf(adapter, cleaned_count);
+ adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
@@ -3104,7 +3109,8 @@ static void e1000_configure(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring));
+ adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring),
+ GFP_KERNEL);
}
/**
@@ -3346,7 +3352,7 @@ int e1000e_up(struct e1000_adapter *adapter)
e1000_configure_msix(adapter);
e1000_irq_enable(adapter);
- netif_wake_queue(adapter->netdev);
+ netif_start_queue(adapter->netdev);
/* fire a link change interrupt to start the watchdog */
if (adapter->msix_entries)
@@ -3413,17 +3419,16 @@ void e1000e_down(struct e1000_adapter *adapter)
e1000e_update_stats(adapter);
spin_unlock(&adapter->stats64_lock);
+ e1000e_flush_descriptors(adapter);
+ e1000_clean_tx_ring(adapter);
+ e1000_clean_rx_ring(adapter);
+
adapter->link_speed = 0;
adapter->link_duplex = 0;
if (!pci_channel_offline(adapter->pdev))
e1000e_reset(adapter);
- e1000e_flush_descriptors(adapter);
-
- e1000_clean_tx_ring(adapter);
- e1000_clean_rx_ring(adapter);
-
/*
* TODO: for power management, we could drop the link and
* pci_disable_device here.
@@ -3833,6 +3838,8 @@ static void e1000_update_phy_info(unsigned long data)
/**
* e1000e_update_phy_stats - Update the PHY statistics counters
* @adapter: board private structure
+ *
+ * Read/clear the upper 16-bit PHY registers and read/accumulate lower
**/
static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
{
@@ -3844,89 +3851,61 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
if (ret_val)
return;
- hw->phy.addr = 1;
-
-#define HV_PHY_STATS_PAGE 778
/*
* A page set is expensive so check if already on desired page.
* If not, set to the page with the PHY status registers.
*/
+ hw->phy.addr = 1;
ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
&phy_data);
if (ret_val)
goto release;
- if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) {
- ret_val = e1000e_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (HV_PHY_STATS_PAGE <<
- IGP_PAGE_SHIFT));
+ if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) {
+ ret_val = hw->phy.ops.set_page(hw,
+ HV_STATS_PAGE << IGP_PAGE_SHIFT);
if (ret_val)
goto release;
}
- /* Read/clear the upper 16-bit registers and read/accumulate lower */
-
/* Single Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_SCC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
if (!ret_val)
adapter->stats.scc += phy_data;
/* Excessive Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
if (!ret_val)
adapter->stats.ecol += phy_data;
/* Multiple Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_MCC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
if (!ret_val)
adapter->stats.mcc += phy_data;
/* Late Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_LATECOL_LOWER &
- MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
if (!ret_val)
adapter->stats.latecol += phy_data;
/* Collision Count - also used for adaptive IFS */
- e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_COLC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
if (!ret_val)
hw->mac.collision_delta = phy_data;
/* Defer Count */
- e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_DC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
if (!ret_val)
adapter->stats.dc += phy_data;
/* Transmit with no CRS */
- e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
if (!ret_val)
adapter->stats.tncrs += phy_data;
@@ -5154,21 +5133,34 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
{
struct e1000_hw *hw = &adapter->hw;
u32 i, mac_reg;
- u16 phy_reg;
+ u16 phy_reg, wuc_enable;
int retval = 0;
/* copy MAC RARs to PHY RARs */
e1000_copy_rx_addrs_to_phy_ich8lan(hw);
- /* copy MAC MTA to PHY MTA */
+ retval = hw->phy.ops.acquire(hw);
+ if (retval) {
+ e_err("Could not acquire PHY\n");
+ return retval;
+ }
+
+ /* Enable access to wakeup registers on and set page to BM_WUC_PAGE */
+ retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
+ if (retval)
+ goto out;
+
+ /* copy MAC MTA to PHY MTA - only needed for pchlan */
for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i);
- e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_MTA(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1,
+ (u16)((mac_reg >> 16) & 0xFFFF));
}
/* configure PHY Rx Control register */
- e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg);
+ hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg);
mac_reg = er32(RCTL);
if (mac_reg & E1000_RCTL_UPE)
phy_reg |= BM_RCTL_UPE;
@@ -5185,31 +5177,19 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
mac_reg = er32(CTRL);
if (mac_reg & E1000_CTRL_RFCE)
phy_reg |= BM_RCTL_RFCE;
- e1e_wphy(&adapter->hw, BM_RCTL, phy_reg);
+ hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg);
/* enable PHY wakeup in MAC register */
ew32(WUFC, wufc);
ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
/* configure and enable PHY wakeup in PHY registers */
- e1e_wphy(&adapter->hw, BM_WUFC, wufc);
- e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
+ hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc);
+ hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
/* activate PHY wakeup */
- retval = hw->phy.ops.acquire(hw);
- if (retval) {
- e_err("Could not acquire PHY\n");
- return retval;
- }
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
- retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
- if (retval) {
- e_err("Could not read PHY page 769\n");
- goto out;
- }
- phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
- retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+ wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
+ retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
if (retval)
e_err("Could not set PHY Host Wakeup bit\n");
out:
@@ -5277,7 +5257,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
}
if (adapter->flags & FLAG_IS_ICH)
- e1000e_disable_gig_wol_ich8lan(&adapter->hw);
+ e1000_suspend_workarounds_ich8lan(&adapter->hw);
/* Allow time for pending master requests to run */
e1000e_disable_pcie_master(&adapter->hw);
@@ -5343,7 +5323,7 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
*/
if (adapter->flags & FLAG_IS_QUAD_PORT) {
struct pci_dev *us_dev = pdev->bus->self;
- int pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP);
+ int pos = pci_pcie_cap(us_dev);
u16 devctl;
pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl);
@@ -5428,6 +5408,9 @@ static int __e1000_resume(struct pci_dev *pdev)
return err;
}
+ if (hw->mac.type == e1000_pch2lan)
+ e1000_resume_workarounds_pchlan(&adapter->hw);
+
e1000e_power_up_phy(adapter);
/* report the system wakeup cause from S3/S4 */
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 484774c13c21..2a6ee13285b1 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -36,7 +36,7 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
static s32 e1000_wait_autoneg(struct e1000_hw *hw);
static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read);
+ u16 *data, bool read, bool page_set);
static u32 e1000_get_phy_addr_for_hv_page(u32 page);
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
u16 *data, bool read);
@@ -348,6 +348,24 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
+ * e1000_set_page_igp - Set page as on IGP-like PHY(s)
+ * @hw: pointer to the HW structure
+ * @page: page to set (shifted left when necessary)
+ *
+ * Sets PHY page required for PHY register access. Assumes semaphore is
+ * already acquired. Note, this function sets phy.addr to 1 so the caller
+ * must set it appropriately (if necessary) after this function returns.
+ **/
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
+{
+ e_dbg("Setting page 0x%x\n", page);
+
+ hw->phy.addr = 1;
+
+ return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
+}
+
+/**
* __e1000e_read_phy_reg_igp - Read igp PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
@@ -2418,7 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
- false);
+ false, false);
goto out;
}
@@ -2477,7 +2495,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
- true);
+ true, false);
goto out;
}
@@ -2535,7 +2553,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
- true);
+ true, false);
goto out;
}
@@ -2579,7 +2597,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
- false);
+ false, false);
goto out;
}
@@ -2603,104 +2621,163 @@ out:
}
/**
- * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
+ * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
* @hw: pointer to the HW structure
- * @offset: register offset to be read or written
- * @data: pointer to the data to read or write
- * @read: determines if operation is read or write
+ * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
*
- * Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retrieved information in data. Release any acquired
- * semaphores before exiting. Note that procedure to read the wakeup
- * registers are different. It works as such:
- * 1) Set page 769, register 17, bit 2 = 1
- * 2) Set page to 800 for host (801 if we were manageability)
- * 3) Write the address using the address opcode (0x11)
- * 4) Read or write the data using the data opcode (0x12)
- * 5) Restore 769_17.2 to its original value
- *
- * Assumes semaphore already acquired.
+ * Assumes semaphore already acquired and phy_reg points to a valid memory
+ * address to store contents of the BM_WUC_ENABLE_REG register.
**/
-static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read)
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
{
s32 ret_val;
- u16 reg = BM_PHY_REG_NUM(offset);
- u16 phy_reg = 0;
+ u16 temp;
- /* Gig must be disabled for MDIO accesses to page 800 */
- if ((hw->mac.type == e1000_pchlan) &&
- (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
- e_dbg("Attempting to access page 800 while gig enabled.\n");
-
- /* All operations in this function are phy address 1 */
+ /* All page select, port ctrl and wakeup registers use phy address 1 */
hw->phy.addr = 1;
- /* Set page 769 */
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
+ /* Select Port Control Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+ if (ret_val) {
+ e_dbg("Could not set Port Control page\n");
+ goto out;
+ }
- ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
+ ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
if (ret_val) {
- e_dbg("Could not read PHY page 769\n");
+ e_dbg("Could not read PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
goto out;
}
- /* First clear bit 4 to avoid a power state change */
- phy_reg &= ~(BM_WUC_HOST_WU_BIT);
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+ /*
+ * Enable both PHY wakeup mode and Wakeup register page writes.
+ * Prevent a power state change by disabling ME and Host PHY wakeup.
+ */
+ temp = *phy_reg;
+ temp |= BM_WUC_ENABLE_BIT;
+ temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
+
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
if (ret_val) {
- e_dbg("Could not clear PHY page 769 bit 4\n");
+ e_dbg("Could not write PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
goto out;
}
- /* Write bit 2 = 1, and clear bit 4 to 769_17 */
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
- phy_reg | BM_WUC_ENABLE_BIT);
+ /* Select Host Wakeup Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+
+ /* caller now able to write registers on the Wakeup registers page */
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
+ * @hw: pointer to the HW structure
+ * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
+ *
+ * Restore BM_WUC_ENABLE_REG to its original value.
+ *
+ * Assumes semaphore already acquired and *phy_reg is the contents of the
+ * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
+ * caller.
+ **/
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+ s32 ret_val = 0;
+
+ /* Select Port Control Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
if (ret_val) {
- e_dbg("Could not write PHY page 769 bit 2\n");
+ e_dbg("Could not set Port Control page\n");
goto out;
}
- /* Select page 800 */
- ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+ /* Restore 769.17 to its original value */
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
+ if (ret_val)
+ e_dbg("Could not restore PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+out:
+ return ret_val;
+}
- /* Write the page 800 offset value using opcode 0x11 */
+/**
+ * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read or written
+ * @data: pointer to the data to read or write
+ * @read: determines if operation is read or write
+ * @page_set: BM_WUC_PAGE already set and access enabled
+ *
+ * Read the PHY register at offset and store the retrieved information in
+ * data, or write data to PHY register at offset. Note the procedure to
+ * access the PHY wakeup registers is different than reading the other PHY
+ * registers. It works as such:
+ * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1
+ * 2) Set page to 800 for host (801 if we were manageability)
+ * 3) Write the address using the address opcode (0x11)
+ * 4) Read or write the data using the data opcode (0x12)
+ * 5) Restore 769.17.2 to its original value
+ *
+ * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
+ * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
+ *
+ * Assumes semaphore is already acquired. When page_set==true, assumes
+ * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
+ * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
+ **/
+static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
+ u16 *data, bool read, bool page_set)
+{
+ s32 ret_val;
+ u16 reg = BM_PHY_REG_NUM(offset);
+ u16 page = BM_PHY_REG_PAGE(offset);
+ u16 phy_reg = 0;
+
+ /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
+ if ((hw->mac.type == e1000_pchlan) &&
+ (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
+ e_dbg("Attempting to access page %d while gig enabled.\n",
+ page);
+
+ if (!page_set) {
+ /* Enable access to PHY wakeup registers */
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+ if (ret_val) {
+ e_dbg("Could not enable PHY wakeup reg access\n");
+ goto out;
+ }
+ }
+
+ e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg);
+
+ /* Write the Wakeup register page offset value using opcode 0x11 */
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
if (ret_val) {
- e_dbg("Could not write address opcode to page 800\n");
+ e_dbg("Could not write address opcode to page %d\n", page);
goto out;
}
if (read) {
- /* Read the page 800 value using opcode 0x12 */
+ /* Read the Wakeup register page value using opcode 0x12 */
ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
data);
} else {
- /* Write the page 800 value using opcode 0x12 */
+ /* Write the Wakeup register page value using opcode 0x12 */
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
*data);
}
if (ret_val) {
- e_dbg("Could not access data value from page 800\n");
+ e_dbg("Could not access PHY reg %d.%d\n", page, reg);
goto out;
}
- /*
- * Restore 769_17.2 to its original value
- * Set page 769
- */
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-
- /* Clear 769_17.2 */
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
- if (ret_val) {
- e_dbg("Could not clear PHY page 769 bit 2\n");
- goto out;
- }
+ if (!page_set)
+ ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
out:
return ret_val;
@@ -2792,11 +2869,12 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
* semaphore before exiting.
**/
static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
- bool locked)
+ bool locked, bool page_set)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (!locked) {
ret_val = hw->phy.ops.acquire(hw);
@@ -2806,8 +2884,8 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
- data, true);
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+ true, page_set);
goto out;
}
@@ -2817,26 +2895,25 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
goto out;
}
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
- if (page == HV_INTC_FC_PAGE_START)
- page = 0;
+ if (!page_set) {
+ if (page == HV_INTC_FC_PAGE_START)
+ page = 0;
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
- u32 phy_addr = hw->phy.addr;
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000_set_page_igp(hw,
+ (page << IGP_PAGE_SHIFT));
- hw->phy.addr = 1;
-
- /* Page is shifted left, PHY expects (page x 32) */
- ret_val = e1000e_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
- hw->phy.addr = phy_addr;
+ hw->phy.addr = phy_addr;
- if (ret_val)
- goto out;
+ if (ret_val)
+ goto out;
+ }
}
+ e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+ page << IGP_PAGE_SHIFT, reg);
+
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
data);
out:
@@ -2858,7 +2935,7 @@ out:
**/
s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
{
- return __e1000_read_phy_reg_hv(hw, offset, data, false);
+ return __e1000_read_phy_reg_hv(hw, offset, data, false, false);
}
/**
@@ -2872,7 +2949,21 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
**/
s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
{
- return __e1000_read_phy_reg_hv(hw, offset, data, true);
+ return __e1000_read_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ * e1000_read_phy_reg_page_hv - Read HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Reads the PHY register at offset and stores the retrieved information
+ * in data. Assumes semaphore already acquired and page already set.
+ **/
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000_read_phy_reg_hv(hw, offset, data, true, true);
}
/**
@@ -2886,11 +2977,12 @@ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
* at the offset. Release any acquired semaphores before exiting.
**/
static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
- bool locked)
+ bool locked, bool page_set)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (!locked) {
ret_val = hw->phy.ops.acquire(hw);
@@ -2900,8 +2992,8 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
- &data, false);
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+ false, page_set);
goto out;
}
@@ -2911,42 +3003,41 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
goto out;
}
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
- if (page == HV_INTC_FC_PAGE_START)
- page = 0;
-
- /*
- * Workaround MDIO accesses being disabled after entering IEEE Power
- * Down (whenever bit 11 of the PHY Control register is set)
- */
- if ((hw->phy.type == e1000_phy_82578) &&
- (hw->phy.revision >= 1) &&
- (hw->phy.addr == 2) &&
- ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
- (data & (1 << 11))) {
- u16 data2 = 0x7EFF;
- ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
- &data2, false);
- if (ret_val)
- goto out;
- }
+ if (!page_set) {
+ if (page == HV_INTC_FC_PAGE_START)
+ page = 0;
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
- u32 phy_addr = hw->phy.addr;
+ /*
+ * Workaround MDIO accesses being disabled after entering IEEE
+ * Power Down (when bit 11 of the PHY Control register is set)
+ */
+ if ((hw->phy.type == e1000_phy_82578) &&
+ (hw->phy.revision >= 1) &&
+ (hw->phy.addr == 2) &&
+ ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) {
+ u16 data2 = 0x7EFF;
+ ret_val = e1000_access_phy_debug_regs_hv(hw,
+ (1 << 6) | 0x3,
+ &data2, false);
+ if (ret_val)
+ goto out;
+ }
- hw->phy.addr = 1;
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000_set_page_igp(hw,
+ (page << IGP_PAGE_SHIFT));
- /* Page is shifted left, PHY expects (page x 32) */
- ret_val = e1000e_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
- hw->phy.addr = phy_addr;
+ hw->phy.addr = phy_addr;
- if (ret_val)
- goto out;
+ if (ret_val)
+ goto out;
+ }
}
+ e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+ page << IGP_PAGE_SHIFT, reg);
+
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
data);
@@ -2968,7 +3059,7 @@ out:
**/
s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
{
- return __e1000_write_phy_reg_hv(hw, offset, data, false);
+ return __e1000_write_phy_reg_hv(hw, offset, data, false, false);
}
/**
@@ -2982,7 +3073,21 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
**/
s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
{
- return __e1000_write_phy_reg_hv(hw, offset, data, true);
+ return __e1000_write_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ * e1000_write_phy_reg_page_hv - Write HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Writes the data to PHY register at the offset. Assumes semaphore
+ * already acquired and page already set.
+ **/
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000_write_phy_reg_hv(hw, offset, data, true, true);
}
/**
@@ -3004,11 +3109,12 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
* @hw: pointer to the HW structure
* @offset: register offset to be read or written
* @data: pointer to the data to be read or written
- * @read: determines if operation is read or written
+ * @read: determines if operation is read or write
*
* Reads the PHY register at offset and stores the retreived information
* in data. Assumes semaphore already acquired. Note that the procedure
- * to read these regs uses the address port and data port to read/write.
+ * to access these regs uses the address port and data port to read/write.
+ * These accesses done with PHY address 2 and without using pages.
**/
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
u16 *data, bool read)
@@ -3028,7 +3134,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
/* masking with 0x3F to remove the page from offset */
ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
if (ret_val) {
- e_dbg("Could not write PHY the HV address register\n");
+ e_dbg("Could not write the Address Offset port register\n");
goto out;
}
@@ -3039,7 +3145,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
if (ret_val) {
- e_dbg("Could not read data value from HV data register\n");
+ e_dbg("Could not access the Data port register\n");
goto out;
}
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 94ec973b2bdc..d50a9998ae77 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -44,6 +44,7 @@ static const char version[] =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/io.h>
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 48ee51bb9e50..a19228563efd 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -365,7 +365,7 @@ static int __init do_express_probe(struct net_device *dev)
dev->irq = mca_irqmap[(pos1>>4)&0x7];
/*
- * XXX: Transciever selection is done
+ * XXX: Transceiver selection is done
* differently on the MCA version.
* How to get it to select something
* other than external/AUI is currently
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 6c7257bd73fc..7dd5e6a0d998 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -457,7 +457,6 @@ struct ehea_port {
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 vlan_group *vgrp;
struct ehea_eq *qp_eq;
struct work_struct reset_task;
struct mutex port_lock;
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 3fd5a2400348..be2cb4ab8b4f 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -683,24 +683,13 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
struct sk_buff *skb)
{
- int vlan_extracted = ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
- pr->port->vgrp);
-
- if (skb->dev->features & NETIF_F_LRO) {
- if (vlan_extracted)
- lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb,
- pr->port->vgrp,
- cqe->vlan_tag,
- cqe);
- else
- lro_receive_skb(&pr->lro_mgr, skb, cqe);
- } else {
- if (vlan_extracted)
- vlan_hwaccel_receive_skb(skb, pr->port->vgrp,
- cqe->vlan_tag);
- else
- netif_receive_skb(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,
@@ -2339,32 +2328,6 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
-static void ehea_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
-{
- struct ehea_port *port = netdev_priv(dev);
- struct ehea_adapter *adapter = port->adapter;
- struct hcp_ehea_port_cb1 *cb1;
- u64 hret;
-
- port->vgrp = grp;
-
- cb1 = (void *)get_zeroed_page(GFP_KERNEL);
- if (!cb1) {
- pr_err("no mem for cb1\n");
- goto out;
- }
-
- hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
- H_PORT_CB1, H_PORT_CB1_ALL, cb1);
- if (hret != H_SUCCESS)
- pr_err("modify_ehea_port failed\n");
-
- free_page((unsigned long)cb1);
-out:
- return;
-}
-
static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct ehea_port *port = netdev_priv(dev);
@@ -2406,8 +2369,6 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
int index;
u64 hret;
- vlan_group_set_device(port->vgrp, vid, NULL);
-
cb1 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb1) {
pr_err("no mem for cb1\n");
@@ -3202,7 +3163,6 @@ static const struct net_device_ops ehea_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = ehea_set_multicast_list,
.ndo_change_mtu = ehea_change_mtu,
- .ndo_vlan_rx_register = ehea_vlan_rx_register,
.ndo_vlan_rx_add_vid = ehea_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ehea_vlan_rx_kill_vid,
.ndo_tx_timeout = ehea_tx_watchdog,
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index cd44bb8017d9..95b9f4fa811e 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -331,7 +331,7 @@ struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq)
unsigned long flags;
spin_lock_irqsave(&eq->spinlock, flags);
- eqe = (struct ehea_eqe *)hw_eqit_eq_get_inc_valid(&eq->hw_queue);
+ eqe = hw_eqit_eq_get_inc_valid(&eq->hw_queue);
spin_unlock_irqrestore(&eq->spinlock, flags);
return eqe;
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 38b351c7b979..ce76d9a8ca6e 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/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.13"
+#define DRV_VERSION "2.1.1.24"
#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
@@ -74,6 +74,7 @@ struct enic {
struct vnic_dev *vdev;
struct timer_list notify_timer;
struct work_struct reset;
+ struct work_struct change_mtu_work;
struct msix_entry msix_entry[ENIC_INTR_MAX];
struct enic_msix_entry msix[ENIC_INTR_MAX];
u32 msg_enable;
@@ -93,7 +94,6 @@ struct enic {
____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX];
spinlock_t wq_lock[ENIC_WQ_MAX];
unsigned int wq_count;
- struct vlan_group *vlan_group;
u16 loop_enable;
u16 loop_tag;
diff --git a/drivers/net/enic/enic_dev.c b/drivers/net/enic/enic_dev.c
index 90687b14e60f..fd6247b3c0ee 100644
--- a/drivers/net/enic/enic_dev.c
+++ b/drivers/net/enic/enic_dev.c
@@ -166,6 +166,17 @@ int enic_dev_disable(struct enic *enic)
return err;
}
+int enic_dev_intr_coal_timer_info(struct enic *enic)
+{
+ int err;
+
+ spin_lock(&enic->devcmd_lock);
+ err = vnic_dev_intr_coal_timer_info(enic->vdev);
+ spin_unlock(&enic->devcmd_lock);
+
+ return err;
+}
+
int enic_vnic_dev_deinit(struct enic *enic)
{
int err;
diff --git a/drivers/net/enic/enic_dev.h b/drivers/net/enic/enic_dev.h
index d5f681337626..ff8e87fdfc1d 100644
--- a/drivers/net/enic/enic_dev.h
+++ b/drivers/net/enic/enic_dev.h
@@ -34,6 +34,7 @@ int enic_dev_hang_notify(struct enic *enic);
int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic);
int enic_dev_enable(struct enic *enic);
int enic_dev_disable(struct enic *enic);
+int enic_dev_intr_coal_timer_info(struct enic *enic);
int enic_vnic_dev_deinit(struct enic *enic);
int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp);
int enic_dev_deinit_done(struct enic *enic, int *status);
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 2f433fbfca0c..67a27cd304dd 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -23,6 +23,7 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -152,12 +153,12 @@ static inline unsigned int enic_legacy_notify_intr(void)
static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq)
{
- return rq;
+ return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset;
}
static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq)
{
- return enic->rq_count + wq;
+ return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset;
}
static inline unsigned int enic_msix_err_intr(struct enic *enic)
@@ -283,12 +284,10 @@ static int enic_set_coalesce(struct net_device *netdev,
u32 rx_coalesce_usecs;
unsigned int i, intr;
- tx_coalesce_usecs = min_t(u32,
- INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
- ecmd->tx_coalesce_usecs);
- rx_coalesce_usecs = min_t(u32,
- INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
- ecmd->rx_coalesce_usecs);
+ tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
+ vnic_dev_get_intr_coal_timer_max(enic->vdev));
+ rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
+ vnic_dev_get_intr_coal_timer_max(enic->vdev));
switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_INTX:
@@ -297,26 +296,26 @@ static int enic_set_coalesce(struct net_device *netdev,
intr = enic_legacy_io_intr();
vnic_intr_coalescing_timer_set(&enic->intr[intr],
- INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+ tx_coalesce_usecs);
break;
case VNIC_DEV_INTR_MODE_MSI:
if (tx_coalesce_usecs != rx_coalesce_usecs)
return -EINVAL;
vnic_intr_coalescing_timer_set(&enic->intr[0],
- INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+ tx_coalesce_usecs);
break;
case VNIC_DEV_INTR_MODE_MSIX:
for (i = 0; i < enic->wq_count; i++) {
intr = enic_msix_wq_intr(enic, i);
vnic_intr_coalescing_timer_set(&enic->intr[intr],
- INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+ tx_coalesce_usecs);
}
for (i = 0; i < enic->rq_count; i++) {
intr = enic_msix_rq_intr(enic, i);
vnic_intr_coalescing_timer_set(&enic->intr[intr],
- INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs));
+ rx_coalesce_usecs);
}
break;
@@ -423,11 +422,18 @@ static void enic_mtu_check(struct enic *enic)
if (mtu && mtu != enic->port_mtu) {
enic->port_mtu = mtu;
- if (mtu < netdev->mtu)
- netdev_warn(netdev,
- "interface MTU (%d) set higher "
- "than switch port MTU (%d)\n",
- netdev->mtu, mtu);
+ if (enic_is_dynamic(enic)) {
+ mtu = max_t(int, ENIC_MIN_MTU,
+ min_t(int, ENIC_MAX_MTU, mtu));
+ if (mtu != netdev->mtu)
+ schedule_work(&enic->change_mtu_work);
+ } else {
+ if (mtu < netdev->mtu)
+ netdev_warn(netdev,
+ "interface MTU (%d) set higher "
+ "than switch port MTU (%d)\n",
+ netdev->mtu, mtu);
+ }
}
}
@@ -793,10 +799,10 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
}
/* dev_base_lock rwlock held, nominally process context */
-static struct net_device_stats *enic_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *enic_get_stats(struct net_device *netdev,
+ struct rtnl_link_stats64 *net_stats)
{
struct enic *enic = netdev_priv(netdev);
- struct net_device_stats *net_stats = &netdev->stats;
struct vnic_stats *stats;
enic_dev_stats_dump(enic, &stats);
@@ -1023,14 +1029,6 @@ static void enic_set_rx_mode(struct net_device *netdev)
}
}
-/* rtnl lock is held */
-static void enic_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *vlan_group)
-{
- struct enic *enic = netdev_priv(netdev);
- enic->vlan_group = vlan_group;
-}
-
/* netif_tx_lock held, BHs disabled */
static void enic_tx_timeout(struct net_device *netdev)
{
@@ -1258,24 +1256,13 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
skb->dev = netdev;
- if (enic->vlan_group && vlan_stripped &&
- (vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) {
-
- if (netdev->features & NETIF_F_GRO)
- vlan_gro_receive(&enic->napi[q_number],
- enic->vlan_group, vlan_tci, skb);
- else
- vlan_hwaccel_receive_skb(skb,
- enic->vlan_group, vlan_tci);
-
- } else {
+ if (vlan_stripped)
+ __vlan_hwaccel_put_tag(skb, vlan_tci);
- if (netdev->features & NETIF_F_GRO)
- napi_gro_receive(&enic->napi[q_number], skb);
- else
- netif_receive_skb(skb);
-
- }
+ if (netdev->features & NETIF_F_GRO)
+ napi_gro_receive(&enic->napi[q_number], skb);
+ else
+ netif_receive_skb(skb);
} else {
/* Buffer overflow
@@ -1560,7 +1547,7 @@ static void enic_notify_timer_start(struct enic *enic)
default:
/* Using intr for notification for INTx/MSI-X */
break;
- };
+ }
}
/* rtnl lock is held, process context */
@@ -1688,6 +1675,9 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
return -EINVAL;
+ if (enic_is_dynamic(enic))
+ return -EOPNOTSUPP;
+
if (running)
enic_stop(netdev);
@@ -1704,6 +1694,55 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
return 0;
}
+static void enic_change_mtu_work(struct work_struct *work)
+{
+ struct enic *enic = container_of(work, struct enic, change_mtu_work);
+ struct net_device *netdev = enic->netdev;
+ int new_mtu = vnic_dev_mtu(enic->vdev);
+ int err;
+ unsigned int i;
+
+ new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu));
+
+ rtnl_lock();
+
+ /* Stop RQ */
+ del_timer_sync(&enic->notify_timer);
+
+ for (i = 0; i < enic->rq_count; i++)
+ napi_disable(&enic->napi[i]);
+
+ vnic_intr_mask(&enic->intr[0]);
+ enic_synchronize_irqs(enic);
+ err = vnic_rq_disable(&enic->rq[0]);
+ if (err) {
+ netdev_err(netdev, "Unable to disable RQ.\n");
+ return;
+ }
+ vnic_rq_clean(&enic->rq[0], enic_free_rq_buf);
+ vnic_cq_clean(&enic->cq[0]);
+ vnic_intr_clean(&enic->intr[0]);
+
+ /* Fill RQ with new_mtu-sized buffers */
+ netdev->mtu = new_mtu;
+ vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
+ /* Need at least one buffer on ring to get going */
+ if (vnic_rq_desc_used(&enic->rq[0]) == 0) {
+ netdev_err(netdev, "Unable to alloc receive buffers.\n");
+ return;
+ }
+
+ /* Start RQ */
+ vnic_rq_enable(&enic->rq[0]);
+ napi_enable(&enic->napi[0]);
+ vnic_intr_unmask(&enic->intr[0]);
+ enic_notify_timer_start(enic);
+
+ rtnl_unlock();
+
+ netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu);
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void enic_poll_controller(struct net_device *netdev)
{
@@ -1718,8 +1757,12 @@ static void enic_poll_controller(struct net_device *netdev)
enic_isr_msix_rq(enic->msix_entry[intr].vector,
&enic->napi[i]);
}
- intr = enic_msix_wq_intr(enic, i);
- enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+
+ for (i = 0; i < enic->wq_count; i++) {
+ intr = enic_msix_wq_intr(enic, i);
+ enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+ }
+
break;
case VNIC_DEV_INTR_MODE_MSI:
enic_isr_msi(enic->pdev->irq, enic);
@@ -2057,13 +2100,12 @@ static const struct net_device_ops enic_netdev_dynamic_ops = {
.ndo_open = enic_open,
.ndo_stop = enic_stop,
.ndo_start_xmit = enic_hard_start_xmit,
- .ndo_get_stats = enic_get_stats,
+ .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_register = enic_vlan_rx_register,
.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,
@@ -2079,13 +2121,12 @@ static const struct net_device_ops enic_netdev_ops = {
.ndo_open = enic_open,
.ndo_stop = enic_stop,
.ndo_start_xmit = enic_hard_start_xmit,
- .ndo_get_stats = enic_get_stats,
+ .ndo_get_stats64 = enic_get_stats,
.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_register = enic_vlan_rx_register,
.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,
@@ -2112,6 +2153,14 @@ static int enic_dev_init(struct enic *enic)
unsigned int i;
int err;
+ /* Get interrupt coalesce timer info */
+ err = enic_dev_intr_coal_timer_info(enic);
+ if (err) {
+ dev_warn(dev, "Using default conversion factor for "
+ "interrupt coalesce timer\n");
+ vnic_dev_intr_coal_timer_info_default(enic->vdev);
+ }
+
/* Get vNIC configuration
*/
@@ -2345,6 +2394,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
enic->notify_timer.data = (unsigned long)enic;
INIT_WORK(&enic->reset, enic_reset);
+ INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
for (i = 0; i < enic->wq_count; i++)
spin_lock_init(&enic->wq_lock[i]);
@@ -2427,6 +2477,7 @@ static void __devexit enic_remove(struct pci_dev *pdev)
struct enic *enic = netdev_priv(netdev);
cancel_work_sync(&enic->reset);
+ cancel_work_sync(&enic->change_mtu_work);
unregister_netdev(netdev);
enic_dev_deinit(enic);
vnic_dev_close(enic->vdev);
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 6e5c6356e7df..4a35367de790 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -90,18 +90,30 @@ int enic_get_vnic_config(struct enic *enic)
max_t(u16, ENIC_MIN_MTU,
c->mtu));
- c->intr_timer_usec = min_t(u32,
- INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
- c->intr_timer_usec);
+ c->intr_timer_usec = min_t(u32, c->intr_timer_usec,
+ vnic_dev_get_intr_coal_timer_max(enic->vdev));
dev_info(enic_get_dev(enic),
"vNIC MAC addr %pM wq/rq %d/%d mtu %d\n",
enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu);
- dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d "
- "tso %d intr timer %d usec rss %d\n",
- ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM),
- ENIC_SETTING(enic, TSO),
- c->intr_timer_usec, ENIC_SETTING(enic, RSS));
+
+ dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
+ "tso/lro %s/%s rss %s intr mode %s type %s timer %d usec "
+ "loopback tag 0x%04x\n",
+ ENIC_SETTING(enic, TXCSUM) ? "yes" : "no",
+ ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
+ ENIC_SETTING(enic, TSO) ? "yes" : "no",
+ ENIC_SETTING(enic, LRO) ? "yes" : "no",
+ ENIC_SETTING(enic, RSS) ? "yes" : "no",
+ c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
+ c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
+ c->intr_mode == VENET_INTR_MODE_ANY ? "any" :
+ "unknown",
+ c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" :
+ c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" :
+ "unknown",
+ c->intr_timer_usec,
+ c->loop_tag);
return 0;
}
@@ -290,7 +302,7 @@ void enic_init_vnic_resources(struct enic *enic)
for (i = 0; i < enic->intr_count; i++) {
vnic_intr_init(&enic->intr[i],
- INTR_COALESCE_USEC_TO_HW(enic->config.intr_timer_usec),
+ enic->config.intr_timer_usec,
enic->config.intr_timer_type,
mask_on_assertion);
}
diff --git a/drivers/net/enic/vnic_cq.c b/drivers/net/enic/vnic_cq.c
index b86d6ef8dad3..0daa1c7073cb 100644
--- a/drivers/net/enic/vnic_cq.c
+++ b/drivers/net/enic/vnic_cq.c
@@ -74,6 +74,8 @@ void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
iowrite32(cq_message_enable, &cq->ctrl->cq_message_enable);
iowrite32(interrupt_offset, &cq->ctrl->interrupt_offset);
writeq(cq_message_addr, &cq->ctrl->cq_message_addr);
+
+ cq->interrupt_offset = interrupt_offset;
}
void vnic_cq_clean(struct vnic_cq *cq)
diff --git a/drivers/net/enic/vnic_cq.h b/drivers/net/enic/vnic_cq.h
index 552d3daf2508..579315cbe803 100644
--- a/drivers/net/enic/vnic_cq.h
+++ b/drivers/net/enic/vnic_cq.h
@@ -57,6 +57,7 @@ struct vnic_cq {
struct vnic_dev_ring ring;
unsigned int to_clean;
unsigned int last_color;
+ unsigned int interrupt_offset;
};
static inline unsigned int vnic_cq_service(struct vnic_cq *cq,
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 68f24ae860ae..8c4c8cf486f6 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -40,6 +40,12 @@ struct vnic_res {
unsigned int count;
};
+struct vnic_intr_coal_timer_info {
+ u32 mul;
+ u32 div;
+ u32 max_usec;
+};
+
struct vnic_dev {
void *priv;
struct pci_dev *pdev;
@@ -58,6 +64,7 @@ struct vnic_dev {
enum vnic_proxy_type proxy;
u32 proxy_index;
u64 args[VNIC_DEVCMD_NARGS];
+ struct vnic_intr_coal_timer_info intr_coal_timer_info;
};
#define VNIC_MAX_RES_HDR_SIZE \
@@ -794,6 +801,42 @@ int vnic_dev_deinit(struct vnic_dev *vdev)
return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait);
}
+void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev)
+{
+ /* Default: hardware intr coal timer is in units of 1.5 usecs */
+ vdev->intr_coal_timer_info.mul = 2;
+ vdev->intr_coal_timer_info.div = 3;
+ vdev->intr_coal_timer_info.max_usec =
+ vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff);
+}
+
+int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev)
+{
+ int wait = 1000;
+ int err;
+
+ memset(vdev->args, 0, sizeof(vdev->args));
+
+ err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait);
+
+ /* Use defaults when firmware doesn't support the devcmd at all or
+ * supports it for only specific hardware
+ */
+ if ((err == ERR_ECMDUNKNOWN) ||
+ (!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) {
+ pr_warning("Using default conversion factor for "
+ "interrupt coalesce timer\n");
+ vnic_dev_intr_coal_timer_info_default(vdev);
+ return 0;
+ }
+
+ vdev->intr_coal_timer_info.mul = (u32) vdev->args[0];
+ vdev->intr_coal_timer_info.div = (u32) vdev->args[1];
+ vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2];
+
+ return err;
+}
+
int vnic_dev_link_status(struct vnic_dev *vdev)
{
if (!vnic_dev_notify_ready(vdev))
@@ -838,6 +881,23 @@ enum vnic_dev_intr_mode vnic_dev_get_intr_mode(
return vdev->intr_mode;
}
+u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec)
+{
+ return (usec * vdev->intr_coal_timer_info.mul) /
+ vdev->intr_coal_timer_info.div;
+}
+
+u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles)
+{
+ return (hw_cycles * vdev->intr_coal_timer_info.div) /
+ vdev->intr_coal_timer_info.mul;
+}
+
+u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev)
+{
+ return vdev->intr_coal_timer_info.max_usec;
+}
+
void vnic_dev_unregister(struct vnic_dev *vdev)
{
if (vdev) {
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index cf482a2c9dd9..852b698fbe7d 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -109,11 +109,16 @@ int vnic_dev_open(struct vnic_dev *vdev, int arg);
int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
int vnic_dev_init(struct vnic_dev *vdev, int arg);
int vnic_dev_deinit(struct vnic_dev *vdev);
+void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev);
+int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev);
int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
enum vnic_dev_intr_mode intr_mode);
enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev);
+u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec);
+u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles);
+u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev);
void vnic_dev_unregister(struct vnic_dev *vdev);
int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
u8 ig_vlan_rewrite_mode);
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index c5569bfb47ac..8025e8808d61 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -318,6 +318,25 @@ enum vnic_devcmd_cmd {
* ERR_EINPROGRESS - command in a0 is still in progress
*/
CMD_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 49),
+
+ /*
+ * Returns interrupt coalescing timer conversion factors.
+ * After calling this devcmd, ENIC driver can convert
+ * interrupt coalescing timer in usec into CPU cycles as follows:
+ *
+ * intr_timer_cycles = intr_timer_usec * multiplier / divisor
+ *
+ * Interrupt coalescing timer in usecs can be obtained from
+ * CPU cycles as follows:
+ *
+ * intr_timer_usec = intr_timer_cycles * divisor / multiplier
+ *
+ * in: none
+ * out: (u32)a0 = multiplier
+ * (u32)a1 = divisor
+ * (u32)a2 = maximum timer value in usec
+ */
+ CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
};
/* CMD_ENABLE2 flags */
diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h
index e8740e3704e4..609542848e02 100644
--- a/drivers/net/enic/vnic_enet.h
+++ b/drivers/net/enic/vnic_enet.h
@@ -20,10 +20,6 @@
#ifndef _VNIC_ENIC_H_
#define _VNIC_ENIC_H_
-/* Hardware intr coalesce timer is in units of 1.5us */
-#define INTR_COALESCE_USEC_TO_HW(usec) ((usec) * 2/3)
-#define INTR_COALESCE_HW_TO_USEC(usec) ((usec) * 3/2)
-
/* Device-specific region: enet configuration */
struct vnic_enet_config {
u32 flags;
@@ -51,4 +47,11 @@ struct vnic_enet_config {
#define VENETF_RSSHASH_TCPIPV6_EX 0x400 /* Hash on TCP + IPv6 ext. fields */
#define VENETF_LOOP 0x800 /* Loopback enabled */
+#define VENET_INTR_TYPE_MIN 0 /* Timer specs min interrupt spacing */
+#define VENET_INTR_TYPE_IDLE 1 /* Timer specs idle time before irq */
+
+#define VENET_INTR_MODE_ANY 0 /* Try MSI-X, then MSI, then INTx */
+#define VENET_INTR_MODE_MSI 1 /* Try MSI then INTx */
+#define VENET_INTR_MODE_INTX 2 /* Try INTx only */
+
#endif /* _VNIC_ENIC_H_ */
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c
index 3873771d75cc..0ca107f7bc8c 100644
--- a/drivers/net/enic/vnic_intr.c
+++ b/drivers/net/enic/vnic_intr.c
@@ -46,7 +46,7 @@ int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
return 0;
}
-void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
unsigned int coalescing_type, unsigned int mask_on_assertion)
{
vnic_intr_coalescing_timer_set(intr, coalescing_timer);
@@ -56,9 +56,10 @@ void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
}
void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
- unsigned int coalescing_timer)
+ u32 coalescing_timer)
{
- iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer);
+ iowrite32(vnic_dev_intr_coal_timer_usec_to_hw(intr->vdev,
+ coalescing_timer), &intr->ctrl->coalescing_timer);
}
void vnic_intr_clean(struct vnic_intr *intr)
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h
index 09dc0b73ff46..2b1636392294 100644
--- a/drivers/net/enic/vnic_intr.h
+++ b/drivers/net/enic/vnic_intr.h
@@ -24,8 +24,6 @@
#include "vnic_dev.h"
-#define VNIC_INTR_TIMER_MAX 0xffff
-
#define VNIC_INTR_TIMER_TYPE_ABS 0
#define VNIC_INTR_TIMER_TYPE_QUIET 1
@@ -104,10 +102,10 @@ static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba)
void vnic_intr_free(struct vnic_intr *intr);
int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
unsigned int index);
-void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
unsigned int coalescing_type, unsigned int mask_on_assertion);
void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
- unsigned int coalescing_timer);
+ u32 coalescing_timer);
void vnic_intr_clean(struct vnic_intr *intr);
#endif /* _VNIC_INTR_H_ */
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index c353bf3113cc..814c187d5f95 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -391,13 +391,13 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_iounmap;
- ep->tx_ring = (struct epic_tx_desc *)ring_space;
+ ep->tx_ring = ring_space;
ep->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- ep->rx_ring = (struct epic_rx_desc *)ring_space;
+ ep->rx_ring = ring_space;
ep->rx_ring_dma = ring_dma;
if (dev->mem_start) {
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 0ba5e7b90584..7a09575ecff0 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -54,6 +54,7 @@ static const char version[] =
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a83dd312c3ac..8abbe1d82826 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -11,8 +11,10 @@
* Written by Thierry Reding <thierry.reding@avionic-design.de>
*/
+#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
#include <linux/crc32.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mii.h>
#include <linux/phy.h>
@@ -874,6 +876,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
spin_unlock_irq(&priv->lock);
+ skb_tx_timestamp(skb);
out:
dev_kfree_skb(skb);
return NETDEV_TX_OK;
@@ -965,7 +968,7 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
priv = netdev_priv(netdev);
priv->netdev = netdev;
priv->dma_alloc = 0;
- priv->io_region_size = mmio->end - mmio->start + 1;
+ priv->io_region_size = resource_size(mmio);
priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
resource_size(mmio));
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index b5f6173130f4..05a5f71451a7 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -1008,15 +1008,13 @@ static int ewrk3_rx(struct net_device *dev)
}
}
p = skb->data; /* Look at the dest addr */
- if (p[0] & 0x01) { /* Multicast/Broadcast */
- if ((*(s16 *) & p[0] == -1) && (*(s16 *) & p[2] == -1) && (*(s16 *) & p[4] == -1)) {
+ if (is_multicast_ether_addr(p)) {
+ if (is_broadcast_ether_addr(p)) {
lp->pktStats.broadcast++;
} else {
lp->pktStats.multicast++;
}
- } else if ((*(s16 *) & p[0] == *(s16 *) & dev->dev_addr[0]) &&
- (*(s16 *) & p[2] == *(s16 *) & dev->dev_addr[2]) &&
- (*(s16 *) & p[4] == *(s16 *) & dev->dev_addr[4])) {
+ } else if (compare_ether_addr(p, dev->dev_addr) == 0) {
lp->pktStats.unicast++;
}
lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */
@@ -1171,7 +1169,7 @@ static void SetMulticastFilter(struct net_device *dev)
struct netdev_hw_addr *ha;
u_long iobase = dev->base_addr;
int i;
- char *addrs, bit, byte;
+ char bit, byte;
short __iomem *p = lp->mctbl;
u16 hashcode;
u32 crc;
@@ -1213,25 +1211,22 @@ static void SetMulticastFilter(struct net_device *dev)
/* Update table */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
- if ((*addrs & 0x01) == 1) { /* multicast address? */
- crc = ether_crc_le(ETH_ALEN, addrs);
- hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */
+ crc = ether_crc_le(ETH_ALEN, ha->addr);
+ hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */
- byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
- bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
+ byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
+ bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
- if (lp->shmem_length == IO_ONLY) {
- u_char tmp;
+ if (lp->shmem_length == IO_ONLY) {
+ u_char tmp;
- outw(PAGE0_HTE + byte, EWRK3_PIR1);
- tmp = inb(EWRK3_DATA);
- tmp |= bit;
- outw(PAGE0_HTE + byte, EWRK3_PIR1);
- outb(tmp, EWRK3_DATA);
- } else {
- writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
- }
+ outw(PAGE0_HTE + byte, EWRK3_PIR1);
+ tmp = inb(EWRK3_DATA);
+ tmp |= bit;
+ outw(PAGE0_HTE + byte, EWRK3_PIR1);
+ outb(tmp, EWRK3_DATA);
+ } else {
+ writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
}
}
}
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index dd54abe2f710..fa8677c32384 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -566,7 +566,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
err = -ENOMEM;
goto err_out_free_dev;
}
- np->rx_ring = (struct fealnx_desc *)ring_space;
+ np->rx_ring = ring_space;
np->rx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
@@ -574,7 +574,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
err = -ENOMEM;
goto err_out_free_rx;
}
- np->tx_ring = (struct fealnx_desc *)ring_space;
+ np->tx_ring = ring_space;
np->tx_ring_dma = ring_dma;
/* find the connected MII xcvrs */
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 885d8baff7d5..5b631fe74738 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -324,6 +324,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
fep->cur_tx = bdp;
+ skb_tx_timestamp(skb);
+
spin_unlock_irqrestore(&fep->hw_lock, flags);
return NETDEV_TX_OK;
@@ -650,7 +652,8 @@ fec_enet_rx(struct net_device *ndev)
skb_put(skb, pkt_len - 4); /* Make room */
skb_copy_to_linear_data(skb, data, pkt_len - 4);
skb->protocol = eth_type_trans(skb, ndev);
- netif_rx(skb);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb);
}
bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
@@ -1224,10 +1227,6 @@ static void set_multicast_list(struct net_device *ndev)
writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
netdev_for_each_mc_addr(ha, ndev) {
- /* Only support group multicast for now */
- if (!(ha->addr[0] & 1))
- continue;
-
/* calculate crc32 value of mac address */
crc = 0xffffffff;
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 9f81b1ac130e..cb4416e591f1 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -14,6 +14,7 @@
*
*/
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -22,6 +23,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/crc32.h>
#include <linux/hardirq.h>
#include <linux/delay.h>
@@ -335,6 +337,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, skb->len,
DMA_TO_DEVICE);
+ skb_tx_timestamp(skb);
bcom_submit_next_buffer(priv->tx_dmatsk, skb);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -434,7 +437,8 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
length = status & BCOM_FEC_RX_BD_LEN_MASK;
skb_put(rskb, length - 4); /* length without CRC32 */
rskb->protocol = eth_type_trans(rskb, dev);
- netif_rx(rskb);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(rskb);
spin_lock(&priv->lock);
}
@@ -867,10 +871,11 @@ static int __devinit mpc52xx_fec_probe(struct platform_device *op)
"Error while parsing device node resource\n" );
goto err_netdev;
}
- if ((mem.end - mem.start + 1) < sizeof(struct mpc52xx_fec)) {
+ if (resource_size(&mem) < sizeof(struct mpc52xx_fec)) {
printk(KERN_ERR DRIVER_NAME
- " - invalid resource size (%lx < %x), check mpc52xx_devices.c\n",
- (unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec));
+ " - invalid resource size (%lx < %x), check mpc52xx_devices.c\n",
+ (unsigned long)resource_size(&mem),
+ sizeof(struct mpc52xx_fec));
rv = -EINVAL;
goto err_netdev;
}
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 537b6957bb79..e64cd9ceac3f 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -820,9 +820,6 @@ struct fe_priv {
struct nv_skb_map *tx_end_flip;
int tx_stop;
- /* vlan fields */
- struct vlan_group *vlangrp;
-
/* msi/msi-x fields */
u32 msi_flags;
struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS];
@@ -2766,17 +2763,13 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
skb->protocol = eth_type_trans(skb, dev);
prefetch(skb->data);
- if (likely(!np->vlangrp)) {
- napi_gro_receive(&np->napi, skb);
- } else {
- vlanflags = le32_to_cpu(np->get_rx.ex->buflow);
- if (vlanflags & NV_RX3_VLAN_TAG_PRESENT) {
- vlan_gro_receive(&np->napi, np->vlangrp,
- vlanflags & NV_RX3_VLAN_TAG_MASK, skb);
- } else {
- napi_gro_receive(&np->napi, skb);
- }
+ vlanflags = le32_to_cpu(np->get_rx.ex->buflow);
+ if (vlanflags & NV_RX3_VLAN_TAG_PRESENT) {
+ u16 vid = vlanflags & NV_RX3_VLAN_TAG_MASK;
+
+ __vlan_hwaccel_put_tag(skb, vid);
}
+ napi_gro_receive(&np->napi, skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
@@ -4484,6 +4477,27 @@ static u32 nv_fix_features(struct net_device *dev, u32 features)
return features;
}
+static void nv_vlan_mode(struct net_device *dev, u32 features)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ spin_lock_irq(&np->lock);
+
+ if (features & NETIF_F_HW_VLAN_RX)
+ np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP;
+ else
+ np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP;
+
+ if (features & NETIF_F_HW_VLAN_TX)
+ np->txrxctl_bits |= NVREG_TXRXCTL_VLANINS;
+ else
+ np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS;
+
+ writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+
+ spin_unlock_irq(&np->lock);
+}
+
static int nv_set_features(struct net_device *dev, u32 features)
{
struct fe_priv *np = netdev_priv(dev);
@@ -4504,6 +4518,9 @@ static int nv_set_features(struct net_device *dev, u32 features)
spin_unlock_irq(&np->lock);
}
+ if (changed & (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX))
+ nv_vlan_mode(dev, features);
+
return 0;
}
@@ -4879,29 +4896,6 @@ static const struct ethtool_ops ops = {
.self_test = nv_self_test,
};
-static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
- struct fe_priv *np = get_nvpriv(dev);
-
- spin_lock_irq(&np->lock);
-
- /* save vlan group */
- np->vlangrp = grp;
-
- if (grp) {
- /* enable vlan on MAC */
- np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP | NVREG_TXRXCTL_VLANINS;
- } else {
- /* disable vlan on MAC */
- np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP;
- np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS;
- }
-
- writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
-
- spin_unlock_irq(&np->lock);
-}
-
/* The mgmt unit and driver use a semaphore to access the phy during init */
static int nv_mgmt_acquire_sema(struct net_device *dev)
{
@@ -5208,7 +5202,6 @@ static const struct net_device_ops nv_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = nv_set_mac_address,
.ndo_set_multicast_list = nv_set_multicast,
- .ndo_vlan_rx_register = nv_vlan_rx_register,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = nv_poll_controller,
#endif
@@ -5226,7 +5219,6 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = nv_set_mac_address,
.ndo_set_multicast_list = nv_set_multicast,
- .ndo_vlan_rx_register = nv_vlan_rx_register,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = nv_poll_controller,
#endif
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 21abb5c01a56..329ef231a096 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -697,6 +697,8 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
sc |= BD_ENET_TX_PAD;
CBDS_SC(bdp, sc);
+ skb_tx_timestamp(skb);
+
(*fep->ops->tx_kickstart)(dev);
spin_unlock_irqrestore(&fep->tx_lock, flags);
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index ad2975440719..b09270b5d0a5 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -120,7 +120,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
if (ret)
return ret;
- if (res.end - res.start < 13)
+ if (resource_size(&res) <= 13)
return -ENODEV;
/* This should really encode the pin number as well, but all
@@ -139,7 +139,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
return -ENODEV;
mdc_pin = *data;
- bitbang->dir = ioremap(res.start, res.end - res.start + 1);
+ bitbang->dir = ioremap(res.start, resource_size(&res));
if (!bitbang->dir)
return -ENOMEM;
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 6a2e150e75bb..e0e9d6c35d83 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -136,7 +136,7 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
- fec->fecp = ioremap(res.start, res.end - res.start + 1);
+ fec->fecp = ioremap(res.start, resource_size(&res));
if (!fec->fecp)
goto out_fec;
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
new file mode 100644
index 000000000000..54709af917e9
--- /dev/null
+++ b/drivers/net/ftgmac100.c
@@ -0,0 +1,1365 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <net/ip.h>
+
+#include "ftgmac100.h"
+
+#define DRV_NAME "ftgmac100"
+#define DRV_VERSION "0.7"
+
+#define RX_QUEUE_ENTRIES 256 /* must be power of 2 */
+#define TX_QUEUE_ENTRIES 512 /* must be power of 2 */
+
+#define MAX_PKT_SIZE 1518
+#define RX_BUF_SIZE PAGE_SIZE /* must be smaller than 0x3fff */
+
+/******************************************************************************
+ * private data
+ *****************************************************************************/
+struct ftgmac100_descs {
+ struct ftgmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
+ struct ftgmac100_txdes txdes[TX_QUEUE_ENTRIES];
+};
+
+struct ftgmac100 {
+ struct resource *res;
+ void __iomem *base;
+ int irq;
+
+ struct ftgmac100_descs *descs;
+ dma_addr_t descs_dma_addr;
+
+ unsigned int rx_pointer;
+ unsigned int tx_clean_pointer;
+ unsigned int tx_pointer;
+ unsigned int tx_pending;
+
+ spinlock_t tx_lock;
+
+ struct net_device *netdev;
+ struct device *dev;
+ struct napi_struct napi;
+
+ struct mii_bus *mii_bus;
+ int phy_irq[PHY_MAX_ADDR];
+ struct phy_device *phydev;
+ int old_speed;
+};
+
+static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
+ struct ftgmac100_rxdes *rxdes, gfp_t gfp);
+
+/******************************************************************************
+ * internal functions (hardware register access)
+ *****************************************************************************/
+#define INT_MASK_ALL_ENABLED (FTGMAC100_INT_RPKT_LOST | \
+ FTGMAC100_INT_XPKT_ETH | \
+ FTGMAC100_INT_XPKT_LOST | \
+ FTGMAC100_INT_AHB_ERR | \
+ FTGMAC100_INT_PHYSTS_CHG | \
+ FTGMAC100_INT_RPKT_BUF | \
+ FTGMAC100_INT_NO_RXBUF)
+
+static void ftgmac100_set_rx_ring_base(struct ftgmac100 *priv, dma_addr_t addr)
+{
+ iowrite32(addr, priv->base + FTGMAC100_OFFSET_RXR_BADR);
+}
+
+static void ftgmac100_set_rx_buffer_size(struct ftgmac100 *priv,
+ unsigned int size)
+{
+ size = FTGMAC100_RBSR_SIZE(size);
+ iowrite32(size, priv->base + FTGMAC100_OFFSET_RBSR);
+}
+
+static void ftgmac100_set_normal_prio_tx_ring_base(struct ftgmac100 *priv,
+ dma_addr_t addr)
+{
+ iowrite32(addr, priv->base + FTGMAC100_OFFSET_NPTXR_BADR);
+}
+
+static void ftgmac100_txdma_normal_prio_start_polling(struct ftgmac100 *priv)
+{
+ iowrite32(1, priv->base + FTGMAC100_OFFSET_NPTXPD);
+}
+
+static int ftgmac100_reset_hw(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ int i;
+
+ /* NOTE: reset clears all registers */
+ iowrite32(FTGMAC100_MACCR_SW_RST, priv->base + FTGMAC100_OFFSET_MACCR);
+ for (i = 0; i < 5; i++) {
+ unsigned int maccr;
+
+ maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR);
+ if (!(maccr & FTGMAC100_MACCR_SW_RST))
+ return 0;
+
+ udelay(1000);
+ }
+
+ netdev_err(netdev, "software reset failed\n");
+ return -EIO;
+}
+
+static void ftgmac100_set_mac(struct ftgmac100 *priv, const unsigned char *mac)
+{
+ unsigned int maddr = mac[0] << 8 | mac[1];
+ unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+
+ iowrite32(maddr, priv->base + FTGMAC100_OFFSET_MAC_MADR);
+ iowrite32(laddr, priv->base + FTGMAC100_OFFSET_MAC_LADR);
+}
+
+static void ftgmac100_init_hw(struct ftgmac100 *priv)
+{
+ /* setup ring buffer base registers */
+ ftgmac100_set_rx_ring_base(priv,
+ priv->descs_dma_addr +
+ offsetof(struct ftgmac100_descs, rxdes));
+ ftgmac100_set_normal_prio_tx_ring_base(priv,
+ priv->descs_dma_addr +
+ offsetof(struct ftgmac100_descs, txdes));
+
+ ftgmac100_set_rx_buffer_size(priv, RX_BUF_SIZE);
+
+ iowrite32(FTGMAC100_APTC_RXPOLL_CNT(1), priv->base + FTGMAC100_OFFSET_APTC);
+
+ ftgmac100_set_mac(priv, priv->netdev->dev_addr);
+}
+
+#define MACCR_ENABLE_ALL (FTGMAC100_MACCR_TXDMA_EN | \
+ FTGMAC100_MACCR_RXDMA_EN | \
+ FTGMAC100_MACCR_TXMAC_EN | \
+ FTGMAC100_MACCR_RXMAC_EN | \
+ FTGMAC100_MACCR_FULLDUP | \
+ FTGMAC100_MACCR_CRC_APD | \
+ FTGMAC100_MACCR_RX_RUNT | \
+ FTGMAC100_MACCR_RX_BROADPKT)
+
+static void ftgmac100_start_hw(struct ftgmac100 *priv, int speed)
+{
+ int maccr = MACCR_ENABLE_ALL;
+
+ switch (speed) {
+ default:
+ case 10:
+ break;
+
+ case 100:
+ maccr |= FTGMAC100_MACCR_FAST_MODE;
+ break;
+
+ case 1000:
+ maccr |= FTGMAC100_MACCR_GIGA_MODE;
+ break;
+ }
+
+ iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR);
+}
+
+static void ftgmac100_stop_hw(struct ftgmac100 *priv)
+{
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_MACCR);
+}
+
+/******************************************************************************
+ * internal functions (receive descriptor)
+ *****************************************************************************/
+static bool ftgmac100_rxdes_first_segment(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FRS);
+}
+
+static bool ftgmac100_rxdes_last_segment(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_LRS);
+}
+
+static bool ftgmac100_rxdes_packet_ready(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RXPKT_RDY);
+}
+
+static void ftgmac100_rxdes_set_dma_own(struct ftgmac100_rxdes *rxdes)
+{
+ /* clear status bits */
+ rxdes->rxdes0 &= cpu_to_le32(FTGMAC100_RXDES0_EDORR);
+}
+
+static bool ftgmac100_rxdes_rx_error(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ERR);
+}
+
+static bool ftgmac100_rxdes_crc_error(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_CRC_ERR);
+}
+
+static bool ftgmac100_rxdes_frame_too_long(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FTL);
+}
+
+static bool ftgmac100_rxdes_runt(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RUNT);
+}
+
+static bool ftgmac100_rxdes_odd_nibble(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ODD_NB);
+}
+
+static unsigned int ftgmac100_rxdes_data_length(struct ftgmac100_rxdes *rxdes)
+{
+ return le32_to_cpu(rxdes->rxdes0) & FTGMAC100_RXDES0_VDBC;
+}
+
+static bool ftgmac100_rxdes_multicast(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_MULTICAST);
+}
+
+static void ftgmac100_rxdes_set_end_of_ring(struct ftgmac100_rxdes *rxdes)
+{
+ rxdes->rxdes0 |= cpu_to_le32(FTGMAC100_RXDES0_EDORR);
+}
+
+static void ftgmac100_rxdes_set_dma_addr(struct ftgmac100_rxdes *rxdes,
+ dma_addr_t addr)
+{
+ rxdes->rxdes3 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftgmac100_rxdes_get_dma_addr(struct ftgmac100_rxdes *rxdes)
+{
+ return le32_to_cpu(rxdes->rxdes3);
+}
+
+static bool ftgmac100_rxdes_is_tcp(struct ftgmac100_rxdes *rxdes)
+{
+ return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
+ cpu_to_le32(FTGMAC100_RXDES1_PROT_TCPIP);
+}
+
+static bool ftgmac100_rxdes_is_udp(struct ftgmac100_rxdes *rxdes)
+{
+ return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
+ cpu_to_le32(FTGMAC100_RXDES1_PROT_UDPIP);
+}
+
+static bool ftgmac100_rxdes_tcpcs_err(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR);
+}
+
+static bool ftgmac100_rxdes_udpcs_err(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_UDP_CHKSUM_ERR);
+}
+
+static bool ftgmac100_rxdes_ipcs_err(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_IP_CHKSUM_ERR);
+}
+
+/*
+ * rxdes2 is not used by hardware. We use it to keep track of page.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftgmac100_rxdes_set_page(struct ftgmac100_rxdes *rxdes, struct page *page)
+{
+ rxdes->rxdes2 = (unsigned int)page;
+}
+
+static struct page *ftgmac100_rxdes_get_page(struct ftgmac100_rxdes *rxdes)
+{
+ return (struct page *)rxdes->rxdes2;
+}
+
+/******************************************************************************
+ * internal functions (receive)
+ *****************************************************************************/
+static int ftgmac100_next_rx_pointer(int pointer)
+{
+ return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
+}
+
+static void ftgmac100_rx_pointer_advance(struct ftgmac100 *priv)
+{
+ priv->rx_pointer = ftgmac100_next_rx_pointer(priv->rx_pointer);
+}
+
+static struct ftgmac100_rxdes *ftgmac100_current_rxdes(struct ftgmac100 *priv)
+{
+ return &priv->descs->rxdes[priv->rx_pointer];
+}
+
+static struct ftgmac100_rxdes *
+ftgmac100_rx_locate_first_segment(struct ftgmac100 *priv)
+{
+ struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
+
+ while (ftgmac100_rxdes_packet_ready(rxdes)) {
+ if (ftgmac100_rxdes_first_segment(rxdes))
+ return rxdes;
+
+ ftgmac100_rxdes_set_dma_own(rxdes);
+ ftgmac100_rx_pointer_advance(priv);
+ rxdes = ftgmac100_current_rxdes(priv);
+ }
+
+ return NULL;
+}
+
+static bool ftgmac100_rx_packet_error(struct ftgmac100 *priv,
+ struct ftgmac100_rxdes *rxdes)
+{
+ struct net_device *netdev = priv->netdev;
+ bool error = false;
+
+ if (unlikely(ftgmac100_rxdes_rx_error(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx err\n");
+
+ netdev->stats.rx_errors++;
+ error = true;
+ }
+
+ if (unlikely(ftgmac100_rxdes_crc_error(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx crc err\n");
+
+ netdev->stats.rx_crc_errors++;
+ error = true;
+ } else if (unlikely(ftgmac100_rxdes_ipcs_err(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx IP checksum err\n");
+
+ error = true;
+ }
+
+ if (unlikely(ftgmac100_rxdes_frame_too_long(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx frame too long\n");
+
+ netdev->stats.rx_length_errors++;
+ error = true;
+ } else if (unlikely(ftgmac100_rxdes_runt(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx runt\n");
+
+ netdev->stats.rx_length_errors++;
+ error = true;
+ } else if (unlikely(ftgmac100_rxdes_odd_nibble(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx odd nibble\n");
+
+ netdev->stats.rx_length_errors++;
+ error = true;
+ }
+
+ return error;
+}
+
+static void ftgmac100_rx_drop_packet(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
+ bool done = false;
+
+ if (net_ratelimit())
+ netdev_dbg(netdev, "drop packet %p\n", rxdes);
+
+ do {
+ if (ftgmac100_rxdes_last_segment(rxdes))
+ done = true;
+
+ ftgmac100_rxdes_set_dma_own(rxdes);
+ ftgmac100_rx_pointer_advance(priv);
+ rxdes = ftgmac100_current_rxdes(priv);
+ } while (!done && ftgmac100_rxdes_packet_ready(rxdes));
+
+ netdev->stats.rx_dropped++;
+}
+
+static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_rxdes *rxdes;
+ struct sk_buff *skb;
+ bool done = false;
+
+ rxdes = ftgmac100_rx_locate_first_segment(priv);
+ if (!rxdes)
+ return false;
+
+ if (unlikely(ftgmac100_rx_packet_error(priv, rxdes))) {
+ ftgmac100_rx_drop_packet(priv);
+ return true;
+ }
+
+ /* start processing */
+ skb = netdev_alloc_skb_ip_align(netdev, 128);
+ if (unlikely(!skb)) {
+ if (net_ratelimit())
+ netdev_err(netdev, "rx skb alloc failed\n");
+
+ ftgmac100_rx_drop_packet(priv);
+ return true;
+ }
+
+ if (unlikely(ftgmac100_rxdes_multicast(rxdes)))
+ netdev->stats.multicast++;
+
+ /*
+ * It seems that HW does checksum incorrectly with fragmented packets,
+ * so we are conservative here - if HW checksum error, let software do
+ * the checksum again.
+ */
+ if ((ftgmac100_rxdes_is_tcp(rxdes) && !ftgmac100_rxdes_tcpcs_err(rxdes)) ||
+ (ftgmac100_rxdes_is_udp(rxdes) && !ftgmac100_rxdes_udpcs_err(rxdes)))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ do {
+ dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
+ struct page *page = ftgmac100_rxdes_get_page(rxdes);
+ unsigned int size;
+
+ dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+
+ size = ftgmac100_rxdes_data_length(rxdes);
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 0, size);
+
+ skb->len += size;
+ skb->data_len += size;
+ skb->truesize += size;
+
+ if (ftgmac100_rxdes_last_segment(rxdes))
+ done = true;
+
+ ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
+
+ ftgmac100_rx_pointer_advance(priv);
+ rxdes = ftgmac100_current_rxdes(priv);
+ } while (!done);
+
+ __pskb_pull_tail(skb, min(skb->len, 64U));
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ netdev->stats.rx_packets++;
+ netdev->stats.rx_bytes += skb->len;
+
+ /* push packet to protocol stack */
+ napi_gro_receive(&priv->napi, skb);
+
+ (*processed)++;
+ return true;
+}
+
+/******************************************************************************
+ * internal functions (transmit descriptor)
+ *****************************************************************************/
+static void ftgmac100_txdes_reset(struct ftgmac100_txdes *txdes)
+{
+ /* clear all except end of ring bit */
+ txdes->txdes0 &= cpu_to_le32(FTGMAC100_TXDES0_EDOTR);
+ txdes->txdes1 = 0;
+ txdes->txdes2 = 0;
+ txdes->txdes3 = 0;
+}
+
+static bool ftgmac100_txdes_owned_by_dma(struct ftgmac100_txdes *txdes)
+{
+ return txdes->txdes0 & cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftgmac100_txdes_set_dma_own(struct ftgmac100_txdes *txdes)
+{
+ /*
+ * Make sure dma own bit will not be set before any other
+ * descriptor fields.
+ */
+ wmb();
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftgmac100_txdes_set_end_of_ring(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_EDOTR);
+}
+
+static void ftgmac100_txdes_set_first_segment(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_FTS);
+}
+
+static void ftgmac100_txdes_set_last_segment(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_LTS);
+}
+
+static void ftgmac100_txdes_set_buffer_size(struct ftgmac100_txdes *txdes,
+ unsigned int len)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXBUF_SIZE(len));
+}
+
+static void ftgmac100_txdes_set_txint(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TXIC);
+}
+
+static void ftgmac100_txdes_set_tcpcs(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TCP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_udpcs(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_UDP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_ipcs(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_IP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_dma_addr(struct ftgmac100_txdes *txdes,
+ dma_addr_t addr)
+{
+ txdes->txdes3 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftgmac100_txdes_get_dma_addr(struct ftgmac100_txdes *txdes)
+{
+ return le32_to_cpu(txdes->txdes3);
+}
+
+/*
+ * txdes2 is not used by hardware. We use it to keep track of socket buffer.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftgmac100_txdes_set_skb(struct ftgmac100_txdes *txdes,
+ struct sk_buff *skb)
+{
+ txdes->txdes2 = (unsigned int)skb;
+}
+
+static struct sk_buff *ftgmac100_txdes_get_skb(struct ftgmac100_txdes *txdes)
+{
+ return (struct sk_buff *)txdes->txdes2;
+}
+
+/******************************************************************************
+ * internal functions (transmit)
+ *****************************************************************************/
+static int ftgmac100_next_tx_pointer(int pointer)
+{
+ return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
+}
+
+static void ftgmac100_tx_pointer_advance(struct ftgmac100 *priv)
+{
+ priv->tx_pointer = ftgmac100_next_tx_pointer(priv->tx_pointer);
+}
+
+static void ftgmac100_tx_clean_pointer_advance(struct ftgmac100 *priv)
+{
+ priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv->tx_clean_pointer);
+}
+
+static struct ftgmac100_txdes *ftgmac100_current_txdes(struct ftgmac100 *priv)
+{
+ return &priv->descs->txdes[priv->tx_pointer];
+}
+
+static struct ftgmac100_txdes *
+ftgmac100_current_clean_txdes(struct ftgmac100 *priv)
+{
+ return &priv->descs->txdes[priv->tx_clean_pointer];
+}
+
+static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_txdes *txdes;
+ struct sk_buff *skb;
+ dma_addr_t map;
+
+ if (priv->tx_pending == 0)
+ return false;
+
+ txdes = ftgmac100_current_clean_txdes(priv);
+
+ if (ftgmac100_txdes_owned_by_dma(txdes))
+ return false;
+
+ skb = ftgmac100_txdes_get_skb(txdes);
+ map = ftgmac100_txdes_get_dma_addr(txdes);
+
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
+
+ dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+
+ dev_kfree_skb(skb);
+
+ ftgmac100_txdes_reset(txdes);
+
+ ftgmac100_tx_clean_pointer_advance(priv);
+
+ spin_lock(&priv->tx_lock);
+ priv->tx_pending--;
+ spin_unlock(&priv->tx_lock);
+ netif_wake_queue(netdev);
+
+ return true;
+}
+
+static void ftgmac100_tx_complete(struct ftgmac100 *priv)
+{
+ while (ftgmac100_tx_complete_packet(priv))
+ ;
+}
+
+static int ftgmac100_xmit(struct ftgmac100 *priv, struct sk_buff *skb,
+ dma_addr_t map)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_txdes *txdes;
+ unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+
+ txdes = ftgmac100_current_txdes(priv);
+ ftgmac100_tx_pointer_advance(priv);
+
+ /* setup TX descriptor */
+ ftgmac100_txdes_set_skb(txdes, skb);
+ ftgmac100_txdes_set_dma_addr(txdes, map);
+ ftgmac100_txdes_set_buffer_size(txdes, len);
+
+ ftgmac100_txdes_set_first_segment(txdes);
+ ftgmac100_txdes_set_last_segment(txdes);
+ ftgmac100_txdes_set_txint(txdes);
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ __be16 protocol = skb->protocol;
+
+ if (protocol == cpu_to_be16(ETH_P_IP)) {
+ u8 ip_proto = ip_hdr(skb)->protocol;
+
+ ftgmac100_txdes_set_ipcs(txdes);
+ if (ip_proto == IPPROTO_TCP)
+ ftgmac100_txdes_set_tcpcs(txdes);
+ else if (ip_proto == IPPROTO_UDP)
+ ftgmac100_txdes_set_udpcs(txdes);
+ }
+ }
+
+ spin_lock(&priv->tx_lock);
+ priv->tx_pending++;
+ if (priv->tx_pending == TX_QUEUE_ENTRIES)
+ netif_stop_queue(netdev);
+
+ /* start transmit */
+ ftgmac100_txdes_set_dma_own(txdes);
+ spin_unlock(&priv->tx_lock);
+
+ ftgmac100_txdma_normal_prio_start_polling(priv);
+
+ return NETDEV_TX_OK;
+}
+
+/******************************************************************************
+ * internal functions (buffer)
+ *****************************************************************************/
+static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
+ struct ftgmac100_rxdes *rxdes, gfp_t gfp)
+{
+ struct net_device *netdev = priv->netdev;
+ struct page *page;
+ dma_addr_t map;
+
+ page = alloc_page(gfp);
+ if (!page) {
+ if (net_ratelimit())
+ netdev_err(netdev, "failed to allocate rx page\n");
+ return -ENOMEM;
+ }
+
+ map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, map))) {
+ if (net_ratelimit())
+ netdev_err(netdev, "failed to map rx page\n");
+ __free_page(page);
+ return -ENOMEM;
+ }
+
+ ftgmac100_rxdes_set_page(rxdes, page);
+ ftgmac100_rxdes_set_dma_addr(rxdes, map);
+ ftgmac100_rxdes_set_dma_own(rxdes);
+ return 0;
+}
+
+static void ftgmac100_free_buffers(struct ftgmac100 *priv)
+{
+ int i;
+
+ for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+ struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+ struct page *page = ftgmac100_rxdes_get_page(rxdes);
+ dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
+
+ if (!page)
+ continue;
+
+ dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+ __free_page(page);
+ }
+
+ for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
+ struct ftgmac100_txdes *txdes = &priv->descs->txdes[i];
+ struct sk_buff *skb = ftgmac100_txdes_get_skb(txdes);
+ dma_addr_t map = ftgmac100_txdes_get_dma_addr(txdes);
+
+ if (!skb)
+ continue;
+
+ dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+ dev_kfree_skb(skb);
+ }
+
+ dma_free_coherent(priv->dev, sizeof(struct ftgmac100_descs),
+ priv->descs, priv->descs_dma_addr);
+}
+
+static int ftgmac100_alloc_buffers(struct ftgmac100 *priv)
+{
+ int i;
+
+ priv->descs = dma_alloc_coherent(priv->dev,
+ sizeof(struct ftgmac100_descs),
+ &priv->descs_dma_addr, GFP_KERNEL);
+ if (!priv->descs)
+ return -ENOMEM;
+
+ memset(priv->descs, 0, sizeof(struct ftgmac100_descs));
+
+ /* initialize RX ring */
+ ftgmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
+
+ for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+ struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+
+ if (ftgmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
+ goto err;
+ }
+
+ /* initialize TX ring */
+ ftgmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
+ return 0;
+
+err:
+ ftgmac100_free_buffers(priv);
+ return -ENOMEM;
+}
+
+/******************************************************************************
+ * internal functions (mdio)
+ *****************************************************************************/
+static void ftgmac100_adjust_link(struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ struct phy_device *phydev = priv->phydev;
+ int ier;
+
+ if (phydev->speed == priv->old_speed)
+ return;
+
+ priv->old_speed = phydev->speed;
+
+ ier = ioread32(priv->base + FTGMAC100_OFFSET_IER);
+
+ /* disable all interrupts */
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+
+ netif_stop_queue(netdev);
+ ftgmac100_stop_hw(priv);
+
+ netif_start_queue(netdev);
+ ftgmac100_init_hw(priv);
+ ftgmac100_start_hw(priv, phydev->speed);
+
+ /* re-enable interrupts */
+ iowrite32(ier, priv->base + FTGMAC100_OFFSET_IER);
+}
+
+static int ftgmac100_mii_probe(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct phy_device *phydev = NULL;
+ int i;
+
+ /* search for connect PHY device */
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ struct phy_device *tmp = priv->mii_bus->phy_map[i];
+
+ if (tmp) {
+ phydev = tmp;
+ break;
+ }
+ }
+
+ /* now we are supposed to have a proper phydev, to attach to... */
+ if (!phydev) {
+ netdev_info(netdev, "%s: no PHY found\n", netdev->name);
+ return -ENODEV;
+ }
+
+ phydev = phy_connect(netdev, dev_name(&phydev->dev),
+ &ftgmac100_adjust_link, 0,
+ PHY_INTERFACE_MODE_GMII);
+
+ if (IS_ERR(phydev)) {
+ netdev_err(netdev, "%s: Could not attach to PHY\n", netdev->name);
+ return PTR_ERR(phydev);
+ }
+
+ priv->phydev = phydev;
+ return 0;
+}
+
+/******************************************************************************
+ * struct mii_bus functions
+ *****************************************************************************/
+static int ftgmac100_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+ struct net_device *netdev = bus->priv;
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ unsigned int phycr;
+ int i;
+
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ /* preserve MDC cycle threshold */
+ phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
+
+ phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
+ FTGMAC100_PHYCR_REGAD(regnum) |
+ FTGMAC100_PHYCR_MIIRD;
+
+ iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ for (i = 0; i < 10; i++) {
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) {
+ int data;
+
+ data = ioread32(priv->base + FTGMAC100_OFFSET_PHYDATA);
+ return FTGMAC100_PHYDATA_MIIRDATA(data);
+ }
+
+ udelay(100);
+ }
+
+ netdev_err(netdev, "mdio read timed out\n");
+ return -EIO;
+}
+
+static int ftgmac100_mdiobus_write(struct mii_bus *bus, int phy_addr,
+ int regnum, u16 value)
+{
+ struct net_device *netdev = bus->priv;
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ unsigned int phycr;
+ int data;
+ int i;
+
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ /* preserve MDC cycle threshold */
+ phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
+
+ phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
+ FTGMAC100_PHYCR_REGAD(regnum) |
+ FTGMAC100_PHYCR_MIIWR;
+
+ data = FTGMAC100_PHYDATA_MIIWDATA(value);
+
+ iowrite32(data, priv->base + FTGMAC100_OFFSET_PHYDATA);
+ iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ for (i = 0; i < 10; i++) {
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0)
+ return 0;
+
+ udelay(100);
+ }
+
+ netdev_err(netdev, "mdio write timed out\n");
+ return -EIO;
+}
+
+static int ftgmac100_mdiobus_reset(struct mii_bus *bus)
+{
+ return 0;
+}
+
+/******************************************************************************
+ * struct ethtool_ops functions
+ *****************************************************************************/
+static void ftgmac100_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, dev_name(&netdev->dev));
+}
+
+static int ftgmac100_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int ftgmac100_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static const struct ethtool_ops ftgmac100_ethtool_ops = {
+ .set_settings = ftgmac100_set_settings,
+ .get_settings = ftgmac100_get_settings,
+ .get_drvinfo = ftgmac100_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+};
+
+/******************************************************************************
+ * interrupt handler
+ *****************************************************************************/
+static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
+{
+ struct net_device *netdev = dev_id;
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ if (likely(netif_running(netdev))) {
+ /* Disable interrupts for polling */
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+ napi_schedule(&priv->napi);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ * struct napi_struct functions
+ *****************************************************************************/
+static int ftgmac100_poll(struct napi_struct *napi, int budget)
+{
+ struct ftgmac100 *priv = container_of(napi, struct ftgmac100, napi);
+ struct net_device *netdev = priv->netdev;
+ unsigned int status;
+ bool completed = true;
+ int rx = 0;
+
+ status = ioread32(priv->base + FTGMAC100_OFFSET_ISR);
+ iowrite32(status, priv->base + FTGMAC100_OFFSET_ISR);
+
+ if (status & (FTGMAC100_INT_RPKT_BUF | FTGMAC100_INT_NO_RXBUF)) {
+ /*
+ * FTGMAC100_INT_RPKT_BUF:
+ * RX DMA has received packets into RX buffer successfully
+ *
+ * FTGMAC100_INT_NO_RXBUF:
+ * RX buffer unavailable
+ */
+ bool retry;
+
+ do {
+ retry = ftgmac100_rx_packet(priv, &rx);
+ } while (retry && rx < budget);
+
+ if (retry && rx == budget)
+ completed = false;
+ }
+
+ if (status & (FTGMAC100_INT_XPKT_ETH | FTGMAC100_INT_XPKT_LOST)) {
+ /*
+ * FTGMAC100_INT_XPKT_ETH:
+ * packet transmitted to ethernet successfully
+ *
+ * FTGMAC100_INT_XPKT_LOST:
+ * packet transmitted to ethernet lost due to late
+ * collision or excessive collision
+ */
+ ftgmac100_tx_complete(priv);
+ }
+
+ if (status & (FTGMAC100_INT_NO_RXBUF | FTGMAC100_INT_RPKT_LOST |
+ FTGMAC100_INT_AHB_ERR | FTGMAC100_INT_PHYSTS_CHG)) {
+ if (net_ratelimit())
+ netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
+ status & FTGMAC100_INT_NO_RXBUF ? "NO_RXBUF " : "",
+ status & FTGMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
+ status & FTGMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
+ status & FTGMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
+
+ if (status & FTGMAC100_INT_NO_RXBUF) {
+ /* RX buffer unavailable */
+ netdev->stats.rx_over_errors++;
+ }
+
+ if (status & FTGMAC100_INT_RPKT_LOST) {
+ /* received packet lost due to RX FIFO full */
+ netdev->stats.rx_fifo_errors++;
+ }
+ }
+
+ if (completed) {
+ napi_complete(napi);
+
+ /* enable all interrupts */
+ iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTGMAC100_OFFSET_IER);
+ }
+
+ return rx;
+}
+
+/******************************************************************************
+ * struct net_device_ops functions
+ *****************************************************************************/
+static int ftgmac100_open(struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ int err;
+
+ err = ftgmac100_alloc_buffers(priv);
+ if (err) {
+ netdev_err(netdev, "failed to allocate buffers\n");
+ goto err_alloc;
+ }
+
+ err = request_irq(priv->irq, ftgmac100_interrupt, 0, netdev->name, netdev);
+ if (err) {
+ netdev_err(netdev, "failed to request irq %d\n", priv->irq);
+ goto err_irq;
+ }
+
+ priv->rx_pointer = 0;
+ priv->tx_clean_pointer = 0;
+ priv->tx_pointer = 0;
+ priv->tx_pending = 0;
+
+ err = ftgmac100_reset_hw(priv);
+ if (err)
+ goto err_hw;
+
+ ftgmac100_init_hw(priv);
+ ftgmac100_start_hw(priv, 10);
+
+ phy_start(priv->phydev);
+
+ napi_enable(&priv->napi);
+ netif_start_queue(netdev);
+
+ /* enable all interrupts */
+ iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTGMAC100_OFFSET_IER);
+ return 0;
+
+err_hw:
+ free_irq(priv->irq, netdev);
+err_irq:
+ ftgmac100_free_buffers(priv);
+err_alloc:
+ return err;
+}
+
+static int ftgmac100_stop(struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ /* disable all interrupts */
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+
+ netif_stop_queue(netdev);
+ napi_disable(&priv->napi);
+ phy_stop(priv->phydev);
+
+ ftgmac100_stop_hw(priv);
+ free_irq(priv->irq, netdev);
+ ftgmac100_free_buffers(priv);
+
+ return 0;
+}
+
+static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ dma_addr_t map;
+
+ if (unlikely(skb->len > MAX_PKT_SIZE)) {
+ if (net_ratelimit())
+ netdev_dbg(netdev, "tx packet too big\n");
+
+ netdev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, map))) {
+ /* drop packet */
+ if (net_ratelimit())
+ netdev_err(netdev, "map socket buffer failed\n");
+
+ netdev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ return ftgmac100_xmit(priv, skb, map);
+}
+
+/* optional */
+static int ftgmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ return phy_mii_ioctl(priv->phydev, ifr, cmd);
+}
+
+static const struct net_device_ops ftgmac100_netdev_ops = {
+ .ndo_open = ftgmac100_open,
+ .ndo_stop = ftgmac100_stop,
+ .ndo_start_xmit = ftgmac100_hard_start_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = ftgmac100_do_ioctl,
+};
+
+/******************************************************************************
+ * struct platform_driver functions
+ *****************************************************************************/
+static int ftgmac100_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int irq;
+ struct net_device *netdev;
+ struct ftgmac100 *priv;
+ int err;
+ int i;
+
+ if (!pdev)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ /* setup net_device */
+ netdev = alloc_etherdev(sizeof(*priv));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops);
+ netdev->netdev_ops = &ftgmac100_netdev_ops;
+ netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
+
+ platform_set_drvdata(pdev, netdev);
+
+ /* setup private data */
+ priv = netdev_priv(netdev);
+ priv->netdev = netdev;
+ priv->dev = &pdev->dev;
+
+ spin_lock_init(&priv->tx_lock);
+
+ /* initialize NAPI */
+ netif_napi_add(netdev, &priv->napi, ftgmac100_poll, 64);
+
+ /* map io memory */
+ priv->res = request_mem_region(res->start, resource_size(res),
+ dev_name(&pdev->dev));
+ if (!priv->res) {
+ dev_err(&pdev->dev, "Could not reserve memory region\n");
+ err = -ENOMEM;
+ goto err_req_mem;
+ }
+
+ priv->base = ioremap(res->start, resource_size(res));
+ if (!priv->base) {
+ dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+ err = -EIO;
+ goto err_ioremap;
+ }
+
+ priv->irq = irq;
+
+ /* initialize mdio bus */
+ priv->mii_bus = mdiobus_alloc();
+ if (!priv->mii_bus) {
+ err = -EIO;
+ goto err_alloc_mdiobus;
+ }
+
+ priv->mii_bus->name = "ftgmac100_mdio";
+ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "ftgmac100_mii");
+
+ priv->mii_bus->priv = netdev;
+ priv->mii_bus->read = ftgmac100_mdiobus_read;
+ priv->mii_bus->write = ftgmac100_mdiobus_write;
+ priv->mii_bus->reset = ftgmac100_mdiobus_reset;
+ priv->mii_bus->irq = priv->phy_irq;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ priv->mii_bus->irq[i] = PHY_POLL;
+
+ err = mdiobus_register(priv->mii_bus);
+ if (err) {
+ dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+ goto err_register_mdiobus;
+ }
+
+ err = ftgmac100_mii_probe(priv);
+ if (err) {
+ dev_err(&pdev->dev, "MII Probe failed!\n");
+ goto err_mii_probe;
+ }
+
+ /* register network device */
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register netdev\n");
+ goto err_register_netdev;
+ }
+
+ netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
+
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ random_ether_addr(netdev->dev_addr);
+ netdev_info(netdev, "generated random MAC address %pM\n",
+ netdev->dev_addr);
+ }
+
+ return 0;
+
+err_register_netdev:
+ phy_disconnect(priv->phydev);
+err_mii_probe:
+ mdiobus_unregister(priv->mii_bus);
+err_register_mdiobus:
+ mdiobus_free(priv->mii_bus);
+err_alloc_mdiobus:
+ iounmap(priv->base);
+err_ioremap:
+ release_resource(priv->res);
+err_req_mem:
+ netif_napi_del(&priv->napi);
+ platform_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+err_alloc_etherdev:
+ return err;
+}
+
+static int __exit ftgmac100_remove(struct platform_device *pdev)
+{
+ struct net_device *netdev;
+ struct ftgmac100 *priv;
+
+ netdev = platform_get_drvdata(pdev);
+ priv = netdev_priv(netdev);
+
+ unregister_netdev(netdev);
+
+ phy_disconnect(priv->phydev);
+ mdiobus_unregister(priv->mii_bus);
+ mdiobus_free(priv->mii_bus);
+
+ iounmap(priv->base);
+ release_resource(priv->res);
+
+ netif_napi_del(&priv->napi);
+ platform_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+ return 0;
+}
+
+static struct platform_driver ftgmac100_driver = {
+ .probe = ftgmac100_probe,
+ .remove = __exit_p(ftgmac100_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+/******************************************************************************
+ * initialization / finalization
+ *****************************************************************************/
+static int __init ftgmac100_init(void)
+{
+ pr_info("Loading version " DRV_VERSION " ...\n");
+ return platform_driver_register(&ftgmac100_driver);
+}
+
+static void __exit ftgmac100_exit(void)
+{
+ platform_driver_unregister(&ftgmac100_driver);
+}
+
+module_init(ftgmac100_init);
+module_exit(ftgmac100_exit);
+
+MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
+MODULE_DESCRIPTION("FTGMAC100 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ftgmac100.h b/drivers/net/ftgmac100.h
new file mode 100644
index 000000000000..13408d448b05
--- /dev/null
+++ b/drivers/net/ftgmac100.h
@@ -0,0 +1,246 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.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 __FTGMAC100_H
+#define __FTGMAC100_H
+
+#define FTGMAC100_OFFSET_ISR 0x00
+#define FTGMAC100_OFFSET_IER 0x04
+#define FTGMAC100_OFFSET_MAC_MADR 0x08
+#define FTGMAC100_OFFSET_MAC_LADR 0x0c
+#define FTGMAC100_OFFSET_MAHT0 0x10
+#define FTGMAC100_OFFSET_MAHT1 0x14
+#define FTGMAC100_OFFSET_NPTXPD 0x18
+#define FTGMAC100_OFFSET_RXPD 0x1c
+#define FTGMAC100_OFFSET_NPTXR_BADR 0x20
+#define FTGMAC100_OFFSET_RXR_BADR 0x24
+#define FTGMAC100_OFFSET_HPTXPD 0x28
+#define FTGMAC100_OFFSET_HPTXR_BADR 0x2c
+#define FTGMAC100_OFFSET_ITC 0x30
+#define FTGMAC100_OFFSET_APTC 0x34
+#define FTGMAC100_OFFSET_DBLAC 0x38
+#define FTGMAC100_OFFSET_DMAFIFOS 0x3c
+#define FTGMAC100_OFFSET_REVR 0x40
+#define FTGMAC100_OFFSET_FEAR 0x44
+#define FTGMAC100_OFFSET_TPAFCR 0x48
+#define FTGMAC100_OFFSET_RBSR 0x4c
+#define FTGMAC100_OFFSET_MACCR 0x50
+#define FTGMAC100_OFFSET_MACSR 0x54
+#define FTGMAC100_OFFSET_TM 0x58
+#define FTGMAC100_OFFSET_PHYCR 0x60
+#define FTGMAC100_OFFSET_PHYDATA 0x64
+#define FTGMAC100_OFFSET_FCR 0x68
+#define FTGMAC100_OFFSET_BPR 0x6c
+#define FTGMAC100_OFFSET_WOLCR 0x70
+#define FTGMAC100_OFFSET_WOLSR 0x74
+#define FTGMAC100_OFFSET_WFCRC 0x78
+#define FTGMAC100_OFFSET_WFBM1 0x80
+#define FTGMAC100_OFFSET_WFBM2 0x84
+#define FTGMAC100_OFFSET_WFBM3 0x88
+#define FTGMAC100_OFFSET_WFBM4 0x8c
+#define FTGMAC100_OFFSET_NPTXR_PTR 0x90
+#define FTGMAC100_OFFSET_HPTXR_PTR 0x94
+#define FTGMAC100_OFFSET_RXR_PTR 0x98
+#define FTGMAC100_OFFSET_TX 0xa0
+#define FTGMAC100_OFFSET_TX_MCOL_SCOL 0xa4
+#define FTGMAC100_OFFSET_TX_ECOL_FAIL 0xa8
+#define FTGMAC100_OFFSET_TX_LCOL_UND 0xac
+#define FTGMAC100_OFFSET_RX 0xb0
+#define FTGMAC100_OFFSET_RX_BC 0xb4
+#define FTGMAC100_OFFSET_RX_MC 0xb8
+#define FTGMAC100_OFFSET_RX_PF_AEP 0xbc
+#define FTGMAC100_OFFSET_RX_RUNT 0xc0
+#define FTGMAC100_OFFSET_RX_CRCER_FTL 0xc4
+#define FTGMAC100_OFFSET_RX_COL_LOST 0xc8
+
+/*
+ * Interrupt status register & interrupt enable register
+ */
+#define FTGMAC100_INT_RPKT_BUF (1 << 0)
+#define FTGMAC100_INT_RPKT_FIFO (1 << 1)
+#define FTGMAC100_INT_NO_RXBUF (1 << 2)
+#define FTGMAC100_INT_RPKT_LOST (1 << 3)
+#define FTGMAC100_INT_XPKT_ETH (1 << 4)
+#define FTGMAC100_INT_XPKT_FIFO (1 << 5)
+#define FTGMAC100_INT_NO_NPTXBUF (1 << 6)
+#define FTGMAC100_INT_XPKT_LOST (1 << 7)
+#define FTGMAC100_INT_AHB_ERR (1 << 8)
+#define FTGMAC100_INT_PHYSTS_CHG (1 << 9)
+#define FTGMAC100_INT_NO_HPTXBUF (1 << 10)
+
+/*
+ * Interrupt timer control register
+ */
+#define FTGMAC100_ITC_RXINT_CNT(x) (((x) & 0xf) << 0)
+#define FTGMAC100_ITC_RXINT_THR(x) (((x) & 0x7) << 4)
+#define FTGMAC100_ITC_RXINT_TIME_SEL (1 << 7)
+#define FTGMAC100_ITC_TXINT_CNT(x) (((x) & 0xf) << 8)
+#define FTGMAC100_ITC_TXINT_THR(x) (((x) & 0x7) << 12)
+#define FTGMAC100_ITC_TXINT_TIME_SEL (1 << 15)
+
+/*
+ * Automatic polling timer control register
+ */
+#define FTGMAC100_APTC_RXPOLL_CNT(x) (((x) & 0xf) << 0)
+#define FTGMAC100_APTC_RXPOLL_TIME_SEL (1 << 4)
+#define FTGMAC100_APTC_TXPOLL_CNT(x) (((x) & 0xf) << 8)
+#define FTGMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
+
+/*
+ * DMA burst length and arbitration control register
+ */
+#define FTGMAC100_DBLAC_RXFIFO_LTHR(x) (((x) & 0x7) << 0)
+#define FTGMAC100_DBLAC_RXFIFO_HTHR(x) (((x) & 0x7) << 3)
+#define FTGMAC100_DBLAC_RX_THR_EN (1 << 6)
+#define FTGMAC100_DBLAC_RXBURST_SIZE(x) (((x) & 0x3) << 8)
+#define FTGMAC100_DBLAC_TXBURST_SIZE(x) (((x) & 0x3) << 10)
+#define FTGMAC100_DBLAC_RXDES_SIZE(x) (((x) & 0xf) << 12)
+#define FTGMAC100_DBLAC_TXDES_SIZE(x) (((x) & 0xf) << 16)
+#define FTGMAC100_DBLAC_IFG_CNT(x) (((x) & 0x7) << 20)
+#define FTGMAC100_DBLAC_IFG_INC (1 << 23)
+
+/*
+ * DMA FIFO status register
+ */
+#define FTGMAC100_DMAFIFOS_RXDMA1_SM(dmafifos) ((dmafifos) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXDMA2_SM(dmafifos) (((dmafifos) >> 4) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXDMA3_SM(dmafifos) (((dmafifos) >> 8) & 0x7)
+#define FTGMAC100_DMAFIFOS_TXDMA1_SM(dmafifos) (((dmafifos) >> 12) & 0xf)
+#define FTGMAC100_DMAFIFOS_TXDMA2_SM(dmafifos) (((dmafifos) >> 16) & 0x3)
+#define FTGMAC100_DMAFIFOS_TXDMA3_SM(dmafifos) (((dmafifos) >> 18) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXFIFO_EMPTY (1 << 26)
+#define FTGMAC100_DMAFIFOS_TXFIFO_EMPTY (1 << 27)
+#define FTGMAC100_DMAFIFOS_RXDMA_GRANT (1 << 28)
+#define FTGMAC100_DMAFIFOS_TXDMA_GRANT (1 << 29)
+#define FTGMAC100_DMAFIFOS_RXDMA_REQ (1 << 30)
+#define FTGMAC100_DMAFIFOS_TXDMA_REQ (1 << 31)
+
+/*
+ * Receive buffer size register
+ */
+#define FTGMAC100_RBSR_SIZE(x) ((x) & 0x3fff)
+
+/*
+ * MAC control register
+ */
+#define FTGMAC100_MACCR_TXDMA_EN (1 << 0)
+#define FTGMAC100_MACCR_RXDMA_EN (1 << 1)
+#define FTGMAC100_MACCR_TXMAC_EN (1 << 2)
+#define FTGMAC100_MACCR_RXMAC_EN (1 << 3)
+#define FTGMAC100_MACCR_RM_VLAN (1 << 4)
+#define FTGMAC100_MACCR_HPTXR_EN (1 << 5)
+#define FTGMAC100_MACCR_LOOP_EN (1 << 6)
+#define FTGMAC100_MACCR_ENRX_IN_HALFTX (1 << 7)
+#define FTGMAC100_MACCR_FULLDUP (1 << 8)
+#define FTGMAC100_MACCR_GIGA_MODE (1 << 9)
+#define FTGMAC100_MACCR_CRC_APD (1 << 10)
+#define FTGMAC100_MACCR_RX_RUNT (1 << 12)
+#define FTGMAC100_MACCR_JUMBO_LF (1 << 13)
+#define FTGMAC100_MACCR_RX_ALL (1 << 14)
+#define FTGMAC100_MACCR_HT_MULTI_EN (1 << 15)
+#define FTGMAC100_MACCR_RX_MULTIPKT (1 << 16)
+#define FTGMAC100_MACCR_RX_BROADPKT (1 << 17)
+#define FTGMAC100_MACCR_DISCARD_CRCERR (1 << 18)
+#define FTGMAC100_MACCR_FAST_MODE (1 << 19)
+#define FTGMAC100_MACCR_SW_RST (1 << 31)
+
+/*
+ * PHY control register
+ */
+#define FTGMAC100_PHYCR_MDC_CYCTHR_MASK 0x3f
+#define FTGMAC100_PHYCR_MDC_CYCTHR(x) ((x) & 0x3f)
+#define FTGMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
+#define FTGMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
+#define FTGMAC100_PHYCR_MIIRD (1 << 26)
+#define FTGMAC100_PHYCR_MIIWR (1 << 27)
+
+/*
+ * PHY data register
+ */
+#define FTGMAC100_PHYDATA_MIIWDATA(x) ((x) & 0xffff)
+#define FTGMAC100_PHYDATA_MIIRDATA(phydata) (((phydata) >> 16) & 0xffff)
+
+/*
+ * Transmit descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_txdes {
+ unsigned int txdes0;
+ unsigned int txdes1;
+ unsigned int txdes2; /* not used by HW */
+ unsigned int txdes3; /* TXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_TXDES0_TXBUF_SIZE(x) ((x) & 0x3fff)
+#define FTGMAC100_TXDES0_EDOTR (1 << 15)
+#define FTGMAC100_TXDES0_CRC_ERR (1 << 19)
+#define FTGMAC100_TXDES0_LTS (1 << 28)
+#define FTGMAC100_TXDES0_FTS (1 << 29)
+#define FTGMAC100_TXDES0_TXDMA_OWN (1 << 31)
+
+#define FTGMAC100_TXDES1_VLANTAG_CI(x) ((x) & 0xffff)
+#define FTGMAC100_TXDES1_INS_VLANTAG (1 << 16)
+#define FTGMAC100_TXDES1_TCP_CHKSUM (1 << 17)
+#define FTGMAC100_TXDES1_UDP_CHKSUM (1 << 18)
+#define FTGMAC100_TXDES1_IP_CHKSUM (1 << 19)
+#define FTGMAC100_TXDES1_LLC (1 << 22)
+#define FTGMAC100_TXDES1_TX2FIC (1 << 30)
+#define FTGMAC100_TXDES1_TXIC (1 << 31)
+
+/*
+ * Receive descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_rxdes {
+ unsigned int rxdes0;
+ unsigned int rxdes1;
+ unsigned int rxdes2; /* not used by HW */
+ unsigned int rxdes3; /* RXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_RXDES0_VDBC 0x3fff
+#define FTGMAC100_RXDES0_EDORR (1 << 15)
+#define FTGMAC100_RXDES0_MULTICAST (1 << 16)
+#define FTGMAC100_RXDES0_BROADCAST (1 << 17)
+#define FTGMAC100_RXDES0_RX_ERR (1 << 18)
+#define FTGMAC100_RXDES0_CRC_ERR (1 << 19)
+#define FTGMAC100_RXDES0_FTL (1 << 20)
+#define FTGMAC100_RXDES0_RUNT (1 << 21)
+#define FTGMAC100_RXDES0_RX_ODD_NB (1 << 22)
+#define FTGMAC100_RXDES0_FIFO_FULL (1 << 23)
+#define FTGMAC100_RXDES0_PAUSE_OPCODE (1 << 24)
+#define FTGMAC100_RXDES0_PAUSE_FRAME (1 << 25)
+#define FTGMAC100_RXDES0_LRS (1 << 28)
+#define FTGMAC100_RXDES0_FRS (1 << 29)
+#define FTGMAC100_RXDES0_RXPKT_RDY (1 << 31)
+
+#define FTGMAC100_RXDES1_VLANTAG_CI 0xffff
+#define FTGMAC100_RXDES1_PROT_MASK (0x3 << 20)
+#define FTGMAC100_RXDES1_PROT_NONIP (0x0 << 20)
+#define FTGMAC100_RXDES1_PROT_IP (0x1 << 20)
+#define FTGMAC100_RXDES1_PROT_TCPIP (0x2 << 20)
+#define FTGMAC100_RXDES1_PROT_UDPIP (0x3 << 20)
+#define FTGMAC100_RXDES1_LLC (1 << 22)
+#define FTGMAC100_RXDES1_DF (1 << 23)
+#define FTGMAC100_RXDES1_VLANTAG_AVAIL (1 << 24)
+#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR (1 << 25)
+#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR (1 << 26)
+#define FTGMAC100_RXDES1_IP_CHKSUM_ERR (1 << 27)
+
+#endif /* __FTGMAC100_H */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index dfa55f94ba7f..835cd2588148 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -62,6 +62,9 @@
* The driver then cleans up the buffer.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define DEBUG
+
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -137,8 +140,6 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
int amount_pull);
-static void gfar_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp);
void gfar_halt(struct net_device *dev);
static void gfar_halt_nodisable(struct net_device *dev);
void gfar_start(struct net_device *dev);
@@ -213,8 +214,7 @@ static int gfar_init_bds(struct net_device *ndev)
} else {
skb = gfar_new_skb(ndev);
if (!skb) {
- pr_err("%s: Can't allocate RX buffers\n",
- ndev->name);
+ netdev_err(ndev, "Can't allocate RX buffers\n");
goto err_rxalloc_fail;
}
rx_queue->rx_skbuff[j] = skb;
@@ -258,15 +258,14 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
sizeof(struct rxbd8) * priv->total_rx_ring_size,
&addr, GFP_KERNEL);
if (!vaddr) {
- if (netif_msg_ifup(priv))
- pr_err("%s: Could not allocate buffer descriptors!\n",
- ndev->name);
+ netif_err(priv, ifup, ndev,
+ "Could not allocate buffer descriptors!\n");
return -ENOMEM;
}
for (i = 0; i < priv->num_tx_queues; i++) {
tx_queue = priv->tx_queue[i];
- tx_queue->tx_bd_base = (struct txbd8 *) vaddr;
+ tx_queue->tx_bd_base = vaddr;
tx_queue->tx_bd_dma_base = addr;
tx_queue->dev = ndev;
/* enet DMA only understands physical addresses */
@@ -277,7 +276,7 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
/* Start the rx descriptor ring where the tx ring leaves off */
for (i = 0; i < priv->num_rx_queues; i++) {
rx_queue = priv->rx_queue[i];
- rx_queue->rx_bd_base = (struct rxbd8 *) vaddr;
+ rx_queue->rx_bd_base = vaddr;
rx_queue->rx_bd_dma_base = addr;
rx_queue->dev = ndev;
addr += sizeof (struct rxbd8) * rx_queue->rx_ring_size;
@@ -290,9 +289,8 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
tx_queue->tx_skbuff = kmalloc(sizeof(*tx_queue->tx_skbuff) *
tx_queue->tx_ring_size, GFP_KERNEL);
if (!tx_queue->tx_skbuff) {
- if (netif_msg_ifup(priv))
- pr_err("%s: Could not allocate tx_skbuff\n",
- ndev->name);
+ netif_err(priv, ifup, ndev,
+ "Could not allocate tx_skbuff\n");
goto cleanup;
}
@@ -306,9 +304,8 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
rx_queue->rx_ring_size, GFP_KERNEL);
if (!rx_queue->rx_skbuff) {
- if (netif_msg_ifup(priv))
- pr_err("%s: Could not allocate rx_skbuff\n",
- ndev->name);
+ netif_err(priv, ifup, ndev,
+ "Could not allocate rx_skbuff\n");
goto cleanup;
}
@@ -392,10 +389,11 @@ static void gfar_init_mac(struct net_device *ndev)
rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
/* keep vlan related bits if it's enabled */
- if (priv->vlgrp) {
+ if (ndev->features & NETIF_F_HW_VLAN_TX)
rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
+
+ if (ndev->features & NETIF_F_HW_VLAN_RX)
tctrl |= TCTRL_VLINS;
- }
/* Init rctrl based on our settings */
gfar_write(&regs->rctrl, rctrl);
@@ -468,7 +466,6 @@ static const struct net_device_ops gfar_netdev_ops = {
.ndo_tx_timeout = gfar_timeout,
.ndo_do_ioctl = gfar_ioctl,
.ndo_get_stats = gfar_get_stats,
- .ndo_vlan_rx_register = gfar_vlan_rx_register,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -508,10 +505,17 @@ void unlock_tx_qs(struct gfar_private *priv)
spin_unlock(&priv->tx_queue[i]->txlock);
}
+static bool gfar_is_vlan_on(struct gfar_private *priv)
+{
+ return (priv->ndev->features & NETIF_F_HW_VLAN_RX) ||
+ (priv->ndev->features & NETIF_F_HW_VLAN_TX);
+}
+
/* Returns 1 if incoming frames use an FCB */
static inline int gfar_uses_fcb(struct gfar_private *priv)
{
- return priv->vlgrp || (priv->ndev->features & NETIF_F_RXCSUM) ||
+ return gfar_is_vlan_on(priv) ||
+ (priv->ndev->features & NETIF_F_RXCSUM) ||
(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER);
}
@@ -625,9 +629,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
num_tx_qs = tx_queues ? *tx_queues : 1;
if (num_tx_qs > MAX_TX_QS) {
- printk(KERN_ERR "num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
- num_tx_qs, MAX_TX_QS);
- printk(KERN_ERR "Cannot do alloc_etherdev, aborting\n");
+ pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
+ num_tx_qs, MAX_TX_QS);
+ pr_err("Cannot do alloc_etherdev, aborting\n");
return -EINVAL;
}
@@ -635,9 +639,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
num_rx_qs = rx_queues ? *rx_queues : 1;
if (num_rx_qs > MAX_RX_QS) {
- printk(KERN_ERR "num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
- num_tx_qs, MAX_TX_QS);
- printk(KERN_ERR "Cannot do alloc_etherdev, aborting\n");
+ pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
+ num_rx_qs, MAX_RX_QS);
+ pr_err("Cannot do alloc_etherdev, aborting\n");
return -EINVAL;
}
@@ -655,6 +659,11 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
priv->num_rx_queues = num_rx_qs;
priv->num_grps = 0x0;
+ /* Init Rx queue filer rule set linked list*/
+ INIT_LIST_HEAD(&priv->rx_list.list);
+ priv->rx_list.count = 0;
+ mutex_init(&priv->rx_queue_access);
+
model = of_get_property(np, "model", NULL);
for (i = 0; i < MAXGROUPS; i++)
@@ -1034,10 +1043,10 @@ static int gfar_probe(struct platform_device *ofdev)
NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
}
- priv->vlgrp = NULL;
-
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN)
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
+ dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ }
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
priv->extended_hash = 1;
@@ -1148,9 +1157,8 @@ static int gfar_probe(struct platform_device *ofdev)
priv->rx_queue[i]->rxic = DEFAULT_RXIC;
}
- /* enable filer if using multiple RX queues*/
- if(priv->num_rx_queues > 1)
- priv->rx_filer_enable = 1;
+ /* always enable rx filer*/
+ priv->rx_filer_enable = 1;
/* Enable most messages by default */
priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
@@ -1160,8 +1168,7 @@ static int gfar_probe(struct platform_device *ofdev)
err = register_netdev(dev);
if (err) {
- printk(KERN_ERR "%s: Cannot register net device, aborting.\n",
- dev->name);
+ pr_err("%s: Cannot register net device, aborting\n", dev->name);
goto register_fail;
}
@@ -1212,17 +1219,17 @@ static int gfar_probe(struct platform_device *ofdev)
gfar_init_sysfs(dev);
/* Print out the device info */
- printk(KERN_INFO DEVICE_NAME "%pM\n", dev->name, dev->dev_addr);
+ netdev_info(dev, "mac: %pM\n", dev->dev_addr);
/* Even more device info helps when determining which kernel */
/* provided which set of benchmarks. */
- printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
+ netdev_info(dev, "Running with NAPI enabled\n");
for (i = 0; i < priv->num_rx_queues; i++)
- printk(KERN_INFO "%s: RX BD ring size for Q[%d]: %d\n",
- dev->name, i, priv->rx_queue[i]->rx_ring_size);
+ netdev_info(dev, "RX BD ring size for Q[%d]: %d\n",
+ i, priv->rx_queue[i]->rx_ring_size);
for(i = 0; i < priv->num_tx_queues; i++)
- printk(KERN_INFO "%s: TX BD ring size for Q[%d]: %d\n",
- dev->name, i, priv->tx_queue[i]->tx_ring_size);
+ netdev_info(dev, "TX BD ring size for Q[%d]: %d\n",
+ i, priv->tx_queue[i]->tx_ring_size);
return 0;
@@ -1855,34 +1862,30 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
* Transmit, and Receive */
if ((err = request_irq(grp->interruptError, gfar_error, 0,
grp->int_name_er,grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptError);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptError);
goto err_irq_fail;
}
if ((err = request_irq(grp->interruptTransmit, gfar_transmit,
0, grp->int_name_tx, grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptTransmit);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptTransmit);
goto tx_irq_fail;
}
if ((err = request_irq(grp->interruptReceive, gfar_receive, 0,
grp->int_name_rx, grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptReceive);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptReceive);
goto rx_irq_fail;
}
} else {
if ((err = request_irq(grp->interruptTransmit, gfar_interrupt, 0,
grp->int_name_tx, grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptTransmit);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptTransmit);
goto err_irq_fail;
}
}
@@ -2306,10 +2309,8 @@ void gfar_check_rx_parser_mode(struct gfar_private *priv)
gfar_write(&regs->rctrl, tempval);
}
-
/* Enables and disables VLAN insertion/extraction */
-static void gfar_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
+void gfar_vlan_mode(struct net_device *dev, u32 features)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = NULL;
@@ -2320,25 +2321,24 @@ static void gfar_vlan_rx_register(struct net_device *dev,
local_irq_save(flags);
lock_rx_qs(priv);
- priv->vlgrp = grp;
-
- if (grp) {
+ if (features & NETIF_F_HW_VLAN_TX) {
/* Enable VLAN tag insertion */
tempval = gfar_read(&regs->tctrl);
tempval |= TCTRL_VLINS;
-
gfar_write(&regs->tctrl, tempval);
-
- /* Enable VLAN tag extraction */
- tempval = gfar_read(&regs->rctrl);
- tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
- gfar_write(&regs->rctrl, tempval);
} else {
/* Disable VLAN tag insertion */
tempval = gfar_read(&regs->tctrl);
tempval &= ~TCTRL_VLINS;
gfar_write(&regs->tctrl, tempval);
+ }
+ if (features & NETIF_F_HW_VLAN_RX) {
+ /* Enable VLAN tag extraction */
+ tempval = gfar_read(&regs->rctrl);
+ tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
+ gfar_write(&regs->rctrl, tempval);
+ } else {
/* Disable VLAN tag extraction */
tempval = gfar_read(&regs->rctrl);
tempval &= ~RCTRL_VLEX;
@@ -2361,13 +2361,11 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
int oldsize = priv->rx_buffer_size;
int frame_size = new_mtu + ETH_HLEN;
- if (priv->vlgrp)
+ if (gfar_is_vlan_on(priv))
frame_size += VLAN_HLEN;
if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
- if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: Invalid MTU setting\n",
- dev->name);
+ netif_err(priv, drv, dev, "Invalid MTU setting\n");
return -EINVAL;
}
@@ -2716,11 +2714,12 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
/* Tell the skb what kind of packet this is */
skb->protocol = eth_type_trans(skb, dev);
+ /* Set vlan tag */
+ if (fcb->flags & RXFCB_VLN)
+ __vlan_hwaccel_put_tag(skb, fcb->vlctl);
+
/* Send the packet up the stack */
- if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN)))
- ret = vlan_hwaccel_receive_skb(skb, priv->vlgrp, fcb->vlctl);
- else
- ret = netif_receive_skb(skb);
+ ret = netif_receive_skb(skb);
if (NET_RX_DROP == ret)
priv->extra_stats.kernel_dropped++;
@@ -2787,9 +2786,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
gfar_process_frame(dev, skb, amount_pull);
} else {
- if (netif_msg_rx_err(priv))
- printk(KERN_WARNING
- "%s: Missing skb!\n", dev->name);
+ netif_warn(priv, rx_err, dev, "Missing skb!\n");
rx_queue->stats.rx_dropped++;
priv->extra_stats.rx_skbmissing++;
}
@@ -2992,10 +2989,9 @@ static void adjust_link(struct net_device *dev)
ecntrl &= ~(ECNTRL_R100);
break;
default:
- if (netif_msg_link(priv))
- printk(KERN_WARNING
- "%s: Ack! Speed (%d) is not 10/100/1000!\n",
- dev->name, phydev->speed);
+ netif_warn(priv, link, dev,
+ "Ack! Speed (%d) is not 10/100/1000!\n",
+ phydev->speed);
break;
}
@@ -3200,8 +3196,8 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
/* Hmm... */
if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
- dev->name, events, gfar_read(&regs->imask));
+ netdev_dbg(dev, "error interrupt (ievent=0x%08x imask=0x%08x)\n",
+ events, gfar_read(&regs->imask));
/* Update the error counters */
if (events & IEVENT_TXE) {
@@ -3214,9 +3210,8 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
if (events & IEVENT_XFUN) {
unsigned long flags;
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: TX FIFO underrun, "
- "packet dropped.\n", dev->name);
+ netif_dbg(priv, tx_err, dev,
+ "TX FIFO underrun, packet dropped\n");
dev->stats.tx_dropped++;
priv->extra_stats.tx_underrun++;
@@ -3229,8 +3224,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
unlock_tx_qs(priv);
local_irq_restore(flags);
}
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: Transmit Error\n", dev->name);
+ netif_dbg(priv, tx_err, dev, "Transmit Error\n");
}
if (events & IEVENT_BSY) {
dev->stats.rx_errors++;
@@ -3238,29 +3232,25 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
gfar_receive(irq, grp_id);
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: busy error (rstat: %x)\n",
- dev->name, gfar_read(&regs->rstat));
+ netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n",
+ gfar_read(&regs->rstat));
}
if (events & IEVENT_BABR) {
dev->stats.rx_errors++;
priv->extra_stats.rx_babr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babbling RX error\n", dev->name);
+ netif_dbg(priv, rx_err, dev, "babbling RX error\n");
}
if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: bus error\n", dev->name);
+ netif_dbg(priv, rx_err, dev, "bus error\n");
}
- if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
- printk(KERN_DEBUG "%s: control frame\n", dev->name);
+ if (events & IEVENT_RXC)
+ netif_dbg(priv, rx_status, dev, "control frame\n");
if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++;
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: babbling TX error\n", dev->name);
+ netif_dbg(priv, tx_err, dev, "babbling TX error\n");
}
return IRQ_HANDLED;
}
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 440e69d8beff..9aa43773e8e3 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -47,6 +47,16 @@
#include <linux/workqueue.h>
#include <linux/ethtool.h>
+struct ethtool_flow_spec_container {
+ struct ethtool_rx_flow_spec fs;
+ struct list_head list;
+};
+
+struct ethtool_rx_list {
+ struct list_head list;
+ unsigned int count;
+};
+
/* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64
@@ -168,6 +178,7 @@ extern const char gfar_driver_version[];
#define MACCFG2_LENGTHCHECK 0x00000010
#define MACCFG2_MPEN 0x00000008
+#define ECNTRL_FIFM 0x00008000
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
#define ECNTRL_REDUCED_MODE 0x00000010
@@ -271,6 +282,7 @@ extern const char gfar_driver_version[];
#define RCTRL_TUCSEN 0x00000100
#define RCTRL_PRSDEP_MASK 0x000000c0
#define RCTRL_PRSDEP_INIT 0x000000c0
+#define RCTRL_PRSFM 0x00000020
#define RCTRL_PROM 0x00000008
#define RCTRL_EMEN 0x00000002
#define RCTRL_REQ_PARSER (RCTRL_VLEX | RCTRL_IPCSEN | \
@@ -397,6 +409,7 @@ extern const char gfar_driver_version[];
#define RQFCR_HASHTBL_2 0x00060000
#define RQFCR_HASHTBL_3 0x00080000
#define RQFCR_HASH 0x00010000
+#define RQFCR_QUEUE 0x0000FC00
#define RQFCR_CLE 0x00000200
#define RQFCR_RJE 0x00000100
#define RQFCR_AND 0x00000080
@@ -1064,8 +1077,9 @@ struct gfar_private {
struct sk_buff_head rx_recycle;
- struct vlan_group *vlgrp;
-
+ /* RX queue filer rule set*/
+ struct ethtool_rx_list rx_list;
+ struct mutex rx_queue_access;
/* Hash registers and their width */
u32 __iomem *hash_regs[16];
@@ -1142,6 +1156,16 @@ static inline void gfar_write_filer(struct gfar_private *priv,
gfar_write(&regs->rqfpr, fpr);
}
+static inline void gfar_read_filer(struct gfar_private *priv,
+ unsigned int far, unsigned int *fcr, unsigned int *fpr)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+
+ gfar_write(&regs->rqfar, far);
+ *fcr = gfar_read(&regs->rqfcr);
+ *fpr = gfar_read(&regs->rqfpr);
+}
+
extern void lock_rx_qs(struct gfar_private *priv);
extern void lock_tx_qs(struct gfar_private *priv);
extern void unlock_rx_qs(struct gfar_private *priv);
@@ -1157,7 +1181,36 @@ extern void gfar_configure_coalescing(struct gfar_private *priv,
void gfar_init_sysfs(struct net_device *dev);
int gfar_set_features(struct net_device *dev, u32 features);
extern void gfar_check_rx_parser_mode(struct gfar_private *priv);
+extern void gfar_vlan_mode(struct net_device *dev, u32 features);
extern const struct ethtool_ops gfar_ethtool_ops;
+#define MAX_FILER_CACHE_IDX (2*(MAX_FILER_IDX))
+
+#define RQFCR_PID_PRI_MASK 0xFFFFFFF8
+#define RQFCR_PID_L4P_MASK 0xFFFFFF00
+#define RQFCR_PID_VID_MASK 0xFFFFF000
+#define RQFCR_PID_PORT_MASK 0xFFFF0000
+#define RQFCR_PID_MAC_MASK 0xFF000000
+
+struct gfar_mask_entry {
+ unsigned int mask; /* The mask value which is valid form start to end */
+ unsigned int start;
+ unsigned int end;
+ unsigned int block; /* Same block values indicate depended entries */
+};
+
+/* Represents a receive filer table entry */
+struct gfar_filer_entry {
+ u32 ctrl;
+ u32 prop;
+};
+
+
+/* The 20 additional entries are a shadow for one extra element */
+struct filer_table {
+ u32 index;
+ struct gfar_filer_entry fe[MAX_FILER_CACHE_IDX + 20];
+};
+
#endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 239e3330495f..6e350692d118 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -16,6 +16,8 @@
* by reference.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -37,6 +39,8 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <linux/sort.h>
+#include <linux/if_vlan.h>
#include "gianfar.h"
@@ -375,13 +379,13 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
/* Check the bounds of the values */
if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
pr_info("Coalescing is limited to %d microseconds\n",
- GFAR_MAX_COAL_USECS);
+ GFAR_MAX_COAL_USECS);
return -EINVAL;
}
if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
pr_info("Coalescing is limited to %d frames\n",
- GFAR_MAX_COAL_FRAMES);
+ GFAR_MAX_COAL_FRAMES);
return -EINVAL;
}
@@ -404,13 +408,13 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
/* Check the bounds of the values */
if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
pr_info("Coalescing is limited to %d microseconds\n",
- GFAR_MAX_COAL_USECS);
+ GFAR_MAX_COAL_USECS);
return -EINVAL;
}
if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
pr_info("Coalescing is limited to %d frames\n",
- GFAR_MAX_COAL_FRAMES);
+ GFAR_MAX_COAL_FRAMES);
return -EINVAL;
}
@@ -464,8 +468,7 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
return -EINVAL;
if (!is_power_of_2(rvals->rx_pending)) {
- printk("%s: Ring sizes must be a power of 2\n",
- dev->name);
+ netdev_err(dev, "Ring sizes must be a power of 2\n");
return -EINVAL;
}
@@ -473,8 +476,7 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
return -EINVAL;
if (!is_power_of_2(rvals->tx_pending)) {
- printk("%s: Ring sizes must be a power of 2\n",
- dev->name);
+ netdev_err(dev, "Ring sizes must be a power of 2\n");
return -EINVAL;
}
@@ -524,6 +526,9 @@ int gfar_set_features(struct net_device *dev, u32 features)
int err = 0, i = 0;
u32 changed = dev->features ^ features;
+ if (changed & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX))
+ gfar_vlan_mode(dev, features);
+
if (!(changed & NETIF_F_RXCSUM))
return 0;
@@ -700,7 +705,7 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
cmp_rqfpr = RQFPR_IPV6 |RQFPR_UDP;
break;
default:
- printk(KERN_ERR "Right now this class is not supported\n");
+ pr_err("Right now this class is not supported\n");
return 0;
}
@@ -715,8 +720,7 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
}
if (i == MAX_FILER_IDX + 1) {
- printk(KERN_ERR "No parse rule found, ");
- printk(KERN_ERR "can't create hash rules\n");
+ pr_err("No parse rule found, can't create hash rules\n");
return 0;
}
@@ -773,19 +777,948 @@ static int gfar_set_hash_opts(struct gfar_private *priv, struct ethtool_rxnfc *c
return 0;
}
+static int gfar_check_filer_hardware(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = NULL;
+ u32 i;
+
+ regs = priv->gfargrp[0].regs;
+
+ /* Check if we are in FIFO mode */
+ i = gfar_read(&regs->ecntrl);
+ i &= ECNTRL_FIFM;
+ if (i == ECNTRL_FIFM) {
+ netdev_notice(priv->ndev, "Interface in FIFO mode\n");
+ i = gfar_read(&regs->rctrl);
+ i &= RCTRL_PRSDEP_MASK | RCTRL_PRSFM;
+ if (i == (RCTRL_PRSDEP_MASK | RCTRL_PRSFM)) {
+ netdev_info(priv->ndev,
+ "Receive Queue Filtering enabled\n");
+ } else {
+ netdev_warn(priv->ndev,
+ "Receive Queue Filtering disabled\n");
+ return -EOPNOTSUPP;
+ }
+ }
+ /* Or in standard mode */
+ else {
+ i = gfar_read(&regs->rctrl);
+ i &= RCTRL_PRSDEP_MASK;
+ if (i == RCTRL_PRSDEP_MASK) {
+ netdev_info(priv->ndev,
+ "Receive Queue Filtering enabled\n");
+ } else {
+ netdev_warn(priv->ndev,
+ "Receive Queue Filtering disabled\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ /* Sets the properties for arbitrary filer rule
+ * to the first 4 Layer 4 Bytes */
+ regs->rbifx = 0xC0C1C2C3;
+ return 0;
+}
+
+static int gfar_comp_asc(const void *a, const void *b)
+{
+ return memcmp(a, b, 4);
+}
+
+static int gfar_comp_desc(const void *a, const void *b)
+{
+ return -memcmp(a, b, 4);
+}
+
+static void gfar_swap(void *a, void *b, int size)
+{
+ u32 *_a = a;
+ u32 *_b = b;
+
+ swap(_a[0], _b[0]);
+ swap(_a[1], _b[1]);
+ swap(_a[2], _b[2]);
+ swap(_a[3], _b[3]);
+}
+
+/* Write a mask to filer cache */
+static void gfar_set_mask(u32 mask, struct filer_table *tab)
+{
+ tab->fe[tab->index].ctrl = RQFCR_AND | RQFCR_PID_MASK | RQFCR_CMP_EXACT;
+ tab->fe[tab->index].prop = mask;
+ tab->index++;
+}
+
+/* Sets parse bits (e.g. IP or TCP) */
+static void gfar_set_parse_bits(u32 value, u32 mask, struct filer_table *tab)
+{
+ gfar_set_mask(mask, tab);
+ tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_PID_PARSE
+ | RQFCR_AND;
+ tab->fe[tab->index].prop = value;
+ tab->index++;
+}
+
+static void gfar_set_general_attribute(u32 value, u32 mask, u32 flag,
+ struct filer_table *tab)
+{
+ gfar_set_mask(mask, tab);
+ tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_AND | flag;
+ tab->fe[tab->index].prop = value;
+ tab->index++;
+}
+
+/*
+ * For setting a tuple of value and mask of type flag
+ * Example:
+ * IP-Src = 10.0.0.0/255.0.0.0
+ * value: 0x0A000000 mask: FF000000 flag: RQFPR_IPV4
+ *
+ * Ethtool gives us a value=0 and mask=~0 for don't care a tuple
+ * For a don't care mask it gives us a 0
+ *
+ * The check if don't care and the mask adjustment if mask=0 is done for VLAN
+ * and MAC stuff on an upper level (due to missing information on this level).
+ * For these guys we can discard them if they are value=0 and mask=0.
+ *
+ * Further the all masks are one-padded for better hardware efficiency.
+ */
+static void gfar_set_attribute(u32 value, u32 mask, u32 flag,
+ struct filer_table *tab)
+{
+ switch (flag) {
+ /* 3bit */
+ case RQFCR_PID_PRI:
+ if (!(value | mask))
+ return;
+ mask |= RQFCR_PID_PRI_MASK;
+ break;
+ /* 8bit */
+ case RQFCR_PID_L4P:
+ case RQFCR_PID_TOS:
+ if (!~(mask | RQFCR_PID_L4P_MASK))
+ return;
+ if (!mask)
+ mask = ~0;
+ else
+ mask |= RQFCR_PID_L4P_MASK;
+ break;
+ /* 12bit */
+ case RQFCR_PID_VID:
+ if (!(value | mask))
+ return;
+ mask |= RQFCR_PID_VID_MASK;
+ break;
+ /* 16bit */
+ case RQFCR_PID_DPT:
+ case RQFCR_PID_SPT:
+ case RQFCR_PID_ETY:
+ if (!~(mask | RQFCR_PID_PORT_MASK))
+ return;
+ if (!mask)
+ mask = ~0;
+ else
+ mask |= RQFCR_PID_PORT_MASK;
+ break;
+ /* 24bit */
+ case RQFCR_PID_DAH:
+ case RQFCR_PID_DAL:
+ case RQFCR_PID_SAH:
+ case RQFCR_PID_SAL:
+ if (!(value | mask))
+ return;
+ mask |= RQFCR_PID_MAC_MASK;
+ break;
+ /* for all real 32bit masks */
+ default:
+ if (!~mask)
+ return;
+ if (!mask)
+ mask = ~0;
+ break;
+ }
+ gfar_set_general_attribute(value, mask, flag, tab);
+}
+
+/* Translates value and mask for UDP, TCP or SCTP */
+static void gfar_set_basic_ip(struct ethtool_tcpip4_spec *value,
+ struct ethtool_tcpip4_spec *mask, struct filer_table *tab)
+{
+ gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
+ gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
+ gfar_set_attribute(value->pdst, mask->pdst, RQFCR_PID_DPT, tab);
+ gfar_set_attribute(value->psrc, mask->psrc, RQFCR_PID_SPT, tab);
+ gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
+}
+
+/* Translates value and mask for RAW-IP4 */
+static void gfar_set_user_ip(struct ethtool_usrip4_spec *value,
+ struct ethtool_usrip4_spec *mask, struct filer_table *tab)
+{
+ gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
+ gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
+ gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
+ gfar_set_attribute(value->proto, mask->proto, RQFCR_PID_L4P, tab);
+ gfar_set_attribute(value->l4_4_bytes, mask->l4_4_bytes, RQFCR_PID_ARB,
+ tab);
+
+}
+
+/* Translates value and mask for ETHER spec */
+static void gfar_set_ether(struct ethhdr *value, struct ethhdr *mask,
+ struct filer_table *tab)
+{
+ u32 upper_temp_mask = 0;
+ u32 lower_temp_mask = 0;
+ /* Source address */
+ if (!is_broadcast_ether_addr(mask->h_source)) {
+
+ if (is_zero_ether_addr(mask->h_source)) {
+ upper_temp_mask = 0xFFFFFFFF;
+ lower_temp_mask = 0xFFFFFFFF;
+ } else {
+ upper_temp_mask = mask->h_source[0] << 16
+ | mask->h_source[1] << 8
+ | mask->h_source[2];
+ lower_temp_mask = mask->h_source[3] << 16
+ | mask->h_source[4] << 8
+ | mask->h_source[5];
+ }
+ /* Upper 24bit */
+ gfar_set_attribute(
+ value->h_source[0] << 16 | value->h_source[1]
+ << 8 | value->h_source[2],
+ upper_temp_mask, RQFCR_PID_SAH, tab);
+ /* And the same for the lower part */
+ gfar_set_attribute(
+ value->h_source[3] << 16 | value->h_source[4]
+ << 8 | value->h_source[5],
+ lower_temp_mask, RQFCR_PID_SAL, tab);
+ }
+ /* Destination address */
+ if (!is_broadcast_ether_addr(mask->h_dest)) {
+
+ /* Special for destination is limited broadcast */
+ if ((is_broadcast_ether_addr(value->h_dest)
+ && is_zero_ether_addr(mask->h_dest))) {
+ gfar_set_parse_bits(RQFPR_EBC, RQFPR_EBC, tab);
+ } else {
+
+ if (is_zero_ether_addr(mask->h_dest)) {
+ upper_temp_mask = 0xFFFFFFFF;
+ lower_temp_mask = 0xFFFFFFFF;
+ } else {
+ upper_temp_mask = mask->h_dest[0] << 16
+ | mask->h_dest[1] << 8
+ | mask->h_dest[2];
+ lower_temp_mask = mask->h_dest[3] << 16
+ | mask->h_dest[4] << 8
+ | mask->h_dest[5];
+ }
+
+ /* Upper 24bit */
+ gfar_set_attribute(
+ value->h_dest[0] << 16
+ | value->h_dest[1] << 8
+ | value->h_dest[2],
+ upper_temp_mask, RQFCR_PID_DAH, tab);
+ /* And the same for the lower part */
+ gfar_set_attribute(
+ value->h_dest[3] << 16
+ | value->h_dest[4] << 8
+ | value->h_dest[5],
+ lower_temp_mask, RQFCR_PID_DAL, tab);
+ }
+ }
+
+ gfar_set_attribute(value->h_proto, mask->h_proto, RQFCR_PID_ETY, tab);
+
+}
+
+/* Convert a rule to binary filter format of gianfar */
+static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,
+ struct filer_table *tab)
+{
+ u32 vlan = 0, vlan_mask = 0;
+ u32 id = 0, id_mask = 0;
+ u32 cfi = 0, cfi_mask = 0;
+ u32 prio = 0, prio_mask = 0;
+
+ u32 old_index = tab->index;
+
+ /* Check if vlan is wanted */
+ if ((rule->flow_type & FLOW_EXT) && (rule->m_ext.vlan_tci != 0xFFFF)) {
+ if (!rule->m_ext.vlan_tci)
+ rule->m_ext.vlan_tci = 0xFFFF;
+
+ vlan = RQFPR_VLN;
+ vlan_mask = RQFPR_VLN;
+
+ /* Separate the fields */
+ id = rule->h_ext.vlan_tci & VLAN_VID_MASK;
+ id_mask = rule->m_ext.vlan_tci & VLAN_VID_MASK;
+ cfi = rule->h_ext.vlan_tci & VLAN_CFI_MASK;
+ cfi_mask = rule->m_ext.vlan_tci & VLAN_CFI_MASK;
+ prio = (rule->h_ext.vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+ prio_mask = (rule->m_ext.vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+
+ if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
+ vlan |= RQFPR_CFI;
+ vlan_mask |= RQFPR_CFI;
+ } else if (cfi != VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
+ vlan_mask |= RQFPR_CFI;
+ }
+ }
+
+ switch (rule->flow_type & ~FLOW_EXT) {
+ case TCP_V4_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_TCP | vlan,
+ RQFPR_IPV4 | RQFPR_TCP | vlan_mask, tab);
+ gfar_set_basic_ip(&rule->h_u.tcp_ip4_spec,
+ &rule->m_u.tcp_ip4_spec, tab);
+ break;
+ case UDP_V4_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_UDP | vlan,
+ RQFPR_IPV4 | RQFPR_UDP | vlan_mask, tab);
+ gfar_set_basic_ip(&rule->h_u.udp_ip4_spec,
+ &rule->m_u.udp_ip4_spec, tab);
+ break;
+ case SCTP_V4_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
+ tab);
+ gfar_set_attribute(132, 0, RQFCR_PID_L4P, tab);
+ gfar_set_basic_ip((struct ethtool_tcpip4_spec *) &rule->h_u,
+ (struct ethtool_tcpip4_spec *) &rule->m_u, tab);
+ break;
+ case IP_USER_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
+ tab);
+ gfar_set_user_ip((struct ethtool_usrip4_spec *) &rule->h_u,
+ (struct ethtool_usrip4_spec *) &rule->m_u, tab);
+ break;
+ case ETHER_FLOW:
+ if (vlan)
+ gfar_set_parse_bits(vlan, vlan_mask, tab);
+ gfar_set_ether((struct ethhdr *) &rule->h_u,
+ (struct ethhdr *) &rule->m_u, tab);
+ break;
+ default:
+ return -1;
+ }
+
+ /* Set the vlan attributes in the end */
+ if (vlan) {
+ gfar_set_attribute(id, id_mask, RQFCR_PID_VID, tab);
+ gfar_set_attribute(prio, prio_mask, RQFCR_PID_PRI, tab);
+ }
+
+ /* If there has been nothing written till now, it must be a default */
+ if (tab->index == old_index) {
+ gfar_set_mask(0xFFFFFFFF, tab);
+ tab->fe[tab->index].ctrl = 0x20;
+ tab->fe[tab->index].prop = 0x0;
+ tab->index++;
+ }
+
+ /* Remove last AND */
+ tab->fe[tab->index - 1].ctrl &= (~RQFCR_AND);
+
+ /* Specify which queue to use or to drop */
+ if (rule->ring_cookie == RX_CLS_FLOW_DISC)
+ tab->fe[tab->index - 1].ctrl |= RQFCR_RJE;
+ else
+ tab->fe[tab->index - 1].ctrl |= (rule->ring_cookie << 10);
+
+ /* Only big enough entries can be clustered */
+ if (tab->index > (old_index + 2)) {
+ tab->fe[old_index + 1].ctrl |= RQFCR_CLE;
+ tab->fe[tab->index - 1].ctrl |= RQFCR_CLE;
+ }
+
+ /* In rare cases the cache can be full while there is free space in hw */
+ if (tab->index > MAX_FILER_CACHE_IDX - 1)
+ return -EBUSY;
+
+ return 0;
+}
+
+/* Copy size filer entries */
+static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0],
+ struct gfar_filer_entry src[0], s32 size)
+{
+ while (size > 0) {
+ size--;
+ dst[size].ctrl = src[size].ctrl;
+ dst[size].prop = src[size].prop;
+ }
+}
+
+/* Delete the contents of the filer-table between start and end
+ * and collapse them */
+static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab)
+{
+ int length;
+ if (end > MAX_FILER_CACHE_IDX || end < begin)
+ return -EINVAL;
+
+ end++;
+ length = end - begin;
+
+ /* Copy */
+ while (end < tab->index) {
+ tab->fe[begin].ctrl = tab->fe[end].ctrl;
+ tab->fe[begin++].prop = tab->fe[end++].prop;
+
+ }
+ /* Fill up with don't cares */
+ while (begin < tab->index) {
+ tab->fe[begin].ctrl = 0x60;
+ tab->fe[begin].prop = 0xFFFFFFFF;
+ begin++;
+ }
+
+ tab->index -= length;
+ return 0;
+}
+
+/* Make space on the wanted location */
+static int gfar_expand_filer_entries(u32 begin, u32 length,
+ struct filer_table *tab)
+{
+ if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX || begin
+ > MAX_FILER_CACHE_IDX)
+ return -EINVAL;
+
+ gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]),
+ tab->index - length + 1);
+
+ tab->index += length;
+ return 0;
+}
+
+static int gfar_get_next_cluster_start(int start, struct filer_table *tab)
+{
+ for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) {
+ if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE))
+ == (RQFCR_AND | RQFCR_CLE))
+ return start;
+ }
+ return -1;
+}
+
+static int gfar_get_next_cluster_end(int start, struct filer_table *tab)
+{
+ for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) {
+ if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE))
+ == (RQFCR_CLE))
+ return start;
+ }
+ return -1;
+}
+
+/*
+ * Uses hardwares clustering option to reduce
+ * the number of filer table entries
+ */
+static void gfar_cluster_filer(struct filer_table *tab)
+{
+ s32 i = -1, j, iend, jend;
+
+ while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) {
+ j = i;
+ while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) {
+ /*
+ * The cluster entries self and the previous one
+ * (a mask) must be identical!
+ */
+ if (tab->fe[i].ctrl != tab->fe[j].ctrl)
+ break;
+ if (tab->fe[i].prop != tab->fe[j].prop)
+ break;
+ if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl)
+ break;
+ if (tab->fe[i - 1].prop != tab->fe[j - 1].prop)
+ break;
+ iend = gfar_get_next_cluster_end(i, tab);
+ jend = gfar_get_next_cluster_end(j, tab);
+ if (jend == -1 || iend == -1)
+ break;
+ /*
+ * First we make some free space, where our cluster
+ * element should be. Then we copy it there and finally
+ * delete in from its old location.
+ */
+
+ if (gfar_expand_filer_entries(iend, (jend - j), tab)
+ == -EINVAL)
+ break;
+
+ gfar_copy_filer_entries(&(tab->fe[iend + 1]),
+ &(tab->fe[jend + 1]), jend - j);
+
+ if (gfar_trim_filer_entries(jend - 1,
+ jend + (jend - j), tab) == -EINVAL)
+ return;
+
+ /* Mask out cluster bit */
+ tab->fe[iend].ctrl &= ~(RQFCR_CLE);
+ }
+ }
+}
+
+/* Swaps the masked bits of a1<>a2 and b1<>b2 */
+static void gfar_swap_bits(struct gfar_filer_entry *a1,
+ struct gfar_filer_entry *a2, struct gfar_filer_entry *b1,
+ struct gfar_filer_entry *b2, u32 mask)
+{
+ u32 temp[4];
+ temp[0] = a1->ctrl & mask;
+ temp[1] = a2->ctrl & mask;
+ temp[2] = b1->ctrl & mask;
+ temp[3] = b2->ctrl & mask;
+
+ a1->ctrl &= ~mask;
+ a2->ctrl &= ~mask;
+ b1->ctrl &= ~mask;
+ b2->ctrl &= ~mask;
+
+ a1->ctrl |= temp[1];
+ a2->ctrl |= temp[0];
+ b1->ctrl |= temp[3];
+ b2->ctrl |= temp[2];
+}
+
+/*
+ * Generate a list consisting of masks values with their start and
+ * end of validity and block as indicator for parts belonging
+ * together (glued by ANDs) in mask_table
+ */
+static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table,
+ struct filer_table *tab)
+{
+ u32 i, and_index = 0, block_index = 1;
+
+ for (i = 0; i < tab->index; i++) {
+
+ /* LSByte of control = 0 sets a mask */
+ if (!(tab->fe[i].ctrl & 0xF)) {
+ mask_table[and_index].mask = tab->fe[i].prop;
+ mask_table[and_index].start = i;
+ mask_table[and_index].block = block_index;
+ if (and_index >= 1)
+ mask_table[and_index - 1].end = i - 1;
+ and_index++;
+ }
+ /* cluster starts and ends will be separated because they should
+ * hold their position */
+ if (tab->fe[i].ctrl & RQFCR_CLE)
+ block_index++;
+ /* A not set AND indicates the end of a depended block */
+ if (!(tab->fe[i].ctrl & RQFCR_AND))
+ block_index++;
+
+ }
+
+ mask_table[and_index - 1].end = i - 1;
+
+ return and_index;
+}
+
+/*
+ * Sorts the entries of mask_table by the values of the masks.
+ * Important: The 0xFF80 flags of the first and last entry of a
+ * block must hold their position (which queue, CLusterEnable, ReJEct,
+ * AND)
+ */
+static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table,
+ struct filer_table *temp_table, u32 and_index)
+{
+ /* Pointer to compare function (_asc or _desc) */
+ int (*gfar_comp)(const void *, const void *);
+
+ u32 i, size = 0, start = 0, prev = 1;
+ u32 old_first, old_last, new_first, new_last;
+
+ gfar_comp = &gfar_comp_desc;
+
+ for (i = 0; i < and_index; i++) {
+
+ if (prev != mask_table[i].block) {
+ old_first = mask_table[start].start + 1;
+ old_last = mask_table[i - 1].end;
+ sort(mask_table + start, size,
+ sizeof(struct gfar_mask_entry),
+ gfar_comp, &gfar_swap);
+
+ /* Toggle order for every block. This makes the
+ * thing more efficient! */
+ if (gfar_comp == gfar_comp_desc)
+ gfar_comp = &gfar_comp_asc;
+ else
+ gfar_comp = &gfar_comp_desc;
+
+ new_first = mask_table[start].start + 1;
+ new_last = mask_table[i - 1].end;
+
+ gfar_swap_bits(&temp_table->fe[new_first],
+ &temp_table->fe[old_first],
+ &temp_table->fe[new_last],
+ &temp_table->fe[old_last],
+ RQFCR_QUEUE | RQFCR_CLE |
+ RQFCR_RJE | RQFCR_AND
+ );
+
+ start = i;
+ size = 0;
+ }
+ size++;
+ prev = mask_table[i].block;
+ }
+
+}
+
+/*
+ * Reduces the number of masks needed in the filer table to save entries
+ * This is done by sorting the masks of a depended block. A depended block is
+ * identified by gluing ANDs or CLE. The sorting order toggles after every
+ * block. Of course entries in scope of a mask must change their location with
+ * it.
+ */
+static int gfar_optimize_filer_masks(struct filer_table *tab)
+{
+ struct filer_table *temp_table;
+ struct gfar_mask_entry *mask_table;
+
+ u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0;
+ s32 ret = 0;
+
+ /* We need a copy of the filer table because
+ * we want to change its order */
+ temp_table = kmalloc(sizeof(*temp_table), GFP_KERNEL);
+ if (temp_table == NULL)
+ return -ENOMEM;
+ memcpy(temp_table, tab, sizeof(*temp_table));
+
+ mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1,
+ sizeof(struct gfar_mask_entry), GFP_KERNEL);
+
+ if (mask_table == NULL) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ and_index = gfar_generate_mask_table(mask_table, tab);
+
+ gfar_sort_mask_table(mask_table, temp_table, and_index);
+
+ /* Now we can copy the data from our duplicated filer table to
+ * the real one in the order the mask table says */
+ for (i = 0; i < and_index; i++) {
+ size = mask_table[i].end - mask_table[i].start + 1;
+ gfar_copy_filer_entries(&(tab->fe[j]),
+ &(temp_table->fe[mask_table[i].start]), size);
+ j += size;
+ }
+
+ /* And finally we just have to check for duplicated masks and drop the
+ * second ones */
+ for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
+ if (tab->fe[i].ctrl == 0x80) {
+ previous_mask = i++;
+ break;
+ }
+ }
+ for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
+ if (tab->fe[i].ctrl == 0x80) {
+ if (tab->fe[i].prop == tab->fe[previous_mask].prop) {
+ /* Two identical ones found!
+ * So drop the second one! */
+ gfar_trim_filer_entries(i, i, tab);
+ } else
+ /* Not identical! */
+ previous_mask = i;
+ }
+ }
+
+ kfree(mask_table);
+end: kfree(temp_table);
+ return ret;
+}
+
+/* Write the bit-pattern from software's buffer to hardware registers */
+static int gfar_write_filer_table(struct gfar_private *priv,
+ struct filer_table *tab)
+{
+ u32 i = 0;
+ if (tab->index > MAX_FILER_IDX - 1)
+ return -EBUSY;
+
+ /* Avoid inconsistent filer table to be processed */
+ lock_rx_qs(priv);
+
+ /* Fill regular entries */
+ for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl); i++)
+ gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);
+ /* Fill the rest with fall-troughs */
+ for (; i < MAX_FILER_IDX - 1; i++)
+ gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF);
+ /* Last entry must be default accept
+ * because that's what people expect */
+ gfar_write_filer(priv, i, 0x20, 0x0);
+
+ unlock_rx_qs(priv);
+
+ return 0;
+}
+
+static int gfar_check_capability(struct ethtool_rx_flow_spec *flow,
+ struct gfar_private *priv)
+{
+
+ if (flow->flow_type & FLOW_EXT) {
+ if (~flow->m_ext.data[0] || ~flow->m_ext.data[1])
+ netdev_warn(priv->ndev,
+ "User-specific data not supported!\n");
+ if (~flow->m_ext.vlan_etype)
+ netdev_warn(priv->ndev,
+ "VLAN-etype not supported!\n");
+ }
+ if (flow->flow_type == IP_USER_FLOW)
+ if (flow->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4)
+ netdev_warn(priv->ndev,
+ "IP-Version differing from IPv4 not supported!\n");
+
+ return 0;
+}
+
+static int gfar_process_filer_changes(struct gfar_private *priv)
+{
+ struct ethtool_flow_spec_container *j;
+ struct filer_table *tab;
+ s32 i = 0;
+ s32 ret = 0;
+
+ /* So index is set to zero, too! */
+ tab = kzalloc(sizeof(*tab), GFP_KERNEL);
+ if (tab == NULL)
+ return -ENOMEM;
+
+ /* Now convert the existing filer data from flow_spec into
+ * filer tables binary format */
+ list_for_each_entry(j, &priv->rx_list.list, list) {
+ ret = gfar_convert_to_filer(&j->fs, tab);
+ if (ret == -EBUSY) {
+ netdev_err(priv->ndev, "Rule not added: No free space!\n");
+ goto end;
+ }
+ if (ret == -1) {
+ netdev_err(priv->ndev, "Rule not added: Unsupported Flow-type!\n");
+ goto end;
+ }
+ }
+
+ i = tab->index;
+
+ /* Optimizations to save entries */
+ gfar_cluster_filer(tab);
+ gfar_optimize_filer_masks(tab);
+
+ pr_debug("\n\tSummary:\n"
+ "\tData on hardware: %d\n"
+ "\tCompression rate: %d%%\n",
+ tab->index, 100 - (100 * tab->index) / i);
+
+ /* Write everything to hardware */
+ ret = gfar_write_filer_table(priv, tab);
+ if (ret == -EBUSY) {
+ netdev_err(priv->ndev, "Rule not added: No free space!\n");
+ goto end;
+ }
+
+end: kfree(tab);
+ return ret;
+}
+
+static void gfar_invert_masks(struct ethtool_rx_flow_spec *flow)
+{
+ u32 i = 0;
+
+ for (i = 0; i < sizeof(flow->m_u); i++)
+ flow->m_u.hdata[i] ^= 0xFF;
+
+ flow->m_ext.vlan_etype ^= 0xFFFF;
+ flow->m_ext.vlan_tci ^= 0xFFFF;
+ flow->m_ext.data[0] ^= ~0;
+ flow->m_ext.data[1] ^= ~0;
+}
+
+static int gfar_add_cls(struct gfar_private *priv,
+ struct ethtool_rx_flow_spec *flow)
+{
+ struct ethtool_flow_spec_container *temp, *comp;
+ int ret = 0;
+
+ temp = kmalloc(sizeof(*temp), GFP_KERNEL);
+ if (temp == NULL)
+ return -ENOMEM;
+ memcpy(&temp->fs, flow, sizeof(temp->fs));
+
+ gfar_invert_masks(&temp->fs);
+ ret = gfar_check_capability(&temp->fs, priv);
+ if (ret)
+ goto clean_mem;
+ /* Link in the new element at the right @location */
+ if (list_empty(&priv->rx_list.list)) {
+ ret = gfar_check_filer_hardware(priv);
+ if (ret != 0)
+ goto clean_mem;
+ list_add(&temp->list, &priv->rx_list.list);
+ goto process;
+ } else {
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (comp->fs.location > flow->location) {
+ list_add_tail(&temp->list, &comp->list);
+ goto process;
+ }
+ if (comp->fs.location == flow->location) {
+ netdev_err(priv->ndev,
+ "Rule not added: ID %d not free!\n",
+ flow->location);
+ ret = -EBUSY;
+ goto clean_mem;
+ }
+ }
+ list_add_tail(&temp->list, &priv->rx_list.list);
+ }
+
+process:
+ ret = gfar_process_filer_changes(priv);
+ if (ret)
+ goto clean_list;
+ priv->rx_list.count++;
+ return ret;
+
+clean_list:
+ list_del(&temp->list);
+clean_mem:
+ kfree(temp);
+ return ret;
+}
+
+static int gfar_del_cls(struct gfar_private *priv, u32 loc)
+{
+ struct ethtool_flow_spec_container *comp;
+ u32 ret = -EINVAL;
+
+ if (list_empty(&priv->rx_list.list))
+ return ret;
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (comp->fs.location == loc) {
+ list_del(&comp->list);
+ kfree(comp);
+ priv->rx_list.count--;
+ gfar_process_filer_changes(priv);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+
+}
+
+static int gfar_get_cls(struct gfar_private *priv, struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_flow_spec_container *comp;
+ u32 ret = -EINVAL;
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (comp->fs.location == cmd->fs.location) {
+ memcpy(&cmd->fs, &comp->fs, sizeof(cmd->fs));
+ gfar_invert_masks(&cmd->fs);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int gfar_get_cls_all(struct gfar_private *priv,
+ struct ethtool_rxnfc *cmd, u32 *rule_locs)
+{
+ struct ethtool_flow_spec_container *comp;
+ u32 i = 0;
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (i <= cmd->rule_cnt) {
+ rule_locs[i] = comp->fs.location;
+ i++;
+ }
+ }
+
+ cmd->data = MAX_FILER_IDX;
+
+ return 0;
+}
+
static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
{
struct gfar_private *priv = netdev_priv(dev);
int ret = 0;
- switch(cmd->cmd) {
+ mutex_lock(&priv->rx_queue_access);
+
+ switch (cmd->cmd) {
case ETHTOOL_SRXFH:
ret = gfar_set_hash_opts(priv, cmd);
break;
+ case ETHTOOL_SRXCLSRLINS:
+ if (cmd->fs.ring_cookie != RX_CLS_FLOW_DISC &&
+ cmd->fs.ring_cookie >= priv->num_rx_queues) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = gfar_add_cls(priv, &cmd->fs);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ ret = gfar_del_cls(priv, cmd->fs.location);
+ break;
default:
ret = -EINVAL;
}
+ mutex_unlock(&priv->rx_queue_access);
+
+ return ret;
+}
+
+static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ void *rule_locs)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ int ret = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = priv->num_rx_queues;
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = priv->rx_list.count;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ ret = gfar_get_cls(priv, cmd);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ ret = gfar_get_cls_all(priv, cmd, (u32 *) rule_locs);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
return ret;
}
@@ -810,4 +1743,5 @@ const struct ethtool_ops gfar_ethtool_ops = {
.set_wol = gfar_set_wol,
#endif
.set_rxnfc = gfar_set_nfc,
+ .get_rxnfc = gfar_get_nfc,
};
diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/gianfar_ptp.c
index d8e175382d1d..1c97861596f0 100644
--- a/drivers/net/gianfar_ptp.c
+++ b/drivers/net/gianfar_ptp.c
@@ -491,7 +491,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
spin_lock_init(&etsects->lock);
etsects->regs = ioremap(etsects->rsrc->start,
- 1 + etsects->rsrc->end - etsects->rsrc->start);
+ resource_size(etsects->rsrc));
if (!etsects->regs) {
pr_err("ioremap ptp registers failed\n");
goto no_ioremap;
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index 672f096fe090..16ce45c11934 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -22,9 +22,11 @@
* Marko Isomaki
*/
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index a09041aa8509..c274b3d77eb5 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -648,13 +648,13 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_cleardev;
- hmp->tx_ring = (struct hamachi_desc *)ring_space;
+ hmp->tx_ring = ring_space;
hmp->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- hmp->rx_ring = (struct hamachi_desc *)ring_space;
+ hmp->rx_ring = ring_space;
hmp->rx_ring_dma = ring_dma;
/* Check for options being passed in */
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 0d283781bc5e..2a5a34d2d67b 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -36,7 +36,7 @@
#include <linux/tcp.h>
#include <linux/semaphore.h>
#include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#define SIXPACK_VERSION "Revision: 0.3.0"
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 99cdce33df8b..a974727dd9a2 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -76,6 +76,7 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
#include <linux/jiffies.h>
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index d92fe6ca788f..e349d867449b 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -66,6 +66,7 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/hdlcdrv.h>
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 52b14256e2c0..ce555d9ac02c 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -36,7 +36,7 @@
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 82bffc3cabdf..29917363ebfb 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -30,6 +30,7 @@ static const char version[] =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/system.h>
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index ef2014375e62..18564d4a7c04 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -30,6 +30,7 @@ static const char version[] =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/system.h>
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index c3ecb118c1df..b6519c1ba7e1 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2103,20 +2103,18 @@ static void hp100_set_multicast_list(struct net_device *dev)
#endif
netdev_for_each_mc_addr(ha, dev) {
addrs = ha->addr;
- if ((*addrs & 0x01) == 0x01) { /* multicast address? */
#ifdef HP100_DEBUG
- printk("hp100: %s: multicast = %pM, ",
- dev->name, addrs);
+ printk("hp100: %s: multicast = %pM, ",
+ dev->name, addrs);
#endif
- for (i = idx = 0; i < 6; i++) {
- idx ^= *addrs++ & 0x3f;
- printk(":%02x:", idx);
- }
+ for (i = idx = 0; i < 6; i++) {
+ idx ^= *addrs++ & 0x3f;
+ printk(":%02x:", idx);
+ }
#ifdef HP100_DEBUG
- printk("idx = %i\n", idx);
+ printk("idx = %i\n", idx);
#endif
- lp->hash_bytes[idx >> 3] |= (1 << (idx & 7));
- }
+ lp->hash_bytes[idx >> 3] |= (1 << (idx & 7));
}
}
#else
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 079450fe5e96..725399ea0690 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2770,7 +2770,7 @@ static int __devinit emac_probe(struct platform_device *ofdev)
}
// TODO : request_mem_region
dev->emacp = ioremap(dev->rsrc_regs.start,
- dev->rsrc_regs.end - dev->rsrc_regs.start + 1);
+ resource_size(&dev->rsrc_regs));
if (dev->emacp == NULL) {
printk(KERN_ERR "%s: Can't map device registers!\n",
np->full_name);
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index b388d782c7c4..ba99af05bf62 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -34,6 +34,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/pm.h>
#include <linux/ethtool.h>
@@ -42,7 +43,7 @@
#include <linux/ipv6.h>
#include <linux/slab.h>
#include <asm/hvcall.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/vio.h>
#include <asm/iommu.h>
#include <asm/firmware.h>
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 4fecaed67fc4..6e82dd32e806 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -32,6 +32,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <net/pkt_sched.h>
#include <net/net_namespace.h>
@@ -40,8 +41,16 @@
struct ifb_private {
struct tasklet_struct ifb_tasklet;
int tasklet_pending;
+
+ struct u64_stats_sync rsync;
struct sk_buff_head rq;
+ u64 rx_packets;
+ u64 rx_bytes;
+
+ struct u64_stats_sync tsync;
struct sk_buff_head tq;
+ u64 tx_packets;
+ u64 tx_bytes;
};
static int numifbs = 2;
@@ -53,10 +62,8 @@ static int ifb_close(struct net_device *dev);
static void ri_tasklet(unsigned long dev)
{
-
struct net_device *_dev = (struct net_device *)dev;
struct ifb_private *dp = netdev_priv(_dev);
- struct net_device_stats *stats = &_dev->stats;
struct netdev_queue *txq;
struct sk_buff *skb;
@@ -76,15 +83,18 @@ static void ri_tasklet(unsigned long dev)
skb->tc_verd = 0;
skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
- stats->tx_packets++;
- stats->tx_bytes +=skb->len;
+
+ u64_stats_update_begin(&dp->tsync);
+ dp->tx_packets++;
+ dp->tx_bytes += skb->len;
+ u64_stats_update_end(&dp->tsync);
rcu_read_lock();
skb->dev = dev_get_by_index_rcu(&init_net, skb->skb_iif);
if (!skb->dev) {
rcu_read_unlock();
dev_kfree_skb(skb);
- stats->tx_dropped++;
+ _dev->stats.tx_dropped++;
if (skb_queue_len(&dp->tq) != 0)
goto resched;
break;
@@ -119,9 +129,37 @@ resched:
}
+static struct rtnl_link_stats64 *ifb_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&dp->rsync);
+ stats->rx_packets = dp->rx_packets;
+ stats->rx_bytes = dp->rx_bytes;
+ } while (u64_stats_fetch_retry_bh(&dp->rsync, start));
+
+ do {
+ start = u64_stats_fetch_begin_bh(&dp->tsync);
+
+ stats->tx_packets = dp->tx_packets;
+ stats->tx_bytes = dp->tx_bytes;
+
+ } while (u64_stats_fetch_retry_bh(&dp->tsync, start));
+
+ stats->rx_dropped = dev->stats.rx_dropped;
+ stats->tx_dropped = dev->stats.tx_dropped;
+
+ return stats;
+}
+
+
static const struct net_device_ops ifb_netdev_ops = {
.ndo_open = ifb_open,
.ndo_stop = ifb_close,
+ .ndo_get_stats64 = ifb_stats64,
.ndo_start_xmit = ifb_xmit,
.ndo_validate_addr = eth_validate_addr,
};
@@ -152,15 +190,16 @@ static void ifb_setup(struct net_device *dev)
static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ifb_private *dp = netdev_priv(dev);
- struct net_device_stats *stats = &dev->stats;
u32 from = G_TC_FROM(skb->tc_verd);
- stats->rx_packets++;
- stats->rx_bytes+=skb->len;
+ u64_stats_update_begin(&dp->rsync);
+ dp->rx_packets++;
+ dp->rx_bytes += skb->len;
+ u64_stats_update_end(&dp->rsync);
if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->skb_iif) {
dev_kfree_skb(skb);
- stats->rx_dropped++;
+ dev->stats.rx_dropped++;
return NETDEV_TX_OK;
}
diff --git a/drivers/net/igb/Makefile b/drivers/net/igb/Makefile
index 8372cb9a8c1a..c6e4621b6262 100644
--- a/drivers/net/igb/Makefile
+++ b/drivers/net/igb/Makefile
@@ -1,7 +1,7 @@
################################################################################
#
# Intel 82575 PCI-Express Ethernet Linux driver
-# Copyright(c) 1999 - 2009 Intel Corporation.
+# Copyright(c) 1999 - 2011 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 0f563c8c5ffc..c0857bdfb03a 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -1156,10 +1156,13 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
{
u32 ctrl_ext, ctrl_reg, reg;
bool pcs_autoneg;
+ s32 ret_val = E1000_SUCCESS;
+ u16 data;
if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
!igb_sgmii_active_82575(hw))
- return 0;
+ return ret_val;
+
/*
* On the 82575, SerDes loopback mode persists until it is
@@ -1203,6 +1206,18 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
/* disable PCS autoneg and support parallel detect only */
pcs_autoneg = false;
default:
+ if (hw->mac.type == e1000_82575 ||
+ hw->mac.type == e1000_82576) {
+ ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
+ if (ret_val) {
+ printk(KERN_DEBUG "NVM Read Error\n\n");
+ return ret_val;
+ }
+
+ if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT)
+ pcs_autoneg = false;
+ }
+
/*
* non-SGMII modes only supports a speed of 1000/Full for the
* link so it is best to just force the MAC and let the pcs
@@ -1250,7 +1265,7 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
if (!igb_sgmii_active_82575(hw))
igb_force_mac_fc(hw);
- return 0;
+ return ret_val;
}
/**
@@ -1735,6 +1750,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
ctrl |= E1000_CTRL_RST;
wr32(E1000_CTRL, ctrl);
+ wrfl();
/* Add delay to insure DEV_RST has time to complete */
if (global_device_reset)
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index dd6df3498998..786e110011a3 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -243,6 +243,8 @@ struct e1000_adv_tx_context_desc {
#define E1000_DTXCTL_MDP_EN 0x0020
#define E1000_DTXCTL_SPOOF_INT 0x0040
+#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT (1 << 14)
+
#define ALL_QUEUES 0xFFFF
/* RX packet buffer size defines */
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 6b80d40110ca..7b8ddd830f19 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -437,6 +437,7 @@
#define E1000_RAH_POOL_1 0x00040000
/* Error Codes */
+#define E1000_SUCCESS 0
#define E1000_ERR_NVM 1
#define E1000_ERR_PHY 2
#define E1000_ERR_CONFIG 3
@@ -511,6 +512,16 @@
#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000
#define E1000_GCR_CAP_VER2 0x00040000
+/* mPHY Address Control and Data Registers */
+#define E1000_MPHY_ADDR_CTL 0x0024 /* mPHY Address Control Register */
+#define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000
+#define E1000_MPHY_DATA 0x0E10 /* mPHY Data Register */
+
+/* mPHY PCS CLK Register */
+#define E1000_MPHY_PCS_CLK_REG_OFFSET 0x0004 /* mPHY PCS CLK AFE CSR Offset */
+/* mPHY Near End Digital Loopback Override Bit */
+#define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10
+
/* PHY Control Register */
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
@@ -587,8 +598,8 @@
#define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */
/* NVM Word Offsets */
-#define NVM_ID_LED_SETTINGS 0x0004
-/* For SERDES output amplitude adjustment. */
+#define NVM_COMPAT 0x0003
+#define NVM_ID_LED_SETTINGS 0x0004 /* SERDES output amplitude */
#define NVM_INIT_CONTROL2_REG 0x000F
#define NVM_INIT_CONTROL3_PORT_B 0x0014
#define NVM_INIT_CONTROL3_PORT_A 0x0024
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index 27153e8d7b16..4519a1367170 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
index ce8255fc3c52..2b5ef761d2ab 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/igb/e1000_mac.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include "e1000_mac.h"
@@ -217,7 +218,7 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw)
}
/* if multicast bit is set, the alternate address will not be used */
- if (alt_mac_addr[0] & 0x01) {
+ if (is_multicast_ether_addr(alt_mac_addr)) {
hw_dbg("Ignoring Alternate Mac Address with MC bit set\n");
goto out;
}
diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h
index 601be99711c2..4927f61fbbc8 100644
--- a/drivers/net/igb/e1000_mac.h
+++ b/drivers/net/igb/e1000_mac.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c
index 78d48c7fa859..74f2f11ac290 100644
--- a/drivers/net/igb/e1000_mbx.c
+++ b/drivers/net/igb/e1000_mbx.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_mbx.h b/drivers/net/igb/e1000_mbx.h
index bb112fb6c3a1..eddb0f83dcea 100644
--- a/drivers/net/igb/e1000_mbx.h
+++ b/drivers/net/igb/e1000_mbx.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c
index 75bf36a4baee..7dcd65cede56 100644
--- a/drivers/net/igb/e1000_nvm.c
+++ b/drivers/net/igb/e1000_nvm.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/igb/e1000_nvm.h
index 7f43564c4bcc..a2a7ca9fa733 100644
--- a/drivers/net/igb/e1000_nvm.h
+++ b/drivers/net/igb/e1000_nvm.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007 Intel Corporation.
+ Copyright(c) 2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index d639706eb3f6..e662554c62d6 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h
index 2cc117705a31..8510797b9d81 100644
--- a/drivers/net/igb/e1000_phy.h
+++ b/drivers/net/igb/e1000_phy.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 958ca3bda482..0990f6d860c7 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index f4fa4b1751cf..265e151b66c4 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -37,6 +37,8 @@
#include <linux/clocksource.h>
#include <linux/timecompare.h>
#include <linux/net_tstamp.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
struct igb_adapter;
@@ -252,7 +254,7 @@ static inline int igb_desc_unused(struct igb_ring *ring)
struct igb_adapter {
struct timer_list watchdog_timer;
struct timer_list phy_info_timer;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 mng_vlan_id;
u32 bd_number;
u32 wol;
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index fdc895e5a3f8..ff244ce803ce 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -318,65 +318,6 @@ static int igb_set_pauseparam(struct net_device *netdev,
return retval;
}
-static u32 igb_get_rx_csum(struct net_device *netdev)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
- return !!(adapter->rx_ring[0]->flags & IGB_RING_FLAG_RX_CSUM);
-}
-
-static int igb_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
- int i;
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- if (data)
- adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
- else
- adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
- }
-
- return 0;
-}
-
-static u32 igb_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int igb_set_tx_csum(struct net_device *netdev, u32 data)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
-
- if (data) {
- netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- if (adapter->hw.mac.type >= e1000_82576)
- netdev->features |= NETIF_F_SCTP_CSUM;
- } else {
- netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_SCTP_CSUM);
- }
-
- return 0;
-}
-
-static int igb_set_tso(struct net_device *netdev, u32 data)
-{
- struct igb_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 igb_get_msglevel(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
@@ -1520,6 +1461,22 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter)
/* use CTRL_EXT to identify link type as SGMII can appear as copper */
if (reg & E1000_CTRL_EXT_LINK_MODE_MASK) {
+ if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) ||
+ (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) ||
+ (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) ||
+ (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) {
+
+ /* Enable DH89xxCC MPHY for near end loopback */
+ reg = rd32(E1000_MPHY_ADDR_CTL);
+ reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) |
+ E1000_MPHY_PCS_CLK_REG_OFFSET;
+ wr32(E1000_MPHY_ADDR_CTL, reg);
+
+ reg = rd32(E1000_MPHY_DATA);
+ reg |= E1000_MPHY_PCS_CLK_REG_DIGINELBEN;
+ wr32(E1000_MPHY_DATA, reg);
+ }
+
reg = rd32(E1000_RCTL);
reg |= E1000_RCTL_LBM_TCVR;
wr32(E1000_RCTL, reg);
@@ -1561,6 +1518,23 @@ static void igb_loopback_cleanup(struct igb_adapter *adapter)
u32 rctl;
u16 phy_reg;
+ if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) ||
+ (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) ||
+ (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) ||
+ (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) {
+ u32 reg;
+
+ /* Disable near end loopback on DH89xxCC */
+ reg = rd32(E1000_MPHY_ADDR_CTL);
+ reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) |
+ E1000_MPHY_PCS_CLK_REG_OFFSET;
+ wr32(E1000_MPHY_ADDR_CTL, reg);
+
+ reg = rd32(E1000_MPHY_DATA);
+ reg &= ~E1000_MPHY_PCS_CLK_REG_DIGINELBEN;
+ wr32(E1000_MPHY_DATA, reg);
+ }
+
rctl = rd32(E1000_RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
wr32(E1000_RCTL, rctl);
@@ -2207,14 +2181,6 @@ static const struct ethtool_ops igb_ethtool_ops = {
.set_ringparam = igb_set_ringparam,
.get_pauseparam = igb_get_pauseparam,
.set_pauseparam = igb_set_pauseparam,
- .get_rx_csum = igb_get_rx_csum,
- .set_rx_csum = igb_set_rx_csum,
- .get_tx_csum = igb_get_tx_csum,
- .set_tx_csum = igb_set_tx_csum,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
- .get_tso = ethtool_op_get_tso,
- .set_tso = igb_set_tso,
.self_test = igb_diag_test,
.get_strings = igb_get_strings,
.set_phys_id = igb_set_phys_id,
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 2c28621eb30b..dc599059512a 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2009 Intel Corporation.
+ Copyright(c) 2007-2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -28,6 +28,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/bitops.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/netdevice.h>
@@ -54,9 +55,8 @@
#define MAJ 3
#define MIN 0
#define BUILD 6
-#define KFIX 2
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
-__stringify(BUILD) "-k" __stringify(KFIX)
+__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
char igb_driver_version[] = DRV_VERSION;
static const char igb_driver_string[] =
@@ -141,7 +141,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, 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 *);
-static void igb_vlan_rx_register(struct net_device *, struct vlan_group *);
+static void igb_vlan_mode(struct net_device *netdev, u32 features);
static void igb_vlan_rx_add_vid(struct net_device *, u16);
static void igb_vlan_rx_kill_vid(struct net_device *, u16);
static void igb_restore_vlan(struct igb_adapter *);
@@ -1363,7 +1363,7 @@ static void igb_update_mng_vlan(struct igb_adapter *adapter)
if ((old_vid != (u16)IGB_MNG_VLAN_NONE) &&
(vid != old_vid) &&
- !vlan_group_get_device(adapter->vlgrp, old_vid)) {
+ !test_bit(old_vid, adapter->active_vlans)) {
/* remove VID from filter table */
igb_vfta_set(hw, old_vid, false);
}
@@ -1749,6 +1749,39 @@ void igb_reset(struct igb_adapter *adapter)
igb_get_phy_info(hw);
}
+static u32 igb_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return 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);
+
+ return 0;
+}
+
static const struct net_device_ops igb_netdev_ops = {
.ndo_open = igb_open,
.ndo_stop = igb_close,
@@ -1761,7 +1794,6 @@ static const struct net_device_ops igb_netdev_ops = {
.ndo_do_ioctl = igb_ioctl,
.ndo_tx_timeout = igb_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_vlan_rx_register = igb_vlan_rx_register,
.ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid,
.ndo_set_vf_mac = igb_ndo_set_vf_mac,
@@ -1771,6 +1803,8 @@ static const struct net_device_ops igb_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = igb_netpoll,
#endif
+ .ndo_fix_features = igb_fix_features,
+ .ndo_set_features = igb_set_features,
};
/**
@@ -1910,17 +1944,18 @@ static int __devinit igb_probe(struct pci_dev *pdev,
dev_info(&pdev->dev,
"PHY reset is blocked due to SOL/IDER session.\n");
- 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 |
+ NETIF_F_HW_VLAN_RX;
+
+ 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;
@@ -1932,8 +1967,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_HIGHDMA;
}
- if (hw->mac.type >= e1000_82576)
+ if (hw->mac.type >= e1000_82576) {
+ netdev->hw_features |= NETIF_F_SCTP_CSUM;
netdev->features |= NETIF_F_SCTP_CSUM;
+ }
adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
@@ -2039,6 +2076,8 @@ 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);
@@ -2921,12 +2960,11 @@ 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 = adapter->max_frame_size;
+ u32 max_frame_size;
struct e1000_hw *hw = &adapter->hw;
u16 pf_id = adapter->vfs_allocated_count;
- if (adapter->vlgrp)
- max_frame_size += VLAN_TAG_SIZE;
+ 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 */
@@ -5675,25 +5713,6 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
return count < tx_ring->count;
}
-/**
- * igb_receive_skb - helper function to handle rx indications
- * @q_vector: structure containing interrupt and ring information
- * @skb: packet to send up
- * @vlan_tag: vlan tag for packet
- **/
-static void igb_receive_skb(struct igb_q_vector *q_vector,
- struct sk_buff *skb,
- u16 vlan_tag)
-{
- struct igb_adapter *adapter = q_vector->adapter;
-
- if (vlan_tag && adapter->vlgrp)
- vlan_gro_receive(&q_vector->napi, adapter->vlgrp,
- vlan_tag, skb);
- else
- napi_gro_receive(&q_vector->napi, skb);
-}
-
static inline void igb_rx_checksum_adv(struct igb_ring *ring,
u32 status_err, struct sk_buff *skb)
{
@@ -5791,7 +5810,6 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
unsigned int i;
u32 staterr;
u16 length;
- u16 vlan_tag;
i = rx_ring->next_to_clean;
buffer_info = &rx_ring->buffer_info[i];
@@ -5876,10 +5894,12 @@ send_up:
skb->protocol = eth_type_trans(skb, netdev);
skb_record_rx_queue(skb, rx_ring->queue_index);
- vlan_tag = ((staterr & E1000_RXD_STAT_VP) ?
- le16_to_cpu(rx_desc->wb.upper.vlan) : 0);
+ if (staterr & E1000_RXD_STAT_VP) {
+ u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan);
- igb_receive_skb(q_vector, skb, vlan_tag);
+ __vlan_hwaccel_put_tag(skb, vid);
+ }
+ napi_gro_receive(&q_vector->napi, skb);
next_desc:
rx_desc->wb.upper.status_error = 0;
@@ -6249,7 +6269,7 @@ s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
struct igb_adapter *adapter = hw->back;
u16 cap_offset;
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ cap_offset = adapter->pdev->pcie_cap;
if (!cap_offset)
return -E1000_ERR_CONFIG;
@@ -6263,7 +6283,7 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
struct igb_adapter *adapter = hw->back;
u16 cap_offset;
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ cap_offset = adapter->pdev->pcie_cap;
if (!cap_offset)
return -E1000_ERR_CONFIG;
@@ -6272,17 +6292,15 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
return 0;
}
-static void igb_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+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;
igb_irq_disable(adapter);
- adapter->vlgrp = grp;
- if (grp) {
+ if (features & NETIF_F_HW_VLAN_RX) {
/* enable VLAN tag insert/strip */
ctrl = rd32(E1000_CTRL);
ctrl |= E1000_CTRL_VME;
@@ -6316,6 +6334,8 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
/* add the filter since PF can receive vlans w/o entry in vlvf */
igb_vfta_set(hw, vid, true);
+
+ set_bit(vid, adapter->active_vlans);
}
static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -6326,7 +6346,6 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
s32 err;
igb_irq_disable(adapter);
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
if (!test_bit(__IGB_DOWN, &adapter->state))
igb_irq_enable(adapter);
@@ -6337,20 +6356,16 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
/* if vid was not present in VLVF just remove it from table */
if (err)
igb_vfta_set(hw, vid, false);
+
+ clear_bit(vid, adapter->active_vlans);
}
static void igb_restore_vlan(struct igb_adapter *adapter)
{
- igb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ u16 vid;
- if (adapter->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
- igb_vlan_rx_add_vid(adapter->netdev, vid);
- }
- }
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ igb_vlan_rx_add_vid(adapter->netdev, vid);
}
int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx)
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h
index d5dad5d607d6..fd4a7b780fdd 100644
--- a/drivers/net/igbvf/igbvf.h
+++ b/drivers/net/igbvf/igbvf.h
@@ -34,7 +34,7 @@
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/netdevice.h>
-
+#include <linux/if_vlan.h>
#include "vf.h"
@@ -173,7 +173,7 @@ struct igbvf_adapter {
const struct igbvf_info *ei;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u32 bd_number;
u32 rx_buffer_len;
u32 polling_interval;
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 1c77fb3bf4ae..1330c8e932da 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -45,7 +45,7 @@
#include "igbvf.h"
-#define DRV_VERSION "1.0.8-k0"
+#define DRV_VERSION "2.0.0-k"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
static const char igbvf_driver_string[] =
@@ -100,12 +100,12 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
struct sk_buff *skb,
u32 status, u16 vlan)
{
- if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(vlan) &
- E1000_RXD_SPC_VLAN_MASK);
- else
- netif_receive_skb(skb);
+ if (status & E1000_RXD_STAT_VP) {
+ u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+
+ __vlan_hwaccel_put_tag(skb, vid);
+ }
+ netif_receive_skb(skb);
}
static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
@@ -1167,12 +1167,10 @@ static int igbvf_poll(struct napi_struct *napi, int budget)
*/
static void igbvf_set_rlpml(struct igbvf_adapter *adapter)
{
- int max_frame_size = adapter->max_frame_size;
+ int max_frame_size;
struct e1000_hw *hw = &adapter->hw;
- if (adapter->vlgrp)
- max_frame_size += VLAN_TAG_SIZE;
-
+ max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE;
e1000_rlpml_set_vf(hw, max_frame_size);
}
@@ -1183,6 +1181,8 @@ static void igbvf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
if (hw->mac.ops.set_vfta(hw, vid, true))
dev_err(&adapter->pdev->dev, "Failed to add vlan id %d\n", vid);
+ else
+ set_bit(vid, adapter->active_vlans);
}
static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -1191,7 +1191,6 @@ static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct e1000_hw *hw = &adapter->hw;
igbvf_irq_disable(adapter);
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
if (!test_bit(__IGBVF_DOWN, &adapter->state))
igbvf_irq_enable(adapter);
@@ -1199,30 +1198,16 @@ static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
if (hw->mac.ops.set_vfta(hw, vid, false))
dev_err(&adapter->pdev->dev,
"Failed to remove vlan id %d\n", vid);
-}
-
-static void igbvf_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
-{
- struct igbvf_adapter *adapter = netdev_priv(netdev);
-
- adapter->vlgrp = grp;
+ else
+ clear_bit(vid, adapter->active_vlans);
}
static void igbvf_restore_vlan(struct igbvf_adapter *adapter)
{
u16 vid;
- if (!adapter->vlgrp)
- return;
-
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
igbvf_vlan_rx_add_vid(adapter->netdev, vid);
- }
-
- igbvf_set_rlpml(adapter);
}
/**
@@ -2203,7 +2188,7 @@ static netdev_tx_t igbvf_xmit_frame_ring_adv(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
tx_flags |= IGBVF_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << IGBVF_TX_FLAGS_VLAN_SHIFT);
}
@@ -2556,7 +2541,6 @@ static const struct net_device_ops igbvf_netdev_ops = {
.ndo_change_mtu = igbvf_change_mtu,
.ndo_do_ioctl = igbvf_ioctl,
.ndo_tx_timeout = igbvf_tx_timeout,
- .ndo_vlan_rx_register = igbvf_vlan_rx_register,
.ndo_vlan_rx_add_vid = igbvf_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = igbvf_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 32f07f868d89..a234e4504522 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -532,7 +532,7 @@ static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len)
return;
ih = (struct iphdr *) ((char *)eh + ETH_HLEN);
- if (ih->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(ih))
return;
proto = ih->protocol;
@@ -1664,12 +1664,7 @@ static void ioc3_set_multicast_list(struct net_device *dev)
ip->ehar_l = 0xffffffff;
} else {
netdev_for_each_mc_addr(ha, dev) {
- char *addr = ha->addr;
-
- if (!(*addr & 1))
- continue;
-
- ehar |= (1UL << ioc3_hash(addr));
+ ehar |= (1UL << ioc3_hash(ha->addr));
}
ip->ehar_h = ehar >> 32;
ip->ehar_l = ehar & 0xffffffff;
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 58cd3202b48c..d4aa40adf1e9 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -22,6 +22,7 @@
*/
#include <linux/crc32.h>
#include <linux/ethtool.h>
+#include <linux/interrupt.h>
#include <linux/gfp.h>
#include <linux/mii.h>
#include <linux/mutex.h>
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index d532dde5120f..963067d3bda2 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -31,6 +31,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 174cafad2c1a..b45b2cc42804 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -152,6 +152,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 7a963d4e6d06..b56636da6cc3 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -52,6 +52,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
#include <linux/pnp.h>
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 001ed0a255f6..d0851dfa0378 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -12,6 +12,8 @@
* Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
*
*/
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index efe05bb34dd8..5039f08f5a5b 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -11,6 +11,7 @@
*
********************************************************************/
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 8800e1fe4129..954f6e938fb7 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -49,6 +49,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
@@ -515,7 +516,7 @@ static const struct net_device_ops smsc_ircc_netdev_ops = {
* Try to open driver instance
*
*/
-static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
{
struct smsc_ircc_cb *self;
struct net_device *dev;
diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c
index 99e1ec02a011..19ad4606b799 100644
--- a/drivers/net/irda/toim3232-sir.c
+++ b/drivers/net/irda/toim3232-sir.c
@@ -78,7 +78,7 @@
* Target hardware: IRWave IR320ST-2
*
* The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic
- * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever.
+ * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transceiver.
* It uses a hex inverter and some discrete components to buffer and
* line convert the RS232 down to 5V.
*
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index f504b262ba36..6d6479049aa1 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -46,6 +46,7 @@ F02 Oct/28/02: Add SB device ID for 3147 and 3177.
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
index c6f58482b769..f903a6a2dcb7 100644
--- a/drivers/net/irda/via-ircc.h
+++ b/drivers/net/irda/via-ircc.h
@@ -210,7 +210,7 @@ static void DisableDmaChannel(unsigned int channel)
break;
default:
break;
- }; //Switch
+ }
}
static unsigned char ReadLPCReg(int iRegNum)
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index c3d07382b7fa..9021d0131727 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL");
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 1f9c3f08d1a3..c4366601b067 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -47,6 +47,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
#include <linux/gfp.h>
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 9ece1fd9889d..53dd39e9130e 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -538,7 +538,7 @@ static void veth_handle_ack(struct veth_lpevent *event)
default:
veth_error("Unknown ack type %d from LPAR %d.\n",
event->base_event.xSubtype, rlp);
- };
+ }
}
static void veth_handle_int(struct veth_lpevent *event)
@@ -584,7 +584,7 @@ static void veth_handle_int(struct veth_lpevent *event)
default:
veth_error("Unknown interrupt type %d from LPAR %d.\n",
event->base_event.xSubtype, rlp);
- };
+ }
}
static void veth_handle_event(struct HvLpEvent *event)
@@ -964,11 +964,9 @@ static void veth_set_multicast_list(struct net_device *dev)
u8 *addr = ha->addr;
u64 xaddr = 0;
- if (addr[0] & 0x01) {/* multicast address? */
- memcpy(&xaddr, addr, ETH_ALEN);
- port->mcast_addr[port->num_mcast] = xaddr;
- port->num_mcast++;
- }
+ memcpy(&xaddr, addr, ETH_ALEN);
+ port->mcast_addr[port->num_mcast] = xaddr;
+ port->num_mcast++;
}
}
@@ -1184,7 +1182,7 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct veth_port *port = netdev_priv(dev);
HvLpIndexMap lpmask;
- if (! (frame[0] & 0x01)) {
+ if (is_unicast_ether_addr(frame)) {
/* unicast packet */
HvLpIndex rlp = frame[5];
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index e467b20ed1f0..e04a8e49e6dc 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -131,6 +131,13 @@ struct vf_macvlans {
u8 vf_macvlan[ETH_ALEN];
};
+#define IXGBE_MAX_TXD_PWR 14
+#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR)
+
+/* Tx Descriptors needed, worst case */
+#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IXGBE_MAX_DATA_PER_TXD)
+#define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4)
+
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
struct ixgbe_tx_buffer {
@@ -207,12 +214,10 @@ struct ixgbe_ring {
struct ixgbe_rx_buffer *rx_buffer_info;
};
unsigned long state;
- u8 atr_sample_rate;
- u8 atr_count;
+ u8 __iomem *tail;
+
u16 count; /* amount of descriptors */
u16 rx_buf_len;
- u16 next_to_use;
- u16 next_to_clean;
u8 queue_index; /* needed for multiqueue queue management */
u8 reg_idx; /* holds the special value that gets
@@ -220,15 +225,13 @@ struct ixgbe_ring {
* associated with this ring, which is
* different for DCB and RSS modes
*/
- u8 dcb_tc;
-
- u16 work_limit; /* max work per interrupt */
-
- u8 __iomem *tail;
+ u8 atr_sample_rate;
+ u8 atr_count;
- unsigned int total_bytes;
- unsigned int total_packets;
+ u16 next_to_use;
+ u16 next_to_clean;
+ u8 dcb_tc;
struct ixgbe_queue_stats stats;
struct u64_stats_sync syncp;
union {
@@ -244,7 +247,6 @@ struct ixgbe_ring {
enum ixgbe_ring_f_enum {
RING_F_NONE = 0,
- RING_F_DCB,
RING_F_VMDQ, /* SR-IOV uses the same ring feature */
RING_F_RSS,
RING_F_FDIR,
@@ -255,7 +257,6 @@ enum ixgbe_ring_f_enum {
RING_F_ARRAY_SIZE /* must be last in enum set */
};
-#define IXGBE_MAX_DCB_INDICES 64
#define IXGBE_MAX_RSS_INDICES 16
#define IXGBE_MAX_VMDQ_INDICES 64
#define IXGBE_MAX_FDIR_INDICES 64
@@ -272,6 +273,18 @@ struct ixgbe_ring_feature {
int mask;
} ____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
+ 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 */
+};
#define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \
? 8 : 1)
@@ -289,12 +302,7 @@ struct ixgbe_q_vector {
int cpu; /* CPU for DCA */
#endif
struct napi_struct napi;
- DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
- DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
- u8 rxr_count; /* Rx ring count assigned to this vector */
- u8 txr_count; /* Tx ring count assigned to this vector */
- u8 tx_itr;
- u8 rx_itr;
+ struct ixgbe_ring_container rx, tx;
u32 eitr;
cpumask_var_t affinity_mask;
char name[IFNAMSIZ + 9];
@@ -308,9 +316,13 @@ struct ixgbe_q_vector {
((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
-#define IXGBE_DESC_UNUSED(R) \
- ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
- (R)->next_to_clean - (R)->next_to_use - 1)
+static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
+{
+ u16 ntc = ring->next_to_clean;
+ u16 ntu = ring->next_to_use;
+
+ return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
+}
#define IXGBE_RX_DESC_ADV(R, i) \
(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
@@ -404,6 +416,9 @@ struct ixgbe_adapter {
u16 eitr_low;
u16 eitr_high;
+ /* Work limits */
+ u16 tx_work_limit;
+
/* TX */
struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp;
int num_tx_queues;
@@ -484,6 +499,17 @@ struct ixgbe_adapter {
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;
+};
+
+struct ixgbe_fdir_filter {
+ struct hlist_node fdir_node;
+ union ixgbe_atr_input filter;
+ u16 sw_idx;
+ u16 action;
};
enum ixbge_state_t {
@@ -545,31 +571,35 @@ extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
extern int ethtool_ioctl(struct ifreq *ifr);
extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
-extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
-extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
+extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
+extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_hash_dword input,
union ixgbe_atr_hash_dword common,
u8 queue);
-extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- struct ixgbe_atr_input_masks *input_masks,
- u16 soft_id, u8 queue);
-extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *ring);
-extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *ring);
+extern s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input_mask);
+extern s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id, u8 queue);
+extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id);
+extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+ union ixgbe_atr_input *mask);
extern void ixgbe_set_rx_mode(struct net_device *netdev);
extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
+extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
+extern void ixgbe_do_reset(struct net_device *netdev);
#ifdef IXGBE_FCOE
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
-extern int ixgbe_fso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
u32 tx_flags, u8 *hdr_len);
extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
- union ixgbe_adv_rx_desc *rx_desc,
- struct sk_buff *skb);
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb,
+ u32 staterr);
extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
struct scatterlist *sgl, unsigned int sgc);
extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 8179e5060a18..0d4e38264492 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -1242,6 +1242,47 @@ static void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw)
}
}
+/**
+ * ixgbe_set_rxpba_82598 - Configure packet buffers
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure packet buffers.
+ */
+static void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, u32 headroom,
+ int strategy)
+{
+ u32 rxpktsize = IXGBE_RXPBSIZE_64KB;
+ u8 i = 0;
+
+ if (!num_pb)
+ return;
+
+ /* Setup Rx packet buffer sizes */
+ switch (strategy) {
+ case PBA_STRATEGY_WEIGHTED:
+ /* Setup the first four at 80KB */
+ rxpktsize = IXGBE_RXPBSIZE_80KB;
+ for (; i < 4; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ /* Setup the last four at 48KB...don't re-init i */
+ rxpktsize = IXGBE_RXPBSIZE_48KB;
+ /* Fall Through */
+ case PBA_STRATEGY_EQUAL:
+ default:
+ /* Divide the remaining Rx packet buffer evenly among the TCs */
+ for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ break;
+ }
+
+ /* Setup Tx packet buffer sizes */
+ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB);
+
+ return;
+}
+
static struct ixgbe_mac_operations mac_ops_82598 = {
.init_hw = &ixgbe_init_hw_generic,
.reset_hw = &ixgbe_reset_hw_82598,
@@ -1257,6 +1298,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.read_analog_reg8 = &ixgbe_read_analog_reg8_82598,
.write_analog_reg8 = &ixgbe_write_analog_reg8_82598,
.setup_link = &ixgbe_setup_mac_link_82598,
+ .set_rxpba = &ixgbe_set_rxpba_82598,
.check_link = &ixgbe_check_mac_link_82598,
.get_link_capabilities = &ixgbe_get_link_capabilities_82598,
.led_on = &ixgbe_led_on_generic,
@@ -1274,6 +1316,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.clear_vfta = &ixgbe_clear_vfta_82598,
.set_vfta = &ixgbe_set_vfta_82598,
.fc_enable = &ixgbe_fc_enable_82598,
+ .set_fw_drv_ver = NULL,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync,
};
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index 8ee661245af3..3b3dd4df4c5c 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -1107,153 +1107,87 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
}
/**
- * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ * ixgbe_set_fdir_rxpba_82599 - Initialize Flow Director Rx packet buffer
* @hw: pointer to hardware structure
* @pballoc: which mode to allocate filters with
**/
-s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
+static s32 ixgbe_set_fdir_rxpba_82599(struct ixgbe_hw *hw, const u32 pballoc)
{
- u32 fdirctrl = 0;
- u32 pbsize;
+ u32 fdir_pbsize = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
+ u32 current_rxpbsize = 0;
int i;
- /*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
- */
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * initialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
-
+ /* reserve space for Flow Director filters */
switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 8k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+ case IXGBE_FDIR_PBALLOC_256K:
+ fdir_pbsize -= 256 << IXGBE_RXPBSIZE_SHIFT;
break;
case IXGBE_FDIR_PBALLOC_128K:
- /* 16k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+ fdir_pbsize -= 128 << IXGBE_RXPBSIZE_SHIFT;
break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 32k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+ case IXGBE_FDIR_PBALLOC_64K:
+ fdir_pbsize -= 64 << IXGBE_RXPBSIZE_SHIFT;
break;
+ case IXGBE_FDIR_PBALLOC_NONE:
default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
-
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+ 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));
- /* Prime the keys for hashing */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
+ /* if there is already room for the filters do nothing */
+ if (current_rxpbsize <= fdir_pbsize)
+ return 0;
- /*
- * Poll init-done after we write the register. Estimated times:
- * 10G: PBALLOC = 11b, timing is 60us
- * 1G: PBALLOC = 11b, timing is 600us
- * 100M: PBALLOC = 11b, timing is 6ms
- *
- * Multiple these timings by 4 if under full Rx load
- *
- * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
- * 1 msec per poll time. If we're at line rate and drop to 100M, then
- * this might not finish in our poll time, but we can live with that
- * for now.
- */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
- IXGBE_WRITE_FLUSH(hw);
- for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
- if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
- IXGBE_FDIRCTRL_INIT_DONE)
- break;
- usleep_range(1000, 2000);
+ 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);
+ }
}
- if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
return 0;
}
/**
- * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ * ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
* @hw: pointer to hardware structure
- * @pballoc: which mode to allocate filters with
+ * @fdirctrl: value to write to flow director control register
**/
-s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
+static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
{
- u32 fdirctrl = 0;
- u32 pbsize;
int i;
- /*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
- */
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * initialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Initialize the drop queue to Rx queue 127 */
- fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
-
- switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 2k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
- break;
- case IXGBE_FDIR_PBALLOC_128K:
- /* 4k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
- break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 8k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
- break;
- default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
-
- /* Turn perfect match filtering on */
- fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
- fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
-
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
-
/* Prime the keys for hashing */
IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
@@ -1271,10 +1205,6 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
* this might not finish in our poll time, but we can live with that
* for now.
*/
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
-
IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
IXGBE_WRITE_FLUSH(hw);
for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
@@ -1283,101 +1213,77 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
break;
usleep_range(1000, 2000);
}
- if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- hw_dbg(hw, "Flow Director Perfect poll time exceeded!\n");
- return 0;
+ if (i >= IXGBE_FDIR_INIT_DONE_POLL)
+ hw_dbg(hw, "Flow Director poll time exceeded!\n");
}
-
/**
- * ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
- * @stream: input bitstream to compute the hash on
- * @key: 32-bit hash key
+ * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ * @hw: pointer to hardware structure
+ * @fdirctrl: value to write to flow director control register, initially
+ * contains just the value of the Rx packet buffer allocation
**/
-static u32 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
- u32 key)
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
{
- /*
- * The algorithm is as follows:
- * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
- * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
- * and A[n] x B[n] is bitwise AND between same length strings
- *
- * K[n] is 16 bits, defined as:
- * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
- * for n modulo 32 < 15, K[n] =
- * K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
- *
- * S[n] is 16 bits, defined as:
- * for n >= 15, S[n] = S[n:n - 15]
- * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
- *
- * To simplify for programming, the algorithm is implemented
- * in software this way:
- *
- * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
- *
- * for (i = 0; i < 352; i+=32)
- * hi_hash_dword[31:0] ^= Stream[(i+31):i];
- *
- * lo_hash_dword[15:0] ^= Stream[15:0];
- * lo_hash_dword[15:0] ^= hi_hash_dword[31:16];
- * lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
- *
- * hi_hash_dword[31:0] ^= Stream[351:320];
- *
- * if(key[0])
- * hash[15:0] ^= Stream[15:0];
- *
- * for (i = 0; i < 16; i++) {
- * if (key[i])
- * hash[15:0] ^= lo_hash_dword[(i+15):i];
- * if (key[i + 16])
- * hash[15:0] ^= hi_hash_dword[(i+15):i];
- * }
- *
- */
- __be32 common_hash_dword = 0;
- u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
- u32 hash_result = 0;
- u8 i;
+ s32 err;
- /* record the flow_vm_vlan bits as they are a key part to the hash */
- flow_vm_vlan = ntohl(atr_input->dword_stream[0]);
+ /* Before enabling Flow Director, verify the Rx Packet Buffer size */
+ err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+ if (err)
+ return err;
- /* generate common hash dword */
- for (i = 10; i; i -= 2)
- common_hash_dword ^= atr_input->dword_stream[i] ^
- atr_input->dword_stream[i - 1];
+ /*
+ * Continue setup of fdirctrl register bits:
+ * Move the flexible bytes to use the ethertype - shift 6 words
+ * Set the maximum length per hash bucket to 0xA filters
+ * Send interrupt when 64 filters are left
+ */
+ fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+ (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+ (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
- hi_hash_dword = ntohl(common_hash_dword);
+ /* write hashes and fdirctrl register, poll for completion */
+ ixgbe_fdir_enable_82599(hw, fdirctrl);
- /* low dword is word swapped version of common */
- lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
+ return 0;
+}
- /* apply flow ID/VM pool/VLAN ID bits to hash words */
- hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
+/**
+ * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ * @hw: pointer to hardware structure
+ * @fdirctrl: value to write to flow director control register, initially
+ * contains just the value of the Rx packet buffer allocation
+ **/
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
+{
+ s32 err;
- /* Process bits 0 and 16 */
- if (key & 0x0001) hash_result ^= lo_hash_dword;
- if (key & 0x00010000) hash_result ^= hi_hash_dword;
+ /* Before enabling Flow Director, verify the Rx Packet Buffer size */
+ err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+ if (err)
+ return err;
/*
- * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
- * delay this because bit 0 of the stream should not be processed
- * so we do not add the vlan until after bit 0 was processed
+ * Continue setup of fdirctrl register bits:
+ * Turn perfect match filtering on
+ * Report hash in RSS field of Rx wb descriptor
+ * Initialize the drop queue
+ * Move the flexible bytes to use the ethertype - shift 6 words
+ * Set the maximum length per hash bucket to 0xA filters
+ * Send interrupt when 64 (0x4 * 16) filters are left
*/
- lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
+ fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH |
+ IXGBE_FDIRCTRL_REPORT_STATUS |
+ (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) |
+ (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+ (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+ (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
+ /* write hashes and fdirctrl register, poll for completion */
+ ixgbe_fdir_enable_82599(hw, fdirctrl);
- /* process the remaining 30 bits in the key 2 bits at a time */
- for (i = 15; i; i-- ) {
- if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
- if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
- }
-
- return hash_result & IXGBE_ATR_HASH_MASK;
+ return 0;
}
/*
@@ -1514,7 +1420,6 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
*/
fdirhashcmd = (u64)fdircmd << 32;
fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
-
IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
@@ -1522,6 +1427,101 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
return 0;
}
+#define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
+do { \
+ u32 n = (_n); \
+ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
+ bucket_hash ^= lo_hash_dword >> n; \
+ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
+ bucket_hash ^= hi_hash_dword >> n; \
+} while (0);
+
+/**
+ * ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
+ * @atr_input: input bitstream to compute the hash on
+ * @input_mask: mask for the input bitstream
+ *
+ * This function serves two main purposes. First it applys the input_mask
+ * to the atr_input resulting in a cleaned up atr_input data stream.
+ * Secondly it computes the hash and stores it in the bkt_hash field at
+ * the end of the input byte stream. This way it will be available for
+ * future use without needing to recompute the hash.
+ **/
+void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+ union ixgbe_atr_input *input_mask)
+{
+
+ u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+ u32 bucket_hash = 0;
+
+ /* Apply masks to input data */
+ input->dword_stream[0] &= input_mask->dword_stream[0];
+ input->dword_stream[1] &= input_mask->dword_stream[1];
+ input->dword_stream[2] &= input_mask->dword_stream[2];
+ input->dword_stream[3] &= input_mask->dword_stream[3];
+ input->dword_stream[4] &= input_mask->dword_stream[4];
+ input->dword_stream[5] &= input_mask->dword_stream[5];
+ input->dword_stream[6] &= input_mask->dword_stream[6];
+ input->dword_stream[7] &= input_mask->dword_stream[7];
+ input->dword_stream[8] &= input_mask->dword_stream[8];
+ input->dword_stream[9] &= input_mask->dword_stream[9];
+ input->dword_stream[10] &= input_mask->dword_stream[10];
+
+ /* record the flow_vm_vlan bits as they are a key part to the hash */
+ flow_vm_vlan = ntohl(input->dword_stream[0]);
+
+ /* generate common hash dword */
+ hi_hash_dword = ntohl(input->dword_stream[1] ^
+ input->dword_stream[2] ^
+ input->dword_stream[3] ^
+ input->dword_stream[4] ^
+ input->dword_stream[5] ^
+ input->dword_stream[6] ^
+ input->dword_stream[7] ^
+ input->dword_stream[8] ^
+ input->dword_stream[9] ^
+ input->dword_stream[10]);
+
+ /* low dword is word swapped version of common */
+ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
+
+ /* apply flow ID/VM pool/VLAN ID bits to hash words */
+ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
+
+ /* Process bits 0 and 16 */
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(0);
+
+ /*
+ * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+ * delay this because bit 0 of the stream should not be processed
+ * so we do not add the vlan until after bit 0 was processed
+ */
+ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
+
+ /* Process remaining 30 bit of the key */
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(1);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(2);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(3);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(4);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(5);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(6);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(7);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(8);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(9);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(10);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(11);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(12);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(13);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(14);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(15);
+
+ /*
+ * Limit hash to 13 bits since max bucket count is 8K.
+ * Store result at the end of the input stream.
+ */
+ input->formatted.bkt_hash = bucket_hash & 0x1FFF;
+}
+
/**
* ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
* @input_mask: mask to be bit swapped
@@ -1531,11 +1531,11 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
* generate a correctly swapped value we need to bit swap the mask and that
* is what is accomplished by this function.
**/
-static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
+static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
{
- u32 mask = ntohs(input_masks->dst_port_mask);
+ u32 mask = ntohs(input_mask->formatted.dst_port);
mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
- mask |= ntohs(input_masks->src_port_mask);
+ mask |= ntohs(input_mask->formatted.src_port);
mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
@@ -1557,52 +1557,14 @@ static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
#define IXGBE_STORE_AS_BE16(_value) \
- (((u16)(_value) >> 8) | ((u16)(_value) << 8))
+ ntohs(((u16)(_value) >> 8) | ((u16)(_value) << 8))
-/**
- * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
- * @hw: pointer to hardware structure
- * @input: input bitstream
- * @input_masks: bitwise masks for relevant fields
- * @soft_id: software index into the silicon hash tables for filter storage
- * @queue: queue index to direct traffic to
- *
- * Note that the caller to this function must lock before calling, since the
- * hardware writes must be protected from one another.
- **/
-s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- struct ixgbe_atr_input_masks *input_masks,
- u16 soft_id, u8 queue)
+s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input_mask)
{
- u32 fdirhash;
- u32 fdircmd;
- u32 fdirport, fdirtcpm;
- u32 fdirvlan;
- /* start with VLAN, flex bytes, VM pool, and IPv6 destination masked */
- u32 fdirm = IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP | IXGBE_FDIRM_FLEX |
- IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
-
- /*
- * Check flow_type formatting, and bail out before we touch the hardware
- * if there's a configuration issue
- */
- switch (input->formatted.flow_type) {
- case IXGBE_ATR_FLOW_TYPE_IPV4:
- /* use the L4 protocol mask for raw IPv4/IPv6 traffic */
- fdirm |= IXGBE_FDIRM_L4P;
- case IXGBE_ATR_FLOW_TYPE_SCTPV4:
- if (input_masks->dst_port_mask || input_masks->src_port_mask) {
- hw_dbg(hw, " Error on src/dst port mask\n");
- return IXGBE_ERR_CONFIG;
- }
- case IXGBE_ATR_FLOW_TYPE_TCPV4:
- case IXGBE_ATR_FLOW_TYPE_UDPV4:
- break;
- default:
- hw_dbg(hw, " Error on flow type input\n");
- return IXGBE_ERR_CONFIG;
- }
+ /* mask IPv6 since it is currently not supported */
+ u32 fdirm = IXGBE_FDIRM_DIPv6;
+ u32 fdirtcpm;
/*
* Program the relevant mask registers. If src/dst_port or src/dst_addr
@@ -1614,41 +1576,71 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
* point in time.
*/
- /* Program FDIRM */
- switch (ntohs(input_masks->vlan_id_mask) & 0xEFFF) {
- case 0xEFFF:
- /* Unmask VLAN ID - bit 0 and fall through to unmask prio */
- fdirm &= ~IXGBE_FDIRM_VLANID;
- case 0xE000:
- /* Unmask VLAN prio - bit 1 */
- fdirm &= ~IXGBE_FDIRM_VLANP;
+ /* verify bucket hash is cleared on hash generation */
+ if (input_mask->formatted.bkt_hash)
+ hw_dbg(hw, " bucket hash should always be 0 in mask\n");
+
+ /* Program FDIRM and verify partial masks */
+ switch (input_mask->formatted.vm_pool & 0x7F) {
+ case 0x0:
+ fdirm |= IXGBE_FDIRM_POOL;
+ case 0x7F:
break;
- case 0x0FFF:
- /* Unmask VLAN ID - bit 0 */
- fdirm &= ~IXGBE_FDIRM_VLANID;
+ default:
+ hw_dbg(hw, " Error on vm pool mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
+ case 0x0:
+ fdirm |= IXGBE_FDIRM_L4P;
+ if (input_mask->formatted.dst_port ||
+ input_mask->formatted.src_port) {
+ hw_dbg(hw, " Error on src/dst port mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+ case IXGBE_ATR_L4TYPE_MASK:
break;
+ default:
+ hw_dbg(hw, " Error on flow type mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ switch (ntohs(input_mask->formatted.vlan_id) & 0xEFFF) {
case 0x0000:
- /* do nothing, vlans already masked */
+ /* mask VLAN ID, fall through to mask VLAN priority */
+ fdirm |= IXGBE_FDIRM_VLANID;
+ case 0x0FFF:
+ /* mask VLAN priority */
+ fdirm |= IXGBE_FDIRM_VLANP;
+ break;
+ case 0xE000:
+ /* mask VLAN ID only, fall through */
+ fdirm |= IXGBE_FDIRM_VLANID;
+ case 0xEFFF:
+ /* no VLAN fields masked */
break;
default:
hw_dbg(hw, " Error on VLAN mask\n");
return IXGBE_ERR_CONFIG;
}
- if (input_masks->flex_mask & 0xFFFF) {
- if ((input_masks->flex_mask & 0xFFFF) != 0xFFFF) {
- hw_dbg(hw, " Error on flexible byte mask\n");
- return IXGBE_ERR_CONFIG;
- }
- /* Unmask Flex Bytes - bit 4 */
- fdirm &= ~IXGBE_FDIRM_FLEX;
+ switch (input_mask->formatted.flex_bytes & 0xFFFF) {
+ case 0x0000:
+ /* Mask Flex Bytes, fall through */
+ fdirm |= IXGBE_FDIRM_FLEX;
+ case 0xFFFF:
+ break;
+ default:
+ hw_dbg(hw, " Error on flexible byte mask\n");
+ return IXGBE_ERR_CONFIG;
}
/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
/* store the TCP/UDP port masks, bit reversed from port layout */
- fdirtcpm = ixgbe_get_fdirtcpm_82599(input_masks);
+ fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
/* write both the same so that UDP and TCP use the same mask */
IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
@@ -1656,24 +1648,32 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
/* store source and destination IP masks (big-enian) */
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
- ~input_masks->src_ip_mask[0]);
+ ~input_mask->formatted.src_ip[0]);
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
- ~input_masks->dst_ip_mask[0]);
+ ~input_mask->formatted.dst_ip[0]);
- /* Apply masks to input data */
- input->formatted.vlan_id &= input_masks->vlan_id_mask;
- input->formatted.flex_bytes &= input_masks->flex_mask;
- input->formatted.src_port &= input_masks->src_port_mask;
- input->formatted.dst_port &= input_masks->dst_port_mask;
- input->formatted.src_ip[0] &= input_masks->src_ip_mask[0];
- input->formatted.dst_ip[0] &= input_masks->dst_ip_mask[0];
+ return 0;
+}
- /* record vlan (little-endian) and flex_bytes(big-endian) */
- fdirvlan =
- IXGBE_STORE_AS_BE16(ntohs(input->formatted.flex_bytes));
- fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
- fdirvlan |= ntohs(input->formatted.vlan_id);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
+s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id, u8 queue)
+{
+ u32 fdirport, fdirvlan, fdirhash, fdircmd;
+
+ /* currently IPv6 is not supported, must be programmed with 0 */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
+ input->formatted.src_ip[0]);
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
+ input->formatted.src_ip[1]);
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
+ input->formatted.src_ip[2]);
+
+ /* record the source address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+
+ /* record the first 32 bits of the destination address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
/* record source and destination port (little-endian)*/
fdirport = ntohs(input->formatted.dst_port);
@@ -1681,29 +1681,80 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
fdirport |= ntohs(input->formatted.src_port);
IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
- /* record the first 32 bits of the destination address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
+ /* record vlan (little-endian) and flex_bytes(big-endian) */
+ fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
+ fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
+ fdirvlan |= ntohs(input->formatted.vlan_id);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
- /* record the source address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+ /* configure FDIRHASH register */
+ fdirhash = input->formatted.bkt_hash;
+ fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+ /*
+ * flush all previous writes to make certain registers are
+ * programmed prior to issuing the command
+ */
+ IXGBE_WRITE_FLUSH(hw);
/* configure FDIRCMD register */
fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+ if (queue == IXGBE_FDIR_DROP_QUEUE)
+ fdircmd |= IXGBE_FDIRCMD_DROP;
fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+ fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
- /* we only want the bucket hash so drop the upper 16 bits */
- fdirhash = ixgbe_atr_compute_hash_82599(input,
- IXGBE_ATR_BUCKET_HASH_KEY);
- fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
return 0;
}
+s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id)
+{
+ u32 fdirhash;
+ u32 fdircmd = 0;
+ u32 retry_count;
+ s32 err = 0;
+
+ /* configure FDIRHASH register */
+ fdirhash = input->formatted.bkt_hash;
+ fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+ /* flush hash to HW */
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* Query if filter is present */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
+
+ for (retry_count = 10; retry_count; retry_count--) {
+ /* allow 10us for query to process */
+ udelay(10);
+ /* verify query completed successfully */
+ fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
+ if (!(fdircmd & IXGBE_FDIRCMD_CMD_MASK))
+ break;
+ }
+
+ if (!retry_count)
+ err = IXGBE_ERR_FDIR_REINIT_FAILED;
+
+ /* if filter exists in hardware then remove it */
+ if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+ IXGBE_WRITE_FLUSH(hw);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+ IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
+ }
+
+ return err;
+}
+
/**
* ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
* @hw: pointer to hardware structure
@@ -2146,6 +2197,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
.read_analog_reg8 = &ixgbe_read_analog_reg8_82599,
.write_analog_reg8 = &ixgbe_write_analog_reg8_82599,
.setup_link = &ixgbe_setup_mac_link_82599,
+ .set_rxpba = &ixgbe_set_rxpba_generic,
.check_link = &ixgbe_check_mac_link_generic,
.get_link_capabilities = &ixgbe_get_link_capabilities_82599,
.led_on = &ixgbe_led_on_generic,
@@ -2163,6 +2215,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
.clear_vfta = &ixgbe_clear_vfta_generic,
.set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic,
+ .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = &ixgbe_setup_sfp_modules_82599,
.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing,
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index b894b42a741c..777051f54e53 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1292,7 +1292,7 @@ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
udelay(5);
ixgbe_standby_eeprom(hw);
- };
+ }
/*
* On some parts, SPI write time could vary from 0-20mSec on 3.3V
@@ -1374,7 +1374,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
* EEPROM
*/
mask = mask >> 1;
- };
+ }
/* We leave the "DI" bit set to "0" when we leave this routine. */
eec &= ~IXGBE_EEC_DI;
@@ -3267,3 +3267,243 @@ s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps)
return 0;
}
+
+/**
+ * ixgbe_set_rxpba_generic - Initialize RX packet buffer
+ * @hw: pointer to hardware structure
+ * @num_pb: number of packet buffers to allocate
+ * @headroom: reserve n KB of headroom
+ * @strategy: packet buffer allocation strategy
+ **/
+void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw,
+ int num_pb,
+ u32 headroom,
+ int strategy)
+{
+ u32 pbsize = hw->mac.rx_pb_size;
+ int i = 0;
+ u32 rxpktsize, txpktsize, txpbthresh;
+
+ /* Reserve headroom */
+ pbsize -= headroom;
+
+ if (!num_pb)
+ num_pb = 1;
+
+ /* Divide remaining packet buffer space amongst the number
+ * of packet buffers requested using supplied strategy.
+ */
+ switch (strategy) {
+ case (PBA_STRATEGY_WEIGHTED):
+ /* pba_80_48 strategy weight first half of packet buffer with
+ * 5/8 of the packet buffer space.
+ */
+ rxpktsize = ((pbsize * 5 * 2) / (num_pb * 8));
+ pbsize -= rxpktsize * (num_pb / 2);
+ rxpktsize <<= IXGBE_RXPBSIZE_SHIFT;
+ for (; i < (num_pb / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ /* Fall through to configure remaining packet buffers */
+ case (PBA_STRATEGY_EQUAL):
+ /* Divide the remaining Rx packet buffer evenly among the TCs */
+ rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT;
+ for (; i < num_pb; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Setup Tx packet buffer and threshold equally for all TCs
+ * TXPBTHRESH register is set in K so divide by 1024 and subtract
+ * 10 since the largest packet we support is just over 9K.
+ */
+ txpktsize = IXGBE_TXPBSIZE_MAX / num_pb;
+ txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
+ for (i = 0; i < num_pb; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
+ }
+
+ /* Clear unused TCs, if any, to zero buffer size*/
+ for (; i < IXGBE_MAX_PB; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
+ }
+}
+
+/**
+ * ixgbe_calculate_checksum - Calculate checksum for buffer
+ * @buffer: pointer to EEPROM
+ * @length: size of EEPROM to calculate a checksum for
+ * Calculates the checksum for some buffer on a specified length. The
+ * checksum calculated is returned.
+ **/
+static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
+{
+ u32 i;
+ u8 sum = 0;
+
+ if (!buffer)
+ return 0;
+
+ for (i = 0; i < length; i++)
+ sum += buffer[i];
+
+ return (u8) (0 - sum);
+}
+
+/**
+ * ixgbe_host_interface_command - Issue command to manageability block
+ * @hw: pointer to the HW structure
+ * @buffer: contains the command to write and where the return status will
+ * be placed
+ * @lenght: lenght of buffer, must be multiple of 4 bytes
+ *
+ * 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,
+ u32 length)
+{
+ u32 hicr, i;
+ u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
+ u8 buf_len, dword_len;
+
+ s32 ret_val = 0;
+
+ if (length == 0 || length & 0x3 ||
+ length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+ hw_dbg(hw, "Buffer length failure.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Check that the host interface is enabled. */
+ hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+ if ((hicr & IXGBE_HICR_EN) == 0) {
+ hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Calculate length in DWORDs */
+ dword_len = length >> 2;
+
+ /*
+ * The device driver writes the relevant command block
+ * into the ram area.
+ */
+ for (i = 0; i < dword_len; i++)
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
+ i, *((u32 *)buffer + i));
+
+ /* Setting this bit tells the ARC that a new command is pending. */
+ IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
+
+ for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) {
+ hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+ if (!(hicr & IXGBE_HICR_C))
+ break;
+ usleep_range(1000, 2000);
+ }
+
+ /* Check command successful completion. */
+ if (i == IXGBE_HI_COMMAND_TIMEOUT ||
+ (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
+ hw_dbg(hw, "Command has failed with no status valid.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Calculate length in DWORDs */
+ 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);
+
+ /* If there is any thing in data position pull it in */
+ buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
+ if (buf_len == 0)
+ goto out;
+
+ if (length < (buf_len + hdr_size)) {
+ hw_dbg(hw, "Buffer not large enough for reply message.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Calculate length in DWORDs, add one for odd lengths */
+ dword_len = (buf_len + 1) >> 2;
+
+ /* 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);
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware
+ * @hw: pointer to the HW structure
+ * @maj: driver version major number
+ * @min: driver version minor number
+ * @build: driver version build number
+ * @sub: driver version sub build number
+ *
+ * Sends driver version number to firmware through the manageability
+ * block. On success return 0
+ * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
+ * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
+ u8 build, u8 sub)
+{
+ struct ixgbe_hic_drv_info fw_cmd;
+ int i;
+ s32 ret_val = 0;
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != 0) {
+ ret_val = IXGBE_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
+ fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
+ fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+ fw_cmd.port_num = (u8)hw->bus.func;
+ fw_cmd.ver_maj = maj;
+ fw_cmd.ver_min = min;
+ fw_cmd.ver_build = build;
+ fw_cmd.ver_sub = sub;
+ fw_cmd.hdr.checksum = 0;
+ fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
+ (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
+ fw_cmd.pad = 0;
+ fw_cmd.pad2 = 0;
+
+ for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
+ ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd,
+ sizeof(fw_cmd));
+ if (ret_val != 0)
+ continue;
+
+ if (fw_cmd.hdr.cmd_or_resp.ret_status ==
+ FW_CEM_RESP_STATUS_SUCCESS)
+ ret_val = 0;
+ else
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+
+ break;
+ }
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+out:
+ return ret_val;
+}
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index 46be83cfb500..f24fd64a4c46 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -99,6 +99,11 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
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_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
+ u32 headroom, int strategy);
#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
index 686a17aadef3..9d88c31487bc 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -258,15 +258,13 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- ret = ixgbe_dcb_hw_config_82598(hw, dcb_config->rx_pba_cfg,
- pfc_en, refill, max, bwgid,
- ptype);
+ ret = ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
+ bwgid, ptype);
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
- ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->rx_pba_cfg,
- pfc_en, refill, max, bwgid,
- ptype, prio_tc);
+ ret = ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
+ bwgid, ptype, prio_tc);
break;
default:
break;
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
index 944838fc7b59..e85826ae0320 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -123,11 +123,6 @@ struct tc_configuration {
u8 tc; /* Traffic class (TC) */
};
-enum dcb_rx_pba_cfg {
- pba_equal, /* PBA[0-7] each use 64KB FIFO */
- pba_80_48 /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */
-};
-
struct dcb_num_tcs {
u8 pg_tcs;
u8 pfc_tcs;
@@ -140,8 +135,6 @@ struct ixgbe_dcb_config {
u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */
bool pfc_mode_enable;
- enum dcb_rx_pba_cfg rx_pba_cfg;
-
u32 dcb_cfg_version; /* Not used...OS-specific? */
u32 link_speed; /* For bandwidth allocation validation purpose */
};
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
index 771d01a60d06..2288c3cac010 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -32,45 +32,6 @@
#include "ixgbe_dcb_82598.h"
/**
- * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure packet buffers for DCB mode.
- */
-static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw, u8 rx_pba)
-{
- s32 ret_val = 0;
- u32 value = IXGBE_RXPBSIZE_64KB;
- u8 i = 0;
-
- /* Setup Rx packet buffer sizes */
- switch (rx_pba) {
- case pba_80_48:
- /* Setup the first four at 80KB */
- value = IXGBE_RXPBSIZE_80KB;
- for (; i < 4; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
- /* Setup the last four at 48KB...don't re-init i */
- value = IXGBE_RXPBSIZE_48KB;
- /* Fall Through */
- case pba_equal:
- default:
- for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
-
- /* Setup Tx packet buffer sizes */
- for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i),
- IXGBE_TXPBSIZE_40KB);
- }
- break;
- }
-
- return ret_val;
-}
-
-/**
* ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter
* @hw: pointer to hardware structure
* @dcb_config: pointer to ixgbe_dcb_config structure
@@ -321,11 +282,9 @@ static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
*
* Configure dcb settings and enable dcb mode.
*/
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type)
{
- ixgbe_dcb_config_packet_buffers_82598(hw, rx_pba);
ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, prio_type);
ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
bwg_id, prio_type);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h
index 1e9750c2b46b..2f318935561a 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
@@ -91,8 +91,7 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
u8 *bwg_id,
u8 *prio_type);
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type);
#endif /* _DCB_82598_CONFIG_H */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c
index d50cf78c234d..ade98200288c 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c
@@ -31,63 +31,6 @@
#include "ixgbe_dcb_82599.h"
/**
- * ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers
- * @hw: pointer to hardware structure
- * @rx_pba: method to distribute packet buffer
- *
- * Configure packet buffers for DCB mode.
- */
-static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, u8 rx_pba)
-{
- int num_tcs = IXGBE_MAX_PACKET_BUFFERS;
- u32 rx_pb_size = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
- u32 rxpktsize;
- u32 txpktsize;
- u32 txpbthresh;
- u8 i = 0;
-
- /*
- * This really means configure the first half of the TCs
- * (Traffic Classes) to use 5/8 of the Rx packet buffer
- * space. To determine the size of the buffer for each TC,
- * we are multiplying the average size by 5/4 and applying
- * it to half of the traffic classes.
- */
- if (rx_pba == pba_80_48) {
- rxpktsize = (rx_pb_size * 5) / (num_tcs * 4);
- rx_pb_size -= rxpktsize * (num_tcs / 2);
- for (; i < (num_tcs / 2); i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
- }
-
- /* Divide the remaining Rx packet buffer evenly among the TCs */
- rxpktsize = rx_pb_size / (num_tcs - i);
- for (; i < num_tcs; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
-
- /*
- * Setup Tx packet buffer and threshold equally for all TCs
- * TXPBTHRESH register is set in K so divide by 1024 and subtract
- * 10 since the largest packet we support is just over 9K.
- */
- txpktsize = IXGBE_TXPBSIZE_MAX / num_tcs;
- txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
- for (i = 0; i < num_tcs; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
- IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
- }
-
- /* Clear unused TCs, if any, to zero buffer size*/
- for (; i < MAX_TRAFFIC_CLASS; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
- }
-
- return 0;
-}
-
-/**
* ixgbe_dcb_config_rx_arbiter_82599 - Config Rx Data arbiter
* @hw: pointer to hardware structure
* @refill: refill credits index by traffic class
@@ -376,65 +319,8 @@ static s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
}
/**
- * ixgbe_dcb_config_82599 - Configure general DCB parameters
- * @hw: pointer to hardware structure
- *
- * Configure general DCB parameters.
- */
-static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
-{
- u32 reg;
- u32 q;
-
- /* Disable the Tx desc arbiter so that MTQC can be changed */
- reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
- reg |= IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg);
-
- /* Enable DCB for Rx with 8 TCs */
- reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
- switch (reg & IXGBE_MRQC_MRQE_MASK) {
- case 0:
- case IXGBE_MRQC_RT4TCEN:
- /* RSS disabled cases */
- reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN;
- break;
- case IXGBE_MRQC_RSSEN:
- case IXGBE_MRQC_RTRSS4TCEN:
- /* RSS enabled cases */
- reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RTRSS8TCEN;
- break;
- default:
- /* Unsupported value, assume stale data, overwrite no RSS */
- reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN;
- }
- IXGBE_WRITE_REG(hw, IXGBE_MRQC, reg);
-
- /* Enable DCB for Tx with 8 TCs */
- reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ;
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg);
-
- /* Disable drop for all queues */
- for (q = 0; q < 128; q++)
- IXGBE_WRITE_REG(hw, IXGBE_QDE, q << IXGBE_QDE_IDX_SHIFT);
-
- /* Enable the Tx desc arbiter */
- reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
- reg &= ~IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg);
-
- /* Enable Security TX Buffer IFG for DCB */
- reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
- reg |= IXGBE_SECTX_DCB;
- IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
-
- return 0;
-}
-
-/**
* ixgbe_dcb_hw_config_82599 - Configure and enable DCB
* @hw: pointer to hardware structure
- * @rx_pba: method to distribute packet buffer
* @refill: refill credits index by traffic class
* @max: max credits index by traffic class
* @bwg_id: bandwidth grouping indexed by traffic class
@@ -443,12 +329,9 @@ static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
*
* Configure dcb settings and enable dcb mode.
*/
-s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type, u8 *prio_tc)
{
- ixgbe_dcb_config_packet_buffers_82599(hw, rx_pba);
- ixgbe_dcb_config_82599(hw);
ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
prio_type, prio_tc);
ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h
index 2de71a503153..08d1749862a3 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h
@@ -86,17 +86,6 @@
#define IXGBE_RTTPCS_ARBD_SHIFT 22
#define IXGBE_RTTPCS_ARBD_DCB 0x4 /* Arbitration delay in DCB mode */
-#define IXGBE_TXPBSIZE_20KB 0x00005000 /* 20KB Packet Buffer */
-#define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */
-#define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */
-#define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */
-#define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */
-#define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */
-#define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer*/
-
-#define IXGBE_TXPBTHRESH_DCB 0xA /* THRESH value for DCB mode */
-#define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */
-
/* SECTXMINIFG DCB */
#define IXGBE_SECTX_DCB 0x00001F00 /* DCB TX Buffer IFG */
@@ -127,8 +116,7 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
u8 *prio_type,
u8 *prio_tc);
-s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type,
u8 *prio_tc);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index 5e7ed225851a..0ace6ce1d0b4 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -114,20 +114,19 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
u8 err = 0;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ /* 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_DCB_ENABLED)
- goto out;
-
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
e_err(drv, "Enable failed, needs MSI-X\n");
err = 1;
goto out;
}
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_stop(netdev);
- ixgbe_clear_interrupt_scheme(adapter);
+ adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
switch (adapter->hw.mac.type) {
case ixgbe_mac_82598EB:
@@ -137,46 +136,30 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
break;
default:
break;
}
- adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
- if (!netdev_get_num_tc(netdev))
- ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
-
- ixgbe_init_interrupt_scheme(adapter);
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_open(netdev);
+ ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
} else {
/* Turn off DCB */
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_stop(netdev);
- ixgbe_clear_interrupt_scheme(adapter);
-
- 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:
+ 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);
-
- ixgbe_init_interrupt_scheme(adapter);
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_open(netdev);
+ break;
+ default:
+ break;
}
+ ixgbe_setup_tc(netdev, 0);
}
+
out:
return err;
}
@@ -347,24 +330,20 @@ 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;
+#ifdef IXGBE_FCOE
struct dcb_app app = {
.selector = DCB_APP_IDTYPE_ETHTYPE,
.protocol = ETH_P_FCOE,
};
u8 up = dcb_getapp(netdev, &app);
- int ret;
+#endif
ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
MAX_TRAFFIC_CLASS);
if (ret)
return DCB_NO_HW_CHG;
- /* In IEEE mode app data must be parsed into DCBX format for
- * hardware routines.
- */
- if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
- up = (1 << up);
-
#ifdef IXGBE_FCOE
if (up && (up != (1 << adapter->fcoe.up)))
adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
@@ -378,7 +357,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
usleep_range(1000, 2000);
- ixgbe_fcoe_setapp(adapter, up);
+ adapter->fcoe.up = ffs(up) - 1;
if (netif_running(netdev))
netdev->netdev_ops->ndo_stop(netdev);
@@ -691,24 +670,75 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
return err;
}
+#ifdef IXGBE_FCOE
+static void ixgbe_dcbnl_devreset(struct net_device *dev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ if (netif_running(dev))
+ dev->netdev_ops->ndo_stop(dev);
+
+ ixgbe_clear_interrupt_scheme(adapter);
+ ixgbe_init_interrupt_scheme(adapter);
+
+ if (netif_running(dev))
+ dev->netdev_ops->ndo_open(dev);
+}
+#endif
+
static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
struct dcb_app *app)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EINVAL;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
- return -EINVAL;
+ return err;
- dcb_setapp(dev, app);
+ err = dcb_ieee_setapp(dev, app);
#ifdef IXGBE_FCOE
- if (app->selector == 1 && app->protocol == ETH_P_FCOE &&
- adapter->fcoe.tc == app->priority)
- ixgbe_dcbnl_set_all(dev);
+ if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+ app->protocol == ETH_P_FCOE) {
+ u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+ if (app_mask & (1 << adapter->fcoe.up))
+ return err;
+
+ adapter->fcoe.up = app->priority;
+ ixgbe_dcbnl_devreset(dev);
+ }
#endif
return 0;
}
+static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
+ struct dcb_app *app)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err;
+
+ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+ return -EINVAL;
+
+ err = dcb_ieee_delapp(dev, app);
+
+#ifdef IXGBE_FCOE
+ if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+ app->protocol == ETH_P_FCOE) {
+ u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+ if (app_mask & (1 << adapter->fcoe.up))
+ return err;
+
+ adapter->fcoe.up = app_mask ?
+ ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
+ ixgbe_dcbnl_devreset(dev);
+ }
+#endif
+ return err;
+}
+
static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
@@ -760,6 +790,7 @@ const struct dcbnl_rtnl_ops dcbnl_ops = {
.ieee_getpfc = ixgbe_dcbnl_ieee_getpfc,
.ieee_setpfc = ixgbe_dcbnl_ieee_setpfc,
.ieee_setapp = ixgbe_dcbnl_ieee_setapp,
+ .ieee_delapp = ixgbe_dcbnl_ieee_delapp,
.getstate = ixgbe_dcbnl_get_state,
.setstate = ixgbe_dcbnl_set_state,
.getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr,
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index cb1555bc8548..dc649553a0a6 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -27,6 +27,7 @@
/* ethtool support for ixgbe */
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -441,62 +442,6 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
return 0;
}
-static u32 ixgbe_get_rx_csum(struct net_device *netdev)
-{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
-}
-
-static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- if (data)
- adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
- else
- adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
-
- return 0;
-}
-
-static u32 ixgbe_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
-{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- u32 feature_list;
-
- feature_list = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- feature_list |= NETIF_F_SCTP_CSUM;
- break;
- default:
- break;
- }
- if (data)
- netdev->features |= feature_list;
- else
- netdev->features &= ~feature_list;
-
- return 0;
-}
-
-static int ixgbe_set_tso(struct net_device *netdev, u32 data)
-{
- if (data) {
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- } else {
- netdev->features &= ~NETIF_F_TSO;
- netdev->features &= ~NETIF_F_TSO6;
- }
- return 0;
-}
-
static u32 ixgbe_get_msglevel(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -2055,7 +2000,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0]->work_limit;
+ ec->tx_max_coalesced_frames_irq = adapter->tx_work_limit;
/* only valid if in constant ITR mode */
switch (adapter->rx_itr_setting) {
@@ -2074,7 +2019,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
}
/* if in mixed tx/rx queues per vector mode, report only rx settings */
- if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+ if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count)
return 0;
/* only valid if in constant ITR mode */
@@ -2139,12 +2084,12 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
bool need_reset = false;
/* don't accept tx specific changes if we've got mixed RxTx vectors */
- if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count
+ if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count
&& ec->tx_coalesce_usecs)
return -EINVAL;
if (ec->tx_max_coalesced_frames_irq)
- adapter->tx_ring[0]->work_limit = 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 */
@@ -2213,18 +2158,20 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
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->txr_count && !q_vector->rxr_count)
+ 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;
+ q_vector->tx.work_limit = adapter->tx_work_limit;
ixgbe_write_eitr(q_vector);
}
@@ -2233,241 +2180,376 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
* correctly w.r.t stopping tx, and changing TXDCTL.WTHRESH settings
* also locks in RSC enable/disable which requires reset
*/
- if (need_reset) {
- if (netif_running(netdev))
- ixgbe_reinit_locked(adapter);
- else
- ixgbe_reset(adapter);
- }
+ if (need_reset)
+ ixgbe_do_reset(netdev);
return 0;
}
-static int ixgbe_set_flags(struct net_device *netdev, u32 data)
+static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- bool need_reset = false;
- int rc;
+ union ixgbe_atr_input *mask = &adapter->fdir_mask;
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *rule = NULL;
+
+ /* report total rule count */
+ cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ if (fsp->location <= rule->sw_idx)
+ break;
+ }
-#ifdef CONFIG_IXGBE_DCB
- if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
- !(data & ETH_FLAG_RXVLAN))
+ if (!rule || fsp->location != rule->sw_idx)
return -EINVAL;
-#endif
- need_reset = (data & ETH_FLAG_RXVLAN) !=
- (netdev->features & NETIF_F_HW_VLAN_RX);
+ /* fill out the flow spec entry */
- if ((data & ETH_FLAG_RXHASH) &&
- !(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
- return -EOPNOTSUPP;
-
- rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE |
- ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN |
- ETH_FLAG_RXHASH);
- if (rc)
- return rc;
-
- /* if state changes we need to update adapter->flags and reset */
- if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) &&
- (!!(data & ETH_FLAG_LRO) !=
- !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
- if ((data & ETH_FLAG_LRO) &&
- (!adapter->rx_itr_setting ||
- (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) {
- e_info(probe, "rx-usecs set too low, "
- "not enabling RSC.\n");
- } else {
- adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- need_reset = true;
- break;
- case ixgbe_mac_X540: {
- int i;
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct ixgbe_ring *ring =
- adapter->rx_ring[i];
- if (adapter->flags2 &
- IXGBE_FLAG2_RSC_ENABLED) {
- ixgbe_configure_rscctl(adapter,
- ring);
- } else {
- ixgbe_clear_rscctl(adapter,
- ring);
- }
- }
- }
- break;
- default:
- break;
- }
- }
+ /* set flow type field */
+ switch (rule->filter.formatted.flow_type) {
+ case IXGBE_ATR_FLOW_TYPE_TCPV4:
+ fsp->flow_type = TCP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_UDPV4:
+ fsp->flow_type = UDP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+ fsp->flow_type = SCTP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_IPV4:
+ fsp->flow_type = IP_USER_FLOW;
+ fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
+ fsp->h_u.usr_ip4_spec.proto = 0;
+ fsp->m_u.usr_ip4_spec.proto = 0;
+ break;
+ default:
+ return -EINVAL;
}
- /*
- * Check if Flow Director n-tuple support was enabled or disabled. If
- * the state changed, we need to reset.
- */
- if ((adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) &&
- (!(data & ETH_FLAG_NTUPLE))) {
- /* turn off Flow Director perfect, set hash and reset */
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
- adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
- need_reset = true;
- } else if ((!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) &&
- (data & ETH_FLAG_NTUPLE)) {
- /* turn off Flow Director hash, enable perfect and reset */
- adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
- need_reset = true;
- } else {
- /* no state change */
- }
+ fsp->h_u.tcp_ip4_spec.psrc = rule->filter.formatted.src_port;
+ fsp->m_u.tcp_ip4_spec.psrc = mask->formatted.src_port;
+ fsp->h_u.tcp_ip4_spec.pdst = rule->filter.formatted.dst_port;
+ fsp->m_u.tcp_ip4_spec.pdst = mask->formatted.dst_port;
+ fsp->h_u.tcp_ip4_spec.ip4src = rule->filter.formatted.src_ip[0];
+ fsp->m_u.tcp_ip4_spec.ip4src = mask->formatted.src_ip[0];
+ fsp->h_u.tcp_ip4_spec.ip4dst = rule->filter.formatted.dst_ip[0];
+ fsp->m_u.tcp_ip4_spec.ip4dst = mask->formatted.dst_ip[0];
+ fsp->h_ext.vlan_tci = rule->filter.formatted.vlan_id;
+ fsp->m_ext.vlan_tci = mask->formatted.vlan_id;
+ fsp->h_ext.vlan_etype = rule->filter.formatted.flex_bytes;
+ fsp->m_ext.vlan_etype = mask->formatted.flex_bytes;
+ fsp->h_ext.data[1] = htonl(rule->filter.formatted.vm_pool);
+ fsp->m_ext.data[1] = htonl(mask->formatted.vm_pool);
+ fsp->flow_type |= FLOW_EXT;
+
+ /* record action */
+ if (rule->action == IXGBE_FDIR_DROP_QUEUE)
+ fsp->ring_cookie = RX_CLS_FLOW_DISC;
+ else
+ fsp->ring_cookie = rule->action;
- if (need_reset) {
- if (netif_running(netdev))
- ixgbe_reinit_locked(adapter);
- else
- ixgbe_reset(adapter);
+ return 0;
+}
+
+static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *rule;
+ int cnt = 0;
+
+ /* report total rule count */
+ cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ if (cnt == cmd->rule_cnt)
+ return -EMSGSIZE;
+ rule_locs[cnt] = rule->sw_idx;
+ cnt++;
}
return 0;
}
-static int ixgbe_set_rx_ntuple(struct net_device *dev,
- struct ethtool_rx_ntuple *cmd)
+static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ void *rule_locs)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
- struct ethtool_rx_ntuple_flow_spec *fs = &cmd->fs;
- union ixgbe_atr_input input_struct;
- struct ixgbe_atr_input_masks input_masks;
- int target_queue;
- int err;
+ int ret = -EOPNOTSUPP;
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
- return -EOPNOTSUPP;
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = adapter->num_rx_queues;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = adapter->fdir_filter_count;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ ret = ixgbe_get_ethtool_fdir_entry(adapter, cmd);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ ret = ixgbe_get_ethtool_fdir_all(adapter, cmd,
+ (u32 *)rule_locs);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ixgbe_fdir_filter *input,
+ u16 sw_idx)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct hlist_node *node, *node2, *parent;
+ struct ixgbe_fdir_filter *rule;
+ int err = -EINVAL;
+
+ parent = NULL;
+ rule = NULL;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ /* hash found, or no matching entry */
+ if (rule->sw_idx >= sw_idx)
+ break;
+ parent = node;
+ }
+
+ /* if there is an old rule occupying our place remove it */
+ if (rule && (rule->sw_idx == sw_idx)) {
+ if (!input || (rule->filter.formatted.bkt_hash !=
+ input->filter.formatted.bkt_hash)) {
+ err = ixgbe_fdir_erase_perfect_filter_82599(hw,
+ &rule->filter,
+ sw_idx);
+ }
+
+ hlist_del(&rule->fdir_node);
+ kfree(rule);
+ adapter->fdir_filter_count--;
+ }
/*
- * Don't allow programming if the action is a queue greater than
- * the number of online Tx queues.
+ * If no input this was a delete, err should be 0 if a rule was
+ * successfully found and removed from the list else -EINVAL
*/
- if ((fs->action >= adapter->num_tx_queues) ||
- (fs->action < ETHTOOL_RXNTUPLE_ACTION_DROP))
- return -EINVAL;
+ if (!input)
+ return err;
- memset(&input_struct, 0, sizeof(union ixgbe_atr_input));
- memset(&input_masks, 0, sizeof(struct ixgbe_atr_input_masks));
+ /* initialize node and set software index */
+ INIT_HLIST_NODE(&input->fdir_node);
- /* record flow type */
- switch (fs->flow_type) {
- case IPV4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
- break;
+ /* add filter to the list */
+ if (parent)
+ hlist_add_after(parent, &input->fdir_node);
+ else
+ hlist_add_head(&input->fdir_node,
+ &adapter->fdir_filter_list);
+
+ /* update counts */
+ adapter->fdir_filter_count++;
+
+ return 0;
+}
+
+static int ixgbe_flowspec_to_flow_type(struct ethtool_rx_flow_spec *fsp,
+ u8 *flow_type)
+{
+ switch (fsp->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+ *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
break;
case UDP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+ *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
break;
case SCTP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+ *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
break;
- default:
- return -1;
- }
-
- /* copy vlan tag minus the CFI bit */
- if ((fs->vlan_tag & 0xEFFF) || (~fs->vlan_tag_mask & 0xEFFF)) {
- input_struct.formatted.vlan_id = htons(fs->vlan_tag & 0xEFFF);
- if (!fs->vlan_tag_mask) {
- input_masks.vlan_id_mask = htons(0xEFFF);
- } else {
- switch (~fs->vlan_tag_mask & 0xEFFF) {
- /* all of these are valid vlan-mask values */
- case 0xEFFF:
- case 0xE000:
- case 0x0FFF:
- case 0x0000:
- input_masks.vlan_id_mask =
- htons(~fs->vlan_tag_mask);
+ case IP_USER_FLOW:
+ switch (fsp->h_u.usr_ip4_spec.proto) {
+ case IPPROTO_TCP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+ break;
+ case IPPROTO_UDP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+ break;
+ case IPPROTO_SCTP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+ break;
+ case 0:
+ if (!fsp->m_u.usr_ip4_spec.proto) {
+ *flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
break;
- /* exit with error if vlan-mask is invalid */
- default:
- e_err(drv, "Partial VLAN ID or "
- "priority mask in vlan-mask is not "
- "supported by hardware\n");
- return -1;
}
+ default:
+ return 0;
}
+ break;
+ default:
+ return 0;
}
- /* make sure we only use the first 2 bytes of user data */
- if ((fs->data & 0xFFFF) || (~fs->data_mask & 0xFFFF)) {
- input_struct.formatted.flex_bytes = htons(fs->data & 0xFFFF);
- if (!(fs->data_mask & 0xFFFF)) {
- input_masks.flex_mask = 0xFFFF;
- } else if (~fs->data_mask & 0xFFFF) {
- e_err(drv, "Partial user-def-mask is not "
- "supported by hardware\n");
- return -1;
- }
- }
+ return 1;
+}
+
+static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_fdir_filter *input;
+ union ixgbe_atr_input mask;
+ int err;
+
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+ return -EOPNOTSUPP;
/*
- * Copy input into formatted structures
- *
- * These assignments are based on the following logic
- * If neither input or mask are set assume value is masked out.
- * If input is set, but mask is not mask should default to accept all.
- * If input is not set, but mask is set then mask likely results in 0.
- * If input is set and mask is set then assign both.
+ * Don't allow programming if the action is a queue greater than
+ * the number of online Rx queues.
*/
- if (fs->h_u.tcp_ip4_spec.ip4src || ~fs->m_u.tcp_ip4_spec.ip4src) {
- input_struct.formatted.src_ip[0] = fs->h_u.tcp_ip4_spec.ip4src;
- if (!fs->m_u.tcp_ip4_spec.ip4src)
- input_masks.src_ip_mask[0] = 0xFFFFFFFF;
- else
- input_masks.src_ip_mask[0] =
- ~fs->m_u.tcp_ip4_spec.ip4src;
- }
- if (fs->h_u.tcp_ip4_spec.ip4dst || ~fs->m_u.tcp_ip4_spec.ip4dst) {
- input_struct.formatted.dst_ip[0] = fs->h_u.tcp_ip4_spec.ip4dst;
- if (!fs->m_u.tcp_ip4_spec.ip4dst)
- input_masks.dst_ip_mask[0] = 0xFFFFFFFF;
- else
- input_masks.dst_ip_mask[0] =
- ~fs->m_u.tcp_ip4_spec.ip4dst;
+ if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
+ (fsp->ring_cookie >= adapter->num_rx_queues))
+ return -EINVAL;
+
+ /* Don't allow indexes to exist outside of available space */
+ if (fsp->location >= ((1024 << adapter->fdir_pballoc) - 2)) {
+ e_err(drv, "Location out of range\n");
+ return -EINVAL;
}
- if (fs->h_u.tcp_ip4_spec.psrc || ~fs->m_u.tcp_ip4_spec.psrc) {
- input_struct.formatted.src_port = fs->h_u.tcp_ip4_spec.psrc;
- if (!fs->m_u.tcp_ip4_spec.psrc)
- input_masks.src_port_mask = 0xFFFF;
- else
- input_masks.src_port_mask = ~fs->m_u.tcp_ip4_spec.psrc;
+
+ input = kzalloc(sizeof(*input), GFP_ATOMIC);
+ if (!input)
+ return -ENOMEM;
+
+ memset(&mask, 0, sizeof(union ixgbe_atr_input));
+
+ /* set SW index */
+ input->sw_idx = fsp->location;
+
+ /* record flow type */
+ if (!ixgbe_flowspec_to_flow_type(fsp,
+ &input->filter.formatted.flow_type)) {
+ e_err(drv, "Unrecognized flow type\n");
+ goto err_out;
}
- if (fs->h_u.tcp_ip4_spec.pdst || ~fs->m_u.tcp_ip4_spec.pdst) {
- input_struct.formatted.dst_port = fs->h_u.tcp_ip4_spec.pdst;
- if (!fs->m_u.tcp_ip4_spec.pdst)
- input_masks.dst_port_mask = 0xFFFF;
- else
- input_masks.dst_port_mask = ~fs->m_u.tcp_ip4_spec.pdst;
+
+ mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
+ IXGBE_ATR_L4TYPE_MASK;
+
+ if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
+ mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
+
+ /* Copy input into formatted structures */
+ input->filter.formatted.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
+ mask.formatted.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src;
+ input->filter.formatted.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
+ mask.formatted.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst;
+ input->filter.formatted.src_port = fsp->h_u.tcp_ip4_spec.psrc;
+ mask.formatted.src_port = fsp->m_u.tcp_ip4_spec.psrc;
+ input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst;
+ mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
+
+ if (fsp->flow_type & FLOW_EXT) {
+ input->filter.formatted.vm_pool =
+ (unsigned char)ntohl(fsp->h_ext.data[1]);
+ mask.formatted.vm_pool =
+ (unsigned char)ntohl(fsp->m_ext.data[1]);
+ input->filter.formatted.vlan_id = fsp->h_ext.vlan_tci;
+ mask.formatted.vlan_id = fsp->m_ext.vlan_tci;
+ input->filter.formatted.flex_bytes =
+ fsp->h_ext.vlan_etype;
+ mask.formatted.flex_bytes = fsp->m_ext.vlan_etype;
}
/* determine if we need to drop or route the packet */
- if (fs->action == ETHTOOL_RXNTUPLE_ACTION_DROP)
- target_queue = MAX_RX_QUEUES - 1;
+ if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
+ input->action = IXGBE_FDIR_DROP_QUEUE;
else
- target_queue = fs->action;
+ input->action = fsp->ring_cookie;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ if (hlist_empty(&adapter->fdir_filter_list)) {
+ /* save mask and program input mask into HW */
+ memcpy(&adapter->fdir_mask, &mask, sizeof(mask));
+ err = ixgbe_fdir_set_input_mask_82599(hw, &mask);
+ if (err) {
+ e_err(drv, "Error writing mask\n");
+ goto err_out_w_lock;
+ }
+ } else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) {
+ e_err(drv, "Only one mask supported per port\n");
+ goto err_out_w_lock;
+ }
+
+ /* apply mask and compute/store hash */
+ ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
+
+ /* program filters to filter memory */
+ err = ixgbe_fdir_write_perfect_filter_82599(hw,
+ &input->filter, input->sw_idx,
+ (input->action == IXGBE_FDIR_DROP_QUEUE) ?
+ IXGBE_FDIR_DROP_QUEUE :
+ adapter->rx_ring[input->action]->reg_idx);
+ if (err)
+ goto err_out_w_lock;
+
+ ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+
+ return err;
+err_out_w_lock:
+ spin_unlock(&adapter->fdir_perfect_lock);
+err_out:
+ kfree(input);
+ return -EINVAL;
+}
+
+static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ int err;
spin_lock(&adapter->fdir_perfect_lock);
- err = ixgbe_fdir_add_perfect_filter_82599(&adapter->hw,
- &input_struct,
- &input_masks, 0,
- target_queue);
+ err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, fsp->location);
spin_unlock(&adapter->fdir_perfect_lock);
- return err ? -1 : 0;
+ return err;
+}
+
+static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXCLSRLINS:
+ ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
}
static const struct ethtool_ops ixgbe_ethtool_ops = {
@@ -2486,16 +2568,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.set_ringparam = ixgbe_set_ringparam,
.get_pauseparam = ixgbe_get_pauseparam,
.set_pauseparam = ixgbe_set_pauseparam,
- .get_rx_csum = ixgbe_get_rx_csum,
- .set_rx_csum = ixgbe_set_rx_csum,
- .get_tx_csum = ixgbe_get_tx_csum,
- .set_tx_csum = ixgbe_set_tx_csum,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
.get_msglevel = ixgbe_get_msglevel,
.set_msglevel = ixgbe_set_msglevel,
- .get_tso = ethtool_op_get_tso,
- .set_tso = ixgbe_set_tso,
.self_test = ixgbe_diag_test,
.get_strings = ixgbe_get_strings,
.set_phys_id = ixgbe_set_phys_id,
@@ -2503,9 +2577,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_ethtool_stats = ixgbe_get_ethtool_stats,
.get_coalesce = ixgbe_get_coalesce,
.set_coalesce = ixgbe_set_coalesce,
- .get_flags = ethtool_op_get_flags,
- .set_flags = ixgbe_set_flags,
- .set_rx_ntuple = ixgbe_set_rx_ntuple,
+ .get_rxnfc = ixgbe_get_rxnfc,
+ .set_rxnfc = ixgbe_set_rxnfc,
};
void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index 05920726e824..824edae77865 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -26,9 +26,6 @@
*******************************************************************************/
#include "ixgbe.h"
-#ifdef CONFIG_IXGBE_DCB
-#include "ixgbe_dcb_82599.h"
-#endif /* CONFIG_IXGBE_DCB */
#include <linux/if_ether.h>
#include <linux/gfp.h>
#include <linux/if_vlan.h>
@@ -40,25 +37,6 @@
#include <scsi/libfcoe.h>
/**
- * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
- * @rx_desc: advanced rx descriptor
- *
- * Returns : true if it is FCoE pkt
- */
-static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc)
-{
- u16 p;
-
- p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info);
- if (p & IXGBE_RXDADV_PKTTYPE_ETQF) {
- p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK;
- p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT;
- return p == IXGBE_ETQF_FILTER_FCOE;
- }
- return false;
-}
-
-/**
* ixgbe_fcoe_clear_ddp - clear the given ddp context
* @ddp - ptr to the ixgbe_fcoe_ddp
*
@@ -128,14 +106,17 @@ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
if (ddp->sgl)
pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc,
DMA_FROM_DEVICE);
- pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+ if (ddp->pool) {
+ pci_pool_free(ddp->pool, ddp->udl, ddp->udp);
+ ddp->pool = NULL;
+ }
+
ixgbe_fcoe_clear_ddp(ddp);
out_ddp_put:
return len;
}
-
/**
* ixgbe_fcoe_ddp_setup - called to set up ddp context
* @netdev: the corresponding net_device
@@ -163,6 +144,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
unsigned int thislen = 0;
u32 fcbuff, fcdmarw, fcfltrw, fcrxctl;
dma_addr_t addr = 0;
+ struct pci_pool *pool;
if (!netdev || !sgl)
return 0;
@@ -199,12 +181,14 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
return 0;
}
- /* alloc the udl from our ddp pool */
- ddp->udl = pci_pool_alloc(fcoe->pool, GFP_ATOMIC, &ddp->udp);
+ /* alloc the udl from per cpu ddp pool */
+ pool = *per_cpu_ptr(fcoe->pool, get_cpu());
+ ddp->udl = pci_pool_alloc(pool, GFP_ATOMIC, &ddp->udp);
if (!ddp->udl) {
e_err(drv, "failed allocated ddp context\n");
goto out_noddp_unmap;
}
+ ddp->pool = pool;
ddp->sgl = sgl;
ddp->sgc = sgc;
@@ -268,6 +252,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
j++;
lastsize = 1;
}
+ put_cpu();
fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
@@ -311,11 +296,12 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
return 1;
out_noddp_free:
- pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+ pci_pool_free(pool, ddp->udl, ddp->udp);
ixgbe_fcoe_clear_ddp(ddp);
out_noddp_unmap:
pci_unmap_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
+ put_cpu();
return 0;
}
@@ -374,23 +360,20 @@ int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
*/
int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
union ixgbe_adv_rx_desc *rx_desc,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ u32 staterr)
{
u16 xid;
u32 fctl;
- u32 sterr, fceofe, fcerr, fcstat;
+ u32 fceofe, fcerr, fcstat;
int rc = -EINVAL;
struct ixgbe_fcoe *fcoe;
struct ixgbe_fcoe_ddp *ddp;
struct fc_frame_header *fh;
struct fcoe_crc_eof *crc;
- if (!ixgbe_rx_is_fcoe(rx_desc))
- goto ddp_out;
-
- sterr = le32_to_cpu(rx_desc->wb.upper.status_error);
- fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR);
- fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE);
+ fcerr = (staterr & IXGBE_RXDADV_ERR_FCERR);
+ fceofe = (staterr & IXGBE_RXDADV_ERR_FCEOFE);
if (fcerr == IXGBE_FCERR_BADCRC)
skb_checksum_none_assert(skb);
else
@@ -419,7 +402,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
if (fcerr | fceofe)
goto ddp_out;
- fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT);
+ fcstat = (staterr & IXGBE_RXDADV_STAT_FCSTAT);
if (fcstat) {
/* update length of DDPed data */
ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
@@ -465,24 +448,18 @@ ddp_out:
*
* Returns : 0 indicates no FSO, > 0 for FSO, < 0 for error
*/
-int ixgbe_fso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
u32 tx_flags, u8 *hdr_len)
{
- u8 sof, eof;
+ struct fc_frame_header *fh;
u32 vlan_macip_lens;
- u32 fcoe_sof_eof;
- u32 type_tucmd;
+ u32 fcoe_sof_eof = 0;
u32 mss_l4len_idx;
- int mss = 0;
- unsigned int i;
- struct ixgbe_tx_buffer *tx_buffer_info;
- struct ixgbe_adv_tx_context_desc *context_desc;
- struct fc_frame_header *fh;
+ u8 sof, eof;
if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) {
- e_err(drv, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
- skb_shinfo(skb)->gso_type);
+ dev_err(tx_ring->dev, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
+ skb_shinfo(skb)->gso_type);
return -EINVAL;
}
@@ -492,23 +469,22 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
sizeof(struct fcoe_hdr));
/* sets up SOF and ORIS */
- fcoe_sof_eof = 0;
sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
switch (sof) {
case FC_SOF_I2:
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+ fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_ORIS;
break;
case FC_SOF_I3:
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+ fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF |
+ IXGBE_ADVTXD_FCOEF_ORIS;
break;
case FC_SOF_N2:
break;
case FC_SOF_N3:
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
+ fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF;
break;
default:
- e_warn(drv, "unknown sof = 0x%x\n", sof);
+ dev_warn(tx_ring->dev, "unknown sof = 0x%x\n", sof);
return -EINVAL;
}
@@ -521,12 +497,11 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
break;
case FC_EOF_T:
/* lso needs ORIE */
- if (skb_is_gso(skb)) {
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIE;
- } else {
+ if (skb_is_gso(skb))
+ fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N |
+ IXGBE_ADVTXD_FCOEF_ORIE;
+ else
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T;
- }
break;
case FC_EOF_NI:
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI;
@@ -535,7 +510,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A;
break;
default:
- e_warn(drv, "unknown eof = 0x%x\n", eof);
+ dev_warn(tx_ring->dev, "unknown eof = 0x%x\n", eof);
return -EINVAL;
}
@@ -544,47 +519,72 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC;
- /* hdr_len includes fc_hdr if FCoE lso is enabled */
+ /* include trailer in headlen as it is replicated per frame */
*hdr_len = sizeof(struct fcoe_crc_eof);
+
+ /* hdr_len includes fc_hdr if FCoE LSO is enabled */
if (skb_is_gso(skb))
*hdr_len += (skb_transport_offset(skb) +
sizeof(struct fc_frame_header));
- /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
- vlan_macip_lens = (skb_transport_offset(skb) +
- sizeof(struct fc_frame_header));
- vlan_macip_lens |= ((skb_transport_offset(skb) - 4)
- << IXGBE_ADVTXD_MACLEN_SHIFT);
- vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
-
- /* type_tycmd and mss: set TUCMD.FCoE to enable offload */
- type_tucmd = IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT |
- IXGBE_ADVTXT_TUCMD_FCOE;
- if (skb_is_gso(skb))
- mss = skb_shinfo(skb)->gso_size;
+
/* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */
- mss_l4len_idx = (mss << IXGBE_ADVTXD_MSS_SHIFT) |
- (1 << IXGBE_ADVTXD_IDX_SHIFT);
+ mss_l4len_idx = skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
+ mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
+
+ /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+ vlan_macip_lens = skb_transport_offset(skb) +
+ sizeof(struct fc_frame_header);
+ vlan_macip_lens |= (skb_transport_offset(skb) - 4)
+ << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
/* write context desc */
- i = tx_ring->next_to_use;
- context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
- context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
- context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
- context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
- context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
-
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
-
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
+ ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, fcoe_sof_eof,
+ IXGBE_ADVTXT_TUCMD_FCOE, mss_l4len_idx);
return skb_is_gso(skb);
}
+static void ixgbe_fcoe_ddp_pools_free(struct ixgbe_fcoe *fcoe)
+{
+ unsigned int cpu;
+ struct pci_pool **pool;
+
+ for_each_possible_cpu(cpu) {
+ pool = per_cpu_ptr(fcoe->pool, cpu);
+ if (*pool)
+ pci_pool_destroy(*pool);
+ }
+ free_percpu(fcoe->pool);
+ fcoe->pool = NULL;
+}
+
+static void ixgbe_fcoe_ddp_pools_alloc(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_fcoe *fcoe = &adapter->fcoe;
+ unsigned int cpu;
+ struct pci_pool **pool;
+ char pool_name[32];
+
+ fcoe->pool = alloc_percpu(struct pci_pool *);
+ if (!fcoe->pool)
+ return;
+
+ /* allocate pci pool for each cpu */
+ for_each_possible_cpu(cpu) {
+ snprintf(pool_name, 32, "ixgbe_fcoe_ddp_%d", cpu);
+ pool = per_cpu_ptr(fcoe->pool, cpu);
+ *pool = pci_pool_create(pool_name,
+ adapter->pdev, IXGBE_FCPTR_MAX,
+ IXGBE_FCPTR_ALIGN, PAGE_SIZE);
+ if (!*pool) {
+ e_err(drv, "failed to alloc DDP pool on cpu:%d\n", cpu);
+ ixgbe_fcoe_ddp_pools_free(fcoe);
+ return;
+ }
+ }
+}
+
/**
* ixgbe_configure_fcoe - configures registers for fcoe at start
* @adapter: ptr to ixgbe adapter
@@ -599,27 +599,21 @@ 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];
-#ifdef CONFIG_IXGBE_DCB
- u8 tc;
- u32 up2tc;
-#endif
- /* create the pool for ddp if not created yet */
if (!fcoe->pool) {
- /* allocate ddp pool */
- fcoe->pool = pci_pool_create("ixgbe_fcoe_ddp",
- adapter->pdev, IXGBE_FCPTR_MAX,
- IXGBE_FCPTR_ALIGN, PAGE_SIZE);
- if (!fcoe->pool)
- e_err(drv, "failed to allocated FCoE DDP pool\n");
-
spin_lock_init(&fcoe->lock);
+ ixgbe_fcoe_ddp_pools_alloc(adapter);
+ if (!fcoe->pool) {
+ e_err(drv, "failed to alloc percpu fcoe DDP pools\n");
+ return;
+ }
+
/* Extra buffer to be shared by all DDPs for HW work around */
fcoe->extra_ddp_buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_ATOMIC);
if (fcoe->extra_ddp_buffer == NULL) {
e_err(drv, "failed to allocated extra DDP buffer\n");
- goto out_extra_ddp_buffer_alloc;
+ goto out_ddp_pools;
}
fcoe->extra_ddp_buffer_dma =
@@ -630,7 +624,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
if (dma_mapping_error(&adapter->pdev->dev,
fcoe->extra_ddp_buffer_dma)) {
e_err(drv, "failed to map extra DDP buffer\n");
- goto out_extra_ddp_buffer_dma;
+ goto out_extra_ddp_buffer;
}
}
@@ -670,25 +664,12 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
IXGBE_FCRXCTRL_FCOELLI |
IXGBE_FCRXCTRL_FCCRCBO |
(FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT));
-#ifdef CONFIG_IXGBE_DCB
- up2tc = IXGBE_READ_REG(&adapter->hw, IXGBE_RTTUP2TC);
- for (i = 0; i < MAX_USER_PRIORITY; i++) {
- tc = (u8)(up2tc >> (i * IXGBE_RTTUP2TC_UP_SHIFT));
- tc &= (MAX_TRAFFIC_CLASS - 1);
- if (fcoe->tc == tc) {
- fcoe->up = i;
- break;
- }
- }
-#endif
-
return;
-out_extra_ddp_buffer_dma:
+out_extra_ddp_buffer:
kfree(fcoe->extra_ddp_buffer);
-out_extra_ddp_buffer_alloc:
- pci_pool_destroy(fcoe->pool);
- fcoe->pool = NULL;
+out_ddp_pools:
+ ixgbe_fcoe_ddp_pools_free(fcoe);
}
/**
@@ -704,18 +685,17 @@ void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter)
int i;
struct ixgbe_fcoe *fcoe = &adapter->fcoe;
- /* release ddp resource */
- if (fcoe->pool) {
- for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
- ixgbe_fcoe_ddp_put(adapter->netdev, i);
- dma_unmap_single(&adapter->pdev->dev,
- fcoe->extra_ddp_buffer_dma,
- IXGBE_FCBUFF_MIN,
- DMA_FROM_DEVICE);
- kfree(fcoe->extra_ddp_buffer);
- pci_pool_destroy(fcoe->pool);
- fcoe->pool = NULL;
- }
+ if (!fcoe->pool)
+ return;
+
+ for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
+ ixgbe_fcoe_ddp_put(adapter->netdev, i);
+ dma_unmap_single(&adapter->pdev->dev,
+ fcoe->extra_ddp_buffer_dma,
+ IXGBE_FCBUFF_MIN,
+ DMA_FROM_DEVICE);
+ kfree(fcoe->extra_ddp_buffer);
+ ixgbe_fcoe_ddp_pools_free(fcoe);
}
/**
@@ -811,41 +791,6 @@ out_disable:
return rc;
}
-#ifdef CONFIG_IXGBE_DCB
-/**
- * ixgbe_fcoe_setapp - sets the user priority bitmap for FCoE
- * @adapter : ixgbe adapter
- * @up : 802.1p user priority bitmap
- *
- * Finds out the traffic class from the input user priority
- * bitmap for FCoE.
- *
- * Returns : 0 on success otherwise returns 1 on error
- */
-u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up)
-{
- int i;
- u32 up2tc;
-
- /* valid user priority bitmap must not be 0 */
- if (up) {
- /* from user priority to the corresponding traffic class */
- up2tc = IXGBE_READ_REG(&adapter->hw, IXGBE_RTTUP2TC);
- for (i = 0; i < MAX_USER_PRIORITY; i++) {
- if (up & (1 << i)) {
- up2tc >>= (i * IXGBE_RTTUP2TC_UP_SHIFT);
- up2tc &= (MAX_TRAFFIC_CLASS - 1);
- adapter->fcoe.tc = (u8)up2tc;
- adapter->fcoe.up = i;
- return 0;
- }
- }
- }
-
- return 1;
-}
-#endif /* CONFIG_IXGBE_DCB */
-
/**
* ixgbe_fcoe_get_wwn - get world wide name for the node or the port
* @netdev : ixgbe adapter
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h
index 5a650a4ace66..99de145e290d 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ixgbe/ixgbe_fcoe.h
@@ -62,20 +62,20 @@ struct ixgbe_fcoe_ddp {
struct scatterlist *sgl;
dma_addr_t udp;
u64 *udl;
+ struct pci_pool *pool;
};
struct ixgbe_fcoe {
-#ifdef CONFIG_IXGBE_DCB
- u8 tc;
- u8 up;
-#endif
- unsigned long mode;
+ struct pci_pool **pool;
atomic_t refcnt;
spinlock_t lock;
- struct pci_pool *pool;
struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
unsigned char *extra_ddp_buffer;
dma_addr_t extra_ddp_buffer_dma;
+ unsigned long mode;
+#ifdef CONFIG_IXGBE_DCB
+ u8 up;
+#endif
};
#endif /* _IXGBE_FCOE_H */
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 08e8e25c159d..1be617545dc9 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -32,8 +32,10 @@
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/in.h>
+#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/tcp.h>
+#include <linux/sctp.h>
#include <linux/pkt_sched.h>
#include <linux/ipv6.h>
#include <linux/slab.h>
@@ -53,11 +55,10 @@ char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Network Driver";
#define MAJ 3
-#define MIN 3
+#define MIN 4
#define BUILD 8
-#define KFIX 2
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
- __stringify(BUILD) "-k" __stringify(KFIX)
+ __stringify(BUILD) "-k"
const char ixgbe_driver_version[] = DRV_VERSION;
static const char ixgbe_copyright[] =
"Copyright (c) 1999-2011 Intel Corporation.";
@@ -664,62 +665,6 @@ void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
/* tx_buffer_info must be completely set up in the transmit path */
}
-/**
- * ixgbe_dcb_txq_to_tc - convert a reg index to a traffic class
- * @adapter: driver private struct
- * @index: reg idx of queue to query (0-127)
- *
- * Helper function to determine the traffic index for a particular
- * register index.
- *
- * Returns : a tc index for use in range 0-7, or 0-3
- */
-static u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
-{
- int tc = -1;
- int dcb_i = netdev_get_num_tc(adapter->netdev);
-
- /* if DCB is not enabled the queues have no TC */
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
- return tc;
-
- /* check valid range */
- if (reg_idx >= adapter->hw.mac.max_tx_queues)
- return tc;
-
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82598EB:
- tc = reg_idx >> 2;
- break;
- default:
- if (dcb_i != 4 && dcb_i != 8)
- break;
-
- /* if VMDq is enabled the lowest order bits determine TC */
- if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED |
- IXGBE_FLAG_VMDQ_ENABLED)) {
- tc = reg_idx & (dcb_i - 1);
- break;
- }
-
- /*
- * Convert the reg_idx into the correct TC. This bitmask
- * targets the last full 32 ring traffic class and assigns
- * it a value of 1. From there the rest of the rings are
- * based on shifting the mask further up to include the
- * reg_idx / 16 and then reg_idx / 8. It assumes dcB_i
- * will only ever be 8 or 4 and that reg_idx will never
- * be greater then 128. The code without the power of 2
- * optimizations would be:
- * (((reg_idx % 32) + 32) * dcb_i) >> (9 - reg_idx / 32)
- */
- tc = ((reg_idx & 0X1F) + 0x20) * dcb_i;
- tc >>= 9 - (reg_idx >> 5);
- }
-
- return tc;
-}
-
static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
@@ -765,7 +710,7 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
/* disarm tx queues that have received xoff frames */
for (i = 0; i < adapter->num_tx_queues; i++) {
struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
- u32 tc = ixgbe_dcb_txq_to_tc(adapter, tx_ring->reg_idx);
+ u8 tc = tx_ring->dcb_tc;
if (xoff[tc])
clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
@@ -827,15 +772,6 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
return ret;
}
-#define IXGBE_MAX_TXD_PWR 14
-#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR)
-
-/* Tx Descriptors needed, worst case */
-#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \
- (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
- MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */
-
/**
* ixgbe_tx_timeout_reset - initiate reset due to Tx timeout
* @adapter: driver private struct
@@ -869,7 +805,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
- (count < tx_ring->work_limit)) {
+ (count < q_vector->tx.work_limit)) {
bool cleaned = false;
rmb(); /* read buffer_info after eop_desc */
for ( ; !cleaned; count++) {
@@ -898,11 +834,11 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
}
tx_ring->next_to_clean = i;
- tx_ring->total_bytes += total_bytes;
- tx_ring->total_packets += total_packets;
- u64_stats_update_begin(&tx_ring->syncp);
- tx_ring->stats.packets += total_packets;
tx_ring->stats.bytes += total_bytes;
+ tx_ring->stats.packets += total_packets;
+ u64_stats_update_begin(&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)) {
@@ -938,7 +874,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) &&
- (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+ (ixgbe_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
* sees the new next_to_clean.
*/
@@ -950,7 +886,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
}
}
- return count < tx_ring->work_limit;
+ return count < q_vector->tx.work_limit;
}
#ifdef CONFIG_IXGBE_DCA
@@ -1023,17 +959,17 @@ static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector)
if (q_vector->cpu == cpu)
goto out_no_update;
- r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->txr_count; i++) {
+ 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->txr_idx, adapter->num_tx_queues,
+ r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
r_idx + 1);
}
- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rxr_count; i++) {
+ 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->rxr_idx, adapter->num_rx_queues,
+ r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
r_idx + 1);
}
@@ -1103,6 +1039,24 @@ static inline void ixgbe_rx_hash(union ixgbe_adv_rx_desc *rx_desc,
}
/**
+ * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
+ * @adapter: address of board private structure
+ * @rx_desc: advanced rx descriptor
+ *
+ * Returns : true if it is FCoE pkt
+ */
+static inline bool ixgbe_rx_is_fcoe(struct ixgbe_adapter *adapter,
+ union ixgbe_adv_rx_desc *rx_desc)
+{
+ __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
+
+ return (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
+ ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_ETQF_MASK)) ==
+ (cpu_to_le16(IXGBE_ETQF_FILTER_FCOE <<
+ IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT)));
+}
+
+/**
* ixgbe_receive_skb - Send a completed packet up the stack
* @adapter: board private structure
* @skb: packet to send up
@@ -1134,14 +1088,14 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
* @adapter: address of board private structure
* @status_err: hardware indication of status of receive
* @skb: skb currently being received and modified
+ * @status_err: status error value of last descriptor in packet
**/
static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
union ixgbe_adv_rx_desc *rx_desc,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ u32 status_err)
{
- u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error);
-
- skb_checksum_none_assert(skb);
+ skb->ip_summed = CHECKSUM_NONE;
/* Rx csum disabled */
if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -1485,14 +1439,12 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
}
/* ERR_MASK will only have valid bits if EOP set */
- if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) {
- /* trim packet back to size 0 and recycle it */
- __pskb_trim(skb, 0);
- rx_buffer_info->skb = skb;
+ if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) {
+ dev_kfree_skb_any(skb);
goto next_desc;
}
- ixgbe_rx_checksum(adapter, rx_desc, skb);
+ ixgbe_rx_checksum(adapter, rx_desc, skb, staterr);
if (adapter->netdev->features & NETIF_F_RXHASH)
ixgbe_rx_hash(rx_desc, skb);
@@ -1503,8 +1455,9 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
#ifdef IXGBE_FCOE
/* if ddp, not passing to ULD unless for FCP_RSP or error */
- if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
- ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb);
+ if (ixgbe_rx_is_fcoe(adapter, rx_desc)) {
+ ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb,
+ staterr);
if (!ddp_bytes)
goto next_desc;
}
@@ -1530,7 +1483,7 @@ next_desc:
}
rx_ring->next_to_clean = i;
- cleaned_count = IXGBE_DESC_UNUSED(rx_ring);
+ cleaned_count = ixgbe_desc_unused(rx_ring);
if (cleaned_count)
ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
@@ -1550,12 +1503,12 @@ next_desc:
}
#endif /* IXGBE_FCOE */
- rx_ring->total_packets += total_rx_packets;
- rx_ring->total_bytes += total_rx_bytes;
u64_stats_update_begin(&rx_ring->syncp);
rx_ring->stats.packets += total_rx_packets;
rx_ring->stats.bytes += total_rx_bytes;
u64_stats_update_end(&rx_ring->syncp);
+ q_vector->rx.total_packets += total_rx_packets;
+ q_vector->rx.total_bytes += total_rx_bytes;
}
static int ixgbe_clean_rxonly(struct napi_struct *, int);
@@ -1581,38 +1534,37 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
for (v_idx = 0; v_idx < q_vectors; v_idx++) {
q_vector = adapter->q_vector[v_idx];
/* XXX for_each_set_bit(...) */
- r_idx = find_first_bit(q_vector->rxr_idx,
+ r_idx = find_first_bit(q_vector->rx.idx,
adapter->num_rx_queues);
- for (i = 0; i < q_vector->rxr_count; i++) {
+ 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->rxr_idx,
+ r_idx = find_next_bit(q_vector->rx.idx,
adapter->num_rx_queues,
r_idx + 1);
}
- r_idx = find_first_bit(q_vector->txr_idx,
+ r_idx = find_first_bit(q_vector->tx.idx,
adapter->num_tx_queues);
- for (i = 0; i < q_vector->txr_count; i++) {
+ 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->txr_idx,
+ r_idx = find_next_bit(q_vector->tx.idx,
adapter->num_tx_queues,
r_idx + 1);
}
- if (q_vector->txr_count && !q_vector->rxr_count)
+ if (q_vector->tx.count && !q_vector->rx.count)
/* tx only */
q_vector->eitr = adapter->tx_eitr_param;
- else if (q_vector->rxr_count)
+ else if (q_vector->rx.count)
/* rx or mixed */
q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector);
- /* If Flow Director is enabled, set interrupt affinity */
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ /* 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
@@ -1662,11 +1614,8 @@ enum latency_range {
/**
* ixgbe_update_itr - update the dynamic ITR value based on statistics
- * @adapter: pointer to adapter
- * @eitr: eitr setting (ints per sec) to give last timeslice
- * @itr_setting: current throttle rate in ints/second
- * @packets: the number of packets during this measurement interval
- * @bytes: the number of bytes during this measurement interval
+ * @q_vector: structure containing interrupt and ring information
+ * @ring_container: structure containing ring performance data
*
* Stores a new ITR value based on packets and byte
* counts during the last interrupt. The advantage of per interrupt
@@ -1678,17 +1627,18 @@ enum latency_range {
* this functionality is controlled by the InterruptThrottleRate module
* parameter (see ixgbe_param.c)
**/
-static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
- u32 eitr, u8 itr_setting,
- int packets, int bytes)
+static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector,
+ struct ixgbe_ring_container *ring_container)
{
- unsigned int retval = itr_setting;
- u32 timepassed_us;
u64 bytes_perint;
+ struct ixgbe_adapter *adapter = q_vector->adapter;
+ int bytes = ring_container->total_bytes;
+ int packets = ring_container->total_packets;
+ u32 timepassed_us;
+ u8 itr_setting = ring_container->itr;
if (packets == 0)
- goto update_itr_done;
-
+ return;
/* simple throttlerate management
* 0-20MB/s lowest (100000 ints/s)
@@ -1696,28 +1646,32 @@ static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
* 100-1249MB/s bulk (8000 ints/s)
*/
/* what was last interrupt timeslice? */
- timepassed_us = 1000000/eitr;
+ timepassed_us = 1000000/q_vector->eitr;
bytes_perint = bytes / timepassed_us; /* bytes/usec */
switch (itr_setting) {
case lowest_latency:
if (bytes_perint > adapter->eitr_low)
- retval = low_latency;
+ itr_setting = low_latency;
break;
case low_latency:
if (bytes_perint > adapter->eitr_high)
- retval = bulk_latency;
+ itr_setting = bulk_latency;
else if (bytes_perint <= adapter->eitr_low)
- retval = lowest_latency;
+ itr_setting = lowest_latency;
break;
case bulk_latency:
if (bytes_perint <= adapter->eitr_high)
- retval = low_latency;
+ itr_setting = 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 = itr_setting;
}
/**
@@ -1763,44 +1717,15 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg);
}
-static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
+static void ixgbe_set_itr(struct ixgbe_q_vector *q_vector)
{
- struct ixgbe_adapter *adapter = q_vector->adapter;
- int i, r_idx;
- u32 new_itr;
- u8 current_itr, ret_itr;
-
- r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->txr_count; i++) {
- struct ixgbe_ring *tx_ring = adapter->tx_ring[r_idx];
- ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
- q_vector->tx_itr,
- tx_ring->total_packets,
- tx_ring->total_bytes);
- /* if the result for this queue would decrease interrupt
- * rate for this vector then use that result */
- q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ?
- q_vector->tx_itr - 1 : ret_itr);
- r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
- r_idx + 1);
- }
+ u32 new_itr = q_vector->eitr;
+ u8 current_itr;
- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rxr_count; i++) {
- struct ixgbe_ring *rx_ring = adapter->rx_ring[r_idx];
- ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
- q_vector->rx_itr,
- rx_ring->total_packets,
- rx_ring->total_bytes);
- /* if the result for this queue would decrease interrupt
- * rate for this vector then use that result */
- q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ?
- q_vector->rx_itr - 1 : ret_itr);
- r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
- r_idx + 1);
- }
+ ixgbe_update_itr(q_vector, &q_vector->tx);
+ ixgbe_update_itr(q_vector, &q_vector->rx);
- current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
+ current_itr = max(q_vector->rx.itr, q_vector->tx.itr);
switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */
@@ -1811,16 +1736,17 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
new_itr = 20000; /* aka hwitr = ~200 */
break;
case bulk_latency:
- default:
new_itr = 8000;
break;
+ default:
+ break;
}
if (new_itr != q_vector->eitr) {
/* do an exponential smoothing */
new_itr = ((q_vector->eitr * 9) + new_itr)/10;
- /* save the algorithm value here, not the smoothed one */
+ /* save the algorithm value here */
q_vector->eitr = new_itr;
ixgbe_write_eitr(q_vector);
@@ -1937,8 +1863,7 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
{
- struct net_device *netdev = data;
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_adapter *adapter = data;
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr;
@@ -2061,15 +1986,13 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
struct ixgbe_ring *tx_ring;
int i, r_idx;
- if (!q_vector->txr_count)
+ if (!q_vector->tx.count)
return IRQ_HANDLED;
- r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->txr_count; i++) {
+ 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];
- tx_ring->total_bytes = 0;
- tx_ring->total_packets = 0;
- r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+ r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
r_idx + 1);
}
@@ -2097,16 +2020,14 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
ixgbe_update_dca(q_vector);
#endif
- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rxr_count; i++) {
+ 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];
- rx_ring->total_bytes = 0;
- rx_ring->total_packets = 0;
- r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+ r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
r_idx + 1);
}
- if (!q_vector->rxr_count)
+ if (!q_vector->rx.count)
return IRQ_HANDLED;
/* EIAM disabled interrupts (on this vector) for us */
@@ -2123,24 +2044,20 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
int r_idx;
int i;
- if (!q_vector->txr_count && !q_vector->rxr_count)
+ if (!q_vector->tx.count && !q_vector->rx.count)
return IRQ_HANDLED;
- r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->txr_count; i++) {
+ 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];
- ring->total_bytes = 0;
- ring->total_packets = 0;
- r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+ r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
r_idx + 1);
}
- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rxr_count; i++) {
+ 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];
- ring->total_bytes = 0;
- ring->total_packets = 0;
- r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+ r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
r_idx + 1);
}
@@ -2172,7 +2089,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
ixgbe_update_dca(q_vector);
#endif
- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+ r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
rx_ring = adapter->rx_ring[r_idx];
ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
@@ -2181,7 +2098,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete(napi);
if (adapter->rx_itr_setting & 1)
- ixgbe_set_itr_msix(q_vector);
+ ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter,
((u64)1 << q_vector->v_idx));
@@ -2213,33 +2130,33 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
ixgbe_update_dca(q_vector);
#endif
- r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->txr_count; i++) {
+ 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->txr_idx, adapter->num_tx_queues,
+ r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
r_idx + 1);
}
/* 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->rxr_count ?: 1);
+ budget /= (q_vector->rx.count ?: 1);
budget = max(budget, 1);
- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rxr_count; i++) {
+ 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->rxr_idx, adapter->num_rx_queues,
+ r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
r_idx + 1);
}
- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+ 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_msix(q_vector);
+ ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter,
((u64)1 << q_vector->v_idx));
@@ -2271,7 +2188,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
ixgbe_update_dca(q_vector);
#endif
- r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+ r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
tx_ring = adapter->tx_ring[r_idx];
if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
@@ -2281,7 +2198,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete(napi);
if (adapter->tx_itr_setting & 1)
- ixgbe_set_itr_msix(q_vector);
+ ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter,
((u64)1 << q_vector->v_idx));
@@ -2296,8 +2213,8 @@ 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->rxr_idx);
- q_vector->rxr_count++;
+ set_bit(r_idx, q_vector->rx.idx);
+ q_vector->rx.count++;
rx_ring->q_vector = q_vector;
}
@@ -2307,9 +2224,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->txr_idx);
- q_vector->txr_count++;
+ set_bit(t_idx, q_vector->tx.idx);
+ q_vector->tx.count++;
tx_ring->q_vector = q_vector;
+ q_vector->tx.work_limit = a->tx_work_limit;
}
/**
@@ -2398,10 +2316,10 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
if (err)
return err;
-#define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count) \
+#define SET_HANDLER(_v) (((_v)->rx.count && (_v)->tx.count) \
? &ixgbe_msix_clean_many : \
- (_v)->rxr_count ? &ixgbe_msix_clean_rx : \
- (_v)->txr_count ? &ixgbe_msix_clean_tx : \
+ (_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];
@@ -2433,7 +2351,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
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, netdev);
+ ixgbe_msix_lsc, 0, adapter->lsc_int_name, adapter);
if (err) {
e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
goto free_queue_irqs;
@@ -2452,51 +2370,6 @@ free_queue_irqs:
return err;
}
-static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
-{
- struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
- struct ixgbe_ring *rx_ring = adapter->rx_ring[0];
- struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
- u32 new_itr = q_vector->eitr;
- u8 current_itr;
-
- q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
- q_vector->tx_itr,
- tx_ring->total_packets,
- tx_ring->total_bytes);
- q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr,
- q_vector->rx_itr,
- rx_ring->total_packets,
- rx_ring->total_bytes);
-
- current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
-
- switch (current_itr) {
- /* counts and packets in update_itr are dependent on these numbers */
- case lowest_latency:
- new_itr = 100000;
- break;
- case low_latency:
- new_itr = 20000; /* aka hwitr = ~200 */
- break;
- case bulk_latency:
- new_itr = 8000;
- break;
- default:
- break;
- }
-
- if (new_itr != q_vector->eitr) {
- /* do an exponential smoothing */
- new_itr = ((q_vector->eitr * 9) + new_itr)/10;
-
- /* save the algorithm value here */
- q_vector->eitr = new_itr;
-
- ixgbe_write_eitr(q_vector);
- }
-}
-
/**
* ixgbe_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
@@ -2523,8 +2396,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
default:
break;
}
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
mask |= IXGBE_EIMS_FLOW_DIR;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
@@ -2546,8 +2418,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
**/
static irqreturn_t ixgbe_intr(int irq, void *data)
{
- struct net_device *netdev = data;
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_adapter *adapter = data;
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
u32 eicr;
@@ -2596,10 +2467,6 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
ixgbe_check_fan_failure(adapter, eicr);
if (napi_schedule_prep(&(q_vector->napi))) {
- adapter->tx_ring[0]->total_packets = 0;
- adapter->tx_ring[0]->total_bytes = 0;
- adapter->rx_ring[0]->total_packets = 0;
- adapter->rx_ring[0]->total_bytes = 0;
/* would disable interrupts here but EIAM disabled it */
__napi_schedule(&(q_vector->napi));
}
@@ -2621,10 +2488,10 @@ static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
for (i = 0; i < q_vectors; i++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
- bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES);
- bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES);
- q_vector->rxr_count = 0;
- q_vector->txr_count = 0;
+ 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;
}
}
@@ -2644,10 +2511,10 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
err = ixgbe_request_msix_irqs(adapter);
} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
- netdev->name, netdev);
+ netdev->name, adapter);
} else {
err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
- netdev->name, netdev);
+ netdev->name, adapter);
}
if (err)
@@ -2658,21 +2525,19 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
-
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
int i, q_vectors;
q_vectors = adapter->num_msix_vectors;
i = q_vectors - 1;
- free_irq(adapter->msix_entries[i].vector, netdev);
+ 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]->rxr_count &&
- !adapter->q_vector[i]->txr_count)
+ if (!adapter->q_vector[i]->rx.count &&
+ !adapter->q_vector[i]->tx.count)
continue;
free_irq(adapter->msix_entries[i].vector,
@@ -2681,7 +2546,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
ixgbe_reset_q_vectors(adapter);
} else {
- free_irq(adapter->pdev->irq, netdev);
+ free_irq(adapter->pdev->irq, adapter);
}
}
@@ -2814,7 +2679,8 @@ static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 rttdcs;
- u32 mask;
+ u32 reg;
+ u8 tcs = netdev_get_num_tc(adapter->netdev);
if (hw->mac.type == ixgbe_mac_82598EB)
return;
@@ -2825,22 +2691,27 @@ static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
/* set transmit pool layout */
- mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
- switch (adapter->flags & mask) {
-
+ switch (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
case (IXGBE_FLAG_SRIOV_ENABLED):
IXGBE_WRITE_REG(hw, IXGBE_MTQC,
(IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
break;
+ default:
+ if (!tcs)
+ reg = IXGBE_MTQC_64Q_1PB;
+ else if (tcs <= 4)
+ reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_4TC_4TQ;
+ else
+ reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ;
- case (IXGBE_FLAG_DCB_ENABLED):
- /* We enable 8 traffic classes, DCB only */
- IXGBE_WRITE_REG(hw, IXGBE_MTQC,
- (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
- break;
+ IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg);
- default:
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
+ /* Enable Security TX Buffer IFG for multiple pb */
+ if (tcs) {
+ reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
+ reg |= IXGBE_SECTX_DCB;
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
+ }
break;
}
@@ -2931,7 +2802,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
u32 mrqc = 0, reta = 0;
u32 rxcsum;
int i, j;
- int mask;
+ u8 tcs = netdev_get_num_tc(adapter->netdev);
+ int maxq = adapter->ring_feature[RING_F_RSS].indices;
+
+ if (tcs)
+ maxq = min(maxq, adapter->num_tx_queues / tcs);
/* Fill out hash function seeds */
for (i = 0; i < 10; i++)
@@ -2939,7 +2814,7 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
/* Fill out redirection table */
for (i = 0, j = 0; i < 128; i++, j++) {
- if (j == adapter->ring_feature[RING_F_RSS].indices)
+ if (j == maxq)
j = 0;
/* reta = 4-byte sliding window of
* 0x00..(indices-1)(indices-1)00..etc. */
@@ -2953,33 +2828,28 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
rxcsum |= IXGBE_RXCSUM_PCSD;
IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
- mask = adapter->flags & IXGBE_FLAG_RSS_ENABLED;
- else
- mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
-#ifdef CONFIG_IXGBE_DCB
- | IXGBE_FLAG_DCB_ENABLED
-#endif
- | IXGBE_FLAG_SRIOV_ENABLED
- );
-
- switch (mask) {
-#ifdef CONFIG_IXGBE_DCB
- case (IXGBE_FLAG_DCB_ENABLED | IXGBE_FLAG_RSS_ENABLED):
- mrqc = IXGBE_MRQC_RTRSS8TCEN;
- break;
- case (IXGBE_FLAG_DCB_ENABLED):
- mrqc = IXGBE_MRQC_RT8TCEN;
- break;
-#endif /* CONFIG_IXGBE_DCB */
- case (IXGBE_FLAG_RSS_ENABLED):
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB &&
+ (adapter->flags & IXGBE_FLAG_RSS_ENABLED)) {
mrqc = IXGBE_MRQC_RSSEN;
- break;
- case (IXGBE_FLAG_SRIOV_ENABLED):
- mrqc = IXGBE_MRQC_VMDQEN;
- break;
- default:
- break;
+ } else {
+ int mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
+ | IXGBE_FLAG_SRIOV_ENABLED);
+
+ switch (mask) {
+ case (IXGBE_FLAG_RSS_ENABLED):
+ if (!tcs)
+ mrqc = IXGBE_MRQC_RSSEN;
+ else if (tcs <= 4)
+ mrqc = IXGBE_MRQC_RTRSS4TCEN;
+ else
+ mrqc = IXGBE_MRQC_RTRSS8TCEN;
+ break;
+ case (IXGBE_FLAG_SRIOV_ENABLED):
+ mrqc = IXGBE_MRQC_VMDQEN;
+ break;
+ default:
+ break;
+ }
}
/* Perform hash on these packet types */
@@ -2992,28 +2862,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_clear_rscctl - disable RSC for the indicated ring
- * @adapter: address of board private structure
- * @ring: structure containing ring specific data
- **/
-void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *ring)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- u32 rscctrl;
- u8 reg_idx = ring->reg_idx;
-
- rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx));
- rscctrl &= ~IXGBE_RSCCTL_RSCEN;
- IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
-}
-
-/**
* ixgbe_configure_rscctl - enable RSC for the indicated ring
* @adapter: address of board private structure
* @index: index of ring to set
**/
-void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
+static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring)
{
struct ixgbe_hw *hw = &adapter->hw;
@@ -3183,7 +3036,7 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
ixgbe_rx_desc_queue_enable(adapter, ring);
- ixgbe_alloc_rx_buffers(ring, IXGBE_DESC_UNUSED(ring));
+ ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
}
static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
@@ -3681,10 +3534,10 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
q_vector = adapter->q_vector[q_idx];
napi = &q_vector->napi;
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- if (!q_vector->rxr_count || !q_vector->txr_count) {
- if (q_vector->txr_count == 1)
+ if (!q_vector->rx.count || !q_vector->tx.count) {
+ if (q_vector->tx.count == 1)
napi->poll = &ixgbe_clean_txonly;
- else if (q_vector->rxr_count == 1)
+ else if (q_vector->rx.count == 1)
napi->poll = &ixgbe_clean_rxonly;
}
}
@@ -3739,7 +3592,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
/* reconfigure the hardware */
- if (adapter->dcbx_cap & (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE)) {
+ if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE) {
#ifdef CONFIG_FCOE
if (adapter->netdev->features & NETIF_F_FCOE_MTU)
max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
@@ -3779,12 +3632,51 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
}
#endif
+
+static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
+{
+ int hdrm = 0;
+ int num_tc = netdev_get_num_tc(adapter->netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+ adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ hdrm = 64 << adapter->fdir_pballoc;
+
+ hw->mac.ops.set_rxpba(&adapter->hw, num_tc, hdrm, PBA_STRATEGY_EQUAL);
+}
+
+static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *filter;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ if (!hlist_empty(&adapter->fdir_filter_list))
+ ixgbe_fdir_set_input_mask_82599(hw, &adapter->fdir_mask);
+
+ hlist_for_each_entry_safe(filter, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ ixgbe_fdir_write_perfect_filter_82599(hw,
+ &filter->filter,
+ filter->sw_idx,
+ (filter->action == IXGBE_FDIR_DROP_QUEUE) ?
+ IXGBE_FDIR_DROP_QUEUE :
+ adapter->rx_ring[filter->action]->reg_idx);
+ }
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+}
+
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
@@ -3803,7 +3695,9 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
adapter->atr_sample_rate;
ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
- ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc);
+ ixgbe_init_fdir_perfect_82599(&adapter->hw,
+ adapter->fdir_pballoc);
+ ixgbe_fdir_filter_restore(adapter);
}
ixgbe_configure_virtualization(adapter);
@@ -4180,6 +4074,23 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
ixgbe_clean_tx_ring(adapter->tx_ring[i]);
}
+static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
+{
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *filter;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ hlist_for_each_entry_safe(filter, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ hlist_del(&filter->fdir_node);
+ kfree(filter);
+ }
+ adapter->fdir_filter_count = 0;
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+}
+
void ixgbe_down(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -4306,7 +4217,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete(napi);
if (adapter->rx_itr_setting & 1)
- ixgbe_set_itr(adapter);
+ ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
}
@@ -4369,15 +4280,13 @@ static inline bool ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
f_fdir->mask = 0;
/* Flow Director must have RSS enabled */
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
- ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)))) {
+ if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+ (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) {
adapter->num_tx_queues = f_fdir->indices;
adapter->num_rx_queues = f_fdir->indices;
ret = true;
} else {
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
}
return ret;
}
@@ -4400,69 +4309,72 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
return false;
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-#ifdef CONFIG_IXGBE_DCB
- int tc;
- struct net_device *dev = adapter->netdev;
+ f->indices = min((int)num_online_cpus(), f->indices);
- tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
- f->indices = dev->tc_to_txq[tc].count;
- f->mask = dev->tc_to_txq[tc].offset;
-#endif
- } else {
- f->indices = min((int)num_online_cpus(), f->indices);
-
- adapter->num_rx_queues = 1;
- adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 1;
+ adapter->num_tx_queues = 1;
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
- e_info(probe, "FCoE enabled with RSS\n");
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
- ixgbe_set_fdir_queues(adapter);
- else
- ixgbe_set_rss_queues(adapter);
- }
- /* adding FCoE rx rings to the end */
- f->mask = adapter->num_rx_queues;
- adapter->num_rx_queues += f->indices;
- adapter->num_tx_queues += f->indices;
+ if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
+ e_info(probe, "FCoE enabled with RSS\n");
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
+ ixgbe_set_fdir_queues(adapter);
+ else
+ ixgbe_set_rss_queues(adapter);
}
+ /* adding FCoE rx rings to the end */
+ f->mask = adapter->num_rx_queues;
+ adapter->num_rx_queues += f->indices;
+ adapter->num_tx_queues += f->indices;
+
return true;
}
#endif /* IXGBE_FCOE */
+/* Artificial max queue cap per traffic class in DCB mode */
+#define DCB_QUEUE_CAP 8
+
#ifdef CONFIG_IXGBE_DCB
static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
{
- bool ret = false;
- struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_DCB];
- int i, q;
+ int per_tc_q, q, i, offset = 0;
+ struct net_device *dev = adapter->netdev;
+ int tcs = netdev_get_num_tc(dev);
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
- return ret;
+ if (!tcs)
+ return false;
- f->indices = 0;
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
- q = min((int)num_online_cpus(), MAX_TRAFFIC_CLASS);
- f->indices += q;
+ /* Map queue offset and counts onto allocated tx queues */
+ per_tc_q = min(dev->num_tx_queues / tcs, (unsigned int)DCB_QUEUE_CAP);
+ 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;
}
- f->mask = 0x7 << 3;
- adapter->num_rx_queues = f->indices;
- adapter->num_tx_queues = f->indices;
- ret = true;
+ adapter->num_tx_queues = q * tcs;
+ adapter->num_rx_queues = q * tcs;
#ifdef IXGBE_FCOE
- /* FCoE enabled queues require special configuration done through
- * configure_fcoe() and others. Here we map FCoE indices onto the
- * DCB queue pairs allowing FCoE to own configuration later.
+ /* FCoE enabled queues require special configuration indexed
+ * by feature specific indices and mask. Here we map FCoE
+ * indices onto the DCB queue pairs allowing FCoE to own
+ * configuration later.
*/
- ixgbe_set_fcoe_queues(adapter);
+ if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+ int tc;
+ struct ixgbe_ring_feature *f =
+ &adapter->ring_feature[RING_F_FCOE];
+
+ tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
+ f->indices = dev->tc_to_txq[tc].count;
+ f->mask = dev->tc_to_txq[tc].offset;
+ }
#endif
- return ret;
+ return true;
}
#endif
@@ -4616,8 +4528,8 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- *tx = tc << 3;
- *rx = tc << 2;
+ *tx = tc << 2;
+ *rx = tc << 3;
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
@@ -4657,55 +4569,6 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
}
}
-#define IXGBE_MAX_Q_PER_TC (IXGBE_MAX_DCB_INDICES / MAX_TRAFFIC_CLASS)
-
-/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
- * classes.
- *
- * @netdev: net device to configure
- * @tc: number of traffic classes to enable
- */
-int ixgbe_setup_tc(struct net_device *dev, u8 tc)
-{
- int i;
- unsigned int q, offset = 0;
-
- if (!tc) {
- netdev_reset_tc(dev);
- } else {
- struct ixgbe_adapter *adapter = netdev_priv(dev);
-
- /* Hardware supports up to 8 traffic classes */
- if (tc > MAX_TRAFFIC_CLASS || netdev_set_num_tc(dev, tc))
- return -EINVAL;
-
- /* Partition Tx queues evenly amongst traffic classes */
- for (i = 0; i < tc; i++) {
- q = min((int)num_online_cpus(), IXGBE_MAX_Q_PER_TC);
- netdev_set_prio_tc_map(dev, i, i);
- netdev_set_tc_queue(dev, i, q, offset);
- offset += q;
- }
-
- /* This enables multiple traffic class support in the hardware
- * which defaults to strict priority transmission by default.
- * If traffic classes are already enabled perhaps through DCB
- * code path then existing configuration will be used.
- */
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
- dev->dcbnl_ops && dev->dcbnl_ops->setdcbx) {
- struct ieee_ets ets = {
- .prio_tc = {0, 1, 2, 3, 4, 5, 6, 7},
- };
- u8 mode = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
-
- dev->dcbnl_ops->setdcbx(dev, mode);
- dev->dcbnl_ops->ieee_setets(dev, &ets);
- }
- }
- return 0;
-}
-
/**
* ixgbe_cache_ring_dcb - Descriptor ring to register mapping for DCB
* @adapter: board private structure to initialize
@@ -4719,7 +4582,7 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
int i, j, k;
u8 num_tcs = netdev_get_num_tc(dev);
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+ if (!num_tcs)
return false;
for (i = 0, k = 0; i < num_tcs; i++) {
@@ -4751,9 +4614,8 @@ static inline bool ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
int i;
bool ret = false;
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
- ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) {
+ if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+ (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) {
for (i = 0; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i]->reg_idx = i;
for (i = 0; i < adapter->num_tx_queues; i++)
@@ -4782,8 +4644,7 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
return false;
if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
ixgbe_cache_ring_fdir(adapter);
else
ixgbe_cache_ring_rss(adapter);
@@ -4963,14 +4824,12 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
- if (adapter->flags & (IXGBE_FLAG_FDIR_HASH_CAPABLE |
- IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
e_err(probe,
- "Flow Director is not supported while multiple "
+ "ATR is not supported while multiple "
"queues are disabled. Disabling Flow Director\n");
}
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
adapter->atr_sample_rate = 0;
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
ixgbe_disable_sriov(adapter);
@@ -5024,7 +4883,7 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
if (!q_vector)
goto err_out;
q_vector->adapter = adapter;
- if (q_vector->txr_count && !q_vector->rxr_count)
+ if (q_vector->tx.count && !q_vector->rx.count)
q_vector->eitr = adapter->tx_eitr_param;
else
q_vector->eitr = adapter->rx_eitr_param;
@@ -5201,7 +5060,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
adapter->ring_feature[RING_F_RSS].indices = rss;
adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
- adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
if (hw->device_id == IXGBE_DEV_ID_82598AT)
@@ -5215,21 +5073,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM)
adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
- /* n-tuple support exists, always init our spinlock */
- spin_lock_init(&adapter->fdir_perfect_lock);
/* Flow Director hash filters enabled */
adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
adapter->atr_sample_rate = 20;
adapter->ring_feature[RING_F_FDIR].indices =
IXGBE_MAX_FDIR_INDICES;
- adapter->fdir_pballoc = 0;
+ adapter->fdir_pballoc = IXGBE_FDIR_PBALLOC_64K;
#ifdef IXGBE_FCOE
adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
adapter->ring_feature[RING_F_FCOE].indices = 0;
#ifdef CONFIG_IXGBE_DCB
/* Default traffic class to use for FCoE */
- adapter->fcoe.tc = IXGBE_FCOE_DEFTC;
adapter->fcoe.up = IXGBE_FCOE_DEFTC;
#endif
#endif /* IXGBE_FCOE */
@@ -5238,6 +5093,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
break;
}
+ /* n-tuple support exists, always init our spinlock */
+ spin_lock_init(&adapter->fdir_perfect_lock);
+
#ifdef CONFIG_IXGBE_DCB
/* Configure DCB traffic classes */
for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
@@ -5250,7 +5108,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
}
adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
- adapter->dcb_cfg.rx_pba_cfg = pba_equal;
adapter->dcb_cfg.pfc_mode_enable = false;
adapter->dcb_set_bitmap = 0x00;
adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
@@ -5285,6 +5142,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->tx_ring_count = IXGBE_DEFAULT_TXD;
adapter->rx_ring_count = IXGBE_DEFAULT_RXD;
+ /* set default work limits */
+ adapter->tx_work_limit = adapter->tx_ring_count;
+
/* initialize eeprom parameters */
if (ixgbe_init_eeprom_params_generic(hw)) {
e_dev_err("EEPROM initialization failed\n");
@@ -5331,7 +5191,6 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
- tx_ring->work_limit = tx_ring->count;
return 0;
err:
@@ -5620,6 +5479,8 @@ static int ixgbe_close(struct net_device *netdev)
ixgbe_down(adapter);
ixgbe_free_irq(adapter);
+ ixgbe_fdir_filter_exit(adapter);
+
ixgbe_free_all_tx_resources(adapter);
ixgbe_free_all_rx_resources(adapter);
@@ -6038,7 +5899,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->rxr_count || qv->txr_count)
+ if (qv->rx.count || qv->tx.count)
eics |= ((u64)1 << i);
}
}
@@ -6143,9 +6004,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
(flow_tx ? "TX" : "None"))));
netif_carrier_on(netdev);
-#ifdef HAVE_IPLINK_VF_CONFIG
ixgbe_check_vf_rate_limit(adapter);
-#endif /* HAVE_IPLINK_VF_CONFIG */
}
/**
@@ -6404,179 +6263,145 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_service_event_complete(adapter);
}
-static int ixgbe_tso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
- u32 tx_flags, u8 *hdr_len, __be16 protocol)
+void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
+ u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx)
{
struct ixgbe_adv_tx_context_desc *context_desc;
- unsigned int i;
- int err;
- struct ixgbe_tx_buffer *tx_buffer_info;
- u32 vlan_macip_lens = 0, type_tucmd_mlhl;
- u32 mss_l4len_idx, l4len;
+ u16 i = tx_ring->next_to_use;
- if (skb_is_gso(skb)) {
- if (skb_header_cloned(skb)) {
- err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
- if (err)
- return err;
- }
- l4len = tcp_hdrlen(skb);
- *hdr_len += l4len;
-
- if (protocol == htons(ETH_P_IP)) {
- struct iphdr *iph = ip_hdr(skb);
- iph->tot_len = 0;
- iph->check = 0;
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
- } 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);
- }
+ context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
- i = tx_ring->next_to_use;
+ i++;
+ tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
-
- /* VLAN MACLEN IPLEN */
- if (tx_flags & IXGBE_TX_FLAGS_VLAN)
- vlan_macip_lens |=
- (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
- vlan_macip_lens |= ((skb_network_offset(skb)) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
- *hdr_len += skb_network_offset(skb);
- vlan_macip_lens |=
- (skb_transport_header(skb) - skb_network_header(skb));
- *hdr_len +=
- (skb_transport_header(skb) - skb_network_header(skb));
- context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
- context_desc->seqnum_seed = 0;
-
- /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
- type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
+ /* set bits to identify this as an advanced context descriptor */
+ type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
- if (protocol == htons(ETH_P_IP))
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
- context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
-
- /* MSS L4LEN IDX */
- mss_l4len_idx =
- (skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT);
- mss_l4len_idx |= (l4len << IXGBE_ADVTXD_L4LEN_SHIFT);
- /* use index 1 for TSO */
- mss_l4len_idx |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
- context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
+ context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
+ context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
+ context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
+ context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
+}
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
+static int ixgbe_tso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+ u32 tx_flags, __be16 protocol, u8 *hdr_len)
+{
+ int err;
+ u32 vlan_macip_lens, type_tucmd;
+ u32 mss_l4len_idx, l4len;
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
+ if (!skb_is_gso(skb))
+ return 0;
- return true;
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+ return err;
}
- return false;
-}
-static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb,
- __be16 protocol)
+ /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
+ type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
+
+ if (protocol == __constant_htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+ iph->tot_len = 0;
+ iph->check = 0;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0,
+ IPPROTO_TCP,
+ 0);
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_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);
+ }
+
+ l4len = tcp_hdrlen(skb);
+ *hdr_len = skb_transport_offset(skb) + l4len;
+
+ /* mss_l4len_id: use 1 as index for TSO */
+ mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT;
+ mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
+ mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
+
+ /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+ vlan_macip_lens = skb_network_header_len(skb);
+ vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
+
+ ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd,
+ mss_l4len_idx);
+
+ return 1;
+}
+
+static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
+ struct sk_buff *skb, u32 tx_flags,
+ __be16 protocol)
{
- u32 rtn = 0;
+ u32 vlan_macip_lens = 0;
+ u32 mss_l4len_idx = 0;
+ u32 type_tucmd = 0;
- switch (protocol) {
- case cpu_to_be16(ETH_P_IP):
- rtn |= IXGBE_ADVTXD_TUCMD_IPV4;
- switch (ip_hdr(skb)->protocol) {
- case IPPROTO_TCP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ if (!(tx_flags & IXGBE_TX_FLAGS_VLAN))
+ return false;
+ } else {
+ u8 l4_hdr = 0;
+ switch (protocol) {
+ case __constant_htons(ETH_P_IP):
+ vlan_macip_lens |= skb_network_header_len(skb);
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+ l4_hdr = ip_hdr(skb)->protocol;
break;
- case IPPROTO_SCTP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ 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",
+ skb->protocol);
+ }
break;
}
- break;
- case cpu_to_be16(ETH_P_IPV6):
- /* XXX what about other V6 headers?? */
- switch (ipv6_hdr(skb)->nexthdr) {
+
+ switch (l4_hdr) {
case IPPROTO_TCP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ mss_l4len_idx = tcp_hdrlen(skb) <<
+ IXGBE_ADVTXD_L4LEN_SHIFT;
break;
case IPPROTO_SCTP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ mss_l4len_idx = sizeof(struct sctphdr) <<
+ IXGBE_ADVTXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_UDP:
+ mss_l4len_idx = sizeof(struct udphdr) <<
+ IXGBE_ADVTXD_L4LEN_SHIFT;
+ break;
+ default:
+ if (unlikely(net_ratelimit())) {
+ dev_warn(tx_ring->dev,
+ "partial checksum but l4 proto=%x!\n",
+ skb->protocol);
+ }
break;
}
- break;
- default:
- if (unlikely(net_ratelimit()))
- e_warn(probe, "partial checksum but proto=%x!\n",
- protocol);
- break;
}
- return rtn;
-}
-
-static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags,
- __be16 protocol)
-{
- struct ixgbe_adv_tx_context_desc *context_desc;
- unsigned int i;
- struct ixgbe_tx_buffer *tx_buffer_info;
- u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
-
- if (skb->ip_summed == CHECKSUM_PARTIAL ||
- (tx_flags & IXGBE_TX_FLAGS_VLAN)) {
- i = tx_ring->next_to_use;
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
-
- if (tx_flags & IXGBE_TX_FLAGS_VLAN)
- vlan_macip_lens |=
- (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
- vlan_macip_lens |= (skb_network_offset(skb) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- vlan_macip_lens |= (skb_transport_header(skb) -
- skb_network_header(skb));
-
- context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
- context_desc->seqnum_seed = 0;
-
- type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
+ vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- type_tucmd_mlhl |= ixgbe_psum(adapter, skb, protocol);
+ ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0,
+ type_tucmd, mss_l4len_idx);
- context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
- /* use index zero for tx checksum offload */
- context_desc->mss_l4len_idx = 0;
-
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
-
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
-
- return true;
- }
-
- return false;
+ return (skb->ip_summed == CHECKSUM_PARTIAL);
}
static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
@@ -6588,11 +6413,12 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
struct ixgbe_tx_buffer *tx_buffer_info;
unsigned int len;
unsigned int total = skb->len;
- unsigned int offset = 0, size, count = 0, i;
+ 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;
i = tx_ring->next_to_use;
@@ -6858,7 +6684,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
input, common, ring->queue_index);
}
-static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
+static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
{
netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
/* Herbert's original patch had:
@@ -6868,7 +6694,7 @@ static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
/* We need to check again in a case another CPU has just
* made room available. */
- if (likely(IXGBE_DESC_UNUSED(tx_ring) < size))
+ if (likely(ixgbe_desc_unused(tx_ring) < size))
return -EBUSY;
/* A reprieve! - use start_queue because it doesn't call schedule */
@@ -6877,9 +6703,9 @@ static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
return 0;
}
-static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
+static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
{
- if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
+ if (likely(ixgbe_desc_unused(tx_ring) >= size))
return 0;
return __ixgbe_maybe_stop_tx(tx_ring, size);
}
@@ -6887,11 +6713,10 @@ static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
- int txq = smp_processor_id();
+ int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
+ smp_processor_id();
#ifdef IXGBE_FCOE
- __be16 protocol;
-
- protocol = vlan_get_protocol(skb);
+ __be16 protocol = vlan_get_protocol(skb);
if (((protocol == htons(ETH_P_FCOE)) ||
(protocol == htons(ETH_P_FIP))) &&
@@ -6915,13 +6740,33 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring)
{
- unsigned int first;
- unsigned int tx_flags = 0;
- u8 hdr_len = 0;
int tso;
- int count = 0;
- unsigned int f;
+ 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;
+ u8 hdr_len = 0;
+
+ /*
+ * need: 1 descriptor per page * PAGE_SIZE/IXGBE_MAX_DATA_PER_TXD,
+ * + 1 desc for skb_head_len/IXGBE_MAX_DATA_PER_TXD,
+ * + 2 desc gap to keep tail from touching head,
+ * + 1 desc for context descriptor,
+ * otherwise try next time
+ */
+#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
+ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
+ count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
+#else
+ count += skb_shinfo(skb)->nr_frags;
+#endif
+ if (ixgbe_maybe_stop_tx(tx_ring, count + 3)) {
+ tx_ring->tx_stats.tx_busy++;
+ return NETDEV_TX_BUSY;
+ }
protocol = vlan_get_protocol(skb);
@@ -6946,51 +6791,29 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
(protocol == htons(ETH_P_FCOE)))
tx_flags |= IXGBE_TX_FLAGS_FCOE;
-#endif
-
- /* four things can cause us to need a context descriptor */
- if (skb_is_gso(skb) ||
- (skb->ip_summed == CHECKSUM_PARTIAL) ||
- (tx_flags & IXGBE_TX_FLAGS_VLAN) ||
- (tx_flags & IXGBE_TX_FLAGS_FCOE))
- count++;
-
- 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);
-
- if (ixgbe_maybe_stop_tx(tx_ring, count)) {
- tx_ring->tx_stats.tx_busy++;
- return NETDEV_TX_BUSY;
- }
+#endif
+ /* record the location of the first descriptor for this packet */
first = tx_ring->next_to_use;
+
if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
#ifdef IXGBE_FCOE
/* setup tx offload for FCoE */
- tso = ixgbe_fso(adapter, tx_ring, skb, tx_flags, &hdr_len);
- if (tso < 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
- if (tso)
+ 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(adapter, tx_ring, skb, tx_flags, &hdr_len,
- protocol);
- if (tso < 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
- if (tso)
+ 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(adapter, tx_ring, skb, tx_flags,
- protocol) &&
- (skb->ip_summed == CHECKSUM_PARTIAL))
+ else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
tx_flags |= IXGBE_TX_FLAGS_CSUM;
}
@@ -7003,12 +6826,16 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
} else {
- dev_kfree_skb_any(skb);
tx_ring->tx_buffer_info[first].time_stamp = 0;
tx_ring->next_to_use = first;
+ goto out_drop;
}
return NETDEV_TX_OK;
+
+out_drop:
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -7198,6 +7025,177 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev,
return stats;
}
+/* ixgbe_validate_rtr - verify 802.1Qp to Rx packet buffer mapping is valid.
+ * #adapter: pointer to ixgbe_adapter
+ * @tc: number of traffic classes currently enabled
+ *
+ * Configure a valid 802.1Qp to Rx packet buffer mapping ie confirm
+ * 802.1Q priority maps to a packet buffer that exists.
+ */
+static void ixgbe_validate_rtr(struct ixgbe_adapter *adapter, u8 tc)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reg, rsave;
+ int i;
+
+ /* 82598 have a static priority to TC mapping that can not
+ * be changed so no validation is needed.
+ */
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return;
+
+ reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
+ rsave = reg;
+
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ u8 up2tc = reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT);
+
+ /* If up2tc is out of bounds default to zero */
+ if (up2tc > tc)
+ reg &= ~(0x7 << IXGBE_RTRUP2TC_UP_SHIFT);
+ }
+
+ if (reg != rsave)
+ IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, reg);
+
+ return;
+}
+
+
+/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
+ * classes.
+ *
+ * @netdev: net device to configure
+ * @tc: number of traffic classes to enable
+ */
+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;
+
+ /* Hardware supports up to 8 traffic classes */
+ if (tc > MAX_TRAFFIC_CLASS ||
+ (hw->mac.type == ixgbe_mac_82598EB && tc < MAX_TRAFFIC_CLASS))
+ return -EINVAL;
+
+ /* Hardware has to reinitialize queues and interrupts to
+ * match packet buffer alignment. Unfortunantly, the
+ * hardware is not flexible enough to do this dynamically.
+ */
+ if (netif_running(dev))
+ ixgbe_close(dev);
+ ixgbe_clear_interrupt_scheme(adapter);
+
+ if (tc)
+ netdev_set_num_tc(dev, tc);
+ else
+ netdev_reset_tc(dev);
+
+ ixgbe_init_interrupt_scheme(adapter);
+ ixgbe_validate_rtr(adapter, tc);
+ if (netif_running(dev))
+ ixgbe_open(dev);
+
+ return 0;
+}
+
+void ixgbe_do_reset(struct net_device *netdev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ if (netif_running(netdev))
+ ixgbe_reinit_locked(adapter);
+ else
+ ixgbe_reset(adapter);
+}
+
+static u32 ixgbe_fix_features(struct net_device *netdev, u32 data)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+#ifdef CONFIG_DCB
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
+ data &= ~NETIF_F_HW_VLAN_RX;
+#endif
+
+ /* return error if RXHASH is being enabled when RSS is not supported */
+ if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
+ data &= ~NETIF_F_RXHASH;
+
+ /* If Rx checksum is disabled, then RSC/LRO should also be disabled */
+ if (!(data & NETIF_F_RXCSUM))
+ data &= ~NETIF_F_LRO;
+
+ /* Turn off LRO if not RSC capable or invalid ITR settings */
+ if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
+ data &= ~NETIF_F_LRO;
+ } else if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
+ (adapter->rx_itr_setting != 1 &&
+ adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE)) {
+ data &= ~NETIF_F_LRO;
+ e_info(probe, "rx-usecs set too low, not enabling RSC\n");
+ }
+
+ return data;
+}
+
+static int ixgbe_set_features(struct net_device *netdev, u32 data)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ bool need_reset = false;
+
+ /* If Rx checksum is disabled, then RSC/LRO should also be disabled */
+ if (!(data & NETIF_F_RXCSUM))
+ adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
+ else
+ adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+
+ /* Make sure RSC matches LRO, reset if change */
+ if (!!(data & NETIF_F_LRO) !=
+ !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) {
+ adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X540:
+ case ixgbe_mac_82599EB:
+ need_reset = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Check if Flow Director n-tuple support was enabled or disabled. If
+ * the state changed, we need to reset.
+ */
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ /* turn off ATR, enable perfect filters and reset */
+ if (data & NETIF_F_NTUPLE) {
+ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+ adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+ need_reset = true;
+ }
+ } else if (!(data & NETIF_F_NTUPLE)) {
+ /* turn off Flow Director, set ATR and reset */
+ adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+ if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+ !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+ adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+ need_reset = true;
+ }
+
+ if (need_reset)
+ ixgbe_do_reset(netdev);
+
+ return 0;
+
+}
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
@@ -7218,9 +7216,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_vf_tx_rate = ixgbe_ndo_set_vf_bw,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_stats64 = ixgbe_get_stats64,
-#ifdef CONFIG_IXGBE_DCB
.ndo_setup_tc = ixgbe_setup_tc,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ixgbe_netpoll,
#endif
@@ -7232,6 +7228,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_fcoe_disable = ixgbe_fcoe_disable,
.ndo_fcoe_get_wwn = ixgbe_fcoe_get_wwn,
#endif /* IXGBE_FCOE */
+ .ndo_set_features = ixgbe_set_features,
+ .ndo_fix_features = ixgbe_fix_features,
};
static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
@@ -7379,14 +7377,16 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
pci_set_master(pdev);
pci_save_state(pdev);
+#ifdef CONFIG_IXGBE_DCB
+ indices *= MAX_TRAFFIC_CLASS;
+#endif
+
if (ii->mac == ixgbe_mac_82598EB)
indices = min_t(unsigned int, indices, IXGBE_MAX_RSS_INDICES);
else
indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES);
-#if defined(CONFIG_DCB)
- indices = max_t(unsigned int, indices, IXGBE_MAX_DCB_INDICES);
-#elif defined(IXGBE_FCOE)
+#ifdef IXGBE_FCOE
indices += min_t(unsigned int, num_possible_cpus(),
IXGBE_MAX_FCOE_INDICES);
#endif
@@ -7497,20 +7497,24 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->features = NETIF_F_SG |
NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
- NETIF_F_HW_VLAN_FILTER;
+ NETIF_F_HW_VLAN_FILTER |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_GRO |
+ NETIF_F_RXHASH |
+ NETIF_F_RXCSUM;
- netdev->features |= NETIF_F_IPV6_CSUM;
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- netdev->features |= NETIF_F_GRO;
- netdev->features |= NETIF_F_RXHASH;
+ netdev->hw_features = netdev->features;
switch (adapter->hw.mac.type) {
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
netdev->features |= NETIF_F_SCTP_CSUM;
+ netdev->hw_features |= NETIF_F_SCTP_CSUM |
+ NETIF_F_NTUPLE;
break;
default:
break;
@@ -7549,6 +7553,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_HIGHDMA;
}
+ if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
+ netdev->hw_features |= NETIF_F_LRO;
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
netdev->features |= NETIF_F_LRO;
@@ -7585,25 +7591,24 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
if (err)
goto err_sw_init;
- if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
+ if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) {
+ netdev->hw_features &= ~NETIF_F_RXHASH;
netdev->features &= ~NETIF_F_RXHASH;
+ }
switch (pdev->device) {
case IXGBE_DEV_ID_82599_SFP:
/* Only this subdevice supports WOL */
if (pdev->subsystem_device == IXGBE_SUBDEV_ID_82599_SFP)
- adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
- IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+ adapter->wol = IXGBE_WUFC_MAG;
break;
case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
/* All except this subdevice support WOL */
if (pdev->subsystem_device != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)
- adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
- IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+ adapter->wol = IXGBE_WUFC_MAG;
break;
case IXGBE_DEV_ID_82599_KX4:
- adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
- IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+ adapter->wol = IXGBE_WUFC_MAG;
break;
default:
adapter->wol = 0;
@@ -7678,6 +7683,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
ixgbe_vf_configuration(pdev, (i | 0x10000000));
}
+ /* Inform firmware of driver version */
+ if (hw->mac.ops.set_fw_drv_ver)
+ hw->mac.ops.set_fw_drv_ver(hw, MAJ, MIN, BUILD,
+ FW_CEM_UNUSED_VER);
+
/* add san mac addr to netdev */
ixgbe_add_sanmac_netdev(netdev);
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c
index ac99b0458fe2..d99d01e21326 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ixgbe/ixgbe_sriov.c
@@ -605,6 +605,22 @@ static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate,
}
IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, 2*vf); /* vf Y uses queue 2*Y */
+ /*
+ * Set global transmit compensation time to the MMW_SIZE in RTTBCNRM
+ * register. Typically MMW_SIZE=0x014 if 9728-byte jumbo is supported
+ * and 0x004 otherwise.
+ */
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x4);
+ break;
+ case ixgbe_mac_X540:
+ IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x14);
+ break;
+ default:
+ break;
+ }
+
IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val);
}
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index fa43f2507f43..e0d970ebab7a 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -534,7 +534,7 @@
#define IXGBE_RTTBCNRC_RF_INT_SHIFT 14
#define IXGBE_RTTBCNRC_RF_INT_MASK \
(IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT)
-
+#define IXGBE_RTTBCNRM 0x04980
/* FCoE DMA Context Registers */
#define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */
@@ -707,6 +707,13 @@
#define IXGBE_HFDR 0x15FE8
#define IXGBE_FLEX_MNG 0x15800 /* 0x15800 - 0x15EFC */
+#define IXGBE_HICR_EN 0x01 /* Enable bit - RO */
+/* Driver sets this bit when done to put command in RAM */
+#define IXGBE_HICR_C 0x02
+#define IXGBE_HICR_SV 0x04 /* Status Validity */
+#define IXGBE_HICR_FW_RESET_ENABLE 0x40
+#define IXGBE_HICR_FW_RESET 0x80
+
/* PCI-E registers */
#define IXGBE_GCR 0x11000
#define IXGBE_GTV 0x11004
@@ -1118,6 +1125,27 @@
#define IXGBE_GPIE_VTMODE_32 0x00008000 /* 32 VFs 4 queues per VF */
#define IXGBE_GPIE_VTMODE_64 0x0000C000 /* 64 VFs 2 queues per VF */
+/* Packet Buffer Initialization */
+#define IXGBE_TXPBSIZE_20KB 0x00005000 /* 20KB Packet Buffer */
+#define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */
+#define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */
+#define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */
+#define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */
+#define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */
+#define IXGBE_RXPBSIZE_MAX 0x00080000 /* 512KB Packet Buffer*/
+#define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer*/
+
+#define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */
+#define IXGBE_MAX_PB 8
+
+/* Packet buffer allocation strategies */
+enum {
+ PBA_STRATEGY_EQUAL = 0, /* Distribute PB space equally */
+#define PBA_STRATEGY_EQUAL PBA_STRATEGY_EQUAL
+ PBA_STRATEGY_WEIGHTED = 1, /* Weight front half of TCs */
+#define PBA_STRATEGY_WEIGHTED PBA_STRATEGY_WEIGHTED
+};
+
/* Transmit Flow Control status */
#define IXGBE_TFCS_TXOFF 0x00000001
#define IXGBE_TFCS_TXOFF0 0x00000100
@@ -1860,6 +1888,7 @@
#define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */
#define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */
#define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */
+#define IXGBE_MTQC_4TC_4TQ 0x8 /* 4 TC if RT_ENA or 4 TQ if VT_ENA */
/* Receive Descriptor bit definitions */
#define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */
@@ -2027,9 +2056,10 @@
#define IXGBE_VFLREC(_i) (0x00700 + (_i * 4))
enum ixgbe_fdir_pballoc_type {
- IXGBE_FDIR_PBALLOC_64K = 0,
- IXGBE_FDIR_PBALLOC_128K,
- IXGBE_FDIR_PBALLOC_256K,
+ IXGBE_FDIR_PBALLOC_NONE = 0,
+ IXGBE_FDIR_PBALLOC_64K = 1,
+ IXGBE_FDIR_PBALLOC_128K = 2,
+ IXGBE_FDIR_PBALLOC_256K = 3,
};
#define IXGBE_FDIR_PBALLOC_SIZE_SHIFT 16
@@ -2083,7 +2113,7 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIRCMD_CMD_ADD_FLOW 0x00000001
#define IXGBE_FDIRCMD_CMD_REMOVE_FLOW 0x00000002
#define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT 0x00000003
-#define IXGBE_FDIRCMD_CMD_QUERY_REM_HASH 0x00000007
+#define IXGBE_FDIRCMD_FILTER_VALID 0x00000004
#define IXGBE_FDIRCMD_FILTER_UPDATE 0x00000008
#define IXGBE_FDIRCMD_IPv6DMATCH 0x00000010
#define IXGBE_FDIRCMD_L4TYPE_UDP 0x00000020
@@ -2102,6 +2132,44 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIR_INIT_DONE_POLL 10
#define IXGBE_FDIRCMD_CMD_POLL 10
+#define IXGBE_FDIR_DROP_QUEUE 127
+
+/* Manageablility Host Interface defines */
+#define IXGBE_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */
+#define IXGBE_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */
+#define IXGBE_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */
+
+/* CEM Support */
+#define FW_CEM_HDR_LEN 0x4
+#define FW_CEM_CMD_DRIVER_INFO 0xDD
+#define FW_CEM_CMD_DRIVER_INFO_LEN 0x5
+#define FW_CEM_CMD_RESERVED 0x0
+#define FW_CEM_UNUSED_VER 0x0
+#define FW_CEM_MAX_RETRIES 3
+#define FW_CEM_RESP_STATUS_SUCCESS 0x1
+
+/* Host Interface Command Structures */
+struct ixgbe_hic_hdr {
+ u8 cmd;
+ u8 buf_len;
+ union {
+ u8 cmd_resv;
+ u8 ret_status;
+ } cmd_or_resp;
+ u8 checksum;
+};
+
+struct ixgbe_hic_drv_info {
+ struct ixgbe_hic_hdr hdr;
+ u8 port_num;
+ u8 ver_sub;
+ u8 ver_build;
+ u8 ver_min;
+ u8 ver_maj;
+ u8 pad; /* end spacing to ensure length is mult. of dword */
+ u16 pad2; /* end spacing to ensure length is mult. of dword2 */
+};
+
/* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc {
struct {
@@ -2286,7 +2354,7 @@ union ixgbe_atr_input {
* src_port - 2 bytes
* dst_port - 2 bytes
* flex_bytes - 2 bytes
- * rsvd0 - 2 bytes - space reserved must be 0.
+ * bkt_hash - 2 bytes
*/
struct {
u8 vm_pool;
@@ -2297,7 +2365,7 @@ union ixgbe_atr_input {
__be16 src_port;
__be16 dst_port;
__be16 flex_bytes;
- __be16 rsvd0;
+ __be16 bkt_hash;
} formatted;
__be32 dword_stream[11];
};
@@ -2318,16 +2386,6 @@ union ixgbe_atr_hash_dword {
__be32 dword;
};
-struct ixgbe_atr_input_masks {
- __be16 rsvd0;
- __be16 vlan_id_mask;
- __be32 dst_ip_mask[4];
- __be32 src_ip_mask[4];
- __be16 src_port_mask;
- __be16 dst_port_mask;
- __be16 flex_mask;
-};
-
enum ixgbe_eeprom_type {
ixgbe_eeprom_uninitialized = 0,
ixgbe_eeprom_spi,
@@ -2615,6 +2673,9 @@ struct ixgbe_mac_operations {
s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
bool *);
+ /* Packet Buffer Manipulation */
+ void (*set_rxpba)(struct ixgbe_hw *, int, u32, int);
+
/* LED */
s32 (*led_on)(struct ixgbe_hw *, u32);
s32 (*led_off)(struct ixgbe_hw *, u32);
@@ -2638,6 +2699,9 @@ struct ixgbe_mac_operations {
/* Flow Control */
s32 (*fc_enable)(struct ixgbe_hw *, s32);
+
+ /* Manageability interface */
+ s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
};
struct ixgbe_phy_operations {
@@ -2807,6 +2871,7 @@ struct ixgbe_info {
#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30
#define IXGBE_ERR_PBA_SECTION -31
#define IXGBE_ERR_INVALID_ARGUMENT -32
+#define IXGBE_ERR_HOST_INTERFACE_COMMAND -33
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c
index 4ed687be2fe3..bec30ed91adc 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ixgbe/ixgbe_x540.c
@@ -876,6 +876,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
.read_analog_reg8 = NULL,
.write_analog_reg8 = NULL,
.setup_link = &ixgbe_setup_mac_link_X540,
+ .set_rxpba = &ixgbe_set_rxpba_generic,
.check_link = &ixgbe_check_mac_link_generic,
.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic,
.led_on = &ixgbe_led_on_generic,
@@ -893,6 +894,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
.clear_vfta = &ixgbe_clear_vfta_generic,
.set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic,
+ .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = NULL,
.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing,
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h
index b703f60be3b7..8857df4dd3b9 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ixgbevf/ixgbevf.h
@@ -29,9 +29,11 @@
#define _IXGBEVF_H_
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
#include "vf.h"
@@ -185,9 +187,7 @@ struct ixgbevf_q_vector {
/* board specific private data structure */
struct ixgbevf_adapter {
struct timer_list watchdog_timer;
-#ifdef NETIF_F_HW_VLAN_TX
- struct vlan_group *vlgrp;
-#endif
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 bd_number;
struct work_struct reset_task;
struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
@@ -279,7 +279,7 @@ enum ixgbevf_boards {
extern struct ixgbevf_info ixgbevf_82599_vf_info;
extern struct ixgbevf_info ixgbevf_X540_vf_info;
-extern struct ixgbe_mac_operations ixgbevf_mbx_ops;
+extern struct ixgbe_mbx_operations ixgbevf_mbx_ops;
/* needed by ethtool.c */
extern char ixgbevf_driver_name[];
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 28d3cb21d376..3b880a27f8d1 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -30,6 +30,7 @@
Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code
******************************************************************************/
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -52,7 +53,7 @@ char ixgbevf_driver_name[] = "ixgbevf";
static const char ixgbevf_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
-#define DRV_VERSION "2.0.0-k2"
+#define DRV_VERSION "2.1.0-k"
const char ixgbevf_driver_version[] = DRV_VERSION;
static char ixgbevf_copyright[] =
"Copyright (c) 2009 - 2010 Intel Corporation.";
@@ -288,21 +289,17 @@ 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 (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
- if (adapter->vlgrp && is_vlan)
- vlan_gro_receive(&q_vector->napi,
- adapter->vlgrp,
- tag, skb);
- else
+ if (is_vlan) {
+ u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
+
+ __vlan_hwaccel_put_tag(skb, tag);
+ }
+
+ if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
napi_gro_receive(&q_vector->napi, skb);
- } else {
- if (adapter->vlgrp && is_vlan)
- vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
- else
+ else
netif_rx(skb);
- }
}
/**
@@ -1401,24 +1398,6 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter)
}
}
-static void ixgbevf_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
-{
- struct ixgbevf_adapter *adapter = netdev_priv(netdev);
- struct ixgbe_hw *hw = &adapter->hw;
- int i, j;
- u32 ctrl;
-
- adapter->vlgrp = grp;
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- j = adapter->rx_ring[i].reg_idx;
- ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
- ctrl |= IXGBE_RXDCTL_VME;
- IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), ctrl);
- }
-}
-
static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -1427,6 +1406,7 @@ static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
/* add VID to filter table */
if (hw->mac.ops.set_vfta)
hw->mac.ops.set_vfta(hw, vid, 0, true);
+ set_bit(vid, adapter->active_vlans);
}
static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -1434,31 +1414,18 @@ static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
- if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
- ixgbevf_irq_disable(adapter);
-
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
- if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
- ixgbevf_irq_enable(adapter, true, true);
-
/* remove VID from filter table */
if (hw->mac.ops.set_vfta)
hw->mac.ops.set_vfta(hw, vid, 0, false);
+ clear_bit(vid, adapter->active_vlans);
}
static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter)
{
- ixgbevf_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ u16 vid;
- if (adapter->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
- ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
- }
- }
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
}
static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
@@ -1648,7 +1615,7 @@ static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
for (i = 0; i < num_rx_rings; i++) {
j = adapter->rx_ring[i].reg_idx;
rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
- rxdctl |= IXGBE_RXDCTL_ENABLE;
+ rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME;
if (hw->mac.type == ixgbe_mac_X540_vf) {
rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
rxdctl |= ((netdev->mtu + ETH_HLEN + ETH_FCS_LEN) |
@@ -3249,18 +3216,17 @@ static void ixgbevf_shutdown(struct pci_dev *pdev)
}
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_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_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_register = &ixgbevf_vlan_rx_register,
- .ndo_vlan_rx_add_vid = &ixgbevf_vlan_rx_add_vid,
- .ndo_vlan_rx_kill_vid = &ixgbevf_vlan_rx_kill_vid,
+ .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,
};
static void ixgbevf_assign_netdev_ops(struct net_device *dev)
@@ -3364,7 +3330,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
hw->mac.type = ii->mac;
memcpy(&hw->mbx.ops, &ixgbevf_mbx_ops,
- sizeof(struct ixgbe_mac_operations));
+ sizeof(struct ixgbe_mbx_operations));
adapter->flags &= ~IXGBE_FLAG_RX_PS_CAPABLE;
adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 78ddd8b79e7e..e122493ab70e 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -14,6 +14,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/gfp.h>
#include <asm/hardware/uengine.h>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index b5b174a8c149..3ac262f55633 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -271,9 +271,7 @@ jme_reset_mac_processor(struct jme_adapter *jme)
static inline void
jme_clear_pm(struct jme_adapter *jme)
{
- jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
- pci_set_power_state(jme->pdev, PCI_D0);
- device_set_wakeup_enable(&jme->pdev->dev, false);
+ jwrite32(jme, JME_PMCS, PMCS_STMASK | jme->reg_pmcs);
}
static int
@@ -753,20 +751,28 @@ jme_make_new_rx_buf(struct jme_adapter *jme, int i)
struct jme_ring *rxring = &(jme->rxring[0]);
struct jme_buffer_info *rxbi = rxring->bufinf + i;
struct sk_buff *skb;
+ dma_addr_t mapping;
skb = netdev_alloc_skb(jme->dev,
jme->dev->mtu + RX_EXTRA_LEN);
if (unlikely(!skb))
return -ENOMEM;
+ mapping = pci_map_page(jme->pdev, virt_to_page(skb->data),
+ offset_in_page(skb->data), skb_tailroom(skb),
+ PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(jme->pdev, mapping))) {
+ dev_kfree_skb(skb);
+ return -ENOMEM;
+ }
+
+ if (likely(rxbi->mapping))
+ pci_unmap_page(jme->pdev, rxbi->mapping,
+ rxbi->len, PCI_DMA_FROMDEVICE);
+
rxbi->skb = skb;
rxbi->len = skb_tailroom(skb);
- rxbi->mapping = pci_map_page(jme->pdev,
- virt_to_page(skb->data),
- offset_in_page(skb->data),
- rxbi->len,
- PCI_DMA_FROMDEVICE);
-
+ rxbi->mapping = mapping;
return 0;
}
@@ -1050,16 +1056,12 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
skb_checksum_none_assert(skb);
if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) {
- if (jme->vlgrp) {
- jme->jme_vlan_rx(skb, jme->vlgrp,
- le16_to_cpu(rxdesc->descwb.vlan));
- NET_STAT(jme).rx_bytes += 4;
- } else {
- dev_kfree_skb(skb);
- }
- } else {
- jme->jme_rx(skb);
+ u16 vid = le16_to_cpu(rxdesc->descwb.vlan);
+
+ __vlan_hwaccel_put_tag(skb, vid);
+ NET_STAT(jme).rx_bytes += 4;
}
+ jme->jme_rx(skb);
if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) ==
cpu_to_le16(RXWBFLAG_DEST_MUL))
@@ -1817,11 +1819,9 @@ jme_powersave_phy(struct jme_adapter *jme)
{
if (jme->reg_pmcs) {
jme_set_100m_half(jme);
-
if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
jme_wait_link(jme);
-
- jwrite32(jme, JME_PMCS, jme->reg_pmcs);
+ jme_clear_pm(jme);
} else {
jme_phy_off(jme);
}
@@ -2286,16 +2286,6 @@ static inline void jme_resume_rx(struct jme_adapter *jme)
}
static void
-jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
- struct jme_adapter *jme = netdev_priv(netdev);
-
- jme_pause_rx(jme);
- jme->vlgrp = grp;
- jme_resume_rx(jme);
-}
-
-static void
jme_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
{
@@ -2405,7 +2395,6 @@ jme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
test_bit(JME_FLAG_POLL, &jme->flags)) {
clear_bit(JME_FLAG_POLL, &jme->flags);
jme->jme_rx = netif_rx;
- jme->jme_vlan_rx = vlan_hwaccel_rx;
dpi->cur = PCC_P1;
dpi->attempt = PCC_P1;
dpi->cnt = 0;
@@ -2415,7 +2404,6 @@ jme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
!(test_bit(JME_FLAG_POLL, &jme->flags))) {
set_bit(JME_FLAG_POLL, &jme->flags);
jme->jme_rx = netif_receive_skb;
- jme->jme_vlan_rx = vlan_hwaccel_receive_skb;
jme_interrupt_mode(jme);
}
@@ -2529,8 +2517,7 @@ jme_set_wol(struct net_device *netdev,
jme->reg_pmcs |= PMCS_MFEN;
jwrite32(jme, JME_PMCS, jme->reg_pmcs);
-
- device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs);
+ device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs));
return 0;
}
@@ -2855,7 +2842,6 @@ static const struct net_device_ops jme_netdev_ops = {
.ndo_set_multicast_list = jme_set_multi,
.ndo_change_mtu = jme_change_mtu,
.ndo_tx_timeout = jme_tx_timeout,
- .ndo_vlan_rx_register = jme_vlan_rx_register,
.ndo_fix_features = jme_fix_features,
.ndo_set_features = jme_set_features,
};
@@ -2938,7 +2924,6 @@ jme_init_one(struct pci_dev *pdev,
jme->pdev = pdev;
jme->dev = netdev;
jme->jme_rx = netif_rx;
- jme->jme_vlan_rx = vlan_hwaccel_rx;
jme->old_mtu = netdev->mtu = 1500;
jme->phylink = 0;
jme->tx_ring_size = 1 << 10;
@@ -3058,6 +3043,9 @@ jme_init_one(struct pci_dev *pdev,
jme->mii_if.mdio_write = jme_mdio_write;
jme_clear_pm(jme);
+ pci_set_power_state(jme->pdev, PCI_D0);
+ device_set_wakeup_enable(&pdev->dev, true);
+
jme_set_phyfifo_5level(jme);
jme->pcirev = pdev->revision;
if (!jme->fpgaver)
@@ -3135,8 +3123,9 @@ jme_shutdown(struct pci_dev *pdev)
pci_pme_active(pdev, true);
}
-#ifdef CONFIG_PM
-static int jme_suspend(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int
+jme_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3175,14 +3164,14 @@ static int jme_suspend(struct device *dev)
return 0;
}
-static int jme_resume(struct device *dev)
+static int
+jme_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
struct jme_adapter *jme = netdev_priv(netdev);
- jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
-
+ jme_clear_pm(jme);
jme_phy_on(jme);
if (test_bit(JME_FLAG_SSET, &jme->flags))
jme_set_settings(netdev, &jme->old_ecmd);
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index e9aaeca96abc..c1f8b893e2ea 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -24,6 +24,7 @@
#ifndef __JME_H_INCLUDED__
#define __JME_H_INCLUDED__
+#include <linux/interrupt.h>
#define DRV_NAME "jme"
#define DRV_VERSION "1.0.8"
@@ -450,7 +451,6 @@ struct jme_adapter {
u32 msg_enable;
struct ethtool_cmd old_ecmd;
unsigned int old_mtu;
- struct vlan_group *vlgrp;
struct dynpcc_info dpi;
atomic_t intr_sem;
atomic_t link_changing;
@@ -458,9 +458,6 @@ struct jme_adapter {
atomic_t rx_cleaning;
atomic_t rx_empty;
int (*jme_rx)(struct sk_buff *skb);
- int (*jme_vlan_rx)(struct sk_buff *skb,
- struct vlan_group *grp,
- unsigned short vlan_tag);
DECLARE_NAPI_STRUCT
DECLARE_NET_DEVICE_STATS
};
@@ -851,6 +848,7 @@ enum jme_ghc_txmac_clk {
* Power management control and status register
*/
enum jme_pmcs_bit_masks {
+ PMCS_STMASK = 0xFFFF0000,
PMCS_WF7DET = 0x80000000,
PMCS_WF6DET = 0x40000000,
PMCS_WF5DET = 0x20000000,
@@ -862,6 +860,7 @@ enum jme_pmcs_bit_masks {
PMCS_LFDET = 0x00040000,
PMCS_LRDET = 0x00020000,
PMCS_MFDET = 0x00010000,
+ PMCS_ENMASK = 0x0000FFFF,
PMCS_WF7EN = 0x00008000,
PMCS_WF6EN = 0x00004000,
PMCS_WF5EN = 0x00002000,
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index c7a9bef4dfb0..763844c587fd 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -504,12 +504,7 @@ static void korina_multicast_list(struct net_device *dev)
hash_table[i] = 0;
netdev_for_each_mc_addr(ha, dev) {
- char *addrs = ha->addr;
-
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
}
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index fc12ac0d9f2e..4a6ae057e3b1 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -23,6 +23,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index bcd9ba68c9f2..f56743a28fc0 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -13,6 +13,7 @@
#define DEBUG
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index 61631cace913..d19c849059d8 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -23,6 +23,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -34,6 +35,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <asm/io.h>
#define DRV_NAME "ks8851_mll"
@@ -1188,8 +1190,6 @@ static void ks_set_rx_mode(struct net_device *netdev)
int i = 0;
netdev_for_each_mc_addr(ha, netdev) {
- if (!(*ha->addr & 1))
- continue;
if (i >= MAX_MCAST_LST)
break;
memcpy(ks->mcast_lst[i++], ha->addr, ETH_ALEN);
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index 41ea5920c158..27418d31a09f 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -17,6 +17,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioport.h>
@@ -5784,8 +5785,6 @@ static void netdev_set_rx_mode(struct net_device *dev)
}
netdev_for_each_mc_addr(ha, dev) {
- if (!(*ha->addr & 1))
- continue;
if (i >= MAX_MULTICAST_LIST)
break;
memcpy(hw->multi_list[i++], ha->addr, MAC_ADDR_LEN);
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
index 17b75e5f1b0a..05ae21435bfd 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/lib8390.c
@@ -36,7 +36,7 @@
Paul Gortmaker : tweak ANK's above multicast changes a bit.
Paul Gortmaker : update packet statistics for v2.1.x
Alan Cox : support arbitrary stupid port mappings on the
- 68K Macintosh. Support >16bit I/O spaces
+ 68K Macintosh. Support >16bit I/O spaces
Paul Gortmaker : add kmod support for auto-loading of the 8390
module by all drivers that require it.
Alan Cox : Spinlocking work, added 'BUG_83C690'
@@ -58,8 +58,8 @@
#include <linux/string.h>
#include <linux/bitops.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -108,7 +108,6 @@ int ei_debug = 1;
/* Index to functions. */
static void ei_tx_intr(struct net_device *dev);
static void ei_tx_err(struct net_device *dev);
-void ei_tx_timeout(struct net_device *dev);
static void ei_receive(struct net_device *dev);
static void ei_rx_overrun(struct net_device *dev);
@@ -206,19 +205,19 @@ static int __ei_open(struct net_device *dev)
struct ei_device *ei_local = netdev_priv(dev);
if (dev->watchdog_timeo <= 0)
- dev->watchdog_timeo = TX_TIMEOUT;
+ dev->watchdog_timeo = TX_TIMEOUT;
/*
* Grab the page lock so we own the register set, then call
* the init function.
*/
- spin_lock_irqsave(&ei_local->page_lock, flags);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
__NS8390_init(dev, 1);
/* Set the flag before we drop the lock, That way the IRQ arrives
after its set and we get no silly warnings */
netif_start_queue(dev);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
ei_local->irqlock = 0;
return 0;
}
@@ -238,9 +237,9 @@ static int __ei_close(struct net_device *dev)
* Hold the page lock during close
*/
- spin_lock_irqsave(&ei_local->page_lock, flags);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
__NS8390_init(dev, 0);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
netif_stop_queue(dev);
return 0;
}
@@ -267,12 +266,12 @@ static void __ei_tx_timeout(struct net_device *dev)
isr = ei_inb(e8390_base+EN0_ISR);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
- printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
- dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
- (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+ netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d\n",
+ (txsr & ENTSR_ABT) ? "excess collisions." :
+ (isr) ? "lost interrupt?" : "cable problem?",
+ txsr, isr, tickssofar);
- if (!isr && !dev->stats.tx_packets)
- {
+ if (!isr && !dev->stats.tx_packets) {
/* The 8390 probably hasn't gotten on the cable yet. */
ei_local->interface_num ^= 1; /* Try a different xcvr. */
}
@@ -344,27 +343,22 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
* card, leaving a substantial gap between each transmitted packet.
*/
- if (ei_local->tx1 == 0)
- {
+ if (ei_local->tx1 == 0) {
output_page = ei_local->tx_start_page;
ei_local->tx1 = send_length;
if (ei_debug && ei_local->tx2 > 0)
- printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
- }
- else if (ei_local->tx2 == 0)
- {
+ netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+ ei_local->tx2, ei_local->lasttx, ei_local->txing);
+ } else if (ei_local->tx2 == 0) {
output_page = ei_local->tx_start_page + TX_PAGES/2;
ei_local->tx2 = send_length;
if (ei_debug && ei_local->tx1 > 0)
- printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
- }
- else
- { /* We should never get here. */
+ netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+ ei_local->tx1, ei_local->lasttx, ei_local->txing);
+ } else { /* We should never get here. */
if (ei_debug)
- printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
- dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+ netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+ ei_local->tx1, ei_local->tx2, ei_local->lasttx);
ei_local->irqlock = 0;
netif_stop_queue(dev);
ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -382,22 +376,18 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
ei_block_output(dev, send_length, data, output_page);
- if (! ei_local->txing)
- {
+ if (!ei_local->txing) {
ei_local->txing = 1;
NS8390_trigger_send(dev, send_length, output_page);
- if (output_page == ei_local->tx_start_page)
- {
+ if (output_page == ei_local->tx_start_page) {
ei_local->tx1 = -1;
ei_local->lasttx = -1;
- }
- else
- {
+ } else {
ei_local->tx2 = -1;
ei_local->lasttx = -2;
}
- }
- else ei_local->txqueue++;
+ } else
+ ei_local->txqueue++;
if (ei_local->tx1 && ei_local->tx2)
netif_stop_queue(dev);
@@ -410,8 +400,8 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
spin_unlock(&ei_local->page_lock);
enable_irq_lockdep_irqrestore(dev->irq, &flags);
-
- dev_kfree_skb (skb);
+ skb_tx_timestamp(skb);
+ dev_kfree_skb(skb);
dev->stats.tx_bytes += send_length;
return NETDEV_TX_OK;
@@ -442,15 +432,13 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
spin_lock(&ei_local->page_lock);
- if (ei_local->irqlock)
- {
+ if (ei_local->irqlock) {
/*
* This might just be an interrupt for a PCI device sharing
* this line
*/
- printk("%s: Interrupted while interrupts are masked!"
- " isr=%#2x imr=%#2x.\n",
- dev->name, ei_inb_p(e8390_base + EN0_ISR),
+ netdev_err(dev, "Interrupted while interrupts are masked! isr=%#2x imr=%#2x\n",
+ ei_inb_p(e8390_base + EN0_ISR),
ei_inb_p(e8390_base + EN0_IMR));
spin_unlock(&ei_local->page_lock);
return IRQ_NONE;
@@ -459,15 +447,14 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
/* Change to page 0 and read the intr status reg. */
ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
if (ei_debug > 3)
- printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
+ netdev_dbg(dev, "interrupt(isr=%#2.2x)\n",
ei_inb_p(e8390_base + EN0_ISR));
/* !!Assumption!! -- we stay in page 0. Don't break this. */
while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 &&
- ++nr_serviced < MAX_SERVICE)
- {
+ ++nr_serviced < MAX_SERVICE) {
if (!netif_running(dev)) {
- printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+ netdev_warn(dev, "interrupt from stopped card\n");
/* rmk - acknowledge the interrupts */
ei_outb_p(interrupts, e8390_base + EN0_ISR);
interrupts = 0;
@@ -475,8 +462,7 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
}
if (interrupts & ENISR_OVER)
ei_rx_overrun(dev);
- else if (interrupts & (ENISR_RX+ENISR_RX_ERR))
- {
+ else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
/* Got a good (?) packet. */
ei_receive(dev);
}
@@ -486,35 +472,30 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
else if (interrupts & ENISR_TX_ERR)
ei_tx_err(dev);
- if (interrupts & ENISR_COUNTERS)
- {
+ if (interrupts & ENISR_COUNTERS) {
dev->stats.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0);
dev->stats.rx_crc_errors += ei_inb_p(e8390_base + EN0_COUNTER1);
- dev->stats.rx_missed_errors+= ei_inb_p(e8390_base + EN0_COUNTER2);
+ dev->stats.rx_missed_errors += ei_inb_p(e8390_base + EN0_COUNTER2);
ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
}
/* Ignore any RDC interrupts that make it back to here. */
if (interrupts & ENISR_RDC)
- {
ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR);
- }
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
}
- if (interrupts && ei_debug)
- {
+ if (interrupts && ei_debug) {
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
- if (nr_serviced >= MAX_SERVICE)
- {
+ if (nr_serviced >= MAX_SERVICE) {
/* 0xFF is valid for a card removal */
- if(interrupts!=0xFF)
- printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
- dev->name, interrupts);
+ if (interrupts != 0xFF)
+ netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+ interrupts);
ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
} else {
- printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
+ netdev_warn(dev, "unknown interrupt %#2x\n", interrupts);
ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
}
}
@@ -554,30 +535,32 @@ static void ei_tx_err(struct net_device *dev)
unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
#ifdef VERBOSE_ERROR_DUMP
- printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+ netdev_dbg(dev, "transmitter error (%#2x):", txsr);
if (txsr & ENTSR_ABT)
- printk("excess-collisions ");
+ pr_cont(" excess-collisions ");
if (txsr & ENTSR_ND)
- printk("non-deferral ");
+ pr_cont(" non-deferral ");
if (txsr & ENTSR_CRS)
- printk("lost-carrier ");
+ pr_cont(" lost-carrier ");
if (txsr & ENTSR_FU)
- printk("FIFO-underrun ");
+ pr_cont(" FIFO-underrun ");
if (txsr & ENTSR_CDH)
- printk("lost-heartbeat ");
- printk("\n");
+ pr_cont(" lost-heartbeat ");
+ pr_cont("\n");
#endif
ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
if (tx_was_aborted)
ei_tx_intr(dev);
- else
- {
+ else {
dev->stats.tx_errors++;
- if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++;
- if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++;
- if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++;
+ if (txsr & ENTSR_CRS)
+ dev->stats.tx_carrier_errors++;
+ if (txsr & ENTSR_CDH)
+ dev->stats.tx_heartbeat_errors++;
+ if (txsr & ENTSR_OWC)
+ dev->stats.tx_window_errors++;
}
}
@@ -603,52 +586,45 @@ static void ei_tx_intr(struct net_device *dev)
*/
ei_local->txqueue--;
- if (ei_local->tx1 < 0)
- {
+ if (ei_local->tx1 < 0) {
if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
- printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx1);
+ pr_err("%s: bogus last_tx_buffer %d, tx1=%d\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx1);
ei_local->tx1 = 0;
- if (ei_local->tx2 > 0)
- {
+ if (ei_local->tx2 > 0) {
ei_local->txing = 1;
NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
dev->trans_start = jiffies;
ei_local->tx2 = -1,
ei_local->lasttx = 2;
- }
- else ei_local->lasttx = 20, ei_local->txing = 0;
- }
- else if (ei_local->tx2 < 0)
- {
+ } else
+ ei_local->lasttx = 20, ei_local->txing = 0;
+ } else if (ei_local->tx2 < 0) {
if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
- printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx2);
+ pr_err("%s: bogus last_tx_buffer %d, tx2=%d\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx2);
ei_local->tx2 = 0;
- if (ei_local->tx1 > 0)
- {
+ if (ei_local->tx1 > 0) {
ei_local->txing = 1;
NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
dev->trans_start = jiffies;
ei_local->tx1 = -1;
ei_local->lasttx = 1;
- }
- else
+ } else
ei_local->lasttx = 10, ei_local->txing = 0;
- }
-// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
-// dev->name, ei_local->lasttx);
+ } /* else
+ netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+ ei_local->lasttx);
+*/
/* Minimize Tx latency: update the statistics after we restart TXing. */
if (status & ENTSR_COL)
dev->stats.collisions++;
if (status & ENTSR_PTX)
dev->stats.tx_packets++;
- else
- {
+ else {
dev->stats.tx_errors++;
- if (status & ENTSR_ABT)
- {
+ if (status & ENTSR_ABT) {
dev->stats.tx_aborted_errors++;
dev->stats.collisions += 16;
}
@@ -682,8 +658,7 @@ static void ei_receive(struct net_device *dev)
struct e8390_pkt_hdr rx_frame;
int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
- while (++rx_pkt_count < 10)
- {
+ while (++rx_pkt_count < 10) {
int pkt_len, pkt_stat;
/* Get the rx page (incoming packet pointer). */
@@ -702,9 +677,11 @@ static void ei_receive(struct net_device *dev)
Keep quiet if it looks like a card removal. One problem here
is that some clones crash in roughly the same way.
*/
- if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
- printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
- dev->name, this_frame, ei_local->current_page);
+ if (ei_debug > 0 &&
+ this_frame != ei_local->current_page &&
+ (this_frame != 0x0 || rxing_page != 0xFF))
+ netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+ this_frame, ei_local->current_page);
if (this_frame == rxing_page) /* Read all the frames? */
break; /* Done for now */
@@ -730,46 +707,39 @@ static void ei_receive(struct net_device *dev)
continue;
}
- if (pkt_len < 60 || pkt_len > 1518)
- {
+ if (pkt_len < 60 || pkt_len > 1518) {
if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
- dev->name, rx_frame.count, rx_frame.status,
+ netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+ rx_frame.count, rx_frame.status,
rx_frame.next);
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
- }
- else if ((pkt_stat & 0x0F) == ENRSR_RXOK)
- {
+ } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
struct sk_buff *skb;
skb = dev_alloc_skb(pkt_len+2);
- if (skb == NULL)
- {
+ if (skb == NULL) {
if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
- dev->name, pkt_len);
+ netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
+ pkt_len);
dev->stats.rx_dropped++;
break;
- }
- else
- {
- skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
+ } else {
+ skb_reserve(skb, 2); /* IP headers on 16 byte boundaries */
skb_put(skb, pkt_len); /* Make room */
ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
+ skb->protocol = eth_type_trans(skb, dev);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
if (pkt_stat & ENRSR_PHY)
dev->stats.multicast++;
}
- }
- else
- {
+ } else {
if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
- dev->name, rx_frame.status, rx_frame.next,
+ netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+ rx_frame.status, rx_frame.next,
rx_frame.count);
dev->stats.rx_errors++;
/* NB: The NIC counts CRC, frame and missed errors. */
@@ -780,8 +750,8 @@ static void ei_receive(struct net_device *dev)
/* This _should_ never happen: it's here for avoiding bad clones. */
if (next_frame >= ei_local->stop_page) {
- printk("%s: next frame inconsistency, %#2x\n", dev->name,
- next_frame);
+ netdev_notice(dev, "next frame inconsistency, %#2x\n",
+ next_frame);
next_frame = ei_local->rx_start_page;
}
ei_local->current_page = next_frame;
@@ -821,7 +791,7 @@ static void ei_rx_overrun(struct net_device *dev)
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+ netdev_dbg(dev, "Receiver overrun\n");
dev->stats.rx_over_errors++;
/*
@@ -844,8 +814,7 @@ static void ei_rx_overrun(struct net_device *dev)
* step is vital, and skipping it will cause no end of havoc.
*/
- if (was_txing)
- {
+ if (was_txing) {
unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
if (!tx_completed)
must_resend = 1;
@@ -869,7 +838,7 @@ static void ei_rx_overrun(struct net_device *dev)
*/
ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
if (must_resend)
- ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+ ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
}
/*
@@ -886,11 +855,11 @@ static struct net_device_stats *__ei_get_stats(struct net_device *dev)
if (!netif_running(dev))
return &dev->stats;
- spin_lock_irqsave(&ei_local->page_lock,flags);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
/* Read the counter registers, assuming we are in page 0. */
- dev->stats.rx_frame_errors += ei_inb_p(ioaddr + EN0_COUNTER0);
- dev->stats.rx_crc_errors += ei_inb_p(ioaddr + EN0_COUNTER1);
- dev->stats.rx_missed_errors+= ei_inb_p(ioaddr + EN0_COUNTER2);
+ dev->stats.rx_frame_errors += ei_inb_p(ioaddr + EN0_COUNTER0);
+ dev->stats.rx_crc_errors += ei_inb_p(ioaddr + EN0_COUNTER1);
+ dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
return &dev->stats;
@@ -929,13 +898,11 @@ static void do_set_multicast_list(struct net_device *dev)
int i;
struct ei_device *ei_local = netdev_priv(dev);
- if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
- {
+ if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
memset(ei_local->mcfilter, 0, 8);
if (!netdev_mc_empty(dev))
make_mc_bits(ei_local->mcfilter, dev);
- }
- else
+ } else
memset(ei_local->mcfilter, 0xFF, 8); /* mcast set to accept-all */
/*
@@ -954,23 +921,23 @@ static void do_set_multicast_list(struct net_device *dev)
if (netif_running(dev))
ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
- for(i = 0; i < 8; i++)
- {
+ for (i = 0; i < 8; i++) {
ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
#ifndef BUG_83C690
- if(ei_inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
- printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
+ if (ei_inb_p(e8390_base + EN1_MULT_SHIFT(i)) != ei_local->mcfilter[i])
+ netdev_err(dev, "Multicast filter read/write mismap %d\n",
+ i);
#endif
}
ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
- if(dev->flags&IFF_PROMISC)
- ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+ if (dev->flags&IFF_PROMISC)
+ ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
- ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
- else
- ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
- }
+ ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+ else
+ ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+}
/*
* Called without lock held. This is invoked from user context and may
@@ -1042,8 +1009,8 @@ static void __NS8390_init(struct net_device *dev, int startp)
? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
: 0x48;
- if(sizeof(struct e8390_pkt_hdr)!=4)
- panic("8390.c: header struct mispacked\n");
+ if (sizeof(struct e8390_pkt_hdr) != 4)
+ panic("8390.c: header struct mispacked\n");
/* Follow National Semi's recommendations for initing the DP83902. */
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
ei_outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */
@@ -1067,11 +1034,11 @@ static void __NS8390_init(struct net_device *dev, int startp)
/* Copy the station address into the DS8390 registers. */
ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
- for(i = 0; i < 6; i++)
- {
+ for (i = 0; i < 6; i++) {
ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
- if (ei_debug > 1 && ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
- printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+ if (ei_debug > 1 &&
+ ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i])
+ netdev_err(dev, "Hw. address read/write mismap %d\n", i);
}
ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
@@ -1080,8 +1047,7 @@ static void __NS8390_init(struct net_device *dev, int startp)
ei_local->tx1 = ei_local->tx2 = 0;
ei_local->txing = 0;
- if (startp)
- {
+ if (startp) {
ei_outb_p(0xff, e8390_base + EN0_ISR);
ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
@@ -1099,14 +1065,12 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
int start_page)
{
unsigned long e8390_base = dev->base_addr;
- struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
+ struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
- if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS)
- {
- printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
- dev->name);
+ if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS) {
+ netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
return;
}
ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index b7948ccfcf7d..728fe414147a 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -48,6 +48,8 @@
#include <linux/io.h>
#include <linux/ip.h>
#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
#include "ll_temac.h"
@@ -727,6 +729,8 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
if (lp->tx_bd_tail >= TX_BD_NUM)
lp->tx_bd_tail = 0;
+ skb_tx_timestamp(skb);
+
/* Kick off the transfer */
lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
@@ -772,7 +776,8 @@ static void ll_temac_recv(struct net_device *ndev)
skb->ip_summed = CHECKSUM_COMPLETE;
}
- netif_rx(skb);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb);
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += length;
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 8a1097cf8a83..f9888d20177b 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -41,6 +41,7 @@ static const char *version =
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 6c6a02869dfc..0fcdc25699d8 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/dma-mapping.h>
@@ -669,6 +670,8 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
entry = NEXT_TX(entry);
bp->tx_head = entry;
+ skb_tx_timestamp(skb);
+
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
if (TX_BUFFS_AVAIL(bp) < 1)
@@ -1169,7 +1172,7 @@ static int __init macb_probe(struct platform_device *pdev)
clk_enable(bp->hclk);
#endif
- bp->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ bp->regs = ioremap(regs->start, resource_size(regs));
if (!bp->regs) {
dev_err(&pdev->dev, "failed to map registers, aborting.\n");
err = -ENOMEM;
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 1c5221f79d6f..2074e9724ba3 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -13,6 +13,7 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/crc32.h>
#include <linux/spinlock.h>
#include <linux/bitrev.h>
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index c685a4656878..4286e67f9634 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -221,7 +221,7 @@ static int __devinit mace_probe(struct platform_device *pdev)
SET_NETDEV_DEV(dev, &pdev->dev);
dev->base_addr = (u32)MACE_BASE;
- mp->mace = (volatile struct mace *) MACE_BASE;
+ mp->mace = MACE_BASE;
dev->irq = IRQ_MAC_MACE;
mp->dma_intr = IRQ_MAC_MACE_DMA;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index d6aeaa5f25ea..ba631fcece34 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -414,7 +414,8 @@ static struct lock_class_key macvlan_netdev_addr_lock_key;
#define MACVLAN_FEATURES \
(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
- NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM)
+ NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
+ NETIF_F_HW_VLAN_FILTER)
#define MACVLAN_STATE_MASK \
((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
@@ -509,6 +510,28 @@ static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
return stats;
}
+static void macvlan_vlan_rx_add_vid(struct net_device *dev,
+ unsigned short vid)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+ const struct net_device_ops *ops = lowerdev->netdev_ops;
+
+ if (ops->ndo_vlan_rx_add_vid)
+ ops->ndo_vlan_rx_add_vid(lowerdev, vid);
+}
+
+static void macvlan_vlan_rx_kill_vid(struct net_device *dev,
+ unsigned short vid)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+ const struct net_device_ops *ops = lowerdev->netdev_ops;
+
+ if (ops->ndo_vlan_rx_kill_vid)
+ ops->ndo_vlan_rx_kill_vid(lowerdev, vid);
+}
+
static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *drvinfo)
{
@@ -541,6 +564,8 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_set_multicast_list = 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,
+ .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid,
};
void macvlan_common_setup(struct net_device *dev)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 6696e56e6320..ab96c319a240 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -60,6 +60,7 @@ static struct proto macvtap_proto = {
*/
static dev_t macvtap_major;
#define MACVTAP_NUM_DEVS 65536
+#define GOODCOPY_LEN 128
static struct class *macvtap_class;
static struct cdev macvtap_cdev;
@@ -340,6 +341,7 @@ 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 macvtap_queue *q;
int err;
@@ -369,6 +371,16 @@ static int macvtap_open(struct inode *inode, struct file *file)
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
+ */
+ if (vlan) {
+ if ((vlan->lowerdev->features & NETIF_F_HIGHDMA) &&
+ (vlan->lowerdev->features & NETIF_F_SG))
+ sock_set_flag(&q->sk, SOCK_ZEROCOPY);
+ }
+
err = macvtap_set_queue(dev, file, q);
if (err)
sock_put(&q->sk);
@@ -433,6 +445,80 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
return skb;
}
+/* set skb frags from iovec, this can move to core network code for reuse */
+static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
+ int offset, size_t count)
+{
+ int len = iov_length(from, count) - offset;
+ 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)) {
+ offset -= from->iov_len;
+ ++from;
+ --count;
+ }
+
+ /* copy up to skb headlen */
+ while (count && (copy > 0)) {
+ size = min_t(unsigned int, copy, from->iov_len - offset);
+ if (copy_from_user(skb->data + offset1, from->iov_base + offset,
+ size))
+ return -EFAULT;
+ if (copy > size) {
+ ++from;
+ --count;
+ }
+ copy -= size;
+ offset1 += size;
+ offset = 0;
+ }
+
+ if (len == offset1)
+ return 0;
+
+ while (count--) {
+ struct page *page[MAX_SKB_FRAGS];
+ int num_pages;
+ unsigned long base;
+
+ len = from->iov_len - offset1;
+ if (!len) {
+ offset1 = 0;
+ ++from;
+ continue;
+ }
+ base = (unsigned long)from->iov_base + offset1;
+ size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+ num_pages = get_user_pages_fast(base, size, 0, &page[i]);
+ if ((num_pages != size) ||
+ (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
+ /* put_page is in skb free */
+ return -EFAULT;
+ skb->data_len += len;
+ skb->len += len;
+ 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);
+ skb_shinfo(skb)->nr_frags++;
+ /* increase sk_wmem_alloc */
+ base += f->size;
+ len -= f->size;
+ i++;
+ }
+ offset1 = 0;
+ ++from;
+ }
+ return 0;
+}
+
/*
* macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should
* be shared with the tun/tap driver.
@@ -508,6 +594,8 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
vnet_hdr->csum_start = skb_checksum_start_offset(skb);
vnet_hdr->csum_offset = skb->csum_offset;
+ } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+ vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */
return 0;
@@ -515,16 +603,18 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
/* Get packet from user space buffer */
-static ssize_t macvtap_get_user(struct macvtap_queue *q,
- const struct iovec *iv, size_t count,
- int noblock)
+static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
+ const struct iovec *iv, unsigned long total_len,
+ size_t count, int noblock)
{
struct sk_buff *skb;
struct macvlan_dev *vlan;
- size_t len = count;
+ unsigned long len = total_len;
int err;
struct virtio_net_hdr vnet_hdr = { 0 };
int vnet_hdr_len = 0;
+ int copylen;
+ bool zerocopy = false;
if (q->flags & IFF_VNET_HDR) {
vnet_hdr_len = q->vnet_hdr_sz;
@@ -552,12 +642,31 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
if (unlikely(len < ETH_HLEN))
goto err;
- skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, len, vnet_hdr.hdr_len,
- noblock, &err);
+ if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY))
+ zerocopy = true;
+
+ if (zerocopy) {
+ /* There are 256 bytes to be copied in skb, so there is enough
+ * room for skb expand head in case it is used.
+ * The rest buffer is mapped from userspace.
+ */
+ copylen = vnet_hdr.hdr_len;
+ if (!copylen)
+ copylen = GOODCOPY_LEN;
+ } else
+ copylen = len;
+
+ skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
+ vnet_hdr.hdr_len, noblock, &err);
if (!skb)
goto err;
- err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len);
+ if (zerocopy) {
+ err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
+ skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ } else
+ err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
+ len);
if (err)
goto err_kfree;
@@ -573,13 +682,16 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
rcu_read_lock_bh();
vlan = rcu_dereference_bh(q->vlan);
+ /* copy skb_ubuf_info for callback when skb has no error */
+ if (zerocopy)
+ skb_shinfo(skb)->destructor_arg = m->msg_control;
if (vlan)
macvlan_start_xmit(skb, vlan->dev);
else
kfree_skb(skb);
rcu_read_unlock_bh();
- return count;
+ return total_len;
err_kfree:
kfree_skb(skb);
@@ -601,8 +713,8 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
ssize_t result = -ENOLINK;
struct macvtap_queue *q = file->private_data;
- result = macvtap_get_user(q, iv, iov_length(iv, count),
- file->f_flags & O_NONBLOCK);
+ result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count,
+ file->f_flags & O_NONBLOCK);
return result;
}
@@ -815,7 +927,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len)
{
struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
- return macvtap_get_user(q, m->msg_iov, total_len,
+ return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen,
m->msg_flags & MSG_DONTWAIT);
}
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 869f0ea43a5b..004e64ab1f95 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -5,6 +5,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 2e858e4dcf4d..eb096253d781 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -104,7 +104,7 @@ static void mlx4_en_get_wol(struct net_device *netdev,
int err = 0;
u64 config = 0;
- if (!priv->mdev->dev->caps.wol) {
+ if (!(priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_WOL)) {
wol->supported = 0;
wol->wolopts = 0;
return;
@@ -134,7 +134,7 @@ static int mlx4_en_set_wol(struct net_device *netdev,
u64 config = 0;
int err = 0;
- if (!priv->mdev->dev->caps.wol)
+ if (!(priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_WOL))
return -EOPNOTSUPP;
if (wol->supported & ~WAKE_MAGIC)
@@ -170,7 +170,8 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
return NUM_ALL_STATS +
(priv->tx_ring_num + priv->rx_ring_num) * 2;
case ETH_SS_TEST:
- return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2;
+ return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
+ & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
default:
return -EOPNOTSUPP;
}
@@ -220,7 +221,7 @@ static void mlx4_en_get_strings(struct net_device *dev,
case ETH_SS_TEST:
for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
- if (priv->mdev->dev->caps.loopback_support)
+ if (priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UC_LOOPBACK)
for (; i < MLX4_EN_NUM_SELF_TEST; i++)
strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
break;
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 9276b1b25586..6bfea233a9f2 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -106,7 +106,8 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->tcp_rss = tcp_rss;
params->udp_rss = udp_rss;
- if (params->udp_rss && !mdev->dev->caps.udp_rss) {
+ if (params->udp_rss && !(mdev->dev->caps.flags
+ & MLX4_DEV_CAP_FLAG_UDP_RSS)) {
mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
params->udp_rss = 0;
}
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 61850adae6f7..4b0f32e568f8 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -45,25 +45,6 @@
#include "mlx4_en.h"
#include "en_port.h"
-
-static void mlx4_en_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int err;
-
- en_dbg(HW, priv, "Registering VLAN group:%p\n", grp);
- priv->vlgrp = grp;
-
- mutex_lock(&mdev->state_lock);
- if (mdev->device_up && priv->port_up) {
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, grp);
- if (err)
- en_err(priv, "Failed configuring VLAN filter\n");
- }
- mutex_unlock(&mdev->state_lock);
-}
-
static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -71,16 +52,14 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
int err;
int idx;
- if (!priv->vlgrp)
- return;
+ en_dbg(HW, priv, "adding VLAN:%d\n", vid);
- en_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n",
- vid, vlan_group_get_device(priv->vlgrp, vid));
+ set_bit(vid, priv->active_vlans);
/* Add VID to port VLAN filter */
mutex_lock(&mdev->state_lock);
if (mdev->device_up && priv->port_up) {
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
if (err)
en_err(priv, "Failed configuring VLAN filter\n");
}
@@ -97,12 +76,9 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
int err;
int idx;
- if (!priv->vlgrp)
- return;
+ en_dbg(HW, priv, "Killing VID:%d\n", vid);
- en_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp entry:%p)\n",
- vid, priv->vlgrp, vlan_group_get_device(priv->vlgrp, vid));
- vlan_group_set_device(priv->vlgrp, vid, NULL);
+ clear_bit(vid, priv->active_vlans);
/* Remove VID from port VLAN filter */
mutex_lock(&mdev->state_lock);
@@ -112,7 +88,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
en_err(priv, "could not find vid %d in cache\n", vid);
if (mdev->device_up && priv->port_up) {
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
if (err)
en_err(priv, "Failed configuring VLAN filter\n");
}
@@ -239,7 +215,8 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
priv->flags |= MLX4_EN_FLAG_PROMISC;
/* Enable promiscouos mode */
- if (!mdev->dev->caps.vep_uc_steering)
+ if (!(mdev->dev->caps.flags &
+ MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
priv->base_qpn, 1);
else
@@ -265,12 +242,10 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
}
- if (priv->vlgrp) {
- /* Disable port VLAN filter */
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
- if (err)
- en_err(priv, "Failed disabling VLAN filter\n");
- }
+ /* Disable port VLAN filter */
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
+ if (err)
+ en_err(priv, "Failed disabling VLAN filter\n");
}
goto out;
}
@@ -285,7 +260,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
priv->flags &= ~MLX4_EN_FLAG_PROMISC;
/* Disable promiscouos mode */
- if (!mdev->dev->caps.vep_uc_steering)
+ if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
priv->base_qpn, 0);
else
@@ -304,7 +279,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
}
/* Enable port VLAN filter */
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
if (err)
en_err(priv, "Failed enabling VLAN filter\n");
}
@@ -1046,7 +1021,6 @@ static const struct net_device_ops mlx4_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = mlx4_en_change_mtu,
.ndo_tx_timeout = mlx4_en_tx_timeout,
- .ndo_vlan_rx_register = mlx4_en_vlan_rx_register,
.ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index f2a4f5dd313d..5e7109178061 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -48,7 +48,7 @@ int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B);
}
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp)
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv)
{
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_set_vlan_fltr_mbox *filter;
@@ -63,20 +63,15 @@ int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp)
return PTR_ERR(mailbox);
filter = mailbox->buf;
- if (grp) {
- memset(filter, 0, sizeof *filter);
- for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
- entry = 0;
- for (j = 0; j < 32; j++)
- if (vlan_group_get_device(grp, index++))
- entry |= 1 << j;
- filter->entry[i] = cpu_to_be32(entry);
- }
- } else {
- /* When no vlans are configured we block all vlans */
- memset(filter, 0, sizeof(*filter));
+ memset(filter, 0, sizeof(*filter));
+ for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
+ entry = 0;
+ for (j = 0; j < 32; j++)
+ if (test_bit(index++, priv->active_vlans))
+ entry |= 1 << j;
+ filter->entry[i] = cpu_to_be32(entry);
}
- err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
+ err = mlx4_cmd(dev, mailbox->dma, priv->port, 0, MLX4_CMD_SET_VLAN_FLTR,
MLX4_CMD_TIME_CLASS_B);
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
@@ -119,9 +114,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
struct mlx4_set_port_rqp_calc_context *context;
int err;
u32 in_mod;
- u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;
+ u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ?
+ MCAST_DIRECT : MCAST_DEFAULT;
- if (dev->caps.vep_mc_steering && dev->caps.vep_uc_steering)
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER &&
+ dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)
return 0;
mailbox = mlx4_alloc_cmd_mailbox(dev);
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 277215fb9d72..37cc9e5c56be 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -611,11 +611,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
gro_skb->truesize += length;
gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
- if (priv->vlgrp && (cqe->vlan_my_qpn &
- cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)))
- vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid));
- else
- napi_gro_frags(&cq->napi);
+ if (cqe->vlan_my_qpn &
+ cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) {
+ u16 vid = be16_to_cpu(cqe->sl_vid);
+
+ __vlan_hwaccel_put_tag(gro_skb, vid);
+ }
+
+ napi_gro_frags(&cq->napi);
goto next;
}
@@ -647,13 +650,12 @@ 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 (be32_to_cpu(cqe->vlan_my_qpn) &
+ MLX4_CQE_VLAN_PRESENT_MASK)
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(cqe->sl_vid));
+
/* Push it up the stack */
- if (priv->vlgrp && (be32_to_cpu(cqe->vlan_my_qpn) &
- MLX4_CQE_VLAN_PRESENT_MASK)) {
- vlan_hwaccel_receive_skb(skb, priv->vlgrp,
- be16_to_cpu(cqe->sl_vid));
- } else
- netif_receive_skb(skb);
+ netif_receive_skb(skb);
next:
++cq->mcq.cons_index;
@@ -859,7 +861,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
priv->rx_ring[0].cqn, &context);
ptr = ((void *) &context) + 0x3c;
- rss_context = (struct mlx4_en_rss_context *) ptr;
+ rss_context = ptr;
rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/mlx4/en_selftest.c
index 191a8dcd8a93..9fdbcecd499d 100644
--- a/drivers/net/mlx4/en_selftest.c
+++ b/drivers/net/mlx4/en_selftest.c
@@ -159,7 +159,8 @@ retry_tx:
goto retry_tx;
}
- if (priv->mdev->dev->caps.loopback_support){
+ if (priv->mdev->dev->caps.flags &
+ MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
buf[3] = mlx4_en_test_registers(priv);
buf[4] = mlx4_en_test_loopback(priv);
}
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index b229acf1855f..6e03de034ac7 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -238,8 +238,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
} else {
if (!tx_info->inl) {
if ((void *) data >= end) {
- data = (struct mlx4_wqe_data_seg *)
- (ring->buf + ((void *) data - end));
+ data = ring->buf + ((void *)data - end);
}
if (tx_info->linear) {
@@ -253,7 +252,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
for (i = 0; i < frags; i++) {
/* Check for wraparound before unmapping */
if ((void *) data >= end)
- data = (struct mlx4_wqe_data_seg *) ring->buf;
+ data = ring->buf;
frag = &skb_shinfo(skb)->frags[i];
pci_unmap_page(mdev->pdev,
(dma_addr_t) be64_to_cpu(data->addr),
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 67a209ba939d..7eb8ba822e97 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -75,7 +75,7 @@ MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (defa
} \
} while (0)
-static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
+static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
{
static const char *fname[] = {
[ 0] = "RC transport",
@@ -99,13 +99,19 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
[21] = "UD multicast support",
[24] = "Demand paging support",
[25] = "Router support",
- [30] = "IBoE support"
+ [30] = "IBoE support",
+ [32] = "Unicast loopback support",
+ [38] = "Wake On LAN support",
+ [40] = "UDP RSS support",
+ [41] = "Unicast VEP steering support",
+ [42] = "Multicast VEP steering support",
+ [48] = "Counters support",
};
int i;
mlx4_dbg(dev, "DEV_CAP flags:\n");
for (i = 0; i < ARRAY_SIZE(fname); ++i)
- if (fname[i] && (flags & (1 << i)))
+ if (fname[i] && (flags & (1LL << i)))
mlx4_dbg(dev, " %s\n", fname[i]);
}
@@ -142,7 +148,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
struct mlx4_cmd_mailbox *mailbox;
u32 *outbox;
u8 field;
- u32 field32;
+ u32 field32, flags, ext_flags;
u16 size;
u16 stat_rate;
int err;
@@ -180,8 +186,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b
#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f
-#define QUERY_DEV_CAP_UDP_RSS_OFFSET 0x42
-#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43
+#define QUERY_DEV_CAP_EXT_FLAGS_OFFSET 0x40
#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44
#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48
#define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49
@@ -199,6 +204,7 @@ 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_MAX_COUNTERS_OFFSET 0x68
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84
@@ -272,14 +278,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_msg_sz = 1 << (field & 0x1f);
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
- dev_cap->udp_rss = field & 0x1;
- dev_cap->vep_uc_steering = field & 0x2;
- dev_cap->vep_mc_steering = field & 0x4;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
- dev_cap->loopback_support = field & 0x1;
- dev_cap->wol = field & 0x40;
- MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
+ MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
+ MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
+ dev_cap->flags = flags | (u64)ext_flags << 32;
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
dev_cap->reserved_uars = field >> 4;
MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET);
@@ -356,6 +357,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
QUERY_DEV_CAP_RSVD_LKEY_OFFSET);
MLX4_GET(dev_cap->max_icm_sz, outbox,
QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
+ if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
+ MLX4_GET(dev_cap->max_counters, outbox,
+ QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
for (i = 1; i <= dev_cap->num_ports; ++i) {
@@ -449,6 +453,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
+ mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters);
dump_dev_cap_flags(dev, dev_cap->flags);
@@ -781,6 +786,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
if (enable_qos)
*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
+ /* enable counters */
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS)
+ *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4);
+
/* QPC/EEC/CQC/EQC/RDMARC attributes */
MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
@@ -801,7 +810,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
- if (dev->caps.vep_mc_steering)
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET);
MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 88003ebc6185..1e8ecc3708e2 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -78,12 +78,7 @@ struct mlx4_dev_cap {
u16 wavelength[MLX4_MAX_PORTS + 1];
u64 trans_code[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
- int udp_rss;
- int loopback_support;
- int vep_uc_steering;
- int vep_mc_steering;
- int wol;
- u32 flags;
+ u64 flags;
int reserved_uars;
int uar_size;
int min_page_sz;
@@ -116,6 +111,7 @@ struct mlx4_dev_cap {
u8 supported_port_types[MLX4_MAX_PORTS + 1];
u8 log_max_macs[MLX4_MAX_PORTS + 1];
u8 log_max_vlans[MLX4_MAX_PORTS + 1];
+ u32 max_counters;
};
struct mlx4_adapter {
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 3814fc9b1145..c94b3426d355 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -143,6 +143,7 @@ static void mlx4_set_port_mask(struct mlx4_dev *dev)
if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB)
dev->caps.port_mask |= 1 << (i - 1);
}
+
static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
int err;
@@ -226,11 +227,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.bmme_flags = dev_cap->bmme_flags;
dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
- dev->caps.udp_rss = dev_cap->udp_rss;
- dev->caps.loopback_support = dev_cap->loopback_support;
- dev->caps.vep_uc_steering = dev_cap->vep_uc_steering;
- dev->caps.vep_mc_steering = dev_cap->vep_mc_steering;
- dev->caps.wol = dev_cap->wol;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
dev->caps.log_num_macs = log_num_mac;
@@ -262,6 +258,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
mlx4_set_port_mask(dev);
+ dev->caps.max_counters = 1 << ilog2(dev_cap->max_counters);
+
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] =
@@ -839,6 +837,45 @@ err_stop_fw:
return err;
}
+static int mlx4_init_counters_table(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int nent;
+
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
+ return -ENOENT;
+
+ nent = dev->caps.max_counters;
+ return mlx4_bitmap_init(&priv->counters_bitmap, nent, nent - 1, 0, 0);
+}
+
+static void mlx4_cleanup_counters_table(struct mlx4_dev *dev)
+{
+ mlx4_bitmap_cleanup(&mlx4_priv(dev)->counters_bitmap);
+}
+
+int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
+ return -ENOENT;
+
+ *idx = mlx4_bitmap_alloc(&priv->counters_bitmap);
+ if (*idx == -1)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
+
+void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
+{
+ mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx);
+ return;
+}
+EXPORT_SYMBOL_GPL(mlx4_counter_free);
+
static int mlx4_setup_hca(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -943,6 +980,12 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
goto err_qp_table_free;
}
+ err = mlx4_init_counters_table(dev);
+ if (err && err != -ENOENT) {
+ mlx4_err(dev, "Failed to initialize counters table, aborting.\n");
+ goto err_counters_table_free;
+ }
+
for (port = 1; port <= dev->caps.num_ports; port++) {
enum mlx4_port_type port_type = 0;
mlx4_SENSE_PORT(dev, port, &port_type);
@@ -969,6 +1012,9 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
err_mcg_table_free:
mlx4_cleanup_mcg_table(dev);
+err_counters_table_free:
+ mlx4_cleanup_counters_table(dev);
+
err_qp_table_free:
mlx4_cleanup_qp_table(dev);
@@ -1230,11 +1276,11 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&priv->pgdir_list);
mutex_init(&priv->pgdir_mutex);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &dev->rev_id);
-
INIT_LIST_HEAD(&priv->bf_list);
mutex_init(&priv->bf_mutex);
+ dev->rev_id = pdev->revision;
+
/*
* Now reset the HCA before we touch the PCI capabilities or
* attempt a firmware command, since a boot ROM may have left
@@ -1299,6 +1345,7 @@ err_port:
for (--port; port >= 1; --port)
mlx4_cleanup_port_info(&priv->port[port]);
+ mlx4_cleanup_counters_table(dev);
mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
mlx4_cleanup_srq_table(dev);
@@ -1359,6 +1406,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
mlx4_CLOSE_PORT(dev, p);
}
+ mlx4_cleanup_counters_table(dev);
mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
mlx4_cleanup_srq_table(dev);
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index e63c37d6a115..cd1784593a3c 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -559,7 +559,8 @@ static int find_entry(struct mlx4_dev *dev, u8 port,
struct mlx4_mgm *mgm = mgm_mailbox->buf;
u8 *mgid;
int err;
- u8 op_mod = (prot == MLX4_PROT_ETH) ? !!(dev->caps.vep_mc_steering) : 0;
+ u8 op_mod = (prot == MLX4_PROT_ETH) ?
+ !!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
@@ -834,7 +835,8 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
- if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
+ if (prot == MLX4_PROT_ETH &&
+ !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
if (prot == MLX4_PROT_ETH)
@@ -853,7 +855,8 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
- if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
+ if (prot == MLX4_PROT_ETH &&
+ !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
if (prot == MLX4_PROT_ETH) {
@@ -867,7 +870,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
{
- if (!dev->caps.vep_mc_steering)
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
@@ -877,7 +880,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
{
- if (!dev->caps.vep_mc_steering)
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
@@ -887,7 +890,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
{
- if (!dev->caps.vep_mc_steering)
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
@@ -897,7 +900,7 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
{
- if (!dev->caps.vep_mc_steering)
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index dd7d745fbab4..a2fcd8402d37 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -48,8 +48,8 @@
#include <linux/mlx4/doorbell.h>
#define DRV_NAME "mlx4_core"
-#define DRV_VERSION "0.01"
-#define DRV_RELDATE "May 1, 2007"
+#define DRV_VERSION "1.0"
+#define DRV_RELDATE "July 14, 2011"
enum {
MLX4_HCR_BASE = 0x80680,
@@ -342,6 +342,7 @@ struct mlx4_priv {
struct mlx4_srq_table srq_table;
struct mlx4_qp_table qp_table;
struct mlx4_mcg_table mcg_table;
+ struct mlx4_bitmap counters_bitmap;
struct mlx4_catas_err catas_err;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 0b5150df0585..ed84811766e6 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -34,10 +34,12 @@
#ifndef _MLX4_EN_H_
#define _MLX4_EN_H_
+#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
#include <linux/mlx4/device.h>
#include <linux/mlx4/qp.h>
@@ -418,7 +420,7 @@ struct mlx4_en_priv {
struct mlx4_en_dev *mdev;
struct mlx4_en_port_profile *prof;
struct net_device *dev;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct net_device_stats stats;
struct net_device_stats ret_stats;
struct mlx4_en_port_state port_state;
@@ -553,7 +555,7 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
void mlx4_en_rx_irq(struct mlx4_cq *mcq);
int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp);
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv);
int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 8856659fb43c..1f95afda6841 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -146,7 +146,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
int i, err = 0;
int free = -1;
- if (dev->caps.vep_uc_steering) {
+ 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);
@@ -203,7 +203,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
goto out;
}
- if (!dev->caps.vep_uc_steering)
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
*qpn = info->base_qpn + free;
++table->total;
out:
@@ -243,7 +243,7 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn)
int index = qpn - info->base_qpn;
struct mlx4_mac_entry *entry;
- if (dev->caps.vep_uc_steering) {
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
entry = radix_tree_lookup(&info->mac_tree, qpn);
if (entry) {
mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1);
@@ -274,7 +274,7 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wra
struct mlx4_mac_entry *entry;
int err;
- if (dev->caps.vep_uc_steering) {
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
entry = radix_tree_lookup(&info->mac_tree, qpn);
if (!entry)
return -EINVAL;
diff --git a/drivers/net/mlx4/reset.c b/drivers/net/mlx4/reset.c
index e5741dab3825..11e7c1cb99bf 100644
--- a/drivers/net/mlx4/reset.c
+++ b/drivers/net/mlx4/reset.c
@@ -77,7 +77,7 @@ int mlx4_reset(struct mlx4_dev *dev)
goto out;
}
- pcie_cap = pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
+ pcie_cap = pci_pcie_cap(dev->pdev);
for (i = 0; i < 64; ++i) {
if (i == 22 || i == 23)
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index a5d9b1c310b3..259699983ca5 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -840,6 +840,8 @@ no_csum:
__skb_queue_tail(&txq->tx_skb, skb);
+ skb_tx_timestamp(skb);
+
/* ensure all other descriptors are written before first cmd_sts */
wmb();
desc->cmd_sts = cmd_sts;
@@ -859,7 +861,7 @@ no_csum:
static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- int queue;
+ int length, queue;
struct tx_queue *txq;
struct netdev_queue *nq;
@@ -881,10 +883,12 @@ static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
+ length = skb->len;
+
if (!txq_submit_skb(txq, skb)) {
int entries_left;
- txq->tx_bytes += skb->len;
+ txq->tx_bytes += length;
txq->tx_packets++;
entries_left = txq->tx_ring_size - txq->tx_desc_count;
@@ -2593,7 +2597,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
if (msp == NULL)
goto out;
- msp->base = ioremap(res->start, res->end - res->start + 1);
+ msp->base = ioremap(res->start, resource_size(res));
if (msp->base == NULL)
goto out_free;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index bf84849600ce..1d2247554a35 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1,7 +1,7 @@
/*************************************************************************
* myri10ge.c: Myricom Myri-10G Ethernet driver.
*
- * Copyright (C) 2005 - 2009 Myricom, Inc.
+ * Copyright (C) 2005 - 2011 Myricom, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -79,7 +79,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.5.2-1.459"
+#define MYRI10GE_VERSION_STR "1.5.3-1.534"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -193,6 +193,7 @@ struct myri10ge_slice_state {
int watchdog_tx_done;
int watchdog_tx_req;
int watchdog_rx_done;
+ int stuck;
#ifdef CONFIG_MYRI10GE_DCA
int cached_dca_tag;
int cpu;
@@ -210,7 +211,6 @@ struct myri10ge_priv {
int big_bytes;
int max_intr_slots;
struct net_device *dev;
- spinlock_t stats_lock;
u8 __iomem *sram;
int sram_size;
unsigned long board_span;
@@ -377,7 +377,8 @@ static inline void put_be32(__be32 val, __be32 __iomem * p)
__raw_writel((__force __u32) val, (__force void __iomem *)p);
}
-static struct net_device_stats *myri10ge_get_stats(struct net_device *dev);
+static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats);
static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated)
{
@@ -1013,7 +1014,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
cmd.data2 = i;
status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA,
&cmd, 0);
- };
+ }
status |=
myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
@@ -1080,11 +1081,14 @@ static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on)
int ret, cap, err;
u16 ctl;
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(pdev);
if (!cap)
return 0;
err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+ if (err)
+ return 0;
+
ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4;
if (ret != on) {
ctl &= ~PCI_EXP_DEVCTL_RELAX_EN;
@@ -1139,20 +1143,19 @@ static void myri10ge_setup_dca(struct myri10ge_priv *mgp)
mgp->ss[i].cpu = -1;
mgp->ss[i].cached_dca_tag = -1;
myri10ge_update_dca(&mgp->ss[i]);
- }
+ }
}
static void myri10ge_teardown_dca(struct myri10ge_priv *mgp)
{
struct pci_dev *pdev = mgp->pdev;
- int err;
if (!mgp->dca_enabled)
return;
mgp->dca_enabled = 0;
if (mgp->relaxed_order)
myri10ge_toggle_relaxed(pdev, 1);
- err = dca_remove_requester(&pdev->dev);
+ dca_remove_requester(&pdev->dev);
}
static int myri10ge_notify_dca_device(struct device *dev, void *data)
@@ -1313,7 +1316,7 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
static inline int
myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
- int lro_enabled)
+ bool lro_enabled)
{
struct myri10ge_priv *mgp = ss->mgp;
struct sk_buff *skb;
@@ -1461,7 +1464,8 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
/* start the queue if we've stopped it */
if (netif_tx_queue_stopped(dev_queue) &&
- tx->req - tx->done < (tx->mask >> 1)) {
+ tx->req - tx->done < (tx->mask >> 1) &&
+ ss->mgp->running == MYRI10GE_ETH_RUNNING) {
tx->wake_queue++;
netif_tx_wake_queue(dev_queue);
}
@@ -1472,11 +1476,9 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
{
struct myri10ge_rx_done *rx_done = &ss->rx_done;
struct myri10ge_priv *mgp = ss->mgp;
-
unsigned long rx_bytes = 0;
unsigned long rx_packets = 0;
unsigned long rx_ok;
-
int idx = rx_done->idx;
int cnt = rx_done->cnt;
int work_done = 0;
@@ -1529,16 +1531,14 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
mgp->link_state = link_up;
if (mgp->link_state == MXGEFW_LINK_UP) {
- if (netif_msg_link(mgp))
- netdev_info(mgp->dev, "link up\n");
+ netif_info(mgp, link, mgp->dev, "link up\n");
netif_carrier_on(mgp->dev);
mgp->link_changes++;
} else {
- if (netif_msg_link(mgp))
- netdev_info(mgp->dev, "link %s\n",
- link_up == MXGEFW_LINK_MYRINET ?
+ netif_info(mgp, link, mgp->dev, "link %s\n",
+ (link_up == MXGEFW_LINK_MYRINET ?
"mismatch (Myrinet detected)" :
- "down");
+ "down"));
netif_carrier_off(mgp->dev);
mgp->link_changes++;
}
@@ -1619,7 +1619,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
if (send_done_count != tx->pkt_done)
myri10ge_tx_done(ss, (int)send_done_count);
if (unlikely(i > myri10ge_max_irq_loops)) {
- netdev_err(mgp->dev, "irq stuck?\n");
+ netdev_warn(mgp->dev, "irq stuck?\n");
stats->valid = 0;
schedule_work(&mgp->watchdog_work);
}
@@ -1783,9 +1783,8 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = {
"----------- slice ---------",
"tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done",
"rx_small_cnt", "rx_big_cnt",
- "wake_queue", "stop_queue", "tx_linearized", "LRO aggregated",
- "LRO flushed",
- "LRO avg aggr", "LRO no_desc"
+ "wake_queue", "stop_queue", "tx_linearized",
+ "LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc",
};
#define MYRI10GE_NET_STATS_LEN 21
@@ -1831,13 +1830,15 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
{
struct myri10ge_priv *mgp = netdev_priv(netdev);
struct myri10ge_slice_state *ss;
+ struct rtnl_link_stats64 link_stats;
int slice;
int i;
/* force stats update */
- (void)myri10ge_get_stats(netdev);
+ memset(&link_stats, 0, sizeof(link_stats));
+ (void)myri10ge_get_stats(netdev, &link_stats);
for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
- data[i] = ((unsigned long *)&netdev->stats)[i];
+ data[i] = ((u64 *)&link_stats)[i];
data[i++] = (unsigned int)mgp->tx_boundary;
data[i++] = (unsigned int)mgp->wc_enabled;
@@ -1907,6 +1908,60 @@ static u32 myri10ge_get_msglevel(struct net_device *netdev)
return mgp->msg_enable;
}
+/*
+ * Use a low-level command to change the LED behavior. Rather than
+ * blinking (which is the normal case), when identify is used, the
+ * yellow LED turns solid.
+ */
+static int myri10ge_led(struct myri10ge_priv *mgp, int on)
+{
+ struct mcp_gen_header *hdr;
+ struct device *dev = &mgp->pdev->dev;
+ size_t hdr_off, pattern_off, hdr_len;
+ u32 pattern = 0xfffffffe;
+
+ /* find running firmware header */
+ hdr_off = swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+ if ((hdr_off & 3) || hdr_off + sizeof(*hdr) > mgp->sram_size) {
+ dev_err(dev, "Running firmware has bad header offset (%d)\n",
+ (int)hdr_off);
+ return -EIO;
+ }
+ hdr_len = swab32(readl(mgp->sram + hdr_off +
+ offsetof(struct mcp_gen_header, header_length)));
+ pattern_off = hdr_off + offsetof(struct mcp_gen_header, led_pattern);
+ if (pattern_off >= (hdr_len + hdr_off)) {
+ dev_info(dev, "Firmware does not support LED identification\n");
+ return -EINVAL;
+ }
+ if (!on)
+ pattern = swab32(readl(mgp->sram + pattern_off + 4));
+ writel(htonl(pattern), mgp->sram + pattern_off);
+ return 0;
+}
+
+static int
+myri10ge_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
+{
+ struct myri10ge_priv *mgp = netdev_priv(netdev);
+ int rc;
+
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ rc = myri10ge_led(mgp, 1);
+ break;
+
+ case ETHTOOL_ID_INACTIVE:
+ rc = myri10ge_led(mgp, 0);
+ break;
+
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
static const struct ethtool_ops myri10ge_ethtool_ops = {
.get_settings = myri10ge_get_settings,
.get_drvinfo = myri10ge_get_drvinfo,
@@ -1921,6 +1976,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = {
.get_ethtool_stats = myri10ge_get_ethtool_stats,
.set_msglevel = myri10ge_set_msglevel,
.get_msglevel = myri10ge_get_msglevel,
+ .set_phys_id = myri10ge_phys_id,
};
static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
@@ -2000,8 +2056,12 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
ss->rx_big.page_offset = MYRI10GE_ALLOC_SIZE;
ss->rx_small.watchdog_needed = 0;
ss->rx_big.watchdog_needed = 0;
- myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
- mgp->small_bytes + MXGEFW_PAD, 0);
+ if (mgp->small_bytes == 0) {
+ ss->rx_small.fill_cnt = ss->rx_small.mask + 1;
+ } else {
+ myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
+ mgp->small_bytes + MXGEFW_PAD, 0);
+ }
if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) {
netdev_err(dev, "slice-%d: alloced only %d small bufs\n",
@@ -2027,6 +2087,8 @@ abort_with_rx_big_ring:
}
abort_with_rx_small_ring:
+ if (mgp->small_bytes == 0)
+ ss->rx_small.fill_cnt = ss->rx_small.cnt;
for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) {
int idx = i & ss->rx_small.mask;
myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_small.info[idx],
@@ -2077,6 +2139,8 @@ static void myri10ge_free_rings(struct myri10ge_slice_state *ss)
put_page(ss->rx_big.info[idx].page);
}
+ if (mgp->small_bytes == 0)
+ ss->rx_small.fill_cnt = ss->rx_small.cnt;
for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) {
idx = i & ss->rx_small.mask;
if (i == ss->rx_small.fill_cnt - 1)
@@ -2255,7 +2319,7 @@ myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
*ip_hdr = iph;
if (iph->protocol != IPPROTO_TCP)
return -1;
- if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(iph))
return -1;
*hdr_flags |= LRO_TCP;
*tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
@@ -2414,7 +2478,7 @@ static int myri10ge_open(struct net_device *dev)
mgp->small_bytes = VLAN_ETH_FRAME_LEN;
/* Override the small buffer size? */
- if (myri10ge_small_bytes > 0)
+ if (myri10ge_small_bytes >= 0)
mgp->small_bytes = myri10ge_small_bytes;
/* Firmware needs the big buff size as a power of 2. Lie and
@@ -2976,15 +3040,13 @@ drop:
return NETDEV_TX_OK;
}
-static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
{
- struct myri10ge_priv *mgp = netdev_priv(dev);
- struct myri10ge_slice_netstats *slice_stats;
- struct net_device_stats *stats = &dev->stats;
+ const struct myri10ge_priv *mgp = netdev_priv(dev);
+ const struct myri10ge_slice_netstats *slice_stats;
int i;
- spin_lock(&mgp->stats_lock);
- memset(stats, 0, sizeof(*stats));
for (i = 0; i < mgp->num_slices; i++) {
slice_stats = &mgp->ss[i].stats;
stats->rx_packets += slice_stats->rx_packets;
@@ -2994,7 +3056,6 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
stats->rx_dropped += slice_stats->rx_dropped;
stats->tx_dropped += slice_stats->tx_dropped;
}
- spin_unlock(&mgp->stats_lock);
return stats;
}
@@ -3127,7 +3188,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
{
struct pci_dev *bridge = mgp->pdev->bus->self;
struct device *dev = &mgp->pdev->dev;
- unsigned cap;
+ int cap;
unsigned err_cap;
u16 val;
u8 ext_type;
@@ -3137,7 +3198,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
return;
/* check that the bridge is a root port */
- cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(bridge);
pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val);
ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
if (ext_type != PCI_EXP_TYPE_ROOT_PORT) {
@@ -3155,8 +3216,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
" to force ECRC\n");
return;
}
- cap =
- pci_find_capability(bridge, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(bridge);
pci_read_config_word(bridge,
cap + PCI_CAP_FLAGS, &val);
ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
@@ -3266,7 +3326,6 @@ abort:
/* fall back to using the unaligned firmware */
mgp->tx_boundary = 2048;
set_fw_name(mgp, myri10ge_fw_unaligned, false);
-
}
static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
@@ -3277,7 +3336,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
int link_width, exp_cap;
u16 lnk;
- exp_cap = pci_find_capability(mgp->pdev, PCI_CAP_ID_EXP);
+ exp_cap = pci_pcie_cap(mgp->pdev);
pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
link_width = (lnk >> 4) & 0x3f;
@@ -3327,6 +3386,26 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
mgp->fw_name);
}
+static void myri10ge_mask_surprise_down(struct pci_dev *pdev)
+{
+ struct pci_dev *bridge = pdev->bus->self;
+ int cap;
+ u32 mask;
+
+ if (bridge == NULL)
+ return;
+
+ cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR);
+ if (cap) {
+ /* a sram parity error can cause a surprise link
+ * down; since we expect and can recover from sram
+ * parity errors, mask surprise link down events */
+ pci_read_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, &mask);
+ mask |= 0x20;
+ pci_write_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, mask);
+ }
+}
+
#ifdef CONFIG_PM
static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
{
@@ -3422,6 +3501,42 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
return reboot;
}
+static void
+myri10ge_check_slice(struct myri10ge_slice_state *ss, int *reset_needed,
+ int *busy_slice_cnt, u32 rx_pause_cnt)
+{
+ struct myri10ge_priv *mgp = ss->mgp;
+ int slice = ss - mgp->ss;
+
+ if (ss->tx.req != ss->tx.done &&
+ ss->tx.done == ss->watchdog_tx_done &&
+ ss->watchdog_tx_req != ss->watchdog_tx_done) {
+ /* nic seems like it might be stuck.. */
+ if (rx_pause_cnt != mgp->watchdog_pause) {
+ if (net_ratelimit())
+ netdev_warn(mgp->dev, "slice %d: TX paused, "
+ "check link partner\n", slice);
+ } else {
+ netdev_warn(mgp->dev,
+ "slice %d: TX stuck %d %d %d %d %d %d\n",
+ slice, ss->tx.queue_active, ss->tx.req,
+ ss->tx.done, ss->tx.pkt_start,
+ ss->tx.pkt_done,
+ (int)ntohl(mgp->ss[slice].fw_stats->
+ send_done_count));
+ *reset_needed = 1;
+ ss->stuck = 1;
+ }
+ }
+ if (ss->watchdog_tx_done != ss->tx.done ||
+ ss->watchdog_rx_done != ss->rx_done.cnt) {
+ *busy_slice_cnt += 1;
+ }
+ ss->watchdog_tx_done = ss->tx.done;
+ ss->watchdog_tx_req = ss->tx.req;
+ ss->watchdog_rx_done = ss->rx_done.cnt;
+}
+
/*
* This watchdog is used to check whether the board has suffered
* from a parity error and needs to be recovered.
@@ -3430,10 +3545,12 @@ static void myri10ge_watchdog(struct work_struct *work)
{
struct myri10ge_priv *mgp =
container_of(work, struct myri10ge_priv, watchdog_work);
- struct myri10ge_tx_buf *tx;
- u32 reboot;
+ struct myri10ge_slice_state *ss;
+ u32 reboot, rx_pause_cnt;
int status, rebooted;
int i;
+ int reset_needed = 0;
+ int busy_slice_cnt = 0;
u16 cmd, vendor;
mgp->watchdog_resets++;
@@ -3445,8 +3562,7 @@ static void myri10ge_watchdog(struct work_struct *work)
* For now, just report it */
reboot = myri10ge_read_reboot(mgp);
netdev_err(mgp->dev, "NIC rebooted (0x%x),%s resetting\n",
- reboot,
- myri10ge_reset_recover ? "" : " not");
+ reboot, myri10ge_reset_recover ? "" : " not");
if (myri10ge_reset_recover == 0)
return;
rtnl_lock();
@@ -3478,23 +3594,24 @@ static void myri10ge_watchdog(struct work_struct *work)
return;
}
}
- /* Perhaps it is a software error. Try to reset */
-
- netdev_err(mgp->dev, "device timeout, resetting\n");
+ /* Perhaps it is a software error. See if stuck slice
+ * has recovered, reset if not */
+ rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause);
for (i = 0; i < mgp->num_slices; i++) {
- tx = &mgp->ss[i].tx;
- netdev_err(mgp->dev, "(%d): %d %d %d %d %d %d\n",
- i, tx->queue_active, tx->req,
- tx->done, tx->pkt_start, tx->pkt_done,
- (int)ntohl(mgp->ss[i].fw_stats->
- send_done_count));
- msleep(2000);
- netdev_info(mgp->dev, "(%d): %d %d %d %d %d %d\n",
- i, tx->queue_active, tx->req,
- tx->done, tx->pkt_start, tx->pkt_done,
- (int)ntohl(mgp->ss[i].fw_stats->
- send_done_count));
+ ss = mgp->ss;
+ if (ss->stuck) {
+ myri10ge_check_slice(ss, &reset_needed,
+ &busy_slice_cnt,
+ rx_pause_cnt);
+ ss->stuck = 0;
+ }
}
+ if (!reset_needed) {
+ netdev_dbg(mgp->dev, "not resetting\n");
+ return;
+ }
+
+ netdev_err(mgp->dev, "device timeout, resetting\n");
}
if (!rebooted) {
@@ -3547,27 +3664,8 @@ static void myri10ge_watchdog_timer(unsigned long arg)
myri10ge_fill_thresh)
ss->rx_big.watchdog_needed = 0;
}
-
- if (ss->tx.req != ss->tx.done &&
- ss->tx.done == ss->watchdog_tx_done &&
- ss->watchdog_tx_req != ss->watchdog_tx_done) {
- /* nic seems like it might be stuck.. */
- if (rx_pause_cnt != mgp->watchdog_pause) {
- if (net_ratelimit())
- netdev_err(mgp->dev, "slice %d: TX paused, check link partner\n",
- i);
- } else {
- netdev_warn(mgp->dev, "slice %d stuck:", i);
- reset_needed = 1;
- }
- }
- if (ss->watchdog_tx_done != ss->tx.done ||
- ss->watchdog_rx_done != ss->rx_done.cnt) {
- busy_slice_cnt++;
- }
- ss->watchdog_tx_done = ss->tx.done;
- ss->watchdog_tx_req = ss->tx.req;
- ss->watchdog_rx_done = ss->rx_done.cnt;
+ myri10ge_check_slice(ss, &reset_needed, &busy_slice_cnt,
+ rx_pause_cnt);
}
/* if we've sent or received no traffic, poll the NIC to
* ensure it is still there. Otherwise, we risk not noticing
@@ -3613,8 +3711,8 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp)
dma_free_coherent(&pdev->dev, bytes,
ss->fw_stats, ss->fw_stats_bus);
ss->fw_stats = NULL;
- netif_napi_del(&ss->napi);
}
+ netif_napi_del(&ss->napi);
}
kfree(mgp->ss);
mgp->ss = NULL;
@@ -3790,7 +3888,7 @@ static const struct net_device_ops myri10ge_netdev_ops = {
.ndo_open = myri10ge_open,
.ndo_stop = myri10ge_close,
.ndo_start_xmit = myri10ge_xmit,
- .ndo_get_stats = myri10ge_get_stats,
+ .ndo_get_stats64 = myri10ge_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = myri10ge_change_mtu,
.ndo_fix_features = myri10ge_fix_features,
@@ -3845,6 +3943,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto abort_with_enabled;
}
+ myri10ge_mask_surprise_down(pdev);
pci_set_master(pdev);
dac_enabled = 1;
status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
@@ -3964,7 +4063,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
(unsigned long)mgp);
- spin_lock_init(&mgp->stats_lock);
SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
status = register_netdev(netdev);
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
index 62a1cbab603f..7ec4b864a550 100644
--- a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
+++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
@@ -45,6 +45,8 @@ struct mcp_gen_header {
unsigned bss_addr; /* start of bss */
unsigned features;
unsigned ee_hdr_addr;
+ unsigned led_pattern;
+ unsigned led_pattern_dflt;
/* 8 */
};
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
deleted file mode 100644
index 53aeea4b536e..000000000000
--- a/drivers/net/myri_sbus.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* myri_sbus.c: MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996, 1999, 2006, 2008 David S. Miller (davem@davemloft.net)
- */
-
-static char version[] =
- "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n";
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/dma-mapping.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/firmware.h>
-#include <linux/gfp.h>
-
-#include <net/dst.h>
-#include <net/arp.h>
-#include <net/sock.h>
-#include <net/ipv6.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-#include <asm/idprom.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/auxio.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-#include "myri_sbus.h"
-
-/* #define DEBUG_DETECT */
-/* #define DEBUG_IRQ */
-/* #define DEBUG_TRANSMIT */
-/* #define DEBUG_RECEIVE */
-/* #define DEBUG_HEADER */
-
-#ifdef DEBUG_DETECT
-#define DET(x) printk x
-#else
-#define DET(x)
-#endif
-
-#ifdef DEBUG_IRQ
-#define DIRQ(x) printk x
-#else
-#define DIRQ(x)
-#endif
-
-#ifdef DEBUG_TRANSMIT
-#define DTX(x) printk x
-#else
-#define DTX(x)
-#endif
-
-#ifdef DEBUG_RECEIVE
-#define DRX(x) printk x
-#else
-#define DRX(x)
-#endif
-
-#ifdef DEBUG_HEADER
-#define DHDR(x) printk x
-#else
-#define DHDR(x)
-#endif
-
-/* Firmware name */
-#define FWNAME "myricom/lanai.bin"
-
-static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
-{
- /* Clear IRQ mask. */
- sbus_writel(0, lp + LANAI_EIMASK);
-
- /* Turn RESET function off. */
- sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_reset_on(void __iomem *cregs)
-{
- /* Enable RESET function. */
- sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
-
- /* Disable IRQ's. */
- sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_disable_irq(void __iomem *lp, void __iomem *cregs)
-{
- sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
- sbus_writel(0, lp + LANAI_EIMASK);
- sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
-}
-
-static void myri_enable_irq(void __iomem *lp, void __iomem *cregs)
-{
- sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
- sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
-}
-
-static inline void bang_the_chip(struct myri_eth *mp)
-{
- struct myri_shmem __iomem *shmem = mp->shmem;
- void __iomem *cregs = mp->cregs;
-
- sbus_writel(1, &shmem->send);
- sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-}
-
-static int myri_do_handshake(struct myri_eth *mp)
-{
- struct myri_shmem __iomem *shmem = mp->shmem;
- void __iomem *cregs = mp->cregs;
- struct myri_channel __iomem *chan = &shmem->channel;
- int tick = 0;
-
- DET(("myri_do_handshake: "));
- if (sbus_readl(&chan->state) == STATE_READY) {
- DET(("Already STATE_READY, failed.\n"));
- return -1; /* We're hosed... */
- }
-
- myri_disable_irq(mp->lregs, cregs);
-
- while (tick++ < 25) {
- u32 softstate;
-
- /* Wake it up. */
- DET(("shakedown, CONTROL_WON, "));
- sbus_writel(1, &shmem->shakedown);
- sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-
- softstate = sbus_readl(&chan->state);
- DET(("chanstate[%08x] ", softstate));
- if (softstate == STATE_READY) {
- DET(("wakeup successful, "));
- break;
- }
-
- if (softstate != STATE_WFN) {
- DET(("not WFN setting that, "));
- sbus_writel(STATE_WFN, &chan->state);
- }
-
- udelay(20);
- }
-
- myri_enable_irq(mp->lregs, cregs);
-
- if (tick > 25) {
- DET(("25 ticks we lose, failure.\n"));
- return -1;
- }
- DET(("success\n"));
- return 0;
-}
-
-static int __devinit myri_load_lanai(struct myri_eth *mp)
-{
- const struct firmware *fw;
- struct net_device *dev = mp->dev;
- struct myri_shmem __iomem *shmem = mp->shmem;
- void __iomem *rptr;
- int i, lanai4_data_size;
-
- myri_disable_irq(mp->lregs, mp->cregs);
- myri_reset_on(mp->cregs);
-
- rptr = mp->lanai;
- for (i = 0; i < mp->eeprom.ramsz; i++)
- sbus_writeb(0, rptr + i);
-
- if (mp->eeprom.cpuvers >= CPUVERS_3_0)
- sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
-
- i = request_firmware(&fw, FWNAME, &mp->myri_op->dev);
- if (i) {
- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
- FWNAME, i);
- return i;
- }
- if (fw->size < 2) {
- printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
- fw->size, FWNAME);
- release_firmware(fw);
- return -EINVAL;
- }
- lanai4_data_size = fw->data[0] << 8 | fw->data[1];
-
- /* Load executable code. */
- for (i = 2; i < fw->size; i++)
- sbus_writeb(fw->data[i], rptr++);
-
- /* Load data segment. */
- for (i = 0; i < lanai4_data_size; i++)
- sbus_writeb(0, rptr++);
-
- /* Set device address. */
- sbus_writeb(0, &shmem->addr[0]);
- sbus_writeb(0, &shmem->addr[1]);
- for (i = 0; i < 6; i++)
- sbus_writeb(dev->dev_addr[i],
- &shmem->addr[i + 2]);
-
- /* Set SBUS bursts and interrupt mask. */
- sbus_writel(((mp->myri_bursts & 0xf8) >> 3), &shmem->burst);
- sbus_writel(SHMEM_IMASK_RX, &shmem->imask);
-
- /* Release the LANAI. */
- myri_disable_irq(mp->lregs, mp->cregs);
- myri_reset_off(mp->lregs, mp->cregs);
- myri_disable_irq(mp->lregs, mp->cregs);
-
- /* Wait for the reset to complete. */
- for (i = 0; i < 5000; i++) {
- if (sbus_readl(&shmem->channel.state) != STATE_READY)
- break;
- else
- udelay(10);
- }
-
- if (i == 5000)
- printk(KERN_ERR "myricom: Chip would not reset after firmware load.\n");
-
- i = myri_do_handshake(mp);
- if (i)
- printk(KERN_ERR "myricom: Handshake with LANAI failed.\n");
-
- if (mp->eeprom.cpuvers == CPUVERS_4_0)
- sbus_writel(0, mp->lregs + LANAI_VERS);
-
- release_firmware(fw);
- return i;
-}
-
-static void myri_clean_rings(struct myri_eth *mp)
-{
- struct sendq __iomem *sq = mp->sq;
- struct recvq __iomem *rq = mp->rq;
- int i;
-
- sbus_writel(0, &rq->tail);
- sbus_writel(0, &rq->head);
- for (i = 0; i < (RX_RING_SIZE+1); i++) {
- if (mp->rx_skbs[i] != NULL) {
- struct myri_rxd __iomem *rxd = &rq->myri_rxd[i];
- u32 dma_addr;
-
- dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
- dma_unmap_single(&mp->myri_op->dev, dma_addr,
- RX_ALLOC_SIZE, DMA_FROM_DEVICE);
- dev_kfree_skb(mp->rx_skbs[i]);
- mp->rx_skbs[i] = NULL;
- }
- }
-
- mp->tx_old = 0;
- sbus_writel(0, &sq->tail);
- sbus_writel(0, &sq->head);
- for (i = 0; i < TX_RING_SIZE; i++) {
- if (mp->tx_skbs[i] != NULL) {
- struct sk_buff *skb = mp->tx_skbs[i];
- struct myri_txd __iomem *txd = &sq->myri_txd[i];
- u32 dma_addr;
-
- dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
- dma_unmap_single(&mp->myri_op->dev, dma_addr,
- (skb->len + 3) & ~3,
- DMA_TO_DEVICE);
- dev_kfree_skb(mp->tx_skbs[i]);
- mp->tx_skbs[i] = NULL;
- }
- }
-}
-
-static void myri_init_rings(struct myri_eth *mp, int from_irq)
-{
- struct recvq __iomem *rq = mp->rq;
- struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
- struct net_device *dev = mp->dev;
- gfp_t gfp_flags = GFP_KERNEL;
- int i;
-
- if (from_irq || in_interrupt())
- gfp_flags = GFP_ATOMIC;
-
- myri_clean_rings(mp);
- for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags);
- u32 dma_addr;
-
- if (!skb)
- continue;
- mp->rx_skbs[i] = skb;
- skb->dev = dev;
- skb_put(skb, RX_ALLOC_SIZE);
-
- dma_addr = dma_map_single(&mp->myri_op->dev,
- skb->data, RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
- sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
- sbus_writel(i, &rxd[i].ctx);
- sbus_writel(1, &rxd[i].num_sg);
- }
- sbus_writel(0, &rq->head);
- sbus_writel(RX_RING_SIZE, &rq->tail);
-}
-
-static int myri_init(struct myri_eth *mp, int from_irq)
-{
- myri_init_rings(mp, from_irq);
- return 0;
-}
-
-static void myri_is_not_so_happy(struct myri_eth *mp)
-{
-}
-
-#ifdef DEBUG_HEADER
-static void dump_ehdr(struct ethhdr *ehdr)
-{
- printk("ehdr[h_dst(%pM)"
- "h_source(%pM)"
- "h_proto(%04x)]\n",
- ehdr->h_dest, ehdr->h_source, ehdr->h_proto);
-}
-
-static void dump_ehdr_and_myripad(unsigned char *stuff)
-{
- struct ethhdr *ehdr = (struct ethhdr *) (stuff + 2);
-
- printk("pad[%02x:%02x]", stuff[0], stuff[1]);
- dump_ehdr(ehdr);
-}
-#endif
-
-static void myri_tx(struct myri_eth *mp, struct net_device *dev)
-{
- struct sendq __iomem *sq= mp->sq;
- int entry = mp->tx_old;
- int limit = sbus_readl(&sq->head);
-
- DTX(("entry[%d] limit[%d] ", entry, limit));
- if (entry == limit)
- return;
- while (entry != limit) {
- struct sk_buff *skb = mp->tx_skbs[entry];
- u32 dma_addr;
-
- DTX(("SKB[%d] ", entry));
- dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
- dma_unmap_single(&mp->myri_op->dev, dma_addr,
- skb->len, DMA_TO_DEVICE);
- dev_kfree_skb(skb);
- mp->tx_skbs[entry] = NULL;
- dev->stats.tx_packets++;
- entry = NEXT_TX(entry);
- }
- mp->tx_old = entry;
-}
-
-/* Determine the packet's protocol ID. The rule here is that we
- * assume 802.3 if the type field is short enough to be a length.
- * This is normal practice and works for any 'now in use' protocol.
- */
-static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
- struct ethhdr *eth;
- unsigned char *rawp;
-
- skb_set_mac_header(skb, MYRI_PAD_LEN);
- skb_pull(skb, dev->hard_header_len);
- eth = eth_hdr(skb);
-
-#ifdef DEBUG_HEADER
- DHDR(("myri_type_trans: "));
- dump_ehdr(eth);
-#endif
- if (*eth->h_dest & 1) {
- if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
- skb->pkt_type = PACKET_BROADCAST;
- else
- skb->pkt_type = PACKET_MULTICAST;
- } else if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
- if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
- skb->pkt_type = PACKET_OTHERHOST;
- }
-
- if (ntohs(eth->h_proto) >= 1536)
- return eth->h_proto;
-
- rawp = skb->data;
-
- /* This is a magic hack to spot IPX packets. Older Novell breaks
- * the protocol design and runs IPX over 802.3 without an 802.2 LLC
- * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
- * won't work for fault tolerant netware but does for the rest.
- */
- if (*(unsigned short *)rawp == 0xFFFF)
- return htons(ETH_P_802_3);
-
- /* Real 802.2 LLC */
- return htons(ETH_P_802_2);
-}
-
-static void myri_rx(struct myri_eth *mp, struct net_device *dev)
-{
- struct recvq __iomem *rq = mp->rq;
- struct recvq __iomem *rqa = mp->rqack;
- int entry = sbus_readl(&rqa->head);
- int limit = sbus_readl(&rqa->tail);
- int drops;
-
- DRX(("entry[%d] limit[%d] ", entry, limit));
- if (entry == limit)
- return;
- drops = 0;
- DRX(("\n"));
- while (entry != limit) {
- struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry];
- u32 csum = sbus_readl(&rxdack->csum);
- int len = sbus_readl(&rxdack->myri_scatters[0].len);
- int index = sbus_readl(&rxdack->ctx);
- struct myri_rxd __iomem *rxd = &rq->myri_rxd[sbus_readl(&rq->tail)];
- struct sk_buff *skb = mp->rx_skbs[index];
-
- /* Ack it. */
- sbus_writel(NEXT_RX(entry), &rqa->head);
-
- /* Check for errors. */
- DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
- dma_sync_single_for_cpu(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE, DMA_FROM_DEVICE);
- if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
- DRX(("ERROR["));
- dev->stats.rx_errors++;
- if (len < (ETH_HLEN + MYRI_PAD_LEN)) {
- DRX(("BAD_LENGTH] "));
- dev->stats.rx_length_errors++;
- } else {
- DRX(("NO_PADDING] "));
- dev->stats.rx_frame_errors++;
- }
-
- /* Return it to the LANAI. */
- drop_it:
- drops++;
- DRX(("DROP "));
- dev->stats.rx_dropped++;
- dma_sync_single_for_device(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
- sbus_writel(index, &rxd->ctx);
- sbus_writel(1, &rxd->num_sg);
- sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
- goto next;
- }
-
- DRX(("len[%d] ", len));
- if (len > RX_COPY_THRESHOLD) {
- struct sk_buff *new_skb;
- u32 dma_addr;
-
- DRX(("BIGBUFF "));
- new_skb = myri_alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC);
- if (new_skb == NULL) {
- DRX(("skb_alloc(FAILED) "));
- goto drop_it;
- }
- dma_unmap_single(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- mp->rx_skbs[index] = new_skb;
- new_skb->dev = dev;
- skb_put(new_skb, RX_ALLOC_SIZE);
- dma_addr = dma_map_single(&mp->myri_op->dev,
- new_skb->data,
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
- sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
- sbus_writel(index, &rxd->ctx);
- sbus_writel(1, &rxd->num_sg);
- sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
- /* Trim the original skb for the netif. */
- DRX(("trim(%d) ", len));
- skb_trim(skb, len);
- } else {
- struct sk_buff *copy_skb = dev_alloc_skb(len);
-
- DRX(("SMALLBUFF "));
- if (copy_skb == NULL) {
- DRX(("dev_alloc_skb(FAILED) "));
- goto drop_it;
- }
- /* DMA sync already done above. */
- copy_skb->dev = dev;
- DRX(("resv_and_put "));
- skb_put(copy_skb, len);
- skb_copy_from_linear_data(skb, copy_skb->data, len);
-
- /* Reuse original ring buffer. */
- DRX(("reuse "));
- dma_sync_single_for_device(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
- sbus_writel(index, &rxd->ctx);
- sbus_writel(1, &rxd->num_sg);
- sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
- skb = copy_skb;
- }
-
- /* Just like the happy meal we get checksums from this card. */
- skb->csum = csum;
- skb->ip_summed = CHECKSUM_UNNECESSARY; /* XXX */
-
- skb->protocol = myri_type_trans(skb, dev);
- DRX(("prot[%04x] netif_rx ", skb->protocol));
- netif_rx(skb);
-
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += len;
- next:
- DRX(("NEXT\n"));
- entry = NEXT_RX(entry);
- }
-}
-
-static irqreturn_t myri_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct myri_eth *mp = netdev_priv(dev);
- void __iomem *lregs = mp->lregs;
- struct myri_channel __iomem *chan = &mp->shmem->channel;
- unsigned long flags;
- u32 status;
- int handled = 0;
-
- spin_lock_irqsave(&mp->irq_lock, flags);
-
- status = sbus_readl(lregs + LANAI_ISTAT);
- DIRQ(("myri_interrupt: status[%08x] ", status));
- if (status & ISTAT_HOST) {
- u32 softstate;
-
- handled = 1;
- DIRQ(("IRQ_DISAB "));
- myri_disable_irq(lregs, mp->cregs);
- softstate = sbus_readl(&chan->state);
- DIRQ(("state[%08x] ", softstate));
- if (softstate != STATE_READY) {
- DIRQ(("myri_not_so_happy "));
- myri_is_not_so_happy(mp);
- }
- DIRQ(("\nmyri_rx: "));
- myri_rx(mp, dev);
- DIRQ(("\nistat=ISTAT_HOST "));
- sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT);
- DIRQ(("IRQ_ENAB "));
- myri_enable_irq(lregs, mp->cregs);
- }
- DIRQ(("\n"));
-
- spin_unlock_irqrestore(&mp->irq_lock, flags);
-
- return IRQ_RETVAL(handled);
-}
-
-static int myri_open(struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
-
- return myri_init(mp, in_interrupt());
-}
-
-static int myri_close(struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
-
- myri_clean_rings(mp);
- return 0;
-}
-
-static void myri_tx_timeout(struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
-
- printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-
- dev->stats.tx_errors++;
- myri_init(mp, 0);
- netif_wake_queue(dev);
-}
-
-static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
- struct sendq __iomem *sq = mp->sq;
- struct myri_txd __iomem *txd;
- unsigned long flags;
- unsigned int head, tail;
- int len, entry;
- u32 dma_addr;
-
- DTX(("myri_start_xmit: "));
-
- myri_tx(mp, dev);
-
- netif_stop_queue(dev);
-
- /* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
- head = sbus_readl(&sq->head);
- tail = sbus_readl(&sq->tail);
-
- if (!TX_BUFFS_AVAIL(head, tail)) {
- DTX(("no buffs available, returning 1\n"));
- return NETDEV_TX_BUSY;
- }
-
- spin_lock_irqsave(&mp->irq_lock, flags);
-
- DHDR(("xmit[skbdata(%p)]\n", skb->data));
-#ifdef DEBUG_HEADER
- dump_ehdr_and_myripad(((unsigned char *) skb->data));
-#endif
-
- /* XXX Maybe this can go as well. */
- len = skb->len;
- if (len & 3) {
- DTX(("len&3 "));
- len = (len + 4) & (~3);
- }
-
- entry = sbus_readl(&sq->tail);
-
- txd = &sq->myri_txd[entry];
- mp->tx_skbs[entry] = skb;
-
- /* Must do this before we sbus map it. */
- if (skb->data[MYRI_PAD_LEN] & 0x1) {
- sbus_writew(0xffff, &txd->addr[0]);
- sbus_writew(0xffff, &txd->addr[1]);
- sbus_writew(0xffff, &txd->addr[2]);
- sbus_writew(0xffff, &txd->addr[3]);
- } else {
- sbus_writew(0xffff, &txd->addr[0]);
- sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]);
- sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]);
- sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
- }
-
- dma_addr = dma_map_single(&mp->myri_op->dev, skb->data,
- len, DMA_TO_DEVICE);
- sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
- sbus_writel(len, &txd->myri_gathers[0].len);
- sbus_writel(1, &txd->num_sg);
- sbus_writel(KERNEL_CHANNEL, &txd->chan);
- sbus_writel(len, &txd->len);
- sbus_writel((u32)-1, &txd->csum_off);
- sbus_writel(0, &txd->csum_field);
-
- sbus_writel(NEXT_TX(entry), &sq->tail);
- DTX(("BangTheChip "));
- bang_the_chip(mp);
-
- DTX(("tbusy=0, returning 0\n"));
- netif_start_queue(dev);
- spin_unlock_irqrestore(&mp->irq_lock, flags);
- return NETDEV_TX_OK;
-}
-
-/* Create the MyriNet MAC header for an arbitrary protocol layer
- *
- * saddr=NULL means use device source address
- * daddr=NULL means leave destination address (eg unresolved arp)
- */
-static int myri_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, const void *daddr,
- const void *saddr, unsigned len)
-{
- struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
- unsigned char *pad = (unsigned char *) skb_push(skb, MYRI_PAD_LEN);
-
-#ifdef DEBUG_HEADER
- DHDR(("myri_header: pad[%02x,%02x] ", pad[0], pad[1]));
- dump_ehdr(eth);
-#endif
-
- /* Set the MyriNET padding identifier. */
- pad[0] = MYRI_PAD_LEN;
- pad[1] = 0xab;
-
- /* Set the protocol type. For a packet of type ETH_P_802_3/2 we put the
- * length in here instead.
- */
- if (type != ETH_P_802_3 && type != ETH_P_802_2)
- eth->h_proto = htons(type);
- else
- eth->h_proto = htons(len);
-
- /* Set the source hardware address. */
- if (saddr)
- memcpy(eth->h_source, saddr, dev->addr_len);
- else
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-
- /* Anyway, the loopback-device should never use this function... */
- if (dev->flags & IFF_LOOPBACK) {
- int i;
- for (i = 0; i < dev->addr_len; i++)
- eth->h_dest[i] = 0;
- return dev->hard_header_len;
- }
-
- if (daddr) {
- memcpy(eth->h_dest, daddr, dev->addr_len);
- return dev->hard_header_len;
- }
- return -dev->hard_header_len;
-}
-
-/* Rebuild the MyriNet MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on this
- * sk_buff. We now let ARP fill in the other fields.
- */
-static int myri_rebuild_header(struct sk_buff *skb)
-{
- unsigned char *pad = (unsigned char *) skb->data;
- struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
- struct net_device *dev = skb->dev;
-
-#ifdef DEBUG_HEADER
- DHDR(("myri_rebuild_header: pad[%02x,%02x] ", pad[0], pad[1]));
- dump_ehdr(eth);
-#endif
-
- /* Refill MyriNet padding identifiers, this is just being anal. */
- pad[0] = MYRI_PAD_LEN;
- pad[1] = 0xab;
-
- switch (eth->h_proto)
- {
-#ifdef CONFIG_INET
- case cpu_to_be16(ETH_P_IP):
- return arp_find(eth->h_dest, skb);
-#endif
-
- default:
- printk(KERN_DEBUG
- "%s: unable to resolve type %X addresses.\n",
- dev->name, (int)eth->h_proto);
-
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
- return 0;
- break;
- }
-
- return 0;
-}
-
-static int myri_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
-{
- unsigned short type = hh->hh_type;
- unsigned char *pad;
- struct ethhdr *eth;
- const struct net_device *dev = neigh->dev;
-
- pad = ((unsigned char *) hh->hh_data) +
- HH_DATA_OFF(sizeof(*eth) + MYRI_PAD_LEN);
- eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
-
- if (type == htons(ETH_P_802_3))
- return -1;
-
- /* Refill MyriNet padding identifiers, this is just being anal. */
- pad[0] = MYRI_PAD_LEN;
- pad[1] = 0xab;
-
- eth->h_proto = type;
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
- memcpy(eth->h_dest, neigh->ha, dev->addr_len);
- hh->hh_len = 16;
- return 0;
-}
-
-
-/* Called by Address Resolution module to notify changes in address. */
-void myri_header_cache_update(struct hh_cache *hh,
- const struct net_device *dev,
- const unsigned char * haddr)
-{
- memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
- haddr, dev->addr_len);
-}
-
-static int myri_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < (ETH_HLEN + MYRI_PAD_LEN)) || (new_mtu > MYRINET_MTU))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
-static void myri_set_multicast(struct net_device *dev)
-{
- /* Do nothing, all MyriCOM nodes transmit multicast frames
- * as broadcast packets...
- */
-}
-
-static inline void set_boardid_from_idprom(struct myri_eth *mp, int num)
-{
- mp->eeprom.id[0] = 0;
- mp->eeprom.id[1] = idprom->id_machtype;
- mp->eeprom.id[2] = (idprom->id_sernum >> 16) & 0xff;
- mp->eeprom.id[3] = (idprom->id_sernum >> 8) & 0xff;
- mp->eeprom.id[4] = (idprom->id_sernum >> 0) & 0xff;
- mp->eeprom.id[5] = num;
-}
-
-static inline void determine_reg_space_size(struct myri_eth *mp)
-{
- switch(mp->eeprom.cpuvers) {
- case CPUVERS_2_3:
- case CPUVERS_3_0:
- case CPUVERS_3_1:
- case CPUVERS_3_2:
- mp->reg_size = (3 * 128 * 1024) + 4096;
- break;
-
- case CPUVERS_4_0:
- case CPUVERS_4_1:
- mp->reg_size = ((4096<<1) + mp->eeprom.ramsz);
- break;
-
- case CPUVERS_4_2:
- case CPUVERS_5_0:
- default:
- printk("myricom: AIEEE weird cpu version %04x assuming pre4.0\n",
- mp->eeprom.cpuvers);
- mp->reg_size = (3 * 128 * 1024) + 4096;
- }
-}
-
-#ifdef DEBUG_DETECT
-static void dump_eeprom(struct myri_eth *mp)
-{
- printk("EEPROM: clockval[%08x] cpuvers[%04x] "
- "id[%02x,%02x,%02x,%02x,%02x,%02x]\n",
- mp->eeprom.cval, mp->eeprom.cpuvers,
- mp->eeprom.id[0], mp->eeprom.id[1], mp->eeprom.id[2],
- mp->eeprom.id[3], mp->eeprom.id[4], mp->eeprom.id[5]);
- printk("EEPROM: ramsz[%08x]\n", mp->eeprom.ramsz);
- printk("EEPROM: fvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.fvers[0], mp->eeprom.fvers[1], mp->eeprom.fvers[2],
- mp->eeprom.fvers[3], mp->eeprom.fvers[4], mp->eeprom.fvers[5],
- mp->eeprom.fvers[6], mp->eeprom.fvers[7]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.fvers[8], mp->eeprom.fvers[9], mp->eeprom.fvers[10],
- mp->eeprom.fvers[11], mp->eeprom.fvers[12], mp->eeprom.fvers[13],
- mp->eeprom.fvers[14], mp->eeprom.fvers[15]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.fvers[16], mp->eeprom.fvers[17], mp->eeprom.fvers[18],
- mp->eeprom.fvers[19], mp->eeprom.fvers[20], mp->eeprom.fvers[21],
- mp->eeprom.fvers[22], mp->eeprom.fvers[23]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
- mp->eeprom.fvers[24], mp->eeprom.fvers[25], mp->eeprom.fvers[26],
- mp->eeprom.fvers[27], mp->eeprom.fvers[28], mp->eeprom.fvers[29],
- mp->eeprom.fvers[30], mp->eeprom.fvers[31]);
- printk("EEPROM: mvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.mvers[0], mp->eeprom.mvers[1], mp->eeprom.mvers[2],
- mp->eeprom.mvers[3], mp->eeprom.mvers[4], mp->eeprom.mvers[5],
- mp->eeprom.mvers[6], mp->eeprom.mvers[7]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
- mp->eeprom.mvers[8], mp->eeprom.mvers[9], mp->eeprom.mvers[10],
- mp->eeprom.mvers[11], mp->eeprom.mvers[12], mp->eeprom.mvers[13],
- mp->eeprom.mvers[14], mp->eeprom.mvers[15]);
- printk("EEPROM: dlval[%04x] brd_type[%04x] bus_type[%04x] prod_code[%04x]\n",
- mp->eeprom.dlval, mp->eeprom.brd_type, mp->eeprom.bus_type,
- mp->eeprom.prod_code);
- printk("EEPROM: serial_num[%08x]\n", mp->eeprom.serial_num);
-}
-#endif
-
-static const struct header_ops myri_header_ops = {
- .create = myri_header,
- .rebuild = myri_rebuild_header,
- .cache = myri_header_cache,
- .cache_update = myri_header_cache_update,
-};
-
-static const struct net_device_ops myri_ops = {
- .ndo_open = myri_open,
- .ndo_stop = myri_close,
- .ndo_start_xmit = myri_start_xmit,
- .ndo_set_multicast_list = myri_set_multicast,
- .ndo_tx_timeout = myri_tx_timeout,
- .ndo_change_mtu = myri_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-static int __devinit myri_sbus_probe(struct platform_device *op)
-{
- struct device_node *dp = op->dev.of_node;
- static unsigned version_printed;
- struct net_device *dev;
- struct myri_eth *mp;
- const void *prop;
- static int num;
- int i, len;
-
- DET(("myri_ether_init(%p,%d):\n", op, num));
- dev = alloc_etherdev(sizeof(struct myri_eth));
- if (!dev)
- return -ENOMEM;
-
- if (version_printed++ == 0)
- printk(version);
-
- SET_NETDEV_DEV(dev, &op->dev);
-
- mp = netdev_priv(dev);
- spin_lock_init(&mp->irq_lock);
- mp->myri_op = op;
-
- /* Clean out skb arrays. */
- for (i = 0; i < (RX_RING_SIZE + 1); i++)
- mp->rx_skbs[i] = NULL;
-
- for (i = 0; i < TX_RING_SIZE; i++)
- mp->tx_skbs[i] = NULL;
-
- /* First check for EEPROM information. */
- prop = of_get_property(dp, "myrinet-eeprom-info", &len);
-
- if (prop)
- memcpy(&mp->eeprom, prop, sizeof(struct myri_eeprom));
- if (!prop) {
- /* No eeprom property, must cook up the values ourselves. */
- DET(("No EEPROM: "));
- mp->eeprom.bus_type = BUS_TYPE_SBUS;
- mp->eeprom.cpuvers =
- of_getintprop_default(dp, "cpu_version", 0);
- mp->eeprom.cval =
- of_getintprop_default(dp, "clock_value", 0);
- mp->eeprom.ramsz = of_getintprop_default(dp, "sram_size", 0);
- if (!mp->eeprom.cpuvers)
- mp->eeprom.cpuvers = CPUVERS_2_3;
- if (mp->eeprom.cpuvers < CPUVERS_3_0)
- mp->eeprom.cval = 0;
- if (!mp->eeprom.ramsz)
- mp->eeprom.ramsz = (128 * 1024);
-
- prop = of_get_property(dp, "myrinet-board-id", &len);
- if (prop)
- memcpy(&mp->eeprom.id[0], prop, 6);
- else
- set_boardid_from_idprom(mp, num);
-
- prop = of_get_property(dp, "fpga_version", &len);
- if (prop)
- memcpy(&mp->eeprom.fvers[0], prop, 32);
- else
- memset(&mp->eeprom.fvers[0], 0, 32);
-
- if (mp->eeprom.cpuvers == CPUVERS_4_1) {
- if (mp->eeprom.ramsz == (128 * 1024))
- mp->eeprom.ramsz = (256 * 1024);
- if ((mp->eeprom.cval == 0x40414041) ||
- (mp->eeprom.cval == 0x90449044))
- mp->eeprom.cval = 0x50e450e4;
- }
- }
-#ifdef DEBUG_DETECT
- dump_eeprom(mp);
-#endif
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = mp->eeprom.id[i];
-
- determine_reg_space_size(mp);
-
- /* Map in the MyriCOM register/localram set. */
- if (mp->eeprom.cpuvers < CPUVERS_4_0) {
- /* XXX Makes no sense, if control reg is non-existent this
- * XXX driver cannot function at all... maybe pre-4.0 is
- * XXX only a valid version for PCI cards? Ask feldy...
- */
- DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
- mp->regs = of_ioremap(&op->resource[0], 0,
- mp->reg_size, "MyriCOM Regs");
- if (!mp->regs) {
- printk("MyriCOM: Cannot map MyriCOM registers.\n");
- goto err;
- }
- mp->lanai = mp->regs + (256 * 1024);
- mp->lregs = mp->lanai + (0x10000 * 2);
- } else {
- DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
- mp->cregs = of_ioremap(&op->resource[0], 0,
- PAGE_SIZE, "MyriCOM Control Regs");
- mp->lregs = of_ioremap(&op->resource[0], (256 * 1024),
- PAGE_SIZE, "MyriCOM LANAI Regs");
- mp->lanai = of_ioremap(&op->resource[0], (512 * 1024),
- mp->eeprom.ramsz, "MyriCOM SRAM");
- }
- DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
- mp->cregs, mp->lregs, mp->lanai));
-
- if (mp->eeprom.cpuvers >= CPUVERS_4_0)
- mp->shmem_base = 0xf000;
- else
- mp->shmem_base = 0x8000;
-
- DET(("Shared memory base is %04x, ", mp->shmem_base));
-
- mp->shmem = (struct myri_shmem __iomem *)
- (mp->lanai + (mp->shmem_base * 2));
- DET(("shmem mapped at %p\n", mp->shmem));
-
- mp->rqack = &mp->shmem->channel.recvqa;
- mp->rq = &mp->shmem->channel.recvq;
- mp->sq = &mp->shmem->channel.sendq;
-
- /* Reset the board. */
- DET(("Resetting LANAI\n"));
- myri_reset_off(mp->lregs, mp->cregs);
- myri_reset_on(mp->cregs);
-
- /* Turn IRQ's off. */
- myri_disable_irq(mp->lregs, mp->cregs);
-
- /* Reset once more. */
- myri_reset_on(mp->cregs);
-
- /* Get the supported DVMA burst sizes from our SBUS. */
- mp->myri_bursts = of_getintprop_default(dp->parent,
- "burst-sizes", 0x00);
- if (!sbus_can_burst64())
- mp->myri_bursts &= ~(DMA_BURST64);
-
- DET(("MYRI bursts %02x\n", mp->myri_bursts));
-
- /* Encode SBUS interrupt level in second control register. */
- i = of_getintprop_default(dp, "interrupts", 0);
- if (i == 0)
- i = 4;
- DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
- i, (1 << i)));
-
- sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);
-
- mp->dev = dev;
- dev->watchdog_timeo = 5*HZ;
- dev->irq = op->archdata.irqs[0];
- dev->netdev_ops = &myri_ops;
-
- /* Register interrupt handler now. */
- DET(("Requesting MYRIcom IRQ line.\n"));
- if (request_irq(dev->irq, myri_interrupt,
- IRQF_SHARED, "MyriCOM Ethernet", (void *) dev)) {
- printk("MyriCOM: Cannot register interrupt handler.\n");
- goto err;
- }
-
- dev->mtu = MYRINET_MTU;
- dev->header_ops = &myri_header_ops;
-
- dev->hard_header_len = (ETH_HLEN + MYRI_PAD_LEN);
-
- /* Load code onto the LANai. */
- DET(("Loading LANAI firmware\n"));
- if (myri_load_lanai(mp)) {
- printk(KERN_ERR "MyriCOM: Cannot Load LANAI firmware.\n");
- goto err_free_irq;
- }
-
- if (register_netdev(dev)) {
- printk("MyriCOM: Cannot register device.\n");
- goto err_free_irq;
- }
-
- dev_set_drvdata(&op->dev, mp);
-
- num++;
-
- printk("%s: MyriCOM MyriNET Ethernet %pM\n",
- dev->name, dev->dev_addr);
-
- return 0;
-
-err_free_irq:
- free_irq(dev->irq, dev);
-err:
- /* This will also free the co-allocated private data*/
- free_netdev(dev);
- return -ENODEV;
-}
-
-static int __devexit myri_sbus_remove(struct platform_device *op)
-{
- struct myri_eth *mp = dev_get_drvdata(&op->dev);
- struct net_device *net_dev = mp->dev;
-
- unregister_netdev(net_dev);
-
- free_irq(net_dev->irq, net_dev);
-
- if (mp->eeprom.cpuvers < CPUVERS_4_0) {
- of_iounmap(&op->resource[0], mp->regs, mp->reg_size);
- } else {
- of_iounmap(&op->resource[0], mp->cregs, PAGE_SIZE);
- of_iounmap(&op->resource[0], mp->lregs, (256 * 1024));
- of_iounmap(&op->resource[0], mp->lanai, (512 * 1024));
- }
-
- free_netdev(net_dev);
-
- dev_set_drvdata(&op->dev, NULL);
-
- return 0;
-}
-
-static const struct of_device_id myri_sbus_match[] = {
- {
- .name = "MYRICOM,mlanai",
- },
- {
- .name = "myri",
- },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, myri_sbus_match);
-
-static struct platform_driver myri_sbus_driver = {
- .driver = {
- .name = "myri",
- .owner = THIS_MODULE,
- .of_match_table = myri_sbus_match,
- },
- .probe = myri_sbus_probe,
- .remove = __devexit_p(myri_sbus_remove),
-};
-
-static int __init myri_sbus_init(void)
-{
- return platform_driver_register(&myri_sbus_driver);
-}
-
-static void __exit myri_sbus_exit(void)
-{
- platform_driver_unregister(&myri_sbus_driver);
-}
-
-module_init(myri_sbus_init);
-module_exit(myri_sbus_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(FWNAME);
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
deleted file mode 100644
index 80a2fa5cf757..000000000000
--- a/drivers/net/myri_sbus.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/* myri_sbus.h: Defines for MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _MYRI_SBUS_H
-#define _MYRI_SBUS_H
-
-/* LANAI Registers */
-#define LANAI_IPF0 0x00UL /* Context zero state registers.*/
-#define LANAI_CUR0 0x04UL
-#define LANAI_PREV0 0x08UL
-#define LANAI_DATA0 0x0cUL
-#define LANAI_DPF0 0x10UL
-#define LANAI_IPF1 0x14UL /* Context one state registers. */
-#define LANAI_CUR1 0x18UL
-#define LANAI_PREV1 0x1cUL
-#define LANAI_DATA1 0x20UL
-#define LANAI_DPF1 0x24UL
-#define LANAI_ISTAT 0x28UL /* Interrupt status. */
-#define LANAI_EIMASK 0x2cUL /* External IRQ mask. */
-#define LANAI_ITIMER 0x30UL /* IRQ timer. */
-#define LANAI_RTC 0x34UL /* Real Time Clock */
-#define LANAI_CSUM 0x38UL /* Checksum. */
-#define LANAI_DMAXADDR 0x3cUL /* SBUS DMA external address. */
-#define LANAI_DMALADDR 0x40UL /* SBUS DMA local address. */
-#define LANAI_DMACTR 0x44UL /* SBUS DMA counter. */
-#define LANAI_RXDMAPTR 0x48UL /* Receive DMA pointer. */
-#define LANAI_RXDMALIM 0x4cUL /* Receive DMA limit. */
-#define LANAI_TXDMAPTR 0x50UL /* Transmit DMA pointer. */
-#define LANAI_TXDMALIM 0x54UL /* Transmit DMA limit. */
-#define LANAI_TXDMALIMT 0x58UL /* Transmit DMA limit w/tail. */
- /* 0x5cUL, reserved */
-#define LANAI_RBYTE 0x60UL /* Receive byte. */
- /* 0x64-->0x6c, reserved */
-#define LANAI_RHALF 0x70UL /* Receive half-word. */
- /* 0x72UL, reserved */
-#define LANAI_RWORD 0x74UL /* Receive word. */
-#define LANAI_SALIGN 0x78UL /* Send align. */
-#define LANAI_SBYTE 0x7cUL /* SingleSend send-byte. */
-#define LANAI_SHALF 0x80UL /* SingleSend send-halfword. */
-#define LANAI_SWORD 0x84UL /* SingleSend send-word. */
-#define LANAI_SSENDT 0x88UL /* SingleSend special. */
-#define LANAI_DMADIR 0x8cUL /* DMA direction. */
-#define LANAI_DMASTAT 0x90UL /* DMA status. */
-#define LANAI_TIMEO 0x94UL /* Timeout register. */
-#define LANAI_MYRINET 0x98UL /* XXX MAGIC myricom thing */
-#define LANAI_HWDEBUG 0x9cUL /* Hardware debugging reg. */
-#define LANAI_LEDS 0xa0UL /* LED control. */
-#define LANAI_VERS 0xa4UL /* Version register. */
-#define LANAI_LINKON 0xa8UL /* Link activation reg. */
- /* 0xac-->0x104, reserved */
-#define LANAI_CVAL 0x108UL /* Clock value register. */
-#define LANAI_REG_SIZE 0x10cUL
-
-/* Interrupt status bits. */
-#define ISTAT_DEBUG 0x80000000
-#define ISTAT_HOST 0x40000000
-#define ISTAT_LAN7 0x00800000
-#define ISTAT_LAN6 0x00400000
-#define ISTAT_LAN5 0x00200000
-#define ISTAT_LAN4 0x00100000
-#define ISTAT_LAN3 0x00080000
-#define ISTAT_LAN2 0x00040000
-#define ISTAT_LAN1 0x00020000
-#define ISTAT_LAN0 0x00010000
-#define ISTAT_WRDY 0x00008000
-#define ISTAT_HRDY 0x00004000
-#define ISTAT_SRDY 0x00002000
-#define ISTAT_LINK 0x00001000
-#define ISTAT_FRES 0x00000800
-#define ISTAT_NRES 0x00000800
-#define ISTAT_WAKE 0x00000400
-#define ISTAT_OB2 0x00000200
-#define ISTAT_OB1 0x00000100
-#define ISTAT_TAIL 0x00000080
-#define ISTAT_WDOG 0x00000040
-#define ISTAT_TIME 0x00000020
-#define ISTAT_DMA 0x00000010
-#define ISTAT_SEND 0x00000008
-#define ISTAT_BUF 0x00000004
-#define ISTAT_RECV 0x00000002
-#define ISTAT_BRDY 0x00000001
-
-/* MYRI Registers */
-#define MYRI_RESETOFF 0x00UL
-#define MYRI_RESETON 0x04UL
-#define MYRI_IRQOFF 0x08UL
-#define MYRI_IRQON 0x0cUL
-#define MYRI_WAKEUPOFF 0x10UL
-#define MYRI_WAKEUPON 0x14UL
-#define MYRI_IRQREAD 0x18UL
- /* 0x1c-->0x3ffc, reserved */
-#define MYRI_LOCALMEM 0x4000UL
-#define MYRI_REG_SIZE 0x25000UL
-
-/* Shared memory interrupt mask. */
-#define SHMEM_IMASK_RX 0x00000002
-#define SHMEM_IMASK_TX 0x00000001
-
-/* Just to make things readable. */
-#define KERNEL_CHANNEL 0
-
-/* The size of this must be >= 129 bytes. */
-struct myri_eeprom {
- unsigned int cval;
- unsigned short cpuvers;
- unsigned char id[6];
- unsigned int ramsz;
- unsigned char fvers[32];
- unsigned char mvers[16];
- unsigned short dlval;
- unsigned short brd_type;
- unsigned short bus_type;
- unsigned short prod_code;
- unsigned int serial_num;
- unsigned short _reserved[24];
- unsigned int _unused[2];
-};
-
-/* EEPROM bus types, only SBUS is valid in this driver. */
-#define BUS_TYPE_SBUS 1
-
-/* EEPROM CPU revisions. */
-#define CPUVERS_2_3 0x0203
-#define CPUVERS_3_0 0x0300
-#define CPUVERS_3_1 0x0301
-#define CPUVERS_3_2 0x0302
-#define CPUVERS_4_0 0x0400
-#define CPUVERS_4_1 0x0401
-#define CPUVERS_4_2 0x0402
-#define CPUVERS_5_0 0x0500
-
-/* MYRI Control Registers */
-#define MYRICTRL_CTRL 0x00UL
-#define MYRICTRL_IRQLVL 0x02UL
-#define MYRICTRL_REG_SIZE 0x04UL
-
-/* Global control register defines. */
-#define CONTROL_ROFF 0x8000 /* Reset OFF. */
-#define CONTROL_RON 0x4000 /* Reset ON. */
-#define CONTROL_EIRQ 0x2000 /* Enable IRQ's. */
-#define CONTROL_DIRQ 0x1000 /* Disable IRQ's. */
-#define CONTROL_WON 0x0800 /* Wake-up ON. */
-
-#define MYRI_SCATTER_ENTRIES 8
-#define MYRI_GATHER_ENTRIES 16
-
-struct myri_sglist {
- u32 addr;
- u32 len;
-};
-
-struct myri_rxd {
- struct myri_sglist myri_scatters[MYRI_SCATTER_ENTRIES]; /* DMA scatter list.*/
- u32 csum; /* HW computed checksum. */
- u32 ctx;
- u32 num_sg; /* Total scatter entries. */
-};
-
-struct myri_txd {
- struct myri_sglist myri_gathers[MYRI_GATHER_ENTRIES]; /* DMA scatter list. */
- u32 num_sg; /* Total scatter entries. */
- u16 addr[4]; /* XXX address */
- u32 chan;
- u32 len; /* Total length of packet. */
- u32 csum_off; /* Where data to csum is. */
- u32 csum_field; /* Where csum goes in pkt. */
-};
-
-#define MYRINET_MTU 8432
-#define RX_ALLOC_SIZE 8448
-#define MYRI_PAD_LEN 2
-#define RX_COPY_THRESHOLD 256
-
-/* These numbers are cast in stone, new firmware is needed if
- * you want to change them.
- */
-#define TX_RING_MAXSIZE 16
-#define RX_RING_MAXSIZE 16
-
-#define TX_RING_SIZE 16
-#define RX_RING_SIZE 16
-
-/* GRRR... */
-static __inline__ int NEXT_RX(int num)
-{
- /* XXX >=??? */
- if(++num > RX_RING_SIZE)
- num = 0;
- return num;
-}
-
-static __inline__ int PREV_RX(int num)
-{
- if(--num < 0)
- num = RX_RING_SIZE;
- return num;
-}
-
-#define NEXT_TX(num) (((num) + 1) & (TX_RING_SIZE - 1))
-#define PREV_TX(num) (((num) - 1) & (TX_RING_SIZE - 1))
-
-#define TX_BUFFS_AVAIL(head, tail) \
- ((head) <= (tail) ? \
- (head) + (TX_RING_SIZE - 1) - (tail) : \
- (head) - (tail) - 1)
-
-struct sendq {
- u32 tail;
- u32 head;
- u32 hdebug;
- u32 mdebug;
- struct myri_txd myri_txd[TX_RING_MAXSIZE];
-};
-
-struct recvq {
- u32 head;
- u32 tail;
- u32 hdebug;
- u32 mdebug;
- struct myri_rxd myri_rxd[RX_RING_MAXSIZE + 1];
-};
-
-#define MYRI_MLIST_SIZE 8
-
-struct mclist {
- u32 maxlen;
- u32 len;
- u32 cache;
- struct pair {
- u8 addr[8];
- u32 val;
- } mc_pairs[MYRI_MLIST_SIZE];
- u8 bcast_addr[8];
-};
-
-struct myri_channel {
- u32 state; /* State of the channel. */
- u32 busy; /* Channel is busy. */
- struct sendq sendq; /* Device tx queue. */
- struct recvq recvq; /* Device rx queue. */
- struct recvq recvqa; /* Device rx queue acked. */
- u32 rbytes; /* Receive bytes. */
- u32 sbytes; /* Send bytes. */
- u32 rmsgs; /* Receive messages. */
- u32 smsgs; /* Send messages. */
- struct mclist mclist; /* Device multicast list. */
-};
-
-/* Values for per-channel state. */
-#define STATE_WFH 0 /* Waiting for HOST. */
-#define STATE_WFN 1 /* Waiting for NET. */
-#define STATE_READY 2 /* Ready. */
-
-struct myri_shmem {
- u8 addr[8]; /* Board's address. */
- u32 nchan; /* Number of channels. */
- u32 burst; /* SBUS dma burst enable. */
- u32 shakedown; /* DarkkkkStarrr Crashesss... */
- u32 send; /* Send wanted. */
- u32 imask; /* Interrupt enable mask. */
- u32 mlevel; /* Map level. */
- u32 debug[4]; /* Misc. debug areas. */
- struct myri_channel channel; /* Only one channel on a host. */
-};
-
-struct myri_eth {
- /* These are frequently accessed, keep together
- * to obtain good cache hit rates.
- */
- spinlock_t irq_lock;
- struct myri_shmem __iomem *shmem; /* Shared data structures. */
- void __iomem *cregs; /* Control register space. */
- struct recvq __iomem *rqack; /* Where we ack rx's. */
- struct recvq __iomem *rq; /* Where we put buffers. */
- struct sendq __iomem *sq; /* Where we stuff tx's. */
- struct net_device *dev; /* Linux/NET dev struct. */
- int tx_old; /* To speed up tx cleaning. */
- void __iomem *lregs; /* Quick ptr to LANAI regs. */
- struct sk_buff *rx_skbs[RX_RING_SIZE+1];/* RX skb's */
- struct sk_buff *tx_skbs[TX_RING_SIZE]; /* TX skb's */
-
- /* These are less frequently accessed. */
- void __iomem *regs; /* MyriCOM register space. */
- void __iomem *lanai; /* View 2 of register space. */
- unsigned int myri_bursts; /* SBUS bursts. */
- struct myri_eeprom eeprom; /* Local copy of EEPROM. */
- unsigned int reg_size; /* Size of register space. */
- unsigned int shmem_base; /* Offset to shared ram. */
- struct platform_device *myri_op; /* Our OF device struct. */
-};
-
-/* We use this to acquire receive skb's that we can DMA directly into. */
-#define ALIGNED_RX_SKB_ADDR(addr) \
- ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
-{
- struct sk_buff *skb;
-
- skb = alloc_skb(length + 64, gfp_flags);
- if(skb) {
- int offset = ALIGNED_RX_SKB_ADDR(skb->data);
-
- if(offset)
- skb_reserve(skb, offset);
- }
- return skb;
-}
-
-#endif /* !(_MYRI_SBUS_H) */
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 60f46bc2bf64..2962cc695ce3 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -1382,7 +1382,7 @@ static int find_mii(struct net_device *dev)
/* WCSR bits [0:4] [9:10] */
#define WCSR_RESET_SAVE 0x61f
/* RFCR bits [20] [22] [27:31] */
-#define RFCR_RESET_SAVE 0xf8500000;
+#define RFCR_RESET_SAVE 0xf8500000
static void natsemi_reset(struct net_device *dev)
{
@@ -2920,7 +2920,7 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
/*
* If we're ignoring the PHY then autoneg and the internal
- * transciever are really not going to work so don't let the
+ * transceiver are really not going to work so don't let the
* user select them.
*/
if (np->ignore_phy && (ecmd->autoneg == AUTONEG_ENABLE ||
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index 2e4b42175f3f..2dfee892d200 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -18,6 +18,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 77220687b92a..f744d291218a 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/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 75
-#define NETXEN_NIC_LINUX_VERSIONID "4.0.75"
+#define _NETXEN_NIC_LINUX_SUBVERSION 76
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.76"
#define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
#define _major(v) (((v) >> 24) & 0xff)
@@ -1302,6 +1302,7 @@ int netxen_nic_wol_supported(struct netxen_adapter *adapter);
int netxen_init_dummy_dma(struct netxen_adapter *adapter);
void netxen_free_dummy_dma(struct netxen_adapter *adapter);
+int netxen_check_flash_fw_compatibility(struct netxen_adapter *adapter);
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
int netxen_load_firmware(struct netxen_adapter *adapter);
int netxen_need_fw_reset(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index f16966afa64e..a925392abd6f 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -163,7 +163,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
rq_size, &hostrq_phys_addr);
if (addr == NULL)
return -ENOMEM;
- prq = (nx_hostrq_rx_ctx_t *)addr;
+ prq = addr;
addr = pci_alloc_consistent(adapter->pdev,
rsp_size, &cardrsp_phys_addr);
@@ -171,7 +171,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
err = -ENOMEM;
goto out_free_rq;
}
- prsp = (nx_cardrsp_rx_ctx_t *)addr;
+ prsp = addr;
prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
@@ -318,10 +318,10 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
}
memset(rq_addr, 0, rq_size);
- prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+ prq = rq_addr;
memset(rsp_addr, 0, rsp_size);
- prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+ prsp = rsp_addr;
prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
@@ -629,7 +629,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
}
memset(addr, 0, sizeof(struct netxen_ring_ctx));
- recv_ctx->hwctx = (struct netxen_ring_ctx *)addr;
+ recv_ctx->hwctx = addr;
recv_ctx->hwctx->ctx_id = cpu_to_le32(port);
recv_ctx->hwctx->cmd_consumer_offset =
cpu_to_le64(recv_ctx->phys_addr +
@@ -648,7 +648,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
goto err_out_free;
}
- tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
+ tx_ring->desc_head = addr;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
@@ -662,7 +662,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
err = -ENOMEM;
goto err_out_free;
}
- rds_ring->desc_head = (struct rcv_desc *)addr;
+ rds_ring->desc_head = addr;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
rds_ring->crb_rcv_producer =
@@ -683,7 +683,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
err = -ENOMEM;
goto err_out_free;
}
- sds_ring->desc_head = (struct status_desc *)addr;
+ sds_ring->desc_head = addr;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
sds_ring->crb_sts_consumer =
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 5cef718fe35f..3f89e57cae50 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -809,6 +809,9 @@ int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable)
u64 word;
int rv = 0;
+ if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
+ return 0;
+
memset(&req, 0, sizeof(nx_nic_req_t));
req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
@@ -959,6 +962,9 @@ int netxen_send_lro_cleanup(struct netxen_adapter *adapter)
u64 word;
int rv;
+ if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
+ return 0;
+
memset(&req, 0, sizeof(nx_nic_req_t));
req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 7f999671c7b2..e8993a76a080 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -964,6 +964,35 @@ netxen_need_fw_reset(struct netxen_adapter *adapter)
return 0;
}
+#define NETXEN_MIN_P3_FW_SUPP NETXEN_VERSION_CODE(4, 0, 505)
+
+int
+netxen_check_flash_fw_compatibility(struct netxen_adapter *adapter)
+{
+ u32 flash_fw_ver, min_fw_ver;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return 0;
+
+ if (netxen_rom_fast_read(adapter,
+ NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) {
+ dev_err(&adapter->pdev->dev, "Unable to read flash fw"
+ "version\n");
+ return -EIO;
+ }
+
+ flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver);
+ min_fw_ver = NETXEN_MIN_P3_FW_SUPP;
+ if (flash_fw_ver >= min_fw_ver)
+ return 0;
+
+ dev_info(&adapter->pdev->dev, "Flash fw[%d.%d.%d] is < min fw supported"
+ "[4.0.505]. Please update firmware on flash\n",
+ _major(flash_fw_ver), _minor(flash_fw_ver),
+ _build(flash_fw_ver));
+ return -EINVAL;
+}
+
static char *fw_name[] = {
NX_P2_MN_ROMIMAGE_NAME,
NX_P3_CT_ROMIMAGE_NAME,
@@ -1071,10 +1100,12 @@ static int
netxen_validate_firmware(struct netxen_adapter *adapter)
{
__le32 val;
- u32 ver, min_ver, bios;
+ __le32 flash_fw_ver;
+ u32 file_fw_ver, min_ver, bios;
struct pci_dev *pdev = adapter->pdev;
const struct firmware *fw = adapter->fw;
u8 fw_type = adapter->fw_type;
+ u32 crbinit_fix_fw;
if (fw_type == NX_UNIFIED_ROMIMAGE) {
if (netxen_nic_validate_unified_romimage(adapter))
@@ -1091,16 +1122,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
val = nx_get_fw_version(adapter);
if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
- min_ver = NETXEN_VERSION_CODE(4, 0, 216);
+ min_ver = NETXEN_MIN_P3_FW_SUPP;
else
min_ver = NETXEN_VERSION_CODE(3, 4, 216);
- ver = NETXEN_DECODE_VERSION(val);
+ file_fw_ver = NETXEN_DECODE_VERSION(val);
- if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+ if ((_major(file_fw_ver) > _NETXEN_NIC_LINUX_MAJOR) ||
+ (file_fw_ver < min_ver)) {
dev_err(&pdev->dev,
"%s: firmware version %d.%d.%d unsupported\n",
- fw_name[fw_type], _major(ver), _minor(ver), _build(ver));
+ fw_name[fw_type], _major(file_fw_ver), _minor(file_fw_ver),
+ _build(file_fw_ver));
return -EINVAL;
}
@@ -1112,17 +1145,34 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
return -EINVAL;
}
- /* check if flashed firmware is newer */
if (netxen_rom_fast_read(adapter,
- NX_FW_VERSION_OFFSET, (int *)&val))
+ NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) {
+ dev_err(&pdev->dev, "Unable to read flash fw version\n");
return -EIO;
- val = NETXEN_DECODE_VERSION(val);
- if (val > ver) {
- dev_info(&pdev->dev, "%s: firmware is older than flash\n",
- fw_name[fw_type]);
+ }
+ flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver);
+
+ /* New fw from file is not allowed, if fw on flash is < 4.0.554 */
+ crbinit_fix_fw = NETXEN_VERSION_CODE(4, 0, 554);
+ if (file_fw_ver >= crbinit_fix_fw && flash_fw_ver < crbinit_fix_fw &&
+ NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ dev_err(&pdev->dev, "Incompatibility detected between driver "
+ "and firmware version on flash. This configuration "
+ "is not recommended. Please update the firmware on "
+ "flash immediately\n");
return -EINVAL;
}
+ /* check if flashed firmware is newer only for no-mn and P2 case*/
+ if (!netxen_p3_has_mn(adapter) ||
+ NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ if (flash_fw_ver > file_fw_ver) {
+ dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+ fw_name[fw_type]);
+ return -EINVAL;
+ }
+ }
+
NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
return 0;
}
@@ -1279,7 +1329,7 @@ void netxen_free_dummy_dma(struct netxen_adapter *adapter)
if (--i == 0)
break;
- };
+ }
}
if (i) {
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index c0788a31ff0f..f574edff7fcb 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -92,7 +92,8 @@ 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 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+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);
/* PCI Device ID Table */
@@ -520,7 +521,7 @@ static const struct net_device_ops netxen_netdev_ops = {
.ndo_open = netxen_nic_open,
.ndo_stop = netxen_nic_close,
.ndo_start_xmit = netxen_nic_xmit_frame,
- .ndo_get_stats = netxen_nic_get_stats,
+ .ndo_get_stats64 = netxen_nic_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = netxen_set_multicast_list,
.ndo_set_mac_address = netxen_nic_set_mac,
@@ -1387,6 +1388,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
+ err = netxen_check_flash_fw_compatibility(adapter);
+ if (err)
+ goto err_out_iounmap;
+
if (adapter->portnum == 0) {
val = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
if (val != 0xffffffff && val != 0) {
@@ -2110,10 +2115,10 @@ request_reset:
clear_bit(__NX_RESETTING, &adapter->state);
}
-static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
- struct net_device_stats *stats = &netdev->stats;
stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
stats->tx_packets = adapter->stats.xmitfinished;
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index cc25bff0bd3b..cd6c2317e29e 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/netdevice.h>
@@ -6248,9 +6249,10 @@ static void niu_sync_mac_stats(struct niu *np)
niu_sync_bmac_stats(np);
}
-static void niu_get_rx_stats(struct niu *np)
+static void niu_get_rx_stats(struct niu *np,
+ struct rtnl_link_stats64 *stats)
{
- unsigned long pkts, dropped, errors, bytes;
+ u64 pkts, dropped, errors, bytes;
struct rx_ring_info *rx_rings;
int i;
@@ -6272,15 +6274,16 @@ static void niu_get_rx_stats(struct niu *np)
}
no_rings:
- np->dev->stats.rx_packets = pkts;
- np->dev->stats.rx_bytes = bytes;
- np->dev->stats.rx_dropped = dropped;
- np->dev->stats.rx_errors = errors;
+ stats->rx_packets = pkts;
+ stats->rx_bytes = bytes;
+ stats->rx_dropped = dropped;
+ stats->rx_errors = errors;
}
-static void niu_get_tx_stats(struct niu *np)
+static void niu_get_tx_stats(struct niu *np,
+ struct rtnl_link_stats64 *stats)
{
- unsigned long pkts, errors, bytes;
+ u64 pkts, errors, bytes;
struct tx_ring_info *tx_rings;
int i;
@@ -6299,20 +6302,22 @@ static void niu_get_tx_stats(struct niu *np)
}
no_rings:
- np->dev->stats.tx_packets = pkts;
- np->dev->stats.tx_bytes = bytes;
- np->dev->stats.tx_errors = errors;
+ stats->tx_packets = pkts;
+ stats->tx_bytes = bytes;
+ stats->tx_errors = errors;
}
-static struct net_device_stats *niu_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *niu_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
{
struct niu *np = netdev_priv(dev);
if (netif_running(dev)) {
- niu_get_rx_stats(np);
- niu_get_tx_stats(np);
+ niu_get_rx_stats(np, stats);
+ niu_get_tx_stats(np, stats);
}
- return &dev->stats;
+
+ return stats;
}
static void niu_load_hash_xmac(struct niu *np, u16 *hash)
@@ -9710,7 +9715,7 @@ static const struct net_device_ops niu_netdev_ops = {
.ndo_open = niu_open,
.ndo_stop = niu_close,
.ndo_start_xmit = niu_start_xmit,
- .ndo_get_stats = niu_get_stats,
+ .ndo_get_stats64 = niu_get_stats,
.ndo_set_multicast_list = niu_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = niu_set_mac_addr,
@@ -9792,7 +9797,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
goto err_out_disable_pdev;
}
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
if (pos <= 0) {
dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n");
goto err_out_free_res;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 3e4040f2f3cb..e736aec588fc 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -106,6 +106,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ip.h> /* for iph */
#include <linux/in.h> /* for IPPROTO_... */
#include <linux/compiler.h>
@@ -429,10 +430,6 @@ struct ns83820 {
struct pci_dev *pci_dev;
struct net_device *ndev;
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
- struct vlan_group *vlgrp;
-#endif
-
struct rx_info rx_info;
struct tasklet_struct rx_tasklet;
@@ -493,22 +490,6 @@ static inline void kick_rx(struct net_device *ndev)
#define start_tx_okay(dev) \
(((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE)
-
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
-static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
-{
- struct ns83820 *dev = PRIV(ndev);
-
- spin_lock_irq(&dev->misc_lock);
- spin_lock(&dev->tx_lock);
-
- dev->vlgrp = grp;
-
- spin_unlock(&dev->tx_lock);
- spin_unlock_irq(&dev->misc_lock);
-}
-#endif
-
/* Packet Receiver
*
* The hardware supports linked lists of receive descriptors for
@@ -929,14 +910,12 @@ static void rx_irq(struct net_device *ndev)
#ifdef NS83820_VLAN_ACCEL_SUPPORT
if(extsts & EXTSTS_VPKT) {
unsigned short tag;
+
tag = ntohs(extsts & EXTSTS_VTG_MASK);
- rx_rc = vlan_hwaccel_rx(skb,dev->vlgrp,tag);
- } else {
- rx_rc = netif_rx(skb);
+ __vlan_hwaccel_put_tag(skb, tag);
}
-#else
- rx_rc = netif_rx(skb);
#endif
+ rx_rc = netif_rx(skb);
if (NET_RX_DROP == rx_rc) {
netdev_mangle_me_harder_failed:
ndev->stats.rx_dropped++;
@@ -1960,11 +1939,8 @@ static const struct net_device_ops netdev_ops = {
.ndo_change_mtu = ns83820_change_mtu,
.ndo_set_multicast_list = ns83820_set_multicast,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = ns83820_tx_timeout,
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
- .ndo_vlan_rx_register = ns83820_vlan_rx_register,
-#endif
};
static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
index b264f0f45605..429e08c84e9b 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -9,6 +9,7 @@
#include <linux/capability.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index b48aba9e4227..8b3090dc4bcd 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -2570,7 +2570,6 @@ static void pcnet32_load_multicast(struct net_device *dev)
volatile __le16 *mcast_table = (__le16 *)ib->filter;
struct netdev_hw_addr *ha;
unsigned long ioaddr = dev->base_addr;
- char *addrs;
int i;
u32 crc;
@@ -2590,13 +2589,7 @@ static void pcnet32_load_multicast(struct net_device *dev)
/* Add addresses */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- /* multicast address? */
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc = crc >> 26;
mcast_table[crc >> 4] |= cpu_to_le16(1 << (crc & 0xf));
}
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 9a09e24c30bc..d4cbc2922b23 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -109,11 +109,7 @@ static int ip1001_config_init(struct phy_device *phydev)
value = phy_read(phydev, 16);
value |= 0x3;
- err = phy_write(phydev, 16, value);
- if (err < 0)
- return err;
-
- return err;
+ return phy_write(phydev, 16, value);
}
static int ip175c_read_status(struct phy_device *phydev)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index a47595760751..3cbda0851f83 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -33,7 +33,7 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index ca4df7f4cf21..a9e9ca8a86ed 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -152,7 +152,7 @@ static int plip_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
const void *saddr, unsigned len);
static int plip_hard_header_cache(const struct neighbour *neigh,
- struct hh_cache *hh);
+ struct hh_cache *hh, __be16 type);
static int plip_open(struct net_device *dev);
static int plip_close(struct net_device *dev);
static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
@@ -1026,11 +1026,11 @@ plip_hard_header(struct sk_buff *skb, struct net_device *dev,
}
static int plip_hard_header_cache(const struct neighbour *neigh,
- struct hh_cache *hh)
+ struct hh_cache *hh, __be16 type)
{
int ret;
- ret = eth_header_cache(neigh, hh);
+ ret = eth_header_cache(neigh, hh, type);
if (ret == 0) {
struct ethhdr *eth;
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index c554a397e558..c6ba64380829 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -30,6 +30,7 @@
#include <linux/ppp_channel.h>
#include <linux/spinlock.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 4609bc0e2f56..10e5d985afa3 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -48,7 +48,7 @@
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <net/slhc_vj.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/nsproxy.h>
#include <net/net_namespace.h>
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 2573f525f11c..736a39ee05bb 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -44,6 +44,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
index 1286fe212dc4..eae542a7e987 100644
--- a/drivers/net/pptp.c
+++ b/drivers/net/pptp.c
@@ -30,7 +30,6 @@
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
-#include <linux/version.h>
#include <linux/rcupdate.h>
#include <linux/spinlock.h>
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index b1f251da1535..d82a82d9870c 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -28,6 +28,7 @@
#undef DEBUG
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -837,9 +838,11 @@ static int gelic_card_kick_txdma(struct gelic_card *card,
card->tx_dma_progress = 1;
status = lv1_net_start_tx_dma(bus_id(card), dev_id(card),
descr->bus_addr, 0);
- if (status)
+ if (status) {
+ card->tx_dma_progress = 0;
dev_info(ctodev(card), "lv1_net_start_txdma failed," \
"status=%d\n", status);
+ }
}
return status;
}
@@ -875,7 +878,7 @@ int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
result = gelic_descr_prepare_tx(card, descr, skb);
if (result) {
/*
- * DMA map failed. As chanses are that failure
+ * DMA map failed. As chances are that failure
* would continue, just release skb and return
*/
netdev->stats.tx_dropped++;
@@ -896,12 +899,16 @@ int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
if (gelic_card_kick_txdma(card, descr)) {
/*
* kick failed.
- * release descriptors which were just prepared
+ * release descriptor which was just prepared
*/
netdev->stats.tx_dropped++;
+ /* don't trigger BUG_ON() in gelic_descr_release_tx */
+ descr->data_status = cpu_to_be32(GELIC_DESCR_TX_TAIL);
gelic_descr_release_tx(card, descr);
- gelic_descr_release_tx(card, descr->next);
- card->tx_chain.tail = descr->next->next;
+ /* reset head */
+ card->tx_chain.head = descr;
+ /* reset hw termination */
+ descr->prev->next_descr_addr = 0;
dev_info(ctodev(card), "%s: kick failure\n", __func__);
}
@@ -986,10 +993,6 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
int dmac_chain_ended;
status = gelic_descr_get_status(descr);
- /* is this descriptor terminated with next_descr == NULL? */
- dmac_chain_ended =
- be32_to_cpu(descr->dmac_cmd_status) &
- GELIC_DESCR_RX_DMA_CHAIN_END;
if (status == GELIC_DESCR_DMA_CARDOWNED)
return 0;
@@ -1009,7 +1012,7 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
netdev = card->netdev[i];
break;
}
- };
+ }
if (GELIC_PORT_MAX <= i) {
pr_info("%s: unknown packet vid=%x\n", __func__, vid);
goto refill;
@@ -1040,7 +1043,7 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
goto refill;
}
/*
- * descriptoers any other than FRAME_END here should
+ * descriptors any other than FRAME_END here should
* be treated as error.
*/
if (status != GELIC_DESCR_DMA_FRAME_END) {
@@ -1052,6 +1055,11 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
/* ok, we've got a packet in descr */
gelic_net_pass_skb_up(descr, card, netdev);
refill:
+
+ /* is the current descriptor terminated with next_descr == NULL? */
+ dmac_chain_ended =
+ be32_to_cpu(descr->dmac_cmd_status) &
+ GELIC_DESCR_RX_DMA_CHAIN_END;
/*
* So that always DMAC can see the end
* of the descriptor chain to avoid
@@ -1080,10 +1088,9 @@ refill:
* If dmac chain was met, DMAC stopped.
* thus re-enable it
*/
- if (dmac_chain_ended) {
- card->rx_dma_restart_required = 1;
- dev_dbg(ctodev(card), "reenable rx dma scheduled\n");
- }
+
+ if (dmac_chain_ended)
+ gelic_card_enable_rxdmac(card);
return 1;
}
@@ -1149,11 +1156,6 @@ static irqreturn_t gelic_card_interrupt(int irq, void *ptr)
status &= card->irq_mask;
- if (card->rx_dma_restart_required) {
- card->rx_dma_restart_required = 0;
- gelic_card_enable_rxdmac(card);
- }
-
if (status & GELIC_CARD_RXINT) {
gelic_card_rx_irq_off(card);
napi_schedule(&card->napi);
@@ -1199,7 +1201,7 @@ void gelic_net_poll_controller(struct net_device *netdev)
#endif /* CONFIG_NET_POLL_CONTROLLER */
/**
- * gelic_net_open - called upon ifonfig up
+ * gelic_net_open - called upon ifconfig up
* @netdev: interface device structure
*
* returns 0 on success, <0 on failure
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
index d9a55b93898b..d3fadfbc3bcc 100644
--- a/drivers/net/ps3_gelic_net.h
+++ b/drivers/net/ps3_gelic_net.h
@@ -289,7 +289,6 @@ struct gelic_card {
struct gelic_descr_chain tx_chain;
struct gelic_descr_chain rx_chain;
- int rx_dma_restart_required;
/*
* tx_lock guards tx descriptor list and
* tx_dma_progress.
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
index 5f597ca592bb..1a3033d8e7ed 100644
--- a/drivers/net/pxa168_eth.c
+++ b/drivers/net/pxa168_eth.c
@@ -502,7 +502,7 @@ static int add_del_hash_entry(struct pxa168_eth_private *pep,
* Pick the appropriate table, start scanning for free/reusable
* entries at the index obtained by hashing the specified MAC address
*/
- start = (struct addr_table_entry *)(pep->htpr);
+ start = pep->htpr;
entry = start + hash_function(mac_addr);
for (i = 0; i < HOP_NUMBER; i++) {
if (!(le32_to_cpu(entry->lo) & HASH_ENTRY_VALID)) {
@@ -1267,6 +1267,9 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
pep->tx_skb[tx_index] = skb;
desc->byte_cnt = length;
desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+
+ skb_tx_timestamp(skb);
+
wmb();
desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC |
TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT;
@@ -1502,7 +1505,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
err = -ENODEV;
goto err_netdev;
}
- pep->base = ioremap(res->start, res->end - res->start + 1);
+ pep->base = ioremap(res->start, resource_size(res));
if (pep->base == NULL) {
err = -ENOMEM;
goto err_netdev;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 771bb614ccc9..2f6914025efc 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2873,7 +2873,7 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
PAGE_SIZE, &qdev->shadow_reg_phy_addr);
if (qdev->shadow_reg_virt_addr != NULL) {
- qdev->preq_consumer_index = (u16 *) qdev->shadow_reg_virt_addr;
+ qdev->preq_consumer_index = qdev->shadow_reg_virt_addr;
qdev->req_consumer_index_phy_addr_high =
MS_64BITS(qdev->shadow_reg_phy_addr);
qdev->req_consumer_index_phy_addr_low =
@@ -3114,8 +3114,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
qdev->small_buf_release_cnt = 8;
qdev->lrg_buf_q_producer_index = qdev->num_lbufq_entries - 1;
qdev->lrg_buf_release_cnt = 8;
- qdev->lrg_buf_next_free =
- (struct bufq_addr_element *)qdev->lrg_buf_q_virt_addr;
+ qdev->lrg_buf_next_free = qdev->lrg_buf_q_virt_addr;
qdev->small_buf_index = 0;
qdev->lrg_buf_index = 0;
qdev->lrg_buf_free_count = 0;
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 480ef5cb6ef9..baf646d98fa0 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 18
-#define QLCNIC_LINUX_VERSIONID "5.0.18"
+#define _QLCNIC_LINUX_SUBVERSION 21
+#define QLCNIC_LINUX_VERSIONID "5.0.21"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -429,6 +429,7 @@ struct qlcnic_dump_template_hdr {
struct qlcnic_fw_dump {
u8 clr; /* flag to indicate if dump is cleared */
+ u8 enable; /* enable/disable dump */
u32 size; /* total size of the dump */
void *data; /* dump data area */
struct qlcnic_dump_template_hdr *tmpl_hdr;
@@ -450,6 +451,7 @@ struct qlcnic_hardware_context {
u8 revision_id;
u8 pci_func;
u8 linkup;
+ u8 loopback_state;
u16 port_type;
u16 board_type;
@@ -779,6 +781,14 @@ struct qlcnic_mac_list_s {
#define QLCNIC_IP_UP 2
#define QLCNIC_IP_DOWN 3
+#define QLCNIC_ILB_MODE 0x1
+#define QLCNIC_ELB_MODE 0x2
+
+#define QLCNIC_LINKEVENT 0x1
+#define QLCNIC_LB_RESPONSE 0x2
+#define QLCNIC_IS_LB_CONFIGURED(VAL) \
+ (VAL == (QLCNIC_LINKEVENT | QLCNIC_LB_RESPONSE))
+
/*
* Driver --> Firmware
*/
@@ -788,13 +798,17 @@ struct qlcnic_mac_list_s {
#define QLCNIC_H2C_OPCODE_LRO_REQUEST 0x7
#define QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE 0xc
#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 0x12
+
#define QLCNIC_H2C_OPCODE_GET_LINKEVENT 0x15
#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING 0x17
#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO 0x18
+#define QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK 0x13
+
/*
* Firmware --> Driver
*/
+#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f
#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141
#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */
@@ -808,6 +822,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAPABILITY_BDG BIT_8
#define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9
#define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10
+#define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27
/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1
@@ -895,11 +910,11 @@ struct qlcnic_ipaddr {
#define QLCNIC_MAC_OVERRIDE_DISABLED 0x400
#define QLCNIC_PROMISC_DISABLED 0x800
#define QLCNIC_NEED_FLR 0x1000
+#define QLCNIC_FW_RESET_OWNER 0x2000
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
#define QLCNIC_DEF_NUM_STS_DESC_RINGS 4
-#define QLCNIC_MIN_NUM_RSS_RINGS 2
#define QLCNIC_MSIX_TBL_SPACE 8192
#define QLCNIC_PCI_REG_MSIX_TBL 0x44
#define QLCNIC_MSIX_TBL_PGSIZE 4096
@@ -922,6 +937,12 @@ struct qlcnic_ipaddr {
#define QLCNIC_READD_AGE 20
#define QLCNIC_LB_MAX_FILTERS 64
+/* QLCNIC Driver Error Code */
+#define QLCNIC_FW_NOT_RESPOND 51
+#define QLCNIC_TEST_IN_PROGRESS 52
+#define QLCNIC_UNDEFINED_ERROR 53
+#define QLCNIC_LB_CABLE_NOT_CONN 54
+
struct qlcnic_filter {
struct hlist_node fnode;
u8 faddr[ETH_ALEN];
@@ -993,7 +1014,7 @@ struct qlcnic_adapter {
u8 max_mac_filters;
u8 dev_state;
u8 diag_test;
- u8 diag_cnt;
+ char diag_cnt;
u8 reset_ack_timeo;
u8 dev_init_timeo;
u16 msg_enable;
@@ -1001,6 +1022,7 @@ struct qlcnic_adapter {
u8 mac_addr[ETH_ALEN];
u64 dev_rst_time;
+ u8 mac_learn;
unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct qlcnic_npar_info *npars;
@@ -1219,8 +1241,7 @@ struct __ctrl {
struct __cache {
__le32 addr;
- u8 stride;
- u8 rsvd;
+ __le16 stride;
__le16 init_tag_val;
__le32 size;
__le32 no_ops;
@@ -1318,9 +1339,11 @@ enum op_codes {
#define QLCNIC_DUMP_SKIP BIT_7
#define QLCNIC_DUMP_MASK_MIN 3
-#define QLCNIC_DUMP_MASK_DEF 0x0f
+#define QLCNIC_DUMP_MASK_DEF 0x1f
#define QLCNIC_DUMP_MASK_MAX 0xff
#define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed
+#define QLCNIC_ENABLE_FW_DUMP 0xaddfeed
+#define QLCNIC_DISABLE_FW_DUMP 0xbadfeed
struct qlcnic_dump_operations {
enum op_codes opcode;
@@ -1428,6 +1451,12 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring);
void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
+void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
+int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
+
+/* Functions from qlcnic_ethtool.c */
+int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
/* Functions from qlcnic_main.c */
int qlcnic_reset_context(struct qlcnic_adapter *);
@@ -1439,6 +1468,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val);
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data);
void qlcnic_dev_request_reset(struct qlcnic_adapter *);
+void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
@@ -1489,6 +1519,8 @@ static const struct qlcnic_brdinfo qlcnic_boards[] = {
"NC523SFP 10Gb 2-port Server Adapter"},
{0x1077, 0x8020, 0x103c, 0x3346,
"CN1000Q Dual Port Converged Network Adapter"},
+ {0x1077, 0x8020, 0x1077, 0x210,
+ "QME8242-k 10GbE Dual Port Mezzanine Card"},
{0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
};
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index bab041a5c758..b0d32ddd2ccb 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -95,8 +95,8 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
QLCNIC_CDRP_CMD_TEMP_SIZE);
if (err != QLCNIC_RCODE_SUCCESS) {
err = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
- dev_err(&adapter->pdev->dev,
- "Failed to get template size %d\n", err);
+ dev_info(&adapter->pdev->dev,
+ "Can't get template size %d\n", err);
err = -EIO;
return err;
}
@@ -126,7 +126,7 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
err = -EIO;
goto error;
}
- tmp_tmpl = (struct qlcnic_dump_template_hdr *) tmp_addr;
+ tmp_tmpl = tmp_addr;
csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size);
if (csum) {
dev_err(&adapter->pdev->dev,
@@ -139,17 +139,14 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
err = -EIO;
goto error;
}
- tmp_buf = (u32 *) tmp_addr;
+ tmp_buf = tmp_addr;
template = (u32 *) ahw->fw_dump.tmpl_hdr;
for (i = 0; i < temp_size/sizeof(u32); i++)
*template++ = __le32_to_cpu(*tmp_buf++);
tmpl_hdr = ahw->fw_dump.tmpl_hdr;
- if (tmpl_hdr->cap_mask > QLCNIC_DUMP_MASK_DEF &&
- tmpl_hdr->cap_mask <= QLCNIC_DUMP_MASK_MAX)
- tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask;
- else
- tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
+ tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
+ ahw->fw_dump.enable = 1;
error:
dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t);
return err;
@@ -214,7 +211,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
&hostrq_phys_addr, GFP_KERNEL);
if (addr == NULL)
return -ENOMEM;
- prq = (struct qlcnic_hostrq_rx_ctx *)addr;
+ prq = addr;
addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
&cardrsp_phys_addr, GFP_KERNEL);
@@ -222,7 +219,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
err = -ENOMEM;
goto out_free_rq;
}
- prsp = (struct qlcnic_cardrsp_rx_ctx *)addr;
+ prsp = addr;
prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
@@ -380,10 +377,10 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
}
memset(rq_addr, 0, rq_size);
- prq = (struct qlcnic_hostrq_tx_ctx *)rq_addr;
+ prq = rq_addr;
memset(rsp_addr, 0, rsp_size);
- prsp = (struct qlcnic_cardrsp_tx_ctx *)rsp_addr;
+ prsp = rsp_addr;
prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
@@ -493,7 +490,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
goto err_out_free;
}
- tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
+ tx_ring->desc_head = addr;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
@@ -506,7 +503,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
err = -ENOMEM;
goto err_out_free;
}
- rds_ring->desc_head = (struct rcv_desc *)addr;
+ rds_ring->desc_head = addr;
}
@@ -522,7 +519,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
err = -ENOMEM;
goto err_out_free;
}
- sds_ring->desc_head = (struct status_desc *)addr;
+ sds_ring->desc_head = addr;
}
return 0;
@@ -662,7 +659,7 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
return -ENOMEM;
memset(nic_info_addr, 0, nic_size);
- nic_info = (struct qlcnic_info *) nic_info_addr;
+ nic_info = nic_info_addr;
err = qlcnic_issue_cmd(adapter,
adapter->ahw->pci_func,
adapter->fw_hal_version,
@@ -720,7 +717,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
return -ENOMEM;
memset(nic_info_addr, 0, nic_size);
- nic_info = (struct qlcnic_info *)nic_info_addr;
+ nic_info = nic_info_addr;
nic_info->pci_func = cpu_to_le16(nic->pci_func);
nic_info->op_mode = cpu_to_le16(nic->op_mode);
@@ -769,7 +766,7 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
return -ENOMEM;
memset(pci_info_addr, 0, pci_size);
- npar = (struct qlcnic_pci_info *) pci_info_addr;
+ npar = pci_info_addr;
err = qlcnic_issue_cmd(adapter,
adapter->ahw->pci_func,
adapter->fw_hal_version,
@@ -877,7 +874,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
if (!err) {
- stats = (struct __qlcnic_esw_statistics *)stats_addr;
+ stats = stats_addr;
esw_stats->context_id = le16_to_cpu(stats->context_id);
esw_stats->version = le16_to_cpu(stats->version);
esw_stats->size = le16_to_cpu(stats->size);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 9efc690a289f..72a723d5c988 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -84,7 +84,9 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_on_offline",
"Link_Test_on_offline",
- "Interrupt_Test_offline"
+ "Interrupt_Test_offline",
+ "Internal_Loopback_offline",
+ "External_Loopback_offline"
};
#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
@@ -685,6 +687,129 @@ clear_it:
return ret;
}
+#define QLCNIC_ILB_PKT_SIZE 64
+#define QLCNIC_NUM_ILB_PKT 16
+#define QLCNIC_ILB_MAX_RCV_LOOP 10
+
+static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
+{
+ unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
+
+ memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
+
+ memcpy(data, mac, ETH_ALEN);
+ memcpy(data + ETH_ALEN, mac, ETH_ALEN);
+
+ memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
+}
+
+int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
+{
+ unsigned char buff[QLCNIC_ILB_PKT_SIZE];
+ qlcnic_create_loopback_buff(buff, mac);
+ return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
+}
+
+static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
+ struct sk_buff *skb;
+ int i, loop, cnt = 0;
+
+ for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
+ skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE);
+ qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
+ skb_put(skb, QLCNIC_ILB_PKT_SIZE);
+
+ adapter->diag_cnt = 0;
+ qlcnic_xmit_frame(skb, adapter->netdev);
+
+ loop = 0;
+ do {
+ msleep(1);
+ qlcnic_process_rcv_ring_diag(sds_ring);
+ if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
+ break;
+ } while (!adapter->diag_cnt);
+
+ dev_kfree_skb_any(skb);
+
+ if (!adapter->diag_cnt)
+ dev_warn(&adapter->pdev->dev, "LB Test: %dth packet"
+ " not recevied\n", i + 1);
+ else
+ cnt++;
+ }
+ if (cnt != i) {
+ dev_warn(&adapter->pdev->dev, "LB Test failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ int max_sds_rings = adapter->max_sds_rings;
+ struct qlcnic_host_sds_ring *sds_ring;
+ int loop = 0;
+ int ret;
+
+ if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
+ netdev_info(netdev, "Firmware is not loopback test capable\n");
+ return -EOPNOTSUPP;
+ }
+
+ netdev_info(netdev, "%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 "
+ "privilege function\n");
+ return 0;
+ }
+
+ if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+ return -EBUSY;
+
+ ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
+ if (ret)
+ goto clear_it;
+
+ sds_ring = &adapter->recv_ctx->sds_rings[0];
+
+ ret = qlcnic_set_lb_mode(adapter, mode);
+ if (ret)
+ goto free_res;
+
+ adapter->diag_cnt = 0;
+ do {
+ msleep(500);
+ qlcnic_process_rcv_ring_diag(sds_ring);
+ if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
+ netdev_info(netdev, "firmware didnt respond to loopback"
+ " configure request\n");
+ ret = -QLCNIC_FW_NOT_RESPOND;
+ goto free_res;
+ } else if (adapter->diag_cnt) {
+ ret = adapter->diag_cnt;
+ goto free_res;
+ }
+ } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
+
+ ret = qlcnic_do_lb_test(adapter);
+
+ qlcnic_clear_lb_mode(adapter);
+
+ free_res:
+ qlcnic_diag_free_res(netdev, max_sds_rings);
+
+ clear_it:
+ adapter->max_sds_rings = max_sds_rings;
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ return ret;
+}
+
static void
qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
u64 *data)
@@ -704,7 +829,16 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
if (data[2])
eth_test->flags |= ETH_TEST_FL_FAILED;
+ 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])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+ eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
+ }
}
}
@@ -986,8 +1120,6 @@ qlcnic_get_dump_data(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;
- if (qlcnic_api_lock(adapter))
- return -EIO;
if (!fw_dump->clr) {
netdev_info(netdev, "Dump not available\n");
qlcnic_api_unlock(adapter);
@@ -996,7 +1128,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
/* Copy template header first */
copy_sz = fw_dump->tmpl_hdr->size;
hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
- data = (u32 *) buffer;
+ data = buffer;
for (i = 0; i < copy_sz/sizeof(u32); i++)
*data++ = cpu_to_le32(*hdr_ptr++);
@@ -1009,7 +1141,6 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
vfree(fw_dump->data);
fw_dump->data = NULL;
fw_dump->clr = 0;
- qlcnic_api_unlock(adapter);
return 0;
}
@@ -1022,8 +1153,27 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) {
+ if (!fw_dump->enable) {
+ netdev_info(netdev, "FW dump not enabled\n");
+ return ret;
+ }
+ if (fw_dump->clr) {
+ dev_info(&adapter->pdev->dev,
+ "Previous dump not cleared, not forcing dump\n");
+ return ret;
+ }
netdev_info(netdev, "Forcing a FW dump\n");
qlcnic_dev_request_reset(adapter);
+ } else if (val->flag == 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) {
+ if (!fw_dump->enable && fw_dump->tmpl_hdr) {
+ netdev_info(netdev, "Enabling FW dump\n");
+ fw_dump->enable = 1;
+ }
} else {
if (val->flag > QLCNIC_DUMP_MASK_MAX ||
val->flag < QLCNIC_DUMP_MASK_MIN) {
@@ -1032,10 +1182,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
ret = -EINVAL;
goto out;
}
- if (qlcnic_api_lock(adapter))
- return -EIO;
fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff;
- qlcnic_api_unlock(adapter);
netdev_info(netdev, "Driver mask changed to: 0x%x\n",
fw_dump->tmpl_hdr->drv_cap_mask);
}
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index a5d9fbf9d816..4055c218ef2a 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -446,6 +446,13 @@ void qlcnic_set_multi(struct net_device *netdev)
}
send_fw_cmd:
+ if (mode == VPORT_MISS_MODE_ACCEPT_ALL) {
+ qlcnic_alloc_lb_filters_mem(adapter);
+ adapter->mac_learn = 1;
+ } else {
+ adapter->mac_learn = 0;
+ }
+
qlcnic_nic_set_promisc(adapter, mode);
}
@@ -533,6 +540,56 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
}
}
+int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
+{
+ struct qlcnic_nic_req req;
+ int rv;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+ req.req_hdr = cpu_to_le64(QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
+ ((u64) adapter->portnum << 16) | ((u64) 0x1 << 32));
+
+ req.words[0] = cpu_to_le64(flag);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->pdev->dev, "%sting loopback mode failed\n",
+ flag ? "Set" : "Reset");
+ return rv;
+}
+
+int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
+{
+ if (qlcnic_set_fw_loopback(adapter, mode))
+ return -EIO;
+
+ if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) {
+ qlcnic_set_fw_loopback(adapter, mode);
+ return -EIO;
+ }
+
+ msleep(1000);
+ return 0;
+}
+
+void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter)
+{
+ int mode = VPORT_MISS_MODE_DROP;
+ struct net_device *netdev = adapter->netdev;
+
+ qlcnic_set_fw_loopback(adapter, 0);
+
+ if (netdev->flags & IFF_PROMISC)
+ mode = VPORT_MISS_MODE_ACCEPT_ALL;
+ else if (netdev->flags & IFF_ALLMULTI)
+ mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+
+ qlcnic_nic_set_promisc(adapter, mode);
+ msleep(1000);
+}
+
/*
* Send the interrupt coalescing parameter set by ethtool to the card.
*/
@@ -1509,18 +1566,26 @@ qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
for (i = 0; i < l2->no_ops; i++) {
QLCNIC_WR_DUMP_REG(l2->addr, base, val);
- do {
+ if (LSW(l2->ctrl_val))
QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base,
LSW(l2->ctrl_val));
+ if (!poll_mask)
+ goto skip_poll;
+ do {
QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data);
if (!(data & poll_mask))
break;
msleep(1);
time_out++;
} while (time_out <= poll_to);
- if (time_out > poll_to)
- return -EINVAL;
+ if (time_out > poll_to) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout exceeded in %s, aborting dump\n",
+ __func__);
+ return -EINVAL;
+ }
+skip_poll:
addr = l2->read_addr;
cnt = l2->read_addr_num;
while (cnt) {
@@ -1673,8 +1738,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
tmpl_hdr->sys_info[1] = adapter->fw_version;
for (i = 0; i < no_entries; i++) {
- entry = (struct qlcnic_dump_entry *) ((void *) tmpl_hdr +
- entry_offset);
+ entry = (void *)tmpl_hdr + entry_offset;
if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
entry->hdr.flags |= QLCNIC_DUMP_SKIP;
entry_offset += entry->hdr.offset;
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 5b8bbcf904d5..ee8a3982395e 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1281,6 +1281,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
u16 cable_len;
u16 link_speed;
u8 link_status, module, duplex, autoneg;
+ u8 lb_status = 0;
struct net_device *netdev = adapter->netdev;
adapter->has_link_events = 1;
@@ -1292,6 +1293,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
link_status = msg->body[2] & 0xff;
duplex = (msg->body[2] >> 16) & 0xff;
autoneg = (msg->body[2] >> 24) & 0xff;
+ lb_status = (msg->body[2] >> 32) & 0x3;
module = (msg->body[2] >> 8) & 0xff;
if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
@@ -1301,6 +1303,10 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
dev_info(&netdev->dev, "unsupported cable length %d\n",
cable_len);
+ if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+ lb_status == QLCNIC_ELB_MODE))
+ adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
+
qlcnic_advert_link_change(adapter, link_status);
if (duplex == LINKEVENT_FULL_DUPLEX)
@@ -1319,7 +1325,9 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
{
struct qlcnic_fw_msg msg;
struct status_desc *desc;
- int i = 0, opcode;
+ struct qlcnic_adapter *adapter;
+ struct device *dev;
+ int i = 0, opcode, ret;
while (desc_cnt > 0 && i < 8) {
desc = &sds_ring->desc_head[index];
@@ -1330,10 +1338,34 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
desc_cnt--;
}
+ adapter = sds_ring->adapter;
+ dev = &adapter->pdev->dev;
opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
+
switch (opcode) {
case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
- qlcnic_handle_linkevent(sds_ring->adapter, &msg);
+ qlcnic_handle_linkevent(adapter, &msg);
+ break;
+ case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
+ ret = (u32)(msg.body[1]);
+ switch (ret) {
+ case 0:
+ adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
+ break;
+ case 1:
+ dev_info(dev, "loopback already in progress\n");
+ adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+ break;
+ case 2:
+ dev_info(dev, "loopback cable is not connected\n");
+ adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+ break;
+ default:
+ dev_info(dev, "loopback configure request failed,"
+ " ret %x\n", ret);
+ adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+ break;
+ }
break;
default:
break;
@@ -1746,6 +1778,103 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
spin_unlock(&rds_ring->lock);
}
+static void dump_skb(struct sk_buff *skb)
+{
+ int i;
+ unsigned char *data = skb->data;
+
+ printk(KERN_INFO "\n");
+ for (i = 0; i < skb->len; i++) {
+ printk(KERN_INFO "%02x ", data[i]);
+ if ((i & 0x0f) == 8)
+ printk(KERN_INFO "\n");
+ }
+}
+
+void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ int ring, u64 sts_data0)
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum, pkt_offset;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_sts_refhandle(sts_data0);
+ length = qlcnic_get_sts_totallength(sts_data0);
+ if (unlikely(index >= rds_ring->num_desc))
+ return;
+
+ cksum = qlcnic_get_sts_status(sts_data0);
+ pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
+
+ if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+ adapter->diag_cnt++;
+ else
+ dump_skb(skb);
+
+ dev_kfree_skb_any(skb);
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return;
+}
+
+void
+qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct status_desc *desc;
+ u64 sts_data0;
+ int ring, opcode, desc_cnt;
+
+ u32 consumer = sds_ring->consumer;
+
+ desc = &sds_ring->desc_head[consumer];
+ sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+ if (!(sts_data0 & STATUS_OWNER_HOST))
+ return;
+
+ desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+ opcode = qlcnic_get_sts_opcode(sts_data0);
+ switch (opcode) {
+ case QLCNIC_RESPONSE_DESC:
+ qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+ break;
+ default:
+ ring = qlcnic_get_sts_type(sts_data0);
+ qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
+ break;
+ }
+
+ for (; desc_cnt > 0; desc_cnt--) {
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ }
+
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+}
+
void
qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
u8 alt_mac, u8 *mac)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 0f6af5c61a7c..5ca1b562443c 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -90,7 +90,6 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long);
static int qlcnic_start_firmware(struct qlcnic_adapter *);
-static void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
@@ -418,10 +417,8 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
int num_msix;
if (adapter->msix_supported) {
- num_msix = (num_online_cpus() >=
- QLCNIC_DEF_NUM_STS_DESC_RINGS) ?
- QLCNIC_DEF_NUM_STS_DESC_RINGS :
- QLCNIC_MIN_NUM_RSS_RINGS;
+ num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
+ QLCNIC_DEF_NUM_STS_DESC_RINGS));
} else
num_msix = 1;
@@ -1393,6 +1390,12 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
qlcnic_enable_int(sds_ring);
}
}
+
+ if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) {
+ adapter->ahw->loopback_state = 0;
+ qlcnic_linkevent_request(adapter, 1);
+ }
+
set_bit(__QLCNIC_DEV_UP, &adapter->state);
return 0;
@@ -1487,8 +1490,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
netdev->irq = adapter->msix_entries[0].vector;
- netif_carrier_off(netdev);
-
err = register_netdev(netdev);
if (err) {
dev_err(&pdev->dev, "failed to register net device\n");
@@ -1576,6 +1577,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->dev_rst_time = jiffies;
revision_id = pdev->revision;
adapter->ahw->revision_id = revision_id;
+ adapter->mac_learn = qlcnic_mac_learn;
rwlock_init(&adapter->ahw->crb_lock);
mutex_init(&adapter->ahw->mem_lock);
@@ -1590,10 +1592,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* This will be reset for mezz cards */
adapter->portnum = adapter->ahw->pci_func;
- /* Get FW dump template and store it */
- if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
- qlcnic_fw_cmd_get_minidump_temp(adapter);
-
err = qlcnic_get_board_info(adapter);
if (err) {
dev_err(&pdev->dev, "Error getting board config info.\n");
@@ -1612,6 +1610,12 @@ 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");
@@ -1650,7 +1654,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
- qlcnic_alloc_lb_filters_mem(adapter);
+ if (adapter->mac_learn)
+ qlcnic_alloc_lb_filters_mem(adapter);
+
qlcnic_create_diag_entries(adapter);
return 0;
@@ -1816,6 +1822,8 @@ static int qlcnic_open(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int err;
+ netif_carrier_off(netdev);
+
err = qlcnic_attach(adapter);
if (err)
return err;
@@ -1844,13 +1852,12 @@ static int qlcnic_close(struct net_device *netdev)
return 0;
}
-static void
-qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
+void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
{
void *head;
int i;
- if (!qlcnic_mac_learn)
+ if (adapter->fhash.fmax && adapter->fhash.fhead)
return;
spin_lock_init(&adapter->mac_learn_lock);
@@ -1861,7 +1868,7 @@ qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
return;
adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
- adapter->fhash.fhead = (struct hlist_head *)head;
+ adapter->fhash.fhead = head;
for (i = 0; i < adapter->fhash.fmax; i++)
INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
@@ -2280,14 +2287,14 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
goto unwind_buff;
- if (qlcnic_mac_learn)
+ if (adapter->mac_learn)
qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
- qlcnic_update_cmd_producer(adapter, tx_ring);
-
adapter->stats.txbytes += skb->len;
adapter->stats.xmitcalled++;
+ qlcnic_update_cmd_producer(adapter, tx_ring);
+
return NETDEV_TX_OK;
unwind_buff:
@@ -2683,11 +2690,16 @@ err:
static int
qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
{
- int act, state;
+ int act, state, active_mask;
state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
+ if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
+ active_mask = (~(1 << (adapter->ahw->pci_func * 4)));
+ act = act & active_mask;
+ }
+
if (((state & 0x11111111) == (act & 0x11111111)) ||
((act & 0x11111111) == ((state >> 1) & 0x11111111)))
return 0;
@@ -2800,6 +2812,7 @@ qlcnic_fwinit_work(struct work_struct *work)
struct qlcnic_adapter *adapter = container_of(work,
struct qlcnic_adapter, fw_work.work);
u32 dev_state = 0xf;
+ u32 val;
if (qlcnic_api_lock(adapter))
goto err_ret;
@@ -2834,12 +2847,22 @@ skip_ack_check:
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCDB(adapter, DRV, "Restarting fw\n");
qlcnic_idc_debug_info(adapter, 0);
- QLCDB(adapter, DRV, "Take FW dump\n");
- qlcnic_dump_fw(adapter);
+ val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ QLC_DEV_SET_RST_RDY(val, adapter->portnum);
+ QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
}
qlcnic_api_unlock(adapter);
+ rtnl_lock();
+ if (adapter->ahw->fw_dump.enable &&
+ (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
+ QLCDB(adapter, DRV, "Take FW dump\n");
+ qlcnic_dump_fw(adapter);
+ }
+ rtnl_unlock();
+
+ adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
if (!adapter->nic_ops->start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
adapter->fw_wait_cnt = 0;
@@ -2900,9 +2923,11 @@ qlcnic_detach_work(struct work_struct *work)
if (adapter->temp == QLCNIC_TEMP_PANIC)
goto err_ret;
-
- if (qlcnic_set_drv_state(adapter, adapter->dev_state))
- 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))
+ goto err_ret;
+ }
adapter->fw_wait_cnt = 0;
@@ -2947,6 +2972,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
if (state == QLCNIC_DEV_READY) {
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
+ adapter->flags |= QLCNIC_FW_RESET_OWNER;
QLCDB(adapter, DRV, "NEED_RESET state set\n");
qlcnic_idc_debug_info(adapter, 0);
}
@@ -4178,7 +4204,7 @@ qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
qlcnic_config_indev_addr(adapter, netdev, event);
for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
- dev = vlan_find_dev(netdev, vid);
+ dev = __vlan_find_dev_deep(netdev, vid);
if (!dev)
continue;
qlcnic_config_indev_addr(adapter, dev, event);
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index ca306fd5f588..8731f79c9efc 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -7,9 +7,11 @@
#ifndef _QLGE_H_
#define _QLGE_H_
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
/*
* General definitions...
@@ -2051,7 +2053,7 @@ struct ql_adapter {
struct nic_stats nic_stats;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
/* PCI Configuration information for this device */
struct pci_dev *pdev;
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index 19b00fa0eaf0..9b67bfea035f 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -650,8 +650,6 @@ static int ql_set_pauseparam(struct net_device *netdev,
return -EINVAL;
status = ql_mb_set_port_cfg(qdev);
- if (status)
- return status;
return status;
}
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 6b4ff970972b..f07e96ec8843 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -7,6 +7,7 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/list.h>
@@ -33,8 +34,8 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
-#include <linux/skbuff.h>
#include <linux/if_vlan.h>
+#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
@@ -415,7 +416,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
(qdev->
func << CAM_OUT_FUNC_SHIFT) |
(0 << CAM_OUT_CQ_ID_SHIFT));
- if (qdev->vlgrp)
+ if (qdev->ndev->features & NETIF_F_HW_VLAN_RX)
cam_output |= CAM_OUT_RV;
/* route to NIC core */
ql_write32(qdev, MAC_ADDR_DATA, cam_output);
@@ -1507,10 +1508,9 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
rx_ring->rx_bytes += length;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_gro_frags(&rx_ring->napi, qdev->vlgrp, vlan_id);
- else
- napi_gro_frags(napi);
+ if (vlan_id != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ napi_gro_frags(napi);
}
/* Process an inbound completion from an rx ring. */
@@ -1594,17 +1594,12 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
}
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_gro_receive(napi, qdev->vlgrp, vlan_id, skb);
- else
- napi_gro_receive(napi, skb);
- } else {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
- else
- netif_receive_skb(skb);
- }
+ if (vlan_id != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ napi_gro_receive(napi, skb);
+ else
+ netif_receive_skb(skb);
return;
err_out:
dev_kfree_skb_any(skb);
@@ -1707,18 +1702,12 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
}
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_gro_receive(&rx_ring->napi, qdev->vlgrp,
- vlan_id, skb);
- else
- napi_gro_receive(&rx_ring->napi, skb);
- } else {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
- else
- netif_receive_skb(skb);
- }
+ if (vlan_id != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ napi_gro_receive(&rx_ring->napi, skb);
+ else
+ netif_receive_skb(skb);
}
static void ql_realign_skb(struct sk_buff *skb, int len)
@@ -2028,22 +2017,12 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev,
rx_ring->rx_packets++;
rx_ring->rx_bytes += skb->len;
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- if (qdev->vlgrp &&
- (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
- (vlan_id != 0))
- vlan_gro_receive(&rx_ring->napi, qdev->vlgrp,
- vlan_id, skb);
- else
- napi_gro_receive(&rx_ring->napi, skb);
- } else {
- if (qdev->vlgrp &&
- (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
- (vlan_id != 0))
- vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
- else
- netif_receive_skb(skb);
- }
+ if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && (vlan_id != 0))
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ napi_gro_receive(&rx_ring->napi, skb);
+ else
+ netif_receive_skb(skb);
}
/* Process an inbound completion from an rx ring. */
@@ -2334,71 +2313,111 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget)
return work_done;
}
-static void qlge_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
+static void qlge_vlan_mode(struct net_device *ndev, u32 features)
{
struct ql_adapter *qdev = netdev_priv(ndev);
- qdev->vlgrp = grp;
- if (grp) {
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
+ if (features & NETIF_F_HW_VLAN_RX) {
+ netif_printk(qdev, ifup, KERN_DEBUG, ndev,
"Turning on VLAN in NIC_RCV_CFG.\n");
ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK |
- NIC_RCV_CFG_VLAN_MATCH_AND_NON);
+ NIC_RCV_CFG_VLAN_MATCH_AND_NON);
} else {
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
+ netif_printk(qdev, ifup, KERN_DEBUG, ndev,
"Turning off VLAN in NIC_RCV_CFG.\n");
ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK);
}
}
-static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
+static u32 qlge_fix_features(struct net_device *ndev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int qlge_set_features(struct net_device *ndev, u32 features)
+{
+ u32 changed = ndev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ qlge_vlan_mode(ndev, features);
+
+ return 0;
+}
+
+static void __qlge_vlan_rx_add_vid(struct ql_adapter *qdev, u16 vid)
{
- struct ql_adapter *qdev = netdev_priv(ndev);
u32 enable_bit = MAC_ADDR_E;
- int status;
- status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
- if (status)
- return;
if (ql_set_mac_addr_reg
(qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
netif_err(qdev, ifup, qdev->ndev,
"Failed to init vlan address.\n");
}
- ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
}
-static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
{
struct ql_adapter *qdev = netdev_priv(ndev);
- u32 enable_bit = 0;
int status;
status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
if (status)
return;
+ __qlge_vlan_rx_add_vid(qdev, vid);
+ set_bit(vid, qdev->active_vlans);
+
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+}
+
+static void __qlge_vlan_rx_kill_vid(struct ql_adapter *qdev, u16 vid)
+{
+ u32 enable_bit = 0;
+
if (ql_set_mac_addr_reg
(qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
netif_err(qdev, ifup, qdev->ndev,
"Failed to clear vlan address.\n");
}
- ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+}
+static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ int status;
+
+ status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+ if (status)
+ return;
+
+ __qlge_vlan_rx_kill_vid(qdev, vid);
+ clear_bit(vid, qdev->active_vlans);
+
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
}
static void qlge_restore_vlan(struct ql_adapter *qdev)
{
- qlge_vlan_rx_register(qdev->ndev, qdev->vlgrp);
+ int status;
+ u16 vid;
- if (qdev->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(qdev->vlgrp, vid))
- continue;
- qlge_vlan_rx_add_vid(qdev->ndev, vid);
- }
- }
+ status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+ if (status)
+ return;
+
+ for_each_set_bit(vid, qdev->active_vlans, VLAN_N_VID)
+ __qlge_vlan_rx_add_vid(qdev, vid);
+
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
}
/* MSI-X Multiple Vector Interrupt Handler for inbound completions. */
@@ -3096,7 +3115,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
if (rx_ring->lbq_len) {
cqicb->flags |= FLAGS_LL; /* Load lbq values */
tmp = (u64)rx_ring->lbq_base_dma;
- base_indirect_ptr = (__le64 *) rx_ring->lbq_base_indirect;
+ base_indirect_ptr = rx_ring->lbq_base_indirect;
page_entries = 0;
do {
*base_indirect_ptr = cpu_to_le64(tmp);
@@ -3120,7 +3139,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
if (rx_ring->sbq_len) {
cqicb->flags |= FLAGS_LS; /* Load sbq values */
tmp = (u64)rx_ring->sbq_base_dma;
- base_indirect_ptr = (__le64 *) rx_ring->sbq_base_indirect;
+ base_indirect_ptr = rx_ring->sbq_base_indirect;
page_entries = 0;
do {
*base_indirect_ptr = cpu_to_le64(tmp);
@@ -4661,7 +4680,8 @@ static const struct net_device_ops qlge_netdev_ops = {
.ndo_set_mac_address = qlge_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = qlge_tx_timeout,
- .ndo_vlan_rx_register = qlge_vlan_rx_register,
+ .ndo_fix_features = qlge_fix_features,
+ .ndo_set_features = qlge_set_features,
.ndo_vlan_rx_add_vid = qlge_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid,
};
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 0ffec4608441..b64fcee483aa 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -838,6 +838,9 @@ static netdev_tx_t r6040_start_xmit(struct sk_buff *skb,
descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
descptr->status = DSC_OWNER_MAC;
+
+ skb_tx_timestamp(skb);
+
/* Trigger the MAC to check the TX descriptor */
iowrite16(0x01, ioaddr + MTPR);
lp->tx_insert_ptr = descptr->vndescp;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5990621fb5cd..7d9c650f395e 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -22,6 +22,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/firmware.h>
@@ -40,6 +41,7 @@
#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
#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_8105E_1 "rtl_nic/rtl8105e-1.fw"
#ifdef RTL8169_DEBUG
@@ -69,8 +71,6 @@ static const int multicast_filter_limit = 32;
#define MAC_ADDR_LEN 6
#define MAX_READ_REQUEST_SHIFT 12
-#define RX_FIFO_THRESH 7 /* 7 means NO threshold, 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 */
#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
@@ -132,6 +132,7 @@ enum mac_version {
RTL_GIGA_MAC_VER_31,
RTL_GIGA_MAC_VER_32,
RTL_GIGA_MAC_VER_33,
+ RTL_GIGA_MAC_VER_34,
RTL_GIGA_MAC_NONE = 0xff,
};
@@ -215,7 +216,9 @@ static const struct {
[RTL_GIGA_MAC_VER_32] =
_R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1),
[RTL_GIGA_MAC_VER_33] =
- _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2)
+ _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2),
+ [RTL_GIGA_MAC_VER_34] =
+ _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3)
};
#undef _R
@@ -269,10 +272,20 @@ enum rtl_registers {
TxPoll = 0x38,
IntrMask = 0x3c,
IntrStatus = 0x3e,
+
TxConfig = 0x40,
- RxConfig = 0x44,
+#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
+#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
-#define RTL_RX_CONFIG_MASK 0xff7e1880u
+ RxConfig = 0x44,
+#define RX128_INT_EN (1 << 15) /* 8111c and later */
+#define RX_MULTI_EN (1 << 14) /* 8111c only */
+#define RXCFG_FIFO_SHIFT 13
+ /* No threshold before first PCI xfer */
+#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
+#define RXCFG_DMA_SHIFT 8
+ /* Unlimited maximum PCI burst. */
+#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
RxMissed = 0x4c,
Cfg9346 = 0x50,
@@ -326,12 +339,13 @@ enum rtl8168_8101_registers {
#define EPHYAR_REG_SHIFT 16
#define EPHYAR_DATA_MASK 0xffff
DLLPR = 0xd0,
-#define PM_SWITCH (1 << 6)
+#define PFM_EN (1 << 6)
DBG_REG = 0xd1,
#define FIX_NAK_1 (1 << 4)
#define FIX_NAK_2 (1 << 3)
TWSI = 0xd2,
MCU = 0xd3,
+#define NOW_IS_OOB (1 << 7)
#define EN_NDP (1 << 3)
#define EN_OOB_RESET (1 << 2)
EFUSEAR = 0xdc,
@@ -344,18 +358,22 @@ enum rtl8168_8101_registers {
};
enum rtl8168_registers {
+ LED_FREQ = 0x1a,
+ EEE_LED = 0x1b,
ERIDR = 0x70,
ERIAR = 0x74,
#define ERIAR_FLAG 0x80000000
#define ERIAR_WRITE_CMD 0x80000000
#define ERIAR_READ_CMD 0x00000000
#define ERIAR_ADDR_BYTE_ALIGN 4
-#define ERIAR_EXGMAC 0
-#define ERIAR_MSIX 1
-#define ERIAR_ASF 2
#define ERIAR_TYPE_SHIFT 16
-#define ERIAR_BYTEEN 0x0f
-#define ERIAR_BYTEEN_SHIFT 12
+#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
+#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
+#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
+#define ERIAR_MASK_SHIFT 12
+#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
EPHY_RXER_NUM = 0x7c,
OCPDR = 0xb0, /* OCP GPHY access */
#define OCPDR_WRITE_CMD 0x80000000
@@ -370,6 +388,7 @@ enum rtl8168_registers {
RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
MISC = 0xf0, /* 8168e only. */
#define TXPLA_RST (1 << 29)
+#define PWM_EN (1 << 22)
};
enum rtl_register_content {
@@ -394,6 +413,7 @@ enum rtl_register_content {
RxCRC = (1 << 19),
/* ChipCmdBits */
+ StopReq = 0x80,
CmdReset = 0x10,
CmdRxEnb = 0x08,
CmdTxEnb = 0x04,
@@ -415,10 +435,7 @@ enum rtl_register_content {
AcceptMulticast = 0x04,
AcceptMyPhys = 0x02,
AcceptAllPhys = 0x01,
-
- /* RxConfigBits */
- RxCfgFIFOShift = 13,
- RxCfgDMAShift = 8,
+#define RX_CONFIG_ACCEPT_MASK 0x3f
/* TxConfigBits */
TxInterFrameGapShift = 24,
@@ -658,7 +675,6 @@ struct rtl8169_private {
unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
unsigned int (*link_ok)(void __iomem *);
int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
- int pcie_cap;
struct delayed_work task;
unsigned features;
@@ -666,8 +682,19 @@ struct rtl8169_private {
struct rtl8169_counters counters;
u32 saved_wolopts;
- const struct firmware *fw;
-#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN);
+ struct rtl_fw {
+ const struct firmware *fw;
+
+#define RTL_VER_SIZE 32
+
+ char version[RTL_VER_SIZE];
+
+ struct rtl_fw_phy_action {
+ __le32 *code;
+ size_t size;
+ } phy_action;
+ } *rtl_fw;
+#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -701,9 +728,6 @@ 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 const unsigned int rtl8169_rx_config =
- (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
-
static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -1024,6 +1048,49 @@ static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
return value;
}
+static
+void rtl_eri_write(void __iomem *ioaddr, int addr, u32 mask, u32 val, int type)
+{
+ unsigned int i;
+
+ BUG_ON((addr & 3) || (mask == 0));
+ RTL_W32(ERIDR, val);
+ RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
+
+ for (i = 0; i < 100; i++) {
+ if (!(RTL_R32(ERIAR) & ERIAR_FLAG))
+ break;
+ udelay(100);
+ }
+}
+
+static u32 rtl_eri_read(void __iomem *ioaddr, int addr, int type)
+{
+ u32 value = ~0x00;
+ unsigned int i;
+
+ RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
+
+ for (i = 0; i < 100; i++) {
+ if (RTL_R32(ERIAR) & ERIAR_FLAG) {
+ value = RTL_R32(ERIDR);
+ break;
+ }
+ udelay(100);
+ }
+
+ return value;
+}
+
+static void
+rtl_w1w0_eri(void __iomem *ioaddr, int addr, u32 mask, u32 p, u32 m, int type)
+{
+ u32 val;
+
+ val = rtl_eri_read(ioaddr, addr, type);
+ rtl_eri_write(ioaddr, addr, mask, (val & ~m) | p, type);
+}
+
static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
{
u8 value = 0xff;
@@ -1049,13 +1116,6 @@ static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
RTL_W16(IntrStatus, 0xffff);
}
-static void rtl8169_asic_down(void __iomem *ioaddr)
-{
- RTL_W8(ChipCmd, 0x00);
- rtl8169_irq_mask_and_ack(ioaddr);
- RTL_R16(CPlusCmd);
-}
-
static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -1093,6 +1153,39 @@ static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
rtl_writephy(tp, MII_BMCR, val & 0xffff);
}
+static void rtl_link_chg_patch(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct net_device *dev = tp->dev;
+
+ if (!netif_running(dev))
+ return;
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+ 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 if (RTL_R8(PHYstatus) & _100bps) {
+ rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+ 0x0000001f, 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);
+ }
+ /* Reset packet filter */
+ rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
+ ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
+ ERIAR_EXGMAC);
+ }
+}
+
static void __rtl8169_check_link_status(struct net_device *dev,
struct rtl8169_private *tp,
void __iomem *ioaddr, bool pm)
@@ -1101,6 +1194,7 @@ static void __rtl8169_check_link_status(struct net_device *dev,
spin_lock_irqsave(&tp->lock, flags);
if (tp->link_ok(ioaddr)) {
+ rtl_link_chg_patch(tp);
/* This is to cancel a scheduled suspend if there's one. */
if (pm)
pm_request_resume(&tp->pci_dev->dev);
@@ -1221,12 +1315,14 @@ static void rtl8169_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct rtl8169_private *tp = netdev_priv(dev);
+ struct rtl_fw *rtl_fw = tp->rtl_fw;
strcpy(info->driver, MODULENAME);
strcpy(info->version, RTL8169_VERSION);
strcpy(info->bus_info, pci_name(tp->pci_dev));
- strncpy(info->fw_version, IS_ERR_OR_NULL(tp->fw) ? "N/A" :
- rtl_lookup_firmware_name(tp), sizeof(info->fw_version) - 1);
+ BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
+ strcpy(info->fw_version, IS_ERR_OR_NULL(rtl_fw) ? "N/A" :
+ rtl_fw->version);
}
static int rtl8169_get_regs_len(struct net_device *dev)
@@ -1627,6 +1723,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
int mac_version;
} mac_info[] = {
/* 8168E family. */
+ { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
{ 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
{ 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
{ 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
@@ -1741,21 +1838,75 @@ static void rtl_writephy_batch(struct rtl8169_private *tp,
#define PHY_DELAY_MS 0xe0000000
#define PHY_WRITE_ERI_WORD 0xf0000000
-static void
-rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
+struct fw_info {
+ u32 magic;
+ char version[RTL_VER_SIZE];
+ __le32 fw_start;
+ __le32 fw_len;
+ u8 chksum;
+} __packed;
+
+#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
+
+static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
{
- __le32 *phytable = (__le32 *)fw->data;
- struct net_device *dev = tp->dev;
- size_t index, fw_size = fw->size / sizeof(*phytable);
- u32 predata, count;
+ const struct firmware *fw = rtl_fw->fw;
+ struct fw_info *fw_info = (struct fw_info *)fw->data;
+ struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+ char *version = rtl_fw->version;
+ bool rc = false;
- if (fw->size % sizeof(*phytable)) {
- netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size);
- return;
+ if (fw->size < FW_OPCODE_SIZE)
+ goto out;
+
+ if (!fw_info->magic) {
+ size_t i, size, start;
+ u8 checksum = 0;
+
+ if (fw->size < sizeof(*fw_info))
+ goto out;
+
+ for (i = 0; i < fw->size; i++)
+ checksum += fw->data[i];
+ if (checksum != 0)
+ goto out;
+
+ start = le32_to_cpu(fw_info->fw_start);
+ if (start > fw->size)
+ goto out;
+
+ size = le32_to_cpu(fw_info->fw_len);
+ if (size > (fw->size - start) / FW_OPCODE_SIZE)
+ goto out;
+
+ memcpy(version, fw_info->version, RTL_VER_SIZE);
+
+ pa->code = (__le32 *)(fw->data + start);
+ pa->size = size;
+ } else {
+ if (fw->size % FW_OPCODE_SIZE)
+ goto out;
+
+ strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
+
+ pa->code = (__le32 *)fw->data;
+ pa->size = fw->size / FW_OPCODE_SIZE;
}
+ version[RTL_VER_SIZE - 1] = 0;
- for (index = 0; index < fw_size; index++) {
- u32 action = le32_to_cpu(phytable[index]);
+ rc = true;
+out:
+ return rc;
+}
+
+static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
+ struct rtl_fw_phy_action *pa)
+{
+ bool rc = false;
+ size_t index;
+
+ for (index = 0; index < pa->size; index++) {
+ u32 action = le32_to_cpu(pa->code[index]);
u32 regno = (action & 0x0fff0000) >> 16;
switch(action & 0xf0000000) {
@@ -1771,25 +1922,25 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
case PHY_BJMPN:
if (regno > index) {
- netif_err(tp, probe, tp->dev,
+ netif_err(tp, ifup, tp->dev,
"Out of range of firmware\n");
- return;
+ goto out;
}
break;
case PHY_READCOUNT_EQ_SKIP:
- if (index + 2 >= fw_size) {
- netif_err(tp, probe, tp->dev,
+ if (index + 2 >= pa->size) {
+ netif_err(tp, ifup, tp->dev,
"Out of range of firmware\n");
- return;
+ goto out;
}
break;
case PHY_COMP_EQ_SKIPN:
case PHY_COMP_NEQ_SKIPN:
case PHY_SKIPN:
- if (index + 1 + regno >= fw_size) {
- netif_err(tp, probe, tp->dev,
+ if (index + 1 + regno >= pa->size) {
+ netif_err(tp, ifup, tp->dev,
"Out of range of firmware\n");
- return;
+ goto out;
}
break;
@@ -1797,17 +1948,42 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
case PHY_WRITE_MAC_BYTE:
case PHY_WRITE_ERI_WORD:
default:
- netif_err(tp, probe, tp->dev,
+ netif_err(tp, ifup, tp->dev,
"Invalid action 0x%08x\n", action);
- return;
+ goto out;
}
}
+ rc = true;
+out:
+ return rc;
+}
+
+static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
+{
+ struct net_device *dev = tp->dev;
+ int rc = -EINVAL;
+
+ if (!rtl_fw_format_ok(tp, rtl_fw)) {
+ netif_err(tp, ifup, dev, "invalid firwmare\n");
+ goto out;
+ }
+
+ if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
+ rc = 0;
+out:
+ return rc;
+}
+
+static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
+{
+ struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+ u32 predata, count;
+ size_t index;
- predata = 0;
- count = 0;
+ predata = count = 0;
- for (index = 0; index < fw_size; ) {
- u32 action = le32_to_cpu(phytable[index]);
+ for (index = 0; index < pa->size; ) {
+ u32 action = le32_to_cpu(pa->code[index]);
u32 data = action & 0x0000ffff;
u32 regno = (action & 0x0fff0000) >> 16;
@@ -1879,18 +2055,20 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
static void rtl_release_firmware(struct rtl8169_private *tp)
{
- if (!IS_ERR_OR_NULL(tp->fw))
- release_firmware(tp->fw);
- tp->fw = RTL_FIRMWARE_UNKNOWN;
+ if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
+ release_firmware(tp->rtl_fw->fw);
+ kfree(tp->rtl_fw);
+ }
+ tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
}
static void rtl_apply_firmware(struct rtl8169_private *tp)
{
- const struct firmware *fw = tp->fw;
+ struct rtl_fw *rtl_fw = tp->rtl_fw;
/* TODO: release firmware once rtl_phy_write_fw signals failures. */
- if (!IS_ERR_OR_NULL(fw))
- rtl_phy_write_fw(tp, fw);
+ if (!IS_ERR_OR_NULL(rtl_fw))
+ rtl_phy_write_fw(tp, rtl_fw);
}
static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -1982,12 +2160,9 @@ static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
{
struct pci_dev *pdev = tp->pci_dev;
- u16 vendor_id, device_id;
-
- pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id);
- pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id);
- if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000))
+ if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
+ (pdev->subsystem_device != 0xe000))
return;
rtl_writephy(tp, 0x1f, 0x0001);
@@ -2523,7 +2698,7 @@ static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
rtl_patchphy(tp, 0x0d, 1 << 5);
}
-static void rtl8168e_hw_phy_config(struct rtl8169_private *tp)
+static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
/* Enable Delay cap */
@@ -2596,6 +2771,91 @@ static void rtl8168e_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x0d, 0x0000);
}
+static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
+{
+ static const struct phy_reg phy_reg_init[] = {
+ /* Enable Delay cap */
+ { 0x1f, 0x0004 },
+ { 0x1f, 0x0007 },
+ { 0x1e, 0x00ac },
+ { 0x18, 0x0006 },
+ { 0x1f, 0x0002 },
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0000 },
+
+ /* Channel estimation fine tune */
+ { 0x1f, 0x0003 },
+ { 0x09, 0xa20f },
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0000 },
+
+ /* Green Setting */
+ { 0x1f, 0x0005 },
+ { 0x05, 0x8b5b },
+ { 0x06, 0x9222 },
+ { 0x05, 0x8b6d },
+ { 0x06, 0x8000 },
+ { 0x05, 0x8b76 },
+ { 0x06, 0x8000 },
+ { 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, 0x17, 0x0006, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* PHY auto speed down */
+ rtl_writephy(tp, 0x1f, 0x0004);
+ rtl_writephy(tp, 0x1f, 0x0007);
+ rtl_writephy(tp, 0x1e, 0x002d);
+ rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0002);
+ 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);
+
+ /* EEE setting */
+ rtl_w1w0_eri(tp->mmio_addr, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003,
+ ERIAR_EXGMAC);
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b85);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
+ rtl_writephy(tp, 0x1f, 0x0004);
+ rtl_writephy(tp, 0x1f, 0x0007);
+ rtl_writephy(tp, 0x1e, 0x0020);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
+ rtl_writephy(tp, 0x1f, 0x0002);
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_writephy(tp, 0x0d, 0x0007);
+ rtl_writephy(tp, 0x0e, 0x003c);
+ rtl_writephy(tp, 0x0d, 0x4007);
+ rtl_writephy(tp, 0x0e, 0x0000);
+ rtl_writephy(tp, 0x0d, 0x0000);
+
+ /* Green feature */
+ rtl_writephy(tp, 0x1f, 0x0003);
+ rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
+ rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
+ rtl_writephy(tp, 0x1f, 0x0000);
+}
+
static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -2715,7 +2975,10 @@ static void rtl_hw_phy_config(struct net_device *dev)
break;
case RTL_GIGA_MAC_VER_32:
case RTL_GIGA_MAC_VER_33:
- rtl8168e_hw_phy_config(tp);
+ rtl8168e_1_hw_phy_config(tp);
+ break;
+ case RTL_GIGA_MAC_VER_34:
+ rtl8168e_2_hw_phy_config(tp);
break;
default:
@@ -3125,8 +3388,10 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0000);
rtl_writephy(tp, MII_BMCR, 0x0000);
- RTL_W32(RxConfig, RTL_R32(RxConfig) |
- AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
+ if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_33)
+ RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast |
+ AcceptMulticast | AcceptMyPhys);
return;
}
@@ -3221,6 +3486,7 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_31:
case RTL_GIGA_MAC_VER_32:
case RTL_GIGA_MAC_VER_33:
+ case RTL_GIGA_MAC_VER_34:
ops->down = r8168_pll_power_down;
ops->up = r8168_pll_power_up;
break;
@@ -3232,6 +3498,47 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
}
}
+static void rtl_init_rxcfg(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_01:
+ case RTL_GIGA_MAC_VER_02:
+ case RTL_GIGA_MAC_VER_03:
+ case RTL_GIGA_MAC_VER_04:
+ case RTL_GIGA_MAC_VER_05:
+ case RTL_GIGA_MAC_VER_06:
+ case RTL_GIGA_MAC_VER_10:
+ case RTL_GIGA_MAC_VER_11:
+ case RTL_GIGA_MAC_VER_12:
+ case RTL_GIGA_MAC_VER_13:
+ case RTL_GIGA_MAC_VER_14:
+ case RTL_GIGA_MAC_VER_15:
+ case RTL_GIGA_MAC_VER_16:
+ case RTL_GIGA_MAC_VER_17:
+ RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
+ break;
+ case RTL_GIGA_MAC_VER_18:
+ case RTL_GIGA_MAC_VER_19:
+ case RTL_GIGA_MAC_VER_20:
+ case RTL_GIGA_MAC_VER_21:
+ case RTL_GIGA_MAC_VER_22:
+ case RTL_GIGA_MAC_VER_23:
+ case RTL_GIGA_MAC_VER_24:
+ RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
+ break;
+ default:
+ RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
+ break;
+ }
+}
+
+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_reset(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -3244,8 +3551,10 @@ static void rtl_hw_reset(struct rtl8169_private *tp)
for (i = 0; i < 100; i++) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
- msleep_interruptible(1);
+ udelay(100);
}
+
+ rtl8169_init_ring_indexes(tp);
}
static int __devinit
@@ -3349,9 +3658,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
tp->mmio_addr = ioaddr;
- tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (!tp->pcie_cap)
- netif_info(tp, probe, dev, "no PCI Express capability\n");
+ if (!pci_is_pcie(pdev))
+ netif_info(tp, probe, dev, "not PCI Express\n");
+
+ /* Identify chip attached to board */
+ rtl8169_get_mac_version(tp, dev, cfg->default_ver);
+
+ rtl_init_rxcfg(tp);
RTL_W16(IntrMask, 0x0000);
@@ -3361,9 +3674,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev);
- /* Identify chip attached to board */
- rtl8169_get_mac_version(tp, dev, cfg->default_ver);
-
/*
* Pretend we are using VLANs; This bypasses a nasty bug where
* Interrupts stop flowing on high load on 8110SCd controllers.
@@ -3443,7 +3753,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->timer.data = (unsigned long) dev;
tp->timer.function = rtl8169_phy_timer;
- tp->fw = RTL_FIRMWARE_UNKNOWN;
+ tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
rc = register_netdev(dev);
if (rc < 0)
@@ -3512,25 +3822,48 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
-static void rtl_request_firmware(struct rtl8169_private *tp)
+static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
{
- /* Return early if the firmware is already loaded / cached. */
- if (IS_ERR(tp->fw)) {
- const char *name;
+ struct rtl_fw *rtl_fw;
+ const char *name;
+ int rc = -ENOMEM;
- name = rtl_lookup_firmware_name(tp);
- if (name) {
- int rc;
+ name = rtl_lookup_firmware_name(tp);
+ if (!name)
+ goto out_no_firmware;
- rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev);
- if (rc >= 0)
- return;
+ rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
+ if (!rtl_fw)
+ goto err_warn;
- netif_warn(tp, ifup, tp->dev, "unable to load "
- "firmware patch %s (%d)\n", name, rc);
- }
- tp->fw = NULL;
- }
+ rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
+ if (rc < 0)
+ goto err_free;
+
+ rc = rtl_check_firmware(tp, rtl_fw);
+ if (rc < 0)
+ goto err_release_firmware;
+
+ tp->rtl_fw = rtl_fw;
+out:
+ return;
+
+err_release_firmware:
+ release_firmware(rtl_fw->fw);
+err_free:
+ kfree(rtl_fw);
+err_warn:
+ netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
+ name, rc);
+out_no_firmware:
+ tp->rtl_fw = NULL;
+ goto out;
+}
+
+static void rtl_request_firmware(struct rtl8169_private *tp)
+{
+ if (IS_ERR(tp->rtl_fw))
+ rtl_request_uncached_firmware(tp);
}
static int rtl8169_open(struct net_device *dev)
@@ -3605,6 +3938,13 @@ err_pm_runtime_put:
goto out;
}
+static void rtl_rx_close(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
+}
+
static void rtl8169_hw_reset(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -3612,28 +3952,27 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
/* Disable interrupts */
rtl8169_irq_mask_and_ack(ioaddr);
+ rtl_rx_close(tp);
+
if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
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) {
+ while (!(RTL_R32(TxConfig) & TXCFG_EMPTY))
+ udelay(100);
+ } else {
+ RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
+ udelay(100);
}
- /* Reset the chipset */
- RTL_W8(ChipCmd, CmdReset);
-
- /* PCI commit */
- RTL_R8(ChipCmd);
+ rtl_hw_reset(tp);
}
static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- u32 cfg = rtl8169_rx_config;
-
- cfg |= (RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK);
- RTL_W32(RxConfig, cfg);
/* Set DMA burst size and Interframe Gap Time */
RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
@@ -3644,8 +3983,6 @@ static void rtl_hw_start(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
- rtl_hw_reset(tp);
-
tp->hw_start(dev);
netif_start_queue(dev);
@@ -3723,6 +4060,8 @@ static void rtl_hw_start_8169(struct net_device *dev)
tp->mac_version == RTL_GIGA_MAC_VER_04)
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ rtl_init_rxcfg(tp);
+
RTL_W8(EarlyTxThres, NoEarlyTx);
rtl_set_rx_max_size(ioaddr, rx_buf_sz);
@@ -3780,9 +4119,7 @@ static void rtl_hw_start_8169(struct net_device *dev)
static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
u16 ctl;
@@ -3830,9 +4167,7 @@ static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int l
static void rtl_disable_clock_request(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
u16 ctl;
@@ -3845,9 +4180,7 @@ static void rtl_disable_clock_request(struct pci_dev *pdev)
static void rtl_enable_clock_request(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
u16 ctl;
@@ -4038,9 +4371,9 @@ static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_enable_clock_request(pdev);
}
-static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168e_1(void __iomem *ioaddr, struct pci_dev *pdev)
{
- static const struct ephy_info e_info_8168e[] = {
+ static const struct ephy_info e_info_8168e_1[] = {
{ 0x00, 0x0200, 0x0100 },
{ 0x00, 0x0000, 0x0004 },
{ 0x06, 0x0002, 0x0001 },
@@ -4058,7 +4391,7 @@ static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_csi_access_enable_2(ioaddr);
- rtl_ephy_init(ioaddr, e_info_8168e, ARRAY_SIZE(e_info_8168e));
+ rtl_ephy_init(ioaddr, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
@@ -4073,6 +4406,44 @@ static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
}
+static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ static const struct ephy_info e_info_8168e_2[] = {
+ { 0x09, 0x0000, 0x0080 },
+ { 0x19, 0x0000, 0x0224 }
+ };
+
+ rtl_csi_access_enable_1(ioaddr);
+
+ rtl_ephy_init(ioaddr, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
+
+ 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_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
+ ERIAR_EXGMAC);
+
+ RTL_W8(MaxTxPacketSize, 0x27);
+
+ 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_8168(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -4161,7 +4532,10 @@ static void rtl_hw_start_8168(struct net_device *dev)
case RTL_GIGA_MAC_VER_32:
case RTL_GIGA_MAC_VER_33:
- rtl_hw_start_8168e(ioaddr, pdev);
+ rtl_hw_start_8168e_1(ioaddr, pdev);
+ break;
+ case RTL_GIGA_MAC_VER_34:
+ rtl_hw_start_8168e_2(ioaddr, pdev);
break;
default:
@@ -4258,7 +4632,7 @@ static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
- RTL_W8(DLLPR, RTL_R8(DLLPR) | PM_SWITCH);
+ RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
rtl_ephy_init(ioaddr, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
}
@@ -4277,7 +4651,7 @@ static void rtl_hw_start_8101(struct net_device *dev)
if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
tp->mac_version == RTL_GIGA_MAC_VER_16) {
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL,
@@ -4460,11 +4834,6 @@ err_out:
return -ENOMEM;
}
-static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
-{
- tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
-}
-
static int rtl8169_init_ring(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -4592,7 +4961,7 @@ static void rtl8169_reset_task(struct work_struct *work)
rtl8169_tx_clear(tp);
- rtl8169_init_ring_indexes(tp);
+ rtl8169_hw_reset(tp);
rtl_hw_start(dev);
netif_wake_queue(dev);
rtl8169_check_link_status(dev, tp, tp->mmio_addr);
@@ -5006,7 +5375,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
* the chip, so just exit the loop.
*/
if (unlikely(!netif_running(dev))) {
- rtl8169_asic_down(ioaddr);
+ rtl8169_hw_reset(tp);
break;
}
@@ -5129,7 +5498,7 @@ static void rtl8169_down(struct net_device *dev)
spin_lock_irq(&tp->lock);
- rtl8169_asic_down(ioaddr);
+ rtl8169_hw_reset(tp);
/*
* At this point device interrupts can not be enabled in any function,
* as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task,
@@ -5212,8 +5581,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
spin_lock_irqsave(&tp->lock, flags);
- tmp = rtl8169_rx_config | rx_mode |
- (RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK);
+ tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
u32 data = mc_filter[0];
@@ -5383,13 +5751,16 @@ static void rtl_shutdown(struct pci_dev *pdev)
spin_lock_irq(&tp->lock);
- rtl8169_asic_down(ioaddr);
+ rtl8169_hw_reset(tp);
spin_unlock_irq(&tp->lock);
if (system_state == SYSTEM_POWER_OFF) {
- /* WoL fails with some 8168 when the receiver is disabled. */
- if (tp->features & RTL_FEATURE_WOL) {
+ /* WoL fails with 8168b when the receiver is disabled. */
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_11 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_12 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_17) &&
+ (tp->features & RTL_FEATURE_WOL)) {
pci_clear_master(pdev);
RTL_W8(ChipCmd, CmdRxEnb);
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 5d3436d47edd..86ac38c96bcf 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -190,7 +190,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return NETDEV_TX_BUSY;
}
- if (eth->h_dest[0] & 0x01) {
+ if (is_multicast_ether_addr(eth->h_dest)) {
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
i++)
if (rionet_active[i])
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index df0d2c8ecc09..277d48b0800a 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -356,56 +356,6 @@ static void do_s2io_copy_mac_addr(struct s2io_nic *sp, int offset, u64 mac_addr)
sp->def_mac_addr[offset].mac_addr[0] = (u8) (mac_addr >> 40);
}
-/* Add the vlan */
-static void s2io_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
-{
- int i;
- struct s2io_nic *nic = netdev_priv(dev);
- unsigned long flags[MAX_TX_FIFOS];
- struct config_param *config = &nic->config;
- struct mac_info *mac_control = &nic->mac_control;
-
- for (i = 0; i < config->tx_fifo_num; i++) {
- struct fifo_info *fifo = &mac_control->fifos[i];
-
- spin_lock_irqsave(&fifo->tx_lock, flags[i]);
- }
-
- nic->vlgrp = grp;
-
- for (i = config->tx_fifo_num - 1; i >= 0; i--) {
- struct fifo_info *fifo = &mac_control->fifos[i];
-
- spin_unlock_irqrestore(&fifo->tx_lock, flags[i]);
- }
-}
-
-/* Unregister the vlan */
-static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- int i;
- struct s2io_nic *nic = netdev_priv(dev);
- unsigned long flags[MAX_TX_FIFOS];
- struct config_param *config = &nic->config;
- struct mac_info *mac_control = &nic->mac_control;
-
- for (i = 0; i < config->tx_fifo_num; i++) {
- struct fifo_info *fifo = &mac_control->fifos[i];
-
- spin_lock_irqsave(&fifo->tx_lock, flags[i]);
- }
-
- if (nic->vlgrp)
- vlan_group_set_device(nic->vlgrp, vid, NULL);
-
- for (i = config->tx_fifo_num - 1; i >= 0; i--) {
- struct fifo_info *fifo = &mac_control->fifos[i];
-
- spin_unlock_irqrestore(&fifo->tx_lock, flags[i]);
- }
-}
-
/*
* Constants to be programmed into the Xena's registers, to configure
* the XAUI.
@@ -841,7 +791,7 @@ static int init_shared_mem(struct s2io_nic *nic)
tmp_p_addr = ring->rx_blocks[j].block_dma_addr;
tmp_p_addr_next = ring->rx_blocks[next].block_dma_addr;
- pre_rxd_blk = (struct RxD_block *)tmp_v_addr;
+ pre_rxd_blk = tmp_v_addr;
pre_rxd_blk->reserved_2_pNext_RxD_block =
(unsigned long)tmp_v_addr_next;
pre_rxd_blk->pNext_RxD_Blk_physical =
@@ -918,7 +868,7 @@ static int init_shared_mem(struct s2io_nic *nic)
mac_control->stats_mem_sz = size;
tmp_v_addr = mac_control->stats_mem;
- mac_control->stats_info = (struct stat_block *)tmp_v_addr;
+ mac_control->stats_info = tmp_v_addr;
memset(tmp_v_addr, 0, size);
DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n",
dev_name(&nic->pdev->dev), (unsigned long long)tmp_p_addr);
@@ -2439,7 +2389,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
spin_lock_irqsave(&fifo->tx_lock, flags);
for (j = 0; j < tx_cfg->fifo_len; j++) {
- txdp = (struct TxD *)fifo->list_info[j].list_virt_addr;
+ txdp = fifo->list_info[j].list_virt_addr;
skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
if (skb) {
swstats->mem_freed += skb->truesize;
@@ -3075,8 +3025,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
get_info = fifo_data->tx_curr_get_info;
memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info));
- txdlp = (struct TxD *)
- fifo_data->list_info[get_info.offset].list_virt_addr;
+ txdlp = fifo_data->list_info[get_info.offset].list_virt_addr;
while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
(get_info.offset != put_info.offset) &&
(txdlp->Host_Control)) {
@@ -3129,8 +3078,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
get_info.offset++;
if (get_info.offset == get_info.fifo_len + 1)
get_info.offset = 0;
- txdlp = (struct TxD *)
- fifo_data->list_info[get_info.offset].list_virt_addr;
+ txdlp = fifo_data->list_info[get_info.offset].list_virt_addr;
fifo_data->tx_curr_get_info.offset = get_info.offset;
}
@@ -4111,7 +4059,7 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
struct tcphdr *th;
ip = ip_hdr(skb);
- if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+ if (!ip_is_fragment(ip)) {
th = (struct tcphdr *)(((unsigned char *)ip) +
ip->ihl*4);
@@ -4163,7 +4111,7 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
put_off = (u16)fifo->tx_curr_put_info.offset;
get_off = (u16)fifo->tx_curr_get_info.offset;
- txdp = (struct TxD *)fifo->list_info[put_off].list_virt_addr;
+ txdp = fifo->list_info[put_off].list_virt_addr;
queue_len = fifo->tx_curr_put_info.fifo_len + 1;
/* Avoid "put" pointer going beyond "get" pointer */
@@ -7739,8 +7687,6 @@ static const struct net_device_ops s2io_netdev_ops = {
.ndo_set_mac_address = s2io_set_mac_addr,
.ndo_change_mtu = s2io_change_mtu,
.ndo_set_features = s2io_set_features,
- .ndo_vlan_rx_register = s2io_vlan_rx_register,
- .ndo_vlan_rx_kill_vid = s2io_vlan_rx_kill_vid,
.ndo_tx_timeout = s2io_tx_watchdog,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = s2io_netpoll,
@@ -7972,9 +7918,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
/* Initializing the BAR1 address as the start of the FIFO pointer. */
for (j = 0; j < MAX_TX_FIFOS; j++) {
- mac_control->tx_FIFO_start[j] =
- (struct TxFIFO_element __iomem *)
- (sp->bar1 + (j * 0x00020000));
+ mac_control->tx_FIFO_start[j] = sp->bar1 + (j * 0x00020000);
}
/* Driver entry points */
@@ -8621,18 +8565,12 @@ static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
struct s2io_nic *sp = netdev_priv(dev);
skb->protocol = eth_type_trans(skb, dev);
- if (sp->vlgrp && vlan_tag && (sp->vlan_strip_flag)) {
- /* Queueing the vlan frame to the upper layer */
- if (sp->config.napi)
- vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
- else
- vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag);
- } else {
- if (sp->config.napi)
- netif_receive_skb(skb);
- else
- netif_rx(skb);
- }
+ if (vlan_tag && sp->vlan_strip_flag)
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
+ if (sp->config.napi)
+ netif_receive_skb(skb);
+ else
+ netif_rx(skb);
}
static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 800b3a44e653..d5596926a1ef 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -939,7 +939,6 @@ struct s2io_nic {
int task_flag;
unsigned long long start_time;
- struct vlan_group *vlgrp;
int vlan_strip_flag;
#define MSIX_FLG 0xA5
int num_entries;
@@ -968,8 +967,8 @@ struct s2io_nic {
u8 serial_num[VPD_STRING_LEN];
};
-#define RESET_ERROR 1;
-#define CMD_ERROR 2;
+#define RESET_ERROR 1
+#define CMD_ERROR 2
/* OS related system calls */
#ifndef readq
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 68d50429ddf3..ea65f7ec360a 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2597,7 +2597,7 @@ static int __devinit sbmac_probe(struct platform_device *pldev)
res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
BUG_ON(!res);
- sbm_base = ioremap_nocache(res->start, res->end - res->start + 1);
+ sbm_base = ioremap_nocache(res->start, resource_size(res));
if (!sbm_base) {
printk(KERN_ERR "%s: unable to map device registers\n",
dev_name(&pldev->dev));
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index fa74314ef789..9da47337b7c3 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -22,6 +22,7 @@
* matching, so you need to enable IFF_PROMISC when using it.
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig
index a65c98638398..a3d5bb9e39dc 100644
--- a/drivers/net/sfc/Kconfig
+++ b/drivers/net/sfc/Kconfig
@@ -1,5 +1,5 @@
config SFC
- tristate "Solarflare Solarstorm SFC4000/SFC9000-family support"
+ tristate "Solarflare SFC4000/SFC9000-family support"
depends on PCI && INET
select MDIO
select CRC32
@@ -7,13 +7,12 @@ config SFC
select I2C_ALGOBIT
help
This driver supports 10-gigabit Ethernet cards based on
- the Solarflare Communications Solarstorm SFC4000 and
- SFC9000-family controllers.
+ the Solarflare SFC4000 and SFC9000-family controllers.
To compile this driver as a module, choose M here. The module
will be called sfc.
config SFC_MTD
- bool "Solarflare Solarstorm SFC4000/SFC9000-family MTD support"
+ bool "Solarflare SFC4000/SFC9000-family MTD support"
depends on SFC && MTD && !(SFC=y && MTD=m)
default y
help
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index c914729f9554..faca764aa21b 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -229,8 +229,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
struct efx_nic *efx = channel->efx;
int spent;
- if (unlikely(efx->reset_pending != RESET_TYPE_NONE ||
- !channel->enabled))
+ if (unlikely(efx->reset_pending || !channel->enabled))
return 0;
spent = efx_nic_process_eventq(channel, budget);
@@ -1461,7 +1460,7 @@ static void efx_start_all(struct efx_nic *efx)
* reset_pending [modified from an atomic context], we instead guarantee
* that efx_mcdi_mode_poll() isn't reverted erroneously */
efx_mcdi_mode_event(efx);
- if (efx->reset_pending != RESET_TYPE_NONE)
+ if (efx->reset_pending)
efx_mcdi_mode_poll(efx);
/* Start the hardware monitor if there is one. Otherwise (we're link
@@ -2118,8 +2117,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
goto out;
}
- /* Allow resets to be rescheduled. */
- efx->reset_pending = RESET_TYPE_NONE;
+ /* Clear flags for the scopes we covered. We assume the NIC and
+ * driver are now quiescent so that there is no race here.
+ */
+ efx->reset_pending &= -(1 << (method + 1));
/* Reinitialise bus-mastering, which may have been turned off before
* the reset was scheduled. This is still appropriate, even in the
@@ -2154,12 +2155,13 @@ out:
static void efx_reset_work(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
+ unsigned long pending = ACCESS_ONCE(efx->reset_pending);
- if (efx->reset_pending == RESET_TYPE_NONE)
+ if (!pending)
return;
/* If we're not RUNNING then don't reset. Leave the reset_pending
- * flag set so that efx_pci_probe_main will be retried */
+ * flags set so that efx_pci_probe_main will be retried */
if (efx->state != STATE_RUNNING) {
netif_info(efx, drv, efx->net_dev,
"scheduled reset quenched. NIC not RUNNING\n");
@@ -2167,7 +2169,7 @@ static void efx_reset_work(struct work_struct *data)
}
rtnl_lock();
- (void)efx_reset(efx, efx->reset_pending);
+ (void)efx_reset(efx, fls(pending) - 1);
rtnl_unlock();
}
@@ -2175,40 +2177,24 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
{
enum reset_type method;
- if (efx->reset_pending != RESET_TYPE_NONE) {
- netif_info(efx, drv, efx->net_dev,
- "quenching already scheduled reset\n");
- return;
- }
-
switch (type) {
case RESET_TYPE_INVISIBLE:
case RESET_TYPE_ALL:
case RESET_TYPE_WORLD:
case RESET_TYPE_DISABLE:
method = type;
+ netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
+ RESET_TYPE(method));
break;
- case RESET_TYPE_RX_RECOVERY:
- case RESET_TYPE_RX_DESC_FETCH:
- case RESET_TYPE_TX_DESC_FETCH:
- case RESET_TYPE_TX_SKIP:
- method = RESET_TYPE_INVISIBLE;
- break;
- case RESET_TYPE_MC_FAILURE:
default:
- method = RESET_TYPE_ALL;
- break;
- }
-
- if (method != type)
+ method = efx->type->map_reset_reason(type);
netif_dbg(efx, drv, efx->net_dev,
"scheduling %s reset for %s\n",
RESET_TYPE(method), RESET_TYPE(type));
- else
- netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
- RESET_TYPE(method));
+ break;
+ }
- efx->reset_pending = method;
+ set_bit(method, &efx->reset_pending);
/* efx_process_channel() will no longer read events once a
* reset is scheduled. So switch back to poll'd MCDI completions. */
@@ -2288,7 +2274,6 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type,
efx->pci_dev = pci_dev;
efx->msg_enable = debug;
efx->state = STATE_INIT;
- efx->reset_pending = RESET_TYPE_NONE;
strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
efx->net_dev = net_dev;
@@ -2491,7 +2476,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
goto fail1;
netif_info(efx, probe, efx->net_dev,
- "Solarflare Communications NIC detected\n");
+ "Solarflare NIC detected\n");
/* Set up basic I/O (BAR mappings etc) */
rc = efx_init_io(efx);
@@ -2510,7 +2495,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
cancel_work_sync(&efx->reset_work);
if (rc == 0) {
- if (efx->reset_pending != RESET_TYPE_NONE) {
+ if (efx->reset_pending) {
/* If there was a scheduled reset during
* probe, the NIC is probably hosed anyway */
efx_pci_remove_main(efx);
@@ -2521,11 +2506,12 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
}
/* Retry if a recoverably reset event has been scheduled */
- if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
- (efx->reset_pending != RESET_TYPE_ALL))
+ if (efx->reset_pending &
+ ~(1 << RESET_TYPE_INVISIBLE | 1 << RESET_TYPE_ALL) ||
+ !efx->reset_pending)
goto fail3;
- efx->reset_pending = RESET_TYPE_NONE;
+ efx->reset_pending = 0;
}
if (rc) {
@@ -2609,7 +2595,7 @@ static int efx_pm_poweroff(struct device *dev)
efx->type->fini(efx);
- efx->reset_pending = RESET_TYPE_NONE;
+ efx->reset_pending = 0;
pci_save_state(pci_dev);
return pci_set_power_state(pci_dev, PCI_D3hot);
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h
index 384cfe3b1be1..d725a8fbe1a6 100644
--- a/drivers/net/sfc/enum.h
+++ b/drivers/net/sfc/enum.h
@@ -134,6 +134,8 @@ enum efx_loopback_mode {
* other valuesspecify reasons, which efx_schedule_reset() will choose
* a method for.
*
+ * Reset methods are numbered in order of increasing scope.
+ *
* @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts
* @RESET_TYPE_ALL: reset everything but PCI core blocks
* @RESET_TYPE_WORLD: reset everything, save & restore PCI config
@@ -147,7 +149,6 @@ enum efx_loopback_mode {
* @RESET_TYPE_MC_FAILURE: MC reboot/assertion
*/
enum reset_type {
- RESET_TYPE_NONE = -1,
RESET_TYPE_INVISIBLE = 0,
RESET_TYPE_ALL = 1,
RESET_TYPE_WORLD = 2,
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index d229027dc363..bc4643af6dd1 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -796,30 +796,13 @@ static int efx_ethtool_set_wol(struct net_device *net_dev,
static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
{
struct efx_nic *efx = netdev_priv(net_dev);
- enum reset_type method;
- enum {
- ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER |
- ETH_RESET_OFFLOAD | ETH_RESET_MAC)
- };
-
- /* Check for minimal reset flags */
- if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE)
- return -EINVAL;
- *flags ^= ETH_RESET_EFX_INVISIBLE;
- method = RESET_TYPE_INVISIBLE;
-
- if (*flags & ETH_RESET_PHY) {
- *flags ^= ETH_RESET_PHY;
- method = RESET_TYPE_ALL;
- }
+ int rc;
- if ((*flags & efx->type->reset_world_flags) ==
- efx->type->reset_world_flags) {
- *flags ^= efx->type->reset_world_flags;
- method = RESET_TYPE_WORLD;
- }
+ rc = efx->type->map_reset_flags(flags);
+ if (rc < 0)
+ return rc;
- return efx_reset(efx, method);
+ return efx_reset(efx, rc);
}
static int
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 60176e873d62..94bf4aaf984d 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -536,7 +536,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
efx_oword_t reg;
int link_speed, isolate;
- isolate = (efx->reset_pending != RESET_TYPE_NONE);
+ isolate = !!ACCESS_ONCE(efx->reset_pending);
switch (link_state->speed) {
case 10000: link_speed = 3; break;
@@ -1051,6 +1051,49 @@ static int falcon_b0_test_registers(struct efx_nic *efx)
**************************************************************************
*/
+static enum reset_type falcon_map_reset_reason(enum reset_type reason)
+{
+ switch (reason) {
+ case RESET_TYPE_RX_RECOVERY:
+ case RESET_TYPE_RX_DESC_FETCH:
+ case RESET_TYPE_TX_DESC_FETCH:
+ case RESET_TYPE_TX_SKIP:
+ /* These can occasionally occur due to hardware bugs.
+ * We try to reset without disrupting the link.
+ */
+ return RESET_TYPE_INVISIBLE;
+ default:
+ return RESET_TYPE_ALL;
+ }
+}
+
+static int falcon_map_reset_flags(u32 *flags)
+{
+ enum {
+ FALCON_RESET_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER |
+ ETH_RESET_OFFLOAD | ETH_RESET_MAC),
+ FALCON_RESET_ALL = FALCON_RESET_INVISIBLE | ETH_RESET_PHY,
+ FALCON_RESET_WORLD = FALCON_RESET_ALL | ETH_RESET_IRQ,
+ };
+
+ if ((*flags & FALCON_RESET_WORLD) == FALCON_RESET_WORLD) {
+ *flags &= ~FALCON_RESET_WORLD;
+ return RESET_TYPE_WORLD;
+ }
+
+ if ((*flags & FALCON_RESET_ALL) == FALCON_RESET_ALL) {
+ *flags &= ~FALCON_RESET_ALL;
+ return RESET_TYPE_ALL;
+ }
+
+ if ((*flags & FALCON_RESET_INVISIBLE) == FALCON_RESET_INVISIBLE) {
+ *flags &= ~FALCON_RESET_INVISIBLE;
+ return RESET_TYPE_INVISIBLE;
+ }
+
+ return -EINVAL;
+}
+
/* Resets NIC to known state. This routine must be called in process
* context and is allowed to sleep. */
static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
@@ -1709,6 +1752,8 @@ const struct efx_nic_type falcon_a1_nic_type = {
.init = falcon_init_nic,
.fini = efx_port_dummy_op_void,
.monitor = falcon_monitor,
+ .map_reset_reason = falcon_map_reset_reason,
+ .map_reset_flags = falcon_map_reset_flags,
.reset = falcon_reset_hw,
.probe_port = falcon_probe_port,
.remove_port = falcon_remove_port,
@@ -1741,7 +1786,6 @@ const struct efx_nic_type falcon_a1_nic_type = {
.tx_dc_base = 0x130000,
.rx_dc_base = 0x100000,
.offload_features = NETIF_F_IP_CSUM,
- .reset_world_flags = ETH_RESET_IRQ,
};
const struct efx_nic_type falcon_b0_nic_type = {
@@ -1750,6 +1794,8 @@ const struct efx_nic_type falcon_b0_nic_type = {
.init = falcon_init_nic,
.fini = efx_port_dummy_op_void,
.monitor = falcon_monitor,
+ .map_reset_reason = falcon_map_reset_reason,
+ .map_reset_flags = falcon_map_reset_flags,
.reset = falcon_reset_hw,
.probe_port = falcon_probe_port,
.remove_port = falcon_remove_port,
@@ -1791,6 +1837,5 @@ const struct efx_nic_type falcon_b0_nic_type = {
.tx_dc_base = 0x130000,
.rx_dc_base = 0x100000,
.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
- .reset_world_flags = ETH_RESET_IRQ,
};
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
index 95a980fd63d5..2b9636f96e05 100644
--- a/drivers/net/sfc/filter.c
+++ b/drivers/net/sfc/filter.c
@@ -335,28 +335,35 @@ static int efx_filter_search(struct efx_filter_table *table,
bool for_insert, int *depth_required)
{
unsigned hash, incr, filter_idx, depth, depth_max;
- struct efx_filter_spec *cmp;
hash = efx_filter_hash(key);
incr = efx_filter_increment(key);
- depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ?
- FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX);
-
- for (depth = 1, filter_idx = hash & (table->size - 1);
- depth <= depth_max && test_bit(filter_idx, table->used_bitmap);
- ++depth) {
- cmp = &table->spec[filter_idx];
- if (efx_filter_equal(spec, cmp))
- goto found;
+
+ filter_idx = hash & (table->size - 1);
+ depth = 1;
+ depth_max = (for_insert ?
+ (spec->priority <= EFX_FILTER_PRI_HINT ?
+ FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX) :
+ table->search_depth[spec->type]);
+
+ for (;;) {
+ /* Return success if entry is used and matches this spec
+ * or entry is unused and we are trying to insert.
+ */
+ if (test_bit(filter_idx, table->used_bitmap) ?
+ efx_filter_equal(spec, &table->spec[filter_idx]) :
+ for_insert) {
+ *depth_required = depth;
+ return filter_idx;
+ }
+
+ /* Return failure if we reached the maximum search depth */
+ if (depth == depth_max)
+ return for_insert ? -EBUSY : -ENOENT;
+
filter_idx = (filter_idx + incr) & (table->size - 1);
+ ++depth;
}
- if (!for_insert)
- return -ENOENT;
- if (depth > depth_max)
- return -EBUSY;
-found:
- *depth_required = depth;
- return filter_idx;
}
/* Construct/deconstruct external filter IDs */
@@ -650,11 +657,11 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
return -EPROTONOSUPPORT;
/* RFS must validate the IP header length before calling us */
- EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + sizeof(*ip)));
+ EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
ip = (const struct iphdr *)(skb->data + nhoff);
- if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(ip))
return -EPROTONOSUPPORT;
- EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + 4 * ip->ihl + 4));
+ EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index e8d5f03a89fe..b8e251a1ee48 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -17,7 +17,6 @@
#define DEBUG
#endif
-#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -645,7 +644,7 @@ struct efx_filter_state;
* @irq_rx_moderation: IRQ moderation time for RX event queues
* @msg_enable: Log message enable flags
* @state: Device state flag. Serialised by the rtnl_lock.
- * @reset_pending: Pending reset method (normally RESET_TYPE_NONE)
+ * @reset_pending: Bitmask for pending resets
* @tx_queue: TX DMA queues
* @rx_queue: RX DMA queues
* @channel: Channels
@@ -728,7 +727,7 @@ struct efx_nic {
u32 msg_enable;
enum nic_state state;
- enum reset_type reset_pending;
+ unsigned long reset_pending;
struct efx_channel *channel[EFX_MAX_CHANNELS];
char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6];
@@ -828,6 +827,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @init: Initialise the controller
* @fini: Shut down the controller
* @monitor: Periodic function for polling link state and hardware monitor
+ * @map_reset_reason: Map ethtool reset reason to a reset method
+ * @map_reset_flags: Map ethtool reset flags to a reset method, if possible
* @reset: Reset the controller hardware and possibly the PHY. This will
* be called while the controller is uninitialised.
* @probe_port: Probe the MAC and PHY
@@ -865,8 +866,6 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @rx_dc_base: Base address in SRAM of RX queue descriptor caches
* @offload_features: net_device feature flags for protocol offload
* features implemented in hardware
- * @reset_world_flags: Flags for additional components covered by
- * reset method RESET_TYPE_WORLD
*/
struct efx_nic_type {
int (*probe)(struct efx_nic *efx);
@@ -874,6 +873,8 @@ struct efx_nic_type {
int (*init)(struct efx_nic *efx);
void (*fini)(struct efx_nic *efx);
void (*monitor)(struct efx_nic *efx);
+ enum reset_type (*map_reset_reason)(enum reset_type reason);
+ int (*map_reset_flags)(u32 *flags);
int (*reset)(struct efx_nic *efx, enum reset_type method);
int (*probe_port)(struct efx_nic *efx);
void (*remove_port)(struct efx_nic *efx);
@@ -908,7 +909,6 @@ struct efx_nic_type {
unsigned int tx_dc_base;
unsigned int rx_dc_base;
u32 offload_features;
- u32 reset_world_flags;
};
/**************************************************************************
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index f2a2b947f860..bafa23a6874c 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -10,6 +10,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/seq_file.h>
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index fb4721f780ff..5735e84c69de 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -177,6 +177,36 @@ static int siena_test_registers(struct efx_nic *efx)
**************************************************************************
*/
+static enum reset_type siena_map_reset_reason(enum reset_type reason)
+{
+ return RESET_TYPE_ALL;
+}
+
+static int siena_map_reset_flags(u32 *flags)
+{
+ enum {
+ SIENA_RESET_PORT = (ETH_RESET_DMA | ETH_RESET_FILTER |
+ ETH_RESET_OFFLOAD | ETH_RESET_MAC |
+ ETH_RESET_PHY),
+ SIENA_RESET_MC = (SIENA_RESET_PORT |
+ ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT),
+ };
+
+ if ((*flags & SIENA_RESET_MC) == SIENA_RESET_MC) {
+ *flags &= ~SIENA_RESET_MC;
+ return RESET_TYPE_WORLD;
+ }
+
+ if ((*flags & SIENA_RESET_PORT) == SIENA_RESET_PORT) {
+ *flags &= ~SIENA_RESET_PORT;
+ return RESET_TYPE_ALL;
+ }
+
+ /* no invisible reset implemented */
+
+ return -EINVAL;
+}
+
static int siena_reset_hw(struct efx_nic *efx, enum reset_type method)
{
int rc;
@@ -390,17 +420,16 @@ static void siena_remove_nic(struct efx_nic *efx)
efx->nic_data = NULL;
}
-#define STATS_GENERATION_INVALID ((u64)(-1))
+#define STATS_GENERATION_INVALID ((__force __le64)(-1))
static int siena_try_update_nic_stats(struct efx_nic *efx)
{
- u64 *dma_stats;
+ __le64 *dma_stats;
struct efx_mac_stats *mac_stats;
- u64 generation_start;
- u64 generation_end;
+ __le64 generation_start, generation_end;
mac_stats = &efx->mac_stats;
- dma_stats = (u64 *)efx->stats_buffer.addr;
+ dma_stats = efx->stats_buffer.addr;
generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
if (generation_end == STATS_GENERATION_INVALID)
@@ -408,7 +437,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
rmb();
#define MAC_STAT(M, D) \
- mac_stats->M = dma_stats[MC_CMD_MAC_ ## D]
+ mac_stats->M = le64_to_cpu(dma_stats[MC_CMD_MAC_ ## D])
MAC_STAT(tx_bytes, TX_BYTES);
MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
@@ -478,7 +507,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS);
mac_stats->rx_good_lt64 = 0;
- efx->n_rx_nodesc_drop_cnt = dma_stats[MC_CMD_MAC_RX_NODESC_DROPS];
+ efx->n_rx_nodesc_drop_cnt =
+ le64_to_cpu(dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]);
#undef MAC_STAT
@@ -507,7 +537,7 @@ static void siena_update_nic_stats(struct efx_nic *efx)
static void siena_start_nic_stats(struct efx_nic *efx)
{
- u64 *dma_stats = (u64 *)efx->stats_buffer.addr;
+ __le64 *dma_stats = efx->stats_buffer.addr;
dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID;
@@ -605,6 +635,8 @@ const struct efx_nic_type siena_a0_nic_type = {
.init = siena_init_nic,
.fini = efx_port_dummy_op_void,
.monitor = NULL,
+ .map_reset_reason = siena_map_reset_reason,
+ .map_reset_flags = siena_map_reset_flags,
.reset = siena_reset_hw,
.probe_port = siena_probe_port,
.remove_port = siena_remove_port,
@@ -641,5 +673,4 @@ const struct efx_nic_type siena_a0_nic_type = {
.rx_dc_base = 0x68000,
.offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_RXHASH | NETIF_F_NTUPLE),
- .reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT,
};
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 54415c7b84a2..52fb7ed9f365 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -6,6 +6,7 @@
#undef DEBUG
+#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 1f3f7b4dd638..ad35c210b839 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -33,7 +33,6 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/ethtool.h>
-#include <asm/cacheflush.h>
#include "sh_eth.h"
@@ -866,6 +865,8 @@ static int sh_eth_txfree(struct net_device *ndev)
break;
/* Free the original skb. */
if (mdp->tx_skbuff[entry]) {
+ dma_unmap_single(&ndev->dev, txdesc->addr,
+ txdesc->buffer_length, DMA_TO_DEVICE);
dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
mdp->tx_skbuff[entry] = NULL;
freeNum++;
@@ -1489,13 +1490,12 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
entry = mdp->cur_tx % TX_RING_SIZE;
mdp->tx_skbuff[entry] = skb;
txdesc = &mdp->tx_ring[entry];
- txdesc->addr = virt_to_phys(skb->data);
/* soft swap. */
if (!mdp->cd->hw_swap)
sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
skb->len + 2);
- /* write back */
- __flush_purge_region(skb->data, skb->len);
+ txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
if (skb->len < ETHERSMALL)
txdesc->buffer_length = ETHERSMALL;
else
@@ -1772,7 +1772,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
int ret, devno = 0;
struct resource *res;
struct net_device *ndev = NULL;
- struct sh_eth_private *mdp;
+ struct sh_eth_private *mdp = NULL;
struct sh_eth_plat_data *pd;
/* get base addr */
@@ -1890,7 +1890,7 @@ out_unregister:
out_release:
/* net_dev free */
- if (mdp->tsu_addr)
+ if (mdp && mdp->tsu_addr)
iounmap(mdp->tsu_addr);
if (ndev)
free_netdev(ndev);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b436e007eea0..8ad7bfbaa3af 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -21,6 +21,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 484f795a779d..658a1928fe79 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -482,7 +482,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
ret = -ENOMEM;
goto err_out_cleardev;
}
- sis_priv->tx_ring = (BufferDesc *)ring_space;
+ sis_priv->tx_ring = ring_space;
sis_priv->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pci_dev, RX_TOTAL_SIZE, &ring_dma);
@@ -490,7 +490,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
ret = -ENOMEM;
goto err_unmap_tx;
}
- sis_priv->rx_ring = (BufferDesc *)ring_space;
+ sis_priv->rx_ring = ring_space;
sis_priv->rx_ring_dma = ring_dma;
/* The SiS900-specific entries in the device structure. */
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index f4be5c78ebfd..98ec614c5690 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -50,7 +50,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "1.13"
+#define DRV_VERSION "1.14"
#define DEFAULT_TX_RING_SIZE 128
#define DEFAULT_RX_RING_SIZE 512
@@ -83,17 +83,20 @@ module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940) },
- { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
- { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
- { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
- { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T) },
- { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* DGE-530T */
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
- { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
- { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 },
+ { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) }, /* 3Com 3C940 */
+ { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) }, /* 3Com 3C940B */
+#ifdef CONFIG_SKGE_GENESIS
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4300) }, /* SK-9xx */
+#endif
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* D-Link DGE-530T (rev.B) */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) }, /* D-Link DGE-530T */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) }, /* D-Link DGE-530T Rev C1 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, /* Marvell Yukon 88E8001/8003/8010 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
+ { PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, /* CNet PowerG-2000 */
+ { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, 0x1064) }, /* Linksys EG1064 v2 */
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 }, /* Linksys EG1032 v2 */
{ 0 }
};
MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -119,6 +122,15 @@ static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 };
+static inline bool is_genesis(const struct skge_hw *hw)
+{
+#ifdef CONFIG_SKGE_GENESIS
+ return hw->chip_id == CHIP_ID_GENESIS;
+#else
+ return false;
+#endif
+}
+
static int skge_get_regs_len(struct net_device *dev)
{
return 0x4000;
@@ -146,7 +158,7 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
/* Wake on Lan only supported on Yukon chips with rev 1 or above */
static u32 wol_supported(const struct skge_hw *hw)
{
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
return 0;
if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0)
@@ -270,7 +282,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw)
SUPPORTED_Autoneg |
SUPPORTED_TP);
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
supported &= ~(SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
@@ -433,7 +445,7 @@ static void skge_get_ethtool_stats(struct net_device *dev,
{
struct skge_port *skge = netdev_priv(dev);
- if (skge->hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(skge->hw))
genesis_get_stats(skge, data);
else
yukon_get_stats(skge, data);
@@ -448,7 +460,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev)
struct skge_port *skge = netdev_priv(dev);
u64 data[ARRAY_SIZE(skge_stats)];
- if (skge->hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(skge->hw))
genesis_get_stats(skge, data);
else
yukon_get_stats(skge, data);
@@ -589,7 +601,7 @@ static int skge_set_pauseparam(struct net_device *dev,
/* Chip internal frequency for clock calculations */
static inline u32 hwkhz(const struct skge_hw *hw)
{
- return (hw->chip_id == CHIP_ID_GENESIS) ? 53125 : 78125;
+ return is_genesis(hw) ? 53125 : 78125;
}
/* Chip HZ to microseconds */
@@ -674,7 +686,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
int port = skge->port;
spin_lock_bh(&hw->phy_lock);
- if (hw->chip_id == CHIP_ID_GENESIS) {
+ if (is_genesis(hw)) {
switch (mode) {
case LED_MODE_OFF:
if (hw->phy_type == SK_PHY_BCOM)
@@ -1053,7 +1065,6 @@ static void skge_link_down(struct skge_port *skge)
netif_info(skge, link, skge->netdev, "Link is down\n");
}
-
static void xm_link_down(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
@@ -1172,7 +1183,6 @@ static void genesis_reset(struct skge_hw *hw, int port)
xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF);
}
-
/* Convert mode to MII values */
static const u16 phy_pause_map[] = {
[FLOW_MODE_NONE] = 0,
@@ -2405,7 +2415,7 @@ static void skge_phy_reset(struct skge_port *skge)
netif_carrier_off(skge->netdev);
spin_lock_bh(&hw->phy_lock);
- if (hw->chip_id == CHIP_ID_GENESIS) {
+ if (is_genesis(hw)) {
genesis_reset(hw, port);
genesis_mac_init(hw, port);
} else {
@@ -2436,7 +2446,8 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG: {
u16 val = 0;
spin_lock_bh(&hw->phy_lock);
- if (hw->chip_id == CHIP_ID_GENESIS)
+
+ if (is_genesis(hw))
err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
else
err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
@@ -2447,7 +2458,7 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCSMIIREG:
spin_lock_bh(&hw->phy_lock);
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
data->val_in);
else
@@ -2559,7 +2570,7 @@ static int skge_up(struct net_device *dev)
/* Initialize MAC */
spin_lock_bh(&hw->phy_lock);
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
genesis_mac_init(hw, port);
else
yukon_mac_init(hw, port);
@@ -2621,7 +2632,7 @@ static int skge_down(struct net_device *dev)
netif_tx_disable(dev);
- if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
+ if (is_genesis(hw) && hw->phy_type == SK_PHY_XMAC)
del_timer_sync(&skge->link_timer);
napi_disable(&skge->napi);
@@ -2633,7 +2644,7 @@ static int skge_down(struct net_device *dev)
spin_unlock_irq(&hw->hw_lock);
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
genesis_stop(skge);
else
yukon_stop(skge);
@@ -2661,7 +2672,7 @@ static int skge_down(struct net_device *dev)
skge_rx_stop(hw, port);
- if (hw->chip_id == CHIP_ID_GENESIS) {
+ if (is_genesis(hw)) {
skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
} else {
@@ -2957,7 +2968,7 @@ static void yukon_set_multicast(struct net_device *dev)
static inline u16 phy_length(const struct skge_hw *hw, u32 status)
{
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
return status >> XMR_FS_LEN_SHIFT;
else
return status >> GMR_FS_LEN_SHIFT;
@@ -2965,7 +2976,7 @@ static inline u16 phy_length(const struct skge_hw *hw, u32 status)
static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
{
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0;
else
return (status & GMR_FS_ANY_ERR) ||
@@ -2975,9 +2986,8 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
static void skge_set_multicast(struct net_device *dev)
{
struct skge_port *skge = netdev_priv(dev);
- struct skge_hw *hw = skge->hw;
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(skge->hw))
genesis_set_multicast(dev);
else
yukon_set_multicast(dev);
@@ -3057,7 +3067,7 @@ error:
"rx err, slot %td control 0x%x status 0x%x\n",
e - skge->rx_ring.start, control, status);
- if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+ if (is_genesis(skge->hw)) {
if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
dev->stats.rx_length_errors++;
if (status & XMR_FS_FRA_ERR)
@@ -3171,7 +3181,7 @@ static void skge_mac_parity(struct skge_hw *hw, int port)
++dev->stats.tx_heartbeat_errors;
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
MFF_CLR_PERR);
else
@@ -3183,7 +3193,7 @@ static void skge_mac_parity(struct skge_hw *hw, int port)
static void skge_mac_intr(struct skge_hw *hw, int port)
{
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
genesis_mac_intr(hw, port);
else
yukon_mac_intr(hw, port);
@@ -3195,7 +3205,7 @@ static void skge_error_irq(struct skge_hw *hw)
struct pci_dev *pdev = hw->pdev;
u32 hwstatus = skge_read32(hw, B0_HWE_ISRC);
- if (hw->chip_id == CHIP_ID_GENESIS) {
+ if (is_genesis(hw)) {
/* clear xmac errors */
if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
@@ -3278,7 +3288,7 @@ static void skge_extirq(unsigned long arg)
struct skge_port *skge = netdev_priv(dev);
spin_lock(&hw->phy_lock);
- if (hw->chip_id != CHIP_ID_GENESIS)
+ if (!is_genesis(hw))
yukon_phy_intr(skge);
else if (hw->phy_type == SK_PHY_BCOM)
bcom_phy_intr(skge);
@@ -3397,7 +3407,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
xm_outaddr(hw, port, XM_SA, dev->dev_addr);
else {
gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
@@ -3473,6 +3483,7 @@ static int skge_reset(struct skge_hw *hw)
switch (hw->chip_id) {
case CHIP_ID_GENESIS:
+#ifdef CONFIG_SKGE_GENESIS
switch (hw->phy_type) {
case SK_PHY_XMAC:
hw->phy_addr = PHY_ADDR_XMAC;
@@ -3486,6 +3497,10 @@ static int skge_reset(struct skge_hw *hw)
return -EOPNOTSUPP;
}
break;
+#else
+ dev_err(&hw->pdev->dev, "Genesis chip detected but not configured\n");
+ return -EOPNOTSUPP;
+#endif
case CHIP_ID_YUKON:
case CHIP_ID_YUKON_LITE:
@@ -3508,7 +3523,7 @@ static int skge_reset(struct skge_hw *hw)
/* read the adapters RAM size */
t8 = skge_read8(hw, B2_E_0);
- if (hw->chip_id == CHIP_ID_GENESIS) {
+ if (is_genesis(hw)) {
if (t8 == 3) {
/* special case: 4 x 64k x 36, offset = 0x80000 */
hw->ram_size = 0x100000;
@@ -3523,10 +3538,10 @@ static int skge_reset(struct skge_hw *hw)
hw->intr_mask = IS_HW_ERR;
/* Use PHY IRQ for all but fiber based Genesis board */
- if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
+ if (!(is_genesis(hw) && hw->phy_type == SK_PHY_XMAC))
hw->intr_mask |= IS_EXT_REG;
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
genesis_init(hw);
else {
/* switch power to VCC (WA for VAUX problem) */
@@ -3591,7 +3606,7 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B0_IMSK, hw->intr_mask);
for (i = 0; i < hw->ports; i++) {
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (is_genesis(hw))
genesis_reset(hw, i);
else
yukon_reset(hw, i);
@@ -3802,9 +3817,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
skge->port = port;
/* Only used for Genesis XMAC */
- setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
-
- if (hw->chip_id != CHIP_ID_GENESIS) {
+ if (is_genesis(hw))
+ setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
+ else {
dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
NETIF_F_RXCSUM;
dev->features |= dev->hw_features;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 598bf7a1a55e..a2eb34115844 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -3,6 +3,7 @@
*/
#ifndef _SKGE_H
#define _SKGE_H
+#include <linux/interrupt.h>
/* PCI config registers */
#define PCI_DEV_REG1 0x40
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3ee41da130c2..57339da76326 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -32,6 +32,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
+#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/slab.h>
#include <net/ip.h>
@@ -49,7 +50,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.28"
+#define DRV_VERSION "1.29"
/*
* The Yukon II chipset takes 64 bit command blocks (called list elements)
@@ -364,6 +365,17 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec);
}
} else {
+ if (hw->chip_id >= CHIP_ID_YUKON_OPT) {
+ u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2);
+
+ /* enable PHY Reverse Auto-Negotiation */
+ ctrl2 |= 1u << 13;
+
+ /* Write PHY changes (SW-reset must follow) */
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2);
+ }
+
+
/* disable energy detect */
ctrl &= ~PHY_M_PC_EN_DET_MSK;
@@ -625,6 +637,63 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
if (ledover)
gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+ } else if (hw->chip_id == CHIP_ID_YUKON_PRM &&
+ (sky2_read8(hw, B2_MAC_CFG) & 0xf) == 0x7) {
+ int i;
+ /* This a phy register setup workaround copied from vendor driver. */
+ static const struct {
+ u16 reg, val;
+ } eee_afe[] = {
+ { 0x156, 0x58ce },
+ { 0x153, 0x99eb },
+ { 0x141, 0x8064 },
+ /* { 0x155, 0x130b },*/
+ { 0x000, 0x0000 },
+ { 0x151, 0x8433 },
+ { 0x14b, 0x8c44 },
+ { 0x14c, 0x0f90 },
+ { 0x14f, 0x39aa },
+ /* { 0x154, 0x2f39 },*/
+ { 0x14d, 0xba33 },
+ { 0x144, 0x0048 },
+ { 0x152, 0x2010 },
+ /* { 0x158, 0x1223 },*/
+ { 0x140, 0x4444 },
+ { 0x154, 0x2f3b },
+ { 0x158, 0xb203 },
+ { 0x157, 0x2029 },
+ };
+
+ /* Start Workaround for OptimaEEE Rev.Z0 */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fb);
+
+ gm_phy_write(hw, port, 1, 0x4099);
+ gm_phy_write(hw, port, 3, 0x1120);
+ gm_phy_write(hw, port, 11, 0x113c);
+ gm_phy_write(hw, port, 14, 0x8100);
+ gm_phy_write(hw, port, 15, 0x112a);
+ gm_phy_write(hw, port, 17, 0x1008);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fc);
+ gm_phy_write(hw, port, 1, 0x20b0);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff);
+
+ for (i = 0; i < ARRAY_SIZE(eee_afe); i++) {
+ /* apply AFE settings */
+ gm_phy_write(hw, port, 17, eee_afe[i].val);
+ gm_phy_write(hw, port, 16, eee_afe[i].reg | 1u<<13);
+ }
+
+ /* End Workaround for OptimaEEE */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+
+ /* Enable 10Base-Te (EEE) */
+ if (hw->chip_id >= CHIP_ID_YUKON_PRM) {
+ reg = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL,
+ reg | PHY_M_10B_TE_ENABLE);
+ }
}
/* Enable phy interrupt on auto-negotiation complete (or link up) */
@@ -713,6 +782,20 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
}
+/* configure IPG according to used link speed */
+static void sky2_set_ipg(struct sky2_port *sky2)
+{
+ u16 reg;
+
+ reg = gma_read16(sky2->hw, sky2->port, GM_SERIAL_MODE);
+ reg &= ~GM_SMOD_IPG_MSK;
+ if (sky2->speed > SPEED_100)
+ reg |= IPG_DATA_VAL(IPG_DATA_DEF_1000);
+ else
+ reg |= IPG_DATA_VAL(IPG_DATA_DEF_10_100);
+ gma_write16(sky2->hw, sky2->port, GM_SERIAL_MODE, reg);
+}
+
/* Enable Rx/Tx */
static void sky2_enable_rx_tx(struct sky2_port *sky2)
{
@@ -881,7 +964,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
/* serial mode register */
reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |
- GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+ GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF_1000);
if (hw->dev[port]->mtu > ETH_DATA_LEN)
reg |= GM_SMOD_JUMBO_ENA;
@@ -1361,13 +1444,14 @@ static inline unsigned sky2_rx_pad(const struct sky2_hw *hw)
* Allocate an skb for receiving. If the MTU is large enough
* make the skb non-linear with a fragment list of pages.
*/
-static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2)
+static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2, gfp_t gfp)
{
struct sk_buff *skb;
int i;
- skb = netdev_alloc_skb(sky2->netdev,
- sky2->rx_data_size + sky2_rx_pad(sky2->hw));
+ skb = __netdev_alloc_skb(sky2->netdev,
+ sky2->rx_data_size + sky2_rx_pad(sky2->hw),
+ gfp);
if (!skb)
goto nomem;
@@ -1385,7 +1469,7 @@ static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2)
skb_reserve(skb, NET_IP_ALIGN);
for (i = 0; i < sky2->rx_nfrags; i++) {
- struct page *page = alloc_page(GFP_ATOMIC);
+ struct page *page = alloc_page(gfp);
if (!page)
goto free_partial;
@@ -1415,7 +1499,7 @@ static int sky2_alloc_rx_skbs(struct sky2_port *sky2)
for (i = 0; i < sky2->rx_pending; i++) {
struct rx_ring_info *re = sky2->rx_ring + i;
- re->skb = sky2_rx_alloc(sky2);
+ re->skb = sky2_rx_alloc(sky2, GFP_KERNEL);
if (!re->skb)
return -ENOMEM;
@@ -1448,7 +1532,7 @@ static void sky2_rx_start(struct sky2_port *sky2)
sky2_qset(hw, rxq);
/* On PCI express lowering the watermark gives better performance */
- if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+ if (pci_is_pcie(hw->pdev))
sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX);
/* These chips have no ram buffer?
@@ -2051,6 +2135,8 @@ static void sky2_link_up(struct sky2_port *sky2)
[FC_BOTH] = "both",
};
+ sky2_set_ipg(sky2);
+
sky2_enable_rx_tx(sky2);
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
@@ -2288,8 +2374,11 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
dev->mtu = new_mtu;
netdev_update_features(dev);
- mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |
- GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+ mode = DATA_BLIND_VAL(DATA_BLIND_DEF) | GM_SMOD_VLAN_ENA;
+ if (sky2->speed > SPEED_100)
+ mode |= IPG_DATA_VAL(IPG_DATA_DEF_1000);
+ else
+ mode |= IPG_DATA_VAL(IPG_DATA_DEF_10_100);
if (dev->mtu > ETH_DATA_LEN)
mode |= GM_SMOD_JUMBO_ENA;
@@ -2383,7 +2472,7 @@ static struct sk_buff *receive_new(struct sky2_port *sky2,
struct rx_ring_info nre;
unsigned hdr_space = sky2->rx_data_size;
- nre.skb = sky2_rx_alloc(sky2);
+ nre.skb = sky2_rx_alloc(sky2, GFP_ATOMIC);
if (unlikely(!nre.skb))
goto nobuf;
@@ -2938,6 +3027,8 @@ static u32 sky2_mhz(const struct sky2_hw *hw)
case CHIP_ID_YUKON_SUPR:
case CHIP_ID_YUKON_UL_2:
case CHIP_ID_YUKON_OPT:
+ case CHIP_ID_YUKON_PRM:
+ case CHIP_ID_YUKON_OP_2:
return 125;
case CHIP_ID_YUKON_FE:
@@ -2994,7 +3085,8 @@ static int __devinit sky2_init(struct sky2_hw *hw)
hw->flags = SKY2_HW_GIGABIT
| SKY2_HW_NEWER_PHY
| SKY2_HW_NEW_LE
- | SKY2_HW_ADV_POWER_CTL;
+ | SKY2_HW_ADV_POWER_CTL
+ | SKY2_HW_RSS_CHKSUM;
/* New transmit checksum */
if (hw->chip_rev != CHIP_REV_YU_EX_B0)
@@ -3022,7 +3114,7 @@ static int __devinit sky2_init(struct sky2_hw *hw)
/* The workaround for status conflicts VLAN tag detection. */
if (hw->chip_rev == CHIP_REV_YU_FE2_A0)
- hw->flags |= SKY2_HW_VLAN_BROKEN;
+ hw->flags |= SKY2_HW_VLAN_BROKEN | SKY2_HW_RSS_CHKSUM;
break;
case CHIP_ID_YUKON_SUPR:
@@ -3031,6 +3123,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
| SKY2_HW_NEW_LE
| SKY2_HW_AUTO_TX_SUM
| SKY2_HW_ADV_POWER_CTL;
+
+ if (hw->chip_rev == CHIP_REV_YU_SU_A0)
+ hw->flags |= SKY2_HW_RSS_CHKSUM;
break;
case CHIP_ID_YUKON_UL_2:
@@ -3039,6 +3134,8 @@ static int __devinit sky2_init(struct sky2_hw *hw)
break;
case CHIP_ID_YUKON_OPT:
+ case CHIP_ID_YUKON_PRM:
+ case CHIP_ID_YUKON_OP_2:
hw->flags = SKY2_HW_GIGABIT
| SKY2_HW_NEW_LE
| SKY2_HW_ADV_POWER_CTL;
@@ -3071,7 +3168,7 @@ static void sky2_reset(struct sky2_hw *hw)
{
struct pci_dev *pdev = hw->pdev;
u16 status;
- int i, cap;
+ int i;
u32 hwe_mask = Y2_HWE_ALL_MASK;
/* disable ASF */
@@ -3107,8 +3204,7 @@ static void sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (cap) {
+ if (pci_is_pcie(pdev)) {
sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
0xfffffffful);
@@ -3139,30 +3235,33 @@ static void sky2_reset(struct sky2_hw *hw)
sky2_pci_write32(hw, PCI_DEV_REG3, P_CLK_MACSEC_DIS);
}
- if (hw->chip_id == CHIP_ID_YUKON_OPT) {
+ if (hw->chip_id == CHIP_ID_YUKON_OPT ||
+ hw->chip_id == CHIP_ID_YUKON_PRM ||
+ hw->chip_id == CHIP_ID_YUKON_OP_2) {
u16 reg;
u32 msk;
- if (hw->chip_rev == 0) {
+ if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) {
/* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */
sky2_write32(hw, Y2_PEX_PHY_DATA, (0x80UL << 16) | (1 << 7));
/* set PHY Link Detect Timer to 1.1 second (11x 100ms) */
reg = 10;
+
+ /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
+ sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));
} else {
/* set PHY Link Detect Timer to 0.4 second (4x 100ms) */
reg = 3;
}
reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE;
+ reg |= PSM_CONFIG_REG4_RST_PHY_LINK_DETECT;
/* reset PHY Link Detect */
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- sky2_pci_write16(hw, PSM_CONFIG_REG4,
- reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT);
sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
-
/* enable PHY Quick Link */
msk = sky2_read32(hw, B0_IMSK);
msk |= Y2_IS_PHY_QLNK;
@@ -3170,11 +3269,11 @@ static void sky2_reset(struct sky2_hw *hw)
/* check if PSMv2 was running before */
reg = sky2_pci_read16(hw, PSM_CONFIG_REG3);
- if (reg & PCI_EXP_LNKCTL_ASPMC) {
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (reg & PCI_EXP_LNKCTL_ASPMC)
/* restore the PCIe Link Control register */
- sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg);
- }
+ sky2_pci_write16(hw, pdev->pcie_cap + PCI_EXP_LNKCTL,
+ reg);
+
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
/* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
@@ -4175,8 +4274,18 @@ static u32 sky2_fix_features(struct net_device *dev, u32 features)
/* In order to do Jumbo packets on these chips, need to turn off the
* transmit store/forward. Therefore checksum offload won't work.
*/
- if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U)
+ if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ netdev_info(dev, "checksum offload not possible with jumbo frames\n");
features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM);
+ }
+
+ /* Some hardware requires receive checksum for RSS to work. */
+ if ( (features & NETIF_F_RXHASH) &&
+ !(features & NETIF_F_RXCSUM) &&
+ (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) {
+ netdev_info(dev, "receive hashing forces receive checksum\n");
+ features |= NETIF_F_RXCSUM;
+ }
return features;
}
@@ -4676,9 +4785,11 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
"UL 2", /* 0xba */
"Unknown", /* 0xbb */
"Optima", /* 0xbc */
+ "Optima Prime", /* 0xbd */
+ "Optima 2", /* 0xbe */
};
- if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OPT)
+ if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OP_2)
strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
else
snprintf(buf, sz, "(chip %#x)", chipid);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 318c9ae7bf91..0af31b8b5f10 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -412,7 +412,7 @@ enum {
Y2_IS_HW_ERR = 1<<31, /* Interrupt HW Error */
Y2_IS_STAT_BMU = 1<<30, /* Status BMU Interrupt */
Y2_IS_ASF = 1<<29, /* ASF subsystem Interrupt */
-
+ Y2_IS_CPU_TO = 1<<28, /* CPU Timeout */
Y2_IS_POLL_CHK = 1<<27, /* Check IRQ from polling unit */
Y2_IS_TWSI_RDY = 1<<26, /* IRQ on end of TWSI Tx */
Y2_IS_IRQ_SW = 1<<25, /* SW forced IRQ */
@@ -547,6 +547,8 @@ enum {
CHIP_ID_YUKON_SUPR = 0xb9, /* YUKON-2 Supreme */
CHIP_ID_YUKON_UL_2 = 0xba, /* YUKON-2 Ultra 2 */
CHIP_ID_YUKON_OPT = 0xbc, /* YUKON-2 Optima */
+ CHIP_ID_YUKON_PRM = 0xbd, /* YUKON-2 Optima Prime */
+ CHIP_ID_YUKON_OP_2 = 0xbe, /* YUKON-2 Optima 2 */
};
enum yukon_xl_rev {
@@ -1420,8 +1422,10 @@ enum {
PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */
PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */
- PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */};
+ PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */
+ PHY_M_10B_TE_ENABLE = 1<<7, /* 10Base-Te Enable (88E8079 and above) */
+};
#define PHY_M_EC_M_DSC(x) ((u16)(x)<<10 & PHY_M_EC_M_DSC_MSK)
/* 00=1x; 01=2x; 10=3x; 11=4x */
#define PHY_M_EC_S_DSC(x) ((u16)(x)<<8 & PHY_M_EC_S_DSC_MSK)
@@ -1807,10 +1811,11 @@ enum {
};
#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK)
-#define DATA_BLIND_DEF 0x04
-
#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
-#define IPG_DATA_DEF 0x1e
+
+#define DATA_BLIND_DEF 0x04
+#define IPG_DATA_DEF_1000 0x1e
+#define IPG_DATA_DEF_10_100 0x18
/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
enum {
@@ -2281,6 +2286,7 @@ struct sky2_hw {
#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
#define SKY2_HW_RSS_BROKEN 0x00000100
#define SKY2_HW_VLAN_BROKEN 0x00000200
+#define SKY2_HW_RSS_CHKSUM 0x00000400 /* RSS requires chksum */
u8 chip_id;
u8 chip_rev;
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
index ab9e3b785b5b..0a0a6643cf3a 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slhc.c
@@ -297,7 +297,7 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
lcs = cs;
cs = cs->next;
comp->sls_o_searches++;
- };
+ }
/*
* Didn't find it -- re-use oldest cstate. Send an
* uncompressed packet that tells the other side what
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 2f110fb30daa..f11b3f3df24f 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -194,8 +194,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu)
err_exit:
#ifdef SL_INCLUDE_CSLIP
kfree(cbuff);
- if (slcomp)
- slhc_free(slcomp);
+ slhc_free(slcomp);
#endif
kfree(xbuff);
kfree(rbuff);
@@ -248,7 +247,7 @@ static int sl_realloc_bufs(struct slip *sl, int mtu)
#else
if (xbuff == NULL || rbuff == NULL) {
#endif
- if (mtu >= sl->mtu) {
+ if (mtu > sl->mtu) {
printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n",
dev->name);
err = -ENOBUFS;
@@ -724,12 +723,10 @@ static void sl_sync(void)
static struct slip *sl_alloc(dev_t line)
{
int i;
+ char name[IFNAMSIZ];
struct net_device *dev = NULL;
struct slip *sl;
- if (slip_devs == NULL)
- return NULL; /* Master array missing ! */
-
for (i = 0; i < slip_maxdev; i++) {
dev = slip_devs[i];
if (dev == NULL)
@@ -739,25 +736,12 @@ static struct slip *sl_alloc(dev_t line)
if (i >= slip_maxdev)
return NULL;
- if (dev) {
- sl = netdev_priv(dev);
- if (test_bit(SLF_INUSE, &sl->flags)) {
- unregister_netdevice(dev);
- dev = NULL;
- slip_devs[i] = NULL;
- }
- }
-
- if (!dev) {
- char name[IFNAMSIZ];
- sprintf(name, "sl%d", i);
-
- dev = alloc_netdev(sizeof(*sl), name, sl_setup);
- if (!dev)
- return NULL;
- dev->base_addr = i;
- }
+ sprintf(name, "sl%d", i);
+ dev = alloc_netdev(sizeof(*sl), name, sl_setup);
+ if (!dev)
+ return NULL;
+ dev->base_addr = i;
sl = netdev_priv(dev);
/* Initialize channel control data */
@@ -823,7 +807,6 @@ static int slip_open(struct tty_struct *tty)
sl->tty = tty;
tty->disc_data = sl;
- sl->line = tty_devnum(tty);
sl->pid = current->pid;
if (!test_bit(SLF_INUSE, &sl->flags)) {
@@ -890,8 +873,6 @@ static void slip_close(struct tty_struct *tty)
tty->disc_data = NULL;
sl->tty = NULL;
- if (!sl->leased)
- sl->line = 0;
/* VSV = very important to remove timers */
#ifdef CONFIG_SLIP_SMART
diff --git a/drivers/net/slip.h b/drivers/net/slip.h
index 914e958abbfc..aa0764ce2342 100644
--- a/drivers/net/slip.h
+++ b/drivers/net/slip.h
@@ -90,7 +90,6 @@ struct slip {
unsigned char mode; /* SLIP mode */
unsigned char leased;
- dev_t line;
pid_t pid;
#define SL_MODE_SLIP 0
#define SL_MODE_CSLIP 1
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index d07c39cb4daf..34934fb23b97 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -42,6 +42,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 235a3c6c9f91..ba44ede29198 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -62,6 +62,7 @@ static const char version[] =
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/isapnp.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 053863aefb12..a91fe1723020 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -1351,11 +1351,6 @@ static void smc911x_set_multicast_list(struct net_device *dev)
netdev_for_each_mc_addr(ha, dev) {
u32 position;
- /* make sure this is a multicast address -
- shouldn't this be a given if we have it here ? */
- if (!(*ha->addr & 1))
- continue;
-
/* upper 6 bits are used as hash index */
position = ether_crc(ETH_ALEN, ha->addr)>>26;
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index 7486d0908064..5b65ac4b3cef 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -447,11 +447,6 @@ static void smc_setmulticast(int ioaddr, struct net_device *dev)
netdev_for_each_mc_addr(ha, dev) {
int position;
- /* make sure this is a multicast address - shouldn't this
- be a given if we have it here ? */
- if (!(*ha->addr & 1))
- continue;
-
/* only use the low order bits */
position = ether_crc_le(6, ha->addr) & 0x3f;
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index f6285748bd3c..2b1d254d59af 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1425,11 +1425,6 @@ static void smc_set_multicast_list(struct net_device *dev)
netdev_for_each_mc_addr(ha, dev) {
int position;
- /* make sure this is a multicast address -
- shouldn't this be a given if we have it here ? */
- if (!(*ha->addr & 1))
- continue;
-
/* only use the low order bits */
position = crc32_le(~0, ha->addr, 6) & 0x3f;
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index c6d47d10590c..b9016a30cdc5 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -37,6 +37,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -1473,6 +1474,7 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
freespace -= (skb->len + 32);
+ skb_tx_timestamp(skb);
dev_kfree_skb(skb);
if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 4c92ad8be765..459726f54754 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -19,6 +19,7 @@
***************************************************************************
*/
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -1030,6 +1031,8 @@ static netdev_tx_t smsc9420_hard_start_xmit(struct sk_buff *skb,
pd->tx_ring[index].status = TDES0_OWN_;
wmb();
+ skb_tx_timestamp(skb);
+
/* kick the DMA */
smsc9420_reg_write(pd, TX_POLL_DEMAND, 1);
smsc9420_pci_flush_write(pd);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 949f124e1278..1ff3491c8240 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -31,6 +31,7 @@
#include <linux/if_vlan.h>
#include <linux/in.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/gfp.h>
#include <linux/ioport.h>
#include <linux/ip.h>
@@ -1003,9 +1004,7 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
}
if (data_status & SPIDER_NET_VLAN_PACKET) {
- /* further enhancements: HW-accel VLAN
- * vlan_hwaccel_receive_skb
- */
+ /* further enhancements: HW-accel VLAN */
}
/* update netdevice statistics */
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 36045f3b0327..7ae1f990a98e 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -30,6 +30,7 @@
#define DRV_VERSION "2.1"
#define DRV_RELDATE "July 6, 2008"
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -560,7 +561,7 @@ struct netdev_private {
struct net_device *dev;
struct pci_dev *pci_dev;
#ifdef VLAN_SUPPORT
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
#endif
void *queue_mem;
dma_addr_t queue_mem_dma;
@@ -606,18 +607,6 @@ static const struct ethtool_ops ethtool_ops;
#ifdef VLAN_SUPPORT
-static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
- struct netdev_private *np = netdev_priv(dev);
-
- spin_lock(&np->lock);
- if (debug > 2)
- printk("%s: Setting vlgrp to %p\n", dev->name, grp);
- np->vlgrp = grp;
- set_rx_mode(dev);
- spin_unlock(&np->lock);
-}
-
static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct netdev_private *np = netdev_priv(dev);
@@ -625,6 +614,7 @@ static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
spin_lock(&np->lock);
if (debug > 1)
printk("%s: Adding vlanid %d to vlan filter\n", dev->name, vid);
+ set_bit(vid, np->active_vlans);
set_rx_mode(dev);
spin_unlock(&np->lock);
}
@@ -636,7 +626,7 @@ static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
spin_lock(&np->lock);
if (debug > 1)
printk("%s: removing vlanid %d from vlan filter\n", dev->name, vid);
- vlan_group_set_device(np->vlgrp, vid, NULL);
+ clear_bit(vid, np->active_vlans);
set_rx_mode(dev);
spin_unlock(&np->lock);
}
@@ -647,15 +637,14 @@ static const struct net_device_ops netdev_ops = {
.ndo_open = netdev_open,
.ndo_stop = netdev_close,
.ndo_start_xmit = start_tx,
- .ndo_tx_timeout = tx_timeout,
- .ndo_get_stats = get_stats,
+ .ndo_tx_timeout = tx_timeout,
+ .ndo_get_stats = get_stats,
.ndo_set_multicast_list = &set_rx_mode,
- .ndo_do_ioctl = netdev_ioctl,
+ .ndo_do_ioctl = netdev_ioctl,
.ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef VLAN_SUPPORT
- .ndo_vlan_rx_register = netdev_vlan_rx_register,
.ndo_vlan_rx_add_vid = netdev_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = netdev_vlan_rx_kill_vid,
#endif
@@ -1527,21 +1516,17 @@ static int __netdev_rx(struct net_device *dev, int *quota)
printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
}
#ifdef VLAN_SUPPORT
- if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
+ if (le16_to_cpu(desc->status2) & 0x0200) {
u16 vlid = le16_to_cpu(desc->vlanid);
if (debug > 4) {
printk(KERN_DEBUG " netdev_rx() vlanid = %d\n",
vlid);
}
- /*
- * vlan_hwaccel_rx expects a packet with the VLAN tag
- * stripped out.
- */
- vlan_hwaccel_rx(skb, np->vlgrp, vlid);
- } else
+ __vlan_hwaccel_put_tag(skb, vlid);
+ }
#endif /* VLAN_SUPPORT */
- netif_receive_skb(skb);
+ netif_receive_skb(skb);
dev->stats.rx_packets++;
next_rx:
@@ -1751,6 +1736,32 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return &dev->stats;
}
+#ifdef VLAN_SUPPORT
+static u32 set_vlan_mode(struct netdev_private *np)
+{
+ u32 ret = VlanMode;
+ u16 vid;
+ void __iomem *filter_addr = np->base + HashTable + 8;
+ int vlan_count = 0;
+
+ for_each_set_bit(vid, np->active_vlans, VLAN_N_VID) {
+ if (vlan_count == 32)
+ break;
+ writew(vid, filter_addr);
+ filter_addr += 16;
+ vlan_count++;
+ }
+ if (vlan_count == 32) {
+ ret |= PerfectFilterVlan;
+ while (vlan_count < 32) {
+ writew(0, filter_addr);
+ filter_addr += 16;
+ vlan_count++;
+ }
+ }
+ return ret;
+}
+#endif /* VLAN_SUPPORT */
static void set_rx_mode(struct net_device *dev)
{
@@ -1759,30 +1770,9 @@ static void set_rx_mode(struct net_device *dev)
u32 rx_mode = MinVLANPrio;
struct netdev_hw_addr *ha;
int i;
-#ifdef VLAN_SUPPORT
- rx_mode |= VlanMode;
- if (np->vlgrp) {
- int vlan_count = 0;
- void __iomem *filter_addr = ioaddr + HashTable + 8;
- for (i = 0; i < VLAN_VID_MASK; i++) {
- if (vlan_group_get_device(np->vlgrp, i)) {
- if (vlan_count >= 32)
- break;
- writew(i, filter_addr);
- filter_addr += 16;
- vlan_count++;
- }
- }
- if (i == VLAN_VID_MASK) {
- rx_mode |= PerfectFilterVlan;
- while (vlan_count < 32) {
- writew(0, filter_addr);
- filter_addr += 16;
- vlan_count++;
- }
- }
- }
+#ifdef VLAN_SUPPORT
+ rx_mode |= set_vlan_mode(np);
#endif /* VLAN_SUPPORT */
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index f20455cbfbbc..0f63b3c83c19 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -28,6 +28,7 @@
#include <linux/crc32.h>
#include <linux/slab.h>
+#include <asm/io.h>
#include "dwmac1000.h"
static void dwmac1000_core_init(void __iomem *ioaddr)
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index 2c47712d45d0..3dbeea619085 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -26,6 +26,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <asm/io.h>
#include "dwmac1000.h"
#include "dwmac_dma.h"
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index c724fc36a24f..743a58017637 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -29,6 +29,7 @@
*******************************************************************************/
#include <linux/crc32.h>
+#include <asm/io.h>
#include "dwmac100.h"
static void dwmac100_core_init(void __iomem *ioaddr)
diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/stmmac/dwmac100_dma.c
index e3e224b7d9e2..627f656b0f3c 100644
--- a/drivers/net/stmmac/dwmac100_dma.c
+++ b/drivers/net/stmmac/dwmac100_dma.c
@@ -28,6 +28,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <asm/io.h>
#include "dwmac100.h"
#include "dwmac_dma.h"
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index 2b076b313622..de1929b2641b 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -20,7 +20,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
-#define DRV_MODULE_VERSION "Nov_2010"
+#define DRV_MODULE_VERSION "July_2011"
#include <linux/stmmac.h>
#include "common.h"
@@ -56,14 +56,9 @@ struct stmmac_priv {
struct stmmac_extra_stats xstats;
struct napi_struct napi;
- phy_interface_t phy_interface;
- int phy_addr;
- int phy_mask;
- int (*phy_reset) (void *priv);
int rx_coe;
int no_csum_insertion;
- int phy_irq;
struct phy_device *phydev;
int oldlink;
int speed;
@@ -71,6 +66,7 @@ struct stmmac_priv {
unsigned int flow_ctrl;
unsigned int pause;
struct mii_bus *mii;
+ int mii_irq[PHY_MAX_ADDR];
u32 msg_enable;
spinlock_t lock;
@@ -79,9 +75,6 @@ struct stmmac_priv {
#ifdef CONFIG_STMMAC_TIMER
struct stmmac_timer *tm;
#endif
-#ifdef STMMAC_VLAN_TAG_USED
- struct vlan_group *vlgrp;
-#endif
struct plat_stmmacenet_data *plat;
};
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index ae5213a8c4cd..7ed8fb6c2117 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -24,8 +24,10 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <asm/io.h>
#include "stmmac.h"
#include "dwmac_dma.h"
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index e25e44a45c28..c6e567e04eff 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -49,7 +49,6 @@
#include "stmmac.h"
#define STMMAC_RESOURCE_NAME "stmmaceth"
-#define PHY_RESOURCE_NAME "stmmacphy"
#undef STMMAC_DEBUG
/*#define STMMAC_DEBUG*/
@@ -305,18 +304,13 @@ static int stmmac_init_phy(struct net_device *dev)
priv->speed = 0;
priv->oldduplex = -1;
- if (priv->phy_addr == -1) {
- /* We don't have a PHY, so do nothing */
- return 0;
- }
-
snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
- priv->phy_addr);
+ 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->phy_interface);
+ priv->plat->interface);
if (IS_ERR(phydev)) {
pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -335,7 +329,7 @@ static int stmmac_init_phy(struct net_device *dev)
return -ENODEV;
}
pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)"
- " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
+ " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
priv->phydev = phydev;
@@ -557,9 +551,11 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
*/
static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
{
- if (likely((priv->plat->tx_coe) && (!priv->no_csum_insertion))) {
- /* In case of GMAC, SF mode has to be enabled
- * to perform the TX COE. This depends on:
+ if (likely(priv->plat->force_sf_dma_mode ||
+ ((priv->plat->tx_coe) && (!priv->no_csum_insertion)))) {
+ /*
+ * In case of GMAC, SF mode can be enabled
+ * to perform the TX COE in HW. This depends on:
* 1) TX COE if actually supported
* 2) There is no bugged Jumbo frame support
* that needs to not insert csum in the TDES.
@@ -1045,6 +1041,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
len, DMA_TO_DEVICE);
priv->tx_skbuff[entry] = NULL;
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion);
+ wmb();
priv->hw->desc->set_tx_owner(desc);
}
@@ -1056,6 +1053,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
if (likely(priv->tm->enable))
priv->hw->desc->clear_tx_ic(desc);
#endif
+
+ wmb();
+
/* To avoid raise condition */
priv->hw->desc->set_tx_owner(first);
@@ -1079,6 +1079,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += skb->len;
+ skb_tx_timestamp(skb);
+
priv->hw->dma->enable_dma_transmission(priv->ioaddr);
return NETDEV_TX_OK;
@@ -1116,6 +1118,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
}
RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
}
+ wmb();
priv->hw->desc->set_rx_owner(p + entry);
}
}
@@ -1412,20 +1415,6 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return ret;
}
-#ifdef STMMAC_VLAN_TAG_USED
-static void stmmac_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
-
- DBG(probe, INFO, "%s: Setting vlgrp to %p\n", dev->name, grp);
-
- spin_lock(&priv->lock);
- priv->vlgrp = grp;
- spin_unlock(&priv->lock);
-}
-#endif
-
static const struct net_device_ops stmmac_netdev_ops = {
.ndo_open = stmmac_open,
.ndo_start_xmit = stmmac_xmit,
@@ -1436,9 +1425,6 @@ static const struct net_device_ops stmmac_netdev_ops = {
.ndo_tx_timeout = stmmac_tx_timeout,
.ndo_do_ioctl = stmmac_ioctl,
.ndo_set_config = stmmac_config,
-#ifdef STMMAC_VLAN_TAG_USED
- .ndo_vlan_rx_register = stmmac_vlan_rx_register,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = stmmac_poll_controller,
#endif
@@ -1536,71 +1522,6 @@ static int stmmac_mac_device_setup(struct net_device *dev)
return 0;
}
-static int stmmacphy_dvr_probe(struct platform_device *pdev)
-{
- struct plat_stmmacphy_data *plat_dat = pdev->dev.platform_data;
-
- pr_debug("stmmacphy_dvr_probe: added phy for bus %d\n",
- plat_dat->bus_id);
-
- return 0;
-}
-
-static int stmmacphy_dvr_remove(struct platform_device *pdev)
-{
- return 0;
-}
-
-static struct platform_driver stmmacphy_driver = {
- .driver = {
- .name = PHY_RESOURCE_NAME,
- },
- .probe = stmmacphy_dvr_probe,
- .remove = stmmacphy_dvr_remove,
-};
-
-/**
- * stmmac_associate_phy
- * @dev: pointer to device structure
- * @data: points to the private structure.
- * Description: Scans through all the PHYs we have registered and checks if
- * any are associated with our MAC. If so, then just fill in
- * the blanks in our local context structure
- */
-static int stmmac_associate_phy(struct device *dev, void *data)
-{
- struct stmmac_priv *priv = (struct stmmac_priv *)data;
- struct plat_stmmacphy_data *plat_dat = dev->platform_data;
-
- DBG(probe, DEBUG, "%s: checking phy for bus %d\n", __func__,
- plat_dat->bus_id);
-
- /* Check that this phy is for the MAC being initialised */
- if (priv->plat->bus_id != plat_dat->bus_id)
- return 0;
-
- /* OK, this PHY is connected to the MAC.
- Go ahead and get the parameters */
- DBG(probe, DEBUG, "%s: OK. Found PHY config\n", __func__);
- priv->phy_irq =
- platform_get_irq_byname(to_platform_device(dev), "phyirq");
- DBG(probe, DEBUG, "%s: PHY irq on bus %d is %d\n", __func__,
- plat_dat->bus_id, priv->phy_irq);
-
- /* Override with kernel parameters if supplied XXX CRS XXX
- * this needs to have multiple instances */
- if ((phyaddr >= 0) && (phyaddr <= 31))
- plat_dat->phy_addr = phyaddr;
-
- priv->phy_addr = plat_dat->phy_addr;
- priv->phy_mask = plat_dat->phy_mask;
- priv->phy_interface = plat_dat->interface;
- priv->phy_reset = plat_dat->phy_reset;
-
- DBG(probe, DEBUG, "%s: exiting\n", __func__);
- return 1; /* forces exit of driver_for_each_device() */
-}
-
/**
* stmmac_dvr_probe
* @pdev: platform device pointer
@@ -1691,14 +1612,10 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
if (ret < 0)
goto out_plat_exit;
- /* associate a PHY - it is provided by another platform bus */
- if (!driver_for_each_device
- (&(stmmacphy_driver.driver), NULL, (void *)priv,
- stmmac_associate_phy)) {
- pr_err("No PHY device is associated with this MAC!\n");
- ret = -ENODEV;
- goto out_unregister;
- }
+ /* Override with kernel parameters if supplied XXX CRS XXX
+ * this needs to have multiple instances */
+ if ((phyaddr >= 0) && (phyaddr <= 31))
+ priv->plat->phy_addr = phyaddr;
pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
"\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
@@ -1898,11 +1815,6 @@ static int __init stmmac_init_module(void)
{
int ret;
- if (platform_driver_register(&stmmacphy_driver)) {
- pr_err("No PHY devices registered!\n");
- return -ENODEV;
- }
-
ret = platform_driver_register(&stmmac_driver);
return ret;
}
@@ -1913,7 +1825,6 @@ static int __init stmmac_init_module(void)
*/
static void __exit stmmac_cleanup_module(void)
{
- platform_driver_unregister(&stmmacphy_driver);
platform_driver_unregister(&stmmac_driver);
}
@@ -1925,33 +1836,52 @@ static int __init stmmac_cmdline_opt(char *str)
if (!str || !*str)
return -EINVAL;
while ((opt = strsep(&str, ",")) != NULL) {
- if (!strncmp(opt, "debug:", 6))
- strict_strtoul(opt + 6, 0, (unsigned long *)&debug);
- else if (!strncmp(opt, "phyaddr:", 8))
- strict_strtoul(opt + 8, 0, (unsigned long *)&phyaddr);
- else if (!strncmp(opt, "dma_txsize:", 11))
- strict_strtoul(opt + 11, 0,
- (unsigned long *)&dma_txsize);
- else if (!strncmp(opt, "dma_rxsize:", 11))
- strict_strtoul(opt + 11, 0,
- (unsigned long *)&dma_rxsize);
- else if (!strncmp(opt, "buf_sz:", 7))
- strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz);
- else if (!strncmp(opt, "tc:", 3))
- strict_strtoul(opt + 3, 0, (unsigned long *)&tc);
- else if (!strncmp(opt, "watchdog:", 9))
- strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog);
- else if (!strncmp(opt, "flow_ctrl:", 10))
- strict_strtoul(opt + 10, 0,
- (unsigned long *)&flow_ctrl);
- else if (!strncmp(opt, "pause:", 6))
- strict_strtoul(opt + 6, 0, (unsigned long *)&pause);
+ if (!strncmp(opt, "debug:", 6)) {
+ if (strict_strtoul(opt + 6, 0, (unsigned long *)&debug))
+ goto err;
+ } else if (!strncmp(opt, "phyaddr:", 8)) {
+ if (strict_strtoul(opt + 8, 0,
+ (unsigned long *)&phyaddr))
+ goto err;
+ } else if (!strncmp(opt, "dma_txsize:", 11)) {
+ if (strict_strtoul(opt + 11, 0,
+ (unsigned long *)&dma_txsize))
+ goto err;
+ } else if (!strncmp(opt, "dma_rxsize:", 11)) {
+ if (strict_strtoul(opt + 11, 0,
+ (unsigned long *)&dma_rxsize))
+ goto err;
+ } else if (!strncmp(opt, "buf_sz:", 7)) {
+ if (strict_strtoul(opt + 7, 0,
+ (unsigned long *)&buf_sz))
+ goto err;
+ } else if (!strncmp(opt, "tc:", 3)) {
+ if (strict_strtoul(opt + 3, 0, (unsigned long *)&tc))
+ goto err;
+ } else if (!strncmp(opt, "watchdog:", 9)) {
+ if (strict_strtoul(opt + 9, 0,
+ (unsigned long *)&watchdog))
+ goto err;
+ } else if (!strncmp(opt, "flow_ctrl:", 10)) {
+ if (strict_strtoul(opt + 10, 0,
+ (unsigned long *)&flow_ctrl))
+ goto err;
+ } else if (!strncmp(opt, "pause:", 6)) {
+ if (strict_strtoul(opt + 6, 0, (unsigned long *)&pause))
+ goto err;
#ifdef CONFIG_STMMAC_TIMER
- else if (!strncmp(opt, "tmrate:", 7))
- strict_strtoul(opt + 7, 0, (unsigned long *)&tmrate);
+ } else if (!strncmp(opt, "tmrate:", 7)) {
+ if (strict_strtoul(opt + 7, 0,
+ (unsigned long *)&tmrate))
+ goto err;
#endif
+ }
}
return 0;
+
+err:
+ pr_err("%s: ERROR broken module parameter conversion", __func__);
+ return -EINVAL;
}
__setup("stmmaceth=", stmmac_cmdline_opt);
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c
index 234b4068a1fc..9c3b9d5c3411 100644
--- a/drivers/net/stmmac/stmmac_mdio.c
+++ b/drivers/net/stmmac/stmmac_mdio.c
@@ -27,6 +27,7 @@
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/slab.h>
+#include <asm/io.h>
#include "stmmac.h"
@@ -112,9 +113,9 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
struct stmmac_priv *priv = netdev_priv(ndev);
unsigned int mii_address = priv->hw->mii.addr;
- if (priv->phy_reset) {
+ if (priv->plat->mdio_bus_data->phy_reset) {
pr_debug("stmmac_mdio_reset: calling phy_reset\n");
- priv->phy_reset(priv->plat->bsp_priv);
+ priv->plat->mdio_bus_data->phy_reset(priv->plat->bsp_priv);
}
/* This is a workaround for problems with the STE101P PHY.
@@ -137,30 +138,29 @@ int stmmac_mdio_register(struct net_device *ndev)
struct mii_bus *new_bus;
int *irqlist;
struct stmmac_priv *priv = netdev_priv(ndev);
+ struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
int addr, found;
+ if (!mdio_bus_data)
+ return 0;
+
new_bus = mdiobus_alloc();
if (new_bus == NULL)
return -ENOMEM;
- irqlist = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
- if (irqlist == NULL) {
- err = -ENOMEM;
- goto irqlist_alloc_fail;
- }
-
- /* Assign IRQ to phy at address phy_addr */
- if (priv->phy_addr != -1)
- irqlist[priv->phy_addr] = priv->phy_irq;
+ if (mdio_bus_data->irqs)
+ irqlist = mdio_bus_data->irqs;
+ else
+ irqlist = priv->mii_irq;
new_bus->name = "STMMAC MII Bus";
new_bus->read = &stmmac_mdio_read;
new_bus->write = &stmmac_mdio_write;
new_bus->reset = &stmmac_mdio_reset;
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", mdio_bus_data->bus_id);
new_bus->priv = ndev;
new_bus->irq = irqlist;
- new_bus->phy_mask = priv->phy_mask;
+ new_bus->phy_mask = mdio_bus_data->phy_mask;
new_bus->parent = priv->device;
err = mdiobus_register(new_bus);
if (err != 0) {
@@ -171,18 +171,50 @@ int stmmac_mdio_register(struct net_device *ndev)
priv->mii = new_bus;
found = 0;
- for (addr = 0; addr < 32; addr++) {
+ for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
struct phy_device *phydev = new_bus->phy_map[addr];
if (phydev) {
- if (priv->phy_addr == -1) {
- priv->phy_addr = addr;
- phydev->irq = priv->phy_irq;
- irqlist[addr] = priv->phy_irq;
+ int act = 0;
+ char irq_num[4];
+ char *irq_str;
+
+ /*
+ * If an IRQ was provided to be assigned after
+ * the bus probe, do it here.
+ */
+ if ((mdio_bus_data->irqs == NULL) &&
+ (mdio_bus_data->probed_phy_irq > 0)) {
+ irqlist[addr] = mdio_bus_data->probed_phy_irq;
+ phydev->irq = mdio_bus_data->probed_phy_irq;
}
- pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n",
- ndev->name, phydev->phy_id, addr,
- phydev->irq, dev_name(&phydev->dev),
- (addr == priv->phy_addr) ? " active" : "");
+
+ /*
+ * If we're going to bind the MAC to this PHY bus,
+ * and no PHY number was provided to the MAC,
+ * use the one probed here.
+ */
+ if ((priv->plat->bus_id == mdio_bus_data->bus_id) &&
+ (priv->plat->phy_addr == -1))
+ priv->plat->phy_addr = addr;
+
+ act = (priv->plat->bus_id == mdio_bus_data->bus_id) &&
+ (priv->plat->phy_addr == addr);
+ switch (phydev->irq) {
+ case PHY_POLL:
+ irq_str = "POLL";
+ break;
+ case PHY_IGNORE_INTERRUPT:
+ irq_str = "IGNORE";
+ break;
+ default:
+ sprintf(irq_num, "%d", phydev->irq);
+ irq_str = irq_num;
+ break;
+ }
+ pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
+ ndev->name, phydev->phy_id, addr,
+ irq_str, dev_name(&phydev->dev),
+ act ? " active" : "");
found = 1;
}
}
@@ -191,10 +223,9 @@ int stmmac_mdio_register(struct net_device *ndev)
pr_warning("%s: No PHY found\n", ndev->name);
return 0;
+
bus_register_fail:
- kfree(irqlist);
-irqlist_alloc_fail:
- kfree(new_bus);
+ mdiobus_free(new_bus);
return err;
}
@@ -209,7 +240,8 @@ int stmmac_mdio_unregister(struct net_device *ndev)
mdiobus_unregister(priv->mii);
priv->mii->priv = NULL;
- kfree(priv->mii);
+ mdiobus_free(priv->mii);
+ priv->mii = NULL;
return 0;
}
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index aa4765803a4c..297a4242106b 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -998,7 +998,6 @@ static void bigmac_set_multicast(struct net_device *dev)
struct bigmac *bp = netdev_priv(dev);
void __iomem *bregs = bp->bregs;
struct netdev_hw_addr *ha;
- char *addrs;
int i;
u32 tmp, crc;
@@ -1027,12 +1026,7 @@ static void bigmac_set_multicast(struct net_device *dev)
hash_table[i] = 0;
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (crc & 0xf);
}
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index ab5930099267..be745ae8f4e3 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -10,25 +10,6 @@
* NAPI and NETPOLL support
* (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
*
- * TODO:
- * - Now that the driver was significantly simplified, I need to rework
- * the locking. I'm sure we don't need _2_ spinlocks, and we probably
- * can avoid taking most of them for so long period of time (and schedule
- * instead). The main issues at this point are caused by the netdev layer
- * though:
- *
- * gem_change_mtu() and gem_set_multicast() are called with a read_lock()
- * help by net/core/dev.c, thus they can't schedule. That means they can't
- * call napi_disable() neither, thus force gem_poll() to keep a spinlock
- * where it could have been dropped. change_mtu especially would love also to
- * be able to msleep instead of horrid locked delays when resetting the HW,
- * but that read_lock() makes it impossible, unless I defer it's action to
- * the reset task, which means it'll be asynchronous (won't take effect until
- * the system schedules a bit).
- *
- * Also, it would probably be possible to also remove most of the long-life
- * locking in open/resume code path (gem_reinit_chip) by beeing more careful
- * about when we can start taking interrupts or get xmit() called...
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -57,7 +38,6 @@
#include <linux/workqueue.h>
#include <linux/if_vlan.h>
#include <linux/bitops.h>
-#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/gfp.h>
@@ -66,15 +46,14 @@
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
+#include <asm/prom.h>
#ifdef CONFIG_SPARC
#include <asm/idprom.h>
-#include <asm/prom.h>
#endif
#ifdef CONFIG_PPC_PMAC
#include <asm/pci-bridge.h>
-#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#endif
@@ -95,12 +74,11 @@
SUPPORTED_Pause | SUPPORTED_Autoneg)
#define DRV_NAME "sungem"
-#define DRV_VERSION "0.98"
-#define DRV_RELDATE "8/24/03"
-#define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
+#define DRV_VERSION "1.0"
+#define DRV_AUTHOR "David S. Miller <davem@redhat.com>"
static char version[] __devinitdata =
- DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+ DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n";
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver");
@@ -218,6 +196,7 @@ static inline void gem_disable_ints(struct gem *gp)
{
/* Disable all interrupts, including TXDONE */
writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+ (void)readl(gp->regs + GREG_IMASK); /* write posting */
}
static void gem_get_cell(struct gem *gp)
@@ -247,6 +226,29 @@ static void gem_put_cell(struct gem *gp)
#endif /* CONFIG_PPC_PMAC */
}
+static inline void gem_netif_stop(struct gem *gp)
+{
+ gp->dev->trans_start = jiffies; /* prevent tx timeout */
+ napi_disable(&gp->napi);
+ netif_tx_disable(gp->dev);
+}
+
+static inline void gem_netif_start(struct gem *gp)
+{
+ /* NOTE: unconditional netif_wake_queue is only
+ * appropriate so long as all callers are assured to
+ * have free tx slots.
+ */
+ netif_wake_queue(gp->dev);
+ napi_enable(&gp->napi);
+}
+
+static void gem_schedule_reset(struct gem *gp)
+{
+ gp->reset_task_pending = 1;
+ schedule_work(&gp->reset_task);
+}
+
static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
{
if (netif_msg_intr(gp))
@@ -604,56 +606,46 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
gp->dev->name);
dev->stats.rx_errors++;
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_PCS) {
if (gem_pcs_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_TXMAC) {
if (gem_txmac_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_RXMAC) {
if (gem_rxmac_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_MAC) {
if (gem_mac_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_MIF) {
if (gem_mif_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_PCIERR) {
if (gem_pci_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
return 0;
-
-do_reset:
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
-
- return 1;
}
static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_status)
{
int entry, limit;
- if (netif_msg_intr(gp))
- printk(KERN_DEBUG "%s: tx interrupt, gem_status: 0x%x\n",
- gp->dev->name, gem_status);
-
entry = gp->tx_old;
limit = ((gem_status & GREG_STAT_TXNR) >> GREG_STAT_TXNR_SHIFT);
while (entry != limit) {
@@ -697,13 +689,27 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st
}
dev->stats.tx_packets++;
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
}
gp->tx_old = entry;
- if (netif_queue_stopped(dev) &&
- TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
- netif_wake_queue(dev);
+ /* Need to make the tx_old update visible to gem_start_xmit()
+ * before checking for netif_queue_stopped(). Without the
+ * memory barrier, there is a small possibility that gem_start_xmit()
+ * will miss it and cause the queue to be stopped forever.
+ */
+ smp_mb();
+
+ if (unlikely(netif_queue_stopped(dev) &&
+ TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+
+ __netif_tx_lock(txq, smp_processor_id());
+ if (netif_queue_stopped(dev) &&
+ TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+ netif_wake_queue(dev);
+ __netif_tx_unlock(txq);
+ }
}
static __inline__ void gem_post_rxds(struct gem *gp, int limit)
@@ -736,6 +742,21 @@ static __inline__ void gem_post_rxds(struct gem *gp, int limit)
}
}
+#define ALIGNED_RX_SKB_ADDR(addr) \
+ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
+static __inline__ struct sk_buff *gem_alloc_skb(struct net_device *dev, int size,
+ gfp_t gfp_flags)
+{
+ struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
+
+ if (likely(skb)) {
+ unsigned long offset = ALIGNED_RX_SKB_ADDR(skb->data);
+ skb_reserve(skb, offset);
+ skb->dev = dev;
+ }
+ return skb;
+}
+
static int gem_rx(struct gem *gp, int work_to_do)
{
struct net_device *dev = gp->dev;
@@ -799,7 +820,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
if (len > RX_COPY_THRESHOLD) {
struct sk_buff *new_skb;
- new_skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+ new_skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
if (new_skb == NULL) {
drops++;
goto drop_it;
@@ -808,7 +829,6 @@ static int gem_rx(struct gem *gp, int work_to_do)
RX_BUF_ALLOC_SIZE(gp),
PCI_DMA_FROMDEVICE);
gp->rx_skbs[entry] = new_skb;
- new_skb->dev = gp->dev;
skb_put(new_skb, (gp->rx_buf_sz + RX_OFFSET));
rxd->buffer = cpu_to_le64(pci_map_page(gp->pdev,
virt_to_page(new_skb->data),
@@ -820,7 +840,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
/* Trim the original skb for the netif. */
skb_trim(skb, len);
} else {
- struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
+ struct sk_buff *copy_skb = netdev_alloc_skb(dev, len + 2);
if (copy_skb == NULL) {
drops++;
@@ -842,7 +862,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
skb->ip_summed = CHECKSUM_COMPLETE;
skb->protocol = eth_type_trans(skb, gp->dev);
- netif_receive_skb(skb);
+ napi_gro_receive(&gp->napi, skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
@@ -865,28 +885,32 @@ static int gem_poll(struct napi_struct *napi, int budget)
{
struct gem *gp = container_of(napi, struct gem, napi);
struct net_device *dev = gp->dev;
- unsigned long flags;
int work_done;
- /*
- * NAPI locking nightmare: See comment at head of driver
- */
- spin_lock_irqsave(&gp->lock, flags);
-
work_done = 0;
do {
/* Handle anomalies */
- if (gp->status & GREG_STAT_ABNORMAL) {
- if (gem_abnormal_irq(dev, gp, gp->status))
- break;
+ if (unlikely(gp->status & GREG_STAT_ABNORMAL)) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+ int reset;
+
+ /* We run the abnormal interrupt handling code with
+ * the Tx lock. It only resets the Rx portion of the
+ * chip, but we need to guard it against DMA being
+ * restarted by the link poll timer
+ */
+ __netif_tx_lock(txq, smp_processor_id());
+ reset = gem_abnormal_irq(dev, gp, gp->status);
+ __netif_tx_unlock(txq);
+ if (reset) {
+ gem_schedule_reset(gp);
+ napi_complete(napi);
+ return work_done;
+ }
}
/* Run TX completion thread */
- spin_lock(&gp->tx_lock);
gem_tx(dev, gp, gp->status);
- spin_unlock(&gp->tx_lock);
-
- spin_unlock_irqrestore(&gp->lock, flags);
/* Run RX thread. We don't use any locking here,
* code willing to do bad things - like cleaning the
@@ -898,16 +922,12 @@ static int gem_poll(struct napi_struct *napi, int budget)
if (work_done >= budget)
return work_done;
- spin_lock_irqsave(&gp->lock, flags);
-
gp->status = readl(gp->regs + GREG_STAT);
} while (gp->status & GREG_STAT_NAPI);
- __napi_complete(napi);
+ napi_complete(napi);
gem_enable_ints(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
-
return work_done;
}
@@ -915,32 +935,23 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- /* Swallow interrupts when shutting the chip down, though
- * that shouldn't happen, we should have done free_irq() at
- * this point...
- */
- if (!gp->running)
- return IRQ_HANDLED;
-
- spin_lock_irqsave(&gp->lock, flags);
if (napi_schedule_prep(&gp->napi)) {
u32 gem_status = readl(gp->regs + GREG_STAT);
- if (gem_status == 0) {
+ if (unlikely(gem_status == 0)) {
napi_enable(&gp->napi);
- spin_unlock_irqrestore(&gp->lock, flags);
return IRQ_NONE;
}
+ if (netif_msg_intr(gp))
+ printk(KERN_DEBUG "%s: gem_interrupt() gem_status: 0x%x\n",
+ gp->dev->name, gem_status);
+
gp->status = gem_status;
gem_disable_ints(gp);
__napi_schedule(&gp->napi);
}
- spin_unlock_irqrestore(&gp->lock, flags);
-
/* If polling was disabled at the time we received that
* interrupt, we may return IRQ_HANDLED here while we
* should return IRQ_NONE. No big deal...
@@ -951,10 +962,11 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void gem_poll_controller(struct net_device *dev)
{
- /* gem_interrupt is safe to reentrance so no need
- * to disable_irq here.
- */
- gem_interrupt(dev->irq, dev);
+ struct gem *gp = netdev_priv(dev);
+
+ disable_irq(gp->pdev->irq);
+ gem_interrupt(gp->pdev->irq, dev);
+ enable_irq(gp->pdev->irq);
}
#endif
@@ -963,10 +975,7 @@ static void gem_tx_timeout(struct net_device *dev)
struct gem *gp = netdev_priv(dev);
netdev_err(dev, "transmit timed out, resetting\n");
- if (!gp->running) {
- netdev_err(dev, "hrm.. hw not running !\n");
- return;
- }
+
netdev_err(dev, "TX_STATE[%08x:%08x:%08x]\n",
readl(gp->regs + TXDMA_CFG),
readl(gp->regs + MAC_TXSTAT),
@@ -976,14 +985,7 @@ static void gem_tx_timeout(struct net_device *dev)
readl(gp->regs + MAC_RXSTAT),
readl(gp->regs + MAC_RXCFG));
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ gem_schedule_reset(gp);
}
static __inline__ int gem_intme(int entry)
@@ -1001,7 +1003,6 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
struct gem *gp = netdev_priv(dev);
int entry;
u64 ctrl;
- unsigned long flags;
ctrl = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -1013,21 +1014,12 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
(csum_stuff_off << 21));
}
- if (!spin_trylock_irqsave(&gp->tx_lock, flags)) {
- /* Tell upper layer to requeue */
- return NETDEV_TX_LOCKED;
- }
- /* We raced with gem_do_stop() */
- if (!gp->running) {
- spin_unlock_irqrestore(&gp->tx_lock, flags);
- return NETDEV_TX_BUSY;
- }
-
- /* This is a hard error, log it. */
- if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
- netif_stop_queue(dev);
- spin_unlock_irqrestore(&gp->tx_lock, flags);
- netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+ if (unlikely(TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+ /* This is a hard error, log it. */
+ if (!netif_queue_stopped(dev)) {
+ netif_stop_queue(dev);
+ netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+ }
return NETDEV_TX_BUSY;
}
@@ -1104,17 +1096,23 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
}
gp->tx_new = entry;
- if (TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))
+ if (unlikely(TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev);
+ /* netif_stop_queue() must be done before checking
+ * checking tx index in TX_BUFFS_AVAIL() below, because
+ * in gem_tx(), we update tx_old before checking for
+ * netif_queue_stopped().
+ */
+ smp_mb();
+ if (TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+ netif_wake_queue(dev);
+ }
if (netif_msg_tx_queued(gp))
printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
dev->name, entry, skb->len);
mb();
writel(gp->tx_new, gp->regs + TXDMA_KICK);
- spin_unlock_irqrestore(&gp->tx_lock, flags);
-
- dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
return NETDEV_TX_OK;
}
@@ -1184,7 +1182,6 @@ static void gem_pcs_reinit_adv(struct gem *gp)
#define STOP_TRIES 32
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_reset(struct gem *gp)
{
int limit;
@@ -1213,7 +1210,6 @@ static void gem_reset(struct gem *gp)
gem_pcs_reinit_adv(gp);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_start_dma(struct gem *gp)
{
u32 val;
@@ -1236,8 +1232,7 @@ static void gem_start_dma(struct gem *gp)
writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
}
-/* Must be invoked under gp->lock and gp->tx_lock. DMA won't be
- * actually stopped before about 4ms tho ...
+/* DMA won't be actually stopped before about 4ms tho ...
*/
static void gem_stop_dma(struct gem *gp)
{
@@ -1259,7 +1254,6 @@ static void gem_stop_dma(struct gem *gp)
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
// XXX dbl check what that function should do when called on PCS PHY
static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
{
@@ -1319,7 +1313,7 @@ start_aneg:
/* If we are asleep, we don't try to actually setup the PHY, we
* just store the settings
*/
- if (gp->asleep) {
+ if (!netif_device_present(gp->dev)) {
gp->phy_mii.autoneg = gp->want_autoneg = autoneg;
gp->phy_mii.speed = speed;
gp->phy_mii.duplex = duplex;
@@ -1345,13 +1339,12 @@ non_mii:
/* A link-up condition has occurred, initialize and enable the
* rest of the chip.
- *
- * Must be invoked under gp->lock and gp->tx_lock.
*/
static int gem_set_link_modes(struct gem *gp)
{
- u32 val;
+ struct netdev_queue *txq = netdev_get_tx_queue(gp->dev, 0);
int full_duplex, speed, pause;
+ u32 val;
full_duplex = 0;
speed = SPEED_10;
@@ -1375,8 +1368,11 @@ static int gem_set_link_modes(struct gem *gp)
netif_info(gp, link, gp->dev, "Link is up at %d Mbps, %s-duplex\n",
speed, (full_duplex ? "full" : "half"));
- if (!gp->running)
- return 0;
+
+ /* We take the tx queue lock to avoid collisions between
+ * this code, the tx path and the NAPI-driven error path
+ */
+ __netif_tx_lock(txq, smp_processor_id());
val = (MAC_TXCFG_EIPG0 | MAC_TXCFG_NGU);
if (full_duplex) {
@@ -1425,18 +1421,6 @@ static int gem_set_link_modes(struct gem *gp)
pause = 1;
}
- if (netif_msg_link(gp)) {
- if (pause) {
- netdev_info(gp->dev,
- "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
- gp->rx_fifo_sz,
- gp->rx_pause_off,
- gp->rx_pause_on);
- } else {
- netdev_info(gp->dev, "Pause is disabled\n");
- }
- }
-
if (!full_duplex)
writel(512, gp->regs + MAC_STIME);
else
@@ -1450,10 +1434,23 @@ static int gem_set_link_modes(struct gem *gp)
gem_start_dma(gp);
+ __netif_tx_unlock(txq);
+
+ if (netif_msg_link(gp)) {
+ if (pause) {
+ netdev_info(gp->dev,
+ "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
+ gp->rx_fifo_sz,
+ gp->rx_pause_off,
+ gp->rx_pause_on);
+ } else {
+ netdev_info(gp->dev, "Pause is disabled\n");
+ }
+ }
+
return 0;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static int gem_mdio_link_not_up(struct gem *gp)
{
switch (gp->lstate) {
@@ -1501,20 +1498,12 @@ static int gem_mdio_link_not_up(struct gem *gp)
static void gem_link_timer(unsigned long data)
{
struct gem *gp = (struct gem *) data;
+ struct net_device *dev = gp->dev;
int restart_aneg = 0;
- if (gp->asleep)
- return;
-
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
- gem_get_cell(gp);
-
- /* If the reset task is still pending, we just
- * reschedule the link timer
- */
+ /* There's no point doing anything if we're going to be reset */
if (gp->reset_task_pending)
- goto restart;
+ return;
if (gp->phy_type == phy_serialink ||
gp->phy_type == phy_serdes) {
@@ -1528,7 +1517,7 @@ static void gem_link_timer(unsigned long data)
goto restart;
gp->lstate = link_up;
- netif_carrier_on(gp->dev);
+ netif_carrier_on(dev);
(void)gem_set_link_modes(gp);
}
goto restart;
@@ -1544,12 +1533,12 @@ static void gem_link_timer(unsigned long data)
gp->last_forced_speed = gp->phy_mii.speed;
gp->timer_ticks = 5;
if (netif_msg_link(gp))
- netdev_info(gp->dev,
+ netdev_info(dev,
"Got link after fallback, retrying autoneg once...\n");
gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising);
} else if (gp->lstate != link_up) {
gp->lstate = link_up;
- netif_carrier_on(gp->dev);
+ netif_carrier_on(dev);
if (gem_set_link_modes(gp))
restart_aneg = 1;
}
@@ -1559,11 +1548,11 @@ static void gem_link_timer(unsigned long data)
*/
if (gp->lstate == link_up) {
gp->lstate = link_down;
- netif_info(gp, link, gp->dev, "Link down\n");
- netif_carrier_off(gp->dev);
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
- restart_aneg = 1;
+ netif_info(gp, link, dev, "Link down\n");
+ netif_carrier_off(dev);
+ gem_schedule_reset(gp);
+ /* The reset task will restart the timer */
+ return;
} else if (++gp->timer_ticks > 10) {
if (found_mii_phy(gp))
restart_aneg = gem_mdio_link_not_up(gp);
@@ -1573,17 +1562,12 @@ static void gem_link_timer(unsigned long data)
}
if (restart_aneg) {
gem_begin_auto_negotiation(gp, NULL);
- goto out_unlock;
+ return;
}
restart:
mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
-out_unlock:
- gem_put_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_clean_rings(struct gem *gp)
{
struct gem_init_block *gb = gp->init_block;
@@ -1634,7 +1618,6 @@ static void gem_clean_rings(struct gem *gp)
}
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_rings(struct gem *gp)
{
struct gem_init_block *gb = gp->init_block;
@@ -1653,7 +1636,7 @@ static void gem_init_rings(struct gem *gp)
struct sk_buff *skb;
struct gem_rxd *rxd = &gb->rxd[i];
- skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+ skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_KERNEL);
if (!skb) {
rxd->buffer = 0;
rxd->status_word = 0;
@@ -1661,7 +1644,6 @@ static void gem_init_rings(struct gem *gp)
}
gp->rx_skbs[i] = skb;
- skb->dev = dev;
skb_put(skb, (gp->rx_buf_sz + RX_OFFSET));
dma_addr = pci_map_page(gp->pdev,
virt_to_page(skb->data),
@@ -1737,7 +1719,7 @@ static void gem_init_phy(struct gem *gp)
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1) {
- // XXX check for errors
+ /* Reset and detect MII PHY */
mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
/* Init PHY */
@@ -1753,13 +1735,15 @@ static void gem_init_phy(struct gem *gp)
gp->lstate = link_down;
netif_carrier_off(gp->dev);
- /* Can I advertise gigabit here ? I'd need BCM PHY docs... */
- spin_lock_irq(&gp->lock);
+ /* Print things out */
+ if (gp->phy_type == phy_mii_mdio0 ||
+ gp->phy_type == phy_mii_mdio1)
+ netdev_info(gp->dev, "Found %s PHY\n",
+ gp->phy_mii.def ? gp->phy_mii.def->name : "no");
+
gem_begin_auto_negotiation(gp, NULL);
- spin_unlock_irq(&gp->lock);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_dma(struct gem *gp)
{
u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1797,7 +1781,6 @@ static void gem_init_dma(struct gem *gp)
gp->regs + RXDMA_BLANK);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static u32 gem_setup_multicast(struct gem *gp)
{
u32 rxcfg = 0;
@@ -1818,12 +1801,7 @@ static u32 gem_setup_multicast(struct gem *gp)
memset(hash_table, 0, sizeof(hash_table));
netdev_for_each_mc_addr(ha, gp->dev) {
- char *addrs = ha->addr;
-
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc >>= 24;
hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
}
@@ -1835,7 +1813,6 @@ static u32 gem_setup_multicast(struct gem *gp)
return rxcfg;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_mac(struct gem *gp)
{
unsigned char *e = &gp->dev->dev_addr[0];
@@ -1918,7 +1895,6 @@ static void gem_init_mac(struct gem *gp)
writel(0, gp->regs + WOL_WAKECSR);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_pause_thresholds(struct gem *gp)
{
u32 cfg;
@@ -2079,7 +2055,6 @@ static int gem_check_invariants(struct gem *gp)
return 0;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_reinit_chip(struct gem *gp)
{
/* Reset the chip */
@@ -2100,11 +2075,9 @@ static void gem_reinit_chip(struct gem *gp)
}
-/* Must be invoked with no lock held. */
static void gem_stop_phy(struct gem *gp, int wol)
{
u32 mifcfg;
- unsigned long flags;
/* Let the chip settle down a bit, it seems that helps
* for sleep mode on some models
@@ -2150,15 +2123,9 @@ static void gem_stop_phy(struct gem *gp, int wol)
writel(0, gp->regs + RXDMA_CFG);
if (!wol) {
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
gem_reset(gp);
writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- /* No need to take the lock here */
if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
gp->phy_mii.def->ops->suspend(&gp->phy_mii);
@@ -2175,54 +2142,55 @@ static void gem_stop_phy(struct gem *gp, int wol)
}
}
-
static int gem_do_start(struct net_device *dev)
{
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ int rc;
/* Enable the cell */
gem_get_cell(gp);
- /* Init & setup chip hardware */
- gem_reinit_chip(gp);
-
- gp->running = 1;
-
- napi_enable(&gp->napi);
+ /* Make sure PCI access and bus master are enabled */
+ rc = pci_enable_device(gp->pdev);
+ if (rc) {
+ netdev_err(dev, "Failed to enable chip on PCI bus !\n");
- if (gp->lstate == link_up) {
- netif_carrier_on(gp->dev);
- gem_set_link_modes(gp);
+ /* Put cell and forget it for now, it will be considered as
+ * still asleep, a new sleep cycle may bring it back
+ */
+ gem_put_cell(gp);
+ return -ENXIO;
}
+ pci_set_master(gp->pdev);
- netif_wake_queue(gp->dev);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
+ /* Init & setup chip hardware */
+ gem_reinit_chip(gp);
- if (request_irq(gp->pdev->irq, gem_interrupt,
- IRQF_SHARED, dev->name, (void *)dev)) {
+ /* An interrupt might come in handy */
+ rc = request_irq(gp->pdev->irq, gem_interrupt,
+ IRQF_SHARED, dev->name, (void *)dev);
+ if (rc) {
netdev_err(dev, "failed to request irq !\n");
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
-
- napi_disable(&gp->napi);
-
- gp->running = 0;
gem_reset(gp);
gem_clean_rings(gp);
gem_put_cell(gp);
+ return rc;
+ }
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
+ /* Mark us as attached again if we come from resume(), this has
+ * no effect if we weren't detatched and needs to be done now.
+ */
+ netif_device_attach(dev);
- return -EAGAIN;
- }
+ /* Restart NAPI & queues */
+ gem_netif_start(gp);
+
+ /* Detect & init PHY, start autoneg etc... this will
+ * eventually result in starting DMA operations when
+ * the link is up
+ */
+ gem_init_phy(gp);
return 0;
}
@@ -2230,22 +2198,30 @@ static int gem_do_start(struct net_device *dev)
static void gem_do_stop(struct net_device *dev, int wol)
{
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
- gp->running = 0;
+ /* Stop NAPI and stop tx queue */
+ gem_netif_stop(gp);
- /* Stop netif queue */
- netif_stop_queue(dev);
-
- /* Make sure ints are disabled */
+ /* Make sure ints are disabled. We don't care about
+ * synchronizing as NAPI is disabled, thus a stray
+ * interrupt will do nothing bad (our irq handler
+ * just schedules NAPI)
+ */
gem_disable_ints(gp);
- /* We can drop the lock now */
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
+
+ /* We cannot cancel the reset task while holding the
+ * rtnl lock, we'd get an A->B / B->A deadlock stituation
+ * if we did. This is not an issue however as the reset
+ * task is synchronized vs. us (rtnl_lock) and will do
+ * nothing if the device is down or suspended. We do
+ * still clear reset_task_pending to avoid a spurrious
+ * reset later on in case we do resume before it gets
+ * scheduled.
+ */
+ gp->reset_task_pending = 0;
/* If we are going to sleep with WOL */
gem_stop_dma(gp);
@@ -2260,79 +2236,79 @@ static void gem_do_stop(struct net_device *dev, int wol)
/* No irq needed anymore */
free_irq(gp->pdev->irq, (void *) dev);
+ /* Shut the PHY down eventually and setup WOL */
+ gem_stop_phy(gp, wol);
+
+ /* Make sure bus master is disabled */
+ pci_disable_device(gp->pdev);
+
/* Cell not needed neither if no WOL */
- if (!wol) {
- spin_lock_irqsave(&gp->lock, flags);
+ if (!wol)
gem_put_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
- }
}
static void gem_reset_task(struct work_struct *work)
{
struct gem *gp = container_of(work, struct gem, reset_task);
- mutex_lock(&gp->pm_mutex);
+ /* Lock out the network stack (essentially shield ourselves
+ * against a racing open, close, control call, or suspend
+ */
+ rtnl_lock();
- if (gp->opened)
- napi_disable(&gp->napi);
+ /* Skip the reset task if suspended or closed, or if it's
+ * been cancelled by gem_do_stop (see comment there)
+ */
+ if (!netif_device_present(gp->dev) ||
+ !netif_running(gp->dev) ||
+ !gp->reset_task_pending) {
+ rtnl_unlock();
+ return;
+ }
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
- if (gp->running) {
- netif_stop_queue(gp->dev);
+ /* Stop NAPI and tx */
+ gem_netif_stop(gp);
- /* Reset the chip & rings */
- gem_reinit_chip(gp);
- if (gp->lstate == link_up)
- gem_set_link_modes(gp);
- netif_wake_queue(gp->dev);
- }
+ /* Reset the chip & rings */
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
- gp->reset_task_pending = 0;
+ /* Restart NAPI and Tx */
+ gem_netif_start(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ /* We are back ! */
+ gp->reset_task_pending = 0;
- if (gp->opened)
- napi_enable(&gp->napi);
+ /* If the link is not up, restart autoneg, else restart the
+ * polling timer
+ */
+ if (gp->lstate != link_up)
+ gem_begin_auto_negotiation(gp, NULL);
+ else
+ mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
- mutex_unlock(&gp->pm_mutex);
+ rtnl_unlock();
}
-
static int gem_open(struct net_device *dev)
{
- struct gem *gp = netdev_priv(dev);
- int rc = 0;
-
- mutex_lock(&gp->pm_mutex);
-
- /* We need the cell enabled */
- if (!gp->asleep)
- rc = gem_do_start(dev);
- gp->opened = (rc == 0);
-
- mutex_unlock(&gp->pm_mutex);
-
- return rc;
+ /* We allow open while suspended, we just do nothing,
+ * the chip will be initialized in resume()
+ */
+ if (netif_device_present(dev))
+ return gem_do_start(dev);
+ return 0;
}
static int gem_close(struct net_device *dev)
{
- struct gem *gp = netdev_priv(dev);
-
- mutex_lock(&gp->pm_mutex);
-
- napi_disable(&gp->napi);
-
- gp->opened = 0;
- if (!gp->asleep)
+ if (netif_device_present(dev))
gem_do_stop(dev, 0);
- mutex_unlock(&gp->pm_mutex);
-
return 0;
}
@@ -2341,59 +2317,35 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- mutex_lock(&gp->pm_mutex);
-
- netdev_info(dev, "suspending, WakeOnLan %s\n",
- (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
-
- /* Keep the cell enabled during the entire operation */
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
- gem_get_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
- /* If the driver is opened, we stop the MAC */
- if (gp->opened) {
- napi_disable(&gp->napi);
+ /* Lock the network stack first to avoid racing with open/close,
+ * reset task and setting calls
+ */
+ rtnl_lock();
- /* Stop traffic, mark us closed */
+ /* Not running, mark ourselves non-present, no need for
+ * a lock here
+ */
+ if (!netif_running(dev)) {
netif_device_detach(dev);
+ rtnl_unlock();
+ return 0;
+ }
+ netdev_info(dev, "suspending, WakeOnLan %s\n",
+ (gp->wake_on_lan && netif_running(dev)) ?
+ "enabled" : "disabled");
- /* Switch off MAC, remember WOL setting */
- gp->asleep_wol = gp->wake_on_lan;
- gem_do_stop(dev, gp->asleep_wol);
- } else
- gp->asleep_wol = 0;
-
- /* Mark us asleep */
- gp->asleep = 1;
- wmb();
-
- /* Stop the link timer */
- del_timer_sync(&gp->link_timer);
-
- /* Now we release the mutex to not block the reset task who
- * can take it too. We are marked asleep, so there will be no
- * conflict here
+ /* Tell the network stack we're gone. gem_do_stop() below will
+ * synchronize with TX, stop NAPI etc...
*/
- mutex_unlock(&gp->pm_mutex);
-
- /* Wait for the pending reset task to complete */
- flush_work_sync(&gp->reset_task);
+ netif_device_detach(dev);
- /* Shut the PHY down eventually and setup WOL */
- gem_stop_phy(gp, gp->asleep_wol);
+ /* Switch off chip, remember WOL setting */
+ gp->asleep_wol = gp->wake_on_lan;
+ gem_do_stop(dev, gp->asleep_wol);
- /* Make sure bus master is disabled */
- pci_disable_device(gp->pdev);
-
- /* Release the cell, no need to take a lock at this point since
- * nothing else can happen now
- */
- gem_put_cell(gp);
+ /* Unlock the network stack */
+ rtnl_unlock();
return 0;
}
@@ -2402,53 +2354,23 @@ static int gem_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
- netdev_info(dev, "resuming\n");
+ /* See locking comment in gem_suspend */
+ rtnl_lock();
- mutex_lock(&gp->pm_mutex);
-
- /* Keep the cell enabled during the entire operation, no need to
- * take a lock here tho since nothing else can happen while we are
- * marked asleep
+ /* Not running, mark ourselves present, no need for
+ * a lock here
*/
- gem_get_cell(gp);
-
- /* Make sure PCI access and bus master are enabled */
- if (pci_enable_device(gp->pdev)) {
- netdev_err(dev, "Can't re-enable chip !\n");
- /* Put cell and forget it for now, it will be considered as
- * still asleep, a new sleep cycle may bring it back
- */
- gem_put_cell(gp);
- mutex_unlock(&gp->pm_mutex);
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ rtnl_unlock();
return 0;
}
- pci_set_master(gp->pdev);
-
- /* Reset everything */
- gem_reset(gp);
- /* Mark us woken up */
- gp->asleep = 0;
- wmb();
-
- /* Bring the PHY back. Again, lock is useless at this point as
- * nothing can be happening until we restart the whole thing
+ /* Restart chip. If that fails there isn't much we can do, we
+ * leave things stopped.
*/
- gem_init_phy(gp);
-
- /* If we were opened, bring everything back */
- if (gp->opened) {
- /* Restart MAC */
- gem_do_start(dev);
-
- /* Re-attach net device */
- netif_device_attach(dev);
- }
-
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ gem_do_start(dev);
/* If we had WOL enabled, the cell clock was never turned off during
* sleep, so we end up beeing unbalanced. Fix that here
@@ -2456,15 +2378,8 @@ static int gem_resume(struct pci_dev *pdev)
if (gp->asleep_wol)
gem_put_cell(gp);
- /* This function doesn't need to hold the cell, it will be held if the
- * driver is open by gem_do_start().
- */
- gem_put_cell(gp);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- mutex_unlock(&gp->pm_mutex);
+ /* Unlock the network stack */
+ rtnl_unlock();
return 0;
}
@@ -2474,33 +2389,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
{
struct gem *gp = netdev_priv(dev);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
/* I have seen this being called while the PM was in progress,
- * so we shield against this
+ * so we shield against this. Let's also not poke at registers
+ * while the reset task is going on.
+ *
+ * TODO: Move stats collection elsewhere (link timer ?) and
+ * make this a nop to avoid all those synchro issues
*/
- if (gp->running) {
- dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
- writel(0, gp->regs + MAC_FCSERR);
+ if (!netif_device_present(dev) || !netif_running(dev))
+ goto bail;
- dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
- writel(0, gp->regs + MAC_AERR);
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ goto bail;
- dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
- writel(0, gp->regs + MAC_LERR);
+ dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
+ writel(0, gp->regs + MAC_FCSERR);
- dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
- dev->stats.collisions +=
- (readl(gp->regs + MAC_ECOLL) +
- readl(gp->regs + MAC_LCOLL));
- writel(0, gp->regs + MAC_ECOLL);
- writel(0, gp->regs + MAC_LCOLL);
- }
+ dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
+ writel(0, gp->regs + MAC_AERR);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
+ writel(0, gp->regs + MAC_LERR);
+ dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
+ dev->stats.collisions +=
+ (readl(gp->regs + MAC_ECOLL) + readl(gp->regs + MAC_LCOLL));
+ writel(0, gp->regs + MAC_ECOLL);
+ writel(0, gp->regs + MAC_LCOLL);
+ bail:
return &dev->stats;
}
@@ -2513,22 +2430,19 @@ static int gem_set_mac_address(struct net_device *dev, void *addr)
if (!is_valid_ether_addr(macaddr->sa_data))
return -EADDRNOTAVAIL;
- if (!netif_running(dev) || !netif_device_present(dev)) {
- /* We'll just catch it later when the
- * device is up'd or resumed.
- */
- memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+ memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+
+ /* We'll just catch it later when the device is up'd or resumed */
+ if (!netif_running(dev) || !netif_device_present(dev))
return 0;
- }
- mutex_lock(&gp->pm_mutex);
- memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
- if (gp->running) {
- writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
- writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
- writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
- }
- mutex_unlock(&gp->pm_mutex);
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ return 0;
+
+ writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
+ writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
+ writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
return 0;
}
@@ -2539,14 +2453,12 @@ static void gem_set_multicast(struct net_device *dev)
u32 rxcfg, rxcfg_new;
int limit = 10000;
+ if (!netif_running(dev) || !netif_device_present(dev))
+ return;
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
- if (!gp->running)
- goto bail;
-
- netif_stop_queue(dev);
+ /* Better safe than sorry... */
+ if (gp->reset_task_pending || WARN_ON(!gp->cell_enabled))
+ return;
rxcfg = readl(gp->regs + MAC_RXCFG);
rxcfg_new = gem_setup_multicast(gp);
@@ -2566,12 +2478,6 @@ static void gem_set_multicast(struct net_device *dev)
rxcfg |= rxcfg_new;
writel(rxcfg, gp->regs + MAC_RXCFG);
-
- netif_wake_queue(dev);
-
- bail:
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
}
/* Jumbo-grams don't seem to work :-( */
@@ -2589,26 +2495,21 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
return -EINVAL;
- if (!netif_running(dev) || !netif_device_present(dev)) {
- /* We'll just catch it later when the
- * device is up'd or resumed.
- */
- dev->mtu = new_mtu;
+ dev->mtu = new_mtu;
+
+ /* We'll just catch it later when the device is up'd or resumed */
+ if (!netif_running(dev) || !netif_device_present(dev))
return 0;
- }
- mutex_lock(&gp->pm_mutex);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
- dev->mtu = new_mtu;
- if (gp->running) {
- gem_reinit_chip(gp);
- if (gp->lstate == link_up)
- gem_set_link_modes(gp);
- }
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
- mutex_unlock(&gp->pm_mutex);
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ return 0;
+
+ gem_netif_stop(gp);
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
+ gem_netif_start(gp);
return 0;
}
@@ -2640,7 +2541,6 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->phy_address = 0; /* XXX fixed PHYAD */
/* Return current PHY settings */
- spin_lock_irq(&gp->lock);
cmd->autoneg = gp->want_autoneg;
ethtool_cmd_speed_set(cmd, gp->phy_mii.speed);
cmd->duplex = gp->phy_mii.duplex;
@@ -2652,7 +2552,6 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
*/
if (cmd->advertising == 0)
cmd->advertising = cmd->supported;
- spin_unlock_irq(&gp->lock);
} else { // XXX PCS ?
cmd->supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
@@ -2706,11 +2605,10 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
/* Apply settings and restart link process. */
- spin_lock_irq(&gp->lock);
- gem_get_cell(gp);
- gem_begin_auto_negotiation(gp, cmd);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ if (netif_device_present(gp->dev)) {
+ del_timer_sync(&gp->link_timer);
+ gem_begin_auto_negotiation(gp, cmd);
+ }
return 0;
}
@@ -2722,12 +2620,11 @@ static int gem_nway_reset(struct net_device *dev)
if (!gp->want_autoneg)
return -EINVAL;
- /* Restart link process. */
- spin_lock_irq(&gp->lock);
- gem_get_cell(gp);
- gem_begin_auto_negotiation(gp, NULL);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ /* Restart link process */
+ if (netif_device_present(gp->dev)) {
+ del_timer_sync(&gp->link_timer);
+ gem_begin_auto_negotiation(gp, NULL);
+ }
return 0;
}
@@ -2791,16 +2688,11 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct gem *gp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
int rc = -EOPNOTSUPP;
- unsigned long flags;
- /* Hold the PM mutex while doing ioctl's or we may collide
- * with power management.
+ /* For SIOCGMIIREG and SIOCSMIIREG the core checks for us that
+ * netif_device_present() is true and holds rtnl_lock for us
+ * so we have nothing to worry about
*/
- mutex_lock(&gp->pm_mutex);
-
- spin_lock_irqsave(&gp->lock, flags);
- gem_get_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
switch (cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
@@ -2808,32 +2700,17 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
/* Fallthrough... */
case SIOCGMIIREG: /* Read MII PHY register. */
- if (!gp->running)
- rc = -EAGAIN;
- else {
- data->val_out = __phy_read(gp, data->phy_id & 0x1f,
- data->reg_num & 0x1f);
- rc = 0;
- }
+ data->val_out = __phy_read(gp, data->phy_id & 0x1f,
+ data->reg_num & 0x1f);
+ rc = 0;
break;
case SIOCSMIIREG: /* Write MII PHY register. */
- if (!gp->running)
- rc = -EAGAIN;
- else {
- __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
- data->val_in);
- rc = 0;
- }
+ __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
+ data->val_in);
+ rc = 0;
break;
- };
-
- spin_lock_irqsave(&gp->lock, flags);
- gem_put_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- mutex_unlock(&gp->pm_mutex);
-
+ }
return rc;
}
@@ -2921,23 +2798,9 @@ static void gem_remove_one(struct pci_dev *pdev)
unregister_netdev(dev);
- /* Stop the link timer */
- del_timer_sync(&gp->link_timer);
-
- /* We shouldn't need any locking here */
- gem_get_cell(gp);
-
- /* Cancel reset task */
+ /* Ensure reset task is truely gone */
cancel_work_sync(&gp->reset_task);
- /* Shut the PHY down */
- gem_stop_phy(gp, 0);
-
- gem_put_cell(gp);
-
- /* Make sure bus master is disabled */
- pci_disable_device(gp->pdev);
-
/* Free resources */
pci_free_consistent(pdev,
sizeof(struct gem_init_block),
@@ -3043,10 +2906,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
gp->msg_enable = DEFAULT_MSG;
- spin_lock_init(&gp->lock);
- spin_lock_init(&gp->tx_lock);
- mutex_init(&gp->pm_mutex);
-
init_timer(&gp->link_timer);
gp->link_timer.function = gem_link_timer;
gp->link_timer.data = (unsigned long) gp;
@@ -3122,14 +2981,11 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
/* Set that now, in case PM kicks in now */
pci_set_drvdata(pdev, dev);
- /* Detect & init PHY, start autoneg, we release the cell now
- * too, it will be managed by whoever needs it
- */
- gem_init_phy(gp);
-
- spin_lock_irq(&gp->lock);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ /* We can do scatter/gather and HW checksum */
+ dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
+ dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+ if (pci_using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
/* Register with kernel */
if (register_netdev(dev)) {
@@ -3138,20 +2994,15 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
goto err_out_free_consistent;
}
+ /* Undo the get_cell with appropriate locking (we could use
+ * ndo_init/uninit but that would be even more clumsy imho)
+ */
+ rtnl_lock();
+ gem_put_cell(gp);
+ rtnl_unlock();
+
netdev_info(dev, "Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
dev->dev_addr);
-
- if (gp->phy_type == phy_mii_mdio0 ||
- gp->phy_type == phy_mii_mdio1)
- netdev_info(dev, "Found %s PHY\n",
- gp->phy_mii.def ? gp->phy_mii.def->name : "no");
-
- /* GEM can do it all... */
- dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
- dev->features |= dev->hw_features | NETIF_F_RXCSUM | NETIF_F_LLTX;
- if (pci_using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
return 0;
err_out_free_consistent:
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index d225077964e2..835ce1b3cb9f 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -973,23 +973,14 @@ enum link_state {
};
struct gem {
- spinlock_t lock;
- spinlock_t tx_lock;
void __iomem *regs;
int rx_new, rx_old;
int tx_new, tx_old;
unsigned int has_wol : 1; /* chip supports wake-on-lan */
- unsigned int asleep : 1; /* chip asleep, protected by pm_mutex */
unsigned int asleep_wol : 1; /* was asleep with WOL enabled */
- unsigned int opened : 1; /* driver opened, protected by pm_mutex */
- unsigned int running : 1; /* chip running, protected by lock */
- /* cell enable count, protected by lock */
int cell_enabled;
-
- struct mutex pm_mutex;
-
u32 msg_enable;
u32 status;
@@ -1033,20 +1024,4 @@ struct gem {
#define found_mii_phy(gp) ((gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) && \
gp->phy_mii.def && gp->phy_mii.def->ops)
-#define ALIGNED_RX_SKB_ADDR(addr) \
- ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
-static __inline__ struct sk_buff *gem_alloc_skb(int size,
- gfp_t gfp_flags)
-{
- struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
-
- if (skb) {
- int offset = (int) ALIGNED_RX_SKB_ADDR(skb->data);
- if (offset)
- skb_reserve(skb, offset);
- }
-
- return skb;
-}
-
#endif /* _SUNGEM_H */
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 30aad54b1b3a..856e05b9fba3 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1524,17 +1524,11 @@ static int happy_meal_init(struct happy_meal *hp)
} else if ((hp->dev->flags & IFF_PROMISC) == 0) {
u16 hash_table[4];
struct netdev_hw_addr *ha;
- char *addrs;
u32 crc;
memset(hash_table, 0, sizeof(hash_table));
netdev_for_each_mc_addr(ha, hp->dev) {
- addrs = ha->addr;
-
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (crc & 0xf);
}
@@ -2361,7 +2355,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
struct happy_meal *hp = netdev_priv(dev);
void __iomem *bregs = hp->bigmacregs;
struct netdev_hw_addr *ha;
- char *addrs;
u32 crc;
spin_lock_irq(&hp->happy_lock);
@@ -2379,12 +2372,7 @@ static void happy_meal_set_multicast(struct net_device *dev)
memset(hash_table, 0, sizeof(hash_table));
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- if (!(*addrs & 1))
- continue;
-
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (crc & 0xf);
}
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 32a5c7f63c43..06f2d4382dc4 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1170,7 +1170,6 @@ static void lance_load_multicast(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
struct netdev_hw_addr *ha;
- char *addrs;
u32 crc;
u32 val;
@@ -1195,12 +1194,7 @@ static void lance_load_multicast(struct net_device *dev)
/* Add addresses */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- /* multicast address? */
- if (!(*addrs & 1))
- continue;
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc = crc >> 26;
if (lp->pio_buffer) {
struct lance_init_block __iomem *ib = lp->init_block_iomem;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 18ecdc303751..209c7f8df003 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -628,7 +628,6 @@ static void qe_set_multicast(struct net_device *dev)
struct sunqe *qep = netdev_priv(dev);
struct netdev_hw_addr *ha;
u8 new_mconfig = qep->mconfig;
- char *addrs;
int i;
u32 crc;
@@ -651,11 +650,7 @@ static void qe_set_multicast(struct net_device *dev)
memset(hash_table, 0, sizeof(hash_table));
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
-
- if (!(*addrs & 1))
- continue;
- crc = ether_crc_le(6, addrs);
+ crc = ether_crc_le(6, ha->addr);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (crc & 0xf);
}
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 80fbee0d40af..749bbf18dc6a 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -742,22 +742,6 @@ static void bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
__bdx_vlan_rx_vid(ndev, vid, 0);
}
-/*
- * bdx_vlan_rx_register - kernel hook for adding VLAN group
- * @ndev network device
- * @grp VLAN group
- */
-static void
-bdx_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
-{
- struct bdx_priv *priv = netdev_priv(ndev);
-
- ENTER;
- DBG("device='%s', group='%p'\n", ndev->name, grp);
- priv->vlgrp = grp;
- RET();
-}
-
/**
* bdx_change_mtu - Change the Maximum Transfer Unit
* @netdev: network interface device structure
@@ -1146,21 +1130,15 @@ NETIF_RX_MUX(struct bdx_priv *priv, u32 rxd_val1, u16 rxd_vlan,
struct sk_buff *skb)
{
ENTER;
- DBG("rxdd->flags.bits.vtag=%d vlgrp=%p\n", GET_RXD_VTAG(rxd_val1),
- priv->vlgrp);
- if (priv->vlgrp && GET_RXD_VTAG(rxd_val1)) {
- DBG("%s: vlan rcv vlan '%x' vtag '%x', device name '%s'\n",
+ DBG("rxdd->flags.bits.vtag=%d\n", GET_RXD_VTAG(rxd_val1));
+ if (GET_RXD_VTAG(rxd_val1)) {
+ DBG("%s: vlan rcv vlan '%x' vtag '%x'\n",
priv->ndev->name,
GET_RXD_VLAN_ID(rxd_vlan),
- GET_RXD_VTAG(rxd_val1),
- vlan_group_get_device(priv->vlgrp,
- GET_RXD_VLAN_ID(rxd_vlan))->name);
- /* NAPI variant of receive functions */
- vlan_hwaccel_receive_skb(skb, priv->vlgrp,
- GET_RXD_VLAN_TCI(rxd_vlan));
- } else {
- netif_receive_skb(skb);
+ GET_RXD_VTAG(rxd_val1));
+ __vlan_hwaccel_put_tag(skb, GET_RXD_VLAN_TCI(rxd_vlan));
}
+ netif_receive_skb(skb);
}
static void bdx_recycle_skb(struct bdx_priv *priv, struct rxd_desc *rxdd)
@@ -1877,7 +1855,7 @@ static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size)
}
static const struct net_device_ops bdx_netdev_ops = {
- .ndo_open = bdx_open,
+ .ndo_open = bdx_open,
.ndo_stop = bdx_close,
.ndo_start_xmit = bdx_tx_transmit,
.ndo_validate_addr = eth_validate_addr,
@@ -1885,7 +1863,6 @@ static const struct net_device_ops bdx_netdev_ops = {
.ndo_set_multicast_list = bdx_setmulti,
.ndo_change_mtu = bdx_change_mtu,
.ndo_set_mac_address = bdx_set_mac,
- .ndo_vlan_rx_register = bdx_vlan_rx_register,
.ndo_vlan_rx_add_vid = bdx_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bdx_vlan_rx_kill_vid,
};
diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
index c5642fefc9e7..709ebd6e28b4 100644
--- a/drivers/net/tehuti.h
+++ b/drivers/net/tehuti.h
@@ -250,7 +250,6 @@ struct bdx_priv {
struct rxf_fifo rxf_fifo0;
struct rxdb *rxdb; /* rx dbs to store skb pointers */
int napi_stop;
- struct vlan_group *vlgrp;
/* Tx FIFOs: 1 for data desc, 1 for empty (acks) desc */
struct txd_fifo txd_fifo0;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index a1f9f9eef37d..803576568154 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/in.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -106,6 +107,8 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
NETIF_MSG_RX_ERR | \
NETIF_MSG_TX_ERR)
+#define TG3_GRC_LCLCTL_PWRSW_DELAY 100
+
/* length of time before we decide the hardware is borked,
* and dev->tx_timeout() should be called to fix the problem
*/
@@ -605,7 +608,7 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
static void tg3_ape_lock_init(struct tg3 *tp)
{
int i;
- u32 regbase;
+ u32 regbase, bit;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
regbase = TG3_APE_LOCK_GRANT;
@@ -613,20 +616,34 @@ static void tg3_ape_lock_init(struct tg3 *tp)
regbase = TG3_APE_PER_LOCK_GRANT;
/* Make sure the driver hasn't any stale locks. */
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
+ if (i == TG3_APE_LOCK_GPIO)
+ continue;
tg3_ape_write32(tp, regbase + 4 * i, APE_LOCK_GRANT_DRIVER);
+ }
+
+ /* Clear the correct bit of the GPIO lock too. */
+ if (!tp->pci_fn)
+ bit = APE_LOCK_GRANT_DRIVER;
+ else
+ bit = 1 << tp->pci_fn;
+
+ tg3_ape_write32(tp, regbase + 4 * TG3_APE_LOCK_GPIO, bit);
}
static int tg3_ape_lock(struct tg3 *tp, int locknum)
{
int i, off;
int ret = 0;
- u32 status, req, gnt;
+ u32 status, req, gnt, bit;
if (!tg3_flag(tp, ENABLE_APE))
return 0;
switch (locknum) {
+ case TG3_APE_LOCK_GPIO:
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ return 0;
case TG3_APE_LOCK_GRC:
case TG3_APE_LOCK_MEM:
break;
@@ -644,21 +661,24 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
off = 4 * locknum;
- tg3_ape_write32(tp, req + off, APE_LOCK_REQ_DRIVER);
+ if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
+ bit = APE_LOCK_REQ_DRIVER;
+ else
+ bit = 1 << tp->pci_fn;
+
+ tg3_ape_write32(tp, req + off, bit);
/* Wait for up to 1 millisecond to acquire lock. */
for (i = 0; i < 100; i++) {
status = tg3_ape_read32(tp, gnt + off);
- if (status == APE_LOCK_GRANT_DRIVER)
+ if (status == bit)
break;
udelay(10);
}
- if (status != APE_LOCK_GRANT_DRIVER) {
+ if (status != bit) {
/* Revoke the lock request. */
- tg3_ape_write32(tp, gnt + off,
- APE_LOCK_GRANT_DRIVER);
-
+ tg3_ape_write32(tp, gnt + off, bit);
ret = -EBUSY;
}
@@ -667,12 +687,15 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
static void tg3_ape_unlock(struct tg3 *tp, int locknum)
{
- u32 gnt;
+ u32 gnt, bit;
if (!tg3_flag(tp, ENABLE_APE))
return;
switch (locknum) {
+ case TG3_APE_LOCK_GPIO:
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ return;
case TG3_APE_LOCK_GRC:
case TG3_APE_LOCK_MEM:
break;
@@ -685,7 +708,12 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
else
gnt = TG3_APE_PER_LOCK_GRANT;
- tg3_ape_write32(tp, gnt + 4 * locknum, APE_LOCK_GRANT_DRIVER);
+ if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
+ bit = APE_LOCK_GRANT_DRIVER;
+ else
+ bit = 1 << tp->pci_fn;
+
+ tg3_ape_write32(tp, gnt + 4 * locknum, bit);
}
static void tg3_disable_ints(struct tg3 *tp)
@@ -860,7 +888,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
int ret;
if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
- (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+ (reg == MII_CTRL1000 || reg == MII_TG3_AUX_CTRL))
return 0;
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
@@ -1167,7 +1195,7 @@ static int tg3_mdio_init(struct tg3 *tp)
if (tg3_flag(tp, 5717_PLUS)) {
u32 is_serdes;
- tp->phy_addr = PCI_FUNC(tp->pdev->devfn) + 1;
+ tp->phy_addr = tp->pci_fn + 1;
if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
@@ -1830,6 +1858,12 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
}
if (!tp->setlpicnt) {
+ if (current_link_up == 1 &&
+ !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+ tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+ }
+
val = tr32(TG3_CPMU_EEE_MODE);
tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE);
}
@@ -1844,7 +1878,9 @@ static void tg3_phy_eee_enable(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
- tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0003);
+ val = MII_TG3_DSP_TAP26_ALNOKO |
+ MII_TG3_DSP_TAP26_RMRXSTO;
+ tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
}
@@ -1980,15 +2016,14 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
/* Set full-duplex, 1000 mbps. */
tg3_writephy(tp, MII_BMCR,
- BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+ BMCR_FULLDPLX | BMCR_SPEED1000);
/* Set to master mode. */
- if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
+ if (tg3_readphy(tp, MII_CTRL1000, &phy9_orig))
continue;
- tg3_writephy(tp, MII_TG3_CTRL,
- (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER));
+ tg3_writephy(tp, MII_CTRL1000,
+ CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
if (err)
@@ -2013,7 +2048,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
- tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+ tg3_writephy(tp, MII_CTRL1000, phy9_orig);
if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
reg32 &= ~0x3000;
@@ -2165,21 +2200,214 @@ out:
return 0;
}
-static void tg3_frob_aux_power(struct tg3 *tp)
+#define TG3_GPIO_MSG_DRVR_PRES 0x00000001
+#define TG3_GPIO_MSG_NEED_VAUX 0x00000002
+#define TG3_GPIO_MSG_MASK (TG3_GPIO_MSG_DRVR_PRES | \
+ TG3_GPIO_MSG_NEED_VAUX)
+#define TG3_GPIO_MSG_ALL_DRVR_PRES_MASK \
+ ((TG3_GPIO_MSG_DRVR_PRES << 0) | \
+ (TG3_GPIO_MSG_DRVR_PRES << 4) | \
+ (TG3_GPIO_MSG_DRVR_PRES << 8) | \
+ (TG3_GPIO_MSG_DRVR_PRES << 12))
+
+#define TG3_GPIO_MSG_ALL_NEED_VAUX_MASK \
+ ((TG3_GPIO_MSG_NEED_VAUX << 0) | \
+ (TG3_GPIO_MSG_NEED_VAUX << 4) | \
+ (TG3_GPIO_MSG_NEED_VAUX << 8) | \
+ (TG3_GPIO_MSG_NEED_VAUX << 12))
+
+static inline u32 tg3_set_function_status(struct tg3 *tp, u32 newstat)
+{
+ u32 status, shift;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ status = tg3_ape_read32(tp, TG3_APE_GPIO_MSG);
+ else
+ status = tr32(TG3_CPMU_DRV_STATUS);
+
+ shift = TG3_APE_GPIO_MSG_SHIFT + 4 * tp->pci_fn;
+ status &= ~(TG3_GPIO_MSG_MASK << shift);
+ status |= (newstat << shift);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ tg3_ape_write32(tp, TG3_APE_GPIO_MSG, status);
+ else
+ tw32(TG3_CPMU_DRV_STATUS, status);
+
+ return status >> TG3_APE_GPIO_MSG_SHIFT;
+}
+
+static inline int tg3_pwrsrc_switch_to_vmain(struct tg3 *tp)
+{
+ if (!tg3_flag(tp, IS_NIC))
+ return 0;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ if (tg3_ape_lock(tp, TG3_APE_LOCK_GPIO))
+ return -EIO;
+
+ tg3_set_function_status(tp, TG3_GPIO_MSG_DRVR_PRES);
+
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ tg3_ape_unlock(tp, TG3_APE_LOCK_GPIO);
+ } else {
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ }
+
+ return 0;
+}
+
+static void tg3_pwrsrc_die_with_vmain(struct tg3 *tp)
+{
+ u32 grc_local_ctrl;
+
+ if (!tg3_flag(tp, IS_NIC) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
+ return;
+
+ grc_local_ctrl = tp->grc_local_ctrl | GRC_LCLCTRL_GPIO_OE1;
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+}
+
+static void tg3_pwrsrc_switch_to_vaux(struct tg3 *tp)
+{
+ if (!tg3_flag(tp, IS_NIC))
+ return;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+ (GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1),
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
+ /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
+ u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 |
+ tp->grc_local_ctrl;
+ tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
+ tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
+ tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ } else {
+ u32 no_gpio2;
+ u32 grc_local_ctrl = 0;
+
+ /* Workaround to prevent overdrawing Amps. */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+ grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ }
+
+ /* On 5753 and variants, GPIO2 cannot be used. */
+ no_gpio2 = tp->nic_sram_data_cfg &
+ NIC_SRAM_DATA_CFG_NO_GPIO2;
+
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 |
+ GRC_LCLCTRL_GPIO_OUTPUT2;
+ if (no_gpio2) {
+ grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT2);
+ }
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ if (!no_gpio2) {
+ grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ }
+ }
+}
+
+static void tg3_frob_aux_power_5717(struct tg3 *tp, bool wol_enable)
+{
+ u32 msg = 0;
+
+ /* Serialize power state transitions */
+ if (tg3_ape_lock(tp, TG3_APE_LOCK_GPIO))
+ return;
+
+ if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE) || wol_enable)
+ msg = TG3_GPIO_MSG_NEED_VAUX;
+
+ msg = tg3_set_function_status(tp, msg);
+
+ if (msg & TG3_GPIO_MSG_ALL_DRVR_PRES_MASK)
+ goto done;
+
+ if (msg & TG3_GPIO_MSG_ALL_NEED_VAUX_MASK)
+ tg3_pwrsrc_switch_to_vaux(tp);
+ else
+ tg3_pwrsrc_die_with_vmain(tp);
+
+done:
+ tg3_ape_unlock(tp, TG3_APE_LOCK_GPIO);
+}
+
+static void tg3_frob_aux_power(struct tg3 *tp, bool include_wol)
{
bool need_vaux = false;
/* The GPIOs do something completely different on 57765. */
if (!tg3_flag(tp, IS_NIC) ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
return;
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) &&
- tp->pdev_peer != tp->pdev) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ tg3_frob_aux_power_5717(tp, include_wol ?
+ tg3_flag(tp, WOL_ENABLE) != 0 : 0);
+ return;
+ }
+
+ if (tp->pdev_peer && tp->pdev_peer != tp->pdev) {
struct net_device *dev_peer;
dev_peer = pci_get_drvdata(tp->pdev_peer);
@@ -2191,95 +2419,20 @@ static void tg3_frob_aux_power(struct tg3 *tp)
if (tg3_flag(tp_peer, INIT_COMPLETE))
return;
- if (tg3_flag(tp_peer, WOL_ENABLE) ||
+ if ((include_wol && tg3_flag(tp_peer, WOL_ENABLE)) ||
tg3_flag(tp_peer, ENABLE_ASF))
need_vaux = true;
}
}
- if (tg3_flag(tp, WOL_ENABLE) || tg3_flag(tp, ENABLE_ASF))
+ if ((include_wol && tg3_flag(tp, WOL_ENABLE)) ||
+ tg3_flag(tp, ENABLE_ASF))
need_vaux = true;
- if (need_vaux) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- (GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 |
- GRC_LCLCTRL_GPIO_OUTPUT1),
- 100);
- } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
- /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
- u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 |
- GRC_LCLCTRL_GPIO_OUTPUT1 |
- tp->grc_local_ctrl;
- tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
-
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
- tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
-
- grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
- tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
- } else {
- u32 no_gpio2;
- u32 grc_local_ctrl = 0;
-
- /* Workaround to prevent overdrawing Amps. */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
- ASIC_REV_5714) {
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
- }
-
- /* On 5753 and variants, GPIO2 cannot be used. */
- no_gpio2 = tp->nic_sram_data_cfg &
- NIC_SRAM_DATA_CFG_NO_GPIO2;
-
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT1 |
- GRC_LCLCTRL_GPIO_OUTPUT2;
- if (no_gpio2) {
- grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT2);
- }
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
-
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
-
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
-
- if (!no_gpio2) {
- grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
- }
- }
- } else {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- (GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OUTPUT1), 100);
-
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- GRC_LCLCTRL_GPIO_OE1, 100);
-
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- (GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OUTPUT1), 100);
- }
- }
+ if (need_vaux)
+ tg3_pwrsrc_switch_to_vaux(tp);
+ else
+ tg3_pwrsrc_die_with_vmain(tp);
}
static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
@@ -2619,15 +2772,19 @@ static void tg3_enable_register_access(struct tg3 *tp)
static int tg3_power_up(struct tg3 *tp)
{
- tg3_enable_register_access(tp);
+ int err;
- pci_set_power_state(tp->pdev, PCI_D0);
+ tg3_enable_register_access(tp);
- /* Switch out of Vaux if it is a NIC */
- if (tg3_flag(tp, IS_NIC))
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
+ err = pci_set_power_state(tp->pdev, PCI_D0);
+ if (!err) {
+ /* Switch out of Vaux if it is a NIC */
+ tg3_pwrsrc_switch_to_vmain(tp);
+ } else {
+ netdev_err(tp->dev, "Transition to D0 failed\n");
+ }
- return 0;
+ return err;
}
static int tg3_power_down_prepare(struct tg3 *tp)
@@ -2642,11 +2799,11 @@ static int tg3_power_down_prepare(struct tg3 *tp)
u16 lnkctl;
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
&lnkctl);
lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
lnkctl);
}
@@ -2852,7 +3009,7 @@ static int tg3_power_down_prepare(struct tg3 *tp)
if (!(device_should_wake) && !tg3_flag(tp, ENABLE_ASF))
tg3_power_down_phy(tp, do_low_power);
- tg3_frob_aux_power(tp);
+ tg3_frob_aux_power(tp, true);
/* Workaround for unstable PLL clock */
if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
@@ -2957,16 +3114,15 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
new_adv = 0;
if (advertise & ADVERTISED_1000baseT_Half)
- new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
+ new_adv |= ADVERTISE_1000HALF;
if (advertise & ADVERTISED_1000baseT_Full)
- new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
+ new_adv |= ADVERTISE_1000FULL;
if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
- new_adv |= (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER);
+ new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
- err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
+ err = tg3_writephy(tp, MII_CTRL1000, new_adv);
if (err)
goto done;
@@ -2980,20 +3136,6 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
if (!err) {
u32 err2;
- switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
- case ASIC_REV_5717:
- case ASIC_REV_57765:
- if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
- tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
- MII_TG3_DSP_CH34TP2_HIBW01);
- /* Fall through */
- case ASIC_REV_5719:
- val = MII_TG3_DSP_TAP26_ALNOKO |
- MII_TG3_DSP_TAP26_RMRXSTO |
- MII_TG3_DSP_TAP26_OPCSINPT;
- tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
- }
-
val = 0;
/* Advertise 100-BaseTX EEE ability */
if (advertise & ADVERTISED_100baseT_Full)
@@ -3002,6 +3144,25 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
if (advertise & ADVERTISED_1000baseT_Full)
val |= MDIO_AN_EEE_ADV_1000T;
err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
+ if (err)
+ val = 0;
+
+ switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+ case ASIC_REV_5717:
+ case ASIC_REV_57765:
+ case ASIC_REV_5719:
+ /* If we advertised any eee advertisements above... */
+ if (val)
+ val = MII_TG3_DSP_TAP26_ALNOKO |
+ MII_TG3_DSP_TAP26_RMRXSTO |
+ MII_TG3_DSP_TAP26_OPCSINPT;
+ tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
+ /* Fall through */
+ case ASIC_REV_5720:
+ if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
+ tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
+ MII_TG3_DSP_CH34TP2_HIBW01);
+ }
err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
if (!err)
@@ -3075,7 +3236,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
break;
case SPEED_1000:
- bmcr |= TG3_BMCR_SPEED1000;
+ bmcr |= BMCR_SPEED1000;
break;
}
@@ -3152,7 +3313,7 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
if (mask & ADVERTISED_1000baseT_Full)
all_mask |= ADVERTISE_1000FULL;
- if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
+ if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
return 0;
if ((tg3_ctrl & all_mask) != all_mask)
@@ -3449,7 +3610,7 @@ relink:
u16 oldlnkctl, newlnkctl;
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
&oldlnkctl);
if (tp->link_config.active_speed == SPEED_100 ||
tp->link_config.active_speed == SPEED_10)
@@ -3458,7 +3619,7 @@ relink:
newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
if (newlnkctl != oldlnkctl)
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
newlnkctl);
}
@@ -5821,8 +5982,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
/* Make sure new skb does not cross any 4G boundaries.
* Drop the packet if it does.
*/
- } else if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
- tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ } else if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
pci_unmap_single(tp->pdev, new_addr, new_skb->len,
PCI_DMA_TODEVICE);
ret = -1;
@@ -6017,12 +6177,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (tg3_flag(tp, SHORT_DMA_BUG) && len <= 8)
would_hit_hwbug = 1;
- if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
- tg3_4g_overflow_test(mapping, len))
+ if (tg3_4g_overflow_test(mapping, len))
would_hit_hwbug = 1;
- if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) &&
- tg3_40bit_overflow_test(tp, mapping, len))
+ if (tg3_40bit_overflow_test(tp, mapping, len))
would_hit_hwbug = 1;
if (tg3_flag(tp, 5701_DMA_BUG))
@@ -6055,12 +6213,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
len <= 8)
would_hit_hwbug = 1;
- if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
- tg3_4g_overflow_test(mapping, len))
+ if (tg3_4g_overflow_test(mapping, len))
would_hit_hwbug = 1;
- if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) &&
- tg3_40bit_overflow_test(tp, mapping, len))
+ if (tg3_40bit_overflow_test(tp, mapping, len))
would_hit_hwbug = 1;
if (tg3_flag(tp, HW_TSO_1) ||
@@ -6088,6 +6244,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
entry = NEXT_TX(tnapi->tx_prod);
}
+ skb_tx_timestamp(skb);
+
/* Packets are ready, update Tx producer idx local and on card. */
tw32_tx_mbox(tnapi->prodmbox, entry);
@@ -7193,7 +7351,7 @@ static int tg3_chip_reset(struct tg3 *tp)
udelay(120);
- if (tg3_flag(tp, PCI_EXPRESS) && tp->pcie_cap) {
+ if (tg3_flag(tp, PCI_EXPRESS) && pci_pcie_cap(tp->pdev)) {
u16 val16;
if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
@@ -7211,7 +7369,7 @@ static int tg3_chip_reset(struct tg3 *tp)
/* Clear the "no snoop" and "relaxed ordering" bits. */
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_DEVCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
&val16);
val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN |
PCI_EXP_DEVCTL_NOSNOOP_EN);
@@ -7222,14 +7380,14 @@ static int tg3_chip_reset(struct tg3 *tp)
if (!tg3_flag(tp, CPMU_PRESENT))
val16 &= ~PCI_EXP_DEVCTL_PAYLOAD;
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_DEVCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
val16);
pcie_set_readrq(tp->pdev, tp->pcie_readrq);
/* Clear error status */
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_DEVSTA,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_DEVSTA,
PCI_EXP_DEVSTA_CED |
PCI_EXP_DEVSTA_NFED |
PCI_EXP_DEVSTA_FED |
@@ -7267,16 +7425,11 @@ static int tg3_chip_reset(struct tg3 *tp)
tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
}
- if (tg3_flag(tp, ENABLE_APE))
- tp->mac_mode = MAC_MODE_APE_TX_EN |
- MAC_MODE_APE_RX_EN |
- MAC_MODE_TDE_ENABLE;
-
if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
- tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+ tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
val = tp->mac_mode;
} else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+ tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
val = tp->mac_mode;
} else
val = 0;
@@ -7751,6 +7904,9 @@ static void tg3_rings_reset(struct tg3 *tp)
/* Disable interrupts */
tw32_mailbox_f(tp->napi[0].int_mbox, 1);
+ tp->napi[0].chk_msi_cnt = 0;
+ tp->napi[0].last_rx_cons = 0;
+ tp->napi[0].last_tx_cons = 0;
/* Zero mailbox registers. */
if (tg3_flag(tp, SUPPORT_MSIX)) {
@@ -7761,6 +7917,9 @@ 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].last_rx_cons = 0;
+ tp->napi[i].last_tx_cons = 0;
}
if (!tg3_flag(tp, ENABLE_TSS))
tw32_mailbox(tp->napi[0].prodmbox, 0);
@@ -8408,12 +8567,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
udelay(10);
}
- if (tg3_flag(tp, ENABLE_APE))
- tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
- else
- tp->mac_mode = 0;
tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
- MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+ MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE |
+ MAC_MODE_FHDE_ENABLE;
+ if (tg3_flag(tp, ENABLE_APE))
+ tp->mac_mode |= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
if (!tg3_flag(tp, 5705_PLUS) &&
!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
@@ -8565,15 +8723,24 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
udelay(100);
if (tg3_flag(tp, ENABLE_RSS)) {
+ int i = 0;
u32 reg = MAC_RSS_INDIR_TBL_0;
- u8 *ent = (u8 *)&val;
- /* Setup the indirection table */
- for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
- int idx = i % sizeof(val);
+ if (tp->irq_cnt == 2) {
+ for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i += 8) {
+ tw32(reg, 0x0);
+ reg += 4;
+ }
+ } else {
+ u32 val;
- ent[idx] = i % (tp->irq_cnt - 1);
- if (idx == sizeof(val) - 1) {
+ while (i < TG3_RSS_INDIR_TBL_SIZE) {
+ val = i % (tp->irq_cnt - 1);
+ i++;
+ for (; i % 8; i++) {
+ val <<= 4;
+ val |= (i % (tp->irq_cnt - 1));
+ }
tw32(reg, val);
reg += 4;
}
@@ -8816,6 +8983,30 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT);
}
+static void tg3_chk_missed_msi(struct tg3 *tp)
+{
+ u32 i;
+
+ for (i = 0; i < tp->irq_cnt; i++) {
+ struct tg3_napi *tnapi = &tp->napi[i];
+
+ if (tg3_has_work(tnapi)) {
+ if (tnapi->last_rx_cons == tnapi->rx_rcb_ptr &&
+ tnapi->last_tx_cons == tnapi->tx_cons) {
+ if (tnapi->chk_msi_cnt < 1) {
+ tnapi->chk_msi_cnt++;
+ return;
+ }
+ tw32_mailbox(tnapi->int_mbox,
+ tnapi->last_tag << 24);
+ }
+ }
+ tnapi->chk_msi_cnt = 0;
+ tnapi->last_rx_cons = tnapi->rx_rcb_ptr;
+ tnapi->last_tx_cons = tnapi->tx_cons;
+ }
+}
+
static void tg3_timer(unsigned long __opaque)
{
struct tg3 *tp = (struct tg3 *) __opaque;
@@ -8825,6 +9016,10 @@ static void tg3_timer(unsigned long __opaque)
spin_lock(&tp->lock);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ tg3_chk_missed_msi(tp);
+
if (!tg3_flag(tp, TAGGED_STATUS)) {
/* All of this garbage is because when using non-tagged
* IRQ status the mailbox/status_block protocol the chip
@@ -8988,7 +9183,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
* Turn off MSI one shot mode. Otherwise this test has no
* observable way to know whether the interrupt was delivered.
*/
- if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
+ if (tg3_flag(tp, 57765_PLUS)) {
val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE;
tw32(MSGINT_MODE, val);
}
@@ -9016,6 +9211,10 @@ static int tg3_test_interrupt(struct tg3 *tp)
break;
}
+ if (tg3_flag(tp, 57765_PLUS) &&
+ tnapi->hw_status->status_tag != tnapi->last_tag)
+ tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
+
msleep(10);
}
@@ -9030,7 +9229,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
if (intr_ok) {
/* Reenable MSI one shot mode. */
- if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
+ if (tg3_flag(tp, 57765_PLUS)) {
val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE;
tw32(MSGINT_MODE, val);
}
@@ -9300,7 +9499,9 @@ static int tg3_open(struct net_device *dev)
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
} else {
- if (tg3_flag(tp, TAGGED_STATUS))
+ if (tg3_flag(tp, TAGGED_STATUS) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765)
tp->timer_offset = HZ;
else
tp->timer_offset = HZ / 10;
@@ -9376,6 +9577,8 @@ err_out2:
err_out1:
tg3_ints_fini(tp);
+ tg3_frob_aux_power(tp, false);
+ pci_set_power_state(tp->pdev, PCI_D3hot);
return err;
}
@@ -9902,6 +10105,18 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
}
cmd->advertising = tp->link_config.advertising;
+ if (tg3_flag(tp, PAUSE_AUTONEG)) {
+ if (tp->link_config.flowctrl & FLOW_CTRL_RX) {
+ if (tp->link_config.flowctrl & FLOW_CTRL_TX) {
+ cmd->advertising |= ADVERTISED_Pause;
+ } else {
+ cmd->advertising |= ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause;
+ }
+ } else if (tp->link_config.flowctrl & FLOW_CTRL_TX) {
+ cmd->advertising |= ADVERTISED_Asym_Pause;
+ }
+ }
if (netif_running(dev)) {
ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
cmd->duplex = tp->link_config.active_duplex;
@@ -10358,7 +10573,7 @@ static void tg3_get_ethtool_stats(struct net_device *dev,
memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
}
-static __be32 * tg3_vpd_readblock(struct tg3 *tp)
+static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
{
int i;
__be32 *buf;
@@ -10425,6 +10640,8 @@ static __be32 * tg3_vpd_readblock(struct tg3 *tp)
goto error;
}
+ *vpdlen = len;
+
return buf;
error:
@@ -10436,12 +10653,15 @@ error:
#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14
#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18
#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c
+#define NVRAM_SELFBOOT_FORMAT1_4_SIZE 0x20
+#define NVRAM_SELFBOOT_FORMAT1_5_SIZE 0x24
+#define NVRAM_SELFBOOT_FORMAT1_6_SIZE 0x50
#define NVRAM_SELFBOOT_HW_SIZE 0x20
#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
static int tg3_test_nvram(struct tg3 *tp)
{
- u32 csum, magic;
+ u32 csum, magic, len;
__be32 *buf;
int i, j, k, err = 0, size;
@@ -10466,8 +10686,17 @@ static int tg3_test_nvram(struct tg3 *tp)
case TG3_EEPROM_SB_REVISION_3:
size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
break;
+ case TG3_EEPROM_SB_REVISION_4:
+ size = NVRAM_SELFBOOT_FORMAT1_4_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_5:
+ size = NVRAM_SELFBOOT_FORMAT1_5_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_6:
+ size = NVRAM_SELFBOOT_FORMAT1_6_SIZE;
+ break;
default:
- return 0;
+ return -EIO;
}
} else
return 0;
@@ -10573,18 +10802,17 @@ static int tg3_test_nvram(struct tg3 *tp)
kfree(buf);
- buf = tg3_vpd_readblock(tp);
+ buf = tg3_vpd_readblock(tp, &len);
if (!buf)
return -ENOMEM;
- i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN,
- PCI_VPD_LRDT_RO_DATA);
+ i = pci_vpd_find_tag((u8 *)buf, 0, len, PCI_VPD_LRDT_RO_DATA);
if (i > 0) {
j = pci_vpd_lrdt_size(&((u8 *)buf)[i]);
if (j < 0)
goto out;
- if (i + PCI_VPD_LRDT_TAG_SIZE + j > TG3_NVM_VPD_LEN)
+ if (i + PCI_VPD_LRDT_TAG_SIZE + j > len)
goto out;
i += PCI_VPD_LRDT_TAG_SIZE;
@@ -11340,8 +11568,12 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
{
struct tg3 *tp = netdev_priv(dev);
- if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
- tg3_power_up(tp);
+ if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
+ tg3_power_up(tp)) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ memset(data, 1, sizeof(u64) * TG3_NUM_TEST);
+ return;
+ }
memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
@@ -12585,29 +12817,6 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
{
u32 val;
- u16 pmcsr;
-
- /* On some early chips the SRAM cannot be accessed in D3hot state,
- * so need make sure we're in D0.
- */
- pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr);
- pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
- pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr);
- msleep(1);
-
- /* Make sure register accesses (indirect or otherwise)
- * will function correctly.
- */
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- tp->misc_host_ctrl);
-
- /* The memory arbiter has to be enabled in order for SRAM accesses
- * to succeed. Normally on powerup the tg3 chip firmware will make
- * sure it is enabled, but other entities such as system netboot
- * code might disable it.
- */
- val = tr32(MEMARB_MODE);
- tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
tp->phy_id = TG3_PHY_ID_INVALID;
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
@@ -12947,7 +13156,9 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
}
if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
- ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720 ||
+ (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
@@ -12999,14 +13210,14 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
{
u8 *vpd_data;
unsigned int block_end, rosize, len;
+ u32 vpdlen;
int j, i = 0;
- vpd_data = (u8 *)tg3_vpd_readblock(tp);
+ vpd_data = (u8 *)tg3_vpd_readblock(tp, &vpdlen);
if (!vpd_data)
goto out_no_vpd;
- i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN,
- PCI_VPD_LRDT_RO_DATA);
+ i = pci_vpd_find_tag(vpd_data, 0, vpdlen, PCI_VPD_LRDT_RO_DATA);
if (i < 0)
goto out_not_found;
@@ -13014,7 +13225,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
i += PCI_VPD_LRDT_TAG_SIZE;
- if (block_end > TG3_NVM_VPD_LEN)
+ if (block_end > vpdlen)
goto out_not_found;
j = pci_vpd_find_info_keyword(vpd_data, i, rosize,
@@ -13039,7 +13250,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
goto partno;
memcpy(tp->fw_ver, &vpd_data[j], len);
- strncat(tp->fw_ver, " bc ", TG3_NVM_VPD_LEN - len - 1);
+ strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
}
partno:
@@ -13052,7 +13263,7 @@ partno:
i += PCI_VPD_INFO_FLD_HDR_SIZE;
if (len > TG3_BPN_SIZE ||
- (len + i) > TG3_NVM_VPD_LEN)
+ (len + i) > vpdlen)
goto out_not_found;
memcpy(tp->board_part_number, &vpd_data[i], len);
@@ -13353,10 +13564,15 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
else
return;
- if (!tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE) || vpd_vers)
+ if (vpd_vers)
goto done;
- tg3_read_mgmtfw_ver(tp);
+ if (tg3_flag(tp, ENABLE_APE)) {
+ if (tg3_flag(tp, ENABLE_ASF))
+ tg3_read_dash_ver(tp);
+ } else if (tg3_flag(tp, ENABLE_ASF)) {
+ tg3_read_mgmtfw_ver(tp);
+ }
done:
tp->fw_ver[TG3_VER_SIZE - 1] = 0;
@@ -13400,14 +13616,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_cmd &= ~PCI_COMMAND_INVALIDATE;
pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
- /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
- * has the register indirect write enable bit set before
- * we try to access any of the MMIO registers. It is also
- * critical that the PCI-X hw workaround situation is decided
- * before that as well.
+ /* Important! -- Make sure register accesses are byteswapped
+ * correctly. Also, for those chips that require it, make
+ * sure that indirect register accesses are enabled before
+ * the first operation.
*/
pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
&misc_ctrl_reg);
+ tp->misc_host_ctrl |= (misc_ctrl_reg &
+ MISC_HOST_CTRL_CHIPREV);
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
tp->pci_chip_rev_id = (misc_ctrl_reg >>
MISC_HOST_CTRL_CHIPREV_SHIFT);
@@ -13563,16 +13782,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
} while (bridge);
}
- /* Initialize misc host control in PCI block. */
- tp->misc_host_ctrl |= (misc_ctrl_reg &
- MISC_HOST_CTRL_CHIPREV);
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- tp->misc_host_ctrl);
-
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)
tp->pdev_peer = tg3_find_peer(tp);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
@@ -13666,15 +13877,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
}
- /* All chips can get confused if TX buffers
- * straddle the 4GB address boundary.
- */
- tg3_flag_set(tp, 4G_DMA_BNDRY_BUG);
-
if (tg3_flag(tp, 5755_PLUS))
tg3_flag_set(tp, SHORT_DMA_BUG);
- else
- tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG);
if (tg3_flag(tp, 5717_PLUS))
tg3_flag_set(tp, LRG_PROD_RING_CAP);
@@ -13691,8 +13895,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
&pci_state_reg);
- tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
- if (tp->pcie_cap != 0) {
+ if (pci_is_pcie(tp->pdev)) {
u16 lnkctl;
tg3_flag_set(tp, PCI_EXPRESS);
@@ -13705,7 +13908,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pcie_set_readrq(tp->pdev, tp->pcie_readrq);
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
&lnkctl);
if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
@@ -13722,6 +13925,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tg3_flag_set(tp, L1PLLPD_EN);
}
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ /* 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)) {
@@ -13757,6 +13964,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->pci_lat_timer);
}
+ /* Important! -- It is critical that the PCI-X hw workaround
+ * situation is decided before the first MMIO register access.
+ */
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
/* 5700 BX chips need to have their TX producer index
* mailboxes written twice to workaround a bug.
@@ -13863,6 +14073,22 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
tg3_flag_set(tp, SRAM_USE_CONFIG);
+ /* The memory arbiter has to be enabled in order for SRAM accesses
+ * to succeed. Normally on powerup the tg3 chip firmware will make
+ * sure it is enabled, but other entities such as system netboot
+ * code might disable it.
+ */
+ val = tr32(MEMARB_MODE);
+ tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+ if (tg3_flag(tp, PCIX_MODE)) {
+ pci_read_config_dword(tp->pdev,
+ tp->pcix_cap + PCI_X_STATUS, &val);
+ tp->pci_fn = val & 0x7;
+ } else {
+ tp->pci_fn = PCI_FUNC(tp->pdev->devfn) & 3;
+ }
+
/* Get eeprom hw config before calling tg3_set_power_state().
* In particular, the TG3_FLAG_IS_NIC flag must be
* determined before calling tg3_set_power_state() so that
@@ -13882,6 +14108,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
PCISTATE_ALLOW_APE_PSPACE_WR;
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE,
pci_state_reg);
+
+ tg3_ape_lock_init(tp);
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -13891,8 +14119,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tg3_flag(tp, 57765_PLUS))
tg3_flag_set(tp, CPMU_PRESENT);
- /* Set up tp->grc_local_ctrl before calling tg3_power_up().
- * GPIO1 driven high will bring 5700's external PHY out of reset.
+ /* Set up tp->grc_local_ctrl before calling
+ * tg3_pwrsrc_switch_to_vmain(). GPIO1 driven high
+ * will bring 5700's external PHY out of reset.
* It is also used as eeprom write protect on LOMs.
*/
tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
@@ -13921,12 +14150,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
GRC_LCLCTRL_GPIO_OUTPUT0;
}
- /* Force the chip into D0. */
- err = tg3_power_up(tp);
- if (err) {
- dev_err(&tp->pdev->dev, "Transition to D0 failed\n");
- return err;
- }
+ /* Switch out of Vaux if it is a NIC */
+ tg3_pwrsrc_switch_to_vmain(tp);
/* Derive initial jumbo mode from MTU assigned in
* ether_setup() via the alloc_etherdev() call
@@ -14229,9 +14454,9 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
else
tg3_nvram_unlock(tp);
} else if (tg3_flag(tp, 5717_PLUS)) {
- if (PCI_FUNC(tp->pdev->devfn) & 1)
+ if (tp->pci_fn & 1)
mac_offset = 0xcc;
- if (PCI_FUNC(tp->pdev->devfn) > 1)
+ if (tp->pci_fn > 1)
mac_offset += 0x18c;
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
mac_offset = 0x10;
@@ -14941,11 +15166,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_free_res;
}
+ err = pci_set_power_state(pdev, PCI_D0);
+ if (err) {
+ dev_err(&pdev->dev, "Transition to D0 failed, aborting\n");
+ goto err_out_free_res;
+ }
+
dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
if (!dev) {
dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n");
err = -ENOMEM;
- goto err_out_free_res;
+ goto err_out_power_down;
}
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -14994,6 +15225,24 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_free_dev;
}
+ if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761E ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761SE ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) {
+ tg3_flag_set(tp, ENABLE_APE);
+ tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
+ if (!tp->aperegs) {
+ dev_err(&pdev->dev,
+ "Cannot map APE registers, aborting\n");
+ err = -ENOMEM;
+ goto err_out_iounmap;
+ }
+ }
+
tp->rx_pending = TG3_DEF_RX_RING_PENDING;
tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
@@ -15006,7 +15255,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
if (err) {
dev_err(&pdev->dev,
"Problem fetching invariants of chip, aborting\n");
- goto err_out_iounmap;
+ goto err_out_apeunmap;
}
/* The EPB bridge inside 5714, 5715, and 5780 and any
@@ -15035,7 +15284,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
if (err < 0) {
dev_err(&pdev->dev, "Unable to obtain 64 bit "
"DMA for consistent allocations\n");
- goto err_out_iounmap;
+ goto err_out_apeunmap;
}
}
}
@@ -15044,7 +15293,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
if (err) {
dev_err(&pdev->dev,
"No usable DMA configuration, aborting\n");
- goto err_out_iounmap;
+ goto err_out_apeunmap;
}
}
@@ -15109,22 +15358,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
if (err) {
dev_err(&pdev->dev,
"Could not obtain valid ethernet address, aborting\n");
- goto err_out_iounmap;
- }
-
- if (tg3_flag(tp, ENABLE_APE)) {
- tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
- if (!tp->aperegs) {
- dev_err(&pdev->dev,
- "Cannot map APE registers, aborting\n");
- err = -ENOMEM;
- goto err_out_iounmap;
- }
-
- tg3_ape_lock_init(tp);
-
- if (tg3_flag(tp, ENABLE_ASF))
- tg3_read_dash_ver(tp);
+ goto err_out_apeunmap;
}
/*
@@ -15192,6 +15426,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
+ if (tg3_flag(tp, 5717_PLUS)) {
+ /* Resume a low-power mode */
+ tg3_frob_aux_power(tp, false);
+ }
+
err = register_netdev(dev);
if (err) {
dev_err(&pdev->dev, "Cannot register net device, aborting\n");
@@ -15257,6 +15496,9 @@ err_out_iounmap:
err_out_free_dev:
free_netdev(dev);
+err_out_power_down:
+ pci_set_power_state(pdev, PCI_D3hot);
+
err_out_free_res:
pci_release_regions(pdev);
@@ -15481,10 +15723,8 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
}
err = tg3_power_up(tp);
- if (err) {
- netdev_err(netdev, "Failed to restore register access.\n");
+ if (err)
goto done;
- }
rc = PCI_ERS_RESULT_RECOVERED;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5b3d2f34da7a..691539ba17b3 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1065,6 +1065,8 @@
#define RCVLSC_STATUS_ERROR_ATTN 0x00000004
/* 0x3408 --> 0x3600 unused */
+#define TG3_CPMU_DRV_STATUS 0x0000344c
+
/* CPMU registers */
#define TG3_CPMU_CTRL 0x00003600
#define CPMU_CTRL_LINK_IDLE_MODE 0x00000200
@@ -1118,10 +1120,10 @@
#define TG3_CPMU_EEEMD_EEE_ENABLE 0x00100000
#define TG3_CPMU_EEE_DBTMR1 0x000036b4
#define TG3_CPMU_DBTMR1_PCIEXIT_2047US 0x07ff0000
-#define TG3_CPMU_DBTMR1_LNKIDLE_2047US 0x000070ff
+#define TG3_CPMU_DBTMR1_LNKIDLE_2047US 0x000007ff
#define TG3_CPMU_EEE_DBTMR2 0x000036b8
#define TG3_CPMU_DBTMR2_APE_TX_2047US 0x07ff0000
-#define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000070ff
+#define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000007ff
#define TG3_CPMU_EEE_LNKIDL_CTRL 0x000036bc
#define TG3_CPMU_EEE_LNKIDL_PCIE_NL0 0x01000000
#define TG3_CPMU_EEE_LNKIDL_UART_IDL 0x00000004
@@ -2152,14 +2154,6 @@
/*** Tigon3 specific PHY MII registers. ***/
-#define TG3_BMCR_SPEED1000 0x0040
-
-#define MII_TG3_CTRL 0x09 /* 1000-baseT control register */
-#define MII_TG3_CTRL_ADV_1000_HALF 0x0100
-#define MII_TG3_CTRL_ADV_1000_FULL 0x0200
-#define MII_TG3_CTRL_AS_MASTER 0x0800
-#define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000
-
#define MII_TG3_MMD_CTRL 0x0d /* MMD Access Control register */
#define MII_TG3_MMD_CTRL_DATA_NOINC 0x4000
#define MII_TG3_MMD_ADDRESS 0x0e /* MMD Address Data register */
@@ -2186,7 +2180,7 @@
#define MII_TG3_DSP_TAP26_OPCSINPT 0x0004
#define MII_TG3_DSP_AADJ1CH0 0x001f
#define MII_TG3_DSP_CH34TP2 0x4022
-#define MII_TG3_DSP_CH34TP2_HIBW01 0x017b
+#define MII_TG3_DSP_CH34TP2_HIBW01 0x01ff
#define MII_TG3_DSP_AADJ1CH3 0x601f
#define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002
#define MII_TG3_DSP_EXP1_INT_STAT 0x0f01
@@ -2285,6 +2279,8 @@
/* APE registers. Accessible through BAR1 */
+#define TG3_APE_GPIO_MSG 0x0008
+#define TG3_APE_GPIO_MSG_SHIFT 4
#define TG3_APE_EVENT 0x000c
#define APE_EVENT_1 0x00000001
#define TG3_APE_LOCK_REQ 0x002c
@@ -2347,6 +2343,7 @@
/* APE convenience enumerations. */
#define TG3_APE_LOCK_GRC 1
#define TG3_APE_LOCK_MEM 4
+#define TG3_APE_LOCK_GPIO 7
#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
@@ -2800,6 +2797,7 @@ struct tg3_napi {
struct tg3 *tp;
struct tg3_hw_status *hw_status;
+ u32 chk_msi_cnt;
u32 last_tag;
u32 last_irq_tag;
u32 int_mbox;
@@ -2807,6 +2805,7 @@ struct tg3_napi {
u32 consmbox ____cacheline_aligned;
u32 rx_rcb_ptr;
+ u32 last_rx_cons;
u16 *rx_rcb_prod_idx;
struct tg3_rx_prodring_set prodring;
struct tg3_rx_buffer_desc *rx_rcb;
@@ -2814,6 +2813,7 @@ struct tg3_napi {
u32 tx_prod ____cacheline_aligned;
u32 tx_cons;
u32 tx_pending;
+ u32 last_tx_cons;
u32 prodmbox;
struct tg3_tx_buffer_desc *tx_ring;
struct ring_info *tx_buffers;
@@ -2862,7 +2862,7 @@ enum TG3_FLAGS {
TG3_FLAG_IS_5788,
TG3_FLAG_MAX_RXPEND_64,
TG3_FLAG_TSO_CAPABLE,
- TG3_FLAG_PCI_EXPRESS,
+ TG3_FLAG_PCI_EXPRESS, /* BCM5785 + pci_is_pcie() */
TG3_FLAG_ASF_NEW_HANDSHAKE,
TG3_FLAG_HW_AUTONEG,
TG3_FLAG_IS_NIC,
@@ -2893,8 +2893,6 @@ enum TG3_FLAGS {
TG3_FLAG_NO_NVRAM,
TG3_FLAG_ENABLE_RSS,
TG3_FLAG_ENABLE_TSS,
- TG3_FLAG_4G_DMA_BNDRY_BUG,
- TG3_FLAG_40BIT_DMA_LIMIT_BUG,
TG3_FLAG_SHORT_DMA_BUG,
TG3_FLAG_USE_JUMBO_BDFLAG,
TG3_FLAG_L1PLLPD_EN,
@@ -3027,12 +3025,10 @@ struct tg3 {
u8 pci_cacheline_sz;
u8 pci_lat_timer;
+ int pci_fn;
int pm_cap;
int msi_cap;
- union {
int pcix_cap;
- int pcie_cap;
- };
int pcie_readrq;
struct mii_bus *mdio_bus;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index ace6404e2fac..145871b3130b 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -29,8 +29,10 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/eisa.h>
#include <linux/pci.h>
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index ff32befd8443..b6162fe2348e 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -304,7 +304,7 @@ static int __devinit xl_probe(struct pci_dev *pdev,
if ((i = pci_request_regions(pdev,"3c359"))) {
return i ;
- } ;
+ }
/*
* Allowing init_trdev to allocate the private data will align
@@ -1773,7 +1773,9 @@ static void xl_wait_misr_flags(struct net_device *dev)
if (readb(xl_mmio + MMIO_MACDATA) != 0) { /* Misr not clear */
for (i=0; i<6; i++) {
writel(MEM_BYTE_READ | 0xDFFE0 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
- while (readb(xl_mmio + MMIO_MACDATA) != 0 ) {} ; /* Empty Loop */
+ while (readb(xl_mmio + MMIO_MACDATA) != 0) {
+ ; /* Empty Loop */
+ }
}
}
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 4786497de03e..e257a00fe14b 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -123,6 +123,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */
/* some 95 OS send many non UI frame; this allow removing the warning */
#define TR_FILTERNONUI 1
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
@@ -177,7 +178,7 @@ static char __devinit *adapter_def(char type)
case 0xD: return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter";
case 0xC: return "Auto 16/4 Adapter";
default: return "adapter (unknown type)";
- };
+ }
};
#define TRC_INIT 0x01 /* Trace initialization & PROBEs */
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 2bedc0ace812..6153cfd696b6 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -418,7 +418,7 @@ static irqreturn_t madgemc_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
- dev = (struct net_device *)dev_id;
+ dev = dev_id;
/* Make sure its really us. -- the Madge way */
pending = inb(dev->base_addr + MC_CONTROL_REG0);
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index 5c633a32eaeb..64cb9ac19ed9 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -33,6 +33,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index e2f692351180..ce90efc6ba3c 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -38,6 +38,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index efaa1d69b720..959b41021a65 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1868,14 +1868,13 @@ de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len)
i = DE4X5_PKT_STAT_SZ;
}
}
- if (buf[0] & 0x01) { /* Multicast/Broadcast */
- if ((*(s32 *)&buf[0] == -1) && (*(s16 *)&buf[4] == -1)) {
+ if (is_multicast_ether_addr(buf)) {
+ if (is_broadcast_ether_addr(buf)) {
lp->pktStats.broadcast++;
} else {
lp->pktStats.multicast++;
}
- } else if ((*(s32 *)&buf[0] == *(s32 *)&dev->dev_addr[0]) &&
- (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {
+ } else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
lp->pktStats.unicast++;
}
@@ -1964,9 +1963,7 @@ SetMulticastFilter(struct net_device *dev)
omr |= OMR_PM; /* Pass all multicasts */
} else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
- if ((*addrs & 0x01) == 1) { /* multicast address? */
- crc = ether_crc_le(ETH_ALEN, addrs);
+ crc = ether_crc_le(ETH_ALEN, ha->addr);
hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */
byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
@@ -1977,7 +1974,6 @@ SetMulticastFilter(struct net_device *dev)
byte -= 1;
}
lp->setup_frame[byte] |= bit;
- }
}
} else { /* Perfect filtering */
netdev_for_each_mc_addr(ha, dev) {
diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c
index aa4d9dad0395..52d898bdbeb4 100644
--- a/drivers/net/tulip/pnic.c
+++ b/drivers/net/tulip/pnic.c
@@ -13,6 +13,7 @@
Please submit bugs to http://bugzilla.kernel.org/ .
*/
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include "tulip.h"
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 82f87647207e..1246998a677c 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include "tulip.h"
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/mii.h>
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5235f48be1be..9a6b3824da14 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -572,9 +572,9 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
/* prepad is the amount to reserve at front. len is length after that.
* linear is a hint as to how much to copy (usually headers). */
-static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
- size_t prepad, size_t len,
- size_t linear, int noblock)
+static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
+ size_t prepad, size_t len,
+ size_t linear, int noblock)
{
struct sock *sk = tun->socket.sk;
struct sk_buff *skb;
@@ -600,13 +600,13 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
}
/* Get packet from user space buffer */
-static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
- const struct iovec *iv, size_t count,
- int noblock)
+static ssize_t tun_get_user(struct tun_struct *tun,
+ const struct iovec *iv, size_t count,
+ int noblock)
{
struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
struct sk_buff *skb;
- size_t len = count, align = 0;
+ size_t len = count, align = NET_SKB_PAD;
struct virtio_net_hdr gso = { 0 };
int offset = 0;
@@ -636,7 +636,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
}
if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
- align = NET_IP_ALIGN;
+ align += NET_IP_ALIGN;
if (unlikely(len < ETH_HLEN ||
(gso.hdr_len && gso.hdr_len < ETH_HLEN)))
return -EINVAL;
@@ -688,7 +688,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
case TUN_TAP_DEV:
skb->protocol = eth_type_trans(skb, tun->dev);
break;
- };
+ }
if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
pr_debug("GSO!\n");
@@ -751,9 +751,9 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
}
/* Put packet to the user space buffer */
-static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
- struct sk_buff *skb,
- const struct iovec *iv, int len)
+static ssize_t tun_put_user(struct tun_struct *tun,
+ struct sk_buff *skb,
+ const struct iovec *iv, int len)
{
struct tun_pi pi = { 0, skb->protocol };
ssize_t total = 0;
@@ -810,6 +810,8 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
gso.csum_start = skb_checksum_start_offset(skb);
gso.csum_offset = skb->csum_offset;
+ } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+ gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */
if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
@@ -839,7 +841,8 @@ static ssize_t tun_do_read(struct tun_struct *tun,
tun_debug(KERN_INFO, tun, "tun_chr_read\n");
- add_wait_queue(&tun->wq.wait, &wait);
+ if (unlikely(!noblock))
+ add_wait_queue(&tun->wq.wait, &wait);
while (len) {
current->state = TASK_INTERRUPTIBLE;
@@ -870,7 +873,8 @@ static ssize_t tun_do_read(struct tun_struct *tun,
}
current->state = TASK_RUNNING;
- remove_wait_queue(&tun->wq.wait, &wait);
+ if (unlikely(!noblock))
+ remove_wait_queue(&tun->wq.wait, &wait);
return ret;
}
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 3de4283344e9..1d5091a1e49a 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -2367,7 +2367,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->irq = pdev->irq;
tp = netdev_priv(dev);
- tp->shared = (struct typhoon_shared *) shared;
+ tp->shared = shared;
tp->shared_dma = shared_dma;
tp->pdev = pdev;
tp->tx_pdev = pdev;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index ef041057d9d3..d3465ab50e56 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2030,11 +2030,6 @@ static void ucc_geth_set_multi(struct net_device *dev)
out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
netdev_for_each_mc_addr(ha, dev) {
- /* Only support group multicast for now.
- */
- if (!is_multicast_ether_addr(ha->addr))
- continue;
-
/* Ask CPM to run CRC and set bit in
* filter mask.
*/
@@ -3165,6 +3160,8 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
ugeth->txBd[txQ] = bd;
+ skb_tx_timestamp(skb);
+
if (ugeth->p_scheduler) {
ugeth->cpucount[txQ]++;
/* Indicate to QE that there are more Tx bds ready for
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 6998aa6b7bb7..52502883523e 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -1502,6 +1502,10 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x04f1, 0x3008),
.driver_info = (unsigned long) &ax8817x_info,
}, {
+ // ASIX AX88772B 10/100
+ USB_DEVICE (0x0b95, 0x772b),
+ .driver_info = (unsigned long) &ax88772_info,
+}, {
// ASIX AX88772 10/100
USB_DEVICE (0x0b95, 0x7720),
.driver_info = (unsigned long) &ax88772_info,
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index f967913e11bc..a60d0069cc45 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -21,6 +21,7 @@
*/
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/usb.h>
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index f33ca6aa29e9..fd622a66ebbf 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -47,7 +47,6 @@
#include <linux/mii.h>
#include <linux/crc32.h>
#include <linux/usb.h>
-#include <linux/version.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
#include <linux/atomic.h>
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 81126ff85e05..15772b1b6a91 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -409,12 +409,6 @@ static void ipheth_tx_timeout(struct net_device *net)
usb_unlink_urb(dev->tx_urb);
}
-static struct net_device_stats *ipheth_stats(struct net_device *net)
-{
- struct ipheth_device *dev = netdev_priv(net);
- return &dev->net->stats;
-}
-
static u32 ipheth_ethtool_op_get_link(struct net_device *net)
{
struct ipheth_device *dev = netdev_priv(net);
@@ -426,11 +420,10 @@ static struct ethtool_ops ops = {
};
static const struct net_device_ops ipheth_netdev_ops = {
- .ndo_open = &ipheth_open,
- .ndo_stop = &ipheth_close,
- .ndo_start_xmit = &ipheth_tx,
- .ndo_tx_timeout = &ipheth_tx_timeout,
- .ndo_get_stats = &ipheth_stats,
+ .ndo_open = ipheth_open,
+ .ndo_stop = ipheth_close,
+ .ndo_start_xmit = ipheth_tx,
+ .ndo_tx_timeout = ipheth_tx_timeout,
};
static int ipheth_probe(struct usb_interface *intf,
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
index a9b6c63d54e4..5a6d0f88f43b 100644
--- a/drivers/net/usb/kalmia.c
+++ b/drivers/net/usb/kalmia.c
@@ -100,13 +100,13 @@ kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
static int
kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
{
- const static char init_msg_1[] =
+ static const char init_msg_1[] =
{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00 };
- const static char init_msg_2[] =
+ static const char init_msg_2[] =
{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4,
0x00, 0x00 };
- const static int buflen = 28;
+ static const int buflen = 28;
char *usb_buf;
int status;
@@ -239,11 +239,11 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
* Our task here is to strip off framing, leaving skb with one
* data frame for the usbnet framework code to process.
*/
- const static u8 HEADER_END_OF_USB_PACKET[] =
+ static const u8 HEADER_END_OF_USB_PACKET[] =
{ 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 };
- const static u8 EXPECTED_UNKNOWN_HEADER_1[] =
+ static const u8 EXPECTED_UNKNOWN_HEADER_1[] =
{ 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 };
- const static u8 EXPECTED_UNKNOWN_HEADER_2[] =
+ static const u8 EXPECTED_UNKNOWN_HEADER_2[] =
{ 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 };
int i = 0;
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 8461576fa015..7f78db7bd68d 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
+#include <linux/u64_stats_sync.h>
#include <net/dst.h>
#include <net/xfrm.h>
@@ -24,12 +25,12 @@
#define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */
struct veth_net_stats {
- unsigned long rx_packets;
- unsigned long tx_packets;
- unsigned long rx_bytes;
- unsigned long tx_bytes;
- unsigned long tx_dropped;
- unsigned long rx_dropped;
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ u64 rx_dropped;
+ struct u64_stats_sync syncp;
};
struct veth_priv {
@@ -124,9 +125,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
stats = this_cpu_ptr(priv->stats);
rcv_stats = this_cpu_ptr(rcv_priv->stats);
- if (!(rcv->flags & IFF_UP))
- goto tx_drop;
-
/* don't change ip_summed == CHECKSUM_PARTIAL, as that
will cause bad checksum on forwarded packets */
if (skb->ip_summed == CHECKSUM_NONE &&
@@ -137,21 +135,22 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
goto rx_drop;
+ u64_stats_update_begin(&stats->syncp);
stats->tx_bytes += length;
stats->tx_packets++;
+ u64_stats_update_end(&stats->syncp);
+ u64_stats_update_begin(&rcv_stats->syncp);
rcv_stats->rx_bytes += length;
rcv_stats->rx_packets++;
+ u64_stats_update_end(&rcv_stats->syncp);
return NETDEV_TX_OK;
-tx_drop:
- kfree_skb(skb);
- stats->tx_dropped++;
- return NETDEV_TX_OK;
-
rx_drop:
+ u64_stats_update_begin(&rcv_stats->syncp);
rcv_stats->rx_dropped++;
+ u64_stats_update_end(&rcv_stats->syncp);
return NETDEV_TX_OK;
}
@@ -159,32 +158,34 @@ rx_drop:
* general routines
*/
-static struct net_device_stats *veth_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *veth_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
{
- struct veth_priv *priv;
+ struct veth_priv *priv = netdev_priv(dev);
int cpu;
- struct veth_net_stats *stats, total = {0};
-
- priv = netdev_priv(dev);
for_each_possible_cpu(cpu) {
- stats = per_cpu_ptr(priv->stats, cpu);
-
- total.rx_packets += stats->rx_packets;
- total.tx_packets += stats->tx_packets;
- total.rx_bytes += stats->rx_bytes;
- total.tx_bytes += stats->tx_bytes;
- total.tx_dropped += stats->tx_dropped;
- total.rx_dropped += stats->rx_dropped;
+ struct veth_net_stats *stats = per_cpu_ptr(priv->stats, cpu);
+ u64 rx_packets, rx_bytes, rx_dropped;
+ u64 tx_packets, tx_bytes;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->syncp);
+ rx_packets = stats->rx_packets;
+ tx_packets = stats->tx_packets;
+ rx_bytes = stats->rx_bytes;
+ tx_bytes = stats->tx_bytes;
+ rx_dropped = stats->rx_dropped;
+ } while (u64_stats_fetch_retry_bh(&stats->syncp, start));
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ tot->rx_dropped += rx_dropped;
}
- dev->stats.rx_packets = total.rx_packets;
- dev->stats.tx_packets = total.tx_packets;
- dev->stats.rx_bytes = total.rx_bytes;
- dev->stats.tx_bytes = total.tx_bytes;
- dev->stats.tx_dropped = total.tx_dropped;
- dev->stats.rx_dropped = total.rx_dropped;
-
- return &dev->stats;
+
+ return tot;
}
static int veth_open(struct net_device *dev)
@@ -254,7 +255,7 @@ static const struct net_device_ops veth_netdev_ops = {
.ndo_stop = veth_close,
.ndo_start_xmit = veth_xmit,
.ndo_change_mtu = veth_change_mtu,
- .ndo_get_stats = veth_get_stats,
+ .ndo_get_stats64 = veth_get_stats64,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 06daa9d6fee8..deb1eca13c9f 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -45,6 +45,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/errno.h>
@@ -501,6 +502,7 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
static void velocity_init_cam_filter(struct velocity_info *vptr)
{
struct mac_regs __iomem *regs = vptr->mac_regs;
+ unsigned int vid, i = 0;
/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
@@ -513,30 +515,17 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
mac_set_cam_mask(regs, vptr->mCAMmask);
/* Enable VCAMs */
- if (vptr->vlgrp) {
- unsigned int vid, i = 0;
-
- if (!vlan_group_get_device(vptr->vlgrp, 0))
- WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
-
- for (vid = 1; (vid < VLAN_VID_MASK); vid++) {
- if (vlan_group_get_device(vptr->vlgrp, vid)) {
- mac_set_vlan_cam(regs, i, (u8 *) &vid);
- vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
- if (++i >= VCAM_SIZE)
- break;
- }
- }
- mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
- }
-}
-static void velocity_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
-{
- struct velocity_info *vptr = netdev_priv(dev);
+ if (test_bit(0, vptr->active_vlans))
+ WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
- vptr->vlgrp = grp;
+ for_each_set_bit(vid, vptr->active_vlans, VLAN_N_VID) {
+ mac_set_vlan_cam(regs, i, (u8 *) &vid);
+ vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
+ if (++i >= VCAM_SIZE)
+ break;
+ }
+ mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
}
static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
@@ -544,6 +533,7 @@ static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
struct velocity_info *vptr = netdev_priv(dev);
spin_lock_irq(&vptr->lock);
+ set_bit(vid, vptr->active_vlans);
velocity_init_cam_filter(vptr);
spin_unlock_irq(&vptr->lock);
}
@@ -553,7 +543,7 @@ static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid
struct velocity_info *vptr = netdev_priv(dev);
spin_lock_irq(&vptr->lock);
- vlan_group_set_device(vptr->vlgrp, vid, NULL);
+ clear_bit(vid, vptr->active_vlans);
velocity_init_cam_filter(vptr);
spin_unlock_irq(&vptr->lock);
}
@@ -1887,7 +1877,7 @@ static void velocity_error(struct velocity_info *vptr, int status)
else
netif_wake_queue(vptr->dev);
- };
+ }
if (status & ISR_MIBFI)
velocity_update_hw_mibs(vptr);
if (status & ISR_LSTEI)
@@ -2094,11 +2084,12 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
skb_put(skb, pkt_len - 4);
skb->protocol = eth_type_trans(skb, vptr->dev);
- if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) {
- vlan_hwaccel_rx(skb, vptr->vlgrp,
- swab16(le16_to_cpu(rd->rdesc1.PQTAG)));
- } else
- netif_rx(skb);
+ if (rd->rdesc0.RSR & RSR_DETAG) {
+ u16 vid = swab16(le16_to_cpu(rd->rdesc1.PQTAG));
+
+ __vlan_hwaccel_put_tag(skb, vid);
+ }
+ netif_rx(skb);
stats->rx_bytes += pkt_len;
@@ -2641,7 +2632,6 @@ static const struct net_device_ops velocity_netdev_ops = {
.ndo_do_ioctl = velocity_ioctl,
.ndo_vlan_rx_add_vid = velocity_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = velocity_vlan_rx_kill_vid,
- .ndo_vlan_rx_register = velocity_vlan_rx_register,
};
/**
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index 0f1f05f6c4f8..4cb9f13485e9 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -1437,7 +1437,7 @@ struct velocity_info {
struct pci_dev *pdev;
struct net_device *dev;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u8 ip_addr[4];
enum chip_type chip_id;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f6853247a620..0c7321c35ad4 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -40,6 +40,15 @@ module_param(gso, bool, 0444);
#define VIRTNET_SEND_COMMAND_SG_MAX 2
+struct virtnet_stats {
+ struct u64_stats_sync syncp;
+ u64 tx_bytes;
+ u64 tx_packets;
+
+ u64 rx_bytes;
+ u64 rx_packets;
+};
+
struct virtnet_info {
struct virtio_device *vdev;
struct virtqueue *rvq, *svq, *cvq;
@@ -56,6 +65,9 @@ struct virtnet_info {
/* Host will merge rx buffers for big packets (shake it! shake it!) */
bool mergeable_rx_bufs;
+ /* Active statistics */
+ struct virtnet_stats __percpu *stats;
+
/* Work struct for refilling if we run low on memory. */
struct delayed_work refill;
@@ -209,7 +221,6 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
skb->dev->stats.rx_length_errors++;
return -EINVAL;
}
-
page = virtqueue_get_buf(vi->rvq, &len);
if (!page) {
pr_debug("%s: rx error: %d buffers missing\n",
@@ -217,6 +228,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
skb->dev->stats.rx_length_errors++;
return -EINVAL;
}
+
if (len > PAGE_SIZE)
len = PAGE_SIZE;
@@ -230,6 +242,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
{
struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
struct sk_buff *skb;
struct page *page;
struct skb_vnet_hdr *hdr;
@@ -265,8 +278,11 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
hdr = skb_vnet_hdr(skb);
skb->truesize += skb->data_len;
- dev->stats.rx_bytes += skb->len;
- dev->stats.rx_packets++;
+
+ u64_stats_update_begin(&stats->syncp);
+ stats->rx_bytes += skb->len;
+ stats->rx_packets++;
+ u64_stats_update_end(&stats->syncp);
if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
pr_debug("Needs csum!\n");
@@ -274,6 +290,8 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
hdr->hdr.csum_start,
hdr->hdr.csum_offset))
goto frame_err;
+ } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
}
skb->protocol = eth_type_trans(skb, dev);
@@ -513,11 +531,16 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
{
struct sk_buff *skb;
unsigned int len, tot_sgs = 0;
+ struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
pr_debug("Sent skb %p\n", skb);
- vi->dev->stats.tx_bytes += skb->len;
- vi->dev->stats.tx_packets++;
+
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+ u64_stats_update_end(&stats->syncp);
+
tot_sgs += skb_vnet_hdr(skb)->num_sg;
dev_kfree_skb_any(skb);
}
@@ -639,6 +662,40 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
return 0;
}
+static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ int cpu;
+ unsigned int start;
+
+ for_each_possible_cpu(cpu) {
+ struct virtnet_stats __percpu *stats
+ = per_cpu_ptr(vi->stats, cpu);
+ u64 tpackets, tbytes, rpackets, rbytes;
+
+ do {
+ start = u64_stats_fetch_begin(&stats->syncp);
+ tpackets = stats->tx_packets;
+ tbytes = stats->tx_bytes;
+ rpackets = stats->rx_packets;
+ rbytes = stats->rx_bytes;
+ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ tot->rx_packets += rpackets;
+ tot->tx_packets += tpackets;
+ tot->rx_bytes += rbytes;
+ tot->tx_bytes += tbytes;
+ }
+
+ tot->tx_dropped = dev->stats.tx_dropped;
+ tot->rx_dropped = dev->stats.rx_dropped;
+ tot->rx_length_errors = dev->stats.rx_length_errors;
+ tot->rx_frame_errors = dev->stats.rx_frame_errors;
+
+ return tot;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void virtnet_netpoll(struct net_device *dev)
{
@@ -833,6 +890,7 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_set_mac_address = virtnet_set_mac_address,
.ndo_set_rx_mode = virtnet_set_rx_mode,
.ndo_change_mtu = virtnet_change_mtu,
+ .ndo_get_stats64 = virtnet_stats,
.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -893,6 +951,7 @@ static int virtnet_probe(struct virtio_device *vdev)
/* Set up network device as normal. */
dev->netdev_ops = &virtnet_netdev;
dev->features = NETIF_F_HIGHDMA;
+
SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
SET_NETDEV_DEV(dev, &vdev->dev);
@@ -937,6 +996,11 @@ static int virtnet_probe(struct virtio_device *vdev)
vi->vdev = vdev;
vdev->priv = vi;
vi->pages = NULL;
+ vi->stats = alloc_percpu(struct virtnet_stats);
+ err = -ENOMEM;
+ if (vi->stats == NULL)
+ goto free;
+
INIT_DELAYED_WORK(&vi->refill, refill_work);
sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
@@ -956,7 +1020,7 @@ static int virtnet_probe(struct virtio_device *vdev)
err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names);
if (err)
- goto free;
+ goto free_stats;
vi->rvq = vqs[0];
vi->svq = vqs[1];
@@ -1001,6 +1065,8 @@ unregister:
cancel_delayed_work_sync(&vi->refill);
free_vqs:
vdev->config->del_vqs(vdev);
+free_stats:
+ free_percpu(vi->stats);
free:
free_netdev(dev);
return err;
@@ -1047,6 +1113,7 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
while (vi->pages)
__free_pages(get_a_page(vi, GFP_KERNEL), 0);
+ free_percpu(vi->stats);
free_netdev(vi->dev);
}
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 67402350d0df..1cbacb389652 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -405,10 +405,8 @@ vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq,
while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) {
struct vmxnet3_tx_buf_info *tbi;
- union Vmxnet3_GenericDesc *gdesc;
tbi = tq->buf_info + tq->tx_ring.next2comp;
- gdesc = tq->tx_ring.base + tq->tx_ring.next2comp;
vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
if (tbi->skb) {
@@ -926,7 +924,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
skb_shinfo(skb)->nr_frags + 1;
- ctx.ipv4 = (skb->protocol == cpu_to_be16(ETH_P_IP));
+ ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
ctx.mss = skb_shinfo(skb)->gso_size;
if (ctx.mss) {
@@ -1285,12 +1283,13 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
(union Vmxnet3_GenericDesc *)rcd);
skb->protocol = eth_type_trans(skb, adapter->netdev);
- if (unlikely(adapter->vlan_grp && rcd->ts)) {
- vlan_hwaccel_receive_skb(skb,
- adapter->vlan_grp, rcd->tci);
- } else {
+ if (unlikely(rcd->ts))
+ __vlan_hwaccel_put_tag(skb, rcd->tci);
+
+ if (adapter->netdev->features & NETIF_F_LRO)
netif_receive_skb(skb);
- }
+ else
+ napi_gro_receive(&rq->napi, skb);
ctx->skb = NULL;
}
@@ -1911,79 +1910,18 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
}
}
-static void
-vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
- struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- struct Vmxnet3_DriverShared *shared = adapter->shared;
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
-
- if (grp) {
- /* add vlan rx stripping. */
- if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
- int i;
- adapter->vlan_grp = grp;
-
- /*
- * Clear entire vfTable; then enable untagged pkts.
- * Note: setting one entry in vfTable to non-zero turns
- * on VLAN rx filtering.
- */
- for (i = 0; i < VMXNET3_VFT_SIZE; i++)
- vfTable[i] = 0;
-
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- } else {
- printk(KERN_ERR "%s: vlan_rx_register when device has "
- "no NETIF_F_HW_VLAN_RX\n", netdev->name);
- }
- } else {
- /* remove vlan rx stripping. */
- struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
- adapter->vlan_grp = NULL;
-
- if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) {
- int i;
-
- for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
- /* clear entire vfTable; this also disables
- * VLAN rx filtering
- */
- vfTable[i] = 0;
- }
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- }
- }
-}
-
static void
vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
{
- if (adapter->vlan_grp) {
- u16 vid;
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- bool activeVlan = false;
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (vlan_group_get_device(adapter->vlan_grp, vid)) {
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
- activeVlan = true;
- }
- }
- if (activeVlan) {
- /* continue to allow untagged pkts */
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- }
- }
+ /* allow untagged pkts */
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
}
@@ -1999,6 +1937,8 @@ vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_VLAN_FILTERS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+ set_bit(vid, adapter->active_vlans);
}
@@ -2014,6 +1954,8 @@ vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_VLAN_FILTERS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+ clear_bit(vid, adapter->active_vlans);
}
@@ -2050,8 +1992,14 @@ vmxnet3_set_mc(struct net_device *netdev)
u8 *new_table = NULL;
u32 new_mode = VMXNET3_RXM_UCAST;
- if (netdev->flags & IFF_PROMISC)
+ if (netdev->flags & IFF_PROMISC) {
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ memset(vfTable, 0, VMXNET3_VFT_SIZE * sizeof(*vfTable));
+
new_mode |= VMXNET3_RXM_PROMISC;
+ } else {
+ vmxnet3_restore_vlan(adapter);
+ }
if (netdev->flags & IFF_BROADCAST)
new_mode |= VMXNET3_RXM_BCAST;
@@ -2085,6 +2033,8 @@ vmxnet3_set_mc(struct net_device *netdev)
rxConf->rxMode = cpu_to_le32(new_mode);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_RX_MODE);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
}
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
@@ -2694,12 +2644,13 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter, bool dma64)
netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX |
- NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_LRO;
+ NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_LRO;
if (dma64)
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->vlan_features = netdev->hw_features & ~NETIF_F_HW_VLAN_TX;
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+ netdev->hw_features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features = netdev->hw_features &
+ ~(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+ netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_FILTER;
netdev_info(adapter->netdev,
"features: sg csum vlan jf tso tsoIPv6 lro%s\n",
@@ -2917,10 +2868,9 @@ vmxnet3_probe_device(struct pci_dev *pdev,
.ndo_set_mac_address = vmxnet3_set_mac_addr,
.ndo_change_mtu = vmxnet3_change_mtu,
.ndo_set_features = vmxnet3_set_features,
- .ndo_get_stats = vmxnet3_get_stats,
+ .ndo_get_stats64 = vmxnet3_get_stats64,
.ndo_tx_timeout = vmxnet3_tx_timeout,
.ndo_set_multicast_list = vmxnet3_set_mc,
- .ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
.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
@@ -3043,6 +2993,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
goto err_ver;
}
+ SET_NETDEV_DEV(netdev, &pdev->dev);
vmxnet3_declare_features(adapter, dma64);
adapter->dev_number = atomic_read(&devices_found);
@@ -3088,7 +3039,6 @@ vmxnet3_probe_device(struct pci_dev *pdev,
netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues);
- SET_NETDEV_DEV(netdev, &pdev->dev);
err = register_netdev(netdev);
if (err) {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index dc959fe27aa5..27400edeef55 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -113,15 +113,15 @@ vmxnet3_global_stats[] = {
};
-struct net_device_stats *
-vmxnet3_get_stats(struct net_device *netdev)
+struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
struct vmxnet3_adapter *adapter;
struct vmxnet3_tq_driver_stats *drvTxStats;
struct vmxnet3_rq_driver_stats *drvRxStats;
struct UPT1_TxStats *devTxStats;
struct UPT1_RxStats *devRxStats;
- struct net_device_stats *net_stats = &netdev->stats;
unsigned long flags;
int i;
@@ -132,36 +132,36 @@ vmxnet3_get_stats(struct net_device *netdev)
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- memset(net_stats, 0, sizeof(*net_stats));
for (i = 0; i < adapter->num_tx_queues; i++) {
devTxStats = &adapter->tqd_start[i].stats;
drvTxStats = &adapter->tx_queue[i].stats;
- net_stats->tx_packets += devTxStats->ucastPktsTxOK +
- devTxStats->mcastPktsTxOK +
- devTxStats->bcastPktsTxOK;
- net_stats->tx_bytes += devTxStats->ucastBytesTxOK +
- devTxStats->mcastBytesTxOK +
- devTxStats->bcastBytesTxOK;
- net_stats->tx_errors += devTxStats->pktsTxError;
- net_stats->tx_dropped += drvTxStats->drop_total;
+ stats->tx_packets += devTxStats->ucastPktsTxOK +
+ devTxStats->mcastPktsTxOK +
+ devTxStats->bcastPktsTxOK;
+ stats->tx_bytes += devTxStats->ucastBytesTxOK +
+ devTxStats->mcastBytesTxOK +
+ devTxStats->bcastBytesTxOK;
+ stats->tx_errors += devTxStats->pktsTxError;
+ stats->tx_dropped += drvTxStats->drop_total;
}
for (i = 0; i < adapter->num_rx_queues; i++) {
devRxStats = &adapter->rqd_start[i].stats;
drvRxStats = &adapter->rx_queue[i].stats;
- net_stats->rx_packets += devRxStats->ucastPktsRxOK +
- devRxStats->mcastPktsRxOK +
- devRxStats->bcastPktsRxOK;
+ stats->rx_packets += devRxStats->ucastPktsRxOK +
+ devRxStats->mcastPktsRxOK +
+ devRxStats->bcastPktsRxOK;
- net_stats->rx_bytes += devRxStats->ucastBytesRxOK +
- devRxStats->mcastBytesRxOK +
- devRxStats->bcastBytesRxOK;
+ stats->rx_bytes += devRxStats->ucastBytesRxOK +
+ devRxStats->mcastBytesRxOK +
+ devRxStats->bcastBytesRxOK;
- net_stats->rx_errors += devRxStats->pktsRxError;
- net_stats->rx_dropped += drvRxStats->drop_total;
- net_stats->multicast += devRxStats->mcastPktsRxOK;
+ stats->rx_errors += devRxStats->pktsRxError;
+ stats->rx_dropped += drvRxStats->drop_total;
+ stats->multicast += devRxStats->mcastPktsRxOK;
}
- return net_stats;
+
+ return stats;
}
static int
@@ -268,7 +268,7 @@ int vmxnet3_set_features(struct net_device *netdev, u32 features)
unsigned long flags;
u32 changed = features ^ netdev->features;
- if (changed & (NETIF_F_RXCSUM|NETIF_F_LRO)) {
+ if (changed & (NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_RX)) {
if (features & NETIF_F_RXCSUM)
adapter->shared->devRead.misc.uptFeatures |=
UPT1_F_RXCSUM;
@@ -284,6 +284,13 @@ int vmxnet3_set_features(struct net_device *netdev, u32 features)
adapter->shared->devRead.misc.uptFeatures &=
~UPT1_F_LRO;
+ if (features & NETIF_F_HW_VLAN_RX)
+ adapter->shared->devRead.misc.uptFeatures |=
+ UPT1_F_RXVLAN;
+ else
+ adapter->shared->devRead.misc.uptFeatures &=
+ ~UPT1_F_RXVLAN;
+
spin_lock_irqsave(&adapter->cmd_lock, flags);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_FEATURE);
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index e08d75e3f170..b18eac1dccaa 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -27,6 +27,7 @@
#ifndef _VMXNET3_INT_H
#define _VMXNET3_INT_H
+#include <linux/bitops.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
@@ -316,7 +317,7 @@ struct vmxnet3_intr {
struct vmxnet3_adapter {
struct vmxnet3_tx_queue tx_queue[VMXNET3_DEVICE_MAX_TX_QUEUES];
struct vmxnet3_rx_queue rx_queue[VMXNET3_DEVICE_MAX_RX_QUEUES];
- struct vlan_group *vlan_grp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct vmxnet3_intr intr;
spinlock_t cmd_lock;
struct Vmxnet3_DriverShared *shared;
@@ -324,7 +325,6 @@ struct vmxnet3_adapter {
struct Vmxnet3_TxQueueDesc *tqd_start; /* all tx queue desc */
struct Vmxnet3_RxQueueDesc *rqd_start; /* all rx queue desc */
struct net_device *netdev;
- struct net_device_stats net_stats;
struct pci_dev *pdev;
u8 __iomem *hw_addr0; /* for BAR 0 */
@@ -408,7 +408,9 @@ vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size);
extern void vmxnet3_set_ethtool_ops(struct net_device *netdev);
-extern struct net_device_stats *vmxnet3_get_stats(struct net_device *netdev);
+
+extern struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
extern char vmxnet3_driver_name[];
#endif
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
index 32763b2dd73f..1520c574cb20 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/vxge/vxge-config.c
@@ -582,7 +582,7 @@ __vxge_hw_device_toc_get(void __iomem *bar0)
goto exit;
val64 = readq(&legacy_reg->toc_first_pointer);
- toc = (struct vxge_hw_toc_reg __iomem *)(bar0+val64);
+ toc = bar0 + val64;
exit:
return toc;
}
@@ -600,7 +600,7 @@ __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
u32 i;
enum vxge_hw_status status = VXGE_HW_OK;
- hldev->legacy_reg = (struct vxge_hw_legacy_reg __iomem *)hldev->bar0;
+ hldev->legacy_reg = hldev->bar0;
hldev->toc_reg = __vxge_hw_device_toc_get(hldev->bar0);
if (hldev->toc_reg == NULL) {
@@ -609,39 +609,31 @@ __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
}
val64 = readq(&hldev->toc_reg->toc_common_pointer);
- hldev->common_reg =
- (struct vxge_hw_common_reg __iomem *)(hldev->bar0 + val64);
+ hldev->common_reg = hldev->bar0 + val64;
val64 = readq(&hldev->toc_reg->toc_mrpcim_pointer);
- hldev->mrpcim_reg =
- (struct vxge_hw_mrpcim_reg __iomem *)(hldev->bar0 + val64);
+ hldev->mrpcim_reg = hldev->bar0 + val64;
for (i = 0; i < VXGE_HW_TITAN_SRPCIM_REG_SPACES; i++) {
val64 = readq(&hldev->toc_reg->toc_srpcim_pointer[i]);
- hldev->srpcim_reg[i] =
- (struct vxge_hw_srpcim_reg __iomem *)
- (hldev->bar0 + val64);
+ hldev->srpcim_reg[i] = hldev->bar0 + val64;
}
for (i = 0; i < VXGE_HW_TITAN_VPMGMT_REG_SPACES; i++) {
val64 = readq(&hldev->toc_reg->toc_vpmgmt_pointer[i]);
- hldev->vpmgmt_reg[i] =
- (struct vxge_hw_vpmgmt_reg __iomem *)(hldev->bar0 + val64);
+ hldev->vpmgmt_reg[i] = hldev->bar0 + val64;
}
for (i = 0; i < VXGE_HW_TITAN_VPATH_REG_SPACES; i++) {
val64 = readq(&hldev->toc_reg->toc_vpath_pointer[i]);
- hldev->vpath_reg[i] =
- (struct vxge_hw_vpath_reg __iomem *)
- (hldev->bar0 + val64);
+ hldev->vpath_reg[i] = hldev->bar0 + val64;
}
val64 = readq(&hldev->toc_reg->toc_kdfc);
switch (VXGE_HW_TOC_GET_KDFC_INITIAL_BIR(val64)) {
case 0:
- hldev->kdfc = (u8 __iomem *)(hldev->bar0 +
- VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
+ hldev->kdfc = hldev->bar0 + VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64) ;
break;
default:
break;
@@ -761,12 +753,11 @@ static void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev)
static enum vxge_hw_status
__vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev)
{
- int exp_cap;
+ struct pci_dev *dev = hldev->pdev;
u16 lnk;
/* Get the negotiated link width and speed from PCI config space */
- exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
- pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
+ pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
if ((lnk & PCI_EXP_LNKSTA_CLS) != 1)
return VXGE_HW_ERR_INVALID_PCI_INFO;
@@ -1024,7 +1015,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
}
val64 = readq(&toc->toc_common_pointer);
- common_reg = (struct vxge_hw_common_reg __iomem *)(bar0 + val64);
+ common_reg = bar0 + val64;
status = __vxge_hw_device_vpath_reset_in_prog_check(
(u64 __iomem *)&common_reg->vpath_rst_in_prog);
@@ -1044,8 +1035,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
val64 = readq(&toc->toc_vpmgmt_pointer[i]);
- vpmgmt_reg = (struct vxge_hw_vpmgmt_reg __iomem *)
- (bar0 + val64);
+ vpmgmt_reg = bar0 + val64;
hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg);
if (__vxge_hw_device_access_rights_get(hw_info->host_type,
@@ -1054,8 +1044,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
val64 = readq(&toc->toc_mrpcim_pointer);
- mrpcim_reg = (struct vxge_hw_mrpcim_reg __iomem *)
- (bar0 + val64);
+ mrpcim_reg = bar0 + val64;
writeq(0, &mrpcim_reg->xgmac_gen_fw_memo_mask);
wmb();
@@ -1064,8 +1053,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
val64 = readq(&toc->toc_vpath_pointer[i]);
spin_lock_init(&vpath.lock);
- vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
- (bar0 + val64);
+ vpath.vp_reg = bar0 + val64;
vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info);
@@ -1088,8 +1076,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
continue;
val64 = readq(&toc->toc_vpath_pointer[i]);
- vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
- (bar0 + val64);
+ vpath.vp_reg = bar0 + val64;
vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
status = __vxge_hw_vpath_addr_get(&vpath,
@@ -1994,13 +1981,11 @@ exit:
u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *hldev)
{
- int link_width, exp_cap;
+ struct pci_dev *dev = hldev->pdev;
u16 lnk;
- exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
- pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
- link_width = (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
- return link_width;
+ pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
+ return (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
}
/*
@@ -2140,8 +2125,7 @@ __vxge_hw_ring_mempool_item_alloc(struct vxge_hw_mempool *mempoolh,
memblock_index, item,
&memblock_item_idx);
- rxdp = (struct vxge_hw_ring_rxd_1 *)
- ring->channel.reserve_arr[reserve_index];
+ rxdp = ring->channel.reserve_arr[reserve_index];
uld_priv = ((u8 *)rxdblock_priv + ring->rxd_priv_size * i);
@@ -4880,8 +4864,7 @@ vxge_hw_vpath_open(struct __vxge_hw_device *hldev,
goto vpath_open_exit8;
}
- vpath->hw_stats = (struct vxge_hw_vpath_stats_hw_info *)vpath->
- stats_block->memblock;
+ vpath->hw_stats = vpath->stats_block->memblock;
memset(vpath->hw_stats, 0,
sizeof(struct vxge_hw_vpath_stats_hw_info));
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h
index 359b9b9f8041..dd362584f5ca 100644
--- a/drivers/net/vxge/vxge-config.h
+++ b/drivers/net/vxge/vxge-config.h
@@ -13,8 +13,10 @@
******************************************************************************/
#ifndef VXGE_CONFIG_H
#define VXGE_CONFIG_H
+#include <linux/hardirq.h>
#include <linux/list.h>
#include <linux/slab.h>
+#include <asm/io.h>
#ifndef VXGE_CACHE_LINE_SIZE
#define VXGE_CACHE_LINE_SIZE 128
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index 8ab870a2ad02..178348a258d2 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -43,7 +43,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/bitops.h>
#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/tcp.h>
@@ -295,23 +297,22 @@ vxge_rx_complete(struct vxge_ring *ring, struct sk_buff *skb, u16 vlan,
skb_record_rx_queue(skb, ring->driver_id);
skb->protocol = eth_type_trans(skb, ring->ndev);
+ u64_stats_update_begin(&ring->stats.syncp);
ring->stats.rx_frms++;
ring->stats.rx_bytes += pkt_length;
if (skb->pkt_type == PACKET_MULTICAST)
ring->stats.rx_mcast++;
+ u64_stats_update_end(&ring->stats.syncp);
vxge_debug_rx(VXGE_TRACE,
"%s: %s:%d skb protocol = %d",
ring->ndev->name, __func__, __LINE__, skb->protocol);
- if (ring->vlgrp && ext_info->vlan &&
- (ring->vlan_tag_strip ==
- VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE))
- vlan_gro_receive(ring->napi_p, ring->vlgrp,
- ext_info->vlan, skb);
- else
- napi_gro_receive(ring->napi_p, skb);
+ if (ext_info->vlan &&
+ ring->vlan_tag_strip == VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE)
+ __vlan_hwaccel_put_tag(skb, ext_info->vlan);
+ napi_gro_receive(ring->napi_p, skb);
vxge_debug_entryexit(VXGE_TRACE,
"%s: %s:%d Exiting...", ring->ndev->name, __func__, __LINE__);
@@ -591,8 +592,10 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
vxge_hw_fifo_txdl_free(fifo_hw, dtr);
/* Updating the statistics block */
+ u64_stats_update_begin(&fifo->stats.syncp);
fifo->stats.tx_frms++;
fifo->stats.tx_bytes += skb->len;
+ u64_stats_update_end(&fifo->stats.syncp);
*done_skb++ = skb;
@@ -628,7 +631,7 @@ static u32 vxge_get_vpath_no(struct vxgedev *vdev, struct sk_buff *skb)
ip = ip_hdr(skb);
- if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+ if (!ip_is_fragment(ip)) {
th = (struct tcphdr *)(((unsigned char *)ip) +
ip->ihl*4);
@@ -679,8 +682,7 @@ static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac)
new_mac_entry->state = mac->state;
vpath->mac_addr_cnt++;
- /* Is this a multicast address */
- if (0x01 & mac->macaddr[0])
+ if (is_multicast_ether_addr(mac->macaddr))
vpath->mcast_addr_cnt++;
return TRUE;
@@ -694,7 +696,7 @@ vxge_add_mac_addr(struct vxgedev *vdev, struct macInfo *mac)
struct vxge_vpath *vpath;
enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode;
- if (0x01 & mac->macaddr[0]) /* multicast address */
+ if (is_multicast_ether_addr(mac->macaddr))
duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE;
else
duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE;
@@ -1073,8 +1075,7 @@ static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac)
kfree((struct vxge_mac_addrs *)entry);
vpath->mac_addr_cnt--;
- /* Is this a multicast address */
- if (0x01 & mac->macaddr[0])
+ if (is_multicast_ether_addr(mac->macaddr))
vpath->mcast_addr_cnt--;
return TRUE;
}
@@ -1196,8 +1197,7 @@ static void vxge_set_multicast(struct net_device *dev)
mac_address = (u8 *)&mac_entry->macaddr;
memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
- /* Is this a multicast address */
- if (0x01 & mac_info.macaddr[0]) {
+ if (is_multicast_ether_addr(mac_info.macaddr)) {
for (vpath_idx = 0; vpath_idx <
vdev->no_of_vpath;
vpath_idx++) {
@@ -1239,8 +1239,7 @@ _set_all_mcast:
mac_address = (u8 *)&mac_entry->macaddr;
memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
- /* Is this a multicast address */
- if (0x01 & mac_info.macaddr[0])
+ if (is_multicast_ether_addr(mac_info.macaddr))
break;
}
@@ -1488,15 +1487,11 @@ vxge_restore_vpath_vid_table(struct vxge_vpath *vpath)
struct vxgedev *vdev = vpath->vdev;
u16 vid;
- if (vdev->vlgrp && vpath->is_open) {
+ if (!vpath->is_open)
+ return status;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(vdev->vlgrp, vid))
- continue;
- /* Add these vlan to the vid table */
- status = vxge_hw_vpath_vid_add(vpath->handle, vid);
- }
- }
+ for_each_set_bit(vid, vdev->active_vlans, VLAN_N_VID)
+ status = vxge_hw_vpath_vid_add(vpath->handle, vid);
return status;
}
@@ -2629,11 +2624,16 @@ static void vxge_poll_vp_lockup(unsigned long data)
struct vxge_vpath *vpath;
struct vxge_ring *ring;
int i;
+ unsigned long rx_frms;
for (i = 0; i < vdev->no_of_vpath; i++) {
ring = &vdev->vpaths[i].ring;
+
+ /* Truncated to machine word size number of frames */
+ rx_frms = ACCESS_ONCE(ring->stats.rx_frms);
+
/* Did this vpath received any packets */
- if (ring->stats.prev_rx_frms == ring->stats.rx_frms) {
+ if (ring->stats.prev_rx_frms == rx_frms) {
status = vxge_hw_vpath_check_leak(ring->handle);
/* Did it received any packets last time */
@@ -2653,7 +2653,7 @@ static void vxge_poll_vp_lockup(unsigned long data)
}
}
}
- ring->stats.prev_rx_frms = ring->stats.rx_frms;
+ ring->stats.prev_rx_frms = rx_frms;
ring->last_status = status;
}
@@ -3124,14 +3124,36 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
/* net_stats already zeroed by caller */
for (k = 0; k < vdev->no_of_vpath; k++) {
- net_stats->rx_packets += vdev->vpaths[k].ring.stats.rx_frms;
- net_stats->rx_bytes += vdev->vpaths[k].ring.stats.rx_bytes;
- net_stats->rx_errors += vdev->vpaths[k].ring.stats.rx_errors;
- net_stats->multicast += vdev->vpaths[k].ring.stats.rx_mcast;
- net_stats->rx_dropped += vdev->vpaths[k].ring.stats.rx_dropped;
- net_stats->tx_packets += vdev->vpaths[k].fifo.stats.tx_frms;
- net_stats->tx_bytes += vdev->vpaths[k].fifo.stats.tx_bytes;
- net_stats->tx_errors += vdev->vpaths[k].fifo.stats.tx_errors;
+ struct vxge_ring_stats *rxstats = &vdev->vpaths[k].ring.stats;
+ struct vxge_fifo_stats *txstats = &vdev->vpaths[k].fifo.stats;
+ unsigned int start;
+ u64 packets, bytes, multicast;
+
+ do {
+ start = u64_stats_fetch_begin(&rxstats->syncp);
+
+ packets = rxstats->rx_frms;
+ multicast = rxstats->rx_mcast;
+ bytes = rxstats->rx_bytes;
+ } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+
+ net_stats->rx_packets += packets;
+ net_stats->rx_bytes += bytes;
+ net_stats->multicast += multicast;
+
+ net_stats->rx_errors += rxstats->rx_errors;
+ net_stats->rx_dropped += rxstats->rx_dropped;
+
+ do {
+ start = u64_stats_fetch_begin(&txstats->syncp);
+
+ packets = txstats->tx_frms;
+ bytes = txstats->tx_bytes;
+ } while (u64_stats_fetch_retry(&txstats->syncp, start));
+
+ net_stats->tx_packets += packets;
+ net_stats->tx_bytes += bytes;
+ net_stats->tx_errors += txstats->tx_errors;
}
return net_stats;
@@ -3275,60 +3297,6 @@ static void vxge_tx_watchdog(struct net_device *dev)
}
/**
- * vxge_vlan_rx_register
- * @dev: net device pointer.
- * @grp: vlan group
- *
- * Vlan group registration
- */
-static void
-vxge_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
- struct vxgedev *vdev;
- struct vxge_vpath *vpath;
- int vp;
- u64 vid;
- enum vxge_hw_status status;
- int i;
-
- vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
-
- vdev = netdev_priv(dev);
-
- vpath = &vdev->vpaths[0];
- if ((NULL == grp) && (vpath->is_open)) {
- /* Get the first vlan */
- status = vxge_hw_vpath_vid_get(vpath->handle, &vid);
-
- while (status == VXGE_HW_OK) {
-
- /* Delete this vlan from the vid table */
- for (vp = 0; vp < vdev->no_of_vpath; vp++) {
- vpath = &vdev->vpaths[vp];
- if (!vpath->is_open)
- continue;
-
- vxge_hw_vpath_vid_delete(vpath->handle, vid);
- }
-
- /* Get the next vlan to be deleted */
- vpath = &vdev->vpaths[0];
- status = vxge_hw_vpath_vid_get(vpath->handle, &vid);
- }
- }
-
- vdev->vlgrp = grp;
-
- for (i = 0; i < vdev->no_of_vpath; i++) {
- if (vdev->vpaths[i].is_configured)
- vdev->vpaths[i].ring.vlgrp = grp;
- }
-
- vxge_debug_entryexit(VXGE_TRACE,
- "%s:%d Exiting...", __func__, __LINE__);
-}
-
-/**
* vxge_vlan_rx_add_vid
* @dev: net device pointer.
* @vid: vid
@@ -3338,12 +3306,10 @@ vxge_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
static void
vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
- struct vxgedev *vdev;
+ struct vxgedev *vdev = netdev_priv(dev);
struct vxge_vpath *vpath;
int vp_id;
- vdev = netdev_priv(dev);
-
/* Add these vlan to the vid table */
for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
vpath = &vdev->vpaths[vp_id];
@@ -3351,6 +3317,7 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
continue;
vxge_hw_vpath_vid_add(vpath->handle, vid);
}
+ set_bit(vid, vdev->active_vlans);
}
/**
@@ -3363,16 +3330,12 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
static void
vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
- struct vxgedev *vdev;
+ struct vxgedev *vdev = netdev_priv(dev);
struct vxge_vpath *vpath;
int vp_id;
vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
- vdev = netdev_priv(dev);
-
- vlan_group_set_device(vdev->vlgrp, vid, NULL);
-
/* Delete this vlan from the vid table */
for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
vpath = &vdev->vpaths[vp_id];
@@ -3382,6 +3345,7 @@ vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
}
vxge_debug_entryexit(VXGE_TRACE,
"%s:%d Exiting...", __func__, __LINE__);
+ clear_bit(vid, vdev->active_vlans);
}
static const struct net_device_ops vxge_netdev_ops = {
@@ -3396,7 +3360,6 @@ static const struct net_device_ops vxge_netdev_ops = {
.ndo_change_mtu = vxge_change_mtu,
.ndo_fix_features = vxge_fix_features,
.ndo_set_features = vxge_set_features,
- .ndo_vlan_rx_register = vxge_vlan_rx_register,
.ndo_vlan_rx_kill_vid = vxge_vlan_rx_kill_vid,
.ndo_vlan_rx_add_vid = vxge_vlan_rx_add_vid,
.ndo_tx_timeout = vxge_tx_watchdog,
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index ed120aba443d..f52a42d1dbb7 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -18,6 +18,8 @@
#include "vxge-config.h"
#include "vxge-version.h"
#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
#define VXGE_DRIVER_NAME "vxge"
#define VXGE_DRIVER_VENDOR "Neterion, Inc"
@@ -201,30 +203,14 @@ struct vxge_msix_entry {
/* Software Statistics */
struct vxge_sw_stats {
- /* Network Stats (interface stats) */
-
- /* Tx */
- u64 tx_frms;
- u64 tx_errors;
- u64 tx_bytes;
- u64 txd_not_free;
- u64 txd_out_of_desc;
/* Virtual Path */
- u64 vpaths_open;
- u64 vpath_open_fail;
-
- /* Rx */
- u64 rx_frms;
- u64 rx_errors;
- u64 rx_bytes;
- u64 rx_mcast;
+ unsigned long vpaths_open;
+ unsigned long vpath_open_fail;
/* Misc. */
- u64 link_up;
- u64 link_down;
- u64 pci_map_fail;
- u64 skb_alloc_fail;
+ unsigned long link_up;
+ unsigned long link_down;
};
struct vxge_mac_addrs {
@@ -237,12 +223,14 @@ struct vxge_mac_addrs {
struct vxgedev;
struct vxge_fifo_stats {
+ struct u64_stats_sync syncp;
u64 tx_frms;
- u64 tx_errors;
u64 tx_bytes;
- u64 txd_not_free;
- u64 txd_out_of_desc;
- u64 pci_map_fail;
+
+ unsigned long tx_errors;
+ unsigned long txd_not_free;
+ unsigned long txd_out_of_desc;
+ unsigned long pci_map_fail;
};
struct vxge_fifo {
@@ -264,14 +252,16 @@ struct vxge_fifo {
} ____cacheline_aligned;
struct vxge_ring_stats {
- u64 prev_rx_frms;
+ struct u64_stats_sync syncp;
u64 rx_frms;
- u64 rx_errors;
- u64 rx_dropped;
- u64 rx_bytes;
u64 rx_mcast;
- u64 pci_map_fail;
- u64 skb_alloc_fail;
+ u64 rx_bytes;
+
+ unsigned long rx_errors;
+ unsigned long rx_dropped;
+ unsigned long prev_rx_frms;
+ unsigned long pci_map_fail;
+ unsigned long skb_alloc_fail;
};
struct vxge_ring {
@@ -299,7 +289,6 @@ struct vxge_ring {
#define VXGE_MAX_MAC_ADDR_COUNT 30
int vlan_tag_strip;
- struct vlan_group *vlgrp;
u32 rx_vector_no;
enum vxge_hw_status last_status;
@@ -344,7 +333,7 @@ struct vxgedev {
struct net_device *ndev;
struct pci_dev *pdev;
struct __vxge_hw_device *devh;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
int vlan_tag_strip;
struct vxge_config config;
unsigned long state;
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index f93517055162..ad64ce0afe3f 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -1309,7 +1309,7 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed(
vxge_hw_channel_dtr_try_complete(channel, rxdh);
- rxdp = (struct vxge_hw_ring_rxd_1 *)*rxdh;
+ rxdp = *rxdh;
if (rxdp == NULL) {
status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
goto exit;
@@ -1565,7 +1565,7 @@ void vxge_hw_fifo_txdl_post(struct __vxge_hw_fifo *fifo, void *txdlh)
channel = &fifo->channel;
txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdlh);
- txdp_first = (struct vxge_hw_fifo_txd *)txdlh;
+ txdp_first = txdlh;
txdp_last = (struct vxge_hw_fifo_txd *)txdlh + (txdl_priv->frags - 1);
txdp_last->control_0 |=
@@ -1631,7 +1631,7 @@ enum vxge_hw_status vxge_hw_fifo_txdl_next_completed(
vxge_hw_channel_dtr_try_complete(channel, txdlh);
- txdp = (struct vxge_hw_fifo_txd *)*txdlh;
+ txdp = *txdlh;
if (txdp == NULL) {
status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
goto exit;
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 4ac85a09c5a6..54f995f4a5a3 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -14,6 +14,8 @@
* Moxa C101 User's Manual
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -313,44 +315,44 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
int result;
if (irq<3 || irq>15 || irq == 6) /* FIXME */ {
- printk(KERN_ERR "c101: invalid IRQ value\n");
+ pr_err("invalid IRQ value\n");
return -ENODEV;
}
if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) !=0) {
- printk(KERN_ERR "c101: invalid RAM value\n");
+ pr_err("invalid RAM value\n");
return -ENODEV;
}
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "c101: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
return -ENOBUFS;
}
card->dev = alloc_hdlcdev(card);
if (!card->dev) {
- printk(KERN_ERR "c101: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
kfree(card);
return -ENOBUFS;
}
if (request_irq(irq, sca_intr, 0, devname, card)) {
- printk(KERN_ERR "c101: could not allocate IRQ\n");
+ pr_err("could not allocate IRQ\n");
c101_destroy_card(card);
return -EBUSY;
}
card->irq = irq;
if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
- printk(KERN_ERR "c101: could not request RAM window\n");
+ pr_err("could not request RAM window\n");
c101_destroy_card(card);
return -EBUSY;
}
card->phy_winbase = winbase;
card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
if (!card->win0base) {
- printk(KERN_ERR "c101: could not map I/O address\n");
+ pr_err("could not map I/O address\n");
c101_destroy_card(card);
return -EFAULT;
}
@@ -381,7 +383,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
result = register_hdlc_device(dev);
if (result) {
- printk(KERN_WARNING "c101: unable to register hdlc device\n");
+ pr_warn("unable to register hdlc device\n");
c101_destroy_card(card);
return result;
}
@@ -389,10 +391,8 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
sca_init_port(card); /* Set up C101 memory */
set_carrier(card);
- printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
- " using %u TX + %u RX packets rings\n",
- dev->name, card->irq,
- card->tx_ring_buffers, card->rx_ring_buffers);
+ netdev_info(dev, "Moxa C101 on IRQ%u, using %u TX + %u RX packets rings\n",
+ card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
*new_card = card;
new_card = &card->next_card;
@@ -405,12 +405,12 @@ static int __init c101_init(void)
{
if (hw == NULL) {
#ifdef MODULE
- printk(KERN_INFO "c101: no card initialized\n");
+ pr_info("no card initialized\n");
#endif
return -EINVAL; /* no parameters specified, abort */
}
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
do {
unsigned long irq, ram;
@@ -428,7 +428,7 @@ static int __init c101_init(void)
return first_card ? 0 : -EINVAL;
}while(*hw++ == ':');
- printk(KERN_ERR "c101: invalid hardware parameters\n");
+ pr_err("invalid hardware parameters\n");
return first_card ? 0 : -EINVAL;
}
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6fb6f8e667d0..6aed238e573e 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -74,6 +74,8 @@
* The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -361,14 +363,13 @@ static int __init cosa_init(void)
if (cosa_major > 0) {
if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
- printk(KERN_WARNING "cosa: unable to get major %d\n",
- cosa_major);
+ pr_warn("unable to get major %d\n", cosa_major);
err = -EIO;
goto out;
}
} else {
if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
- printk(KERN_WARNING "cosa: unable to register chardev\n");
+ pr_warn("unable to register chardev\n");
err = -EIO;
goto out;
}
@@ -378,7 +379,7 @@ static int __init cosa_init(void)
for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
cosa_probe(io[i], irq[i], dma[i]);
if (!nr_cards) {
- printk(KERN_WARNING "cosa: no devices found.\n");
+ pr_warn("no devices found\n");
unregister_chrdev(cosa_major, "cosa");
err = -ENODEV;
goto out;
@@ -447,26 +448,25 @@ static int cosa_probe(int base, int irq, int dma)
/* Checking validity of parameters: */
/* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */
if ((irq >= 0 && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) {
- printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq);
+ pr_info("invalid IRQ %d\n", irq);
return -1;
}
/* I/O address should be between 0x100 and 0x3ff and should be
* multiple of 8. */
if (base < 0x100 || base > 0x3ff || base & 0x7) {
- printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n",
- base);
+ pr_info("invalid I/O address 0x%x\n", base);
return -1;
}
/* DMA should be 0,1 or 3-7 */
if (dma < 0 || dma == 4 || dma > 7) {
- printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma);
+ pr_info("invalid DMA %d\n", dma);
return -1;
}
/* and finally, on 16-bit COSA DMA should be 4-7 and
* I/O base should not be multiple of 0x10 */
if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) {
- printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch"
- " (base=0x%x, dma=%d)\n", base, dma);
+ pr_info("8/16 bit base and DMA mismatch (base=0x%x, dma=%d)\n",
+ base, dma);
return -1;
}
@@ -479,7 +479,7 @@ static int cosa_probe(int base, int irq, int dma)
return -1;
if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) {
- printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base);
+ printk(KERN_DEBUG "probe at 0x%x failed.\n", base);
err = -1;
goto err_out;
}
@@ -492,8 +492,7 @@ static int cosa_probe(int base, int irq, int dma)
else {
/* Print a warning only if we are not autoprobing */
#ifndef COSA_ISA_AUTOPROBE
- printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n",
- base);
+ pr_info("valid signature not found at 0x%x\n", base);
#endif
err = -1;
goto err_out;
@@ -501,14 +500,14 @@ static int cosa_probe(int base, int irq, int dma)
/* Update the name of the region now we know the type of card */
release_region(base, is_8bit(cosa)?2:4);
if (!request_region(base, is_8bit(cosa)?2:4, cosa->type)) {
- printk(KERN_DEBUG "cosa: changing name at 0x%x failed.\n", base);
+ printk(KERN_DEBUG "changing name at 0x%x failed.\n", base);
return -1;
}
/* Now do IRQ autoprobe */
if (irq < 0) {
unsigned long irqs;
-/* printk(KERN_INFO "IRQ autoprobe\n"); */
+/* pr_info("IRQ autoprobe\n"); */
irqs = probe_irq_on();
/*
* Enable interrupt on tx buffer empty (it sure is)
@@ -526,13 +525,13 @@ static int cosa_probe(int base, int irq, int dma)
cosa_getdata8(cosa);
if (irq < 0) {
- printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n",
+ pr_info("multiple interrupts obtained (%d, board at 0x%x)\n",
irq, cosa->datareg);
err = -1;
goto err_out;
}
if (irq == 0) {
- printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n",
+ pr_info("no interrupt obtained (board at 0x%x)\n",
cosa->datareg);
/* return -1; */
}
@@ -579,8 +578,7 @@ static int cosa_probe(int base, int irq, int dma)
/* Register the network interface */
if (!(chan->netdev = alloc_hdlcdev(chan))) {
- printk(KERN_WARNING "%s: alloc_hdlcdev failed.\n",
- chan->name);
+ pr_warn("%s: alloc_hdlcdev failed\n", chan->name);
goto err_hdlcdev;
}
dev_to_hdlc(chan->netdev)->attach = cosa_net_attach;
@@ -591,14 +589,14 @@ static int cosa_probe(int base, int irq, int dma)
chan->netdev->irq = chan->cosa->irq;
chan->netdev->dma = chan->cosa->dma;
if (register_hdlc_device(chan->netdev)) {
- printk(KERN_WARNING "%s: register_hdlc_device()"
- " failed.\n", chan->netdev->name);
+ netdev_warn(chan->netdev,
+ "register_hdlc_device() failed\n");
free_netdev(chan->netdev);
goto err_hdlcdev;
}
}
- printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
+ pr_info("cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
cosa->num, cosa->id_string, cosa->type,
cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
@@ -618,8 +616,7 @@ err_out1:
free_irq(cosa->irq, cosa);
err_out:
release_region(cosa->datareg,is_8bit(cosa)?2:4);
- printk(KERN_NOTICE "cosa%d: allocating resources failed\n",
- cosa->num);
+ pr_notice("cosa%d: allocating resources failed\n", cosa->num);
return err;
}
@@ -641,14 +638,14 @@ static int cosa_net_open(struct net_device *dev)
unsigned long flags;
if (!(chan->cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- chan->cosa->name, chan->cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ chan->cosa->name, chan->cosa->firmware_status);
return -EPERM;
}
spin_lock_irqsave(&chan->cosa->lock, flags);
if (chan->usage != 0) {
- printk(KERN_WARNING "%s: cosa_net_open called with usage count"
- " %d\n", chan->name, chan->usage);
+ pr_warn("%s: cosa_net_open called with usage count %d\n",
+ chan->name, chan->usage);
spin_unlock_irqrestore(&chan->cosa->lock, flags);
return -EBUSY;
}
@@ -736,8 +733,7 @@ static char *cosa_net_setup_rx(struct channel_data *chan, int size)
kfree_skb(chan->rx_skb);
chan->rx_skb = dev_alloc_skb(size);
if (chan->rx_skb == NULL) {
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",
- chan->name);
+ pr_notice("%s: Memory squeeze, dropping packet\n", chan->name);
chan->netdev->stats.rx_dropped++;
return NULL;
}
@@ -748,8 +744,7 @@ static char *cosa_net_setup_rx(struct channel_data *chan, int size)
static int cosa_net_rx_done(struct channel_data *chan)
{
if (!chan->rx_skb) {
- printk(KERN_WARNING "%s: rx_done with empty skb!\n",
- chan->name);
+ pr_warn("%s: rx_done with empty skb!\n", chan->name);
chan->netdev->stats.rx_errors++;
chan->netdev->stats.rx_frame_errors++;
return 0;
@@ -768,8 +763,7 @@ static int cosa_net_rx_done(struct channel_data *chan)
static int cosa_net_tx_done(struct channel_data *chan, int size)
{
if (!chan->tx_skb) {
- printk(KERN_WARNING "%s: tx_done with empty skb!\n",
- chan->name);
+ pr_warn("%s: tx_done with empty skb!\n", chan->name);
chan->netdev->stats.tx_errors++;
chan->netdev->stats.tx_aborted_errors++;
return 1;
@@ -794,15 +788,15 @@ static ssize_t cosa_read(struct file *file,
char *kbuf;
if (!(cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
if (mutex_lock_interruptible(&chan->rlock))
return -ERESTARTSYS;
if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
- printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+ pr_info("%s: cosa_read() - OOM\n", cosa->name);
mutex_unlock(&chan->rlock);
return -ENOMEM;
}
@@ -869,8 +863,8 @@ static ssize_t cosa_write(struct file *file,
char *kbuf;
if (!(cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
if (down_interruptible(&chan->wsem))
@@ -881,8 +875,8 @@ static ssize_t cosa_write(struct file *file,
/* Allocate the buffer */
if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) {
- printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n",
- cosa->name);
+ pr_notice("%s: cosa_write() OOM - dropping packet\n",
+ cosa->name);
up(&chan->wsem);
return -ENOMEM;
}
@@ -932,7 +926,7 @@ static int chrdev_tx_done(struct channel_data *chan, int size)
static unsigned int cosa_poll(struct file *file, poll_table *poll)
{
- printk(KERN_INFO "cosa_poll is here\n");
+ pr_info("cosa_poll is here\n");
return 0;
}
@@ -1017,15 +1011,14 @@ static inline int cosa_reset(struct cosa_data *cosa)
{
char idstring[COSA_MAX_ID_STRING];
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START);
if (cosa_reset_and_read_id(cosa, idstring) < 0) {
- printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num);
+ pr_notice("cosa%d: reset failed\n", cosa->num);
return -EIO;
}
- printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num,
- idstring);
+ pr_info("cosa%d: resetting device: %s\n", cosa->num, idstring);
cosa->firmware_status |= COSA_FW_RESET;
return 0;
}
@@ -1037,11 +1030,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->name, cosa->usage);
if (!(cosa->firmware_status & COSA_FW_RESET)) {
- printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
@@ -1059,11 +1052,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
i = download(cosa, d.code, d.len, d.addr);
if (i < 0) {
- printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: microcode download failed: %d\n",
+ cosa->num, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
+ pr_info("cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
cosa->num, d.len, d.addr);
cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD;
return 0;
@@ -1076,12 +1069,11 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: readmem requested with "
- "cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: readmem requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
if (!(cosa->firmware_status & COSA_FW_RESET)) {
- printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
@@ -1093,11 +1085,10 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
i = readmem(cosa, d.code, d.len, d.addr);
if (i < 0) {
- printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: reading memory failed: %d\n", cosa->num, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
+ pr_info("cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
cosa->num, d.len, d.addr);
cosa->firmware_status |= COSA_FW_RESET;
return 0;
@@ -1109,23 +1100,22 @@ static inline int cosa_start(struct cosa_data *cosa, int address)
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
if ((cosa->firmware_status & (COSA_FW_RESET|COSA_FW_DOWNLOAD))
!= (COSA_FW_RESET|COSA_FW_DOWNLOAD)) {
- printk(KERN_NOTICE "%s: download the microcode and/or reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: download the microcode and/or reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
cosa->firmware_status &= ~COSA_FW_RESET;
if ((i=startmicrocode(cosa, address)) < 0) {
- printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n",
- cosa->num, address, i);
+ pr_notice("cosa%d: start microcode at 0x%04x failed: %d\n",
+ cosa->num, address, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n",
- cosa->num, address);
+ pr_info("cosa%d: starting microcode at 0x%04x\n", cosa->num, address);
cosa->startaddr = address;
cosa->firmware_status |= COSA_FW_START;
return 0;
@@ -1255,11 +1245,11 @@ static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
#ifdef DEBUG_DATA
int i;
- printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num,
- chan->num, len);
+ pr_info("cosa%dc%d: starting tx(0x%x)",
+ chan->cosa->num, chan->num, len);
for (i=0; i<len; i++)
- printk(" %02x", buf[i]&0xff);
- printk("\n");
+ pr_cont(" %02x", buf[i]&0xff);
+ pr_cont("\n");
#endif
spin_lock_irqsave(&cosa->lock, flags);
chan->txbuf = buf;
@@ -1353,7 +1343,7 @@ static void cosa_kick(struct cosa_data *cosa)
if (test_bit(TXBIT, &cosa->rxtx))
s = "TX DMA";
- printk(KERN_INFO "%s: %s timeout - restarting.\n", cosa->name, s);
+ pr_info("%s: %s timeout - restarting\n", cosa->name, s);
spin_lock_irqsave(&cosa->lock, flags);
cosa->rxtx = 0;
@@ -1387,7 +1377,7 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len)
return 0;
if ((b^ (b+len)) & 0x10000) {
if (count++ < 5)
- printk(KERN_INFO "%s: packet spanning a 64k boundary\n",
+ pr_info("%s: packet spanning a 64k boundary\n",
chan->name);
return 0;
}
@@ -1498,8 +1488,7 @@ static int readmem(struct cosa_data *cosa, char __user *microcode, int length, i
char c;
int i;
if ((i=get_wait_data(cosa)) == -1) {
- printk (KERN_INFO "cosa: 0x%04x bytes remaining\n",
- length);
+ pr_info("0x%04x bytes remaining\n", length);
return -11;
}
c=i;
@@ -1582,14 +1571,15 @@ static int get_wait_data(struct cosa_data *cosa)
short r;
r = cosa_getdata8(cosa);
#if 0
- printk(KERN_INFO "cosa: get_wait_data returning after %d retries\n", 999-retries);
+ pr_info("get_wait_data returning after %d retries\n",
+ 999-retries);
#endif
return r;
}
/* sleep if not ready to read */
schedule_timeout_interruptible(1);
}
- printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
+ pr_info("timeout in get_wait_data (status 0x%x)\n",
cosa_getstatus(cosa));
return -1;
}
@@ -1607,7 +1597,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
if (cosa_getstatus(cosa) & SR_TX_RDY) {
cosa_putdata8(cosa, data);
#if 0
- printk(KERN_INFO "Putdata: %d retries\n", 999-retries);
+ pr_info("Putdata: %d retries\n", 999-retries);
#endif
return 0;
}
@@ -1616,7 +1606,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
schedule_timeout_interruptible(1);
#endif
}
- printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
+ pr_info("cosa%d: timeout in put_wait_data (status 0x%x)\n",
cosa->num, cosa_getstatus(cosa));
return -1;
}
@@ -1636,13 +1626,13 @@ static int puthexnumber(struct cosa_data *cosa, int number)
sprintf(temp, "%04X", number);
for (i=0; i<4; i++) {
if (put_wait_data(cosa, temp[i]) == -1) {
- printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: puthexnumber failed to write byte %d\n",
+ cosa->num, i);
return -1-2*i;
}
if (get_wait_data(cosa) != temp[i]) {
- printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: puthexhumber failed to read echo of byte %d\n",
+ cosa->num, i);
return -2-2*i;
}
}
@@ -1687,8 +1677,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
{
unsigned long flags, flags1;
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n",
- cosa->num, status);
+ pr_info("cosa%d: SR_DOWN_REQUEST status=0x%04x\n", cosa->num, status);
#endif
spin_lock_irqsave(&cosa->lock, flags);
set_bit(TXBIT, &cosa->rxtx);
@@ -1696,8 +1685,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
/* flow control, see the comment above */
int i=0;
if (!cosa->txbitmap) {
- printk(KERN_WARNING "%s: No channel wants data "
- "in TX IRQ. Expect DMA timeout.",
+ pr_warn("%s: No channel wants data in TX IRQ. Expect DMA timeout.\n",
cosa->name);
put_driver_status_nolock(cosa);
clear_bit(TXBIT, &cosa->rxtx);
@@ -1780,14 +1768,14 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
if (cosa->busmaster) {
unsigned long addr = virt_to_bus(cosa->txbuf);
int count=0;
- printk(KERN_INFO "busmaster IRQ\n");
+ pr_info("busmaster IRQ\n");
while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
count++;
udelay(10);
if (count > 1000) break;
}
- printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
- printk(KERN_INFO "ready after %d loops\n", count);
+ pr_info("status %x\n", cosa_getstatus(cosa));
+ pr_info("ready after %d loops\n", count);
cosa_putdata16(cosa, (addr >> 16)&0xffff);
count = 0;
@@ -1796,7 +1784,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
if (count > 1000) break;
udelay(10);
}
- printk(KERN_INFO "ready after %d loops\n", count);
+ pr_info("ready after %d loops\n", count);
cosa_putdata16(cosa, addr &0xffff);
flags1 = claim_dma_lock();
set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
@@ -1824,7 +1812,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
{
unsigned long flags;
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num);
+ pr_info("cosa%d: SR_UP_REQUEST\n", cosa->num);
#endif
spin_lock_irqsave(&cosa->lock, flags);
@@ -1847,7 +1835,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
debug_data_in(cosa, cosa->rxsize & 0xff);
#endif
#if 0
- printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ pr_info("cosa%d: receive rxsize = (0x%04x)\n",
cosa->num, cosa->rxsize);
#endif
}
@@ -1857,12 +1845,12 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
debug_data_in(cosa, cosa->rxsize);
#endif
#if 0
- printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ pr_info("cosa%d: receive rxsize = (0x%04x)\n",
cosa->num, cosa->rxsize);
#endif
}
if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) {
- printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n",
+ pr_warn("%s: rx for unknown channel (0x%04x)\n",
cosa->name, cosa->rxsize);
spin_unlock_irqrestore(&cosa->lock, flags);
goto reject;
@@ -1877,7 +1865,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
if (!cosa->rxbuf) {
reject: /* Reject the packet */
- printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
+ pr_info("cosa%d: rejecting packet on channel %d\n",
cosa->num, cosa->rxchan->num);
cosa->rxbuf = cosa->bouncebuf;
}
@@ -1924,11 +1912,11 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status)
#ifdef DEBUG_DATA
{
int i;
- printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num,
- cosa->rxchan->num, cosa->rxsize);
+ pr_info("cosa%dc%d: done rx(0x%x)",
+ cosa->num, cosa->rxchan->num, cosa->rxsize);
for (i=0; i<cosa->rxsize; i++)
- printk (" %02x", cosa->rxbuf[i]&0xff);
- printk("\n");
+ pr_cont(" %02x", cosa->rxbuf[i]&0xff);
+ pr_cont("\n");
}
#endif
/* Packet for unknown channel? */
@@ -1940,8 +1928,7 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status)
if (cosa->rxchan->rx_done(cosa->rxchan))
clear_bit(cosa->rxchan->num, &cosa->rxbitmap);
} else {
- printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n",
- cosa->num);
+ pr_notice("cosa%d: unexpected EOT interrupt\n", cosa->num);
}
/*
* Clear the RXBIT, TXBIT and IRQBIT (the latest should be
@@ -1963,8 +1950,7 @@ static irqreturn_t cosa_interrupt(int irq, void *cosa_)
again:
status = cosa_getstatus(cosa);
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num,
- status & 0xff);
+ pr_info("cosa%d: got IRQ, status 0x%02x\n", cosa->num, status & 0xff);
#endif
#ifdef DEBUG_IO
debug_status_in(cosa, status);
@@ -1985,15 +1971,15 @@ again:
udelay(100);
goto again;
}
- printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
+ pr_info("cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
cosa->num, status & 0xff, count);
}
#ifdef DEBUG_IRQS
if (count)
- printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n",
+ pr_info("%s: %d-times got unknown status in IRQ\n",
cosa->name, count);
else
- printk(KERN_INFO "%s: returning from IRQ\n", cosa->name);
+ pr_info("%s: returning from IRQ\n", cosa->name);
#endif
return IRQ_HANDLED;
}
@@ -2024,41 +2010,41 @@ static void debug_status_in(struct cosa_data *cosa, int status)
s = "NO_REQ";
break;
}
- printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n",
+ pr_info("%s: IO: status -> 0x%02x (%s%s%s%s)\n",
cosa->name,
status,
- status & SR_USR_RQ ? "USR_RQ|":"",
- status & SR_TX_RDY ? "TX_RDY|":"",
- status & SR_RX_RDY ? "RX_RDY|":"",
+ status & SR_USR_RQ ? "USR_RQ|" : "",
+ status & SR_TX_RDY ? "TX_RDY|" : "",
+ status & SR_RX_RDY ? "RX_RDY|" : "",
s);
}
static void debug_status_out(struct cosa_data *cosa, int status)
{
- printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
+ pr_info("%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
cosa->name,
status,
- status & SR_RX_DMA_ENA ? "RXDMA|":"!rxdma|",
- status & SR_TX_DMA_ENA ? "TXDMA|":"!txdma|",
- status & SR_RST ? "RESET|":"",
- status & SR_USR_INT_ENA ? "USRINT|":"!usrint|",
- status & SR_TX_INT_ENA ? "TXINT|":"!txint|",
- status & SR_RX_INT_ENA ? "RXINT":"!rxint");
+ status & SR_RX_DMA_ENA ? "RXDMA|" : "!rxdma|",
+ status & SR_TX_DMA_ENA ? "TXDMA|" : "!txdma|",
+ status & SR_RST ? "RESET|" : "",
+ status & SR_USR_INT_ENA ? "USRINT|" : "!usrint|",
+ status & SR_TX_INT_ENA ? "TXINT|" : "!txint|",
+ status & SR_RX_INT_ENA ? "RXINT" : "!rxint");
}
static void debug_data_in(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data);
+ pr_info("%s: IO: data -> 0x%04x\n", cosa->name, data);
}
static void debug_data_out(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data);
+ pr_info("%s: IO: data <- 0x%04x\n", cosa->name, data);
}
static void debug_data_cmd(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n",
+ pr_info("%s: IO: data <- 0x%04x (%s|%s)\n",
cosa->name, data,
data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy",
data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy");
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 164c3624ba89..2a3ecae67a90 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -48,6 +48,8 @@
* Aug 8, 1998 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h> /* __init */
#include <linux/module.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
@@ -81,10 +83,9 @@ static u16 checksum(u8 *buf, u32 len);
/* Global Data */
/* private data */
-static const char modname[] = "cycx_drv";
static const char fullname[] = "Cyclom 2X Support Module";
-static const char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
- "<acme@conectiva.com.br>";
+static const char copyright[] =
+ "(c) 1998-2003 Arnaldo Carvalho de Melo <acme@conectiva.com.br>";
/* Hardware configuration options.
* These are arrays of configuration options used by verification routines.
@@ -110,8 +111,8 @@ static const long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
static int __init cycx_drv_init(void)
{
- printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
- copyright);
+ pr_info("%s v%u.%u %s\n",
+ fullname, MOD_VERSION, MOD_RELEASE, copyright);
return 0;
}
@@ -139,18 +140,16 @@ int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase)
/* Verify IRQ configuration options */
if (!get_option_index(cycx_2x_irq_options, hw->irq)) {
- printk(KERN_ERR "%s: IRQ %d is invalid!\n", modname, hw->irq);
+ pr_err("IRQ %d is invalid!\n", hw->irq);
return -EINVAL;
}
/* Setup adapter dual-port memory window and test memory */
if (!dpmbase) {
- printk(KERN_ERR "%s: you must specify the dpm address!\n",
- modname);
+ pr_err("you must specify the dpm address!\n");
return -EINVAL;
} else if (!get_option_index(cyc2x_dpmbase_options, dpmbase)) {
- printk(KERN_ERR "%s: memory address 0x%lX is invalid!\n",
- modname, dpmbase);
+ pr_err("memory address 0x%lX is invalid!\n", dpmbase);
return -EINVAL;
}
@@ -158,13 +157,12 @@ int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase)
hw->dpmsize = CYCX_WINDOWSIZE;
if (!detect_cyc2x(hw->dpmbase)) {
- printk(KERN_ERR "%s: adapter Cyclom 2X not found at "
- "address 0x%lX!\n", modname, dpmbase);
+ pr_err("adapter Cyclom 2X not found at address 0x%lX!\n",
+ dpmbase);
return -EINVAL;
}
- printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n",
- modname, dpmbase);
+ pr_info("found Cyclom 2X card at address 0x%lX\n", dpmbase);
/* Load firmware. If loader fails then shut down adapter */
err = load_cyc2x(hw, cfm, len);
@@ -339,7 +337,7 @@ static int cycx_data_boot(void __iomem *addr, u8 *code, u32 len)
for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
if (buffer_load(addr, code + i,
min_t(u32, CFM_LOAD_BUFSZ, (len - i))) < 0) {
- printk(KERN_ERR "%s: Error !!\n", modname);
+ pr_err("Error !!\n");
return -1;
}
@@ -370,7 +368,7 @@ static int cycx_code_boot(void __iomem *addr, u8 *code, u32 len)
for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
if (buffer_load(addr, code + i,
min_t(u32, CFM_LOAD_BUFSZ, (len - i)))) {
- printk(KERN_ERR "%s: Error !!\n", modname);
+ pr_err("Error !!\n");
return -1;
}
@@ -391,23 +389,20 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
u16 cksum;
/* Announce */
- printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname,
- cfm->signature);
+ pr_info("firmware signature=\"%s\"\n", cfm->signature);
/* Verify firmware signature */
if (strcmp(cfm->signature, CFM_SIGNATURE)) {
- printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n",
- modname);
+ pr_err("load_cyc2x: not Cyclom-2X firmware!\n");
return -EINVAL;
}
- printk(KERN_INFO "%s: firmware version=%u\n", modname, cfm->version);
+ pr_info("firmware version=%u\n", cfm->version);
/* Verify firmware module format version */
if (cfm->version != CFM_VERSION) {
- printk(KERN_ERR "%s:%s: firmware format %u rejected! "
- "Expecting %u.\n",
- modname, __func__, cfm->version, CFM_VERSION);
+ pr_err("%s: firmware format %u rejected! Expecting %u.\n",
+ __func__, cfm->version, CFM_VERSION);
return -EINVAL;
}
@@ -419,23 +414,22 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
if (((len - sizeof(struct cycx_firmware) - 1) != cfm->info.codesize) ||
*/
if (cksum != cfm->checksum) {
- printk(KERN_ERR "%s:%s: firmware corrupted!\n",
- modname, __func__);
- printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
- len - (int)sizeof(struct cycx_firmware) - 1,
- cfm->info.codesize);
- printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
- cksum, cfm->checksum);
+ pr_err("%s: firmware corrupted!\n", __func__);
+ pr_err(" cdsize = 0x%x (expected 0x%lx)\n",
+ len - (int)sizeof(struct cycx_firmware) - 1,
+ cfm->info.codesize);
+ pr_err(" chksum = 0x%x (expected 0x%x)\n",
+ cksum, cfm->checksum);
return -EINVAL;
}
/* If everything is ok, set reset, data and code pointers */
img_hdr = (struct cycx_fw_header *)&cfm->image;
#ifdef FIRMWARE_DEBUG
- printk(KERN_INFO "%s:%s: image sizes\n", __func__, modname);
- printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
- printk(KERN_INFO " data=%lu\n", img_hdr->data_size);
- printk(KERN_INFO " code=%lu\n", img_hdr->code_size);
+ pr_info("%s: image sizes\n", __func__);
+ pr_info(" reset=%lu\n", img_hdr->reset_size);
+ pr_info(" data=%lu\n", img_hdr->data_size);
+ pr_info(" code=%lu\n", img_hdr->code_size);
#endif
reset_image = ((u8 *)img_hdr) + sizeof(struct cycx_fw_header);
data_image = reset_image + img_hdr->reset_size;
@@ -443,15 +437,14 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
/*---- Start load ----*/
/* Announce */
- printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname,
- cfm->descr[0] ? cfm->descr : "unknown firmware",
- cfm->info.codeid);
+ pr_info("loading firmware %s (ID=%u)...\n",
+ cfm->descr[0] ? cfm->descr : "unknown firmware",
+ cfm->info.codeid);
for (i = 0 ; i < 5 ; i++) {
/* Reset Cyclom hardware */
if (!reset_cyc2x(hw->dpmbase)) {
- printk(KERN_ERR "%s: dpm problem or board not found\n",
- modname);
+ pr_err("dpm problem or board not found\n");
return -EINVAL;
}
@@ -468,19 +461,19 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
msleep_interruptible(1 * 1000);
}
- printk(KERN_ERR "%s: reset not started.\n", modname);
+ pr_err("reset not started\n");
return -EINVAL;
reset_loaded:
/* Load data.bin */
if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) {
- printk(KERN_ERR "%s: cannot load data file.\n", modname);
+ pr_err("cannot load data file\n");
return -EINVAL;
}
/* Load code.bin */
if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) {
- printk(KERN_ERR "%s: cannot load code file.\n", modname);
+ pr_err("cannot load code file\n");
return -EINVAL;
}
@@ -493,7 +486,7 @@ reset_loaded:
/* Arthur Ganzert's tip: wait a while after the firmware loading...
seg abr 26 17:17:12 EST 1999 - acme */
msleep_interruptible(7 * 1000);
- printk(KERN_INFO "%s: firmware loaded!\n", modname);
+ pr_info("firmware loaded!\n");
/* enable interrupts */
cycx_inten(hw);
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 859dba9b972e..81fbbad406be 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -40,6 +40,8 @@
* 1998/08/08 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
#include <linux/string.h> /* inline memset(), etc. */
@@ -50,6 +52,7 @@
#include <linux/wanrouter.h> /* WAN router definitions */
#include <linux/cyclomx.h> /* cyclomx common user API definitions */
#include <linux/init.h> /* __init (when not using as a module) */
+#include <linux/interrupt.h>
unsigned int cycx_debug;
@@ -106,7 +109,7 @@ static int __init cycx_init(void)
{
int cnt, err = -ENOMEM;
- printk(KERN_INFO "%s v%u.%u %s\n",
+ pr_info("%s v%u.%u %s\n",
cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE,
cycx_copyright);
@@ -132,9 +135,8 @@ static int __init cycx_init(void)
err = register_wan_device(wandev);
if (err) {
- printk(KERN_ERR "%s: %s registration failed with "
- "error %d!\n",
- cycx_drvname, card->devname, err);
+ pr_err("%s registration failed with error %d!\n",
+ card->devname, err);
break;
}
}
@@ -197,14 +199,13 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
rc = -EINVAL;
if (!conf->data_size || !conf->data) {
- printk(KERN_ERR "%s: firmware not found in configuration "
- "data!\n", wandev->name);
+ pr_err("%s: firmware not found in configuration data!\n",
+ wandev->name);
goto out;
}
if (conf->irq <= 0) {
- printk(KERN_ERR "%s: can't configure without IRQ!\n",
- wandev->name);
+ pr_err("%s: can't configure without IRQ!\n", wandev->name);
goto out;
}
@@ -212,8 +213,7 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
irq = conf->irq == 2 ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
if (request_irq(irq, cycx_isr, 0, wandev->name, card)) {
- printk(KERN_ERR "%s: can't reserve IRQ %d!\n",
- wandev->name, irq);
+ pr_err("%s: can't reserve IRQ %d!\n", wandev->name, irq);
goto out;
}
@@ -245,8 +245,7 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
break;
#endif
default:
- printk(KERN_ERR "%s: this firmware is not supported!\n",
- wandev->name);
+ pr_err("%s: this firmware is not supported!\n", wandev->name);
rc = -EINVAL;
}
@@ -287,8 +286,7 @@ static int cycx_wan_shutdown(struct wan_device *wandev)
card = wandev->private;
wandev->state = WAN_UNCONFIGURED;
cycx_down(&card->hw);
- printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
- wandev->irq);
+ pr_info("%s: irq %d being freed!\n", wandev->name, wandev->irq);
free_irq(wandev->irq, card);
out: return ret;
}
@@ -307,8 +305,8 @@ static irqreturn_t cycx_isr(int irq, void *dev_id)
goto out;
if (card->in_isr) {
- printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
- card->devname, card->wandev.irq);
+ pr_warn("%s: interrupt re-entrancy on IRQ %d!\n",
+ card->devname, card->wandev.irq);
goto out;
}
@@ -336,7 +334,7 @@ void cycx_set_state(struct cycx_device *card, int state)
string_state = "disconnected!";
break;
}
- printk(KERN_INFO "%s: link %s\n", card->devname, string_state);
+ pr_info("%s: link %s\n", card->devname, string_state);
card->wandev.state = state;
}
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index cf9e15fd8d91..06f3f6309e4b 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -76,6 +76,8 @@
* 1998/08/08 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define CYCLOMX_X25_DEBUG 1
#include <linux/ctype.h> /* isdigit() */
@@ -230,8 +232,8 @@ int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
/* Verify configuration ID */
if (conf->config_id != WANCONFIG_X25) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
+ pr_info("%s: invalid configuration ID %u!\n",
+ card->devname, conf->config_id);
return -EINVAL;
}
@@ -374,8 +376,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
int err = 0;
if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname);
+ pr_info("%s: invalid interface name!\n", card->devname);
return -EINVAL;
}
@@ -398,8 +399,8 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
if (len) {
if (len > WAN_ADDRESS_SZ) {
- printk(KERN_ERR "%s: %s local addr too long!\n",
- wandev->name, chan->name);
+ pr_err("%s: %s local addr too long!\n",
+ wandev->name, chan->name);
err = -EINVAL;
goto error;
} else {
@@ -429,15 +430,14 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
chan->lcn = lcn;
else {
- printk(KERN_ERR
- "%s: PVC %u is out of range on interface %s!\n",
- wandev->name, lcn, chan->name);
+ pr_err("%s: PVC %u is out of range on interface %s!\n",
+ wandev->name, lcn, chan->name);
err = -EINVAL;
goto error;
}
} else {
- printk(KERN_ERR "%s: invalid media address on interface %s!\n",
- wandev->name, chan->name);
+ pr_err("%s: invalid media address on interface %s!\n",
+ wandev->name, chan->name);
err = -EINVAL;
goto error;
}
@@ -607,9 +607,8 @@ static netdev_tx_t cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
++chan->ifstats.tx_dropped;
else if (chan->svc && chan->protocol &&
chan->protocol != ntohs(skb->protocol)) {
- printk(KERN_INFO
- "%s: unsupported Ethertype 0x%04X on interface %s!\n",
- card->devname, ntohs(skb->protocol), dev->name);
+ pr_info("%s: unsupported Ethertype 0x%04X on interface %s!\n",
+ card->devname, ntohs(skb->protocol), dev->name);
++chan->ifstats.tx_errors;
} else if (chan->protocol == ETH_P_IP) {
switch (chan->state) {
@@ -643,9 +642,8 @@ static netdev_tx_t cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
cycx_x25_chan_disconnect(dev);
goto free_packet;
default:
- printk(KERN_INFO
- "%s: unknown %d x25-iface request on %s!\n",
- card->devname, skb->data[0], dev->name);
+ pr_info("%s: unknown %d x25-iface request on %s!\n",
+ card->devname, skb->data[0], dev->name);
++chan->ifstats.tx_errors;
goto free_packet;
}
@@ -746,8 +744,7 @@ static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
card->buff_int_mode_unbusy = 1;
netif_wake_queue(dev);
} else
- printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
- card->devname, lcn);
+ pr_err("%s:ackvc for inexistent lcn %d\n", card->devname, lcn);
}
/* Receive interrupt handler.
@@ -780,8 +777,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
- card->devname, lcn);
+ pr_info("%s: receiving on orphaned LCN %d!\n",
+ card->devname, lcn);
return;
}
@@ -802,8 +799,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
bufsize +
dev->hard_header_len)) == NULL) {
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
+ pr_info("%s: no socket buffers available!\n",
+ card->devname);
chan->drop_sequence = 1;
++chan->ifstats.rx_dropped;
return;
@@ -826,8 +823,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
if (bitm)
chan->drop_sequence = 1;
- printk(KERN_INFO "%s: unexpectedly long packet sequence "
- "on interface %s!\n", card->devname, dev->name);
+ pr_info("%s: unexpectedly long packet sequence on interface %s!\n",
+ card->devname, dev->name);
++chan->ifstats.rx_length_errors;
return;
}
@@ -880,8 +877,8 @@ static void cycx_x25_irq_connect(struct cycx_device *card,
dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s: connect not expected: remote %s!\n",
- card->devname, rem);
+ pr_info("%s: connect not expected: remote %s!\n",
+ card->devname, rem);
return;
}
@@ -909,8 +906,8 @@ static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
if (!dev) {
/* Invalid channel, discard packet */
clear_bit(--key, (void*)&card->u.x.connection_keys);
- printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
- "key=%d!\n", card->devname, lcn, key);
+ pr_info("%s: connect confirm not expected: lcn %d, key=%d!\n",
+ card->devname, lcn, key);
return;
}
@@ -934,8 +931,8 @@ static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
- card->devname, lcn);
+ pr_info("%s:disconnect confirm not expected!:lcn %d\n",
+ card->devname, lcn);
return;
}
@@ -980,13 +977,13 @@ static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
- printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
- printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
- printk(KERN_INFO "Log message code=0x%X\n", msg_code);
- printk(KERN_INFO "Link=%d\n", link);
- printk(KERN_INFO "log code=0x%X\n", code);
- printk(KERN_INFO "log routine=0x%X\n", routine);
- printk(KERN_INFO "Message size=%d\n", size);
+ pr_info("cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
+ pr_info("cmd->buf=0x%X\n", cmd->buf);
+ pr_info("Log message code=0x%X\n", msg_code);
+ pr_info("Link=%d\n", link);
+ pr_info("log code=0x%X\n", code);
+ pr_info("log routine=0x%X\n", routine);
+ pr_info("Message size=%d\n", size);
hex_dump("Message", bf, toread);
#endif
}
@@ -1009,24 +1006,14 @@ static void cycx_x25_irq_stat(struct cycx_device *card,
static void cycx_x25_irq_spurious(struct cycx_device *card,
struct cycx_x25_cmd *cmd)
{
- printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
- card->devname, cmd->command);
+ pr_info("%s: spurious interrupt (0x%X)!\n",
+ card->devname, cmd->command);
}
#ifdef CYCLOMX_X25_DEBUG
static void hex_dump(char *msg, unsigned char *p, int len)
{
- unsigned char hex[1024],
- * phex = hex;
-
- if (len >= (sizeof(hex) / 2))
- len = (sizeof(hex) / 2) - 1;
-
- while (len--) {
- sprintf(phex, "%02x", *p++);
- phex += 2;
- }
-
- printk(KERN_INFO "%s: %s\n", msg, hex);
+ print_hex_dump(KERN_INFO, msg, DUMP_PREFIX_OFFSET, 16, 1,
+ p, len, true);
}
#endif
@@ -1203,8 +1190,8 @@ static int x25_place_call(struct cycx_device *card,
u8 key;
if (card->u.x.connection_keys == ~0U) {
- printk(KERN_INFO "%s: too many simultaneous connection "
- "requests!\n", card->devname);
+ pr_info("%s: too many simultaneous connection requests!\n",
+ card->devname);
return -EAGAIN;
}
@@ -1381,8 +1368,8 @@ static void cycx_x25_chan_timer(unsigned long d)
if (chan->state == WAN_CONNECTED)
cycx_x25_chan_disconnect(dev);
else
- printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
- chan->card->devname, __func__, dev->name);
+ pr_err("%s: %s for svc (%s) not connected!\n",
+ chan->card->devname, __func__, dev->name);
}
/* Set logical channel state. */
@@ -1433,8 +1420,8 @@ static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
break;
}
- printk(KERN_INFO "%s: interface %s %s\n", card->devname,
- dev->name, string_state);
+ pr_info("%s: interface %s %s\n",
+ card->devname, dev->name, string_state);
chan->state = state;
}
@@ -1488,7 +1475,7 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "%s: out of memory\n", __func__);
+ pr_err("%s: out of memory\n", __func__);
return;
}
@@ -1557,56 +1544,56 @@ static void reset_timer(struct net_device *dev)
#ifdef CYCLOMX_X25_DEBUG
static void cycx_x25_dump_config(struct cycx_x25_config *conf)
{
- printk(KERN_INFO "X.25 configuration\n");
- printk(KERN_INFO "-----------------\n");
- printk(KERN_INFO "link number=%d\n", conf->link);
- printk(KERN_INFO "line speed=%d\n", conf->speed);
- printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
- printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
- printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
- printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
- printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
- printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
- printk(KERN_INFO "my address=%d\n", conf->locaddr);
- printk(KERN_INFO "remote address=%d\n", conf->remaddr);
- printk(KERN_INFO "t1=%d seconds\n", conf->t1);
- printk(KERN_INFO "t2=%d seconds\n", conf->t2);
- printk(KERN_INFO "t21=%d seconds\n", conf->t21);
- printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
- printk(KERN_INFO "t23=%d seconds\n", conf->t23);
- printk(KERN_INFO "flags=0x%x\n", conf->flags);
+ pr_info("X.25 configuration\n");
+ pr_info("-----------------\n");
+ pr_info("link number=%d\n", conf->link);
+ pr_info("line speed=%d\n", conf->speed);
+ pr_info("clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
+ pr_info("# level 2 retransm.=%d\n", conf->n2);
+ pr_info("level 2 window=%d\n", conf->n2win);
+ pr_info("level 3 window=%d\n", conf->n3win);
+ pr_info("# logical channels=%d\n", conf->nvc);
+ pr_info("level 3 pkt len=%d\n", conf->pktlen);
+ pr_info("my address=%d\n", conf->locaddr);
+ pr_info("remote address=%d\n", conf->remaddr);
+ pr_info("t1=%d seconds\n", conf->t1);
+ pr_info("t2=%d seconds\n", conf->t2);
+ pr_info("t21=%d seconds\n", conf->t21);
+ pr_info("# PVCs=%d\n", conf->npvc);
+ pr_info("t23=%d seconds\n", conf->t23);
+ pr_info("flags=0x%x\n", conf->flags);
}
static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
{
- printk(KERN_INFO "X.25 statistics\n");
- printk(KERN_INFO "--------------\n");
- printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
- printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
- printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
- printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
- printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
- printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
- printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
- printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
- printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
- printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
+ pr_info("X.25 statistics\n");
+ pr_info("--------------\n");
+ pr_info("rx_crc_errors=%d\n", stats->rx_crc_errors);
+ pr_info("rx_over_errors=%d\n", stats->rx_over_errors);
+ pr_info("n2_tx_frames=%d\n", stats->n2_tx_frames);
+ pr_info("n2_rx_frames=%d\n", stats->n2_rx_frames);
+ pr_info("tx_timeouts=%d\n", stats->tx_timeouts);
+ pr_info("rx_timeouts=%d\n", stats->rx_timeouts);
+ pr_info("n3_tx_packets=%d\n", stats->n3_tx_packets);
+ pr_info("n3_rx_packets=%d\n", stats->n3_rx_packets);
+ pr_info("tx_aborts=%d\n", stats->tx_aborts);
+ pr_info("rx_aborts=%d\n", stats->rx_aborts);
}
static void cycx_x25_dump_devs(struct wan_device *wandev)
{
struct net_device *dev = wandev->dev;
- printk(KERN_INFO "X.25 dev states\n");
- printk(KERN_INFO "name: addr: txoff: protocol:\n");
- printk(KERN_INFO "---------------------------------------\n");
+ pr_info("X.25 dev states\n");
+ pr_info("name: addr: txoff: protocol:\n");
+ pr_info("---------------------------------------\n");
while(dev) {
struct cycx_x25_channel *chan = netdev_priv(dev);
- printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
- chan->name, chan->addr, netif_queue_stopped(dev),
- chan->protocol == ETH_P_IP ? "IP" : "X25");
+ pr_info("%-5.5s %-15.15s %d ETH_P_%s\n",
+ chan->name, chan->addr, netif_queue_stopped(dev),
+ chan->protocol == ETH_P_IP ? "IP" : "X25");
dev = chan->slave;
}
}
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 21b104db5a90..48ab38a34c5a 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -28,6 +28,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -112,8 +114,7 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
dlp = netdev_priv(dev);
if (!pskb_may_pull(skb, sizeof(*hdr))) {
- printk(KERN_NOTICE "%s: invalid data no header\n",
- dev->name);
+ netdev_notice(dev, "invalid data no header\n");
dev->stats.rx_errors++;
kfree_skb(skb);
return;
@@ -126,7 +127,8 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
if (hdr->control != FRAD_I_UI)
{
- printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control);
+ netdev_notice(dev, "Invalid header flag 0x%02X\n",
+ hdr->control);
dev->stats.rx_errors++;
}
else
@@ -135,14 +137,18 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
case FRAD_P_PADDING:
if (hdr->NLPID != FRAD_P_SNAP)
{
- printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID);
+ netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+ hdr->NLPID);
dev->stats.rx_errors++;
break;
}
if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
{
- printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]);
+ netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n",
+ hdr->OUI[0],
+ hdr->OUI[1],
+ hdr->OUI[2]);
dev->stats.rx_errors++;
break;
}
@@ -163,12 +169,14 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
case FRAD_P_SNAP:
case FRAD_P_Q933:
case FRAD_P_CLNP:
- printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad);
+ netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+ hdr->pad);
dev->stats.rx_errors++;
break;
default:
- printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad);
+ netdev_notice(dev, "Invalid pad byte 0x%02X\n",
+ hdr->pad);
dev->stats.rx_errors++;
break;
}
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index acb9ea830628..058e1697c174 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -80,6 +80,8 @@
* - misc crapectomy.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -99,6 +101,7 @@
#include <asm/irq.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/if_arp.h>
@@ -552,7 +555,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
schedule_timeout_uninterruptible(10);
rmb();
} while (++i > 0);
- printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+ netdev_err(dev, "%s timeout\n", msg);
done:
return (i >= 0) ? i : -EAGAIN;
}
@@ -568,18 +571,18 @@ static int dscc4_do_action(struct net_device *dev, char *msg)
u32 state = readl(ioaddr);
if (state & ArAck) {
- printk(KERN_DEBUG "%s: %s ack\n", dev->name, msg);
+ netdev_dbg(dev, "%s ack\n", msg);
writel(ArAck, ioaddr);
goto done;
} else if (state & Arf) {
- printk(KERN_ERR "%s: %s failed\n", dev->name, msg);
+ netdev_err(dev, "%s failed\n", msg);
writel(Arf, ioaddr);
i = -1;
goto done;
}
rmb();
} while (++i > 0);
- printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+ netdev_err(dev, "%s timeout\n", msg);
done:
return i;
}
@@ -635,7 +638,7 @@ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
writel(MTFi|Rdt, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG);
if (dscc4_do_action(dev, "Rdt") < 0)
- printk(KERN_ERR "%s: Tx reset failed\n", dev->name);
+ netdev_err(dev, "Tx reset failed\n");
}
#endif
@@ -721,22 +724,20 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,
rc = pci_request_region(pdev, 0, "registers");
if (rc < 0) {
- printk(KERN_ERR "%s: can't reserve MMIO region (regs)\n",
- DRV_NAME);
+ pr_err("can't reserve MMIO region (regs)\n");
goto err_disable_0;
}
rc = pci_request_region(pdev, 1, "LBI interface");
if (rc < 0) {
- printk(KERN_ERR "%s: can't reserve MMIO region (lbi)\n",
- DRV_NAME);
+ pr_err("can't reserve MMIO region (lbi)\n");
goto err_free_mmio_region_1;
}
ioaddr = pci_ioremap_bar(pdev, 0);
if (!ioaddr) {
- printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n",
- DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0),
- (unsigned long long)pci_resource_start(pdev, 0));
+ pr_err("cannot remap MMIO region %llx @ %llx\n",
+ (unsigned long long)pci_resource_len(pdev, 0),
+ (unsigned long long)pci_resource_start(pdev, 0));
rc = -EIO;
goto err_free_mmio_regions_2;
}
@@ -756,7 +757,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,
rc = request_irq(pdev->irq, dscc4_irq, IRQF_SHARED, DRV_NAME, priv->root);
if (rc < 0) {
- printk(KERN_WARNING "%s: IRQ %d busy\n", DRV_NAME, pdev->irq);
+ pr_warn("IRQ %d busy\n", pdev->irq);
goto err_release_4;
}
@@ -903,7 +904,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
root = kcalloc(dev_per_card, sizeof(*root), GFP_KERNEL);
if (!root) {
- printk(KERN_ERR "%s: can't allocate data\n", DRV_NAME);
+ pr_err("can't allocate data\n");
goto err_out;
}
@@ -915,7 +916,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
ppriv = kzalloc(sizeof(*ppriv), GFP_KERNEL);
if (!ppriv) {
- printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME);
+ pr_err("can't allocate private data\n");
goto err_free_dev;
}
@@ -951,7 +952,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
ret = register_hdlc_device(d);
if (ret < 0) {
- printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
+ pr_err("unable to register\n");
dscc4_release_ring(dpriv);
goto err_unregister;
}
@@ -1004,7 +1005,7 @@ static int dscc4_loopback_check(struct dscc4_dev_priv *dpriv)
if (settings->loopback && (settings->clock_type != CLOCK_INT)) {
struct net_device *dev = dscc4_to_dev(dpriv);
- printk(KERN_INFO "%s: loopback requires clock\n", dev->name);
+ netdev_info(dev, "loopback requires clock\n");
return -1;
}
return 0;
@@ -1077,7 +1078,7 @@ static int dscc4_open(struct net_device *dev)
scc_patchl(0, PowerUp, dpriv, dev, CCR0);
scc_patchl(0, 0x00050000, dpriv, dev, CCR2);
scc_writel(EventsMask, dpriv, dev, IMR);
- printk(KERN_INFO "%s: up again.\n", dev->name);
+ netdev_info(dev, "up again\n");
goto done;
}
@@ -1094,11 +1095,11 @@ static int dscc4_open(struct net_device *dev)
* situations.
*/
if (scc_readl_star(dpriv, dev) & SccBusy) {
- printk(KERN_ERR "%s busy. Try later\n", dev->name);
+ netdev_err(dev, "busy - try later\n");
ret = -EAGAIN;
goto err_out;
} else
- printk(KERN_INFO "%s: available. Good\n", dev->name);
+ netdev_info(dev, "available - good\n");
scc_writel(EventsMask, dpriv, dev, IMR);
@@ -1116,7 +1117,7 @@ static int dscc4_open(struct net_device *dev)
* reset is needed. Suggestions anyone ?
*/
if ((ret = dscc4_xpr_ack(dpriv)) < 0) {
- printk(KERN_ERR "%s: %s timeout\n", DRV_NAME, "XPR");
+ pr_err("XPR timeout\n");
goto err_disable_scc_events;
}
@@ -1341,8 +1342,7 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EPERM;
if (dpriv->flags & FakeReset) {
- printk(KERN_INFO "%s: please reset the device"
- " before this command\n", dev->name);
+ netdev_info(dev, "please reset the device before this command\n");
return -EPERM;
}
if (copy_from_user(&dpriv->settings, line, size))
@@ -1505,8 +1505,7 @@ static irqreturn_t dscc4_irq(int irq, void *token)
writel(state, ioaddr + GSTAR);
if (state & Arf) {
- printk(KERN_ERR "%s: failure (Arf). Harass the maintener\n",
- dev->name);
+ netdev_err(dev, "failure (Arf). Harass the maintainer\n");
goto out;
}
state &= ~ArAck;
@@ -1514,7 +1513,7 @@ static irqreturn_t dscc4_irq(int irq, void *token)
if (debug > 0)
printk(KERN_DEBUG "%s: CfgIV\n", DRV_NAME);
if (priv->iqcfg[priv->cfg_cur++%IRQ_RING_SIZE] & cpu_to_le32(Arf))
- printk(KERN_ERR "%s: %s failed\n", dev->name, "CFG");
+ netdev_err(dev, "CFG failed\n");
if (!(state &= ~Cfg))
goto out;
}
@@ -1595,8 +1594,8 @@ try:
++dpriv->tx_dirty;
} else {
if (debug > 1)
- printk(KERN_ERR "%s Tx: NULL skb %d\n",
- dev->name, cur);
+ netdev_err(dev, "Tx: NULL skb %d\n",
+ cur);
}
/*
* If the driver ends sending crap on the wire, it
@@ -1615,7 +1614,7 @@ try:
* Transmit Data Underrun
*/
if (state & Xdu) {
- printk(KERN_ERR "%s: XDU. Ask maintainer\n", DRV_NAME);
+ netdev_err(dev, "Tx Data Underrun. Ask maintainer\n");
dpriv->flags = NeedIDT;
/* Tx reset */
writel(MTFi | Rdt,
@@ -1624,13 +1623,13 @@ try:
return;
}
if (state & Cts) {
- printk(KERN_INFO "%s: CTS transition\n", dev->name);
+ netdev_info(dev, "CTS transition\n");
if (!(state &= ~Cts)) /* DEBUG */
goto try;
}
if (state & Xmr) {
/* Frame needs to be sent again - FIXME */
- printk(KERN_ERR "%s: Xmr. Ask maintainer\n", DRV_NAME);
+ netdev_err(dev, "Tx ReTx. Ask maintainer\n");
if (!(state &= ~Xmr)) /* DEBUG */
goto try;
}
@@ -1648,7 +1647,7 @@ try:
break;
}
if (!i)
- printk(KERN_INFO "%s busy in irq\n", dev->name);
+ netdev_info(dev, "busy in irq\n");
scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id;
/* Keep this order: IDT before IDR */
@@ -1685,7 +1684,7 @@ try:
}
if (state & Cd) {
if (debug > 0)
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ netdev_info(dev, "CD transition\n");
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
@@ -1694,11 +1693,11 @@ try:
#ifdef DSCC4_POLLING
while (!dscc4_tx_poll(dpriv, dev));
#endif
- printk(KERN_INFO "%s: Tx Hi\n", dev->name);
+ netdev_info(dev, "Tx Hi\n");
state &= ~Hi;
}
if (state & Err) {
- printk(KERN_INFO "%s: Tx ERR\n", dev->name);
+ netdev_info(dev, "Tx ERR\n");
dev->stats.tx_errors++;
state &= ~Err;
}
@@ -1768,7 +1767,7 @@ try:
goto try;
}
if (state & Hi ) { /* HI bit */
- printk(KERN_INFO "%s: Rx Hi\n", dev->name);
+ netdev_info(dev, "Rx Hi\n");
state &= ~Hi;
goto try;
}
@@ -1799,7 +1798,7 @@ try:
goto try;
}
if (state & Cts) {
- printk(KERN_INFO "%s: CTS transition\n", dev->name);
+ netdev_info(dev, "CTS transition\n");
if (!(state &= ~Cts)) /* DEBUG */
goto try;
}
@@ -1858,14 +1857,12 @@ try:
sizeof(struct RxFD), scc_addr + CH0BRDA);
writel(MTFi|Rdr|Idr, scc_addr + CH0CFG);
if (dscc4_do_action(dev, "RDR") < 0) {
- printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
- dev->name, "RDR");
+ netdev_err(dev, "RDO recovery failed(RDR)\n");
goto rdo_end;
}
writel(MTFi|Idr, scc_addr + CH0CFG);
if (dscc4_do_action(dev, "IDR") < 0) {
- printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
- dev->name, "IDR");
+ netdev_err(dev, "RDO recovery failed(IDR)\n");
goto rdo_end;
}
rdo_end:
@@ -1874,7 +1871,7 @@ try:
goto try;
}
if (state & Cd) {
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ netdev_info(dev, "CD transition\n");
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 777d1a4e81b2..ebb9f24eefb5 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/if.h>
#include <linux/hdlc.h>
#include <asm/io.h>
@@ -1664,10 +1665,9 @@ check_started_ok(struct fst_card_info *card)
* existing firmware etc so we just report it for the moment.
*/
if (FST_RDL(card, numberOfPorts) != card->nports) {
- pr_warning("Port count mismatch on card %d. "
- "Firmware thinks %d we say %d\n",
- card->card_no,
- FST_RDL(card, numberOfPorts), card->nports);
+ pr_warn("Port count mismatch on card %d. Firmware thinks %d we say %d\n",
+ card->card_no,
+ FST_RDL(card, numberOfPorts), card->nports);
}
}
diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c
index a3ea27ce04f2..33b67d88fceb 100644
--- a/drivers/net/wan/hd64570.c
+++ b/drivers/net/wan/hd64570.c
@@ -582,8 +582,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_RX(phy_node(port)), card), port->rxin,
sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
- printk(KERN_CONT "\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
"last=%u %sactive",
@@ -593,8 +593,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_TX(phy_node(port)), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port_to_card(port)->tx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
- printk("\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, ST: %02x %02x %02x %02x,"
" FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c
index e305274f83fb..efc0db101183 100644
--- a/drivers/net/wan/hd64572.c
+++ b/drivers/net/wan/hd64572.c
@@ -530,8 +530,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_RX(port->chan), card), port->rxin,
sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
- printk(KERN_CONT "\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
"last=%u %sactive",
@@ -541,8 +541,8 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(DSR_TX(port->chan), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port->card->tx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
- printk("\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x,"
" ST: %02x %02x %02x %02x %02x, FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 5d4bb615ccce..10cc7df95498 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -22,6 +22,8 @@
* - proto->start() and stop() are called with spin_lock_irq held.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/hdlc.h>
#include <linux/if_arp.h>
@@ -130,10 +132,10 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
goto carrier_exit;
if (hdlc->carrier) {
- printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+ netdev_info(dev, "Carrier detected\n");
hdlc_proto_start(dev);
} else {
- printk(KERN_INFO "%s: Carrier lost\n", dev->name);
+ netdev_info(dev, "Carrier lost\n");
hdlc_proto_stop(dev);
}
@@ -165,10 +167,10 @@ int hdlc_open(struct net_device *dev)
spin_lock_irq(&hdlc->state_lock);
if (hdlc->carrier) {
- printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+ netdev_info(dev, "Carrier detected\n");
hdlc_proto_start(dev);
} else
- printk(KERN_INFO "%s: No carrier\n", dev->name);
+ netdev_info(dev, "No carrier\n");
hdlc->open = 1;
@@ -281,8 +283,8 @@ int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
if (size)
if ((dev_to_hdlc(dev)->state = kmalloc(size,
GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "Memory squeeze on"
- " hdlc_proto_attach()\n");
+ netdev_warn(dev,
+ "Memory squeeze on hdlc_proto_attach()\n");
module_put(proto->module);
return -ENOBUFS;
}
@@ -363,7 +365,7 @@ static int __init hdlc_module_init(void)
{
int result;
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0)
return result;
dev_add_pack(&hdlc_packet_type);
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index b1e5e5b69c2a..3f20808b5ff8 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -103,9 +103,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
skb = dev_alloc_skb(sizeof(struct hdlc_header) +
sizeof(struct cisco_packet));
if (!skb) {
- printk(KERN_WARNING
- "%s: Memory squeeze on cisco_keepalive_send()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on cisco_keepalive_send()\n");
return;
}
skb_reserve(skb, 4);
@@ -181,8 +179,8 @@ static int cisco_rx(struct sk_buff *skb)
CISCO_PACKET_LEN) &&
(skb->len != sizeof(struct hdlc_header) +
CISCO_BIG_PACKET_LEN)) {
- printk(KERN_INFO "%s: Invalid length of Cisco control"
- " packet (%d bytes)\n", dev->name, skb->len);
+ netdev_info(dev, "Invalid length of Cisco control packet (%d bytes)\n",
+ skb->len);
goto rx_error;
}
@@ -217,8 +215,7 @@ static int cisco_rx(struct sk_buff *skb)
return NET_RX_SUCCESS;
case CISCO_ADDR_REPLY:
- printk(KERN_INFO "%s: Unexpected Cisco IP address "
- "reply\n", dev->name);
+ netdev_info(dev, "Unexpected Cisco IP address reply\n");
goto rx_error;
case CISCO_KEEPALIVE_REQ:
@@ -235,9 +232,8 @@ static int cisco_rx(struct sk_buff *skb)
min = sec / 60; sec -= min * 60;
hrs = min / 60; min -= hrs * 60;
days = hrs / 24; hrs -= days * 24;
- printk(KERN_INFO "%s: Link up (peer "
- "uptime %ud%uh%um%us)\n",
- dev->name, days, hrs, min, sec);
+ netdev_info(dev, "Link up (peer uptime %ud%uh%um%us)\n",
+ days, hrs, min, sec);
netif_dormant_off(dev);
st->up = 1;
}
@@ -249,8 +245,7 @@ static int cisco_rx(struct sk_buff *skb)
} /* switch (keepalive type) */
} /* switch (protocol) */
- printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
- ntohs(data->protocol));
+ netdev_info(dev, "Unsupported protocol %x\n", ntohs(data->protocol));
dev_kfree_skb_any(skb);
return NET_RX_DROP;
@@ -272,7 +267,7 @@ static void cisco_timer(unsigned long arg)
if (st->up &&
time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) {
st->up = 0;
- printk(KERN_INFO "%s: Link down\n", dev->name);
+ netdev_info(dev, "Link down\n");
netif_dormant_on(dev);
}
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index fc433f28c047..b25c9229a6a9 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -446,15 +446,14 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
static inline void fr_log_dlci_active(pvc_device *pvc)
{
- printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
- pvc->frad->name,
- pvc->dlci,
- pvc->main ? pvc->main->name : "",
- pvc->main && pvc->ether ? " " : "",
- pvc->ether ? pvc->ether->name : "",
- pvc->state.new ? " new" : "",
- !pvc->state.exist ? "deleted" :
- pvc->state.active ? "active" : "inactive");
+ netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n",
+ pvc->dlci,
+ pvc->main ? pvc->main->name : "",
+ pvc->main && pvc->ether ? " " : "",
+ pvc->ether ? pvc->ether->name : "",
+ pvc->state.new ? " new" : "",
+ !pvc->state.exist ? "deleted" :
+ pvc->state.active ? "active" : "inactive");
}
@@ -481,16 +480,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
if (dce && fullrep) {
len += state(hdlc)->dce_pvc_count * (2 + stat_len);
if (len > HDLC_MAX_MRU) {
- printk(KERN_WARNING "%s: Too many PVCs while sending "
- "LMI full report\n", dev->name);
+ netdev_warn(dev, "Too many PVCs while sending LMI full report\n");
return;
}
}
skb = dev_alloc_skb(len);
if (!skb) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on fr_lmi_send()\n");
return;
}
memset(skb->data, 0, len);
@@ -615,8 +612,7 @@ static void fr_timer(unsigned long arg)
state(hdlc)->last_errors <<= 1; /* Shift the list */
if (state(hdlc)->request) {
if (state(hdlc)->reliable)
- printk(KERN_INFO "%s: No LMI status reply "
- "received\n", dev->name);
+ netdev_info(dev, "No LMI status reply received\n");
state(hdlc)->last_errors |= 1;
}
@@ -628,8 +624,7 @@ static void fr_timer(unsigned long arg)
}
if (state(hdlc)->reliable != reliable) {
- printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
- reliable ? "" : "un");
+ netdev_info(dev, "Link %sreliable\n", reliable ? "" : "un");
fr_set_link_state(reliable, dev);
}
@@ -665,33 +660,32 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
LMI_CCITT_CISCO_LENGTH)) {
- printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
+ netdev_info(dev, "Short LMI frame\n");
return 1;
}
if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
NLPID_CCITT_ANSI_LMI)) {
- printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
- dev->name);
+ netdev_info(dev, "Received non-LMI frame with LMI DLCI\n");
return 1;
}
if (skb->data[4] != LMI_CALLREF) {
- printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
- dev->name, skb->data[4]);
+ netdev_info(dev, "Invalid LMI Call reference (0x%02X)\n",
+ skb->data[4]);
return 1;
}
if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
- printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
- dev->name, skb->data[5]);
+ netdev_info(dev, "Invalid LMI Message type (0x%02X)\n",
+ skb->data[5]);
return 1;
}
if (lmi == LMI_ANSI) {
if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
- printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
- " message (0x%02X)\n", dev->name, skb->data[6]);
+ netdev_info(dev, "Not ANSI locking shift in LMI message (0x%02X)\n",
+ skb->data[6]);
return 1;
}
i = 7;
@@ -700,34 +694,34 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
LMI_ANSI_CISCO_REPTYPE)) {
- printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
- dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI Report type IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != LMI_REPT_LEN) {
- printk(KERN_INFO "%s: Invalid LMI Report type IE length"
- " (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI Report type IE length (%u)\n",
+ skb->data[i]);
return 1;
}
reptype = skb->data[++i];
if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
- printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
- dev->name, reptype);
+ netdev_info(dev, "Unsupported LMI Report type (0x%02X)\n",
+ reptype);
return 1;
}
if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
LMI_ANSI_CISCO_ALIVE)) {
- printk(KERN_INFO "%s: Not an LMI Link integrity verification"
- " IE (0x%02X)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI Link integrity verification IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != LMI_INTEG_LEN) {
- printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
- " IE length (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI Link integrity verification IE length (%u)\n",
+ skb->data[i]);
return 1;
}
i++;
@@ -801,14 +795,14 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
LMI_ANSI_CISCO_PVCSTAT)) {
- printk(KERN_INFO "%s: Not an LMI PVC status IE"
- " (0x%02X)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI PVC status IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != stat_len) {
- printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
- " (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI PVC status IE length (%u)\n",
+ skb->data[i]);
return 1;
}
i++;
@@ -829,9 +823,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc = add_pvc(dev, dlci);
if (!pvc && !no_ram) {
- printk(KERN_WARNING
- "%s: Memory squeeze on fr_lmi_recv()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on fr_lmi_recv()\n");
no_ram = 1;
}
@@ -902,8 +894,8 @@ static int fr_rx(struct sk_buff *skb)
pvc = find_pvc(hdlc, dlci);
if (!pvc) {
#ifdef DEBUG_PKT
- printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
- frad->name, dlci);
+ netdev_info(frad, "No PVC for received frame's DLCI %d\n",
+ dlci);
#endif
dev_kfree_skb_any(skb);
return NET_RX_DROP;
@@ -962,14 +954,14 @@ static int fr_rx(struct sk_buff *skb)
break;
default:
- printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
- "PID=%x\n", frad->name, oui, pid);
+ netdev_info(frad, "Unsupported protocol, OUI=%x PID=%x\n",
+ oui, pid);
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
} else {
- printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
- "length = %i\n", frad->name, data[3], skb->len);
+ netdev_info(frad, "Unsupported protocol, NLPID=%x length=%i\n",
+ data[3], skb->len);
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
@@ -1073,8 +1065,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
int used;
if ((pvc = add_pvc(frad, dlci)) == NULL) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
- frad->name);
+ netdev_warn(frad, "Memory squeeze on fr_add_pvc()\n");
return -ENOBUFS;
}
@@ -1089,8 +1080,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
dev = alloc_netdev(0, "pvc%d", pvc_setup);
if (!dev) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
- frad->name);
+ netdev_warn(frad, "Memory squeeze on fr_pvc()\n");
delete_unused_pvcs(hdlc);
return -ENOBUFS;
}
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 941f053e650e..055a918067e6 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -223,8 +223,7 @@ static void ppp_tx_cp(struct net_device *dev, u16 pid, u8 code,
skb = dev_alloc_skb(sizeof(struct hdlc_header) +
sizeof(struct cp_header) + magic_len + len);
if (!skb) {
- printk(KERN_WARNING "%s: out of memory in ppp_tx_cp()\n",
- dev->name);
+ netdev_warn(dev, "out of memory in ppp_tx_cp()\n");
return;
}
skb_reserve(skb, sizeof(struct hdlc_header));
@@ -345,7 +344,7 @@ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data);
if (old_state != OPENED && proto->state == OPENED) {
- printk(KERN_INFO "%s: %s up\n", dev->name, proto_name(pid));
+ netdev_info(dev, "%s up\n", proto_name(pid));
if (pid == PID_LCP) {
netif_dormant_off(dev);
ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL);
@@ -356,7 +355,7 @@ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
}
}
if (old_state == OPENED && proto->state != OPENED) {
- printk(KERN_INFO "%s: %s down\n", dev->name, proto_name(pid));
+ netdev_info(dev, "%s down\n", proto_name(pid));
if (pid == PID_LCP) {
netif_dormant_on(dev);
ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL);
@@ -585,7 +584,7 @@ static void ppp_timer(unsigned long arg)
break;
if (time_after(jiffies, ppp->last_pong +
ppp->keepalive_timeout * HZ)) {
- printk(KERN_INFO "%s: Link down\n", proto->dev->name);
+ netdev_info(proto->dev, "Link down\n");
ppp_cp_event(proto->dev, PID_LCP, STOP, 0, 0, 0, NULL);
ppp_cp_event(proto->dev, PID_LCP, START, 0, 0, 0, NULL);
} else { /* send keep-alive packet */
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index 70527e5a54a2..56aeb011cb3d 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -34,7 +34,7 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "%s: out of memory\n", dev->name);
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -106,9 +106,8 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
/* Send connect confirm. msg to level 3 */
x25_connected(dev, 0);
else
- printk(KERN_ERR "%s: LAPB connect request "
- "failed, error code = %i\n",
- dev->name, result);
+ netdev_err(dev, "LAPB connect request failed, error code = %i\n",
+ result);
}
break;
@@ -118,9 +117,8 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
/* Send disconnect confirm. msg to level 3 */
x25_disconnected(dev, 0);
else
- printk(KERN_ERR "%s: LAPB disconnect request "
- "failed, error code = %i\n",
- dev->name, result);
+ netdev_err(dev, "LAPB disconnect request failed, error code = %i\n",
+ result);
}
break;
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index e817583e6ec5..3d80e4267de8 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -20,6 +20,8 @@
* Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -192,8 +194,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
*/
if (!request_region(iobase, 8, "Comtrol SV11")) {
- printk(KERN_WARNING "hostess: I/O 0x%X already in use.\n",
- iobase);
+ pr_warn("I/O 0x%X already in use\n", iobase);
return NULL;
}
@@ -221,7 +222,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
"Hostess SV11", sv) < 0) {
- printk(KERN_WARNING "hostess: IRQ %d already in use.\n", irq);
+ pr_warn("IRQ %d already in use\n", irq);
goto err_irq;
}
@@ -255,7 +256,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
*/
if (z8530_init(sv)) {
- printk(KERN_ERR "Z8530 series device not found.\n");
+ pr_err("Z8530 series device not found\n");
enable_irq(irq);
goto free_dma;
}
@@ -282,7 +283,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
netdev->irq = irq;
if (register_hdlc_device(netdev)) {
- printk(KERN_ERR "hostess: unable to register HDLC device.\n");
+ pr_err("unable to register HDLC device\n");
free_netdev(netdev);
goto free_dma;
}
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index f1e1643dc3eb..aaaca9aa2293 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -8,6 +8,8 @@
* as published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/bitops.h>
#include <linux/cdev.h>
#include <linux/dma-mapping.h>
@@ -358,9 +360,8 @@ static void hss_npe_send(struct port *port, struct msg *msg, const char* what)
{
u32 *val = (u32*)msg;
if (npe_send_message(port->npe, msg, what)) {
- printk(KERN_CRIT "HSS-%i: unable to send command [%08X:%08X]"
- " to %s\n", port->id, val[0], val[1],
- npe_name(port->npe));
+ pr_crit("HSS-%i: unable to send command [%08X:%08X] to %s\n",
+ port->id, val[0], val[1], npe_name(port->npe));
BUG();
}
}
@@ -447,8 +448,7 @@ static void hss_config(struct port *port)
if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") ||
/* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */
msg.cmd != PORT_CONFIG_LOAD || msg.data32) {
- printk(KERN_CRIT "HSS-%i: HSS_LOAD_CONFIG failed\n",
- port->id);
+ pr_crit("HSS-%i: HSS_LOAD_CONFIG failed\n", port->id);
BUG();
}
@@ -477,8 +477,7 @@ static u32 hss_get_status(struct port *port)
msg.hss_port = port->id;
hss_npe_send(port, &msg, "PORT_ERROR_READ");
if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) {
- printk(KERN_CRIT "HSS-%i: unable to read HSS status\n",
- port->id);
+ pr_crit("HSS-%i: unable to read HSS status\n", port->id);
BUG();
}
@@ -736,9 +735,8 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
dev->stats.rx_errors++;
break;
default: /* FIXME - remove printk */
- printk(KERN_ERR "%s: hss_hdlc_poll: status 0x%02X"
- " errors %u\n", dev->name, desc->status,
- desc->error_count);
+ netdev_err(dev, "hss_hdlc_poll: status 0x%02X errors %u\n",
+ desc->status, desc->error_count);
dev->stats.rx_errors++;
}
@@ -1127,8 +1125,8 @@ static int hss_hdlc_close(struct net_device *dev)
buffs--;
if (buffs)
- printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
- " left in NPE\n", dev->name, buffs);
+ netdev_crit(dev, "unable to drain RX queue, %i buffer(s) left in NPE\n",
+ buffs);
buffs = TX_DESCS;
while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0)
@@ -1143,8 +1141,8 @@ static int hss_hdlc_close(struct net_device *dev)
} while (++i < MAX_CLOSE_WAIT);
if (buffs)
- printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
- "left in NPE\n", dev->name, buffs);
+ netdev_crit(dev, "unable to drain TX queue, %i buffer(s) left in NPE\n",
+ buffs);
#if DEBUG_CLOSE
if (!buffs)
printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
@@ -1364,7 +1362,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
platform_set_drvdata(pdev, port);
- printk(KERN_INFO "%s: HSS-%i\n", dev->name, port->id);
+ netdev_info(dev, "HSS-%i\n", port->id);
return 0;
err_free_netdev:
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index eec463f99c09..a817081737a0 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -20,6 +20,8 @@
* 2000-11-14 Henner Eisen dev_hold/put, NETDEV_GOING_DOWN support
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -165,13 +167,11 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
break;
case X25_IFACE_CONNECT:
if ((err = lapb_connect_request(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_connect_request "
- "error: %d\n", err);
+ pr_err("lapb_connect_request error: %d\n", err);
goto drop;
case X25_IFACE_DISCONNECT:
if ((err = lapb_disconnect_request(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_disconnect_request "
- "err: %d\n", err);
+ pr_err("lapb_disconnect_request err: %d\n", err);
/* Fall thru */
default:
goto drop;
@@ -180,7 +180,7 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
skb_pull(skb, 1);
if ((err = lapb_data_request(dev, skb)) != LAPB_OK) {
- printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
+ pr_err("lapb_data_request error - %d\n", err);
goto drop;
}
out:
@@ -220,7 +220,7 @@ static void lapbeth_connected(struct net_device *dev, int reason)
struct sk_buff *skb = dev_alloc_skb(1);
if (!skb) {
- printk(KERN_ERR "lapbeth: out of memory\n");
+ pr_err("out of memory\n");
return;
}
@@ -237,7 +237,7 @@ static void lapbeth_disconnected(struct net_device *dev, int reason)
struct sk_buff *skb = dev_alloc_skb(1);
if (!skb) {
- printk(KERN_ERR "lapbeth: out of memory\n");
+ pr_err("out of memory\n");
return;
}
@@ -277,7 +277,7 @@ static int lapbeth_open(struct net_device *dev)
int err;
if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
- printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
+ pr_err("lapb_register error: %d\n", err);
return -ENODEV;
}
@@ -292,7 +292,7 @@ static int lapbeth_close(struct net_device *dev)
netif_stop_queue(dev);
if ((err = lapb_unregister(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err);
+ pr_err("lapb_unregister error: %d\n", err);
return 0;
}
diff --git a/drivers/net/wan/lmc/lmc_var.h b/drivers/net/wan/lmc/lmc_var.h
index 01ad45218d19..a1d202d8ad67 100644
--- a/drivers/net/wan/lmc/lmc_var.h
+++ b/drivers/net/wan/lmc/lmc_var.h
@@ -380,7 +380,7 @@ struct lmc___softc {
/* CSR6 settings */
#define OPERATION_MODE 0x00000200 /* Full Duplex */
#define PROMISC_MODE 0x00000040 /* Promiscuous Mode */
-#define RECIEVE_ALL 0x40000000 /* Receive All */
+#define RECEIVE_ALL 0x40000000 /* Receive All */
#define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames */
/* Dec control registers CSR6 as well */
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 17d408fe693f..5129ad514d26 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -16,6 +16,8 @@
* SDL Inc. PPP/HDLC/CISCO driver
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -341,57 +343,57 @@ static int __init n2_run(unsigned long io, unsigned long irq,
int i;
if (io < 0x200 || io > 0x3FF || (io % N2_IOPORTS) != 0) {
- printk(KERN_ERR "n2: invalid I/O port value\n");
+ pr_err("invalid I/O port value\n");
return -ENODEV;
}
if (irq < 3 || irq > 15 || irq == 6) /* FIXME */ {
- printk(KERN_ERR "n2: invalid IRQ value\n");
+ pr_err("invalid IRQ value\n");
return -ENODEV;
}
if (winbase < 0xA0000 || winbase > 0xFFFFF || (winbase & 0xFFF) != 0) {
- printk(KERN_ERR "n2: invalid RAM value\n");
+ pr_err("invalid RAM value\n");
return -ENODEV;
}
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "n2: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
return -ENOBUFS;
}
card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
if (!card->ports[0].dev || !card->ports[1].dev) {
- printk(KERN_ERR "n2: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
n2_destroy_card(card);
return -ENOMEM;
}
if (!request_region(io, N2_IOPORTS, devname)) {
- printk(KERN_ERR "n2: I/O port region in use\n");
+ pr_err("I/O port region in use\n");
n2_destroy_card(card);
return -EBUSY;
}
card->io = io;
if (request_irq(irq, sca_intr, 0, devname, card)) {
- printk(KERN_ERR "n2: could not allocate IRQ\n");
+ pr_err("could not allocate IRQ\n");
n2_destroy_card(card);
return -EBUSY;
}
card->irq = irq;
if (!request_mem_region(winbase, USE_WINDOWSIZE, devname)) {
- printk(KERN_ERR "n2: could not request RAM window\n");
+ pr_err("could not request RAM window\n");
n2_destroy_card(card);
return -EBUSY;
}
card->phy_winbase = winbase;
card->winbase = ioremap(winbase, USE_WINDOWSIZE);
if (!card->winbase) {
- printk(KERN_ERR "n2: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
n2_destroy_card(card);
return -EFAULT;
}
@@ -413,7 +415,7 @@ static int __init n2_run(unsigned long io, unsigned long irq,
break;
default:
- printk(KERN_ERR "n2: invalid window size\n");
+ pr_err("invalid window size\n");
n2_destroy_card(card);
return -ENODEV;
}
@@ -433,12 +435,12 @@ static int __init n2_run(unsigned long io, unsigned long irq,
card->buff_offset = (valid0 + valid1) * sizeof(pkt_desc) *
(card->tx_ring_buffers + card->rx_ring_buffers);
- printk(KERN_INFO "n2: RISCom/N2 %u KB RAM, IRQ%u, "
- "using %u TX + %u RX packets rings\n", card->ram_size / 1024,
- card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("RISCom/N2 %u KB RAM, IRQ%u, using %u TX + %u RX packets rings\n",
+ card->ram_size / 1024, card->irq,
+ card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "n2: RAM test failed\n");
+ pr_err("RAM test failed\n");
n2_destroy_card(card);
return -EIO;
}
@@ -474,16 +476,14 @@ static int __init n2_run(unsigned long io, unsigned long irq,
port->card = card;
if (register_hdlc_device(dev)) {
- printk(KERN_WARNING "n2: unable to register hdlc "
- "device\n");
+ pr_warn("unable to register hdlc device\n");
port->card = NULL;
n2_destroy_card(card);
return -ENOBUFS;
}
sca_init_port(port); /* Set up SCA memory */
- printk(KERN_INFO "%s: RISCom/N2 node %d\n",
- dev->name, port->phy_node);
+ netdev_info(dev, "RISCom/N2 node %d\n", port->phy_node);
}
*new_card = card;
@@ -498,12 +498,12 @@ static int __init n2_init(void)
{
if (hw==NULL) {
#ifdef MODULE
- printk(KERN_INFO "n2: no card initialized\n");
+ pr_info("no card initialized\n");
#endif
return -EINVAL; /* no parameters specified, abort */
}
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
do {
unsigned long io, irq, ram;
@@ -541,7 +541,7 @@ static int __init n2_init(void)
return first_card ? 0 : -EINVAL;
}while(*hw++ == ':');
- printk(KERN_ERR "n2: invalid hardware parameters\n");
+ pr_err("invalid hardware parameters\n");
return first_card ? 0 : -EINVAL;
}
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 9617d3d0ee39..1eeedd6a10b1 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -212,6 +212,8 @@ static const char rcsid[] =
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -3242,7 +3244,7 @@ static inline void show_version(void)
rcsdate++;
tmp = strrchr(rcsdate, ' ');
*tmp = '\0';
- printk(KERN_INFO "Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
+ pr_info("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
} /* show_version */
static const struct net_device_ops cpc_netdev_ops = {
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 1c65d1c33873..d47d2cd10475 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -755,7 +755,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
dsr_rx = cpc_readb(card->hw.scabase + DSR_RX(ch));
- cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty;
+ cpc_tty = pc300dev->cpc_tty;
while (1) {
rx_len = 0;
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index c7ab3becd261..c49c1b3c7aad 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -17,6 +17,8 @@
* PC300/X21 cards.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -318,7 +320,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "pc300: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -328,7 +330,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
- printk(KERN_ERR "pc300: invalid card EEPROM parameters\n");
+ pr_err("invalid card EEPROM parameters\n");
pc300_pci_remove_one(pdev);
return -EFAULT;
}
@@ -345,7 +347,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
if (card->plxbase == NULL ||
card->scabase == NULL ||
card->rambase == NULL) {
- printk(KERN_ERR "pc300: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
pc300_pci_remove_one(pdev);
}
@@ -370,7 +372,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
for (i = 0; i < card->n_ports; i++)
if (!(card->ports[i].netdev = alloc_hdlcdev(&card->ports[i]))) {
- printk(KERN_ERR "pc300: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pc300_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -411,15 +413,14 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
card->buff_offset = card->n_ports * sizeof(pkt_desc) *
(card->tx_ring_buffers + card->rx_ring_buffers);
- printk(KERN_INFO "pc300: PC300/%s, %u KB RAM at 0x%x, IRQ%u, "
- "using %u TX + %u RX packets rings\n",
- card->type == PC300_X21 ? "X21" :
- card->type == PC300_TE ? "TE" : "RSV",
- ramsize / 1024, ramphys, pdev->irq,
- card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("PC300/%s, %u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+ card->type == PC300_X21 ? "X21" :
+ card->type == PC300_TE ? "TE" : "RSV",
+ ramsize / 1024, ramphys, pdev->irq,
+ card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "pc300: RAM test failed\n");
+ pr_err("RAM test failed\n");
pc300_pci_remove_one(pdev);
return -EFAULT;
}
@@ -429,8 +430,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
/* Allocate IRQ */
if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pc300", card)) {
- printk(KERN_WARNING "pc300: could not allocate IRQ%d.\n",
- pdev->irq);
+ pr_warn("could not allocate IRQ%d\n", pdev->irq);
pc300_pci_remove_one(pdev);
return -EBUSY;
}
@@ -466,15 +466,13 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
sca_init_port(port);
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "pc300: unable to register hdlc "
- "device\n");
+ pr_err("unable to register hdlc device\n");
port->card = NULL;
pc300_pci_remove_one(pdev);
return -ENOBUFS;
}
- printk(KERN_INFO "%s: PC300 channel %d\n",
- dev->name, port->chan);
+ netdev_info(dev, "PC300 channel %d\n", port->chan);
}
return 0;
}
@@ -505,11 +503,11 @@ static struct pci_driver pc300_pci_driver = {
static int __init pc300_init_module(void)
{
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
- printk(KERN_ERR "pc300: Invalid PCI clock frequency\n");
+ pr_err("Invalid PCI clock frequency\n");
return -EINVAL;
}
if (use_crystal_clock != 0 && use_crystal_clock != 1) {
- printk(KERN_ERR "pc300: Invalid 'use_crystal_clock' value\n");
+ pr_err("Invalid 'use_crystal_clock' value\n");
return -EINVAL;
}
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index fd7375955e41..1ce21163c776 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -14,6 +14,8 @@
* PLX Technology Inc. PCI9052 Data Book
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -297,7 +299,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -306,7 +308,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
card->ports[0].netdev = alloc_hdlcdev(&card->ports[0]);
card->ports[1].netdev = alloc_hdlcdev(&card->ports[1]);
if (!card->ports[0].netdev || !card->ports[1].netdev) {
- printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci200_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -314,7 +316,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
- printk(KERN_ERR "pci200syn: invalid card EEPROM parameters\n");
+ pr_err("invalid card EEPROM parameters\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -331,7 +333,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
if (card->plxbase == NULL ||
card->scabase == NULL ||
card->rambase == NULL) {
- printk(KERN_ERR "pci200syn: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -357,12 +359,12 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
card->buff_offset = 2 * sizeof(pkt_desc) * (card->tx_ring_buffers +
card->rx_ring_buffers);
- printk(KERN_INFO "pci200syn: %u KB RAM at 0x%x, IRQ%u, using %u TX +"
- " %u RX packets rings\n", ramsize / 1024, ramphys,
- pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("%u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+ ramsize / 1024, ramphys,
+ pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "pci200syn: RAM test failed\n");
+ pr_err("RAM test failed\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -373,8 +375,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
/* Allocate IRQ */
if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pci200syn", card)) {
- printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
- pdev->irq);
+ pr_warn("could not allocate IRQ%d\n", pdev->irq);
pci200_pci_remove_one(pdev);
return -EBUSY;
}
@@ -400,15 +401,13 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
port->card = card;
sca_init_port(port);
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "pci200syn: unable to register hdlc "
- "device\n");
+ pr_err("unable to register hdlc device\n");
port->card = NULL;
pci200_pci_remove_one(pdev);
return -ENOBUFS;
}
- printk(KERN_INFO "%s: PCI200SYN channel %d\n",
- dev->name, port->chan);
+ netdev_info(dev, "PCI200SYN channel %d\n", port->chan);
}
sca_flush(card);
@@ -435,7 +434,7 @@ static struct pci_driver pci200_pci_driver = {
static int __init pci200_init_module(void)
{
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
- printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
+ pr_err("Invalid PCI clock frequency\n");
return -EINVAL;
}
return pci_register_driver(&pci200_pci_driver);
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index cff13a9597cd..86127bcc9f7a 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -37,6 +37,8 @@
* Known problem: this driver wasn't tested on multiprocessor machine.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
@@ -200,8 +202,8 @@ sbni_isa_probe( struct net_device *dev )
return 0;
else {
- printk( KERN_ERR "sbni: base address 0x%lx is busy, or adapter "
- "is malfunctional!\n", dev->base_addr );
+ pr_err("base address 0x%lx is busy, or adapter is malfunctional!\n",
+ dev->base_addr);
return -ENODEV;
}
}
@@ -226,7 +228,6 @@ static void __init sbni_devsetup(struct net_device *dev)
int __init sbni_probe(int unit)
{
struct net_device *dev;
- static unsigned version_printed __initdata = 0;
int err;
dev = alloc_netdev(sizeof(struct net_local), "sbni", sbni_devsetup);
@@ -250,8 +251,7 @@ int __init sbni_probe(int unit)
free_netdev(dev);
return err;
}
- if( version_printed++ == 0 )
- printk( KERN_INFO "%s", version );
+ pr_info_once("%s", version);
return 0;
}
@@ -303,7 +303,6 @@ sbni_pci_probe( struct net_device *dev )
!= NULL ) {
int pci_irq_line;
unsigned long pci_ioaddr;
- u16 subsys;
if( pdev->vendor != SBNI_PCI_VENDOR &&
pdev->device != SBNI_PCI_DEVICE )
@@ -314,9 +313,7 @@ sbni_pci_probe( struct net_device *dev )
/* Avoid already found cards from previous calls */
if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
- pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys );
-
- if (subsys != 2)
+ if (pdev->subsystem_device != 2)
continue;
/* Dual adapter is present */
@@ -326,9 +323,9 @@ sbni_pci_probe( struct net_device *dev )
}
if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
- printk( KERN_WARNING
- " WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
- " You should use the PCI BIOS setup to assign a valid IRQ line.\n",
+ pr_warn(
+"WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
+"You should use the PCI BIOS setup to assign a valid IRQ line.\n",
pci_irq_line );
/* avoiding re-enable dual adapters */
@@ -372,8 +369,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
outb( 0, ioaddr + CSR0 );
if( !irq ) {
- printk( KERN_ERR "%s: can't detect device irq!\n",
- dev->name );
+ pr_err("%s: can't detect device irq!\n", dev->name);
release_region( ioaddr, SBNI_IO_EXTENT );
return NULL;
}
@@ -386,7 +382,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
/* Fill in sbni-specific dev fields. */
nl = netdev_priv(dev);
if( !nl ) {
- printk( KERN_ERR "%s: unable to get memory!\n", dev->name );
+ pr_err("%s: unable to get memory!\n", dev->name);
release_region( ioaddr, SBNI_IO_EXTENT );
return NULL;
}
@@ -415,21 +411,21 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
if( inb( ioaddr + CSR0 ) & 0x01 )
nl->state |= FL_SLOW_MODE;
- printk( KERN_NOTICE "%s: ioaddr %#lx, irq %d, "
- "MAC: 00:ff:01:%02x:%02x:%02x\n",
- dev->name, dev->base_addr, dev->irq,
- ((u8 *) dev->dev_addr) [3],
- ((u8 *) dev->dev_addr) [4],
- ((u8 *) dev->dev_addr) [5] );
+ pr_notice("%s: ioaddr %#lx, irq %d, MAC: 00:ff:01:%02x:%02x:%02x\n",
+ dev->name, dev->base_addr, dev->irq,
+ ((u8 *)dev->dev_addr)[3],
+ ((u8 *)dev->dev_addr)[4],
+ ((u8 *)dev->dev_addr)[5]);
- printk( KERN_NOTICE "%s: speed %d, receive level ", dev->name,
- ( (nl->state & FL_SLOW_MODE) ? 500000 : 2000000)
- / (1 << nl->csr1.rate) );
+ pr_notice("%s: speed %d",
+ dev->name,
+ ((nl->state & FL_SLOW_MODE) ? 500000 : 2000000)
+ / (1 << nl->csr1.rate));
if( nl->delta_rxl == 0 )
- printk( "0x%x (fixed)\n", nl->cur_rxl_index );
+ pr_cont(", receive level 0x%x (fixed)\n", nl->cur_rxl_index);
else
- printk( "(auto)\n");
+ pr_cont(", receive level (auto)\n");
#ifdef CONFIG_SBNI_MULTILINE
nl->master = dev;
@@ -568,7 +564,7 @@ handle_channel( struct net_device *dev )
*/
csr0 = inb( ioaddr + CSR0 );
if( !(csr0 & TR_RDY) || (csr0 & RC_RDY) )
- printk( KERN_ERR "%s: internal error!\n", dev->name );
+ netdev_err(dev, "internal error!\n");
/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
if( req_ans || nl->tx_frameno != 0 )
@@ -851,7 +847,7 @@ prepare_to_send( struct sk_buff *skb, struct net_device *dev )
/* nl->tx_buf_p == NULL here! */
if( nl->tx_buf_p )
- printk( KERN_ERR "%s: memory leak!\n", dev->name );
+ netdev_err(dev, "memory leak!\n");
nl->outpos = 0;
nl->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
@@ -1179,16 +1175,15 @@ sbni_open( struct net_device *dev )
((struct net_local *) (netdev_priv(*p)))
->second = dev;
- printk( KERN_NOTICE "%s: using shared irq "
- "with %s\n", dev->name, (*p)->name );
+ netdev_notice(dev, "using shared irq with %s\n",
+ (*p)->name);
nl->state |= FL_SECONDARY;
goto handler_attached;
}
}
if( request_irq(dev->irq, sbni_interrupt, IRQF_SHARED, dev->name, dev) ) {
- printk( KERN_ERR "%s: unable to get IRQ %d.\n",
- dev->name, dev->irq );
+ netdev_err(dev, "unable to get IRQ %d\n", dev->irq);
return -EAGAIN;
}
@@ -1220,8 +1215,8 @@ sbni_close( struct net_device *dev )
struct net_local *nl = netdev_priv(dev);
if( nl->second && nl->second->flags & IFF_UP ) {
- printk( KERN_NOTICE "Secondary channel (%s) is active!\n",
- nl->second->name );
+ netdev_notice(dev, "Secondary channel (%s) is active!\n",
+ nl->second->name);
return -EBUSY;
}
@@ -1363,8 +1358,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )
return -EFAULT;
slave_dev = dev_get_by_name(&init_net, slave_name );
if( !slave_dev || !(slave_dev->flags & IFF_UP) ) {
- printk( KERN_ERR "%s: trying to enslave non-active "
- "device %s\n", dev->name, slave_name );
+ netdev_err(dev, "trying to enslave non-active device %s\n",
+ slave_name);
return -EPERM;
}
@@ -1417,8 +1412,7 @@ enslave( struct net_device *dev, struct net_device *slave_dev )
spin_unlock( &snl->lock );
spin_unlock( &nl->lock );
- printk( KERN_NOTICE "%s: slave device (%s) attached.\n",
- dev->name, slave_dev->name );
+ netdev_notice(dev, "slave device (%s) attached\n", slave_dev->name);
return 0;
}
@@ -1547,7 +1541,7 @@ sbni_setup( char *p )
break;
}
bad_param:
- printk( KERN_ERR "Error in sbni kernel parameter!\n" );
+ pr_err("Error in sbni kernel parameter!\n");
return 0;
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 3f4e2b5684db..c8531612eea9 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -32,6 +32,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -350,24 +352,24 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
case SDLA_RET_MODEM:
state = data;
if (*state & SDLA_MODEM_DCD_LOW)
- printk(KERN_INFO "%s: Modem DCD unexpectedly low!\n", dev->name);
+ netdev_info(dev, "Modem DCD unexpectedly low!\n");
if (*state & SDLA_MODEM_CTS_LOW)
- printk(KERN_INFO "%s: Modem CTS unexpectedly low!\n", dev->name);
+ netdev_info(dev, "Modem CTS unexpectedly low!\n");
/* I should probably do something about this! */
break;
case SDLA_RET_CHANNEL_OFF:
- printk(KERN_INFO "%s: Channel became inoperative!\n", dev->name);
+ netdev_info(dev, "Channel became inoperative!\n");
/* same here */
break;
case SDLA_RET_CHANNEL_ON:
- printk(KERN_INFO "%s: Channel became operative!\n", dev->name);
+ netdev_info(dev, "Channel became operative!\n");
/* same here */
break;
case SDLA_RET_DLCI_STATUS:
- printk(KERN_INFO "%s: Status change reported by Access Node.\n", dev->name);
+ netdev_info(dev, "Status change reported by Access Node\n");
len /= sizeof(struct _dlci_stat);
for(pstatus = data, i=0;i < len;i++,pstatus++)
{
@@ -382,29 +384,32 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
sprintf(line, "unknown status: %02X", pstatus->flags);
state = line;
}
- printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
+ netdev_info(dev, "DLCI %i: %s\n",
+ pstatus->dlci, state);
/* same here */
}
break;
case SDLA_RET_DLCI_UNKNOWN:
- printk(KERN_INFO "%s: Received unknown DLCIs:", dev->name);
+ netdev_info(dev, "Received unknown DLCIs:");
len /= sizeof(short);
for(pdlci = data,i=0;i < len;i++,pdlci++)
- printk(" %i", *pdlci);
- printk("\n");
+ pr_cont(" %i", *pdlci);
+ pr_cont("\n");
break;
case SDLA_RET_TIMEOUT:
- printk(KERN_ERR "%s: Command timed out!\n", dev->name);
+ netdev_err(dev, "Command timed out!\n");
break;
case SDLA_RET_BUF_OVERSIZE:
- printk(KERN_INFO "%s: Bc/CIR overflow, acceptable size is %i\n", dev->name, len);
+ netdev_info(dev, "Bc/CIR overflow, acceptable size is %i\n",
+ len);
break;
case SDLA_RET_BUF_TOO_BIG:
- printk(KERN_INFO "%s: Buffer size over specified max of %i\n", dev->name, len);
+ netdev_info(dev, "Buffer size over specified max of %i\n",
+ len);
break;
case SDLA_RET_CHANNEL_INACTIVE:
@@ -415,7 +420,8 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
break;
default:
- printk(KERN_DEBUG "%s: Cmd 0x%2.2X generated return code 0x%2.2X\n", dev->name, cmd, ret);
+ netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n",
+ cmd, ret);
/* Further processing could be done here */
break;
}
@@ -678,12 +684,14 @@ static netdev_tx_t sdla_transmit(struct sk_buff *skb,
case ARPHRD_FRAD:
if (skb->dev->type != ARPHRD_DLCI)
{
- printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
+ netdev_warn(dev, "Non DLCI device, type %i, tried to send on FRAD module\n",
+ skb->dev->type);
accept = 0;
}
break;
default:
- printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
+ netdev_warn(dev, "unknown firmware type 0x%04X\n",
+ dev->type);
accept = 0;
break;
}
@@ -807,7 +815,8 @@ static void sdla_receive(struct net_device *dev)
if (i == CONFIG_DLCI_MAX)
{
- printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci);
+ netdev_notice(dev, "Received packet from invalid DLCI %i, ignoring\n",
+ dlci);
dev->stats.rx_errors++;
success = 0;
}
@@ -819,7 +828,7 @@ static void sdla_receive(struct net_device *dev)
skb = dev_alloc_skb(len + sizeof(struct frhdr));
if (skb == NULL)
{
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+ netdev_notice(dev, "Memory squeeze, dropping packet\n");
dev->stats.rx_dropped++;
success = 0;
}
@@ -880,8 +889,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id)
if (!flp->initialized)
{
- printk(KERN_WARNING "%s: irq %d for uninitialized device.\n",
- dev->name, dev->irq);
+ netdev_warn(dev, "irq %d for uninitialized device\n", dev->irq);
return IRQ_NONE;
}
@@ -901,7 +909,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id)
case SDLA_INTR_TX:
case SDLA_INTR_COMPLETE:
case SDLA_INTR_TIMER:
- printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte);
+ netdev_warn(dev, "invalid irq flag 0x%02X\n", byte);
break;
}
@@ -1347,7 +1355,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
return -EINVAL;
if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
- printk(KERN_WARNING "SDLA: io-port 0x%04lx in use\n", dev->base_addr);
+ pr_warn("io-port 0x%04lx in use\n", dev->base_addr);
return -EINVAL;
}
base = map->base_addr;
@@ -1412,7 +1420,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
}
}
- printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
+ netdev_notice(dev, "Unknown card type\n");
err = -ENODEV;
goto fail;
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index e91457d6023e..0b4fd05e1508 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -12,6 +12,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -190,7 +192,7 @@ static int slvl_setup(struct slvl_device *sv, int iobase, int irq)
dev->irq = irq;
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "sealevel: unable to register HDLC device\n");
+ pr_err("unable to register HDLC device\n");
free_netdev(dev);
return -1;
}
@@ -215,8 +217,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
*/
if (!request_region(iobase, 8, "Sealevel 4021")) {
- printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n",
- iobase);
+ pr_warn("I/O 0x%X already in use\n", iobase);
return NULL;
}
@@ -267,7 +268,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
"SeaLevel", dev) < 0) {
- printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq);
+ pr_warn("IRQ %d already in use\n", irq);
goto err_request_irq;
}
@@ -292,7 +293,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
*/
if (z8530_init(dev) != 0) {
- printk(KERN_ERR "Z8530 series device not found.\n");
+ pr_err("Z8530 series device not found\n");
enable_irq(irq);
goto free_hw;
}
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index db73a7be199f..44b707197258 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -13,6 +13,8 @@
* - wanXL100 will require minor driver modifications, no access to hw
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -22,6 +24,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/hdlc.h>
@@ -101,9 +104,8 @@ static inline dma_addr_t pci_map_single_debug(struct pci_dev *pdev, void *ptr,
{
dma_addr_t addr = pci_map_single(pdev, ptr, size, direction);
if (addr + size > 0x100000000LL)
- printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory"
- " at 0x%LX!\n", pci_name(pdev),
- (unsigned long long)addr);
+ pr_crit("%s: pci_map_single() returned memory at 0x%llx!\n",
+ pci_name(pdev), (unsigned long long)addr);
return addr;
}
@@ -146,8 +148,8 @@ static inline void wanxl_cable_intr(port_t *port)
}
dte = (value & STATUS_CABLE_DCE) ? " DCE" : " DTE";
}
- printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n",
- port->dev->name, pm, dte, cable, dsr, dcd);
+ netdev_info(port->dev, "%s%s module, %s cable%s%s\n",
+ pm, dte, cable, dsr, dcd);
if (value & STATUS_CABLE_DCD)
netif_carrier_on(port->dev);
@@ -197,8 +199,8 @@ static inline void wanxl_rx_intr(card_t *card)
while (desc = &card->status->rx_descs[card->rx_in],
desc->stat != PACKET_EMPTY) {
if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
- printk(KERN_CRIT "wanXL %s: received packet for"
- " nonexistent port\n", pci_name(card->pdev));
+ pr_crit("%s: received packet for nonexistent port\n",
+ pci_name(card->pdev));
else {
struct sk_buff *skb = card->rx_skbs[card->rx_in];
port_t *port = &card->ports[desc->stat &
@@ -282,7 +284,7 @@ static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name);
#endif
netif_stop_queue(dev);
- spin_unlock_irq(&port->lock);
+ spin_unlock(&port->lock);
return NETDEV_TX_BUSY; /* request packet to be queued */
}
@@ -396,7 +398,7 @@ static int wanxl_open(struct net_device *dev)
int i;
if (get_status(port)->open) {
- printk(KERN_ERR "%s: port already open\n", dev->name);
+ netdev_err(dev, "port already open\n");
return -EIO;
}
if ((i = hdlc_open(dev)) != 0)
@@ -416,7 +418,7 @@ static int wanxl_open(struct net_device *dev)
}
} while (time_after(timeout, jiffies));
- printk(KERN_ERR "%s: unable to open port\n", dev->name);
+ netdev_err(dev, "unable to open port\n");
/* ask the card to close the port, should it be still alive */
writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), dbr);
return -EFAULT;
@@ -442,7 +444,7 @@ static int wanxl_close(struct net_device *dev)
} while (time_after(timeout, jiffies));
if (get_status(port)->open)
- printk(KERN_ERR "%s: unable to close port\n", dev->name);
+ netdev_err(dev, "unable to close port\n");
netif_stop_queue(dev);
@@ -567,11 +569,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
int i, ports, alloc_size;
#ifndef MODULE
- static int printed_version;
- if (!printed_version) {
- printed_version++;
- printk(KERN_INFO "%s\n", version);
- }
+ pr_info_once("%s\n", version);
#endif
i = pci_enable_device(pdev);
@@ -587,7 +585,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
work on most platforms */
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(28)) ||
pci_set_dma_mask(pdev, DMA_BIT_MASK(28))) {
- printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+ pr_err("No usable DMA configuration\n");
return -EIO;
}
@@ -606,8 +604,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
alloc_size = sizeof(card_t) + ports * sizeof(port_t);
card = kzalloc(alloc_size, GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
- pci_name(pdev));
+ pr_err("%s: unable to allocate memory\n", pci_name(pdev));
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -634,7 +631,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
to indicate the card can do 32-bit DMA addressing */
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) ||
pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
- printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+ pr_err("No usable DMA configuration\n");
wanxl_pci_remove_one(pdev);
return -EIO;
}
@@ -644,7 +641,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
card->plx = ioremap_nocache(plx_phy, 0x70);
if (!card->plx) {
- printk(KERN_ERR "wanxl: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
wanxl_pci_remove_one(pdev);
return -EFAULT;
}
@@ -656,8 +653,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
timeout = jiffies + 20 * HZ;
while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) {
if (time_before(timeout, jiffies)) {
- printk(KERN_WARNING "wanXL %s: timeout waiting for"
- " PUTS to complete\n", pci_name(pdev));
+ pr_warn("%s: timeout waiting for PUTS to complete\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -668,8 +665,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
break;
default:
- printk(KERN_WARNING "wanXL %s: PUTS test 0x%X"
- " failed\n", pci_name(pdev), stat & 0x30);
+ pr_warn("%s: PUTS test 0x%X failed\n",
+ pci_name(pdev), stat & 0x30);
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -687,17 +684,16 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
/* sanity check the board's reported memory size */
if (ramsize < BUFFERS_ADDR +
(TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) {
- printk(KERN_WARNING "wanXL %s: no enough on-board RAM"
- " (%u bytes detected, %u bytes required)\n",
- pci_name(pdev), ramsize, BUFFERS_ADDR +
- (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
+ pr_warn("%s: no enough on-board RAM (%u bytes detected, %u bytes required)\n",
+ pci_name(pdev), ramsize,
+ BUFFERS_ADDR +
+ (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) {
- printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap"
- " Mode\n", pci_name(pdev));
+ pr_warn("%s: unable to Set Byte Swap Mode\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -714,7 +710,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware));
if (!mem) {
- printk(KERN_ERR "wanxl: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
wanxl_pci_remove_one(pdev);
return -EFAULT;
}
@@ -733,8 +729,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
writel(0, card->plx + PLX_MAILBOX_5);
if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) {
- printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n",
- pci_name(pdev));
+ pr_warn("%s: unable to Abort and Jump\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -748,8 +743,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
}while (time_after(timeout, jiffies));
if (!stat) {
- printk(KERN_WARNING "wanXL %s: timeout while initializing card "
- "firmware\n", pci_name(pdev));
+ pr_warn("%s: timeout while initializing card firmware\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -758,13 +753,13 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
ramsize = stat;
#endif
- printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
- pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
+ pr_info("%s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
+ pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
/* Allocate IRQ */
if (request_irq(pdev->irq, wanxl_intr, IRQF_SHARED, "wanXL", card)) {
- printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n",
- pci_name(pdev), pdev->irq);
+ pr_warn("%s: could not allocate IRQ%i\n",
+ pci_name(pdev), pdev->irq);
wanxl_pci_remove_one(pdev);
return -EBUSY;
}
@@ -775,8 +770,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
port_t *port = &card->ports[i];
struct net_device *dev = alloc_hdlcdev(port);
if (!dev) {
- printk(KERN_ERR "wanXL %s: unable to allocate"
- " memory\n", pci_name(pdev));
+ pr_err("%s: unable to allocate memory\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -792,8 +787,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
port->node = i;
get_status(port)->clocking = CLOCK_EXT;
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "wanXL %s: unable to register hdlc"
- " device\n", pci_name(pdev));
+ pr_err("%s: unable to register hdlc device\n",
+ pci_name(pdev));
free_netdev(dev);
wanxl_pci_remove_one(pdev);
return -ENOBUFS;
@@ -801,11 +796,11 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
card->n_ports++;
}
- printk(KERN_INFO "wanXL %s: port", pci_name(pdev));
+ pr_info("%s: port", pci_name(pdev));
for (i = 0; i < ports; i++)
- printk("%s #%i: %s", i ? "," : "", i,
- card->ports[i].dev->name);
- printk("\n");
+ pr_cont("%s #%i: %s",
+ i ? "," : "", i, card->ports[i].dev->name);
+ pr_cont("\n");
for (i = 0; i < ports; i++)
wanxl_cable_intr(&card->ports[i]); /* get carrier status etc.*/
@@ -835,7 +830,7 @@ static struct pci_driver wanxl_pci_driver = {
static int __init wanxl_init_module(void)
{
#ifdef MODULE
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
#endif
return pci_register_driver(&wanxl_pci_driver);
}
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 24297b274cd4..46ceb3ae9073 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -14,6 +14,8 @@
* 2000-10-29 Henner Eisen lapb_data_indication() return status.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <asm/system.h>
@@ -96,7 +98,7 @@ static struct x25_asy *x25_asy_alloc(void)
x25_asy_devs[i] = dev;
return sl;
} else {
- printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
+ pr_warn("%s(): register_netdev() failure\n", __func__);
free_netdev(dev);
}
}
@@ -114,8 +116,7 @@ static void x25_asy_free(struct x25_asy *sl)
sl->xbuff = NULL;
if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
- printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
- sl->dev->name);
+ netdev_err(sl->dev, "x25_asy_free for already free unit\n");
}
static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
@@ -128,8 +129,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL) {
- printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
- dev->name);
+ netdev_warn(dev, "unable to grow X.25 buffers, MTU change cancelled\n");
kfree(xbuff);
kfree(rbuff);
return -ENOMEM;
@@ -198,8 +198,7 @@ static void x25_asy_bump(struct x25_asy *sl)
skb = dev_alloc_skb(count+1);
if (skb == NULL) {
- printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
- sl->dev->name);
+ netdev_warn(sl->dev, "memory squeeze, dropping packet\n");
dev->stats.rx_dropped++;
return;
}
@@ -287,9 +286,9 @@ static void x25_asy_timeout(struct net_device *dev)
/* May be we must check transmitter timeout here ?
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
- (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
- "bad line quality" : "driver error");
+ netdev_warn(dev, "transmit timed out, %s?\n",
+ (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
+ "bad line quality" : "driver error");
sl->xleft = 0;
clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
x25_asy_unlock(sl);
@@ -306,8 +305,7 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
int err;
if (!netif_running(sl->dev)) {
- printk(KERN_ERR "%s: xmit call when iface is down\n",
- dev->name);
+ netdev_err(dev, "xmit call when iface is down\n");
kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -318,13 +316,15 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
case X25_IFACE_CONNECT: /* Connection request .. do nothing */
err = lapb_connect_request(dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
+ netdev_err(dev, "lapb_connect_request error: %d\n",
+ err);
kfree_skb(skb);
return NETDEV_TX_OK;
case X25_IFACE_DISCONNECT: /* do nothing - hang up ?? */
err = lapb_disconnect_request(dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
+ netdev_err(dev, "lapb_disconnect_request error: %d\n",
+ err);
default:
kfree_skb(skb);
return NETDEV_TX_OK;
@@ -343,7 +343,7 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
err = lapb_data_request(dev, skb);
if (err != LAPB_OK) {
- printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
+ netdev_err(dev, "lapb_data_request error: %d\n", err);
kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -378,7 +378,7 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
spin_lock(&sl->lock);
if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
spin_unlock(&sl->lock);
- printk(KERN_ERR "x25_asy: tbusy drop\n");
+ netdev_err(dev, "tbusy drop\n");
kfree_skb(skb);
return;
}
@@ -404,7 +404,7 @@ static void x25_asy_connected(struct net_device *dev, int reason)
skb = dev_alloc_skb(1);
if (skb == NULL) {
- printk(KERN_ERR "x25_asy: out of memory\n");
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -423,7 +423,7 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
skb = dev_alloc_skb(1);
if (skb == NULL) {
- printk(KERN_ERR "x25_asy: out of memory\n");
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -603,8 +603,8 @@ static void x25_asy_close_tty(struct tty_struct *tty)
err = lapb_unregister(sl->dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
- err);
+ pr_err("x25_asy_close: lapb_unregister error: %d\n",
+ err);
tty->disc_data = NULL;
sl->tty = NULL;
@@ -782,14 +782,13 @@ static int __init init_x25_asy(void)
if (x25_asy_maxdev < 4)
x25_asy_maxdev = 4; /* Sanity */
- printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
- "(dynamic channels, max=%d).\n", x25_asy_maxdev);
+ pr_info("X.25 async: version 0.00 ALPHA (dynamic channels, max=%d)\n",
+ x25_asy_maxdev);
x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
GFP_KERNEL);
if (!x25_asy_devs) {
- printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
- "array! Uaargh! (-> No X.25 available)\n");
+ pr_warn("Can't allocate x25_asy_ctrls[] array! Uaargh! (-> No X.25 available)\n");
return -ENOMEM;
}
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 0806232e0f8f..0e5769061702 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -36,6 +36,8 @@
* Synchronous mode without DMA is unlikely to pass about 2400 baud.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -365,7 +367,7 @@ static void z8530_rx(struct z8530_channel *c)
c->count=0;
if(stat&Rx_OVR)
{
- printk(KERN_WARNING "%s: overrun\n", c->dev->name);
+ pr_warn("%s: overrun\n", c->dev->name);
c->rx_overrun++;
}
if(stat&CRC_ERR)
@@ -464,12 +466,12 @@ static void z8530_status(struct z8530_channel *chan)
if (altered & chan->dcdcheck)
{
if (status & chan->dcdcheck) {
- printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+ pr_info("%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
if (chan->netdevice)
netif_carrier_on(chan->netdevice);
} else {
- printk(KERN_INFO "%s: DCD lost\n", chan->dev->name);
+ pr_info("%s: DCD lost\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
z8530_flush_fifo(chan);
if (chan->netdevice)
@@ -538,12 +540,12 @@ static void z8530_dma_tx(struct z8530_channel *chan)
{
if(!chan->dma_tx)
{
- printk(KERN_WARNING "Hey who turned the DMA off?\n");
+ pr_warn("Hey who turned the DMA off?\n");
z8530_tx(chan);
return;
}
/* This shouldn't occur in DMA mode */
- printk(KERN_ERR "DMA tx - bogus event!\n");
+ pr_err("DMA tx - bogus event!\n");
z8530_tx(chan);
}
@@ -585,12 +587,12 @@ static void z8530_dma_status(struct z8530_channel *chan)
if (altered & chan->dcdcheck)
{
if (status & chan->dcdcheck) {
- printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+ pr_info("%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
if (chan->netdevice)
netif_carrier_on(chan->netdevice);
} else {
- printk(KERN_INFO "%s:DCD lost\n", chan->dev->name);
+ pr_info("%s: DCD lost\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
z8530_flush_fifo(chan);
if (chan->netdevice)
@@ -712,7 +714,7 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id)
if(locker)
{
- printk(KERN_ERR "IRQ re-enter\n");
+ pr_err("IRQ re-enter\n");
return IRQ_NONE;
}
locker=1;
@@ -758,7 +760,8 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id)
}
spin_unlock(&dev->lock);
if(work==5000)
- printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr);
+ pr_err("%s: interrupt jammed - abort(0x%X)!\n",
+ dev->name, intr);
/* Ok all done */
locker=0;
return IRQ_HANDLED;
@@ -1225,7 +1228,7 @@ static const char *z8530_type_name[]={
void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io)
{
- printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n",
+ pr_info("%s: %s found at %s 0x%lX, IRQ %d\n",
dev->name,
z8530_type_name[dev->type],
mapping,
@@ -1621,8 +1624,7 @@ static void z8530_rx_done(struct z8530_channel *c)
else
/* Can't occur as we dont reenable the DMA irq until
after the flip is done */
- printk(KERN_WARNING "%s: DMA flip overrun!\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "DMA flip overrun!\n");
release_dma_lock(flags);
@@ -1637,8 +1639,7 @@ static void z8530_rx_done(struct z8530_channel *c)
skb = dev_alloc_skb(ct);
if (skb == NULL) {
c->netdevice->stats.rx_dropped++;
- printk(KERN_WARNING "%s: Memory squeeze.\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "Memory squeeze\n");
} else {
skb_put(skb, ct);
skb_copy_to_linear_data(skb, rxb, ct);
@@ -1678,8 +1679,7 @@ static void z8530_rx_done(struct z8530_channel *c)
c->skb2 = dev_alloc_skb(c->mtu);
if (c->skb2 == NULL)
- printk(KERN_WARNING "%s: memory squeeze.\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "memory squeeze\n");
else
skb_put(c->skb2, c->mtu);
c->netdevice->stats.rx_packets++;
@@ -1693,7 +1693,7 @@ static void z8530_rx_done(struct z8530_channel *c)
c->rx_function(c, skb);
} else {
c->netdevice->stats.rx_dropped++;
- printk(KERN_ERR "%s: Lost a frame\n", c->netdevice->name);
+ netdev_err(c->netdevice, "Lost a frame\n");
}
}
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 5eacc653a94d..c421a6141854 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -155,7 +155,7 @@
#include <linux/netdevice.h>
#include <linux/completion.h>
#include <linux/rwsem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <net/wimax.h>
#include <linux/wimax/i2400m.h>
#include <asm/byteorder.h>
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index afe2cbc6cb24..43ebc44fc82c 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -16,6 +16,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/if.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 7cf4317a2a84..17c4b56c3874 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -161,6 +161,7 @@ struct ath_common {
const struct ath_bus_ops *bus_ops;
bool btcoex_enabled;
+ bool disable_ani;
};
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index ea9982781559..a2a167363dbf 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -24,7 +24,6 @@
#include "debug.h"
#include "base.h"
#include "reg.h"
-#include "debug.h"
/* return bus cachesize in 4B word units */
static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
@@ -35,8 +34,8 @@ static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
static bool
ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
- struct ath5k_softc *sc = common->priv;
- struct platform_device *pdev = to_platform_device(sc->dev);
+ struct ath5k_hw *ah = common->priv;
+ struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
u16 *eeprom, *eeprom_end;
@@ -56,8 +55,7 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
int ath5k_hw_read_srev(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
- struct platform_device *pdev = to_platform_device(sc->dev);
+ struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
ah->ah_mac_srev = bcfg->devid;
return 0;
@@ -65,12 +63,11 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
{
- struct ath5k_softc *sc = ah->ah_sc;
- struct platform_device *pdev = to_platform_device(sc->dev);
+ struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
u8 *cfg_mac;
- if (to_platform_device(sc->dev)->id == 0)
+ if (to_platform_device(ah->dev)->id == 0)
cfg_mac = bcfg->config->wlan0_mac;
else
cfg_mac = bcfg->config->wlan1_mac;
@@ -90,7 +87,7 @@ static const struct ath_bus_ops ath_ahb_bus_ops = {
static int ath_ahb_probe(struct platform_device *pdev)
{
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
- struct ath5k_softc *sc;
+ struct ath5k_hw *ah;
struct ieee80211_hw *hw;
struct resource *res;
void __iomem *mem;
@@ -127,19 +124,19 @@ static int ath_ahb_probe(struct platform_device *pdev)
irq = res->start;
- hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops);
+ hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
if (hw == NULL) {
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
ret = -ENOMEM;
goto err_out;
}
- sc = hw->priv;
- sc->hw = hw;
- sc->dev = &pdev->dev;
- sc->iobase = mem;
- sc->irq = irq;
- sc->devid = bcfg->devid;
+ ah = hw->priv;
+ ah->hw = hw;
+ ah->dev = &pdev->dev;
+ ah->iobase = mem;
+ ah->irq = irq;
+ ah->devid = bcfg->devid;
if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
/* Enable WMAC AHB arbitration */
@@ -155,7 +152,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
/* Enable WMAC DMA access (assuming 5312 or 231x*/
/* TODO: check other platforms */
reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
- if (to_platform_device(sc->dev)->id == 0)
+ if (to_platform_device(ah->dev)->id == 0)
reg |= AR5K_AR5312_ENABLE_WLAN0;
else
reg |= AR5K_AR5312_ENABLE_WLAN1;
@@ -166,13 +163,13 @@ static int ath_ahb_probe(struct platform_device *pdev)
* used as pass-through. Disable 2 GHz support in the
* driver for it
*/
- if (to_platform_device(sc->dev)->id == 0 &&
- (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) ==
- (BD_WLAN1|BD_WLAN0))
- __set_bit(ATH_STAT_2G_DISABLED, sc->status);
+ if (to_platform_device(ah->dev)->id == 0 &&
+ (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
+ (BD_WLAN1 | BD_WLAN0))
+ __set_bit(ATH_STAT_2G_DISABLED, ah->status);
}
- ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
+ ret = ath5k_init_softc(ah, &ath_ahb_bus_ops);
if (ret != 0) {
dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
ret = -ENODEV;
@@ -194,13 +191,13 @@ static int ath_ahb_remove(struct platform_device *pdev)
{
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
- struct ath5k_softc *sc;
+ struct ath5k_hw *ah;
u32 reg;
if (!hw)
return 0;
- sc = hw->priv;
+ ah = hw->priv;
if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
/* Disable WMAC AHB arbitration */
@@ -210,15 +207,16 @@ static int ath_ahb_remove(struct platform_device *pdev)
} else {
/*Stop DMA access */
reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
- if (to_platform_device(sc->dev)->id == 0)
+ if (to_platform_device(ah->dev)->id == 0)
reg &= ~AR5K_AR5312_ENABLE_WLAN0;
else
reg &= ~AR5K_AR5312_ENABLE_WLAN1;
__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
}
- ath5k_deinit_softc(sc);
+ ath5k_deinit_softc(ah);
platform_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(hw);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index f915f404302d..603ae15f139b 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -74,7 +74,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
static const s8 fr[] = { -78, -80 };
#endif
if (level < 0 || level >= ARRAY_SIZE(sz)) {
- ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range",
+ ATH5K_ERR(ah, "noise immunity level %d out of range",
level);
return;
}
@@ -88,8 +88,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG,
AR5K_PHY_SIG_FIRPWR, fr[level]);
- ah->ah_sc->ani_state.noise_imm_level = level;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+ ah->ani_state.noise_imm_level = level;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
}
@@ -105,8 +105,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
if (level < 0 || level >= ARRAY_SIZE(val) ||
- level > ah->ah_sc->ani_state.max_spur_level) {
- ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range",
+ level > ah->ani_state.max_spur_level) {
+ ATH5K_ERR(ah, "spur immunity level %d out of range",
level);
return;
}
@@ -114,8 +114,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]);
- ah->ah_sc->ani_state.spur_level = level;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+ ah->ani_state.spur_level = level;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
}
@@ -130,15 +130,15 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
static const int val[] = { 0, 4, 8 };
if (level < 0 || level >= ARRAY_SIZE(val)) {
- ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level);
+ ATH5K_ERR(ah, "firstep level %d out of range", level);
return;
}
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG,
AR5K_PHY_SIG_FIRSTEP, val[level]);
- ah->ah_sc->ani_state.firstep_level = level;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+ ah->ani_state.firstep_level = level;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
}
@@ -178,8 +178,8 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on)
AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR,
AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN);
- ah->ah_sc->ani_state.ofdm_weak_sig = on;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s",
+ ah->ani_state.ofdm_weak_sig = on;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s",
on ? "on" : "off");
}
@@ -195,8 +195,8 @@ ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on)
static const int val[] = { 8, 6 };
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR,
AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]);
- ah->ah_sc->ani_state.cck_weak_sig = on;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s",
+ ah->ani_state.cck_weak_sig = on;
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s",
on ? "on" : "off");
}
@@ -218,7 +218,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
{
int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)",
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "raise immunity (%s)",
ofdm_trigger ? "ODFM" : "CCK");
/* first: raise noise immunity */
@@ -229,13 +229,13 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
/* only OFDM: raise spur immunity level */
if (ofdm_trigger &&
- as->spur_level < ah->ah_sc->ani_state.max_spur_level) {
+ as->spur_level < ah->ani_state.max_spur_level) {
ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1);
return;
}
/* AP mode */
- if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) {
+ if (ah->opmode == NL80211_IFTYPE_AP) {
if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL)
ath5k_ani_set_firstep_level(ah, as->firstep_level + 1);
return;
@@ -248,7 +248,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
* don't shut out a remote node by raising immunity too high. */
if (rssi > ATH5K_ANI_RSSI_THR_HIGH) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"beacon RSSI high");
/* only OFDM: beacon RSSI is high, we can disable ODFM weak
* signal detection */
@@ -265,7 +265,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
} else if (rssi > ATH5K_ANI_RSSI_THR_LOW) {
/* beacon RSSI in mid range, we need OFDM weak signal detect,
* but can raise firstep level */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"beacon RSSI mid");
if (ofdm_trigger && as->ofdm_weak_sig == false)
ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
@@ -275,7 +275,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
} else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) {
/* beacon RSSI is low. in B/G mode turn of OFDM weak signal
* detect and zero firstep level to maximize CCK sensitivity */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"beacon RSSI low, 2GHz");
if (ofdm_trigger && as->ofdm_weak_sig == true)
ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
@@ -303,9 +303,9 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
{
int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity");
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "lower immunity");
- if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) {
+ if (ah->opmode == NL80211_IFTYPE_AP) {
/* AP mode */
if (as->firstep_level > 0) {
ath5k_ani_set_firstep_level(ah, as->firstep_level - 1);
@@ -464,7 +464,7 @@ ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as)
void
ath5k_ani_calibration(struct ath5k_hw *ah)
{
- struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+ struct ath5k_ani_state *as = &ah->ani_state;
int listen, ofdm_high, ofdm_low, cck_high, cck_low;
/* get listen time since last call and add it to the counter because we
@@ -483,9 +483,9 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000;
cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000;
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"listen %d (now %d)", as->listen_time, listen);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"check high ofdm %d/%d cck %d/%d",
as->ofdm_errors, ofdm_high, as->cck_errors, cck_high);
@@ -498,7 +498,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
} else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) {
/* If more than 5 (TODO: why 5?) periods have passed and we got
* relatively little errors we can try to lower immunity */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"check low ofdm %d/%d cck %d/%d",
as->ofdm_errors, ofdm_low, as->cck_errors, cck_low);
@@ -525,7 +525,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
void
ath5k_ani_mib_intr(struct ath5k_hw *ah)
{
- struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+ struct ath5k_ani_state *as = &ah->ani_state;
/* nothing to do here if HW does not have PHY error counters - they
* can't be the reason for the MIB interrupt then */
@@ -536,7 +536,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT);
ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT);
- if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
+ if (ah->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
return;
/* If one of the errors triggered, we can get a superfluous second
@@ -547,7 +547,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH ||
as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
}
@@ -561,16 +561,16 @@ void
ath5k_ani_phy_error_report(struct ath5k_hw *ah,
enum ath5k_phy_error_code phyerr)
{
- struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+ struct ath5k_ani_state *as = &ah->ani_state;
if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) {
as->ofdm_errors++;
if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH)
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
} else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) {
as->cck_errors++;
if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
}
}
@@ -630,20 +630,25 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
if (ah->ah_version < AR5K_AR5212)
return;
+ if (mode < ATH5K_ANI_MODE_OFF || mode > ATH5K_ANI_MODE_AUTO) {
+ ATH5K_ERR(ah, "ANI mode %d out of range", mode);
+ return;
+ }
+
/* clear old state information */
- memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state));
+ memset(&ah->ani_state, 0, sizeof(ah->ani_state));
/* older hardware has more spur levels than newer */
if (ah->ah_mac_srev < AR5K_SREV_AR2414)
- ah->ah_sc->ani_state.max_spur_level = 7;
+ ah->ani_state.max_spur_level = 7;
else
- ah->ah_sc->ani_state.max_spur_level = 2;
+ ah->ani_state.max_spur_level = 2;
/* initial values for our ani parameters */
if (mode == ATH5K_ANI_MODE_OFF) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n");
- } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI off\n");
+ } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) {
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"ANI manual low -> high sensitivity\n");
ath5k_ani_set_noise_immunity_level(ah, 0);
ath5k_ani_set_spur_immunity_level(ah, 0);
@@ -651,17 +656,17 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
ath5k_ani_set_cck_weak_signal_detection(ah, true);
} else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
"ANI manual high -> low sensitivity\n");
ath5k_ani_set_noise_immunity_level(ah,
ATH5K_ANI_MAX_NOISE_IMM_LVL);
ath5k_ani_set_spur_immunity_level(ah,
- ah->ah_sc->ani_state.max_spur_level);
+ ah->ani_state.max_spur_level);
ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
ath5k_ani_set_cck_weak_signal_detection(ah, false);
} else if (mode == ATH5K_ANI_MODE_AUTO) {
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n");
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI auto\n");
ath5k_ani_set_noise_immunity_level(ah, 0);
ath5k_ani_set_spur_immunity_level(ah, 0);
ath5k_ani_set_firstep_level(ah, 0);
@@ -687,7 +692,7 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
~AR5K_RX_FILTER_PHYERR);
}
- ah->ah_sc->ani_state.ani_mode = mode;
+ ah->ani_state.ani_mode = mode;
}
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index bb50700436fe..277d5cbe0068 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -18,14 +18,16 @@
#ifndef _ATH5K_H
#define _ATH5K_H
-/* TODO: Clean up channel debuging -doesn't work anyway- and start
+/* TODO: Clean up channel debugging (doesn't work anyway) and start
* working on reg. control code using all available eeprom information
- * -rev. engineering needed- */
+ * (rev. engineering needed) */
#define CHAN_DEBUG 0
#include <linux/io.h>
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/average.h>
+#include <linux/leds.h>
#include <net/mac80211.h>
/* RX/TX descriptor hw structs
@@ -36,43 +38,46 @@
* TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
* and clean up common bits, then introduce set/get functions in eeprom.c */
#include "eeprom.h"
+#include "debug.h"
#include "../ath.h"
+#include "ani.h"
/* PCI IDs */
-#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
-#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
-#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
-#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
-#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
-#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
+#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
+#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
+#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
+#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
-#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
-#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
-#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
-#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
+#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
+#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
+#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
+#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
/****************************\
GENERIC DRIVER DEFINITIONS
\****************************/
-#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__)
+#define ATH5K_PRINTF(fmt, ...) \
+ printk(KERN_WARNING "%s: " fmt, __func__, ##__VA_ARGS__)
#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
printk(_level "ath5k %s: " _fmt, \
@@ -155,7 +160,7 @@
} while (0)
/*
- * Some tuneable values (these should be changeable by the user)
+ * Some tunable values (these should be changeable by the user)
* TODO: Make use of them and add more options OR use debug/configfs
*/
#define AR5K_TUNE_DMA_BEACON_RESP 2
@@ -170,8 +175,8 @@
#define AR5K_TUNE_RSSI_THRES 129
/* This must be set when setting the RSSI threshold otherwise it can
* prevent a reset. If AR5K_RSSI_THR is read after writing to it
- * the BMISS_THRES will be seen as 0, seems harware doesn't keep
- * track of it. Max value depends on harware. For AR5210 this is just 7.
+ * the BMISS_THRES will be seen as 0, seems hardware doesn't keep
+ * track of it. Max value depends on hardware. For AR5210 this is just 7.
* For AR5211+ this seems to be up to 255. */
#define AR5K_TUNE_BMISS_THRES 7
#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
@@ -361,7 +366,7 @@ struct ath5k_srev_name {
/*
* Some of this information is based on Documentation from:
*
- * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG
+ * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG
*
* Modulation for Atheros' eXtended Range - range enhancing extension that is
* supposed to double the distance an Atheros client device can keep a
@@ -374,12 +379,12 @@ struct ath5k_srev_name {
* they are exclusive.
*
*/
-#define MODULATION_XR 0x00000200
+#define MODULATION_XR 0x00000200
/*
* Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
* throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
* signaling rate achieved through the bonding of two 54Mbit/s 802.11g
- * channels. To use this feature your Access Point must also suport it.
+ * channels. To use this feature your Access Point must also support it.
* There is also a distinction between "static" and "dynamic" turbo modes:
*
* - Static: is the dumb version: devices set to this mode stick to it until
@@ -495,9 +500,9 @@ enum ath5k_tx_queue {
*/
enum ath5k_tx_queue_subtype {
AR5K_WME_AC_BK = 0, /*Background traffic*/
- AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/
- AR5K_WME_AC_VI, /*Video traffic*/
- AR5K_WME_AC_VO, /*Voice traffic*/
+ AR5K_WME_AC_BE, /*Best-effort (normal) traffic*/
+ AR5K_WME_AC_VI, /*Video traffic*/
+ AR5K_WME_AC_VO, /*Voice traffic*/
};
/*
@@ -537,6 +542,27 @@ enum ath5k_tx_queue_id {
#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
/*
+ * Data transmit queue state. One of these exists for each
+ * hardware transmit queue. Packets sent to us from above
+ * are assigned to queues based on their priority. Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+struct ath5k_txq {
+ unsigned int qnum; /* hardware q number */
+ u32 *link; /* link ptr in last TX desc */
+ struct list_head q; /* transmit queue */
+ spinlock_t lock; /* lock on q and link */
+ bool setup;
+ int txq_len; /* number of queued buffers */
+ int txq_max; /* max allowed num of queued buffers */
+ bool txq_poll_mark;
+ unsigned int txq_stuck; /* informational counter */
+};
+
+/*
* A struct to hold tx queue's parameters
*/
struct ath5k_txq_info {
@@ -616,8 +642,8 @@ struct ath5k_rx_status {
#define AR5K_RXERR_FIFO 0x04
#define AR5K_RXERR_DECRYPT 0x08
#define AR5K_RXERR_MIC 0x10
-#define AR5K_RXKEYIX_INVALID ((u8) - 1)
-#define AR5K_TXKEYIX_INVALID ((u32) - 1)
+#define AR5K_RXKEYIX_INVALID ((u8) -1)
+#define AR5K_TXKEYIX_INVALID ((u32) -1)
/**************************\
@@ -678,17 +704,18 @@ struct ath5k_gain {
#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_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_ALL (CHANNEL_OFDM | CHANNEL_CCK | \
+ CHANNEL_2GHZ | CHANNEL_5GHZ)
#define CHANNEL_MODES CHANNEL_ALL
/*
- * Used internaly for reset_tx_queue).
+ * 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)
@@ -710,7 +737,7 @@ struct ath5k_athchan_2ghz {
\******************/
/**
- * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
+ * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32.
*
* The rate code is used to get the RX rate or set the TX rate on the
* hardware descriptors. It is also used for internal modulation control
@@ -767,6 +794,7 @@ struct ath5k_athchan_2ghz {
*/
#define AR5K_KEYCACHE_SIZE 8
+extern int ath5k_modparam_nohwcrypt;
/***********************\
HW RELATED DEFINITIONS
@@ -775,11 +803,11 @@ struct ath5k_athchan_2ghz {
/*
* Misc definitions
*/
-#define AR5K_RSSI_EP_MULTIPLIER (1<<7)
+#define AR5K_RSSI_EP_MULTIPLIER (1 << 7)
#define AR5K_ASSERT_ENTRY(_e, _s) do { \
if (_e >= _s) \
- return (false); \
+ return false; \
} while (0)
/*
@@ -790,52 +818,52 @@ struct ath5k_athchan_2ghz {
* enum ath5k_int - Hardware interrupt masks helpers
*
* @AR5K_INT_RX: mask to identify received frame interrupts, of type
- * AR5K_ISR_RXOK or AR5K_ISR_RXERR
+ * AR5K_ISR_RXOK or AR5K_ISR_RXERR
* @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
* @AR5K_INT_RXNOFRM: No frame received (?)
* @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
- * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
- * LinkPtr is NULL. For more details, refer to:
- * http://www.freepatentsonline.com/20030225739.html
+ * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
+ * LinkPtr is NULL. For more details, refer to:
+ * http://www.freepatentsonline.com/20030225739.html
* @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
- * Note that Rx overrun is not always fatal, on some chips we can continue
- * operation without reseting the card, that's why int_fatal is not
- * common for all chips.
+ * Note that Rx overrun is not always fatal, on some chips we can continue
+ * operation without resetting the card, that's why int_fatal is not
+ * common for all chips.
* @AR5K_INT_TX: mask to identify received frame interrupts, of type
- * AR5K_ISR_TXOK or AR5K_ISR_TXERR
+ * AR5K_ISR_TXOK or AR5K_ISR_TXERR
* @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
* @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
- * We currently do increments on interrupt by
- * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
+ * We currently do increments on interrupt by
+ * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
* @AR5K_INT_MIB: Indicates the either Management Information Base counters or
* one of the PHY error counters reached the maximum value and should be
* read and cleared.
* @AR5K_INT_RXPHY: RX PHY Error
* @AR5K_INT_RXKCM: RX Key cache miss
* @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
- * beacon that must be handled in software. The alternative is if you
- * have VEOL support, in that case you let the hardware deal with things.
+ * beacon that must be handled in software. The alternative is if you
+ * have VEOL support, in that case you let the hardware deal with things.
* @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
- * beacons from the AP have associated with, we should probably try to
- * reassociate. When in IBSS mode this might mean we have not received
- * any beacons from any local stations. Note that every station in an
- * IBSS schedules to send beacons at the Target Beacon Transmission Time
- * (TBTT) with a random backoff.
+ * beacons from the AP have associated with, we should probably try to
+ * reassociate. When in IBSS mode this might mean we have not received
+ * any beacons from any local stations. Note that every station in an
+ * IBSS schedules to send beacons at the Target Beacon Transmission Time
+ * (TBTT) with a random backoff.
* @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
* @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
- * until properly handled
+ * until properly handled
* @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
- * errors. These types of errors we can enable seem to be of type
- * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
+ * errors. These types of errors we can enable seem to be of type
+ * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
* @AR5K_INT_GLOBAL: Used to clear and set the IER
* @AR5K_INT_NOCARD: signals the card has been removed
- * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
- * bit value
+ * @AR5K_INT_COMMON: common interrupts shared among MACs with the same
+ * bit value
*
* These are mapped to take advantage of some common bits
* between the MACs, to be able to set intr properties
* easier. Some of them are not used yet inside hw.c. Most map
- * to the respective hw interrupt value as they are common amogst different
+ * to the respective hw interrupt value as they are common among different
* MACs.
*/
enum ath5k_int {
@@ -944,35 +972,6 @@ enum ath5k_power_mode {
#define AR5K_SOFTLED_ON 0
#define AR5K_SOFTLED_OFF 1
-/*
- * Chipset capabilities -see ath5k_hw_get_capability-
- * get_capability function is not yet fully implemented
- * in ath5k so most of these don't work yet...
- * TODO: Implement these & merge with _TUNE_ stuff above
- */
-enum ath5k_capability_type {
- AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
- AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */
- AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */
- AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */
- AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */
- AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */
- AR5K_CAP_VEOL = 7, /* Supports virtual EOL */
- AR5K_CAP_COMPRESSION = 8, /* Supports compression */
- AR5K_CAP_BURST = 9, /* Supports packet bursting */
- AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */
- AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */
- AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */
- AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */
- AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */
- AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */
- AR5K_CAP_XR = 16, /* Supports XR mode */
- AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */
- AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */
- AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */
- AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
-};
-
/* XXX: we *may* move cap_range stuff to struct wiphy */
struct ath5k_capabilities {
@@ -1009,8 +1008,7 @@ struct ath5k_capabilities {
/* size of noise floor history (keep it a power of two) */
#define ATH5K_NF_CAL_HIST_MAX 8
-struct ath5k_nfcal_hist
-{
+struct ath5k_nfcal_hist {
s16 index; /* current index into nfval */
s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
};
@@ -1025,9 +1023,66 @@ struct ath5k_avg_val {
int avg_weight;
};
-/***************************************\
- HARDWARE ABSTRACTION LAYER STRUCTURE
-\***************************************/
+#define ATH5K_LED_MAX_NAME_LEN 31
+
+/*
+ * State for LED triggers
+ */
+struct ath5k_led {
+ char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */
+ struct ath5k_hw *ah; /* driver state */
+ struct led_classdev led_dev; /* led classdev */
+};
+
+/* Rfkill */
+struct ath5k_rfkill {
+ /* GPIO PIN for rfkill */
+ u16 gpio;
+ /* polarity of rfkill GPIO PIN */
+ bool polarity;
+ /* RFKILL toggle tasklet */
+ struct tasklet_struct toggleq;
+};
+
+/* statistics */
+struct ath5k_statistics {
+ /* antenna use */
+ unsigned int antenna_rx[5]; /* frames count per antenna RX */
+ unsigned int antenna_tx[5]; /* frames count per antenna TX */
+
+ /* frame errors */
+ unsigned int rx_all_count; /* all RX frames, including errors */
+ unsigned int tx_all_count; /* all TX frames, including errors */
+ unsigned int rx_bytes_count; /* all RX bytes, including errored pkts
+ * and the MAC headers for each packet
+ */
+ unsigned int tx_bytes_count; /* all TX bytes, including errored pkts
+ * and the MAC headers and padding for
+ * each packet.
+ */
+ unsigned int rxerr_crc;
+ unsigned int rxerr_phy;
+ unsigned int rxerr_phy_code[32];
+ unsigned int rxerr_fifo;
+ unsigned int rxerr_decrypt;
+ unsigned int rxerr_mic;
+ unsigned int rxerr_proc;
+ unsigned int rxerr_jumbo;
+ unsigned int txerr_retry;
+ unsigned int txerr_fifo;
+ unsigned int txerr_filt;
+
+ /* MIB counters */
+ unsigned int ack_fail;
+ unsigned int rts_fail;
+ unsigned int rts_ok;
+ unsigned int fcs_error;
+ unsigned int beacons;
+
+ unsigned int mib_intr;
+ unsigned int rxorn_intr;
+ unsigned int rxeol_intr;
+};
/*
* Misc defines
@@ -1036,12 +1091,114 @@ struct ath5k_avg_val {
#define AR5K_MAX_GPIO 10
#define AR5K_MAX_RF_BANKS 8
-/* TODO: Clean up and merge with ath5k_softc */
+#if CHAN_DEBUG
+#define ATH_CHAN_MAX (26 + 26 + 26 + 200 + 200)
+#else
+#define ATH_CHAN_MAX (14 + 14 + 14 + 252 + 20)
+#endif
+
+#define ATH_RXBUF 40 /* number of RX buffers */
+#define ATH_TXBUF 200 /* number of TX buffers */
+#define ATH_BCBUF 4 /* number of beacon buffers */
+#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
+#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
+
+/* Driver state associated with an instance of a device */
struct ath5k_hw {
struct ath_common common;
- struct ath5k_softc *ah_sc;
- void __iomem *ah_iobase;
+ struct pci_dev *pdev;
+ struct device *dev; /* for dma mapping */
+ int irq;
+ u16 devid;
+ void __iomem *iobase; /* address of the device */
+ struct mutex lock; /* dev-level lock */
+ struct ieee80211_hw *hw; /* IEEE 802.11 common */
+ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+ struct ieee80211_channel channels[ATH_CHAN_MAX];
+ struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+ s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+ enum nl80211_iftype opmode;
+
+#ifdef CONFIG_ATH5K_DEBUG
+ struct ath5k_dbg_info debug; /* debug info */
+#endif /* CONFIG_ATH5K_DEBUG */
+
+ struct ath5k_buf *bufptr; /* allocated buffer ptr */
+ struct ath5k_desc *desc; /* TX/RX descriptors */
+ dma_addr_t desc_daddr; /* DMA (physical) address */
+ size_t desc_len; /* size of TX/RX descriptors */
+
+ DECLARE_BITMAP(status, 6);
+#define ATH_STAT_INVALID 0 /* disable hardware accesses */
+#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
+#define ATH_STAT_PROMISC 2
+#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
+#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
+#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */
+
+ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
+ struct ieee80211_channel *curchan; /* current h/w channel */
+
+ u16 nvifs;
+
+ enum ath5k_int imask; /* interrupt mask copy */
+
+ spinlock_t irqlock;
+ 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 */
+ led_on; /* pin setting for LED on */
+
+ 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 */
+ struct tasklet_struct rxtq; /* rx intr tasklet */
+ struct ath5k_led rx_led; /* rx led */
+
+ struct list_head txbuf; /* transmit buffer */
+ spinlock_t txbuflock;
+ unsigned int txbuf_len; /* buf count in txbuf list */
+ struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
+ struct tasklet_struct txtq; /* tx intr tasklet */
+ struct ath5k_led tx_led; /* tx led */
+
+ struct ath5k_rfkill rf_kill;
+
+ struct tasklet_struct calib; /* calibration tasklet */
+
+ spinlock_t block; /* protects beacon */
+ struct tasklet_struct beacontq; /* beacon intr tasklet */
+ struct list_head bcbuf; /* beacon buffer */
+ struct ieee80211_vif *bslot[ATH_BCBUF];
+ u16 num_ap_vifs;
+ u16 num_adhoc_vifs;
+ unsigned int bhalq, /* SW q for outgoing beacons */
+ bmisscount, /* missed beacon transmits */
+ bintval, /* beacon interval in TU */
+ bsent;
+ unsigned int nexttbtt; /* next beacon time in TU */
+ struct ath5k_txq *cabq; /* content after beacon */
+
+ int power_level; /* Requested tx power in dBm */
+ bool assoc; /* associate state */
+ bool enable_beacon; /* true if beacons are on */
+
+ struct ath5k_statistics stats;
+
+ struct ath5k_ani_state ani_state;
+ struct tasklet_struct ani_tasklet; /* ANI calibration */
+
+ struct delayed_work tx_complete_work;
+
+ struct survey_info survey; /* collected survey info */
enum ath5k_int ah_imr;
@@ -1065,6 +1222,8 @@ struct ath5k_hw {
u8 ah_retry_long;
u8 ah_retry_short;
+ u32 ah_use_32khz_clock;
+
u8 ah_coverage_class;
bool ah_ack_bitrate_high;
u8 ah_bwmode;
@@ -1168,43 +1327,43 @@ struct ath_bus_ops {
extern const struct ieee80211_ops ath5k_hw_ops;
/* Initialization and detach functions */
-int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops);
-void ath5k_deinit_softc(struct ath5k_softc *sc);
-int ath5k_hw_init(struct ath5k_softc *sc);
+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_softc *sc);
-void ath5k_sysfs_unregister(struct ath5k_softc *sc);
+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 set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath_any_vif_assoc(struct ath5k_softc *sc);
+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_init_hw(struct ath5k_softc *sc);
-int ath5k_stop_hw(struct ath5k_softc *sc);
-void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+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_softc *sc, struct ieee80211_channel *chan);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
+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_softc *sc);
-void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
-void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+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 */
-int ath5k_init_leds(struct ath5k_softc *sc);
-void ath5k_led_enable(struct ath5k_softc *sc);
-void ath5k_led_off(struct ath5k_softc *sc);
-void ath5k_unregister_leds(struct ath5k_softc *sc);
+int ath5k_init_leds(struct ath5k_hw *ah);
+void ath5k_led_enable(struct ath5k_hw *ah);
+void ath5k_led_off(struct ath5k_hw *ah);
+void ath5k_unregister_leds(struct ath5k_hw *ah);
/* Reset Functions */
@@ -1253,7 +1412,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
int len, struct ieee80211_rate *rate, bool shortpre);
unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
-extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
+int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
/* RX filter control*/
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
@@ -1318,9 +1477,6 @@ void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
/* Misc functions TODO: Cleanup */
int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
- enum ath5k_capability_type cap_type, u32 capability,
- u32 *result);
int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
@@ -1356,17 +1512,17 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
u8 mode, bool fast);
/*
- * Functions used internaly
+ * Functions used internally
*/
static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
{
- return &ah->common;
+ return &ah->common;
}
static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
{
- return &(ath5k_hw_common(ah)->regulatory);
+ return &(ath5k_hw_common(ah)->regulatory);
}
#ifdef CONFIG_ATHEROS_AR231X
@@ -1377,10 +1533,10 @@ static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
/* On AR2315 and AR2317 the PCI clock domain registers
* are outside of the WMAC register space */
if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
- (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
+ (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
return AR5K_AR2315_PCI_BASE + reg;
- return ah->ah_iobase + reg;
+ return ah->iobase + reg;
}
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
@@ -1397,12 +1553,12 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{
- return ioread32(ah->ah_iobase + reg);
+ return ioread32(ah->iobase + reg);
}
static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
{
- iowrite32(val, ah->ah_iobase + reg);
+ iowrite32(val, ah->iobase + reg);
}
#endif
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index 1588401de3c4..f8a6b380d96d 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -59,7 +59,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
cur_val = ath5k_hw_reg_read(ah, cur_reg);
if (cur_val != var_pattern) {
- ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+ ATH5K_ERR(ah, "POST Failed !!!\n");
return -EAGAIN;
}
@@ -74,7 +74,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
cur_val = ath5k_hw_reg_read(ah, cur_reg);
if (cur_val != var_pattern) {
- ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+ ATH5K_ERR(ah, "POST Failed !!!\n");
return -EAGAIN;
}
@@ -95,18 +95,18 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
/**
* ath5k_hw_init - Check if hw is supported and init the needed structs
*
- * @sc: The &struct ath5k_softc we got from the driver's init_softc function
+ * @ah: The &struct ath5k_hw we got from the driver's init_softc function
*
* 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,
* -ENODEV if the device is not supported or prints an error msg if something
* else went wrong.
*/
-int ath5k_hw_init(struct ath5k_softc *sc)
+int ath5k_hw_init(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
+ static const u8 zero_mac[ETH_ALEN] = { };
struct ath_common *common = ath5k_hw_common(ah);
- struct pci_dev *pdev = sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
struct ath5k_eeprom_info *ee;
int ret;
u32 srev;
@@ -122,8 +122,8 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ah->ah_retry_long = AR5K_INIT_RETRY_LONG;
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
ah->ah_noise_floor = -95; /* until first NF calibration is run */
- sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
- ah->ah_current_channel = &sc->channels[0];
+ ah->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+ ah->ah_current_channel = &ah->channels[0];
/*
* Find the mac version
@@ -191,7 +191,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
break;
case AR5K_SREV_RAD_5424:
if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
- ah->ah_mac_version == AR5K_SREV_AR2417){
+ ah->ah_mac_version == AR5K_SREV_AR2417) {
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
} else {
@@ -210,43 +210,42 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
CHANNEL_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) {
+ ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
} else if (srev == AR5K_SREV_AR5213A &&
- ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
ah->ah_radio = AR5K_RF5112;
ah->ah_single_chip = false;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) ||
- ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
+ ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
- ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
- ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
} else {
- ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
+ ATH5K_ERR(ah, "Couldn't identify radio revision.\n");
ret = -ENODEV;
goto err;
}
}
- /* Return on unsuported chips (unsupported eeprom etc) */
- if ((srev >= AR5K_SREV_AR5416) &&
- (srev < AR5K_SREV_AR2425)) {
- ATH5K_ERR(sc, "Device not yet supported.\n");
+ /* Return on unsupported chips (unsupported eeprom etc) */
+ if ((srev >= AR5K_SREV_AR5416) && (srev < AR5K_SREV_AR2425)) {
+ ATH5K_ERR(ah, "Device not yet supported.\n");
ret = -ENODEV;
goto err;
}
@@ -268,7 +267,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
*/
ret = ath5k_eeprom_init(ah);
if (ret) {
- ATH5K_ERR(sc, "unable to init EEPROM\n");
+ ATH5K_ERR(ah, "unable to init EEPROM\n");
goto err;
}
@@ -285,7 +284,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
- /* If serdes programing is enabled, increase PCI-E
+ /* If serdes programming is enabled, increase PCI-E
* tx power for systems with long trace from host
* to minicard connector. */
if (ee->ee_serdes)
@@ -309,17 +308,17 @@ int ath5k_hw_init(struct ath5k_softc *sc)
/* Get misc capabilities */
ret = ath5k_hw_set_capabilities(ah);
if (ret) {
- ATH5K_ERR(sc, "unable to get device capabilities\n");
+ ATH5K_ERR(ah, "unable to get device capabilities\n");
goto err;
}
- if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) {
+ if (test_bit(ATH_STAT_2G_DISABLED, ah->status)) {
__clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode);
__clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode);
}
/* Crypto settings */
- common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
+ common->keymax = (ah->ah_version == AR5K_AR5210 ?
AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
if (srev >= AR5K_SREV_AR5212_V4 &&
@@ -334,12 +333,12 @@ int ath5k_hw_init(struct ath5k_softc *sc)
}
/* MAC address is cleared until add_interface */
- ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){});
+ ath5k_hw_set_lladdr(ah, zero_mac);
/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
ath5k_hw_set_bssid(ah);
- ath5k_hw_set_opmode(ah, sc->opmode);
+ ath5k_hw_set_opmode(ah, ah->opmode);
ath5k_hw_rfgain_opt_init(ah);
@@ -360,7 +359,7 @@ err:
*/
void ath5k_hw_deinit(struct ath5k_hw *ah)
{
- __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
+ __set_bit(ATH_STAT_INVALID, ah->status);
if (ah->ah_rf_banks != NULL)
kfree(ah->ah_rf_banks);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index b6c5d3715b96..f54dff44ed50 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -42,6 +42,7 @@
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/hardirq.h>
#include <linux/if.h>
#include <linux/io.h>
@@ -85,10 +86,8 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
static int ath5k_init(struct ieee80211_hw *hw);
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
bool skip_pcu);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
/* Known SREVs */
static const struct ath5k_srev_name srev_names[] = {
@@ -239,8 +238,8 @@ static const struct ath_ops ath5k_common_ops = {
static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
- struct ath5k_softc *sc = hw->priv;
- struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah);
+ struct ath5k_hw *ah = hw->priv;
+ struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
return ath_reg_notifier_apply(wiphy, request, regulatory);
}
@@ -290,7 +289,7 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
band = IEEE80211_BAND_2GHZ;
break;
default:
- ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
+ ATH5K_WARN(ah, "bad mode, not copying channels\n");
return 0;
}
@@ -328,51 +327,50 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
}
static void
-ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
+ath5k_setup_rate_idx(struct ath5k_hw *ah, struct ieee80211_supported_band *b)
{
u8 i;
for (i = 0; i < AR5K_MAX_RATES; i++)
- sc->rate_idx[b->band][i] = -1;
+ ah->rate_idx[b->band][i] = -1;
for (i = 0; i < b->n_bitrates; i++) {
- sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
+ ah->rate_idx[b->band][b->bitrates[i].hw_value] = i;
if (b->bitrates[i].hw_value_short)
- sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
+ ah->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
}
}
static int
ath5k_setup_bands(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ieee80211_supported_band *sband;
int max_c, count_c = 0;
int i;
- BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
- max_c = ARRAY_SIZE(sc->channels);
+ BUILD_BUG_ON(ARRAY_SIZE(ah->sbands) < IEEE80211_NUM_BANDS);
+ max_c = ARRAY_SIZE(ah->channels);
/* 2GHz band */
- sband = &sc->sbands[IEEE80211_BAND_2GHZ];
+ sband = &ah->sbands[IEEE80211_BAND_2GHZ];
sband->band = IEEE80211_BAND_2GHZ;
- sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0];
+ sband->bitrates = &ah->rates[IEEE80211_BAND_2GHZ][0];
- if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
+ if (test_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode)) {
/* G mode */
memcpy(sband->bitrates, &ath5k_rates[0],
sizeof(struct ieee80211_rate) * 12);
sband->n_bitrates = 12;
- sband->channels = sc->channels;
+ sband->channels = ah->channels;
sband->n_channels = ath5k_setup_channels(ah, sband->channels,
AR5K_MODE_11G, max_c);
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
count_c = sband->n_channels;
max_c -= count_c;
- } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) {
+ } else if (test_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode)) {
/* B mode */
memcpy(sband->bitrates, &ath5k_rates[0],
sizeof(struct ieee80211_rate) * 4);
@@ -391,7 +389,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
}
}
- sband->channels = sc->channels;
+ sband->channels = ah->channels;
sband->n_channels = ath5k_setup_channels(ah, sband->channels,
AR5K_MODE_11B, max_c);
@@ -399,27 +397,27 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
count_c = sband->n_channels;
max_c -= count_c;
}
- ath5k_setup_rate_idx(sc, sband);
+ ath5k_setup_rate_idx(ah, sband);
/* 5GHz band, A mode */
- if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
- sband = &sc->sbands[IEEE80211_BAND_5GHZ];
+ if (test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) {
+ sband = &ah->sbands[IEEE80211_BAND_5GHZ];
sband->band = IEEE80211_BAND_5GHZ;
- sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0];
+ sband->bitrates = &ah->rates[IEEE80211_BAND_5GHZ][0];
memcpy(sband->bitrates, &ath5k_rates[4],
sizeof(struct ieee80211_rate) * 8);
sband->n_bitrates = 8;
- sband->channels = &sc->channels[count_c];
+ sband->channels = &ah->channels[count_c];
sband->n_channels = ath5k_setup_channels(ah, sband->channels,
AR5K_MODE_11A, max_c);
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
}
- ath5k_setup_rate_idx(sc, sband);
+ ath5k_setup_rate_idx(ah, sband);
- ath5k_debug_dump_bands(sc);
+ ath5k_debug_dump_bands(ah);
return 0;
}
@@ -429,14 +427,14 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
* To accomplish this we must first cleanup any pending DMA,
* then restart stuff after a la ath5k_init.
*
- * Called with sc->lock.
+ * Called with ah->lock.
*/
int
-ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan)
{
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"channel set, resetting (%u -> %u MHz)\n",
- sc->curchan->center_freq, chan->center_freq);
+ ah->curchan->center_freq, chan->center_freq);
/*
* To switch channels clear any pending DMA operations;
@@ -444,7 +442,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- return ath5k_reset(sc, chan, true);
+ return ath5k_reset(ah, chan, true);
}
void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -488,10 +486,10 @@ void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
}
void
-ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
struct ieee80211_vif *vif)
{
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_vif_iter_data iter_data;
u32 rfilt;
@@ -510,41 +508,41 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
ath5k_vif_iter(&iter_data, vif->addr, vif);
/* Get list of all active MAC addresses */
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+ ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
&iter_data);
- memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
+ memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN);
- sc->opmode = iter_data.opmode;
- if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED)
+ ah->opmode = iter_data.opmode;
+ if (ah->opmode == NL80211_IFTYPE_UNSPECIFIED)
/* Nothing active, default to station mode */
- sc->opmode = NL80211_IFTYPE_STATION;
+ ah->opmode = NL80211_IFTYPE_STATION;
- ath5k_hw_set_opmode(sc->ah, sc->opmode);
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
- sc->opmode, ath_opmode_to_string(sc->opmode));
+ ath5k_hw_set_opmode(ah, ah->opmode);
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
+ ah->opmode, ath_opmode_to_string(ah->opmode));
if (iter_data.need_set_hw_addr && iter_data.found_active)
- ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
+ ath5k_hw_set_lladdr(ah, iter_data.active_mac);
- if (ath5k_hw_hasbssidmask(sc->ah))
- ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+ if (ath5k_hw_hasbssidmask(ah))
+ ath5k_hw_set_bssid_mask(ah, ah->bssidmask);
/* Set up RX Filter */
if (iter_data.n_stas > 1) {
/* If you have multiple STA interfaces connected to
* different APs, ARPs are not received (most of the time?)
- * Enabling PROMISC appears to fix that probem.
+ * Enabling PROMISC appears to fix that problem.
*/
- sc->filter_flags |= AR5K_RX_FILTER_PROM;
+ ah->filter_flags |= AR5K_RX_FILTER_PROM;
}
- rfilt = sc->filter_flags;
- ath5k_hw_set_rx_filter(sc->ah, rfilt);
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+ rfilt = ah->filter_flags;
+ ath5k_hw_set_rx_filter(ah, rfilt);
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
}
static inline int
-ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
+ath5k_hw_to_driver_rix(struct ath5k_hw *ah, int hw_rix)
{
int rix;
@@ -553,7 +551,7 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
"hw_rix out of bounds: %x\n", hw_rix))
return 0;
- rix = sc->rate_idx[sc->curchan->band][hw_rix];
+ rix = ah->rate_idx[ah->curchan->band][hw_rix];
if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
rix = 0;
@@ -565,9 +563,9 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
\***************/
static
-struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
+struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_hw *ah, dma_addr_t *skb_addr)
{
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
struct sk_buff *skb;
/*
@@ -579,17 +577,17 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
GFP_ATOMIC);
if (!skb) {
- ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
+ ATH5K_ERR(ah, "can't alloc skbuff of size %u\n",
common->rx_bufsize);
return NULL;
}
- *skb_addr = dma_map_single(sc->dev,
+ *skb_addr = dma_map_single(ah->dev,
skb->data, common->rx_bufsize,
DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) {
- ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
+ if (unlikely(dma_mapping_error(ah->dev, *skb_addr))) {
+ ATH5K_ERR(ah, "%s: DMA mapping failed\n", __func__);
dev_kfree_skb(skb);
return NULL;
}
@@ -597,15 +595,14 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
}
static int
-ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_rxbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
- struct ath5k_hw *ah = sc->ah;
struct sk_buff *skb = bf->skb;
struct ath5k_desc *ds;
int ret;
if (!skb) {
- skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
+ skb = ath5k_rx_skb_alloc(ah, &bf->skbaddr);
if (!skb)
return -ENOMEM;
bf->skb = skb;
@@ -631,13 +628,13 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds->ds_data = bf->skbaddr;
ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0);
if (ret) {
- ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__);
+ ATH5K_ERR(ah, "%s: could not setup RX desc\n", __func__);
return ret;
}
- if (sc->rxlink != NULL)
- *sc->rxlink = bf->daddr;
- sc->rxlink = &ds->ds_link;
+ if (ah->rxlink != NULL)
+ *ah->rxlink = bf->daddr;
+ ah->rxlink = &ds->ds_link;
return 0;
}
@@ -665,10 +662,9 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
}
static int
-ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
struct ath5k_txq *txq, int padsize)
{
- struct ath5k_hw *ah = sc->ah;
struct ath5k_desc *ds = bf->desc;
struct sk_buff *skb = bf->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -684,10 +680,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
/* XXX endianness */
- bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+ bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len,
DMA_TO_DEVICE);
- rate = ieee80211_get_tx_rate(sc->hw, info);
+ rate = ieee80211_get_tx_rate(ah->hw, info);
if (!rate) {
ret = -EINVAL;
goto err_unmap;
@@ -711,20 +707,20 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
}
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
flags |= AR5K_TXDESC_RTSENA;
- cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
- duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
+ cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value;
+ duration = le16_to_cpu(ieee80211_rts_duration(ah->hw,
info->control.vif, pktlen, info));
}
if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
flags |= AR5K_TXDESC_CTSENA;
- cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
- duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
+ cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value;
+ duration = le16_to_cpu(ieee80211_ctstoself_duration(ah->hw,
info->control.vif, pktlen, info));
}
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), padsize,
get_hw_packet_type(skb),
- (sc->power_level * 2),
+ (ah->power_level * 2),
hw_rate,
info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
cts_rate, duration);
@@ -734,7 +730,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
memset(mrr_rate, 0, sizeof(mrr_rate));
memset(mrr_tries, 0, sizeof(mrr_tries));
for (i = 0; i < 3; i++) {
- rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
+ rate = ieee80211_get_alt_retry_rate(ah->hw, info, i);
if (!rate)
break;
@@ -765,7 +761,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
return 0;
err_unmap:
- dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
+ dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
return ret;
}
@@ -774,7 +770,7 @@ err_unmap:
\*******************/
static int
-ath5k_desc_alloc(struct ath5k_softc *sc)
+ath5k_desc_alloc(struct ath5k_hw *ah)
{
struct ath5k_desc *ds;
struct ath5k_buf *bf;
@@ -783,69 +779,68 @@ ath5k_desc_alloc(struct ath5k_softc *sc)
int ret;
/* allocate descriptors */
- sc->desc_len = sizeof(struct ath5k_desc) *
+ ah->desc_len = sizeof(struct ath5k_desc) *
(ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
- sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len,
- &sc->desc_daddr, GFP_KERNEL);
- if (sc->desc == NULL) {
- ATH5K_ERR(sc, "can't allocate descriptors\n");
+ ah->desc = dma_alloc_coherent(ah->dev, ah->desc_len,
+ &ah->desc_daddr, GFP_KERNEL);
+ if (ah->desc == NULL) {
+ ATH5K_ERR(ah, "can't allocate descriptors\n");
ret = -ENOMEM;
goto err;
}
- ds = sc->desc;
- da = sc->desc_daddr;
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
- ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
+ ds = ah->desc;
+ da = ah->desc_daddr;
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
+ ds, ah->desc_len, (unsigned long long)ah->desc_daddr);
bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
sizeof(struct ath5k_buf), GFP_KERNEL);
if (bf == NULL) {
- ATH5K_ERR(sc, "can't allocate bufptr\n");
+ ATH5K_ERR(ah, "can't allocate bufptr\n");
ret = -ENOMEM;
goto err_free;
}
- sc->bufptr = bf;
+ ah->bufptr = bf;
- INIT_LIST_HEAD(&sc->rxbuf);
+ INIT_LIST_HEAD(&ah->rxbuf);
for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
bf->desc = ds;
bf->daddr = da;
- list_add_tail(&bf->list, &sc->rxbuf);
+ list_add_tail(&bf->list, &ah->rxbuf);
}
- INIT_LIST_HEAD(&sc->txbuf);
- sc->txbuf_len = ATH_TXBUF;
- for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
- da += sizeof(*ds)) {
+ INIT_LIST_HEAD(&ah->txbuf);
+ ah->txbuf_len = ATH_TXBUF;
+ for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
bf->desc = ds;
bf->daddr = da;
- list_add_tail(&bf->list, &sc->txbuf);
+ list_add_tail(&bf->list, &ah->txbuf);
}
/* beacon buffers */
- INIT_LIST_HEAD(&sc->bcbuf);
+ INIT_LIST_HEAD(&ah->bcbuf);
for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) {
bf->desc = ds;
bf->daddr = da;
- list_add_tail(&bf->list, &sc->bcbuf);
+ list_add_tail(&bf->list, &ah->bcbuf);
}
return 0;
err_free:
- dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
+ dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr);
err:
- sc->desc = NULL;
+ ah->desc = NULL;
return ret;
}
void
-ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
BUG_ON(!bf);
if (!bf->skb)
return;
- dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len,
+ dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len,
DMA_TO_DEVICE);
dev_kfree_skb_any(bf->skb);
bf->skb = NULL;
@@ -854,15 +849,14 @@ ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
}
void
-ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
BUG_ON(!bf);
if (!bf->skb)
return;
- dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize,
+ dma_unmap_single(ah->dev, bf->skbaddr, common->rx_bufsize,
DMA_FROM_DEVICE);
dev_kfree_skb_any(bf->skb);
bf->skb = NULL;
@@ -871,24 +865,24 @@ ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
}
static void
-ath5k_desc_free(struct ath5k_softc *sc)
+ath5k_desc_free(struct ath5k_hw *ah)
{
struct ath5k_buf *bf;
- list_for_each_entry(bf, &sc->txbuf, list)
- ath5k_txbuf_free_skb(sc, bf);
- list_for_each_entry(bf, &sc->rxbuf, list)
- ath5k_rxbuf_free_skb(sc, bf);
- list_for_each_entry(bf, &sc->bcbuf, list)
- ath5k_txbuf_free_skb(sc, bf);
+ list_for_each_entry(bf, &ah->txbuf, list)
+ ath5k_txbuf_free_skb(ah, bf);
+ list_for_each_entry(bf, &ah->rxbuf, list)
+ ath5k_rxbuf_free_skb(ah, bf);
+ list_for_each_entry(bf, &ah->bcbuf, list)
+ ath5k_txbuf_free_skb(ah, bf);
/* Free memory associated with all descriptors */
- dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
- sc->desc = NULL;
- sc->desc_daddr = 0;
+ dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr);
+ ah->desc = NULL;
+ ah->desc_daddr = 0;
- kfree(sc->bufptr);
- sc->bufptr = NULL;
+ kfree(ah->bufptr);
+ ah->bufptr = NULL;
}
@@ -897,10 +891,9 @@ ath5k_desc_free(struct ath5k_softc *sc)
\**************/
static struct ath5k_txq *
-ath5k_txq_setup(struct ath5k_softc *sc,
+ath5k_txq_setup(struct ath5k_hw *ah,
int qtype, int subtype)
{
- struct ath5k_hw *ah = sc->ah;
struct ath5k_txq *txq;
struct ath5k_txq_info qi = {
.tqi_subtype = subtype,
@@ -934,13 +927,13 @@ ath5k_txq_setup(struct ath5k_softc *sc,
*/
return ERR_PTR(qnum);
}
- if (qnum >= ARRAY_SIZE(sc->txqs)) {
- ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
- qnum, ARRAY_SIZE(sc->txqs));
+ 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 = &sc->txqs[qnum];
+ txq = &ah->txqs[qnum];
if (!txq->setup) {
txq->qnum = qnum;
txq->link = NULL;
@@ -952,7 +945,7 @@ ath5k_txq_setup(struct ath5k_softc *sc,
txq->txq_poll_mark = false;
txq->txq_stuck = 0;
}
- return &sc->txqs[qnum];
+ return &ah->txqs[qnum];
}
static int
@@ -972,18 +965,17 @@ ath5k_beaconq_setup(struct ath5k_hw *ah)
}
static int
-ath5k_beaconq_config(struct ath5k_softc *sc)
+ath5k_beaconq_config(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
struct ath5k_txq_info qi;
int ret;
- ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
+ ret = ath5k_hw_get_tx_queueprops(ah, ah->bhalq, &qi);
if (ret)
goto err;
- if (sc->opmode == NL80211_IFTYPE_AP ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+ if (ah->opmode == NL80211_IFTYPE_AP ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
/*
* Always burst out beacon and CAB traffic
* (aifs = cwmin = cwmax = 0)
@@ -991,7 +983,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
qi.tqi_aifs = 0;
qi.tqi_cw_min = 0;
qi.tqi_cw_max = 0;
- } else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+ } else if (ah->opmode == NL80211_IFTYPE_ADHOC) {
/*
* Adhoc mode; backoff between 0 and (2 * cw_min).
*/
@@ -1000,17 +992,17 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN;
}
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
- ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi);
+ ret = ath5k_hw_set_tx_queueprops(ah, ah->bhalq, &qi);
if (ret) {
- ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
+ ATH5K_ERR(ah, "%s: unable to update parameters for beacon "
"hardware queue!\n", __func__);
goto err;
}
- ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */
+ ret = ath5k_hw_reset_tx_queue(ah, ah->bhalq); /* push to h/w */
if (ret)
goto err;
@@ -1019,7 +1011,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
if (ret)
goto err;
- qi.tqi_ready_time = (sc->bintval * 80) / 100;
+ qi.tqi_ready_time = (ah->bintval * 80) / 100;
ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
if (ret)
goto err;
@@ -1032,7 +1024,7 @@ err:
/**
* ath5k_drain_tx_buffs - Empty tx buffers
*
- * @sc The &struct ath5k_softc
+ * @ah The &struct ath5k_hw
*
* Empty tx buffers from all queues in preparation
* of a reset or during shutdown.
@@ -1041,26 +1033,26 @@ err:
* we do not need to block ath5k_tx_tasklet
*/
static void
-ath5k_drain_tx_buffs(struct ath5k_softc *sc)
+ath5k_drain_tx_buffs(struct ath5k_hw *ah)
{
struct ath5k_txq *txq;
struct ath5k_buf *bf, *bf0;
int i;
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
- if (sc->txqs[i].setup) {
- txq = &sc->txqs[i];
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+ if (ah->txqs[i].setup) {
+ txq = &ah->txqs[i];
spin_lock_bh(&txq->lock);
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
- ath5k_debug_printtxbuf(sc, bf);
+ ath5k_debug_printtxbuf(ah, bf);
- ath5k_txbuf_free_skb(sc, bf);
+ ath5k_txbuf_free_skb(ah, bf);
- spin_lock_bh(&sc->txbuflock);
- list_move_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
+ spin_lock_bh(&ah->txbuflock);
+ list_move_tail(&bf->list, &ah->txbuf);
+ ah->txbuf_len++;
txq->txq_len--;
- spin_unlock_bh(&sc->txbuflock);
+ spin_unlock_bh(&ah->txbuflock);
}
txq->link = NULL;
txq->txq_poll_mark = false;
@@ -1070,14 +1062,14 @@ ath5k_drain_tx_buffs(struct ath5k_softc *sc)
}
static void
-ath5k_txq_release(struct ath5k_softc *sc)
+ath5k_txq_release(struct ath5k_hw *ah)
{
- struct ath5k_txq *txq = sc->txqs;
+ struct ath5k_txq *txq = ah->txqs;
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++, txq++)
if (txq->setup) {
- ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
+ ath5k_hw_release_tx_queue(ah, txq->qnum);
txq->setup = false;
}
}
@@ -1091,33 +1083,32 @@ ath5k_txq_release(struct ath5k_softc *sc)
* Enable the receive h/w following a reset.
*/
static int
-ath5k_rx_start(struct ath5k_softc *sc)
+ath5k_rx_start(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_buf *bf;
int ret;
common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
common->cachelsz, common->rx_bufsize);
- spin_lock_bh(&sc->rxbuflock);
- sc->rxlink = NULL;
- list_for_each_entry(bf, &sc->rxbuf, list) {
- ret = ath5k_rxbuf_setup(sc, bf);
+ spin_lock_bh(&ah->rxbuflock);
+ ah->rxlink = NULL;
+ list_for_each_entry(bf, &ah->rxbuf, list) {
+ ret = ath5k_rxbuf_setup(ah, bf);
if (ret != 0) {
- spin_unlock_bh(&sc->rxbuflock);
+ spin_unlock_bh(&ah->rxbuflock);
goto err;
}
}
- bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+ bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list);
ath5k_hw_set_rxdp(ah, bf->daddr);
- spin_unlock_bh(&sc->rxbuflock);
+ spin_unlock_bh(&ah->rxbuflock);
ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
- ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */
+ ath5k_update_bssid_mask_and_opmode(ah, NULL); /* set filters, etc. */
ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
return 0;
@@ -1133,21 +1124,19 @@ err:
* does.
*/
static void
-ath5k_rx_stop(struct ath5k_softc *sc)
+ath5k_rx_stop(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
- ath5k_debug_printrxbuffs(sc, ah);
+ ath5k_debug_printrxbuffs(ah);
}
static unsigned int
-ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_rx_decrypted(struct ath5k_hw *ah, struct sk_buff *skb,
struct ath5k_rx_status *rs)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int keyix, hlen;
@@ -1174,10 +1163,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb,
static void
-ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb,
struct ieee80211_rx_status *rxs)
{
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
u64 tsf, bc_tstamp;
u32 hw_tu;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -1190,11 +1179,11 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
* have updated the local TSF. We have to work around various
* hardware bugs, though...
*/
- tsf = ath5k_hw_get_tsf64(sc->ah);
+ tsf = ath5k_hw_get_tsf64(ah);
bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
hw_tu = TSF_TO_TU(tsf);
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
(unsigned long long)bc_tstamp,
(unsigned long long)rxs->mactime,
@@ -1213,7 +1202,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
* received, not like mac80211 which defines it at the start.
*/
if (bc_tstamp > rxs->mactime) {
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"fixing mactime from %llx to %llx\n",
(unsigned long long)rxs->mactime,
(unsigned long long)tsf);
@@ -1226,25 +1215,24 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
* beacons. This also takes care of synchronizing beacon sending
* times with other stations.
*/
- if (hw_tu >= sc->nexttbtt)
- ath5k_beacon_update_timers(sc, bc_tstamp);
+ if (hw_tu >= ah->nexttbtt)
+ ath5k_beacon_update_timers(ah, bc_tstamp);
/* Check if the beacon timers are still correct, because a TSF
* update might have created a window between them - for a
* longer description see the comment of this function: */
- if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) {
- ath5k_beacon_update_timers(sc, bc_tstamp);
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ if (!ath5k_hw_check_beacon_timers(ah, ah->bintval)) {
+ ath5k_beacon_update_timers(ah, bc_tstamp);
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"fixed beacon timers after beacon receive\n");
}
}
}
static void
-ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
+ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
/* only beacons from our BSSID */
@@ -1263,16 +1251,15 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
*/
static int ath5k_common_padpos(struct sk_buff *skb)
{
- struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 frame_control = hdr->frame_control;
int padpos = 24;
- if (ieee80211_has_a4(frame_control)) {
+ if (ieee80211_has_a4(frame_control))
padpos += ETH_ALEN;
- }
- if (ieee80211_is_data_qos(frame_control)) {
+
+ if (ieee80211_is_data_qos(frame_control))
padpos += IEEE80211_QOS_CTL_LEN;
- }
return padpos;
}
@@ -1286,13 +1273,13 @@ static int ath5k_add_padding(struct sk_buff *skb)
int padpos = ath5k_common_padpos(skb);
int padsize = padpos & 3;
- if (padsize && skb->len>padpos) {
+ if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize)
return -1;
skb_push(skb, padsize);
- memmove(skb->data, skb->data+padsize, padpos);
+ memmove(skb->data, skb->data + padsize, padpos);
return padsize;
}
@@ -1317,7 +1304,7 @@ static int ath5k_remove_padding(struct sk_buff *skb)
int padpos = ath5k_common_padpos(skb);
int padsize = padpos & 3;
- if (padsize && skb->len>=padpos+padsize) {
+ if (padsize && skb->len >= padpos + padsize) {
memmove(skb->data + padsize, skb->data, padpos);
skb_pull(skb, padsize);
return padsize;
@@ -1327,7 +1314,7 @@ static int ath5k_remove_padding(struct sk_buff *skb)
}
static void
-ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
struct ath5k_rx_status *rs)
{
struct ieee80211_rx_status *rxs;
@@ -1353,44 +1340,44 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
* timestamp (beginning of phy frame, data frame, end of rx?).
* The only thing we know is that it is hardware specific...
* On AR5213 it seems the rx timestamp is at the end of the
- * frame, but i'm not sure.
+ * frame, but I'm not sure.
*
* NOTE: mac80211 defines mactime at the beginning of the first
* data symbol. Since we don't have any time references it's
* impossible to comply to that. This affects IBSS merge only
* right now, so it's not too bad...
*/
- rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp);
+ rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp);
rxs->flag |= RX_FLAG_MACTIME_MPDU;
- rxs->freq = sc->curchan->center_freq;
- rxs->band = sc->curchan->band;
+ rxs->freq = ah->curchan->center_freq;
+ rxs->band = ah->curchan->band;
- rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi;
+ rxs->signal = ah->ah_noise_floor + rs->rs_rssi;
rxs->antenna = rs->rs_antenna;
if (rs->rs_antenna > 0 && rs->rs_antenna < 5)
- sc->stats.antenna_rx[rs->rs_antenna]++;
+ ah->stats.antenna_rx[rs->rs_antenna]++;
else
- sc->stats.antenna_rx[0]++; /* invalid */
+ ah->stats.antenna_rx[0]++; /* invalid */
- rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs->rs_rate);
- rxs->flag |= ath5k_rx_decrypted(sc, skb, rs);
+ rxs->rate_idx = ath5k_hw_to_driver_rix(ah, rs->rs_rate);
+ rxs->flag |= ath5k_rx_decrypted(ah, skb, rs);
if (rxs->rate_idx >= 0 && rs->rs_rate ==
- sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
+ ah->sbands[ah->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
rxs->flag |= RX_FLAG_SHORTPRE;
- trace_ath5k_rx(sc, skb);
+ trace_ath5k_rx(ah, skb);
- ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi);
+ ath5k_update_beacon_rssi(ah, skb, rs->rs_rssi);
/* check beacons in IBSS mode */
- if (sc->opmode == NL80211_IFTYPE_ADHOC)
- ath5k_check_ibss_tsf(sc, skb, rxs);
+ if (ah->opmode == NL80211_IFTYPE_ADHOC)
+ ath5k_check_ibss_tsf(ah, skb, rxs);
- ieee80211_rx(sc->hw, skb);
+ ieee80211_rx(ah->hw, skb);
}
/** ath5k_frame_receive_ok() - Do we want to receive this frame or not?
@@ -1399,20 +1386,20 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
* statistics. Return true if we want this frame, false if not.
*/
static bool
-ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
+ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs)
{
- sc->stats.rx_all_count++;
- sc->stats.rx_bytes_count += rs->rs_datalen;
+ ah->stats.rx_all_count++;
+ ah->stats.rx_bytes_count += rs->rs_datalen;
if (unlikely(rs->rs_status)) {
if (rs->rs_status & AR5K_RXERR_CRC)
- sc->stats.rxerr_crc++;
+ ah->stats.rxerr_crc++;
if (rs->rs_status & AR5K_RXERR_FIFO)
- sc->stats.rxerr_fifo++;
+ ah->stats.rxerr_fifo++;
if (rs->rs_status & AR5K_RXERR_PHY) {
- sc->stats.rxerr_phy++;
+ ah->stats.rxerr_phy++;
if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32)
- sc->stats.rxerr_phy_code[rs->rs_phyerr]++;
+ ah->stats.rxerr_phy_code[rs->rs_phyerr]++;
return false;
}
if (rs->rs_status & AR5K_RXERR_DECRYPT) {
@@ -1426,13 +1413,13 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
*
* XXX do key cache faulting
*/
- sc->stats.rxerr_decrypt++;
+ ah->stats.rxerr_decrypt++;
if (rs->rs_keyix == AR5K_RXKEYIX_INVALID &&
!(rs->rs_status & AR5K_RXERR_CRC))
return true;
}
if (rs->rs_status & AR5K_RXERR_MIC) {
- sc->stats.rxerr_mic++;
+ ah->stats.rxerr_mic++;
return true;
}
@@ -1442,25 +1429,26 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
}
if (unlikely(rs->rs_more)) {
- sc->stats.rxerr_jumbo++;
+ ah->stats.rxerr_jumbo++;
return false;
}
return true;
}
static void
-ath5k_set_current_imask(struct ath5k_softc *sc)
+ath5k_set_current_imask(struct ath5k_hw *ah)
{
- enum ath5k_int imask = sc->imask;
+ enum ath5k_int imask;
unsigned long flags;
- spin_lock_irqsave(&sc->irqlock, flags);
- if (sc->rx_pending)
+ spin_lock_irqsave(&ah->irqlock, flags);
+ imask = ah->imask;
+ if (ah->rx_pending)
imask &= ~AR5K_INT_RX_ALL;
- if (sc->tx_pending)
+ if (ah->tx_pending)
imask &= ~AR5K_INT_TX_ALL;
- ath5k_hw_set_imr(sc->ah, imask);
- spin_unlock_irqrestore(&sc->irqlock, flags);
+ ath5k_hw_set_imr(ah, imask);
+ spin_unlock_irqrestore(&ah->irqlock, flags);
}
static void
@@ -1469,39 +1457,38 @@ ath5k_tasklet_rx(unsigned long data)
struct ath5k_rx_status rs = {};
struct sk_buff *skb, *next_skb;
dma_addr_t next_skb_addr;
- struct ath5k_softc *sc = (void *)data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = (void *)data;
struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_buf *bf;
struct ath5k_desc *ds;
int ret;
- spin_lock(&sc->rxbuflock);
- if (list_empty(&sc->rxbuf)) {
- ATH5K_WARN(sc, "empty rx buf pool\n");
+ spin_lock(&ah->rxbuflock);
+ if (list_empty(&ah->rxbuf)) {
+ ATH5K_WARN(ah, "empty rx buf pool\n");
goto unlock;
}
do {
- bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+ bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list);
BUG_ON(bf->skb == NULL);
skb = bf->skb;
ds = bf->desc;
/* bail if HW is still using self-linked descriptor */
- if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr)
+ if (ath5k_hw_get_rxdp(ah) == bf->daddr)
break;
- ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+ ret = ah->ah_proc_rx_desc(ah, ds, &rs);
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
- ATH5K_ERR(sc, "error in processing rx descriptor\n");
- sc->stats.rxerr_proc++;
+ ATH5K_ERR(ah, "error in processing rx descriptor\n");
+ ah->stats.rxerr_proc++;
break;
}
- if (ath5k_receive_frame_ok(sc, &rs)) {
- next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
+ if (ath5k_receive_frame_ok(ah, &rs)) {
+ next_skb = ath5k_rx_skb_alloc(ah, &next_skb_addr);
/*
* If we can't replace bf->skb with a new skb under
@@ -1510,24 +1497,24 @@ ath5k_tasklet_rx(unsigned long data)
if (!next_skb)
goto next;
- dma_unmap_single(sc->dev, bf->skbaddr,
+ dma_unmap_single(ah->dev, bf->skbaddr,
common->rx_bufsize,
DMA_FROM_DEVICE);
skb_put(skb, rs.rs_datalen);
- ath5k_receive_frame(sc, skb, &rs);
+ ath5k_receive_frame(ah, skb, &rs);
bf->skb = next_skb;
bf->skbaddr = next_skb_addr;
}
next:
- list_move_tail(&bf->list, &sc->rxbuf);
- } while (ath5k_rxbuf_setup(sc, bf) == 0);
+ list_move_tail(&bf->list, &ah->rxbuf);
+ } while (ath5k_rxbuf_setup(ah, bf) == 0);
unlock:
- spin_unlock(&sc->rxbuflock);
- sc->rx_pending = false;
- ath5k_set_current_imask(sc);
+ spin_unlock(&ah->rxbuflock);
+ ah->rx_pending = false;
+ ath5k_set_current_imask(ah);
}
@@ -1539,12 +1526,12 @@ void
ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_buf *bf;
unsigned long flags;
int padsize;
- trace_ath5k_tx(sc, skb, txq);
+ trace_ath5k_tx(ah, skb, txq);
/*
* The hardware expects the header padded to 4 byte boundaries.
@@ -1552,36 +1539,37 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
padsize = ath5k_add_padding(skb);
if (padsize < 0) {
- ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
+ ATH5K_ERR(ah, "tx hdrlen not %%4: not enough"
" headroom to pad");
goto drop_packet;
}
- if (txq->txq_len >= txq->txq_max)
+ if (txq->txq_len >= txq->txq_max &&
+ txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX)
ieee80211_stop_queue(hw, txq->qnum);
- spin_lock_irqsave(&sc->txbuflock, flags);
- if (list_empty(&sc->txbuf)) {
- ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
- spin_unlock_irqrestore(&sc->txbuflock, flags);
+ spin_lock_irqsave(&ah->txbuflock, flags);
+ if (list_empty(&ah->txbuf)) {
+ ATH5K_ERR(ah, "no further txbuf available, dropping packet\n");
+ spin_unlock_irqrestore(&ah->txbuflock, flags);
ieee80211_stop_queues(hw);
goto drop_packet;
}
- bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
+ bf = list_first_entry(&ah->txbuf, struct ath5k_buf, list);
list_del(&bf->list);
- sc->txbuf_len--;
- if (list_empty(&sc->txbuf))
+ ah->txbuf_len--;
+ if (list_empty(&ah->txbuf))
ieee80211_stop_queues(hw);
- spin_unlock_irqrestore(&sc->txbuflock, flags);
+ spin_unlock_irqrestore(&ah->txbuflock, flags);
bf->skb = skb;
- if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
+ if (ath5k_txbuf_setup(ah, bf, txq, padsize)) {
bf->skb = NULL;
- spin_lock_irqsave(&sc->txbuflock, flags);
- list_add_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
- spin_unlock_irqrestore(&sc->txbuflock, flags);
+ spin_lock_irqsave(&ah->txbuflock, flags);
+ list_add_tail(&bf->list, &ah->txbuf);
+ ah->txbuf_len++;
+ spin_unlock_irqrestore(&ah->txbuflock, flags);
goto drop_packet;
}
return;
@@ -1591,15 +1579,15 @@ drop_packet:
}
static void
-ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
struct ath5k_txq *txq, struct ath5k_tx_status *ts)
{
struct ieee80211_tx_info *info;
u8 tries[3];
int i;
- sc->stats.tx_all_count++;
- sc->stats.tx_bytes_count += skb->len;
+ ah->stats.tx_all_count++;
+ ah->stats.tx_bytes_count += skb->len;
info = IEEE80211_SKB_CB(skb);
tries[0] = info->status.rates[0].count;
@@ -1619,15 +1607,15 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
info->status.rates[ts->ts_final_idx + 1].idx = -1;
if (unlikely(ts->ts_status)) {
- sc->stats.ack_fail++;
+ ah->stats.ack_fail++;
if (ts->ts_status & AR5K_TXERR_FILT) {
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- sc->stats.txerr_filt++;
+ ah->stats.txerr_filt++;
}
if (ts->ts_status & AR5K_TXERR_XRETRY)
- sc->stats.txerr_retry++;
+ ah->stats.txerr_retry++;
if (ts->ts_status & AR5K_TXERR_FIFO)
- sc->stats.txerr_fifo++;
+ ah->stats.txerr_fifo++;
} else {
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ack_signal = ts->ts_rssi;
@@ -1643,16 +1631,16 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
ath5k_remove_padding(skb);
if (ts->ts_antenna > 0 && ts->ts_antenna < 5)
- sc->stats.antenna_tx[ts->ts_antenna]++;
+ ah->stats.antenna_tx[ts->ts_antenna]++;
else
- sc->stats.antenna_tx[0]++; /* invalid */
+ ah->stats.antenna_tx[0]++; /* invalid */
- trace_ath5k_tx_complete(sc, skb, txq, ts);
- ieee80211_tx_status(sc->hw, skb);
+ trace_ath5k_tx_complete(ah, skb, txq, ts);
+ ieee80211_tx_status(ah->hw, skb);
}
static void
-ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq)
{
struct ath5k_tx_status ts = {};
struct ath5k_buf *bf, *bf0;
@@ -1669,11 +1657,11 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
if (bf->skb != NULL) {
ds = bf->desc;
- ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+ ret = ah->ah_proc_tx_desc(ah, ds, &ts);
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
- ATH5K_ERR(sc,
+ ATH5K_ERR(ah,
"error %d while processing "
"queue %u\n", ret, txq->qnum);
break;
@@ -1682,9 +1670,9 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
skb = bf->skb;
bf->skb = NULL;
- dma_unmap_single(sc->dev, bf->skbaddr, skb->len,
+ dma_unmap_single(ah->dev, bf->skbaddr, skb->len,
DMA_TO_DEVICE);
- ath5k_tx_frame_completed(sc, skb, txq, &ts);
+ ath5k_tx_frame_completed(ah, skb, txq, &ts);
}
/*
@@ -1693,31 +1681,31 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
* host memory and moved on.
* Always keep the last descriptor to avoid HW races...
*/
- if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) {
- spin_lock(&sc->txbuflock);
- list_move_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
+ if (ath5k_hw_get_txdp(ah, txq->qnum) != bf->daddr) {
+ spin_lock(&ah->txbuflock);
+ list_move_tail(&bf->list, &ah->txbuf);
+ ah->txbuf_len++;
txq->txq_len--;
- spin_unlock(&sc->txbuflock);
+ spin_unlock(&ah->txbuflock);
}
}
spin_unlock(&txq->lock);
if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4)
- ieee80211_wake_queue(sc->hw, txq->qnum);
+ ieee80211_wake_queue(ah->hw, txq->qnum);
}
static void
ath5k_tasklet_tx(unsigned long data)
{
int i;
- struct ath5k_softc *sc = (void *)data;
+ struct ath5k_hw *ah = (void *)data;
- for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
- if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
- ath5k_tx_processq(sc, &sc->txqs[i]);
+ for (i = 0; i < AR5K_NUM_TX_QUEUES; i++)
+ if (ah->txqs[i].setup && (ah->ah_txq_isr & BIT(i)))
+ ath5k_tx_processq(ah, &ah->txqs[i]);
- sc->tx_pending = false;
- ath5k_set_current_imask(sc);
+ ah->tx_pending = false;
+ ath5k_set_current_imask(ah);
}
@@ -1729,25 +1717,24 @@ ath5k_tasklet_tx(unsigned long data)
* Setup the beacon frame for transmit.
*/
static int
-ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
struct sk_buff *skb = bf->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ath5k_hw *ah = sc->ah;
struct ath5k_desc *ds;
int ret = 0;
u8 antenna;
u32 flags;
const int padsize = 0;
- bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+ bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len,
DMA_TO_DEVICE);
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
"skbaddr %llx\n", skb, skb->data, skb->len,
(unsigned long long)bf->skbaddr);
- if (dma_mapping_error(sc->dev, bf->skbaddr)) {
- ATH5K_ERR(sc, "beacon DMA mapping failed\n");
+ if (dma_mapping_error(ah->dev, bf->skbaddr)) {
+ ATH5K_ERR(ah, "beacon DMA mapping failed\n");
return -EIO;
}
@@ -1755,7 +1742,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
antenna = ah->ah_tx_ant;
flags = AR5K_TXDESC_NOACK;
- if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
+ if (ah->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
ds->ds_link = bf->daddr; /* self-linked */
flags |= AR5K_TXDESC_VEOL;
} else
@@ -1767,7 +1754,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
* 4 beacons to make sure everybody hears our AP.
* When a client tries to associate, hw will keep
* track of the tx antenna to be used for this client
- * automaticaly, based on ACKed packets.
+ * automatically, based on ACKed packets.
*
* Note: AP still listens and transmits RTS on the
* default antenna which is supposed to be an omni.
@@ -1780,7 +1767,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
* on all of them.
*/
if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP)
- antenna = sc->bsent & 4 ? 2 : 1;
+ antenna = ah->bsent & 4 ? 2 : 1;
/* FIXME: If we are in g mode and rate is a CCK rate
@@ -1789,8 +1776,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds->ds_data = bf->skbaddr;
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
ieee80211_get_hdrlen_from_skb(skb), padsize,
- AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
- ieee80211_get_tx_rate(sc->hw, info)->hw_value,
+ AR5K_PKT_TYPE_BEACON, (ah->power_level * 2),
+ ieee80211_get_tx_rate(ah->hw, info)->hw_value,
1, AR5K_TXKEYIX_INVALID,
antenna, flags, 0, 0);
if (ret)
@@ -1798,7 +1785,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
return 0;
err_unmap:
- dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
+ dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
return ret;
}
@@ -1813,7 +1800,7 @@ int
ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
int ret;
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_vif *avf = (void *)vif->drv_priv;
struct sk_buff *skb;
@@ -1829,9 +1816,9 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
goto out;
}
- ath5k_txbuf_free_skb(sc, avf->bbuf);
+ ath5k_txbuf_free_skb(ah, avf->bbuf);
avf->bbuf->skb = skb;
- ret = ath5k_beacon_setup(sc, avf->bbuf);
+ ret = ath5k_beacon_setup(ah, avf->bbuf);
if (ret)
avf->bbuf->skb = NULL;
out:
@@ -1847,15 +1834,14 @@ out:
* or user context from ath5k_beacon_config.
*/
static void
-ath5k_beacon_send(struct ath5k_softc *sc)
+ath5k_beacon_send(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
struct ieee80211_vif *vif;
struct ath5k_vif *avf;
struct ath5k_buf *bf;
struct sk_buff *skb;
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "in beacon_send\n");
/*
* Check if the previous beacon has gone out. If
@@ -1864,47 +1850,47 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* indicate a problem and should not occur. If we
* miss too many consecutive beacons reset the device.
*/
- if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
- sc->bmisscount++;
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
- "missed %u consecutive beacons\n", sc->bmisscount);
- if (sc->bmisscount > 10) { /* NB: 10 is a guess */
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ if (unlikely(ath5k_hw_num_tx_pending(ah, ah->bhalq) != 0)) {
+ ah->bmisscount++;
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
+ "missed %u consecutive beacons\n", ah->bmisscount);
+ if (ah->bmisscount > 10) { /* NB: 10 is a guess */
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"stuck beacon time (%u missed)\n",
- sc->bmisscount);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ah->bmisscount);
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"stuck beacon, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
}
return;
}
- if (unlikely(sc->bmisscount != 0)) {
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ if (unlikely(ah->bmisscount != 0)) {
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"resume beacon xmit after %u misses\n",
- sc->bmisscount);
- sc->bmisscount = 0;
+ ah->bmisscount);
+ ah->bmisscount = 0;
}
- if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
u64 tsf = ath5k_hw_get_tsf64(ah);
u32 tsftu = TSF_TO_TU(tsf);
- int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
- vif = sc->bslot[(slot + 1) % ATH_BCBUF];
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ int slot = ((tsftu % ah->bintval) * ATH_BCBUF) / ah->bintval;
+ vif = ah->bslot[(slot + 1) % ATH_BCBUF];
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"tsf %llx tsftu %x intval %u slot %u vif %p\n",
- (unsigned long long)tsf, tsftu, sc->bintval, slot, vif);
+ (unsigned long long)tsf, tsftu, ah->bintval, slot, vif);
} else /* only one interface */
- vif = sc->bslot[0];
+ vif = ah->bslot[0];
if (!vif)
return;
avf = (void *)vif->drv_priv;
bf = avf->bbuf;
- if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
- sc->opmode == NL80211_IFTYPE_MONITOR)) {
- ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
+ if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION ||
+ ah->opmode == NL80211_IFTYPE_MONITOR)) {
+ ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
return;
}
@@ -1913,36 +1899,40 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* This should never fail since we check above that no frames
* are still pending on the queue.
*/
- if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) {
- ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq);
+ if (unlikely(ath5k_hw_stop_beacon_queue(ah, ah->bhalq))) {
+ ATH5K_WARN(ah, "beacon queue %u didn't start/stop ?\n", ah->bhalq);
/* NB: hw still stops DMA, so proceed */
}
/* refresh the beacon for AP or MESH mode */
- if (sc->opmode == NL80211_IFTYPE_AP ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT)
- ath5k_beacon_update(sc->hw, vif);
+ if (ah->opmode == NL80211_IFTYPE_AP ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT)
+ ath5k_beacon_update(ah->hw, vif);
- trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]);
+ trace_ath5k_tx(ah, bf->skb, &ah->txqs[ah->bhalq]);
- ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
- ath5k_hw_start_tx_dma(ah, sc->bhalq);
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
- sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
+ ath5k_hw_set_txdp(ah, ah->bhalq, bf->daddr);
+ ath5k_hw_start_tx_dma(ah, ah->bhalq);
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
+ ah->bhalq, (unsigned long long)bf->daddr, bf->desc);
- skb = ieee80211_get_buffered_bc(sc->hw, vif);
+ skb = ieee80211_get_buffered_bc(ah->hw, vif);
while (skb) {
- ath5k_tx_queue(sc->hw, skb, sc->cabq);
- skb = ieee80211_get_buffered_bc(sc->hw, vif);
+ ath5k_tx_queue(ah->hw, skb, ah->cabq);
+
+ if (ah->cabq->txq_len >= ah->cabq->txq_max)
+ break;
+
+ skb = ieee80211_get_buffered_bc(ah->hw, vif);
}
- sc->bsent++;
+ ah->bsent++;
}
/**
* ath5k_beacon_update_timers - update beacon timers
*
- * @sc: struct ath5k_softc pointer we are operating on
+ * @ah: struct ath5k_hw pointer we are operating on
* @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
* beacon timer update based on the current HW TSF.
*
@@ -1956,17 +1946,16 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* function to have it all together in one place.
*/
void
-ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
+ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
{
- struct ath5k_hw *ah = sc->ah;
u32 nexttbtt, intval, hw_tu, bc_tu;
u64 hw_tsf;
- intval = sc->bintval & AR5K_BEACON_PERIOD;
- if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+ intval = ah->bintval & AR5K_BEACON_PERIOD;
+ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
if (intval < 15)
- ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+ ATH5K_WARN(ah, "intval %u is too low, min 15\n",
intval);
}
if (WARN_ON(!intval))
@@ -1979,7 +1968,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
hw_tsf = ath5k_hw_get_tsf64(ah);
hw_tu = TSF_TO_TU(hw_tsf);
-#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
+#define FUDGE (AR5K_TUNE_SW_BEACON_RESP + 3)
/* We use FUDGE to make sure the next TBTT is ahead of the current TU.
* Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
* configuration we need to make sure it is bigger than that. */
@@ -2005,7 +1994,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
* automatically update the TSF and then we need to reconfigure
* the timers.
*/
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"need to wait for HW TSF sync\n");
return;
} else {
@@ -2020,7 +2009,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
}
#undef FUDGE
- sc->nexttbtt = nexttbtt;
+ ah->nexttbtt = nexttbtt;
intval |= AR5K_BEACON_ENA;
ath5k_hw_init_beacon(ah, nexttbtt, intval);
@@ -2030,20 +2019,20 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
* of this function
*/
if (bc_tsf == -1)
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"reconfigured timers based on HW TSF\n");
else if (bc_tsf == 0)
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"reset HW TSF and timers\n");
else
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"updated timers based on beacon TSF\n");
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
"bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
(unsigned long long) bc_tsf,
(unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt);
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
intval & AR5K_BEACON_PERIOD,
intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
@@ -2052,22 +2041,21 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
/**
* ath5k_beacon_config - Configure the beacon queues and interrupts
*
- * @sc: struct ath5k_softc pointer we are operating on
+ * @ah: struct ath5k_hw pointer we are operating on
*
* In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
* interrupts to detect TSF updates only.
*/
void
-ath5k_beacon_config(struct ath5k_softc *sc)
+ath5k_beacon_config(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
unsigned long flags;
- spin_lock_irqsave(&sc->block, flags);
- sc->bmisscount = 0;
- sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
+ spin_lock_irqsave(&ah->block, flags);
+ ah->bmisscount = 0;
+ ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
- if (sc->enable_beacon) {
+ if (ah->enable_beacon) {
/*
* In IBSS mode we use a self-linked tx descriptor and let the
* hardware send the beacons automatically. We have to load it
@@ -2075,50 +2063,50 @@ ath5k_beacon_config(struct ath5k_softc *sc)
* We use the SWBA interrupt only to keep track of the beacon
* timers in order to detect automatic TSF updates.
*/
- ath5k_beaconq_config(sc);
+ ath5k_beaconq_config(ah);
- sc->imask |= AR5K_INT_SWBA;
+ ah->imask |= AR5K_INT_SWBA;
- if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+ if (ah->opmode == NL80211_IFTYPE_ADHOC) {
if (ath5k_hw_hasveol(ah))
- ath5k_beacon_send(sc);
+ ath5k_beacon_send(ah);
} else
- ath5k_beacon_update_timers(sc, -1);
+ ath5k_beacon_update_timers(ah, -1);
} else {
- ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq);
+ ath5k_hw_stop_beacon_queue(ah, ah->bhalq);
}
- ath5k_hw_set_imr(ah, sc->imask);
+ ath5k_hw_set_imr(ah, ah->imask);
mmiowb();
- spin_unlock_irqrestore(&sc->block, flags);
+ spin_unlock_irqrestore(&ah->block, flags);
}
static void ath5k_tasklet_beacon(unsigned long data)
{
- struct ath5k_softc *sc = (struct ath5k_softc *) data;
+ struct ath5k_hw *ah = (struct ath5k_hw *) data;
/*
* Software beacon alert--time to send a beacon.
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
- * transmission time) in order to detect wether
+ * transmission time) in order to detect whether
* automatic TSF updates happened.
*/
- if (sc->opmode == NL80211_IFTYPE_ADHOC) {
- /* XXX: only if VEOL suppported */
- u64 tsf = ath5k_hw_get_tsf64(sc->ah);
- sc->nexttbtt += sc->bintval;
- ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ if (ah->opmode == NL80211_IFTYPE_ADHOC) {
+ /* XXX: only if VEOL supported */
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ ah->nexttbtt += ah->bintval;
+ ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
"SWBA nexttbtt: %x hw_tu: %x "
"TSF: %llx\n",
- sc->nexttbtt,
+ ah->nexttbtt,
TSF_TO_TU(tsf),
(unsigned long long) tsf);
} else {
- spin_lock(&sc->block);
- ath5k_beacon_send(sc);
- spin_unlock(&sc->block);
+ spin_lock(&ah->block);
+ ath5k_beacon_send(ah);
+ spin_unlock(&ah->block);
}
}
@@ -2135,12 +2123,12 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
/* run ANI only when full calibration is not active */
ah->ah_cal_next_ani = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
- tasklet_schedule(&ah->ah_sc->ani_tasklet);
+ tasklet_schedule(&ah->ani_tasklet);
} else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
ah->ah_cal_next_full = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
- tasklet_schedule(&ah->ah_sc->calib);
+ tasklet_schedule(&ah->calib);
}
/* we could use SWI to generate enough interrupts to meet our
* calibration interval requirements, if necessary:
@@ -2148,44 +2136,43 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
}
static void
-ath5k_schedule_rx(struct ath5k_softc *sc)
+ath5k_schedule_rx(struct ath5k_hw *ah)
{
- sc->rx_pending = true;
- tasklet_schedule(&sc->rxtq);
+ ah->rx_pending = true;
+ tasklet_schedule(&ah->rxtq);
}
static void
-ath5k_schedule_tx(struct ath5k_softc *sc)
+ath5k_schedule_tx(struct ath5k_hw *ah)
{
- sc->tx_pending = true;
- tasklet_schedule(&sc->txtq);
+ ah->tx_pending = true;
+ tasklet_schedule(&ah->txtq);
}
-irqreturn_t
+static irqreturn_t
ath5k_intr(int irq, void *dev_id)
{
- struct ath5k_softc *sc = dev_id;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = dev_id;
enum ath5k_int status;
unsigned int counter = 1000;
- if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
+ if (unlikely(test_bit(ATH_STAT_INVALID, ah->status) ||
((ath5k_get_bus_type(ah) != ATH_AHB) &&
!ath5k_hw_is_intr_pending(ah))))
return IRQ_NONE;
do {
ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
- ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
- status, sc->imask);
+ ATH5K_DBG(ah, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
+ status, ah->imask);
if (unlikely(status & AR5K_INT_FATAL)) {
/*
* Fatal errors are unrecoverable.
* Typically these are caused by DMA errors.
*/
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"fatal int, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
} else if (unlikely(status & AR5K_INT_RXORN)) {
/*
* Receive buffers are full. Either the bus is busy or
@@ -2196,45 +2183,44 @@ ath5k_intr(int irq, void *dev_id)
* We don't know exactly which versions need a reset -
* this guess is copied from the HAL.
*/
- sc->stats.rxorn_intr++;
+ ah->stats.rxorn_intr++;
if (ah->ah_mac_srev < AR5K_SREV_AR5212) {
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"rx overrun, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
- }
- else
- ath5k_schedule_rx(sc);
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
+ } else
+ ath5k_schedule_rx(ah);
} else {
- if (status & AR5K_INT_SWBA) {
- tasklet_hi_schedule(&sc->beacontq);
- }
+ if (status & AR5K_INT_SWBA)
+ tasklet_hi_schedule(&ah->beacontq);
+
if (status & AR5K_INT_RXEOL) {
/*
* NB: the hardware should re-read the link when
* RXE bit is written, but it doesn't work at
* least on older hardware revs.
*/
- sc->stats.rxeol_intr++;
+ ah->stats.rxeol_intr++;
}
if (status & AR5K_INT_TXURN) {
/* bump tx trigger level */
ath5k_hw_update_tx_triglevel(ah, true);
}
if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
- ath5k_schedule_rx(sc);
+ ath5k_schedule_rx(ah);
if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
| AR5K_INT_TXERR | AR5K_INT_TXEOL))
- ath5k_schedule_tx(sc);
+ ath5k_schedule_tx(ah);
if (status & AR5K_INT_BMISS) {
/* TODO */
}
if (status & AR5K_INT_MIB) {
- sc->stats.mib_intr++;
+ ah->stats.mib_intr++;
ath5k_hw_update_mib_counters(ah);
ath5k_ani_mib_intr(ah);
}
if (status & AR5K_INT_GPIO)
- tasklet_schedule(&sc->rf_kill.toggleq);
+ tasklet_schedule(&ah->rf_kill.toggleq);
}
@@ -2243,11 +2229,11 @@ ath5k_intr(int irq, void *dev_id)
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
- if (sc->rx_pending || sc->tx_pending)
- ath5k_set_current_imask(sc);
+ if (ah->rx_pending || ah->tx_pending)
+ ath5k_set_current_imask(ah);
if (unlikely(!counter))
- ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
+ ATH5K_WARN(ah, "too many interrupts, giving up for now\n");
ath5k_intr_calibration_poll(ah);
@@ -2261,28 +2247,27 @@ ath5k_intr(int irq, void *dev_id)
static void
ath5k_tasklet_calibrate(unsigned long data)
{
- struct ath5k_softc *sc = (void *)data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = (void *)data;
/* Only full calibration for now */
ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
- ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
- ieee80211_frequency_to_channel(sc->curchan->center_freq),
- sc->curchan->hw_value);
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
+ ieee80211_frequency_to_channel(ah->curchan->center_freq),
+ ah->curchan->hw_value);
if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
/*
* Rfgain is out of bounds, reset the chip
* to load new gain values.
*/
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "calibration, resetting\n");
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
}
- if (ath5k_hw_phy_calibrate(ah, sc->curchan))
- ATH5K_ERR(sc, "calibration of channel %u failed\n",
+ if (ath5k_hw_phy_calibrate(ah, ah->curchan))
+ ATH5K_ERR(ah, "calibration of channel %u failed\n",
ieee80211_frequency_to_channel(
- sc->curchan->center_freq));
+ ah->curchan->center_freq));
/* Noise floor calibration interrupts rx/tx path while I/Q calibration
* doesn't.
@@ -2301,8 +2286,7 @@ ath5k_tasklet_calibrate(unsigned long data)
static void
ath5k_tasklet_ani(unsigned long data)
{
- struct ath5k_softc *sc = (void *)data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = (void *)data;
ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
ath5k_ani_calibration(ah);
@@ -2313,21 +2297,21 @@ ath5k_tasklet_ani(unsigned long data)
static void
ath5k_tx_complete_poll_work(struct work_struct *work)
{
- struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+ struct ath5k_hw *ah = container_of(work, struct ath5k_hw,
tx_complete_work.work);
struct ath5k_txq *txq;
int i;
bool needreset = false;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
- if (sc->txqs[i].setup) {
- txq = &sc->txqs[i];
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+ if (ah->txqs[i].setup) {
+ txq = &ah->txqs[i];
spin_lock_bh(&txq->lock);
if (txq->txq_len > 1) {
if (txq->txq_poll_mark) {
- ATH5K_DBG(sc, ATH5K_DEBUG_XMIT,
+ ATH5K_DBG(ah, ATH5K_DEBUG_XMIT,
"TX queue stuck %d\n",
txq->qnum);
needreset = true;
@@ -2343,14 +2327,14 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
}
if (needreset) {
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"TX queues stuck, resetting\n");
- ath5k_reset(sc, NULL, true);
+ ath5k_reset(ah, NULL, true);
}
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+ ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
}
@@ -2359,16 +2343,16 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
* Initialization routines *
\*************************/
-int
-ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
+int __devinit
+ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
{
- struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_hw *hw = ah->hw;
struct ath_common *common;
int ret;
int csz;
/* Initialize driver private data */
- SET_IEEE80211_DEV(hw, sc->dev);
+ SET_IEEE80211_DEV(hw, ah->dev);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
@@ -2391,39 +2375,30 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
* Mark the device as detached to avoid processing
* interrupts until setup is complete.
*/
- __set_bit(ATH_STAT_INVALID, sc->status);
+ __set_bit(ATH_STAT_INVALID, ah->status);
- sc->opmode = NL80211_IFTYPE_STATION;
- sc->bintval = 1000;
- mutex_init(&sc->lock);
- spin_lock_init(&sc->rxbuflock);
- spin_lock_init(&sc->txbuflock);
- spin_lock_init(&sc->block);
- spin_lock_init(&sc->irqlock);
+ ah->opmode = NL80211_IFTYPE_STATION;
+ ah->bintval = 1000;
+ mutex_init(&ah->lock);
+ spin_lock_init(&ah->rxbuflock);
+ spin_lock_init(&ah->txbuflock);
+ spin_lock_init(&ah->block);
+ spin_lock_init(&ah->irqlock);
/* Setup interrupt handler */
- ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+ ret = request_irq(ah->irq, ath5k_intr, IRQF_SHARED, "ath", ah);
if (ret) {
- ATH5K_ERR(sc, "request_irq failed\n");
+ ATH5K_ERR(ah, "request_irq failed\n");
goto err;
}
- /* If we passed the test, malloc an ath5k_hw struct */
- sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
- if (!sc->ah) {
- ret = -ENOMEM;
- ATH5K_ERR(sc, "out of memory\n");
- goto err_irq;
- }
-
- sc->ah->ah_sc = sc;
- sc->ah->ah_iobase = sc->iobase;
- common = ath5k_hw_common(sc->ah);
+ common = ath5k_hw_common(ah);
common->ops = &ath5k_common_ops;
common->bus_ops = bus_ops;
- common->ah = sc->ah;
+ common->ah = ah;
common->hw = hw;
- common->priv = sc;
+ common->priv = ah;
+ common->clockrate = 40;
/*
* Cache line size is used to size and align various
@@ -2435,12 +2410,12 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
spin_lock_init(&common->cc_lock);
/* Initialize device */
- ret = ath5k_hw_init(sc);
+ ret = ath5k_hw_init(ah);
if (ret)
- goto err_free_ah;
+ goto err_irq;
/* set up multi-rate retry capabilities */
- if (sc->ah->ah_version == AR5K_AR5212) {
+ if (ah->ah_version == AR5K_AR5212) {
hw->max_rates = 4;
hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT,
AR5K_INIT_RETRY_LONG);
@@ -2453,77 +2428,74 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
if (ret)
goto err_ah;
- ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
- sc->ah->ah_mac_srev,
- sc->ah->ah_phy_revision);
+ ATH5K_INFO(ah, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_MAC, ah->ah_mac_srev),
+ ah->ah_mac_srev,
+ ah->ah_phy_revision);
- if (!sc->ah->ah_single_chip) {
+ if (!ah->ah_single_chip) {
/* Single chip radio (!RF5111) */
- if (sc->ah->ah_radio_5ghz_revision &&
- !sc->ah->ah_radio_2ghz_revision) {
+ if (ah->ah_radio_5ghz_revision &&
+ !ah->ah_radio_2ghz_revision) {
/* No 5GHz support -> report 2GHz radio */
if (!test_bit(AR5K_MODE_11A,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
/* No 2GHz support (5110 and some
- * 5Ghz only cards) -> report 5Ghz radio */
+ * 5GHz only cards) -> report 5GHz radio */
} else if (!test_bit(AR5K_MODE_11B,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
/* Multiband radio */
} else {
- ATH5K_INFO(sc, "RF%s multiband radio found"
+ ATH5K_INFO(ah, "RF%s multiband radio found"
" (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
}
}
/* Multi chip radio (RF5111 - RF2111) ->
* report both 2GHz/5GHz radios */
- else if (sc->ah->ah_radio_5ghz_revision &&
- sc->ah->ah_radio_2ghz_revision){
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ else if (ah->ah_radio_5ghz_revision &&
+ ah->ah_radio_2ghz_revision) {
+ ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ah->ah_radio_5ghz_revision),
+ ah->ah_radio_5ghz_revision);
+ ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_2ghz_revision),
- sc->ah->ah_radio_2ghz_revision);
+ ah->ah_radio_2ghz_revision),
+ ah->ah_radio_2ghz_revision);
}
}
- ath5k_debug_init_device(sc);
+ ath5k_debug_init_device(ah);
/* ready to process interrupts */
- __clear_bit(ATH_STAT_INVALID, sc->status);
+ __clear_bit(ATH_STAT_INVALID, ah->status);
return 0;
err_ah:
- ath5k_hw_deinit(sc->ah);
-err_free_ah:
- kfree(sc->ah);
+ ath5k_hw_deinit(ah);
err_irq:
- free_irq(sc->irq, sc);
+ free_irq(ah->irq, ah);
err:
return ret;
}
static int
-ath5k_stop_locked(struct ath5k_softc *sc)
+ath5k_stop_locked(struct ath5k_hw *ah)
{
- struct ath5k_hw *ah = sc->ah;
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
- test_bit(ATH_STAT_INVALID, sc->status));
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "invalid %u\n",
+ test_bit(ATH_STAT_INVALID, ah->status));
/*
* Shutdown the hardware and driver:
@@ -2540,37 +2512,36 @@ ath5k_stop_locked(struct ath5k_softc *sc)
* Note that some of this work is not possible if the
* hardware is gone (invalid).
*/
- ieee80211_stop_queues(sc->hw);
+ ieee80211_stop_queues(ah->hw);
- if (!test_bit(ATH_STAT_INVALID, sc->status)) {
- ath5k_led_off(sc);
+ if (!test_bit(ATH_STAT_INVALID, ah->status)) {
+ ath5k_led_off(ah);
ath5k_hw_set_imr(ah, 0);
- synchronize_irq(sc->irq);
- ath5k_rx_stop(sc);
+ synchronize_irq(ah->irq);
+ ath5k_rx_stop(ah);
ath5k_hw_dma_stop(ah);
- ath5k_drain_tx_buffs(sc);
+ ath5k_drain_tx_buffs(ah);
ath5k_hw_phy_disable(ah);
}
return 0;
}
-int
-ath5k_init_hw(struct ath5k_softc *sc)
+int ath5k_start(struct ieee80211_hw *hw)
{
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_common *common = ath5k_hw_common(ah);
int ret, i;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "mode %d\n", ah->opmode);
/*
* Stop anything previously setup. This is safe
* no matter this is the first time through or not.
*/
- ath5k_stop_locked(sc);
+ ath5k_stop_locked(ah);
/*
* The basic interface to setting the hardware in a good
@@ -2579,12 +2550,12 @@ ath5k_init_hw(struct ath5k_softc *sc)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
- sc->curchan = sc->hw->conf.channel;
- sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+ ah->curchan = ah->hw->conf.channel;
+ ah->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
- ret = ath5k_reset(sc, NULL, false);
+ ret = ath5k_reset(ah, NULL, false);
if (ret)
goto done;
@@ -2601,29 +2572,29 @@ ath5k_init_hw(struct ath5k_softc *sc)
* rate */
ah->ah_ack_bitrate_high = true;
- for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
- sc->bslot[i] = NULL;
+ for (i = 0; i < ARRAY_SIZE(ah->bslot); i++)
+ ah->bslot[i] = NULL;
ret = 0;
done:
mmiowb();
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+ ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
return ret;
}
-static void stop_tasklets(struct ath5k_softc *sc)
+static void ath5k_stop_tasklets(struct ath5k_hw *ah)
{
- sc->rx_pending = false;
- sc->tx_pending = false;
- tasklet_kill(&sc->rxtq);
- tasklet_kill(&sc->txtq);
- tasklet_kill(&sc->calib);
- tasklet_kill(&sc->beacontq);
- tasklet_kill(&sc->ani_tasklet);
+ ah->rx_pending = false;
+ ah->tx_pending = false;
+ tasklet_kill(&ah->rxtq);
+ tasklet_kill(&ah->txtq);
+ tasklet_kill(&ah->calib);
+ tasklet_kill(&ah->beacontq);
+ tasklet_kill(&ah->ani_tasklet);
}
/*
@@ -2632,14 +2603,14 @@ static void stop_tasklets(struct ath5k_softc *sc)
* if another thread does a system call and the thread doing the
* stop is preempted).
*/
-int
-ath5k_stop_hw(struct ath5k_softc *sc)
+void ath5k_stop(struct ieee80211_hw *hw)
{
+ struct ath5k_hw *ah = hw->priv;
int ret;
- mutex_lock(&sc->lock);
- ret = ath5k_stop_locked(sc);
- if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
+ mutex_lock(&ah->lock);
+ ret = ath5k_stop_locked(ah);
+ if (ret == 0 && !test_bit(ATH_STAT_INVALID, ah->status)) {
/*
* Don't set the card in full sleep mode!
*
@@ -2660,82 +2631,78 @@ ath5k_stop_hw(struct ath5k_softc *sc)
* and Sam's HAL do anyway). Instead Perform a full reset
* on the device (same as initial state after attach) and
* leave it idle (keep MAC/BB on warm reset) */
- ret = ath5k_hw_on_hold(sc->ah);
+ ret = ath5k_hw_on_hold(ah);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"putting device to sleep\n");
}
mmiowb();
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
- stop_tasklets(sc);
+ ath5k_stop_tasklets(ah);
- cancel_delayed_work_sync(&sc->tx_complete_work);
+ cancel_delayed_work_sync(&ah->tx_complete_work);
- ath5k_rfkill_hw_stop(sc->ah);
-
- return ret;
+ ath5k_rfkill_hw_stop(ah);
}
/*
* Reset the hardware. If chan is not NULL, then also pause rx/tx
* and change to the given channel.
*
- * This should be called with sc->lock.
+ * This should be called with ah->lock.
*/
static int
-ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
bool skip_pcu)
{
- struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
int ret, ani_mode;
bool fast;
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n");
ath5k_hw_set_imr(ah, 0);
- synchronize_irq(sc->irq);
- stop_tasklets(sc);
+ synchronize_irq(ah->irq);
+ ath5k_stop_tasklets(ah);
/* Save ani mode and disable ANI during
* reset. If we don't we might get false
* PHY error interrupts. */
- ani_mode = ah->ah_sc->ani_state.ani_mode;
+ ani_mode = ah->ani_state.ani_mode;
ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
/* We are going to empty hw queues
* so we should also free any remaining
* tx buffers */
- ath5k_drain_tx_buffs(sc);
+ ath5k_drain_tx_buffs(ah);
if (chan)
- sc->curchan = chan;
+ ah->curchan = chan;
fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0;
- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast,
- skip_pcu);
+ ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu);
if (ret) {
- ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
+ ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret);
goto err;
}
- ret = ath5k_rx_start(sc);
+ ret = ath5k_rx_start(ah);
if (ret) {
- ATH5K_ERR(sc, "can't start recv logic\n");
+ ATH5K_ERR(ah, "can't start recv logic\n");
goto err;
}
ath5k_ani_init(ah, ani_mode);
- ah->ah_cal_next_full = jiffies;
+ ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100);
ah->ah_cal_next_ani = jiffies;
ah->ah_cal_next_nf = jiffies;
ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
/* clear survey data and cycle counters */
- memset(&sc->survey, 0, sizeof(sc->survey));
+ memset(&ah->survey, 0, sizeof(ah->survey));
spin_lock_bh(&common->cc_lock);
ath_hw_cycle_counters_update(common);
memset(&common->cc_survey, 0, sizeof(common->cc_survey));
@@ -2751,12 +2718,12 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
*
* XXX needed?
*/
-/* ath5k_chan_change(sc, c); */
+/* ath5k_chan_change(ah, c); */
- ath5k_beacon_config(sc);
+ ath5k_beacon_config(ah);
/* intrs are enabled by ath5k_beacon_config */
- ieee80211_wake_queues(sc->hw);
+ ieee80211_wake_queues(ah->hw);
return 0;
err:
@@ -2765,20 +2732,19 @@ err:
static void ath5k_reset_work(struct work_struct *work)
{
- struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+ struct ath5k_hw *ah = container_of(work, struct ath5k_hw,
reset_work);
- mutex_lock(&sc->lock);
- ath5k_reset(sc, NULL, true);
- mutex_unlock(&sc->lock);
+ mutex_lock(&ah->lock);
+ ath5k_reset(ah, NULL, true);
+ mutex_unlock(&ah->lock);
}
-static int
+static int __devinit
ath5k_init(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
struct ath5k_txq *txq;
u8 mac[ETH_ALEN] = {};
@@ -2797,26 +2763,26 @@ ath5k_init(struct ieee80211_hw *hw)
if (ret < 0)
goto err;
if (ret > 0)
- __set_bit(ATH_STAT_MRRETRY, sc->status);
+ __set_bit(ATH_STAT_MRRETRY, ah->status);
/*
* Collect the channel list. The 802.11 layer
- * is resposible for filtering this list based
+ * is responsible for filtering this list based
* on settings like the phy mode and regulatory
* domain restrictions.
*/
ret = ath5k_setup_bands(hw);
if (ret) {
- ATH5K_ERR(sc, "can't get channels\n");
+ ATH5K_ERR(ah, "can't get channels\n");
goto err;
}
/*
* Allocate tx+rx descriptors and populate the lists.
*/
- ret = ath5k_desc_alloc(sc);
+ ret = ath5k_desc_alloc(ah);
if (ret) {
- ATH5K_ERR(sc, "can't allocate descriptors\n");
+ ATH5K_ERR(ah, "can't allocate descriptors\n");
goto err;
}
@@ -2828,14 +2794,14 @@ ath5k_init(struct ieee80211_hw *hw)
*/
ret = ath5k_beaconq_setup(ah);
if (ret < 0) {
- ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
+ ATH5K_ERR(ah, "can't setup a beacon xmit queue\n");
goto err_desc;
}
- sc->bhalq = ret;
- sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
- if (IS_ERR(sc->cabq)) {
- ATH5K_ERR(sc, "can't setup cab queue\n");
- ret = PTR_ERR(sc->cabq);
+ ah->bhalq = ret;
+ ah->cabq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_CAB, 0);
+ if (IS_ERR(ah->cabq)) {
+ ATH5K_ERR(ah, "can't setup cab queue\n");
+ ret = PTR_ERR(ah->cabq);
goto err_bhal;
}
@@ -2844,97 +2810,97 @@ ath5k_init(struct ieee80211_hw *hw)
if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) {
/* This order matches mac80211's queue priority, so we can
* directly use the mac80211 queue number without any mapping */
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
hw->queues = 4;
} else {
/* older hardware (5210) can only support one data queue */
- txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+ txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
if (IS_ERR(txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ATH5K_ERR(ah, "can't setup xmit queue\n");
ret = PTR_ERR(txq);
goto err_queues;
}
hw->queues = 1;
}
- tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
- tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
- tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
- tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
- tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
+ tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah);
+ tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah);
+ tasklet_init(&ah->calib, ath5k_tasklet_calibrate, (unsigned long)ah);
+ tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah);
+ tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah);
- INIT_WORK(&sc->reset_work, ath5k_reset_work);
- INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
+ INIT_WORK(&ah->reset_work, ath5k_reset_work);
+ INIT_DELAYED_WORK(&ah->tx_complete_work, ath5k_tx_complete_poll_work);
ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
if (ret) {
- ATH5K_ERR(sc, "unable to read address from EEPROM\n");
+ ATH5K_ERR(ah, "unable to read address from EEPROM\n");
goto err_queues;
}
SET_IEEE80211_PERM_ADDR(hw, mac);
- memcpy(&sc->lladdr, mac, ETH_ALEN);
+ memcpy(&ah->lladdr, mac, ETH_ALEN);
/* All MAC address bits matter for ACKs */
- ath5k_update_bssid_mask_and_opmode(sc, NULL);
+ ath5k_update_bssid_mask_and_opmode(ah, NULL);
regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
if (ret) {
- ATH5K_ERR(sc, "can't initialize regulatory system\n");
+ ATH5K_ERR(ah, "can't initialize regulatory system\n");
goto err_queues;
}
ret = ieee80211_register_hw(hw);
if (ret) {
- ATH5K_ERR(sc, "can't register ieee80211 hw\n");
+ ATH5K_ERR(ah, "can't register ieee80211 hw\n");
goto err_queues;
}
if (!ath_is_world_regd(regulatory))
regulatory_hint(hw->wiphy, regulatory->alpha2);
- ath5k_init_leds(sc);
+ ath5k_init_leds(ah);
- ath5k_sysfs_register(sc);
+ ath5k_sysfs_register(ah);
return 0;
err_queues:
- ath5k_txq_release(sc);
+ ath5k_txq_release(ah);
err_bhal:
- ath5k_hw_release_tx_queue(ah, sc->bhalq);
+ ath5k_hw_release_tx_queue(ah, ah->bhalq);
err_desc:
- ath5k_desc_free(sc);
+ ath5k_desc_free(ah);
err:
return ret;
}
void
-ath5k_deinit_softc(struct ath5k_softc *sc)
+ath5k_deinit_softc(struct ath5k_hw *ah)
{
- struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_hw *hw = ah->hw;
/*
* NB: the order of these is important:
@@ -2950,23 +2916,23 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
* Other than that, it's straightforward...
*/
ieee80211_unregister_hw(hw);
- ath5k_desc_free(sc);
- ath5k_txq_release(sc);
- ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
- ath5k_unregister_leds(sc);
+ ath5k_desc_free(ah);
+ ath5k_txq_release(ah);
+ ath5k_hw_release_tx_queue(ah, ah->bhalq);
+ ath5k_unregister_leds(ah);
- ath5k_sysfs_unregister(sc);
+ ath5k_sysfs_unregister(ah);
/*
* NB: can't reclaim these until after ieee80211_ifdetach
* returns because we'll get called back to reclaim node
* state and potentially want to use them.
*/
- ath5k_hw_deinit(sc->ah);
- free_irq(sc->irq, sc);
+ ath5k_hw_deinit(ah);
+ free_irq(ah->irq, ah);
}
bool
-ath_any_vif_assoc(struct ath5k_softc *sc)
+ath5k_any_vif_assoc(struct ath5k_hw *ah)
{
struct ath5k_vif_iter_data iter_data;
iter_data.hw_macaddr = NULL;
@@ -2974,16 +2940,15 @@ ath_any_vif_assoc(struct ath5k_softc *sc)
iter_data.need_set_hw_addr = false;
iter_data.found_active = true;
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+ ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
&iter_data);
return iter_data.any_assoc;
}
void
-set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
u32 rfilt;
rfilt = ath5k_hw_get_rx_filter(ah);
if (enable)
@@ -2991,5 +2956,5 @@ set_beacon_filter(struct ieee80211_hw *hw, bool enable)
else
rfilt &= ~AR5K_RX_FILTER_BEACON;
ath5k_hw_set_rx_filter(ah, rfilt);
- sc->filter_flags = rfilt;
+ ah->filter_flags = rfilt;
}
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index b294f3305011..a81f28d5bddc 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -45,23 +45,13 @@
#include <linux/list.h>
#include <linux/wireless.h>
#include <linux/if_ether.h>
-#include <linux/leds.h>
#include <linux/rfkill.h>
#include <linux/workqueue.h>
#include "ath5k.h"
-#include "debug.h"
-#include "ani.h"
-
#include "../regd.h"
#include "../ath.h"
-#define ATH_RXBUF 40 /* number of RX buffers */
-#define ATH_TXBUF 200 /* number of TX buffers */
-#define ATH_BCBUF 4 /* number of beacon buffers */
-#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
-#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
-
struct ath5k_buf {
struct list_head list;
struct ath5k_desc *desc; /* virtual addr of desc */
@@ -70,95 +60,6 @@ struct ath5k_buf {
dma_addr_t skbaddr;/* physical addr of skb data */
};
-/*
- * Data transmit queue state. One of these exists for each
- * hardware transmit queue. Packets sent to us from above
- * are assigned to queues based on their priority. Not all
- * devices support a complete set of hardware transmit queues.
- * For those devices the array sc_ac2q will map multiple
- * priorities to fewer hardware queues (typically all to one
- * hardware queue).
- */
-struct ath5k_txq {
- unsigned int qnum; /* hardware q number */
- u32 *link; /* link ptr in last TX desc */
- struct list_head q; /* transmit queue */
- spinlock_t lock; /* lock on q and link */
- bool setup;
- int txq_len; /* number of queued buffers */
- int txq_max; /* max allowed num of queued buffers */
- bool txq_poll_mark;
- unsigned int txq_stuck; /* informational counter */
-};
-
-#define ATH5K_LED_MAX_NAME_LEN 31
-
-/*
- * State for LED triggers
- */
-struct ath5k_led
-{
- char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */
- struct ath5k_softc *sc; /* driver state */
- struct led_classdev led_dev; /* led classdev */
-};
-
-/* Rfkill */
-struct ath5k_rfkill {
- /* GPIO PIN for rfkill */
- u16 gpio;
- /* polarity of rfkill GPIO PIN */
- bool polarity;
- /* RFKILL toggle tasklet */
- struct tasklet_struct toggleq;
-};
-
-/* statistics */
-struct ath5k_statistics {
- /* antenna use */
- unsigned int antenna_rx[5]; /* frames count per antenna RX */
- unsigned int antenna_tx[5]; /* frames count per antenna TX */
-
- /* frame errors */
- unsigned int rx_all_count; /* all RX frames, including errors */
- unsigned int tx_all_count; /* all TX frames, including errors */
- unsigned int rx_bytes_count; /* all RX bytes, including errored pks
- * and the MAC headers for each packet
- */
- unsigned int tx_bytes_count; /* all TX bytes, including errored pkts
- * and the MAC headers and padding for
- * each packet.
- */
- unsigned int rxerr_crc;
- unsigned int rxerr_phy;
- unsigned int rxerr_phy_code[32];
- unsigned int rxerr_fifo;
- unsigned int rxerr_decrypt;
- unsigned int rxerr_mic;
- unsigned int rxerr_proc;
- unsigned int rxerr_jumbo;
- unsigned int txerr_retry;
- unsigned int txerr_fifo;
- unsigned int txerr_filt;
-
- /* MIB counters */
- unsigned int ack_fail;
- unsigned int rts_fail;
- unsigned int rts_ok;
- unsigned int fcs_error;
- unsigned int beacons;
-
- unsigned int mib_intr;
- unsigned int rxorn_intr;
- unsigned int rxeol_intr;
-};
-
-#if CHAN_DEBUG
-#define ATH_CHAN_MAX (26+26+26+200+200)
-#else
-#define ATH_CHAN_MAX (14+14+14+252+20)
-#endif
-
struct ath5k_vif {
bool assoc; /* are we associated or not */
enum nl80211_iftype opmode;
@@ -167,104 +68,6 @@ struct ath5k_vif {
u8 lladdr[ETH_ALEN];
};
-/* Software Carrier, keeps track of the driver state
- * associated with an instance of a device */
-struct ath5k_softc {
- struct pci_dev *pdev;
- struct device *dev; /* for dma mapping */
- int irq;
- u16 devid;
- void __iomem *iobase; /* address of the device */
- struct mutex lock; /* dev-level lock */
- struct ieee80211_hw *hw; /* IEEE 802.11 common */
- struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
- struct ieee80211_channel channels[ATH_CHAN_MAX];
- struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
- s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
- enum nl80211_iftype opmode;
- struct ath5k_hw *ah; /* Atheros HW */
-
-#ifdef CONFIG_ATH5K_DEBUG
- struct ath5k_dbg_info debug; /* debug info */
-#endif /* CONFIG_ATH5K_DEBUG */
-
- struct ath5k_buf *bufptr; /* allocated buffer ptr */
- struct ath5k_desc *desc; /* TX/RX descriptors */
- dma_addr_t desc_daddr; /* DMA (physical) address */
- size_t desc_len; /* size of TX/RX descriptors */
-
- DECLARE_BITMAP(status, 6);
-#define ATH_STAT_INVALID 0 /* disable hardware accesses */
-#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
-#define ATH_STAT_PROMISC 2
-#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
-#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
-#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */
-
- unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
- struct ieee80211_channel *curchan; /* current h/w channel */
-
- u16 nvifs;
-
- enum ath5k_int imask; /* interrupt mask copy */
-
- spinlock_t irqlock;
- 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 */
- led_on; /* pin setting for LED on */
-
- 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 */
- struct tasklet_struct rxtq; /* rx intr tasklet */
- struct ath5k_led rx_led; /* rx led */
-
- struct list_head txbuf; /* transmit buffer */
- spinlock_t txbuflock;
- unsigned int txbuf_len; /* buf count in txbuf list */
- struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
- struct tasklet_struct txtq; /* tx intr tasklet */
- struct ath5k_led tx_led; /* tx led */
-
- struct ath5k_rfkill rf_kill;
-
- struct tasklet_struct calib; /* calibration tasklet */
-
- spinlock_t block; /* protects beacon */
- struct tasklet_struct beacontq; /* beacon intr tasklet */
- struct list_head bcbuf; /* beacon buffer */
- struct ieee80211_vif *bslot[ATH_BCBUF];
- u16 num_ap_vifs;
- u16 num_adhoc_vifs;
- unsigned int bhalq, /* SW q for outgoing beacons */
- bmisscount, /* missed beacon transmits */
- bintval, /* beacon interval in TU */
- bsent;
- unsigned int nexttbtt; /* next beacon time in TU */
- struct ath5k_txq *cabq; /* content after beacon */
-
- int power_level; /* Requested tx power in dbm */
- bool assoc; /* associate state */
- bool enable_beacon; /* true if beacons are on */
-
- struct ath5k_statistics stats;
-
- struct ath5k_ani_state ani_state;
- struct tasklet_struct ani_tasklet; /* ANI calibration */
-
- struct delayed_work tx_complete_work;
-
- struct survey_info survey; /* collected survey info */
-};
-
struct ath5k_vif_iter_data {
const u8 *hw_macaddr;
u8 mask[ETH_ALEN];
@@ -278,9 +81,10 @@ struct ath5k_vif_iter_data {
void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
-#define ath5k_hw_hasbssidmask(_ah) \
- (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
-#define ath5k_hw_hasveol(_ah) \
- (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
+/* Check whether BSSID mask is supported */
+#define ath5k_hw_hasbssidmask(_ah) (ah->ah_version == AR5K_AR5212)
+
+/* Check whether virtual EOL is supported */
+#define ath5k_hw_hasveol(_ah) (ah->ah_version != AR5K_AR5210)
#endif
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index 7dd88e1c3ff8..eefe670e28a7 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -52,8 +52,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
__set_bit(AR5K_MODE_11A, caps->cap_mode);
} else {
/*
- * XXX The tranceiver supports frequencies from 4920 to 6100GHz
- * XXX and from 2312 to 2732GHz. There are problems with the
+ * XXX The transceiver supports frequencies from 4920 to 6100MHz
+ * XXX and from 2312 to 2732MHz. There are problems with the
* XXX current ieee80211 implementation because the IEEE
* XXX channel mapping does not support negative channel
* XXX numbers (2312MHz is channel -19). Of course, this
@@ -112,51 +112,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
return 0;
}
-/* Main function used by the driver part to check caps */
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
- enum ath5k_capability_type cap_type,
- u32 capability, u32 *result)
-{
- switch (cap_type) {
- case AR5K_CAP_NUM_TXQUEUES:
- if (result) {
- if (ah->ah_version == AR5K_AR5210)
- *result = AR5K_NUM_TX_QUEUES_NOQCU;
- else
- *result = AR5K_NUM_TX_QUEUES;
- goto yes;
- }
- case AR5K_CAP_VEOL:
- goto yes;
- case AR5K_CAP_COMPRESSION:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- case AR5K_CAP_BURST:
- goto yes;
- case AR5K_CAP_TPC:
- goto yes;
- case AR5K_CAP_BSSIDMASK:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- case AR5K_CAP_XR:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- default:
- goto no;
- }
-
-no:
- return -EINVAL;
-yes:
- return 0;
-}
-
/*
* TODO: Following functions should be part of a new function
* set_capability
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 0bf7313b8a17..ccca724de173 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -157,10 +157,10 @@ static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
static int reg_show(struct seq_file *seq, void *p)
{
- struct ath5k_softc *sc = seq->private;
+ struct ath5k_hw *ah = seq->private;
struct reg *r = p;
seq_printf(seq, "%-25s0x%08x\n", r->name,
- ath5k_hw_reg_read(sc->ah, r->addr));
+ ath5k_hw_reg_read(ah, r->addr));
return 0;
}
@@ -197,43 +197,42 @@ static const struct file_operations fops_registers = {
static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = file->private_data;
char buf[500];
unsigned int len = 0;
unsigned int v;
u64 tsf;
- v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_BEACON);
+ len += snprintf(buf + len, sizeof(buf) - len,
"%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
"AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
(v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
- "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
+ "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
- "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
+ "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER0 (TBTT)", v, v);
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER1 (DMA)", v, v >> 3);
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER2 (SWBA)", v, v >> 3);
- v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
- len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
+ len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
"AR5K_TIMER3 (ATIM)", v, v);
- tsf = ath5k_hw_get_tsf64(sc->ah);
- len += snprintf(buf+len, sizeof(buf)-len,
+ tsf = ath5k_hw_get_tsf64(ah);
+ len += snprintf(buf + len, sizeof(buf) - len,
"TSF\t\t0x%016llx\tTU: %08x\n",
(unsigned long long)tsf, TSF_TO_TU(tsf));
@@ -247,8 +246,7 @@ static ssize_t write_file_beacon(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = file->private_data;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
@@ -279,9 +277,9 @@ static ssize_t write_file_reset(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
- ieee80211_queue_work(sc->hw, &sc->reset_work);
+ struct ath5k_hw *ah = file->private_data;
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
+ ieee80211_queue_work(ah->hw, &ah->reset_work);
return count;
}
@@ -318,23 +316,23 @@ static const struct {
static ssize_t read_file_debug(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
unsigned int i;
- len += snprintf(buf+len, sizeof(buf)-len,
- "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"%10s %c 0x%08x - %s\n", dbg_info[i].name,
- sc->debug.level & dbg_info[i].level ? '+' : ' ',
+ ah->debug.level & dbg_info[i].level ? '+' : ' ',
dbg_info[i].level, dbg_info[i].desc);
}
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"%10s %c 0x%08x - %s\n", dbg_info[i].name,
- sc->debug.level == dbg_info[i].level ? '+' : ' ',
+ ah->debug.level == dbg_info[i].level ? '+' : ' ',
dbg_info[i].level, dbg_info[i].desc);
if (len > sizeof(buf))
@@ -347,7 +345,7 @@ static ssize_t write_file_debug(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
unsigned int i;
char buf[20];
@@ -357,7 +355,7 @@ static ssize_t write_file_debug(struct file *file,
for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
if (strncmp(buf, dbg_info[i].name,
strlen(dbg_info[i].name)) == 0) {
- sc->debug.level ^= dbg_info[i].level; /* toggle bit */
+ ah->debug.level ^= dbg_info[i].level; /* toggle bit */
break;
}
}
@@ -378,66 +376,66 @@ static const struct file_operations fops_debug = {
static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
unsigned int i;
unsigned int v;
- len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n",
- sc->ah->ah_ant_mode);
- len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
- sc->ah->ah_def_ant);
- len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n",
- sc->ah->ah_tx_ant);
+ len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
+ ah->ah_ant_mode);
+ len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
+ ah->ah_def_ant);
+ len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
+ ah->ah_tx_ant);
- len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n");
- for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
+ for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
+ len += snprintf(buf + len, sizeof(buf) - len,
"[antenna %d]\t%d\t%d\n",
- i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);
+ i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
}
- len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
- sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]);
+ len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
+ ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
- v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
- v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
(v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
(v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
(v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
(v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
(v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
(v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
- v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
- len += snprintf(buf+len, sizeof(buf)-len,
+ v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
if (len > sizeof(buf))
@@ -450,7 +448,7 @@ static ssize_t write_file_antenna(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
unsigned int i;
char buf[20];
@@ -458,18 +456,18 @@ static ssize_t write_file_antenna(struct file *file,
return -EFAULT;
if (strncmp(buf, "diversity", 9) == 0) {
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
printk(KERN_INFO "ath5k debug: enable diversity\n");
} else if (strncmp(buf, "fixed-a", 7) == 0) {
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
printk(KERN_INFO "ath5k debugfs: fixed antenna A\n");
} else if (strncmp(buf, "fixed-b", 7) == 0) {
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
printk(KERN_INFO "ath5k debug: fixed antenna B\n");
} else if (strncmp(buf, "clear", 5) == 0) {
- for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
- sc->stats.antenna_rx[i] = 0;
- sc->stats.antenna_tx[i] = 0;
+ for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
+ ah->stats.antenna_rx[i] = 0;
+ ah->stats.antenna_tx[i] = 0;
}
printk(KERN_INFO "ath5k debug: cleared antenna stats\n");
}
@@ -489,42 +487,42 @@ static const struct file_operations fops_antenna = {
static ssize_t read_file_misc(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
- u32 filt = ath5k_hw_get_rx_filter(sc->ah);
+ u32 filt = ath5k_hw_get_rx_filter(ah);
- len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
- sc->bssidmask);
- len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ",
+ len += snprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
+ ah->bssidmask);
+ len += snprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
filt);
if (filt & AR5K_RX_FILTER_UCAST)
- len += snprintf(buf+len, sizeof(buf)-len, " UCAST");
+ len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
if (filt & AR5K_RX_FILTER_MCAST)
- len += snprintf(buf+len, sizeof(buf)-len, " MCAST");
+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
if (filt & AR5K_RX_FILTER_BCAST)
- len += snprintf(buf+len, sizeof(buf)-len, " BCAST");
+ len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
if (filt & AR5K_RX_FILTER_CONTROL)
- len += snprintf(buf+len, sizeof(buf)-len, " CONTROL");
+ len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
if (filt & AR5K_RX_FILTER_BEACON)
- len += snprintf(buf+len, sizeof(buf)-len, " BEACON");
+ len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
if (filt & AR5K_RX_FILTER_PROM)
- len += snprintf(buf+len, sizeof(buf)-len, " PROM");
+ len += snprintf(buf + len, sizeof(buf) - len, " PROM");
if (filt & AR5K_RX_FILTER_XRPOLL)
- len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL");
+ len += snprintf(buf + len, sizeof(buf) - len, " XRPOLL");
if (filt & AR5K_RX_FILTER_PROBEREQ)
- len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ");
+ len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
if (filt & AR5K_RX_FILTER_PHYERR_5212)
- len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212");
+ len += snprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
if (filt & AR5K_RX_FILTER_RADARERR_5212)
- len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212");
+ len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
if (filt & AR5K_RX_FILTER_PHYERR_5211)
- snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211");
+ snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
if (filt & AR5K_RX_FILTER_RADARERR_5211)
- len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211");
+ len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
- len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n",
- ath_opmode_to_string(sc->opmode), sc->opmode);
+ len += snprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
+ ath_opmode_to_string(ah->opmode), ah->opmode);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -544,71 +542,71 @@ static const struct file_operations fops_misc = {
static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_statistics *st = &sc->stats;
+ struct ath5k_hw *ah = file->private_data;
+ struct ath5k_statistics *st = &ah->stats;
char buf[700];
unsigned int len = 0;
int i;
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"RX\n---------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
st->rxerr_crc,
st->rx_all_count > 0 ?
- st->rxerr_crc*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n",
+ st->rxerr_crc * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
st->rxerr_phy,
st->rx_all_count > 0 ?
- st->rxerr_phy*100/st->rx_all_count : 0);
+ st->rxerr_phy * 100 / st->rx_all_count : 0);
for (i = 0; i < 32; i++) {
if (st->rxerr_phy_code[i])
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
" phy_err[%u]\t%u\n",
i, st->rxerr_phy_code[i]);
}
- len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
st->rxerr_fifo,
st->rx_all_count > 0 ?
- st->rxerr_fifo*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n",
+ st->rxerr_fifo * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
st->rxerr_decrypt,
st->rx_all_count > 0 ?
- st->rxerr_decrypt*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n",
+ st->rxerr_decrypt * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
st->rxerr_mic,
st->rx_all_count > 0 ?
- st->rxerr_mic*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n",
+ st->rxerr_mic * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
st->rxerr_proc,
st->rx_all_count > 0 ?
- st->rxerr_proc*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n",
+ st->rxerr_proc * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
st->rxerr_jumbo,
st->rx_all_count > 0 ?
- st->rxerr_jumbo*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n",
+ st->rxerr_jumbo * 100 / st->rx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
st->rx_all_count);
- len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
st->rx_bytes_count);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nTX\n---------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
st->txerr_retry,
st->tx_all_count > 0 ?
- st->txerr_retry*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
+ st->txerr_retry * 100 / st->tx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
st->txerr_fifo,
st->tx_all_count > 0 ?
- st->txerr_fifo*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n",
+ st->txerr_fifo * 100 / st->tx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
st->txerr_filt,
st->tx_all_count > 0 ?
- st->txerr_filt*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n",
+ st->txerr_filt * 100 / st->tx_all_count : 0);
+ len += snprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
st->tx_all_count);
- len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
st->tx_bytes_count);
if (len > sizeof(buf))
@@ -621,8 +619,8 @@ static ssize_t write_file_frameerrors(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_statistics *st = &sc->stats;
+ struct ath5k_hw *ah = file->private_data;
+ struct ath5k_statistics *st = &ah->stats;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
@@ -660,100 +658,104 @@ static const struct file_operations fops_frameerrors = {
static ssize_t read_file_ani(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
- struct ath5k_statistics *st = &sc->stats;
- struct ath5k_ani_state *as = &sc->ani_state;
+ struct ath5k_hw *ah = file->private_data;
+ struct ath5k_statistics *st = &ah->stats;
+ struct ath5k_ani_state *as = &ah->ani_state;
char buf[700];
unsigned int len = 0;
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"HW has PHY error counters:\t%s\n",
- sc->ah->ah_capabilities.cap_has_phyerr_counters ?
+ ah->ah_capabilities.cap_has_phyerr_counters ?
"yes" : "no");
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"HW max spur immunity level:\t%d\n",
as->max_spur_level);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nANI state\n--------------------------------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t");
+ len += snprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
switch (as->ani_mode) {
case ATH5K_ANI_MODE_OFF:
- len += snprintf(buf+len, sizeof(buf)-len, "OFF\n");
+ len += snprintf(buf + len, sizeof(buf) - len, "OFF\n");
break;
case ATH5K_ANI_MODE_MANUAL_LOW:
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"MANUAL LOW\n");
break;
case ATH5K_ANI_MODE_MANUAL_HIGH:
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"MANUAL HIGH\n");
break;
case ATH5K_ANI_MODE_AUTO:
- len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n");
+ len += snprintf(buf + len, sizeof(buf) - len, "AUTO\n");
break;
default:
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"??? (not good)\n");
break;
}
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"noise immunity level:\t\t%d\n",
as->noise_imm_level);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"spur immunity level:\t\t%d\n",
as->spur_level);
- len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "firstep level:\t\t\t%d\n",
as->firstep_level);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"OFDM weak signal detection:\t%s\n",
as->ofdm_weak_sig ? "on" : "off");
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"CCK weak signal detection:\t%s\n",
as->cck_weak_sig ? "on" : "off");
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"\nMIB INTERRUPTS:\t\t%u\n",
st->mib_intr);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"beacon RSSI average:\t%d\n",
- (int)ewma_read(&sc->ah->ah_beacon_rssi_avg));
+ (int)ewma_read(&ah->ah_beacon_rssi_avg));
#define CC_PRINT(_struct, _field) \
_struct._field, \
_struct.cycles > 0 ? \
- _struct._field*100/_struct.cycles : 0
+ _struct._field * 100 / _struct.cycles : 0
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "profcnt tx\t\t%u\t(%d%%)\n",
CC_PRINT(as->last_cc, tx_frame));
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "profcnt rx\t\t%u\t(%d%%)\n",
CC_PRINT(as->last_cc, rx_frame));
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "profcnt busy\t\t%u\t(%d%%)\n",
CC_PRINT(as->last_cc, rx_busy));
#undef CC_PRINT
- len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
+ len += snprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
as->last_cc.cycles);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"listen time\t\t%d\tlast: %d\n",
as->listen_time, as->last_listen);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
as->ofdm_errors, as->last_ofdm_errors,
as->sum_ofdm_errors);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"CCK errors\t\t%u\tlast: %u\tsum: %u\n",
as->cck_errors, as->last_cck_errors,
as->sum_cck_errors);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1),
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1)));
- len += snprintf(buf+len, sizeof(buf)-len,
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
+ len += snprintf(buf + len, sizeof(buf) - len,
"AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2),
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
- ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2)));
+ ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
if (len > sizeof(buf))
len = sizeof(buf);
@@ -765,42 +767,42 @@ static ssize_t write_file_ani(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
return -EFAULT;
if (strncmp(buf, "sens-low", 8) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
} else if (strncmp(buf, "sens-high", 9) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
} else if (strncmp(buf, "ani-off", 7) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
} else if (strncmp(buf, "ani-on", 6) == 0) {
- ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO);
+ ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
} else if (strncmp(buf, "noise-low", 9) == 0) {
- ath5k_ani_set_noise_immunity_level(sc->ah, 0);
+ ath5k_ani_set_noise_immunity_level(ah, 0);
} else if (strncmp(buf, "noise-high", 10) == 0) {
- ath5k_ani_set_noise_immunity_level(sc->ah,
+ ath5k_ani_set_noise_immunity_level(ah,
ATH5K_ANI_MAX_NOISE_IMM_LVL);
} else if (strncmp(buf, "spur-low", 8) == 0) {
- ath5k_ani_set_spur_immunity_level(sc->ah, 0);
+ ath5k_ani_set_spur_immunity_level(ah, 0);
} else if (strncmp(buf, "spur-high", 9) == 0) {
- ath5k_ani_set_spur_immunity_level(sc->ah,
- sc->ani_state.max_spur_level);
+ ath5k_ani_set_spur_immunity_level(ah,
+ ah->ani_state.max_spur_level);
} else if (strncmp(buf, "fir-low", 7) == 0) {
- ath5k_ani_set_firstep_level(sc->ah, 0);
+ ath5k_ani_set_firstep_level(ah, 0);
} else if (strncmp(buf, "fir-high", 8) == 0) {
- ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
+ ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
} else if (strncmp(buf, "ofdm-off", 8) == 0) {
- ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false);
+ ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
} else if (strncmp(buf, "ofdm-on", 7) == 0) {
- ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true);
+ ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
} else if (strncmp(buf, "cck-off", 7) == 0) {
- ath5k_ani_set_cck_weak_signal_detection(sc->ah, false);
+ ath5k_ani_set_cck_weak_signal_detection(ah, false);
} else if (strncmp(buf, "cck-on", 6) == 0) {
- ath5k_ani_set_cck_weak_signal_detection(sc->ah, true);
+ ath5k_ani_set_cck_weak_signal_detection(ah, true);
}
return count;
}
@@ -819,7 +821,7 @@ static const struct file_operations fops_ani = {
static ssize_t read_file_queue(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[700];
unsigned int len = 0;
@@ -827,13 +829,13 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
struct ath5k_buf *bf, *bf0;
int i, n;
- len += snprintf(buf+len, sizeof(buf)-len,
- "available txbuffers: %d\n", sc->txbuf_len);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "available txbuffers: %d\n", ah->txbuf_len);
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
- txq = &sc->txqs[i];
+ for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+ txq = &ah->txqs[i];
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
"%02d: %ssetup\n", i, txq->setup ? "" : "not ");
if (!txq->setup)
@@ -845,9 +847,9 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
n++;
spin_unlock_bh(&txq->lock);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
" len: %d bufs: %d\n", txq->txq_len, n);
- len += snprintf(buf+len, sizeof(buf)-len,
+ len += snprintf(buf + len, sizeof(buf) - len,
" stuck: %d\n", txq->txq_stuck);
}
@@ -861,16 +863,16 @@ static ssize_t write_file_queue(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = file->private_data;
char buf[20];
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
return -EFAULT;
if (strncmp(buf, "start", 5) == 0)
- ieee80211_wake_queues(sc->hw);
+ ieee80211_wake_queues(ah->hw);
else if (strncmp(buf, "stop", 4) == 0)
- ieee80211_stop_queues(sc->hw);
+ ieee80211_stop_queues(ah->hw);
return count;
}
@@ -886,54 +888,57 @@ static const struct file_operations fops_queue = {
void
-ath5k_debug_init_device(struct ath5k_softc *sc)
+ath5k_debug_init_device(struct ath5k_hw *ah)
{
struct dentry *phydir;
- sc->debug.level = ath5k_debug;
+ ah->debug.level = ath5k_debug;
- phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
+ phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
if (!phydir)
- return;
+ return;
- debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, ah,
&fops_debug);
- debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
+ debugfs_create_file("registers", S_IRUSR, phydir, ah, &fops_registers);
- debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
&fops_beacon);
- debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
+ debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
- debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
&fops_antenna);
- debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
+ debugfs_create_file("misc", S_IRUSR, phydir, ah, &fops_misc);
- debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, ah,
&fops_frameerrors);
- debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
+ debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, ah, &fops_ani);
- debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
+ debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, ah,
&fops_queue);
+
+ debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir,
+ &ah->ah_use_32khz_clock);
}
/* functions used in other places */
void
-ath5k_debug_dump_bands(struct ath5k_softc *sc)
+ath5k_debug_dump_bands(struct ath5k_hw *ah)
{
unsigned int b, i;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
+ if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
return;
- BUG_ON(!sc->sbands);
+ BUG_ON(!ah->sbands);
for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
- struct ieee80211_supported_band *band = &sc->sbands[b];
+ struct ieee80211_supported_band *band = &ah->sbands[b];
char bname[6];
switch (band->band) {
case IEEE80211_BAND_2GHZ:
@@ -983,41 +988,41 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
}
void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
{
struct ath5k_desc *ds;
struct ath5k_buf *bf;
struct ath5k_rx_status rs = {};
int status;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
+ if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
return;
printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
- ath5k_hw_get_rxdp(ah), sc->rxlink);
+ ath5k_hw_get_rxdp(ah), ah->rxlink);
- spin_lock_bh(&sc->rxbuflock);
- list_for_each_entry(bf, &sc->rxbuf, list) {
+ spin_lock_bh(&ah->rxbuflock);
+ list_for_each_entry(bf, &ah->rxbuf, list) {
ds = bf->desc;
status = ah->ah_proc_rx_desc(ah, ds, &rs);
if (!status)
ath5k_debug_printrxbuf(bf, status == 0, &rs);
}
- spin_unlock_bh(&sc->rxbuflock);
+ spin_unlock_bh(&ah->rxbuflock);
}
void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
{
struct ath5k_desc *ds = bf->desc;
struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
struct ath5k_tx_status ts = {};
int done;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
+ if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
return;
- done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
+ done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 193dd2d4ea3c..7f37df3125fd 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -61,7 +61,6 @@
#ifndef _ATH5K_DEBUG_H
#define _ATH5K_DEBUG_H
-struct ath5k_softc;
struct ath5k_hw;
struct sk_buff;
struct ath5k_buf;
@@ -127,39 +126,39 @@ enum ath5k_debug_level {
} while (0)
void
-ath5k_debug_init_device(struct ath5k_softc *sc);
+ath5k_debug_init_device(struct ath5k_hw *ah);
void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah);
void
-ath5k_debug_dump_bands(struct ath5k_softc *sc);
+ath5k_debug_dump_bands(struct ath5k_hw *ah);
void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf);
#else /* no debugging */
#include <linux/compiler.h>
static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
+ATH5K_DBG(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {}
static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
+ATH5K_DBG_UNLIMIT(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...)
{}
static inline void
-ath5k_debug_init_device(struct ath5k_softc *sc) {}
+ath5k_debug_init_device(struct ath5k_hw *ah) {}
static inline void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah) {}
static inline void
-ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
+ath5k_debug_dump_bands(struct ath5k_hw *ah) {}
static inline void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf) {}
#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
index f82383b3ed30..846535f59efc 100644
--- a/drivers/net/wireless/ath/ath5k/desc.c
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -55,12 +55,12 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
* noise on the channel, so it is important to avoid this.
*/
if (unlikely(tx_tries0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ ATH5K_ERR(ah, "zero retries\n");
WARN_ON(1);
return -EINVAL;
}
if (unlikely(tx_rate0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ ATH5K_ERR(ah, "zero rate\n");
WARN_ON(1);
return -EINVAL;
}
@@ -203,12 +203,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
* noise on the channel, so it is important to avoid this.
*/
if (unlikely(tx_tries0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ ATH5K_ERR(ah, "zero retries\n");
WARN_ON(1);
return -EINVAL;
}
if (unlikely(tx_rate0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ ATH5K_ERR(ah, "zero rate\n");
WARN_ON(1);
return -EINVAL;
}
@@ -316,7 +316,7 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
(tx_rate2 == 0 && tx_tries2 != 0) ||
(tx_rate3 == 0 && tx_tries3 != 0))) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ ATH5K_ERR(ah, "zero rate\n");
WARN_ON(1);
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h
index 2509d0bf037d..cfd529b548f3 100644
--- a/drivers/net/wireless/ath/ath5k/desc.h
+++ b/drivers/net/wireless/ath/ath5k/desc.h
@@ -58,11 +58,11 @@ struct ath5k_hw_rx_status {
#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* reception success */
#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */
#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210 0x00000008 /* [5210] FIFO overrun */
-#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 /* decyption CRC failure */
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 /* decryption CRC failure */
#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 /* PHY error */
#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */
-#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 /* decyption key index */
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 /* decryption key index */
#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 /* 13 bit of TSF */
#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 21091c26a9a5..0d5d4033f12a 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -25,7 +25,7 @@
*
* Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
* handle queue setup for 5210 chipset (rest are handled on qcu.c).
- * Also we setup interrupt mask register (IMR) and read the various iterrupt
+ * Also we setup interrupt mask register (IMR) and read the various interrupt
* status registers (ISR).
*
* TODO: Handle SISR on 5211+ and introduce a function to return the queue
@@ -73,7 +73,7 @@ static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
udelay(100);
if (!i)
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"failed to stop RX DMA !\n");
return i ? 0 : -EBUSY;
@@ -100,7 +100,7 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
{
if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"tried to set RXDP while rx was active !\n");
return -EIO;
}
@@ -243,7 +243,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
udelay(100);
if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"queue %i didn't stop !\n", queue);
/* Check for pending frames */
@@ -258,7 +258,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* For 2413+ order PCU to drop packets using
* QUIET mechanism */
if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
- pending){
+ pending) {
/* Set periodicity and duration */
ath5k_hw_reg_write(ah,
AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
@@ -295,7 +295,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
if (pending)
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"quiet mechanism didn't work q:%i !\n",
queue);
}
@@ -309,7 +309,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* Clear register */
ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
if (pending) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"tx dma didn't stop (q:%i, frm:%i) !\n",
queue, pending);
return -EBUSY;
@@ -333,7 +333,7 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
int ret;
ret = ath5k_hw_stop_tx_dma(ah, queue);
if (ret) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
"beacon queue didn't stop !\n");
return -EIO;
}
@@ -726,7 +726,7 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
int_mask |= AR5K_IMR_RXDOPPLER;
/* Note: Per queue interrupt masks
- * are set via reset_tx_queue (qcu.c) */
+ * are set via ath5k_hw_reset_tx_queue() (qcu.c) */
ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
@@ -783,7 +783,7 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah)
* for all PCI-E cards to be safe).
*
* XXX: need to check 5210 for this
- * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * TODO: Check out tx trigger level, it's always 64 on dumps but I
* guess we can tweak it and see how it goes ;-)
*/
if (ah->ah_version != AR5K_AR5210) {
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 392771f93759..9068b9165265 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -105,7 +105,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
* big still, waiting on a better value.
*/
if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
- ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
+ ATH5K_ERR(ah, "Invalid max custom EEPROM size: "
"%d (0x%04x) max expected: %d (0x%04x)\n",
eep_max, eep_max,
3 * AR5K_EEPROM_INFO_MAX,
@@ -119,7 +119,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
cksum ^= val;
}
if (cksum != AR5K_EEPROM_INFO_CKSUM) {
- ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
+ ATH5K_ERR(ah, "Invalid EEPROM "
"checksum: 0x%04x eep_max: 0x%04x (%s)\n",
cksum, eep_max,
eep_max == AR5K_EEPROM_INFO_MAX ?
@@ -223,14 +223,14 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
ah->ah_ant_ctl[mode][AR5K_ANT_CTL] =
(ee->ee_ant_control[mode][0] << 4);
ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] =
- ee->ee_ant_control[mode][1] |
- (ee->ee_ant_control[mode][2] << 6) |
+ ee->ee_ant_control[mode][1] |
+ (ee->ee_ant_control[mode][2] << 6) |
(ee->ee_ant_control[mode][3] << 12) |
(ee->ee_ant_control[mode][4] << 18) |
(ee->ee_ant_control[mode][5] << 24);
ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] =
- ee->ee_ant_control[mode][6] |
- (ee->ee_ant_control[mode][7] << 6) |
+ ee->ee_ant_control[mode][6] |
+ (ee->ee_ant_control[mode][7] << 6) |
(ee->ee_ant_control[mode][8] << 12) |
(ee->ee_ant_control[mode][9] << 18) |
(ee->ee_ant_control[mode][10] << 24);
@@ -255,7 +255,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
ee->ee_n_piers[mode] = 0;
AR5K_EEPROM_READ(o++, val);
ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
ee->ee_ob[mode][3] = (val >> 5) & 0x7;
ee->ee_db[mode][3] = (val >> 2) & 0x7;
@@ -349,7 +349,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
/* Note: >= v5 have bg freq piers on another location
* so these freq piers are ignored for >= v5 (should be 0xff
* anyway) */
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
break;
@@ -422,7 +422,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
goto done;
- switch (mode){
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
@@ -436,7 +436,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
- if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
+ if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >= 2)
ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
break;
case AR5K_EEPROM_MODE_11G:
@@ -516,7 +516,7 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
u16 val;
ee->ee_n_piers[mode] = 0;
- while(i < max) {
+ while (i < max) {
AR5K_EEPROM_READ(o++, val);
freq1 = val & 0xff;
@@ -602,7 +602,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
struct ath5k_chan_pcal_info *pcal;
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11B:
pcal = ee->ee_pwr_cal_b;
break;
@@ -634,7 +634,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
/* Used to match PCDAC steps with power values on RF5111 chips
* (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
* steps that match with the power values we read from eeprom. On
- * older eeprom versions (< 3.2) these steps are equaly spaced at
+ * older eeprom versions (< 3.2) these steps are equally spaced at
* 10% of the pcdac curve -until the curve reaches its maximum-
* (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
* these 11 steps are spaced in a different way. This function returns
@@ -644,10 +644,12 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
static inline void
ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
{
- static const u16 intercepts3[] =
- { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
- static const u16 intercepts3_2[] =
- { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+ static const u16 intercepts3[] = {
+ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100
+ };
+ static const u16 intercepts3_2[] = {
+ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
+ };
const u16 *ip;
int i;
@@ -762,7 +764,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
/* Fill raw dataset
* (convert power to 0.25dB units
- * for RF5112 combatibility) */
+ * for RF5112 compatibility) */
for (point = 0; point < pd->pd_points; point++) {
/* Absolute values */
@@ -796,7 +798,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
u16 val;
offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11A:
if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
return 0;
@@ -882,7 +884,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
* Read power calibration for RF5112 chips
*
* For RF5112 we have 4 XPD -eXternal Power Detector- curves
- * for each calibrated channel on 0, -6, -12 and -18dbm but we only
+ * for each calibrated channel on 0, -6, -12 and -18dBm but we only
* use the higher (3) and the lower (0) curves. Each curve has 0.5dB
* power steps on x axis and PCDAC steps on y axis and looks like a
* linear function. To recreate the curve and pass the power values
@@ -1163,7 +1165,7 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
{
u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
- switch(mode) {
+ switch (mode) {
case AR5K_EEPROM_MODE_11G:
if (AR5K_EEPROM_HDR_11B(ee->ee_header))
offset += ath5k_pdgains_size_2413(ee,
@@ -1239,7 +1241,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
/* Fill raw dataset
* convert all pwr levels to
- * quarter dB for RF5112 combatibility */
+ * quarter dB for RF5112 compatibility */
pd->pd_step[0] = pcinfo->pddac_i[pdg];
pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
@@ -1620,8 +1622,8 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
rep = ee->ee_ctl_pwr;
- for(i = 0; i < ee->ee_ctls; i++) {
- switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
+ for (i = 0; i < ee->ee_ctls; i++) {
+ switch (ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
case AR5K_CTL_11A:
case AR5K_CTL_TURBO:
ctl_mode = AR5K_EEPROM_MODE_11A;
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 6511c27d938e..dc2bcfeadeb4 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -50,7 +50,7 @@
#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
-#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2GHz (ar5211_rfregs) */
#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
@@ -75,11 +75,11 @@
#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
-#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz */
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2GHz */
#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for < 2W power consumption */
#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) /* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */
#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5GHz */
/* Newer EEPROMs are using a different offset */
#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
@@ -120,7 +120,7 @@
#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) /* disable fast frames */
#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) /* disable bursting */
#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) /* max number of QCUs. defaults to 10 */
-#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heayy clipping */
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heavy clipping */
#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) /* key cache size. defaults to 128 */
#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
@@ -223,7 +223,7 @@
#define AR5K_EEPROM_CCK_OFDM_DELTA 15
#define AR5K_EEPROM_N_IQ_CAL 2
/* 5GHz/2GHz */
-enum ath5k_eeprom_freq_bands{
+enum ath5k_eeprom_freq_bands {
AR5K_EEPROM_BAND_5GHZ = 0,
AR5K_EEPROM_BAND_2GHZ = 1,
AR5K_EEPROM_N_FREQ_BANDS,
@@ -270,7 +270,7 @@ enum ath5k_ctl_mode {
/* Per channel calibration data, used for power table setup */
struct ath5k_chan_pcal_info_rf5111 {
- /* Power levels in half dbm units
+ /* Power levels in half dBm units
* for one power curve. */
u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
/* PCDAC table steps
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
index e49340d18df4..5ab607f40e0e 100644
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -113,8 +113,8 @@ static const struct ath5k_ini ar5210_ini[] = {
{ AR5K_PHY(28), 0x0000000f },
{ AR5K_PHY(29), 0x00000080 },
{ AR5K_PHY(30), 0x00000004 },
- { AR5K_PHY(31), 0x00000018 }, /* 0x987c */
- { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */
+ { AR5K_PHY(31), 0x00000018 }, /* 0x987c */
+ { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */
{ AR5K_PHY(65), 0x00000000 },
{ AR5K_PHY(66), 0x00000000 },
{ AR5K_PHY(67), 0x00800000 },
@@ -549,7 +549,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
{ AR5K_DIAG_SW_5211, 0x00000000 },
{ AR5K_ADDAC_TEST, 0x00000000 },
{ AR5K_DEFAULT_ANTENNA, 0x00000000 },
- { AR5K_FRAME_CTL_QOSM, 0x000fc78f },
+ { AR5K_FRAME_CTL_QOSM, 0x000fc78f },
{ AR5K_XRMODE, 0x2a82301a },
{ AR5K_XRDELAY, 0x05dc01e0 },
{ AR5K_XRTIMEOUT, 0x1f402710 },
@@ -760,9 +760,9 @@ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
static const struct ath5k_ini rf5111_ini_common_end[] = {
{ AR5K_DCU_FP, 0x00000000 },
- { AR5K_PHY_AGC, 0x00000000 },
- { AR5K_PHY_ADC_CTL, 0x00022ffe },
- { 0x983c, 0x00020100 },
+ { AR5K_PHY_AGC, 0x00000000 },
+ { AR5K_PHY_ADC_CTL, 0x00022ffe },
+ { 0x983c, 0x00020100 },
{ AR5K_PHY_GAIN_OFFSET, 0x1284613c },
{ AR5K_PHY_PAPD_PROBE, 0x00004883 },
{ 0x9940, 0x00000004 },
@@ -1409,7 +1409,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
* Write initial register settings
*/
- /* For AR5212 and combatible */
+ /* For AR5212 and compatible */
if (ah->ah_version == AR5K_AR5212) {
/* First set of mode-specific settings */
@@ -1542,7 +1542,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
/* AR5K_MODE_11B */
if (mode > 2) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"unsupported channel mode: %d\n", mode);
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 576edf2965dc..8c17a00f7dad 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -43,16 +43,16 @@
#include "ath5k.h"
#include "base.h"
-#define ATH_SDEVICE(subv,subd) \
+#define ATH_SDEVICE(subv, subd) \
.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
.subvendor = (subv), .subdevice = (subd)
-#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity))
+#define ATH_LED(pin, polarity) .driver_data = (((pin) << 8) | (polarity))
#define ATH_PIN(data) ((data) >> 8)
#define ATH_POLARITY(data) ((data) & 0xff)
/* Devices we match on for LED config info (typically laptops) */
-static const struct pci_device_id ath5k_led_devices[] = {
+static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = {
/* AR5211 */
{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
/* HP Compaq nc6xx, nc4000, nx6000 */
@@ -86,26 +86,26 @@ static const struct pci_device_id ath5k_led_devices[] = {
{ }
};
-void ath5k_led_enable(struct ath5k_softc *sc)
+void ath5k_led_enable(struct ath5k_hw *ah)
{
- if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
- ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
- ath5k_led_off(sc);
+ if (test_bit(ATH_STAT_LEDSOFT, ah->status)) {
+ ath5k_hw_set_gpio_output(ah, ah->led_pin);
+ ath5k_led_off(ah);
}
}
-static void ath5k_led_on(struct ath5k_softc *sc)
+static void ath5k_led_on(struct ath5k_hw *ah)
{
- if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+ if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
return;
- ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
+ ath5k_hw_set_gpio(ah, ah->led_pin, ah->led_on);
}
-void ath5k_led_off(struct ath5k_softc *sc)
+void ath5k_led_off(struct ath5k_hw *ah)
{
- if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+ if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
return;
- ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
+ ath5k_hw_set_gpio(ah, ah->led_pin, !ah->led_on);
}
static void
@@ -116,27 +116,27 @@ ath5k_led_brightness_set(struct led_classdev *led_dev,
led_dev);
if (brightness == LED_OFF)
- ath5k_led_off(led->sc);
+ ath5k_led_off(led->ah);
else
- ath5k_led_on(led->sc);
+ ath5k_led_on(led->ah);
}
static int
-ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
+ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led,
const char *name, char *trigger)
{
int err;
- led->sc = sc;
+ led->ah = ah;
strncpy(led->name, name, sizeof(led->name));
led->led_dev.name = led->name;
led->led_dev.default_trigger = trigger;
led->led_dev.brightness_set = ath5k_led_brightness_set;
- err = led_classdev_register(sc->dev, &led->led_dev);
+ err = led_classdev_register(ah->dev, &led->led_dev);
if (err) {
- ATH5K_WARN(sc, "could not register LED %s\n", name);
- led->sc = NULL;
+ ATH5K_WARN(ah, "could not register LED %s\n", name);
+ led->ah = NULL;
}
return err;
}
@@ -144,30 +144,30 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
static void
ath5k_unregister_led(struct ath5k_led *led)
{
- if (!led->sc)
+ if (!led->ah)
return;
led_classdev_unregister(&led->led_dev);
- ath5k_led_off(led->sc);
- led->sc = NULL;
+ ath5k_led_off(led->ah);
+ led->ah = NULL;
}
-void ath5k_unregister_leds(struct ath5k_softc *sc)
+void ath5k_unregister_leds(struct ath5k_hw *ah)
{
- ath5k_unregister_led(&sc->rx_led);
- ath5k_unregister_led(&sc->tx_led);
+ ath5k_unregister_led(&ah->rx_led);
+ ath5k_unregister_led(&ah->tx_led);
}
-int ath5k_init_leds(struct ath5k_softc *sc)
+int __devinit ath5k_init_leds(struct ath5k_hw *ah)
{
int ret = 0;
- struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_hw *hw = ah->hw;
#ifndef CONFIG_ATHEROS_AR231X
- struct pci_dev *pdev = sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
#endif
char name[ATH5K_LED_MAX_NAME_LEN + 1];
const struct pci_device_id *match;
- if (!sc->pdev)
+ if (!ah->pdev)
return 0;
#ifdef CONFIG_ATHEROS_AR231X
@@ -176,24 +176,24 @@ int ath5k_init_leds(struct ath5k_softc *sc)
match = pci_match_id(&ath5k_led_devices[0], pdev);
#endif
if (match) {
- __set_bit(ATH_STAT_LEDSOFT, sc->status);
- sc->led_pin = ATH_PIN(match->driver_data);
- sc->led_on = ATH_POLARITY(match->driver_data);
+ __set_bit(ATH_STAT_LEDSOFT, ah->status);
+ ah->led_pin = ATH_PIN(match->driver_data);
+ ah->led_on = ATH_POLARITY(match->driver_data);
}
- if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+ if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
goto out;
- ath5k_led_enable(sc);
+ ath5k_led_enable(ah);
snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
- ret = ath5k_register_led(sc, &sc->rx_led, name,
+ ret = ath5k_register_led(ah, &ah->rx_led, name,
ieee80211_get_rx_led_name(hw));
if (ret)
goto out;
snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
- ret = ath5k_register_led(sc, &sc->tx_led, name,
+ ret = ath5k_register_led(ah, &ah->tx_led, name,
ieee80211_get_tx_led_name(hw));
out:
return ret;
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 807bd6440169..2a715ca0c5e4 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -46,8 +46,6 @@
#include "base.h"
#include "reg.h"
-extern int ath5k_modparam_nohwcrypt;
-
/********************\
* Mac80211 functions *
\********************/
@@ -55,44 +53,30 @@ extern int ath5k_modparam_nohwcrypt;
static void
ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
u16 qnum = skb_get_queue_mapping(skb);
- if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
+ if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) {
dev_kfree_skb_any(skb);
return;
}
- ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
-}
-
-
-static int
-ath5k_start(struct ieee80211_hw *hw)
-{
- return ath5k_init_hw(hw->priv);
-}
-
-
-static void
-ath5k_stop(struct ieee80211_hw *hw)
-{
- ath5k_stop_hw(hw->priv);
+ ath5k_tx_queue(hw, skb, &ah->txqs[qnum]);
}
static int
ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
int ret;
struct ath5k_vif *avf = (void *)vif->drv_priv;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
if ((vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC)
- && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
+ && (ah->num_ap_vifs + ah->num_adhoc_vifs) >= ATH_BCBUF) {
ret = -ELNRNG;
goto end;
}
@@ -102,9 +86,9 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
* We would need to operate the HW in ad-hoc mode to allow TSF updates
* for the IBSS, but this breaks with additional AP or STA interfaces
* at the moment. */
- if (sc->num_adhoc_vifs ||
- (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
- ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
+ if (ah->num_adhoc_vifs ||
+ (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+ ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
ret = -ELNRNG;
goto end;
}
@@ -121,8 +105,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
goto end;
}
- sc->nvifs++;
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
+ ah->nvifs++;
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
/* Assign the vap/adhoc to a beacon xmit slot. */
if ((avf->opmode == NL80211_IFTYPE_AP) ||
@@ -130,38 +114,38 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
(avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
int slot;
- WARN_ON(list_empty(&sc->bcbuf));
- avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
+ WARN_ON(list_empty(&ah->bcbuf));
+ avf->bbuf = list_first_entry(&ah->bcbuf, struct ath5k_buf,
list);
list_del(&avf->bbuf->list);
avf->bslot = 0;
for (slot = 0; slot < ATH_BCBUF; slot++) {
- if (!sc->bslot[slot]) {
+ if (!ah->bslot[slot]) {
avf->bslot = slot;
break;
}
}
- BUG_ON(sc->bslot[avf->bslot] != NULL);
- sc->bslot[avf->bslot] = vif;
+ BUG_ON(ah->bslot[avf->bslot] != NULL);
+ ah->bslot[avf->bslot] = vif;
if (avf->opmode == NL80211_IFTYPE_AP)
- sc->num_ap_vifs++;
+ ah->num_ap_vifs++;
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
- sc->num_adhoc_vifs++;
+ ah->num_adhoc_vifs++;
}
/* Any MAC address is fine, all others are included through the
* filter.
*/
- memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
- ath5k_hw_set_lladdr(sc->ah, vif->addr);
+ 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(sc, vif);
+ ath5k_update_bssid_mask_and_opmode(ah, vif);
ret = 0;
end:
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
@@ -170,31 +154,31 @@ static void
ath5k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_vif *avf = (void *)vif->drv_priv;
unsigned int i;
- mutex_lock(&sc->lock);
- sc->nvifs--;
+ mutex_lock(&ah->lock);
+ ah->nvifs--;
if (avf->bbuf) {
- ath5k_txbuf_free_skb(sc, avf->bbuf);
- list_add_tail(&avf->bbuf->list, &sc->bcbuf);
+ ath5k_txbuf_free_skb(ah, avf->bbuf);
+ list_add_tail(&avf->bbuf->list, &ah->bcbuf);
for (i = 0; i < ATH_BCBUF; i++) {
- if (sc->bslot[i] == vif) {
- sc->bslot[i] = NULL;
+ if (ah->bslot[i] == vif) {
+ ah->bslot[i] = NULL;
break;
}
}
avf->bbuf = NULL;
}
if (avf->opmode == NL80211_IFTYPE_AP)
- sc->num_ap_vifs--;
+ ah->num_ap_vifs--;
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
- sc->num_adhoc_vifs--;
+ ah->num_adhoc_vifs--;
- ath5k_update_bssid_mask_and_opmode(sc, NULL);
- mutex_unlock(&sc->lock);
+ ath5k_update_bssid_mask_and_opmode(ah, NULL);
+ mutex_unlock(&ah->lock);
}
@@ -204,23 +188,22 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
static int
ath5k_config(struct ieee80211_hw *hw, u32 changed)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
int ret = 0;
int i;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- ret = ath5k_chan_set(sc, conf->channel);
+ ret = ath5k_chan_set(ah, conf->channel);
if (ret < 0)
goto unlock;
}
if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
- (sc->power_level != conf->power_level)) {
- sc->power_level = conf->power_level;
+ (ah->power_level != conf->power_level)) {
+ ah->power_level = conf->power_level;
/* Half dB steps */
ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
@@ -254,7 +237,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
unlock:
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
@@ -264,12 +247,11 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, u32 changes)
{
struct ath5k_vif *avf = (void *)vif->drv_priv;
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_common *common = ath5k_hw_common(ah);
unsigned long flags;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
if (changes & BSS_CHANGED_BSSID) {
/* Cache for later use during resets */
@@ -280,7 +262,7 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (changes & BSS_CHANGED_BEACON_INT)
- sc->bintval = bss_conf->beacon_int;
+ ah->bintval = bss_conf->beacon_int;
if (changes & BSS_CHANGED_ERP_SLOT) {
int slot_time;
@@ -294,16 +276,16 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (changes & BSS_CHANGED_ASSOC) {
avf->assoc = bss_conf->assoc;
if (bss_conf->assoc)
- sc->assoc = bss_conf->assoc;
+ ah->assoc = bss_conf->assoc;
else
- sc->assoc = ath_any_vif_assoc(sc);
+ ah->assoc = ath5k_any_vif_assoc(ah);
- if (sc->opmode == NL80211_IFTYPE_STATION)
- set_beacon_filter(hw, sc->assoc);
- ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+ if (ah->opmode == NL80211_IFTYPE_STATION)
+ ath5k_set_beacon_filter(hw, ah->assoc);
+ ath5k_hw_set_ledstate(ah, ah->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT);
if (bss_conf->assoc) {
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY,
"Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, common->curbssid);
common->curaid = bss_conf->aid;
@@ -313,19 +295,19 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (changes & BSS_CHANGED_BEACON) {
- spin_lock_irqsave(&sc->block, flags);
+ spin_lock_irqsave(&ah->block, flags);
ath5k_beacon_update(hw, vif);
- spin_unlock_irqrestore(&sc->block, flags);
+ spin_unlock_irqrestore(&ah->block, flags);
}
if (changes & BSS_CHANGED_BEACON_ENABLED)
- sc->enable_beacon = bss_conf->enable_beacon;
+ ah->enable_beacon = bss_conf->enable_beacon;
if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON_INT))
- ath5k_beacon_config(sc);
+ ath5k_beacon_config(ah);
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
}
@@ -350,7 +332,7 @@ ath5k_prepare_multicast(struct ieee80211_hw *hw,
mfilt[pos / 32] |= (1 << (pos % 32));
/* XXX: we might be able to just do this instead,
* but not sure, needs testing, if we do use this we'd
- * neet to inform below to not reset the mcast */
+ * need to inform below not to reset the mcast */
/* ath5k_hw_set_mcast_filterindex(ah,
* ha->addr[5]); */
}
@@ -386,12 +368,11 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC)
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
u32 mfilt[2], rfilt;
struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
mfilt[0] = multicast;
mfilt[1] = multicast >> 32;
@@ -409,12 +390,12 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
if (*new_flags & FIF_PROMISC_IN_BSS)
- __set_bit(ATH_STAT_PROMISC, sc->status);
+ __set_bit(ATH_STAT_PROMISC, ah->status);
else
- __clear_bit(ATH_STAT_PROMISC, sc->status);
+ __clear_bit(ATH_STAT_PROMISC, ah->status);
}
- if (test_bit(ATH_STAT_PROMISC, sc->status))
+ if (test_bit(ATH_STAT_PROMISC, ah->status))
rfilt |= AR5K_RX_FILTER_PROM;
/* Note, AR5K_RX_FILTER_MCAST is already enabled */
@@ -429,7 +410,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
* and probes for any BSSID */
- if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
+ if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (ah->nvifs > 1))
rfilt |= AR5K_RX_FILTER_BEACON;
/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
@@ -444,7 +425,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
- switch (sc->opmode) {
+ switch (ah->opmode) {
case NL80211_IFTYPE_MESH_POINT:
rfilt |= AR5K_RX_FILTER_CONTROL |
AR5K_RX_FILTER_BEACON |
@@ -457,7 +438,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
AR5K_RX_FILTER_BEACON;
break;
case NL80211_IFTYPE_STATION:
- if (sc->assoc)
+ if (ah->assoc)
rfilt |= AR5K_RX_FILTER_BEACON;
default:
break;
@@ -466,14 +447,14 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
iter_data.hw_macaddr = NULL;
iter_data.n_stas = 0;
iter_data.need_set_hw_addr = false;
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+ ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
&iter_data);
/* Set up RX Filter */
if (iter_data.n_stas > 1) {
/* If you have multiple STA interfaces connected to
* different APs, ARPs are not received (most of the time?)
- * Enabling PROMISC appears to fix that probem.
+ * Enabling PROMISC appears to fix that problem.
*/
rfilt |= AR5K_RX_FILTER_PROM;
}
@@ -485,9 +466,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
/* Set the cached hw filter flags, this will later actually
* be set in HW */
- sc->filter_flags = rfilt;
+ ah->filter_flags = rfilt;
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
}
@@ -496,8 +477,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath_common *common = ath5k_hw_common(ah);
int ret = 0;
@@ -518,7 +498,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EINVAL;
}
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
switch (cmd) {
case SET_KEY:
@@ -542,7 +522,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
mmiowb();
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
@@ -550,17 +530,17 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
static void
ath5k_sw_scan_start(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- if (!sc->assoc)
- ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
+ struct ath5k_hw *ah = hw->priv;
+ if (!ah->assoc)
+ ath5k_hw_set_ledstate(ah, AR5K_LED_SCAN);
}
static void
ath5k_sw_scan_complete(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
- ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+ struct ath5k_hw *ah = hw->priv;
+ ath5k_hw_set_ledstate(ah, ah->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT);
}
@@ -569,15 +549,15 @@ static int
ath5k_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
/* Force update */
- ath5k_hw_update_mib_counters(sc->ah);
+ ath5k_hw_update_mib_counters(ah);
- stats->dot11ACKFailureCount = sc->stats.ack_fail;
- stats->dot11RTSFailureCount = sc->stats.rts_fail;
- stats->dot11RTSSuccessCount = sc->stats.rts_ok;
- stats->dot11FCSErrorCount = sc->stats.fcs_error;
+ stats->dot11ACKFailureCount = ah->stats.ack_fail;
+ stats->dot11RTSFailureCount = ah->stats.rts_fail;
+ stats->dot11RTSSuccessCount = ah->stats.rts_ok;
+ stats->dot11FCSErrorCount = ah->stats.fcs_error;
return 0;
}
@@ -587,15 +567,14 @@ static int
ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
+ struct ath5k_hw *ah = hw->priv;
struct ath5k_txq_info qi;
int ret = 0;
if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
return 0;
- mutex_lock(&sc->lock);
+ mutex_lock(&ah->lock);
ath5k_hw_get_tx_queueprops(ah, queue, &qi);
@@ -604,20 +583,20 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
qi.tqi_cw_max = params->cw_max;
qi.tqi_burst_time = params->txop;
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY,
"Configure tx [queue %d], "
"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
queue, params->aifs, params->cw_min,
params->cw_max, params->txop);
if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
- ATH5K_ERR(sc,
+ ATH5K_ERR(ah,
"Unable to update hardware queue %u!\n", queue);
ret = -EIO;
} else
ath5k_hw_reset_tx_queue(ah, queue);
- mutex_unlock(&sc->lock);
+ mutex_unlock(&ah->lock);
return ret;
}
@@ -626,43 +605,43 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
static u64
ath5k_get_tsf(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- return ath5k_hw_get_tsf64(sc->ah);
+ return ath5k_hw_get_tsf64(ah);
}
static void
ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- ath5k_hw_set_tsf64(sc->ah, tsf);
+ ath5k_hw_set_tsf64(ah, tsf);
}
static void
ath5k_reset_tsf(struct ieee80211_hw *hw)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
/*
* in IBSS mode we need to update the beacon timers too.
* this will also reset the TSF if we call it with 0
*/
- if (sc->opmode == NL80211_IFTYPE_ADHOC)
- ath5k_beacon_update_timers(sc, 0);
+ if (ah->opmode == NL80211_IFTYPE_ADHOC)
+ ath5k_beacon_update_timers(ah, 0);
else
- ath5k_hw_reset_tsf(sc->ah);
+ ath5k_hw_reset_tsf(ah);
}
static int
ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
- struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_common *common = ath5k_hw_common(ah);
struct ath_cycle_counters *cc = &common->cc_survey;
unsigned int div = common->clockrate * 1000;
@@ -672,18 +651,18 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
spin_lock_bh(&common->cc_lock);
ath_hw_cycle_counters_update(common);
if (cc->cycles > 0) {
- sc->survey.channel_time += cc->cycles / div;
- sc->survey.channel_time_busy += cc->rx_busy / div;
- sc->survey.channel_time_rx += cc->rx_frame / div;
- sc->survey.channel_time_tx += cc->tx_frame / div;
+ ah->survey.channel_time += cc->cycles / div;
+ ah->survey.channel_time_busy += cc->rx_busy / div;
+ ah->survey.channel_time_rx += cc->rx_frame / div;
+ ah->survey.channel_time_tx += cc->tx_frame / div;
}
memset(cc, 0, sizeof(*cc));
spin_unlock_bh(&common->cc_lock);
- memcpy(survey, &sc->survey, sizeof(*survey));
+ memcpy(survey, &ah->survey, sizeof(*survey));
survey->channel = conf->channel;
- survey->noise = sc->ah->ah_noise_floor;
+ survey->noise = ah->ah_noise_floor;
survey->filled = SURVEY_INFO_NOISE_DBM |
SURVEY_INFO_CHANNEL_TIME |
SURVEY_INFO_CHANNEL_TIME_BUSY |
@@ -707,25 +686,25 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
static void
ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- mutex_lock(&sc->lock);
- ath5k_hw_set_coverage_class(sc->ah, coverage_class);
- mutex_unlock(&sc->lock);
+ mutex_lock(&ah->lock);
+ ath5k_hw_set_coverage_class(ah, coverage_class);
+ mutex_unlock(&ah->lock);
}
static int
ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
if (tx_ant == 1 && rx_ant == 1)
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
else if (tx_ant == 2 && rx_ant == 2)
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3)
- ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+ ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
else
return -EINVAL;
return 0;
@@ -735,9 +714,9 @@ ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
static int
ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- switch (sc->ah->ah_ant_mode) {
+ switch (ah->ah_ant_mode) {
case AR5K_ANTMODE_FIXED_A:
*tx_ant = 1; *rx_ant = 1; break;
case AR5K_ANTMODE_FIXED_B:
@@ -752,9 +731,9 @@ ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
static void ath5k_get_ringparam(struct ieee80211_hw *hw,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- *tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
+ *tx = ah->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
*tx_max = ATH5K_TXQ_LEN_MAX;
*rx = *rx_max = ATH_RXBUF;
@@ -763,7 +742,7 @@ static void ath5k_get_ringparam(struct ieee80211_hw *hw,
static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
u16 qnum;
/* only support setting tx ring size for now */
@@ -774,16 +753,16 @@ static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
if (!tx || tx > ATH5K_TXQ_LEN_MAX)
return -EINVAL;
- for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) {
- if (!sc->txqs[qnum].setup)
+ for (qnum = 0; qnum < ARRAY_SIZE(ah->txqs); qnum++) {
+ if (!ah->txqs[qnum].setup)
continue;
- if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
- sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
+ if (ah->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
+ ah->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
continue;
- sc->txqs[qnum].txq_max = tx;
- if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max)
- ieee80211_stop_queue(hw, sc->txqs[qnum].qnum);
+ ah->txqs[qnum].txq_max = tx;
+ if (ah->txqs[qnum].txq_len >= ah->txqs[qnum].txq_max)
+ ieee80211_stop_queue(hw, ah->txqs[qnum].qnum);
}
return 0;
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index f2c0c236392f..eaf79b49341e 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -34,12 +34,12 @@ static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
{ PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */
{ PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */
{ PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
- { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 compatible */
+ { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 compatible */
{ PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
@@ -51,10 +51,10 @@ MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
/* return bus cachesize in 4B word units */
static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz)
{
- struct ath5k_softc *sc = (struct ath5k_softc *) common->priv;
+ struct ath5k_hw *ah = (struct ath5k_hw *) common->priv;
u8 u8tmp;
- pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
+ pci_read_config_byte(ah->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
*csz = (int)u8tmp;
/*
@@ -156,7 +156,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
void __iomem *mem;
- struct ath5k_softc *sc;
+ struct ath5k_hw *ah;
struct ieee80211_hw *hw;
int ret;
u8 csz;
@@ -234,7 +234,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
mem = pci_iomap(pdev, 0, 0);
if (!mem) {
- dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+ dev_err(&pdev->dev, "cannot remap PCI memory region\n");
ret = -EIO;
goto err_reg;
}
@@ -243,7 +243,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
* Allocate hw (mac80211 main struct)
* and hw->priv (driver private data)
*/
- hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+ hw = ieee80211_alloc_hw(sizeof(*ah), &ath5k_hw_ops);
if (hw == NULL) {
dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
ret = -ENOMEM;
@@ -252,16 +252,16 @@ ath5k_pci_probe(struct pci_dev *pdev,
dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
- sc = hw->priv;
- sc->hw = hw;
- sc->pdev = pdev;
- sc->dev = &pdev->dev;
- sc->irq = pdev->irq;
- sc->devid = id->device;
- sc->iobase = mem; /* So we can unmap it on detach */
+ ah = hw->priv;
+ ah->hw = hw;
+ ah->pdev = pdev;
+ ah->dev = &pdev->dev;
+ ah->irq = pdev->irq;
+ ah->devid = id->device;
+ ah->iobase = mem; /* So we can unmap it on detach */
/* Initialize */
- ret = ath5k_init_softc(sc, &ath_pci_bus_ops);
+ ret = ath5k_init_softc(ah, &ath_pci_bus_ops);
if (ret)
goto err_free;
@@ -285,10 +285,10 @@ static void __devexit
ath5k_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- ath5k_deinit_softc(sc);
- pci_iounmap(pdev, sc->iobase);
+ ath5k_deinit_softc(ah);
+ pci_iounmap(pdev, ah->iobase);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
ieee80211_free_hw(hw);
@@ -299,9 +299,9 @@ static int ath5k_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
- ath5k_led_off(sc);
+ ath5k_led_off(ah);
return 0;
}
@@ -309,7 +309,7 @@ static int ath5k_pci_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = hw->priv;
/*
* Suspend/Resume resets the PCI configuration space, so we have to
@@ -318,7 +318,7 @@ static int ath5k_pci_resume(struct device *dev)
*/
pci_write_config_byte(pdev, 0x41, 0);
- ath5k_led_enable(sc);
+ ath5k_led_enable(ah);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 712a9ac4000e..067313845060 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -32,7 +32,7 @@
#include "base.h"
/*
- * AR5212+ can use higher rates for ack transmition
+ * AR5212+ can use higher rates for ack transmission
* based on current tx rate instead of the base rate.
* It does this to better utilize channel usage.
* This is a mapping between G rates (that cover both
@@ -77,14 +77,13 @@ static const unsigned int ack_rates_high[] =
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
int len, struct ieee80211_rate *rate, bool shortpre)
{
- struct ath5k_softc *sc = ah->ah_sc;
int sifs, preamble, plcp_bits, sym_time;
int bitrate, bits, symbols, symbol_bits;
int dur;
/* Fallback */
if (!ah->ah_bwmode) {
- __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
+ __le16 raw_dur = ieee80211_generic_frame_duration(ah->hw,
NULL, len, rate);
/* subtract difference between long and short preamble */
@@ -205,7 +204,7 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
*/
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
{
- struct ath5k_statistics *stats = &ah->ah_sc->stats;
+ struct ath5k_statistics *stats = &ah->stats;
/* Read-And-Clear */
stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
@@ -240,25 +239,24 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
*/
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
struct ieee80211_rate *rate;
unsigned int i;
/* 802.11g covers both OFDM and CCK */
u8 band = IEEE80211_BAND_2GHZ;
/* Write rate duration table */
- for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
+ for (i = 0; i < ah->sbands[band].n_bitrates; i++) {
u32 reg;
u16 tx_time;
if (ah->ah_ack_bitrate_high)
- rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
+ rate = &ah->sbands[band].bitrates[ack_rates_high[i]];
/* CCK -> 1Mb */
else if (i < 4)
- rate = &sc->sbands[band].bitrates[0];
+ rate = &ah->sbands[band].bitrates[0];
/* OFDM -> 6Mb */
else
- rate = &sc->sbands[band].bitrates[4];
+ rate = &ah->sbands[band].bitrates[4];
/* Set ACK timeout */
reg = AR5K_RATE_DUR(rate->hw_value);
@@ -534,9 +532,9 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
local_irq_restore(flags);
- WARN_ON( i == ATH5K_MAX_TSF_READ );
+ WARN_ON(i == ATH5K_MAX_TSF_READ);
- return (((u64)tsf_upper1 << 32) | tsf_lower);
+ return ((u64)tsf_upper1 << 32) | tsf_lower;
}
/**
@@ -586,7 +584,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
/*
* Set the additional timers by mode
*/
- switch (ah->ah_sc->opmode) {
+ switch (ah->opmode) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_STATION:
/* In STA mode timer1 is used as next wakeup
@@ -623,8 +621,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
* Set the beacon register and enable all timers.
*/
/* When in AP or Mesh Point mode zero timer0 to start TSF */
- if (ah->ah_sc->opmode == NL80211_IFTYPE_AP ||
- ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT)
+ if (ah->opmode == NL80211_IFTYPE_AP ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT)
ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
@@ -643,14 +641,14 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
/* Flush any pending BMISS interrupts on ISR by
* performing a clear-on-write operation on PISR
* register for the BMISS bit (writing a bit on
- * ISR togles a reset for that bit and leaves
- * the rest bits intact) */
+ * ISR toggles a reset for that bit and leaves
+ * the remaining bits intact) */
if (ah->ah_version == AR5K_AR5210)
ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
else
ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
- /* TODO: Set enchanced sleep registers on AR5212
+ /* TODO: Set enhanced sleep registers on AR5212
* based on vif->bss_conf params, until then
* disable power save reporting.*/
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
@@ -738,7 +736,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;
/* NOTE: SWBA is different. Having a wrong window there does not
- * stop us from sending data and this condition is catched thru
+ * stop us from sending data and this condition is caught by
* other means (SWBA interrupt) */
if (ath5k_check_timer_win(nbtt, atim, 1, intval) &&
@@ -814,7 +812,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
struct ath_common *common = ath5k_hw_common(ah);
u32 pcu_reg, beacon_reg, low_id, high_id;
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
+ ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
/* Preserve rest settings */
pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
@@ -890,13 +888,13 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* XXX: rethink this after new mode changes to
* mac80211 are integrated */
if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_sc->nvifs)
+ ah->nvifs)
ath5k_hw_write_rate_duration(ah);
/* Set RSSI/BRSSI thresholds
*
* Note: If we decide to set this value
- * dynamicaly, have in mind that when AR5K_RSSI_THR
+ * dynamically, have in mind that when AR5K_RSSI_THR
* register is read it might return 0x40 if we haven't
* wrote anything to it plus BMISS RSSI threshold is zeroed.
* So doing a save/restore procedure here isn't the right
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 55441913344d..81e465e70175 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
+#include <asm/unaligned.h>
#include "ath5k.h"
#include "reg.h"
@@ -105,6 +106,7 @@ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
if ((ah->ah_radio == AR5K_RF5112) ||
(ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2413) ||
(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
refclk_freq = 40;
else
@@ -173,7 +175,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
data = ath5k_hw_bitswap(val, num_bits);
for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
- position = 0, entry++) {
+ position = 0, entry++) {
last_bit = (position + bits_left > 8) ? 8 :
position + bits_left;
@@ -363,7 +365,7 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
return 0;
}
-/* Schedule a gain probe check on the next transmited packet.
+/* Schedule a gain probe check on the next transmitted packet.
* That means our next packet is going to be sent with lower
* tx power and a Peak to Average Power Detector (PAPD) will try
* to measure the gain.
@@ -472,7 +474,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
level[0] = 0;
level[1] = (step == 63) ? 50 : step + 4;
level[2] = (step != 63) ? 64 : level[0];
- level[3] = level[2] + 50 ;
+ level[3] = level[2] + 50;
ah->ah_gain.g_high = level[3] -
(step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
@@ -549,7 +551,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
for (ah->ah_gain.g_target = ah->ah_gain.g_current;
ah->ah_gain.g_target <= ah->ah_gain.g_low &&
- ah->ah_gain.g_step_idx < go->go_steps_count-1;
+ ah->ah_gain.g_step_idx < go->go_steps_count - 1;
g_step = &go->go_step[ah->ah_gain.g_step_idx])
ah->ah_gain.g_target -= 2 *
(go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
@@ -560,7 +562,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
}
done:
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"ret %d, gain step %u, current gain %u, target gain %u\n",
ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
ah->ah_gain.g_target);
@@ -614,13 +616,13 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
ath5k_hw_rf_gainf_corr(ah);
ah->ah_gain.g_current =
ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
- (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
+ (ah->ah_gain.g_current - ah->ah_gain.g_f_corr) :
0;
}
/* Check if measurement is ok and if we need
* to adjust gain, schedule a gain adjustment,
- * else switch back to the acive state */
+ * else switch back to the active state */
if (ath5k_hw_rf_check_gainf_readback(ah) &&
AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
ath5k_hw_rf_gainf_adjust(ah)) {
@@ -772,7 +774,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
GFP_KERNEL);
if (ah->ah_rf_banks == NULL) {
- ATH5K_ERR(ah->ah_sc, "out of memory\n");
+ ATH5K_ERR(ah, "out of memory\n");
return -ENOMEM;
}
}
@@ -782,7 +784,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
for (i = 0; i < ah->ah_rf_banks_size; i++) {
if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
- ATH5K_ERR(ah->ah_sc, "invalid bank\n");
+ ATH5K_ERR(ah, "invalid bank\n");
return -EINVAL;
}
@@ -807,7 +809,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
* use b_OB and b_DB parameters stored
* in eeprom on ee->ee_ob[ee_mode][0]
*
- * For all other chips we use OB/DB for 2Ghz
+ * For all other chips we use OB/DB for 2GHz
* stored in the b/g modal section just like
* 802.11a on ee->ee_ob[ee_mode][1] */
if ((ah->ah_radio == AR5K_RF5111) ||
@@ -970,17 +972,20 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
}
/* Lower synth voltage on Rev 2 */
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_HIGH_VC_CP, true);
+ if (ah->ah_radio == AR5K_RF5112 &&
+ (ah->ah_radio_5ghz_revision & AR5K_SREV_REV) > 0) {
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_HIGH_VC_CP, true);
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_MID_VC_CP, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_MID_VC_CP, true);
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_LOW_VC_CP, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_LOW_VC_CP, true);
- ath5k_hw_rfb_op(ah, rf_regs, 2,
- AR5K_RF_PUSH_UP, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_PUSH_UP, true);
+ }
/* Decrease power consumption on 5213+ BaseBand */
if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
@@ -1259,12 +1264,12 @@ static int ath5k_hw_channel(struct ath5k_hw *ah,
{
int ret;
/*
- * Check bounds supported by the PHY (we don't care about regultory
+ * 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)) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"channel frequency (%u MHz) out of supported "
"band range\n",
channel->center_freq);
@@ -1331,7 +1336,7 @@ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor)
{
struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist;
- hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1);
+ hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX - 1);
hist->nfval[hist->index] = noise_floor;
}
@@ -1344,18 +1349,18 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort));
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) {
for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) {
- if (sort[j] > sort[j-1]) {
+ if (sort[j] > sort[j - 1]) {
tmp = sort[j];
- sort[j] = sort[j-1];
- sort[j-1] = tmp;
+ sort[j] = sort[j - 1];
+ sort[j - 1] = tmp;
}
}
}
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"cal %d:%d\n", i, sort[i]);
}
- return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2];
+ return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2];
}
/*
@@ -1378,7 +1383,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
/* keep last value if calibration hasn't completed */
if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"NF did not complete in calibration window\n");
return;
@@ -1391,7 +1396,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
threshold = ee->ee_noise_floor_thr[ee_mode];
if (nf > threshold) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"noise floor failure detected; "
"read %d, threshold %d\n",
nf, threshold);
@@ -1428,7 +1433,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
ah->ah_noise_floor = nf;
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
"noise floor calibrated: %d\n", nf);
}
@@ -1516,7 +1521,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+ ATH5K_ERR(ah, "calibration timeout (%uMHz)\n",
channel->center_freq);
return ret;
}
@@ -1551,7 +1556,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE,
"iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr);
if (i_pwr && q_pwr)
break;
@@ -1577,7 +1582,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
q_coff = (i_pwr / q_coffd) - 128;
q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */
- ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE,
"new I:%d Q:%d (i_coffd:%x q_coffd:%x)",
i_coff, q_coff, i_coffd, q_coffd);
@@ -1604,11 +1609,13 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
int ret;
if (ah->ah_radio == AR5K_RF5110)
- ret = ath5k_hw_rf5110_calibrate(ah, channel);
- else {
- ret = ath5k_hw_rf511x_iq_calibrate(ah);
+ return ath5k_hw_rf5110_calibrate(ah, channel);
+
+ ret = ath5k_hw_rf511x_iq_calibrate(ah);
+
+ if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) &&
+ (channel->hw_value & CHANNEL_OFDM))
ath5k_hw_request_rfgain_probe(ah);
- }
return ret;
}
@@ -1815,7 +1822,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
} else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) &
AR5K_PHY_IQ_SPUR_FILT_EN) {
- /* Clean up spur mitigation settings and disable fliter */
+ /* Clean up spur mitigation settings and disable filter */
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
AR5K_PHY_BIN_MASK_CTL_RATE, 0);
AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ,
@@ -1960,7 +1967,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
ee_mode = ath5k_eeprom_mode_from_channel(channel);
if (ee_mode < 0) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid channel: %d\n", channel->center_freq);
return;
}
@@ -2080,7 +2087,7 @@ ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
* always 1 instead of 1.25, 1.75 etc). We scale up by 100
* to have some accuracy both for 0.5 and 0.25 steps.
*/
- ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
+ ratio = ((100 * y_right - 100 * y_left) / (x_right - x_left));
/* Now scale down to be in range */
result = y_left + (ratio * (target - x_left) / 100);
@@ -2159,7 +2166,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax,
u8 *vpd_table, u8 type)
{
u8 idx[2] = { 0, 1 };
- s16 pwr_i = 2*pmin;
+ s16 pwr_i = 2 * pmin;
int i;
if (num_points < 2)
@@ -2437,7 +2444,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
}
if (edge_pwr)
- ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
+ ah->ah_txpower.txp_max_pwr = 4 * min(edge_pwr, max_chan_pwr);
}
@@ -2456,7 +2463,7 @@ static void
ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
s16 *table_max)
{
- u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
u8 *pcdac_tmp = ah->ah_txpower.tmpL[0];
u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
s16 min_pwr, max_pwr;
@@ -2475,8 +2482,8 @@ ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
/* Copy values from pcdac_tmp */
pwr_idx = min_pwr;
- for (i = 0 ; pwr_idx <= max_pwr &&
- pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
+ for (i = 0; pwr_idx <= max_pwr &&
+ pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
pcdac_out[pcdac_i++] = pcdac_tmp[i];
pwr_idx++;
}
@@ -2502,7 +2509,7 @@ static void
ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
s16 *table_max, u8 pdcurves)
{
- u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
u8 *pcdac_low_pwr;
u8 *pcdac_high_pwr;
u8 *pcdac_tmp;
@@ -2510,8 +2517,8 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
s16 max_pwr_idx;
s16 min_pwr_idx;
s16 mid_pwr_idx = 0;
- /* Edge flag turs on the 7nth bit on the PCDAC
- * to delcare the higher power curve (force values
+ /* Edge flag turns on the 7nth bit on the PCDAC
+ * to declare the higher power curve (force values
* to be greater than 64). If we only have one curve
* we don't need to set this, if we have 2 curves and
* fill the table backwards this can also be used to
@@ -2552,7 +2559,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
}
/* This is used when setting tx power*/
- ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
+ ah->ah_txpower.txp_min_idx = min_pwr_idx / 2;
/* Fill Power to PCDAC table backwards */
pwr = max_pwr_idx;
@@ -2561,14 +2568,14 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
* edge flag and set pcdac_tmp to lower
* power curve.*/
if (edge_flag == 0x40 &&
- (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
+ (2 * pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
edge_flag = 0x00;
pcdac_tmp = pcdac_low_pwr;
- pwr = mid_pwr_idx/2;
+ pwr = mid_pwr_idx / 2;
}
/* Don't go below 1, extrapolate below if we have
- * already swithced to the lower power curve -or
+ * already switched to the lower power curve -or
* we only have one curve and edge_flag is zero
* anyway */
if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
@@ -2596,7 +2603,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
static void
ath5k_write_pcdac_table(struct ath5k_hw *ah)
{
- u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
int i;
/*
@@ -2604,8 +2611,8 @@ ath5k_write_pcdac_table(struct ath5k_hw *ah)
*/
for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
ath5k_hw_reg_write(ah,
- (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
- (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
+ (((pcdac_out[2 * i + 0] << 8 | 0xff) & 0xffff) << 0) |
+ (((pcdac_out[2 * i + 1] << 8 | 0xff) & 0xffff) << 16),
AR5K_PHY_PCDAC_TXPOWER(i));
}
}
@@ -2788,12 +2795,8 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
* Write TX power values
*/
for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
- ath5k_hw_reg_write(ah,
- ((pdadc_out[4*i + 0] & 0xff) << 0) |
- ((pdadc_out[4*i + 1] & 0xff) << 8) |
- ((pdadc_out[4*i + 2] & 0xff) << 16) |
- ((pdadc_out[4*i + 3] & 0xff) << 24),
- AR5K_PHY_PDADC_TXPOWER(i));
+ u32 val = get_unaligned_le32(&pdadc_out[4 * i]);
+ ath5k_hw_reg_write(ah, val, AR5K_PHY_PDADC_TXPOWER(i));
}
}
@@ -2805,7 +2808,7 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
/*
* This is the main function that uses all of the above
* to set PCDAC/PDADC table on hw for the current channel.
- * This table is used for tx power calibration on the basband,
+ * This table is used for tx power calibration on the baseband,
* without it we get weird tx power levels and in some cases
* distorted spectral mask
*/
@@ -3116,13 +3119,13 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
int ret;
if (txpower > AR5K_TUNE_MAX_TXPOWER) {
- ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
+ ATH5K_ERR(ah, "invalid tx power: %u\n", txpower);
return -EINVAL;
}
ee_mode = ath5k_eeprom_mode_from_channel(channel);
if (ee_mode < 0) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid channel: %d\n", channel->center_freq);
return -EINVAL;
}
@@ -3223,7 +3226,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
{
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
+ ATH5K_DBG(ah, ATH5K_DEBUG_TXPOWER,
"changing txpower to %d\n", txpower);
return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower);
@@ -3434,7 +3437,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
* during ath5k_phy_calibrate) */
if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL, 0, false)) {
- ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
+ ATH5K_ERR(ah, "gain calibration timeout (%uMHz)\n",
channel->center_freq);
}
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index b18c5021aac3..65f10398999e 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -187,7 +187,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
break;
case AR5K_TX_QUEUE_XR_DATA:
if (ah->ah_version != AR5K_AR5212)
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"XR data queues only supported in"
" 5212!\n");
queue = AR5K_TX_QUEUE_ID_XR_DATA;
@@ -510,7 +510,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
{
struct ieee80211_channel *channel = ah->ah_current_channel;
- struct ath5k_softc *sc = ah->ah_sc;
struct ieee80211_rate *rate;
u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
@@ -546,9 +545,9 @@ 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)
- rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
+ rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
else
- rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
+ rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
@@ -622,7 +621,7 @@ int ath5k_hw_init_queues(struct ath5k_hw *ah)
for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
ret = ath5k_hw_reset_tx_queue(ah, i);
if (ret) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"failed to reset TX queue #%d\n", i);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index d12b827033c1..f5c1000045d3 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -72,7 +72,7 @@
#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */
#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */
-#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
+#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */
@@ -170,7 +170,7 @@
#define AR5K_TXCFG_SDMAMR_S 0
#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */
#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */
-#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */
+#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Trigger level mask */
#define AR5K_TXCFG_TXFULL_S 4
#define AR5K_TXCFG_TXFULL_0B 0x00000000
#define AR5K_TXCFG_TXFULL_64B 0x00000010
@@ -283,16 +283,16 @@
*/
#define AR5K_ISR 0x001c /* Register Address [5210] */
#define AR5K_PISR 0x0080 /* Register Address [5211+] */
-#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly received */
+#define AR5K_ISR_RXOK 0x00000001 /* Frame successfully received */
#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */
#define AR5K_ISR_RXERR 0x00000004 /* Receive error */
#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */
#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */
#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */
-#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */
+#define AR5K_ISR_TXOK 0x00000040 /* Frame successfully transmitted */
#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
-#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */
+#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout) */
#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
@@ -303,7 +303,7 @@
#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
-#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */
#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */
@@ -377,16 +377,16 @@
*/
#define AR5K_IMR 0x0020 /* Register Address [5210] */
#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */
-#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly received*/
+#define AR5K_IMR_RXOK 0x00000001 /* Frame successfully received*/
#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/
#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/
#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/
#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/
#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/
-#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/
+#define AR5K_IMR_TXOK 0x00000040 /* Frame successfully transmitted*/
#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/
#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/
-#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/
+#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout)*/
#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/
#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/
#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/
@@ -397,7 +397,7 @@
#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
-#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/
#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */
@@ -601,7 +601,7 @@
* QCU misc registers
*/
#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */
-#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
+#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame scheduling mask */
#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */
@@ -653,13 +653,13 @@
* registers [5211+]
*
* These registers control the various characteristics of each queue
- * for 802.11e (WME) combatibility so they go together with
+ * for 802.11e (WME) compatibility so they go together with
* QCU registers in pairs. For each queue we have a QCU mask register,
* (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
* a retry limit register (0x1080 - 0x10ac), a channel time register
* (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
* a sequence number register (0x1140 - 0x116c). It seems that "global"
- * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
+ * registers here affect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
* We use the same macros here for easier register access.
*
*/
@@ -779,7 +779,7 @@
* and it's used for generating pseudo-random
* number sequences.
*
- * (If i understand corectly, random numbers are
+ * (If i understand correctly, random numbers are
* used for idle sensing -multiplied with cwmin/max etc-)
*/
#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */
@@ -1007,7 +1007,7 @@
#define AR5K_PCIE_WAEN 0x407c
/*
- * PCI-E Serializer/Desirializer
+ * PCI-E Serializer/Deserializer
* registers
*/
#define AR5K_PCIE_SERDES 0x4080
@@ -1227,7 +1227,7 @@
AR5K_USEC_5210 : AR5K_USEC_5211)
#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */
#define AR5K_USEC_1_S 0
-#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */
+#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32MHz clock */
#define AR5K_USEC_32_S 7
#define AR5K_USEC_TX_LATENCY_5211 0x007fc000
#define AR5K_USEC_TX_LATENCY_5211_S 14
@@ -1328,16 +1328,16 @@
#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */
#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \
AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
-#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
-#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
-#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
-#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
-#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
-#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
-#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
+#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
+#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
+#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
+#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
+#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
+#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
+#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */
#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */
-#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
+#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */
#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */
#define AR5K_RX_FILTER_PHYERR \
@@ -1461,7 +1461,7 @@
* ADDAC test register [5211+]
*/
#define AR5K_ADDAC_TEST 0x8054 /* Register Address */
-#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */
+#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */
#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */
#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */
#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */
@@ -1632,7 +1632,7 @@
#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */
#define AR5K_SLEEP0_NEXT_DTIM_S 0
#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */
-#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */
+#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enhanced sleep control */
#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */
#define AR5K_SLEEP0_CABTO_S 24
@@ -1657,7 +1657,7 @@
/*
* TX power control (TPC) register
*
- * XXX: PCDAC steps (0.5dbm) or DBM ?
+ * XXX: PCDAC steps (0.5dBm) or dBm ?
*
*/
#define AR5K_TXPC 0x80e8 /* Register Address */
@@ -1673,7 +1673,7 @@
/*
* Profile count registers
*
- * These registers can be cleared and freezed with ATH5K_MIBC, but they do not
+ * These registers can be cleared and frozen with ATH5K_MIBC, but they do not
* generate a MIB interrupt.
* Instead of overflowing, they shift by one bit to the right. All registers
* shift together, i.e. when one reaches the max, all shift at the same time by
@@ -1838,7 +1838,7 @@
#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/
#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */
#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */
-#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */
+#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32kHz external) */
#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */
#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */
#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */
@@ -2002,7 +2002,7 @@
#define AR5K_PHY_AGCCTL_OFDM_DIV_DIS 0x00000008 /* Disable antenna diversity on OFDM modes */
#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */
#define AR5K_PHY_AGCTL_FLTR_CAL 0x00010000 /* Allow filter calibration (?) */
-#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
+#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automatically */
/*
* PHY noise floor status register (CCA = Clear Channel Assessment)
@@ -2038,7 +2038,7 @@
#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24
/* Low thresholds */
-#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c
+#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c
#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001
#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00
#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8
@@ -2089,7 +2089,7 @@
*
* It's obvious from the code that 0x989c is the buffer register but
* for the other special registers that we write to after sending each
- * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
+ * packet, i have no idea. So I'll name them BUFFER_CONTROL_X registers
* for now. It's interesting that they are also used for some other operations.
*/
@@ -2259,12 +2259,13 @@
#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */
#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000
#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */
-#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
- AR5K_PHY_FRAME_CTL_TXURN_ERR | \
- AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
- AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
- AR5K_PHY_FRAME_CTL_PARITY_ERR | \
- AR5K_PHY_FRAME_CTL_TIMING_ERR
+#define AR5K_PHY_FRAME_CTL_INI \
+ (AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
+ AR5K_PHY_FRAME_CTL_TXURN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
+ AR5K_PHY_FRAME_CTL_PARITY_ERR | \
+ AR5K_PHY_FRAME_CTL_TIMING_ERR)
/*
* PHY Tx Power adjustment register [5212A+]
@@ -2281,22 +2282,22 @@
#define AR5K_PHY_RADAR 0x9954
#define AR5K_PHY_RADAR_ENABLE 0x00000001
#define AR5K_PHY_RADAR_DISABLE 0x00000000
-#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
+#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
5-bits, units unknown {0..31}
(? MHz ?) */
#define AR5K_PHY_RADAR_INBANDTHR_S 1
-#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
+#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
6-bits, dBm range {0..63}
in dBm units. */
#define AR5K_PHY_RADAR_PRSSI_THR_S 6
-#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
+#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
6-bits, dBm range {0..63}
in dBm units. */
#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12
-#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
+#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
6-bits, dBm range {0..63}
in dBm units. */
#define AR5K_PHY_RADAR_RSSI_THR_S 18
@@ -2339,7 +2340,7 @@
#define AR5K_PHY_RESTART_DIV_GC_S 18
/*
- * RF Bus access request register (for synth-oly channel switching)
+ * RF Bus access request register (for synth-only channel switching)
*/
#define AR5K_PHY_RFBUS_REQ 0x997C
#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001
@@ -2381,7 +2382,7 @@
*/
#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
-#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */
+#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplifier Gain table base address */
#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2))
/*
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 126a4eab35f3..0686c5d8d56e 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -25,7 +25,7 @@
#include <asm/unaligned.h>
-#include <linux/pci.h> /* To determine if a card is pci-e */
+#include <linux/pci.h> /* To determine if a card is pci-e */
#include <linux/log2.h>
#include <linux/platform_device.h>
#include "ath5k.h"
@@ -142,10 +142,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
/* Set 32MHz USEC counter */
if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413) ||
- (ah->ah_radio == AR5K_RF2316) ||
- (ah->ah_radio == AR5K_RF2317))
- /* Remain on 40MHz clock ? */
+ (ah->ah_radio == AR5K_RF2413) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2316) ||
+ (ah->ah_radio == AR5K_RF2317))
+ /* Remain on 40MHz clock ? */
sclock = 40 - 1;
else
sclock = 32 - 1;
@@ -213,7 +214,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
usec_reg = (usec | sclock | txlat | rxlat);
ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC);
- /* On 5112 set tx frane to tx data start delay */
+ /* On 5112 set tx frame to tx data start delay */
if (ah->ah_radio == AR5K_RF5112) {
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
AR5K_PHY_RF_CTL2_TXF2TXD_START,
@@ -233,7 +234,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- u32 scal, spending;
+ u32 scal, spending, sclock;
/* Only set 32KHz settings if we have an external
* 32KHz crystal present */
@@ -317,6 +318,15 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
/* Set up tsf increment on each cycle */
AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2316) ||
+ (ah->ah_radio == AR5K_RF2317))
+ sclock = 40 - 1;
+ else
+ sclock = 32 - 1;
+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);
}
}
@@ -375,20 +385,20 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
{
u32 mask = flags ? flags : ~0U;
- volatile u32 *reg;
+ u32 __iomem *reg;
u32 regval;
u32 val = 0;
/* ah->ah_mac_srev is not available at this point yet */
- if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) {
- reg = (u32 *) AR5K_AR2315_RESET;
+ if (ah->devid >= AR5K_SREV_AR2315_R6) {
+ reg = (u32 __iomem *) AR5K_AR2315_RESET;
if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR2315_RESET_WMAC;
if (mask & AR5K_RESET_CTL_BASEBAND)
val |= AR5K_AR2315_RESET_BB_WARM;
} else {
- reg = (u32 *) AR5K_AR5312_RESET;
- if (to_platform_device(ah->ah_sc->dev)->id == 0) {
+ reg = (u32 __iomem *) AR5K_AR5312_RESET;
+ if (to_platform_device(ah->dev)->id == 0) {
if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR5312_RESET_WMAC0;
if (mask & AR5K_RESET_CTL_BASEBAND)
@@ -520,7 +530,7 @@ commit:
*/
int ath5k_hw_on_hold(struct ath5k_hw *ah)
{
- struct pci_dev *pdev = ah->ah_sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
u32 bus_flags;
int ret;
@@ -530,7 +540,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
/* Make sure device is awake */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
return ret;
}
@@ -539,7 +549,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
*
* Note: putting PCI core on warm reset on PCI-E cards
* results card to hang and always return 0xffff... so
- * we ingore that flag for PCI-E cards. On PCI cards
+ * we ignore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
*/
bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
@@ -555,14 +565,14 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
}
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
+ ATH5K_ERR(ah, "failed to put device on warm reset\n");
return -EIO;
}
/* ...wakeup again!*/
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
+ ATH5K_ERR(ah, "failed to put device on hold\n");
return ret;
}
@@ -574,7 +584,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
*/
int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
{
- struct pci_dev *pdev = ah->ah_sc->pdev;
+ struct pci_dev *pdev = ah->pdev;
u32 turbo, mode, clock, bus_flags;
int ret;
@@ -586,7 +596,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
/* Wakeup the device */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
return ret;
}
}
@@ -596,7 +606,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
*
* Note: putting PCI core on warm reset on PCI-E cards
* results card to hang and always return 0xffff... so
- * we ingore that flag for PCI-E cards. On PCI cards
+ * we ignore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
*/
bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
@@ -616,18 +626,18 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to reset the MAC Chip\n");
return -EIO;
}
/* ...wakeup again!...*/
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to resume the MAC Chip\n");
return ret;
}
- /* ...reset configuration regiter on Wisoc ...
+ /* ...reset configuration register on Wisoc ...
* ...clear reset control register and pull device out of
* warm reset on others */
if (ath5k_get_bus_type(ah) == ATH_AHB)
@@ -636,7 +646,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
ret = ath5k_hw_nic_reset(ah, 0);
if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+ ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n");
return -EIO;
}
@@ -677,7 +687,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
else
mode |= AR5K_PHY_MODE_MOD_DYN;
} else {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid radio modulation mode\n");
return -EINVAL;
}
@@ -693,18 +703,18 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
if (flags & CHANNEL_OFDM)
mode |= AR5K_PHY_MODE_MOD_OFDM;
else {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid radio modulation mode\n");
return -EINVAL;
}
} else {
- ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
+ ATH5K_ERR(ah, "invalid radio frequency mode\n");
return -EINVAL;
}
/*XXX: Can bwmode be used with dynamic mode ?
* (I don't think it supports 44MHz) */
- /* On 2425 initvals TURBO_SHORT is not pressent */
+ /* On 2425 initvals TURBO_SHORT is not present */
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
turbo = AR5K_PHY_TURBO_MODE |
(ah->ah_radio == AR5K_RF2425) ? 0 :
@@ -1066,7 +1076,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* RF Bus grant won't work if we have pending
* frames */
if (ret && fast) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"DMA didn't stop, falling back to normal reset\n");
fast = 0;
/* Non fatal, just continue with
@@ -1081,7 +1091,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
case CHANNEL_G:
if (ah->ah_version <= AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"G mode not available on 5210/5211");
return -EINVAL;
}
@@ -1091,7 +1101,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
case CHANNEL_B:
if (ah->ah_version < AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"B mode not available on 5210");
return -EINVAL;
}
@@ -1100,14 +1110,14 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
break;
case CHANNEL_XR:
if (ah->ah_version == AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"XR mode not available on 5211");
return -EINVAL;
}
mode = AR5K_MODE_XR;
break;
default:
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"invalid channel: %d\n", channel->center_freq);
return -EINVAL;
}
@@ -1119,13 +1129,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
if (fast) {
ret = ath5k_hw_phy_init(ah, channel, mode, true);
if (ret) {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"fast chan change failed, falling back to normal reset\n");
/* Non fatal, can happen eg.
* on mode change */
ret = 0;
} else {
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"fast chan change successful\n");
return 0;
}
@@ -1258,7 +1268,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
*/
ret = ath5k_hw_phy_init(ah, channel, mode, false);
if (ret) {
- ATH5K_ERR(ah->ah_sc,
+ ATH5K_ERR(ah,
"failed to initialize PHY (%i) !\n", ret);
return ret;
}
@@ -1277,11 +1287,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ath5k_hw_dma_init(ah);
- /* Enable 32KHz clock function for AR5212+ chips
+ /*
+ * Enable 32KHz clock function for AR5212+ chips
* Set clocks to 32KHz operation and use an
* external 32KHz crystal when sleeping if one
- * exists */
- if (ah->ah_version == AR5K_AR5212 &&
+ * exists.
+ * Disabled by default because it is also disabled in
+ * other drivers and it is known to cause stability
+ * issues on some devices
+ */
+ if (ah->ah_use_32khz_clock && ah->ah_version == AR5K_AR5212 &&
op_mode != NL80211_IFTYPE_AP)
ath5k_hw_set_sleep_clock(ah, true);
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h
index 16b67e84906d..5d11c23b4297 100644
--- a/drivers/net/wireless/ath/ath5k/rfbuffer.h
+++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h
@@ -254,7 +254,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = {
/* RFX112 (Derby 1) */
-/* BANK 6 len pos col */
+/* BANK 6 len pos col */
#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 }
#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 }
@@ -495,7 +495,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
/* BANK 2 len pos col */
#define AR5K_RF2413_RF_TURBO { 1, 1, 2 }
-/* BANK 6 len pos col */
+/* BANK 6 len pos col */
#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 }
#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 }
diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h
index 1354d8c392c8..ebfae052d89e 100644
--- a/drivers/net/wireless/ath/ath5k/rfgain.h
+++ b/drivers/net/wireless/ath/ath5k/rfgain.h
@@ -30,7 +30,7 @@ struct ath5k_ini_rfgain {
/* Initial RF Gain settings for RF5111 */
static const struct ath5k_ini_rfgain rfgain_5111[] = {
- /* 5Ghz 2Ghz */
+ /* 5GHz 2GHz */
{ AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } },
{ AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } },
{ AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } },
@@ -99,7 +99,7 @@ static const struct ath5k_ini_rfgain rfgain_5111[] = {
/* Initial RF Gain settings for RF5112 */
static const struct ath5k_ini_rfgain rfgain_5112[] = {
- /* 5Ghz 2Ghz */
+ /* 5GHz 2GHz */
{ AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } },
{ AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } },
{ AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } },
@@ -305,7 +305,7 @@ static const struct ath5k_ini_rfgain rfgain_2316[] = {
/* Initial RF Gain settings for RF5413 */
static const struct ath5k_ini_rfgain rfgain_5413[] = {
- /* 5Ghz 2Ghz */
+ /* 5GHz 2GHz */
{ AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
{ AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } },
{ AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } },
@@ -452,7 +452,7 @@ static const struct ath5k_ini_rfgain rfgain_2425[] = {
/* Check if our current measurement is inside our
* current variable attenuation window */
-#define AR5K_GAIN_CHECK_ADJUST(_g) \
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
struct ath5k_gain_opt_step {
diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c
index 41a877b73fce..945fc9f21e76 100644
--- a/drivers/net/wireless/ath/ath5k/rfkill.c
+++ b/drivers/net/wireless/ath/ath5k/rfkill.c
@@ -36,86 +36,81 @@
#include "base.h"
-static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+static inline void ath5k_rfkill_disable(struct ath5k_hw *ah)
{
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
- sc->rf_kill.gpio, sc->rf_kill.polarity);
- ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
- ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
+ ah->rf_kill.gpio, ah->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
+ ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, !ah->rf_kill.polarity);
}
-static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
+static inline void ath5k_rfkill_enable(struct ath5k_hw *ah)
{
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
- sc->rf_kill.gpio, sc->rf_kill.polarity);
- ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
- ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
+ ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
+ ah->rf_kill.gpio, ah->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
+ ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, ah->rf_kill.polarity);
}
-static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable)
+static inline void ath5k_rfkill_set_intr(struct ath5k_hw *ah, bool enable)
{
- struct ath5k_hw *ah = sc->ah;
u32 curval;
- ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
- curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
- ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+ ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);
+ curval = ath5k_hw_get_gpio(ah, ah->rf_kill.gpio);
+ ath5k_hw_set_gpio_intr(ah, ah->rf_kill.gpio, enable ?
!!curval : !curval);
}
static bool
-ath5k_is_rfkill_set(struct ath5k_softc *sc)
+ath5k_is_rfkill_set(struct ath5k_hw *ah)
{
/* configuring GPIO for input for some reason disables rfkill */
- /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
- return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
- sc->rf_kill.polarity;
+ /*ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);*/
+ return ath5k_hw_get_gpio(ah, ah->rf_kill.gpio) ==
+ ah->rf_kill.polarity;
}
static void
ath5k_tasklet_rfkill_toggle(unsigned long data)
{
- struct ath5k_softc *sc = (void *)data;
+ struct ath5k_hw *ah = (void *)data;
bool blocked;
- blocked = ath5k_is_rfkill_set(sc);
- wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked);
+ blocked = ath5k_is_rfkill_set(ah);
+ wiphy_rfkill_set_hw_state(ah->hw->wiphy, blocked);
}
void
ath5k_rfkill_hw_start(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
-
/* read rfkill GPIO configuration from EEPROM header */
- sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
- sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
+ ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
+ ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
- tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
- (unsigned long)sc);
+ tasklet_init(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
+ (unsigned long)ah);
- ath5k_rfkill_disable(sc);
+ ath5k_rfkill_disable(ah);
/* enable interrupt for rfkill switch */
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
- ath5k_rfkill_set_intr(sc, true);
+ ath5k_rfkill_set_intr(ah, true);
}
void
ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
{
- struct ath5k_softc *sc = ah->ah_sc;
-
/* disable interrupt for rfkill switch */
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
- ath5k_rfkill_set_intr(sc, false);
+ ath5k_rfkill_set_intr(ah, false);
- tasklet_kill(&sc->rf_kill.toggleq);
+ tasklet_kill(&ah->rf_kill.toggleq);
/* enable RFKILL when stopping HW so Wifi LED is turned off */
- ath5k_rfkill_enable(sc);
+ ath5k_rfkill_enable(ah);
}
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
index a073cdce1f15..0244a36ba958 100644
--- a/drivers/net/wireless/ath/ath5k/sysfs.c
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -11,8 +11,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
char *buf) \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
- struct ath5k_softc *sc = hw->priv; \
- return snprintf(buf, PAGE_SIZE, "%d\n", get); \
+ struct ath5k_hw *ah = hw->priv; \
+ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
} \
\
static ssize_t ath5k_attr_store_##name(struct device *dev, \
@@ -20,11 +20,13 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \
const char *buf, size_t count) \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
- struct ath5k_softc *sc = hw->priv; \
- int val; \
+ struct ath5k_hw *ah = hw->priv; \
+ int val, ret; \
\
- val = (int)simple_strtoul(buf, NULL, 10); \
- set(sc->ah, val); \
+ ret = kstrtoint(buf, 10, &val); \
+ if (ret < 0) \
+ return ret; \
+ set(ah, val); \
return count; \
} \
static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, \
@@ -36,25 +38,25 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
char *buf) \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
- struct ath5k_softc *sc = hw->priv; \
- return snprintf(buf, PAGE_SIZE, "%d\n", get); \
+ struct ath5k_hw *ah = hw->priv; \
+ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
} \
static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
/*** ANI ***/
-SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init);
-SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level,
+SIMPLE_SHOW_STORE(ani_mode, ah->ani_state.ani_mode, ath5k_ani_init);
+SIMPLE_SHOW_STORE(noise_immunity_level, ah->ani_state.noise_imm_level,
ath5k_ani_set_noise_immunity_level);
-SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level,
+SIMPLE_SHOW_STORE(spur_level, ah->ani_state.spur_level,
ath5k_ani_set_spur_immunity_level);
-SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level,
+SIMPLE_SHOW_STORE(firstep_level, ah->ani_state.firstep_level,
ath5k_ani_set_firstep_level);
-SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig,
+SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, ah->ani_state.ofdm_weak_sig,
ath5k_ani_set_ofdm_weak_signal_detection);
-SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig,
+SIMPLE_SHOW_STORE(cck_weak_signal_detection, ah->ani_state.cck_weak_sig,
ath5k_ani_set_cck_weak_signal_detection);
-SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level);
+SIMPLE_SHOW(spur_level_max, ah->ani_state.max_spur_level);
static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev,
struct device_attribute *attr,
@@ -96,14 +98,14 @@ static struct attribute_group ath5k_attribute_group_ani = {
/*** register / unregister ***/
int
-ath5k_sysfs_register(struct ath5k_softc *sc)
+ath5k_sysfs_register(struct ath5k_hw *ah)
{
- struct device *dev = sc->dev;
+ struct device *dev = ah->dev;
int err;
err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
if (err) {
- ATH5K_ERR(sc, "failed to create sysfs group\n");
+ ATH5K_ERR(ah, "failed to create sysfs group\n");
return err;
}
@@ -111,9 +113,9 @@ ath5k_sysfs_register(struct ath5k_softc *sc)
}
void
-ath5k_sysfs_unregister(struct ath5k_softc *sc)
+ath5k_sysfs_unregister(struct ath5k_hw *ah)
{
- struct device *dev = sc->dev;
+ struct device *dev = ah->dev;
sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
}
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
index 2de68adb6240..c741c871f4e9 100644
--- a/drivers/net/wireless/ath/ath5k/trace.h
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -12,22 +12,19 @@ static inline void trace_ ## name(proto) {}
struct sk_buff;
-#define PRIV_ENTRY __field(struct ath5k_softc *, priv)
-#define PRIV_ASSIGN __entry->priv = priv
-
#undef TRACE_SYSTEM
#define TRACE_SYSTEM ath5k
TRACE_EVENT(ath5k_rx,
- TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb),
+ TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb),
TP_ARGS(priv, skb),
TP_STRUCT__entry(
- PRIV_ENTRY
+ __field(struct ath5k_hw *, priv)
__field(unsigned long, skbaddr)
__dynamic_array(u8, frame, skb->len)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ __entry->priv = priv;
__entry->skbaddr = (unsigned long) skb;
memcpy(__get_dynamic_array(frame), skb->data, skb->len);
),
@@ -37,20 +34,20 @@ TRACE_EVENT(ath5k_rx,
);
TRACE_EVENT(ath5k_tx,
- TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+ TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb,
struct ath5k_txq *q),
TP_ARGS(priv, skb, q),
TP_STRUCT__entry(
- PRIV_ENTRY
+ __field(struct ath5k_hw *, priv)
__field(unsigned long, skbaddr)
__field(u8, qnum)
__dynamic_array(u8, frame, skb->len)
),
TP_fast_assign(
- PRIV_ASSIGN;
+ __entry->priv = priv;
__entry->skbaddr = (unsigned long) skb;
__entry->qnum = (u8) q->qnum;
memcpy(__get_dynamic_array(frame), skb->data, skb->len);
@@ -63,13 +60,13 @@ TRACE_EVENT(ath5k_tx,
);
TRACE_EVENT(ath5k_tx_complete,
- TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+ TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb,
struct ath5k_txq *q, struct ath5k_tx_status *ts),
TP_ARGS(priv, skb, q, ts),
TP_STRUCT__entry(
- PRIV_ENTRY
+ __field(struct ath5k_hw *, priv)
__field(unsigned long, skbaddr)
__field(u8, qnum)
__field(u8, ts_status)
@@ -78,7 +75,7 @@ TRACE_EVENT(ath5k_tx_complete,
),
TP_fast_assign(
- PRIV_ASSIGN;
+ __entry->priv = priv;
__entry->skbaddr = (unsigned long) skb;
__entry->qnum = (u8) q->qnum;
__entry->ts_status = ts->ts_status;
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 5b49cd03bfdf..0b36fcf8a280 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -27,6 +27,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {
.driver_data = AR5416_AR9100_DEVID,
},
{
+ .name = "ar933x_wmac",
+ .driver_data = AR9300_DEVID_AR9330,
+ },
+ {
.name = "ar934x_wmac",
.driver_data = AR9300_DEVID_AR9340,
},
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 441bb33f17ad..fac2c6da6ca4 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -627,6 +627,11 @@ static void ar5008_hw_init_bb(struct ath_hw *ah,
else
synthDelay /= 10;
+ if (IS_CHAN_HALF_RATE(chan))
+ synthDelay *= 2;
+ else if (IS_CHAN_QUARTER_RATE(chan))
+ synthDelay *= 4;
+
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
udelay(synthDelay + BASE_ACTIVATE_DELAY);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index f344cc2b3d59..9ff7c30573b8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -499,45 +499,6 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
}
}
-/*
- * If Async FIFO is enabled, the following counters change as MAC now runs
- * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
- *
- * The values below tested for ht40 2 chain.
- * Overwrite the delay/timeouts initialized in process ini.
- */
-void ar9002_hw_update_async_fifo(struct ath_hw *ah)
-{
- if (AR_SREV_9287_13_OR_LATER(ah)) {
- REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
- AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
- REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
- AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
- REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
- AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
-
- REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
- REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
-
- REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
- AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
- REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
- AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
- }
-}
-
-/*
- * We don't enable WEP aggregation on mac80211 but we keep this
- * around for HAL unification purposes.
- */
-void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
-{
- if (AR_SREV_9287_13_OR_LATER(ah)) {
- REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
- AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
- }
-}
-
/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
void ar9002_hw_attach_ops(struct ath_hw *ah)
{
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 077e8a6983fa..45b262fe2c25 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -28,11 +28,6 @@ static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
((struct ath_desc*) ds)->ds_link = ds_link;
}
-static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
-{
- *ds_link = &((struct ath_desc *)ds)->ds_link;
-}
-
static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
@@ -437,7 +432,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_desc_link = ar9002_hw_get_desc_link;
ops->get_isr = ar9002_hw_get_isr;
ops->fill_txdesc = ar9002_hw_fill_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 2fe0a34cbabc..3cbbb033fcea 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -111,7 +111,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
case 0:
- if ((freq % 20) == 0)
+ if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
+ aModeRefSel = 0;
+ else if ((freq % 20) == 0)
aModeRefSel = 3;
else if ((freq % 10) == 0)
aModeRefSel = 2;
@@ -129,8 +131,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
channelSel = CHANSEL_5G(freq);
/* RefDivA setting */
- REG_RMW_FIELD(ah, AR_AN_SYNTH9,
- AR_AN_SYNTH9_REFDIVA, refDivA);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9,
+ AR_AN_SYNTH9_REFDIVA,
+ AR_AN_SYNTH9_REFDIVA_S, refDivA);
}
@@ -447,26 +450,27 @@ static void ar9002_olc_init(struct ath_hw *ah)
static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
+ int ref_div = 5;
+ int pll_div = 0x2c;
u32 pll;
- pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+ if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) {
+ if (AR_SREV_9280_20(ah)) {
+ ref_div = 10;
+ pll_div = 0x50;
+ } else {
+ pll_div = 0x28;
+ }
+ }
+
+ pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV);
+ pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
- if (chan && IS_CHAN_5GHZ(chan)) {
- if (IS_CHAN_A_FAST_CLOCK(ah, chan))
- pll = 0x142c;
- else if (AR_SREV_9280_20(ah))
- pll = 0x2850;
- else
- pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
- } else {
- pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
- }
-
return pll;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index e8ac70da5ac7..2339728a7306 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -653,8 +653,8 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
- {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
- {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {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},
@@ -761,7 +761,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
{0x0000a3ec, 0x20202020},
{0x0000a3f0, 0x00000000},
{0x0000a3f4, 0x00000246},
- {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3f8, 0x0c9bd380},
{0x0000a3fc, 0x000f0f01},
{0x0000a400, 0x8fa91f01},
{0x0000a404, 0x00000000},
@@ -780,7 +780,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
{0x0000a43c, 0x00100000},
{0x0000a440, 0x00000000},
{0x0000a444, 0x00000000},
- {0x0000a448, 0x06000080},
+ {0x0000a448, 0x05000080},
{0x0000a44c, 0x00000001},
{0x0000a450, 0x00010000},
{0x0000a458, 0x00000000},
@@ -1500,8 +1500,6 @@ static const u32 ar9300_2p2_mac_core[][2] = {
{0x0000816c, 0x00000000},
{0x000081c0, 0x00000000},
{0x000081c4, 0x33332210},
- {0x000081c8, 0x00000000},
- {0x000081cc, 0x00000000},
{0x000081ec, 0x00000000},
{0x000081f0, 0x00000000},
{0x000081f4, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index ff8150e46f0e..d109c25417f4 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9003_phy.h"
#include "ar9003_eeprom.h"
@@ -1461,7 +1462,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
@@ -2616,7 +2617,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
@@ -3006,11 +3007,11 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
switch (param) {
case EEP_MAC_LSW:
- return eep->macAddr[0] << 8 | eep->macAddr[1];
+ return get_unaligned_be16(eep->macAddr);
case EEP_MAC_MID:
- return eep->macAddr[2] << 8 | eep->macAddr[3];
+ return get_unaligned_be16(eep->macAddr + 2);
case EEP_MAC_MSW:
- return eep->macAddr[4] << 8 | eep->macAddr[5];
+ return get_unaligned_be16(eep->macAddr + 4);
case EEP_REG_0:
return le16_to_cpu(pBase->regDmn[0]);
case EEP_REG_1:
@@ -3038,7 +3039,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
case EEP_CHAIN_MASK_REDUCE:
return (pBase->miscConfiguration >> 0x3) & 0x1;
case EEP_ANT_DIV_CTL1:
- return le32_to_cpu(eep->base_ext1.ant_div_control);
+ return eep->base_ext1.ant_div_control;
default:
return 0;
}
@@ -3324,6 +3325,8 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
read = ar9300_read_eeprom;
if (AR_SREV_9485(ah))
cptr = AR9300_BASE_ADDR_4K;
+ else if (AR_SREV_9330(ah))
+ cptr = AR9300_BASE_ADDR_512;
else
cptr = AR9300_BASE_ADDR;
ath_dbg(common, ATH_DBG_EEPROM,
@@ -3378,8 +3381,7 @@ found:
osize = length;
read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
- mchecksum = word[COMP_HDR_LEN + osize] |
- (word[COMP_HDR_LEN + osize + 1] << 8);
+ mchecksum = get_unaligned_le16(&word[COMP_HDR_LEN + osize]);
ath_dbg(common, ATH_DBG_EEPROM,
"checksum %x %x\n", checksum, mchecksum);
if (checksum == mchecksum) {
@@ -3442,7 +3444,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
{
int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ 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 {
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@@ -3523,7 +3525,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
}
}
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
/*
* main_lnaconf, alt_lnaconf, main_tb, alt_tb
@@ -3710,7 +3712,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
if (internal_regulator) {
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
int reg_pmu_set;
reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
@@ -3718,9 +3720,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return;
- reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
- (2 << 14) | (6 << 17) | (1 << 20) |
- (3 << 24) | (1 << 28);
+ if (AR_SREV_9330(ah)) {
+ if (ah->is_clk_25mhz) {
+ reg_pmu_set = (3 << 1) | (8 << 4) |
+ (3 << 8) | (1 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24);
+ } else {
+ reg_pmu_set = (4 << 1) | (7 << 4) |
+ (3 << 8) | (1 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24);
+ }
+ } else {
+ reg_pmu_set = (5 << 1) | (7 << 4) |
+ (1 << 8) | (2 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24) | (1 << 28);
+ }
REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
@@ -3751,7 +3768,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
}
} else {
- if (AR_SREV_9485(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))
@@ -3795,9 +3812,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
ar9003_hw_drive_strength_apply(ah);
ar9003_hw_atten_apply(ah, chan);
- if (!AR_SREV_9340(ah))
+ if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
ar9003_hw_internal_regulator_apply(ah);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
ar9003_hw_apply_tuning_caps(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 392bf0f8ff16..8efdec247c02 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -19,6 +19,8 @@
#include "ar9003_2p2_initvals.h"
#include "ar9485_initvals.h"
#include "ar9340_initvals.h"
+#include "ar9330_1p1_initvals.h"
+#include "ar9330_1p2_initvals.h"
/* General hardware code for the AR9003 hadware family */
@@ -29,7 +31,113 @@
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
- if (AR_SREV_9340(ah)) {
+ if (AR_SREV_9330_11(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9331_1p1_mac_core,
+ ARRAY_SIZE(ar9331_1p1_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9331_1p1_mac_postamble,
+ ARRAY_SIZE(ar9331_1p1_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9331_1p1_baseband_core,
+ ARRAY_SIZE(ar9331_1p1_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9331_1p1_baseband_postamble,
+ ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9331_1p1_radio_core,
+ ARRAY_SIZE(ar9331_1p1_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9331_1p1_soc_preamble,
+ ARRAY_SIZE(ar9331_1p1_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9331_1p1_soc_postamble,
+ ARRAY_SIZE(ar9331_1p1_soc_postamble), 2);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+ 5);
+
+ /* additional clock settings */
+ if (ah->is_clk_25mhz)
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p1_xtal_25M,
+ ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p1_xtal_40M,
+ ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
+ } else if (AR_SREV_9330_12(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9331_1p2_mac_core,
+ ARRAY_SIZE(ar9331_1p2_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9331_1p2_mac_postamble,
+ ARRAY_SIZE(ar9331_1p2_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9331_1p2_baseband_core,
+ ARRAY_SIZE(ar9331_1p2_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9331_1p2_baseband_postamble,
+ ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9331_1p2_radio_core,
+ ARRAY_SIZE(ar9331_1p2_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9331_1p2_soc_preamble,
+ ARRAY_SIZE(ar9331_1p2_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9331_1p2_soc_postamble,
+ ARRAY_SIZE(ar9331_1p2_soc_postamble), 2);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+ 5);
+
+ /* additional clock settings */
+ if (ah->is_clk_25mhz)
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p2_xtal_25M,
+ ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p2_xtal_40M,
+ ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
+ } else if (AR_SREV_9340(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -220,7 +328,17 @@ 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_9340(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),
@@ -237,7 +355,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
5);
break;
case 1:
- if (AR_SREV_9340(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),
@@ -254,7 +382,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
5);
break;
case 2:
- if (AR_SREV_9340(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),
@@ -271,7 +409,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
5);
break;
case 3:
- if (AR_SREV_9340(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),
@@ -295,7 +443,17 @@ 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_9340(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),
@@ -312,7 +470,17 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
2);
break;
case 1:
- if (AR_SREV_9340(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),
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 10d71f7d3fc2..8ff0b88a29b9 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -43,13 +43,6 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
}
-static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
-{
- struct ar9003_txc *ads = ds;
-
- *ds_link = &ads->link;
-}
-
static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
@@ -236,6 +229,7 @@ static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
+ struct ar9003_txc *txc = (struct ar9003_txc *) ds;
struct ar9003_txs *ads;
u32 status;
@@ -245,7 +239,11 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
if ((status & AR_TxDone) == 0)
return -EINPROGRESS;
- ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+ ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+ if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
+ ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+ else
+ return -ENOENT;
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
@@ -261,7 +259,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid);
- ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId);
ts->ts_tstamp = ads->status4;
ts->ts_status = 0;
@@ -498,7 +495,6 @@ 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_desc_link = ar9003_hw_get_desc_link;
ops->get_isr = ar9003_hw_get_isr;
ops->fill_txdesc = ar9003_hw_fill_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc;
@@ -629,8 +625,7 @@ 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;
-
- if (rxsp->status11 & AR_KeyMiss)
+ else if (rxsp->status11 & AR_KeyMiss)
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index e4d6a87ec538..f80d1d633980 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -21,6 +21,36 @@ 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;
+
+ /*
+ * 3 bits for modalHeader5G.papdRateMaskHt20
+ * is used for sub-band disabling of PAPRD.
+ * 5G band is divided into 3 sub-bands -- upper,
+ * middle, lower.
+ * if bit 30 of modalHeader5G.papdRateMaskHt20 is set
+ * -- disable PAPRD for upper band 5GHz
+ * if bit 29 of modalHeader5G.papdRateMaskHt20 is set
+ * -- disable PAPRD for middle band 5GHz
+ * if bit 28 of modalHeader5G.papdRateMaskHt20 is set
+ * -- disable PAPRD for lower band 5GHz
+ */
+
+ if (IS_CHAN_5GHZ(chan)) {
+ if (chan->channel >= UPPER_5G_SUB_BAND_START) {
+ if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+ & BIT(30))
+ val = false;
+ } else if (chan->channel >= MID_5G_SUB_BAND_START) {
+ if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+ & BIT(29))
+ val = false;
+ } else {
+ if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+ & BIT(28))
+ val = false;
+ }
+ }
if (val) {
ah->paprd_table_write_done = true;
@@ -46,11 +76,10 @@ EXPORT_SYMBOL(ar9003_paprd_enable);
static int ar9003_get_training_power_2g(struct ath_hw *ah)
{
- struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
- struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
+ struct ath9k_channel *chan = ah->curchan;
unsigned int power, scale, delta;
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
+ scale = ar9003_get_paprd_scale_factor(ah, chan);
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
@@ -67,20 +96,10 @@ static int ar9003_get_training_power_2g(struct ath_hw *ah)
static int ar9003_get_training_power_5g(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
- struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
struct ath9k_channel *chan = ah->curchan;
unsigned int power, scale, delta;
- if (chan->channel >= 5700)
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
- AR9300_PAPRD_SCALE_1);
- else if (chan->channel >= 5400)
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
- AR9300_PAPRD_SCALE_2);
- else
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
- AR9300_PAPRD_SCALE_1);
+ scale = ar9003_get_paprd_scale_factor(ah, chan);
if (IS_CHAN_HT40(chan))
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
@@ -94,7 +113,23 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
if (delta > scale)
return -1;
- power += 2 * get_streams(common->tx_chainmask);
+ switch (get_streams(common->tx_chainmask)) {
+ case 1:
+ delta = 6;
+ break;
+ case 2:
+ delta = 4;
+ break;
+ case 3:
+ delta = 2;
+ break;
+ default:
+ delta = 0;
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "Invalid tx-chainmask: %u\n", common->tx_chainmask);
+ }
+
+ power += delta;
return power;
}
@@ -119,15 +154,16 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
else
training_power = ar9003_get_training_power_5g(ah);
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "Training power: %d, Target power: %d\n",
+ training_power, ah->paprd_target_power);
+
if (training_power < 0) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"PAPRD target power delta out of range");
return -ERANGE;
}
ah->paprd_training_power = training_power;
- ath_dbg(common, ATH_DBG_CALIBRATE,
- "Training power: %d, Target power: %d\n",
- ah->paprd_training_power, ah->paprd_target_power);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
ah->paprd_ratemask);
@@ -230,7 +266,7 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
memset(index, 0, sizeof(ah->paprd_gain_table_index));
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
entry[i] = REG_READ(ah, reg);
index[i] = (entry[i] >> 24) & 0xff;
reg += 4;
@@ -240,13 +276,13 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
int target_power)
{
- int olpc_gain_delta = 0;
+ int olpc_gain_delta = 0, cl_gain_mod;
int alpha_therm, alpha_volt;
int therm_cal_value, volt_cal_value;
int therm_value, volt_value;
int thermal_gain_corr, voltage_gain_corr;
int desired_scale, desired_gain = 0;
- u32 reg;
+ u32 reg_olpc = 0, reg_cl_gain = 0;
REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
@@ -265,15 +301,29 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
- if (chain == 0)
- reg = AR_PHY_TPC_11_B0;
- else if (chain == 1)
- reg = AR_PHY_TPC_11_B1;
- else
- reg = AR_PHY_TPC_11_B2;
+ switch (chain) {
+ case 0:
+ reg_olpc = AR_PHY_TPC_11_B0;
+ reg_cl_gain = AR_PHY_CL_TAB_0;
+ break;
+ case 1:
+ reg_olpc = AR_PHY_TPC_11_B1;
+ reg_cl_gain = AR_PHY_CL_TAB_1;
+ break;
+ case 2:
+ reg_olpc = AR_PHY_TPC_11_B2;
+ reg_cl_gain = AR_PHY_CL_TAB_2;
+ break;
+ default:
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+ "Invalid chainmask: %d\n", chain);
+ break;
+ }
- olpc_gain_delta = REG_READ_FIELD(ah, reg,
+ olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
AR_PHY_TPC_11_OLPC_GAIN_DELTA);
+ cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
+ AR_PHY_CL_TAB_CL_GAIN_MOD);
if (olpc_gain_delta >= 128)
olpc_gain_delta = olpc_gain_delta - 256;
@@ -283,7 +333,7 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
(128 / 2)) / 128;
desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
- voltage_gain_corr + desired_scale;
+ voltage_gain_corr + desired_scale + cl_gain_mod;
return desired_gain;
}
@@ -721,7 +771,7 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
gain_index = 0;
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
if (ah->paprd_gain_table_index[i] >= desired_gain)
break;
gain_index++;
@@ -795,7 +845,26 @@ EXPORT_SYMBOL(ar9003_paprd_init_table);
bool ar9003_paprd_is_done(struct ath_hw *ah)
{
- return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ int paprd_done, agc2_pwr;
+ paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+ if (paprd_done == 0x1) {
+ agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
+
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+ "AGC2_PWR = 0x%x training done = 0x%x\n",
+ agc2_pwr, paprd_done);
+ /*
+ * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE'
+ * when the training is completely done, otherwise retraining is
+ * done to make sure the value is in ideal range
+ */
+ if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
+ paprd_done = 0;
+ }
+
+ return !!paprd_done;
}
EXPORT_SYMBOL(ar9003_paprd_is_done);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 892c48b15434..1baca8e4715d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -75,7 +75,19 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
freq = centers.synth_center;
if (freq < 4800) { /* 2 GHz, fractional mode */
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah)) {
+ u32 chan_frac;
+ u32 div;
+
+ if (ah->is_clk_25mhz)
+ div = 75;
+ else
+ div = 120;
+
+ channelSel = (freq * 4) / div;
+ chan_frac = (((freq * 4) % div) * 0x20000) / div;
+ channelSel = (channelSel << 17) | chan_frac;
+ } else if (AR_SREV_9485(ah)) {
u32 chan_frac;
/*
@@ -104,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
u32 chan_frac;
channelSel = (freq * 2) / 75;
- chan_frac = ((freq % 75) * 0x20000) / 75;
+ chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
channelSel = (channelSel << 17) | chan_frac;
} else {
channelSel = CHANSEL_5G(freq);
@@ -168,7 +180,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
* is out-of-band and can be ignored.
*/
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) {
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
IS_CHAN_2GHZ(chan));
if (spur_fbin_ptr[0] == 0) /* No spur */
@@ -193,7 +205,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
for (i = 0; i < max_spur_cnts; i++) {
negative = 0;
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
IS_CHAN_2GHZ(chan)) - synth_freq;
else
@@ -659,6 +671,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
REG_WRITE_ARRAY(&ah->iniModesAdditional,
modesIndex, regWrites);
+ if (AR_SREV_9300(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);
@@ -1074,7 +1089,10 @@ static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
{
ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
- ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
+ if (AR_SREV_9330(ah))
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ;
+ else
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
@@ -1196,8 +1214,17 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
- antconf->lna1_lna2_delta = -9;
- antconf->div_group = 2;
+
+ if (AR_SREV_9330_11(ah)) {
+ antconf->lna1_lna2_delta = -9;
+ antconf->div_group = 1;
+ } else if (AR_SREV_9485(ah)) {
+ antconf->lna1_lna2_delta = -9;
+ antconf->div_group = 2;
+ } else {
+ antconf->lna1_lna2_delta = -3;
+ antconf->div_group = 0;
+ }
}
static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 443090d278e3..6de3f0bc18e6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -332,6 +332,8 @@
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100
+#define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118
+
/*
* AGC Field Definitions
*/
@@ -623,11 +625,11 @@
#define AR_PHY_65NM_CH2_RXTX1 0x16900
#define AR_PHY_65NM_CH2_RXTX2 0x16904
-#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c)
+#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : 0x16284)
#define AR_CH0_TOP2_XPABIASLVL 0xf000
#define AR_CH0_TOP2_XPABIASLVL_S 12
-#define AR_CH0_XTAL (AR_SREV_9485(ah) ? 0x16290 : 0x16294)
+#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : 0x16290)
#define AR_CH0_XTAL_CAPINDAC 0x7f000000
#define AR_CH0_XTAL_CAPINDAC_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
@@ -1119,6 +1121,9 @@
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8
+#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/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
new file mode 100644
index 000000000000..f11d9b2677fd
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
@@ -0,0 +1,1147 @@
+/*
+ * 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 INITVALS_9330_1P1_H
+#define INITVALS_9330_1P1_H
+
+static const u32 ar9331_1p1_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+ {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+ {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+ {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+ {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+ {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+ {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+ {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52},
+ {0x0000a2e0, 0xffb31c84, 0xffb31c84, 0xffb31c84, 0xffb31c84},
+ {0x0000a2e4, 0xff43e000, 0xff43e000, 0xff43e000, 0xff43e000},
+ {0x0000a2e8, 0xfffc0000, 0xfffc0000, 0xfffc0000, 0xfffc0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3d001620, 0x3d001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x3f001621, 0x3f001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x42001640, 0x42001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x44001641, 0x44001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x46001642, 0x46001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49001644, 0x49001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4c001a81, 0x4c001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4f001a83, 0x4f001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x52001c84, 0x52001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001ce3, 0x55001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x59001ce5, 0x59001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5d001ce9, 0x5d001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x64001eec, 0x64001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x64001eec, 0x64001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+ {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+ {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+ {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+ {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p1_xtal_25M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000002f8},
+ {0x00008244, 0x0010f3d7},
+ {0x0000824c, 0x0001e7ae},
+ {0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p1_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73800000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x00016044, 0x03db62db},
+ {0x00016048, 0x6c924268},
+ {0x0001604c, 0x000f0278},
+ {0x00016050, 0x4db6db8c},
+ {0x00016054, 0x6db60000},
+ {0x00016080, 0x00080000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x14214514},
+ {0x0001608c, 0x119f081c},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd411eb84},
+ {0x000160a0, 0xc2108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160ac, 0x24651800},
+ {0x000160b0, 0x03284f3e},
+ {0x000160b4, 0x92480040},
+ {0x000160c0, 0x006db6db},
+ {0x000160c4, 0x0186db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x6de6c300},
+ {0x000160d0, 0x14500820},
+ {0x00016100, 0x04cb0001},
+ {0x00016104, 0xfff80015},
+ {0x00016108, 0x00080010},
+ {0x0001610c, 0x00170000},
+ {0x00016140, 0x10804000},
+ {0x00016144, 0x01884080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x01000015},
+ {0x00016284, 0x14d20000},
+ {0x00016288, 0x00318000},
+ {0x0001628c, 0x50000000},
+ {0x00016290, 0x4b96210f},
+ {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},
+};
+
+static const u32 ar9331_1p1_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p1[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00060005},
+ {0x0000a004, 0x00810080},
+ {0x0000a008, 0x00830082},
+ {0x0000a00c, 0x00850084},
+ {0x0000a010, 0x01820181},
+ {0x0000a014, 0x01840183},
+ {0x0000a018, 0x01880185},
+ {0x0000a01c, 0x018a0189},
+ {0x0000a020, 0x02850284},
+ {0x0000a024, 0x02890288},
+ {0x0000a028, 0x028b028a},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x24242428},
+ {0x0000a098, 0x171e1e1e},
+ {0x0000a09c, 0x02020b0b},
+ {0x0000a0a0, 0x02020202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x22072208},
+ {0x0000a0c4, 0x22052206},
+ {0x0000a0c8, 0x22032204},
+ {0x0000a0cc, 0x22012202},
+ {0x0000a0d0, 0x221f2200},
+ {0x0000a0d4, 0x221d221e},
+ {0x0000a0d8, 0x33023303},
+ {0x0000a0dc, 0x33003301},
+ {0x0000a0e0, 0x331e331f},
+ {0x0000a0e4, 0x4402331d},
+ {0x0000a0e8, 0x44004401},
+ {0x0000a0ec, 0x441e441f},
+ {0x0000a0f0, 0x55025503},
+ {0x0000a0f4, 0x55005501},
+ {0x0000a0f8, 0x551e551f},
+ {0x0000a0fc, 0x6602551d},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9331_1p1_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a8f6b},
+ {0x0000980c, 0x04800000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x5f3ca3de},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0x00000000},
+ {0x00009c08, 0x03200000},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x1883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c00400},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038233c},
+ {0x00009e24, 0x9927b515},
+ {0x00009e28, 0x12ef0200},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2dc, 0x00000000},
+ {0x0000a2e0, 0x00000000},
+ {0x0000a2e4, 0x00000000},
+ {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000006},
+ {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00000000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x04000000},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+ {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+ {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+ {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+ {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_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 ar9331_1p1_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p1_xtal_40M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000004c2},
+ {0x00008244, 0x0010f400},
+ {0x0000824c, 0x0001e800},
+ {0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p1_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, 0x13881c20},
+ {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},
+ {0x00008170, 0x18486200},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008248, 0x00000800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9d400010},
+ {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 ar9331_common_rx_gain_1p1[][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},
+};
+
+static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
+ {0},
+ {3},
+ {0},
+ {0},
+};
+
+static const u32 ar9331_1p1_chansel_xtal_25M[] = {
+ 0x0101479e,
+ 0x0101d027,
+ 0x010258af,
+ 0x0102e138,
+ 0x010369c0,
+ 0x0103f249,
+ 0x01047ad1,
+ 0x0105035a,
+ 0x01058be2,
+ 0x0106146b,
+ 0x01069cf3,
+ 0x0107257c,
+ 0x0107ae04,
+ 0x0108f5b2,
+};
+
+static const u32 ar9331_1p1_chansel_xtal_40M[] = {
+ 0x00a0ccbe,
+ 0x00a12213,
+ 0x00a17769,
+ 0x00a1ccbe,
+ 0x00a22213,
+ 0x00a27769,
+ 0x00a2ccbe,
+ 0x00a32213,
+ 0x00a37769,
+ 0x00a3ccbe,
+ 0x00a42213,
+ 0x00a47769,
+ 0x00a4ccbe,
+ 0x00a5998b,
+};
+
+#endif /* INITVALS_9330_1P1_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
new file mode 100644
index 000000000000..0e6ca0834b34
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
@@ -0,0 +1,1080 @@
+/*
+ * 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 INITVALS_9330_1P2_H
+#define INITVALS_9330_1P2_H
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+ {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+ {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+ {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p2_xtal_25M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000002f8},
+ {0x00008244, 0x0010f3d7},
+ {0x0000824c, 0x0001e7ae},
+ {0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p2_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73800000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x00016044, 0x03d6d2db},
+ {0x00016048, 0x6c924268},
+ {0x0001604c, 0x000f0278},
+ {0x00016050, 0x4db6db8c},
+ {0x00016054, 0x6db60000},
+ {0x00016080, 0x00080000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x14214514},
+ {0x0001608c, 0x119f081c},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd411eb84},
+ {0x000160a0, 0xc2108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160ac, 0x24651800},
+ {0x000160b0, 0x03284f3e},
+ {0x000160b4, 0x92480040},
+ {0x000160c0, 0x006db6db},
+ {0x000160c4, 0x0186db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x6de6c300},
+ {0x000160d0, 0x14500820},
+ {0x00016100, 0x04cb0001},
+ {0x00016104, 0xfff80015},
+ {0x00016108, 0x00080010},
+ {0x0001610c, 0x00170000},
+ {0x00016140, 0x10804000},
+ {0x00016144, 0x01884080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x01000015},
+ {0x00016284, 0x14d20000},
+ {0x00016288, 0x00318000},
+ {0x0001628c, 0x50000000},
+ {0x00016290, 0x4b96210f},
+ {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},
+};
+
+static const u32 ar9331_1p2_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p2[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00060005},
+ {0x0000a004, 0x00810080},
+ {0x0000a008, 0x00830082},
+ {0x0000a00c, 0x00850084},
+ {0x0000a010, 0x01820181},
+ {0x0000a014, 0x01840183},
+ {0x0000a018, 0x01880185},
+ {0x0000a01c, 0x018a0189},
+ {0x0000a020, 0x02850284},
+ {0x0000a024, 0x02890288},
+ {0x0000a028, 0x028b028a},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x24242428},
+ {0x0000a098, 0x171e1e1e},
+ {0x0000a09c, 0x02020b0b},
+ {0x0000a0a0, 0x02020202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x22072208},
+ {0x0000a0c4, 0x22052206},
+ {0x0000a0c8, 0x22032204},
+ {0x0000a0cc, 0x22012202},
+ {0x0000a0d0, 0x221f2200},
+ {0x0000a0d4, 0x221d221e},
+ {0x0000a0d8, 0x33023303},
+ {0x0000a0dc, 0x33003301},
+ {0x0000a0e0, 0x331e331f},
+ {0x0000a0e4, 0x4402331d},
+ {0x0000a0e8, 0x44004401},
+ {0x0000a0ec, 0x441e441f},
+ {0x0000a0f0, 0x55025503},
+ {0x0000a0f4, 0x55005501},
+ {0x0000a0f8, 0x551e551f},
+ {0x0000a0fc, 0x6602551d},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9331_1p2_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a8f6b},
+ {0x0000980c, 0x04800000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x5f3ca3de},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0x00000000},
+ {0x00009c08, 0x03200000},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x1883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c00400},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038233c},
+ {0x00009e24, 0x9927b515},
+ {0x00009e28, 0x12ef0200},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2dc, 0x00000000},
+ {0x0000a2e0, 0x00000000},
+ {0x0000a2e4, 0x00000000},
+ {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000006},
+ {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00000000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x04000000},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_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 ar9331_1p2_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p2_xtal_40M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000004c2},
+ {0x00008244, 0x0010f400},
+ {0x0000824c, 0x0001e800},
+ {0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p2_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, 0x13881c20},
+ {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},
+ {0x00008170, 0x18486200},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008248, 0x00000800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9d400010},
+ {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 ar9331_common_rx_gain_1p2[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x01800082},
+ {0x0000a014, 0x01820181},
+ {0x0000a018, 0x01840183},
+ {0x0000a01c, 0x01880185},
+ {0x0000a020, 0x018a0189},
+ {0x0000a024, 0x02850284},
+ {0x0000a028, 0x02890288},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x21212128},
+ {0x0000a098, 0x171c1c1c},
+ {0x0000a09c, 0x02020212},
+ {0x0000a0a0, 0x00000202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x111f1100},
+ {0x0000a0c8, 0x111d111e},
+ {0x0000a0cc, 0x111b111c},
+ {0x0000a0d0, 0x22032204},
+ {0x0000a0d4, 0x22012202},
+ {0x0000a0d8, 0x221f2200},
+ {0x0000a0dc, 0x221d221e},
+ {0x0000a0e0, 0x33013302},
+ {0x0000a0e4, 0x331f3300},
+ {0x0000a0e8, 0x4402331e},
+ {0x0000a0ec, 0x44004401},
+ {0x0000a0f0, 0x441e441f},
+ {0x0000a0f4, 0x55015502},
+ {0x0000a0f8, 0x551f5500},
+ {0x0000a0fc, 0x6602551e},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000296},
+};
+
+#endif /* INITVALS_9330_1P2_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index f75068b4b310..46393f90f16c 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -19,6 +19,7 @@
#include <linux/etherdevice.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/completion.h>
@@ -54,8 +55,6 @@ struct ath_node;
(_l) &= ((_sz) - 1); \
} while (0)
-#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
-
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
@@ -102,6 +101,11 @@ enum buffer_type {
#define ATH_TXSTATUS_RING_SIZE 64
+#define DS2PHYS(_dd, _ds) \
+ ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
struct ath_descdma {
void *dd_desc;
dma_addr_t dd_desc_paddr;
@@ -179,7 +183,7 @@ enum ATH_AGGR_STATUS {
struct ath_txq {
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
u32 axq_qnum; /* ath9k hardware queue number */
- u32 *axq_link;
+ void *axq_link;
struct list_head axq_q;
spinlock_t axq_lock;
u32 axq_depth;
@@ -188,7 +192,6 @@ struct ath_txq {
bool axq_tx_inprogress;
struct list_head axq_acq;
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
- struct list_head txq_fifo_pending;
u8 txq_headidx;
u8 txq_tailidx;
int pending_frames;
@@ -428,6 +431,7 @@ 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);
void ath_ani_calibrate(unsigned long data);
+void ath_start_ani(struct ath_common *common);
/**********/
/* BTCOEX */
@@ -579,7 +583,7 @@ struct ath9k_vif_iter_data {
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
- int nwds; /* number of nwd vifs */
+ int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
int nothers; /* number of vifs not specified above. */
};
@@ -669,12 +673,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
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);
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
- struct ath9k_channel *hchan);
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
bool ath9k_uses_beacons(int type);
#ifdef CONFIG_ATH9K_PCI
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index d4d8ceced89b..0d13ff74a68b 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#define FUDGE 2
@@ -360,6 +361,7 @@ void ath_beacon_tasklet(unsigned long data)
struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL;
struct ieee80211_vif *vif;
+ struct ath_tx_status ts;
int slot;
u32 bfaddr, bc = 0;
@@ -384,7 +386,9 @@ 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);
}
return;
@@ -464,6 +468,11 @@ void ath_beacon_tasklet(unsigned long data)
ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ }
}
}
@@ -496,7 +505,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
u32 nexttbtt, intval;
/* NB: the beacon interval is kept internally in TU's */
- intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
+ intval = TU_TO_USEC(conf->beacon_interval);
intval /= ATH_BCBUF; /* for staggered beacons */
nexttbtt = intval;
@@ -543,7 +552,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
}
memset(&bs, 0, sizeof(bs));
- intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = conf->beacon_interval;
/*
* Setup dtim and cfp parameters according to
@@ -652,22 +661,13 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- u32 tsf, delta, intval, nexttbtt;
+ u32 tsf, intval, nexttbtt;
ath9k_reset_beacon_status(sc);
- tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
- intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
-
- if (!sc->beacon.bc_tstamp)
- nexttbtt = tsf + intval;
- else {
- if (tsf > sc->beacon.bc_tstamp)
- delta = (tsf - sc->beacon.bc_tstamp);
- else
- delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
- nexttbtt = tsf + intval - (delta % intval);
- }
+ intval = TU_TO_USEC(conf->beacon_interval);
+ tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval);
+ nexttbtt = tsf + intval;
ath_dbg(common, ATH_DBG_BEACON,
"IBSS nexttbtt %u intval %u (%u)\n",
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 41ce0b139886..6635c377dc00 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -50,7 +50,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
.bt_first_slot_time = 5,
.bt_hold_rx_clear = true,
};
- u32 i;
+ u32 i, idx;
bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
if (AR_SREV_9300_20_OR_LATER(ah))
@@ -73,8 +73,10 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
AR_BT_DISABLE_BT_ANT;
- for (i = 0; i < 32; i++)
- ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
+ for (i = 0; i < 32; i++) {
+ idx = (debruijn32 << i) >> 27;
+ ah->hw_gen_timers.gen_timer_index[idx] = i;
+ }
}
EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index d55ffd7d4bd2..d1eb89611ff7 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -176,6 +176,56 @@ static const struct file_operations fops_rx_chainmask = {
.llseek = default_llseek,
};
+static ssize_t read_file_disable_ani(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);
+ char buf[32];
+ unsigned int len;
+
+ len = sprintf(buf, "%d\n", common->disable_ani);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_disable_ani(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ unsigned long disable_ani;
+ 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, &disable_ani))
+ return -EINVAL;
+
+ common->disable_ani = !!disable_ani;
+
+ if (disable_ani) {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
+ } else {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_disable_ani = {
+ .read = read_file_disable_ani,
+ .write = write_file_disable_ani,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
static ssize_t read_file_dma(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -550,6 +600,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PR("MPDUs Queued: ", queued);
PR("MPDUs Completed: ", completed);
+ PR("MPDUs XRetried: ", xretries);
PR("Aggregates: ", a_aggr);
PR("AMPDUs Queued HW:", a_queued_hw);
PR("AMPDUs Queued SW:", a_queued_sw);
@@ -587,7 +638,6 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PRQLE("axq_q empty: ", axq_q);
PRQLE("axq_acq empty: ", axq_acq);
- PRQLE("txq_fifo_pending: ", txq_fifo_pending);
for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
PRQLE(tmp, txq_fifo[i]);
@@ -699,7 +749,6 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
char *buf;
unsigned int len = 0, size = 8000;
ssize_t retval = 0;
- const char *tmp;
unsigned int reg;
struct ath9k_vif_iter_data iter_data;
@@ -709,31 +758,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
if (buf == NULL)
return -ENOMEM;
- switch (sc->sc_ah->opmode) {
- case NL80211_IFTYPE_ADHOC:
- tmp = "ADHOC";
- break;
- case NL80211_IFTYPE_MESH_POINT:
- tmp = "MESH";
- break;
- case NL80211_IFTYPE_AP:
- tmp = "AP";
- break;
- case NL80211_IFTYPE_STATION:
- tmp = "STATION";
- break;
- default:
- tmp = "???";
- break;
- }
-
ath9k_ps_wakeup(sc);
len += snprintf(buf + len, size - len,
"curbssid: %pM\n"
"OP-Mode: %s(%i)\n"
"Beacon-Timer-Register: 0x%x\n",
common->curbssid,
- tmp, (int)(sc->sc_ah->opmode),
+ ath_opmode_to_string(sc->sc_ah->opmode),
+ (int)(sc->sc_ah->opmode),
REG_READ(ah, AR_BEACON_PERIOD));
reg = REG_READ(ah, AR_TIMER_MODE);
@@ -807,7 +839,10 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
else
TX_STAT_INC(qnum, a_completed);
} else {
- TX_STAT_INC(qnum, completed);
+ if (bf_isxretried(bf))
+ TX_STAT_INC(qnum, xretries);
+ else
+ TX_STAT_INC(qnum, completed);
}
if (ts->ts_status & ATH9K_TXERR_FIFO)
@@ -1160,6 +1195,8 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.debugfs_phy, sc, &fops_rx_chainmask);
debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
+ debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
+ sc->debug.debugfs_phy, sc, &fops_disable_ani);
debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
sc, &fops_regidx);
debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 8ce6ad80f4e2..4a04510e1111 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -116,6 +116,7 @@ struct ath_tx_stats {
u32 tx_bytes_all;
u32 queued;
u32 completed;
+ u32 xretries;
u32 a_aggr;
u32 a_queued_hw;
u32 a_queued_sw;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 5b1e894f3d67..47cc95086e6e 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9002_phy.h"
@@ -203,11 +204,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
case EEP_NFTHRESH_2:
return pModal->noiseFloorThreshCh[0];
case EEP_MAC_LSW:
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ return get_unaligned_be16(pBase->macAddr);
case EEP_MAC_MID:
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ return get_unaligned_be16(pBase->macAddr + 2);
case EEP_MAC_MSW:
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
case EEP_REG_1:
@@ -331,10 +332,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
- ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
- ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
- ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
REG_WRITE(ah, regOffset, reg32);
ath_dbg(common, ATH_DBG_EEPROM,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 343fc9f946db..d6f6b192f450 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9002_phy.h"
@@ -195,11 +196,11 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
case EEP_NFTHRESH_2:
return pModal->noiseFloorThreshCh[0];
case EEP_MAC_LSW:
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ return get_unaligned_be16(pBase->macAddr);
case EEP_MAC_MID:
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ return get_unaligned_be16(pBase->macAddr + 2);
case EEP_MAC_MSW:
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
case EEP_REG_1:
@@ -434,10 +435,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
(672 << 2) + regChainOffset;
for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0)
- | ((pdadcValues[4*j + 1] & 0xFF) << 8)
- | ((pdadcValues[4*j + 2] & 0xFF) << 16)
- | ((pdadcValues[4*j + 3] & 0xFF) << 24);
+ reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
REG_WRITE(ah, regOffset, reg32);
regOffset += 4;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 17f0a6806207..b9540a992616 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "hw.h"
#include "ar9002_phy.h"
@@ -276,11 +277,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
case EEP_NFTHRESH_2:
return pModal[1].noiseFloorThreshCh[0];
case EEP_MAC_LSW:
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ return get_unaligned_be16(pBase->macAddr);
case EEP_MAC_MID:
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ return get_unaligned_be16(pBase->macAddr + 2);
case EEP_MAC_MSW:
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
case EEP_REG_1:
@@ -831,10 +832,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
- ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
- ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
- ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
REG_WRITE(ah, regOffset, reg32);
ath_dbg(common, ATH_DBG_EEPROM,
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 260f1f37a60e..d3f4a59cd456 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/unaligned.h>
#include "htc.h"
/* identify firmware images */
@@ -49,6 +50,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
.driver_info = AR9280_USB }, /* Netgear WNDA3200 */
{ USB_DEVICE(0x083A, 0xA704),
.driver_info = AR9280_USB }, /* SMC Networks */
+ { USB_DEVICE(0x0411, 0x017f),
+ .driver_info = AR9280_USB }, /* Sony UWA-BR100 */
{ USB_DEVICE(0x0cf3, 0x20ff),
.driver_info = STORAGE_DEVICE },
@@ -127,12 +130,14 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
static void hif_usb_mgmt_cb(struct urb *urb)
{
struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
- struct hif_device_usb *hif_dev = cmd->hif_dev;
+ struct hif_device_usb *hif_dev;
bool txok = true;
if (!cmd || !cmd->skb || !cmd->hif_dev)
return;
+ hif_dev = cmd->hif_dev;
+
switch (urb->status) {
case 0:
break;
@@ -555,8 +560,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
ptr = (u8 *) skb->data;
- pkt_len = ptr[index] + (ptr[index+1] << 8);
- pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
+ pkt_len = get_unaligned_le16(ptr + index);
+ pkt_tag = get_unaligned_le16(ptr + index + 2);
if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
RX_STAT_INC(skb_dropped);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index aa6a73118706..57fe22b24247 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -79,7 +79,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
memset(&bs, 0, sizeof(bs));
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
/*
@@ -194,7 +194,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
u8 cmd_rsp;
u64 tsf;
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
intval /= ATH9K_HTC_MAX_BCN_VIF;
nexttbtt = intval;
@@ -250,7 +250,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
u8 cmd_rsp;
u64 tsf;
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
nexttbtt = intval;
/*
@@ -427,7 +427,7 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
u16 intval;
int slot;
- intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = priv->cur_beacon_conf.beacon_interval;
tsf = be64_to_cpu(swba->tsf);
tsftu = TSF_TO_TU(tsf >> 32, tsf);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index aa48b3abbc48..d3ff33c71aa5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -623,11 +623,8 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
pBase9287->openLoopPwrCntl);
}
- len += snprintf(buf + len, size - len,
- "%20s : %02X:%02X:%02X:%02X:%02X:%02X\n",
- "MacAddress",
- pBase->macAddr[0], pBase->macAddr[1], pBase->macAddr[2],
- pBase->macAddr[3], pBase->macAddr[4], pBase->macAddr[5]);
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
if (len > size)
len = size;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 61e6d3950718..3bea7ea86f0a 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -754,6 +754,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
hw->wiphy->interface_modes =
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 7b7796895432..7212acb2bd6c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1294,11 +1294,16 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
u32 rfilt;
mutex_lock(&priv->mutex);
- ath9k_htc_ps_wakeup(priv);
-
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
+ if (priv->op_flags & OP_INVALID) {
+ ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY,
+ "Unable to configure filter on invalid state\n");
+ return;
+ }
+ ath9k_htc_ps_wakeup(priv);
+
priv->rxfilter = *total_flags;
rfilt = ath9k_htc_calcrxfilter(priv);
ath9k_hw_setrxfilter(priv->ah, rfilt);
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 2f3e07263fcb..cb29e8875386 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -39,11 +39,6 @@ static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,
ath9k_hw_ops(ah)->set_desc_link(ds, link);
}
-static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
- u32 **link)
-{
- ath9k_hw_ops(ah)->get_desc_link(ds, link);
-}
static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1be7c8bbef84..8006ce0c7357 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -87,7 +87,10 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
unsigned int clockrate;
- if (!ah->curchan) /* should really check for CCK instead */
+ /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah))
+ clockrate = 117;
+ else if (!ah->curchan) /* should really check for CCK instead */
clockrate = ATH9K_CLOCK_RATE_CCK;
else if (conf->channel->band == IEEE80211_BAND_2GHZ)
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
@@ -99,6 +102,13 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
if (conf_is_ht40(conf))
clockrate *= 2;
+ if (ah->curchan) {
+ if (IS_CHAN_HALF_RATE(ah->curchan))
+ clockrate /= 2;
+ if (IS_CHAN_QUARTER_RATE(ah->curchan))
+ clockrate /= 4;
+ }
+
common->clockrate = clockrate;
}
@@ -251,6 +261,15 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
case AR5416_AR9100_DEVID:
ah->hw_version.macVersion = AR_SREV_VERSION_9100;
break;
+ case AR9300_DEVID_AR9330:
+ ah->hw_version.macVersion = AR_SREV_VERSION_9330;
+ if (ah->get_mac_revision) {
+ ah->hw_version.macRev = ah->get_mac_revision();
+ } else {
+ val = REG_READ(ah, AR_SREV);
+ ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+ }
+ return;
case AR9300_DEVID_AR9340:
ah->hw_version.macVersion = AR_SREV_VERSION_9340;
val = REG_READ(ah, AR_SREV);
@@ -551,6 +570,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9287:
case AR_SREV_VERSION_9271:
case AR_SREV_VERSION_9300:
+ case AR_SREV_VERSION_9330:
case AR_SREV_VERSION_9485:
case AR_SREV_VERSION_9340:
break;
@@ -561,7 +581,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)
return -EOPNOTSUPP;
}
- if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
+ AR_SREV_9330(ah))
ah->is_pciexpress = false;
ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
@@ -604,7 +625,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)
else
ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
- ah->bb_watchdog_timeout_ms = 25;
+ if (AR_SREV_9330(ah))
+ ah->bb_watchdog_timeout_ms = 85;
+ else
+ ah->bb_watchdog_timeout_ms = 25;
common->state = ATH_HW_INITIALIZED;
@@ -630,6 +654,7 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR2427_DEVID_PCIE:
case AR9300_DEVID_PCIE:
case AR9300_DEVID_AR9485_PCIE:
+ case AR9300_DEVID_AR9330:
case AR9300_DEVID_AR9340:
break;
default:
@@ -722,6 +747,39 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
udelay(1000);
+ } else if (AR_SREV_9330(ah)) {
+ u32 ddr_dpll2, pll_control2, kd;
+
+ if (ah->is_clk_25mhz) {
+ ddr_dpll2 = 0x18e82f01;
+ pll_control2 = 0xe04a3d;
+ kd = 0x1d;
+ } else {
+ ddr_dpll2 = 0x19e82f01;
+ pll_control2 = 0x886666;
+ kd = 0x3d;
+ }
+
+ /* program DDR PLL ki and kd value */
+ REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2);
+
+ /* program DDR PLL phase_shift */
+ REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+ AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
+
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+ udelay(1000);
+
+ /* program refdiv, nint, frac to RTC register */
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2);
+
+ /* program BB PLL kd and ki value */
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06);
+
+ /* program BB PLL phase_shift */
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+ AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
} else if (AR_SREV_9340(ah)) {
u32 regval, pll2_divint, pll2_divfrac, refdiv;
@@ -763,7 +821,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
udelay(1000);
/* Switch the core clock for ar9271 to 117Mhz */
@@ -847,6 +905,13 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
}
}
+static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
+{
+ u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
+ val = min(val, (u32) 0xFFFF);
+ REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
+}
+
static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
{
u32 val = ath9k_hw_mac_to_clks(ah, us);
@@ -884,25 +949,60 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
void ath9k_hw_init_global_settings(struct ath_hw *ah)
{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+ 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 slottime;
int sifstime;
+ int rx_lat = 0, tx_lat = 0, eifs = 0;
+ u32 reg;
ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
ah->misc_mode);
+ if (!chan)
+ return;
+
if (ah->misc_mode != 0)
REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
- if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
- sifstime = 16;
- else
- sifstime = 10;
+ rx_lat = 37;
+ tx_lat = 54;
+
+ if (IS_CHAN_HALF_RATE(chan)) {
+ eifs = 175;
+ rx_lat *= 2;
+ tx_lat *= 2;
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ tx_lat += 11;
+
+ slottime = 13;
+ sifstime = 32;
+ } else if (IS_CHAN_QUARTER_RATE(chan)) {
+ eifs = 340;
+ rx_lat *= 4;
+ tx_lat *= 4;
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ tx_lat += 22;
+
+ slottime = 21;
+ sifstime = 64;
+ } else {
+ eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS);
+ reg = REG_READ(ah, AR_USEC);
+ rx_lat = MS(reg, AR_USEC_RX_LAT);
+ tx_lat = MS(reg, AR_USEC_TX_LAT);
+
+ slottime = ah->slottime;
+ if (IS_CHAN_5GHZ(chan))
+ sifstime = 16;
+ else
+ sifstime = 10;
+ }
/* As defined by IEEE 802.11-2007 17.3.8.6 */
- slottime = ah->slottime + 3 * ah->coverage_class;
- acktimeout = slottime + sifstime;
+ acktimeout = slottime + sifstime + 3 * ah->coverage_class;
/*
* Workaround for early ACK timeouts, add an offset to match the
@@ -914,11 +1014,20 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
acktimeout += 64 - sifstime - ah->slottime;
- ath9k_hw_setslottime(ah, ah->slottime);
+ 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);
if (ah->globaltxtimeout != (u32) -1)
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
+
+ REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs));
+ REG_RMW(ah, AR_USEC,
+ (common->clockrate - 1) |
+ SM(rx_lat, AR_USEC_RX_LAT) |
+ SM(tx_lat, AR_USEC_TX_LAT),
+ AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC);
+
}
EXPORT_SYMBOL(ath9k_hw_init_global_settings);
@@ -1114,6 +1223,41 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
rst_flags |= AR_RTC_RC_MAC_COLD;
}
+ if (AR_SREV_9330(ah)) {
+ int npend = 0;
+ int i;
+
+ /* AR9330 WAR:
+ * call external reset function to reset WMAC if:
+ * - doing a cold reset
+ * - we have pending frames in the TX queues
+ */
+
+ for (i = 0; i < AR_NUM_QCU; i++) {
+ npend = ath9k_hw_numtxpending(ah, i);
+ if (npend)
+ break;
+ }
+
+ if (ah->external_reset &&
+ (npend || type == ATH9K_RESET_COLD)) {
+ int reset_err = 0;
+
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+ "reset MAC via external reset\n");
+
+ reset_err = ah->external_reset();
+ if (reset_err) {
+ ath_err(ath9k_hw_common(ah),
+ "External reset failed, err=%d\n",
+ reset_err);
+ return false;
+ }
+
+ REG_WRITE(ah, AR_RTC_RESET, 1);
+ }
+ }
+
REG_WRITE(ah, AR_RTC_RC, rst_flags);
REGWRITE_BUFFER_FLUSH(ah);
@@ -1487,9 +1631,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_global_settings(ah);
- if (!AR_SREV_9300_20_OR_LATER(ah)) {
- ar9002_hw_update_async_fifo(ah);
- ar9002_hw_enable_wep_aggregation(ah);
+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+ REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
+ AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
+ REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
+ AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
+ REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
}
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
@@ -1545,7 +1693,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
}
#ifdef __BIG_ENDIAN
- else if (AR_SREV_9340(ah))
+ else if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
else
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@@ -1785,16 +1933,16 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
REG_WRITE(ah, AR_BEACON_PERIOD,
- TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+ TU_TO_USEC(bs->bs_intval));
REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
- TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+ TU_TO_USEC(bs->bs_intval));
REGWRITE_BUFFER_FLUSH(ah);
REG_RMW_FIELD(ah, AR_RSSI_THR,
AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
- beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
+ beaconintval = bs->bs_intval;
if (bs->bs_sleepduration > beaconintval)
beaconintval = bs->bs_sleepduration;
@@ -1849,12 +1997,22 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers);
/* HW Capabilities */
/*******************/
+static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
+{
+ eeprom_chainmask &= chip_chainmask;
+ if (eeprom_chainmask)
+ return eeprom_chainmask;
+ else
+ return chip_chainmask;
+}
+
int ath9k_hw_fill_cap_info(struct ath_hw *ah)
{
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+ unsigned int chip_chainmask;
u16 eeval;
u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
@@ -1891,6 +2049,15 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (eeval & AR5416_OPFLAGS_11G)
pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
+ if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah))
+ chip_chainmask = 1;
+ else if (!AR_SREV_9280_20_OR_LATER(ah))
+ chip_chainmask = 7;
+ else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
+ chip_chainmask = 3;
+ else
+ chip_chainmask = 7;
+
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
/*
* For AR9271 we will temporarilly uses the rx chainmax as read from
@@ -1907,6 +2074,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
/* Use rx_chainmask from EEPROM. */
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
+ pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+ pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
/* enable key search for every frame in an aggregate */
@@ -1983,7 +2153,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9300_20_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
- if (!AR_SREV_9485(ah))
+ if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))
pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
@@ -1996,10 +2166,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
} else {
pCap->tx_desc_len = sizeof(struct ath_desc);
- if (AR_SREV_9280_20(ah) &&
- ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
- AR5416_EEP_MINOR_VER_16) ||
- ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
+ if (AR_SREV_9280_20(ah))
pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
}
@@ -2025,7 +2192,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
/*
* enable the diversity-combining algorithm only when
@@ -2574,6 +2741,7 @@ static struct {
{ AR_SREV_VERSION_9287, "9287" },
{ AR_SREV_VERSION_9271, "9271" },
{ AR_SREV_VERSION_9300, "9300" },
+ { AR_SREV_VERSION_9330, "9330" },
{ AR_SREV_VERSION_9485, "9485" },
};
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 4b157c53d1a8..6acd0f975ae1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -45,6 +45,7 @@
#define AR9300_DEVID_PCIE 0x0030
#define AR9300_DEVID_AR9340 0x0031
#define AR9300_DEVID_AR9485_PCIE 0x0032
+#define AR9300_DEVID_AR9330 0x0035
#define AR5416_AR9100_DEVID 0x000b
@@ -142,6 +143,8 @@
#define AR_KEYTABLE_SIZE 128
#define POWER_UP_TIME 10000
#define SPUR_RSSI_THRESH 40
+#define UPPER_5G_SUB_BAND_START 5700
+#define MID_5G_SUB_BAND_START 5400
#define CAB_TIMEOUT_VAL 10
#define BEACON_TIMEOUT_VAL 10
@@ -157,8 +160,9 @@
#define ATH9K_HW_RX_HP_QDEPTH 16
#define ATH9K_HW_RX_LP_QDEPTH 128
-#define PAPRD_GAIN_TABLE_ENTRIES 32
-#define PAPRD_TABLE_SZ 24
+#define PAPRD_GAIN_TABLE_ENTRIES 32
+#define PAPRD_TABLE_SZ 24
+#define PAPRD_IDEAL_AGC2_PWR_RANGE 0xe0
enum ath_hw_txq_subtype {
ATH_TXQ_AC_BE = 0,
@@ -403,7 +407,6 @@ struct ath9k_beacon_state {
u32 bs_nexttbtt;
u32 bs_nextdtim;
u32 bs_intval;
-#define ATH9K_BEACON_PERIOD 0x0000ffff
#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
u32 bs_dtimperiod;
u16 bs_cfpperiod;
@@ -603,7 +606,6 @@ struct ath_hw_ops {
int power_off);
void (*rx_enable)(struct ath_hw *ah);
void (*set_desc_link)(void *ds, u32 link);
- void (*get_desc_link)(void *ds, u32 **link);
bool (*calibrate)(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
@@ -862,6 +864,8 @@ struct ath_hw {
u32 ent_mode;
bool is_clk_25mhz;
+ int (*get_mac_revision)(void);
+ int (*external_reset)(void);
};
struct ath_bus_ops {
@@ -981,8 +985,6 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
int ar9002_hw_rf_claim(struct ath_hw *ah);
void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
-void ar9002_hw_update_async_fifo(struct ath_hw *ah);
-void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
/*
* Code specific to AR9003, we stuff these here to avoid callbacks
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 45c585a337e9..ac5107172f94 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/ath9k_platform.h>
@@ -196,6 +197,19 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
return val;
}
+static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset,
+ u32 set, u32 clr)
+{
+ u32 val;
+
+ val = ioread32(sc->mem + reg_offset);
+ val &= ~clr;
+ val |= set;
+ iowrite32(val, sc->mem + reg_offset);
+
+ return val;
+}
+
static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -204,16 +218,12 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl
unsigned long uninitialized_var(flags);
u32 val;
- if (ah->config.serialize_regmode == SER_REG_MODE_ON)
+ if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
spin_lock_irqsave(&sc->sc_serial_rw, flags);
-
- val = ioread32(sc->mem + reg_offset);
- val &= ~clr;
- val |= set;
- iowrite32(val, sc->mem + reg_offset);
-
- if (ah->config.serialize_regmode == SER_REG_MODE_ON)
+ val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+ } else
+ val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
return val;
}
@@ -245,7 +255,7 @@ static void setup_ht_cap(struct ath_softc *sc,
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
- if (AR_SREV_9485(ah))
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
max_streams = 1;
else if (AR_SREV_9300_20_OR_LATER(ah))
max_streams = 3;
@@ -298,10 +308,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
struct list_head *head, const char *name,
int nbuf, int ndesc, bool is_tx)
{
-#define DS2PHYS(_dd, _ds) \
- ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
u8 *ds;
struct ath_buf *bf;
@@ -396,9 +402,6 @@ fail2:
fail:
memset(dd, 0, sizeof(*dd));
return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
}
void ath9k_init_crypto(struct ath_softc *sc)
@@ -519,7 +522,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
-
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->config.txpowlimit = ATH_TXPOWER_MAX;
@@ -575,6 +577,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
sc->sc_ah->gpio_val = pdata->gpio_val;
sc->sc_ah->led_pin = pdata->led_pin;
ah->is_clk_25mhz = pdata->is_clk_25mhz;
+ ah->get_mac_revision = pdata->get_mac_revision;
+ ah->external_reset = pdata->external_reset;
}
common = ath9k_hw_common(ah);
@@ -585,6 +589,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
common->priv = sc;
common->debug_mask = ath9k_debug;
common->btcoex_enabled = ath9k_btcoex_enable == 1;
+ common->disable_ani = false;
spin_lock_init(&common->cc_lock);
spin_lock_init(&sc->sc_serial_rw);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index c2091f1f4096..b6b523a897e5 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -645,8 +645,7 @@ 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;
-
- if (ads.ds_rxstatus8 & AR_KeyMiss)
+ else if (ads.ds_rxstatus8 & AR_KeyMiss)
rs->rs_status |= ATH9K_RXERR_DECRYPT;
}
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 2ca351fe6d3c..9098aaad97a9 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -62,14 +62,12 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
if (txq->axq_depth || !list_empty(&txq->axq_acq))
pending = true;
- else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
- pending = !list_empty(&txq->txq_fifo_pending);
spin_unlock_bh(&txq->axq_lock);
return pending;
}
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
+static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
{
unsigned long flags;
bool ret;
@@ -136,7 +134,7 @@ void ath9k_ps_restore(struct ath_softc *sc)
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}
-static void ath_start_ani(struct ath_common *common)
+void ath_start_ani(struct ath_common *common)
{
struct ath_hw *ah = common->ah;
unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -219,7 +217,7 @@ static int ath_update_survey_stats(struct ath_softc *sc)
* by reseting the chip. To accomplish this we must first cleanup any pending
* DMA, then restart stuff.
*/
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
struct ath9k_channel *hchan)
{
struct ath_hw *ah = sc->sc_ah;
@@ -302,7 +300,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
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);
- ath_start_ani(common);
+ if (!common->disable_ani)
+ ath_start_ani(common);
}
ps_restore:
@@ -361,7 +360,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0) {
- ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n");
+ ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");
dev_kfree_skb_any(skb);
return false;
}
@@ -370,7 +369,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
if (!time_left)
- ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
+ ath_dbg(common, ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on TX chain %d\n",
chain);
@@ -394,12 +393,14 @@ void ath_paprd_calibrate(struct work_struct *work)
if (!caldata)
return;
+ ath9k_ps_wakeup(sc);
+
if (ar9003_paprd_init_table(ah) < 0)
- return;
+ goto fail_paprd;
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
- return;
+ goto fail_paprd;
skb_put(skb, len);
memset(skb->data, 0, len);
@@ -411,7 +412,6 @@ void ath_paprd_calibrate(struct work_struct *work)
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
- ath9k_ps_wakeup(sc);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(common->tx_chainmask & BIT(chain)))
continue;
@@ -431,11 +431,18 @@ void ath_paprd_calibrate(struct work_struct *work)
if (!ath_paprd_send_frame(sc, skb, chain))
goto fail_paprd;
- if (!ar9003_paprd_is_done(ah))
+ if (!ar9003_paprd_is_done(ah)) {
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "PAPRD not yet done on chain %d\n", chain);
break;
+ }
- if (ar9003_paprd_create_curve(ah, caldata, chain) != 0)
+ if (ar9003_paprd_create_curve(ah, caldata, chain)) {
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "PAPRD create curve failed on chain %d\n",
+ chain);
break;
+ }
chain_ok = 1;
}
@@ -515,24 +522,19 @@ void ath_ani_calibrate(unsigned long data)
common->ani.checkani_timer = timestamp;
}
- /* Skip all processing if there's nothing to do. */
- if (longcal || shortcal || aniflag) {
- /* Call ANI routine if necessary */
- if (aniflag) {
- spin_lock_irqsave(&common->cc_lock, flags);
- ath9k_hw_ani_monitor(ah, ah->curchan);
- ath_update_survey_stats(sc);
- spin_unlock_irqrestore(&common->cc_lock, flags);
- }
+ /* Call ANI routine if necessary */
+ if (aniflag) {
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath9k_hw_ani_monitor(ah, ah->curchan);
+ ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+ }
- /* Perform calibration if necessary */
- if (longcal || shortcal) {
- common->ani.caldone =
- ath9k_hw_calibrate(ah,
- ah->curchan,
- common->rx_chainmask,
- longcal);
- }
+ /* Perform calibration if necessary */
+ if (longcal || shortcal) {
+ common->ani.caldone =
+ ath9k_hw_calibrate(ah, ah->curchan,
+ common->rx_chainmask, longcal);
}
ath9k_ps_restore(sc);
@@ -615,8 +617,11 @@ void ath_hw_check(struct work_struct *work)
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)
+ 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;
@@ -635,7 +640,9 @@ static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
/* 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
@@ -672,7 +679,9 @@ void ath9k_tasklet(unsigned long data)
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;
}
@@ -868,7 +877,7 @@ chip_reset:
#undef SCHED_INTR
}
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
+static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -974,10 +983,10 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
sc->hw_busy_count = 0;
/* Stop ANI */
+
del_timer_sync(&common->ani.timer);
ath9k_ps_wakeup(sc);
- spin_lock_bh(&sc->sc_pcu_lock);
ieee80211_stop_queues(hw);
@@ -1020,10 +1029,11 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
}
ieee80211_wake_queues(hw);
- spin_unlock_bh(&sc->sc_pcu_lock);
/* Start ANI */
- ath_start_ani(common);
+ if (!common->disable_ani)
+ ath_start_ani(common);
+
ath9k_ps_restore(sc);
return r;
@@ -1261,7 +1271,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(ah);
- ath9k_hw_configpcipowersave(ah, 1, 1);
spin_unlock_bh(&sc->sc_pcu_lock);
@@ -1412,10 +1421,14 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
ath9k_hw_set_interrupts(ah, ah->imask);
/* Set up ANI */
- if ((iter_data.naps + iter_data.nadhocs) > 0) {
+ if (iter_data.naps > 0) {
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_flags |= SC_OP_ANI_RUN;
- ath_start_ani(common);
+
+ if (!common->disable_ani) {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
} else {
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
@@ -1952,50 +1965,38 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
- switch (sc->sc_ah->opmode) {
- case NL80211_IFTYPE_ADHOC:
- /* There can be only one vif available */
+ /*
+ * Skip iteration if primary station vif's bss info
+ * was not changed
+ */
+ if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
+ return;
+
+ if (bss_conf->assoc) {
+ sc->sc_flags |= SC_OP_PRIM_STA_VIF;
+ avp->primary_sta_vif = true;
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
- /* configure beacon */
- if (bss_conf->enable_beacon)
- ath_beacon_config(sc, vif);
- break;
- case NL80211_IFTYPE_STATION:
- /*
- * Skip iteration if primary station vif's bss info
- * was not changed
- */
- if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
- break;
-
- if (bss_conf->assoc) {
- sc->sc_flags |= SC_OP_PRIM_STA_VIF;
- avp->primary_sta_vif = true;
- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
- common->curaid = bss_conf->aid;
- ath9k_hw_write_associd(sc->sc_ah);
- ath_dbg(common, ATH_DBG_CONFIG,
+ ath_dbg(common, ATH_DBG_CONFIG,
"Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, common->curbssid);
- ath_beacon_config(sc, vif);
- /*
- * Request a re-configuration of Beacon related timers
- * on the receipt of the first Beacon frame (i.e.,
- * after time sync with the AP).
- */
- sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
- /* Reset rssi stats */
- sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ ath_beacon_config(sc, vif);
+ /*
+ * Request a re-configuration of Beacon related timers
+ * on the receipt of the first Beacon frame (i.e.,
+ * after time sync with the AP).
+ */
+ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+ /* Reset rssi stats */
+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ if (!common->disable_ani) {
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
}
- break;
- default:
- break;
+
}
}
@@ -2005,6 +2006,9 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
+ if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+ return;
+
/* Reconfigure bss info */
if (avp->primary_sta_vif && !bss_conf->assoc) {
ath_dbg(common, ATH_DBG_CONFIG,
@@ -2023,8 +2027,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
* None of station vifs are associated.
* Clear bssid & aid
*/
- if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
- !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
+ if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
ath9k_hw_write_associd(sc->sc_ah);
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
@@ -2054,6 +2057,26 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
common->curbssid, common->curaid);
}
+ if (changed & BSS_CHANGED_IBSS) {
+ /* There can be only one vif available */
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+
+ if (bss_conf->ibss_joined) {
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+ if (!common->disable_ani) {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
+ } else {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
+ }
+ }
+
/* Enable transmission of beacons (AP, IBSS, MESH) */
if ((changed & BSS_CHANGED_BEACON) ||
((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
@@ -2308,9 +2331,9 @@ 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);
@@ -2334,7 +2357,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
return false;
}
-int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
+static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index ba7f36ab0a74..c04a6c3cac7f 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -379,7 +379,30 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
};
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
- struct ieee80211_tx_rate *rate);
+ struct ieee80211_tx_rate *rate)
+{
+ int rix = 0, i = 0;
+ static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
+
+ if (!(rate->flags & IEEE80211_TX_RC_MCS))
+ return rate->idx;
+
+ while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
+ rix++; i++;
+ }
+
+ rix += rate->idx + rate_table->mcs_start;
+
+ if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+ (rate->flags & IEEE80211_TX_RC_SHORT_GI))
+ rix = rate_table->info[rix].ht_index;
+ else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ rix = rate_table->info[rix].sgi_index;
+ else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ rix = rate_table->info[rix].cw40index;
+
+ return rix;
+}
static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
struct ath_rate_priv *ath_rc_priv)
@@ -533,7 +556,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
[valid_rate_count] = j;
ath_rc_priv->valid_phy_ratecnt[phy] += 1;
ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
- hi = A_MAX(hi, j);
+ hi = max(hi, j);
}
}
}
@@ -569,7 +592,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
ath_rc_priv->valid_phy_ratecnt[phy] += 1;
ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
- hi = A_MAX(hi, j);
+ hi = max(hi, j);
}
}
@@ -1080,31 +1103,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
}
-static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
- struct ieee80211_tx_rate *rate)
-{
- int rix = 0, i = 0;
- static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
-
- if (!(rate->flags & IEEE80211_TX_RC_MCS))
- return rate->idx;
-
- while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
- rix++; i++;
- }
-
- rix += rate->idx + rate_table->mcs_start;
-
- if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
- (rate->flags & IEEE80211_TX_RC_SHORT_GI))
- rix = rate_table->info[rix].ht_index;
- else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- rix = rate_table->info[rix].sgi_index;
- else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- rix = rate_table->info[rix].cw40index;
-
- return rix;
-}
static void ath_rc_tx_status(struct ath_softc *sc,
struct ath_rate_priv *ath_rc_priv,
@@ -1228,7 +1226,7 @@ static void ath_rc_init(struct ath_softc *sc,
ht_mcs,
ath_rc_priv->ht_cap);
}
- hi = A_MAX(hi, hthi);
+ hi = max(hi, hthi);
}
ath_rc_priv->rate_table_size = hi + 1;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 07e35e59c9e3..9a4850154fb2 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#include "ar9003_mac.h"
@@ -39,6 +40,7 @@ static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,
result = true;
break;
case 1:
+ case 2:
if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
(curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
(alt_rssi_avg >= (main_rssi_avg - 5))) ||
@@ -813,16 +815,19 @@ static bool ath9k_rx_accept(struct ath_common *common,
struct ath_rx_status *rx_stats,
bool *decrypt_error)
{
-#define is_mc_or_valid_tkip_keyix ((is_mc || \
- (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
- test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
-
+ bool is_mc, is_valid_tkip, strip_mic, mic_error;
struct ath_hw *ah = common->ah;
__le16 fc;
u8 rx_status_len = ah->caps.rx_status_len;
fc = hdr->frame_control;
+ 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));
+
if (!rx_stats->rs_datalen)
return false;
/*
@@ -837,6 +842,11 @@ static bool ath9k_rx_accept(struct ath_common *common,
if (rx_stats->rs_more)
return true;
+ mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
+ !ieee80211_has_morefrags(fc) &&
+ !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+ (rx_stats->rs_status & ATH9K_RXERR_MIC);
+
/*
* The rx_stats->rs_status will not be set until the end of the
* chained descriptors so it can be ignored if rs_more is set. The
@@ -844,30 +854,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
* descriptors.
*/
if (rx_stats->rs_status != 0) {
- if (rx_stats->rs_status & ATH9K_RXERR_CRC)
+ if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+ mic_error = false;
+ }
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
return false;
if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
*decrypt_error = true;
- } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
- bool is_mc;
- /*
- * The MIC error bit is only valid if the frame
- * is not a control frame or fragment, and it was
- * decrypted using a valid TKIP key.
- */
- is_mc = !!is_multicast_ether_addr(hdr->addr1);
-
- if (!ieee80211_is_ctl(fc) &&
- !ieee80211_has_morefrags(fc) &&
- !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
- is_mc_or_valid_tkip_keyix)
- rxs->flag |= RX_FLAG_MMIC_ERROR;
- else
- rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+ mic_error = false;
}
+
/*
* Reject error frames with the exception of
* decryption and MIC failures. For monitor mode,
@@ -885,6 +883,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
}
}
}
+
+ /*
+ * For unicast frames the MIC error bit can have false positives,
+ * so all MIC error reports need to be validated in software.
+ * False negatives are not common, so skip software verification
+ * if the hardware considers the MIC valid.
+ */
+ if (strip_mic)
+ rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+ else if (is_mc && mic_error)
+ rxs->flag |= RX_FLAG_MMIC_ERROR;
+
return true;
}
@@ -1075,39 +1085,39 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
antcomb->rssi_lna1 = main_rssi_avg;
switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
@@ -1324,65 +1334,148 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
/* Adjust the fast_div_bias based on main and alt lna conf */
switch ((ant_conf->main_lna_conf << 4) |
ant_conf->alt_lna_conf) {
- case (0x01): /* A-B LNA2 */
+ case 0x01: /* A-B LNA2 */
ant_conf->fast_div_bias = 0x3b;
break;
- case (0x02): /* A-B LNA1 */
+ case 0x02: /* A-B LNA1 */
ant_conf->fast_div_bias = 0x3d;
break;
- case (0x03): /* A-B A+B */
+ case 0x03: /* A-B A+B */
ant_conf->fast_div_bias = 0x1;
break;
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
ant_conf->fast_div_bias = 0x7;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
ant_conf->fast_div_bias = 0x2;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
ant_conf->fast_div_bias = 0x7;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
ant_conf->fast_div_bias = 0x6;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
ant_conf->fast_div_bias = 0x0;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
ant_conf->fast_div_bias = 0x6;
break;
- case (0x30): /* A+B A-B */
+ case 0x30: /* A+B A-B */
ant_conf->fast_div_bias = 0x1;
break;
- case (0x31): /* A+B LNA2 */
+ case 0x31: /* A+B LNA2 */
ant_conf->fast_div_bias = 0x3b;
break;
- case (0x32): /* A+B LNA1 */
+ case 0x32: /* A+B LNA1 */
ant_conf->fast_div_bias = 0x3d;
break;
default:
break;
}
+ } else if (ant_conf->div_group == 1) {
+ /* Adjust the fast_div_bias based on main and alt_lna_conf */
+ switch ((ant_conf->main_lna_conf << 4) |
+ ant_conf->alt_lna_conf) {
+ case 0x01: /* A-B LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x02: /* A-B LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x03: /* A-B A+B */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x10: /* LNA2 A-B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x12: /* LNA2 LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x13: /* LNA2 A+B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x20: /* LNA1 A-B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x21: /* LNA1 LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x23: /* LNA1 A+B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x30: /* A+B A-B */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x31: /* A+B LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x32: /* A+B LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ default:
+ break;
+ }
} else if (ant_conf->div_group == 2) {
/* Adjust the fast_div_bias based on main and alt_lna_conf */
switch ((ant_conf->main_lna_conf << 4) |
ant_conf->alt_lna_conf) {
- case (0x01): /* A-B LNA2 */
+ case 0x01: /* A-B LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x02): /* A-B LNA1 */
+ case 0x02: /* A-B LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x03): /* A-B A+B */
+ case 0x03: /* A-B A+B */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1391,12 +1484,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1405,7 +1498,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1414,12 +1507,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1428,17 +1521,17 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x30): /* A+B A-B */
+ case 0x30: /* A+B A-B */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x31): /* A+B LNA2 */
+ case 0x31: /* A+B LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x32): /* A+B LNA1 */
+ case 0x32: /* A+B LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
@@ -1446,9 +1539,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
default:
break;
}
-
}
-
}
/* Antenna diversity and combining */
@@ -1856,6 +1947,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.rxotherant = 0;
}
+ if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
+ skb_trim(skb, skb->len - 8);
+
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index c18ee9921fb1..fa4c0bbce6b9 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -600,7 +600,6 @@
#define AR_D_GBL_IFS_SIFS 0x1030
#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF
-#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB
#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF
#define AR_D_TXBLK_BASE 0x1038
@@ -616,12 +615,10 @@
#define AR_D_GBL_IFS_SLOT 0x1070
#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF
#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000
-#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420
#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_DUR 0x0000A5EB
#define AR_D_GBL_IFS_MISC 0x10f0
#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
@@ -788,6 +785,10 @@
#define AR_SREV_REVISION_9271_11 1
#define AR_SREV_VERSION_9300 0x1c0
#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9330 0x200
+#define AR_SREV_REVISION_9330_10 0
+#define AR_SREV_REVISION_9330_11 1
+#define AR_SREV_REVISION_9330_12 2
#define AR_SREV_VERSION_9485 0x240
#define AR_SREV_REVISION_9485_10 0
#define AR_SREV_REVISION_9485_11 1
@@ -862,6 +863,18 @@
#define AR_SREV_9300_20_OR_LATER(_ah) \
((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
+#define AR_SREV_9330(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
+#define AR_SREV_9330_10(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
+#define AR_SREV_9330_11(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
+#define AR_SREV_9330_12(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
+
#define AR_SREV_9485(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
#define AR_SREV_9485_10(_ah) \
@@ -1461,7 +1474,6 @@ enum {
#define AR_TIME_OUT_ACK_S 0
#define AR_TIME_OUT_CTS 0x3FFF0000
#define AR_TIME_OUT_CTS_S 16
-#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56
#define AR_RSSI_THR 0x8018
#define AR_RSSI_THR_MASK 0x000000FF
@@ -1477,7 +1489,6 @@ 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_DUR 0x12e00074
#define AR_RESET_TSF 0x8020
#define AR_RESET_TSF_ONCE 0x01000000
@@ -1862,29 +1873,6 @@ enum {
#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2))
-#define AR_KEYTABLE_0 0x8800
-#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
-#define AR_KEY_CACHE_SIZE 128
-#define AR_RSVD_KEYTABLE_ENTRIES 4
-#define AR_KEY_TYPE 0x00000007
-#define AR_KEYTABLE_TYPE_40 0x00000000
-#define AR_KEYTABLE_TYPE_104 0x00000001
-#define AR_KEYTABLE_TYPE_128 0x00000003
-#define AR_KEYTABLE_TYPE_TKIP 0x00000004
-#define AR_KEYTABLE_TYPE_AES 0x00000005
-#define AR_KEYTABLE_TYPE_CCM 0x00000006
-#define AR_KEYTABLE_TYPE_CLR 0x00000007
-#define AR_KEYTABLE_ANT 0x00000008
-#define AR_KEYTABLE_VALID 0x00008000
-#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
-#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
-#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
-#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
-#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
-#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
-#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
-#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
-
#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */
#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 33443bcaa8d9..cc595712f518 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#include "ar9003_mac.h"
@@ -53,7 +54,7 @@ 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);
+ 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,
@@ -377,8 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf_next = bf->bf_next;
bf->bf_state.bf_type |= BUF_XRETRY;
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
- !bf->bf_stale || bf_next != NULL)
+ 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);
@@ -463,20 +463,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
}
}
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
- bf_next == NULL) {
- /*
- * Make sure the last desc is reclaimed if it
- * not a holding desc.
- */
- if (!bf_last->bf_stale)
- list_move_tail(&bf->list, &bf_head);
- else
- INIT_LIST_HEAD(&bf_head);
- } else {
- BUG_ON(list_empty(bf_q));
+ /*
+ * Make sure the last desc is reclaimed if it
+ * not a holding desc.
+ */
+ if (!bf_last->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
- }
+ else
+ INIT_LIST_HEAD(&bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) {
/*
@@ -572,11 +566,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_unlock();
- if (needreset) {
- spin_unlock_bh(&sc->sc_pcu_lock);
+ if (needreset)
ath_reset(sc, false);
- spin_lock_bh(&sc->sc_pcu_lock);
- }
}
static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -838,7 +829,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
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);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, false);
continue;
}
@@ -850,7 +841,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
/* anchor last desc of aggregate */
ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
- ath_tx_txqaddbuf(sc, txq, &bf_q);
+ 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 &&
@@ -1086,7 +1077,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
txq->txq_headidx = txq->txq_tailidx = 0;
for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
INIT_LIST_HEAD(&txq->txq_fifo[i]);
- INIT_LIST_HEAD(&txq->txq_fifo_pending);
}
return &sc->tx.txq[axq_qnum];
}
@@ -1156,13 +1146,10 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
}
-/*
- * Drain a given TX queue (could be Beacon or Data)
- *
- * This assumes output has been stopped and
- * we do not need to block ath_tx_tasklet.
- */
-void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
+ struct list_head *list, bool retry_tx)
+ __releases(txq->axq_lock)
+ __acquires(txq->axq_lock)
{
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
@@ -1171,93 +1158,63 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head);
- for (;;) {
- spin_lock_bh(&txq->axq_lock);
+ while (!list_empty(list)) {
+ bf = list_first_entry(list, struct ath_buf, list);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
- txq->txq_headidx = txq->txq_tailidx = 0;
- spin_unlock_bh(&txq->axq_lock);
- break;
- } else {
- bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
- struct ath_buf, list);
- }
- } else {
- if (list_empty(&txq->axq_q)) {
- txq->axq_link = NULL;
- spin_unlock_bh(&txq->axq_lock);
- break;
- }
- bf = list_first_entry(&txq->axq_q, struct ath_buf,
- list);
-
- if (bf->bf_stale) {
- list_del(&bf->list);
- spin_unlock_bh(&txq->axq_lock);
+ if (bf->bf_stale) {
+ list_del(&bf->list);
- ath_tx_return_buffer(sc, bf);
- continue;
- }
+ ath_tx_return_buffer(sc, bf);
+ continue;
}
lastbf = bf->bf_lastbf;
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- list_cut_position(&bf_head,
- &txq->txq_fifo[txq->txq_tailidx],
- &lastbf->list);
- INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- } else {
- /* remove ath_buf's of the same mpdu from txq */
- list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
- }
+ list_cut_position(&bf_head, list, &lastbf->list);
txq->axq_depth--;
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
- spin_unlock_bh(&txq->axq_lock);
+ spin_unlock_bh(&txq->axq_lock);
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
retry_tx);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+ spin_lock_bh(&txq->axq_lock);
}
+}
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+{
spin_lock_bh(&txq->axq_lock);
- txq->axq_tx_inprogress = false;
- spin_unlock_bh(&txq->axq_lock);
-
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- spin_lock_bh(&txq->axq_lock);
- while (!list_empty(&txq->txq_fifo_pending)) {
- bf = list_first_entry(&txq->txq_fifo_pending,
- struct ath_buf, list);
- list_cut_position(&bf_head,
- &txq->txq_fifo_pending,
- &bf->bf_lastbf->list);
- spin_unlock_bh(&txq->axq_lock);
+ int idx = txq->txq_tailidx;
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head,
- &ts, 0, retry_tx);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head,
- &ts, 0, 0);
- spin_lock_bh(&txq->axq_lock);
+ while (!list_empty(&txq->txq_fifo[idx])) {
+ ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
+ retry_tx);
+
+ INCR(idx, ATH_TXFIFO_DEPTH);
}
- spin_unlock_bh(&txq->axq_lock);
+ txq->txq_tailidx = idx;
}
+ txq->axq_link = NULL;
+ txq->axq_tx_inprogress = false;
+ ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
+
/* flush any pending frames if aggregation is enabled */
- if (sc->sc_flags & SC_OP_TXAGGR) {
- if (!retry_tx) {
- spin_lock_bh(&txq->axq_lock);
- ath_txq_drain_pending_buffers(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
- }
- }
+ if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
+ ath_txq_drain_pending_buffers(sc, txq);
+
+ spin_unlock_bh(&txq->axq_lock);
}
bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@@ -1371,11 +1328,13 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
* assume the descriptors are already chained together by caller.
*/
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head)
+ struct list_head *head, bool internal)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_buf *bf;
+ struct ath_buf *bf, *bf_last;
+ bool puttxbuf = false;
+ bool edma;
/*
* Insert the frame on the outbound list and
@@ -1385,51 +1344,49 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
if (list_empty(head))
return;
+ edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
bf = list_first_entry(head, struct ath_buf, list);
+ bf_last = list_entry(head->prev, struct ath_buf, list);
ath_dbg(common, ATH_DBG_QUEUE,
"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
- list_splice_tail_init(head, &txq->txq_fifo_pending);
- return;
- }
- if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
- ath_dbg(common, ATH_DBG_XMIT,
- "Initializing tx fifo %d which is non-empty\n",
- txq->txq_headidx);
- INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
- list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
+ if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
+ list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
- TX_STAT_INC(txq->axq_qnum, puttxbuf);
- ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
- ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
- txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+ puttxbuf = true;
} else {
list_splice_tail_init(head, &txq->axq_q);
- if (txq->axq_link == NULL) {
- TX_STAT_INC(txq->axq_qnum, puttxbuf);
- ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
- ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
- txq->axq_qnum, ito64(bf->bf_daddr),
- bf->bf_desc);
- } else {
- *txq->axq_link = bf->bf_daddr;
+ if (txq->axq_link) {
+ ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
ath_dbg(common, ATH_DBG_XMIT,
"link[%u] (%p)=%llx (%p)\n",
txq->axq_qnum, txq->axq_link,
ito64(bf->bf_daddr), bf->bf_desc);
- }
- ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
- &txq->axq_link);
+ } else if (!edma)
+ puttxbuf = true;
+
+ txq->axq_link = bf_last->bf_desc;
+ }
+
+ if (puttxbuf) {
+ TX_STAT_INC(txq->axq_qnum, puttxbuf);
+ ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+ ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+ txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+ }
+
+ if (!edma) {
TX_STAT_INC(txq->axq_qnum, txstart);
ath9k_hw_txstart(ah, txq->axq_qnum);
}
- txq->axq_depth++;
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth++;
+
+ if (!internal) {
+ txq->axq_depth++;
+ if (bf_is_ampdu_not_probing(bf))
+ txq->axq_ampdu_depth++;
+ }
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
@@ -1471,7 +1428,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
+ ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
}
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
@@ -1491,7 +1448,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
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);
+ ath_tx_txqaddbuf(sc, txq, bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued);
}
@@ -2078,6 +2035,40 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
}
+static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_tx_status *ts, struct ath_buf *bf,
+ struct list_head *bf_head)
+ __releases(txq->axq_lock)
+ __acquires(txq->axq_lock)
+{
+ int txok;
+
+ txq->axq_depth--;
+ txok = !(ts->ts_status & ATH9K_TXERR_MASK);
+ txq->axq_tx_inprogress = false;
+ if (bf_is_ampdu_not_probing(bf))
+ txq->axq_ampdu_depth--;
+
+ 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_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
+ } else
+ ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+
+ spin_lock_bh(&txq->axq_lock);
+
+ if (sc->sc_flags & SC_OP_TXAGGR)
+ ath_txq_schedule(sc, txq);
+}
+
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_hw *ah = sc->sc_ah;
@@ -2086,20 +2077,18 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
struct list_head bf_head;
struct ath_desc *ds;
struct ath_tx_status ts;
- int txok;
int status;
ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
txq->axq_link);
+ spin_lock_bh(&txq->axq_lock);
for (;;) {
- spin_lock_bh(&txq->axq_lock);
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
if (sc->sc_flags & SC_OP_TXAGGR)
ath_txq_schedule(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
break;
}
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
@@ -2115,13 +2104,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
bf_held = NULL;
if (bf->bf_stale) {
bf_held = bf;
- if (list_is_last(&bf_held->list, &txq->axq_q)) {
- spin_unlock_bh(&txq->axq_lock);
+ if (list_is_last(&bf_held->list, &txq->axq_q))
break;
- } else {
- bf = list_entry(bf_held->list.next,
- struct ath_buf, list);
- }
+
+ bf = list_entry(bf_held->list.next, struct ath_buf,
+ list);
}
lastbf = bf->bf_lastbf;
@@ -2129,10 +2116,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
memset(&ts, 0, sizeof(ts));
status = ath9k_hw_txprocdesc(ah, ds, &ts);
- if (status == -EINPROGRESS) {
- spin_unlock_bh(&txq->axq_lock);
+ if (status == -EINPROGRESS)
break;
- }
+
TX_STAT_INC(txq->axq_qnum, txprocdesc);
/*
@@ -2146,42 +2132,14 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
list_cut_position(&bf_head,
&txq->axq_q, lastbf->list.prev);
- txq->axq_depth--;
- txok = !(ts.ts_status & ATH9K_TXERR_MASK);
- txq->axq_tx_inprogress = false;
- if (bf_held)
+ if (bf_held) {
list_del(&bf_held->list);
-
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth--;
-
- spin_unlock_bh(&txq->axq_lock);
-
- if (bf_held)
ath_tx_return_buffer(sc, bf_held);
-
- 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);
}
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
- true);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
-
- spin_lock_bh(&txq->axq_lock);
-
- if (sc->sc_flags & SC_OP_TXAGGR)
- ath_txq_schedule(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
+ ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
}
+ spin_unlock_bh(&txq->axq_lock);
}
static void ath_tx_complete_poll_work(struct work_struct *work)
@@ -2214,7 +2172,9 @@ 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);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2238,17 +2198,16 @@ void ath_tx_tasklet(struct ath_softc *sc)
void ath_tx_edma_tasklet(struct ath_softc *sc)
{
- struct ath_tx_status txs;
+ struct ath_tx_status ts;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_txq *txq;
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
int status;
- int txok;
for (;;) {
- status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
+ status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
if (status == -EINPROGRESS)
break;
if (status == -EIO) {
@@ -2258,12 +2217,13 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
}
/* Skip beacon completions */
- if (txs.qid == sc->beacon.beaconq)
+ if (ts.qid == sc->beacon.beaconq)
continue;
- txq = &sc->tx.txq[txs.qid];
+ txq = &sc->tx.txq[ts.qid];
spin_lock_bh(&txq->axq_lock);
+
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
spin_unlock_bh(&txq->axq_lock);
return;
@@ -2276,41 +2236,21 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
INIT_LIST_HEAD(&bf_head);
list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
&lastbf->list);
- INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- txq->axq_depth--;
- txq->axq_tx_inprogress = false;
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth--;
- spin_unlock_bh(&txq->axq_lock);
- txok = !(txs.ts_status & ATH9K_TXERR_MASK);
-
- if (!bf_isampdu(bf)) {
- if (txs.ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
- }
-
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
- txok, true);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head,
- &txs, txok, 0);
+ if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- spin_lock_bh(&txq->axq_lock);
+ if (!list_empty(&txq->axq_q)) {
+ struct list_head bf_q;
- if (!list_empty(&txq->txq_fifo_pending)) {
- INIT_LIST_HEAD(&bf_head);
- bf = list_first_entry(&txq->txq_fifo_pending,
- struct ath_buf, list);
- list_cut_position(&bf_head,
- &txq->txq_fifo_pending,
- &bf->bf_lastbf->list);
- ath_tx_txqaddbuf(sc, txq, &bf_head);
- } else if (sc->sc_flags & SC_OP_TXAGGR)
- ath_txq_schedule(sc, txq);
+ INIT_LIST_HEAD(&bf_q);
+ txq->axq_link = NULL;
+ list_splice_tail_init(&txq->axq_q, &bf_q);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, true);
+ }
+ }
+ ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
spin_unlock_bh(&txq->axq_lock);
}
}
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 4da01a9f5680..c5427a72a1e2 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -67,6 +67,8 @@
#define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1)
+static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
+
enum carl9170_rf_init_mode {
CARL9170_RFI_NONE,
CARL9170_RFI_WARM,
@@ -175,7 +177,7 @@ struct carl9170_tx_queue_stats {
struct carl9170_vif {
unsigned int id;
- struct ieee80211_vif *vif;
+ struct ieee80211_vif __rcu *vif;
};
struct carl9170_vif_info {
@@ -309,7 +311,7 @@ struct ar9170 {
spinlock_t beacon_lock;
unsigned int global_pretbtt;
unsigned int global_beacon_int;
- struct carl9170_vif_info *beacon_iter;
+ struct carl9170_vif_info __rcu *beacon_iter;
unsigned int beacon_enabled;
/* cryptographic engine */
@@ -387,7 +389,7 @@ struct ar9170 {
/* tx ampdu */
struct work_struct ampdu_work;
spinlock_t tx_ampdu_list_lock;
- struct carl9170_sta_tid *tx_ampdu_iter;
+ struct carl9170_sta_tid __rcu *tx_ampdu_iter;
struct list_head tx_ampdu_list;
atomic_t tx_ampdu_upload;
atomic_t tx_ampdu_scheduler;
@@ -440,7 +442,6 @@ struct ar9170 {
enum carl9170_ps_off_override_reasons {
PS_OFF_VIF = BIT(0),
PS_OFF_BCN = BIT(1),
- PS_OFF_5GHZ = BIT(2),
};
struct carl9170_ba_stats {
@@ -455,7 +456,7 @@ struct carl9170_sta_info {
bool sleeping;
atomic_t pending_frames;
unsigned int ampdu_max_len;
- struct carl9170_sta_tid *agg[CARL9170_NUM_TID];
+ struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID];
struct carl9170_ba_stats stats[CARL9170_NUM_TID];
};
@@ -531,7 +532,6 @@ int carl9170_set_ampdu_settings(struct ar9170 *ar);
int carl9170_set_slot_time(struct ar9170 *ar);
int carl9170_set_mac_rates(struct ar9170 *ar);
int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry);
-int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen);
int carl9170_disable_key(struct ar9170 *ar, const u8 id);
@@ -552,6 +552,7 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb);
void carl9170_tx_scheduler(struct ar9170 *ar);
void carl9170_tx_get_skb(struct sk_buff *skb);
int carl9170_tx_put_skb(struct sk_buff *skb);
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
/* LEDs */
#ifdef CONFIG_CARL9170_LEDS
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
index 568174c71b94..d5f95bdc75c1 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.h
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -87,7 +87,7 @@ do { \
__ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \
__ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \
__nreg++; \
- if ((__nreg >= PAYLOAD_MAX/2)) { \
+ if ((__nreg >= PAYLOAD_MAX / 2)) { \
if (IS_ACCEPTING_CMD(__ar)) \
__err = carl9170_exec_cmd(__ar, \
CARL9170_CMD_WREG, 8 * __nreg, \
@@ -160,7 +160,7 @@ do { \
} while (0)
#define carl9170_async_regwrite_finish() do { \
-__async_regwrite_out : \
+__async_regwrite_out: \
if (__cmd != NULL && __err == 0) \
carl9170_async_regwrite_flush(); \
kfree(__cmd); \
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 0ac1124c2a0b..de57f90e1d5f 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -695,7 +695,7 @@ static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
}
__DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);
-static const char *erp_modes[] = {
+static const char *const erp_modes[] = {
[CARL9170_ERP_INVALID] = "INVALID",
[CARL9170_ERP_AUTO] = "Automatic",
[CARL9170_ERP_MAC80211] = "Set by MAC80211",
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 221957c5d373..39ddea5794f7 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -237,7 +237,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
ar->disable_offload = true;
}
- if (SUPP(CARL9170FW_PSM))
+ if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))
ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS;
if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) {
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index 30449d21b762..0a6dec529b59 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -4,7 +4,7 @@
* Firmware command interface definitions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@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
@@ -54,6 +54,7 @@ enum carl9170_cmd_oids {
CARL9170_CMD_BCN_CTRL = 0x05,
CARL9170_CMD_READ_TSF = 0x06,
CARL9170_CMD_RX_FILTER = 0x07,
+ CARL9170_CMD_WOL = 0x08,
/* CAM */
CARL9170_CMD_EKEY = 0x10,
@@ -180,6 +181,21 @@ struct carl9170_bcn_ctrl_cmd {
#define CARL9170_BCN_CTRL_DRAIN 0
#define CARL9170_BCN_CTRL_CAB_TRIGGER 1
+struct carl9170_wol_cmd {
+ __le32 flags;
+ u8 mac[6];
+ u8 bssid[6];
+ __le32 null_interval;
+ __le32 free_for_use2;
+ __le32 mask;
+ u8 pattern[32];
+} __packed;
+
+#define CARL9170_WOL_CMD_SIZE 60
+
+#define CARL9170_WOL_DISCONNECT 1
+#define CARL9170_WOL_MAGIC_PKT 2
+
struct carl9170_cmd_head {
union {
struct {
@@ -203,6 +219,7 @@ struct carl9170_cmd {
struct carl9170_write_reg wreg;
struct carl9170_rf_init rf_init;
struct carl9170_psm psm;
+ struct carl9170_wol_cmd wol;
struct carl9170_bcn_ctrl_cmd bcn_ctrl;
struct carl9170_rx_filter_cmd rx_filter;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 921066822dd5..6d9c0891ce7f 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -3,7 +3,7 @@
*
* Firmware descriptor format
*
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@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
@@ -72,6 +72,12 @@ enum carl9170fw_feature_list {
/* Wake up on WLAN */
CARL9170FW_WOL,
+ /* Firmware supports PSM in the 5GHZ Band */
+ CARL9170FW_FIXED_5GHZ_PSM,
+
+ /* HW (ANI, CCA, MIB) tally counters */
+ CARL9170FW_HW_COUNTERS,
+
/* KEEP LAST */
__CARL9170FW_FEATURE_NUM
};
@@ -82,6 +88,7 @@ enum carl9170fw_feature_list {
#define DBG_MAGIC "DBG\0"
#define CHK_MAGIC "CHK\0"
#define TXSQ_MAGIC "TXSQ"
+#define WOL_MAGIC "WOL\0"
#define LAST_MAGIC "LAST"
#define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
@@ -104,7 +111,7 @@ struct carl9170fw_desc_head {
(sizeof(struct carl9170fw_desc_head))
#define CARL9170FW_OTUS_DESC_MIN_VER 6
-#define CARL9170FW_OTUS_DESC_CUR_VER 6
+#define CARL9170FW_OTUS_DESC_CUR_VER 7
struct carl9170fw_otus_desc {
struct carl9170fw_desc_head head;
__le32 feature_set;
@@ -186,6 +193,16 @@ struct carl9170fw_txsq_desc {
#define CARL9170FW_TXSQ_DESC_SIZE \
(sizeof(struct carl9170fw_txsq_desc))
+#define CARL9170FW_WOL_DESC_MIN_VER 1
+#define CARL9170FW_WOL_DESC_CUR_VER 1
+struct carl9170fw_wol_desc {
+ struct carl9170fw_desc_head head;
+
+ __le32 supported_triggers; /* CARL9170_WOL_ */
+} __packed;
+#define CARL9170FW_WOL_DESC_SIZE \
+ (sizeof(struct carl9170fw_wol_desc))
+
#define CARL9170FW_LAST_DESC_MIN_VER 1
#define CARL9170FW_LAST_DESC_CUR_VER 2
struct carl9170fw_last_desc {
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index 4e30762dd903..fa834c1460f0 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -4,7 +4,7 @@
* Register map, hardware-specific definitions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@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
@@ -174,6 +174,7 @@
#define AR9170_MAC_SNIFFER_ENABLE_PROMISC BIT(0)
#define AR9170_MAC_SNIFFER_DEFAULTS 0x02000000
#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678)
+#define AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE BIT(2)
#define AR9170_MAC_ENCRYPTION_RX_SOFTWARE BIT(3)
#define AR9170_MAC_ENCRYPTION_DEFAULTS 0x70
@@ -222,6 +223,12 @@
#define AR9170_MAC_REG_TX_BLOCKACKS (AR9170_MAC_REG_BASE + 0x6c0)
#define AR9170_MAC_REG_NAV_COUNT (AR9170_MAC_REG_BASE + 0x6c4)
#define AR9170_MAC_REG_BACKOFF_STATUS (AR9170_MAC_REG_BASE + 0x6c8)
+#define AR9170_MAC_BACKOFF_CCA BIT(24)
+#define AR9170_MAC_BACKOFF_TX_PEX BIT(25)
+#define AR9170_MAC_BACKOFF_RX_PE BIT(26)
+#define AR9170_MAC_BACKOFF_MD_READY BIT(27)
+#define AR9170_MAC_BACKOFF_TX_PE BIT(28)
+
#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6cc)
#define AR9170_MAC_REG_TX_COMPLETE (AR9170_MAC_REG_BASE + 0x6d4)
@@ -357,7 +364,18 @@
#define AR9170_MAC_REG_DMA_WLAN_STATUS (AR9170_MAC_REG_BASE + 0xd38)
#define AR9170_MAC_REG_DMA_STATUS (AR9170_MAC_REG_BASE + 0xd3c)
-
+#define AR9170_MAC_REG_DMA_TXQ_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd40)
+#define AR9170_MAC_REG_DMA_TXQ0_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd40)
+#define AR9170_MAC_REG_DMA_TXQ1_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd44)
+#define AR9170_MAC_REG_DMA_TXQ2_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd48)
+#define AR9170_MAC_REG_DMA_TXQ3_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd4c)
+#define AR9170_MAC_REG_DMA_TXQ4_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd50)
+#define AR9170_MAC_REG_DMA_TXQ0Q1_LEN (AR9170_MAC_REG_BASE + 0xd54)
+#define AR9170_MAC_REG_DMA_TXQ2Q3_LEN (AR9170_MAC_REG_BASE + 0xd58)
+#define AR9170_MAC_REG_DMA_TXQ4_LEN (AR9170_MAC_REG_BASE + 0xd5c)
+
+#define AR9170_MAC_REG_DMA_TXQX_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd74)
+#define AR9170_MAC_REG_DMA_TXQX_FAIL_ADDR (AR9170_MAC_REG_BASE + 0xd78)
#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xd7c)
#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f
#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0
@@ -377,10 +395,40 @@
#define AR9170_MAC_REG_BCN_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd98)
#define AR9170_MAC_REG_BCN_COUNT (AR9170_MAC_REG_BASE + 0xd9c)
-
-
#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xda0)
+#define AR9170_MAC_BCN_HT1_HT_EN BIT(0)
+#define AR9170_MAC_BCN_HT1_GF_PMB BIT(1)
+#define AR9170_MAC_BCN_HT1_SP_EXP BIT(2)
+#define AR9170_MAC_BCN_HT1_TX_BF BIT(3)
+#define AR9170_MAC_BCN_HT1_PWR_CTRL_S 4
+#define AR9170_MAC_BCN_HT1_PWR_CTRL 0x70
+#define AR9170_MAC_BCN_HT1_TX_ANT1 BIT(7)
+#define AR9170_MAC_BCN_HT1_TX_ANT0 BIT(8)
+#define AR9170_MAC_BCN_HT1_NUM_LFT_S 9
+#define AR9170_MAC_BCN_HT1_NUM_LFT 0x600
+#define AR9170_MAC_BCN_HT1_BWC_20M_EXT BIT(16)
+#define AR9170_MAC_BCN_HT1_BWC_40M_SHARED BIT(17)
+#define AR9170_MAC_BCN_HT1_BWC_40M_DUP (BIT(16) | BIT(17))
+#define AR9170_MAC_BCN_HT1_BF_MCS_S 18
+#define AR9170_MAC_BCN_HT1_BF_MCS 0x1c0000
+#define AR9170_MAC_BCN_HT1_TPC_S 21
+#define AR9170_MAC_BCN_HT1_TPC 0x7e00000
+#define AR9170_MAC_BCN_HT1_CHAIN_MASK_S 27
+#define AR9170_MAC_BCN_HT1_CHAIN_MASK 0x38000000
+
#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xda4)
+#define AR9170_MAC_BCN_HT2_MCS_S 0
+#define AR9170_MAC_BCN_HT2_MCS 0x7f
+#define AR9170_MAC_BCN_HT2_BW40 BIT(8)
+#define AR9170_MAC_BCN_HT2_SMOOTHING BIT(9)
+#define AR9170_MAC_BCN_HT2_SS BIT(10)
+#define AR9170_MAC_BCN_HT2_NSS BIT(11)
+#define AR9170_MAC_BCN_HT2_STBC_S 12
+#define AR9170_MAC_BCN_HT2_STBC 0x3000
+#define AR9170_MAC_BCN_HT2_ADV_COD BIT(14)
+#define AR9170_MAC_BCN_HT2_SGI BIT(15)
+#define AR9170_MAC_BCN_HT2_LEN_S 16
+#define AR9170_MAC_BCN_HT2_LEN 0xffff0000
#define AR9170_MAC_REG_DMA_TXQX_ADDR_CURR (AR9170_MAC_REG_BASE + 0xdc0)
diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c
index 4bb2cbd8bd9b..78dadc797558 100644
--- a/drivers/net/wireless/ath/carl9170/led.c
+++ b/drivers/net/wireless/ath/carl9170/led.c
@@ -118,7 +118,7 @@ static void carl9170_led_set_brightness(struct led_classdev *led,
}
if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
- ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
+ ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ / 10);
}
static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index 385cf508479b..dfda91970995 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -455,135 +455,6 @@ int carl9170_set_beacon_timers(struct ar9170 *ar)
return carl9170_regwrite_result();
}
-int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
-{
- struct sk_buff *skb = NULL;
- struct carl9170_vif_info *cvif;
- struct ieee80211_tx_info *txinfo;
- __le32 *data, *old = NULL;
- u32 word, off, addr, len;
- int i = 0, err = 0;
-
- rcu_read_lock();
- cvif = rcu_dereference(ar->beacon_iter);
-retry:
- if (ar->vifs == 0 || !cvif)
- goto out_unlock;
-
- list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
- if (cvif->active && cvif->enable_beacon)
- goto found;
- }
-
- if (!ar->beacon_enabled || i++)
- goto out_unlock;
-
- goto retry;
-
-found:
- rcu_assign_pointer(ar->beacon_iter, cvif);
-
- skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
- NULL, NULL);
-
- if (!skb) {
- err = -ENOMEM;
- goto err_free;
- }
-
- txinfo = IEEE80211_SKB_CB(skb);
- if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
- err = -EINVAL;
- goto err_free;
- }
-
- spin_lock_bh(&ar->beacon_lock);
- data = (__le32 *)skb->data;
- if (cvif->beacon)
- old = (__le32 *)cvif->beacon->data;
-
- off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
- addr = ar->fw.beacon_addr + off;
- len = roundup(skb->len + FCS_LEN, 4);
-
- if ((off + len) > ar->fw.beacon_max_len) {
- if (net_ratelimit()) {
- wiphy_err(ar->hw->wiphy, "beacon does not "
- "fit into device memory!\n");
- }
- err = -EINVAL;
- goto err_unlock;
- }
-
- if (len > AR9170_MAC_BCN_LENGTH_MAX) {
- if (net_ratelimit()) {
- wiphy_err(ar->hw->wiphy, "no support for beacons "
- "bigger than %d (yours:%d).\n",
- AR9170_MAC_BCN_LENGTH_MAX, len);
- }
-
- err = -EMSGSIZE;
- goto err_unlock;
- }
-
- i = txinfo->control.rates[0].idx;
- if (txinfo->band != IEEE80211_BAND_2GHZ)
- i += 4;
-
- word = __carl9170_ratetable[i].hw_value & 0xf;
- if (i < 4)
- word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
- else
- word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
-
- carl9170_async_regwrite_begin(ar);
- carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
-
- for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
- /*
- * XXX: This accesses beyond skb data for up
- * to the last 3 bytes!!
- */
-
- if (old && (data[i] == old[i]))
- continue;
-
- word = le32_to_cpu(data[i]);
- carl9170_async_regwrite(addr + 4 * i, word);
- }
- carl9170_async_regwrite_finish();
-
- dev_kfree_skb_any(cvif->beacon);
- cvif->beacon = NULL;
-
- err = carl9170_async_regwrite_result();
- if (!err)
- cvif->beacon = skb;
- spin_unlock_bh(&ar->beacon_lock);
- if (err)
- goto err_free;
-
- if (submit) {
- err = carl9170_bcn_ctrl(ar, cvif->id,
- CARL9170_BCN_CTRL_CAB_TRIGGER,
- addr, skb->len + FCS_LEN);
-
- if (err)
- goto err_free;
- }
-out_unlock:
- rcu_read_unlock();
- return 0;
-
-err_unlock:
- spin_unlock_bh(&ar->beacon_lock);
-
-err_free:
- rcu_read_unlock();
- dev_kfree_skb_any(skb);
- return err;
-}
-
int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
const u8 ktype, const u8 keyidx, const u8 *keydata,
const int keylen)
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 54d093c2ab44..0122930b14c7 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -345,11 +345,11 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
carl9170_zap_queues(ar);
/* reset QoS defaults */
- CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT */
- CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7, 15, 94); /* VIDEO */
- CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3, 7, 47); /* VOICE */
- CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023, 0); /* BACKGROUND */
- CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VO], 2, 3, 7, 47);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VI], 2, 7, 15, 94);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BE], 3, 15, 1023, 0);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BK], 7, 15, 1023, 0);
+ CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_SPECIAL], 2, 3, 7, 0);
ar->current_factor = ar->current_density = -1;
/* "The first key is unique." */
@@ -1484,6 +1484,13 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
}
}
+static bool carl9170_tx_frames_pending(struct ieee80211_hw *hw)
+{
+ struct ar9170 *ar = hw->priv;
+
+ return !!atomic_read(&ar->tx_total_queued);
+}
+
static const struct ieee80211_ops carl9170_ops = {
.start = carl9170_op_start,
.stop = carl9170_op_stop,
@@ -1504,6 +1511,7 @@ static const struct ieee80211_ops carl9170_ops = {
.get_survey = carl9170_op_get_survey,
.get_stats = carl9170_op_get_stats,
.ampdu_action = carl9170_op_ampdu_action,
+ .tx_frames_pending = carl9170_tx_frames_pending,
};
void *carl9170_alloc(size_t priv_size)
@@ -1577,6 +1585,7 @@ void *carl9170_alloc(size_t priv_size)
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
+ IEEE80211_HW_NEED_DTIM_PERIOD |
IEEE80211_HW_SIGNAL_DBM;
if (!modparam_noht) {
@@ -1621,7 +1630,7 @@ static int carl9170_read_eeprom(struct ar9170 *ar)
BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
#endif
- for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
+ for (i = 0; i < sizeof(ar->eeprom) / RB; i++) {
for (j = 0; j < RW; j++)
offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
RB * i + 4 * j);
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index b6ae0e179c8d..aa147a9120b6 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1098,7 +1098,7 @@ static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
* Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
* Can we rely on the compiler to optimise away the div?
*/
- return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
+ return (y >> SHIFT) + ((y & (1 << (SHIFT - 1))) >> (SHIFT - 1));
#undef SHIFT
}
@@ -1379,7 +1379,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
modes[i].max_power =
carl9170_get_max_edge_power(ar,
- freq+f_off, EDGES(ctl_idx, 1));
+ freq + f_off, EDGES(ctl_idx, 1));
/*
* TODO: check if the regulatory max. power is
@@ -1441,7 +1441,7 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
if (freq < 3000)
f = freq - 2300;
else
- f = (freq - 4800)/5;
+ f = (freq - 4800) / 5;
/*
* cycle through the various modes
@@ -1783,12 +1783,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
}
}
- /* FIXME: PSM does not work in 5GHz Band */
- if (channel->band == IEEE80211_BAND_5GHZ)
- ar->ps.off_override |= PS_OFF_5GHZ;
- else
- ar->ps.off_override &= ~PS_OFF_5GHZ;
-
ar->channel = channel;
ar->ht_settings = new_ht;
return 0;
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index ec21ea9fd8d5..dc99030ea8b6 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -472,7 +472,7 @@ static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len)
u8 *qc = ieee80211_get_qos_ctl(hdr);
reserved += NET_IP_ALIGN;
- if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
reserved += NET_IP_ALIGN;
}
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index e94084fcf6f5..d20946939cd8 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -661,11 +661,67 @@ void carl9170_tx_process_status(struct ar9170 *ar,
}
}
+static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar,
+ struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate,
+ unsigned int *phyrate, unsigned int *tpc, unsigned int *chains)
+{
+ struct ieee80211_rate *rate = NULL;
+ u8 *txpower;
+ unsigned int idx;
+
+ idx = txrate->idx;
+ *tpc = 0;
+ *phyrate = 0;
+
+ if (txrate->flags & IEEE80211_TX_RC_MCS) {
+ if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+ /* +1 dBm for HT40 */
+ *tpc += 2;
+
+ if (info->band == IEEE80211_BAND_2GHZ)
+ txpower = ar->power_2G_ht40;
+ else
+ txpower = ar->power_5G_ht40;
+ } else {
+ if (info->band == IEEE80211_BAND_2GHZ)
+ txpower = ar->power_2G_ht20;
+ else
+ txpower = ar->power_5G_ht20;
+ }
+
+ *phyrate = txrate->idx;
+ *tpc += txpower[idx & 7];
+ } else {
+ if (info->band == IEEE80211_BAND_2GHZ) {
+ if (idx < 4)
+ txpower = ar->power_2G_cck;
+ else
+ txpower = ar->power_2G_ofdm;
+ } else {
+ txpower = ar->power_5G_leg;
+ idx += 4;
+ }
+
+ rate = &__carl9170_ratetable[idx];
+ *tpc += txpower[(rate->hw_value & 0x30) >> 4];
+ *phyrate = rate->hw_value & 0xf;
+ }
+
+ if (ar->eeprom.tx_mask == 1) {
+ *chains = AR9170_TX_PHY_TXCHAIN_1;
+ } else {
+ if (!(txrate->flags & IEEE80211_TX_RC_MCS) &&
+ rate && rate->bitrate >= 360)
+ *chains = AR9170_TX_PHY_TXCHAIN_1;
+ else
+ *chains = AR9170_TX_PHY_TXCHAIN_2;
+ }
+}
+
static __le32 carl9170_tx_physet(struct ar9170 *ar,
struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate)
{
- struct ieee80211_rate *rate = NULL;
- u32 power, chains;
+ unsigned int power = 0, chains = 0, phyrate = 0;
__le32 tmp;
tmp = cpu_to_le32(0);
@@ -682,35 +738,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
if (txrate->flags & IEEE80211_TX_RC_MCS) {
- u32 r = txrate->idx;
- u8 *txpower;
+ SET_VAL(AR9170_TX_PHY_MCS, phyrate, txrate->idx);
/* heavy clip control */
- tmp |= cpu_to_le32((r & 0x7) <<
+ tmp |= cpu_to_le32((txrate->idx & 0x7) <<
AR9170_TX_PHY_TX_HEAVY_CLIP_S);
- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
- if (info->band == IEEE80211_BAND_5GHZ)
- txpower = ar->power_5G_ht40;
- else
- txpower = ar->power_2G_ht40;
- } else {
- if (info->band == IEEE80211_BAND_5GHZ)
- txpower = ar->power_5G_ht20;
- else
- txpower = ar->power_2G_ht20;
- }
-
- power = txpower[r & 7];
-
- /* +1 dBm for HT40 */
- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- power += 2;
-
- r <<= AR9170_TX_PHY_MCS_S;
- BUG_ON(r & ~AR9170_TX_PHY_MCS);
-
- tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS);
tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
/*
@@ -720,34 +753,15 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
* tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
*/
} else {
- u8 *txpower;
- u32 mod;
- u32 phyrate;
- u8 idx = txrate->idx;
-
- if (info->band != IEEE80211_BAND_2GHZ) {
- idx += 4;
- txpower = ar->power_5G_leg;
- mod = AR9170_TX_PHY_MOD_OFDM;
+ if (info->band == IEEE80211_BAND_2GHZ) {
+ if (txrate->idx <= AR9170_TX_PHY_RATE_CCK_11M)
+ tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_CCK);
+ else
+ tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
} else {
- if (idx < 4) {
- txpower = ar->power_2G_cck;
- mod = AR9170_TX_PHY_MOD_CCK;
- } else {
- mod = AR9170_TX_PHY_MOD_OFDM;
- txpower = ar->power_2G_ofdm;
- }
+ tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
}
- rate = &__carl9170_ratetable[idx];
-
- phyrate = rate->hw_value & 0xF;
- power = txpower[(rate->hw_value & 0x30) >> 4];
- phyrate <<= AR9170_TX_PHY_MCS_S;
-
- tmp |= cpu_to_le32(mod);
- tmp |= cpu_to_le32(phyrate);
-
/*
* short preamble seems to be broken too.
*
@@ -755,23 +769,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
* tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
*/
}
- power <<= AR9170_TX_PHY_TX_PWR_S;
- power &= AR9170_TX_PHY_TX_PWR;
- tmp |= cpu_to_le32(power);
-
- /* set TX chains */
- if (ar->eeprom.tx_mask == 1) {
- chains = AR9170_TX_PHY_TXCHAIN_1;
- } else {
- chains = AR9170_TX_PHY_TXCHAIN_2;
-
- /* >= 36M legacy OFDM - use only one chain */
- if (rate && rate->bitrate >= 360 &&
- !(txrate->flags & IEEE80211_TX_RC_MCS))
- chains = AR9170_TX_PHY_TXCHAIN_1;
- }
- tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S);
+ carl9170_tx_rate_tpc_chains(ar, info, txrate,
+ &phyrate, &power, &chains);
+ tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_MCS, phyrate));
+ tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TX_PWR, power));
+ tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TXCHAIN, chains));
return tmp;
}
@@ -1438,3 +1441,154 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
if (ar->tx_schedule)
carl9170_tx(ar);
}
+
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
+{
+ struct sk_buff *skb = NULL;
+ struct carl9170_vif_info *cvif;
+ struct ieee80211_tx_info *txinfo;
+ struct ieee80211_tx_rate *rate;
+ __le32 *data, *old = NULL;
+ unsigned int plcp, power, chains;
+ u32 word, ht1, off, addr, len;
+ int i = 0, err = 0;
+
+ rcu_read_lock();
+ cvif = rcu_dereference(ar->beacon_iter);
+retry:
+ if (ar->vifs == 0 || !cvif)
+ goto out_unlock;
+
+ list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
+ if (cvif->active && cvif->enable_beacon)
+ goto found;
+ }
+
+ if (!ar->beacon_enabled || i++)
+ goto out_unlock;
+
+ goto retry;
+
+found:
+ rcu_assign_pointer(ar->beacon_iter, cvif);
+
+ skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
+ NULL, NULL);
+
+ if (!skb) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ spin_lock_bh(&ar->beacon_lock);
+ data = (__le32 *)skb->data;
+ if (cvif->beacon)
+ old = (__le32 *)cvif->beacon->data;
+
+ off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
+ addr = ar->fw.beacon_addr + off;
+ len = roundup(skb->len + FCS_LEN, 4);
+
+ if ((off + len) > ar->fw.beacon_max_len) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "beacon does not "
+ "fit into device memory!\n");
+ }
+ err = -EINVAL;
+ goto err_unlock;
+ }
+
+ if (len > AR9170_MAC_BCN_LENGTH_MAX) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "no support for beacons "
+ "bigger than %d (yours:%d).\n",
+ AR9170_MAC_BCN_LENGTH_MAX, len);
+ }
+
+ err = -EMSGSIZE;
+ goto err_unlock;
+ }
+
+ ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
+ rate = &txinfo->control.rates[0];
+ carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains);
+ if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
+ if (plcp <= AR9170_TX_PHY_RATE_CCK_11M)
+ plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+ else
+ plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
+ } else {
+ ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ plcp |= AR9170_MAC_BCN_HT2_SGI;
+
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+ ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
+ plcp |= AR9170_MAC_BCN_HT2_BW40;
+ }
+ if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
+ ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
+ plcp |= AR9170_MAC_BCN_HT2_BW40;
+ }
+
+ SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN);
+ }
+
+ SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7);
+ SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power);
+ SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains);
+ if (chains == AR9170_TX_PHY_TXCHAIN_2)
+ ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
+
+ carl9170_async_regwrite_begin(ar);
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1);
+ if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS))
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
+ else
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp);
+
+ for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
+ /*
+ * XXX: This accesses beyond skb data for up
+ * to the last 3 bytes!!
+ */
+
+ if (old && (data[i] == old[i]))
+ continue;
+
+ word = le32_to_cpu(data[i]);
+ carl9170_async_regwrite(addr + 4 * i, word);
+ }
+ carl9170_async_regwrite_finish();
+
+ dev_kfree_skb_any(cvif->beacon);
+ cvif->beacon = NULL;
+
+ err = carl9170_async_regwrite_result();
+ if (!err)
+ cvif->beacon = skb;
+ spin_unlock_bh(&ar->beacon_lock);
+ if (err)
+ goto err_free;
+
+ if (submit) {
+ err = carl9170_bcn_ctrl(ar, cvif->id,
+ CARL9170_BCN_CTRL_CAB_TRIGGER,
+ addr, skb->len + FCS_LEN);
+
+ if (err)
+ goto err_free;
+ }
+out_unlock:
+ rcu_read_unlock();
+ return 0;
+
+err_unlock:
+ spin_unlock_bh(&ar->beacon_lock);
+
+err_free:
+ rcu_read_unlock();
+ dev_kfree_skb_any(skb);
+ return err;
+}
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index 15095c035169..64703778cfea 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 1
-#define CARL9170FW_VERSION_DAY 22
-#define CARL9170FW_VERSION_GIT "1.9.2"
+#define CARL9170FW_VERSION_MONTH 6
+#define CARL9170FW_VERSION_DAY 30
+#define CARL9170FW_VERSION_GIT "1.9.4"
#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h
index 9e1324b67e08..ea17995b32f4 100644
--- a/drivers/net/wireless/ath/carl9170/wlan.h
+++ b/drivers/net/wireless/ath/carl9170/wlan.h
@@ -4,7 +4,7 @@
* RX/TX meta descriptor format
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@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
@@ -278,7 +278,7 @@ struct ar9170_tx_frame {
struct carl9170_tx_superframe {
struct carl9170_tx_superdesc s;
struct ar9170_tx_frame f;
-} __packed;
+} __packed __aligned(4);
#endif /* __CARL9170FW__ */
@@ -328,7 +328,7 @@ struct _carl9170_tx_superframe {
struct _carl9170_tx_superdesc s;
struct _ar9170_tx_hwdesc f;
u8 frame_data[0];
-} __packed;
+} __packed __aligned(4);
#define CARL9170_TX_SUPERDESC_LEN 24
#define AR9170_TX_HWDESC_LEN 8
@@ -404,16 +404,6 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
(t->DAidx & 0xc0) >> 6;
}
-enum ar9170_txq {
- AR9170_TXQ_BE,
-
- AR9170_TXQ_VI,
- AR9170_TXQ_VO,
- AR9170_TXQ_BK,
-
- __AR9170_NUM_TXQ,
-};
-
/*
* This is an workaround for several undocumented bugs.
* Don't mess with the QoS/AC <-> HW Queue map, if you don't
@@ -431,7 +421,14 @@ enum ar9170_txq {
* result, this makes the device pretty much useless
* for any serious 802.11n setup.
*/
-static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };
+enum ar9170_txq {
+ AR9170_TXQ_BK = 0, /* TXQ0 */
+ AR9170_TXQ_BE, /* TXQ1 */
+ AR9170_TXQ_VI, /* TXQ2 */
+ AR9170_TXQ_VO, /* TXQ3 */
+
+ __AR9170_NUM_TXQ,
+};
#define AR9170_TXQ_DEPTH 32
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
index a61ef3d6d89c..17b0efd86f9a 100644
--- a/drivers/net/wireless/ath/key.c
+++ b/drivers/net/wireless/ath/key.c
@@ -105,11 +105,8 @@ static bool ath_hw_keysetmac(struct ath_common *common,
if (mac[0] & 0x01)
unicast_flag = 0;
- macHi = (mac[5] << 8) | mac[4];
- macLo = (mac[3] << 24) |
- (mac[2] << 16) |
- (mac[1] << 8) |
- mac[0];
+ macLo = get_unaligned_le32(mac);
+ macHi = get_unaligned_le16(mac + 4);
macLo >>= 1;
macLo |= (macHi & 1) << 31;
macHi >>= 1;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 39a11e8af4fa..7e45ca2e78ef 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -40,6 +40,7 @@
******************************************************************************/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 480595f04411..d2293dcc117f 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -26,6 +26,16 @@ config B43
This driver can be built as a module (recommended) that will be called "b43".
If unsure, say M.
+config B43_BCMA
+ bool "Support for BCMA bus"
+ depends on B43 && BCMA && BROKEN
+ default y
+
+config B43_SSB
+ bool
+ depends on B43 && SSB
+ default y
+
# Auto-select SSB PCI-HOST support, if possible
config B43_PCI_AUTOSELECT
bool
@@ -80,6 +90,12 @@ config B43_SDIO
#Data transfers to the device via PIO. We want it as a fallback even
# if we can do DMA.
+config B43_BCMA_PIO
+ bool
+ depends on B43_BCMA
+ select BCMA_BLOCKIO
+ default y
+
config B43_PIO
bool
depends on B43
@@ -107,6 +123,22 @@ config B43_PHY_LP
and embedded devices. It supports 802.11a/g
(802.11a support is optional, and currently disabled).
+config B43_PHY_HT
+ bool "Support for HT-PHY devices (BROKEN)"
+ depends on B43 && BROKEN
+ ---help---
+ Support for the HT-PHY.
+
+ Say N, this is BROKEN and crashes driver.
+
+config B43_PHY_LCN
+ bool "Support for LCN-PHY devices (BROKEN)"
+ depends on B43 && BROKEN
+ ---help---
+ Support for the LCN-PHY.
+
+ Say N, this is BROKEN and crashes driver.
+
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index cef334a8c669..4648bbf76abc 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,4 +1,5 @@
b43-y += main.o
+b43-y += bus.o
b43-y += tables.o
b43-$(CONFIG_B43_PHY_N) += tables_nphy.o
b43-$(CONFIG_B43_PHY_N) += radio_2055.o
@@ -9,6 +10,10 @@ b43-y += phy_a.o
b43-$(CONFIG_B43_PHY_N) += phy_n.o
b43-$(CONFIG_B43_PHY_LP) += phy_lp.o
b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o
+b43-$(CONFIG_B43_PHY_HT) += phy_ht.o
+b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o
+b43-$(CONFIG_B43_PHY_HT) += radio_2059.o
+b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o
b43-y += sysfs.o
b43-y += xmit.o
b43-y += lo.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 25a78cfb7d15..c818b0bc88ec 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -5,12 +5,14 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/hw_random.h>
+#include <linux/bcma/bcma.h>
#include <linux/ssb/ssb.h>
#include <net/mac80211.h>
#include "debugfs.h"
#include "leds.h"
#include "rfkill.h"
+#include "bus.h"
#include "lo.h"
#include "phy_common.h"
@@ -90,6 +92,8 @@
#define B43_MMIO_PIO11_BASE4 0x300
#define B43_MMIO_PIO11_BASE5 0x340
+#define B43_MMIO_RADIO24_CONTROL 0x3D8 /* core rev >= 24 only */
+#define B43_MMIO_RADIO24_DATA 0x3DA /* core rev >= 24 only */
#define B43_MMIO_PHY_VER 0x3E0
#define B43_MMIO_PHY_RADIO 0x3E2
#define B43_MMIO_PHY0 0x3E6
@@ -361,6 +365,10 @@ enum {
#define B43_PHYTYPE_G 0x02
#define B43_PHYTYPE_N 0x04
#define B43_PHYTYPE_LP 0x05
+#define B43_PHYTYPE_SSLPN 0x06
+#define B43_PHYTYPE_HT 0x07
+#define B43_PHYTYPE_LCN 0x08
+#define B43_PHYTYPE_LCNXN 0x09
/* PHYRegisters */
#define B43_PHY_ILT_A_CTRL 0x0072
@@ -414,6 +422,23 @@ enum {
#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */
+/* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */
+#define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */
+#define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */
+#define B43_BCMA_IOCTL_MACPHYCLKEN 0x00000010 /* MAC PHY Clock Control Enable */
+#define B43_BCMA_IOCTL_PLLREFSEL 0x00000020 /* PLL Frequency Reference Select */
+#define B43_BCMA_IOCTL_PHY_BW 0x000000C0 /* PHY band width and clock speed mask (N-PHY+ only?) */
+#define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */
+#define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */
+#define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */
+#define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */
+
+/* BCMA 802.11 core specific IO status (BCMA_IOST) flags */
+#define B43_BCMA_IOST_2G_PHY 0x00000001 /* 2.4G capable phy */
+#define B43_BCMA_IOST_5G_PHY 0x00000002 /* 5G capable phy */
+#define B43_BCMA_IOST_FASTCLKA 0x00000004 /* Fast Clock Available */
+#define B43_BCMA_IOST_DUALB_PHY 0x00000008 /* Dualband phy */
+
/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
#define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */
@@ -569,6 +594,7 @@ struct b43_dma {
struct b43_dmaring *rx_ring;
u32 translation; /* Routing bits */
+ bool parity; /* Check for parity */
};
struct b43_pio_txqueue;
@@ -707,7 +733,7 @@ enum {
/* Data structure for one wireless device (802.11 core) */
struct b43_wldev {
- struct ssb_device *sdev;
+ struct b43_bus_dev *dev;
struct b43_wl *wl;
/* The device initialization status.
@@ -879,36 +905,59 @@ static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
return wl->hw->conf.channel->band;
}
+static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
+{
+ return wldev->dev->bus_may_powerdown(wldev->dev);
+}
+static inline int b43_bus_powerup(struct b43_wldev *wldev, bool dynamic_pctl)
+{
+ return wldev->dev->bus_powerup(wldev->dev, dynamic_pctl);
+}
+static inline int b43_device_is_enabled(struct b43_wldev *wldev)
+{
+ return wldev->dev->device_is_enabled(wldev->dev);
+}
+static inline void b43_device_enable(struct b43_wldev *wldev,
+ u32 core_specific_flags)
+{
+ wldev->dev->device_enable(wldev->dev, core_specific_flags);
+}
+static inline void b43_device_disable(struct b43_wldev *wldev,
+ u32 core_specific_flags)
+{
+ wldev->dev->device_disable(wldev->dev, core_specific_flags);
+}
+
static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
{
- return ssb_read16(dev->sdev, offset);
+ return dev->dev->read16(dev->dev, offset);
}
static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
{
- ssb_write16(dev->sdev, offset, value);
+ dev->dev->write16(dev->dev, offset, value);
}
static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)
{
- return ssb_read32(dev->sdev, offset);
+ return dev->dev->read32(dev->dev, offset);
}
static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
{
- ssb_write32(dev->sdev, offset, value);
+ dev->dev->write32(dev->dev, offset, value);
}
static inline void b43_block_read(struct b43_wldev *dev, void *buffer,
size_t count, u16 offset, u8 reg_width)
{
- ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+ dev->dev->block_read(dev->dev, buffer, count, offset, reg_width);
}
static inline void b43_block_write(struct b43_wldev *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width)
{
- ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+ dev->dev->block_write(dev->dev, buffer, count, offset, reg_width);
}
static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c
new file mode 100644
index 000000000000..64c3f65ff8c0
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.c
@@ -0,0 +1,253 @@
+/*
+
+ Broadcom B43 wireless driver
+ Bus abstraction layer
+
+ This program is free software; you can redistribute it and/or modify
+ 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.
+
+*/
+
+#include "b43.h"
+#include "bus.h"
+
+/* BCMA */
+#ifdef CONFIG_B43_BCMA
+static int b43_bus_bcma_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+ return 0; /* bcma_bus_may_powerdown(dev->bdev->bus); */
+}
+static int b43_bus_bcma_bus_powerup(struct b43_bus_dev *dev,
+ bool dynamic_pctl)
+{
+ return 0; /* bcma_bus_powerup(dev->sdev->bus, dynamic_pctl); */
+}
+static int b43_bus_bcma_device_is_enabled(struct b43_bus_dev *dev)
+{
+ return bcma_core_is_enabled(dev->bdev);
+}
+static void b43_bus_bcma_device_enable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ bcma_core_enable(dev->bdev, core_specific_flags);
+}
+static void b43_bus_bcma_device_disable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ bcma_core_disable(dev->bdev, core_specific_flags);
+}
+static u16 b43_bus_bcma_read16(struct b43_bus_dev *dev, u16 offset)
+{
+ return bcma_read16(dev->bdev, offset);
+}
+static u32 b43_bus_bcma_read32(struct b43_bus_dev *dev, u16 offset)
+{
+ return bcma_read32(dev->bdev, offset);
+}
+static
+void b43_bus_bcma_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+ bcma_write16(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+ bcma_write32(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_block_read(struct b43_bus_dev *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ bcma_block_read(dev->bdev, buffer, count, offset, reg_width);
+}
+static
+void b43_bus_bcma_block_write(struct b43_bus_dev *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ bcma_block_write(dev->bdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
+{
+ struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->bus_type = B43_BUS_BCMA;
+ dev->bdev = core;
+
+ dev->bus_may_powerdown = b43_bus_bcma_bus_may_powerdown;
+ dev->bus_powerup = b43_bus_bcma_bus_powerup;
+ dev->device_is_enabled = b43_bus_bcma_device_is_enabled;
+ dev->device_enable = b43_bus_bcma_device_enable;
+ dev->device_disable = b43_bus_bcma_device_disable;
+
+ dev->read16 = b43_bus_bcma_read16;
+ dev->read32 = b43_bus_bcma_read32;
+ dev->write16 = b43_bus_bcma_write16;
+ dev->write32 = b43_bus_bcma_write32;
+ dev->block_read = b43_bus_bcma_block_read;
+ dev->block_write = b43_bus_bcma_block_write;
+
+ dev->dev = &core->dev;
+ dev->dma_dev = core->dma_dev;
+ dev->irq = core->irq;
+
+ /*
+ dev->board_vendor = core->bus->boardinfo.vendor;
+ dev->board_type = core->bus->boardinfo.type;
+ dev->board_rev = core->bus->boardinfo.rev;
+ */
+
+ dev->chip_id = core->bus->chipinfo.id;
+ dev->chip_rev = core->bus->chipinfo.rev;
+ dev->chip_pkg = core->bus->chipinfo.pkg;
+
+ dev->bus_sprom = &core->bus->sprom;
+
+ dev->core_id = core->id.id;
+ dev->core_rev = core->id.rev;
+
+ return dev;
+}
+#endif /* CONFIG_B43_BCMA */
+
+/* SSB */
+#ifdef CONFIG_B43_SSB
+static int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+ return ssb_bus_may_powerdown(dev->sdev->bus);
+}
+static int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
+ bool dynamic_pctl)
+{
+ return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl);
+}
+static int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
+{
+ return ssb_device_is_enabled(dev->sdev);
+}
+static void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ ssb_device_enable(dev->sdev, core_specific_flags);
+}
+static void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ ssb_device_disable(dev->sdev, core_specific_flags);
+}
+
+static u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
+{
+ return ssb_read16(dev->sdev, offset);
+}
+static u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
+{
+ return ssb_read32(dev->sdev, offset);
+}
+static void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+ ssb_write16(dev->sdev, offset, value);
+}
+static void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+ ssb_write32(dev->sdev, offset, value);
+}
+static void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+}
+static
+void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
+{
+ struct b43_bus_dev *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->bus_type = B43_BUS_SSB;
+ dev->sdev = sdev;
+
+ dev->bus_may_powerdown = b43_bus_ssb_bus_may_powerdown;
+ dev->bus_powerup = b43_bus_ssb_bus_powerup;
+ dev->device_is_enabled = b43_bus_ssb_device_is_enabled;
+ dev->device_enable = b43_bus_ssb_device_enable;
+ dev->device_disable = b43_bus_ssb_device_disable;
+
+ dev->read16 = b43_bus_ssb_read16;
+ dev->read32 = b43_bus_ssb_read32;
+ dev->write16 = b43_bus_ssb_write16;
+ dev->write32 = b43_bus_ssb_write32;
+ dev->block_read = b43_bus_ssb_block_read;
+ dev->block_write = b43_bus_ssb_block_write;
+
+ dev->dev = sdev->dev;
+ dev->dma_dev = sdev->dma_dev;
+ dev->irq = sdev->irq;
+
+ dev->board_vendor = sdev->bus->boardinfo.vendor;
+ dev->board_type = sdev->bus->boardinfo.type;
+ dev->board_rev = sdev->bus->boardinfo.rev;
+
+ dev->chip_id = sdev->bus->chip_id;
+ dev->chip_rev = sdev->bus->chip_rev;
+ dev->chip_pkg = sdev->bus->chip_package;
+
+ dev->bus_sprom = &sdev->bus->sprom;
+
+ dev->core_id = sdev->id.coreid;
+ dev->core_rev = sdev->id.revision;
+
+ return dev;
+}
+#endif /* CONFIG_B43_SSB */
+
+void *b43_bus_get_wldev(struct b43_bus_dev *dev)
+{
+ switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ return bcma_get_drvdata(dev->bdev);
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ return ssb_get_drvdata(dev->sdev);
+#endif
+ }
+ return NULL;
+}
+
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *wldev)
+{
+ switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_set_drvdata(dev->bdev, wldev);
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_set_drvdata(dev->sdev, wldev);
+#endif
+ }
+}
diff --git a/drivers/net/wireless/b43/bus.h b/drivers/net/wireless/b43/bus.h
new file mode 100644
index 000000000000..184c95659279
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.h
@@ -0,0 +1,70 @@
+#ifndef B43_BUS_H_
+#define B43_BUS_H_
+
+enum b43_bus_type {
+#ifdef CONFIG_B43_BCMA
+ B43_BUS_BCMA,
+#endif
+ B43_BUS_SSB,
+};
+
+struct b43_bus_dev {
+ enum b43_bus_type bus_type;
+ union {
+ struct bcma_device *bdev;
+ struct ssb_device *sdev;
+ };
+
+ int (*bus_may_powerdown)(struct b43_bus_dev *dev);
+ int (*bus_powerup)(struct b43_bus_dev *dev, bool dynamic_pctl);
+ int (*device_is_enabled)(struct b43_bus_dev *dev);
+ void (*device_enable)(struct b43_bus_dev *dev,
+ u32 core_specific_flags);
+ void (*device_disable)(struct b43_bus_dev *dev,
+ u32 core_specific_flags);
+
+ u16 (*read16)(struct b43_bus_dev *dev, u16 offset);
+ u32 (*read32)(struct b43_bus_dev *dev, u16 offset);
+ void (*write16)(struct b43_bus_dev *dev, u16 offset, u16 value);
+ void (*write32)(struct b43_bus_dev *dev, u16 offset, u32 value);
+ void (*block_read)(struct b43_bus_dev *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+ void (*block_write)(struct b43_bus_dev *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+
+ struct device *dev;
+ struct device *dma_dev;
+ unsigned int irq;
+
+ u16 board_vendor;
+ u16 board_type;
+ u16 board_rev;
+
+ u16 chip_id;
+ u8 chip_rev;
+ u8 chip_pkg;
+
+ struct ssb_sprom *bus_sprom;
+
+ u16 core_id;
+ u8 core_rev;
+};
+
+static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev)
+{
+ return (dev->bus_type == B43_BUS_SSB &&
+ dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA);
+}
+static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
+{
+ return (dev->bus_type == B43_BUS_SSB &&
+ dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
+}
+
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
+struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
+
+void *b43_bus_get_wldev(struct b43_bus_dev *dev);
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *data);
+
+#endif /* B43_BUS_H_ */
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 59f59fa40334..e751fdee89b2 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -4,7 +4,7 @@
debugfs driver debugging code
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
This 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/dma.c b/drivers/net/wireless/b43/dma.c
index 47d44bcff37d..83cba22ac6e8 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -4,7 +4,7 @@
DMA ringbuffer and descriptor allocation/management
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
Some code in this file is derived from the b44.c driver
Copyright (C) 2002 David S. Miller
@@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
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 << 1);
+ addrhi |= ring->dev->dma.translation;
if (slot == ring->nr_slots - 1)
ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
if (start)
@@ -333,10 +333,10 @@ static inline
dma_addr_t dmaaddr;
if (tx) {
- dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
buf, len, DMA_TO_DEVICE);
} else {
- dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
buf, len, DMA_FROM_DEVICE);
}
@@ -348,10 +348,10 @@ static inline
dma_addr_t addr, size_t len, int tx)
{
if (tx) {
- dma_unmap_single(ring->dev->sdev->dma_dev,
+ dma_unmap_single(ring->dev->dev->dma_dev,
addr, len, DMA_TO_DEVICE);
} else {
- dma_unmap_single(ring->dev->sdev->dma_dev,
+ dma_unmap_single(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
}
@@ -361,7 +361,7 @@ static inline
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_cpu(ring->dev->sdev->dma_dev,
+ dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -370,7 +370,7 @@ static inline
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_device(ring->dev->sdev->dma_dev,
+ dma_sync_single_for_device(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -401,7 +401,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
*/
if (ring->type == B43_DMA_64BIT)
flags |= GFP_DMA;
- ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev,
+ ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
B43_DMA_RINGMEMSIZE,
&(ring->dmabase), flags);
if (!ring->descbase) {
@@ -415,7 +415,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
static void free_ringmemory(struct b43_dmaring *ring)
{
- dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE,
+ dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
ring->descbase, ring->dmabase);
}
@@ -523,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
dma_addr_t addr,
size_t buffersize, bool dma_to_device)
{
- if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr)))
+ if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
return 1;
switch (ring->type) {
@@ -659,6 +659,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
u32 value;
u32 addrext;
u32 trans = ring->dev->dma.translation;
+ bool parity = ring->dev->dma.parity;
if (ring->tx) {
if (ring->type == B43_DMA_64BIT) {
@@ -669,13 +670,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
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 << 1));
+ | trans);
} else {
u32 ringbase = (u32) (ring->dmabase);
@@ -684,6 +687,8 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
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)
@@ -702,13 +707,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
value |= B43_DMA64_RXENABLE;
value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
& B43_DMA64_RXADDREXT_MASK;
+ 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 << 1));
+ | trans);
b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc64));
} else {
@@ -720,6 +727,8 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
value |= B43_DMA32_RXENABLE;
value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
& B43_DMA32_RXADDREXT_MASK;
+ 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)
@@ -757,14 +766,14 @@ static void dmacontroller_cleanup(struct b43_dmaring *ring)
static void free_all_descbuffers(struct b43_dmaring *ring)
{
- struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ /* get meta - ignore returned value */
+ ring->ops->idx2desc(ring, i, &meta);
if (!meta->skb || b43_dma_ptr_is_poisoned(meta->skb)) {
B43_WARN_ON(!ring->tx);
@@ -869,7 +878,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
goto err_kfree_meta;
/* test for ability to dma to txhdr_cache */
- dma_test = dma_map_single(dev->sdev->dma_dev,
+ dma_test = dma_map_single(dev->dev->dma_dev,
ring->txhdr_cache,
b43_txhdr_size(dev),
DMA_TO_DEVICE);
@@ -884,7 +893,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
if (!ring->txhdr_cache)
goto err_kfree_meta;
- dma_test = dma_map_single(dev->sdev->dma_dev,
+ dma_test = dma_map_single(dev->dev->dma_dev,
ring->txhdr_cache,
b43_txhdr_size(dev),
DMA_TO_DEVICE);
@@ -898,7 +907,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
}
}
- dma_unmap_single(dev->sdev->dma_dev,
+ dma_unmap_single(dev->dev->dma_dev,
dma_test, b43_txhdr_size(dev),
DMA_TO_DEVICE);
}
@@ -1013,9 +1022,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
/* Try to set the DMA mask. If it fails, try falling back to a
* lower mask, as we can always also support a lower one. */
while (1) {
- err = dma_set_mask(dev->sdev->dma_dev, mask);
+ err = dma_set_mask(dev->dev->dma_dev, mask);
if (!err) {
- err = dma_set_coherent_mask(dev->sdev->dma_dev, mask);
+ err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
if (!err)
break;
}
@@ -1055,7 +1064,26 @@ int b43_dma_init(struct b43_wldev *dev)
err = b43_dma_set_mask(dev, dmamask);
if (err)
return err;
- dma->translation = ssb_dma_translation(dev->sdev);
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ dma->translation = bcma_core_dma_translation(dev->dev->bdev);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ dma->translation = ssb_dma_translation(dev->dev->sdev);
+ break;
+#endif
+ }
+
+ dma->parity = true;
+#ifdef CONFIG_B43_BCMA
+ /* TODO: find out which SSB devices need disabling parity */
+ if (dev->dev->bus_type == B43_BUS_BCMA)
+ dma->parity = false;
+#endif
err = -ENOMEM;
/* setup TX DMA channels. */
@@ -1085,7 +1113,7 @@ int b43_dma_init(struct b43_wldev *dev)
goto err_destroy_mcast;
/* No support for the TX status DMA ring. */
- B43_WARN_ON(dev->sdev->id.revision < 5);
+ B43_WARN_ON(dev->dev->core_rev < 5);
b43dbg(dev->wl, "%u-bit DMA initialized\n",
(unsigned int)type);
@@ -1388,7 +1416,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
{
const struct b43_dma_ops *ops;
struct b43_dmaring *ring;
- struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
int slot, firstused;
bool frame_succeed;
@@ -1416,7 +1443,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
ops = ring->ops;
while (1) {
B43_WARN_ON(slot < 0 || slot >= ring->nr_slots);
- desc = ops->idx2desc(ring, slot, &meta);
+ /* get meta - ignore returned value */
+ ops->idx2desc(ring, slot, &meta);
if (b43_dma_ptr_is_poisoned(meta->skb)) {
b43dbg(dev->wl, "Poisoned TX slot %d (first=%d) "
@@ -1600,6 +1628,7 @@ void b43_dma_rx(struct b43_dmaring *ring)
dma_rx(ring, &slot);
update_max_used_slots(ring, ++used_slots);
}
+ wmb();
ops->set_current_rxslot(ring, slot);
ring->current_slot = slot;
}
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index e8a80a1251bf..cdf87094efe8 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -20,6 +20,7 @@
#define B43_DMA32_TXSUSPEND 0x00000002
#define B43_DMA32_TXLOOPBACK 0x00000004
#define B43_DMA32_TXFLUSH 0x00000010
+#define B43_DMA32_TXPARITYDISABLE 0x00000800
#define B43_DMA32_TXADDREXT_MASK 0x00030000
#define B43_DMA32_TXADDREXT_SHIFT 16
#define B43_DMA32_TXRING 0x04
@@ -44,6 +45,7 @@
#define B43_DMA32_RXFROFF_MASK 0x000000FE
#define B43_DMA32_RXFROFF_SHIFT 1
#define B43_DMA32_RXDIRECTFIFO 0x00000100
+#define B43_DMA32_RXPARITYDISABLE 0x00000800
#define B43_DMA32_RXADDREXT_MASK 0x00030000
#define B43_DMA32_RXADDREXT_SHIFT 16
#define B43_DMA32_RXRING 0x14
@@ -84,6 +86,7 @@ struct b43_dmadesc32 {
#define B43_DMA64_TXSUSPEND 0x00000002
#define B43_DMA64_TXLOOPBACK 0x00000004
#define B43_DMA64_TXFLUSH 0x00000010
+#define B43_DMA64_TXPARITYDISABLE 0x00000800
#define B43_DMA64_TXADDREXT_MASK 0x00030000
#define B43_DMA64_TXADDREXT_SHIFT 16
#define B43_DMA64_TXINDEX 0x04
@@ -111,6 +114,7 @@ struct b43_dmadesc32 {
#define B43_DMA64_RXFROFF_MASK 0x000000FE
#define B43_DMA64_RXFROFF_SHIFT 1
#define B43_DMA64_RXDIRECTFIFO 0x00000100
+#define B43_DMA64_RXPARITYDISABLE 0x00000800
#define B43_DMA64_RXADDREXT_MASK 0x00030000
#define B43_DMA64_RXADDREXT_SHIFT 16
#define B43_DMA64_RXINDEX 0x24
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 0cafafe368af..a38c1c6446ad 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -138,7 +138,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
led->led_dev.default_trigger = default_trigger;
led->led_dev.brightness_set = b43_led_brightness_set;
- err = led_classdev_register(dev->sdev->dev, &led->led_dev);
+ err = led_classdev_register(dev->dev->dev, &led->led_dev);
if (err) {
b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
led->wl = NULL;
@@ -215,13 +215,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
enum b43_led_behaviour *behaviour,
bool *activelow)
{
- struct ssb_bus *bus = dev->sdev->bus;
u8 sprom[4];
- sprom[0] = bus->sprom.gpio0;
- sprom[1] = bus->sprom.gpio1;
- sprom[2] = bus->sprom.gpio2;
- sprom[3] = bus->sprom.gpio3;
+ sprom[0] = dev->dev->bus_sprom->gpio0;
+ sprom[1] = dev->dev->bus_sprom->gpio1;
+ sprom[2] = dev->dev->bus_sprom->gpio2;
+ sprom[3] = dev->dev->bus_sprom->gpio3;
if (sprom[led_index] == 0xFF) {
/* There is no LED information in the SPROM
@@ -231,12 +230,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
case 0:
*behaviour = B43_LED_ACTIVITY;
*activelow = 1;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+ if (dev->dev->board_vendor == PCI_VENDOR_ID_COMPAQ)
*behaviour = B43_LED_RADIO_ALL;
break;
case 1:
*behaviour = B43_LED_RADIO_B;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+ if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)
*behaviour = B43_LED_ASSOC;
break;
case 2:
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index 2ef7d4b38540..4c82d582a524 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -6,7 +6,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005, 2006 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,
rfover |= pga;
rfover |= lna;
rfover |= trsw_rx;
- if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+ if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA)
&& phy->rev > 6)
rfover |= B43_PHY_RFOVERVAL_EXTLNA;
@@ -301,14 +301,12 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
max_rx_gain = 0;
if (has_loopback_gain(phy)) {
- int trsw_rx = 0;
int trsw_rx_gain;
if (use_trsw_rx) {
trsw_rx_gain = gphy->trsw_rx_gain / 2;
if (max_rx_gain >= trsw_rx_gain) {
trsw_rx_gain = max_rx_gain - trsw_rx_gain;
- trsw_rx = 0x20;
}
} else
trsw_rx_gain = max_rx_gain;
@@ -387,7 +385,7 @@ struct lo_g_saved_values {
static void lo_measure_setup(struct b43_wldev *dev,
struct lo_g_saved_values *sav)
{
- struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
struct b43_txpower_lo_control *lo = gphy->lo_control;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index eb4159686985..032d46674f6b 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2009 Michael Buesch <mb@bu3sch.de>
+ 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>
@@ -113,6 +113,17 @@ static int b43_modparam_pio = B43_PIO_DEFAULT;
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, 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),
+ BCMA_CORETABLE_END
+};
+MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
+#endif
+
+#ifdef CONFIG_B43_SSB
static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
@@ -126,8 +137,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
SSB_DEVTABLE_END
};
-
MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+#endif
/* Channel and ratetables are shared for all devices.
* They can't be const, because ieee80211 puts some precalculated
@@ -548,7 +559,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
{
u32 low, high;
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
/* The hardware guarantees us an atomic read, if we
* read the low register first. */
@@ -586,7 +597,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
{
u32 low, high;
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
low = tsf;
high = (tsf >> 32);
@@ -714,7 +725,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
b43_ram_write(dev, i * 4, buffer[i]);
b43_write16(dev, 0x0568, 0x0000);
- if (dev->sdev->id.revision < 11)
+ if (dev->dev->core_rev < 11)
b43_write16(dev, 0x07C0, 0x0000);
else
b43_write16(dev, 0x07C0, 0x0100);
@@ -1132,7 +1143,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit write */
b43_read32(dev, B43_MMIO_MACCTL);
- if (awake && dev->sdev->id.revision >= 5) {
+ if (awake && dev->dev->core_rev >= 5) {
/* Wait for the microcode to wake up. */
for (i = 0; i < 100; i++) {
ucstat = b43_shm_read16(dev, B43_SHM_SHARED,
@@ -1144,35 +1155,85 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
}
}
-static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+#ifdef CONFIG_B43_BCMA
+static void b43_bcma_phy_reset(struct b43_wldev *dev)
+{
+ u32 flags;
+
+ /* Put PHY into reset */
+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ flags |= B43_BCMA_IOCTL_PHY_RESET;
+ flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+ udelay(2);
+
+ /* Take PHY out of reset */
+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ flags &= ~B43_BCMA_IOCTL_PHY_RESET;
+ flags |= BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+ udelay(1);
+
+ /* Do not force clock anymore */
+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ flags &= ~BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+ udelay(1);
+}
+
+static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+ b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN);
+ bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
+ b43_bcma_phy_reset(dev);
+ bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true);
+}
+#endif
+
+static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
+ struct ssb_device *sdev = dev->dev->sdev;
u32 tmslow;
+ u32 flags = 0;
+ if (gmode)
+ flags |= B43_TMSLOW_GMODE;
flags |= B43_TMSLOW_PHYCLKEN;
flags |= B43_TMSLOW_PHYRESET;
if (dev->phy.type == B43_PHYTYPE_N)
flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
- ssb_device_enable(dev->sdev, flags);
+ b43_device_enable(dev, flags);
msleep(2); /* Wait for the PLL to turn on. */
/* Now take the PHY out of Reset again */
- tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
+ tmslow = ssb_read32(sdev, SSB_TMSLOW);
tmslow |= SSB_TMSLOW_FGC;
tmslow &= ~B43_TMSLOW_PHYRESET;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */
+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_read32(sdev, SSB_TMSLOW); /* flush */
msleep(1);
tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */
+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_read32(sdev, SSB_TMSLOW); /* flush */
msleep(1);
}
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
u32 macctl;
- b43_ssb_wireless_core_reset(dev, flags);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ b43_bcma_wireless_core_reset(dev, gmode);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ b43_ssb_wireless_core_reset(dev, gmode);
+ break;
+#endif
+ }
/* Turn Analog ON, but only if we already know the PHY-type.
* This protects against very early setup where we don't know the
@@ -1183,7 +1244,7 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_GMODE;
- if (flags & B43_TMSLOW_GMODE)
+ if (gmode)
macctl |= B43_MACCTL_GMODE;
macctl |= B43_MACCTL_IHR_ENABLED;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
@@ -1221,7 +1282,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev)
{
u32 dummy;
- if (dev->sdev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
return;
/* Read all entries from the microcode TXstatus FIFO
* and throw them away.
@@ -1427,9 +1488,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
/* Get the mask of available antennas. */
if (dev->phy.gmode)
- antenna_mask = dev->sdev->bus->sprom.ant_available_bg;
+ antenna_mask = dev->dev->bus_sprom->ant_available_bg;
else
- antenna_mask = dev->sdev->bus->sprom.ant_available_a;
+ antenna_mask = dev->dev->bus_sprom->ant_available_a;
if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
/* This antenna is not available. Fall back to default. */
@@ -1644,7 +1705,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
/* wl->mutex is enough. */
b43_do_beacon_update_trigger_work(dev);
mmiowb();
@@ -1689,7 +1750,7 @@ static void b43_update_templates(struct b43_wl *wl)
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
{
b43_time_lock(dev);
- if (dev->sdev->id.revision >= 3) {
+ if (dev->dev->core_rev >= 3) {
b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
} else {
@@ -1923,7 +1984,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
return IRQ_NONE;
reason &= dev->irq_mask;
if (!reason)
- return IRQ_HANDLED;
+ return IRQ_NONE;
dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
& 0x0001DC00;
@@ -2063,7 +2124,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
B43_WARN_ON(1);
return -ENOSYS;
}
- err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev);
+ err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
if (err == -ENOENT) {
snprintf(ctx->errors[ctx->req_type],
sizeof(ctx->errors[ctx->req_type]),
@@ -2113,26 +2174,48 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
{
struct b43_wldev *dev = ctx->dev;
struct b43_firmware *fw = &ctx->dev->fw;
- const u8 rev = ctx->dev->sdev->id.revision;
+ const u8 rev = ctx->dev->dev->core_rev;
const char *filename;
u32 tmshigh;
int err;
+ /* Files for HT and LCN were found by trying one by one */
+
/* Get microcode */
- if ((rev >= 5) && (rev <= 10))
+ if ((rev >= 5) && (rev <= 10)) {
filename = "ucode5";
- else if ((rev >= 11) && (rev <= 12))
+ } else if ((rev >= 11) && (rev <= 12)) {
filename = "ucode11";
- else if (rev == 13)
+ } else if (rev == 13) {
filename = "ucode13";
- else if (rev == 14)
+ } else if (rev == 14) {
filename = "ucode14";
- else if (rev == 15)
+ } else if (rev == 15) {
filename = "ucode15";
- else if ((rev >= 16) && (rev <= 20))
- filename = "ucode16_mimo";
- else
- goto err_no_ucode;
+ } else {
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_N:
+ if (rev >= 16)
+ filename = "ucode16_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ucode29_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "ucode24_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ default:
+ goto err_no_ucode;
+ }
+ }
err = b43_do_request_fw(ctx, filename, &fw->ucode);
if (err)
goto err_load;
@@ -2157,7 +2240,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1initvals5";
else
@@ -2191,6 +2274,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0initvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0initvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
@@ -2202,7 +2297,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1bsinitvals5";
else
@@ -2238,6 +2333,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0bsinitvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0bsinitvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
@@ -2448,7 +2555,7 @@ static int b43_upload_microcode(struct b43_wldev *dev)
snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
dev->fw.rev, dev->fw.patch);
- wiphy->hw_version = dev->sdev->id.coreid;
+ wiphy->hw_version = dev->dev->core_id;
if (b43_is_old_txhdr_format(dev)) {
/* We're over the deadline, but we keep support for old fw
@@ -2566,7 +2673,7 @@ out:
*/
static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
#ifdef CONFIG_SSB_DRIVER_PCICORE
return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
@@ -2588,7 +2695,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
mask = 0x0000001F;
set = 0x0000000F;
- if (dev->sdev->bus->chip_id == 0x4301) {
+ if (dev->dev->chip_id == 0x4301) {
mask |= 0x0060;
set |= 0x0060;
}
@@ -2599,21 +2706,34 @@ static int b43_gpio_init(struct b43_wldev *dev)
mask |= 0x0180;
set |= 0x0180;
}
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) {
b43_write16(dev, B43_MMIO_GPIO_MASK,
b43_read16(dev, B43_MMIO_GPIO_MASK)
| 0x0200);
mask |= 0x0200;
set |= 0x0200;
}
- if (dev->sdev->id.revision >= 2)
+ if (dev->dev->core_rev >= 2)
mask |= 0x0010; /* FIXME: This is redundant. */
- gpiodev = b43_ssb_gpio_dev(dev);
- if (gpiodev)
- ssb_write32(gpiodev, B43_GPIO_CONTROL,
- (ssb_read32(gpiodev, B43_GPIO_CONTROL)
- & mask) | set);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+ (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
+ BCMA_CC_GPIOCTL) & mask) | set);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ gpiodev = b43_ssb_gpio_dev(dev);
+ if (gpiodev)
+ ssb_write32(gpiodev, B43_GPIO_CONTROL,
+ (ssb_read32(gpiodev, B43_GPIO_CONTROL)
+ & mask) | set);
+ break;
+#endif
+ }
return 0;
}
@@ -2623,9 +2743,21 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
{
struct ssb_device *gpiodev;
- gpiodev = b43_ssb_gpio_dev(dev);
- if (gpiodev)
- ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+ 0);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ gpiodev = b43_ssb_gpio_dev(dev);
+ if (gpiodev)
+ ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+ break;
+#endif
+ }
}
/* http://bcm-specs.sipsolutions.net/EnableMac */
@@ -2697,12 +2829,30 @@ out:
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
{
- u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
- if (on)
- tmslow |= B43_TMSLOW_MACPHYCLKEN;
- else
- tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+ u32 tmp;
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ if (on)
+ tmp |= B43_BCMA_IOCTL_MACPHYCLKEN;
+ else
+ tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN;
+ 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 (on)
+ tmp |= B43_TMSLOW_MACPHYCLKEN;
+ else
+ tmp &= ~B43_TMSLOW_MACPHYCLKEN;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ break;
+#endif
+ }
}
static void b43_adjust_opmode(struct b43_wldev *dev)
@@ -2741,15 +2891,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
/* Workaround: On old hardware the HW-MAC-address-filter
* doesn't work properly, so always run promisc in filter
* it in software. */
- if (dev->sdev->id.revision <= 4)
+ if (dev->dev->core_rev <= 4)
ctl |= B43_MACCTL_PROMISC;
b43_write32(dev, B43_MMIO_MACCTL, ctl);
cfp_pretbtt = 2;
if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) {
- if (dev->sdev->bus->chip_id == 0x4306 &&
- dev->sdev->bus->chip_rev == 3)
+ if (dev->dev->chip_id == 0x4306 &&
+ dev->dev->chip_rev == 3)
cfp_pretbtt = 100;
else
cfp_pretbtt = 50;
@@ -2907,7 +3057,7 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_write16(dev, 0x005E, value16);
}
b43_write32(dev, 0x0100, 0x01000000);
- if (dev->sdev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
b43_write32(dev, 0x010C, 0x01000000);
b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
@@ -2922,7 +3072,7 @@ static int b43_chip_init(struct b43_wldev *dev)
/* Initially set the wireless operation mode. */
b43_adjust_opmode(dev);
- if (dev->sdev->id.revision < 3) {
+ if (dev->dev->core_rev < 3) {
b43_write16(dev, 0x060E, 0x0000);
b43_write16(dev, 0x0610, 0x8000);
b43_write16(dev, 0x0604, 0x0000);
@@ -2941,8 +3091,20 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_mac_phy_clock_set(dev, true);
- b43_write16(dev, B43_MMIO_POWERUP_DELAY,
- dev->sdev->bus->chipco.fast_pwrup_delay);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ /* FIXME: 0xE74 is quite common, but should be read from CC */
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY,
+ dev->dev->sdev->bus->chipco.fast_pwrup_delay);
+ break;
+#endif
+ }
err = 0;
b43dbg(dev->wl, "Chip initialized\n");
@@ -3105,7 +3267,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
- if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) {
+ if ((dev->dev->core_rev >= 3) && (dev->dev->core_rev <= 10)) {
/* The 32bit register shadows the two 16bit registers
* with update sideeffects. Validate this. */
b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA);
@@ -3458,21 +3620,33 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
static void b43_put_phy_into_reset(struct b43_wldev *dev)
{
- struct ssb_device *sdev = dev->sdev;
- u32 tmslow;
+ u32 tmp;
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~B43_TMSLOW_GMODE;
- tmslow |= B43_TMSLOW_PHYRESET;
- tmslow |= SSB_TMSLOW_FGC;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ b43err(dev->wl,
+ "Putting PHY into reset not supported on BCMA\n");
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~B43_TMSLOW_GMODE;
+ tmp |= B43_TMSLOW_PHYRESET;
+ tmp |= SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ msleep(1);
+
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~SSB_TMSLOW_FGC;
+ tmp |= B43_TMSLOW_PHYRESET;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ msleep(1);
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~SSB_TMSLOW_FGC;
- tmslow |= B43_TMSLOW_PHYRESET;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
+ break;
+#endif
+ }
}
static const char *band_to_string(enum ieee80211_band band)
@@ -3954,7 +4128,7 @@ redo:
/* Disable interrupts on the device. */
b43_set_status(dev, B43_STAT_INITIALIZED);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
/* wl->mutex is locked. That is enough. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
@@ -3967,11 +4141,11 @@ redo:
/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
orig_dev = dev;
mutex_unlock(&wl->mutex);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
b43_sdio_free_irq(dev);
} else {
- synchronize_irq(dev->sdev->irq);
- free_irq(dev->sdev->irq, dev);
+ synchronize_irq(dev->dev->irq);
+ free_irq(dev->dev->irq, dev);
}
mutex_lock(&wl->mutex);
dev = wl->current_dev;
@@ -4004,19 +4178,19 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
drain_txstatus_queue(dev);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
if (err) {
b43err(dev->wl, "Cannot request SDIO IRQ\n");
goto out;
}
} else {
- err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler,
+ err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
b43_interrupt_thread_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) {
b43err(dev->wl, "Cannot request IRQ-%d\n",
- dev->sdev->irq);
+ dev->dev->irq);
goto out;
}
}
@@ -4083,9 +4257,21 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1;
break;
#endif
+#ifdef CONFIG_B43_PHY_HT
+ case B43_PHYTYPE_HT:
+ if (phy_rev > 1)
+ unsupported = 1;
+ break;
+#endif
+#ifdef CONFIG_B43_PHY_LCN
+ case B43_PHYTYPE_LCN:
+ if (phy_rev > 1)
+ unsupported = 1;
+ break;
+#endif
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43err(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
@@ -4096,22 +4282,42 @@ static int b43_phy_versioning(struct b43_wldev *dev)
analog_type, phy_type, phy_rev);
/* Get RADIO versioning */
- if (dev->sdev->bus->chip_id == 0x4317) {
- if (dev->sdev->bus->chip_rev == 0)
- tmp = 0x3205017F;
- else if (dev->sdev->bus->chip_rev == 1)
- tmp = 0x4205017F;
- else
- tmp = 0x5205017F;
+ if (dev->dev->core_rev >= 24) {
+ u16 radio24[3];
+
+ for (tmp = 0; tmp < 3; tmp++) {
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+ radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+ }
+
+ /* Broadcom uses "id" for our "ver" and has separated "ver" */
+ /* radio_ver = (radio24[0] & 0xF0) >> 4; */
+
+ radio_manuf = 0x17F;
+ radio_ver = (radio24[2] << 8) | radio24[1];
+ radio_rev = (radio24[0] & 0xF);
} else {
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
- }
- radio_manuf = (tmp & 0x00000FFF);
- radio_ver = (tmp & 0x0FFFF000) >> 12;
- radio_rev = (tmp & 0xF0000000) >> 28;
+ if (dev->dev->chip_id == 0x4317) {
+ if (dev->dev->chip_rev == 0)
+ tmp = 0x3205017F;
+ else if (dev->dev->chip_rev == 1)
+ tmp = 0x4205017F;
+ else
+ tmp = 0x5205017F;
+ } else {
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
+ << 16;
+ }
+ radio_manuf = (tmp & 0x00000FFF);
+ radio_ver = (tmp & 0x0FFFF000) >> 12;
+ radio_rev = (tmp & 0xF0000000) >> 28;
+ }
+
if (radio_manuf != 0x17F /* Broadcom */)
unsupported = 1;
switch (phy_type) {
@@ -4139,6 +4345,14 @@ static int b43_phy_versioning(struct b43_wldev *dev)
if (radio_ver != 0x2062 && radio_ver != 0x2063)
unsupported = 1;
break;
+ case B43_PHYTYPE_HT:
+ if (radio_ver != 0x2059)
+ unsupported = 1;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (radio_ver != 0x2064)
+ unsupported = 1;
+ break;
default:
B43_WARN_ON(1);
}
@@ -4204,7 +4418,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
{
- struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u64 hf;
if (!modparam_btcoex)
@@ -4231,16 +4445,21 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus;
u32 tmp;
+ if (dev->dev->bus_type != B43_BUS_SSB)
+ return;
+
+ bus = dev->dev->sdev->bus;
+
if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) ||
(bus->chip_id == 0x4312)) {
- tmp = ssb_read32(dev->sdev, SSB_IMCFGLO);
+ tmp = ssb_read32(dev->dev->sdev, SSB_IMCFGLO);
tmp &= ~SSB_IMCFGLO_REQTO;
tmp &= ~SSB_IMCFGLO_SERTO;
tmp |= 0x3;
- ssb_write32(dev->sdev, SSB_IMCFGLO, tmp);
+ ssb_write32(dev->dev->sdev, SSB_IMCFGLO, tmp);
ssb_commit_settings(bus);
}
}
@@ -4310,36 +4529,45 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
dev->wl->current_beacon = NULL;
}
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(dev->sdev->bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
}
/* Initialize a wireless core */
static int b43_wireless_core_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
- struct ssb_sprom *sprom = &bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
int err;
u64 hf;
- u32 tmp;
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
- err = ssb_bus_powerup(bus, 0);
+ err = b43_bus_powerup(dev, 0);
if (err)
goto out;
- if (!ssb_device_is_enabled(dev->sdev)) {
- tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
- }
+ if (!b43_device_is_enabled(dev))
+ b43_wireless_core_reset(dev, phy->gmode);
/* Reset all data structures. */
setup_struct_wldev_for_init(dev);
phy->ops->prepare_structs(dev);
/* Enable IRQ routing to this device. */
- ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+ dev->dev->bdev, true);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore,
+ dev->dev->sdev);
+ break;
+#endif
+ }
b43_imcfglo_timeouts_workaround(dev);
b43_bluetooth_coext_disable(dev);
@@ -4352,7 +4580,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
if (err)
goto err_busdown;
b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_WLCOREREV, dev->sdev->id.revision);
+ B43_SHM_SH_WLCOREREV, dev->dev->core_rev);
hf = b43_hf_read(dev);
if (phy->type == B43_PHYTYPE_G) {
hf |= B43_HF_SYMW;
@@ -4370,8 +4598,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
#ifdef CONFIG_SSB_DRIVER_PCICORE
- if ((bus->bustype == SSB_BUSTYPE_PCI) &&
- (bus->pcicore.dev->id.revision <= 10))
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */
#endif
hf &= ~B43_HF_SKCFPUP;
@@ -4399,8 +4628,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
/* Maximum Contention Window */
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
- if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
- (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) ||
+ if (b43_bus_host_is_pcmcia(dev->dev) ||
+ b43_bus_host_is_sdio(dev->dev) ||
dev->use_pio) {
dev->__using_pio_transfers = 1;
err = b43_pio_init(dev);
@@ -4414,7 +4643,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_set_synth_pu_delay(dev, 1);
b43_bluetooth_coext_enable(dev);
- ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
+ b43_bus_powerup(dev, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
b43_upload_card_macaddress(dev);
b43_security_init(dev);
@@ -4431,7 +4660,7 @@ out:
err_chip_exit:
b43_chip_exit(dev);
err_busdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
return err;
}
@@ -4737,11 +4966,10 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
static int b43_wireless_core_attach(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
- struct ssb_bus *bus = dev->sdev->bus;
- struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
+ struct pci_dev *pdev = NULL;
int err;
- bool have_2ghz_phy = 0, have_5ghz_phy = 0;
u32 tmp;
+ bool have_2ghz_phy = 0, have_5ghz_phy = 0;
/* Do NOT do any device initialization here.
* Do it in wireless_core_init() instead.
@@ -4750,25 +4978,42 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
* that in core_init(), too.
*/
- err = ssb_bus_powerup(bus, 0);
+#ifdef CONFIG_B43_SSB
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
+ pdev = dev->dev->sdev->bus->host_pci;
+#endif
+
+ err = b43_bus_powerup(dev, 0);
if (err) {
b43err(wl, "Bus powerup failed\n");
goto out;
}
- /* Get the PHY type. */
- if (dev->sdev->id.revision >= 5) {
- u32 tmshigh;
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
- have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
- have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
- } else
- B43_WARN_ON(1);
+ /* Get the PHY type. */
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
+ have_2ghz_phy = !!(tmp & B43_BCMA_IOST_2G_PHY);
+ have_5ghz_phy = !!(tmp & B43_BCMA_IOST_5G_PHY);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ if (dev->dev->core_rev >= 5) {
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+ have_2ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_2GHZ_PHY);
+ have_5ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_5GHZ_PHY);
+ } else
+ B43_WARN_ON(1);
+ break;
+#endif
+ }
dev->phy.gmode = have_2ghz_phy;
dev->phy.radio_on = 1;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_phy_versioning(dev);
if (err)
@@ -4790,6 +5035,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
#endif
case B43_PHYTYPE_G:
case B43_PHYTYPE_N:
+ case B43_PHYTYPE_HT:
+ case B43_PHYTYPE_LCN:
have_2ghz_phy = 1;
break;
default:
@@ -4816,8 +5063,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
goto err_powerdown;
dev->phy.gmode = have_2ghz_phy;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_validate_chipaccess(dev);
if (err)
@@ -4832,8 +5078,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
INIT_WORK(&dev->restart_work, b43_chip_reset);
dev->phy.ops->switch_analog(dev, 0);
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
out:
return err;
@@ -4841,11 +5087,11 @@ out:
err_phy_free:
b43_phy_free(dev);
err_powerdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
return err;
}
-static void b43_one_core_detach(struct ssb_device *dev)
+static void b43_one_core_detach(struct b43_bus_dev *dev)
{
struct b43_wldev *wldev;
struct b43_wl *wl;
@@ -4853,17 +5099,17 @@ static void b43_one_core_detach(struct ssb_device *dev)
/* Do not cancel ieee80211-workqueue based work here.
* See comment in b43_remove(). */
- wldev = ssb_get_drvdata(dev);
+ wldev = b43_bus_get_wldev(dev);
wl = wldev->wl;
b43_debugfs_remove_device(wldev);
b43_wireless_core_detach(wldev);
list_del(&wldev->list);
wl->nr_devs--;
- ssb_set_drvdata(dev, NULL);
+ b43_bus_set_wldev(dev, NULL);
kfree(wldev);
}
-static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct b43_wldev *wldev;
int err = -ENOMEM;
@@ -4873,7 +5119,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
goto out;
wldev->use_pio = b43_modparam_pio;
- wldev->sdev = dev;
+ wldev->dev = dev;
wldev->wl = wl;
b43_set_status(wldev, B43_STAT_UNINIT);
wldev->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -4885,7 +5131,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
list_add(&wldev->list, &wl->devlist);
wl->nr_devs++;
- ssb_set_drvdata(dev, wldev);
+ b43_bus_set_wldev(dev, wldev);
b43_debugfs_add_device(wldev);
out:
@@ -4926,19 +5172,20 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
}
}
-static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
+static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct ieee80211_hw *hw = wl->hw;
- ssb_set_devtypedata(dev, NULL);
+ ssb_set_devtypedata(dev->sdev, NULL);
ieee80211_free_hw(hw);
}
-static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
{
- struct ssb_sprom *sprom = &dev->bus->sprom;
+ struct ssb_sprom *sprom = dev->bus_sprom;
struct ieee80211_hw *hw;
struct b43_wl *wl;
+ char chip_name[6];
hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
if (!hw) {
@@ -4977,29 +5224,105 @@ static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
INIT_WORK(&wl->tx_work, b43_tx_work);
skb_queue_head_init(&wl->tx_queue);
- b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
- dev->bus->chip_id, dev->id.revision);
+ snprintf(chip_name, ARRAY_SIZE(chip_name),
+ (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id);
+ b43info(wl, "Broadcom %s WLAN found (core revision %u)\n", chip_name,
+ dev->core_rev);
return wl;
}
-static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
+#ifdef CONFIG_B43_BCMA
+static int b43_bcma_probe(struct bcma_device *core)
{
+ struct b43_bus_dev *dev;
+ struct b43_wl *wl;
+ int err;
+
+ dev = b43_bus_dev_bcma_init(core);
+ if (!dev)
+ return -ENODEV;
+
+ wl = b43_wireless_init(dev);
+ if (IS_ERR(wl)) {
+ err = PTR_ERR(wl);
+ goto bcma_out;
+ }
+
+ err = b43_one_core_attach(dev, wl);
+ if (err)
+ goto bcma_err_wireless_exit;
+
+ err = ieee80211_register_hw(wl->hw);
+ if (err)
+ goto bcma_err_one_core_detach;
+ b43_leds_register(wl->current_dev);
+
+bcma_out:
+ return err;
+
+bcma_err_one_core_detach:
+ b43_one_core_detach(dev);
+bcma_err_wireless_exit:
+ ieee80211_free_hw(wl->hw);
+ return err;
+}
+
+static void b43_bcma_remove(struct bcma_device *core)
+{
+ struct b43_wldev *wldev = bcma_get_drvdata(core);
+ struct b43_wl *wl = wldev->wl;
+
+ /* We must cancel any work here before unregistering from ieee80211,
+ * as the ieee80211 unreg will destroy the workqueue. */
+ cancel_work_sync(&wldev->restart_work);
+
+ /* Restore the queues count before unregistering, because firmware detect
+ * might have modified it. Restoring is important, so the networking
+ * stack can properly free resources. */
+ wl->hw->queues = wl->mac80211_initially_registered_queues;
+ b43_leds_stop(wldev);
+ ieee80211_unregister_hw(wl->hw);
+
+ b43_one_core_detach(wldev->dev);
+
+ b43_leds_unregister(wl);
+
+ ieee80211_free_hw(wl->hw);
+}
+
+static struct bcma_driver b43_bcma_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = b43_bcma_tbl,
+ .probe = b43_bcma_probe,
+ .remove = b43_bcma_remove,
+};
+#endif
+
+#ifdef CONFIG_B43_SSB
+static
+int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+{
+ struct b43_bus_dev *dev;
struct b43_wl *wl;
int err;
int first = 0;
- wl = ssb_get_devtypedata(dev);
+ dev = b43_bus_dev_ssb_init(sdev);
+ if (!dev)
+ return -ENOMEM;
+
+ wl = ssb_get_devtypedata(sdev);
if (!wl) {
/* Probing the first core. Must setup common struct b43_wl */
first = 1;
- b43_sprom_fixup(dev->bus);
+ b43_sprom_fixup(sdev->bus);
wl = b43_wireless_init(dev);
if (IS_ERR(wl)) {
err = PTR_ERR(wl);
goto out;
}
- ssb_set_devtypedata(dev, wl);
- B43_WARN_ON(ssb_get_devtypedata(dev) != wl);
+ ssb_set_devtypedata(sdev, wl);
+ B43_WARN_ON(ssb_get_devtypedata(sdev) != wl);
}
err = b43_one_core_attach(dev, wl);
if (err)
@@ -5023,10 +5346,10 @@ static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
return err;
}
-static void b43_ssb_remove(struct ssb_device *dev)
+static void b43_ssb_remove(struct ssb_device *sdev)
{
- struct b43_wl *wl = ssb_get_devtypedata(dev);
- struct b43_wldev *wldev = ssb_get_drvdata(dev);
+ struct b43_wl *wl = ssb_get_devtypedata(sdev);
+ struct b43_wldev *wldev = ssb_get_drvdata(sdev);
/* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */
@@ -5042,17 +5365,25 @@ static void b43_ssb_remove(struct ssb_device *dev)
ieee80211_unregister_hw(wl->hw);
}
- b43_one_core_detach(dev);
+ b43_one_core_detach(wldev->dev);
if (list_empty(&wl->devlist)) {
b43_leds_unregister(wl);
/* Last core on the chip unregistered.
* We can destroy common struct b43_wl.
*/
- b43_wireless_exit(dev, wl);
+ b43_wireless_exit(wldev->dev, wl);
}
}
+static struct ssb_driver b43_ssb_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = b43_ssb_tbl,
+ .probe = b43_ssb_probe,
+ .remove = b43_ssb_remove,
+};
+#endif /* CONFIG_B43_SSB */
+
/* Perform a hardware reset. This can be called from any context. */
void b43_controller_restart(struct b43_wldev *dev, const char *reason)
{
@@ -5063,13 +5394,6 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
}
-static struct ssb_driver b43_ssb_driver = {
- .name = KBUILD_MODNAME,
- .id_table = b43_ssb_tbl,
- .probe = b43_ssb_probe,
- .remove = b43_ssb_remove,
-};
-
static void b43_print_driverinfo(void)
{
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
@@ -5108,14 +5432,27 @@ static int __init b43_init(void)
err = b43_sdio_init();
if (err)
goto err_pcmcia_exit;
- err = ssb_driver_register(&b43_ssb_driver);
+#ifdef CONFIG_B43_BCMA
+ err = bcma_driver_register(&b43_bcma_driver);
if (err)
goto err_sdio_exit;
+#endif
+#ifdef CONFIG_B43_SSB
+ err = ssb_driver_register(&b43_ssb_driver);
+ if (err)
+ goto err_bcma_driver_exit;
+#endif
b43_print_driverinfo();
return err;
+#ifdef CONFIG_B43_SSB
+err_bcma_driver_exit:
+#endif
+#ifdef CONFIG_B43_BCMA
+ bcma_driver_unregister(&b43_bcma_driver);
err_sdio_exit:
+#endif
b43_sdio_exit();
err_pcmcia_exit:
b43_pcmcia_exit();
@@ -5126,7 +5463,12 @@ err_dfs_exit:
static void __exit b43_exit(void)
{
+#ifdef CONFIG_B43_SSB
ssb_driver_unregister(&b43_ssb_driver);
+#endif
+#ifdef CONFIG_B43_BCMA
+ bcma_driver_unregister(&b43_bcma_driver);
+#endif
b43_sdio_exit();
b43_pcmcia_exit();
b43_debugfs_exit();
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index a0d327f13183..8c684cd33529 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mb@bu3sch.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -121,7 +121,7 @@ void b43_hf_write(struct b43_wldev *dev, u64 value);
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on);
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);
void b43_controller_restart(struct b43_wldev *dev, const char *reason);
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 2c8461dcf1b0..12b6b4067a39 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -2,7 +2,7 @@
Broadcom B43 wireless driver
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2007 Michael Buesch <m@bues.ch>
This 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/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index b01c8ced57c3..a6c38104693d 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -265,7 +265,6 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev)
void b43_phy_inita(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
/* This lowlevel A-PHY init is also called from G-PHY init.
@@ -296,9 +295,9 @@ void b43_phy_inita(struct b43_wldev *dev)
b43_radio_init2060(dev);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
- (bus->boardinfo.type == SSB_BOARD_BU4309))) {
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ ((dev->dev->board_type == SSB_BOARD_BU4306) ||
+ (dev->dev->board_type == SSB_BOARD_BU4309))) {
; //TODO: A PHY LO
}
@@ -311,7 +310,7 @@ void b43_phy_inita(struct b43_wldev *dev)
}
if ((phy->type == B43_PHYTYPE_G) &&
- (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+ (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {
b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
}
}
@@ -323,17 +322,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
struct b43_phy_a *aphy = phy->a;
s16 pab0, pab1, pab2;
- pab0 = (s16) (dev->sdev->bus->sprom.pa1b0);
- pab1 = (s16) (dev->sdev->bus->sprom.pa1b1);
- pab2 = (s16) (dev->sdev->bus->sprom.pa1b2);
+ pab0 = (s16) (dev->dev->bus_sprom->pa1b0);
+ pab1 = (s16) (dev->dev->bus_sprom->pa1b1);
+ pab2 = (s16) (dev->dev->bus_sprom->pa1b2);
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8) dev->sdev->bus->sprom.itssi_a != 0 &&
- (s8) dev->sdev->bus->sprom.itssi_a != -1)
+ if ((s8) dev->dev->bus_sprom->itssi_a != 0 &&
+ (s8) dev->dev->bus_sprom->itssi_a != -1)
aphy->tgt_idle_tssi =
- (s8) (dev->sdev->bus->sprom.itssi_a);
+ (s8) (dev->dev->bus_sprom->itssi_a);
else
aphy->tgt_idle_tssi = 62;
aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index e46b2f4f0920..07f009ff5ee2 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -31,6 +31,8 @@
#include "phy_a.h"
#include "phy_n.h"
#include "phy_lp.h"
+#include "phy_ht.h"
+#include "phy_lcn.h"
#include "b43.h"
#include "main.h"
@@ -59,6 +61,16 @@ int b43_phy_allocate(struct b43_wldev *dev)
phy->ops = &b43_phyops_lp;
#endif
break;
+ case B43_PHYTYPE_HT:
+#ifdef CONFIG_B43_PHY_HT
+ phy->ops = &b43_phyops_ht;
+#endif
+ break;
+ case B43_PHYTYPE_LCN:
+#ifdef CONFIG_B43_PHY_LCN
+ phy->ops = &b43_phyops_lcn;
+#endif
+ break;
}
if (B43_WARN_ON(!phy->ops))
return -ENODEV;
@@ -168,7 +180,7 @@ void b43_phy_lock(struct b43_wldev *dev)
B43_WARN_ON(dev->phy.phy_locked);
dev->phy.phy_locked = 1;
#endif
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
@@ -180,7 +192,7 @@ void b43_phy_unlock(struct b43_wldev *dev)
B43_WARN_ON(!dev->phy.phy_locked);
dev->phy.phy_locked = 0;
#endif
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, 0);
@@ -368,8 +380,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
/* The next check will be needed in two seconds, or later. */
phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
- if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306))
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type == SSB_BOARD_BU4306))
return; /* No software txpower adjustment needed */
result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 2401bee8b081..aa77ba612a92 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -194,6 +194,8 @@ struct b43_phy_a;
struct b43_phy_g;
struct b43_phy_n;
struct b43_phy_lp;
+struct b43_phy_ht;
+struct b43_phy_lcn;
struct b43_phy {
/* Hardware operation callbacks. */
@@ -216,6 +218,10 @@ struct b43_phy {
struct b43_phy_n *n;
/* LP-PHY specific information */
struct b43_phy_lp *lp;
+ /* HT-PHY specific information */
+ struct b43_phy_ht *ht;
+ /* LCN-PHY specific information */
+ struct b43_phy_lcn *lcn;
};
/* Band support flags. */
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 1758a282f913..8e157bc213f3 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev)
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
if (!phy->gmode ||
- !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
tmp16 = b43_nrssi_hw_read(dev, 0x20);
if (tmp16 >= 0x20)
tmp16 -= 0x40;
@@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
if (!phy->gmode)
return 0;
@@ -1491,7 +1491,6 @@ static u16 b43_radio_init2050(struct b43_wldev *dev)
static void b43_phy_initb5(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
u16 offset, value;
@@ -1500,8 +1499,8 @@ static void b43_phy_initb5(struct b43_wldev *dev)
if (phy->analog == 1) {
b43_radio_set(dev, 0x007A, 0x0050);
}
- if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type != SSB_BOARD_BU4306)) {
+ if ((dev->dev->board_vendor != SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type != SSB_BOARD_BU4306)) {
value = 0x2120;
for (offset = 0x00A8; offset < 0x00C7; offset++) {
b43_phy_write(dev, offset, value);
@@ -1620,7 +1619,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
b43_radio_write16(dev, 0x5A, 0x88);
b43_radio_write16(dev, 0x5B, 0x6B);
b43_radio_write16(dev, 0x5C, 0x0F);
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {
b43_radio_write16(dev, 0x5D, 0xFA);
b43_radio_write16(dev, 0x5E, 0xD8);
} else {
@@ -1787,7 +1786,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);
b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF);
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) {
if (phy->rev >= 7) {
b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);
b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000);
@@ -1922,7 +1921,6 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)
/* Initialize B/G PHY power control */
static void b43_phy_init_pctl(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
struct b43_rfatt old_rfatt;
@@ -1931,8 +1929,8 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306))
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type == SSB_BOARD_BU4306))
return;
b43_phy_write(dev, 0x0028, 0x8018);
@@ -2053,7 +2051,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
if (phy->rev >= 6) {
b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));
}
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
else
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
@@ -2066,7 +2064,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
}
- if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
/* The specs state to update the NRSSI LT with
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
@@ -2088,8 +2086,8 @@ static void b43_phy_initg(struct b43_wldev *dev)
/* FIXME: The spec says in the following if, the 0 should be replaced
'if OFDM may not be used in the current locale'
but OFDM is legal everywhere */
- if ((dev->sdev->bus->chip_id == 0x4306
- && dev->sdev->bus->chip_package == 2) || 0) {
+ if ((dev->dev->chip_id == 0x4306
+ && dev->dev->chip_pkg == 2) || 0) {
b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);
b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);
}
@@ -2105,7 +2103,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev,
b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
if (channel == 14) {
- if (dev->sdev->bus->sprom.country_code ==
+ if (dev->dev->bus_sprom->country_code ==
SSB_SPROM1CCODE_JAPAN)
b43_hf_write(dev,
b43_hf_read(dev) & ~B43_HF_ACPR);
@@ -2136,17 +2134,17 @@ static void default_baseband_attenuation(struct b43_wldev *dev,
static void default_radio_attenuation(struct b43_wldev *dev,
struct b43_rfatt *rf)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct b43_bus_dev *bdev = dev->dev;
struct b43_phy *phy = &dev->phy;
rf->with_padmix = 0;
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BCM4309G) {
- if (bus->boardinfo.rev < 0x43) {
+ if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+ dev->dev->board_type == SSB_BOARD_BCM4309G) {
+ if (dev->dev->board_rev < 0x43) {
rf->att = 2;
return;
- } else if (bus->boardinfo.rev < 0x51) {
+ } else if (dev->dev->board_rev < 0x51) {
rf->att = 3;
return;
}
@@ -2172,21 +2170,21 @@ static void default_radio_attenuation(struct b43_wldev *dev,
return;
case 1:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 3;
else
rf->att = 1;
} else {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 7;
else
rf->att = 6;
@@ -2194,16 +2192,16 @@ static void default_radio_attenuation(struct b43_wldev *dev,
return;
case 2:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 5;
- else if (bus->chip_id == 0x4320)
+ else if (bdev->chip_id == 0x4320)
rf->att = 4;
else
rf->att = 3;
@@ -2384,11 +2382,11 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
struct b43_phy_g *gphy = phy->g;
s16 pab0, pab1, pab2;
- pab0 = (s16) (dev->sdev->bus->sprom.pa0b0);
- pab1 = (s16) (dev->sdev->bus->sprom.pa0b1);
- pab2 = (s16) (dev->sdev->bus->sprom.pa0b2);
+ pab0 = (s16) (dev->dev->bus_sprom->pa0b0);
+ pab1 = (s16) (dev->dev->bus_sprom->pa0b1);
+ pab2 = (s16) (dev->dev->bus_sprom->pa0b2);
- B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) &&
+ B43_WARN_ON((dev->dev->chip_id == 0x4301) &&
(phy->radio_ver != 0x2050)); /* Not supported anymore */
gphy->dyn_tssi_tbl = 0;
@@ -2396,10 +2394,10 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 &&
- (s8) dev->sdev->bus->sprom.itssi_bg != -1) {
+ if ((s8) dev->dev->bus_sprom->itssi_bg != 0 &&
+ (s8) dev->dev->bus_sprom->itssi_bg != -1) {
gphy->tgt_idle_tssi =
- (s8) (dev->sdev->bus->sprom.itssi_bg);
+ (s8) (dev->dev->bus_sprom->itssi_bg);
} else
gphy->tgt_idle_tssi = 62;
gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
@@ -2537,7 +2535,7 @@ static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
b43_wireless_core_reset(dev, 0);
b43_phy_initg(dev);
phy->gmode = 1;
- b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
+ b43_wireless_core_reset(dev, 1);
}
return 0;
@@ -2840,7 +2838,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
B43_TXCTL_TXMIX;
rfatt += 2;
bbatt += 2;
- } else if (dev->sdev->bus->sprom.
+ } else if (dev->dev->bus_sprom->
boardflags_lo &
B43_BFL_PACTRL) {
bbatt += 4 * (rfatt - 2);
@@ -2914,14 +2912,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- max_pwr = dev->sdev->bus->sprom.maxpwr_bg;
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ max_pwr = dev->dev->bus_sprom->maxpwr_bg;
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
max_pwr -= 3; /* minus 0.75 */
if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {
b43warn(dev->wl,
"Invalid max-TX-power value in SPROM.\n");
max_pwr = INT_TO_Q52(20); /* fake it */
- dev->sdev->bus->sprom.maxpwr_bg = max_pwr;
+ dev->dev->bus_sprom->maxpwr_bg = max_pwr;
}
/* Get desired power (in Q5.2) */
@@ -3014,7 +3012,7 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI))
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))
return;
b43_mac_suspend(dev);
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
new file mode 100644
index 000000000000..7c40919651a7
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -0,0 +1,413 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n HT-PHY 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_ht.h"
+#include "tables_phy_ht.h"
+#include "radio_2059.h"
+#include "main.h"
+
+/**************************************************
+ * Radio 2059.
+ **************************************************/
+
+static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
+ const struct b43_phy_ht_channeltab_e_radio2059 *e)
+{
+ u8 i;
+ u16 routing;
+
+ b43_radio_write(dev, 0x16, e->radio_syn16);
+ b43_radio_write(dev, 0x17, e->radio_syn17);
+ b43_radio_write(dev, 0x22, e->radio_syn22);
+ b43_radio_write(dev, 0x25, e->radio_syn25);
+ b43_radio_write(dev, 0x27, e->radio_syn27);
+ b43_radio_write(dev, 0x28, e->radio_syn28);
+ b43_radio_write(dev, 0x29, e->radio_syn29);
+ b43_radio_write(dev, 0x2c, e->radio_syn2c);
+ b43_radio_write(dev, 0x2d, e->radio_syn2d);
+ b43_radio_write(dev, 0x37, e->radio_syn37);
+ b43_radio_write(dev, 0x41, e->radio_syn41);
+ b43_radio_write(dev, 0x43, e->radio_syn43);
+ b43_radio_write(dev, 0x47, e->radio_syn47);
+ b43_radio_write(dev, 0x4a, e->radio_syn4a);
+ b43_radio_write(dev, 0x58, e->radio_syn58);
+ b43_radio_write(dev, 0x5a, e->radio_syn5a);
+ b43_radio_write(dev, 0x6a, e->radio_syn6a);
+ b43_radio_write(dev, 0x6d, e->radio_syn6d);
+ b43_radio_write(dev, 0x6e, e->radio_syn6e);
+ b43_radio_write(dev, 0x92, e->radio_syn92);
+ b43_radio_write(dev, 0x98, e->radio_syn98);
+
+ for (i = 0; i < 2; i++) {
+ routing = i ? R2059_RXRX1 : R2059_TXRX0;
+ b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
+ b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
+ b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
+ b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
+ b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
+ b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
+ b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
+ b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
+ }
+
+ udelay(50);
+
+ /* Calibration */
+ b43_radio_mask(dev, 0x2b, ~0x1);
+ b43_radio_mask(dev, 0x2e, ~0x4);
+ b43_radio_set(dev, 0x2e, 0x4);
+ b43_radio_set(dev, 0x2b, 0x1);
+
+ udelay(300);
+}
+
+static void b43_radio_2059_init(struct b43_wldev *dev)
+{
+ const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
+ const u16 radio_values[3][2] = {
+ { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
+ };
+ u16 i, j;
+
+ b43_radio_write(dev, R2059_ALL | 0x51, 0x0070);
+ b43_radio_write(dev, R2059_ALL | 0x5a, 0x0003);
+
+ for (i = 0; i < ARRAY_SIZE(routing); i++)
+ b43_radio_set(dev, routing[i] | 0x146, 0x3);
+
+ b43_radio_set(dev, 0x2e, 0x0078);
+ b43_radio_set(dev, 0xc0, 0x0080);
+ msleep(2);
+ b43_radio_mask(dev, 0x2e, ~0x0078);
+ b43_radio_mask(dev, 0xc0, ~0x0080);
+
+ if (1) { /* FIXME */
+ b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
+ udelay(10);
+ b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
+ b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
+
+ b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
+ udelay(100);
+ b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
+
+ for (i = 0; i < 10000; i++) {
+ if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
+ i = 0;
+ break;
+ }
+ udelay(100);
+ }
+ if (i)
+ b43err(dev->wl, "radio 0x945 timeout\n");
+
+ b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
+ b43_radio_set(dev, 0xa, 0x60);
+
+ for (i = 0; i < 3; i++) {
+ b43_radio_write(dev, 0x17F, radio_values[i][0]);
+ b43_radio_write(dev, 0x13D, 0x6E);
+ b43_radio_write(dev, 0x13E, radio_values[i][1]);
+ b43_radio_write(dev, 0x13C, 0x55);
+
+ for (j = 0; j < 10000; j++) {
+ if (b43_radio_read(dev, 0x140) & 2) {
+ j = 0;
+ break;
+ }
+ udelay(500);
+ }
+ if (j)
+ b43err(dev->wl, "radio 0x140 timeout\n");
+
+ b43_radio_write(dev, 0x13C, 0x15);
+ }
+
+ b43_radio_mask(dev, 0x17F, ~0x1);
+ }
+
+ b43_radio_mask(dev, 0x11, ~0x0008);
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
+ const struct b43_phy_ht_channeltab_e_phy *e,
+ struct ieee80211_channel *new_channel)
+{
+ bool old_band_5ghz;
+ u8 i;
+
+ old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */
+ if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+ /* TODO */
+ } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+ /* TODO */
+ }
+
+ b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1);
+ b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2);
+ b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3);
+ b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4);
+ b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5);
+ b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6);
+
+ /* TODO: some ops on PHY regs 0x0B0 and 0xC0A */
+
+ /* TODO: separated function? */
+ for (i = 0; i < 3; i++) {
+ u16 mask;
+ u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8));
+
+ if (0) /* FIXME */
+ mask = 0x2 << (i * 4);
+ else
+ mask = 0;
+ b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask);
+
+ b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16);
+ b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)),
+ tmp & 0xFF);
+ b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)),
+ tmp & 0xFF);
+ }
+
+ b43_phy_write(dev, 0x017e, 0x3830);
+}
+
+static int b43_phy_ht_set_channel(struct b43_wldev *dev,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL;
+
+ if (phy->radio_ver == 0x2059) {
+ chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev,
+ channel->center_freq);
+ if (!chent_r2059)
+ return -ESRCH;
+ } else {
+ return -ESRCH;
+ }
+
+ /* TODO: In case of N-PHY some bandwidth switching goes here */
+
+ if (phy->radio_ver == 0x2059) {
+ b43_radio_2059_channel_setup(dev, chent_r2059);
+ b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs),
+ channel);
+ } else {
+ return -ESRCH;
+ }
+
+ return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_ht_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_ht *phy_ht;
+
+ phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL);
+ if (!phy_ht)
+ return -ENOMEM;
+ dev->phy.ht = phy_ht;
+
+ return 0;
+}
+
+static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_ht *phy_ht = phy->ht;
+
+ memset(phy_ht, 0, sizeof(*phy_ht));
+}
+
+static int b43_phy_ht_op_init(struct b43_wldev *dev)
+{
+ b43_phy_ht_tables_init(dev);
+
+ return 0;
+}
+
+static void b43_phy_ht_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_ht *phy_ht = phy->ht;
+
+ kfree(phy_ht);
+ phy->ht = NULL;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
+static void b43_phy_ht_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");
+
+ /* In the following PHY ops we copy wl's dummy behaviour.
+ * TODO: Find out if reads (currently hidden in masks/masksets) are
+ * needed and replace following ops with just writes or w&r.
+ * Note: B43_PHY_HT_RF_CTL1 register is tricky, wrong operation can
+ * cause delayed (!) machine lock up. */
+ if (blocked) {
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+ } else {
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x1);
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x2);
+
+ if (dev->phy.radio_ver == 0x2059)
+ b43_radio_2059_init(dev);
+ else
+ B43_WARN_ON(1);
+
+ b43_switch_channel(dev, dev->phy.channel);
+ }
+}
+
+static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+ if (on) {
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000);
+ } else {
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd);
+ }
+}
+
+static int b43_phy_ht_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_ht_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ return 11;
+ return 36;
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static u16 b43_phy_ht_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_ht_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_ht_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_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ /* HT-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_ht_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);
+}
+
+static enum b43_txpwr_result
+b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+ return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
+/**************************************************
+ * PHY ops struct.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_ht = {
+ .allocate = b43_phy_ht_op_allocate,
+ .free = b43_phy_ht_op_free,
+ .prepare_structs = b43_phy_ht_op_prepare_structs,
+ .init = b43_phy_ht_op_init,
+ .phy_read = b43_phy_ht_op_read,
+ .phy_write = b43_phy_ht_op_write,
+ .phy_maskset = b43_phy_ht_op_maskset,
+ .radio_read = b43_phy_ht_op_radio_read,
+ .radio_write = b43_phy_ht_op_radio_write,
+ .software_rfkill = b43_phy_ht_op_software_rfkill,
+ .switch_analog = b43_phy_ht_op_switch_analog,
+ .switch_channel = b43_phy_ht_op_switch_channel,
+ .get_default_chan = b43_phy_ht_op_get_default_chan,
+ .recalc_txpower = b43_phy_ht_op_recalc_txpower,
+ .adjust_txpower = b43_phy_ht_op_adjust_txpower,
+};
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
new file mode 100644
index 000000000000..7ad7affc8df0
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -0,0 +1,46 @@
+#ifndef B43_PHY_HT_H_
+#define B43_PHY_HT_H_
+
+#include "phy_common.h"
+
+
+#define B43_PHY_HT_BANDCTL 0x009 /* Band control */
+#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 */
+#define B43_PHY_HT_BW1 0x1CE
+#define B43_PHY_HT_BW2 0x1CF
+#define B43_PHY_HT_BW3 0x1D0
+#define B43_PHY_HT_BW4 0x1D1
+#define B43_PHY_HT_BW5 0x1D2
+#define B43_PHY_HT_BW6 0x1D3
+
+#define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010)
+
+#define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110)
+#define B43_PHY_HT_AFE_CTL2 B43_PHY_EXTG(0x111)
+#define B43_PHY_HT_AFE_CTL3 B43_PHY_EXTG(0x114)
+#define B43_PHY_HT_AFE_CTL4 B43_PHY_EXTG(0x115)
+#define B43_PHY_HT_AFE_CTL5 B43_PHY_EXTG(0x118)
+#define B43_PHY_HT_AFE_CTL6 B43_PHY_EXTG(0x119)
+
+
+/* Values for PHY registers used on channel switching */
+struct b43_phy_ht_channeltab_e_phy {
+ u16 bw1;
+ u16 bw2;
+ u16 bw3;
+ u16 bw4;
+ u16 bw5;
+ u16 bw6;
+};
+
+
+struct b43_phy_ht {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_ht;
+
+#endif /* B43_PHY_HT_H_ */
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
new file mode 100644
index 000000000000..9f7dbbd5ced6
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -0,0 +1,52 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n LCN-PHY 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_lcn.h"
+#include "tables_phy_lcn.h"
+#include "main.h"
+
+/**************************************************
+ * 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,
+ .init = b43_phy_lcn_op_init,
+ .phy_read = b43_phy_lcn_op_read,
+ .phy_write = b43_phy_lcn_op_write,
+ .phy_maskset = b43_phy_lcn_op_maskset,
+ .radio_read = b43_phy_lcn_op_radio_read,
+ .radio_write = b43_phy_lcn_op_radio_write,
+ .software_rfkill = b43_phy_lcn_op_software_rfkill,
+ .switch_analog = b43_phy_lcn_op_switch_analog,
+ .switch_channel = b43_phy_lcn_op_switch_channel,
+ .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
new file mode 100644
index 000000000000..c046c2a6cab4
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -0,0 +1,14 @@
+#ifndef B43_PHY_LCN_H_
+#define B43_PHY_LCN_H_
+
+#include "phy_common.h"
+
+
+struct b43_phy_lcn {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_lcn;
+
+#endif /* B43_PHY_LCN_H_ */ \ No newline at end of file
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 012c8da2f944..f93d66b1817b 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11a/g LP-PHY driver
- Copyright (c) 2008-2009 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008-2009 Michael Buesch <m@bues.ch>
Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
This program is free software; you can redistribute it and/or modify
@@ -85,39 +85,39 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
static void lpphy_read_band_sprom(struct b43_wldev *dev)
{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
u16 cckpo, maxpwr;
u32 ofdmpo;
int i;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- lpphy->tx_isolation_med_band = bus->sprom.tri2g;
- lpphy->bx_arch = bus->sprom.bxa2g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo2g;
- lpphy->rssi_vf = bus->sprom.rssismf2g;
- lpphy->rssi_vc = bus->sprom.rssismc2g;
- lpphy->rssi_gs = bus->sprom.rssisav2g;
- lpphy->txpa[0] = bus->sprom.pa0b0;
- lpphy->txpa[1] = bus->sprom.pa0b1;
- lpphy->txpa[2] = bus->sprom.pa0b2;
- maxpwr = bus->sprom.maxpwr_bg;
+ lpphy->tx_isolation_med_band = sprom->tri2g;
+ lpphy->bx_arch = sprom->bxa2g;
+ lpphy->rx_pwr_offset = sprom->rxpo2g;
+ lpphy->rssi_vf = sprom->rssismf2g;
+ lpphy->rssi_vc = sprom->rssismc2g;
+ lpphy->rssi_gs = sprom->rssisav2g;
+ lpphy->txpa[0] = sprom->pa0b0;
+ lpphy->txpa[1] = sprom->pa0b1;
+ lpphy->txpa[2] = sprom->pa0b2;
+ maxpwr = sprom->maxpwr_bg;
lpphy->max_tx_pwr_med_band = maxpwr;
- cckpo = bus->sprom.cck2gpo;
+ cckpo = sprom->cck2gpo;
/*
* We don't read SPROM's opo as specs say. On rev8 SPROMs
* opo == ofdm2gpo and we don't know any SSB with LP-PHY
* and SPROM rev below 8.
*/
- B43_WARN_ON(bus->sprom.revision < 8);
- ofdmpo = bus->sprom.ofdm2gpo;
+ B43_WARN_ON(sprom->revision < 8);
+ ofdmpo = sprom->ofdm2gpo;
if (cckpo) {
for (i = 0; i < 4; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- ofdmpo = bus->sprom.ofdm2gpo;
+ ofdmpo = sprom->ofdm2gpo;
for (i = 4; i < 15; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
@@ -131,39 +131,39 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
}
} else { /* 5GHz */
- lpphy->tx_isolation_low_band = bus->sprom.tri5gl;
- lpphy->tx_isolation_med_band = bus->sprom.tri5g;
- lpphy->tx_isolation_hi_band = bus->sprom.tri5gh;
- lpphy->bx_arch = bus->sprom.bxa5g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo5g;
- lpphy->rssi_vf = bus->sprom.rssismf5g;
- lpphy->rssi_vc = bus->sprom.rssismc5g;
- lpphy->rssi_gs = bus->sprom.rssisav5g;
- lpphy->txpa[0] = bus->sprom.pa1b0;
- lpphy->txpa[1] = bus->sprom.pa1b1;
- lpphy->txpa[2] = bus->sprom.pa1b2;
- lpphy->txpal[0] = bus->sprom.pa1lob0;
- lpphy->txpal[1] = bus->sprom.pa1lob1;
- lpphy->txpal[2] = bus->sprom.pa1lob2;
- lpphy->txpah[0] = bus->sprom.pa1hib0;
- lpphy->txpah[1] = bus->sprom.pa1hib1;
- lpphy->txpah[2] = bus->sprom.pa1hib2;
- maxpwr = bus->sprom.maxpwr_al;
- ofdmpo = bus->sprom.ofdm5glpo;
+ lpphy->tx_isolation_low_band = sprom->tri5gl;
+ lpphy->tx_isolation_med_band = sprom->tri5g;
+ lpphy->tx_isolation_hi_band = sprom->tri5gh;
+ lpphy->bx_arch = sprom->bxa5g;
+ lpphy->rx_pwr_offset = sprom->rxpo5g;
+ lpphy->rssi_vf = sprom->rssismf5g;
+ lpphy->rssi_vc = sprom->rssismc5g;
+ lpphy->rssi_gs = sprom->rssisav5g;
+ lpphy->txpa[0] = sprom->pa1b0;
+ lpphy->txpa[1] = sprom->pa1b1;
+ lpphy->txpa[2] = sprom->pa1b2;
+ lpphy->txpal[0] = sprom->pa1lob0;
+ lpphy->txpal[1] = sprom->pa1lob1;
+ lpphy->txpal[2] = sprom->pa1lob2;
+ lpphy->txpah[0] = sprom->pa1hib0;
+ lpphy->txpah[1] = sprom->pa1hib1;
+ lpphy->txpah[2] = sprom->pa1hib2;
+ maxpwr = sprom->maxpwr_al;
+ ofdmpo = sprom->ofdm5glpo;
lpphy->max_tx_pwr_low_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- maxpwr = bus->sprom.maxpwr_a;
- ofdmpo = bus->sprom.ofdm5gpo;
+ maxpwr = sprom->maxpwr_a;
+ ofdmpo = sprom->ofdm5gpo;
lpphy->max_tx_pwr_med_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- maxpwr = bus->sprom.maxpwr_ah;
- ofdmpo = bus->sprom.ofdm5ghpo;
+ maxpwr = sprom->maxpwr_ah;
+ ofdmpo = sprom->ofdm5ghpo;
lpphy->max_tx_pwr_hi_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
@@ -214,7 +214,8 @@ static void lpphy_table_init(struct b43_wldev *dev)
static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy_lp *lpphy = dev->phy.lp;
u16 tmp, tmp2;
@@ -242,9 +243,9 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,
0xFF00, lpphy->rx_pwr_offset);
- if ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
+ if ((sprom->boardflags_lo & B43_BFL_FEM) &&
((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
+ (sprom->boardflags_hi & B43_BFH_PAREF))) {
ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
ssb_pmu_set_ldo_paref(&bus->chipco, true);
if (dev->phy.rev == 0) {
@@ -260,7 +261,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
}
tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
- if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV)
+ if (sprom->boardflags_hi & B43_BFH_RSSIINV)
b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);
else
b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA);
@@ -268,7 +269,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
0xFFF9, (lpphy->bx_arch << 1));
if (dev->phy.rev == 1 &&
- (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) {
+ (sprom->boardflags_hi & B43_BFH_FEM_BT)) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
@@ -286,8 +287,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
- (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) &&
- (bus->sprom.boardflags_lo & B43_BFL_FEM))) {
+ (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
+ (sprom->boardflags_lo & B43_BFL_FEM))) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
@@ -297,7 +298,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
} else if (dev->phy.rev == 1 ||
- (bus->sprom.boardflags_lo & B43_BFL_FEM)) {
+ (sprom->boardflags_lo & B43_BFL_FEM)) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
@@ -316,15 +317,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
}
- if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) {
+ if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
}
- if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) &&
- (bus->chip_id == 0x5354) &&
- (bus->chip_package == SSB_CHIPPACK_BCM4712S)) {
+ if ((sprom->boardflags_hi & B43_BFH_FEM_BT) &&
+ (dev->dev->chip_id == 0x5354) &&
+ (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {
b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
@@ -412,7 +413,6 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy_lp *lpphy = dev->phy.lp;
b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
@@ -432,7 +432,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
- if (bus->boardinfo.rev >= 0x18) {
+ if (dev->dev->board_rev >= 0x18) {
b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
} else {
@@ -449,7 +449,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);
b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);
b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);
} else {
@@ -467,7 +467,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
}
@@ -492,7 +492,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
0x2000 | ((u16)lpphy->rssi_gs << 10) |
((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
@@ -519,7 +519,7 @@ struct b2062_freqdata {
static void lpphy_2062_init(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
u32 crystalfreq, tmp, ref;
unsigned int i;
const struct b2062_freqdata *fd = NULL;
@@ -697,7 +697,7 @@ static void lpphy_radio_init(struct b43_wldev *dev)
lpphy_sync_stx(dev);
b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
- if (dev->sdev->bus->chip_id == 0x4325) {
+ if (dev->dev->chip_id == 0x4325) {
// TODO SSB PMU recalibration
}
}
@@ -1289,7 +1289,7 @@ finish:
static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
int i;
@@ -1840,7 +1840,6 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
struct lpphy_tx_gains gains, oldgains;
int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
@@ -1854,7 +1853,7 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
- if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
+ if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0)
lpphy_papd_cal(dev, gains, 0, 1, 30);
else
lpphy_papd_cal(dev, gains, 0, 1, 65);
@@ -1870,7 +1869,6 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
bool rx, bool pa, struct lpphy_tx_gains *gains)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
const struct lpphy_rx_iq_comp *iqcomp = NULL;
struct lpphy_tx_gains nogains, oldgains;
u16 tmp;
@@ -1879,7 +1877,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
memset(&nogains, 0, sizeof(nogains));
memset(&oldgains, 0, sizeof(oldgains));
- if (bus->chip_id == 0x5354) {
+ if (dev->dev->chip_id == 0x5354) {
for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
iqcomp = &lpphy_5354_iq_table[i];
@@ -2408,11 +2406,9 @@ static const struct b206x_channel b2063_chantbl[] = {
static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
-
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
udelay(20);
- if (bus->chip_id == 0x5354) {
+ if (dev->dev->chip_id == 0x5354) {
b43_radio_write(dev, B2062_N_COMM1, 4);
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
} else {
@@ -2432,7 +2428,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
unsigned int channel)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
const struct b206x_channel *chandata = NULL;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
@@ -2522,7 +2518,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
static int lpphy_b2063_tune(struct b43_wldev *dev,
unsigned int channel)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
static const struct b206x_channel *chandata = NULL;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
@@ -2670,6 +2666,11 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
{
int err;
+ if (dev->dev->bus_type != B43_BUS_SSB) {
+ b43err(dev->wl, "LP-PHY is supported only on SSB!\n");
+ return -EOPNOTSUPP;
+ }
+
lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
lpphy_baseband_init(dev);
lpphy_radio_init(dev);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 05960ddde24e..3b46360da99b 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY support
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008 Michael Buesch <m@bues.ch>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -299,7 +299,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u8 txpi[2], bbmult, i;
u16 tmp, radio_gain, dac_gain;
@@ -423,16 +423,15 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev)
static void b43_radio_init2055_post(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
- struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
int i;
u16 val;
bool workaround = false;
if (sprom->revision < 4)
- workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM &&
- binfo->type == 0x46D &&
- binfo->rev >= 0x41);
+ workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
+ && dev->dev->board_type == 0x46D
+ && dev->dev->board_rev >= 0x41);
else
workaround =
!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
@@ -604,17 +603,33 @@ 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 tmslow;
+ u32 tmp;
if (dev->phy.type != B43_PHYTYPE_N)
return;
- tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
- if (force)
- tmslow |= SSB_TMSLOW_FGC;
- else
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+ 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 */
@@ -959,8 +974,21 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
- ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00,
- 0xFC00);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
+ 0xFC00, 0xFC00);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
+ 0xFC00, 0xFC00);
+ break;
+#endif
+ }
+
b43_write32(dev, B43_MMIO_MACCTL,
b43_read32(dev, B43_MMIO_MACCTL) &
~B43_MACCTL_GPOUTSMSK);
@@ -983,7 +1011,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
{
u16 tmp;
- if (dev->sdev->id.revision == 16)
+ if (dev->dev->core_rev == 16)
b43_mac_suspend(dev);
tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
@@ -993,7 +1021,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
tmp |= (val & mask);
b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
- if (dev->sdev->id.revision == 16)
+ if (dev->dev->core_rev == 16)
b43_mac_enable(dev);
return tmp;
@@ -1168,7 +1196,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
/* PHY rev 0, 1, 2 */
u8 i, j;
@@ -1373,7 +1401,7 @@ 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)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
@@ -1443,9 +1471,9 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
- if ((bus->sprom.boardflags2_lo & B43_BFL2_APLL_WAR &&
+ if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (bus->sprom.boardflags2_lo & B43_BFL2_GPLL_WAR &&
+ (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
tmp32 = 0x00088888;
else
@@ -1503,8 +1531,8 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
- if (bus->sprom.boardflags2_lo & 0x100 &&
- bus->boardinfo.type == 0x8B) {
+ if (sprom->boardflags2_lo & 0x100 &&
+ dev->dev->board_type == 0x8B) {
delays1[0] = 0x1;
delays1[5] = 0x14;
}
@@ -3586,7 +3614,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
*/
int b43_phy_initn(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
u8 tx_pwr_state;
@@ -3599,9 +3627,22 @@ int b43_phy_initn(struct b43_wldev *dev)
bool do_cal = false;
if ((dev->phy.rev >= 3) &&
- (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
- chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
+ BCMA_CC_CHIPCTL, 0x40);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ chipco_set32(&dev->dev->sdev->bus->chipco,
+ SSB_CHIPCO_CHIPCTL, 0x40);
+ break;
+#endif
+ }
}
nphy->deaf_count = 0;
b43_nphy_tables_init(dev);
@@ -3639,9 +3680,9 @@ 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 (bus->sprom.boardflags2_lo & 0x100 ||
- (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
- bus->boardinfo.type == 0x8B))
+ if (sprom->boardflags2_lo & 0x100 ||
+ (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
+ dev->dev->board_type == 0x8B))
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
else
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
@@ -4026,11 +4067,24 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
{
- u16 val = on ? 0 : 0x7FFF;
+ u16 override = on ? 0x0 : 0x7FFF;
+ u16 core = on ? 0xD : 0x00FD;
- if (dev->phy.rev >= 3)
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val);
+ if (dev->phy.rev >= 3) {
+ if (on) {
+ b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ } else {
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+ }
+ } else {
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ }
}
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 72ab94df7569..6e4228c3ed1b 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -4,7 +4,7 @@
PIO data transfer
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
B43_MMIO_PIO11_BASE5,
};
- if (dev->sdev->id.revision >= 11) {
+ if (dev->dev->core_rev >= 11) {
B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
return bases_rev11[index];
}
@@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
static u16 pio_txqueue_offset(struct b43_wldev *dev)
{
- if (dev->sdev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x18;
return 0;
}
static u16 pio_rxqueue_offset(struct b43_wldev *dev)
{
- if (dev->sdev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x38;
return 8;
}
@@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->sdev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_txqueue_offset(dev);
q->index = index;
@@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->sdev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_rxqueue_offset(dev);
diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c
index 44c6dea66882..93643f18c2b3 100644
--- a/drivers/net/wireless/b43/radio_2055.c
+++ b/drivers/net/wireless/b43/radio_2055.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY and radio device data tables
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008 Michael Buesch <m@bues.ch>
This 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_2055.h b/drivers/net/wireless/b43/radio_2055.h
index d9bfa0f21b72..67f96122f8d8 100644
--- a/drivers/net/wireless/b43/radio_2055.h
+++ b/drivers/net/wireless/b43/radio_2055.h
@@ -251,4 +251,9 @@ struct b43_nphy_channeltab_entry_rev2 {
void b2055_upload_inittab(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+
#endif /* B43_RADIO_2055_H_ */
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
index d601f6e7e313..d52df6be705a 100644
--- a/drivers/net/wireless/b43/radio_2056.h
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -1117,4 +1117,9 @@ struct b43_nphy_channeltab_entry_rev3 {
void b2056_upload_inittabs(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
+
#endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
new file mode 100644
index 000000000000..f029f6e1f5d1
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -0,0 +1,174 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n 2059 radio device data tables
+
+ This program is free software; you can redistribute it and/or modify
+ 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.
+
+*/
+
+#include "b43.h"
+#include "radio_2059.h"
+
+#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+ r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+ r20, r21, r22, r23, r24, r25, r26, r27, r28) \
+ .radio_syn16 = r00, \
+ .radio_syn17 = r01, \
+ .radio_syn22 = r02, \
+ .radio_syn25 = r03, \
+ .radio_syn27 = r04, \
+ .radio_syn28 = r05, \
+ .radio_syn29 = r06, \
+ .radio_syn2c = r07, \
+ .radio_syn2d = r08, \
+ .radio_syn37 = r09, \
+ .radio_syn41 = r10, \
+ .radio_syn43 = r11, \
+ .radio_syn47 = r12, \
+ .radio_syn4a = r13, \
+ .radio_syn58 = r14, \
+ .radio_syn5a = r15, \
+ .radio_syn6a = r16, \
+ .radio_syn6d = r17, \
+ .radio_syn6e = r18, \
+ .radio_syn92 = r19, \
+ .radio_syn98 = r20, \
+ .radio_rxtx4a = r21, \
+ .radio_rxtx58 = r22, \
+ .radio_rxtx5a = r23, \
+ .radio_rxtx6a = r24, \
+ .radio_rxtx6d = r25, \
+ .radio_rxtx6e = r26, \
+ .radio_rxtx92 = r27, \
+ .radio_rxtx98 = r28
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5) \
+ .phy_regs.bw1 = r0, \
+ .phy_regs.bw2 = r1, \
+ .phy_regs.bw3 = r2, \
+ .phy_regs.bw4 = r3, \
+ .phy_regs.bw5 = r4, \
+ .phy_regs.bw6 = r5
+
+static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = {
+ { .freq = 2412,
+ RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+ },
+ { .freq = 2417,
+ RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+ },
+ { .freq = 2422,
+ RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+ },
+ { .freq = 2427,
+ RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+ },
+ { .freq = 2432,
+ RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+ },
+ { .freq = 2437,
+ RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+ },
+ { .freq = 2442,
+ RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+ },
+ { .freq = 2447,
+ RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+ },
+ { .freq = 2452,
+ RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+ },
+ { .freq = 2457,
+ RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+ },
+ { .freq = 2462,
+ RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+ },
+ { .freq = 2467,
+ RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+ 0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+ },
+ { .freq = 2472,
+ RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+ 0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+ },
+};
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq)
+{
+ const struct b43_phy_ht_channeltab_e_radio2059 *e;
+ unsigned int i;
+
+ e = b43_phy_ht_channeltab_radio2059;
+ for (i = 0; i < ARRAY_SIZE(b43_phy_ht_channeltab_radio2059); i++, e++) {
+ if (e->freq == freq)
+ return e;
+ }
+
+ return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h
new file mode 100644
index 000000000000..e4d69e55e9fe
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.h
@@ -0,0 +1,54 @@
+#ifndef B43_RADIO_2059_H_
+#define B43_RADIO_2059_H_
+
+#include <linux/types.h>
+
+#include "phy_ht.h"
+
+#define R2059_SYN 0x000
+#define R2059_TXRX0 0x400
+#define R2059_RXRX1 0x800
+#define R2059_ALL 0xC00
+
+/* Values for various registers uploaded on channel switching */
+struct b43_phy_ht_channeltab_e_radio2059 {
+ /* The channel frequency in MHz */
+ u16 freq;
+ /* Values for radio registers */
+ u8 radio_syn16;
+ u8 radio_syn17;
+ u8 radio_syn22;
+ u8 radio_syn25;
+ u8 radio_syn27;
+ u8 radio_syn28;
+ u8 radio_syn29;
+ u8 radio_syn2c;
+ u8 radio_syn2d;
+ u8 radio_syn37;
+ u8 radio_syn41;
+ u8 radio_syn43;
+ u8 radio_syn47;
+ u8 radio_syn4a;
+ u8 radio_syn58;
+ u8 radio_syn5a;
+ u8 radio_syn6a;
+ u8 radio_syn6d;
+ u8 radio_syn6e;
+ u8 radio_syn92;
+ u8 radio_syn98;
+ u8 radio_rxtx4a;
+ u8 radio_rxtx58;
+ u8 radio_rxtx5a;
+ u8 radio_rxtx6a;
+ u8 radio_rxtx6d;
+ u8 radio_rxtx6e;
+ u8 radio_rxtx92;
+ u8 radio_rxtx98;
+ /* Values for PHY registers */
+ struct b43_phy_ht_channeltab_e_phy phy_regs;
+};
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq);
+
+#endif /* B43_RADIO_2059_H_ */
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index a617efe38289..70c2fcedd1bb 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
RFKILL support
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2007 Michael Buesch <m@bues.ch>
This 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,17 +37,16 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
- struct ssb_bus *bus = dev->sdev->bus;
bool enabled;
bool brought_up = false;
mutex_lock(&wl->mutex);
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
- if (ssb_bus_powerup(bus, 0)) {
+ if (b43_bus_powerup(dev, 0)) {
mutex_unlock(&wl->mutex);
return;
}
- ssb_device_enable(dev->sdev, 0);
+ b43_device_enable(dev, 0);
brought_up = true;
}
@@ -63,8 +62,8 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
}
if (brought_up) {
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
}
mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
index 808e25b79703..80b0755ed3af 100644
--- a/drivers/net/wireless/b43/sdio.c
+++ b/drivers/net/wireless/b43/sdio.c
@@ -4,7 +4,7 @@
* SDIO over Sonics Silicon Backplane bus glue for b43.
*
* Copyright (C) 2009 Albert Herranz
- * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2009 Michael Buesch <m@bues.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
int err;
@@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev,
void b43_sdio_free_irq(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
@@ -93,8 +93,8 @@ void b43_sdio_free_irq(struct b43_wldev *dev)
sdio->irq_handler = NULL;
}
-static int b43_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
+static int __devinit b43_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
{
struct b43_sdio *sdio;
struct sdio_func_tuple *tuple;
@@ -171,7 +171,7 @@ out:
return error;
}
-static void b43_sdio_remove(struct sdio_func *func)
+static void __devexit b43_sdio_remove(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index 57af619725c3..8e8431d4eb0c 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -4,7 +4,7 @@
SYSFS support routines
- Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2006 Michael Buesch <m@bues.ch>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -140,7 +140,7 @@ static DEVICE_ATTR(interference, 0644,
int b43_sysfs_register(struct b43_wldev *wldev)
{
- struct device *dev = wldev->sdev->dev;
+ struct device *dev = wldev->dev->dev;
B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
@@ -149,7 +149,7 @@ int b43_sysfs_register(struct b43_wldev *wldev)
void b43_sysfs_unregister(struct b43_wldev *wldev)
{
- struct device *dev = wldev->sdev->dev;
+ struct device *dev = wldev->dev->dev;
device_remove_file(dev, &dev_attr_interference);
}
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
index 1ef9a6463ec6..ea288df8aee9 100644
--- a/drivers/net/wireless/b43/tables.c
+++ b/drivers/net/wireless/b43/tables.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2006, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2006, 2006 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 59df3c64af63..cff187c5616d 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11a/g LP-PHY and radio device data tables
- Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2009 Michael Buesch <m@bues.ch>
Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
This program is free software; you can redistribute it and/or modify
@@ -2304,7 +2304,6 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
void lpphy_rev2plus_table_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
int i;
B43_WARN_ON(dev->phy.rev < 2);
@@ -2341,7 +2340,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);
b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
@@ -2416,12 +2415,12 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
void lpphy_init_tx_gain_table(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
switch (dev->phy.rev) {
case 0:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+ (sprom->boardflags_lo & B43_BFL_HGPA))
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev0_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2432,8 +2431,8 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
lpphy_rev0_5ghz_tx_gain_table);
break;
case 1:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+ (sprom->boardflags_lo & B43_BFL_HGPA))
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev1_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2444,7 +2443,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
lpphy_rev1_5ghz_tx_gain_table);
break;
default:
- if (bus->sprom.boardflags_hi & B43_BFH_NOPA)
+ if (sprom->boardflags_hi & B43_BFH_NOPA)
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev2_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 2de483b3d3ba..916f238a71df 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY data tables
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2008 Michael Buesch <m@bues.ch>
This 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_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 18569367ce43..a81696bff0ed 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -60,16 +60,8 @@ struct nphy_gain_ctl_workaround_entry {
struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
struct b43_wldev *dev, bool ghz5, bool ext_lna);
-/* Get the NPHY Channel Switch Table entry for a channel.
- * Returns NULL on failure to find an entry. */
-const struct b43_nphy_channeltab_entry_rev2 *
-b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
-const struct b43_nphy_channeltab_entry_rev3 *
-b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
-
/* The N-PHY tables. */
-
#define B43_NTAB_TYPEMASK 0xF0000000
#define B43_NTAB_8BIT 0x10000000
#define B43_NTAB_16BIT 0x20000000
diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c
new file mode 100644
index 000000000000..603938657b15
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.c
@@ -0,0 +1,750 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n HT-PHY data tables
+
+ This program is free software; you can redistribute it and/or modify
+ 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.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_ht.h"
+#include "phy_common.h"
+#include "phy_ht.h"
+
+static const u16 b43_httab_0x12[] = {
+ 0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
+ 0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
+ 0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
+ 0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
+ 0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
+ 0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
+ 0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
+ 0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
+ 0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
+ 0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
+ 0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
+ 0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
+ 0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
+ 0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
+ 0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
+ 0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
+ 0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007,
+};
+
+static const u16 b43_httab_0x27[] = {
+ 0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+ 0x001d, 0x0020, 0x0009, 0x000e, 0x0011, 0x0014,
+ 0x0017, 0x001a, 0x001d, 0x0020, 0x0009, 0x000e,
+ 0x0011, 0x0014, 0x0017, 0x001a, 0x001d, 0x0020,
+ 0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+ 0x001d, 0x0020,
+};
+
+static const u16 b43_httab_0x26[] = {
+ 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, 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_httab_0x25[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x2f[] = {
+ 0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f,
+ 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+ 0x0001581f, 0x0001581f, 0x0001581f, 0x00035700,
+ 0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f,
+ 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+ 0x0001581f, 0x0001581f,
+};
+
+static const u16 b43_httab_0x1a[] = {
+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+ 0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1b[] = {
+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+ 0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1c[] = {
+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+ 0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u32 b43_httab_0x1a_0xc0[] = {
+ 0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+ 0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+ 0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+ 0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+ 0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+ 0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+ 0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+ 0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+ 0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+ 0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+ 0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+ 0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+ 0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+ 0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+ 0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+ 0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+ 0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+ 0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+ 0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+ 0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+ 0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+ 0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+ 0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+ 0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+ 0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+ 0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+ 0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+ 0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+ 0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+ 0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+ 0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+ 0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_httab_0x1a_0x140[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1b_0x140[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1c_0x140[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 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_httab_0x1a_0x1c0[] = {
+ 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, 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 u16 b43_httab_0x1b_0x1c0[] = {
+ 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, 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 u16 b43_httab_0x1c_0x1c0[] = {
+ 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, 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 u16 b43_httab_0x1a_0x240[] = {
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1b_0x240[] = {
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1c_0x240[] = {
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6,
+};
+
+static const u32 b43_httab_0x1f[] = {
+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x21[] = {
+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x23[] = {
+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x20[] = {
+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x22[] = {
+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x24[] = {
+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+u32 b43_httab_read(struct b43_wldev *dev, u32 offset)
+{
+ u32 type, value;
+
+ type = offset & B43_HTTAB_TYPEMASK;
+ offset &= ~B43_HTTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+ break;
+ case B43_HTTAB_16BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ break;
+ case B43_HTTAB_32BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+ value <<= 16;
+ value |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ break;
+ default:
+ B43_WARN_ON(1);
+ value = 0;
+ }
+
+ return value;
+}
+
+void b43_httab_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_HTTAB_TYPEMASK;
+ offset &= ~B43_HTTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+ for (i = 0; i < nr_elements; i++) {
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ *data = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+ data++;
+ break;
+ case B43_HTTAB_16BIT:
+ *((u16 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ data += 2;
+ break;
+ case B43_HTTAB_32BIT:
+ *((u32 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+ *((u32 *)data) <<= 16;
+ *((u32 *)data) |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ data += 4;
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ }
+}
+
+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+ u32 type;
+
+ type = offset & B43_HTTAB_TYPEMASK;
+ offset &= 0xFFFF;
+
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ break;
+ case B43_HTTAB_16BIT:
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ 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);
+ 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);
+ }
+
+ return;
+}
+
+void b43_httab_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_HTTAB_TYPEMASK;
+ offset &= ~B43_HTTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+ for (i = 0; i < nr_elements; i++) {
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ value = *data;
+ data++;
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ break;
+ case B43_HTTAB_16BIT:
+ value = *((u16 *)data);
+ data += 2;
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ break;
+ case B43_HTTAB_32BIT:
+ value = *((u32 *)data);
+ data += 4;
+ 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);
+ }
+ }
+}
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+#define httab_upload(dev, offset, data) do { \
+ b43_httab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+ } while (0)
+void b43_phy_ht_tables_init(struct b43_wldev *dev)
+{
+ 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);
+ httab_upload(dev, B43_HTTAB32(0x25, 0), b43_httab_0x25);
+ httab_upload(dev, B43_HTTAB32(0x2f, 0), b43_httab_0x2f);
+ httab_upload(dev, B43_HTTAB16(0x1a, 0), b43_httab_0x1a);
+ httab_upload(dev, B43_HTTAB16(0x1b, 0), b43_httab_0x1b);
+ httab_upload(dev, B43_HTTAB16(0x1c, 0), b43_httab_0x1c);
+ httab_upload(dev, B43_HTTAB32(0x1a, 0x0c0), b43_httab_0x1a_0xc0);
+ httab_upload(dev, B43_HTTAB32(0x1a, 0x140), b43_httab_0x1a_0x140);
+ httab_upload(dev, B43_HTTAB32(0x1b, 0x140), b43_httab_0x1b_0x140);
+ httab_upload(dev, B43_HTTAB32(0x1c, 0x140), b43_httab_0x1c_0x140);
+ httab_upload(dev, B43_HTTAB16(0x1a, 0x1c0), b43_httab_0x1a_0x1c0);
+ httab_upload(dev, B43_HTTAB16(0x1b, 0x1c0), b43_httab_0x1b_0x1c0);
+ httab_upload(dev, B43_HTTAB16(0x1c, 0x1c0), b43_httab_0x1c_0x1c0);
+ httab_upload(dev, B43_HTTAB16(0x1a, 0x240), b43_httab_0x1a_0x240);
+ httab_upload(dev, B43_HTTAB16(0x1b, 0x240), b43_httab_0x1b_0x240);
+ httab_upload(dev, B43_HTTAB16(0x1c, 0x240), b43_httab_0x1c_0x240);
+ httab_upload(dev, B43_HTTAB32(0x1f, 0), b43_httab_0x1f);
+ httab_upload(dev, B43_HTTAB32(0x21, 0), b43_httab_0x21);
+ httab_upload(dev, B43_HTTAB32(0x23, 0), b43_httab_0x23);
+ httab_upload(dev, B43_HTTAB32(0x20, 0), b43_httab_0x20);
+ httab_upload(dev, B43_HTTAB32(0x22, 0), b43_httab_0x22);
+ httab_upload(dev, B43_HTTAB32(0x24, 0), b43_httab_0x24);
+}
diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h
new file mode 100644
index 000000000000..ea3be382c894
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.h
@@ -0,0 +1,22 @@
+#ifndef B43_TABLES_PHY_HT_H_
+#define B43_TABLES_PHY_HT_H_
+
+/* The HT-PHY tables. */
+#define B43_HTTAB_TYPEMASK 0xF0000000
+#define B43_HTTAB_8BIT 0x10000000
+#define B43_HTTAB_16BIT 0x20000000
+#define B43_HTTAB_32BIT 0x30000000
+#define B43_HTTAB8(table, offset) (((table) << 10) | (offset) | B43_HTTAB_8BIT)
+#define B43_HTTAB16(table, offset) (((table) << 10) | (offset) | B43_HTTAB_16BIT)
+#define B43_HTTAB32(table, offset) (((table) << 10) | (offset) | B43_HTTAB_32BIT)
+
+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_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, const void *_data);
+
+void b43_phy_ht_tables_init(struct b43_wldev *dev);
+
+#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
new file mode 100644
index 000000000000..40c1d0915dd3
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.c
@@ -0,0 +1,34 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n LCN-PHY data tables
+
+ This program is free software; you can redistribute it and/or modify
+ 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.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_lcn.h"
+#include "phy_common.h"
+#include "phy_lcn.h"
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev)
+{
+}
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h
new file mode 100644
index 000000000000..5e31b15b81ec
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.h
@@ -0,0 +1,6 @@
+#ifndef B43_TABLES_PHY_LCN_H_
+#define B43_TABLES_PHY_LCN_H_
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
index 8f4db448ec33..9b1a038be08b 100644
--- a/drivers/net/wireless/b43/wa.c
+++ b/drivers/net/wireless/b43/wa.c
@@ -5,7 +5,7 @@
PHY workarounds.
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -458,17 +458,15 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev)
static void b43_wa_boards_a(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
-
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BU4306 &&
- bus->boardinfo.rev < 0x30) {
+ if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+ dev->dev->board_type == SSB_BOARD_BU4306 &&
+ dev->dev->board_rev < 0x30) {
b43_phy_write(dev, 0x0010, 0xE000);
b43_phy_write(dev, 0x0013, 0x0140);
b43_phy_write(dev, 0x0014, 0x0280);
} else {
- if (bus->boardinfo.type == SSB_BOARD_MP4318 &&
- bus->boardinfo.rev < 0x20) {
+ if (dev->dev->board_type == SSB_BOARD_MP4318 &&
+ dev->dev->board_rev < 0x20) {
b43_phy_write(dev, 0x0013, 0x0210);
b43_phy_write(dev, 0x0014, 0x0840);
} else {
@@ -486,19 +484,19 @@ static void b43_wa_boards_a(struct b43_wldev *dev)
static void b43_wa_boards_g(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
- if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM ||
- bus->boardinfo.type != SSB_BOARD_BU4306 ||
- bus->boardinfo.rev != 0x17) {
+ if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM ||
+ dev->dev->board_type != SSB_BOARD_BU4306 ||
+ dev->dev->board_rev != 0x17) {
if (phy->rev < 2) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
- if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(phy->rev >= 7)) {
b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
@@ -510,7 +508,7 @@ static void b43_wa_boards_g(struct b43_wldev *dev)
}
}
}
- if (bus->sprom.boardflags_lo & B43_BFL_FEM) {
+ if (sprom->boardflags_lo & B43_BFL_FEM) {
b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
}
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index c8f99aebe01f..b74f25ec1ab4 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -6,7 +6,7 @@
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -323,8 +323,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
/* we give the phase1key and iv16 here, the key is stored in
* shm. With that the hardware can do phase 2 and encryption.
*/
- ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
- IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
+ ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
for (i = 0; i < 5; i++) {
txhdr->iv[i * 2 + 0] = phase1key[i];
@@ -547,7 +546,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
else
tmp -= 3;
} else {
- if (dev->sdev->bus->sprom.
+ if (dev->dev->bus_sprom->
boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 23583be1ee0b..a610a352102a 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -8,7 +8,7 @@
#include <linux/stringify.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/io.h>
#include <linux/ssb/ssb.h>
@@ -532,6 +532,8 @@ struct b43legacy_dma {
struct b43legacy_dmaring *rx_ring0;
struct b43legacy_dmaring *rx_ring3; /* only on core.rev < 5 */
+
+ u32 translation; /* Routing bits */
};
/* Data structures for PIO transmission, per 80211 core. */
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index f232618f2cd1..5e28ad0d6d17 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -4,7 +4,7 @@
debugfs driver debugging code
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
This 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/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index e03e01d0bc35..5010c477abdf 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -4,7 +4,7 @@
DMA ringbuffer and descriptor allocation/management
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
Some code in this file is derived from the b44.c driver
Copyright (C) 2002 David S. Miller
@@ -73,7 +73,7 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
- addr |= ssb_dma_translation(ring->dev->dev);
+ addr |= ring->dev->dma.translation;
ctl = (bufsize - ring->frameoffset)
& B43legacy_DMA32_DCTL_BYTECNT;
if (slot == ring->nr_slots - 1)
@@ -175,7 +175,7 @@ static void op64_fill_descriptor(struct b43legacy_dmaring *ring,
addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= ssb_dma_translation(ring->dev->dev);
+ addrhi |= ring->dev->dma.translation;
if (slot == ring->nr_slots - 1)
ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND;
if (start)
@@ -709,7 +709,7 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring)
int err = 0;
u32 value;
u32 addrext;
- u32 trans = ssb_dma_translation(ring->dev->dev);
+ u32 trans = ring->dev->dma.translation;
if (ring->tx) {
if (ring->type == B43legacy_DMA_64BIT) {
@@ -817,14 +817,13 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
static void free_all_descbuffers(struct b43legacy_dmaring *ring)
{
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ ring->ops->idx2desc(ring, i, &meta);
if (!meta->skb) {
B43legacy_WARN_ON(!ring->tx);
@@ -1094,6 +1093,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev)
return -EOPNOTSUPP;
#endif
}
+ dma->translation = ssb_dma_translation(dev->dev);
err = -ENOMEM;
/* setup TX DMA channels. */
@@ -1371,10 +1371,8 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
struct sk_buff *skb)
{
struct b43legacy_dmaring *ring;
- struct ieee80211_hdr *hdr;
int err = 0;
unsigned long flags;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
spin_lock_irqsave(&ring->lock, flags);
@@ -1401,8 +1399,6 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
* into the skb data or cb now. */
- hdr = NULL;
- info = NULL;
err = dma_tx_fragment(ring, &skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
@@ -1435,7 +1431,6 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
{
const struct b43legacy_dma_ops *ops;
struct b43legacy_dmaring *ring;
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
int retry_limit;
int slot;
@@ -1450,7 +1445,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
ops = ring->ops;
while (1) {
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- desc = ops->idx2desc(ring, slot, &meta);
+ ops->idx2desc(ring, slot, &meta);
if (meta->skb)
unmap_descbuffer(ring, meta->dmaaddr,
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h
index f89c34226288..686941c242fc 100644
--- a/drivers/net/wireless/b43legacy/dma.h
+++ b/drivers/net/wireless/b43legacy/dma.h
@@ -5,7 +5,7 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "b43legacy.h"
diff --git a/drivers/net/wireless/b43legacy/ilt.c b/drivers/net/wireless/b43legacy/ilt.c
index a849078aea69..ee5682e54204 100644
--- a/drivers/net/wireless/b43legacy/ilt.c
+++ b/drivers/net/wireless/b43legacy/ilt.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index 37e9be893560..2f1bfdc44f94 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1ab8861dd43a..04c03b212a5e 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -4,7 +4,7 @@
*
* Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
- * Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (c) 2005, 2006 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) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -1564,10 +1564,10 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
struct b43legacy_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision;
const char *filename;
- u32 tmshigh;
int err;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
+ /* do dummy read */
+ ssb_read32(dev->dev, SSB_TMSHIGH);
if (!fw->ucode) {
if (rev == 2)
filename = "ucode2";
@@ -2634,11 +2634,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
int antenna_tx;
- int antenna_rx;
int err = 0;
antenna_tx = B43legacy_ANTENNA_DEFAULT;
- antenna_rx = B43legacy_ANTENNA_DEFAULT;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
@@ -2775,14 +2773,12 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
- struct b43legacy_phy *phy;
unsigned long flags;
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(wl->vif != vif);
dev = wl->current_dev;
- phy = &dev->phy;
/* Disable IRQs while reconfiguring the device.
* This makes it possible to drop the spinlock throughout
@@ -2974,7 +2970,7 @@ static int b43legacy_phy_versioning(struct b43legacy_wldev *dev)
break;
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
diff --git a/drivers/net/wireless/b43legacy/main.h b/drivers/net/wireless/b43legacy/main.h
index 1f0e2e379b02..b74a058d7bac 100644
--- a/drivers/net/wireless/b43legacy/main.h
+++ b/drivers/net/wireless/b43legacy/main.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 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) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 28e477d01587..96faaef3661b 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/phy.h b/drivers/net/wireless/b43legacy/phy.h
index ecbe409f9a94..831a7a4760e5 100644
--- a/drivers/net/wireless/b43legacy/phy.h
+++ b/drivers/net/wireless/b43legacy/phy.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index b033b0ed4ca0..192251adf986 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -4,7 +4,7 @@
PIO Transmission
- Copyright (c) 2005 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005 Michael Buesch <m@bues.ch>
This 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/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index 2df545cfad14..475eb14e665b 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h
index ec4de2811c52..bccb3d7da682 100644
--- a/drivers/net/wireless/b43legacy/radio.h
+++ b/drivers/net/wireless/b43legacy/radio.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index b90f223fb31c..c4559bcbc707 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
RFKILL support
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2007 Michael Buesch <m@bues.ch>
This 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/b43legacy/sysfs.c b/drivers/net/wireless/b43legacy/sysfs.c
index 56c384fa9b1f..57f8b089767c 100644
--- a/drivers/net/wireless/b43legacy/sysfs.c
+++ b/drivers/net/wireless/b43legacy/sysfs.c
@@ -4,7 +4,7 @@
SYSFS support routines
- Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2006 Michael Buesch <m@bues.ch>
This 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/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 3a95541708a6..5188fab0b377 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -6,7 +6,7 @@
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (C) 2005, 2006 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) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -321,11 +321,9 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
struct ieee80211_hdr *hdr;
int rts_rate;
int rts_rate_fb;
- int rts_rate_ofdm;
int rts_rate_fb_ofdm;
rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
- rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
if (rts_rate_fb_ofdm)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 88dc6a52bdf1..7bb0b4b3f2cb 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,7 @@
#ifndef HOSTAP_WLAN_H
#define HOSTAP_WLAN_H
+#include <linux/interrupt.h>
#include <linux/wireless.h>
#include <linux/netdevice.h>
#include <linux/mutex.h>
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 44307753587d..3774dd034746 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -287,7 +287,7 @@ static const char *command_types[] = {
"unused", /* HOST_INTERRUPT_COALESCING */
"undefined",
"CARD_DISABLE_PHY_OFF",
- "MSDU_TX_RATES" "undefined",
+ "MSDU_TX_RATES",
"undefined",
"SET_STATION_STAT_BITS",
"CLEAR_STATIONS_STAT_BITS",
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index 91795b5a93c5..ecb561d7a7a0 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/pci.h>
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index e5ad76cd77da..32a9966c3bf6 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -442,7 +442,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
* 802.11, but makes it easier to use different keys with
* stations that do not support WEP key mapping). */
- if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+ if (is_unicast_ether_addr(hdr->addr1) || local->bcrx_sta_key)
(void)hostap_handle_sta_crypto(local, hdr, &crypt,
&sta);
#endif
@@ -772,7 +772,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
#ifdef NOT_YET
if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) {
- if (dst[0] & 0x01) {
+ if (is_multicast_ether_addr(dst)) {
/* copy multicast frame both to the higher layers and
* to the wireless media */
ieee->ap->bridged_multicast++;
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
index d7bd6cf00a81..6623e5052254 100644
--- a/drivers/net/wireless/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -30,6 +30,7 @@
******************************************************************************/
+#include <linux/hardirq.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/module.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index d096dc28204d..dab67a12d73b 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -408,7 +408,6 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
#endif
- iwl_legacy_recover_from_statistics(priv, pkt);
memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
}
@@ -2640,7 +2639,6 @@ static struct iwl_lib_ops iwl3945_lib = {
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
.txq_init = iwl3945_hw_tx_queue_init,
.load_ucode = iwl3945_load_bsm,
- .dump_nic_event_log = iwl3945_dump_nic_event_log,
.dump_nic_error_log = iwl3945_dump_nic_error_log,
.apm_ops = {
.init = iwl3945_apm_init,
@@ -2698,9 +2696,7 @@ static struct iwl_base_params iwl3945_base_params = {
.set_l0s = false,
.use_bsm = true,
.led_compensation = 64,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
.wd_timeout = IWL_DEF_WD_TIMEOUT,
- .max_event_log_size = 512,
};
static struct iwl_cfg iwl3945_bg_cfg = {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
index a7a4739880dc..2be6d9e3b019 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
@@ -694,47 +694,6 @@ void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
sizeof(struct iwl_rx_phy_res));
}
-static int iwl4965_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_legacy_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
- channel = iwl_legacy_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 iwl4965_get_channels_for_scan(struct iwl_priv *priv,
struct ieee80211_vif *vif,
enum ieee80211_band band,
@@ -858,16 +817,13 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_legacy_is_any_associated(priv)) {
- u16 interval = 0;
+ u16 interval;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
- if (priv->is_internal_short_scan)
- interval = 0;
- else
- interval = vif->bss_conf.beacon_int;
+ interval = vif->bss_conf.beacon_int;
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -882,9 +838,7 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan_suspend_time, interval);
}
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- } else if (priv->scan_request->n_ssids) {
+ 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++) {
@@ -981,38 +935,21 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
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);
- if (!priv->is_internal_short_scan) {
- cmd_len = iwl_legacy_fill_probe_req(priv,
+
+ cmd_len = iwl_legacy_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));
- } else {
- /* use bcast addr, will not be transmitted but must be valid */
- cmd_len = iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- iwlegacy_bcast_addr, NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
- }
scan->tx_cmd.len = cpu_to_le16(cmd_len);
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
RXON_FILTER_BCON_AWARE_MSK);
- if (priv->is_internal_short_scan) {
- scan->channel_count =
- iwl4965_get_single_channel_for_scan(priv, vif, band,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- } else {
- scan->channel_count =
- iwl4965_get_channels_for_scan(priv, vif, band,
- is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- }
+ scan->channel_count = iwl4965_get_channels_for_scan(priv, vif, band,
+ is_active, n_probes,
+ (void *)&scan->data[cmd_len]);
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
return -EIO;
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
index 24d149909ba3..9b65153bdd01 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
@@ -2275,6 +2275,9 @@ iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
if (rate_control_send_low(sta, priv_sta, txrc))
return;
+ if (!lq_sta)
+ return;
+
rate_idx = lq_sta->last_txrate_idx;
if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
index b9fa2f6411a7..2b144bbfc3c5 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
@@ -151,81 +151,6 @@ static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
#define REG_RECALIB_PERIOD (60)
-/**
- * iwl4965_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl4965_good_plcp_health(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt)
-{
- bool rc = true;
- int combined_plcp_delta;
- unsigned int plcp_msec;
- unsigned long plcp_received_jiffies;
-
- if (priv->cfg->base_params->plcp_delta_threshold ==
- IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
- IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
- return rc;
- }
-
- /*
- * check for plcp_err and trigger radio reset if it exceeds
- * the plcp error threshold plcp_delta.
- */
- plcp_received_jiffies = jiffies;
- plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
- (long) priv->plcp_jiffies);
- priv->plcp_jiffies = plcp_received_jiffies;
- /*
- * check to make sure plcp_msec is not 0 to prevent division
- * by zero.
- */
- if (plcp_msec) {
- struct statistics_rx_phy *ofdm;
- struct statistics_rx_ht_phy *ofdm_ht;
-
- ofdm = &pkt->u.stats.rx.ofdm;
- ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
- combined_plcp_delta =
- (le32_to_cpu(ofdm->plcp_err) -
- le32_to_cpu(priv->_4965.statistics.
- rx.ofdm.plcp_err)) +
- (le32_to_cpu(ofdm_ht->plcp_err) -
- le32_to_cpu(priv->_4965.statistics.
- rx.ofdm_ht.plcp_err));
-
- if ((combined_plcp_delta > 0) &&
- ((combined_plcp_delta * 100) / plcp_msec) >
- priv->cfg->base_params->plcp_delta_threshold) {
- /*
- * if plcp_err exceed the threshold,
- * the following data is printed in csv format:
- * Text: plcp_err exceeded %d,
- * Received ofdm.plcp_err,
- * Current ofdm.plcp_err,
- * Received ofdm_ht.plcp_err,
- * Current ofdm_ht.plcp_err,
- * combined_plcp_delta,
- * plcp_msec
- */
- IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
- "%u, %u, %u, %u, %d, %u mSecs\n",
- priv->cfg->base_params->plcp_delta_threshold,
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- combined_plcp_delta, plcp_msec);
-
- rc = false;
- }
- }
- return rc;
-}
-
void iwl4965_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -248,8 +173,7 @@ void iwl4965_rx_statistics(struct iwl_priv *priv,
iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
- iwl_legacy_recover_from_statistics(priv, pkt);
-
+ /* TODO: reading some of statistics is unneeded */
memcpy(&priv->_4965.statistics, &pkt->u.stats,
sizeof(priv->_4965.statistics));
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
index 79ac081832fb..ac4f64de1363 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
@@ -240,8 +240,7 @@ static void iwl4965_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
- ieee80211_get_tkip_key(keyconf, skb_frag,
- IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
break;
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
index facc94e74b07..bd4b000733f7 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
@@ -496,7 +496,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
return CALIB_CH_GROUP_4;
- return -1;
+ return -EINVAL;
}
static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
@@ -915,7 +915,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
if (txatten_grp < 0) {
IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
channel);
- return -EINVAL;
+ return txatten_grp;
}
IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
@@ -1185,8 +1185,6 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
sizeof(rxon_assoc), &rxon_assoc, NULL);
- if (ret)
- return ret;
return ret;
}
@@ -2071,7 +2069,6 @@ static struct iwl_lib_ops iwl4965_lib = {
.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
.init_alive_start = iwl4965_init_alive_start,
.load_ucode = iwl4965_load_bsm,
- .dump_nic_event_log = iwl4965_dump_nic_event_log,
.dump_nic_error_log = iwl4965_dump_nic_error_log,
.dump_fh = iwl4965_dump_fh,
.set_channel_switch = iwl4965_hw_channel_switch,
@@ -2102,7 +2099,6 @@ static struct iwl_lib_ops iwl4965_lib = {
.tx_stats_read = iwl4965_ucode_tx_stats_read,
.general_stats_read = iwl4965_ucode_general_stats_read,
},
- .check_plcp_health = iwl4965_good_plcp_health,
};
static const struct iwl_legacy_ops iwl4965_legacy_ops = {
@@ -2152,10 +2148,8 @@ static struct iwl_base_params iwl4965_base_params = {
.use_bsm = true,
.led_compensation = 61,
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
.wd_timeout = IWL_DEF_WD_TIMEOUT,
.temperature_kelvin = true,
- .max_event_log_size = 512,
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
diff --git a/drivers/net/wireless/iwlegacy/iwl-commands.h b/drivers/net/wireless/iwlegacy/iwl-commands.h
index 17a1d504348e..89904054473f 100644
--- a/drivers/net/wireless/iwlegacy/iwl-commands.h
+++ b/drivers/net/wireless/iwlegacy/iwl-commands.h
@@ -2297,14 +2297,7 @@ struct iwl_spectrum_notification {
#define IWL_POWER_VEC_SIZE 5
#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_SAVE_ENA_MSK cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK cpu_to_le16(BIT(1))
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2))
#define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3))
-#define IWL_POWER_FAST_PD cpu_to_le16(BIT(4))
-#define IWL_POWER_BEACON_FILTERING cpu_to_le16(BIT(5))
-#define IWL_POWER_SHADOW_REG_ENA cpu_to_le16(BIT(6))
-#define IWL_POWER_CT_KILL_SET cpu_to_le16(BIT(7))
struct iwl3945_powertable_cmd {
__le16 flags;
@@ -2624,8 +2617,8 @@ struct iwl_scanstart_notification {
__le32 status;
} __packed;
-#define SCAN_OWNER_STATUS 0x1;
-#define MEASURE_OWNER_STATUS 0x2;
+#define SCAN_OWNER_STATUS 0x1
+#define MEASURE_OWNER_STATUS 0x2
#define IWL_PROBE_STATUS_OK 0
#define IWL_PROBE_STATUS_TX_FAILED BIT(0)
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
index 3be76bd5499a..35cd2537e7fd 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -931,7 +931,6 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv)
priv->cfg->ops->lib->dump_nic_error_log(priv);
if (priv->cfg->ops->lib->dump_fh)
priv->cfg->ops->lib->dump_fh(priv, NULL, false);
- priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
iwl_legacy_print_rx_config_cmd(priv,
@@ -1707,41 +1706,14 @@ iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
EXPORT_SYMBOL(iwl_legacy_update_stats);
#endif
-static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (!iwl_legacy_is_any_associated(priv)) {
- IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
- return;
- }
- /*
- * There is no easy and better way to force reset the radio,
- * the only known method is switching channel which will force to
- * reset and tune the radio.
- * Use internal short scan (single channel) operation to should
- * achieve this objective.
- * Driver should reset the radio when number of consecutive missed
- * beacon, or any other uCode error condition detected.
- */
- IWL_DEBUG_INFO(priv, "perform radio reset.\n");
- iwl_legacy_internal_short_hw_scan(priv);
-}
-
-
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
{
struct iwl_force_reset *force_reset;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EINVAL;
- if (mode >= IWL_MAX_FORCE_RESET) {
- IWL_DEBUG_INFO(priv, "invalid reset request.\n");
- return -EINVAL;
- }
- force_reset = &priv->force_reset[mode];
+ force_reset = &priv->force_reset;
force_reset->reset_request_count++;
if (!external) {
if (force_reset->last_force_reset_jiffies &&
@@ -1754,37 +1726,34 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
}
force_reset->reset_success_count++;
force_reset->last_force_reset_jiffies = jiffies;
- IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
- switch (mode) {
- case IWL_RF_RESET:
- _iwl_legacy_force_rf_reset(priv);
- break;
- case IWL_FW_RESET:
- /*
- * if the request is from external(ex: debugfs),
- * then always perform the request in regardless the module
- * parameter setting
- * if the request is from internal (uCode error or driver
- * detect failure), then fw_restart module parameter
- * need to be check before performing firmware reload
- */
- if (!external && !priv->cfg->mod_params->restart_fw) {
- IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
- "module parameter setting\n");
- break;
- }
- IWL_ERR(priv, "On demand firmware reload\n");
- /* Set the FW error flag -- cleared on iwl_down */
- set_bit(STATUS_FW_ERROR, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
- /*
- * Keep the restart process from trying to send host
- * commands by clearing the INIT status bit
- */
- clear_bit(STATUS_READY, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- break;
+
+ /*
+ * if the request is from external(ex: debugfs),
+ * then always perform the request in regardless the module
+ * parameter setting
+ * if the request is from internal (uCode error or driver
+ * detect failure), then fw_restart module parameter
+ * need to be check before performing firmware reload
+ */
+
+ if (!external && !priv->cfg->mod_params->restart_fw) {
+ IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+ "module parameter setting\n");
+ return 0;
}
+
+ IWL_ERR(priv, "On demand firmware reload\n");
+
+ /* Set the FW error flag -- cleared on iwl_down */
+ set_bit(STATUS_FW_ERROR, &priv->status);
+ wake_up_interruptible(&priv->wait_command_queue);
+ /*
+ * Keep the restart process from trying to send host
+ * commands by clearing the INIT status bit
+ */
+ clear_bit(STATUS_READY, &priv->status);
+ queue_work(priv->workqueue, &priv->restart);
+
return 0;
}
@@ -1879,7 +1848,7 @@ static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
if (time_after(jiffies, timeout)) {
IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
q->id, priv->cfg->base_params->wd_timeout);
- ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false);
+ ret = iwl_legacy_force_reset(priv, false);
return (ret == -EAGAIN) ? 0 : 1;
}
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
index c5fbda0760de..84da79376ef8 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.h
+++ b/drivers/net/wireless/iwlegacy/iwl-core.h
@@ -143,8 +143,7 @@ struct iwl_lib_ops {
int (*is_valid_rtc_data_addr)(u32 addr);
/* 1st ucode load */
int (*load_ucode)(struct iwl_priv *priv);
- int (*dump_nic_event_log)(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
+
void (*dump_nic_error_log)(struct iwl_priv *priv);
int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
int (*set_channel_switch)(struct iwl_priv *priv,
@@ -161,9 +160,6 @@ struct iwl_lib_ops {
/* temperature */
struct iwl_temp_ops temp_ops;
- /* check for plcp health */
- bool (*check_plcp_health)(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt);
struct iwl_debugfs_ops debugfs_ops;
@@ -207,11 +203,8 @@ struct iwl_mod_params {
* to the deviation to achieve the desired led frequency.
* The detail algorithm is described in iwl-led.c
* @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- * radio tuning when there is a high receiving plcp error rate
* @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
* @ucode_tracing: support ucode continuous tracing
* @sensitivity_calib_by_driver: driver has the capability to perform
* sensitivity calibration operation
@@ -229,10 +222,8 @@ struct iwl_base_params {
u16 led_compensation;
int chain_noise_num_beacons;
- u8 plcp_delta_threshold;
unsigned int wd_timeout;
bool temperature_kelvin;
- u32 max_event_log_size;
const bool ucode_tracing;
const bool sensitivity_calib_by_driver;
const bool chain_noise_calib_by_driver;
@@ -441,7 +432,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external);
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external);
u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
struct ieee80211_mgmt *frame,
const u8 *ta, const u8 *ie, int ie_len, int left);
@@ -493,7 +484,7 @@ static inline u16 iwl_legacy_pcie_link_ctl(struct iwl_priv *priv)
{
int pos;
u16 pci_lnk_ctl;
- pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(priv->pci_dev);
pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
return pci_lnk_ctl;
}
@@ -521,8 +512,6 @@ extern const struct dev_pm_ops iwl_legacy_pm_ops;
* Error Handling Debugging
******************************************************/
void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
diff --git a/drivers/net/wireless/iwlegacy/iwl-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
index 2d32438b4cb8..996996a71657 100644
--- a/drivers/net/wireless/iwlegacy/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
@@ -391,48 +391,6 @@ static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
return ret;
}
-static ssize_t iwl_legacy_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 = priv->cfg->ops->lib->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_legacy_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)
- priv->cfg->ops->lib->dump_nic_event_log(priv, true,
- NULL, false);
-
- return count;
-}
-
-
-
static ssize_t
iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -706,7 +664,6 @@ static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
}
DEBUGFS_READ_WRITE_FILE_OPS(sram);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(channels);
@@ -1098,56 +1055,6 @@ static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,
return count;
}
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int pos = 0;
- char buf[128];
- const size_t bufsz = sizeof(buf);
-
- pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
- priv->event_log.ucode_trace ? "On" : "Off");
- pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
- priv->event_log.non_wraps_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
- priv->event_log.wraps_once_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
- priv->event_log.wraps_more_count);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_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 trace;
-
- 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", &trace) != 1)
- return -EFAULT;
-
- if (trace) {
- priv->event_log.ucode_trace = true;
- /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- } else {
- priv->event_log.ucode_trace = false;
- del_timer_sync(&priv->ucode_trace);
- }
-
- return count;
-}
-
static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
@@ -1236,72 +1143,31 @@ static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,
return count;
}
-static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int pos = 0;
- char buf[12];
- const size_t bufsz = sizeof(buf);
-
- pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
- priv->cfg->base_params->plcp_delta_threshold);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_plcp_delta_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 plcp;
-
- 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", &plcp) != 1)
- return -EINVAL;
- if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
- (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
- priv->cfg->base_params->plcp_delta_threshold =
- IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
- else
- priv->cfg->base_params->plcp_delta_threshold = plcp;
- return count;
-}
-
static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data;
- int i, pos = 0;
+ int pos = 0;
char buf[300];
const size_t bufsz = sizeof(buf);
struct iwl_force_reset *force_reset;
- for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
- force_reset = &priv->force_reset[i];
- pos += scnprintf(buf + pos, bufsz - pos,
- "Force reset method %d\n", i);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request: %d\n",
- force_reset->reset_request_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request success: %d\n",
- force_reset->reset_success_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request reject: %d\n",
- force_reset->reset_reject_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\treset duration: %lu\n",
- force_reset->reset_duration);
- }
+ force_reset = &priv->force_reset;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request: %d\n",
+ force_reset->reset_request_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request success: %d\n",
+ force_reset->reset_success_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request reject: %d\n",
+ force_reset->reset_reject_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\treset duration: %lu\n",
+ force_reset->reset_duration);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1309,25 +1175,11 @@ static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos) {
+ int ret;
struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int reset, ret;
- 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", &reset) != 1)
- return -EINVAL;
- switch (reset) {
- case IWL_RF_RESET:
- case IWL_FW_RESET:
- ret = iwl_legacy_force_reset(priv, reset, true);
- break;
- default:
- return -EINVAL;
- }
+ ret = iwl_legacy_force_reset(priv, true);
+
return ret ? ret : count;
}
@@ -1367,10 +1219,8 @@ 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_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);
DEBUGFS_READ_FILE_OPS(rxon_flags);
DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
@@ -1403,7 +1253,6 @@ int iwl_legacy_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(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);
@@ -1420,7 +1269,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(clear_traffic_statistics, 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);
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
@@ -1430,8 +1278,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
if (priv->cfg->base_params->chain_noise_calib_by_driver)
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
- if (priv->cfg->base_params->ucode_tracing)
- DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
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);
diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
index ea30122669ee..9c786edf56fd 100644
--- a/drivers/net/wireless/iwlegacy/iwl-dev.h
+++ b/drivers/net/wireless/iwlegacy/iwl-dev.h
@@ -32,6 +32,7 @@
#ifndef __iwl_legacy_dev_h__
#define __iwl_legacy_dev_h__
+#include <linux/interrupt.h>
#include <linux/pci.h> /* for struct pci_device_id */
#include <linux/kernel.h>
#include <linux/leds.h>
@@ -855,32 +856,6 @@ struct traffic_stats {
};
/*
- * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
- * to perform continuous uCode event logging operation if enabled
- */
-#define UCODE_TRACE_PERIOD (100)
-
-/*
- * iwl_event_log: current uCode event log position
- *
- * @ucode_trace: enable/disable ucode continuous trace timer
- * @num_wraps: how many times the event buffer wraps
- * @next_entry: the entry just before the next one that uCode would fill
- * @non_wraps_count: counter for no wrap detected when dump ucode events
- * @wraps_once_count: counter for wrap once detected when dump ucode events
- * @wraps_more_count: counter for wrap more than once detected
- * when dump ucode events
- */
-struct iwl_event_log {
- bool ucode_trace;
- u32 num_wraps;
- u32 next_entry;
- int non_wraps_count;
- int wraps_once_count;
- int wraps_more_count;
-};
-
-/*
* host interrupt timeout value
* used with setting interrupt coalescing timer
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
@@ -895,18 +870,6 @@ struct iwl_event_log {
#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.
- */
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (1)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
-#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
-#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0)
-
-#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
/* TX queue watchdog timeouts in mSecs */
@@ -914,12 +877,6 @@ struct iwl_event_log {
#define IWL_LONG_WD_TIMEOUT (10000)
#define IWL_MAX_WD_TIMEOUT (120000)
-enum iwl_reset {
- IWL_RF_RESET = 0,
- IWL_FW_RESET,
- IWL_MAX_FORCE_RESET,
-};
-
struct iwl_force_reset {
int reset_request_count;
int reset_success_count;
@@ -1032,11 +989,8 @@ struct iwl_priv {
/* track IBSS manager (last beacon) status */
u32 ibss_manager;
- /* storing the jiffies when the plcp error rate is received */
- unsigned long plcp_jiffies;
-
/* force reset */
- struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+ struct iwl_force_reset force_reset;
/* we allocate array of iwl_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */
@@ -1057,7 +1011,6 @@ struct iwl_priv {
enum ieee80211_band scan_band;
struct cfg80211_scan_request *scan_request;
struct ieee80211_vif *scan_vif;
- bool is_internal_short_scan;
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 mgmt_tx_ant;
@@ -1212,12 +1165,6 @@ struct iwl_priv {
#endif
#if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
struct {
- /*
- * reporting the number of tids has AGG on. 0 means
- * no AGGREGATION
- */
- u8 agg_tids_count;
-
struct iwl_rx_phy_res last_phy_res;
bool last_phy_res_valid;
@@ -1256,7 +1203,6 @@ struct iwl_priv {
struct iwl_rxon_context *beacon_ctx;
struct sk_buff *beacon_skb;
- struct work_struct start_internal_scan;
struct work_struct tx_flush;
struct tasklet_struct irq_tasklet;
@@ -1293,12 +1239,9 @@ struct iwl_priv {
u32 disable_tx_power_cal;
struct work_struct run_time_calib_work;
struct timer_list statistics_periodic;
- struct timer_list ucode_trace;
struct timer_list watchdog;
bool hw_ready;
- struct iwl_event_log event_log;
-
struct led_classdev led;
unsigned long blink_on, blink_off;
bool led_registered;
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.c b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
index 080b852b33bd..acec99197ce0 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.c
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
@@ -38,8 +38,5 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);
#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.h b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
index 9612aa0f6ec4..a443725ba6be 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
@@ -96,47 +96,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_legacy_ucode
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event,
- TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, time)
- __field(u32, data)
- __field(u32, ev)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->time = time;
- __entry->data = data;
- __entry->ev = ev;
- ),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event,
- TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
- TP_ARGS(priv, wraps, n_entry, p_entry),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, wraps)
- __field(u32, n_entry)
- __field(u32, p_entry)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->wraps = wraps;
- __entry->n_entry = n_entry;
- __entry->p_entry = p_entry;
- ),
- TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
- __entry->priv, __entry->wraps, __entry->n_entry,
- __entry->p_entry)
-);
-
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi
@@ -242,25 +201,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,
__entry->blink2, __entry->ilink1, __entry->ilink2)
);
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_event,
- TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, time)
- __field(u32, data)
- __field(u32, ev)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->time = time;
- __entry->data = data;
- __entry->ev = ev;
- ),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
#endif /* __IWLWIFI_DEVICE_TRACE */
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
index cb346d1a9ffa..5bf3f49b74ab 100644
--- a/drivers/net/wireless/iwlegacy/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
@@ -316,7 +316,6 @@ static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,
break;
default:
BUG();
- return;
}
}
diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h
index a6effdae63f9..5cf23eaecbbb 100644
--- a/drivers/net/wireless/iwlegacy/iwl-helpers.h
+++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h
@@ -132,7 +132,16 @@ static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,
ieee80211_stop_queue(priv->hw, 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_legacy_disable_interrupts(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlegacy/iwl-rx.c b/drivers/net/wireless/iwlegacy/iwl-rx.c
index 654cf233a384..9b5d0abe8be9 100644
--- a/drivers/net/wireless/iwlegacy/iwl-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-rx.c
@@ -227,27 +227,6 @@ void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
-void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
- if (iwl_legacy_is_any_associated(priv)) {
- if (priv->cfg->ops->lib->check_plcp_health) {
- if (!priv->cfg->ops->lib->check_plcp_health(
- priv, pkt)) {
- /*
- * high plcp error detected
- * reset Radio
- */
- iwl_legacy_force_reset(priv,
- IWL_RF_RESET, false);
- }
- }
- }
-}
-EXPORT_SYMBOL(iwl_legacy_recover_from_statistics);
-
/*
* returns non-zero if packet should be dropped
*/
diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c
index 353234a02c6d..a6b5222fc59e 100644
--- a/drivers/net/wireless/iwlegacy/iwl-scan.c
+++ b/drivers/net/wireless/iwlegacy/iwl-scan.c
@@ -101,7 +101,6 @@ static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)
ieee80211_scan_completed(priv->hw, aborted);
}
- priv->is_internal_short_scan = false;
priv->scan_vif = NULL;
priv->scan_request = NULL;
}
@@ -329,10 +328,8 @@ void iwl_legacy_init_scan_params(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_legacy_init_scan_params);
-static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- bool internal,
- enum ieee80211_band band)
+static int iwl_legacy_scan_initiate(struct iwl_priv *priv,
+ struct ieee80211_vif *vif)
{
int ret;
@@ -359,18 +356,14 @@ static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
return -EBUSY;
}
- IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
- internal ? "internal short " : "");
+ IWL_DEBUG_SCAN(priv, "Starting scan...\n");
set_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = internal;
priv->scan_start = jiffies;
- priv->scan_band = band;
ret = priv->cfg->ops->utils->request_scan(priv, vif);
if (ret) {
clear_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = false;
return ret;
}
@@ -394,8 +387,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCANNING, &priv->status) &&
- !priv->is_internal_short_scan) {
+ if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
ret = -EAGAIN;
goto out_unlock;
@@ -404,17 +396,9 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
/* mac80211 will only ask for one band at a time */
priv->scan_request = req;
priv->scan_vif = vif;
+ priv->scan_band = req->channels[0]->band;
- /*
- * If an internal scan is in progress, just set
- * up the scan_request as per above.
- */
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
- ret = 0;
- } else
- ret = iwl_legacy_scan_initiate(priv, vif, false,
- req->channels[0]->band);
+ ret = iwl_legacy_scan_initiate(priv, vif);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -425,40 +409,6 @@ out_unlock:
}
EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
-/*
- * internal short scan, this function should only been called while associated.
- * It will reset and tune the radio to prevent possible RF related problem
- */
-void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv)
-{
- queue_work(priv->workqueue, &priv->start_internal_scan);
-}
-
-static void iwl_legacy_bg_start_internal_scan(struct work_struct *work)
-{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, start_internal_scan);
-
- IWL_DEBUG_SCAN(priv, "Start internal scan\n");
-
- mutex_lock(&priv->mutex);
-
- if (priv->is_internal_short_scan == true) {
- IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
- goto unlock;
- }
-
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
- goto unlock;
- }
-
- if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band))
- IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
- unlock:
- mutex_unlock(&priv->mutex);
-}
-
static void iwl_legacy_bg_scan_check(struct work_struct *data)
{
struct iwl_priv *priv =
@@ -542,8 +492,7 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
container_of(work, struct iwl_priv, scan_completed);
bool aborted;
- IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
- priv->is_internal_short_scan ? "internal short " : "");
+ IWL_DEBUG_SCAN(priv, "Completed scan.\n");
cancel_delayed_work(&priv->scan_check);
@@ -558,27 +507,6 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
goto out_settings;
}
- if (priv->is_internal_short_scan && !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_legacy_scan_initiate(priv, priv->scan_vif, false,
- 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_legacy_complete_scan(priv, aborted);
out_settings:
@@ -590,8 +518,7 @@ out_settings:
* We do not commit power settings while scan is pending,
* do it now if the settings changed.
*/
- iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next,
- false);
+ iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
priv->cfg->ops->utils->post_scan(priv);
@@ -604,15 +531,12 @@ void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)
{
INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
- INIT_WORK(&priv->start_internal_scan,
- iwl_legacy_bg_start_internal_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
}
EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
{
- cancel_work_sync(&priv->start_internal_scan);
cancel_work_sync(&priv->abort_scan);
cancel_work_sync(&priv->scan_completed);
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 0ee6be6a9c5d..795826a014ed 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -1409,212 +1409,6 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
}
}
-#define EVENT_START_OFFSET (6 * sizeof(u32))
-
-/**
- * iwl3945_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl3945_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 = le32_to_cpu(priv->card_alive.log_event_table_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_legacy_write_direct32(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_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- /* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "0x%08x:%04u\n",
- time, ev);
- } else {
- IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
- trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
- time, ev);
- }
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
- time, data, ev);
- trace_iwlwifi_legacy_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;
-}
-
-/**
- * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl3945_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 = iwl3945_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
- } else {
- if (next_entry < size)
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
- }
- return pos;
-}
-
-#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl3945_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 */
- int pos = 0;
- size_t bufsz = 0;
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!iwl3945_hw_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return -EINVAL;
- }
-
- /* event log header */
- capacity = iwl_legacy_read_targ_mem(priv, base);
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- if (capacity > priv->cfg->base_params->max_event_log_size) {
- IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
- capacity, priv->cfg->base_params->max_event_log_size);
- capacity = priv->cfg->base_params->max_event_log_size;
- }
-
- if (next_entry > priv->cfg->base_params->max_event_log_size) {
- IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
- next_entry, priv->cfg->base_params->max_event_log_size);
- next_entry = priv->cfg->base_params->max_event_log_size;
- }
-
- 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;
- }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
- size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#else
- size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-
- IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
- size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
- if ((iwl_legacy_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 = iwl3945_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
-
- /* (then/else) start at top of log */
- pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#endif
- return pos;
-}
-
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
{
u32 inta, handled = 0;
@@ -1762,49 +1556,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
#endif
}
-static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- struct iwl3945_scan_channel *scan_ch)
-{
- const struct ieee80211_supported_band *sband;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added = 0;
- u8 channel = 0;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband) {
- IWL_ERR(priv, "invalid band\n");
- return added;
- }
-
- active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
-
- channel = iwl_legacy_get_single_channel_number(priv, band);
-
- if (channel) {
- scan_ch->channel = channel;
- scan_ch->type = 0; /* 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->tpc.dsp_atten = 110;
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
-}
-
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
@@ -2816,6 +2567,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
enum ieee80211_band band;
bool is_active = false;
int ret;
+ u16 len;
lockdep_assert_held(&priv->mutex);
@@ -2834,17 +2586,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
- u16 interval = 0;
+ u16 interval;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
- if (priv->is_internal_short_scan)
- interval = 0;
- else
- interval = vif->bss_conf.beacon_int;
+ interval = vif->bss_conf.beacon_int;
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -2866,9 +2615,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan_suspend_time, interval);
}
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- } else if (priv->scan_request->n_ssids) {
+ 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++) {
@@ -2919,36 +2666,17 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
IWL_GOOD_CRC_TH_DISABLED;
- if (!priv->is_internal_short_scan) {
- scan->tx_cmd.len = cpu_to_le16(
- iwl_legacy_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)));
- } else {
- /* use bcast addr, will not be transmitted but must be valid */
- scan->tx_cmd.len = cpu_to_le16(
- iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- iwlegacy_bcast_addr, NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan)));
- }
+ len = iwl_legacy_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));
+ scan->tx_cmd.len = cpu_to_le16(len);
+
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
- if (priv->is_internal_short_scan) {
- scan->channel_count =
- iwl3945_get_single_channel_for_scan(priv, vif, band,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- } else {
- scan->channel_count =
- iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
- }
-
+ scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+ (void *)&scan->data[len], vif);
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
return -EIO;
@@ -3824,10 +3552,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
/* initialize force reset */
- priv->force_reset[IWL_RF_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_RF_RESET;
- priv->force_reset[IWL_FW_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+ priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
index 7157ba529680..14334668034e 100644
--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -488,134 +488,6 @@ static void iwl4965_bg_statistics_periodic(unsigned long data)
iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
}
-
-static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base,
- u32 start_idx, u32 num_events,
- u32 mode)
-{
- u32 i;
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (mode == 0)
- ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
- else
- 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);
- return;
- }
-
- /* Set starting address; reads will auto-increment */
- _iwl_legacy_write_direct32(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_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
- 0, time, ev);
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- trace_iwlwifi_legacy_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);
-}
-
-static void iwl4965_continuous_event_trace(struct iwl_priv *priv)
-{
- u32 capacity; /* event log capacity in # entries */
- u32 base; /* SRAM byte address of event log header */
- 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 */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- capacity = iwl_legacy_read_targ_mem(priv, base);
- num_wraps = iwl_legacy_read_targ_mem(priv,
- base + (2 * sizeof(u32)));
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv,
- base + (3 * sizeof(u32)));
- } else
- return;
-
- if (num_wraps == priv->event_log.num_wraps) {
- iwl4965_print_cont_event_trace(priv,
- base, priv->event_log.next_entry,
- next_entry - priv->event_log.next_entry,
- mode);
- priv->event_log.non_wraps_count++;
- } else {
- if ((num_wraps - priv->event_log.num_wraps) > 1)
- priv->event_log.wraps_more_count++;
- else
- priv->event_log.wraps_once_count++;
- trace_iwlwifi_legacy_dev_ucode_wrap_event(priv,
- num_wraps - priv->event_log.num_wraps,
- next_entry, priv->event_log.next_entry);
- if (next_entry < priv->event_log.next_entry) {
- iwl4965_print_cont_event_trace(priv, base,
- priv->event_log.next_entry,
- capacity - priv->event_log.next_entry,
- mode);
-
- iwl4965_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- } else {
- iwl4965_print_cont_event_trace(priv, base,
- next_entry, capacity - next_entry,
- mode);
-
- iwl4965_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- }
- }
- priv->event_log.num_wraps = num_wraps;
- priv->event_log.next_entry = next_entry;
-}
-
-/**
- * iwl4965_bg_ucode_trace - Timer callback to log ucode event
- *
- * The timer is continually set to execute every
- * UCODE_TRACE_PERIOD milliseconds after the last timer expired
- * this function is to perform continuous uCode event logging operation
- * if enabled
- */
-static void iwl4965_bg_ucode_trace(unsigned long data)
-{
- struct iwl_priv *priv = (struct iwl_priv *)data;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (priv->event_log.ucode_trace) {
- iwl4965_continuous_event_trace(priv);
- /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- }
-}
-
static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -1612,7 +1484,7 @@ static const char * const desc_lookup_text[] = {
"NMI_INTERRUPT_DATA_ACTION_PT",
"NMI_TRM_HW_ER",
"NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
+ "NMI_INTERRUPT_BREAK_POINT",
"DEBUG_0",
"DEBUG_1",
"DEBUG_2",
@@ -1711,209 +1583,6 @@ void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
pc, blink1, blink2, ilink1, ilink2, hcmd);
}
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl4965_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;
-
- if (priv->ucode_type == UCODE_INIT) {
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- } else {
- base = le32_to_cpu(priv->card_alive.log_event_table_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_legacy_write_direct32(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_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(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_legacy_dev_ucode_event(priv, 0,
- time, ev);
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- }
- } else {
- data = _iwl_legacy_read_direct32(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_legacy_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;
-}
-
-/**
- * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl4965_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 = iwl4965_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl4965_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl4965_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- } else {
- if (next_entry < size) {
- pos = iwl4965_print_event_log(priv, 0, next_entry,
- mode, pos, buf, bufsz);
- } else {
- pos = iwl4965_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- }
- }
- return pos;
-}
-
-#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl4965_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 */
- int pos = 0;
- size_t bufsz = 0;
-
- if (priv->ucode_type == UCODE_INIT) {
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- } else {
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- }
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv,
- "Invalid event log pointer 0x%08X for %s uCode\n",
- base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
- return -EINVAL;
- }
-
- /* event log header */
- capacity = iwl_legacy_read_targ_mem(priv, base);
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- 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;
- }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (!(iwl_legacy_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_LEGACY_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
- if ((iwl_legacy_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 = iwl4965_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
- /* (then/else) start at top of log */
- pos = iwl4965_print_event_log(priv, 0,
- next_entry, mode, pos, buf, bufsz);
- } else
- pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#else
- pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#endif
- return pos;
-}
-
static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
@@ -2773,20 +2442,10 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
- if (ret == 0) {
- priv->_4965.agg_tids_count++;
- IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
- priv->_4965.agg_tids_count);
- }
break;
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
- if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) {
- priv->_4965.agg_tids_count--;
- IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
- priv->_4965.agg_tids_count);
- }
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
ret = 0;
break;
@@ -2851,7 +2510,6 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u16 ch;
- unsigned long flags = 0;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2868,64 +2526,64 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
if (!iwl_legacy_is_associated_ctx(ctx))
goto out;
- if (priv->cfg->ops->lib->set_channel_switch) {
+ if (!priv->cfg->ops->lib->set_channel_switch)
+ goto out;
- ch = channel->hw_value;
- if (le16_to_cpu(ctx->active.channel) != ch) {
- ch_info = iwl_legacy_get_channel_info(priv,
- channel->band,
- ch);
- if (!iwl_legacy_is_channel_valid(ch_info)) {
- IWL_DEBUG_MAC80211(priv, "invalid channel\n");
- goto out;
- }
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->current_ht_config.smps = conf->smps_mode;
-
- /* Configure HT40 channels */
- ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ctx->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ctx->ht.is_40mhz = true;
- } else {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ctx->ht.is_40mhz = false;
- }
- } else
- ctx->ht.is_40mhz = false;
-
- if ((le16_to_cpu(ctx->staging.channel) != ch))
- ctx->staging.flags = 0;
-
- iwl_legacy_set_rxon_channel(priv, channel, ctx);
- iwl_legacy_set_rxon_ht(priv, ht_conf);
- iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
- ctx->vif);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- iwl_legacy_set_rate(priv);
- /*
- * at this point, staging_rxon has the
- * configuration for channel switch
- */
- set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
- priv->switch_channel = cpu_to_le16(ch);
- if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
- clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
- &priv->status);
- priv->switch_channel = 0;
- ieee80211_chswitch_done(ctx->vif, false);
- }
+ ch = channel->hw_value;
+ if (le16_to_cpu(ctx->active.channel) == ch)
+ goto out;
+
+ ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
+ if (!iwl_legacy_is_channel_valid(ch_info)) {
+ IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+ goto out;
+ }
+
+ spin_lock_irq(&priv->lock);
+
+ priv->current_ht_config.smps = conf->smps_mode;
+
+ /* Configure HT40 channels */
+ ctx->ht.enabled = conf_is_ht(conf);
+ if (ctx->ht.enabled) {
+ if (conf_is_ht40_minus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ } else if (conf_is_ht40_plus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ } else {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ ctx->ht.is_40mhz = false;
}
+ } else
+ ctx->ht.is_40mhz = false;
+
+ if ((le16_to_cpu(ctx->staging.channel) != ch))
+ ctx->staging.flags = 0;
+
+ iwl_legacy_set_rxon_channel(priv, channel, ctx);
+ iwl_legacy_set_rxon_ht(priv, ht_conf);
+ iwl_legacy_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+ spin_unlock_irq(&priv->lock);
+
+ iwl_legacy_set_rate(priv);
+ /*
+ * at this point, staging_rxon has the
+ * configuration for channel switch
+ */
+ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = cpu_to_le16(ch);
+ if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
+ clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = 0;
+ ieee80211_chswitch_done(ctx->vif, false);
}
+
out:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3034,10 +2692,6 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
priv->statistics_periodic.data = (unsigned long)priv;
priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
- init_timer(&priv->ucode_trace);
- priv->ucode_trace.data = (unsigned long)priv;
- priv->ucode_trace.function = iwl4965_bg_ucode_trace;
-
init_timer(&priv->watchdog);
priv->watchdog.data = (unsigned long)priv;
priv->watchdog.function = iwl_legacy_bg_watchdog;
@@ -3056,7 +2710,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
iwl_legacy_cancel_scan_deferred_work(priv);
del_timer_sync(&priv->statistics_periodic);
- del_timer_sync(&priv->ucode_trace);
}
static void iwl4965_init_hw_rates(struct iwl_priv *priv,
@@ -3132,13 +2785,9 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
- priv->_4965.agg_tids_count = 0;
/* initialize force reset */
- priv->force_reset[IWL_RF_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_RF_RESET;
- priv->force_reset[IWL_FW_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+ priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 822660483f9f..48ab9142af38 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -5,14 +5,16 @@ 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
-iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
-iwlagn-objs += iwl-rx.o iwl-tx.o iwl-sta.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 iwl-agn-hcmd.o iwl-agn-ict.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
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 2a88e73bb39c..01b49eb8c8ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -127,7 +125,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -140,7 +137,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity)
@@ -172,15 +168,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
static struct iwl_lib_ops iwl1000_lib = {
.set_hw_params = iwl1000_hw_set_hw_params,
- .rx_handler_setup = iwlagn_rx_handler_setup,
- .setup_deferred_work = iwlagn_setup_deferred_work,
- .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
- .update_chain_flags = iwl_update_chain_flags,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl1000_nic_config,
- },
+ .nic_config = iwl1000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -191,19 +179,8 @@ static struct iwl_lib_ops iwl1000_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .query_addr = iwlagn_eeprom_query_addr,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-};
-
-static const struct iwl_ops iwl1000_ops = {
- .lib = &iwl1000_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
+ .temperature = iwlagn_temperature,
};
static struct iwl_base_params iwl1000_base_params = {
@@ -224,6 +201,7 @@ 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,
};
#define IWL_DEVICE_1000 \
@@ -232,7 +210,7 @@ static struct iwl_ht_params iwl1000_ht_params = {
.ucode_api_min = IWL1000_UCODE_API_MIN, \
.eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
- .ops = &iwl1000_ops, \
+ .lib = &iwl1000_lib, \
.base_params = &iwl1000_base_params, \
.led_mode = IWL_LED_BLINK
@@ -253,7 +231,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
.ucode_api_min = IWL100_UCODE_API_MIN, \
.eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
- .ops = &iwl1000_ops, \
+ .lib = &iwl1000_lib, \
.base_params = &iwl1000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index 3df76f53a41b..0e13f0bb2e17 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -52,11 +50,13 @@
#define IWL2030_UCODE_API_MAX 5
#define IWL2000_UCODE_API_MAX 5
#define IWL105_UCODE_API_MAX 5
+#define IWL135_UCODE_API_MAX 5
/* Lowest firmware API version supported */
#define IWL2030_UCODE_API_MIN 5
#define IWL2000_UCODE_API_MIN 5
#define IWL105_UCODE_API_MIN 5
+#define IWL135_UCODE_API_MIN 5
#define IWL2030_FW_PRE "iwlwifi-2030-"
#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"
@@ -67,6 +67,9 @@
#define IWL105_FW_PRE "iwlwifi-105-"
#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"
+
static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
@@ -77,28 +80,11 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
/* NIC configuration for 2000 series */
static void iwl2000_nic_config(struct iwl_priv *priv)
{
- u16 radio_cfg;
-
- radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
- /* 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,
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
- EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
- EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
- /* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+ iwl_rf_config(priv);
if (priv->cfg->iq_invert)
iwl_set_bit(priv, CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
-
- if (priv->cfg->disable_otp_refresh)
- iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010);
}
static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
@@ -134,7 +120,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -147,7 +132,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity)
@@ -169,7 +153,7 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
- priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
+ priv->hw_params.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);
@@ -180,16 +164,7 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
static struct iwl_lib_ops iwl2000_lib = {
.set_hw_params = iwl2000_hw_set_hw_params,
- .rx_handler_setup = iwlagn_rx_handler_setup,
- .setup_deferred_work = iwlagn_bt_setup_deferred_work,
- .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
- .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
- .update_chain_flags = iwl_update_chain_flags,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl2000_nic_config,
- },
+ .nic_config = iwl2000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -200,38 +175,30 @@ static struct iwl_lib_ops iwl2000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .query_addr = iwlagn_eeprom_query_addr,
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .temperature = iwlagn_temperature,
};
-static const struct iwl_ops iwl2000_ops = {
- .lib = &iwl2000_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl2030_ops = {
- .lib = &iwl2000_lib,
- .hcmd = &iwlagn_bt_hcmd,
- .utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl105_ops = {
- .lib = &iwl2000_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl135_ops = {
- .lib = &iwl2000_lib,
- .hcmd = &iwlagn_bt_hcmd,
- .utils = &iwlagn_hcmd_utils,
+static struct iwl_lib_ops iwl2030_lib = {
+ .set_hw_params = iwl2000_hw_set_hw_params,
+ .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
+ .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
+ .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
+ .nic_config = iwl2000_nic_config,
+ .eeprom_ops = {
+ .regulatory_bands = {
+ EEPROM_REG_BAND_1_CHANNELS,
+ EEPROM_REG_BAND_2_CHANNELS,
+ EEPROM_REG_BAND_3_CHANNELS,
+ EEPROM_REG_BAND_4_CHANNELS,
+ EEPROM_REG_BAND_5_CHANNELS,
+ EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
+ EEPROM_REGULATORY_BAND_NO_HT40,
+ },
+ .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+ },
+ .temperature = iwlagn_temperature,
};
static struct iwl_base_params iwl2000_base_params = {
@@ -292,13 +259,12 @@ static struct iwl_bt_params iwl2030_bt_params = {
.ucode_api_min = IWL2000_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .ops = &iwl2000_ops, \
+ .lib = &iwl2000_lib, \
.base_params = &iwl2000_base_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
.led_mode = IWL_LED_RF_STATE, \
- .iq_invert = true, \
- .disable_otp_refresh = true \
+ .iq_invert = true \
struct iwl_cfg iwl2000_2bgn_cfg = {
.name = "2000 Series 2x2 BGN",
@@ -317,7 +283,7 @@ struct iwl_cfg iwl2000_2bg_cfg = {
.ucode_api_min = IWL2030_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .ops = &iwl2030_ops, \
+ .lib = &iwl2030_lib, \
.base_params = &iwl2030_base_params, \
.bt_params = &iwl2030_bt_params, \
.need_dc_calib = true, \
@@ -343,13 +309,14 @@ struct iwl_cfg iwl2030_2bg_cfg = {
.ucode_api_min = IWL105_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .ops = &iwl105_ops, \
+ .lib = &iwl2000_lib, \
.base_params = &iwl2000_base_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
.led_mode = IWL_LED_RF_STATE, \
.adv_pm = true, \
- .rx_with_siso_diversity = true \
+ .rx_with_siso_diversity = true, \
+ .iq_invert = true \
struct iwl_cfg iwl105_bg_cfg = {
.name = "105 Series 1x1 BG",
@@ -363,27 +330,28 @@ struct iwl_cfg iwl105_bgn_cfg = {
};
#define IWL_DEVICE_135 \
- .fw_name_pre = IWL105_FW_PRE, \
- .ucode_api_max = IWL105_UCODE_API_MAX, \
- .ucode_api_min = IWL105_UCODE_API_MIN, \
+ .fw_name_pre = IWL135_FW_PRE, \
+ .ucode_api_max = IWL135_UCODE_API_MAX, \
+ .ucode_api_min = IWL135_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .ops = &iwl135_ops, \
+ .lib = &iwl2030_lib, \
.base_params = &iwl2030_base_params, \
.bt_params = &iwl2030_bt_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
.led_mode = IWL_LED_RF_STATE, \
.adv_pm = true, \
- .rx_with_siso_diversity = true \
+ .rx_with_siso_diversity = true, \
+ .iq_invert = true \
struct iwl_cfg iwl135_bg_cfg = {
- .name = "105 Series 1x1 BG/BT",
+ .name = "135 Series 1x1 BG/BT",
IWL_DEVICE_135,
};
struct iwl_cfg iwl135_bgn_cfg = {
- .name = "105 Series 1x1 BGN/BT",
+ .name = "135 Series 1x1 BGN/BT",
IWL_DEVICE_135,
.ht_params = &iwl2000_ht_params,
};
@@ -391,3 +359,4 @@ struct iwl_cfg iwl135_bgn_cfg = {
MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 05ad47628b63..f9630a3c79fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -75,7 +75,7 @@ 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_5000_TEMPERATURE);
+ (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
temperature = le16_to_cpu(temp_calib[0]);
voltage = le16_to_cpu(temp_calib[1]);
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index e816c27db794..3eeb12ebe6e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
@@ -48,6 +46,7 @@
#include "iwl-agn.h"
#include "iwl-agn-hw.h"
#include "iwl-5000-hw.h"
+#include "iwl-trans.h"
/* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 5
@@ -67,23 +66,10 @@
static void iwl5000_nic_config(struct iwl_priv *priv)
{
unsigned long flags;
- u16 radio_cfg;
- spin_lock_irqsave(&priv->lock, flags);
-
- radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
- /* 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,
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
- EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
- EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+ iwl_rf_config(priv);
- /* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+ spin_lock_irqsave(&priv->lock, flags);
/* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted),
@@ -171,7 +157,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -184,7 +169,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
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);
@@ -216,7 +200,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -229,7 +212,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
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);
@@ -333,21 +315,13 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return iwl_send_cmd_sync(priv, &hcmd);
+ return trans_send_cmd(&priv->trans, &hcmd);
}
static struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
- .rx_handler_setup = iwlagn_rx_handler_setup,
- .setup_deferred_work = iwlagn_setup_deferred_work,
- .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl5000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl5000_nic_config,
- },
+ .nic_config = iwl5000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -358,27 +332,14 @@ static struct iwl_lib_ops iwl5000_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .temperature = iwlagn_temperature,
};
static struct iwl_lib_ops iwl5150_lib = {
.set_hw_params = iwl5150_hw_set_hw_params,
- .rx_handler_setup = iwlagn_rx_handler_setup,
- .setup_deferred_work = iwlagn_setup_deferred_work,
- .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl5000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl5000_nic_config,
- },
+ .nic_config = iwl5000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -389,25 +350,8 @@ static struct iwl_lib_ops iwl5150_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
},
- .temp_ops = {
- .temperature = iwl5150_temperature,
- },
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-};
-
-static const struct iwl_ops iwl5000_ops = {
- .lib = &iwl5000_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl5150_ops = {
- .lib = &iwl5150_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
+ .temperature = iwl5150_temperature,
};
static struct iwl_base_params iwl5000_base_params = {
@@ -432,7 +376,7 @@ static struct iwl_ht_params iwl5000_ht_params = {
.ucode_api_min = IWL5000_UCODE_API_MIN, \
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \
- .ops = &iwl5000_ops, \
+ .lib = &iwl5000_lib, \
.base_params = &iwl5000_base_params, \
.led_mode = IWL_LED_BLINK
@@ -475,7 +419,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
.ucode_api_min = IWL5000_UCODE_API_MIN,
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
- .ops = &iwl5000_ops,
+ .lib = &iwl5000_lib,
.base_params = &iwl5000_base_params,
.ht_params = &iwl5000_ht_params,
.led_mode = IWL_LED_BLINK,
@@ -488,7 +432,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
.ucode_api_min = IWL5150_UCODE_API_MIN, \
.eeprom_ver = EEPROM_5050_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
- .ops = &iwl5150_ops, \
+ .lib = &iwl5150_lib, \
.base_params = &iwl5000_base_params, \
.need_dc_calib = true, \
.led_mode = IWL_LED_BLINK, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 5b150bc70b06..973d1972e8cc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -47,6 +45,7 @@
#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-6000-hw.h"
+#include "iwl-trans.h"
/* Highest firmware API version supported */
#define IWL6000_UCODE_API_MAX 4
@@ -98,21 +97,7 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
/* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv)
{
- u16 radio_cfg;
-
- radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
- /* 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,
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
- EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
- EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
- /* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+ iwl_rf_config(priv);
/* no locking required for register write */
if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
@@ -121,10 +106,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
}
/* do additional nic configuration if needed */
- if (priv->cfg->ops->nic &&
- priv->cfg->ops->nic->additional_nic_config) {
- priv->cfg->ops->nic->additional_nic_config(priv);
- }
+ if (priv->cfg->additional_nic_config)
+ priv->cfg->additional_nic_config(priv);
}
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
@@ -160,7 +143,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -173,7 +155,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity)
@@ -195,7 +176,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
- priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
+ priv->hw_params.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);
@@ -272,21 +253,13 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return iwl_send_cmd_sync(priv, &hcmd);
+ return trans_send_cmd(&priv->trans, &hcmd);
}
static struct iwl_lib_ops iwl6000_lib = {
.set_hw_params = iwl6000_hw_set_hw_params,
- .rx_handler_setup = iwlagn_rx_handler_setup,
- .setup_deferred_work = iwlagn_setup_deferred_work,
- .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl6000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl6000_nic_config,
- },
+ .nic_config = iwl6000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -297,29 +270,18 @@ static struct iwl_lib_ops iwl6000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .temperature = iwlagn_temperature,
};
static struct iwl_lib_ops iwl6030_lib = {
.set_hw_params = iwl6000_hw_set_hw_params,
- .rx_handler_setup = iwlagn_bt_rx_handler_setup,
- .setup_deferred_work = iwlagn_bt_setup_deferred_work,
+ .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
+ .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
- .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl6000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl6000_nic_config,
- },
+ .nic_config = iwl6000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -330,48 +292,9 @@ static struct iwl_lib_ops iwl6030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-};
-
-static struct iwl_nic_ops iwl6050_nic_ops = {
- .additional_nic_config = &iwl6050_additional_nic_config,
-};
-
-static struct iwl_nic_ops iwl6150_nic_ops = {
- .additional_nic_config = &iwl6150_additional_nic_config,
-};
-
-static const struct iwl_ops iwl6000_ops = {
- .lib = &iwl6000_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl6050_ops = {
- .lib = &iwl6000_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
- .nic = &iwl6050_nic_ops,
-};
-
-static const struct iwl_ops iwl6150_ops = {
- .lib = &iwl6000_lib,
- .hcmd = &iwlagn_hcmd,
- .utils = &iwlagn_hcmd_utils,
- .nic = &iwl6150_nic_ops,
-};
-
-static const struct iwl_ops iwl6030_ops = {
- .lib = &iwl6030_lib,
- .hcmd = &iwlagn_bt_hcmd,
- .utils = &iwlagn_hcmd_utils,
+ .temperature = iwlagn_temperature,
};
static struct iwl_base_params iwl6000_base_params = {
@@ -447,7 +370,7 @@ static struct iwl_bt_params iwl6000_bt_params = {
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.eeprom_ver = EEPROM_6005_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
- .ops = &iwl6000_ops, \
+ .lib = &iwl6000_lib, \
.base_params = &iwl6000_g2_base_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
@@ -475,7 +398,7 @@ struct iwl_cfg iwl6005_2bg_cfg = {
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.eeprom_ver = EEPROM_6030_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
- .ops = &iwl6030_ops, \
+ .lib = &iwl6030_lib, \
.base_params = &iwl6000_g2_base_params, \
.bt_params = &iwl6000_bt_params, \
.need_dc_calib = true, \
@@ -556,7 +479,7 @@ struct iwl_cfg iwl130_bg_cfg = {
.valid_rx_ant = ANT_BC, /* .cfg overwrite */ \
.eeprom_ver = EEPROM_6000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
- .ops = &iwl6000_ops, \
+ .lib = &iwl6000_lib, \
.base_params = &iwl6000_base_params, \
.pa_type = IWL_PA_INTERNAL, \
.led_mode = IWL_LED_BLINK
@@ -583,7 +506,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
.ucode_api_min = IWL6050_UCODE_API_MIN, \
.valid_tx_ant = ANT_AB, /* .cfg overwrite */ \
.valid_rx_ant = ANT_AB, /* .cfg overwrite */ \
- .ops = &iwl6050_ops, \
+ .lib = &iwl6000_lib, \
+ .additional_nic_config = iwl6050_additional_nic_config, \
.eeprom_ver = EEPROM_6050_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \
.base_params = &iwl6050_base_params, \
@@ -606,7 +530,8 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \
- .ops = &iwl6150_ops, \
+ .lib = &iwl6000_lib, \
+ .additional_nic_config = iwl6150_additional_nic_config, \
.eeprom_ver = EEPROM_6150_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \
.base_params = &iwl6050_base_params, \
@@ -632,7 +557,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
- .ops = &iwl6000_ops,
+ .lib = &iwl6000_lib,
.base_params = &iwl6000_base_params,
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index c9255def1080..72d6297602b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -66,6 +66,8 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-agn-calib.h"
+#include "iwl-trans.h"
+#include "iwl-agn.h"
/*****************************************************************************
* INIT calibrations framework
@@ -87,6 +89,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD,
+ .flags = CMD_SYNC,
};
for (i = 0; i < IWL_CALIB_MAX; i++) {
@@ -95,7 +98,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
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 = iwl_send_cmd_sync(priv, &hcmd);
+ ret = trans_send_cmd(&priv->trans, &hcmd);
if (ret) {
IWL_ERR(priv, "Error %d iteration %d\n",
ret, i);
@@ -481,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 iwl_send_cmd(priv, &cmd_out);
+ return trans_send_cmd(&priv->trans, &cmd_out);
}
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
@@ -545,7 +548,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 iwl_send_cmd(priv, &cmd_out);
+ return trans_send_cmd(&priv->trans, &cmd_out);
}
void iwl_init_sensitivity(struct iwl_priv *priv)
@@ -837,6 +840,65 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
active_chains);
}
+static void iwlagn_gain_computation(struct iwl_priv *priv,
+ u32 average_noise[NUM_RX_CHAINS],
+ u16 min_average_noise_antenna_i,
+ u32 min_average_noise,
+ u8 default_chain)
+{
+ int i;
+ s32 delta_g;
+ struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+
+ /*
+ * Find Gain Code for the chains based on "default chain"
+ */
+ for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) {
+ if ((data->disconn_array[i])) {
+ data->delta_gain_code[i] = 0;
+ continue;
+ }
+
+ delta_g = (priv->cfg->base_params->chain_noise_scale *
+ ((s32)average_noise[default_chain] -
+ (s32)average_noise[i])) / 1500;
+
+ /* bound gain by 2 bits value max, 3rd bit is sign */
+ data->delta_gain_code[i] =
+ min(abs(delta_g),
+ (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
+
+ if (delta_g < 0)
+ /*
+ * set negative sign ...
+ * note to Intel developers: This is uCode API format,
+ * not the format of any internal device registers.
+ * Do not change this format for e.g. 6050 or similar
+ * devices. Change format only if more resolution
+ * (i.e. more than 2 bits magnitude) is needed.
+ */
+ data->delta_gain_code[i] |= (1 << 2);
+ }
+
+ IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n",
+ data->delta_gain_code[1], data->delta_gain_code[2]);
+
+ if (!data->radio_write) {
+ struct iwl_calib_chain_noise_gain_cmd cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ iwl_set_calib_hdr(&cmd.hdr,
+ 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,
+ CMD_ASYNC, sizeof(cmd), &cmd);
+
+ data->radio_write = 1;
+ data->state = IWL_CHAIN_NOISE_CALIBRATED;
+ }
+}
/*
* Accumulate 16 beacons of signal and noise statistics for each of
@@ -991,16 +1053,14 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
min_average_noise, min_average_noise_antenna_i);
- if (priv->cfg->ops->utils->gain_computation)
- priv->cfg->ops->utils->gain_computation(priv, average_noise,
+ iwlagn_gain_computation(priv, average_noise,
min_average_noise_antenna_i, min_average_noise,
find_first_chain(priv->cfg->valid_rx_ant));
/* Some power changes may have been made during the calibration.
* Update and commit the RXON
*/
- if (priv->cfg->ops->lib->update_chain_flags)
- priv->cfg->ops->lib->update_chain_flags(priv);
+ iwl_update_chain_flags(priv);
data->state = IWL_CHAIN_NOISE_DONE;
iwl_power_update_mode(priv, false);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
index 4ef4dd934254..a869fc9205d2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
@@ -71,13 +71,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv);
void iwl_init_sensitivity(struct iwl_priv *priv);
void iwl_reset_run_time_calib(struct iwl_priv *priv);
-static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
-{
-
- if (!priv->disable_chain_noise_cal &&
- priv->cfg->ops->utils->chain_noise_reset)
- priv->cfg->ops->utils->chain_noise_reset(priv);
-}
int iwl_send_calib_results(struct iwl_priv *priv);
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
index 2ef9448b1c20..b8347db850e7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -108,18 +108,16 @@ err:
int iwl_eeprom_check_sku(struct iwl_priv *priv)
{
- u16 eeprom_sku;
u16 radio_cfg;
- eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
-
if (!priv->cfg->sku) {
/* not using sku overwrite */
- priv->cfg->sku =
- ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >>
- EEPROM_SKU_CAP_BAND_POS);
- if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE)
- priv->cfg->sku |= IWL_SKU_N;
+ 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");
@@ -152,7 +150,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
{
- const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
+ const u8 *addr = iwl_eeprom_query_addr(priv,
EEPROM_MAC_ADDRESS);
memcpy(mac, addr, ETH_ALEN);
}
@@ -247,10 +245,10 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
/* the length is in 16-bit words, but we want entries */
- txp_len = (__le16 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
+ 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 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+ txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
for (idx = 0; idx < entries; idx++) {
txp = &txp_array[idx];
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
deleted file mode 100644
index 23fa93deae96..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/******************************************************************************
- *
- * 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
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-agn.h"
-
-int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
-{
- struct iwl_tx_ant_config_cmd tx_ant_cmd = {
- .valid = cpu_to_le32(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 iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD,
- sizeof(struct iwl_tx_ant_config_cmd),
- &tx_ant_cmd);
- } else {
- IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
- return -EOPNOTSUPP;
- }
-}
-
-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;
-}
-
-static void iwlagn_gain_computation(struct iwl_priv *priv,
- u32 average_noise[NUM_RX_CHAINS],
- u16 min_average_noise_antenna_i,
- u32 min_average_noise,
- u8 default_chain)
-{
- int i;
- s32 delta_g;
- struct iwl_chain_noise_data *data = &priv->chain_noise_data;
-
- /*
- * Find Gain Code for the chains based on "default chain"
- */
- for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) {
- if ((data->disconn_array[i])) {
- data->delta_gain_code[i] = 0;
- continue;
- }
-
- delta_g = (priv->cfg->base_params->chain_noise_scale *
- ((s32)average_noise[default_chain] -
- (s32)average_noise[i])) / 1500;
-
- /* bound gain by 2 bits value max, 3rd bit is sign */
- data->delta_gain_code[i] =
- min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
-
- if (delta_g < 0)
- /*
- * set negative sign ...
- * note to Intel developers: This is uCode API format,
- * not the format of any internal device registers.
- * Do not change this format for e.g. 6050 or similar
- * devices. Change format only if more resolution
- * (i.e. more than 2 bits magnitude) is needed.
- */
- data->delta_gain_code[i] |= (1 << 2);
- }
-
- IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n",
- data->delta_gain_code[1], data->delta_gain_code[2]);
-
- if (!data->radio_write) {
- struct iwl_calib_chain_noise_gain_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
-
- cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
- cmd.delta_gain_1 = data->delta_gain_code[1];
- cmd.delta_gain_2 = data->delta_gain_code[2];
- iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
- sizeof(cmd), &cmd, NULL);
-
- data->radio_write = 1;
- data->state = IWL_CHAIN_NOISE_CALIBRATED;
- }
-}
-
-static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
-{
- struct iwl_chain_noise_data *data = &priv->chain_noise_data;
- int ret;
-
- if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
- iwl_is_any_associated(priv)) {
- struct iwl_calib_chain_noise_reset_cmd cmd;
-
- /* clear data for chain noise calibration algorithm */
- data->chain_noise_a = 0;
- data->chain_noise_b = 0;
- data->chain_noise_c = 0;
- data->chain_signal_a = 0;
- data->chain_signal_b = 0;
- data->chain_signal_c = 0;
- data->beacon_count = 0;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
- ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
- sizeof(cmd), &cmd);
- if (ret)
- IWL_ERR(priv,
- "Could not send REPLY_PHY_CALIBRATION_CMD\n");
- data->state = IWL_CHAIN_NOISE_ACCUMULATE;
- IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
- }
-}
-
-static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
- struct ieee80211_tx_info *info,
- __le16 fc, __le32 *tx_flags)
-{
- if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
- info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
- info->flags & IEEE80211_TX_CTL_AMPDU)
- *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
-}
-
-/* Calc max signal level (dBm) among 3 possible receivers */
-static int iwlagn_calc_rssi(struct iwl_priv *priv,
- struct iwl_rx_phy_res *rx_resp)
-{
- /* data from PHY/DSP regarding signal strength, etc.,
- * contents are always there, not configurable by host
- */
- struct iwlagn_non_cfg_phy *ncphy =
- (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
- u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
- u8 agc;
-
- val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
- agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
-
- /* Find max rssi among 3 possible receivers.
- * These values are measured by the digital signal processor (DSP).
- * They should stay fairly constant even as the signal strength varies,
- * if the radio's automatic gain control (AGC) is working right.
- * AGC value (see below) will provide the "interesting" info.
- */
- val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
- rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
- IWLAGN_OFDM_RSSI_A_BIT_POS;
- rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
- IWLAGN_OFDM_RSSI_B_BIT_POS;
- val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
- rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
- IWLAGN_OFDM_RSSI_C_BIT_POS;
-
- max_rssi = max_t(u32, rssi_a, rssi_b);
- max_rssi = max_t(u32, max_rssi, rssi_c);
-
- IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
- rssi_a, rssi_b, rssi_c, max_rssi, agc);
-
- /* dBm = max_rssi dB - agc dB - constant.
- * Higher AGC (higher radio gain) means lower signal. */
- return max_rssi - agc - IWLAGN_RSSI_OFFSET;
-}
-
-static int iwlagn_set_pan_params(struct iwl_priv *priv)
-{
- struct iwl_wipan_params_cmd cmd;
- struct iwl_rxon_context *ctx_bss, *ctx_pan;
- int slot0 = 300, slot1 = 0;
- int ret;
-
- if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
- return 0;
-
- BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
-
- lockdep_assert_held(&priv->mutex);
-
- ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
- ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
-
- /*
- * If the PAN context is inactive, then we don't need
- * to update the PAN parameters, the last thing we'll
- * have done before it goes inactive is making the PAN
- * parameters be WLAN-only.
- */
- if (!ctx_pan->is_active)
- return 0;
-
- memset(&cmd, 0, sizeof(cmd));
-
- /* only 2 slots are currently allowed */
- cmd.num_slots = 2;
-
- cmd.slots[0].type = 0; /* BSS */
- cmd.slots[1].type = 1; /* PAN */
-
- if (priv->_agn.hw_roc_channel) {
- /* both contexts must be used for this to happen */
- slot1 = priv->_agn.hw_roc_duration;
- slot0 = IWL_MIN_SLOT_TIME;
- } else if (ctx_bss->vif && ctx_pan->vif) {
- int bcnint = ctx_pan->vif->bss_conf.beacon_int;
- int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
-
- /* should be set, but seems unused?? */
- cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
-
- if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
- bcnint &&
- bcnint != ctx_bss->vif->bss_conf.beacon_int) {
- IWL_ERR(priv,
- "beacon intervals don't match (%d, %d)\n",
- ctx_bss->vif->bss_conf.beacon_int,
- ctx_pan->vif->bss_conf.beacon_int);
- } else
- bcnint = max_t(int, bcnint,
- ctx_bss->vif->bss_conf.beacon_int);
- if (!bcnint)
- bcnint = DEFAULT_BEACON_INTERVAL;
- slot0 = bcnint / 2;
- slot1 = bcnint - slot0;
-
- if (test_bit(STATUS_SCAN_HW, &priv->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;
- slot0 = IWL_MIN_SLOT_TIME;
- }
- } else if (ctx_pan->vif) {
- slot0 = 0;
- slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
- ctx_pan->vif->bss_conf.beacon_int;
- slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
-
- if (test_bit(STATUS_SCAN_HW, &priv->status)) {
- slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
- slot1 = IWL_MIN_SLOT_TIME;
- }
- }
-
- cmd.slots[0].width = cpu_to_le16(slot0);
- cmd.slots[1].width = cpu_to_le16(slot1);
-
- ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
- if (ret)
- IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
-
- return ret;
-}
-
-struct iwl_hcmd_ops iwlagn_hcmd = {
- .commit_rxon = iwlagn_commit_rxon,
- .set_rxon_chain = iwlagn_set_rxon_chain,
- .set_tx_ant = iwlagn_send_tx_ant_config,
- .send_bt_config = iwl_send_bt_config,
- .set_pan_params = iwlagn_set_pan_params,
-};
-
-struct iwl_hcmd_ops iwlagn_bt_hcmd = {
- .commit_rxon = iwlagn_commit_rxon,
- .set_rxon_chain = iwlagn_set_rxon_chain,
- .set_tx_ant = iwlagn_send_tx_ant_config,
- .send_bt_config = iwlagn_send_advance_bt_config,
- .set_pan_params = iwlagn_set_pan_params,
-};
-
-struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
- .build_addsta_hcmd = iwlagn_build_addsta_hcmd,
- .gain_computation = iwlagn_gain_computation,
- .chain_noise_reset = iwlagn_chain_noise_reset,
- .tx_cmd_protection = iwlagn_tx_cmd_protection,
- .calc_rssi = iwlagn_calc_rssi,
- .request_scan = iwlagn_request_scan,
- .post_scan = iwlagn_post_scan,
-};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
index 7bd19f4e66de..0e5b842529c4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
@@ -81,13 +81,6 @@
/* RSSI to dBm */
#define IWLAGN_RSSI_OFFSET 44
-/* PCI registers */
-#define PCI_CFG_RETRY_TIMEOUT 0x041
-
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
-
#define IWLAGN_DEFAULT_TX_RETRY 15
/* Limit range of txpower output target to be between these values */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
deleted file mode 100644
index 0d5fda44c3a3..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/******************************************************************************
- *
- * 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
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/etherdevice.h>
-#include <linux/sched.h>
-#include <linux/gfp.h>
-#include <net/mac80211.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-agn.h"
-#include "iwl-helpers.h"
-
-#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
-
-/* Free dram table */
-void iwl_free_isr_ict(struct iwl_priv *priv)
-{
- if (priv->_agn.ict_tbl_vir) {
- dma_free_coherent(&priv->pci_dev->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- priv->_agn.ict_tbl_vir,
- priv->_agn.ict_tbl_dma);
- priv->_agn.ict_tbl_vir = NULL;
- }
-}
-
-
-/* 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->_agn.ict_tbl_vir =
- dma_alloc_coherent(&priv->pci_dev->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- &priv->_agn.ict_tbl_dma, GFP_KERNEL);
- if (!priv->_agn.ict_tbl_vir)
- return -ENOMEM;
-
- /* align table to PAGE_SIZE boundary */
- priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE);
-
- IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
- (unsigned long long)priv->_agn.ict_tbl_dma,
- (unsigned long long)priv->_agn.aligned_ict_tbl_dma,
- (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
-
- priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir +
- (priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma);
-
- IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
- priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir,
- (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
-
- /* reset table and index to all 0 */
- memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
- priv->_agn.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->_agn.ict_tbl_vir)
- return 0;
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_disable_interrupts(priv);
-
- memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
-
- val = priv->_agn.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->_agn.aligned_ict_tbl_dma);
-
- iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
- priv->_agn.use_ict = true;
- priv->_agn.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->_agn.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->_agn.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->_agn.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->_agn.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->_agn.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->_agn.ict_tbl[priv->_agn.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->_agn.ict_tbl[priv->_agn.ict_index]) {
-
- val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]);
- IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
- priv->_agn.ict_index,
- le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]));
- priv->_agn.ict_tbl[priv->_agn.ict_index] = 0;
- priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.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->_agn.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->_agn.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->_agn.inta)
- iwl_enable_interrupts(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- return IRQ_NONE;
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index f803fb62f8bc..3bee0f119bcd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -39,6 +39,7 @@
#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)
{
@@ -52,73 +53,73 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
switch (status) {
case TX_STATUS_POSTPONE_DELAY:
- priv->_agn.reply_tx_stats.pp_delay++;
+ priv->reply_tx_stats.pp_delay++;
break;
case TX_STATUS_POSTPONE_FEW_BYTES:
- priv->_agn.reply_tx_stats.pp_few_bytes++;
+ priv->reply_tx_stats.pp_few_bytes++;
break;
case TX_STATUS_POSTPONE_BT_PRIO:
- priv->_agn.reply_tx_stats.pp_bt_prio++;
+ priv->reply_tx_stats.pp_bt_prio++;
break;
case TX_STATUS_POSTPONE_QUIET_PERIOD:
- priv->_agn.reply_tx_stats.pp_quiet_period++;
+ priv->reply_tx_stats.pp_quiet_period++;
break;
case TX_STATUS_POSTPONE_CALC_TTAK:
- priv->_agn.reply_tx_stats.pp_calc_ttak++;
+ priv->reply_tx_stats.pp_calc_ttak++;
break;
case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
- priv->_agn.reply_tx_stats.int_crossed_retry++;
+ priv->reply_tx_stats.int_crossed_retry++;
break;
case TX_STATUS_FAIL_SHORT_LIMIT:
- priv->_agn.reply_tx_stats.short_limit++;
+ priv->reply_tx_stats.short_limit++;
break;
case TX_STATUS_FAIL_LONG_LIMIT:
- priv->_agn.reply_tx_stats.long_limit++;
+ priv->reply_tx_stats.long_limit++;
break;
case TX_STATUS_FAIL_FIFO_UNDERRUN:
- priv->_agn.reply_tx_stats.fifo_underrun++;
+ priv->reply_tx_stats.fifo_underrun++;
break;
case TX_STATUS_FAIL_DRAIN_FLOW:
- priv->_agn.reply_tx_stats.drain_flow++;
+ priv->reply_tx_stats.drain_flow++;
break;
case TX_STATUS_FAIL_RFKILL_FLUSH:
- priv->_agn.reply_tx_stats.rfkill_flush++;
+ priv->reply_tx_stats.rfkill_flush++;
break;
case TX_STATUS_FAIL_LIFE_EXPIRE:
- priv->_agn.reply_tx_stats.life_expire++;
+ priv->reply_tx_stats.life_expire++;
break;
case TX_STATUS_FAIL_DEST_PS:
- priv->_agn.reply_tx_stats.dest_ps++;
+ priv->reply_tx_stats.dest_ps++;
break;
case TX_STATUS_FAIL_HOST_ABORTED:
- priv->_agn.reply_tx_stats.host_abort++;
+ priv->reply_tx_stats.host_abort++;
break;
case TX_STATUS_FAIL_BT_RETRY:
- priv->_agn.reply_tx_stats.bt_retry++;
+ priv->reply_tx_stats.bt_retry++;
break;
case TX_STATUS_FAIL_STA_INVALID:
- priv->_agn.reply_tx_stats.sta_invalid++;
+ priv->reply_tx_stats.sta_invalid++;
break;
case TX_STATUS_FAIL_FRAG_DROPPED:
- priv->_agn.reply_tx_stats.frag_drop++;
+ priv->reply_tx_stats.frag_drop++;
break;
case TX_STATUS_FAIL_TID_DISABLE:
- priv->_agn.reply_tx_stats.tid_disable++;
+ priv->reply_tx_stats.tid_disable++;
break;
case TX_STATUS_FAIL_FIFO_FLUSHED:
- priv->_agn.reply_tx_stats.fifo_flush++;
+ priv->reply_tx_stats.fifo_flush++;
break;
case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL:
- priv->_agn.reply_tx_stats.insuff_cf_poll++;
+ priv->reply_tx_stats.insuff_cf_poll++;
break;
case TX_STATUS_FAIL_PASSIVE_NO_RX:
- priv->_agn.reply_tx_stats.fail_hw_drop++;
+ priv->reply_tx_stats.fail_hw_drop++;
break;
case TX_STATUS_FAIL_NO_BEACON_ON_RADAR:
- priv->_agn.reply_tx_stats.sta_color_mismatch++;
+ priv->reply_tx_stats.sta_color_mismatch++;
break;
default:
- priv->_agn.reply_tx_stats.unknown++;
+ priv->reply_tx_stats.unknown++;
break;
}
}
@@ -129,43 +130,43 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
switch (status) {
case AGG_TX_STATE_UNDERRUN_MSK:
- priv->_agn.reply_agg_tx_stats.underrun++;
+ priv->reply_agg_tx_stats.underrun++;
break;
case AGG_TX_STATE_BT_PRIO_MSK:
- priv->_agn.reply_agg_tx_stats.bt_prio++;
+ priv->reply_agg_tx_stats.bt_prio++;
break;
case AGG_TX_STATE_FEW_BYTES_MSK:
- priv->_agn.reply_agg_tx_stats.few_bytes++;
+ priv->reply_agg_tx_stats.few_bytes++;
break;
case AGG_TX_STATE_ABORT_MSK:
- priv->_agn.reply_agg_tx_stats.abort++;
+ priv->reply_agg_tx_stats.abort++;
break;
case AGG_TX_STATE_LAST_SENT_TTL_MSK:
- priv->_agn.reply_agg_tx_stats.last_sent_ttl++;
+ priv->reply_agg_tx_stats.last_sent_ttl++;
break;
case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK:
- priv->_agn.reply_agg_tx_stats.last_sent_try++;
+ priv->reply_agg_tx_stats.last_sent_try++;
break;
case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK:
- priv->_agn.reply_agg_tx_stats.last_sent_bt_kill++;
+ priv->reply_agg_tx_stats.last_sent_bt_kill++;
break;
case AGG_TX_STATE_SCD_QUERY_MSK:
- priv->_agn.reply_agg_tx_stats.scd_query++;
+ priv->reply_agg_tx_stats.scd_query++;
break;
case AGG_TX_STATE_TEST_BAD_CRC32_MSK:
- priv->_agn.reply_agg_tx_stats.bad_crc32++;
+ priv->reply_agg_tx_stats.bad_crc32++;
break;
case AGG_TX_STATE_RESPONSE_MSK:
- priv->_agn.reply_agg_tx_stats.response++;
+ priv->reply_agg_tx_stats.response++;
break;
case AGG_TX_STATE_DUMP_TX_MSK:
- priv->_agn.reply_agg_tx_stats.dump_tx++;
+ priv->reply_agg_tx_stats.dump_tx++;
break;
case AGG_TX_STATE_DELAY_TX_MSK:
- priv->_agn.reply_agg_tx_stats.delay_tx++;
+ priv->reply_agg_tx_stats.delay_tx++;
break;
default:
- priv->_agn.reply_agg_tx_stats.unknown++;
+ priv->reply_agg_tx_stats.unknown++;
break;
}
}
@@ -390,8 +391,7 @@ void iwl_check_abort_status(struct iwl_priv *priv,
}
}
-static void iwlagn_rx_reply_tx(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)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
@@ -400,6 +400,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
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;
@@ -408,9 +409,9 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
unsigned long flags;
if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
- IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
- "is out of range [0-%d] %d %d\n", txq_id,
- index, txq->q.n_bd, txq->q.write_ptr,
+ 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;
}
@@ -426,6 +427,11 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
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;
@@ -438,7 +444,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist) {
- IWL_WARN(priv, "receive reply tx with bt_kill\n");
+ IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n");
}
iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
@@ -478,27 +484,6 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-void iwlagn_rx_handler_setup(struct iwl_priv *priv)
-{
- /* init calibration handlers */
- priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
- iwlagn_rx_calib_result;
- priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
-
- /* set up notification wait support */
- spin_lock_init(&priv->_agn.notif_wait_lock);
- INIT_LIST_HEAD(&priv->_agn.notif_waits);
- init_waitqueue_head(&priv->_agn.notif_waitq);
-}
-
-void iwlagn_setup_deferred_work(struct iwl_priv *priv)
-{
- /*
- * nothing need to be done here anymore
- * still keep for future use if needed
- */
-}
-
int iwlagn_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) &&
@@ -540,8 +525,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
else
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
- return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd),
- &tx_power_cmd);
+ return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC,
+ sizeof(tx_power_cmd), &tx_power_cmd);
}
void iwlagn_temperature(struct iwl_priv *priv)
@@ -610,8 +595,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
return (address & ADDRESS_MSK) + (offset << 1);
}
-const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
- size_t offset)
+const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
{
u32 address = eeprom_indirect_address(priv, offset);
BUG_ON(address >= priv->cfg->base_params->eeprom_size);
@@ -622,367 +606,12 @@ struct iwl_mod_params iwlagn_mod_params = {
.amsdu_size_8K = 1,
.restart_fw = 1,
.plcp_check = true,
+ .bt_coex_active = true,
+ .no_sleep_autoadjust = true,
+ .power_level = IWL_POWER_INDEX_1,
/* the rest are 0 by default */
};
-void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
- unsigned long flags;
- int i;
- spin_lock_irqsave(&rxq->lock, flags);
- INIT_LIST_HEAD(&rxq->rx_free);
- INIT_LIST_HEAD(&rxq->rx_used);
- /* 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) {
- pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
- PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
- __iwl_free_pages(priv, rxq->pool[i].page);
- rxq->pool[i].page = NULL;
- }
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
- }
-
- 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);
-}
-
-int iwlagn_rx_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);
-
- return 0;
-}
-
-static void iwlagn_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);
-}
-
-int iwlagn_hw_nic_init(struct iwl_priv *priv)
-{
- unsigned long flags;
- struct iwl_rx_queue *rxq = &priv->rxq;
- int ret;
-
- /* nic_init */
- spin_lock_irqsave(&priv->lock, flags);
- priv->cfg->ops->lib->apm_ops.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);
-
- iwlagn_set_pwr_vmain(priv);
-
- priv->cfg->ops->lib->apm_ops.config(priv);
-
- /* Allocate the RX queue, or reset if it is already allocated */
- if (!rxq->bd) {
- ret = iwl_rx_queue_alloc(priv);
- if (ret) {
- IWL_ERR(priv, "Unable to initialize Rx queue\n");
- return -ENOMEM;
- }
- } else
- iwlagn_rx_queue_reset(priv, rxq);
-
- iwlagn_rx_replenish(priv);
-
- iwlagn_rx_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);
-
- /* Allocate or reset and init all Tx and Command queues */
- if (!priv->txq) {
- ret = iwlagn_txq_ctx_alloc(priv);
- if (ret)
- return ret;
- } else
- iwlagn_txq_ctx_reset(priv);
-
- 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;
-}
-
-/**
- * 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.
- */
-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)
- */
-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 = pci_map_page(priv->pci_dev, page, 0,
- PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
- /* 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);
-}
-
-void iwlagn_rx_replenish_now(struct iwl_priv *priv)
-{
- iwlagn_rx_allocate(priv, GFP_ATOMIC);
-
- iwlagn_rx_queue_restock(priv);
-}
-
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have its SKB set to NULL
- * This free routine walks the list of POOL entries and if SKB is set to
- * non NULL it is unmapped and freed
- */
-void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
- int i;
- for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
- if (rxq->pool[i].page != NULL) {
- pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
- PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
- __iwl_free_pages(priv, rxq->pool[i].page);
- rxq->pool[i].page = NULL;
- }
- }
-
- dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->bd_dma);
- dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
- rxq->bd = NULL;
- rxq->rb_stts = NULL;
-}
-
-int iwlagn_rxq_stop(struct iwl_priv *priv)
-{
-
- /* stop Rx DMA */
- iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
- iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
- FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-
- return 0;
-}
-
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
{
int idx = 0;
@@ -1126,7 +755,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen)
{
- struct sk_buff *skb = priv->_agn.offchan_tx_skb;
+ struct sk_buff *skb = priv->offchan_tx_skb;
if (skb->len < maxlen)
maxlen = skb->len;
@@ -1141,6 +770,7 @@ 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];
@@ -1211,7 +841,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
} else if (priv->scan_type == IWL_SCAN_OFFCH_TX) {
scan->suspend_time = 0;
scan->max_out_time =
- cpu_to_le32(1024 * priv->_agn.offchan_tx_timeout);
+ cpu_to_le32(1024 * priv->offchan_tx_timeout);
}
switch (priv->scan_type) {
@@ -1399,9 +1029,9 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan_ch = (void *)&scan->data[cmd_len];
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
scan_ch->channel =
- cpu_to_le16(priv->_agn.offchan_tx_chan->hw_value);
+ cpu_to_le16(priv->offchan_tx_chan->hw_value);
scan_ch->active_dwell =
- cpu_to_le16(priv->_agn.offchan_tx_timeout);
+ cpu_to_le16(priv->offchan_tx_timeout);
scan_ch->passive_dwell = 0;
/* Set txpower levels to defaults */
@@ -1411,7 +1041,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
* power level:
* scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
*/
- if (priv->_agn.offchan_tx_chan->band == IEEE80211_BAND_5GHZ)
+ 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));
@@ -1433,17 +1063,14 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
/* set scan bit here for PAN params */
set_bit(STATUS_SCAN_HW, &priv->status);
- if (priv->cfg->ops->hcmd->set_pan_params) {
- ret = priv->cfg->ops->hcmd->set_pan_params(priv);
- if (ret)
- return ret;
- }
+ ret = iwlagn_set_pan_params(priv);
+ if (ret)
+ return ret;
- ret = iwl_send_cmd_sync(priv, &cmd);
+ ret = trans_send_cmd(&priv->trans, &cmd);
if (ret) {
clear_bit(STATUS_SCAN_HW, &priv->status);
- if (priv->cfg->ops->hcmd->set_pan_params)
- priv->cfg->ops->hcmd->set_pan_params(priv);
+ iwlagn_set_pan_params(priv);
}
return ret;
@@ -1528,23 +1155,32 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
might_sleep();
memset(&flush_cmd, 0, sizeof(flush_cmd));
- flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK |
- IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (flush_control & BIT(IWL_RXON_CTX_BSS))
+ flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+ IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+ IWL_SCD_MGMT_MSK;
+ if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
+ (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
+ flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
+ IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
+ IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
+ IWL_PAN_SCD_MULTICAST_MSK;
+
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_control);
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(&priv->trans, &cmd);
}
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{
mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
- if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+ if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -1699,18 +1335,21 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
* (might be in monitor mode), or the interface is in
* IBSS mode (no proper uCode support for coex then).
*/
- if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
+ if (!iwlagn_mod_params.bt_coex_active ||
+ priv->iw_mode == NL80211_IFTYPE_ADHOC) {
basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
} else {
basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
- if (priv->cfg->bt_params &&
- priv->cfg->bt_params->bt_sco_disable)
+
+ if (!priv->bt_enable_pspoll)
basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
+ else
+ basic.flags &= ~IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
if (priv->bt_ch_announce)
basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
- IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", basic.flags);
+ IWL_DEBUG_COEX(priv, "BT coex flag: 0X%x\n", basic.flags);
}
priv->bt_enable_flag = basic.flags;
if (priv->bt_full_concurrent)
@@ -1720,7 +1359,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
sizeof(iwlagn_def_3w_lookup));
- IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
+ IWL_DEBUG_COEX(priv, "BT coex %s in %s mode\n",
basic.flags ? "active" : "disabled",
priv->bt_full_concurrent ?
"full concurrency" : "3-wire");
@@ -1728,19 +1367,97 @@ 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 = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(bt_cmd_2000), &bt_cmd_2000);
+ ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+ CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
} else {
memcpy(&bt_cmd_6000.basic, &basic,
sizeof(basic));
- ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(bt_cmd_6000), &bt_cmd_6000);
+ ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+ CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
}
if (ret)
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
+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);
+
+ /* Check whether AP or GO mode is active. */
+ if (rssi_ena) {
+ for_each_context(priv, ctx) {
+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_AP &&
+ iwl_is_associated_ctx(ctx)) {
+ found_ap = true;
+ break;
+ }
+ }
+ }
+
+ /*
+ * If disable was received or If GO/AP mode, disable RSSI
+ * measurements.
+ */
+ if (!rssi_ena || found_ap) {
+ if (priv->cur_rssi_ctx) {
+ ctx = priv->cur_rssi_ctx;
+ ieee80211_disable_rssi_reports(ctx->vif);
+ priv->cur_rssi_ctx = NULL;
+ }
+ return;
+ }
+
+ /*
+ * If rssi measurements need to be enabled, consider all cases now.
+ * Figure out how many contexts are active.
+ */
+ for_each_context(priv, ctx) {
+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
+ iwl_is_associated_ctx(ctx)) {
+ found_ctx = ctx;
+ break;
+ }
+ }
+
+ /*
+ * rssi monitor already enabled for the correct interface...nothing
+ * to do.
+ */
+ if (found_ctx == priv->cur_rssi_ctx)
+ return;
+
+ /*
+ * Figure out if rssi monitor is currently enabled, and needs
+ * to be changed. If rssi monitor is already enabled, disable
+ * it first else just enable rssi measurements on the
+ * interface found above.
+ */
+ if (priv->cur_rssi_ctx) {
+ ctx = priv->cur_rssi_ctx;
+ if (ctx->vif)
+ ieee80211_disable_rssi_reports(ctx->vif);
+ }
+
+ priv->cur_rssi_ctx = found_ctx;
+
+ if (!found_ctx)
+ return;
+
+ ieee80211_enable_rssi_reports(found_ctx->vif,
+ IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD,
+ IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD);
+}
+
+static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
+{
+ return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >>
+ BT_UART_MSG_FRAME3SCOESCO_POS;
+}
+
static void iwlagn_bt_traffic_change_work(struct work_struct *work)
{
struct iwl_priv *priv =
@@ -1758,7 +1475,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
* coex profile notifications. Ignore that since only bad consequence
* can be not matching debug print with actual state.
*/
- IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
+ IWL_DEBUG_COEX(priv, "BT traffic load changes: %d\n",
priv->bt_traffic_load);
switch (priv->bt_traffic_load) {
@@ -1793,23 +1510,43 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
if (test_bit(STATUS_SCAN_HW, &priv->status))
goto out;
- if (priv->cfg->ops->lib->update_chain_flags)
- priv->cfg->ops->lib->update_chain_flags(priv);
+ iwl_update_chain_flags(priv);
if (smps_request != -1) {
+ priv->current_ht_config.smps = smps_request;
for_each_context(priv, ctx) {
if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
ieee80211_request_smps(ctx->vif, smps_request);
}
}
+
+ /*
+ * Dynamic PS poll related functionality. Adjust RSSI measurements if
+ * necessary.
+ */
+ iwlagn_bt_coex_rssi_monitor(priv);
out:
mutex_unlock(&priv->mutex);
}
+/*
+ * If BT sco traffic, and RSSI monitor is enabled, move measurements to the
+ * correct interface or disable it if this is the last interface to be
+ * removed.
+ */
+void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv)
+{
+ if (priv->bt_is_sco &&
+ priv->bt_traffic_load == IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS)
+ iwlagn_bt_adjust_rssi_monitor(priv, true);
+ else
+ iwlagn_bt_adjust_rssi_monitor(priv, false);
+}
+
static void iwlagn_print_uartmsg(struct iwl_priv *priv,
struct iwl_bt_uart_msg *uart_msg)
{
- IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, "
+ IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, "
"Update Req = 0x%X",
(BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
BT_UART_MSG_FRAME1MSGTYPE_POS,
@@ -1818,7 +1555,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
(BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
BT_UART_MSG_FRAME1UPDATEREQ_POS);
- IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
+ IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
"Chl_SeqN = 0x%X, In band = 0x%X",
(BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
@@ -1829,7 +1566,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
(BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
BT_UART_MSG_FRAME2INBAND_POS);
- IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
+ IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
"ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",
(BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
BT_UART_MSG_FRAME3SCOESCO_POS,
@@ -1844,11 +1581,11 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
(BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
BT_UART_MSG_FRAME3OBEX_POS);
- IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X",
+ IWL_DEBUG_COEX(priv, "Idle duration = 0x%X",
(BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
BT_UART_MSG_FRAME4IDLEDURATION_POS);
- IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
+ IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
"eSCO Retransmissions = 0x%X",
(BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
BT_UART_MSG_FRAME5TXACTIVITY_POS,
@@ -1857,13 +1594,13 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
(BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
- IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
+ IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
(BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
(BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
BT_UART_MSG_FRAME6DISCOVERABLE_POS);
- IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Page = "
+ IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = "
"0x%X, Inquiry = 0x%X, Connectable = 0x%X",
(BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
@@ -1913,14 +1650,16 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
return;
}
- IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
- IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status);
- IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load);
- IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n",
+ IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
+ IWL_DEBUG_COEX(priv, " status: %d\n", coex->bt_status);
+ IWL_DEBUG_COEX(priv, " traffic load: %d\n", coex->bt_traffic_load);
+ IWL_DEBUG_COEX(priv, " CI compliance: %d\n",
coex->bt_ci_compliance);
iwlagn_print_uartmsg(priv, uart_msg);
priv->last_bt_traffic_load = priv->bt_traffic_load;
+ priv->bt_is_sco = iwlagn_bt_traffic_is_sco(uart_msg);
+
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
if (priv->bt_status != coex->bt_status ||
priv->last_bt_traffic_load != coex->bt_traffic_load) {
@@ -1954,15 +1693,12 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
{
- iwlagn_rx_handler_setup(priv);
priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
iwlagn_bt_coex_profile_notif;
}
void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv)
{
- iwlagn_setup_deferred_work(priv);
-
INIT_WORK(&priv->bt_traffic_change_work,
iwlagn_bt_traffic_change_work);
}
@@ -2274,9 +2010,9 @@ void iwlagn_init_notification_wait(struct iwl_priv *priv,
wait_entry->triggered = false;
wait_entry->aborted = false;
- spin_lock_bh(&priv->_agn.notif_wait_lock);
- list_add(&wait_entry->list, &priv->_agn.notif_waits);
- spin_unlock_bh(&priv->_agn.notif_wait_lock);
+ spin_lock_bh(&priv->notif_wait_lock);
+ list_add(&wait_entry->list, &priv->notif_waits);
+ spin_unlock_bh(&priv->notif_wait_lock);
}
int iwlagn_wait_notification(struct iwl_priv *priv,
@@ -2285,13 +2021,13 @@ int iwlagn_wait_notification(struct iwl_priv *priv,
{
int ret;
- ret = wait_event_timeout(priv->_agn.notif_waitq,
+ ret = wait_event_timeout(priv->notif_waitq,
wait_entry->triggered || wait_entry->aborted,
timeout);
- spin_lock_bh(&priv->_agn.notif_wait_lock);
+ spin_lock_bh(&priv->notif_wait_lock);
list_del(&wait_entry->list);
- spin_unlock_bh(&priv->_agn.notif_wait_lock);
+ spin_unlock_bh(&priv->notif_wait_lock);
if (wait_entry->aborted)
return -EIO;
@@ -2305,91 +2041,7 @@ int iwlagn_wait_notification(struct iwl_priv *priv,
void iwlagn_remove_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry)
{
- spin_lock_bh(&priv->_agn.notif_wait_lock);
+ spin_lock_bh(&priv->notif_wait_lock);
list_del(&wait_entry->list);
- spin_unlock_bh(&priv->_agn.notif_wait_lock);
-}
-
-int iwlagn_start_device(struct iwl_priv *priv)
-{
- int ret;
-
- if (iwl_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 = iwlagn_hw_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;
-}
-
-void iwlagn_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);
- iwl_synchronize_irq(priv);
-
- /* 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)) {
- iwlagn_txq_ctx_stop(priv);
- iwlagn_rxq_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);
+ spin_unlock_bh(&priv->notif_wait_lock);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 592b0cfcf717..3789ff4bf53b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -336,6 +336,12 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
}
#ifdef CONFIG_MAC80211_DEBUGFS
+/**
+ * Program the device to use fixed rate for frame transmit
+ * This is for debugging/testing only
+ * once the device start use fixed rate, we need to reload the module
+ * to being back the normal operation.
+ */
static void rs_program_fix_rate(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta)
{
@@ -348,13 +354,17 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
- lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate;
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+ /* testmode has higher priority to overwirte the fixed rate */
+ if (priv->tm_fixed_rate)
+ lq_sta->dbg_fixed_rate = priv->tm_fixed_rate;
+#endif
IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
- lq_sta->lq.sta_id, priv->dbg_fixed_rate);
+ lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
- if (priv->dbg_fixed_rate) {
- rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate);
+ if (lq_sta->dbg_fixed_rate) {
+ rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
false);
}
@@ -426,7 +436,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
ieee80211_stop_tx_ba_session(sta, tid);
}
} else {
- IWL_ERR(priv, "Aggregation not enabled for tid %d "
+ IWL_DEBUG_HT(priv, "Aggregation not enabled for tid %d "
"because load = %u\n", tid, load);
}
return ret;
@@ -1072,8 +1082,10 @@ done:
/* See if there's a better rate or modulation mode to try. */
if (sta && sta->supp_rates[sband->band])
rs_rate_scale_perform(priv, skb, sta, lq_sta);
-#ifdef CONFIG_MAC80211_DEBUGFS
- if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate)
+
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_SVTOOL)
+ if ((priv->tm_fixed_rate) &&
+ (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
rs_program_fix_rate(priv, lq_sta);
#endif
if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
@@ -2895,8 +2907,9 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
if (sband->band == IEEE80211_BAND_5GHZ)
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_agg = 0;
-
- priv->dbg_fixed_rate = 0;
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+ priv->tm_fixed_rate = 0;
+#endif
#ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->dbg_fixed_rate = 0;
#endif
@@ -3095,7 +3108,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
} else {
lq_sta->dbg_fixed_rate = 0;
- priv->dbg_fixed_rate = 0;
IWL_ERR(priv,
"Invalid antenna selection 0x%X, Valid is 0x%X\n",
ant_sel_tx, valid_tx_ant);
@@ -3123,9 +3135,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
return -EFAULT;
if (sscanf(buf, "%x", &parsed_rate) == 1)
- priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate;
+ lq_sta->dbg_fixed_rate = parsed_rate;
else
- priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0;
+ lq_sta->dbg_fixed_rate = 0;
rs_program_fix_rate(priv, lq_sta);
@@ -3155,7 +3167,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
lq_sta->total_failed, lq_sta->total_success,
lq_sta->active_legacy_rate);
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
- priv->dbg_fixed_rate);
+ 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," : "",
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 09f679d6046f..d42ef1763a71 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -30,6 +30,7 @@
#include "iwl-core.h"
#include "iwl-agn-calib.h"
#include "iwl-helpers.h"
+#include "iwl-trans.h"
static int iwlagn_disable_bss(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
@@ -39,7 +40,8 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+ ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd,
+ CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
@@ -64,7 +66,8 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P;
- ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+ ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd,
+ CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
send->dev_type = old_dev_type;
@@ -81,6 +84,22 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
return ret;
}
+static int iwlagn_disconn_pan(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct iwl_rxon_cmd *send)
+{
+ __le32 old_filter = send->filter_flags;
+ int ret;
+
+ send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC,
+ sizeof(*send), send);
+
+ send->filter_flags = old_filter;
+
+ return ret;
+}
+
static void iwlagn_update_qos(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
@@ -102,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags);
- ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
+ ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC,
sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm);
if (ret)
@@ -161,11 +180,8 @@ 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 = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
- sizeof(rxon_assoc), &rxon_assoc, NULL);
- if (ret)
- return ret;
-
+ ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd,
+ CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
return ret;
}
@@ -175,10 +191,21 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
int ret;
struct iwl_rxon_cmd *active = (void *)&ctx->active;
- if (ctx->ctxid == IWL_RXON_CTX_BSS)
+ if (ctx->ctxid == IWL_RXON_CTX_BSS) {
ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
- else
+ } else {
ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
+ if (ret)
+ return ret;
+ if (ctx->vif) {
+ ret = iwl_send_rxon_timing(priv, ctx);
+ if (ret) {
+ IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+ return ret;
+ }
+ ret = iwlagn_disconn_pan(priv, ctx, &ctx->staging);
+ }
+ }
if (ret)
return ret;
@@ -187,6 +214,8 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
* keys, so we have to restore those afterwards.
*/
iwl_clear_ucode_stations(priv, ctx);
+ /* update -- might need P2P now */
+ iwl_update_bcast_station(priv, ctx);
iwl_restore_stations(priv, ctx);
ret = iwl_restore_default_wep_keys(priv, ctx);
if (ret) {
@@ -205,10 +234,12 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
struct iwl_rxon_cmd *active = (void *)&ctx->active;
/* RXON timing must be before associated RXON */
- ret = iwl_send_rxon_timing(priv, ctx);
- if (ret) {
- IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
- return ret;
+ if (ctx->ctxid == IWL_RXON_CTX_BSS) {
+ ret = iwl_send_rxon_timing(priv, ctx);
+ if (ret) {
+ IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+ return ret;
+ }
}
/* QoS info may be cleared by previous un-assoc RXON */
iwlagn_update_qos(priv, ctx);
@@ -235,7 +266,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 = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+ ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC,
sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@@ -263,9 +294,107 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
return ret;
}
+
+ if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) &&
+ priv->cfg->ht_params->smps_mode)
+ ieee80211_request_smps(ctx->vif,
+ priv->cfg->ht_params->smps_mode);
+
return 0;
}
+int iwlagn_set_pan_params(struct iwl_priv *priv)
+{
+ struct iwl_wipan_params_cmd cmd;
+ struct iwl_rxon_context *ctx_bss, *ctx_pan;
+ int slot0 = 300, slot1 = 0;
+ int ret;
+
+ if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
+ return 0;
+
+ BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+ lockdep_assert_held(&priv->mutex);
+
+ ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
+ ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
+
+ /*
+ * If the PAN context is inactive, then we don't need
+ * to update the PAN parameters, the last thing we'll
+ * have done before it goes inactive is making the PAN
+ * parameters be WLAN-only.
+ */
+ if (!ctx_pan->is_active)
+ return 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ /* only 2 slots are currently allowed */
+ cmd.num_slots = 2;
+
+ cmd.slots[0].type = 0; /* BSS */
+ cmd.slots[1].type = 1; /* PAN */
+
+ if (priv->hw_roc_channel) {
+ /* both contexts must be used for this to happen */
+ slot1 = priv->hw_roc_duration;
+ slot0 = IWL_MIN_SLOT_TIME;
+ } else if (ctx_bss->vif && ctx_pan->vif) {
+ int bcnint = ctx_pan->beacon_int;
+ int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
+
+ /* should be set, but seems unused?? */
+ cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
+
+ if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
+ bcnint &&
+ bcnint != ctx_bss->beacon_int) {
+ IWL_ERR(priv,
+ "beacon intervals don't match (%d, %d)\n",
+ ctx_bss->beacon_int, ctx_pan->beacon_int);
+ } else
+ bcnint = max_t(int, bcnint,
+ ctx_bss->beacon_int);
+ if (!bcnint)
+ bcnint = DEFAULT_BEACON_INTERVAL;
+ slot0 = bcnint / 2;
+ slot1 = bcnint - slot0;
+
+ if (test_bit(STATUS_SCAN_HW, &priv->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;
+ slot0 = IWL_MIN_SLOT_TIME;
+ }
+ } else if (ctx_pan->vif) {
+ slot0 = 0;
+ slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
+ ctx_pan->beacon_int;
+ slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
+
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
+ slot1 = IWL_MIN_SLOT_TIME;
+ }
+ }
+
+ 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,
+ sizeof(cmd), &cmd);
+ if (ret)
+ IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
+
+ return ret;
+}
+
/**
* iwlagn_commit_rxon - commit staging_rxon to hardware
*
@@ -308,8 +437,8 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
/* always get timestamp with Rx frame */
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
- if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) {
- struct ieee80211_channel *chan = priv->_agn.hw_roc_channel;
+ 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);
@@ -375,13 +504,11 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
* do it now if after settings changed.
*/
iwl_set_tx_power(priv, priv->tx_power_next, false);
- return 0;
- }
- if (priv->cfg->ops->hcmd->set_pan_params) {
- ret = priv->cfg->ops->hcmd->set_pan_params(priv);
- if (ret)
- return ret;
+ /* make sure we are in the right PS state */
+ iwl_power_update_mode(priv, true);
+
+ return 0;
}
iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto);
@@ -405,6 +532,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (ret)
return ret;
+ ret = iwlagn_set_pan_params(priv);
+ if (ret)
+ return ret;
+
if (new_assoc)
return iwlagn_rxon_connect(priv, ctx);
@@ -446,9 +577,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
* set up the SM PS mode to OFF if an HT channel is
* configured.
*/
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- for_each_context(priv, ctx)
- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+ for_each_context(priv, ctx)
+ iwlagn_set_rxon_chain(priv, ctx);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
@@ -636,6 +766,38 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
ht_conf->single_chain_sufficient = !need_multiple;
}
+static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
+{
+ struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+ int ret;
+
+ if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
+ iwl_is_any_associated(priv)) {
+ struct iwl_calib_chain_noise_reset_cmd cmd;
+
+ /* clear data for chain noise calibration algorithm */
+ data->chain_noise_a = 0;
+ data->chain_noise_b = 0;
+ data->chain_noise_c = 0;
+ data->chain_signal_a = 0;
+ data->chain_signal_b = 0;
+ data->chain_signal_c = 0;
+ data->beacon_count = 0;
+
+ 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,
+ REPLY_PHY_CALIBRATION_CMD,
+ CMD_SYNC, sizeof(cmd), &cmd);
+ if (ret)
+ IWL_ERR(priv,
+ "Could not send REPLY_PHY_CALIBRATION_CMD\n");
+ data->state = IWL_CHAIN_NOISE_ACCUMULATE;
+ IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
+ }
+}
+
void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -692,7 +854,12 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
iwl_wake_any_queue(priv, ctx);
}
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+ if (ctx->ctxid == IWL_RXON_CTX_BSS)
+ priv->have_rekey_data = false;
}
+
+ iwlagn_bt_coex_rssi_monitor(priv);
}
if (ctx->ht.enabled) {
@@ -704,8 +871,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
iwl_set_rxon_ht(priv, &priv->current_ht_config);
}
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+ iwlagn_set_rxon_chain(priv, ctx);
if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
@@ -743,7 +909,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
iwl_power_update_mode(priv, false);
/* Enable RX differential gain and sensitivity calibrations */
- iwl_chain_noise_reset(priv);
+ if (!priv->disable_chain_noise_cal)
+ iwlagn_chain_noise_reset(priv);
priv->start_calib = 1;
}
@@ -770,6 +937,13 @@ void iwlagn_post_scan(struct iwl_priv *priv)
struct iwl_rxon_context *ctx;
/*
+ * We do not commit power settings while scan is pending,
+ * do it now if the settings changed.
+ */
+ iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
+ iwl_set_tx_power(priv, priv->tx_power_next, false);
+
+ /*
* Since setting the RXON may have been deferred while
* performing the scan, fire one off if needed
*/
@@ -777,6 +951,5 @@ void iwlagn_post_scan(struct iwl_priv *priv)
if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
iwlagn_commit_rxon(priv, ctx);
- if (priv->cfg->ops->hcmd->set_pan_params)
- priv->cfg->ops->hcmd->set_pan_params(priv);
+ iwlagn_set_pan_params(priv);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 0bd722cee5ae..37e624095e40 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -33,9 +33,10 @@
#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, u8 sta_id)
+iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
{
int i, r;
struct iwl_link_quality_cmd *link_cmd;
@@ -47,10 +48,15 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
return NULL;
}
+
+ lockdep_assert_held(&priv->mutex);
+
/* 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 */
if (priv->band == IEEE80211_BAND_5GHZ)
r = IWL_RATE_6M_INDEX;
+ else if (ctx && ctx->vif && ctx->vif->p2p)
+ r = IWL_RATE_6M_INDEX;
else
r = IWL_RATE_1M_INDEX;
@@ -115,7 +121,7 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
spin_unlock_irqrestore(&priv->sta_lock, flags);
/* Set up default rate scaling table in device's station table */
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ 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",
addr);
@@ -133,6 +139,14 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
return 0;
}
+/*
+ * static WEP keys
+ *
+ * For each context, the device has a table of 4 static WEP keys
+ * (one for each key index) that is updated with the following
+ * commands.
+ */
+
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
bool send_if_empty)
@@ -175,7 +189,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
cmd.len[0] = cmd_size;
if (not_empty || send_if_empty)
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(&priv->trans, &cmd);
else
return 0;
}
@@ -226,9 +240,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
return -EINVAL;
}
- keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->hw_key_idx = HW_KEY_DEFAULT;
- priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
+ keyconf->hw_key_idx = IWLAGN_HW_KEY_DEFAULT;
ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
@@ -241,166 +253,117 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
return ret;
}
-static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- __le16 key_flags = 0;
- struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-
- key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- if (keyconf->keylen == WEP_KEY_LEN_128)
- key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
-
- if (sta_id == ctx->bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
- priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
- priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
-
- memcpy(priv->stations[sta_id].keyinfo.key,
- keyconf->key, keyconf->keylen);
-
- memcpy(&priv->stations[sta_id].sta.key.key[3],
- keyconf->key, keyconf->keylen);
-
- if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
- == STA_KEY_FLG_NO_ENC)
- priv->stations[sta_id].sta.key.key_offset =
- iwl_get_free_ucode_key_index(priv);
- /* else, we are overriding an existing key => no need to allocated room
- * in uCode. */
+/*
+ * dynamic (per-station) keys
+ *
+ * The dynamic keys are a little more complicated. The device has
+ * a key cache of up to STA_KEY_MAX_NUM/STA_KEY_MAX_NUM_PAN keys.
+ * These are linked to stations by a table that contains an index
+ * into the key table for each station/key index/{mcast,unicast},
+ * i.e. it's basically an array of pointers like this:
+ * key_offset_t key_mapping[NUM_STATIONS][4][2];
+ * (it really works differently, but you can think of it as such)
+ *
+ * The key uploading and linking happens in the same command, the
+ * add station command with STA_MODIFY_KEY_MASK.
+ */
- WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
- "no space for a new key");
+static u8 iwlagn_key_sta_id(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+ u8 sta_id = IWL_INVALID_STATION;
- priv->stations[sta_id].sta.key.key_flags = key_flags;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ if (sta)
+ sta_id = iwl_sta_id(sta);
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ /*
+ * The device expects GTKs for station interfaces to be
+ * installed as GTKs for the AP station. If we have no
+ * station ID, then use the ap_sta_id in that case.
+ */
+ if (!sta && vif && vif_priv->ctx) {
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ sta_id = vif_priv->ctx->ap_sta_id;
+ break;
+ default:
+ /*
+ * In all other cases, the key will be
+ * used either for TX only or is bound
+ * to a station already.
+ */
+ break;
+ }
+ }
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ return sta_id;
}
-static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
+static int iwlagn_send_sta_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
+ u32 cmd_flags)
{
unsigned long flags;
- __le16 key_flags = 0;
+ __le16 key_flags;
struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- if (sta_id == ctx->bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ int i;
spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
- priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-
- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
- keyconf->keylen);
-
- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
- keyconf->keylen);
-
- if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
- == STA_KEY_FLG_NO_ENC)
- priv->stations[sta_id].sta.key.key_offset =
- iwl_get_free_ucode_key_index(priv);
- /* else, we are overriding an existing key => no need to allocated room
- * in uCode. */
-
- WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
- "no space for a new key");
-
- priv->stations[sta_id].sta.key.key_flags = key_flags;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags);
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
+ key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
-static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- int ret = 0;
- __le16 key_flags = 0;
-
- key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ key_flags |= STA_KEY_FLG_CCMP;
+ memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ key_flags |= STA_KEY_FLG_TKIP;
+ sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
+ for (i = 0; i < 5; i++)
+ sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
+ memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+ /* fall through */
+ case WLAN_CIPHER_SUITE_WEP40:
+ key_flags |= STA_KEY_FLG_WEP;
+ memcpy(&sta_cmd.key.key[3], keyconf->key, keyconf->keylen);
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
- if (sta_id == ctx->bcast_sta_id)
+ if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
key_flags |= STA_KEY_MULTICAST_MSK;
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
- priv->stations[sta_id].keyinfo.keylen = 16;
-
- if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
- == STA_KEY_FLG_NO_ENC)
- priv->stations[sta_id].sta.key.key_offset =
- iwl_get_free_ucode_key_index(priv);
- /* else, we are overriding an existing key => no need to allocated room
- * in uCode. */
-
- WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
- "no space for a new key");
-
- priv->stations[sta_id].sta.key.key_flags = key_flags;
-
+ /* key pointer (offset) */
+ sta_cmd.key.key_offset = keyconf->hw_key_idx;
- /* This copy is acutally not needed: we get the key with each TX */
- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
+ sta_cmd.key.key_flags = key_flags;
+ sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
+ sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return ret;
+ return iwl_send_add_sta(priv, &sta_cmd, cmd_flags);
}
void iwl_update_tkip_key(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
+ struct ieee80211_vif *vif,
struct ieee80211_key_conf *keyconf,
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
{
- u8 sta_id;
- unsigned long flags;
- int i;
+ u8 sta_id = iwlagn_key_sta_id(priv, vif, sta);
+
+ if (sta_id == IWL_INVALID_STATION)
+ return;
if (iwl_scan_cancel(priv)) {
/* cancel scan failed, just live w/ bad key and rely
@@ -408,121 +371,110 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
return;
}
- sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta);
- if (sta_id == IWL_INVALID_STATION)
- return;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-
- for (i = 0; i < 5; i++)
- priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
- cpu_to_le16(phase1key[i]);
-
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- 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);
-
+ iwlagn_send_sta_key(priv, keyconf, sta_id,
+ iv32, phase1key, CMD_ASYNC);
}
int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *keyconf,
- u8 sta_id)
+ struct ieee80211_sta *sta)
{
unsigned long flags;
- u16 key_flags;
- u8 keyidx;
struct iwl_addsta_cmd sta_cmd;
+ u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
+
+ /* if station isn't there, neither is the key */
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENOENT;
+
+ spin_lock_irqsave(&priv->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);
+
+ if (sta_id == IWL_INVALID_STATION)
+ return 0;
lockdep_assert_held(&priv->mutex);
ctx->key_mapping_keys--;
- spin_lock_irqsave(&priv->sta_lock, flags);
- key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
- keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
-
IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
keyconf->keyidx, sta_id);
- if (keyconf->keyidx != keyidx) {
- /* We need to remove a key with index different that the one
- * in the uCode. This means that the key we need to remove has
- * been replaced by another one with different index.
- * Don't do anything and return ok
- */
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
-
- if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
- IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
- keyconf->keyidx, key_flags);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
-
- if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
- &priv->ucode_key_table))
- IWL_ERR(priv, "index %d not used in uCode key table.\n",
- priv->stations[sta_id].sta.key.key_offset);
- memset(&priv->stations[sta_id].keyinfo, 0,
- sizeof(struct iwl_hw_key));
- memset(&priv->stations[sta_id].sta.key, 0,
- sizeof(struct iwl_keyinfo));
- priv->stations[sta_id].sta.key.key_flags =
- STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
- priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ if (!test_and_clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table))
+ IWL_ERR(priv, "offset %d not used in uCode key table.\n",
+ keyconf->hw_key_idx);
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ sta_cmd.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
+ sta_cmd.key.key_offset = WEP_INVALID_OFFSET;
+ sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
-int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- struct ieee80211_key_conf *keyconf, u8 sta_id)
+int iwl_set_dynamic_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf,
+ struct ieee80211_sta *sta)
{
+ struct ieee80211_key_seq seq;
+ u16 p1k[5];
int ret;
+ u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
+ const u8 *addr;
+
+ if (sta_id == IWL_INVALID_STATION)
+ return -EINVAL;
lockdep_assert_held(&priv->mutex);
+ keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
+ if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
+ return -ENOSPC;
+
ctx->key_mapping_keys++;
- keyconf->hw_key_idx = HW_KEY_DYNAMIC;
switch (keyconf->cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
- break;
case WLAN_CIPHER_SUITE_TKIP:
- ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id);
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+ if (sta)
+ addr = sta->addr;
+ else /* station mode case only */
+ addr = ctx->active.bssid_addr;
+
+ /* pre-fill phase 1 key into device cache */
+ ieee80211_get_key_rx_seq(keyconf, 0, &seq);
+ ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
+ ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
+ seq.tkip.iv32, p1k, CMD_SYNC);
break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ /* fall through */
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
- ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id);
+ ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
+ 0, NULL, CMD_SYNC);
break;
default:
- IWL_ERR(priv,
- "Unknown alg: %s cipher = %x\n", __func__,
- keyconf->cipher);
+ IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher);
ret = -EINVAL;
}
- IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
+ if (ret) {
+ ctx->key_mapping_keys--;
+ clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table);
+ }
+
+ IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
keyconf->cipher, keyconf->keylen, keyconf->keyidx,
- sta_id, ret);
+ sta ? sta->addr : NULL, ret);
return ret;
}
@@ -554,7 +506,7 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
priv->stations[sta_id].used |= IWL_STA_BCAST;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
IWL_ERR(priv,
"Unable to initialize rate scaling for bcast station.\n");
@@ -574,14 +526,14 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
* Only used by iwlagn. Placed here to have all bcast station management
* code together.
*/
-static int iwl_update_bcast_station(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
+int iwl_update_bcast_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
unsigned long flags;
struct iwl_link_quality_cmd *link_cmd;
u8 sta_id = ctx->bcast_sta_id;
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index 348f74f1c8e8..f501d742984c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -198,7 +198,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
/* Reschedule the ct_kill timer to occur in
* CT_KILL_EXIT_DURATION seconds to ensure we get a
* thermal update */
- IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
+ IWL_DEBUG_TEMP(priv, "schedule ct_kill exit timer\n");
mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
jiffies + CT_KILL_EXIT_DURATION * HZ);
}
@@ -208,15 +208,15 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
bool stop)
{
if (stop) {
- IWL_DEBUG_POWER(priv, "Stop all queues\n");
+ IWL_DEBUG_TEMP(priv, "Stop all queues\n");
if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw);
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Schedule 5 seconds CT_KILL Timer\n");
mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
jiffies + CT_KILL_EXIT_DURATION * HZ);
} else {
- IWL_DEBUG_POWER(priv, "Wake all queues\n");
+ IWL_DEBUG_TEMP(priv, "Wake all queues\n");
if (priv->mac80211_registered)
ieee80211_wake_queues(priv->hw);
}
@@ -232,7 +232,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
/* temperature timer expired, ready to go into CT_KILL state */
if (tt->state != IWL_TI_CT_KILL) {
- IWL_DEBUG_POWER(priv, "entering CT_KILL state when "
+ 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);
@@ -242,7 +242,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
{
- IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
+ IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");
/* make request to retrieve statistics information */
iwl_send_statistics_request(priv, CMD_SYNC, false);
/* Reschedule the ct_kill wait timer */
@@ -273,7 +273,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
(temp > tt->tt_previous_temp) &&
((temp - tt->tt_previous_temp) >
IWL_TT_INCREASE_MARGIN)) {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Temperature increase %d degree Celsius\n",
(temp - tt->tt_previous_temp));
}
@@ -338,9 +338,9 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
} else if (old_state == IWL_TI_CT_KILL &&
tt->state != IWL_TI_CT_KILL)
iwl_perform_ct_kill_task(priv, false);
- IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+ IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",
tt->state);
- IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+ IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
tt->tt_power_mode);
}
mutex_unlock(&priv->mutex);
@@ -397,7 +397,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
(temp > tt->tt_previous_temp) &&
((temp - tt->tt_previous_temp) >
IWL_TT_INCREASE_MARGIN)) {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Temperature increase %d "
"degree Celsius\n",
(temp - tt->tt_previous_temp));
@@ -467,13 +467,13 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
set_bit(STATUS_CT_KILL, &priv->status);
tt->state = old_state;
} else {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Thermal Throttling to new state: %u\n",
tt->state);
if (old_state != IWL_TI_CT_KILL &&
tt->state == IWL_TI_CT_KILL) {
if (force) {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Enter IWL_TI_CT_KILL\n");
set_bit(STATUS_CT_KILL, &priv->status);
iwl_perform_ct_kill_task(priv, true);
@@ -483,7 +483,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
}
} else if (old_state == IWL_TI_CT_KILL &&
tt->state != IWL_TI_CT_KILL) {
- IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+ IWL_DEBUG_TEMP(priv, "Exit IWL_TI_CT_KILL\n");
iwl_perform_ct_kill_task(priv, false);
}
}
@@ -568,7 +568,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+ IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
queue_work(priv->workqueue, &priv->ct_enter);
}
@@ -577,7 +577,7 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+ IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
queue_work(priv->workqueue, &priv->ct_exit);
}
@@ -603,7 +603,7 @@ void iwl_tt_handler(struct iwl_priv *priv)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+ IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
queue_work(priv->workqueue, &priv->tt_work);
}
@@ -618,7 +618,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
struct iwl_tt_trans *transaction;
- IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
+ IWL_DEBUG_TEMP(priv, "Initialize Thermal Throttling\n");
memset(tt, 0, sizeof(struct iwl_tt_mgmt));
@@ -638,7 +638,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
if (priv->cfg->base_params->adv_thermal_throttle) {
- IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+ 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) *
@@ -671,7 +671,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
priv->thermal_throttle.advanced_tt = true;
}
} else {
- IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+ IWL_DEBUG_TEMP(priv, "Legacy Thermal Throttling\n");
priv->thermal_throttle.advanced_tt = false;
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 4974cd7837cb..53bb59ee719d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -39,6 +39,7 @@
#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
+#include "iwl-trans.h"
/*
* mac80211 queues, ACs, hardware queues, FIFOs.
@@ -95,132 +96,8 @@ static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
return -EINVAL;
}
-/**
- * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
- */
-static void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- u16 byte_cnt)
-{
- struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
- 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;
-
- 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;
-
- switch (sec_ctl & TX_CMD_SEC_MSK) {
- case TX_CMD_SEC_CCM:
- len += CCMP_MIC_LEN;
- break;
- case TX_CMD_SEC_TKIP:
- len += TKIP_ICV_LEN;
- break;
- case TX_CMD_SEC_WEP:
- len += WEP_IV_LEN + WEP_ICV_LEN;
- break;
- }
-
- bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
-
- scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
-
- if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
- scd_bc_tbl[txq_id].
- tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
-}
-
-static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
-{
- struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
- int txq_id = txq->q.id;
- int read_ptr = txq->q.read_ptr;
- u8 sta_id = 0;
- __le16 bc_ent;
-
- WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
-
- if (txq_id != priv->cmd_queue)
- sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
-
- bc_ent = cpu_to_le16(1 | (sta_id << 12));
- scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
-
- if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
- scd_bc_tbl[txq_id].
- tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
-}
-
-static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
- u16 txq_id)
-{
- u32 tbl_dw_addr;
- u32 tbl_dw;
- u16 scd_q2ratid;
-
- scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
-
- tbl_dw_addr = priv->scd_base_addr +
- IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
-
- tbl_dw = iwl_read_targ_mem(priv, 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);
-
- return 0;
-}
-
-static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, 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,
- IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id),
- (0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
- (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-}
-
-void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
- int txq_id, u32 index)
-{
- iwl_write_direct32(priv, HBUS_TARG_WRPTR,
- (index & 0xff) | (txq_id << 8));
- iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index);
-}
-
-void iwlagn_tx_queue_set_status(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- int tx_fifo_id, int scd_retry)
-{
- int txq_id = txq->q.id;
- int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
-
- iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id),
- (active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
- (tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) |
- (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) |
- IWLAGN_SCD_QUEUE_STTS_REG_MSK);
-
- txq->sched_retry = scd_retry;
-
- IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n",
- active ? "Activate" : "Deactivate",
- scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
-}
-
-static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid)
+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 +
@@ -237,106 +114,14 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id,
return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
}
-void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv,
- struct ieee80211_sta *sta,
- int tid, int frame_limit)
+static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
+ struct ieee80211_tx_info *info,
+ __le16 fc, __le32 *tx_flags)
{
- int sta_id, tx_fifo, txq_id, ssn_idx;
- u16 ra_tid;
- unsigned long flags;
- struct iwl_tid_data *tid_data;
-
- sta_id = iwl_sta_id(sta);
- if (WARN_ON(sta_id == IWL_INVALID_STATION))
- return;
- if (WARN_ON(tid >= MAX_TID_COUNT))
- return;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- tid_data = &priv->stations[sta_id].tid[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);
-
- ra_tid = BUILD_RAxTID(sta_id, tid);
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Stop this Tx queue before configuring it */
- iwlagn_tx_queue_stop_scheduler(priv, txq_id);
-
- /* Map receiver-address / traffic-ID to this queue */
- iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
-
- /* Set this queue as a chain-building queue */
- iwl_set_bits_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, (1<<txq_id));
-
- /* enable aggregations for the queue */
- iwl_set_bits_prph(priv, IWLAGN_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);
- iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx);
-
- /* Set up Tx window size and frame limit for this queue */
- iwl_write_targ_mem(priv, priv->scd_base_addr +
- IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
- sizeof(u32),
- ((frame_limit <<
- IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
- IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
- ((frame_limit <<
- IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
- IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
-
- iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));
-
- /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
- iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
- u16 ssn_idx, u8 tx_fifo)
-{
- if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
- (IWLAGN_FIRST_AMPDU_QUEUE +
- priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
- IWL_ERR(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;
- }
-
- iwlagn_tx_queue_stop_scheduler(priv, txq_id);
-
- iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id));
-
- 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) */
- iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx);
-
- iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));
- iwl_txq_ctx_deactivate(priv, txq_id);
- iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
-
- return 0;
-}
-
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->lock and mac access
- */
-void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
-{
- iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
+ info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
+ info->flags & IEEE80211_TX_CTL_AMPDU)
+ *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
}
/*
@@ -353,19 +138,15 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
__le32 tx_flags = tx_cmd->tx_flags;
tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
tx_flags |= TX_CMD_FLG_ACK_MSK;
- if (ieee80211_is_mgmt(fc))
- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
- if (ieee80211_is_probe_resp(fc) &&
- !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
- tx_flags |= TX_CMD_FLG_TSF_MSK;
- } else {
- tx_flags &= (~TX_CMD_FLG_ACK_MSK);
- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
- }
+ else
+ tx_flags &= ~TX_CMD_FLG_ACK_MSK;
- if (ieee80211_is_back_req(fc))
+ if (ieee80211_is_probe_resp(fc))
+ tx_flags |= TX_CMD_FLG_TSF_MSK;
+ else if (ieee80211_is_back_req(fc))
tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
else if (info->band == IEEE80211_BAND_2GHZ &&
priv->cfg->bt_params &&
@@ -388,7 +169,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
}
- priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
+ iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags);
tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
if (ieee80211_is_mgmt(fc)) {
@@ -436,6 +217,18 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
if (ieee80211_is_data(fc)) {
tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+ if (priv->tm_fixed_rate) {
+ /*
+ * rate overwrite by testmode
+ * we not only send lq command to change rate
+ * we also re-enforce per data pkt base.
+ */
+ tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK;
+ memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate,
+ sizeof(tx_cmd->rate_n_flags));
+ }
+#endif
return;
}
@@ -497,8 +290,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
- ieee80211_get_tkip_key(keyconf, skb_frag,
- IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
break;
@@ -528,26 +320,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_sta *sta = info->control.sta;
struct iwl_station_priv *sta_priv = NULL;
- struct iwl_tx_queue *txq;
- struct iwl_queue *q;
- struct iwl_device_cmd *out_cmd;
- struct iwl_cmd_meta *out_meta;
- struct iwl_tx_cmd *tx_cmd;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct iwl_tx_cmd *tx_cmd;
int txq_id;
- dma_addr_t phys_addr = 0;
- dma_addr_t txcmd_phys;
- dma_addr_t scratch_phys;
- u16 len, firstlen, secondlen;
+
u16 seq_number = 0;
__le16 fc;
u8 hdr_len;
+ u16 len;
u8 sta_id;
- u8 wait_write_ptr = 0;
u8 tid = 0;
- u8 *qc = NULL;
unsigned long flags;
bool is_agg = false;
@@ -595,8 +378,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
- if (sta)
- sta_priv = (void *)sta->drv_priv;
+ if (info->control.sta)
+ sta_priv = (void *)info->control.sta->drv_priv;
if (sta_priv && sta_priv->asleep &&
(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
@@ -631,6 +414,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
spin_lock(&priv->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;
@@ -651,38 +435,13 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
}
}
- txq = &priv->txq[txq_id];
- q = &txq->q;
-
- if (unlikely(iwl_queue_space(q) < q->high_mark))
+ tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id);
+ if (unlikely(!tx_cmd))
goto drop_unlock_sta;
- /* 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_cmd = txq->cmd[q->write_ptr];
- out_meta = &txq->meta[q->write_ptr];
- tx_cmd = &out_cmd->cmd.tx;
- memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
- memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
-
- /*
- * 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.
- */
- out_cmd->hdr.cmd = REPLY_TX;
- out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
- INDEX_TO_SEQ(q->write_ptr)));
-
/* Copy MAC header from skb into command buffer */
memcpy(tx_cmd->hdr, hdr, hdr_len);
-
/* Total # bytes to be transmitted */
len = (u16)skb->len;
tx_cmd->len = cpu_to_le16(len);
@@ -697,54 +456,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc);
iwl_update_stats(priv, true, fc, len);
- /*
- * 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 = pci_map_single(priv->pci_dev,
- &out_cmd->hdr, firstlen,
- PCI_DMA_BIDIRECTIONAL);
- if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys)))
- goto drop_unlock_sta;
- dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
- dma_unmap_len_set(out_meta, len, firstlen);
- if (!ieee80211_has_morefrags(hdr->frame_control)) {
- 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 = pci_map_single(priv->pci_dev, skb->data + hdr_len,
- secondlen, PCI_DMA_TODEVICE);
- if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
- pci_unmap_single(priv->pci_dev,
- dma_unmap_addr(out_meta, mapping),
- dma_unmap_len(out_meta, len),
- PCI_DMA_BIDIRECTIONAL);
- goto drop_unlock_sta;
- }
- }
+ if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx))
+ goto drop_unlock_sta;
if (ieee80211_is_data_qos(fc)) {
priv->stations[sta_id].tid[tid].tfds_in_queue++;
@@ -753,55 +467,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
}
spin_unlock(&priv->sta_lock);
-
- /* 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 */
- pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
- firstlen, PCI_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(out_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 (info->flags & IEEE80211_TX_CTL_AMPDU)
- iwlagn_txq_update_byte_cnt_tbl(priv, txq,
- le16_to_cpu(tx_cmd->len));
-
- pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
- firstlen, PCI_DMA_BIDIRECTIONAL);
-
- trace_iwlwifi_dev_tx(priv,
- &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
- sizeof(struct iwl_tfd),
- &out_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);
spin_unlock_irqrestore(&priv->lock, flags);
/*
- * 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.
- */
-
- /*
* Avoid atomic ops if it isn't an associated client.
* Also, if this is a packet for aggregation, don't
* increase the counter because the ucode will stop
@@ -811,17 +479,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (sta_priv && sta_priv->client && !is_agg)
atomic_inc(&sta_priv->pending_frames);
- if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
- if (wait_write_ptr) {
- spin_lock_irqsave(&priv->lock, flags);
- txq->need_update = 1;
- iwl_txq_update_write_ptr(priv, txq);
- spin_unlock_irqrestore(&priv->lock, flags);
- } else {
- iwl_stop_queue(priv, txq);
- }
- }
-
return 0;
drop_unlock_sta:
@@ -831,178 +488,6 @@ drop_unlock_priv:
return -1;
}
-static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
- struct iwl_dma_ptr *ptr, size_t size)
-{
- ptr->addr = dma_alloc_coherent(&priv->pci_dev->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->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
- memset(ptr, 0, sizeof(*ptr));
-}
-
-/**
- * iwlagn_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwlagn_hw_txq_ctx_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++)
- if (txq_id == priv->cmd_queue)
- iwl_cmd_queue_free(priv);
- else
- iwl_tx_queue_free(priv, txq_id);
- }
- iwlagn_free_dma_ptr(priv, &priv->kw);
-
- iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
-
- /* free tx queue structure */
- iwl_free_txq_mem(priv);
-}
-
-/**
- * iwlagn_txq_ctx_alloc - allocate TX queue context
- * Allocate all Tx DMA structures and initialize them
- *
- * @param priv
- * @return error code
- */
-int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
-{
- int ret;
- int txq_id, slots_num;
- unsigned long flags;
-
- /* Free all tx/cmd queues and keep-warm buffer */
- iwlagn_hw_txq_ctx_free(priv);
-
- 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_bc_tbls;
- }
- /* 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_kw;
- }
-
- /* allocate tx queue structure */
- ret = iwl_alloc_txq_mem(priv);
- if (ret)
- goto error;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Turn off all Tx DMA fifos */
- iwlagn_txq_set_sched(priv, 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_tx_queue_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 ret;
-
- error:
- iwlagn_hw_txq_ctx_free(priv);
- iwlagn_free_dma_ptr(priv, &priv->kw);
- error_kw:
- iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
- error_bc_tbls:
- return ret;
-}
-
-void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
-{
- int txq_id, slots_num;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Turn off all Tx DMA fifos */
- iwlagn_txq_set_sched(priv, 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) */
- 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;
- iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
- }
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
-{
- int ch, txq_id;
- unsigned long flags;
-
- /* Turn off all Tx DMA fifos */
- spin_lock_irqsave(&priv->lock, flags);
-
- iwlagn_txq_set_sched(priv, 0);
-
- /* Stop each Tx DMA channel, and wait for it to be idle */
- for (ch = 0; ch < priv->hw_params.dma_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)
- return;
-
- /* Unmap DMA from host system and free skb's */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- if (txq_id == priv->cmd_queue)
- iwl_cmd_queue_unmap(priv);
- else
- iwl_tx_queue_unmap(priv, txq_id);
-}
-
/*
* Find first available (lowest unused) Tx Queue, mark it "active".
* Called only when finding queue for aggregation.
@@ -1033,8 +518,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
if (unlikely(tx_fifo < 0))
return tx_fifo;
- IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
- __func__, sta->addr, tid);
+ IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n",
+ sta->addr, tid);
sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) {
@@ -1150,7 +635,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
* to deactivate the uCode queue, just return "success" to allow
* mac80211 to clean up it own data.
*/
- iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id);
+ 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);
@@ -1179,7 +664,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
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");
- iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo);
+ 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);
}
@@ -1236,9 +722,9 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
struct ieee80211_hdr *hdr;
if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
- IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
- "is out of range [0-%d] %d %d.\n", txq_id,
- index, q->n_bd, q->write_ptr, q->read_ptr);
+ 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;
}
@@ -1261,7 +747,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
- iwlagn_txq_free_tfd(priv, txq);
+ iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr);
}
return nfreed;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 97de5d9de67b..a895a099d086 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -39,38 +39,7 @@
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
#include "iwl-agn-calib.h"
-
-#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, },
-};
+#include "iwl-trans.h"
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
@@ -143,7 +112,7 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
- IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
+ 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) {
@@ -183,10 +152,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
__le16 *xtal_calib =
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
- cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
+ iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
@@ -197,17 +163,16 @@ 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_5000_TEMPERATURE);
- cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
- cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);
+ (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
+
+ memset(&cmd, 0, sizeof(cmd));
+ iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
+ memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(offset_calib));
if (!(cmd.radio_sensor_offset))
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
- cmd.reserved = 0;
+
IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
- cmd.radio_sensor_offset);
+ le16_to_cpu(cmd.radio_sensor_offset));
return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
(u8 *)&cmd, sizeof(cmd));
}
@@ -225,9 +190,10 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
- calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL;
+ calib_cfg_cmd.ucd_calib_cfg.flags =
+ IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(&priv->trans, &cmd);
}
void iwlagn_rx_calib_result(struct iwl_priv *priv,
@@ -325,7 +291,8 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
/* coexistence is disabled */
memset(&coex_cmd, 0, sizeof(coex_cmd));
}
- return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
+ return trans_send_cmd_pdu(&priv->trans,
+ COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
sizeof(coex_cmd), &coex_cmd);
}
@@ -357,7 +324,8 @@ 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 (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE,
+ if (trans_send_cmd_pdu(&priv->trans,
+ 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");
}
@@ -369,7 +337,8 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
env_cmd.action = action;
env_cmd.type = type;
- ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
+ ret = trans_send_cmd_pdu(&priv->trans,
+ REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
sizeof(env_cmd), &env_cmd);
if (ret)
IWL_ERR(priv, "failed to send BT env command\n");
@@ -379,109 +348,9 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
static int iwlagn_alive_notify(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;
int ret;
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR);
- a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET;
- for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET;
- a += 4)
- iwl_write_targ_mem(priv, a, 0);
- for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET;
- a += 4)
- iwl_write_targ_mem(priv, a, 0);
- for (; a < priv->scd_base_addr +
- IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
- iwl_write_targ_mem(priv, a, 0);
-
- iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR,
- priv->scd_bc_tbls.dma >> 10);
-
- /* Enable DMA channel */
- for (chan = 0; chan < FH50_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, IWLAGN_SCD_QUEUECHAIN_SEL,
- IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
- iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
-
- /* initiate the queues */
- for (i = 0; i < priv->hw_params.max_txq_num; i++) {
- iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0);
- iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
- iwl_write_targ_mem(priv, priv->scd_base_addr +
- IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
- iwl_write_targ_mem(priv, priv->scd_base_addr +
- IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) +
- sizeof(u32),
- ((SCD_WIN_SIZE <<
- IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
- IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
- ((SCD_FRAME_LIMIT <<
- IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
- IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
- }
-
- iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK,
- IWL_MASK(0, priv->hw_params.max_txq_num));
-
- /* Activate all Tx DMA/FIFO channels */
- iwlagn_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;
-
- iwlagn_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);
- iwlagn_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);
+ trans_tx_start(&priv->trans);
ret = iwlagn_send_wimax_coex(priv);
if (ret)
@@ -508,7 +377,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv,
u32 val;
u32 i;
- IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+ IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
/* read data comes through single port, auto-incr addr */
@@ -533,7 +402,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
u32 offs;
int errors = 0;
- IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+ IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
IWLAGN_RTC_INST_LOWER_BOUND);
@@ -559,7 +428,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)) {
- IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n");
+ IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
return 0;
}
@@ -583,7 +452,7 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
palive = &pkt->u.alive_frame;
- IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+ IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
"0x%01X 0x%01X\n",
palive->is_valid, palive->ver_type,
palive->ver_subtype);
@@ -602,14 +471,14 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image,
- int subtype, int alternate_subtype)
+ enum iwlagn_ucode_type ucode_type)
{
struct iwl_notification_wait alive_wait;
struct iwlagn_alive_data alive_data;
int ret;
- enum iwlagn_ucode_subtype old_type;
+ enum iwlagn_ucode_type old_type;
- ret = iwlagn_start_device(priv);
+ ret = trans_start_device(&priv->trans);
if (ret)
return ret;
@@ -617,7 +486,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
iwlagn_alive_fn, &alive_data);
old_type = priv->ucode_type;
- priv->ucode_type = subtype;
+ priv->ucode_type = ucode_type;
ret = iwlagn_load_given_ucode(priv, image);
if (ret) {
@@ -626,8 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
return ret;
}
- /* Remove all resets to allow NIC to operate */
- iwl_write32(priv, CSR_RESET, 0);
+ trans_kick_nic(&priv->trans);
/*
* Some things may run in the background now, but we
@@ -645,24 +513,22 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
return -EIO;
}
- if (alive_data.subtype != subtype &&
- alive_data.subtype != alternate_subtype) {
- IWL_ERR(priv,
- "Loaded ucode is not expected type (got %d, expected %d)!\n",
- alive_data.subtype, subtype);
- priv->ucode_type = old_type;
- return -EIO;
- }
+ /*
+ * This step takes a long time (60-80ms!!) and
+ * WoWLAN image should be loaded quickly, so
+ * skip it for WoWLAN.
+ */
+ if (ucode_type != IWL_UCODE_WOWLAN) {
+ ret = iwl_verify_ucode(priv, image);
+ if (ret) {
+ priv->ucode_type = old_type;
+ return ret;
+ }
- ret = iwl_verify_ucode(priv, image);
- if (ret) {
- priv->ucode_type = old_type;
- return ret;
+ /* delay a bit to give rfkill time to run */
+ msleep(5);
}
- /* delay a bit to give rfkill time to run */
- msleep(5);
-
ret = iwlagn_alive_notify(priv);
if (ret) {
IWL_WARN(priv,
@@ -685,7 +551,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
if (!priv->ucode_init.code.len)
return 0;
- if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED)
+ if (priv->ucode_type != IWL_UCODE_NONE)
return 0;
iwlagn_init_notification_wait(priv, &calib_wait,
@@ -694,7 +560,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
/* Will also start the device */
ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
- UCODE_SUBTYPE_INIT, -1);
+ IWL_UCODE_INIT);
if (ret)
goto error;
@@ -714,6 +580,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
iwlagn_remove_notification(priv, &calib_wait);
out:
/* Whatever happened, stop the device */
- iwlagn_stop_device(priv);
+ trans_stop_device(&priv->trans);
return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8e1942ebd9a0..b0ae4de7f083 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -26,14 +26,9 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
@@ -49,8 +44,6 @@
#include <asm/div64.h>
-#define DRV_NAME "iwlagn"
-
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
@@ -59,7 +52,8 @@
#include "iwl-sta.h"
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
-
+#include "iwl-bus.h"
+#include "iwl-trans.h"
/******************************************************************************
*
@@ -93,12 +87,10 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
{
struct iwl_rxon_context *ctx;
- if (priv->cfg->ops->hcmd->set_rxon_chain) {
- for_each_context(priv, ctx) {
- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
- if (ctx->active.rx_chain != ctx->staging.rx_chain)
- iwlcore_commit_rxon(priv, ctx);
- }
+ for_each_context(priv, ctx) {
+ iwlagn_set_rxon_chain(priv, ctx);
+ if (ctx->active.rx_chain != ctx->staging.rx_chain)
+ iwlagn_commit_rxon(priv, ctx);
}
}
@@ -134,7 +126,9 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
struct iwl_tx_beacon_cmd *tx_beacon_cmd;
struct iwl_host_cmd cmd = {
.id = REPLY_TX_BEACON,
+ .flags = CMD_SYNC,
};
+ struct ieee80211_tx_info *info;
u32 frame_size;
u32 rate_flags;
u32 rate;
@@ -175,14 +169,31 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
frame_size);
/* Set up packet rate and flags */
- rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
+ info = IEEE80211_SKB_CB(priv->beacon_skb);
+
+ /*
+ * Let's set up the rate at least somewhat correctly;
+ * it will currently not actually be used by the uCode,
+ * it uses the broadcast station's rate instead.
+ */
+ if (info->control.rates[0].idx < 0 ||
+ info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+ rate = 0;
+ else
+ 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);
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
- if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+
+ /* In mac80211, rates for 5 GHz start at 0 */
+ if (info->band == IEEE80211_BAND_5GHZ)
+ rate += IWL_FIRST_OFDM_RATE;
+ else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
- tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
- rate_flags);
+
+ tx_beacon_cmd->tx.rate_n_flags =
+ iwl_hw_set_rate_n_flags(rate, rate_flags);
/* Submit command */
cmd.len[0] = sizeof(*tx_beacon_cmd);
@@ -192,7 +203,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 iwl_send_cmd_sync(priv, &cmd);
+ return trans_send_cmd(&priv->trans, &cmd);
}
static void iwl_bg_beacon_update(struct work_struct *work)
@@ -245,7 +256,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
/* dont send host command if rf-kill is on */
if (!iwl_is_ready_rf(priv))
return;
- priv->cfg->ops->hcmd->send_bt_config(priv);
+ iwlagn_send_advance_bt_config(priv);
}
static void iwl_bg_bt_full_concurrency(struct work_struct *work)
@@ -272,12 +283,11 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
* to avoid 3-wire collisions
*/
for_each_context(priv, ctx) {
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
- iwlcore_commit_rxon(priv, ctx);
+ iwlagn_set_rxon_chain(priv, ctx);
+ iwlagn_commit_rxon(priv, ctx);
}
- priv->cfg->ops->hcmd->send_bt_config(priv);
+ iwlagn_send_advance_bt_config(priv);
out:
mutex_unlock(&priv->mutex);
}
@@ -362,7 +372,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
u32 next_entry; /* index of next entry to be written by uCode */
base = priv->device_pointers.error_event_table;
- if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ 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)));
@@ -440,383 +450,8 @@ static void iwl_bg_tx_flush(struct work_struct *work)
if (!iwl_is_ready_rf(priv))
return;
- if (priv->cfg->ops->lib->txfifo_flush) {
- IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
- iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
- }
-}
-
-/**
- * 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;
-
- pci_unmap_page(priv->pci_dev, rxb->page_dma,
- PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
- pkt = rxb_addr(rxb);
-
- 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);
-
- /*
- * Do the notification wait before RX handlers so
- * even if the RX handler consumes the RXB we have
- * access to it in the notification wait entry.
- */
- if (!list_empty(&priv->_agn.notif_waits)) {
- struct iwl_notification_wait *w;
-
- spin_lock(&priv->_agn.notif_wait_lock);
- list_for_each_entry(w, &priv->_agn.notif_waits, list) {
- if (w->cmd == pkt->hdr.cmd) {
- w->triggered = true;
- if (w->fn)
- w->fn(priv, pkt, w->fn_data);
- }
- }
- spin_unlock(&priv->_agn.notif_wait_lock);
-
- wake_up_all(&priv->_agn.notif_waitq);
- }
- if (priv->pre_rx_handler)
- priv->pre_rx_handler(priv, rxb);
-
- /* Based on type of command response or notification,
- * handle those that need handling via function in
- * rx_handlers table. See iwl_setup_rx_handlers() */
- if (priv->rx_handlers[pkt->hdr.cmd]) {
- IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
- i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
- priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
- priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
- } else {
- /* No handling needed */
- IWL_DEBUG_RX(priv,
- "r %d i %d No handler needed for %s, 0x%02x\n",
- r, i, get_cmd_string(pkt->hdr.cmd),
- pkt->hdr.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_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 = pci_map_page(priv->pci_dev, rxb->page,
- 0, PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
- 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 */
-static 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->_agn.inta | ~priv->inta_mask);
-
- inta = priv->_agn.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->_agn.inta */
- priv->_agn.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);
+ IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
+ iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
}
/*****************************************************************************
@@ -939,22 +574,29 @@ static struct attribute_group iwl_attribute_group = {
*
******************************************************************************/
-static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)
{
if (desc->v_addr)
- dma_free_coherent(&pci_dev->dev, desc->len,
+ dma_free_coherent(priv->bus->dev, desc->len,
desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
}
-static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
+static void iwl_free_fw_img(struct iwl_priv *priv, struct fw_img *img)
+{
+ iwl_free_fw_desc(priv, &img->code);
+ iwl_free_fw_desc(priv, &img->data);
+}
+
+static void iwl_dealloc_ucode(struct iwl_priv *priv)
{
- iwl_free_fw_desc(pci_dev, &img->code);
- iwl_free_fw_desc(pci_dev, &img->data);
+ iwl_free_fw_img(priv, &priv->ucode_rt);
+ iwl_free_fw_img(priv, &priv->ucode_init);
+ iwl_free_fw_img(priv, &priv->ucode_wowlan);
}
-static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
+static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
const void *data, size_t len)
{
if (!len) {
@@ -962,21 +604,16 @@ static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
return -EINVAL;
}
- desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len,
+ desc->v_addr = dma_alloc_coherent(priv->bus->dev, len,
&desc->p_addr, GFP_KERNEL);
if (!desc->v_addr)
return -ENOMEM;
+
desc->len = len;
memcpy(desc->v_addr, data, len);
return 0;
}
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
-{
- iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt);
- iwl_free_fw_img(priv->pci_dev, &priv->ucode_init);
-}
-
struct iwlagn_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
@@ -1021,13 +658,14 @@ 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->pci_dev->dev, GFP_KERNEL, priv,
- iwl_ucode_callback);
+ priv->bus->dev,
+ GFP_KERNEL, priv, iwl_ucode_callback);
}
struct iwlagn_firmware_pieces {
- const void *inst, *data, *init, *init_data;
- size_t inst_size, data_size, init_size, init_data_size;
+ const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
+ size_t inst_size, data_size, init_size, init_data_size,
+ wowlan_inst_size, wowlan_data_size;
u32 build;
@@ -1266,6 +904,14 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
goto invalid_tlv_len;
priv->enhance_sensitivity_table = true;
break;
+ case IWL_UCODE_TLV_WOWLAN_INST:
+ pieces->wowlan_inst = tlv_data;
+ pieces->wowlan_inst_size = tlv_len;
+ break;
+ case IWL_UCODE_TLV_WOWLAN_DATA:
+ pieces->wowlan_data = tlv_data;
+ pieces->wowlan_data_size = tlv_len;
+ break;
case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
@@ -1443,23 +1089,35 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
/* Runtime instructions and 2 copies of data:
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.code,
pieces.inst, pieces.inst_size))
goto err_pci_alloc;
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.data,
pieces.data, pieces.data_size))
goto err_pci_alloc;
/* Initialization instructions and data */
if (pieces.init_size && pieces.init_data_size) {
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_init.code,
pieces.init, pieces.init_size))
goto err_pci_alloc;
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_init.data,
pieces.init_data, pieces.init_data_size))
goto err_pci_alloc;
}
+ /* WoWLAN instructions and data */
+ if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.code,
+ pieces.wowlan_inst,
+ pieces.wowlan_inst_size))
+ goto err_pci_alloc;
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.data,
+ pieces.wowlan_data,
+ pieces.wowlan_data_size))
+ goto err_pci_alloc;
+ }
+
/* Now that we can no longer fail, copy information */
/*
@@ -1467,25 +1125,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
* for each event, which is of mode 1 (including timestamp) for all
* new microcodes that include this information.
*/
- priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr;
+ priv->init_evtlog_ptr = pieces.init_evtlog_ptr;
if (pieces.init_evtlog_size)
- priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
+ priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
else
- priv->_agn.init_evtlog_size =
+ priv->init_evtlog_size =
priv->cfg->base_params->max_event_log_size;
- priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr;
- priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr;
+ priv->init_errlog_ptr = pieces.init_errlog_ptr;
+ priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
if (pieces.inst_evtlog_size)
- priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
+ priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
else
- priv->_agn.inst_evtlog_size =
+ priv->inst_evtlog_size =
priv->cfg->base_params->max_event_log_size;
- priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
+ priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
priv->new_scan_threshold_behaviour =
!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
- if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
+ 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);
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
} else
@@ -1505,9 +1164,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
ucode_capa.standard_phy_calibration_size =
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
- priv->_agn.phy_calib_chain_noise_reset_cmd =
+ priv->phy_calib_chain_noise_reset_cmd =
ucode_capa.standard_phy_calibration_size;
- priv->_agn.phy_calib_chain_noise_gain_cmd =
+ priv->phy_calib_chain_noise_gain_cmd =
ucode_capa.standard_phy_calibration_size + 1;
/**************************************************
@@ -1523,7 +1182,7 @@ 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->pci_dev->dev.kobj,
+ err = sysfs_create_group(&(priv->bus->dev->kobj),
&iwl_attribute_group);
if (err) {
IWL_ERR(priv, "failed to create sysfs device attributes\n");
@@ -1532,7 +1191,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
/* We have our copies now, allow OS release its copies */
release_firmware(ucode_raw);
- complete(&priv->_agn.firmware_loading_complete);
+ complete(&priv->firmware_loading_complete);
return;
try_again:
@@ -1544,14 +1203,14 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
err_pci_alloc:
IWL_ERR(priv, "failed to allocate pci memory\n");
- iwl_dealloc_ucode_pci(priv);
+ iwl_dealloc_ucode(priv);
out_unbind:
- complete(&priv->_agn.firmware_loading_complete);
- device_release_driver(&priv->pci_dev->dev);
+ complete(&priv->firmware_loading_complete);
+ device_release_driver(priv->bus->dev);
release_firmware(ucode_raw);
}
-static const char *desc_lookup_text[] = {
+static const char * const desc_lookup_text[] = {
"OK",
"FAIL",
"BAD_PARAM",
@@ -1575,7 +1234,7 @@ static const char *desc_lookup_text[] = {
"NMI_INTERRUPT_DATA_ACTION_PT",
"NMI_TRM_HW_ER",
"NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
+ "NMI_INTERRUPT_BREAK_POINT",
"DEBUG_0",
"DEBUG_1",
"DEBUG_2",
@@ -1626,19 +1285,19 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
struct iwl_error_event_table table;
base = priv->device_pointers.error_event_table;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+ if (priv->ucode_type == IWL_UCODE_INIT) {
if (!base)
- base = priv->_agn.init_errlog_ptr;
+ base = priv->init_errlog_ptr;
} else {
if (!base)
- base = priv->_agn.inst_errlog_ptr;
+ base = priv->inst_errlog_ptr;
}
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ 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 == UCODE_SUBTYPE_INIT)
+ (priv->ucode_type == IWL_UCODE_INIT)
? "Init" : "RT");
return;
}
@@ -1702,12 +1361,12 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
return pos;
base = priv->device_pointers.log_event_table;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+ if (priv->ucode_type == IWL_UCODE_INIT) {
if (!base)
- base = priv->_agn.init_evtlog_ptr;
+ base = priv->init_evtlog_ptr;
} else {
if (!base)
- base = priv->_agn.inst_evtlog_ptr;
+ base = priv->inst_evtlog_ptr;
}
if (mode == 0)
@@ -1815,21 +1474,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
size_t bufsz = 0;
base = priv->device_pointers.log_event_table;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
- logsize = priv->_agn.init_evtlog_size;
+ if (priv->ucode_type == IWL_UCODE_INIT) {
+ logsize = priv->init_evtlog_size;
if (!base)
- base = priv->_agn.init_evtlog_ptr;
+ base = priv->init_evtlog_ptr;
} else {
- logsize = priv->_agn.inst_evtlog_size;
+ logsize = priv->inst_evtlog_size;
if (!base)
- base = priv->_agn.inst_evtlog_ptr;
+ base = priv->inst_evtlog_ptr;
}
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ 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 == UCODE_SUBTYPE_INIT)
+ (priv->ucode_type == IWL_UCODE_INIT)
? "Init" : "RT");
return -EINVAL;
}
@@ -1928,8 +1587,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
adv_cmd.critical_temperature_exit =
cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
- ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
- sizeof(adv_cmd), &adv_cmd);
+ ret = trans_send_cmd_pdu(&priv->trans,
+ 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
@@ -1943,8 +1603,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
cmd.critical_temperature_R =
cpu_to_le32(priv->hw_params.ct_kill_threshold);
- ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
- sizeof(cmd), &cmd);
+ ret = trans_send_cmd_pdu(&priv->trans,
+ REPLY_CT_KILL_CONFIG_CMD,
+ CMD_SYNC, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
else
@@ -1968,10 +1629,29 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(&priv->trans, &cmd);
}
+static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
+{
+ struct iwl_tx_ant_config_cmd tx_ant_cmd = {
+ .valid = cpu_to_le32(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,
+ TX_ANT_CONFIGURATION_CMD,
+ CMD_SYNC,
+ sizeof(struct iwl_tx_ant_config_cmd),
+ &tx_ant_cmd);
+ } else {
+ IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
+ return -EOPNOTSUPP;
+ }
+}
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
@@ -1982,6 +1662,7 @@ int iwl_alive_start(struct iwl_priv *priv)
int ret = 0;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ /*TODO: this should go to the transport layer */
iwl_reset_ict(priv);
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
@@ -1999,11 +1680,18 @@ int iwl_alive_start(struct iwl_priv *priv)
if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist) {
/* Configure Bluetooth device coexistence support */
+ if (priv->cfg->bt_params->bt_sco_disable)
+ priv->bt_enable_pspoll = false;
+ else
+ priv->bt_enable_pspoll = true;
+
priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
- priv->cfg->ops->hcmd->send_bt_config(priv);
+ iwlagn_send_advance_bt_config(priv);
priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
+ priv->cur_rssi_ctx = NULL;
+
iwlagn_send_prio_tbl(priv);
/* FIXME: w/a to force change uCode BT state machine */
@@ -2015,7 +1703,13 @@ int iwl_alive_start(struct iwl_priv *priv)
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
+ } else {
+ /*
+ * default is 2-wire BT coexexistence support
+ */
+ iwl_send_bt_config(priv);
}
+
if (priv->hw_params.calib_rt_cfg)
iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
@@ -2024,10 +1718,9 @@ int iwl_alive_start(struct iwl_priv *priv)
priv->active_rate = IWL_RATES_MASK;
/* Configure Tx antenna selection based on H/W config */
- if (priv->cfg->ops->hcmd->set_tx_ant)
- priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
+ iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
- if (iwl_is_associated_ctx(ctx)) {
+ if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
struct iwl_rxon_cmd *active_rxon =
(struct iwl_rxon_cmd *)&ctx->active;
/* apply any changes in staging */
@@ -2039,24 +1732,18 @@ int iwl_alive_start(struct iwl_priv *priv)
for_each_context(priv, tmp)
iwl_connection_init_rx_config(priv, tmp);
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+ iwlagn_set_rxon_chain(priv, ctx);
}
- if (!priv->cfg->bt_params || (priv->cfg->bt_params &&
- !priv->cfg->bt_params->advanced_bt_coexist)) {
- /*
- * default is 2-wire BT coexexistence support
- */
- priv->cfg->ops->hcmd->send_bt_config(priv);
+ if (!priv->wowlan) {
+ /* WoWLAN ucode will not reply in the same way, skip it */
+ iwl_reset_run_time_calib(priv);
}
- iwl_reset_run_time_calib(priv);
-
set_bit(STATUS_READY, &priv->status);
/* Configure the adapter for unassociated operation */
- ret = iwlcore_commit_rxon(priv, ctx);
+ ret = iwlagn_commit_rxon(priv, ctx);
if (ret)
return ret;
@@ -2090,6 +1777,8 @@ static void __iwl_down(struct iwl_priv *priv)
/* reset BT coex data */
priv->bt_status = 0;
+ priv->cur_rssi_ctx = NULL;
+ priv->bt_is_sco = 0;
if (priv->cfg->bt_params)
priv->bt_traffic_load =
priv->cfg->bt_params->bt_init_traffic_load;
@@ -2116,7 +1805,7 @@ static void __iwl_down(struct iwl_priv *priv)
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
STATUS_EXIT_PENDING;
- iwlagn_stop_device(priv);
+ trans_stop_device(&priv->trans);
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = NULL;
@@ -2131,55 +1820,6 @@ static void iwl_down(struct iwl_priv *priv)
iwl_cancel_deferred_work(priv);
}
-#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 */
-int iwl_prepare_card_hw(struct iwl_priv *priv)
-{
- int ret;
-
- IWL_DEBUG_INFO(priv, "iwl_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;
-}
-
#define MAX_HW_RESTARTS 5
static int __iwl_up(struct iwl_priv *priv)
@@ -2210,8 +1850,7 @@ static int __iwl_up(struct iwl_priv *priv)
ret = iwlagn_load_ucode_wait_alive(priv,
&priv->ucode_rt,
- UCODE_SUBTYPE_REGULAR,
- UCODE_SUBTYPE_REGULAR_NEW);
+ IWL_UCODE_REGULAR);
if (ret) {
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
goto error;
@@ -2266,6 +1905,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
u8 bt_ci_compliance;
u8 bt_load;
u8 bt_status;
+ bool bt_is_sco;
lockdep_assert_held(&priv->mutex);
@@ -2286,6 +1926,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
bt_ci_compliance = priv->bt_ci_compliance;
bt_load = priv->bt_traffic_load;
bt_status = priv->bt_status;
+ bt_is_sco = priv->bt_is_sco;
__iwl_down(priv);
@@ -2293,6 +1934,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
priv->bt_ci_compliance = bt_ci_compliance;
priv->bt_traffic_load = bt_load;
priv->bt_status = bt_status;
+ priv->bt_is_sco = bt_is_sco;
}
static void iwl_bg_restart(struct work_struct *data)
@@ -2313,19 +1955,6 @@ static void iwl_bg_restart(struct work_struct *data)
}
}
-static 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);
-}
-
static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
@@ -2360,7 +1989,7 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
/* TODO: queue up if scanning? */
if (test_bit(STATUS_SCANNING, &priv->status) ||
- priv->_agn.offchan_tx_skb) {
+ priv->offchan_tx_skb) {
ret = -EBUSY;
goto out;
}
@@ -2374,14 +2003,14 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
goto out;
}
- priv->_agn.offchan_tx_skb = skb;
- priv->_agn.offchan_tx_timeout = wait;
- priv->_agn.offchan_tx_chan = chan;
+ 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->_agn.offchan_tx_skb = NULL;
+ priv->offchan_tx_skb = NULL;
out:
mutex_unlock(&priv->mutex);
free:
@@ -2398,12 +2027,12 @@ static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
- if (!priv->_agn.offchan_tx_skb) {
+ if (!priv->offchan_tx_skb) {
ret = -EINVAL;
goto unlock;
}
- priv->_agn.offchan_tx_skb = NULL;
+ priv->offchan_tx_skb = NULL;
ret = iwl_scan_cancel_timeout(priv, 200);
if (ret)
@@ -2420,6 +2049,77 @@ unlock:
*
*****************************************************************************/
+static const struct ieee80211_iface_limit iwlagn_sta_ap_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP),
+ },
+};
+
+static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = {
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+};
+
+static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_AP),
+ },
+};
+
+static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = {
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
+ },
+};
+
+static const struct ieee80211_iface_combination
+iwlagn_iface_combinations_dualmode[] = {
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .beacon_int_infra_match = true,
+ .limits = iwlagn_sta_ap_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_sta_ap_limits),
+ },
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .limits = iwlagn_2sta_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_2sta_limits),
+ },
+};
+
+static const struct ieee80211_iface_combination
+iwlagn_iface_combinations_p2p[] = {
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .beacon_int_infra_match = true,
+ .limits = iwlagn_p2p_sta_go_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits),
+ },
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .limits = iwlagn_p2p_2sta_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits),
+ },
+};
+
/*
* Not a mac80211 entry point function, but it fits in with all the
* other mac80211 functions grouped here.
@@ -2445,7 +2145,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
@@ -2460,17 +2160,45 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
}
+ BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+ if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) {
+ hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
+ hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(iwlagn_iface_combinations_p2p);
+ } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
+ hw->wiphy->iface_combinations = iwlagn_iface_combinations_dualmode;
+ hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
+ }
+
hw->wiphy->max_remain_on_channel_duration = 1000;
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS |
WIPHY_FLAG_IBSS_RSN;
- /*
- * For now, disable PS by default because it affects
- * RX performance significantly.
- */
- hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ if (priv->ucode_wowlan.code.len && device_can_wakeup(priv->bus->dev)) {
+ hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
+ WIPHY_WOWLAN_DISCONNECT |
+ WIPHY_WOWLAN_EAP_IDENTITY_REQ |
+ WIPHY_WOWLAN_RFKILL_RELEASE;
+ if (!iwlagn_mod_params.sw_crypto)
+ hw->wiphy->wowlan.flags |=
+ WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+ WIPHY_WOWLAN_GTK_REKEY_FAILURE;
+
+ hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS;
+ hw->wiphy->wowlan.pattern_min_len =
+ IWLAGN_WOWLAN_MIN_PATTERN_LEN;
+ hw->wiphy->wowlan.pattern_max_len =
+ IWLAGN_WOWLAN_MAX_PATTERN_LEN;
+ }
+
+ if (iwlagn_mod_params.power_save)
+ hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ else
+ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
/* we create the 802.11 header and a zero-length SSID element */
@@ -2551,6 +2279,471 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211(priv, "leave\n");
}
+#ifdef CONFIG_PM
+static int iwlagn_send_patterns(struct iwl_priv *priv,
+ struct cfg80211_wowlan *wowlan)
+{
+ struct iwlagn_wowlan_patterns_cmd *pattern_cmd;
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_WOWLAN_PATTERNS,
+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+ .flags = CMD_SYNC,
+ };
+ int i, err;
+
+ if (!wowlan->n_patterns)
+ return 0;
+
+ cmd.len[0] = sizeof(*pattern_cmd) +
+ wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern);
+
+ pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
+ if (!pattern_cmd)
+ return -ENOMEM;
+
+ pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
+
+ for (i = 0; i < wowlan->n_patterns; i++) {
+ int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
+
+ memcpy(&pattern_cmd->patterns[i].mask,
+ wowlan->patterns[i].mask, mask_len);
+ memcpy(&pattern_cmd->patterns[i].pattern,
+ wowlan->patterns[i].pattern,
+ wowlan->patterns[i].pattern_len);
+ pattern_cmd->patterns[i].mask_size = mask_len;
+ pattern_cmd->patterns[i].pattern_size =
+ wowlan->patterns[i].pattern_len;
+ }
+
+ cmd.data[0] = pattern_cmd;
+ err = trans_send_cmd(&priv->trans, &cmd);
+ kfree(pattern_cmd);
+ return err;
+}
+#endif
+
+static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_gtk_rekey_data *data)
+{
+ struct iwl_priv *priv = hw->priv;
+
+ if (iwlagn_mod_params.sw_crypto)
+ return;
+
+ mutex_lock(&priv->mutex);
+
+ if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
+ goto out;
+
+ memcpy(priv->kek, data->kek, NL80211_KEK_LEN);
+ memcpy(priv->kck, data->kck, NL80211_KCK_LEN);
+ priv->replay_ctr = cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr));
+ priv->have_rekey_data = true;
+
+ out:
+ mutex_unlock(&priv->mutex);
+}
+
+struct wowlan_key_data {
+ struct iwl_rxon_context *ctx;
+ struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc;
+ struct iwlagn_wowlan_tkip_params_cmd *tkip;
+ const u8 *bssid;
+ bool error, use_rsc_tsc, use_tkip;
+};
+
+#ifdef CONFIG_PM
+static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
+{
+ int i;
+
+ for (i = 0; i < IWLAGN_P1K_SIZE; i++)
+ out[i] = cpu_to_le16(p1k[i]);
+}
+
+static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *_data)
+{
+ struct iwl_priv *priv = hw->priv;
+ struct wowlan_key_data *data = _data;
+ struct iwl_rxon_context *ctx = data->ctx;
+ struct aes_sc *aes_sc, *aes_tx_sc = NULL;
+ struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
+ struct iwlagn_p1k_cache *rx_p1ks;
+ u8 *rx_mic_key;
+ struct ieee80211_key_seq seq;
+ u32 cur_rx_iv32 = 0;
+ u16 p1k[IWLAGN_P1K_SIZE];
+ int ret, i;
+
+ mutex_lock(&priv->mutex);
+
+ if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+ !sta && !ctx->key_mapping_keys)
+ ret = iwl_set_default_wep_key(priv, ctx, key);
+ else
+ ret = iwl_set_dynamic_key(priv, ctx, key, sta);
+
+ if (ret) {
+ IWL_ERR(priv, "Error setting key during suspend!\n");
+ data->error = true;
+ }
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ if (sta) {
+ tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
+ tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
+
+ rx_p1ks = data->tkip->rx_uni;
+
+ ieee80211_get_key_tx_seq(key, &seq);
+ tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
+ tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
+
+ ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
+ iwlagn_convert_p1k(p1k, data->tkip->tx.p1k);
+
+ memcpy(data->tkip->mic_keys.tx,
+ &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
+ IWLAGN_MIC_KEY_SIZE);
+
+ rx_mic_key = data->tkip->mic_keys.rx_unicast;
+ } else {
+ tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
+ rx_p1ks = data->tkip->rx_multi;
+ rx_mic_key = data->tkip->mic_keys.rx_mcast;
+ }
+
+ /*
+ * For non-QoS this relies on the fact that both the uCode and
+ * mac80211 use TID 0 (as they need to to avoid replay attacks)
+ * for checking the IV in the frames.
+ */
+ for (i = 0; i < IWLAGN_NUM_RSC; i++) {
+ ieee80211_get_key_rx_seq(key, i, &seq);
+ tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16);
+ tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);
+ /* wrapping isn't allowed, AP must rekey */
+ if (seq.tkip.iv32 > cur_rx_iv32)
+ cur_rx_iv32 = seq.tkip.iv32;
+ }
+
+ ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k);
+ iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k);
+ ieee80211_get_tkip_rx_p1k(key, data->bssid,
+ cur_rx_iv32 + 1, p1k);
+ iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k);
+
+ memcpy(rx_mic_key,
+ &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
+ IWLAGN_MIC_KEY_SIZE);
+
+ data->use_tkip = true;
+ data->use_rsc_tsc = true;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ if (sta) {
+ u8 *pn = seq.ccmp.pn;
+
+ aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
+ aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
+
+ ieee80211_get_key_tx_seq(key, &seq);
+ aes_tx_sc->pn = cpu_to_le64(
+ (u64)pn[5] |
+ ((u64)pn[4] << 8) |
+ ((u64)pn[3] << 16) |
+ ((u64)pn[2] << 24) |
+ ((u64)pn[1] << 32) |
+ ((u64)pn[0] << 40));
+ } else
+ aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
+
+ /*
+ * For non-QoS this relies on the fact that both the uCode and
+ * mac80211 use TID 0 for checking the IV in the frames.
+ */
+ for (i = 0; i < IWLAGN_NUM_RSC; i++) {
+ u8 *pn = seq.ccmp.pn;
+
+ ieee80211_get_key_rx_seq(key, i, &seq);
+ aes_sc->pn = cpu_to_le64(
+ (u64)pn[5] |
+ ((u64)pn[4] << 8) |
+ ((u64)pn[3] << 16) |
+ ((u64)pn[2] << 24) |
+ ((u64)pn[1] << 32) |
+ ((u64)pn[0] << 40));
+ }
+ data->use_rsc_tsc = true;
+ break;
+ }
+
+ mutex_unlock(&priv->mutex);
+}
+
+static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
+ struct cfg80211_wowlan *wowlan)
+{
+ struct iwl_priv *priv = hw->priv;
+ struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
+ struct iwl_rxon_cmd rxon;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
+ struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
+ struct wowlan_key_data key_data = {
+ .ctx = ctx,
+ .bssid = ctx->active.bssid_addr,
+ .use_rsc_tsc = false,
+ .tkip = &tkip_cmd,
+ .use_tkip = false,
+ };
+ int ret, i;
+ u16 seq;
+
+ if (WARN_ON(!wowlan))
+ return -EINVAL;
+
+ mutex_lock(&priv->mutex);
+
+ /* Don't attempt WoWLAN when not associated, tear down instead. */
+ if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
+ !iwl_is_associated_ctx(ctx)) {
+ ret = 1;
+ goto out;
+ }
+
+ key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
+ if (!key_data.rsc_tsc) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd));
+
+ /*
+ * We know the last used seqno, and the uCode expects to know that
+ * one, it will increment before TX.
+ */
+ seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ;
+ wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq);
+
+ /*
+ * For QoS counters, we store the one to use next, so subtract 0x10
+ * 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 -= 0x10;
+ wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
+ }
+
+ if (wowlan->disconnect)
+ wakeup_filter_cmd.enabled |=
+ cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS |
+ IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE);
+ if (wowlan->magic_pkt)
+ wakeup_filter_cmd.enabled |=
+ cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET);
+ if (wowlan->gtk_rekey_failure)
+ wakeup_filter_cmd.enabled |=
+ cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
+ if (wowlan->eap_identity_req)
+ wakeup_filter_cmd.enabled |=
+ cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ);
+ if (wowlan->four_way_handshake)
+ wakeup_filter_cmd.enabled |=
+ cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
+ if (wowlan->rfkill_release)
+ wakeup_filter_cmd.enabled |=
+ cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_RFKILL);
+ if (wowlan->n_patterns)
+ wakeup_filter_cmd.enabled |=
+ cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH);
+
+ iwl_scan_cancel_timeout(priv, 200);
+
+ memcpy(&rxon, &ctx->active, sizeof(rxon));
+
+ trans_stop_device(&priv->trans);
+
+ priv->wowlan = true;
+
+ ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan,
+ IWL_UCODE_WOWLAN);
+ if (ret)
+ goto error;
+
+ /* now configure WoWLAN ucode */
+ ret = iwl_alive_start(priv);
+ if (ret)
+ goto error;
+
+ memcpy(&ctx->staging, &rxon, sizeof(rxon));
+ ret = iwlagn_commit_rxon(priv, ctx);
+ if (ret)
+ goto error;
+
+ ret = iwl_power_update_mode(priv, true);
+ if (ret)
+ goto error;
+
+ if (!iwlagn_mod_params.sw_crypto) {
+ /* mark all keys clear */
+ priv->ucode_key_table = 0;
+ ctx->key_mapping_keys = 0;
+
+ /*
+ * This needs to be unlocked due to lock ordering
+ * constraints. Since we're in the suspend path
+ * that isn't really a problem though.
+ */
+ mutex_unlock(&priv->mutex);
+ ieee80211_iter_keys(priv->hw, ctx->vif,
+ iwlagn_wowlan_program_keys,
+ &key_data);
+ mutex_lock(&priv->mutex);
+ if (key_data.error) {
+ ret = -EIO;
+ goto error;
+ }
+
+ if (key_data.use_rsc_tsc) {
+ struct iwl_host_cmd rsc_tsc_cmd = {
+ .id = REPLY_WOWLAN_TSC_RSC_PARAMS,
+ .flags = CMD_SYNC,
+ .data[0] = key_data.rsc_tsc,
+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+ .len[0] = sizeof(*key_data.rsc_tsc),
+ };
+
+ ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd);
+ if (ret)
+ goto error;
+ }
+
+ if (key_data.use_tkip) {
+ ret = trans_send_cmd_pdu(&priv->trans,
+ REPLY_WOWLAN_TKIP_PARAMS,
+ CMD_SYNC, sizeof(tkip_cmd),
+ &tkip_cmd);
+ if (ret)
+ goto error;
+ }
+
+ if (priv->have_rekey_data) {
+ memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
+ memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN);
+ kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
+ memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN);
+ 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,
+ REPLY_WOWLAN_KEK_KCK_MATERIAL,
+ CMD_SYNC, sizeof(kek_kck_cmd),
+ &kek_kck_cmd);
+ if (ret)
+ goto error;
+ }
+ }
+
+ ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER,
+ CMD_SYNC, sizeof(wakeup_filter_cmd),
+ &wakeup_filter_cmd);
+ if (ret)
+ goto error;
+
+ ret = iwlagn_send_patterns(priv, wowlan);
+ if (ret)
+ goto error;
+
+ device_set_wakeup_enable(priv->bus->dev, true);
+
+ /* Now let the ucode operate on its own */
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
+
+ goto out;
+
+ error:
+ priv->wowlan = false;
+ iwlagn_prepare_restart(priv);
+ ieee80211_restart_hw(priv->hw);
+ out:
+ mutex_unlock(&priv->mutex);
+ kfree(key_data.rsc_tsc);
+ return ret;
+}
+
+static int iwlagn_mac_resume(struct ieee80211_hw *hw)
+{
+ struct iwl_priv *priv = hw->priv;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct ieee80211_vif *vif;
+ unsigned long flags;
+ u32 base, status = 0xffffffff;
+ int ret = -EIO;
+
+ mutex_lock(&priv->mutex);
+
+ iwl_write32(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);
+ if (ret == 0) {
+ iwl_write32(priv, HBUS_TARG_MEM_RADDR, base);
+ status = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+ iwl_release_nic_access(priv);
+ }
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ if (ret == 0) {
+ if (!priv->wowlan_sram)
+ priv->wowlan_sram =
+ kzalloc(priv->ucode_wowlan.data.len,
+ GFP_KERNEL);
+
+ if (priv->wowlan_sram)
+ _iwl_read_targ_mem_words(
+ priv, 0x800000, priv->wowlan_sram,
+ priv->ucode_wowlan.data.len / 4);
+ }
+#endif
+ }
+
+ /* we'll clear ctx->vif during iwlagn_prepare_restart() */
+ vif = ctx->vif;
+
+ priv->wowlan = false;
+
+ device_set_wakeup_enable(priv->bus->dev, false);
+
+ iwlagn_prepare_restart(priv);
+
+ memset((void *)&ctx->active, 0, sizeof(ctx->active));
+ iwl_connection_init_rx_config(priv, ctx);
+ iwlagn_set_rxon_chain(priv, ctx);
+
+ mutex_unlock(&priv->mutex);
+
+ ieee80211_resume_disconnect(vif);
+
+ return 1;
+}
+#endif
+
static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct iwl_priv *priv = hw->priv;
@@ -2573,14 +2766,8 @@ static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
u32 iv32, u16 *phase1key)
{
struct iwl_priv *priv = hw->priv;
- struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-
- IWL_DEBUG_MAC80211(priv, "enter\n");
-
- iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
- iv32, phase1key);
- IWL_DEBUG_MAC80211(priv, "leave\n");
+ iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key);
}
static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -2592,7 +2779,6 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
int ret;
- u8 sta_id;
bool is_default_wep_key = false;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2603,20 +2789,27 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
/*
- * To support IBSS RSN, don't program group keys in IBSS, the
- * hardware will then not attempt to decrypt the frames.
+ * We could program these keys into the hardware as well, but we
+ * don't expect much multicast traffic in IBSS and having keys
+ * for more stations is probably more useful.
+ *
+ * Mark key TX-only and return 0.
*/
if (vif->type == NL80211_IFTYPE_ADHOC &&
- !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
- return -EOPNOTSUPP;
+ !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ key->hw_key_idx = WEP_INVALID_OFFSET;
+ return 0;
+ }
- sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
- if (sta_id == IWL_INVALID_STATION)
- return -EINVAL;
+ /* If they key was TX-only, accept deletion */
+ if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
+ return 0;
mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 100);
+ BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
+
/*
* If we are getting WEP group key and we didn't receive any key mapping
* so far, we are in legacy wep mode (group key only), otherwise we are
@@ -2624,22 +2817,30 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
* In legacy wep mode, we use another host command to the uCode.
*/
if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
- key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
- !sta) {
+ key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) {
if (cmd == SET_KEY)
is_default_wep_key = !ctx->key_mapping_keys;
else
is_default_wep_key =
- (key->hw_key_idx == HW_KEY_DEFAULT);
+ key->hw_key_idx == IWLAGN_HW_KEY_DEFAULT;
}
+
switch (cmd) {
case SET_KEY:
- if (is_default_wep_key)
+ if (is_default_wep_key) {
ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key);
- else
- ret = iwl_set_dynamic_key(priv, vif_priv->ctx,
- key, sta_id);
+ break;
+ }
+ ret = iwl_set_dynamic_key(priv, vif_priv->ctx, key, sta);
+ if (ret) {
+ /*
+ * can't add key for RX, but we don't need it
+ * in the device for TX so still return 0
+ */
+ ret = 0;
+ key->hw_key_idx = WEP_INVALID_OFFSET;
+ }
IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
break;
@@ -2647,7 +2848,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (is_default_wep_key)
ret = iwl_remove_default_wep_key(priv, ctx, key);
else
- ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id);
+ ret = iwl_remove_dynamic_key(priv, ctx, key, sta);
IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
break;
@@ -2674,7 +2875,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
- if (!(priv->cfg->sku & IWL_SKU_N))
+ if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES;
mutex_lock(&priv->mutex);
@@ -2694,29 +2895,26 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
if (ret == 0) {
- priv->_agn.agg_tids_count++;
- IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
- priv->_agn.agg_tids_count);
+ 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");
ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
- if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) {
- priv->_agn.agg_tids_count--;
- IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
- priv->_agn.agg_tids_count);
+ if ((ret == 0) && (priv->agg_tids_count > 0)) {
+ priv->agg_tids_count--;
+ IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+ priv->agg_tids_count);
}
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
ret = 0;
if (priv->cfg->ht_params &&
priv->cfg->ht_params->use_rts_for_aggregation) {
- struct iwl_station_priv *sta_priv =
- (void *) sta->drv_priv;
/*
* switch off RTS/CTS if it was previously enabled
*/
-
sta_priv->lq_sta.lq.general_params.flags &=
~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
@@ -2726,7 +2924,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);
- iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size);
+ trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid,
+ buf_size);
/*
* If the limit is 0, then it wasn't initialised yet,
@@ -2764,6 +2963,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
&sta_priv->lq_sta.lq, CMD_ASYNC, false);
+
+ IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
+ sta->addr, tid);
ret = 0;
break;
}
@@ -2833,7 +3035,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u16 ch;
- unsigned long flags = 0;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2850,65 +3051,64 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
if (!iwl_is_associated_ctx(ctx))
goto out;
- if (priv->cfg->ops->lib->set_channel_switch) {
+ if (!priv->cfg->lib->set_channel_switch)
+ goto out;
- ch = channel->hw_value;
- if (le16_to_cpu(ctx->active.channel) != ch) {
- ch_info = iwl_get_channel_info(priv,
- channel->band,
- ch);
- if (!is_channel_valid(ch_info)) {
- IWL_DEBUG_MAC80211(priv, "invalid channel\n");
- goto out;
- }
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->current_ht_config.smps = conf->smps_mode;
-
- /* Configure HT40 channels */
- ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ctx->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ctx->ht.is_40mhz = true;
- } else {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ctx->ht.is_40mhz = false;
- }
- } else
- ctx->ht.is_40mhz = false;
-
- if ((le16_to_cpu(ctx->staging.channel) != ch))
- ctx->staging.flags = 0;
-
- iwl_set_rxon_channel(priv, channel, ctx);
- iwl_set_rxon_ht(priv, ht_conf);
- iwl_set_flags_for_band(priv, ctx, channel->band,
- ctx->vif);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- iwl_set_rate(priv);
- /*
- * at this point, staging_rxon has the
- * configuration for channel switch
- */
- set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
- priv->switch_channel = cpu_to_le16(ch);
- if (priv->cfg->ops->lib->set_channel_switch(priv,
- ch_switch)) {
- clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
- &priv->status);
- priv->switch_channel = 0;
- ieee80211_chswitch_done(ctx->vif, false);
- }
+ ch = channel->hw_value;
+ if (le16_to_cpu(ctx->active.channel) == ch)
+ goto out;
+
+ ch_info = iwl_get_channel_info(priv, channel->band, ch);
+ if (!is_channel_valid(ch_info)) {
+ IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+ goto out;
+ }
+
+ spin_lock_irq(&priv->lock);
+
+ priv->current_ht_config.smps = conf->smps_mode;
+
+ /* Configure HT40 channels */
+ ctx->ht.enabled = conf_is_ht(conf);
+ if (ctx->ht.enabled) {
+ if (conf_is_ht40_minus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ } else if (conf_is_ht40_plus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ } else {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ ctx->ht.is_40mhz = false;
}
+ } else
+ ctx->ht.is_40mhz = false;
+
+ if ((le16_to_cpu(ctx->staging.channel) != ch))
+ ctx->staging.flags = 0;
+
+ iwl_set_rxon_channel(priv, channel, ctx);
+ iwl_set_rxon_ht(priv, ht_conf);
+ iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+ spin_unlock_irq(&priv->lock);
+
+ iwl_set_rate(priv);
+ /*
+ * at this point, staging_rxon has the
+ * configuration for channel switch
+ */
+ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->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);
+ priv->switch_channel = 0;
+ ieee80211_chswitch_done(ctx->vif, false);
}
+
out:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -2971,10 +3171,6 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
- /* do not support "flush" */
- if (!priv->cfg->ops->lib->txfifo_flush)
- goto done;
-
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
goto done;
@@ -2990,7 +3186,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
*/
if (drop) {
IWL_DEBUG_MAC80211(priv, "send flush command\n");
- if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+ if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -3017,9 +3213,9 @@ static void iwlagn_disable_roc(struct iwl_priv *priv)
iwl_set_rxon_channel(priv, chan, ctx);
iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
- priv->_agn.hw_roc_channel = NULL;
+ priv->hw_roc_channel = NULL;
- iwlcore_commit_rxon(priv, ctx);
+ iwlagn_commit_rxon(priv, ctx);
ctx->is_active = false;
}
@@ -3027,7 +3223,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv)
static void iwlagn_bg_roc_done(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv,
- _agn.hw_roc_work.work);
+ hw_roc_work.work);
mutex_lock(&priv->mutex);
ieee80211_remain_on_channel_expired(priv->hw);
@@ -3059,11 +3255,11 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
}
priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
- priv->_agn.hw_roc_channel = channel;
- priv->_agn.hw_roc_chantype = channel_type;
- priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
- iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
- queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
+ 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));
msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */
@@ -3082,7 +3278,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP;
- cancel_delayed_work_sync(&priv->_agn.hw_roc_work);
+ cancel_delayed_work_sync(&priv->hw_roc_work);
mutex_lock(&priv->mutex);
iwlagn_disable_roc(priv);
@@ -3104,18 +3300,17 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
init_waitqueue_head(&priv->wait_command_queue);
INIT_WORK(&priv->restart, iwl_bg_restart);
- INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
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->_agn.hw_roc_work, iwlagn_bg_roc_done);
+ INIT_DELAYED_WORK(&priv->hw_roc_work, iwlagn_bg_roc_done);
iwl_setup_scan_deferred_work(priv);
- if (priv->cfg->ops->lib->setup_deferred_work)
- priv->cfg->ops->lib->setup_deferred_work(priv);
+ if (priv->cfg->lib->bt_setup_deferred_work)
+ priv->cfg->lib->bt_setup_deferred_work(priv);
init_timer(&priv->statistics_periodic);
priv->statistics_periodic.data = (unsigned long)priv;
@@ -3128,15 +3323,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
init_timer(&priv->watchdog);
priv->watchdog.data = (unsigned long)priv;
priv->watchdog.function = iwl_bg_watchdog;
-
- tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
- iwl_irq_tasklet, (unsigned long)priv);
}
static void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
- if (priv->cfg->ops->lib->cancel_deferred_work)
- priv->cfg->ops->lib->cancel_deferred_work(priv);
+ if (priv->cfg->lib->cancel_deferred_work)
+ priv->cfg->lib->cancel_deferred_work(priv);
cancel_work_sync(&priv->run_time_calib_work);
cancel_work_sync(&priv->beacon_update);
@@ -3187,7 +3379,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
- priv->_agn.agg_tids_count = 0;
+ priv->agg_tids_count = 0;
/* initialize force reset */
priv->force_reset[IWL_RF_RESET].reset_duration =
@@ -3198,9 +3390,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
priv->rx_statistics_jiffies = jiffies;
/* Choose which receivers/antennas to use */
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv,
- &priv->contexts[IWL_RXON_CTX_BSS]);
+ iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
iwl_init_scan_params(priv);
@@ -3243,12 +3433,42 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
iwl_free_channel_map(priv);
kfree(priv->scan_cmd);
kfree(priv->beacon_cmd);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ kfree(priv->wowlan_sram);
+#endif
+}
+
+static void iwl_mac_rssi_callback(struct ieee80211_hw *hw,
+ enum ieee80211_rssi_event rssi_event)
+{
+ struct iwl_priv *priv = hw->priv;
+
+ mutex_lock(&priv->mutex);
+
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ if (rssi_event == RSSI_EVENT_LOW)
+ priv->bt_enable_pspoll = true;
+ else if (rssi_event == RSSI_EVENT_HIGH)
+ priv->bt_enable_pspoll = false;
+
+ iwlagn_send_advance_bt_config(priv);
+ } else {
+ IWL_DEBUG_MAC80211(priv, "Advanced BT coex disabled,"
+ "ignoring RSSI callback\n");
+ }
+
+ mutex_unlock(&priv->mutex);
}
struct ieee80211_ops iwlagn_hw_ops = {
.tx = iwlagn_mac_tx,
.start = iwlagn_mac_start,
.stop = iwlagn_mac_stop,
+#ifdef CONFIG_PM
+ .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,
@@ -3256,6 +3476,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
.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,
.bss_info_changed = iwlagn_bss_info_changed,
.ampdu_action = iwlagn_mac_ampdu_action,
@@ -3270,15 +3491,13 @@ struct ieee80211_ops iwlagn_hw_ops = {
.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)
};
static u32 iwl_hw_detect(struct iwl_priv *priv)
{
- u8 rev_id;
-
- pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
- IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
return iwl_read32(priv, CSR_HW_REV);
}
@@ -3294,10 +3513,10 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
if (iwlagn_mod_params.disable_11n)
- priv->cfg->sku &= ~IWL_SKU_N;
+ priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
/* Device-specific setup */
- return priv->cfg->ops->lib->set_hw_params(priv);
+ return priv->cfg->lib->set_hw_params(priv);
}
static const u8 iwlagn_bss_ac_to_fifo[] = {
@@ -3344,29 +3563,9 @@ out:
return hw;
}
-static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static void iwl_init_context(struct iwl_priv *priv)
{
- int err = 0, i;
- struct iwl_priv *priv;
- struct ieee80211_hw *hw;
- struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
- unsigned long flags;
- u16 pci_cmd, num_mac;
- u32 hw_rev;
-
- /************************
- * 1. Allocating HW data
- ************************/
-
- hw = iwl_alloc_all(cfg);
- if (!hw) {
- err = -ENOMEM;
- goto out;
- }
- priv = hw->priv;
- /* At this point both hw and priv are allocated. */
-
- priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
+ int i;
/*
* The default context is always valid,
@@ -3398,8 +3597,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
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].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;
@@ -3419,12 +3620,35 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+}
- SET_IEEE80211_DEV(hw, &pdev->dev);
+int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
+{
+ int err = 0;
+ struct iwl_priv *priv;
+ struct ieee80211_hw *hw;
+ u16 num_mac;
+ u32 hw_rev;
+
+ /************************
+ * 1. Allocating HW data
+ ************************/
+ hw = iwl_alloc_all(cfg);
+ if (!hw) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ priv = hw->priv;
+ priv->bus = bus;
+ bus_set_drv_data(priv->bus, priv);
+
+ /* At this point both hw and priv are allocated. */
+
+ SET_IEEE80211_DEV(hw, priv->bus->dev);
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
priv->cfg = cfg;
- priv->pci_dev = pdev;
priv->inta_mask = CSR_INI_SET_MASK;
/* is antenna coupling more than 35dB ? */
@@ -3440,53 +3664,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (iwl_alloc_traffic_mem(priv))
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
- /**************************
- * 2. Initializing PCI bus
- **************************/
- pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
- PCIE_LINK_STATE_CLKPM);
-
- if (pci_enable_device(pdev)) {
- err = -ENODEV;
- goto out_ieee80211_free_hw;
- }
-
- pci_set_master(pdev);
-
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
- if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
- if (err) {
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- /* both attempts failed: */
- if (err) {
- IWL_WARN(priv, "No suitable DMA available.\n");
- goto out_pci_disable_device;
- }
- }
-
- err = pci_request_regions(pdev, DRV_NAME);
- if (err)
- goto out_pci_disable_device;
-
- pci_set_drvdata(pdev, priv);
-
-
- /***********************
- * 3. Read REV register
- ***********************/
- priv->hw_base = pci_iomap(pdev, 0, 0);
- if (!priv->hw_base) {
- err = -ENODEV;
- goto out_pci_release_regions;
- }
-
- IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
- (unsigned long long) pci_resource_len(pdev, 0));
- IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
-
/* these spin locks will be used in apm_ops.init and EEPROM access
* we should init now
*/
@@ -3500,17 +3677,21 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+ /***********************
+ * 3. Read REV register
+ ***********************/
hw_rev = iwl_hw_detect(priv);
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
priv->cfg->name, hw_rev);
- /* We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state */
- pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+ err = iwl_trans_register(&priv->trans, priv);
+ if (err)
+ goto out_free_traffic_mem;
- if (iwl_prepare_card_hw(priv)) {
+ if (trans_prepare_card_hw(&priv->trans)) {
+ err = -EIO;
IWL_WARN(priv, "Failed, HW not ready\n");
- goto out_iounmap;
+ goto out_free_trans;
}
/*****************
@@ -3520,7 +3701,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = iwl_eeprom_init(priv, hw_rev);
if (err) {
IWL_ERR(priv, "Unable to init EEPROM\n");
- goto out_iounmap;
+ goto out_free_trans;
}
err = iwl_eeprom_check_version(priv);
if (err)
@@ -3543,10 +3724,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->hw->wiphy->n_addresses++;
}
+ /* initialize all valid contexts */
+ iwl_init_context(priv);
+
/************************
* 5. Setup HW constants
************************/
if (iwl_set_hw_params(priv)) {
+ err = -ENOENT;
IWL_ERR(priv, "failed to set hw parameters\n");
goto out_free_eeprom;
}
@@ -3563,36 +3748,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/********************
* 7. Setup services
********************/
- spin_lock_irqsave(&priv->lock, flags);
- iwl_disable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- pci_enable_msi(priv->pci_dev);
-
- iwl_alloc_isr_ict(priv);
-
- err = request_irq(priv->pci_dev->irq, iwl_isr_ict,
- IRQF_SHARED, DRV_NAME, priv);
- if (err) {
- IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
- goto out_disable_msi;
- }
-
iwl_setup_deferred_work(priv);
iwl_setup_rx_handlers(priv);
iwl_testmode_init(priv);
/*********************************************
- * 8. Enable interrupts and read RFKILL state
+ * 8. Enable interrupts
*********************************************/
- /* enable rfkill interrupt: hw bug w/a */
- pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
- if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
- pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
- }
-
iwl_enable_rfkill_int(priv);
/* If platform's RF_KILL switch is NOT set to KILL */
@@ -3607,7 +3770,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_power_initialize(priv);
iwl_tt_initialize(priv);
- init_completion(&priv->_agn.firmware_loading_complete);
+ init_completion(&priv->firmware_loading_complete);
err = iwl_request_firmware(priv, true);
if (err)
@@ -3615,44 +3778,32 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
- out_destroy_workqueue:
+out_destroy_workqueue:
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
- free_irq(priv->pci_dev->irq, priv);
- iwl_free_isr_ict(priv);
- out_disable_msi:
- pci_disable_msi(priv->pci_dev);
iwl_uninit_drv(priv);
- out_free_eeprom:
+out_free_eeprom:
iwl_eeprom_free(priv);
- out_iounmap:
- pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
- pci_set_drvdata(pdev, NULL);
- pci_release_regions(pdev);
- out_pci_disable_device:
- pci_disable_device(pdev);
- out_ieee80211_free_hw:
+out_free_trans:
+ trans_free(&priv->trans);
+out_free_traffic_mem:
iwl_free_traffic_mem(priv);
ieee80211_free_hw(priv->hw);
- out:
+out:
return err;
}
-static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+void __devexit iwl_remove(struct iwl_priv * priv)
{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
unsigned long flags;
- if (!priv)
- return;
-
- wait_for_completion(&priv->_agn.firmware_loading_complete);
+ wait_for_completion(&priv->firmware_loading_complete);
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
iwl_dbgfs_unregister(priv);
- sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+ sysfs_remove_group(&priv->bus->dev->kobj,
+ &iwl_attribute_group);
/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
* to be called and iwl_down since we are removing the device
@@ -3680,17 +3831,15 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_synchronize_irq(priv);
+ trans_sync_irq(&priv->trans);
- iwl_dealloc_ucode_pci(priv);
+ iwl_dealloc_ucode(priv);
- if (priv->rxq.bd)
- iwlagn_rx_queue_free(priv, &priv->rxq);
- iwlagn_hw_txq_ctx_free(priv);
+ trans_rx_free(&priv->trans);
+ trans_tx_free(&priv->trans);
iwl_eeprom_free(priv);
-
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
@@ -3701,16 +3850,11 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
priv->workqueue = NULL;
iwl_free_traffic_mem(priv);
- free_irq(priv->pci_dev->irq, priv);
- pci_disable_msi(priv->pci_dev);
- pci_iounmap(pdev, priv->hw_base);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
+ trans_free(&priv->trans);
- iwl_uninit_drv(priv);
+ bus_set_drv_data(priv->bus, NULL);
- iwl_free_isr_ict(priv);
+ iwl_uninit_drv(priv);
dev_kfree_skb(priv->beacon_skb);
@@ -3723,206 +3867,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
* driver and module entry point
*
*****************************************************************************/
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
- {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
-
-/* 5300 Series WiFi */
- {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
-
-/* 5350 Series WiFi/WiMax */
- {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
-
-/* 5150 Series Wifi/WiMax */
- {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
-
- {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
-
-/* 6x00 Series */
- {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
- {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
-
-/* 6x05 Series */
- {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
-
-/* 6x30 Series */
- {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
-
-/* 6x50 WiFi/WiMax Series */
- {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
-
-/* 6150 WiFi/WiMax Series */
- {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
- {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
-
-/* 1000 Series WiFi */
- {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
-
-/* 100 Series WiFi */
- {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
- {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
-
-/* 130 Series WiFi */
- {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
- {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
-
-/* 2x00 Series */
- {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
-
-/* 2x30 Series */
- {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
-
-/* 6x35 Series */
- {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
-
-/* 105 Series */
- {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
- {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
-
-/* 135 Series */
- {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
- {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
- {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
-
- {0}
-};
-MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
-
-static struct pci_driver iwl_driver = {
- .name = DRV_NAME,
- .id_table = iwl_hw_card_ids,
- .probe = iwl_pci_probe,
- .remove = __devexit_p(iwl_pci_remove),
- .driver.pm = IWL_PM_OPS,
-};
-
static int __init iwl_init(void)
{
@@ -3936,12 +3880,10 @@ static int __init iwl_init(void)
return ret;
}
- ret = pci_register_driver(&iwl_driver);
- if (ret) {
- pr_err("Unable to initialize PCI module\n");
- goto error_register;
- }
+ ret = iwl_pci_register_driver();
+ if (ret)
+ goto error_register;
return ret;
error_register:
@@ -3951,7 +3893,7 @@ error_register:
static void __exit iwl_exit(void)
{
- pci_unregister_driver(&iwl_driver);
+ iwl_pci_unregister_driver();
iwlagn_rate_control_unregister();
}
@@ -3993,3 +3935,51 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
+
+module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO);
+MODULE_PARM_DESC(wd_disable,
+ "Disable stuck queue watchdog timer (default: 0 [enabled])");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ * Able to scan and finding all the available AP
+ * Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+module_param_named(bt_coex_active, iwlagn_mod_params.bt_coex_active,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bt co-exist (default: enable)");
+
+module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode, "0=system default, "
+ "1=On(RF On)/Off(RF Off), 2=blinking (default: 0)");
+
+module_param_named(power_save, iwlagn_mod_params.power_save,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(power_save,
+ "enable WiFi power management (default: disable)");
+
+module_param_named(power_level, iwlagn_mod_params.power_level,
+ int, S_IRUGO);
+MODULE_PARM_DESC(power_level,
+ "default power save level (range from 1 - 5, default: 1)");
+
+/*
+ * For now, keep using power level 1 instead of automatically
+ * adjusting ...
+ */
+module_param_named(no_sleep_autoadjust, iwlagn_mod_params.no_sleep_autoadjust,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(no_sleep_autoadjust,
+ "don't automatically adjust sleep level "
+ "according to maximum network latency (default: true)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index d1716844002e..d941c4c98e4b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -109,42 +109,25 @@ extern struct iwl_cfg iwl135_bg_cfg;
extern struct iwl_cfg iwl135_bgn_cfg;
extern struct iwl_mod_params iwlagn_mod_params;
-extern struct iwl_hcmd_ops iwlagn_hcmd;
-extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
-extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
extern struct ieee80211_ops iwlagn_hw_ops;
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);
-/* call this function to flush any scheduled tasklet */
-static inline void iwl_synchronize_irq(struct iwl_priv *priv)
+static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
{
- /* wait to make sure we flush pending tasklet*/
- synchronize_irq(priv->pci_dev->irq);
- tasklet_kill(&priv->irq_tasklet);
+ hdr->op_code = cmd;
+ hdr->first_group = 0;
+ hdr->groups_num = 1;
+ hdr->data_valid = 1;
}
-int iwl_prepare_card_hw(struct iwl_priv *priv);
-
-int iwlagn_start_device(struct iwl_priv *priv);
-void iwlagn_stop_device(struct iwl_priv *priv);
-
/* tx queue */
-void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
- int txq_id, u32 index);
-void iwlagn_tx_queue_set_status(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- int tx_fifo_id, int scd_retry);
-void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask);
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);
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
@@ -161,41 +144,29 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv);
int iwlagn_run_init_ucode(struct iwl_priv *priv);
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image,
- int subtype, int alternate_subtype);
+ enum iwlagn_ucode_type ucode_type);
/* lib */
void iwl_check_abort_status(struct iwl_priv *priv,
u8 frame_count, u32 status);
-void iwlagn_rx_handler_setup(struct iwl_priv *priv);
-void iwlagn_setup_deferred_work(struct iwl_priv *priv);
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);
-const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
- size_t offset);
-void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwlagn_hw_nic_init(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);
/* rx */
-void iwlagn_rx_queue_restock(struct iwl_priv *priv);
-void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority);
-void iwlagn_rx_replenish(struct iwl_priv *priv);
-void iwlagn_rx_replenish_now(struct iwl_priv *priv);
-void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwlagn_rxq_stop(struct iwl_priv *priv);
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 iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- dma_addr_t addr, u16 len, u8 reset);
+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);
@@ -203,18 +174,12 @@ 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);
-void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv,
- struct ieee80211_sta *sta,
- int tid, int frame_limit);
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);
-void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv);
-int iwlagn_txq_ctx_alloc(struct iwl_priv *priv);
-void iwlagn_txq_ctx_reset(struct iwl_priv *priv);
-void iwlagn_txq_ctx_stop(struct iwl_priv *priv);
static inline u32 iwl_tx_status_to_mac80211(u32 status)
{
@@ -249,10 +214,6 @@ void iwlagn_post_scan(struct iwl_priv *priv);
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add);
-/* hcmd */
-int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
-int iwlagn_send_beacon_cmd(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,
@@ -260,6 +221,8 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
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);
+void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv);
+void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena);
#ifdef CONFIG_IWLWIFI_DEBUG
const char *iwl_get_tx_fail_reason(u32 status);
@@ -283,11 +246,13 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- struct ieee80211_key_conf *key, u8 sta_id);
+ struct ieee80211_key_conf *key,
+ struct ieee80211_sta *sta);
int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- struct ieee80211_key_conf *key, u8 sta_id);
+ struct ieee80211_key_conf *key,
+ struct ieee80211_sta *sta);
void iwl_update_tkip_key(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
+ struct ieee80211_vif *vif,
struct ieee80211_key_conf *keyconf,
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
@@ -296,6 +261,8 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
int tid);
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
+int iwl_update_bcast_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
int iwl_update_bcast_stations(struct iwl_priv *priv);
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -343,6 +310,9 @@ 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 void iwl_testmode_init(struct iwl_priv *priv);
extern void iwl_testmode_cleanup(struct iwl_priv *priv);
#else
@@ -352,6 +322,13 @@ int iwl_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,
+ struct netlink_callback *cb,
+ void *data, int len)
+{
+ return -ENOSYS;
+}
+static inline
void iwl_testmode_init(struct iwl_priv *priv)
{
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h
new file mode 100644
index 000000000000..f3ee1c0c004c
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-bus.h
@@ -0,0 +1,139 @@
+/******************************************************************************
+ *
+ * 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_pci_h__
+#define __iwl_pci_h__
+
+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
+ * @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
+ * @wread32: read a dword at register at offset ofs
+ */
+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 {
+ /* Common data to all buses */
+ void *drv_data; /* driver's context */
+ struct device *dev;
+ struct iwl_bus_ops *ops;
+
+ unsigned int irq;
+
+ /* pointer to bus specific struct */
+ /*Ensure that this pointer will always be aligned to sizeof pointer */
+ char bus_specific[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+static inline bool bus_get_pm_support(struct iwl_bus *bus)
+{
+ return bus->ops->get_pm_support(bus);
+}
+
+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);
+}
+
+static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val)
+{
+ bus->ops->write8(bus, ofs, val);
+}
+
+static inline void bus_write32(struct iwl_bus *bus, u32 ofs, u32 val)
+{
+ bus->ops->write32(bus, ofs, val);
+}
+
+static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs)
+{
+ return bus->ops->read32(bus, ofs);
+}
+
+int __must_check iwl_pci_register_driver(void);
+void iwl_pci_unregister_driver(void);
+
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6ee5f1aa555c..e9e9d1d1778d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -188,6 +188,13 @@ enum {
REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd,
+ REPLY_WOWLAN_PATTERNS = 0xe0,
+ REPLY_WOWLAN_WAKEUP_FILTER = 0xe1,
+ REPLY_WOWLAN_TSC_RSC_PARAMS = 0xe2,
+ REPLY_WOWLAN_TKIP_PARAMS = 0xe3,
+ REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4,
+ REPLY_WOWLAN_GET_STATUS = 0xe5,
+
REPLY_MAX = 0xff
};
@@ -384,18 +391,6 @@ struct iwl_tx_ant_config_cmd {
#define UCODE_VALID_OK cpu_to_le32(0x1)
-enum iwlagn_ucode_subtype {
- UCODE_SUBTYPE_REGULAR = 0,
- UCODE_SUBTYPE_REGULAR_NEW = 1,
- UCODE_SUBTYPE_INIT = 9,
-
- /*
- * Not a valid subtype, the ucode has just a u8, so
- * we can use something > 0xff for this value.
- */
- UCODE_SUBTYPE_NONE_LOADED = 0x100,
-};
-
/**
* REPLY_ALIVE = 0x1 (response only, not a command)
*
@@ -844,6 +839,8 @@ struct iwl_qosparam_cmd {
#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
#define STA_KEY_MAX_NUM 8
#define STA_KEY_MAX_NUM_PAN 16
+/* must not match WEP_INVALID_OFFSET */
+#define IWLAGN_HW_KEY_DEFAULT 0xfe
/* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01
@@ -984,15 +981,26 @@ struct iwl_rem_sta_cmd {
u8 reserved2[2];
} __packed;
-#define IWL_TX_FIFO_BK_MSK cpu_to_le32(BIT(0))
-#define IWL_TX_FIFO_BE_MSK cpu_to_le32(BIT(1))
-#define IWL_TX_FIFO_VI_MSK cpu_to_le32(BIT(2))
-#define IWL_TX_FIFO_VO_MSK cpu_to_le32(BIT(3))
+
+/* WiFi queues mask */
+#define IWL_SCD_BK_MSK cpu_to_le32(BIT(0))
+#define IWL_SCD_BE_MSK cpu_to_le32(BIT(1))
+#define IWL_SCD_VI_MSK cpu_to_le32(BIT(2))
+#define IWL_SCD_VO_MSK cpu_to_le32(BIT(3))
+#define IWL_SCD_MGMT_MSK cpu_to_le32(BIT(3))
+
+/* PAN queues mask */
+#define IWL_PAN_SCD_BK_MSK cpu_to_le32(BIT(4))
+#define IWL_PAN_SCD_BE_MSK cpu_to_le32(BIT(5))
+#define IWL_PAN_SCD_VI_MSK cpu_to_le32(BIT(6))
+#define IWL_PAN_SCD_VO_MSK cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MGMT_MSK cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MULTICAST_MSK cpu_to_le32(BIT(8))
+
#define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00)
#define IWL_DROP_SINGLE 0
-#define IWL_DROP_SELECTED 1
-#define IWL_DROP_ALL 2
+#define IWL_DROP_ALL (BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN))
/*
* REPLY_TXFIFO_FLUSH = 0x1e(command and response)
@@ -1932,6 +1940,9 @@ struct iwl_bt_cmd {
/* Disable Sync PSPoll on SCO/eSCO */
#define IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE BIT(7)
+#define IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD -75 /* dBm */
+#define IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD -65 /* dBm */
+
#define IWLAGN_BT_PRIO_BOOST_MAX 0xFF
#define IWLAGN_BT_PRIO_BOOST_MIN 0x00
#define IWLAGN_BT_PRIO_BOOST_DEFAULT 0xF0
@@ -2457,8 +2468,8 @@ struct iwl_scanstart_notification {
__le32 status;
} __packed;
-#define SCAN_OWNER_STATUS 0x1;
-#define MEASURE_OWNER_STATUS 0x2;
+#define SCAN_OWNER_STATUS 0x1
+#define MEASURE_OWNER_STATUS 0x2
#define IWL_PROBE_STATUS_OK 0
#define IWL_PROBE_STATUS_TX_FAILED BIT(0)
@@ -3153,7 +3164,6 @@ struct iwl_enhance_sensitivity_cmd {
/* The default calibrate table size if not specified by firmware */
#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
enum {
- IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
IWL_PHY_CALIBRATE_DC_CMD = 8,
IWL_PHY_CALIBRATE_LO_CMD = 9,
IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
@@ -3166,22 +3176,36 @@ enum {
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253)
-#define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff)
-
/* This enum defines the bitmap of various calibrations to enable in both
* init ucode and runtime ucode through CALIBRATION_CFG_CMD.
*/
enum iwl_ucode_calib_cfg {
- IWL_CALIB_CFG_RX_BB_IDX,
- IWL_CALIB_CFG_DC_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_TEMPERATURE_IDX,
- IWL_CALIB_CFG_PAPD_IDX,
+ IWL_CALIB_CFG_RX_BB_IDX = BIT(0),
+ IWL_CALIB_CFG_DC_IDX = BIT(1),
+ IWL_CALIB_CFG_LO_IDX = BIT(2),
+ IWL_CALIB_CFG_TX_IQ_IDX = BIT(3),
+ IWL_CALIB_CFG_RX_IQ_IDX = BIT(4),
+ IWL_CALIB_CFG_NOISE_IDX = BIT(5),
+ IWL_CALIB_CFG_CRYSTAL_IDX = BIT(6),
+ IWL_CALIB_CFG_TEMPERATURE_IDX = BIT(7),
+ IWL_CALIB_CFG_PAPD_IDX = BIT(8),
+ IWL_CALIB_CFG_SENSITIVITY_IDX = BIT(9),
+ IWL_CALIB_CFG_TX_PWR_IDX = BIT(10),
};
+#define IWL_CALIB_INIT_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_NOISE_IDX | \
+ IWL_CALIB_CFG_CRYSTAL_IDX | \
+ IWL_CALIB_CFG_TEMPERATURE_IDX | \
+ IWL_CALIB_CFG_PAPD_IDX | \
+ IWL_CALIB_CFG_SENSITIVITY_IDX | \
+ IWL_CALIB_CFG_TX_PWR_IDX)
+
+#define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK cpu_to_le32(BIT(0))
struct iwl_calib_cfg_elmnt_s {
__le32 is_enable;
@@ -3215,15 +3239,6 @@ struct iwl_calib_cmd {
u8 data[0];
} __packed;
-/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
-struct iwl_calib_diff_gain_cmd {
- struct iwl_calib_hdr hdr;
- s8 diff_gain_a; /* see above */
- s8 diff_gain_b;
- s8 diff_gain_c;
- u8 reserved1;
-} __packed;
-
struct iwl_calib_xtal_freq_cmd {
struct iwl_calib_hdr hdr;
u8 cap_pin1;
@@ -3231,11 +3246,11 @@ struct iwl_calib_xtal_freq_cmd {
u8 pad[2];
} __packed;
-#define DEFAULT_RADIO_SENSOR_OFFSET 2700
+#define DEFAULT_RADIO_SENSOR_OFFSET cpu_to_le16(2700)
struct iwl_calib_temperature_offset_cmd {
struct iwl_calib_hdr hdr;
- s16 radio_sensor_offset;
- s16 reserved;
+ __le16 radio_sensor_offset;
+ __le16 reserved;
} __packed;
/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
@@ -3756,6 +3771,127 @@ struct iwl_bt_coex_prot_env_cmd {
u8 reserved[2];
} __attribute__((packed));
+/*
+ * REPLY_WOWLAN_PATTERNS
+ */
+#define IWLAGN_WOWLAN_MIN_PATTERN_LEN 16
+#define IWLAGN_WOWLAN_MAX_PATTERN_LEN 128
+
+struct iwlagn_wowlan_pattern {
+ u8 mask[IWLAGN_WOWLAN_MAX_PATTERN_LEN / 8];
+ u8 pattern[IWLAGN_WOWLAN_MAX_PATTERN_LEN];
+ u8 mask_size;
+ u8 pattern_size;
+ __le16 reserved;
+} __packed;
+
+#define IWLAGN_WOWLAN_MAX_PATTERNS 20
+
+struct iwlagn_wowlan_patterns_cmd {
+ __le32 n_patterns;
+ struct iwlagn_wowlan_pattern patterns[];
+} __packed;
+
+/*
+ * REPLY_WOWLAN_WAKEUP_FILTER
+ */
+enum iwlagn_wowlan_wakeup_filters {
+ IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
+ IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
+ IWLAGN_WOWLAN_WAKEUP_BEACON_MISS = BIT(2),
+ IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3),
+ IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4),
+ IWLAGN_WOWLAN_WAKEUP_RFKILL = BIT(5),
+ IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR = BIT(6),
+ IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(7),
+ IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(8),
+ IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(9),
+ IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(10),
+};
+
+struct iwlagn_wowlan_wakeup_filter_cmd {
+ __le32 enabled;
+ __le16 non_qos_seq;
+ u8 min_sleep_seconds;
+ u8 reserved;
+ __le16 qos_seq[8];
+};
+
+/*
+ * REPLY_WOWLAN_TSC_RSC_PARAMS
+ */
+#define IWLAGN_NUM_RSC 16
+
+struct tkip_sc {
+ __le16 iv16;
+ __le16 pad;
+ __le32 iv32;
+} __packed;
+
+struct iwlagn_tkip_rsc_tsc {
+ struct tkip_sc unicast_rsc[IWLAGN_NUM_RSC];
+ struct tkip_sc multicast_rsc[IWLAGN_NUM_RSC];
+ struct tkip_sc tsc;
+} __packed;
+
+struct aes_sc {
+ __le64 pn;
+} __packed;
+
+struct iwlagn_aes_rsc_tsc {
+ struct aes_sc unicast_rsc[IWLAGN_NUM_RSC];
+ struct aes_sc multicast_rsc[IWLAGN_NUM_RSC];
+ struct aes_sc tsc;
+} __packed;
+
+union iwlagn_all_tsc_rsc {
+ struct iwlagn_tkip_rsc_tsc tkip;
+ struct iwlagn_aes_rsc_tsc aes;
+};
+
+struct iwlagn_wowlan_rsc_tsc_params_cmd {
+ union iwlagn_all_tsc_rsc all_tsc_rsc;
+} __packed;
+
+/*
+ * REPLY_WOWLAN_TKIP_PARAMS
+ */
+#define IWLAGN_MIC_KEY_SIZE 8
+#define IWLAGN_P1K_SIZE 5
+struct iwlagn_mic_keys {
+ u8 tx[IWLAGN_MIC_KEY_SIZE];
+ u8 rx_unicast[IWLAGN_MIC_KEY_SIZE];
+ u8 rx_mcast[IWLAGN_MIC_KEY_SIZE];
+} __packed;
+
+struct iwlagn_p1k_cache {
+ __le16 p1k[IWLAGN_P1K_SIZE];
+} __packed;
+
+#define IWLAGN_NUM_RX_P1K_CACHE 2
+
+struct iwlagn_wowlan_tkip_params_cmd {
+ struct iwlagn_mic_keys mic_keys;
+ struct iwlagn_p1k_cache tx;
+ struct iwlagn_p1k_cache rx_uni[IWLAGN_NUM_RX_P1K_CACHE];
+ struct iwlagn_p1k_cache rx_multi[IWLAGN_NUM_RX_P1K_CACHE];
+} __packed;
+
+/*
+ * REPLY_WOWLAN_KEK_KCK_MATERIAL
+ */
+
+#define IWLAGN_KCK_MAX_SIZE 32
+#define IWLAGN_KEK_MAX_SIZE 32
+
+struct iwlagn_wowlan_kek_kck_material_cmd {
+ u8 kck[IWLAGN_KCK_MAX_SIZE];
+ u8 kek[IWLAGN_KEK_MAX_SIZE];
+ __le16 kck_len;
+ __le16 kek_len;
+ __le64 replay_ctr;
+} __packed;
+
/******************************************************************************
* (13)
* Union of all expected notifications/responses:
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 45cc51c9c93e..cf376f62b2f6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -42,27 +42,7 @@
#include "iwl-sta.h"
#include "iwl-helpers.h"
#include "iwl-agn.h"
-
-
-/*
- * set bt_coex_active to true, uCode will do kill/defer
- * every time the priority line is asserted (BT is sending signals on the
- * priority line in the PCIx).
- * set bt_coex_active to false, uCode will ignore the BT activity and
- * perform the normal operation
- *
- * User might experience transmit issue on some platform due to WiFi/BT
- * co-exist problem. The possible behaviors are:
- * Able to scan and finding all the available AP
- * Not able to associate with any AP
- * On those platforms, WiFi communication can be restored by set
- * "bt_coex_active" module parameter to "false"
- *
- * default: bt_coex_active = true (BT_COEX_ENABLE)
- */
-bool bt_coex_active = true;
-module_param(bt_coex_active, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
+#include "iwl-trans.h"
u32 iwl_debug_level;
@@ -164,7 +144,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ);
@@ -174,7 +154,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->bitrates = rates;
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ);
@@ -229,12 +209,12 @@ int iwlcore_init_geos(struct iwl_priv *priv)
priv->tx_power_next = max_tx_power;
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
- priv->cfg->sku & IWL_SKU_A) {
+ priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
+ char buf[32];
+ bus_get_hw_id(priv->bus, buf, sizeof(buf));
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
- "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
- priv->pci_dev->device,
- priv->pci_dev->subsystem_device);
- priv->cfg->sku &= ~IWL_SKU_A;
+ "Please send your %s to maintainer.\n", buf);
+ priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
}
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
@@ -383,6 +363,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
}
+ ctx->beacon_int = beacon_int;
+
tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
interval_tm = beacon_int * TIME_UNIT;
rem = do_div(tsf, interval_tm);
@@ -396,8 +378,8 @@ 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 iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
- sizeof(ctx->timing), &ctx->timing);
+ return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd,
+ CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
}
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
@@ -547,19 +529,6 @@ int iwl_full_rxon_required(struct iwl_priv *priv,
return 0;
}
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
- /*
- * Assign the lowest rate -- should really get this from
- * the beacon skb from mac80211.
- */
- if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
- return IWL_RATE_1M_PLCP;
- else
- return IWL_RATE_6M_PLCP;
-}
-
static void _iwl_set_rxon_ht(struct iwl_priv *priv,
struct iwl_ht_config *ht_conf,
struct iwl_rxon_context *ctx)
@@ -619,8 +588,7 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv,
rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
}
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+ iwlagn_set_rxon_chain(priv, ctx);
IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x\n",
@@ -874,12 +842,12 @@ static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
unsigned long flags;
struct iwl_notification_wait *wait_entry;
- spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags);
- list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list)
+ spin_lock_irqsave(&priv->notif_wait_lock, flags);
+ list_for_each_entry(wait_entry, &priv->notif_waits, list)
wait_entry->aborted = true;
- spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags);
+ spin_unlock_irqrestore(&priv->notif_wait_lock, flags);
- wake_up_all(&priv->_agn.notif_waitq);
+ wake_up_all(&priv->notif_waitq);
}
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
@@ -1018,8 +986,6 @@ void iwl_apm_stop(struct iwl_priv *priv)
int iwl_apm_init(struct iwl_priv *priv)
{
int ret = 0;
- u16 lctl;
-
IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
/*
@@ -1048,27 +1014,7 @@ int iwl_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
- /*
- * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
- * Check if BIOS (or OS) enabled L1-ASPM on this device.
- * If so (likely), disable L0S, so device moves directly L0->L1;
- * costs negligible amount of power savings.
- * If not (unlikely), enable L0S, so there is at least some
- * power savings, even without L1.
- */
- lctl = iwl_pcie_link_ctl(priv);
- if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
- PCI_CFG_LINK_CTRL_VAL_L1_EN) {
- /* L1-ASPM enabled; disable(!) L0S */
- iwl_set_bit(priv, CSR_GIO_REG,
- CSR_GIO_REG_VAL_L0S_ENABLED);
- IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
- } else {
- /* L1-ASPM disabled; enable(!) L0S */
- iwl_clear_bit(priv, CSR_GIO_REG,
- CSR_GIO_REG_VAL_L0S_ENABLED);
- IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
- }
+ bus_apm_config(priv->bus);
/* Configure analog phase-lock-loop before activating to D0A */
if (priv->cfg->base_params->pll_cfg_val)
@@ -1127,9 +1073,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
if (priv->tx_power_user_lmt == tx_power && !force)
return 0;
- if (!priv->cfg->ops->lib->send_tx_power)
- return -EOPNOTSUPP;
-
if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
IWL_WARN(priv,
"Requested user TXPOWER %d below lower limit %d.\n",
@@ -1163,7 +1106,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
prev_tx_power = priv->tx_power_user_lmt;
priv->tx_power_user_lmt = tx_power;
- ret = priv->cfg->ops->lib->send_tx_power(priv);
+ ret = iwlagn_send_tx_power(priv);
/* if fail to set tx_power, restore the orig. tx power */
if (ret) {
@@ -1182,7 +1125,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
.kill_cts_mask = 0,
};
- if (!bt_coex_active)
+ if (!iwlagn_mod_params.bt_coex_active)
bt_cmd.flags = BT_COEX_DISABLE;
else
bt_cmd.flags = BT_COEX_ENABLE;
@@ -1191,8 +1134,8 @@ 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 (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(struct iwl_bt_cmd), &bt_cmd))
+ if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+ CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
@@ -1204,11 +1147,13 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
};
if (flags & CMD_ASYNC)
- return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
+ return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD,
+ CMD_ASYNC,
sizeof(struct iwl_statistics_cmd),
- &statistics_cmd, NULL);
+ &statistics_cmd);
else
- return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+ return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD,
+ CMD_SYNC,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
}
@@ -1275,10 +1220,9 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
iwl_connection_init_rx_config(priv, ctx);
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+ iwlagn_set_rxon_chain(priv, ctx);
- return iwlcore_commit_rxon(priv, ctx);
+ return iwlagn_commit_rxon(priv, ctx);
}
static int iwl_setup_interface(struct iwl_priv *priv,
@@ -1431,26 +1375,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
}
-int iwl_alloc_txq_mem(struct iwl_priv *priv)
-{
- if (!priv->txq)
- 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");
- return -ENOMEM;
- }
- return 0;
-}
-
-void iwl_free_txq_mem(struct iwl_priv *priv)
-{
- kfree(priv->txq);
- priv->txq = NULL;
-}
-
#ifdef CONFIG_IWLWIFI_DEBUGFS
#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
@@ -1912,7 +1836,7 @@ void iwl_setup_watchdog(struct iwl_priv *priv)
{
unsigned int timeout = priv->cfg->base_params->wd_timeout;
- if (timeout)
+ if (timeout && !iwlagn_mod_params.wd_disable)
mod_timer(&priv->watchdog,
jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));
else
@@ -1973,35 +1897,28 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
#ifdef CONFIG_PM
-int iwl_pci_suspend(struct device *device)
+int iwl_suspend(struct iwl_priv *priv)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_priv *priv = pci_get_drvdata(pdev);
-
/*
* 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 :-)
*/
- iwl_apm_stop(priv);
+ if (!priv->wowlan)
+ iwl_apm_stop(priv);
return 0;
}
-int iwl_pci_resume(struct device *device)
+int iwl_resume(struct iwl_priv *priv)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_priv *priv = pci_get_drvdata(pdev);
bool hw_rfkill = false;
- /*
- * We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state.
- */
- pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
iwl_enable_interrupts(priv);
if (!(iwl_read32(priv, CSR_GP_CNTRL) &
@@ -2018,13 +1935,4 @@ int iwl_pci_resume(struct device *device)
return 0;
}
-const struct dev_pm_ops iwl_pm_ops = {
- .suspend = iwl_pci_suspend,
- .resume = iwl_pci_resume,
- .freeze = iwl_pci_suspend,
- .thaw = iwl_pci_resume,
- .poweroff = iwl_pci_suspend,
- .restore = iwl_pci_resume,
-};
-
#endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index a54d416ec345..3e6bb734dcb7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -76,95 +76,29 @@ struct iwl_cmd;
#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
-#define IWL_PCI_DEVICE(dev, subdev, cfg) \
- .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
- .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
- .driver_data = (kernel_ulong_t)&(cfg)
-
#define TIME_UNIT 1024
-#define IWL_SKU_G 0x1
-#define IWL_SKU_A 0x2
-#define IWL_SKU_N 0x8
-
#define IWL_CMD(x) case x: return #x
-struct iwl_hcmd_ops {
- int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
- void (*set_rxon_chain)(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx);
- int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
- void (*send_bt_config)(struct iwl_priv *priv);
- int (*set_pan_params)(struct iwl_priv *priv);
-};
-
-struct iwl_hcmd_utils_ops {
- u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data);
- void (*gain_computation)(struct iwl_priv *priv,
- u32 *average_noise,
- u16 min_average_noise_antennat_i,
- u32 min_average_noise,
- u8 default_chain);
- void (*chain_noise_reset)(struct iwl_priv *priv);
- void (*tx_cmd_protection)(struct iwl_priv *priv,
- struct ieee80211_tx_info *info,
- __le16 fc, __le32 *tx_flags);
- int (*calc_rssi)(struct iwl_priv *priv,
- struct iwl_rx_phy_res *rx_resp);
- int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
- void (*post_scan)(struct iwl_priv *priv);
-};
-
-struct iwl_apm_ops {
- int (*init)(struct iwl_priv *priv);
- void (*config)(struct iwl_priv *priv);
-};
-
-struct iwl_temp_ops {
- void (*temperature)(struct iwl_priv *priv);
-};
-
struct iwl_lib_ops {
/* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv);
- /* setup Rx handler */
- void (*rx_handler_setup)(struct iwl_priv *priv);
- /* setup deferred work */
- void (*setup_deferred_work)(struct iwl_priv *priv);
+ /* setup BT Rx handler */
+ void (*bt_rx_handler_setup)(struct iwl_priv *priv);
+ /* setup BT related deferred work */
+ void (*bt_setup_deferred_work)(struct iwl_priv *priv);
/* cancel deferred work */
void (*cancel_deferred_work)(struct iwl_priv *priv);
- /* check validity of rtc data address */
- int (*is_valid_rtc_data_addr)(u32 addr);
int (*set_channel_switch)(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch);
- /* power management */
- struct iwl_apm_ops apm_ops;
-
- /* power */
- int (*send_tx_power) (struct iwl_priv *priv);
- void (*update_chain_flags)(struct iwl_priv *priv);
+ /* device specific configuration */
+ void (*nic_config)(struct iwl_priv *priv);
/* eeprom operations (as defined in iwl-eeprom.h) */
struct iwl_eeprom_ops eeprom_ops;
/* temperature */
- struct iwl_temp_ops temp_ops;
-
- int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
- void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
-
-};
-
-/* NIC specific ops */
-struct iwl_nic_ops {
- void (*additional_nic_config)(struct iwl_priv *priv);
-};
-
-struct iwl_ops {
- const struct iwl_lib_ops *lib;
- const struct iwl_hcmd_ops *hcmd;
- const struct iwl_hcmd_utils_ops *utils;
- const struct iwl_nic_ops *nic;
+ void (*temperature)(struct iwl_priv *priv);
};
struct iwl_mod_params {
@@ -176,6 +110,12 @@ struct iwl_mod_params {
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 */
};
/*
@@ -225,7 +165,7 @@ struct iwl_base_params {
* @ampdu_factor: Maximum A-MPDU length factor
* @ampdu_density: Minimum A-MPDU spacing
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
-*/
+ */
struct iwl_bt_params {
bool advanced_bt_coexist;
u8 bt_init_traffic_load;
@@ -238,19 +178,31 @@ struct iwl_bt_params {
};
/*
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
-*/
+ */
struct iwl_ht_params {
const bool ht_greenfield_support; /* if used set to true */
bool use_rts_for_aggregation;
+ enum ieee80211_smps_mode smps_mode;
};
/**
* struct iwl_cfg
+ * @name: Offical name of the device
* @fw_name_pre: Firmware filename prefix. The api version and extension
* (.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_min: Lowest version of uCode API supported by driver.
+ * @valid_tx_ant: valid transmit antenna
+ * @valid_rx_ant: valid receive antenna
+ * @sku: sku information from EEPROM
+ * @eeprom_ver: EEPROM version
+ * @eeprom_calib_ver: EEPROM calibration version
+ * @lib: pointer to the lib ops
+ * @additional_nic_config: additional nic configuration
+ * @base_params: pointer to basic parameters
+ * @ht_params: point to ht patameters
+ * @bt_params: pointer to bt parameters
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
* @need_dc_calib: need to perform init dc calibration
* @need_temp_offset_calib: need to perform temperature offset calibration
@@ -260,7 +212,6 @@ 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
- * @disable_otp_refresh: disable OTP refresh current limit
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
@@ -277,11 +228,7 @@ struct iwl_ht_params {
* }
*
* The ideal usage of this infrastructure is to treat a new ucode API
- * release as a new hardware revision. That is, through utilizing the
- * iwl_hcmd_utils_ops etc. we accommodate different command structures
- * and flows between hardware versions (4965/5000) as well as their API
- * versions.
- *
+ * release as a new hardware revision.
*/
struct iwl_cfg {
/* params specific to an individual device within a device family */
@@ -291,10 +238,11 @@ struct iwl_cfg {
const unsigned int ucode_api_min;
u8 valid_tx_ant;
u8 valid_rx_ant;
- unsigned int sku;
+ u16 sku;
u16 eeprom_ver;
u16 eeprom_calib_ver;
- const struct iwl_ops *ops;
+ const struct iwl_lib_ops *lib;
+ void (*additional_nic_config)(struct iwl_priv *priv);
/* params not likely to change within a device family */
struct iwl_base_params *base_params;
/* params likely to change within a device family */
@@ -309,7 +257,6 @@ struct iwl_cfg {
const bool rx_with_siso_diversity;
const bool internal_wimax_coex;
const bool iq_invert;
- const bool disable_otp_refresh;
};
/***************************
@@ -346,9 +293,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
int iwl_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p);
-int iwl_alloc_txq_mem(struct iwl_priv *priv);
-void iwl_free_txq_mem(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);
@@ -390,28 +334,8 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
/*****************************************************
* RX
******************************************************/
-void iwl_cmd_queue_free(struct iwl_priv *priv);
-void iwl_cmd_queue_unmap(struct iwl_priv *priv);
-int iwl_rx_queue_alloc(struct iwl_priv *priv);
-void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl_rx_queue *q);
-int iwl_rx_queue_space(const struct iwl_rx_queue *q);
-void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
-/* TX helpers */
-
-/*****************************************************
-* TX
-******************************************************/
-void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int slots_num, u32 txq_id);
-void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int slots_num, u32 txq_id);
-void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
-void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
void iwl_setup_watchdog(struct iwl_priv *priv);
/*****************************************************
* TX power
@@ -419,13 +343,6 @@ void iwl_setup_watchdog(struct iwl_priv *priv);
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
/*******************************************************************************
- * Rate
- ******************************************************************************/
-
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx);
-
-/*******************************************************************************
* Scanning
******************************************************************************/
void iwl_init_scan_params(struct iwl_priv *priv);
@@ -469,51 +386,19 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
*****************************************************/
const char *get_cmd_string(u8 cmd);
-int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
- struct iwl_host_cmd *cmd);
-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,
- u16 len, const void *data);
-int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
- const void *data,
- void (*callback)(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt));
-
-int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-
-
-/*****************************************************
- * PCI *
- *****************************************************/
-
-static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
-{
- int pos;
- u16 pci_lnk_ctl;
- pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
- pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
- return pci_lnk_ctl;
-}
-
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_pci_suspend(struct device *device);
-int iwl_pci_resume(struct device *device);
-extern const struct dev_pm_ops iwl_pm_ops;
-
-#define IWL_PM_OPS (&iwl_pm_ops)
-
-#else /* !CONFIG_PM */
-
-#define IWL_PM_OPS NULL
-
+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
******************************************************/
@@ -613,11 +498,7 @@ 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);
-static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
- return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
-}
+
static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
struct iwl_priv *priv, enum ieee80211_band band)
{
@@ -630,7 +511,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
priv->cfg->bt_params->advanced_bt_coexist;
}
-extern bool bt_coex_active;
extern bool bt_siso_mode;
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 5ab90ba7a024..d6dbb0423045 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -351,6 +351,7 @@
#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
+#define CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE (0x00000020)
/* GP Driver */
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 2824ccbcc1fc..f9a407e40aff 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -32,10 +32,10 @@
struct iwl_priv;
extern u32 iwl_debug_level;
-#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
-#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
-#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
-#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+#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)
#define iwl_print_hex_error(priv, p, len) \
do { \
@@ -78,8 +78,6 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
void iwl_dbgfs_unregister(struct iwl_priv *priv);
-extern int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
- int bufsz);
#else
static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
{
@@ -125,13 +123,13 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
/* 0x00000F00 - 0x00000100 */
#define IWL_DL_POWER (1 << 8)
#define IWL_DL_TEMP (1 << 9)
-#define IWL_DL_NOTIF (1 << 10)
+/* reserved (1 << 10) */
#define IWL_DL_SCAN (1 << 11)
/* 0x0000F000 - 0x00001000 */
#define IWL_DL_ASSOC (1 << 12)
#define IWL_DL_DROP (1 << 13)
-#define IWL_DL_TXPOWER (1 << 14)
-#define IWL_DL_AP (1 << 15)
+/* reserved (1 << 14) */
+#define IWL_DL_COEX (1 << 15)
/* 0x000F0000 - 0x00010000 */
#define IWL_DL_FW (1 << 16)
#define IWL_DL_RF_KILL (1 << 17)
@@ -171,12 +169,10 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#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)
-#define IWL_DEBUG_AP(p, f, a...) IWL_DEBUG(p, IWL_DL_AP, f, ## a)
-#define IWL_DEBUG_TXPOWER(p, f, a...) IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_COEX(p, f, a...) IWL_DEBUG(p, IWL_DL_COEX, f, ## a)
#define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
#define IWL_DEBUG_RATE_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_NOTIF(p, f, a...) IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)
#define IWL_DEBUG_ASSOC(p, f, a...) \
IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...) \
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 0e6a04b739ad..ec1485b2d3fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -227,7 +227,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
/* default is to dump the entire data segment */
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
priv->dbgfs_sram_offset = 0x800000;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT)
+ if (priv->ucode_type == IWL_UCODE_INIT)
priv->dbgfs_sram_len = priv->ucode_init.data.len;
else
priv->dbgfs_sram_len = priv->ucode_rt.data.len;
@@ -322,6 +322,19 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file,
return count;
}
+static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+
+ if (!priv->wowlan_sram)
+ return -ENODATA;
+
+ return simple_read_from_buffer(user_buf, count, ppos,
+ priv->wowlan_sram,
+ priv->ucode_wowlan.data.len);
+}
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -856,6 +869,7 @@ 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);
@@ -1915,121 +1929,121 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n");
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),
- priv->_agn.reply_tx_stats.pp_delay);
+ priv->reply_tx_stats.pp_delay);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),
- priv->_agn.reply_tx_stats.pp_few_bytes);
+ priv->reply_tx_stats.pp_few_bytes);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),
- priv->_agn.reply_tx_stats.pp_bt_prio);
+ priv->reply_tx_stats.pp_bt_prio);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),
- priv->_agn.reply_tx_stats.pp_quiet_period);
+ priv->reply_tx_stats.pp_quiet_period);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),
- priv->_agn.reply_tx_stats.pp_calc_ttak);
+ priv->reply_tx_stats.pp_calc_ttak);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
iwl_get_tx_fail_reason(
TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),
- priv->_agn.reply_tx_stats.int_crossed_retry);
+ priv->reply_tx_stats.int_crossed_retry);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),
- priv->_agn.reply_tx_stats.short_limit);
+ priv->reply_tx_stats.short_limit);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),
- priv->_agn.reply_tx_stats.long_limit);
+ priv->reply_tx_stats.long_limit);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),
- priv->_agn.reply_tx_stats.fifo_underrun);
+ priv->reply_tx_stats.fifo_underrun);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),
- priv->_agn.reply_tx_stats.drain_flow);
+ priv->reply_tx_stats.drain_flow);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),
- priv->_agn.reply_tx_stats.rfkill_flush);
+ priv->reply_tx_stats.rfkill_flush);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),
- priv->_agn.reply_tx_stats.life_expire);
+ priv->reply_tx_stats.life_expire);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),
- priv->_agn.reply_tx_stats.dest_ps);
+ priv->reply_tx_stats.dest_ps);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),
- priv->_agn.reply_tx_stats.host_abort);
+ priv->reply_tx_stats.host_abort);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),
- priv->_agn.reply_tx_stats.pp_delay);
+ priv->reply_tx_stats.pp_delay);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),
- priv->_agn.reply_tx_stats.sta_invalid);
+ priv->reply_tx_stats.sta_invalid);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),
- priv->_agn.reply_tx_stats.frag_drop);
+ priv->reply_tx_stats.frag_drop);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),
- priv->_agn.reply_tx_stats.tid_disable);
+ priv->reply_tx_stats.tid_disable);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),
- priv->_agn.reply_tx_stats.fifo_flush);
+ priv->reply_tx_stats.fifo_flush);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
iwl_get_tx_fail_reason(
TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),
- priv->_agn.reply_tx_stats.insuff_cf_poll);
+ priv->reply_tx_stats.insuff_cf_poll);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX),
- priv->_agn.reply_tx_stats.fail_hw_drop);
+ priv->reply_tx_stats.fail_hw_drop);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
iwl_get_tx_fail_reason(
TX_STATUS_FAIL_NO_BEACON_ON_RADAR),
- priv->_agn.reply_tx_stats.sta_color_mismatch);
+ priv->reply_tx_stats.sta_color_mismatch);
pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
- priv->_agn.reply_tx_stats.unknown);
+ priv->reply_tx_stats.unknown);
pos += scnprintf(buf + pos, bufsz - pos,
"\nStatistics_Agg_TX_Error:\n");
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK),
- priv->_agn.reply_agg_tx_stats.underrun);
+ priv->reply_agg_tx_stats.underrun);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK),
- priv->_agn.reply_agg_tx_stats.bt_prio);
+ priv->reply_agg_tx_stats.bt_prio);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK),
- priv->_agn.reply_agg_tx_stats.few_bytes);
+ priv->reply_agg_tx_stats.few_bytes);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK),
- priv->_agn.reply_agg_tx_stats.abort);
+ priv->reply_agg_tx_stats.abort);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
iwl_get_agg_tx_fail_reason(
AGG_TX_STATE_LAST_SENT_TTL_MSK),
- priv->_agn.reply_agg_tx_stats.last_sent_ttl);
+ priv->reply_agg_tx_stats.last_sent_ttl);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
iwl_get_agg_tx_fail_reason(
AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK),
- priv->_agn.reply_agg_tx_stats.last_sent_try);
+ priv->reply_agg_tx_stats.last_sent_try);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
iwl_get_agg_tx_fail_reason(
AGG_TX_STATE_LAST_SENT_BT_KILL_MSK),
- priv->_agn.reply_agg_tx_stats.last_sent_bt_kill);
+ priv->reply_agg_tx_stats.last_sent_bt_kill);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK),
- priv->_agn.reply_agg_tx_stats.scd_query);
+ priv->reply_agg_tx_stats.scd_query);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
iwl_get_agg_tx_fail_reason(
AGG_TX_STATE_TEST_BAD_CRC32_MSK),
- priv->_agn.reply_agg_tx_stats.bad_crc32);
+ priv->reply_agg_tx_stats.bad_crc32);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK),
- priv->_agn.reply_agg_tx_stats.response);
+ priv->reply_agg_tx_stats.response);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK),
- priv->_agn.reply_agg_tx_stats.dump_tx);
+ priv->reply_agg_tx_stats.dump_tx);
pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK),
- priv->_agn.reply_agg_tx_stats.delay_tx);
+ priv->reply_agg_tx_stats.delay_tx);
pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
- priv->_agn.reply_agg_tx_stats.unknown);
+ priv->reply_agg_tx_stats.unknown);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
@@ -2493,7 +2507,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
if (iwl_is_rfkill(priv))
return -EFAULT;
- priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL);
+ iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
return count;
}
@@ -2667,6 +2681,7 @@ 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);
@@ -2693,8 +2708,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
- if (priv->cfg->ops->lib->dev_txfifo_flush)
- DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
+ 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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c8de236c141b..6c9790cac8d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -31,6 +31,7 @@
#ifndef __iwl_dev_h__
#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>
@@ -47,6 +48,10 @@
#include "iwl-power.h"
#include "iwl-agn-rs.h"
#include "iwl-agn-tt.h"
+#include "iwl-bus.h"
+#include "iwl-trans.h"
+
+#define DRV_NAME "iwlagn"
struct iwl_tx_queue;
@@ -257,11 +262,9 @@ struct iwl_channel_info {
enum {
CMD_SYNC = 0,
- CMD_SIZE_NORMAL = 0,
- CMD_NO_SKB = 0,
- CMD_ASYNC = (1 << 1),
- CMD_WANT_SKB = (1 << 2),
- CMD_MAPPED = (1 << 3),
+ CMD_ASYNC = BIT(0),
+ CMD_WANT_SKB = BIT(1),
+ CMD_ON_DEMAND = BIT(2),
};
#define DEF_CMD_PAYLOAD_SIZE 320
@@ -294,6 +297,16 @@ 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;
@@ -385,13 +398,6 @@ struct iwl_tid_data {
struct iwl_ht_agg agg;
};
-struct iwl_hw_key {
- u32 cipher;
- int keylen;
- u8 keyidx;
- u8 key[32];
-};
-
union iwl_ht_rate_supp {
u16 rates;
struct {
@@ -444,7 +450,6 @@ struct iwl_station_entry {
struct iwl_addsta_cmd sta;
struct iwl_tid_data tid[MAX_TID_COUNT];
u8 used, ctxid;
- struct iwl_hw_key keyinfo;
struct iwl_link_quality_cmd *lq;
};
@@ -547,7 +552,8 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13,
IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14,
IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15,
- /* 16 and 17 reserved for future use */
+ IWL_UCODE_TLV_WOWLAN_INST = 16,
+ IWL_UCODE_TLV_WOWLAN_DATA = 17,
IWL_UCODE_TLV_FLAGS = 18,
};
@@ -631,7 +637,6 @@ struct iwl_sensitivity_ranges {
/**
* struct iwl_hw_params
* @max_txq_num: Max # Tx queues supported
- * @dma_chnl_num: Number of Tx DMA/FIFO channels
* @scd_bc_tbls_size: size of scheduler byte count tables
* @tfd_size: TFD size
* @tx/rx_chains_num: Number of TX/RX chains
@@ -653,7 +658,6 @@ struct iwl_sensitivity_ranges {
*/
struct iwl_hw_params {
u8 max_txq_num;
- u8 dma_chnl_num;
u16 scd_bc_tbls_size;
u32 tfd_size;
u8 tx_chains_num;
@@ -663,7 +667,6 @@ struct iwl_hw_params {
u16 max_rxq_size;
u16 max_rxq_log;
u32 rx_page_order;
- u32 rx_wrt_ptr_reg;
u8 max_stations;
u8 ht40_channel;
u8 max_beacon_itrvl; /* in 1024 ms */
@@ -694,8 +697,6 @@ 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_rxq_stop(struct iwl_priv *priv);
-extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl_queue_space(const struct iwl_queue *q);
static inline int iwl_queue_used(const struct iwl_queue *q, int i)
{
@@ -1152,6 +1153,8 @@ struct iwl_rxon_context {
__le32 station_flags;
+ int beacon_int;
+
struct {
bool non_gf_sta_present;
u8 protection;
@@ -1168,14 +1171,29 @@ enum iwl_scan_type {
IWL_SCAN_OFFCH_TX,
};
+enum iwlagn_ucode_type {
+ IWL_UCODE_NONE,
+ IWL_UCODE_REGULAR,
+ IWL_UCODE_INIT,
+ IWL_UCODE_WOWLAN,
+};
+
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
struct iwl_testmode_trace {
+ u32 buff_size;
+ u32 total_size;
+ u32 num_chunks;
u8 *cpu_addr;
u8 *trace_addr;
dma_addr_t dma_addr;
bool trace_enabled;
};
#endif
+
+/* uCode ownership */
+#define IWL_OWNERSHIP_DRIVER 0
+#define IWL_OWNERSHIP_TM 1
+
struct iwl_priv {
/* ieee device used by generic ieee processing code */
@@ -1243,11 +1261,8 @@ struct iwl_priv {
spinlock_t reg_lock; /* protect hw register access */
struct mutex mutex;
- /* basic pci-network driver stuff */
- struct pci_dev *pci_dev;
-
- /* pci hardware address support */
- void __iomem *hw_base;
+ struct iwl_bus *bus; /* bus specific data */
+ struct iwl_trans trans;
/* microcode/device supports multiple contexts */
u8 valid_contexts;
@@ -1267,10 +1282,15 @@ struct iwl_priv {
int fw_index; /* firmware we're trying to load */
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;
- enum iwlagn_ucode_subtype ucode_type;
+ enum iwlagn_ucode_type ucode_type;
u8 ucode_write_complete; /* the image write is complete */
char firmware_name[25];
@@ -1341,6 +1361,8 @@ struct iwl_priv {
u8 mac80211_registered;
+ bool wowlan;
+
/* eeprom -- this is in the card's little endian byte order */
u8 *eeprom;
int nvm_device_type;
@@ -1376,56 +1398,54 @@ struct iwl_priv {
} accum_stats, delta_stats, max_delta_stats;
#endif
- struct {
- /* 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
- */
- u8 agg_tids_count;
-
- struct iwl_rx_phy_res last_phy_res;
- bool last_phy_res_valid;
-
- struct completion firmware_loading_complete;
-
- u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
- u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-
- /*
- * chain noise reset and gain commands are the
- * two extra calibration commands follows the standard
- * phy calibration commands
- */
- u8 phy_calib_chain_noise_reset_cmd;
- u8 phy_calib_chain_noise_gain_cmd;
-
- /* counts reply_tx error */
- struct reply_tx_error_statistics reply_tx_stats;
- struct reply_agg_tx_error_statistics reply_agg_tx_stats;
- /* notification wait support */
- struct list_head notif_waits;
- spinlock_t notif_wait_lock;
- wait_queue_head_t notif_waitq;
-
- /* remain-on-channel offload support */
- struct ieee80211_channel *hw_roc_channel;
- struct delayed_work hw_roc_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;
- } _agn;
+ /* 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
+ */
+ u8 agg_tids_count;
+
+ struct iwl_rx_phy_res last_phy_res;
+ bool last_phy_res_valid;
+
+ struct completion firmware_loading_complete;
+
+ u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
+ u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+
+ /*
+ * chain noise reset and gain commands are the
+ * two extra calibration commands follows the standard
+ * phy calibration commands
+ */
+ u8 phy_calib_chain_noise_reset_cmd;
+ u8 phy_calib_chain_noise_gain_cmd;
+
+ /* counts reply_tx error */
+ struct reply_tx_error_statistics reply_tx_stats;
+ struct reply_agg_tx_error_statistics reply_agg_tx_stats;
+ /* notification wait support */
+ struct list_head notif_waits;
+ spinlock_t notif_wait_lock;
+ wait_queue_head_t notif_waitq;
+
+ /* remain-on-channel offload support */
+ struct ieee80211_channel *hw_roc_channel;
+ struct delayed_work hw_roc_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;
/* bt coex */
u8 bt_enable_flag;
@@ -1442,6 +1462,9 @@ struct iwl_priv {
u16 dynamic_frag_thresh;
u8 bt_ci_compliance;
struct work_struct bt_traffic_change_work;
+ bool bt_enable_pspoll;
+ struct iwl_rxon_context *cur_rssi_ctx;
+ bool bt_is_sco;
struct iwl_hw_params hw_params;
@@ -1492,6 +1515,7 @@ struct iwl_priv {
struct dentry *debugfs_dir;
u32 dbgfs_sram_offset, dbgfs_sram_len;
bool disable_ht40;
+ void *wowlan_sram;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
struct work_struct txpower_work;
@@ -1509,9 +1533,14 @@ struct iwl_priv {
bool led_registered;
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
struct iwl_testmode_trace testmode_trace;
+ u32 tm_fixed_rate;
#endif
- u32 dbg_fixed_rate;
+ /* WoWLAN GTK rekey data */
+ u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
+ __le64 replay_ctr;
+ __le16 last_seq_ctl;
+ bool have_rekey_data;
}; /*iwl_priv */
static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 47a56bc1cd12..19d31a5e32e5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -407,11 +407,6 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
return -EINVAL;
}
-const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
- return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
-}
-
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
{
if (!priv->eeprom)
@@ -449,7 +444,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
}
e = (__le16 *)priv->eeprom;
- priv->cfg->ops->lib->apm_ops.init(priv);
+ iwl_apm_init(priv);
ret = iwl_eeprom_verify_signature(priv);
if (ret < 0) {
@@ -548,7 +543,7 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
const struct iwl_eeprom_channel **eeprom_ch_info,
const u8 **eeprom_ch_index)
{
- u32 offset = priv->cfg->ops->lib->
+ u32 offset = priv->cfg->lib->
eeprom_ops.regulatory_bands[eep_band - 1];
switch (eep_band) {
case 1: /* 2.4GHz band */
@@ -754,9 +749,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
}
/* Check if we do have HT40 channels */
- if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
+ if (priv->cfg->lib->eeprom_ops.regulatory_bands[5] ==
EEPROM_REGULATORY_BAND_NO_HT40 &&
- priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
+ priv->cfg->lib->eeprom_ops.regulatory_bands[6] ==
EEPROM_REGULATORY_BAND_NO_HT40)
return 0;
@@ -792,8 +787,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
* driver need to process addition information
* to determine the max channel tx power limits
*/
- if (priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower)
- priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower(priv);
+ if (priv->cfg->lib->eeprom_ops.update_enhanced_txpower)
+ priv->cfg->lib->eeprom_ops.update_enhanced_txpower(priv);
return 0;
}
@@ -834,3 +829,28 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
return NULL;
}
+
+void iwl_rf_config(struct iwl_priv *priv)
+{
+ u16 radio_cfg;
+
+ radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+ /* 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,
+ EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+ EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+ EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+ IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
+ EEPROM_RF_CFG_TYPE_MSK(radio_cfg),
+ EEPROM_RF_CFG_STEP_MSK(radio_cfg),
+ EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+ } else
+ WARN_ON(1);
+
+ /* set CSR_HW_CONFIG_REG for uCode use */
+ iwl_set_bit(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 c960c6fa009b..e4bf8ac5e64e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -110,12 +110,10 @@ enum {
};
/* SKU Capabilities */
-/* 5000 and up */
-#define EEPROM_SKU_CAP_BAND_POS (4)
-#define EEPROM_SKU_CAP_BAND_SELECTION \
- (3 << EEPROM_SKU_CAP_BAND_POS)
+#define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4)
+#define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
#define EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
-#define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7)
+#define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7)
#define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8)
/* *regulatory* channel data format in eeprom, one for each channel.
@@ -164,16 +162,12 @@ struct iwl_eeprom_enhanced_txpwr {
s8 mimo3_max;
} __packed;
-/* 5000 Specific */
-#define EEPROM_5000_TX_POWER_VERSION (4)
-#define EEPROM_5000_EEPROM_VERSION (0x11A)
-
-/* 5000 and up calibration */
+/* calibration */
#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL)
-/* 5000 temperature */
-#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+/* temperature */
+#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
/* agn links */
#define EEPROM_LINK_HOST (2*0x64)
@@ -205,6 +199,10 @@ struct iwl_eeprom_enhanced_txpwr {
#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */
+/* 5000 Specific */
+#define EEPROM_5000_TX_POWER_VERSION (4)
+#define EEPROM_5000_EEPROM_VERSION (0x11A)
+
/* 5050 Specific */
#define EEPROM_5050_TX_POWER_VERSION (4)
#define EEPROM_5050_EEPROM_VERSION (0x21E)
@@ -270,13 +268,13 @@ extern const u8 iwl_eeprom_band_1[14];
/* General */
#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
+#define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */
#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
#define EEPROM_VERSION (2*0x44) /* 2 bytes */
#define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */
#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
-#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
#define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */
#define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */
@@ -294,7 +292,6 @@ extern const u8 iwl_eeprom_band_1[14];
struct iwl_eeprom_ops {
const u32 regulatory_bands[7];
- const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);
void (*update_enhanced_txpower) (struct iwl_priv *priv);
};
@@ -311,5 +308,6 @@ void iwl_free_channel_map(struct iwl_priv *priv);
const struct iwl_channel_info *iwl_get_channel_info(
const struct iwl_priv *priv,
enum ieee80211_band band, u16 channel);
+void iwl_rf_config(struct iwl_priv *priv);
#endif /* __iwl_eeprom_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 6dfa806aefec..0ad60b3c04db 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -326,7 +326,7 @@
#define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60)
/* Find Control/Status reg for given Tx DMA/FIFO channel */
-#define FH50_TCSR_CHNL_NUM (8)
+#define FH_TCSR_CHNL_NUM (8)
/* TCSR: tx_config register values */
#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
deleted file mode 100644
index 76f996623140..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/******************************************************************************
- *
- * 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
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <net/mac80211.h>
-
-#include "iwl-dev.h" /* FIXME: remove */
-#include "iwl-debug.h"
-#include "iwl-eeprom.h"
-#include "iwl-core.h"
-
-
-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);
- default:
- return "UNKNOWN";
-
- }
-}
-
-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-
-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)
-{
- int ret;
-
- if (WARN_ON(!(cmd->flags & CMD_ASYNC)))
- return -EINVAL;
-
- /* An asynchronous command can not expect an SKB to be set. */
- 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))
- return -EBUSY;
-
- ret = iwl_enqueue_hcmd(priv, cmd);
- if (ret < 0) {
- IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
- get_cmd_string(cmd->id), ret);
- return ret;
- }
- return 0;
-}
-
-int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
- int cmd_idx;
- int ret;
-
- if (WARN_ON(cmd->flags & CMD_ASYNC))
- return -EINVAL;
-
- /* 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",
- get_cmd_string(cmd->id));
-
- set_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
- get_cmd_string(cmd->id));
-
- cmd_idx = iwl_enqueue_hcmd(priv, 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",
- get_cmd_string(cmd->id), ret);
- return ret;
- }
-
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
- HOST_COMPLETE_TIMEOUT);
- if (!ret) {
- if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
- IWL_ERR(priv,
- "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 %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",
- 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",
- 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",
- get_cmd_string(cmd->id));
- ret = -EIO;
- goto cancel;
- }
-
- return 0;
-
-cancel:
- if (cmd->flags & CMD_WANT_SKB) {
- /*
- * Cancel the CMD_WANT_SKB flag for the cmd in the
- * TX cmd queue. Otherwise in case the cmd comes
- * in later, it will possibly set an invalid
- * address (cmd->meta.source).
- */
- priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
- ~CMD_WANT_SKB;
- }
-fail:
- if (cmd->reply_page) {
- iwl_free_pages(priv, cmd->reply_page);
- cmd->reply_page = 0;
- }
-
- return ret;
-}
-
-int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
- if (cmd->flags & CMD_ASYNC)
- return iwl_send_cmd_async(priv, cmd);
-
- return iwl_send_cmd_sync(priv, cmd);
-}
-
-int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
-{
- struct iwl_host_cmd cmd = {
- .id = id,
- .len = { len, },
- .data = { data, },
- };
-
- return iwl_send_cmd_sync(priv, &cmd);
-}
-
-int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
- u8 id, u16 len, const void *data,
- void (*callback)(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt))
-{
- struct iwl_host_cmd cmd = {
- .id = id,
- .len = { len, },
- .data = { data, },
- };
-
- cmd.flags |= CMD_ASYNC;
- cmd.callback = callback;
-
- return iwl_send_cmd_async(priv, &cmd);
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 41207a3645b8..9d91552d13c1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -120,7 +120,16 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv,
}
}
+#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)
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 869edc580ec6..19a093101122 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -34,22 +34,23 @@
#include "iwl-dev.h"
#include "iwl-debug.h"
#include "iwl-devtrace.h"
+#include "iwl-bus.h"
static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val)
{
trace_iwlwifi_dev_iowrite8(priv, ofs, val);
- iowrite8(val, priv->hw_base + ofs);
+ bus_write8(priv->bus, ofs, val);
}
static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val)
{
trace_iwlwifi_dev_iowrite32(priv, ofs, val);
- iowrite32(val, priv->hw_base + ofs);
+ bus_write32(priv->bus, ofs, val);
}
static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs)
{
- u32 val = ioread32(priv->hw_base + ofs);
+ u32 val = bus_read32(priv->bus, ofs);
trace_iwlwifi_dev_ioread32(priv, ofs, val);
return val;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 7c23beb49d7c..a67ae56d5464 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -28,8 +28,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -40,13 +38,9 @@
#include "iwl-dev.h"
#include "iwl-core.h"
+#include "iwl-agn.h"
#include "iwl-io.h"
-
-/* default: IWL_LED_BLINK(0) using blinking index table */
-static int led_mode;
-module_param(led_mode, int, S_IRUGO);
-MODULE_PARM_DESC(led_mode, "0=system default, "
- "1=On(RF On)/Off(RF Off), 2=blinking");
+#include "iwl-trans.h"
/* Throughput OFF time(ms) ON time (ms)
* >300 25 25
@@ -118,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(&priv->trans, &cmd);
}
/* Set led pattern command */
@@ -181,7 +175,7 @@ static int iwl_led_blink_set(struct led_classdev *led_cdev,
void iwl_leds_init(struct iwl_priv *priv)
{
- int mode = led_mode;
+ int mode = iwlagn_mod_params.led_mode;
int ret;
if (mode == IWL_LED_DEFAULT)
@@ -209,7 +203,8 @@ void iwl_leds_init(struct iwl_priv *priv)
break;
}
- ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+ ret = led_classdev_register(priv->bus->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
new file mode 100644
index 000000000000..fb7e436b40c7
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
@@ -0,0 +1,569 @@
+/******************************************************************************
+ *
+ * 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/pci.h>
+#include <linux/pci-aspm.h>
+
+#include "iwl-bus.h"
+#include "iwl-agn.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT 0x041
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
+
+struct iwl_pci_bus {
+ /* basic pci-network driver stuff */
+ struct pci_dev *pci_dev;
+
+ /* pci hardware address support */
+ void __iomem *hw_base;
+};
+
+#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \
+ ((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific))
+
+#define IWL_BUS_GET_PCI_DEV(_iwl_bus) \
+ ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev)
+
+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);
+ pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+ return pci_lnk_ctl;
+}
+
+static bool iwl_pci_is_pm_supported(struct iwl_bus *bus)
+{
+ u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+ return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+}
+
+static void iwl_pci_apm_config(struct iwl_bus *bus)
+{
+ /*
+ * HW bug W/A for instability in PCIe bus L0S->L1 transition.
+ * Check if BIOS (or OS) enabled L1-ASPM on this device.
+ * If so (likely), disable L0S, so device moves directly L0->L1;
+ * costs negligible amount of power savings.
+ * If not (unlikely), enable L0S, so there is at least some
+ * power savings, even without L1.
+ */
+ u16 lctl = iwl_pciexp_link_ctrl(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,
+ 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,
+ 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;
+}
+
+static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
+ int buf_len)
+{
+ struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+ snprintf(buf, buf_len, "PCI ID: 0x%04X:0x%04X", pci_dev->device,
+ pci_dev->subsystem_device);
+}
+
+static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val)
+{
+ iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val)
+{
+ iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
+{
+ u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+ return val;
+}
+
+static struct iwl_bus_ops pci_ops = {
+ .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,
+ .read32 = iwl_pci_read32,
+};
+
+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
+ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
+ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
+ .driver_data = (kernel_ulong_t)&(cfg)
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
+ {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
+
+/* 5300 Series WiFi */
+ {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
+
+/* 5350 Series WiFi/WiMax */
+ {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
+
+/* 5150 Series Wifi/WiMax */
+ {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
+
+ {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
+
+/* 6x00 Series */
+ {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
+
+/* 6x05 Series */
+ {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
+
+/* 6x30 Series */
+ {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
+ {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
+
+/* 6x50 WiFi/WiMax Series */
+ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
+
+/* 6150 WiFi/WiMax Series */
+ {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
+
+/* 1000 Series WiFi */
+ {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+
+/* 100 Series WiFi */
+ {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
+
+/* 130 Series WiFi */
+ {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+
+/* 2x00 Series */
+ {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
+
+/* 2x30 Series */
+ {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
+
+/* 6x35 Series */
+ {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
+
+/* 105 Series */
+ {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
+
+/* 135 Series */
+ {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
+
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
+
+static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+ struct iwl_bus *bus;
+ struct iwl_pci_bus *pci_bus;
+ u16 pci_cmd;
+ int err;
+
+ bus = kzalloc(sizeof(*bus) + sizeof(*pci_bus), GFP_KERNEL);
+ if (!bus) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "Couldn't allocate iwl_pci_bus");
+ err = -ENOMEM;
+ goto out_no_pci;
+ }
+
+ pci_bus = IWL_BUS_GET_PCI_BUS(bus);
+ pci_bus->pci_dev = pdev;
+
+ /* 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 |
+ PCIE_LINK_STATE_CLKPM);
+
+ if (pci_enable_device(pdev)) {
+ err = -ENODEV;
+ goto out_no_pci;
+ }
+
+ pci_set_master(pdev);
+
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+ if (err) {
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev,
+ DMA_BIT_MASK(32));
+ /* both attempts failed: */
+ if (err) {
+ dev_printk(KERN_ERR, bus->dev,
+ "No suitable DMA available.\n");
+ goto out_pci_disable_device;
+ }
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ dev_printk(KERN_ERR, bus->dev, "pci_request_regions failed");
+ goto out_pci_disable_device;
+ }
+
+ pci_bus->hw_base = pci_iomap(pdev, 0, 0);
+ if (!pci_bus->hw_base) {
+ dev_printk(KERN_ERR, bus->dev, "pci_iomap failed");
+ err = -ENODEV;
+ goto out_pci_release_regions;
+ }
+
+ dev_printk(KERN_INFO, &pdev->dev,
+ "pci_resource_len = 0x%08llx\n",
+ (unsigned long long) pci_resource_len(pdev, 0));
+ dev_printk(KERN_INFO, &pdev->dev,
+ "pci_resource_base = %p\n", pci_bus->hw_base);
+
+ dev_printk(KERN_INFO, &pdev->dev,
+ "HW Revision ID = 0x%X\n", pdev->revision);
+
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+ err = pci_enable_msi(pdev);
+ if (err) {
+ dev_printk(KERN_ERR, &pdev->dev, "pci_enable_msi failed");
+ goto out_iounmap;
+ }
+
+ /* TODO: Move this away, not needed if not MSI */
+ /* enable rfkill interrupt: hw bug w/a */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+ if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+ pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+ }
+
+ pci_set_drvdata(pdev, bus);
+
+ bus->dev = &pdev->dev;
+ bus->irq = pdev->irq;
+ bus->ops = &pci_ops;
+
+ err = iwl_probe(bus, cfg);
+ if (err)
+ goto out_disable_msi;
+ return 0;
+
+out_disable_msi:
+ pci_disable_msi(pdev);
+out_iounmap:
+ pci_iounmap(pdev, pci_bus->hw_base);
+out_pci_release_regions:
+ pci_set_drvdata(pdev, NULL);
+ pci_release_regions(pdev);
+out_pci_disable_device:
+ pci_disable_device(pdev);
+out_no_pci:
+ kfree(bus);
+ return err;
+}
+
+static void iwl_pci_down(struct iwl_bus *bus)
+{
+ struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific;
+
+ pci_disable_msi(pci_bus->pci_dev);
+ pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
+ pci_release_regions(pci_bus->pci_dev);
+ pci_disable_device(pci_bus->pci_dev);
+ pci_set_drvdata(pci_bus->pci_dev, NULL);
+
+ kfree(bus);
+}
+
+static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+{
+ struct iwl_bus *bus = pci_get_drvdata(pdev);
+
+ iwl_remove(bus->drv_data);
+
+ iwl_pci_down(bus);
+}
+
+#ifdef CONFIG_PM
+
+static int iwl_pci_suspend(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct iwl_bus *bus = pci_get_drvdata(pdev);
+
+ /* 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(bus->drv_data);
+}
+
+static int iwl_pci_resume(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct iwl_bus *bus = pci_get_drvdata(pdev);
+
+ /* 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 - the NIC may be alive.
+ */
+
+ /*
+ * We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+ return iwl_resume(bus->drv_data);
+}
+
+static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);
+
+#define IWL_PM_OPS (&iwl_dev_pm_ops)
+
+#else
+
+#define IWL_PM_OPS NULL
+
+#endif
+
+static struct pci_driver iwl_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = iwl_hw_card_ids,
+ .probe = iwl_pci_probe,
+ .remove = __devexit_p(iwl_pci_remove),
+ .driver.pm = IWL_PM_OPS,
+};
+
+int __must_check iwl_pci_register_driver(void)
+{
+ int ret;
+ ret = pci_register_driver(&iwl_pci_driver);
+ if (ret)
+ pr_err("Unable to initialize PCI module\n");
+
+ return ret;
+}
+
+void iwl_pci_unregister_driver(void)
+{
+ pci_unregister_driver(&iwl_pci_driver);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 595c930b28ae..3ec619c6881c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -36,11 +36,13 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
+#include "iwl-agn.h"
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-commands.h"
#include "iwl-debug.h"
#include "iwl-power.h"
+#include "iwl-trans.h"
/*
* Setting power level allows the card to go to sleep when not busy.
@@ -51,16 +53,6 @@
*/
/*
- * For now, keep using power level 1 instead of automatically
- * adjusting ...
- */
-bool no_sleep_autoadjust = true;
-module_param(no_sleep_autoadjust, bool, S_IRUGO);
-MODULE_PARM_DESC(no_sleep_autoadjust,
- "don't automatically adjust sleep level "
- "according to maximum network latency");
-
-/*
* This defines the old power levels. They are still used by default
* (level 1) and for thermal throttle (levels 3 through 5)
*/
@@ -254,7 +246,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
}
}
- if (priv->power_data.pci_pm)
+ if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
else
cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
@@ -269,7 +261,7 @@ static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
{
memset(cmd, 0, sizeof(*cmd));
- if (priv->power_data.pci_pm)
+ if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
@@ -305,7 +297,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
IWL_POWER_FAST_PD; /* no use seeing frames for others */
- if (priv->power_data.pci_pm)
+ if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
if (priv->cfg->base_params->shadow_reg_enable)
@@ -343,7 +335,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 iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+ return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC,
sizeof(struct iwl_powertable_cmd), cmd);
}
@@ -355,7 +347,9 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
- if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
+ if (priv->wowlan)
+ iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
+ else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
else if (iwl_tt_is_low_power_state(priv)) {
/* in thermal throttling low power state */
@@ -367,9 +361,15 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
iwl_static_sleep_cmd(priv, cmd,
priv->power_data.debug_sleep_level_override,
dtimper);
- else if (no_sleep_autoadjust)
- iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
- else
+ else if (iwlagn_mod_params.no_sleep_autoadjust) {
+ if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 &&
+ iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5)
+ iwl_static_sleep_cmd(priv, cmd,
+ iwlagn_mod_params.power_level, dtimper);
+ else
+ iwl_static_sleep_cmd(priv, cmd,
+ IWL_POWER_INDEX_1, dtimper);
+ } else
iwl_power_fill_sleep_cmd(priv, cmd,
priv->hw->conf.dynamic_ps_timeout,
priv->hw->conf.max_sleep_period);
@@ -408,9 +408,9 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
clear_bit(STATUS_POWER_PMI, &priv->status);
- if (priv->cfg->ops->lib->update_chain_flags && update_chains)
- priv->cfg->ops->lib->update_chain_flags(priv);
- else if (priv->cfg->ops->lib->update_chain_flags)
+ if (update_chains)
+ iwl_update_chain_flags(priv);
+ else
IWL_DEBUG_POWER(priv,
"Cannot update the power, chain noise "
"calibration running: %d\n",
@@ -434,9 +434,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
- u16 lctl = iwl_pcie_link_ctl(priv);
-
- priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+ priv->power_data.bus_pm = bus_get_pm_support(priv->bus);
priv->power_data.debug_sleep_level_override = -1;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 59635d784e27..5f7b720cf1a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -43,7 +43,7 @@ struct iwl_power_mgr {
struct iwl_powertable_cmd sleep_cmd;
struct iwl_powertable_cmd sleep_cmd_next;
int debug_sleep_level_override;
- bool pci_pm;
+ bool bus_pm;
};
int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index f00d188b2cfc..2f267b8aabbb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -168,6 +168,7 @@
* the scheduler (especially for queue #4/#9, the command queue, otherwise
* the driver can't issue commands!):
*/
+#define SCD_MEM_LOWER_BOUND (0x0000)
/**
* Max Tx window size is the max number of contiguous TFDs that the scheduler
@@ -177,53 +178,61 @@
#define SCD_WIN_SIZE 64
#define SCD_FRAME_LIMIT 64
-#define IWL_SCD_TXFIFO_POS_TID (0)
-#define IWL_SCD_TXFIFO_POS_RA (4)
-#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
+#define SCD_TXFIFO_POS_TID (0)
+#define SCD_TXFIFO_POS_RA (4)
+#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
/* agn SCD */
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF (0)
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE (3)
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL (4)
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
-#define IWLAGN_SCD_QUEUE_STTS_REG_MSK (0x00FF0000)
-
-#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
-#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
-#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
-#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
-
-#define IWLAGN_SCD_CONTEXT_DATA_OFFSET (0x600)
-#define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET (0x7B1)
-#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET (0x7E0)
-
-#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\
- (IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
-
-#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
- ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
-
-#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \
+#define SCD_QUEUE_STTS_REG_POS_TXF (0)
+#define SCD_QUEUE_STTS_REG_POS_ACTIVE (3)
+#define SCD_QUEUE_STTS_REG_POS_WSL (4)
+#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
+#define SCD_QUEUE_STTS_REG_MSK (0x00FF0000)
+
+#define SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
+#define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
+#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
+#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
+#define SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0)
+#define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F)
+#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
+#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
+
+/* Context Data */
+#define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600)
+#define SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)
+
+/* Tx status */
+#define SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)
+#define SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)
+
+/* Translation Data */
+#define SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)
+#define SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808)
+
+#define SCD_CONTEXT_QUEUE_OFFSET(x)\
+ (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
+
+#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
+ ((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)))
-#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00)
-
-#define IWLAGN_SCD_SRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x0)
-#define IWLAGN_SCD_DRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x8)
-#define IWLAGN_SCD_AIT (IWLAGN_SCD_BASE + 0x0c)
-#define IWLAGN_SCD_TXFACT (IWLAGN_SCD_BASE + 0x10)
-#define IWLAGN_SCD_ACTIVE (IWLAGN_SCD_BASE + 0x14)
-#define IWLAGN_SCD_QUEUE_WRPTR(x) (IWLAGN_SCD_BASE + 0x18 + (x) * 4)
-#define IWLAGN_SCD_QUEUE_RDPTR(x) (IWLAGN_SCD_BASE + 0x68 + (x) * 4)
-#define IWLAGN_SCD_QUEUECHAIN_SEL (IWLAGN_SCD_BASE + 0xe8)
-#define IWLAGN_SCD_AGGR_SEL (IWLAGN_SCD_BASE + 0x248)
-#define IWLAGN_SCD_INTERRUPT_MASK (IWLAGN_SCD_BASE + 0x108)
-#define IWLAGN_SCD_QUEUE_STATUS_BITS(x) (IWLAGN_SCD_BASE + 0x10c + (x) * 4)
+#define SCD_BASE (PRPH_BASE + 0xa02c00)
+
+#define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0)
+#define SCD_DRAM_BASE_ADDR (SCD_BASE + 0x8)
+#define SCD_AIT (SCD_BASE + 0x0c)
+#define SCD_TXFACT (SCD_BASE + 0x10)
+#define SCD_ACTIVE (SCD_BASE + 0x14)
+#define SCD_QUEUE_WRPTR(x) (SCD_BASE + 0x18 + (x) * 4)
+#define SCD_QUEUE_RDPTR(x) (SCD_BASE + 0x68 + (x) * 4)
+#define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8)
+#define SCD_AGGR_SEL (SCD_BASE + 0x248)
+#define SCD_INTERRUPT_MASK (SCD_BASE + 0x108)
+#define SCD_QUEUE_STATUS_BITS(x) (SCD_BASE + 0x10c + (x) * 4)
/*********************** END TX SCHEDULER *************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index b774517aa9fa..8e314003b63a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -41,183 +41,6 @@
#include "iwl-agn-calib.h"
#include "iwl-agn.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.
- */
-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 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
- 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, rx_wrt_ptr_reg, 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, rx_wrt_ptr_reg,
- 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, rx_wrt_ptr_reg,
- q->write_actual);
- }
- }
- q->need_update = 0;
-
- exit_unlock:
- spin_unlock_irqrestore(&q->lock, flags);
-}
-
-int iwl_rx_queue_alloc(struct iwl_priv *priv)
-{
- struct iwl_rx_queue *rxq = &priv->rxq;
- struct device *dev = &priv->pci_dev->dev;
- int i;
-
- spin_lock_init(&rxq->lock);
- INIT_LIST_HEAD(&rxq->rx_free);
- INIT_LIST_HEAD(&rxq->rx_used);
-
- /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
- rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
- GFP_KERNEL);
- if (!rxq->bd)
- goto err_bd;
-
- rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
- &rxq->rb_stts_dma, GFP_KERNEL);
- if (!rxq->rb_stts)
- goto err_rb;
-
- /* Fill the rx_used queue with _all_ of the Rx buffers */
- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-
- /* 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;
- rxq->need_update = 0;
- return 0;
-
-err_rb:
- dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->bd_dma);
-err_bd:
- return -ENOMEM;
-}
/******************************************************************************
*
@@ -347,7 +170,7 @@ static bool iwl_good_ack_health(struct iwl_priv *priv,
int actual_delta, expected_delta, ba_timeout_delta;
struct statistics_tx *old;
- if (priv->_agn.agg_tids_count)
+ if (priv->agg_tids_count)
return true;
old = &priv->statistics.tx;
@@ -665,8 +488,8 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
iwl_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work);
}
- if (priv->cfg->ops->lib->temp_ops.temperature && change)
- priv->cfg->ops->lib->temp_ops.temperature(priv);
+ if (priv->cfg->lib->temperature && change)
+ priv->cfg->lib->temperature(priv);
}
static void iwl_rx_reply_statistics(struct iwl_priv *priv,
@@ -769,8 +592,8 @@ static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- priv->_agn.last_phy_res_valid = true;
- memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
+ priv->last_phy_res_valid = true;
+ memcpy(&priv->last_phy_res, pkt->u.raw,
sizeof(struct iwl_rx_phy_res));
}
@@ -943,6 +766,47 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
return decrypt_out;
}
+/* Calc max signal level (dBm) among 3 possible receivers */
+static int iwlagn_calc_rssi(struct iwl_priv *priv,
+ struct iwl_rx_phy_res *rx_resp)
+{
+ /* data from PHY/DSP regarding signal strength, etc.,
+ * contents are always there, not configurable by host
+ */
+ struct iwlagn_non_cfg_phy *ncphy =
+ (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+ u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
+ u8 agc;
+
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
+ agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
+
+ /* Find max rssi among 3 possible receivers.
+ * These values are measured by the digital signal processor (DSP).
+ * They should stay fairly constant even as the signal strength varies,
+ * if the radio's automatic gain control (AGC) is working right.
+ * AGC value (see below) will provide the "interesting" info.
+ */
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
+ rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
+ IWLAGN_OFDM_RSSI_A_BIT_POS;
+ rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
+ IWLAGN_OFDM_RSSI_B_BIT_POS;
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
+ rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
+ IWLAGN_OFDM_RSSI_C_BIT_POS;
+
+ max_rssi = max_t(u32, rssi_a, rssi_b);
+ max_rssi = max_t(u32, max_rssi, rssi_c);
+
+ IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+ rssi_a, rssi_b, rssi_c, max_rssi, agc);
+
+ /* dBm = max_rssi dB - agc dB - constant.
+ * Higher AGC (higher radio gain) means lower signal. */
+ return max_rssi - agc - IWLAGN_RSSI_OFFSET;
+}
+
/* 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,
@@ -977,11 +841,11 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
phy_res->cfg_phy_cnt + len);
ampdu_status = le32_to_cpu(rx_pkt_status);
} else {
- if (!priv->_agn.last_phy_res_valid) {
+ if (!priv->last_phy_res_valid) {
IWL_ERR(priv, "MPDU frame without cached PHY data\n");
return;
}
- phy_res = &priv->_agn.last_phy_res;
+ 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);
@@ -1024,7 +888,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
/* Find max signal strength (dBm) among 3 antenna/receiver chains */
- rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res);
+ rx_status.signal = iwlagn_calc_rssi(priv, phy_res);
iwl_dbg_log_rx_data_frame(priv, len, header);
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
@@ -1102,6 +966,64 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
/* block ack */
handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba;
- /* Set up hardware specific Rx handlers */
- priv->cfg->ops->lib->rx_handler_setup(priv);
+ /* init calibration handlers */
+ priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
+ iwlagn_rx_calib_result;
+ priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
+
+ /* set up notification wait support */
+ spin_lock_init(&priv->notif_wait_lock);
+ INIT_LIST_HEAD(&priv->notif_waits);
+ init_waitqueue_head(&priv->notif_waitq);
+
+ /* Set up BT Rx handlers */
+ if (priv->cfg->lib->bt_rx_handler_setup)
+ priv->cfg->lib->bt_rx_handler_setup(priv);
+
+}
+
+void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+ /*
+ * Do the notification wait before RX handlers so
+ * even if the RX handler consumes the RXB we have
+ * access to it in the notification wait entry.
+ */
+ if (!list_empty(&priv->notif_waits)) {
+ struct iwl_notification_wait *w;
+
+ spin_lock(&priv->notif_wait_lock);
+ list_for_each_entry(w, &priv->notif_waits, list) {
+ if (w->cmd != pkt->hdr.cmd)
+ continue;
+ IWL_DEBUG_RX(priv,
+ "Notif: %s, 0x%02x - wake the callers up\n",
+ get_cmd_string(pkt->hdr.cmd),
+ pkt->hdr.cmd);
+ w->triggered = true;
+ if (w->fn)
+ w->fn(priv, pkt, w->fn_data);
+ }
+ spin_unlock(&priv->notif_wait_lock);
+
+ wake_up_all(&priv->notif_waitq);
+ }
+
+ if (priv->pre_rx_handler)
+ priv->pre_rx_handler(priv, rxb);
+
+ /* Based on type of command response or notification,
+ * 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);
+ } 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);
+ }
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index d60d630cb93a..dd6937e97055 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -36,6 +36,8 @@
#include "iwl-sta.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
+#include "iwl-agn.h"
+#include "iwl-trans.h"
/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
* sending probe req. This should be set long enough to hear probe responses
@@ -60,7 +62,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
- .flags = CMD_WANT_SKB,
+ .flags = CMD_SYNC | CMD_WANT_SKB,
};
/* Exit instantly with error when device is not ready
@@ -73,7 +75,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EIO;
- ret = iwl_send_cmd_sync(priv, &cmd);
+ ret = trans_send_cmd(&priv->trans, &cmd);
if (ret)
return ret;
@@ -348,9 +350,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
lockdep_assert_held(&priv->mutex);
- if (WARN_ON(!priv->cfg->ops->utils->request_scan))
- return -EOPNOTSUPP;
-
cancel_delayed_work(&priv->scan_check);
if (!iwl_is_ready_rf(priv)) {
@@ -379,7 +378,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
priv->scan_start = jiffies;
priv->scan_band = band;
- ret = priv->cfg->ops->utils->request_scan(priv, vif);
+ ret = iwlagn_request_scan(priv, vif);
if (ret) {
clear_bit(STATUS_SCANNING, &priv->status);
priv->scan_type = IWL_SCAN_NORMAL;
@@ -566,10 +565,10 @@ static void iwl_bg_scan_completed(struct work_struct *work)
goto out_settings;
}
- if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) {
+ if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) {
ieee80211_tx_status_irqsafe(priv->hw,
- priv->_agn.offchan_tx_skb);
- priv->_agn.offchan_tx_skb = NULL;
+ priv->offchan_tx_skb);
+ priv->offchan_tx_skb = NULL;
}
if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
@@ -600,14 +599,7 @@ out_settings:
if (!iwl_is_ready_rf(priv))
goto out;
- /*
- * We do not commit power settings while scan is pending,
- * do it now if the settings changed.
- */
- iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
- iwl_set_tx_power(priv, priv->tx_power_next, false);
-
- priv->cfg->ops->utils->post_scan(priv);
+ iwlagn_post_scan(priv);
out:
mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 7df2814fd4f8..1ef3b7106ad5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -35,6 +35,8 @@
#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)
@@ -132,6 +134,16 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,
}
+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)
{
@@ -155,8 +167,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,
might_sleep();
}
- cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
- ret = iwl_send_cmd(priv, &cmd);
+ cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
+ ret = trans_send_cmd(&priv->trans, &cmd);
if (ret || (flags & CMD_ASYNC))
return ret;
@@ -412,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
cmd.flags |= CMD_WANT_SKB;
- ret = iwl_send_cmd(priv, &cmd);
+ ret = trans_send_cmd(&priv->trans, &cmd);
if (ret)
return ret;
@@ -657,7 +669,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
}
-int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
+int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
{
int i;
@@ -781,7 +793,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
return -EINVAL;
if (is_lq_table_valid(priv, ctx, lq))
- ret = iwl_send_cmd(priv, &cmd);
+ ret = trans_send_cmd(&priv->trans, &cmd);
else
ret = -EINVAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index ff64027ff4cb..9a6768d66851 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -31,9 +31,6 @@
#include "iwl-dev.h"
-#define HW_KEY_DYNAMIC 0
-#define HW_KEY_DEFAULT 1
-
#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
@@ -47,7 +44,7 @@ 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_index(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,
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index 69b7e6bf2d6f..b11f60de4f1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -69,7 +69,6 @@
#include <net/mac80211.h>
#include <net/netlink.h>
-
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-debug.h"
@@ -77,7 +76,7 @@
#include "iwl-io.h"
#include "iwl-agn.h"
#include "iwl-testmode.h"
-
+#include "iwl-trans.h"
/* The TLVs used in the gnl message policy between the kernel module and
* user space application. iwl_testmode_gnl_msg_policy is to be carried
@@ -101,9 +100,12 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
[IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
[IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
- [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
+ [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
+ [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
[IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
+
+ [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
};
/*
@@ -179,19 +181,19 @@ void iwl_testmode_init(struct iwl_priv *priv)
static void iwl_trace_cleanup(struct iwl_priv *priv)
{
- struct device *dev = &priv->pci_dev->dev;
-
if (priv->testmode_trace.trace_enabled) {
if (priv->testmode_trace.cpu_addr &&
priv->testmode_trace.dma_addr)
- dma_free_coherent(dev,
- TRACE_TOTAL_SIZE,
+ dma_free_coherent(priv->bus->dev,
+ priv->testmode_trace.total_size,
priv->testmode_trace.cpu_addr,
priv->testmode_trace.dma_addr);
priv->testmode_trace.trace_enabled = false;
priv->testmode_trace.cpu_addr = NULL;
priv->testmode_trace.trace_addr = NULL;
priv->testmode_trace.dma_addr = 0;
+ priv->testmode_trace.buff_size = 0;
+ priv->testmode_trace.total_size = 0;
}
}
@@ -229,6 +231,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
return -ENOMSG;
}
+ cmd.flags = CMD_ON_DEMAND;
cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
@@ -236,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 iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(&priv->trans, &cmd);
}
@@ -394,7 +397,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
- UCODE_SUBTYPE_INIT, -1);
+ IWL_UCODE_INIT);
if (status)
IWL_DEBUG_INFO(priv,
"Error loading init ucode: %d\n", status);
@@ -402,14 +405,13 @@ 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);
- iwlagn_stop_device(priv);
+ trans_stop_device(&priv->trans);
break;
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
status = iwlagn_load_ucode_wait_alive(priv,
&priv->ucode_rt,
- UCODE_SUBTYPE_REGULAR,
- UCODE_SUBTYPE_REGULAR_NEW);
+ IWL_UCODE_REGULAR);
if (status) {
IWL_DEBUG_INFO(priv,
"Error loading runtime ucode: %d\n", status);
@@ -450,7 +452,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
"Error finding fixrate setting\n");
return -ENOMSG;
}
- priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
+ priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
break;
default:
@@ -482,16 +484,29 @@ 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->pci_dev->dev;
+ struct device *dev = priv->bus->dev;
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
if (priv->testmode_trace.trace_enabled)
return -EBUSY;
+ if (!tb[IWL_TM_ATTR_TRACE_SIZE])
+ priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF;
+ else
+ priv->testmode_trace.buff_size =
+ nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]);
+ if (!priv->testmode_trace.buff_size)
+ return -EINVAL;
+ if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN ||
+ priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX)
+ return -EINVAL;
+
+ priv->testmode_trace.total_size =
+ priv->testmode_trace.buff_size + TRACE_BUFF_PADD;
priv->testmode_trace.cpu_addr =
dma_alloc_coherent(dev,
- TRACE_TOTAL_SIZE,
+ priv->testmode_trace.total_size,
&priv->testmode_trace.dma_addr,
GFP_KERNEL);
if (!priv->testmode_trace.cpu_addr)
@@ -500,7 +515,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
priv->testmode_trace.cpu_addr, 0x100);
memset(priv->testmode_trace.trace_addr, 0x03B,
- TRACE_BUFF_SIZE);
+ priv->testmode_trace.buff_size);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
sizeof(priv->testmode_trace.dma_addr) + 20);
if (!skb) {
@@ -518,34 +533,14 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
"Error sending msg : %d\n",
status);
}
+ priv->testmode_trace.num_chunks =
+ DIV_ROUND_UP(priv->testmode_trace.buff_size,
+ TRACE_CHUNK_SIZE);
break;
case IWL_TM_CMD_APP2DEV_END_TRACE:
iwl_trace_cleanup(priv);
break;
-
- case IWL_TM_CMD_APP2DEV_READ_TRACE:
- if (priv->testmode_trace.trace_enabled &&
- priv->testmode_trace.trace_addr) {
- skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
- 20 + TRACE_BUFF_SIZE);
- if (skb == NULL) {
- IWL_DEBUG_INFO(priv,
- "Error allocating memory\n");
- return -ENOMEM;
- }
- NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
- TRACE_BUFF_SIZE,
- priv->testmode_trace.trace_addr);
- status = cfg80211_testmode_reply(skb);
- if (status < 0) {
- IWL_DEBUG_INFO(priv,
- "Error sending msg : %d\n", status);
- }
- } else
- return -EFAULT;
- break;
-
default:
IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
return -ENOSYS;
@@ -560,6 +555,73 @@ nla_put_failure:
return -EMSGSIZE;
}
+static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+ struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct iwl_priv *priv = hw->priv;
+ int idx, length;
+
+ if (priv->testmode_trace.trace_enabled &&
+ priv->testmode_trace.trace_addr) {
+ idx = cb->args[4];
+ if (idx >= priv->testmode_trace.num_chunks)
+ return -ENOENT;
+ length = TRACE_CHUNK_SIZE;
+ if (((idx + 1) == priv->testmode_trace.num_chunks) &&
+ (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE))
+ length = priv->testmode_trace.buff_size %
+ TRACE_CHUNK_SIZE;
+
+ NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
+ priv->testmode_trace.trace_addr +
+ (TRACE_CHUNK_SIZE * idx));
+ idx++;
+ cb->args[4] = idx;
+ return 0;
+ } else
+ return -EFAULT;
+
+ nla_put_failure:
+ return -ENOBUFS;
+}
+
+/*
+ * This function handles the user application switch ucode ownership.
+ *
+ * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
+ * decide who the current owner of the uCode
+ *
+ * If the current owner is OWNERSHIP_TM, then the only host command
+ * can deliver to uCode is from testmode, all the other host commands
+ * will dropped.
+ *
+ * default driver is the owner of uCode in normal operational mode
+ *
+ * @hw: ieee80211_hw object that represents the device
+ * @tb: gnl message fields from the user space
+ */
+static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
+{
+ struct iwl_priv *priv = hw->priv;
+ u8 owner;
+
+ if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
+ IWL_DEBUG_INFO(priv, "Error finding ucode owner\n");
+ return -ENOMSG;
+ }
+
+ owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
+ if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
+ priv->ucode_owner = owner;
+ else {
+ IWL_DEBUG_INFO(priv, "Invalid owner\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
/* The testmode gnl message handler that takes the gnl message from the
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
* invoke the corresponding handlers.
@@ -581,7 +643,7 @@ nla_put_failure:
*/
int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
{
- struct nlattr *tb[IWL_TM_ATTR_MAX - 1];
+ struct nlattr *tb[IWL_TM_ATTR_MAX];
struct iwl_priv *priv = hw->priv;
int result;
@@ -629,6 +691,11 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
result = iwl_testmode_trace(hw, tb);
break;
+ case IWL_TM_CMD_APP2DEV_OWNERSHIP:
+ IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
+ result = iwl_testmode_ownership(hw, tb);
+ break;
+
default:
IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
result = -ENOSYS;
@@ -638,3 +705,50 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
mutex_unlock(&priv->mutex);
return result;
}
+
+int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len)
+{
+ struct nlattr *tb[IWL_TM_ATTR_MAX];
+ struct iwl_priv *priv = hw->priv;
+ int result;
+ u32 cmd;
+
+ if (cb->args[3]) {
+ /* offset by 1 since commands start at 0 */
+ cmd = cb->args[3] - 1;
+ } else {
+ result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
+ iwl_testmode_gnl_msg_policy);
+ if (result) {
+ IWL_DEBUG_INFO(priv,
+ "Error parsing the gnl message : %d\n", result);
+ return result;
+ }
+
+ /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
+ if (!tb[IWL_TM_ATTR_COMMAND]) {
+ IWL_DEBUG_INFO(priv,
+ "Error finding testmode command type\n");
+ return -ENOMSG;
+ }
+ cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
+ cb->args[3] = cmd + 1;
+ }
+
+ /* in case multiple accesses to the device happens */
+ mutex_lock(&priv->mutex);
+ switch (cmd) {
+ case IWL_TM_CMD_APP2DEV_READ_TRACE:
+ IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
+ result = iwl_testmode_trace_dump(hw, tb, skb, cb);
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&priv->mutex);
+ return result;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index a88085e9b361..b980bda4b0f8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -66,120 +66,161 @@
#include <linux/types.h>
-/* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and
+/*
+ * Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and
* from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX).
- * The command ID is carried with IWL_TM_ATTR_COMMAND. There are three types of
- * of command from user space and two types of command from kernel space.
- * See below.
+ * The command ID is carried with IWL_TM_ATTR_COMMAND.
+ *
+ * @IWL_TM_CMD_APP2DEV_UCODE:
+ * commands from user application to the uCode,
+ * the actual uCode host command ID is carried with
+ * IWL_TM_ATTR_UCODE_CMD_ID
+ *
+ * @IWL_TM_CMD_APP2DEV_REG_READ32:
+ * @IWL_TM_CMD_APP2DEV_REG_WRITE32:
+ * @IWL_TM_CMD_APP2DEV_REG_WRITE8:
+ * commands from user applicaiton to access register
+ *
+ * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name
+ * @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image
+ * @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration
+ * @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image
+ * @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data
+ * @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS
+ * commands fom user space for pure driver level operations
+ *
+ * @IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
+ * @IWL_TM_CMD_APP2DEV_END_TRACE:
+ * @IWL_TM_CMD_APP2DEV_READ_TRACE:
+ * commands fom user space for uCode trace operations
+ *
+ * @IWL_TM_CMD_DEV2APP_SYNC_RSP:
+ * commands from kernel space to carry the synchronous response
+ * to user application
+ * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT:
+ * commands from kernel space to multicast the spontaneous messages
+ * to user application
+ * @IWL_TM_CMD_DEV2APP_EEPROM_RSP:
+ * commands from kernel space to carry the eeprom response
+ * to user application
+ * @IWL_TM_CMD_APP2DEV_OWNERSHIP:
+ * commands from user application to own change the ownership of the uCode
+ * if application has the ownership, the only host command from
+ * testmode will deliver to uCode. Default owner is driver
*/
enum iwl_tm_cmd_t {
- /* commands from user application to the uCode,
- * the actual uCode host command ID is carried with
- * IWL_TM_ATTR_UCODE_CMD_ID */
- IWL_TM_CMD_APP2DEV_UCODE = 1,
-
- /* commands from user applicaiton to access register */
- IWL_TM_CMD_APP2DEV_REG_READ32,
- IWL_TM_CMD_APP2DEV_REG_WRITE32,
- IWL_TM_CMD_APP2DEV_REG_WRITE8,
-
- /* commands fom user space for pure driver level operations */
- IWL_TM_CMD_APP2DEV_GET_DEVICENAME,
- IWL_TM_CMD_APP2DEV_LOAD_INIT_FW,
- IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB,
- IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW,
- IWL_TM_CMD_APP2DEV_GET_EEPROM,
- IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
- /* if there is other new command for the driver layer operation,
- * append them here */
-
- /* commands fom user space for uCode trace operations */
- IWL_TM_CMD_APP2DEV_BEGIN_TRACE,
- IWL_TM_CMD_APP2DEV_END_TRACE,
- IWL_TM_CMD_APP2DEV_READ_TRACE,
-
- /* commands from kernel space to carry the synchronous response
- * to user application */
- IWL_TM_CMD_DEV2APP_SYNC_RSP,
-
- /* commands from kernel space to multicast the spontaneous messages
- * to user application */
- IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
-
- /* commands from kernel space to carry the eeprom response
- * to user application */
- IWL_TM_CMD_DEV2APP_EEPROM_RSP,
-
- IWL_TM_CMD_MAX,
+ IWL_TM_CMD_APP2DEV_UCODE = 1,
+ IWL_TM_CMD_APP2DEV_REG_READ32 = 2,
+ IWL_TM_CMD_APP2DEV_REG_WRITE32 = 3,
+ IWL_TM_CMD_APP2DEV_REG_WRITE8 = 4,
+ IWL_TM_CMD_APP2DEV_GET_DEVICENAME = 5,
+ IWL_TM_CMD_APP2DEV_LOAD_INIT_FW = 6,
+ IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB = 7,
+ IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW = 8,
+ IWL_TM_CMD_APP2DEV_GET_EEPROM = 9,
+ IWL_TM_CMD_APP2DEV_FIXRATE_REQ = 10,
+ IWL_TM_CMD_APP2DEV_BEGIN_TRACE = 11,
+ IWL_TM_CMD_APP2DEV_END_TRACE = 12,
+ IWL_TM_CMD_APP2DEV_READ_TRACE = 13,
+ IWL_TM_CMD_DEV2APP_SYNC_RSP = 14,
+ IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15,
+ IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16,
+ IWL_TM_CMD_APP2DEV_OWNERSHIP = 17,
+ IWL_TM_CMD_MAX = 18,
};
+/*
+ * Atrribute filed in testmode command
+ * See enum iwl_tm_cmd_t.
+ *
+ * @IWL_TM_ATTR_NOT_APPLICABLE:
+ * The attribute is not applicable or invalid
+ * @IWL_TM_ATTR_COMMAND:
+ * From user space to kernel space:
+ * the command either destines to ucode, driver, or register;
+ * From kernel space to user space:
+ * the command either carries synchronous response,
+ * or the spontaneous message multicast from the device;
+ *
+ * @IWL_TM_ATTR_UCODE_CMD_ID:
+ * @IWL_TM_ATTR_UCODE_CMD_DATA:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,
+ * The mandatory fields are :
+ * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;
+ * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands;
+ * The optional fields are:
+ * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload
+ * to the ucode
+ *
+ * @IWL_TM_ATTR_REG_OFFSET:
+ * @IWL_TM_ATTR_REG_VALUE8:
+ * @IWL_TM_ATTR_REG_VALUE32:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_REG_OFFSET for the offset of the target register;
+ * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value
+ *
+ * @IWL_TM_ATTR_SYNC_RSP:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user
+ * application command
+ *
+ * @IWL_TM_ATTR_UCODE_RX_PKT:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user
+ * application
+ *
+ * @IWL_TM_ATTR_EEPROM:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_EEPROM for the data content responging to the user
+ * application
+ *
+ * @IWL_TM_ATTR_TRACE_ADDR:
+ * @IWL_TM_ATTR_TRACE_SIZE:
+ * @IWL_TM_ATTR_TRACE_DUMP:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
+ * IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size
+ * IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump
+ *
+ * @IWL_TM_ATTR_FIXRATE:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_FIXRATE for the fixed rate
+ *
+ * @IWL_TM_ATTR_UCODE_OWNER:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_UCODE_OWNER for the new owner
+ */
enum iwl_tm_attr_t {
- IWL_TM_ATTR_NOT_APPLICABLE = 0,
-
- /* From user space to kernel space:
- * the command either destines to ucode, driver, or register;
- * See enum iwl_tm_cmd_t.
- *
- * From kernel space to user space:
- * the command either carries synchronous response,
- * or the spontaneous message multicast from the device;
- * See enum iwl_tm_cmd_t. */
- IWL_TM_ATTR_COMMAND,
-
- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,
- * The mandatory fields are :
- * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;
- * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands;
- * The optional fields are:
- * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload
- * to the ucode */
- IWL_TM_ATTR_UCODE_CMD_ID,
- IWL_TM_ATTR_UCODE_CMD_DATA,
-
- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,
- * The mandatory fields are:
- * IWL_TM_ATTR_REG_OFFSET for the offset of the target register;
- * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value */
- IWL_TM_ATTR_REG_OFFSET,
- IWL_TM_ATTR_REG_VALUE8,
- IWL_TM_ATTR_REG_VALUE32,
-
- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,
- * The mandatory fields are:
- * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user
- * application command */
- IWL_TM_ATTR_SYNC_RSP,
- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
- * The mandatory fields are:
- * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user
- * application */
- IWL_TM_ATTR_UCODE_RX_PKT,
-
- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
- * The mandatory fields are:
- * IWL_TM_ATTR_EEPROM for the data content responging to the user
- * application */
- IWL_TM_ATTR_EEPROM,
-
- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
- * The mandatory fields are:
- * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
- */
- IWL_TM_ATTR_TRACE_ADDR,
- IWL_TM_ATTR_TRACE_DATA,
-
- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
- * The mandatory fields are:
- * IWL_TM_ATTR_FIXRATE for the fixed rate
- */
- IWL_TM_ATTR_FIXRATE,
-
- IWL_TM_ATTR_MAX,
+ IWL_TM_ATTR_NOT_APPLICABLE = 0,
+ IWL_TM_ATTR_COMMAND = 1,
+ IWL_TM_ATTR_UCODE_CMD_ID = 2,
+ IWL_TM_ATTR_UCODE_CMD_DATA = 3,
+ IWL_TM_ATTR_REG_OFFSET = 4,
+ IWL_TM_ATTR_REG_VALUE8 = 5,
+ IWL_TM_ATTR_REG_VALUE32 = 6,
+ IWL_TM_ATTR_SYNC_RSP = 7,
+ IWL_TM_ATTR_UCODE_RX_PKT = 8,
+ IWL_TM_ATTR_EEPROM = 9,
+ IWL_TM_ATTR_TRACE_ADDR = 10,
+ IWL_TM_ATTR_TRACE_SIZE = 11,
+ IWL_TM_ATTR_TRACE_DUMP = 12,
+ IWL_TM_ATTR_FIXRATE = 13,
+ IWL_TM_ATTR_UCODE_OWNER = 14,
+ IWL_TM_ATTR_MAX = 15,
};
/* uCode trace buffer */
-#define TRACE_BUFF_SIZE 0x20000
+#define TRACE_BUFF_SIZE_MAX 0x200000
+#define TRACE_BUFF_SIZE_MIN 0x20000
+#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN
#define TRACE_BUFF_PADD 0x2000
-#define TRACE_TOTAL_SIZE (TRACE_BUFF_SIZE + TRACE_BUFF_PADD)
+#define TRACE_CHUNK_SIZE (PAGE_SIZE - 1024)
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
new file mode 100644
index 000000000000..b79330d84185
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ * 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-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
new file mode 100644
index 000000000000..474860290404
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
@@ -0,0 +1,979 @@
+/******************************************************************************
+ *
+ * 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-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
index 137dba95b1ad..a6b2b1db0b1d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
@@ -26,18 +26,58 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
-
#include <linux/etherdevice.h>
-#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#include <net/mac80211.h>
-#include "iwl-eeprom.h"
+
#include "iwl-agn.h"
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-sta.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
+#include "iwl-trans-int-pcie.h"
+
+/**
+ * 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,
+ struct iwl_tx_queue *txq,
+ u16 byte_cnt)
+{
+ struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+ 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;
+
+ 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;
+
+ switch (sec_ctl & TX_CMD_SEC_MSK) {
+ case TX_CMD_SEC_CCM:
+ len += CCMP_MIC_LEN;
+ break;
+ case TX_CMD_SEC_TKIP:
+ len += TKIP_ICV_LEN;
+ break;
+ case TX_CMD_SEC_WEP:
+ len += WEP_IV_LEN + WEP_ICV_LEN;
+ break;
+ }
+
+ bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
+
+ scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
+
+ if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ scd_bc_tbl[txq_id].
+ tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
+}
/**
* iwl_txq_update_write_ptr - Send new write index to hardware
@@ -126,9 +166,8 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
}
static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
- struct iwl_tfd *tfd, int dma_dir)
+ struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
{
- struct pci_dev *dev = priv->pci_dev;
int i;
int num_tbs;
@@ -143,14 +182,14 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
/* Unmap tx_cmd */
if (num_tbs)
- pci_unmap_single(dev,
+ dma_unmap_single(priv->bus->dev,
dma_unmap_addr(meta, mapping),
dma_unmap_len(meta, len),
- PCI_DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++)
- pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
+ dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i),
iwl_tfd_tb_get_len(tfd, i), dma_dir);
}
@@ -158,28 +197,29 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
* iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
* @priv - driver private data
* @txq - tx queue
+ * @index - the index of the TFD to be freed
*
* 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)
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+ int index)
{
struct iwl_tfd *tfd_tmp = txq->tfds;
- int index = txq->q.read_ptr;
iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index],
- PCI_DMA_TODEVICE);
+ DMA_TO_DEVICE);
/* free SKB */
if (txq->txb) {
struct sk_buff *skb;
- skb = txq->txb[txq->q.read_ptr].skb;
+ skb = txq->txb[index].skb;
/* can be called from irqs-disabled context */
if (skb) {
dev_kfree_skb_any(skb);
- txq->txb[txq->q.read_ptr].skb = NULL;
+ txq->txb[index].skb = NULL;
}
}
}
@@ -221,140 +261,6 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
return 0;
}
-/*
- * Tell nic where to find circular buffer of Tx Frame Descriptors for
- * given Tx queue, and enable the DMA channel used for that queue.
- *
- * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
- * channels supported in hardware.
- */
-static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
- int txq_id = txq->q.id;
-
- /* 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
- */
-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 == 0)
- return;
-
- while (q->write_ptr != q->read_ptr) {
- iwlagn_txq_free_tfd(priv, txq);
- 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.
- */
-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->pci_dev->dev;
- int i;
-
- iwl_tx_queue_unmap(priv, txq_id);
-
- /* De-alloc array of command/tx buffers */
- for (i = 0; i < TFD_TX_CMD_SLOTS; 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);
-
- /* 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_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
- */
-void iwl_cmd_queue_unmap(struct iwl_priv *priv)
-{
- struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
- struct iwl_queue *q = &txq->q;
- int i;
-
- if (q->n_bd == 0)
- return;
-
- while (q->read_ptr != q->write_ptr) {
- i = get_cmd_index(q, q->read_ptr);
-
- if (txq->meta[i].flags & CMD_MAPPED) {
- iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i],
- PCI_DMA_BIDIRECTIONAL);
- txq->meta[i].flags = 0;
- }
-
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
- }
-}
-
-/**
- * iwl_cmd_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.
- */
-void iwl_cmd_queue_free(struct iwl_priv *priv)
-{
- struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
- struct device *dev = &priv->pci_dev->dev;
- int i;
-
- iwl_cmd_queue_unmap(priv);
-
- /* De-alloc array of command/tx buffers */
- for (i = 0; i < TFD_CMD_SLOTS; 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);
-
- /* deallocate arrays */
- kfree(txq->cmd);
- kfree(txq->meta);
- txq->cmd = NULL;
- txq->meta = NULL;
-
- /* 0-fill queue descriptor structure */
- memset(txq, 0, sizeof(*txq));
-}
-
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
*
@@ -393,11 +299,10 @@ int iwl_queue_space(const struct iwl_queue *q)
return s;
}
-
/**
* iwl_queue_init - Initialize queue's high/low-water and read/write indexes
*/
-static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
+int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
int count, int slots_num, u32 id)
{
q->n_bd = count;
@@ -427,122 +332,185 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
return 0;
}
-/**
- * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
- */
-static int iwl_tx_queue_alloc(struct iwl_priv *priv,
- struct iwl_tx_queue *txq, u32 id)
+/*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,
+ struct iwl_tx_queue *txq)
{
- struct device *dev = &priv->pci_dev->dev;
- size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
-
- /* Driver private data, only for Tx (not command) queues,
- * not shared with device. */
- if (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;
- }
+ struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+ int txq_id = txq->q.id;
+ int read_ptr = txq->q.read_ptr;
+ u8 sta_id = 0;
+ __le16 bc_ent;
- /* Circular buffer of transmit frame descriptors (TFDs),
- * shared with device */
- txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
- GFP_KERNEL);
- if (!txq->tfds) {
- IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
- goto error;
- }
- txq->q.id = id;
+ WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+
+ if (txq_id != priv->cmd_queue)
+ sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
+
+ bc_ent = cpu_to_le16(1 | (sta_id << 12));
+ scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+
+ if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ scd_bc_tbl[txq_id].
+ tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+}
+
+static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+ u16 txq_id)
+{
+ u32 tbl_dw_addr;
+ u32 tbl_dw;
+ u16 scd_q2ratid;
+
+ scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK;
+
+ tbl_dw_addr = priv->scd_base_addr +
+ SCD_TRANS_TBL_OFFSET_QUEUE(txq_id);
+
+ tbl_dw = iwl_read_targ_mem(priv, 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);
return 0;
+}
+
+static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, 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,
+ 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,
+ int txq_id, u32 index)
+{
+ iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ (index & 0xff) | (txq_id << 8));
+ iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index);
+}
+
+void iwl_trans_tx_queue_set_status(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq,
+ int tx_fifo_id, int scd_retry)
+{
+ int txq_id = txq->q.id;
+ int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
- error:
- kfree(txq->txb);
- txq->txb = NULL;
+ iwl_write_prph(priv, 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) |
+ SCD_QUEUE_STTS_REG_MSK);
- return -ENOMEM;
+ txq->sched_retry = scd_retry;
+
+ IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n",
+ active ? "Activate" : "Deactivate",
+ scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
}
-/**
- * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue
- */
-int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int slots_num, u32 txq_id)
+void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid,
+ int frame_limit)
{
- int i, len;
- int ret;
+ int tx_fifo, txq_id, ssn_idx;
+ u16 ra_tid;
+ unsigned long flags;
+ struct iwl_tid_data *tid_data;
- txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num,
- GFP_KERNEL);
- txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num,
- GFP_KERNEL);
+ if (WARN_ON(sta_id == IWL_INVALID_STATION))
+ return;
+ if (WARN_ON(tid >= MAX_TID_COUNT))
+ return;
- if (!txq->meta || !txq->cmd)
- goto out_free_arrays;
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ tid_data = &priv->stations[sta_id].tid[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);
- len = sizeof(struct iwl_device_cmd);
- for (i = 0; i < slots_num; i++) {
- txq->cmd[i] = kmalloc(len, GFP_KERNEL);
- if (!txq->cmd[i])
- goto err;
- }
+ ra_tid = BUILD_RAxTID(sta_id, tid);
- /* Alloc driver data array and TFD circular buffer */
- ret = iwl_tx_queue_alloc(priv, txq, txq_id);
- if (ret)
- goto err;
+ spin_lock_irqsave(&priv->lock, flags);
- txq->need_update = 0;
+ /* Stop this Tx queue before configuring it */
+ iwlagn_tx_queue_stop_scheduler(priv, txq_id);
- /*
- * 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);
+ /* Map receiver-address / traffic-ID to this queue */
+ iwlagn_tx_queue_set_q2ratid(priv, ra_tid, 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));
+ /* Set this queue as a chain-building queue */
+ iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<<txq_id));
- /* 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;
+ /* enable aggregations for the queue */
+ iwl_set_bits_prph(priv, SCD_AGGR_SEL, (1<<txq_id));
- /* Tell device where to find queue */
- iwlagn_tx_queue_init(priv, txq);
+ /* 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);
- return 0;
-err:
- for (i = 0; i < slots_num; i++)
- kfree(txq->cmd[i]);
-out_free_arrays:
- kfree(txq->meta);
- kfree(txq->cmd);
-
- return -ENOMEM;
+ /* Set up Tx window size and frame limit for this queue */
+ iwl_write_targ_mem(priv, priv->scd_base_addr +
+ SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
+ sizeof(u32),
+ ((frame_limit <<
+ SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
+ SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+ ((frame_limit <<
+ 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));
+
+ /* 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);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
-void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int slots_num, u32 txq_id)
+int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+ u16 ssn_idx, u8 tx_fifo)
{
- memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * slots_num);
+ if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
+ (IWLAGN_FIRST_AMPDU_QUEUE +
+ priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+ IWL_ERR(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;
+ }
- txq->need_update = 0;
+ iwlagn_tx_queue_stop_scheduler(priv, txq_id);
+
+ iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id));
- /* Initialize queue's high/low-water marks, and head/tail indexes */
- iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+ 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);
- /* Tell device where to find queue */
- iwlagn_tx_queue_init(priv, txq);
+ 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);
+
+ return 0;
}
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
@@ -556,7 +524,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
* failed. On success, it turns the index (> 0) of command in the
* command queue.
*/
-int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
struct iwl_queue *q = &txq->q;
@@ -581,6 +549,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return -EIO;
}
+ if ((priv->ucode_owner == IWL_OWNERSHIP_TM) &&
+ !(cmd->flags & CMD_ON_DEMAND)) {
+ IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
+ return -EIO;
+ }
+
copy_size = sizeof(out_cmd->hdr);
cmd_size = sizeof(out_cmd->hdr);
@@ -634,11 +608,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd = txq->cmd[idx];
out_meta = &txq->meta[idx];
- if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
- return -ENOSPC;
- }
-
memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
if (cmd->flags & CMD_WANT_SKB)
out_meta->source = cmd;
@@ -671,9 +640,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
q->write_ptr, idx, priv->cmd_queue);
- phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
- copy_size, PCI_DMA_BIDIRECTIONAL);
- if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
+ phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size,
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) {
idx = -ENOMEM;
goto out;
}
@@ -693,12 +662,12 @@ 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 = pci_map_single(priv->pci_dev, (void *)cmd->data[i],
- cmd->len[i], PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) {
+ phys_addr = dma_map_single(priv->bus->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,
&txq->tfds[q->write_ptr],
- PCI_DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
idx = -ENOMEM;
goto out;
}
@@ -712,7 +681,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
#endif
}
- out_meta->flags = cmd->flags | CMD_MAPPED;
+ out_meta->flags = cmd->flags;
txq->need_update = 1;
@@ -748,9 +717,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
int nfreed = 0;
if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
- IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
- "is out of range [0-%d] %d %d.\n", txq_id,
- idx, q->n_bd, q->write_ptr, q->read_ptr);
+ 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, idx, q->n_bd, q->write_ptr, q->read_ptr);
return;
}
@@ -802,7 +771,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
cmd = txq->cmd[cmd_index];
meta = &txq->meta[cmd_index];
- iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], PCI_DMA_BIDIRECTIONAL);
+ iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
/* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) {
@@ -822,8 +791,246 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
wake_up_interruptible(&priv->wait_command_queue);
}
- /* Mark as unmapped */
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";
+
+ }
+}
+
+#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)
+{
+ int ret;
+
+ /* An asynchronous command can not expect an SKB to be set. */
+ 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))
+ return -EBUSY;
+
+ ret = iwl_enqueue_hcmd(priv, cmd);
+ if (ret < 0) {
+ IWL_ERR(priv, "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)
+{
+ int cmd_idx;
+ int ret;
+
+ lockdep_assert_held(&priv->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",
+ get_cmd_string(cmd->id));
+
+ set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+ IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
+ get_cmd_string(cmd->id));
+
+ cmd_idx = iwl_enqueue_hcmd(priv, 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",
+ get_cmd_string(cmd->id), ret);
+ return ret;
+ }
+
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+ HOST_COMPLETE_TIMEOUT);
+ if (!ret) {
+ if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+ IWL_ERR(priv,
+ "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"
+ "%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",
+ 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",
+ 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",
+ get_cmd_string(cmd->id));
+ ret = -EIO;
+ goto cancel;
+ }
+
+ return 0;
+
+cancel:
+ if (cmd->flags & CMD_WANT_SKB) {
+ /*
+ * Cancel the CMD_WANT_SKB flag for the cmd in the
+ * TX cmd queue. Otherwise in case the cmd comes
+ * in later, it will possibly set an invalid
+ * address (cmd->meta.source).
+ */
+ priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
+ ~CMD_WANT_SKB;
+ }
+fail:
+ if (cmd->reply_page) {
+ iwl_free_pages(priv, cmd->reply_page);
+ cmd->reply_page = 0;
+ }
+
+ return ret;
+}
+
+int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+ if (cmd->flags & CMD_ASYNC)
+ return iwl_send_cmd_async(priv, cmd);
+
+ return iwl_send_cmd_sync(priv, cmd);
+}
+
+int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
+ const void *data)
+{
+ struct iwl_host_cmd cmd = {
+ .id = id,
+ .len = { len, },
+ .data = { data, },
+ .flags = flags,
+ };
+
+ return iwl_send_cmd(priv, &cmd);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
new file mode 100644
index 000000000000..41f0de914008
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -0,0 +1,1172 @@
+/******************************************************************************
+ *
+ * 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 "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,
+};
+
+int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv)
+{
+ 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);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
new file mode 100644
index 000000000000..7993aa7ae668
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -0,0 +1,225 @@
+/******************************************************************************
+ *
+ * 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_trans_h__
+#define __iwl_trans_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_trans_ops - transport specific operations
+ * @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.
+ * @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
+ * ready and a successful ADDBA response has been received.
+ * @txq_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...
+ */
+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);
+
+ int (*send_cmd)(struct iwl_priv *priv, 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 (*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);
+
+ void (*kick_nic)(struct iwl_priv *priv);
+
+ void (*sync_irq)(struct iwl_priv *priv);
+ void (*free)(struct iwl_priv *priv);
+};
+
+struct iwl_trans {
+ const struct iwl_trans_ops *ops;
+ struct iwl_priv *priv;
+};
+
+static inline int trans_start_device(struct iwl_trans *trans)
+{
+ return trans->ops->start_device(trans->priv);
+}
+
+static inline int trans_prepare_card_hw(struct iwl_trans *trans)
+{
+ return trans->ops->prepare_card_hw(trans->priv);
+}
+
+static inline void trans_stop_device(struct iwl_trans *trans)
+{
+ trans->ops->stop_device(trans->priv);
+}
+
+static inline void trans_tx_start(struct iwl_trans *trans)
+{
+ trans->ops->tx_start(trans->priv);
+}
+
+static inline void trans_rx_free(struct iwl_trans *trans)
+{
+ trans->ops->rx_free(trans->priv);
+}
+
+static inline void trans_tx_free(struct iwl_trans *trans)
+{
+ trans->ops->tx_free(trans->priv);
+}
+
+static inline int trans_send_cmd(struct iwl_trans *trans,
+ struct iwl_host_cmd *cmd)
+{
+ return trans->ops->send_cmd(trans->priv, cmd);
+}
+
+static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
+ u16 len, const void *data)
+{
+ return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data);
+}
+
+static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans,
+ int txq_id)
+{
+ return trans->ops->get_tx_cmd(trans->priv, txq_id);
+}
+
+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)
+{
+ return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx);
+}
+
+static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id,
+ u16 ssn_idx, u8 tx_fifo)
+{
+ return trans->ops->txq_agg_disable(trans->priv, txq_id,
+ ssn_idx, tx_fifo);
+}
+
+static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id,
+ int tid, int frame_limit)
+{
+ trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit);
+}
+
+static inline void trans_kick_nic(struct iwl_trans *trans)
+{
+ trans->ops->kick_nic(trans->priv);
+}
+
+static inline void trans_sync_irq(struct iwl_trans *trans)
+{
+ trans->ops->sync_irq(trans->priv);
+}
+
+static inline void trans_free(struct iwl_trans *trans)
+{
+ trans->ops->free(trans->priv);
+}
+
+int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv);
+
+/*TODO: this functions should NOT be exported from trans module - export it
+ * until the reclaim flow will be brought to the transport module too */
+
+struct iwl_tx_queue;
+void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq);
+
+#endif /* __iwl_trans_h__ */
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
index 49067092d336..6f1afe6bbc8c 100644
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -187,7 +187,7 @@ static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
if (ret < 0)
goto err_release_fw;
opcode_idx++;
- };
+ }
/* Read firmware version */
fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0);
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 5d637af2d7c3..b456a53b64b1 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 71c8f3fccfa1..dbd24a4607ec 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -3,6 +3,7 @@
* It prepares command and sends it to firmware when it is ready.
*/
+#include <linux/hardirq.h>
#include <linux/kfifo.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -873,6 +874,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_GET);
+ cmd.offset = cpu_to_le16(offset);
if (reg != CMD_MAC_REG_ACCESS &&
reg != CMD_BBP_REG_ACCESS &&
@@ -882,7 +884,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
}
ret = lbs_cmd_with_response(priv, reg, &cmd);
- if (ret) {
+ if (!ret) {
if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
*value = cmd.value.bbp_rf;
else if (reg == CMD_MAC_REG_ACCESS)
@@ -915,6 +917,7 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.offset = cpu_to_le16(offset);
if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
cmd.value.bbp_rf = (u8) (value & 0xFF);
@@ -1067,16 +1070,34 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
spin_unlock_irqrestore(&priv->driver_lock, flags);
}
-void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
- int result)
+void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result)
{
+ /*
+ * Normally, commands are removed from cmdpendingq before being
+ * submitted. However, we can arrive here on alternative codepaths
+ * where the command is still pending. Make sure the command really
+ * isn't part of a list at this point.
+ */
+ list_del_init(&cmd->list);
+
cmd->result = result;
cmd->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmd->cmdwait_q);
+ wake_up(&cmd->cmdwait_q);
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);
+}
+
+void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ __lbs_complete_command(priv, cmd, result);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
}
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
@@ -1248,7 +1269,7 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
if (!list_empty(&priv->cmdfreeq)) {
tempnode = list_first_entry(&priv->cmdfreeq,
struct cmd_ctrl_node, list);
- list_del(&tempnode->list);
+ list_del_init(&tempnode->list);
} else {
lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
tempnode = NULL;
@@ -1356,10 +1377,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
- spin_lock_irqsave(&priv->driver_lock, flags);
- list_del(&cmdnode->list);
lbs_complete_command(priv, cmdnode, 0);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
goto done;
@@ -1369,10 +1387,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
(priv->psstate == PS_STATE_PRE_SLEEP)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
- spin_lock_irqsave(&priv->driver_lock, flags);
- list_del(&cmdnode->list);
lbs_complete_command(priv, cmdnode, 0);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
priv->needtowakeup = 1;
ret = 0;
@@ -1384,7 +1399,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
}
}
spin_lock_irqsave(&priv->driver_lock, flags);
- list_del(&cmdnode->list);
+ list_del_init(&cmdnode->list);
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
le16_to_cpu(cmd->command));
@@ -1667,7 +1682,13 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
}
might_sleep();
- wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
+
+ /*
+ * Be careful with signals here. A signal may be received as the system
+ * goes into suspend or resume. We do not want this to interrupt the
+ * command, so we perform an uninterruptible sleep.
+ */
+ wait_event(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
spin_lock_irqsave(&priv->driver_lock, flags);
ret = cmdnode->result;
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 7109d6b717ea..b280ef7a0aea 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -59,6 +59,8 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv);
int lbs_free_cmd_buffer(struct lbs_private *priv);
int lbs_execute_next_command(struct lbs_private *priv);
+void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result);
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
int result);
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 207fc361db84..178b222b3ce1 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -3,6 +3,7 @@
* responses as well as events generated by firmware.
*/
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sched.h>
@@ -165,7 +166,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
}
- lbs_complete_command(priv, priv->cur_cmd, result);
+ __lbs_complete_command(priv, priv->cur_cmd, result);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
@@ -186,7 +187,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
break;
}
- lbs_complete_command(priv, priv->cur_cmd, result);
+ __lbs_complete_command(priv, priv->cur_cmd, result);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
@@ -204,7 +205,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
if (priv->cur_cmd) {
/* Clean up and Put current command back to cmdfreeq */
- lbs_complete_command(priv, priv->cur_cmd, result);
+ __lbs_complete_command(priv, priv->cur_cmd, result);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 23250f621761..1af182778844 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -1,6 +1,7 @@
#include <linux/dcache.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
+#include <linux/hardirq.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 76d018beebf4..adb3490e3cf5 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -44,9 +44,7 @@ struct lbs_private {
/* Mesh */
struct net_device *mesh_dev; /* Virtual device */
#ifdef CONFIG_LIBERTAS_MESH
- u32 mesh_connect_status;
struct lbs_mesh_stats mstats;
- int mesh_open;
uint16_t mesh_tlv;
u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 mesh_ssid_len;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 29dbce4a9f86..4dfb3bfd2cf3 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -1,3 +1,4 @@
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 224e9853c480..387786e1b394 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -892,6 +892,37 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
}
+static struct mmc_host *reset_host;
+
+static void if_sdio_reset_card_worker(struct work_struct *work)
+{
+ /*
+ * The actual reset operation must be run outside of lbs_thread. This
+ * is because mmc_remove_host() will cause the device to be instantly
+ * destroyed, and the libertas driver then needs to end lbs_thread,
+ * leading to a deadlock.
+ *
+ * We run it in a workqueue totally independent from the if_sdio_card
+ * instance for that reason.
+ */
+
+ pr_info("Resetting card...");
+ mmc_remove_host(reset_host);
+ mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker);
+
+static void if_sdio_reset_card(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+
+ if (work_pending(&card_reset_work))
+ return;
+
+ reset_host = card->func->card->host;
+ schedule_work(&card_reset_work);
+}
+
/*******************************************************************/
/* SDIO callbacks */
/*******************************************************************/
@@ -1065,6 +1096,7 @@ static int if_sdio_probe(struct sdio_func *func,
priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
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;
sdio_claim_host(func);
@@ -1301,6 +1333,8 @@ static void __exit if_sdio_exit_module(void)
/* Set the flag as user is removing this module. */
user_rmmod = 1;
+ cancel_work_sync(&card_reset_work);
+
sdio_unregister_driver(&if_sdio_driver);
lbs_deb_leave(LBS_DEB_SDIO);
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 463352c890d7..e0286cfbc91d 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -19,6 +19,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
@@ -1032,7 +1034,6 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
static int if_spi_init_card(struct if_spi_card *card)
{
struct lbs_private *priv = card->priv;
- struct spi_device *spi = card->spi;
int err, i;
u32 scratch;
const struct firmware *helper = NULL;
@@ -1080,8 +1081,9 @@ static int if_spi_init_card(struct if_spi_card *card)
"attached to SPI bus_num %d, chip_select %d. "
"spi->max_speed_hz=%d\n",
card->card_id, card->card_rev,
- spi->master->bus_num, spi->chip_select,
- spi->max_speed_hz);
+ card->spi->master->bus_num,
+ card->spi->chip_select,
+ card->spi->max_speed_hz);
err = if_spi_prog_helper_firmware(card, helper);
if (err)
goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 8c40949cb076..94652c5a25de 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -9,6 +9,7 @@
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/kthread.h>
@@ -511,7 +512,7 @@ static int lbs_thread(void *data)
if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
if (priv->mesh_dev &&
- lbs_mesh_connected(priv))
+ netif_running(priv->mesh_dev))
netif_wake_queue(priv->mesh_dev);
}
}
@@ -638,6 +639,14 @@ static void lbs_cmd_timeout_handler(unsigned long data)
le16_to_cpu(priv->cur_cmd->cmdbuf->command));
priv->cmd_timed_out = 1;
+
+ /*
+ * If the device didn't even acknowledge the command, reset the state
+ * so that we don't block all future commands due to this one timeout.
+ */
+ if (priv->dnld_sent == DNLD_CMD_SENT)
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+
wake_up_interruptible(&priv->waitq);
out:
spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -994,7 +1003,7 @@ void lbs_stop_card(struct lbs_private *priv)
list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
cmdnode->result = -ENOENT;
cmdnode->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmdnode->cmdwait_q);
+ wake_up(&cmdnode->cmdwait_q);
}
/* Flush the command the card is currently processing */
@@ -1002,7 +1011,7 @@ void lbs_stop_card(struct lbs_private *priv)
lbs_deb_main("clearing current command\n");
priv->cur_cmd->result = -ENOENT;
priv->cur_cmd->cmdwaitqwoken = 1;
- wake_up_interruptible(&priv->cur_cmd->cmdwait_q);
+ wake_up(&priv->cur_cmd->cmdwait_q);
}
lbs_deb_main("done clearing commands\n");
spin_unlock_irqrestore(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 24cf06680c6b..be72c08ea2a7 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -2,6 +2,7 @@
#include <linux/delay.h>
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
@@ -14,6 +15,121 @@
#include "cmd.h"
+static int lbs_add_mesh(struct lbs_private *priv);
+
+/***************************************************************************
+ * Mesh command handling
+ */
+
+static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+ struct cmd_ds_mesh_access *cmd)
+{
+ int ret;
+
+ lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+ cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
+ cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
+ cmd->hdr.result = 0;
+
+ cmd->action = cpu_to_le16(cmd_action);
+
+ ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
+
+ lbs_deb_leave(LBS_DEB_CMD);
+ return ret;
+}
+
+static int __lbs_mesh_config_send(struct lbs_private *priv,
+ struct cmd_ds_mesh_config *cmd,
+ uint16_t action, uint16_t type)
+{
+ int ret;
+ u16 command = CMD_MESH_CONFIG_OLD;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ /*
+ * Command id is 0xac for v10 FW along with mesh interface
+ * id in bits 14-13-12.
+ */
+ if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+ command = CMD_MESH_CONFIG |
+ (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
+
+ cmd->hdr.command = cpu_to_le16(command);
+ cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
+ cmd->hdr.result = 0;
+
+ cmd->type = cpu_to_le16(type);
+ cmd->action = cpu_to_le16(action);
+
+ ret = lbs_cmd_with_response(priv, command, cmd);
+
+ lbs_deb_leave(LBS_DEB_CMD);
+ return ret;
+}
+
+static int lbs_mesh_config_send(struct lbs_private *priv,
+ struct cmd_ds_mesh_config *cmd,
+ uint16_t action, uint16_t type)
+{
+ int ret;
+
+ if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
+ return -EOPNOTSUPP;
+
+ ret = __lbs_mesh_config_send(priv, cmd, action, type);
+ return ret;
+}
+
+/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
+ * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
+ * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
+ * lbs_mesh_config_send.
+ */
+static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
+ uint16_t chan)
+{
+ struct cmd_ds_mesh_config cmd;
+ struct mrvl_meshie *ie;
+ DECLARE_SSID_BUF(ssid);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.channel = cpu_to_le16(chan);
+ ie = (struct mrvl_meshie *)cmd.data;
+
+ switch (action) {
+ case CMD_ACT_MESH_CONFIG_START:
+ ie->id = WLAN_EID_GENERIC;
+ ie->val.oui[0] = 0x00;
+ ie->val.oui[1] = 0x50;
+ ie->val.oui[2] = 0x43;
+ ie->val.type = MARVELL_MESH_IE_TYPE;
+ ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
+ ie->val.version = MARVELL_MESH_IE_VERSION;
+ ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
+ ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
+ ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
+ ie->val.mesh_id_len = priv->mesh_ssid_len;
+ memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
+ ie->len = sizeof(struct mrvl_meshie_val) -
+ IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
+ cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
+ break;
+ case CMD_ACT_MESH_CONFIG_STOP:
+ break;
+ default:
+ return -1;
+ }
+ lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
+ action, priv->mesh_tlv, chan,
+ print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+
+ return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
+}
+
+
/***************************************************************************
* Mesh sysfs support
*/
@@ -154,17 +270,11 @@ static ssize_t lbs_mesh_set(struct device *dev,
{
struct lbs_private *priv = to_net_dev(dev)->ml_priv;
int enable;
- int ret, action = CMD_ACT_MESH_CONFIG_STOP;
sscanf(buf, "%x", &enable);
enable = !!enable;
if (enable == !!priv->mesh_dev)
return count;
- if (enable)
- action = CMD_ACT_MESH_CONFIG_START;
- ret = lbs_mesh_config(priv, action, priv->channel);
- if (ret)
- return ret;
if (enable)
lbs_add_mesh(priv);
@@ -199,582 +309,11 @@ static struct attribute *lbs_mesh_sysfs_entries[] = {
NULL,
};
-static struct attribute_group lbs_mesh_attr_group = {
+static const struct attribute_group lbs_mesh_attr_group = {
.attrs = lbs_mesh_sysfs_entries,
};
-
-/***************************************************************************
- * Initializing and starting, stopping mesh
- */
-
-/*
- * Check mesh FW version and appropriately send the mesh start
- * command
- */
-int lbs_init_mesh(struct lbs_private *priv)
-{
- struct net_device *dev = priv->dev;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MESH);
-
- priv->mesh_connect_status = LBS_DISCONNECTED;
-
- /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
- /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
- /* 5.110.22 have mesh command with 0xa3 command id */
- /* 10.0.0.p0 FW brings in mesh config command with different id */
- /* Check FW version MSB and initialize mesh_fw_ver */
- if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
- /* Enable mesh, if supported, and work out which TLV it uses.
- 0x100 + 291 is an unofficial value used in 5.110.20.pXX
- 0x100 + 37 is the official value used in 5.110.21.pXX
- but we check them in that order because 20.pXX doesn't
- give an error -- it just silently fails. */
-
- /* 5.110.20.pXX firmware will fail the command if the channel
- doesn't match the existing channel. But only if the TLV
- is correct. If the channel is wrong, _BOTH_ versions will
- give an error to 0x100+291, and allow 0x100+37 to succeed.
- It's just that 5.110.20.pXX will not have done anything
- useful */
-
- priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel)) {
- priv->mesh_tlv = TLV_TYPE_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel))
- priv->mesh_tlv = 0;
- }
- } else
- if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
- (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
- /* 10.0.0.pXX new firmwares should succeed with TLV
- * 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))
- priv->mesh_tlv = 0;
- }
-
-
- 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;
- }
-
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
-
-
-int lbs_deinit_mesh(struct lbs_private *priv)
-{
- struct net_device *dev = priv->dev;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MESH);
-
- if (priv->mesh_tlv) {
- device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
- ret = 1;
- }
-
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
-
-
-/**
- * lbs_mesh_stop - close the mshX interface
- *
- * @dev: A pointer to &net_device structure
- * returns: 0
- */
-static int lbs_mesh_stop(struct net_device *dev)
-{
- struct lbs_private *priv = dev->ml_priv;
-
- lbs_deb_enter(LBS_DEB_MESH);
- spin_lock_irq(&priv->driver_lock);
-
- priv->mesh_open = 0;
- priv->mesh_connect_status = LBS_DISCONNECTED;
-
- netif_stop_queue(dev);
- netif_carrier_off(dev);
-
- spin_unlock_irq(&priv->driver_lock);
-
- schedule_work(&priv->mcast_work);
-
- lbs_deb_leave(LBS_DEB_MESH);
- return 0;
-}
-
-/**
- * lbs_mesh_dev_open - open the mshX interface
- *
- * @dev: A pointer to &net_device structure
- * returns: 0 or -EBUSY if monitor mode active
- */
-static int lbs_mesh_dev_open(struct net_device *dev)
-{
- struct lbs_private *priv = dev->ml_priv;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_NET);
-
- spin_lock_irq(&priv->driver_lock);
-
- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
- ret = -EBUSY;
- goto out;
- }
-
- priv->mesh_open = 1;
- priv->mesh_connect_status = LBS_CONNECTED;
- netif_carrier_on(dev);
-
- if (!priv->tx_pending_len)
- netif_wake_queue(dev);
- out:
-
- spin_unlock_irq(&priv->driver_lock);
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
- return ret;
-}
-
-static const struct net_device_ops mesh_netdev_ops = {
- .ndo_open = lbs_mesh_dev_open,
- .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,
-};
-
-/**
- * lbs_add_mesh - add mshX interface
- *
- * @priv: A pointer to the &struct lbs_private structure
- * returns: 0 if successful, -X otherwise
- */
-int lbs_add_mesh(struct lbs_private *priv)
-{
- struct net_device *mesh_dev = NULL;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MESH);
-
- /* Allocate a virtual mesh device */
- mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
- if (!mesh_dev) {
- lbs_deb_mesh("init mshX device failed\n");
- ret = -ENOMEM;
- goto done;
- }
- mesh_dev->ml_priv = priv;
- priv->mesh_dev = mesh_dev;
-
- mesh_dev->netdev_ops = &mesh_netdev_ops;
- mesh_dev->ethtool_ops = &lbs_ethtool_ops;
- memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
-
- SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
-
- mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- /* Register virtual mesh interface */
- ret = register_netdev(mesh_dev);
- if (ret) {
- pr_err("cannot register mshX virtual interface\n");
- goto err_free;
- }
-
- ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
- if (ret)
- goto err_unregister;
-
- lbs_persist_config_init(mesh_dev);
-
- /* Everything successful */
- ret = 0;
- goto done;
-
-err_unregister:
- unregister_netdev(mesh_dev);
-
-err_free:
- free_netdev(mesh_dev);
-
-done:
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
-
-void lbs_remove_mesh(struct lbs_private *priv)
-{
- struct net_device *mesh_dev;
-
- mesh_dev = priv->mesh_dev;
- if (!mesh_dev)
- return;
-
- lbs_deb_enter(LBS_DEB_MESH);
- netif_stop_queue(mesh_dev);
- netif_carrier_off(mesh_dev);
- sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
- lbs_persist_config_remove(mesh_dev);
- unregister_netdev(mesh_dev);
- priv->mesh_dev = NULL;
- free_netdev(mesh_dev);
- lbs_deb_leave(LBS_DEB_MESH);
-}
-
-
-
-/***************************************************************************
- * Sending and receiving
- */
-struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
- struct net_device *dev, struct rxpd *rxpd)
-{
- if (priv->mesh_dev) {
- if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
- if (rxpd->rx_control & RxPD_MESH_FRAME)
- dev = priv->mesh_dev;
- } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
- if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
- dev = priv->mesh_dev;
- }
- }
- return dev;
-}
-
-
-void lbs_mesh_set_txpd(struct lbs_private *priv,
- struct net_device *dev, struct txpd *txpd)
-{
- if (dev == priv->mesh_dev) {
- if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
- txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
- else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
- txpd->u.bss.bss_num = MESH_IFACE_ID;
- }
-}
-
-
-/***************************************************************************
- * Mesh command handling
- */
-
-/**
- * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries
- *
- * @priv: A pointer to &struct lbs_private structure
- * @add: TRUE to add the entry, FALSE to delete it
- * @addr1: Destination address to blind or unblind
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- BUG_ON(addr1 == NULL);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- memcpy(cmd.addr1, addr1, ETH_ALEN);
- if (add) {
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD);
- lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
- addr1, ETH_ALEN);
- } else {
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL);
- lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
- addr1, ETH_ALEN);
- }
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_reset - Reset/clear the mesh blinding table
- *
- * @priv: A pointer to &struct lbs_private structure
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_reset(struct lbs_private *priv)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh
- * blinding table
- *
- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
- * table, but an inverted table allows *only* traffic from nodes listed in
- * the table.
- *
- * @priv: A pointer to &struct lbs_private structure
- * @inverted: On success, TRUE if the blinding table is inverted,
- * FALSE if it is not inverted
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- BUG_ON(inverted == NULL);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
- if (ret == 0)
- *inverted = !!cmd.id;
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_set_inverted - Sets the inverted status of the mesh
- * blinding table
- *
- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
- * table, but an inverted table allows *only* traffic from nodes listed in
- * the table.
- *
- * @priv: A pointer to &struct lbs_private structure
- * @inverted: TRUE to invert the blinding table (only traffic from
- * listed nodes allowed), FALSE to return it
- * to normal state (listed nodes ignored)
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
- cmd.id = cpu_to_le32(!!inverted);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table
- *
- * @priv: A pointer to &struct lbs_private structure
- * @id: The ID of the entry to list
- * @addr1: MAC address associated with the table entry
- *
- * returns: 0 on success, error on failure
- */
-int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1)
-{
- struct cmd_ds_bt_access cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- BUG_ON(addr1 == NULL);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
- cmd.id = cpu_to_le32(id);
-
- ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
- if (ret == 0)
- memcpy(addr1, cmd.addr1, sizeof(cmd.addr1));
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * lbs_cmd_fwt_access - Access the mesh forwarding table
- *
- * @priv: A pointer to &struct lbs_private structure
- * @cmd_action: The forwarding table action to perform
- * @cmd: The pre-filled FWT_ACCESS command
- *
- * returns: 0 on success and 'cmd' will be filled with the
- * firmware's response
- */
-int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
- struct cmd_ds_fwt_access *cmd)
-{
- int ret;
-
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
- cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS);
- cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access));
- cmd->hdr.result = 0;
- cmd->action = cpu_to_le16(cmd_action);
-
- ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return 0;
-}
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
- struct cmd_ds_mesh_access *cmd)
-{
- int ret;
-
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
- cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
- cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
- cmd->hdr.result = 0;
-
- cmd->action = cpu_to_le16(cmd_action);
-
- ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return ret;
-}
-
-static int __lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type)
-{
- int ret;
- u16 command = CMD_MESH_CONFIG_OLD;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- /*
- * Command id is 0xac for v10 FW along with mesh interface
- * id in bits 14-13-12.
- */
- if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
- command = CMD_MESH_CONFIG |
- (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
-
- cmd->hdr.command = cpu_to_le16(command);
- cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
- cmd->hdr.result = 0;
-
- cmd->type = cpu_to_le16(type);
- cmd->action = cpu_to_le16(action);
-
- ret = lbs_cmd_with_response(priv, command, cmd);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return ret;
-}
-
-int lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type)
-{
- int ret;
-
- if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
- return -EOPNOTSUPP;
-
- ret = __lbs_mesh_config_send(priv, cmd, action, type);
- return ret;
-}
-
-/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
- * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
- * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
- * lbs_mesh_config_send.
- */
-int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
-{
- struct cmd_ds_mesh_config cmd;
- struct mrvl_meshie *ie;
- DECLARE_SSID_BUF(ssid);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.channel = cpu_to_le16(chan);
- ie = (struct mrvl_meshie *)cmd.data;
-
- switch (action) {
- case CMD_ACT_MESH_CONFIG_START:
- ie->id = WLAN_EID_GENERIC;
- ie->val.oui[0] = 0x00;
- ie->val.oui[1] = 0x50;
- ie->val.oui[2] = 0x43;
- ie->val.type = MARVELL_MESH_IE_TYPE;
- ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
- ie->val.version = MARVELL_MESH_IE_VERSION;
- ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
- ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
- ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
- ie->val.mesh_id_len = priv->mesh_ssid_len;
- memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
- ie->len = sizeof(struct mrvl_meshie_val) -
- IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
- cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
- break;
- case CMD_ACT_MESH_CONFIG_STOP:
- break;
- default:
- return -1;
- }
- lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
- action, priv->mesh_tlv, chan,
- print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
-
- return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
-}
-
-
-
/***************************************************************************
* Persistent configuration support
*/
@@ -1231,7 +770,7 @@ static struct attribute *boot_opts_attrs[] = {
NULL
};
-static struct attribute_group boot_opts_group = {
+static const struct attribute_group boot_opts_group = {
.name = "boot_options",
.attrs = boot_opts_attrs,
};
@@ -1244,31 +783,299 @@ static struct attribute *mesh_ie_attrs[] = {
NULL
};
-static struct attribute_group mesh_ie_group = {
+static const struct attribute_group mesh_ie_group = {
.name = "mesh_ie",
.attrs = mesh_ie_attrs,
};
-void lbs_persist_config_init(struct net_device *dev)
+static void lbs_persist_config_init(struct net_device *dev)
{
int ret;
ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
}
-void lbs_persist_config_remove(struct net_device *dev)
+static void lbs_persist_config_remove(struct net_device *dev)
{
sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
}
+/***************************************************************************
+ * Initializing and starting, stopping mesh
+ */
+
+/*
+ * Check mesh FW version and appropriately send the mesh start
+ * command
+ */
+int lbs_init_mesh(struct lbs_private *priv)
+{
+ struct net_device *dev = priv->dev;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
+ /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
+ /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
+ /* 5.110.22 have mesh command with 0xa3 command id */
+ /* 10.0.0.p0 FW brings in mesh config command with different id */
+ /* Check FW version MSB and initialize mesh_fw_ver */
+ if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
+ /* Enable mesh, if supported, and work out which TLV it uses.
+ 0x100 + 291 is an unofficial value used in 5.110.20.pXX
+ 0x100 + 37 is the official value used in 5.110.21.pXX
+ but we check them in that order because 20.pXX doesn't
+ give an error -- it just silently fails. */
+
+ /* 5.110.20.pXX firmware will fail the command if the channel
+ doesn't match the existing channel. But only if the TLV
+ is correct. If the channel is wrong, _BOTH_ versions will
+ give an error to 0x100+291, and allow 0x100+37 to succeed.
+ It's just that 5.110.20.pXX will not have done anything
+ useful */
+
+ priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+ priv->channel)) {
+ priv->mesh_tlv = TLV_TYPE_MESH_ID;
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+ priv->channel))
+ priv->mesh_tlv = 0;
+ }
+ } else
+ if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
+ (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
+ /* 10.0.0.pXX new firmwares should succeed with TLV
+ * 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))
+ priv->mesh_tlv = 0;
+ }
+
+ /* Stop meshing until interface is brought up */
+ lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
+
+ 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;
+ }
+
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
+}
+
+
+int lbs_deinit_mesh(struct lbs_private *priv)
+{
+ struct net_device *dev = priv->dev;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
+ if (priv->mesh_tlv) {
+ device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+ ret = 1;
+ }
+
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
+}
+
+
+/**
+ * lbs_mesh_stop - close the mshX interface
+ *
+ * @dev: A pointer to &net_device structure
+ * returns: 0
+ */
+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);
+
+ spin_lock_irq(&priv->driver_lock);
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+
+ spin_unlock_irq(&priv->driver_lock);
+
+ schedule_work(&priv->mcast_work);
+
+ lbs_deb_leave(LBS_DEB_MESH);
+ return 0;
+}
+
+/**
+ * lbs_mesh_dev_open - open the mshX interface
+ *
+ * @dev: A pointer to &net_device structure
+ * returns: 0 or -EBUSY if monitor mode active
+ */
+static int lbs_mesh_dev_open(struct net_device *dev)
+{
+ struct lbs_private *priv = dev->ml_priv;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_NET);
+
+ spin_lock_irq(&priv->driver_lock);
+
+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+ ret = -EBUSY;
+ spin_unlock_irq(&priv->driver_lock);
+ goto out;
+ }
+
+ netif_carrier_on(dev);
+
+ if (!priv->tx_pending_len)
+ netif_wake_queue(dev);
+
+ spin_unlock_irq(&priv->driver_lock);
+
+ ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+ return ret;
+}
+
+static const struct net_device_ops mesh_netdev_ops = {
+ .ndo_open = lbs_mesh_dev_open,
+ .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,
+};
+
+/**
+ * lbs_add_mesh - add mshX interface
+ *
+ * @priv: A pointer to the &struct lbs_private structure
+ * returns: 0 if successful, -X otherwise
+ */
+static int lbs_add_mesh(struct lbs_private *priv)
+{
+ struct net_device *mesh_dev = NULL;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
+ /* Allocate a virtual mesh device */
+ mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+ if (!mesh_dev) {
+ lbs_deb_mesh("init mshX device failed\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+ mesh_dev->ml_priv = priv;
+ priv->mesh_dev = mesh_dev;
+
+ mesh_dev->netdev_ops = &mesh_netdev_ops;
+ mesh_dev->ethtool_ops = &lbs_ethtool_ops;
+ memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
+
+ SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
+
+ mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+ /* Register virtual mesh interface */
+ ret = register_netdev(mesh_dev);
+ if (ret) {
+ pr_err("cannot register mshX virtual interface\n");
+ goto err_free;
+ }
+
+ ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+ if (ret)
+ goto err_unregister;
+
+ lbs_persist_config_init(mesh_dev);
+
+ /* Everything successful */
+ ret = 0;
+ goto done;
+
+err_unregister:
+ unregister_netdev(mesh_dev);
+
+err_free:
+ free_netdev(mesh_dev);
+
+done:
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
+}
+
+void lbs_remove_mesh(struct lbs_private *priv)
+{
+ struct net_device *mesh_dev;
+
+ mesh_dev = priv->mesh_dev;
+ if (!mesh_dev)
+ return;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+ netif_stop_queue(mesh_dev);
+ netif_carrier_off(mesh_dev);
+ sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+ lbs_persist_config_remove(mesh_dev);
+ unregister_netdev(mesh_dev);
+ priv->mesh_dev = NULL;
+ free_netdev(mesh_dev);
+ lbs_deb_leave(LBS_DEB_MESH);
+}
+
+
+/***************************************************************************
+ * Sending and receiving
+ */
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+ struct net_device *dev, struct rxpd *rxpd)
+{
+ if (priv->mesh_dev) {
+ if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
+ if (rxpd->rx_control & RxPD_MESH_FRAME)
+ dev = priv->mesh_dev;
+ } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
+ if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
+ dev = priv->mesh_dev;
+ }
+ }
+ return dev;
+}
+
+
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+ struct net_device *dev, struct txpd *txpd)
+{
+ if (dev == priv->mesh_dev) {
+ if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
+ txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+ else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+ txpd->u.bss.bss_num = MESH_IFACE_ID;
+ }
+}
+
/***************************************************************************
* Ethtool related
*/
-static const char *mesh_stat_strings[] = {
+static const char * const mesh_stat_strings[] = {
"drop_duplicate_bcast",
"drop_ttl_zero",
"drop_no_fwd_route",
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index ee95c73ed5f4..50144913f2ab 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -31,7 +31,6 @@ struct lbs_private;
int lbs_init_mesh(struct lbs_private *priv);
int lbs_deinit_mesh(struct lbs_private *priv);
-int lbs_add_mesh(struct lbs_private *priv);
void lbs_remove_mesh(struct lbs_private *priv);
@@ -52,29 +51,6 @@ struct cmd_ds_command;
struct cmd_ds_mesh_access;
struct cmd_ds_mesh_config;
-int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1);
-int lbs_mesh_bt_reset(struct lbs_private *priv);
-int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted);
-int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted);
-int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1);
-
-int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
- struct cmd_ds_fwt_access *cmd);
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
- struct cmd_ds_mesh_access *cmd);
-int lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type);
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
-
-
-
-/* Persistent configuration */
-
-void lbs_persist_config_init(struct net_device *net);
-void lbs_persist_config_remove(struct net_device *net);
-
/* Ethtool statistics */
@@ -87,11 +63,6 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
uint32_t stringset, uint8_t *s);
-/* Accessors */
-
-#define lbs_mesh_open(priv) (priv->mesh_open)
-#define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED)
-
#else
#define lbs_init_mesh(priv)
@@ -101,8 +72,6 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
#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_open(priv) (0)
-#define lbs_mesh_connected(priv) (0)
#endif
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index fdb0448301a0..bfb8898ae518 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -5,6 +5,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <net/cfg80211.h>
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index bbb95f88dc01..a6e85134cfe1 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -1,6 +1,7 @@
/*
* This file contains the handling of TX in wlan driver.
*/
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
@@ -198,7 +199,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
- if (priv->mesh_dev && lbs_mesh_connected(priv))
+ if (priv->mesh_dev && netif_running(priv->mesh_dev))
netif_wake_queue(priv->mesh_dev);
}
EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
index 8945afd6ce3e..13557fe0bf95 100644
--- a/drivers/net/wireless/libertas_tf/cmd.c
+++ b/drivers/net/wireless/libertas_tf/cmd.c
@@ -9,6 +9,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include "libertas_tf.h"
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index d4005081f1df..acc461aa385e 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -9,6 +9,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
@@ -585,7 +586,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
need_padding ^= ieee80211_has_a4(hdr->frame_control);
need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
(*ieee80211_get_qos_ctl(hdr) &
- IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
+ IEEE80211_QOS_CTL_A_MSDU_PRESENT);
if (need_padding) {
memmove(skb->data + 2, skb->data, skb->len);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 9d4a40ee16c4..031cd89b1768 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1,6 +1,7 @@
/*
* mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2011, Javier Lopez <jlopex@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
@@ -25,11 +26,17 @@
#include <linux/rtnetlink.h>
#include <linux/etherdevice.h>
#include <linux/debugfs.h>
+#include <net/genetlink.h>
+#include "mac80211_hwsim.h"
+
+#define WARN_QUEUE 100
+#define MAX_QUEUE 200
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
MODULE_LICENSE("GPL");
+int wmediumd_pid;
static int radios = 2;
module_param(radios, int, 0444);
MODULE_PARM_DESC(radios, "Number of simulated radios");
@@ -302,6 +309,7 @@ struct mac80211_hwsim_data {
struct dentry *debugfs;
struct dentry *debugfs_ps;
+ struct sk_buff_head pending; /* packets pending */
/*
* Only radios in the same group can communicate together (the
* channel has to match too). Each bit represents a group. A
@@ -322,6 +330,32 @@ struct hwsim_radiotap_hdr {
__le16 rt_chbitmask;
} __packed;
+/* MAC80211_HWSIM netlinf family */
+static struct genl_family hwsim_genl_family = {
+ .id = GENL_ID_GENERATE,
+ .hdrsize = 0,
+ .name = "MAC80211_HWSIM",
+ .version = 1,
+ .maxattr = HWSIM_ATTR_MAX,
+};
+
+/* MAC80211_HWSIM netlink policy */
+
+static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
+ [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC,
+ .len = 6*sizeof(u8) },
+ [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC,
+ .len = 6*sizeof(u8) },
+ [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
+ [HWSIM_ATTR_FLAGS] = { .type = NLA_U32 },
+ [HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 },
+ [HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 },
+ [HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC,
+ .len = IEEE80211_TX_MAX_RATES*sizeof(
+ struct hwsim_tx_rate)},
+ [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 },
+};
static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
struct net_device *dev)
@@ -478,9 +512,89 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
return md.ret;
}
+static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
+ struct sk_buff *my_skb,
+ int dst_pid)
+{
+ struct sk_buff *skb;
+ struct mac80211_hwsim_data *data = hw->priv;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) my_skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(my_skb);
+ void *msg_head;
+ unsigned int hwsim_flags = 0;
+ int i;
+ struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
+
+ if (data->idle) {
+ wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
+ dev_kfree_skb(my_skb);
+ return;
+ }
+
+ if (data->ps != PS_DISABLED)
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+ /* If the queue contains MAX_QUEUE skb's drop some */
+ if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
+ /* Droping until WARN_QUEUE level */
+ while (skb_queue_len(&data->pending) >= WARN_QUEUE)
+ skb_dequeue(&data->pending);
+ }
+
+ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (skb == NULL)
+ goto nla_put_failure;
+
+ msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
+ HWSIM_CMD_FRAME);
+ if (msg_head == NULL) {
+ printk(KERN_DEBUG "mac80211_hwsim: problem with msg_head\n");
+ goto nla_put_failure;
+ }
+
+ NLA_PUT(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
+ sizeof(struct mac_address), data->addresses[1].addr);
-static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+ /* We get the skb->data */
+ NLA_PUT(skb, HWSIM_ATTR_FRAME, my_skb->len, my_skb->data);
+
+ /* We get the flags for this transmission, and we translate them to
+ wmediumd flags */
+
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
+ hwsim_flags |= HWSIM_TX_CTL_REQ_TX_STATUS;
+
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ hwsim_flags |= HWSIM_TX_CTL_NO_ACK;
+
+ NLA_PUT_U32(skb, HWSIM_ATTR_FLAGS, hwsim_flags);
+
+ /* We get the tx control (rate and retries) info*/
+
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ tx_attempts[i].idx = info->status.rates[i].idx;
+ tx_attempts[i].count = info->status.rates[i].count;
+ }
+
+ NLA_PUT(skb, HWSIM_ATTR_TX_INFO,
+ sizeof(struct hwsim_tx_rate)*IEEE80211_TX_MAX_RATES,
+ tx_attempts);
+
+ /* We create a cookie to identify this skb */
+ NLA_PUT_U64(skb, HWSIM_ATTR_COOKIE, (unsigned long) my_skb);
+
+ genlmsg_end(skb, msg_head);
+ genlmsg_unicast(&init_net, skb, dst_pid);
+
+ /* Enqueue the packet */
+ skb_queue_tail(&data->pending, my_skb);
+ return;
+
+nla_put_failure:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+}
+
+static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
{
struct mac80211_hwsim_data *data = hw->priv, *data2;
bool ack = false;
@@ -540,11 +654,11 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
return ack;
}
-
static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
bool ack;
struct ieee80211_tx_info *txi;
+ int _pid;
mac80211_hwsim_monitor_rx(hw, skb);
@@ -554,7 +668,15 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return;
}
- ack = mac80211_hwsim_tx_frame(hw, skb);
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+ /* NO wmediumd detected, perfect medium simulation */
+ ack = mac80211_hwsim_tx_frame_no_nl(hw, skb);
+
if (ack && skb->len >= 16) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
mac80211_hwsim_monitor_ack(hw, hdr->addr2);
@@ -635,6 +757,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
struct ieee80211_hw *hw = arg;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
+ int _pid;
hwsim_check_magic(vif);
@@ -649,7 +772,14 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
info = IEEE80211_SKB_CB(skb);
mac80211_hwsim_monitor_rx(hw, skb);
- mac80211_hwsim_tx_frame(hw, skb);
+
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+ mac80211_hwsim_tx_frame_no_nl(hw, skb);
dev_kfree_skb(skb);
}
@@ -966,12 +1096,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
{
- /*
- * In this special case, there's nothing we need to
- * do because hwsim does transmission synchronously.
- * In the future, when it does transmissions via
- * userspace, we may need to do something.
- */
+ /* Not implemented, queues only on kernel side */
}
struct hw_scan_done {
@@ -1005,6 +1130,8 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
for (i = 0; i < req->n_channels; i++)
printk(KERN_DEBUG "hwsim hw_scan freq %d\n",
req->channels[i]->center_freq);
+ print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET,
+ 16, 1, req->ie, req->ie_len, 1);
ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ);
@@ -1119,6 +1246,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_pspoll *pspoll;
+ int _pid;
if (!vp->assoc)
return;
@@ -1137,8 +1265,15 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
pspoll->aid = cpu_to_le16(0xc000 | vp->aid);
memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
memcpy(pspoll->ta, mac, ETH_ALEN);
- if (!mac80211_hwsim_tx_frame(data->hw, skb))
- printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__);
+
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
+
+ if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
+ printk(KERN_DEBUG "%s: PS-poll frame not ack'ed\n", __func__);
dev_kfree_skb(skb);
}
@@ -1149,6 +1284,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
+ int _pid;
if (!vp->assoc)
return;
@@ -1168,7 +1304,14 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
memcpy(hdr->addr1, vp->bssid, ETH_ALEN);
memcpy(hdr->addr2, mac, ETH_ALEN);
memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
- if (!mac80211_hwsim_tx_frame(data->hw, skb))
+
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
+
+ if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
dev_kfree_skb(skb);
}
@@ -1248,6 +1391,273 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group,
hwsim_fops_group_read, hwsim_fops_group_write,
"%llx\n");
+struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(
+ struct mac_address *addr)
+{
+ struct mac80211_hwsim_data *data;
+ bool _found = false;
+
+ spin_lock_bh(&hwsim_radio_lock);
+ list_for_each_entry(data, &hwsim_radios, list) {
+ if (memcmp(data->addresses[1].addr, addr,
+ sizeof(struct mac_address)) == 0) {
+ _found = true;
+ break;
+ }
+ }
+ spin_unlock_bh(&hwsim_radio_lock);
+
+ if (!_found)
+ return NULL;
+
+ return data;
+}
+
+static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
+ struct genl_info *info)
+{
+
+ struct ieee80211_hdr *hdr;
+ struct mac80211_hwsim_data *data2;
+ struct ieee80211_tx_info *txi;
+ struct hwsim_tx_rate *tx_attempts;
+ struct sk_buff __user *ret_skb;
+ struct sk_buff *skb, *tmp;
+ struct mac_address *src;
+ unsigned int hwsim_flags;
+
+ int i;
+ bool found = false;
+
+ if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
+ !info->attrs[HWSIM_ATTR_FLAGS] ||
+ !info->attrs[HWSIM_ATTR_COOKIE] ||
+ !info->attrs[HWSIM_ATTR_TX_INFO])
+ goto out;
+
+ src = (struct mac_address *)nla_data(
+ info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
+ hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]);
+
+ ret_skb = (struct sk_buff __user *)
+ (unsigned long) nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]);
+
+ data2 = get_hwsim_data_ref_from_addr(src);
+
+ if (data2 == NULL)
+ goto out;
+
+ /* look for the skb matching the cookie passed back from user */
+ skb_queue_walk_safe(&data2->pending, skb, tmp) {
+ if (skb == ret_skb) {
+ skb_unlink(skb, &data2->pending);
+ found = true;
+ break;
+ }
+ }
+
+ /* not found */
+ if (!found)
+ goto out;
+
+ /* Tx info received because the frame was broadcasted on user space,
+ so we get all the necessary info: tx attempts and skb control buff */
+
+ tx_attempts = (struct hwsim_tx_rate *)nla_data(
+ info->attrs[HWSIM_ATTR_TX_INFO]);
+
+ /* now send back TX status */
+ txi = IEEE80211_SKB_CB(skb);
+
+ if (txi->control.vif)
+ hwsim_check_magic(txi->control.vif);
+ if (txi->control.sta)
+ hwsim_check_sta_magic(txi->control.sta);
+
+ ieee80211_tx_info_clear_status(txi);
+
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ txi->status.rates[i].idx = tx_attempts[i].idx;
+ txi->status.rates[i].count = tx_attempts[i].count;
+ /*txi->status.rates[i].flags = 0;*/
+ }
+
+ txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
+
+ if (!(hwsim_flags & HWSIM_TX_CTL_NO_ACK) &&
+ (hwsim_flags & HWSIM_TX_STAT_ACK)) {
+ if (skb->len >= 16) {
+ hdr = (struct ieee80211_hdr *) skb->data;
+ mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2);
+ }
+ }
+ ieee80211_tx_status_irqsafe(data2->hw, skb);
+ return 0;
+out:
+ return -EINVAL;
+
+}
+
+static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
+ struct genl_info *info)
+{
+
+ struct mac80211_hwsim_data *data2;
+ struct ieee80211_rx_status rx_status;
+ struct mac_address *dst;
+ int frame_data_len;
+ char *frame_data;
+ struct sk_buff *skb = NULL;
+
+ if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
+ !info->attrs[HWSIM_ATTR_FRAME] ||
+ !info->attrs[HWSIM_ATTR_RX_RATE] ||
+ !info->attrs[HWSIM_ATTR_SIGNAL])
+ goto out;
+
+ dst = (struct mac_address *)nla_data(
+ info->attrs[HWSIM_ATTR_ADDR_RECEIVER]);
+
+ frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]);
+ frame_data = (char *)nla_data(info->attrs[HWSIM_ATTR_FRAME]);
+
+ /* Allocate new skb here */
+ skb = alloc_skb(frame_data_len, GFP_KERNEL);
+ if (skb == NULL)
+ goto err;
+
+ if (frame_data_len <= IEEE80211_MAX_DATA_LEN) {
+ /* Copy the data */
+ memcpy(skb_put(skb, frame_data_len), frame_data,
+ frame_data_len);
+ } else
+ goto err;
+
+ data2 = get_hwsim_data_ref_from_addr(dst);
+
+ if (data2 == NULL)
+ goto out;
+
+ /* check if radio is configured properly */
+
+ if (data2->idle || !data2->started || !data2->channel)
+ goto out;
+
+ /*A frame is received from user space*/
+ memset(&rx_status, 0, sizeof(rx_status));
+ rx_status.freq = data2->channel->center_freq;
+ rx_status.band = data2->channel->band;
+ rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
+ rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
+
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(data2->hw, skb);
+
+ return 0;
+err:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+ goto out;
+out:
+ dev_kfree_skb(skb);
+ return -EINVAL;
+}
+
+static int hwsim_register_received_nl(struct sk_buff *skb_2,
+ struct genl_info *info)
+{
+ if (info == NULL)
+ goto out;
+
+ wmediumd_pid = info->snd_pid;
+
+ printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, "
+ "switching to wmediumd mode with pid %d\n", info->snd_pid);
+
+ return 0;
+out:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+ return -EINVAL;
+}
+
+/* Generic Netlink operations array */
+static struct genl_ops hwsim_ops[] = {
+ {
+ .cmd = HWSIM_CMD_REGISTER,
+ .policy = hwsim_genl_policy,
+ .doit = hwsim_register_received_nl,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = HWSIM_CMD_FRAME,
+ .policy = hwsim_genl_policy,
+ .doit = hwsim_cloned_frame_received_nl,
+ },
+ {
+ .cmd = HWSIM_CMD_TX_INFO_FRAME,
+ .policy = hwsim_genl_policy,
+ .doit = hwsim_tx_info_frame_received_nl,
+ },
+};
+
+static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
+ unsigned long state,
+ void *_notify)
+{
+ struct netlink_notify *notify = _notify;
+
+ if (state != NETLINK_URELEASE)
+ return NOTIFY_DONE;
+
+ if (notify->pid == wmediumd_pid) {
+ printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink"
+ " socket, switching to perfect channel medium\n");
+ wmediumd_pid = 0;
+ }
+ return NOTIFY_DONE;
+
+}
+
+static struct notifier_block hwsim_netlink_notifier = {
+ .notifier_call = mac80211_hwsim_netlink_notify,
+};
+
+static int hwsim_init_netlink(void)
+{
+ int rc;
+ printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
+
+ wmediumd_pid = 0;
+
+ rc = genl_register_family_with_ops(&hwsim_genl_family,
+ hwsim_ops, ARRAY_SIZE(hwsim_ops));
+ if (rc)
+ goto failure;
+
+ rc = netlink_register_notifier(&hwsim_netlink_notifier);
+ if (rc)
+ goto failure;
+
+ return 0;
+
+failure:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+ return -EINVAL;
+}
+
+static void hwsim_exit_netlink(void)
+{
+ int ret;
+
+ printk(KERN_INFO "mac80211_hwsim: closing netlink\n");
+ /* unregister the notifier */
+ netlink_unregister_notifier(&hwsim_netlink_notifier);
+ /* unregister the family */
+ ret = genl_unregister_family(&hwsim_genl_family);
+ if (ret)
+ printk(KERN_DEBUG "mac80211_hwsim: "
+ "unregister family %i\n", ret);
+}
+
static int __init init_mac80211_hwsim(void)
{
int i, err = 0;
@@ -1298,6 +1708,7 @@ static int __init init_mac80211_hwsim(void)
goto failed_drvdata;
}
data->dev->driver = &mac80211_hwsim_driver;
+ skb_queue_head_init(&data->pending);
SET_IEEE80211_DEV(hw, data->dev);
addr[3] = i >> 8;
@@ -1379,6 +1790,10 @@ static int __init init_mac80211_hwsim(void)
data->group = 1;
mutex_init(&data->mutex);
+ /* Enable frame retransmissions for lossy channels */
+ hw->max_rates = 4;
+ hw->max_rate_tries = 11;
+
/* Work to be done prior to ieee80211_register_hw() */
switch (regtest) {
case HWSIM_REGTEST_DISABLED:
@@ -1515,12 +1930,29 @@ static int __init init_mac80211_hwsim(void)
if (hwsim_mon == NULL)
goto failed;
- err = register_netdev(hwsim_mon);
+ rtnl_lock();
+
+ err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
if (err < 0)
goto failed_mon;
+
+ err = register_netdevice(hwsim_mon);
+ if (err < 0)
+ goto failed_mon;
+
+ rtnl_unlock();
+
+ err = hwsim_init_netlink();
+ if (err < 0)
+ goto failed_nl;
+
return 0;
+failed_nl:
+ printk(KERN_DEBUG "mac_80211_hwsim: failed initializing netlink\n");
+ return err;
+
failed_mon:
rtnl_unlock();
free_netdev(hwsim_mon);
@@ -1541,6 +1973,8 @@ static void __exit exit_mac80211_hwsim(void)
{
printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
+ hwsim_exit_netlink();
+
mac80211_hwsim_free();
unregister_netdev(hwsim_mon);
}
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
new file mode 100644
index 000000000000..afaad5a443b6
--- /dev/null
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -0,0 +1,133 @@
+/*
+ * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2011, Javier Lopez <jlopex@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.
+ */
+
+#ifndef __MAC80211_HWSIM_H
+#define __MAC80211_HWSIM_H
+
+/**
+ * enum hwsim_tx_control_flags - flags to describe transmission info/status
+ *
+ * These flags are used to give the wmediumd extra information in order to
+ * modify its behavior for each frame
+ *
+ * @HWSIM_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame.
+ * @HWSIM_TX_CTL_NO_ACK: tell the wmediumd not to wait for an ack
+ * @HWSIM_TX_STAT_ACK: Frame was acknowledged
+ *
+ */
+enum hwsim_tx_control_flags {
+ HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0),
+ HWSIM_TX_CTL_NO_ACK = BIT(1),
+ HWSIM_TX_STAT_ACK = BIT(2),
+};
+
+/**
+ * DOC: Frame transmission/registration support
+ *
+ * Frame transmission and registration support exists to allow userspace
+ * entities such as wmediumd to receive and process all broadcasted
+ * frames from a mac80211_hwsim radio device.
+ *
+ * This allow user space applications to decide if the frame should be
+ * dropped or not and implement a wireless medium simulator at user space.
+ *
+ * Registration is done by sending a register message to the driver and
+ * will be automatically unregistered if the user application doesn't
+ * responds to sent frames.
+ * Once registered the user application has to take responsibility of
+ * broadcasting the frames to all listening mac80211_hwsim radio
+ * interfaces.
+ *
+ * For more technical details, see the corresponding command descriptions
+ * below.
+ */
+
+/**
+ * enum hwsim_commands - supported hwsim commands
+ *
+ * @HWSIM_CMD_UNSPEC: unspecified command to catch errors
+ *
+ * @HWSIM_CMD_REGISTER: request to register and received all broadcasted
+ * frames by any mac80211_hwsim radio device.
+ * @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user
+ * space, uses:
+ * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
+ * %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE,
+ * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
+ * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
+ * kernel, uses:
+ * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
+ * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
+ * @__HWSIM_CMD_MAX: enum limit
+ */
+enum {
+ HWSIM_CMD_UNSPEC,
+ HWSIM_CMD_REGISTER,
+ HWSIM_CMD_FRAME,
+ HWSIM_CMD_TX_INFO_FRAME,
+ __HWSIM_CMD_MAX,
+};
+#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
+
+/**
+ * enum hwsim_attrs - hwsim netlink attributes
+ *
+ * @HWSIM_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @HWSIM_ATTR_ADDR_RECEIVER: MAC address of the radio device that
+ * the frame is broadcasted to
+ * @HWSIM_ATTR_ADDR_TRANSMITTER: MAC address of the radio device that
+ * the frame was broadcasted from
+ * @HWSIM_ATTR_FRAME: Data array
+ * @HWSIM_ATTR_FLAGS: mac80211 transmission flags, used to process
+ properly the frame at user space
+ * @HWSIM_ATTR_RX_RATE: estimated rx rate index for this frame at user
+ space
+ * @HWSIM_ATTR_SIGNAL: estimated RX signal for this frame at user
+ space
+ * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
+ * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame
+ * @__HWSIM_ATTR_MAX: enum limit
+ */
+
+
+enum {
+ HWSIM_ATTR_UNSPEC,
+ HWSIM_ATTR_ADDR_RECEIVER,
+ HWSIM_ATTR_ADDR_TRANSMITTER,
+ HWSIM_ATTR_FRAME,
+ HWSIM_ATTR_FLAGS,
+ HWSIM_ATTR_RX_RATE,
+ HWSIM_ATTR_SIGNAL,
+ HWSIM_ATTR_TX_INFO,
+ HWSIM_ATTR_COOKIE,
+ __HWSIM_ATTR_MAX,
+};
+#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
+
+/**
+ * struct hwsim_tx_rate - rate selection/status
+ *
+ * @idx: rate index to attempt to send with
+ * @count: number of tries in this rate before going to the next rate
+ *
+ * A value of -1 for @idx indicates an invalid rate and, if used
+ * in an array of retry rates, that no more rates should be tried.
+ *
+ * When used for transmit status reporting, the driver should
+ * always report the rate and number of retries used.
+ *
+ */
+struct hwsim_tx_rate {
+ s8 idx;
+ u8 count;
+} __packed;
+
+#endif /* __MAC80211_HWSIM_H */
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 916183d39009..34bba5234294 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -185,13 +185,12 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
*
* Handling includes changing the header fields into CPU format.
*/
-int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
+int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
+ struct mwifiex_ds_11n_tx_cfg *tx_cfg)
{
- struct mwifiex_ds_11n_tx_cfg *tx_cfg;
struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
- if (data_buf) {
- tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf;
+ if (tx_cfg) {
tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap);
tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info);
}
@@ -208,11 +207,10 @@ int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
*/
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd, int cmd_action,
- void *data_buf)
+ u16 *buf_size)
{
struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;
u16 action = (u16) cmd_action;
- u16 buf_size = *((u16 *) data_buf);
cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
cmd->size =
@@ -220,8 +218,8 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
tx_buf->action = cpu_to_le16(action);
switch (action) {
case HostCmd_ACT_GEN_SET:
- dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size);
- tx_buf->buff_size = cpu_to_le16(buf_size);
+ dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size);
+ tx_buf->buff_size = cpu_to_le16(*buf_size);
break;
case HostCmd_ACT_GEN_GET:
default:
@@ -240,13 +238,12 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
* - Ensuring correct endian-ness
*/
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf)
+ int cmd_action,
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)
{
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
&cmd->params.amsdu_aggr_ctrl;
u16 action = (u16) cmd_action;
- struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
- (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl)
@@ -272,15 +269,13 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
* Handling includes changing the header fields into CPU format.
*/
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl
+ *amsdu_aggr_ctrl)
{
- struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl;
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
&resp->params.amsdu_aggr_ctrl;
- if (data_buf) {
- amsdu_aggr_ctrl =
- (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
+ if (amsdu_aggr_ctrl) {
amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable);
amsdu_aggr_ctrl->curr_buf_size =
le16_to_cpu(amsdu_ctrl->curr_buf_size);
@@ -296,12 +291,10 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
* - Setting HT Tx capability and HT Tx information fields
* - Ensuring correct endian-ness
*/
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+ struct mwifiex_ds_11n_tx_cfg *txcfg)
{
struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
- struct mwifiex_ds_11n_tx_cfg *txcfg =
- (struct mwifiex_ds_11n_tx_cfg *) data_buf;
cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN);
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index a4390a1a2a9f..90b421e343d4 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -29,9 +29,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
- void *data_buf);
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf);
+ struct mwifiex_ds_11n_tx_cfg *tx_cfg);
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+ struct mwifiex_ds_11n_tx_cfg *txcfg);
int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc,
@@ -62,12 +62,14 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
struct mwifiex_ds_tx_ba_stream_tbl *buf);
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
- void *data_buf);
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl
+ *amsdu_aggr_ctrl);
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf);
+ int cmd_action, u16 *buf_size);
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf);
+ int cmd_action,
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
/*
* This function checks whether AMPDU is allowed or not for a particular TID.
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index f807447e4d99..1a453a605b3f 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -164,12 +164,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
struct mwifiex_tx_param tx_param;
struct txpd *ptx_pd = NULL;
- if (skb_queue_empty(&pra_list->skb_head)) {
+ skb_src = skb_peek(&pra_list->skb_head);
+ if (!skb_src) {
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
return 0;
}
- skb_src = skb_peek(&pra_list->skb_head);
+
tx_info_src = MWIFIEX_SKB_TXCB(skb_src);
skb_aggr = dev_alloc_skb(adapter->tx_buf_size);
if (!skb_aggr) {
@@ -184,17 +185,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
tx_info_aggr->bss_index = tx_info_src->bss_index;
skb_aggr->priority = skb_src->priority;
- while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len
- + LLC_SNAP_LEN)
- <= adapter->tx_buf_size)) {
+ do {
+ /* Check if AMSDU can accommodate this MSDU */
+ if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
+ break;
- if (!skb_queue_empty(&pra_list->skb_head))
- skb_src = skb_dequeue(&pra_list->skb_head);
- else
- skb_src = NULL;
+ skb_src = skb_dequeue(&pra_list->skb_head);
- if (skb_src)
- pra_list->total_pkts_size -= skb_src->len;
+ pra_list->total_pkts_size -= skb_src->len;
+ pra_list->total_pkts--;
atomic_dec(&priv->wmm.tx_pkts_queued);
@@ -212,11 +211,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
return -1;
}
- if (!skb_queue_empty(&pra_list->skb_head))
- skb_src = skb_peek(&pra_list->skb_head);
- else
- skb_src = NULL;
- }
+ if (skb_tailroom(skb_aggr) < pad) {
+ pad = 0;
+ break;
+ }
+ skb_put(skb_aggr, pad);
+
+ skb_src = skb_peek(&pra_list->skb_head);
+
+ } while (skb_src);
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
@@ -230,11 +233,19 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
skb_push(skb_aggr, headroom);
- tx_param.next_pkt_len = ((pra_list->total_pkts_size) ?
- (((pra_list->total_pkts_size) >
- adapter->tx_buf_size) ? adapter->
- tx_buf_size : pra_list->total_pkts_size +
- LLC_SNAP_LEN + sizeof(struct txpd)) : 0);
+ /*
+ * Padding per MSDU will affect the length of next
+ * packet and hence the exact length of next packet
+ * is uncertain here.
+ *
+ * Also, aggregation of transmission buffer, while
+ * downloading the data to the card, wont gain much
+ * on the AMSDU packets as the AMSDU packets utilizes
+ * the transmission buffer space to the maximum
+ * (adapter->tx_buf_size).
+ */
+ 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);
@@ -258,6 +269,7 @@ 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_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index e5dfdc39a921..7aa9aa0ac958 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -328,13 +328,12 @@ int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
*/
int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ struct host_cmd_ds_11n_addba_req
+ *cmd_addba_req)
{
struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =
(struct host_cmd_ds_11n_addba_rsp *)
&cmd->params.add_ba_rsp;
- struct host_cmd_ds_11n_addba_req *cmd_addba_req =
- (struct host_cmd_ds_11n_addba_req *) data_buf;
u8 tid;
int win_size;
uint16_t block_ack_param_set;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index f3ca8c8c18f9..033c8adbdcd4 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -52,8 +52,9 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
void *data_buf);
int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
- struct host_cmd_ds_command
- *cmd, void *data_buf);
+ struct host_cmd_ds_command *cmd,
+ struct host_cmd_ds_11n_addba_req
+ *cmd_addba_req);
int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
void *data_buf);
void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 687c1f223497..352d2c5da1fc 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -672,6 +672,59 @@ static const u32 mwifiex_cipher_suites[] = {
};
/*
+ * CFG802.11 operation handler for setting bit rates.
+ *
+ * Function selects legacy bang B/G/BG from corresponding bitrates selection.
+ * Currently only 2.4GHz band is supported.
+ */
+static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct mwifiex_ds_band_cfg band_cfg;
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ int index = 0, mode = 0, i;
+
+ /* Currently only 2.4GHz is supported */
+ for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
+ /*
+ * Rates below 6 Mbps in the table are CCK rates; 802.11b
+ * and from 6 they are OFDM; 802.11G
+ */
+ if (mwifiex_rates[i].bitrate == 60) {
+ index = 1 << i;
+ break;
+ }
+ }
+
+ if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) {
+ mode = BAND_B;
+ } else {
+ mode = BAND_G;
+ if (mask->control[IEEE80211_BAND_2GHZ].legacy % index)
+ mode |= BAND_B;
+ }
+
+ memset(&band_cfg, 0, sizeof(band_cfg));
+ band_cfg.config_bands = mode;
+
+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
+ band_cfg.adhoc_start_band = mode;
+
+ band_cfg.sec_chan_offset = NO_SEC_CHANNEL;
+
+ if (mwifiex_set_radio_band_cfg(priv, &band_cfg))
+ return -EFAULT;
+
+ wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
+ (mode & BAND_B) ? "b" : "",
+ (mode & BAND_G) ? "g" : "");
+
+ return 0;
+}
+
+/*
* CFG802.11 operation handler for disconnection request.
*
* This function does not work when there is already a disconnection
@@ -960,7 +1013,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
if (sme->key) {
- if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) {
+ if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
dev_dbg(priv->adapter->dev,
"info: setting wep encryption"
" with key len %d\n", sme->key_len);
@@ -1225,6 +1278,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.set_default_key = mwifiex_cfg80211_set_default_key,
.set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
.set_tx_power = mwifiex_cfg80211_set_tx_power,
+ .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
};
/*
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index cd89fed206ae..b5352afb8714 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -104,13 +104,11 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
* main thread.
*/
static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_ds_misc_cmd *pcmd_ptr)
{
- struct mwifiex_ds_misc_cmd *pcmd_ptr =
- (struct mwifiex_ds_misc_cmd *) data_buf;
-
/* Copy the HOST command to command buffer */
- memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len);
+ memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len);
return 0;
}
@@ -707,15 +705,14 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
/* Copy original response back to response buffer */
- struct mwifiex_ds_misc_cmd *hostcmd = NULL;
+ struct mwifiex_ds_misc_cmd *hostcmd;
uint16_t size = le16_to_cpu(resp->size);
dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size);
size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
if (adapter->curr_cmd->data_buf) {
- hostcmd = (struct mwifiex_ds_misc_cmd *)
- adapter->curr_cmd->data_buf;
+ hostcmd = adapter->curr_cmd->data_buf;
hostcmd->len = size;
- memcpy(hostcmd->cmd, (void *) resp, size);
+ memcpy(hostcmd->cmd, resp, size);
}
}
orig_cmdresp_no = le16_to_cpu(resp->command);
@@ -1155,7 +1152,7 @@ EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);
int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, uint16_t ps_bitmap,
- void *data_buf)
+ struct mwifiex_ds_auto_ds *auto_ds)
{
struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
&cmd->params.psmode_enh;
@@ -1218,9 +1215,8 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
sizeof(struct mwifiex_ie_types_header));
cmd_size += sizeof(*auto_ds_tlv);
tlv += sizeof(*auto_ds_tlv);
- if (data_buf)
- idletime = ((struct mwifiex_ds_auto_ds *)
- data_buf)->idle_time;
+ if (auto_ds)
+ idletime = auto_ds->idle_time;
dev_dbg(priv->adapter->dev,
"cmd: PS Command: Enter Auto Deep Sleep\n");
auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
@@ -1239,7 +1235,7 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
*/
int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_pm_cfg *pm_cfg)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
@@ -1282,10 +1278,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap);
- if (data_buf) {
+ if (pm_cfg) {
/* This section is for get power save mode */
- struct mwifiex_ds_pm_cfg *pm_cfg =
- (struct mwifiex_ds_pm_cfg *)data_buf;
if (ps_bitmap & BITMAP_STA_PS)
pm_cfg->param.ps_mode = 1;
else
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index 46d65e02c7ba..d26a78b6b3c4 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -27,8 +27,8 @@ static struct dentry *mwifiex_dfs_dir;
static char *bss_modes[] = {
"Unknown",
- "Managed",
"Ad-hoc",
+ "Managed",
"Auto"
};
@@ -216,28 +216,19 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
p += sprintf(p, "media_state=\"%s\"\n",
(!priv->media_connected ? "Disconnected" : "Connected"));
- p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
- netdev->dev_addr[0], netdev->dev_addr[1],
- netdev->dev_addr[2], netdev->dev_addr[3],
- netdev->dev_addr[4], netdev->dev_addr[5]);
+ p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
p += sprintf(p, "multicast_count=\"%d\"\n",
netdev_mc_count(netdev));
p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
- p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
- info.bssid[0], info.bssid[1],
- info.bssid[2], info.bssid[3],
- info.bssid[4], info.bssid[5]);
+ p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
p += sprintf(p, "region_code = \"%02x\"\n", info.region_code);
netdev_for_each_mc_addr(ha, netdev)
- p += sprintf(p, "multicast_address[%d]="
- "\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++,
- ha->addr[0], ha->addr[1],
- ha->addr[2], ha->addr[3],
- ha->addr[4], ha->addr[5]);
+ p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
+ i++, ha->addr);
}
p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
@@ -451,26 +442,18 @@ mwifiex_debug_read(struct file *file, char __user *ubuf,
if (info.tx_tbl_num) {
p += sprintf(p, "Tx BA stream table:\n");
for (i = 0; i < info.tx_tbl_num; i++)
- p += sprintf(p, "tid = %d, "
- "ra = %02x:%02x:%02x:%02x:%02x:%02x\n",
- info.tx_tbl[i].tid, info.tx_tbl[i].ra[0],
- info.tx_tbl[i].ra[1], info.tx_tbl[i].ra[2],
- info.tx_tbl[i].ra[3], info.tx_tbl[i].ra[4],
- info.tx_tbl[i].ra[5]);
+ p += sprintf(p, "tid = %d, ra = %pM\n",
+ info.tx_tbl[i].tid, info.tx_tbl[i].ra);
}
if (info.rx_tbl_num) {
p += sprintf(p, "Rx reorder table:\n");
for (i = 0; i < info.rx_tbl_num; i++) {
-
- p += sprintf(p, "tid = %d, "
- "ta = %02x:%02x:%02x:%02x:%02x:%02x, "
+ p += sprintf(p, "tid = %d, ta = %pM, "
"start_win = %d, "
"win_size = %d, buffer: ",
info.rx_tbl[i].tid,
- info.rx_tbl[i].ta[0], info.rx_tbl[i].ta[1],
- info.rx_tbl[i].ta[2], info.rx_tbl[i].ta[3],
- info.rx_tbl[i].ta[4], info.rx_tbl[i].ta[5],
+ info.rx_tbl[i].ta,
info.rx_tbl[i].start_win,
info.rx_tbl[i].win_size);
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 0e90b0986ed8..94ddc9038cb3 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -30,7 +30,9 @@
#define MWIFIEX_MAX_BSS_NUM (1)
-#define MWIFIEX_MIN_DATA_HEADER_LEN 32 /* (sizeof(mwifiex_txpd)) */
+#define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd)
+ * + 4 byte alignment
+ */
#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2
#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index afdd145dff0b..4fee0993b186 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -157,6 +157,17 @@ enum MWIFIEX_802_11_WEP_STATUS {
#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26))
#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
+/* httxcfg bitmap
+ * 0 reserved
+ * 1 20/40 Mhz enable(1)/disable(0)
+ * 2-3 reserved
+ * 4 green field enable(1)/disable(0)
+ * 5 short GI in 20 Mhz enable(1)/disable(0)
+ * 6 short GI in 40 Mhz enable(1)/disable(0)
+ * 7-15 reserved
+ */
+#define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6))
+
#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
#define SETHT_MCS32(x) (x[4] |= 1)
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index 7c1c5ee40eb9..f6bcc868562f 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -249,6 +249,7 @@ struct mwifiex_ds_hs_cfg {
};
#define DEEP_SLEEP_ON 1
+#define DEEP_SLEEP_OFF 0
#define DEEP_SLEEP_IDLE_TIME 100
#define PS_MODE_AUTO 1
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 5eab3dc29b1c..644e2e405cb5 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -364,10 +364,9 @@ static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,
*/
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ struct mwifiex_bssdescriptor *bss_desc)
{
struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
- struct mwifiex_bssdescriptor *bss_desc;
struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
struct mwifiex_ie_types_phy_param_set *phy_tlv;
struct mwifiex_ie_types_ss_param_set *ss_tlv;
@@ -380,7 +379,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
u8 *pos;
int rsn_ie_len = 0;
- bss_desc = (struct mwifiex_bssdescriptor *) data_buf;
pos = (u8 *) assoc;
mwifiex_cfg_tx_buf(priv, bss_desc);
@@ -748,7 +746,8 @@ done:
*/
int
mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_802_11_ssid *req_ssid)
{
int rsn_ie_len = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -786,20 +785,15 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
- memcpy(adhoc_start->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+ memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",
adhoc_start->ssid);
memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
- memcpy(bss_desc->ssid.ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+ memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
- bss_desc->ssid.ssid_len =
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len;
+ bss_desc->ssid.ssid_len = req_ssid->ssid_len;
/* Set the BSS mode */
adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
@@ -1036,13 +1030,12 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
*/
int
mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_bssdescriptor *bss_desc)
{
int rsn_ie_len = 0;
struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
&cmd->params.adhoc_join;
- struct mwifiex_bssdescriptor *bss_desc =
- (struct mwifiex_bssdescriptor *) data_buf;
struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
u32 cmd_append_size = 0;
u16 tmp_cap;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index f0582259c935..e5fc53dc6887 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -26,17 +26,12 @@
const char driver_version[] = "mwifiex " VERSION " (%s) ";
-struct mwifiex_adapter *g_adapter;
-EXPORT_SYMBOL_GPL(g_adapter);
-
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;
-static char fw_name[32] = DEFAULT_FW_NAME;
-
/* Supported drv_mode table */
static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
{
@@ -62,7 +57,8 @@ 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)
+ struct mwifiex_drv_mode *drv_mode_ptr,
+ void **padapter)
{
struct mwifiex_adapter *adapter;
int i;
@@ -71,7 +67,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
if (!adapter)
return -ENOMEM;
- g_adapter = adapter;
+ *padapter = adapter;
adapter->card = card;
/* Save interface specific operations in adapter */
@@ -326,7 +322,7 @@ exit_main_proc:
* and initializing the private structures.
*/
static int
-mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
+mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter)
{
int i;
struct mwifiex_drv_mode *drv_mode_ptr;
@@ -345,7 +341,7 @@ mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
return -1;
}
- if (mwifiex_register(card, if_ops, drv_mode_ptr))
+ if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter))
return -1;
return 0;
@@ -384,20 +380,8 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
memset(&fw, 0, sizeof(struct mwifiex_fw_image));
- switch (adapter->revision_id) {
- case SD8787_W0:
- case SD8787_W1:
- strcpy(fw_name, SD8787_W1_FW_NAME);
- break;
- case SD8787_A0:
- case SD8787_A1:
- strcpy(fw_name, SD8787_AX_FW_NAME);
- break;
- default:
- break;
- }
-
- err = request_firmware(&adapter->firmware, fw_name, adapter->dev);
+ err = request_firmware(&adapter->firmware, adapter->fw_name,
+ adapter->dev);
if (err < 0) {
dev_err(adapter->dev, "request_firmware() returned"
" error code %#x\n", err);
@@ -569,7 +553,7 @@ static int
mwifiex_set_mac_address(struct net_device *dev, void *addr)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- struct sockaddr *hw_addr = (struct sockaddr *) addr;
+ struct sockaddr *hw_addr = addr;
int ret;
memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
@@ -869,13 +853,11 @@ mwifiex_add_card(void *card, struct semaphore *sem,
if (down_interruptible(sem))
goto exit_sem_err;
- if (mwifiex_init_sw(card, if_ops)) {
+ if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) {
pr_err("%s: software init failed\n", __func__);
goto err_init_sw;
}
- adapter = g_adapter;
-
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
adapter->surprise_removed = false;
init_waitqueue_head(&adapter->init_wait_q);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 8316b3cd92cd..2215c3c97354 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -39,7 +39,6 @@
#include "fw.h"
extern const char driver_version[];
-extern struct mwifiex_adapter *g_adapter;
enum {
MWIFIEX_ASYNC_CMD,
@@ -48,15 +47,6 @@ enum {
#define DRV_MODE_STA 0x1
-#define SD8787_W0 0x30
-#define SD8787_W1 0x31
-#define SD8787_A0 0x40
-#define SD8787_A1 0x41
-
-#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
-#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin"
-#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin"
-
struct mwifiex_drv_mode {
u16 drv_mode;
u16 intf_num;
@@ -190,6 +180,7 @@ 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;
};
@@ -576,10 +567,10 @@ struct mwifiex_adapter {
u8 priv_num;
struct mwifiex_drv_mode *drv_mode;
const struct firmware *firmware;
+ char fw_name[32];
struct device *dev;
bool surprise_removed;
u32 fw_release_number;
- u32 revision_id;
u16 init_wait_q_woken;
wait_queue_head_t init_wait_q;
void *card;
@@ -745,10 +736,10 @@ void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *,
int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, uint16_t ps_bitmap,
- void *data_buf);
+ struct mwifiex_ds_auto_ds *auto_ds);
int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf);
+ struct mwifiex_ds_pm_cfg *pm_cfg);
void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
void mwifiex_hs_activated_event(struct mwifiex_private *priv,
u8 activated);
@@ -760,7 +751,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
u16 cmd_action, u32 cmd_oid,
void *data_buf, void *cmd_buf);
int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
- void *cmd_buf);
+ struct host_cmd_ds_command *resp);
int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
struct sk_buff *skb);
int mwifiex_process_sta_event(struct mwifiex_private *);
@@ -769,7 +760,7 @@ 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,
- void *data_buf);
+ 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,
@@ -786,8 +777,8 @@ s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
int mwifiex_associate(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
- struct host_cmd_ds_command
- *cmd, void *data_buf);
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_bssdescriptor *bss_desc);
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);
@@ -800,10 +791,10 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
@@ -938,6 +929,7 @@ int mwifiex_set_hs_params(struct mwifiex_private *priv,
struct mwifiex_ds_hs_cfg *hscfg);
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);
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,
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 5c22860fb40a..6f88c8ab5de5 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -2357,12 +2357,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
* - Setting command ID, and proper size
* - Ensuring correct endian-ness
*/
-int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
+ struct mwifiex_scan_cmd_config *scan_cfg)
{
struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
- struct mwifiex_scan_cmd_config *scan_cfg;
-
- scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;
/* Set fixed field variables in scan command */
scan_cmd->bss_mode = scan_cfg->bss_mode;
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index d425dbd91d19..82098ac483b8 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -31,10 +31,27 @@
#define SDIO_VERSION "1.0"
+/* The mwifiex_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
+ * differently.
+ * If the user is removing the module, the few commands (FUNC_SHUTDOWN,
+ * HS_CANCEL etc.) are sent to the firmware.
+ * If the card is removed, there is no need to send these command.
+ *
+ * The variable 'user_rmmod' is used to distinguish these two
+ * scenarios. This flag is initialized as FALSE in case the card
+ * is removed, and will be set to TRUE for module removal when
+ * module_exit function is called.
+ */
+static u8 user_rmmod;
+
static struct mwifiex_if_ops sdio_ops;
static struct semaphore add_remove_card_sem;
+static int mwifiex_sdio_resume(struct device *dev);
+
/*
* SDIO probe.
*
@@ -93,17 +110,39 @@ static void
mwifiex_sdio_remove(struct sdio_func *func)
{
struct sdio_mmc_card *card;
+ struct mwifiex_adapter *adapter;
+ int i;
pr_debug("info: SDIO func num=%d\n", func->num);
- if (func) {
- card = sdio_get_drvdata(func);
- if (card) {
- mwifiex_remove_card(card->adapter,
- &add_remove_card_sem);
- kfree(card);
- }
+ card = sdio_get_drvdata(func);
+ if (!card)
+ return;
+
+ adapter = card->adapter;
+ if (!adapter || !adapter->priv_num)
+ return;
+
+ if (user_rmmod) {
+ if (adapter->is_suspended)
+ mwifiex_sdio_resume(adapter->dev);
+
+ 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);
}
/*
@@ -1283,7 +1322,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
if (!(card->mp_wr_bitmap &
(1 << card->curr_wr_port))
|| !MP_TX_AGGR_BUF_HAS_ROOM(
- card, next_pkt_len))
+ card, pkt_len + next_pkt_len))
f_send_aggr_buf = 1;
} else {
/* No room in Aggr buf, send it */
@@ -1531,6 +1570,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
sdio_set_drvdata(func, card);
adapter->dev = &func->dev;
+ strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
return 0;
@@ -1552,7 +1592,6 @@ disable_func:
* the first interrupt got from bootloader
* - Disable host interrupt mask register
* - Get SDIO port
- * - Get revision ID
* - Initialize SDIO variables in card
* - Allocate MP registers
* - Allocate MPA Tx and Rx buffers
@@ -1576,10 +1615,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
/* Get SDIO ioport */
mwifiex_init_sdio_ioport(adapter);
- /* Get revision ID */
-#define REV_ID_REG 0x5c
- mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id);
-
/* Initialize SDIO variables in card */
card->mp_rd_bitmap = 0;
card->mp_wr_bitmap = 0;
@@ -1700,6 +1735,9 @@ mwifiex_sdio_init_module(void)
{
sema_init(&add_remove_card_sem, 1);
+ /* Clear the flag in case user removes the card. */
+ user_rmmod = 0;
+
return sdio_register_driver(&mwifiex_sdio);
}
@@ -1715,32 +1753,12 @@ mwifiex_sdio_init_module(void)
static void
mwifiex_sdio_cleanup_module(void)
{
- struct mwifiex_adapter *adapter = g_adapter;
- int i;
-
- if (down_interruptible(&add_remove_card_sem))
- goto exit_sem_err;
-
- if (!adapter || !adapter->priv_num)
- goto exit;
-
- if (adapter->is_suspended)
- mwifiex_sdio_resume(adapter->dev);
-
- 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);
-
- if (!adapter->surprise_removed)
- mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
- MWIFIEX_BSS_ROLE_ANY),
- MWIFIEX_FUNC_SHUTDOWN);
+ if (!down_interruptible(&add_remove_card_sem))
+ up(&add_remove_card_sem);
-exit:
- up(&add_remove_card_sem);
+ /* Set the flag as user is removing this module. */
+ user_rmmod = 1;
-exit_sem_err:
sdio_unregister_driver(&mwifiex_sdio);
}
@@ -1751,4 +1769,4 @@ MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
MODULE_VERSION(SDIO_VERSION);
MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE("sd8787.bin");
+MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 4e97e90aa399..524f78f4ee69 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -28,6 +28,8 @@
#include "main.h"
+#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
+
#define BLOCK_MODE 1
#define BYTE_MODE 0
@@ -52,10 +54,10 @@
#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8
-#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (4096) /* 4K */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (8192) /* 8K */
/* Multi port RX aggregation buffer size */
-#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (4096) /* 4K */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (16384) /* 16K */
/* Misc. Config Register : Auto Re-enable interrupts */
#define AUTO_RE_ENABLE_INT BIT(4)
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 8af3a78d2723..c54ee287b878 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -67,10 +67,9 @@ mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv,
*/
static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *action)
{
struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
- u16 action = *((u16 *) data_buf);
if (cmd_action != HostCmd_ACT_GEN_SET) {
dev_err(priv->adapter->dev,
@@ -81,7 +80,7 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
cmd->size =
cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
- mac_ctrl->action = cpu_to_le16(action);
+ mac_ctrl->action = cpu_to_le16(*action);
return 0;
}
@@ -104,10 +103,9 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, u32 cmd_oid,
- void *data_buf)
+ u32 *ul_temp)
{
struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
- u32 ul_temp;
dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
@@ -127,9 +125,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *((u32 *) data_buf);
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -139,9 +136,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *((u32 *) data_buf);
*(__le16 *) (snmp_mib->value) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -152,9 +148,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = (*(u32 *) data_buf);
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -164,9 +159,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *(u32 *) data_buf;
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -209,13 +203,11 @@ mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)
*/
static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *pbitmap_rates)
{
struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
struct mwifiex_rate_scope *rate_scope;
struct mwifiex_rate_drop_pattern *rate_drop;
- u16 *pbitmap_rates = (u16 *) data_buf;
-
u32 i;
cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
@@ -272,10 +264,10 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
* - Ensuring correct endian-ness
*/
static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action,
+ struct host_cmd_ds_txpwr_cfg *txp)
{
struct mwifiex_types_power_group *pg_tlv;
- struct host_cmd_ds_txpwr_cfg *txp;
struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
@@ -283,12 +275,11 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
- txp = (struct host_cmd_ds_txpwr_cfg *) data_buf;
if (txp->mode) {
pg_tlv = (struct mwifiex_types_power_group
- *) ((unsigned long) data_buf +
+ *) ((unsigned long) txp +
sizeof(struct host_cmd_ds_txpwr_cfg));
- memmove(cmd_txp_cfg, data_buf,
+ memmove(cmd_txp_cfg, txp,
sizeof(struct host_cmd_ds_txpwr_cfg) +
sizeof(struct mwifiex_types_power_group) +
pg_tlv->length);
@@ -300,8 +291,7 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
sizeof(struct mwifiex_types_power_group) +
pg_tlv->length);
} else {
- memmove(cmd_txp_cfg, data_buf,
- sizeof(struct host_cmd_ds_txpwr_cfg));
+ memmove(cmd_txp_cfg, txp, sizeof(*txp));
}
cmd_txp_cfg->action = cpu_to_le16(cmd_action);
break;
@@ -322,22 +312,23 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
* (as required)
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd,
- u16 cmd_action,
- struct mwifiex_hs_config_param *data_buf)
+static int
+mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action,
+ struct mwifiex_hs_config_param *hscfg_param)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
u16 hs_activate = false;
- if (data_buf == NULL)
+ if (!hscfg_param)
/* New Activate command */
hs_activate = true;
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
if (!hs_activate &&
- (data_buf->conditions
+ (hscfg_param->conditions
!= cpu_to_le32(HOST_SLEEP_CFG_CANCEL))
&& ((adapter->arp_filter_size > 0)
&& (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
@@ -359,9 +350,9 @@ static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;
} else {
hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
- hs_cfg->params.hs_config.conditions = data_buf->conditions;
- hs_cfg->params.hs_config.gpio = data_buf->gpio;
- hs_cfg->params.hs_config.gap = data_buf->gap;
+ hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
+ hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
+ hs_cfg->params.hs_config.gap = hscfg_param->gap;
dev_dbg(adapter->dev,
"cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
hs_cfg->params.hs_config.conditions,
@@ -405,11 +396,11 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,
* - Setting MAC multicast address
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+static int
+mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
+ u16 cmd_action,
+ struct mwifiex_multicast_list *mcast_list)
{
- struct mwifiex_multicast_list *mcast_list =
- (struct mwifiex_multicast_list *) data_buf;
struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
@@ -435,7 +426,7 @@ static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
*/
static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ u8 *mac)
{
struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
@@ -444,7 +435,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
+ S_DS_GEN);
/* Set AP MAC address */
- memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN);
+ memcpy(deauth->mac_addr, mac, ETH_ALEN);
dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr);
@@ -543,15 +534,14 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
* encryption (TKIP, AES) (as required)
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd,
- u16 cmd_action,
- u32 cmd_oid, void *data_buf)
+static int
+mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action, u32 cmd_oid,
+ struct mwifiex_ds_encrypt_key *enc_key)
{
struct host_cmd_ds_802_11_key_material *key_material =
&cmd->params.key_material;
- struct mwifiex_ds_encrypt_key *enc_key =
- (struct mwifiex_ds_encrypt_key *) data_buf;
u16 key_param_len = 0;
int ret = 0;
const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -741,7 +731,7 @@ static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
*/
static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *channel)
{
struct host_cmd_ds_802_11_rf_channel *rf_chan =
&cmd->params.rf_channel;
@@ -759,7 +749,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
rf_type = le16_to_cpu(rf_chan->rf_type);
SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset);
- rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf));
+ rf_chan->current_channel = cpu_to_le16(*channel);
}
rf_chan->action = cpu_to_le16(cmd_action);
return 0;
@@ -774,11 +764,10 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
* - Ensuring correct endian-ness
*/
static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *enable)
{
struct host_cmd_ds_802_11_ibss_status *ibss_coal =
&(cmd->params.ibss_coalescing);
- u16 enable = 0;
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) +
@@ -788,9 +777,10 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
- if (data_buf != NULL)
- enable = *(u16 *) data_buf;
- ibss_coal->enable = cpu_to_le16(enable);
+ if (enable)
+ ibss_coal->enable = cpu_to_le16(*enable);
+ else
+ ibss_coal->enable = 0;
break;
/* In other case.. Nothing to do */
@@ -822,9 +812,8 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
u16 cmd_action, void *data_buf)
{
- struct mwifiex_ds_reg_rw *reg_rw;
+ struct mwifiex_ds_reg_rw *reg_rw = data_buf;
- reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
switch (le16_to_cpu(cmd->command)) {
case HostCmd_CMD_MAC_REG_ACCESS:
{
@@ -893,8 +882,7 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
}
case HostCmd_CMD_802_11_EEPROM_ACCESS:
{
- struct mwifiex_ds_read_eeprom *rd_eeprom =
- (struct mwifiex_ds_read_eeprom *) data_buf;
+ struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;
struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
(struct host_cmd_ds_802_11_eeprom_access *)
&cmd->params.eeprom;
@@ -923,8 +911,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
u16 cmd_action, u32 cmd_oid,
void *data_buf, void *cmd_buf)
{
- struct host_cmd_ds_command *cmd_ptr =
- (struct host_cmd_ds_command *) cmd_buf;
+ struct host_cmd_ds_command *cmd_ptr = cmd_buf;
int ret = 0;
/* Prepare command */
@@ -1126,6 +1113,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
struct mwifiex_ds_auto_ds auto_ds;
enum state_11d_t state_11d;
+ struct mwifiex_ds_11n_tx_cfg tx_cfg;
if (first_sta) {
@@ -1181,7 +1169,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
/* Send request to firmware */
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
HostCmd_ACT_GEN_SET, 0,
- (void *) &amsdu_aggr_ctrl);
+ &amsdu_aggr_ctrl);
if (ret)
return -1;
/* MAC Control must be the last command in init_fw */
@@ -1211,8 +1199,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
if (ret)
dev_err(priv->adapter->dev, "11D: failed to enable 11D\n");
+ /* Send cmd to FW to configure 11n specific configuration
+ * (Short GI, Channel BW, Green field support etc.) for transmit
+ */
+ tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG;
+ ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_CFG,
+ HostCmd_ACT_GEN_SET, 0, &tx_cfg);
+
/* set last_init_cmd */
- priv->adapter->last_init_cmd = HostCmd_CMD_802_11_SNMP_MIB;
+ priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG;
ret = -EINPROGRESS;
return ret;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index d08f76429a0a..6804239d87bd 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -120,11 +120,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
*/
static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_get_signal *signal)
{
struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
&resp->params.rssi_info_rsp;
- struct mwifiex_ds_get_signal *signal;
priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
@@ -139,9 +138,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
/* Need to indicate IOCTL complete */
- if (data_buf) {
- signal = (struct mwifiex_ds_get_signal *) data_buf;
- memset(signal, 0, sizeof(struct mwifiex_ds_get_signal));
+ if (signal) {
+ memset(signal, 0, sizeof(*signal));
signal->selector = ALL_RSSI_INFO_MASK;
@@ -185,7 +183,7 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
*/
static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ u32 *data_buf)
{
struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
u16 oid = le16_to_cpu(smib->oid);
@@ -198,7 +196,7 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
if (query_type == HostCmd_ACT_GEN_GET) {
ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
if (data_buf)
- *(u32 *)data_buf = ul_temp;
+ *data_buf = ul_temp;
switch (oid) {
case FRAG_THRESH_I:
dev_dbg(priv->adapter->dev,
@@ -228,14 +226,12 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
*/
static int mwifiex_ret_get_log(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_get_stats *stats)
{
struct host_cmd_ds_802_11_get_log *get_log =
(struct host_cmd_ds_802_11_get_log *) &resp->params.get_log;
- struct mwifiex_ds_get_stats *stats;
- if (data_buf) {
- stats = (struct mwifiex_ds_get_stats *) data_buf;
+ if (stats) {
stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
stats->failed = le32_to_cpu(get_log->failed);
stats->retry = le32_to_cpu(get_log->retry);
@@ -278,9 +274,8 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv,
*/
static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_rate_cfg *ds_rate)
{
- struct mwifiex_rate_cfg *ds_rate;
struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
struct mwifiex_rate_scope *rate_scope;
struct mwifiex_ie_types_header *head;
@@ -329,8 +324,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
- if (data_buf) {
- ds_rate = (struct mwifiex_rate_cfg *) data_buf;
+ if (ds_rate) {
if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
if (priv->is_data_rate_auto) {
ds_rate->is_rate_auto = 1;
@@ -413,8 +407,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
* and saving the current Tx power level in driver.
*/
static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
- struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct host_cmd_ds_command *resp)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
@@ -631,7 +624,7 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
*/
static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ u16 *data_buf)
{
struct host_cmd_ds_802_11_rf_channel *rf_channel =
&resp->params.rf_channel;
@@ -644,8 +637,9 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
/* Update the channel again */
priv->curr_bss_params.bss_descriptor.channel = new_channel;
}
+
if (data_buf)
- *((u16 *)data_buf) = new_channel;
+ *data_buf = new_channel;
return 0;
}
@@ -658,13 +652,11 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
*/
static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct host_cmd_ds_version_ext *version_ext)
{
struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
- struct host_cmd_ds_version_ext *version_ext;
- if (data_buf) {
- version_ext = (struct host_cmd_ds_version_ext *)data_buf;
+ if (version_ext) {
version_ext->version_str_sel = ver_ext->version_str_sel;
memcpy(version_ext->version_str, ver_ext->version_str,
sizeof(char) * 128);
@@ -686,8 +678,8 @@ static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
struct mwifiex_ds_read_eeprom *eeprom;
if (data_buf) {
- reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
- eeprom = (struct mwifiex_ds_read_eeprom *) data_buf;
+ reg_rw = data_buf;
+ eeprom = data_buf;
switch (type) {
case HostCmd_CMD_MAC_REG_ACCESS:
{
@@ -825,13 +817,11 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
* This is a generic function, which calls command specific
* response handlers based on the command ID.
*/
-int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
- u16 cmdresp_no, void *cmd_buf)
+int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
+ struct host_cmd_ds_command *resp)
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
- struct host_cmd_ds_command *resp =
- (struct host_cmd_ds_command *) cmd_buf;
void *data_buf = adapter->curr_cmd->data_buf;
/* If the command is not successful, cleanup and return failure */
@@ -865,7 +855,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
"info: CMD_RESP: BG_SCAN result is ready!\n");
break;
case HostCmd_CMD_TXPWR_CFG:
- ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf);
+ ret = mwifiex_ret_tx_power_cfg(priv, resp);
break;
case HostCmd_CMD_802_11_PS_MODE_ENH:
ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index d05907d05039..c34ff8c4f4f8 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -487,6 +487,20 @@ int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv,
}
/*
+ * The function disables auto deep sleep mode.
+ */
+int mwifiex_disable_auto_ds(struct mwifiex_private *priv)
+{
+ struct mwifiex_ds_auto_ds auto_ds;
+
+ auto_ds.auto_ds = DEEP_SLEEP_OFF;
+
+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds);
+}
+EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds);
+
+/*
* IOCTL request handler to set/get active channel.
*
* This function performs validity checking on channel/frequency
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 1fdddece7479..27430512f7cd 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -187,7 +187,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
local_rx_pd->priority, ta,
(u8) local_rx_pd->rx_pkt_type,
- (void *) skb);
+ skb);
if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
if (priv && (ret == -1))
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index fa6221bc9104..1822bfad8896 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -47,6 +47,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter;
struct txpd *local_tx_pd;
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+ u8 pad;
if (!skb->len) {
dev_err(adapter->dev, "Tx: bad packet length: %d\n",
@@ -55,15 +56,19 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
return skb->data;
}
- BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN));
- skb_push(skb, sizeof(*local_tx_pd));
+ /* If skb->data is not aligned; add padding */
+ pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4;
+
+ BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN
+ + pad));
+ skb_push(skb, sizeof(*local_tx_pd) + pad);
local_tx_pd = (struct txpd *) skb->data;
memset(local_tx_pd, 0, sizeof(struct txpd));
local_tx_pd->bss_num = priv->bss_num;
local_tx_pd->bss_type = priv->bss_type;
local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len -
- sizeof(struct txpd)));
+ (sizeof(struct txpd) + pad)));
local_tx_pd->priority = (u8) skb->priority;
local_tx_pd->pkt_delay_2ms =
@@ -88,7 +93,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
}
/* Offset of actual data */
- local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
+ local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + pad);
/* make space for INTF_HEADER_LEN */
skb_push(skb, INTF_HEADER_LEN);
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index aaa50c074196..6190b2fa57a3 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -71,7 +71,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
u8 *head_ptr;
struct txpd *local_tx_pd = NULL;
- head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb);
+ head_ptr = mwifiex_process_sta_txpd(priv, skb);
if (head_ptr) {
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
local_tx_pd =
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 91634daec306..69e260b41711 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -121,6 +121,7 @@ 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);
@@ -633,6 +634,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter,
ra_list = NULL;
} else {
memcpy(ra, skb->data, ETH_ALEN);
+ if (ra[0] & 0x01)
+ memset(ra, 0xff, ETH_ALEN);
ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra);
}
@@ -645,6 +648,7 @@ 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);
@@ -971,28 +975,6 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
}
/*
- * This function gets the number of packets in the Tx queue of a
- * particular RA list.
- */
-static int
-mwifiex_num_pkts_in_txq(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)
- ++count;
- else
- break;
- }
-
- return count;
-}
-
-/*
* This function sends a single packet to firmware for transmission.
*/
static void
@@ -1019,6 +1001,7 @@ 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);
@@ -1044,6 +1027,7 @@ 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);
@@ -1231,9 +1215,9 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
}
/* Minimum number of AMSDU */
#define MIN_NUM_AMSDU 2
+
if (mwifiex_is_amsdu_allowed(priv, tid) &&
- (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >=
- MIN_NUM_AMSDU))
+ (ptr->total_pkts >= MIN_NUM_AMSDU))
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 aeac3cc4dbe4..da36dbf8d871 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -10,6 +10,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -1891,9 +1892,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
txpriority = index;
- if (ieee80211_is_data_qos(wh->frame_control) &&
- skb->protocol != cpu_to_be16(ETH_P_PAE) &&
- sta->ht_cap.ht_supported && priv->ap_fw) {
+ if (priv->ap_fw && sta && sta->ht_cap.ht_supported
+ && skb->protocol != cpu_to_be16(ETH_P_PAE)
+ && ieee80211_is_data_qos(wh->frame_control)) {
tid = qos & 0xf;
mwl8k_tx_count_packet(sta, tid);
spin_lock(&priv->stream_lock);
diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c
index 4a0a0e5265c9..0ca8b1455cd9 100644
--- a/drivers/net/wireless/orinoco/airport.c
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -150,7 +150,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
struct orinoco_private *priv;
struct airport *card;
unsigned long phys_addr;
- hermes_t *hw;
+ struct hermes *hw;
if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
@@ -228,10 +228,9 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
MODULE_LICENSE("Dual MPL/GPL");
-static struct of_device_id airport_match[] =
-{
+static struct of_device_id airport_match[] = {
{
- .name = "radio",
+ .name = "radio",
},
{},
};
@@ -240,7 +239,7 @@ MODULE_DEVICE_TABLE(of, airport_match);
static struct macio_driver airport_driver = {
.driver = {
- .name = DRIVER_NAME,
+ .name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = airport_match,
},
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 736bbb9bd1d0..f7b15b8934fa 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -59,7 +59,7 @@ int orinoco_wiphy_register(struct wiphy *wiphy)
for (i = 0; i < NUM_CHANNELS; i++) {
if (priv->channel_mask & (1 << i)) {
priv->channels[i].center_freq =
- ieee80211_dsss_chan_to_freq(i+1);
+ ieee80211_dsss_chan_to_freq(i + 1);
channels++;
}
}
@@ -182,7 +182,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
if ((channel < 1) || (channel > NUM_CHANNELS) ||
- !(priv->channel_mask & (1 << (channel-1))))
+ !(priv->channel_mask & (1 << (channel - 1))))
return -EINVAL;
if (orinoco_lock(priv, &flags) != 0)
@@ -191,7 +191,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
priv->channel = channel;
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
/* Fast channel change - no commit if successful */
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
HERMES_TEST_SET_CHANNEL,
channel, NULL);
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c
index 259d75853984..527cf5333db5 100644
--- a/drivers/net/wireless/orinoco/fw.c
+++ b/drivers/net/wireless/orinoco/fw.c
@@ -100,7 +100,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
/* Plug Data Area (PDA) */
__le16 *pda;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
const struct firmware *fw_entry;
const struct orinoco_fw_header *hdr;
const unsigned char *first_block;
@@ -205,7 +205,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
const unsigned char *image, const void *end,
int secondary)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret = 0;
const unsigned char *ptr;
const unsigned char *first_block;
@@ -322,9 +322,8 @@ symbol_dl_firmware(struct orinoco_private *priv,
fw_entry->data + fw_entry->size, 1);
if (!orinoco_cached_fw_get(priv, false))
release_firmware(fw_entry);
- if (ret) {
+ if (ret)
dev_err(dev, "Secondary firmware download failed\n");
- }
return ret;
}
diff --git a/drivers/net/wireless/orinoco/fw.h b/drivers/net/wireless/orinoco/fw.h
index 89fc26d25b06..aca63e3c4b5b 100644
--- a/drivers/net/wireless/orinoco/fw.h
+++ b/drivers/net/wireless/orinoco/fw.h
@@ -14,7 +14,7 @@ int orinoco_download(struct orinoco_private *priv);
void orinoco_cache_fw(struct orinoco_private *priv, int ap);
void orinoco_uncache_fw(struct orinoco_private *priv);
#else
-#define orinoco_cache_fw(priv, ap) do { } while(0)
+#define orinoco_cache_fw(priv, ap) do { } while (0)
#define orinoco_uncache_fw(priv) do { } while (0)
#endif
diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c
index 6c6a23e08df6..75c15bc7b34c 100644
--- a/drivers/net/wireless/orinoco/hermes.c
+++ b/drivers/net/wireless/orinoco/hermes.c
@@ -103,7 +103,7 @@ static const struct hermes_ops hermes_ops_local;
Callable from any context.
*/
-static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
+static int hermes_issue_cmd(struct hermes *hw, u16 cmd, u16 param0,
u16 param1, u16 param2)
{
int k = CMD_BUSY_TIMEOUT;
@@ -132,7 +132,7 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
*/
/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
-static int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
+static int hermes_doicmd_wait(struct hermes *hw, u16 cmd,
u16 parm0, u16 parm1, u16 parm2,
struct hermes_response *resp)
{
@@ -185,7 +185,8 @@ out:
return err;
}
-void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
+void hermes_struct_init(struct hermes *hw, void __iomem *address,
+ int reg_spacing)
{
hw->iobase = address;
hw->reg_spacing = reg_spacing;
@@ -195,7 +196,7 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
}
EXPORT_SYMBOL(hermes_struct_init);
-static int hermes_init(hermes_t *hw)
+static int hermes_init(struct hermes *hw)
{
u16 reg;
int err = 0;
@@ -249,7 +250,7 @@ static int hermes_init(hermes_t *hw)
* > 0 on error returned by the firmware
*
* Callable from any context, but locking is your problem. */
-static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
struct hermes_response *resp)
{
int err;
@@ -313,7 +314,7 @@ static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
return err;
}
-static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
+static int hermes_allocate(struct hermes *hw, u16 size, u16 *fid)
{
int err = 0;
int k;
@@ -363,7 +364,7 @@ static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
* from firmware
*
* Callable from any context */
-static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
+static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset)
{
int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
@@ -422,7 +423,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
* 0 on success
* > 0 on error from firmware
*/
-static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
+static int hermes_bap_pread(struct hermes *hw, int bap, void *buf, int len,
u16 id, u16 offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -436,7 +437,7 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
goto out;
/* Actually do the transfer */
- hermes_read_words(hw, dreg, buf, len/2);
+ hermes_read_words(hw, dreg, buf, len / 2);
out:
return err;
@@ -450,8 +451,8 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
* 0 on success
* > 0 on error from firmware
*/
-static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
- u16 id, u16 offset)
+static int hermes_bap_pwrite(struct hermes *hw, int bap, const void *buf,
+ int len, u16 id, u16 offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
int err = 0;
@@ -478,8 +479,8 @@ static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
* practice.
*
* Callable from user or bh context. */
-static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
- u16 *length, void *buf)
+static int hermes_read_ltv(struct hermes *hw, int bap, u16 rid,
+ unsigned bufsize, u16 *length, void *buf)
{
int err = 0;
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -523,7 +524,7 @@ static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
return 0;
}
-static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
+static int hermes_write_ltv(struct hermes *hw, int bap, u16 rid,
u16 length, const void *value)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -553,14 +554,14 @@ static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
/*** Hermes AUX control ***/
static inline void
-hermes_aux_setaddr(hermes_t *hw, u32 addr)
+hermes_aux_setaddr(struct hermes *hw, u32 addr)
{
hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
}
static inline int
-hermes_aux_control(hermes_t *hw, int enabled)
+hermes_aux_control(struct hermes *hw, int enabled)
{
int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
@@ -594,7 +595,7 @@ hermes_aux_control(hermes_t *hw, int enabled)
* wl_lkm Agere fw does
* Don't know about intersil
*/
-static int hermesi_program_init(hermes_t *hw, u32 offset)
+static int hermesi_program_init(struct hermes *hw, u32 offset)
{
int err;
@@ -643,7 +644,7 @@ static int hermesi_program_init(hermes_t *hw, u32 offset)
* wl_lkm Agere fw does
* Don't know about intersil
*/
-static int hermesi_program_end(hermes_t *hw)
+static int hermesi_program_end(struct hermes *hw)
{
struct hermes_response resp;
int rc = 0;
@@ -684,7 +685,8 @@ static int hermes_program_bytes(struct hermes *hw, const char *data,
}
/* Read PDA from the adapter */
-static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len)
+static int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr,
+ u16 pda_len)
{
int ret;
u16 pda_size;
diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h
index d9f18c11682a..28a42448d329 100644
--- a/drivers/net/wireless/orinoco/hermes.h
+++ b/drivers/net/wireless/orinoco/hermes.h
@@ -28,7 +28,7 @@
*
* As a module of low level hardware access routines, there is no
* locking. Users of this module should ensure that they serialize
- * access to the hermes_t structure, and to the hardware
+ * access to the hermes structure, and to the hardware
*/
#include <linux/if_ether.h>
@@ -43,7 +43,7 @@
#define HERMES_BAP_DATALEN_MAX (4096)
#define HERMES_BAP_OFFSET_MAX (4096)
#define HERMES_PORTID_MAX (7)
-#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX+1)
+#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX + 1)
#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */
#define HERMES_PDA_RECS_MAX (200) /* a guess */
#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */
@@ -148,7 +148,7 @@
#define HERMES_CMD_WRITEMIF (0x0031)
/*--- Debugging Commands -----------------------------*/
-#define HERMES_CMD_TEST (0x0038)
+#define HERMES_CMD_TEST (0x0038)
/* Test command arguments */
@@ -178,8 +178,8 @@
#define HERMES_DESCRIPTOR_OFFSET 0
#define HERMES_802_11_OFFSET (14)
-#define HERMES_802_3_OFFSET (14+32)
-#define HERMES_802_2_OFFSET (14+32+14)
+#define HERMES_802_3_OFFSET (14 + 32)
+#define HERMES_802_2_OFFSET (14 + 32 + 14)
#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2)
#define HERMES_RXSTAT_ERR (0x0003)
@@ -406,7 +406,7 @@ struct hermes_ops {
};
/* Basic control structure */
-typedef struct hermes {
+struct hermes {
void __iomem *iobase;
int reg_spacing;
#define HERMES_16BIT_REGSPACING 0
@@ -415,7 +415,7 @@ typedef struct hermes {
bool eeprom_pda;
const struct hermes_ops *ops;
void *priv;
-} hermes_t;
+};
/* Register access convenience macros */
#define hermes_read_reg(hw, off) \
@@ -427,28 +427,29 @@ typedef struct hermes {
hermes_write_reg((hw), HERMES_##name, (val))
/* Function prototypes */
-void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
+void hermes_struct_init(struct hermes *hw, void __iomem *address,
+ int reg_spacing);
/* Inline functions */
-static inline int hermes_present(hermes_t *hw)
+static inline int hermes_present(struct hermes *hw)
{
return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
}
-static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
+static inline void hermes_set_irqmask(struct hermes *hw, u16 events)
{
hw->inten = events;
hermes_write_regn(hw, INTEN, events);
}
-static inline int hermes_enable_port(hermes_t *hw, int port)
+static inline int hermes_enable_port(struct hermes *hw, int port)
{
return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
0, NULL);
}
-static inline int hermes_disable_port(hermes_t *hw, int port)
+static inline int hermes_disable_port(struct hermes *hw, int port)
{
return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
0, NULL);
@@ -456,13 +457,13 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
/* Initiate an INQUIRE command (tallies or scan). The result will come as an
* information frame in __orinoco_ev_info() */
-static inline int hermes_inquire(hermes_t *hw, u16 rid)
+static inline int hermes_inquire(struct hermes *hw, u16 rid)
{
return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
}
-#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1)
-#define HERMES_RECLEN_TO_BYTES(n) (((n)-1) * 2)
+#define HERMES_BYTES_TO_RECLEN(n) ((((n) + 1) / 2) + 1)
+#define HERMES_RECLEN_TO_BYTES(n) (((n) - 1) * 2)
/* Note that for the next two, the count is in 16-bit words, not bytes */
static inline void hermes_read_words(struct hermes *hw, int off,
@@ -498,7 +499,8 @@ static inline void hermes_clear_words(struct hermes *hw, int off,
(hw->ops->write_ltv((hw), (bap), (rid), \
HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
-static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
+static inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid,
+ u16 *word)
{
__le16 rec;
int err;
@@ -508,7 +510,8 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
return err;
}
-static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
+static inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid,
+ u16 word)
{
__le16 rec = cpu_to_le16(word);
return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
index 2b2b9a1a979c..4a10b7aca043 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.c
+++ b/drivers/net/wireless/orinoco/hermes_dld.c
@@ -193,7 +193,7 @@ hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end)
/* Process one Plug Data Item - find corresponding PDR and plug it */
static int
-hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
+hermes_plug_pdi(struct hermes *hw, const struct pdr *first_pdr,
const struct pdi *pdi, const void *pdr_end)
{
const struct pdr *pdr;
@@ -220,7 +220,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
* Attempt to write every records that is in the specified pda
* which also has a valid production data record for the firmware.
*/
-int hermes_apply_pda(hermes_t *hw,
+int hermes_apply_pda(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
@@ -274,7 +274,7 @@ hermes_blocks_length(const char *first_block, const void *end)
/*** Hermes programming ***/
/* Program the data blocks */
-int hermes_program(hermes_t *hw, const char *first_block, const void *end)
+int hermes_program(struct hermes *hw, const char *first_block, const void *end)
{
const struct dblock *blk;
u32 blkaddr;
@@ -387,7 +387,7 @@ DEFINE_DEFAULT_PDR(0x0161, 256,
*
* For certain records, use defaults if they are not found in pda.
*/
-int hermes_apply_pda_with_defaults(hermes_t *hw,
+int hermes_apply_pda_with_defaults(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
diff --git a/drivers/net/wireless/orinoco/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h
index 583a5bcf9175..b5377e232c63 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.h
+++ b/drivers/net/wireless/orinoco/hermes_dld.h
@@ -27,21 +27,21 @@
#include "hermes.h"
-int hermesi_program_init(hermes_t *hw, u32 offset);
-int hermesi_program_end(hermes_t *hw);
-int hermes_program(hermes_t *hw, const char *first_block, const void *end);
+int hermesi_program_init(struct hermes *hw, u32 offset);
+int hermesi_program_end(struct hermes *hw);
+int hermes_program(struct hermes *hw, const char *first_block, const void *end);
-int hermes_read_pda(hermes_t *hw,
+int hermes_read_pda(struct hermes *hw,
__le16 *pda,
u32 pda_addr,
u16 pda_len,
int use_eeprom);
-int hermes_apply_pda(hermes_t *hw,
+int hermes_apply_pda(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
const void *pda_end);
-int hermes_apply_pda_with_defaults(hermes_t *hw,
+int hermes_apply_pda_with_defaults(struct hermes *hw,
const char *first_pdr,
const void *pdr_end,
const __le16 *pda,
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 3c7877a7c31c..c09c8437c0b8 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -47,7 +47,7 @@ struct comp_id {
u16 id, variant, major, minor;
} __packed;
-static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
+static inline enum fwtype determine_firmware_type(struct comp_id *nic_id)
{
if (nic_id->id < 0x8000)
return FIRMWARE_TYPE_AGERE;
@@ -71,11 +71,11 @@ int determine_fw_capabilities(struct orinoco_private *priv,
u32 *hw_ver)
{
struct device *dev = priv->dev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
struct comp_id nic_id, sta_id;
unsigned int firmver;
- char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
+ char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
/* Get the hardware version */
err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
@@ -280,7 +280,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
{
struct device *dev = priv->dev;
struct hermes_idstring nickbuf;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int len;
int err;
u16 reclen;
@@ -458,7 +458,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
{
struct net_device *dev = priv->ndev;
struct wireless_dev *wdev = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
struct hermes_idstring idbuf;
@@ -529,7 +529,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
- HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+ HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
&idbuf);
if (err) {
printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
@@ -537,7 +537,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
return err;
}
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
- HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+ HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
&idbuf);
if (err) {
printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
@@ -549,7 +549,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
idbuf.len = cpu_to_le16(strlen(priv->nick));
memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
- HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+ HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2),
&idbuf);
if (err) {
printk(KERN_ERR "%s: Error %d setting nickname\n",
@@ -689,7 +689,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
/* Get tsc from the firmware */
int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u8 tsc_arr[4][ORINOCO_SEQ_LEN];
@@ -706,7 +706,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ratemode = priv->bitratemode;
int err = 0;
@@ -737,7 +737,7 @@ int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int i;
int err = 0;
u16 val;
@@ -786,7 +786,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv)
{
int roaming_flag;
int err = 0;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
switch (priv->firmware_type) {
case FIRMWARE_TYPE_AGERE:
@@ -818,7 +818,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv)
* which is needed for 802.1x implementations. */
int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
int i;
@@ -902,7 +902,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
int __orinoco_hw_setup_enc(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
int master_wep_flag;
int auth_flag;
@@ -999,7 +999,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
u8 rx_mic[MIC_KEYLEN];
u8 tsc[ORINOCO_SEQ_LEN];
} __packed buf;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret;
int err;
int k;
@@ -1052,7 +1052,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
err = hermes_write_wordrec(hw, USER_BAP,
@@ -1068,7 +1068,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
struct net_device *dev,
int mc_count, int promisc)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
if (promisc != priv->promiscuous) {
@@ -1111,9 +1111,9 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
/* Return : < 0 -> error code ; >= 0 -> length */
int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
- char buf[IW_ESSID_MAX_SIZE+1])
+ char buf[IW_ESSID_MAX_SIZE + 1])
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
struct hermes_idstring essidbuf;
char *p = (char *)(&essidbuf.val);
@@ -1166,7 +1166,7 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
int orinoco_hw_get_freq(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u16 channel;
int freq = 0;
@@ -1206,7 +1206,7 @@ int orinoco_hw_get_freq(struct orinoco_private *priv)
int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
int *numrates, s32 *rates, int max)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct hermes_idstring list;
unsigned char *p = (unsigned char *)&list.val;
int err = 0;
@@ -1238,7 +1238,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
const struct cfg80211_ssid *ssid)
{
struct net_device *dev = priv->ndev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
unsigned long flags;
int err = 0;
@@ -1323,7 +1323,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
int orinoco_hw_disassociate(struct orinoco_private *priv,
u8 *addr, u16 reason_code)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
struct {
@@ -1346,7 +1346,7 @@ int orinoco_hw_disassociate(struct orinoco_private *priv,
int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
u8 *addr)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index 97af71e79950..8f6831f4e328 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -45,7 +45,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
struct net_device *dev,
int mc_count, int promisc);
int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
- char buf[IW_ESSID_MAX_SIZE+1]);
+ char buf[IW_ESSID_MAX_SIZE + 1]);
int orinoco_hw_get_freq(struct orinoco_private *priv);
int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
int *numrates, s32 *rates, int max);
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 62c6b2b37dbe..ef7efe839bb8 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -4,7 +4,7 @@
* adaptors, with Lucent/Agere, Intersil or Symbol firmware.
*
* Current maintainers (as of 29 September 2003) are:
- * Pavel Roskin <proski AT gnu.org>
+ * Pavel Roskin <proski AT gnu.org>
* and David Gibson <hermes AT gibson.dropbear.id.au>
*
* (C) Copyright David Gibson, IBM Corporation 2001-2003.
@@ -146,10 +146,10 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
#define MAX_IRQLOOPS_PER_IRQ 10
-#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
- * how many events the
- * device could
- * legitimately generate */
+#define MAX_IRQLOOPS_PER_JIFFY (20000 / HZ) /* Based on a guestimate of
+ * how many events the
+ * device could
+ * legitimately generate */
#define DUMMY_FID 0xFFFF
@@ -157,7 +157,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
HERMES_MAX_MULTICAST : 0)*/
#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
-#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
+#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
| HERMES_EV_TX | HERMES_EV_TXEXC \
| HERMES_EV_WTERR | HERMES_EV_INFO \
| HERMES_EV_INFDROP)
@@ -437,12 +437,12 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u16 txfid = priv->txfid;
int tx_control;
unsigned long flags;
- u8 mic_buf[MICHAEL_MIC_LEN+1];
+ u8 mic_buf[MICHAEL_MIC_LEN + 1];
if (!netif_running(dev)) {
printk(KERN_ERR "%s: Tx on stopped device!\n",
@@ -579,7 +579,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
-static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_alloc(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
u16 fid = hermes_read_regn(hw, ALLOCFID);
@@ -594,7 +594,7 @@ static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
}
-static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_tx(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
@@ -606,7 +606,7 @@ static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
}
-static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_txexc(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
@@ -753,7 +753,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
struct sk_buff *skb;
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
len = le16_to_cpu(desc->data_len);
@@ -840,7 +840,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
stats->rx_dropped++;
}
-void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
@@ -918,7 +918,7 @@ void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
32bit boundary, plus 1 byte so we can read in odd length
packets from the card, which has an IO granularity of 16
bits */
- skb = dev_alloc_skb(length+ETH_HLEN+2+1);
+ skb = dev_alloc_skb(length + ETH_HLEN + 2 + 1);
if (!skb) {
printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
dev->name);
@@ -1402,7 +1402,7 @@ static void orinoco_process_scan_results(struct work_struct *work)
spin_unlock_irqrestore(&priv->scan_lock, flags);
}
-void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_info(struct net_device *dev, struct hermes *hw)
{
struct orinoco_private *priv = ndev_priv(dev);
u16 infofid;
@@ -1620,7 +1620,7 @@ void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
}
EXPORT_SYMBOL(__orinoco_ev_info);
-static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_infdrop(struct net_device *dev, struct hermes *hw)
{
if (net_ratelimit())
printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
@@ -1831,7 +1831,7 @@ static int __orinoco_commit(struct orinoco_private *priv)
int orinoco_commit(struct orinoco_private *priv)
{
struct net_device *dev = priv->ndev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err;
if (priv->broken_disableport) {
@@ -1874,12 +1874,12 @@ int orinoco_commit(struct orinoco_private *priv)
/* Interrupt handler */
/********************************************************************/
-static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_tick(struct net_device *dev, struct hermes *hw)
{
printk(KERN_DEBUG "%s: TICK\n", dev->name);
}
-static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_wterr(struct net_device *dev, struct hermes *hw)
{
/* This seems to happen a fair bit under load, but ignoring it
seems to work fine...*/
@@ -1891,7 +1891,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
{
struct orinoco_private *priv = dev_id;
struct net_device *dev = priv->ndev;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int count = MAX_IRQLOOPS_PER_IRQ;
u16 evstat, events;
/* These are used to detect a runaway interrupt situation.
@@ -1958,7 +1958,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
evstat = hermes_read_regn(hw, EVSTAT);
events = evstat & hw->inten;
- };
+ }
orinoco_unlock(priv, &flags);
return IRQ_HANDLED;
@@ -2017,8 +2017,8 @@ static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
unregister_pm_notifier(&priv->pm_notifier);
}
#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
-#define orinoco_register_pm_notifier(priv) do { } while(0)
-#define orinoco_unregister_pm_notifier(priv) do { } while(0)
+#define orinoco_register_pm_notifier(priv) do { } while (0)
+#define orinoco_unregister_pm_notifier(priv) do { } while (0)
#endif
/********************************************************************/
@@ -2029,7 +2029,7 @@ int orinoco_init(struct orinoco_private *priv)
{
struct device *dev = priv->dev;
struct wiphy *wiphy = priv_to_wiphy(priv);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
/* No need to lock, the hw_unavailable flag is already set in
diff --git a/drivers/net/wireless/orinoco/mic.c b/drivers/net/wireless/orinoco/mic.c
index c03e7f54d1b8..fce4a843e656 100644
--- a/drivers/net/wireless/orinoco/mic.c
+++ b/drivers/net/wireless/orinoco/mic.c
@@ -59,10 +59,10 @@ int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key,
/* Copy header into buffer. We need the padding on the end zeroed */
memcpy(&hdr[0], da, ETH_ALEN);
memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
- hdr[ETH_ALEN*2] = priority;
- hdr[ETH_ALEN*2+1] = 0;
- hdr[ETH_ALEN*2+2] = 0;
- hdr[ETH_ALEN*2+3] = 0;
+ hdr[ETH_ALEN * 2] = priority;
+ hdr[ETH_ALEN * 2 + 1] = 0;
+ hdr[ETH_ALEN * 2 + 2] = 0;
+ hdr[ETH_ALEN * 2 + 3] = 0;
/* Use scatter gather to MIC header and data in one go */
sg_init_table(sg, 2);
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 255710ef082a..3bb936b9558c 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -49,11 +49,11 @@ enum orinoco_alg {
ORINOCO_ALG_TKIP
};
-typedef enum {
+enum fwtype {
FIRMWARE_TYPE_AGERE,
FIRMWARE_TYPE_INTERSIL,
FIRMWARE_TYPE_SYMBOL
-} fwtype_t;
+};
struct firmware;
@@ -88,11 +88,11 @@ struct orinoco_private {
struct iw_statistics wstats;
/* Hardware control variables */
- hermes_t hw;
+ struct hermes hw;
u16 txfid;
/* Capabilities of the hardware/firmware */
- fwtype_t firmware_type;
+ enum fwtype firmware_type;
int ibss_port;
int nicbuf_size;
u16 channel_mask;
@@ -122,8 +122,8 @@ struct orinoco_private {
struct key_params keys[ORINOCO_MAX_KEYS];
int bitratemode;
- char nick[IW_ESSID_MAX_SIZE+1];
- char desired_essid[IW_ESSID_MAX_SIZE+1];
+ char nick[IW_ESSID_MAX_SIZE + 1];
+ char desired_essid[IW_ESSID_MAX_SIZE + 1];
char desired_bssid[ETH_ALEN];
int bssid_fixed;
u16 frag_thresh, mwo_robust;
@@ -197,8 +197,8 @@ extern int orinoco_up(struct orinoco_private *priv);
extern void orinoco_down(struct orinoco_private *priv);
extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
-extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
-extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
+extern void __orinoco_ev_info(struct net_device *dev, struct hermes *hw);
+extern void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw);
int orinoco_process_xmit_skb(struct sk_buff *skb,
struct net_device *dev,
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 88e3c0ebcaad..3f7fc4a0b43d 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -65,7 +65,7 @@ static void orinoco_cs_release(struct pcmcia_device *link);
static void orinoco_cs_detach(struct pcmcia_device *p_dev);
/********************************************************************/
-/* Device methods */
+/* Device methods */
/********************************************************************/
static int
@@ -89,7 +89,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
}
/********************************************************************/
-/* PCMCIA stuff */
+/* PCMCIA stuff */
/********************************************************************/
static int
@@ -134,7 +134,7 @@ static int
orinoco_cs_config(struct pcmcia_device *link)
{
struct orinoco_private *priv = link->priv;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret;
void __iomem *mem;
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index bc3ea0b67a4f..326396b313a6 100644
--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -296,8 +296,7 @@ static struct pci_driver orinoco_nortel_driver = {
static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
" (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
-MODULE_DESCRIPTION
- ("Driver for wireless LAN cards using the Nortel PCI bridge");
+MODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge");
MODULE_LICENSE("Dual MPL/GPL");
static int __init orinoco_nortel_init(void)
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 468197f86673..6058c66b844e 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -6,7 +6,7 @@
* hermes registers, as well as the COR register.
*
* Current maintainers are:
- * Pavel Roskin <proski AT gnu.org>
+ * Pavel Roskin <proski AT gnu.org>
* and David Gibson <hermes AT gibson.dropbear.id.au>
*
* Some of this code is borrowed from orinoco_plx.c
@@ -81,7 +81,7 @@
*/
static int orinoco_pci_cor_reset(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
unsigned long timeout;
u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index 9358f4d2307b..2bac8248a991 100644
--- a/drivers/net/wireless/orinoco/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -4,7 +4,7 @@
* but are connected to the PCI bus by a PLX9052.
*
* Current maintainers are:
- * Pavel Roskin <proski AT gnu.org>
+ * Pavel Roskin <proski AT gnu.org>
* and David Gibson <hermes AT gibson.dropbear.id.au>
*
* (C) Copyright David Gibson, IBM Corp. 2001-2003.
@@ -102,14 +102,14 @@
#define PLX_RESET_TIME (500) /* milliseconds */
#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */
-#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
+#define PLX_INTCSR_INTEN (1 << 6) /* Interrupt Enable bit */
/*
* Do a soft reset of the card using the Configuration Option Register
*/
static int orinoco_plx_cor_reset(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct orinoco_pci_card *card = priv->card;
unsigned long timeout;
u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index 784605f0af15..93159d68ec93 100644
--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -59,7 +59,7 @@
*/
static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
{
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct orinoco_pci_card *card = priv->card;
unsigned long timeout;
u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index b9aedf18a046..811e87f8a349 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -199,7 +199,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
#define EZUSB_FRAME_DATA 1
#define EZUSB_FRAME_CONTROL 2
-#define DEF_TIMEOUT (3*HZ)
+#define DEF_TIMEOUT (3 * HZ)
#define BULK_BUF_SIZE 2048
@@ -959,7 +959,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
return retval;
}
-static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid,
+static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
u16 length, const void *data)
{
struct ezusb_priv *upriv = hw->priv;
@@ -989,7 +989,7 @@ static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid,
NULL, 0, NULL);
}
-static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid,
+static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
unsigned bufsize, u16 *length, void *buf)
{
struct ezusb_priv *upriv = hw->priv;
@@ -1006,7 +1006,7 @@ static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid,
buf, bufsize, length);
}
-static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1,
+static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
u16 parm2, struct hermes_response *resp)
{
struct ezusb_priv *upriv = hw->priv;
@@ -1028,7 +1028,7 @@ static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1,
EZUSB_FRAME_CONTROL, NULL, 0, NULL);
}
-static int ezusb_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
struct hermes_response *resp)
{
struct ezusb_priv *upriv = hw->priv;
@@ -1196,7 +1196,7 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct ezusb_priv *upriv = priv->card;
- u8 mic[MICHAEL_MIC_LEN+1];
+ u8 mic[MICHAEL_MIC_LEN + 1];
int err = 0;
int tx_control;
unsigned long flags;
@@ -1356,7 +1356,7 @@ static int ezusb_hard_reset(struct orinoco_private *priv)
}
-static int ezusb_init(hermes_t *hw)
+static int ezusb_init(struct hermes *hw)
{
struct ezusb_priv *upriv = hw->priv;
int retval;
@@ -1438,7 +1438,7 @@ static void ezusb_bulk_in_callback(struct urb *urb)
} else if (upriv->dev) {
struct net_device *dev = upriv->dev;
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
if (hermes_rid == EZUSB_RID_RX) {
__orinoco_ev_rx(dev, hw);
@@ -1575,7 +1575,7 @@ static int ezusb_probe(struct usb_interface *interface,
{
struct usb_device *udev = interface_to_usbdev(interface);
struct orinoco_private *priv;
- hermes_t *hw;
+ struct hermes *hw;
struct ezusb_priv *upriv = NULL;
struct usb_interface_descriptor *iface_desc;
struct usb_endpoint_descriptor *ep;
@@ -1757,7 +1757,7 @@ static struct usb_driver orinoco_driver = {
/* Can't be declared "const" or the whole __initdata section will
* become const */
static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
- " (Manuel Estrada Sainz)";
+ " (Manuel Estrada Sainz)";
static int __init ezusb_module_init(void)
{
@@ -1787,6 +1787,5 @@ module_init(ezusb_module_init);
module_exit(ezusb_module_exit);
MODULE_AUTHOR("Manuel Estrada Sainz");
-MODULE_DESCRIPTION
- ("Driver for Orinoco wireless LAN cards using EZUSB bridge");
+MODULE_DESCRIPTION("Driver for Orinoco wireless LAN cards using EZUSB bridge");
MODULE_LICENSE("Dual MPL/GPL");
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 81f3673d31d4..6e28ee4e9c52 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -11,9 +11,9 @@
*
* Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
* Portions based on orinoco_cs.c:
- * Copyright (C) David Gibson, Linuxcare Australia
+ * Copyright (C) David Gibson, Linuxcare Australia
* Portions based on Spectrum24tDnld.c from original spectrum24 driver:
- * Copyright (C) Symbol Technologies.
+ * Copyright (C) Symbol Technologies.
*
* See copyright notice in file main.c.
*/
@@ -125,7 +125,7 @@ failed:
}
/********************************************************************/
-/* Device methods */
+/* Device methods */
/********************************************************************/
static int
@@ -150,7 +150,7 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
}
/********************************************************************/
-/* PCMCIA stuff */
+/* PCMCIA stuff */
/********************************************************************/
static int
@@ -197,7 +197,7 @@ static int
spectrum_cs_config(struct pcmcia_device *link)
{
struct orinoco_private *priv = link->priv;
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int ret;
void __iomem *mem;
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index e793679e2e19..bbb9beb206b1 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -87,7 +87,7 @@ nomem:
static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct iw_statistics *wstats = &priv->wstats;
int err;
unsigned long flags;
@@ -448,7 +448,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
}
if ((chan < 1) || (chan > NUM_CHANNELS) ||
- !(priv->channel_mask & (1 << (chan-1))))
+ !(priv->channel_mask & (1 << (chan - 1))))
return -EINVAL;
if (orinoco_lock(priv, &flags) != 0)
@@ -457,7 +457,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
priv->channel = chan;
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
/* Fast channel change - no commit if successful */
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
HERMES_TEST_SET_CHANNEL,
chan, NULL);
@@ -492,7 +492,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
u16 val;
int err;
unsigned long flags;
@@ -668,7 +668,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int err = 0;
u16 enable, period, timeout, mcast;
unsigned long flags;
@@ -873,7 +873,7 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
struct iw_param *param = &wrqu->param;
unsigned long flags;
int ret = -EINPROGRESS;
@@ -1269,7 +1269,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct hermes *hw = &priv->hw;
int rid = data->flags;
u16 length;
int err;
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index ee9bc62a4fa2..7aa509f7e387 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -1,5 +1,6 @@
#ifndef P54PCI_H
#define P54PCI_H
+#include <linux/interrupt.h>
/*
* Defines for PCI based mac80211 Prism54 driver
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index ec2c75d77cea..5d0f61508a2e 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -18,6 +18,7 @@
*
*/
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index c4d0f19b7cbc..c40403877f97 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -22,6 +22,7 @@
#ifndef _ISLPCI_DEV_H
#define _ISLPCI_DEV_H
+#include <linux/irqreturn.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index b5e64d71b7a6..9e68e0cb718e 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -17,6 +17,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index b2f8b8fd4d2d..a0a7854facc0 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -83,14 +83,12 @@ config RT2800PCI_RT33XX
config RT2800PCI_RT35XX
bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default n
+ default y
---help---
This adds support for rt35xx wireless chipset family to the
rt2800pci driver.
Supported chips: RT3060, RT3062, RT3562, RT3592
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
config RT2800PCI_RT53XX
bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
@@ -154,15 +152,12 @@ config RT2800USB_RT33XX
config RT2800USB_RT35XX
bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default n
+ default y
---help---
This adds support for rt35xx wireless chipset family to the
rt2800usb driver.
Supported chips: RT3572
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
config RT2800USB_RT53XX
bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 937f9e8bf05f..76bcc3547976 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1723,6 +1723,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index d27d7b8ba3b6..c288d951c034 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2016,6 +2016,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 15237c275486..53c5f878f61d 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1827,6 +1827,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index f67bc9b31b28..c69a7d71f4ca 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1740,6 +1740,7 @@ struct mac_iveiv_entry {
/*
* BBP 3: RX Antenna
*/
+#define BBP3_RX_ADC FIELD8(0x03)
#define BBP3_RX_ANTENNA FIELD8(0x18)
#define BBP3_HT40_MINUS FIELD8(0x20)
@@ -1783,6 +1784,8 @@ struct mac_iveiv_entry {
#define RFCSR1_TX0_PD FIELD8(0x08)
#define RFCSR1_RX1_PD FIELD8(0x10)
#define RFCSR1_TX1_PD FIELD8(0x20)
+#define RFCSR1_RX2_PD FIELD8(0x40)
+#define RFCSR1_TX2_PD FIELD8(0x80)
/*
* RFCSR 2:
@@ -1790,15 +1793,25 @@ struct mac_iveiv_entry {
#define RFCSR2_RESCAL_EN FIELD8(0x80)
/*
+ * FRCSR 5:
+ */
+#define RFCSR5_R1 FIELD8(0x0c)
+
+/*
* RFCSR 6:
*/
#define RFCSR6_R1 FIELD8(0x03)
#define RFCSR6_R2 FIELD8(0x40)
+#define RFCSR6_TXDIV FIELD8(0x0c)
/*
* RFCSR 7:
*/
#define RFCSR7_RF_TUNING FIELD8(0x01)
+#define RFCSR7_R02 FIELD8(0x07)
+#define RFCSR7_R3 FIELD8(0x08)
+#define RFCSR7_R45 FIELD8(0x30)
+#define RFCSR7_R67 FIELD8(0xc0)
/*
* RFCSR 11:
@@ -1809,11 +1822,13 @@ struct mac_iveiv_entry {
* RFCSR 12:
*/
#define RFCSR12_TX_POWER FIELD8(0x1f)
+#define RFCSR12_DR0 FIELD8(0xe0)
/*
* RFCSR 13:
*/
#define RFCSR13_TX_POWER FIELD8(0x1f)
+#define RFCSR13_DR0 FIELD8(0xe0)
/*
* RFCSR 15:
@@ -2256,6 +2271,7 @@ struct mac_iveiv_entry {
#define MCU_ANT_SELECT 0X73
#define MCU_BBP_SIGNAL 0x80
#define MCU_POWER_SAVE 0x83
+#define MCU_BAND_SELECT 0x91
/*
* MCU mailbox tokens
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 2a6aa85cc6c9..84ab7d1acb6a 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -401,7 +401,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
return -EBUSY;
if (rt2x00_is_pci(rt2x00dev)) {
- if (rt2x00_rt(rt2x00dev, RT5390)) {
+ if (rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -600,49 +601,6 @@ void rt2800_process_rxwi(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
-static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
-{
- __le32 *txwi;
- u32 word;
- int wcid, ack, pid;
- int tx_wcid, tx_ack, tx_pid;
-
- wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
- ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
- pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-
- /*
- * This frames has returned with an IO error,
- * so the status report is not intended for this
- * frame.
- */
- if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
- rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
- return false;
- }
-
- /*
- * Validate if this TX status report is intended for
- * this entry by comparing the WCID/ACK/PID fields.
- */
- txwi = rt2800_drv_get_txwi(entry);
-
- rt2x00_desc_read(txwi, 1, &word);
- tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
- tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
- tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
-
- if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
- WARNING(entry->queue->rt2x00dev,
- "TX status report missed for queue %d entry %d\n",
- entry->queue->qid, entry->entry_idx);
- rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
- return false;
- }
-
- return true;
-}
-
void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -725,45 +683,6 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
}
EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue;
- struct queue_entry *entry;
- u32 reg;
- u8 qid;
-
- while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
-
- /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
- * qid is guaranteed to be one of the TX QIDs
- */
- qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
- queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
- if (unlikely(!queue)) {
- WARNING(rt2x00dev, "Got TX status for an unavailable "
- "queue %u, dropping\n", qid);
- continue;
- }
-
- /*
- * Inside each queue, we process each entry in a chronological
- * order. We first check that the queue is not empty.
- */
- entry = NULL;
- while (!rt2x00queue_empty(queue)) {
- entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- if (rt2800_txdone_entry_check(entry, reg))
- break;
- }
-
- if (!entry || rt2x00queue_empty(queue))
- break;
-
- rt2800_txdone_entry(entry, reg);
- }
-}
-EXPORT_SYMBOL_GPL(rt2800_txdone);
-
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -1355,7 +1274,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
gf20_rate = gf40_rate = 0x0003;
}
break;
- };
+ }
/* check for STAs not supporting greenfield mode */
if (any_sta_nongf)
@@ -1433,6 +1352,40 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
}
EXPORT_SYMBOL_GPL(rt2800_config_erp);
+static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+ u16 eeprom;
+ u8 led_ctrl, led_g_mode, led_r_mode;
+
+ rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+ rt2x00_set_field32(&reg, GPIO_SWITCH_0, 1);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_1, 1);
+ } else {
+ rt2x00_set_field32(&reg, GPIO_SWITCH_0, 0);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_1, 0);
+ }
+ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+ rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+ led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
+ led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
+ if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
+ led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+ led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
+ if (led_ctrl == 0 || led_ctrl > 0x40) {
+ rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
+ rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, led_r_mode);
+ rt2800_register_write(rt2x00dev, LED_CFG, reg);
+ } else {
+ rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff,
+ (led_g_mode << 2) | led_r_mode, 1);
+ }
+ }
+}
+
static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
enum antenna ant)
{
@@ -1463,6 +1416,10 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2800_bbp_read(rt2x00dev, 1, &r1);
rt2800_bbp_read(rt2x00dev, 3, &r3);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2800_config_3572bt_ant(rt2x00dev);
+
/*
* Configure the TX antenna.
*/
@@ -1471,7 +1428,11 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
break;
case 2:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1);
+ else
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
break;
case 3:
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
@@ -1496,7 +1457,15 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
break;
case 2:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+ rt2x00_set_field8(&r3, BBP3_RX_ADC, 1);
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA,
+ rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+ rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B);
+ } else {
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+ }
break;
case 3:
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
@@ -1630,6 +1599,161 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
}
+static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u8 rfcsr;
+ u32 reg;
+
+ if (rf->channel <= 14) {
+ rt2800_bbp_write(rt2x00dev, 25, 0x15);
+ rt2800_bbp_write(rt2x00dev, 26, 0x85);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 25, 0x09);
+ rt2800_bbp_write(rt2x00dev, 26, 0xff);
+ }
+
+ rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
+ rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
+ if (rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
+ if (rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
+ rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+ (info->default_power1 & 0x3) |
+ ((info->default_power1 & 0xC) << 1));
+ } else {
+ rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7);
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+ (info->default_power1 & 0x3) |
+ ((info->default_power1 & 0xC) << 1));
+ }
+ rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
+ rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+ (info->default_power2 & 0x3) |
+ ((info->default_power2 & 0xC) << 1));
+ } else {
+ rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7);
+ rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+ (info->default_power2 & 0x3) |
+ ((info->default_power2 & 0xC) << 1));
+ }
+ rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+ }
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+ } else {
+ switch (rt2x00dev->default_ant.tx_chain_num) {
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+ break;
+ }
+
+ switch (rt2x00dev->default_ant.rx_chain_num) {
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+ break;
+ }
+ }
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+ rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+ rt2800_rfcsr_write(rt2x00dev, 24,
+ rt2x00dev->calibration[conf_is_ht40(conf)]);
+ rt2800_rfcsr_write(rt2x00dev, 31,
+ rt2x00dev->calibration[conf_is_ht40(conf)]);
+
+ if (rf->channel <= 14) {
+ rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+ } else {
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x14);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x43);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x7a);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ if (rf->channel <= 64) {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0xb7);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf6);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
+ } else if (rf->channel <= 128) {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x74);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf4);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ } else {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x72);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf3);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ }
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x87);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x01);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
+ }
+
+ rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT7, 0);
+ if (rf->channel <= 14)
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 1);
+ else
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 0);
+ rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
+ rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+ rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+}
#define RT5390_POWER_BOUND 0x27
#define RT5390_FREQ_OFFSET_BOUND 0x5f
@@ -1748,9 +1872,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_rf(rt2x00dev, RF3020) ||
rt2x00_rf(rt2x00dev, RF3021) ||
rt2x00_rf(rt2x00dev, RF3022) ||
- rt2x00_rf(rt2x00dev, RF3052) ||
rt2x00_rf(rt2x00dev, RF3320))
rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
+ else if (rt2x00_rf(rt2x00dev, RF3052))
+ rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
else if (rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5390))
rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
@@ -1777,7 +1902,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
}
}
} else {
- rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_bbp_write(rt2x00dev, 82, 0x94);
+ else
+ rt2800_bbp_write(rt2x00dev, 82, 0xf2);
if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
rt2800_bbp_write(rt2x00dev, 75, 0x46);
@@ -1791,12 +1919,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_rfcsr_write(rt2x00dev, 8, 0);
+
tx_pin = 0;
/* Turn on unused PA or LNA when not using 1T or 1R */
if (rt2x00dev->default_ant.tx_chain_num == 2) {
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,
+ rf->channel > 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,
+ rf->channel <= 14);
}
/* Turn on unused PA or LNA when not using 1T or 1R */
@@ -1809,11 +1942,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
+ else
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN,
+ rf->channel <= 14);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
+
rt2800_bbp_read(rt2x00dev, 4, &bbp);
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
rt2800_bbp_write(rt2x00dev, 4, bbp);
@@ -2413,6 +2553,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
} else if (rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -2799,6 +2942,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
}
if (rt2800_is_305x_soc(rt2x00dev) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390))
rt2800_bbp_write(rt2x00dev, 31, 0x08);
@@ -2828,6 +2972,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_bbp_write(rt2x00dev, 79, 0x13);
rt2800_bbp_write(rt2x00dev, 80, 0x05);
@@ -2868,6 +3013,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2800_is_305x_soc(rt2x00dev))
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
@@ -2895,6 +3041,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_bbp_read(rt2x00dev, 138, &value);
@@ -3031,6 +3178,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
!rt2x00_rt(rt2x00dev, RT3071) &&
!rt2x00_rt(rt2x00dev, RT3090) &&
!rt2x00_rt(rt2x00dev, RT3390) &&
+ !rt2x00_rt(rt2x00dev, RT3572) &&
!rt2x00_rt(rt2x00dev, RT5390) &&
!rt2800_is_305x_soc(rt2x00dev))
return 0;
@@ -3109,6 +3257,38 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x05);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x4a);
+ rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x70);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x65);
+ rt2800_rfcsr_write(rt2x00dev, 14, 0xa0);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0xac);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 21, 0xd0);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 23, 0x3c);
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
} else if (rt2800_is_305x_soc(rt2x00dev)) {
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
@@ -3258,6 +3438,19 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+ msleep(1);
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
}
/*
@@ -3270,7 +3463,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
} else if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3390)) {
+ rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572)) {
rt2x00dev->calibration[0] =
rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);
rt2x00dev->calibration[1] =
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index f2d15941c71a..69deb3148ae7 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -152,7 +152,6 @@ 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(struct rt2x00_dev *rt2x00dev);
void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index cc4a54f571b8..ebc17ad61dec 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -219,7 +219,7 @@ static void rt2800pci_start_queue(struct data_queue *queue)
break;
default:
break;
- };
+ }
}
static void rt2800pci_kick_queue(struct data_queue *queue)
@@ -501,7 +501,9 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
- if (rt2x00_rt(rt2x00dev, RT5390)) {
+ if (rt2x00_is_pcie(rt2x00dev) &&
+ (rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390))) {
rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -1029,6 +1031,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2800_ops rt2800pci_rt2800_ops = {
@@ -1158,6 +1161,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
#endif
#ifdef CONFIG_RT2800PCI_RT53XX
{ PCI_DEVICE(0x1814, 0x5390) },
+ { PCI_DEVICE(0x1814, 0x539f) },
#endif
{ 0, }
};
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index ba82c972703a..507559361d87 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -457,6 +457,87 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
/*
* TX control handlers
*/
+static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+ __le32 *txwi;
+ u32 word;
+ int wcid, ack, pid;
+ int tx_wcid, tx_ack, tx_pid;
+
+ wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+ ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+ pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+
+ /*
+ * This frames has returned with an IO error,
+ * so the status report is not intended for this
+ * frame.
+ */
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+ return false;
+ }
+
+ /*
+ * Validate if this TX status report is intended for
+ * this entry by comparing the WCID/ACK/PID fields.
+ */
+ txwi = rt2800usb_get_txwi(entry);
+
+ rt2x00_desc_read(txwi, 1, &word);
+ tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+ tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
+ tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+ if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+ WARNING(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
+ rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+ return false;
+ }
+
+ return true;
+}
+
+static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+ struct queue_entry *entry;
+ u32 reg;
+ u8 qid;
+
+ while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
+
+ /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+ * qid is guaranteed to be one of the TX QIDs
+ */
+ qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+ queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+ if (unlikely(!queue)) {
+ WARNING(rt2x00dev, "Got TX status for an unavailable "
+ "queue %u, dropping\n", qid);
+ continue;
+ }
+
+ /*
+ * Inside each queue, we process each entry in a chronological
+ * order. We first check that the queue is not empty.
+ */
+ entry = NULL;
+ while (!rt2x00queue_empty(queue)) {
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ if (rt2800usb_txdone_entry_check(entry, reg))
+ break;
+ }
+
+ if (!entry || rt2x00queue_empty(queue))
+ break;
+
+ rt2800_txdone_entry(entry, reg);
+ }
+}
+
static void rt2800usb_work_txdone(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
@@ -464,7 +545,7 @@ static void rt2800usb_work_txdone(struct work_struct *work)
struct data_queue *queue;
struct queue_entry *entry;
- rt2800_txdone(rt2x00dev);
+ rt2800usb_txdone(rt2x00dev);
/*
* Process any trailing TX status reports for IO failures,
@@ -676,6 +757,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2800_ops rt2800usb_rt2800_ops = {
@@ -939,6 +1021,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0df6, 0x0048) },
{ USB_DEVICE(0x0df6, 0x0051) },
{ USB_DEVICE(0x0df6, 0x005f) },
+ { USB_DEVICE(0x0df6, 0x0060) },
/* SMC */
{ USB_DEVICE(0x083a, 0x6618) },
{ USB_DEVICE(0x083a, 0x7511) },
@@ -971,6 +1054,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0586, 0x341e) },
{ USB_DEVICE(0x0586, 0x343e) },
#ifdef CONFIG_RT2800USB_RT33XX
+ /* Belkin */
+ { USB_DEVICE(0x050d, 0x945b) },
/* Ralink */
{ USB_DEVICE(0x148f, 0x3370) },
{ USB_DEVICE(0x148f, 0x8070) },
@@ -995,6 +1080,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x148f, 0x3572) },
/* Sitecom */
{ USB_DEVICE(0x0df6, 0x0041) },
+ { USB_DEVICE(0x0df6, 0x0062) },
/* Toshiba */
{ USB_DEVICE(0x0930, 0x0a07) },
/* Zinwell */
@@ -1093,8 +1179,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0df6, 0x004a) },
{ USB_DEVICE(0x0df6, 0x004d) },
{ USB_DEVICE(0x0df6, 0x0053) },
- { USB_DEVICE(0x0df6, 0x0060) },
- { USB_DEVICE(0x0df6, 0x0062) },
/* SMC */
{ USB_DEVICE(0x083a, 0xa512) },
{ USB_DEVICE(0x083a, 0xc522) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c446db69bd3c..f82bfeb79ebb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -29,6 +29,7 @@
#define RT2X00_H
#include <linux/bitops.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
@@ -1276,6 +1277,7 @@ int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);
/*
* Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 1bb9d46077ff..1ca4c7ffc189 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -45,11 +45,11 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
}
}
-void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 939821b4af2f..0955c941317f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -583,6 +583,18 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
/*
+ * Check for valid size in case we get corrupted descriptor from
+ * hardware.
+ */
+ if (unlikely(rxdesc.size == 0 ||
+ rxdesc.size > entry->queue->data_size)) {
+ WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
+ rxdesc.size, entry->queue->data_size);
+ dev_kfree_skb(entry->skb);
+ goto renew_skb;
+ }
+
+ /*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
@@ -642,6 +654,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
+renew_skb:
/*
* Replace the skb with the freshly allocated one.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 322cc4f3de5d..15cdc7e57fc4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -336,7 +336,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
*/
#ifdef CONFIG_RT2X00_LIB_CRYPTO
enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
-void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc);
unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 93bec140e598..8efab3983528 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -818,3 +818,17 @@ void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
*rx_max = rt2x00dev->rx->limit;
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
+
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct data_queue *queue;
+
+ tx_queue_for_each(rt2x00dev, queue) {
+ if (!rt2x00queue_empty(queue))
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index ab8c16f8bcaf..29edb9fbe6f1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -200,20 +200,20 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
skb_pull(skb, l2pad);
}
-static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc)
{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
- unsigned long irqflags;
if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
return;
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
- if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
+ if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags))
return;
/*
@@ -227,23 +227,23 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
* sequence counting per-frame, since those will override the
* sequence counter given by mac80211.
*/
- spin_lock_irqsave(&intf->seqlock, irqflags);
+ spin_lock(&intf->seqlock);
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
intf->seqno += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
- spin_unlock_irqrestore(&intf->seqlock, irqflags);
+ spin_unlock(&intf->seqlock);
}
-static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc,
const struct rt2x00_rate *hwrate)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
unsigned int data_length;
unsigned int duration;
@@ -260,8 +260,8 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
txdesc->u.plcp.ifs = IFS_SIFS;
/* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
- data_length = entry->skb->len + 4;
- data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb);
+ data_length = skb->len + 4;
+ data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
/*
* PLCP setup
@@ -302,13 +302,14 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
}
}
-static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc,
const struct rt2x00_rate *hwrate)
{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ 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 *)entry->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
if (tx_info->control.sta)
txdesc->u.ht.mpdu_density =
@@ -381,12 +382,12 @@ static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
txdesc->u.ht.txop = TXOP_HTTXOP;
}
-static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
struct txentry_desc *txdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
struct ieee80211_rate *rate;
const struct rt2x00_rate *hwrate = NULL;
@@ -396,8 +397,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Header and frame information.
*/
- txdesc->length = entry->skb->len;
- txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+ txdesc->length = skb->len;
+ txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);
/*
* Check whether this frame is to be acked.
@@ -472,13 +473,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Apply TX descriptor handling by components
*/
- rt2x00crypto_create_tx_descriptor(entry, txdesc);
- rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
+ rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc);
+ rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);
if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
- rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
+ rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc,
+ hwrate);
else
- rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
+ rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,
+ hwrate);
}
static int rt2x00queue_write_tx_data(struct queue_entry *entry,
@@ -556,33 +559,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
bool local)
{
struct ieee80211_tx_info *tx_info;
- struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
+ struct queue_entry *entry;
struct txentry_desc txdesc;
struct skb_frame_desc *skbdesc;
u8 rate_idx, rate_flags;
-
- if (unlikely(rt2x00queue_full(queue))) {
- ERROR(queue->rt2x00dev,
- "Dropping frame due to full tx queue %d.\n", queue->qid);
- return -ENOBUFS;
- }
-
- if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
- &entry->flags))) {
- ERROR(queue->rt2x00dev,
- "Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- queue->qid, DRV_PROJECT);
- return -EINVAL;
- }
+ int ret = 0;
/*
* Copy all TX descriptor information into txdesc,
* after that we are free to use the skb->cb array
* for our information.
*/
- entry->skb = skb;
- rt2x00queue_create_tx_descriptor(entry, &txdesc);
+ rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc);
/*
* All information is retrieved from the skb->cb array,
@@ -594,7 +582,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
rate_flags = tx_info->control.rates[0].flags;
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
- skbdesc->entry = entry;
skbdesc->tx_rate_idx = rate_idx;
skbdesc->tx_rate_flags = rate_flags;
@@ -623,9 +610,33 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
* for PCI devices.
*/
if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
- rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
+ rt2x00queue_insert_l2pad(skb, txdesc.header_length);
else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
- rt2x00queue_align_frame(entry->skb);
+ rt2x00queue_align_frame(skb);
+
+ spin_lock(&queue->tx_lock);
+
+ if (unlikely(rt2x00queue_full(queue))) {
+ ERROR(queue->rt2x00dev,
+ "Dropping frame due to full tx queue %d.\n", queue->qid);
+ ret = -ENOBUFS;
+ goto out;
+ }
+
+ entry = rt2x00queue_get_entry(queue, Q_INDEX);
+
+ if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
+ &entry->flags))) {
+ ERROR(queue->rt2x00dev,
+ "Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ queue->qid, DRV_PROJECT);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ skbdesc->entry = entry;
+ entry->skb = skb;
/*
* It could be possible that the queue was corrupted and this
@@ -635,7 +646,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
entry->skb = NULL;
- return -EIO;
+ ret = -EIO;
+ goto out;
}
set_bit(ENTRY_DATA_PENDING, &entry->flags);
@@ -644,7 +656,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
rt2x00queue_write_tx_descriptor(entry, &txdesc);
rt2x00queue_kick_tx_queue(queue, &txdesc);
- return 0;
+out:
+ spin_unlock(&queue->tx_lock);
+ return ret;
}
int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
@@ -698,7 +712,7 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
* after that we are free to use the skb->cb array
* for our information.
*/
- rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
+ rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc);
/*
* Fill in skb descriptor
@@ -1185,6 +1199,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
struct data_queue *queue, enum data_queue_qid qid)
{
mutex_init(&queue->status_lock);
+ spin_lock_init(&queue->tx_lock);
spin_lock_init(&queue->index_lock);
queue->rt2x00dev = rt2x00dev;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 167d45873dca..f2100f4ddcff 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -54,7 +54,7 @@
* @QID_RX: RX queue
* @QID_OTHER: None of the above (don't use, only present for completeness)
* @QID_BEACON: Beacon queue (value unspecified, don't send it to device)
- * @QID_ATIM: Atim queue (value unspeficied, don't send it to device)
+ * @QID_ATIM: Atim queue (value unspecified, don't send it to device)
*/
enum data_queue_qid {
QID_AC_VO = 0,
@@ -432,6 +432,7 @@ enum data_queue_flags {
* @flags: Entry flags, see &enum queue_entry_flags.
* @status_lock: The mutex for protecting the start/stop/flush
* handling on this queue.
+ * @tx_lock: Spinlock to serialize tx operations on this queue.
* @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or
* @index_crypt needs to be changed this lock should be grabbed to prevent
* index corruption due to concurrency.
@@ -458,6 +459,7 @@ struct data_queue {
unsigned long flags;
struct mutex status_lock;
+ spinlock_t tx_lock;
spinlock_t index_lock;
unsigned int count;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 8f90f6268077..b6b4542c2460 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -802,6 +802,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
int retval;
usb_dev = usb_get_dev(usb_dev);
+ usb_reset_device(usb_dev);
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9d35ec16a3a5..53110b83bf6e 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2982,6 +2982,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ad20953cbf05..6a93939f44e8 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2314,6 +2314,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.set_antenna = rt2x00mac_set_antenna,
.get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
+ .tx_frames_pending = rt2x00mac_tx_frames_pending,
};
static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 80db5cabc9b9..66b29dc07cc3 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -16,6 +16,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/delay.h>
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 5aee8b22d74e..45e14760c16e 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -21,6 +21,17 @@ config RTL8192SE
If you choose to build it as a module, it will be called rtl8192se
+config RTL8192DE
+ tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
+ depends on MAC80211 && EXPERIMENTAL
+ select FW_LOADER
+ select RTLWIFI
+ ---help---
+ This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe
+ wireless network adapters.
+
+ If you choose to build it as a module, it will be called rtl8192de
+
config RTL8192CU
tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
depends on MAC80211 && USB && EXPERIMENTAL
@@ -35,10 +46,10 @@ config RTL8192CU
config RTLWIFI
tristate
- depends on RTL8192CE || RTL8192CU || RTL8192SE
+ depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
default m
config RTL8192C_COMMON
tristate
- depends on RTL8192CE || RTL8192CU || RTL8192SE
+ depends on RTL8192CE || RTL8192CU
default m
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 7acce83c3785..97935c565bab 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -23,5 +23,6 @@ obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/
obj-$(CONFIG_RTL8192CE) += rtl8192ce/
obj-$(CONFIG_RTL8192CU) += rtl8192cu/
obj-$(CONFIG_RTL8192SE) += rtl8192se/
+obj-$(CONFIG_RTL8192DE) += rtl8192de/
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index ccb6da38fe22..0b598db38da9 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/ip.h>
#include "wifi.h"
#include "rc.h"
@@ -397,8 +399,8 @@ void rtl_init_rfkill(struct ieee80211_hw *hw)
radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
if (valid) {
- printk(KERN_INFO "rtlwifi: wireless switch is %s\n",
- rtlpriv->rfkill.rfkill_state ? "on" : "off");
+ pr_info("wireless switch is %s\n",
+ rtlpriv->rfkill.rfkill_state ? "on" : "off");
rtlpriv->rfkill.rfkill_state = radio_state;
@@ -523,7 +525,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
mac->opmode == NL80211_IFTYPE_ADHOC)
bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- if ((bw_40 == true) && sgi_40)
+ if (bw_40 && sgi_40)
tcb_desc->use_shortgi = true;
else if ((bw_40 == false) && sgi_20)
tcb_desc->use_shortgi = true;
@@ -756,18 +758,17 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
return false;
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
- ("%s ACT_ADDBAREQ From :" MAC_FMT "\n",
- is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
+ ("%s ACT_ADDBAREQ From :%pM\n",
+ is_tx ? "Tx" : "Rx", hdr->addr2));
break;
case ACT_ADDBARSP:
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
- ("%s ACT_ADDBARSP From :" MAC_FMT "\n",
- is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
+ ("%s ACT_ADDBARSP From :%pM\n",
+ is_tx ? "Tx" : "Rx", hdr->addr2));
break;
case ACT_DELBA:
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
- ("ACT_ADDBADEL From :" MAC_FMT "\n",
- MAC_ARG(hdr->addr2)));
+ ("ACT_ADDBADEL From :%pM\n", hdr->addr2));
break;
}
break;
@@ -888,7 +889,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
if (sta == NULL)
@@ -906,7 +906,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
return -EINVAL;
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
- tid_data = &sta_entry->tids[tid];
sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP;
ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid);
@@ -918,7 +917,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
if (sta == NULL)
@@ -936,7 +934,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
return -EINVAL;
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
- tid_data = &sta_entry->tids[tid];
sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL;
return 0;
@@ -1406,8 +1403,7 @@ MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
static int __init rtl_core_module_init(void)
{
if (rtl_rate_control_register())
- printk(KERN_ERR "rtlwifi: Unable to register rtl_rc,"
- "use default RC !!\n");
+ pr_err("Unable to register rtl_rc, use default RC !!\n");
return 0;
}
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 7295af0536b7..7babb6acd957 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "wifi.h"
#include "cam.h"
@@ -131,9 +133,9 @@ u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, "
- "ulUseDK=%x MacAddr" MAC_FMT "\n",
+ "ulUseDK=%x MacAddr %pM\n",
ul_entry_idx, ul_key_id, ul_enc_alg,
- ul_default_key, MAC_ARG(mac_addr)));
+ ul_default_key, mac_addr));
if (ul_key_id == TOTAL_CAM_ENTRY) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
@@ -347,7 +349,7 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
/* Remove from HW Security CAM */
memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
- printk(KERN_INFO "&&&&&&&&&del entry %d\n", i);
+ pr_info("&&&&&&&&&del entry %d\n", i);
}
}
return;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index d2ec2535aa3c..1bdc1aa305c0 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -335,8 +335,8 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
* before going offchannel, or dis-association or delete BA will
* happen by AP
*/
- if (rtlpriv->mac80211.offchan_deley) {
- rtlpriv->mac80211.offchan_deley = false;
+ if (rtlpriv->mac80211.offchan_delay) {
+ rtlpriv->mac80211.offchan_delay = false;
mdelay(50);
}
rtlphy->current_channel = wide_chan;
@@ -443,11 +443,11 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
sta_entry->wireless_mode = WIRELESS_MODE_G;
if (sta->supp_rates[0] <= 0xf)
sta_entry->wireless_mode = WIRELESS_MODE_B;
- if (sta->ht_cap.ht_supported == true)
+ if (sta->ht_cap.ht_supported)
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
} else if (rtlhal->current_bandtype == BAND_ON_5G) {
sta_entry->wireless_mode = WIRELESS_MODE_A;
- if (sta->ht_cap.ht_supported == true)
+ if (sta->ht_cap.ht_supported)
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
}
@@ -456,7 +456,7 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
sta_entry->wireless_mode = WIRELESS_MODE_G;
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
- ("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr)));
+ ("Add sta addr is %pM\n", sta->addr));
rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
}
return 0;
@@ -469,7 +469,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
struct rtl_sta_info *sta_entry;
if (sta) {
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
- ("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr)));
+ ("Remove sta addr is %pM\n", sta->addr));
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
sta_entry->wireless_mode = 0;
sta_entry->ratr_index = 0;
@@ -650,7 +650,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
("BSS_CHANGED_HT\n"));
rcu_read_lock();
- sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+ sta = get_sta(hw, vif, bss_conf->bssid);
if (sta) {
if (sta->ht_cap.ampdu_density >
mac->current_ampdu_density)
@@ -678,14 +678,14 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
(u8 *) bss_conf->bssid);
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
- (MAC_FMT "\n", MAC_ARG(bss_conf->bssid)));
+ ("%pM\n", bss_conf->bssid));
mac->vendor = PEER_UNKNOWN;
memcpy(mac->bssid, bss_conf->bssid, 6);
rtlpriv->cfg->ops->set_network_type(hw, vif->type);
rcu_read_lock();
- sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+ sta = get_sta(hw, vif, bss_conf->bssid);
if (!sta) {
rcu_read_unlock();
goto out;
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h
index 4b247db2861d..f02824a3b747 100644
--- a/drivers/net/wireless/rtlwifi/core.h
+++ b/drivers/net/wireless/rtlwifi/core.h
@@ -30,6 +30,8 @@
#ifndef __RTL_CORE_H__
#define __RTL_CORE_H__
+#include <net/mac80211.h>
+
#define RTL_SUPPORTED_FILTERS \
(FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | FIF_CONTROL | \
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index e4aa8687408c..160dd0685213 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -204,10 +204,5 @@ enum dbgp_flag_e {
} \
} while (0);
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) \
- ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2],\
- ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-
void rtl_dbgp_flag_init(struct ieee80211_hw *hw);
#endif
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 50de6f5d8a56..3fc21f60bb04 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -382,7 +382,7 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
}
}
- if (wordchanged == true)
+ if (wordchanged)
hdr_num++;
}
@@ -453,7 +453,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
base = offset * 8;
for (i = 0; i < 8; i++) {
- if (first_pg == true) {
+ if (first_pg) {
word_en &= ~(BIT(i / 2));
@@ -505,7 +505,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF,
rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
else
@@ -690,7 +690,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
}
}
- if (dataempty == true) {
+ if (dataempty) {
*readstate = PG_STATE_DATA;
} else {
*efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
@@ -925,7 +925,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct pgpkt_struct target_pkt;
u8 write_state = PG_STATE_HEADER;
- int continual = true, dataempty = true, result = true;
+ int continual = true, result = true;
u16 efuse_addr = 0;
u8 efuse_data;
u8 target_word_cnts = 0;
@@ -953,7 +953,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
(EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) {
if (write_state == PG_STATE_HEADER) {
- dataempty = true;
badworden = 0x0F;
RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
("efuse PG_STATE_HEADER\n"));
@@ -1176,13 +1175,12 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw)
{
int continual = true;
u16 efuse_addr = 0;
- u8 hoffset, hworden;
+ u8 hworden;
u8 efuse_data, word_cnts;
while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data)
&& (efuse_addr < EFUSE_MAX_SIZE)) {
if (efuse_data != 0xFF) {
- hoffset = (efuse_data >> 4) & 0x0F;
hworden = efuse_data & 0x0F;
word_cnts = efuse_calculate_word_cnts(hworden);
efuse_addr = efuse_addr + (word_cnts * 2) + 1;
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 254b64ba4bf6..5efd57833489 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -35,10 +35,10 @@
#include "efuse.h"
static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
- INTEL_VENDOR_ID,
- ATI_VENDOR_ID,
- AMD_VENDOR_ID,
- SIS_VENDOR_ID
+ PCI_VENDOR_ID_INTEL,
+ PCI_VENDOR_ID_ATI,
+ PCI_VENDOR_ID_AMD,
+ PCI_VENDOR_ID_SI
};
static const u8 ac_to_hwq[] = {
@@ -390,7 +390,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
u8 linkctrl_reg;
/*Link Control Register */
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);
pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg;
@@ -581,7 +581,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
fc = rtl_get_fc(skb);
if (ieee80211_is_nullfunc(fc)) {
if (ieee80211_has_pm(fc)) {
- rtlpriv->mac80211.offchan_deley = true;
+ rtlpriv->mac80211.offchan_delay = true;
rtlpriv->psc.state_inap = 1;
} else {
rtlpriv->psc.state_inap = 0;
@@ -622,10 +622,60 @@ tx_status_ok:
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
(rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtl_lps_leave(hw);
+ tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
}
}
+static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_rx_status rx_status)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
+ __le16 fc = rtl_get_fc(skb);
+ bool unicast = false;
+ struct sk_buff *uskb = NULL;
+ u8 *pdata;
+
+
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+ if (is_broadcast_ether_addr(hdr->addr1)) {
+ ;/*TODO*/
+ } else if (is_multicast_ether_addr(hdr->addr1)) {
+ ;/*TODO*/
+ } else {
+ unicast = true;
+ rtlpriv->stats.rxbytesunicast += skb->len;
+ }
+
+ rtl_is_special_data(hw, skb, false);
+
+ if (ieee80211_is_data(fc)) {
+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+ if (unicast)
+ rtlpriv->link_info.num_rx_inperiod++;
+ }
+
+ /* for sw lps */
+ rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
+ rtl_recognize_peer(hw, (void *)skb->data, skb->len);
+ if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
+ (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) &&
+ (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)))
+ return;
+
+ if (unlikely(!rtl_action_proc(hw, skb, false)))
+ return;
+
+ uskb = dev_alloc_skb(skb->len + 128);
+ memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
+ pdata = (u8 *)skb_put(uskb, skb->len);
+ memcpy(pdata, skb->data, skb->len);
+
+ ieee80211_rx_irqsafe(hw, uskb);
+}
+
static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -637,185 +687,112 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
u8 own;
u8 tmp_one;
u32 bufferaddress;
- bool unicast = false;
struct rtl_stats stats = {
.signal = 0,
.noise = -98,
.rate = 0,
};
+ int index = rtlpci->rx_ring[rx_queue_idx].idx;
/*RX NORMAL PKT */
while (count--) {
/*rx descriptor */
struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[
- rtlpci->rx_ring[rx_queue_idx].idx];
+ index];
/*rx pkt */
struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[
- rtlpci->rx_ring[rx_queue_idx].idx];
+ index];
+ struct sk_buff *new_skb = NULL;
own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
false, HW_DESC_OWN);
- if (own) {
- /*wait data to be filled by hardware */
- return;
- } else {
- struct ieee80211_hdr *hdr;
- __le16 fc;
- struct sk_buff *new_skb = NULL;
-
- rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
- &rx_status,
- (u8 *) pdesc, skb);
-
- new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
- if (unlikely(!new_skb)) {
- RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
- DBG_DMESG,
- ("can't alloc skb for rx\n"));
- goto done;
- }
+ /*wait data to be filled by hardware */
+ if (own)
+ break;
- pci_unmap_single(rtlpci->pdev,
- *((dma_addr_t *) skb->cb),
- rtlpci->rxbuffersize,
- PCI_DMA_FROMDEVICE);
+ rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
+ &rx_status,
+ (u8 *) pdesc, skb);
- skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
- false,
- HW_DESC_RXPKT_LEN));
- skb_reserve(skb,
- stats.rx_drvinfo_size + stats.rx_bufshift);
+ if (stats.crc || stats.hwerror)
+ goto done;
- /*
- *NOTICE This can not be use for mac80211,
- *this is done in mac80211 code,
- *if you done here sec DHCP will fail
- *skb_trim(skb, skb->len - 4);
- */
+ new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
+ if (unlikely(!new_skb)) {
+ RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
+ DBG_DMESG,
+ ("can't alloc skb for rx\n"));
+ goto done;
+ }
- hdr = rtl_get_hdr(skb);
- fc = rtl_get_fc(skb);
-
- if (!stats.crc && !stats.hwerror) {
- memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
- sizeof(rx_status));
-
- if (is_broadcast_ether_addr(hdr->addr1)) {
- ;/*TODO*/
- } else if (is_multicast_ether_addr(hdr->addr1)) {
- ;/*TODO*/
- } else {
- unicast = true;
- rtlpriv->stats.rxbytesunicast +=
- skb->len;
- }
-
- rtl_is_special_data(hw, skb, false);
-
- if (ieee80211_is_data(fc)) {
- rtlpriv->cfg->ops->led_control(hw,
- LED_CTL_RX);
-
- if (unicast)
- rtlpriv->link_info.
- num_rx_inperiod++;
- }
-
- /* for sw lps */
- rtl_swlps_beacon(hw, (void *)skb->data,
- skb->len);
- rtl_recognize_peer(hw, (void *)skb->data,
- skb->len);
- if ((rtlpriv->mac80211.opmode ==
- NL80211_IFTYPE_AP) &&
- (rtlpriv->rtlhal.current_bandtype ==
- BAND_ON_2_4G) &&
- (ieee80211_is_beacon(fc) ||
- ieee80211_is_probe_resp(fc))) {
- dev_kfree_skb_any(skb);
- } else {
- if (unlikely(!rtl_action_proc(hw, skb,
- false))) {
- dev_kfree_skb_any(skb);
- } else {
- struct sk_buff *uskb = NULL;
- u8 *pdata;
- uskb = dev_alloc_skb(skb->len
- + 128);
- memcpy(IEEE80211_SKB_RXCB(uskb),
- &rx_status,
- sizeof(rx_status));
- pdata = (u8 *)skb_put(uskb,
- skb->len);
- memcpy(pdata, skb->data,
- skb->len);
- dev_kfree_skb_any(skb);
-
- ieee80211_rx_irqsafe(hw, uskb);
- }
- }
- } else {
- dev_kfree_skb_any(skb);
- }
+ pci_unmap_single(rtlpci->pdev,
+ *((dma_addr_t *) skb->cb),
+ rtlpci->rxbuffersize,
+ PCI_DMA_FROMDEVICE);
- if (((rtlpriv->link_info.num_rx_inperiod +
- rtlpriv->link_info.num_tx_inperiod) > 8) ||
- (rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtl_lps_leave(hw);
- }
+ skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false,
+ HW_DESC_RXPKT_LEN));
+ skb_reserve(skb, stats.rx_drvinfo_size + stats.rx_bufshift);
- skb = new_skb;
+ /*
+ * NOTICE This can not be use for mac80211,
+ * this is done in mac80211 code,
+ * if you done here sec DHCP will fail
+ * skb_trim(skb, skb->len - 4);
+ */
- rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci->
- rx_ring
- [rx_queue_idx].
- idx] = skb;
- *((dma_addr_t *) skb->cb) =
+ _rtl_receive_one(hw, skb, rx_status);
+
+ if (((rtlpriv->link_info.num_rx_inperiod +
+ rtlpriv->link_info.num_tx_inperiod) > 8) ||
+ (rtlpriv->link_info.num_rx_inperiod > 2)) {
+ tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
+ }
+
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+
+ rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb;
+ *((dma_addr_t *) skb->cb) =
pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
rtlpci->rxbuffersize,
PCI_DMA_FROMDEVICE);
- }
done:
bufferaddress = (*((dma_addr_t *)skb->cb));
tmp_one = 1;
rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
HW_DESC_RXBUFF_ADDR,
(u8 *)&bufferaddress);
- rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
- (u8 *)&tmp_one);
rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
HW_DESC_RXPKT_LEN,
(u8 *)&rtlpci->rxbuffersize);
- if (rtlpci->rx_ring[rx_queue_idx].idx ==
- rtlpci->rxringcount - 1)
+ if (index == rtlpci->rxringcount - 1)
rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
HW_DESC_RXERO,
(u8 *)&tmp_one);
- rtlpci->rx_ring[rx_queue_idx].idx =
- (rtlpci->rx_ring[rx_queue_idx].idx + 1) %
- rtlpci->rxringcount;
+ rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
+ (u8 *)&tmp_one);
+
+ index = (index + 1) % rtlpci->rxringcount;
}
+ rtlpci->rx_ring[rx_queue_idx].idx = index;
}
static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
{
struct ieee80211_hw *hw = dev_id;
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
unsigned long flags;
u32 inta = 0;
u32 intb = 0;
- if (rtlpci->irq_enabled == 0)
- return IRQ_HANDLED;
-
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
/*read ISR: 4/8bytes */
@@ -938,6 +915,11 @@ static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
_rtl_pci_tx_chk_waitq(hw);
}
+static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw)
+{
+ rtl_lps_leave(hw);
+}
+
static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1036,6 +1018,9 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
(void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
(unsigned long)hw);
+ tasklet_init(&rtlpriv->works.ips_leave_tasklet,
+ (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet,
+ (unsigned long)hw);
}
static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
@@ -1505,6 +1490,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
synchronize_irq(rtlpci->pdev->irq);
tasklet_kill(&rtlpriv->works.irq_tasklet);
+ tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
flush_workqueue(rtlpriv->works.rtl_wq);
destroy_workqueue(rtlpriv->works.rtl_wq);
@@ -1579,6 +1565,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
set_hal_stop(rtlhal);
rtlpriv->cfg->ops->disable_interrupt(hw);
+ tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
while (ppsc->rfchange_inprogress) {
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 671b1f5aa0cf..c53c62046747 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -62,12 +62,6 @@
.subdevice = PCI_ANY_ID,\
.driver_data = (kernel_ulong_t)&(cfg)
-#define INTEL_VENDOR_ID 0x8086
-#define SIS_VENDOR_ID 0x1039
-#define ATI_VENDOR_ID 0x1002
-#define ATI_DEVICE_ID 0x7914
-#define AMD_VENDOR_ID 0x1022
-
#define PCI_MAX_BRIDGE_NUMBER 255
#define PCI_MAX_DEVICES 32
#define PCI_MAX_FUNCTION 8
@@ -75,11 +69,6 @@
#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */
#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */
-#define PCI_CLASS_BRIDGE_DEV 0x06
-#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04
-#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10
-#define PCI_CAP_ID_EXP 0x10
-
#define U1DONTCARE 0xFF
#define U2DONTCARE 0xFFFF
#define U4DONTCARE 0xFFFFFFFF
@@ -169,7 +158,6 @@ struct rtl_pci {
bool first_init;
bool being_init_adapter;
bool init_ready;
- bool irq_enabled;
/*Tx */
struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT];
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index 39b0297ce925..a693feffbe72 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -68,6 +68,7 @@ bool rtl_ps_disable_nic(struct ieee80211_hw *hw)
/*<2> Disable Interrupt */
rtlpriv->cfg->ops->disable_interrupt(hw);
+ tasklet_kill(&rtlpriv->works.irq_tasklet);
/*<3> Disable Adapter */
rtlpriv->cfg->ops->hw_disable(hw);
@@ -78,65 +79,18 @@ EXPORT_SYMBOL(rtl_ps_disable_nic);
bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
enum rf_pwrstate state_toset,
- u32 changesource, bool protect_or_not)
+ u32 changesource)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- enum rf_pwrstate rtstate;
bool actionallowed = false;
- u16 rfwait_cnt = 0;
- unsigned long flag;
-
- /*protect_or_not = true; */
-
- if (protect_or_not)
- goto no_protect;
-
- /*
- *Only one thread can change
- *the RF state at one time, and others
- *should wait to be executed.
- */
- while (true) {
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- if (ppsc->rfchange_inprogress) {
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
- flag);
-
- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
- ("RF Change in progress!"
- "Wait to set..state_toset(%d).\n",
- state_toset));
-
- /* Set RF after the previous action is done. */
- while (ppsc->rfchange_inprogress) {
- rfwait_cnt++;
- mdelay(1);
-
- /*
- *Wait too long, return false to avoid
- *to be stuck here.
- */
- if (rfwait_cnt > 100)
- return false;
- }
- } else {
- ppsc->rfchange_inprogress = true;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
- flag);
- break;
- }
- }
-
-no_protect:
- rtstate = ppsc->rfpwr_state;
switch (state_toset) {
case ERFON:
ppsc->rfoff_reason &= (~changesource);
if ((changesource == RF_CHANGE_BY_HW) &&
- (ppsc->hwradiooff == true)) {
+ (ppsc->hwradiooff)) {
ppsc->hwradiooff = false;
}
@@ -172,12 +126,6 @@ no_protect:
if (actionallowed)
rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
- if (!protect_or_not) {
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- ppsc->rfchange_inprogress = false;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
- }
-
return actionallowed;
}
EXPORT_SYMBOL(rtl_ps_set_rf_state);
@@ -200,8 +148,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
}
}
- rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
- RF_CHANGE_BY_IPS, false);
+ rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);
if (ppsc->inactive_pwrstate == ERFOFF &&
rtlhal->interface == INTF_PCI) {
@@ -289,12 +236,11 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
enum rf_pwrstate rtstate;
- unsigned long flags;
if (mac->opmode != NL80211_IFTYPE_STATION)
return;
- spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
+ spin_lock(&rtlpriv->locks.ips_lock);
if (ppsc->inactiveps) {
rtstate = ppsc->rfpwr_state;
@@ -310,7 +256,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
+ spin_unlock(&rtlpriv->locks.ips_lock);
}
/*for FW LPS*/
@@ -428,7 +374,6 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
- unsigned long flag;
if (!ppsc->fwctrl_lps)
return;
@@ -449,7 +394,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
if (mac->link_state != MAC80211_LINKED)
return;
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
/* Idle for a while if we connect to AP a while ago. */
if (mac->cnt_after_linked >= 2) {
@@ -461,7 +406,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_unlock(&rtlpriv->locks.lps_lock);
}
/*Leave the leisure power save mode.*/
@@ -470,9 +415,8 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- unsigned long flag;
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
if (ppsc->fwctrl_lps) {
if (ppsc->dot11_psmode != EACTIVE) {
@@ -493,7 +437,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
rtl_lps_set_psmode(hw, EACTIVE);
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_unlock(&rtlpriv->locks.lps_lock);
}
/* For sw LPS*/
@@ -582,7 +526,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- unsigned long flag;
if (!rtlpriv->psc.swctrl_lps)
return;
@@ -595,9 +538,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
}
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
- rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
+ rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
+ spin_unlock(&rtlpriv->locks.lps_lock);
}
void rtl_swlps_rfon_wq_callback(void *data)
@@ -614,7 +557,6 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- unsigned long flag;
u8 sleep_intv;
if (!rtlpriv->psc.sw_ps_enabled)
@@ -631,16 +573,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
if (rtlpriv->link_info.busytraffic)
return;
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- if (rtlpriv->psc.rfchange_inprogress) {
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
- return;
- }
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
-
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
- rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false);
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
+ rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
+ spin_unlock(&rtlpriv->locks.lps_lock);
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h
index e3bf89840370..84628e6041c7 100644
--- a/drivers/net/wireless/rtlwifi/ps.h
+++ b/drivers/net/wireless/rtlwifi/ps.h
@@ -33,8 +33,7 @@
#define MAX_SW_LPS_SLEEP_INTV 5
bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
- enum rf_pwrstate state_toset, u32 changesource,
- bool protect_or_not);
+ enum rf_pwrstate state_toset, u32 changesource);
bool rtl_ps_enable_nic(struct ieee80211_hw *hw);
bool rtl_ps_disable_nic(struct ieee80211_hw *hw);
void rtl_ips_nic_off(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index 30da68a77786..539df66dce0a 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -200,7 +200,7 @@ static void rtl_tx_status(void *ppriv,
if (sta) {
/* Check if aggregation has to be enabled for this tid */
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
- if ((sta->ht_cap.ht_supported == true) &&
+ if ((sta->ht_cap.ht_supported) &&
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
if (ieee80211_is_data_qos(fc)) {
u8 tid = rtl_get_tid(skb);
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c
index 8f6718f163e5..9fedb1f70919 100644
--- a/drivers/net/wireless/rtlwifi/regd.c
+++ b/drivers/net/wireless/rtlwifi/regd.c
@@ -303,22 +303,6 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy,
return;
}
-static void _rtl_dump_channel_map(struct wiphy *wiphy)
-{
- enum ieee80211_band band;
- struct ieee80211_supported_band *sband;
- struct ieee80211_channel *ch;
- unsigned int i;
-
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
- if (!wiphy->bands[band])
- continue;
- sband = wiphy->bands[band];
- for (i = 0; i < sband->n_channels; i++)
- ch = &sband->channels[i];
- }
-}
-
static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
struct regulatory_request *request,
struct rtl_regulatory *reg)
@@ -336,8 +320,6 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
break;
}
- _rtl_dump_channel_map(wiphy);
-
return 0;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 97183829b9be..a00774e7090d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -474,7 +474,7 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- if (mac->act_scanning == true)
+ if (mac->act_scanning)
return;
if (mac->link_state >= MAC80211_LINKED)
@@ -670,7 +670,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
int i;
bool is2t = IS_92C_SERIAL(rtlhal->version);
- u8 txpwr_level[2] = {0, 0};
+ s8 txpwr_level[2] = {0, 0};
u8 ofdm_min_index = 6, rf;
rtlpriv->dm.txpower_trackinginit = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 50303e1adff1..49a064bdbce6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/firmware.h>
#include "../wifi.h"
#include "../pci.h"
@@ -224,8 +226,7 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
u32 fwsize;
enum version_8192c version = rtlhal->version;
- printk(KERN_INFO "rtl8192c: Loading firmware file %s\n",
- rtlpriv->cfg->fw_name);
+ pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
if (!rtlhal->pfirmware)
return 1;
@@ -546,7 +547,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring;
struct rtl_tx_desc *pdesc;
- u8 own;
unsigned long flags;
struct sk_buff *pskb = NULL;
@@ -559,7 +559,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
pdesc = &ring->desc[0];
- own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index d2cc81586a6a..3b11642d3f7d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -1253,10 +1253,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
const u32 retrycount = 2;
- u32 bbvalue;
-
if (t == 0) {
- bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+ /* dummy read */
+ rtl_get_bbreg(hw, 0x800, MASKDWORD);
_rtl92c_phy_save_adda_registers(hw, adda_reg,
rtlphy->adda_backup, 16);
@@ -1762,8 +1761,7 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
long result[4][8];
u8 i, final_candidate;
bool patha_ok, pathb_ok;
- long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
- reg_ecc, reg_tmp = 0;
+ long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4, reg_tmp = 0;
bool is12simular, is13simular, is23simular;
bool start_conttx = false, singletone = false;
u32 iqk_bb_reg[10] = {
@@ -1841,21 +1839,17 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
reg_e94 = result[i][0];
reg_e9c = result[i][1];
reg_ea4 = result[i][2];
- reg_eac = result[i][3];
reg_eb4 = result[i][4];
reg_ebc = result[i][5];
reg_ec4 = result[i][6];
- reg_ecc = result[i][7];
}
if (final_candidate != 0xff) {
rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
reg_ea4 = result[final_candidate][2];
- reg_eac = result[final_candidate][3];
rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
reg_ec4 = result[final_candidate][6];
- reg_ecc = result[final_candidate][7];
patha_ok = pathb_ok = true;
} else {
rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index defb4370cf74..a3deaefa788c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -488,7 +488,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_CORRECT_TSF:{
u8 btype_ibss = ((u8 *) (val))[0];
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92ce_stop_tx_beacon(hw);
_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3));
@@ -500,7 +500,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92ce_resume_tx_beacon(hw);
break;
@@ -763,11 +763,9 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
u8 reg_bw_opmode;
- u32 reg_ratr, reg_prsr;
+ u32 reg_prsr;
reg_bw_opmode = BW_OPMODE_20MHZ;
- reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
- RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
@@ -1123,7 +1121,7 @@ void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (check_bssid == true) {
+ if (check_bssid) {
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *) (&reg_rcr));
@@ -1185,7 +1183,6 @@ void rtl92ce_enable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
- rtlpci->irq_enabled = true;
}
void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
@@ -1195,7 +1192,7 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
- rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
}
static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
@@ -1586,7 +1583,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
for (i = 0; i < 6; i += 2) {
@@ -1595,7 +1592,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr)));
+ ("%pM\n", rtlefuse->dev_addr));
_rtl92ce_read_txpower_info_from_hwpg(hw,
rtlefuse->autoload_failflag,
@@ -1969,7 +1966,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+ enum rf_pwrstate e_rfpowerstate_toset;
u8 u1tmp;
bool actuallyset = false;
unsigned long flag;
@@ -1989,15 +1986,13 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
}
- cur_rfstate = ppsc->rfpwr_state;
-
rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,
REG_MAC_PINMUX_CFG)&~(BIT(3)));
u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
- if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+ if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
("GPIOChangeRF - HW Radio ON, RF ON\n"));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
index 9dd1ed7b6422..28a1a707d09c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
@@ -84,7 +84,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (pcipriv->ledctl.led_opendrain == true)
+ if (pcipriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, REG_LEDCFG2,
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
index abe0fcc75368..592a10ac5929 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
@@ -46,13 +46,12 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, readback_value, bitshift;
struct rtl_phy *rtlphy = &(rtlpriv->phy);
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
"rfpath(%#x), bitmask(%#x)\n",
regaddr, rfpath, bitmask));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (rtlphy->rf_mode != RF_OP_BY_FW) {
original_value = _rtl92c_phy_rf_serial_read(hw,
@@ -65,7 +64,7 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
readback_value = (original_value & bitmask) >> bitshift;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
("regaddr(%#x), rfpath(%#x), "
@@ -120,13 +119,12 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 original_value, bitshift;
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
regaddr, bitmask, data, rfpath));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (rtlphy->rf_mode != RF_OP_BY_FW) {
if (bitmask != RFREG_OFFSET_MASK) {
@@ -153,7 +151,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
_rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
}
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
"bitmask(%#x), data(%#x), "
@@ -281,7 +279,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
{
int i;
- bool rtstatus = true;
u32 *radioa_array_table;
u32 *radiob_array_table;
u16 radioa_arraylen, radiob_arraylen;
@@ -308,7 +305,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
- rtstatus = true;
switch (rfpath) {
case RF90_PATH_A:
for (i = 0; i < radioa_arraylen; i = i + 2) {
@@ -521,7 +517,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
u8 i, queue_id;
struct rtl8192_tx_ring *ring = NULL;
- ppsc->set_rfpowerstate_inprogress = true;
switch (rfpwr_state) {
case ERFON:{
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -617,7 +612,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
}
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
return bresult;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index 598cecc63f41..ba5ff0411f0a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -1074,10 +1074,10 @@
#define _SRL(x) (((x) & 0x3F) << 8)
#define _SIFS_CCK_CTX(x) ((x) & 0xFF)
-#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8);
+#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8)
#define _SIFS_OFDM_CTX(x) ((x) & 0xFF)
-#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8);
+#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8)
#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8)
@@ -1203,7 +1203,9 @@
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_LOAD 1
+#define HWSET_MAX_SIZE 128
#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE
+#define EFUSE_MAX_SECTION 16
#define WL_HWPDN_EN BIT(0)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
index 90d0f2cf3b27..d3b01e6023ba 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
@@ -76,7 +76,7 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
if (rtlefuse->eeprom_regulatory != 0)
turbo_scanoff = true;
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 54b2bd53d36a..230bbe900d8d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -225,7 +225,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct phy_sts_cck_8192s_t *cck_buf;
- s8 rx_pwr_all, rx_pwr[4];
+ s8 rx_pwr_all = 0, rx_pwr[4];
u8 evm, pwdb_all, rf_rx_num = 0;
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
@@ -592,7 +592,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, c_fc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -604,7 +603,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
c_fc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid =
((IEEE80211_FTYPE_CTL != type) &&
@@ -680,7 +678,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
stats->rx_bufshift);
@@ -929,9 +927,10 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
{
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
@@ -945,6 +944,7 @@ void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
+ wmb();
SET_RX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
@@ -968,7 +968,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
{
u32 ret = 0;
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(p_desc);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 52e2af58c1ed..814c05df51e8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "../efuse.h"
#include "../base.h"
@@ -337,7 +339,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
rtlefuse->board_type = boardType;
if (IS_HIGHT_PA(rtlefuse->board_type))
rtlefuse->external_pa = 1;
- printk(KERN_INFO "rtl8192cu: Board Type %x\n", rtlefuse->board_type);
+ pr_info("Board Type %x\n", rtlefuse->board_type);
#ifdef CONFIG_ANTENNA_DIVERSITY
/* Antenna Diversity setting. */
@@ -346,8 +348,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
else
rtl_efuse->antenna_cfg = registry_par->antdiv_cfg; /* 0:OFF, */
- printk(KERN_INFO "rtl8192cu: Antenna Config %x\n",
- rtl_efuse->antenna_cfg);
+ pr_info("Antenna Config %x\n", rtl_efuse->antenna_cfg);
#endif
}
@@ -384,71 +385,57 @@ static void _update_bt_param(_adapter *padapter)
pbtpriv->bBTNonTrafficModeSet = _FALSE;
pbtpriv->CurrentState = 0;
pbtpriv->PreviousState = 0;
- printk(KERN_INFO "rtl8192cu: BT Coexistance = %s\n",
- (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
+ pr_info("BT Coexistance = %s\n",
+ (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
if (pbtpriv->BT_Coexist) {
if (pbtpriv->BT_Ant_Num == Ant_x2)
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "Ant_Num = Antx2\n");
+ pr_info("BlueTooth BT_Ant_Num = Antx2\n");
else if (pbtpriv->BT_Ant_Num == Ant_x1)
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "Ant_Num = Antx1\n");
+ pr_info("BlueTooth BT_Ant_Num = Antx1\n");
switch (pbtpriv->BT_CoexistType) {
case BT_2Wire:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_2Wire\n");
+ pr_info("BlueTooth BT_CoexistType = BT_2Wire\n");
break;
case BT_ISSC_3Wire:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_ISSC_3Wire\n");
+ pr_info("BlueTooth BT_CoexistType = BT_ISSC_3Wire\n");
break;
case BT_Accel:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_Accel\n");
+ pr_info("BlueTooth BT_CoexistType = BT_Accel\n");
break;
case BT_CSR_BC4:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_CSR_BC4\n");
+ pr_info("BlueTooth BT_CoexistType = BT_CSR_BC4\n");
break;
case BT_CSR_BC8:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_CSR_BC8\n");
+ pr_info("BlueTooth BT_CoexistType = BT_CSR_BC8\n");
break;
case BT_RTL8756:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = BT_RTL8756\n");
+ pr_info("BlueTooth BT_CoexistType = BT_RTL8756\n");
break;
default:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
- "CoexistType = Unknown\n");
+ pr_info("BlueTooth BT_CoexistType = Unknown\n");
break;
}
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Ant_isolation = %d\n",
- pbtpriv->BT_Ant_isolation);
+ pr_info("BlueTooth BT_Ant_isolation = %d\n",
+ pbtpriv->BT_Ant_isolation);
switch (pbtpriv->BT_Service) {
case BT_OtherAction:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_OtherAction\n");
+ pr_info("BlueTooth BT_Service = BT_OtherAction\n");
break;
case BT_SCO:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_SCO\n");
+ pr_info("BlueTooth BT_Service = BT_SCO\n");
break;
case BT_Busy:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_Busy\n");
+ pr_info("BlueTooth BT_Service = BT_Busy\n");
break;
case BT_OtherBusy:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_OtherBusy\n");
+ pr_info("BlueTooth BT_Service = BT_OtherBusy\n");
break;
default:
- printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
- "BT_Idle\n");
+ pr_info("BlueTooth BT_Service = BT_Idle\n");
break;
}
- printk(KERN_INFO "rtl8192cu: BT_RadioSharedType = 0x%x\n",
- pbtpriv->BT_RadioSharedType);
+ pr_info("BT_RadioSharedType = 0x%x\n",
+ pbtpriv->BT_RadioSharedType);
}
}
@@ -520,13 +507,13 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
for (i = 0; i < 6; i += 2) {
usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
}
- printk(KERN_INFO "rtl8192cu: MAC address: %pM\n", rtlefuse->dev_addr);
+ pr_info("MAC address: %pM\n", rtlefuse->dev_addr);
_rtl92cu_read_txpower_info_from_hwpg(hw,
rtlefuse->autoload_failflag, hwinfo);
rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
@@ -665,7 +652,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
rtl_write_word(rtlpriv, REG_APS_FSMCO, value16);
do {
if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) {
- printk(KERN_INFO "rtl8192cu: MAC auto ON okay!\n");
+ pr_info("MAC auto ON okay!\n");
break;
}
if (pollingCount++ > 100) {
@@ -819,7 +806,7 @@ static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw,
}
_rtl92c_init_chipN_reg_priority(hw, value, value, value, value,
value, value);
- printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+ pr_info("Tx queue select: 0x%02x\n", queue_sel);
}
static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
@@ -863,7 +850,7 @@ static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
hiQ = valueHi;
}
_rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
- printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+ pr_info("Tx queue select: 0x%02x\n", queue_sel);
}
static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw,
@@ -1594,7 +1581,7 @@ static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
default:
break;
}
- if (filterout_non_associated_bssid == true) {
+ if (filterout_non_associated_bssid) {
if (IS_NORMAL_CHIP(rtlhal->version)) {
switch (rtlphy->current_io_type) {
case IO_CMD_RESUME_DM_BY_SCAN:
@@ -2155,7 +2142,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_CORRECT_TSF:{
u8 btype_ibss = ((u8 *) (val))[0];
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92cu_stop_tx_beacon(hw);
_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf &
@@ -2163,7 +2150,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
rtl_write_dword(rtlpriv, REG_TSFTR + 4,
(u32)((mac->tsf >> 32) & 0xffffffff));
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92cu_resume_tx_beacon(hw);
break;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
index 332c74348a69..2ff9d8314e7b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
@@ -82,7 +82,7 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (usbpriv->ledctl.led_opendrain == true)
+ if (usbpriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, REG_LEDCFG2,
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index f8514cba17b6..194fc693c1fa 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -26,6 +26,9 @@
* Larry Finger <Larry.Finger@lwfinger.net>
*
****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include "../wifi.h"
@@ -213,14 +216,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
for (i = 0; i < (boundary - 1); i++) {
rst = rtl92c_llt_write(hw, i , i + 1);
if (true != rst) {
- printk(KERN_ERR "===> %s #1 fail\n", __func__);
+ pr_err("===> %s #1 fail\n", __func__);
return rst;
}
}
/* end of list */
rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
if (true != rst) {
- printk(KERN_ERR "===> %s #2 fail\n", __func__);
+ pr_err("===> %s #2 fail\n", __func__);
return rst;
}
/* Make the other pages as ring buffer
@@ -231,14 +234,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
rst = rtl92c_llt_write(hw, i, (i + 1));
if (true != rst) {
- printk(KERN_ERR "===> %s #3 fail\n", __func__);
+ pr_err("===> %s #3 fail\n", __func__);
return rst;
}
}
/* Let last entry point to the start entry of ring buffer */
rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
if (true != rst) {
- printk(KERN_ERR "===> %s #4 fail\n", __func__);
+ pr_err("===> %s #4 fail\n", __func__);
return rst;
}
return rst;
@@ -380,13 +383,11 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
0xFFFFFFFF);
- rtlpci->irq_enabled = true;
} else {
rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
0xFFFFFFFF);
- rtlusb->irq_enabled = true;
}
}
@@ -398,16 +399,9 @@ void rtl92c_init_interrupt(struct ieee80211_hw *hw)
void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
- if (IS_HARDWARE_TYPE_8192CE(rtlhal))
- rtlpci->irq_enabled = false;
- else if (IS_HARDWARE_TYPE_8192CU(rtlhal))
- rtlusb->irq_enabled = false;
}
void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
@@ -1113,7 +1107,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, cpu_fc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -1124,7 +1117,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
cpu_fc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid =
((IEEE80211_FTYPE_CTL != type) &&
(!compare_ether_addr(mac->bssid,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
index 9a3d0239e27e..72852900df84 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
@@ -470,7 +470,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
u8 i, queue_id;
struct rtl8192_tx_ring *ring = NULL;
- ppsc->set_rfpowerstate_inprogress = true;
switch (rfpwr_state) {
case ERFON:
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -590,7 +589,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
}
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
return bresult;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index c7576ec4744e..17a8e9628512 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -82,7 +82,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
(rtlefuse->external_pa))
turbo_scanoff = true;
}
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
if (turbo_scanoff) {
@@ -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_LEVEL1) {
+ TXHIGHPWRLEVEL_LEVEL2) {
tx_agc[RF90_PATH_A] = 0x00000000;
tx_agc[RF90_PATH_B] = 0x00000000;
} else{
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 3a92ba3c4a1e..906e7aa55bc3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -342,7 +342,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
(u8)GET_RX_DESC_RX_MCS(pdesc),
(bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
p_drvinfo);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile
new file mode 100644
index 000000000000..e3213c8264b6
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile
@@ -0,0 +1,14 @@
+rtl8192de-objs := \
+ dm.o \
+ fw.o \
+ hw.o \
+ led.o \
+ phy.o \
+ rf.o \
+ sw.o \
+ table.o \
+ trx.o
+
+obj-$(CONFIG_RTL8192DE) += rtl8192de.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
new file mode 100644
index 000000000000..f0f5f9bfbb7b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
@@ -0,0 +1,269 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_DEF_H__
+#define __RTL92D_DEF_H__
+
+/* Min Spacing related settings. */
+#define MAX_MSS_DENSITY_2T 0x13
+#define MAX_MSS_DENSITY_1T 0x0A
+
+#define RF6052_MAX_TX_PWR 0x3F
+#define RF6052_MAX_REG 0x3F
+#define RF6052_MAX_PATH 2
+
+#define HAL_RETRY_LIMIT_INFRA 48
+#define HAL_RETRY_LIMIT_AP_ADHOC 7
+
+#define PHY_RSSI_SLID_WIN_MAX 100
+#define PHY_LINKQUALITY_SLID_WIN_MAX 20
+#define PHY_BEACON_RSSI_SLID_WIN_MAX 10
+
+#define RESET_DELAY_8185 20
+
+#define RT_IBSS_INT_MASKS (IMR_BCNINT | IMR_TBDOK | IMR_TBDER)
+#define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK)
+
+#define NUM_OF_FIRMWARE_QUEUE 10
+#define NUM_OF_PAGES_IN_FW 0x100
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x2
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xA1
+
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00
+
+#define MAX_LINES_HWCONFIG_TXT 1000
+#define MAX_BYTES_LINE_HWCONFIG_TXT 256
+
+#define SW_THREE_WIRE 0
+#define HW_THREE_WIRE 2
+
+#define BT_DEMO_BOARD 0
+#define BT_QA_BOARD 1
+#define BT_FPGA 2
+
+#define RX_SMOOTH_FACTOR 20
+
+#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
+#define HAL_PRIME_CHNL_OFFSET_LOWER 1
+#define HAL_PRIME_CHNL_OFFSET_UPPER 2
+
+#define MAX_H2C_QUEUE_NUM 10
+
+#define RX_MPDU_QUEUE 0
+#define RX_CMD_QUEUE 1
+#define RX_MAX_QUEUE 2
+
+#define C2H_RX_CMD_HDR_LEN 8
+#define GET_C2H_CMD_CMD_LEN(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 0, 16)
+#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 16, 8)
+#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 24, 7)
+#define GET_C2H_CMD_CONTINUE(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 31, 1)
+#define GET_C2H_CMD_CONTENT(__prxhdr) \
+ ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN)
+
+#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8)
+#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8)
+#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16)
+#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5)
+#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1)
+#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5)
+#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1)
+#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
+#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 */
+
+/* for 92D */
+#define CHIP_92D BIT(8)
+#define CHIP_92D_SINGLEPHY BIT(9)
+#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,
+ RF_OP_MAX
+};
+
+enum rtl_desc_qsel {
+ QSLT_BK = 0x2,
+ QSLT_BE = 0x0,
+ QSLT_VI = 0x5,
+ QSLT_VO = 0x7,
+ QSLT_BEACON = 0x10,
+ QSLT_HIGH = 0x11,
+ QSLT_MGNT = 0x12,
+ QSLT_CMD = 0x13,
+};
+
+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,
+ CHPL_ETSI = 2,
+ CHPL_SPAIN = 3,
+ CHPL_FRANCE = 4,
+ CHPL_MKK = 5,
+ CHPL_MKK1 = 6,
+ CHPL_ISRAEL = 7,
+ CHPL_TELEC = 8,
+ CHPL_GLOBAL = 9,
+ CHPL_WORLD = 10,
+};
+
+struct phy_sts_cck_8192d {
+ u8 adc_pwdb_X[4];
+ u8 sq_rpt;
+ u8 cck_agc_rpt;
+};
+
+struct h2c_cmd_8192c {
+ u8 element_id;
+ u32 cmd_len;
+ u8 *p_cmdbuffer;
+};
+
+struct txpower_info {
+ u8 cck_index[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht40_1sindex[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht40_2sindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht20indexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ofdmindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht40maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht20maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 tssi_a[3]; /* 5GL/5GM/5GH */
+ u8 tssi_b[3];
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
new file mode 100644
index 000000000000..3cd0736fe8e1
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
@@ -0,0 +1,1355 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+
+#define UNDEC_SM_PWDB entry_min_undecoratedsmoothed_pwdb
+
+struct dig_t de_digtable;
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = {
+ 0x7f8001fe, /* 0, +6.0dB */
+ 0x788001e2, /* 1, +5.5dB */
+ 0x71c001c7, /* 2, +5.0dB */
+ 0x6b8001ae, /* 3, +4.5dB */
+ 0x65400195, /* 4, +4.0dB */
+ 0x5fc0017f, /* 5, +3.5dB */
+ 0x5a400169, /* 6, +3.0dB */
+ 0x55400155, /* 7, +2.5dB */
+ 0x50800142, /* 8, +2.0dB */
+ 0x4c000130, /* 9, +1.5dB */
+ 0x47c0011f, /* 10, +1.0dB */
+ 0x43c0010f, /* 11, +0.5dB */
+ 0x40000100, /* 12, +0dB */
+ 0x3c8000f2, /* 13, -0.5dB */
+ 0x390000e4, /* 14, -1.0dB */
+ 0x35c000d7, /* 15, -1.5dB */
+ 0x32c000cb, /* 16, -2.0dB */
+ 0x300000c0, /* 17, -2.5dB */
+ 0x2d4000b5, /* 18, -3.0dB */
+ 0x2ac000ab, /* 19, -3.5dB */
+ 0x288000a2, /* 20, -4.0dB */
+ 0x26000098, /* 21, -4.5dB */
+ 0x24000090, /* 22, -5.0dB */
+ 0x22000088, /* 23, -5.5dB */
+ 0x20000080, /* 24, -6.0dB */
+ 0x1e400079, /* 25, -6.5dB */
+ 0x1c800072, /* 26, -7.0dB */
+ 0x1b00006c, /* 27. -7.5dB */
+ 0x19800066, /* 28, -8.0dB */
+ 0x18000060, /* 29, -8.5dB */
+ 0x16c0005b, /* 30, -9.0dB */
+ 0x15800056, /* 31, -9.5dB */
+ 0x14400051, /* 32, -10.0dB */
+ 0x1300004c, /* 33, -10.5dB */
+ 0x12000048, /* 34, -11.0dB */
+ 0x11000044, /* 35, -11.5dB */
+ 0x10000040, /* 36, -12.0dB */
+ 0x0f00003c, /* 37, -12.5dB */
+ 0x0e400039, /* 38, -13.0dB */
+ 0x0d800036, /* 39, -13.5dB */
+ 0x0cc00033, /* 40, -14.0dB */
+ 0x0c000030, /* 41, -14.5dB */
+ 0x0b40002d, /* 42, -15.0dB */
+};
+
+static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */
+};
+
+static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */
+};
+
+static void rtl92d_dm_diginit(struct ieee80211_hw *hw)
+{
+ de_digtable.dig_enable_flag = true;
+ de_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+ de_digtable.cur_igvalue = 0x20;
+ de_digtable.pre_igvalue = 0x0;
+ de_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+ de_digtable.presta_connectstate = DIG_STA_DISCONNECT;
+ de_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+ de_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
+ de_digtable.rssi_highthresh = DM_DIG_THRESH_HIGH;
+ de_digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
+ de_digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
+ de_digtable.rx_gain_range_max = DM_DIG_FA_UPPER;
+ de_digtable.rx_gain_range_min = DM_DIG_FA_LOWER;
+ de_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
+ de_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX;
+ de_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+ de_digtable.pre_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
+ de_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
+ de_digtable.large_fa_hit = 0;
+ de_digtable.recover_cnt = 0;
+ de_digtable.forbidden_igi = DM_DIG_FA_LOWER;
+}
+
+static void rtl92d_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+ u32 ret_value;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+ unsigned long flag = 0;
+
+ /* hold ofdm counter */
+ rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); /* hold page C counter */
+ rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); /*hold page D counter */
+
+ ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, BMASKDWORD);
+ falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
+ falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, BMASKDWORD);
+ falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, BMASKDWORD);
+ falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+ falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, BMASKDWORD);
+ falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+ falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
+ falsealm_cnt->cnt_rate_illegal +
+ falsealm_cnt->cnt_crc8_fail +
+ falsealm_cnt->cnt_mcs_fail +
+ falsealm_cnt->cnt_fast_fsync_fail +
+ falsealm_cnt->cnt_sb_search_fail;
+
+ if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
+ /* hold cck counter */
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, BMASKBYTE0);
+ falsealm_cnt->cnt_cck_fail = ret_value;
+ ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, BMASKBYTE3);
+ falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ } else {
+ falsealm_cnt->cnt_cck_fail = 0;
+ }
+
+ /* reset false alarm counter registers */
+ falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
+ falsealm_cnt->cnt_sb_search_fail +
+ falsealm_cnt->cnt_parity_fail +
+ falsealm_cnt->cnt_rate_illegal +
+ falsealm_cnt->cnt_crc8_fail +
+ falsealm_cnt->cnt_mcs_fail +
+ falsealm_cnt->cnt_cck_fail;
+
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
+ /* update ofdm counter */
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
+ /* update page C counter */
+ rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0);
+ /* update page D counter */
+ rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0);
+ if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
+ /* reset cck counter */
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
+ /* enable cck counter */
+ rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Fast_Fsync_fail = %x, "
+ "Cnt_SB_Search_fail = %x\n",
+ falsealm_cnt->cnt_fast_fsync_fail,
+ falsealm_cnt->cnt_sb_search_fail));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Parity_Fail = %x, "
+ "Cnt_Rate_Illegal = %x, Cnt_Crc8_fail = %x, "
+ "Cnt_Mcs_fail = %x\n",
+ falsealm_cnt->cnt_parity_fail,
+ falsealm_cnt->cnt_rate_illegal,
+ falsealm_cnt->cnt_crc8_fail,
+ falsealm_cnt->cnt_mcs_fail));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("Cnt_Ofdm_fail = %x, " "Cnt_Cck_fail = %x, "
+ "Cnt_all = %x\n",
+ falsealm_cnt->cnt_ofdm_fail,
+ falsealm_cnt->cnt_cck_fail,
+ falsealm_cnt->cnt_all));
+}
+
+static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+
+ /* Determine the minimum RSSI */
+ if ((mac->link_state < MAC80211_LINKED) &&
+ (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
+ de_digtable.min_undecorated_pwdb_for_dm = 0;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("Not connected to any\n"));
+ }
+ if (mac->link_state >= MAC80211_LINKED) {
+ if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC) {
+ de_digtable.min_undecorated_pwdb_for_dm =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("AP Client PWDB = 0x%lx\n",
+ rtlpriv->dm.UNDEC_SM_PWDB));
+ } else {
+ de_digtable.min_undecorated_pwdb_for_dm =
+ rtlpriv->dm.undecorated_smoothed_pwdb;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("STA Default Port PWDB = 0x%x\n",
+ de_digtable.min_undecorated_pwdb_for_dm));
+ }
+ } else {
+ de_digtable.min_undecorated_pwdb_for_dm =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("AP Ext Port or disconnet PWDB = 0x%x\n",
+ de_digtable.min_undecorated_pwdb_for_dm));
+ }
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n",
+ de_digtable.min_undecorated_pwdb_for_dm));
+}
+
+static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ unsigned long flag = 0;
+
+ if (de_digtable.cursta_connectctate == DIG_STA_CONNECT) {
+ if (de_digtable.pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
+ if (de_digtable.min_undecorated_pwdb_for_dm <= 25)
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_LOWRSSI;
+ else
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_HIGHRSSI;
+ } else {
+ if (de_digtable.min_undecorated_pwdb_for_dm <= 20)
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_LOWRSSI;
+ else
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_HIGHRSSI;
+ }
+ } else {
+ de_digtable.cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
+ }
+ if (de_digtable.pre_cck_pd_state != de_digtable.cur_cck_pd_state) {
+ if (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0x83);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ } else {
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0xcd);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ de_digtable.pre_cck_pd_state = de_digtable.cur_cck_pd_state;
+ }
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CurSTAConnectState=%s\n",
+ (de_digtable.cursta_connectctate == DIG_STA_CONNECT ?
+ "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT")));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CCKPDStage=%s\n",
+ (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ?
+ "Low RSSI " : "High RSSI ")));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("is92d single phy =%x\n",
+ IS_92D_SINGLEPHY(rtlpriv->rtlhal.version)));
+
+}
+
+void rtl92d_dm_write_dig(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("cur_igvalue = 0x%x, "
+ "pre_igvalue = 0x%x, backoff_val = %d\n",
+ de_digtable.cur_igvalue, de_digtable.pre_igvalue,
+ de_digtable.backoff_val));
+ if (de_digtable.dig_enable_flag == false) {
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("DIG is disabled\n"));
+ de_digtable.pre_igvalue = 0x17;
+ return;
+ }
+ if (de_digtable.pre_igvalue != de_digtable.cur_igvalue) {
+ rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+ de_digtable.cur_igvalue);
+ rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
+ de_digtable.cur_igvalue);
+ de_digtable.pre_igvalue = de_digtable.cur_igvalue;
+ }
+}
+
+static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv)
+{
+ if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) &&
+ (rtlpriv->mac80211.vendor == PEER_CISCO)) {
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("IOT_PEER = CISCO\n"));
+ if (de_digtable.last_min_undecorated_pwdb_for_dm >= 50
+ && de_digtable.min_undecorated_pwdb_for_dm < 50) {
+ rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("Early Mode Off\n"));
+ } else if (de_digtable.last_min_undecorated_pwdb_for_dm <= 55 &&
+ de_digtable.min_undecorated_pwdb_for_dm > 55) {
+ rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("Early Mode On\n"));
+ }
+ } else if (!(rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL) & 0xf)) {
+ rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Early Mode On\n"));
+ }
+}
+
+static void rtl92d_dm_dig(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 value_igi = de_digtable.cur_igvalue;
+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("==>\n"));
+ if (rtlpriv->rtlhal.earlymode_enable) {
+ rtl92d_early_mode_enabled(rtlpriv);
+ de_digtable.last_min_undecorated_pwdb_for_dm =
+ de_digtable.min_undecorated_pwdb_for_dm;
+ }
+ if (rtlpriv->dm.dm_initialgain_enable == false)
+ return;
+
+ /* because we will send data pkt when scanning
+ * this will cause some ap like gear-3700 wep TP
+ * lower if we retrun here, this is the diff of
+ * mac80211 driver vs ieee80211 driver */
+ /* if (rtlpriv->mac80211.act_scanning)
+ * return; */
+
+ /* Not STA mode return tmp */
+ if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+ return;
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("progress\n"));
+ /* Decide the current status and if modify initial gain or not */
+ if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ de_digtable.cursta_connectctate = DIG_STA_CONNECT;
+ else
+ de_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+
+ /* adjust initial gain according to false alarm counter */
+ if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0)
+ value_igi--;
+ else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH1)
+ value_igi += 0;
+ else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH2)
+ value_igi++;
+ else if (falsealm_cnt->cnt_all >= DM_DIG_FA_TH2)
+ value_igi += 2;
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n",
+ de_digtable.large_fa_hit, de_digtable.forbidden_igi));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() Before: Recover_cnt=%d, rx_gain_range_min=%x\n",
+ de_digtable.recover_cnt, de_digtable.rx_gain_range_min));
+
+ /* deal with abnorally large false alarm */
+ if (falsealm_cnt->cnt_all > 10000) {
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG(): Abnornally false alarm case.\n"));
+
+ de_digtable.large_fa_hit++;
+ if (de_digtable.forbidden_igi < de_digtable.cur_igvalue) {
+ de_digtable.forbidden_igi = de_digtable.cur_igvalue;
+ de_digtable.large_fa_hit = 1;
+ }
+ if (de_digtable.large_fa_hit >= 3) {
+ if ((de_digtable.forbidden_igi + 1) > DM_DIG_MAX)
+ de_digtable.rx_gain_range_min = DM_DIG_MAX;
+ else
+ de_digtable.rx_gain_range_min =
+ (de_digtable.forbidden_igi + 1);
+ de_digtable.recover_cnt = 3600; /* 3600=2hr */
+ }
+ } else {
+ /* Recovery mechanism for IGI lower bound */
+ if (de_digtable.recover_cnt != 0) {
+ de_digtable.recover_cnt--;
+ } else {
+ if (de_digtable.large_fa_hit == 0) {
+ if ((de_digtable.forbidden_igi - 1) <
+ DM_DIG_FA_LOWER) {
+ de_digtable.forbidden_igi =
+ DM_DIG_FA_LOWER;
+ de_digtable.rx_gain_range_min =
+ DM_DIG_FA_LOWER;
+
+ } else {
+ de_digtable.forbidden_igi--;
+ de_digtable.rx_gain_range_min =
+ (de_digtable.forbidden_igi + 1);
+ }
+ } else if (de_digtable.large_fa_hit == 3) {
+ de_digtable.large_fa_hit = 0;
+ }
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n",
+ de_digtable.large_fa_hit, de_digtable.forbidden_igi));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() After: recover_cnt=%d, rx_gain_range_min=%x\n",
+ de_digtable.recover_cnt, de_digtable.rx_gain_range_min));
+
+ if (value_igi > DM_DIG_MAX)
+ value_igi = DM_DIG_MAX;
+ else if (value_igi < de_digtable.rx_gain_range_min)
+ value_igi = de_digtable.rx_gain_range_min;
+ de_digtable.cur_igvalue = value_igi;
+ rtl92d_dm_write_dig(hw);
+ if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G)
+ rtl92d_dm_cck_packet_detection_thresh(hw);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("<<==\n"));
+}
+
+static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.dynamic_txpower_enable = true;
+ rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+}
+
+static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ long undecorated_smoothed_pwdb;
+
+ if ((!rtlpriv->dm.dynamic_txpower_enable)
+ || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+ return;
+ }
+ if ((mac->link_state < MAC80211_LINKED) &&
+ (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+ ("Not connected to any\n"));
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+ rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+ return;
+ }
+ if (mac->link_state >= MAC80211_LINKED) {
+ if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("IBSS Client PWDB = 0x%lx\n",
+ undecorated_smoothed_pwdb));
+ } else {
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.undecorated_smoothed_pwdb;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("STA Default Port PWDB = 0x%lx\n",
+ undecorated_smoothed_pwdb));
+ }
+ } else {
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("AP Ext Port PWDB = 0x%lx\n",
+ undecorated_smoothed_pwdb));
+ }
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ if (undecorated_smoothed_pwdb >= 0x33) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL2;
+ RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+ ("5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n"));
+ } else if ((undecorated_smoothed_pwdb < 0x33)
+ && (undecorated_smoothed_pwdb >= 0x2b)) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL1;
+ RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+ ("5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n"));
+ } else if (undecorated_smoothed_pwdb < 0x2b) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_NORMAL;
+ RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+ ("5G:TxHighPwrLevel_Normal\n"));
+ }
+ } else {
+ if (undecorated_smoothed_pwdb >=
+ TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL2;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"));
+ } else
+ if ((undecorated_smoothed_pwdb <
+ (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3))
+ && (undecorated_smoothed_pwdb >=
+ TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL1;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"));
+ } else if (undecorated_smoothed_pwdb <
+ (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_NORMAL;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("TXHIGHPWRLEVEL_NORMAL\n"));
+ }
+ }
+ if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("PHY_SetTxPowerLevel8192S() Channel = %d\n",
+ rtlphy->current_channel));
+ rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+ }
+ rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
+
+static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ /* AP & ADHOC & MESH will return tmp */
+ if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+ return;
+ /* Indicate Rx signal strength to FW. */
+ if (rtlpriv->dm.useramask) {
+ u32 temp = rtlpriv->dm.undecorated_smoothed_pwdb;
+
+ temp <<= 16;
+ temp |= 0x100;
+ /* fw v12 cmdid 5:use max macid ,for nic ,
+ * default macid is 0 ,max macid is 1 */
+ rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp));
+ } else {
+ rtl_write_byte(rtlpriv, 0x4fe,
+ (u8) rtlpriv->dm.undecorated_smoothed_pwdb);
+ }
+}
+
+void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.current_turbo_edca = false;
+ rtlpriv->dm.is_any_nonbepkts = false;
+ rtlpriv->dm.is_cur_rdlstate = false;
+}
+
+static void rtl92d_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ static u64 last_txok_cnt;
+ static u64 last_rxok_cnt;
+ u64 cur_txok_cnt;
+ u64 cur_rxok_cnt;
+ u32 edca_be_ul = 0x5ea42b;
+ u32 edca_be_dl = 0x5ea42b;
+
+ if (mac->link_state != MAC80211_LINKED) {
+ rtlpriv->dm.current_turbo_edca = false;
+ goto exit;
+ }
+
+ /* Enable BEQ TxOP limit configuration in wireless G-mode. */
+ /* To check whether we shall force turn on TXOP configuration. */
+ if ((!rtlpriv->dm.disable_framebursting) &&
+ (rtlpriv->sec.pairwise_enc_algorithm == WEP40_ENCRYPTION ||
+ rtlpriv->sec.pairwise_enc_algorithm == WEP104_ENCRYPTION ||
+ rtlpriv->sec.pairwise_enc_algorithm == TKIP_ENCRYPTION)) {
+ /* Force TxOP limit to 0x005e for UL. */
+ if (!(edca_be_ul & 0xffff0000))
+ edca_be_ul |= 0x005e0000;
+ /* Force TxOP limit to 0x005e for DL. */
+ if (!(edca_be_dl & 0xffff0000))
+ edca_be_dl |= 0x005e0000;
+ }
+
+ if ((!rtlpriv->dm.is_any_nonbepkts) &&
+ (!rtlpriv->dm.disable_framebursting)) {
+ cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
+ cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
+ if (cur_rxok_cnt > 4 * cur_txok_cnt) {
+ if (!rtlpriv->dm.is_cur_rdlstate ||
+ !rtlpriv->dm.current_turbo_edca) {
+ rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+ edca_be_dl);
+ rtlpriv->dm.is_cur_rdlstate = true;
+ }
+ } else {
+ if (rtlpriv->dm.is_cur_rdlstate ||
+ !rtlpriv->dm.current_turbo_edca) {
+ rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+ edca_be_ul);
+ rtlpriv->dm.is_cur_rdlstate = false;
+ }
+ }
+ rtlpriv->dm.current_turbo_edca = true;
+ } else {
+ if (rtlpriv->dm.current_turbo_edca) {
+ u8 tmp = AC0_BE;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
+ (u8 *) (&tmp));
+ rtlpriv->dm.current_turbo_edca = false;
+ }
+ }
+
+exit:
+ rtlpriv->dm.is_any_nonbepkts = false;
+ last_txok_cnt = rtlpriv->stats.txbytesunicast;
+ last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl92d_dm_rxgain_tracking_thermalmeter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 index_mapping[RX_INDEX_MAPPING_NUM] = {
+ 0x0f, 0x0f, 0x0d, 0x0c, 0x0b,
+ 0x0a, 0x09, 0x08, 0x07, 0x06,
+ 0x05, 0x04, 0x04, 0x03, 0x02
+ };
+ int i;
+ u32 u4tmp;
+
+ u4tmp = (index_mapping[(rtlpriv->efuse.eeprom_thermalmeter -
+ rtlpriv->dm.thermalvalue_rxgain)]) << 12;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("===> Rx Gain %x\n", u4tmp));
+ for (i = RF90_PATH_A; i < rtlpriv->phy.num_total_rfpath; i++)
+ rtl_set_rfreg(hw, i, 0x3C, BRFREGOFFSETMASK,
+ (rtlpriv->phy.reg_rf3c[i] & (~(0xF000))) | u4tmp);
+}
+
+static void rtl92d_bandtype_2_4G(struct ieee80211_hw *hw, long *temp_cckg,
+ u8 *cck_index_old)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+ unsigned long flag = 0;
+ long temp_cck;
+
+ /* Query CCK default setting From 0xa24 */
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2,
+ BMASKDWORD) & BMASKCCK;
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ for (i = 0; i < CCK_TABLE_LENGTH; i++) {
+ if (rtlpriv->dm.cck_inch14) {
+ if (!memcmp((void *)&temp_cck,
+ (void *)&cckswing_table_ch14[i][2], 4)) {
+ *cck_index_old = (u8) i;
+ RT_TRACE(rtlpriv,
+ COMP_POWER_TRACKING,
+ DBG_LOUD,
+ ("Initial reg0x%x = 0x%lx, "
+ "cck_index=0x%x, ch 14 %d\n",
+ RCCK0_TXFILTER2,
+ temp_cck, *cck_index_old,
+ rtlpriv->dm.cck_inch14));
+ break;
+ }
+ } else {
+ if (!memcmp((void *) &temp_cck,
+ &cckswing_table_ch1ch13[i][2], 4)) {
+ *cck_index_old = (u8) i;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+ DBG_LOUD,
+ ("Initial reg0x%x = 0x%lx, "
+ "cck_index = 0x%x, ch14 %d\n",
+ RCCK0_TXFILTER2,
+ temp_cck, *cck_index_old,
+ rtlpriv->dm.cck_inch14));
+ break;
+ }
+ }
+ }
+ *temp_cckg = temp_cck;
+}
+
+static void rtl92d_bandtype_5G(struct rtl_hal *rtlhal, u8 *ofdm_index,
+ bool *internal_pa, u8 thermalvalue, u8 delta,
+ u8 rf, struct rtl_efuse *rtlefuse,
+ struct rtl_priv *rtlpriv, struct rtl_phy *rtlphy,
+ u8 index_mapping[5][INDEX_MAPPING_NUM],
+ u8 index_mapping_pa[8][INDEX_MAPPING_NUM])
+{
+ int i;
+ u8 index;
+ u8 offset = 0;
+
+ for (i = 0; i < rf; i++) {
+ if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+ rtlhal->interfaceindex == 1) /* MAC 1 5G */
+ *internal_pa = rtlefuse->internal_pa_5g[1];
+ else
+ *internal_pa = rtlefuse->internal_pa_5g[i];
+ if (*internal_pa) {
+ if (rtlhal->interfaceindex == 1 || i == rf)
+ offset = 4;
+ else
+ offset = 0;
+ if (rtlphy->current_channel >= 100 &&
+ rtlphy->current_channel <= 165)
+ offset += 2;
+ } else {
+ if (rtlhal->interfaceindex == 1 || i == rf)
+ offset = 2;
+ else
+ offset = 0;
+ }
+ if (thermalvalue > rtlefuse->eeprom_thermalmeter)
+ offset++;
+ if (*internal_pa) {
+ if (delta > INDEX_MAPPING_NUM - 1)
+ index = index_mapping_pa[offset]
+ [INDEX_MAPPING_NUM - 1];
+ else
+ index =
+ index_mapping_pa[offset][delta];
+ } else {
+ if (delta > INDEX_MAPPING_NUM - 1)
+ index =
+ index_mapping[offset][INDEX_MAPPING_NUM - 1];
+ else
+ index = index_mapping[offset][delta];
+ }
+ if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
+ if (*internal_pa && thermalvalue > 0x12) {
+ ofdm_index[i] = rtlpriv->dm.ofdm_index[i] -
+ ((delta / 2) * 3 + (delta % 2));
+ } else {
+ ofdm_index[i] -= index;
+ }
+ } else {
+ ofdm_index[i] += index;
+ }
+ }
+}
+
+static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
+ struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 thermalvalue, delta, delta_lck, delta_iqk, delta_rxgain;
+ u8 offset, thermalvalue_avg_count = 0;
+ u32 thermalvalue_avg = 0;
+ bool internal_pa = false;
+ long ele_a = 0, ele_d, temp_cck, val_x, value32;
+ long val_y, ele_c = 0;
+ u8 ofdm_index[2];
+ u8 cck_index = 0;
+ u8 ofdm_index_old[2];
+ u8 cck_index_old = 0;
+ u8 index;
+ int i;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+ u8 ofdm_min_index = 6, ofdm_min_index_internal_pa = 3, rf;
+ u8 indexforchannel =
+ rtl92d_get_rightchnlplace_for_iqk(rtlphy->current_channel);
+ u8 index_mapping[5][INDEX_MAPPING_NUM] = {
+ /* 5G, path A/MAC 0, decrease power */
+ {0, 1, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18},
+ /* 5G, path A/MAC 0, increase power */
+ {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
+ /* 5G, path B/MAC 1, decrease power */
+ {0, 2, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18},
+ /* 5G, path B/MAC 1, increase power */
+ {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
+ /* 2.4G, for decreas power */
+ {0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10},
+ };
+ u8 index_mapping_internal_pa[8][INDEX_MAPPING_NUM] = {
+ /* 5G, path A/MAC 0, ch36-64, decrease power */
+ {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16},
+ /* 5G, path A/MAC 0, ch36-64, increase power */
+ {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
+ /* 5G, path A/MAC 0, ch100-165, decrease power */
+ {0, 1, 2, 3, 5, 6, 8, 10, 11, 13, 14, 15, 15},
+ /* 5G, path A/MAC 0, ch100-165, increase power */
+ {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
+ /* 5G, path B/MAC 1, ch36-64, decrease power */
+ {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16},
+ /* 5G, path B/MAC 1, ch36-64, increase power */
+ {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
+ /* 5G, path B/MAC 1, ch100-165, decrease power */
+ {0, 1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 14, 14},
+ /* 5G, path B/MAC 1, ch100-165, increase power */
+ {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
+ };
+
+ rtlpriv->dm.txpower_trackinginit = true;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("\n"));
+ thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xf800);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
+ "eeprom_thermalmeter 0x%x\n", thermalvalue,
+ rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter));
+ rtl92d_phy_ap_calibrate(hw, (thermalvalue -
+ rtlefuse->eeprom_thermalmeter));
+ if (is2t)
+ rf = 2;
+ else
+ rf = 1;
+ if (thermalvalue) {
+ ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD) & BMASKOFDM_D;
+ for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
+ if (ele_d == (ofdmswing_table[i] & BMASKOFDM_D)) {
+ ofdm_index_old[0] = (u8) i;
+
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Initial pathA ele_d reg0x%x = 0x%lx,"
+ " ofdm_index=0x%x\n",
+ ROFDM0_XATxIQIMBALANCE,
+ ele_d, ofdm_index_old[0]));
+ break;
+ }
+ }
+ if (is2t) {
+ ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD) & BMASKOFDM_D;
+ for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
+ if (ele_d ==
+ (ofdmswing_table[i] & BMASKOFDM_D)) {
+ ofdm_index_old[1] = (u8) i;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+ DBG_LOUD,
+ ("Initial pathB ele_d reg "
+ "0x%x = 0x%lx, ofdm_index "
+ "= 0x%x\n",
+ ROFDM0_XBTxIQIMBALANCE, ele_d,
+ ofdm_index_old[1]));
+ break;
+ }
+ }
+ }
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ rtl92d_bandtype_2_4G(hw, &temp_cck, &cck_index_old);
+ } else {
+ temp_cck = 0x090e1317;
+ cck_index_old = 12;
+ }
+
+ if (!rtlpriv->dm.thermalvalue) {
+ rtlpriv->dm.thermalvalue =
+ rtlefuse->eeprom_thermalmeter;
+ rtlpriv->dm.thermalvalue_lck = thermalvalue;
+ rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+ rtlpriv->dm.thermalvalue_rxgain =
+ rtlefuse->eeprom_thermalmeter;
+ for (i = 0; i < rf; i++)
+ rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
+ rtlpriv->dm.cck_index = cck_index_old;
+ }
+ if (rtlhal->reloadtxpowerindex) {
+ for (i = 0; i < rf; i++)
+ rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
+ rtlpriv->dm.cck_index = cck_index_old;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("reload ofdm index for band switch\n"));
+ }
+ rtlpriv->dm.thermalvalue_avg
+ [rtlpriv->dm.thermalvalue_avg_index] = thermalvalue;
+ rtlpriv->dm.thermalvalue_avg_index++;
+ if (rtlpriv->dm.thermalvalue_avg_index == AVG_THERMAL_NUM)
+ rtlpriv->dm.thermalvalue_avg_index = 0;
+ for (i = 0; i < AVG_THERMAL_NUM; i++) {
+ if (rtlpriv->dm.thermalvalue_avg[i]) {
+ thermalvalue_avg +=
+ rtlpriv->dm.thermalvalue_avg[i];
+ thermalvalue_avg_count++;
+ }
+ }
+ if (thermalvalue_avg_count)
+ thermalvalue = (u8) (thermalvalue_avg /
+ thermalvalue_avg_count);
+ if (rtlhal->reloadtxpowerindex) {
+ delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+ (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+ (rtlefuse->eeprom_thermalmeter - thermalvalue);
+ rtlhal->reloadtxpowerindex = false;
+ rtlpriv->dm.done_txpower = false;
+ } else if (rtlpriv->dm.done_txpower) {
+ delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue) :
+ (rtlpriv->dm.thermalvalue - thermalvalue);
+ } else {
+ delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+ (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+ (rtlefuse->eeprom_thermalmeter - thermalvalue);
+ }
+ delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
+ (rtlpriv->dm.thermalvalue_lck - thermalvalue);
+ delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
+ (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
+ delta_rxgain =
+ (thermalvalue > rtlpriv->dm.thermalvalue_rxgain) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue_rxgain) :
+ (rtlpriv->dm.thermalvalue_rxgain - thermalvalue);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x"
+ " eeprom_thermalmeter 0x%x delta 0x%x "
+ "delta_lck 0x%x delta_iqk 0x%x\n",
+ thermalvalue, rtlpriv->dm.thermalvalue,
+ rtlefuse->eeprom_thermalmeter, delta, delta_lck,
+ delta_iqk));
+ if ((delta_lck > rtlefuse->delta_lck) &&
+ (rtlefuse->delta_lck != 0)) {
+ rtlpriv->dm.thermalvalue_lck = thermalvalue;
+ rtl92d_phy_lc_calibrate(hw);
+ }
+ if (delta > 0 && rtlpriv->dm.txpower_track_control) {
+ rtlpriv->dm.done_txpower = true;
+ delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+ (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+ (rtlefuse->eeprom_thermalmeter - thermalvalue);
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ offset = 4;
+ if (delta > INDEX_MAPPING_NUM - 1)
+ index = index_mapping[offset]
+ [INDEX_MAPPING_NUM - 1];
+ else
+ index = index_mapping[offset][delta];
+ if (thermalvalue > rtlpriv->dm.thermalvalue) {
+ for (i = 0; i < rf; i++)
+ ofdm_index[i] -= delta;
+ cck_index -= delta;
+ } else {
+ for (i = 0; i < rf; i++)
+ ofdm_index[i] += index;
+ cck_index += index;
+ }
+ } else if (rtlhal->current_bandtype == BAND_ON_5G) {
+ rtl92d_bandtype_5G(rtlhal, ofdm_index,
+ &internal_pa, thermalvalue,
+ delta, rf, rtlefuse, rtlpriv,
+ rtlphy, index_mapping,
+ index_mapping_internal_pa);
+ }
+ if (is2t) {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("temp OFDM_A_index=0x%x, OFDM_B_index"
+ " = 0x%x,cck_index=0x%x\n",
+ rtlpriv->dm.ofdm_index[0],
+ rtlpriv->dm.ofdm_index[1],
+ rtlpriv->dm.cck_index));
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("temp OFDM_A_index=0x%x,cck_index = "
+ "0x%x\n",
+ rtlpriv->dm.ofdm_index[0],
+ rtlpriv->dm.cck_index));
+ }
+ for (i = 0; i < rf; i++) {
+ if (ofdm_index[i] > OFDM_TABLE_SIZE_92D - 1)
+ ofdm_index[i] = OFDM_TABLE_SIZE_92D - 1;
+ else if (ofdm_index[i] < ofdm_min_index)
+ ofdm_index[i] = ofdm_min_index;
+ }
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ if (cck_index > CCK_TABLE_SIZE - 1) {
+ cck_index = CCK_TABLE_SIZE - 1;
+ } else if (internal_pa ||
+ rtlhal->current_bandtype ==
+ BAND_ON_2_4G) {
+ if (ofdm_index[i] <
+ ofdm_min_index_internal_pa)
+ ofdm_index[i] =
+ ofdm_min_index_internal_pa;
+ } else if (cck_index < 0) {
+ cck_index = 0;
+ }
+ }
+ if (is2t) {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("new OFDM_A_index=0x%x, OFDM_B_index "
+ "= 0x%x, cck_index=0x%x\n",
+ ofdm_index[0], ofdm_index[1],
+ cck_index));
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("new OFDM_A_index=0x%x,cck_index = "
+ "0x%x\n",
+ ofdm_index[0], cck_index));
+ }
+ ele_d = (ofdmswing_table[(u8) ofdm_index[0]] &
+ 0xFFC00000) >> 22;
+ val_x = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][0];
+ val_y = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][1];
+ if (val_x != 0) {
+ if ((val_x & 0x00000200) != 0)
+ val_x = val_x | 0xFFFFFC00;
+ ele_a =
+ ((val_x * ele_d) >> 8) & 0x000003FF;
+
+ /* new element C = element D x Y */
+ if ((val_y & 0x00000200) != 0)
+ val_y = val_y | 0xFFFFFC00;
+ ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
+
+ /* wirte new elements A, C, D to regC80 and
+ * regC94, element B is always 0 */
+ value32 = (ele_d << 22) | ((ele_c & 0x3F) <<
+ 16) | ele_a;
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD, value32);
+
+ value32 = (ele_c & 0x000003C0) >> 6;
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS,
+ value32);
+
+ value32 = ((val_x * ele_d) >> 7) & 0x01;
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
+ value32);
+
+ } else {
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD,
+ ofdmswing_table
+ [(u8)ofdm_index[0]]);
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS,
+ 0x00);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+ BIT(24), 0x00);
+ }
+
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("TxPwrTracking for interface %d path A: X ="
+ " 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = "
+ "0x%lx ele_D = 0x%lx 0xe94 = 0x%lx 0xe9c = "
+ "0x%lx\n", rtlhal->interfaceindex,
+ val_x, val_y, ele_a, ele_c, ele_d,
+ val_x, val_y));
+
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* Adjust CCK according to IQK result */
+ if (!rtlpriv->dm.cck_inch14) {
+ rtl_write_byte(rtlpriv, 0xa22,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][0]);
+ rtl_write_byte(rtlpriv, 0xa23,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][1]);
+ rtl_write_byte(rtlpriv, 0xa24,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][2]);
+ rtl_write_byte(rtlpriv, 0xa25,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][3]);
+ rtl_write_byte(rtlpriv, 0xa26,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][4]);
+ rtl_write_byte(rtlpriv, 0xa27,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][5]);
+ rtl_write_byte(rtlpriv, 0xa28,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][6]);
+ rtl_write_byte(rtlpriv, 0xa29,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][7]);
+ } else {
+ rtl_write_byte(rtlpriv, 0xa22,
+ cckswing_table_ch14
+ [(u8)cck_index][0]);
+ rtl_write_byte(rtlpriv, 0xa23,
+ cckswing_table_ch14
+ [(u8)cck_index][1]);
+ rtl_write_byte(rtlpriv, 0xa24,
+ cckswing_table_ch14
+ [(u8)cck_index][2]);
+ rtl_write_byte(rtlpriv, 0xa25,
+ cckswing_table_ch14
+ [(u8)cck_index][3]);
+ rtl_write_byte(rtlpriv, 0xa26,
+ cckswing_table_ch14
+ [(u8)cck_index][4]);
+ rtl_write_byte(rtlpriv, 0xa27,
+ cckswing_table_ch14
+ [(u8)cck_index][5]);
+ rtl_write_byte(rtlpriv, 0xa28,
+ cckswing_table_ch14
+ [(u8)cck_index][6]);
+ rtl_write_byte(rtlpriv, 0xa29,
+ cckswing_table_ch14
+ [(u8)cck_index][7]);
+ }
+ }
+ if (is2t) {
+ ele_d = (ofdmswing_table[(u8) ofdm_index[1]] &
+ 0xFFC00000) >> 22;
+ val_x = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][4];
+ val_y = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][5];
+ if (val_x != 0) {
+ if ((val_x & 0x00000200) != 0)
+ /* consider minus */
+ val_x = val_x | 0xFFFFFC00;
+ ele_a = ((val_x * ele_d) >> 8) &
+ 0x000003FF;
+ /* new element C = element D x Y */
+ if ((val_y & 0x00000200) != 0)
+ val_y =
+ val_y | 0xFFFFFC00;
+ ele_c =
+ ((val_y *
+ ele_d) >> 8) & 0x00003FF;
+ /* write new elements A, C, D to regC88
+ * and regC9C, element B is always 0
+ */
+ value32 = (ele_d << 22) |
+ ((ele_c & 0x3F) << 16) |
+ ele_a;
+ rtl_set_bbreg(hw,
+ ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD, value32);
+ value32 = (ele_c & 0x000003C0) >> 6;
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+ BMASKH4BITS, value32);
+ value32 = ((val_x * ele_d) >> 7) & 0x01;
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+ BIT(28), value32);
+ } else {
+ rtl_set_bbreg(hw,
+ ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD,
+ ofdmswing_table
+ [(u8) ofdm_index[1]]);
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+ BMASKH4BITS, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+ BIT(28), 0x00);
+ }
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("TxPwrTracking path B: X = 0x%lx, "
+ "Y = 0x%lx ele_A = 0x%lx ele_C = 0x"
+ "%lx ele_D = 0x%lx 0xeb4 = 0x%lx "
+ "0xebc = 0x%lx\n",
+ val_x, val_y, ele_a, ele_c,
+ ele_d, val_x, val_y));
+ }
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("TxPwrTracking 0xc80 = 0x%x, 0xc94 = "
+ "0x%x RF 0x24 = 0x%x\n",
+ rtl_get_bbreg(hw, 0xc80, BMASKDWORD),
+ rtl_get_bbreg(hw, 0xc94, BMASKDWORD),
+ rtl_get_rfreg(hw, RF90_PATH_A, 0x24,
+ BRFREGOFFSETMASK)));
+ }
+ if ((delta_iqk > rtlefuse->delta_iqk) &&
+ (rtlefuse->delta_iqk != 0)) {
+ rtl92d_phy_reset_iqk_result(hw);
+ rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+ rtl92d_phy_iq_calibrate(hw);
+ }
+ if (delta_rxgain > 0 && rtlhal->current_bandtype == BAND_ON_5G
+ && thermalvalue <= rtlefuse->eeprom_thermalmeter) {
+ rtlpriv->dm.thermalvalue_rxgain = thermalvalue;
+ rtl92d_dm_rxgain_tracking_thermalmeter(hw);
+ }
+ if (rtlpriv->dm.txpower_track_control)
+ rtlpriv->dm.thermalvalue = thermalvalue;
+ }
+
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n"));
+}
+
+static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.txpower_tracking = true;
+ rtlpriv->dm.txpower_trackinginit = false;
+ rtlpriv->dm.txpower_track_control = true;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("pMgntInfo->txpower_tracking = %d\n",
+ rtlpriv->dm.txpower_tracking));
+}
+
+void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ static u8 tm_trigger;
+
+ if (!rtlpriv->dm.txpower_tracking)
+ return;
+
+ if (!tm_trigger) {
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) |
+ BIT(16), 0x03);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Trigger 92S Thermal Meter!!\n"));
+ tm_trigger = 1;
+ return;
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Schedule TxPowerTracking direct call!!\n"));
+ rtl92d_dm_txpower_tracking_callback_thermalmeter(hw);
+ tm_trigger = 0;
+ }
+}
+
+void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rate_adaptive *ra = &(rtlpriv->ra);
+
+ ra->ratr_state = DM_RATR_STA_INIT;
+ ra->pre_ratr_state = DM_RATR_STA_INIT;
+ if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
+ rtlpriv->dm.useramask = true;
+ else
+ rtlpriv->dm.useramask = false;
+}
+
+void rtl92d_dm_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+ rtl92d_dm_diginit(hw);
+ rtl92d_dm_init_dynamic_txpower(hw);
+ rtl92d_dm_init_edca_turbo(hw);
+ rtl92d_dm_init_rate_adaptive_mask(hw);
+ rtl92d_dm_initialize_txpower_tracking(hw);
+}
+
+void rtl92d_dm_watchdog(struct ieee80211_hw *hw)
+{
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ bool fw_current_inpsmode = false;
+ bool fwps_awake = true;
+
+ /* 1. RF is OFF. (No need to do DM.)
+ * 2. Fw is under power saving mode for FwLPS.
+ * (Prevent from SW/FW I/O racing.)
+ * 3. IPS workitem is scheduled. (Prevent from IPS sequence
+ * to be swapped with DM.
+ * 4. RFChangeInProgress is TRUE.
+ * (Prevent from broken by IPS/HW/SW Rf off.) */
+
+ if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
+ fwps_awake) && (!ppsc->rfchange_inprogress)) {
+ rtl92d_dm_pwdb_monitor(hw);
+ rtl92d_dm_false_alarm_counter_statistics(hw);
+ rtl92d_dm_find_minimum_rssi(hw);
+ rtl92d_dm_dig(hw);
+ /* rtl92d_dm_dynamic_bb_powersaving(hw); */
+ rtl92d_dm_dynamic_txpower(hw);
+ /* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */
+ /* rtl92d_dm_refresh_rate_adaptive_mask(hw); */
+ /* rtl92d_dm_interrupt_migration(hw); */
+ rtl92d_dm_check_edca_turbo(hw);
+ }
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h
new file mode 100644
index 000000000000..69354657f0f5
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C_DM_H__
+#define __RTL92C_DM_H__
+
+#define HAL_DM_DIG_DISABLE BIT(0)
+#define HAL_DM_HIPWR_DISABLE BIT(1)
+
+#define OFDM_TABLE_LENGTH 37
+#define OFDM_TABLE_SIZE_92D 43
+#define CCK_TABLE_LENGTH 33
+
+#define CCK_TABLE_SIZE 33
+
+#define BW_AUTO_SWITCH_HIGH_LOW 25
+#define BW_AUTO_SWITCH_LOW_HIGH 30
+
+#define DM_DIG_THRESH_HIGH 40
+#define DM_DIG_THRESH_LOW 35
+
+#define DM_FALSEALARM_THRESH_LOW 400
+#define DM_FALSEALARM_THRESH_HIGH 1000
+
+#define DM_DIG_MAX 0x3e
+#define DM_DIG_MIN 0x1c
+
+#define DM_DIG_FA_UPPER 0x32
+#define DM_DIG_FA_LOWER 0x20
+#define DM_DIG_FA_TH0 0x100
+#define DM_DIG_FA_TH1 0x400
+#define DM_DIG_FA_TH2 0x600
+
+#define DM_DIG_BACKOFF_MAX 12
+#define DM_DIG_BACKOFF_MIN -4
+#define DM_DIG_BACKOFF_DEFAULT 10
+
+#define RXPATHSELECTION_SS_TH_lOW 30
+#define RXPATHSELECTION_DIFF_TH 18
+
+#define DM_RATR_STA_INIT 0
+#define DM_RATR_STA_HIGH 1
+#define DM_RATR_STA_MIDDLE 2
+#define DM_RATR_STA_LOW 3
+
+#define CTS2SELF_THVAL 30
+#define REGC38_TH 20
+
+#define WAIOTTHVAL 25
+
+#define TXHIGHPWRLEVEL_NORMAL 0
+#define TXHIGHPWRLEVEL_LEVEL1 1
+#define TXHIGHPWRLEVEL_LEVEL2 2
+#define TXHIGHPWRLEVEL_BT1 3
+#define TXHIGHPWRLEVEL_BT2 4
+
+#define DM_TYPE_BYFW 0
+#define DM_TYPE_BYDRIVER 1
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
+#define INDEX_MAPPING_NUM 13
+
+struct ps_t {
+ u8 pre_ccastate;
+ u8 cur_ccasate;
+
+ u8 pre_rfstate;
+ u8 cur_rfstate;
+
+ long rssi_val_min;
+};
+
+struct dig_t {
+ u8 dig_enable_flag;
+ u8 dig_ext_port_stage;
+
+ u32 rssi_lowthresh;
+ u32 rssi_highthresh;
+
+ u32 fa_lowthresh;
+ u32 fa_highthresh;
+
+ u8 cursta_connectctate;
+ u8 presta_connectstate;
+ u8 curmultista_connectstate;
+
+ u8 pre_igvalue;
+ u8 cur_igvalue;
+
+ char backoff_val;
+ char backoff_val_range_max;
+ char backoff_val_range_min;
+ u8 rx_gain_range_max;
+ u8 rx_gain_range_min;
+ u8 min_undecorated_pwdb_for_dm;
+ long last_min_undecorated_pwdb_for_dm;
+
+ u8 pre_cck_pd_state;
+ u8 cur_cck_pd_state;
+
+ u8 pre_cck_fa_state;
+ u8 cur_cck_fa_state;
+
+ u8 pre_ccastate;
+ u8 cur_ccasate;
+
+ u8 large_fa_hit;
+ u8 forbidden_igi;
+ u32 recover_cnt;
+};
+
+struct swat {
+ u8 failure_cnt;
+ u8 try_flag;
+ u8 stop_trying;
+ long pre_rssi;
+ long trying_threshold;
+ u8 cur_antenna;
+ u8 pre_antenna;
+};
+
+enum tag_dynamic_init_gain_operation_type_definition {
+ DIG_TYPE_THRESH_HIGH = 0,
+ DIG_TYPE_THRESH_LOW = 1,
+ DIG_TYPE_BACKOFF = 2,
+ DIG_TYPE_RX_GAIN_MIN = 3,
+ DIG_TYPE_RX_GAIN_MAX = 4,
+ DIG_TYPE_ENABLE = 5,
+ DIG_TYPE_DISABLE = 6,
+ DIG_OP_TYPE_MAX
+};
+
+enum tag_cck_packet_detection_threshold_type_definition {
+ CCK_PD_STAGE_LOWRSSI = 0,
+ CCK_PD_STAGE_HIGHRSSI = 1,
+ CCK_FA_STAGE_LOW = 2,
+ CCK_FA_STAGE_HIGH = 3,
+ CCK_PD_STAGE_MAX = 4,
+};
+
+enum dm_1r_cca {
+ CCA_1R = 0,
+ CCA_2R = 1,
+ CCA_MAX = 2,
+};
+
+enum dm_rf {
+ RF_SAVE = 0,
+ RF_NORMAL = 1,
+ RF_MAX = 2,
+};
+
+enum dm_sw_ant_switch {
+ ANS_ANTENNA_B = 1,
+ ANS_ANTENNA_A = 2,
+ ANS_ANTENNA_MAX = 3,
+};
+
+enum dm_dig_ext_port_alg {
+ DIG_EXT_PORT_STAGE_0 = 0,
+ DIG_EXT_PORT_STAGE_1 = 1,
+ DIG_EXT_PORT_STAGE_2 = 2,
+ DIG_EXT_PORT_STAGE_3 = 3,
+ DIG_EXT_PORT_STAGE_MAX = 4,
+};
+
+enum dm_dig_connect {
+ DIG_STA_DISCONNECT = 0,
+ DIG_STA_CONNECT = 1,
+ DIG_STA_BEFORE_CONNECT = 2,
+ DIG_MULTISTA_DISCONNECT = 3,
+ DIG_MULTISTA_CONNECT = 4,
+ DIG_CONNECT_MAX
+};
+
+extern struct dig_t de_digtable;
+
+void rtl92d_dm_init(struct ieee80211_hw *hw);
+void rtl92d_dm_watchdog(struct ieee80211_hw *hw);
+void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl92d_dm_write_dig(struct ieee80211_hw *hw);
+void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw);
+void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
new file mode 100644
index 000000000000..82f060bdbc0b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
@@ -0,0 +1,790 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "fw.h"
+#include "sw.h"
+
+static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
+{
+ return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
+ true : false;
+}
+
+static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp;
+
+ if (enable) {
+ tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
+ } else {
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
+ /* Reserved for fw extension.
+ * 0x81[7] is used for mac0 status ,
+ * so don't write this reg here
+ * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
+ }
+}
+
+static void _rtl92d_fw_block_write(struct ieee80211_hw *hw,
+ const u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 blocksize = sizeof(u32);
+ u8 *bufferptr = (u8 *) buffer;
+ u32 *pu4BytePtr = (u32 *) buffer;
+ u32 i, offset, blockCount, remainSize;
+
+ blockCount = size / blocksize;
+ remainSize = size % blocksize;
+ for (i = 0; i < blockCount; i++) {
+ offset = i * blocksize;
+ rtl_write_dword(rtlpriv, (FW_8192D_START_ADDRESS + offset),
+ *(pu4BytePtr + i));
+ }
+ if (remainSize) {
+ offset = blockCount * blocksize;
+ bufferptr += offset;
+ for (i = 0; i < remainSize; i++) {
+ rtl_write_byte(rtlpriv, (FW_8192D_START_ADDRESS +
+ offset + i), *(bufferptr + i));
+ }
+ }
+}
+
+static void _rtl92d_fw_page_write(struct ieee80211_hw *hw,
+ u32 page, const u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 value8;
+ u8 u8page = (u8) (page & 0x07);
+
+ value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
+ rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
+ _rtl92d_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl92d_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
+{
+ u32 fwlen = *pfwlen;
+ u8 remain = (u8) (fwlen % 4);
+
+ remain = (remain == 0) ? 0 : (4 - remain);
+ while (remain > 0) {
+ pfwbuf[fwlen] = 0;
+ fwlen++;
+ remain--;
+ }
+ *pfwlen = fwlen;
+}
+
+static void _rtl92d_write_fw(struct ieee80211_hw *hw,
+ enum version_8192d version, u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 *bufferPtr = (u8 *) buffer;
+ u32 pagenums, remainSize;
+ u32 page, offset;
+
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
+ _rtl92d_fill_dummy(bufferPtr, &size);
+ pagenums = size / FW_8192D_PAGE_SIZE;
+ remainSize = size % FW_8192D_PAGE_SIZE;
+ if (pagenums > 8) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Page numbers should not greater then 8\n"));
+ }
+ for (page = 0; page < pagenums; page++) {
+ offset = page * FW_8192D_PAGE_SIZE;
+ _rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
+ FW_8192D_PAGE_SIZE);
+ }
+ if (remainSize) {
+ offset = pagenums * FW_8192D_PAGE_SIZE;
+ page = pagenums;
+ _rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
+ remainSize);
+ }
+}
+
+static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 counter = 0;
+ u32 value32;
+
+ do {
+ value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+ } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
+ (!(value32 & FWDL_ChkSum_rpt)));
+ if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+ value32));
+ return -EIO;
+ }
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
+ value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+ value32 |= MCUFWDL_RDY;
+ rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+ return 0;
+}
+
+void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 u1b_tmp;
+ u8 delay = 100;
+
+ /* Set (REG_HMETFR + 3) to 0x20 is reset 8051 */
+ rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ while (u1b_tmp & BIT(2)) {
+ delay--;
+ if (delay == 0)
+ break;
+ udelay(50);
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ }
+ RT_ASSERT((delay > 0), ("8051 reset failed!\n"));
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("=====> 8051 reset success (%d) .\n", delay));
+}
+
+static int _rtl92d_fw_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 counter;
+
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, ("FW already have download\n"));
+ /* polling for FW ready */
+ counter = 0;
+ do {
+ if (rtlhal->interfaceindex == 0) {
+ if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
+ MAC0_READY) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready success!! "
+ "REG_MCUFWDL: 0x%x .\n",
+ rtl_read_byte(rtlpriv,
+ FW_MAC0_READY)));
+ return 0;
+ }
+ udelay(5);
+ } else {
+ if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
+ MAC1_READY) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready success!! "
+ "REG_MCUFWDL: 0x%x .\n",
+ rtl_read_byte(rtlpriv,
+ FW_MAC1_READY)));
+ return 0;
+ }
+ udelay(5);
+ }
+ } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
+
+ if (rtlhal->interfaceindex == 0) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready fail!! MAC0 FW init not ready: "
+ "0x%x .\n",
+ rtl_read_byte(rtlpriv, FW_MAC0_READY)));
+ } else {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready fail!! MAC1 FW init not ready: "
+ "0x%x .\n",
+ rtl_read_byte(rtlpriv, FW_MAC1_READY)));
+ }
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready fail!! REG_MCUFWDL:0x%08ul .\n",
+ rtl_read_dword(rtlpriv, REG_MCUFWDL)));
+ return -1;
+}
+
+int rtl92d_download_fw(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 *pfwheader;
+ u8 *pfwdata;
+ u32 fwsize;
+ int err;
+ enum version_8192d version = rtlhal->version;
+ u8 value;
+ u32 count;
+ bool fw_downloaded = false, fwdl_in_process = false;
+ unsigned long flags;
+
+ if (!rtlhal->pfirmware)
+ return 1;
+ fwsize = rtlhal->fwsize;
+ pfwheader = (u8 *) rtlhal->pfirmware;
+ pfwdata = (u8 *) rtlhal->pfirmware;
+ rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
+ rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, (" FirmwareVersion(%d),"
+ "FirmwareSubVersion(%d), Signature(%#x)\n",
+ rtlhal->fw_version, rtlhal->fw_subversion,
+ GET_FIRMWARE_HDR_SIGNATURE(pfwheader)));
+ if (IS_FW_HEADER_EXIST(pfwheader)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Shift 32 bytes for FW header!!\n"));
+ pfwdata = pfwdata + 32;
+ fwsize = fwsize - 32;
+ }
+
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
+ if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
+ fwdl_in_process = true;
+ else
+ fwdl_in_process = false;
+ if (fw_downloaded) {
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ goto exit;
+ } else if (fwdl_in_process) {
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ for (count = 0; count < 5000; count++) {
+ udelay(500);
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
+ if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
+ fwdl_in_process = true;
+ else
+ fwdl_in_process = false;
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload,
+ flags);
+ if (fw_downloaded)
+ goto exit;
+ else if (!fwdl_in_process)
+ break;
+ else
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Wait for another mac "
+ "download fw\n"));
+ }
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ value = rtl_read_byte(rtlpriv, 0x1f);
+ value |= BIT(5);
+ rtl_write_byte(rtlpriv, 0x1f, value);
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ } else {
+ value = rtl_read_byte(rtlpriv, 0x1f);
+ value |= BIT(5);
+ rtl_write_byte(rtlpriv, 0x1f, value);
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ }
+
+ /* If 8051 is running in RAM code, driver should
+ * inform Fw to reset by itself, or it will cause
+ * download Fw fail.*/
+ /* 8051 RAM code */
+ if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
+ rtl92d_firmware_selfreset(hw);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+ }
+ _rtl92d_enable_fw_download(hw, true);
+ _rtl92d_write_fw(hw, version, pfwdata, fwsize);
+ _rtl92d_enable_fw_download(hw, false);
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ err = _rtl92d_fw_free_to_go(hw);
+ /* download fw over,clear 0x1f[5] */
+ value = rtl_read_byte(rtlpriv, 0x1f);
+ value &= (~BIT(5));
+ rtl_write_byte(rtlpriv, 0x1f, value);
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("fw is not ready to run!\n"));
+ goto exit;
+ } else {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ ("fw is ready to run!\n"));
+ }
+exit:
+ err = _rtl92d_fw_init(hw);
+ return err;
+}
+
+static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 val_hmetfr;
+ bool result = false;
+
+ val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+ if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
+ result = true;
+ return result;
+}
+
+static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
+ u8 element_id, u32 cmd_len, u8 *cmdbuffer)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ u8 boxnum;
+ u16 box_reg = 0, box_extreg = 0;
+ u8 u1b_tmp;
+ bool isfw_read = false;
+ u8 buf_index = 0;
+ bool bwrite_sucess = false;
+ u8 wait_h2c_limmit = 100;
+ u8 wait_writeh2c_limmit = 100;
+ u8 boxcontent[4], boxextcontent[2];
+ u32 h2c_waitcounter = 0;
+ unsigned long flag;
+ u8 idx;
+
+ if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Return as RF is off!!!\n"));
+ return;
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
+ while (true) {
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+ if (rtlhal->h2c_setinprogress) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("H2C set in progress! Wait to set.."
+ "element_id(%d).\n", element_id));
+
+ while (rtlhal->h2c_setinprogress) {
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+ flag);
+ h2c_waitcounter++;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Wait 100 us (%d times)...\n",
+ h2c_waitcounter));
+ udelay(100);
+
+ if (h2c_waitcounter > 1000)
+ return;
+
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+ flag);
+ }
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ } else {
+ rtlhal->h2c_setinprogress = true;
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ break;
+ }
+ }
+ while (!bwrite_sucess) {
+ wait_writeh2c_limmit--;
+ if (wait_writeh2c_limmit == 0) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Write H2C fail because no trigger "
+ "for FW INT!\n"));
+ break;
+ }
+ boxnum = rtlhal->last_hmeboxnum;
+ switch (boxnum) {
+ case 0:
+ box_reg = REG_HMEBOX_0;
+ box_extreg = REG_HMEBOX_EXT_0;
+ break;
+ case 1:
+ box_reg = REG_HMEBOX_1;
+ box_extreg = REG_HMEBOX_EXT_1;
+ break;
+ case 2:
+ box_reg = REG_HMEBOX_2;
+ box_extreg = REG_HMEBOX_EXT_2;
+ break;
+ case 3:
+ box_reg = REG_HMEBOX_3;
+ box_extreg = REG_HMEBOX_EXT_3;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
+ while (!isfw_read) {
+ wait_h2c_limmit--;
+ if (wait_h2c_limmit == 0) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Wating too long for FW read "
+ "clear HMEBox(%d)!\n", boxnum));
+ break;
+ }
+ udelay(10);
+ isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
+ u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Wating for FW read clear HMEBox(%d)!!! "
+ "0x1BF = %2x\n", boxnum, u1b_tmp));
+ }
+ if (!isfw_read) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Write H2C register BOX[%d] fail!!!!! "
+ "Fw do not read.\n", boxnum));
+ break;
+ }
+ memset(boxcontent, 0, sizeof(boxcontent));
+ memset(boxextcontent, 0, sizeof(boxextcontent));
+ boxcontent[0] = element_id;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Write element_id box_reg(%4x) = %2x\n",
+ box_reg, element_id));
+ switch (cmd_len) {
+ case 1:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 2:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 3:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 4:
+ boxcontent[0] |= (BIT(7));
+ memcpy(boxextcontent, cmdbuffer + buf_index, 2);
+ memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
+ for (idx = 0; idx < 2; idx++)
+ rtl_write_byte(rtlpriv, box_extreg + idx,
+ boxextcontent[idx]);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 5:
+ boxcontent[0] |= (BIT(7));
+ memcpy(boxextcontent, cmdbuffer + buf_index, 2);
+ memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
+ for (idx = 0; idx < 2; idx++)
+ rtl_write_byte(rtlpriv, box_extreg + idx,
+ boxextcontent[idx]);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ bwrite_sucess = true;
+ rtlhal->last_hmeboxnum = boxnum + 1;
+ if (rtlhal->last_hmeboxnum == 4)
+ rtlhal->last_hmeboxnum = 0;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("pHalData->last_hmeboxnum = %d\n",
+ rtlhal->last_hmeboxnum));
+ }
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+ rtlhal->h2c_setinprogress = false;
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
+}
+
+void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
+ u8 element_id, u32 cmd_len, u8 *cmdbuffer)
+{
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 tmp_cmdbuf[2];
+
+ if (rtlhal->fw_ready == false) {
+ RT_ASSERT(false, ("return H2C cmd because of Fw "
+ "download fail!!!\n"));
+ return;
+ }
+ memset(tmp_cmdbuf, 0, 8);
+ memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
+ _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
+ return;
+}
+
+void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 u1_h2c_set_pwrmode[3] = { 0 };
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
+ SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
+ SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
+ SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
+ ppsc->reg_max_lps_awakeintvl);
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "rtl92d_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
+ u1_h2c_set_pwrmode, 3);
+ rtl92d_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
+}
+
+static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl8192_tx_ring *ring;
+ struct rtl_tx_desc *pdesc;
+ u8 idx = 0;
+ unsigned long flags;
+ struct sk_buff *pskb;
+
+ ring = &rtlpci->tx_ring[BEACON_QUEUE];
+ pskb = __skb_dequeue(&ring->queue);
+ if (pskb)
+ kfree_skb(pskb);
+ spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+ pdesc = &ring->desc[idx];
+ /* discard output from call below */
+ rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
+ rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
+ __skb_queue_tail(&ring->queue, skb);
+ spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+ rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
+ return true;
+}
+
+#define BEACON_PG 0 /*->1 */
+#define PSPOLL_PG 2
+#define NULL_PG 3
+#define PROBERSP_PG 4 /*->5 */
+#define TOTAL_RESERVED_PKT_LEN 768
+
+static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
+ /* page 0 beacon */
+ 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+ 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+ 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+ 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+ 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+ 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+ 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 1 beacon */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 2 ps-poll */
+ 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 3 null */
+ 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 4 probe_resp */
+ 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+ 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
+ 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+ 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+ 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+ 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+ 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+ 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+ 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 5 probe_resp */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct sk_buff *skb = NULL;
+ u32 totalpacketlen;
+ bool rtstatus;
+ u8 u1RsvdPageLoc[3] = { 0 };
+ bool dlok = false;
+ u8 *beacon;
+ u8 *p_pspoll;
+ u8 *nullfunc;
+ u8 *p_probersp;
+ /*---------------------------------------------------------
+ (1) beacon
+ ---------------------------------------------------------*/
+ beacon = &reserved_page_packet[BEACON_PG * 128];
+ SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+ /*-------------------------------------------------------
+ (2) ps-poll
+ --------------------------------------------------------*/
+ p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+ SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+ SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+ SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+ SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+ /*--------------------------------------------------------
+ (3) null data
+ ---------------------------------------------------------*/
+ nullfunc = &reserved_page_packet[NULL_PG * 128];
+ SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+ SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+ SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+ /*---------------------------------------------------------
+ (4) probe response
+ ----------------------------------------------------------*/
+ p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+ SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+ SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+ SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+ totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+ "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+ &reserved_page_packet[0], totalpacketlen);
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+ u1RsvdPageLoc, 3);
+ skb = dev_alloc_skb(totalpacketlen);
+ memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet,
+ totalpacketlen);
+ rtstatus = _rtl92d_cmd_send_packet(hw, skb);
+
+ if (rtstatus)
+ dlok = true;
+ if (dlok) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("Set RSVD page location to Fw.\n"));
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3);
+ rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
+ sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+ } else
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
+}
+
+void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
+{
+ u8 u1_joinbssrpt_parm[1] = {0};
+
+ SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
+ rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h
new file mode 100644
index 000000000000..0c4d489eaa48
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h
@@ -0,0 +1,155 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D__FW__H__
+#define __RTL92D__FW__H__
+
+#define FW_8192D_START_ADDRESS 0x1000
+#define FW_8192D_PAGE_SIZE 4096
+#define FW_8192D_POLLING_TIMEOUT_COUNT 1000
+
+#define IS_FW_HEADER_EXIST(_pfwhdr) \
+ ((GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x92C0 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x88C0 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D0 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D1 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D2 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D3)
+
+/* Define a macro that takes an le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \
+ ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \
+ BIT_LEN_MASK_32(__mask))
+
+/* Firmware Header(8-byte alinment required) */
+/* --- LONG WORD 0 ---- */
+#define GET_FIRMWARE_HDR_SIGNATURE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr, 0, 16)
+#define GET_FIRMWARE_HDR_CATEGORY(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr, 16, 8)
+#define GET_FIRMWARE_HDR_FUNCTION(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr, 24, 8)
+#define GET_FIRMWARE_HDR_VERSION(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 4, 0, 16)
+#define GET_FIRMWARE_HDR_SUB_VER(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 4, 16, 8)
+#define GET_FIRMWARE_HDR_RSVD1(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 4, 24, 8)
+
+/* --- LONG WORD 1 ---- */
+#define GET_FIRMWARE_HDR_MONTH(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 0, 8)
+#define GET_FIRMWARE_HDR_DATE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 8, 8)
+#define GET_FIRMWARE_HDR_HOUR(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 16, 8)
+#define GET_FIRMWARE_HDR_MINUTE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 24, 8)
+#define GET_FIRMWARE_HDR_ROMCODE_SIZE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 12, 0, 16)
+#define GET_FIRMWARE_HDR_RSVD2(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 12, 16, 16)
+
+/* --- LONG WORD 2 ---- */
+#define GET_FIRMWARE_HDR_SVN_IDX(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 16, 0, 32)
+#define GET_FIRMWARE_HDR_RSVD3(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 20, 0, 32)
+
+/* --- LONG WORD 3 ---- */
+#define GET_FIRMWARE_HDR_RSVD4(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 24, 0, 32)
+#define GET_FIRMWARE_HDR_RSVD5(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 28, 0, 32)
+
+#define pagenum_128(_len) \
+ (u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0))
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+
+struct rtl92d_firmware_header {
+ u16 signature;
+ u8 category;
+ u8 function;
+ u16 version;
+ u8 subversion;
+ u8 rsvd1;
+
+ u8 month;
+ u8 date;
+ u8 hour;
+ u8 minute;
+ u16 ramcodeSize;
+ u16 rsvd2;
+
+ u32 svnindex;
+ u32 rsvd3;
+
+ u32 rsvd4;
+ u32 rsvd5;
+};
+
+enum rtl8192d_h2c_cmd {
+ H2C_AP_OFFLOAD = 0,
+ H2C_SETPWRMODE = 1,
+ H2C_JOINBSSRPT = 2,
+ H2C_RSVDPAGE = 3,
+ H2C_RSSI_REPORT = 5,
+ H2C_RA_MASK = 6,
+ H2C_MAC_MODE_SEL = 9,
+ H2C_PWRM = 15,
+ MAX_H2CCMD
+};
+
+int rtl92d_download_fw(struct ieee80211_hw *hw);
+void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+ u32 cmd_len, u8 *p_cmdbuffer);
+void rtl92d_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
new file mode 100644
index 000000000000..0073cf106af2
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
@@ -0,0 +1,2329 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../efuse.h"
+#include "../base.h"
+#include "../regd.h"
+#include "../cam.h"
+#include "../ps.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "led.h"
+#include "sw.h"
+#include "hw.h"
+
+u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 value;
+
+ rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC));
+ rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct);
+ udelay(10);
+ value = rtl_read_dword(rtlpriv, REG_DBI_RDATA);
+ return value;
+}
+
+void rtl92de_write_dword_dbi(struct ieee80211_hw *hw,
+ u16 offset, u32 value, u8 direct)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000));
+ rtl_write_dword(rtlpriv, REG_DBI_WDATA, value);
+ rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct);
+}
+
+static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
+ u8 set_bits, u8 clear_bits)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpci->reg_bcn_ctrl_val |= set_bits;
+ rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
+ rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
+}
+
+static void _rtl92de_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp1byte;
+
+ tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6)));
+ rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
+ tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+ tmp1byte &= ~(BIT(0));
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl92de_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp1byte;
+
+ tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6));
+ rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+ tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+ tmp1byte |= BIT(0);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1));
+}
+
+static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0);
+}
+
+void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ switch (variable) {
+ case HW_VAR_RCR:
+ *((u32 *) (val)) = rtlpci->receive_config;
+ break;
+ case HW_VAR_RF_STATE:
+ *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+ break;
+ case HW_VAR_FWLPS_RF_ON:{
+ enum rf_pwrstate rfState;
+ u32 val_rcr;
+
+ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
+ (u8 *) (&rfState));
+ if (rfState == ERFOFF) {
+ *((bool *) (val)) = true;
+ } else {
+ val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+ val_rcr &= 0x00070000;
+ if (val_rcr)
+ *((bool *) (val)) = false;
+ else
+ *((bool *) (val)) = true;
+ }
+ break;
+ }
+ case HW_VAR_FW_PSMODE_STATUS:
+ *((bool *) (val)) = ppsc->fw_current_inpsmode;
+ break;
+ case HW_VAR_CORRECT_TSF:{
+ u64 tsf;
+ u32 *ptsf_low = (u32 *)&tsf;
+ u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+ *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
+ *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+ *((u64 *) (val)) = tsf;
+ break;
+ }
+ case HW_VAR_INT_MIGRATION:
+ *((bool *)(val)) = rtlpriv->dm.interrupt_migration;
+ break;
+ case HW_VAR_INT_AC:
+ *((bool *)(val)) = rtlpriv->dm.disable_tx_int;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+}
+
+void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ u8 idx;
+
+ switch (variable) {
+ case HW_VAR_ETHER_ADDR:
+ for (idx = 0; idx < ETH_ALEN; idx++) {
+ rtl_write_byte(rtlpriv, (REG_MACID + idx),
+ val[idx]);
+ }
+ break;
+ case HW_VAR_BASIC_RATE: {
+ u16 rate_cfg = ((u16 *) val)[0];
+ u8 rate_index = 0;
+
+ rate_cfg = rate_cfg & 0x15f;
+ if (mac->vendor == PEER_CISCO &&
+ ((rate_cfg & 0x150) == 0))
+ rate_cfg |= 0x01;
+ rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
+ rtl_write_byte(rtlpriv, REG_RRSR + 1,
+ (rate_cfg >> 8) & 0xff);
+ while (rate_cfg > 0x1) {
+ rate_cfg = (rate_cfg >> 1);
+ rate_index++;
+ }
+ if (rtlhal->fw_version > 0xe)
+ rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
+ rate_index);
+ break;
+ }
+ case HW_VAR_BSSID:
+ for (idx = 0; idx < ETH_ALEN; idx++) {
+ rtl_write_byte(rtlpriv, (REG_BSSID + idx),
+ val[idx]);
+ }
+ break;
+ case HW_VAR_SIFS:
+ rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]);
+ rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]);
+ rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
+ rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
+ if (!mac->ht_enable)
+ rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+ 0x0e0e);
+ else
+ rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+ *((u16 *) val));
+ break;
+ case HW_VAR_SLOT_TIME: {
+ u8 e_aci;
+
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("HW_VAR_SLOT_TIME %x\n", val[0]));
+ rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
+ for (e_aci = 0; e_aci < AC_MAX; e_aci++)
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_AC_PARAM,
+ (u8 *) (&e_aci));
+ break;
+ }
+ case HW_VAR_ACK_PREAMBLE: {
+ u8 reg_tmp;
+ u8 short_preamble = (bool) (*(u8 *) val);
+
+ reg_tmp = (mac->cur_40_prime_sc) << 5;
+ if (short_preamble)
+ reg_tmp |= 0x80;
+ rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp);
+ break;
+ }
+ case HW_VAR_AMPDU_MIN_SPACE: {
+ u8 min_spacing_to_set;
+ u8 sec_min_space;
+
+ min_spacing_to_set = *((u8 *) val);
+ if (min_spacing_to_set <= 7) {
+ sec_min_space = 0;
+ if (min_spacing_to_set < sec_min_space)
+ min_spacing_to_set = sec_min_space;
+ mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) |
+ min_spacing_to_set);
+ *val = min_spacing_to_set;
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
+ mac->min_space_cfg));
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+ mac->min_space_cfg);
+ }
+ break;
+ }
+ case HW_VAR_SHORTGI_DENSITY: {
+ u8 density_to_set;
+
+ density_to_set = *((u8 *) val);
+ mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg;
+ mac->min_space_cfg |= (density_to_set << 3);
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("Set HW_VAR_SHORTGI_DENSITY: %#x\n",
+ mac->min_space_cfg));
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+ mac->min_space_cfg);
+ break;
+ }
+ case HW_VAR_AMPDU_FACTOR: {
+ u8 factor_toset;
+ u32 regtoSet;
+ u8 *ptmp_byte = NULL;
+ u8 index;
+
+ if (rtlhal->macphymode == DUALMAC_DUALPHY)
+ regtoSet = 0xb9726641;
+ else if (rtlhal->macphymode == DUALMAC_SINGLEPHY)
+ regtoSet = 0x66626641;
+ else
+ regtoSet = 0xb972a841;
+ factor_toset = *((u8 *) val);
+ if (factor_toset <= 3) {
+ factor_toset = (1 << (factor_toset + 2));
+ if (factor_toset > 0xf)
+ factor_toset = 0xf;
+ for (index = 0; index < 4; index++) {
+ ptmp_byte = (u8 *) (&regtoSet) + index;
+ if ((*ptmp_byte & 0xf0) >
+ (factor_toset << 4))
+ *ptmp_byte = (*ptmp_byte & 0x0f)
+ | (factor_toset << 4);
+ if ((*ptmp_byte & 0x0f) > factor_toset)
+ *ptmp_byte = (*ptmp_byte & 0xf0)
+ | (factor_toset);
+ }
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet);
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("Set HW_VAR_AMPDU_FACTOR: %#x\n",
+ factor_toset));
+ }
+ break;
+ }
+ case HW_VAR_AC_PARAM: {
+ u8 e_aci = *((u8 *) val);
+ rtl92d_dm_init_edca_turbo(hw);
+ if (rtlpci->acm_method != eAcmWay2_SW)
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL,
+ (u8 *) (&e_aci));
+ break;
+ }
+ case HW_VAR_ACM_CTRL: {
+ u8 e_aci = *((u8 *) val);
+ union aci_aifsn *p_aci_aifsn =
+ (union aci_aifsn *)(&(mac->ac[0].aifs));
+ u8 acm = p_aci_aifsn->f.acm;
+ u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
+
+ acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
+ if (acm) {
+ switch (e_aci) {
+ case AC0_BE:
+ acm_ctrl |= ACMHW_BEQEN;
+ break;
+ case AC2_VI:
+ acm_ctrl |= ACMHW_VIQEN;
+ break;
+ case AC3_VO:
+ acm_ctrl |= ACMHW_VOQEN;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("HW_VAR_ACM_CTRL acm set "
+ "failed: eACI is %d\n", acm));
+ break;
+ }
+ } else {
+ switch (e_aci) {
+ case AC0_BE:
+ acm_ctrl &= (~ACMHW_BEQEN);
+ break;
+ case AC2_VI:
+ acm_ctrl &= (~ACMHW_VIQEN);
+ break;
+ case AC3_VO:
+ acm_ctrl &= (~ACMHW_VOQEN);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
+ ("SetHwReg8190pci(): [HW_VAR_ACM_CTRL] "
+ "Write 0x%X\n", acm_ctrl));
+ rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
+ break;
+ }
+ case HW_VAR_RCR:
+ rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]);
+ rtlpci->receive_config = ((u32 *) (val))[0];
+ break;
+ case HW_VAR_RETRY_LIMIT: {
+ u8 retry_limit = ((u8 *) (val))[0];
+
+ rtl_write_word(rtlpriv, REG_RL,
+ retry_limit << RETRY_LIMIT_SHORT_SHIFT |
+ retry_limit << RETRY_LIMIT_LONG_SHIFT);
+ break;
+ }
+ case HW_VAR_DUAL_TSF_RST:
+ rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+ break;
+ case HW_VAR_EFUSE_BYTES:
+ rtlefuse->efuse_usedbytes = *((u16 *) val);
+ break;
+ case HW_VAR_EFUSE_USAGE:
+ rtlefuse->efuse_usedpercentage = *((u8 *) val);
+ break;
+ case HW_VAR_IO_CMD:
+ rtl92d_phy_set_io_cmd(hw, (*(enum io_type *)val));
+ break;
+ case HW_VAR_WPA_CONFIG:
+ rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val));
+ break;
+ case HW_VAR_SET_RPWM:
+ rtl92d_fill_h2c_cmd(hw, H2C_PWRM, 1, (u8 *) (val));
+ break;
+ case HW_VAR_H2C_FW_PWRMODE:
+ break;
+ case HW_VAR_FW_PSMODE_STATUS:
+ ppsc->fw_current_inpsmode = *((bool *) val);
+ break;
+ case HW_VAR_H2C_FW_JOINBSSRPT: {
+ u8 mstatus = (*(u8 *) val);
+ u8 tmp_regcr, tmp_reg422;
+ bool recover = false;
+
+ if (mstatus == RT_MEDIA_CONNECT) {
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_AID, NULL);
+ tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1);
+ rtl_write_byte(rtlpriv, REG_CR + 1,
+ (tmp_regcr | BIT(0)));
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3));
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0);
+ tmp_reg422 = rtl_read_byte(rtlpriv,
+ REG_FWHW_TXQ_CTRL + 2);
+ if (tmp_reg422 & BIT(6))
+ recover = true;
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+ tmp_reg422 & (~BIT(6)));
+ rtl92d_set_fw_rsvdpagepkt(hw, 0);
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0);
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4));
+ if (recover)
+ rtl_write_byte(rtlpriv,
+ REG_FWHW_TXQ_CTRL + 2,
+ tmp_reg422);
+ rtl_write_byte(rtlpriv, REG_CR + 1,
+ (tmp_regcr & ~(BIT(0))));
+ }
+ rtl92d_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
+ break;
+ }
+ case HW_VAR_AID: {
+ u16 u2btmp;
+ u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
+ u2btmp &= 0xC000;
+ rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
+ mac->assoc_id));
+ break;
+ }
+ case HW_VAR_CORRECT_TSF: {
+ u8 btype_ibss = ((u8 *) (val))[0];
+
+ if (btype_ibss)
+ _rtl92de_stop_tx_beacon(hw);
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3));
+ rtl_write_dword(rtlpriv, REG_TSFTR,
+ (u32) (mac->tsf & 0xffffffff));
+ rtl_write_dword(rtlpriv, REG_TSFTR + 4,
+ (u32) ((mac->tsf >> 32) & 0xffffffff));
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0);
+ if (btype_ibss)
+ _rtl92de_resume_tx_beacon(hw);
+
+ break;
+ }
+ case HW_VAR_INT_MIGRATION: {
+ bool int_migration = *(bool *) (val);
+
+ if (int_migration) {
+ /* Set interrrupt migration timer and
+ * corresponging Tx/Rx counter.
+ * timer 25ns*0xfa0=100us for 0xf packets.
+ * 0x306:Rx, 0x307:Tx */
+ rtl_write_dword(rtlpriv, REG_INT_MIG, 0xfe000fa0);
+ rtlpriv->dm.interrupt_migration = int_migration;
+ } else {
+ /* Reset all interrupt migration settings. */
+ rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+ rtlpriv->dm.interrupt_migration = int_migration;
+ }
+ break;
+ }
+ case HW_VAR_INT_AC: {
+ bool disable_ac_int = *((bool *) val);
+
+ /* Disable four ACs interrupts. */
+ if (disable_ac_int) {
+ /* Disable VO, VI, BE and BK four AC interrupts
+ * to gain more efficient CPU utilization.
+ * When extremely highly Rx OK occurs,
+ * we will disable Tx interrupts.
+ */
+ rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
+ RT_AC_INT_MASKS);
+ rtlpriv->dm.disable_tx_int = disable_ac_int;
+ /* Enable four ACs interrupts. */
+ } else {
+ rtlpriv->cfg->ops->update_interrupt_mask(hw,
+ RT_AC_INT_MASKS, 0);
+ rtlpriv->dm.disable_tx_int = disable_ac_int;
+ }
+ break;
+ }
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+}
+
+static bool _rtl92de_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ bool status = true;
+ long count = 0;
+ u32 value = _LLT_INIT_ADDR(address) |
+ _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+
+ rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
+ do {
+ value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
+ if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+ break;
+ if (count > POLLING_LLT_THRESHOLD) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Failed to polling write LLT done at "
+ "address %d!\n", address));
+ status = false;
+ break;
+ }
+ } while (++count);
+ return status;
+}
+
+static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ unsigned short i;
+ u8 txpktbuf_bndy;
+ u8 maxPage;
+ bool status;
+ u32 value32; /* High+low page number */
+ u8 value8; /* normal page number */
+
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) {
+ maxPage = 255;
+ txpktbuf_bndy = 246;
+ value8 = 0;
+ value32 = 0x80bf0d29;
+ } else if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+ maxPage = 127;
+ txpktbuf_bndy = 123;
+ value8 = 0;
+ value32 = 0x80750005;
+ }
+
+ /* Set reserved page for each queue */
+ /* 11. RQPN 0x200[31:0] = 0x80BD1C1C */
+ /* load RQPN */
+ rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8);
+ rtl_write_dword(rtlpriv, REG_RQPN, value32);
+
+ /* 12. TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 */
+ /* TXRKTBUG_PG_BNDY */
+ rtl_write_dword(rtlpriv, REG_TRXFF_BNDY,
+ (rtl_read_word(rtlpriv, REG_TRXFF_BNDY + 2) << 16 |
+ txpktbuf_bndy));
+
+ /* 13. TDECTRL[15:8] 0x209[7:0] = 0xF6 */
+ /* Beacon Head for TXDMA */
+ rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
+
+ /* 14. BCNQ_PGBNDY 0x424[7:0] = 0xF6 */
+ /* BCNQ_PGBNDY */
+ rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+ rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+
+ /* 15. WMAC_LBK_BF_HD 0x45D[7:0] = 0xF6 */
+ /* WMAC_LBK_BF_HD */
+ rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
+
+ /* Set Tx/Rx page size (Tx must be 128 Bytes, */
+ /* Rx can be 64,128,256,512,1024 bytes) */
+ /* 16. PBP [7:0] = 0x11 */
+ /* TRX page size */
+ rtl_write_byte(rtlpriv, REG_PBP, 0x11);
+
+ /* 17. DRV_INFO_SZ = 0x04 */
+ rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
+
+ /* 18. LLT_table_init(Adapter); */
+ for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+ status = _rtl92de_llt_write(hw, i, i + 1);
+ if (true != status)
+ return status;
+ }
+
+ /* end of list */
+ status = _rtl92de_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
+ if (true != status)
+ return status;
+
+ /* Make the other pages as ring buffer */
+ /* This ring buffer is used as beacon buffer if we */
+ /* config this MAC as two MAC transfer. */
+ /* Otherwise used as local loopback buffer. */
+ for (i = txpktbuf_bndy; i < maxPage; i++) {
+ status = _rtl92de_llt_write(hw, i, (i + 1));
+ if (true != status)
+ return status;
+ }
+
+ /* Let last entry point to the start entry of ring buffer */
+ status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy);
+ if (true != status)
+ return status;
+
+ return true;
+}
+
+static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+ if (rtlpci->up_first_time)
+ return;
+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+ rtl92de_sw_led_on(hw, pLed0);
+ else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
+ rtl92de_sw_led_on(hw, pLed0);
+ else
+ rtl92de_sw_led_off(hw, pLed0);
+}
+
+static bool _rtl92de_init_mac(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ unsigned char bytetmp;
+ unsigned short wordtmp;
+ u16 retry;
+
+ rtl92d_phy_set_poweron(hw);
+ /* Add for resume sequence of power domain according
+ * to power document V11. Chapter V.11.... */
+ /* 0. RSV_CTRL 0x1C[7:0] = 0x00 */
+ /* unlock ISO/CLK/Power control register */
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
+ rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x05);
+
+ /* 1. AFE_XTAL_CTRL [7:0] = 0x0F enable XTAL */
+ /* 2. SPS0_CTRL 0x11[7:0] = 0x2b enable SPS into PWM mode */
+ /* 3. delay (1ms) this is not necessary when initially power on */
+
+ /* C. Resume Sequence */
+ /* a. SPS0_CTRL 0x11[7:0] = 0x2b */
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+
+ /* b. AFE_XTAL_CTRL [7:0] = 0x0F */
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F);
+
+ /* c. DRV runs power on init flow */
+
+ /* auto enable WLAN */
+ /* 4. APS_FSMCO 0x04[8] = 1; wait till 0x04[8] = 0 */
+ /* Power On Reset for MAC Block */
+ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0);
+ udelay(2);
+ rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp);
+ udelay(2);
+
+ /* 5. Wait while 0x04[8] == 0 goto 2, otherwise goto 1 */
+ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1);
+ udelay(50);
+ retry = 0;
+ while ((bytetmp & BIT(0)) && retry < 1000) {
+ retry++;
+ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1);
+ udelay(50);
+ }
+
+ /* Enable Radio off, GPIO, and LED function */
+ /* 6. APS_FSMCO 0x04[15:0] = 0x0012 when enable HWPDN */
+ rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012);
+
+ /* release RF digital isolation */
+ /* 7. SYS_ISO_CTRL 0x01[1] = 0x0; */
+ /*Set REG_SYS_ISO_CTRL 0x1=0x82 to prevent wake# problem. */
+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82);
+ udelay(2);
+
+ /* make sure that BB reset OK. */
+ /* rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); */
+
+ /* Disable REG_CR before enable it to assure reset */
+ rtl_write_word(rtlpriv, REG_CR, 0x0);
+
+ /* Release MAC IO register reset */
+ rtl_write_word(rtlpriv, REG_CR, 0x2ff);
+
+ /* clear stopping tx/rx dma */
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x0);
+
+ /* rtl_write_word(rtlpriv,REG_CR+2, 0x2); */
+
+ /* System init */
+ /* 18. LLT_table_init(Adapter); */
+ if (_rtl92de_llt_table_init(hw) == false)
+ return false;
+
+ /* Clear interrupt and enable interrupt */
+ /* 19. HISR 0x124[31:0] = 0xffffffff; */
+ /* HISRE 0x12C[7:0] = 0xFF */
+ rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
+ rtl_write_byte(rtlpriv, REG_HISRE, 0xff);
+
+ /* 20. HIMR 0x120[31:0] |= [enable INT mask bit map]; */
+ /* 21. HIMRE 0x128[7:0] = [enable INT mask bit map] */
+ /* The IMR should be enabled later after all init sequence
+ * is finished. */
+
+ /* 22. PCIE configuration space configuration */
+ /* 23. Ensure PCIe Device 0x80[15:0] = 0x0143 (ASPM+CLKREQ), */
+ /* and PCIe gated clock function is enabled. */
+ /* PCIE configuration space will be written after
+ * all init sequence.(Or by BIOS) */
+
+ rtl92d_phy_config_maccoexist_rfpage(hw);
+
+ /* THe below section is not related to power document Vxx . */
+ /* This is only useful for driver and OS setting. */
+ /* -------------------Software Relative Setting---------------------- */
+ wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL);
+ wordtmp &= 0xf;
+ wordtmp |= 0xF771;
+ rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
+
+ /* Reported Tx status from HW for rate adaptive. */
+ /* This should be realtive to power on step 14. But in document V11 */
+ /* still not contain the description.!!! */
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F);
+
+ /* Set Tx/Rx page size (Tx must be 128 Bytes,
+ * Rx can be 64,128,256,512,1024 bytes) */
+ /* rtl_write_byte(rtlpriv,REG_PBP, 0x11); */
+
+ /* Set RCR register */
+ rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+ /* rtl_write_byte(rtlpriv,REG_RX_DRVINFO_SZ, 4); */
+
+ /* Set TCR register */
+ rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
+
+ /* disable earlymode */
+ rtl_write_byte(rtlpriv, 0x4d0, 0x0);
+
+ /* Set TX/RX descriptor physical address(from OS API). */
+ rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
+ rtlpci->tx_ring[BEACON_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_MGQ_DESA, rtlpci->tx_ring[MGNT_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_VOQ_DESA, rtlpci->tx_ring[VO_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_VIQ_DESA, rtlpci->tx_ring[VI_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_BEQ_DESA, rtlpci->tx_ring[BE_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_BKQ_DESA, rtlpci->tx_ring[BK_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_HQ_DESA, rtlpci->tx_ring[HIGH_QUEUE].dma);
+ /* Set RX Desc Address */
+ rtl_write_dword(rtlpriv, REG_RX_DESA,
+ rtlpci->rx_ring[RX_MPDU_QUEUE].dma);
+
+ /* if we want to support 64 bit DMA, we should set it here,
+ * but now we do not support 64 bit DMA*/
+
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x33);
+
+ /* Reset interrupt migration setting when initialization */
+ rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+
+ /* Reconsider when to do this operation after asking HWSD. */
+ bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6));
+ do {
+ retry++;
+ bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+ } while ((retry < 200) && !(bytetmp & BIT(7)));
+
+ /* After MACIO reset,we must refresh LED state. */
+ _rtl92de_gen_refresh_led_state(hw);
+
+ /* Reset H2C protection register */
+ rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
+
+ return true;
+}
+
+static void _rtl92de_hw_configure(struct ieee80211_hw *hw)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 reg_bw_opmode = BW_OPMODE_20MHZ;
+ u32 reg_rrsr;
+
+ reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+ rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr);
+ rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0);
+ rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80);
+ rtl_write_word(rtlpriv, REG_RL, 0x0707);
+ rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802);
+ rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+ rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000);
+ rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504);
+ rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000);
+ rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504);
+ /* Aggregation threshold */
+ if (rtlhal->macphymode == DUALMAC_DUALPHY)
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb9726641);
+ else if (rtlhal->macphymode == DUALMAC_SINGLEPHY)
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x66626641);
+ else
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841);
+ rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2);
+ rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a);
+ rtlpci->reg_bcn_ctrl_val = 0x1f;
+ rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+ rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
+ rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+ /* For throughput */
+ rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0x6666);
+ /* ACKTO for IOT issue. */
+ rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
+ /* Set Spec SIFS (used in NAV) */
+ rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010);
+ rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010);
+ /* Set SIFS for CCK */
+ rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010);
+ /* Set SIFS for OFDM */
+ rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010);
+ /* Set Multicast Address. */
+ rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff);
+ rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff);
+ switch (rtlpriv->phy.rf_type) {
+ case RF_1T2R:
+ case RF_1T1R:
+ rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3);
+ break;
+ case RF_2T2R:
+ case RF_2T2R_GREEN:
+ rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3);
+ break;
+ }
+}
+
+static void _rtl92de_enable_aspm_back_door(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ rtl_write_byte(rtlpriv, 0x34b, 0x93);
+ rtl_write_word(rtlpriv, 0x350, 0x870c);
+ rtl_write_byte(rtlpriv, 0x352, 0x1);
+ if (ppsc->support_backdoor)
+ rtl_write_byte(rtlpriv, 0x349, 0x1b);
+ else
+ rtl_write_byte(rtlpriv, 0x349, 0x03);
+ rtl_write_word(rtlpriv, 0x350, 0x2718);
+ rtl_write_byte(rtlpriv, 0x352, 0x1);
+}
+
+void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 sec_reg_value;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+ rtlpriv->sec.pairwise_enc_algorithm,
+ rtlpriv->sec.group_enc_algorithm));
+ if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("not open hw encryption\n"));
+ return;
+ }
+ sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE;
+ if (rtlpriv->sec.use_defaultkey) {
+ sec_reg_value |= SCR_TXUSEDK;
+ sec_reg_value |= SCR_RXUSEDK;
+ }
+ sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+ rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+ ("The SECR-value %x\n", sec_reg_value));
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+}
+
+int rtl92de_hw_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ bool rtstatus = true;
+ u8 tmp_u1b;
+ int i;
+ int err;
+ unsigned long flags;
+
+ rtlpci->being_init_adapter = true;
+ rtlpci->init_ready = false;
+ spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags);
+ /* we should do iqk after disable/enable */
+ rtl92d_phy_reset_iqk_result(hw);
+ /* rtlpriv->intf_ops->disable_aspm(hw); */
+ rtstatus = _rtl92de_init_mac(hw);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Init MAC failed\n"));
+ err = 1;
+ spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+ return err;
+ }
+ err = rtl92d_download_fw(hw);
+ spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("Failed to download FW. Init HW "
+ "without FW..\n"));
+ rtlhal->fw_ready = false;
+ return 1;
+ } else {
+ rtlhal->fw_ready = true;
+ }
+ rtlhal->last_hmeboxnum = 0;
+ rtlpriv->psc.fw_current_inpsmode = false;
+
+ tmp_u1b = rtl_read_byte(rtlpriv, 0x605);
+ tmp_u1b = tmp_u1b | 0x30;
+ rtl_write_byte(rtlpriv, 0x605, tmp_u1b);
+
+ if (rtlhal->earlymode_enable) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EarlyMode Enabled!!!\n"));
+
+ tmp_u1b = rtl_read_byte(rtlpriv, 0x4d0);
+ tmp_u1b = tmp_u1b | 0x1f;
+ rtl_write_byte(rtlpriv, 0x4d0, tmp_u1b);
+
+ rtl_write_byte(rtlpriv, 0x4d3, 0x80);
+
+ tmp_u1b = rtl_read_byte(rtlpriv, 0x605);
+ tmp_u1b = tmp_u1b | 0x40;
+ rtl_write_byte(rtlpriv, 0x605, tmp_u1b);
+ }
+
+ if (mac->rdg_en) {
+ rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xff);
+ rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
+ rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
+ }
+
+ rtl92d_phy_mac_config(hw);
+ /* because last function modify RCR, so we update
+ * rcr var here, or TP will unstable for receive_config
+ * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+ * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/
+ rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+ rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+
+ rtl92d_phy_bb_config(hw);
+
+ rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+ /* set before initialize RF */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+
+ /* config RF */
+ rtl92d_phy_rf_config(hw);
+
+ /* After read predefined TXT, we must set BB/MAC/RF
+ * register as our requirement */
+ /* After load BB,RF params,we need do more for 92D. */
+ rtl92d_update_bbrf_configuration(hw);
+ /* set default value after initialize RF, */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0);
+ rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+ RF_CHNLBW, BRFREGOFFSETMASK);
+ rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
+ RF_CHNLBW, BRFREGOFFSETMASK);
+
+ /*---- Set CCK and OFDM Block "ON"----*/
+ if (rtlhal->current_bandtype == BAND_ON_2_4G)
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+ if (rtlhal->interfaceindex == 0) {
+ /* RFPGA0_ANALOGPARAMETER2: cck clock select,
+ * set to 20MHz by default */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+ BIT(11), 3);
+ } else {
+ /* Mac1 */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(11) |
+ BIT(10), 3);
+ }
+
+ _rtl92de_hw_configure(hw);
+
+ /* reset hw sec */
+ rtl_cam_reset_all_entry(hw);
+ rtl92de_enable_hw_security_config(hw);
+
+ /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */
+ /* TX power index for different rate set. */
+ rtl92d_phy_get_hw_reg_originalvalue(hw);
+ rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+
+ ppsc->rfpwr_state = ERFON;
+
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+
+ _rtl92de_enable_aspm_back_door(hw);
+ /* rtlpriv->intf_ops->enable_aspm(hw); */
+
+ rtl92d_dm_init(hw);
+ rtlpci->being_init_adapter = false;
+
+ if (ppsc->rfpwr_state == ERFON) {
+ rtl92d_phy_lc_calibrate(hw);
+ /* 5G and 2.4G must wait sometime to let RF LO ready */
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ u32 tmp_rega;
+ for (i = 0; i < 10000; i++) {
+ udelay(MAX_STALL_TIME);
+
+ tmp_rega = rtl_get_rfreg(hw,
+ (enum radio_path)RF90_PATH_A,
+ 0x2a, BMASKDWORD);
+
+ if (((tmp_rega & BIT(11)) == BIT(11)))
+ break;
+ }
+ /* check that loop was successful. If not, exit now */
+ if (i == 10000) {
+ rtlpci->init_ready = false;
+ return 1;
+ }
+ }
+ }
+ rtlpci->init_ready = true;
+ return err;
+}
+
+static enum version_8192d _rtl92de_read_chip_version(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ enum version_8192d version = VERSION_NORMAL_CHIP_92D_SINGLEPHY;
+ u32 value32;
+
+ value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+ if (!(value32 & 0x000f0000)) {
+ version = VERSION_TEST_CHIP_92D_SINGLEPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("TEST CHIP!!!\n"));
+ } else {
+ version = VERSION_NORMAL_CHIP_92D_SINGLEPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Normal CHIP!!!\n"));
+ }
+ return version;
+}
+
+static int _rtl92de_set_media_status(struct ieee80211_hw *hw,
+ enum nl80211_iftype type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
+ enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
+ u8 bcnfunc_enable;
+
+ bt_msr &= 0xfc;
+
+ if (type == NL80211_IFTYPE_UNSPECIFIED ||
+ type == NL80211_IFTYPE_STATION) {
+ _rtl92de_stop_tx_beacon(hw);
+ _rtl92de_enable_bcn_sub_func(hw);
+ } else if (type == NL80211_IFTYPE_ADHOC ||
+ type == NL80211_IFTYPE_AP) {
+ _rtl92de_resume_tx_beacon(hw);
+ _rtl92de_disable_bcn_sub_func(hw);
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("Set HW_VAR_MEDIA_STATUS: No such media "
+ "status(%x).\n", type));
+ }
+ bcnfunc_enable = rtl_read_byte(rtlpriv, REG_BCN_CTRL);
+ switch (type) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ bt_msr |= MSR_NOLINK;
+ ledaction = LED_CTL_LINK;
+ bcnfunc_enable &= 0xF7;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to NO LINK!\n"));
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ bt_msr |= MSR_ADHOC;
+ bcnfunc_enable |= 0x08;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to Ad Hoc!\n"));
+ break;
+ case NL80211_IFTYPE_STATION:
+ bt_msr |= MSR_INFRA;
+ ledaction = LED_CTL_LINK;
+ bcnfunc_enable &= 0xF7;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to STA!\n"));
+ break;
+ case NL80211_IFTYPE_AP:
+ bt_msr |= MSR_AP;
+ bcnfunc_enable |= 0x08;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to AP!\n"));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Network type %d not support!\n", type));
+ return 1;
+ break;
+
+ }
+ rtl_write_byte(rtlpriv, REG_CR + 2, bt_msr);
+ rtlpriv->cfg->ops->led_control(hw, ledaction);
+ if ((bt_msr & 0xfc) == MSR_AP)
+ rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
+ else
+ rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
+ return 0;
+}
+
+void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ u32 reg_rcr = rtlpci->receive_config;
+
+ if (rtlpriv->psc.rfpwr_state != ERFON)
+ return;
+ if (check_bssid) {
+ reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4));
+ } else if (check_bssid == false) {
+ reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0);
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
+ }
+}
+
+int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (_rtl92de_set_media_status(hw, type))
+ return -EOPNOTSUPP;
+
+ /* check bssid */
+ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+ if (type != NL80211_IFTYPE_AP)
+ rtl92de_set_check_bssid(hw, true);
+ } else {
+ rtl92de_set_check_bssid(hw, false);
+ }
+ return 0;
+}
+
+/* do iqk or reload iqk */
+/* windows just rtl92d_phy_reload_iqk_setting in set channel,
+ * but it's very strict for time sequence so we add
+ * rtl92d_phy_reload_iqk_setting here */
+void rtl92d_linked_set_reg(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 indexforchannel;
+ u8 channel = rtlphy->current_channel;
+
+ indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel);
+ if (!rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done) {
+ RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG,
+ ("Do IQK for channel:%d.\n", channel));
+ rtl92d_phy_iq_calibrate(hw);
+ }
+}
+
+/* don't set REG_EDCA_BE_PARAM here because
+ * mac80211 will send pkt when scan */
+void rtl92de_set_qos(struct ieee80211_hw *hw, int aci)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ rtl92d_dm_init_edca_turbo(hw);
+ return;
+ switch (aci) {
+ case AC1_BK:
+ rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f);
+ break;
+ case AC0_BE:
+ break;
+ case AC2_VI:
+ rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322);
+ break;
+ case AC3_VO:
+ rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222);
+ break;
+ default:
+ RT_ASSERT(false, ("invalid aci: %d !\n", aci));
+ break;
+ }
+}
+
+void rtl92de_enable_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
+ rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
+}
+
+void rtl92de_disable_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
+ rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
+ synchronize_irq(rtlpci->pdev->irq);
+}
+
+static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 u1b_tmp;
+ unsigned long flags;
+
+ rtlpriv->intf_ops->enable_aspm(hw);
+ rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(3), 0);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(15), 0);
+
+ /* 0x20:value 05-->04 */
+ rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04);
+
+ /* ==== Reset digital sequence ====== */
+ rtl92d_firmware_selfreset(hw);
+
+ /* f. SYS_FUNC_EN 0x03[7:0]=0x51 reset MCU, MAC register, DCORE */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
+
+ /* g. MCUFWDL 0x80[1:0]=0 reset MCU ready status */
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+
+ /* ==== Pull GPIO PIN to balance level and LED control ====== */
+
+ /* h. GPIO_PIN_CTRL 0x44[31:0]=0x000 */
+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000);
+
+ /* i. Value = GPIO_PIN_CTRL[7:0] */
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL);
+
+ /* j. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); */
+ /* write external PIN level */
+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL,
+ 0x00FF0000 | (u1b_tmp << 8));
+
+ /* k. GPIO_MUXCFG 0x42 [15:0] = 0x0780 */
+ rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
+
+ /* l. LEDCFG 0x4C[15:0] = 0x8080 */
+ rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
+
+ /* ==== Disable analog sequence === */
+
+ /* m. AFE_PLL_CTRL[7:0] = 0x80 disable PLL */
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
+
+ /* n. SPS0_CTRL 0x11[7:0] = 0x22 enter PFM mode */
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+
+ /* o. AFE_XTAL_CTRL 0x24[7:0] = 0x0E disable XTAL, if No BT COEX */
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e);
+
+ /* p. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e);
+
+ /* ==== interface into suspend === */
+
+ /* q. APS_FSMCO[15:8] = 0x58 PCIe suspend mode */
+ /* According to power document V11, we need to set this */
+ /* value as 0x18. Otherwise, we may not L0s sometimes. */
+ /* This indluences power consumption. Bases on SD1's test, */
+ /* set as 0x00 do not affect power current. And if it */
+ /* is set as 0x18, they had ever met auto load fail problem. */
+ rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("In PowerOff,reg0x%x=%X\n", REG_SPS0_CTRL,
+ rtl_read_byte(rtlpriv, REG_SPS0_CTRL)));
+ /* r. Note: for PCIe interface, PON will not turn */
+ /* off m-bias and BandGap in PCIe suspend mode. */
+
+ /* 0x17[7] 1b': power off in process 0b' : power off over */
+ if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+ spin_lock_irqsave(&globalmutex_power, flags);
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+ u1b_tmp &= (~BIT(7));
+ rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1b_tmp);
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ }
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<=======\n"));
+}
+
+void rtl92de_card_disable(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ enum nl80211_iftype opmode;
+
+ mac->link_state = MAC80211_NOLINK;
+ opmode = NL80211_IFTYPE_UNSPECIFIED;
+ _rtl92de_set_media_status(hw, opmode);
+
+ if (rtlpci->driver_is_goingto_unload ||
+ ppsc->rfoff_reason > RF_CHANGE_BY_PS)
+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ /* Power sequence for each MAC. */
+ /* a. stop tx DMA */
+ /* b. close RF */
+ /* c. clear rx buf */
+ /* d. stop rx DMA */
+ /* e. reset MAC */
+
+ /* a. stop tx DMA */
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE);
+ udelay(50);
+
+ /* b. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */
+
+ /* c. ========RF OFF sequence========== */
+ /* 0x88c[23:20] = 0xf. */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+
+ /* APSD_CTRL 0x600[7:0] = 0x40 */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+
+ /* Close antenna 0,0xc04,0xd04 */
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0);
+
+ /* SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB state machine */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+
+ /* Mac0 can not do Global reset. Mac1 can do. */
+ /* SYS_FUNC_EN 0x02[7:0] = 0xE0 reset BB state machine */
+ if (rtlpriv->rtlhal.interfaceindex == 1)
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
+ udelay(50);
+
+ /* d. stop tx/rx dma before disable REG_CR (0x100) to fix */
+ /* dma hang issue when disable/enable device. */
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff);
+ udelay(50);
+ rtl_write_byte(rtlpriv, REG_CR, 0x0);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==> Do power off.......\n"));
+ if (rtl92d_phy_check_poweroff(hw))
+ _rtl92de_poweroff_adapter(hw);
+ return;
+}
+
+void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
+ u32 *p_inta, u32 *p_intb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0];
+ rtl_write_dword(rtlpriv, ISR, *p_inta);
+
+ /*
+ * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1];
+ * rtl_write_dword(rtlpriv, ISR + 4, *p_intb);
+ */
+}
+
+void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 bcn_interval, atim_window;
+
+ bcn_interval = mac->beacon_interval;
+ atim_window = 2;
+ /*rtl92de_disable_interrupt(hw); */
+ rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
+ rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+ rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x20);
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G)
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x30);
+ else
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x20);
+ rtl_write_byte(rtlpriv, 0x606, 0x30);
+}
+
+void rtl92de_set_beacon_interval(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 bcn_interval = mac->beacon_interval;
+
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ ("beacon_interval:%d\n", bcn_interval));
+ /* rtl92de_disable_interrupt(hw); */
+ rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+ /* rtl92de_enable_interrupt(hw); */
+}
+
+void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
+ u32 add_msr, u32 rm_msr)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr));
+ if (add_msr)
+ rtlpci->irq_mask[0] |= add_msr;
+ if (rm_msr)
+ rtlpci->irq_mask[0] &= (~rm_msr);
+ rtl92de_disable_interrupt(hw);
+ rtl92de_enable_interrupt(hw);
+}
+
+static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo,
+ u8 *rom_content, bool autoLoadfail)
+{
+ u32 rfpath, eeaddr, group, offset1, offset2;
+ u8 i;
+
+ memset(pwrinfo, 0, sizeof(struct txpower_info));
+ if (autoLoadfail) {
+ for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ if (group < CHANNEL_GROUP_MAX_2G) {
+ pwrinfo->cck_index[rfpath][group] =
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G;
+ pwrinfo->ht40_1sindex[rfpath][group] =
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G;
+ } else {
+ pwrinfo->ht40_1sindex[rfpath][group] =
+ EEPROM_DEFAULT_TXPOWERLEVEL_5G;
+ }
+ pwrinfo->ht40_2sindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT40_2SDIFF;
+ pwrinfo->ht20indexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT20_DIFF;
+ pwrinfo->ofdmindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+ pwrinfo->ht40maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT40_PWRMAXOFFSET;
+ pwrinfo->ht20maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT20_PWRMAXOFFSET;
+ }
+ }
+ for (i = 0; i < 3; i++) {
+ pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI;
+ pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI;
+ }
+ return;
+ }
+
+ /* Maybe autoload OK,buf the tx power index value is not filled.
+ * If we find it, we set it to default value. */
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ for (group = 0; group < CHANNEL_GROUP_MAX_2G; group++) {
+ eeaddr = EEPROM_CCK_TX_PWR_INX_2G + (rfpath * 3)
+ + group;
+ pwrinfo->cck_index[rfpath][group] =
+ (rom_content[eeaddr] == 0xFF) ?
+ (eeaddr > 0x7B ?
+ EEPROM_DEFAULT_TXPOWERLEVEL_5G :
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G) :
+ rom_content[eeaddr];
+ }
+ }
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+ offset1 = group / 3;
+ offset2 = group % 3;
+ eeaddr = EEPROM_HT40_1S_TX_PWR_INX_2G + (rfpath * 3) +
+ offset2 + offset1 * 21;
+ pwrinfo->ht40_1sindex[rfpath][group] =
+ (rom_content[eeaddr] == 0xFF) ? (eeaddr > 0x7B ?
+ EEPROM_DEFAULT_TXPOWERLEVEL_5G :
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G) :
+ rom_content[eeaddr];
+ }
+ }
+ /* These just for 92D efuse offset. */
+ for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ int base1 = EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G;
+
+ offset1 = group / 3;
+ offset2 = group % 3;
+
+ if (rom_content[base1 + offset2 + offset1 * 21] != 0xFF)
+ pwrinfo->ht40_2sindexdiff[rfpath][group] =
+ (rom_content[base1 +
+ offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ht40_2sindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT40_2SDIFF;
+ if (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ht20indexdiff[rfpath][group] =
+ (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G
+ + offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ht20indexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT20_DIFF;
+ if (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ofdmindexdiff[rfpath][group] =
+ (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G
+ + offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ofdmindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+ if (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ht40maxoffset[rfpath][group] =
+ (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G
+ + offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ht40maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT40_PWRMAXOFFSET;
+ if (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ht20maxoffset[rfpath][group] =
+ (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G +
+ offset2 + offset1 * 21] >> (rfpath * 4)) &
+ 0xF;
+ else
+ pwrinfo->ht20maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT20_PWRMAXOFFSET;
+ }
+ }
+ if (rom_content[EEPROM_TSSI_A_5G] != 0xFF) {
+ /* 5GL */
+ pwrinfo->tssi_a[0] = rom_content[EEPROM_TSSI_A_5G] & 0x3F;
+ pwrinfo->tssi_b[0] = rom_content[EEPROM_TSSI_B_5G] & 0x3F;
+ /* 5GM */
+ pwrinfo->tssi_a[1] = rom_content[EEPROM_TSSI_AB_5G] & 0x3F;
+ pwrinfo->tssi_b[1] =
+ (rom_content[EEPROM_TSSI_AB_5G] & 0xC0) >> 6 |
+ (rom_content[EEPROM_TSSI_AB_5G + 1] & 0x0F) << 2;
+ /* 5GH */
+ pwrinfo->tssi_a[2] = (rom_content[EEPROM_TSSI_AB_5G + 1] &
+ 0xF0) >> 4 |
+ (rom_content[EEPROM_TSSI_AB_5G + 2] & 0x03) << 4;
+ pwrinfo->tssi_b[2] = (rom_content[EEPROM_TSSI_AB_5G + 2] &
+ 0xFC) >> 2;
+ } else {
+ for (i = 0; i < 3; i++) {
+ pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI;
+ pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI;
+ }
+ }
+}
+
+static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw,
+ bool autoload_fail, u8 *hwinfo)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct txpower_info pwrinfo;
+ u8 tempval[2], i, pwr, diff;
+ u32 ch, rfPath, group;
+
+ _rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail);
+ if (!autoload_fail) {
+ /* bit0~2 */
+ rtlefuse->eeprom_regulatory = (hwinfo[EEPROM_RF_OPT1] & 0x7);
+ rtlefuse->eeprom_thermalmeter =
+ hwinfo[EEPROM_THERMAL_METER] & 0x1f;
+ rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_K];
+ 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)) {
+ rtlefuse->internal_pa_5g[0] =
+ !((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,
+ ("Is D cut,Internal PA0 %d Internal PA1 %d\n",
+ rtlefuse->internal_pa_5g[0],
+ rtlefuse->internal_pa_5g[1]))
+ }
+ rtlefuse->eeprom_c9 = hwinfo[EEPROM_RF_OPT6];
+ rtlefuse->eeprom_cc = hwinfo[EEPROM_RF_OPT7];
+ } else {
+ rtlefuse->eeprom_regulatory = 0;
+ rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
+ rtlefuse->crystalcap = EEPROM_DEFAULT_CRYSTALCAP;
+ tempval[0] = tempval[1] = 3;
+ }
+
+ /* Use default value to fill parameters if
+ * efuse is not filled on some place. */
+
+ /* ThermalMeter from EEPROM */
+ if (rtlefuse->eeprom_thermalmeter < 0x06 ||
+ rtlefuse->eeprom_thermalmeter > 0x1c)
+ rtlefuse->eeprom_thermalmeter = 0x12;
+ rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+
+ /* check XTAL_K */
+ if (rtlefuse->crystalcap == 0xFF)
+ rtlefuse->crystalcap = 0;
+ if (rtlefuse->eeprom_regulatory > 3)
+ rtlefuse->eeprom_regulatory = 0;
+
+ for (i = 0; i < 2; i++) {
+ switch (tempval[i]) {
+ case 0:
+ tempval[i] = 5;
+ break;
+ case 1:
+ tempval[i] = 4;
+ break;
+ case 2:
+ tempval[i] = 3;
+ break;
+ case 3:
+ default:
+ tempval[i] = 0;
+ break;
+ }
+ }
+
+ rtlefuse->delta_iqk = tempval[0];
+ if (tempval[1] > 0)
+ rtlefuse->delta_lck = tempval[1] - 1;
+ if (rtlefuse->eeprom_c9 == 0xFF)
+ rtlefuse->eeprom_c9 = 0x00;
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("EEPROMRegulatory = 0x%x\n", rtlefuse->eeprom_regulatory));
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("ThermalMeter = 0x%x\n", rtlefuse->eeprom_thermalmeter));
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("CrystalCap = 0x%x\n", rtlefuse->crystalcap));
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("Delta_IQK = 0x%x Delta_LCK = 0x%x\n", rtlefuse->delta_iqk,
+ rtlefuse->delta_lck));
+
+ for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) {
+ for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
+ group = rtl92d_get_chnlgroup_fromarray((u8) ch);
+ if (ch < CHANNEL_MAX_NUMBER_2G)
+ rtlefuse->txpwrlevel_cck[rfPath][ch] =
+ pwrinfo.cck_index[rfPath][group];
+ rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] =
+ pwrinfo.ht40_1sindex[rfPath][group];
+ rtlefuse->txpwr_ht20diff[rfPath][ch] =
+ pwrinfo.ht20indexdiff[rfPath][group];
+ rtlefuse->txpwr_legacyhtdiff[rfPath][ch] =
+ pwrinfo.ofdmindexdiff[rfPath][group];
+ rtlefuse->pwrgroup_ht20[rfPath][ch] =
+ pwrinfo.ht20maxoffset[rfPath][group];
+ rtlefuse->pwrgroup_ht40[rfPath][ch] =
+ pwrinfo.ht40maxoffset[rfPath][group];
+ pwr = pwrinfo.ht40_1sindex[rfPath][group];
+ diff = pwrinfo.ht40_2sindexdiff[rfPath][group];
+ rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] =
+ (pwr > diff) ? (pwr - diff) : 0;
+ }
+ }
+}
+
+static void _rtl92de_read_macphymode_from_prom(struct ieee80211_hw *hw,
+ u8 *content)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 macphy_crvalue = content[EEPROM_MAC_FUNCTION];
+
+ if (macphy_crvalue & BIT(3)) {
+ rtlhal->macphymode = SINGLEMAC_SINGLEPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode SINGLEMAC_SINGLEPHY\n"));
+ } else {
+ rtlhal->macphymode = DUALMAC_DUALPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode DUALMAC_DUALPHY\n"));
+ }
+}
+
+static void _rtl92de_read_macphymode_and_bandtype(struct ieee80211_hw *hw,
+ u8 *content)
+{
+ _rtl92de_read_macphymode_from_prom(hw, content);
+ rtl92d_phy_config_macphymode(hw);
+ rtl92d_phy_config_macphymode_info(hw);
+}
+
+static void _rtl92de_efuse_update_chip_version(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ enum version_8192d chipver = rtlpriv->rtlhal.version;
+ u8 cutvalue[2];
+ u16 chipvalue;
+
+ rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_H,
+ &cutvalue[1]);
+ rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_L,
+ &cutvalue[0]);
+ chipvalue = (cutvalue[1] << 8) | cutvalue[0];
+ switch (chipvalue) {
+ case 0xAA55:
+ chipver |= CHIP_92D_C_CUT;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("C-CUT!!!\n"));
+ break;
+ case 0x9966:
+ chipver |= CHIP_92D_D_CUT;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("D-CUT!!!\n"));
+ break;
+ default:
+ chipver |= CHIP_92D_D_CUT;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("Unkown CUT!\n"));
+ break;
+ }
+ rtlpriv->rtlhal.version = chipver;
+}
+
+static void _rtl92de_read_adapter_info(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u16 i, usvalue;
+ u8 hwinfo[HWSET_MAX_SIZE];
+ u16 eeprom_id;
+ unsigned long flags;
+
+ if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+ spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags);
+ rtl_efuse_shadow_map_update(hw);
+ _rtl92de_efuse_update_chip_version(hw);
+ spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+ memcpy((void *)hwinfo, (void *)&rtlefuse->efuse_map
+ [EFUSE_INIT_MAP][0],
+ HWSET_MAX_SIZE);
+ } else if (rtlefuse->epromtype == EEPROM_93C46) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("RTL819X Not boot from eeprom, check it !!"));
+ }
+ RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"),
+ hwinfo, HWSET_MAX_SIZE);
+
+ eeprom_id = *((u16 *)&hwinfo[0]);
+ if (eeprom_id != RTL8190_EEPROM_ID) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("EEPROM ID(%#x) is invalid!!\n", eeprom_id));
+ rtlefuse->autoload_failflag = true;
+ } else {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
+ rtlefuse->autoload_failflag = false;
+ }
+ if (rtlefuse->autoload_failflag) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("RTL819X Not boot from eeprom, check it !!"));
+ return;
+ }
+ rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+ _rtl92de_read_macphymode_and_bandtype(hw, hwinfo);
+
+ /* VID, DID SE 0xA-D */
+ rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
+ rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
+ rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID];
+ rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID];
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROMId = 0x%4x\n", eeprom_id));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid));
+
+ /* Read Permanent MAC address */
+ if (rtlhal->interfaceindex == 0) {
+ for (i = 0; i < 6; i += 2) {
+ usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC0_92D + i];
+ *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+ }
+ } else {
+ for (i = 0; i < 6; i += 2) {
+ usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC1_92D + i];
+ *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+ }
+ }
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR,
+ rtlefuse->dev_addr);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ ("%pM\n", rtlefuse->dev_addr));
+ _rtl92de_read_txpower_info(hw, rtlefuse->autoload_failflag, hwinfo);
+
+ /* Read Channel Plan */
+ switch (rtlhal->bandset) {
+ case BAND_ON_2_4G:
+ rtlefuse->channel_plan = COUNTRY_CODE_TELEC;
+ break;
+ case BAND_ON_5G:
+ rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+ break;
+ case BAND_ON_BOTH:
+ rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+ break;
+ default:
+ rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+ break;
+ }
+ rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+ rtlefuse->txpwr_fromeprom = true;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid));
+}
+
+void rtl92de_read_eeprom_info(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 tmp_u1b;
+
+ rtlhal->version = _rtl92de_read_chip_version(hw);
+ tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+ rtlefuse->autoload_status = tmp_u1b;
+ if (tmp_u1b & BIT(4)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n"));
+ rtlefuse->epromtype = EEPROM_93C46;
+ } else {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n"));
+ rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
+ }
+ if (tmp_u1b & BIT(5)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
+
+ rtlefuse->autoload_failflag = false;
+ _rtl92de_read_adapter_info(hw);
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n"));
+ }
+ return;
+}
+
+static void rtl92de_update_hal_rate_table(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 ratr_value;
+ u8 ratr_index = 0;
+ u8 nmode = mac->ht_enable;
+ u8 mimo_ps = IEEE80211_SMPS_OFF;
+ u16 shortgi_rate;
+ u32 tmp_ratr_value;
+ u8 curtxbw_40mhz = mac->bw_40;
+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+ 1 : 0;
+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+ 1 : 0;
+ enum wireless_mode wirelessmode = mac->mode;
+
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ ratr_value = sta->supp_rates[1] << 4;
+ else
+ ratr_value = sta->supp_rates[0];
+ ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+ sta->ht_cap.mcs.rx_mask[0] << 12);
+ switch (wirelessmode) {
+ case WIRELESS_MODE_A:
+ ratr_value &= 0x00000FF0;
+ break;
+ case WIRELESS_MODE_B:
+ if (ratr_value & 0x0000000c)
+ ratr_value &= 0x0000000d;
+ else
+ ratr_value &= 0x0000000f;
+ break;
+ case WIRELESS_MODE_G:
+ ratr_value &= 0x00000FF5;
+ break;
+ case WIRELESS_MODE_N_24G:
+ case WIRELESS_MODE_N_5G:
+ nmode = 1;
+ if (mimo_ps == IEEE80211_SMPS_STATIC) {
+ ratr_value &= 0x0007F005;
+ } else {
+ u32 ratr_mask;
+
+ if (get_rf_type(rtlphy) == RF_1T2R ||
+ get_rf_type(rtlphy) == RF_1T1R) {
+ ratr_mask = 0x000ff005;
+ } else {
+ ratr_mask = 0x0f0ff005;
+ }
+
+ ratr_value &= ratr_mask;
+ }
+ break;
+ default:
+ if (rtlphy->rf_type == RF_1T2R)
+ ratr_value &= 0x000ff0ff;
+ else
+ ratr_value &= 0x0f0ff0ff;
+
+ break;
+ }
+ ratr_value &= 0x0FFFFFFF;
+ if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
+ (!curtxbw_40mhz && curshortgi_20mhz))) {
+ ratr_value |= 0x10000000;
+ tmp_ratr_value = (ratr_value >> 12);
+ for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
+ if ((1 << shortgi_rate) & tmp_ratr_value)
+ break;
+ }
+ shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
+ (shortgi_rate << 4) | (shortgi_rate);
+ }
+ rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+ ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)));
+}
+
+static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_sta_info *sta_entry = NULL;
+ u32 ratr_bitmap;
+ u8 ratr_index;
+ u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ ? 1 : 0;
+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+ 1 : 0;
+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+ 1 : 0;
+ enum wireless_mode wirelessmode = 0;
+ bool shortgi = false;
+ u32 value[2];
+ u8 macid = 0;
+ u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+ sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+ mimo_ps = sta_entry->mimo_ps;
+ wirelessmode = sta_entry->wireless_mode;
+ if (mac->opmode == NL80211_IFTYPE_STATION)
+ curtxbw_40mhz = mac->bw_40;
+ else if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC)
+ macid = sta->aid + 1;
+
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ ratr_bitmap = sta->supp_rates[1] << 4;
+ else
+ ratr_bitmap = sta->supp_rates[0];
+ ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+ sta->ht_cap.mcs.rx_mask[0] << 12);
+ switch (wirelessmode) {
+ case WIRELESS_MODE_B:
+ ratr_index = RATR_INX_WIRELESS_B;
+ if (ratr_bitmap & 0x0000000c)
+ ratr_bitmap &= 0x0000000d;
+ else
+ ratr_bitmap &= 0x0000000f;
+ break;
+ case WIRELESS_MODE_G:
+ ratr_index = RATR_INX_WIRELESS_GB;
+
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x00000f00;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x00000ff0;
+ else
+ ratr_bitmap &= 0x00000ff5;
+ break;
+ case WIRELESS_MODE_A:
+ ratr_index = RATR_INX_WIRELESS_G;
+ ratr_bitmap &= 0x00000ff0;
+ break;
+ case WIRELESS_MODE_N_24G:
+ case WIRELESS_MODE_N_5G:
+ if (wirelessmode == WIRELESS_MODE_N_24G)
+ ratr_index = RATR_INX_WIRELESS_NGB;
+ else
+ ratr_index = RATR_INX_WIRELESS_NG;
+ if (mimo_ps == IEEE80211_SMPS_STATIC) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x00070000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0007f000;
+ else
+ ratr_bitmap &= 0x0007f005;
+ } else {
+ if (rtlphy->rf_type == RF_1T2R ||
+ rtlphy->rf_type == RF_1T1R) {
+ if (curtxbw_40mhz) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x000f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x000ff000;
+ else
+ ratr_bitmap &= 0x000ff015;
+ } else {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x000f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x000ff000;
+ else
+ ratr_bitmap &= 0x000ff005;
+ }
+ } else {
+ if (curtxbw_40mhz) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x0f0f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0f0ff000;
+ else
+ ratr_bitmap &= 0x0f0ff015;
+ } else {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x0f0f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0f0ff000;
+ else
+ ratr_bitmap &= 0x0f0ff005;
+ }
+ }
+ }
+ if ((curtxbw_40mhz && curshortgi_40mhz) ||
+ (!curtxbw_40mhz && curshortgi_20mhz)) {
+
+ if (macid == 0)
+ shortgi = true;
+ else if (macid == 1)
+ shortgi = false;
+ }
+ break;
+ default:
+ ratr_index = RATR_INX_WIRELESS_NGB;
+
+ if (rtlphy->rf_type == RF_1T2R)
+ ratr_bitmap &= 0x000ff0ff;
+ else
+ ratr_bitmap &= 0x0f0ff0ff;
+ break;
+ }
+
+ value[0] = (ratr_bitmap & 0x0fffffff) | (ratr_index << 28);
+ value[1] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+ ("ratr_bitmap :%x value0:%x value1:%x\n",
+ ratr_bitmap, value[0], value[1]));
+ rtl92d_fill_h2c_cmd(hw, H2C_RA_MASK, 5, (u8 *) value);
+ if (macid != 0)
+ sta_entry->ratr_index = ratr_index;
+}
+
+void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->dm.useramask)
+ rtl92de_update_hal_rate_mask(hw, sta, rssi_level);
+ else
+ rtl92de_update_hal_rate_table(hw, sta);
+}
+
+void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 sifs_timer;
+
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
+ (u8 *)&mac->slot_time);
+ if (!mac->ht_enable)
+ sifs_timer = 0x0a0a;
+ else
+ sifs_timer = 0x1010;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ enum rf_pwrstate e_rfpowerstate_toset;
+ u8 u1tmp;
+ bool actuallyset = false;
+ unsigned long flag;
+
+ if (rtlpci->being_init_adapter)
+ return false;
+ if (ppsc->swrf_processing)
+ return false;
+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+ if (ppsc->rfchange_inprogress) {
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ return false;
+ } else {
+ ppsc->rfchange_inprogress = true;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ }
+ rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,
+ REG_MAC_PINMUX_CFG) & ~(BIT(3)));
+ u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
+ e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
+ if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("GPIOChangeRF - HW Radio ON, RF ON\n"));
+ e_rfpowerstate_toset = ERFON;
+ ppsc->hwradiooff = false;
+ actuallyset = true;
+ } else if ((ppsc->hwradiooff == false)
+ && (e_rfpowerstate_toset == ERFOFF)) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("GPIOChangeRF - HW Radio OFF, RF OFF\n"));
+ e_rfpowerstate_toset = ERFOFF;
+ ppsc->hwradiooff = true;
+ actuallyset = true;
+ }
+ if (actuallyset) {
+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+ ppsc->rfchange_inprogress = false;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ } else {
+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC)
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+ ppsc->rfchange_inprogress = false;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ }
+ *valid = 1;
+ return !ppsc->hwradiooff;
+}
+
+void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index,
+ u8 *p_macaddr, bool is_group, u8 enc_algo,
+ bool is_wepkey, bool clear_all)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 *macaddr = p_macaddr;
+ u32 entry_id;
+ bool is_pairwise = false;
+ static u8 cam_const_addr[4][6] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+ };
+ static u8 cam_const_broad[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+ if (clear_all) {
+ u8 idx;
+ u8 cam_offset = 0;
+ u8 clear_number = 5;
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n"));
+ for (idx = 0; idx < clear_number; idx++) {
+ rtl_cam_mark_invalid(hw, cam_offset + idx);
+ rtl_cam_empty_entry(hw, cam_offset + idx);
+
+ if (idx < 5) {
+ memset(rtlpriv->sec.key_buf[idx], 0,
+ MAX_KEY_LEN);
+ rtlpriv->sec.key_len[idx] = 0;
+ }
+ }
+ } else {
+ switch (enc_algo) {
+ case WEP40_ENCRYPTION:
+ enc_algo = CAM_WEP40;
+ break;
+ case WEP104_ENCRYPTION:
+ enc_algo = CAM_WEP104;
+ break;
+ case TKIP_ENCRYPTION:
+ enc_algo = CAM_TKIP;
+ break;
+ case AESCCMP_ENCRYPTION:
+ enc_algo = CAM_AES;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case "
+ "not process\n"));
+ enc_algo = CAM_TKIP;
+ break;
+ }
+ if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+ macaddr = cam_const_addr[key_index];
+ entry_id = key_index;
+ } else {
+ if (is_group) {
+ macaddr = cam_const_broad;
+ entry_id = key_index;
+ } else {
+ if (mac->opmode == NL80211_IFTYPE_AP) {
+ entry_id = rtl_cam_get_free_entry(hw,
+ p_macaddr);
+ if (entry_id >= TOTAL_CAM_ENTRY) {
+ RT_TRACE(rtlpriv, COMP_SEC,
+ DBG_EMERG, ("Can not "
+ "find free hw security"
+ " cam entry\n"));
+ return;
+ }
+ } else {
+ entry_id = CAM_PAIRWISE_KEY_POSITION;
+ }
+ key_index = PAIRWISE_KEYIDX;
+ is_pairwise = true;
+ }
+ }
+ if (rtlpriv->sec.key_len[key_index] == 0) {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("delete one entry, entry_id is %d\n",
+ entry_id));
+ if (mac->opmode == NL80211_IFTYPE_AP)
+ rtl_cam_del_entry(hw, p_macaddr);
+ rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+ ("The insert KEY length is %d\n",
+ rtlpriv->sec.key_len[PAIRWISE_KEYIDX]));
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+ ("The insert KEY is %x %x\n",
+ rtlpriv->sec.key_buf[0][0],
+ rtlpriv->sec.key_buf[0][1]));
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("add one entry\n"));
+ if (is_pairwise) {
+ RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
+ "Pairwiase Key content :",
+ rtlpriv->sec.pairwise_key,
+ rtlpriv->
+ sec.key_len[PAIRWISE_KEYIDX]);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("set Pairwiase key\n"));
+ rtl_cam_add_one_entry(hw, macaddr, key_index,
+ entry_id, enc_algo,
+ CAM_CONFIG_NO_USEDK,
+ rtlpriv->
+ sec.key_buf[key_index]);
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("set group key\n"));
+ if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+ rtl_cam_add_one_entry(hw,
+ rtlefuse->dev_addr,
+ PAIRWISE_KEYIDX,
+ CAM_PAIRWISE_KEY_POSITION,
+ enc_algo, CAM_CONFIG_NO_USEDK,
+ rtlpriv->sec.key_buf[entry_id]);
+ }
+ rtl_cam_add_one_entry(hw, macaddr, key_index,
+ entry_id, enc_algo,
+ CAM_CONFIG_NO_USEDK,
+ rtlpriv->sec.key_buf
+ [entry_id]);
+ }
+ }
+ }
+}
+
+void rtl92de_suspend(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->rtlhal.macphyctl_reg = rtl_read_byte(rtlpriv,
+ REG_MAC_PHY_CTRL_NORMAL);
+}
+
+void rtl92de_resume(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL,
+ rtlpriv->rtlhal.macphyctl_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
new file mode 100644
index 000000000000..ad44ffa520e6
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_HW_H__
+#define __RTL92DE_HW_H__
+
+void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92de_read_eeprom_info(struct ieee80211_hw *hw);
+void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
+ u32 *p_inta, u32 *p_intb);
+int rtl92de_hw_init(struct ieee80211_hw *hw);
+void rtl92de_card_disable(struct ieee80211_hw *hw);
+void rtl92de_enable_interrupt(struct ieee80211_hw *hw);
+void rtl92de_disable_interrupt(struct ieee80211_hw *hw);
+int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+void rtl92de_set_qos(struct ieee80211_hw *hw, int aci);
+void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl92de_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
+ u32 add_msr, u32 rm_msr);
+void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level);
+void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
+void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw);
+void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index,
+ u8 *p_macaddr, bool is_group, u8 enc_algo,
+ bool is_wepkey, bool clear_all);
+
+extern void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset,
+ u32 value, u8 direct);
+extern u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset,
+ u8 direct);
+void rtl92de_suspend(struct ieee80211_hw *hw);
+void rtl92de_resume(struct ieee80211_hw *hw);
+void rtl92d_linked_set_reg(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/rtlwifi/rtl8192de/led.c
new file mode 100644
index 000000000000..f1552f4df658
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.c
@@ -0,0 +1,159 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl92ce_init_led(struct ieee80211_hw *hw,
+ struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+ pled->hw = hw;
+ pled->ledpin = ledpin;
+ pled->ledon = false;
+}
+
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+ u8 ledcfg;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+ ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+
+ switch (pled->ledpin) {
+ case LED_PIN_GPIO0:
+ break;
+ case LED_PIN_LED0:
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+ if ((rtlpriv->efuse.eeprom_did == 0x8176) ||
+ (rtlpriv->efuse.eeprom_did == 0x8193))
+ /* BIT7 of REG_LEDCFG2 should be set to
+ * make sure we could emit the led2. */
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) |
+ BIT(7) | BIT(5) | BIT(6));
+ else
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) |
+ BIT(7) | BIT(5));
+ break;
+ case LED_PIN_LED1:
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
+
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ pled->ledon = true;
+}
+
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ u8 ledcfg;
+
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+ ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+ switch (pled->ledpin) {
+ case LED_PIN_GPIO0:
+ break;
+ case LED_PIN_LED0:
+ ledcfg &= 0xf0;
+ if (pcipriv->ledctl.led_opendrain)
+ rtl_write_byte(rtlpriv, REG_LEDCFG2,
+ (ledcfg | BIT(1) | BIT(5) | BIT(6)));
+ else
+ rtl_write_byte(rtlpriv, REG_LEDCFG2,
+ (ledcfg | BIT(3) | BIT(5) | BIT(6)));
+ break;
+ case LED_PIN_LED1:
+ ledcfg &= 0x0f;
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ pled->ledon = false;
+}
+
+void rtl92de_init_sw_leds(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
+ _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
+ enum led_ctl_mode ledaction)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+ switch (ledaction) {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_LINK:
+ case LED_CTL_NO_LINK:
+ rtl92de_sw_led_on(hw, pLed0);
+ break;
+ case LED_CTL_POWER_OFF:
+ rtl92de_sw_led_off(hw, pLed0);
+ break;
+ default:
+ break;
+ }
+}
+
+void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+ (ledaction == LED_CTL_TX ||
+ ledaction == LED_CTL_RX ||
+ ledaction == LED_CTL_SITE_SURVEY ||
+ ledaction == LED_CTL_LINK ||
+ ledaction == LED_CTL_NO_LINK ||
+ ledaction == LED_CTL_START_TO_LINK ||
+ ledaction == LED_CTL_POWER_ON)) {
+ return;
+ }
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", ledaction));
+
+ _rtl92ce_sw_led_control(hw, ledaction);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/rtlwifi/rtl8192de/led.h
new file mode 100644
index 000000000000..57f4a3c583d4
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CE_LED_H__
+#define __RTL92CE_LED_H__
+
+void rtl92de_init_sw_leds(struct ieee80211_hw *hw);
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
new file mode 100644
index 000000000000..3ac7af1c5509
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -0,0 +1,3831 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "table.h"
+#include "sw.h"
+#include "hw.h"
+
+#define MAX_RF_IMR_INDEX 12
+#define MAX_RF_IMR_INDEX_NORMAL 13
+#define RF_REG_NUM_FOR_C_CUT_5G 6
+#define RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA 7
+#define RF_REG_NUM_FOR_C_CUT_2G 5
+#define RF_CHNL_NUM_5G 19
+#define RF_CHNL_NUM_5G_40M 17
+#define TARGET_CHNL_NUM_5G 221
+#define TARGET_CHNL_NUM_2G 14
+#define CV_CURVE_CNT 64
+
+static u32 rf_reg_for_5g_swchnl_normal[MAX_RF_IMR_INDEX_NORMAL] = {
+ 0, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0
+};
+
+static u8 rf_reg_for_c_cut_5g[RF_REG_NUM_FOR_C_CUT_5G] = {
+ RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G4, RF_SYN_G5, RF_SYN_G6
+};
+
+static u8 rf_reg_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = {
+ RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G7, RF_SYN_G8
+};
+
+static u8 rf_for_c_cut_5g_internal_pa[RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = {
+ 0x0B, 0x48, 0x49, 0x4B, 0x03, 0x04, 0x0E
+};
+
+static u32 rf_reg_mask_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = {
+ BIT(19) | BIT(18) | BIT(17) | BIT(14) | BIT(1),
+ BIT(10) | BIT(9),
+ BIT(18) | BIT(17) | BIT(16) | BIT(1),
+ BIT(2) | BIT(1),
+ BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11)
+};
+
+static u8 rf_chnl_5g[RF_CHNL_NUM_5G] = {
+ 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108,
+ 112, 116, 120, 124, 128, 132, 136, 140
+};
+
+static u8 rf_chnl_5g_40m[RF_CHNL_NUM_5G_40M] = {
+ 38, 42, 46, 50, 54, 58, 62, 102, 106, 110, 114,
+ 118, 122, 126, 130, 134, 138
+};
+static u32 rf_reg_pram_c_5g[5][RF_REG_NUM_FOR_C_CUT_5G] = {
+ {0xE43BE, 0xFC638, 0x77C0A, 0xDE471, 0xd7110, 0x8EB04},
+ {0xE43BE, 0xFC078, 0xF7C1A, 0xE0C71, 0xD7550, 0xAEB04},
+ {0xE43BF, 0xFF038, 0xF7C0A, 0xDE471, 0xE5550, 0xAEB04},
+ {0xE43BF, 0xFF079, 0xF7C1A, 0xDE471, 0xE5550, 0xAEB04},
+ {0xE43BF, 0xFF038, 0xF7C1A, 0xDE471, 0xd7550, 0xAEB04}
+};
+
+static u32 rf_reg_param_for_c_cut_2g[3][RF_REG_NUM_FOR_C_CUT_2G] = {
+ {0x643BC, 0xFC038, 0x77C1A, 0x41289, 0x01840},
+ {0x643BC, 0xFC038, 0x07C1A, 0x41289, 0x01840},
+ {0x243BC, 0xFC438, 0x07C1A, 0x4128B, 0x0FC41}
+};
+
+static u32 rf_syn_g4_for_c_cut_2g = 0xD1C31 & 0x7FF;
+
+static u32 rf_pram_c_5g_int_pa[3][RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = {
+ {0x01a00, 0x40443, 0x00eb5, 0x89bec, 0x94a12, 0x94a12, 0x94a12},
+ {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a52, 0x94a52, 0x94a52},
+ {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a12, 0x94a12, 0x94a12}
+};
+
+/* [mode][patha+b][reg] */
+static u32 rf_imr_param_normal[1][3][MAX_RF_IMR_INDEX_NORMAL] = {
+ {
+ /* channel 1-14. */
+ {
+ 0x70000, 0x00ff0, 0x4400f, 0x00ff0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x64888, 0xe266c, 0x00090, 0x22fff
+ },
+ /* path 36-64 */
+ {
+ 0x70000, 0x22880, 0x4470f, 0x55880, 0x00070, 0x88000,
+ 0x0, 0x88080, 0x70000, 0x64a82, 0xe466c, 0x00090,
+ 0x32c9a
+ },
+ /* 100 -165 */
+ {
+ 0x70000, 0x44880, 0x4477f, 0x77880, 0x00070, 0x88000,
+ 0x0, 0x880b0, 0x0, 0x64b82, 0xe466c, 0x00090, 0x32c9a
+ }
+ }
+};
+
+static u32 curveindex_5g[TARGET_CHNL_NUM_5G] = {0};
+
+static u32 curveindex_2g[TARGET_CHNL_NUM_2G] = {0};
+
+static u32 targetchnl_5g[TARGET_CHNL_NUM_5G] = {
+ 25141, 25116, 25091, 25066, 25041,
+ 25016, 24991, 24966, 24941, 24917,
+ 24892, 24867, 24843, 24818, 24794,
+ 24770, 24765, 24721, 24697, 24672,
+ 24648, 24624, 24600, 24576, 24552,
+ 24528, 24504, 24480, 24457, 24433,
+ 24409, 24385, 24362, 24338, 24315,
+ 24291, 24268, 24245, 24221, 24198,
+ 24175, 24151, 24128, 24105, 24082,
+ 24059, 24036, 24013, 23990, 23967,
+ 23945, 23922, 23899, 23876, 23854,
+ 23831, 23809, 23786, 23764, 23741,
+ 23719, 23697, 23674, 23652, 23630,
+ 23608, 23586, 23564, 23541, 23519,
+ 23498, 23476, 23454, 23432, 23410,
+ 23388, 23367, 23345, 23323, 23302,
+ 23280, 23259, 23237, 23216, 23194,
+ 23173, 23152, 23130, 23109, 23088,
+ 23067, 23046, 23025, 23003, 22982,
+ 22962, 22941, 22920, 22899, 22878,
+ 22857, 22837, 22816, 22795, 22775,
+ 22754, 22733, 22713, 22692, 22672,
+ 22652, 22631, 22611, 22591, 22570,
+ 22550, 22530, 22510, 22490, 22469,
+ 22449, 22429, 22409, 22390, 22370,
+ 22350, 22336, 22310, 22290, 22271,
+ 22251, 22231, 22212, 22192, 22173,
+ 22153, 22134, 22114, 22095, 22075,
+ 22056, 22037, 22017, 21998, 21979,
+ 21960, 21941, 21921, 21902, 21883,
+ 21864, 21845, 21826, 21807, 21789,
+ 21770, 21751, 21732, 21713, 21695,
+ 21676, 21657, 21639, 21620, 21602,
+ 21583, 21565, 21546, 21528, 21509,
+ 21491, 21473, 21454, 21436, 21418,
+ 21400, 21381, 21363, 21345, 21327,
+ 21309, 21291, 21273, 21255, 21237,
+ 21219, 21201, 21183, 21166, 21148,
+ 21130, 21112, 21095, 21077, 21059,
+ 21042, 21024, 21007, 20989, 20972,
+ 25679, 25653, 25627, 25601, 25575,
+ 25549, 25523, 25497, 25471, 25446,
+ 25420, 25394, 25369, 25343, 25318,
+ 25292, 25267, 25242, 25216, 25191,
+ 25166
+};
+
+/* channel 1~14 */
+static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = {
+ 26084, 26030, 25976, 25923, 25869, 25816, 25764,
+ 25711, 25658, 25606, 25554, 25502, 25451, 25328
+};
+
+static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++) {
+ if (((bitmask >> i) & 0x1) == 1)
+ break;
+ }
+
+ return i;
+}
+
+u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u32 returnvalue, originalvalue, bitshift;
+ u8 dbi_direct;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+ "bitmask(%#x)\n", regaddr, bitmask));
+ if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) {
+ /* mac1 use phy0 read radio_b. */
+ /* mac0 use phy1 read radio_b. */
+ if (rtlhal->during_mac1init_radioa)
+ dbi_direct = BIT(3);
+ else if (rtlhal->during_mac0init_radiob)
+ dbi_direct = BIT(3) | BIT(2);
+ originalvalue = rtl92de_read_dword_dbi(hw, (u16)regaddr,
+ dbi_direct);
+ } else {
+ originalvalue = rtl_read_dword(rtlpriv, regaddr);
+ }
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ returnvalue = (originalvalue & bitmask) >> bitshift;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x "
+ "Addr[0x%x]=0x%x\n", bitmask, regaddr, originalvalue));
+ return returnvalue;
+}
+
+void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u8 dbi_direct = 0;
+ u32 originalvalue, bitshift;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+ " data(%#x)\n", regaddr, bitmask, data));
+ if (rtlhal->during_mac1init_radioa)
+ dbi_direct = BIT(3);
+ else if (rtlhal->during_mac0init_radiob)
+ /* mac0 use phy1 write radio_b. */
+ dbi_direct = BIT(3) | BIT(2);
+ if (bitmask != BMASKDWORD) {
+ if (rtlhal->during_mac1init_radioa ||
+ rtlhal->during_mac0init_radiob)
+ originalvalue = rtl92de_read_dword_dbi(hw,
+ (u16) regaddr,
+ dbi_direct);
+ else
+ originalvalue = rtl_read_dword(rtlpriv, regaddr);
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ data = ((originalvalue & (~bitmask)) | (data << bitshift));
+ }
+ if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob)
+ rtl92de_write_dword_dbi(hw, (u16) regaddr, data, dbi_direct);
+ else
+ rtl_write_dword(rtlpriv, regaddr, data);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+ " data(%#x)\n", regaddr, bitmask, data));
+}
+
+static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset)
+{
+
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+ u32 newoffset;
+ u32 tmplong, tmplong2;
+ u8 rfpi_enable = 0;
+ u32 retvalue;
+
+ newoffset = offset;
+ tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD);
+ if (rfpath == RF90_PATH_A)
+ tmplong2 = tmplong;
+ else
+ tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD);
+ tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
+ (newoffset << 23) | BLSSIREADEDGE;
+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD,
+ tmplong & (~BLSSIREADEDGE));
+ udelay(10);
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD, tmplong2);
+ udelay(50);
+ udelay(50);
+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD,
+ tmplong | BLSSIREADEDGE);
+ udelay(10);
+ if (rfpath == RF90_PATH_A)
+ rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+ BIT(8));
+ else if (rfpath == RF90_PATH_B)
+ rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+ BIT(8));
+ if (rfpi_enable)
+ retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+ BLSSIREADBACKDATA);
+ else
+ retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+ BLSSIREADBACKDATA);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x] = 0x%x\n",
+ rfpath, pphyreg->rflssi_readback, retvalue));
+ return retvalue;
+}
+
+static void _rtl92d_phy_rf_serial_write(struct ieee80211_hw *hw,
+ enum radio_path rfpath,
+ u32 offset, u32 data)
+{
+ u32 data_and_addr;
+ u32 newoffset;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ newoffset = offset;
+ /* T65 RF */
+ data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+ rtl_set_bbreg(hw, pphyreg->rf3wire_offset, BMASKDWORD, data_and_addr);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n",
+ rfpath, pphyreg->rf3wire_offset, data_and_addr));
+}
+
+u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr, u32 bitmask)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 original_value, readback_value, bitshift;
+ unsigned long flags;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+ "rfpath(%#x), bitmask(%#x)\n",
+ regaddr, rfpath, bitmask));
+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr);
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ readback_value = (original_value & bitmask) >> bitshift;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
+ "bitmask(%#x), original_value(%#x)\n",
+ regaddr, rfpath, bitmask, original_value));
+ return readback_value;
+}
+
+void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 original_value, bitshift;
+ unsigned long flags;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ ("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+ regaddr, bitmask, data, rfpath));
+ if (bitmask == 0)
+ return;
+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ if (rtlphy->rf_mode != RF_OP_BY_FW) {
+ if (bitmask != BRFREGOFFSETMASK) {
+ original_value = _rtl92d_phy_rf_serial_read(hw,
+ rfpath, regaddr);
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ data = ((original_value & (~bitmask)) |
+ (data << bitshift));
+ }
+ _rtl92d_phy_rf_serial_write(hw, rfpath, regaddr, data);
+ }
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+ "bitmask(%#x), data(%#x), rfpath(%#x)\n",
+ regaddr, bitmask, data, rfpath));
+}
+
+bool rtl92d_phy_mac_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+ u32 arraylength;
+ u32 *ptrarray;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Read Rtl819XMACPHY_Array\n"));
+ arraylength = MAC_2T_ARRAYLENGTH;
+ ptrarray = rtl8192de_mac_2tarray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Img:Rtl819XMAC_Array\n"));
+ for (i = 0; i < arraylength; i = i + 2)
+ rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) {
+ /* improve 2-stream TX EVM */
+ /* rtl_write_byte(rtlpriv, 0x14,0x71); */
+ /* AMPDU aggregation number 9 */
+ /* rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */
+ rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x0B);
+ } else {
+ /* 92D need to test to decide the num. */
+ rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x07);
+ }
+ return true;
+}
+
+static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ /* RF Interface Sowrtware Control */
+ /* 16 LSBs if read 32-bit from 0x870 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+ /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+ /* 16 LSBs if read 32-bit from 0x874 */
+ rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+ /* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */
+
+ rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+ /* RF Interface Readback Value */
+ /* 16 LSBs if read 32-bit from 0x8E0 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+ /* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+ /* 16 LSBs if read 32-bit from 0x8E4 */
+ rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+ /* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */
+ rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+
+ /* RF Interface Output (and Enable) */
+ /* 16 LSBs if read 32-bit from 0x860 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+ /* 16 LSBs if read 32-bit from 0x864 */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+ /* RF Interface (Output and) Enable */
+ /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+ /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+ /* Addr of LSSI. Wirte RF register by driver */
+ /* LSSI Parameter */
+ rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
+ RFPGA0_XA_LSSIPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
+ RFPGA0_XB_LSSIPARAMETER;
+
+ /* RF parameter */
+ /* BB Band Select */
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER;
+
+ /* Tx AGC Gain Stage (same for all path. Should we remove this?) */
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+
+ /* Tranceiver A~D HSSI Parameter-1 */
+ /* wire control parameter1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+ /* wire control parameter1 */
+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+ /* Tranceiver A~D HSSI Parameter-2 */
+ /* wire control parameter2 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+ /* wire control parameter2 */
+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+ /* RF switch Control */
+ /* TR/Ant switch control */
+ rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
+ RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
+ RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
+ RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
+ RFPGA0_XCD_SWITCHCONTROL;
+
+ /* AGC control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+ /* AGC control 2 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+ /* RX AFE control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
+ ROFDM0_XARXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
+ ROFDM0_XBRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
+ ROFDM0_XCRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
+ ROFDM0_XDRXIQIMBALANCE;
+
+ /*RX AFE control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+ /* Tx AFE control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
+ ROFDM0_XATxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
+ ROFDM0_XBTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
+ ROFDM0_XCTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
+ ROFDM0_XDTxIQIMBALANCE;
+
+ /* Tx AFE control 2 */
+ rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE;
+
+ /* Tranceiver LSSI Readback SI mode */
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
+ RFPGA0_XA_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
+ RFPGA0_XB_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
+ RFPGA0_XC_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
+ RFPGA0_XD_LSSIREADBACK;
+
+ /* Tranceiver LSSI Readback PI mode */
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
+ TRANSCEIVERA_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
+ TRANSCEIVERB_HSPI_READBACK;
+}
+
+static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+ u8 configtype)
+{
+ int i;
+ u32 *phy_regarray_table;
+ u32 *agctab_array_table = NULL;
+ u32 *agctab_5garray_table;
+ u16 phy_reg_arraylen, agctab_arraylen = 0, agctab_5garraylen;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ /* Normal chip,Mac0 use AGC_TAB.txt for 2G and 5G band. */
+ if (rtlhal->interfaceindex == 0) {
+ agctab_arraylen = AGCTAB_ARRAYLENGTH;
+ agctab_array_table = rtl8192de_agctab_array;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:MAC0, Rtl819XAGCTAB_Array\n"));
+ } else {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ agctab_arraylen = AGCTAB_2G_ARRAYLENGTH;
+ agctab_array_table = rtl8192de_agctab_2garray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:MAC1, Rtl819XAGCTAB_2GArray\n"));
+ } else {
+ agctab_5garraylen = AGCTAB_5G_ARRAYLENGTH;
+ agctab_5garray_table = rtl8192de_agctab_5garray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:MAC1, Rtl819XAGCTAB_5GArray\n"));
+
+ }
+ }
+ phy_reg_arraylen = PHY_REG_2T_ARRAYLENGTH;
+ phy_regarray_table = rtl8192de_phy_reg_2tarray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:Rtl819XPHY_REG_Array_PG\n"));
+ if (configtype == BASEBAND_CONFIG_PHY_REG) {
+ for (i = 0; i < phy_reg_arraylen; i = i + 2) {
+ if (phy_regarray_table[i] == 0xfe)
+ mdelay(50);
+ else if (phy_regarray_table[i] == 0xfd)
+ mdelay(5);
+ else if (phy_regarray_table[i] == 0xfc)
+ mdelay(1);
+ else if (phy_regarray_table[i] == 0xfb)
+ udelay(50);
+ else if (phy_regarray_table[i] == 0xfa)
+ udelay(5);
+ else if (phy_regarray_table[i] == 0xf9)
+ udelay(1);
+ rtl_set_bbreg(hw, phy_regarray_table[i], BMASKDWORD,
+ phy_regarray_table[i + 1]);
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The phy_regarray_table[0] is %x"
+ " Rtl819XPHY_REGArray[1] is %x\n",
+ phy_regarray_table[i],
+ phy_regarray_table[i + 1]));
+ }
+ } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
+ if (rtlhal->interfaceindex == 0) {
+ for (i = 0; i < agctab_arraylen; i = i + 2) {
+ rtl_set_bbreg(hw, agctab_array_table[i],
+ BMASKDWORD,
+ agctab_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register
+ * setting. */
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The Rtl819XAGCTAB_Array_"
+ "Table[0] is %ul "
+ "Rtl819XPHY_REGArray[1] is %ul\n",
+ agctab_array_table[i],
+ agctab_array_table[i + 1]));
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Normal Chip, MAC0, load "
+ "Rtl819XAGCTAB_Array\n"));
+ } else {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ for (i = 0; i < agctab_arraylen; i = i + 2) {
+ rtl_set_bbreg(hw, agctab_array_table[i],
+ BMASKDWORD,
+ agctab_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register
+ * setting. */
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The Rtl819XAGCTAB_Array_"
+ "Table[0] is %ul Rtl819XPHY_"
+ "REGArray[1] is %ul\n",
+ agctab_array_table[i],
+ agctab_array_table[i + 1]));
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Load Rtl819XAGCTAB_2GArray\n"));
+ } else {
+ for (i = 0; i < agctab_5garraylen; i = i + 2) {
+ rtl_set_bbreg(hw,
+ agctab_5garray_table[i],
+ BMASKDWORD,
+ agctab_5garray_table[i + 1]);
+ /* Add 1us delay between BB/RF registeri
+ * setting. */
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The Rtl819XAGCTAB_5GArray_"
+ "Table[0] is %ul Rtl819XPHY_"
+ "REGArray[1] is %ul\n",
+ agctab_5garray_table[i],
+ agctab_5garray_table[i + 1]));
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Load Rtl819XAGCTAB_5GArray\n"));
+ }
+ }
+ }
+ return true;
+}
+
+static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask,
+ u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ if (regaddr == RTXAGC_A_RATE18_06) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][0]));
+ }
+ if (regaddr == RTXAGC_A_RATE54_24) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][1]));
+ }
+ if (regaddr == RTXAGC_A_CCK1_MCS32) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][6]));
+ }
+ if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][7]));
+ }
+ if (regaddr == RTXAGC_A_MCS03_MCS00) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][2]));
+ }
+ if (regaddr == RTXAGC_A_MCS07_MCS04) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][3]));
+ }
+ if (regaddr == RTXAGC_A_MCS11_MCS08) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][4]));
+ }
+ if (regaddr == RTXAGC_A_MCS15_MCS12) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][5]));
+ }
+ if (regaddr == RTXAGC_B_RATE18_06) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][8]));
+ }
+ if (regaddr == RTXAGC_B_RATE54_24) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][9]));
+ }
+ if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][14]));
+ }
+ if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][15]));
+ }
+ if (regaddr == RTXAGC_B_MCS03_MCS00) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][10]));
+ }
+ if (regaddr == RTXAGC_B_MCS07_MCS04) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][11]));
+ }
+ if (regaddr == RTXAGC_B_MCS11_MCS08) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][12]));
+ }
+ if (regaddr == RTXAGC_B_MCS15_MCS12) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][13]));
+ rtlphy->pwrgroup_cnt++;
+ }
+}
+
+static bool _rtl92d_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+ u8 configtype)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+ u32 *phy_regarray_table_pg;
+ u16 phy_regarray_pg_len;
+
+ phy_regarray_pg_len = PHY_REG_ARRAY_PG_LENGTH;
+ phy_regarray_table_pg = rtl8192de_phy_reg_array_pg;
+ if (configtype == BASEBAND_CONFIG_PHY_REG) {
+ for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
+ if (phy_regarray_table_pg[i] == 0xfe)
+ mdelay(50);
+ else if (phy_regarray_table_pg[i] == 0xfd)
+ mdelay(5);
+ else if (phy_regarray_table_pg[i] == 0xfc)
+ mdelay(1);
+ else if (phy_regarray_table_pg[i] == 0xfb)
+ udelay(50);
+ else if (phy_regarray_table_pg[i] == 0xfa)
+ udelay(5);
+ else if (phy_regarray_table_pg[i] == 0xf9)
+ udelay(1);
+ _rtl92d_store_pwrindex_diffrate_offset(hw,
+ phy_regarray_table_pg[i],
+ phy_regarray_table_pg[i + 1],
+ phy_regarray_table_pg[i + 2]);
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ ("configtype != BaseBand_Config_PHY_REG\n"));
+ }
+ return true;
+}
+
+static bool _rtl92d_phy_bb_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ bool rtstatus = true;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n"));
+ rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_PHY_REG);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!"));
+ return false;
+ }
+
+ /* if (rtlphy->rf_type == RF_1T2R) {
+ * _rtl92c_phy_bb_config_1t(hw);
+ * RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n"));
+ *} */
+
+ if (rtlefuse->autoload_failflag == false) {
+ rtlphy->pwrgroup_cnt = 0;
+ rtstatus = _rtl92d_phy_config_bb_with_pgheaderfile(hw,
+ BASEBAND_CONFIG_PHY_REG);
+ }
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!"));
+ return false;
+ }
+ rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_AGC_TAB);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n"));
+ return false;
+ }
+ rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER2, 0x200));
+
+ return true;
+}
+
+bool rtl92d_phy_bb_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u16 regval;
+ u32 regvaldw;
+ u8 value;
+
+ _rtl92d_phy_init_bb_rf_register_definition(hw);
+ regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN,
+ regval | BIT(13) | BIT(0) | BIT(1));
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
+ /* 0x1f bit7 bit6 represent for mac0/mac1 driver ready */
+ value = rtl_read_byte(rtlpriv, REG_RF_CTRL);
+ rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB |
+ RF_SDMRSTB);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
+ FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
+ if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) {
+ regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
+ rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23));
+ }
+
+ return _rtl92d_phy_bb_config(hw);
+}
+
+bool rtl92d_phy_rf_config(struct ieee80211_hw *hw)
+{
+ return rtl92d_phy_rf6052_config(hw);
+}
+
+bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+ enum rf_content content,
+ enum radio_path rfpath)
+{
+ int i;
+ u32 *radioa_array_table;
+ u32 *radiob_array_table;
+ u16 radioa_arraylen, radiob_arraylen;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ radioa_arraylen = RADIOA_2T_ARRAYLENGTH;
+ radioa_array_table = rtl8192de_radioa_2tarray;
+ radiob_arraylen = RADIOB_2T_ARRAYLENGTH;
+ radiob_array_table = rtl8192de_radiob_2tarray;
+ if (rtlpriv->efuse.internal_pa_5g[0]) {
+ radioa_arraylen = RADIOA_2T_INT_PA_ARRAYLENGTH;
+ radioa_array_table = rtl8192de_radioa_2t_int_paarray;
+ }
+ if (rtlpriv->efuse.internal_pa_5g[1]) {
+ radiob_arraylen = RADIOB_2T_INT_PA_ARRAYLENGTH;
+ radiob_array_table = rtl8192de_radiob_2t_int_paarray;
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("PHY_ConfigRFWithHeaderFile() "
+ "Radio_A:Rtl819XRadioA_1TArray\n"));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("PHY_ConfigRFWithHeaderFile() "
+ "Radio_B:Rtl819XRadioB_1TArray\n"));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
+
+ /* this only happens when DMDP, mac0 start on 2.4G,
+ * mac1 start on 5G, mac 0 has to set phy0&phy1
+ * pathA or mac1 has to set phy0&phy1 pathA */
+ if ((content == radiob_txt) && (rfpath == RF90_PATH_A)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> althougth Path A, we load radiob.txt\n"));
+ radioa_arraylen = radiob_arraylen;
+ radioa_array_table = radiob_array_table;
+ }
+ switch (rfpath) {
+ case RF90_PATH_A:
+ for (i = 0; i < radioa_arraylen; i = i + 2) {
+ if (radioa_array_table[i] == 0xfe) {
+ mdelay(50);
+ } else if (radioa_array_table[i] == 0xfd) {
+ /* delay_ms(5); */
+ mdelay(5);
+ } else if (radioa_array_table[i] == 0xfc) {
+ /* delay_ms(1); */
+ mdelay(1);
+ } else if (radioa_array_table[i] == 0xfb) {
+ udelay(50);
+ } else if (radioa_array_table[i] == 0xfa) {
+ udelay(5);
+ } else if (radioa_array_table[i] == 0xf9) {
+ udelay(1);
+ } else {
+ rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
+ BRFREGOFFSETMASK,
+ radioa_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register set. */
+ udelay(1);
+ }
+ }
+ break;
+ case RF90_PATH_B:
+ for (i = 0; i < radiob_arraylen; i = i + 2) {
+ if (radiob_array_table[i] == 0xfe) {
+ /* Delay specific ms. Only RF configuration
+ * requires delay. */
+ mdelay(50);
+ } else if (radiob_array_table[i] == 0xfd) {
+ /* delay_ms(5); */
+ mdelay(5);
+ } else if (radiob_array_table[i] == 0xfc) {
+ /* delay_ms(1); */
+ mdelay(1);
+ } else if (radiob_array_table[i] == 0xfb) {
+ udelay(50);
+ } else if (radiob_array_table[i] == 0xfa) {
+ udelay(5);
+ } else if (radiob_array_table[i] == 0xf9) {
+ udelay(1);
+ } else {
+ rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
+ BRFREGOFFSETMASK,
+ radiob_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register set. */
+ udelay(1);
+ }
+ }
+ break;
+ case RF90_PATH_C:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ case RF90_PATH_D:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ return true;
+}
+
+void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ rtlphy->default_initialgain[0] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, BMASKBYTE0);
+ rtlphy->default_initialgain[1] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, BMASKBYTE0);
+ rtlphy->default_initialgain[2] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, BMASKBYTE0);
+ rtlphy->default_initialgain[3] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, BMASKBYTE0);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Default initial gain (c50=0x%x, "
+ "c58=0x%x, c60=0x%x, c68=0x%x\n",
+ rtlphy->default_initialgain[0],
+ rtlphy->default_initialgain[1],
+ rtlphy->default_initialgain[2],
+ rtlphy->default_initialgain[3]));
+ rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3,
+ BMASKBYTE0);
+ rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2,
+ BMASKDWORD);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Default framesync (0x%x) = 0x%x\n",
+ ROFDM0_RXDETECTOR3, rtlphy->framesync));
+}
+
+static void _rtl92d_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+ u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 index = (channel - 1);
+
+ /* 1. CCK */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* RF-A */
+ cckpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
+ /* RF-B */
+ cckpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
+ } else {
+ cckpowerlevel[RF90_PATH_A] = 0;
+ cckpowerlevel[RF90_PATH_B] = 0;
+ }
+ /* 2. OFDM for 1S or 2S */
+ if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) {
+ /* Read HT 40 OFDM TX power */
+ ofdmpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
+ ofdmpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
+ } else if (rtlphy->rf_type == RF_2T2R) {
+ /* Read HT 40 OFDM TX power */
+ ofdmpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
+ ofdmpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
+ }
+}
+
+static void _rtl92d_ccxpower_index_check(struct ieee80211_hw *hw,
+ u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
+ rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
+}
+
+static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl)
+{
+ u8 channel_5g[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128,
+ 130, 132, 134, 136, 138, 140, 149, 151,
+ 153, 155, 157, 159, 161, 163, 165
+ };
+ u8 place = chnl;
+
+ if (chnl > 14) {
+ for (place = 14; place < sizeof(channel_5g); place++) {
+ if (channel_5g[place] == chnl) {
+ place++;
+ break;
+ }
+ }
+ }
+ return place;
+}
+
+void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 cckpowerlevel[2], ofdmpowerlevel[2];
+
+ if (rtlefuse->txpwr_fromeprom == false)
+ return;
+ channel = _rtl92c_phy_get_rightchnlplace(channel);
+ _rtl92d_get_txpower_index(hw, channel, &cckpowerlevel[0],
+ &ofdmpowerlevel[0]);
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
+ _rtl92d_ccxpower_index_check(hw, channel, &cckpowerlevel[0],
+ &ofdmpowerlevel[0]);
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
+ rtl92d_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
+ rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
+}
+
+void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ enum io_type iotype;
+
+ if (!is_hal_stop(rtlhal)) {
+ switch (operation) {
+ case SCAN_OPT_BACKUP:
+ rtlhal->current_bandtypebackup =
+ rtlhal->current_bandtype;
+ iotype = IO_CMD_PAUSE_DM_BY_SCAN;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+ (u8 *)&iotype);
+ break;
+ case SCAN_OPT_RESTORE:
+ iotype = IO_CMD_RESUME_DM_BY_SCAN;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+ (u8 *)&iotype);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Unknown Scan Backup operation.\n"));
+ break;
+ }
+ }
+}
+
+void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ unsigned long flag = 0;
+ u8 reg_prsr_rsc;
+ u8 reg_bw_opmode;
+
+ if (rtlphy->set_bwmode_inprogress)
+ return;
+ if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("FALSE driver sleep or unload\n"));
+ return;
+ }
+ rtlphy->set_bwmode_inprogress = true;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+ ("Switch to %s bandwidth\n",
+ rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+ "20MHz" : "40MHz"));
+ reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
+ reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
+ switch (rtlphy->current_chan_bw) {
+ case HT_CHANNEL_WIDTH_20:
+ reg_bw_opmode |= BW_OPMODE_20MHZ;
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+
+ reg_prsr_rsc = (reg_prsr_rsc & 0x90) |
+ (mac->cur_40_prime_sc << 5);
+ rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+ break;
+ }
+ switch (rtlphy->current_chan_bw) {
+ case HT_CHANNEL_WIDTH_20:
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
+ /* SET BIT10 BIT11 for receive cck */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+ BIT(11), 3);
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+ /* Set Control channel to upper or lower.
+ * These settings are required only for 40MHz */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCKSIDEBAND,
+ (mac->cur_40_prime_sc >> 1));
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+ /* SET BIT10 BIT11 for receive cck */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+ BIT(11), 0);
+ rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
+ (mac->cur_40_prime_sc ==
+ HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+ break;
+
+ }
+ rtl92d_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+ rtlphy->set_bwmode_inprogress = false;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+
+static void _rtl92d_phy_stop_trx_before_changeband(struct ieee80211_hw *hw)
+{
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0);
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x00);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x0);
+}
+
+static void rtl92d_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 value8;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n"));
+ rtlhal->bandset = band;
+ rtlhal->current_bandtype = band;
+ if (IS_92D_SINGLEPHY(rtlhal->version))
+ rtlhal->bandset = BAND_ON_BOTH;
+ /* stop RX/Tx */
+ _rtl92d_phy_stop_trx_before_changeband(hw);
+ /* reconfig BB/RF according to wireless mode */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* BB & RF Config */
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>2.4G\n"));
+ if (rtlhal->interfaceindex == 1)
+ _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_AGC_TAB);
+ } else {
+ /* 5G band */
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>5G\n"));
+ if (rtlhal->interfaceindex == 1)
+ _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_AGC_TAB);
+ }
+ rtl92d_update_bbrf_configuration(hw);
+ if (rtlhal->current_bandtype == BAND_ON_2_4G)
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+
+ /* 20M BW. */
+ /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); */
+ rtlhal->reloadtxpowerindex = true;
+ /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1));
+ value8 |= BIT(1);
+ rtl_write_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1), value8);
+ } else {
+ value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1));
+ value8 &= (~BIT(1));
+ rtl_write_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1), value8);
+ }
+ mdelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==Switch Band OK.\n"));
+}
+
+static void _rtl92d_phy_reload_imr_setting(struct ieee80211_hw *hw,
+ u8 channel, u8 rfpath)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 imr_num = MAX_RF_IMR_INDEX;
+ u32 rfmask = BRFREGOFFSETMASK;
+ u8 group, i;
+ unsigned long flag = 0;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>path %d\n", rfpath));
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n"));
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+ /* fc area 0xd2c */
+ if (channel > 99)
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) |
+ BIT(14), 2);
+ else
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) |
+ BIT(14), 1);
+ /* leave 0 for channel1-14. */
+ group = channel <= 64 ? 1 : 2;
+ imr_num = MAX_RF_IMR_INDEX_NORMAL;
+ for (i = 0; i < imr_num; i++)
+ rtl_set_rfreg(hw, (enum radio_path)rfpath,
+ rf_reg_for_5g_swchnl_normal[i], rfmask,
+ rf_imr_param_normal[0][group][i]);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 1);
+ } else {
+ /* G band. */
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ ("Load RF IMR parameters for G band. IMR already "
+ "setting %d\n",
+ rtlpriv->rtlhal.load_imrandiqk_setting_for2g));
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n"));
+ if (!rtlpriv->rtlhal.load_imrandiqk_setting_for2g) {
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ ("Load RF IMR parameters "
+ "for G band. %d\n", rfpath));
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4,
+ 0x00f00000, 0xf);
+ imr_num = MAX_RF_IMR_INDEX_NORMAL;
+ for (i = 0; i < imr_num; i++) {
+ rtl_set_rfreg(hw, (enum radio_path)rfpath,
+ rf_reg_for_5g_swchnl_normal[i],
+ BRFREGOFFSETMASK,
+ rf_imr_param_normal[0][0][i]);
+ }
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4,
+ 0x00f00000, 0);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN | BCCKEN, 3);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_enable_rf_env(struct ieee80211_hw *hw,
+ u8 rfpath, u32 *pu4_regval)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n"));
+ /*----Store original RFENV control type----*/
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ *pu4_regval = rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ *pu4_regval =
+ rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16);
+ break;
+ }
+ /*----Set RF_ENV enable----*/
+ rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+ udelay(1);
+ /*----Set RF_ENV output high----*/
+ rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+ udelay(1);
+ /* Set bit number of Address and Data for RF register */
+ /* Set 1 to 4 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREADDRESSLENGTH, 0x0);
+ udelay(1);
+ /*Set 0 to 12 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_restore_rf_env(struct ieee80211_hw *hw, u8 rfpath,
+ u32 *pu4_regval)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("=====>\n"));
+ /*----Restore RFENV control type----*/ ;
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, *pu4_regval);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
+ *pu4_regval);
+ break;
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<=====\n"));
+}
+
+static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 path = rtlhal->current_bandtype ==
+ BAND_ON_5G ? RF90_PATH_A : RF90_PATH_B;
+ u8 index = 0, i = 0, rfpath = RF90_PATH_A;
+ bool need_pwr_down = false, internal_pa = false;
+ u32 u4regvalue, mask = 0x1C000, value = 0, u4tmp, u4tmp2;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>\n"));
+ /* config path A for 5G */
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n"));
+ u4tmp = curveindex_5g[channel - 1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 1 set RF-A, 5G, "
+ "0x28 = 0x%x !!\n", u4tmp));
+ for (i = 0; i < RF_CHNL_NUM_5G; i++) {
+ if (channel == rf_chnl_5g[i] && channel <= 140)
+ index = 0;
+ }
+ for (i = 0; i < RF_CHNL_NUM_5G_40M; i++) {
+ if (channel == rf_chnl_5g_40m[i] && channel <= 140)
+ index = 1;
+ }
+ if (channel == 149 || channel == 155 || channel == 161)
+ index = 2;
+ else if (channel == 151 || channel == 153 || channel == 163
+ || channel == 165)
+ index = 3;
+ else if (channel == 157 || channel == 159)
+ index = 4;
+
+ if (rtlhal->macphymode == DUALMAC_DUALPHY
+ && rtlhal->interfaceindex == 1) {
+ need_pwr_down = rtl92d_phy_enable_anotherphy(hw, false);
+ rtlhal->during_mac1init_radioa = true;
+ /* asume no this case */
+ if (need_pwr_down)
+ _rtl92d_phy_enable_rf_env(hw, path,
+ &u4regvalue);
+ }
+ for (i = 0; i < RF_REG_NUM_FOR_C_CUT_5G; i++) {
+ if (i == 0 && (rtlhal->macphymode == DUALMAC_DUALPHY)) {
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i],
+ BRFREGOFFSETMASK, 0xE439D);
+ } else if (rf_reg_for_c_cut_5g[i] == RF_SYN_G4) {
+ u4tmp2 = (rf_reg_pram_c_5g[index][i] &
+ 0x7FF) | (u4tmp << 11);
+ if (channel == 36)
+ u4tmp2 &= ~(BIT(7) | BIT(6));
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i],
+ BRFREGOFFSETMASK, u4tmp2);
+ } else {
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i],
+ BRFREGOFFSETMASK,
+ rf_reg_pram_c_5g[index][i]);
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ ("offset 0x%x value 0x%x "
+ "path %d index %d readback 0x%x\n",
+ rf_reg_for_c_cut_5g[i],
+ rf_reg_pram_c_5g[index][i], path,
+ index, rtl_get_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i], BRFREGOFFSETMASK)));
+ }
+ if (need_pwr_down)
+ _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue);
+ if (rtlhal->during_mac1init_radioa)
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ if (channel < 149)
+ value = 0x07;
+ else if (channel >= 149)
+ value = 0x02;
+ if (channel >= 36 && channel <= 64)
+ index = 0;
+ else if (channel >= 100 && channel <= 140)
+ index = 1;
+ else
+ index = 2;
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+ rtlhal->interfaceindex == 1) /* MAC 1 5G */
+ internal_pa = rtlpriv->efuse.internal_pa_5g[1];
+ else
+ internal_pa =
+ rtlpriv->efuse.internal_pa_5g[rfpath];
+ if (internal_pa) {
+ for (i = 0;
+ i < RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA;
+ i++) {
+ rtl_set_rfreg(hw, rfpath,
+ rf_for_c_cut_5g_internal_pa[i],
+ BRFREGOFFSETMASK,
+ rf_pram_c_5g_int_pa[index][i]);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+ ("offset 0x%x value 0x%x "
+ "path %d index %d\n",
+ rf_for_c_cut_5g_internal_pa[i],
+ rf_pram_c_5g_int_pa[index][i],
+ rfpath, index));
+ }
+ } else {
+ rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B,
+ mask, value);
+ }
+ }
+ } else if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n"));
+ u4tmp = curveindex_2g[channel - 1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 3 set RF-B, 2G, "
+ "0x28 = 0x%x !!\n", u4tmp));
+ if (channel == 1 || channel == 2 || channel == 4 || channel == 9
+ || channel == 10 || channel == 11 || channel == 12)
+ index = 0;
+ else if (channel == 3 || channel == 13 || channel == 14)
+ index = 1;
+ else if (channel >= 5 && channel <= 8)
+ index = 2;
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ path = RF90_PATH_A;
+ if (rtlhal->interfaceindex == 0) {
+ need_pwr_down =
+ rtl92d_phy_enable_anotherphy(hw, true);
+ rtlhal->during_mac0init_radiob = true;
+
+ if (need_pwr_down)
+ _rtl92d_phy_enable_rf_env(hw, path,
+ &u4regvalue);
+ }
+ }
+ for (i = 0; i < RF_REG_NUM_FOR_C_CUT_2G; i++) {
+ if (rf_reg_for_c_cut_2g[i] == RF_SYN_G7)
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_2g[i],
+ BRFREGOFFSETMASK,
+ (rf_reg_param_for_c_cut_2g[index][i] |
+ BIT(17)));
+ else
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_2g[i],
+ BRFREGOFFSETMASK,
+ rf_reg_param_for_c_cut_2g
+ [index][i]);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ ("offset 0x%x value 0x%x mak 0x%x path %d "
+ "index %d readback 0x%x\n",
+ rf_reg_for_c_cut_2g[i],
+ rf_reg_param_for_c_cut_2g[index][i],
+ rf_reg_mask_for_c_cut_2g[i], path, index,
+ rtl_get_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_2g[i],
+ BRFREGOFFSETMASK)));
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("cosa ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n",
+ rf_syn_g4_for_c_cut_2g | (u4tmp << 11)));
+
+ rtl_set_rfreg(hw, (enum radio_path)path, RF_SYN_G4,
+ BRFREGOFFSETMASK,
+ rf_syn_g4_for_c_cut_2g | (u4tmp << 11));
+ if (need_pwr_down)
+ _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue);
+ if (rtlhal->during_mac0init_radiob)
+ rtl92d_phy_powerdown_anotherphy(hw, true);
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl)
+{
+ u8 channel_all[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128, 130,
+ 132, 134, 136, 138, 140, 149, 151, 153, 155,
+ 157, 159, 161, 163, 165
+ };
+ u8 place = chnl;
+
+ if (chnl > 14) {
+ for (place = 14; place < sizeof(channel_all); place++) {
+ if (channel_all[place] == chnl)
+ return place - 13;
+ }
+ }
+
+ return 0;
+}
+
+#define MAX_TOLERANCE 5
+#define IQK_DELAY_TIME 1 /* ms */
+#define MAX_TOLERANCE_92D 3
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_patha_iqk(struct ieee80211_hw *hw, bool configpathb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 regeac, rege94, rege9c, regea4;
+ u8 result = 0;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n"));
+ /* path-A IQK setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+ if (rtlhal->interfaceindex == 0) {
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c1f);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c1f);
+ } else {
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c22);
+ }
+ rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140102);
+ rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x28160206);
+ /* path-B IQK setting */
+ if (configpathb) {
+ rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140102);
+ rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x28160206);
+ }
+ /* LO calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+ rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+ /* One shot, path A LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000);
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path A LOK & IQK.\n",
+ IQK_DELAY_TIME));
+ mdelay(IQK_DELAY_TIME);
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94));
+ rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c));
+ regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4));
+ if (!(regeac & BIT(28)) && (((rege94 & 0x03FF0000) >> 16) != 0x142) &&
+ (((rege9c & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else /* if Tx not OK, ignore Rx */
+ return result;
+ /* if Tx is OK, check whether Rx is OK */
+ if (!(regeac & BIT(27)) && (((regea4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((regeac & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+ else
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A Rx IQK fail!!\n"));
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw,
+ bool configpathb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 regeac, rege94, rege9c, regea4;
+ u8 result = 0;
+ u8 i;
+ u8 retrycount = 2;
+ u32 TxOKBit = BIT(28), RxOKBit = BIT(27);
+
+ if (rtlhal->interfaceindex == 1) { /* PHY1 */
+ TxOKBit = BIT(31);
+ RxOKBit = BIT(30);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n"));
+ /* path-A IQK setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140307);
+ rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68160960);
+ /* path-B IQK setting */
+ if (configpathb) {
+ rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82110000);
+ rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68110000);
+ }
+ /* LO calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+ rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+ /* path-A PA on */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x07000f60);
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD, 0x66e60e30);
+ for (i = 0; i < retrycount; i++) {
+ /* One shot, path A LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000);
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path A LOK & IQK.\n",
+ IQK_DELAY_TIME));
+ mdelay(IQK_DELAY_TIME * 10);
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94));
+ rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c));
+ regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4));
+ if (!(regeac & TxOKBit) &&
+ (((rege94 & 0x03FF0000) >> 16) != 0x142)) {
+ result |= 0x01;
+ } else { /* if Tx not OK, ignore Rx */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A Tx IQK fail!!\n"));
+ continue;
+ }
+
+ /* if Tx is OK, check whether Rx is OK */
+ if (!(regeac & RxOKBit) &&
+ (((regea4 & 0x03FF0000) >> 16) != 0x132)) {
+ result |= 0x02;
+ break;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A Rx IQK fail!!\n"));
+ }
+ }
+ /* path A PA off */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD,
+ rtlphy->iqk_bb_backup[0]);
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD,
+ rtlphy->iqk_bb_backup[1]);
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_pathb_iqk(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 regeac, regeb4, regebc, regec4, regecc;
+ u8 result = 0;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n"));
+ /* One shot, path B LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000002);
+ rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000000);
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path B LOK & IQK.\n",
+ IQK_DELAY_TIME));
+ mdelay(IQK_DELAY_TIME);
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4));
+ regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc));
+ regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4));
+ regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc));
+ if (!(regeac & BIT(31)) && (((regeb4 & 0x03FF0000) >> 16) != 0x142) &&
+ (((regebc & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else
+ return result;
+ if (!(regeac & BIT(30)) && (((regec4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((regecc & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+ else
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B Rx IQK fail!!\n"));
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_pathb_iqk_5g_normal(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 regeac, regeb4, regebc, regec4, regecc;
+ u8 result = 0;
+ u8 i;
+ u8 retrycount = 2;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n"));
+ /* path-A IQK setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82110000);
+ rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68110000);
+
+ /* path-B IQK setting */
+ rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140307);
+ rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68160960);
+
+ /* LO calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+ rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+
+ /* path-B PA on */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x0f600700);
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD, 0x061f0d30);
+
+ for (i = 0; i < retrycount; i++) {
+ /* One shot, path B LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xfa000000);
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path B LOK & IQK.\n", 10));
+ mdelay(IQK_DELAY_TIME * 10);
+
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4));
+ regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc));
+ regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4));
+ regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc));
+ if (!(regeac & BIT(31)) &&
+ (((regeb4 & 0x03FF0000) >> 16) != 0x142))
+ result |= 0x01;
+ else
+ continue;
+ if (!(regeac & BIT(30)) &&
+ (((regec4 & 0x03FF0000) >> 16) != 0x132)) {
+ result |= 0x02;
+ break;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B Rx IQK fail!!\n"));
+ }
+ }
+
+ /* path B PA off */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD,
+ rtlphy->iqk_bb_backup[0]);
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD,
+ rtlphy->iqk_bb_backup[2]);
+ return result;
+}
+
+static void _rtl92d_phy_save_adda_registers(struct ieee80211_hw *hw,
+ u32 *adda_reg, u32 *adda_backup,
+ u32 regnum)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save ADDA parameters.\n"));
+ for (i = 0; i < regnum; i++)
+ adda_backup[i] = rtl_get_bbreg(hw, adda_reg[i], BMASKDWORD);
+}
+
+static void _rtl92d_phy_save_mac_registers(struct ieee80211_hw *hw,
+ u32 *macreg, u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save MAC parameters.\n"));
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
+ macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
+}
+
+static void _rtl92d_phy_reload_adda_registers(struct ieee80211_hw *hw,
+ u32 *adda_reg, u32 *adda_backup,
+ u32 regnum)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Reload ADDA power saving parameters !\n"));
+ for (i = 0; i < regnum; i++)
+ rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, adda_backup[i]);
+}
+
+static void _rtl92d_phy_reload_mac_registers(struct ieee80211_hw *hw,
+ u32 *macreg, u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Reload MAC parameters !\n"));
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
+ rtl_write_byte(rtlpriv, macreg[i], macbackup[i]);
+}
+
+static void _rtl92d_phy_path_adda_on(struct ieee80211_hw *hw,
+ u32 *adda_reg, bool patha_on, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 pathon;
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ADDA ON.\n"));
+ pathon = patha_on ? 0x04db25a4 : 0x0b1b25a4;
+ if (patha_on)
+ pathon = rtlpriv->rtlhal.interfaceindex == 0 ?
+ 0x04db25a4 : 0x0b1b25a4;
+ for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+ rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, pathon);
+}
+
+static void _rtl92d_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+ u32 *macreg, u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("MAC settings for Calibration.\n"));
+ rtl_write_byte(rtlpriv, macreg[0], 0x3F);
+
+ for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+ rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] &
+ (~BIT(3))));
+ rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
+}
+
+static void _rtl92d_phy_patha_standby(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A standby mode!\n"));
+
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x0);
+ rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD, 0x00010000);
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+}
+
+static void _rtl92d_phy_pimode_switch(struct ieee80211_hw *hw, bool pi_mode)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 mode;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("BB Switch to %s mode!\n", (pi_mode ? "PI" : "SI")));
+ mode = pi_mode ? 0x01000100 : 0x01000000;
+ rtl_set_bbreg(hw, 0x820, BMASKDWORD, mode);
+ rtl_set_bbreg(hw, 0x828, BMASKDWORD, mode);
+}
+
+static void _rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw, long result[][8],
+ u8 t, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 i;
+ u8 patha_ok, pathb_ok;
+ static u32 adda_reg[IQK_ADDA_REG_NUM] = {
+ RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74,
+ 0xe78, 0xe7c, 0xe80, 0xe84,
+ 0xe88, 0xe8c, 0xed0, 0xed4,
+ 0xed8, 0xedc, 0xee0, 0xeec
+ };
+ static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+ 0x522, 0x550, 0x551, 0x040
+ };
+ static u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
+ RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE,
+ RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR,
+ RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE,
+ RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4,
+ ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1
+ };
+ const u32 retrycount = 2;
+ u32 bbvalue;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 2.4G :Start!!!\n"));
+ if (t == 0) {
+ bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n",
+ (is2t ? "2T2R" : "1T1R")));
+
+ /* Save ADDA parameters, turn Path A ADDA on */
+ _rtl92d_phy_save_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup, IQK_ADDA_REG_NUM);
+ _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup, IQK_BB_REG_NUM);
+ }
+ _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t);
+ if (t == 0)
+ rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER1, BIT(8));
+
+ /* Switch BB to PI mode to do IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, true);
+
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00);
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600);
+ rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22204000);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f);
+ if (is2t) {
+ rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD,
+ 0x00010000);
+ rtl_set_bbreg(hw, RFPGA0_XB_LSSIPARAMETER, BMASKDWORD,
+ 0x00010000);
+ }
+ /* MAC settings */
+ _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ /* Page B init */
+ rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000);
+ if (is2t)
+ rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000);
+ /* IQ calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+ rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x01007c00);
+ rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800);
+ for (i = 0; i < retrycount; i++) {
+ patha_ok = _rtl92d_phy_patha_iqk(hw, is2t);
+ if (patha_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQK Success!!\n"));
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ break;
+ } else if (i == (retrycount - 1) && patha_ok == 0x01) {
+ /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQK Only Tx Success!!\n"));
+
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ }
+ }
+ if (0x00 == patha_ok)
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK failed!!\n"));
+ if (is2t) {
+ _rtl92d_phy_patha_standby(hw);
+ /* Turn Path B ADDA on */
+ _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t);
+ for (i = 0; i < retrycount; i++) {
+ pathb_ok = _rtl92d_phy_pathb_iqk(hw);
+ if (pathb_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][6] = (rtl_get_bbreg(hw, 0xec4,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][7] = (rtl_get_bbreg(hw, 0xecc,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ break;
+ } else if (i == (retrycount - 1) && pathb_ok == 0x01) {
+ /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B Only Tx IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ }
+ }
+ if (0x00 == pathb_ok)
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK failed!!\n"));
+ }
+
+ /* Back to BB mode, load original value */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK:Back to BB mode, load original value!\n"));
+
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0);
+ if (t != 0) {
+ /* Switch back BB to SI mode after finish IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, false);
+ /* Reload ADDA power saving parameters */
+ _rtl92d_phy_reload_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup, IQK_ADDA_REG_NUM);
+ /* Reload MAC parameters */
+ _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ if (is2t)
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM);
+ else
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM - 1);
+ /* load 0xe30 IQC default value */
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x01008c00);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x01008c00);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n"));
+}
+
+static void _rtl92d_phy_iq_calibrate_5g_normal(struct ieee80211_hw *hw,
+ long result[][8], u8 t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 patha_ok, pathb_ok;
+ static u32 adda_reg[IQK_ADDA_REG_NUM] = {
+ RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74,
+ 0xe78, 0xe7c, 0xe80, 0xe84,
+ 0xe88, 0xe8c, 0xed0, 0xed4,
+ 0xed8, 0xedc, 0xee0, 0xeec
+ };
+ static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+ 0x522, 0x550, 0x551, 0x040
+ };
+ static u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
+ RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE,
+ RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR,
+ RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE,
+ RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4,
+ ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1
+ };
+ u32 bbvalue;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+
+ /* Note: IQ calibration must be performed after loading
+ * PHY_REG.txt , and radio_a, radio_b.txt */
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 5G NORMAL:Start!!!\n"));
+ mdelay(IQK_DELAY_TIME * 20);
+ if (t == 0) {
+ bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n",
+ (is2t ? "2T2R" : "1T1R")));
+ /* Save ADDA parameters, turn Path A ADDA on */
+ _rtl92d_phy_save_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup,
+ IQK_ADDA_REG_NUM);
+ _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ if (is2t)
+ _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM);
+ else
+ _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM - 1);
+ }
+ _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t);
+ /* MAC settings */
+ _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ if (t == 0)
+ rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER1, BIT(8));
+ /* Switch BB to PI mode to do IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, true);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00);
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600);
+ rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22208000);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f);
+
+ /* Page B init */
+ rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000);
+ if (is2t)
+ rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000);
+ /* IQ calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+ rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x10007c00);
+ rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800);
+ patha_ok = _rtl92d_phy_patha_iqk_5g_normal(hw, is2t);
+ if (patha_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Success!!\n"));
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else if (patha_ok == 0x01) { /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQK Only Tx Success!!\n"));
+
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Fail!!\n"));
+ }
+ if (is2t) {
+ /* _rtl92d_phy_patha_standby(hw); */
+ /* Turn Path B ADDA on */
+ _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t);
+ pathb_ok = _rtl92d_phy_pathb_iqk_5g_normal(hw);
+ if (pathb_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][6] = (rtl_get_bbreg(hw, 0xec4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][7] = (rtl_get_bbreg(hw, 0xecc, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else if (pathb_ok == 0x01) { /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B Only Tx IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK failed!!\n"));
+ }
+ }
+
+ /* Back to BB mode, load original value */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK:Back to BB mode, load original value!\n"));
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0);
+ if (t != 0) {
+ if (is2t)
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM);
+ else
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM - 1);
+ /* Reload MAC parameters */
+ _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ /* Switch back BB to SI mode after finish IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, false);
+ /* Reload ADDA power saving parameters */
+ _rtl92d_phy_reload_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup,
+ IQK_ADDA_REG_NUM);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n"));
+}
+
+static bool _rtl92d_phy_simularity_compare(struct ieee80211_hw *hw,
+ long result[][8], u8 c1, u8 c2)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 i, j, diff, sim_bitmap, bound;
+ u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
+ bool bresult = true;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+
+ if (is2t)
+ bound = 8;
+ else
+ bound = 4;
+ sim_bitmap = 0;
+ for (i = 0; i < bound; i++) {
+ diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] -
+ result[c2][i]) : (result[c2][i] - result[c1][i]);
+ if (diff > MAX_TOLERANCE_92D) {
+ if ((i == 2 || i == 6) && !sim_bitmap) {
+ if (result[c1][i] + result[c1][i + 1] == 0)
+ final_candidate[(i / 4)] = c2;
+ else if (result[c2][i] + result[c2][i + 1] == 0)
+ final_candidate[(i / 4)] = c1;
+ else
+ sim_bitmap = sim_bitmap | (1 << i);
+ } else {
+ sim_bitmap = sim_bitmap | (1 << i);
+ }
+ }
+ }
+ if (sim_bitmap == 0) {
+ for (i = 0; i < (bound / 4); i++) {
+ if (final_candidate[i] != 0xFF) {
+ for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+ result[3][j] =
+ result[final_candidate[i]][j];
+ bresult = false;
+ }
+ }
+ return bresult;
+ }
+ if (!(sim_bitmap & 0x0F)) { /* path A OK */
+ for (i = 0; i < 4; i++)
+ result[3][i] = result[c1][i];
+ } else if (!(sim_bitmap & 0x03)) { /* path A, Tx OK */
+ for (i = 0; i < 2; i++)
+ result[3][i] = result[c1][i];
+ }
+ if (!(sim_bitmap & 0xF0) && is2t) { /* path B OK */
+ for (i = 4; i < 8; i++)
+ result[3][i] = result[c1][i];
+ } else if (!(sim_bitmap & 0x30)) { /* path B, Tx OK */
+ for (i = 4; i < 6; i++)
+ result[3][i] = result[c1][i];
+ }
+ return false;
+}
+
+static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw,
+ bool iqk_ok, long result[][8],
+ u8 final_candidate, bool txonly)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 oldval_0, val_x, tx0_a, reg;
+ long val_y, tx0_c;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version) ||
+ rtlhal->macphymode == DUALMAC_DUALPHY;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQ Calibration %s !\n",
+ (iqk_ok) ? "Success" : "Failed"));
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqk_ok) {
+ oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD) >> 22) & 0x3FF; /* OFDM0_D */
+ val_x = result[final_candidate][0];
+ if ((val_x & 0x00000200) != 0)
+ val_x = val_x | 0xFFFFFC00;
+ tx0_a = (val_x * oldval_0) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx0_a = 0x%x,"
+ " oldval_0 0x%x\n", val_x, tx0_a, oldval_0));
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
+ ((val_x * oldval_0 >> 7) & 0x1));
+ val_y = result[final_candidate][1];
+ if ((val_y & 0x00000200) != 0)
+ val_y = val_y | 0xFFFFFC00;
+ /* path B IQK result + 3 */
+ if (rtlhal->interfaceindex == 1 &&
+ rtlhal->current_bandtype == BAND_ON_5G)
+ val_y += 3;
+ tx0_c = (val_y * oldval_0) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx0_c = 0x%lx\n",
+ val_y, tx0_c));
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000,
+ ((tx0_c & 0x3C0) >> 6));
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000,
+ (tx0_c & 0x3F));
+ if (is2t)
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26),
+ ((val_y * oldval_0 >> 7) & 0x1));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xC80 = 0x%x\n",
+ rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD)));
+ if (txonly) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("only Tx OK\n"));
+ return;
+ }
+ reg = result[final_candidate][2];
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
+ reg = result[final_candidate][3] & 0x3F;
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
+ reg = (result[final_candidate][3] >> 6) & 0xF;
+ rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+ }
+}
+
+static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw,
+ bool iqk_ok, long result[][8], u8 final_candidate, bool txonly)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 oldval_1, val_x, tx1_a, reg;
+ long val_y, tx1_c;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQ Calibration %s !\n",
+ (iqk_ok) ? "Success" : "Failed"));
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqk_ok) {
+ oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD) >> 22) & 0x3FF;
+ val_x = result[final_candidate][4];
+ if ((val_x & 0x00000200) != 0)
+ val_x = val_x | 0xFFFFFC00;
+ tx1_a = (val_x * oldval_1) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx1_a = 0x%x\n",
+ val_x, tx1_a));
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28),
+ ((val_x * oldval_1 >> 7) & 0x1));
+ val_y = result[final_candidate][5];
+ if ((val_y & 0x00000200) != 0)
+ val_y = val_y | 0xFFFFFC00;
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ val_y += 3;
+ tx1_c = (val_y * oldval_1) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx1_c = 0x%lx\n",
+ val_y, tx1_c));
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000,
+ ((tx1_c & 0x3C0) >> 6));
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000,
+ (tx1_c & 0x3F));
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30),
+ ((val_y * oldval_1 >> 7) & 0x1));
+ if (txonly)
+ return;
+ reg = result[final_candidate][6];
+ rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
+ reg = result[final_candidate][7] & 0x3F;
+ rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
+ reg = (result[final_candidate][7] >> 6) & 0xF;
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg);
+ }
+}
+
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ long result[4][8];
+ u8 i, final_candidate, indexforchannel;
+ bool patha_ok, pathb_ok;
+ long rege94, rege9c, regea4, regeac, regeb4;
+ long regebc, regec4, regecc, regtmp = 0;
+ bool is12simular, is13simular, is23simular;
+ unsigned long flag = 0;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK:Start!!!channel %d\n", rtlphy->current_channel));
+ for (i = 0; i < 8; i++) {
+ result[0][i] = 0;
+ result[1][i] = 0;
+ result[2][i] = 0;
+ result[3][i] = 0;
+ }
+ final_candidate = 0xff;
+ patha_ok = false;
+ pathb_ok = false;
+ is12simular = false;
+ is23simular = false;
+ is13simular = false;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK !!!currentband %d\n", rtlhal->current_bandtype));
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ for (i = 0; i < 3; i++) {
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ _rtl92d_phy_iq_calibrate_5g_normal(hw, result, i);
+ } else if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ if (IS_92D_SINGLEPHY(rtlhal->version))
+ _rtl92d_phy_iq_calibrate(hw, result, i, true);
+ else
+ _rtl92d_phy_iq_calibrate(hw, result, i, false);
+ }
+ if (i == 1) {
+ is12simular = _rtl92d_phy_simularity_compare(hw, result,
+ 0, 1);
+ if (is12simular) {
+ final_candidate = 0;
+ break;
+ }
+ }
+ if (i == 2) {
+ is13simular = _rtl92d_phy_simularity_compare(hw, result,
+ 0, 2);
+ if (is13simular) {
+ final_candidate = 0;
+ break;
+ }
+ is23simular = _rtl92d_phy_simularity_compare(hw, result,
+ 1, 2);
+ if (is23simular) {
+ final_candidate = 1;
+ } else {
+ for (i = 0; i < 8; i++)
+ regtmp += result[3][i];
+
+ if (regtmp != 0)
+ final_candidate = 3;
+ else
+ final_candidate = 0xFF;
+ }
+ }
+ }
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ for (i = 0; i < 4; i++) {
+ rege94 = result[i][0];
+ rege9c = result[i][1];
+ regea4 = result[i][2];
+ regeac = result[i][3];
+ regeb4 = result[i][4];
+ regebc = result[i][5];
+ regec4 = result[i][6];
+ regecc = result[i][7];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx "
+ "regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ",
+ rege94, rege9c, regea4, regeac, regeb4, regebc, regec4,
+ regecc));
+ }
+ if (final_candidate != 0xff) {
+ rtlphy->reg_e94 = rege94 = result[final_candidate][0];
+ rtlphy->reg_e9c = rege9c = result[final_candidate][1];
+ regea4 = result[final_candidate][2];
+ regeac = result[final_candidate][3];
+ rtlphy->reg_eb4 = regeb4 = result[final_candidate][4];
+ rtlphy->reg_ebc = regebc = result[final_candidate][5];
+ regec4 = result[final_candidate][6];
+ regecc = result[final_candidate][7];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK: final_candidate is %x\n", final_candidate));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx "
+ "regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ",
+ rege94, rege9c, regea4, regeac, regeb4, regebc, regec4,
+ regecc));
+ patha_ok = pathb_ok = true;
+ } else {
+ rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; /* X default value */
+ rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; /* Y default value */
+ }
+ if ((rege94 != 0) /*&&(regea4 != 0) */)
+ _rtl92d_phy_patha_fill_iqk_matrix(hw, patha_ok, result,
+ final_candidate, (regea4 == 0));
+ if (IS_92D_SINGLEPHY(rtlhal->version)) {
+ if ((regeb4 != 0) /*&&(regec4 != 0) */)
+ _rtl92d_phy_pathb_fill_iqk_matrix(hw, pathb_ok, result,
+ final_candidate, (regec4 == 0));
+ }
+ if (final_candidate != 0xFF) {
+ indexforchannel = rtl92d_get_rightchnlplace_for_iqk(
+ rtlphy->current_channel);
+
+ for (i = 0; i < IQK_MATRIX_REG_NUM; i++)
+ rtlphy->iqk_matrix_regsetting[indexforchannel].
+ value[0][i] = result[final_candidate][i];
+ rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done =
+ true;
+
+ RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD,
+ ("\nIQK OK indexforchannel %d.\n", indexforchannel));
+ }
+}
+
+void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 indexforchannel;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("channel %d\n", channel));
+ /*------Do IQK for normal chip and test chip 5G band------- */
+ indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("indexforchannel %d done %d\n", indexforchannel,
+ rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done));
+ if (0 && !rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done &&
+ rtlphy->need_iqk) {
+ /* Re Do IQK. */
+ RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD,
+ ("Do IQK Matrix reg for channel:%d....\n", channel));
+ rtl92d_phy_iq_calibrate(hw);
+ } else {
+ /* Just load the value. */
+ /* 2G band just load once. */
+ if (((!rtlhal->load_imrandiqk_setting_for2g) &&
+ indexforchannel == 0) || indexforchannel > 0) {
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ ("Just Read IQK Matrix reg for channel:%d"
+ "....\n", channel));
+ if ((rtlphy->iqk_matrix_regsetting[indexforchannel].
+ value[0] != NULL)
+ /*&&(regea4 != 0) */)
+ _rtl92d_phy_patha_fill_iqk_matrix(hw, true,
+ rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value, 0,
+ (rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value[0][2] == 0));
+ if (IS_92D_SINGLEPHY(rtlhal->version)) {
+ if ((rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value[0][4] != 0)
+ /*&&(regec4 != 0) */)
+ _rtl92d_phy_pathb_fill_iqk_matrix(hw,
+ true,
+ rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value, 0,
+ (rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value[0][6]
+ == 0));
+ }
+ }
+ }
+ rtlphy->need_iqk = false;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static u32 _rtl92d_phy_get_abs(u32 val1, u32 val2)
+{
+ u32 ret;
+
+ if (val1 >= val2)
+ ret = val1 - val2;
+ else
+ ret = val2 - val1;
+ return ret;
+}
+
+static bool _rtl92d_is_legal_5g_channel(struct ieee80211_hw *hw, u8 channel)
+{
+
+ int i;
+ u8 channel_5g[45] = {
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
+ 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
+ 161, 163, 165
+ };
+
+ for (i = 0; i < sizeof(channel_5g); i++)
+ if (channel == channel_5g[i])
+ return true;
+ return false;
+}
+
+static void _rtl92d_phy_calc_curvindex(struct ieee80211_hw *hw,
+ u32 *targetchnl, u32 * curvecount_val,
+ bool is5g, u32 *curveindex)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 smallest_abs_val = 0xffffffff, u4tmp;
+ u8 i, j;
+ u8 chnl_num = is5g ? TARGET_CHNL_NUM_5G : TARGET_CHNL_NUM_2G;
+
+ for (i = 0; i < chnl_num; i++) {
+ if (is5g && !_rtl92d_is_legal_5g_channel(hw, i + 1))
+ continue;
+ curveindex[i] = 0;
+ for (j = 0; j < (CV_CURVE_CNT * 2); j++) {
+ u4tmp = _rtl92d_phy_get_abs(targetchnl[i],
+ curvecount_val[j]);
+
+ if (u4tmp < smallest_abs_val) {
+ curveindex[i] = j;
+ smallest_abs_val = u4tmp;
+ }
+ }
+ smallest_abs_val = 0xffffffff;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("curveindex[%d] = %x\n", i,
+ curveindex[i]));
+ }
+}
+
+static void _rtl92d_phy_reload_lck_setting(struct ieee80211_hw *hw,
+ u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 erfpath = rtlpriv->rtlhal.current_bandtype ==
+ BAND_ON_5G ? RF90_PATH_A :
+ IS_92D_SINGLEPHY(rtlpriv->rtlhal.version) ?
+ RF90_PATH_B : RF90_PATH_A;
+ u32 u4tmp = 0, u4regvalue = 0;
+ bool bneed_powerdown_radio = false;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("path %d\n", erfpath));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("band type = %d\n",
+ rtlpriv->rtlhal.current_bandtype));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("channel = %d\n", channel));
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {/* Path-A for 5G */
+ u4tmp = curveindex_5g[channel-1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("ver 1 set RF-A, 5G, 0x28 = 0x%ulx !!\n", u4tmp));
+ if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY &&
+ rtlpriv->rtlhal.interfaceindex == 1) {
+ bneed_powerdown_radio =
+ rtl92d_phy_enable_anotherphy(hw, false);
+ rtlpriv->rtlhal.during_mac1init_radioa = true;
+ /* asume no this case */
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_enable_rf_env(hw, erfpath,
+ &u4regvalue);
+ }
+ rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp);
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue);
+ if (rtlpriv->rtlhal.during_mac1init_radioa)
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ } else if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) {
+ u4tmp = curveindex_2g[channel-1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n", u4tmp));
+ if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY &&
+ rtlpriv->rtlhal.interfaceindex == 0) {
+ bneed_powerdown_radio =
+ rtl92d_phy_enable_anotherphy(hw, true);
+ rtlpriv->rtlhal.during_mac0init_radiob = true;
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_enable_rf_env(hw, erfpath,
+ &u4regvalue);
+ }
+ rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n",
+ rtl_get_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800)));
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue);
+ if (rtlpriv->rtlhal.during_mac0init_radiob)
+ rtl92d_phy_powerdown_anotherphy(hw, true);
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_lc_calibrate_sw(struct ieee80211_hw *hw, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ u8 tmpreg, index, rf_mode[2];
+ u8 path = is2t ? 2 : 1;
+ u8 i;
+ u32 u4tmp, offset;
+ u32 curvecount_val[CV_CURVE_CNT * 2] = {0};
+ u16 timeout = 800, timecount = 0;
+
+ /* Check continuous TX and Packet TX */
+ tmpreg = rtl_read_byte(rtlpriv, 0xd03);
+ /* if Deal with contisuous TX case, disable all continuous TX */
+ /* if Deal with Packet TX case, block all queues */
+ if ((tmpreg & 0x70) != 0)
+ rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
+ else
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x0F);
+ for (index = 0; index < path; index++) {
+ /* 1. Read original RF mode */
+ offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1;
+ rf_mode[index] = rtl_read_byte(rtlpriv, offset);
+ /* 2. Set RF mode = standby mode */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_AC,
+ BRFREGOFFSETMASK, 0x010000);
+ if (rtlpci->init_ready) {
+ /* switch CV-curve control by LC-calibration */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7,
+ BIT(17), 0x0);
+ /* 4. Set LC calibration begin */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW,
+ 0x08000, 0x01);
+ }
+ u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, RF_SYN_G6,
+ BRFREGOFFSETMASK);
+ while ((!(u4tmp & BIT(11))) && timecount <= timeout) {
+ mdelay(50);
+ timecount += 50;
+ u4tmp = rtl_get_rfreg(hw, (enum radio_path)index,
+ RF_SYN_G6, BRFREGOFFSETMASK);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("PHY_LCK finish delay for %d ms=2\n", timecount));
+ u4tmp = rtl_get_rfreg(hw, index, RF_SYN_G4, BRFREGOFFSETMASK);
+ if (index == 0 && rtlhal->interfaceindex == 0) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("path-A / 5G LCK\n"));
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("path-B / 2.4G LCK\n"));
+ }
+ memset(&curvecount_val[0], 0, CV_CURVE_CNT * 2);
+ /* Set LC calibration off */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW,
+ 0x08000, 0x0);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("set RF 0x18[15] = 0\n"));
+ /* save Curve-counting number */
+ for (i = 0; i < CV_CURVE_CNT; i++) {
+ u32 readval = 0, readval2 = 0;
+ rtl_set_rfreg(hw, (enum radio_path)index, 0x3F,
+ 0x7f, i);
+
+ rtl_set_rfreg(hw, (enum radio_path)index, 0x4D,
+ BRFREGOFFSETMASK, 0x0);
+ readval = rtl_get_rfreg(hw, (enum radio_path)index,
+ 0x4F, BRFREGOFFSETMASK);
+ curvecount_val[2 * i + 1] = (readval & 0xfffe0) >> 5;
+ /* reg 0x4f [4:0] */
+ /* reg 0x50 [19:10] */
+ readval2 = rtl_get_rfreg(hw, (enum radio_path)index,
+ 0x50, 0xffc00);
+ curvecount_val[2 * i] = (((readval & 0x1F) << 10) |
+ readval2);
+ }
+ if (index == 0 && rtlhal->interfaceindex == 0)
+ _rtl92d_phy_calc_curvindex(hw, targetchnl_5g,
+ curvecount_val,
+ true, curveindex_5g);
+ else
+ _rtl92d_phy_calc_curvindex(hw, targetchnl_2g,
+ curvecount_val,
+ false, curveindex_2g);
+ /* switch CV-curve control mode */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7,
+ BIT(17), 0x1);
+ }
+
+ /* Restore original situation */
+ for (index = 0; index < path; index++) {
+ offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1;
+ rtl_write_byte(rtlpriv, offset, 0x50);
+ rtl_write_byte(rtlpriv, offset, rf_mode[index]);
+ }
+ if ((tmpreg & 0x70) != 0)
+ rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+ else /*Deal with Packet TX case */
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x00);
+ _rtl92d_phy_reload_lck_setting(hw, rtlpriv->phy.current_channel);
+}
+
+static void _rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("cosa PHY_LCK ver=2\n"));
+ _rtl92d_phy_lc_calibrate_sw(hw, is2t);
+}
+
+void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 timeout = 2000, timecount = 0;
+
+ while (rtlpriv->mac80211.act_scanning && timecount < timeout) {
+ udelay(50);
+ timecount += 50;
+ }
+
+ rtlphy->lck_inprogress = true;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("LCK:Start!!! currentband %x delay %d ms\n",
+ rtlhal->current_bandtype, timecount));
+ if (IS_92D_SINGLEPHY(rtlhal->version)) {
+ _rtl92d_phy_lc_calibrate(hw, true);
+ } else {
+ /* For 1T1R */
+ _rtl92d_phy_lc_calibrate(hw, false);
+ }
+ rtlphy->lck_inprogress = false;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LCK:Finish!!!\n"));
+}
+
+void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
+{
+ return;
+}
+
+static bool _rtl92d_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+ u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid,
+ u32 para1, u32 para2, u32 msdelay)
+{
+ struct swchnlcmd *pcmd;
+
+ if (cmdtable == NULL) {
+ RT_ASSERT(false, ("cmdtable cannot be NULL.\n"));
+ return false;
+ }
+ if (cmdtableidx >= cmdtablesz)
+ return false;
+
+ pcmd = cmdtable + cmdtableidx;
+ pcmd->cmdid = cmdid;
+ pcmd->para1 = para1;
+ pcmd->para2 = para2;
+ pcmd->msdelay = msdelay;
+ return true;
+}
+
+void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 i;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("settings regs %d default regs %d\n",
+ (int)(sizeof(rtlphy->iqk_matrix_regsetting) /
+ sizeof(struct iqk_matrix_regs)),
+ IQK_MATRIX_REG_NUM));
+ /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */
+ for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) {
+ rtlphy->iqk_matrix_regsetting[i].value[0][0] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][2] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][4] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][6] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][1] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].value[0][3] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].value[0][5] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].value[0][7] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].iqk_done = false;
+ }
+}
+
+static bool _rtl92d_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
+ u8 channel, u8 *stage, u8 *step,
+ u32 *delay)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
+ u32 precommoncmdcnt;
+ struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
+ u32 postcommoncmdcnt;
+ struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
+ u32 rfdependcmdcnt;
+ struct swchnlcmd *currentcmd = NULL;
+ u8 rfpath;
+ u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
+ precommoncmdcnt = 0;
+ _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+ MAX_PRECMD_CNT,
+ CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
+ _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+ MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+ postcommoncmdcnt = 0;
+ _rtl92d_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
+ MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
+ rfdependcmdcnt = 0;
+ _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+ MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+ RF_CHNLBW, channel, 0);
+ _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+ MAX_RFDEPENDCMD_CNT, CMDID_END,
+ 0, 0, 0);
+
+ do {
+ switch (*stage) {
+ case 0:
+ currentcmd = &precommoncmd[*step];
+ break;
+ case 1:
+ currentcmd = &rfdependcmd[*step];
+ break;
+ case 2:
+ currentcmd = &postcommoncmd[*step];
+ break;
+ }
+ if (currentcmd->cmdid == CMDID_END) {
+ if ((*stage) == 2) {
+ return true;
+ } else {
+ (*stage)++;
+ (*step) = 0;
+ continue;
+ }
+ }
+ switch (currentcmd->cmdid) {
+ case CMDID_SET_TXPOWEROWER_LEVEL:
+ rtl92d_phy_set_txpower_level(hw, channel);
+ break;
+ case CMDID_WRITEPORT_ULONG:
+ rtl_write_dword(rtlpriv, currentcmd->para1,
+ currentcmd->para2);
+ break;
+ case CMDID_WRITEPORT_USHORT:
+ rtl_write_word(rtlpriv, currentcmd->para1,
+ (u16)currentcmd->para2);
+ break;
+ case CMDID_WRITEPORT_UCHAR:
+ rtl_write_byte(rtlpriv, currentcmd->para1,
+ (u8)currentcmd->para2);
+ break;
+ case CMDID_RF_WRITEREG:
+ for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] =
+ ((rtlphy->rfreg_chnlval[rfpath] &
+ 0xffffff00) | currentcmd->para2);
+ if (rtlpriv->rtlhal.current_bandtype ==
+ BAND_ON_5G) {
+ if (currentcmd->para2 > 99)
+ rtlphy->rfreg_chnlval[rfpath] =
+ rtlphy->rfreg_chnlval
+ [rfpath] | (BIT(18));
+ else
+ rtlphy->rfreg_chnlval[rfpath] =
+ rtlphy->rfreg_chnlval
+ [rfpath] & (~BIT(18));
+ rtlphy->rfreg_chnlval[rfpath] |=
+ (BIT(16) | BIT(8));
+ } else {
+ rtlphy->rfreg_chnlval[rfpath] &=
+ ~(BIT(8) | BIT(16) | BIT(18));
+ }
+ rtl_set_rfreg(hw, (enum radio_path)rfpath,
+ currentcmd->para1,
+ BRFREGOFFSETMASK,
+ rtlphy->rfreg_chnlval[rfpath]);
+ _rtl92d_phy_reload_imr_setting(hw, channel,
+ rfpath);
+ }
+ _rtl92d_phy_switch_rf_setting(hw, channel);
+ /* do IQK when all parameters are ready */
+ rtl92d_phy_reload_iqk_setting(hw, channel);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ break;
+ } while (true);
+ (*delay) = currentcmd->msdelay;
+ (*step)++;
+ return false;
+}
+
+u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 delay;
+ u32 timeout = 1000, timecount = 0;
+ u8 channel = rtlphy->current_channel;
+ u32 ret_value;
+
+ if (rtlphy->sw_chnl_inprogress)
+ return 0;
+ if (rtlphy->set_bwmode_inprogress)
+ return 0;
+
+ if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) {
+ RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+ ("sw_chnl_inprogress false driver sleep or unload\n"));
+ return 0;
+ }
+ while (rtlphy->lck_inprogress && timecount < timeout) {
+ mdelay(50);
+ timecount += 50;
+ }
+ if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY &&
+ rtlhal->bandset == BAND_ON_BOTH) {
+ ret_value = rtl_get_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+ BMASKDWORD);
+ if (rtlphy->current_channel > 14 && !(ret_value & BIT(0)))
+ rtl92d_phy_switch_wirelessband(hw, BAND_ON_5G);
+ else if (rtlphy->current_channel <= 14 && (ret_value & BIT(0)))
+ rtl92d_phy_switch_wirelessband(hw, BAND_ON_2_4G);
+ }
+ switch (rtlhal->current_bandtype) {
+ case BAND_ON_5G:
+ /* Get first channel error when change between
+ * 5G and 2.4G band. */
+ if (channel <= 14)
+ return 0;
+ RT_ASSERT((channel > 14), ("5G but channel<=14"));
+ break;
+ case BAND_ON_2_4G:
+ /* Get first channel error when change between
+ * 5G and 2.4G band. */
+ if (channel > 14)
+ return 0;
+ RT_ASSERT((channel <= 14), ("2G but channel>14"));
+ break;
+ default:
+ RT_ASSERT(false,
+ ("Invalid WirelessMode(%#x)!!\n",
+ rtlpriv->mac80211.mode));
+ break;
+ }
+ rtlphy->sw_chnl_inprogress = true;
+ if (channel == 0)
+ channel = 1;
+ rtlphy->sw_chnl_stage = 0;
+ rtlphy->sw_chnl_step = 0;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+ ("switch to channel%d\n", rtlphy->current_channel));
+
+ do {
+ if (!rtlphy->sw_chnl_inprogress)
+ break;
+ if (!_rtl92d_phy_sw_chnl_step_by_step(hw,
+ rtlphy->current_channel,
+ &rtlphy->sw_chnl_stage, &rtlphy->sw_chnl_step, &delay)) {
+ if (delay > 0)
+ mdelay(delay);
+ else
+ continue;
+ } else {
+ rtlphy->sw_chnl_inprogress = false;
+ }
+ break;
+ } while (true);
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+ rtlphy->sw_chnl_inprogress = false;
+ return 1;
+}
+
+static void rtl92d_phy_set_io(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("--->Cmd(%#x), set_io_inprogress(%d)\n",
+ rtlphy->current_io_type, rtlphy->set_io_inprogress));
+ switch (rtlphy->current_io_type) {
+ case IO_CMD_RESUME_DM_BY_SCAN:
+ de_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+ rtl92d_dm_write_dig(hw);
+ rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+ break;
+ case IO_CMD_PAUSE_DM_BY_SCAN:
+ rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue;
+ de_digtable.cur_igvalue = 0x17;
+ rtl92d_dm_write_dig(hw);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ rtlphy->set_io_inprogress = false;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("<---(%#x)\n", rtlphy->current_io_type));
+}
+
+bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ bool postprocessing = false;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("-->IO Cmd(%#x), set_io_inprogress(%d)\n",
+ iotype, rtlphy->set_io_inprogress));
+ do {
+ switch (iotype) {
+ case IO_CMD_RESUME_DM_BY_SCAN:
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("[IO CMD] Resume DM after scan.\n"));
+ postprocessing = true;
+ break;
+ case IO_CMD_PAUSE_DM_BY_SCAN:
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("[IO CMD] Pause DM before scan.\n"));
+ postprocessing = true;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ } while (false);
+ if (postprocessing && !rtlphy->set_io_inprogress) {
+ rtlphy->set_io_inprogress = true;
+ rtlphy->current_io_type = iotype;
+ } else {
+ return false;
+ }
+ rtl92d_phy_set_io(hw);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype));
+ return true;
+}
+
+static void _rtl92d_phy_set_rfon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ /* a. SYS_CLKR 0x08[11] = 1 restore MAC clock */
+ /* b. SPS_CTRL 0x11[7:0] = 0x2b */
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY)
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+ /* c. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ /* RF_ON_EXCEP(d~g): */
+ /* d. APSD_CTRL 0x600[7:0] = 0x00 */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+ /* e. SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function again */
+ /* f. SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function*/
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ /* g. txpause 0x522[7:0] = 0x00 enable mac tx queue */
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+}
+
+static void _rtl92d_phy_set_rfsleep(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 u4btmp;
+ u8 delay = 5;
+
+ /* a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+ /* b. RF path 0 offset 0x00 = 0x00 disable RF */
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+ /* c. APSD_CTRL 0x600[7:0] = 0x40 */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+ /* d. APSD_CTRL 0x600[7:0] = 0x00
+ * APSD_CTRL 0x600[7:0] = 0x00
+ * RF path 0 offset 0x00 = 0x00
+ * APSD_CTRL 0x600[7:0] = 0x40
+ * */
+ u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK);
+ while (u4btmp != 0 && delay > 0) {
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+ u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK);
+ delay--;
+ }
+ if (delay == 0) {
+ /* Jump out the LPS turn off sequence to RF_ON_EXCEP */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("Fail !!! Switch RF timeout.\n"));
+ return;
+ }
+ /* e. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ /* f. SPS_CTRL 0x11[7:0] = 0x22 */
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY)
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+ /* g. SYS_CLKR 0x08[11] = 0 gated MAC clock */
+}
+
+bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state)
+{
+
+ bool bresult = true;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ u8 i, queue_id;
+ struct rtl8192_tx_ring *ring = NULL;
+
+ if (rfpwr_state == ppsc->rfpwr_state)
+ return false;
+ switch (rfpwr_state) {
+ case ERFON:
+ if ((ppsc->rfpwr_state == ERFOFF) &&
+ RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+ bool rtstatus;
+ u32 InitializeCount = 0;
+ do {
+ InitializeCount++;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("IPS Set eRf nic enable\n"));
+ rtstatus = rtl_ps_enable_nic(hw);
+ } while ((rtstatus != true) &&
+ (InitializeCount < 10));
+
+ RT_CLEAR_PS_LEVEL(ppsc,
+ RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+ ("awake, sleeped:%d ms state_"
+ "inap:%x\n",
+ jiffies_to_msecs(jiffies -
+ ppsc->last_sleep_jiffies),
+ rtlpriv->psc.state_inap));
+ ppsc->last_awake_jiffies = jiffies;
+ _rtl92d_phy_set_rfon(hw);
+ }
+
+ if (mac->link_state == MAC80211_LINKED)
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_LINK);
+ else
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_NO_LINK);
+ break;
+ case ERFOFF:
+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("IPS Set eRf nic disable\n"));
+ rtl_ps_disable_nic(hw);
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_NO_LINK);
+ else
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_POWER_OFF);
+ }
+ break;
+ case ERFSLEEP:
+ if (ppsc->rfpwr_state == ERFOFF)
+ break;
+
+ for (queue_id = 0, i = 0;
+ queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+ ring = &pcipriv->dev.tx_ring[queue_id];
+ if (skb_queue_len(&ring->queue) == 0 ||
+ queue_id == BEACON_QUEUE) {
+ queue_id++;
+ continue;
+ } else if (rtlpci->pdev->current_state != PCI_D0) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("eRf Off/Sleep: %d times TcbBusyQueu"
+ "e[%d] !=0 but lower power state!\n",
+ (i + 1), queue_id));
+ break;
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("eRf Off/Sleep: %d times TcbBusyQueu"
+ "e[%d] =%d "
+ "before doze!\n", (i + 1), queue_id,
+ skb_queue_len(&ring->queue)));
+ udelay(10);
+ i++;
+ }
+
+ if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("\nERFOFF: %d times TcbBusyQueue[%d] "
+ "= %d !\n",
+ MAX_DOZE_WAITING_TIMES_9x, queue_id,
+ skb_queue_len(&ring->queue)));
+ break;
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+ ("Set rfsleep awaked:%d ms\n",
+ jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)));
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("sleep awaked:%d ms "
+ "state_inap:%x\n", jiffies_to_msecs(jiffies -
+ ppsc->last_awake_jiffies), rtlpriv->psc.state_inap));
+ ppsc->last_sleep_jiffies = jiffies;
+ _rtl92d_phy_set_rfsleep(hw);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ bresult = false;
+ break;
+ }
+ if (bresult)
+ ppsc->rfpwr_state = rfpwr_state;
+ return bresult;
+}
+
+void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 offset = REG_MAC_PHY_CTRL_NORMAL;
+
+ switch (rtlhal->macphymode) {
+ case DUALMAC_DUALPHY:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode: DUALMAC_DUALPHY\n"));
+ rtl_write_byte(rtlpriv, offset, 0xF3);
+ break;
+ case SINGLEMAC_SINGLEPHY:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode: SINGLEMAC_SINGLEPHY\n"));
+ rtl_write_byte(rtlpriv, offset, 0xF4);
+ break;
+ case DUALMAC_SINGLEPHY:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode: DUALMAC_SINGLEPHY\n"));
+ rtl_write_byte(rtlpriv, offset, 0xF1);
+ break;
+ }
+}
+
+void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ switch (rtlhal->macphymode) {
+ case DUALMAC_SINGLEPHY:
+ rtlphy->rf_type = RF_2T2R;
+ rtlhal->version |= CHIP_92D_SINGLEPHY;
+ rtlhal->bandset = BAND_ON_BOTH;
+ rtlhal->current_bandtype = BAND_ON_2_4G;
+ break;
+
+ case SINGLEMAC_SINGLEPHY:
+ rtlphy->rf_type = RF_2T2R;
+ rtlhal->version |= CHIP_92D_SINGLEPHY;
+ rtlhal->bandset = BAND_ON_BOTH;
+ rtlhal->current_bandtype = BAND_ON_2_4G;
+ break;
+
+ case DUALMAC_DUALPHY:
+ rtlphy->rf_type = RF_1T1R;
+ rtlhal->version &= (~CHIP_92D_SINGLEPHY);
+ /* Now we let MAC0 run on 5G band. */
+ if (rtlhal->interfaceindex == 0) {
+ rtlhal->bandset = BAND_ON_5G;
+ rtlhal->current_bandtype = BAND_ON_5G;
+ } else {
+ rtlhal->bandset = BAND_ON_2_4G;
+ rtlhal->current_bandtype = BAND_ON_2_4G;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+u8 rtl92d_get_chnlgroup_fromarray(u8 chnl)
+{
+ u8 group;
+ u8 channel_info[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
+ 58, 60, 62, 64, 100, 102, 104, 106, 108,
+ 110, 112, 114, 116, 118, 120, 122, 124,
+ 126, 128, 130, 132, 134, 136, 138, 140,
+ 149, 151, 153, 155, 157, 159, 161, 163,
+ 165
+ };
+
+ if (channel_info[chnl] <= 3)
+ group = 0;
+ else if (channel_info[chnl] <= 9)
+ group = 1;
+ else if (channel_info[chnl] <= 14)
+ group = 2;
+ else if (channel_info[chnl] <= 44)
+ group = 3;
+ else if (channel_info[chnl] <= 54)
+ group = 4;
+ else if (channel_info[chnl] <= 64)
+ group = 5;
+ else if (channel_info[chnl] <= 112)
+ group = 6;
+ else if (channel_info[chnl] <= 126)
+ group = 7;
+ else if (channel_info[chnl] <= 140)
+ group = 8;
+ else if (channel_info[chnl] <= 153)
+ group = 9;
+ else if (channel_info[chnl] <= 159)
+ group = 10;
+ else
+ group = 11;
+ return group;
+}
+
+void rtl92d_phy_set_poweron(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ unsigned long flags;
+ u8 value8;
+ u16 i;
+ u32 mac_reg = (rtlhal->interfaceindex == 0 ? REG_MAC0 : REG_MAC1);
+
+ /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ value8 = rtl_read_byte(rtlpriv, mac_reg);
+ value8 |= BIT(1);
+ rtl_write_byte(rtlpriv, mac_reg, value8);
+ } else {
+ value8 = rtl_read_byte(rtlpriv, mac_reg);
+ value8 &= (~BIT(1));
+ rtl_write_byte(rtlpriv, mac_reg, value8);
+ }
+
+ if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) {
+ value8 = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON);
+ } else {
+ spin_lock_irqsave(&globalmutex_power, flags);
+ if (rtlhal->interfaceindex == 0) {
+ value8 = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON);
+ } else {
+ value8 = rtl_read_byte(rtlpriv, REG_MAC1);
+ rtl_write_byte(rtlpriv, REG_MAC1, value8 | MAC1_ON);
+ }
+ value8 = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ for (i = 0; i < 200; i++) {
+ if ((value8 & BIT(7)) == 0) {
+ break;
+ } else {
+ udelay(500);
+ spin_lock_irqsave(&globalmutex_power, flags);
+ value8 = rtl_read_byte(rtlpriv,
+ REG_POWER_OFF_IN_PROCESS);
+ spin_unlock_irqrestore(&globalmutex_power,
+ flags);
+ }
+ }
+ if (i == 200)
+ RT_ASSERT(false, ("Another mac power off over time\n"));
+ }
+}
+
+void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ switch (rtlpriv->rtlhal.macphymode) {
+ case DUALMAC_DUALPHY:
+ rtl_write_byte(rtlpriv, REG_DMC, 0x0);
+ rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08);
+ rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff);
+ break;
+ case DUALMAC_SINGLEPHY:
+ rtl_write_byte(rtlpriv, REG_DMC, 0xf8);
+ rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08);
+ rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff);
+ break;
+ case SINGLEMAC_SINGLEPHY:
+ rtl_write_byte(rtlpriv, REG_DMC, 0x0);
+ rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x10);
+ rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF);
+ break;
+ default:
+ break;
+ }
+}
+
+void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 rfpath, i;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n"));
+ /* r_select_5G for path_A/B 0 for 2.4G, 1 for 5G */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* r_select_5G for path_A/B,0x878 */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x0);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x0);
+ if (rtlhal->macphymode != DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x0);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x0);
+ }
+ /* rssi_table_select:index 0 for 2.4G.1~3 for 5G,0xc78 */
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x0);
+ /* fc_area 0xd2c */
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x0);
+ /* 5G LAN ON */
+ rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa);
+ /* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+ 0x40000100);
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+ 0x40000100);
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) |
+ (rtlefuse->eeprom_c9 & BIT(1)) |
+ ((rtlefuse->eeprom_cc & BIT(1)) << 4));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) |
+ ((rtlefuse->eeprom_c9 & BIT(0)) << 1) |
+ ((rtlefuse->eeprom_cc & BIT(0)) << 5));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0);
+ } else {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(26) | BIT(22) | BIT(21) | BIT(10) |
+ BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) |
+ (rtlefuse->eeprom_c9 & BIT(1)) |
+ ((rtlefuse->eeprom_cc & BIT(1)) << 4) |
+ ((rtlefuse->eeprom_c9 & BIT(7)) << 9) |
+ ((rtlefuse->eeprom_c9 & BIT(5)) << 12) |
+ ((rtlefuse->eeprom_cc & BIT(3)) << 18));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) |
+ ((rtlefuse->eeprom_c9 & BIT(0)) << 1) |
+ ((rtlefuse->eeprom_cc & BIT(0)) << 5));
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(6)) >> 6) |
+ ((rtlefuse->eeprom_c9 & BIT(4)) >> 3) |
+ ((rtlefuse->eeprom_cc & BIT(2)) << 3));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+ BIT(31) | BIT(15), 0);
+ }
+ /* 1.5V_LDO */
+ } else {
+ /* r_select_5G for path_A/B */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x1);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x1);
+ if (rtlhal->macphymode != DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x1);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x1);
+ }
+ /* rssi_table_select:index 0 for 2.4G.1~3 for 5G */
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x1);
+ /* fc_area */
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x1);
+ /* 5G LAN ON */
+ rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0);
+ /* TX BB gain shift,Just for testchip,0xc80,0xc88 */
+ if (rtlefuse->internal_pa_5g[0])
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+ 0x2d4000b5);
+ else
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+ 0x20000080);
+ if (rtlefuse->internal_pa_5g[1])
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+ 0x2d4000b5);
+ else
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+ 0x20000080);
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(10) | BIT(6) | BIT(5),
+ (rtlefuse->eeprom_cc & BIT(5)));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10),
+ ((rtlefuse->eeprom_cc & BIT(4)) >> 4));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15),
+ (rtlefuse->eeprom_cc & BIT(4)) >> 4);
+ } else {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(26) | BIT(22) | BIT(21) | BIT(10) |
+ BIT(6) | BIT(5),
+ (rtlefuse->eeprom_cc & BIT(5)) |
+ ((rtlefuse->eeprom_cc & BIT(7)) << 14));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10),
+ ((rtlefuse->eeprom_cc & BIT(4)) >> 4));
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10),
+ ((rtlefuse->eeprom_cc & BIT(6)) >> 6));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+ BIT(31) | BIT(15),
+ ((rtlefuse->eeprom_cc & BIT(4)) >> 4) |
+ ((rtlefuse->eeprom_cc & BIT(6)) << 10));
+ }
+ }
+ /* update IQK related settings */
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, BMASKDWORD, 0x40000100);
+ rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, BMASKDWORD, 0x40000100);
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) |
+ BIT(26) | BIT(24), 0x00);
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00);
+
+ /* Update RF */
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | BIT(16) |
+ BIT(18), 0);
+ /* RF0x0b[16:14] =3b'111 */
+ rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B,
+ 0x1c000, 0x07);
+ } else {
+ /* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) |
+ BIT(16) | BIT(18),
+ (BIT(16) | BIT(8)) >> 8);
+ }
+ }
+ /* Update for all band. */
+ /* DMDP */
+ if (rtlphy->rf_type == RF_1T1R) {
+ /* Use antenna 0,0xc04,0xd04 */
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x11);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x1);
+
+ /* enable ad/da clock1 for dual-phy reg0x888 */
+ if (rtlhal->interfaceindex == 0) {
+ rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) |
+ BIT(13), 0x3);
+ } else {
+ rtl92d_phy_enable_anotherphy(hw, false);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MAC1 use DBI to update 0x888"));
+ /* 0x888 */
+ rtl92de_write_dword_dbi(hw, RFPGA0_ADDALLOCKEN,
+ rtl92de_read_dword_dbi(hw,
+ RFPGA0_ADDALLOCKEN,
+ BIT(3)) | BIT(12) | BIT(13),
+ BIT(3));
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ }
+ } else {
+ /* Single PHY */
+ /* Use antenna 0 & 1,0xc04,0xd04 */
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x33);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x3);
+ /* disable ad/da clock1,0x888 */
+ rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | BIT(13), 0);
+ }
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] = rtl_get_rfreg(hw, rfpath,
+ RF_CHNLBW, BRFREGOFFSETMASK);
+ rtlphy->reg_rf3c[rfpath] = rtl_get_rfreg(hw, rfpath, 0x3C,
+ BRFREGOFFSETMASK);
+ }
+ for (i = 0; i < 2; i++)
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("RF 0x18 = 0x%x\n",
+ rtlphy->rfreg_chnlval[i]));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==\n"));
+
+}
+
+bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 u1btmp;
+ unsigned long flags;
+
+ if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) {
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON));
+ return true;
+ }
+ spin_lock_irqsave(&globalmutex_power, flags);
+ if (rtlhal->interfaceindex == 0) {
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON));
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC1);
+ u1btmp &= MAC1_ON;
+ } else {
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC1);
+ rtl_write_byte(rtlpriv, REG_MAC1, u1btmp & (~MAC1_ON));
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+ u1btmp &= MAC0_ON;
+ }
+ if (u1btmp) {
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ return false;
+ }
+ u1btmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+ u1btmp |= BIT(7);
+ rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1btmp);
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ return true;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
new file mode 100644
index 000000000000..a52c824b41e3
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
@@ -0,0 +1,178 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_PHY_H__
+#define __RTL92D_PHY_H__
+
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT 16
+#define MAX_POSTCMD_CNT 16
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+#define RT_CANNOT_IO(hw) false
+#define HIGHPOWER_RADIOA_ARRAYLEN 22
+
+#define IQK_ADDA_REG_NUM 16
+#define MAX_TOLERANCE 5
+#define IQK_DELAY_TIME 1
+
+#define APK_BB_REG_NUM 5
+#define APK_AFE_REG_NUM 16
+#define APK_CURVE_REG_NUM 4
+#define PATH_NUM 2
+
+#define LOOP_LIMIT 5
+#define MAX_STALL_TIME 50
+#define ANTENNA_DIVERSITY_VALUE 0x80
+#define MAX_TXPWR_IDX_NMODE_92S 63
+#define RESET_CNT_LIMIT 3
+
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM 10
+#define IQK_BB_REG_NUM_test 6
+#define IQK_MAC_REG_NUM 4
+#define RX_INDEX_MAPPING_NUM 15
+
+#define IQK_DELAY_TIME 1
+
+#define CT_OFFSET_MAC_ADDR 0X16
+
+#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A
+#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60
+#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66
+#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69
+#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C
+
+#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F
+#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72
+
+#define CT_OFFSET_CHANNEL_PLAH 0x75
+#define CT_OFFSET_THERMAL_METER 0x78
+#define CT_OFFSET_RF_OPTION 0x79
+#define CT_OFFSET_VERSION 0x7E
+#define CT_OFFSET_CUSTOMER_ID 0x7F
+
+enum swchnlcmd_id {
+ CMDID_END,
+ CMDID_SET_TXPOWEROWER_LEVEL,
+ CMDID_BBREGWRITE10,
+ CMDID_WRITEPORT_ULONG,
+ CMDID_WRITEPORT_USHORT,
+ CMDID_WRITEPORT_UCHAR,
+ CMDID_RF_WRITEREG,
+};
+
+struct swchnlcmd {
+ enum swchnlcmd_id cmdid;
+ u32 para1;
+ u32 para2;
+ u32 msdelay;
+};
+
+enum baseband_config_type {
+ BASEBAND_CONFIG_PHY_REG = 0,
+ BASEBAND_CONFIG_AGC_TAB = 1,
+};
+
+enum rf_content {
+ radioa_txt = 0,
+ radiob_txt = 1,
+ radioc_txt = 2,
+ radiod_txt = 3
+};
+
+static inline void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->rtlhal.interfaceindex == 1)
+ spin_lock_irqsave(&rtlpriv->locks.cck_and_rw_pagea_lock, *flag);
+}
+
+static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->rtlhal.interfaceindex == 1)
+ spin_unlock_irqrestore(&rtlpriv->locks.cck_and_rw_pagea_lock,
+ *flag);
+}
+
+extern u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask);
+extern void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr,
+ u32 bitmask);
+extern void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr,
+ u32 bitmask, u32 data);
+extern bool rtl92d_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_rf_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+ enum radio_path rfpath);
+extern void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+extern void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw,
+ u8 operation);
+extern void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type);
+extern u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw);
+bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+ enum rf_content content,
+ enum radio_path rfpath);
+bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+extern bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state);
+
+void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw);
+void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw);
+u8 rtl92d_get_chnlgroup_fromarray(u8 chnl);
+void rtl92d_phy_set_poweron(struct ieee80211_hw *hw);
+void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw);
+bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw);
+void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw);
+void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
+void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw);
+void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag);
+void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag);
+u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl);
+void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel);
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
new file mode 100644
index 000000000000..131acc306fcc
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
@@ -0,0 +1,1313 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_REG_H__
+#define __RTL92D_REG_H__
+
+/* ----------------------------------------------------- */
+/* 0x0000h ~ 0x00FFh System Configuration */
+/* ----------------------------------------------------- */
+#define REG_SYS_ISO_CTRL 0x0000
+#define REG_SYS_FUNC_EN 0x0002
+#define REG_APS_FSMCO 0x0004
+#define REG_SYS_CLKR 0x0008
+#define REG_9346CR 0x000A
+#define REG_EE_VPD 0x000C
+#define REG_AFE_MISC 0x0010
+#define REG_SPS0_CTRL 0x0011
+#define REG_POWER_OFF_IN_PROCESS 0x0017
+#define REG_SPS_OCP_CFG 0x0018
+#define REG_RSV_CTRL 0x001C
+#define REG_RF_CTRL 0x001F
+#define REG_LDOA15_CTRL 0x0020
+#define REG_LDOV12D_CTRL 0x0021
+#define REG_LDOHCI12_CTRL 0x0022
+#define REG_LPLDO_CTRL 0x0023
+#define REG_AFE_XTAL_CTRL 0x0024
+#define REG_AFE_PLL_CTRL 0x0028
+/* for 92d, DMDP,SMSP,DMSP contrl */
+#define REG_MAC_PHY_CTRL 0x002c
+#define REG_EFUSE_CTRL 0x0030
+#define REG_EFUSE_TEST 0x0034
+#define REG_PWR_DATA 0x0038
+#define REG_CAL_TIMER 0x003C
+#define REG_ACLK_MON 0x003E
+#define REG_GPIO_MUXCFG 0x0040
+#define REG_GPIO_IO_SEL 0x0042
+#define REG_MAC_PINMUX_CFG 0x0043
+#define REG_GPIO_PIN_CTRL 0x0044
+#define REG_GPIO_INTM 0x0048
+#define REG_LEDCFG0 0x004C
+#define REG_LEDCFG1 0x004D
+#define REG_LEDCFG2 0x004E
+#define REG_LEDCFG3 0x004F
+#define REG_FSIMR 0x0050
+#define REG_FSISR 0x0054
+
+#define REG_MCUFWDL 0x0080
+
+#define REG_HMEBOX_EXT_0 0x0088
+#define REG_HMEBOX_EXT_1 0x008A
+#define REG_HMEBOX_EXT_2 0x008C
+#define REG_HMEBOX_EXT_3 0x008E
+
+#define REG_BIST_SCAN 0x00D0
+#define REG_BIST_RPT 0x00D4
+#define REG_BIST_ROM_RPT 0x00D8
+#define REG_USB_SIE_INTF 0x00E0
+#define REG_PCIE_MIO_INTF 0x00E4
+#define REG_PCIE_MIO_INTD 0x00E8
+#define REG_HPON_FSM 0x00EC
+#define REG_SYS_CFG 0x00F0
+#define REG_MAC_PHY_CTRL_NORMAL 0x00f8
+
+#define REG_MAC0 0x0081
+#define REG_MAC1 0x0053
+#define FW_MAC0_READY 0x18
+#define FW_MAC1_READY 0x1A
+#define MAC0_ON BIT(7)
+#define MAC1_ON BIT(0)
+#define MAC0_READY BIT(0)
+#define MAC1_READY BIT(0)
+
+/* ----------------------------------------------------- */
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+/* ----------------------------------------------------- */
+#define REG_CR 0x0100
+#define REG_PBP 0x0104
+#define REG_TRXDMA_CTRL 0x010C
+#define REG_TRXFF_BNDY 0x0114
+#define REG_TRXFF_STATUS 0x0118
+#define REG_RXFF_PTR 0x011C
+#define REG_HIMR 0x0120
+#define REG_HISR 0x0124
+#define REG_HIMRE 0x0128
+#define REG_HISRE 0x012C
+#define REG_CPWM 0x012F
+#define REG_FWIMR 0x0130
+#define REG_FWISR 0x0134
+#define REG_PKTBUF_DBG_CTRL 0x0140
+#define REG_PKTBUF_DBG_DATA_L 0x0144
+#define REG_PKTBUF_DBG_DATA_H 0x0148
+
+#define REG_TC0_CTRL 0x0150
+#define REG_TC1_CTRL 0x0154
+#define REG_TC2_CTRL 0x0158
+#define REG_TC3_CTRL 0x015C
+#define REG_TC4_CTRL 0x0160
+#define REG_TCUNIT_BASE 0x0164
+#define REG_MBIST_START 0x0174
+#define REG_MBIST_DONE 0x0178
+#define REG_MBIST_FAIL 0x017C
+#define REG_C2HEVT_MSG_NORMAL 0x01A0
+#define REG_C2HEVT_MSG_TEST 0x01B8
+#define REG_C2HEVT_CLEAR 0x01BF
+#define REG_MCUTST_1 0x01c0
+#define REG_FMETHR 0x01C8
+#define REG_HMETFR 0x01CC
+#define REG_HMEBOX_0 0x01D0
+#define REG_HMEBOX_1 0x01D4
+#define REG_HMEBOX_2 0x01D8
+#define REG_HMEBOX_3 0x01DC
+
+#define REG_LLT_INIT 0x01E0
+#define REG_BB_ACCEESS_CTRL 0x01E8
+#define REG_BB_ACCESS_DATA 0x01EC
+
+
+/* ----------------------------------------------------- */
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* ----------------------------------------------------- */
+#define REG_RQPN 0x0200
+#define REG_FIFOPAGE 0x0204
+#define REG_TDECTRL 0x0208
+#define REG_TXDMA_OFFSET_CHK 0x020C
+#define REG_TXDMA_STATUS 0x0210
+#define REG_RQPN_NPQ 0x0214
+
+/* ----------------------------------------------------- */
+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
+/* ----------------------------------------------------- */
+#define REG_RXDMA_AGG_PG_TH 0x0280
+#define REG_RXPKT_NUM 0x0284
+#define REG_RXDMA_STATUS 0x0288
+
+/* ----------------------------------------------------- */
+/* 0x0300h ~ 0x03FFh PCIe */
+/* ----------------------------------------------------- */
+#define REG_PCIE_CTRL_REG 0x0300
+#define REG_INT_MIG 0x0304
+#define REG_BCNQ_DESA 0x0308
+#define REG_HQ_DESA 0x0310
+#define REG_MGQ_DESA 0x0318
+#define REG_VOQ_DESA 0x0320
+#define REG_VIQ_DESA 0x0328
+#define REG_BEQ_DESA 0x0330
+#define REG_BKQ_DESA 0x0338
+#define REG_RX_DESA 0x0340
+#define REG_DBI 0x0348
+#define REG_DBI_WDATA 0x0348
+#define REG_DBI_RDATA 0x034C
+#define REG_DBI_CTRL 0x0350
+#define REG_DBI_FLAG 0x0352
+#define REG_MDIO 0x0354
+#define REG_DBG_SEL 0x0360
+#define REG_PCIE_HRPWM 0x0361
+#define REG_PCIE_HCPWM 0x0363
+#define REG_UART_CTRL 0x0364
+#define REG_UART_TX_DESA 0x0370
+#define REG_UART_RX_DESA 0x0378
+
+/* ----------------------------------------------------- */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* ----------------------------------------------------- */
+#define REG_VOQ_INFORMATION 0x0400
+#define REG_VIQ_INFORMATION 0x0404
+#define REG_BEQ_INFORMATION 0x0408
+#define REG_BKQ_INFORMATION 0x040C
+#define REG_MGQ_INFORMATION 0x0410
+#define REG_HGQ_INFORMATION 0x0414
+#define REG_BCNQ_INFORMATION 0x0418
+
+
+#define REG_CPU_MGQ_INFORMATION 0x041C
+#define REG_FWHW_TXQ_CTRL 0x0420
+#define REG_HWSEQ_CTRL 0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
+#define REG_TXPKTBUF_MGQ_BDNY 0x0425
+#define REG_MULTI_BCNQ_EN 0x0426
+#define REG_MULTI_BCNQ_OFFSET 0x0427
+#define REG_SPEC_SIFS 0x0428
+#define REG_RL 0x042A
+#define REG_DARFRC 0x0430
+#define REG_RARFRC 0x0438
+#define REG_RRSR 0x0440
+#define REG_ARFR0 0x0444
+#define REG_ARFR1 0x0448
+#define REG_ARFR2 0x044C
+#define REG_ARFR3 0x0450
+#define REG_AGGLEN_LMT 0x0458
+#define REG_AMPDU_MIN_SPACE 0x045C
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D
+#define REG_FAST_EDCA_CTRL 0x0460
+#define REG_RD_RESP_PKT_TH 0x0463
+#define REG_INIRTS_RATE_SEL 0x0480
+#define REG_INIDATA_RATE_SEL 0x0484
+#define REG_POWER_STATUS 0x04A4
+#define REG_POWER_STAGE1 0x04B4
+#define REG_POWER_STAGE2 0x04B8
+#define REG_PKT_LIFE_TIME 0x04C0
+#define REG_STBC_SETTING 0x04C4
+#define REG_PROT_MODE_CTRL 0x04C8
+#define REG_MAX_AGGR_NUM 0x04CA
+#define REG_RTS_MAX_AGGR_NUM 0x04CB
+#define REG_BAR_MODE_CTRL 0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT 0x04CF
+#define REG_EARLY_MODE_CONTROL 0x4D0
+#define REG_NQOS_SEQ 0x04DC
+#define REG_QOS_SEQ 0x04DE
+#define REG_NEED_CPU_HANDLE 0x04E0
+#define REG_PKT_LOSE_RPT 0x04E1
+#define REG_PTCL_ERR_STATUS 0x04E2
+#define REG_DUMMY 0x04FC
+
+/* ----------------------------------------------------- */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* ----------------------------------------------------- */
+#define REG_EDCA_VO_PARAM 0x0500
+#define REG_EDCA_VI_PARAM 0x0504
+#define REG_EDCA_BE_PARAM 0x0508
+#define REG_EDCA_BK_PARAM 0x050C
+#define REG_BCNTCFG 0x0510
+#define REG_PIFS 0x0512
+#define REG_RDG_PIFS 0x0513
+#define REG_SIFS_CTX 0x0514
+#define REG_SIFS_TRX 0x0516
+#define REG_AGGR_BREAK_TIME 0x051A
+#define REG_SLOT 0x051B
+#define REG_TX_PTCL_CTRL 0x0520
+#define REG_TXPAUSE 0x0522
+#define REG_DIS_TXREQ_CLR 0x0523
+#define REG_RD_CTRL 0x0524
+#define REG_TBTT_PROHIBIT 0x0540
+#define REG_RD_NAV_NXT 0x0544
+#define REG_NAV_PROT_LEN 0x0546
+#define REG_BCN_CTRL 0x0550
+#define REG_USTIME_TSF 0x0551
+#define REG_MBID_NUM 0x0552
+#define REG_DUAL_TSF_RST 0x0553
+#define REG_BCN_INTERVAL 0x0554
+#define REG_MBSSID_BCN_SPACE 0x0554
+#define REG_DRVERLYINT 0x0558
+#define REG_BCNDMATIM 0x0559
+#define REG_ATIMWND 0x055A
+#define REG_BCN_MAX_ERR 0x055D
+#define REG_RXTSF_OFFSET_CCK 0x055E
+#define REG_RXTSF_OFFSET_OFDM 0x055F
+#define REG_TSFTR 0x0560
+#define REG_INIT_TSFTR 0x0564
+#define REG_PSTIMER 0x0580
+#define REG_TIMER0 0x0584
+#define REG_TIMER1 0x0588
+#define REG_ACMHWCTRL 0x05C0
+#define REG_ACMRSTCTRL 0x05C1
+#define REG_ACMAVG 0x05C2
+#define REG_VO_ADMTIME 0x05C4
+#define REG_VI_ADMTIME 0x05C6
+#define REG_BE_ADMTIME 0x05C8
+#define REG_EDCA_RANDOM_GEN 0x05CC
+#define REG_SCH_TXCMD 0x05D0
+
+/* Dual MAC Co-Existence Register */
+#define REG_DMC 0x05F0
+
+/* ----------------------------------------------------- */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* ----------------------------------------------------- */
+#define REG_APSD_CTRL 0x0600
+#define REG_BWOPMODE 0x0603
+#define REG_TCR 0x0604
+#define REG_RCR 0x0608
+#define REG_RX_PKT_LIMIT 0x060C
+#define REG_RX_DLK_TIME 0x060D
+#define REG_RX_DRVINFO_SZ 0x060F
+
+#define REG_MACID 0x0610
+#define REG_BSSID 0x0618
+#define REG_MAR 0x0620
+#define REG_MBIDCAMCFG 0x0628
+
+#define REG_USTIME_EDCA 0x0638
+#define REG_MAC_SPEC_SIFS 0x063A
+#define REG_RESP_SIFS_CCK 0x063C
+#define REG_RESP_SIFS_OFDM 0x063E
+#define REG_ACKTO 0x0640
+#define REG_CTS2TO 0x0641
+#define REG_EIFS 0x0642
+
+
+/* WMA, BA, CCX */
+#define REG_NAV_CTRL 0x0650
+#define REG_BACAMCMD 0x0654
+#define REG_BACAMCONTENT 0x0658
+#define REG_LBDLY 0x0660
+#define REG_FWDLY 0x0661
+#define REG_RXERR_RPT 0x0664
+#define REG_WMAC_TRXPTCL_CTL 0x0668
+
+
+/* Security */
+#define REG_CAMCMD 0x0670
+#define REG_CAMWRITE 0x0674
+#define REG_CAMREAD 0x0678
+#define REG_CAMDBG 0x067C
+#define REG_SECCFG 0x0680
+
+/* Power */
+#define REG_WOW_CTRL 0x0690
+#define REG_PSSTATUS 0x0691
+#define REG_PS_RX_INFO 0x0692
+#define REG_LPNAV_CTRL 0x0694
+#define REG_WKFMCAM_CMD 0x0698
+#define REG_WKFMCAM_RWD 0x069C
+#define REG_RXFLTMAP0 0x06A0
+#define REG_RXFLTMAP1 0x06A2
+#define REG_RXFLTMAP2 0x06A4
+#define REG_BCN_PSR_RPT 0x06A8
+#define REG_CALB32K_CTRL 0x06AC
+#define REG_PKT_MON_CTRL 0x06B4
+#define REG_BT_COEX_TABLE 0x06C0
+#define REG_WMAC_RESP_TXINFO 0x06D8
+
+
+/* ----------------------------------------------------- */
+/* Redifine 8192C register definition for compatibility */
+/* ----------------------------------------------------- */
+#define CR9346 REG_9346CR
+#define MSR (REG_CR + 2)
+#define ISR REG_HISR
+#define TSFR REG_TSFTR
+
+#define MACIDR0 REG_MACID
+#define MACIDR4 (REG_MACID + 4)
+
+#define PBP REG_PBP
+
+#define IDR0 MACIDR0
+#define IDR4 MACIDR4
+
+/* ----------------------------------------------------- */
+/* 8192C (MSR) Media Status Register(Offset 0x4C, 8 bits)*/
+/* ----------------------------------------------------- */
+#define MSR_NOLINK 0x00
+#define MSR_ADHOC 0x01
+#define MSR_INFRA 0x02
+#define MSR_AP 0x03
+
+/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */
+/* ----------------------------------------------------- */
+/* 8192C Response Rate Set Register(offset 0x181, 24bits)*/
+/* ----------------------------------------------------- */
+#define RRSR_RSC_OFFSET 21
+#define RRSR_SHORT_OFFSET 23
+#define RRSR_RSC_BW_40M 0x600000
+#define RRSR_RSC_UPSUBCHNL 0x400000
+#define RRSR_RSC_LOWSUBCHNL 0x200000
+#define RRSR_SHORT 0x800000
+#define RRSR_1M BIT0
+#define RRSR_2M BIT1
+#define RRSR_5_5M BIT2
+#define RRSR_11M BIT3
+#define RRSR_6M BIT4
+#define RRSR_9M BIT5
+#define RRSR_12M BIT6
+#define RRSR_18M BIT7
+#define RRSR_24M BIT8
+#define RRSR_36M BIT9
+#define RRSR_48M BIT10
+#define RRSR_54M BIT11
+#define RRSR_MCS0 BIT12
+#define RRSR_MCS1 BIT13
+#define RRSR_MCS2 BIT14
+#define RRSR_MCS3 BIT15
+#define RRSR_MCS4 BIT16
+#define RRSR_MCS5 BIT17
+#define RRSR_MCS6 BIT18
+#define RRSR_MCS7 BIT19
+#define BRSR_ACKSHORTPMB BIT23
+
+/* ----------------------------------------------------- */
+/* 8192C Rate Definition */
+/* ----------------------------------------------------- */
+/* CCK */
+#define RATR_1M 0x00000001
+#define RATR_2M 0x00000002
+#define RATR_55M 0x00000004
+#define RATR_11M 0x00000008
+/* OFDM */
+#define RATR_6M 0x00000010
+#define RATR_9M 0x00000020
+#define RATR_12M 0x00000040
+#define RATR_18M 0x00000080
+#define RATR_24M 0x00000100
+#define RATR_36M 0x00000200
+#define RATR_48M 0x00000400
+#define RATR_54M 0x00000800
+/* MCS 1 Spatial Stream */
+#define RATR_MCS0 0x00001000
+#define RATR_MCS1 0x00002000
+#define RATR_MCS2 0x00004000
+#define RATR_MCS3 0x00008000
+#define RATR_MCS4 0x00010000
+#define RATR_MCS5 0x00020000
+#define RATR_MCS6 0x00040000
+#define RATR_MCS7 0x00080000
+/* MCS 2 Spatial Stream */
+#define RATR_MCS8 0x00100000
+#define RATR_MCS9 0x00200000
+#define RATR_MCS10 0x00400000
+#define RATR_MCS11 0x00800000
+#define RATR_MCS12 0x01000000
+#define RATR_MCS13 0x02000000
+#define RATR_MCS14 0x04000000
+#define RATR_MCS15 0x08000000
+
+/* CCK */
+#define RATE_1M BIT(0)
+#define RATE_2M BIT(1)
+#define RATE_5_5M BIT(2)
+#define RATE_11M BIT(3)
+/* OFDM */
+#define RATE_6M BIT(4)
+#define RATE_9M BIT(5)
+#define RATE_12M BIT(6)
+#define RATE_18M BIT(7)
+#define RATE_24M BIT(8)
+#define RATE_36M BIT(9)
+#define RATE_48M BIT(10)
+#define RATE_54M BIT(11)
+/* MCS 1 Spatial Stream */
+#define RATE_MCS0 BIT(12)
+#define RATE_MCS1 BIT(13)
+#define RATE_MCS2 BIT(14)
+#define RATE_MCS3 BIT(15)
+#define RATE_MCS4 BIT(16)
+#define RATE_MCS5 BIT(17)
+#define RATE_MCS6 BIT(18)
+#define RATE_MCS7 BIT(19)
+/* MCS 2 Spatial Stream */
+#define RATE_MCS8 BIT(20)
+#define RATE_MCS9 BIT(21)
+#define RATE_MCS10 BIT(22)
+#define RATE_MCS11 BIT(23)
+#define RATE_MCS12 BIT(24)
+#define RATE_MCS13 BIT(25)
+#define RATE_MCS14 BIT(26)
+#define RATE_MCS15 BIT(27)
+
+/* ALL CCK Rate */
+#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | \
+ RATR_11M)
+#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | \
+ RATR_18M | RATR_24M | \
+ RATR_36M | RATR_48M | RATR_54M)
+#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \
+ RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \
+ RATR_MCS6 | RATR_MCS7)
+#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \
+ RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \
+ RATR_MCS14 | RATR_MCS15)
+
+/* ----------------------------------------------------- */
+/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */
+/* ----------------------------------------------------- */
+#define BW_OPMODE_20MHZ BIT(2)
+#define BW_OPMODE_5G BIT(1)
+#define BW_OPMODE_11J BIT(0)
+
+
+/* ----------------------------------------------------- */
+/* 8192C CAM Config Setting (offset 0x250, 1 byte) */
+/* ----------------------------------------------------- */
+#define CAM_VALID BIT(15)
+#define CAM_NOTVALID 0x0000
+#define CAM_USEDK BIT(5)
+
+#define CAM_NONE 0x0
+#define CAM_WEP40 0x01
+#define CAM_TKIP 0x02
+#define CAM_AES 0x04
+#define CAM_WEP104 0x05
+#define CAM_SMS4 0x6
+
+
+#define TOTAL_CAM_ENTRY 32
+#define HALF_CAM_ENTRY 16
+
+#define CAM_WRITE BIT(16)
+#define CAM_READ 0x00000000
+#define CAM_POLLINIG BIT(31)
+
+/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */
+#define WOW_PMEN BIT0 /* Power management Enable. */
+#define WOW_WOMEN BIT1 /* WoW function on or off. */
+#define WOW_MAGIC BIT2 /* Magic packet */
+#define WOW_UWF BIT3 /* Unicast Wakeup frame. */
+
+/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */
+/* ----------------------------------------------------- */
+/* 8190 IMR/ISR bits (offset 0xfd, 8bits) */
+/* ----------------------------------------------------- */
+#define IMR8190_DISABLED 0x0
+#define IMR_BCNDMAINT6 BIT(31)
+#define IMR_BCNDMAINT5 BIT(30)
+#define IMR_BCNDMAINT4 BIT(29)
+#define IMR_BCNDMAINT3 BIT(28)
+#define IMR_BCNDMAINT2 BIT(27)
+#define IMR_BCNDMAINT1 BIT(26)
+#define IMR_BCNDOK8 BIT(25)
+#define IMR_BCNDOK7 BIT(24)
+#define IMR_BCNDOK6 BIT(23)
+#define IMR_BCNDOK5 BIT(22)
+#define IMR_BCNDOK4 BIT(21)
+#define IMR_BCNDOK3 BIT(20)
+#define IMR_BCNDOK2 BIT(19)
+#define IMR_BCNDOK1 BIT(18)
+#define IMR_TIMEOUT2 BIT(17)
+#define IMR_TIMEOUT1 BIT(16)
+#define IMR_TXFOVW BIT(15)
+#define IMR_PSTIMEOUT BIT(14)
+#define IMR_BcnInt BIT(13)
+#define IMR_RXFOVW BIT(12)
+#define IMR_RDU BIT(11)
+#define IMR_ATIMEND BIT(10)
+#define IMR_BDOK BIT(9)
+#define IMR_HIGHDOK BIT(8)
+#define IMR_TBDOK BIT(7)
+#define IMR_MGNTDOK BIT(6)
+#define IMR_TBDER BIT(5)
+#define IMR_BKDOK BIT(4)
+#define IMR_BEDOK BIT(3)
+#define IMR_VIDOK BIT(2)
+#define IMR_VODOK BIT(1)
+#define IMR_ROK BIT(0)
+
+#define IMR_TXERR BIT(11)
+#define IMR_RXERR BIT(10)
+#define IMR_C2HCMD BIT(9)
+#define IMR_CPWM BIT(8)
+#define IMR_OCPINT BIT(1)
+#define IMR_WLANOFF BIT(0)
+
+/* ----------------------------------------------------- */
+/* 8192C EFUSE */
+/* ----------------------------------------------------- */
+#define HWSET_MAX_SIZE 256
+#define EFUSE_MAX_SECTION 32
+#define EFUSE_REAL_CONTENT_LEN 512
+
+/* ----------------------------------------------------- */
+/* 8192C EEPROM/EFUSE share register definition. */
+/* ----------------------------------------------------- */
+#define EEPROM_DEFAULT_TSSI 0x0
+#define EEPROM_DEFAULT_CRYSTALCAP 0x0
+#define EEPROM_DEFAULT_THERMALMETER 0x12
+
+#define EEPROM_DEFAULT_TXPOWERLEVEL_2G 0x2C
+#define EEPROM_DEFAULT_TXPOWERLEVEL_5G 0x22
+
+#define EEPROM_DEFAULT_HT40_2SDIFF 0x0
+/* HT20<->40 default Tx Power Index Difference */
+#define EEPROM_DEFAULT_HT20_DIFF 2
+/* OFDM Tx Power index diff */
+#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x4
+#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0
+#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0
+
+#define EEPROM_CHANNEL_PLAN_FCC 0x0
+#define EEPROM_CHANNEL_PLAN_IC 0x1
+#define EEPROM_CHANNEL_PLAN_ETSI 0x2
+#define EEPROM_CHANNEL_PLAN_SPAIN 0x3
+#define EEPROM_CHANNEL_PLAN_FRANCE 0x4
+#define EEPROM_CHANNEL_PLAN_MKK 0x5
+#define EEPROM_CHANNEL_PLAN_MKK1 0x6
+#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7
+#define EEPROM_CHANNEL_PLAN_TELEC 0x8
+#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9
+#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA
+#define EEPROM_CHANNEL_PLAN_NCC 0xB
+#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
+
+#define EEPROM_CID_DEFAULT 0x0
+#define EEPROM_CID_TOSHIBA 0x4
+#define EEPROM_CID_CCX 0x10
+#define EEPROM_CID_QMI 0x0D
+#define EEPROM_CID_WHQL 0xFE
+
+
+#define RTL8192_EEPROM_ID 0x8129
+#define EEPROM_WAPI_SUPPORT 0x78
+
+
+#define RTL8190_EEPROM_ID 0x8129 /* 0-1 */
+#define EEPROM_HPON 0x02 /* LDO settings.2-5 */
+#define EEPROM_CLK 0x06 /* Clock settings.6-7 */
+#define EEPROM_MAC_FUNCTION 0x08 /* SE Test mode.8 */
+
+#define EEPROM_VID 0x28 /* SE Vendor ID.A-B */
+#define EEPROM_DID 0x2A /* SE Device ID. C-D */
+#define EEPROM_SVID 0x2C /* SE Vendor ID.E-F */
+#define EEPROM_SMID 0x2E /* SE PCI Subsystem ID. 10-11 */
+
+#define EEPROM_MAC_ADDR 0x16 /* SEMAC Address. 12-17 */
+#define EEPROM_MAC_ADDR_MAC0_92D 0x55
+#define EEPROM_MAC_ADDR_MAC1_92D 0x5B
+
+/* 2.4G band Tx power index setting */
+#define EEPROM_CCK_TX_PWR_INX_2G 0x61
+#define EEPROM_HT40_1S_TX_PWR_INX_2G 0x67
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G 0x6D
+#define EEPROM_HT20_TX_PWR_INX_DIFF_2G 0x70
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_2G 0x73
+#define EEPROM_HT40_MAX_PWR_OFFSET_2G 0x76
+#define EEPROM_HT20_MAX_PWR_OFFSET_2G 0x79
+
+/*5GL channel 32-64 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GL 0x7C
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GL 0x82
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GL 0x85
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GL 0x88
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GL 0x8B
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GL 0x8E
+
+/* 5GM channel 100-140 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GM 0x91
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GM 0x97
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GM 0x9A
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GM 0x9D
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GM 0xA0
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GM 0xA3
+
+/* 5GH channel 149-165 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GH 0xA6
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GH 0xAC
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GH 0xAF
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GH 0xB2
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GH 0xB5
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GH 0xB8
+
+/* Map of supported channels. */
+#define EEPROM_CHANNEL_PLAN 0xBB
+#define EEPROM_IQK_DELTA 0xBC
+#define EEPROM_LCK_DELTA 0xBC
+#define EEPROM_XTAL_K 0xBD /* [7:5] */
+#define EEPROM_TSSI_A_5G 0xBE
+#define EEPROM_TSSI_B_5G 0xBF
+#define EEPROM_TSSI_AB_5G 0xC0
+#define EEPROM_THERMAL_METER 0xC3 /* [4:0] */
+#define EEPROM_RF_OPT1 0xC4
+#define EEPROM_RF_OPT2 0xC5
+#define EEPROM_RF_OPT3 0xC6
+#define EEPROM_RF_OPT4 0xC7
+#define EEPROM_RF_OPT5 0xC8
+#define EEPROM_RF_OPT6 0xC9
+#define EEPROM_VERSION 0xCA
+#define EEPROM_CUSTOMER_ID 0xCB
+#define EEPROM_RF_OPT7 0xCC
+
+#define EEPROM_DEF_PART_NO 0x3FD /* Byte */
+#define EEPROME_CHIP_VERSION_L 0x3FF
+#define EEPROME_CHIP_VERSION_H 0x3FE
+
+/*
+ * Current IOREG MAP
+ * 0x0000h ~ 0x00FFh System Configuration (256 Bytes)
+ * 0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes)
+ * 0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes)
+ * 0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes)
+ * 0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes)
+ * 0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes)
+ * 0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes)
+ * 0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes)
+ * 0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes)
+ */
+
+/* ----------------------------------------------------- */
+/* 8192C (RCR) (Offset 0x608, 32 bits) */
+/* ----------------------------------------------------- */
+#define RCR_APPFCS BIT(31)
+#define RCR_APP_MIC BIT(30)
+#define RCR_APP_ICV BIT(29)
+#define RCR_APP_PHYST_RXFF BIT(28)
+#define RCR_APP_BA_SSN BIT(27)
+#define RCR_ENMBID BIT(24)
+#define RCR_LSIGEN BIT(23)
+#define RCR_MFBEN BIT(22)
+#define RCR_HTC_LOC_CTRL BIT(14)
+#define RCR_AMF BIT(13)
+#define RCR_ACF BIT(12)
+#define RCR_ADF BIT(11)
+#define RCR_AICV BIT(9)
+#define RCR_ACRC32 BIT(8)
+#define RCR_CBSSID_BCN BIT(7)
+#define RCR_CBSSID_DATA BIT(6)
+#define RCR_APWRMGT BIT(5)
+#define RCR_ADD3 BIT(4)
+#define RCR_AB BIT(3)
+#define RCR_AM BIT(2)
+#define RCR_APM BIT(1)
+#define RCR_AAP BIT(0)
+#define RCR_MXDMA_OFFSET 8
+#define RCR_FIFO_OFFSET 13
+
+/* ----------------------------------------------------- */
+/* 8192C Regsiter Bit and Content definition */
+/* ----------------------------------------------------- */
+/* ----------------------------------------------------- */
+/* 0x0000h ~ 0x00FFh System Configuration */
+/* ----------------------------------------------------- */
+
+/* SPS0_CTRL */
+#define SW18_FPWM BIT(3)
+
+
+/* SYS_ISO_CTRL */
+#define ISO_MD2PP BIT(0)
+#define ISO_UA2USB BIT(1)
+#define ISO_UD2CORE BIT(2)
+#define ISO_PA2PCIE BIT(3)
+#define ISO_PD2CORE BIT(4)
+#define ISO_IP2MAC BIT(5)
+#define ISO_DIOP BIT(6)
+#define ISO_DIOE BIT(7)
+#define ISO_EB2CORE BIT(8)
+#define ISO_DIOR BIT(9)
+
+#define PWC_EV25V BIT(14)
+#define PWC_EV12V BIT(15)
+
+
+/* SYS_FUNC_EN */
+#define FEN_BBRSTB BIT(0)
+#define FEN_BB_GLB_RSTn BIT(1)
+#define FEN_USBA BIT(2)
+#define FEN_UPLL BIT(3)
+#define FEN_USBD BIT(4)
+#define FEN_DIO_PCIE BIT(5)
+#define FEN_PCIEA BIT(6)
+#define FEN_PPLL BIT(7)
+#define FEN_PCIED BIT(8)
+#define FEN_DIOE BIT(9)
+#define FEN_CPUEN BIT(10)
+#define FEN_DCORE BIT(11)
+#define FEN_ELDR BIT(12)
+#define FEN_DIO_RF BIT(13)
+#define FEN_HWPDN BIT(14)
+#define FEN_MREGEN BIT(15)
+
+/* APS_FSMCO */
+#define PFM_LDALL BIT(0)
+#define PFM_ALDN BIT(1)
+#define PFM_LDKP BIT(2)
+#define PFM_WOWL BIT(3)
+#define EnPDN BIT(4)
+#define PDN_PL BIT(5)
+#define APFM_ONMAC BIT(8)
+#define APFM_OFF BIT(9)
+#define APFM_RSM BIT(10)
+#define AFSM_HSUS BIT(11)
+#define AFSM_PCIE BIT(12)
+#define APDM_MAC BIT(13)
+#define APDM_HOST BIT(14)
+#define APDM_HPDN BIT(15)
+#define RDY_MACON BIT(16)
+#define SUS_HOST BIT(17)
+#define ROP_ALD BIT(20)
+#define ROP_PWR BIT(21)
+#define ROP_SPS BIT(22)
+#define SOP_MRST BIT(25)
+#define SOP_FUSE BIT(26)
+#define SOP_ABG BIT(27)
+#define SOP_AMB BIT(28)
+#define SOP_RCK BIT(29)
+#define SOP_A8M BIT(30)
+#define XOP_BTCK BIT(31)
+
+/* SYS_CLKR */
+#define ANAD16V_EN BIT(0)
+#define ANA8M BIT(1)
+#define MACSLP BIT(4)
+#define LOADER_CLK_EN BIT(5)
+#define _80M_SSC_DIS BIT(7)
+#define _80M_SSC_EN_HO BIT(8)
+#define PHY_SSC_RSTB BIT(9)
+#define SEC_CLK_EN BIT(10)
+#define MAC_CLK_EN BIT(11)
+#define SYS_CLK_EN BIT(12)
+#define RING_CLK_EN BIT(13)
+
+
+/* 9346CR */
+#define BOOT_FROM_EEPROM BIT(4)
+#define EEPROM_EN BIT(5)
+
+/* AFE_MISC */
+#define AFE_BGEN BIT(0)
+#define AFE_MBEN BIT(1)
+#define MAC_ID_EN BIT(7)
+
+/* RSV_CTRL */
+#define WLOCK_ALL BIT(0)
+#define WLOCK_00 BIT(1)
+#define WLOCK_04 BIT(2)
+#define WLOCK_08 BIT(3)
+#define WLOCK_40 BIT(4)
+#define R_DIS_PRST_0 BIT(5)
+#define R_DIS_PRST_1 BIT(6)
+#define LOCK_ALL_EN BIT(7)
+
+/* RF_CTRL */
+#define RF_EN BIT(0)
+#define RF_RSTB BIT(1)
+#define RF_SDMRSTB BIT(2)
+
+
+
+/* LDOA15_CTRL */
+#define LDA15_EN BIT(0)
+#define LDA15_STBY BIT(1)
+#define LDA15_OBUF BIT(2)
+#define LDA15_REG_VOS BIT(3)
+#define _LDA15_VOADJ(x) (((x) & 0x7) << 4)
+
+
+
+/* LDOV12D_CTRL */
+#define LDV12_EN BIT(0)
+#define LDV12_SDBY BIT(1)
+#define LPLDO_HSM BIT(2)
+#define LPLDO_LSM_DIS BIT(3)
+#define _LDV12_VADJ(x) (((x) & 0xF) << 4)
+
+
+/* AFE_XTAL_CTRL */
+#define XTAL_EN BIT(0)
+#define XTAL_BSEL BIT(1)
+#define _XTAL_BOSC(x) (((x) & 0x3) << 2)
+#define _XTAL_CADJ(x) (((x) & 0xF) << 4)
+#define XTAL_GATE_USB BIT(8)
+#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9)
+#define XTAL_GATE_AFE BIT(11)
+#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12)
+#define XTAL_RF_GATE BIT(14)
+#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15)
+#define XTAL_GATE_DIG BIT(17)
+#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18)
+#define XTAL_BT_GATE BIT(20)
+#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21)
+#define _XTAL_GPIO(x) (((x) & 0x7) << 23)
+
+
+#define CKDLY_AFE BIT(26)
+#define CKDLY_USB BIT(27)
+#define CKDLY_DIG BIT(28)
+#define CKDLY_BT BIT(29)
+
+
+/* AFE_PLL_CTRL */
+#define APLL_EN BIT(0)
+#define APLL_320_EN BIT(1)
+#define APLL_FREF_SEL BIT(2)
+#define APLL_EDGE_SEL BIT(3)
+#define APLL_WDOGB BIT(4)
+#define APLL_LPFEN BIT(5)
+
+#define APLL_REF_CLK_13MHZ 0x1
+#define APLL_REF_CLK_19_2MHZ 0x2
+#define APLL_REF_CLK_20MHZ 0x3
+#define APLL_REF_CLK_25MHZ 0x4
+#define APLL_REF_CLK_26MHZ 0x5
+#define APLL_REF_CLK_38_4MHZ 0x6
+#define APLL_REF_CLK_40MHZ 0x7
+
+#define APLL_320EN BIT(14)
+#define APLL_80EN BIT(15)
+#define APLL_1MEN BIT(24)
+
+
+/* EFUSE_CTRL */
+#define ALD_EN BIT(18)
+#define EF_PD BIT(19)
+#define EF_FLAG BIT(31)
+
+/* EFUSE_TEST */
+#define EF_TRPT BIT(7)
+#define LDOE25_EN BIT(31)
+
+/* MCUFWDL */
+#define MCUFWDL_EN BIT(0)
+#define MCUFWDL_RDY BIT(1)
+#define FWDL_ChkSum_rpt BIT(2)
+#define MACINI_RDY BIT(3)
+#define BBINI_RDY BIT(4)
+#define RFINI_RDY BIT(5)
+#define WINTINI_RDY BIT(6)
+#define MAC1_WINTINI_RDY BIT(11)
+#define CPRST BIT(23)
+
+/* REG_SYS_CFG */
+#define XCLK_VLD BIT(0)
+#define ACLK_VLD BIT(1)
+#define UCLK_VLD BIT(2)
+#define PCLK_VLD BIT(3)
+#define PCIRSTB BIT(4)
+#define V15_VLD BIT(5)
+#define TRP_B15V_EN BIT(7)
+#define SIC_IDLE BIT(8)
+#define BD_MAC2 BIT(9)
+#define BD_MAC1 BIT(10)
+#define IC_MACPHY_MODE BIT(11)
+#define PAD_HWPD_IDN BIT(22)
+#define TRP_VAUX_EN BIT(23)
+#define TRP_BT_EN BIT(24)
+#define BD_PKG_SEL BIT(25)
+#define BD_HCI_SEL BIT(26)
+#define TYPE_ID BIT(27)
+
+/* LLT_INIT */
+#define _LLT_NO_ACTIVE 0x0
+#define _LLT_WRITE_ACCESS 0x1
+#define _LLT_READ_ACCESS 0x2
+
+#define _LLT_INIT_DATA(x) ((x) & 0xFF)
+#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8)
+#define _LLT_OP(x) (((x) & 0x3) << 30)
+#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
+
+
+/* ----------------------------------------------------- */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* ----------------------------------------------------- */
+#define RETRY_LIMIT_SHORT_SHIFT 8
+#define RETRY_LIMIT_LONG_SHIFT 0
+
+
+/* ----------------------------------------------------- */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* ----------------------------------------------------- */
+/* EDCA setting */
+#define AC_PARAM_TXOP_LIMIT_OFFSET 16
+#define AC_PARAM_ECW_MAX_OFFSET 12
+#define AC_PARAM_ECW_MIN_OFFSET 8
+#define AC_PARAM_AIFS_OFFSET 0
+
+/* ACMHWCTRL */
+#define ACMHW_HWEN BIT(0)
+#define ACMHW_BEQEN BIT(1)
+#define ACMHW_VIQEN BIT(2)
+#define ACMHW_VOQEN BIT(3)
+
+/* ----------------------------------------------------- */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* ----------------------------------------------------- */
+
+/* TCR */
+#define TSFRST BIT(0)
+#define DIS_GCLK BIT(1)
+#define PAD_SEL BIT(2)
+#define PWR_ST BIT(6)
+#define PWRBIT_OW_EN BIT(7)
+#define ACRC BIT(8)
+#define CFENDFORM BIT(9)
+#define ICV BIT(10)
+
+/* SECCFG */
+#define SCR_TXUSEDK BIT(0)
+#define SCR_RXUSEDK BIT(1)
+#define SCR_TXENCENABLE BIT(2)
+#define SCR_RXENCENABLE BIT(3)
+#define SCR_SKBYA2 BIT(4)
+#define SCR_NOSKMC BIT(5)
+#define SCR_TXBCUSEDK BIT(6)
+#define SCR_RXBCUSEDK BIT(7)
+
+/* General definitions */
+#define MAC_ADDR_LEN 6
+#define LAST_ENTRY_OF_TX_PKT_BUFFER 255
+#define LAST_ENTRY_OF_TX_PKT_BUFFER_DUAL_MAC 127
+
+#define POLLING_LLT_THRESHOLD 20
+#define POLLING_READY_TIMEOUT_COUNT 1000
+
+/* Min Spacing related settings. */
+#define MAX_MSS_DENSITY_2T 0x13
+#define MAX_MSS_DENSITY_1T 0x0A
+
+
+/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */
+/* 1. PMAC duplicate register due to connection: */
+/* RF_Mode, TRxRN, NumOf L-STF */
+/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
+/* 3. RF register 0x00-2E */
+/* 4. Bit Mask for BB/RF register */
+/* 5. Other defintion for BB/RF R/W */
+
+/* 3. Page8(0x800) */
+#define RFPGA0_RFMOD 0x800
+
+#define RFPGA0_TXINFO 0x804
+#define RFPGA0_PSDFUNCTION 0x808
+
+#define RFPGA0_TXGAINSTAGE 0x80c
+
+#define RFPGA0_RFTIMING1 0x810
+#define RFPGA0_RFTIMING2 0x814
+
+#define RFPGA0_XA_HSSIPARAMETER1 0x820
+#define RFPGA0_XA_HSSIPARAMETER2 0x824
+#define RFPGA0_XB_HSSIPARAMETER1 0x828
+#define RFPGA0_XB_HSSIPARAMETER2 0x82c
+
+#define RFPGA0_XA_LSSIPARAMETER 0x840
+#define RFPGA0_XB_LSSIPARAMETER 0x844
+
+#define RFPGA0_RFWAkEUPPARAMETER 0x850
+#define RFPGA0_RFSLEEPUPPARAMETER 0x854
+
+#define RFPGA0_XAB_SWITCHCONTROL 0x858
+#define RFPGA0_XCD_SWITCHCONTROL 0x85c
+
+#define RFPGA0_XA_RFINTERFACEOE 0x860
+#define RFPGA0_XB_RFINTERFACEOE 0x864
+
+#define RFPGA0_XAB_RFINTERFACESW 0x870
+#define RFPGA0_XCD_RFINTERFACESW 0x874
+
+#define RFPGA0_XAB_RFPARAMETER 0x878
+#define RFPGA0_XCD_RFPARAMETER 0x87c
+
+#define RFPGA0_ANALOGPARAMETER1 0x880
+#define RFPGA0_ANALOGPARAMETER2 0x884
+#define RFPGA0_ANALOGPARAMETER3 0x888
+#define RFPGA0_ADDALLOCKEN 0x888
+#define RFPGA0_ANALOGPARAMETER4 0x88c
+
+#define RFPGA0_XA_LSSIREADBACK 0x8a0
+#define RFPGA0_XB_LSSIREADBACK 0x8a4
+#define RFPGA0_XC_LSSIREADBACK 0x8a8
+#define RFPGA0_XD_LSSIREADBACK 0x8ac
+
+#define RFPGA0_PSDREPORT 0x8b4
+#define TRANSCEIVERA_HSPI_READBACK 0x8b8
+#define TRANSCEIVERB_HSPI_READBACK 0x8bc
+#define RFPGA0_XAB_RFINTERFACERB 0x8e0
+#define RFPGA0_XCD_RFINTERFACERB 0x8e4
+
+/* 4. Page9(0x900) */
+#define RFPGA1_RFMOD 0x900
+
+#define RFPGA1_TXBLOCK 0x904
+#define RFPGA1_DEBUGSELECT 0x908
+#define RFPGA1_TXINFO 0x90c
+
+/* 5. PageA(0xA00) */
+#define RCCK0_SYSTEM 0xa00
+
+#define RCCK0_AFESSTTING 0xa04
+#define RCCK0_CCA 0xa08
+
+#define RCCK0_RXAGC1 0xa0c
+#define RCCK0_RXAGC2 0xa10
+
+#define RCCK0_RXHP 0xa14
+
+#define RCCK0_DSPPARAMETER1 0xa18
+#define RCCK0_DSPPARAMETER2 0xa1c
+
+#define RCCK0_TXFILTER1 0xa20
+#define RCCK0_TXFILTER2 0xa24
+#define RCCK0_DEBUGPORT 0xa28
+#define RCCK0_FALSEALARMREPORT 0xa2c
+#define RCCK0_TRSSIREPORT 0xa50
+#define RCCK0_RXREPORT 0xa54
+#define RCCK0_FACOUNTERLOWER 0xa5c
+#define RCCK0_FACOUNTERUPPER 0xa58
+
+/* 6. PageC(0xC00) */
+#define ROFDM0_LSTF 0xc00
+
+#define ROFDM0_TRXPATHENABLE 0xc04
+#define ROFDM0_TRMUXPAR 0xc08
+#define ROFDM0_TRSWISOLATION 0xc0c
+
+#define ROFDM0_XARXAFE 0xc10
+#define ROFDM0_XARXIQIMBALANCE 0xc14
+#define ROFDM0_XBRXAFE 0xc18
+#define ROFDM0_XBRXIQIMBALANCE 0xc1c
+#define ROFDM0_XCRXAFE 0xc20
+#define ROFDM0_XCRXIQIMBALANCE 0xc24
+#define ROFDM0_XDRXAFE 0xc28
+#define ROFDM0_XDRXIQIMBALANCE 0xc2c
+
+#define ROFDM0_RXDETECTOR1 0xc30
+#define ROFDM0_RXDETECTOR2 0xc34
+#define ROFDM0_RXDETECTOR3 0xc38
+#define ROFDM0_RXDETECTOR4 0xc3c
+
+#define ROFDM0_RXDSP 0xc40
+#define ROFDM0_CFOANDDAGC 0xc44
+#define ROFDM0_CCADROPTHRESHOLD 0xc48
+#define ROFDM0_ECCATHRESHOLD 0xc4c
+
+#define ROFDM0_XAAGCCORE1 0xc50
+#define ROFDM0_XAAGCCORE2 0xc54
+#define ROFDM0_XBAGCCORE1 0xc58
+#define ROFDM0_XBAGCCORE2 0xc5c
+#define ROFDM0_XCAGCCORE1 0xc60
+#define ROFDM0_XCAGCCORE2 0xc64
+#define ROFDM0_XDAGCCORE1 0xc68
+#define ROFDM0_XDAGCCORE2 0xc6c
+
+#define ROFDM0_AGCPARAMETER1 0xc70
+#define ROFDM0_AGCPARAMETER2 0xc74
+#define ROFDM0_AGCRSSITABLE 0xc78
+#define ROFDM0_HTSTFAGC 0xc7c
+
+#define ROFDM0_XATxIQIMBALANCE 0xc80
+#define ROFDM0_XATxAFE 0xc84
+#define ROFDM0_XBTxIQIMBALANCE 0xc88
+#define ROFDM0_XBTxAFE 0xc8c
+#define ROFDM0_XCTxIQIMBALANCE 0xc90
+#define ROFDM0_XCTxAFE 0xc94
+#define ROFDM0_XDTxIQIMBALANCE 0xc98
+#define ROFDM0_XDTxAFE 0xc9c
+
+#define ROFDM0_RXHPPARAMETER 0xce0
+#define ROFDM0_TXPSEUDONOISEWGT 0xce4
+#define ROFDM0_FRAMESYNC 0xcf0
+#define ROFDM0_DFSREPORT 0xcf4
+#define ROFDM0_TXCOEFF1 0xca4
+#define ROFDM0_TXCOEFF2 0xca8
+#define ROFDM0_TXCOEFF3 0xcac
+#define ROFDM0_TXCOEFF4 0xcb0
+#define ROFDM0_TXCOEFF5 0xcb4
+#define ROFDM0_TXCOEFF6 0xcb8
+
+/* 7. PageD(0xD00) */
+#define ROFDM1_LSTF 0xd00
+#define ROFDM1_TRXPATHENABLE 0xd04
+
+#define ROFDM1_CFO 0xd08
+#define ROFDM1_CSI1 0xd10
+#define ROFDM1_SBD 0xd14
+#define ROFDM1_CSI2 0xd18
+#define ROFDM1_CFOTRACKING 0xd2c
+#define ROFDM1_TRXMESAURE1 0xd34
+#define ROFDM1_INTFDET 0xd3c
+#define ROFDM1_PSEUDONOISESTATEAB 0xd50
+#define ROFDM1_PSEUDONOISESTATECD 0xd54
+#define ROFDM1_RXPSEUDONOISEWGT 0xd58
+
+#define ROFDM_PHYCOUNTER1 0xda0
+#define ROFDM_PHYCOUNTER2 0xda4
+#define ROFDM_PHYCOUNTER3 0xda8
+
+#define ROFDM_SHORTCFOAB 0xdac
+#define ROFDM_SHORTCFOCD 0xdb0
+#define ROFDM_LONGCFOAB 0xdb4
+#define ROFDM_LONGCFOCD 0xdb8
+#define ROFDM_TAILCFOAB 0xdbc
+#define ROFDM_TAILCFOCD 0xdc0
+#define ROFDM_PWMEASURE1 0xdc4
+#define ROFDM_PWMEASURE2 0xdc8
+#define ROFDM_BWREPORT 0xdcc
+#define ROFDM_AGCREPORT 0xdd0
+#define ROFDM_RXSNR 0xdd4
+#define ROFDM_RXEVMCSI 0xdd8
+#define ROFDM_SIGReport 0xddc
+
+/* 8. PageE(0xE00) */
+#define RTXAGC_A_RATE18_06 0xe00
+#define RTXAGC_A_RATE54_24 0xe04
+#define RTXAGC_A_CCK1_MCS32 0xe08
+#define RTXAGC_A_MCS03_MCS00 0xe10
+#define RTXAGC_A_MCS07_MCS04 0xe14
+#define RTXAGC_A_MCS11_MCS08 0xe18
+#define RTXAGC_A_MCS15_MCS12 0xe1c
+
+#define RTXAGC_B_RATE18_06 0x830
+#define RTXAGC_B_RATE54_24 0x834
+#define RTXAGC_B_CCK1_55_MCS32 0x838
+#define RTXAGC_B_MCS03_MCS00 0x83c
+#define RTXAGC_B_MCS07_MCS04 0x848
+#define RTXAGC_B_MCS11_MCS08 0x84c
+#define RTXAGC_B_MCS15_MCS12 0x868
+#define RTXAGC_B_CCK11_A_CCK2_11 0x86c
+
+/* RL6052 Register definition */
+#define RF_AC 0x00
+
+#define RF_IQADJ_G1 0x01
+#define RF_IQADJ_G2 0x02
+#define RF_POW_TRSW 0x05
+
+#define RF_GAIN_RX 0x06
+#define RF_GAIN_TX 0x07
+
+#define RF_TXM_IDAC 0x08
+#define RF_BS_IQGEN 0x0F
+
+#define RF_MODE1 0x10
+#define RF_MODE2 0x11
+
+#define RF_RX_AGC_HP 0x12
+#define RF_TX_AGC 0x13
+#define RF_BIAS 0x14
+#define RF_IPA 0x15
+#define RF_POW_ABILITY 0x17
+#define RF_MODE_AG 0x18
+#define rRfChannel 0x18
+#define RF_CHNLBW 0x18
+#define RF_TOP 0x19
+
+#define RF_RX_G1 0x1A
+#define RF_RX_G2 0x1B
+
+#define RF_RX_BB2 0x1C
+#define RF_RX_BB1 0x1D
+
+#define RF_RCK1 0x1E
+#define RF_RCK2 0x1F
+
+#define RF_TX_G1 0x20
+#define RF_TX_G2 0x21
+#define RF_TX_G3 0x22
+
+#define RF_TX_BB1 0x23
+
+#define RF_T_METER 0x42
+
+#define RF_SYN_G1 0x25
+#define RF_SYN_G2 0x26
+#define RF_SYN_G3 0x27
+#define RF_SYN_G4 0x28
+#define RF_SYN_G5 0x29
+#define RF_SYN_G6 0x2A
+#define RF_SYN_G7 0x2B
+#define RF_SYN_G8 0x2C
+
+#define RF_RCK_OS 0x30
+
+#define RF_TXPA_G1 0x31
+#define RF_TXPA_G2 0x32
+#define RF_TXPA_G3 0x33
+
+/* Bit Mask */
+
+/* 2. Page8(0x800) */
+#define BRFMOD 0x1
+#define BCCKTXSC 0x30
+#define BCCKEN 0x1000000
+#define BOFDMEN 0x2000000
+
+#define B3WIREDATALENGTH 0x800
+#define B3WIREADDRESSLENGTH 0x400
+
+#define BRFSI_RFENV 0x10
+
+#define BLSSIREADADDRESS 0x7f800000
+#define BLSSIREADEDGE 0x80000000
+#define BLSSIREADBACKDATA 0xfffff
+/* 4. PageA(0xA00) */
+#define BCCKSIDEBAND 0x10
+
+/* Other Definition */
+#define BBYTE0 0x1
+#define BBYTE1 0x2
+#define BBYTE2 0x4
+#define BBYTE3 0x8
+#define BWORD0 0x3
+#define BWORD1 0xc
+#define BDWORD 0xf
+
+#define BMASKBYTE0 0xff
+#define BMASKBYTE1 0xff00
+#define BMASKBYTE2 0xff0000
+#define BMASKBYTE3 0xff000000
+#define BMASKHWORD 0xffff0000
+#define BMASKLWORD 0x0000ffff
+#define BMASKDWORD 0xffffffff
+#define BMASK12BITS 0xfff
+#define BMASKH4BITS 0xf0000000
+#define BMASKOFDM_D 0xffc00000
+#define BMASKCCK 0x3f3f3f3f
+
+#define BRFREGOFFSETMASK 0xfffff
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
new file mode 100644
index 000000000000..db27cebaac2c
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
@@ -0,0 +1,628 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "hw.h"
+
+void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 rfpath;
+
+ switch (bandwidth) {
+ case HT_CHANNEL_WIDTH_20:
+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] = ((rtlphy->rfreg_chnlval
+ [rfpath] & 0xfffff3ff) | 0x0400);
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) |
+ BIT(11), 0x01);
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+ ("20M RF 0x18 = 0x%x\n",
+ rtlphy->rfreg_chnlval[rfpath]));
+ }
+
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] =
+ ((rtlphy->rfreg_chnlval[rfpath] & 0xfffff3ff));
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | BIT(11),
+ 0x00);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+ ("40M RF 0x18 = 0x%x\n",
+ rtlphy->rfreg_chnlval[rfpath]));
+ }
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("unknown bandwidth: %#X\n", bandwidth));
+ break;
+ }
+}
+
+void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u32 tx_agc[2] = {0, 0}, tmpval;
+ bool turbo_scanoff = false;
+ u8 idx1, idx2;
+ u8 *ptr;
+
+ if (rtlefuse->eeprom_regulatory != 0)
+ turbo_scanoff = true;
+ if (mac->act_scanning) {
+ tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
+ tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
+ if (turbo_scanoff) {
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ tx_agc[idx1] = ppowerlevel[idx1] |
+ (ppowerlevel[idx1] << 8) |
+ (ppowerlevel[idx1] << 16) |
+ (ppowerlevel[idx1] << 24);
+ }
+ }
+ } else {
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ tx_agc[idx1] = ppowerlevel[idx1] |
+ (ppowerlevel[idx1] << 8) |
+ (ppowerlevel[idx1] << 16) |
+ (ppowerlevel[idx1] << 24);
+ }
+ if (rtlefuse->eeprom_regulatory == 0) {
+ tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
+ (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8);
+ tx_agc[RF90_PATH_A] += tmpval;
+ tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
+ (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24);
+ tx_agc[RF90_PATH_B] += tmpval;
+ }
+ }
+
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ ptr = (u8 *) (&(tx_agc[idx1]));
+ for (idx2 = 0; idx2 < 4; idx2++) {
+ if (*ptr > RF6052_MAX_TX_PWR)
+ *ptr = RF6052_MAX_TX_PWR;
+ ptr++;
+ }
+ }
+
+ tmpval = tx_agc[RF90_PATH_A] & 0xff;
+ rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, BMASKBYTE1, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_A_CCK1_MCS32));
+ tmpval = tx_agc[RF90_PATH_A] >> 8;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK11_A_CCK2_11));
+ tmpval = tx_agc[RF90_PATH_B] >> 24;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, BMASKBYTE0, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK11_A_CCK2_11));
+ tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK1_55_MCS32));
+}
+
+static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel,
+ u32 *ofdmbase, u32 *mcsbase)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u32 powerbase0, powerbase1;
+ u8 legacy_pwrdiff, ht20_pwrdiff;
+ u8 i, powerlevel[2];
+
+ for (i = 0; i < 2; i++) {
+ powerlevel[i] = ppowerlevel[i];
+ legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
+ powerbase0 = powerlevel[i] + legacy_pwrdiff;
+ powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
+ (powerbase0 << 8) | powerbase0;
+ *(ofdmbase + i) = powerbase0;
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ (" [OFDM power base index rf(%c) = 0x%x]\n",
+ ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)));
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
+ ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
+ powerlevel[i] += ht20_pwrdiff;
+ }
+ powerbase1 = powerlevel[i];
+ powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) |
+ (powerbase1 << 8) | powerbase1;
+ *(mcsbase + i) = powerbase1;
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ (" [MCS power base index rf(%c) = 0x%x]\n",
+ ((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
+ }
+}
+
+static u8 _rtl92d_phy_get_chnlgroup_bypg(u8 chnlindex)
+{
+ u8 group;
+ u8 channel_info[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
+ 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
+ 161, 163, 165
+ };
+
+ if (channel_info[chnlindex] <= 3) /* Chanel 1-3 */
+ group = 0;
+ else if (channel_info[chnlindex] <= 9) /* Channel 4-9 */
+ group = 1;
+ else if (channel_info[chnlindex] <= 14) /* Channel 10-14 */
+ group = 2;
+ else if (channel_info[chnlindex] <= 64)
+ group = 6;
+ else if (channel_info[chnlindex] <= 140)
+ group = 7;
+ else
+ group = 8;
+ return group;
+}
+
+static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
+ u8 channel, u8 index,
+ u32 *powerbase0,
+ u32 *powerbase1,
+ u32 *p_outwriteval)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 i, chnlgroup = 0, pwr_diff_limit[4];
+ u32 writeval = 0, customer_limit, rf;
+
+ for (rf = 0; rf < 2; rf++) {
+ switch (rtlefuse->eeprom_regulatory) {
+ case 0:
+ chnlgroup = 0;
+ writeval = rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index +
+ (rf ? 8 : 0)] + ((index < 2) ?
+ powerbase0[rf] :
+ powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better "
+ "performance, writeval(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ case 1:
+ if (rtlphy->pwrgroup_cnt == 1)
+ chnlgroup = 0;
+ if (rtlphy->pwrgroup_cnt >= MAX_PG_GROUP) {
+ chnlgroup = _rtl92d_phy_get_chnlgroup_bypg(
+ channel - 1);
+ if (rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20)
+ chnlgroup++;
+ else
+ chnlgroup += 4;
+ writeval = rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index +
+ (rf ? 8 : 0)] + ((index < 2) ?
+ powerbase0[rf] :
+ powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Realtek regulatory, "
+ "20MHz, writeval(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'),
+ writeval));
+ }
+ break;
+ case 2:
+ writeval = ((index < 2) ? powerbase0[rf] :
+ powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("Better regulatory, "
+ "writeval(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ case 3:
+ chnlgroup = 0;
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("customer's limit, 40MHz rf(%c) = "
+ "0x%x\n", ((rf == 0) ? 'A' : 'B'),
+ rtlefuse->pwrgroup_ht40[rf]
+ [channel - 1]));
+ } else {
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("customer's limit, 20MHz rf(%c) = "
+ "0x%x\n", ((rf == 0) ? 'A' : 'B'),
+ rtlefuse->pwrgroup_ht20[rf]
+ [channel - 1]));
+ }
+ for (i = 0; i < 4; i++) {
+ pwr_diff_limit[i] =
+ (u8)((rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index + (rf ? 8 : 0)] &
+ (0x7f << (i * 8))) >> (i * 8));
+ if (rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20_40) {
+ if (pwr_diff_limit[i] >
+ rtlefuse->pwrgroup_ht40[rf]
+ [channel - 1])
+ pwr_diff_limit[i] =
+ rtlefuse->pwrgroup_ht40
+ [rf][channel - 1];
+ } else {
+ if (pwr_diff_limit[i] >
+ rtlefuse->pwrgroup_ht20[rf][
+ channel - 1])
+ pwr_diff_limit[i] =
+ rtlefuse->pwrgroup_ht20[rf]
+ [channel - 1];
+ }
+ }
+ customer_limit = (pwr_diff_limit[3] << 24) |
+ (pwr_diff_limit[2] << 16) |
+ (pwr_diff_limit[1] << 8) |
+ (pwr_diff_limit[0]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Customer's limit rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), customer_limit));
+ writeval = customer_limit + ((index < 2) ?
+ powerbase0[rf] : powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Customer, writeval rf(%c)= 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ default:
+ chnlgroup = 0;
+ writeval = rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index +
+ (rf ? 8 : 0)] + ((index < 2) ?
+ powerbase0[rf] : powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("RTK better performance, writeval "
+ "rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ }
+ *(p_outwriteval + rf) = writeval;
+ }
+}
+
+static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw,
+ u8 index, u32 *pvalue)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ static u16 regoffset_a[6] = {
+ RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
+ RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
+ RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
+ };
+ static u16 regoffset_b[6] = {
+ RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
+ RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
+ RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
+ };
+ u8 i, rf, pwr_val[4];
+ u32 writeval;
+ u16 regoffset;
+
+ for (rf = 0; rf < 2; rf++) {
+ writeval = pvalue[rf];
+ for (i = 0; i < 4; i++) {
+ pwr_val[i] = (u8) ((writeval & (0x7f <<
+ (i * 8))) >> (i * 8));
+ if (pwr_val[i] > RF6052_MAX_TX_PWR)
+ pwr_val[i] = RF6052_MAX_TX_PWR;
+ }
+ writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+ (pwr_val[1] << 8) | pwr_val[0];
+ if (rf == 0)
+ regoffset = regoffset_a[index];
+ else
+ regoffset = regoffset_b[index];
+ rtl_set_bbreg(hw, regoffset, BMASKDWORD, writeval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Set 0x%x = %08x\n", regoffset, writeval));
+ if (((get_rf_type(rtlphy) == RF_2T2R) &&
+ (regoffset == RTXAGC_A_MCS15_MCS12 ||
+ regoffset == RTXAGC_B_MCS15_MCS12)) ||
+ ((get_rf_type(rtlphy) != RF_2T2R) &&
+ (regoffset == RTXAGC_A_MCS07_MCS04 ||
+ regoffset == RTXAGC_B_MCS07_MCS04))) {
+ writeval = pwr_val[3];
+ if (regoffset == RTXAGC_A_MCS15_MCS12 ||
+ regoffset == RTXAGC_A_MCS07_MCS04)
+ regoffset = 0xc90;
+ if (regoffset == RTXAGC_B_MCS15_MCS12 ||
+ regoffset == RTXAGC_B_MCS07_MCS04)
+ regoffset = 0xc98;
+ for (i = 0; i < 3; i++) {
+ if (i != 2)
+ writeval = (writeval > 8) ?
+ (writeval - 8) : 0;
+ else
+ writeval = (writeval > 6) ?
+ (writeval - 6) : 0;
+ rtl_write_byte(rtlpriv, (u32) (regoffset + i),
+ (u8) writeval);
+ }
+ }
+ }
+}
+
+void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel)
+{
+ u32 writeval[2], powerbase0[2], powerbase1[2];
+ u8 index;
+
+ _rtl92d_phy_get_power_base(hw, ppowerlevel, channel,
+ &powerbase0[0], &powerbase1[0]);
+ for (index = 0; index < 6; index++) {
+ _rtl92d_get_txpower_writeval_by_regulatory(hw,
+ channel, index, &powerbase0[0],
+ &powerbase1[0], &writeval[0]);
+ _rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]);
+ }
+}
+
+bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 u1btmp;
+ u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3);
+ u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0;
+ u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON;
+ bool bresult = true; /* true: need to enable BB/RF power */
+
+ rtlhal->during_mac0init_radiob = false;
+ rtlhal->during_mac1init_radioa = false;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("===>\n"));
+ /* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */
+ u1btmp = rtl_read_byte(rtlpriv, mac_reg);
+ if (!(u1btmp & mac_on_bit)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("enable BB & RF\n"));
+ /* Enable BB and RF power */
+ rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL,
+ rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) |
+ BIT(29) | BIT(16) | BIT(17), direct);
+ } else {
+ /* We think if MAC1 is ON,then radio_a.txt
+ * and radio_b.txt has been load. */
+ bresult = false;
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<===\n"));
+ return bresult;
+
+}
+
+void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 u1btmp;
+ u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3);
+ u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0;
+ u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON;
+
+ rtlhal->during_mac0init_radiob = false;
+ rtlhal->during_mac1init_radioa = false;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n"));
+ /* check MAC0 enable or not again now, if
+ * enabled, not power down radio A. */
+ u1btmp = rtl_read_byte(rtlpriv, mac_reg);
+ if (!(u1btmp & mac_on_bit)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("power down\n"));
+ /* power down RF radio A according to YuNan's advice. */
+ rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER,
+ 0x00000000, direct);
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n"));
+}
+
+bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ bool rtstatus = true;
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 u4_regvalue = 0;
+ u8 rfpath;
+ struct bb_reg_def *pphyreg;
+ bool mac1_initradioa_first = false, mac0_initradiob_first = false;
+ bool need_pwrdown_radioa = false, need_pwrdown_radiob = false;
+ bool true_bpath = false;
+
+ if (rtlphy->rf_type == RF_1T1R)
+ rtlphy->num_total_rfpath = 1;
+ else
+ rtlphy->num_total_rfpath = 2;
+
+ /* Single phy mode: use radio_a radio_b config path_A path_B */
+ /* seperately by MAC0, and MAC1 needn't configure RF; */
+ /* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */
+ /* MAC1 use radio_b config 2nd PHY path_A. */
+ /* DMDP,MAC0 on G band,MAC1 on A band. */
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G &&
+ rtlhal->interfaceindex == 0) {
+ /* MAC0 needs PHY1 load radio_b.txt.
+ * Driver use DBI to write. */
+ if (rtl92d_phy_enable_anotherphy(hw, true)) {
+ rtlphy->num_total_rfpath = 2;
+ mac0_initradiob_first = true;
+ } else {
+ /* We think if MAC1 is ON,then radio_a.txt and
+ * radio_b.txt has been load. */
+ return rtstatus;
+ }
+ } else if (rtlhal->current_bandtype == BAND_ON_5G &&
+ rtlhal->interfaceindex == 1) {
+ /* MAC1 needs PHY0 load radio_a.txt.
+ * Driver use DBI to write. */
+ if (rtl92d_phy_enable_anotherphy(hw, false)) {
+ rtlphy->num_total_rfpath = 2;
+ mac1_initradioa_first = true;
+ } else {
+ /* We think if MAC0 is ON,then radio_a.txt and
+ * radio_b.txt has been load. */
+ return rtstatus;
+ }
+ } else if (rtlhal->interfaceindex == 1) {
+ /* MAC0 enabled, only init radia B. */
+ true_bpath = true;
+ }
+ }
+
+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+ /* Mac1 use PHY0 write */
+ if (mac1_initradioa_first) {
+ if (rfpath == RF90_PATH_A) {
+ rtlhal->during_mac1init_radioa = true;
+ need_pwrdown_radioa = true;
+ } else if (rfpath == RF90_PATH_B) {
+ rtlhal->during_mac1init_radioa = false;
+ mac1_initradioa_first = false;
+ rfpath = RF90_PATH_A;
+ true_bpath = true;
+ rtlphy->num_total_rfpath = 1;
+ }
+ } else if (mac0_initradiob_first) {
+ /* Mac0 use PHY1 write */
+ if (rfpath == RF90_PATH_A)
+ rtlhal->during_mac0init_radiob = false;
+ if (rfpath == RF90_PATH_B) {
+ rtlhal->during_mac0init_radiob = true;
+ mac0_initradiob_first = false;
+ need_pwrdown_radiob = true;
+ rfpath = RF90_PATH_A;
+ true_bpath = true;
+ rtlphy->num_total_rfpath = 1;
+ }
+ }
+ pphyreg = &rtlphy->phyreg_def[rfpath];
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV << 16);
+ break;
+ }
+ rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+ udelay(1);
+ rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+ udelay(1);
+ /* Set bit number of Address and Data for RF register */
+ /* Set 1 to 4 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
+ B3WIREADDRESSLENGTH, 0x0);
+ udelay(1);
+ /* Set 0 to 12 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+ udelay(1);
+ switch (rfpath) {
+ case RF90_PATH_A:
+ if (true_bpath)
+ rtstatus = rtl92d_phy_config_rf_with_headerfile(
+ hw, radiob_txt,
+ (enum radio_path)rfpath);
+ else
+ rtstatus = rtl92d_phy_config_rf_with_headerfile(
+ hw, radioa_txt,
+ (enum radio_path)rfpath);
+ break;
+ case RF90_PATH_B:
+ rtstatus =
+ rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt,
+ (enum radio_path) rfpath);
+ break;
+ case RF90_PATH_C:
+ break;
+ case RF90_PATH_D:
+ break;
+ }
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV,
+ u4_regvalue);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
+ u4_regvalue);
+ break;
+ }
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Radio[%d] Fail!!", rfpath));
+ goto phy_rf_cfg_fail;
+ }
+
+ }
+
+ /* check MAC0 enable or not again, if enabled,
+ * not power down radio A. */
+ /* check MAC1 enable or not again, if enabled,
+ * not power down radio B. */
+ if (need_pwrdown_radioa)
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ else if (need_pwrdown_radiob)
+ rtl92d_phy_powerdown_anotherphy(hw, true);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));
+ return rtstatus;
+
+phy_rf_cfg_fail:
+ return rtstatus;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
new file mode 100644
index 000000000000..74b9cfc39a83
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_RF_H__
+#define __RTL92D_RF_H__
+
+extern void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+ u8 bandwidth);
+extern void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel);
+extern void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
+extern bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0);
+extern void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw,
+ bool bmac0);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
new file mode 100644
index 000000000000..351765df517d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/vmalloc.h>
+
+#include "../wifi.h"
+#include "../core.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "hw.h"
+#include "sw.h"
+#include "trx.h"
+#include "led.h"
+
+static void rtl92d_init_aspm_vars(struct ieee80211_hw *hw)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ /*close ASPM for AMD defaultly */
+ rtlpci->const_amdpci_aspm = 0;
+
+ /*
+ * ASPM PS mode.
+ * 0 - Disable ASPM,
+ * 1 - Enable ASPM without Clock Req,
+ * 2 - Enable ASPM with Clock Req,
+ * 3 - Alwyas Enable ASPM with Clock Req,
+ * 4 - Always Enable ASPM without Clock Req.
+ * set defult to RTL8192CE:3 RTL8192E:2
+ * */
+ rtlpci->const_pci_aspm = 3;
+
+ /*Setting for PCI-E device */
+ rtlpci->const_devicepci_aspm_setting = 0x03;
+
+ /*Setting for PCI-E bridge */
+ rtlpci->const_hostpci_aspm_setting = 0x02;
+
+ /*
+ * In Hw/Sw Radio Off situation.
+ * 0 - Default,
+ * 1 - From ASPM setting without low Mac Pwr,
+ * 2 - From ASPM setting with low Mac Pwr,
+ * 3 - Bus D3
+ * set default to RTL8192CE:0 RTL8192SE:2
+ */
+ rtlpci->const_hwsw_rfoff_d3 = 0;
+
+ /*
+ * This setting works for those device with
+ * backdoor ASPM setting such as EPHY setting.
+ * 0 - Not support ASPM,
+ * 1 - Support ASPM,
+ * 2 - According to chipset.
+ */
+ rtlpci->const_support_pciaspm = 1;
+}
+
+static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
+{
+ int err;
+ u8 tid;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ const struct firmware *firmware;
+ static int header_print;
+
+ rtlpriv->dm.dm_initialgain_enable = true;
+ rtlpriv->dm.dm_flag = 0;
+ rtlpriv->dm.disable_framebursting = 0;
+ rtlpriv->dm.thermalvalue = 0;
+ rtlpriv->dm.useramask = 1;
+
+ /* dual mac */
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G)
+ rtlpriv->phy.current_channel = 36;
+ else
+ rtlpriv->phy.current_channel = 1;
+
+ if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+ rtlpriv->rtlhal.disable_amsdu_8k = true;
+ /* No long RX - reduce fragmentation */
+ rtlpci->rxbuffersize = 4096;
+ }
+
+ rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13);
+
+ rtlpci->receive_config = (
+ RCR_APPFCS
+ | RCR_AMF
+ | RCR_ADF
+ | RCR_APP_MIC
+ | RCR_APP_ICV
+ | RCR_AICV
+ | RCR_ACRC32
+ | RCR_AB
+ | RCR_AM
+ | RCR_APM
+ | RCR_APP_PHYST_RXFF
+ | RCR_HTC_LOC_CTRL
+ );
+
+ rtlpci->irq_mask[0] = (u32) (
+ IMR_ROK
+ | IMR_VODOK
+ | IMR_VIDOK
+ | IMR_BEDOK
+ | IMR_BKDOK
+ | IMR_MGNTDOK
+ | IMR_HIGHDOK
+ | IMR_BDOK
+ | IMR_RDU
+ | IMR_RXFOVW
+ );
+
+ rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD);
+
+ /* for LPS & IPS */
+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+ rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+ rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ rtlpriv->psc.reg_fwctrl_lps = 3;
+ rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+ /* for ASPM, you can close aspm through
+ * set const_support_pciaspm = 0 */
+ rtl92d_init_aspm_vars(hw);
+
+ if (rtlpriv->psc.reg_fwctrl_lps == 1)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
+ else if (rtlpriv->psc.reg_fwctrl_lps == 2)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
+ else if (rtlpriv->psc.reg_fwctrl_lps == 3)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
+
+ /* for firmware buf */
+ rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
+ if (!rtlpriv->rtlhal.pfirmware) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Can't alloc buffer for fw.\n"));
+ return 1;
+ }
+
+ if (!header_print) {
+ pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
+ pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
+ header_print++;
+ }
+ /* request fw */
+ err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
+ rtlpriv->io.dev);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Failed to request firmware!\n"));
+ return 1;
+ }
+ if (firmware->size > 0x8000) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Firmware is too big!\n"));
+ release_firmware(firmware);
+ return 1;
+ }
+ memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
+ rtlpriv->rtlhal.fwsize = firmware->size;
+ release_firmware(firmware);
+
+ /* for early mode */
+ rtlpriv->rtlhal.earlymode_enable = true;
+ for (tid = 0; tid < 8; tid++)
+ skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
+ return 0;
+}
+
+static void rtl92d_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tid;
+
+ if (rtlpriv->rtlhal.pfirmware) {
+ vfree(rtlpriv->rtlhal.pfirmware);
+ rtlpriv->rtlhal.pfirmware = NULL;
+ }
+ for (tid = 0; tid < 8; tid++)
+ skb_queue_purge(&rtlpriv->mac80211.skb_waitq[tid]);
+}
+
+static struct rtl_hal_ops rtl8192de_hal_ops = {
+ .init_sw_vars = rtl92d_init_sw_vars,
+ .deinit_sw_vars = rtl92d_deinit_sw_vars,
+ .read_eeprom_info = rtl92de_read_eeprom_info,
+ .interrupt_recognized = rtl92de_interrupt_recognized,
+ .hw_init = rtl92de_hw_init,
+ .hw_disable = rtl92de_card_disable,
+ .hw_suspend = rtl92de_suspend,
+ .hw_resume = rtl92de_resume,
+ .enable_interrupt = rtl92de_enable_interrupt,
+ .disable_interrupt = rtl92de_disable_interrupt,
+ .set_network_type = rtl92de_set_network_type,
+ .set_chk_bssid = rtl92de_set_check_bssid,
+ .set_qos = rtl92de_set_qos,
+ .set_bcn_reg = rtl92de_set_beacon_related_registers,
+ .set_bcn_intv = rtl92de_set_beacon_interval,
+ .update_interrupt_mask = rtl92de_update_interrupt_mask,
+ .get_hw_reg = rtl92de_get_hw_reg,
+ .set_hw_reg = rtl92de_set_hw_reg,
+ .update_rate_tbl = rtl92de_update_hal_rate_tbl,
+ .fill_tx_desc = rtl92de_tx_fill_desc,
+ .fill_tx_cmddesc = rtl92de_tx_fill_cmddesc,
+ .query_rx_desc = rtl92de_rx_query_desc,
+ .set_channel_access = rtl92de_update_channel_access_setting,
+ .radio_onoff_checking = rtl92de_gpio_radio_on_off_checking,
+ .set_bw_mode = rtl92d_phy_set_bw_mode,
+ .switch_channel = rtl92d_phy_sw_chnl,
+ .dm_watchdog = rtl92d_dm_watchdog,
+ .scan_operation_backup = rtl92d_phy_scan_operation_backup,
+ .set_rf_power_state = rtl92d_phy_set_rf_power_state,
+ .led_control = rtl92de_led_control,
+ .set_desc = rtl92de_set_desc,
+ .get_desc = rtl92de_get_desc,
+ .tx_polling = rtl92de_tx_polling,
+ .enable_hw_sec = rtl92de_enable_hw_security_config,
+ .set_key = rtl92de_set_key,
+ .init_sw_leds = rtl92de_init_sw_leds,
+ .get_bbreg = rtl92d_phy_query_bb_reg,
+ .set_bbreg = rtl92d_phy_set_bb_reg,
+ .get_rfreg = rtl92d_phy_query_rf_reg,
+ .set_rfreg = rtl92d_phy_set_rf_reg,
+ .linked_set_reg = rtl92d_linked_set_reg,
+};
+
+static struct rtl_mod_params rtl92de_mod_params = {
+ .sw_crypto = false,
+ .inactiveps = true,
+ .swctrl_lps = true,
+ .fwctrl_lps = false,
+};
+
+static struct rtl_hal_cfg rtl92de_hal_cfg = {
+ .bar_id = 2,
+ .write_readback = true,
+ .name = "rtl8192de",
+ .fw_name = "rtlwifi/rtl8192defw.bin",
+ .ops = &rtl8192de_hal_ops,
+ .mod_params = &rtl92de_mod_params,
+
+ .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
+ .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
+ .maps[SYS_CLK] = REG_SYS_CLKR,
+ .maps[MAC_RCR_AM] = RCR_AM,
+ .maps[MAC_RCR_AB] = RCR_AB,
+ .maps[MAC_RCR_ACRC32] = RCR_ACRC32,
+ .maps[MAC_RCR_ACF] = RCR_ACF,
+ .maps[MAC_RCR_AAP] = RCR_AAP,
+
+ .maps[EFUSE_TEST] = REG_EFUSE_TEST,
+ .maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
+ .maps[EFUSE_CLK] = 0, /* just for 92se */
+ .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
+ .maps[EFUSE_PWC_EV12V] = PWC_EV12V,
+ .maps[EFUSE_FEN_ELDR] = FEN_ELDR,
+ .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
+ .maps[EFUSE_ANA8M] = 0, /* just for 92se */
+ .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
+ .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
+ .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+
+ .maps[RWCAM] = REG_CAMCMD,
+ .maps[WCAMI] = REG_CAMWRITE,
+ .maps[RCAMO] = REG_CAMREAD,
+ .maps[CAMDBG] = REG_CAMDBG,
+ .maps[SECR] = REG_SECCFG,
+ .maps[SEC_CAM_NONE] = CAM_NONE,
+ .maps[SEC_CAM_WEP40] = CAM_WEP40,
+ .maps[SEC_CAM_TKIP] = CAM_TKIP,
+ .maps[SEC_CAM_AES] = CAM_AES,
+ .maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+ .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+ .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+ .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+ .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+ .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+ .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+ .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
+ .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+ .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+ .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+ .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+ .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+ .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+ .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+ .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
+ .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
+
+ .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
+ .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
+ .maps[RTL_IMR_BcnInt] = IMR_BcnInt,
+ .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
+ .maps[RTL_IMR_RDU] = IMR_RDU,
+ .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
+ .maps[RTL_IMR_BDOK] = IMR_BDOK,
+ .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
+ .maps[RTL_IMR_TBDER] = IMR_TBDER,
+ .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
+ .maps[RTL_IMR_TBDOK] = IMR_TBDOK,
+ .maps[RTL_IMR_BKDOK] = IMR_BKDOK,
+ .maps[RTL_IMR_BEDOK] = IMR_BEDOK,
+ .maps[RTL_IMR_VIDOK] = IMR_VIDOK,
+ .maps[RTL_IMR_VODOK] = IMR_VODOK,
+ .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,
+};
+
+static struct pci_device_id rtl92de_pci_ids[] __devinitdata = {
+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)},
+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)},
+ {},
+};
+
+MODULE_DEVICE_TABLE(pci, rtl92de_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 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(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");
+
+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
+
+};
+
+/* add global spin lock to solve the problem that
+ * Dul mac register operation on the same time */
+spinlock_t globalmutex_power;
+spinlock_t globalmutex_for_fwdownload;
+spinlock_t globalmutex_for_power_and_efuse;
+
+static int __init rtl92de_module_init(void)
+{
+ int ret = 0;
+
+ spin_lock_init(&globalmutex_power);
+ spin_lock_init(&globalmutex_for_fwdownload);
+ spin_lock_init(&globalmutex_for_power_and_efuse);
+
+ ret = pci_register_driver(&rtl92de_driver);
+ if (ret)
+ RT_ASSERT(false, (": No device found\n"));
+ return ret;
+}
+
+static void __exit rtl92de_module_exit(void)
+{
+ pci_unregister_driver(&rtl92de_driver);
+}
+
+module_init(rtl92de_module_init);
+module_exit(rtl92de_module_exit);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h
new file mode 100644
index 000000000000..c95e47de1346
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_SW_H__
+#define __RTL92DE_SW_H__
+
+extern spinlock_t globalmutex_power;
+extern spinlock_t globalmutex_for_fwdownload;
+extern spinlock_t globalmutex_for_power_and_efuse;
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/rtlwifi/rtl8192de/table.c
new file mode 100644
index 000000000000..bad7f9449ecf
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.c
@@ -0,0 +1,1690 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Created on 2010/12/23, 6:38
+ *****************************************************************************/
+
+#include <linux/types.h>
+
+#include "table.h"
+
+u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH] = {
+ 0x024, 0x0011800d,
+ 0x028, 0x00ffdb83,
+ 0x014, 0x088ba955,
+ 0x010, 0x49022b03,
+ 0x800, 0x80040002,
+ 0x804, 0x00000003,
+ 0x808, 0x0000fc00,
+ 0x80c, 0x0000000a,
+ 0x810, 0x80706388,
+ 0x814, 0x020c3d10,
+ 0x818, 0x02200385,
+ 0x81c, 0x00000000,
+ 0x820, 0x01000100,
+ 0x824, 0x00390004,
+ 0x828, 0x01000100,
+ 0x82c, 0x00390004,
+ 0x830, 0x27272727,
+ 0x834, 0x27272727,
+ 0x838, 0x27272727,
+ 0x83c, 0x27272727,
+ 0x840, 0x00010000,
+ 0x844, 0x00010000,
+ 0x848, 0x27272727,
+ 0x84c, 0x27272727,
+ 0x850, 0x00000000,
+ 0x854, 0x00000000,
+ 0x858, 0x569a569a,
+ 0x85c, 0x0c1b25a4,
+ 0x860, 0x66e60230,
+ 0x864, 0x061f0130,
+ 0x868, 0x27272727,
+ 0x86c, 0x272b2b2b,
+ 0x870, 0x07000700,
+ 0x874, 0x22188000,
+ 0x878, 0x08080808,
+ 0x87c, 0x00007ff8,
+ 0x880, 0xc0083070,
+ 0x884, 0x00000cd5,
+ 0x888, 0x00000000,
+ 0x88c, 0xcc0000c0,
+ 0x890, 0x00000800,
+ 0x894, 0xfffffffe,
+ 0x898, 0x40302010,
+ 0x89c, 0x00706050,
+ 0x900, 0x00000000,
+ 0x904, 0x00000023,
+ 0x908, 0x00000000,
+ 0x90c, 0x81121313,
+ 0xa00, 0x00d047c8,
+ 0xa04, 0x80ff000c,
+ 0xa08, 0x8c838300,
+ 0xa0c, 0x2e68120f,
+ 0xa10, 0x9500bb78,
+ 0xa14, 0x11144028,
+ 0xa18, 0x00881117,
+ 0xa1c, 0x89140f00,
+ 0xa20, 0x1a1b0000,
+ 0xa24, 0x090e1317,
+ 0xa28, 0x00000204,
+ 0xa2c, 0x00d30000,
+ 0xa70, 0x101fbf00,
+ 0xa74, 0x00000007,
+ 0xc00, 0x40071d40,
+ 0xc04, 0x03a05633,
+ 0xc08, 0x001000e4,
+ 0xc0c, 0x6c6c6c6c,
+ 0xc10, 0x08800000,
+ 0xc14, 0x40000100,
+ 0xc18, 0x08800000,
+ 0xc1c, 0x40000100,
+ 0xc20, 0x00000000,
+ 0xc24, 0x00000000,
+ 0xc28, 0x00000000,
+ 0xc2c, 0x00000000,
+ 0xc30, 0x69e9ac44,
+ 0xc34, 0x469652cf,
+ 0xc38, 0x49795994,
+ 0xc3c, 0x0a979718,
+ 0xc40, 0x1f7c403f,
+ 0xc44, 0x000100b7,
+ 0xc48, 0xec020107,
+ 0xc4c, 0x007f037f,
+ 0xc50, 0x69543420,
+ 0xc54, 0x43bc009e,
+ 0xc58, 0x69543420,
+ 0xc5c, 0x433c00a8,
+ 0xc60, 0x00000000,
+ 0xc64, 0x5116848b,
+ 0xc68, 0x47c00bff,
+ 0xc6c, 0x00000036,
+ 0xc70, 0x2c7f000d,
+ 0xc74, 0x058610db,
+ 0xc78, 0x0000001f,
+ 0xc7c, 0x40b95612,
+ 0xc80, 0x40000100,
+ 0xc84, 0x20f60000,
+ 0xc88, 0x40000100,
+ 0xc8c, 0x20e00000,
+ 0xc90, 0x00121820,
+ 0xc94, 0x00000007,
+ 0xc98, 0x00121820,
+ 0xc9c, 0x00007f7f,
+ 0xca0, 0x00000000,
+ 0xca4, 0x00000080,
+ 0xca8, 0x00000000,
+ 0xcac, 0x00000000,
+ 0xcb0, 0x00000000,
+ 0xcb4, 0x00000000,
+ 0xcb8, 0x00000000,
+ 0xcbc, 0x28000000,
+ 0xcc0, 0x00000000,
+ 0xcc4, 0x00000000,
+ 0xcc8, 0x00000000,
+ 0xccc, 0x00000000,
+ 0xcd0, 0x00000000,
+ 0xcd4, 0x00000000,
+ 0xcd8, 0x64b11e20,
+ 0xcdc, 0xe8767533,
+ 0xce0, 0x00222222,
+ 0xce4, 0x00000000,
+ 0xce8, 0x37644302,
+ 0xcec, 0x2f97d40c,
+ 0xd00, 0x00080740,
+ 0xd04, 0x00020403,
+ 0xd08, 0x0000907f,
+ 0xd0c, 0x20010201,
+ 0xd10, 0xa0633333,
+ 0xd14, 0x3333bc43,
+ 0xd18, 0x7a8f5b6b,
+ 0xd2c, 0xcc979975,
+ 0xd30, 0x00000000,
+ 0xd34, 0x80608404,
+ 0xd38, 0x00000000,
+ 0xd3c, 0x00027293,
+ 0xd40, 0x00000000,
+ 0xd44, 0x00000000,
+ 0xd48, 0x00000000,
+ 0xd4c, 0x00000000,
+ 0xd50, 0x6437140a,
+ 0xd54, 0x00000000,
+ 0xd58, 0x00000000,
+ 0xd5c, 0x30032064,
+ 0xd60, 0x4653de68,
+ 0xd64, 0x04518a3c,
+ 0xd68, 0x00002101,
+ 0xd6c, 0x2a201c16,
+ 0xd70, 0x1812362e,
+ 0xd74, 0x322c2220,
+ 0xd78, 0x000e3c24,
+ 0xe00, 0x2a2a2a2a,
+ 0xe04, 0x2a2a2a2a,
+ 0xe08, 0x03902a2a,
+ 0xe10, 0x2a2a2a2a,
+ 0xe14, 0x2a2a2a2a,
+ 0xe18, 0x2a2a2a2a,
+ 0xe1c, 0x2a2a2a2a,
+ 0xe28, 0x00000000,
+ 0xe30, 0x1000dc1f,
+ 0xe34, 0x10008c1f,
+ 0xe38, 0x02140102,
+ 0xe3c, 0x681604c2,
+ 0xe40, 0x01007c00,
+ 0xe44, 0x01004800,
+ 0xe48, 0xfb000000,
+ 0xe4c, 0x000028d1,
+ 0xe50, 0x1000dc1f,
+ 0xe54, 0x10008c1f,
+ 0xe58, 0x02140102,
+ 0xe5c, 0x28160d05,
+ 0xe60, 0x00000010,
+ 0xe68, 0x001b25a4,
+ 0xe6c, 0x63db25a4,
+ 0xe70, 0x63db25a4,
+ 0xe74, 0x0c126da4,
+ 0xe78, 0x0c126da4,
+ 0xe7c, 0x0c126da4,
+ 0xe80, 0x0c126da4,
+ 0xe84, 0x63db25a4,
+ 0xe88, 0x0c126da4,
+ 0xe8c, 0x63db25a4,
+ 0xed0, 0x63db25a4,
+ 0xed4, 0x63db25a4,
+ 0xed8, 0x63db25a4,
+ 0xedc, 0x001b25a4,
+ 0xee0, 0x001b25a4,
+ 0xeec, 0x6fdb25a4,
+ 0xf14, 0x00000003,
+ 0xf1c, 0x00000064,
+ 0xf4c, 0x00000004,
+ 0xf00, 0x00000300,
+};
+
+u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH] = {
+ 0xe00, 0xffffffff, 0x07090c0c,
+ 0xe04, 0xffffffff, 0x01020405,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x0b0c0c0e,
+ 0xe14, 0xffffffff, 0x01030506,
+ 0xe18, 0xffffffff, 0x0b0c0d0e,
+ 0xe1c, 0xffffffff, 0x01030509,
+ 0x830, 0xffffffff, 0x07090c0c,
+ 0x834, 0xffffffff, 0x01020405,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x0b0c0c0e,
+ 0x848, 0xffffffff, 0x01030506,
+ 0x84c, 0xffffffff, 0x0b0c0d0e,
+ 0x868, 0xffffffff, 0x01030509,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x06060606,
+ 0xe14, 0xffffffff, 0x00020406,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x06060606,
+ 0x848, 0xffffffff, 0x00020406,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+};
+
+u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00017524,
+ 0x019, 0x00000000,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000de471,
+ 0x029, 0x000d7110,
+ 0x02a, 0x0008cb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000f9c43,
+ 0x049, 0x00002e0c,
+ 0x04a, 0x000546eb,
+ 0x04b, 0x0008966c,
+ 0x04c, 0x0000dde9,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00037524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00057568,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00097524,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x0006aaaa,
+ 0x02e, 0x000b4d01,
+ 0x02d, 0x00080000,
+ 0x02e, 0x00004d02,
+ 0x02d, 0x00095555,
+ 0x02e, 0x00054d03,
+ 0x02d, 0x000aaaaa,
+ 0x02e, 0x000b4d04,
+ 0x02d, 0x000c0000,
+ 0x02e, 0x00004d05,
+ 0x02d, 0x000d5555,
+ 0x02e, 0x00054d06,
+ 0x02d, 0x000eaaaa,
+ 0x02e, 0x000b4d07,
+ 0x02d, 0x00000000,
+ 0x02e, 0x00005108,
+ 0x02d, 0x00015555,
+ 0x02e, 0x00055109,
+ 0x02d, 0x0002aaaa,
+ 0x02e, 0x000b510a,
+ 0x02d, 0x00040000,
+ 0x02e, 0x0000510b,
+ 0x02d, 0x00055555,
+ 0x02e, 0x0005510c,
+};
+
+u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00007401,
+ 0x019, 0x00000060,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000d1c31,
+ 0x029, 0x000d7110,
+ 0x02a, 0x000aeb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000f9c43,
+ 0x049, 0x00002e0c,
+ 0x04a, 0x000546eb,
+ 0x04b, 0x0008966c,
+ 0x04c, 0x0000dde9,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00037524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00057524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00087401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x00066666,
+ 0x02e, 0x00064001,
+ 0x02d, 0x00091111,
+ 0x02e, 0x00014002,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4003,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x00064004,
+ 0x02d, 0x00088888,
+ 0x02e, 0x00084005,
+ 0x02d, 0x0009dddd,
+ 0x02e, 0x000d4006,
+ 0x02d, 0x000b3333,
+ 0x02e, 0x00034007,
+ 0x02d, 0x00048888,
+ 0x02e, 0x00084408,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4409,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x0006440a,
+ 0x02d, 0x00011111,
+ 0x02e, 0x0001480b,
+ 0x02d, 0x0003bbbb,
+ 0x02e, 0x000b480c,
+ 0x02d, 0x00066666,
+ 0x02e, 0x0006480d,
+ 0x02d, 0x000ccccc,
+ 0x02e, 0x000c480e,
+};
+
+u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00017524,
+ 0x019, 0x00000000,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000de471,
+ 0x029, 0x000d7110,
+ 0x02a, 0x0008eb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000c0443,
+ 0x049, 0x00000730,
+ 0x04a, 0x00050f0f,
+ 0x04b, 0x000896ee,
+ 0x04c, 0x0000ddee,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00037564,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00057595,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00097524,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x0006aaaa,
+ 0x02e, 0x000b4d01,
+ 0x02d, 0x00080000,
+ 0x02e, 0x00004d02,
+ 0x02d, 0x00095555,
+ 0x02e, 0x00054d03,
+ 0x02d, 0x000aaaaa,
+ 0x02e, 0x000b4d04,
+ 0x02d, 0x000c0000,
+ 0x02e, 0x00004d05,
+ 0x02d, 0x000d5555,
+ 0x02e, 0x00054d06,
+ 0x02d, 0x000eaaaa,
+ 0x02e, 0x000b4d07,
+ 0x02d, 0x00000000,
+ 0x02e, 0x00005108,
+ 0x02d, 0x00015555,
+ 0x02e, 0x00055109,
+ 0x02d, 0x0002aaaa,
+ 0x02e, 0x000b510a,
+ 0x02d, 0x00040000,
+ 0x02e, 0x0000510b,
+ 0x02d, 0x00055555,
+ 0x02e, 0x0005510c,
+};
+
+u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00007401,
+ 0x019, 0x00000060,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000d1c31,
+ 0x029, 0x000d7110,
+ 0x02a, 0x000aeb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000c0443,
+ 0x049, 0x00000730,
+ 0x04a, 0x00050f0f,
+ 0x04b, 0x000896ee,
+ 0x04c, 0x0000ddee,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00037564,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00057595,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00087401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x00066666,
+ 0x02e, 0x00064001,
+ 0x02d, 0x00091111,
+ 0x02e, 0x00014002,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4003,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x00064004,
+ 0x02d, 0x00088888,
+ 0x02e, 0x00084005,
+ 0x02d, 0x0009dddd,
+ 0x02e, 0x000d4006,
+ 0x02d, 0x000b3333,
+ 0x02e, 0x00034007,
+ 0x02d, 0x00048888,
+ 0x02e, 0x00084408,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4409,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x0006440a,
+ 0x02d, 0x00011111,
+ 0x02e, 0x0001480b,
+ 0x02d, 0x0003bbbb,
+ 0x02e, 0x000b480c,
+ 0x02d, 0x00066666,
+ 0x02e, 0x0006480d,
+ 0x02d, 0x000ccccc,
+ 0x02e, 0x000c480e,
+};
+
+u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH] = {
+ 0x420, 0x00000080,
+ 0x423, 0x00000000,
+ 0x430, 0x00000000,
+ 0x431, 0x00000000,
+ 0x432, 0x00000000,
+ 0x433, 0x00000001,
+ 0x434, 0x00000004,
+ 0x435, 0x00000005,
+ 0x436, 0x00000006,
+ 0x437, 0x00000007,
+ 0x438, 0x00000000,
+ 0x439, 0x00000000,
+ 0x43a, 0x00000000,
+ 0x43b, 0x00000001,
+ 0x43c, 0x00000004,
+ 0x43d, 0x00000005,
+ 0x43e, 0x00000006,
+ 0x43f, 0x00000007,
+ 0x440, 0x00000050,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000015,
+ 0x445, 0x000000f0,
+ 0x446, 0x0000000f,
+ 0x447, 0x00000000,
+ 0x462, 0x00000008,
+ 0x463, 0x00000003,
+ 0x4c8, 0x000000ff,
+ 0x4c9, 0x00000008,
+ 0x4cc, 0x000000ff,
+ 0x4cd, 0x000000ff,
+ 0x4ce, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000a2,
+ 0x502, 0x0000002f,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000a3,
+ 0x506, 0x0000005e,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002b,
+ 0x509, 0x000000a4,
+ 0x50a, 0x0000005e,
+ 0x50b, 0x00000000,
+ 0x50c, 0x0000004f,
+ 0x50d, 0x000000a4,
+ 0x50e, 0x00000000,
+ 0x50f, 0x00000000,
+ 0x512, 0x0000001c,
+ 0x514, 0x0000000a,
+ 0x515, 0x00000010,
+ 0x516, 0x0000000a,
+ 0x517, 0x00000010,
+ 0x51a, 0x00000016,
+ 0x524, 0x0000000f,
+ 0x525, 0x0000004f,
+ 0x546, 0x00000040,
+ 0x547, 0x00000000,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55a, 0x00000002,
+ 0x55d, 0x000000ff,
+ 0x605, 0x00000030,
+ 0x608, 0x0000000e,
+ 0x609, 0x0000002a,
+ 0x652, 0x00000020,
+ 0x63c, 0x0000000a,
+ 0x63d, 0x0000000a,
+ 0x63e, 0x0000000e,
+ 0x63f, 0x0000000e,
+ 0x66e, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70a, 0x00000065,
+ 0x70b, 0x00000087,
+};
+
+u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH] = {
+ 0xc78, 0x7b000001,
+ 0xc78, 0x7b010001,
+ 0xc78, 0x7b020001,
+ 0xc78, 0x7b030001,
+ 0xc78, 0x7b040001,
+ 0xc78, 0x7b050001,
+ 0xc78, 0x7b060001,
+ 0xc78, 0x7a070001,
+ 0xc78, 0x79080001,
+ 0xc78, 0x78090001,
+ 0xc78, 0x770a0001,
+ 0xc78, 0x760b0001,
+ 0xc78, 0x750c0001,
+ 0xc78, 0x740d0001,
+ 0xc78, 0x730e0001,
+ 0xc78, 0x720f0001,
+ 0xc78, 0x71100001,
+ 0xc78, 0x70110001,
+ 0xc78, 0x6f120001,
+ 0xc78, 0x6e130001,
+ 0xc78, 0x6d140001,
+ 0xc78, 0x6c150001,
+ 0xc78, 0x6b160001,
+ 0xc78, 0x6a170001,
+ 0xc78, 0x69180001,
+ 0xc78, 0x68190001,
+ 0xc78, 0x671a0001,
+ 0xc78, 0x661b0001,
+ 0xc78, 0x651c0001,
+ 0xc78, 0x641d0001,
+ 0xc78, 0x631e0001,
+ 0xc78, 0x621f0001,
+ 0xc78, 0x61200001,
+ 0xc78, 0x60210001,
+ 0xc78, 0x49220001,
+ 0xc78, 0x48230001,
+ 0xc78, 0x47240001,
+ 0xc78, 0x46250001,
+ 0xc78, 0x45260001,
+ 0xc78, 0x44270001,
+ 0xc78, 0x43280001,
+ 0xc78, 0x42290001,
+ 0xc78, 0x412a0001,
+ 0xc78, 0x402b0001,
+ 0xc78, 0x262c0001,
+ 0xc78, 0x252d0001,
+ 0xc78, 0x242e0001,
+ 0xc78, 0x232f0001,
+ 0xc78, 0x22300001,
+ 0xc78, 0x21310001,
+ 0xc78, 0x20320001,
+ 0xc78, 0x06330001,
+ 0xc78, 0x05340001,
+ 0xc78, 0x04350001,
+ 0xc78, 0x03360001,
+ 0xc78, 0x02370001,
+ 0xc78, 0x01380001,
+ 0xc78, 0x00390001,
+ 0xc78, 0x003a0001,
+ 0xc78, 0x003b0001,
+ 0xc78, 0x003c0001,
+ 0xc78, 0x003d0001,
+ 0xc78, 0x003e0001,
+ 0xc78, 0x003f0001,
+ 0xc78, 0x7b400001,
+ 0xc78, 0x7b410001,
+ 0xc78, 0x7a420001,
+ 0xc78, 0x79430001,
+ 0xc78, 0x78440001,
+ 0xc78, 0x77450001,
+ 0xc78, 0x76460001,
+ 0xc78, 0x75470001,
+ 0xc78, 0x74480001,
+ 0xc78, 0x73490001,
+ 0xc78, 0x724a0001,
+ 0xc78, 0x714b0001,
+ 0xc78, 0x704c0001,
+ 0xc78, 0x6f4d0001,
+ 0xc78, 0x6e4e0001,
+ 0xc78, 0x6d4f0001,
+ 0xc78, 0x6c500001,
+ 0xc78, 0x6b510001,
+ 0xc78, 0x6a520001,
+ 0xc78, 0x69530001,
+ 0xc78, 0x68540001,
+ 0xc78, 0x67550001,
+ 0xc78, 0x66560001,
+ 0xc78, 0x65570001,
+ 0xc78, 0x64580001,
+ 0xc78, 0x63590001,
+ 0xc78, 0x625a0001,
+ 0xc78, 0x615b0001,
+ 0xc78, 0x605c0001,
+ 0xc78, 0x485d0001,
+ 0xc78, 0x475e0001,
+ 0xc78, 0x465f0001,
+ 0xc78, 0x45600001,
+ 0xc78, 0x44610001,
+ 0xc78, 0x43620001,
+ 0xc78, 0x42630001,
+ 0xc78, 0x41640001,
+ 0xc78, 0x40650001,
+ 0xc78, 0x27660001,
+ 0xc78, 0x26670001,
+ 0xc78, 0x25680001,
+ 0xc78, 0x24690001,
+ 0xc78, 0x236a0001,
+ 0xc78, 0x226b0001,
+ 0xc78, 0x216c0001,
+ 0xc78, 0x206d0001,
+ 0xc78, 0x206e0001,
+ 0xc78, 0x206f0001,
+ 0xc78, 0x20700001,
+ 0xc78, 0x20710001,
+ 0xc78, 0x20720001,
+ 0xc78, 0x20730001,
+ 0xc78, 0x20740001,
+ 0xc78, 0x20750001,
+ 0xc78, 0x20760001,
+ 0xc78, 0x20770001,
+ 0xc78, 0x20780001,
+ 0xc78, 0x20790001,
+ 0xc78, 0x207a0001,
+ 0xc78, 0x207b0001,
+ 0xc78, 0x207c0001,
+ 0xc78, 0x207d0001,
+ 0xc78, 0x207e0001,
+ 0xc78, 0x207f0001,
+ 0xc78, 0x38000002,
+ 0xc78, 0x38010002,
+ 0xc78, 0x38020002,
+ 0xc78, 0x38030002,
+ 0xc78, 0x38040002,
+ 0xc78, 0x38050002,
+ 0xc78, 0x38060002,
+ 0xc78, 0x38070002,
+ 0xc78, 0x38080002,
+ 0xc78, 0x3c090002,
+ 0xc78, 0x3e0a0002,
+ 0xc78, 0x400b0002,
+ 0xc78, 0x440c0002,
+ 0xc78, 0x480d0002,
+ 0xc78, 0x4c0e0002,
+ 0xc78, 0x500f0002,
+ 0xc78, 0x52100002,
+ 0xc78, 0x56110002,
+ 0xc78, 0x5a120002,
+ 0xc78, 0x5e130002,
+ 0xc78, 0x60140002,
+ 0xc78, 0x60150002,
+ 0xc78, 0x60160002,
+ 0xc78, 0x62170002,
+ 0xc78, 0x62180002,
+ 0xc78, 0x62190002,
+ 0xc78, 0x621a0002,
+ 0xc78, 0x621b0002,
+ 0xc78, 0x621c0002,
+ 0xc78, 0x621d0002,
+ 0xc78, 0x621e0002,
+ 0xc78, 0x621f0002,
+ 0xc78, 0x32000044,
+ 0xc78, 0x32010044,
+ 0xc78, 0x32020044,
+ 0xc78, 0x32030044,
+ 0xc78, 0x32040044,
+ 0xc78, 0x32050044,
+ 0xc78, 0x32060044,
+ 0xc78, 0x32070044,
+ 0xc78, 0x32080044,
+ 0xc78, 0x34090044,
+ 0xc78, 0x350a0044,
+ 0xc78, 0x360b0044,
+ 0xc78, 0x370c0044,
+ 0xc78, 0x380d0044,
+ 0xc78, 0x390e0044,
+ 0xc78, 0x3a0f0044,
+ 0xc78, 0x3e100044,
+ 0xc78, 0x42110044,
+ 0xc78, 0x44120044,
+ 0xc78, 0x46130044,
+ 0xc78, 0x4a140044,
+ 0xc78, 0x4e150044,
+ 0xc78, 0x50160044,
+ 0xc78, 0x55170044,
+ 0xc78, 0x5a180044,
+ 0xc78, 0x5e190044,
+ 0xc78, 0x641a0044,
+ 0xc78, 0x6e1b0044,
+ 0xc78, 0x6e1c0044,
+ 0xc78, 0x6e1d0044,
+ 0xc78, 0x6e1e0044,
+ 0xc78, 0x6e1f0044,
+ 0xc78, 0x6e1f0000,
+};
+
+u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH] = {
+ 0xc78, 0x7b000001,
+ 0xc78, 0x7b010001,
+ 0xc78, 0x7a020001,
+ 0xc78, 0x79030001,
+ 0xc78, 0x78040001,
+ 0xc78, 0x77050001,
+ 0xc78, 0x76060001,
+ 0xc78, 0x75070001,
+ 0xc78, 0x74080001,
+ 0xc78, 0x73090001,
+ 0xc78, 0x720a0001,
+ 0xc78, 0x710b0001,
+ 0xc78, 0x700c0001,
+ 0xc78, 0x6f0d0001,
+ 0xc78, 0x6e0e0001,
+ 0xc78, 0x6d0f0001,
+ 0xc78, 0x6c100001,
+ 0xc78, 0x6b110001,
+ 0xc78, 0x6a120001,
+ 0xc78, 0x69130001,
+ 0xc78, 0x68140001,
+ 0xc78, 0x67150001,
+ 0xc78, 0x66160001,
+ 0xc78, 0x65170001,
+ 0xc78, 0x64180001,
+ 0xc78, 0x63190001,
+ 0xc78, 0x621a0001,
+ 0xc78, 0x611b0001,
+ 0xc78, 0x601c0001,
+ 0xc78, 0x481d0001,
+ 0xc78, 0x471e0001,
+ 0xc78, 0x461f0001,
+ 0xc78, 0x45200001,
+ 0xc78, 0x44210001,
+ 0xc78, 0x43220001,
+ 0xc78, 0x42230001,
+ 0xc78, 0x41240001,
+ 0xc78, 0x40250001,
+ 0xc78, 0x27260001,
+ 0xc78, 0x26270001,
+ 0xc78, 0x25280001,
+ 0xc78, 0x24290001,
+ 0xc78, 0x232a0001,
+ 0xc78, 0x222b0001,
+ 0xc78, 0x212c0001,
+ 0xc78, 0x202d0001,
+ 0xc78, 0x202e0001,
+ 0xc78, 0x202f0001,
+ 0xc78, 0x20300001,
+ 0xc78, 0x20310001,
+ 0xc78, 0x20320001,
+ 0xc78, 0x20330001,
+ 0xc78, 0x20340001,
+ 0xc78, 0x20350001,
+ 0xc78, 0x20360001,
+ 0xc78, 0x20370001,
+ 0xc78, 0x20380001,
+ 0xc78, 0x20390001,
+ 0xc78, 0x203a0001,
+ 0xc78, 0x203b0001,
+ 0xc78, 0x203c0001,
+ 0xc78, 0x203d0001,
+ 0xc78, 0x203e0001,
+ 0xc78, 0x203f0001,
+ 0xc78, 0x32000044,
+ 0xc78, 0x32010044,
+ 0xc78, 0x32020044,
+ 0xc78, 0x32030044,
+ 0xc78, 0x32040044,
+ 0xc78, 0x32050044,
+ 0xc78, 0x32060044,
+ 0xc78, 0x32070044,
+ 0xc78, 0x32080044,
+ 0xc78, 0x34090044,
+ 0xc78, 0x350a0044,
+ 0xc78, 0x360b0044,
+ 0xc78, 0x370c0044,
+ 0xc78, 0x380d0044,
+ 0xc78, 0x390e0044,
+ 0xc78, 0x3a0f0044,
+ 0xc78, 0x3e100044,
+ 0xc78, 0x42110044,
+ 0xc78, 0x44120044,
+ 0xc78, 0x46130044,
+ 0xc78, 0x4a140044,
+ 0xc78, 0x4e150044,
+ 0xc78, 0x50160044,
+ 0xc78, 0x55170044,
+ 0xc78, 0x5a180044,
+ 0xc78, 0x5e190044,
+ 0xc78, 0x641a0044,
+ 0xc78, 0x6e1b0044,
+ 0xc78, 0x6e1c0044,
+ 0xc78, 0x6e1d0044,
+ 0xc78, 0x6e1e0044,
+ 0xc78, 0x6e1f0044,
+ 0xc78, 0x6e1f0000,
+};
+
+u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH] = {
+ 0xc78, 0x7b000001,
+ 0xc78, 0x7b010001,
+ 0xc78, 0x7b020001,
+ 0xc78, 0x7b030001,
+ 0xc78, 0x7b040001,
+ 0xc78, 0x7b050001,
+ 0xc78, 0x7b060001,
+ 0xc78, 0x7a070001,
+ 0xc78, 0x79080001,
+ 0xc78, 0x78090001,
+ 0xc78, 0x770a0001,
+ 0xc78, 0x760b0001,
+ 0xc78, 0x750c0001,
+ 0xc78, 0x740d0001,
+ 0xc78, 0x730e0001,
+ 0xc78, 0x720f0001,
+ 0xc78, 0x71100001,
+ 0xc78, 0x70110001,
+ 0xc78, 0x6f120001,
+ 0xc78, 0x6e130001,
+ 0xc78, 0x6d140001,
+ 0xc78, 0x6c150001,
+ 0xc78, 0x6b160001,
+ 0xc78, 0x6a170001,
+ 0xc78, 0x69180001,
+ 0xc78, 0x68190001,
+ 0xc78, 0x671a0001,
+ 0xc78, 0x661b0001,
+ 0xc78, 0x651c0001,
+ 0xc78, 0x641d0001,
+ 0xc78, 0x631e0001,
+ 0xc78, 0x621f0001,
+ 0xc78, 0x61200001,
+ 0xc78, 0x60210001,
+ 0xc78, 0x49220001,
+ 0xc78, 0x48230001,
+ 0xc78, 0x47240001,
+ 0xc78, 0x46250001,
+ 0xc78, 0x45260001,
+ 0xc78, 0x44270001,
+ 0xc78, 0x43280001,
+ 0xc78, 0x42290001,
+ 0xc78, 0x412a0001,
+ 0xc78, 0x402b0001,
+ 0xc78, 0x262c0001,
+ 0xc78, 0x252d0001,
+ 0xc78, 0x242e0001,
+ 0xc78, 0x232f0001,
+ 0xc78, 0x22300001,
+ 0xc78, 0x21310001,
+ 0xc78, 0x20320001,
+ 0xc78, 0x06330001,
+ 0xc78, 0x05340001,
+ 0xc78, 0x04350001,
+ 0xc78, 0x03360001,
+ 0xc78, 0x02370001,
+ 0xc78, 0x01380001,
+ 0xc78, 0x00390001,
+ 0xc78, 0x003a0001,
+ 0xc78, 0x003b0001,
+ 0xc78, 0x003c0001,
+ 0xc78, 0x003d0001,
+ 0xc78, 0x003e0001,
+ 0xc78, 0x003f0001,
+ 0xc78, 0x38000002,
+ 0xc78, 0x38010002,
+ 0xc78, 0x38020002,
+ 0xc78, 0x38030002,
+ 0xc78, 0x38040002,
+ 0xc78, 0x38050002,
+ 0xc78, 0x38060002,
+ 0xc78, 0x38070002,
+ 0xc78, 0x38080002,
+ 0xc78, 0x3c090002,
+ 0xc78, 0x3e0a0002,
+ 0xc78, 0x400b0002,
+ 0xc78, 0x440c0002,
+ 0xc78, 0x480d0002,
+ 0xc78, 0x4c0e0002,
+ 0xc78, 0x500f0002,
+ 0xc78, 0x52100002,
+ 0xc78, 0x56110002,
+ 0xc78, 0x5a120002,
+ 0xc78, 0x5e130002,
+ 0xc78, 0x60140002,
+ 0xc78, 0x60150002,
+ 0xc78, 0x60160002,
+ 0xc78, 0x62170002,
+ 0xc78, 0x62180002,
+ 0xc78, 0x62190002,
+ 0xc78, 0x621a0002,
+ 0xc78, 0x621b0002,
+ 0xc78, 0x621c0002,
+ 0xc78, 0x621d0002,
+ 0xc78, 0x621e0002,
+ 0xc78, 0x621f0002,
+ 0xc78, 0x6e1f0000,
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/rtlwifi/rtl8192de/table.h
new file mode 100644
index 000000000000..93f30ca62d8f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Created on 2010/ 5/18, 1:41
+ *****************************************************************************/
+
+#ifndef __RTL92DE_TABLE__H_
+#define __RTL92DE_TABLE__H_
+
+/*Created on 2011/ 1/14, 1:35*/
+
+#define PHY_REG_2T_ARRAYLENGTH 380
+extern u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH];
+#define PHY_REG_ARRAY_PG_LENGTH 624
+extern u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH];
+#define RADIOA_2T_ARRAYLENGTH 378
+extern u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH];
+#define RADIOB_2T_ARRAYLENGTH 384
+extern u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH];
+#define RADIOA_2T_INT_PA_ARRAYLENGTH 378
+extern u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH];
+#define RADIOB_2T_INT_PA_ARRAYLENGTH 384
+extern u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH];
+#define MAC_2T_ARRAYLENGTH 160
+extern u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH];
+#define AGCTAB_ARRAYLENGTH 386
+extern u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH];
+#define AGCTAB_5G_ARRAYLENGTH 194
+extern u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH];
+#define AGCTAB_2G_ARRAYLENGTH 194
+extern u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH];
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
new file mode 100644
index 000000000000..dc86fcb0b3a3
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -0,0 +1,959 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "led.h"
+
+static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
+{
+ __le16 fc = rtl_get_fc(skb);
+
+ if (unlikely(ieee80211_is_beacon(fc)))
+ return QSLT_BEACON;
+ if (ieee80211_is_mgmt(fc))
+ return QSLT_MGNT;
+
+ 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))
+ return 0;
+ else if (antpower >= 0)
+ return 100;
+ else
+ return 100 + antpower;
+}
+
+static u8 _rtl92d_evm_db_to_percentage(char value)
+{
+ char ret_val = value;
+
+ if (ret_val >= 0)
+ ret_val = 0;
+ if (ret_val <= -33)
+ ret_val = -33;
+ ret_val = 0 - ret_val;
+ ret_val *= 3;
+ if (ret_val == 99)
+ ret_val = 100;
+ return ret_val;
+}
+
+static long _rtl92de_translate_todbm(struct ieee80211_hw *hw,
+ u8 signal_strength_index)
+{
+ long signal_power;
+
+ signal_power = (long)((signal_strength_index + 1) >> 1);
+ signal_power -= 95;
+ return signal_power;
+}
+
+static long _rtl92de_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
+{
+ long retsig;
+
+ if (currsig >= 61 && currsig <= 100)
+ retsig = 90 + ((currsig - 60) / 4);
+ else if (currsig >= 41 && currsig <= 60)
+ retsig = 78 + ((currsig - 40) / 2);
+ else if (currsig >= 31 && currsig <= 40)
+ retsig = 66 + (currsig - 30);
+ else if (currsig >= 21 && currsig <= 30)
+ retsig = 54 + (currsig - 20);
+ else if (currsig >= 5 && currsig <= 20)
+ retsig = 42 + (((currsig - 5) * 2) / 3);
+ else if (currsig == 4)
+ retsig = 36;
+ else if (currsig == 3)
+ retsig = 27;
+ else if (currsig == 2)
+ retsig = 18;
+ else if (currsig == 1)
+ retsig = 9;
+ else
+ retsig = currsig;
+ return retsig;
+}
+
+static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats,
+ struct rx_desc_92d *pdesc,
+ struct rx_fwinfo_92d *p_drvinfo,
+ bool packet_match_bssid,
+ bool packet_toself,
+ bool packet_beacon)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ struct phy_sts_cck_8192d *cck_buf;
+ s8 rx_pwr_all, rx_pwr[4];
+ u8 rf_rx_num = 0, evm, pwdb_all;
+ u8 i, max_spatial_stream;
+ u32 rssi, total_rssi = 0;
+ bool is_cck_rate;
+
+ is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
+ pstats->packet_matchbssid = packet_match_bssid;
+ pstats->packet_toself = packet_toself;
+ pstats->packet_beacon = packet_beacon;
+ pstats->is_cck = is_cck_rate;
+ pstats->rx_mimo_signalquality[0] = -1;
+ pstats->rx_mimo_signalquality[1] = -1;
+
+ if (is_cck_rate) {
+ u8 report, cck_highpwr;
+ cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo;
+ if (ppsc->rfpwr_state == ERFON)
+ cck_highpwr = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER2,
+ BIT(9));
+ else
+ cck_highpwr = false;
+ if (!cck_highpwr) {
+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+ report = cck_buf->cck_agc_rpt & 0xc0;
+ report = report >> 6;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+ break;
+ }
+ } else {
+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+ report = p_drvinfo->cfosho[0] & 0x60;
+ report = report >> 5;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ }
+ }
+ pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
+ /* CCK gain is smaller than OFDM/MCS gain, */
+ /* so we add gain diff by experiences, the val is 6 */
+ pwdb_all += 6;
+ if (pwdb_all > 100)
+ pwdb_all = 100;
+ /* modify the offset to make the same gain index with OFDM. */
+ if (pwdb_all > 34 && pwdb_all <= 42)
+ pwdb_all -= 2;
+ else if (pwdb_all > 26 && pwdb_all <= 34)
+ pwdb_all -= 6;
+ else if (pwdb_all > 14 && pwdb_all <= 26)
+ pwdb_all -= 8;
+ else if (pwdb_all > 4 && pwdb_all <= 14)
+ pwdb_all -= 4;
+ pstats->rx_pwdb_all = pwdb_all;
+ pstats->recvsignalpower = rx_pwr_all;
+ if (packet_match_bssid) {
+ u8 sq;
+ if (pstats->rx_pwdb_all > 40) {
+ sq = 100;
+ } else {
+ sq = cck_buf->sq_rpt;
+ if (sq > 64)
+ sq = 0;
+ else if (sq < 20)
+ sq = 100;
+ else
+ sq = ((64 - sq) * 100) / 44;
+ }
+ pstats->signalquality = sq;
+ pstats->rx_mimo_signalquality[0] = sq;
+ pstats->rx_mimo_signalquality[1] = -1;
+ }
+ } else {
+ rtlpriv->dm.rfpath_rxenable[0] = true;
+ rtlpriv->dm.rfpath_rxenable[1] = true;
+ for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
+ if (rtlpriv->dm.rfpath_rxenable[i])
+ rf_rx_num++;
+ rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)
+ - 110;
+ rssi = _rtl92d_query_rxpwrpercentage(rx_pwr[i]);
+ total_rssi += rssi;
+ rtlpriv->stats.rx_snr_db[i] =
+ (long)(p_drvinfo->rxsnr[i] / 2);
+ if (packet_match_bssid)
+ pstats->rx_mimo_signalstrength[i] = (u8) rssi;
+ }
+ rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106;
+ pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
+ 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)
+ max_spatial_stream = 2;
+ else
+ max_spatial_stream = 1;
+ for (i = 0; i < max_spatial_stream; i++) {
+ evm = _rtl92d_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+ if (packet_match_bssid) {
+ if (i == 0)
+ pstats->signalquality =
+ (u8)(evm & 0xff);
+ pstats->rx_mimo_signalquality[i] =
+ (u8)(evm & 0xff);
+ }
+ }
+ }
+ if (is_cck_rate)
+ pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
+ pwdb_all));
+ else if (rf_rx_num != 0)
+ pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
+ total_rssi /= rf_rx_num));
+}
+
+static void rtl92d_loop_over_paths(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 rfpath;
+
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ pstats->rx_mimo_signalstrength[rfpath];
+
+ }
+ if (pstats->rx_mimo_signalstrength[rfpath] >
+ rtlpriv->stats.rx_rssi_percentage[rfpath]) {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_mimo_signalstrength[rfpath])) /
+ (RX_SMOOTH_FACTOR);
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
+ } else {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_mimo_signalstrength[rfpath])) /
+ (RX_SMOOTH_FACTOR);
+ }
+ }
+}
+
+static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 last_rssi, tmpval;
+
+ if (pstats->packet_toself || pstats->packet_beacon) {
+ rtlpriv->stats.rssi_calculate_cnt++;
+ if (rtlpriv->stats.ui_rssi.total_num++ >=
+ PHY_RSSI_SLID_WIN_MAX) {
+ rtlpriv->stats.ui_rssi.total_num =
+ PHY_RSSI_SLID_WIN_MAX;
+ last_rssi = rtlpriv->stats.ui_rssi.elements[
+ rtlpriv->stats.ui_rssi.index];
+ rtlpriv->stats.ui_rssi.total_val -= last_rssi;
+ }
+ rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
+ rtlpriv->stats.ui_rssi.elements
+ [rtlpriv->stats.ui_rssi.index++] =
+ pstats->signalstrength;
+ if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
+ rtlpriv->stats.ui_rssi.index = 0;
+ tmpval = rtlpriv->stats.ui_rssi.total_val /
+ rtlpriv->stats.ui_rssi.total_num;
+ rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw,
+ (u8) tmpval);
+ pstats->rssi = rtlpriv->stats.signal_strength;
+ }
+ if (!pstats->is_cck && pstats->packet_toself)
+ rtl92d_loop_over_paths(hw, pstats);
+}
+
+static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int weighting = 0;
+
+ if (rtlpriv->stats.recv_signal_power == 0)
+ rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
+ if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
+ weighting = 5;
+ else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
+ weighting = (-5);
+ rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
+ 5 + pstats->recvsignalpower + weighting) / 6;
+}
+
+static void _rtl92de_process_pwdb(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ long undecorated_smoothed_pwdb;
+
+ if (mac->opmode == NL80211_IFTYPE_ADHOC ||
+ mac->opmode == NL80211_IFTYPE_AP)
+ return;
+ else
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.undecorated_smoothed_pwdb;
+
+ if (pstats->packet_toself || pstats->packet_beacon) {
+ if (undecorated_smoothed_pwdb < 0)
+ undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
+ if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
+ undecorated_smoothed_pwdb =
+ (((undecorated_smoothed_pwdb) *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+ undecorated_smoothed_pwdb =
+ undecorated_smoothed_pwdb + 1;
+ } else {
+ undecorated_smoothed_pwdb =
+ (((undecorated_smoothed_pwdb) *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+ }
+ rtlpriv->dm.undecorated_smoothed_pwdb =
+ undecorated_smoothed_pwdb;
+ _rtl92de_update_rxsignalstatistics(hw, pstats);
+ }
+}
+
+static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ if (pstats->rx_mimo_signalquality[stream] != -1) {
+ if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
+ rtlpriv->stats.rx_evm_percentage[stream] =
+ pstats->rx_mimo_signalquality[stream];
+ }
+ rtlpriv->stats.rx_evm_percentage[stream] =
+ ((rtlpriv->stats.rx_evm_percentage[stream]
+ * (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_mimo_signalquality[stream] * 1)) /
+ (RX_SMOOTH_FACTOR);
+ }
+ }
+}
+
+static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 last_evm, tmpval;
+
+ if (pstats->signalquality == 0)
+ return;
+ if (pstats->packet_toself || pstats->packet_beacon) {
+ if (rtlpriv->stats.ui_link_quality.total_num++ >=
+ PHY_LINKQUALITY_SLID_WIN_MAX) {
+ rtlpriv->stats.ui_link_quality.total_num =
+ PHY_LINKQUALITY_SLID_WIN_MAX;
+ last_evm = rtlpriv->stats.ui_link_quality.elements[
+ rtlpriv->stats.ui_link_quality.index];
+ rtlpriv->stats.ui_link_quality.total_val -= last_evm;
+ }
+ rtlpriv->stats.ui_link_quality.total_val +=
+ pstats->signalquality;
+ rtlpriv->stats.ui_link_quality.elements[
+ rtlpriv->stats.ui_link_quality.index++] =
+ pstats->signalquality;
+ if (rtlpriv->stats.ui_link_quality.index >=
+ PHY_LINKQUALITY_SLID_WIN_MAX)
+ rtlpriv->stats.ui_link_quality.index = 0;
+ tmpval = rtlpriv->stats.ui_link_quality.total_val /
+ rtlpriv->stats.ui_link_quality.total_num;
+ rtlpriv->stats.signal_quality = tmpval;
+ rtlpriv->stats.last_sigstrength_inpercent = tmpval;
+ rtl92d_loop_over_streams(hw, pstats);
+ }
+}
+
+static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw,
+ u8 *buffer,
+ struct rtl_stats *pcurrent_stats)
+{
+
+ if (!pcurrent_stats->packet_matchbssid &&
+ !pcurrent_stats->packet_beacon)
+ return;
+
+ _rtl92de_process_ui_rssi(hw, pcurrent_stats);
+ _rtl92de_process_pwdb(hw, pcurrent_stats);
+ _rtl92de_process_ui_link_quality(hw, pcurrent_stats);
+}
+
+static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct rtl_stats *pstats,
+ struct rx_desc_92d *pdesc,
+ struct rx_fwinfo_92d *p_drvinfo)
+{
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct ieee80211_hdr *hdr;
+ u8 *tmp_buf;
+ u8 *praddr;
+ u16 type, cfc;
+ __le16 fc;
+ bool packet_matchbssid, packet_toself, packet_beacon;
+
+ tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
+ hdr = (struct ieee80211_hdr *)tmp_buf;
+ fc = hdr->frame_control;
+ cfc = le16_to_cpu(fc);
+ type = WLAN_FC_GET_TYPE(fc);
+ praddr = hdr->addr1;
+ packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
+ (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
+ hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ?
+ hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) &&
+ (!pstats->crc) && (!pstats->icv));
+ packet_toself = packet_matchbssid &&
+ (!compare_ether_addr(praddr, rtlefuse->dev_addr));
+ if (ieee80211_is_beacon(fc))
+ packet_beacon = true;
+ _rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
+ packet_matchbssid, packet_toself,
+ packet_beacon);
+ _rtl92de_process_phyinfo(hw, tmp_buf, pstats);
+}
+
+bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
+ struct ieee80211_rx_status *rx_status,
+ u8 *p_desc, struct sk_buff *skb)
+{
+ struct rx_fwinfo_92d *p_drvinfo;
+ struct rx_desc_92d *pdesc = (struct rx_desc_92d *)p_desc;
+ u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
+ stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+ stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
+ RX_DRV_INFO_SIZE_UNIT;
+ stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+ stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
+ stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+ stats->hwerror = (stats->crc | stats->icv);
+ stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+ stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
+ stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+ stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+ stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+ && (GET_RX_DESC_FAGGR(pdesc) == 1));
+ stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+ stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+ rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.channel->band;
+ if (GET_RX_DESC_CRC32(pdesc))
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ if (!GET_RX_DESC_SWDEC(pdesc))
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ if (GET_RX_DESC_BW(pdesc))
+ rx_status->flag |= RX_FLAG_40MHZ;
+ if (GET_RX_DESC_RXHT(pdesc))
+ rx_status->flag |= RX_FLAG_HT;
+ rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ 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->mactime = GET_RX_DESC_TSFL(pdesc);
+ if (phystatus) {
+ p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +
+ stats->rx_bufshift);
+ _rtl92de_translate_rx_signal_stuff(hw,
+ skb, stats, pdesc,
+ p_drvinfo);
+ }
+ /*rx_status->qual = stats->signal; */
+ rx_status->signal = stats->rssi + 10;
+ /*rx_status->noise = -stats->noise; */
+ return true;
+}
+
+static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc,
+ u8 *virtualaddress)
+{
+ memset(virtualaddress, 0, 8);
+
+ SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num);
+ SET_EARLYMODE_LEN0(virtualaddress, ptcb_desc->empkt_len[0]);
+ SET_EARLYMODE_LEN1(virtualaddress, ptcb_desc->empkt_len[1]);
+ SET_EARLYMODE_LEN2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF);
+ SET_EARLYMODE_LEN2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4);
+ SET_EARLYMODE_LEN3(virtualaddress, ptcb_desc->empkt_len[3]);
+ SET_EARLYMODE_LEN4(virtualaddress, ptcb_desc->empkt_len[4]);
+}
+
+void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
+ struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+ struct ieee80211_tx_info *info, struct sk_buff *skb,
+ u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct ieee80211_sta *sta = info->control.sta;
+ u8 *pdesc = (u8 *) pdesc_tx;
+ u16 seq_number;
+ __le16 fc = hdr->frame_control;
+ unsigned int buf_len = 0;
+ unsigned int skb_len = skb->len;
+ u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue);
+ bool firstseg = ((hdr->seq_ctrl &
+ cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+ bool lastseg = ((hdr->frame_control &
+ cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+ dma_addr_t mapping;
+ u8 bw_40 = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_STATION) {
+ bw_40 = mac->bw_40;
+ } else if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC) {
+ if (sta)
+ bw_40 = sta->ht_cap.cap &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+ seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+ rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
+ /* reserve 8 byte for AMPDU early mode */
+ if (rtlhal->earlymode_enable) {
+ skb_push(skb, EM_HDR_LEN);
+ memset(skb->data, 0, EM_HDR_LEN);
+ }
+ buf_len = skb->len;
+ mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d));
+ if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+ firstseg = true;
+ lastseg = true;
+ }
+ if (firstseg) {
+ if (rtlhal->earlymode_enable) {
+ SET_TX_DESC_PKT_OFFSET(pdesc, 1);
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN +
+ EM_HDR_LEN);
+ if (ptcb_desc->empkt_num) {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD,
+ ("Insert 8 byte.pTcb->EMPktNum:%d\n",
+ ptcb_desc->empkt_num));
+ _rtl92de_insert_emcontent(ptcb_desc,
+ (u8 *)(skb->data));
+ }
+ } else {
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+ }
+ /* 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;
+ 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)
+ SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
+
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ SET_TX_DESC_AGG_ENABLE(pdesc, 1);
+ SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
+ }
+ SET_TX_DESC_SEQ(pdesc, seq_number);
+ SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
+ !ptcb_desc->cts_enable) ? 1 : 0));
+ SET_TX_DESC_HW_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable
+ || ptcb_desc->cts_enable) ? 1 : 0));
+ SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
+ 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;
+ 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) ?
+ (ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
+ (ptcb_desc->rts_use_shortgi ? 1 : 0)));
+ if (bw_40) {
+ if (ptcb_desc->packet_bw) {
+ SET_TX_DESC_DATA_BW(pdesc, 1);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
+ } else {
+ SET_TX_DESC_DATA_BW(pdesc, 0);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc,
+ mac->cur_40_prime_sc);
+ }
+ } else {
+ SET_TX_DESC_DATA_BW(pdesc, 0);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
+ }
+ SET_TX_DESC_LINIP(pdesc, 0);
+ SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len);
+ if (sta) {
+ u8 ampdu_density = sta->ht_cap.ampdu_density;
+ SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
+ }
+ if (info->control.hw_key) {
+ struct ieee80211_key_conf *keyconf;
+
+ keyconf = info->control.hw_key;
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
+ break;
+ default:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
+ break;
+
+ }
+ }
+ SET_TX_DESC_PKT_ID(pdesc, 0);
+ SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
+ SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
+ SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
+ SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ?
+ 1 : 0);
+ SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
+
+ /* Set TxRate and RTSRate in TxDesc */
+ /* This prevent Tx initial rate of new-coming packets */
+ /* from being overwritten by retried packet rate.*/
+ if (!ptcb_desc->use_driver_rate) {
+ SET_TX_DESC_RTS_RATE(pdesc, 0x08);
+ /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */
+ }
+ if (ieee80211_is_data_qos(fc)) {
+ if (mac->rdg_en) {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ ("Enable RDG function.\n"));
+ SET_TX_DESC_RDG_ENABLE(pdesc, 1);
+ SET_TX_DESC_HTC(pdesc, 1);
+ }
+ }
+ }
+
+ SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
+ SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len);
+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+ if (rtlpriv->dm.useramask) {
+ SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index);
+ SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
+ } else {
+ SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index);
+ SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index);
+ }
+ if (ieee80211_is_data_qos(fc))
+ SET_TX_DESC_QOS(pdesc, 1);
+
+ if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
+ SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+ SET_TX_DESC_PKT_ID(pdesc, 8);
+ }
+ SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
+}
+
+void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
+ u8 *pdesc, bool firstseg,
+ bool lastseg, struct sk_buff *skb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u8 fw_queue = QSLT_BEACON;
+ dma_addr_t mapping = pci_map_single(rtlpci->pdev,
+ skb->data, skb->len, PCI_DMA_TODEVICE);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ __le16 fc = hdr->frame_control;
+
+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
+ if (firstseg)
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+ /* 5G have no CCK rate
+ * Caution: The macros below are multi-line expansions.
+ * The braces are needed no matter what checkpatch says
+ */
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M);
+ } else {
+ SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M);
+ }
+ SET_TX_DESC_SEQ(pdesc, 0);
+ SET_TX_DESC_LINIP(pdesc, 0);
+ SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
+ SET_TX_DESC_FIRST_SEG(pdesc, 1);
+ SET_TX_DESC_LAST_SEG(pdesc, 1);
+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+ SET_TX_DESC_RATE_ID(pdesc, 7);
+ SET_TX_DESC_MACID(pdesc, 0);
+ SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
+ SET_TX_DESC_FIRST_SEG(pdesc, 1);
+ SET_TX_DESC_LAST_SEG(pdesc, 1);
+ SET_TX_DESC_OFFSET(pdesc, 0x20);
+ SET_TX_DESC_USE_RATE(pdesc, 1);
+
+ if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) {
+ SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+ SET_TX_DESC_PKT_ID(pdesc, 8);
+ }
+
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+ "H2C Tx Cmd Content\n", pdesc, TX_DESC_SIZE);
+ wmb();
+ SET_TX_DESC_OWN(pdesc, 1);
+}
+
+void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
+{
+ if (istx) {
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ wmb();
+ SET_TX_DESC_OWN(pdesc, 1);
+ break;
+ case HW_DESC_TX_NEXTDESC_ADDR:
+ SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR txdesc :%d"
+ " not process\n", desc_name));
+ break;
+ }
+ } else {
+ switch (desc_name) {
+ case HW_DESC_RXOWN:
+ wmb();
+ SET_RX_DESC_OWN(pdesc, 1);
+ break;
+ case HW_DESC_RXBUFF_ADDR:
+ SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
+ break;
+ case HW_DESC_RXPKT_LEN:
+ SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
+ break;
+ case HW_DESC_RXERO:
+ SET_RX_DESC_EOR(pdesc, 1);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR rxdesc :%d "
+ "not process\n", desc_name));
+ break;
+ }
+ }
+}
+
+u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name)
+{
+ u32 ret = 0;
+
+ if (istx) {
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ ret = GET_TX_DESC_OWN(p_desc);
+ break;
+ case HW_DESC_TXBUFF_ADDR:
+ ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR txdesc :%d "
+ "not process\n", desc_name));
+ break;
+ }
+ } else {
+ struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ ret = GET_RX_DESC_OWN(pdesc);
+ break;
+ case HW_DESC_RXPKT_LEN:
+ ret = GET_RX_DESC_PKT_LEN(pdesc);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR rxdesc :%d "
+ "not process\n", desc_name));
+ break;
+ }
+ }
+ return ret;
+}
+
+void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ if (hw_queue == BEACON_QUEUE)
+ rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
+ else
+ rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
+ BIT(0) << (hw_queue));
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
new file mode 100644
index 000000000000..992d6766e667
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
@@ -0,0 +1,756 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_TRX_H__
+#define __RTL92DE_TRX_H__
+
+#define TX_DESC_SIZE 64
+#define TX_DESC_AGGR_SUBFRAME_SIZE 32
+
+#define RX_DESC_SIZE 32
+#define RX_DRV_INFO_SIZE_UNIT 8
+
+#define TX_DESC_NEXT_DESC_OFFSET 40
+#define USB_HWDESC_HEADER_LEN 32
+#define CRCLENGTH 4
+
+/* Define a macro that takes a le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \
+ ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \
+ BIT_LEN_MASK_32(__mask))
+
+/* Define a macro that clears a bit field in an le32 word and
+ * sets the specified value into that bit field. The resulting
+ * value remains in le32 ordering; however, it is properly converted
+ * to host ordering for the clear and set operations before conversion
+ * back to le32.
+ */
+
+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \
+ (*(__le32 *)(__pdesc) = \
+ (cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \
+ (~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \
+ (((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
+
+/* macros to read/write various fields in RX or TX descriptors */
+
+#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val)
+#define SET_TX_DESC_OFFSET(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val)
+#define SET_TX_DESC_BMC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val)
+#define SET_TX_DESC_HTC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val)
+#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val)
+#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val)
+#define SET_TX_DESC_LINIP(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val)
+#define SET_TX_DESC_NO_ACM(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val)
+#define SET_TX_DESC_GF(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
+#define SET_TX_DESC_OWN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
+
+#define GET_TX_DESC_PKT_SIZE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 0, 16)
+#define GET_TX_DESC_OFFSET(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 16, 8)
+#define GET_TX_DESC_BMC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 24, 1)
+#define GET_TX_DESC_HTC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 25, 1)
+#define GET_TX_DESC_LAST_SEG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 26, 1)
+#define GET_TX_DESC_FIRST_SEG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 27, 1)
+#define GET_TX_DESC_LINIP(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 28, 1)
+#define GET_TX_DESC_NO_ACM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 29, 1)
+#define GET_TX_DESC_GF(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 30, 1)
+#define GET_TX_DESC_OWN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 31, 1)
+
+#define SET_TX_DESC_MACID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val)
+#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val)
+#define SET_TX_DESC_BK(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val)
+#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val)
+#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val)
+#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val)
+#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val)
+#define SET_TX_DESC_PIFS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val)
+#define SET_TX_DESC_RATE_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val)
+#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val)
+#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val)
+#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val)
+#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 26, 8, __val)
+
+#define GET_TX_DESC_MACID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
+#define GET_TX_DESC_AGG_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 5, 1)
+#define GET_TX_DESC_AGG_BREAK(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 6, 1)
+#define GET_TX_DESC_RDG_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 7, 1)
+#define GET_TX_DESC_QUEUE_SEL(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 8, 5)
+#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 13, 1)
+#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
+#define GET_TX_DESC_PIFS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
+#define GET_TX_DESC_RATE_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
+#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 20, 1)
+#define GET_TX_DESC_EN_DESC_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 21, 1)
+#define GET_TX_DESC_SEC_TYPE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 22, 2)
+#define GET_TX_DESC_PKT_OFFSET(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 24, 8)
+
+#define SET_TX_DESC_RTS_RC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val)
+#define SET_TX_DESC_DATA_RC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val)
+#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val)
+#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val)
+#define SET_TX_DESC_RAW(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val)
+#define SET_TX_DESC_CCX(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val)
+#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val)
+#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val)
+#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val)
+#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 0, 6)
+#define GET_TX_DESC_DATA_RC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 6, 6)
+#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 14, 2)
+#define GET_TX_DESC_MORE_FRAG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 17, 1)
+#define GET_TX_DESC_RAW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 18, 1)
+#define GET_TX_DESC_CCX(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 19, 1)
+#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 20, 3)
+#define GET_TX_DESC_ANTSEL_A(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 24, 1)
+#define GET_TX_DESC_ANTSEL_B(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 25, 1)
+#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 26, 2)
+#define GET_TX_DESC_TX_ANTL(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 28, 2)
+#define GET_TX_DESC_TX_ANT_HT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 30, 2)
+
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val)
+#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val)
+#define SET_TX_DESC_SEQ(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val)
+#define SET_TX_DESC_PKT_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val)
+
+#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 0, 8)
+#define GET_TX_DESC_TAIL_PAGE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 8, 8)
+#define GET_TX_DESC_SEQ(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 16, 12)
+#define GET_TX_DESC_PKT_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 28, 4)
+
+#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val)
+#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val)
+#define SET_TX_DESC_QOS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val)
+#define SET_TX_DESC_USE_RATE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val)
+#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val)
+#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val)
+#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val)
+#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val)
+#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val)
+#define SET_TX_DESC_PORT_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val)
+#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val)
+#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val)
+#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val)
+#define SET_TX_DESC_TX_STBC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val)
+#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val)
+#define SET_TX_DESC_DATA_BW(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val)
+#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val)
+#define SET_TX_DESC_RTS_BW(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val)
+#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val)
+#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RATE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 0, 5)
+#define GET_TX_DESC_AP_DCFE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 5, 1)
+#define GET_TX_DESC_QOS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 6, 1)
+#define GET_TX_DESC_HWSEQ_EN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 7, 1)
+#define GET_TX_DESC_USE_RATE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 8, 1)
+#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 9, 1)
+#define GET_TX_DESC_DISABLE_FB(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 10, 1)
+#define GET_TX_DESC_CTS2SELF(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 11, 1)
+#define GET_TX_DESC_RTS_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 12, 1)
+#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 13, 1)
+#define GET_TX_DESC_PORT_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 14, 1)
+#define GET_TX_DESC_WAIT_DCTS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 18, 1)
+#define GET_TX_DESC_CTS2AP_EN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 19, 1)
+#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 20, 2)
+#define GET_TX_DESC_TX_STBC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 22, 2)
+#define GET_TX_DESC_DATA_SHORT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 24, 1)
+#define GET_TX_DESC_DATA_BW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 25, 1)
+#define GET_TX_DESC_RTS_SHORT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 26, 1)
+#define GET_TX_DESC_RTS_BW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 27, 1)
+#define GET_TX_DESC_RTS_SC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 28, 2)
+#define GET_TX_DESC_RTS_STBC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 30, 2)
+
+#define SET_TX_DESC_TX_RATE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val)
+#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val)
+
+#define GET_TX_DESC_TX_RATE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 0, 6)
+#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 6, 1)
+#define GET_TX_DESC_CCX_TAG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 7, 1)
+#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 8, 5)
+#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 13, 4)
+#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 17, 1)
+#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 18, 6)
+#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 24, 8)
+
+#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val)
+#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val)
+#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val)
+#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val)
+#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val)
+
+#define GET_TX_DESC_TXAGC_A(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 0, 5)
+#define GET_TX_DESC_TXAGC_B(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 5, 5)
+#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 10, 1)
+#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 11, 5)
+#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 16, 4)
+#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 20, 4)
+#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 24, 4)
+#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val)
+#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val)
+#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val)
+#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val)
+#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val)
+
+#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 0, 16)
+#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 16, 4)
+#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 20, 4)
+#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 24, 4)
+#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val)
+#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val)
+
+#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+32, 0, 32)
+#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+36, 0, 32)
+
+#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val)
+#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val)
+
+#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+40, 0, 32)
+#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+44, 0, 32)
+
+#define GET_RX_DESC_PKT_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 0, 14)
+#define GET_RX_DESC_CRC32(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 14, 1)
+#define GET_RX_DESC_ICV(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 15, 1)
+#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 20, 3)
+#define GET_RX_DESC_QOS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 24, 2)
+#define GET_RX_DESC_PHYST(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 27, 1)
+#define GET_RX_DESC_LS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 28, 1)
+#define GET_RX_DESC_FS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 29, 1)
+#define GET_RX_DESC_EOR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 30, 1)
+#define GET_RX_DESC_OWN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 31, 1)
+
+#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val)
+#define SET_RX_DESC_EOR(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
+#define SET_RX_DESC_OWN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
+
+#define GET_RX_DESC_MACID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
+#define GET_RX_DESC_TID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 5, 4)
+#define GET_RX_DESC_HWRSVD(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 9, 5)
+#define GET_RX_DESC_PAGGR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 25, 1)
+#define GET_RX_DESC_MD(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 26, 1)
+#define GET_RX_DESC_MF(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 31, 1)
+#define GET_RX_DESC_SEQ(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 12, 4)
+#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 16, 14)
+#define GET_RX_DESC_NEXT_IND(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 30, 1)
+#define GET_RX_DESC_RSVD(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 31, 1)
+
+#define GET_RX_DESC_RXMCS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 0, 6)
+#define GET_RX_DESC_RXHT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 6, 1)
+#define GET_RX_DESC_SPLCP(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 10, 1)
+#define GET_RX_DESC_HWPC_ERR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 14, 1)
+#define GET_RX_DESC_HWPC_IND(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 15, 1)
+#define GET_RX_DESC_IV0(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 16, 16)
+
+#define GET_RX_DESC_IV1(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 0, 32)
+#define GET_RX_DESC_TSFL(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 0, 32)
+
+#define GET_RX_DESC_BUFF_ADDR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 0, 32)
+#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 0, 32)
+
+#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val)
+#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val)
+
+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \
+do { \
+ if (_size > TX_DESC_NEXT_DESC_OFFSET) \
+ memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \
+ else \
+ 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)
+#define SET_EARLYMODE_LEN0(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr, 4, 12, __value)
+#define SET_EARLYMODE_LEN1(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr, 16, 12, __value)
+#define SET_EARLYMODE_LEN2_1(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr, 28, 4, __value)
+#define SET_EARLYMODE_LEN2_2(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr+4, 0, 8, __value)
+#define SET_EARLYMODE_LEN3(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr+4, 8, 12, __value)
+#define SET_EARLYMODE_LEN4(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr+4, 20, 12, __value)
+
+struct rx_fwinfo_92d {
+ u8 gain_trsw[4];
+ u8 pwdb_all;
+ u8 cfosho[4];
+ u8 cfotail[4];
+ char rxevm[2];
+ char rxsnr[4];
+ u8 pdsnr[2];
+ u8 csi_current[2];
+ u8 csi_target[2];
+ u8 sigevm;
+ u8 max_ex_pwr;
+ u8 ex_intf_flag:1;
+ u8 sgi_en:1;
+ u8 rxsc:2;
+ u8 reserve:4;
+} __packed;
+
+struct tx_desc_92d {
+ u32 pktsize:16;
+ u32 offset:8;
+ u32 bmc:1;
+ u32 htc:1;
+ u32 lastseg:1;
+ u32 firstseg:1;
+ u32 linip:1;
+ u32 noacm:1;
+ u32 gf:1;
+ u32 own:1;
+
+ u32 macid:5;
+ u32 agg_en:1;
+ u32 bk:1;
+ u32 rdg_en:1;
+ u32 queuesel:5;
+ u32 rd_nav_ext:1;
+ u32 lsig_txop_en:1;
+ u32 pifs:1;
+ u32 rateid:4;
+ u32 nav_usehdr:1;
+ u32 en_descid:1;
+ u32 sectype:2;
+ u32 pktoffset:8;
+
+ u32 rts_rc:6;
+ u32 data_rc:6;
+ u32 rsvd0:2;
+ u32 bar_retryht:2;
+ u32 rsvd1:1;
+ u32 morefrag:1;
+ u32 raw:1;
+ u32 ccx:1;
+ u32 ampdudensity:3;
+ u32 rsvd2:1;
+ u32 ant_sela:1;
+ u32 ant_selb:1;
+ u32 txant_cck:2;
+ u32 txant_l:2;
+ u32 txant_ht:2;
+
+ u32 nextheadpage:8;
+ u32 tailpage:8;
+ u32 seq:12;
+ u32 pktid:4;
+
+ u32 rtsrate:5;
+ u32 apdcfe:1;
+ u32 qos:1;
+ u32 hwseq_enable:1;
+ u32 userrate:1;
+ u32 dis_rtsfb:1;
+ u32 dis_datafb:1;
+ u32 cts2self:1;
+ u32 rts_en:1;
+ u32 hwrts_en:1;
+ u32 portid:1;
+ u32 rsvd3:3;
+ u32 waitdcts:1;
+ u32 cts2ap_en:1;
+ u32 txsc:2;
+ u32 stbc:2;
+ u32 txshort:1;
+ u32 txbw:1;
+ u32 rtsshort:1;
+ u32 rtsbw:1;
+ u32 rtssc:2;
+ u32 rtsstbc:2;
+
+ u32 txrate:6;
+ u32 shortgi:1;
+ u32 ccxt:1;
+ u32 txrate_fb_lmt:5;
+ u32 rtsrate_fb_lmt:4;
+ u32 retrylmt_en:1;
+ u32 txretrylmt:6;
+ u32 usb_txaggnum:8;
+
+ u32 txagca:5;
+ u32 txagcb:5;
+ u32 usemaxlen:1;
+ u32 maxaggnum:5;
+ u32 mcsg1maxlen:4;
+ u32 mcsg2maxlen:4;
+ u32 mcsg3maxlen:4;
+ u32 mcs7sgimaxlen:4;
+
+ u32 txbuffersize:16;
+ u32 mcsg4maxlen:4;
+ u32 mcsg5maxlen:4;
+ u32 mcsg6maxlen:4;
+ u32 mcsg15sgimaxlen:4;
+
+ u32 txbuffaddr;
+ u32 txbufferaddr64;
+ u32 nextdescaddress;
+ u32 nextdescaddress64;
+
+ u32 reserve_pass_pcie_mm_limit[4];
+} __packed;
+
+struct rx_desc_92d {
+ u32 length:14;
+ u32 crc32:1;
+ u32 icverror:1;
+ u32 drv_infosize:4;
+ u32 security:3;
+ u32 qos:1;
+ u32 shift:2;
+ u32 phystatus:1;
+ u32 swdec:1;
+ u32 lastseg:1;
+ u32 firstseg:1;
+ u32 eor:1;
+ u32 own:1;
+
+ u32 macid:5;
+ u32 tid:4;
+ u32 hwrsvd:5;
+ u32 paggr:1;
+ u32 faggr:1;
+ u32 a1_fit:4;
+ u32 a2_fit:4;
+ u32 pam:1;
+ u32 pwr:1;
+ u32 moredata:1;
+ u32 morefrag:1;
+ u32 type:2;
+ u32 mc:1;
+ u32 bc:1;
+
+ u32 seq:12;
+ u32 frag:4;
+ u32 nextpktlen:14;
+ u32 nextind:1;
+ u32 rsvd:1;
+
+ u32 rxmcs:6;
+ u32 rxht:1;
+ u32 amsdu:1;
+ u32 splcp:1;
+ u32 bandwidth:1;
+ u32 htc:1;
+ u32 tcpchk_rpt:1;
+ u32 ipcchk_rpt:1;
+ u32 tcpchk_valid:1;
+ u32 hwpcerr:1;
+ u32 hwpcind:1;
+ u32 iv0:16;
+
+ u32 iv1;
+
+ u32 tsfl;
+
+ u32 bufferaddress;
+ u32 bufferaddress64;
+
+} __packed;
+
+void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
+ struct ieee80211_hdr *hdr,
+ u8 *pdesc, struct ieee80211_tx_info *info,
+ struct sk_buff *skb, u8 hw_queue,
+ struct rtl_tcb_desc *ptcb_desc);
+bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,
+ struct rtl_stats *stats,
+ struct ieee80211_rx_status *rx_status,
+ u8 *pdesc, struct sk_buff *skb);
+void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val);
+u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name);
+void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
+void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
+ bool b_firstseg, bool b_lastseg,
+ struct sk_buff *skb);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index da86db86fa4a..4203a8531ca0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -222,7 +222,6 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
u32 low_rssi_thresh = 0;
u32 middle_rssi_thresh = 0;
u32 high_rssi_thresh = 0;
- u8 rssi_level;
struct ieee80211_sta *sta = NULL;
if (is_hal_stop(rtlhal))
@@ -272,18 +271,14 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)high_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_HIGH;
- rssi_level = 1;
} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)middle_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
- rssi_level = 3;
} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)low_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
- rssi_level = 5;
} else {
ra->ratr_state = DM_RATR_STA_ULTRALOW;
- rssi_level = 6;
}
if (ra->pre_ratr_state != ra->ratr_state) {
@@ -457,7 +452,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (digtable.backoff_enable_flag == true)
+ if (digtable.backoff_enable_flag)
rtl92s_backoff_enable_flag(hw);
else
digtable.backoff_val = DM_DIG_BACKOFF;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 3b5af0113d7f..6f91a148c222 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -358,7 +358,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
struct fw_priv *pfw_priv = NULL;
u8 *puc_mappedfile = NULL;
u32 ul_filelength = 0;
- u32 file_length = 0;
u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;
u8 fwstatus = FW_STATUS_INIT;
bool rtstatus = true;
@@ -370,7 +369,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
firmware->fwstatus = FW_STATUS_INIT;
puc_mappedfile = firmware->sz_fw_tmpbuffer;
- file_length = firmware->sz_fw_tmpbufferlen;
/* 1. Retrieve FW header. */
firmware->pfwheader = (struct fw_hdr *) puc_mappedfile;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 2e9005d0454b..d59f66cb7768 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "../efuse.h"
#include "../base.h"
@@ -465,8 +467,7 @@ static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data)
if ((tmpvalue & BIT(6)))
break;
- printk(KERN_ERR "wait for BIT(6) return value %x\n",
- tmpvalue);
+ pr_err("wait for BIT(6) return value %x\n", tmpvalue);
if (waitcount == 0)
break;
@@ -516,7 +517,7 @@ static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw)
mdelay(10);
/* check GPIO3 */
- u1tmp = rtl_read_byte(rtlpriv, GPIO_IN);
+ u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE);
retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF;
return retval;
@@ -884,12 +885,10 @@ static void _rtl92se_hw_configure(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 reg_bw_opmode = 0;
- u32 reg_ratr = 0, reg_rrsr = 0;
+ u32 reg_rrsr = 0;
u8 regtmp = 0;
reg_bw_opmode = BW_OPMODE_20MHZ;
- reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS |
- RATE_ALL_OFDM_2SS;
reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL);
@@ -996,7 +995,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT;
rtlpriv->psc.rfpwr_state = ERFON;
- rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true);
+ /* FIXME: check spinlocks if this block is uncommented */
+ rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason);
} else {
/* gpio radio on/off is out of adapter start */
if (rtlpriv->psc.hwradiooff == false) {
@@ -1107,7 +1107,7 @@ void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (check_bssid == true) {
+ if (check_bssid) {
reg_rcr |= (RCR_CBSSID);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
} else if (check_bssid == false) {
@@ -1122,14 +1122,12 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
- enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
u32 temp;
bt_msr &= ~MSR_LINK_MASK;
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
- ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
("Set Network type to NO LINK!\n"));
break;
@@ -1140,7 +1138,6 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
break;
case NL80211_IFTYPE_STATION:
bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
- ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
("Set Network type to STA!\n"));
break;
@@ -1218,8 +1215,6 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);
/* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */
rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);
-
- rtlpci->irq_enabled = true;
}
void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
@@ -1230,7 +1225,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, INTA_MASK, 0);
rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
- rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
}
@@ -1261,8 +1256,7 @@ static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
if ((tmp & BIT(6)))
break;
- printk(KERN_ERR "wait for BIT(6) return value %x\n",
- tmp);
+ pr_err("wait for BIT(6) return value %x\n", tmp);
if (waitcnt == 0)
break;
@@ -1321,7 +1315,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
if (u1btmp & BIT(7)) {
u1btmp &= ~(BIT(6) | BIT(7));
if (!_rtl92s_set_sysclk(hw, u1btmp)) {
- printk(KERN_ERR "Switch ctrl path fail\n");
+ pr_err("Switch ctrl path fail\n");
return;
}
}
@@ -1655,7 +1649,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
_rtl8192se_get_IC_Inferiority(hw);
@@ -1688,7 +1682,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr)));
+ ("%pM\n", rtlefuse->dev_addr));
/* Get Tx Power Level by Channel */
/* Read Tx power of Channel 1 ~ 14 from EEPROM. */
@@ -2271,7 +2265,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- enum rf_pwrstate rfpwr_toset, cur_rfstate;
+ enum rf_pwrstate rfpwr_toset /*, cur_rfstate */;
unsigned long flag = 0;
bool actuallyset = false;
bool turnonbypowerdomain = false;
@@ -2292,7 +2286,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
}
- cur_rfstate = ppsc->rfpwr_state;
+ /* cur_rfstate = ppsc->rfpwr_state;*/
/* because after _rtl92s_phy_set_rfhalt, all power
* closed, so we must open some power for GPIO check,
@@ -2305,7 +2299,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
rfpwr_toset = _rtl92se_rf_onoff_detect(hw);
- if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) {
+ if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
("RFKILL-HW Radio ON, RF ON\n"));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
index 6d4f66616680..e3fe7c90ebf4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
@@ -90,7 +90,7 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (pcipriv->ledctl.led_opendrain == true)
+ if (pcipriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1)));
else
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 63b45e60a95e..f27171af979c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "../pci.h"
#include "../ps.h"
@@ -180,19 +182,18 @@ u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, readback_value, bitshift;
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
"bitmask(%#x)\n", regaddr, rfpath, bitmask));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);
bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
readback_value = (original_value & bitmask) >> bitshift;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
"bitmask(%#x), original_value(%#x)\n", regaddr, rfpath,
@@ -207,7 +208,6 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 original_value, bitshift;
- unsigned long flags;
if (!((rtlphy->rf_pathmap >> rfpath) & 0x1))
return;
@@ -215,7 +215,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
" data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (bitmask != RFREG_OFFSET_MASK) {
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath,
@@ -226,7 +226,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
_rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data);
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), "
"data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
@@ -263,7 +263,6 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u8 reg_bw_opmode;
- u8 reg_prsr_rsc;
RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n",
rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
@@ -277,7 +276,8 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,
rtlphy->set_bwmode_inprogress = true;
reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE);
- reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2);
+ /* dummy read */
+ rtl_read_byte(rtlpriv, RRSR + 2);
switch (rtlphy->current_chan_bw) {
case HT_CHANNEL_WIDTH_20:
@@ -546,8 +546,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
if (rfpwr_state == ppsc->rfpwr_state)
return false;
- ppsc->set_rfpowerstate_inprogress = true;
-
switch (rfpwr_state) {
case ERFON:{
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -659,8 +657,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
-
return bresult;
}
@@ -1022,8 +1018,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw)
rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB);
if (rtstatus != true) {
- printk(KERN_ERR "_rtl92s_phy_bb_config_parafile(): "
- "AGC Table Fail\n");
+ pr_err("%s(): AGC Table Fail\n", __func__);
goto phy_BB8190_Config_ParaFile_Fail;
}
@@ -1422,7 +1417,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)
break;
case FW_CMD_HIGH_PWR_ENABLE:
if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
- (rtlpriv->dm.dynamic_txpower_enable == true))
+ rtlpriv->dm.dynamic_txpower_enable)
break;
/* CCA threshold */
@@ -1614,7 +1609,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
- (rtlpriv->dm.dynamic_txpower_enable == true))
+ rtlpriv->dm.dynamic_txpower_enable)
fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
if ((digtable.dig_ext_port_stage ==
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
index 0116eaddbfac..ea32ef2d4098 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
@@ -248,12 +248,8 @@
#define PSTIME 0x02E0
#define TIMER0 0x02E4
#define TIMER1 0x02E8
-#define GPIO_CTRL 0x02EC
-#define GPIO_IN 0x02EC
-#define GPIO_OUT 0x02ED
+#define GPIO_IN_SE 0x02EC
#define GPIO_IO_SEL 0x02EE
-#define GPIO_MOD 0x02EF
-#define GPIO_INTCTRL 0x02F0
#define MAC_PINMUX_CFG 0x02F1
#define LEDCFG 0x02F2
#define PHY_REG 0x02F3
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
index 1d3a48330399..0ad50fe44aa2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "../wifi.h"
#include "reg.h"
#include "def.h"
@@ -410,7 +412,7 @@ void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)
(rtlefuse->eeprom_regulatory != 0)))
dont_inc_cck_or_turboscanoff = true;
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
txagc = 0x3f;
if (dont_inc_cck_or_turboscanoff)
txagc = pwrlevel;
@@ -507,7 +509,7 @@ bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw)
}
if (rtstatus != true) {
- printk(KERN_ERR "Radio[%d] Fail!!", rfpath);
+ pr_err("Radio[%d] Fail!!\n", rfpath);
goto fail;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index 1c6cb1d7d660..3876078a63de 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/vmalloc.h>
#include "../wifi.h"
@@ -183,8 +185,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
return 1;
}
- printk(KERN_INFO "rtl8192se: Driver for Realtek RTL8192SE/RTL8191SE\n"
- " Loading firmware %s\n", rtlpriv->cfg->fw_name);
+ pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
+ "Loading firmware %s\n", rtlpriv->cfg->fw_name);
/* request fw */
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
rtlpriv->io.dev);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 5cf442373d46..cffe30851f79 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -581,7 +581,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, cfc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -593,7 +592,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
cfc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
(!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
@@ -663,7 +661,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo *)(skb->data +
stats->rx_bufshift);
_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
@@ -875,6 +873,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
} else { /* H2C Command Desc format (Host TXCMD) */
/* 92SE must set as 1 for firmware download HW DMA error */
@@ -893,6 +892,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
}
@@ -900,9 +900,10 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
{
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
@@ -916,6 +917,7 @@ void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
+ wmb();
SET_RX_STATUS_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
@@ -939,7 +941,7 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
{
u32 ret = 0;
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(desc);
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index a9367eba1ea7..8b1cef0ffde6 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -24,6 +24,9 @@
* Hsinchu 300, Taiwan.
*
*****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/usb.h>
#include "core.h"
#include "wifi.h"
@@ -104,9 +107,8 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
pdata, len, 0); /* max. timeout */
if (status < 0)
- printk(KERN_ERR "reg 0x%x, usbctrl_vendorreq TimeOut! "
- "status:0x%x value=0x%x\n", value, status,
- *(u32 *)pdata);
+ pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n",
+ value, status, *(u32 *)pdata);
return status;
}
@@ -316,7 +318,7 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
rtlusb->usb_rx_segregate_hdl =
rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl;
- printk(KERN_INFO "rtl8192cu: rx_max_size %d, rx_urb_num %d, in_ep %d\n",
+ pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n",
rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep);
init_usb_anchor(&rtlusb->rx_submitted);
return 0;
@@ -580,7 +582,7 @@ static void _rtl_rx_completed(struct urb *_urb)
} else{
/* TO DO */
_rtl_rx_pre_process(hw, skb);
- printk(KERN_ERR "rtlwifi: rx agg not supported\n");
+ pr_err("rx agg not supported\n");
}
goto resubmit;
}
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 693395ee98f9..d3c3ffd38984 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -32,7 +32,6 @@
#include <linux/sched.h>
#include <linux/firmware.h>
-#include <linux/version.h>
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include <linux/usb.h>
@@ -303,9 +302,6 @@ enum hw_variables {
HW_VAR_DATA_FILTER,
};
-#define HWSET_MAX_SIZE 128
-#define EFUSE_MAX_SECTION 16
-
enum _RT_MEDIA_STATUS {
RT_MEDIA_DISCONNECT = 0,
RT_MEDIA_CONNECT = 1
@@ -938,7 +934,7 @@ struct rtl_mac {
int n_channels;
int n_bitrates;
- bool offchan_deley;
+ bool offchan_delay;
/*filters */
u32 rx_conf;
@@ -1188,7 +1184,6 @@ struct rtl_efuse {
struct rtl_ps_ctl {
bool pwrdomain_protect;
- bool set_rfpowerstate_inprogress;
bool in_powersavemode;
bool rfchange_inprogress;
bool swrf_processing;
@@ -1536,6 +1531,7 @@ struct rtl_works {
/* For SW LPS */
struct delayed_work ps_work;
struct delayed_work ps_rfon_wq;
+ struct tasklet_struct ips_leave_tasklet;
};
struct rtl_debug {
@@ -1983,7 +1979,7 @@ static inline u16 rtl_get_tid(struct sk_buff *skb)
static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- u8 *bssid)
+ const u8 *bssid)
{
return ieee80211_find_sta(vif, bssid);
}
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index f51a0241a440..f78694295c39 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -19,6 +19,7 @@
* Copyright (C) 2008 Google Inc
* Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mmc/sdio_func.h>
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c
index af6448c4d3e2..eaa5f9556200 100644
--- a/drivers/net/wireless/wl1251/spi.c
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 35ce7b0f4a60..07bcb1548d8b 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -11,7 +11,6 @@ config WL12XX
depends on WL12XX_MENU && GENERIC_HARDIRQS
depends on INET
select FW_LOADER
- select CRC7
---help---
This module adds support for wireless adapters based on TI wl1271 and
TI wl1273 chipsets. This module does *not* include support for wl1251.
@@ -33,6 +32,7 @@ config WL12XX_HT
config WL12XX_SPI
tristate "TI wl12xx SPI support"
depends on WL12XX && SPI_MASTER
+ select CRC7
---help---
This module adds support for the SPI interface of adapters using
TI wl12xx chipsets. Select this if your platform is using
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index c6ee530e5bf7..7e33f1f4f3d4 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -91,7 +90,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
struct acx_current_tx_power *acx;
int ret;
- wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
+ wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr %d", power);
if (power < 0 || power > 25)
return -EINVAL;
@@ -1068,6 +1067,7 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
mem_conf->tx_free_req = mem->min_req_tx_blocks;
mem_conf->rx_free_req = mem->min_req_rx_blocks;
mem_conf->tx_min = mem->tx_min;
+ mem_conf->fwlog_blocks = wl->conf.fwlog.mem_blocks;
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
sizeof(*mem_conf));
@@ -1577,22 +1577,69 @@ out:
return ret;
}
-int wl1271_acx_max_tx_retry(struct wl1271 *wl)
+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
{
- struct wl1271_acx_max_tx_retry *acx = NULL;
+ struct wl1271_acx_ps_rx_streaming *rx_streaming;
+ u32 conf_queues, enable_queues;
+ int i, ret = 0;
+
+ wl1271_debug(DEBUG_ACX, "acx ps rx streaming");
+
+ rx_streaming = kzalloc(sizeof(*rx_streaming), GFP_KERNEL);
+ if (!rx_streaming) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ conf_queues = wl->conf.rx_streaming.queues;
+ if (enable)
+ enable_queues = conf_queues;
+ else
+ enable_queues = 0;
+
+ for (i = 0; i < 8; i++) {
+ /*
+ * Skip non-changed queues, to avoid redundant acxs.
+ * this check assumes conf.rx_streaming.queues can't
+ * be changed while rx_streaming is enabled.
+ */
+ if (!(conf_queues & BIT(i)))
+ continue;
+
+ rx_streaming->tid = i;
+ rx_streaming->enable = enable_queues & BIT(i);
+ rx_streaming->period = wl->conf.rx_streaming.interval;
+ rx_streaming->timeout = wl->conf.rx_streaming.interval;
+
+ ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING,
+ rx_streaming,
+ sizeof(*rx_streaming));
+ if (ret < 0) {
+ wl1271_warning("acx ps rx streaming failed: %d", ret);
+ goto out;
+ }
+ }
+out:
+ kfree(rx_streaming);
+ return ret;
+}
+
+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
+{
+ struct wl1271_acx_ap_max_tx_retry *acx = NULL;
int ret;
- wl1271_debug(DEBUG_ACX, "acx max tx retry");
+ wl1271_debug(DEBUG_ACX, "acx ap max tx retry");
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx)
return -ENOMEM;
- acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);
+ 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));
if (ret < 0) {
- wl1271_warning("acx max tx retry failed: %d", ret);
+ wl1271_warning("acx ap max tx retry failed: %d", ret);
goto out;
}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 9a895e3cc613..d2eb86eccc04 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -828,6 +828,8 @@ struct wl1271_acx_sta_config_memory {
u8 tx_free_req;
u8 rx_free_req;
u8 tx_min;
+ u8 fwlog_blocks;
+ u8 padding[3];
} __packed;
struct wl1271_acx_mem_map {
@@ -1153,7 +1155,20 @@ struct wl1271_acx_fw_tsf_information {
u8 padding[3];
} __packed;
-struct wl1271_acx_max_tx_retry {
+struct wl1271_acx_ps_rx_streaming {
+ struct acx_header header;
+
+ u8 tid;
+ u8 enable;
+
+ /* interval between triggers (10-100 msec) */
+ u8 period;
+
+ /* timeout before first trigger (0-200 msec) */
+ u8 timeout;
+} __packed;
+
+struct wl1271_acx_ap_max_tx_retry {
struct acx_header header;
/*
@@ -1384,7 +1399,8 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
bool enable);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
-int wl1271_acx_max_tx_retry(struct wl1271 *wl);
+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);
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index b07f8b7e5f11..5ebc64d89407 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -102,6 +102,33 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}
+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))
+ quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+ /* This feature is not yet supported for AP mode */
+ if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
+ quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+ return quirks;
+}
+
static void wl1271_parse_fw_ver(struct wl1271 *wl)
{
int ret;
@@ -116,6 +143,9 @@ static void wl1271_parse_fw_ver(struct wl1271 *wl)
memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
return;
}
+
+ /* Check if any quirks are needed with older fw versions */
+ wl->quirks |= wl12xx_get_fw_ver_quirks(wl);
}
static void wl1271_boot_fw_version(struct wl1271 *wl)
@@ -483,9 +513,12 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
PERIODIC_SCAN_COMPLETE_EVENT_ID;
if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
+ 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;
+ wl->event_mask |= DUMMY_PACKET_EVENT_ID |
+ BA_SESSION_RX_CONSTRAINT_EVENT_ID;
ret = wl1271_event_unmask(wl);
if (ret < 0) {
@@ -748,6 +781,9 @@ 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]);
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 42935ac72663..97dd237a9580 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
@@ -106,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
fail:
WARN_ON(1);
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
return ret;
}
@@ -135,6 +134,11 @@ 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");
@@ -352,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
if (ret != 0) {
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
return ret;
}
@@ -396,10 +400,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
- /* reset TX security counters */
- wl->tx_security_last_seq = 0;
- wl->tx_security_seq = 0;
-
wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
join->basic_rate_set, join->supported_rate_set);
@@ -1080,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)
memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
- cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
+ 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;
@@ -1167,14 +1167,7 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
cmd->bss_index = WL1271_AP_BSS_INDEX;
cmd->aid = sta->aid;
cmd->hlid = hlid;
-
- /*
- * FIXME: Does STA support QOS? We need to propagate this info from
- * hostapd. Currently not that important since this is only used for
- * sending the correct flavor of null-data packet in response to a
- * trigger.
- */
- cmd->wmm = 0;
+ cmd->wmm = sta->wme ? 1 : 0;
cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
sta->supp_rates[wl->band]));
@@ -1230,3 +1223,87 @@ out_free:
out:
return ret;
}
+
+int wl12xx_cmd_config_fwlog(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_config_fwlog *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd config firmware logger");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ 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);
+ if (ret < 0) {
+ wl1271_error("failed to send config firmware logger command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_start_fwlog *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd start firmware logger");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ 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;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_stop_fwlog *cmd;
+ int ret = 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 send stop firmware logger command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 5cac95d9480c..1f7037292c15 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -70,6 +70,9 @@ 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_config_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
enum wl1271_commands {
CMD_INTERROGATE = 1, /*use this to read information elements*/
@@ -107,6 +110,9 @@ enum wl1271_commands {
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,
/* AP mode commands */
CMD_BSS_START = 60,
@@ -575,4 +581,60 @@ struct wl1271_cmd_remove_sta {
u8 padding1;
} __packed;
+/*
+ * Continuous mode - packets are transferred to the host periodically
+ * via the data path.
+ * On demand - Log messages are stored in a cyclic buffer in the
+ * firmware, and only transferred to the host when explicitly requested
+ */
+enum wl12xx_fwlogger_log_mode {
+ WL12XX_FWLOG_CONTINUOUS,
+ WL12XX_FWLOG_ON_DEMAND
+};
+
+/* Include/exclude timestamps from the log messages */
+enum wl12xx_fwlogger_timestamp {
+ WL12XX_FWLOG_TIMESTAMP_DISABLED,
+ WL12XX_FWLOG_TIMESTAMP_ENABLED
+};
+
+/*
+ * Logs can be routed to the debug pinouts (where available), to the host bus
+ * (SDIO/SPI), or dropped
+ */
+enum wl12xx_fwlogger_output {
+ WL12XX_FWLOG_OUTPUT_NONE,
+ WL12XX_FWLOG_OUTPUT_DBG_PINS,
+ WL12XX_FWLOG_OUTPUT_HOST,
+};
+
+struct wl12xx_cmd_config_fwlog {
+ struct wl1271_cmd_header header;
+
+ /* See enum wl12xx_fwlogger_log_mode */
+ u8 logger_mode;
+
+ /* Minimum log level threshold */
+ u8 log_severity;
+
+ /* Include/exclude timestamps from the log messages */
+ u8 timestamp;
+
+ /* See enum wl1271_fwlogger_output */
+ u8 output;
+
+ /* Regulates the frequency of log messages */
+ u8 threshold;
+
+ u8 padding[3];
+} __packed;
+
+struct wl12xx_cmd_start_fwlog {
+ struct wl1271_cmd_header header;
+} __packed;
+
+struct wl12xx_cmd_stop_fwlog {
+ 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 c83fefb6662f..6080e01d92c6 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -713,8 +713,16 @@ struct conf_tx_settings {
/*
* AP-mode - allow this number of TX retries to a station before an
* event is triggered from FW.
+ * In AP-mode the hlids of unreachable stations are given in the
+ * "sta_tx_retry_exceeded" member in the event mailbox.
*/
- u16 ap_max_tx_retries;
+ u8 max_tx_retries;
+
+ /*
+ * AP-mode - after this number of seconds a connected station is
+ * considered inactive.
+ */
+ u16 ap_aging_period;
/*
* Configuration for TID parameters.
@@ -1248,6 +1256,59 @@ struct conf_fm_coex {
u8 swallow_clk_diff;
};
+struct conf_rx_streaming_settings {
+ /*
+ * RX Streaming duration (in msec) from last tx/rx
+ *
+ * Range: u32
+ */
+ u32 duration;
+
+ /*
+ * Bitmap of tids to be polled during RX streaming.
+ * (Note: it doesn't look like it really matters)
+ *
+ * Range: 0x1-0xff
+ */
+ u8 queues;
+
+ /*
+ * RX Streaming interval.
+ * (Note:this value is also used as the rx streaming timeout)
+ * Range: 0 (disabled), 10 - 100
+ */
+ u8 interval;
+
+ /*
+ * enable rx streaming also when there is no coex activity
+ */
+ u8 always;
+};
+
+struct conf_fwlog {
+ /* Continuous or on-demand */
+ u8 mode;
+
+ /*
+ * Number of memory blocks dedicated for the FW logger
+ *
+ * Range: 1-3, or 0 to disable the FW logger
+ */
+ u8 mem_blocks;
+
+ /* Minimum log level threshold */
+ u8 severity;
+
+ /* Include/exclude timestamps from the log messages */
+ u8 timestamp;
+
+ /* See enum wl1271_fwlogger_output */
+ u8 output;
+
+ /* Regulates the frequency of log messages */
+ u8 threshold;
+};
+
struct conf_drv_settings {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
@@ -1263,6 +1324,8 @@ struct conf_drv_settings {
struct conf_memory_settings mem_wl127x;
struct conf_memory_settings mem_wl128x;
struct conf_fm_coex fm_coex;
+ struct conf_rx_streaming_settings rx_streaming;
+ struct conf_fwlog fwlog;
u8 hci_io_ds;
};
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index f1f8df9b6cd7..37934b5601cd 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -30,6 +30,7 @@
#include "acx.h"
#include "ps.h"
#include "io.h"
+#include "tx.h"
/* ms */
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
@@ -71,6 +72,14 @@ static const struct file_operations name## _ops = { \
if (!entry || IS_ERR(entry)) \
goto err; \
+#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \
+ do { \
+ entry = debugfs_create_file(#name, 0400, parent, \
+ wl, &prefix## _## name## _ops); \
+ if (!entry || IS_ERR(entry)) \
+ goto err; \
+ } while (0);
+
#define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \
static ssize_t sub## _ ##name## _read(struct file *file, \
char __user *userbuf, \
@@ -225,7 +234,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
char buf[20];
int res;
- queue_len = wl->tx_queue_count;
+ queue_len = wl1271_tx_total_queue_count(wl);
res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
@@ -298,7 +307,7 @@ static ssize_t start_recovery_write(struct file *file,
struct wl1271 *wl = file->private_data;
mutex_lock(&wl->mutex);
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
mutex_unlock(&wl->mutex);
return count;
@@ -330,10 +339,16 @@ 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);
+ 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_frames_cnt);
DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
- DRIVER_STATE_PRINT_INT(tx_queue_count);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
+ DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
DRIVER_STATE_PRINT_INT(tx_packets_count);
DRIVER_STATE_PRINT_INT(tx_results_count);
DRIVER_STATE_PRINT_LHEX(flags);
@@ -341,7 +356,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
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_security_last_seq);
+ DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
DRIVER_STATE_PRINT_INT(rx_counter);
DRIVER_STATE_PRINT_INT(session_counter);
DRIVER_STATE_PRINT_INT(state);
@@ -527,11 +542,129 @@ static const struct file_operations beacon_interval_ops = {
.llseek = default_llseek,
};
+static ssize_t rx_streaming_interval_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 in rx_streaming_interval!");
+ return -EINVAL;
+ }
+
+ /* valid values: 0, 10-100 */
+ if (value && (value < 10 || value > 100)) {
+ wl1271_warning("value is not in range!");
+ return -ERANGE;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ wl->conf.rx_streaming.interval = value;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ wl1271_recalc_rx_streaming(wl);
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static ssize_t rx_streaming_interval_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ return wl1271_format_buffer(userbuf, count, ppos,
+ "%d\n", wl->conf.rx_streaming.interval);
+}
+
+static const struct file_operations rx_streaming_interval_ops = {
+ .read = rx_streaming_interval_read,
+ .write = rx_streaming_interval_write,
+ .open = wl1271_open_file_generic,
+ .llseek = default_llseek,
+};
+
+static ssize_t rx_streaming_always_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 in rx_streaming_write!");
+ return -EINVAL;
+ }
+
+ /* valid values: 0, 10-100 */
+ if (!(value == 0 || value == 1)) {
+ wl1271_warning("value is not in valid!");
+ return -EINVAL;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ wl->conf.rx_streaming.always = value;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ wl1271_recalc_rx_streaming(wl);
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static ssize_t rx_streaming_always_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ return wl1271_format_buffer(userbuf, count, ppos,
+ "%d\n", wl->conf.rx_streaming.always);
+}
+
+static const struct file_operations rx_streaming_always_ops = {
+ .read = rx_streaming_always_read,
+ .write = rx_streaming_always_write,
+ .open = wl1271_open_file_generic,
+ .llseek = default_llseek,
+};
+
static int wl1271_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
int ret = 0;
- struct dentry *entry, *stats;
+ struct dentry *entry, *stats, *streaming;
stats = debugfs_create_dir("fw-statistics", rootdir);
if (!stats || IS_ERR(stats)) {
@@ -640,6 +773,14 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(dtim_interval, rootdir);
DEBUGFS_ADD(beacon_interval, rootdir);
+ streaming = debugfs_create_dir("rx_streaming", rootdir);
+ if (!streaming || IS_ERR(streaming))
+ goto err;
+
+ DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
+ DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
+
+
return 0;
err:
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index c3c554cd6580..304aaa2ee011 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -133,10 +133,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
if (ret < 0)
break;
- /* enable beacon early termination */
- ret = wl1271_acx_bet_enable(wl, true);
- if (ret < 0)
- break;
+ /*
+ * BET has only a minor effect in 5GHz and masks
+ * channel switch IEs, so we only enable BET on 2.4GHz
+ */
+ if (wl->band == IEEE80211_BAND_2GHZ)
+ /* enable beacon early termination */
+ ret = wl1271_acx_bet_enable(wl, true);
if (wl->ps_compl) {
complete(wl->ps_compl);
@@ -168,6 +171,36 @@ 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)
+{
+ /* 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;
+
+ ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);
+}
+
+static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
+ u8 enable)
+{
+ if (enable) {
+ /* disable dynamic PS when requested by the firmware */
+ ieee80211_disable_dyn_ps(wl->vif);
+ set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
+ } else {
+ ieee80211_enable_dyn_ps(wl->vif);
+ clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
+ wl1271_recalc_rx_streaming(wl);
+ }
+
+}
+
static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
{
wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -181,6 +214,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
u32 vector;
bool beacon_loss = false;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+ bool disconnect_sta = false;
+ unsigned long sta_bitmap = 0;
wl1271_event_mbox_dump(mbox);
@@ -211,14 +246,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
}
}
- /* disable dynamic PS when requested by the firmware */
if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
- wl->bss_type == BSS_TYPE_STA_BSS) {
- if (mbox->soft_gemini_sense_info)
- ieee80211_disable_dyn_ps(wl->vif);
- else
- ieee80211_enable_dyn_ps(wl->vif);
- }
+ wl->bss_type == BSS_TYPE_STA_BSS)
+ wl12xx_event_soft_gemini_sense(wl,
+ mbox->soft_gemini_sense_info);
/*
* The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
@@ -252,12 +283,60 @@ 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) {
+ wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
+ "ba_allowed = 0x%x", mbox->ba_allowed);
+
+ if (wl->vif)
+ wl1271_stop_ba_event(wl, mbox->ba_allowed);
+ }
+
if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif)
wl1271_tx_dummy_packet(wl);
}
+ /*
+ * "TX retries exceeded" has a different meaning according to mode.
+ * In AP mode the offending station is disconnected.
+ */
+ if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) {
+ wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
+ sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
+ disconnect_sta = true;
+ }
+
+ if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
+ wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
+ sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
+ disconnect_sta = true;
+ }
+
+ if (is_ap && disconnect_sta) {
+ u32 num_packets = wl->conf.tx.max_tx_retries;
+ struct ieee80211_sta *sta;
+ const u8 *addr;
+ int h;
+
+ for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS);
+ h < AP_MAX_LINKS;
+ h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
+ if (!wl1271_is_active_sta(wl, h))
+ continue;
+
+ addr = wl->links[h].addr;
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(wl->vif, addr);
+ if (sta) {
+ wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
+ ieee80211_report_low_ack(sta, num_packets);
+ }
+ rcu_read_unlock();
+ }
+ }
+
if (wl->vif && beacon_loss)
ieee80211_connection_loss(wl->vif);
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index b6cf06e565a4..e524ad6fe4e3 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -58,20 +58,23 @@ enum {
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19),
- ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
+ 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),
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),
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),
PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
- BA_SESSION_TEAR_DOWN_EVENT_ID = BIT(30),
+ BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30),
EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
};
@@ -119,10 +122,27 @@ struct event_mailbox {
/* AP FW only */
u8 hlid_removed;
+
+ /* a bitmap of hlids for stations that have been inactive too long */
__le16 sta_aging_status;
+
+ /* a bitmap of hlids for stations which didn't respond to TX */
__le16 sta_tx_retry_exceeded;
- u8 reserved_5[24];
+ /*
+ * 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];
} __packed;
int wl1271_event_unmask(struct wl1271 *wl);
@@ -130,4 +150,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
void wl1271_pspoll_work(struct work_struct *work);
+/* Functions from main.c */
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
+
#endif
diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/wl12xx/ini.h
index 1420c842b8f1..4cf9ecc56212 100644
--- a/drivers/net/wireless/wl12xx/ini.h
+++ b/drivers/net/wireless/wl12xx/ini.h
@@ -24,6 +24,9 @@
#ifndef __INI_H__
#define __INI_H__
+#define GENERAL_SETTINGS_DRPW_LPD 0xc0
+#define SCRATCH_ENABLE_LPD BIT(25)
+
#define WL1271_INI_MAX_SMART_REFLEX_PARAM 16
struct wl1271_ini_general_params {
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index a8f4f156c055..c3e9a2e4410e 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -321,6 +321,20 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
return 0;
}
+static int wl12xx_init_fwlog(struct wl1271 *wl)
+{
+ int ret;
+
+ if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)
+ return 0;
+
+ ret = wl12xx_cmd_config_fwlog(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int wl1271_sta_hw_init(struct wl1271 *wl)
{
int ret;
@@ -382,6 +396,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
+ /* Configure the FW logger */
+ ret = wl12xx_init_fwlog(wl);
+ if (ret < 0)
+ return ret;
+
return 0;
}
@@ -428,7 +447,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_acx_max_tx_retry(wl);
+ ret = wl1271_acx_ap_max_tx_retry(wl);
if (ret < 0)
return ret;
@@ -436,6 +455,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
+ /* initialize Tx power */
+ ret = wl1271_acx_tx_power(wl, wl->power_level);
+ if (ret < 0)
+ return ret;
+
return 0;
}
@@ -541,6 +565,7 @@ static int wl1271_set_ba_policies(struct wl1271 *wl)
/* Reset the BA RX indicators */
wl->ba_rx_bitmap = 0;
+ wl->ba_allowed = true;
/* validate that FW support BA */
wl1271_check_ba_support(wl);
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
index da5c1ad942a4..c2da66f45046 100644
--- a/drivers/net/wireless/wl12xx/io.c
+++ b/drivers/net/wireless/wl12xx/io.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include "wl12xx.h"
@@ -128,12 +127,14 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition);
void wl1271_io_reset(struct wl1271 *wl)
{
- wl->if_ops->reset(wl);
+ if (wl->if_ops->reset)
+ wl->if_ops->reset(wl);
}
void wl1271_io_init(struct wl1271 *wl)
{
- wl->if_ops->init(wl);
+ if (wl->if_ops->init)
+ wl->if_ops->init(wl);
}
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index beed621a8ae0..a2fe4f506ada 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -25,6 +25,7 @@
#ifndef __IO_H__
#define __IO_H__
+#include <linux/irqreturn.h>
#include "reg.h"
#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
@@ -128,6 +129,20 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
wl1271_raw_write(wl, physical, buf, len, fixed);
}
+static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
+ void *buf, size_t len, bool fixed)
+{
+ int physical;
+ int addr;
+
+ /* Addresses are stored internally as addresses to 32 bytes blocks */
+ addr = hwaddr << 5;
+
+ physical = wl1271_translate_addr(wl, addr);
+
+ wl1271_raw_read(wl, physical, buf, len, fixed);
+}
+
static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
{
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e6497dc669df..e58c22d21e39 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/wl12xx.h>
+#include <linux/sched.h>
#include "wl12xx.h"
#include "wl12xx_80211.h"
@@ -209,7 +210,8 @@ static struct conf_drv_settings default_conf = {
.tx_op_limit = 1504,
},
},
- .ap_max_tx_retries = 100,
+ .max_tx_retries = 100,
+ .ap_aging_period = 300,
.tid_conf_count = 4,
.tid_conf = {
[CONF_TX_AC_BE] = {
@@ -362,9 +364,25 @@ static struct conf_drv_settings default_conf = {
.fm_disturbed_band_margin = 0xff, /* default */
.swallow_clk_diff = 0xff, /* default */
},
+ .rx_streaming = {
+ .duration = 150,
+ .queues = 0x1,
+ .interval = 20,
+ .always = 0,
+ },
+ .fwlog = {
+ .mode = WL12XX_FWLOG_ON_DEMAND,
+ .mem_blocks = 2,
+ .severity = 0,
+ .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
+ .output = WL12XX_FWLOG_OUTPUT_HOST,
+ .threshold = 0,
+ },
.hci_io_ds = HCI_IO_DS_6MA,
};
+static char *fwlog_param;
+
static void __wl1271_op_remove_interface(struct wl1271 *wl,
bool reset_tx_queues);
static void wl1271_free_ap_keys(struct wl1271 *wl);
@@ -388,6 +406,22 @@ static struct platform_device wl1271_device = {
static DEFINE_MUTEX(wl_list_mutex);
static LIST_HEAD(wl_list);
+static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
+{
+ int ret;
+ if (operstate != IF_OPER_UP)
+ return 0;
+
+ if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))
+ return 0;
+
+ ret = wl1271_cmd_set_sta_state(wl);
+ if (ret < 0)
+ return ret;
+
+ wl1271_info("Association completed.");
+ return 0;
+}
static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
void *arg)
{
@@ -437,11 +471,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
if (ret < 0)
goto out;
- if ((dev->operstate == IF_OPER_UP) &&
- !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) {
- wl1271_cmd_set_sta_state(wl);
- wl1271_info("Association completed.");
- }
+ wl1271_check_operstate(wl, dev->operstate);
wl1271_ps_elp_sleep(wl);
@@ -473,6 +503,117 @@ static int wl1271_reg_notify(struct wiphy *wiphy,
return 0;
}
+static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable)
+{
+ int ret = 0;
+
+ /* we should hold wl->mutex */
+ ret = wl1271_acx_ps_rx_streaming(wl, enable);
+ if (ret < 0)
+ goto out;
+
+ if (enable)
+ set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+ else
+ clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+out:
+ return ret;
+}
+
+/*
+ * this function is being called when the rx_streaming interval
+ * has beed changed or rx_streaming should be disabled
+ */
+int wl1271_recalc_rx_streaming(struct wl1271 *wl)
+{
+ int ret = 0;
+ int period = wl->conf.rx_streaming.interval;
+
+ /* don't reconfigure if rx_streaming is disabled */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ goto out;
+
+ /* reconfigure/disable according to new streaming_period */
+ if (period &&
+ test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&
+ (wl->conf.rx_streaming.always ||
+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
+ ret = wl1271_set_rx_streaming(wl, true);
+ else {
+ ret = wl1271_set_rx_streaming(wl, false);
+ /* don't cancel_work_sync since we might deadlock */
+ del_timer_sync(&wl->rx_streaming_timer);
+ }
+out:
+ return ret;
+}
+
+static void wl1271_rx_streaming_enable_work(struct work_struct *work)
+{
+ int ret;
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, rx_streaming_enable_work);
+
+ mutex_lock(&wl->mutex);
+
+ if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) ||
+ !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ (!wl->conf.rx_streaming.always &&
+ !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
+ goto out;
+
+ if (!wl->conf.rx_streaming.interval)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_set_rx_streaming(wl, true);
+ if (ret < 0)
+ goto out_sleep;
+
+ /* stop it after some time of inactivity */
+ mod_timer(&wl->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration));
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static void wl1271_rx_streaming_disable_work(struct work_struct *work)
+{
+ int ret;
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, rx_streaming_disable_work);
+
+ mutex_lock(&wl->mutex);
+
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_set_rx_streaming(wl, false);
+ if (ret)
+ goto out_sleep;
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static void wl1271_rx_streaming_timer(unsigned long data)
+{
+ struct wl1271 *wl = (struct wl1271 *)data;
+ ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work);
+}
+
static void wl1271_conf_init(struct wl1271 *wl)
{
@@ -488,8 +629,24 @@ static void wl1271_conf_init(struct wl1271 *wl)
/* apply driver default configuration */
memcpy(&wl->conf, &default_conf, sizeof(default_conf));
-}
+ /* Adjust settings according to optional module parameters */
+ if (fwlog_param) {
+ if (!strcmp(fwlog_param, "continuous")) {
+ wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
+ } else if (!strcmp(fwlog_param, "ondemand")) {
+ wl->conf.fwlog.mode = WL12XX_FWLOG_ON_DEMAND;
+ } else if (!strcmp(fwlog_param, "dbgpins")) {
+ wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
+ wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_DBG_PINS;
+ } else if (!strcmp(fwlog_param, "disable")) {
+ wl->conf.fwlog.mem_blocks = 0;
+ wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_NONE;
+ } else {
+ wl1271_error("Unknown fwlog parameter %s", fwlog_param);
+ }
+ }
+}
static int wl1271_plt_init(struct wl1271 *wl)
{
@@ -667,13 +824,24 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
}
}
+static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl)
+{
+ int i;
+ u32 total_alloc_blocks = 0;
+
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ total_alloc_blocks += wl->tx_allocated_blocks[i];
+
+ return total_alloc_blocks;
+}
+
static void wl1271_fw_status(struct wl1271 *wl,
struct wl1271_fw_full_status *full_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;
+ u32 freed_blocks = 0, ac_freed_blocks;
int i;
if (wl->bss_type == BSS_TYPE_AP_BSS) {
@@ -693,21 +861,23 @@ static void wl1271_fw_status(struct wl1271 *wl,
/* update number of available TX blocks */
for (i = 0; i < NUM_TX_QUEUES; i++) {
- freed_blocks += le32_to_cpu(status->tx_released_blks[i]) -
- wl->tx_blocks_freed[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;
wl->tx_blocks_freed[i] =
le32_to_cpu(status->tx_released_blks[i]);
}
- wl->tx_allocated_blocks -= freed_blocks;
-
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 - wl->tx_allocated_blocks;
+ int avail = full_status->sta.tx_total -
+ wl1271_tx_allocated_blocks(wl);
/*
* The FW might change the total number of TX memblocks before
@@ -741,7 +911,7 @@ static void wl1271_flush_deferred_work(struct wl1271 *wl)
/* Return sent skbs to the network stack */
while ((skb = skb_dequeue(&wl->deferred_tx_queue)))
- ieee80211_tx_status(wl->hw, skb);
+ ieee80211_tx_status_ni(wl->hw, skb);
}
static void wl1271_netstack_work(struct work_struct *work)
@@ -808,7 +978,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
wl1271_error("watchdog interrupt received! "
"starting recovery.");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
/* restarting the chip. ignore any other interrupt. */
goto out;
@@ -822,7 +992,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
/* Check if any tx blocks were freed */
spin_lock_irqsave(&wl->wl_lock, flags);
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
- wl->tx_queue_count) {
+ wl1271_tx_total_queue_count(wl) > 0) {
spin_unlock_irqrestore(&wl->wl_lock, flags);
/*
* In order to avoid starvation of the TX path,
@@ -870,7 +1040,7 @@ out:
/* In case TX was not handled here, queue TX work */
clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
- wl->tx_queue_count)
+ wl1271_tx_total_queue_count(wl) > 0)
ieee80211_queue_work(wl->hw, &wl->tx_work);
spin_unlock_irqrestore(&wl->wl_lock, flags);
@@ -970,6 +1140,89 @@ out:
return ret;
}
+void wl12xx_queue_recovery_work(struct wl1271 *wl)
+{
+ if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
+}
+
+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
+{
+ size_t len = 0;
+
+ /* The FW log is a length-value list, find where the log end */
+ while (len < maxlen) {
+ if (memblock[len] == 0)
+ break;
+ if (len + memblock[len] + 1 > maxlen)
+ break;
+ len += memblock[len] + 1;
+ }
+
+ /* Make sure we have enough room */
+ len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size));
+
+ /* Fill the FW log file, consumed by the sysfs fwlog entry */
+ memcpy(wl->fwlog + wl->fwlog_size, memblock, len);
+ wl->fwlog_size += len;
+
+ return len;
+}
+
+static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
+{
+ u32 addr;
+ u32 first_addr;
+ u8 *block;
+
+ if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
+ (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||
+ (wl->conf.fwlog.mem_blocks == 0))
+ return;
+
+ wl1271_info("Reading FW panic log");
+
+ block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL);
+ if (!block)
+ return;
+
+ /*
+ * Make sure the chip is awake and the logger isn't active.
+ * This might fail if the firmware hanged.
+ */
+ if (!wl1271_ps_elp_wakeup(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);
+ if (!first_addr)
+ goto out;
+
+ /* Traverse the memory blocks linked list */
+ addr = first_addr;
+ do {
+ memset(block, 0, WL12XX_HW_BLOCK_SIZE);
+ wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE,
+ false);
+
+ /*
+ * Memory blocks are linked to one another. The first 4 bytes
+ * 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);
+ if (!wl12xx_copy_fwlog(wl, block + sizeof(addr),
+ WL12XX_HW_BLOCK_SIZE - sizeof(addr)))
+ break;
+ } while (addr && (addr != first_addr));
+
+ wake_up_interruptible(&wl->fwlog_waitq);
+
+out:
+ kfree(block);
+}
+
static void wl1271_recovery_work(struct work_struct *work)
{
struct wl1271 *wl =
@@ -980,9 +1233,23 @@ static void wl1271_recovery_work(struct work_struct *work)
if (wl->state != WL1271_STATE_ON)
goto out;
+ /* Avoid a recursive recovery */
+ set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+
+ wl12xx_read_fwlog_panic(wl);
+
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
+ /*
+ * Advance security sequence number to overcome potential progress
+ * in the firmware during recovery. This doens't hurt if the network is
+ * not encrypted.
+ */
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ 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);
@@ -996,6 +1263,9 @@ static void wl1271_recovery_work(struct work_struct *work)
/* reboot the chipset */
__wl1271_op_remove_interface(wl, false);
+
+ clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+
ieee80211_restart_hw(wl->hw);
/*
@@ -1074,9 +1344,13 @@ 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 should be set in wl127x AP mode */
+ /*
+ * '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;
+ wl->quirks |= (WL12XX_QUIRK_END_OF_TRANSACTION |
+ WL12XX_QUIRK_LPD_MODE);
ret = wl1271_setup(wl);
if (ret < 0)
@@ -1089,6 +1363,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
ret = wl1271_setup(wl);
if (ret < 0)
goto out;
+
if (wl1271_set_block_size(wl))
wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT;
break;
@@ -1117,24 +1392,6 @@ out:
return ret;
}
-static unsigned int wl1271_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;
-
- return quirks;
-}
-
int wl1271_plt_start(struct wl1271 *wl)
{
int retries = WL1271_BOOT_RETRIES;
@@ -1171,8 +1428,6 @@ int wl1271_plt_start(struct wl1271 *wl)
wl1271_notice("firmware booted in PLT mode (%s)",
wl->chip.fw_ver_str);
- /* Check if any quirks are needed with older fw versions */
- wl->quirks |= wl1271_get_fw_ver_quirks(wl);
goto out;
irq_disable:
@@ -1242,26 +1497,27 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1271 *wl = hw->priv;
unsigned long flags;
- int q;
+ int q, mapping;
u8 hlid = 0;
- q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+ mapping = skb_get_queue_mapping(skb);
+ q = wl1271_tx_get_queue(mapping);
if (wl->bss_type == BSS_TYPE_AP_BSS)
hlid = wl1271_tx_get_hlid(skb);
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count++;
+ wl->tx_queue_count[q]++;
/*
* The workqueue is slow to process the tx_queue and we need stop
* the queue here, otherwise the queue will get too long.
*/
- if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
- wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
- ieee80211_stop_queues(wl->hw);
- set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
+ if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
+ wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q);
+ ieee80211_stop_queue(wl->hw, mapping);
+ set_bit(q, &wl->stopped_queues_map);
}
/* queue the packet */
@@ -1287,10 +1543,11 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
int wl1271_tx_dummy_packet(struct wl1271 *wl)
{
unsigned long flags;
+ int 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);
- wl->tx_queue_count++;
+ wl->tx_queue_count[q]++;
spin_unlock_irqrestore(&wl->wl_lock, flags);
/* The FW is low on RX memory blocks, so send the dummy packet asap */
@@ -1352,15 +1609,15 @@ static struct notifier_block wl1271_dev_notifier = {
};
#ifdef CONFIG_PM
-static int wl1271_configure_suspend(struct wl1271 *wl)
+static int wl1271_configure_suspend_sta(struct wl1271 *wl)
{
- int ret;
-
- if (wl->bss_type != BSS_TYPE_STA_BSS)
- return 0;
+ int ret = 0;
mutex_lock(&wl->mutex);
+ if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ goto out_unlock;
+
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out_unlock;
@@ -1403,11 +1660,44 @@ out:
}
+static int wl1271_configure_suspend_ap(struct wl1271 *wl)
+{
+ int ret = 0;
+
+ mutex_lock(&wl->mutex);
+
+ if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ goto out_unlock;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
+ ret = wl1271_acx_set_ap_beacon_filter(wl, true);
+
+ wl1271_ps_elp_sleep(wl);
+out_unlock:
+ mutex_unlock(&wl->mutex);
+ return ret;
+
+}
+
+static int wl1271_configure_suspend(struct wl1271 *wl)
+{
+ if (wl->bss_type == BSS_TYPE_STA_BSS)
+ return wl1271_configure_suspend_sta(wl);
+ if (wl->bss_type == BSS_TYPE_AP_BSS)
+ return wl1271_configure_suspend_ap(wl);
+ return 0;
+}
+
static void wl1271_configure_resume(struct wl1271 *wl)
{
int ret;
+ bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS;
+ bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS;
- if (wl->bss_type != BSS_TYPE_STA_BSS)
+ if (!is_sta && !is_ap)
return;
mutex_lock(&wl->mutex);
@@ -1415,10 +1705,14 @@ static void wl1271_configure_resume(struct wl1271 *wl)
if (ret < 0)
goto out;
- /* exit psm if it wasn't configured */
- if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
- wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- wl->basic_rate, true);
+ if (is_sta) {
+ /* exit psm if it wasn't configured */
+ if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
+ 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_ps_elp_sleep(wl);
out:
@@ -1429,69 +1723,68 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wow)
{
struct wl1271 *wl = hw->priv;
+ int ret;
+
wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
- wl->wow_enabled = !!wow;
- if (wl->wow_enabled) {
- int ret;
- ret = wl1271_configure_suspend(wl);
- if (ret < 0) {
- wl1271_warning("couldn't prepare device to suspend");
- return ret;
- }
- /* flush any remaining work */
- wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
- flush_delayed_work(&wl->scan_complete_work);
+ WARN_ON(!wow || !wow->any);
- /*
- * disable and re-enable interrupts in order to flush
- * the threaded_irq
- */
- wl1271_disable_interrupts(wl);
+ wl->wow_enabled = true;
+ ret = wl1271_configure_suspend(wl);
+ if (ret < 0) {
+ wl1271_warning("couldn't prepare device to suspend");
+ return ret;
+ }
+ /* flush any remaining work */
+ wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
- /*
- * set suspended flag to avoid triggering a new threaded_irq
- * work. no need for spinlock as interrupts are disabled.
- */
- set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+ /*
+ * disable and re-enable interrupts in order to flush
+ * the threaded_irq
+ */
+ wl1271_disable_interrupts(wl);
+
+ /*
+ * set suspended flag to avoid triggering a new threaded_irq
+ * work. no need for spinlock as interrupts are disabled.
+ */
+ set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+
+ wl1271_enable_interrupts(wl);
+ flush_work(&wl->tx_work);
+ flush_delayed_work(&wl->pspoll_work);
+ flush_delayed_work(&wl->elp_work);
- wl1271_enable_interrupts(wl);
- flush_work(&wl->tx_work);
- flush_delayed_work(&wl->pspoll_work);
- flush_delayed_work(&wl->elp_work);
- }
return 0;
}
static int wl1271_op_resume(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
+ unsigned long flags;
+ bool run_irq_work = false;
+
wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
wl->wow_enabled);
+ WARN_ON(!wl->wow_enabled);
/*
* re-enable irq_work enqueuing, and call irq_work directly if
* there is a pending work.
*/
- if (wl->wow_enabled) {
- struct wl1271 *wl = hw->priv;
- unsigned long flags;
- bool run_irq_work = false;
-
- spin_lock_irqsave(&wl->wl_lock, flags);
- clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
- if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
- run_irq_work = true;
- spin_unlock_irqrestore(&wl->wl_lock, flags);
-
- if (run_irq_work) {
- wl1271_debug(DEBUG_MAC80211,
- "run postponed irq_work directly");
- wl1271_irq(0, wl);
- wl1271_enable_interrupts(wl);
- }
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+ if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
+ run_irq_work = true;
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
- wl1271_configure_resume(wl);
+ if (run_irq_work) {
+ wl1271_debug(DEBUG_MAC80211,
+ "run postponed irq_work directly");
+ wl1271_irq(0, wl);
+ wl1271_enable_interrupts(wl);
}
+ wl1271_configure_resume(wl);
+ wl->wow_enabled = false;
return 0;
}
@@ -1629,9 +1922,6 @@ power_off:
strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
sizeof(wiphy->fw_version));
- /* Check if any quirks are needed with older fw versions */
- wl->quirks |= wl1271_get_fw_ver_quirks(wl);
-
/*
* Now we know if 11a is supported (info from the NVS), so disable
* 11a channels if not supported
@@ -1694,6 +1984,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->tx_work);
+ del_timer_sync(&wl->rx_streaming_timer);
+ cancel_work_sync(&wl->rx_streaming_enable_work);
+ cancel_work_sync(&wl->rx_streaming_disable_work);
cancel_delayed_work_sync(&wl->pspoll_work);
cancel_delayed_work_sync(&wl->elp_work);
@@ -1714,11 +2007,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
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->tx_security_last_seq = 0;
- wl->tx_security_seq = 0;
wl->time_offset = 0;
wl->session_counter = 0;
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
@@ -1737,8 +2027,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
*/
wl->flags = 0;
- for (i = 0; i < NUM_TX_QUEUES; i++)
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
wl->tx_blocks_freed[i] = 0;
+ wl->tx_allocated_blocks[i] = 0;
+ }
wl1271_debugfs_reset(wl);
@@ -1891,6 +2183,10 @@ static int wl1271_unjoin(struct wl1271 *wl)
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);
@@ -1983,6 +2279,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wl->channel = channel;
}
+ if ((changed & IEEE80211_CONF_CHANGE_POWER))
+ wl->power_level = conf->power_level;
+
goto out;
}
@@ -2490,6 +2789,44 @@ out:
return ret;
}
+static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan");
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ if (wl->scan.state != WL1271_SCAN_STATE_DONE) {
+ ret = wl1271_scan_stop(wl);
+ if (ret < 0)
+ goto out_sleep;
+ }
+ 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, true);
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+
+ cancel_delayed_work_sync(&wl->scan_complete_work);
+}
+
static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
@@ -2780,24 +3117,6 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
}
}
- if (changed & BSS_CHANGED_IBSS) {
- wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
- bss_conf->ibss_joined);
-
- 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);
-
- /* by default, use 11b rates */
- wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
- ret = wl1271_acx_sta_rate_policies(wl);
- if (ret < 0)
- goto out;
- }
- }
-
ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
if (ret < 0)
goto out;
@@ -3023,6 +3342,24 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
}
}
+ if (changed & BSS_CHANGED_IBSS) {
+ wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
+ bss_conf->ibss_joined);
+
+ 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);
+
+ /* by default, use 11b rates */
+ wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
+ ret = wl1271_acx_sta_rate_policies(wl);
+ if (ret < 0)
+ goto out;
+ }
+ }
+
ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
if (ret < 0)
goto out;
@@ -3061,6 +3398,7 @@ 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));
}
out:
@@ -3251,6 +3589,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
__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);
+}
+
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@@ -3354,9 +3698,12 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
+ wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu: Rx tid %d action %d",
+ tid, action);
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
- if (wl->ba_support) {
+ if ((wl->ba_support) && (wl->ba_allowed)) {
ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
true);
if (!ret)
@@ -3406,7 +3753,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
goto out;
/* packets are considered pending if in the TX queue or the FW */
- ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0);
+ ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0);
/* the above is appropriate for STA mode for PS purposes */
WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
@@ -3569,40 +3916,40 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {
/* 5 GHz band channels for WL1273 */
static struct ieee80211_channel wl1271_channels_5ghz[] = {
- { .hw_value = 7, .center_freq = 5035},
- { .hw_value = 8, .center_freq = 5040},
- { .hw_value = 9, .center_freq = 5045},
- { .hw_value = 11, .center_freq = 5055},
- { .hw_value = 12, .center_freq = 5060},
- { .hw_value = 16, .center_freq = 5080},
- { .hw_value = 34, .center_freq = 5170},
- { .hw_value = 36, .center_freq = 5180},
- { .hw_value = 38, .center_freq = 5190},
- { .hw_value = 40, .center_freq = 5200},
- { .hw_value = 42, .center_freq = 5210},
- { .hw_value = 44, .center_freq = 5220},
- { .hw_value = 46, .center_freq = 5230},
- { .hw_value = 48, .center_freq = 5240},
- { .hw_value = 52, .center_freq = 5260},
- { .hw_value = 56, .center_freq = 5280},
- { .hw_value = 60, .center_freq = 5300},
- { .hw_value = 64, .center_freq = 5320},
- { .hw_value = 100, .center_freq = 5500},
- { .hw_value = 104, .center_freq = 5520},
- { .hw_value = 108, .center_freq = 5540},
- { .hw_value = 112, .center_freq = 5560},
- { .hw_value = 116, .center_freq = 5580},
- { .hw_value = 120, .center_freq = 5600},
- { .hw_value = 124, .center_freq = 5620},
- { .hw_value = 128, .center_freq = 5640},
- { .hw_value = 132, .center_freq = 5660},
- { .hw_value = 136, .center_freq = 5680},
- { .hw_value = 140, .center_freq = 5700},
- { .hw_value = 149, .center_freq = 5745},
- { .hw_value = 153, .center_freq = 5765},
- { .hw_value = 157, .center_freq = 5785},
- { .hw_value = 161, .center_freq = 5805},
- { .hw_value = 165, .center_freq = 5825},
+ { .hw_value = 7, .center_freq = 5035, .max_power = 25 },
+ { .hw_value = 8, .center_freq = 5040, .max_power = 25 },
+ { .hw_value = 9, .center_freq = 5045, .max_power = 25 },
+ { .hw_value = 11, .center_freq = 5055, .max_power = 25 },
+ { .hw_value = 12, .center_freq = 5060, .max_power = 25 },
+ { .hw_value = 16, .center_freq = 5080, .max_power = 25 },
+ { .hw_value = 34, .center_freq = 5170, .max_power = 25 },
+ { .hw_value = 36, .center_freq = 5180, .max_power = 25 },
+ { .hw_value = 38, .center_freq = 5190, .max_power = 25 },
+ { .hw_value = 40, .center_freq = 5200, .max_power = 25 },
+ { .hw_value = 42, .center_freq = 5210, .max_power = 25 },
+ { .hw_value = 44, .center_freq = 5220, .max_power = 25 },
+ { .hw_value = 46, .center_freq = 5230, .max_power = 25 },
+ { .hw_value = 48, .center_freq = 5240, .max_power = 25 },
+ { .hw_value = 52, .center_freq = 5260, .max_power = 25 },
+ { .hw_value = 56, .center_freq = 5280, .max_power = 25 },
+ { .hw_value = 60, .center_freq = 5300, .max_power = 25 },
+ { .hw_value = 64, .center_freq = 5320, .max_power = 25 },
+ { .hw_value = 100, .center_freq = 5500, .max_power = 25 },
+ { .hw_value = 104, .center_freq = 5520, .max_power = 25 },
+ { .hw_value = 108, .center_freq = 5540, .max_power = 25 },
+ { .hw_value = 112, .center_freq = 5560, .max_power = 25 },
+ { .hw_value = 116, .center_freq = 5580, .max_power = 25 },
+ { .hw_value = 120, .center_freq = 5600, .max_power = 25 },
+ { .hw_value = 124, .center_freq = 5620, .max_power = 25 },
+ { .hw_value = 128, .center_freq = 5640, .max_power = 25 },
+ { .hw_value = 132, .center_freq = 5660, .max_power = 25 },
+ { .hw_value = 136, .center_freq = 5680, .max_power = 25 },
+ { .hw_value = 140, .center_freq = 5700, .max_power = 25 },
+ { .hw_value = 149, .center_freq = 5745, .max_power = 25 },
+ { .hw_value = 153, .center_freq = 5765, .max_power = 25 },
+ { .hw_value = 157, .center_freq = 5785, .max_power = 25 },
+ { .hw_value = 161, .center_freq = 5805, .max_power = 25 },
+ { .hw_value = 165, .center_freq = 5825, .max_power = 25 },
};
/* mapping to indexes for wl1271_rates_5ghz */
@@ -3663,6 +4010,7 @@ static const struct ieee80211_ops wl1271_ops = {
.tx = wl1271_op_tx,
.set_key = wl1271_op_set_key,
.hw_scan = wl1271_op_hw_scan,
+ .cancel_hw_scan = wl1271_op_cancel_hw_scan,
.sched_scan_start = wl1271_op_sched_scan_start,
.sched_scan_stop = wl1271_op_sched_scan_stop,
.bss_info_changed = wl1271_op_bss_info_changed,
@@ -3781,6 +4129,69 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR,
wl1271_sysfs_show_hw_pg_ver, NULL);
+static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct wl1271 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+ int ret;
+
+ ret = mutex_lock_interruptible(&wl->mutex);
+ if (ret < 0)
+ return -ERESTARTSYS;
+
+ /* Let only one thread read the log at a time, blocking others */
+ while (wl->fwlog_size == 0) {
+ DEFINE_WAIT(wait);
+
+ prepare_to_wait_exclusive(&wl->fwlog_waitq,
+ &wait,
+ TASK_INTERRUPTIBLE);
+
+ if (wl->fwlog_size != 0) {
+ finish_wait(&wl->fwlog_waitq, &wait);
+ break;
+ }
+
+ mutex_unlock(&wl->mutex);
+
+ schedule();
+ finish_wait(&wl->fwlog_waitq, &wait);
+
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ ret = mutex_lock_interruptible(&wl->mutex);
+ if (ret < 0)
+ return -ERESTARTSYS;
+ }
+
+ /* Check if the fwlog is still valid */
+ if (wl->fwlog_size < 0) {
+ mutex_unlock(&wl->mutex);
+ return 0;
+ }
+
+ /* Seeking is not supported - old logs are not kept. Disregard pos. */
+ len = min(count, (size_t)wl->fwlog_size);
+ wl->fwlog_size -= len;
+ memcpy(buffer, wl->fwlog, len);
+
+ /* Make room for new messages */
+ memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size);
+
+ mutex_unlock(&wl->mutex);
+
+ return len;
+}
+
+static struct bin_attribute fwlog_attr = {
+ .attr = {.name = "fwlog", .mode = S_IRUSR},
+ .read = wl1271_sysfs_read_fwlog,
+};
+
int wl1271_register_hw(struct wl1271 *wl)
{
int ret;
@@ -3961,6 +4372,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
INIT_WORK(&wl->tx_work, wl1271_tx_work);
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+ INIT_WORK(&wl->rx_streaming_enable_work,
+ wl1271_rx_streaming_enable_work);
+ INIT_WORK(&wl->rx_streaming_disable_work,
+ wl1271_rx_streaming_disable_work);
+
+ wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
+ if (!wl->freezable_wq) {
+ ret = -ENOMEM;
+ goto err_hw;
+ }
+
wl->channel = WL1271_DEFAULT_CHANNEL;
wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
wl->default_key = 0;
@@ -3986,6 +4408,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->quirks = 0;
wl->platform_quirks = 0;
wl->sched_scanning = false;
+ wl->tx_security_seq = 0;
+ wl->tx_security_last_seq_lsb = 0;
+
+ setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
+ (unsigned long) wl);
+ wl->fwlog_size = 0;
+ init_waitqueue_head(&wl->fwlog_waitq);
memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
@@ -4003,7 +4432,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
if (!wl->aggr_buf) {
ret = -ENOMEM;
- goto err_hw;
+ goto err_wq;
}
wl->dummy_packet = wl12xx_alloc_dummy_packet(wl);
@@ -4012,11 +4441,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
goto err_aggr;
}
+ /* Allocate one page for the FW log */
+ wl->fwlog = (u8 *)get_zeroed_page(GFP_KERNEL);
+ if (!wl->fwlog) {
+ ret = -ENOMEM;
+ goto err_dummy_packet;
+ }
+
/* Register platform device */
ret = platform_device_register(wl->plat_dev);
if (ret) {
wl1271_error("couldn't register platform device");
- goto err_dummy_packet;
+ goto err_fwlog;
}
dev_set_drvdata(&wl->plat_dev->dev, wl);
@@ -4034,20 +4470,36 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
goto err_bt_coex_state;
}
+ /* Create sysfs file for the FW log */
+ ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr);
+ if (ret < 0) {
+ wl1271_error("failed to create sysfs file fwlog");
+ goto err_hw_pg_ver;
+ }
+
return hw;
+err_hw_pg_ver:
+ device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver);
+
err_bt_coex_state:
device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);
err_platform:
platform_device_unregister(wl->plat_dev);
+err_fwlog:
+ free_page((unsigned long)wl->fwlog);
+
err_dummy_packet:
dev_kfree_skb(wl->dummy_packet);
err_aggr:
free_pages((unsigned long)wl->aggr_buf, order);
+err_wq:
+ destroy_workqueue(wl->freezable_wq);
+
err_hw:
wl1271_debugfs_exit(wl);
kfree(plat_dev);
@@ -4063,7 +4515,15 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
int wl1271_free_hw(struct wl1271 *wl)
{
+ /* Unblock any fwlog readers */
+ mutex_lock(&wl->mutex);
+ wl->fwlog_size = -1;
+ wake_up_interruptible_all(&wl->fwlog_waitq);
+ mutex_unlock(&wl->mutex);
+
+ device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr);
platform_device_unregister(wl->plat_dev);
+ free_page((unsigned long)wl->fwlog);
dev_kfree_skb(wl->dummy_packet);
free_pages((unsigned long)wl->aggr_buf,
get_order(WL1271_AGGR_BUFFER_SIZE));
@@ -4078,6 +4538,7 @@ int wl1271_free_hw(struct wl1271 *wl)
kfree(wl->fw_status);
kfree(wl->tx_res_if);
+ destroy_workqueue(wl->freezable_wq);
ieee80211_free_hw(wl->hw);
@@ -4090,6 +4551,10 @@ EXPORT_SYMBOL_GPL(wl12xx_debug_level);
module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
+module_param_named(fwlog, fwlog_param, charp, 0);
+MODULE_PARM_DESC(keymap,
+ "FW logger options: continuous, ondemand, dbgpins or disable");
+
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 b59b67711a17..3548377ab9c2 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
if (ret == 0) {
wl1271_error("ELP wakeup timeout!");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
ret = -ETIMEDOUT;
goto err;
} else if (ret < 0) {
@@ -169,9 +169,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
wl1271_debug(DEBUG_PSM, "leaving psm");
/* disable beacon early termination */
- ret = wl1271_acx_bet_enable(wl, false);
- if (ret < 0)
- return ret;
+ if (wl->band == IEEE80211_BAND_2GHZ) {
+ ret = wl1271_acx_bet_enable(wl, false);
+ if (ret < 0)
+ return ret;
+ }
/* disable beacon filtering */
ret = wl1271_acx_beacon_filter_opt(wl, false);
@@ -191,24 +193,27 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
{
- int i, filtered = 0;
+ int i;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
unsigned long flags;
+ int filtered[NUM_TX_QUEUES];
/* filter all frames currently the low level queus for this hlid */
for (i = 0; i < NUM_TX_QUEUES; i++) {
+ filtered[i] = 0;
while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
info->status.rates[0].idx = -1;
- ieee80211_tx_status(wl->hw, skb);
- filtered++;
+ ieee80211_tx_status_ni(wl->hw, skb);
+ filtered[i]++;
}
}
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count -= filtered;
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_queue_count[i] -= filtered[i];
spin_unlock_irqrestore(&wl->wl_lock, flags);
wl1271_handle_tx_low_watermark(wl);
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 70091035e019..0450fb49dbb1 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -22,6 +22,7 @@
*/
#include <linux/gfp.h>
+#include <linux/sched.h>
#include "wl12xx.h"
#include "acx.h"
@@ -95,6 +96,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
struct ieee80211_hdr *hdr;
u8 *buf;
u8 beacon = 0;
+ u8 is_data = 0;
/*
* In PLT mode we seem to get frames and mac80211 warns about them,
@@ -106,6 +108,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) data;
+ if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) {
+ size_t len = length - sizeof(*desc);
+ wl12xx_copy_fwlog(wl, data + sizeof(*desc), len);
+ wake_up_interruptible(&wl->fwlog_waitq);
+ return 0;
+ }
+
switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {
/* discard corrupted packets */
case WL1271_RX_DESC_DRIVER_RX_Q_FAIL:
@@ -137,6 +146,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_beacon(hdr->frame_control))
beacon = 1;
+ if (ieee80211_is_data_present(hdr->frame_control))
+ is_data = 1;
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
@@ -147,9 +158,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
skb_trim(skb, skb->len - desc->pad_len);
skb_queue_tail(&wl->deferred_rx_queue, skb);
- ieee80211_queue_work(wl->hw, &wl->netstack_work);
+ queue_work(wl->freezable_wq, &wl->netstack_work);
- return 0;
+ return is_data;
}
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
@@ -162,6 +173,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
u32 mem_block;
u32 pkt_length;
u32 pkt_offset;
+ bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+ bool had_data = false;
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
@@ -214,9 +227,11 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
* conditions, in that case the received frame will just
* be dropped.
*/
- wl1271_rx_handle_data(wl,
- wl->aggr_buf + pkt_offset,
- pkt_length);
+ if (wl1271_rx_handle_data(wl,
+ wl->aggr_buf + pkt_offset,
+ pkt_length) == 1)
+ had_data = true;
+
wl->rx_counter++;
drv_rx_counter++;
drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
@@ -230,6 +245,20 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
*/
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+
+ if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+ (wl->conf.rx_streaming.always ||
+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
+ u32 timeout = wl->conf.rx_streaming.duration;
+
+ /* restart rx streaming */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ ieee80211_queue_work(wl->hw,
+ &wl->rx_streaming_enable_work);
+
+ mod_timer(&wl->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ }
}
void wl1271_set_default_filters(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index 75fabf836491..c88e3fa1d603 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -97,6 +97,18 @@
#define RX_BUF_SIZE_MASK 0xFFF00
#define RX_BUF_SIZE_SHIFT_DIV 6
+enum {
+ WL12XX_RX_CLASS_UNKNOWN,
+ WL12XX_RX_CLASS_MANAGEMENT,
+ WL12XX_RX_CLASS_DATA,
+ WL12XX_RX_CLASS_QOS_DATA,
+ WL12XX_RX_CLASS_BCN_PRBRSP,
+ WL12XX_RX_CLASS_EAPOL,
+ WL12XX_RX_CLASS_BA_EVENT,
+ WL12XX_RX_CLASS_AMSDU,
+ WL12XX_RX_CLASS_LOGGER,
+};
+
struct wl1271_rx_descriptor {
__le16 length;
u8 status;
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 56f76abc754d..edfe01c321ca 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -62,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
if (wl->scan.failed) {
wl1271_info("Scan completed due to error.");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
}
out:
@@ -321,12 +321,39 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
return 0;
}
+int wl1271_scan_stop(struct wl1271 *wl)
+{
+ struct wl1271_cmd_header *cmd = NULL;
+ int ret = 0;
+
+ if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE))
+ return -EINVAL;
+
+ wl1271_debug(DEBUG_CMD, "cmd scan stop");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd,
+ sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("cmd stop_scan failed");
+ goto out;
+ }
+out:
+ kfree(cmd);
+ return ret;
+}
+
static int
wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct conn_scan_ch_params *channels,
u32 band, bool radar, bool passive,
- int start)
+ int start, int max_channels)
{
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
int i, j;
@@ -334,7 +361,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
bool force_passive = !req->n_ssids;
for (i = 0, j = start;
- i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS;
+ i < req->n_channels && j < max_channels;
i++) {
flags = req->channels[i]->flags;
@@ -380,46 +407,42 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
return j - start;
}
-static int
+static bool
wl1271_scan_sched_scan_channels(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct wl1271_cmd_sched_scan_config *cfg)
{
- int idx = 0;
-
cfg->passive[0] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,
IEEE80211_BAND_2GHZ,
- false, true, idx);
- idx += cfg->passive[0];
-
+ false, true, 0,
+ MAX_CHANNELS_2GHZ);
cfg->active[0] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,
IEEE80211_BAND_2GHZ,
- false, false, idx);
- /*
- * 5GHz channels always start at position 14, not immediately
- * after the last 2.4GHz channel
- */
- idx = 14;
-
+ false, false,
+ cfg->passive[0],
+ MAX_CHANNELS_2GHZ);
cfg->passive[1] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
IEEE80211_BAND_5GHZ,
- false, true, idx);
- idx += cfg->passive[1];
-
+ false, true, 0,
+ MAX_CHANNELS_5GHZ);
cfg->dfs =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
IEEE80211_BAND_5GHZ,
- true, true, idx);
- idx += cfg->dfs;
-
+ true, true,
+ cfg->passive[1],
+ MAX_CHANNELS_5GHZ);
cfg->active[1] =
- wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+ wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
IEEE80211_BAND_5GHZ,
- false, false, idx);
- idx += cfg->active[1];
+ false, false,
+ cfg->passive[1] + cfg->dfs,
+ MAX_CHANNELS_5GHZ);
+ /* 802.11j channels are not supported yet */
+ cfg->passive[2] = 0;
+ cfg->active[2] = 0;
wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d",
cfg->active[0], cfg->passive[0]);
@@ -427,7 +450,9 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg->active[1], cfg->passive[1]);
wl1271_debug(DEBUG_SCAN, " DFS: %d", cfg->dfs);
- return idx;
+ return cfg->passive[0] || cfg->active[0] ||
+ cfg->passive[1] || cfg->active[1] || cfg->dfs ||
+ cfg->passive[2] || cfg->active[2];
}
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
@@ -436,7 +461,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
{
struct wl1271_cmd_sched_scan_config *cfg = NULL;
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
- int i, total_channels, ret;
+ int i, ret;
bool force_passive = !req->n_ssids;
wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
@@ -471,8 +496,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
cfg->ssid_len = 0;
}
- total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg);
- if (total_channels == 0) {
+ if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
wl1271_error("scan channel list is empty");
ret = -EINVAL;
goto out;
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h
index a0b6c5d67b07..d882e4da71b7 100644
--- a/drivers/net/wireless/wl12xx/scan.h
+++ b/drivers/net/wireless/wl12xx/scan.h
@@ -28,6 +28,7 @@
int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
struct cfg80211_scan_request *req);
+int wl1271_scan_stop(struct wl1271 *wl);
int wl1271_scan_build_probe_req(struct wl1271 *wl,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band);
@@ -112,19 +113,14 @@ struct wl1271_cmd_trigger_scan_to {
__le32 timeout;
} __packed;
-#define MAX_CHANNELS_ALL_BANDS 41
+#define MAX_CHANNELS_2GHZ 14
+#define MAX_CHANNELS_5GHZ 23
+#define MAX_CHANNELS_4GHZ 4
+
#define SCAN_MAX_CYCLE_INTERVALS 16
#define SCAN_MAX_BANDS 3
enum {
- SCAN_CHANNEL_TYPE_2GHZ_PASSIVE,
- SCAN_CHANNEL_TYPE_2GHZ_ACTIVE,
- SCAN_CHANNEL_TYPE_5GHZ_PASSIVE,
- SCAN_CHANNEL_TYPE_5GHZ_ACTIVE,
- SCAN_CHANNEL_TYPE_5GHZ_DFS,
-};
-
-enum {
SCAN_SSID_FILTER_ANY = 0,
SCAN_SSID_FILTER_SPECIFIC = 1,
SCAN_SSID_FILTER_LIST = 2,
@@ -182,7 +178,9 @@ struct wl1271_cmd_sched_scan_config {
u8 padding[3];
- struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS];
+ struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ];
+ struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ];
+ struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];
} __packed;
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 536e5065454b..5cf18c2c23f0 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -23,7 +23,6 @@
#include <linux/irq.h>
#include <linux/module.h>
-#include <linux/crc7.h>
#include <linux/vmalloc.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
@@ -45,7 +44,7 @@
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
#endif
-static const struct sdio_device_id wl1271_devices[] = {
+static const struct sdio_device_id wl1271_devices[] __devinitconst = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
{}
};
@@ -107,14 +106,6 @@ static void wl1271_sdio_enable_interrupts(struct wl1271 *wl)
enable_irq(wl->irq);
}
-static void wl1271_sdio_reset(struct wl1271 *wl)
-{
-}
-
-static void wl1271_sdio_init(struct wl1271 *wl)
-{
-}
-
static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
{
@@ -170,15 +161,17 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
struct sdio_func *func = wl_to_func(wl);
int ret;
- /* Make sure the card will not be powered off by runtime PM */
- ret = pm_runtime_get_sync(&func->dev);
- if (ret < 0)
- goto out;
-
- /* Runtime PM might be disabled, so power up the card manually */
- ret = mmc_power_restore_host(func->card->host);
- if (ret < 0)
- goto out;
+ /* If enabled, tell runtime PM not to power off the card */
+ if (pm_runtime_enabled(&func->dev)) {
+ ret = pm_runtime_get_sync(&func->dev);
+ if (ret)
+ goto out;
+ } else {
+ /* Runtime PM is 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);
@@ -195,13 +188,16 @@ static int wl1271_sdio_power_off(struct wl1271 *wl)
sdio_disable_func(func);
sdio_release_host(func);
- /* Runtime PM might be disabled, so power off the card manually */
+ /* Power off the card manually, even if runtime PM is enabled. */
ret = mmc_power_save_host(func->card->host);
if (ret < 0)
return ret;
- /* Let runtime PM know the card is powered off */
- return pm_runtime_put_sync(&func->dev);
+ /* If enabled, let runtime PM know the card is powered off */
+ if (pm_runtime_enabled(&func->dev))
+ ret = pm_runtime_put_sync(&func->dev);
+
+ return ret;
}
static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
@@ -215,8 +211,6 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
static struct wl1271_if_operations sdio_ops = {
.read = wl1271_sdio_raw_read,
.write = wl1271_sdio_raw_write,
- .reset = wl1271_sdio_reset,
- .init = wl1271_sdio_init,
.power = wl1271_sdio_set_power,
.dev = wl1271_sdio_wl_to_dev,
.enable_irq = wl1271_sdio_enable_interrupts,
@@ -278,17 +272,19 @@ static int __devinit wl1271_probe(struct sdio_func *func,
goto out_free;
}
- enable_irq_wake(wl->irq);
- device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);
+ ret = enable_irq_wake(wl->irq);
+ if (!ret) {
+ wl->irq_wake_enabled = true;
+ device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);
- disable_irq(wl->irq);
-
- /* if sdio can keep power while host is suspended, enable wow */
- mmcflags = sdio_get_host_pm_caps(func);
- wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);
+ /* if sdio can keep power while host is suspended, enable wow */
+ mmcflags = sdio_get_host_pm_caps(func);
+ wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);
- if (mmcflags & MMC_PM_KEEP_POWER)
- hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+ if (mmcflags & MMC_PM_KEEP_POWER)
+ hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+ }
+ disable_irq(wl->irq);
ret = wl1271_init_ieee80211(wl);
if (ret)
@@ -303,8 +299,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle(&func->dev);
- wl1271_notice("initialized");
-
return 0;
out_irq:
@@ -324,8 +318,10 @@ static void __devexit wl1271_remove(struct sdio_func *func)
pm_runtime_get_noresume(&func->dev);
wl1271_unregister_hw(wl);
- device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
- disable_irq_wake(wl->irq);
+ if (wl->irq_wake_enabled) {
+ device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
+ disable_irq_wake(wl->irq);
+ }
free_irq(wl->irq, wl);
wl1271_free_hw(wl);
}
@@ -402,23 +398,12 @@ static struct sdio_driver wl1271_sdio_driver = {
static int __init wl1271_init(void)
{
- int ret;
-
- ret = sdio_register_driver(&wl1271_sdio_driver);
- if (ret < 0) {
- wl1271_error("failed to register sdio driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
+ return sdio_register_driver(&wl1271_sdio_driver);
}
static void __exit wl1271_exit(void)
{
sdio_unregister_driver(&wl1271_sdio_driver);
-
- wl1271_notice("unloaded");
}
module_init(wl1271_init);
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 51662bb68019..e0b3736d7e19 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/crc7.h>
@@ -435,8 +436,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
if (ret)
goto out_irq;
- wl1271_notice("initialized");
-
return 0;
out_irq:
@@ -473,23 +472,12 @@ static struct spi_driver wl1271_spi_driver = {
static int __init wl1271_init(void)
{
- int ret;
-
- ret = spi_register_driver(&wl1271_spi_driver);
- if (ret < 0) {
- wl1271_error("failed to register spi driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
+ return spi_register_driver(&wl1271_spi_driver);
}
static void __exit wl1271_exit(void)
{
spi_unregister_driver(&wl1271_spi_driver);
-
- wl1271_notice("unloaded");
}
module_init(wl1271_init);
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c
index da351d7cd1f2..5d5e1ef87206 100644
--- a/drivers/net/wireless/wl12xx/testmode.c
+++ b/drivers/net/wireless/wl12xx/testmode.c
@@ -260,7 +260,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
{
wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
- ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ wl12xx_queue_recovery_work(wl);
return 0;
}
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index ca3ab1c1acef..48fde96ce0d4 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -168,7 +168,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 len;
u32 total_blocks;
- int id, ret = -EBUSY;
+ int id, ret = -EBUSY, ac;
u32 spare_blocks;
if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS))
@@ -206,7 +206,9 @@ 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;
if (wl->bss_type == BSS_TYPE_AP_BSS)
wl->links[hlid].allocated_blks += total_blocks;
@@ -383,6 +385,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
if (ret < 0)
return ret;
+ wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
+
if (wl->bss_type == BSS_TYPE_AP_BSS) {
wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_regulate_link(wl, hlid);
@@ -390,8 +394,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
wl1271_tx_update_filters(wl, skb);
}
- wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
-
/*
* The length of each packet is stored in terms of
* words. Thus, we must pad the skb data to make sure its
@@ -442,37 +444,62 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
{
unsigned long flags;
+ int i;
- if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) &&
- wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) {
- /* firmware buffer has space, restart queues */
- spin_lock_irqsave(&wl->wl_lock, flags);
- ieee80211_wake_queues(wl->hw);
- clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
- spin_unlock_irqrestore(&wl->wl_lock, flags);
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ if (test_bit(i, &wl->stopped_queues_map) &&
+ wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) {
+ /* firmware buffer has space, restart queues */
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ ieee80211_wake_queue(wl->hw,
+ wl1271_tx_get_mac80211_queue(i));
+ clear_bit(i, &wl->stopped_queues_map);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+ }
}
}
+static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
+ struct sk_buff_head *queues)
+{
+ int i, q = -1;
+ u32 min_blks = 0xffffffff;
+
+ /*
+ * Find a non-empty ac where:
+ * 1. There are packets to transmit
+ * 2. The FW has the least allocated blocks
+ */
+ 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];
+ }
+
+ if (q == -1)
+ return NULL;
+
+ return &queues[q];
+}
+
static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
{
struct sk_buff *skb = NULL;
unsigned long flags;
+ struct sk_buff_head *queue;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]);
- if (skb)
+ queue = wl1271_select_queue(wl, wl->tx_queue);
+ if (!queue)
goto out;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]);
+
+ skb = skb_dequeue(queue);
out:
if (skb) {
+ int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count--;
+ wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -484,6 +511,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
struct sk_buff *skb = NULL;
unsigned long flags;
int i, h, start_hlid;
+ struct sk_buff_head *queue;
/* start from the link after the last one */
start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
@@ -492,25 +520,25 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
for (i = 0; i < AP_MAX_LINKS; i++) {
h = (start_hlid + i) % AP_MAX_LINKS;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+ /* only consider connected stations */
+ if (h >= WL1271_AP_STA_HLID_START &&
+ !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map))
+ continue;
+
+ queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
+ if (!queue)
+ continue;
+
+ skb = skb_dequeue(queue);
if (skb)
- goto out;
+ break;
}
-out:
if (skb) {
+ int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->last_tx_hlid = h;
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count--;
+ wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
} else {
wl->last_tx_hlid = 0;
@@ -531,9 +559,12 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
if (!skb &&
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
+ int q;
+
skb = wl->dummy_packet;
+ q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count--;
+ wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -558,21 +589,33 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
}
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count++;
+ wl->tx_queue_count[q]++;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
+static bool wl1271_tx_is_data_present(struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+
+ return ieee80211_is_data_present(hdr->frame_control);
+}
+
void wl1271_tx_work_locked(struct wl1271 *wl)
{
struct sk_buff *skb;
u32 buf_offset = 0;
bool sent_packets = false;
+ bool had_data = false;
+ bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
int ret;
if (unlikely(wl->state == WL1271_STATE_OFF))
return;
while ((skb = wl1271_skb_dequeue(wl))) {
+ if (wl1271_tx_is_data_present(skb))
+ had_data = true;
+
ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
if (ret == -EAGAIN) {
/*
@@ -619,6 +662,19 @@ out_ack:
wl1271_handle_tx_low_watermark(wl);
}
+ if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+ (wl->conf.rx_streaming.always ||
+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
+ u32 timeout = wl->conf.rx_streaming.duration;
+
+ /* enable rx streaming */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ ieee80211_queue_work(wl->hw,
+ &wl->rx_streaming_enable_work);
+
+ mod_timer(&wl->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ }
}
void wl1271_tx_work(struct work_struct *work)
@@ -679,10 +735,24 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
wl->stats.retry_count += result->ack_failures;
- /* update security sequence number */
- wl->tx_security_seq += (result->lsb_security_sequence_number -
- wl->tx_security_last_seq);
- wl->tx_security_last_seq = result->lsb_security_sequence_number;
+ /*
+ * update sequence number only when relevant, i.e. only in
+ * sessions of TKIP, AES and GEM (not in open or WEP sessions)
+ */
+ if (info->control.hw_key &&
+ (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP ||
+ info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
+ info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
+ u8 fw_lsb = result->tx_security_sequence_number_lsb;
+ u8 cur_lsb = wl->tx_security_last_seq_lsb;
+
+ /*
+ * update security sequence number, taking care of potential
+ * wrap-around
+ */
+ wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256;
+ wl->tx_security_last_seq_lsb = fw_lsb;
+ }
/* remove private header from packet */
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
@@ -702,7 +772,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* return the packet to the stack */
skb_queue_tail(&wl->deferred_tx_queue, skb);
- ieee80211_queue_work(wl->hw, &wl->netstack_work);
+ queue_work(wl->freezable_wq, &wl->netstack_work);
wl1271_free_tx_id(wl, result->id);
}
@@ -747,23 +817,26 @@ void wl1271_tx_complete(struct wl1271 *wl)
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
{
struct sk_buff *skb;
- int i, total = 0;
+ int i;
unsigned long flags;
struct ieee80211_tx_info *info;
+ int total[NUM_TX_QUEUES];
for (i = 0; i < NUM_TX_QUEUES; i++) {
+ 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(wl->hw, skb);
- total++;
+ ieee80211_tx_status_ni(wl->hw, skb);
+ total[i]++;
}
}
spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count -= total;
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_queue_count[i] -= total[i];
spin_unlock_irqrestore(&wl->wl_lock, flags);
wl1271_handle_tx_low_watermark(wl);
@@ -795,13 +868,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
info = IEEE80211_SKB_CB(skb);
info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;
- ieee80211_tx_status(wl->hw, skb);
+ ieee80211_tx_status_ni(wl->hw, skb);
}
}
+ wl->tx_queue_count[i] = 0;
}
}
- wl->tx_queue_count = 0;
+ wl->stopped_queues_map = 0;
/*
* Make sure the driver is at a consistent state, in case this
@@ -838,7 +912,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;
- ieee80211_tx_status(wl->hw, skb);
+ ieee80211_tx_status_ni(wl->hw, skb);
}
}
}
@@ -854,8 +928,10 @@ void wl1271_tx_flush(struct wl1271 *wl)
while (!time_after(jiffies, timeout)) {
mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
- wl->tx_frames_cnt, wl->tx_queue_count);
- if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) {
+ wl->tx_frames_cnt,
+ wl1271_tx_total_queue_count(wl));
+ if ((wl->tx_frames_cnt == 0) &&
+ (wl1271_tx_total_queue_count(wl) == 0)) {
mutex_unlock(&wl->mutex);
return;
}
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 832f9258d675..5d719b5a3d1d 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -150,7 +150,7 @@ struct wl1271_tx_hw_res_descr {
(from 1st EDCA AIFS counter until TX Complete). */
__le32 medium_delay;
/* LS-byte of last TKIP seq-num (saved per AC for recovery). */
- u8 lsb_security_sequence_number;
+ u8 tx_security_sequence_number_lsb;
/* Retry count - number of transmissions without successful ACK.*/
u8 ack_failures;
/* The rate that succeeded getting ACK
@@ -182,6 +182,32 @@ static inline int wl1271_tx_get_queue(int queue)
}
}
+static inline int wl1271_tx_get_mac80211_queue(int queue)
+{
+ switch (queue) {
+ case CONF_TX_AC_VO:
+ return 0;
+ case CONF_TX_AC_VI:
+ return 1;
+ case CONF_TX_AC_BE:
+ return 2;
+ case CONF_TX_AC_BK:
+ return 3;
+ default:
+ return 2;
+ }
+}
+
+static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
+{
+ int i, count = 0;
+
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ count += wl->tx_queue_count[i];
+
+ return count;
+}
+
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_work_locked(struct wl1271 *wl);
void wl1271_tx_complete(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index fbe8f46d1232..1a8751eb8140 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -144,6 +144,7 @@ extern u32 wl12xx_debug_level;
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
+#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
#define WL1271_CIPHER_SUITE_GEM 0x00147201
@@ -172,7 +173,6 @@ extern u32 wl12xx_debug_level;
#define WL1271_PS_STA_MAX_BLOCKS (2 * 9)
#define WL1271_AP_BSS_INDEX 0
-#define WL1271_AP_DEF_INACTIV_SEC 300
#define WL1271_AP_DEF_BEACON_EXP 20
#define ACX_TX_DESCRIPTORS 32
@@ -226,6 +226,8 @@ enum {
#define FW_VER_MINOR_1_SPARE_STA_MIN 58
#define FW_VER_MINOR_1_SPARE_AP_MIN 47
+#define FW_VER_MINOR_FWLOG_STA_MIN 70
+
struct wl1271_chip {
u32 id;
char fw_ver_str[ETHTOOL_BUSINFO_LEN];
@@ -284,8 +286,7 @@ struct wl1271_fw_sta_status {
u8 tx_total;
u8 reserved1;
__le16 reserved2;
- /* Total structure size is 68 bytes */
- u32 padding;
+ __le32 log_start_addr;
} __packed;
struct wl1271_fw_full_status {
@@ -359,6 +360,9 @@ enum wl12xx_flags {
WL1271_FLAG_DUMMY_PACKET_PENDING,
WL1271_FLAG_SUSPENDED,
WL1271_FLAG_PENDING_WORK,
+ WL1271_FLAG_SOFT_GEMINI,
+ WL1271_FLAG_RX_STREAMING_STARTED,
+ WL1271_FLAG_RECOVERY_IN_PROGRESS,
};
struct wl1271_link {
@@ -420,7 +424,7 @@ struct wl1271 {
/* Accounting for allocated / available TX blocks on HW */
u32 tx_blocks_freed[NUM_TX_QUEUES];
u32 tx_blocks_available;
- u32 tx_allocated_blocks;
+ u32 tx_allocated_blocks[NUM_TX_QUEUES];
u32 tx_results_count;
/* Transmitted TX packets counter for chipset interface */
@@ -434,7 +438,8 @@ struct wl1271 {
/* Frames scheduled for transmission, not handled yet */
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
- int tx_queue_count;
+ int tx_queue_count[NUM_TX_QUEUES];
+ long stopped_queues_map;
/* Frames received, not handled yet by mac80211 */
struct sk_buff_head deferred_rx_queue;
@@ -443,15 +448,23 @@ struct wl1271 {
struct sk_buff_head deferred_tx_queue;
struct work_struct tx_work;
+ struct workqueue_struct *freezable_wq;
/* Pending TX frames */
unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)];
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
int tx_frames_cnt;
- /* Security sequence number counters */
- u8 tx_security_last_seq;
- s64 tx_security_seq;
+ /*
+ * Security sequence number
+ * bits 0-15: lower 16 bits part of sequence number
+ * bits 16-47: higher 32 bits part of sequence number
+ * bits 48-63: not in use
+ */
+ u64 tx_security_seq;
+
+ /* 8 bits of the last sequence number in use */
+ u8 tx_security_last_seq_lsb;
/* FW Rx counter */
u32 rx_counter;
@@ -468,6 +481,15 @@ struct wl1271 {
/* Network stack work */
struct work_struct netstack_work;
+ /* FW log buffer */
+ u8 *fwlog;
+
+ /* Number of valid bytes in the FW log buffer */
+ ssize_t fwlog_size;
+
+ /* Sysfs FW log entry readers wait queue */
+ wait_queue_head_t fwlog_waitq;
+
/* Hardware recovery work */
struct work_struct recovery_work;
@@ -508,6 +530,11 @@ struct wl1271 {
/* Default key (for WEP) */
u32 default_key;
+ /* Rx Streaming */
+ struct work_struct rx_streaming_enable_work;
+ struct work_struct rx_streaming_disable_work;
+ struct timer_list rx_streaming_timer;
+
unsigned int filters;
unsigned int rx_config;
unsigned int rx_filter;
@@ -564,6 +591,7 @@ struct wl1271 {
/* RX BA constraint value */
bool ba_support;
u8 ba_rx_bitmap;
+ bool ba_allowed;
int tcxo_clock;
@@ -572,6 +600,7 @@ struct wl1271 {
* (currently, only "ANY" trigger is supported)
*/
bool wow_enabled;
+ bool irq_wake_enabled;
/*
* AP-mode - links indexed by HLID. The global and broadcast links
@@ -601,6 +630,9 @@ struct wl1271_station {
int wl1271_plt_start(struct wl1271 *wl);
int wl1271_plt_stop(struct wl1271 *wl);
+int wl1271_recalc_rx_streaming(struct wl1271 *wl);
+void wl12xx_queue_recovery_work(struct wl1271 *wl);
+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
@@ -608,8 +640,8 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define WL1271_DEFAULT_POWER_LEVEL 0
-#define WL1271_TX_QUEUE_LOW_WATERMARK 10
-#define WL1271_TX_QUEUE_HIGH_WATERMARK 25
+#define WL1271_TX_QUEUE_LOW_WATERMARK 32
+#define WL1271_TX_QUEUE_HIGH_WATERMARK 256
#define WL1271_DEFERRED_QUEUE_LIMIT 64
@@ -636,4 +668,15 @@ int wl1271_plt_stop(struct wl1271 *wl);
/* 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)
+
+#define WL12XX_HW_BLOCK_SIZE 256
+
#endif
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 4be7c3b5b265..117c4123943c 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -21,6 +21,8 @@
#ifndef _ZD_CHIP_H
#define _ZD_CHIP_H
+#include <net/mac80211.h>
+
#include "zd_rf.h"
#include "zd_usb.h"
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index 5463ca9ebc01..9a1b013f81be 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t;
if (net_ratelimit()) \
dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
} while (0)
+# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
+ bool __cond = !!(cond); \
+ if (unlikely(__cond)) \
+ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+})
#else
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
# define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
+# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
#endif /* DEBUG */
#ifdef DEBUG
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 5037c8b2b415..cabfae1e70b1 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -143,7 +143,7 @@ static void beacon_enable(struct zd_mac *mac);
static void beacon_disable(struct zd_mac *mac);
static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
static int zd_mac_config_beacon(struct ieee80211_hw *hw,
- struct sk_buff *beacon);
+ struct sk_buff *beacon, bool in_intr);
static int zd_reg2alpha2(u8 regdomain, char *alpha2)
{
@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2)
return 1;
}
+static int zd_check_signal(struct ieee80211_hw *hw, int signal)
+{
+ struct zd_mac *mac = zd_hw_mac(hw);
+
+ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
+ "%s: signal value from device not in range 0..100, "
+ "but %d.\n", __func__, signal);
+
+ if (signal < 0)
+ signal = 0;
+ else if (signal > 100)
+ signal = 100;
+
+ return signal;
+}
+
int zd_mac_preinit_hw(struct ieee80211_hw *hw)
{
int r;
@@ -387,10 +403,8 @@ int zd_restore_settings(struct zd_mac *mac)
mac->type == NL80211_IFTYPE_AP) {
if (mac->vif != NULL) {
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
- if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
- }
+ if (beacon)
+ zd_mac_config_beacon(mac->hw, beacon, false);
}
zd_set_beacon_interval(&mac->chip, beacon_interval,
@@ -461,7 +475,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
if (i<IEEE80211_TX_MAX_RATES)
info->status.rates[i].idx = -1; /* terminate */
- info->status.ack_signal = ackssi;
+ info->status.ack_signal = zd_check_signal(hw, ackssi);
ieee80211_tx_status_irqsafe(hw, skb);
}
@@ -664,7 +678,34 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
/* FIXME: Management frame? */
}
-static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
+static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
+{
+ if (!mac->beacon.cur_beacon)
+ return false;
+
+ if (mac->beacon.cur_beacon->len != beacon->len)
+ return false;
+
+ return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
+}
+
+static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
+{
+ ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
+
+ kfree_skb(mac->beacon.cur_beacon);
+ mac->beacon.cur_beacon = NULL;
+}
+
+static void zd_mac_free_cur_beacon(struct zd_mac *mac)
+{
+ mutex_lock(&mac->chip.mutex);
+ zd_mac_free_cur_beacon_locked(mac);
+ mutex_unlock(&mac->chip.mutex);
+}
+
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
+ bool in_intr)
{
struct zd_mac *mac = zd_hw_mac(hw);
int r, ret, num_cmds, req_pos = 0;
@@ -674,13 +715,21 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
unsigned long end_jiffies, message_jiffies;
struct zd_ioreq32 *ioreqs;
+ mutex_lock(&mac->chip.mutex);
+
+ /* Check if hw already has this beacon. */
+ if (zd_mac_match_cur_beacon(mac, beacon)) {
+ r = 0;
+ goto out_nofree;
+ }
+
/* Alloc memory for full beacon write at once. */
num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
- if (!ioreqs)
- return -ENOMEM;
-
- mutex_lock(&mac->chip.mutex);
+ if (!ioreqs) {
+ r = -ENOMEM;
+ goto out_nofree;
+ }
r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
if (r < 0)
@@ -688,6 +737,10 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
if (r < 0)
goto release_sema;
+ if (in_intr && tmp & 0x2) {
+ r = -EBUSY;
+ goto release_sema;
+ }
end_jiffies = jiffies + HZ / 2; /*~500ms*/
message_jiffies = jiffies + HZ / 10; /*~100ms*/
@@ -742,7 +795,7 @@ release_sema:
end_jiffies = jiffies + HZ / 2; /*~500ms*/
ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
while (ret < 0) {
- if (time_is_before_eq_jiffies(end_jiffies)) {
+ if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
ret = -ETIMEDOUT;
break;
}
@@ -757,9 +810,19 @@ release_sema:
if (r < 0 || ret < 0) {
if (r >= 0)
r = ret;
+
+ /* We don't know if beacon was written successfully or not,
+ * so clear current. */
+ zd_mac_free_cur_beacon_locked(mac);
+
goto out;
}
+ /* Beacon has now been written successfully, update current. */
+ zd_mac_free_cur_beacon_locked(mac);
+ mac->beacon.cur_beacon = beacon;
+ beacon = NULL;
+
/* 802.11b/g 2.4G CCK 1Mb
* 802.11a, not yet implemented, uses different values (see GPL vendor
* driver)
@@ -767,11 +830,17 @@ release_sema:
r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
CR_BCN_PLCP_CFG);
out:
- mutex_unlock(&mac->chip.mutex);
kfree(ioreqs);
+out_nofree:
+ kfree_skb(beacon);
+ mutex_unlock(&mac->chip.mutex);
+
return r;
reset_device:
+ zd_mac_free_cur_beacon_locked(mac);
+ kfree_skb(beacon);
+
mutex_unlock(&mac->chip.mutex);
kfree(ioreqs);
@@ -982,7 +1051,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
stats.band = IEEE80211_BAND_2GHZ;
- stats.signal = status->signal_strength;
+ stats.signal = zd_check_signal(hw, status->signal_strength);
rate = zd_rx_rate(buffer, status);
@@ -1057,6 +1126,8 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
mac->vif = NULL;
zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
zd_write_mac_addr(&mac->chip, NULL);
+
+ zd_mac_free_cur_beacon(mac);
}
static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
@@ -1094,10 +1165,8 @@ static void zd_beacon_done(struct zd_mac *mac)
* Fetch next beacon so that tim_count is updated.
*/
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
- if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
- }
+ if (beacon)
+ zd_mac_config_beacon(mac->hw, beacon, true);
spin_lock_irq(&mac->lock);
mac->beacon.last_update = jiffies;
@@ -1222,9 +1291,8 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
if (beacon) {
zd_chip_disable_hwint(&mac->chip);
- zd_mac_config_beacon(hw, beacon);
+ zd_mac_config_beacon(hw, beacon, false);
zd_chip_enable_hwint(&mac->chip);
- kfree_skb(beacon);
}
}
@@ -1361,7 +1429,8 @@ static void beacon_watchdog_handler(struct work_struct *work)
spin_lock_irq(&mac->lock);
interval = mac->beacon.interval;
period = mac->beacon.period;
- timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ;
+ timeout = mac->beacon.last_update +
+ msecs_to_jiffies(interval * 1024 / 1000) * 3;
spin_unlock_irq(&mac->lock);
if (interval > 0 && time_is_before_jiffies(timeout)) {
@@ -1374,8 +1443,9 @@ static void beacon_watchdog_handler(struct work_struct *work)
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
+ zd_mac_free_cur_beacon(mac);
+
+ zd_mac_config_beacon(mac->hw, beacon, false);
}
zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
@@ -1410,6 +1480,8 @@ static void beacon_disable(struct zd_mac *mac)
{
dev_dbg_f(zd_mac_dev(mac), "\n");
cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+
+ zd_mac_free_cur_beacon(mac);
}
#define LINK_LED_WORK_DELAY HZ
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index f8c93c3fe755..c01eca859f95 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -165,6 +165,7 @@ struct housekeeping {
struct beacon {
struct delayed_work watchdog_work;
+ struct sk_buff *cur_beacon;
unsigned long last_update;
u16 interval;
u8 period;
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 631194d49828..cf0d69dd7be5 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -111,6 +111,9 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
#define FW_ZD1211_PREFIX "zd1211/zd1211_"
#define FW_ZD1211B_PREFIX "zd1211/zd1211b_"
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+ unsigned int count);
+
/* USB device initialization */
static void int_urb_complete(struct urb *urb);
@@ -365,6 +368,20 @@ exit:
#define urb_dev(urb) (&(urb)->dev->dev)
+static inline void handle_regs_int_override(struct urb *urb)
+{
+ struct zd_usb *usb = urb->context;
+ struct zd_usb_interrupt *intr = &usb->intr;
+
+ spin_lock(&intr->lock);
+ if (atomic_read(&intr->read_regs_enabled)) {
+ atomic_set(&intr->read_regs_enabled, 0);
+ intr->read_regs_int_overridden = 1;
+ complete(&intr->read_regs.completion);
+ }
+ spin_unlock(&intr->lock);
+}
+
static inline void handle_regs_int(struct urb *urb)
{
struct zd_usb *usb = urb->context;
@@ -383,25 +400,45 @@ static inline void handle_regs_int(struct urb *urb)
USB_MAX_EP_INT_BUFFER);
spin_unlock(&mac->lock);
schedule_work(&mac->process_intr);
- } else if (intr->read_regs_enabled) {
- intr->read_regs.length = len = urb->actual_length;
-
+ } else if (atomic_read(&intr->read_regs_enabled)) {
+ len = urb->actual_length;
+ intr->read_regs.length = urb->actual_length;
if (len > sizeof(intr->read_regs.buffer))
len = sizeof(intr->read_regs.buffer);
+
memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
- intr->read_regs_enabled = 0;
+
+ /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
+ * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
+ * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
+ * retry unhandled. Next read-reg command then might catch
+ * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
+ */
+ if (!check_read_regs(usb, intr->read_regs.req,
+ intr->read_regs.req_count))
+ goto out;
+
+ atomic_set(&intr->read_regs_enabled, 0);
+ intr->read_regs_int_overridden = 0;
complete(&intr->read_regs.completion);
+
goto out;
}
out:
spin_unlock(&intr->lock);
+
+ /* CR_INTERRUPT might override read_reg too. */
+ if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
+ handle_regs_int_override(urb);
}
static void int_urb_complete(struct urb *urb)
{
int r;
struct usb_int_header *hdr;
+ struct zd_usb *usb;
+ struct zd_usb_interrupt *intr;
switch (urb->status) {
case 0:
@@ -430,6 +467,14 @@ static void int_urb_complete(struct urb *urb)
goto resubmit;
}
+ /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
+ * pending USB_INT_ID_REGS causing read command timeout.
+ */
+ usb = urb->context;
+ intr = &usb->intr;
+ if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
+ handle_regs_int_override(urb);
+
switch (hdr->id) {
case USB_INT_ID_REGS:
handle_regs_int(urb);
@@ -579,8 +624,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
if (length < sizeof(struct rx_length_info)) {
/* It's not a complete packet anyhow. */
- printk("%s: invalid, small RX packet : %d\n",
- __func__, length);
+ dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
+ length);
return;
}
length_info = (struct rx_length_info *)
@@ -1129,6 +1174,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)
spin_lock_init(&intr->lock);
intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
init_completion(&intr->read_regs.completion);
+ atomic_set(&intr->read_regs_enabled, 0);
intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
}
@@ -1563,12 +1609,16 @@ static int usb_int_regs_length(unsigned int count)
return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
}
-static void prepare_read_regs_int(struct zd_usb *usb)
+static void prepare_read_regs_int(struct zd_usb *usb,
+ struct usb_req_read_regs *req,
+ unsigned int count)
{
struct zd_usb_interrupt *intr = &usb->intr;
spin_lock_irq(&intr->lock);
- intr->read_regs_enabled = 1;
+ atomic_set(&intr->read_regs_enabled, 1);
+ intr->read_regs.req = req;
+ intr->read_regs.req_count = count;
INIT_COMPLETION(intr->read_regs.completion);
spin_unlock_irq(&intr->lock);
}
@@ -1578,22 +1628,18 @@ static void disable_read_regs_int(struct zd_usb *usb)
struct zd_usb_interrupt *intr = &usb->intr;
spin_lock_irq(&intr->lock);
- intr->read_regs_enabled = 0;
+ atomic_set(&intr->read_regs_enabled, 0);
spin_unlock_irq(&intr->lock);
}
-static int get_results(struct zd_usb *usb, u16 *values,
- struct usb_req_read_regs *req, unsigned int count)
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+ unsigned int count)
{
- int r;
int i;
struct zd_usb_interrupt *intr = &usb->intr;
struct read_regs_int *rr = &intr->read_regs;
struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
- spin_lock_irq(&intr->lock);
-
- r = -EIO;
/* The created block size seems to be larger than expected.
* However results appear to be correct.
*/
@@ -1601,13 +1647,14 @@ static int get_results(struct zd_usb *usb, u16 *values,
dev_dbg_f(zd_usb_dev(usb),
"error: actual length %d less than expected %d\n",
rr->length, usb_int_regs_length(count));
- goto error_unlock;
+ return false;
}
+
if (rr->length > sizeof(rr->buffer)) {
dev_dbg_f(zd_usb_dev(usb),
"error: actual length %d exceeds buffer size %zu\n",
rr->length, sizeof(rr->buffer));
- goto error_unlock;
+ return false;
}
for (i = 0; i < count; i++) {
@@ -1617,8 +1664,39 @@ static int get_results(struct zd_usb *usb, u16 *values,
"rd[%d] addr %#06hx expected %#06hx\n", i,
le16_to_cpu(rd->addr),
le16_to_cpu(req->addr[i]));
- goto error_unlock;
+ return false;
}
+ }
+
+ return true;
+}
+
+static int get_results(struct zd_usb *usb, u16 *values,
+ struct usb_req_read_regs *req, unsigned int count,
+ bool *retry)
+{
+ int r;
+ int i;
+ struct zd_usb_interrupt *intr = &usb->intr;
+ struct read_regs_int *rr = &intr->read_regs;
+ struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+ spin_lock_irq(&intr->lock);
+
+ r = -EIO;
+
+ /* Read failed because firmware bug? */
+ *retry = !!intr->read_regs_int_overridden;
+ if (*retry)
+ goto error_unlock;
+
+ if (!check_read_regs(usb, req, count)) {
+ dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
+ goto error_unlock;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct reg_data *rd = &regs->regs[i];
values[i] = le16_to_cpu(rd->value);
}
@@ -1631,11 +1709,11 @@ error_unlock:
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
const zd_addr_t *addresses, unsigned int count)
{
- int r;
- int i, req_len, actual_req_len;
+ int r, i, req_len, actual_req_len, try_count = 0;
struct usb_device *udev;
struct usb_req_read_regs *req = NULL;
unsigned long timeout;
+ bool retry = false;
if (count < 1) {
dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
@@ -1671,8 +1749,10 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
for (i = 0; i < count; i++)
req->addr[i] = cpu_to_le16((u16)addresses[i]);
+retry_read:
+ try_count++;
udev = zd_usb_to_usbdev(usb);
- prepare_read_regs_int(usb);
+ prepare_read_regs_int(usb, req, count);
r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
if (r) {
dev_dbg_f(zd_usb_dev(usb),
@@ -1696,7 +1776,12 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
goto error;
}
- r = get_results(usb, values, req, count);
+ r = get_results(usb, values, req, count, &retry);
+ if (retry && try_count < 20) {
+ dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
+ try_count);
+ goto retry_read;
+ }
error:
return r;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index bf942843b733..99193b456a79 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -144,6 +144,8 @@ struct usb_int_retry_fail {
struct read_regs_int {
struct completion completion;
+ struct usb_req_read_regs *req;
+ unsigned int req_count;
/* Stores the USB int structure and contains the USB address of the
* first requested register before request.
*/
@@ -169,7 +171,8 @@ struct zd_usb_interrupt {
void *buffer;
dma_addr_t buffer_dma;
int interval;
- u8 read_regs_enabled:1;
+ atomic_t read_regs_enabled;
+ u8 read_regs_int_overridden:1;
};
static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 0e4851b8a773..fd00f25d9850 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1743,3 +1743,4 @@ failed_init:
module_init(netback_init);
MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("xen-backend:vif");
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d29365a232a1..d7c8a98daff6 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -70,6 +70,14 @@ struct netfront_cb {
#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+struct netfront_stats {
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+};
+
struct netfront_info {
struct list_head list;
struct net_device *netdev;
@@ -122,6 +130,8 @@ struct netfront_info {
struct mmu_update rx_mmu[NET_RX_RING_SIZE];
/* Statistics */
+ struct netfront_stats __percpu *stats;
+
unsigned long rx_gso_checksum_fixup;
};
@@ -468,6 +478,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned short id;
struct netfront_info *np = netdev_priv(dev);
+ struct netfront_stats *stats = this_cpu_ptr(np->stats);
struct xen_netif_tx_request *tx;
struct xen_netif_extra_info *extra;
char *data = skb->data;
@@ -552,8 +563,10 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (notify)
notify_remote_via_irq(np->netdev->irq);
- dev->stats.tx_bytes += skb->len;
- dev->stats.tx_packets++;
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+ u64_stats_update_end(&stats->syncp);
/* Note: It is not safe to access skb after xennet_tx_buf_gc()! */
xennet_tx_buf_gc(dev);
@@ -847,6 +860,8 @@ out:
static int handle_incoming_queue(struct net_device *dev,
struct sk_buff_head *rxq)
{
+ struct netfront_info *np = netdev_priv(dev);
+ struct netfront_stats *stats = this_cpu_ptr(np->stats);
int packets_dropped = 0;
struct sk_buff *skb;
@@ -871,8 +886,10 @@ static int handle_incoming_queue(struct net_device *dev,
continue;
}
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
+ u64_stats_update_begin(&stats->syncp);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ u64_stats_update_end(&stats->syncp);
/* Pass it up. */
netif_receive_skb(skb);
@@ -1034,6 +1051,38 @@ static int xennet_change_mtu(struct net_device *dev, int mtu)
return 0;
}
+static struct rtnl_link_stats64 *xennet_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
+{
+ struct netfront_info *np = netdev_priv(dev);
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct netfront_stats *stats = per_cpu_ptr(np->stats, cpu);
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->syncp);
+
+ rx_packets = stats->rx_packets;
+ tx_packets = stats->tx_packets;
+ rx_bytes = stats->rx_bytes;
+ tx_bytes = stats->tx_bytes;
+ } while (u64_stats_fetch_retry_bh(&stats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ }
+
+ tot->rx_errors = dev->stats.rx_errors;
+ tot->tx_dropped = dev->stats.tx_dropped;
+
+ return tot;
+}
+
static void xennet_release_tx_bufs(struct netfront_info *np)
{
struct sk_buff *skb;
@@ -1182,6 +1231,7 @@ static const struct net_device_ops xennet_netdev_ops = {
.ndo_stop = xennet_close,
.ndo_start_xmit = xennet_start_xmit,
.ndo_change_mtu = xennet_change_mtu,
+ .ndo_get_stats64 = xennet_get_stats64,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_fix_features = xennet_fix_features,
@@ -1216,6 +1266,11 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
np->rx_refill_timer.data = (unsigned long)netdev;
np->rx_refill_timer.function = rx_refill_timeout;
+ err = -ENOMEM;
+ np->stats = alloc_percpu(struct netfront_stats);
+ if (np->stats == NULL)
+ goto exit;
+
/* Initialise tx_skbs as a free chain containing every entry. */
np->tx_skb_freelist = 0;
for (i = 0; i < NET_TX_RING_SIZE; i++) {
@@ -1234,7 +1289,7 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
&np->gref_tx_head) < 0) {
printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
err = -ENOMEM;
- goto exit;
+ goto exit_free_stats;
}
/* A grant for every rx ring slot */
if (gnttab_alloc_grant_references(RX_MAX_TARGET,
@@ -1270,6 +1325,8 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
exit_free_tx:
gnttab_free_grant_references(np->gref_tx_head);
+ exit_free_stats:
+ free_percpu(np->stats);
exit:
free_netdev(netdev);
return ERR_PTR(err);
@@ -1869,6 +1926,8 @@ static int __devexit xennet_remove(struct xenbus_device *dev)
xennet_sysfs_delif(info->netdev);
+ free_percpu(info->stats);
+
free_netdev(info->netdev);
return 0;
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 372572c0adc6..8018d7d045b0 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -26,6 +26,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/phy.h>
+#include <linux/interrupt.h>
#define DRIVER_NAME "xilinx_emaclite"
@@ -251,11 +252,11 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
u16 *from_u16_ptr, *to_u16_ptr;
to_u32_ptr = dest_ptr;
- from_u16_ptr = (u16 *) src_ptr;
+ from_u16_ptr = src_ptr;
align_buffer = 0;
for (; length > 3; length -= 4) {
- to_u16_ptr = (u16 *) ((void *) &align_buffer);
+ to_u16_ptr = (u16 *)&align_buffer;
*to_u16_ptr++ = *from_u16_ptr++;
*to_u16_ptr++ = *from_u16_ptr++;
@@ -647,7 +648,8 @@ static void xemaclite_rx_handler(struct net_device *dev)
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
- netif_rx(skb); /* Send the packet upstream */
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb); /* Send the packet upstream */
}
/**
@@ -1029,15 +1031,19 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
spin_lock_irqsave(&lp->reset_lock, flags);
if (xemaclite_send_data(lp, (u8 *) new_skb->data, len) != 0) {
/* If the Emaclite Tx buffer is busy, stop the Tx queue and
- * defer the skb for transmission at a later point when the
+ * defer the skb for transmission during the ISR, after the
* current transmission is complete */
netif_stop_queue(dev);
lp->deferred_skb = new_skb;
+ /* Take the time stamp now, since we can't do this in an ISR. */
+ skb_tx_timestamp(new_skb);
spin_unlock_irqrestore(&lp->reset_lock, flags);
return 0;
}
spin_unlock_irqrestore(&lp->reset_lock, flags);
+ skb_tx_timestamp(new_skb);
+
dev->stats.tx_bytes += len;
dev_kfree_skb(new_skb);
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index ec47e22fa186..3e5ac60b89ac 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -442,19 +442,19 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_cleardev;
- np->tx_ring = (struct yellowfin_desc *)ring_space;
+ np->tx_ring = ring_space;
np->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- np->rx_ring = (struct yellowfin_desc *)ring_space;
+ np->rx_ring = ring_space;
np->rx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, STATUS_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_rx;
- np->tx_status = (struct tx_status_words *)ring_space;
+ np->tx_status = ring_space;
np->tx_status_dma = ring_dma;
if (dev->mem_start)
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index ec2800ff8d42..8b8881718f5e 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -731,7 +731,7 @@ static void znet_rx(struct net_device *dev)
cur_frame_end_offset -= ((count + 1)>>1) + 3;
if (cur_frame_end_offset < 0)
cur_frame_end_offset += RX_BUF_SIZE/2;
- };
+ }
/* Now step forward through the list. */
do {
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 8c7c522a056a..15e7751a273c 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -19,6 +19,8 @@
* Ethernet Controllers.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -34,115 +36,242 @@
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#define ei_inb(port) in_8(port)
-#define ei_outb(val,port) out_8(port,val)
-#define ei_inb_p(port) in_8(port)
-#define ei_outb_p(val,port) out_8(port,val)
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+#define ei_inb(port) in_8(port)
+#define ei_outb(val, port) out_8(port, val)
+#define ei_inb_p(port) in_8(port)
+#define ei_outb_p(val, port) out_8(port, val)
static const char version[] =
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+ "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include "lib8390.c"
#define DRV_NAME "zorro8390"
#define NE_BASE (dev->base_addr)
-#define NE_CMD (0x00*2)
-#define NE_DATAPORT (0x10*2) /* NatSemi-defined port window offset. */
-#define NE_RESET (0x1f*2) /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT (0x20*2)
-
-#define NE_EN0_ISR (0x07*2)
-#define NE_EN0_DCFG (0x0e*2)
-
-#define NE_EN0_RSARLO (0x08*2)
-#define NE_EN0_RSARHI (0x09*2)
-#define NE_EN0_RCNTLO (0x0a*2)
-#define NE_EN0_RXCR (0x0c*2)
-#define NE_EN0_TXCR (0x0d*2)
-#define NE_EN0_RCNTHI (0x0b*2)
-#define NE_EN0_IMR (0x0f*2)
+#define NE_CMD (0x00 * 2)
+#define NE_DATAPORT (0x10 * 2) /* NatSemi-defined port window offset */
+#define NE_RESET (0x1f * 2) /* Issue a read to reset,
+ * a write to clear. */
+#define NE_IO_EXTENT (0x20 * 2)
+
+#define NE_EN0_ISR (0x07 * 2)
+#define NE_EN0_DCFG (0x0e * 2)
+
+#define NE_EN0_RSARLO (0x08 * 2)
+#define NE_EN0_RSARHI (0x09 * 2)
+#define NE_EN0_RCNTLO (0x0a * 2)
+#define NE_EN0_RXCR (0x0c * 2)
+#define NE_EN0_TXCR (0x0d * 2)
+#define NE_EN0_RCNTHI (0x0b * 2)
+#define NE_EN0_IMR (0x0f * 2)
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8))
-
+#define WORDSWAP(a) ((((a) >> 8) & 0xff) | ((a) << 8))
static struct card_info {
- zorro_id id;
- const char *name;
- unsigned int offset;
+ zorro_id id;
+ const char *name;
+ unsigned int offset;
} cards[] __devinitdata = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
- { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
+ { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
};
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent);
-static int __devinit zorro8390_init(struct net_device *dev,
- unsigned long board, const char *name,
- unsigned long ioaddr);
-static int zorro8390_open(struct net_device *dev);
-static int zorro8390_close(struct net_device *dev);
-static void zorro8390_reset_8390(struct net_device *dev);
+/* Hard reset the card. This used to pause for the same period that a
+ * 8390 reset command required, but that shouldn't be necessary.
+ */
+static void zorro8390_reset_8390(struct net_device *dev)
+{
+ unsigned long reset_start_time = jiffies;
+
+ if (ei_debug > 1)
+ netdev_dbg(dev, "resetting - t=%ld...\n", jiffies);
+
+ z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+ ei_status.txing = 0;
+ ei_status.dmaing = 0;
+
+ /* This check _should_not_ be necessary, omit eventually. */
+ while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RESET) == 0)
+ if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
+ netdev_warn(dev, "%s: did not complete\n", __func__);
+ break;
+ }
+ z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly.
+ */
static void zorro8390_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page);
+ struct e8390_pkt_hdr *hdr, int ring_page)
+{
+ int nic_base = dev->base_addr;
+ int cnt;
+ short *ptrs;
+
+ /* This *shouldn't* happen.
+ * If it does, it's the last thing you'll see
+ */
+ if (ei_status.dmaing) {
+ netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+ __func__, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+ z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+ z_writeb(0, nic_base + NE_EN0_RCNTHI);
+ z_writeb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */
+ z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
+ z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ ptrs = (short *)hdr;
+ for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
+ *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
+
+ hdr->count = WORDSWAP(hdr->count);
+
+ ei_status.dmaing &= ~0x01;
+}
+
+/* Block input and output, similar to the Crynwr packet driver.
+ * If you are porting to a new ethercard, look at the packet driver source
+ * for hints. The NEx000 doesn't share the on-board packet memory --
+ * you have to put the packet out through the "remote DMA" dataport
+ * using z_writeb.
+ */
static void zorro8390_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void zorro8390_block_output(struct net_device *dev, const int count,
+ struct sk_buff *skb, int ring_offset)
+{
+ int nic_base = dev->base_addr;
+ char *buf = skb->data;
+ short *ptrs;
+ int cnt;
+
+ /* This *shouldn't* happen.
+ * If it does, it's the last thing you'll see
+ */
+ if (ei_status.dmaing) {
+ netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+ __func__, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+ z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+ z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+ z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+ z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+ z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+ z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ ptrs = (short *)buf;
+ for (cnt = 0; cnt < count >> 1; cnt++)
+ *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+ if (count & 0x01)
+ buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT);
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
+ ei_status.dmaing &= ~0x01;
+}
+
+static void zorro8390_block_output(struct net_device *dev, int count,
const unsigned char *buf,
- const int start_page);
-static void __devexit zorro8390_remove_one(struct zorro_dev *z);
+ const int start_page)
+{
+ int nic_base = NE_BASE;
+ unsigned long dma_start;
+ short *ptrs;
+ int cnt;
+
+ /* Round the count up for word writes. Do we need to do this?
+ * What effect will an odd byte count have on the 8390?
+ * I should check someday.
+ */
+ if (count & 0x01)
+ count++;
+
+ /* This *shouldn't* happen.
+ * If it does, it's the last thing you'll see
+ */
+ if (ei_status.dmaing) {
+ netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+ __func__, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+ /* We should already be in page 0, but to be safe... */
+ z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+ /* Now the normal output. */
+ z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+ z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+ z_writeb(0x00, nic_base + NE_EN0_RSARLO);
+ z_writeb(start_page, nic_base + NE_EN0_RSARHI);
+
+ z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
+ ptrs = (short *)buf;
+ for (cnt = 0; cnt < count >> 1; cnt++)
+ z_writew(*ptrs++, NE_BASE + NE_DATAPORT);
+
+ dma_start = jiffies;
+
+ while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+ if (time_after(jiffies, dma_start + 2 * HZ / 100)) {
+ /* 20ms */
+ netdev_err(dev, "timeout waiting for Tx RDC\n");
+ zorro8390_reset_8390(dev);
+ __NS8390_init(dev, 1);
+ break;
+ }
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
+ ei_status.dmaing &= ~0x01;
+}
-static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
- { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
- { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
+static int zorro8390_open(struct net_device *dev)
+{
+ __ei_open(dev);
+ return 0;
+}
-static struct zorro_driver zorro8390_driver = {
- .name = "zorro8390",
- .id_table = zorro8390_zorro_tbl,
- .probe = zorro8390_init_one,
- .remove = __devexit_p(zorro8390_remove_one),
-};
+static int zorro8390_close(struct net_device *dev)
+{
+ if (ei_debug > 1)
+ netdev_dbg(dev, "Shutting down ethercard\n");
+ __ei_close(dev);
+ return 0;
+}
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static void __devexit zorro8390_remove_one(struct zorro_dev *z)
{
- struct net_device *dev;
- unsigned long board, ioaddr;
- int err, i;
-
- for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
- if (z->id == cards[i].id)
- break;
- if (i < 0)
- return -ENODEV;
-
- board = z->resource.start;
- ioaddr = board+cards[i].offset;
- dev = ____alloc_ei_netdev(0);
- if (!dev)
- return -ENOMEM;
- if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
- free_netdev(dev);
- return -EBUSY;
- }
- if ((err = zorro8390_init(dev, board, cards[i].name,
- ZTWO_VADDR(ioaddr)))) {
- release_mem_region(ioaddr, NE_IO_EXTENT*2);
+ struct net_device *dev = zorro_get_drvdata(z);
+
+ unregister_netdev(dev);
+ free_irq(IRQ_AMIGA_PORTS, dev);
+ release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2);
free_netdev(dev);
- return err;
- }
- zorro_set_drvdata(z, dev);
- return 0;
}
+static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
+ { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
+
static const struct net_device_ops zorro8390_netdev_ops = {
.ndo_open = zorro8390_open,
.ndo_stop = zorro8390_close,
@@ -151,7 +280,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
.ndo_get_stats = __ei_get_stats,
.ndo_set_multicast_list = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = __ei_poll,
@@ -162,295 +291,159 @@ static int __devinit zorro8390_init(struct net_device *dev,
unsigned long board, const char *name,
unsigned long ioaddr)
{
- int i;
- int err;
- unsigned char SA_prom[32];
- int start_page, stop_page;
- static u32 zorro8390_offsets[16] = {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
- };
-
- /* Reset card. Who knows what dain-bramaged state it was left in. */
- {
- unsigned long reset_start_time = jiffies;
-
- z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
- while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- printk(KERN_WARNING " not found (no reset ack).\n");
- return -ENODEV;
- }
-
- z_writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */
- }
-
- /* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to NS8390_init(eifdev, 0).
- We can't reliably read the SAPROM address without this.
- (I learned the hard way!). */
- {
- struct {
- u32 value;
- u32 offset;
- } program_seq[] = {
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
- {0x48, NE_EN0_DCFG}, /* Set byte-wide (0x48) access. */
- {0x00, NE_EN0_RCNTLO}, /* Clear the count regs. */
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_IMR}, /* Mask completion irq. */
- {0xFF, NE_EN0_ISR},
- {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode. */
- {32, NE_EN0_RCNTLO},
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000. */
- {0x00, NE_EN0_RSARHI},
- {E8390_RREAD+E8390_START, NE_CMD},
+ int i;
+ int err;
+ unsigned char SA_prom[32];
+ int start_page, stop_page;
+ static u32 zorro8390_offsets[16] = {
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
};
- for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
- z_writeb(program_seq[i].value, ioaddr + program_seq[i].offset);
- }
- }
- for (i = 0; i < 16; i++) {
- SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
- (void)z_readb(ioaddr + NE_DATAPORT);
- }
- /* We must set the 8390 for word mode. */
- z_writeb(0x49, ioaddr + NE_EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
+ /* Reset card. Who knows what dain-bramaged state it was left in. */
+ {
+ unsigned long reset_start_time = jiffies;
- dev->base_addr = ioaddr;
- dev->irq = IRQ_AMIGA_PORTS;
+ z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
- /* Install the Interrupt handler */
- i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, DRV_NAME, dev);
- if (i) return i;
+ while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+ if (time_after(jiffies,
+ reset_start_time + 2 * HZ / 100)) {
+ netdev_warn(dev, "not found (no reset ack)\n");
+ return -ENODEV;
+ }
- for(i = 0; i < ETHER_ADDR_LEN; i++)
- dev->dev_addr[i] = SA_prom[i];
-
-#ifdef DEBUG
- printk("%pM", dev->dev_addr);
-#endif
+ z_writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */
+ }
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = 1;
+ /* Read the 16 bytes of station address PROM.
+ * We must first initialize registers,
+ * similar to NS8390_init(eifdev, 0).
+ * We can't reliably read the SAPROM address without this.
+ * (I learned the hard way!).
+ */
+ {
+ static const struct {
+ u32 value;
+ u32 offset;
+ } program_seq[] = {
+ {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
+ /* Select page 0 */
+ {0x48, NE_EN0_DCFG}, /* 0x48: Set byte-wide access */
+ {0x00, NE_EN0_RCNTLO}, /* Clear the count regs */
+ {0x00, NE_EN0_RCNTHI},
+ {0x00, NE_EN0_IMR}, /* Mask completion irq */
+ {0xFF, NE_EN0_ISR},
+ {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
+ {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
+ {32, NE_EN0_RCNTLO},
+ {0x00, NE_EN0_RCNTHI},
+ {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000 */
+ {0x00, NE_EN0_RSARHI},
+ {E8390_RREAD + E8390_START, NE_CMD},
+ };
+ for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+ z_writeb(program_seq[i].value,
+ ioaddr + program_seq[i].offset);
+ }
+ for (i = 0; i < 16; i++) {
+ SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
+ (void)z_readb(ioaddr + NE_DATAPORT);
+ }
- ei_status.rx_start_page = start_page + TX_PAGES;
+ /* We must set the 8390 for word mode. */
+ z_writeb(0x49, ioaddr + NE_EN0_DCFG);
+ start_page = NESM_START_PG;
+ stop_page = NESM_STOP_PG;
- ei_status.reset_8390 = &zorro8390_reset_8390;
- ei_status.block_input = &zorro8390_block_input;
- ei_status.block_output = &zorro8390_block_output;
- ei_status.get_8390_hdr = &zorro8390_get_8390_hdr;
- ei_status.reg_offset = zorro8390_offsets;
+ dev->base_addr = ioaddr;
+ dev->irq = IRQ_AMIGA_PORTS;
- dev->netdev_ops = &zorro8390_netdev_ops;
- __NS8390_init(dev, 0);
- err = register_netdev(dev);
- if (err) {
- free_irq(IRQ_AMIGA_PORTS, dev);
- return err;
- }
+ /* Install the Interrupt handler */
+ i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
+ IRQF_SHARED, DRV_NAME, dev);
+ if (i)
+ return i;
- printk(KERN_INFO "%s: %s at 0x%08lx, Ethernet Address %pM\n",
- dev->name, name, board, dev->dev_addr);
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ dev->dev_addr[i] = SA_prom[i];
- return 0;
-}
+ pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
-static int zorro8390_open(struct net_device *dev)
-{
- __ei_open(dev);
- return 0;
-}
+ ei_status.name = name;
+ ei_status.tx_start_page = start_page;
+ ei_status.stop_page = stop_page;
+ ei_status.word16 = 1;
-static int zorro8390_close(struct net_device *dev)
-{
- if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
- __ei_close(dev);
- return 0;
-}
+ ei_status.rx_start_page = start_page + TX_PAGES;
-/* Hard reset the card. This used to pause for the same period that a
- 8390 reset command required, but that shouldn't be necessary. */
-static void zorro8390_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
+ ei_status.reset_8390 = zorro8390_reset_8390;
+ ei_status.block_input = zorro8390_block_input;
+ ei_status.block_output = zorro8390_block_output;
+ ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
+ ei_status.reg_offset = zorro8390_offsets;
- if (ei_debug > 1)
- printk(KERN_DEBUG "resetting the 8390 t=%ld...\n", jiffies);
-
- z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((z_readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n",
- dev->name);
- break;
+ dev->netdev_ops = &zorro8390_netdev_ops;
+ __NS8390_init(dev, 0);
+ err = register_netdev(dev);
+ if (err) {
+ free_irq(IRQ_AMIGA_PORTS, dev);
+ return err;
}
- z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr. */
-}
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- we don't need to be concerned with ring wrap as the header will be at
- the start of a page, so we optimize accordingly. */
+ netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
+ name, board, dev->dev_addr);
-static void zorro8390_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page)
-{
- int nic_base = dev->base_addr;
- int cnt;
- short *ptrs;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d].\n", dev->name, ei_status.dmaing,
- ei_status.irqlock);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
- z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
- z_writeb(0, nic_base + NE_EN0_RCNTHI);
- z_writeb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */
- z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
- z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- ptrs = (short*)hdr;
- for (cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
- *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
-
- hdr->count = WORDSWAP(hdr->count);
-
- ei_status.dmaing &= ~0x01;
+ return 0;
}
-/* Block input and output, similar to the Crynwr packet driver. If you
- are porting to a new ethercard, look at the packet driver source for hints.
- The NEx000 doesn't share the on-board packet memory -- you have to put
- the packet out through the "remote DMA" dataport using z_writeb. */
-
-static void zorro8390_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
+static int __devinit zorro8390_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
- int nic_base = dev->base_addr;
- char *buf = skb->data;
- short *ptrs;
- int cnt;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
- z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
- z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
- z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
- z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- ptrs = (short*)buf;
- for (cnt = 0; cnt < (count>>1); cnt++)
- *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
- if (count & 0x01)
- buf[count-1] = z_readb(NE_BASE + NE_DATAPORT);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
+ struct net_device *dev;
+ unsigned long board, ioaddr;
+ int err, i;
+
+ for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--)
+ if (z->id == cards[i].id)
+ break;
+ if (i < 0)
+ return -ENODEV;
-static void zorro8390_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- const int start_page)
-{
- int nic_base = NE_BASE;
- unsigned long dma_start;
- short *ptrs;
- int cnt;
-
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
- if (count & 0x01)
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d]\n", dev->name, ei_status.dmaing,
- ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
- /* Now the normal output. */
- z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
- z_writeb(0x00, nic_base + NE_EN0_RSARLO);
- z_writeb(start_page, nic_base + NE_EN0_RSARHI);
-
- z_writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- ptrs = (short*)buf;
- for (cnt = 0; cnt < count>>1; cnt++)
- z_writew(*ptrs++, NE_BASE+NE_DATAPORT);
-
- dma_start = jiffies;
-
- while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- printk(KERN_ERR "%s: timeout waiting for Tx RDC.\n",
- dev->name);
- zorro8390_reset_8390(dev);
- __NS8390_init(dev,1);
- break;
+ board = z->resource.start;
+ ioaddr = board + cards[i].offset;
+ dev = ____alloc_ei_netdev(0);
+ if (!dev)
+ return -ENOMEM;
+ if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) {
+ free_netdev(dev);
+ return -EBUSY;
}
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
+ err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr));
+ if (err) {
+ release_mem_region(ioaddr, NE_IO_EXTENT * 2);
+ free_netdev(dev);
+ return err;
+ }
+ zorro_set_drvdata(z, dev);
+ return 0;
}
-static void __devexit zorro8390_remove_one(struct zorro_dev *z)
-{
- struct net_device *dev = zorro_get_drvdata(z);
-
- unregister_netdev(dev);
- free_irq(IRQ_AMIGA_PORTS, dev);
- release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2);
- free_netdev(dev);
-}
+static struct zorro_driver zorro8390_driver = {
+ .name = "zorro8390",
+ .id_table = zorro8390_zorro_tbl,
+ .probe = zorro8390_init_one,
+ .remove = __devexit_p(zorro8390_remove_one),
+};
static int __init zorro8390_init_module(void)
{
- return zorro_register_driver(&zorro8390_driver);
+ return zorro_register_driver(&zorro8390_driver);
}
static void __exit zorro8390_cleanup_module(void)
{
- zorro_unregister_driver(&zorro8390_driver);
+ zorro_unregister_driver(&zorro8390_driver);
}
module_init(zorro8390_init_module);
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index ea1580085347..2acff4307ca4 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -2,17 +2,8 @@
# Near Field Communication (NFC) devices
#
-menuconfig NFC_DEVICES
- bool "Near Field Communication (NFC) devices"
- default n
- ---help---
- You'll have to say Y if your computer contains an NFC device that
- you want to use under Linux.
-
- You can say N here if you don't have any Near Field Communication
- devices connected to your computer.
-
-if NFC_DEVICES
+menu "Near Field Communication (NFC) devices"
+ depends on NFC
config PN544_NFC
tristate "PN544 NFC driver"
@@ -26,5 +17,14 @@ config PN544_NFC
To compile this driver as a module, choose m here. The module will
be called pn544.
+config NFC_PN533
+ tristate "NXP PN533 USB driver"
+ depends on USB
+ help
+ NXP PN533 USB driver.
+ This driver provides support for NFC NXP PN533 devices.
+
+ Say Y here to compile support for PN533 devices into the
+ kernel or say M to compile it as module (pn533).
-endif # NFC_DEVICES
+endmenu
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index a4efb164ec49..8ef446d2c1bd 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -3,3 +3,6 @@
#
obj-$(CONFIG_PN544_NFC) += pn544.o
+obj-$(CONFIG_NFC_PN533) += pn533.o
+
+ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
new file mode 100644
index 000000000000..037231540719
--- /dev/null
+++ b/drivers/nfc/pn533.c
@@ -0,0 +1,1632 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/nfc.h>
+#include <linux/netdevice.h>
+#include <net/nfc.h>
+
+#define VERSION "0.1"
+
+#define PN533_VENDOR_ID 0x4CC
+#define PN533_PRODUCT_ID 0x2533
+
+#define SCM_VENDOR_ID 0x4E6
+#define SCL3711_PRODUCT_ID 0x5591
+
+static const struct usb_device_id pn533_table[] = {
+ { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID) },
+ { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, pn533_table);
+
+/* frame definitions */
+#define PN533_FRAME_TAIL_SIZE 2
+#define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
+ PN533_FRAME_TAIL_SIZE)
+#define PN533_FRAME_ACK_SIZE (sizeof(struct pn533_frame) + 1)
+#define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen])
+#define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
+
+/* start of frame */
+#define PN533_SOF 0x00FF
+
+/* frame identifier: in/out/error */
+#define PN533_FRAME_IDENTIFIER(f) (f->data[0])
+#define PN533_DIR_OUT 0xD4
+#define PN533_DIR_IN 0xD5
+
+/* PN533 Commands */
+#define PN533_FRAME_CMD(f) (f->data[1])
+#define PN533_FRAME_CMD_PARAMS_PTR(f) (&f->data[2])
+#define PN533_FRAME_CMD_PARAMS_LEN(f) (f->datalen - 2)
+
+#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
+#define PN533_CMD_RF_CONFIGURATION 0x32
+#define PN533_CMD_IN_DATA_EXCHANGE 0x40
+#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
+#define PN533_CMD_IN_ATR 0x50
+#define PN533_CMD_IN_RELEASE 0x52
+
+#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
+
+/* PN533 Return codes */
+#define PN533_CMD_RET_MASK 0x3F
+#define PN533_CMD_MI_MASK 0x40
+#define PN533_CMD_RET_SUCCESS 0x00
+
+struct pn533;
+
+typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg,
+ u8 *params, int params_len);
+
+/* structs for pn533 commands */
+
+/* PN533_CMD_GET_FIRMWARE_VERSION */
+struct pn533_fw_version {
+ u8 ic;
+ u8 ver;
+ u8 rev;
+ u8 support;
+};
+
+/* PN533_CMD_RF_CONFIGURATION */
+#define PN533_CFGITEM_MAX_RETRIES 0x05
+
+#define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
+#define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
+
+struct pn533_config_max_retries {
+ u8 mx_rty_atr;
+ u8 mx_rty_psl;
+ u8 mx_rty_passive_act;
+} __packed;
+
+/* PN533_CMD_IN_LIST_PASSIVE_TARGET */
+
+/* felica commands opcode */
+#define PN533_FELICA_OPC_SENSF_REQ 0
+#define PN533_FELICA_OPC_SENSF_RES 1
+/* felica SENSF_REQ parameters */
+#define PN533_FELICA_SENSF_SC_ALL 0xFFFF
+#define PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE 0
+#define PN533_FELICA_SENSF_RC_SYSTEM_CODE 1
+#define PN533_FELICA_SENSF_RC_ADVANCED_PROTOCOL 2
+
+/* type B initiator_data values */
+#define PN533_TYPE_B_AFI_ALL_FAMILIES 0
+#define PN533_TYPE_B_POLL_METHOD_TIMESLOT 0
+#define PN533_TYPE_B_POLL_METHOD_PROBABILISTIC 1
+
+union pn533_cmd_poll_initdata {
+ struct {
+ u8 afi;
+ u8 polling_method;
+ } __packed type_b;
+ struct {
+ u8 opcode;
+ __be16 sc;
+ u8 rc;
+ u8 tsn;
+ } __packed felica;
+};
+
+/* Poll modulations */
+enum {
+ PN533_POLL_MOD_106KBPS_A,
+ PN533_POLL_MOD_212KBPS_FELICA,
+ PN533_POLL_MOD_424KBPS_FELICA,
+ PN533_POLL_MOD_106KBPS_JEWEL,
+ PN533_POLL_MOD_847KBPS_B,
+
+ __PN533_POLL_MOD_AFTER_LAST,
+};
+#define PN533_POLL_MOD_MAX (__PN533_POLL_MOD_AFTER_LAST - 1)
+
+struct pn533_poll_modulations {
+ struct {
+ u8 maxtg;
+ u8 brty;
+ union pn533_cmd_poll_initdata initiator_data;
+ } __packed data;
+ u8 len;
+};
+
+const struct pn533_poll_modulations poll_mod[] = {
+ [PN533_POLL_MOD_106KBPS_A] = {
+ .data = {
+ .maxtg = 1,
+ .brty = 0,
+ },
+ .len = 2,
+ },
+ [PN533_POLL_MOD_212KBPS_FELICA] = {
+ .data = {
+ .maxtg = 1,
+ .brty = 1,
+ .initiator_data.felica = {
+ .opcode = PN533_FELICA_OPC_SENSF_REQ,
+ .sc = PN533_FELICA_SENSF_SC_ALL,
+ .rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE,
+ .tsn = 0,
+ },
+ },
+ .len = 7,
+ },
+ [PN533_POLL_MOD_424KBPS_FELICA] = {
+ .data = {
+ .maxtg = 1,
+ .brty = 2,
+ .initiator_data.felica = {
+ .opcode = PN533_FELICA_OPC_SENSF_REQ,
+ .sc = PN533_FELICA_SENSF_SC_ALL,
+ .rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE,
+ .tsn = 0,
+ },
+ },
+ .len = 7,
+ },
+ [PN533_POLL_MOD_106KBPS_JEWEL] = {
+ .data = {
+ .maxtg = 1,
+ .brty = 4,
+ },
+ .len = 2,
+ },
+ [PN533_POLL_MOD_847KBPS_B] = {
+ .data = {
+ .maxtg = 1,
+ .brty = 8,
+ .initiator_data.type_b = {
+ .afi = PN533_TYPE_B_AFI_ALL_FAMILIES,
+ .polling_method =
+ PN533_TYPE_B_POLL_METHOD_TIMESLOT,
+ },
+ },
+ .len = 3,
+ },
+};
+
+/* PN533_CMD_IN_ATR */
+
+struct pn533_cmd_activate_param {
+ u8 tg;
+ u8 next;
+} __packed;
+
+struct pn533_cmd_activate_response {
+ u8 status;
+ u8 nfcid3t[10];
+ u8 didt;
+ u8 bst;
+ u8 brt;
+ u8 to;
+ u8 ppt;
+ /* optional */
+ u8 gt[];
+} __packed;
+
+
+struct pn533 {
+ struct usb_device *udev;
+ struct usb_interface *interface;
+ struct nfc_dev *nfc_dev;
+
+ struct urb *out_urb;
+ int out_maxlen;
+ struct pn533_frame *out_frame;
+
+ struct urb *in_urb;
+ int in_maxlen;
+ struct pn533_frame *in_frame;
+
+ struct tasklet_struct tasklet;
+ struct pn533_frame *tklt_in_frame;
+ int tklt_in_error;
+
+ pn533_cmd_complete_t cmd_complete;
+ void *cmd_complete_arg;
+ struct semaphore cmd_lock;
+ u8 cmd;
+
+ struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
+ u8 poll_mod_count;
+ u8 poll_mod_curr;
+ u32 poll_protocols;
+
+ u8 tgt_available_prots;
+ u8 tgt_active_prot;
+};
+
+struct pn533_frame {
+ u8 preamble;
+ __be16 start_frame;
+ u8 datalen;
+ u8 datalen_checksum;
+ u8 data[];
+} __packed;
+
+/* The rule: value + checksum = 0 */
+static inline u8 pn533_checksum(u8 value)
+{
+ return ~value + 1;
+}
+
+/* The rule: sum(data elements) + checksum = 0 */
+static u8 pn533_data_checksum(u8 *data, int datalen)
+{
+ u8 sum = 0;
+ int i;
+
+ for (i = 0; i < datalen; i++)
+ sum += data[i];
+
+ return pn533_checksum(sum);
+}
+
+/**
+ * pn533_tx_frame_ack - create a ack frame
+ * @frame: The frame to be set as ack
+ *
+ * Ack is different type of standard frame. As a standard frame, it has
+ * preamble and start_frame. However the checksum of this frame must fail,
+ * i.e. datalen + datalen_checksum must NOT be zero. When the checksum test
+ * fails and datalen = 0 and datalen_checksum = 0xFF, the frame is a ack.
+ * After datalen_checksum field, the postamble is placed.
+ */
+static void pn533_tx_frame_ack(struct pn533_frame *frame)
+{
+ frame->preamble = 0;
+ frame->start_frame = cpu_to_be16(PN533_SOF);
+ frame->datalen = 0;
+ frame->datalen_checksum = 0xFF;
+ /* data[0] is used as postamble */
+ frame->data[0] = 0;
+}
+
+static void pn533_tx_frame_init(struct pn533_frame *frame, u8 cmd)
+{
+ frame->preamble = 0;
+ frame->start_frame = cpu_to_be16(PN533_SOF);
+ PN533_FRAME_IDENTIFIER(frame) = PN533_DIR_OUT;
+ PN533_FRAME_CMD(frame) = cmd;
+ frame->datalen = 2;
+}
+
+static void pn533_tx_frame_finish(struct pn533_frame *frame)
+{
+ frame->datalen_checksum = pn533_checksum(frame->datalen);
+
+ PN533_FRAME_CHECKSUM(frame) =
+ pn533_data_checksum(frame->data, frame->datalen);
+
+ PN533_FRAME_POSTAMBLE(frame) = 0;
+}
+
+static bool pn533_rx_frame_is_valid(struct pn533_frame *frame)
+{
+ u8 checksum;
+
+ if (frame->start_frame != cpu_to_be16(PN533_SOF))
+ return false;
+
+ checksum = pn533_checksum(frame->datalen);
+ if (checksum != frame->datalen_checksum)
+ return false;
+
+ checksum = pn533_data_checksum(frame->data, frame->datalen);
+ if (checksum != PN533_FRAME_CHECKSUM(frame))
+ return false;
+
+ return true;
+}
+
+static bool pn533_rx_frame_is_ack(struct pn533_frame *frame)
+{
+ if (frame->start_frame != cpu_to_be16(PN533_SOF))
+ return false;
+
+ if (frame->datalen != 0 || frame->datalen_checksum != 0xFF)
+ return false;
+
+ return true;
+}
+
+static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd)
+{
+ return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd));
+}
+
+static void pn533_tasklet_cmd_complete(unsigned long arg)
+{
+ struct pn533 *dev = (struct pn533 *) arg;
+ struct pn533_frame *in_frame = dev->tklt_in_frame;
+ int rc;
+
+ if (dev->tklt_in_error)
+ rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL,
+ dev->tklt_in_error);
+ else
+ rc = dev->cmd_complete(dev, dev->cmd_complete_arg,
+ PN533_FRAME_CMD_PARAMS_PTR(in_frame),
+ PN533_FRAME_CMD_PARAMS_LEN(in_frame));
+
+ if (rc != -EINPROGRESS)
+ up(&dev->cmd_lock);
+}
+
+static void pn533_recv_response(struct urb *urb)
+{
+ struct pn533 *dev = urb->context;
+ struct pn533_frame *in_frame;
+
+ dev->tklt_in_frame = NULL;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
+ " status: %d", urb->status);
+ dev->tklt_in_error = urb->status;
+ goto sched_tasklet;
+ default:
+ nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
+ " %d", urb->status);
+ dev->tklt_in_error = urb->status;
+ goto sched_tasklet;
+ }
+
+ in_frame = dev->in_urb->transfer_buffer;
+
+ if (!pn533_rx_frame_is_valid(in_frame)) {
+ nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
+ dev->tklt_in_error = -EIO;
+ goto sched_tasklet;
+ }
+
+ if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) {
+ nfc_dev_err(&dev->interface->dev, "The received frame is not "
+ "response to the last command");
+ dev->tklt_in_error = -EIO;
+ goto sched_tasklet;
+ }
+
+ nfc_dev_dbg(&dev->interface->dev, "Received a valid frame");
+ dev->tklt_in_error = 0;
+ dev->tklt_in_frame = in_frame;
+
+sched_tasklet:
+ tasklet_schedule(&dev->tasklet);
+}
+
+static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
+{
+ dev->in_urb->complete = pn533_recv_response;
+
+ return usb_submit_urb(dev->in_urb, flags);
+}
+
+static void pn533_recv_ack(struct urb *urb)
+{
+ struct pn533 *dev = urb->context;
+ struct pn533_frame *in_frame;
+ int rc;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
+ " status: %d", urb->status);
+ dev->tklt_in_error = urb->status;
+ goto sched_tasklet;
+ default:
+ nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
+ " %d", urb->status);
+ dev->tklt_in_error = urb->status;
+ goto sched_tasklet;
+ }
+
+ in_frame = dev->in_urb->transfer_buffer;
+
+ if (!pn533_rx_frame_is_ack(in_frame)) {
+ nfc_dev_err(&dev->interface->dev, "Received an invalid ack");
+ dev->tklt_in_error = -EIO;
+ goto sched_tasklet;
+ }
+
+ nfc_dev_dbg(&dev->interface->dev, "Received a valid ack");
+
+ rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with"
+ " result %d", rc);
+ dev->tklt_in_error = rc;
+ goto sched_tasklet;
+ }
+
+ return;
+
+sched_tasklet:
+ dev->tklt_in_frame = NULL;
+ tasklet_schedule(&dev->tasklet);
+}
+
+static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
+{
+ dev->in_urb->complete = pn533_recv_ack;
+
+ return usb_submit_urb(dev->in_urb, flags);
+}
+
+static int pn533_send_ack(struct pn533 *dev, gfp_t flags)
+{
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ pn533_tx_frame_ack(dev->out_frame);
+
+ dev->out_urb->transfer_buffer = dev->out_frame;
+ dev->out_urb->transfer_buffer_length = PN533_FRAME_ACK_SIZE;
+ rc = usb_submit_urb(dev->out_urb, flags);
+
+ return rc;
+}
+
+static int __pn533_send_cmd_frame_async(struct pn533 *dev,
+ struct pn533_frame *out_frame,
+ struct pn533_frame *in_frame,
+ int in_frame_len,
+ pn533_cmd_complete_t cmd_complete,
+ void *arg, gfp_t flags)
+{
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x",
+ PN533_FRAME_CMD(out_frame));
+
+ dev->cmd = PN533_FRAME_CMD(out_frame);
+ dev->cmd_complete = cmd_complete;
+ dev->cmd_complete_arg = arg;
+
+ dev->out_urb->transfer_buffer = out_frame;
+ dev->out_urb->transfer_buffer_length =
+ PN533_FRAME_SIZE(out_frame);
+
+ dev->in_urb->transfer_buffer = in_frame;
+ dev->in_urb->transfer_buffer_length = in_frame_len;
+
+ rc = usb_submit_urb(dev->out_urb, flags);
+ if (rc)
+ return rc;
+
+ rc = pn533_submit_urb_for_ack(dev, flags);
+ if (rc)
+ goto error;
+
+ return 0;
+
+error:
+ usb_unlink_urb(dev->out_urb);
+ return rc;
+}
+
+static int pn533_send_cmd_frame_async(struct pn533 *dev,
+ struct pn533_frame *out_frame,
+ struct pn533_frame *in_frame,
+ int in_frame_len,
+ pn533_cmd_complete_t cmd_complete,
+ void *arg, gfp_t flags)
+{
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ if (down_trylock(&dev->cmd_lock))
+ return -EBUSY;
+
+ rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
+ in_frame_len, cmd_complete, arg, flags);
+ if (rc)
+ goto error;
+
+ return 0;
+error:
+ up(&dev->cmd_lock);
+ return rc;
+}
+
+struct pn533_sync_cmd_response {
+ int rc;
+ struct completion done;
+};
+
+static int pn533_sync_cmd_complete(struct pn533 *dev, void *_arg,
+ u8 *params, int params_len)
+{
+ struct pn533_sync_cmd_response *arg = _arg;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ arg->rc = 0;
+
+ if (params_len < 0) /* error */
+ arg->rc = params_len;
+
+ complete(&arg->done);
+
+ return 0;
+}
+
+static int pn533_send_cmd_frame_sync(struct pn533 *dev,
+ struct pn533_frame *out_frame,
+ struct pn533_frame *in_frame,
+ int in_frame_len)
+{
+ int rc;
+ struct pn533_sync_cmd_response arg;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ init_completion(&arg.done);
+
+ rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, in_frame_len,
+ pn533_sync_cmd_complete, &arg, GFP_KERNEL);
+ if (rc)
+ return rc;
+
+ wait_for_completion(&arg.done);
+
+ return arg.rc;
+}
+
+static void pn533_send_complete(struct urb *urb)
+{
+ struct pn533 *dev = urb->context;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
+ " status: %d", urb->status);
+ break;
+ default:
+ nfc_dev_dbg(&dev->interface->dev, "Nonzero urb status received:"
+ " %d", urb->status);
+ }
+}
+
+struct pn533_target_type_a {
+ __be16 sens_res;
+ u8 sel_res;
+ u8 nfcid_len;
+ u8 nfcid_data[];
+} __packed;
+
+
+#define PN533_TYPE_A_SENS_RES_NFCID1(x) ((u8)((be16_to_cpu(x) & 0x00C0) >> 6))
+#define PN533_TYPE_A_SENS_RES_SSD(x) ((u8)((be16_to_cpu(x) & 0x001F) >> 0))
+#define PN533_TYPE_A_SENS_RES_PLATCONF(x) ((u8)((be16_to_cpu(x) & 0x0F00) >> 8))
+
+#define PN533_TYPE_A_SENS_RES_SSD_JEWEL 0x00
+#define PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL 0x0C
+
+#define PN533_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5)
+#define PN533_TYPE_A_SEL_CASCADE(x) (((x) & 0x04) >> 2)
+
+#define PN533_TYPE_A_SEL_PROT_MIFARE 0
+#define PN533_TYPE_A_SEL_PROT_ISO14443 1
+#define PN533_TYPE_A_SEL_PROT_DEP 2
+#define PN533_TYPE_A_SEL_PROT_ISO14443_DEP 3
+
+static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a,
+ int target_data_len)
+{
+ u8 ssd;
+ u8 platconf;
+
+ if (target_data_len < sizeof(struct pn533_target_type_a))
+ return false;
+
+ /* The lenght check of nfcid[] and ats[] are not being performed because
+ the values are not being used */
+
+ /* Requirement 4.6.3.3 from NFC Forum Digital Spec */
+ ssd = PN533_TYPE_A_SENS_RES_SSD(type_a->sens_res);
+ platconf = PN533_TYPE_A_SENS_RES_PLATCONF(type_a->sens_res);
+
+ if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+ platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
+ (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+ platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
+ return false;
+
+ /* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */
+ if (PN533_TYPE_A_SEL_CASCADE(type_a->sel_res) != 0)
+ return false;
+
+ return true;
+}
+
+static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data,
+ int tgt_data_len)
+{
+ struct pn533_target_type_a *tgt_type_a;
+
+ tgt_type_a = (struct pn533_target_type_a *) tgt_data;
+
+ if (!pn533_target_type_a_is_valid(tgt_type_a, tgt_data_len))
+ return -EPROTO;
+
+ switch (PN533_TYPE_A_SEL_PROT(tgt_type_a->sel_res)) {
+ case PN533_TYPE_A_SEL_PROT_MIFARE:
+ nfc_tgt->supported_protocols = NFC_PROTO_MIFARE_MASK;
+ break;
+ case PN533_TYPE_A_SEL_PROT_ISO14443:
+ nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
+ break;
+ case PN533_TYPE_A_SEL_PROT_DEP:
+ nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+ break;
+ case PN533_TYPE_A_SEL_PROT_ISO14443_DEP:
+ nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK |
+ NFC_PROTO_NFC_DEP_MASK;
+ break;
+ }
+
+ nfc_tgt->sens_res = be16_to_cpu(tgt_type_a->sens_res);
+ nfc_tgt->sel_res = tgt_type_a->sel_res;
+
+ return 0;
+}
+
+struct pn533_target_felica {
+ u8 pol_res;
+ u8 opcode;
+ u8 nfcid2[8];
+ u8 pad[8];
+ /* optional */
+ u8 syst_code[];
+} __packed;
+
+#define PN533_FELICA_SENSF_NFCID2_DEP_B1 0x01
+#define PN533_FELICA_SENSF_NFCID2_DEP_B2 0xFE
+
+static bool pn533_target_felica_is_valid(struct pn533_target_felica *felica,
+ int target_data_len)
+{
+ if (target_data_len < sizeof(struct pn533_target_felica))
+ return false;
+
+ if (felica->opcode != PN533_FELICA_OPC_SENSF_RES)
+ return false;
+
+ return true;
+}
+
+static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data,
+ int tgt_data_len)
+{
+ struct pn533_target_felica *tgt_felica;
+
+ tgt_felica = (struct pn533_target_felica *) tgt_data;
+
+ if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len))
+ return -EPROTO;
+
+ if (tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1 &&
+ tgt_felica->nfcid2[1] ==
+ PN533_FELICA_SENSF_NFCID2_DEP_B2)
+ nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+ else
+ nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK;
+
+ return 0;
+}
+
+struct pn533_target_jewel {
+ __be16 sens_res;
+ u8 jewelid[4];
+} __packed;
+
+static bool pn533_target_jewel_is_valid(struct pn533_target_jewel *jewel,
+ int target_data_len)
+{
+ u8 ssd;
+ u8 platconf;
+
+ if (target_data_len < sizeof(struct pn533_target_jewel))
+ return false;
+
+ /* Requirement 4.6.3.3 from NFC Forum Digital Spec */
+ ssd = PN533_TYPE_A_SENS_RES_SSD(jewel->sens_res);
+ platconf = PN533_TYPE_A_SENS_RES_PLATCONF(jewel->sens_res);
+
+ if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+ platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
+ (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+ platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
+ return false;
+
+ return true;
+}
+
+static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data,
+ int tgt_data_len)
+{
+ struct pn533_target_jewel *tgt_jewel;
+
+ tgt_jewel = (struct pn533_target_jewel *) tgt_data;
+
+ if (!pn533_target_jewel_is_valid(tgt_jewel, tgt_data_len))
+ return -EPROTO;
+
+ nfc_tgt->supported_protocols = NFC_PROTO_JEWEL_MASK;
+ nfc_tgt->sens_res = be16_to_cpu(tgt_jewel->sens_res);
+
+ return 0;
+}
+
+struct pn533_type_b_prot_info {
+ u8 bitrate;
+ u8 fsci_type;
+ u8 fwi_adc_fo;
+} __packed;
+
+#define PN533_TYPE_B_PROT_FCSI(x) (((x) & 0xF0) >> 4)
+#define PN533_TYPE_B_PROT_TYPE(x) (((x) & 0x0F) >> 0)
+#define PN533_TYPE_B_PROT_TYPE_RFU_MASK 0x8
+
+struct pn533_type_b_sens_res {
+ u8 opcode;
+ u8 nfcid[4];
+ u8 appdata[4];
+ struct pn533_type_b_prot_info prot_info;
+} __packed;
+
+#define PN533_TYPE_B_OPC_SENSB_RES 0x50
+
+struct pn533_target_type_b {
+ struct pn533_type_b_sens_res sensb_res;
+ u8 attrib_res_len;
+ u8 attrib_res[];
+} __packed;
+
+static bool pn533_target_type_b_is_valid(struct pn533_target_type_b *type_b,
+ int target_data_len)
+{
+ if (target_data_len < sizeof(struct pn533_target_type_b))
+ return false;
+
+ if (type_b->sensb_res.opcode != PN533_TYPE_B_OPC_SENSB_RES)
+ return false;
+
+ if (PN533_TYPE_B_PROT_TYPE(type_b->sensb_res.prot_info.fsci_type) &
+ PN533_TYPE_B_PROT_TYPE_RFU_MASK)
+ return false;
+
+ return true;
+}
+
+static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data,
+ int tgt_data_len)
+{
+ struct pn533_target_type_b *tgt_type_b;
+
+ tgt_type_b = (struct pn533_target_type_b *) tgt_data;
+
+ if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len))
+ return -EPROTO;
+
+ nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
+
+ return 0;
+}
+
+struct pn533_poll_response {
+ u8 nbtg;
+ u8 tg;
+ u8 target_data[];
+} __packed;
+
+static int pn533_target_found(struct pn533 *dev,
+ struct pn533_poll_response *resp, int resp_len)
+{
+ int target_data_len;
+ struct nfc_target nfc_tgt;
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__,
+ dev->poll_mod_curr);
+
+ if (resp->tg != 1)
+ return -EPROTO;
+
+ target_data_len = resp_len - sizeof(struct pn533_poll_response);
+
+ switch (dev->poll_mod_curr) {
+ case PN533_POLL_MOD_106KBPS_A:
+ rc = pn533_target_found_type_a(&nfc_tgt, resp->target_data,
+ target_data_len);
+ break;
+ case PN533_POLL_MOD_212KBPS_FELICA:
+ case PN533_POLL_MOD_424KBPS_FELICA:
+ rc = pn533_target_found_felica(&nfc_tgt, resp->target_data,
+ target_data_len);
+ break;
+ case PN533_POLL_MOD_106KBPS_JEWEL:
+ rc = pn533_target_found_jewel(&nfc_tgt, resp->target_data,
+ target_data_len);
+ break;
+ case PN533_POLL_MOD_847KBPS_B:
+ rc = pn533_target_found_type_b(&nfc_tgt, resp->target_data,
+ target_data_len);
+ break;
+ default:
+ nfc_dev_err(&dev->interface->dev, "Unknown current poll"
+ " modulation");
+ return -EPROTO;
+ }
+
+ if (rc)
+ return rc;
+
+ if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
+ nfc_dev_dbg(&dev->interface->dev, "The target found does not"
+ " have the desired protocol");
+ return -EAGAIN;
+ }
+
+ nfc_dev_dbg(&dev->interface->dev, "Target found - supported protocols: "
+ "0x%x", nfc_tgt.supported_protocols);
+
+ dev->tgt_available_prots = nfc_tgt.supported_protocols;
+
+ nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
+
+ return 0;
+}
+
+static void pn533_poll_reset_mod_list(struct pn533 *dev)
+{
+ dev->poll_mod_count = 0;
+}
+
+static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
+{
+ dev->poll_mod_active[dev->poll_mod_count] =
+ (struct pn533_poll_modulations *) &poll_mod[mod_index];
+ dev->poll_mod_count++;
+}
+
+static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols)
+{
+ pn533_poll_reset_mod_list(dev);
+
+ if (protocols & NFC_PROTO_MIFARE_MASK
+ || protocols & NFC_PROTO_ISO14443_MASK
+ || protocols & NFC_PROTO_NFC_DEP_MASK)
+ pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
+
+ if (protocols & NFC_PROTO_FELICA_MASK
+ || protocols & NFC_PROTO_NFC_DEP_MASK) {
+ pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
+ pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
+ }
+
+ if (protocols & NFC_PROTO_JEWEL_MASK)
+ pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
+
+ if (protocols & NFC_PROTO_ISO14443_MASK)
+ pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
+}
+
+static void pn533_start_poll_frame(struct pn533_frame *frame,
+ struct pn533_poll_modulations *mod)
+{
+
+ pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);
+
+ memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
+ frame->datalen += mod->len;
+
+ pn533_tx_frame_finish(frame);
+}
+
+static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
+ u8 *params, int params_len)
+{
+ struct pn533_poll_response *resp;
+ struct pn533_poll_modulations *next_mod;
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ if (params_len == -ENOENT) {
+ nfc_dev_dbg(&dev->interface->dev, "Polling operation has been"
+ " stopped");
+ goto stop_poll;
+ }
+
+ if (params_len < 0) {
+ nfc_dev_err(&dev->interface->dev, "Error %d when running poll",
+ params_len);
+ goto stop_poll;
+ }
+
+ resp = (struct pn533_poll_response *) params;
+ if (resp->nbtg) {
+ rc = pn533_target_found(dev, resp, params_len);
+
+ /* We must stop the poll after a valid target found */
+ if (rc == 0)
+ goto stop_poll;
+
+ if (rc != -EAGAIN)
+ nfc_dev_err(&dev->interface->dev, "The target found is"
+ " not valid - continuing to poll");
+ }
+
+ dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
+
+ next_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+ nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)",
+ dev->poll_mod_curr);
+
+ pn533_start_poll_frame(dev->out_frame, next_mod);
+
+ /* Don't need to down the semaphore again */
+ rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen, pn533_start_poll_complete,
+ NULL, GFP_ATOMIC);
+
+ if (rc == -EPERM) {
+ nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation"
+ " because poll has been stopped");
+ goto stop_poll;
+ }
+
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll"
+ " next modulation", rc);
+ goto stop_poll;
+ }
+
+ /* Inform caller function to do not up the semaphore */
+ return -EINPROGRESS;
+
+stop_poll:
+ pn533_poll_reset_mod_list(dev);
+ dev->poll_protocols = 0;
+ return 0;
+}
+
+static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+ struct pn533_poll_modulations *start_mod;
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__,
+ protocols);
+
+ if (dev->poll_mod_count) {
+ nfc_dev_err(&dev->interface->dev, "Polling operation already"
+ " active");
+ return -EBUSY;
+ }
+
+ if (dev->tgt_active_prot) {
+ nfc_dev_err(&dev->interface->dev, "Cannot poll with a target"
+ " already activated");
+ return -EBUSY;
+ }
+
+ pn533_poll_create_mod_list(dev, protocols);
+
+ if (!dev->poll_mod_count) {
+ nfc_dev_err(&dev->interface->dev, "No valid protocols"
+ " specified");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types",
+ dev->poll_mod_count);
+
+ dev->poll_mod_curr = 0;
+ start_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+ pn533_start_poll_frame(dev->out_frame, start_mod);
+
+ rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen, pn533_start_poll_complete,
+ NULL, GFP_KERNEL);
+
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
+ " start poll", rc);
+ goto error;
+ }
+
+ dev->poll_protocols = protocols;
+
+ return 0;
+
+error:
+ pn533_poll_reset_mod_list(dev);
+ return rc;
+}
+
+static void pn533_stop_poll(struct nfc_dev *nfc_dev)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ if (!dev->poll_mod_count) {
+ nfc_dev_dbg(&dev->interface->dev, "Polling operation was not"
+ " running");
+ return;
+ }
+
+ /* An ack will cancel the last issued command (poll) */
+ pn533_send_ack(dev, GFP_KERNEL);
+
+ /* prevent pn533_start_poll_complete to issue a new poll meanwhile */
+ usb_kill_urb(dev->in_urb);
+}
+
+static int pn533_activate_target_nfcdep(struct pn533 *dev)
+{
+ struct pn533_cmd_activate_param param;
+ struct pn533_cmd_activate_response *resp;
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_ATR);
+
+ param.tg = 1;
+ param.next = 0;
+ memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), &param,
+ sizeof(struct pn533_cmd_activate_param));
+ dev->out_frame->datalen += sizeof(struct pn533_cmd_activate_param);
+
+ pn533_tx_frame_finish(dev->out_frame);
+
+ rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen);
+ if (rc)
+ return rc;
+
+ resp = (struct pn533_cmd_activate_response *)
+ PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame);
+ rc = resp->status & PN533_CMD_RET_MASK;
+ if (rc != PN533_CMD_RET_SUCCESS)
+ return -EIO;
+
+ return 0;
+}
+
+static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx,
+ u32 protocol)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__,
+ protocol);
+
+ if (dev->poll_mod_count) {
+ nfc_dev_err(&dev->interface->dev, "Cannot activate while"
+ " polling");
+ return -EBUSY;
+ }
+
+ if (dev->tgt_active_prot) {
+ nfc_dev_err(&dev->interface->dev, "There is already an active"
+ " target");
+ return -EBUSY;
+ }
+
+ if (!dev->tgt_available_prots) {
+ nfc_dev_err(&dev->interface->dev, "There is no available target"
+ " to activate");
+ return -EINVAL;
+ }
+
+ if (!(dev->tgt_available_prots & (1 << protocol))) {
+ nfc_dev_err(&dev->interface->dev, "The target does not support"
+ " the requested protocol %u", protocol);
+ return -EINVAL;
+ }
+
+ if (protocol == NFC_PROTO_NFC_DEP) {
+ rc = pn533_activate_target_nfcdep(dev);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev, "Error %d when"
+ " activating target with"
+ " NFC_DEP protocol", rc);
+ return rc;
+ }
+ }
+
+ dev->tgt_active_prot = protocol;
+ dev->tgt_available_prots = 0;
+
+ return 0;
+}
+
+static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+ u8 tg;
+ u8 status;
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ if (!dev->tgt_active_prot) {
+ nfc_dev_err(&dev->interface->dev, "There is no active target");
+ return;
+ }
+
+ dev->tgt_active_prot = 0;
+
+ pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_RELEASE);
+
+ tg = 1;
+ memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), &tg, sizeof(u8));
+ dev->out_frame->datalen += sizeof(u8);
+
+ pn533_tx_frame_finish(dev->out_frame);
+
+ rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev, "Error when sending release"
+ " command to the controller");
+ return;
+ }
+
+ status = PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame)[0];
+ rc = status & PN533_CMD_RET_MASK;
+ if (rc != PN533_CMD_RET_SUCCESS)
+ nfc_dev_err(&dev->interface->dev, "Error 0x%x when releasing"
+ " the target", rc);
+
+ return;
+}
+
+#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
+#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
+
+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__,
+ payload_len);
+
+ if (payload_len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
+ /* TODO: Implement support to multi-part data exchange */
+ nfc_dev_err(&dev->interface->dev, "Data length greater than the"
+ " max allowed: %d",
+ PN533_CMD_DATAEXCH_DATA_MAXLEN);
+ 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;
+
+ pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
+
+ tg = 1;
+ memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
+ out_frame->datalen += sizeof(u8);
+
+ /* The data is already in the out_frame, just update the datalen */
+ out_frame->datalen += payload_len;
+
+ pn533_tx_frame_finish(out_frame);
+ skb_put(skb, PN533_FRAME_TAIL_SIZE);
+
+ return 0;
+}
+
+struct pn533_data_exchange_arg {
+ struct sk_buff *skb_resp;
+ struct sk_buff *skb_out;
+ data_exchange_cb_t cb;
+ void *cb_context;
+};
+
+static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
+ u8 *params, int params_len)
+{
+ struct pn533_data_exchange_arg *arg = _arg;
+ struct sk_buff *skb_resp = arg->skb_resp;
+ struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data;
+ int err = 0;
+ u8 status;
+ u8 cmd_ret;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ dev_kfree_skb_irq(arg->skb_out);
+
+ if (params_len < 0) { /* error */
+ err = params_len;
+ goto error;
+ }
+
+ skb_put(skb_resp, PN533_FRAME_SIZE(in_frame));
+
+ status = params[0];
+
+ cmd_ret = status & PN533_CMD_RET_MASK;
+ if (cmd_ret != PN533_CMD_RET_SUCCESS) {
+ nfc_dev_err(&dev->interface->dev, "PN533 reported error %d when"
+ " exchanging data", cmd_ret);
+ err = -EIO;
+ goto error;
+ }
+
+ if (status & PN533_CMD_MI_MASK) {
+ /* TODO: Implement support to multi-part data exchange */
+ nfc_dev_err(&dev->interface->dev, "Multi-part message not yet"
+ " supported");
+ /* Prevent the other messages from controller */
+ pn533_send_ack(dev, GFP_ATOMIC);
+ err = -ENOSYS;
+ goto error;
+ }
+
+ skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN);
+ skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE);
+
+ arg->cb(arg->cb_context, skb_resp, 0);
+ kfree(arg);
+ return 0;
+
+error:
+ dev_kfree_skb_irq(skb_resp);
+ arg->cb(arg->cb_context, NULL, err);
+ kfree(arg);
+ return 0;
+}
+
+int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx,
+ struct sk_buff *skb,
+ data_exchange_cb_t cb,
+ void *cb_context)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+ struct pn533_frame *out_frame, *in_frame;
+ struct pn533_data_exchange_arg *arg;
+ struct sk_buff *skb_resp;
+ int skb_resp_len;
+ int rc;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ if (!dev->tgt_active_prot) {
+ nfc_dev_err(&dev->interface->dev, "Cannot exchange data if"
+ " there is no active target");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ rc = pn533_data_exchange_tx_frame(dev, skb);
+ if (rc)
+ goto error;
+
+ skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN +
+ PN533_CMD_DATAEXCH_DATA_MAXLEN +
+ PN533_FRAME_TAIL_SIZE;
+
+ skb_resp = nfc_alloc_skb(skb_resp_len, GFP_KERNEL);
+ if (!skb_resp) {
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ in_frame = (struct pn533_frame *) skb_resp->data;
+ out_frame = (struct pn533_frame *) skb->data;
+
+ arg = kmalloc(sizeof(struct pn533_data_exchange_arg), GFP_KERNEL);
+ if (!arg) {
+ rc = -ENOMEM;
+ goto free_skb_resp;
+ }
+
+ arg->skb_resp = skb_resp;
+ arg->skb_out = skb;
+ arg->cb = cb;
+ arg->cb_context = cb_context;
+
+ rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, skb_resp_len,
+ pn533_data_exchange_complete, arg,
+ GFP_KERNEL);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
+ " perform data_exchange", rc);
+ goto free_arg;
+ }
+
+ return 0;
+
+free_arg:
+ kfree(arg);
+free_skb_resp:
+ kfree_skb(skb_resp);
+error:
+ kfree_skb(skb);
+ return rc;
+}
+
+static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
+ u8 cfgdata_len)
+{
+ int rc;
+ u8 *params;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ pn533_tx_frame_init(dev->out_frame, PN533_CMD_RF_CONFIGURATION);
+
+ params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame);
+ params[0] = cfgitem;
+ memcpy(&params[1], cfgdata, cfgdata_len);
+ dev->out_frame->datalen += (1 + cfgdata_len);
+
+ pn533_tx_frame_finish(dev->out_frame);
+
+ rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen);
+
+ return rc;
+}
+
+struct nfc_ops pn533_nfc_ops = {
+ .start_poll = pn533_start_poll,
+ .stop_poll = pn533_stop_poll,
+ .activate_target = pn533_activate_target,
+ .deactivate_target = pn533_deactivate_target,
+ .data_exchange = pn533_data_exchange,
+};
+
+static int pn533_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct pn533_fw_version *fw_ver;
+ struct pn533 *dev;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ struct pn533_config_max_retries max_retries;
+ int in_endpoint = 0;
+ int out_endpoint = 0;
+ int rc = -ENOMEM;
+ int i;
+ u32 protocols;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+ dev->interface = interface;
+ sema_init(&dev->cmd_lock, 1);
+
+ iface_desc = interface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
+ dev->in_maxlen = le16_to_cpu(endpoint->wMaxPacketSize);
+ in_endpoint = endpoint->bEndpointAddress;
+ }
+
+ if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) {
+ dev->out_maxlen =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ out_endpoint = endpoint->bEndpointAddress;
+ }
+ }
+
+ if (!in_endpoint || !out_endpoint) {
+ nfc_dev_err(&interface->dev, "Could not find bulk-in or"
+ " bulk-out endpoint");
+ rc = -ENODEV;
+ goto error;
+ }
+
+ dev->in_frame = kmalloc(dev->in_maxlen, GFP_KERNEL);
+ dev->in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ dev->out_frame = kmalloc(dev->out_maxlen, GFP_KERNEL);
+ dev->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (!dev->in_frame || !dev->out_frame ||
+ !dev->in_urb || !dev->out_urb)
+ goto error;
+
+ usb_fill_bulk_urb(dev->in_urb, dev->udev,
+ usb_rcvbulkpipe(dev->udev, in_endpoint),
+ NULL, 0, NULL, dev);
+ usb_fill_bulk_urb(dev->out_urb, dev->udev,
+ usb_sndbulkpipe(dev->udev, out_endpoint),
+ NULL, 0,
+ pn533_send_complete, dev);
+
+ tasklet_init(&dev->tasklet, pn533_tasklet_cmd_complete, (ulong)dev);
+
+ usb_set_intfdata(interface, dev);
+
+ pn533_tx_frame_init(dev->out_frame, PN533_CMD_GET_FIRMWARE_VERSION);
+ pn533_tx_frame_finish(dev->out_frame);
+
+ rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen);
+ if (rc)
+ goto kill_tasklet;
+
+ fw_ver = (struct pn533_fw_version *)
+ PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame);
+ nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now"
+ " attached", fw_ver->ver, fw_ver->rev);
+
+ protocols = NFC_PROTO_JEWEL_MASK
+ | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
+ | NFC_PROTO_ISO14443_MASK
+ | NFC_PROTO_NFC_DEP_MASK;
+
+ dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols);
+ if (!dev->nfc_dev)
+ goto kill_tasklet;
+
+ nfc_set_parent_dev(dev->nfc_dev, &interface->dev);
+ nfc_set_drvdata(dev->nfc_dev, dev);
+
+ rc = nfc_register_device(dev->nfc_dev);
+ if (rc)
+ goto free_nfc_dev;
+
+ max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
+ max_retries.mx_rty_psl = 2;
+ max_retries.mx_rty_passive_act = PN533_CONFIG_MAX_RETRIES_NO_RETRY;
+
+ rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
+ (u8 *) &max_retries, sizeof(max_retries));
+
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
+ " config");
+ goto free_nfc_dev;
+ }
+
+ return 0;
+
+free_nfc_dev:
+ nfc_free_device(dev->nfc_dev);
+kill_tasklet:
+ tasklet_kill(&dev->tasklet);
+error:
+ kfree(dev->in_frame);
+ usb_free_urb(dev->in_urb);
+ kfree(dev->out_frame);
+ usb_free_urb(dev->out_urb);
+ kfree(dev);
+ return rc;
+}
+
+static void pn533_disconnect(struct usb_interface *interface)
+{
+ struct pn533 *dev;
+
+ dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+
+ nfc_unregister_device(dev->nfc_dev);
+ nfc_free_device(dev->nfc_dev);
+
+ usb_kill_urb(dev->in_urb);
+ usb_kill_urb(dev->out_urb);
+
+ tasklet_kill(&dev->tasklet);
+
+ kfree(dev->in_frame);
+ usb_free_urb(dev->in_urb);
+ kfree(dev->out_frame);
+ usb_free_urb(dev->out_urb);
+ kfree(dev);
+
+ nfc_dev_info(&dev->interface->dev, "NXP PN533 NFC device disconnected");
+}
+
+static struct usb_driver pn533_driver = {
+ .name = "pn533",
+ .probe = pn533_probe,
+ .disconnect = pn533_disconnect,
+ .id_table = pn533_table,
+};
+
+static int __init pn533_init(void)
+{
+ int rc;
+
+ rc = usb_register(&pn533_driver);
+ if (rc)
+ err("usb_register failed. Error number %d", rc);
+
+ return rc;
+}
+
+static void __exit pn533_exit(void)
+{
+ usb_deregister(&pn533_driver);
+}
+
+module_init(pn533_init);
+module_exit(pn533_exit);
+
+MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>,"
+ " Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
+MODULE_DESCRIPTION("PN533 usb driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index d06a6374ed6c..cac63c9f49ae 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -71,8 +71,14 @@ config OF_MDIO
config OF_PCI
def_tristate PCI
- depends on PCI && (PPC || MICROBLAZE || X86)
+ depends on PCI
help
OpenFirmware PCI bus accessors
+config OF_PCI_IRQ
+ def_tristate PCI
+ depends on OF_PCI && OF_IRQ
+ help
+ OpenFirmware PCI IRQ routing helpers
+
endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index f7861ed2f287..dccb1176be57 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_NET) += of_net.o
obj-$(CONFIG_OF_SPI) += of_spi.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
obj-$(CONFIG_OF_PCI) += of_pci.o
+obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
diff --git a/drivers/of/address.c b/drivers/of/address.c
index b4559c58c095..da1f4b9605df 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -577,6 +577,24 @@ int of_address_to_resource(struct device_node *dev, int index,
}
EXPORT_SYMBOL_GPL(of_address_to_resource);
+struct device_node *of_find_matching_node_by_address(struct device_node *from,
+ const struct of_device_id *matches,
+ u64 base_address)
+{
+ struct device_node *dn = of_find_matching_node(from, matches);
+ struct resource res;
+
+ while (dn) {
+ if (of_address_to_resource(dn, 0, &res))
+ continue;
+ if (res.start == base_address)
+ return dn;
+ dn = of_find_matching_node(dn, matches);
+ }
+
+ return NULL;
+}
+
/**
* of_iomap - Maps the memory mapped IO for a given device_node
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 632ebae7f17a..02ed36719def 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -596,6 +596,71 @@ struct device_node *of_find_node_by_phandle(phandle handle)
EXPORT_SYMBOL(of_find_node_by_phandle);
/**
+ * of_property_read_u32_array - Find and read an array of 32 bit integers
+ * 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 32-bit value(s) 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 u32 value can be decoded.
+ */
+int of_property_read_u32_array(const struct device_node *np, char *propname,
+ u32 *out_values, size_t sz)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ const __be32 *val;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if ((sz * sizeof(*out_values)) > prop->length)
+ return -EOVERFLOW;
+
+ val = prop->value;
+ while (sz--)
+ *out_values++ = be32_to_cpup(val++);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u32_array);
+
+/**
+ * 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.
+ * @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). 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(struct device_node *np, char *propname,
+ const char **out_string)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (strnlen(prop->value, prop->length) >= prop->length)
+ return -EILSEQ;
+ *out_string = prop->value;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string);
+
+/**
* 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
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 905960338fb2..3007662ac614 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -21,8 +21,9 @@
#include <linux/slab.h>
/**
- * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API
+ * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
* @np: device node to get GPIO from
+ * @propname: property name containing gpio specifier(s)
* @index: index of the GPIO
* @flags: a flags pointer to fill in
*
@@ -30,8 +31,8 @@
* value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO.
*/
-int of_get_gpio_flags(struct device_node *np, int index,
- enum of_gpio_flags *flags)
+int of_get_named_gpio_flags(struct device_node *np, const char *propname,
+ int index, enum of_gpio_flags *flags)
{
int ret;
struct device_node *gpio_np;
@@ -40,7 +41,7 @@ int of_get_gpio_flags(struct device_node *np, int index,
const void *gpio_spec;
const __be32 *gpio_cells;
- ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+ ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index,
&gpio_np, &gpio_spec);
if (ret) {
pr_debug("%s: can't parse gpios property\n", __func__);
@@ -79,7 +80,7 @@ err0:
pr_debug("%s exited with status %d\n", __func__, ret);
return ret;
}
-EXPORT_SYMBOL(of_get_gpio_flags);
+EXPORT_SYMBOL(of_get_named_gpio_flags);
/**
* of_gpio_count - Count GPIOs for a device
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index ac1ec54e4fd5..3701b62c1d5e 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -1,92 +1,41 @@
#include <linux/kernel.h>
+#include <linux/of.h>
#include <linux/of_pci.h>
-#include <linux/of_irq.h>
#include <asm/prom.h>
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev: the device whose interrupt is to be resolved
- * @out_irq: structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+static inline int __of_pci_pci_compare(struct device_node *node,
+ unsigned int devfn)
{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- __be32 lspec_be;
- __be32 laddr[3];
- u8 pin;
- int rc;
+ unsigned int size;
+ const __be32 *reg = of_get_property(node, "reg", &size);
- /* Check if we have a device node, if yes, fallback to standard
- * device tree parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn) {
- rc = of_irq_map_one(dn, 0, out_irq);
- if (!rc)
- return rc;
- }
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
- ppnode = pci_bus_to_OF_node(pdev->bus);
-
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else {
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
- }
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't
- * include the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
+ if (!reg || size < 5 * sizeof(__be32))
+ return 0;
+ return ((be32_to_cpup(&reg[0]) >> 8) & 0xff) == devfn;
+}
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
+struct device_node *of_pci_find_child_device(struct device_node *parent,
+ unsigned int devfn)
+{
+ struct device_node *node, *node2;
+
+ for_each_child_of_node(parent, node) {
+ if (__of_pci_pci_compare(node, devfn))
+ return node;
+ /*
+ * Some OFs create a parent node "multifunc-device" as
+ * a fake root for all functions of a multi-function
+ * device we go down them as well.
*/
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
+ if (!strcmp(node->name, "multifunc-device")) {
+ for_each_child_of_node(node, node2) {
+ if (__of_pci_pci_compare(node2, devfn)) {
+ of_node_put(node);
+ return node2;
+ }
+ }
+ }
}
-
- lspec_be = cpu_to_be32(lspec);
- laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
- laddr[1] = laddr[2] = cpu_to_be32(0);
- return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+ return NULL;
}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
+EXPORT_SYMBOL_GPL(of_pci_find_child_device);
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
new file mode 100644
index 000000000000..ac1ec54e4fd5
--- /dev/null
+++ b/drivers/of/of_pci_irq.c
@@ -0,0 +1,92 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <asm/prom.h>
+
+/**
+ * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * @pdev: the device whose interrupt is to be resolved
+ * @out_irq: structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+ struct device_node *dn, *ppnode;
+ struct pci_dev *ppdev;
+ u32 lspec;
+ __be32 lspec_be;
+ __be32 laddr[3];
+ u8 pin;
+ int rc;
+
+ /* Check if we have a device node, if yes, fallback to standard
+ * device tree parsing
+ */
+ dn = pci_device_to_OF_node(pdev);
+ if (dn) {
+ rc = of_irq_map_one(dn, 0, out_irq);
+ if (!rc)
+ return rc;
+ }
+
+ /* Ok, we don't, time to have fun. Let's start by building up an
+ * interrupt spec. we assume #interrupt-cells is 1, which is standard
+ * for PCI. If you do different, then don't use that routine.
+ */
+ rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+ if (rc != 0)
+ return rc;
+ /* No pin, exit */
+ if (pin == 0)
+ return -ENODEV;
+
+ /* Now we walk up the PCI tree */
+ lspec = pin;
+ for (;;) {
+ /* Get the pci_dev of our parent */
+ ppdev = pdev->bus->self;
+
+ /* Ouch, it's a host bridge... */
+ if (ppdev == NULL) {
+ ppnode = pci_bus_to_OF_node(pdev->bus);
+
+ /* No node for host bridge ? give up */
+ if (ppnode == NULL)
+ return -EINVAL;
+ } else {
+ /* We found a P2P bridge, check if it has a node */
+ ppnode = pci_device_to_OF_node(ppdev);
+ }
+
+ /* Ok, we have found a parent with a device-node, hand over to
+ * the OF parsing code.
+ * We build a unit address from the linux device to be used for
+ * resolution. Note that we use the linux bus number which may
+ * not match your firmware bus numbering.
+ * Fortunately, in most cases, interrupt-map-mask doesn't
+ * include the bus number as part of the matching.
+ * You should still be careful about that though if you intend
+ * to rely on this function (you ship a firmware that doesn't
+ * create device nodes for all PCI devices).
+ */
+ if (ppnode)
+ break;
+
+ /* We can only get here if we hit a P2P bridge with no node,
+ * let's do standard swizzling and try again
+ */
+ lspec = pci_swizzle_interrupt_pin(pdev, lspec);
+ pdev = ppdev;
+ }
+
+ lspec_be = cpu_to_be32(lspec);
+ laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+ laddr[1] = laddr[2] = cpu_to_be32(0);
+ return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 63d3cb73bdb9..ed5a6d3c26aa 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -13,6 +13,7 @@
*/
#include <linux/errno.h>
#include <linux/module.h>
+#include <linux/amba/bus.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
@@ -22,6 +23,14 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+const struct of_device_id of_default_bus_match_table[] = {
+ { .compatible = "simple-bus", },
+#ifdef CONFIG_ARM_AMBA
+ { .compatible = "arm,amba-bus", },
+#endif /* CONFIG_ARM_AMBA */
+ {} /* Empty terminated list */
+};
+
static int of_dev_node_match(struct device *dev, void *data)
{
return dev->of_node == data;
@@ -153,7 +162,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
}
dev->dev.of_node = of_node_get(np);
-#if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
+#if defined(CONFIG_MICROBLAZE)
dev->dev.dma_mask = &dev->archdata.dma_mask;
#endif
dev->dev.parent = parent;
@@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np,
EXPORT_SYMBOL(of_device_alloc);
/**
- * of_platform_device_create - Alloc, initialize and register an of_device
+ * of_platform_device_create_pdata - Alloc, initialize and register an of_device
* @np: pointer to node to create device for
* @bus_id: name to assign device
+ * @platform_data: pointer to populate platform_data pointer with
* @parent: Linux device model parent device.
*
* Returns pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered.
*/
-struct platform_device *of_platform_device_create(struct device_node *np,
- const char *bus_id,
- struct device *parent)
+struct platform_device *of_platform_device_create_pdata(
+ struct device_node *np,
+ const char *bus_id,
+ void *platform_data,
+ struct device *parent)
{
struct platform_device *dev;
@@ -189,11 +201,12 @@ struct platform_device *of_platform_device_create(struct device_node *np,
if (!dev)
return NULL;
-#if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
+#if defined(CONFIG_MICROBLAZE)
dev->archdata.dma_mask = 0xffffffffUL;
#endif
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
dev->dev.bus = &platform_bus_type;
+ dev->dev.platform_data = platform_data;
/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
@@ -207,8 +220,111 @@ struct platform_device *of_platform_device_create(struct device_node *np,
return dev;
}
+
+/**
+ * of_platform_device_create - Alloc, initialize and register an of_device
+ * @np: pointer to node to create device for
+ * @bus_id: name to assign device
+ * @parent: Linux device model parent device.
+ *
+ * Returns pointer to created platform device, or NULL if a device was not
+ * registered. Unavailable devices will not get registered.
+ */
+struct platform_device *of_platform_device_create(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ return of_platform_device_create_pdata(np, bus_id, NULL, parent);
+}
EXPORT_SYMBOL(of_platform_device_create);
+#ifdef CONFIG_ARM_AMBA
+static struct amba_device *of_amba_device_create(struct device_node *node,
+ const char *bus_id,
+ void *platform_data,
+ struct device *parent)
+{
+ struct amba_device *dev;
+ const void *prop;
+ int i, ret;
+
+ pr_debug("Creating amba device %s\n", node->full_name);
+
+ if (!of_device_is_available(node))
+ return NULL;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ /* setup generic device info */
+ dev->dev.coherent_dma_mask = ~0;
+ dev->dev.of_node = of_node_get(node);
+ dev->dev.parent = parent;
+ dev->dev.platform_data = platform_data;
+ if (bus_id)
+ dev_set_name(&dev->dev, "%s", bus_id);
+ else
+ of_device_make_bus_id(&dev->dev);
+
+ /* setup amba-specific device info */
+ dev->dma_mask = ~0;
+
+ /* Allow the HW Peripheral ID to be overridden */
+ prop = of_get_property(node, "arm,primecell-periphid", NULL);
+ if (prop)
+ dev->periphid = of_read_ulong(prop, 1);
+
+ /* Decode the IRQs and address ranges */
+ for (i = 0; i < AMBA_NR_IRQS; i++)
+ dev->irq[i] = irq_of_parse_and_map(node, i);
+
+ ret = of_address_to_resource(node, 0, &dev->res);
+ if (ret)
+ goto err_free;
+
+ ret = amba_device_register(dev, &iomem_resource);
+ if (ret)
+ goto err_free;
+
+ return dev;
+
+err_free:
+ kfree(dev);
+ return NULL;
+}
+#else /* CONFIG_ARM_AMBA */
+static struct amba_device *of_amba_device_create(struct device_node *node,
+ const char *bus_id,
+ void *platform_data,
+ struct device *parent)
+{
+ return NULL;
+}
+#endif /* CONFIG_ARM_AMBA */
+
+/**
+ * of_devname_lookup() - Given a device node, lookup the preferred Linux name
+ */
+static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
+ struct device_node *np)
+{
+ struct resource res;
+ if (lookup) {
+ for(; lookup->name != NULL; lookup++) {
+ if (!of_device_is_compatible(np, lookup->compatible))
+ continue;
+ if (of_address_to_resource(np, 0, &res))
+ continue;
+ if (res.start != lookup->phys_addr)
+ continue;
+ pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
+ return lookup;
+ }
+ }
+ return NULL;
+}
+
/**
* of_platform_bus_create() - Create a device for a node and its children.
* @bus: device node of the bus to instantiate
@@ -221,19 +337,41 @@ EXPORT_SYMBOL(of_platform_device_create);
*/
static int of_platform_bus_create(struct device_node *bus,
const struct of_device_id *matches,
- struct device *parent)
+ const struct of_dev_auxdata *lookup,
+ struct device *parent, bool strict)
{
+ const struct of_dev_auxdata *auxdata;
struct device_node *child;
struct platform_device *dev;
+ const char *bus_id = NULL;
+ void *platform_data = NULL;
int rc = 0;
- dev = of_platform_device_create(bus, NULL, parent);
+ /* Make sure it has a compatible property */
+ if (strict && (!of_get_property(bus, "compatible", NULL))) {
+ pr_debug("%s() - skipping %s, no compatible prop\n",
+ __func__, bus->full_name);
+ return 0;
+ }
+
+ auxdata = of_dev_lookup(lookup, bus);
+ if (auxdata) {
+ bus_id = auxdata->name;
+ platform_data = auxdata->platform_data;
+ }
+
+ if (of_device_is_compatible(bus, "arm,primecell")) {
+ of_amba_device_create(bus, bus_id, platform_data, parent);
+ return 0;
+ }
+
+ dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
if (!dev || !of_match_node(matches, bus))
return 0;
for_each_child_of_node(bus, child) {
pr_debug(" create child: %s\n", child->full_name);
- rc = of_platform_bus_create(child, matches, &dev->dev);
+ rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
if (rc) {
of_node_put(child);
break;
@@ -267,11 +405,11 @@ int of_platform_bus_probe(struct device_node *root,
/* Do a self check of bus type, if there's a match, create children */
if (of_match_node(matches, root)) {
- rc = of_platform_bus_create(root, matches, parent);
+ rc = of_platform_bus_create(root, matches, NULL, parent, false);
} else for_each_child_of_node(root, child) {
if (!of_match_node(matches, child))
continue;
- rc = of_platform_bus_create(child, matches, parent);
+ rc = of_platform_bus_create(child, matches, NULL, parent, false);
if (rc)
break;
}
@@ -280,4 +418,44 @@ int of_platform_bus_probe(struct device_node *root,
return rc;
}
EXPORT_SYMBOL(of_platform_bus_probe);
+
+/**
+ * of_platform_populate() - Populate platform_devices from device tree data
+ * @root: parent of the first level to probe or NULL for the root of the tree
+ * @matches: match table, NULL to use the default
+ * @parent: parent to hook devices from, NULL for toplevel
+ *
+ * Similar to of_platform_bus_probe(), this function walks the device tree
+ * and creates devices from nodes. It differs in that it follows the modern
+ * convention of requiring all device nodes to have a 'compatible' property,
+ * and it is suitable for creating devices which are children of the root
+ * node (of_platform_bus_probe will only create children of the root which
+ * are selected by the @matches argument).
+ *
+ * New board support should be using this function instead of
+ * of_platform_bus_probe().
+ *
+ * Returns 0 on success, < 0 on failure.
+ */
+int of_platform_populate(struct device_node *root,
+ const struct of_device_id *matches,
+ const struct of_dev_auxdata *lookup,
+ struct device *parent)
+{
+ struct device_node *child;
+ int rc = 0;
+
+ root = root ? of_node_get(root) : of_find_node_by_path("/");
+ if (!root)
+ return -EINVAL;
+
+ for_each_child_of_node(root, child) {
+ rc = of_platform_bus_create(child, matches, lookup, parent, true);
+ if (rc)
+ break;
+ }
+
+ of_node_put(root);
+ return rc;
+}
#endif /* !CONFIG_SPARC */
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index 9046f7b2ed79..94796f39bc47 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -31,7 +31,7 @@ static int num_counters;
/*
* Overflow callback for oprofile.
*/
-static void op_overflow_handler(struct perf_event *event, int unused,
+static void op_overflow_handler(struct perf_event *event,
struct perf_sample_data *data, struct pt_regs *regs)
{
int id;
@@ -79,7 +79,7 @@ static int op_create_counter(int cpu, int event)
pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
cpu, NULL,
- op_overflow_handler);
+ op_overflow_handler, NULL);
if (IS_ERR(pevent))
return PTR_ERR(pevent);
diff --git a/drivers/oprofile/oprofile_stats.h b/drivers/oprofile/oprofile_stats.h
index 0b54e46c3c14..38b6fc028984 100644
--- a/drivers/oprofile/oprofile_stats.h
+++ b/drivers/oprofile/oprofile_stats.h
@@ -10,7 +10,7 @@
#ifndef OPROFILE_STATS_H
#define OPROFILE_STATS_H
-#include <asm/atomic.h>
+#include <linux/atomic.h>
struct oprofile_stat_struct {
atomic_t sample_lost_no_mm;
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
index 2c5ac2bf5c56..844f6137970a 100644
--- a/drivers/parport/parport_ax88796.c
+++ b/drivers/parport/parport_ax88796.c
@@ -293,7 +293,7 @@ static int parport_ax88796_probe(struct platform_device *pdev)
goto exit_mem;
}
- size = (res->end - res->start) + 1;
+ size = resource_size(res);
spacing = size / 3;
dd->io = request_mem_region(res->start, size, pdev->name);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index f330338c2f22..d1cdb9449f84 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2864,24 +2864,6 @@ enum parport_pc_pci_cards {
lava_parallel_dual_b,
boca_ioppar,
plx_9050,
- timedia_4078a,
- timedia_4079h,
- timedia_4085h,
- timedia_4088a,
- timedia_4089a,
- timedia_4095a,
- timedia_4096a,
- timedia_4078u,
- timedia_4079a,
- timedia_4085u,
- timedia_4079r,
- timedia_4079s,
- timedia_4079d,
- timedia_4079e,
- timedia_4079f,
- timedia_9079a,
- timedia_9079b,
- timedia_9079c,
timedia_4006a,
timedia_4014,
timedia_4008a,
@@ -2940,24 +2922,6 @@ static struct parport_pc_pci {
/* lava_parallel_dual_b */ { 1, { { 0, -1 }, } },
/* boca_ioppar */ { 1, { { 0, -1 }, } },
/* plx_9050 */ { 2, { { 4, -1 }, { 5, -1 }, } },
- /* timedia_4078a */ { 1, { { 2, -1 }, } },
- /* timedia_4079h */ { 1, { { 2, 3 }, } },
- /* timedia_4085h */ { 2, { { 2, -1 }, { 4, -1 }, } },
- /* timedia_4088a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4089a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4095a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4096a */ { 2, { { 2, 3 }, { 4, 5 }, } },
- /* timedia_4078u */ { 1, { { 2, -1 }, } },
- /* timedia_4079a */ { 1, { { 2, 3 }, } },
- /* timedia_4085u */ { 2, { { 2, -1 }, { 4, -1 }, } },
- /* timedia_4079r */ { 1, { { 2, 3 }, } },
- /* timedia_4079s */ { 1, { { 2, 3 }, } },
- /* timedia_4079d */ { 1, { { 2, 3 }, } },
- /* timedia_4079e */ { 1, { { 2, 3 }, } },
- /* timedia_4079f */ { 1, { { 2, 3 }, } },
- /* timedia_9079a */ { 1, { { 2, 3 }, } },
- /* timedia_9079b */ { 1, { { 2, 3 }, } },
- /* timedia_9079c */ { 1, { { 2, 3 }, } },
/* timedia_4006a */ { 1, { { 0, -1 }, } },
/* timedia_4014 */ { 2, { { 0, -1 }, { 2, -1 }, } },
/* timedia_4008a */ { 1, { { 0, 1 }, } },
@@ -3019,24 +2983,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0, 0, plx_9050 },
/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
- { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
- { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
- { 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
- { 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
- { 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
- { 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
- { 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
- { 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
- { 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
- { 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
- { 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
- { 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
- { 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
- { 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
- { 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
- { 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
- { 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
- { 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
{ 0x1409, 0x7268, 0x1409, 0x0101, 0, 0, timedia_4006a },
{ 0x1409, 0x7268, 0x1409, 0x0102, 0, 0, timedia_4014 },
{ 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a },
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index f01e26440f11..e9c32274df3f 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -33,6 +33,9 @@ enum parport_pc_pci_cards {
netmos_9xx5_combo,
netmos_9855,
netmos_9855_2p,
+ netmos_9900,
+ netmos_9900_2p,
+ netmos_99xx_1p,
avlab_1s1p,
avlab_1s2p,
avlab_2s1p,
@@ -41,6 +44,24 @@ enum parport_pc_pci_cards {
siig_2p1s_20x,
siig_1s1p_20x,
siig_2s1p_20x,
+ timedia_4078a,
+ timedia_4079h,
+ timedia_4085h,
+ timedia_4088a,
+ timedia_4089a,
+ timedia_4095a,
+ timedia_4096a,
+ timedia_4078u,
+ timedia_4079a,
+ timedia_4085u,
+ timedia_4079r,
+ timedia_4079s,
+ timedia_4079d,
+ timedia_4079e,
+ timedia_4079f,
+ timedia_9079a,
+ timedia_9079b,
+ timedia_9079c,
};
/* each element directly indexed from enum list, above */
@@ -72,22 +93,20 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc
dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
dev->subsystem_device == 0x0299)
return -ENODEV;
- /*
- * Netmos uses the subdevice ID to indicate the number of parallel
- * and serial ports. The form is 0x00PS, where <P> is the number of
- * parallel ports and <S> is the number of serial ports.
- */
- par->numports = (dev->subsystem_device & 0xf0) >> 4;
- if (par->numports > ARRAY_SIZE(par->addr))
- par->numports = ARRAY_SIZE(par->addr);
- /*
- * This function is currently only called for cards with up to
- * one parallel port.
- * Parallel port BAR is either before or after serial ports BARS;
- * hence, lo should be either 0 or equal to the number of serial ports.
- */
- if (par->addr[0].lo != 0)
- par->addr[0].lo = dev->subsystem_device & 0xf;
+
+ if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
+ par->numports = 1;
+ } else {
+ /*
+ * Netmos uses the subdevice ID to indicate the number of parallel
+ * and serial ports. The form is 0x00PS, where <P> is the number of
+ * parallel ports and <S> is the number of serial ports.
+ */
+ par->numports = (dev->subsystem_device & 0xf0) >> 4;
+ if (par->numports > ARRAY_SIZE(par->addr))
+ par->numports = ARRAY_SIZE(par->addr);
+ }
+
return 0;
}
@@ -97,6 +116,9 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init },
/* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init },
/* netmos_9855_2p */ { 2, { { 0, -1 }, { 2, -1 }, } },
+ /* netmos_9900 */ {1, { { 3, 4 }, }, netmos_parallel_init },
+ /* netmos_9900_2p */ {2, { { 0, 1 }, { 3, 4 }, } },
+ /* netmos_99xx_1p */ {1, { { 0, 1 }, } },
/* avlab_1s1p */ { 1, { { 1, 2}, } },
/* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} },
/* avlab_2s1p */ { 1, { { 2, 3}, } },
@@ -105,6 +127,24 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* siig_2p1s_20x */ { 2, { { 1, 2 }, { 3, 4 }, } },
/* siig_1s1p_20x */ { 1, { { 1, 2 }, } },
/* siig_2s1p_20x */ { 1, { { 2, 3 }, } },
+ /* timedia_4078a */ { 1, { { 2, -1 }, } },
+ /* timedia_4079h */ { 1, { { 2, 3 }, } },
+ /* timedia_4085h */ { 2, { { 2, -1 }, { 4, -1 }, } },
+ /* timedia_4088a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4089a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4095a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4096a */ { 2, { { 2, 3 }, { 4, 5 }, } },
+ /* timedia_4078u */ { 1, { { 2, -1 }, } },
+ /* timedia_4079a */ { 1, { { 2, 3 }, } },
+ /* timedia_4085u */ { 2, { { 2, -1 }, { 4, -1 }, } },
+ /* timedia_4079r */ { 1, { { 2, 3 }, } },
+ /* timedia_4079s */ { 1, { { 2, 3 }, } },
+ /* timedia_4079d */ { 1, { { 2, 3 }, } },
+ /* timedia_4079e */ { 1, { { 2, 3 }, } },
+ /* timedia_4079f */ { 1, { { 2, 3 }, } },
+ /* timedia_9079a */ { 1, { { 2, 3 }, } },
+ /* timedia_9079b */ { 1, { { 2, 3 }, } },
+ /* timedia_9079c */ { 1, { { 2, 3 }, } },
};
static struct pci_device_id parport_serial_pci_tbl[] = {
@@ -127,6 +167,14 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
0x1000, 0x0022, 0, 0, netmos_9855_2p },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x3011, 0, 0, netmos_9900 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x3012, 0, 0, netmos_9900 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x3020, 0, 0, netmos_9900_2p },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
+ 0xA000, 0x2000, 0, 0, netmos_99xx_1p },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
{ PCI_VENDOR_ID_AFAVLAB, 0x2110,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
@@ -176,6 +224,25 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+ /* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
+ { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
+ { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
+ { 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
+ { 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
+ { 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
+ { 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
+ { 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
+ { 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
+ { 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
+ { 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
+ { 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
+ { 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
+ { 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
+ { 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
+ { 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
+ { 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
+ { 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
+ { 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
{ 0, } /* terminate list */
};
@@ -219,6 +286,24 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
.base_baud = 115200,
.uart_offset = 8,
},
+ [netmos_9900] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [netmos_9900_2p] = { /* parallel only */ /* n/t */
+ .flags = FL_BASE0,
+ .num_ports = 0,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [netmos_99xx_1p] = { /* parallel only */ /* n/t */
+ .flags = FL_BASE0,
+ .num_ports = 0,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
[avlab_1s1p] = { /* n/t */
.flags = FL_BASE0 | FL_BASE_BARS,
.num_ports = 1,
@@ -267,6 +352,114 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 8,
},
+ [timedia_4078a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079h] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4085h] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4088a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4089a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4095a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4096a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4078u] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4085u] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079r] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079s] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079d] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079e] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_4079f] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_9079a] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_9079b] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [timedia_9079c] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
};
struct parport_serial_private {
@@ -285,6 +478,10 @@ static int __devinit serial_register (struct pci_dev *dev,
struct serial_private *serial;
board = &pci_parport_serial_boards[id->driver_data];
+
+ if (board->num_ports == 0)
+ return 0;
+
serial = pciserial_init_ports(dev, board);
if (IS_ERR(serial))
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 094308e41be5..6fadae3ad134 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -29,11 +29,6 @@ obj-$(CONFIG_PCI_MSI) += msi.o
# Build the Hypertransport interrupt support
obj-$(CONFIG_HT_IRQ) += htirq.o
-# Build Intel IOMMU support
-obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
-
-obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
-
obj-$(CONFIG_PCI_IOV) += iov.o
#
@@ -71,4 +66,6 @@ obj-$(CONFIG_PCI_STUB) += pci-stub.o
obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
+obj-$(CONFIG_OF) += of.o
+
ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index d703e73fffa7..3fadf2f135e8 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -32,7 +32,7 @@
#include <linux/pci_hotplug.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include "cpci_hotplug.h"
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 083034710fa6..1d002b1c2bf4 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -158,7 +158,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
/* Scan below the new bridge */
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
- of_scan_pci_bridge(dn, dev);
+ of_scan_pci_bridge(dev);
/* Map IO space for child bus, which may or may not succeed */
pcibios_map_io_space(dev->subordinate);
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index 071b7dc0094b..efa30da1ae8f 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -50,29 +50,26 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
pci_bus_for_each_resource(bus, res, index) {
if (res && (res->flags & IORESOURCE_MEM) &&
!(res->flags & IORESOURCE_PREFETCH)) {
- out += sprintf(out, "start = %8.8llx, "
- "length = %8.8llx\n",
- (unsigned long long)res->start,
- (unsigned long long)(res->end - res->start));
+ out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)resource_size(res));
}
}
out += sprintf(out, "Free resources: prefetchable memory\n");
pci_bus_for_each_resource(bus, res, index) {
if (res && (res->flags & IORESOURCE_MEM) &&
(res->flags & IORESOURCE_PREFETCH)) {
- out += sprintf(out, "start = %8.8llx, "
- "length = %8.8llx\n",
- (unsigned long long)res->start,
- (unsigned long long)(res->end - res->start));
+ out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)resource_size(res));
}
}
out += sprintf(out, "Free resources: IO\n");
pci_bus_for_each_resource(bus, res, index) {
if (res && (res->flags & IORESOURCE_IO)) {
- out += sprintf(out, "start = %8.8llx, "
- "length = %8.8llx\n",
- (unsigned long long)res->start,
- (unsigned long long)(res->end - res->start));
+ out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)resource_size(res));
}
}
out += sprintf(out, "Free resources: bus numbers\n");
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
new file mode 100644
index 000000000000..c94d37ec55c8
--- /dev/null
+++ b/drivers/pci/of.c
@@ -0,0 +1,61 @@
+/*
+ * PCI <-> OF mapping helpers
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify 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/pci.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include "pci.h"
+
+void pci_set_of_node(struct pci_dev *dev)
+{
+ if (!dev->bus->dev.of_node)
+ return;
+ dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
+ dev->devfn);
+}
+
+void pci_release_of_node(struct pci_dev *dev)
+{
+ of_node_put(dev->dev.of_node);
+ dev->dev.of_node = NULL;
+}
+
+void pci_set_bus_of_node(struct pci_bus *bus)
+{
+ if (bus->self == NULL)
+ bus->dev.of_node = pcibios_get_phb_of_node(bus);
+ else
+ bus->dev.of_node = of_node_get(bus->self->dev.of_node);
+}
+
+void pci_release_bus_of_node(struct pci_bus *bus)
+{
+ of_node_put(bus->dev.of_node);
+ bus->dev.of_node = NULL;
+}
+
+struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+ /* This should only be called for PHBs */
+ if (WARN_ON(bus->self || bus->parent))
+ return NULL;
+
+ /* Look for a node pointer in either the intermediary device we
+ * create above the root bus or it's own parent. Normally only
+ * the later is populated.
+ */
+ if (bus->bridge->of_node)
+ return of_node_get(bus->bridge->of_node);
+ if (bus->bridge->parent->of_node)
+ return of_node_get(bus->bridge->parent->of_node);
+ return NULL;
+}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 46767c53917a..12d1e81a8abe 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/cpu.h>
#include <linux/pm_runtime.h>
+#include <linux/suspend.h>
#include "pci.h"
struct pci_dynid {
@@ -616,6 +617,21 @@ static int pci_pm_prepare(struct device *dev)
int error = 0;
/*
+ * If a PCI device configured to wake up the system from sleep states
+ * has been suspended at run time and there's a resume request pending
+ * for it, this is equivalent to the device signaling wakeup, so the
+ * system suspend operation should be aborted.
+ */
+ pm_runtime_get_noresume(dev);
+ if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+ pm_wakeup_event(dev, 0);
+
+ if (pm_wakeup_pending()) {
+ pm_runtime_put_sync(dev);
+ return -EBUSY;
+ }
+
+ /*
* PCI devices suspended at run time need to be resumed at this
* point, because in general it is necessary to reconfigure them for
* system suspend. Namely, if the device is supposed to wake up the
@@ -624,7 +640,7 @@ static int pci_pm_prepare(struct device *dev)
* system from the sleep state, we'll have to prevent it from signaling
* wake-up.
*/
- pm_runtime_get_sync(dev);
+ pm_runtime_resume(dev);
if (drv && drv->pm && drv->pm->prepare)
error = drv->pm->prepare(dev);
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index 77cb2a14c896..81525ae5d869 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -55,7 +55,7 @@ enum smbios_attr_enum {
SMBIOS_ATTR_INSTANCE_SHOW,
};
-static mode_t
+static size_t
find_smbios_instance_string(struct pci_dev *pdev, char *buf,
enum smbios_attr_enum attribute)
{
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 3a39bf1f1e2c..c8cee764b0de 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -186,8 +186,6 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
return NULL;
}
-struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
-
/* PCI slot sysfs helper code */
#define to_pci_slot(s) container_of(s, struct pci_slot, kobj)
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 6892601fc76f..cbfbab18be91 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -940,7 +940,7 @@ static int __init pcie_aspm_disable(char *str)
printk(KERN_INFO "PCIe ASPM is disabled\n");
} else if (!strcmp(str, "force")) {
aspm_force = 1;
- printk(KERN_INFO "PCIe ASPM is forcedly enabled\n");
+ printk(KERN_INFO "PCIe ASPM is forcibly enabled\n");
}
return 1;
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bafb3c3d4a89..9ab492f21f86 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -52,6 +52,7 @@ static void release_pcibus_dev(struct device *dev)
if (pci_bus->bridge)
put_device(pci_bus->bridge);
pci_bus_remove_resources(pci_bus);
+ pci_release_bus_of_node(pci_bus);
kfree(pci_bus);
}
@@ -588,7 +589,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
child->self = bridge;
child->bridge = get_device(&bridge->dev);
-
+ pci_set_bus_of_node(child);
pci_set_bus_speed(child);
/* Set up default resource pointers and names.. */
@@ -1038,6 +1039,7 @@ static void pci_release_dev(struct device *dev)
pci_dev = to_pci_dev(dev);
pci_release_capabilities(pci_dev);
+ pci_release_of_node(pci_dev);
kfree(pci_dev);
}
@@ -1157,6 +1159,8 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;
+ pci_set_of_node(dev);
+
if (pci_setup_device(dev)) {
kfree(dev);
return NULL;
@@ -1409,6 +1413,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
goto dev_reg_err;
b->bridge = get_device(dev);
device_enable_async_suspend(b->bridge);
+ pci_set_bus_of_node(b);
if (!parent)
set_dev_node(b->bridge, pcibus_to_node(b));
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 02145e9697a9..1196f61a4ab6 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2758,6 +2758,29 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
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
+ * clock frequency from 200Mhz to 50Mhz fixes this issue.
+ *
+ * 0x150 - SD2.0 mode enable for changing base clock
+ * frequency to 50Mhz
+ * 0xe1 - Base clock frequency
+ * 0x32 - 50Mhz new clock frequency
+ * 0xf9 - Key register for 0x150
+ * 0xfc - key register for 0xe1
+ */
+ if (dev->device == PCI_DEVICE_ID_RICOH_R5CE823) {
+ pci_write_config_byte(dev, 0xf9, 0xfc);
+ pci_write_config_byte(dev, 0x150, 0x10);
+ pci_write_config_byte(dev, 0xf9, 0x00);
+ pci_write_config_byte(dev, 0xfc, 0x01);
+ pci_write_config_byte(dev, 0xe1, 0x32);
+ pci_write_config_byte(dev, 0xfc, 0x00);
+
+ dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\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);
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 492b7d807fe8..6fa215a38615 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -16,7 +16,7 @@
#include <xen/interface/io/pciif.h>
#include <asm/xen/pci.h>
#include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/time.h>
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index fb33fa42d249..4902206f53d9 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -283,8 +283,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
}
/* reserve chip-select regions */
- if (!request_mem_region(io->start, io->end + 1 - io->start,
- driver_name)) {
+ if (!request_mem_region(io->start, resource_size(io), driver_name)) {
status = -ENXIO;
goto fail1;
}
@@ -308,7 +307,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
return 0;
fail2:
- release_mem_region(io->start, io->end + 1 - io->start);
+ release_mem_region(io->start, resource_size(io));
fail1:
if (cf->socket.io_offset)
iounmap((void __iomem *) cf->socket.io_offset);
@@ -339,7 +338,7 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
struct resource *io = cf->socket.io[0].res;
pcmcia_unregister_socket(&cf->socket);
- release_mem_region(io->start, io->end + 1 - io->start);
+ release_mem_region(io->start, resource_size(io));
iounmap((void __iomem *) cf->socket.io_offset);
if (board->irq_pin) {
free_irq(board->irq_pin, cf);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 6defd4a8168e..06ad3e5e7d3d 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -209,9 +209,9 @@ static int __devinit electra_cf_probe(struct platform_device *ofdev)
cf->ofdev = ofdev;
cf->mem_phys = mem.start;
- cf->mem_size = PAGE_ALIGN(mem.end - mem.start);
+ cf->mem_size = PAGE_ALIGN(resource_size(&mem));
cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
- cf->io_size = PAGE_ALIGN(io.end - io.start);
+ cf->io_size = PAGE_ALIGN(resource_size(&io));
area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END);
if (area == NULL)
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 81af2b3bcc00..69ae2fd22400 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -48,9 +48,6 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret;
- if (platform_scoop_config->pcmcia_init)
- platform_scoop_config->pcmcia_init();
-
/* Register interrupts */
if (SCOOP_DEV[skt->nr].cd_irq >= 0) {
struct pcmcia_irqs cd_irq;
diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c
index b829e655457b..57ddb969d888 100644
--- a/drivers/pcmcia/pxa2xx_trizeps4.c
+++ b/drivers/pcmcia/pxa2xx_trizeps4.c
@@ -55,10 +55,6 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
}
skt->socket.pci_irq = IRQ_GPIO(GPIO_PRDY);
break;
-
-#ifndef CONFIG_MACH_TRIZEPS_CONXS
- case 1:
-#endif
default:
break;
}
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index 523eb691c30b..f53c237bda2f 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -135,7 +135,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
try = res->end + 1;
if ((*base == 0) || (*base == try)) {
if (adjust_resource(s->io[i].res, res->start,
- res->end - res->start + num + 1))
+ resource_size(res) + num))
continue;
*base = try;
s->io[i].InUse += num;
@@ -147,8 +147,8 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
try = res->start - num;
if ((*base == 0) || (*base == try)) {
if (adjust_resource(s->io[i].res,
- res->start - num,
- res->end - res->start + num + 1))
+ res->start - num,
+ resource_size(res) + num))
continue;
*base = try;
s->io[i].InUse += num;
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index b187555d4388..9da9656242af 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -770,7 +770,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
res->end + num);
if (!ret) {
ret = adjust_resource(s->io[i].res, res->start,
- res->end - res->start + num + 1);
+ resource_size(res) + num);
if (ret)
continue;
*base = try;
@@ -788,8 +788,8 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
res->end);
if (!ret) {
ret = adjust_resource(s->io[i].res,
- res->start - num,
- res->end - res->start + num + 1);
+ res->start - num,
+ resource_size(res) + num);
if (ret)
continue;
*base = try;
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 3c7857c71a23..65b66aa44c78 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -857,7 +857,7 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
int err = asus_wmi_get_devstate(asus, dev_id, &value);
if (err < 0)
- return err;
+ return 0; /* can't return negative here */
}
if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 100e4d9372f1..bbf3edd85beb 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -509,15 +509,15 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
struct acpi_resource_dma *p)
{
int i;
- unsigned char map = 0, flags;
+ unsigned char map = 0, flags = 0;
if (p->channel_count == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
for (i = 0; i < p->channel_count; i++)
map |= 1 << p->channels[i];
- flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
+ flags |= dma_flags(dev, p->type, p->bus_master, p->transfer);
pnp_register_dma_resource(dev, option_flags, map, flags);
}
@@ -527,17 +527,17 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
{
int i;
pnp_irq_mask_t map;
- unsigned char flags;
+ unsigned char flags = 0;
if (p->interrupt_count == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
bitmap_zero(map.bits, PNP_IRQ_NR);
for (i = 0; i < p->interrupt_count; i++)
if (p->interrupts[i])
__set_bit(p->interrupts[i], map.bits);
- flags = irq_flags(p->triggering, p->polarity, p->sharable);
+ flags |= irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
@@ -547,10 +547,10 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
{
int i;
pnp_irq_mask_t map;
- unsigned char flags;
+ unsigned char flags = 0;
if (p->interrupt_count == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
bitmap_zero(map.bits, PNP_IRQ_NR);
for (i = 0; i < p->interrupt_count; i++) {
@@ -564,7 +564,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
}
}
- flags = irq_flags(p->triggering, p->polarity, p->sharable);
+ flags |= irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
@@ -575,10 +575,10 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (io->address_length == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
if (io->io_decode == ACPI_DECODE_16)
- flags = IORESOURCE_IO_16BIT_ADDR;
+ flags |= IORESOURCE_IO_16BIT_ADDR;
pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
io->alignment, io->address_length, flags);
}
@@ -587,11 +587,13 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
unsigned int option_flags,
struct acpi_resource_fixed_io *io)
{
+ unsigned char flags = 0;
+
if (io->address_length == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
pnp_register_port_resource(dev, option_flags, io->address, io->address,
- 0, io->address_length, IORESOURCE_IO_FIXED);
+ 0, io->address_length, flags | IORESOURCE_IO_FIXED);
}
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
@@ -601,10 +603,10 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
- flags = IORESOURCE_MEM_WRITEABLE;
+ flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
p->alignment, p->address_length, flags);
}
@@ -616,10 +618,10 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
- flags = IORESOURCE_MEM_WRITEABLE;
+ flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
p->alignment, p->address_length, flags);
}
@@ -631,10 +633,10 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
- flags = IORESOURCE_MEM_WRITEABLE;
+ flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->address, p->address,
0, p->address_length, flags);
}
@@ -655,18 +657,18 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
}
if (p->address_length == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
- flags = IORESOURCE_MEM_WRITEABLE;
+ flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
flags);
} else if (p->resource_type == ACPI_IO_RANGE)
pnp_register_port_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
- IORESOURCE_IO_FIXED);
+ flags | IORESOURCE_IO_FIXED);
}
static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
@@ -677,18 +679,18 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
- return;
+ flags |= IORESOURCE_DISABLED;
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
- flags = IORESOURCE_MEM_WRITEABLE;
+ flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
flags);
} else if (p->resource_type == ACPI_IO_RANGE)
pnp_register_port_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
- IORESOURCE_IO_FIXED);
+ flags | IORESOURCE_IO_FIXED);
}
struct acpipnp_parse_option_s {
@@ -1018,7 +1020,7 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
io->minimum = p->start;
io->maximum = p->end;
io->alignment = 0; /* Correct? */
- io->address_length = p->end - p->start + 1;
+ io->address_length = resource_size(p);
} else {
io->minimum = 0;
io->address_length = 0;
@@ -1036,7 +1038,7 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
if (pnp_resource_enabled(p)) {
fixed_io->address = p->start;
- fixed_io->address_length = p->end - p->start + 1;
+ fixed_io->address_length = resource_size(p);
} else {
fixed_io->address = 0;
fixed_io->address_length = 0;
@@ -1059,7 +1061,7 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
memory24->minimum = p->start;
memory24->maximum = p->end;
memory24->alignment = 0;
- memory24->address_length = p->end - p->start + 1;
+ memory24->address_length = resource_size(p);
} else {
memory24->minimum = 0;
memory24->address_length = 0;
@@ -1083,7 +1085,7 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
memory32->minimum = p->start;
memory32->maximum = p->end;
memory32->alignment = 0;
- memory32->address_length = p->end - p->start + 1;
+ memory32->address_length = resource_size(p);
} else {
memory32->minimum = 0;
memory32->alignment = 0;
@@ -1106,7 +1108,7 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
p->flags & IORESOURCE_MEM_WRITEABLE ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
fixed_memory32->address = p->start;
- fixed_memory32->address_length = p->end - p->start + 1;
+ fixed_memory32->address_length = resource_size(p);
} else {
fixed_memory32->address = 0;
fixed_memory32->address_length = 0;
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index cb1f47bfee96..cca2f9f9f3e3 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -505,7 +505,7 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -529,7 +529,7 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -559,7 +559,7 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -617,7 +617,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
@@ -636,11 +636,11 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
struct resource *res)
{
unsigned long base = res->start;
- unsigned long len = res->end - res->start + 1;
+ unsigned long len = resource_size(res);
if (pnp_resource_enabled(res)) {
base = res->start;
- len = res->end - res->start + 1;
+ len = resource_size(res);
} else {
base = 0;
len = 0;
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index 4d2dc4fa2888..bfbce5de49da 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2009 Bluewater Systems Ltd
*
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
*
* DS2786 added by Yulia Vilensky <vilensky@compulab.co.il>
*
@@ -416,6 +416,6 @@ static void __exit ds278x_exit(void)
}
module_exit(ds278x_exit);
-MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
+MODULE_AUTHOR("Ryan Mallon");
MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index d7ed20f293d7..118eb213eb3a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -235,6 +235,7 @@ config REGULATOR_TPS6105X
config REGULATOR_TPS65023
tristate "TI TPS65023 Power regulators"
depends on I2C
+ select REGMAP_I2C
help
This driver supports TPS65023 voltage regulator chips. TPS65023 provides
three step-down converters and two general-purpose LDO voltage regulators.
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index fbddc15e1811..701a5900f83f 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -25,6 +25,7 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/regmap.h>
/* Register definitions */
#define TPS65023_REG_VERSION 0
@@ -125,93 +126,35 @@ struct tps_pmic {
struct i2c_client *client;
struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
const struct tps_info *info[TPS65023_NUM_REGULATOR];
- struct mutex io_lock;
+ struct regmap *regmap;
};
-static inline int tps_65023_read(struct tps_pmic *tps, u8 reg)
-{
- return i2c_smbus_read_byte_data(tps->client, reg);
-}
-
-static inline int tps_65023_write(struct tps_pmic *tps, u8 reg, u8 val)
-{
- return i2c_smbus_write_byte_data(tps->client, reg, val);
-}
-
static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask)
{
- int err, data;
-
- mutex_lock(&tps->io_lock);
-
- data = tps_65023_read(tps, reg);
- if (data < 0) {
- dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
- err = data;
- goto out;
- }
-
- data |= mask;
- err = tps_65023_write(tps, reg, data);
- if (err)
- dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
-
-out:
- mutex_unlock(&tps->io_lock);
- return err;
+ return regmap_update_bits(tps->regmap, reg, mask, mask);
}
static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask)
{
- int err, data;
-
- mutex_lock(&tps->io_lock);
-
- data = tps_65023_read(tps, reg);
- if (data < 0) {
- dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
- err = data;
- goto out;
- }
-
- data &= ~mask;
-
- err = tps_65023_write(tps, reg, data);
- if (err)
- dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
-
-out:
- mutex_unlock(&tps->io_lock);
- return err;
-
+ return regmap_update_bits(tps->regmap, reg, mask, 0);
}
static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg)
{
- int data;
+ unsigned int val;
+ int ret;
- mutex_lock(&tps->io_lock);
+ ret = regmap_read(tps->regmap, reg, &val);
- data = tps_65023_read(tps, reg);
- if (data < 0)
- dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
-
- mutex_unlock(&tps->io_lock);
- return data;
+ if (ret != 0)
+ return ret;
+ else
+ return val;
}
static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val)
{
- int err;
-
- mutex_lock(&tps->io_lock);
-
- err = tps_65023_write(tps, reg, val);
- if (err < 0)
- dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
-
- mutex_unlock(&tps->io_lock);
- return err;
+ return regmap_write(tps->regmap, reg, val);
}
static int tps65023_dcdc_is_enabled(struct regulator_dev *dev)
@@ -463,6 +406,11 @@ static struct regulator_ops tps65023_ldo_ops = {
.list_voltage = tps65023_ldo_list_voltage,
};
+static struct regmap_config tps65023_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
static int __devinit tps_65023_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -488,7 +436,13 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
if (!tps)
return -ENOMEM;
- mutex_init(&tps->io_lock);
+ tps->regmap = regmap_init_i2c(client, &tps65023_regmap_config);
+ if (IS_ERR(tps->regmap)) {
+ error = PTR_ERR(tps->regmap);
+ dev_err(&client->dev, "Failed to allocate register map: %d\n",
+ error);
+ goto fail_alloc;
+ }
/* common for all regulators */
tps->client = client;
@@ -527,6 +481,8 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
while (--i >= 0)
regulator_unregister(tps->rdev[i]);
+ regmap_exit(tps->regmap);
+ fail_alloc:
kfree(tps);
return error;
}
@@ -545,6 +501,7 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
regulator_unregister(tps->rdev[i]);
+ regmap_exit(tps->regmap);
kfree(tps);
return 0;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ce2aabf5c550..5a538fc1cc85 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -981,11 +981,11 @@ config RTC_DRV_COH901331
config RTC_DRV_STMP
- tristate "Freescale STMP3xxx RTC"
- depends on ARCH_STMP3XXX
+ tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC"
+ depends on ARCH_MXS
help
If you say yes here you will get support for the onboard
- STMP3xxx RTC.
+ STMP3xxx/i.MX23/i.MX28 RTC.
This driver can also be built as a module. If so, the module
will be called rtc-stmp3xxx.
@@ -1006,10 +1006,10 @@ config RTC_DRV_MC13XXX
config RTC_DRV_MPC5121
tristate "Freescale MPC5121 built-in RTC"
- depends on PPC_MPC512x && RTC_CLASS
+ depends on PPC_MPC512x || PPC_MPC52xx
help
If you say yes here you will get support for the
- built-in RTC MPC5121.
+ built-in RTC on MPC5121 or on MPC5200.
This driver can also be built as a module. If so, the module
will be called rtc-mpc5121.
@@ -1034,6 +1034,16 @@ config RTC_DRV_LPC32XX
This driver can also be buillt as a module. If so, the module
will be called rtc-lpc32xx.
+config RTC_DRV_PM8XXX
+ tristate "Qualcomm PMIC8XXX RTC"
+ depends on MFD_PM8XXX
+ help
+ If you say yes here you get support for the
+ Qualcomm PMIC8XXX RTC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-pm8xxx.
+
config RTC_DRV_TEGRA
tristate "NVIDIA Tegra Internal RTC driver"
depends on RTC_CLASS && ARCH_TEGRA
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 0ffefe877bfa..6e6982335c10 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
+obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o
obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o
obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 4194e59e14cd..01a7df5317c1 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -41,20 +41,41 @@ static void rtc_device_release(struct device *dev)
* system's wall clock; restore it on resume().
*/
-static time_t oldtime;
-static struct timespec oldts;
+static struct timespec old_rtc, old_system, old_delta;
+
static int rtc_suspend(struct device *dev, pm_message_t mesg)
{
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
-
+ struct timespec delta, delta_delta;
if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;
+ /* snapshot the current RTC and system time at suspend*/
rtc_read_time(rtc, &tm);
- ktime_get_ts(&oldts);
- rtc_tm_to_time(&tm, &oldtime);
+ getnstimeofday(&old_system);
+ rtc_tm_to_time(&tm, &old_rtc.tv_sec);
+
+
+ /*
+ * To avoid drift caused by repeated suspend/resumes,
+ * which each can add ~1 second drift error,
+ * try to compensate so the difference in system time
+ * and rtc time stays close to constant.
+ */
+ delta = timespec_sub(old_system, old_rtc);
+ delta_delta = timespec_sub(delta, old_delta);
+ if (abs(delta_delta.tv_sec) >= 2) {
+ /*
+ * if delta_delta is too large, assume time correction
+ * has occured and set old_delta to the current delta.
+ */
+ old_delta = delta;
+ } else {
+ /* Otherwise try to adjust old_system to compensate */
+ old_system = timespec_sub(old_system, delta_delta);
+ }
return 0;
}
@@ -63,32 +84,42 @@ static int rtc_resume(struct device *dev)
{
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
- time_t newtime;
- struct timespec time;
- struct timespec newts;
+ struct timespec new_system, new_rtc;
+ struct timespec sleep_time;
if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;
- ktime_get_ts(&newts);
+ /* snapshot the current rtc and system time at resume */
+ getnstimeofday(&new_system);
rtc_read_time(rtc, &tm);
if (rtc_valid_tm(&tm) != 0) {
pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev));
return 0;
}
- rtc_tm_to_time(&tm, &newtime);
- if (newtime <= oldtime) {
- if (newtime < oldtime)
+ rtc_tm_to_time(&tm, &new_rtc.tv_sec);
+ new_rtc.tv_nsec = 0;
+
+ if (new_rtc.tv_sec <= old_rtc.tv_sec) {
+ if (new_rtc.tv_sec < old_rtc.tv_sec)
pr_debug("%s: time travel!\n", dev_name(&rtc->dev));
return 0;
}
- /* calculate the RTC time delta */
- set_normalized_timespec(&time, newtime - oldtime, 0);
- /* subtract kernel time between rtc_suspend to rtc_resume */
- time = timespec_sub(time, timespec_sub(newts, oldts));
+ /* calculate the RTC time delta (sleep time)*/
+ sleep_time = timespec_sub(new_rtc, old_rtc);
+
+ /*
+ * Since these RTC suspend/resume handlers are not called
+ * at the very end of suspend or the start of resume,
+ * some run-time may pass on either sides of the sleep time
+ * so subtract kernel run-time between rtc_suspend to rtc_resume
+ * to keep things accurate.
+ */
+ sleep_time = timespec_sub(sleep_time,
+ timespec_sub(new_system, old_system));
- timekeeping_inject_sleeptime(&time);
+ timekeeping_inject_sleeptime(&sleep_time);
return 0;
}
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index df68618f6dbb..3195dbd3ec34 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -636,6 +636,29 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
}
EXPORT_SYMBOL_GPL(rtc_irq_unregister);
+static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
+{
+ /*
+ * We unconditionally cancel the timer here, because otherwise
+ * we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+ * when we manage to start the timer before the callback
+ * returns HRTIMER_RESTART.
+ *
+ * We cannot use hrtimer_cancel() here as a running callback
+ * could be blocked on rtc->irq_task_lock and hrtimer_cancel()
+ * would spin forever.
+ */
+ if (hrtimer_try_to_cancel(&rtc->pie_timer) < 0)
+ return -1;
+
+ if (enabled) {
+ ktime_t period = ktime_set(0, NSEC_PER_SEC / rtc->irq_freq);
+
+ hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
+ }
+ return 0;
+}
+
/**
* rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
* @rtc: the rtc device
@@ -651,21 +674,21 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled
int err = 0;
unsigned long flags;
+retry:
spin_lock_irqsave(&rtc->irq_task_lock, flags);
if (rtc->irq_task != NULL && task == NULL)
err = -EBUSY;
if (rtc->irq_task != task)
err = -EACCES;
-
- if (enabled) {
- ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
- hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
- } else {
- hrtimer_cancel(&rtc->pie_timer);
+ if (!err) {
+ if (rtc_update_hrtimer(rtc, enabled) < 0) {
+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+ cpu_relax();
+ goto retry;
+ }
+ rtc->pie_enabled = enabled;
}
- rtc->pie_enabled = enabled;
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-
return err;
}
EXPORT_SYMBOL_GPL(rtc_irq_set_state);
@@ -685,22 +708,20 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
int err = 0;
unsigned long flags;
- if (freq <= 0)
+ if (freq <= 0 || freq > 5000)
return -EINVAL;
-
+retry:
spin_lock_irqsave(&rtc->irq_task_lock, flags);
if (rtc->irq_task != NULL && task == NULL)
err = -EBUSY;
if (rtc->irq_task != task)
err = -EACCES;
- if (err == 0) {
+ if (!err) {
rtc->irq_freq = freq;
- if (rtc->pie_enabled) {
- ktime_t period;
- hrtimer_cancel(&rtc->pie_timer);
- period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
- hrtimer_start(&rtc->pie_timer, period,
- HRTIMER_MODE_REL);
+ if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) {
+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+ cpu_relax();
+ goto retry;
}
}
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index e725d51e773d..8dd08305aae1 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -223,7 +223,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
}
rtc->irq = irq;
- rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ rtc->regs = ioremap(regs->start, resource_size(regs));
if (!rtc->regs) {
ret = -ENOMEM;
dev_dbg(&pdev->dev, "could not map I/O memory\n");
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 911e75cdc125..05beb6c1ca79 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -606,7 +606,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
* (needing ioremap etc), not i/o space resources like this ...
*/
ports = request_region(ports->start,
- ports->end + 1 - ports->start,
+ resource_size(ports),
driver_name);
if (!ports) {
dev_dbg(dev, "i/o registers already in use\n");
@@ -750,7 +750,7 @@ cleanup1:
cmos_rtc.dev = NULL;
rtc_device_unregister(cmos_rtc.rtc);
cleanup0:
- release_region(ports->start, ports->end + 1 - ports->start);
+ release_region(ports->start, resource_size(ports));
return retval;
}
@@ -779,7 +779,7 @@ static void __exit cmos_do_remove(struct device *dev)
cmos->rtc = NULL;
ports = cmos->iomem;
- release_region(ports->start, ports->end + 1 - ports->start);
+ release_region(ports->start, resource_size(ports));
cmos->iomem = NULL;
cmos->dev = NULL;
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
index 47e681df31e2..68e6caf25496 100644
--- a/drivers/rtc/rtc-ds1286.c
+++ b/drivers/rtc/rtc-ds1286.c
@@ -343,7 +343,7 @@ static int __devinit ds1286_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- priv->size = res->end - res->start + 1;
+ priv->size = resource_size(res);
if (!request_mem_region(res->start, priv->size, pdev->name)) {
ret = -EBUSY;
goto out;
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index fbabc773dded..568ad30617e7 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -490,7 +490,7 @@ ds1511_rtc_probe(struct platform_device *pdev)
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- pdata->size = res->end - res->start + 1;
+ pdata->size = resource_size(res);
if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
pdev->name))
return -EBUSY;
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 042630c90dd3..d84a448dd754 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -173,7 +173,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- pdata->size = res->end - res->start + 1;
+ pdata->size = resource_size(res);
if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
pdev->name))
return -EBUSY;
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
index 7410875e5838..8e2a24e33ed6 100644
--- a/drivers/rtc/rtc-m48t35.c
+++ b/drivers/rtc/rtc-m48t35.c
@@ -154,7 +154,7 @@ static int __devinit m48t35_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- priv->size = res->end - res->start + 1;
+ priv->size = resource_size(res);
/*
* kludge: remove the #ifndef after ioc3 resource
* conflicts are resolved
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 3978f4caf724..28365388fb6c 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -433,7 +433,7 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
if (!m48t59->ioaddr) {
/* ioaddr not mapped externally */
- m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
+ m48t59->ioaddr = ioremap(res->start, resource_size(res));
if (!m48t59->ioaddr)
goto out;
}
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 09ccd8d3ba2a..da60915818b6 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -3,6 +3,7 @@
*
* Copyright 2007, Domen Puncer <domen.puncer@telargo.com>
* Copyright 2008, Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright 2011, Dmitry Eremin-Solenikov
*
* 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
@@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
return 0;
}
+static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+ struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+ int tmp;
+
+ tm->tm_sec = in_8(&regs->second);
+ tm->tm_min = in_8(&regs->minute);
+
+ /* 12 hour format? */
+ if (in_8(&regs->hour) & 0x20)
+ tm->tm_hour = (in_8(&regs->hour) >> 1) +
+ (in_8(&regs->hour) & 1 ? 12 : 0);
+ else
+ tm->tm_hour = in_8(&regs->hour);
+
+ tmp = in_8(&regs->wday_mday);
+ tm->tm_mday = tmp & 0x1f;
+ tm->tm_mon = in_8(&regs->month) - 1;
+ tm->tm_year = in_be16(&regs->year) - 1900;
+ tm->tm_wday = (tmp >> 5) % 7;
+ tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+ tm->tm_isdst = 0;
+
+ return 0;
+}
+
+static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+ struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+ mpc5121_rtc_update_smh(regs, tm);
+
+ /* date */
+ out_8(&regs->month_set, tm->tm_mon + 1);
+ out_8(&regs->weekday_set, tm->tm_wday ? tm->tm_wday : 7);
+ out_8(&regs->date_set, tm->tm_mday);
+ out_be16(&regs->year_set, tm->tm_year + 1900);
+
+ /* set date sequence */
+ out_8(&regs->set_date, 0x1);
+ out_8(&regs->set_date, 0x3);
+ out_8(&regs->set_date, 0x1);
+ out_8(&regs->set_date, 0x0);
+
+ return 0;
+}
+
static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
@@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = {
.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
};
+static const struct rtc_class_ops mpc5200_rtc_ops = {
+ .read_time = mpc5200_rtc_read_time,
+ .set_time = mpc5200_rtc_set_time,
+ .read_alarm = mpc5121_rtc_read_alarm,
+ .set_alarm = mpc5121_rtc_set_alarm,
+ .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
+};
+
static int __devinit mpc5121_rtc_probe(struct platform_device *op)
{
struct mpc5121_rtc_data *rtc;
int err = 0;
- u32 ka;
rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
if (!rtc)
@@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op)
goto out_dispose2;
}
- ka = in_be32(&rtc->regs->keep_alive);
- if (ka & 0x02) {
- dev_warn(&op->dev,
- "mpc5121-rtc: Battery or oscillator failure!\n");
- out_be32(&rtc->regs->keep_alive, ka);
+ if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) {
+ u32 ka;
+ ka = in_be32(&rtc->regs->keep_alive);
+ if (ka & 0x02) {
+ dev_warn(&op->dev,
+ "mpc5121-rtc: Battery or oscillator failure!\n");
+ out_be32(&rtc->regs->keep_alive, ka);
+ }
+
+ rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
+ &mpc5121_rtc_ops, THIS_MODULE);
+ } else {
+ rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev,
+ &mpc5200_rtc_ops, THIS_MODULE);
}
- rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
- &mpc5121_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
goto out_free_irq;
@@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op)
static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
{ .compatible = "fsl,mpc5121-rtc", },
+ { .compatible = "fsl,mpc5200-rtc", },
{},
};
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index 0cec5650d56a..d33544802a2e 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -332,9 +332,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
if (!iomem)
return -ENODEV;
- iomem = request_mem_region(iomem->start,
- iomem->end + 1 - iomem->start,
- driver_name);
+ iomem = request_mem_region(iomem->start, resource_size(iomem),
+ driver_name);
if (!iomem) {
dev_dbg(dev, "i/o mem already in use.\n");
return -EBUSY;
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
new file mode 100644
index 000000000000..d420e9d877e8
--- /dev/null
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -0,0 +1,550 @@
+/* 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/rtc.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/rtc.h>
+
+
+/* RTC Register offsets from RTC CTRL REG */
+#define PM8XXX_ALARM_CTRL_OFFSET 0x01
+#define PM8XXX_RTC_WRITE_OFFSET 0x02
+#define PM8XXX_RTC_READ_OFFSET 0x06
+#define PM8XXX_ALARM_RW_OFFSET 0x0A
+
+/* RTC_CTRL register bit fields */
+#define PM8xxx_RTC_ENABLE BIT(7)
+#define PM8xxx_RTC_ALARM_ENABLE BIT(1)
+#define PM8xxx_RTC_ALARM_CLEAR BIT(0)
+
+#define NUM_8_BIT_RTC_REGS 0x4
+
+/**
+ * struct pm8xxx_rtc - rtc driver internal structure
+ * @rtc: rtc device for this driver.
+ * @rtc_alarm_irq: rtc alarm irq number.
+ * @rtc_base: address of rtc control register.
+ * @rtc_read_base: base address of read registers.
+ * @rtc_write_base: base address of write registers.
+ * @alarm_rw_base: base address of alarm registers.
+ * @ctrl_reg: rtc control register.
+ * @rtc_dev: device structure.
+ * @ctrl_reg_lock: spinlock protecting access to ctrl_reg.
+ */
+struct pm8xxx_rtc {
+ struct rtc_device *rtc;
+ int rtc_alarm_irq;
+ int rtc_base;
+ int rtc_read_base;
+ int rtc_write_base;
+ int alarm_rw_base;
+ u8 ctrl_reg;
+ struct device *rtc_dev;
+ spinlock_t ctrl_reg_lock;
+};
+
+/*
+ * The RTC registers need to be read/written one byte at a time. This is a
+ * hardware limitation.
+ */
+static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
+ int base, int count)
+{
+ int i, rc;
+ struct device *parent = rtc_dd->rtc_dev->parent;
+
+ for (i = 0; i < count; i++) {
+ rc = pm8xxx_readb(parent, base + i, &rtc_val[i]);
+ if (rc < 0) {
+ dev_err(rtc_dd->rtc_dev, "PMIC read failed\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
+ int base, int count)
+{
+ int i, rc;
+ struct device *parent = rtc_dd->rtc_dev->parent;
+
+ for (i = 0; i < count; i++) {
+ rc = pm8xxx_writeb(parent, base + i, rtc_val[i]);
+ if (rc < 0) {
+ dev_err(rtc_dd->rtc_dev, "PMIC write failed\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Steps to write the RTC registers.
+ * 1. Disable alarm if enabled.
+ * 2. Write 0x00 to LSB.
+ * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0].
+ * 4. Enable alarm if disabled in step 1.
+ */
+static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ int rc, i;
+ unsigned long secs, irq_flags;
+ u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg;
+ struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ rtc_tm_to_time(tm, &secs);
+
+ for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
+ value[i] = secs & 0xFF;
+ secs >>= 8;
+ }
+
+ dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
+
+ spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+ ctrl_reg = rtc_dd->ctrl_reg;
+
+ if (ctrl_reg & PM8xxx_RTC_ALARM_ENABLE) {
+ alarm_enabled = 1;
+ ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+ rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
+ 1);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC control register "
+ "failed\n");
+ goto rtc_rw_fail;
+ }
+ rtc_dd->ctrl_reg = ctrl_reg;
+ } else
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+ /* Write 0 to Byte[0] */
+ reg = 0;
+ rc = pm8xxx_write_wrapper(rtc_dd, &reg, rtc_dd->rtc_write_base, 1);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC write data register failed\n");
+ goto rtc_rw_fail;
+ }
+
+ /* Write Byte[1], Byte[2], Byte[3] */
+ rc = pm8xxx_write_wrapper(rtc_dd, value + 1,
+ rtc_dd->rtc_write_base + 1, 3);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC write data register failed\n");
+ goto rtc_rw_fail;
+ }
+
+ /* Write Byte[0] */
+ rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC write data register failed\n");
+ goto rtc_rw_fail;
+ }
+
+ if (alarm_enabled) {
+ ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE;
+ rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
+ 1);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC control register "
+ "failed\n");
+ goto rtc_rw_fail;
+ }
+ rtc_dd->ctrl_reg = ctrl_reg;
+ }
+
+rtc_rw_fail:
+ if (alarm_enabled)
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+ return rc;
+}
+
+static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ int rc;
+ u8 value[NUM_8_BIT_RTC_REGS], reg;
+ unsigned long secs;
+ struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base,
+ NUM_8_BIT_RTC_REGS);
+ if (rc < 0) {
+ dev_err(dev, "RTC read data register failed\n");
+ return rc;
+ }
+
+ /*
+ * Read the LSB again and check if there has been a carry over.
+ * If there is, redo the read operation.
+ */
+ rc = pm8xxx_read_wrapper(rtc_dd, &reg, rtc_dd->rtc_read_base, 1);
+ if (rc < 0) {
+ dev_err(dev, "RTC read data register failed\n");
+ return rc;
+ }
+
+ if (unlikely(reg < value[0])) {
+ rc = pm8xxx_read_wrapper(rtc_dd, value,
+ rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS);
+ if (rc < 0) {
+ dev_err(dev, "RTC read data register failed\n");
+ return rc;
+ }
+ }
+
+ secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
+
+ rtc_time_to_tm(secs, tm);
+
+ rc = rtc_valid_tm(tm);
+ if (rc < 0) {
+ dev_err(dev, "Invalid time read from RTC\n");
+ return rc;
+ }
+
+ dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
+ secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
+ tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+ return 0;
+}
+
+static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ int rc, i;
+ u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg;
+ unsigned long secs, irq_flags;
+ struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ rtc_tm_to_time(&alarm->time, &secs);
+
+ for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
+ value[i] = secs & 0xFF;
+ secs >>= 8;
+ }
+
+ spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+ rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base,
+ NUM_8_BIT_RTC_REGS);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC ALARM register failed\n");
+ goto rtc_rw_fail;
+ }
+
+ ctrl_reg = rtc_dd->ctrl_reg;
+ ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+ (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
+
+ rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC control register failed\n");
+ goto rtc_rw_fail;
+ }
+
+ rtc_dd->ctrl_reg = ctrl_reg;
+
+ dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
+ alarm->time.tm_hour, alarm->time.tm_min,
+ alarm->time.tm_sec, alarm->time.tm_mday,
+ alarm->time.tm_mon, alarm->time.tm_year);
+rtc_rw_fail:
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+ return rc;
+}
+
+static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ int rc;
+ u8 value[NUM_8_BIT_RTC_REGS];
+ unsigned long secs;
+ struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base,
+ NUM_8_BIT_RTC_REGS);
+ if (rc < 0) {
+ dev_err(dev, "RTC alarm time read failed\n");
+ return rc;
+ }
+
+ secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
+
+ rtc_time_to_tm(secs, &alarm->time);
+
+ rc = rtc_valid_tm(&alarm->time);
+ if (rc < 0) {
+ dev_err(dev, "Invalid alarm time read from RTC\n");
+ return rc;
+ }
+
+ dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
+ alarm->time.tm_hour, alarm->time.tm_min,
+ alarm->time.tm_sec, alarm->time.tm_mday,
+ alarm->time.tm_mon, alarm->time.tm_year);
+
+ return 0;
+}
+
+static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+ int rc;
+ unsigned long irq_flags;
+ struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+ u8 ctrl_reg;
+
+ spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+ ctrl_reg = rtc_dd->ctrl_reg;
+ ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+ (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
+
+ rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+ if (rc < 0) {
+ dev_err(dev, "Write to RTC control register failed\n");
+ goto rtc_rw_fail;
+ }
+
+ rtc_dd->ctrl_reg = ctrl_reg;
+
+rtc_rw_fail:
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+ return rc;
+}
+
+static struct rtc_class_ops pm8xxx_rtc_ops = {
+ .read_time = pm8xxx_rtc_read_time,
+ .set_alarm = pm8xxx_rtc_set_alarm,
+ .read_alarm = pm8xxx_rtc_read_alarm,
+ .alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id)
+{
+ struct pm8xxx_rtc *rtc_dd = dev_id;
+ u8 ctrl_reg;
+ int rc;
+ unsigned long irq_flags;
+
+ rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF);
+
+ spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+ /* Clear the alarm enable bit */
+ ctrl_reg = rtc_dd->ctrl_reg;
+ ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+
+ rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+ if (rc < 0) {
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+ dev_err(rtc_dd->rtc_dev, "Write to RTC control register "
+ "failed\n");
+ goto rtc_alarm_handled;
+ }
+
+ rtc_dd->ctrl_reg = ctrl_reg;
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+ /* Clear RTC alarm register */
+ rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
+ PM8XXX_ALARM_CTRL_OFFSET, 1);
+ if (rc < 0) {
+ dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read "
+ "failed\n");
+ goto rtc_alarm_handled;
+ }
+
+ ctrl_reg &= ~PM8xxx_RTC_ALARM_CLEAR;
+ rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
+ PM8XXX_ALARM_CTRL_OFFSET, 1);
+ if (rc < 0)
+ dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register"
+ " failed\n");
+
+rtc_alarm_handled:
+ return IRQ_HANDLED;
+}
+
+static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev)
+{
+ int rc;
+ u8 ctrl_reg;
+ bool rtc_write_enable = false;
+ struct pm8xxx_rtc *rtc_dd;
+ struct resource *rtc_resource;
+ const struct pm8xxx_rtc_platform_data *pdata =
+ dev_get_platdata(&pdev->dev);
+
+ if (pdata != NULL)
+ rtc_write_enable = pdata->rtc_write_enable;
+
+ rtc_dd = kzalloc(sizeof(*rtc_dd), GFP_KERNEL);
+ if (rtc_dd == NULL) {
+ dev_err(&pdev->dev, "Unable to allocate memory!\n");
+ return -ENOMEM;
+ }
+
+ /* Initialise spinlock to protect RTC control register */
+ spin_lock_init(&rtc_dd->ctrl_reg_lock);
+
+ rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0);
+ if (rtc_dd->rtc_alarm_irq < 0) {
+ dev_err(&pdev->dev, "Alarm IRQ resource absent!\n");
+ rc = -ENXIO;
+ goto fail_rtc_enable;
+ }
+
+ rtc_resource = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ "pmic_rtc_base");
+ if (!(rtc_resource && rtc_resource->start)) {
+ dev_err(&pdev->dev, "RTC IO resource absent!\n");
+ rc = -ENXIO;
+ goto fail_rtc_enable;
+ }
+
+ rtc_dd->rtc_base = rtc_resource->start;
+
+ /* Setup RTC register addresses */
+ rtc_dd->rtc_write_base = rtc_dd->rtc_base + PM8XXX_RTC_WRITE_OFFSET;
+ rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET;
+ rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET;
+
+ rtc_dd->rtc_dev = &pdev->dev;
+
+ /* Check if the RTC is on, else turn it on */
+ rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "RTC control register read failed!\n");
+ goto fail_rtc_enable;
+ }
+
+ if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) {
+ ctrl_reg |= PM8xxx_RTC_ENABLE;
+ rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
+ 1);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Write to RTC control register "
+ "failed\n");
+ goto fail_rtc_enable;
+ }
+ }
+
+ rtc_dd->ctrl_reg = ctrl_reg;
+ if (rtc_write_enable == true)
+ pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time;
+
+ platform_set_drvdata(pdev, rtc_dd);
+
+ /* Register the RTC device */
+ rtc_dd->rtc = rtc_device_register("pm8xxx_rtc", &pdev->dev,
+ &pm8xxx_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc_dd->rtc)) {
+ dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n",
+ __func__, PTR_ERR(rtc_dd->rtc));
+ rc = PTR_ERR(rtc_dd->rtc);
+ goto fail_rtc_enable;
+ }
+
+ /* Request the alarm IRQ */
+ rc = request_any_context_irq(rtc_dd->rtc_alarm_irq,
+ pm8xxx_alarm_trigger, IRQF_TRIGGER_RISING,
+ "pm8xxx_rtc_alarm", rtc_dd);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc);
+ goto fail_req_irq;
+ }
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ dev_dbg(&pdev->dev, "Probe success !!\n");
+
+ return 0;
+
+fail_req_irq:
+ rtc_device_unregister(rtc_dd->rtc);
+fail_rtc_enable:
+ platform_set_drvdata(pdev, NULL);
+ kfree(rtc_dd);
+ return rc;
+}
+
+static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev)
+{
+ struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
+
+ device_init_wakeup(&pdev->dev, 0);
+ free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
+ rtc_device_unregister(rtc_dd->rtc);
+ platform_set_drvdata(pdev, NULL);
+ kfree(rtc_dd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm8xxx_rtc_resume(struct device *dev)
+{
+ struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(rtc_dd->rtc_alarm_irq);
+
+ return 0;
+}
+
+static int pm8xxx_rtc_suspend(struct device *dev)
+{
+ struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(rtc_dd->rtc_alarm_irq);
+
+ return 0;
+}
+#endif
+
+SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume);
+
+static struct platform_driver pm8xxx_rtc_driver = {
+ .probe = pm8xxx_rtc_probe,
+ .remove = __devexit_p(pm8xxx_rtc_remove),
+ .driver = {
+ .name = PM8XXX_RTC_DEV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &pm8xxx_rtc_pm_ops,
+ },
+};
+
+static int __init pm8xxx_rtc_init(void)
+{
+ return platform_driver_register(&pm8xxx_rtc_driver);
+}
+module_init(pm8xxx_rtc_init);
+
+static void __exit pm8xxx_rtc_exit(void)
+{
+ platform_driver_unregister(&pm8xxx_rtc_driver);
+}
+module_exit(pm8xxx_rtc_exit);
+
+MODULE_ALIAS("platform:rtc-pm8xxx");
+MODULE_DESCRIPTION("PMIC8xxx RTC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>");
diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c
index 46f14b82f3ab..b3eba3cddd42 100644
--- a/drivers/rtc/rtc-puv3.c
+++ b/drivers/rtc/rtc-puv3.c
@@ -267,9 +267,8 @@ static int puv3_rtc_probe(struct platform_device *pdev)
return -ENOENT;
}
- puv3_rtc_mem = request_mem_region(res->start,
- res->end-res->start+1,
- pdev->name);
+ puv3_rtc_mem = request_mem_region(res->start, resource_size(res),
+ pdev->name);
if (puv3_rtc_mem == NULL) {
dev_err(&pdev->dev, "failed to reserve memory region\n");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 16512ecae31a..9329dbb9ebab 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -57,11 +57,13 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
{
struct rtc_device *rdev = id;
+ clk_enable(rtc_clk);
rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
+ clk_disable(rtc_clk);
return IRQ_HANDLED;
}
@@ -69,11 +71,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
{
struct rtc_device *rdev = id;
+ clk_enable(rtc_clk);
rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
+ clk_disable(rtc_clk);
return IRQ_HANDLED;
}
@@ -84,12 +88,14 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
pr_debug("%s: aie=%d\n", __func__, enabled);
+ clk_enable(rtc_clk);
tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
if (enabled)
tmp |= S3C2410_RTCALM_ALMEN;
writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
+ clk_disable(rtc_clk);
return 0;
}
@@ -103,6 +109,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
if (!is_power_of_2(freq))
return -EINVAL;
+ clk_enable(rtc_clk);
spin_lock_irq(&s3c_rtc_pie_lock);
if (s3c_rtc_cpu_type == TYPE_S3C2410) {
@@ -114,6 +121,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
writel(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
+ clk_disable(rtc_clk);
return 0;
}
@@ -125,6 +133,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
unsigned int have_retried = 0;
void __iomem *base = s3c_rtc_base;
+ clk_enable(rtc_clk);
retry_get_time:
rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);
rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
@@ -157,6 +166,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_year += 100;
rtc_tm->tm_mon -= 1;
+ clk_disable(rtc_clk);
return rtc_valid_tm(rtc_tm);
}
@@ -165,6 +175,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
void __iomem *base = s3c_rtc_base;
int year = tm->tm_year - 100;
+ clk_enable(rtc_clk);
pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
@@ -182,6 +193,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
+ clk_disable(rtc_clk);
return 0;
}
@@ -192,6 +204,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
void __iomem *base = s3c_rtc_base;
unsigned int alm_en;
+ clk_enable(rtc_clk);
alm_tm->tm_sec = readb(base + S3C2410_ALMSEC);
alm_tm->tm_min = readb(base + S3C2410_ALMMIN);
alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
@@ -243,6 +256,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
else
alm_tm->tm_year = -1;
+ clk_disable(rtc_clk);
return 0;
}
@@ -252,6 +266,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
void __iomem *base = s3c_rtc_base;
unsigned int alrm_en;
+ clk_enable(rtc_clk);
pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
@@ -282,6 +297,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
s3c_rtc_setaie(dev, alrm->enabled);
+ clk_disable(rtc_clk);
return 0;
}
@@ -289,6 +305,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned int ticnt;
+ clk_enable(rtc_clk);
if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
ticnt &= S3C64XX_RTCCON_TICEN;
@@ -298,6 +315,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
}
seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
+ clk_disable(rtc_clk);
return 0;
}
@@ -360,6 +378,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
if (s3c_rtc_base == NULL)
return;
+ clk_enable(rtc_clk);
if (!en) {
tmp = readw(base + S3C2410_RTCCON);
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
@@ -399,6 +418,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
base + S3C2410_RTCCON);
}
}
+ clk_disable(rtc_clk);
}
static int __devexit s3c_rtc_remove(struct platform_device *dev)
@@ -410,7 +430,6 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
s3c_rtc_setaie(&dev->dev, 0);
- clk_disable(rtc_clk);
clk_put(rtc_clk);
rtc_clk = NULL;
@@ -455,8 +474,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
return -ENOENT;
}
- s3c_rtc_mem = request_mem_region(res->start,
- res->end-res->start+1,
+ s3c_rtc_mem = request_mem_region(res->start, resource_size(res),
pdev->name);
if (s3c_rtc_mem == NULL) {
@@ -465,7 +483,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
goto err_nores;
}
- s3c_rtc_base = ioremap(res->start, res->end - res->start + 1);
+ s3c_rtc_base = ioremap(res->start, resource_size(res));
if (s3c_rtc_base == NULL) {
dev_err(&pdev->dev, "failed ioremap()\n");
ret = -EINVAL;
@@ -530,6 +548,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
s3c_rtc_setfreq(&pdev->dev, 1);
+ clk_disable(rtc_clk);
+
return 0;
err_nortc:
@@ -555,6 +575,7 @@ static int ticnt_save, ticnt_en_save;
static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
+ clk_enable(rtc_clk);
/* save TICNT for anyone using periodic interrupts */
ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
@@ -569,6 +590,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
else
dev_err(&pdev->dev, "enable_irq_wake failed\n");
}
+ clk_disable(rtc_clk);
return 0;
}
@@ -577,6 +599,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
{
unsigned int tmp;
+ clk_enable(rtc_clk);
s3c_rtc_enable(pdev, 1);
writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
@@ -588,6 +611,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
disable_irq_wake(s3c_rtc_alarmno);
wake_en = false;
}
+ clk_disable(rtc_clk);
return 0;
}
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 572e9534b591..7315068daa59 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -6,6 +6,7 @@
*
* Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ * Copyright 2011 Wolfram Sang, Pengutronix e.K.
*/
/*
@@ -18,21 +19,41 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/io.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/slab.h>
-#include <mach/platform.h>
-#include <mach/stmp3xxx.h>
-#include <mach/regs-rtc.h>
+#include <mach/common.h>
+
+#define STMP3XXX_RTC_CTRL 0x0
+#define STMP3XXX_RTC_CTRL_SET 0x4
+#define STMP3XXX_RTC_CTRL_CLR 0x8
+#define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001
+#define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002
+#define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004
+
+#define STMP3XXX_RTC_STAT 0x10
+#define STMP3XXX_RTC_STAT_STALE_SHIFT 16
+#define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000
+
+#define STMP3XXX_RTC_SECONDS 0x30
+
+#define STMP3XXX_RTC_ALARM 0x40
+
+#define STMP3XXX_RTC_PERSISTENT0 0x60
+#define STMP3XXX_RTC_PERSISTENT0_SET 0x64
+#define STMP3XXX_RTC_PERSISTENT0_CLR 0x68
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080
struct stmp3xxx_rtc_data {
struct rtc_device *rtc;
- unsigned irq_count;
void __iomem *io;
- int irq_alarm, irq_1msec;
+ int irq_alarm;
};
static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
@@ -42,8 +63,8 @@ static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
* NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,
* 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS
*/
- while (__raw_readl(rtc_data->io + HW_RTC_STAT) &
- BF(0x80, RTC_STAT_STALE_REGS))
+ while (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
+ (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))
cpu_relax();
}
@@ -53,7 +74,7 @@ static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
stmp3xxx_wait_time(rtc_data);
- rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm);
+ rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
return 0;
}
@@ -61,7 +82,7 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
{
struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
- __raw_writel(t, rtc_data->io + HW_RTC_SECONDS);
+ writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);
stmp3xxx_wait_time(rtc_data);
return 0;
}
@@ -70,47 +91,34 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
{
struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id);
- u32 status;
- u32 events = 0;
-
- status = __raw_readl(rtc_data->io + HW_RTC_CTRL) &
- (BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ);
+ u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL);
- if (status & BM_RTC_CTRL_ALARM_IRQ) {
- stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ,
- rtc_data->io + HW_RTC_CTRL);
- events |= RTC_AF | RTC_IRQF;
+ if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
+ writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
+ rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+ rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
+ return IRQ_HANDLED;
}
- if (status & BM_RTC_CTRL_ONEMSEC_IRQ) {
- stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ,
- rtc_data->io + HW_RTC_CTRL);
- if (++rtc_data->irq_count % 1000 == 0) {
- events |= RTC_UF | RTC_IRQF;
- rtc_data->irq_count = 0;
- }
- }
-
- if (events)
- rtc_update_irq(rtc_data->rtc, 1, events);
-
- return IRQ_HANDLED;
+ return IRQ_NONE;
}
static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
- void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0,
- *ctl = rtc_data->io + HW_RTC_CTRL;
if (enabled) {
- stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN |
- BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p);
- stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl);
+ writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+ STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+ writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+ rtc_data->io + STMP3XXX_RTC_CTRL_SET);
} else {
- stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
- BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p);
- stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl);
+ writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+ STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+ writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+ rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
}
return 0;
}
@@ -119,7 +127,7 @@ static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
- rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time);
+ rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
return 0;
}
@@ -129,7 +137,10 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
rtc_tm_to_time(&alm->time, &t);
- __raw_writel(t, rtc_data->io + HW_RTC_ALARM);
+ writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
+
+ stmp3xxx_alarm_irq_enable(dev, alm->enabled);
+
return 0;
}
@@ -149,11 +160,11 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)
if (!rtc_data)
return 0;
- stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN,
- rtc_data->io + HW_RTC_CTRL);
+ writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+ rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
free_irq(rtc_data->irq_alarm, &pdev->dev);
- free_irq(rtc_data->irq_1msec, &pdev->dev);
rtc_device_unregister(rtc_data->rtc);
+ platform_set_drvdata(pdev, NULL);
iounmap(rtc_data->io);
kfree(rtc_data);
@@ -185,20 +196,26 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
}
rtc_data->irq_alarm = platform_get_irq(pdev, 0);
- rtc_data->irq_1msec = platform_get_irq(pdev, 1);
- if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) &
- BM_RTC_STAT_RTC_PRESENT)) {
+ if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) &
+ STMP3XXX_RTC_STAT_RTC_PRESENT)) {
dev_err(&pdev->dev, "no device onboard\n");
err = -ENODEV;
goto out_remap;
}
- stmp3xxx_reset_block(rtc_data->io, true);
- stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
- BM_RTC_PERSISTENT0_ALARM_WAKE_EN |
- BM_RTC_PERSISTENT0_ALARM_WAKE,
- rtc_data->io + HW_RTC_PERSISTENT0);
+ platform_set_drvdata(pdev, rtc_data);
+
+ mxs_reset_block(rtc_data->io);
+ writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+ STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
+ STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+
+ writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
+ STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+ rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+
rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev,
&stmp3xxx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc_data->rtc)) {
@@ -206,33 +223,20 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
goto out_remap;
}
- rtc_data->irq_count = 0;
- err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt,
- IRQF_DISABLED, "RTC alarm", &pdev->dev);
+ err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, 0,
+ "RTC alarm", &pdev->dev);
if (err) {
dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
rtc_data->irq_alarm);
goto out_irq_alarm;
}
- err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt,
- IRQF_DISABLED, "RTC tick", &pdev->dev);
- if (err) {
- dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
- rtc_data->irq_1msec);
- goto out_irq1;
- }
-
- platform_set_drvdata(pdev, rtc_data);
return 0;
-out_irq1:
- free_irq(rtc_data->irq_alarm, &pdev->dev);
out_irq_alarm:
- stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN,
- rtc_data->io + HW_RTC_CTRL);
rtc_device_unregister(rtc_data->rtc);
out_remap:
+ platform_set_drvdata(pdev, NULL);
iounmap(rtc_data->io);
out_free:
kfree(rtc_data);
@@ -249,11 +253,11 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev)
{
struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev);
- stmp3xxx_reset_block(rtc_data->io, true);
- stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
- BM_RTC_PERSISTENT0_ALARM_WAKE_EN |
- BM_RTC_PERSISTENT0_ALARM_WAKE,
- rtc_data->io + HW_RTC_PERSISTENT0);
+ mxs_reset_block(rtc_data->io);
+ writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+ STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
+ STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
return 0;
}
#else
@@ -286,5 +290,6 @@ module_init(stmp3xxx_rtc_init);
module_exit(stmp3xxx_rtc_exit);
MODULE_DESCRIPTION("STMP3xxx RTC Driver");
-MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
+MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
+ "Wolfram Sang <w.sang@pengutronix.de>");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 2fc31aac3f4e..75259fe38602 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -343,7 +343,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
/* set context info. */
info->pdev = pdev;
- info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock);
+ spin_lock_init(&info->tegra_rtc_lock);
platform_set_drvdata(pdev, info);
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index f9a2799c44d6..9a81f778d6b2 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -275,7 +275,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
goto out;
save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
- twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+ ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
if (ret < 0)
goto out;
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index efd6066b5cd2..f93f412423c6 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -74,6 +74,8 @@
#define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */
#define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */
+#define VT8500_RTC_IS_ALARM (1 << 0) /* Alarm interrupt status */
+
struct vt8500_rtc {
void __iomem *regbase;
struct resource *res;
@@ -96,7 +98,7 @@ static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id)
spin_unlock(&vt8500_rtc->lock);
- if (isr & 1)
+ if (isr & VT8500_RTC_IS_ALARM)
events |= RTC_AF | RTC_IRQF;
rtc_update_irq(vt8500_rtc->rtc, 1, events);
@@ -161,8 +163,8 @@ static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK));
alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0;
+ alrm->pending = (isr & VT8500_RTC_IS_ALARM) ? 1 : 0;
- alrm->pending = (isr & 1) ? 1 : 0;
return rtc_valid_tm(&alrm->time);
}
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 86b6f1cc1b10..432444af7ee4 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -22,6 +22,8 @@
#include <linux/hdreg.h>
#include <linux/async.h>
#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -45,6 +47,7 @@
* SECTION: exported variables of dasd.c
*/
debug_info_t *dasd_debug_area;
+static struct dentry *dasd_debugfs_root_entry;
struct dasd_discipline *dasd_diag_discipline_pointer;
void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
@@ -71,6 +74,8 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
static void dasd_device_timeout(unsigned long);
static void dasd_block_timeout(unsigned long);
static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *);
+static void dasd_profile_init(struct dasd_profile *, struct dentry *);
+static void dasd_profile_exit(struct dasd_profile *);
/*
* SECTION: Operations on the device structure.
@@ -121,7 +126,7 @@ struct dasd_device *dasd_alloc_device(void)
device->state = DASD_STATE_NEW;
device->target = DASD_STATE_NEW;
mutex_init(&device->state_mutex);
-
+ spin_lock_init(&device->profile.lock);
return device;
}
@@ -159,6 +164,7 @@ struct dasd_block *dasd_alloc_block(void)
init_timer(&block->timer);
block->timer.function = dasd_block_timeout;
block->timer.data = (unsigned long) block;
+ spin_lock_init(&block->profile.lock);
return block;
}
@@ -222,19 +228,44 @@ static int dasd_state_known_to_new(struct dasd_device *device)
return 0;
}
+static struct dentry *dasd_debugfs_setup(const char *name,
+ struct dentry *base_dentry)
+{
+ struct dentry *pde;
+
+ if (!base_dentry)
+ return NULL;
+ pde = debugfs_create_dir(name, base_dentry);
+ if (!pde || IS_ERR(pde))
+ return NULL;
+ return pde;
+}
+
/*
* Request the irq line for the device.
*/
static int dasd_state_known_to_basic(struct dasd_device *device)
{
+ struct dasd_block *block = device->block;
int rc;
/* Allocate and register gendisk structure. */
- if (device->block) {
- rc = dasd_gendisk_alloc(device->block);
+ if (block) {
+ rc = dasd_gendisk_alloc(block);
if (rc)
return rc;
- }
+ block->debugfs_dentry =
+ dasd_debugfs_setup(block->gdp->disk_name,
+ dasd_debugfs_root_entry);
+ dasd_profile_init(&block->profile, block->debugfs_dentry);
+ if (dasd_global_profile_level == DASD_PROFILE_ON)
+ dasd_profile_on(&device->block->profile);
+ }
+ device->debugfs_dentry =
+ dasd_debugfs_setup(dev_name(&device->cdev->dev),
+ dasd_debugfs_root_entry);
+ dasd_profile_init(&device->profile, device->debugfs_dentry);
+
/* register 'device' debug area, used for all DBF_DEV_XXX calls */
device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1,
8 * sizeof(long));
@@ -253,6 +284,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
{
int rc;
if (device->block) {
+ dasd_profile_exit(&device->block->profile);
+ if (device->block->debugfs_dentry)
+ debugfs_remove(device->block->debugfs_dentry);
dasd_gendisk_free(device->block);
dasd_block_clear_timer(device->block);
}
@@ -260,6 +294,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
if (rc)
return rc;
dasd_device_clear_timer(device);
+ dasd_profile_exit(&device->profile);
+ if (device->debugfs_dentry)
+ debugfs_remove(device->debugfs_dentry);
DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
if (device->debug_area != NULL) {
@@ -609,21 +646,13 @@ void dasd_enable_device(struct dasd_device *device)
/*
* SECTION: device operation (interrupt handler, start i/o, term i/o ...)
*/
-#ifdef CONFIG_DASD_PROFILE
-struct dasd_profile_info_t dasd_global_profile;
-unsigned int dasd_profile_level = DASD_PROFILE_OFF;
+unsigned int dasd_global_profile_level = DASD_PROFILE_OFF;
-/*
- * Increments counter in global and local profiling structures.
- */
-#define dasd_profile_counter(value, counter, block) \
-{ \
- int index; \
- for (index = 0; index < 31 && value >> (2+index); index++); \
- dasd_global_profile.counter[index]++; \
- block->profile.counter[index]++; \
-}
+#ifdef CONFIG_DASD_PROFILE
+struct dasd_profile_info dasd_global_profile_data;
+static struct dentry *dasd_global_profile_dentry;
+static struct dentry *dasd_debugfs_global_entry;
/*
* Add profiling information for cqr before execution.
@@ -634,30 +663,121 @@ static void dasd_profile_start(struct dasd_block *block,
{
struct list_head *l;
unsigned int counter;
-
- if (dasd_profile_level != DASD_PROFILE_ON)
- return;
+ struct dasd_device *device;
/* count the length of the chanq for statistics */
counter = 0;
- list_for_each(l, &block->ccw_queue)
- if (++counter >= 31)
- break;
- dasd_global_profile.dasd_io_nr_req[counter]++;
- block->profile.dasd_io_nr_req[counter]++;
+ if (dasd_global_profile_level || block->profile.data)
+ list_for_each(l, &block->ccw_queue)
+ if (++counter >= 31)
+ break;
+
+ if (dasd_global_profile_level) {
+ dasd_global_profile_data.dasd_io_nr_req[counter]++;
+ if (rq_data_dir(req) == READ)
+ dasd_global_profile_data.dasd_read_nr_req[counter]++;
+ }
+
+ spin_lock(&block->profile.lock);
+ if (block->profile.data)
+ block->profile.data->dasd_io_nr_req[counter]++;
+ if (rq_data_dir(req) == READ)
+ block->profile.data->dasd_read_nr_req[counter]++;
+ spin_unlock(&block->profile.lock);
+
+ /*
+ * We count the request for the start device, even though it may run on
+ * some other device due to error recovery. This way we make sure that
+ * we count each request only once.
+ */
+ device = cqr->startdev;
+ if (device->profile.data) {
+ counter = 1; /* request is not yet queued on the start device */
+ list_for_each(l, &device->ccw_queue)
+ if (++counter >= 31)
+ break;
+ }
+ spin_lock(&device->profile.lock);
+ if (device->profile.data) {
+ device->profile.data->dasd_io_nr_req[counter]++;
+ if (rq_data_dir(req) == READ)
+ device->profile.data->dasd_read_nr_req[counter]++;
+ }
+ spin_unlock(&device->profile.lock);
}
/*
* Add profiling information for cqr after execution.
*/
+
+#define dasd_profile_counter(value, index) \
+{ \
+ for (index = 0; index < 31 && value >> (2+index); index++) \
+ ; \
+}
+
+static void dasd_profile_end_add_data(struct dasd_profile_info *data,
+ int is_alias,
+ int is_tpm,
+ int is_read,
+ long sectors,
+ int sectors_ind,
+ int tottime_ind,
+ int tottimeps_ind,
+ int strtime_ind,
+ int irqtime_ind,
+ int irqtimeps_ind,
+ int endtime_ind)
+{
+ /* in case of an overflow, reset the whole profile */
+ if (data->dasd_io_reqs == UINT_MAX) {
+ memset(data, 0, sizeof(*data));
+ getnstimeofday(&data->starttod);
+ }
+ data->dasd_io_reqs++;
+ data->dasd_io_sects += sectors;
+ if (is_alias)
+ data->dasd_io_alias++;
+ if (is_tpm)
+ data->dasd_io_tpm++;
+
+ data->dasd_io_secs[sectors_ind]++;
+ data->dasd_io_times[tottime_ind]++;
+ data->dasd_io_timps[tottimeps_ind]++;
+ data->dasd_io_time1[strtime_ind]++;
+ data->dasd_io_time2[irqtime_ind]++;
+ data->dasd_io_time2ps[irqtimeps_ind]++;
+ data->dasd_io_time3[endtime_ind]++;
+
+ if (is_read) {
+ data->dasd_read_reqs++;
+ data->dasd_read_sects += sectors;
+ if (is_alias)
+ data->dasd_read_alias++;
+ if (is_tpm)
+ data->dasd_read_tpm++;
+ data->dasd_read_secs[sectors_ind]++;
+ data->dasd_read_times[tottime_ind]++;
+ data->dasd_read_time1[strtime_ind]++;
+ data->dasd_read_time2[irqtime_ind]++;
+ data->dasd_read_time3[endtime_ind]++;
+ }
+}
+
static void dasd_profile_end(struct dasd_block *block,
struct dasd_ccw_req *cqr,
struct request *req)
{
long strtime, irqtime, endtime, tottime; /* in microseconds */
long tottimeps, sectors;
+ struct dasd_device *device;
+ int sectors_ind, tottime_ind, tottimeps_ind, strtime_ind;
+ int irqtime_ind, irqtimeps_ind, endtime_ind;
- if (dasd_profile_level != DASD_PROFILE_ON)
+ device = cqr->startdev;
+ if (!(dasd_global_profile_level ||
+ block->profile.data ||
+ device->profile.data))
return;
sectors = blk_rq_sectors(req);
@@ -672,29 +792,392 @@ static void dasd_profile_end(struct dasd_block *block,
tottime = ((cqr->endclk - cqr->buildclk) >> 12);
tottimeps = tottime / sectors;
- if (!dasd_global_profile.dasd_io_reqs)
- memset(&dasd_global_profile, 0,
- sizeof(struct dasd_profile_info_t));
- dasd_global_profile.dasd_io_reqs++;
- dasd_global_profile.dasd_io_sects += sectors;
-
- if (!block->profile.dasd_io_reqs)
- memset(&block->profile, 0,
- sizeof(struct dasd_profile_info_t));
- block->profile.dasd_io_reqs++;
- block->profile.dasd_io_sects += sectors;
-
- dasd_profile_counter(sectors, dasd_io_secs, block);
- dasd_profile_counter(tottime, dasd_io_times, block);
- dasd_profile_counter(tottimeps, dasd_io_timps, block);
- dasd_profile_counter(strtime, dasd_io_time1, block);
- dasd_profile_counter(irqtime, dasd_io_time2, block);
- dasd_profile_counter(irqtime / sectors, dasd_io_time2ps, block);
- dasd_profile_counter(endtime, dasd_io_time3, block);
+ dasd_profile_counter(sectors, sectors_ind);
+ dasd_profile_counter(tottime, tottime_ind);
+ dasd_profile_counter(tottimeps, tottimeps_ind);
+ dasd_profile_counter(strtime, strtime_ind);
+ dasd_profile_counter(irqtime, irqtime_ind);
+ dasd_profile_counter(irqtime / sectors, irqtimeps_ind);
+ dasd_profile_counter(endtime, endtime_ind);
+
+ if (dasd_global_profile_level) {
+ dasd_profile_end_add_data(&dasd_global_profile_data,
+ cqr->startdev != block->base,
+ cqr->cpmode == 1,
+ rq_data_dir(req) == READ,
+ sectors, sectors_ind, tottime_ind,
+ tottimeps_ind, strtime_ind,
+ irqtime_ind, irqtimeps_ind,
+ endtime_ind);
+ }
+
+ spin_lock(&block->profile.lock);
+ if (block->profile.data)
+ dasd_profile_end_add_data(block->profile.data,
+ cqr->startdev != block->base,
+ cqr->cpmode == 1,
+ rq_data_dir(req) == READ,
+ sectors, sectors_ind, tottime_ind,
+ tottimeps_ind, strtime_ind,
+ irqtime_ind, irqtimeps_ind,
+ endtime_ind);
+ spin_unlock(&block->profile.lock);
+
+ spin_lock(&device->profile.lock);
+ if (device->profile.data)
+ dasd_profile_end_add_data(device->profile.data,
+ cqr->startdev != block->base,
+ cqr->cpmode == 1,
+ rq_data_dir(req) == READ,
+ sectors, sectors_ind, tottime_ind,
+ tottimeps_ind, strtime_ind,
+ irqtime_ind, irqtimeps_ind,
+ endtime_ind);
+ spin_unlock(&device->profile.lock);
+}
+
+void dasd_profile_reset(struct dasd_profile *profile)
+{
+ struct dasd_profile_info *data;
+
+ spin_lock_bh(&profile->lock);
+ data = profile->data;
+ if (!data) {
+ spin_unlock_bh(&profile->lock);
+ return;
+ }
+ memset(data, 0, sizeof(*data));
+ getnstimeofday(&data->starttod);
+ spin_unlock_bh(&profile->lock);
+}
+
+void dasd_global_profile_reset(void)
+{
+ memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data));
+ getnstimeofday(&dasd_global_profile_data.starttod);
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+ struct dasd_profile_info *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ spin_lock_bh(&profile->lock);
+ if (profile->data) {
+ spin_unlock_bh(&profile->lock);
+ kfree(data);
+ return 0;
+ }
+ getnstimeofday(&data->starttod);
+ profile->data = data;
+ spin_unlock_bh(&profile->lock);
+ return 0;
+}
+
+void dasd_profile_off(struct dasd_profile *profile)
+{
+ spin_lock_bh(&profile->lock);
+ kfree(profile->data);
+ profile->data = NULL;
+ spin_unlock_bh(&profile->lock);
+}
+
+char *dasd_get_user_string(const char __user *user_buf, size_t user_len)
+{
+ char *buffer;
+
+ buffer = kmalloc(user_len + 1, GFP_KERNEL);
+ if (buffer == NULL)
+ return ERR_PTR(-ENOMEM);
+ if (copy_from_user(buffer, user_buf, user_len) != 0) {
+ kfree(buffer);
+ return ERR_PTR(-EFAULT);
+ }
+ /* got the string, now strip linefeed. */
+ if (buffer[user_len - 1] == '\n')
+ buffer[user_len - 1] = 0;
+ else
+ buffer[user_len] = 0;
+ return buffer;
}
+
+static ssize_t dasd_stats_write(struct file *file,
+ const char __user *user_buf,
+ size_t user_len, loff_t *pos)
+{
+ char *buffer, *str;
+ int rc;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct dasd_profile *prof = m->private;
+
+ if (user_len > 65536)
+ user_len = 65536;
+ buffer = dasd_get_user_string(user_buf, user_len);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+
+ str = skip_spaces(buffer);
+ rc = user_len;
+ if (strncmp(str, "reset", 5) == 0) {
+ dasd_profile_reset(prof);
+ } else if (strncmp(str, "on", 2) == 0) {
+ rc = dasd_profile_on(prof);
+ if (!rc)
+ rc = user_len;
+ } else if (strncmp(str, "off", 3) == 0) {
+ dasd_profile_off(prof);
+ } else
+ rc = -EINVAL;
+ kfree(buffer);
+ return rc;
+}
+
+static void dasd_stats_array(struct seq_file *m, unsigned int *array)
+{
+ int i;
+
+ for (i = 0; i < 32; i++)
+ seq_printf(m, "%u ", array[i]);
+ seq_putc(m, '\n');
+}
+
+static void dasd_stats_seq_print(struct seq_file *m,
+ struct dasd_profile_info *data)
+{
+ seq_printf(m, "start_time %ld.%09ld\n",
+ data->starttod.tv_sec, data->starttod.tv_nsec);
+ seq_printf(m, "total_requests %u\n", data->dasd_io_reqs);
+ seq_printf(m, "total_sectors %u\n", data->dasd_io_sects);
+ seq_printf(m, "total_pav %u\n", data->dasd_io_alias);
+ seq_printf(m, "total_hpf %u\n", data->dasd_io_tpm);
+ seq_printf(m, "histogram_sectors ");
+ dasd_stats_array(m, data->dasd_io_secs);
+ seq_printf(m, "histogram_io_times ");
+ dasd_stats_array(m, data->dasd_io_times);
+ seq_printf(m, "histogram_io_times_weighted ");
+ dasd_stats_array(m, data->dasd_io_timps);
+ seq_printf(m, "histogram_time_build_to_ssch ");
+ dasd_stats_array(m, data->dasd_io_time1);
+ seq_printf(m, "histogram_time_ssch_to_irq ");
+ dasd_stats_array(m, data->dasd_io_time2);
+ seq_printf(m, "histogram_time_ssch_to_irq_weighted ");
+ dasd_stats_array(m, data->dasd_io_time2ps);
+ seq_printf(m, "histogram_time_irq_to_end ");
+ dasd_stats_array(m, data->dasd_io_time3);
+ seq_printf(m, "histogram_ccw_queue_length ");
+ dasd_stats_array(m, data->dasd_io_nr_req);
+ seq_printf(m, "total_read_requests %u\n", data->dasd_read_reqs);
+ seq_printf(m, "total_read_sectors %u\n", data->dasd_read_sects);
+ seq_printf(m, "total_read_pav %u\n", data->dasd_read_alias);
+ seq_printf(m, "total_read_hpf %u\n", data->dasd_read_tpm);
+ seq_printf(m, "histogram_read_sectors ");
+ dasd_stats_array(m, data->dasd_read_secs);
+ seq_printf(m, "histogram_read_times ");
+ dasd_stats_array(m, data->dasd_read_times);
+ seq_printf(m, "histogram_read_time_build_to_ssch ");
+ dasd_stats_array(m, data->dasd_read_time1);
+ seq_printf(m, "histogram_read_time_ssch_to_irq ");
+ dasd_stats_array(m, data->dasd_read_time2);
+ seq_printf(m, "histogram_read_time_irq_to_end ");
+ dasd_stats_array(m, data->dasd_read_time3);
+ seq_printf(m, "histogram_read_ccw_queue_length ");
+ dasd_stats_array(m, data->dasd_read_nr_req);
+}
+
+static int dasd_stats_show(struct seq_file *m, void *v)
+{
+ struct dasd_profile *profile;
+ struct dasd_profile_info *data;
+
+ profile = m->private;
+ spin_lock_bh(&profile->lock);
+ data = profile->data;
+ if (!data) {
+ spin_unlock_bh(&profile->lock);
+ seq_printf(m, "disabled\n");
+ return 0;
+ }
+ dasd_stats_seq_print(m, data);
+ spin_unlock_bh(&profile->lock);
+ return 0;
+}
+
+static int dasd_stats_open(struct inode *inode, struct file *file)
+{
+ struct dasd_profile *profile = inode->i_private;
+ return single_open(file, dasd_stats_show, profile);
+}
+
+static const struct file_operations dasd_stats_raw_fops = {
+ .owner = THIS_MODULE,
+ .open = dasd_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = dasd_stats_write,
+};
+
+static ssize_t dasd_stats_global_write(struct file *file,
+ const char __user *user_buf,
+ size_t user_len, loff_t *pos)
+{
+ char *buffer, *str;
+ ssize_t rc;
+
+ if (user_len > 65536)
+ user_len = 65536;
+ buffer = dasd_get_user_string(user_buf, user_len);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+ str = skip_spaces(buffer);
+ rc = user_len;
+ if (strncmp(str, "reset", 5) == 0) {
+ dasd_global_profile_reset();
+ } else if (strncmp(str, "on", 2) == 0) {
+ dasd_global_profile_reset();
+ dasd_global_profile_level = DASD_PROFILE_GLOBAL_ONLY;
+ } else if (strncmp(str, "off", 3) == 0) {
+ dasd_global_profile_level = DASD_PROFILE_OFF;
+ } else
+ rc = -EINVAL;
+ kfree(buffer);
+ return rc;
+}
+
+static int dasd_stats_global_show(struct seq_file *m, void *v)
+{
+ if (!dasd_global_profile_level) {
+ seq_printf(m, "disabled\n");
+ return 0;
+ }
+ dasd_stats_seq_print(m, &dasd_global_profile_data);
+ return 0;
+}
+
+static int dasd_stats_global_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dasd_stats_global_show, NULL);
+}
+
+static const struct file_operations dasd_stats_global_fops = {
+ .owner = THIS_MODULE,
+ .open = dasd_stats_global_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = dasd_stats_global_write,
+};
+
+static void dasd_profile_init(struct dasd_profile *profile,
+ struct dentry *base_dentry)
+{
+ mode_t mode;
+ struct dentry *pde;
+
+ if (!base_dentry)
+ return;
+ profile->dentry = NULL;
+ profile->data = NULL;
+ mode = (S_IRUSR | S_IWUSR | S_IFREG);
+ pde = debugfs_create_file("statistics", mode, base_dentry,
+ profile, &dasd_stats_raw_fops);
+ if (pde && !IS_ERR(pde))
+ profile->dentry = pde;
+ return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+ dasd_profile_off(profile);
+ if (profile->dentry) {
+ debugfs_remove(profile->dentry);
+ profile->dentry = NULL;
+ }
+}
+
+static void dasd_statistics_removeroot(void)
+{
+ dasd_global_profile_level = DASD_PROFILE_OFF;
+ if (dasd_global_profile_dentry) {
+ debugfs_remove(dasd_global_profile_dentry);
+ dasd_global_profile_dentry = NULL;
+ }
+ if (dasd_debugfs_global_entry)
+ debugfs_remove(dasd_debugfs_global_entry);
+ if (dasd_debugfs_root_entry)
+ debugfs_remove(dasd_debugfs_root_entry);
+}
+
+static void dasd_statistics_createroot(void)
+{
+ mode_t mode;
+ struct dentry *pde;
+
+ dasd_debugfs_root_entry = NULL;
+ dasd_debugfs_global_entry = NULL;
+ dasd_global_profile_dentry = NULL;
+ pde = debugfs_create_dir("dasd", NULL);
+ if (!pde || IS_ERR(pde))
+ goto error;
+ dasd_debugfs_root_entry = pde;
+ pde = debugfs_create_dir("global", dasd_debugfs_root_entry);
+ if (!pde || IS_ERR(pde))
+ goto error;
+ dasd_debugfs_global_entry = pde;
+
+ mode = (S_IRUSR | S_IWUSR | S_IFREG);
+ pde = debugfs_create_file("statistics", mode, dasd_debugfs_global_entry,
+ NULL, &dasd_stats_global_fops);
+ if (!pde || IS_ERR(pde))
+ goto error;
+ dasd_global_profile_dentry = pde;
+ return;
+
+error:
+ DBF_EVENT(DBF_ERR, "%s",
+ "Creation of the dasd debugfs interface failed");
+ dasd_statistics_removeroot();
+ return;
+}
+
#else
#define dasd_profile_start(block, cqr, req) do {} while (0)
#define dasd_profile_end(block, cqr, req) do {} while (0)
+
+static void dasd_statistics_createroot(void)
+{
+ return;
+}
+
+static void dasd_statistics_removeroot(void)
+{
+ return;
+}
+
+int dasd_stats_generic_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "Statistics are not activated in this kernel\n");
+ return 0;
+}
+
+static void dasd_profile_init(struct dasd_profile *profile,
+ struct dentry *base_dentry)
+{
+ return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+ return;
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+ return 0;
+}
+
#endif /* CONFIG_DASD_PROFILE */
/*
@@ -2441,6 +2924,7 @@ dasd_exit(void)
debug_unregister(dasd_debug_area);
dasd_debug_area = NULL;
}
+ dasd_statistics_removeroot();
}
/*
@@ -2992,6 +3476,8 @@ static int __init dasd_init(void)
dasd_diag_discipline_pointer = NULL;
+ dasd_statistics_createroot();
+
rc = dasd_devmap_init();
if (rc)
goto failed;
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 77f778b7b070..16c5208c3dc7 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -21,7 +21,7 @@
#include <linux/slab.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/ebcdic.h>
#include "dasd_int.h"
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d1e4f2c1264c..1dd12bd85a69 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -382,6 +382,41 @@ struct dasd_path {
__u8 npm;
};
+struct dasd_profile_info {
+ /* legacy part of profile data, as in dasd_profile_info_t */
+ unsigned int dasd_io_reqs; /* number of requests processed */
+ unsigned int dasd_io_sects; /* number of sectors processed */
+ unsigned int dasd_io_secs[32]; /* histogram of request's sizes */
+ unsigned int dasd_io_times[32]; /* histogram of requests's times */
+ unsigned int dasd_io_timps[32]; /* h. of requests's times per sector */
+ unsigned int dasd_io_time1[32]; /* hist. of time from build to start */
+ unsigned int dasd_io_time2[32]; /* hist. of time from start to irq */
+ unsigned int dasd_io_time2ps[32]; /* hist. of time from start to irq */
+ unsigned int dasd_io_time3[32]; /* hist. of time from irq to end */
+ unsigned int dasd_io_nr_req[32]; /* hist. of # of requests in chanq */
+
+ /* new data */
+ struct timespec starttod; /* time of start or last reset */
+ unsigned int dasd_io_alias; /* requests using an alias */
+ unsigned int dasd_io_tpm; /* requests using transport mode */
+ unsigned int dasd_read_reqs; /* total number of read requests */
+ unsigned int dasd_read_sects; /* total number read sectors */
+ unsigned int dasd_read_alias; /* read request using an alias */
+ unsigned int dasd_read_tpm; /* read requests in transport mode */
+ unsigned int dasd_read_secs[32]; /* histogram of request's sizes */
+ unsigned int dasd_read_times[32]; /* histogram of requests's times */
+ unsigned int dasd_read_time1[32]; /* hist. time from build to start */
+ unsigned int dasd_read_time2[32]; /* hist. of time from start to irq */
+ unsigned int dasd_read_time3[32]; /* hist. of time from irq to end */
+ unsigned int dasd_read_nr_req[32]; /* hist. of # of requests in chanq */
+};
+
+struct dasd_profile {
+ struct dentry *dentry;
+ struct dasd_profile_info *data;
+ spinlock_t lock;
+};
+
struct dasd_device {
/* Block device stuff. */
struct dasd_block *block;
@@ -431,6 +466,9 @@ struct dasd_device {
/* default expiration time in s */
unsigned long default_expires;
+
+ struct dentry *debugfs_dentry;
+ struct dasd_profile profile;
};
struct dasd_block {
@@ -453,9 +491,8 @@ struct dasd_block {
struct tasklet_struct tasklet;
struct timer_list timer;
-#ifdef CONFIG_DASD_PROFILE
- struct dasd_profile_info_t profile;
-#endif
+ struct dentry *debugfs_dentry;
+ struct dasd_profile profile;
};
@@ -589,12 +626,13 @@ dasd_check_blocksize(int bsize)
}
/* externals in dasd.c */
-#define DASD_PROFILE_ON 1
-#define DASD_PROFILE_OFF 0
+#define DASD_PROFILE_OFF 0
+#define DASD_PROFILE_ON 1
+#define DASD_PROFILE_GLOBAL_ONLY 2
extern debug_info_t *dasd_debug_area;
-extern struct dasd_profile_info_t dasd_global_profile;
-extern unsigned int dasd_profile_level;
+extern struct dasd_profile_info dasd_global_profile_data;
+extern unsigned int dasd_global_profile_level;
extern const struct block_device_operations dasd_device_operations;
extern struct kmem_cache *dasd_page_cache;
@@ -662,6 +700,11 @@ void dasd_device_remove_stop_bits(struct dasd_device *, int);
int dasd_device_is_ro(struct dasd_device *);
+void dasd_profile_reset(struct dasd_profile *);
+int dasd_profile_on(struct dasd_profile *);
+void dasd_profile_off(struct dasd_profile *);
+void dasd_global_profile_reset(void);
+char *dasd_get_user_string(const char __user *, size_t);
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 72261e4c516d..eb4e034378cd 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -239,7 +239,7 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
*/
static int dasd_ioctl_reset_profile(struct dasd_block *block)
{
- memset(&block->profile, 0, sizeof(struct dasd_profile_info_t));
+ dasd_profile_reset(&block->profile);
return 0;
}
@@ -248,10 +248,40 @@ static int dasd_ioctl_reset_profile(struct dasd_block *block)
*/
static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
{
- if (dasd_profile_level == DASD_PROFILE_OFF)
+ struct dasd_profile_info_t *data;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock_bh(&block->profile.lock);
+ if (block->profile.data) {
+ data->dasd_io_reqs = block->profile.data->dasd_io_reqs;
+ data->dasd_io_sects = block->profile.data->dasd_io_sects;
+ memcpy(data->dasd_io_secs, block->profile.data->dasd_io_secs,
+ sizeof(data->dasd_io_secs));
+ memcpy(data->dasd_io_times, block->profile.data->dasd_io_times,
+ sizeof(data->dasd_io_times));
+ memcpy(data->dasd_io_timps, block->profile.data->dasd_io_timps,
+ sizeof(data->dasd_io_timps));
+ memcpy(data->dasd_io_time1, block->profile.data->dasd_io_time1,
+ sizeof(data->dasd_io_time1));
+ memcpy(data->dasd_io_time2, block->profile.data->dasd_io_time2,
+ sizeof(data->dasd_io_time2));
+ memcpy(data->dasd_io_time2ps,
+ block->profile.data->dasd_io_time2ps,
+ sizeof(data->dasd_io_time2ps));
+ memcpy(data->dasd_io_time3, block->profile.data->dasd_io_time3,
+ sizeof(data->dasd_io_time3));
+ memcpy(data->dasd_io_nr_req,
+ block->profile.data->dasd_io_nr_req,
+ sizeof(data->dasd_io_nr_req));
+ spin_unlock_bh(&block->profile.lock);
+ } else {
+ spin_unlock_bh(&block->profile.lock);
return -EIO;
- if (copy_to_user(argp, &block->profile,
- sizeof(struct dasd_profile_info_t)))
+ }
+ if (copy_to_user(argp, data, sizeof(*data)))
return -EFAULT;
return 0;
}
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index c4a6a31bd9cd..6c3c5364d082 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -32,28 +32,6 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
static struct proc_dir_entry *dasd_devices_entry = NULL;
static struct proc_dir_entry *dasd_statistics_entry = NULL;
-#ifdef CONFIG_DASD_PROFILE
-static char *
-dasd_get_user_string(const char __user *user_buf, size_t user_len)
-{
- char *buffer;
-
- buffer = kmalloc(user_len + 1, GFP_KERNEL);
- if (buffer == NULL)
- return ERR_PTR(-ENOMEM);
- if (copy_from_user(buffer, user_buf, user_len) != 0) {
- kfree(buffer);
- return ERR_PTR(-EFAULT);
- }
- /* got the string, now strip linefeed. */
- if (buffer[user_len - 1] == '\n')
- buffer[user_len - 1] = 0;
- else
- buffer[user_len] = 0;
- return buffer;
-}
-#endif /* CONFIG_DASD_PROFILE */
-
static int
dasd_devices_show(struct seq_file *m, void *v)
{
@@ -167,6 +145,55 @@ static const struct file_operations dasd_devices_file_ops = {
};
#ifdef CONFIG_DASD_PROFILE
+static int dasd_stats_all_block_on(void)
+{
+ int i, rc;
+ struct dasd_device *device;
+
+ rc = 0;
+ for (i = 0; i < dasd_max_devindex; ++i) {
+ device = dasd_device_from_devindex(i);
+ if (IS_ERR(device))
+ continue;
+ if (device->block)
+ rc = dasd_profile_on(&device->block->profile);
+ dasd_put_device(device);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+static void dasd_stats_all_block_off(void)
+{
+ int i;
+ struct dasd_device *device;
+
+ for (i = 0; i < dasd_max_devindex; ++i) {
+ device = dasd_device_from_devindex(i);
+ if (IS_ERR(device))
+ continue;
+ if (device->block)
+ dasd_profile_off(&device->block->profile);
+ dasd_put_device(device);
+ }
+}
+
+static void dasd_stats_all_block_reset(void)
+{
+ int i;
+ struct dasd_device *device;
+
+ for (i = 0; i < dasd_max_devindex; ++i) {
+ device = dasd_device_from_devindex(i);
+ if (IS_ERR(device))
+ continue;
+ if (device->block)
+ dasd_profile_reset(&device->block->profile);
+ dasd_put_device(device);
+ }
+}
+
static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor)
{
int i;
@@ -183,18 +210,18 @@ static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int f
static int dasd_stats_proc_show(struct seq_file *m, void *v)
{
#ifdef CONFIG_DASD_PROFILE
- struct dasd_profile_info_t *prof;
+ struct dasd_profile_info *prof;
int factor;
/* check for active profiling */
- if (dasd_profile_level == DASD_PROFILE_OFF) {
+ if (!dasd_global_profile_level) {
seq_printf(m, "Statistics are off - they might be "
"switched on using 'echo set on > "
"/proc/dasd/statistics'\n");
return 0;
}
+ prof = &dasd_global_profile_data;
- prof = &dasd_global_profile;
/* prevent counter 'overflow' on output */
for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999;
factor *= 10);
@@ -245,6 +272,7 @@ static ssize_t dasd_stats_proc_write(struct file *file,
{
#ifdef CONFIG_DASD_PROFILE
char *buffer, *str;
+ int rc;
if (user_len > 65536)
user_len = 65536;
@@ -259,32 +287,40 @@ static ssize_t dasd_stats_proc_write(struct file *file,
str = skip_spaces(str + 4);
if (strcmp(str, "on") == 0) {
/* switch on statistics profiling */
- dasd_profile_level = DASD_PROFILE_ON;
+ rc = dasd_stats_all_block_on();
+ if (rc) {
+ dasd_stats_all_block_off();
+ goto out_error;
+ }
+ dasd_global_profile_reset();
+ dasd_global_profile_level = DASD_PROFILE_ON;
pr_info("The statistics feature has been switched "
"on\n");
} else if (strcmp(str, "off") == 0) {
/* switch off and reset statistics profiling */
- memset(&dasd_global_profile,
- 0, sizeof (struct dasd_profile_info_t));
- dasd_profile_level = DASD_PROFILE_OFF;
+ dasd_global_profile_level = DASD_PROFILE_OFF;
+ dasd_global_profile_reset();
+ dasd_stats_all_block_off();
pr_info("The statistics feature has been switched "
"off\n");
} else
- goto out_error;
+ goto out_parse_error;
} else if (strncmp(str, "reset", 5) == 0) {
/* reset the statistics */
- memset(&dasd_global_profile, 0,
- sizeof (struct dasd_profile_info_t));
+ dasd_global_profile_reset();
+ dasd_stats_all_block_reset();
pr_info("The statistics have been reset\n");
} else
- goto out_error;
+ goto out_parse_error;
kfree(buffer);
return user_len;
-out_error:
+out_parse_error:
+ rc = -EINVAL;
pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
str);
+out_error:
kfree(buffer);
- return -EINVAL;
+ return rc;
#else
pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
return user_len;
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index a4f117d9fdc6..2c9a776bd63c 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -116,9 +116,6 @@ config S390_TAPE
called tape390 and include all selected interfaces and
hardware drivers.
-comment "S/390 tape interface support"
- depends on S390_TAPE
-
comment "S/390 tape hardware support"
depends on S390_TAPE
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 05909a7df8b3..a90a02c28d6a 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -13,7 +13,7 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/reboot.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/ptrace.h>
#include <asm/sigp.h>
#include <asm/smp.h>
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index c837d7419a6a..524d988d89dd 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -21,7 +21,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <asm/cpcmd.h>
#include <asm/debug.h>
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 12ef9121d4f0..11312f401c70 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -258,13 +258,13 @@ static int vmwdt_suspend(void)
if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) {
pr_err("The system cannot be suspended while the watchdog"
" is in use\n");
- return NOTIFY_BAD;
+ return notifier_from_errno(-EBUSY);
}
if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) {
clear_bit(VMWDT_OPEN, &vmwdt_is_open);
pr_err("The system cannot be suspended while the watchdog"
" is running\n");
- return NOTIFY_BAD;
+ return notifier_from_errno(-EBUSY);
}
return NOTIFY_DONE;
}
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index c47b25fd3f43..92d7324acb1c 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -814,8 +814,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
mutex_unlock(&css->mutex);
continue;
}
- if (__chsc_do_secm(css, 0))
- ret = NOTIFY_BAD;
+ ret = __chsc_do_secm(css, 0);
+ ret = notifier_from_errno(ret);
mutex_unlock(&css->mutex);
}
break;
@@ -831,8 +831,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
mutex_unlock(&css->mutex);
continue;
}
- if (__chsc_do_secm(css, 1))
- ret = NOTIFY_BAD;
+ ret = __chsc_do_secm(css, 1);
+ ret = notifier_from_errno(ret);
mutex_unlock(&css->mutex);
}
/* search for subchannels, which appeared during hibernation */
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 7e297c7bb5ff..0b7245c72d5e 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -2,7 +2,7 @@
#define S390_DEVICE_H
#include <asm/ccwdev.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/wait.h>
#include <linux/notifier.h>
#include "io_sch.h"
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 570d4da10696..e58169c32474 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -15,7 +15,7 @@
#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/debug.h>
#include <asm/qdio.h>
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 5c4e741d8221..2a1d4dfaf859 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -9,7 +9,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/debug.h>
#include <asm/qdio.h>
#include <asm/airq.h>
@@ -95,9 +95,11 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
}
}
-static inline u32 shared_ind_set(void)
+static inline u32 clear_shared_ind(void)
{
- return q_indicators[TIQDIO_SHARED_IND].ind;
+ if (!atomic_read(&q_indicators[TIQDIO_SHARED_IND].count))
+ return 0;
+ return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
}
/**
@@ -107,7 +109,7 @@ static inline u32 shared_ind_set(void)
*/
static void tiqdio_thinint_handler(void *alsi, void *data)
{
- u32 si_used = shared_ind_set();
+ u32 si_used = clear_shared_ind();
struct qdio_q *q;
last_ai_time = S390_lowcore.int_clock;
@@ -150,13 +152,6 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
qperf_inc(q, adapter_int);
}
rcu_read_unlock();
-
- /*
- * If the shared indicator was used clear it now after all queues
- * were processed.
- */
- if (si_used && shared_ind_set())
- xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
}
static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 16e4a25596e7..b77ae519d79c 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -6,6 +6,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Ralph Wuerthner <rwuerthn@de.ibm.com>
* Felix Beck <felix.beck@de.ibm.com>
+ * Holger Dengler <hd@linux.vnet.ibm.com>
*
* Adjunct processor bus.
*
@@ -40,7 +41,7 @@
#include <linux/mutex.h>
#include <asm/reset.h>
#include <asm/airq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/system.h>
#include <asm/isc.h>
#include <linux/hrtimer.h>
@@ -222,47 +223,52 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
}
#endif
-static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid,
- int *support)
+#ifdef CONFIG_64BIT
+static inline struct ap_queue_status
+__ap_query_functions(ap_qid_t qid, unsigned int *functions)
{
register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
- register struct ap_queue_status reg1 asm ("1");
- register unsigned long reg2 asm ("2") = 0UL;
+ register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
+ register unsigned long reg2 asm ("2");
asm volatile(
".long 0xb2af0000\n"
- "0: la %1,0\n"
- "1:\n"
- EX_TABLE(0b, 1b)
- : "+d" (reg0), "=d" (reg1), "=d" (reg2)
+ "0:\n"
+ EX_TABLE(0b, 0b)
+ : "+d" (reg0), "+d" (reg1), "=d" (reg2)
:
: "cc");
- if (reg2 & 0x6000000000000000ULL)
- *support = 1;
- else
- *support = 0;
-
+ *functions = (unsigned int)(reg2 >> 32);
return reg1;
}
+#endif
/**
- * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
- * support.
+ * ap_query_functions(): Query supported functions.
* @qid: The AP queue number
+ * @functions: Pointer to functions field.
*
- * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ * Returns
+ * 0 on success.
+ * -ENODEV if queue not valid.
+ * -EBUSY if device busy.
+ * -EINVAL if query function is not supported
*/
-int ap_4096_commands_available(ap_qid_t qid)
+static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
{
+#ifdef CONFIG_64BIT
struct ap_queue_status status;
- int i, support = 0;
- status = __ap_4096_commands_available(qid, &support);
+ int i;
+ status = __ap_query_functions(qid, functions);
for (i = 0; i < AP_MAX_RESET; i++) {
+ if (ap_queue_status_invalid_test(&status))
+ return -ENODEV;
+
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
- return support;
+ return 0;
case AP_RESPONSE_RESET_IN_PROGRESS:
case AP_RESPONSE_BUSY:
break;
@@ -270,7 +276,7 @@ int ap_4096_commands_available(ap_qid_t qid)
case AP_RESPONSE_DECONFIGURED:
case AP_RESPONSE_CHECKSTOPPED:
case AP_RESPONSE_INVALID_ADDRESS:
- return 0;
+ return -ENODEV;
case AP_RESPONSE_OTHERWISE_CHANGED:
break;
default:
@@ -278,10 +284,31 @@ int ap_4096_commands_available(ap_qid_t qid)
}
if (i < AP_MAX_RESET - 1) {
udelay(5);
- status = __ap_4096_commands_available(qid, &support);
+ status = __ap_query_functions(qid, functions);
}
}
- return support;
+ return -EBUSY;
+#else
+ return -EINVAL;
+#endif
+}
+
+/**
+ * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
+ * support.
+ * @qid: The AP queue number
+ *
+ * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ */
+int ap_4096_commands_available(ap_qid_t qid)
+{
+ unsigned int functions;
+
+ if (ap_query_functions(qid, &functions))
+ return 0;
+
+ return test_ap_facility(functions, 1) &&
+ test_ap_facility(functions, 2);
}
EXPORT_SYMBOL(ap_4096_commands_available);
@@ -1135,6 +1162,7 @@ static void ap_scan_bus(struct work_struct *unused)
struct device *dev;
ap_qid_t qid;
int queue_depth, device_type;
+ unsigned int device_functions;
int rc, i;
if (ap_select_domain() != 0)
@@ -1183,14 +1211,30 @@ static void ap_scan_bus(struct work_struct *unused)
INIT_LIST_HEAD(&ap_dev->list);
setup_timer(&ap_dev->timeout, ap_request_timeout,
(unsigned long) ap_dev);
- if (device_type == 0) {
+ switch (device_type) {
+ case 0:
if (ap_probe_device_type(ap_dev)) {
kfree(ap_dev);
continue;
}
- }
- else
+ break;
+ case 10:
+ if (ap_query_functions(qid, &device_functions)) {
+ kfree(ap_dev);
+ continue;
+ }
+ if (test_ap_facility(device_functions, 3))
+ ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
+ else if (test_ap_facility(device_functions, 4))
+ ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
+ else {
+ kfree(ap_dev);
+ continue;
+ }
+ break;
+ default:
ap_dev->device_type = device_type;
+ }
ap_dev->device.bus = &ap_bus_type;
ap_dev->device.parent = ap_root_device;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 08b9738285b4..d960a6309eec 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -6,6 +6,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Ralph Wuerthner <rwuerthn@de.ibm.com>
* Felix Beck <felix.beck@de.ibm.com>
+ * Holger Dengler <hd@linux.vnet.ibm.com>
*
* Adjunct processor bus header file.
*
@@ -72,7 +73,26 @@ struct ap_queue_status {
unsigned int int_enabled : 1;
unsigned int response_code : 8;
unsigned int pad2 : 16;
-};
+} __packed;
+
+#define AP_QUEUE_STATUS_INVALID \
+ { 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
+
+static inline
+int ap_queue_status_invalid_test(struct ap_queue_status *status)
+{
+ struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
+ return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
+}
+
+#define MAX_AP_FACILITY 31
+
+static inline int test_ap_facility(unsigned int function, unsigned int nr)
+{
+ if (nr > MAX_AP_FACILITY)
+ return 0;
+ return function & (unsigned int)(0x80000000 >> nr);
+}
#define AP_RESPONSE_NORMAL 0x00
#define AP_RESPONSE_Q_NOT_AVAIL 0x01
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 8e65447f76b7..88ad33ed5d38 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -36,7 +36,7 @@
#include <linux/seq_file.h>
#include <linux/compat.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <linux/hw_random.h>
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 2176d00b395e..da171b5f3996 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_mono.c b/drivers/s390/crypto/zcrypt_mono.c
index 44253fdd4136..eb313c3fb2d1 100644
--- a/drivers/s390/crypto/zcrypt_mono.c
+++ b/drivers/s390/crypto/zcrypt_mono.c
@@ -32,7 +32,7 @@
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 1afb69c75fea..d84816f144df 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index aa4c050a5694..bdbdbe192993 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -30,7 +30,7 @@
#include <linux/init.h>
#include <linux/gfp.h>
#include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 4f85eb725f4f..dd4737808e06 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -31,7 +31,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include "ap_bus.h"
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
index 5336120cddf1..1fa07b0c11c0 100644
--- a/drivers/s390/net/ctcm_mpc.h
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -12,6 +12,7 @@
#ifndef _CTC_MPC_H_
#define _CTC_MPC_H_
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include "fsm.h"
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index 1e8b235d95b5..a4510cf59034 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -8,7 +8,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/**
* Define this to get debugging messages.
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d3cee33e554c..26a4110eeb2d 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -720,7 +720,7 @@ struct qeth_card {
wait_queue_head_t wait_q;
spinlock_t vlanlock;
spinlock_t mclock;
- struct vlan_group *vlangrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct list_head vid_list;
struct list_head mc_list;
struct work_struct kernel_thread_starter;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index dd08f7b42fb8..4550573c25e5 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1097,7 +1097,6 @@ static int qeth_setup_card(struct qeth_card *card)
card->dev = NULL;
spin_lock_init(&card->vlanlock);
spin_lock_init(&card->mclock);
- card->vlangrp = NULL;
spin_lock_init(&card->lock);
spin_lock_init(&card->ip_lock);
spin_lock_init(&card->thread_mask_lock);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fd69da3fa6b4..fafb8c299540 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/bitops.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h>
@@ -23,6 +24,7 @@
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/slab.h>
+#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/arp.h>
@@ -1696,16 +1698,18 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
static void qeth_l3_add_vlan_mc(struct qeth_card *card)
{
struct in_device *in_dev;
- struct vlan_group *vg;
- int i;
+ u16 vid;
QETH_CARD_TEXT(card, 4, "addmcvl");
- if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+ if (!qeth_is_supported(card, IPA_FULL_VLAN))
return;
- vg = card->vlangrp;
- for (i = 0; i < VLAN_N_VID; i++) {
- struct net_device *netdev = vlan_group_get_device(vg, i);
+ for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+ struct net_device *netdev;
+
+ rcu_read_lock();
+ netdev = __vlan_find_dev_deep(card->dev, vid);
+ rcu_read_unlock();
if (netdev == NULL ||
!(netdev->flags & IFF_UP))
continue;
@@ -1759,16 +1763,16 @@ static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
{
struct inet6_dev *in_dev;
- struct vlan_group *vg;
- int i;
+ u16 vid;
QETH_CARD_TEXT(card, 4, "admc6vl");
- if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+ if (!qeth_is_supported(card, IPA_FULL_VLAN))
return;
- vg = card->vlangrp;
- for (i = 0; i < VLAN_N_VID; i++) {
- struct net_device *netdev = vlan_group_get_device(vg, i);
+ for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+ struct net_device *netdev;
+
+ netdev = __vlan_find_dev_deep(card->dev, vid);
if (netdev == NULL ||
!(netdev->flags & IFF_UP))
continue;
@@ -1806,10 +1810,12 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card,
struct in_device *in_dev;
struct in_ifaddr *ifa;
struct qeth_ipaddr *addr;
+ struct net_device *netdev;
QETH_CARD_TEXT(card, 4, "frvaddr4");
- in_dev = in_dev_get(vlan_group_get_device(card->vlangrp, vid));
+ netdev = __vlan_find_dev_deep(card->dev, vid);
+ in_dev = in_dev_get(netdev);
if (!in_dev)
return;
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
@@ -1832,10 +1838,12 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
struct inet6_dev *in6_dev;
struct inet6_ifaddr *ifa;
struct qeth_ipaddr *addr;
+ struct net_device *netdev;
QETH_CARD_TEXT(card, 4, "frvaddr6");
- in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
+ netdev = __vlan_find_dev_deep(card->dev, vid);
+ in6_dev = in6_dev_get(netdev);
if (!in6_dev)
return;
list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
@@ -1856,26 +1864,15 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
unsigned short vid)
{
- if (!card->vlangrp)
- return;
qeth_l3_free_vlan_addresses4(card, vid);
qeth_l3_free_vlan_addresses6(card, vid);
}
-static void qeth_l3_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
+static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct qeth_card *card = dev->ml_priv;
- unsigned long flags;
-
- QETH_CARD_TEXT(card, 4, "vlanreg");
- spin_lock_irqsave(&card->vlanlock, flags);
- card->vlangrp = grp;
- spin_unlock_irqrestore(&card->vlanlock, flags);
-}
-static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
-{
+ set_bit(vid, card->active_vlans);
return;
}
@@ -1892,7 +1889,7 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
spin_lock_irqsave(&card->vlanlock, flags);
/* unregister IP addresses of vlan device */
qeth_l3_free_vlan_addresses(card, vid);
- vlan_group_set_device(card->vlangrp, vid, NULL);
+ clear_bit(vid, card->active_vlans);
spin_unlock_irqrestore(&card->vlanlock, flags);
qeth_l3_set_multicast_list(card->dev);
}
@@ -2014,10 +2011,8 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
&vlan_tag);
len = skb->len;
if (is_vlan && !card->options.sniffer)
- vlan_gro_receive(&card->napi, card->vlangrp,
- vlan_tag, skb);
- else
- napi_gro_receive(&card->napi, skb);
+ __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;
@@ -2118,15 +2113,15 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev,
struct qeth_card *card)
{
int rc = 0;
- struct vlan_group *vg;
- int i;
+ u16 vid;
- vg = card->vlangrp;
- if (!vg)
- return rc;
+ for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+ struct net_device *netdev;
- for (i = 0; i < VLAN_N_VID; i++) {
- if (vlan_group_get_device(vg, i) == dev) {
+ rcu_read_lock();
+ netdev = __vlan_find_dev_deep(dev, vid);
+ rcu_read_unlock();
+ if (netdev == dev) {
rc = QETH_VLAN_CARD;
break;
}
@@ -2742,9 +2737,14 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
{
int cast_type = RTN_UNSPEC;
-
- if (skb_dst(skb) && skb_dst(skb)->neighbour) {
- cast_type = skb_dst(skb)->neighbour->type;
+ struct neighbour *n = NULL;
+ struct dst_entry *dst;
+
+ dst = skb_dst(skb);
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (n) {
+ cast_type = n->type;
if ((cast_type == RTN_BROADCAST) ||
(cast_type == RTN_MULTICAST) ||
(cast_type == RTN_ANYCAST))
@@ -2787,6 +2787,9 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
+ struct neighbour *n = NULL;
+ struct dst_entry *dst;
+
memset(hdr, 0, sizeof(struct qeth_hdr));
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
hdr->hdr.l3.ext_flags = 0;
@@ -2795,7 +2798,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
* before we're going to overwrite this location with next hop ip.
* v6 uses passthrough, v4 sets the tag in the QDIO header.
*/
- if (card->vlangrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
else
@@ -2804,13 +2807,16 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+ dst = skb_dst(skb);
+ if (dst)
+ n = dst_get_neighbour(dst);
if (ipv == 4) {
/* IPv4 */
hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type);
memset(hdr->hdr.l3.dest_addr, 0, 12);
- if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+ if (n) {
*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
- *((u32 *) skb_dst(skb)->neighbour->primary_key);
+ *((u32 *) n->primary_key);
} else {
/* fill in destination address used in ip header */
*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
@@ -2821,9 +2827,9 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type);
if (card->info.type == QETH_CARD_TYPE_IQD)
hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU;
- if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+ if (n) {
memcpy(hdr->hdr.l3.dest_addr,
- skb_dst(skb)->neighbour->primary_key, 16);
+ n->primary_key, 16);
} else {
/* fill in destination address used in ip header */
memcpy(hdr->hdr.l3.dest_addr,
@@ -2977,8 +2983,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_pull(new_skb, ETH_HLEN);
}
- if (ipv != 4 && card->vlangrp &&
- vlan_tx_tag_present(new_skb)) {
+ if (ipv != 4 && vlan_tx_tag_present(new_skb)) {
skb_push(new_skb, VLAN_HLEN);
skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
skb_copy_to_linear_data_offset(new_skb, 4,
@@ -3222,14 +3227,13 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = 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,
- .ndo_set_features = qeth_l3_set_features,
- .ndo_vlan_rx_register = qeth_l3_vlan_rx_register,
+ .ndo_do_ioctl = qeth_l3_do_ioctl,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_fix_features = qeth_l3_fix_features,
+ .ndo_set_features = qeth_l3_set_features,
.ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
- .ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_tx_timeout = qeth_tx_timeout,
};
static const struct net_device_ops qeth_l3_osa_netdev_ops = {
@@ -3239,14 +3243,13 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = 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,
- .ndo_set_features = qeth_l3_set_features,
- .ndo_vlan_rx_register = qeth_l3_vlan_rx_register,
+ .ndo_do_ioctl = qeth_l3_do_ioctl,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_fix_features = qeth_l3_fix_features,
+ .ndo_set_features = qeth_l3_set_features,
.ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
- .ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_tx_timeout = qeth_tx_timeout,
.ndo_neigh_setup = qeth_l3_neigh_setup,
};
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 2a4991d6d4d5..7cac873c7383 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -13,7 +13,7 @@
#include <linux/slab.h>
#include <scsi/fc/fc_fcp.h>
#include <scsi/scsi_eh.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "zfcp_ext.h"
#include "zfcp_dbf.h"
#include "zfcp_fc.h"
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 740da4465447..965a1fccd66a 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -16,7 +16,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h> /* put_/get_user */
#include <asm/io.h>
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index c5169f01c1cd..f17c92cf808b 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -422,10 +422,19 @@ MODULE_PARM_DESC(aha152x1, "parameters for second controller");
#ifdef __ISAPNP__
static struct isapnp_device_id id_table[] __devinitdata = {
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1530), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1515), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1520), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2015), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1522), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2215), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1530), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3015), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1532), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3215), 0 },
+ { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x6360), 0 },
{ ISAPNP_DEVICE_SINGLE_END, }
};
MODULE_DEVICE_TABLE(isapnp, id_table);
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index ea439f93ed81..2db79b469d9e 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -892,6 +892,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
return 0;
}
+static void NCR5380_exit(struct Scsi_Host *instance)
+{
+ /* Empty, as we didn't schedule any delayed work */
+}
+
/*
* Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
* void (*done)(Scsi_Cmnd *))
@@ -914,7 +919,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{
SETUP_HOSTDATA(cmd->device->host);
Scsi_Cmnd *tmp;
- int oldto;
unsigned long flags;
#if (NDEBUG & NDEBUG_NO_WRITE)
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 3e8658e2f154..04a154f87e3e 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -730,6 +730,7 @@ int atari_scsi_release(struct Scsi_Host *sh)
free_irq(IRQ_TT_MFP_SCSI, sh);
if (atari_dma_buffer)
atari_stram_free(atari_dma_buffer);
+ NCR5380_exit(sh);
return 1;
}
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 94b9a07845d5..0a9bdfa3d939 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -215,73 +215,62 @@ unlock:
static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
{
struct beiscsi_hba *phba = data;
+ struct mgmt_session_info *boot_sess = &phba->boot_sess;
+ struct mgmt_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",
- (int)strlen(phba->boot_sess.target_name),
- (char *)&phba->boot_sess.target_name);
+ (int)strlen(boot_sess->target_name),
+ (char *)&boot_sess->target_name);
break;
case ISCSI_BOOT_TGT_IP_ADDR:
- if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1)
+ if (boot_conn->dest_ipaddr.ip_type == 0x1)
rc = sprintf(buf, "%pI4\n",
- (char *)&phba->boot_sess.conn_list[0].
- dest_ipaddr.ip_address);
+ (char *)&boot_conn->dest_ipaddr.ip_address);
else
rc = sprintf(str, "%pI6\n",
- (char *)&phba->boot_sess.conn_list[0].
- dest_ipaddr.ip_address);
+ (char *)&boot_conn->dest_ipaddr.ip_address);
break;
case ISCSI_BOOT_TGT_PORT:
- rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0].
- dest_port);
+ rc = sprintf(str, "%d\n", boot_conn->dest_port);
break;
case ISCSI_BOOT_TGT_CHAP_NAME:
rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_chap_name_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_chap_name);
+ boot_conn->negotiated_login_options.auth_data.chap.
+ target_chap_name_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.target_chap_name);
break;
case ISCSI_BOOT_TGT_CHAP_SECRET:
rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_secret_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- target_secret);
-
+ boot_conn->negotiated_login_options.auth_data.chap.
+ target_secret_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.target_secret);
break;
case ISCSI_BOOT_TGT_REV_CHAP_NAME:
rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_chap_name_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_chap_name);
-
+ boot_conn->negotiated_login_options.auth_data.chap.
+ intr_chap_name_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.intr_chap_name);
break;
case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
- rc = sprintf(str, "%.*s\n",
- phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_secret_length,
- (char *)&phba->boot_sess.conn_list[0].
- negotiated_login_options.auth_data.chap.
- intr_secret);
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->negotiated_login_options.auth_data.chap.
+ intr_secret_length,
+ (char *)&boot_conn->negotiated_login_options.
+ auth_data.chap.intr_secret);
break;
case ISCSI_BOOT_TGT_FLAGS:
- rc = sprintf(str, "2\n");
+ rc = sprintf(str, "2\n");
break;
case ISCSI_BOOT_TGT_NIC_ASSOC:
- rc = sprintf(str, "0\n");
+ rc = sprintf(str, "0\n");
break;
default:
rc = -ENOSYS;
@@ -315,10 +304,10 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
switch (type) {
case ISCSI_BOOT_ETH_FLAGS:
- rc = sprintf(str, "2\n");
+ rc = sprintf(str, "2\n");
break;
case ISCSI_BOOT_ETH_INDEX:
- rc = sprintf(str, "0\n");
+ rc = sprintf(str, "0\n");
break;
case ISCSI_BOOT_ETH_MAC:
rc = beiscsi_get_macaddr(buf, phba);
@@ -391,40 +380,6 @@ static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
return rc;
}
-static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
-{
- struct iscsi_boot_kobj *boot_kobj;
-
- phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
- if (!phba->boot_kset)
- return -ENOMEM;
-
- /* get boot info using mgmt cmd */
- boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
- beiscsi_show_boot_tgt_info,
- beiscsi_tgt_get_attr_visibility);
- if (!boot_kobj)
- goto free_kset;
-
- boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
- beiscsi_show_boot_ini_info,
- beiscsi_ini_get_attr_visibility);
- if (!boot_kobj)
- goto free_kset;
-
- boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
- beiscsi_show_boot_eth_info,
- beiscsi_eth_get_attr_visibility);
- if (!boot_kobj)
- goto free_kset;
- return 0;
-
-free_kset:
- if (phba->boot_kset)
- iscsi_boot_destroy_kset(phba->boot_kset);
- return -ENOMEM;
-}
-
/*------------------- PCI Driver operations and data ----------------- */
static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
@@ -483,14 +438,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
if (iscsi_host_add(shost, &phba->pcidev->dev))
goto free_devices;
- if (beiscsi_setup_boot_info(phba))
- /*
- * log error but continue, because we may not be using
- * iscsi boot.
- */
- shost_printk(KERN_ERR, phba->shost, "Could not set up "
- "iSCSI boot info.");
-
return phba;
free_devices:
@@ -3511,6 +3458,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
unsigned int tag, wrb_num;
unsigned short status, extd_status;
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+ int ret = -ENOMEM;
tag = beiscsi_get_boot_target(phba);
if (!tag) {
@@ -3535,8 +3483,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
boot_resp = embedded_payload(wrb);
if (boot_resp->boot_session_handle < 0) {
- printk(KERN_ERR "No Boot Session for this pci_func,"
- "session Hndl = %d\n", boot_resp->boot_session_handle);
+ shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n");
return -ENXIO;
}
@@ -3574,14 +3521,70 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
wrb = queue_get_wrb(mccq, wrb_num);
free_mcc_tag(&phba->ctrl, tag);
session_resp = nonemb_cmd.va ;
+
memcpy(&phba->boot_sess, &session_resp->session_info,
sizeof(struct mgmt_session_info));
- pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
- nonemb_cmd.va, nonemb_cmd.dma);
- return 0;
+ ret = 0;
+
boot_freemem:
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
+ return ret;
+}
+
+static void beiscsi_boot_release(void *data)
+{
+ struct beiscsi_hba *phba = data;
+
+ scsi_host_put(phba->shost);
+}
+
+static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+{
+ struct iscsi_boot_kobj *boot_kobj;
+
+ /* get boot info using mgmt cmd */
+ if (beiscsi_get_boot_info(phba))
+ /* Try to see if we can carry on without this */
+ return 0;
+
+ phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
+ if (!phba->boot_kset)
+ return -ENOMEM;
+
+ /* get a ref because the show function will ref the phba */
+ if (!scsi_host_get(phba->shost))
+ goto free_kset;
+ boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
+ beiscsi_show_boot_tgt_info,
+ beiscsi_tgt_get_attr_visibility,
+ beiscsi_boot_release);
+ if (!boot_kobj)
+ goto put_shost;
+
+ if (!scsi_host_get(phba->shost))
+ goto free_kset;
+ boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
+ beiscsi_show_boot_ini_info,
+ beiscsi_ini_get_attr_visibility,
+ beiscsi_boot_release);
+ if (!boot_kobj)
+ goto put_shost;
+
+ if (!scsi_host_get(phba->shost))
+ goto free_kset;
+ boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
+ beiscsi_show_boot_eth_info,
+ beiscsi_eth_get_attr_visibility,
+ beiscsi_boot_release);
+ if (!boot_kobj)
+ goto put_shost;
+ return 0;
+
+put_shost:
+ scsi_host_put(phba->shost);
+free_kset:
+ iscsi_boot_destroy_kset(phba->boot_kset);
return -ENOMEM;
}
@@ -3963,11 +3966,10 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
}
memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
dw[offsetof(struct amap_pdu_data_out, lun) / 32],
- io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
+ &io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
- cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
- lun[0]));
+ cpu_to_be16(*(unsigned short *)&io_task->cmd_bhs->iscsi_hdr.lun));
AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
io_task->pwrb_handle->wrb_index);
@@ -4150,8 +4152,7 @@ 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);
- if (phba->boot_kset)
- iscsi_boot_destroy_kset(phba->boot_kset);
+ iscsi_boot_destroy_kset(phba->boot_kset);
iscsi_host_remove(phba->shost);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);
@@ -4310,11 +4311,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
goto free_blkenbld;
}
hwi_enable_intr(phba);
- ret = beiscsi_get_boot_info(phba);
- if (ret < 0) {
- shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
- "No Boot Devices !!!!!\n");
- }
+
+ if (beiscsi_setup_boot_info(phba))
+ /*
+ * log error but continue, because we may not be using
+ * iscsi boot.
+ */
+ shost_printk(KERN_ERR, phba->shost, "Could not set up "
+ "iSCSI boot info.");
+
SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
return 0;
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
index 4ce6f4942327..475cf925d5e8 100644
--- a/drivers/scsi/bfa/Makefile
+++ b/drivers/scsi/bfa/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
-bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
+bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o bfad_bsg.o
bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
index 7be6b5a8114b..3b0af1102bf4 100644
--- a/drivers/scsi/bfa/bfa.h
+++ b/drivers/scsi/bfa/bfa.h
@@ -27,7 +27,6 @@
struct bfa_s;
typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
-typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
/*
* Interrupt message handlers
@@ -54,7 +53,8 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
+ bfa_reqq_pi((__bfa), (__reqq)))))
-#define bfa_reqq_produce(__bfa, __reqq) do { \
+#define bfa_reqq_produce(__bfa, __reqq, __mh) do { \
+ (__mh).mtag.h2i.qid = (__bfa)->iocfc.hw_qid[__reqq];\
(__bfa)->iocfc.req_cq_pi[__reqq]++; \
(__bfa)->iocfc.req_cq_pi[__reqq] &= \
((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \
@@ -76,16 +76,6 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
} while (0)
/*
- * Queue element to wait for room in request queue. FIFO order is
- * maintained when fullfilling requests.
- */
-struct bfa_reqq_wait_s {
- struct list_head qe;
- void (*qresume) (void *cbarg);
- void *cbarg;
-};
-
-/*
* Circular queue usage assignments
*/
enum {
@@ -128,18 +118,6 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
#define bfa_reqq_wcancel(__wqe) list_del(&(__wqe)->qe)
-
-/*
- * Generic BFA callback element.
- */
-struct bfa_cb_qe_s {
- struct list_head qe;
- bfa_cb_cbfn_t cbfn;
- bfa_boolean_t once;
- u32 rsvd;
- void *cbarg;
-};
-
#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \
@@ -172,44 +150,14 @@ struct bfa_pciid_s {
extern char bfa_version[];
-/*
- * BFA memory resources
- */
-enum bfa_mem_type {
- BFA_MEM_TYPE_KVA = 1, /* Kernel Virtual Memory *(non-dma-able) */
- BFA_MEM_TYPE_DMA = 2, /* DMA-able memory */
- BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
-};
-
-struct bfa_mem_elem_s {
- enum bfa_mem_type mem_type; /* see enum bfa_mem_type */
- u32 mem_len; /* Total Length in Bytes */
- u8 *kva; /* kernel virtual address */
- u64 dma; /* dma address if DMA memory */
- u8 *kva_curp; /* kva allocation cursor */
- u64 dma_curp; /* dma allocation cursor */
-};
-
-struct bfa_meminfo_s {
- struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
-};
-#define bfa_meminfo_kva(_m) \
- ((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
-#define bfa_meminfo_dma_virt(_m) \
- ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
-#define bfa_meminfo_dma_phys(_m) \
- ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
-
struct bfa_iocfc_regs_s {
void __iomem *intr_status;
void __iomem *intr_mask;
void __iomem *cpe_q_pi[BFI_IOC_MAX_CQS];
void __iomem *cpe_q_ci[BFI_IOC_MAX_CQS];
- void __iomem *cpe_q_depth[BFI_IOC_MAX_CQS];
void __iomem *cpe_q_ctrl[BFI_IOC_MAX_CQS];
void __iomem *rme_q_ci[BFI_IOC_MAX_CQS];
void __iomem *rme_q_pi[BFI_IOC_MAX_CQS];
- void __iomem *rme_q_depth[BFI_IOC_MAX_CQS];
void __iomem *rme_q_ctrl[BFI_IOC_MAX_CQS];
};
@@ -231,25 +179,55 @@ struct bfa_hwif_s {
void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
- void (*hw_msix_install)(struct bfa_s *bfa);
+ void (*hw_msix_ctrl_install)(struct bfa_s *bfa);
+ void (*hw_msix_queue_install)(struct bfa_s *bfa);
void (*hw_msix_uninstall)(struct bfa_s *bfa);
void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
u32 *nvecs, u32 *maxvec);
void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
u32 *end);
+ int cpe_vec_q0;
+ int rme_vec_q0;
};
typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
+struct bfa_faa_cbfn_s {
+ bfa_cb_iocfc_t faa_cbfn;
+ void *faa_cbarg;
+};
+
+#define BFA_FAA_ENABLED 1
+#define BFA_FAA_DISABLED 2
+
+/*
+ * FAA attributes
+ */
+struct bfa_faa_attr_s {
+ wwn_t faa;
+ u8 faa_state;
+ u8 pwwn_source;
+ u8 rsvd[6];
+};
+
+struct bfa_faa_args_s {
+ struct bfa_faa_attr_s *faa_attr;
+ struct bfa_faa_cbfn_s faa_cb;
+ u8 faa_state;
+ bfa_boolean_t busy;
+};
+
struct bfa_iocfc_s {
struct bfa_s *bfa;
struct bfa_iocfc_cfg_s cfg;
int action;
u32 req_cq_pi[BFI_IOC_MAX_CQS];
u32 rsp_cq_ci[BFI_IOC_MAX_CQS];
+ u8 hw_qid[BFI_IOC_MAX_CQS];
struct bfa_cb_qe_s init_hcb_qe;
struct bfa_cb_qe_s stop_hcb_qe;
struct bfa_cb_qe_s dis_hcb_qe;
+ struct bfa_cb_qe_s en_hcb_qe;
struct bfa_cb_qe_s stats_hcb_qe;
bfa_boolean_t cfgdone;
@@ -257,7 +235,6 @@ struct bfa_iocfc_s {
struct bfi_iocfc_cfg_s *cfginfo;
struct bfa_dma_s cfgrsp_dma;
struct bfi_iocfc_cfgrsp_s *cfgrsp;
- struct bfi_iocfc_cfg_reply_s *cfg_reply;
struct bfa_dma_s req_cq_ba[BFI_IOC_MAX_CQS];
struct bfa_dma_s req_cq_shadow_ci[BFI_IOC_MAX_CQS];
struct bfa_dma_s rsp_cq_ba[BFI_IOC_MAX_CQS];
@@ -267,18 +244,42 @@ struct bfa_iocfc_s {
bfa_cb_iocfc_t updateq_cbfn; /* bios callback function */
void *updateq_cbarg; /* bios callback arg */
u32 intr_mask;
+ struct bfa_faa_args_s faa_args;
+ struct bfa_mem_dma_s ioc_dma;
+ struct bfa_mem_dma_s iocfc_dma;
+ struct bfa_mem_dma_s reqq_dma[BFI_IOC_MAX_CQS];
+ struct bfa_mem_dma_s rspq_dma[BFI_IOC_MAX_CQS];
+ struct bfa_mem_kva_s kva_seg;
};
-#define bfa_lpuid(__bfa) \
- bfa_ioc_portid(&(__bfa)->ioc)
+#define BFA_MEM_IOC_DMA(_bfa) (&((_bfa)->iocfc.ioc_dma))
+#define BFA_MEM_IOCFC_DMA(_bfa) (&((_bfa)->iocfc.iocfc_dma))
+#define BFA_MEM_REQQ_DMA(_bfa, _qno) (&((_bfa)->iocfc.reqq_dma[(_qno)]))
+#define BFA_MEM_RSPQ_DMA(_bfa, _qno) (&((_bfa)->iocfc.rspq_dma[(_qno)]))
+#define BFA_MEM_IOCFC_KVA(_bfa) (&((_bfa)->iocfc.kva_seg))
+
+#define bfa_fn_lpu(__bfa) \
+ bfi_fn_lpu(bfa_ioc_pcifn(&(__bfa)->ioc), bfa_ioc_portid(&(__bfa)->ioc))
#define bfa_msix_init(__bfa, __nvecs) \
((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
-#define bfa_msix_install(__bfa) \
- ((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
+#define bfa_msix_ctrl_install(__bfa) \
+ ((__bfa)->iocfc.hwif.hw_msix_ctrl_install(__bfa))
+#define bfa_msix_queue_install(__bfa) \
+ ((__bfa)->iocfc.hwif.hw_msix_queue_install(__bfa))
#define bfa_msix_uninstall(__bfa) \
((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
-#define bfa_isr_mode_set(__bfa, __msix) \
- ((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
+#define bfa_isr_rspq_ack(__bfa, __queue) do { \
+ if ((__bfa)->iocfc.hwif.hw_rspq_ack) \
+ (__bfa)->iocfc.hwif.hw_rspq_ack(__bfa, __queue); \
+} while (0)
+#define bfa_isr_reqq_ack(__bfa, __queue) do { \
+ if ((__bfa)->iocfc.hwif.hw_reqq_ack) \
+ (__bfa)->iocfc.hwif.hw_reqq_ack(__bfa, __queue); \
+} while (0)
+#define bfa_isr_mode_set(__bfa, __msix) do { \
+ if ((__bfa)->iocfc.hwif.hw_isr_mode_set) \
+ (__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix); \
+} while (0)
#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \
((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, \
__nvecs, __maxvec))
@@ -290,17 +291,17 @@ struct bfa_iocfc_s {
/*
* FC specific IOC functions.
*/
-void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len);
+void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo,
+ struct bfa_s *bfa);
void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
void bfa_iocfc_init(struct bfa_s *bfa);
void bfa_iocfc_start(struct bfa_s *bfa);
void bfa_iocfc_stop(struct bfa_s *bfa);
void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
-void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
+void bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa);
bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
void bfa_iocfc_reset_queues(struct bfa_s *bfa);
@@ -310,10 +311,10 @@ void bfa_msix_rspq(struct bfa_s *bfa, int vec);
void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
void bfa_hwcb_reginit(struct bfa_s *bfa);
-void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwcb_msix_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_queue_install(struct bfa_s *bfa);
void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
@@ -321,10 +322,12 @@ void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
u32 *end);
void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct2_reginit(struct bfa_s *bfa);
void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwct_msix_install(struct bfa_s *bfa);
+void bfa_hwct_msix_ctrl_install(struct bfa_s *bfa);
+void bfa_hwct_msix_queue_install(struct bfa_s *bfa);
void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
@@ -377,7 +380,8 @@ void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo);
+ struct bfa_meminfo_s *meminfo,
+ struct bfa_s *bfa);
void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 91838c51fb76..c38e589105a5 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -17,7 +17,7 @@
#include "bfad_drv.h"
#include "bfa_modules.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
BFA_TRC_FILE(HAL, CORE);
@@ -25,13 +25,14 @@ BFA_TRC_FILE(HAL, CORE);
* BFA module list terminated by NULL
*/
static struct bfa_module_s *hal_mods[] = {
+ &hal_mod_fcdiag,
&hal_mod_sgpg,
&hal_mod_fcport,
&hal_mod_fcxp,
&hal_mod_lps,
&hal_mod_uf,
&hal_mod_rport,
- &hal_mod_fcpim,
+ &hal_mod_fcp,
NULL
};
@@ -41,7 +42,7 @@ static struct bfa_module_s *hal_mods[] = {
static bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = {
bfa_isr_unhandled, /* NONE */
bfa_isr_unhandled, /* BFI_MC_IOC */
- bfa_isr_unhandled, /* BFI_MC_DIAG */
+ bfa_fcdiag_intr, /* BFI_MC_DIAG */
bfa_isr_unhandled, /* BFI_MC_FLASH */
bfa_isr_unhandled, /* BFI_MC_CEE */
bfa_fcport_isr, /* BFI_MC_FCPORT */
@@ -51,7 +52,7 @@ static bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = {
bfa_fcxp_isr, /* BFI_MC_FCXP */
bfa_lps_isr, /* BFI_MC_LPS */
bfa_rport_isr, /* BFI_MC_RPORT */
- bfa_itnim_isr, /* BFI_MC_ITNIM */
+ bfa_itn_isr, /* BFI_MC_ITN */
bfa_isr_unhandled, /* BFI_MC_IOIM_READ */
bfa_isr_unhandled, /* BFI_MC_IOIM_WRITE */
bfa_isr_unhandled, /* BFI_MC_IOIM_IO */
@@ -89,23 +90,78 @@ static bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = {
static void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+bfa_com_port_attach(struct bfa_s *bfa)
{
struct bfa_port_s *port = &bfa->modules.port;
- u32 dm_len;
- u8 *dm_kva;
- u64 dm_pa;
+ struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa);
- dm_len = bfa_port_meminfo();
- dm_kva = bfa_meminfo_dma_virt(mi);
- dm_pa = bfa_meminfo_dma_phys(mi);
-
- memset(port, 0, sizeof(struct bfa_port_s));
bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
- bfa_port_mem_claim(port, dm_kva, dm_pa);
+ bfa_port_mem_claim(port, port_dma->kva_curp, port_dma->dma_curp);
+}
+
+/*
+ * ablk module attach
+ */
+static void
+bfa_com_ablk_attach(struct bfa_s *bfa)
+{
+ struct bfa_ablk_s *ablk = &bfa->modules.ablk;
+ struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
+
+ bfa_ablk_attach(ablk, &bfa->ioc);
+ bfa_ablk_memclaim(ablk, ablk_dma->kva_curp, ablk_dma->dma_curp);
+}
+
+static void
+bfa_com_cee_attach(struct bfa_s *bfa)
+{
+ struct bfa_cee_s *cee = &bfa->modules.cee;
+ struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa);
+
+ cee->trcmod = bfa->trcmod;
+ bfa_cee_attach(cee, &bfa->ioc, bfa);
+ bfa_cee_mem_claim(cee, cee_dma->kva_curp, cee_dma->dma_curp);
+}
+
+static void
+bfa_com_sfp_attach(struct bfa_s *bfa)
+{
+ struct bfa_sfp_s *sfp = BFA_SFP_MOD(bfa);
+ struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa);
+
+ bfa_sfp_attach(sfp, &bfa->ioc, bfa, bfa->trcmod);
+ bfa_sfp_memclaim(sfp, sfp_dma->kva_curp, sfp_dma->dma_curp);
+}
+
+static void
+bfa_com_flash_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+ struct bfa_flash_s *flash = BFA_FLASH(bfa);
+ struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
+
+ bfa_flash_attach(flash, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+ bfa_flash_memclaim(flash, flash_dma->kva_curp,
+ flash_dma->dma_curp, mincfg);
+}
+
+static void
+bfa_com_diag_attach(struct bfa_s *bfa)
+{
+ struct bfa_diag_s *diag = BFA_DIAG_MOD(bfa);
+ struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
+
+ bfa_diag_attach(diag, &bfa->ioc, bfa, bfa_fcport_beacon, bfa->trcmod);
+ bfa_diag_memclaim(diag, diag_dma->kva_curp, diag_dma->dma_curp);
+}
+
+static void
+bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+ struct bfa_phy_s *phy = BFA_PHY(bfa);
+ struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa);
- bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
- bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+ bfa_phy_attach(phy, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+ bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg);
}
/*
@@ -122,6 +178,7 @@ enum {
BFA_IOCFC_ACT_INIT = 1,
BFA_IOCFC_ACT_STOP = 2,
BFA_IOCFC_ACT_DISABLE = 3,
+ BFA_IOCFC_ACT_ENABLE = 4,
};
#define DEF_CFG_NUM_FABRICS 1
@@ -173,10 +230,92 @@ bfa_reqq_resume(struct bfa_s *bfa, int qid)
}
}
+static inline void
+bfa_isr_rspq(struct bfa_s *bfa, int qid)
+{
+ struct bfi_msg_s *m;
+ u32 pi, ci;
+ struct list_head *waitq;
+
+ bfa_isr_rspq_ack(bfa, qid);
+
+ ci = bfa_rspq_ci(bfa, qid);
+ pi = bfa_rspq_pi(bfa, qid);
+
+ while (ci != pi) {
+ m = bfa_rspq_elem(bfa, qid, ci);
+ WARN_ON(m->mhdr.msg_class >= BFI_MC_MAX);
+
+ bfa_isrs[m->mhdr.msg_class] (bfa, m);
+ CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
+ }
+
+ /*
+ * update CI
+ */
+ bfa_rspq_ci(bfa, qid) = pi;
+ writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
+ mmiowb();
+
+ /*
+ * Resume any pending requests in the corresponding reqq.
+ */
+ waitq = bfa_reqq(bfa, qid);
+ if (!list_empty(waitq))
+ bfa_reqq_resume(bfa, qid);
+}
+
+static inline void
+bfa_isr_reqq(struct bfa_s *bfa, int qid)
+{
+ struct list_head *waitq;
+
+ bfa_isr_reqq_ack(bfa, qid);
+
+ /*
+ * Resume any pending requests in the corresponding reqq.
+ */
+ waitq = bfa_reqq(bfa, qid);
+ if (!list_empty(waitq))
+ bfa_reqq_resume(bfa, qid);
+}
+
void
bfa_msix_all(struct bfa_s *bfa, int vec)
{
- bfa_intx(bfa);
+ u32 intr, qintr;
+ int queue;
+
+ intr = readl(bfa->iocfc.bfa_regs.intr_status);
+ if (!intr)
+ return;
+
+ /*
+ * RME completion queue interrupt
+ */
+ qintr = intr & __HFN_INT_RME_MASK;
+ if (qintr && bfa->queue_process) {
+ for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+ bfa_isr_rspq(bfa, queue);
+ }
+
+ intr &= ~qintr;
+ if (!intr)
+ return;
+
+ /*
+ * CPE completion queue interrupt
+ */
+ qintr = intr & __HFN_INT_CPE_MASK;
+ if (qintr && bfa->queue_process) {
+ for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+ bfa_isr_reqq(bfa, queue);
+ }
+ intr &= ~qintr;
+ if (!intr)
+ return;
+
+ bfa_msix_lpu_err(bfa, intr);
}
bfa_boolean_t
@@ -189,16 +328,19 @@ bfa_intx(struct bfa_s *bfa)
if (!intr)
return BFA_FALSE;
+ qintr = intr & (__HFN_INT_RME_MASK | __HFN_INT_CPE_MASK);
+ if (qintr)
+ writel(qintr, bfa->iocfc.bfa_regs.intr_status);
+
/*
* RME completion queue interrupt
*/
qintr = intr & __HFN_INT_RME_MASK;
- writel(qintr, bfa->iocfc.bfa_regs.intr_status);
-
- for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
- if (intr & (__HFN_INT_RME_Q0 << queue))
- bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+ if (qintr && bfa->queue_process) {
+ for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+ bfa_isr_rspq(bfa, queue);
}
+
intr &= ~qintr;
if (!intr)
return BFA_TRUE;
@@ -207,11 +349,9 @@ bfa_intx(struct bfa_s *bfa)
* CPE completion queue interrupt
*/
qintr = intr & __HFN_INT_CPE_MASK;
- writel(qintr, bfa->iocfc.bfa_regs.intr_status);
-
- for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
- if (intr & (__HFN_INT_CPE_Q0 << queue))
- bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+ if (qintr && bfa->queue_process) {
+ for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+ bfa_isr_reqq(bfa, queue);
}
intr &= ~qintr;
if (!intr)
@@ -225,32 +365,25 @@ bfa_intx(struct bfa_s *bfa)
void
bfa_isr_enable(struct bfa_s *bfa)
{
- u32 intr_unmask;
+ u32 umsk;
int pci_func = bfa_ioc_pcifn(&bfa->ioc);
bfa_trc(bfa, pci_func);
- bfa_msix_install(bfa);
- intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
- __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
- __HFN_INT_LL_HALT);
-
- if (pci_func == 0)
- intr_unmask |= (__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);
- else
- intr_unmask |= (__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);
-
- writel(intr_unmask, bfa->iocfc.bfa_regs.intr_status);
- writel(~intr_unmask, bfa->iocfc.bfa_regs.intr_mask);
- bfa->iocfc.intr_mask = ~intr_unmask;
+ bfa_msix_ctrl_install(bfa);
+
+ if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
+ umsk = __HFN_INT_ERR_MASK_CT2;
+ umsk |= pci_func == 0 ?
+ __HFN_INT_FN0_MASK_CT2 : __HFN_INT_FN1_MASK_CT2;
+ } else {
+ umsk = __HFN_INT_ERR_MASK;
+ umsk |= pci_func == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK;
+ }
+
+ writel(umsk, bfa->iocfc.bfa_regs.intr_status);
+ writel(~umsk, bfa->iocfc.bfa_regs.intr_mask);
+ bfa->iocfc.intr_mask = ~umsk;
bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
}
@@ -263,20 +396,9 @@ bfa_isr_disable(struct bfa_s *bfa)
}
void
-bfa_msix_reqq(struct bfa_s *bfa, int qid)
+bfa_msix_reqq(struct bfa_s *bfa, int vec)
{
- struct list_head *waitq;
-
- qid &= (BFI_IOC_MAX_CQS - 1);
-
- bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
-
- /*
- * Resume any pending requests in the corresponding reqq.
- */
- waitq = bfa_reqq(bfa, qid);
- if (!list_empty(waitq))
- bfa_reqq_resume(bfa, qid);
+ bfa_isr_reqq(bfa, vec - bfa->iocfc.hwif.cpe_vec_q0);
}
void
@@ -290,57 +412,37 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
}
void
-bfa_msix_rspq(struct bfa_s *bfa, int qid)
+bfa_msix_rspq(struct bfa_s *bfa, int vec)
{
- struct bfi_msg_s *m;
- u32 pi, ci;
- struct list_head *waitq;
-
- qid &= (BFI_IOC_MAX_CQS - 1);
-
- bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
-
- ci = bfa_rspq_ci(bfa, qid);
- pi = bfa_rspq_pi(bfa, qid);
-
- if (bfa->rme_process) {
- while (ci != pi) {
- m = bfa_rspq_elem(bfa, qid, ci);
- bfa_isrs[m->mhdr.msg_class] (bfa, m);
- CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
- }
- }
-
- /*
- * update CI
- */
- bfa_rspq_ci(bfa, qid) = pi;
- writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
- mmiowb();
-
- /*
- * Resume any pending requests in the corresponding reqq.
- */
- waitq = bfa_reqq(bfa, qid);
- if (!list_empty(waitq))
- bfa_reqq_resume(bfa, qid);
+ bfa_isr_rspq(bfa, vec - bfa->iocfc.hwif.rme_vec_q0);
}
void
bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
{
u32 intr, curr_value;
+ bfa_boolean_t lpu_isr, halt_isr, pss_isr;
intr = readl(bfa->iocfc.bfa_regs.intr_status);
- if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
- bfa_ioc_mbox_isr(&bfa->ioc);
+ if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
+ halt_isr = intr & __HFN_INT_CPQ_HALT_CT2;
+ pss_isr = intr & __HFN_INT_ERR_PSS_CT2;
+ lpu_isr = intr & (__HFN_INT_MBOX_LPU0_CT2 |
+ __HFN_INT_MBOX_LPU1_CT2);
+ intr &= __HFN_INT_ERR_MASK_CT2;
+ } else {
+ halt_isr = intr & __HFN_INT_LL_HALT;
+ pss_isr = intr & __HFN_INT_ERR_PSS;
+ lpu_isr = intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1);
+ intr &= __HFN_INT_ERR_MASK;
+ }
- intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
- __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
+ if (lpu_isr)
+ bfa_ioc_mbox_isr(&bfa->ioc);
if (intr) {
- if (intr & __HFN_INT_LL_HALT) {
+ if (halt_isr) {
/*
* If LL_HALT bit is set then FW Init Halt LL Port
* Register needs to be cleared as well so Interrupt
@@ -351,7 +453,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
writel(curr_value, bfa->ioc.ioc_regs.ll_halt);
}
- if (intr & __HFN_INT_ERR_PSS) {
+ if (pss_isr) {
/*
* ERR_PSS bit needs to be cleared as well in case
* interrups are shared so driver's interrupt handler is
@@ -359,7 +461,6 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
*/
curr_value = readl(
bfa->ioc.ioc_regs.pss_err_status_reg);
- curr_value &= __PSS_ERR_STATUS_SET;
writel(curr_value,
bfa->ioc.ioc_regs.pss_err_status_reg);
}
@@ -377,41 +478,6 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
* BFA IOC private functions
*/
-static void
-bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
- int i, per_reqq_sz, per_rspq_sz;
-
- per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
- per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
-
- /*
- * Calculate CQ size
- */
- for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
- *dm_len = *dm_len + per_reqq_sz;
- *dm_len = *dm_len + per_rspq_sz;
- }
-
- /*
- * Calculate Shadow CI/PI size
- */
- for (i = 0; i < cfg->fwcfg.num_cqs; i++)
- *dm_len += (2 * BFA_CACHELINE_SZ);
-}
-
-static void
-bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
- *dm_len +=
- BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
- *dm_len +=
- BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
- BFA_CACHELINE_SZ);
-}
-
/*
* Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
*/
@@ -433,8 +499,13 @@ bfa_iocfc_send_cfg(void *bfa_arg)
/*
* initialize IOC configuration info
*/
+ cfg_info->single_msix_vec = 0;
+ if (bfa->msix.nvecs == 1)
+ cfg_info->single_msix_vec = 1;
cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
cfg_info->num_cqs = cfg->fwcfg.num_cqs;
+ cfg_info->num_ioim_reqs = cpu_to_be16(cfg->fwcfg.num_ioim_reqs);
+ cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);
bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
/*
@@ -469,7 +540,7 @@ bfa_iocfc_send_cfg(void *bfa_arg)
* dma map IOC configuration itself
*/
bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
- bfa_lpuid(bfa));
+ bfa_fn_lpu(bfa));
bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
@@ -491,26 +562,40 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
/*
* Initialize chip specific handlers.
*/
- if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
+ if (bfa_asic_id_ctc(bfa_ioc_devid(&bfa->ioc))) {
iocfc->hwif.hw_reginit = bfa_hwct_reginit;
iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
- iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
+ iocfc->hwif.hw_msix_ctrl_install = bfa_hwct_msix_ctrl_install;
+ iocfc->hwif.hw_msix_queue_install = bfa_hwct_msix_queue_install;
iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
+ iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CT;
+ iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CT;
} else {
iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
- iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
- iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+ iocfc->hwif.hw_reqq_ack = NULL;
+ iocfc->hwif.hw_rspq_ack = NULL;
iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
- iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
+ iocfc->hwif.hw_msix_ctrl_install = bfa_hwcb_msix_ctrl_install;
+ iocfc->hwif.hw_msix_queue_install = bfa_hwcb_msix_queue_install;
iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
+ iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CB +
+ bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
+ iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CB +
+ bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
+ }
+
+ if (bfa_asic_id_ct2(bfa_ioc_devid(&bfa->ioc))) {
+ iocfc->hwif.hw_reginit = bfa_hwct2_reginit;
+ iocfc->hwif.hw_isr_mode_set = NULL;
+ iocfc->hwif.hw_rspq_ack = NULL;
}
iocfc->hwif.hw_reginit(bfa);
@@ -518,48 +603,42 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
}
static void
-bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo)
+bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
{
- u8 *dm_kva;
- u64 dm_pa;
- int i, per_reqq_sz, per_rspq_sz;
+ u8 *dm_kva = NULL;
+ u64 dm_pa = 0;
+ int i, per_reqq_sz, per_rspq_sz, dbgsz;
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- int dbgsz;
-
- dm_kva = bfa_meminfo_dma_virt(meminfo);
- dm_pa = bfa_meminfo_dma_phys(meminfo);
+ struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
+ struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
+ struct bfa_mem_dma_s *reqq_dma, *rspq_dma;
- /*
- * First allocate dma memory for IOC.
- */
- bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
- dm_kva += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
- dm_pa += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+ /* First allocate dma memory for IOC */
+ bfa_ioc_mem_claim(&bfa->ioc, bfa_mem_dma_virt(ioc_dma),
+ bfa_mem_dma_phys(ioc_dma));
- /*
- * Claim DMA-able memory for the request/response queues and for shadow
- * ci/pi registers
- */
+ /* Claim DMA-able memory for the request/response queues */
per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
+ BFA_DMA_ALIGN_SZ);
per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
+ BFA_DMA_ALIGN_SZ);
for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
- iocfc->req_cq_ba[i].kva = dm_kva;
- iocfc->req_cq_ba[i].pa = dm_pa;
- memset(dm_kva, 0, per_reqq_sz);
- dm_kva += per_reqq_sz;
- dm_pa += per_reqq_sz;
-
- iocfc->rsp_cq_ba[i].kva = dm_kva;
- iocfc->rsp_cq_ba[i].pa = dm_pa;
- memset(dm_kva, 0, per_rspq_sz);
- dm_kva += per_rspq_sz;
- dm_pa += per_rspq_sz;
+ reqq_dma = BFA_MEM_REQQ_DMA(bfa, i);
+ iocfc->req_cq_ba[i].kva = bfa_mem_dma_virt(reqq_dma);
+ iocfc->req_cq_ba[i].pa = bfa_mem_dma_phys(reqq_dma);
+ memset(iocfc->req_cq_ba[i].kva, 0, per_reqq_sz);
+
+ rspq_dma = BFA_MEM_RSPQ_DMA(bfa, i);
+ iocfc->rsp_cq_ba[i].kva = bfa_mem_dma_virt(rspq_dma);
+ iocfc->rsp_cq_ba[i].pa = bfa_mem_dma_phys(rspq_dma);
+ memset(iocfc->rsp_cq_ba[i].kva, 0, per_rspq_sz);
}
+ /* Claim IOCFC dma memory - for shadow CI/PI */
+ dm_kva = bfa_mem_dma_virt(iocfc_dma);
+ dm_pa = bfa_mem_dma_phys(iocfc_dma);
+
for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
iocfc->req_cq_shadow_ci[i].kva = dm_kva;
iocfc->req_cq_shadow_ci[i].pa = dm_pa;
@@ -572,36 +651,27 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
dm_pa += BFA_CACHELINE_SZ;
}
- /*
- * Claim DMA-able memory for the config info page
- */
+ /* Claim IOCFC dma memory - for the config info page */
bfa->iocfc.cfg_info.kva = dm_kva;
bfa->iocfc.cfg_info.pa = dm_pa;
bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
- /*
- * Claim DMA-able memory for the config response
- */
+ /* Claim IOCFC dma memory - for the config response */
bfa->iocfc.cfgrsp_dma.kva = dm_kva;
bfa->iocfc.cfgrsp_dma.pa = dm_pa;
bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
-
- dm_kva +=
- BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
- BFA_CACHELINE_SZ);
+ dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+ BFA_CACHELINE_SZ);
dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
- BFA_CACHELINE_SZ);
-
-
- bfa_meminfo_dma_virt(meminfo) = dm_kva;
- bfa_meminfo_dma_phys(meminfo) = dm_pa;
+ BFA_CACHELINE_SZ);
+ /* Claim IOCFC kva memory */
dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
if (dbgsz > 0) {
- bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
- bfa_meminfo_kva(meminfo) += dbgsz;
+ bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
+ bfa_mem_kva_curp(iocfc) += dbgsz;
}
}
@@ -613,7 +683,9 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
{
int i;
- bfa->rme_process = BFA_TRUE;
+ bfa->queue_process = BFA_TRUE;
+ for (i = 0; i < BFI_IOC_MAX_CQS; i++)
+ bfa_isr_rspq_ack(bfa, i);
for (i = 0; hal_mods[i]; i++)
hal_mods[i]->start(bfa);
@@ -660,6 +732,16 @@ bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
}
static void
+bfa_iocfc_enable_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+ struct bfa_s *bfa = bfa_arg;
+ struct bfad_s *bfad = bfa->bfad;
+
+ if (compl)
+ complete(&bfad->enable_comp);
+}
+
+static void
bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
{
struct bfa_s *bfa = bfa_arg;
@@ -669,6 +751,37 @@ bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
complete(&bfad->disable_comp);
}
+/**
+ * configure queue registers from firmware response
+ */
+static void
+bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg)
+{
+ int i;
+ struct bfa_iocfc_regs_s *r = &bfa->iocfc.bfa_regs;
+ void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
+
+ for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
+ bfa->iocfc.hw_qid[i] = qreg->hw_qid[i];
+ r->cpe_q_ci[i] = kva + be32_to_cpu(qreg->cpe_q_ci_off[i]);
+ r->cpe_q_pi[i] = kva + be32_to_cpu(qreg->cpe_q_pi_off[i]);
+ r->cpe_q_ctrl[i] = kva + be32_to_cpu(qreg->cpe_qctl_off[i]);
+ r->rme_q_ci[i] = kva + be32_to_cpu(qreg->rme_q_ci_off[i]);
+ r->rme_q_pi[i] = kva + be32_to_cpu(qreg->rme_q_pi_off[i]);
+ r->rme_q_ctrl[i] = kva + be32_to_cpu(qreg->rme_qctl_off[i]);
+ }
+}
+
+static void
+bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg)
+{
+ bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs);
+ bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs);
+ bfa_rport_res_recfg(bfa, fwcfg->num_rports);
+ bfa_fcp_res_recfg(bfa, fwcfg->num_ioim_reqs);
+ bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs);
+}
+
/*
* Update BFA configuration from firmware configuration.
*/
@@ -681,6 +794,7 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
fwcfg->num_cqs = fwcfg->num_cqs;
fwcfg->num_ioim_reqs = be16_to_cpu(fwcfg->num_ioim_reqs);
+ fwcfg->num_fwtio_reqs = be16_to_cpu(fwcfg->num_fwtio_reqs);
fwcfg->num_tskim_reqs = be16_to_cpu(fwcfg->num_tskim_reqs);
fwcfg->num_fcxp_reqs = be16_to_cpu(fwcfg->num_fcxp_reqs);
fwcfg->num_uf_bufs = be16_to_cpu(fwcfg->num_uf_bufs);
@@ -689,14 +803,33 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
iocfc->cfgdone = BFA_TRUE;
/*
+ * configure queue register offsets as learnt from firmware
+ */
+ bfa_iocfc_qreg(bfa, &cfgrsp->qreg);
+
+ /*
+ * Re-configure resources as learnt from Firmware
+ */
+ bfa_iocfc_res_recfg(bfa, fwcfg);
+
+ /*
+ * Install MSIX queue handlers
+ */
+ bfa_msix_queue_install(bfa);
+
+ /*
* Configuration is complete - initialize/start submodules
*/
bfa_fcport_init(bfa);
if (iocfc->action == BFA_IOCFC_ACT_INIT)
bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
- else
+ else {
+ if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
+ bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
+ bfa_iocfc_enable_cb, bfa);
bfa_iocfc_start_submod(bfa);
+ }
}
void
bfa_iocfc_reset_queues(struct bfa_s *bfa)
@@ -711,6 +844,181 @@ bfa_iocfc_reset_queues(struct bfa_s *bfa)
}
}
+/* Fabric Assigned Address specific functions */
+
+/*
+ * Check whether IOC is ready before sending command down
+ */
+static bfa_status_t
+bfa_faa_validate_request(struct bfa_s *bfa)
+{
+ enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
+ u32 card_type = bfa->ioc.attr->card_type;
+
+ if (bfa_ioc_is_operational(&bfa->ioc)) {
+ if ((ioc_type != BFA_IOC_TYPE_FC) || bfa_mfg_is_mezz(card_type))
+ return BFA_STATUS_FEATURE_NOT_SUPPORTED;
+ } else {
+ if (!bfa_ioc_is_acq_addr(&bfa->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+ }
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_enable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn, void *cbarg)
+{
+ struct bfi_faa_en_dis_s faa_enable_req;
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ bfa_status_t status;
+
+ iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+ iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+ status = bfa_faa_validate_request(bfa);
+ if (status != BFA_STATUS_OK)
+ return status;
+
+ if (iocfc->faa_args.busy == BFA_TRUE)
+ return BFA_STATUS_DEVBUSY;
+
+ if (iocfc->faa_args.faa_state == BFA_FAA_ENABLED)
+ return BFA_STATUS_FAA_ENABLED;
+
+ if (bfa_fcport_is_trunk_enabled(bfa))
+ return BFA_STATUS_ERROR_TRUNK_ENABLED;
+
+ bfa_fcport_cfg_faa(bfa, BFA_FAA_ENABLED);
+ iocfc->faa_args.busy = BFA_TRUE;
+
+ memset(&faa_enable_req, 0, sizeof(struct bfi_faa_en_dis_s));
+ bfi_h2i_set(faa_enable_req.mh, BFI_MC_IOCFC,
+ BFI_IOCFC_H2I_FAA_ENABLE_REQ, bfa_fn_lpu(bfa));
+
+ bfa_ioc_mbox_send(&bfa->ioc, &faa_enable_req,
+ sizeof(struct bfi_faa_en_dis_s));
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_disable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn,
+ void *cbarg)
+{
+ struct bfi_faa_en_dis_s faa_disable_req;
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ bfa_status_t status;
+
+ iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+ iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+ status = bfa_faa_validate_request(bfa);
+ if (status != BFA_STATUS_OK)
+ return status;
+
+ if (iocfc->faa_args.busy == BFA_TRUE)
+ return BFA_STATUS_DEVBUSY;
+
+ if (iocfc->faa_args.faa_state == BFA_FAA_DISABLED)
+ return BFA_STATUS_FAA_DISABLED;
+
+ bfa_fcport_cfg_faa(bfa, BFA_FAA_DISABLED);
+ iocfc->faa_args.busy = BFA_TRUE;
+
+ memset(&faa_disable_req, 0, sizeof(struct bfi_faa_en_dis_s));
+ bfi_h2i_set(faa_disable_req.mh, BFI_MC_IOCFC,
+ BFI_IOCFC_H2I_FAA_DISABLE_REQ, bfa_fn_lpu(bfa));
+
+ bfa_ioc_mbox_send(&bfa->ioc, &faa_disable_req,
+ sizeof(struct bfi_faa_en_dis_s));
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
+ bfa_cb_iocfc_t cbfn, void *cbarg)
+{
+ struct bfi_faa_query_s faa_attr_req;
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ bfa_status_t status;
+
+ iocfc->faa_args.faa_attr = attr;
+ iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+ iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+ status = bfa_faa_validate_request(bfa);
+ if (status != BFA_STATUS_OK)
+ return status;
+
+ if (iocfc->faa_args.busy == BFA_TRUE)
+ return BFA_STATUS_DEVBUSY;
+
+ iocfc->faa_args.busy = BFA_TRUE;
+ memset(&faa_attr_req, 0, sizeof(struct bfi_faa_query_s));
+ bfi_h2i_set(faa_attr_req.mh, BFI_MC_IOCFC,
+ BFI_IOCFC_H2I_FAA_QUERY_REQ, bfa_fn_lpu(bfa));
+
+ bfa_ioc_mbox_send(&bfa->ioc, &faa_attr_req,
+ sizeof(struct bfi_faa_query_s));
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * FAA enable response
+ */
+static void
+bfa_faa_enable_reply(struct bfa_iocfc_s *iocfc,
+ struct bfi_faa_en_dis_rsp_s *rsp)
+{
+ void *cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+ bfa_status_t status = rsp->status;
+
+ WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+ iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
+ iocfc->faa_args.busy = BFA_FALSE;
+}
+
+/*
+ * FAA disable response
+ */
+static void
+bfa_faa_disable_reply(struct bfa_iocfc_s *iocfc,
+ struct bfi_faa_en_dis_rsp_s *rsp)
+{
+ void *cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+ bfa_status_t status = rsp->status;
+
+ WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+ iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
+ iocfc->faa_args.busy = BFA_FALSE;
+}
+
+/*
+ * FAA query response
+ */
+static void
+bfa_faa_query_reply(struct bfa_iocfc_s *iocfc,
+ bfi_faa_query_rsp_t *rsp)
+{
+ void *cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+
+ if (iocfc->faa_args.faa_attr) {
+ iocfc->faa_args.faa_attr->faa = rsp->faa;
+ iocfc->faa_args.faa_attr->faa_state = rsp->faa_status;
+ iocfc->faa_args.faa_attr->pwwn_source = rsp->addr_source;
+ }
+
+ WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+ iocfc->faa_args.faa_cb.faa_cbfn(cbarg, BFA_STATUS_OK);
+ iocfc->faa_args.busy = BFA_FALSE;
+}
+
/*
* IOC enable request is complete
*/
@@ -719,11 +1027,20 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
{
struct bfa_s *bfa = bfa_arg;
+ if (status == BFA_STATUS_FAA_ACQ_ADDR) {
+ bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+ bfa_iocfc_init_cb, bfa);
+ return;
+ }
+
if (status != BFA_STATUS_OK) {
bfa_isr_disable(bfa);
if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
bfa_iocfc_init_cb, bfa);
+ else if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
+ bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
+ bfa_iocfc_enable_cb, bfa);
return;
}
@@ -759,7 +1076,7 @@ bfa_iocfc_hbfail_cbfn(void *bfa_arg)
{
struct bfa_s *bfa = bfa_arg;
- bfa->rme_process = BFA_FALSE;
+ bfa->queue_process = BFA_FALSE;
bfa_isr_disable(bfa);
bfa_iocfc_disable_submod(bfa);
@@ -786,15 +1103,47 @@ bfa_iocfc_reset_cbfn(void *bfa_arg)
* Query IOC memory requirement information.
*/
void
-bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
+bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+ struct bfa_s *bfa)
{
- /* dma memory for IOC */
- *dm_len += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+ int q, per_reqq_sz, per_rspq_sz;
+ struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
+ struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
+ struct bfa_mem_kva_s *iocfc_kva = BFA_MEM_IOCFC_KVA(bfa);
+ u32 dm_len = 0;
+
+ /* dma memory setup for IOC */
+ bfa_mem_dma_setup(meminfo, ioc_dma,
+ BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ));
+
+ /* dma memory setup for REQ/RSP queues */
+ per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+ BFA_DMA_ALIGN_SZ);
+ per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+ BFA_DMA_ALIGN_SZ);
+
+ for (q = 0; q < cfg->fwcfg.num_cqs; q++) {
+ bfa_mem_dma_setup(meminfo, BFA_MEM_REQQ_DMA(bfa, q),
+ per_reqq_sz);
+ bfa_mem_dma_setup(meminfo, BFA_MEM_RSPQ_DMA(bfa, q),
+ per_rspq_sz);
+ }
+
+ /* IOCFC dma memory - calculate Shadow CI/PI size */
+ for (q = 0; q < cfg->fwcfg.num_cqs; q++)
+ dm_len += (2 * BFA_CACHELINE_SZ);
+
+ /* IOCFC dma memory - calculate config info / rsp size */
+ dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+ dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+ BFA_CACHELINE_SZ);
- bfa_iocfc_fw_cfg_sz(cfg, dm_len);
- bfa_iocfc_cqs_sz(cfg, dm_len);
- *km_len += (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+ /* dma memory setup for IOCFC */
+ bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len);
+
+ /* kva memory setup for IOCFC */
+ bfa_mem_kva_setup(meminfo, iocfc_kva,
+ ((bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0));
}
/*
@@ -802,7 +1151,7 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
*/
void
bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_pcidev_s *pcidev)
{
int i;
struct bfa_ioc_s *ioc = &bfa->ioc;
@@ -815,17 +1164,11 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
ioc->trcmod = bfa->trcmod;
bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod);
- /*
- * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
- */
- if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
- bfa_ioc_set_fcmode(&bfa->ioc);
-
- bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
+ bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_PCIFN_CLASS_FC);
bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
- bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+ bfa_iocfc_mem_claim(bfa, cfg);
INIT_LIST_HEAD(&bfa->timer_mod.timer_q);
INIT_LIST_HEAD(&bfa->comp_q);
@@ -863,7 +1206,7 @@ bfa_iocfc_stop(struct bfa_s *bfa)
{
bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
- bfa->rme_process = BFA_FALSE;
+ bfa->queue_process = BFA_FALSE;
bfa_ioc_disable(&bfa->ioc);
}
@@ -879,12 +1222,22 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
switch (msg->mh.msg_id) {
case BFI_IOCFC_I2H_CFG_REPLY:
- iocfc->cfg_reply = &msg->cfg_reply;
bfa_iocfc_cfgrsp(bfa);
break;
case BFI_IOCFC_I2H_UPDATEQ_RSP:
iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
break;
+ case BFI_IOCFC_I2H_FAA_ENABLE_RSP:
+ bfa_faa_enable_reply(iocfc,
+ (struct bfi_faa_en_dis_rsp_s *)msg);
+ break;
+ case BFI_IOCFC_I2H_FAA_DISABLE_RSP:
+ bfa_faa_disable_reply(iocfc,
+ (struct bfi_faa_en_dis_rsp_s *)msg);
+ break;
+ case BFI_IOCFC_I2H_FAA_QUERY_RSP:
+ bfa_faa_query_reply(iocfc, (bfi_faa_query_rsp_t *)msg);
+ break;
default:
WARN_ON(1);
}
@@ -926,7 +1279,7 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
return BFA_STATUS_DEVBUSY;
bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
- bfa_lpuid(bfa));
+ bfa_fn_lpu(bfa));
m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
m->delay = iocfc->cfginfo->intr_attr.delay;
m->latency = iocfc->cfginfo->intr_attr.latency;
@@ -934,17 +1287,17 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
bfa_trc(bfa, attr->delay);
bfa_trc(bfa, attr->latency);
- bfa_reqq_produce(bfa, BFA_REQQ_IOC);
+ bfa_reqq_produce(bfa, BFA_REQQ_IOC, m->mh);
return BFA_STATUS_OK;
}
void
-bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa)
{
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
- bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+ bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase[seg_no], snsbase_pa);
}
/*
* Enable IOC after it is disabled.
@@ -954,6 +1307,7 @@ bfa_iocfc_enable(struct bfa_s *bfa)
{
bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
"IOC Enable");
+ bfa->iocfc.action = BFA_IOCFC_ACT_ENABLE;
bfa_ioc_enable(&bfa->ioc);
}
@@ -964,7 +1318,7 @@ bfa_iocfc_disable(struct bfa_s *bfa)
"IOC Disable");
bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
- bfa->rme_process = BFA_FALSE;
+ bfa->queue_process = BFA_FALSE;
bfa_ioc_disable(&bfa->ioc);
}
@@ -1033,33 +1387,49 @@ bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
* starting address for each block and provide the same
* structure as input parameter to bfa_attach() call.
*
+ * @param[in] bfa - pointer to the bfa structure, used while fetching the
+ * dma, kva memory information of the bfa sub-modules.
+ *
* @return void
*
* Special Considerations: @note
*/
void
-bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
+bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+ struct bfa_s *bfa)
{
int i;
- u32 km_len = 0, dm_len = 0;
+ struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa);
+ struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
+ struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa);
+ struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa);
+ struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
+ struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
+ struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa);
WARN_ON((cfg == NULL) || (meminfo == NULL));
memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s));
- meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type =
- BFA_MEM_TYPE_KVA;
- meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type =
- BFA_MEM_TYPE_DMA;
- bfa_iocfc_meminfo(cfg, &km_len, &dm_len);
-
- for (i = 0; hal_mods[i]; i++)
- hal_mods[i]->meminfo(cfg, &km_len, &dm_len);
+ /* Initialize the DMA & KVA meminfo queues */
+ INIT_LIST_HEAD(&meminfo->dma_info.qe);
+ INIT_LIST_HEAD(&meminfo->kva_info.qe);
- dm_len += bfa_port_meminfo();
+ bfa_iocfc_meminfo(cfg, meminfo, bfa);
- meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len;
- meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
+ for (i = 0; hal_mods[i]; i++)
+ hal_mods[i]->meminfo(cfg, meminfo, bfa);
+
+ /* dma info setup */
+ bfa_mem_dma_setup(meminfo, port_dma, bfa_port_meminfo());
+ bfa_mem_dma_setup(meminfo, ablk_dma, bfa_ablk_meminfo());
+ bfa_mem_dma_setup(meminfo, cee_dma, bfa_cee_meminfo());
+ bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo());
+ bfa_mem_dma_setup(meminfo, flash_dma,
+ bfa_flash_meminfo(cfg->drvcfg.min_cfg));
+ bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo());
+ bfa_mem_dma_setup(meminfo, phy_dma,
+ bfa_phy_meminfo(cfg->drvcfg.min_cfg));
}
/*
@@ -1092,28 +1462,46 @@ void
bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
{
- int i;
- struct bfa_mem_elem_s *melem;
+ int i;
+ struct bfa_mem_dma_s *dma_info, *dma_elem;
+ struct bfa_mem_kva_s *kva_info, *kva_elem;
+ struct list_head *dm_qe, *km_qe;
bfa->fcs = BFA_FALSE;
WARN_ON((cfg == NULL) || (meminfo == NULL));
- /*
- * initialize all memory pointers for iterative allocation
- */
- for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
- melem = meminfo->meminfo + i;
- melem->kva_curp = melem->kva;
- melem->dma_curp = melem->dma;
+ /* Initialize memory pointers for iterative allocation */
+ dma_info = &meminfo->dma_info;
+ dma_info->kva_curp = dma_info->kva;
+ dma_info->dma_curp = dma_info->dma;
+
+ kva_info = &meminfo->kva_info;
+ kva_info->kva_curp = kva_info->kva;
+
+ list_for_each(dm_qe, &dma_info->qe) {
+ dma_elem = (struct bfa_mem_dma_s *) dm_qe;
+ dma_elem->kva_curp = dma_elem->kva;
+ dma_elem->dma_curp = dma_elem->dma;
+ }
+
+ list_for_each(km_qe, &kva_info->qe) {
+ kva_elem = (struct bfa_mem_kva_s *) km_qe;
+ kva_elem->kva_curp = kva_elem->kva;
}
- bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev);
+ bfa_iocfc_attach(bfa, bfad, cfg, pcidev);
for (i = 0; hal_mods[i]; i++)
- hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
-
- bfa_com_port_attach(bfa, meminfo);
+ hal_mods[i]->attach(bfa, bfad, cfg, pcidev);
+
+ bfa_com_port_attach(bfa);
+ bfa_com_ablk_attach(bfa);
+ bfa_com_cee_attach(bfa);
+ bfa_com_sfp_attach(bfa);
+ bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
+ bfa_com_diag_attach(bfa);
+ bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg);
}
/*
@@ -1215,6 +1603,7 @@ bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS;
cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS;
cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS;
+ cfg->fwcfg.num_fwtio_reqs = 0;
cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS;
cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS;
@@ -1236,6 +1625,7 @@ bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)
cfg->fwcfg.num_fcxp_reqs = BFA_FCXP_MIN;
cfg->fwcfg.num_uf_bufs = BFA_UF_MIN;
cfg->fwcfg.num_rports = BFA_RPORT_MIN;
+ cfg->fwcfg.num_fwtio_reqs = 0;
cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index d85f93aea465..ed8d31b0188b 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -40,7 +40,12 @@ 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_INVALID = 0, /* Invalid card type */
+ 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)
@@ -53,7 +58,8 @@ enum {
(type) == BFA_MFG_TYPE_WANCHESE || \
(type) == BFA_MFG_TYPE_ASTRA || \
(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
- (type) == BFA_MFG_TYPE_LIGHTNING))
+ (type) == BFA_MFG_TYPE_LIGHTNING || \
+ (type) == BFA_MFG_TYPE_CHINOOK))
/*
* Check if the card having old wwn/mac handling
@@ -124,30 +130,53 @@ enum bfa_status {
BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists,
* contact support */
BFA_STATUS_EPROTOCOL = 6, /* Protocol error */
+ BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */
+ BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */
+ BFA_STATUS_DATACORRUPTED = 12, /* Diag returned data corrupted */
BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */
+ BFA_STATUS_HDMA_FAILED = 16, /* Host dma failed contact support */
+ BFA_STATUS_FLASH_BAD_LEN = 17, /* Flash bad length */
BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */
BFA_STATUS_UNKNOWN_RWWN = 19, /* RPORT PWWN not found */
BFA_STATUS_VPORT_EXISTS = 21, /* VPORT already exists */
BFA_STATUS_VPORT_MAX = 22, /* Reached max VPORT supported limit */
BFA_STATUS_UNSUPP_SPEED = 23, /* Invalid Speed Check speed setting */
BFA_STATUS_INVLD_DFSZ = 24, /* Invalid Max data field size */
+ BFA_STATUS_CMD_NOTSUPP = 26, /* Command/API not supported */
BFA_STATUS_FABRIC_RJT = 29, /* Reject from attached fabric */
+ BFA_STATUS_PORT_OFFLINE = 34, /* Port is not online */
BFA_STATUS_VPORT_WWN_BP = 46, /* WWN is same as base port's WWN */
+ BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port */
BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the rport */
BFA_STATUS_IOC_FAILURE = 56, /* IOC failure - Retry, if persists
* contact support */
BFA_STATUS_INVALID_WWN = 57, /* Invalid WWN */
+ BFA_STATUS_ADAPTER_ENABLED = 60, /* Adapter is not disabled */
+ BFA_STATUS_IOC_NON_OP = 61, /* IOC is not operational */
+ BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */
BFA_STATUS_DIAG_BUSY = 71, /* diag busy */
+ BFA_STATUS_BEACON_ON = 72, /* Port Beacon already on */
BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */
BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */
+ BFA_STATUS_NO_SFP_DEV = 89, /* No SFP device check or replace SFP */
+ BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
+ BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */
BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot
* configuration */
+ BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */
BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
* this adapter */
BFA_STATUS_TRUNK_DISABLED = 165, /* Trunking is disabled on
* the adapter */
BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
+ BFA_STATUS_PHY_NOT_PRESENT = 183, /* PHY module not present */
+ BFA_STATUS_FEATURE_NOT_SUPPORTED = 192, /* Feature not supported */
+ BFA_STATUS_FAA_ENABLED = 197, /* FAA is already enabled */
+ BFA_STATUS_FAA_DISABLED = 198, /* FAA is already disabled */
+ BFA_STATUS_FAA_ACQUIRED = 199, /* FAA is already acquired */
+ BFA_STATUS_FAA_ACQ_ADDR = 200, /* Acquiring addr */
+ BFA_STATUS_ERROR_TRUNK_ENABLED = 203, /* Trunk enabled on adapter */
BFA_STATUS_MAX_VAL /* Unknown error code */
};
#define bfa_status_t enum bfa_status
@@ -265,6 +294,8 @@ 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 */
+ BFA_IOC_ACQ_ADDR = 14, /* Acquiring addr from fabric */
};
/*
@@ -294,6 +325,7 @@ struct bfa_ioc_drv_stats_s {
u32 enable_reqs;
u32 disable_replies;
u32 enable_replies;
+ u32 rsvd;
};
/*
@@ -320,7 +352,10 @@ struct bfa_ioc_attr_s {
struct bfa_ioc_driver_attr_s driver_attr; /* driver attr */
struct bfa_ioc_pci_attr_s pci_attr;
u8 port_id; /* port number */
- u8 rsvd[7]; /* 64bit align */
+ u8 port_mode; /* bfa_mode_s */
+ u8 cap_bm; /* capability */
+ u8 port_mode_cfg; /* bfa_mode_s */
+ u8 rsvd[4]; /* 64bit align */
};
/*
@@ -337,6 +372,21 @@ struct bfa_ioc_attr_s {
#define BFA_MFG_SUPPLIER_PARTNUM_SIZE 20
#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE 20
#define BFA_MFG_SUPPLIER_REVISION_SIZE 4
+/*
+ * Initial capability definition
+ */
+#define BFA_MFG_IC_FC 0x01
+#define BFA_MFG_IC_ETH 0x02
+
+/*
+ * Adapter capability mask definition
+ */
+#define BFA_CM_HBA 0x01
+#define BFA_CM_CNA 0x02
+#define BFA_CM_NIC 0x04
+#define BFA_CM_FC16G 0x08
+#define BFA_CM_SRIOV 0x10
+#define BFA_CM_MEZZ 0x20
#pragma pack(1)
@@ -344,31 +394,39 @@ struct bfa_ioc_attr_s {
* All numerical fields are in big-endian format.
*/
struct bfa_mfg_block_s {
- u8 version; /* manufacturing block version */
- u8 mfg_sig[3]; /* characters 'M', 'F', 'G' */
- u16 mfgsize; /* mfg block size */
- u16 u16_chksum; /* old u16 checksum */
- char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
- char brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
- u8 mfg_day; /* manufacturing day */
- u8 mfg_month; /* manufacturing month */
- u16 mfg_year; /* manufacturing year */
- wwn_t mfg_wwn; /* wwn base for this adapter */
- u8 num_wwn; /* number of wwns assigned */
- u8 mfg_speeds; /* speeds allowed for this adapter */
- u8 rsv[2];
- char supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
- char supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
- char
- supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
- char
- supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
- mac_t mfg_mac; /* mac address */
- u8 num_mac; /* number of mac addresses */
- u8 rsv2;
- u32 mfg_type; /* card type */
- u8 rsv3[108];
- u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /* md5 checksum */
+ u8 version; /*!< manufacturing block version */
+ u8 mfg_sig[3]; /*!< characters 'M', 'F', 'G' */
+ u16 mfgsize; /*!< mfg block size */
+ u16 u16_chksum; /*!< old u16 checksum */
+ char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+ char brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+ u8 mfg_day; /*!< manufacturing day */
+ u8 mfg_month; /*!< manufacturing month */
+ u16 mfg_year; /*!< manufacturing year */
+ wwn_t mfg_wwn; /*!< wwn base for this adapter */
+ u8 num_wwn; /*!< number of wwns assigned */
+ u8 mfg_speeds; /*!< speeds allowed for this adapter */
+ u8 rsv[2];
+ char supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+ char supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+ char supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+ char supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+ mac_t mfg_mac; /*!< base mac address */
+ u8 num_mac; /*!< number of mac addresses */
+ u8 rsv2;
+ 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 */
};
#pragma pack()
@@ -386,17 +444,27 @@ enum {
BFA_PCI_DEVICE_ID_FC_8G1P = 0x17,
BFA_PCI_DEVICE_ID_CT = 0x14,
BFA_PCI_DEVICE_ID_CT_FC = 0x21,
+ BFA_PCI_DEVICE_ID_CT2 = 0x22,
};
-#define bfa_asic_id_ct(devid) \
- ((devid) == BFA_PCI_DEVICE_ID_CT || \
- (devid) == BFA_PCI_DEVICE_ID_CT_FC)
+#define bfa_asic_id_cb(__d) \
+ ((__d) == BFA_PCI_DEVICE_ID_FC_8G2P || \
+ (__d) == BFA_PCI_DEVICE_ID_FC_8G1P)
+#define bfa_asic_id_ct(__d) \
+ ((__d) == BFA_PCI_DEVICE_ID_CT || \
+ (__d) == BFA_PCI_DEVICE_ID_CT_FC)
+#define bfa_asic_id_ct2(__d) ((__d) == BFA_PCI_DEVICE_ID_CT2)
+#define bfa_asic_id_ctc(__d) \
+ (bfa_asic_id_ct(__d) || bfa_asic_id_ct2(__d))
/*
* 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,
};
/*
@@ -416,9 +484,7 @@ enum bfa_port_speed {
BFA_PORT_SPEED_8GBPS = 8,
BFA_PORT_SPEED_10GBPS = 10,
BFA_PORT_SPEED_16GBPS = 16,
- BFA_PORT_SPEED_AUTO =
- (BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
- BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS),
+ BFA_PORT_SPEED_AUTO = 0xf,
};
#define bfa_port_speed_t enum bfa_port_speed
@@ -463,4 +529,453 @@ struct bfa_boot_pbc_s {
struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
};
+/*
+ * ASIC block configuration related structures
+ */
+#define BFA_ABLK_MAX_PORTS 2
+#define BFA_ABLK_MAX_PFS 16
+#define BFA_ABLK_MAX 2
+
+#pragma pack(1)
+enum bfa_mode_s {
+ BFA_MODE_HBA = 1,
+ BFA_MODE_CNA = 2,
+ BFA_MODE_NIC = 3
+};
+
+struct bfa_adapter_cfg_mode_s {
+ u16 max_pf;
+ u16 max_vf;
+ enum bfa_mode_s mode;
+};
+
+struct bfa_ablk_cfg_pf_s {
+ u16 pers;
+ u8 port_id;
+ u8 optrom;
+ u8 valid;
+ u8 sriov;
+ u8 max_vfs;
+ u8 rsvd[1];
+ u16 num_qpairs;
+ u16 num_vectors;
+ u32 bw;
+};
+
+struct bfa_ablk_cfg_port_s {
+ u8 mode;
+ u8 type;
+ u8 max_pfs;
+ u8 rsvd[5];
+};
+
+struct bfa_ablk_cfg_inst_s {
+ u8 nports;
+ u8 max_pfs;
+ u8 rsvd[6];
+ struct bfa_ablk_cfg_pf_s pf_cfg[BFA_ABLK_MAX_PFS];
+ struct bfa_ablk_cfg_port_s port_cfg[BFA_ABLK_MAX_PORTS];
+};
+
+struct bfa_ablk_cfg_s {
+ struct bfa_ablk_cfg_inst_s inst[BFA_ABLK_MAX];
+};
+
+
+/*
+ * SFP module specific
+ */
+#define SFP_DIAGMON_SIZE 10 /* num bytes of diag monitor data */
+
+enum bfa_defs_sfp_media_e {
+ BFA_SFP_MEDIA_UNKNOWN = 0x00,
+ BFA_SFP_MEDIA_CU = 0x01,
+ BFA_SFP_MEDIA_LW = 0x02,
+ BFA_SFP_MEDIA_SW = 0x03,
+ BFA_SFP_MEDIA_EL = 0x04,
+ BFA_SFP_MEDIA_UNSUPPORT = 0x05,
+};
+
+/*
+ * values for xmtr_tech above
+ */
+enum {
+ SFP_XMTR_TECH_CU = (1 << 0), /* copper FC-BaseT */
+ SFP_XMTR_TECH_CP = (1 << 1), /* copper passive */
+ SFP_XMTR_TECH_CA = (1 << 2), /* copper active */
+ SFP_XMTR_TECH_LL = (1 << 3), /* longwave laser */
+ SFP_XMTR_TECH_SL = (1 << 4), /* shortwave laser w/ OFC */
+ SFP_XMTR_TECH_SN = (1 << 5), /* shortwave laser w/o OFC */
+ SFP_XMTR_TECH_EL_INTRA = (1 << 6), /* elec intra-enclosure */
+ SFP_XMTR_TECH_EL_INTER = (1 << 7), /* elec inter-enclosure */
+ SFP_XMTR_TECH_LC = (1 << 8), /* longwave laser */
+ SFP_XMTR_TECH_SA = (1 << 9)
+};
+
+/*
+ * Serial ID: Data Fields -- Address A0h
+ * Basic ID field total 64 bytes
+ */
+struct sfp_srlid_base_s {
+ u8 id; /* 00: Identifier */
+ u8 extid; /* 01: Extended Identifier */
+ u8 connector; /* 02: Connector */
+ u8 xcvr[8]; /* 03-10: Transceiver */
+ u8 encoding; /* 11: Encoding */
+ u8 br_norm; /* 12: BR, Nominal */
+ u8 rate_id; /* 13: Rate Identifier */
+ u8 len_km; /* 14: Length single mode km */
+ u8 len_100m; /* 15: Length single mode 100m */
+ u8 len_om2; /* 16: Length om2 fiber 10m */
+ u8 len_om1; /* 17: Length om1 fiber 10m */
+ u8 len_cu; /* 18: Length copper 1m */
+ u8 len_om3; /* 19: Length om3 fiber 10m */
+ u8 vendor_name[16];/* 20-35 */
+ u8 unalloc1;
+ u8 vendor_oui[3]; /* 37-39 */
+ u8 vendor_pn[16]; /* 40-55 */
+ u8 vendor_rev[4]; /* 56-59 */
+ u8 wavelen[2]; /* 60-61 */
+ u8 unalloc2;
+ u8 cc_base; /* 63: check code for base id field */
+};
+
+/*
+ * Serial ID: Data Fields -- Address A0h
+ * Extended id field total 32 bytes
+ */
+struct sfp_srlid_ext_s {
+ u8 options[2];
+ u8 br_max;
+ u8 br_min;
+ u8 vendor_sn[16];
+ u8 date_code[8];
+ u8 diag_mon_type; /* 92: Diagnostic Monitoring type */
+ u8 en_options;
+ u8 sff_8472;
+ u8 cc_ext;
+};
+
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * Diagnostic and control/status base field total 96 bytes
+ */
+struct sfp_diag_base_s {
+ /*
+ * Alarm and warning Thresholds 40 bytes
+ */
+ u8 temp_high_alarm[2]; /* 00-01 */
+ u8 temp_low_alarm[2]; /* 02-03 */
+ u8 temp_high_warning[2]; /* 04-05 */
+ u8 temp_low_warning[2]; /* 06-07 */
+
+ u8 volt_high_alarm[2]; /* 08-09 */
+ u8 volt_low_alarm[2]; /* 10-11 */
+ u8 volt_high_warning[2]; /* 12-13 */
+ u8 volt_low_warning[2]; /* 14-15 */
+
+ u8 bias_high_alarm[2]; /* 16-17 */
+ u8 bias_low_alarm[2]; /* 18-19 */
+ u8 bias_high_warning[2]; /* 20-21 */
+ u8 bias_low_warning[2]; /* 22-23 */
+
+ u8 tx_pwr_high_alarm[2]; /* 24-25 */
+ u8 tx_pwr_low_alarm[2]; /* 26-27 */
+ u8 tx_pwr_high_warning[2]; /* 28-29 */
+ u8 tx_pwr_low_warning[2]; /* 30-31 */
+
+ u8 rx_pwr_high_alarm[2]; /* 32-33 */
+ u8 rx_pwr_low_alarm[2]; /* 34-35 */
+ u8 rx_pwr_high_warning[2]; /* 36-37 */
+ u8 rx_pwr_low_warning[2]; /* 38-39 */
+
+ u8 unallocate_1[16];
+
+ /*
+ * ext_cal_const[36]
+ */
+ u8 rx_pwr[20];
+ u8 tx_i[4];
+ u8 tx_pwr[4];
+ u8 temp[4];
+ u8 volt[4];
+ u8 unallocate_2[3];
+ u8 cc_dmi;
+};
+
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * Diagnostic and control/status extended field total 24 bytes
+ */
+struct sfp_diag_ext_s {
+ u8 diag[SFP_DIAGMON_SIZE];
+ u8 unalloc1[4];
+ u8 status_ctl;
+ u8 rsvd;
+ u8 alarm_flags[2];
+ u8 unalloc2[2];
+ u8 warning_flags[2];
+ u8 ext_status_ctl[2];
+};
+
+struct sfp_mem_s {
+ struct sfp_srlid_base_s srlid_base;
+ struct sfp_srlid_ext_s srlid_ext;
+ struct sfp_diag_base_s diag_base;
+ struct sfp_diag_ext_s diag_ext;
+};
+
+/*
+ * transceiver codes (SFF-8472 Rev 10.2 Table 3.5)
+ */
+union sfp_xcvr_e10g_code_u {
+ u8 b;
+ struct {
+#ifdef __BIGENDIAN
+ u8 e10g_unall:1; /* 10G Ethernet compliance */
+ u8 e10g_lrm:1;
+ u8 e10g_lr:1;
+ u8 e10g_sr:1;
+ u8 ib_sx:1; /* Infiniband compliance */
+ u8 ib_lx:1;
+ u8 ib_cu_a:1;
+ u8 ib_cu_p:1;
+#else
+ u8 ib_cu_p:1;
+ u8 ib_cu_a:1;
+ u8 ib_lx:1;
+ u8 ib_sx:1; /* Infiniband compliance */
+ u8 e10g_sr:1;
+ u8 e10g_lr:1;
+ u8 e10g_lrm:1;
+ u8 e10g_unall:1; /* 10G Ethernet compliance */
+#endif
+ } r;
+};
+
+union sfp_xcvr_so1_code_u {
+ u8 b;
+ struct {
+ u8 escon:2; /* ESCON compliance code */
+ u8 oc192_reach:1; /* SONET compliance code */
+ u8 so_reach:2;
+ u8 oc48_reach:3;
+ } r;
+};
+
+union sfp_xcvr_so2_code_u {
+ u8 b;
+ struct {
+ u8 reserved:1;
+ u8 oc12_reach:3; /* OC12 reach */
+ u8 reserved1:1;
+ u8 oc3_reach:3; /* OC3 reach */
+ } r;
+};
+
+union sfp_xcvr_eth_code_u {
+ u8 b;
+ struct {
+ u8 base_px:1;
+ u8 base_bx10:1;
+ u8 e100base_fx:1;
+ u8 e100base_lx:1;
+ u8 e1000base_t:1;
+ u8 e1000base_cx:1;
+ u8 e1000base_lx:1;
+ u8 e1000base_sx:1;
+ } r;
+};
+
+struct sfp_xcvr_fc1_code_s {
+ u8 link_len:5; /* FC link length */
+ u8 xmtr_tech2:3;
+ u8 xmtr_tech1:7; /* FC transmitter technology */
+ u8 reserved1:1;
+};
+
+union sfp_xcvr_fc2_code_u {
+ u8 b;
+ struct {
+ u8 tw_media:1; /* twin axial pair (tw) */
+ u8 tp_media:1; /* shielded twisted pair (sp) */
+ u8 mi_media:1; /* miniature coax (mi) */
+ u8 tv_media:1; /* video coax (tv) */
+ u8 m6_media:1; /* multimode, 62.5m (m6) */
+ u8 m5_media:1; /* multimode, 50m (m5) */
+ u8 reserved:1;
+ u8 sm_media:1; /* single mode (sm) */
+ } r;
+};
+
+union sfp_xcvr_fc3_code_u {
+ u8 b;
+ struct {
+#ifdef __BIGENDIAN
+ u8 rsv4:1;
+ u8 mb800:1; /* 800 Mbytes/sec */
+ u8 mb1600:1; /* 1600 Mbytes/sec */
+ u8 mb400:1; /* 400 Mbytes/sec */
+ u8 rsv2:1;
+ u8 mb200:1; /* 200 Mbytes/sec */
+ u8 rsv1:1;
+ u8 mb100:1; /* 100 Mbytes/sec */
+#else
+ u8 mb100:1; /* 100 Mbytes/sec */
+ u8 rsv1:1;
+ u8 mb200:1; /* 200 Mbytes/sec */
+ u8 rsv2:1;
+ u8 mb400:1; /* 400 Mbytes/sec */
+ u8 mb1600:1; /* 1600 Mbytes/sec */
+ u8 mb800:1; /* 800 Mbytes/sec */
+ u8 rsv4:1;
+#endif
+ } r;
+};
+
+struct sfp_xcvr_s {
+ union sfp_xcvr_e10g_code_u e10g;
+ union sfp_xcvr_so1_code_u so1;
+ union sfp_xcvr_so2_code_u so2;
+ union sfp_xcvr_eth_code_u eth;
+ struct sfp_xcvr_fc1_code_s fc1;
+ union sfp_xcvr_fc2_code_u fc2;
+ union sfp_xcvr_fc3_code_u fc3;
+};
+
+/*
+ * Flash module specific
+ */
+#define BFA_FLASH_PART_ENTRY_SIZE 32 /* partition entry size */
+#define BFA_FLASH_PART_MAX 32 /* maximal # of partitions */
+
+enum bfa_flash_part_type {
+ BFA_FLASH_PART_OPTROM = 1, /* option rom partition */
+ BFA_FLASH_PART_FWIMG = 2, /* firmware image partition */
+ BFA_FLASH_PART_FWCFG = 3, /* firmware tuneable config */
+ BFA_FLASH_PART_DRV = 4, /* IOC driver config */
+ BFA_FLASH_PART_BOOT = 5, /* boot config */
+ BFA_FLASH_PART_ASIC = 6, /* asic bootstrap configuration */
+ BFA_FLASH_PART_MFG = 7, /* manufacturing block partition */
+ BFA_FLASH_PART_OPTROM2 = 8, /* 2nd option rom partition */
+ BFA_FLASH_PART_VPD = 9, /* vpd data of OEM info */
+ BFA_FLASH_PART_PBC = 10, /* pre-boot config */
+ BFA_FLASH_PART_BOOTOVL = 11, /* boot overlay partition */
+ BFA_FLASH_PART_LOG = 12, /* firmware log partition */
+ BFA_FLASH_PART_PXECFG = 13, /* pxe boot config partition */
+ BFA_FLASH_PART_PXEOVL = 14, /* pxe boot overlay partition */
+ BFA_FLASH_PART_PORTCFG = 15, /* port cfg partition */
+ BFA_FLASH_PART_ASICBK = 16, /* asic backup partition */
+};
+
+/*
+ * flash partition attributes
+ */
+struct bfa_flash_part_attr_s {
+ u32 part_type; /* partition type */
+ u32 part_instance; /* partition instance */
+ u32 part_off; /* partition offset */
+ u32 part_size; /* partition size */
+ u32 part_len; /* partition content length */
+ u32 part_status; /* partition status */
+ char rsv[BFA_FLASH_PART_ENTRY_SIZE - 24];
+};
+
+/*
+ * flash attributes
+ */
+struct bfa_flash_attr_s {
+ u32 status; /* flash overall status */
+ u32 npart; /* num of partitions */
+ struct bfa_flash_part_attr_s part[BFA_FLASH_PART_MAX];
+};
+
+/*
+ * DIAG module specific
+ */
+#define LB_PATTERN_DEFAULT 0xB5B5B5B5
+#define QTEST_CNT_DEFAULT 10
+#define QTEST_PAT_DEFAULT LB_PATTERN_DEFAULT
+
+struct bfa_diag_memtest_s {
+ u8 algo;
+ u8 rsvd[7];
+};
+
+struct bfa_diag_memtest_result {
+ u32 status;
+ u32 addr;
+ u32 exp; /* expect value read from reg */
+ u32 act; /* actually value read */
+ u32 err_status; /* error status reg */
+ u32 err_status1; /* extra error info reg */
+ u32 err_addr; /* error address reg */
+ u8 algo;
+ u8 rsv[3];
+};
+
+struct bfa_diag_loopback_result_s {
+ u32 numtxmfrm; /* no. of transmit frame */
+ u32 numosffrm; /* no. of outstanding frame */
+ u32 numrcvfrm; /* no. of received good frame */
+ u32 badfrminf; /* mis-match info */
+ u32 badfrmnum; /* mis-match fram number */
+ u8 status; /* loopback test result */
+ u8 rsvd[3];
+};
+
+struct bfa_diag_ledtest_s {
+ u32 cmd; /* bfa_led_op_t */
+ u32 color; /* bfa_led_color_t */
+ u16 freq; /* no. of blinks every 10 secs */
+ u8 led; /* bitmap of LEDs to be tested */
+ u8 rsvd[5];
+};
+
+struct bfa_diag_loopback_s {
+ u32 loopcnt;
+ u32 pattern;
+ u8 lb_mode; /* bfa_port_opmode_t */
+ u8 speed; /* bfa_port_speed_t */
+ u8 rsvd[2];
+};
+
+/*
+ * PHY module specific
+ */
+enum bfa_phy_status_e {
+ BFA_PHY_STATUS_GOOD = 0, /* phy is good */
+ BFA_PHY_STATUS_NOT_PRESENT = 1, /* phy does not exist */
+ BFA_PHY_STATUS_BAD = 2, /* phy is bad */
+};
+
+/*
+ * phy attributes for phy query
+ */
+struct bfa_phy_attr_s {
+ u32 status; /* phy present/absent status */
+ u32 length; /* firmware length */
+ u32 fw_ver; /* firmware version */
+ u32 an_status; /* AN status */
+ u32 pma_pmd_status; /* PMA/PMD link status */
+ u32 pma_pmd_signal; /* PMA/PMD signal detect */
+ u32 pcs_status; /* PCS link status */
+};
+
+/*
+ * phy stats
+ */
+struct bfa_phy_stats_s {
+ u32 status; /* phy stats status */
+ u32 link_breaks; /* Num of link breaks after linkup */
+ u32 pma_pmd_fault; /* NPMA/PMD fault */
+ u32 pcs_fault; /* PCS fault */
+ u32 speed_neg; /* Num of speed negotiation */
+ u32 tx_eq_training; /* Num of TX EQ training */
+ u32 tx_eq_timeout; /* Num of TX EQ timeout */
+ u32 crc_error; /* Num of CRC errors */
+};
+
+#pragma pack()
+
#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h
index 191d34a58b9c..3bbc583f65cf 100644
--- a/drivers/scsi/bfa/bfa_defs_fcs.h
+++ b/drivers/scsi/bfa/bfa_defs_fcs.h
@@ -90,12 +90,14 @@ enum bfa_lport_role {
* FCS port configuration.
*/
struct bfa_lport_cfg_s {
- wwn_t pwwn; /* port wwn */
- wwn_t nwwn; /* node wwn */
- struct bfa_lport_symname_s sym_name; /* vm port symbolic name */
- bfa_boolean_t preboot_vp; /* vport created from PBC */
- enum bfa_lport_role roles; /* FCS port roles */
- u8 tag[16]; /* opaque tag from application */
+ wwn_t pwwn; /* port wwn */
+ wwn_t nwwn; /* node wwn */
+ struct bfa_lport_symname_s sym_name; /* vm port symbolic name */
+ enum bfa_lport_role roles; /* FCS port roles */
+ u32 rsvd;
+ bfa_boolean_t preboot_vp; /* vport created from PBC */
+ u8 tag[16]; /* opaque tag from application */
+ u8 padding[4];
};
/*
@@ -249,12 +251,13 @@ enum bfa_vport_state {
BFA_FCS_VPORT_FDISC_SEND = 2,
BFA_FCS_VPORT_FDISC = 3,
BFA_FCS_VPORT_FDISC_RETRY = 4,
- BFA_FCS_VPORT_ONLINE = 5,
- BFA_FCS_VPORT_DELETING = 6,
- BFA_FCS_VPORT_CLEANUP = 6,
- BFA_FCS_VPORT_LOGO_SEND = 7,
- BFA_FCS_VPORT_LOGO = 8,
- BFA_FCS_VPORT_ERROR = 9,
+ BFA_FCS_VPORT_FDISC_RSP_WAIT = 5,
+ BFA_FCS_VPORT_ONLINE = 6,
+ BFA_FCS_VPORT_DELETING = 7,
+ BFA_FCS_VPORT_CLEANUP = 8,
+ BFA_FCS_VPORT_LOGO_SEND = 9,
+ BFA_FCS_VPORT_LOGO = 10,
+ BFA_FCS_VPORT_ERROR = 11,
BFA_FCS_VPORT_MAX_STATE,
};
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index 207f598877c7..0b97525803fb 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -47,13 +47,12 @@ struct bfa_iocfc_fwcfg_s {
u16 num_rports; /* number of remote ports */
u16 num_ioim_reqs; /* number of IO reqs */
u16 num_tskim_reqs; /* task management requests */
- u16 num_iotm_reqs; /* number of TM IO reqs */
- u16 num_tsktm_reqs; /* TM task management requests*/
+ u16 num_fwtio_reqs; /* number of TM IO reqs in FW */
u16 num_fcxp_reqs; /* unassisted FC exchanges */
u16 num_uf_bufs; /* unsolicited recv buffers */
u8 num_cqs;
u8 fw_tick_res; /* FW clock resolution in ms */
- u8 rsvd[4];
+ u8 rsvd[2];
};
#pragma pack()
@@ -66,8 +65,12 @@ struct bfa_iocfc_drvcfg_s {
u16 ioc_recover; /* IOC recovery mode */
u16 min_cfg; /* minimum configuration */
u16 path_tov; /* device path timeout */
+ u16 num_tio_reqs; /*!< number of TM IO reqs */
+ u8 port_mode;
+ u8 rsvd_a;
bfa_boolean_t delay_comp; /* delay completion of
failed inflight IOs */
+ u16 num_ttsk_reqs; /* TM task management requests */
u32 rsvd;
};
@@ -82,7 +85,7 @@ struct bfa_iocfc_cfg_s {
/*
* IOC firmware IO stats
*/
-struct bfa_fw_io_stats_s {
+struct bfa_fw_ioim_stats_s {
u32 host_abort; /* IO aborted by host driver*/
u32 host_cleanup; /* IO clean up by host driver */
@@ -152,6 +155,54 @@ struct bfa_fw_io_stats_s {
*/
};
+struct bfa_fw_tio_stats_s {
+ u32 tio_conf_proc; /* TIO CONF processed */
+ u32 tio_conf_drop; /* TIO CONF dropped */
+ u32 tio_cleanup_req; /* TIO cleanup requested */
+ u32 tio_cleanup_comp; /* TIO cleanup completed */
+ u32 tio_abort_rsp; /* TIO abort response */
+ u32 tio_abort_rsp_comp; /* TIO abort rsp completed */
+ u32 tio_abts_req; /* TIO ABTS requested */
+ u32 tio_abts_ack; /* TIO ABTS ack-ed */
+ u32 tio_abts_ack_nocomp; /* TIO ABTS ack-ed but not completed */
+ u32 tio_abts_tmo; /* TIO ABTS timeout */
+ u32 tio_snsdata_dma; /* TIO sense data DMA */
+ u32 tio_rxwchan_wait; /* TIO waiting for RX wait channel */
+ u32 tio_rxwchan_avail; /* TIO RX wait channel available */
+ u32 tio_hit_bls; /* TIO IOH BLS event */
+ u32 tio_uf_recv; /* TIO received UF */
+ u32 tio_rd_invalid_sm; /* TIO read reqst in wrong state machine */
+ u32 tio_wr_invalid_sm;/* TIO write reqst in wrong state machine */
+
+ u32 ds_rxwchan_wait; /* DS waiting for RX wait channel */
+ u32 ds_rxwchan_avail; /* DS RX wait channel available */
+ u32 ds_unaligned_rd; /* DS unaligned read */
+ u32 ds_rdcomp_invalid_sm; /* DS read completed in wrong state machine */
+ u32 ds_wrcomp_invalid_sm; /* DS write completed in wrong state machine */
+ u32 ds_flush_req; /* DS flush requested */
+ u32 ds_flush_comp; /* DS flush completed */
+ u32 ds_xfrdy_exp; /* DS XFER_RDY expired */
+ u32 ds_seq_cnt_err; /* DS seq cnt error */
+ u32 ds_seq_len_err; /* DS seq len error */
+ u32 ds_data_oor; /* DS data out of order */
+ u32 ds_hit_bls; /* DS hit BLS */
+ u32 ds_edtov_timer_exp; /* DS edtov expired */
+ u32 ds_cpu_owned; /* DS cpu owned */
+ u32 ds_hit_class2; /* DS hit class2 */
+ u32 ds_length_err; /* DS length error */
+ u32 ds_ro_ooo_err; /* DS relative offset out-of-order error */
+ u32 ds_rectov_timer_exp; /* DS rectov expired */
+ u32 ds_unexp_fr_err; /* DS unexp frame error */
+};
+
+/*
+ * IOC firmware IO stats
+ */
+struct bfa_fw_io_stats_s {
+ struct bfa_fw_ioim_stats_s ioim_stats;
+ struct bfa_fw_tio_stats_s tio_stats;
+};
+
/*
* IOC port firmware stats
*/
@@ -205,6 +256,7 @@ struct bfa_fw_port_lksm_stats_s {
u32 nos_tx; /* No. of times NOS tx started */
u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */
u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */
+ u32 bbsc_lr; /* LKSM LR tx for credit recovery */
};
struct bfa_fw_port_snsm_stats_s {
@@ -266,8 +318,8 @@ struct bfa_fw_fcoe_stats_s {
* IOC firmware FCoE port stats
*/
struct bfa_fw_fcoe_port_stats_s {
- struct bfa_fw_fcoe_stats_s fcoe_stats;
- struct bfa_fw_fip_stats_s fip_stats;
+ struct bfa_fw_fcoe_stats_s fcoe_stats;
+ struct bfa_fw_fip_stats_s fip_stats;
};
/*
@@ -636,6 +688,7 @@ enum bfa_port_states {
BFA_PORT_ST_FWMISMATCH = 12,
BFA_PORT_ST_PREBOOT_DISABLED = 13,
BFA_PORT_ST_TOGGLING_QWAIT = 14,
+ BFA_PORT_ST_ACQ_ADDR = 15,
BFA_PORT_ST_MAX_STATE,
};
@@ -748,6 +801,10 @@ struct bfa_port_cfg_s {
u8 tx_bbcredit; /* transmit buffer credits */
u8 ratelimit; /* ratelimit enabled or not */
u8 trl_def_speed; /* ratelimit default speed */
+ u8 bb_scn; /* BB_SCN value from FLOGI Exchg */
+ u8 bb_scn_state; /* Config state of BB_SCN */
+ u8 faa_state; /* FAA enabled/disabled */
+ u8 rsvd[1];
u16 path_tov; /* device path timeout */
u16 q_depth; /* SCSI Queue depth */
};
@@ -783,7 +840,7 @@ struct bfa_port_attr_s {
enum bfa_port_topology topology; /* current topology */
bfa_boolean_t beacon; /* current beacon status */
bfa_boolean_t link_e2e_beacon; /* link beacon is on */
- bfa_boolean_t plog_enabled; /* portlog is enabled */
+ bfa_boolean_t bbsc_op_status; /* fc credit recovery oper state */
/*
* Dynamic field - info from FCS
@@ -792,12 +849,10 @@ struct bfa_port_attr_s {
enum bfa_port_type port_type; /* current topology */
u32 loopback; /* external loopback */
u32 authfail; /* auth fail state */
- bfa_boolean_t io_profile; /* get it from fcpim mod */
- u8 pad[4]; /* for 64-bit alignement */
/* FCoE specific */
u16 fcoe_vlan;
- u8 rsvd1[6];
+ u8 rsvd1[2];
};
/*
@@ -988,6 +1043,19 @@ struct bfa_itnim_ioprofile_s {
};
/*
+ * vHBA port attribute values.
+ */
+struct bfa_vhba_attr_s {
+ wwn_t nwwn; /* node wwn */
+ wwn_t pwwn; /* port wwn */
+ u32 pid; /* port ID */
+ bfa_boolean_t io_profile; /* get it from fcpim mod */
+ bfa_boolean_t plog_enabled; /* portlog is enabled */
+ u16 path_tov;
+ u8 rsvd[2];
+};
+
+/*
* FC physical port statistics.
*/
struct bfa_port_fc_stats_s {
@@ -1020,6 +1088,9 @@ struct bfa_port_fc_stats_s {
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 */
};
/*
@@ -1078,4 +1149,83 @@ union bfa_port_stats_u {
struct bfa_port_eth_stats_s eth;
};
+struct bfa_port_cfg_mode_s {
+ u16 max_pf;
+ u16 max_vf;
+ enum bfa_mode_s mode;
+};
+
+#pragma pack(1)
+
+#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
+#define BFA_CEE_DCBX_MAX_PRIORITY (8)
+#define BFA_CEE_DCBX_MAX_PGID (8)
+
+struct bfa_cee_lldp_str_s {
+ u8 sub_type;
+ u8 len;
+ u8 rsvd[2];
+ u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
+};
+
+struct bfa_cee_lldp_cfg_s {
+ struct bfa_cee_lldp_str_s chassis_id;
+ struct bfa_cee_lldp_str_s port_id;
+ struct bfa_cee_lldp_str_s port_desc;
+ struct bfa_cee_lldp_str_s sys_name;
+ struct bfa_cee_lldp_str_s sys_desc;
+ struct bfa_cee_lldp_str_s mgmt_addr;
+ u16 time_to_live;
+ u16 enabled_system_cap;
+};
+
+/* CEE/DCBX parameters */
+struct bfa_cee_dcbx_cfg_s {
+ u8 pgid[BFA_CEE_DCBX_MAX_PRIORITY];
+ u8 pg_percentage[BFA_CEE_DCBX_MAX_PGID];
+ u8 pfc_primap; /* bitmap of priorties with PFC enabled */
+ u8 fcoe_primap; /* bitmap of priorities used for FcoE traffic */
+ u8 iscsi_primap; /* bitmap of priorities used for iSCSI traffic */
+ u8 dcbx_version; /* operating version:CEE or preCEE */
+ u8 lls_fcoe; /* FCoE Logical Link Status */
+ u8 lls_lan; /* LAN Logical Link Status */
+ u8 rsvd[2];
+};
+
+/* CEE Query */
+struct bfa_cee_attr_s {
+ u8 cee_status;
+ u8 error_reason;
+ struct bfa_cee_lldp_cfg_s lldp_remote;
+ struct bfa_cee_dcbx_cfg_s dcbx_remote;
+ mac_t src_mac;
+ u8 link_speed;
+ u8 nw_priority;
+ u8 filler[2];
+};
+
+/* LLDP/DCBX/CEE Statistics */
+struct bfa_cee_stats_s {
+ u32 lldp_tx_frames; /* LLDP Tx Frames */
+ u32 lldp_rx_frames; /* LLDP Rx Frames */
+ u32 lldp_rx_frames_invalid; /* LLDP Rx Frames invalid */
+ u32 lldp_rx_frames_new; /* LLDP Rx Frames new */
+ u32 lldp_tlvs_unrecognized; /* LLDP Rx unrecog. TLVs */
+ u32 lldp_rx_shutdown_tlvs; /* LLDP Rx shutdown TLVs */
+ u32 lldp_info_aged_out; /* LLDP remote info aged */
+ u32 dcbx_phylink_ups; /* DCBX phy link ups */
+ u32 dcbx_phylink_downs; /* DCBX phy link downs */
+ u32 dcbx_rx_tlvs; /* DCBX Rx TLVs */
+ u32 dcbx_rx_tlvs_invalid; /* DCBX Rx TLVs invalid */
+ u32 dcbx_control_tlv_error; /* DCBX control TLV errors */
+ u32 dcbx_feature_tlv_error; /* DCBX feature TLV errors */
+ u32 dcbx_cee_cfg_new; /* DCBX new CEE cfg rcvd */
+ u32 cee_status_down; /* DCB status down */
+ u32 cee_status_up; /* DCB status up */
+ u32 cee_hw_cfg_changed; /* DCB hw cfg changed */
+ u32 cee_rx_invalid_cfg; /* DCB invalid cfg */
+};
+
+#pragma pack()
+
#endif /* __BFA_DEFS_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index bf0067e0fd0d..8d0b88f67a38 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -1021,7 +1021,7 @@ struct fc_symname_s {
#define FC_ED_TOV 2
#define FC_REC_TOV (FC_ED_TOV + 1)
#define FC_RA_TOV 10
-#define FC_ELS_TOV (2 * FC_RA_TOV)
+#define FC_ELS_TOV ((2 * FC_RA_TOV) + 1)
#define FC_FCCT_TOV (3 * FC_RA_TOV)
/*
@@ -1049,15 +1049,6 @@ struct fc_vft_s {
};
/*
- * FCP
- */
-enum {
- FCP_RJT = 0x01000000, /* SRR reject */
- FCP_SRR_ACCEPT = 0x02000000, /* SRR accept */
- FCP_SRR = 0x14000000, /* Sequence Retransmission Request */
-};
-
-/*
* FCP_CMND definitions
*/
#define FCP_CMND_CDB_LEN 16
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index b7e253451654..17b59b8b5644 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -94,7 +94,6 @@ fcbuild_init(void)
*/
plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
- plogi_tmpl.csp.bbcred = cpu_to_be16(0x0004);
plogi_tmpl.csp.ciro = 0x1;
plogi_tmpl.csp.cisc = 0x0;
plogi_tmpl.csp.altbbcred = 0x0;
@@ -156,6 +155,22 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
*/
}
+static void
+fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+ memset(fchs, 0, sizeof(struct fchs_s));
+
+ fchs->routing = FC_RTG_FC4_DEV_DATA;
+ fchs->cat_info = FC_CAT_SOLICIT_CTRL;
+ fchs->type = FC_TYPE_SERVICES;
+ fchs->f_ctl =
+ bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+ FCTL_END_SEQ | FCTL_SI_XFER);
+ fchs->d_id = d_id;
+ fchs->s_id = s_id;
+ fchs->ox_id = ox_id;
+}
+
void
fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
{
@@ -207,7 +222,7 @@ fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
static u16
fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
__be16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size, u8 els_code)
+ u16 pdu_size, u16 bb_cr, u8 els_code)
{
struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
@@ -220,6 +235,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
+ plogi->csp.bbcred = cpu_to_be16(bb_cr);
memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
@@ -268,15 +284,17 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
u16
fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
__be16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size, u16 local_bb_credits)
+ u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
{
u32 d_id = 0;
+ u16 bbscn_rxsz = (bb_scn << 12) | pdu_size;
memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
flogi->els_cmd.els_code = FC_ELS_ACC;
- flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
+ flogi->class3.rxsz = cpu_to_be16(pdu_size);
+ flogi->csp.rxsz = cpu_to_be16(bbscn_rxsz); /* bb_scn/rxsz */
flogi->port_name = port_name;
flogi->node_name = node_name;
@@ -306,19 +324,19 @@ fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
u16
fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size)
+ u16 pdu_size, u16 bb_cr)
{
return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
- node_name, pdu_size, FC_ELS_PLOGI);
+ node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
}
u16
fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size)
+ u16 pdu_size, u16 bb_cr)
{
return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
- node_name, pdu_size, FC_ELS_ACC);
+ node_name, pdu_size, bb_cr, FC_ELS_ACC);
}
enum fc_parse_status
@@ -1096,6 +1114,21 @@ fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
}
u16
+fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr,
+ u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
+ u8 reason_code_expl)
+{
+ fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id);
+
+ cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT);
+ cthdr->rev_id = CT_GS3_REVISION;
+
+ cthdr->reason_code = reason_code;
+ cthdr->exp_code = reason_code_expl;
+ return sizeof(struct ct_hdr_s);
+}
+
+u16
fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
u8 set_br_reg, u32 s_id, u16 ox_id)
{
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index ece51ec7620b..42cd9d4da697 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -66,6 +66,9 @@ fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
case RPSC_OP_SPEED_8G:
return BFA_PORT_SPEED_8GBPS;
+ case RPSC_OP_SPEED_16G:
+ return BFA_PORT_SPEED_16GBPS;
+
case RPSC_OP_SPEED_10G:
return BFA_PORT_SPEED_10GBPS;
@@ -94,6 +97,9 @@ fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
case BFA_PORT_SPEED_8GBPS:
return RPSC_OP_SPEED_8G;
+ case BFA_PORT_SPEED_16GBPS:
+ return RPSC_OP_SPEED_16G;
+
case BFA_PORT_SPEED_10GBPS:
return RPSC_OP_SPEED_10G;
@@ -141,11 +147,11 @@ u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
u32 s_id, __be16 ox_id,
wwn_t port_name, wwn_t node_name,
u16 pdu_size,
- u16 local_bb_credits);
+ u16 local_bb_credits, u8 bb_scn);
u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
u32 s_id, u16 ox_id, wwn_t port_name,
- wwn_t node_name, u16 pdu_size);
+ wwn_t node_name, u16 pdu_size, u16 bb_cr);
enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
@@ -177,13 +183,17 @@ u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
u16 ox_id, u32 port_id);
+u16 fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr,
+ u32 d_id, u32 s_id, u16 ox_id,
+ u8 reason_code, u8 reason_code_expl);
+
u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
u8 set_br_reg, u32 s_id, u16 ox_id);
u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
u32 s_id, u16 ox_id,
wwn_t port_name, wwn_t node_name,
- u16 pdu_size);
+ u16 pdu_size, u16 bb_cr);
u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index c0353cdca929..a4e7951c6063 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -19,7 +19,6 @@
#include "bfa_modules.h"
BFA_TRC_FILE(HAL, FCPIM);
-BFA_MODULE(fcpim);
/*
* BFA ITNIM Related definitions
@@ -287,24 +286,16 @@ static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
* Compute and return memory needed by FCP(im) module.
*/
static void
-bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
+bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
{
- bfa_itnim_meminfo(cfg, km_len, dm_len);
+ bfa_itnim_meminfo(cfg, km_len);
/*
* IO memory
*/
- if (cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
- cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
- else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
- cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
-
*km_len += cfg->fwcfg.num_ioim_reqs *
(sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s));
- *dm_len += cfg->fwcfg.num_ioim_reqs * BFI_IOIM_SNSLEN;
-
/*
* task management command memory
*/
@@ -315,52 +306,41 @@ bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
static void
-bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+bfa_fcpim_attach(struct bfa_fcp_mod_s *fcp, void *bfad,
+ struct bfa_iocfc_cfg_s *cfg, struct bfa_pcidev_s *pcidev)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = &fcp->fcpim;
+ struct bfa_s *bfa = fcp->bfa;
bfa_trc(bfa, cfg->drvcfg.path_tov);
bfa_trc(bfa, cfg->fwcfg.num_rports);
bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
+ fcpim->fcp = fcp;
fcpim->bfa = bfa;
fcpim->num_itnims = cfg->fwcfg.num_rports;
- fcpim->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
fcpim->path_tov = cfg->drvcfg.path_tov;
fcpim->delay_comp = cfg->drvcfg.delay_comp;
fcpim->profile_comp = NULL;
fcpim->profile_start = NULL;
- bfa_itnim_attach(fcpim, meminfo);
- bfa_tskim_attach(fcpim, meminfo);
- bfa_ioim_attach(fcpim, meminfo);
-}
-
-static void
-bfa_fcpim_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcpim_start(struct bfa_s *bfa)
-{
+ bfa_itnim_attach(fcpim);
+ bfa_tskim_attach(fcpim);
+ bfa_ioim_attach(fcpim);
}
static void
-bfa_fcpim_stop(struct bfa_s *bfa)
+bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *fcp)
{
-}
-
-static void
-bfa_fcpim_iocdisable(struct bfa_s *bfa)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = &fcp->fcpim;
struct bfa_itnim_s *itnim;
struct list_head *qe, *qen;
+ /* Enqueue unused ioim resources to free_q */
+ list_splice_tail_init(&fcpim->tskim_unused_q, &fcpim->tskim_free_q);
+
list_for_each_safe(qe, qen, &fcpim->itnim_q) {
itnim = (struct bfa_itnim_s *) qe;
bfa_itnim_iocdisable(itnim);
@@ -370,7 +350,7 @@ bfa_fcpim_iocdisable(struct bfa_s *bfa)
void
bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
fcpim->path_tov = path_tov * 1000;
if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX)
@@ -380,15 +360,87 @@ bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
u16
bfa_fcpim_path_tov_get(struct bfa_s *bfa)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
return fcpim->path_tov / 1000;
}
+#define bfa_fcpim_add_iostats(__l, __r, __stats) \
+ (__l->__stats += __r->__stats)
+
+void
+bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
+ struct bfa_itnim_iostats_s *rstats)
+{
+ bfa_fcpim_add_iostats(lstats, rstats, total_ios);
+ bfa_fcpim_add_iostats(lstats, rstats, qresumes);
+ bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
+ bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
+ bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
+ bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
+ bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
+ bfa_fcpim_add_iostats(lstats, rstats, onlines);
+ bfa_fcpim_add_iostats(lstats, rstats, offlines);
+ bfa_fcpim_add_iostats(lstats, rstats, creates);
+ bfa_fcpim_add_iostats(lstats, rstats, deletes);
+ bfa_fcpim_add_iostats(lstats, rstats, create_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, sler_events);
+ bfa_fcpim_add_iostats(lstats, rstats, fw_create);
+ bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
+ bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
+ bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_success);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, io_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
+ bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
+ bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
+ bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
+}
+
+bfa_status_t
+bfa_fcpim_port_iostats(struct bfa_s *bfa,
+ struct bfa_itnim_iostats_s *stats, u8 lp_tag)
+{
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+ struct list_head *qe, *qen;
+ struct bfa_itnim_s *itnim;
+
+ /* accumulate IO stats from itnim */
+ memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
+ list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+ itnim = (struct bfa_itnim_s *) qe;
+ if (itnim->rport->rport_info.lp_tag != lp_tag)
+ continue;
+ bfa_fcpim_add_stats(stats, &(itnim->stats));
+ }
+ return BFA_STATUS_OK;
+}
+
u16
bfa_fcpim_qdepth_get(struct bfa_s *bfa)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
return fcpim->q_depth;
}
@@ -990,8 +1042,7 @@ bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
}
void
-bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
+bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
{
/*
* ITN memory
@@ -1000,15 +1051,16 @@ bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
}
void
-bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_itnim_attach(struct bfa_fcpim_s *fcpim)
{
struct bfa_s *bfa = fcpim->bfa;
+ struct bfa_fcp_mod_s *fcp = fcpim->fcp;
struct bfa_itnim_s *itnim;
int i, j;
INIT_LIST_HEAD(&fcpim->itnim_q);
- itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
+ itnim = (struct bfa_itnim_s *) bfa_mem_kva_curp(fcp);
fcpim->itnim_arr = itnim;
for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
@@ -1030,7 +1082,7 @@ bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
}
- bfa_meminfo_kva(minfo) = (u8 *) itnim;
+ bfa_mem_kva_curp(fcp) = (u8 *) itnim;
}
void
@@ -1043,7 +1095,7 @@ bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
static bfa_boolean_t
bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
{
- struct bfi_itnim_create_req_s *m;
+ struct bfi_itn_create_req_s *m;
itnim->msg_no++;
@@ -1056,8 +1108,8 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
return BFA_FALSE;
}
- bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
- bfa_lpuid(itnim->bfa));
+ bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_CREATE_REQ,
+ bfa_fn_lpu(itnim->bfa));
m->fw_handle = itnim->rport->fw_handle;
m->class = FC_CLASS_3;
m->seq_rec = itnim->seq_rec;
@@ -1067,14 +1119,14 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(itnim->bfa, itnim->reqq);
+ bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
return BFA_TRUE;
}
static bfa_boolean_t
bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
{
- struct bfi_itnim_delete_req_s *m;
+ struct bfi_itn_delete_req_s *m;
/*
* check for room in queue to send request now
@@ -1085,15 +1137,15 @@ bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
return BFA_FALSE;
}
- bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
- bfa_lpuid(itnim->bfa));
+ bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_DELETE_REQ,
+ bfa_fn_lpu(itnim->bfa));
m->fw_handle = itnim->rport->fw_handle;
bfa_stats(itnim, fw_delete);
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(itnim->bfa, itnim->reqq);
+ bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
return BFA_TRUE;
}
@@ -1224,7 +1276,7 @@ bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
static void
bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);
fcpim->del_itn_stats.del_itn_iocomp_aborted +=
itnim->stats.iocomp_aborted;
fcpim->del_itn_stats.del_itn_iocomp_timedout +=
@@ -1250,8 +1302,8 @@ bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
void
bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- union bfi_itnim_i2h_msg_u msg;
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+ union bfi_itn_i2h_msg_u msg;
struct bfa_itnim_s *itnim;
bfa_trc(bfa, m->mhdr.msg_id);
@@ -1259,7 +1311,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
msg.msg = m;
switch (m->mhdr.msg_id) {
- case BFI_ITNIM_I2H_CREATE_RSP:
+ case BFI_ITN_I2H_CREATE_RSP:
itnim = BFA_ITNIM_FROM_TAG(fcpim,
msg.create_rsp->bfa_handle);
WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
@@ -1267,7 +1319,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
break;
- case BFI_ITNIM_I2H_DELETE_RSP:
+ case BFI_ITN_I2H_DELETE_RSP:
itnim = BFA_ITNIM_FROM_TAG(fcpim,
msg.delete_rsp->bfa_handle);
WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
@@ -1275,7 +1327,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
break;
- case BFI_ITNIM_I2H_SLER_EVENT:
+ case BFI_ITN_I2H_SLER_EVENT:
itnim = BFA_ITNIM_FROM_TAG(fcpim,
msg.sler_event->bfa_handle);
bfa_stats(itnim, sler_events);
@@ -1295,9 +1347,11 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
struct bfa_itnim_s *
bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
struct bfa_itnim_s *itnim;
+ bfa_itn_create(bfa, rport, bfa_itnim_isr);
+
itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
WARN_ON(itnim->rport != rport);
@@ -1991,7 +2045,8 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&
m->sns_len) {
sns_len = m->sns_len;
- snsinfo = ioim->iosp->snsinfo;
+ snsinfo = BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
+ ioim->iotag);
}
/*
@@ -2189,12 +2244,12 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
*/
switch (m->cmnd.iodir) {
case FCP_IODIR_READ:
- bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_fn_lpu(ioim->bfa));
bfa_stats(itnim, input_reqs);
ioim->itnim->stats.rd_throughput += fcp_dl;
break;
case FCP_IODIR_WRITE:
- bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_fn_lpu(ioim->bfa));
bfa_stats(itnim, output_reqs);
ioim->itnim->stats.wr_throughput += fcp_dl;
break;
@@ -2202,16 +2257,16 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
bfa_stats(itnim, input_reqs);
bfa_stats(itnim, output_reqs);
default:
- bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
}
if (itnim->seq_rec ||
(scsi_bufflen(cmnd) & (sizeof(u32) - 1)))
- bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(ioim->bfa, ioim->reqq);
+ bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
return BFA_TRUE;
}
@@ -2269,14 +2324,14 @@ bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
else
msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
- bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
+ bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_fn_lpu(ioim->bfa));
m->io_tag = cpu_to_be16(ioim->iotag);
m->abort_tag = ++ioim->abort_tag;
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(ioim->bfa, ioim->reqq);
+ bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
return BFA_TRUE;
}
@@ -2360,46 +2415,32 @@ bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
* Memory allocation and initialization.
*/
void
-bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
{
struct bfa_ioim_s *ioim;
+ struct bfa_fcp_mod_s *fcp = fcpim->fcp;
struct bfa_ioim_sp_s *iosp;
u16 i;
- u8 *snsinfo;
- u32 snsbufsz;
/*
* claim memory first
*/
- ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
+ ioim = (struct bfa_ioim_s *) bfa_mem_kva_curp(fcp);
fcpim->ioim_arr = ioim;
- bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
+ bfa_mem_kva_curp(fcp) = (u8 *) (ioim + fcpim->fcp->num_ioim_reqs);
- iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
+ iosp = (struct bfa_ioim_sp_s *) bfa_mem_kva_curp(fcp);
fcpim->ioim_sp_arr = iosp;
- bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
-
- /*
- * Claim DMA memory for per IO sense data.
- */
- snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
- fcpim->snsbase.pa = bfa_meminfo_dma_phys(minfo);
- bfa_meminfo_dma_phys(minfo) += snsbufsz;
-
- fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
- bfa_meminfo_dma_virt(minfo) += snsbufsz;
- snsinfo = fcpim->snsbase.kva;
- bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
+ bfa_mem_kva_curp(fcp) = (u8 *) (iosp + fcpim->fcp->num_ioim_reqs);
/*
* Initialize ioim free queues
*/
- INIT_LIST_HEAD(&fcpim->ioim_free_q);
INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
INIT_LIST_HEAD(&fcpim->ioim_comp_q);
- for (i = 0; i < fcpim->num_ioim_reqs;
- i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
+ for (i = 0; i < fcpim->fcp->num_ioim_reqs;
+ i++, ioim++, iosp++) {
/*
* initialize IOIM
*/
@@ -2408,22 +2449,19 @@ bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
ioim->bfa = fcpim->bfa;
ioim->fcpim = fcpim;
ioim->iosp = iosp;
- iosp->snsinfo = snsinfo;
INIT_LIST_HEAD(&ioim->sgpg_q);
bfa_reqq_winit(&ioim->iosp->reqq_wait,
bfa_ioim_qresume, ioim);
bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
bfa_ioim_sgpg_alloced, ioim);
bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-
- list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
}
}
void
bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
struct bfa_ioim_s *ioim;
u16 iotag;
@@ -2507,7 +2545,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
void
bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
struct bfa_ioim_s *ioim;
u16 iotag;
@@ -2573,18 +2611,21 @@ struct bfa_ioim_s *
bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
struct bfa_itnim_s *itnim, u16 nsges)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
struct bfa_ioim_s *ioim;
+ struct bfa_iotag_s *iotag = NULL;
/*
* alocate IOIM resource
*/
- bfa_q_deq(&fcpim->ioim_free_q, &ioim);
- if (!ioim) {
+ bfa_q_deq(&fcpim->fcp->iotag_ioim_free_q, &iotag);
+ if (!iotag) {
bfa_stats(itnim, no_iotags);
return NULL;
}
+ ioim = BFA_IOIM_FROM_TAG(fcpim, iotag->tag);
+
ioim->dio = dio;
ioim->itnim = itnim;
ioim->nsges = nsges;
@@ -2601,7 +2642,8 @@ bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
void
bfa_ioim_free(struct bfa_ioim_s *ioim)
{
- struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
+ struct bfa_fcpim_s *fcpim = ioim->fcpim;
+ struct bfa_iotag_s *iotag;
if (ioim->nsgpgs > 0)
bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
@@ -2610,8 +2652,17 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
fcpim->ios_active--;
ioim->iotag &= BFA_IOIM_IOTAG_MASK;
+
+ WARN_ON(!(ioim->iotag <
+ (fcpim->fcp->num_ioim_reqs + fcpim->fcp->num_fwtio_reqs)));
+ iotag = BFA_IOTAG_FROM_TAG(fcpim->fcp, ioim->iotag);
+
+ if (ioim->iotag < fcpim->fcp->num_ioim_reqs)
+ list_add_tail(&iotag->qe, &fcpim->fcp->iotag_ioim_free_q);
+ else
+ list_add_tail(&iotag->qe, &fcpim->fcp->iotag_tio_free_q);
+
list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
}
void
@@ -3021,7 +3072,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)
* build i/o request message next
*/
bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
- bfa_lpuid(tskim->bfa));
+ bfa_fn_lpu(tskim->bfa));
m->tsk_tag = cpu_to_be16(tskim->tsk_tag);
m->itn_fhdl = tskim->itnim->rport->fw_handle;
@@ -3032,7 +3083,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(tskim->bfa, itnim->reqq);
+ bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
return BFA_TRUE;
}
@@ -3056,14 +3107,14 @@ bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
* build i/o request message next
*/
bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
- bfa_lpuid(tskim->bfa));
+ bfa_fn_lpu(tskim->bfa));
m->tsk_tag = cpu_to_be16(tskim->tsk_tag);
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(tskim->bfa, itnim->reqq);
+ bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
return BFA_TRUE;
}
@@ -3129,14 +3180,16 @@ bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
* Memory allocation and initialization.
*/
void
-bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_tskim_attach(struct bfa_fcpim_s *fcpim)
{
struct bfa_tskim_s *tskim;
+ struct bfa_fcp_mod_s *fcp = fcpim->fcp;
u16 i;
INIT_LIST_HEAD(&fcpim->tskim_free_q);
+ INIT_LIST_HEAD(&fcpim->tskim_unused_q);
- tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
+ tskim = (struct bfa_tskim_s *) bfa_mem_kva_curp(fcp);
fcpim->tskim_arr = tskim;
for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
@@ -3155,13 +3208,13 @@ bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
}
- bfa_meminfo_kva(minfo) = (u8 *) tskim;
+ bfa_mem_kva_curp(fcp) = (u8 *) tskim;
}
void
bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
struct bfa_tskim_s *tskim;
u16 tsk_tag = be16_to_cpu(rsp->tsk_tag);
@@ -3188,7 +3241,7 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
struct bfa_tskim_s *
bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
struct bfa_tskim_s *tskim;
bfa_q_deq(&fcpim->tskim_free_q, &tskim);
@@ -3233,3 +3286,214 @@ bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim,
list_add_tail(&tskim->qe, &itnim->tsk_q);
bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
}
+
+void
+bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw)
+{
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+ struct list_head *qe;
+ int i;
+
+ for (i = 0; i < (fcpim->num_tskim_reqs - num_tskim_fw); i++) {
+ bfa_q_deq_tail(&fcpim->tskim_free_q, &qe);
+ list_add_tail(qe, &fcpim->tskim_unused_q);
+ }
+}
+
+/* BFA FCP module - parent module for fcpim */
+
+BFA_MODULE(fcp);
+
+static void
+bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+ struct bfa_s *bfa)
+{
+ struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+ struct bfa_mem_kva_s *fcp_kva = BFA_MEM_FCP_KVA(bfa);
+ struct bfa_mem_dma_s *seg_ptr;
+ u16 nsegs, idx, per_seg_ios, num_io_req;
+ u32 km_len = 0;
+
+ /*
+ * ZERO for num_ioim_reqs and num_fwtio_reqs is allowed config value.
+ * So if the values are non zero, adjust them appropriately.
+ */
+ if (cfg->fwcfg.num_ioim_reqs &&
+ cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
+ cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
+ else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
+ cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
+
+ if (cfg->fwcfg.num_fwtio_reqs > BFA_FWTIO_MAX)
+ cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
+
+ num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+ if (num_io_req > BFA_IO_MAX) {
+ if (cfg->fwcfg.num_ioim_reqs && cfg->fwcfg.num_fwtio_reqs) {
+ cfg->fwcfg.num_ioim_reqs = BFA_IO_MAX/2;
+ cfg->fwcfg.num_fwtio_reqs = BFA_IO_MAX/2;
+ } else if (cfg->fwcfg.num_fwtio_reqs)
+ cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
+ else
+ cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
+ }
+
+ bfa_fcpim_meminfo(cfg, &km_len);
+
+ num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+ km_len += num_io_req * sizeof(struct bfa_iotag_s);
+ km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itn_s);
+
+ /* dma memory */
+ nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
+ per_seg_ios = BFI_MEM_NREQS_SEG(BFI_IOIM_SNSLEN);
+
+ bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
+ if (num_io_req >= per_seg_ios) {
+ num_io_req -= per_seg_ios;
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ per_seg_ios * BFI_IOIM_SNSLEN);
+ } else
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ num_io_req * BFI_IOIM_SNSLEN);
+ }
+
+ /* kva memory */
+ bfa_mem_kva_setup(minfo, fcp_kva, km_len);
+}
+
+static void
+bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+ struct bfa_mem_dma_s *seg_ptr;
+ u16 idx, nsegs, num_io_req;
+
+ fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
+ fcp->num_fwtio_reqs = cfg->fwcfg.num_fwtio_reqs;
+ fcp->num_itns = cfg->fwcfg.num_rports;
+ fcp->bfa = bfa;
+
+ /*
+ * Setup the pool of snsbase addr's, that is passed to fw as
+ * part of bfi_iocfc_cfg_s.
+ */
+ num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+ nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
+
+ bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
+
+ if (!bfa_mem_dma_virt(seg_ptr))
+ break;
+
+ fcp->snsbase[idx].pa = bfa_mem_dma_phys(seg_ptr);
+ fcp->snsbase[idx].kva = bfa_mem_dma_virt(seg_ptr);
+ bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
+ }
+
+ bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
+
+ bfa_iotag_attach(fcp);
+
+ fcp->itn_arr = (struct bfa_itn_s *) bfa_mem_kva_curp(fcp);
+ bfa_mem_kva_curp(fcp) = (u8 *)fcp->itn_arr +
+ (fcp->num_itns * sizeof(struct bfa_itn_s));
+ memset(fcp->itn_arr, 0,
+ (fcp->num_itns * sizeof(struct bfa_itn_s)));
+}
+
+static void
+bfa_fcp_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+
+ /* Enqueue unused ioim resources to free_q */
+ list_splice_tail_init(&fcp->iotag_unused_q, &fcp->iotag_ioim_free_q);
+
+ bfa_fcpim_iocdisable(fcp);
+}
+
+void
+bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw)
+{
+ struct bfa_fcp_mod_s *mod = BFA_FCP_MOD(bfa);
+ struct list_head *qe;
+ int i;
+
+ for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
+ bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
+ list_add_tail(qe, &mod->iotag_unused_q);
+ }
+}
+
+void
+bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
+ void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m))
+{
+ struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+ struct bfa_itn_s *itn;
+
+ itn = BFA_ITN_FROM_TAG(fcp, rport->rport_tag);
+ itn->isr = isr;
+}
+
+/*
+ * Itn interrupt processing.
+ */
+void
+bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+ union bfi_itn_i2h_msg_u msg;
+ struct bfa_itn_s *itn;
+
+ msg.msg = m;
+ itn = BFA_ITN_FROM_TAG(fcp, msg.create_rsp->bfa_handle);
+
+ if (itn->isr)
+ itn->isr(bfa, m);
+ else
+ WARN_ON(1);
+}
+
+void
+bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
+{
+ struct bfa_iotag_s *iotag;
+ u16 num_io_req, i;
+
+ iotag = (struct bfa_iotag_s *) bfa_mem_kva_curp(fcp);
+ fcp->iotag_arr = iotag;
+
+ INIT_LIST_HEAD(&fcp->iotag_ioim_free_q);
+ INIT_LIST_HEAD(&fcp->iotag_tio_free_q);
+ INIT_LIST_HEAD(&fcp->iotag_unused_q);
+
+ num_io_req = fcp->num_ioim_reqs + fcp->num_fwtio_reqs;
+ for (i = 0; i < num_io_req; i++, iotag++) {
+ memset(iotag, 0, sizeof(struct bfa_iotag_s));
+ iotag->tag = i;
+ if (i < fcp->num_ioim_reqs)
+ list_add_tail(&iotag->qe, &fcp->iotag_ioim_free_q);
+ else
+ list_add_tail(&iotag->qe, &fcp->iotag_tio_free_q);
+ }
+
+ bfa_mem_kva_curp(fcp) = (u8 *) iotag;
+}
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index 1e38dade8423..57b695ad4ee5 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -24,6 +24,34 @@
#include "bfa_defs_svc.h"
#include "bfa_cs.h"
+/* FCP module related definitions */
+#define BFA_IO_MAX BFI_IO_MAX
+#define BFA_FWTIO_MAX 2000
+
+struct bfa_fcp_mod_s;
+struct bfa_iotag_s {
+ struct list_head qe; /* queue element */
+ u16 tag; /* FW IO tag */
+};
+
+struct bfa_itn_s {
+ bfa_isr_func_t isr;
+};
+
+void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
+ void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m));
+void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m);
+void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp);
+void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw);
+
+#define BFA_FCP_MOD(_hal) (&(_hal)->modules.fcp_mod)
+#define BFA_MEM_FCP_KVA(__bfa) (&(BFA_FCP_MOD(__bfa)->kva_seg))
+#define BFA_IOTAG_FROM_TAG(_fcp, _tag) \
+ (&(_fcp)->iotag_arr[(_tag & BFA_IOIM_IOTAG_MASK)])
+#define BFA_ITN_FROM_TAG(_fcp, _tag) \
+ ((_fcp)->itn_arr + ((_tag) & ((_fcp)->num_itns - 1)))
+#define BFA_SNSINFO_FROM_TAG(_fcp, _tag) \
+ bfa_mem_get_dmabuf_kva(_fcp, _tag, BFI_IOIM_SNSLEN)
#define BFA_ITNIM_MIN 32
#define BFA_ITNIM_MAX 1024
@@ -75,25 +103,24 @@ struct bfad_tskim_s;
typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
-struct bfa_fcpim_mod_s {
+struct bfa_fcpim_s {
struct bfa_s *bfa;
+ struct bfa_fcp_mod_s *fcp;
struct bfa_itnim_s *itnim_arr;
struct bfa_ioim_s *ioim_arr;
struct bfa_ioim_sp_s *ioim_sp_arr;
struct bfa_tskim_s *tskim_arr;
- struct bfa_dma_s snsbase;
int num_itnims;
- int num_ioim_reqs;
int num_tskim_reqs;
u32 path_tov;
u16 q_depth;
u8 reqq; /* Request queue to be used */
u8 rsvd;
struct list_head itnim_q; /* queue of active itnim */
- struct list_head ioim_free_q; /* free IO resources */
struct list_head ioim_resfree_q; /* IOs waiting for f/w */
struct list_head ioim_comp_q; /* IO global comp Q */
struct list_head tskim_free_q;
+ struct list_head tskim_unused_q; /* Unused tskim Q */
u32 ios_active; /* current active IOs */
u32 delay_comp;
struct bfa_fcpim_del_itn_stats_s del_itn_stats;
@@ -104,6 +131,25 @@ struct bfa_fcpim_mod_s {
bfa_fcpim_profile_t profile_start;
};
+/* Max FCP dma segs required */
+#define BFA_FCP_DMA_SEGS BFI_IOIM_SNSBUF_SEGS
+
+struct bfa_fcp_mod_s {
+ struct bfa_s *bfa;
+ struct list_head iotag_ioim_free_q; /* free IO resources */
+ struct list_head iotag_tio_free_q; /* free IO resources */
+ struct list_head iotag_unused_q; /* unused IO resources*/
+ struct bfa_iotag_s *iotag_arr;
+ struct bfa_itn_s *itn_arr;
+ int num_ioim_reqs;
+ int num_fwtio_reqs;
+ int num_itns;
+ struct bfa_dma_s snsbase[BFA_FCP_DMA_SEGS];
+ struct bfa_fcpim_s fcpim;
+ struct bfa_mem_dma_s dma_seg[BFA_FCP_DMA_SEGS];
+ struct bfa_mem_kva_s kva_seg;
+};
+
/*
* BFA IO (initiator mode)
*/
@@ -111,7 +157,7 @@ struct bfa_ioim_s {
struct list_head qe; /* queue elememt */
bfa_sm_t sm; /* BFA ioim state machine */
struct bfa_s *bfa; /* BFA module */
- struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
+ struct bfa_fcpim_s *fcpim; /* parent fcpim module */
struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
struct bfad_ioim_s *dio; /* driver IO handle */
u16 iotag; /* FWI IO tag */
@@ -129,7 +175,6 @@ struct bfa_ioim_s {
struct bfa_ioim_sp_s {
struct bfi_msg_s comp_rspmsg; /* IO comp f/w response */
- u8 *snsinfo; /* sense info for this IO */
struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */
struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
bfa_boolean_t abort_explicit; /* aborted by OS */
@@ -143,7 +188,7 @@ struct bfa_tskim_s {
struct list_head qe;
bfa_sm_t sm;
struct bfa_s *bfa; /* BFA module */
- struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
+ struct bfa_fcpim_s *fcpim; /* parent fcpim module */
struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */
bfa_boolean_t notify; /* notify itnim on TM comp */
@@ -182,13 +227,13 @@ struct bfa_itnim_s {
struct bfa_wc_s wc; /* waiting counter */
struct bfa_timer_s timer; /* pending IO TOV */
struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
- struct bfa_fcpim_mod_s *fcpim; /* fcpim module */
+ struct bfa_fcpim_s *fcpim; /* fcpim module */
struct bfa_itnim_iostats_s stats;
struct bfa_itnim_ioprofile_s ioprofile;
};
#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
-#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_FCPIM(_hal) (&(_hal)->modules.fcp_mod.fcpim)
#define BFA_IOIM_TAG_2_ID(_iotag) ((_iotag) & BFA_IOIM_IOTAG_MASK)
#define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \
(&fcpim->ioim_arr[(_iotag & BFA_IOIM_IOTAG_MASK)])
@@ -196,9 +241,9 @@ struct bfa_itnim_s {
(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
#define bfa_io_profile_start_time(_bfa) \
- (_bfa->modules.fcpim_mod.io_profile_start_time)
+ ((_bfa)->modules.fcp_mod.fcpim.io_profile_start_time)
#define bfa_fcpim_get_io_profile(_bfa) \
- (_bfa->modules.fcpim_mod.io_profile)
+ ((_bfa)->modules.fcp_mod.fcpim.io_profile)
#define bfa_ioim_update_iotag(__ioim) do { \
uint16_t k = (__ioim)->iotag >> BFA_IOIM_RETRY_TAG_OFFSET; \
k++; (__ioim)->iotag &= BFA_IOIM_IOTAG_MASK; \
@@ -217,8 +262,7 @@ bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
/*
* function prototypes
*/
-void bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
- struct bfa_meminfo_s *minfo);
+void bfa_ioim_attach(struct bfa_fcpim_s *fcpim);
void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
void bfa_ioim_good_comp_isr(struct bfa_s *bfa,
struct bfi_msg_s *msg);
@@ -228,18 +272,15 @@ void bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
void bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
void bfa_ioim_tov(struct bfa_ioim_s *ioim);
-void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
- struct bfa_meminfo_s *minfo);
+void bfa_tskim_attach(struct bfa_fcpim_s *fcpim);
void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
void bfa_tskim_iodone(struct bfa_tskim_s *tskim);
void bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
void bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
+void bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw);
-void bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len);
-void bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
- struct bfa_meminfo_s *minfo);
-void bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
+void bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len);
+void bfa_itnim_attach(struct bfa_fcpim_s *fcpim);
void bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
void bfa_itnim_iodone(struct bfa_itnim_s *itnim);
@@ -252,13 +293,17 @@ bfa_boolean_t bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
u16 bfa_fcpim_path_tov_get(struct bfa_s *bfa);
u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
+ struct bfa_itnim_iostats_s *stats, u8 lp_tag);
+void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
+ struct bfa_itnim_iostats_s *itnim_stats);
#define bfa_fcpim_ioredirect_enabled(__bfa) \
- (((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
+ (((struct bfa_fcpim_s *)(BFA_FCPIM(__bfa)))->ioredirect)
#define bfa_fcpim_get_next_reqq(__bfa, __qid) \
{ \
- struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa); \
+ struct bfa_fcpim_s *__fcpim = BFA_FCPIM(__bfa); \
__fcpim->reqq++; \
__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1); \
*(__qid) = __fcpim->reqq; \
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index 9b43ca4b6778..a9b22bc48bc3 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -92,25 +92,49 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
void
bfa_fcs_init(struct bfa_fcs_s *fcs)
{
- int i, npbc_vports;
+ int i;
struct bfa_fcs_mod_s *mod;
- struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
mod = &fcs_modules[i];
if (mod->modinit)
mod->modinit(fcs);
}
+}
+
+/*
+ * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
+ * with values learned during bfa_init firmware GETATTR REQ.
+ */
+void
+bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)
+{
+ struct bfa_fcs_fabric_s *fabric = &fcs->fabric;
+ struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+ struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc;
+
+ port_cfg->nwwn = ioc->attr->nwwn;
+ port_cfg->pwwn = ioc->attr->pwwn;
+}
+
+/*
+ * fcs pbc vport initialization
+ */
+void
+bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs)
+{
+ int i, npbc_vports;
+ struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
+
/* Initialize pbc vports */
if (!fcs->min_cfg) {
npbc_vports =
- bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
+ bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
for (i = 0; i < npbc_vports; i++)
bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
}
}
-
/*
* brief
* FCS driver details initialization.
@@ -168,11 +192,14 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)
#define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */
#define bfa_fcs_fabric_set_opertype(__fabric) do { \
- if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \
- == BFA_PORT_TOPOLOGY_P2P) \
+ if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \
+ == BFA_PORT_TOPOLOGY_P2P) { \
+ if (fabric->fab_type == BFA_FCS_FABRIC_SWITCHED) \
(__fabric)->oper_type = BFA_PORT_TYPE_NPORT; \
else \
- (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \
+ (__fabric)->oper_type = BFA_PORT_TYPE_P2P; \
+ } else \
+ (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \
} while (0)
/*
@@ -196,6 +223,9 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
u32 rsp_len,
u32 resid_len,
struct fchs_s *rspfchs);
+static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
+static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
+ struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
@@ -269,8 +299,8 @@ bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
break;
case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
- bfa_wc_down(&fabric->fcs->wc);
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_fcs_fabric_delete(fabric);
break;
default:
@@ -322,7 +352,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_CONT_OP:
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit);
+ fabric->bb_credit,
+ bfa_fcs_fabric_oper_bbscn(fabric));
fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
if (fabric->auth_reqd && fabric->is_auth) {
@@ -350,7 +381,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_NO_FABRIC:
fabric->fab_type = BFA_FCS_FABRIC_N2N;
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit);
+ fabric->bb_credit,
+ bfa_fcs_fabric_oper_bbscn(fabric));
bfa_fcs_fabric_notify_online(fabric);
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
break;
@@ -518,7 +550,11 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_NO_FABRIC:
bfa_trc(fabric->fcs, fabric->bb_credit);
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit);
+ fabric->bb_credit,
+ bfa_fcs_fabric_oper_bbscn(fabric));
+ break;
+
+ case BFA_FCS_FABRIC_SM_RETRY_OP:
break;
default:
@@ -764,6 +800,10 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
case BFA_STATUS_FABRIC_RJT:
fabric->stats.flogi_rejects++;
+ if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
+ fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
+ fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;
+
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
return;
@@ -793,6 +833,7 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
*/
fabric->bport.port_topo.pn2n.rem_port_wwn =
fabric->lps->pr_pwwn;
+ fabric->fab_type = BFA_FCS_FABRIC_N2N;
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
}
@@ -808,13 +849,17 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
{
struct bfa_s *bfa = fabric->fcs->bfa;
struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
- u8 alpa = 0;
+ u8 alpa = 0, bb_scn = 0;
if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
alpa = bfa_fcport_get_myalpa(bfa);
+ if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
+ (!fabric->fcs->bbscn_flogi_rjt))
+ bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
+
bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
- pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
+ pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);
fabric->stats.flogi_sent++;
}
@@ -873,6 +918,40 @@ bfa_fcs_fabric_delay(void *cbarg)
}
/*
+ * Computes operating BB_SCN value
+ */
+static u8
+bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
+{
+ u8 pr_bbscn = fabric->lps->pr_bbscn;
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
+
+ if (!(fcport->cfg.bb_scn_state && pr_bbscn))
+ return 0;
+
+ /* return max of local/remote bb_scn values */
+ return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
+ pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
+}
+
+/*
+ * Check if BB_SCN can be enabled.
+ */
+static bfa_boolean_t
+bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
+
+ if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
+ fcport->cfg.bb_scn_state &&
+ !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
+ !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
+ return BFA_TRUE;
+ else
+ return BFA_FALSE;
+}
+
+/*
* Delete all vports and wait for vport delete completions.
*/
static void
@@ -989,6 +1068,7 @@ void
bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
{
bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
}
@@ -1192,6 +1272,7 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
}
fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
+ fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
@@ -1224,9 +1305,10 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
n2n_port->reply_oxid, pcfg->pwwn,
pcfg->nwwn,
bfa_fcport_get_maxfrsize(bfa),
- bfa_fcport_get_rx_bbcredit(bfa));
+ bfa_fcport_get_rx_bbcredit(bfa),
+ bfa_fcs_fabric_oper_bbscn(fabric));
- bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
+ bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,
BFA_FALSE, FC_CLASS_3,
reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
FC_MAX_PDUSZ, 0);
@@ -1298,6 +1380,45 @@ bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
}
/*
+ * Return the list of local logical ports present in the given VF.
+ *
+ * @param[in] vf vf for which logical ports are returned
+ * @param[out] lpwwn returned logical port wwn list
+ * @param[in,out] nlports in:size of lpwwn list;
+ * out:total elements present,
+ * actual elements returned is limited by the size
+ */
+void
+bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
+{
+ struct list_head *qe;
+ struct bfa_fcs_vport_s *vport;
+ int i = 0;
+ struct bfa_fcs_s *fcs;
+
+ if (vf == NULL || lpwwn == NULL || *nlports == 0)
+ return;
+
+ fcs = vf->fcs;
+
+ bfa_trc(fcs, vf->vf_id);
+ bfa_trc(fcs, (uint32_t) *nlports);
+
+ lpwwn[i++] = vf->bport.port_cfg.pwwn;
+
+ list_for_each(qe, &vf->vport_q) {
+ if (i >= *nlports)
+ break;
+
+ vport = (struct bfa_fcs_vport_s *) qe;
+ lpwwn[i++] = vport->lport.port_cfg.pwwn;
+ }
+
+ bfa_trc(fcs, i);
+ *nlports = i;
+}
+
+/*
* BFA FCS PPORT ( physical port)
*/
static void
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index 61cdce4bd913..a5f1faf335a7 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -254,6 +254,9 @@ struct bfa_fcs_fabric_s;
#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48
#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16
+/* bb_scn value in 2^bb_scn */
+#define BFA_FCS_PORT_DEF_BB_SCN 3
+
/*
* Get FC port ID for a logical port.
*/
@@ -379,6 +382,7 @@ void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport);
#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 90 /* in secs */
#define BFA_FCS_RPORT_MAX_RETRIES (5)
@@ -420,6 +424,7 @@ struct bfa_fcs_rport_s {
enum fc_cos fc_cos; /* FC classes of service supp */
bfa_boolean_t cisc; /* CISC capable device */
bfa_boolean_t prlo; /* processing prlo or LOGO */
+ bfa_boolean_t plogi_pending; /* Rx Plogi Pending */
wwn_t pwwn; /* port wwn of rport */
wwn_t nwwn; /* node wwn of rport */
struct bfa_rport_symname_s psym_name; /* port symbolic name */
@@ -447,6 +452,8 @@ bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
/*
* bfa fcs rport API functions
*/
+void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+ struct bfa_rport_attr_s *attr);
struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
wwn_t rpwwn);
struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
@@ -591,10 +598,21 @@ void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
struct fchs_s *fchs, u16 len);
-#define BFA_FCS_FDMI_SUPORTED_SPEEDS (FDMI_TRANS_SPEED_1G | \
- FDMI_TRANS_SPEED_2G | \
- FDMI_TRANS_SPEED_4G | \
- FDMI_TRANS_SPEED_8G)
+#define BFA_FCS_FDMI_SUPP_SPEEDS_4G (FDMI_TRANS_SPEED_1G | \
+ FDMI_TRANS_SPEED_2G | \
+ FDMI_TRANS_SPEED_4G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_8G (FDMI_TRANS_SPEED_1G | \
+ FDMI_TRANS_SPEED_2G | \
+ FDMI_TRANS_SPEED_4G | \
+ FDMI_TRANS_SPEED_8G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_16G (FDMI_TRANS_SPEED_2G | \
+ FDMI_TRANS_SPEED_4G | \
+ FDMI_TRANS_SPEED_8G | \
+ FDMI_TRANS_SPEED_16G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_10G FDMI_TRANS_SPEED_10G
/*
* HBA Attribute Block : BFA internal representation. Note : Some variable
@@ -649,6 +667,8 @@ struct bfa_fcs_s {
struct bfa_trc_mod_s *trcmod; /* tracing module */
bfa_boolean_t vf_enabled; /* VF mode is enabled */
bfa_boolean_t fdmi_enabled; /* FDMI is enabled */
+ bfa_boolean_t bbscn_enabled; /* Driver Config Parameter */
+ bfa_boolean_t bbscn_flogi_rjt;/* FLOGI reject due to BB_SCN */
bfa_boolean_t min_cfg; /* min cfg enabled/disabled */
u16 port_vfid; /* port default VF ID */
struct bfa_fcs_driver_info_s driver_info;
@@ -715,6 +735,8 @@ void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
struct bfad_s *bfad,
bfa_boolean_t min_cfg);
void bfa_fcs_init(struct bfa_fcs_s *fcs);
+void bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs);
+void bfa_fcs_update_cfg(struct bfa_fcs_s *fcs);
void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
struct bfa_fcs_driver_info_s *driver_info);
void bfa_fcs_exit(struct bfa_fcs_s *fcs);
@@ -723,6 +745,7 @@ void bfa_fcs_exit(struct bfa_fcs_s *fcs);
* bfa fcs vf public functions
*/
bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
+void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
/*
* fabric protected interface functions
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index e7b49f4cb51f..29b4108be269 100644
--- a/drivers/scsi/bfa/bfa_fcs_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -54,6 +54,7 @@ enum bfa_fcs_itnim_event {
BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */
BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */
+ BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
};
static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
@@ -178,6 +179,10 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
BFA_FCS_RETRY_TIMEOUT);
break;
+ case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:
+ bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+ break;
+
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_fcxp_discard(itnim->fcxp);
@@ -447,6 +452,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
itnim->rport->scsi_function =
BFA_RPORT_INITIATOR;
itnim->stats.prli_rsp_acc++;
+ itnim->stats.initiator++;
bfa_sm_send_event(itnim,
BFA_FCS_ITNIM_SM_RSP_OK);
return;
@@ -472,6 +478,10 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
itnim->stats.prli_rsp_rjt++;
+ if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
+ bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);
+ return;
+ }
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
}
}
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 1d6be8c14473..f8251a91ba91 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -74,6 +74,7 @@ enum bfa_fcs_lport_event {
BFA_FCS_PORT_SM_OFFLINE = 3,
BFA_FCS_PORT_SM_DELETE = 4,
BFA_FCS_PORT_SM_DELRPORT = 5,
+ BFA_FCS_PORT_SM_STOP = 6,
};
static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
@@ -86,6 +87,8 @@ static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
enum bfa_fcs_lport_event event);
static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
enum bfa_fcs_lport_event event);
+static void bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event);
static void
bfa_fcs_lport_sm_uninit(
@@ -123,6 +126,12 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
bfa_fcs_lport_deleted(port);
break;
+ case BFA_FCS_PORT_SM_STOP:
+ /* If vport - send completion call back */
+ if (port->vport)
+ bfa_fcs_vport_stop_comp(port->vport);
+ break;
+
case BFA_FCS_PORT_SM_OFFLINE:
break;
@@ -148,6 +157,23 @@ bfa_fcs_lport_sm_online(
bfa_fcs_lport_offline_actions(port);
break;
+ case BFA_FCS_PORT_SM_STOP:
+ __port_action[port->fabric->fab_type].offline(port);
+
+ if (port->num_rports == 0) {
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+ /* If vport - send completion call back */
+ if (port->vport)
+ bfa_fcs_vport_stop_comp(port->vport);
+ } else {
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+ list_for_each_safe(qe, qen, &port->rport_q) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+ }
+ }
+ break;
+
case BFA_FCS_PORT_SM_DELETE:
__port_action[port->fabric->fab_type].offline(port);
@@ -189,6 +215,21 @@ bfa_fcs_lport_sm_offline(
bfa_fcs_lport_online_actions(port);
break;
+ case BFA_FCS_PORT_SM_STOP:
+ if (port->num_rports == 0) {
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+ /* If vport - send completion call back */
+ if (port->vport)
+ bfa_fcs_vport_stop_comp(port->vport);
+ } else {
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+ list_for_each_safe(qe, qen, &port->rport_q) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+ }
+ }
+ break;
+
case BFA_FCS_PORT_SM_DELETE:
if (port->num_rports == 0) {
bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
@@ -212,6 +253,28 @@ bfa_fcs_lport_sm_offline(
}
static void
+bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event)
+{
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_PORT_SM_DELRPORT:
+ if (port->num_rports == 0) {
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+ /* If vport - send completion call back */
+ if (port->vport)
+ bfa_fcs_vport_stop_comp(port->vport);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
bfa_fcs_lport_sm_deleting(
struct bfa_fcs_lport_s *port,
enum bfa_fcs_lport_event event)
@@ -265,6 +328,40 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
}
/*
+ * Send a FCCT Reject
+ */
+static void
+bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl)
+{
+ struct fchs_s fchs;
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_rport_s *bfa_rport = NULL;
+ int len;
+ struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1);
+ struct ct_hdr_s *ct_hdr;
+
+ bfa_trc(port->fcs, rx_fchs->d_id);
+ bfa_trc(port->fcs, rx_fchs->s_id);
+
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp)
+ return;
+
+ ct_hdr = bfa_fcxp_get_reqbuf(fcxp);
+ ct_hdr->gs_type = rx_cthdr->gs_type;
+ ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type;
+
+ len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id,
+ bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, reason_code, reason_code_expl);
+
+ bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+ BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
+}
+
+/*
* Process incoming plogi from a remote port.
*/
static void
@@ -647,6 +744,16 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
bfa_fcs_lport_abts_acc(lport, fchs);
return;
}
+
+ if (fchs->type == FC_TYPE_SERVICES) {
+ /*
+ * Unhandled FC-GS frames. Send a FC-CT Reject
+ */
+ bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP,
+ CT_NS_EXP_NOADDITIONAL);
+ return;
+ }
+
/*
* look for a matching remote port ID
*/
@@ -835,8 +942,8 @@ bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
lport->fcs = fcs;
lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
lport->vport = vport;
- lport->lp_tag = (vport) ? vport->lps->lp_tag :
- lport->fabric->lps->lp_tag;
+ lport->lp_tag = (vport) ? vport->lps->bfa_tag :
+ lport->fabric->lps->bfa_tag;
INIT_LIST_HEAD(&lport->rport_q);
lport->num_rports = 0;
@@ -1074,6 +1181,8 @@ static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
struct bfa_fcs_fdmi_port_attr_s *port_attr);
+u32 bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed);
+
/*
* fcs_fdmi_sm FCS FDMI state machine
*/
@@ -1672,7 +1781,7 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
memcpy(attr->value, fcs_hba_attr->driver_version, templen);
templen = fc_roundup(templen, sizeof(u32));
curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
- len += templen;;
+ len += templen;
count++;
attr->len = cpu_to_be16(templen + sizeof(attr->type) +
sizeof(templen));
@@ -2160,12 +2269,36 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
/*
* Supported Speeds
*/
- port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
+ switch (pport_attr.speed_supported) {
+ case BFA_PORT_SPEED_16GBPS:
+ port_attr->supp_speed =
+ cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
+ break;
+
+ case BFA_PORT_SPEED_10GBPS:
+ port_attr->supp_speed =
+ cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
+ break;
+
+ case BFA_PORT_SPEED_8GBPS:
+ port_attr->supp_speed =
+ cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
+ break;
+
+ case BFA_PORT_SPEED_4GBPS:
+ port_attr->supp_speed =
+ cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, pport_attr.speed_supported);
+ }
/*
* Current Speed
*/
- port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
+ port_attr->curr_speed = cpu_to_be32(
+ bfa_fcs_fdmi_convert_speed(pport_attr.speed));
/*
* Max PDU Size.
@@ -2186,6 +2319,41 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
}
+/*
+ * Convert BFA speed to FDMI format.
+ */
+u32
+bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
+{
+ u32 ret;
+
+ switch (pport_speed) {
+ case BFA_PORT_SPEED_1GBPS:
+ case BFA_PORT_SPEED_2GBPS:
+ ret = pport_speed;
+ break;
+
+ case BFA_PORT_SPEED_4GBPS:
+ ret = FDMI_TRANS_SPEED_4G;
+ break;
+
+ case BFA_PORT_SPEED_8GBPS:
+ ret = FDMI_TRANS_SPEED_8G;
+ break;
+
+ case BFA_PORT_SPEED_10GBPS:
+ ret = FDMI_TRANS_SPEED_10G;
+ break;
+
+ case BFA_PORT_SPEED_16GBPS:
+ ret = FDMI_TRANS_SPEED_16G;
+ break;
+
+ default:
+ ret = FDMI_TRANS_SPEED_UNKNOWN;
+ }
+ return ret;
+}
void
bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
@@ -2829,7 +2997,8 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_hton3b(FC_MGMT_SERVER),
bfa_fcs_lport_get_fcid(port), 0,
port->port_cfg.pwwn, port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
+ bfa_fcport_get_maxfrsize(port->fcs->bfa),
+ bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
FC_CLASS_3, len, &fchs,
@@ -3573,7 +3742,7 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->pid);
-fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp) {
port->stats.ns_plogi_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
@@ -3586,7 +3755,8 @@ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
bfa_hton3b(FC_NAME_SERVER),
bfa_fcs_lport_get_fcid(port), 0,
port->port_cfg.pwwn, port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
+ bfa_fcport_get_maxfrsize(port->fcs->bfa),
+ bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
FC_CLASS_3, len, &fchs,
@@ -4762,8 +4932,8 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
while (qe != qh) {
rport = (struct bfa_fcs_rport_s *) qe;
if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
- (bfa_fcs_rport_get_state(rport) ==
- BFA_RPORT_OFFLINE)) {
+ (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
+ (rport->scsi_function != BFA_RPORT_TARGET)) {
qe = bfa_q_next(qe);
continue;
}
@@ -4776,17 +4946,15 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
bfa_fcport_get_ratelim_speed(port->fcs->bfa);
}
- if ((rport_speed == BFA_PORT_SPEED_8GBPS) ||
- (rport_speed > port_speed)) {
+ if (rport_speed > max_speed)
max_speed = rport_speed;
- break;
- } else if (rport_speed > max_speed) {
- max_speed = rport_speed;
- }
qe = bfa_q_next(qe);
}
+ if (max_speed > port_speed)
+ max_speed = port_speed;
+
bfa_trc(fcs, max_speed);
return max_speed;
}
@@ -4918,6 +5086,7 @@ enum bfa_fcs_vport_event {
BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
+ BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
};
static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
@@ -4930,6 +5099,8 @@ static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
enum bfa_fcs_vport_event event);
static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
enum bfa_fcs_vport_event event);
static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
@@ -4940,6 +5111,10 @@ static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
enum bfa_fcs_vport_event event);
static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
static struct bfa_sm_table_s vport_sm_table[] = {
{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
@@ -4947,6 +5122,7 @@ static struct bfa_sm_table_s vport_sm_table[] = {
{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
+ {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
@@ -5042,6 +5218,11 @@ bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
bfa_fcs_vport_do_fdisc(vport);
break;
+ case BFA_FCS_VPORT_SM_STOP:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+ break;
+
case BFA_FCS_VPORT_SM_OFFLINE:
/*
* This can happen if the vport couldn't be initialzied
@@ -5070,9 +5251,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
switch (event) {
case BFA_FCS_VPORT_SM_DELETE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
- bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
- bfa_fcs_lport_delete(&vport->lport);
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
break;
case BFA_FCS_VPORT_SM_OFFLINE:
@@ -5140,6 +5319,41 @@ bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
}
/*
+ * FDISC is in progress and we got a vport delete request -
+ * this is a wait state while we wait for fdisc response and
+ * we will transition to the appropriate state - on rsp status.
+ */
+static void
+bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_RSP_OK:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ case BFA_FCS_VPORT_SM_DELETE:
+ break;
+
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ case BFA_FCS_VPORT_SM_RSP_ERROR:
+ case BFA_FCS_VPORT_SM_RSP_FAILED:
+ case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/*
* Vport is online (FDISC is complete).
*/
static void
@@ -5155,6 +5369,11 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
bfa_fcs_lport_delete(&vport->lport);
break;
+ case BFA_FCS_VPORT_SM_STOP:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
+ bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+ break;
+
case BFA_FCS_VPORT_SM_OFFLINE:
bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
@@ -5167,6 +5386,32 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
}
/*
+ * Vport is being stopped - awaiting lport stop completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_STOPCOMP:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
+ bfa_fcs_vport_do_logo(vport);
+ break;
+
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/*
* Vport is being deleted - awaiting lport delete completion to send
* LOGO to fabric.
*/
@@ -5236,6 +5481,10 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
bfa_fcs_vport_free(vport);
break;
+ case BFA_FCS_VPORT_SM_STOPCOMP:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+ break;
+
case BFA_FCS_VPORT_SM_DELETE:
break;
@@ -5245,6 +5494,34 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
}
/*
+ * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
+ /*
+ * !!! fall through !!!
+ */
+
+ case BFA_FCS_VPORT_SM_RSP_OK:
+ case BFA_FCS_VPORT_SM_RSP_ERROR:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/*
* LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
* is done.
*/
@@ -5391,7 +5668,10 @@ void
bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
{
vport->vport_stats.fab_online++;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+ if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+ else
+ vport->vport_stats.fab_no_npiv++;
}
/*
@@ -5422,6 +5702,15 @@ bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
}
/*
+ * Stop completion callback from associated lport
+ */
+void
+bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
+{
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
+}
+
+/*
* Delete completion callback from associated lport
*/
void
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index caaee6f06937..2c514458a6b4 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -262,6 +262,7 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_PLOGI_RCVD:
+ case RPSM_EVENT_PLOGI_COMP:
case RPSM_EVENT_SCN:
/*
* Ignore, SCN is possibly online notification.
@@ -470,6 +471,7 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_PRLO_RCVD:
+ case RPSM_EVENT_PLOGI_COMP:
break;
case RPSM_EVENT_LOGO_RCVD:
@@ -484,9 +486,9 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_PLOGI_RCVD:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+ rport->plogi_pending = BFA_TRUE;
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
- bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
case RPSM_EVENT_DELETE:
@@ -891,6 +893,18 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_HCB_OFFLINE:
+ if (bfa_fcs_lport_is_online(rport->port) &&
+ (rport->plogi_pending)) {
+ rport->plogi_pending = BFA_FALSE;
+ bfa_sm_set_state(rport,
+ bfa_fcs_rport_sm_plogiacc_sending);
+ bfa_fcs_rport_send_plogiacc(rport, NULL);
+ break;
+ }
+ /*
+ * !! fall through !!
+ */
+
case RPSM_EVENT_ADDRESS_CHANGE:
if (bfa_fcs_lport_is_online(rport->port)) {
if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
@@ -921,6 +935,8 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_SCN:
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
+ case RPSM_EVENT_PLOGI_RCVD:
+ case RPSM_EVENT_LOGO_IMP:
/*
* Ignore, already offline.
*/
@@ -957,10 +973,18 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
*/
if (bfa_fcs_lport_is_online(rport->port) &&
(!BFA_FCS_PID_IS_WKA(rport->pid))) {
- bfa_sm_set_state(rport,
- bfa_fcs_rport_sm_nsdisc_sending);
- rport->ns_retries = 0;
- bfa_fcs_rport_send_nsdisc(rport, NULL);
+ if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+ bfa_sm_set_state(rport,
+ bfa_fcs_rport_sm_nsdisc_sending);
+ rport->ns_retries = 0;
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
+ } else {
+ /* For N2N Direct Attach, try to re-login */
+ bfa_sm_set_state(rport,
+ bfa_fcs_rport_sm_plogi_sending);
+ rport->plogi_retries = 0;
+ bfa_fcs_rport_send_plogi(rport, NULL);
+ }
} else {
/*
* if it is not a well known address, reset the
@@ -1356,7 +1380,8 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
bfa_fcs_lport_get_fcid(port), 0,
port->port_cfg.pwwn, port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
+ bfa_fcport_get_maxfrsize(port->fcs->bfa),
+ bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
@@ -1476,7 +1501,8 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
rport->pid, bfa_fcs_lport_get_fcid(port),
rport->reply_oxid, port->port_cfg.pwwn,
port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
+ bfa_fcport_get_maxfrsize(port->fcs->bfa),
+ bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
@@ -2024,6 +2050,11 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
rport->stats.onlines++;
+ if ((!rport->pid) || (!rport->pwwn)) {
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_sm_fault(rport->fcs, rport->pid);
+ }
+
if (bfa_fcs_lport_is_initiator(port)) {
bfa_fcs_itnim_rport_online(rport->itnim);
if (!BFA_FCS_PID_IS_WKA(rport->pid))
@@ -2047,6 +2078,7 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
char rpwwn_buf[BFA_STRING_32];
rport->stats.offlines++;
+ rport->plogi_pending = BFA_FALSE;
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
wwn2str(rpwwn_buf, rport->pwwn);
@@ -2120,7 +2152,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
- port->fabric->bb_credit);
+ port->fabric->bb_credit, 0);
}
}
@@ -2233,22 +2265,6 @@ bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
}
-static int
-wwn_compare(wwn_t wwn1, wwn_t wwn2)
-{
- u8 *b1 = (u8 *) &wwn1;
- u8 *b2 = (u8 *) &wwn2;
- int i;
-
- for (i = 0; i < sizeof(wwn_t); i++) {
- if (b1[i] < b2[i])
- return -1;
- if (b1[i] > b2[i])
- return 1;
- }
- return 0;
-}
-
/*
* Called by bport/vport to handle PLOGI received from an existing
* remote port.
@@ -2266,19 +2282,8 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
rport->reply_oxid = rx_fchs->ox_id;
bfa_trc(rport->fcs, rport->reply_oxid);
- /*
- * In Switched fabric topology,
- * PLOGI to each other. If our pwwn is smaller, ignore it,
- * if it is not a well known address.
- * If the link topology is N2N,
- * this Plogi should be accepted.
- */
- if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
- (bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
- (!BFA_FCS_PID_IS_WKA(rport->pid))) {
- bfa_trc(rport->fcs, rport->pid);
- return;
- }
+ rport->pid = rx_fchs->s_id;
+ bfa_trc(rport->fcs, rport->pid);
rport->stats.plogi_rcvd++;
bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
@@ -2531,7 +2536,45 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
}
-
+void
+bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+ struct bfa_rport_attr_s *rport_attr)
+{
+ struct bfa_rport_qos_attr_s qos_attr;
+ struct bfa_fcs_lport_s *port = rport->port;
+ bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+
+ memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
+ memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
+
+ rport_attr->pid = rport->pid;
+ rport_attr->pwwn = rport->pwwn;
+ rport_attr->nwwn = rport->nwwn;
+ rport_attr->cos_supported = rport->fc_cos;
+ rport_attr->df_sz = rport->maxfrsize;
+ rport_attr->state = bfa_fcs_rport_get_state(rport);
+ rport_attr->fc_cos = rport->fc_cos;
+ rport_attr->cisc = rport->cisc;
+ rport_attr->scsi_function = rport->scsi_function;
+ rport_attr->curr_speed = rport->rpf.rpsc_speed;
+ rport_attr->assigned_speed = rport->rpf.assigned_speed;
+
+ qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
+ qos_attr.qos_flow_id =
+ cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
+ rport_attr->qos_attr = qos_attr;
+
+ rport_attr->trl_enforced = BFA_FALSE;
+ if (bfa_fcport_is_ratelim(port->fcs->bfa) &&
+ (rport->scsi_function == BFA_RPORT_TARGET)) {
+ if (rport_speed == BFA_PORT_SPEED_UNKNOWN)
+ rport_speed =
+ bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
+
+ if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+ rport_attr->trl_enforced = BFA_TRUE;
+ }
+}
/*
* Remote port implementation.
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
index 977e681ec803..e7ffd8205dc7 100644
--- a/drivers/scsi/bfa/bfa_hw_cb.c
+++ b/drivers/scsi/bfa/bfa_hw_cb.c
@@ -17,14 +17,14 @@
#include "bfad_drv.h"
#include "bfa_modules.h"
-#include "bfi_cbreg.h"
+#include "bfi_reg.h"
void
bfa_hwcb_reginit(struct bfa_s *bfa)
{
struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
- int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+ int fn = bfa_ioc_pcifn(&bfa->ioc);
if (fn == 0) {
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -33,29 +33,6 @@ bfa_hwcb_reginit(struct bfa_s *bfa)
bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
}
-
- for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
- /*
- * CPE registers
- */
- q = CPE_Q_NUM(fn, i);
- bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q));
- bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q));
- bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q));
-
- /*
- * RME registers
- */
- q = CPE_Q_NUM(fn, i);
- bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q));
- bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q));
- bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q));
- }
-}
-
-void
-bfa_hwcb_reqq_ack(struct bfa_s *bfa, int reqq)
-{
}
static void
@@ -65,11 +42,6 @@ bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
bfa->iocfc.bfa_regs.intr_status);
}
-void
-bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq)
-{
-}
-
static void
bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq)
{
@@ -104,43 +76,71 @@ bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
}
/*
+ * Dummy interrupt handler for handling spurious interrupts.
+ */
+static void
+bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec)
+{
+}
+
+/*
* No special setup required for crossbow -- vector assignments are implicit.
*/
void
bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
{
- int i;
-
WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
bfa->msix.nvecs = nvecs;
- if (nvecs == 1) {
- for (i = 0; i < BFA_MSIX_CB_MAX; i++)
+ bfa_hwcb_msix_uninstall(bfa);
+}
+
+void
+bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa)
+{
+ int i;
+
+ if (bfa->msix.nvecs == 0)
+ return;
+
+ if (bfa->msix.nvecs == 1) {
+ for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++)
bfa->msix.handler[i] = bfa_msix_all;
return;
}
- for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++)
- bfa->msix.handler[i] = bfa_msix_reqq;
-
- for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++)
- bfa->msix.handler[i] = bfa_msix_rspq;
-
- for (; i < BFA_MSIX_CB_MAX; i++)
+ for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
bfa->msix.handler[i] = bfa_msix_lpu_err;
}
-/*
- * Crossbow -- dummy, interrupts are masked
- */
void
-bfa_hwcb_msix_install(struct bfa_s *bfa)
+bfa_hwcb_msix_queue_install(struct bfa_s *bfa)
{
+ int i;
+
+ if (bfa->msix.nvecs == 0)
+ return;
+
+ if (bfa->msix.nvecs == 1) {
+ for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
+ bfa->msix.handler[i] = bfa_msix_all;
+ return;
+ }
+
+ for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++)
+ bfa->msix.handler[i] = bfa_msix_reqq;
+
+ for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
+ bfa->msix.handler[i] = bfa_msix_rspq;
}
void
bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
{
+ int i;
+
+ for (i = 0; i < BFI_MSIX_CB_MAX; i++)
+ bfa->msix.handler[i] = bfa_hwcb_msix_dummy;
}
/*
@@ -156,6 +156,6 @@ bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
void
bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
{
- *start = BFA_MSIX_RME_Q0;
- *end = BFA_MSIX_RME_Q7;
+ *start = BFI_MSIX_RME_QMIN_CB;
+ *end = BFI_MSIX_RME_QMAX_CB;
}
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
index 21018d98a07b..989bbce9b296 100644
--- a/drivers/scsi/bfa/bfa_hw_ct.c
+++ b/drivers/scsi/bfa/bfa_hw_ct.c
@@ -17,29 +17,10 @@
#include "bfad_drv.h"
#include "bfa_modules.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
BFA_TRC_FILE(HAL, IOCFC_CT);
-static u32 __ct_msix_err_vec_reg[] = {
- HOST_MSIX_ERR_INDEX_FN0,
- HOST_MSIX_ERR_INDEX_FN1,
- HOST_MSIX_ERR_INDEX_FN2,
- HOST_MSIX_ERR_INDEX_FN3,
-};
-
-static void
-bfa_hwct_msix_lpu_err_set(struct bfa_s *bfa, bfa_boolean_t msix, int vec)
-{
- int fn = bfa_ioc_pcifn(&bfa->ioc);
- void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
-
- if (msix)
- writel(vec, kva + __ct_msix_err_vec_reg[fn]);
- else
- writel(0, kva + __ct_msix_err_vec_reg[fn]);
-}
-
/*
* Dummy interrupt handler for handling spurious interrupt during chip-reinit.
*/
@@ -53,7 +34,7 @@ bfa_hwct_reginit(struct bfa_s *bfa)
{
struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
- int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+ int fn = bfa_ioc_pcifn(&bfa->ioc);
if (fn == 0) {
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -62,26 +43,16 @@ bfa_hwct_reginit(struct bfa_s *bfa)
bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
}
+}
- for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
- /*
- * CPE registers
- */
- q = CPE_Q_NUM(fn, i);
- bfa_regs->cpe_q_pi[i] = (kva + CPE_PI_PTR_Q(q << 5));
- bfa_regs->cpe_q_ci[i] = (kva + CPE_CI_PTR_Q(q << 5));
- bfa_regs->cpe_q_depth[i] = (kva + CPE_DEPTH_Q(q << 5));
- bfa_regs->cpe_q_ctrl[i] = (kva + CPE_QCTRL_Q(q << 5));
-
- /*
- * RME registers
- */
- q = CPE_Q_NUM(fn, i);
- bfa_regs->rme_q_pi[i] = (kva + RME_PI_PTR_Q(q << 5));
- bfa_regs->rme_q_ci[i] = (kva + RME_CI_PTR_Q(q << 5));
- bfa_regs->rme_q_depth[i] = (kva + RME_DEPTH_Q(q << 5));
- bfa_regs->rme_q_ctrl[i] = (kva + RME_QCTRL_Q(q << 5));
- }
+void
+bfa_hwct2_reginit(struct bfa_s *bfa)
+{
+ struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
+ void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
+
+ bfa_regs->intr_status = (kva + CT2_HOSTFN_INT_STATUS);
+ bfa_regs->intr_mask = (kva + CT2_HOSTFN_INTR_MASK);
}
void
@@ -106,9 +77,9 @@ void
bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
u32 *num_vecs, u32 *max_vec_bit)
{
- *msix_vecs_bmap = (1 << BFA_MSIX_CT_MAX) - 1;
- *max_vec_bit = (1 << (BFA_MSIX_CT_MAX - 1));
- *num_vecs = BFA_MSIX_CT_MAX;
+ *msix_vecs_bmap = (1 << BFI_MSIX_CT_MAX) - 1;
+ *max_vec_bit = (1 << (BFI_MSIX_CT_MAX - 1));
+ *num_vecs = BFI_MSIX_CT_MAX;
}
/*
@@ -117,7 +88,7 @@ bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
void
bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
{
- WARN_ON((nvecs != 1) && (nvecs != BFA_MSIX_CT_MAX));
+ WARN_ON((nvecs != 1) && (nvecs != BFI_MSIX_CT_MAX));
bfa_trc(bfa, nvecs);
bfa->msix.nvecs = nvecs;
@@ -125,7 +96,19 @@ bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
}
void
-bfa_hwct_msix_install(struct bfa_s *bfa)
+bfa_hwct_msix_ctrl_install(struct bfa_s *bfa)
+{
+ if (bfa->msix.nvecs == 0)
+ return;
+
+ if (bfa->msix.nvecs == 1)
+ bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_all;
+ else
+ bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_lpu_err;
+}
+
+void
+bfa_hwct_msix_queue_install(struct bfa_s *bfa)
{
int i;
@@ -133,19 +116,16 @@ bfa_hwct_msix_install(struct bfa_s *bfa)
return;
if (bfa->msix.nvecs == 1) {
- for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+ for (i = BFI_MSIX_CPE_QMIN_CT; i < BFI_MSIX_CT_MAX; i++)
bfa->msix.handler[i] = bfa_msix_all;
return;
}
- for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q3; i++)
+ for (i = BFI_MSIX_CPE_QMIN_CT; i <= BFI_MSIX_CPE_QMAX_CT; i++)
bfa->msix.handler[i] = bfa_msix_reqq;
- for (; i <= BFA_MSIX_RME_Q3; i++)
+ for (i = BFI_MSIX_RME_QMIN_CT; i <= BFI_MSIX_RME_QMAX_CT; i++)
bfa->msix.handler[i] = bfa_msix_rspq;
-
- WARN_ON(i != BFA_MSIX_LPU_ERR);
- bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;
}
void
@@ -153,7 +133,7 @@ bfa_hwct_msix_uninstall(struct bfa_s *bfa)
{
int i;
- for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+ for (i = 0; i < BFI_MSIX_CT_MAX; i++)
bfa->msix.handler[i] = bfa_hwct_msix_dummy;
}
@@ -164,13 +144,12 @@ void
bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
{
bfa_trc(bfa, 0);
- bfa_hwct_msix_lpu_err_set(bfa, msix, BFA_MSIX_LPU_ERR);
bfa_ioc_isr_mode_set(&bfa->ioc, msix);
}
void
bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
{
- *start = BFA_MSIX_RME_Q0;
- *end = BFA_MSIX_RME_Q3;
+ *start = BFI_MSIX_RME_QMIN_CT;
+ *end = BFI_MSIX_RME_QMAX_CT;
}
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 6c7e0339dda4..d6c2bf3865d2 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -17,7 +17,7 @@
#include "bfad_drv.h"
#include "bfa_ioc.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
#include "bfa_defs.h"
#include "bfa_defs_svc.h"
@@ -29,8 +29,8 @@ BFA_TRC_FILE(CNA, IOC);
#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_TOV_RECOVER BFA_IOC_HB_TOV
+#define BFA_IOC_POLL_TOV BFA_TIMER_FREQ
#define bfa_ioc_timer_start(__ioc) \
bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
@@ -79,14 +79,17 @@ bfa_boolean_t bfa_auto_recover = BFA_TRUE;
static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
static void bfa_ioc_timeout(void *ioc);
+static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);
static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);
static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
+static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
+ enum bfa_ioc_event_e event);
static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
@@ -105,11 +108,12 @@ 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 */
+ IOC_E_FWRSP_ACQ_ADDR = 13, /* Acquiring address */
};
bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
@@ -121,6 +125,8 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, acq_addr, struct bfa_ioc_s, enum ioc_event);
static struct bfa_sm_table_s ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -132,6 +138,8 @@ static struct bfa_sm_table_s 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},
+ {BFA_SM(bfa_ioc_sm_acq_addr), BFA_IOC_ACQ_ADDR},
};
/*
@@ -143,9 +151,9 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
#define bfa_iocpf_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
-#define bfa_iocpf_recovery_timer_start(__ioc) \
+#define bfa_iocpf_poll_timer_start(__ioc) \
bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
- bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
+ bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)
#define bfa_sem_timer_start(__ioc) \
bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer, \
@@ -157,6 +165,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
*/
static void bfa_iocpf_timeout(void *ioc_arg);
static void bfa_iocpf_sem_timeout(void *ioc_arg);
+static void bfa_iocpf_poll_timeout(void *ioc_arg);
/*
* IOCPF state machine events
@@ -173,6 +182,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 */
};
/*
@@ -314,11 +324,16 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *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_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
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;
@@ -356,17 +371,23 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
case IOC_E_FWRSP_GETATTR:
bfa_ioc_timer_stop(ioc);
bfa_ioc_check_attr_wwns(ioc);
+ bfa_ioc_hb_monitor(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break;
+ case IOC_E_FWRSP_ACQ_ADDR:
+ bfa_ioc_timer_stop(ioc);
+ bfa_ioc_hb_monitor(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_acq_addr);
break;
+
case IOC_E_PFFAILED:
case IOC_E_HWERROR:
bfa_ioc_timer_stop(ioc);
/* !!! 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_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
break;
@@ -384,6 +405,50 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
}
}
+/*
+ * Acquiring address from fabric (entry function)
+ */
+static void
+bfa_ioc_sm_acq_addr_entry(struct bfa_ioc_s *ioc)
+{
+}
+
+/*
+ * Acquiring address from the fabric
+ */
+static void
+bfa_ioc_sm_acq_addr(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOC_E_FWRSP_GETATTR:
+ bfa_ioc_check_attr_wwns(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+ break;
+
+ case IOC_E_PFFAILED:
+ case IOC_E_HWERROR:
+ bfa_hb_timer_stop(ioc);
+ case IOC_E_HBFAIL:
+ 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_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_hb_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_ENABLE:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
static void
bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
@@ -391,7 +456,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
- bfa_ioc_hb_monitor(ioc);
+ bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
}
@@ -414,13 +479,13 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_hb_timer_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_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
break;
@@ -461,6 +526,11 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
break;
+ case IOC_E_HWFAILED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+ bfa_ioc_disable_comp(ioc);
+ break;
+
default:
bfa_sm_fault(ioc, event);
}
@@ -525,12 +595,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc_s *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_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
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:
@@ -590,6 +662,35 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
}
}
+static void
+bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc)
+{
+ bfa_trc(ioc, 0);
+}
+
+static void
+bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+ bfa_trc(ioc, 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(ioc, event);
+ }
+}
+
/*
* IOCPF State Machine
*/
@@ -600,7 +701,7 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
{
- iocpf->retry_count = 0;
+ iocpf->fw_mismatch_notified = BFA_FALSE;
iocpf->auto_recover = bfa_auto_recover;
}
@@ -633,6 +734,28 @@ bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
{
+ struct bfi_ioc_image_hdr_s fwhdr;
+ u32 fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate);
+
+ /* h/w sem init */
+ if (fwstate == BFI_IOC_UNINIT)
+ goto sem_get;
+
+ bfa_ioc_fwver_get(iocpf->ioc, &fwhdr);
+
+ if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+ goto sem_get;
+
+ bfa_trc(iocpf->ioc, fwstate);
+ bfa_trc(iocpf->ioc, fwhdr.exec);
+ writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate);
+
+ /*
+ * Try to lock and then unlock the semaphore.
+ */
+ readl(iocpf->ioc->ioc_regs.ioc_sem_reg);
+ writel(1, iocpf->ioc->ioc_regs.ioc_sem_reg);
+sem_get:
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -650,7 +773,6 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *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 {
@@ -664,6 +786,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+ break;
+
case IOCPF_E_DISABLE:
bfa_sem_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
@@ -689,10 +816,10 @@ bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
/*
* Call only the first time sm enters fwmismatch state.
*/
- if (iocpf->retry_count == 0)
+ if (iocpf->fw_mismatch_notified == BFA_FALSE)
bfa_ioc_pf_fwmismatch(iocpf->ioc);
- iocpf->retry_count++;
+ iocpf->fw_mismatch_notified = BFA_TRUE;
bfa_iocpf_timer_start(iocpf->ioc);
}
@@ -757,6 +884,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+ break;
+
case IOCPF_E_DISABLE:
bfa_sem_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -770,7 +902,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_iocpf_timer_start(iocpf->ioc);
+ iocpf->poll_time = 0;
bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
}
@@ -787,20 +919,12 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_FWREADY:
- bfa_iocpf_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
break;
- case IOCPF_E_INITFAIL:
- bfa_iocpf_timer_stop(ioc);
- /*
- * !!! fall through !!!
- */
-
case IOCPF_E_TIMEOUT:
writel(1, ioc->ioc_regs.ioc_sem_reg);
- if (event == IOCPF_E_TIMEOUT)
- bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
@@ -820,6 +944,10 @@ static void
bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
{
bfa_iocpf_timer_start(iocpf->ioc);
+ /*
+ * Enable Interrupts before sending fw IOC ENABLE cmd.
+ */
+ iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
bfa_ioc_send_enable(iocpf->ioc);
}
@@ -860,10 +988,6 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *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(ioc, event);
}
@@ -895,16 +1019,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
break;
- case IOCPF_E_FWREADY:
- if (bfa_ioc_is_operational(ioc)) {
- bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
- } else {
- bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
- }
- break;
-
default:
bfa_sm_fault(ioc, event);
}
@@ -929,7 +1043,6 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_FWRSP_DISABLE:
- case IOCPF_E_FWREADY:
bfa_iocpf_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
@@ -976,6 +1089,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *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_fsm_send_event(ioc, IOC_E_HWFAILED);
+ break;
+
case IOCPF_E_FAIL:
break;
@@ -990,6 +1108,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
{
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
}
@@ -1002,7 +1121,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *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;
@@ -1019,6 +1137,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
{
+ bfa_ioc_debug_save_ftrc(iocpf->ioc);
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -1035,20 +1154,15 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *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);
- writel(1, ioc->ioc_regs.ioc_sem_reg);
- 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 {
- writel(1, ioc->ioc_regs.ioc_sem_reg);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
- }
- }
+ bfa_ioc_sync_leave(ioc);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ 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_fsm_send_event(ioc, IOC_E_HWFAILED);
break;
case IOCPF_E_DISABLE:
@@ -1073,7 +1187,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_fsm_send_event(iocpf->ioc, IOC_E_INITFAILED);
+ bfa_trc(iocpf->ioc, 0);
}
/*
@@ -1112,7 +1226,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
/*
* Flush any queued up mailbox requests.
*/
- bfa_ioc_mbox_hbfail(iocpf->ioc);
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -1126,11 +1240,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *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);
writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
} else {
@@ -1143,6 +1257,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+ break;
+
case IOCPF_E_DISABLE:
bfa_sem_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1159,6 +1278,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
{
+ bfa_trc(iocpf->ioc, 0);
}
/*
@@ -1185,23 +1305,28 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
* BFA IOC private functions
*/
+/*
+ * Notify common modules registered for notification.
+ */
static void
-bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event)
{
- struct list_head *qe;
- struct bfa_ioc_hbfail_notify_s *notify;
+ struct bfa_ioc_notify_s *notify;
+ struct list_head *qe;
- ioc->cbfn->disable_cbfn(ioc->bfa);
-
- /*
- * Notify common modules registered for notification.
- */
- list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify_s *) qe;
- notify->cbfn(notify->cbarg);
+ list_for_each(qe, &ioc->notify_q) {
+ notify = (struct bfa_ioc_notify_s *)qe;
+ notify->cbfn(notify->cbarg, event);
}
}
+static void
+bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+{
+ ioc->cbfn->disable_cbfn(ioc->bfa);
+ bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
+}
+
bfa_boolean_t
bfa_ioc_sem_get(void __iomem *sem_reg)
{
@@ -1211,16 +1336,15 @@ bfa_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 BFA_TRUE;
- WARN_ON(cnt >= BFA_SEM_SPINCNT);
return BFA_FALSE;
}
@@ -1234,7 +1358,12 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *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) {
+ WARN_ON(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;
}
@@ -1343,7 +1472,7 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
int i;
drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
- 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]) {
@@ -1369,7 +1498,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
bfa_ioc_fwver_get(ioc, &fwhdr);
drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
- 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) {
bfa_trc(ioc, fwhdr.signature);
@@ -1377,8 +1506,8 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
return BFA_FALSE;
}
- if (swab32(fwhdr.param) != boot_env) {
- bfa_trc(ioc, fwhdr.param);
+ if (swab32(fwhdr.bootenv) != boot_env) {
+ bfa_trc(ioc, fwhdr.bootenv);
bfa_trc(ioc, boot_env);
return BFA_FALSE;
}
@@ -1414,8 +1543,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
bfa_trc(ioc, ioc_fwstate);
- boot_type = BFI_BOOT_TYPE_NORMAL;
- boot_env = BFI_BOOT_LOADER_OS;
+ boot_type = BFI_FWBOOT_TYPE_NORMAL;
+ boot_env = BFI_FWBOOT_ENV_OS;
/*
* check if firmware is valid
@@ -1425,6 +1554,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
if (!fwvalid) {
bfa_ioc_boot(ioc, boot_type, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
return;
}
@@ -1433,7 +1563,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t 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;
}
@@ -1452,7 +1582,6 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t 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;
}
@@ -1461,6 +1590,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
* Initialize the h/w for any other states.
*/
bfa_ioc_boot(ioc, boot_type, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
}
static void
@@ -1508,7 +1638,7 @@ bfa_ioc_send_enable(struct bfa_ioc_s *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 = cpu_to_be16(ioc->clscode);
do_gettimeofday(&tv);
enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
@@ -1572,25 +1702,26 @@ bfa_ioc_download_fw(struct bfa_ioc_s *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);
- bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
- fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
+ bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
+ fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
pgoff = PSS_SMEM_PGOFF(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));
}
@@ -1616,11 +1747,15 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
ioc->ioc_regs.host_page_num_fn);
/*
- * Set boot type and boot param at the end.
- */
- bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
+ * Set boot type and device mode at the end.
+ */
+ asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
+ ioc->port0_mode, ioc->port1_mode);
+ bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
+ swab32(asicmode));
+ bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,
swab32(boot_type));
- bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
+ bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
swab32(boot_env));
}
@@ -1636,6 +1771,7 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
attr->adapter_prop = be32_to_cpu(attr->adapter_prop);
attr->card_type = be32_to_cpu(attr->card_type);
attr->maxfrsize = be16_to_cpu(attr->maxfrsize);
+ ioc->fcmode = (attr->port_mode == BFI_PORT_MODE_FC);
bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
}
@@ -1690,7 +1826,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
* Cleanup any pending requests.
*/
static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)
{
struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
struct bfa_mbox_cmd_s *cmd;
@@ -1752,6 +1888,7 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
/*
* release semaphore.
*/
+ readl(ioc->ioc_regs.ioc_init_sem_reg);
writel(1, ioc->ioc_regs.ioc_init_sem_reg);
bfa_trc(ioc, pgnum);
@@ -1808,6 +1945,7 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
/*
* release semaphore.
*/
+ readl(ioc->ioc_regs.ioc_init_sem_reg);
writel(1, ioc->ioc_regs.ioc_init_sem_reg);
bfa_trc(ioc, pgnum);
return BFA_STATUS_OK;
@@ -1816,18 +1954,13 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
static void
bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
{
- struct list_head *qe;
- struct bfa_ioc_hbfail_notify_s *notify;
struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
/*
* Notify driver and common modules registered for notification.
*/
ioc->cbfn->hbfail_cbfn(ioc->bfa);
- list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify_s *) qe;
- notify->cbfn(notify->cbarg);
- }
+ bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
bfa_ioc_debug_save_ftrc(ioc);
@@ -1864,6 +1997,7 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
/*
* release semaphore.
*/
+ readl(ioc->ioc_regs.ioc_init_sem_reg);
writel(1, ioc->ioc_regs.ioc_init_sem_reg);
return BFA_STATUS_OK;
@@ -1876,8 +2010,6 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
void
bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
{
- void __iomem *rb;
-
bfa_ioc_stats(ioc, ioc_boots);
if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
@@ -1886,22 +2018,16 @@ bfa_ioc_boot(struct bfa_ioc_s *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);
}
@@ -1932,13 +2058,17 @@ bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
(r32 != BFI_IOC_MEMTEST));
}
-void
+bfa_boolean_t
bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
{
__be32 *msgp = mbmsg;
u32 r32;
int i;
+ r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+ if ((r32 & 1) == 0)
+ return BFA_FALSE;
+
/*
* read the MBOX msg
*/
@@ -1954,6 +2084,8 @@ bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
*/
writel(1, ioc->ioc_regs.lpu_mbox_cmd);
readl(ioc->ioc_regs.lpu_mbox_cmd);
+
+ return BFA_TRUE;
}
void
@@ -1970,11 +2102,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *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:
+ ioc->port_mode = ioc->port_mode_cfg =
+ (enum bfa_mode_s)msg->fw_event.port_mode;
+ ioc->ad_cap_bm = msg->fw_event.cap_bm;
bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
break;
@@ -1986,6 +2117,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
bfa_ioc_getattr_reply(ioc);
break;
+ case BFI_IOC_I2H_ACQ_ADDR_REPLY:
+ bfa_fsm_send_event(ioc, IOC_E_FWRSP_ACQ_ADDR);
+ break;
+
default:
bfa_trc(ioc, msg->mh.msg_id);
WARN_ON(1);
@@ -2011,7 +2146,7 @@ bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
ioc->iocpf.ioc = ioc;
bfa_ioc_mbox_attach(ioc);
- INIT_LIST_HEAD(&ioc->hb_notify_q);
+ INIT_LIST_HEAD(&ioc->notify_q);
bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
bfa_fsm_send_event(ioc, IOC_E_RESET);
@@ -2024,6 +2159,7 @@ void
bfa_ioc_detach(struct bfa_ioc_s *ioc)
{
bfa_fsm_send_event(ioc, IOC_E_DETACH);
+ INIT_LIST_HEAD(&ioc->notify_q);
}
/*
@@ -2033,20 +2169,80 @@ bfa_ioc_detach(struct bfa_ioc_s *ioc)
*/
void
bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *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;
+
+ /*
+ * 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 BFA_PCI_DEVICE_ID_FC_8G1P:
+ case BFA_PCI_DEVICE_ID_FC_8G2P:
+ ioc->asic_gen = BFI_ASIC_GEN_CB;
+ ioc->fcmode = BFA_TRUE;
+ ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
+ ioc->ad_cap_bm = BFA_CM_HBA;
+ break;
+
+ case BFA_PCI_DEVICE_ID_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_CT_FC:
+ ioc->asic_gen = BFI_ASIC_GEN_CT;
+ ioc->fcmode = BFA_TRUE;
+ ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
+ ioc->ad_cap_bm = BFA_CM_HBA;
+ 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 = BFA_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:
+ WARN_ON(1);
+ }
/*
* Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
*/
- if (ioc->ctdev)
- bfa_ioc_set_ct_hwif(ioc);
- else
+ if (ioc->asic_gen == BFI_ASIC_GEN_CB)
bfa_ioc_set_cb_hwif(ioc);
+ else if (ioc->asic_gen == BFI_ASIC_GEN_CT)
+ bfa_ioc_set_ct_hwif(ioc);
+ else {
+ WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);
+ bfa_ioc_set_ct2_hwif(ioc);
+ bfa_ioc_ct2_poweron(ioc);
+ }
bfa_ioc_map_port(ioc);
bfa_ioc_reg_init(ioc);
@@ -2172,36 +2368,38 @@ bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
struct bfi_mbmsg_s 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
bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
{
+ bfa_ioc_stats(ioc, ioc_hbfails);
+ ioc->stats.hb_count = ioc->hb_count;
bfa_fsm_send_event(ioc, IOC_E_HWERROR);
}
-void
-bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
-{
- ioc->fcmode = BFA_TRUE;
- ioc->port_id = bfa_ioc_pcifn(ioc);
-}
-
/*
* return true if IOC is disabled
*/
@@ -2213,6 +2411,15 @@ bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
}
/*
+ * Return TRUE if IOC is in acquiring address state
+ */
+bfa_boolean_t
+bfa_ioc_is_acq_addr(struct bfa_ioc_s *ioc)
+{
+ return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_acq_addr);
+}
+
+/*
* return true if IOC firmware is different.
*/
bfa_boolean_t
@@ -2239,17 +2446,16 @@ bfa_boolean_t
bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
{
u32 ioc_state;
- void __iomem *rb = ioc->pcidev.pci_bar_kva;
if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
return BFA_FALSE;
- ioc_state = readl(rb + BFA_IOC0_STATE_REG);
+ ioc_state = readl(ioc->ioc_regs.ioc_fwstate);
if (!bfa_ioc_state_disabled(ioc_state))
return BFA_FALSE;
if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
- ioc_state = readl(rb + BFA_IOC1_STATE_REG);
+ ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate);
if (!bfa_ioc_state_disabled(ioc_state))
return BFA_FALSE;
}
@@ -2308,24 +2514,21 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
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 &&
- !ad_attr->is_mezz;
+ ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
+ ad_attr->trunk_capable = (ad_attr->nports > 1) &&
+ !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
}
enum bfa_ioc_type_e
bfa_ioc_get_type(struct bfa_ioc_s *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)
+ if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
return BFA_IOC_TYPE_LL;
- else {
- WARN_ON(ioc->ioc_mc != BFI_MC_LL);
- return BFA_IOC_TYPE_LL;
- }
+
+ WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC);
+
+ return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
+ ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
}
void
@@ -2384,11 +2587,8 @@ bfa_ioc_get_adapter_model(struct bfa_ioc_s *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);
+ BFA_MFG_NAME, ioc_attr->card_type);
}
enum bfa_ioc_state
@@ -2438,6 +2638,9 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *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);
@@ -2475,12 +2678,6 @@ bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
return m;
}
-bfa_boolean_t
-bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
-{
- return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id);
-}
-
/*
* Retrieve saved firmware trace from a prior IOC failure.
*/
@@ -2531,7 +2728,7 @@ bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
bfa_ioc_portid(ioc));
- req->ioc_class = ioc->ioc_mc;
+ req->clscode = cpu_to_be16(ioc->clscode);
bfa_ioc_mbox_queue(ioc, &cmd);
}
@@ -2673,6 +2870,7 @@ static void
bfa_ioc_recover(struct bfa_ioc_s *ioc)
{
bfa_ioc_stats(ioc, ioc_hbfails);
+ ioc->stats.hb_count = ioc->hb_count;
bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
}
@@ -2703,6 +2901,34 @@ bfa_iocpf_sem_timeout(void *ioc_arg)
bfa_ioc_hw_sem_get(ioc);
}
+static void
+bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
+{
+ u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ bfa_trc(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_iocpf_timeout(ioc);
+ else {
+ ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
+ bfa_iocpf_poll_timer_start(ioc);
+ }
+}
+
+static void
+bfa_iocpf_poll_timeout(void *ioc_arg)
+{
+ struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+ bfa_ioc_poll_fwinit(ioc);
+}
+
/*
* bfa timer function
*/
@@ -2770,3 +2996,2423 @@ bfa_timer_stop(struct bfa_timer_s *timer)
list_del(&timer->qe);
}
+
+/*
+ * ASIC block related
+ */
+static void
+bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
+{
+ struct bfa_ablk_cfg_inst_s *cfg_inst;
+ int i, j;
+ u16 be16;
+ u32 be32;
+
+ for (i = 0; i < BFA_ABLK_MAX; i++) {
+ cfg_inst = &cfg->inst[i];
+ for (j = 0; j < BFA_ABLK_MAX_PFS; j++) {
+ be16 = cfg_inst->pf_cfg[j].pers;
+ cfg_inst->pf_cfg[j].pers = be16_to_cpu(be16);
+ be16 = cfg_inst->pf_cfg[j].num_qpairs;
+ cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);
+ be16 = cfg_inst->pf_cfg[j].num_vectors;
+ cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);
+ be32 = cfg_inst->pf_cfg[j].bw;
+ cfg_inst->pf_cfg[j].bw = be16_to_cpu(be32);
+ }
+ }
+}
+
+static void
+bfa_ablk_isr(void *cbarg, struct bfi_mbmsg_s *msg)
+{
+ struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
+ struct bfi_ablk_i2h_rsp_s *rsp = (struct bfi_ablk_i2h_rsp_s *)msg;
+ bfa_ablk_cbfn_t cbfn;
+
+ WARN_ON(msg->mh.msg_class != BFI_MC_ABLK);
+ bfa_trc(ablk->ioc, msg->mh.msg_id);
+
+ switch (msg->mh.msg_id) {
+ case BFI_ABLK_I2H_QUERY:
+ if (rsp->status == BFA_STATUS_OK) {
+ memcpy(ablk->cfg, ablk->dma_addr.kva,
+ sizeof(struct bfa_ablk_cfg_s));
+ bfa_ablk_config_swap(ablk->cfg);
+ ablk->cfg = NULL;
+ }
+ break;
+
+ case BFI_ABLK_I2H_ADPT_CONFIG:
+ case BFI_ABLK_I2H_PORT_CONFIG:
+ /* update config port mode */
+ ablk->ioc->port_mode_cfg = rsp->port_mode;
+
+ case BFI_ABLK_I2H_PF_DELETE:
+ case BFI_ABLK_I2H_PF_UPDATE:
+ case BFI_ABLK_I2H_OPTROM_ENABLE:
+ case BFI_ABLK_I2H_OPTROM_DISABLE:
+ /* No-op */
+ break;
+
+ case BFI_ABLK_I2H_PF_CREATE:
+ *(ablk->pcifn) = rsp->pcifn;
+ ablk->pcifn = NULL;
+ break;
+
+ default:
+ WARN_ON(1);
+ }
+
+ ablk->busy = BFA_FALSE;
+ if (ablk->cbfn) {
+ cbfn = ablk->cbfn;
+ ablk->cbfn = NULL;
+ cbfn(ablk->cbarg, rsp->status);
+ }
+}
+
+static void
+bfa_ablk_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+ struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
+
+ bfa_trc(ablk->ioc, event);
+
+ switch (event) {
+ case BFA_IOC_E_ENABLED:
+ WARN_ON(ablk->busy != BFA_FALSE);
+ break;
+
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ /* Fail any pending requests */
+ ablk->pcifn = NULL;
+ if (ablk->busy) {
+ if (ablk->cbfn)
+ ablk->cbfn(ablk->cbarg, BFA_STATUS_FAILED);
+ ablk->cbfn = NULL;
+ ablk->busy = BFA_FALSE;
+ }
+ break;
+
+ default:
+ WARN_ON(1);
+ break;
+ }
+}
+
+u32
+bfa_ablk_meminfo(void)
+{
+ return BFA_ROUNDUP(sizeof(struct bfa_ablk_cfg_s), BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa)
+{
+ ablk->dma_addr.kva = dma_kva;
+ ablk->dma_addr.pa = dma_pa;
+}
+
+void
+bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc)
+{
+ ablk->ioc = ioc;
+
+ bfa_ioc_mbox_regisr(ablk->ioc, BFI_MC_ABLK, bfa_ablk_isr, ablk);
+ bfa_q_qe_init(&ablk->ioc_notify);
+ bfa_ioc_notify_init(&ablk->ioc_notify, bfa_ablk_notify, ablk);
+ list_add_tail(&ablk->ioc_notify.qe, &ablk->ioc->notify_q);
+}
+
+bfa_status_t
+bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,
+ bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_query_s *m;
+
+ WARN_ON(!ablk_cfg);
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->cfg = ablk_cfg;
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_query_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_QUERY,
+ bfa_ioc_portid(ablk->ioc));
+ bfa_dma_be_addr_set(m->addr, ablk->dma_addr.pa);
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
+ u8 port, enum bfi_pcifn_class personality, int bw,
+ bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_pf_req_s *m;
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->pcifn = pcifn;
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,
+ bfa_ioc_portid(ablk->ioc));
+ m->pers = cpu_to_be16((u16)personality);
+ m->bw = cpu_to_be32(bw);
+ m->port = port;
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
+ bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_pf_req_s *m;
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_DELETE,
+ bfa_ioc_portid(ablk->ioc));
+ m->pcifn = (u8)pcifn;
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_adapter_config(struct bfa_ablk_s *ablk, enum bfa_mode_s mode,
+ int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_cfg_req_s *m;
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_ADPT_CONFIG,
+ bfa_ioc_portid(ablk->ioc));
+ m->mode = (u8)mode;
+ m->max_pf = (u8)max_pf;
+ m->max_vf = (u8)max_vf;
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,
+ int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_cfg_req_s *m;
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PORT_CONFIG,
+ bfa_ioc_portid(ablk->ioc));
+ m->port = (u8)port;
+ m->mode = (u8)mode;
+ m->max_pf = (u8)max_pf;
+ m->max_vf = (u8)max_vf;
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
+ bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_pf_req_s *m;
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,
+ bfa_ioc_portid(ablk->ioc));
+ m->pcifn = (u8)pcifn;
+ m->bw = cpu_to_be32(bw);
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_optrom_en(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_optrom_s *m;
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_ENABLE,
+ bfa_ioc_portid(ablk->ioc));
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_ablk_h2i_optrom_s *m;
+
+ if (!bfa_ioc_is_operational(ablk->ioc)) {
+ bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+
+ if (ablk->busy) {
+ bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ ablk->cbfn = cbfn;
+ ablk->cbarg = cbarg;
+ ablk->busy = BFA_TRUE;
+
+ m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
+ bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_DISABLE,
+ bfa_ioc_portid(ablk->ioc));
+ bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * SFP module specific
+ */
+
+/* forward declarations */
+static void bfa_sfp_getdata_send(struct bfa_sfp_s *sfp);
+static void bfa_sfp_media_get(struct bfa_sfp_s *sfp);
+static bfa_status_t bfa_sfp_speed_valid(struct bfa_sfp_s *sfp,
+ enum bfa_port_speed portspeed);
+
+static void
+bfa_cb_sfp_show(struct bfa_sfp_s *sfp)
+{
+ bfa_trc(sfp, sfp->lock);
+ if (sfp->cbfn)
+ sfp->cbfn(sfp->cbarg, sfp->status);
+ sfp->lock = 0;
+ sfp->cbfn = NULL;
+}
+
+static void
+bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp)
+{
+ bfa_trc(sfp, sfp->portspeed);
+ if (sfp->media) {
+ bfa_sfp_media_get(sfp);
+ if (sfp->state_query_cbfn)
+ sfp->state_query_cbfn(sfp->state_query_cbarg,
+ sfp->status);
+ sfp->media = NULL;
+ }
+
+ if (sfp->portspeed) {
+ sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed);
+ if (sfp->state_query_cbfn)
+ sfp->state_query_cbfn(sfp->state_query_cbarg,
+ sfp->status);
+ sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
+ }
+
+ sfp->state_query_lock = 0;
+ sfp->state_query_cbfn = NULL;
+}
+
+/*
+ * IOC event handler.
+ */
+static void
+bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event)
+{
+ struct bfa_sfp_s *sfp = sfp_arg;
+
+ bfa_trc(sfp, event);
+ bfa_trc(sfp, sfp->lock);
+ bfa_trc(sfp, sfp->state_query_lock);
+
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ if (sfp->lock) {
+ sfp->status = BFA_STATUS_IOC_FAILURE;
+ bfa_cb_sfp_show(sfp);
+ }
+
+ if (sfp->state_query_lock) {
+ sfp->status = BFA_STATUS_IOC_FAILURE;
+ bfa_cb_sfp_state_query(sfp);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * SFP get data send
+ */
+static void
+bfa_sfp_getdata_send(struct bfa_sfp_s *sfp)
+{
+ struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
+
+ bfa_trc(sfp, req->memtype);
+
+ /* build host command */
+ bfi_h2i_set(req->mh, BFI_MC_SFP, BFI_SFP_H2I_SHOW,
+ bfa_ioc_portid(sfp->ioc));
+
+ /* send mbox cmd */
+ bfa_ioc_mbox_queue(sfp->ioc, &sfp->mbcmd);
+}
+
+/*
+ * SFP is valid, read sfp data
+ */
+static void
+bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype)
+{
+ struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
+
+ WARN_ON(sfp->lock != 0);
+ bfa_trc(sfp, sfp->state);
+
+ sfp->lock = 1;
+ sfp->memtype = memtype;
+ req->memtype = memtype;
+
+ /* Setup SG list */
+ bfa_alen_set(&req->alen, sizeof(struct sfp_mem_s), sfp->dbuf_pa);
+
+ bfa_sfp_getdata_send(sfp);
+}
+
+/*
+ * SFP show complete
+ */
+static void
+bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
+{
+ struct bfi_sfp_rsp_s *rsp = (struct bfi_sfp_rsp_s *) msg;
+
+ if (!sfp->lock) {
+ /*
+ * receiving response after ioc failure
+ */
+ bfa_trc(sfp, sfp->lock);
+ return;
+ }
+
+ bfa_trc(sfp, rsp->status);
+ if (rsp->status == BFA_STATUS_OK) {
+ sfp->data_valid = 1;
+ if (sfp->state == BFA_SFP_STATE_VALID)
+ sfp->status = BFA_STATUS_OK;
+ else if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
+ sfp->status = BFA_STATUS_SFP_UNSUPP;
+ else
+ bfa_trc(sfp, sfp->state);
+ } else {
+ sfp->data_valid = 0;
+ sfp->status = rsp->status;
+ /* sfpshow shouldn't change sfp state */
+ }
+
+ bfa_trc(sfp, sfp->memtype);
+ if (sfp->memtype == BFI_SFP_MEM_DIAGEXT) {
+ bfa_trc(sfp, sfp->data_valid);
+ if (sfp->data_valid) {
+ u32 size = sizeof(struct sfp_mem_s);
+ u8 *des = (u8 *) &(sfp->sfpmem->srlid_base);
+ memcpy(des, sfp->dbuf_kva, size);
+ }
+ /*
+ * Queue completion callback.
+ */
+ bfa_cb_sfp_show(sfp);
+ } else
+ sfp->lock = 0;
+
+ bfa_trc(sfp, sfp->state_query_lock);
+ if (sfp->state_query_lock) {
+ sfp->state = rsp->state;
+ /* Complete callback */
+ bfa_cb_sfp_state_query(sfp);
+ }
+}
+
+/*
+ * SFP query fw sfp state
+ */
+static void
+bfa_sfp_state_query(struct bfa_sfp_s *sfp)
+{
+ struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
+
+ /* Should not be doing query if not in _INIT state */
+ WARN_ON(sfp->state != BFA_SFP_STATE_INIT);
+ WARN_ON(sfp->state_query_lock != 0);
+ bfa_trc(sfp, sfp->state);
+
+ sfp->state_query_lock = 1;
+ req->memtype = 0;
+
+ if (!sfp->lock)
+ bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
+}
+
+static void
+bfa_sfp_media_get(struct bfa_sfp_s *sfp)
+{
+ enum bfa_defs_sfp_media_e *media = sfp->media;
+
+ *media = BFA_SFP_MEDIA_UNKNOWN;
+
+ if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
+ *media = BFA_SFP_MEDIA_UNSUPPORT;
+ else if (sfp->state == BFA_SFP_STATE_VALID) {
+ union sfp_xcvr_e10g_code_u e10g;
+ struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
+ u16 xmtr_tech = (sfpmem->srlid_base.xcvr[4] & 0x3) << 7 |
+ (sfpmem->srlid_base.xcvr[5] >> 1);
+
+ e10g.b = sfpmem->srlid_base.xcvr[0];
+ bfa_trc(sfp, e10g.b);
+ bfa_trc(sfp, xmtr_tech);
+ /* check fc transmitter tech */
+ if ((xmtr_tech & SFP_XMTR_TECH_CU) ||
+ (xmtr_tech & SFP_XMTR_TECH_CP) ||
+ (xmtr_tech & SFP_XMTR_TECH_CA))
+ *media = BFA_SFP_MEDIA_CU;
+ else if ((xmtr_tech & SFP_XMTR_TECH_EL_INTRA) ||
+ (xmtr_tech & SFP_XMTR_TECH_EL_INTER))
+ *media = BFA_SFP_MEDIA_EL;
+ else if ((xmtr_tech & SFP_XMTR_TECH_LL) ||
+ (xmtr_tech & SFP_XMTR_TECH_LC))
+ *media = BFA_SFP_MEDIA_LW;
+ else if ((xmtr_tech & SFP_XMTR_TECH_SL) ||
+ (xmtr_tech & SFP_XMTR_TECH_SN) ||
+ (xmtr_tech & SFP_XMTR_TECH_SA))
+ *media = BFA_SFP_MEDIA_SW;
+ /* Check 10G Ethernet Compilance code */
+ else if (e10g.b & 0x10)
+ *media = BFA_SFP_MEDIA_SW;
+ else if (e10g.b & 0x60)
+ *media = BFA_SFP_MEDIA_LW;
+ else if (e10g.r.e10g_unall & 0x80)
+ *media = BFA_SFP_MEDIA_UNKNOWN;
+ else
+ bfa_trc(sfp, 0);
+ } else
+ bfa_trc(sfp, sfp->state);
+}
+
+static bfa_status_t
+bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed)
+{
+ struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
+ struct sfp_xcvr_s *xcvr = (struct sfp_xcvr_s *) sfpmem->srlid_base.xcvr;
+ union sfp_xcvr_fc3_code_u fc3 = xcvr->fc3;
+ union sfp_xcvr_e10g_code_u e10g = xcvr->e10g;
+
+ if (portspeed == BFA_PORT_SPEED_10GBPS) {
+ if (e10g.r.e10g_sr || e10g.r.e10g_lr)
+ return BFA_STATUS_OK;
+ else {
+ bfa_trc(sfp, e10g.b);
+ return BFA_STATUS_UNSUPP_SPEED;
+ }
+ }
+ if (((portspeed & BFA_PORT_SPEED_16GBPS) && fc3.r.mb1600) ||
+ ((portspeed & BFA_PORT_SPEED_8GBPS) && fc3.r.mb800) ||
+ ((portspeed & BFA_PORT_SPEED_4GBPS) && fc3.r.mb400) ||
+ ((portspeed & BFA_PORT_SPEED_2GBPS) && fc3.r.mb200) ||
+ ((portspeed & BFA_PORT_SPEED_1GBPS) && fc3.r.mb100))
+ return BFA_STATUS_OK;
+ else {
+ bfa_trc(sfp, portspeed);
+ bfa_trc(sfp, fc3.b);
+ bfa_trc(sfp, e10g.b);
+ return BFA_STATUS_UNSUPP_SPEED;
+ }
+}
+
+/*
+ * SFP hmbox handler
+ */
+void
+bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg)
+{
+ struct bfa_sfp_s *sfp = sfparg;
+
+ switch (msg->mh.msg_id) {
+ case BFI_SFP_I2H_SHOW:
+ bfa_sfp_show_comp(sfp, msg);
+ break;
+
+ case BFI_SFP_I2H_SCN:
+ bfa_trc(sfp, msg->mh.msg_id);
+ break;
+
+ default:
+ bfa_trc(sfp, msg->mh.msg_id);
+ WARN_ON(1);
+ }
+}
+
+/*
+ * Return DMA memory needed by sfp module.
+ */
+u32
+bfa_sfp_meminfo(void)
+{
+ return BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Attach virtual and physical memory for SFP.
+ */
+void
+bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, void *dev,
+ struct bfa_trc_mod_s *trcmod)
+{
+ sfp->dev = dev;
+ sfp->ioc = ioc;
+ sfp->trcmod = trcmod;
+
+ sfp->cbfn = NULL;
+ sfp->cbarg = NULL;
+ sfp->sfpmem = NULL;
+ sfp->lock = 0;
+ sfp->data_valid = 0;
+ sfp->state = BFA_SFP_STATE_INIT;
+ sfp->state_query_lock = 0;
+ sfp->state_query_cbfn = NULL;
+ sfp->state_query_cbarg = NULL;
+ sfp->media = NULL;
+ sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
+ sfp->is_elb = BFA_FALSE;
+
+ bfa_ioc_mbox_regisr(sfp->ioc, BFI_MC_SFP, bfa_sfp_intr, sfp);
+ bfa_q_qe_init(&sfp->ioc_notify);
+ bfa_ioc_notify_init(&sfp->ioc_notify, bfa_sfp_notify, sfp);
+ list_add_tail(&sfp->ioc_notify.qe, &sfp->ioc->notify_q);
+}
+
+/*
+ * Claim Memory for SFP
+ */
+void
+bfa_sfp_memclaim(struct bfa_sfp_s *sfp, u8 *dm_kva, u64 dm_pa)
+{
+ sfp->dbuf_kva = dm_kva;
+ sfp->dbuf_pa = dm_pa;
+ memset(sfp->dbuf_kva, 0, sizeof(struct sfp_mem_s));
+
+ dm_kva += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
+ dm_pa += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Show SFP eeprom content
+ *
+ * @param[in] sfp - bfa sfp module
+ *
+ * @param[out] sfpmem - sfp eeprom data
+ *
+ */
+bfa_status_t
+bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem,
+ bfa_cb_sfp_t cbfn, void *cbarg)
+{
+
+ if (!bfa_ioc_is_operational(sfp->ioc)) {
+ bfa_trc(sfp, 0);
+ return BFA_STATUS_IOC_NON_OP;
+ }
+
+ if (sfp->lock) {
+ bfa_trc(sfp, 0);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ sfp->cbfn = cbfn;
+ sfp->cbarg = cbarg;
+ sfp->sfpmem = sfpmem;
+
+ bfa_sfp_getdata(sfp, BFI_SFP_MEM_DIAGEXT);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Return SFP Media type
+ *
+ * @param[in] sfp - bfa sfp module
+ *
+ * @param[out] media - port speed from user
+ *
+ */
+bfa_status_t
+bfa_sfp_media(struct bfa_sfp_s *sfp, enum bfa_defs_sfp_media_e *media,
+ bfa_cb_sfp_t cbfn, void *cbarg)
+{
+ if (!bfa_ioc_is_operational(sfp->ioc)) {
+ bfa_trc(sfp, 0);
+ return BFA_STATUS_IOC_NON_OP;
+ }
+
+ sfp->media = media;
+ if (sfp->state == BFA_SFP_STATE_INIT) {
+ if (sfp->state_query_lock) {
+ bfa_trc(sfp, 0);
+ return BFA_STATUS_DEVBUSY;
+ } else {
+ sfp->state_query_cbfn = cbfn;
+ sfp->state_query_cbarg = cbarg;
+ bfa_sfp_state_query(sfp);
+ return BFA_STATUS_SFP_NOT_READY;
+ }
+ }
+
+ bfa_sfp_media_get(sfp);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Check if user set port speed is allowed by the SFP
+ *
+ * @param[in] sfp - bfa sfp module
+ * @param[in] portspeed - port speed from user
+ *
+ */
+bfa_status_t
+bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed,
+ bfa_cb_sfp_t cbfn, void *cbarg)
+{
+ WARN_ON(portspeed == BFA_PORT_SPEED_UNKNOWN);
+
+ if (!bfa_ioc_is_operational(sfp->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /* For Mezz card, all speed is allowed */
+ if (bfa_mfg_is_mezz(sfp->ioc->attr->card_type))
+ return BFA_STATUS_OK;
+
+ /* Check SFP state */
+ sfp->portspeed = portspeed;
+ if (sfp->state == BFA_SFP_STATE_INIT) {
+ if (sfp->state_query_lock) {
+ bfa_trc(sfp, 0);
+ return BFA_STATUS_DEVBUSY;
+ } else {
+ sfp->state_query_cbfn = cbfn;
+ sfp->state_query_cbarg = cbarg;
+ bfa_sfp_state_query(sfp);
+ return BFA_STATUS_SFP_NOT_READY;
+ }
+ }
+
+ if (sfp->state == BFA_SFP_STATE_REMOVED ||
+ sfp->state == BFA_SFP_STATE_FAILED) {
+ bfa_trc(sfp, sfp->state);
+ return BFA_STATUS_NO_SFP_DEV;
+ }
+
+ if (sfp->state == BFA_SFP_STATE_INSERTED) {
+ bfa_trc(sfp, sfp->state);
+ return BFA_STATUS_DEVBUSY; /* sfp is reading data */
+ }
+
+ /* For eloopback, all speed is allowed */
+ if (sfp->is_elb)
+ return BFA_STATUS_OK;
+
+ return bfa_sfp_speed_valid(sfp, portspeed);
+}
+
+/*
+ * Flash module specific
+ */
+
+/*
+ * FLASH DMA buffer should be big enough to hold both MFG block and
+ * asic block(64k) at the same time and also should be 2k aligned to
+ * avoid write segement to cross sector boundary.
+ */
+#define BFA_FLASH_SEG_SZ 2048
+#define BFA_FLASH_DMA_BUF_SZ \
+ BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ)
+
+static void
+bfa_flash_cb(struct bfa_flash_s *flash)
+{
+ flash->op_busy = 0;
+ if (flash->cbfn)
+ flash->cbfn(flash->cbarg, flash->status);
+}
+
+static void
+bfa_flash_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+ struct bfa_flash_s *flash = cbarg;
+
+ bfa_trc(flash, event);
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ if (flash->op_busy) {
+ flash->status = BFA_STATUS_IOC_FAILURE;
+ flash->cbfn(flash->cbarg, flash->status);
+ flash->op_busy = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * Send flash attribute query request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_query_send(void *cbarg)
+{
+ struct bfa_flash_s *flash = cbarg;
+ struct bfi_flash_query_req_s *msg =
+ (struct bfi_flash_query_req_s *) flash->mb.msg;
+
+ bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,
+ bfa_ioc_portid(flash->ioc));
+ bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr_s),
+ flash->dbuf_pa);
+ bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+}
+
+/*
+ * Send flash write request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_write_send(struct bfa_flash_s *flash)
+{
+ struct bfi_flash_write_req_s *msg =
+ (struct bfi_flash_write_req_s *) flash->mb.msg;
+ u32 len;
+
+ msg->type = be32_to_cpu(flash->type);
+ msg->instance = flash->instance;
+ msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
+ len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
+ flash->residue : BFA_FLASH_DMA_BUF_SZ;
+ msg->length = be32_to_cpu(len);
+
+ /* indicate if it's the last msg of the whole write operation */
+ msg->last = (len == flash->residue) ? 1 : 0;
+
+ bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,
+ bfa_ioc_portid(flash->ioc));
+ bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
+ memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);
+ bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+
+ flash->residue -= len;
+ flash->offset += len;
+}
+
+/*
+ * Send flash read request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_read_send(void *cbarg)
+{
+ struct bfa_flash_s *flash = cbarg;
+ struct bfi_flash_read_req_s *msg =
+ (struct bfi_flash_read_req_s *) flash->mb.msg;
+ u32 len;
+
+ msg->type = be32_to_cpu(flash->type);
+ msg->instance = flash->instance;
+ msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
+ len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
+ flash->residue : BFA_FLASH_DMA_BUF_SZ;
+ msg->length = be32_to_cpu(len);
+ bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,
+ bfa_ioc_portid(flash->ioc));
+ bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
+ bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+}
+
+/*
+ * Send flash erase request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_erase_send(void *cbarg)
+{
+ struct bfa_flash_s *flash = cbarg;
+ struct bfi_flash_erase_req_s *msg =
+ (struct bfi_flash_erase_req_s *) flash->mb.msg;
+
+ msg->type = be32_to_cpu(flash->type);
+ msg->instance = flash->instance;
+ bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_ERASE_REQ,
+ bfa_ioc_portid(flash->ioc));
+ bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+}
+
+/*
+ * Process flash response messages upon receiving interrupts.
+ *
+ * @param[in] flasharg - flash structure
+ * @param[in] msg - message structure
+ */
+static void
+bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)
+{
+ struct bfa_flash_s *flash = flasharg;
+ u32 status;
+
+ union {
+ struct bfi_flash_query_rsp_s *query;
+ struct bfi_flash_erase_rsp_s *erase;
+ struct bfi_flash_write_rsp_s *write;
+ struct bfi_flash_read_rsp_s *read;
+ struct bfi_mbmsg_s *msg;
+ } m;
+
+ m.msg = msg;
+ bfa_trc(flash, msg->mh.msg_id);
+
+ if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT) {
+ /* receiving response after ioc failure */
+ bfa_trc(flash, 0x9999);
+ return;
+ }
+
+ switch (msg->mh.msg_id) {
+ case BFI_FLASH_I2H_QUERY_RSP:
+ status = be32_to_cpu(m.query->status);
+ bfa_trc(flash, status);
+ if (status == BFA_STATUS_OK) {
+ u32 i;
+ struct bfa_flash_attr_s *attr, *f;
+
+ attr = (struct bfa_flash_attr_s *) flash->ubuf;
+ f = (struct bfa_flash_attr_s *) flash->dbuf_kva;
+ attr->status = be32_to_cpu(f->status);
+ attr->npart = be32_to_cpu(f->npart);
+ bfa_trc(flash, attr->status);
+ bfa_trc(flash, attr->npart);
+ for (i = 0; i < attr->npart; i++) {
+ attr->part[i].part_type =
+ be32_to_cpu(f->part[i].part_type);
+ attr->part[i].part_instance =
+ be32_to_cpu(f->part[i].part_instance);
+ attr->part[i].part_off =
+ be32_to_cpu(f->part[i].part_off);
+ attr->part[i].part_size =
+ be32_to_cpu(f->part[i].part_size);
+ attr->part[i].part_len =
+ be32_to_cpu(f->part[i].part_len);
+ attr->part[i].part_status =
+ be32_to_cpu(f->part[i].part_status);
+ }
+ }
+ flash->status = status;
+ bfa_flash_cb(flash);
+ break;
+ case BFI_FLASH_I2H_ERASE_RSP:
+ status = be32_to_cpu(m.erase->status);
+ bfa_trc(flash, status);
+ flash->status = status;
+ bfa_flash_cb(flash);
+ break;
+ case BFI_FLASH_I2H_WRITE_RSP:
+ status = be32_to_cpu(m.write->status);
+ bfa_trc(flash, status);
+ if (status != BFA_STATUS_OK || flash->residue == 0) {
+ flash->status = status;
+ bfa_flash_cb(flash);
+ } else {
+ bfa_trc(flash, flash->offset);
+ bfa_flash_write_send(flash);
+ }
+ break;
+ case BFI_FLASH_I2H_READ_RSP:
+ status = be32_to_cpu(m.read->status);
+ bfa_trc(flash, status);
+ if (status != BFA_STATUS_OK) {
+ flash->status = status;
+ bfa_flash_cb(flash);
+ } else {
+ u32 len = be32_to_cpu(m.read->length);
+ bfa_trc(flash, flash->offset);
+ bfa_trc(flash, len);
+ memcpy(flash->ubuf + flash->offset,
+ flash->dbuf_kva, len);
+ flash->residue -= len;
+ flash->offset += len;
+ if (flash->residue == 0) {
+ flash->status = status;
+ bfa_flash_cb(flash);
+ } else
+ bfa_flash_read_send(flash);
+ }
+ break;
+ case BFI_FLASH_I2H_BOOT_VER_RSP:
+ case BFI_FLASH_I2H_EVENT:
+ bfa_trc(flash, msg->mh.msg_id);
+ break;
+
+ default:
+ WARN_ON(1);
+ }
+}
+
+/*
+ * Flash memory info API.
+ *
+ * @param[in] mincfg - minimal cfg variable
+ */
+u32
+bfa_flash_meminfo(bfa_boolean_t mincfg)
+{
+ /* min driver doesn't need flash */
+ if (mincfg)
+ return 0;
+ return BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Flash attach API.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] ioc - ioc structure
+ * @param[in] dev - device structure
+ * @param[in] trcmod - trace module
+ * @param[in] logmod - log module
+ */
+void
+bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, void *dev,
+ struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
+{
+ flash->ioc = ioc;
+ flash->trcmod = trcmod;
+ flash->cbfn = NULL;
+ flash->cbarg = NULL;
+ flash->op_busy = 0;
+
+ bfa_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);
+ bfa_q_qe_init(&flash->ioc_notify);
+ bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);
+ list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);
+
+ /* min driver doesn't need flash */
+ if (mincfg) {
+ flash->dbuf_kva = NULL;
+ flash->dbuf_pa = 0;
+ }
+}
+
+/*
+ * Claim memory for flash
+ *
+ * @param[in] flash - flash structure
+ * @param[in] dm_kva - pointer to virtual memory address
+ * @param[in] dm_pa - physical memory address
+ * @param[in] mincfg - minimal cfg variable
+ */
+void
+bfa_flash_memclaim(struct bfa_flash_s *flash, u8 *dm_kva, u64 dm_pa,
+ bfa_boolean_t mincfg)
+{
+ if (mincfg)
+ return;
+
+ flash->dbuf_kva = dm_kva;
+ flash->dbuf_pa = dm_pa;
+ memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);
+ dm_kva += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+ dm_pa += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Get flash attribute.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] attr - flash attribute structure
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_get_attr(struct bfa_flash_s *flash, struct bfa_flash_attr_s *attr,
+ bfa_cb_flash_t cbfn, void *cbarg)
+{
+ bfa_trc(flash, BFI_FLASH_H2I_QUERY_REQ);
+
+ if (!bfa_ioc_is_operational(flash->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (flash->op_busy) {
+ bfa_trc(flash, flash->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ flash->op_busy = 1;
+ flash->cbfn = cbfn;
+ flash->cbarg = cbarg;
+ flash->ubuf = (u8 *) attr;
+ bfa_flash_query_send(flash);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Erase flash partition.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] type - flash partition type
+ * @param[in] instance - flash partition instance
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
+ u8 instance, bfa_cb_flash_t cbfn, void *cbarg)
+{
+ bfa_trc(flash, BFI_FLASH_H2I_ERASE_REQ);
+ bfa_trc(flash, type);
+ bfa_trc(flash, instance);
+
+ if (!bfa_ioc_is_operational(flash->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (flash->op_busy) {
+ bfa_trc(flash, flash->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ flash->op_busy = 1;
+ flash->cbfn = cbfn;
+ flash->cbarg = cbarg;
+ flash->type = type;
+ flash->instance = instance;
+
+ bfa_flash_erase_send(flash);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Update flash partition.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] type - flash partition type
+ * @param[in] instance - flash partition instance
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to the partition starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_update_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
+ u8 instance, void *buf, u32 len, u32 offset,
+ bfa_cb_flash_t cbfn, void *cbarg)
+{
+ bfa_trc(flash, BFI_FLASH_H2I_WRITE_REQ);
+ bfa_trc(flash, type);
+ bfa_trc(flash, instance);
+ bfa_trc(flash, len);
+ bfa_trc(flash, offset);
+
+ if (!bfa_ioc_is_operational(flash->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /*
+ * 'len' must be in word (4-byte) boundary
+ * 'offset' must be in sector (16kb) boundary
+ */
+ if (!len || (len & 0x03) || (offset & 0x00003FFF))
+ return BFA_STATUS_FLASH_BAD_LEN;
+
+ if (type == BFA_FLASH_PART_MFG)
+ return BFA_STATUS_EINVAL;
+
+ if (flash->op_busy) {
+ bfa_trc(flash, flash->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ flash->op_busy = 1;
+ flash->cbfn = cbfn;
+ flash->cbarg = cbarg;
+ flash->type = type;
+ flash->instance = instance;
+ flash->residue = len;
+ flash->offset = 0;
+ flash->addr_off = offset;
+ flash->ubuf = buf;
+
+ bfa_flash_write_send(flash);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Read flash partition.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] type - flash partition type
+ * @param[in] instance - flash partition instance
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to the partition starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
+ u8 instance, void *buf, u32 len, u32 offset,
+ bfa_cb_flash_t cbfn, void *cbarg)
+{
+ bfa_trc(flash, BFI_FLASH_H2I_READ_REQ);
+ bfa_trc(flash, type);
+ bfa_trc(flash, instance);
+ bfa_trc(flash, len);
+ bfa_trc(flash, offset);
+
+ if (!bfa_ioc_is_operational(flash->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /*
+ * 'len' must be in word (4-byte) boundary
+ * 'offset' must be in sector (16kb) boundary
+ */
+ if (!len || (len & 0x03) || (offset & 0x00003FFF))
+ return BFA_STATUS_FLASH_BAD_LEN;
+
+ if (flash->op_busy) {
+ bfa_trc(flash, flash->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ flash->op_busy = 1;
+ flash->cbfn = cbfn;
+ flash->cbarg = cbarg;
+ flash->type = type;
+ flash->instance = instance;
+ flash->residue = len;
+ flash->offset = 0;
+ flash->addr_off = offset;
+ flash->ubuf = buf;
+ bfa_flash_read_send(flash);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * DIAG module specific
+ */
+
+#define BFA_DIAG_MEMTEST_TOV 50000 /* memtest timeout in msec */
+#define BFA_DIAG_FWPING_TOV 1000 /* msec */
+
+/* IOC event handler */
+static void
+bfa_diag_notify(void *diag_arg, enum bfa_ioc_event_e event)
+{
+ struct bfa_diag_s *diag = diag_arg;
+
+ bfa_trc(diag, event);
+ bfa_trc(diag, diag->block);
+ bfa_trc(diag, diag->fwping.lock);
+ bfa_trc(diag, diag->tsensor.lock);
+
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ if (diag->fwping.lock) {
+ diag->fwping.status = BFA_STATUS_IOC_FAILURE;
+ diag->fwping.cbfn(diag->fwping.cbarg,
+ diag->fwping.status);
+ diag->fwping.lock = 0;
+ }
+
+ if (diag->tsensor.lock) {
+ diag->tsensor.status = BFA_STATUS_IOC_FAILURE;
+ diag->tsensor.cbfn(diag->tsensor.cbarg,
+ diag->tsensor.status);
+ diag->tsensor.lock = 0;
+ }
+
+ if (diag->block) {
+ if (diag->timer_active) {
+ bfa_timer_stop(&diag->timer);
+ diag->timer_active = 0;
+ }
+
+ diag->status = BFA_STATUS_IOC_FAILURE;
+ diag->cbfn(diag->cbarg, diag->status);
+ diag->block = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+bfa_diag_memtest_done(void *cbarg)
+{
+ struct bfa_diag_s *diag = cbarg;
+ struct bfa_ioc_s *ioc = diag->ioc;
+ struct bfa_diag_memtest_result *res = diag->result;
+ u32 loff = BFI_BOOT_MEMTEST_RES_ADDR;
+ u32 pgnum, pgoff, i;
+
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+ pgoff = PSS_SMEM_PGOFF(loff);
+
+ writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+ for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) /
+ sizeof(u32)); i++) {
+ /* read test result from smem */
+ *((u32 *) res + i) =
+ bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+ loff += sizeof(u32);
+ }
+
+ /* Reset IOC fwstates to BFI_IOC_UNINIT */
+ bfa_ioc_reset_fwstate(ioc);
+
+ res->status = swab32(res->status);
+ bfa_trc(diag, res->status);
+
+ if (res->status == BFI_BOOT_MEMTEST_RES_SIG)
+ diag->status = BFA_STATUS_OK;
+ else {
+ diag->status = BFA_STATUS_MEMTEST_FAILED;
+ res->addr = swab32(res->addr);
+ res->exp = swab32(res->exp);
+ res->act = swab32(res->act);
+ res->err_status = swab32(res->err_status);
+ res->err_status1 = swab32(res->err_status1);
+ res->err_addr = swab32(res->err_addr);
+ bfa_trc(diag, res->addr);
+ bfa_trc(diag, res->exp);
+ bfa_trc(diag, res->act);
+ bfa_trc(diag, res->err_status);
+ bfa_trc(diag, res->err_status1);
+ bfa_trc(diag, res->err_addr);
+ }
+ diag->timer_active = 0;
+ diag->cbfn(diag->cbarg, diag->status);
+ diag->block = 0;
+}
+
+/*
+ * Firmware ping
+ */
+
+/*
+ * Perform DMA test directly
+ */
+static void
+diag_fwping_send(struct bfa_diag_s *diag)
+{
+ struct bfi_diag_fwping_req_s *fwping_req;
+ u32 i;
+
+ bfa_trc(diag, diag->fwping.dbuf_pa);
+
+ /* fill DMA area with pattern */
+ for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++)
+ *((u32 *)diag->fwping.dbuf_kva + i) = diag->fwping.data;
+
+ /* Fill mbox msg */
+ fwping_req = (struct bfi_diag_fwping_req_s *)diag->fwping.mbcmd.msg;
+
+ /* Setup SG list */
+ bfa_alen_set(&fwping_req->alen, BFI_DIAG_DMA_BUF_SZ,
+ diag->fwping.dbuf_pa);
+ /* Set up dma count */
+ fwping_req->count = cpu_to_be32(diag->fwping.count);
+ /* Set up data pattern */
+ fwping_req->data = diag->fwping.data;
+
+ /* build host command */
+ bfi_h2i_set(fwping_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_FWPING,
+ bfa_ioc_portid(diag->ioc));
+
+ /* send mbox cmd */
+ bfa_ioc_mbox_queue(diag->ioc, &diag->fwping.mbcmd);
+}
+
+static void
+diag_fwping_comp(struct bfa_diag_s *diag,
+ struct bfi_diag_fwping_rsp_s *diag_rsp)
+{
+ u32 rsp_data = diag_rsp->data;
+ u8 rsp_dma_status = diag_rsp->dma_status;
+
+ bfa_trc(diag, rsp_data);
+ bfa_trc(diag, rsp_dma_status);
+
+ if (rsp_dma_status == BFA_STATUS_OK) {
+ u32 i, pat;
+ pat = (diag->fwping.count & 0x1) ? ~(diag->fwping.data) :
+ diag->fwping.data;
+ /* Check mbox data */
+ if (diag->fwping.data != rsp_data) {
+ bfa_trc(diag, rsp_data);
+ diag->fwping.result->dmastatus =
+ BFA_STATUS_DATACORRUPTED;
+ diag->fwping.status = BFA_STATUS_DATACORRUPTED;
+ diag->fwping.cbfn(diag->fwping.cbarg,
+ diag->fwping.status);
+ diag->fwping.lock = 0;
+ return;
+ }
+ /* Check dma pattern */
+ for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) {
+ if (*((u32 *)diag->fwping.dbuf_kva + i) != pat) {
+ bfa_trc(diag, i);
+ bfa_trc(diag, pat);
+ bfa_trc(diag,
+ *((u32 *)diag->fwping.dbuf_kva + i));
+ diag->fwping.result->dmastatus =
+ BFA_STATUS_DATACORRUPTED;
+ diag->fwping.status = BFA_STATUS_DATACORRUPTED;
+ diag->fwping.cbfn(diag->fwping.cbarg,
+ diag->fwping.status);
+ diag->fwping.lock = 0;
+ return;
+ }
+ }
+ diag->fwping.result->dmastatus = BFA_STATUS_OK;
+ diag->fwping.status = BFA_STATUS_OK;
+ diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
+ diag->fwping.lock = 0;
+ } else {
+ diag->fwping.status = BFA_STATUS_HDMA_FAILED;
+ diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
+ diag->fwping.lock = 0;
+ }
+}
+
+/*
+ * Temperature Sensor
+ */
+
+static void
+diag_tempsensor_send(struct bfa_diag_s *diag)
+{
+ struct bfi_diag_ts_req_s *msg;
+
+ msg = (struct bfi_diag_ts_req_s *)diag->tsensor.mbcmd.msg;
+ bfa_trc(diag, msg->temp);
+ /* build host command */
+ bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_TEMPSENSOR,
+ bfa_ioc_portid(diag->ioc));
+ /* send mbox cmd */
+ bfa_ioc_mbox_queue(diag->ioc, &diag->tsensor.mbcmd);
+}
+
+static void
+diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
+{
+ if (!diag->tsensor.lock) {
+ /* receiving response after ioc failure */
+ bfa_trc(diag, diag->tsensor.lock);
+ return;
+ }
+
+ /*
+ * ASIC junction tempsensor is a reg read operation
+ * it will always return OK
+ */
+ diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
+ diag->tsensor.temp->ts_junc = rsp->ts_junc;
+ diag->tsensor.temp->ts_brd = rsp->ts_brd;
+ diag->tsensor.temp->status = BFA_STATUS_OK;
+
+ if (rsp->ts_brd) {
+ if (rsp->status == BFA_STATUS_OK) {
+ diag->tsensor.temp->brd_temp =
+ be16_to_cpu(rsp->brd_temp);
+ } else {
+ bfa_trc(diag, rsp->status);
+ diag->tsensor.temp->brd_temp = 0;
+ diag->tsensor.temp->status = BFA_STATUS_DEVBUSY;
+ }
+ }
+ bfa_trc(diag, rsp->ts_junc);
+ bfa_trc(diag, rsp->temp);
+ bfa_trc(diag, rsp->ts_brd);
+ bfa_trc(diag, rsp->brd_temp);
+ diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
+ diag->tsensor.lock = 0;
+}
+
+/*
+ * LED Test command
+ */
+static void
+diag_ledtest_send(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
+{
+ struct bfi_diag_ledtest_req_s *msg;
+
+ msg = (struct bfi_diag_ledtest_req_s *)diag->ledtest.mbcmd.msg;
+ /* build host command */
+ bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LEDTEST,
+ bfa_ioc_portid(diag->ioc));
+
+ /*
+ * convert the freq from N blinks per 10 sec to
+ * crossbow ontime value. We do it here because division is need
+ */
+ if (ledtest->freq)
+ ledtest->freq = 500 / ledtest->freq;
+
+ if (ledtest->freq == 0)
+ ledtest->freq = 1;
+
+ bfa_trc(diag, ledtest->freq);
+ /* mcpy(&ledtest_req->req, ledtest, sizeof(bfa_diag_ledtest_t)); */
+ msg->cmd = (u8) ledtest->cmd;
+ msg->color = (u8) ledtest->color;
+ msg->portid = bfa_ioc_portid(diag->ioc);
+ msg->led = ledtest->led;
+ msg->freq = cpu_to_be16(ledtest->freq);
+
+ /* send mbox cmd */
+ bfa_ioc_mbox_queue(diag->ioc, &diag->ledtest.mbcmd);
+}
+
+static void
+diag_ledtest_comp(struct bfa_diag_s *diag, struct bfi_diag_ledtest_rsp_s * msg)
+{
+ bfa_trc(diag, diag->ledtest.lock);
+ diag->ledtest.lock = BFA_FALSE;
+ /* no bfa_cb_queue is needed because driver is not waiting */
+}
+
+/*
+ * Port beaconing
+ */
+static void
+diag_portbeacon_send(struct bfa_diag_s *diag, bfa_boolean_t beacon, u32 sec)
+{
+ struct bfi_diag_portbeacon_req_s *msg;
+
+ msg = (struct bfi_diag_portbeacon_req_s *)diag->beacon.mbcmd.msg;
+ /* build host command */
+ bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_PORTBEACON,
+ bfa_ioc_portid(diag->ioc));
+ msg->beacon = beacon;
+ msg->period = cpu_to_be32(sec);
+ /* send mbox cmd */
+ bfa_ioc_mbox_queue(diag->ioc, &diag->beacon.mbcmd);
+}
+
+static void
+diag_portbeacon_comp(struct bfa_diag_s *diag)
+{
+ bfa_trc(diag, diag->beacon.state);
+ diag->beacon.state = BFA_FALSE;
+ if (diag->cbfn_beacon)
+ diag->cbfn_beacon(diag->dev, BFA_FALSE, diag->beacon.link_e2e);
+}
+
+/*
+ * Diag hmbox handler
+ */
+void
+bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg)
+{
+ struct bfa_diag_s *diag = diagarg;
+
+ switch (msg->mh.msg_id) {
+ case BFI_DIAG_I2H_PORTBEACON:
+ diag_portbeacon_comp(diag);
+ break;
+ case BFI_DIAG_I2H_FWPING:
+ diag_fwping_comp(diag, (struct bfi_diag_fwping_rsp_s *) msg);
+ break;
+ case BFI_DIAG_I2H_TEMPSENSOR:
+ diag_tempsensor_comp(diag, (bfi_diag_ts_rsp_t *) msg);
+ break;
+ case BFI_DIAG_I2H_LEDTEST:
+ diag_ledtest_comp(diag, (struct bfi_diag_ledtest_rsp_s *) msg);
+ break;
+ default:
+ bfa_trc(diag, msg->mh.msg_id);
+ WARN_ON(1);
+ }
+}
+
+/*
+ * Gen RAM Test
+ *
+ * @param[in] *diag - diag data struct
+ * @param[in] *memtest - mem test params input from upper layer,
+ * @param[in] pattern - mem test pattern
+ * @param[in] *result - mem test result
+ * @param[in] cbfn - mem test callback functioin
+ * @param[in] cbarg - callback functioin arg
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_diag_memtest(struct bfa_diag_s *diag, struct bfa_diag_memtest_s *memtest,
+ u32 pattern, struct bfa_diag_memtest_result *result,
+ bfa_cb_diag_t cbfn, void *cbarg)
+{
+ bfa_trc(diag, pattern);
+
+ if (!bfa_ioc_adapter_is_disabled(diag->ioc))
+ return BFA_STATUS_ADAPTER_ENABLED;
+
+ /* check to see if there is another destructive diag cmd running */
+ if (diag->block) {
+ bfa_trc(diag, diag->block);
+ return BFA_STATUS_DEVBUSY;
+ } else
+ diag->block = 1;
+
+ diag->result = result;
+ diag->cbfn = cbfn;
+ diag->cbarg = cbarg;
+
+ /* download memtest code and take LPU0 out of reset */
+ bfa_ioc_boot(diag->ioc, BFI_FWBOOT_TYPE_MEMTEST, BFI_FWBOOT_ENV_OS);
+
+ bfa_timer_begin(diag->ioc->timer_mod, &diag->timer,
+ bfa_diag_memtest_done, diag, BFA_DIAG_MEMTEST_TOV);
+ diag->timer_active = 1;
+ return BFA_STATUS_OK;
+}
+
+/*
+ * DIAG firmware ping command
+ *
+ * @param[in] *diag - diag data struct
+ * @param[in] cnt - dma loop count for testing PCIE
+ * @param[in] data - data pattern to pass in fw
+ * @param[in] *result - pt to bfa_diag_fwping_result_t data struct
+ * @param[in] cbfn - callback function
+ * @param[in] *cbarg - callback functioin arg
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, u32 data,
+ struct bfa_diag_results_fwping *result, bfa_cb_diag_t cbfn,
+ void *cbarg)
+{
+ bfa_trc(diag, cnt);
+ bfa_trc(diag, data);
+
+ if (!bfa_ioc_is_operational(diag->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (bfa_asic_id_ct2(bfa_ioc_devid((diag->ioc))) &&
+ ((diag->ioc)->clscode == BFI_PCIFN_CLASS_ETH))
+ return BFA_STATUS_CMD_NOTSUPP;
+
+ /* check to see if there is another destructive diag cmd running */
+ if (diag->block || diag->fwping.lock) {
+ bfa_trc(diag, diag->block);
+ bfa_trc(diag, diag->fwping.lock);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ /* Initialization */
+ diag->fwping.lock = 1;
+ diag->fwping.cbfn = cbfn;
+ diag->fwping.cbarg = cbarg;
+ diag->fwping.result = result;
+ diag->fwping.data = data;
+ diag->fwping.count = cnt;
+
+ /* Init test results */
+ diag->fwping.result->data = 0;
+ diag->fwping.result->status = BFA_STATUS_OK;
+
+ /* kick off the first ping */
+ diag_fwping_send(diag);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Read Temperature Sensor
+ *
+ * @param[in] *diag - diag data struct
+ * @param[in] *result - pt to bfa_diag_temp_t data struct
+ * @param[in] cbfn - callback function
+ * @param[in] *cbarg - callback functioin arg
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_diag_tsensor_query(struct bfa_diag_s *diag,
+ struct bfa_diag_results_tempsensor_s *result,
+ bfa_cb_diag_t cbfn, void *cbarg)
+{
+ /* check to see if there is a destructive diag cmd running */
+ if (diag->block || diag->tsensor.lock) {
+ bfa_trc(diag, diag->block);
+ bfa_trc(diag, diag->tsensor.lock);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ if (!bfa_ioc_is_operational(diag->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /* Init diag mod params */
+ diag->tsensor.lock = 1;
+ diag->tsensor.temp = result;
+ diag->tsensor.cbfn = cbfn;
+ diag->tsensor.cbarg = cbarg;
+
+ /* Send msg to fw */
+ diag_tempsensor_send(diag);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * LED Test command
+ *
+ * @param[in] *diag - diag data struct
+ * @param[in] *ledtest - pt to ledtest data structure
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_diag_ledtest(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
+{
+ bfa_trc(diag, ledtest->cmd);
+
+ if (!bfa_ioc_is_operational(diag->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (diag->beacon.state)
+ return BFA_STATUS_BEACON_ON;
+
+ if (diag->ledtest.lock)
+ return BFA_STATUS_LEDTEST_OP;
+
+ /* Send msg to fw */
+ diag->ledtest.lock = BFA_TRUE;
+ diag_ledtest_send(diag, ledtest);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Port beaconing command
+ *
+ * @param[in] *diag - diag data struct
+ * @param[in] beacon - port beaconing 1:ON 0:OFF
+ * @param[in] link_e2e_beacon - link beaconing 1:ON 0:OFF
+ * @param[in] sec - beaconing duration in seconds
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_diag_beacon_port(struct bfa_diag_s *diag, bfa_boolean_t beacon,
+ bfa_boolean_t link_e2e_beacon, uint32_t sec)
+{
+ bfa_trc(diag, beacon);
+ bfa_trc(diag, link_e2e_beacon);
+ bfa_trc(diag, sec);
+
+ if (!bfa_ioc_is_operational(diag->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (diag->ledtest.lock)
+ return BFA_STATUS_LEDTEST_OP;
+
+ if (diag->beacon.state && beacon) /* beacon alread on */
+ return BFA_STATUS_BEACON_ON;
+
+ diag->beacon.state = beacon;
+ diag->beacon.link_e2e = link_e2e_beacon;
+ if (diag->cbfn_beacon)
+ diag->cbfn_beacon(diag->dev, beacon, link_e2e_beacon);
+
+ /* Send msg to fw */
+ diag_portbeacon_send(diag, beacon, sec);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Return DMA memory needed by diag module.
+ */
+u32
+bfa_diag_meminfo(void)
+{
+ return BFA_ROUNDUP(BFI_DIAG_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Attach virtual and physical memory for Diag.
+ */
+void
+bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
+ bfa_cb_diag_beacon_t cbfn_beacon, struct bfa_trc_mod_s *trcmod)
+{
+ diag->dev = dev;
+ diag->ioc = ioc;
+ diag->trcmod = trcmod;
+
+ diag->block = 0;
+ diag->cbfn = NULL;
+ diag->cbarg = NULL;
+ diag->result = NULL;
+ diag->cbfn_beacon = cbfn_beacon;
+
+ bfa_ioc_mbox_regisr(diag->ioc, BFI_MC_DIAG, bfa_diag_intr, diag);
+ bfa_q_qe_init(&diag->ioc_notify);
+ bfa_ioc_notify_init(&diag->ioc_notify, bfa_diag_notify, diag);
+ list_add_tail(&diag->ioc_notify.qe, &diag->ioc->notify_q);
+}
+
+void
+bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa)
+{
+ diag->fwping.dbuf_kva = dm_kva;
+ diag->fwping.dbuf_pa = dm_pa;
+ memset(diag->fwping.dbuf_kva, 0, BFI_DIAG_DMA_BUF_SZ);
+}
+
+/*
+ * PHY module specific
+ */
+#define BFA_PHY_DMA_BUF_SZ 0x02000 /* 8k dma buffer */
+#define BFA_PHY_LOCK_STATUS 0x018878 /* phy semaphore status reg */
+
+static void
+bfa_phy_ntoh32(u32 *obuf, u32 *ibuf, int sz)
+{
+ int i, m = sz >> 2;
+
+ for (i = 0; i < m; i++)
+ obuf[i] = be32_to_cpu(ibuf[i]);
+}
+
+static bfa_boolean_t
+bfa_phy_present(struct bfa_phy_s *phy)
+{
+ return (phy->ioc->attr->card_type == BFA_MFG_TYPE_LIGHTNING);
+}
+
+static void
+bfa_phy_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+ struct bfa_phy_s *phy = cbarg;
+
+ bfa_trc(phy, event);
+
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ if (phy->op_busy) {
+ phy->status = BFA_STATUS_IOC_FAILURE;
+ phy->cbfn(phy->cbarg, phy->status);
+ phy->op_busy = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * Send phy attribute query request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_query_send(void *cbarg)
+{
+ struct bfa_phy_s *phy = cbarg;
+ struct bfi_phy_query_req_s *msg =
+ (struct bfi_phy_query_req_s *) phy->mb.msg;
+
+ msg->instance = phy->instance;
+ bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_QUERY_REQ,
+ bfa_ioc_portid(phy->ioc));
+ bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_attr_s), phy->dbuf_pa);
+ bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+}
+
+/*
+ * Send phy write request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_write_send(void *cbarg)
+{
+ struct bfa_phy_s *phy = cbarg;
+ struct bfi_phy_write_req_s *msg =
+ (struct bfi_phy_write_req_s *) phy->mb.msg;
+ u32 len;
+ u16 *buf, *dbuf;
+ int i, sz;
+
+ msg->instance = phy->instance;
+ msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
+ len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
+ phy->residue : BFA_PHY_DMA_BUF_SZ;
+ msg->length = cpu_to_be32(len);
+
+ /* indicate if it's the last msg of the whole write operation */
+ msg->last = (len == phy->residue) ? 1 : 0;
+
+ bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_WRITE_REQ,
+ bfa_ioc_portid(phy->ioc));
+ bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
+
+ buf = (u16 *) (phy->ubuf + phy->offset);
+ dbuf = (u16 *)phy->dbuf_kva;
+ sz = len >> 1;
+ for (i = 0; i < sz; i++)
+ buf[i] = cpu_to_be16(dbuf[i]);
+
+ bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+
+ phy->residue -= len;
+ phy->offset += len;
+}
+
+/*
+ * Send phy read request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_read_send(void *cbarg)
+{
+ struct bfa_phy_s *phy = cbarg;
+ struct bfi_phy_read_req_s *msg =
+ (struct bfi_phy_read_req_s *) phy->mb.msg;
+ u32 len;
+
+ msg->instance = phy->instance;
+ msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
+ len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
+ phy->residue : BFA_PHY_DMA_BUF_SZ;
+ msg->length = cpu_to_be32(len);
+ bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_READ_REQ,
+ bfa_ioc_portid(phy->ioc));
+ bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
+ bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+}
+
+/*
+ * Send phy stats request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_stats_send(void *cbarg)
+{
+ struct bfa_phy_s *phy = cbarg;
+ struct bfi_phy_stats_req_s *msg =
+ (struct bfi_phy_stats_req_s *) phy->mb.msg;
+
+ msg->instance = phy->instance;
+ bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_STATS_REQ,
+ bfa_ioc_portid(phy->ioc));
+ bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_stats_s), phy->dbuf_pa);
+ bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+}
+
+/*
+ * Flash memory info API.
+ *
+ * @param[in] mincfg - minimal cfg variable
+ */
+u32
+bfa_phy_meminfo(bfa_boolean_t mincfg)
+{
+ /* min driver doesn't need phy */
+ if (mincfg)
+ return 0;
+
+ return BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Flash attach API.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] ioc - ioc structure
+ * @param[in] dev - device structure
+ * @param[in] trcmod - trace module
+ * @param[in] logmod - log module
+ */
+void
+bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc, void *dev,
+ struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
+{
+ phy->ioc = ioc;
+ phy->trcmod = trcmod;
+ phy->cbfn = NULL;
+ phy->cbarg = NULL;
+ phy->op_busy = 0;
+
+ bfa_ioc_mbox_regisr(phy->ioc, BFI_MC_PHY, bfa_phy_intr, phy);
+ bfa_q_qe_init(&phy->ioc_notify);
+ bfa_ioc_notify_init(&phy->ioc_notify, bfa_phy_notify, phy);
+ list_add_tail(&phy->ioc_notify.qe, &phy->ioc->notify_q);
+
+ /* min driver doesn't need phy */
+ if (mincfg) {
+ phy->dbuf_kva = NULL;
+ phy->dbuf_pa = 0;
+ }
+}
+
+/*
+ * Claim memory for phy
+ *
+ * @param[in] phy - phy structure
+ * @param[in] dm_kva - pointer to virtual memory address
+ * @param[in] dm_pa - physical memory address
+ * @param[in] mincfg - minimal cfg variable
+ */
+void
+bfa_phy_memclaim(struct bfa_phy_s *phy, u8 *dm_kva, u64 dm_pa,
+ bfa_boolean_t mincfg)
+{
+ if (mincfg)
+ return;
+
+ phy->dbuf_kva = dm_kva;
+ phy->dbuf_pa = dm_pa;
+ memset(phy->dbuf_kva, 0, BFA_PHY_DMA_BUF_SZ);
+ dm_kva += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+ dm_pa += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+bfa_boolean_t
+bfa_phy_busy(struct bfa_ioc_s *ioc)
+{
+ void __iomem *rb;
+
+ rb = bfa_ioc_bar0(ioc);
+ return readl(rb + BFA_PHY_LOCK_STATUS);
+}
+
+/*
+ * Get phy attribute.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] attr - phy attribute structure
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance,
+ struct bfa_phy_attr_s *attr, bfa_cb_phy_t cbfn, void *cbarg)
+{
+ bfa_trc(phy, BFI_PHY_H2I_QUERY_REQ);
+ bfa_trc(phy, instance);
+
+ if (!bfa_phy_present(phy))
+ return BFA_STATUS_PHY_NOT_PRESENT;
+
+ if (!bfa_ioc_is_operational(phy->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+ bfa_trc(phy, phy->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ phy->op_busy = 1;
+ phy->cbfn = cbfn;
+ phy->cbarg = cbarg;
+ phy->instance = instance;
+ phy->ubuf = (uint8_t *) attr;
+ bfa_phy_query_send(phy);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Get phy stats.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] instance - phy image instance
+ * @param[in] stats - pointer to phy stats
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance,
+ struct bfa_phy_stats_s *stats,
+ bfa_cb_phy_t cbfn, void *cbarg)
+{
+ bfa_trc(phy, BFI_PHY_H2I_STATS_REQ);
+ bfa_trc(phy, instance);
+
+ if (!bfa_phy_present(phy))
+ return BFA_STATUS_PHY_NOT_PRESENT;
+
+ if (!bfa_ioc_is_operational(phy->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+ bfa_trc(phy, phy->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ phy->op_busy = 1;
+ phy->cbfn = cbfn;
+ phy->cbarg = cbarg;
+ phy->instance = instance;
+ phy->ubuf = (u8 *) stats;
+ bfa_phy_stats_send(phy);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Update phy image.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] instance - phy image instance
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_update(struct bfa_phy_s *phy, u8 instance,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_phy_t cbfn, void *cbarg)
+{
+ bfa_trc(phy, BFI_PHY_H2I_WRITE_REQ);
+ bfa_trc(phy, instance);
+ bfa_trc(phy, len);
+ bfa_trc(phy, offset);
+
+ if (!bfa_phy_present(phy))
+ return BFA_STATUS_PHY_NOT_PRESENT;
+
+ if (!bfa_ioc_is_operational(phy->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /* 'len' must be in word (4-byte) boundary */
+ if (!len || (len & 0x03))
+ return BFA_STATUS_FAILED;
+
+ if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+ bfa_trc(phy, phy->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ phy->op_busy = 1;
+ phy->cbfn = cbfn;
+ phy->cbarg = cbarg;
+ phy->instance = instance;
+ phy->residue = len;
+ phy->offset = 0;
+ phy->addr_off = offset;
+ phy->ubuf = buf;
+
+ bfa_phy_write_send(phy);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Read phy image.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] instance - phy image instance
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_read(struct bfa_phy_s *phy, u8 instance,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_phy_t cbfn, void *cbarg)
+{
+ bfa_trc(phy, BFI_PHY_H2I_READ_REQ);
+ bfa_trc(phy, instance);
+ bfa_trc(phy, len);
+ bfa_trc(phy, offset);
+
+ if (!bfa_phy_present(phy))
+ return BFA_STATUS_PHY_NOT_PRESENT;
+
+ if (!bfa_ioc_is_operational(phy->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /* 'len' must be in word (4-byte) boundary */
+ if (!len || (len & 0x03))
+ return BFA_STATUS_FAILED;
+
+ if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+ bfa_trc(phy, phy->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ phy->op_busy = 1;
+ phy->cbfn = cbfn;
+ phy->cbarg = cbarg;
+ phy->instance = instance;
+ phy->residue = len;
+ phy->offset = 0;
+ phy->addr_off = offset;
+ phy->ubuf = buf;
+ bfa_phy_read_send(phy);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Process phy response messages upon receiving interrupts.
+ *
+ * @param[in] phyarg - phy structure
+ * @param[in] msg - message structure
+ */
+void
+bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg)
+{
+ struct bfa_phy_s *phy = phyarg;
+ u32 status;
+
+ union {
+ struct bfi_phy_query_rsp_s *query;
+ struct bfi_phy_stats_rsp_s *stats;
+ struct bfi_phy_write_rsp_s *write;
+ struct bfi_phy_read_rsp_s *read;
+ struct bfi_mbmsg_s *msg;
+ } m;
+
+ m.msg = msg;
+ bfa_trc(phy, msg->mh.msg_id);
+
+ if (!phy->op_busy) {
+ /* receiving response after ioc failure */
+ bfa_trc(phy, 0x9999);
+ return;
+ }
+
+ switch (msg->mh.msg_id) {
+ case BFI_PHY_I2H_QUERY_RSP:
+ status = be32_to_cpu(m.query->status);
+ bfa_trc(phy, status);
+
+ if (status == BFA_STATUS_OK) {
+ struct bfa_phy_attr_s *attr =
+ (struct bfa_phy_attr_s *) phy->ubuf;
+ bfa_phy_ntoh32((u32 *)attr, (u32 *)phy->dbuf_kva,
+ sizeof(struct bfa_phy_attr_s));
+ bfa_trc(phy, attr->status);
+ bfa_trc(phy, attr->length);
+ }
+
+ phy->status = status;
+ phy->op_busy = 0;
+ if (phy->cbfn)
+ phy->cbfn(phy->cbarg, phy->status);
+ break;
+ case BFI_PHY_I2H_STATS_RSP:
+ status = be32_to_cpu(m.stats->status);
+ bfa_trc(phy, status);
+
+ if (status == BFA_STATUS_OK) {
+ struct bfa_phy_stats_s *stats =
+ (struct bfa_phy_stats_s *) phy->ubuf;
+ bfa_phy_ntoh32((u32 *)stats, (u32 *)phy->dbuf_kva,
+ sizeof(struct bfa_phy_stats_s));
+ bfa_trc(phy, stats->status);
+ }
+
+ phy->status = status;
+ phy->op_busy = 0;
+ if (phy->cbfn)
+ phy->cbfn(phy->cbarg, phy->status);
+ break;
+ case BFI_PHY_I2H_WRITE_RSP:
+ status = be32_to_cpu(m.write->status);
+ bfa_trc(phy, status);
+
+ if (status != BFA_STATUS_OK || phy->residue == 0) {
+ phy->status = status;
+ phy->op_busy = 0;
+ if (phy->cbfn)
+ phy->cbfn(phy->cbarg, phy->status);
+ } else {
+ bfa_trc(phy, phy->offset);
+ bfa_phy_write_send(phy);
+ }
+ break;
+ case BFI_PHY_I2H_READ_RSP:
+ status = be32_to_cpu(m.read->status);
+ bfa_trc(phy, status);
+
+ if (status != BFA_STATUS_OK) {
+ phy->status = status;
+ phy->op_busy = 0;
+ if (phy->cbfn)
+ phy->cbfn(phy->cbarg, phy->status);
+ } else {
+ u32 len = be32_to_cpu(m.read->length);
+ u16 *buf = (u16 *)(phy->ubuf + phy->offset);
+ u16 *dbuf = (u16 *)phy->dbuf_kva;
+ int i, sz = len >> 1;
+
+ bfa_trc(phy, phy->offset);
+ bfa_trc(phy, len);
+
+ for (i = 0; i < sz; i++)
+ buf[i] = be16_to_cpu(dbuf[i]);
+
+ phy->residue -= len;
+ phy->offset += len;
+
+ if (phy->residue == 0) {
+ phy->status = status;
+ phy->op_busy = 0;
+ if (phy->cbfn)
+ phy->cbfn(phy->cbarg, phy->status);
+ } else
+ bfa_phy_read_send(phy);
+ }
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index c85182a704fb..c5ecd2edc95d 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -85,12 +85,75 @@ struct bfa_sge_s {
#endif
/*
+ * BFA memory resources
+ */
+struct bfa_mem_dma_s {
+ struct list_head qe; /* Queue of DMA elements */
+ u32 mem_len; /* Total Length in Bytes */
+ u8 *kva; /* kernel virtual address */
+ u64 dma; /* dma address if DMA memory */
+ u8 *kva_curp; /* kva allocation cursor */
+ u64 dma_curp; /* dma allocation cursor */
+};
+#define bfa_mem_dma_t struct bfa_mem_dma_s
+
+struct bfa_mem_kva_s {
+ struct list_head qe; /* Queue of KVA elements */
+ u32 mem_len; /* Total Length in Bytes */
+ u8 *kva; /* kernel virtual address */
+ u8 *kva_curp; /* kva allocation cursor */
+};
+#define bfa_mem_kva_t struct bfa_mem_kva_s
+
+struct bfa_meminfo_s {
+ struct bfa_mem_dma_s dma_info;
+ struct bfa_mem_kva_s kva_info;
+};
+
+/* BFA memory segment setup macros */
+#define bfa_mem_dma_setup(_meminfo, _dm_ptr, _seg_sz) do { \
+ ((bfa_mem_dma_t *)(_dm_ptr))->mem_len = (_seg_sz); \
+ if (_seg_sz) \
+ list_add_tail(&((bfa_mem_dma_t *)_dm_ptr)->qe, \
+ &(_meminfo)->dma_info.qe); \
+} while (0)
+
+#define bfa_mem_kva_setup(_meminfo, _kva_ptr, _seg_sz) do { \
+ ((bfa_mem_kva_t *)(_kva_ptr))->mem_len = (_seg_sz); \
+ if (_seg_sz) \
+ list_add_tail(&((bfa_mem_kva_t *)_kva_ptr)->qe, \
+ &(_meminfo)->kva_info.qe); \
+} while (0)
+
+/* BFA dma memory segments iterator */
+#define bfa_mem_dma_sptr(_mod, _i) (&(_mod)->dma_seg[(_i)])
+#define bfa_mem_dma_seg_iter(_mod, _sptr, _nr, _i) \
+ for (_i = 0, _sptr = bfa_mem_dma_sptr(_mod, _i); _i < (_nr); \
+ _i++, _sptr = bfa_mem_dma_sptr(_mod, _i))
+
+#define bfa_mem_kva_curp(_mod) ((_mod)->kva_seg.kva_curp)
+#define bfa_mem_dma_virt(_sptr) ((_sptr)->kva_curp)
+#define bfa_mem_dma_phys(_sptr) ((_sptr)->dma_curp)
+#define bfa_mem_dma_len(_sptr) ((_sptr)->mem_len)
+
+/* Get the corresponding dma buf kva for a req - from the tag */
+#define bfa_mem_get_dmabuf_kva(_mod, _tag, _rqsz) \
+ (((u8 *)(_mod)->dma_seg[BFI_MEM_SEG_FROM_TAG(_tag, _rqsz)].kva_curp) +\
+ BFI_MEM_SEG_REQ_OFFSET(_tag, _rqsz) * (_rqsz))
+
+/* Get the corresponding dma buf pa for a req - from the tag */
+#define bfa_mem_get_dmabuf_pa(_mod, _tag, _rqsz) \
+ ((_mod)->dma_seg[BFI_MEM_SEG_FROM_TAG(_tag, _rqsz)].dma_curp + \
+ BFI_MEM_SEG_REQ_OFFSET(_tag, _rqsz) * (_rqsz))
+
+/*
* PCI device information required by IOC
*/
struct bfa_pcidev_s {
int pci_slot;
u8 pci_func;
u16 device_id;
+ u16 ssid;
void __iomem *pci_bar_kva;
};
@@ -112,18 +175,6 @@ struct bfa_dma_s {
#define BFI_SMEM_CB_SIZE 0x200000U /* ! 2MB for crossbow */
#define BFI_SMEM_CT_SIZE 0x280000U /* ! 2.5MB for catapult */
-
-#define bfa_dma_addr_set(dma_addr, pa) \
- __bfa_dma_addr_set(&dma_addr, (u64)pa)
-
-static inline void
-__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
-{
- dma_addr->a32.addr_lo = (__be32) pa;
- dma_addr->a32.addr_hi = (__be32) (pa >> 32);
-}
-
-
#define bfa_dma_be_addr_set(dma_addr, pa) \
__bfa_dma_be_addr_set(&dma_addr, (u64)pa)
static inline void
@@ -133,11 +184,22 @@ __bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
dma_addr->a32.addr_hi = cpu_to_be32(pa >> 32);
}
+#define bfa_alen_set(__alen, __len, __pa) \
+ __bfa_alen_set(__alen, __len, (u64)__pa)
+
+static inline void
+__bfa_alen_set(struct bfi_alen_s *alen, u32 len, u64 pa)
+{
+ alen->al_len = cpu_to_be32(len);
+ bfa_dma_be_addr_set(alen->al_addr, pa);
+}
+
struct bfa_ioc_regs_s {
void __iomem *hfn_mbox_cmd;
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;
@@ -199,18 +261,26 @@ struct bfa_ioc_cbfn_s {
};
/*
- * Heartbeat failure notification queue element.
+ * IOC event notification mechanism.
*/
-struct bfa_ioc_hbfail_notify_s {
+enum bfa_ioc_event_e {
+ BFA_IOC_E_ENABLED = 1,
+ BFA_IOC_E_DISABLED = 2,
+ BFA_IOC_E_FAILED = 3,
+};
+
+typedef void (*bfa_ioc_notify_cbfn_t)(void *, enum bfa_ioc_event_e);
+
+struct bfa_ioc_notify_s {
struct list_head qe;
- bfa_ioc_hbfail_cbfn_t cbfn;
+ bfa_ioc_notify_cbfn_t cbfn;
void *cbarg;
};
/*
- * Initialize a heartbeat failure notification structure
+ * Initialize a IOC event notification structure
*/
-#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do { \
+#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do { \
(__notify)->cbfn = (__cbfn); \
(__notify)->cbarg = (__cbarg); \
} while (0)
@@ -218,8 +288,9 @@ struct bfa_ioc_hbfail_notify_s {
struct bfa_iocpf_s {
bfa_fsm_t fsm;
struct bfa_ioc_s *ioc;
- u32 retry_count;
+ bfa_boolean_t fw_mismatch_notified;
bfa_boolean_t auto_recover;
+ u32 poll_time;
};
struct bfa_ioc_s {
@@ -231,17 +302,15 @@ struct bfa_ioc_s {
struct bfa_timer_s sem_timer;
struct bfa_timer_s hb_timer;
u32 hb_count;
- struct list_head hb_notify_q;
+ struct list_head notify_q;
void *dbg_fwsave;
int dbg_fwsave_len;
bfa_boolean_t dbg_fwsave_once;
- enum bfi_mclass ioc_mc;
+ enum bfi_pcifn_class clscode;
struct bfa_ioc_regs_s ioc_regs;
struct bfa_trc_mod_s *trcmod;
struct bfa_ioc_drv_stats_s stats;
bfa_boolean_t fcmode;
- bfa_boolean_t ctdev;
- bfa_boolean_t cna;
bfa_boolean_t pllinit;
bfa_boolean_t stats_busy; /* outstanding stats */
u8 port_id;
@@ -251,10 +320,17 @@ struct bfa_ioc_s {
struct bfa_ioc_mbox_mod_s mbox_mod;
struct bfa_ioc_hwif_s *ioc_hwif;
struct bfa_iocpf_s 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_s port_mode;
+ u8 ad_cap_bm; /* adapter cap bit mask */
+ u8 port_mode_cfg; /* config port mode */
};
struct bfa_ioc_hwif_s {
- bfa_status_t (*ioc_pll_init) (void __iomem *rb, bfa_boolean_t fcmode);
+ bfa_status_t (*ioc_pll_init) (void __iomem *rb, enum bfi_asic_mode m);
bfa_boolean_t (*ioc_firmware_lock) (struct bfa_ioc_s *ioc);
void (*ioc_firmware_unlock) (struct bfa_ioc_s *ioc);
void (*ioc_reg_init) (struct bfa_ioc_s *ioc);
@@ -268,12 +344,356 @@ struct bfa_ioc_hwif_s {
void (*ioc_sync_leave) (struct bfa_ioc_s *ioc);
void (*ioc_sync_ack) (struct bfa_ioc_s *ioc);
bfa_boolean_t (*ioc_sync_complete) (struct bfa_ioc_s *ioc);
+ bfa_boolean_t (*ioc_lpu_read_stat) (struct bfa_ioc_s *ioc);
+};
+
+/*
+ * Queue element to wait for room in request queue. FIFO order is
+ * maintained when fullfilling requests.
+ */
+struct bfa_reqq_wait_s {
+ struct list_head qe;
+ void (*qresume) (void *cbarg);
+ void *cbarg;
+};
+
+typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+
+/*
+ * Generic BFA callback element.
+ */
+struct bfa_cb_qe_s {
+ struct list_head qe;
+ bfa_cb_cbfn_t cbfn;
+ bfa_boolean_t once;
+ void *cbarg;
+};
+
+/*
+ * ASIC block configurtion related
+ */
+
+typedef void (*bfa_ablk_cbfn_t)(void *, enum bfa_status);
+
+struct bfa_ablk_s {
+ struct bfa_ioc_s *ioc;
+ struct bfa_ablk_cfg_s *cfg;
+ u16 *pcifn;
+ struct bfa_dma_s dma_addr;
+ bfa_boolean_t busy;
+ struct bfa_mbox_cmd_s mb;
+ bfa_ablk_cbfn_t cbfn;
+ void *cbarg;
+ struct bfa_ioc_notify_s ioc_notify;
+ struct bfa_mem_dma_s ablk_dma;
+};
+#define BFA_MEM_ABLK_DMA(__bfa) (&((__bfa)->modules.ablk.ablk_dma))
+
+/*
+ * SFP module specific
+ */
+typedef void (*bfa_cb_sfp_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_sfp_s {
+ void *dev;
+ struct bfa_ioc_s *ioc;
+ struct bfa_trc_mod_s *trcmod;
+ struct sfp_mem_s *sfpmem;
+ bfa_cb_sfp_t cbfn;
+ void *cbarg;
+ enum bfi_sfp_mem_e memtype; /* mem access type */
+ u32 status;
+ struct bfa_mbox_cmd_s mbcmd;
+ u8 *dbuf_kva; /* dma buf virtual address */
+ u64 dbuf_pa; /* dma buf physical address */
+ struct bfa_ioc_notify_s ioc_notify;
+ enum bfa_defs_sfp_media_e *media;
+ enum bfa_port_speed portspeed;
+ bfa_cb_sfp_t state_query_cbfn;
+ void *state_query_cbarg;
+ u8 lock;
+ u8 data_valid; /* data in dbuf is valid */
+ u8 state; /* sfp state */
+ u8 state_query_lock;
+ struct bfa_mem_dma_s sfp_dma;
+ u8 is_elb; /* eloopback */
+};
+
+#define BFA_SFP_MOD(__bfa) (&(__bfa)->modules.sfp)
+#define BFA_MEM_SFP_DMA(__bfa) (&(BFA_SFP_MOD(__bfa)->sfp_dma))
+
+u32 bfa_sfp_meminfo(void);
+
+void bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc,
+ void *dev, struct bfa_trc_mod_s *trcmod);
+
+void bfa_sfp_memclaim(struct bfa_sfp_s *diag, u8 *dm_kva, u64 dm_pa);
+void bfa_sfp_intr(void *bfaarg, struct bfi_mbmsg_s *msg);
+
+bfa_status_t bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem,
+ bfa_cb_sfp_t cbfn, void *cbarg);
+
+bfa_status_t bfa_sfp_media(struct bfa_sfp_s *sfp,
+ enum bfa_defs_sfp_media_e *media,
+ bfa_cb_sfp_t cbfn, void *cbarg);
+
+bfa_status_t bfa_sfp_speed(struct bfa_sfp_s *sfp,
+ enum bfa_port_speed portspeed,
+ bfa_cb_sfp_t cbfn, void *cbarg);
+
+/*
+ * Flash module specific
+ */
+typedef void (*bfa_cb_flash_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_flash_s {
+ struct bfa_ioc_s *ioc; /* back pointer to ioc */
+ struct bfa_trc_mod_s *trcmod;
+ u32 type; /* partition type */
+ u8 instance; /* partition instance */
+ u8 rsv[3];
+ u32 op_busy; /* operation busy flag */
+ u32 residue; /* residual length */
+ u32 offset; /* offset */
+ bfa_status_t status; /* status */
+ u8 *dbuf_kva; /* dma buf virtual address */
+ u64 dbuf_pa; /* dma buf physical address */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ bfa_cb_flash_t cbfn; /* user callback function */
+ void *cbarg; /* user callback arg */
+ u8 *ubuf; /* user supplied buffer */
+ struct bfa_cb_qe_s hcb_qe; /* comp: BFA callback qelem */
+ u32 addr_off; /* partition address offset */
+ struct bfa_mbox_cmd_s mb; /* mailbox */
+ struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */
+ struct bfa_mem_dma_s flash_dma;
+};
+
+#define BFA_FLASH(__bfa) (&(__bfa)->modules.flash)
+#define BFA_MEM_FLASH_DMA(__bfa) (&(BFA_FLASH(__bfa)->flash_dma))
+
+bfa_status_t bfa_flash_get_attr(struct bfa_flash_s *flash,
+ struct bfa_flash_attr_s *attr,
+ bfa_cb_flash_t cbfn, void *cbarg);
+bfa_status_t bfa_flash_erase_part(struct bfa_flash_s *flash,
+ enum bfa_flash_part_type type, u8 instance,
+ bfa_cb_flash_t cbfn, void *cbarg);
+bfa_status_t bfa_flash_update_part(struct bfa_flash_s *flash,
+ enum bfa_flash_part_type type, u8 instance,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_flash_t cbfn, void *cbarg);
+bfa_status_t bfa_flash_read_part(struct bfa_flash_s *flash,
+ enum bfa_flash_part_type type, u8 instance, void *buf,
+ u32 len, u32 offset, bfa_cb_flash_t cbfn, void *cbarg);
+u32 bfa_flash_meminfo(bfa_boolean_t mincfg);
+void bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc,
+ void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
+void bfa_flash_memclaim(struct bfa_flash_s *flash,
+ u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
+
+/*
+ * DIAG module specific
+ */
+
+typedef void (*bfa_cb_diag_t) (void *cbarg, bfa_status_t status);
+typedef void (*bfa_cb_diag_beacon_t) (void *dev, bfa_boolean_t beacon,
+ bfa_boolean_t link_e2e_beacon);
+
+/*
+ * Firmware ping test results
+ */
+struct bfa_diag_results_fwping {
+ u32 data; /* store the corrupted data */
+ u32 status;
+ u32 dmastatus;
+ u8 rsvd[4];
+};
+
+struct bfa_diag_qtest_result_s {
+ u32 status;
+ u16 count; /* sucessful queue test count */
+ u8 queue;
+ u8 rsvd; /* 64-bit align */
+};
+
+/*
+ * Firmware ping test results
+ */
+struct bfa_diag_fwping_s {
+ struct bfa_diag_results_fwping *result;
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+ u32 data;
+ u8 lock;
+ u8 rsv[3];
+ u32 status;
+ u32 count;
+ struct bfa_mbox_cmd_s mbcmd;
+ u8 *dbuf_kva; /* dma buf virtual address */
+ u64 dbuf_pa; /* dma buf physical address */
+};
+
+/*
+ * Temperature sensor query results
+ */
+struct bfa_diag_results_tempsensor_s {
+ u32 status;
+ u16 temp; /* 10-bit A/D value */
+ u16 brd_temp; /* 9-bit board temp */
+ u8 ts_junc; /* show junction tempsensor */
+ u8 ts_brd; /* show board tempsensor */
+ u8 rsvd[6]; /* keep 8 bytes alignment */
+};
+
+struct bfa_diag_tsensor_s {
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+ struct bfa_diag_results_tempsensor_s *temp;
+ u8 lock;
+ u8 rsv[3];
+ u32 status;
+ struct bfa_mbox_cmd_s mbcmd;
};
+struct bfa_diag_sfpshow_s {
+ struct sfp_mem_s *sfpmem;
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+ u8 lock;
+ u8 static_data;
+ u8 rsv[2];
+ u32 status;
+ struct bfa_mbox_cmd_s mbcmd;
+ u8 *dbuf_kva; /* dma buf virtual address */
+ u64 dbuf_pa; /* dma buf physical address */
+};
+
+struct bfa_diag_led_s {
+ struct bfa_mbox_cmd_s mbcmd;
+ bfa_boolean_t lock; /* 1: ledtest is operating */
+};
+
+struct bfa_diag_beacon_s {
+ struct bfa_mbox_cmd_s mbcmd;
+ bfa_boolean_t state; /* port beacon state */
+ bfa_boolean_t link_e2e; /* link beacon state */
+};
+
+struct bfa_diag_s {
+ void *dev;
+ struct bfa_ioc_s *ioc;
+ struct bfa_trc_mod_s *trcmod;
+ struct bfa_diag_fwping_s fwping;
+ struct bfa_diag_tsensor_s tsensor;
+ struct bfa_diag_sfpshow_s sfpshow;
+ struct bfa_diag_led_s ledtest;
+ struct bfa_diag_beacon_s beacon;
+ void *result;
+ struct bfa_timer_s timer;
+ bfa_cb_diag_beacon_t cbfn_beacon;
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+ u8 block;
+ u8 timer_active;
+ u8 rsvd[2];
+ u32 status;
+ struct bfa_ioc_notify_s ioc_notify;
+ struct bfa_mem_dma_s diag_dma;
+};
+
+#define BFA_DIAG_MOD(__bfa) (&(__bfa)->modules.diag_mod)
+#define BFA_MEM_DIAG_DMA(__bfa) (&(BFA_DIAG_MOD(__bfa)->diag_dma))
+
+u32 bfa_diag_meminfo(void);
+void bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa);
+void bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
+ bfa_cb_diag_beacon_t cbfn_beacon,
+ struct bfa_trc_mod_s *trcmod);
+bfa_status_t bfa_diag_reg_read(struct bfa_diag_s *diag, u32 offset,
+ u32 len, u32 *buf, u32 force);
+bfa_status_t bfa_diag_reg_write(struct bfa_diag_s *diag, u32 offset,
+ u32 len, u32 value, u32 force);
+bfa_status_t bfa_diag_tsensor_query(struct bfa_diag_s *diag,
+ struct bfa_diag_results_tempsensor_s *result,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt,
+ u32 pattern, struct bfa_diag_results_fwping *result,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_diag_sfpshow(struct bfa_diag_s *diag,
+ struct sfp_mem_s *sfpmem, u8 static_data,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_diag_memtest(struct bfa_diag_s *diag,
+ struct bfa_diag_memtest_s *memtest, u32 pattern,
+ struct bfa_diag_memtest_result *result,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_diag_ledtest(struct bfa_diag_s *diag,
+ struct bfa_diag_ledtest_s *ledtest);
+bfa_status_t bfa_diag_beacon_port(struct bfa_diag_s *diag,
+ bfa_boolean_t beacon, bfa_boolean_t link_e2e_beacon,
+ u32 sec);
+
+/*
+ * PHY module specific
+ */
+typedef void (*bfa_cb_phy_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_phy_s {
+ struct bfa_ioc_s *ioc; /* back pointer to ioc */
+ struct bfa_trc_mod_s *trcmod; /* trace module */
+ u8 instance; /* port instance */
+ u8 op_busy; /* operation busy flag */
+ u8 rsv[2];
+ u32 residue; /* residual length */
+ u32 offset; /* offset */
+ bfa_status_t status; /* status */
+ u8 *dbuf_kva; /* dma buf virtual address */
+ u64 dbuf_pa; /* dma buf physical address */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ bfa_cb_phy_t cbfn; /* user callback function */
+ void *cbarg; /* user callback arg */
+ u8 *ubuf; /* user supplied buffer */
+ struct bfa_cb_qe_s hcb_qe; /* comp: BFA callback qelem */
+ u32 addr_off; /* phy address offset */
+ struct bfa_mbox_cmd_s mb; /* mailbox */
+ struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */
+ struct bfa_mem_dma_s phy_dma;
+};
+
+#define BFA_PHY(__bfa) (&(__bfa)->modules.phy)
+#define BFA_MEM_PHY_DMA(__bfa) (&(BFA_PHY(__bfa)->phy_dma))
+
+bfa_boolean_t bfa_phy_busy(struct bfa_ioc_s *ioc);
+bfa_status_t bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance,
+ struct bfa_phy_attr_s *attr,
+ bfa_cb_phy_t cbfn, void *cbarg);
+bfa_status_t bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance,
+ struct bfa_phy_stats_s *stats,
+ bfa_cb_phy_t cbfn, void *cbarg);
+bfa_status_t bfa_phy_update(struct bfa_phy_s *phy, u8 instance,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_phy_t cbfn, void *cbarg);
+bfa_status_t bfa_phy_read(struct bfa_phy_s *phy, u8 instance,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_phy_t cbfn, void *cbarg);
+
+u32 bfa_phy_meminfo(bfa_boolean_t mincfg);
+void bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc,
+ void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
+void bfa_phy_memclaim(struct bfa_phy_s *phy,
+ u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
+void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg);
+
+/*
+ * IOC specfic macros
+ */
#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_is_cna(__ioc) \
+ ((bfa_ioc_get_type(__ioc) == BFA_IOC_TYPE_FCoE) || \
+ (bfa_ioc_get_type(__ioc) == BFA_IOC_TYPE_LL))
#define bfa_ioc_fetch_stats(__ioc, __stats) \
(((__stats)->drv_stats) = (__ioc)->stats)
#define bfa_ioc_clr_stats(__ioc) \
@@ -287,12 +707,9 @@ struct bfa_ioc_hwif_s {
#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++)
#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)
+#define BFA_IOC_FW_SMEM_SIZE(__ioc) \
+ ((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)
@@ -305,7 +722,7 @@ void bfa_ioc_mbox_register(struct bfa_ioc_s *ioc,
bfa_ioc_mbox_mcfunc_t *mcfuncs);
void bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc);
void bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len);
-void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);
+bfa_boolean_t bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);
void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
@@ -315,40 +732,49 @@ void bfa_ioc_mbox_regisr(struct bfa_ioc_s *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))
bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
-bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode);
-bfa_boolean_t bfa_ioc_ct_pll_init_complete(void __iomem *rb);
-bfa_status_t bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode);
+bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode mode);
+bfa_status_t bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode);
+bfa_status_t bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode 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_get_fcmode(__ioc) ((__ioc)->fcmode)
+#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_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc);
+void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
+void bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc);
+void bfa_ioc_ct2_poweron(struct bfa_ioc_s *ioc);
void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);
void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
void bfa_ioc_detach(struct bfa_ioc_s *ioc);
void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
- enum bfi_mclass mc);
+ enum bfi_pcifn_class clscode);
void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa);
void bfa_ioc_enable(struct bfa_ioc_s *ioc);
void bfa_ioc_disable(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
- u32 boot_param);
+ u32 boot_env);
void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_acq_addr(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
void bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc);
@@ -372,8 +798,6 @@ bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
int *trclen);
bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
u32 *offset, int *buflen);
-void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
-bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg);
void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,
struct bfi_ioc_image_hdr_s *fwhdr);
@@ -383,6 +807,33 @@ bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
/*
+ * asic block configuration related APIs
+ */
+u32 bfa_ablk_meminfo(void);
+void bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa);
+void bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc);
+bfa_status_t bfa_ablk_query(struct bfa_ablk_s *ablk,
+ struct bfa_ablk_cfg_s *ablk_cfg,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_adapter_config(struct bfa_ablk_s *ablk,
+ enum bfa_mode_s mode, int max_pf, int max_vf,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port,
+ enum bfa_mode_s mode, int max_pf, int max_vf,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
+ u8 port, enum bfi_pcifn_class personality, int bw,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_optrom_en(struct bfa_ablk_s *ablk,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk,
+ bfa_ablk_cbfn_t cbfn, void *cbarg);
+
+/*
* bfa mfg wwn API functions
*/
mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc);
@@ -391,50 +842,64 @@ mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc);
/*
* F/W Image Size & Chunk
*/
-extern u32 bfi_image_ct_fc_size;
-extern u32 bfi_image_ct_cna_size;
-extern u32 bfi_image_cb_fc_size;
-extern u32 *bfi_image_ct_fc;
-extern u32 *bfi_image_ct_cna;
-extern u32 *bfi_image_cb_fc;
+extern u32 bfi_image_cb_size;
+extern u32 bfi_image_ct_size;
+extern u32 bfi_image_ct2_size;
+extern u32 *bfi_image_cb;
+extern u32 *bfi_image_ct;
+extern u32 *bfi_image_ct2;
static inline u32 *
-bfi_image_ct_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_fc + off); }
+bfi_image_cb_get_chunk(u32 off)
+{
+ return (u32 *)(bfi_image_cb + off);
+}
static inline u32 *
-bfi_image_ct_cna_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_cna + off); }
+bfi_image_ct_get_chunk(u32 off)
+{
+ return (u32 *)(bfi_image_ct + off);
+}
static inline u32 *
-bfi_image_cb_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_cb_fc + off); }
+bfi_image_ct2_get_chunk(u32 off)
+{
+ return (u32 *)(bfi_image_ct2 + off);
+}
static inline u32*
-bfa_cb_image_get_chunk(int type, u32 off)
+bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off)
{
- switch (type) {
- case BFI_IMAGE_CT_FC:
- return bfi_image_ct_fc_get_chunk(off); break;
- case BFI_IMAGE_CT_CNA:
- return bfi_image_ct_cna_get_chunk(off); break;
- case BFI_IMAGE_CB_FC:
- return bfi_image_cb_fc_get_chunk(off); break;
- default: return NULL;
+ switch (asic_gen) {
+ case BFI_ASIC_GEN_CB:
+ return bfi_image_cb_get_chunk(off);
+ break;
+ case BFI_ASIC_GEN_CT:
+ return bfi_image_ct_get_chunk(off);
+ break;
+ case BFI_ASIC_GEN_CT2:
+ return bfi_image_ct2_get_chunk(off);
+ break;
+ default:
+ return NULL;
}
}
static inline u32
-bfa_cb_image_get_size(int type)
+bfa_cb_image_get_size(enum bfi_asic_gen asic_gen)
{
- switch (type) {
- case BFI_IMAGE_CT_FC:
- return bfi_image_ct_fc_size; break;
- case BFI_IMAGE_CT_CNA:
- return bfi_image_ct_cna_size; break;
- case BFI_IMAGE_CB_FC:
- return bfi_image_cb_fc_size; break;
- default: return 0;
+ switch (asic_gen) {
+ case BFI_ASIC_GEN_CB:
+ return bfi_image_cb_size;
+ break;
+ case BFI_ASIC_GEN_CT:
+ return bfi_image_ct_size;
+ break;
+ case BFI_ASIC_GEN_CT2:
+ return bfi_image_ct2_size;
+ break;
+ default:
+ return 0;
}
}
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 89ae4c8f95a2..30df8a284715 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -17,7 +17,7 @@
#include "bfad_drv.h"
#include "bfa_ioc.h"
-#include "bfi_cbreg.h"
+#include "bfi_reg.h"
#include "bfa_defs.h"
BFA_TRC_FILE(CNA, IOC_CB);
@@ -69,21 +69,6 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
static bfa_boolean_t
bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
{
- struct bfi_ioc_image_hdr_s fwhdr;
- uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate);
-
- if (fwstate == BFI_IOC_UNINIT)
- return BFA_TRUE;
-
- bfa_ioc_fwver_get(ioc, &fwhdr);
-
- if (swab32(fwhdr.exec) == BFI_BOOT_TYPE_NORMAL)
- return BFA_TRUE;
-
- bfa_trc(ioc, fwstate);
- bfa_trc(ioc, fwhdr.exec);
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
-
return BFA_TRUE;
}
@@ -98,7 +83,7 @@ bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)
static void
bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)
{
- writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
+ writel(~0U, ioc->ioc_regs.err_set);
readl(ioc->ioc_regs.err_set);
}
@@ -152,8 +137,8 @@ bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
*/
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_400_CTL_REG);
- ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_212_CTL_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
@@ -285,18 +270,18 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
}
bfa_status_t
-bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
+bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
{
u32 pll_sclk, pll_fclk;
- pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
- __APP_PLL_212_P0_1(3U) |
- __APP_PLL_212_JITLMT0_1(3U) |
- __APP_PLL_212_CNTLMT0_1(3U);
- pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
- __APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
- __APP_PLL_400_JITLMT0_1(3U) |
- __APP_PLL_400_CNTLMT0_1(3U);
+ pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN |
+ __APP_PLL_SCLK_P0_1(3U) |
+ __APP_PLL_SCLK_JITLMT0_1(3U) |
+ __APP_PLL_SCLK_CNTLMT0_1(3U);
+ pll_fclk = __APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN |
+ __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
+ __APP_PLL_LCLK_JITLMT0_1(3U) |
+ __APP_PLL_LCLK_CNTLMT0_1(3U);
writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
@@ -305,24 +290,24 @@ bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
- writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG);
- writel(__APP_PLL_212_BYPASS | __APP_PLL_212_LOGIC_SOFT_RESET,
- rb + APP_PLL_212_CTL_REG);
- writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG);
- writel(__APP_PLL_400_BYPASS | __APP_PLL_400_LOGIC_SOFT_RESET,
- rb + APP_PLL_400_CTL_REG);
+ writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
+ writel(__APP_PLL_SCLK_BYPASS | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
+ rb + APP_PLL_SCLK_CTL_REG);
+ writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
+ writel(__APP_PLL_LCLK_BYPASS | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
+ rb + APP_PLL_LCLK_CTL_REG);
udelay(2);
- writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG);
- writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG);
- writel(pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET,
- rb + APP_PLL_212_CTL_REG);
- writel(pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET,
- rb + APP_PLL_400_CTL_REG);
+ writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
+ writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
+ 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);
udelay(2000);
writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
- writel(pll_sclk, (rb + APP_PLL_212_CTL_REG));
- writel(pll_fclk, (rb + APP_PLL_400_CTL_REG));
+ writel(pll_sclk, (rb + APP_PLL_SCLK_CTL_REG));
+ writel(pll_fclk, (rb + APP_PLL_LCLK_CTL_REG));
return BFA_STATUS_OK;
}
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 93612520f0d2..d1b8f0caaa79 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -17,7 +17,7 @@
#include "bfad_drv.h"
#include "bfa_ioc.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
#include "bfa_defs.h"
BFA_TRC_FILE(CNA, IOC_CT);
@@ -36,9 +36,6 @@ BFA_TRC_FILE(CNA, IOC_CT);
*/
static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc);
-static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc);
-static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc);
-static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc);
@@ -48,29 +45,7 @@ static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
static struct bfa_ioc_hwif_s hwif_ct;
-
-/*
- * Called from bfa_ioc_attach() to map asic specific calls.
- */
-void
-bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc)
-{
- hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
- hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
- hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
- hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
- hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
- hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
- hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
- hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
- hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
- hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
- hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
- hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
- hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
-
- ioc->ioc_hwif = &hwif_ct;
-}
+static struct bfa_ioc_hwif_s hwif_ct2;
/*
* Return true if firmware of current driver matches the running firmware.
@@ -83,15 +58,9 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
struct bfi_ioc_image_hdr_s fwhdr;
/*
- * Firmware match check is relevant only for CNA.
- */
- if (!ioc->cna)
- return BFA_TRUE;
-
- /*
* If bios boot (flash based) -- do not increment usage count
*/
- if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+ if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
BFA_IOC_FWIMG_MINSZ)
return BFA_TRUE;
@@ -103,6 +72,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
*/
if (usecnt == 0) {
writel(1, ioc->ioc_regs.ioc_usage_reg);
+ readl(ioc->ioc_regs.ioc_usage_sem_reg);
writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
writel(0, ioc->ioc_regs.ioc_fail_sync);
bfa_trc(ioc, usecnt);
@@ -122,6 +92,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
*/
bfa_ioc_fwver_get(ioc, &fwhdr);
if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
+ readl(ioc->ioc_regs.ioc_usage_sem_reg);
writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
bfa_trc(ioc, usecnt);
return BFA_FALSE;
@@ -132,6 +103,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
*/
usecnt++;
writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+ readl(ioc->ioc_regs.ioc_usage_sem_reg);
writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
bfa_trc(ioc, usecnt);
return BFA_TRUE;
@@ -143,15 +115,9 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *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)) <
+ if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
BFA_IOC_FWIMG_MINSZ)
return;
@@ -166,6 +132,7 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
bfa_trc(ioc, usecnt);
+ readl(ioc->ioc_regs.ioc_usage_sem_reg);
writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
}
@@ -175,14 +142,14 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
static void
bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)
{
- if (ioc->cna) {
+ if (bfa_ioc_is_cna(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);
} else {
- writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
+ writel(~0U, ioc->ioc_regs.err_set);
readl(ioc->ioc_regs.err_set);
}
}
@@ -190,7 +157,7 @@ bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)
/*
* Host to LPU mailbox message addresses
*/
-static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
+static struct { u32 hfn_mbox, lpu_mbox, 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 },
@@ -200,21 +167,31 @@ static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
/*
* 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 }
+static struct { u32 hfn, 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 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 struct { u32 hfn, 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 struct { uint32_t hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu, 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
@@ -225,24 +202,24 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *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;
+ 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 + iocreg_mbcmd_p0[pcifn].hfn;
- ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
+ 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 + iocreg_mbcmd_p1[pcifn].hfn;
- ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
+ 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;
}
@@ -252,8 +229,8 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
*/
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->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
@@ -276,6 +253,64 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
}
+static void
+bfa_ioc_ct2_reg_init(struct bfa_ioc_s *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.
*/
@@ -298,6 +333,19 @@ bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc)
bfa_trc(ioc, ioc->port_id);
}
+static void
+bfa_ioc_ct2_map_port(struct bfa_ioc_s *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);
+
+ bfa_trc(ioc, bfa_ioc_pcifn(ioc));
+ bfa_trc(ioc, ioc->port_id);
+}
+
/*
* Set interrupt mode for a function: INTX or MSIX
*/
@@ -316,7 +364,7 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
/*
* If already in desired mode, do not change anything
*/
- if (!msix && mode)
+ if ((!msix && mode) || (msix && !mode))
return;
if (msix)
@@ -331,6 +379,20 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
writel(r32, rb + FNC_PERS_REG);
}
+bfa_boolean_t
+bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc_s *ioc)
+{
+ u32 r32;
+
+ r32 = readl(ioc->ioc_regs.lpu_read_stat);
+ if (r32) {
+ writel(1, ioc->ioc_regs.lpu_read_stat);
+ return BFA_TRUE;
+ }
+
+ return BFA_FALSE;
+}
+
/*
* Cleanup hw semaphore and usecnt registers
*/
@@ -338,9 +400,10 @@ static void
bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
{
- if (ioc->cna) {
+ if (bfa_ioc_is_cna(ioc)) {
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
writel(0, ioc->ioc_regs.ioc_usage_reg);
+ readl(ioc->ioc_regs.ioc_usage_sem_reg);
writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
}
@@ -449,32 +512,99 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc)
return BFA_FALSE;
}
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+static void
+bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif)
+{
+ hwif->ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
+ hwif->ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
+ hwif->ioc_notify_fail = bfa_ioc_ct_notify_fail;
+ hwif->ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+ hwif->ioc_sync_start = bfa_ioc_ct_sync_start;
+ hwif->ioc_sync_join = bfa_ioc_ct_sync_join;
+ hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave;
+ hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack;
+ hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete;
+}
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc)
+{
+ bfa_ioc_set_ctx_hwif(ioc, &hwif_ct);
+
+ hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
+ hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
+ hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
+ hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
+ ioc->ioc_hwif = &hwif_ct;
+}
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc)
+{
+ bfa_ioc_set_ctx_hwif(ioc, &hwif_ct2);
+
+ hwif_ct2.ioc_pll_init = bfa_ioc_ct2_pll_init;
+ hwif_ct2.ioc_reg_init = bfa_ioc_ct2_reg_init;
+ hwif_ct2.ioc_map_port = bfa_ioc_ct2_map_port;
+ hwif_ct2.ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat;
+ hwif_ct2.ioc_isr_mode_set = NULL;
+ ioc->ioc_hwif = &hwif_ct2;
+}
+
/*
- * Check the firmware state to know if pll_init has been completed already
+ * Workaround for MSI-X resource allocation for catapult-2 with no asic block
*/
-bfa_boolean_t
-bfa_ioc_ct_pll_init_complete(void __iomem *rb)
+#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_ioc_ct2_poweron(struct bfa_ioc_s *ioc)
{
- if ((readl(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) ||
- (readl(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP))
- return BFA_TRUE;
+ void __iomem *rb = ioc->pcidev.pci_bar_kva;
+ u32 r32;
- return BFA_FALSE;
+ 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);
}
bfa_status_t
-bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
+bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
{
u32 pll_sclk, pll_fclk, r32;
+ bfa_boolean_t fcmode = (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);
- 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 |
@@ -491,20 +621,21 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
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);
+ 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_312_ENABLE, rb + APP_PLL_312_CTL_REG);
- writel(pll_fclk | __APP_PLL_425_ENABLE, rb + APP_PLL_425_CTL_REG);
+ 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));
@@ -524,3 +655,206 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
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);
+}
+
+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));
+}
+
+void
+bfa_ioc_ct2_mac_reset(void __iomem *rb)
+{
+ 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
+bfa_status_t
+bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
+{
+ 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.
+ */
+ 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/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index ab79ff6fdeea..1c6efd40a673 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -29,14 +29,21 @@
#include "bfa_port.h"
struct bfa_modules_s {
+ struct bfa_fcdiag_s fcdiag; /* fcdiag module */
struct bfa_fcport_s fcport; /* fc port module */
struct bfa_fcxp_mod_s fcxp_mod; /* fcxp module */
struct bfa_lps_mod_s lps_mod; /* fcxp module */
struct bfa_uf_mod_s uf_mod; /* unsolicited frame module */
struct bfa_rport_mod_s rport_mod; /* remote port module */
- struct bfa_fcpim_mod_s fcpim_mod; /* FCP initiator module */
+ struct bfa_fcp_mod_s fcp_mod; /* FCP initiator module */
struct bfa_sgpg_mod_s sgpg_mod; /* SG page module */
struct bfa_port_s port; /* Physical port module */
+ struct bfa_ablk_s ablk; /* ASIC block config module */
+ struct bfa_cee_s cee; /* CEE Module */
+ struct bfa_sfp_s sfp; /* SFP module */
+ struct bfa_flash_s flash; /* flash module */
+ struct bfa_diag_s diag_mod; /* diagnostics module */
+ struct bfa_phy_s phy; /* phy module */
};
/*
@@ -51,17 +58,16 @@ enum {
BFA_TRC_HAL_IOCFC_CB = 5,
};
-
/*
* Macro to define a new BFA module
*/
#define BFA_MODULE(__mod) \
static void bfa_ ## __mod ## _meminfo( \
- struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, \
- u32 *dm_len); \
+ struct bfa_iocfc_cfg_s *cfg, \
+ struct bfa_meminfo_s *meminfo, \
+ struct bfa_s *bfa); \
static void bfa_ ## __mod ## _attach(struct bfa_s *bfa, \
void *bfad, struct bfa_iocfc_cfg_s *cfg, \
- struct bfa_meminfo_s *meminfo, \
struct bfa_pcidev_s *pcidev); \
static void bfa_ ## __mod ## _detach(struct bfa_s *bfa); \
static void bfa_ ## __mod ## _start(struct bfa_s *bfa); \
@@ -87,11 +93,11 @@ enum {
* can leave entry points as NULL)
*/
struct bfa_module_s {
- void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len);
+ void (*meminfo) (struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo,
+ struct bfa_s *bfa);
void (*attach) (struct bfa_s *bfa, void *bfad,
struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
void (*detach) (struct bfa_s *bfa);
void (*start) (struct bfa_s *bfa);
@@ -109,19 +115,20 @@ struct bfa_s {
struct bfa_timer_mod_s timer_mod; /* timer module */
struct bfa_modules_s modules; /* BFA modules */
struct list_head comp_q; /* pending completions */
- bfa_boolean_t rme_process; /* RME processing enabled */
+ bfa_boolean_t queue_process; /* queue processing enabled */
struct list_head reqq_waitq[BFI_IOC_MAX_CQS];
bfa_boolean_t fcs; /* FCS is attached to BFA */
struct bfa_msix_s msix;
};
extern bfa_boolean_t bfa_auto_recover;
+extern struct bfa_module_s hal_mod_fcdiag;
extern struct bfa_module_s hal_mod_sgpg;
extern struct bfa_module_s hal_mod_fcport;
extern struct bfa_module_s hal_mod_fcxp;
extern struct bfa_module_s hal_mod_lps;
extern struct bfa_module_s hal_mod_uf;
extern struct bfa_module_s hal_mod_rport;
-extern struct bfa_module_s hal_mod_fcpim;
+extern struct bfa_module_s hal_mod_fcp;
#endif /* __BFA_MODULES_H__ */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index 3f8e9d6066ec..95e4ad8759ac 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -24,8 +24,6 @@
BFA_TRC_FILE(CNA, PORT);
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-
static void
bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
{
@@ -236,6 +234,12 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
{
struct bfi_port_generic_req_s *m;
+ /* If port is PBC disabled, return error */
+ if (port->pbc_disabled) {
+ bfa_trc(port, BFA_STATUS_PBC);
+ return BFA_STATUS_PBC;
+ }
+
if (bfa_ioc_is_disabled(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_DISABLED);
return BFA_STATUS_IOC_DISABLED;
@@ -280,6 +284,12 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
{
struct bfi_port_generic_req_s *m;
+ /* If port is PBC disabled, return error */
+ if (port->pbc_disabled) {
+ bfa_trc(port, BFA_STATUS_PBC);
+ return BFA_STATUS_PBC;
+ }
+
if (bfa_ioc_is_disabled(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_DISABLED);
return BFA_STATUS_IOC_DISABLED;
@@ -387,32 +397,43 @@ bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
}
/*
- * bfa_port_hbfail()
+ * bfa_port_notify()
*
+ * Port module IOC event handler
*
* @param[in] Pointer to the Port module data structure.
+ * @param[in] IOC event structure
*
* @return void
*/
void
-bfa_port_hbfail(void *arg)
+bfa_port_notify(void *arg, enum bfa_ioc_event_e event)
{
struct bfa_port_s *port = (struct bfa_port_s *) arg;
- /* Fail any pending get_stats/clear_stats requests */
- if (port->stats_busy) {
- if (port->stats_cbfn)
- port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED);
- port->stats_cbfn = NULL;
- port->stats_busy = BFA_FALSE;
- }
-
- /* Clear any enable/disable is pending */
- if (port->endis_pending) {
- if (port->endis_cbfn)
- port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED);
- port->endis_cbfn = NULL;
- port->endis_pending = BFA_FALSE;
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ /* Fail any pending get_stats/clear_stats requests */
+ if (port->stats_busy) {
+ if (port->stats_cbfn)
+ port->stats_cbfn(port->stats_cbarg,
+ BFA_STATUS_FAILED);
+ port->stats_cbfn = NULL;
+ port->stats_busy = BFA_FALSE;
+ }
+
+ /* Clear any enable/disable is pending */
+ if (port->endis_pending) {
+ if (port->endis_cbfn)
+ port->endis_cbfn(port->endis_cbarg,
+ BFA_STATUS_FAILED);
+ port->endis_cbfn = NULL;
+ port->endis_pending = BFA_FALSE;
+ }
+ break;
+ default:
+ break;
}
}
@@ -445,10 +466,12 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
port->endis_pending = BFA_FALSE;
port->stats_cbfn = NULL;
port->endis_cbfn = NULL;
+ port->pbc_disabled = BFA_FALSE;
bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
- bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port);
- list_add_tail(&port->hbfail.qe, &port->ioc->hb_notify_q);
+ bfa_q_qe_init(&port->ioc_notify);
+ bfa_ioc_notify_init(&port->ioc_notify, bfa_port_notify, port);
+ list_add_tail(&port->ioc_notify.qe, &port->ioc->notify_q);
/*
* initialize time stamp for stats reset
@@ -458,3 +481,368 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
bfa_trc(port, 0);
}
+
+/*
+ * CEE module specific definitions
+ */
+
+/*
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for get-attributes responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ * status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+ struct bfa_cee_lldp_cfg_s *lldp_cfg = &cee->attr->lldp_remote;
+
+ cee->get_attr_status = status;
+ bfa_trc(cee, 0);
+ if (status == BFA_STATUS_OK) {
+ bfa_trc(cee, 0);
+ memcpy(cee->attr, cee->attr_dma.kva,
+ sizeof(struct bfa_cee_attr_s));
+ lldp_cfg->time_to_live = be16_to_cpu(lldp_cfg->time_to_live);
+ lldp_cfg->enabled_system_cap =
+ be16_to_cpu(lldp_cfg->enabled_system_cap);
+ }
+ cee->get_attr_pending = BFA_FALSE;
+ if (cee->cbfn.get_attr_cbfn) {
+ bfa_trc(cee, 0);
+ cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
+ }
+}
+
+/*
+ * bfa_cee_get_stats_isr()
+ *
+ * @brief CEE ISR for get-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ * status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+ u32 *buffer;
+ int i;
+
+ cee->get_stats_status = status;
+ bfa_trc(cee, 0);
+ if (status == BFA_STATUS_OK) {
+ bfa_trc(cee, 0);
+ memcpy(cee->stats, cee->stats_dma.kva,
+ sizeof(struct bfa_cee_stats_s));
+ /* swap the cee stats */
+ buffer = (u32 *)cee->stats;
+ for (i = 0; i < (sizeof(struct bfa_cee_stats_s) /
+ sizeof(u32)); i++)
+ buffer[i] = cpu_to_be32(buffer[i]);
+ }
+ cee->get_stats_pending = BFA_FALSE;
+ bfa_trc(cee, 0);
+ if (cee->cbfn.get_stats_cbfn) {
+ bfa_trc(cee, 0);
+ cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
+ }
+}
+
+/*
+ * bfa_cee_reset_stats_isr()
+ *
+ * @brief CEE ISR for reset-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ * status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+ cee->reset_stats_status = status;
+ cee->reset_stats_pending = BFA_FALSE;
+ if (cee->cbfn.reset_stats_cbfn)
+ cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
+}
+
+/*
+ * bfa_cee_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE module
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+u32
+bfa_cee_meminfo(void)
+{
+ return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ) +
+ BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * bfa_cee_mem_claim()
+ *
+ * @brief Initialized CEE DMA Memory
+ *
+ * @param[in] cee CEE module pointer
+ * dma_kva Kernel Virtual Address of CEE DMA Memory
+ * dma_pa Physical Address of CEE DMA Memory
+ *
+ * @return void
+ */
+void
+bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
+{
+ cee->attr_dma.kva = dma_kva;
+ cee->attr_dma.pa = dma_pa;
+ cee->stats_dma.kva = dma_kva + BFA_ROUNDUP(
+ sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
+ cee->stats_dma.pa = dma_pa + BFA_ROUNDUP(
+ sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
+ cee->attr = (struct bfa_cee_attr_s *) dma_kva;
+ cee->stats = (struct bfa_cee_stats_s *) (dma_kva + BFA_ROUNDUP(
+ sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ));
+}
+
+/*
+ * bfa_cee_get_attr()
+ *
+ * @brief
+ * Send the request to the f/w to fetch CEE attributes.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
+ bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_cee_get_req_s *cmd;
+
+ WARN_ON((cee == NULL) || (cee->ioc == NULL));
+ bfa_trc(cee, 0);
+ if (!bfa_ioc_is_operational(cee->ioc)) {
+ bfa_trc(cee, 0);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+ if (cee->get_attr_pending == BFA_TRUE) {
+ bfa_trc(cee, 0);
+ return BFA_STATUS_DEVBUSY;
+ }
+ cee->get_attr_pending = BFA_TRUE;
+ cmd = (struct bfi_cee_get_req_s *) cee->get_cfg_mb.msg;
+ cee->attr = attr;
+ cee->cbfn.get_attr_cbfn = cbfn;
+ cee->cbfn.get_attr_cbarg = cbarg;
+ bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
+ bfa_ioc_portid(cee->ioc));
+ bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
+ bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * bfa_cee_get_stats()
+ *
+ * @brief
+ * Send the request to the f/w to fetch CEE statistics.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
+ bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_cee_get_req_s *cmd;
+
+ WARN_ON((cee == NULL) || (cee->ioc == NULL));
+
+ if (!bfa_ioc_is_operational(cee->ioc)) {
+ bfa_trc(cee, 0);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+ if (cee->get_stats_pending == BFA_TRUE) {
+ bfa_trc(cee, 0);
+ return BFA_STATUS_DEVBUSY;
+ }
+ cee->get_stats_pending = BFA_TRUE;
+ cmd = (struct bfi_cee_get_req_s *) cee->get_stats_mb.msg;
+ cee->stats = stats;
+ cee->cbfn.get_stats_cbfn = cbfn;
+ cee->cbfn.get_stats_cbarg = cbarg;
+ bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
+ bfa_ioc_portid(cee->ioc));
+ bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
+ bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * bfa_cee_reset_stats()
+ *
+ * @brief Clears CEE Stats in the f/w.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_reset_stats(struct bfa_cee_s *cee,
+ bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg)
+{
+ struct bfi_cee_reset_stats_s *cmd;
+
+ WARN_ON((cee == NULL) || (cee->ioc == NULL));
+ if (!bfa_ioc_is_operational(cee->ioc)) {
+ bfa_trc(cee, 0);
+ return BFA_STATUS_IOC_FAILURE;
+ }
+ if (cee->reset_stats_pending == BFA_TRUE) {
+ bfa_trc(cee, 0);
+ return BFA_STATUS_DEVBUSY;
+ }
+ cee->reset_stats_pending = BFA_TRUE;
+ cmd = (struct bfi_cee_reset_stats_s *) cee->reset_stats_mb.msg;
+ cee->cbfn.reset_stats_cbfn = cbfn;
+ cee->cbfn.reset_stats_cbarg = cbarg;
+ bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
+ bfa_ioc_portid(cee->ioc));
+ bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * bfa_cee_isrs()
+ *
+ * @brief Handles Mail-box interrupts for CEE module.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+void
+bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
+{
+ union bfi_cee_i2h_msg_u *msg;
+ struct bfi_cee_get_rsp_s *get_rsp;
+ struct bfa_cee_s *cee = (struct bfa_cee_s *) cbarg;
+ msg = (union bfi_cee_i2h_msg_u *) m;
+ get_rsp = (struct bfi_cee_get_rsp_s *) m;
+ bfa_trc(cee, msg->mh.msg_id);
+ switch (msg->mh.msg_id) {
+ case BFI_CEE_I2H_GET_CFG_RSP:
+ bfa_trc(cee, get_rsp->cmd_status);
+ bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
+ break;
+ case BFI_CEE_I2H_GET_STATS_RSP:
+ bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
+ break;
+ case BFI_CEE_I2H_RESET_STATS_RSP:
+ bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
+
+/*
+ * bfa_cee_notify()
+ *
+ * @brief CEE module IOC event handler.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ * @param[in] IOC event type
+ *
+ * @return void
+ */
+
+void
+bfa_cee_notify(void *arg, enum bfa_ioc_event_e event)
+{
+ struct bfa_cee_s *cee = (struct bfa_cee_s *) arg;
+
+ bfa_trc(cee, event);
+
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ if (cee->get_attr_pending == BFA_TRUE) {
+ cee->get_attr_status = BFA_STATUS_FAILED;
+ cee->get_attr_pending = BFA_FALSE;
+ if (cee->cbfn.get_attr_cbfn) {
+ cee->cbfn.get_attr_cbfn(
+ cee->cbfn.get_attr_cbarg,
+ BFA_STATUS_FAILED);
+ }
+ }
+ if (cee->get_stats_pending == BFA_TRUE) {
+ cee->get_stats_status = BFA_STATUS_FAILED;
+ cee->get_stats_pending = BFA_FALSE;
+ if (cee->cbfn.get_stats_cbfn) {
+ cee->cbfn.get_stats_cbfn(
+ cee->cbfn.get_stats_cbarg,
+ BFA_STATUS_FAILED);
+ }
+ }
+ if (cee->reset_stats_pending == BFA_TRUE) {
+ cee->reset_stats_status = BFA_STATUS_FAILED;
+ cee->reset_stats_pending = BFA_FALSE;
+ if (cee->cbfn.reset_stats_cbfn) {
+ cee->cbfn.reset_stats_cbfn(
+ cee->cbfn.reset_stats_cbarg,
+ BFA_STATUS_FAILED);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * bfa_cee_attach()
+ *
+ * @brief CEE module-attach API
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ * ioc - Pointer to the ioc module data structure
+ * dev - Pointer to the device driver module data structure
+ * The device driver specific mbox ISR functions have
+ * this pointer as one of the parameters.
+ *
+ * @return void
+ */
+void
+bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc,
+ void *dev)
+{
+ WARN_ON(cee == NULL);
+ cee->dev = dev;
+ cee->ioc = ioc;
+
+ bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
+ bfa_q_qe_init(&cee->ioc_notify);
+ bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee);
+ list_add_tail(&cee->ioc_notify.qe, &cee->ioc->notify_q);
+}
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
index c4ee9db6b470..947f897328d6 100644
--- a/drivers/scsi/bfa/bfa_port.h
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -43,12 +43,16 @@ struct bfa_port_s {
bfa_port_endis_cbfn_t endis_cbfn;
void *endis_cbarg;
bfa_status_t endis_status;
- struct bfa_ioc_hbfail_notify_s hbfail;
+ struct bfa_ioc_notify_s ioc_notify;
+ bfa_boolean_t pbc_disabled;
+ struct bfa_mem_dma_s port_dma;
};
+#define BFA_MEM_PORT_DMA(__bfa) (&((__bfa)->modules.port.port_dma))
+
void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
void *dev, struct bfa_trc_mod_s *trcmod);
-void bfa_port_hbfail(void *arg);
+void bfa_port_notify(void *arg, enum bfa_ioc_event_e event);
bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
union bfa_port_stats_u *stats,
@@ -62,4 +66,58 @@ bfa_status_t bfa_port_disable(struct bfa_port_s *port,
u32 bfa_port_meminfo(void);
void bfa_port_mem_claim(struct bfa_port_s *port,
u8 *dma_kva, u64 dma_pa);
+
+/*
+ * CEE declaration
+ */
+typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_cee_cbfn_s {
+ bfa_cee_get_attr_cbfn_t get_attr_cbfn;
+ void *get_attr_cbarg;
+ bfa_cee_get_stats_cbfn_t get_stats_cbfn;
+ void *get_stats_cbarg;
+ bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
+ void *reset_stats_cbarg;
+};
+
+struct bfa_cee_s {
+ void *dev;
+ bfa_boolean_t get_attr_pending;
+ bfa_boolean_t get_stats_pending;
+ bfa_boolean_t reset_stats_pending;
+ bfa_status_t get_attr_status;
+ bfa_status_t get_stats_status;
+ bfa_status_t reset_stats_status;
+ struct bfa_cee_cbfn_s cbfn;
+ struct bfa_ioc_notify_s ioc_notify;
+ struct bfa_trc_mod_s *trcmod;
+ struct bfa_cee_attr_s *attr;
+ struct bfa_cee_stats_s *stats;
+ struct bfa_dma_s attr_dma;
+ struct bfa_dma_s stats_dma;
+ struct bfa_ioc_s *ioc;
+ struct bfa_mbox_cmd_s get_cfg_mb;
+ struct bfa_mbox_cmd_s get_stats_mb;
+ struct bfa_mbox_cmd_s reset_stats_mb;
+ struct bfa_mem_dma_s cee_dma;
+};
+
+#define BFA_MEM_CEE_DMA(__bfa) (&((__bfa)->modules.cee.cee_dma))
+
+u32 bfa_cee_meminfo(void);
+void bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa);
+void bfa_cee_attach(struct bfa_cee_s *cee,
+ struct bfa_ioc_s *ioc, void *dev);
+bfa_status_t bfa_cee_get_attr(struct bfa_cee_s *cee,
+ struct bfa_cee_attr_s *attr,
+ bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_cee_get_stats(struct bfa_cee_s *cee,
+ struct bfa_cee_stats_s *stats,
+ bfa_cee_get_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_cee_reset_stats(struct bfa_cee_s *cee,
+ bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg);
+
#endif /* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 16d9a5f61c18..21caaefce99f 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -21,6 +21,7 @@
#include "bfa_modules.h"
BFA_TRC_FILE(HAL, FCXP);
+BFA_MODULE(fcdiag);
BFA_MODULE(fcxp);
BFA_MODULE(sgpg);
BFA_MODULE(lps);
@@ -113,11 +114,10 @@ static void bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
/*
* forward declarations for LPS functions
*/
-static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
- u32 *dm_len);
+static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *minfo, struct bfa_s *bfa);
static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
static void bfa_lps_detach(struct bfa_s *bfa);
static void bfa_lps_start(struct bfa_s *bfa);
@@ -125,6 +125,7 @@ static void bfa_lps_stop(struct bfa_s *bfa);
static void bfa_lps_iocdisable(struct bfa_s *bfa);
static void bfa_lps_login_rsp(struct bfa_s *bfa,
struct bfi_lps_login_rsp_s *rsp);
+static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
static void bfa_lps_logout_rsp(struct bfa_s *bfa,
struct bfi_lps_logout_rsp_s *rsp);
static void bfa_lps_reqq_resume(void *lps_arg);
@@ -430,51 +431,17 @@ bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
*/
static void
-claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
- u8 *dm_kva = NULL;
- u64 dm_pa;
- u32 buf_pool_sz;
-
- dm_kva = bfa_meminfo_dma_virt(mi);
- dm_pa = bfa_meminfo_dma_phys(mi);
-
- buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
-
- /*
- * Initialize the fcxp req payload list
- */
- mod->req_pld_list_kva = dm_kva;
- mod->req_pld_list_pa = dm_pa;
- dm_kva += buf_pool_sz;
- dm_pa += buf_pool_sz;
- memset(mod->req_pld_list_kva, 0, buf_pool_sz);
-
- /*
- * Initialize the fcxp rsp payload list
- */
- buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
- mod->rsp_pld_list_kva = dm_kva;
- mod->rsp_pld_list_pa = dm_pa;
- dm_kva += buf_pool_sz;
- dm_pa += buf_pool_sz;
- memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
-
- bfa_meminfo_dma_virt(mi) = dm_kva;
- bfa_meminfo_dma_phys(mi) = dm_pa;
-}
-
-static void
-claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
{
u16 i;
struct bfa_fcxp_s *fcxp;
- fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
+ fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
INIT_LIST_HEAD(&mod->fcxp_free_q);
INIT_LIST_HEAD(&mod->fcxp_active_q);
+ INIT_LIST_HEAD(&mod->fcxp_unused_q);
mod->fcxp_list = fcxp;
@@ -489,40 +456,53 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
fcxp = fcxp + 1;
}
- bfa_meminfo_kva(mi) = (void *)fcxp;
+ bfa_mem_kva_curp(mod) = (void *)fcxp;
}
static void
-bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
- u32 *dm_len)
+bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+ struct bfa_s *bfa)
{
- u16 num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
+ struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);
+ struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);
+ struct bfa_mem_dma_s *seg_ptr;
+ u16 nsegs, idx, per_seg_fcxp;
+ u16 num_fcxps = cfg->fwcfg.num_fcxp_reqs;
+ u32 per_fcxp_sz;
- if (num_fcxp_reqs == 0)
+ if (num_fcxps == 0)
return;
- /*
- * Account for req/rsp payload
- */
- *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
if (cfg->drvcfg.min_cfg)
- *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+ per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;
else
- *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
+ per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;
- /*
- * Account for fcxp structs
- */
- *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
+ /* dma memory */
+ nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);
+ per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);
+
+ bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {
+ if (num_fcxps >= per_seg_fcxp) {
+ num_fcxps -= per_seg_fcxp;
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ per_seg_fcxp * per_fcxp_sz);
+ } else
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ num_fcxps * per_fcxp_sz);
+ }
+
+ /* kva memory */
+ bfa_mem_kva_setup(minfo, fcxp_kva,
+ cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
}
static void
bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_pcidev_s *pcidev)
{
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
- memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
mod->bfa = bfa;
mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
@@ -535,8 +515,7 @@ bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
INIT_LIST_HEAD(&mod->wait_q);
- claim_fcxp_req_rsp_mem(mod, meminfo);
- claim_fcxps_mem(mod, meminfo);
+ claim_fcxps_mem(mod);
}
static void
@@ -561,6 +540,9 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)
struct bfa_fcxp_s *fcxp;
struct list_head *qe, *qen;
+ /* Enqueue unused fcxp resources to free_q */
+ list_splice_tail_init(&mod->fcxp_unused_q, &mod->fcxp_free_q);
+
list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
fcxp = (struct bfa_fcxp_s *) qe;
if (fcxp->caller == NULL) {
@@ -750,23 +732,6 @@ hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
}
static void
-hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
-{
- union bfi_addr_u sga_zero = { {0} };
-
- sge->sg_len = reqlen;
- sge->flags = BFI_SGE_DATA_LAST;
- bfa_dma_addr_set(sge[0].sga, req_pa);
- bfa_sge_to_be(sge);
- sge++;
-
- sge->sga = sga_zero;
- sge->sg_len = reqlen;
- sge->flags = BFI_SGE_PGDLEN;
- bfa_sge_to_be(sge);
-}
-
-static void
hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
struct fchs_s *fchs)
{
@@ -846,7 +811,7 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
struct bfa_rport_s *rport = reqi->bfa_rport;
bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
- bfa_lpuid(bfa));
+ bfa_fn_lpu(bfa));
send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
if (rport) {
@@ -860,7 +825,7 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
}
send_req->vf_id = cpu_to_be16(reqi->vf_id);
- send_req->lp_tag = reqi->lp_tag;
+ send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
send_req->class = reqi->class;
send_req->rsp_timeout = rspi->rsp_timeout;
send_req->cts = reqi->cts;
@@ -873,18 +838,16 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
* setup req sgles
*/
if (fcxp->use_ireqbuf == 1) {
- hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
+ bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
BFA_FCXP_REQ_PLD_PA(fcxp));
} else {
if (fcxp->nreq_sgles > 0) {
WARN_ON(fcxp->nreq_sgles != 1);
- hal_fcxp_set_local_sges(send_req->req_sge,
- reqi->req_tot_len,
- fcxp->req_sga_cbfn(fcxp->caller,
- 0));
+ bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
+ fcxp->req_sga_cbfn(fcxp->caller, 0));
} else {
WARN_ON(reqi->req_tot_len != 0);
- hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+ bfa_alen_set(&send_req->rsp_alen, 0, 0);
}
}
@@ -894,25 +857,23 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
if (fcxp->use_irspbuf == 1) {
WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
- hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
+ bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
BFA_FCXP_RSP_PLD_PA(fcxp));
-
} else {
if (fcxp->nrsp_sgles > 0) {
WARN_ON(fcxp->nrsp_sgles != 1);
- hal_fcxp_set_local_sges(send_req->rsp_sge,
- rspi->rsp_maxlen,
- fcxp->rsp_sga_cbfn(fcxp->caller,
- 0));
+ bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
+ fcxp->rsp_sga_cbfn(fcxp->caller, 0));
+
} else {
WARN_ON(rspi->rsp_maxlen != 0);
- hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+ bfa_alen_set(&send_req->rsp_alen, 0, 0);
}
}
hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
- bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
+ bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
@@ -978,8 +939,8 @@ bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
void *reqbuf;
WARN_ON(fcxp->use_ireqbuf != 1);
- reqbuf = ((u8 *)mod->req_pld_list_kva) +
- fcxp->fcxp_tag * mod->req_pld_sz;
+ reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
+ mod->req_pld_sz + mod->rsp_pld_sz);
return reqbuf;
}
@@ -1002,13 +963,15 @@ void *
bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
{
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
- void *rspbuf;
+ void *fcxp_buf;
WARN_ON(fcxp->use_irspbuf != 1);
- rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
- fcxp->fcxp_tag * mod->rsp_pld_sz;
- return rspbuf;
+ fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
+ mod->req_pld_sz + mod->rsp_pld_sz);
+
+ /* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
+ return ((u8 *) fcxp_buf) + mod->req_pld_sz;
}
/*
@@ -1181,6 +1144,18 @@ bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
return mod->rsp_pld_sz;
}
+void
+bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
+{
+ struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+ struct list_head *qe;
+ int i;
+
+ for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
+ bfa_q_deq_tail(&mod->fcxp_free_q, &qe);
+ list_add_tail(qe, &mod->fcxp_unused_q);
+ }
+}
/*
* BFA LPS state machine functions
@@ -1192,7 +1167,7 @@ bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
static void
bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, event);
switch (event) {
@@ -1244,7 +1219,7 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
static void
bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, event);
switch (event) {
@@ -1278,6 +1253,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
break;
case BFA_LPS_SM_OFFLINE:
+ case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
break;
@@ -1297,7 +1273,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
static void
bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, event);
switch (event) {
@@ -1306,6 +1282,7 @@ bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
break;
case BFA_LPS_SM_OFFLINE:
+ case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
bfa_reqq_wcancel(&lps->wqe);
break;
@@ -1329,7 +1306,7 @@ bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
static void
bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, event);
switch (event) {
@@ -1378,7 +1355,7 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
static void
bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, event);
switch (event) {
@@ -1420,7 +1397,7 @@ bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
static void
bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, event);
switch (event) {
@@ -1430,6 +1407,7 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
break;
case BFA_LPS_SM_OFFLINE:
+ case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
break;
@@ -1444,7 +1422,7 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
static void
bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, event);
switch (event) {
@@ -1454,6 +1432,7 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
break;
case BFA_LPS_SM_OFFLINE:
+ case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
bfa_reqq_wcancel(&lps->wqe);
break;
@@ -1473,13 +1452,17 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
* return memory requirement
*/
static void
-bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
- u32 *dm_len)
+bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+ struct bfa_s *bfa)
{
+ struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
+
if (cfg->drvcfg.min_cfg)
- *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
+ bfa_mem_kva_setup(minfo, lps_kva,
+ sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
else
- *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
+ bfa_mem_kva_setup(minfo, lps_kva,
+ sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
}
/*
@@ -1487,28 +1470,28 @@ bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
*/
static void
bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_pcidev_s *pcidev)
{
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
struct bfa_lps_s *lps;
int i;
- memset(mod, 0, sizeof(struct bfa_lps_mod_s));
mod->num_lps = BFA_LPS_MAX_LPORTS;
if (cfg->drvcfg.min_cfg)
mod->num_lps = BFA_LPS_MIN_LPORTS;
else
mod->num_lps = BFA_LPS_MAX_LPORTS;
- mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
+ mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
- bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
+ bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
INIT_LIST_HEAD(&mod->lps_free_q);
INIT_LIST_HEAD(&mod->lps_active_q);
+ INIT_LIST_HEAD(&mod->lps_login_q);
for (i = 0; i < mod->num_lps; i++, lps++) {
lps->bfa = bfa;
- lps->lp_tag = (u8) i;
+ lps->bfa_tag = (u8) i;
lps->reqq = BFA_REQQ_LPS;
bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
list_add_tail(&lps->qe, &mod->lps_free_q);
@@ -1544,6 +1527,11 @@ bfa_lps_iocdisable(struct bfa_s *bfa)
lps = (struct bfa_lps_s *) qe;
bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
}
+ list_for_each_safe(qe, qen, &mod->lps_login_q) {
+ lps = (struct bfa_lps_s *) qe;
+ bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+ }
+ list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
}
/*
@@ -1555,12 +1543,13 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
struct bfa_lps_s *lps;
- WARN_ON(rsp->lp_tag >= mod->num_lps);
- lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+ WARN_ON(rsp->bfa_tag >= mod->num_lps);
+ lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
lps->status = rsp->status;
switch (rsp->status) {
case BFA_STATUS_OK:
+ lps->fw_tag = rsp->fw_tag;
lps->fport = rsp->f_port;
if (lps->fport)
lps->lp_pid = rsp->lp_pid;
@@ -1572,6 +1561,7 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
lps->lp_mac = rsp->lp_mac;
lps->brcd_switch = rsp->brcd_switch;
lps->fcf_mac = rsp->fcf_mac;
+ lps->pr_bbscn = rsp->bb_scn;
break;
@@ -1586,14 +1576,46 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
break;
+ case BFA_STATUS_VPORT_MAX:
+ if (!rsp->ext_status)
+ bfa_lps_no_res(lps, rsp->ext_status);
+ break;
+
default:
/* Nothing to do with other status */
break;
}
+ list_del(&lps->qe);
+ list_add_tail(&lps->qe, &mod->lps_active_q);
bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
}
+static void
+bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
+{
+ struct bfa_s *bfa = first_lps->bfa;
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct list_head *qe, *qe_next;
+ struct bfa_lps_s *lps;
+
+ bfa_trc(bfa, count);
+
+ qe = bfa_q_next(first_lps);
+
+ while (count && qe) {
+ qe_next = bfa_q_next(qe);
+ lps = (struct bfa_lps_s *)qe;
+ bfa_trc(bfa, lps->bfa_tag);
+ lps->status = first_lps->status;
+ list_del(&lps->qe);
+ list_add_tail(&lps->qe, &mod->lps_active_q);
+ bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+ qe = qe_next;
+ count--;
+ }
+}
+
/*
* Firmware logout response
*/
@@ -1603,8 +1625,8 @@ bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
struct bfa_lps_s *lps;
- WARN_ON(rsp->lp_tag >= mod->num_lps);
- lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+ WARN_ON(rsp->bfa_tag >= mod->num_lps);
+ lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
}
@@ -1618,7 +1640,7 @@ bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
struct bfa_lps_s *lps;
- lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
+ lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
}
@@ -1653,23 +1675,27 @@ bfa_lps_free(struct bfa_lps_s *lps)
static void
bfa_lps_send_login(struct bfa_lps_s *lps)
{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa);
struct bfi_lps_login_req_s *m;
m = bfa_reqq_next(lps->bfa, lps->reqq);
WARN_ON(!m);
bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
- bfa_lpuid(lps->bfa));
+ bfa_fn_lpu(lps->bfa));
- m->lp_tag = lps->lp_tag;
+ m->bfa_tag = lps->bfa_tag;
m->alpa = lps->alpa;
m->pdu_size = cpu_to_be16(lps->pdusz);
m->pwwn = lps->pwwn;
m->nwwn = lps->nwwn;
m->fdisc = lps->fdisc;
m->auth_en = lps->auth_en;
+ m->bb_scn = lps->bb_scn;
- bfa_reqq_produce(lps->bfa, lps->reqq);
+ bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
+ list_del(&lps->qe);
+ list_add_tail(&lps->qe, &mod->lps_login_q);
}
/*
@@ -1684,11 +1710,11 @@ bfa_lps_send_logout(struct bfa_lps_s *lps)
WARN_ON(!m);
bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
- bfa_lpuid(lps->bfa));
+ bfa_fn_lpu(lps->bfa));
- m->lp_tag = lps->lp_tag;
+ m->fw_tag = lps->fw_tag;
m->port_name = lps->pwwn;
- bfa_reqq_produce(lps->bfa, lps->reqq);
+ bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
}
/*
@@ -1703,11 +1729,11 @@ bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
WARN_ON(!m);
bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
- bfa_lpuid(lps->bfa));
+ bfa_fn_lpu(lps->bfa));
- m->lp_tag = lps->lp_tag;
+ m->fw_tag = lps->fw_tag;
m->lp_pid = lps->lp_pid;
- bfa_reqq_produce(lps->bfa, lps->reqq);
+ bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
}
/*
@@ -1859,7 +1885,7 @@ bfa_lps_delete(struct bfa_lps_s *lps)
*/
void
bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
- wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
+ wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en, uint8_t bb_scn)
{
lps->uarg = uarg;
lps->alpa = alpa;
@@ -1868,6 +1894,7 @@ bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
lps->nwwn = nwwn;
lps->fdisc = BFA_FALSE;
lps->auth_en = auth_en;
+ lps->bb_scn = bb_scn;
bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
}
@@ -1898,6 +1925,13 @@ bfa_lps_fdisclogo(struct bfa_lps_s *lps)
bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
}
+u8
+bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+
+ return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
+}
/*
* Return lport services tag given the pid
@@ -1911,7 +1945,7 @@ bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
if (lps->lp_pid == pid)
- return lps->lp_tag;
+ return lps->bfa_tag;
}
/* Return base port tag anyway */
@@ -1936,7 +1970,7 @@ bfa_lps_get_base_pid(struct bfa_s *bfa)
void
bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
{
- bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, lps->bfa_tag);
bfa_trc(lps->bfa, n2n_pid);
lps->lp_pid = n2n_pid;
@@ -1955,15 +1989,15 @@ bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
msg.msg = m;
switch (m->mhdr.msg_id) {
- case BFI_LPS_H2I_LOGIN_RSP:
+ case BFI_LPS_I2H_LOGIN_RSP:
bfa_lps_login_rsp(bfa, msg.login_rsp);
break;
- case BFI_LPS_H2I_LOGOUT_RSP:
+ case BFI_LPS_I2H_LOGOUT_RSP:
bfa_lps_logout_rsp(bfa, msg.logout_rsp);
break;
- case BFI_LPS_H2I_CVL_EVENT:
+ case BFI_LPS_I2H_CVL_EVENT:
bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
break;
@@ -2777,10 +2811,12 @@ bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
BFA_CACHELINE_SZ))
static void
-bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
- u32 *dm_len)
+bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+ struct bfa_s *bfa)
{
- *dm_len += FCPORT_STATS_DMA_SZ;
+ struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
+
+ bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
}
static void
@@ -2792,23 +2828,14 @@ bfa_fcport_qresume(void *cbarg)
}
static void
-bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
+bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
{
- u8 *dm_kva;
- u64 dm_pa;
+ struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
- dm_kva = bfa_meminfo_dma_virt(meminfo);
- dm_pa = bfa_meminfo_dma_phys(meminfo);
-
- fcport->stats_kva = dm_kva;
- fcport->stats_pa = dm_pa;
- fcport->stats = (union bfa_fcport_stats_u *) dm_kva;
-
- dm_kva += FCPORT_STATS_DMA_SZ;
- dm_pa += FCPORT_STATS_DMA_SZ;
-
- bfa_meminfo_dma_virt(meminfo) = dm_kva;
- bfa_meminfo_dma_phys(meminfo) = dm_pa;
+ fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
+ fcport->stats_pa = bfa_mem_dma_phys(fcport_dma);
+ fcport->stats = (union bfa_fcport_stats_u *)
+ bfa_mem_dma_virt(fcport_dma);
}
/*
@@ -2816,18 +2843,17 @@ bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
*/
static void
bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_pcidev_s *pcidev)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
struct bfa_fcport_ln_s *ln = &fcport->ln;
struct timeval tv;
- memset(fcport, 0, sizeof(struct bfa_fcport_s));
fcport->bfa = bfa;
ln->fcport = fcport;
- bfa_fcport_mem_claim(fcport, meminfo);
+ bfa_fcport_mem_claim(fcport);
bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
@@ -2921,6 +2947,7 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
{
fcport->speed = BFA_PORT_SPEED_UNKNOWN;
fcport->topology = BFA_PORT_TOPOLOGY_NONE;
+ fcport->bbsc_op_state = BFA_FALSE;
}
/*
@@ -2948,7 +2975,7 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
}
bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
- bfa_lpuid(fcport->bfa));
+ bfa_fn_lpu(fcport->bfa));
m->nwwn = fcport->nwwn;
m->pwwn = fcport->pwwn;
m->port_cfg = fcport->cfg;
@@ -2962,7 +2989,7 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
return BFA_TRUE;
}
@@ -2991,13 +3018,13 @@ bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
}
bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
- bfa_lpuid(fcport->bfa));
+ bfa_fn_lpu(fcport->bfa));
m->msgtag = fcport->msgtag;
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
return BFA_TRUE;
}
@@ -3029,13 +3056,14 @@ bfa_fcport_send_txcredit(void *port_cbarg)
}
bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
- bfa_lpuid(fcport->bfa));
+ bfa_fn_lpu(fcport->bfa));
m->tx_bbcredit = cpu_to_be16((u16)fcport->cfg.tx_bbcredit);
+ m->bb_scn = fcport->cfg.bb_scn;
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
}
static void
@@ -3139,8 +3167,8 @@ bfa_fcport_send_stats_get(void *cbarg)
memset(msg, 0, sizeof(struct bfi_fcport_req_s));
bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
- bfa_lpuid(fcport->bfa));
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+ bfa_fn_lpu(fcport->bfa));
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
}
static void
@@ -3201,8 +3229,8 @@ bfa_fcport_send_stats_clear(void *cbarg)
memset(msg, 0, sizeof(struct bfi_fcport_req_s));
bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
- bfa_lpuid(fcport->bfa));
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+ bfa_fn_lpu(fcport->bfa));
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
}
/*
@@ -3329,6 +3357,9 @@ bfa_fcport_init(struct bfa_s *bfa)
fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
+ if (bfa_fcport_is_pbcdisabled(bfa))
+ bfa->modules.port.pbc_disabled = BFA_TRUE;
+
WARN_ON(!fcport->cfg.maxfrsize);
WARN_ON(!fcport->cfg.rx_bbcredit);
WARN_ON(!fcport->speed_sup);
@@ -3453,6 +3484,9 @@ bfa_fcport_enable(struct bfa_s *bfa)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ if (bfa_fcport_is_pbcdisabled(bfa))
+ return BFA_STATUS_PBC;
+
if (bfa_ioc_is_disabled(&bfa->ioc))
return BFA_STATUS_IOC_DISABLED;
@@ -3466,6 +3500,8 @@ bfa_fcport_enable(struct bfa_s *bfa)
bfa_status_t
bfa_fcport_disable(struct bfa_s *bfa)
{
+ if (bfa_fcport_is_pbcdisabled(bfa))
+ return BFA_STATUS_PBC;
if (bfa_ioc_is_disabled(&bfa->ioc))
return BFA_STATUS_IOC_DISABLED;
@@ -3474,6 +3510,21 @@ bfa_fcport_disable(struct bfa_s *bfa)
return BFA_STATUS_OK;
}
+/* If PBC is disabled on port, return error */
+bfa_status_t
+bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+ if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
+ bfa_trc(bfa, fcport->pwwn);
+ return BFA_STATUS_PBC;
+ }
+ return BFA_STATUS_OK;
+}
+
/*
* Configure port speed.
*/
@@ -3491,6 +3542,28 @@ bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
return BFA_STATUS_UNSUPP_SPEED;
}
+ /* For Mezz card, port speed entered needs to be checked */
+ if (bfa_mfg_is_mezz(fcport->bfa->ioc.attr->card_type)) {
+ if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
+ /* For CT2, 1G is not supported */
+ if ((speed == BFA_PORT_SPEED_1GBPS) &&
+ (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
+ return BFA_STATUS_UNSUPP_SPEED;
+
+ /* Already checked for Auto Speed and Max Speed supp */
+ if (!(speed == BFA_PORT_SPEED_1GBPS ||
+ speed == BFA_PORT_SPEED_2GBPS ||
+ speed == BFA_PORT_SPEED_4GBPS ||
+ speed == BFA_PORT_SPEED_8GBPS ||
+ speed == BFA_PORT_SPEED_16GBPS ||
+ speed == BFA_PORT_SPEED_AUTO))
+ return BFA_STATUS_UNSUPP_SPEED;
+ } else {
+ if (speed != BFA_PORT_SPEED_10GBPS)
+ return BFA_STATUS_UNSUPP_SPEED;
+ }
+ }
+
fcport->cfg.speed = speed;
return BFA_STATUS_OK;
@@ -3624,11 +3697,14 @@ bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
}
void
-bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
+bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
+ fcport->cfg.bb_scn = bb_scn;
+ if (bb_scn)
+ fcport->bbsc_op_state = BFA_TRUE;
bfa_fcport_send_txcredit(fcport);
}
@@ -3675,16 +3751,23 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
/* beacon attributes */
attr->beacon = fcport->beacon;
attr->link_e2e_beacon = fcport->link_e2e_beacon;
- attr->plog_enabled = (bfa_boolean_t)fcport->bfa->plog->plog_enabled;
- attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
- if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
- attr->port_state = BFA_PORT_ST_IOCDIS;
- else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
- attr->port_state = BFA_PORT_ST_FWMISMATCH;
+ attr->bbsc_op_status = fcport->bbsc_op_state;
+
+ /* PBC Disabled State */
+ if (bfa_fcport_is_pbcdisabled(bfa))
+ attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
+ else {
+ if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
+ attr->port_state = BFA_PORT_ST_IOCDIS;
+ else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
+ attr->port_state = BFA_PORT_ST_FWMISMATCH;
+ else if (bfa_ioc_is_acq_addr(&fcport->bfa->ioc))
+ attr->port_state = BFA_PORT_ST_ACQ_ADDR;
+ }
/* FCoE vlan */
attr->fcoe_vlan = fcport->fcoe_vlan;
@@ -3766,6 +3849,18 @@ bfa_fcport_is_ratelim(struct bfa_s *bfa)
}
/*
+ * Enable/Disable FAA feature in port config
+ */
+void
+bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, state);
+ fcport->cfg.faa_state = state;
+}
+
+/*
* Get default minimum ratelim speed
*/
enum bfa_port_speed
@@ -3778,6 +3873,22 @@ bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
}
+void
+bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+ bfa_boolean_t link_e2e_beacon)
+{
+ struct bfa_s *bfa = dev;
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, beacon);
+ bfa_trc(bfa, link_e2e_beacon);
+ bfa_trc(bfa, fcport->beacon);
+ bfa_trc(bfa, fcport->link_e2e_beacon);
+
+ fcport->beacon = beacon;
+ fcport->link_e2e_beacon = link_e2e_beacon;
+}
+
bfa_boolean_t
bfa_fcport_is_linkup(struct bfa_s *bfa)
{
@@ -3797,6 +3908,14 @@ bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
return fcport->cfg.qos_enabled;
}
+bfa_boolean_t
+bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->cfg.trunked;
+}
+
/*
* Rport State machine functions
*/
@@ -4286,18 +4405,22 @@ bfa_rport_qresume(void *cbarg)
}
static void
-bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
+bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+ struct bfa_s *bfa)
{
+ struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);
+
if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
cfg->fwcfg.num_rports = BFA_RPORT_MIN;
- *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
+ /* kva memory */
+ bfa_mem_kva_setup(minfo, rport_kva,
+ cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
}
static void
bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_pcidev_s *pcidev)
{
struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
struct bfa_rport_s *rp;
@@ -4305,8 +4428,9 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
INIT_LIST_HEAD(&mod->rp_free_q);
INIT_LIST_HEAD(&mod->rp_active_q);
+ INIT_LIST_HEAD(&mod->rp_unused_q);
- rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
+ rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);
mod->rps_list = rp;
mod->num_rports = cfg->fwcfg.num_rports;
@@ -4331,7 +4455,7 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
/*
* consume memory
*/
- bfa_meminfo_kva(meminfo) = (u8 *) rp;
+ bfa_mem_kva_curp(mod) = (u8 *) rp;
}
static void
@@ -4356,6 +4480,9 @@ bfa_rport_iocdisable(struct bfa_s *bfa)
struct bfa_rport_s *rport;
struct list_head *qe, *qen;
+ /* Enqueue unused rport resources to free_q */
+ list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
+
list_for_each_safe(qe, qen, &mod->rp_active_q) {
rport = (struct bfa_rport_s *) qe;
bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
@@ -4399,11 +4526,11 @@ bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
}
bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
- bfa_lpuid(rp->bfa));
+ bfa_fn_lpu(rp->bfa));
m->bfa_handle = rp->rport_tag;
m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
m->pid = rp->rport_info.pid;
- m->lp_tag = rp->rport_info.lp_tag;
+ m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
m->local_pid = rp->rport_info.local_pid;
m->fc_class = rp->rport_info.fc_class;
m->vf_en = rp->rport_info.vf_en;
@@ -4413,7 +4540,7 @@ bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+ bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
return BFA_TRUE;
}
@@ -4432,13 +4559,13 @@ bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
}
bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
- bfa_lpuid(rp->bfa));
+ bfa_fn_lpu(rp->bfa));
m->fw_handle = rp->fw_handle;
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+ bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
return BFA_TRUE;
}
@@ -4457,14 +4584,14 @@ bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
}
bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
- bfa_lpuid(rp->bfa));
+ bfa_fn_lpu(rp->bfa));
m->fw_handle = rp->fw_handle;
m->speed = (u8)rp->rport_info.speed;
/*
* queue I/O message to firmware
*/
- bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+ bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
return BFA_TRUE;
}
@@ -4514,7 +4641,18 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
}
}
+void
+bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
+{
+ struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+ struct list_head *qe;
+ int i;
+ for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
+ bfa_q_deq_tail(&mod->rp_free_q, &qe);
+ list_add_tail(qe, &mod->rp_unused_q);
+ }
+}
/*
* bfa_rport_api
@@ -4577,26 +4715,51 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
* Compute and return memory needed by FCP(im) module.
*/
static void
-bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
+bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+ struct bfa_s *bfa)
{
+ struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);
+ struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);
+ struct bfa_mem_dma_s *seg_ptr;
+ u16 nsegs, idx, per_seg_sgpg, num_sgpg;
+ u32 sgpg_sz = sizeof(struct bfi_sgpg_s);
+
if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
+ else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)
+ cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;
- *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
- *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
-}
+ num_sgpg = cfg->drvcfg.num_sgpgs;
+ nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
+ per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);
+
+ bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {
+ if (num_sgpg >= per_seg_sgpg) {
+ num_sgpg -= per_seg_sgpg;
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ per_seg_sgpg * sgpg_sz);
+ } else
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ num_sgpg * sgpg_sz);
+ }
+
+ /* kva memory */
+ bfa_mem_kva_setup(minfo, sgpg_kva,
+ cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
+}
static void
bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_pcidev_s *pcidev)
{
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
- int i;
struct bfa_sgpg_s *hsgpg;
struct bfi_sgpg_s *sgpg;
u64 align_len;
+ struct bfa_mem_dma_s *seg_ptr;
+ u32 sgpg_sz = sizeof(struct bfi_sgpg_s);
+ u16 i, idx, nsegs, per_seg_sgpg, num_sgpg;
union {
u64 pa;
@@ -4608,39 +4771,45 @@ bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
- mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
- mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
- align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
- mod->sgpg_arr_pa += align_len;
- mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
- align_len);
- mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
- align_len);
-
- hsgpg = mod->hsgpg_arr;
- sgpg = mod->sgpg_arr;
- sgpg_pa.pa = mod->sgpg_arr_pa;
- mod->free_sgpgs = mod->num_sgpgs;
-
- WARN_ON(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1));
-
- for (i = 0; i < mod->num_sgpgs; i++) {
- memset(hsgpg, 0, sizeof(*hsgpg));
- memset(sgpg, 0, sizeof(*sgpg));
-
- hsgpg->sgpg = sgpg;
- sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
- hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
- list_add_tail(&hsgpg->qe, &mod->sgpg_q);
-
- hsgpg++;
- sgpg++;
- sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
+ mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
+
+ num_sgpg = cfg->drvcfg.num_sgpgs;
+ nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
+
+ /* dma/kva mem claim */
+ hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);
+
+ bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {
+
+ if (!bfa_mem_dma_virt(seg_ptr))
+ break;
+
+ align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -
+ bfa_mem_dma_phys(seg_ptr);
+
+ sgpg = (struct bfi_sgpg_s *)
+ (((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);
+ sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;
+ WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));
+
+ per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;
+
+ for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {
+ memset(hsgpg, 0, sizeof(*hsgpg));
+ memset(sgpg, 0, sizeof(*sgpg));
+
+ hsgpg->sgpg = sgpg;
+ sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
+ hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
+ list_add_tail(&hsgpg->qe, &mod->sgpg_q);
+
+ sgpg++;
+ hsgpg++;
+ sgpg_pa.pa += sgpg_sz;
+ }
}
- bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
- bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
- bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
+ bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
}
static void
@@ -4782,31 +4951,13 @@ __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
}
static void
-claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
- u32 uf_pb_tot_sz;
-
- ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
- ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
- uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
- BFA_DMA_ALIGN_SZ);
-
- bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
- bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
-
- memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
-}
-
-static void
-claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)
{
struct bfi_uf_buf_post_s *uf_bp_msg;
- struct bfi_sge_s *sge;
- union bfi_addr_u sga_zero = { {0} };
u16 i;
u16 buf_len;
- ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
+ ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);
uf_bp_msg = ufm->uf_buf_posts;
for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
@@ -4817,28 +4968,18 @@ claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
buf_len = sizeof(struct bfa_uf_buf_s);
uf_bp_msg->buf_len = cpu_to_be16(buf_len);
bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
- bfa_lpuid(ufm->bfa));
-
- sge = uf_bp_msg->sge;
- sge[0].sg_len = buf_len;
- sge[0].flags = BFI_SGE_DATA_LAST;
- bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
- bfa_sge_to_be(sge);
-
- sge[1].sg_len = buf_len;
- sge[1].flags = BFI_SGE_PGDLEN;
- sge[1].sga = sga_zero;
- bfa_sge_to_be(&sge[1]);
+ bfa_fn_lpu(ufm->bfa));
+ bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
}
/*
* advance pointer beyond consumed memory
*/
- bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
+ bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;
}
static void
-claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+claim_ufs(struct bfa_uf_mod_s *ufm)
{
u16 i;
struct bfa_uf_s *uf;
@@ -4846,7 +4987,7 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
/*
* Claim block of memory for UF list
*/
- ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
+ ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);
/*
* Initialize UFs and queue it in UF free queue
@@ -4855,8 +4996,8 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
memset(uf, 0, sizeof(struct bfa_uf_s));
uf->bfa = ufm->bfa;
uf->uf_tag = i;
- uf->pb_len = sizeof(struct bfa_uf_buf_s);
- uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
+ uf->pb_len = BFA_PER_UF_DMA_SZ;
+ uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);
uf->buf_pa = ufm_pbs_pa(ufm, i);
list_add_tail(&uf->qe, &ufm->uf_free_q);
}
@@ -4864,48 +5005,57 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
/*
* advance memory pointer
*/
- bfa_meminfo_kva(mi) = (u8 *) uf;
+ bfa_mem_kva_curp(ufm) = (u8 *) uf;
}
static void
-uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+uf_mem_claim(struct bfa_uf_mod_s *ufm)
{
- claim_uf_pbs(ufm, mi);
- claim_ufs(ufm, mi);
- claim_uf_post_msgs(ufm, mi);
+ claim_ufs(ufm);
+ claim_uf_post_msgs(ufm);
}
static void
-bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
+bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+ struct bfa_s *bfa)
{
- u32 num_ufs = cfg->fwcfg.num_uf_bufs;
-
- /*
- * dma-able memory for UF posted bufs
- */
- *dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
- BFA_DMA_ALIGN_SZ);
+ struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+ struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);
+ u32 num_ufs = cfg->fwcfg.num_uf_bufs;
+ struct bfa_mem_dma_s *seg_ptr;
+ u16 nsegs, idx, per_seg_uf = 0;
+
+ nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);
+ per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);
+
+ bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {
+ if (num_ufs >= per_seg_uf) {
+ num_ufs -= per_seg_uf;
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ per_seg_uf * BFA_PER_UF_DMA_SZ);
+ } else
+ bfa_mem_dma_setup(minfo, seg_ptr,
+ num_ufs * BFA_PER_UF_DMA_SZ);
+ }
- /*
- * kernel Virtual memory for UFs and UF buf post msg copies
- */
- *ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
- *ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
+ /* kva memory */
+ bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *
+ (sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
}
static void
bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_pcidev_s *pcidev)
{
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
- memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
ufm->bfa = bfa;
ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
INIT_LIST_HEAD(&ufm->uf_free_q);
INIT_LIST_HEAD(&ufm->uf_posted_q);
+ INIT_LIST_HEAD(&ufm->uf_unused_q);
- uf_mem_claim(ufm, meminfo);
+ uf_mem_claim(ufm);
}
static void
@@ -4939,7 +5089,7 @@ bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
sizeof(struct bfi_uf_buf_post_s));
- bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
+ bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
bfa_trc(ufm->bfa, uf->uf_tag);
@@ -4963,11 +5113,15 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
{
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
u16 uf_tag = m->buf_tag;
- struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
- u8 *buf = &uf_buf->d[0];
+ struct bfa_uf_buf_s *uf_buf;
+ uint8_t *buf;
struct fchs_s *fchs;
+ uf_buf = (struct bfa_uf_buf_s *)
+ bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
+ buf = &uf_buf->d[0];
+
m->frm_len = be16_to_cpu(m->frm_len);
m->xfr_len = be16_to_cpu(m->xfr_len);
@@ -5008,6 +5162,9 @@ bfa_uf_iocdisable(struct bfa_s *bfa)
struct bfa_uf_s *uf;
struct list_head *qe, *qen;
+ /* Enqueue unused uf resources to free_q */
+ list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);
+
list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
uf = (struct bfa_uf_s *) qe;
list_del(&uf->qe);
@@ -5072,4 +5229,415 @@ bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
}
}
+void
+bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
+{
+ struct bfa_uf_mod_s *mod = BFA_UF_MOD(bfa);
+ struct list_head *qe;
+ int i;
+
+ for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
+ bfa_q_deq_tail(&mod->uf_free_q, &qe);
+ list_add_tail(qe, &mod->uf_unused_q);
+ }
+}
+
+/*
+ * BFA fcdiag module
+ */
+#define BFA_DIAG_QTEST_TOV 1000 /* msec */
+
+/*
+ * Set port status to busy
+ */
+static void
+bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
+
+ if (fcdiag->lb.lock)
+ fcport->diag_busy = BFA_TRUE;
+ else
+ fcport->diag_busy = BFA_FALSE;
+}
+
+static void
+bfa_fcdiag_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+ struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ fcdiag->bfa = bfa;
+ fcdiag->trcmod = bfa->trcmod;
+ /* The common DIAG attach bfa_diag_attach() will do all memory claim */
+}
+
+static void
+bfa_fcdiag_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ bfa_trc(fcdiag, fcdiag->lb.lock);
+ if (fcdiag->lb.lock) {
+ fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
+ fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
+ fcdiag->lb.lock = 0;
+ bfa_fcdiag_set_busy_status(fcdiag);
+ }
+}
+
+static void
+bfa_fcdiag_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_queuetest_timeout(void *cbarg)
+{
+ struct bfa_fcdiag_s *fcdiag = cbarg;
+ struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
+
+ bfa_trc(fcdiag, fcdiag->qtest.all);
+ bfa_trc(fcdiag, fcdiag->qtest.count);
+
+ fcdiag->qtest.timer_active = 0;
+
+ res->status = BFA_STATUS_ETIMER;
+ res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
+ if (fcdiag->qtest.all)
+ res->queue = fcdiag->qtest.all;
+
+ bfa_trc(fcdiag, BFA_STATUS_ETIMER);
+ fcdiag->qtest.status = BFA_STATUS_ETIMER;
+ fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
+ fcdiag->qtest.lock = 0;
+}
+
+static bfa_status_t
+bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
+{
+ u32 i;
+ struct bfi_diag_qtest_req_s *req;
+
+ req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
+ if (!req)
+ return BFA_STATUS_DEVBUSY;
+
+ /* build host command */
+ bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
+ bfa_fn_lpu(fcdiag->bfa));
+
+ for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
+ req->data[i] = QTEST_PAT_DEFAULT;
+
+ bfa_trc(fcdiag, fcdiag->qtest.queue);
+ /* ring door bell */
+ bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
+ return BFA_STATUS_OK;
+}
+
+static void
+bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
+ bfi_diag_qtest_rsp_t *rsp)
+{
+ struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
+ bfa_status_t status = BFA_STATUS_OK;
+ int i;
+
+ /* Check timer, should still be active */
+ if (!fcdiag->qtest.timer_active) {
+ bfa_trc(fcdiag, fcdiag->qtest.timer_active);
+ return;
+ }
+
+ /* update count */
+ fcdiag->qtest.count--;
+
+ /* Check result */
+ for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
+ if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
+ res->status = BFA_STATUS_DATACORRUPTED;
+ break;
+ }
+ }
+
+ if (res->status == BFA_STATUS_OK) {
+ if (fcdiag->qtest.count > 0) {
+ status = bfa_fcdiag_queuetest_send(fcdiag);
+ if (status == BFA_STATUS_OK)
+ return;
+ else
+ res->status = status;
+ } else if (fcdiag->qtest.all > 0 &&
+ fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
+ fcdiag->qtest.count = QTEST_CNT_DEFAULT;
+ fcdiag->qtest.queue++;
+ status = bfa_fcdiag_queuetest_send(fcdiag);
+ if (status == BFA_STATUS_OK)
+ return;
+ else
+ res->status = status;
+ }
+ }
+
+ /* Stop timer when we comp all queue */
+ if (fcdiag->qtest.timer_active) {
+ bfa_timer_stop(&fcdiag->qtest.timer);
+ fcdiag->qtest.timer_active = 0;
+ }
+ res->queue = fcdiag->qtest.queue;
+ res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
+ bfa_trc(fcdiag, res->count);
+ bfa_trc(fcdiag, res->status);
+ fcdiag->qtest.status = res->status;
+ fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
+ fcdiag->qtest.lock = 0;
+}
+
+static void
+bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
+ struct bfi_diag_lb_rsp_s *rsp)
+{
+ struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
+
+ res->numtxmfrm = be32_to_cpu(rsp->res.numtxmfrm);
+ res->numosffrm = be32_to_cpu(rsp->res.numosffrm);
+ res->numrcvfrm = be32_to_cpu(rsp->res.numrcvfrm);
+ res->badfrminf = be32_to_cpu(rsp->res.badfrminf);
+ res->badfrmnum = be32_to_cpu(rsp->res.badfrmnum);
+ res->status = rsp->res.status;
+ fcdiag->lb.status = rsp->res.status;
+ bfa_trc(fcdiag, fcdiag->lb.status);
+ fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
+ fcdiag->lb.lock = 0;
+ bfa_fcdiag_set_busy_status(fcdiag);
+}
+
+static bfa_status_t
+bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
+ struct bfa_diag_loopback_s *loopback)
+{
+ struct bfi_diag_lb_req_s *lb_req;
+
+ lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
+ if (!lb_req)
+ return BFA_STATUS_DEVBUSY;
+
+ /* build host command */
+ bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
+ bfa_fn_lpu(fcdiag->bfa));
+
+ lb_req->lb_mode = loopback->lb_mode;
+ lb_req->speed = loopback->speed;
+ lb_req->loopcnt = loopback->loopcnt;
+ lb_req->pattern = loopback->pattern;
+
+ /* ring door bell */
+ bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
+
+ bfa_trc(fcdiag, loopback->lb_mode);
+ bfa_trc(fcdiag, loopback->speed);
+ bfa_trc(fcdiag, loopback->loopcnt);
+ bfa_trc(fcdiag, loopback->pattern);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * cpe/rme intr handler
+ */
+void
+bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+
+ switch (msg->mhdr.msg_id) {
+ case BFI_DIAG_I2H_LOOPBACK:
+ bfa_fcdiag_loopback_comp(fcdiag,
+ (struct bfi_diag_lb_rsp_s *) msg);
+ break;
+ case BFI_DIAG_I2H_QTEST:
+ bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
+ break;
+ default:
+ bfa_trc(fcdiag, msg->mhdr.msg_id);
+ WARN_ON(1);
+ }
+}
+
+/*
+ * Loopback test
+ *
+ * @param[in] *bfa - bfa data struct
+ * @param[in] opmode - port operation mode
+ * @param[in] speed - port speed
+ * @param[in] lpcnt - loop count
+ * @param[in] pat - pattern to build packet
+ * @param[in] *result - pt to bfa_diag_loopback_result_t data struct
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback functioin arg
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
+ enum bfa_port_speed speed, u32 lpcnt, u32 pat,
+ struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
+ void *cbarg)
+{
+ struct bfa_diag_loopback_s loopback;
+ struct bfa_port_attr_s attr;
+ bfa_status_t status;
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+
+ if (!bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /* if port is PBC disabled, return error */
+ if (bfa_fcport_is_pbcdisabled(bfa)) {
+ bfa_trc(fcdiag, BFA_STATUS_PBC);
+ return BFA_STATUS_PBC;
+ }
+ if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
+ bfa_trc(fcdiag, opmode);
+ return BFA_STATUS_PORT_NOT_DISABLED;
+ }
+
+ /* Check if the speed is supported */
+ bfa_fcport_get_attr(bfa, &attr);
+ bfa_trc(fcdiag, attr.speed_supported);
+ if (speed > attr.speed_supported)
+ return BFA_STATUS_UNSUPP_SPEED;
+
+ /* For Mezz card, port speed entered needs to be checked */
+ if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
+ if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
+ if ((speed == BFA_PORT_SPEED_1GBPS) &&
+ (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
+ return BFA_STATUS_UNSUPP_SPEED;
+ if (!(speed == BFA_PORT_SPEED_1GBPS ||
+ speed == BFA_PORT_SPEED_2GBPS ||
+ speed == BFA_PORT_SPEED_4GBPS ||
+ speed == BFA_PORT_SPEED_8GBPS ||
+ speed == BFA_PORT_SPEED_16GBPS ||
+ speed == BFA_PORT_SPEED_AUTO))
+ return BFA_STATUS_UNSUPP_SPEED;
+ } else {
+ if (speed != BFA_PORT_SPEED_10GBPS)
+ return BFA_STATUS_UNSUPP_SPEED;
+ }
+ }
+
+ /* check to see if there is another destructive diag cmd running */
+ if (fcdiag->lb.lock) {
+ bfa_trc(fcdiag, fcdiag->lb.lock);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ fcdiag->lb.lock = 1;
+ loopback.lb_mode = opmode;
+ loopback.speed = speed;
+ loopback.loopcnt = lpcnt;
+ loopback.pattern = pat;
+ fcdiag->lb.result = result;
+ fcdiag->lb.cbfn = cbfn;
+ fcdiag->lb.cbarg = cbarg;
+ memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
+ bfa_fcdiag_set_busy_status(fcdiag);
+
+ /* Send msg to fw */
+ status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
+ return status;
+}
+
+/*
+ * DIAG queue test command
+ *
+ * @param[in] *bfa - bfa data struct
+ * @param[in] force - 1: don't do ioc op checking
+ * @param[in] queue - queue no. to test
+ * @param[in] *result - pt to bfa_diag_qtest_result_t data struct
+ * @param[in] cbfn - callback function
+ * @param[in] *cbarg - callback functioin arg
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
+ struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
+ void *cbarg)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ bfa_status_t status;
+ bfa_trc(fcdiag, force);
+ bfa_trc(fcdiag, queue);
+
+ if (!force && !bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /* check to see if there is another destructive diag cmd running */
+ if (fcdiag->qtest.lock) {
+ bfa_trc(fcdiag, fcdiag->qtest.lock);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ /* Initialization */
+ fcdiag->qtest.lock = 1;
+ fcdiag->qtest.cbfn = cbfn;
+ fcdiag->qtest.cbarg = cbarg;
+ fcdiag->qtest.result = result;
+ fcdiag->qtest.count = QTEST_CNT_DEFAULT;
+
+ /* Init test results */
+ fcdiag->qtest.result->status = BFA_STATUS_OK;
+ fcdiag->qtest.result->count = 0;
+
+ /* send */
+ if (queue < BFI_IOC_MAX_CQS) {
+ fcdiag->qtest.result->queue = (u8)queue;
+ fcdiag->qtest.queue = (u8)queue;
+ fcdiag->qtest.all = 0;
+ } else {
+ fcdiag->qtest.result->queue = 0;
+ fcdiag->qtest.queue = 0;
+ fcdiag->qtest.all = 1;
+ }
+ status = bfa_fcdiag_queuetest_send(fcdiag);
+
+ /* Start a timer */
+ if (status == BFA_STATUS_OK) {
+ bfa_timer_start(bfa, &fcdiag->qtest.timer,
+ bfa_fcdiag_queuetest_timeout, fcdiag,
+ BFA_DIAG_QTEST_TOV);
+ fcdiag->qtest.timer_active = 1;
+ }
+ return status;
+}
+
+/*
+ * DIAG PLB is running
+ *
+ * @param[in] *bfa - bfa data struct
+ *
+ * @param[out]
+ */
+bfa_status_t
+bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ return fcdiag->lb.lock ? BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index 5902a45c080f..fbe513a671b5 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -26,6 +26,7 @@
* Scatter-gather DMA related defines
*/
#define BFA_SGPG_MIN (16)
+#define BFA_SGPG_MAX (8192)
/*
* Alignment macro for SG page allocation
@@ -54,17 +55,21 @@ struct bfa_sgpg_s {
*/
#define BFA_SGPG_NPAGE(_nsges) (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
+/* Max SGPG dma segs required */
+#define BFA_SGPG_DMA_SEGS \
+ BFI_MEM_DMA_NSEGS(BFA_SGPG_MAX, (uint32_t)sizeof(struct bfi_sgpg_s))
+
struct bfa_sgpg_mod_s {
struct bfa_s *bfa;
int num_sgpgs; /* number of SG pages */
int free_sgpgs; /* number of free SG pages */
- struct bfa_sgpg_s *hsgpg_arr; /* BFA SG page array */
- struct bfi_sgpg_s *sgpg_arr; /* actual SG page array */
- u64 sgpg_arr_pa; /* SG page array DMA addr */
struct list_head sgpg_q; /* queue of free SG pages */
struct list_head sgpg_wait_q; /* wait queue for SG pages */
+ struct bfa_mem_dma_s dma_seg[BFA_SGPG_DMA_SEGS];
+ struct bfa_mem_kva_s kva_seg;
};
#define BFA_SGPG_MOD(__bfa) (&(__bfa)->modules.sgpg_mod)
+#define BFA_MEM_SGPG_KVA(__bfa) (&(BFA_SGPG_MOD(__bfa)->kva_seg))
bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
int nsgpgs);
@@ -79,26 +84,32 @@ void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
* FCXP related defines
*/
#define BFA_FCXP_MIN (1)
+#define BFA_FCXP_MAX (256)
#define BFA_FCXP_MAX_IBUF_SZ (2 * 1024 + 256)
#define BFA_FCXP_MAX_LBUF_SZ (4 * 1024 + 256)
+/* Max FCXP dma segs required */
+#define BFA_FCXP_DMA_SEGS \
+ BFI_MEM_DMA_NSEGS(BFA_FCXP_MAX, \
+ (u32)BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ)
+
struct bfa_fcxp_mod_s {
struct bfa_s *bfa; /* backpointer to BFA */
struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */
u16 num_fcxps; /* max num FCXP requests */
struct list_head fcxp_free_q; /* free FCXPs */
struct list_head fcxp_active_q; /* active FCXPs */
- void *req_pld_list_kva; /* list of FCXP req pld */
- u64 req_pld_list_pa; /* list of FCXP req pld */
- void *rsp_pld_list_kva; /* list of FCXP resp pld */
- u64 rsp_pld_list_pa; /* list of FCXP resp pld */
struct list_head wait_q; /* wait queue for free fcxp */
+ struct list_head fcxp_unused_q; /* unused fcxps */
u32 req_pld_sz;
u32 rsp_pld_sz;
+ struct bfa_mem_dma_s dma_seg[BFA_FCXP_DMA_SEGS];
+ struct bfa_mem_kva_s kva_seg;
};
#define BFA_FCXP_MOD(__bfa) (&(__bfa)->modules.fcxp_mod)
#define BFA_FCXP_FROM_TAG(__mod, __tag) (&(__mod)->fcxp_list[__tag])
+#define BFA_MEM_FCXP_KVA(__bfa) (&(BFA_FCXP_MOD(__bfa)->kva_seg))
typedef void (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
void *cb_arg, bfa_status_t req_status,
@@ -206,13 +217,15 @@ struct bfa_fcxp_wqe_s {
#define BFA_FCXP_RSP_FCHS(_fcxp) (&((_fcxp)->rsp_info.fchs))
#define BFA_FCXP_RSP_PLD(_fcxp) (bfa_fcxp_get_rspbuf(_fcxp))
-#define BFA_FCXP_REQ_PLD_PA(_fcxp) \
- ((_fcxp)->fcxp_mod->req_pld_list_pa + \
- ((_fcxp)->fcxp_mod->req_pld_sz * (_fcxp)->fcxp_tag))
+#define BFA_FCXP_REQ_PLD_PA(_fcxp) \
+ bfa_mem_get_dmabuf_pa((_fcxp)->fcxp_mod, (_fcxp)->fcxp_tag, \
+ (_fcxp)->fcxp_mod->req_pld_sz + (_fcxp)->fcxp_mod->rsp_pld_sz)
-#define BFA_FCXP_RSP_PLD_PA(_fcxp) \
- ((_fcxp)->fcxp_mod->rsp_pld_list_pa + \
- ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
+/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
+#define BFA_FCXP_RSP_PLD_PA(_fcxp) \
+ (bfa_mem_get_dmabuf_pa((_fcxp)->fcxp_mod, (_fcxp)->fcxp_tag, \
+ (_fcxp)->fcxp_mod->req_pld_sz + (_fcxp)->fcxp_mod->rsp_pld_sz) + \
+ (_fcxp)->fcxp_mod->req_pld_sz)
void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
@@ -238,10 +251,13 @@ struct bfa_rport_mod_s {
struct bfa_rport_s *rps_list; /* list of rports */
struct list_head rp_free_q; /* free bfa_rports */
struct list_head rp_active_q; /* free bfa_rports */
+ struct list_head rp_unused_q; /* unused bfa rports */
u16 num_rports; /* number of rports */
+ struct bfa_mem_kva_s kva_seg;
};
#define BFA_RPORT_MOD(__bfa) (&(__bfa)->modules.rport_mod)
+#define BFA_MEM_RPORT_KVA(__bfa) (&(BFA_RPORT_MOD(__bfa)->kva_seg))
/*
* Convert rport tag to RPORT
@@ -254,6 +270,7 @@ struct bfa_rport_mod_s {
* protected functions
*/
void bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw);
/*
* BFA rport information.
@@ -298,7 +315,7 @@ struct bfa_rport_s {
*/
#define BFA_UF_MIN (4)
-
+#define BFA_UF_MAX (256)
struct bfa_uf_s {
struct list_head qe; /* queue element */
@@ -326,36 +343,41 @@ struct bfa_uf_s {
*/
typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
+#define BFA_UF_BUFSZ (2 * 1024 + 256)
+
+struct bfa_uf_buf_s {
+ u8 d[BFA_UF_BUFSZ];
+};
+
+#define BFA_PER_UF_DMA_SZ \
+ (u32)BFA_ROUNDUP(sizeof(struct bfa_uf_buf_s), BFA_DMA_ALIGN_SZ)
+
+/* Max UF dma segs required */
+#define BFA_UF_DMA_SEGS BFI_MEM_DMA_NSEGS(BFA_UF_MAX, BFA_PER_UF_DMA_SZ)
+
struct bfa_uf_mod_s {
struct bfa_s *bfa; /* back pointer to BFA */
struct bfa_uf_s *uf_list; /* array of UFs */
u16 num_ufs; /* num unsolicited rx frames */
struct list_head uf_free_q; /* free UFs */
struct list_head uf_posted_q; /* UFs posted to IOC */
- struct bfa_uf_buf_s *uf_pbs_kva; /* list UF bufs request pld */
- u64 uf_pbs_pa; /* phy addr for UF bufs */
+ struct list_head uf_unused_q; /* unused UF's */
struct bfi_uf_buf_post_s *uf_buf_posts;
/* pre-built UF post msgs */
bfa_cb_uf_recv_t ufrecv; /* uf recv handler function */
void *cbarg; /* uf receive handler arg */
+ struct bfa_mem_dma_s dma_seg[BFA_UF_DMA_SEGS];
+ struct bfa_mem_kva_s kva_seg;
};
#define BFA_UF_MOD(__bfa) (&(__bfa)->modules.uf_mod)
+#define BFA_MEM_UF_KVA(__bfa) (&(BFA_UF_MOD(__bfa)->kva_seg))
#define ufm_pbs_pa(_ufmod, _uftag) \
- ((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
+ bfa_mem_get_dmabuf_pa(_ufmod, _uftag, BFA_PER_UF_DMA_SZ)
void bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#define BFA_UF_BUFSZ (2 * 1024 + 256)
-
-/*
- * @todo private
- */
-struct bfa_uf_buf_s {
- u8 d[BFA_UF_BUFSZ];
-};
-
+void bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw);
/*
* LPS - bfa lport login/logout service interface
@@ -364,7 +386,8 @@ struct bfa_lps_s {
struct list_head qe; /* queue element */
struct bfa_s *bfa; /* parent bfa instance */
bfa_sm_t sm; /* finite state machine */
- u8 lp_tag; /* lport tag */
+ u8 bfa_tag; /* lport tag */
+ u8 fw_tag; /* lport fw tag */
u8 reqq; /* lport request queue */
u8 alpa; /* ALPA for loop topologies */
u32 lp_pid; /* lport port ID */
@@ -377,6 +400,8 @@ struct bfa_lps_s {
bfa_status_t status; /* login status */
u16 pdusz; /* max receive PDU size */
u16 pr_bbcred; /* BB_CREDIT from peer */
+ u8 pr_bbscn; /* BB_SCN from peer */
+ u8 bb_scn; /* local BB_SCN */
u8 lsrjt_rsn; /* LSRJT reason */
u8 lsrjt_expl; /* LSRJT explanation */
wwn_t pwwn; /* port wwn of lport */
@@ -395,12 +420,15 @@ struct bfa_lps_s {
struct bfa_lps_mod_s {
struct list_head lps_free_q;
struct list_head lps_active_q;
+ struct list_head lps_login_q;
struct bfa_lps_s *lps_arr;
int num_lps;
+ struct bfa_mem_kva_s kva_seg;
};
#define BFA_LPS_MOD(__bfa) (&(__bfa)->modules.lps_mod)
#define BFA_LPS_FROM_TAG(__mod, __tag) (&(__mod)->lps_arr[__tag])
+#define BFA_MEM_LPS_KVA(__bfa) (&(BFA_LPS_MOD(__bfa)->kva_seg))
/*
* external functions
@@ -477,11 +505,14 @@ struct bfa_fcport_s {
bfa_boolean_t diag_busy; /* diag busy status */
bfa_boolean_t beacon; /* port beacon status */
bfa_boolean_t link_e2e_beacon; /* link beacon status */
+ bfa_boolean_t bbsc_op_state; /* Cred recov Oper State */
struct bfa_fcport_trunk_s trunk;
u16 fcoe_vlan;
+ struct bfa_mem_dma_s fcport_dma;
};
#define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport)
+#define BFA_MEM_FCPORT_DMA(__bfa) (&(BFA_FCPORT_MOD(__bfa)->fcport_dma))
/*
* protected functions
@@ -515,8 +546,10 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
-void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
+void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn);
bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
+void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+ bfa_boolean_t link_e2e_beacon);
bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
union bfa_fcport_stats_u *stats,
@@ -524,6 +557,9 @@ bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
void *cbarg);
bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
+bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
+void bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state);
/*
* bfa rport API functions
@@ -577,6 +613,7 @@ void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
+void bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw);
static inline void *
bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
@@ -606,11 +643,12 @@ struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
void bfa_lps_delete(struct bfa_lps_s *lps);
void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
u16 pdusz, wwn_t pwwn, wwn_t nwwn,
- bfa_boolean_t auth_en);
+ bfa_boolean_t auth_en, u8 bb_scn);
void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
wwn_t pwwn, wwn_t nwwn);
void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
void bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, u32 n2n_pid);
+u8 bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag);
u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
@@ -618,4 +656,57 @@ void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
+/* FAA specific APIs */
+bfa_status_t bfa_faa_enable(struct bfa_s *bfa,
+ bfa_cb_iocfc_t cbfn, void *cbarg);
+bfa_status_t bfa_faa_disable(struct bfa_s *bfa,
+ bfa_cb_iocfc_t cbfn, void *cbarg);
+bfa_status_t bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
+ bfa_cb_iocfc_t cbfn, void *cbarg);
+
+/*
+ * FC DIAG data structure
+ */
+struct bfa_fcdiag_qtest_s {
+ struct bfa_diag_qtest_result_s *result;
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+ struct bfa_timer_s timer;
+ u32 status;
+ u32 count;
+ u8 lock;
+ u8 queue;
+ u8 all;
+ u8 timer_active;
+};
+
+struct bfa_fcdiag_lb_s {
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+ void *result;
+ bfa_boolean_t lock;
+ u32 status;
+};
+
+struct bfa_fcdiag_s {
+ struct bfa_s *bfa; /* Back pointer to BFA */
+ struct bfa_trc_mod_s *trcmod;
+ struct bfa_fcdiag_lb_s lb;
+ struct bfa_fcdiag_qtest_s qtest;
+};
+
+#define BFA_FCDIAG_MOD(__bfa) (&(__bfa)->modules.fcdiag)
+
+void bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+bfa_status_t bfa_fcdiag_loopback(struct bfa_s *bfa,
+ enum bfa_port_opmode opmode,
+ enum bfa_port_speed speed, u32 lpcnt, u32 pat,
+ struct bfa_diag_loopback_result_s *result,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore,
+ u32 queue, struct bfa_diag_qtest_result_s *result,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_fcdiag_lb_is_running(struct bfa_s *bfa);
+
#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 59b5e9b61d71..beb30a748ea5 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -56,14 +56,15 @@ int fdmi_enable = BFA_TRUE;
int pcie_max_read_reqsz;
int bfa_debugfs_enable = 1;
int msix_disable_cb = 0, msix_disable_ct = 0;
+int max_xfer_size = BFAD_MAX_SECTORS >> 1;
/* Firmware releated */
-u32 bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
-u32 *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
+u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
+u32 *bfi_image_cb, *bfi_image_ct, *bfi_image_ct2;
-#define BFAD_FW_FILE_CT_FC "ctfw_fc.bin"
-#define BFAD_FW_FILE_CT_CNA "ctfw_cna.bin"
-#define BFAD_FW_FILE_CB_FC "cbfw_fc.bin"
+#define BFAD_FW_FILE_CB "cbfw.bin"
+#define BFAD_FW_FILE_CT "ctfw.bin"
+#define BFAD_FW_FILE_CT2 "ct2fw.bin"
static u32 *bfad_load_fwimg(struct pci_dev *pdev);
static void bfad_free_fwimg(void);
@@ -71,18 +72,18 @@ static void bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
u32 *bfi_image_size, char *fw_name);
static const char *msix_name_ct[] = {
+ "ctrl",
"cpe0", "cpe1", "cpe2", "cpe3",
- "rme0", "rme1", "rme2", "rme3",
- "ctrl" };
+ "rme0", "rme1", "rme2", "rme3" };
static const char *msix_name_cb[] = {
"cpe0", "cpe1", "cpe2", "cpe3",
"rme0", "rme1", "rme2", "rme3",
"eemc", "elpu0", "elpu1", "epss", "mlpu" };
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
-MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
+MODULE_FIRMWARE(BFAD_FW_FILE_CB);
+MODULE_FIRMWARE(BFAD_FW_FILE_CT);
+MODULE_FIRMWARE(BFAD_FW_FILE_CT2);
module_param(os_name, charp, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(os_name, "OS name of the hba host machine");
@@ -144,6 +145,9 @@ MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "
module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
" Range[false:0|true:1]");
+module_param(max_xfer_size, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_xfer_size, "default=32MB,"
+ " Range[64k|128k|256k|512k|1024k|2048k]");
static void
bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
@@ -527,28 +531,26 @@ bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
void
bfad_hal_mem_release(struct bfad_s *bfad)
{
- int i;
struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
- struct bfa_mem_elem_s *meminfo_elem;
-
- for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
- meminfo_elem = &hal_meminfo->meminfo[i];
- if (meminfo_elem->kva != NULL) {
- switch (meminfo_elem->mem_type) {
- case BFA_MEM_TYPE_KVA:
- vfree(meminfo_elem->kva);
- break;
- case BFA_MEM_TYPE_DMA:
- dma_free_coherent(&bfad->pcidev->dev,
- meminfo_elem->mem_len,
- meminfo_elem->kva,
- (dma_addr_t) meminfo_elem->dma);
- break;
- default:
- WARN_ON(1);
- break;
- }
- }
+ struct bfa_mem_dma_s *dma_info, *dma_elem;
+ struct bfa_mem_kva_s *kva_info, *kva_elem;
+ struct list_head *dm_qe, *km_qe;
+
+ dma_info = &hal_meminfo->dma_info;
+ kva_info = &hal_meminfo->kva_info;
+
+ /* Iterate through the KVA meminfo queue */
+ list_for_each(km_qe, &kva_info->qe) {
+ kva_elem = (struct bfa_mem_kva_s *) km_qe;
+ vfree(kva_elem->kva);
+ }
+
+ /* Iterate through the DMA meminfo queue */
+ list_for_each(dm_qe, &dma_info->qe) {
+ dma_elem = (struct bfa_mem_dma_s *) dm_qe;
+ dma_free_coherent(&bfad->pcidev->dev,
+ dma_elem->mem_len, dma_elem->kva,
+ (dma_addr_t) dma_elem->dma);
}
memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s));
@@ -563,15 +565,15 @@ bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
bfa_cfg->fwcfg.num_ioim_reqs = num_ios;
if (num_tms > 0)
bfa_cfg->fwcfg.num_tskim_reqs = num_tms;
- if (num_fcxps > 0)
+ if (num_fcxps > 0 && num_fcxps <= BFA_FCXP_MAX)
bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps;
- if (num_ufbufs > 0)
+ if (num_ufbufs > 0 && num_ufbufs <= BFA_UF_MAX)
bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs;
if (reqq_size > 0)
bfa_cfg->drvcfg.num_reqq_elems = reqq_size;
if (rspq_size > 0)
bfa_cfg->drvcfg.num_rspq_elems = rspq_size;
- if (num_sgpgs > 0)
+ if (num_sgpgs > 0 && num_sgpgs <= BFA_SGPG_MAX)
bfa_cfg->drvcfg.num_sgpgs = num_sgpgs;
/*
@@ -591,85 +593,46 @@ bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
bfa_status_t
bfad_hal_mem_alloc(struct bfad_s *bfad)
{
- int i;
struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
- struct bfa_mem_elem_s *meminfo_elem;
- dma_addr_t phys_addr;
- void *kva;
+ struct bfa_mem_dma_s *dma_info, *dma_elem;
+ struct bfa_mem_kva_s *kva_info, *kva_elem;
+ struct list_head *dm_qe, *km_qe;
bfa_status_t rc = BFA_STATUS_OK;
- int retry_count = 0;
- int reset_value = 1;
- int min_num_sgpgs = 512;
+ dma_addr_t phys_addr;
bfa_cfg_get_default(&bfad->ioc_cfg);
-
-retry:
bfad_update_hal_cfg(&bfad->ioc_cfg);
bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs;
- bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo);
-
- for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
- meminfo_elem = &hal_meminfo->meminfo[i];
- switch (meminfo_elem->mem_type) {
- case BFA_MEM_TYPE_KVA:
- kva = vmalloc(meminfo_elem->mem_len);
- if (kva == NULL) {
- bfad_hal_mem_release(bfad);
- rc = BFA_STATUS_ENOMEM;
- goto ext;
- }
- memset(kva, 0, meminfo_elem->mem_len);
- meminfo_elem->kva = kva;
- break;
- case BFA_MEM_TYPE_DMA:
- kva = dma_alloc_coherent(&bfad->pcidev->dev,
- meminfo_elem->mem_len, &phys_addr, GFP_KERNEL);
- if (kva == NULL) {
- bfad_hal_mem_release(bfad);
- /*
- * If we cannot allocate with default
- * num_sgpages try with half the value.
- */
- if (num_sgpgs > min_num_sgpgs) {
- printk(KERN_INFO
- "bfad[%d]: memory allocation failed"
- " with num_sgpgs: %d\n",
- bfad->inst_no, num_sgpgs);
- nextLowerInt(&num_sgpgs);
- printk(KERN_INFO
- "bfad[%d]: trying to allocate memory"
- " with num_sgpgs: %d\n",
- bfad->inst_no, num_sgpgs);
- retry_count++;
- goto retry;
- } else {
- if (num_sgpgs_parm > 0)
- num_sgpgs = num_sgpgs_parm;
- else {
- reset_value =
- (1 << retry_count);
- num_sgpgs *= reset_value;
- }
- rc = BFA_STATUS_ENOMEM;
- goto ext;
- }
- }
-
- if (num_sgpgs_parm > 0)
- num_sgpgs = num_sgpgs_parm;
- else {
- reset_value = (1 << retry_count);
- num_sgpgs *= reset_value;
- }
-
- memset(kva, 0, meminfo_elem->mem_len);
- meminfo_elem->kva = kva;
- meminfo_elem->dma = phys_addr;
- break;
- default:
- break;
+ bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo, &bfad->bfa);
+
+ dma_info = &hal_meminfo->dma_info;
+ kva_info = &hal_meminfo->kva_info;
+
+ /* Iterate through the KVA meminfo queue */
+ list_for_each(km_qe, &kva_info->qe) {
+ kva_elem = (struct bfa_mem_kva_s *) km_qe;
+ kva_elem->kva = vmalloc(kva_elem->mem_len);
+ if (kva_elem->kva == NULL) {
+ bfad_hal_mem_release(bfad);
+ rc = BFA_STATUS_ENOMEM;
+ goto ext;
+ }
+ memset(kva_elem->kva, 0, kva_elem->mem_len);
+ }
+ /* Iterate through the DMA meminfo queue */
+ list_for_each(dm_qe, &dma_info->qe) {
+ dma_elem = (struct bfa_mem_dma_s *) dm_qe;
+ dma_elem->kva = dma_alloc_coherent(&bfad->pcidev->dev,
+ dma_elem->mem_len,
+ &phys_addr, GFP_KERNEL);
+ if (dma_elem->kva == NULL) {
+ bfad_hal_mem_release(bfad);
+ rc = BFA_STATUS_ENOMEM;
+ goto ext;
}
+ dma_elem->dma = phys_addr;
+ memset(dma_elem->kva, 0, dma_elem->mem_len);
}
ext:
return rc;
@@ -780,13 +743,17 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
pci_set_master(pdev);
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
+ if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) ||
+ (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)) {
+ if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) ||
+ (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) {
printk(KERN_ERR "pci_set_dma_mask fail %p\n", pdev);
goto out_release_region;
}
+ }
bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+ bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2));
if (bfad->pci_bar0_kva == NULL) {
printk(KERN_ERR "Fail to map bar0\n");
@@ -797,6 +764,7 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn);
bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva;
bfad->hal_pcidev.device_id = pdev->device;
+ bfad->hal_pcidev.ssid = pdev->subsystem_device;
bfad->pci_name = pci_name(pdev);
bfad->pci_attr.vendor_id = pdev->vendor;
@@ -868,6 +836,7 @@ void
bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
{
pci_iounmap(pdev, bfad->pci_bar0_kva);
+ pci_iounmap(pdev, bfad->pci_bar2_kva);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
@@ -908,12 +877,29 @@ bfad_drv_init(struct bfad_s *bfad)
bfad->bfa_fcs.trcmod = bfad->trcmod;
bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
bfad->bfa_fcs.fdmi_enabled = fdmi_enable;
+ bfa_fcs_init(&bfad->bfa_fcs);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
+ /* configure base port */
+ rc = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
+ if (rc != BFA_STATUS_OK)
+ goto out_cfg_pport_fail;
+
return BFA_STATUS_OK;
+out_cfg_pport_fail:
+ /* fcs exit - on cfg pport failure */
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ init_completion(&bfad->comp);
+ bfad->pport.flags |= BFAD_PORT_DELETE;
+ bfa_fcs_exit(&bfad->bfa_fcs);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ wait_for_completion(&bfad->comp);
+ /* bfa detach - free hal memory */
+ bfa_detach(&bfad->bfa);
+ bfad_hal_mem_release(bfad);
out_hal_mem_alloc_failure:
return BFA_STATUS_FAILED;
}
@@ -945,6 +931,7 @@ bfad_drv_start(struct bfad_s *bfad)
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_iocfc_start(&bfad->bfa);
+ bfa_fcs_pbc_vport_init(&bfad->bfa_fcs);
bfa_fcs_fabric_modstart(&bfad->bfa_fcs);
bfad->bfad_flags |= BFAD_HAL_START_DONE;
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -1032,6 +1019,12 @@ bfad_start_ops(struct bfad_s *bfad) {
struct bfad_vport_s *vport, *vport_new;
struct bfa_fcs_driver_info_s driver_info;
+ /* Limit min/max. xfer size to [64k-32MB] */
+ if (max_xfer_size < BFAD_MIN_SECTORS >> 1)
+ max_xfer_size = BFAD_MIN_SECTORS >> 1;
+ if (max_xfer_size > BFAD_MAX_SECTORS >> 1)
+ max_xfer_size = BFAD_MAX_SECTORS >> 1;
+
/* Fill the driver_info info to fcs*/
memset(&driver_info, 0, sizeof(driver_info));
strncpy(driver_info.version, BFAD_DRIVER_VERSION,
@@ -1049,19 +1042,19 @@ bfad_start_ops(struct bfad_s *bfad) {
strncpy(driver_info.os_device_name, bfad->pci_name,
sizeof(driver_info.os_device_name - 1));
- /* FCS INIT */
+ /* FCS driver info init */
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
- bfa_fcs_init(&bfad->bfa_fcs);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
- if (retval != BFA_STATUS_OK) {
- if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
- bfa_sm_set_state(bfad, bfad_sm_failed);
- bfad_stop(bfad);
- return BFA_STATUS_FAILED;
- }
+ /*
+ * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
+ * with values learned during bfa_init firmware GETATTR REQ.
+ */
+ bfa_fcs_update_cfg(&bfad->bfa_fcs);
+
+ /* Setup fc host fixed attribute if the lk supports */
+ bfad_fc_host_init(bfad->pport.im_port);
/* BFAD level FC4 IM specific resource allocation */
retval = bfad_im_probe(bfad);
@@ -1233,8 +1226,8 @@ bfad_install_msix_handler(struct bfad_s *bfad)
for (i = 0; i < bfad->nvec; i++) {
sprintf(bfad->msix_tab[i].name, "bfa-%s-%s",
bfad->pci_name,
- ((bfa_asic_id_ct(bfad->hal_pcidev.device_id)) ?
- msix_name_ct[i] : msix_name_cb[i]));
+ ((bfa_asic_id_cb(bfad->hal_pcidev.device_id)) ?
+ msix_name_cb[i] : msix_name_ct[i]));
error = request_irq(bfad->msix_tab[i].msix.vector,
(irq_handler_t) bfad_msix, 0,
@@ -1248,6 +1241,9 @@ bfad_install_msix_handler(struct bfad_s *bfad)
free_irq(bfad->msix_tab[j].msix.vector,
&bfad->msix_tab[j]);
+ bfad->bfad_flags &= ~BFAD_MSIX_ON;
+ pci_disable_msix(bfad->pcidev);
+
return 1;
}
}
@@ -1265,6 +1261,7 @@ bfad_setup_intr(struct bfad_s *bfad)
u32 mask = 0, i, num_bit = 0, max_bit = 0;
struct msix_entry msix_entries[MAX_MSIX_ENTRY];
struct pci_dev *pdev = bfad->pcidev;
+ u16 reg;
/* Call BFA to get the msix map for this PCI function. */
bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
@@ -1272,8 +1269,8 @@ bfad_setup_intr(struct bfad_s *bfad)
/* Set up the msix entry table */
bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
- if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
- (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
+ if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) ||
+ (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) {
error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
if (error) {
@@ -1294,6 +1291,13 @@ bfad_setup_intr(struct bfad_s *bfad)
goto line_based;
}
+ /* Disable INTX in MSI-X mode */
+ pci_read_config_word(pdev, PCI_COMMAND, &reg);
+
+ if (!(reg & PCI_COMMAND_INTX_DISABLE))
+ pci_write_config_word(pdev, PCI_COMMAND,
+ reg | PCI_COMMAND_INTX_DISABLE);
+
/* Save the vectors */
for (i = 0; i < bfad->nvec; i++) {
bfa_trc(bfad, msix_entries[i].vector);
@@ -1315,6 +1319,7 @@ line_based:
/* Enable interrupt handler failed */
return 1;
}
+ bfad->bfad_flags |= BFAD_INTX_ON;
return error;
}
@@ -1331,7 +1336,7 @@ bfad_remove_intr(struct bfad_s *bfad)
pci_disable_msix(bfad->pcidev);
bfad->bfad_flags &= ~BFAD_MSIX_ON;
- } else {
+ } else if (bfad->bfad_flags & BFAD_INTX_ON) {
free_irq(bfad->pcidev->irq, bfad);
}
}
@@ -1501,6 +1506,14 @@ struct pci_device_id bfad_id_table[] = {
.class = (PCI_CLASS_SERIAL_FIBER << 8),
.class_mask = ~0,
},
+ {
+ .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+ .device = BFA_PCI_DEVICE_ID_CT2,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_SERIAL_FIBER << 8),
+ .class_mask = ~0,
+ },
{0, 0},
};
@@ -1594,33 +1607,33 @@ out:
static u32 *
bfad_load_fwimg(struct pci_dev *pdev)
{
- if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
- if (bfi_image_ct_fc_size == 0)
- bfad_read_firmware(pdev, &bfi_image_ct_fc,
- &bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
- return bfi_image_ct_fc;
- } else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
- if (bfi_image_ct_cna_size == 0)
- bfad_read_firmware(pdev, &bfi_image_ct_cna,
- &bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
- return bfi_image_ct_cna;
+ if (pdev->device == BFA_PCI_DEVICE_ID_CT2) {
+ if (bfi_image_ct2_size == 0)
+ bfad_read_firmware(pdev, &bfi_image_ct2,
+ &bfi_image_ct2_size, BFAD_FW_FILE_CT2);
+ return bfi_image_ct2;
+ } else if (bfa_asic_id_ct(pdev->device)) {
+ if (bfi_image_ct_size == 0)
+ bfad_read_firmware(pdev, &bfi_image_ct,
+ &bfi_image_ct_size, BFAD_FW_FILE_CT);
+ return bfi_image_ct;
} else {
- if (bfi_image_cb_fc_size == 0)
- bfad_read_firmware(pdev, &bfi_image_cb_fc,
- &bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
- return bfi_image_cb_fc;
+ if (bfi_image_cb_size == 0)
+ bfad_read_firmware(pdev, &bfi_image_cb,
+ &bfi_image_cb_size, BFAD_FW_FILE_CB);
+ return bfi_image_cb;
}
}
static void
bfad_free_fwimg(void)
{
- if (bfi_image_ct_fc_size && bfi_image_ct_fc)
- vfree(bfi_image_ct_fc);
- if (bfi_image_ct_cna_size && bfi_image_ct_cna)
- vfree(bfi_image_ct_cna);
- if (bfi_image_cb_fc_size && bfi_image_cb_fc)
- vfree(bfi_image_cb_fc);
+ if (bfi_image_ct2_size && bfi_image_ct2)
+ vfree(bfi_image_ct2);
+ if (bfi_image_ct_size && bfi_image_ct)
+ vfree(bfi_image_ct);
+ if (bfi_image_cb_size && bfi_image_cb)
+ vfree(bfi_image_cb);
}
module_init(bfad_init);
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index a94ea4235433..9d95844ab463 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -218,6 +218,9 @@ bfad_im_get_host_speed(struct Scsi_Host *shost)
case BFA_PORT_SPEED_10GBPS:
fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
break;
+ case BFA_PORT_SPEED_16GBPS:
+ fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
+ break;
case BFA_PORT_SPEED_8GBPS:
fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
break;
@@ -580,6 +583,8 @@ struct fc_function_template bfad_im_fc_function_template = {
.vport_create = bfad_im_vport_create,
.vport_delete = bfad_im_vport_delete,
.vport_disable = bfad_im_vport_disable,
+ .bsg_request = bfad_im_bsg_request,
+ .bsg_timeout = bfad_im_bsg_timeout,
};
struct fc_function_template bfad_im_vport_fc_function_template = {
@@ -674,8 +679,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
struct bfad_s *bfad = im_port->bfad;
char model[BFA_ADAPTER_MODEL_NAME_LEN];
char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+ int nports = 0;
bfa_get_adapter_model(&bfad->bfa, model);
+ nports = bfa_get_nports(&bfad->bfa);
if (!strcmp(model, "Brocade-425"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 4Gbps PCIe dual port FC HBA");
@@ -684,10 +691,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
"Brocade 8Gbps PCIe dual port FC HBA");
else if (!strcmp(model, "Brocade-42B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "HP 4Gbps PCIe dual port FC HBA");
+ "Brocade 4Gbps PCIe dual port FC HBA for HP");
else if (!strcmp(model, "Brocade-82B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "HP 8Gbps PCIe dual port FC HBA");
+ "Brocade 8Gbps PCIe dual port FC HBA for HP");
else if (!strcmp(model, "Brocade-1010"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps single port CNA");
@@ -696,7 +703,7 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
"Brocade 10Gbps dual port CNA");
else if (!strcmp(model, "Brocade-1007"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "Brocade 10Gbps CNA");
+ "Brocade 10Gbps CNA for IBM Blade Center");
else if (!strcmp(model, "Brocade-415"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 4Gbps PCIe single port FC HBA");
@@ -705,17 +712,45 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
"Brocade 8Gbps PCIe single port FC HBA");
else if (!strcmp(model, "Brocade-41B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "HP 4Gbps PCIe single port FC HBA");
+ "Brocade 4Gbps PCIe single port FC HBA for HP");
else if (!strcmp(model, "Brocade-81B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "HP 8Gbps PCIe single port FC HBA");
+ "Brocade 8Gbps PCIe single port FC HBA for HP");
else if (!strcmp(model, "Brocade-804"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "HP Bladesystem C-class 8Gbps FC HBA");
- else if (!strcmp(model, "Brocade-902"))
+ "Brocade 8Gbps FC HBA for HP Bladesystem C-class");
+ else if (!strcmp(model, "Brocade-902") ||
+ !strcmp(model, "Brocade-1741"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "Brocade 10Gbps CNA");
- else
+ "Brocade 10Gbps CNA for Dell M-Series Blade Servers");
+ else if (strstr(model, "Brocade-1560")) {
+ if (nports == 1)
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 16Gbps PCIe single port FC HBA");
+ else
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 16Gbps PCIe dual port FC HBA");
+ } else if (strstr(model, "Brocade-1710")) {
+ if (nports == 1)
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps single port CNA");
+ else
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps dual port CNA");
+ } else if (strstr(model, "Brocade-1860")) {
+ if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps single port CNA");
+ else if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 16Gbps PCIe single port FC HBA");
+ else if (nports == 2 && bfa_ioc_is_cna(&bfad->bfa.ioc))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps dual port CNA");
+ else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 16Gbps PCIe dual port FC HBA");
+ } else
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Invalid Model");
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
new file mode 100644
index 000000000000..89f863ed2334
--- /dev/null
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -0,0 +1,2163 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus 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.
+ */
+
+#include <linux/uaccess.h>
+#include "bfad_drv.h"
+#include "bfad_im.h"
+#include "bfad_bsg.h"
+
+BFA_TRC_FILE(LDRV, BSG);
+
+int
+bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ int rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ /* If IOC is not in disabled state - return */
+ if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_IOC_FAILURE;
+ return rc;
+ }
+
+ init_completion(&bfad->enable_comp);
+ bfa_iocfc_enable(&bfad->bfa);
+ iocmd->status = BFA_STATUS_OK;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ wait_for_completion(&bfad->enable_comp);
+
+ return rc;
+}
+
+int
+bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ int rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ if (bfad->disable_active) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return EBUSY;
+ }
+
+ bfad->disable_active = BFA_TRUE;
+ init_completion(&bfad->disable_comp);
+ bfa_iocfc_disable(&bfad->bfa);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ wait_for_completion(&bfad->disable_comp);
+ bfad->disable_active = BFA_FALSE;
+ iocmd->status = BFA_STATUS_OK;
+
+ return rc;
+}
+
+static int
+bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
+{
+ int i;
+ struct bfa_bsg_ioc_info_s *iocmd = (struct bfa_bsg_ioc_info_s *)cmd;
+ struct bfad_im_port_s *im_port;
+ struct bfa_port_attr_s pattr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_fcport_get_attr(&bfad->bfa, &pattr);
+ iocmd->nwwn = pattr.nwwn;
+ iocmd->pwwn = pattr.pwwn;
+ iocmd->ioc_type = bfa_get_type(&bfad->bfa);
+ iocmd->mac = bfa_get_mac(&bfad->bfa);
+ iocmd->factory_mac = bfa_get_mfg_mac(&bfad->bfa);
+ bfa_get_adapter_serial_num(&bfad->bfa, iocmd->serialnum);
+ iocmd->factorynwwn = pattr.factorynwwn;
+ iocmd->factorypwwn = pattr.factorypwwn;
+ im_port = bfad->pport.im_port;
+ iocmd->host = im_port->shost->host_no;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ strcpy(iocmd->name, bfad->adapter_name);
+ strcpy(iocmd->port_name, bfad->port_name);
+ strcpy(iocmd->hwpath, bfad->pci_name);
+
+ /* set adapter hw path */
+ strcpy(iocmd->adapter_hwpath, bfad->pci_name);
+ i = strlen(iocmd->adapter_hwpath) - 1;
+ while (iocmd->adapter_hwpath[i] != '.')
+ i--;
+ iocmd->adapter_hwpath[i] = '\0';
+ iocmd->status = BFA_STATUS_OK;
+ return 0;
+}
+
+static int
+bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_ioc_attr_s *iocmd = (struct bfa_bsg_ioc_attr_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_ioc_get_attr(&bfad->bfa.ioc, &iocmd->ioc_attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ /* fill in driver attr info */
+ strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME);
+ strncpy(iocmd->ioc_attr.driver_attr.driver_ver,
+ BFAD_DRIVER_VERSION, BFA_VERSION_LEN);
+ strcpy(iocmd->ioc_attr.driver_attr.fw_ver,
+ iocmd->ioc_attr.adapter_attr.fw_ver);
+ strcpy(iocmd->ioc_attr.driver_attr.bios_ver,
+ iocmd->ioc_attr.adapter_attr.optrom_ver);
+
+ /* copy chip rev info first otherwise it will be overwritten */
+ memcpy(bfad->pci_attr.chip_rev, iocmd->ioc_attr.pci_attr.chip_rev,
+ sizeof(bfad->pci_attr.chip_rev));
+ memcpy(&iocmd->ioc_attr.pci_attr, &bfad->pci_attr,
+ sizeof(struct bfa_ioc_pci_attr_s));
+
+ iocmd->status = BFA_STATUS_OK;
+ return 0;
+}
+
+int
+bfad_iocmd_ioc_get_stats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_ioc_stats_s *iocmd = (struct bfa_bsg_ioc_stats_s *)cmd;
+
+ bfa_ioc_get_stats(&bfad->bfa, &iocmd->ioc_stats);
+ iocmd->status = BFA_STATUS_OK;
+ return 0;
+}
+
+int
+bfad_iocmd_ioc_get_fwstats(struct bfad_s *bfad, void *cmd,
+ unsigned int payload_len)
+{
+ struct bfa_bsg_ioc_fwstats_s *iocmd =
+ (struct bfa_bsg_ioc_fwstats_s *)cmd;
+ void *iocmd_bufptr;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_ioc_fwstats_s),
+ sizeof(struct bfa_fw_stats_s)) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ goto out;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_ioc_fwstats_s);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ioc_fw_stats_get(&bfad->bfa.ioc, iocmd_bufptr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK) {
+ bfa_trc(bfad, iocmd->status);
+ goto out;
+ }
+out:
+ bfa_trc(bfad, 0x6666);
+ return 0;
+}
+
+int
+bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_iocfc_attr_s *iocmd = (struct bfa_bsg_iocfc_attr_s *)cmd;
+
+ iocmd->status = BFA_STATUS_OK;
+ bfa_iocfc_get_attr(&bfad->bfa, &iocmd->iocfc_attr);
+
+ return 0;
+}
+
+int
+bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_iocfc_israttr_set(&bfad->bfa, &iocmd->attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
+int
+bfad_iocmd_port_enable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_port_enable(&bfad->bfa.modules.port,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK) {
+ bfa_trc(bfad, iocmd->status);
+ return 0;
+ }
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ return 0;
+}
+
+int
+bfad_iocmd_port_disable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_port_disable(&bfad->bfa.modules.port,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK) {
+ bfa_trc(bfad, iocmd->status);
+ return 0;
+ }
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ return 0;
+}
+
+static int
+bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_port_attr_s *iocmd = (struct bfa_bsg_port_attr_s *)cmd;
+ struct bfa_lport_attr_s port_attr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_fcport_get_attr(&bfad->bfa, &iocmd->attr);
+ bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->attr.topology != BFA_PORT_TOPOLOGY_NONE)
+ iocmd->attr.pid = port_attr.pid;
+ else
+ iocmd->attr.pid = 0;
+
+ iocmd->attr.port_type = port_attr.port_type;
+ iocmd->attr.loopback = port_attr.loopback;
+ iocmd->attr.authfail = port_attr.authfail;
+ strncpy(iocmd->attr.port_symname.symname,
+ port_attr.port_cfg.sym_name.symname,
+ sizeof(port_attr.port_cfg.sym_name.symname));
+
+ iocmd->status = BFA_STATUS_OK;
+ return 0;
+}
+
+int
+bfad_iocmd_port_get_stats(struct bfad_s *bfad, void *cmd,
+ unsigned int payload_len)
+{
+ struct bfa_bsg_port_stats_s *iocmd = (struct bfa_bsg_port_stats_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ void *iocmd_bufptr;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_port_stats_s),
+ sizeof(union bfa_port_stats_u)) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_port_stats_s);
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_port_get_stats(&bfad->bfa.modules.port,
+ iocmd_bufptr, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK) {
+ bfa_trc(bfad, iocmd->status);
+ goto out;
+ }
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+static int
+bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_bsg_lport_attr_s *iocmd = (struct bfa_bsg_lport_attr_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->pwwn);
+ if (fcs_port == NULL) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ goto out;
+ }
+
+ bfa_fcs_lport_get_attr(fcs_port, &iocmd->port_attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_lport_get_stats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_bsg_lport_stats_s *iocmd =
+ (struct bfa_bsg_lport_stats_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->pwwn);
+ if (fcs_port == NULL) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ goto out;
+ }
+
+ bfa_fcs_lport_get_stats(fcs_port, &iocmd->port_stats);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_lport_get_iostats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_bsg_lport_iostats_s *iocmd =
+ (struct bfa_bsg_lport_iostats_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->pwwn);
+ if (fcs_port == NULL) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ goto out;
+ }
+
+ bfa_fcpim_port_iostats(&bfad->bfa, &iocmd->iostats,
+ fcs_port->lp_tag);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
+ unsigned int payload_len)
+{
+ struct bfa_bsg_lport_get_rports_s *iocmd =
+ (struct bfa_bsg_lport_get_rports_s *)cmd;
+ struct bfa_fcs_lport_s *fcs_port;
+ unsigned long flags;
+ void *iocmd_bufptr;
+
+ if (iocmd->nrports == 0)
+ return EINVAL;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_lport_get_rports_s),
+ sizeof(wwn_t) * iocmd->nrports) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd +
+ sizeof(struct bfa_bsg_lport_get_rports_s);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->pwwn);
+ if (fcs_port == NULL) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, 0);
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ goto out;
+ }
+
+ bfa_fcs_lport_get_rports(fcs_port, (wwn_t *)iocmd_bufptr,
+ &iocmd->nrports);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_rport_attr_s *iocmd = (struct bfa_bsg_rport_attr_s *)cmd;
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_fcs_rport_s *fcs_rport;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->pwwn);
+ if (fcs_port == NULL) {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ goto out;
+ }
+
+ fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
+ if (fcs_rport == NULL) {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+ goto out;
+ }
+
+ bfa_fcs_rport_get_attr(fcs_rport, &iocmd->attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+static int
+bfad_iocmd_rport_get_addr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_rport_scsi_addr_s *iocmd =
+ (struct bfa_bsg_rport_scsi_addr_s *)cmd;
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_fcs_itnim_s *fcs_itnim;
+ struct bfad_itnim_s *drv_itnim;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->pwwn);
+ if (fcs_port == NULL) {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ goto out;
+ }
+
+ fcs_itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+ if (fcs_itnim == NULL) {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+ goto out;
+ }
+
+ drv_itnim = fcs_itnim->itnim_drv;
+
+ if (drv_itnim && drv_itnim->im_port)
+ iocmd->host = drv_itnim->im_port->shost->host_no;
+ else {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+ goto out;
+ }
+
+ iocmd->target = drv_itnim->scsi_tgt_id;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ iocmd->bus = 0;
+ iocmd->lun = 0;
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_rport_stats_s *iocmd =
+ (struct bfa_bsg_rport_stats_s *)cmd;
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_fcs_rport_s *fcs_rport;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->pwwn);
+ if (fcs_port == NULL) {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ goto out;
+ }
+
+ fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
+ if (fcs_rport == NULL) {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+ goto out;
+ }
+
+ memcpy((void *)&iocmd->stats, (void *)&fcs_rport->stats,
+ sizeof(struct bfa_rport_stats_s));
+ memcpy((void *)&iocmd->stats.hal_stats,
+ (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats),
+ sizeof(struct bfa_rport_hal_stats_s));
+
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+static int
+bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd,
+ unsigned int payload_len)
+{
+ struct bfa_bsg_fabric_get_lports_s *iocmd =
+ (struct bfa_bsg_fabric_get_lports_s *)cmd;
+ bfa_fcs_vf_t *fcs_vf;
+ uint32_t nports = iocmd->nports;
+ unsigned long flags;
+ void *iocmd_bufptr;
+
+ if (nports == 0) {
+ iocmd->status = BFA_STATUS_EINVAL;
+ goto out;
+ }
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_fabric_get_lports_s),
+ sizeof(wwn_t[iocmd->nports])) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ goto out;
+ }
+
+ iocmd_bufptr = (char *)iocmd +
+ sizeof(struct bfa_bsg_fabric_get_lports_s);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id);
+ if (fcs_vf == NULL) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_UNKNOWN_VFID;
+ goto out;
+ }
+ bfa_fcs_vf_get_ports(fcs_vf, (wwn_t *)iocmd_bufptr, &nports);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ iocmd->nports = nports;
+ iocmd->status = BFA_STATUS_OK;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_fcpim_modstats_s *iocmd =
+ (struct bfa_bsg_fcpim_modstats_s *)cmd;
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
+ struct list_head *qe, *qen;
+ struct bfa_itnim_s *itnim;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ /* accumulate IO stats from itnim */
+ memset((void *)&iocmd->modstats, 0, sizeof(struct bfa_itnim_iostats_s));
+ list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+ itnim = (struct bfa_itnim_s *) qe;
+ bfa_fcpim_add_stats(&iocmd->modstats, &(itnim->stats));
+ }
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+ return 0;
+}
+
+int
+bfad_iocmd_fcpim_get_del_itn_stats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_fcpim_del_itn_stats_s *iocmd =
+ (struct bfa_bsg_fcpim_del_itn_stats_s *)cmd;
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ memcpy((void *)&iocmd->modstats, (void *)&fcpim->del_itn_stats,
+ sizeof(struct bfa_fcpim_del_itn_stats_s));
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ iocmd->status = BFA_STATUS_OK;
+ return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_itnim_attr_s *iocmd = (struct bfa_bsg_itnim_attr_s *)cmd;
+ struct bfa_fcs_lport_s *fcs_port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->lpwwn);
+ if (!fcs_port)
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ else
+ iocmd->status = bfa_fcs_itnim_attr_get(fcs_port,
+ iocmd->rpwwn, &iocmd->attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_iostats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_itnim_iostats_s *iocmd =
+ (struct bfa_bsg_itnim_iostats_s *)cmd;
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_fcs_itnim_s *itnim;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->lpwwn);
+ if (!fcs_port) {
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ bfa_trc(bfad, 0);
+ } else {
+ itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+ if (itnim == NULL)
+ iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+ else {
+ iocmd->status = BFA_STATUS_OK;
+ memcpy((void *)&iocmd->iostats, (void *)
+ &(bfa_fcs_itnim_get_halitn(itnim)->stats),
+ sizeof(struct bfa_itnim_iostats_s));
+ }
+ }
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_itnstats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_itnim_itnstats_s *iocmd =
+ (struct bfa_bsg_itnim_itnstats_s *)cmd;
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_fcs_itnim_s *itnim;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+ iocmd->vf_id, iocmd->lpwwn);
+ if (!fcs_port) {
+ iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+ bfa_trc(bfad, 0);
+ } else {
+ itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+ if (itnim == NULL)
+ iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+ else {
+ iocmd->status = BFA_STATUS_OK;
+ bfa_fcs_itnim_stats_get(fcs_port, iocmd->rpwwn,
+ &iocmd->itnstats);
+ }
+ }
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+
+int
+bfad_iocmd_fcport_enable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcport_enable(&bfad->bfa);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
+int
+bfad_iocmd_fcport_disable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcport_disable(&bfad->bfa);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
+int
+bfad_iocmd_ioc_get_pcifn_cfg(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_pcifn_cfg_s *iocmd = (struct bfa_bsg_pcifn_cfg_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ablk_query(&bfad->bfa.modules.ablk,
+ &iocmd->pcifn_cfg,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ablk_pf_create(&bfad->bfa.modules.ablk,
+ &iocmd->pcifn_id, iocmd->port,
+ iocmd->pcifn_class, iocmd->bandwidth,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_pcifn_delete(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ablk_pf_delete(&bfad->bfa.modules.ablk,
+ iocmd->pcifn_id,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ablk_pf_update(&bfad->bfa.modules.ablk,
+ iocmd->pcifn_id, iocmd->bandwidth,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ bfa_trc(bfad, iocmd->status);
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_adapter_cfg_mode(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_adapter_cfg_mode_s *iocmd =
+ (struct bfa_bsg_adapter_cfg_mode_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags = 0;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ablk_adapter_config(&bfad->bfa.modules.ablk,
+ iocmd->cfg.mode, iocmd->cfg.max_pf,
+ iocmd->cfg.max_vf, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_port_cfg_mode(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_port_cfg_mode_s *iocmd =
+ (struct bfa_bsg_port_cfg_mode_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags = 0;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ablk_port_config(&bfad->bfa.modules.ablk,
+ iocmd->instance, iocmd->cfg.mode,
+ iocmd->cfg.max_pf, iocmd->cfg.max_vf,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_ablk_optrom(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ if (cmd == IOCMD_FLASH_ENABLE_OPTROM)
+ iocmd->status = bfa_ablk_optrom_en(&bfad->bfa.modules.ablk,
+ bfad_hcb_comp, &fcomp);
+ else
+ iocmd->status = bfa_ablk_optrom_dis(&bfad->bfa.modules.ablk,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_faa_enable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ unsigned long flags;
+ struct bfad_hal_comp fcomp;
+
+ init_completion(&fcomp.comp);
+ iocmd->status = BFA_STATUS_OK;
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_faa_enable(&bfad->bfa, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_faa_disable(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ unsigned long flags;
+ struct bfad_hal_comp fcomp;
+
+ init_completion(&fcomp.comp);
+ iocmd->status = BFA_STATUS_OK;
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_faa_disable(&bfad->bfa, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_faa_query(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_faa_attr_s *iocmd = (struct bfa_bsg_faa_attr_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ iocmd->status = BFA_STATUS_OK;
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_faa_query(&bfad->bfa, &iocmd->faa_attr,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_cee_attr(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
+{
+ struct bfa_bsg_cee_attr_s *iocmd =
+ (struct bfa_bsg_cee_attr_s *)cmd;
+ void *iocmd_bufptr;
+ struct bfad_hal_comp cee_comp;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_cee_attr_s),
+ sizeof(struct bfa_cee_attr_s)) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_attr_s);
+
+ cee_comp.status = 0;
+ init_completion(&cee_comp.comp);
+ mutex_lock(&bfad_mutex);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_cee_get_attr(&bfad->bfa.modules.cee, iocmd_bufptr,
+ bfad_hcb_comp, &cee_comp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK) {
+ mutex_unlock(&bfad_mutex);
+ bfa_trc(bfad, 0x5555);
+ goto out;
+ }
+ wait_for_completion(&cee_comp.comp);
+ mutex_unlock(&bfad_mutex);
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_cee_get_stats(struct bfad_s *bfad, void *cmd,
+ unsigned int payload_len)
+{
+ struct bfa_bsg_cee_stats_s *iocmd =
+ (struct bfa_bsg_cee_stats_s *)cmd;
+ void *iocmd_bufptr;
+ struct bfad_hal_comp cee_comp;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_cee_stats_s),
+ sizeof(struct bfa_cee_stats_s)) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_stats_s);
+
+ cee_comp.status = 0;
+ init_completion(&cee_comp.comp);
+ mutex_lock(&bfad_mutex);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_cee_get_stats(&bfad->bfa.modules.cee, iocmd_bufptr,
+ bfad_hcb_comp, &cee_comp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK) {
+ mutex_unlock(&bfad_mutex);
+ bfa_trc(bfad, 0x5555);
+ goto out;
+ }
+ wait_for_completion(&cee_comp.comp);
+ mutex_unlock(&bfad_mutex);
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_cee_reset_stats(&bfad->bfa.modules.cee, NULL, NULL);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ bfa_trc(bfad, 0x5555);
+ return 0;
+}
+
+int
+bfad_iocmd_sfp_media(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_sfp_media_s *iocmd = (struct bfa_bsg_sfp_media_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_sfp_media(BFA_SFP_MOD(&bfad->bfa), &iocmd->media,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_SFP_NOT_READY)
+ goto out;
+
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_sfp_speed(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_sfp_speed_s *iocmd = (struct bfa_bsg_sfp_speed_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_sfp_speed(BFA_SFP_MOD(&bfad->bfa), iocmd->speed,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_SFP_NOT_READY)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_flash_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_flash_attr_s *iocmd =
+ (struct bfa_bsg_flash_attr_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_flash_get_attr(BFA_FLASH(&bfad->bfa), &iocmd->attr,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_flash_erase_part(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_flash_erase_part(BFA_FLASH(&bfad->bfa), iocmd->type,
+ iocmd->instance, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_flash_update_part(struct bfad_s *bfad, void *cmd,
+ unsigned int payload_len)
+{
+ struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
+ void *iocmd_bufptr;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_flash_s),
+ iocmd->bufsz) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s);
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa),
+ iocmd->type, iocmd->instance, iocmd_bufptr,
+ iocmd->bufsz, 0, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_flash_read_part(struct bfad_s *bfad, void *cmd,
+ unsigned int payload_len)
+{
+ struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ void *iocmd_bufptr;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_flash_s),
+ iocmd->bufsz) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s);
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa), iocmd->type,
+ iocmd->instance, iocmd_bufptr, iocmd->bufsz, 0,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_diag_temp(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_get_temp_s *iocmd =
+ (struct bfa_bsg_diag_get_temp_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_diag_tsensor_query(BFA_DIAG_MOD(&bfad->bfa),
+ &iocmd->result, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_diag_memtest(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_memtest_s *iocmd =
+ (struct bfa_bsg_diag_memtest_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_diag_memtest(BFA_DIAG_MOD(&bfad->bfa),
+ &iocmd->memtest, iocmd->pat,
+ &iocmd->result, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_diag_loopback(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_loopback_s *iocmd =
+ (struct bfa_bsg_diag_loopback_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcdiag_loopback(&bfad->bfa, iocmd->opmode,
+ iocmd->speed, iocmd->lpcnt, iocmd->pat,
+ &iocmd->result, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_diag_fwping(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_fwping_s *iocmd =
+ (struct bfa_bsg_diag_fwping_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_diag_fwping(BFA_DIAG_MOD(&bfad->bfa), iocmd->cnt,
+ iocmd->pattern, &iocmd->result,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ bfa_trc(bfad, 0x77771);
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_diag_queuetest(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_qtest_s *iocmd = (struct bfa_bsg_diag_qtest_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcdiag_queuetest(&bfad->bfa, iocmd->force,
+ iocmd->queue, &iocmd->result,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_diag_sfp(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_sfp_show_s *iocmd =
+ (struct bfa_bsg_sfp_show_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_sfp_show(BFA_SFP_MOD(&bfad->bfa), &iocmd->sfp,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ bfa_trc(bfad, iocmd->status);
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_led_s *iocmd = (struct bfa_bsg_diag_led_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_diag_ledtest(BFA_DIAG_MOD(&bfad->bfa),
+ &iocmd->ledtest);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+
+int
+bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_beacon_s *iocmd =
+ (struct bfa_bsg_diag_beacon_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_diag_beacon_port(BFA_DIAG_MOD(&bfad->bfa),
+ iocmd->beacon, iocmd->link_e2e_beacon,
+ iocmd->second);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+
+int
+bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_diag_lb_stat_s *iocmd =
+ (struct bfa_bsg_diag_lb_stat_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcdiag_lb_is_running(&bfad->bfa);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc(bfad, iocmd->status);
+
+ return 0;
+}
+
+int
+bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_phy_attr_s *iocmd =
+ (struct bfa_bsg_phy_attr_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_phy_get_attr(BFA_PHY(&bfad->bfa), iocmd->instance,
+ &iocmd->attr, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_phy_get_stats(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_phy_stats_s *iocmd =
+ (struct bfa_bsg_phy_stats_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_phy_get_stats(BFA_PHY(&bfad->bfa), iocmd->instance,
+ &iocmd->stats, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_phy_read(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
+{
+ struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ void *iocmd_bufptr;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_phy_s),
+ iocmd->bufsz) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s);
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_phy_read(BFA_PHY(&bfad->bfa),
+ iocmd->instance, iocmd_bufptr, iocmd->bufsz,
+ 0, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_vhba_query(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_vhba_attr_s *iocmd =
+ (struct bfa_bsg_vhba_attr_s *)cmd;
+ struct bfa_vhba_attr_s *attr = &iocmd->attr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ attr->pwwn = bfad->bfa.ioc.attr->pwwn;
+ attr->nwwn = bfad->bfa.ioc.attr->nwwn;
+ attr->plog_enabled = (bfa_boolean_t)bfad->bfa.plog->plog_enabled;
+ attr->io_profile = bfa_fcpim_get_io_profile(&bfad->bfa);
+ attr->path_tov = bfa_fcpim_path_tov_get(&bfad->bfa);
+ iocmd->status = BFA_STATUS_OK;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+
+int
+bfad_iocmd_phy_update(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
+{
+ struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
+ void *iocmd_bufptr;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags;
+
+ if (bfad_chk_iocmd_sz(payload_len,
+ sizeof(struct bfa_bsg_phy_s),
+ iocmd->bufsz) != BFA_STATUS_OK) {
+ iocmd->status = BFA_STATUS_VERSION_FAIL;
+ return 0;
+ }
+
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s);
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_phy_update(BFA_PHY(&bfad->bfa),
+ iocmd->instance, iocmd_bufptr, iocmd->bufsz,
+ 0, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ goto out;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+out:
+ return 0;
+}
+
+int
+bfad_iocmd_porglog_get(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd;
+ void *iocmd_bufptr;
+
+ if (iocmd->bufsz < sizeof(struct bfa_plog_s)) {
+ bfa_trc(bfad, sizeof(struct bfa_plog_s));
+ iocmd->status = BFA_STATUS_EINVAL;
+ goto out;
+ }
+
+ iocmd->status = BFA_STATUS_OK;
+ iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_debug_s);
+ memcpy(iocmd_bufptr, (u8 *) &bfad->plog_buf, sizeof(struct bfa_plog_s));
+out:
+ return 0;
+}
+
+static int
+bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
+ unsigned int payload_len)
+{
+ int rc = EINVAL;
+
+ switch (cmd) {
+ case IOCMD_IOC_ENABLE:
+ rc = bfad_iocmd_ioc_enable(bfad, iocmd);
+ break;
+ case IOCMD_IOC_DISABLE:
+ rc = bfad_iocmd_ioc_disable(bfad, iocmd);
+ break;
+ case IOCMD_IOC_GET_INFO:
+ rc = bfad_iocmd_ioc_get_info(bfad, iocmd);
+ break;
+ case IOCMD_IOC_GET_ATTR:
+ rc = bfad_iocmd_ioc_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_IOC_GET_STATS:
+ rc = bfad_iocmd_ioc_get_stats(bfad, iocmd);
+ break;
+ case IOCMD_IOC_GET_FWSTATS:
+ rc = bfad_iocmd_ioc_get_fwstats(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_IOCFC_GET_ATTR:
+ rc = bfad_iocmd_iocfc_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_IOCFC_SET_INTR:
+ rc = bfad_iocmd_iocfc_set_intr(bfad, iocmd);
+ break;
+ case IOCMD_PORT_ENABLE:
+ rc = bfad_iocmd_port_enable(bfad, iocmd);
+ break;
+ case IOCMD_PORT_DISABLE:
+ rc = bfad_iocmd_port_disable(bfad, iocmd);
+ break;
+ case IOCMD_PORT_GET_ATTR:
+ rc = bfad_iocmd_port_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_PORT_GET_STATS:
+ rc = bfad_iocmd_port_get_stats(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_LPORT_GET_ATTR:
+ rc = bfad_iocmd_lport_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_LPORT_GET_STATS:
+ rc = bfad_iocmd_lport_get_stats(bfad, iocmd);
+ break;
+ case IOCMD_LPORT_GET_IOSTATS:
+ rc = bfad_iocmd_lport_get_iostats(bfad, iocmd);
+ break;
+ case IOCMD_LPORT_GET_RPORTS:
+ rc = bfad_iocmd_lport_get_rports(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_RPORT_GET_ATTR:
+ rc = bfad_iocmd_rport_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_RPORT_GET_ADDR:
+ rc = bfad_iocmd_rport_get_addr(bfad, iocmd);
+ break;
+ case IOCMD_RPORT_GET_STATS:
+ rc = bfad_iocmd_rport_get_stats(bfad, iocmd);
+ break;
+ case IOCMD_FABRIC_GET_LPORTS:
+ rc = bfad_iocmd_fabric_get_lports(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_FCPIM_MODSTATS:
+ rc = bfad_iocmd_fcpim_get_modstats(bfad, iocmd);
+ break;
+ case IOCMD_FCPIM_DEL_ITN_STATS:
+ rc = bfad_iocmd_fcpim_get_del_itn_stats(bfad, iocmd);
+ break;
+ case IOCMD_ITNIM_GET_ATTR:
+ rc = bfad_iocmd_itnim_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_ITNIM_GET_IOSTATS:
+ rc = bfad_iocmd_itnim_get_iostats(bfad, iocmd);
+ break;
+ case IOCMD_ITNIM_GET_ITNSTATS:
+ rc = bfad_iocmd_itnim_get_itnstats(bfad, iocmd);
+ break;
+ case IOCMD_FCPORT_ENABLE:
+ rc = bfad_iocmd_fcport_enable(bfad, iocmd);
+ break;
+ case IOCMD_FCPORT_DISABLE:
+ rc = bfad_iocmd_fcport_disable(bfad, iocmd);
+ break;
+ case IOCMD_IOC_PCIFN_CFG:
+ rc = bfad_iocmd_ioc_get_pcifn_cfg(bfad, iocmd);
+ break;
+ case IOCMD_PCIFN_CREATE:
+ rc = bfad_iocmd_pcifn_create(bfad, iocmd);
+ break;
+ case IOCMD_PCIFN_DELETE:
+ rc = bfad_iocmd_pcifn_delete(bfad, iocmd);
+ break;
+ case IOCMD_PCIFN_BW:
+ rc = bfad_iocmd_pcifn_bw(bfad, iocmd);
+ break;
+ case IOCMD_ADAPTER_CFG_MODE:
+ rc = bfad_iocmd_adapter_cfg_mode(bfad, iocmd);
+ break;
+ case IOCMD_PORT_CFG_MODE:
+ rc = bfad_iocmd_port_cfg_mode(bfad, iocmd);
+ break;
+ case IOCMD_FLASH_ENABLE_OPTROM:
+ case IOCMD_FLASH_DISABLE_OPTROM:
+ rc = bfad_iocmd_ablk_optrom(bfad, cmd, iocmd);
+ break;
+ case IOCMD_FAA_ENABLE:
+ rc = bfad_iocmd_faa_enable(bfad, iocmd);
+ break;
+ case IOCMD_FAA_DISABLE:
+ rc = bfad_iocmd_faa_disable(bfad, iocmd);
+ break;
+ case IOCMD_FAA_QUERY:
+ rc = bfad_iocmd_faa_query(bfad, iocmd);
+ break;
+ case IOCMD_CEE_GET_ATTR:
+ rc = bfad_iocmd_cee_attr(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_CEE_GET_STATS:
+ rc = bfad_iocmd_cee_get_stats(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_CEE_RESET_STATS:
+ rc = bfad_iocmd_cee_reset_stats(bfad, iocmd);
+ break;
+ case IOCMD_SFP_MEDIA:
+ rc = bfad_iocmd_sfp_media(bfad, iocmd);
+ break;
+ case IOCMD_SFP_SPEED:
+ rc = bfad_iocmd_sfp_speed(bfad, iocmd);
+ break;
+ case IOCMD_FLASH_GET_ATTR:
+ rc = bfad_iocmd_flash_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_FLASH_ERASE_PART:
+ rc = bfad_iocmd_flash_erase_part(bfad, iocmd);
+ break;
+ case IOCMD_FLASH_UPDATE_PART:
+ rc = bfad_iocmd_flash_update_part(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_FLASH_READ_PART:
+ rc = bfad_iocmd_flash_read_part(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_DIAG_TEMP:
+ rc = bfad_iocmd_diag_temp(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_MEMTEST:
+ rc = bfad_iocmd_diag_memtest(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_LOOPBACK:
+ rc = bfad_iocmd_diag_loopback(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_FWPING:
+ rc = bfad_iocmd_diag_fwping(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_QUEUETEST:
+ rc = bfad_iocmd_diag_queuetest(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_SFP:
+ rc = bfad_iocmd_diag_sfp(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_LED:
+ rc = bfad_iocmd_diag_led(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_BEACON_LPORT:
+ rc = bfad_iocmd_diag_beacon_lport(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_LB_STAT:
+ rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
+ break;
+ case IOCMD_PHY_GET_ATTR:
+ rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
+ break;
+ case IOCMD_PHY_GET_STATS:
+ rc = bfad_iocmd_phy_get_stats(bfad, iocmd);
+ break;
+ case IOCMD_PHY_UPDATE_FW:
+ rc = bfad_iocmd_phy_update(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_PHY_READ_FW:
+ rc = bfad_iocmd_phy_read(bfad, iocmd, payload_len);
+ break;
+ case IOCMD_VHBA_QUERY:
+ rc = bfad_iocmd_vhba_query(bfad, iocmd);
+ break;
+ case IOCMD_DEBUG_PORTLOG:
+ rc = bfad_iocmd_porglog_get(bfad, iocmd);
+ break;
+ default:
+ rc = EINVAL;
+ break;
+ }
+ return -rc;
+}
+
+static int
+bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
+{
+ uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0];
+ struct bfad_im_port_s *im_port =
+ (struct bfad_im_port_s *) job->shost->hostdata[0];
+ struct bfad_s *bfad = im_port->bfad;
+ void *payload_kbuf;
+ int rc = -EINVAL;
+
+ /* Allocate a temp buffer to hold the passed in user space command */
+ payload_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
+ if (!payload_kbuf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Copy the sg_list passed in to a linear buffer: holds the cmnd data */
+ sg_copy_to_buffer(job->request_payload.sg_list,
+ job->request_payload.sg_cnt, payload_kbuf,
+ job->request_payload.payload_len);
+
+ /* Invoke IOCMD handler - to handle all the vendor command requests */
+ rc = bfad_iocmd_handler(bfad, vendor_cmd, payload_kbuf,
+ job->request_payload.payload_len);
+ if (rc != BFA_STATUS_OK)
+ goto error;
+
+ /* Copy the response data to the job->reply_payload sg_list */
+ sg_copy_from_buffer(job->reply_payload.sg_list,
+ job->reply_payload.sg_cnt,
+ payload_kbuf,
+ job->reply_payload.payload_len);
+
+ /* free the command buffer */
+ kfree(payload_kbuf);
+
+ /* Fill the BSG job reply data */
+ job->reply_len = job->reply_payload.payload_len;
+ job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
+ job->reply->result = rc;
+
+ job->job_done(job);
+ return rc;
+error:
+ /* free the command buffer */
+ kfree(payload_kbuf);
+out:
+ job->reply->result = rc;
+ job->reply_len = sizeof(uint32_t);
+ job->reply->reply_payload_rcv_len = 0;
+ return rc;
+}
+
+/* FC passthru call backs */
+u64
+bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid)
+{
+ struct bfad_fcxp *drv_fcxp = bfad_fcxp;
+ struct bfa_sge_s *sge;
+ u64 addr;
+
+ sge = drv_fcxp->req_sge + sgeid;
+ addr = (u64)(size_t) sge->sg_addr;
+ return addr;
+}
+
+u32
+bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid)
+{
+ struct bfad_fcxp *drv_fcxp = bfad_fcxp;
+ struct bfa_sge_s *sge;
+
+ sge = drv_fcxp->req_sge + sgeid;
+ return sge->sg_len;
+}
+
+u64
+bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid)
+{
+ struct bfad_fcxp *drv_fcxp = bfad_fcxp;
+ struct bfa_sge_s *sge;
+ u64 addr;
+
+ sge = drv_fcxp->rsp_sge + sgeid;
+ addr = (u64)(size_t) sge->sg_addr;
+ return addr;
+}
+
+u32
+bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid)
+{
+ struct bfad_fcxp *drv_fcxp = bfad_fcxp;
+ struct bfa_sge_s *sge;
+
+ sge = drv_fcxp->rsp_sge + sgeid;
+ return sge->sg_len;
+}
+
+void
+bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfad_fcxp *drv_fcxp = bfad_fcxp;
+
+ drv_fcxp->req_status = req_status;
+ drv_fcxp->rsp_len = rsp_len;
+
+ /* bfa_fcxp will be automatically freed by BFA */
+ drv_fcxp->bfa_fcxp = NULL;
+ complete(&drv_fcxp->comp);
+}
+
+struct bfad_buf_info *
+bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
+ uint32_t payload_len, uint32_t *num_sgles)
+{
+ struct bfad_buf_info *buf_base, *buf_info;
+ struct bfa_sge_s *sg_table;
+ int sge_num = 1;
+
+ buf_base = kzalloc((sizeof(struct bfad_buf_info) +
+ sizeof(struct bfa_sge_s)) * sge_num, GFP_KERNEL);
+ if (!buf_base)
+ return NULL;
+
+ sg_table = (struct bfa_sge_s *) (((uint8_t *)buf_base) +
+ (sizeof(struct bfad_buf_info) * sge_num));
+
+ /* Allocate dma coherent memory */
+ buf_info = buf_base;
+ buf_info->size = payload_len;
+ buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size,
+ &buf_info->phys, GFP_KERNEL);
+ if (!buf_info->virt)
+ goto out_free_mem;
+
+ /* copy the linear bsg buffer to buf_info */
+ memset(buf_info->virt, 0, buf_info->size);
+ memcpy(buf_info->virt, payload_kbuf, buf_info->size);
+
+ /*
+ * Setup SG table
+ */
+ sg_table->sg_len = buf_info->size;
+ sg_table->sg_addr = (void *)(size_t) buf_info->phys;
+
+ *num_sgles = sge_num;
+
+ return buf_base;
+
+out_free_mem:
+ kfree(buf_base);
+ return NULL;
+}
+
+void
+bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base,
+ uint32_t num_sgles)
+{
+ int i;
+ struct bfad_buf_info *buf_info = buf_base;
+
+ if (buf_base) {
+ for (i = 0; i < num_sgles; buf_info++, i++) {
+ if (buf_info->virt != NULL)
+ dma_free_coherent(&bfad->pcidev->dev,
+ buf_info->size, buf_info->virt,
+ buf_info->phys);
+ }
+ kfree(buf_base);
+ }
+}
+
+int
+bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
+ bfa_bsg_fcpt_t *bsg_fcpt)
+{
+ struct bfa_fcxp_s *hal_fcxp;
+ struct bfad_s *bfad = drv_fcxp->port->bfad;
+ unsigned long flags;
+ uint8_t lp_tag;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+ /* Allocate bfa_fcxp structure */
+ hal_fcxp = bfa_fcxp_alloc(drv_fcxp, &bfad->bfa,
+ drv_fcxp->num_req_sgles,
+ drv_fcxp->num_rsp_sgles,
+ bfad_fcxp_get_req_sgaddr_cb,
+ bfad_fcxp_get_req_sglen_cb,
+ bfad_fcxp_get_rsp_sgaddr_cb,
+ bfad_fcxp_get_rsp_sglen_cb);
+ if (!hal_fcxp) {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return BFA_STATUS_ENOMEM;
+ }
+
+ drv_fcxp->bfa_fcxp = hal_fcxp;
+
+ lp_tag = bfa_lps_get_tag_from_pid(&bfad->bfa, bsg_fcpt->fchs.s_id);
+
+ bfa_fcxp_send(hal_fcxp, drv_fcxp->bfa_rport, bsg_fcpt->vf_id, lp_tag,
+ bsg_fcpt->cts, bsg_fcpt->cos,
+ job->request_payload.payload_len,
+ &bsg_fcpt->fchs, bfad_send_fcpt_cb, bfad,
+ job->reply_payload.payload_len, bsg_fcpt->tsecs);
+
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return BFA_STATUS_OK;
+}
+
+int
+bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
+{
+ struct bfa_bsg_data *bsg_data;
+ struct bfad_im_port_s *im_port =
+ (struct bfad_im_port_s *) job->shost->hostdata[0];
+ struct bfad_s *bfad = im_port->bfad;
+ bfa_bsg_fcpt_t *bsg_fcpt;
+ struct bfad_fcxp *drv_fcxp;
+ struct bfa_fcs_lport_s *fcs_port;
+ struct bfa_fcs_rport_s *fcs_rport;
+ uint32_t command_type = job->request->msgcode;
+ unsigned long flags;
+ struct bfad_buf_info *rsp_buf_info;
+ void *req_kbuf = NULL, *rsp_kbuf = NULL;
+ int rc = -EINVAL;
+
+ job->reply_len = sizeof(uint32_t); /* Atleast uint32_t reply_len */
+ job->reply->reply_payload_rcv_len = 0;
+
+ /* Get the payload passed in from userspace */
+ bsg_data = (struct bfa_bsg_data *) (((char *)job->request) +
+ sizeof(struct fc_bsg_request));
+ if (bsg_data == NULL)
+ goto out;
+
+ /*
+ * Allocate buffer for bsg_fcpt and do a copy_from_user op for payload
+ * buffer of size bsg_data->payload_len
+ */
+ bsg_fcpt = (struct bfa_bsg_fcpt_s *)
+ kzalloc(bsg_data->payload_len, GFP_KERNEL);
+ if (!bsg_fcpt)
+ goto out;
+
+ if (copy_from_user((uint8_t *)bsg_fcpt, bsg_data->payload,
+ bsg_data->payload_len)) {
+ kfree(bsg_fcpt);
+ goto out;
+ }
+
+ drv_fcxp = kzalloc(sizeof(struct bfad_fcxp), GFP_KERNEL);
+ if (drv_fcxp == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, bsg_fcpt->vf_id,
+ bsg_fcpt->lpwwn);
+ if (fcs_port == NULL) {
+ bsg_fcpt->status = BFA_STATUS_UNKNOWN_LWWN;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ goto out_free_mem;
+ }
+
+ /* Check if the port is online before sending FC Passthru cmd */
+ if (!bfa_fcs_lport_is_online(fcs_port)) {
+ bsg_fcpt->status = BFA_STATUS_PORT_OFFLINE;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ goto out_free_mem;
+ }
+
+ drv_fcxp->port = fcs_port->bfad_port;
+
+ if (drv_fcxp->port->bfad == 0)
+ drv_fcxp->port->bfad = bfad;
+
+ /* Fetch the bfa_rport - if nexus needed */
+ if (command_type == FC_BSG_HST_ELS_NOLOGIN ||
+ command_type == FC_BSG_HST_CT) {
+ /* BSG HST commands: no nexus needed */
+ drv_fcxp->bfa_rport = NULL;
+
+ } else if (command_type == FC_BSG_RPT_ELS ||
+ command_type == FC_BSG_RPT_CT) {
+ /* BSG RPT commands: nexus needed */
+ fcs_rport = bfa_fcs_lport_get_rport_by_pwwn(fcs_port,
+ bsg_fcpt->dpwwn);
+ if (fcs_rport == NULL) {
+ bsg_fcpt->status = BFA_STATUS_UNKNOWN_RWWN;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ goto out_free_mem;
+ }
+
+ drv_fcxp->bfa_rport = fcs_rport->bfa_rport;
+
+ } else { /* Unknown BSG msgcode; return -EINVAL */
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ goto out_free_mem;
+ }
+
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ /* allocate memory for req / rsp buffers */
+ req_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
+ if (!req_kbuf) {
+ printk(KERN_INFO "bfa %s: fcpt request buffer alloc failed\n",
+ bfad->pci_name);
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+
+ rsp_kbuf = kzalloc(job->reply_payload.payload_len, GFP_KERNEL);
+ if (!rsp_kbuf) {
+ printk(KERN_INFO "bfa %s: fcpt response buffer alloc failed\n",
+ bfad->pci_name);
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+
+ /* map req sg - copy the sg_list passed in to the linear buffer */
+ sg_copy_to_buffer(job->request_payload.sg_list,
+ job->request_payload.sg_cnt, req_kbuf,
+ job->request_payload.payload_len);
+
+ drv_fcxp->reqbuf_info = bfad_fcxp_map_sg(bfad, req_kbuf,
+ job->request_payload.payload_len,
+ &drv_fcxp->num_req_sgles);
+ if (!drv_fcxp->reqbuf_info) {
+ printk(KERN_INFO "bfa %s: fcpt request fcxp_map_sg failed\n",
+ bfad->pci_name);
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+
+ drv_fcxp->req_sge = (struct bfa_sge_s *)
+ (((uint8_t *)drv_fcxp->reqbuf_info) +
+ (sizeof(struct bfad_buf_info) *
+ drv_fcxp->num_req_sgles));
+
+ /* map rsp sg */
+ drv_fcxp->rspbuf_info = bfad_fcxp_map_sg(bfad, rsp_kbuf,
+ job->reply_payload.payload_len,
+ &drv_fcxp->num_rsp_sgles);
+ if (!drv_fcxp->rspbuf_info) {
+ printk(KERN_INFO "bfa %s: fcpt response fcxp_map_sg failed\n",
+ bfad->pci_name);
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+
+ rsp_buf_info = (struct bfad_buf_info *)drv_fcxp->rspbuf_info;
+ drv_fcxp->rsp_sge = (struct bfa_sge_s *)
+ (((uint8_t *)drv_fcxp->rspbuf_info) +
+ (sizeof(struct bfad_buf_info) *
+ drv_fcxp->num_rsp_sgles));
+
+ /* fcxp send */
+ init_completion(&drv_fcxp->comp);
+ rc = bfad_fcxp_bsg_send(job, drv_fcxp, bsg_fcpt);
+ if (rc == BFA_STATUS_OK) {
+ wait_for_completion(&drv_fcxp->comp);
+ bsg_fcpt->status = drv_fcxp->req_status;
+ } else {
+ bsg_fcpt->status = rc;
+ goto out_free_mem;
+ }
+
+ /* fill the job->reply data */
+ if (drv_fcxp->req_status == BFA_STATUS_OK) {
+ job->reply_len = drv_fcxp->rsp_len;
+ job->reply->reply_payload_rcv_len = drv_fcxp->rsp_len;
+ job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+ } else {
+ job->reply->reply_payload_rcv_len =
+ sizeof(struct fc_bsg_ctels_reply);
+ job->reply_len = sizeof(uint32_t);
+ job->reply->reply_data.ctels_reply.status =
+ FC_CTELS_STATUS_REJECT;
+ }
+
+ /* Copy the response data to the reply_payload sg list */
+ sg_copy_from_buffer(job->reply_payload.sg_list,
+ job->reply_payload.sg_cnt,
+ (uint8_t *)rsp_buf_info->virt,
+ job->reply_payload.payload_len);
+
+out_free_mem:
+ bfad_fcxp_free_mem(bfad, drv_fcxp->rspbuf_info,
+ drv_fcxp->num_rsp_sgles);
+ bfad_fcxp_free_mem(bfad, drv_fcxp->reqbuf_info,
+ drv_fcxp->num_req_sgles);
+ kfree(req_kbuf);
+ kfree(rsp_kbuf);
+
+ /* Need a copy to user op */
+ if (copy_to_user(bsg_data->payload, (void *) bsg_fcpt,
+ bsg_data->payload_len))
+ rc = -EIO;
+
+ kfree(bsg_fcpt);
+ kfree(drv_fcxp);
+out:
+ job->reply->result = rc;
+
+ if (rc == BFA_STATUS_OK)
+ job->job_done(job);
+
+ return rc;
+}
+
+int
+bfad_im_bsg_request(struct fc_bsg_job *job)
+{
+ uint32_t rc = BFA_STATUS_OK;
+
+ switch (job->request->msgcode) {
+ case FC_BSG_HST_VENDOR:
+ /* Process BSG HST Vendor requests */
+ rc = bfad_im_bsg_vendor_request(job);
+ break;
+ case FC_BSG_HST_ELS_NOLOGIN:
+ case FC_BSG_RPT_ELS:
+ case FC_BSG_HST_CT:
+ case FC_BSG_RPT_CT:
+ /* Process BSG ELS/CT commands */
+ rc = bfad_im_bsg_els_ct_request(job);
+ break;
+ default:
+ job->reply->result = rc = -EINVAL;
+ job->reply->reply_payload_rcv_len = 0;
+ break;
+ }
+
+ return rc;
+}
+
+int
+bfad_im_bsg_timeout(struct fc_bsg_job *job)
+{
+ /* Don't complete the BSG job request - return -EAGAIN
+ * to reset bsg job timeout : for ELS/CT pass thru we
+ * already have timer to track the request.
+ */
+ return -EAGAIN;
+}
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
new file mode 100644
index 000000000000..99b0e8a70c89
--- /dev/null
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus 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.
+ */
+#ifndef BFAD_BSG_H
+#define BFAD_BSG_H
+
+#include "bfa_defs.h"
+#include "bfa_defs_fcs.h"
+
+/* Definitions of vendor unique structures and command codes passed in
+ * using FC_BSG_HST_VENDOR message code.
+ */
+enum {
+ IOCMD_IOC_ENABLE = 0x1,
+ IOCMD_IOC_DISABLE,
+ IOCMD_IOC_GET_ATTR,
+ IOCMD_IOC_GET_INFO,
+ IOCMD_IOC_GET_STATS,
+ IOCMD_IOC_GET_FWSTATS,
+ IOCMD_IOCFC_GET_ATTR,
+ IOCMD_IOCFC_SET_INTR,
+ IOCMD_PORT_ENABLE,
+ IOCMD_PORT_DISABLE,
+ IOCMD_PORT_GET_ATTR,
+ IOCMD_PORT_GET_STATS,
+ IOCMD_LPORT_GET_ATTR,
+ IOCMD_LPORT_GET_RPORTS,
+ IOCMD_LPORT_GET_STATS,
+ IOCMD_LPORT_GET_IOSTATS,
+ IOCMD_RPORT_GET_ATTR,
+ IOCMD_RPORT_GET_ADDR,
+ IOCMD_RPORT_GET_STATS,
+ IOCMD_FABRIC_GET_LPORTS,
+ IOCMD_FCPIM_MODSTATS,
+ IOCMD_FCPIM_DEL_ITN_STATS,
+ IOCMD_ITNIM_GET_ATTR,
+ IOCMD_ITNIM_GET_IOSTATS,
+ IOCMD_ITNIM_GET_ITNSTATS,
+ IOCMD_IOC_PCIFN_CFG,
+ IOCMD_FCPORT_ENABLE,
+ IOCMD_FCPORT_DISABLE,
+ IOCMD_PCIFN_CREATE,
+ IOCMD_PCIFN_DELETE,
+ IOCMD_PCIFN_BW,
+ IOCMD_ADAPTER_CFG_MODE,
+ IOCMD_PORT_CFG_MODE,
+ IOCMD_FLASH_ENABLE_OPTROM,
+ IOCMD_FLASH_DISABLE_OPTROM,
+ IOCMD_FAA_ENABLE,
+ IOCMD_FAA_DISABLE,
+ IOCMD_FAA_QUERY,
+ IOCMD_CEE_GET_ATTR,
+ IOCMD_CEE_GET_STATS,
+ IOCMD_CEE_RESET_STATS,
+ IOCMD_SFP_MEDIA,
+ IOCMD_SFP_SPEED,
+ IOCMD_FLASH_GET_ATTR,
+ IOCMD_FLASH_ERASE_PART,
+ IOCMD_FLASH_UPDATE_PART,
+ IOCMD_FLASH_READ_PART,
+ IOCMD_DIAG_TEMP,
+ IOCMD_DIAG_MEMTEST,
+ IOCMD_DIAG_LOOPBACK,
+ IOCMD_DIAG_FWPING,
+ IOCMD_DIAG_QUEUETEST,
+ IOCMD_DIAG_SFP,
+ IOCMD_DIAG_LED,
+ IOCMD_DIAG_BEACON_LPORT,
+ IOCMD_DIAG_LB_STAT,
+ IOCMD_PHY_GET_ATTR,
+ IOCMD_PHY_GET_STATS,
+ IOCMD_PHY_UPDATE_FW,
+ IOCMD_PHY_READ_FW,
+ IOCMD_VHBA_QUERY,
+ IOCMD_DEBUG_PORTLOG,
+};
+
+struct bfa_bsg_gen_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+};
+
+struct bfa_bsg_ioc_info_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ char serialnum[64];
+ char hwpath[BFA_STRING_32];
+ char adapter_hwpath[BFA_STRING_32];
+ char guid[BFA_ADAPTER_SYM_NAME_LEN*2];
+ char name[BFA_ADAPTER_SYM_NAME_LEN];
+ char port_name[BFA_ADAPTER_SYM_NAME_LEN];
+ char eth_name[BFA_ADAPTER_SYM_NAME_LEN];
+ wwn_t pwwn;
+ wwn_t nwwn;
+ wwn_t factorypwwn;
+ wwn_t factorynwwn;
+ mac_t mac;
+ mac_t factory_mac; /* Factory mac address */
+ mac_t current_mac; /* Currently assigned mac address */
+ enum bfa_ioc_type_e ioc_type;
+ u16 pvid; /* Port vlan id */
+ u16 rsvd1;
+ u32 host;
+ u32 bandwidth; /* For PF support */
+ u32 rsvd2;
+};
+
+struct bfa_bsg_ioc_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_ioc_attr_s ioc_attr;
+};
+
+struct bfa_bsg_ioc_stats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_ioc_stats_s ioc_stats;
+};
+
+struct bfa_bsg_ioc_fwstats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 buf_size;
+ u32 rsvd1;
+ u64 buf_ptr;
+};
+
+struct bfa_bsg_iocfc_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_iocfc_attr_s iocfc_attr;
+};
+
+struct bfa_bsg_iocfc_intr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_iocfc_intr_attr_s attr;
+};
+
+struct bfa_bsg_port_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_port_attr_s attr;
+};
+
+struct bfa_bsg_port_stats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 buf_size;
+ u32 rsvd1;
+ u64 buf_ptr;
+};
+
+struct bfa_bsg_lport_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t pwwn;
+ struct bfa_lport_attr_s port_attr;
+};
+
+struct bfa_bsg_lport_stats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t pwwn;
+ struct bfa_lport_stats_s port_stats;
+};
+
+struct bfa_bsg_lport_iostats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t pwwn;
+ struct bfa_itnim_iostats_s iostats;
+};
+
+struct bfa_bsg_lport_get_rports_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t pwwn;
+ u64 rbuf_ptr;
+ u32 nrports;
+ u32 rsvd;
+};
+
+struct bfa_bsg_rport_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t pwwn;
+ wwn_t rpwwn;
+ struct bfa_rport_attr_s attr;
+};
+
+struct bfa_bsg_rport_stats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t pwwn;
+ wwn_t rpwwn;
+ struct bfa_rport_stats_s stats;
+};
+
+struct bfa_bsg_rport_scsi_addr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t pwwn;
+ wwn_t rpwwn;
+ u32 host;
+ u32 bus;
+ u32 target;
+ u32 lun;
+};
+
+struct bfa_bsg_fabric_get_lports_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ u64 buf_ptr;
+ u32 nports;
+ u32 rsvd;
+};
+
+struct bfa_bsg_fcpim_modstats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ struct bfa_itnim_iostats_s modstats;
+};
+
+struct bfa_bsg_fcpim_del_itn_stats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ struct bfa_fcpim_del_itn_stats_s modstats;
+};
+
+struct bfa_bsg_itnim_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t lpwwn;
+ wwn_t rpwwn;
+ struct bfa_itnim_attr_s attr;
+};
+
+struct bfa_bsg_itnim_iostats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t lpwwn;
+ wwn_t rpwwn;
+ struct bfa_itnim_iostats_s iostats;
+};
+
+struct bfa_bsg_itnim_itnstats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ wwn_t lpwwn;
+ wwn_t rpwwn;
+ struct bfa_itnim_stats_s itnstats;
+};
+
+struct bfa_bsg_pcifn_cfg_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_ablk_cfg_s pcifn_cfg;
+};
+
+struct bfa_bsg_pcifn_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 pcifn_id;
+ u32 bandwidth;
+ u8 port;
+ enum bfi_pcifn_class pcifn_class;
+ u8 rsvd[1];
+};
+
+struct bfa_bsg_adapter_cfg_mode_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_adapter_cfg_mode_s cfg;
+};
+
+struct bfa_bsg_port_cfg_mode_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 instance;
+ struct bfa_port_cfg_mode_s cfg;
+};
+
+struct bfa_bsg_faa_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_faa_attr_s faa_attr;
+};
+
+struct bfa_bsg_cee_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 buf_size;
+ u32 rsvd1;
+ u64 buf_ptr;
+};
+
+struct bfa_bsg_cee_stats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 buf_size;
+ u32 rsvd1;
+ u64 buf_ptr;
+};
+
+struct bfa_bsg_sfp_media_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ enum bfa_defs_sfp_media_e media;
+};
+
+struct bfa_bsg_sfp_speed_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ enum bfa_port_speed speed;
+};
+
+struct bfa_bsg_flash_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_flash_attr_s attr;
+};
+
+struct bfa_bsg_flash_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u8 instance;
+ u8 rsvd;
+ enum bfa_flash_part_type type;
+ int bufsz;
+ u64 buf_ptr;
+};
+
+struct bfa_bsg_diag_get_temp_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_diag_results_tempsensor_s result;
+};
+
+struct bfa_bsg_diag_memtest_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd[3];
+ u32 pat;
+ struct bfa_diag_memtest_result result;
+ struct bfa_diag_memtest_s memtest;
+};
+
+struct bfa_bsg_diag_loopback_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ enum bfa_port_opmode opmode;
+ enum bfa_port_speed speed;
+ u32 lpcnt;
+ u32 pat;
+ struct bfa_diag_loopback_result_s result;
+};
+
+struct bfa_bsg_diag_fwping_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 cnt;
+ u32 pattern;
+ struct bfa_diag_results_fwping result;
+};
+
+struct bfa_bsg_diag_qtest_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 force;
+ u32 queue;
+ struct bfa_diag_qtest_result_s result;
+};
+
+struct bfa_bsg_sfp_show_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct sfp_mem_s sfp;
+};
+
+struct bfa_bsg_diag_led_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_diag_ledtest_s ledtest;
+};
+
+struct bfa_bsg_diag_beacon_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ bfa_boolean_t beacon;
+ bfa_boolean_t link_e2e_beacon;
+ u32 second;
+};
+
+struct bfa_bsg_diag_lb_stat_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+};
+
+struct bfa_bsg_phy_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 instance;
+ struct bfa_phy_attr_s attr;
+};
+
+struct bfa_bsg_phy_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 instance;
+ u64 bufsz;
+ u64 buf_ptr;
+};
+
+struct bfa_bsg_debug_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 bufsz;
+ int inst_no;
+ u64 buf_ptr;
+ u64 offset;
+};
+
+struct bfa_bsg_phy_stats_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 instance;
+ struct bfa_phy_stats_s stats;
+};
+
+struct bfa_bsg_vhba_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 pcifn_id;
+ struct bfa_vhba_attr_s attr;
+};
+
+struct bfa_bsg_fcpt_s {
+ bfa_status_t status;
+ u16 vf_id;
+ wwn_t lpwwn;
+ wwn_t dpwwn;
+ u32 tsecs;
+ int cts;
+ enum fc_cos cos;
+ struct fchs_s fchs;
+};
+#define bfa_bsg_fcpt_t struct bfa_bsg_fcpt_s
+
+struct bfa_bsg_data {
+ int payload_len;
+ void *payload;
+};
+
+#define bfad_chk_iocmd_sz(__payload_len, __hdrsz, __bufsz) \
+ (((__payload_len) != ((__hdrsz) + (__bufsz))) ? \
+ BFA_STATUS_FAILED : BFA_STATUS_OK)
+
+#endif /* BFAD_BSG_H */
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 48be0c54f2de..b412e0300dd4 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -214,10 +214,10 @@ bfad_debugfs_read(struct file *file, char __user *buf,
#define BFA_REG_CT_ADDRSZ (0x40000)
#define BFA_REG_CB_ADDRSZ (0x20000)
-#define BFA_REG_ADDRSZ(__bfa) \
- ((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ? \
- BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)
-#define BFA_REG_ADDRMSK(__bfa) ((u32)(BFA_REG_ADDRSZ(__bfa) - 1))
+#define BFA_REG_ADDRSZ(__ioc) \
+ ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \
+ BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
+#define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1)
static bfa_status_t
bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
@@ -236,7 +236,7 @@ bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
return BFA_STATUS_EINVAL;
} else {
/* CB register space 64KB */
- if ((offset + (len<<2)) > BFA_REG_ADDRMSK(bfa))
+ if ((offset + (len<<2)) > BFA_REG_ADDRMSK(&bfa->ioc))
return BFA_STATUS_EINVAL;
}
return BFA_STATUS_OK;
@@ -317,7 +317,7 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
bfad->reglen = len << 2;
rb = bfa_ioc_bar0(ioc);
- addr &= BFA_REG_ADDRMSK(bfa);
+ addr &= BFA_REG_ADDRMSK(ioc);
/* offset and len sanity check */
rc = bfad_reg_offset_check(bfa, addr, len);
@@ -380,7 +380,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
}
kfree(kern_buf);
- addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */
+ addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */
/* offset and len sanity check */
rc = bfad_reg_offset_check(bfa, addr, 1);
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 7f9ea90254cd..48661a2726d7 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -43,6 +43,7 @@
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_transport.h>
+#include <scsi/scsi_bsg_fc.h>
#include "bfa_modules.h"
#include "bfa_fcs.h"
@@ -55,7 +56,7 @@
#ifdef BFA_DRIVER_VERSION
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
#else
-#define BFAD_DRIVER_VERSION "2.3.2.3"
+#define BFAD_DRIVER_VERSION "3.0.2.1"
#endif
#define BFAD_PROTO_NAME FCPI_NAME
@@ -79,7 +80,7 @@
#define BFAD_HAL_INIT_FAIL 0x00000100
#define BFAD_FC4_PROBE_DONE 0x00000200
#define BFAD_PORT_DELETE 0x00000001
-
+#define BFAD_INTX_ON 0x00000400
/*
* BFAD related definition
*/
@@ -92,6 +93,8 @@
*/
#define BFAD_LUN_QUEUE_DEPTH 32
#define BFAD_IO_MAX_SGE SG_ALL
+#define BFAD_MIN_SECTORS 128 /* 64k */
+#define BFAD_MAX_SECTORS 0xFFFF /* 32 MB */
#define bfad_isr_t irq_handler_t
@@ -110,6 +113,7 @@ struct bfad_msix_s {
enum {
BFA_TRC_LDRV_BFAD = 1,
BFA_TRC_LDRV_IM = 2,
+ BFA_TRC_LDRV_BSG = 3,
};
enum bfad_port_pvb_type {
@@ -189,8 +193,10 @@ struct bfad_s {
struct bfa_pcidev_s hal_pcidev;
struct bfa_ioc_pci_attr_s pci_attr;
void __iomem *pci_bar0_kva;
+ void __iomem *pci_bar2_kva;
struct completion comp;
struct completion suspend;
+ struct completion enable_comp;
struct completion disable_comp;
bfa_boolean_t disable_active;
struct bfad_port_s pport; /* physical port of the BFAD */
@@ -273,21 +279,6 @@ struct bfad_hal_comp {
struct completion comp;
};
-/*
- * Macro to obtain the immediate lower power
- * of two for the integer.
- */
-#define nextLowerInt(x) \
-do { \
- int __i; \
- (*x)--; \
- for (__i = 1; __i < (sizeof(int)*8); __i <<= 1) \
- (*x) = (*x) | (*x) >> __i; \
- (*x)++; \
- (*x) = (*x) >> 1; \
-} while (0)
-
-
#define BFA_LOG(level, bfad, mask, fmt, arg...) \
do { \
if (((mask) == 4) || (level[1] <= '4')) \
@@ -354,6 +345,7 @@ extern int msix_disable_ct;
extern int fdmi_enable;
extern int supported_fc4s;
extern int pcie_max_read_reqsz;
+extern int max_xfer_size;
extern int bfa_debugfs_enable;
extern struct mutex bfad_mutex;
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index c2b36179e8e8..f2bf81265ae5 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -175,21 +175,11 @@ bfad_im_info(struct Scsi_Host *shost)
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
- struct bfa_s *bfa = &bfad->bfa;
- struct bfa_ioc_s *ioc = &bfa->ioc;
- char model[BFA_ADAPTER_MODEL_NAME_LEN];
-
- bfa_get_adapter_model(bfa, model);
memset(bfa_buf, 0, sizeof(bfa_buf));
- if (ioc->ctdev && !ioc->fcmode)
- snprintf(bfa_buf, sizeof(bfa_buf),
- "Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
- model, bfad->pci_name, BFAD_DRIVER_VERSION);
- else
- snprintf(bfa_buf, sizeof(bfa_buf),
- "Brocade FC Adapter, " "model: %s hwpath: %s driver: %s",
- model, bfad->pci_name, BFAD_DRIVER_VERSION);
+ snprintf(bfa_buf, sizeof(bfa_buf),
+ "Brocade FC/FCOE Adapter, " "hwpath: %s driver: %s",
+ bfad->pci_name, BFAD_DRIVER_VERSION);
return bfa_buf;
}
@@ -572,9 +562,6 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
goto out_fc_rel;
}
- /* setup host fixed attribute if the lk supports */
- bfad_fc_host_init(im_port);
-
return 0;
out_fc_rel:
@@ -713,6 +700,9 @@ bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
else
sht = &bfad_im_vport_template;
+ if (max_xfer_size != BFAD_MAX_SECTORS >> 1)
+ sht->max_sectors = max_xfer_size << 1;
+
sht->sg_tablesize = bfad->cfg_data.io_max_sge;
return scsi_host_alloc(sht, sizeof(unsigned long));
@@ -790,7 +780,8 @@ struct scsi_host_template bfad_im_scsi_host_template = {
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = bfad_im_host_attrs,
- .max_sectors = 0xFFFF,
+ .max_sectors = BFAD_MAX_SECTORS,
+ .vendor_id = BFA_PCI_VENDOR_ID_BROCADE,
};
struct scsi_host_template bfad_im_vport_template = {
@@ -811,7 +802,7 @@ struct scsi_host_template bfad_im_vport_template = {
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = bfad_im_vport_attrs,
- .max_sectors = 0xFFFF,
+ .max_sectors = BFAD_MAX_SECTORS,
};
bfa_status_t
@@ -925,7 +916,10 @@ bfad_im_supported_speeds(struct bfa_s *bfa)
return 0;
bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
- if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
+ if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_16GBPS)
+ supported_speed |= FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT |
+ FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT;
+ else if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
if (ioc_attr->adapter_attr.is_mezz) {
supported_speed |= FC_PORTSPEED_8GBIT |
FC_PORTSPEED_4GBIT |
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index c296c8968511..4fe34d576b05 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -141,4 +141,7 @@ extern struct device_attribute *bfad_im_vport_attrs[];
irqreturn_t bfad_intx(int irq, void *dev_id);
+int bfad_im_bsg_request(struct fc_bsg_job *job);
+int bfad_im_bsg_timeout(struct fc_bsg_job *job);
+
#endif
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index 72b69a0c3b51..1e258d5f8aec 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -23,17 +23,29 @@
#pragma pack(1)
+/* Per dma segment max size */
+#define BFI_MEM_DMA_SEG_SZ (131072)
+
+/* Get number of dma segments required */
+#define BFI_MEM_DMA_NSEGS(_num_reqs, _req_sz) \
+ ((u16)(((((_num_reqs) * (_req_sz)) + BFI_MEM_DMA_SEG_SZ - 1) & \
+ ~(BFI_MEM_DMA_SEG_SZ - 1)) / BFI_MEM_DMA_SEG_SZ))
+
+/* Get num dma reqs - that fit in a segment */
+#define BFI_MEM_NREQS_SEG(_rqsz) (BFI_MEM_DMA_SEG_SZ / (_rqsz))
+
+/* Get segment num from tag */
+#define BFI_MEM_SEG_FROM_TAG(_tag, _rqsz) ((_tag) / BFI_MEM_NREQS_SEG(_rqsz))
+
+/* Get dma req offset in a segment */
+#define BFI_MEM_SEG_REQ_OFFSET(_tag, _sz) \
+ ((_tag) - (BFI_MEM_SEG_FROM_TAG(_tag, _sz) * BFI_MEM_NREQS_SEG(_sz)))
+
/*
* BFI FW image type
*/
#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 +55,20 @@ struct bfi_mhdr_s {
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_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 { \
@@ -101,7 +116,7 @@ union bfi_addr_u {
};
/*
- * Scatter Gather Element
+ * Scatter Gather Element used for fast-path IO requests
*/
struct bfi_sge_s {
#ifdef __BIG_ENDIAN
@@ -116,6 +131,14 @@ struct bfi_sge_s {
union bfi_addr_u sga;
};
+/**
+ * Generic DMA addr-len pair.
+ */
+struct bfi_alen_s {
+ union bfi_addr_u al_addr; /* DMA addr of buffer */
+ u32 al_len; /* length of buffer */
+};
+
/*
* Scatter Gather Page
*/
@@ -127,6 +150,12 @@ struct bfi_sgpg_s {
u32 rsvd[BFI_SGPG_RSVD_WD_LEN];
};
+/* FCP module definitions */
+#define BFI_IO_MAX (2000)
+#define BFI_IOIM_SNSLEN (256)
+#define BFI_IOIM_SNSBUF_SEGS \
+ BFI_MEM_DMA_NSEGS(BFI_IO_MAX, BFI_IOIM_SNSLEN)
+
/*
* Large Message structure - 128 Bytes size Msgs
*/
@@ -149,18 +178,29 @@ struct bfi_mbmsg_s {
};
/*
+ * 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 {
BFI_MC_IOC = 1, /* IO Controller (IOC) */
+ BFI_MC_DIAG = 2, /* Diagnostic Msgs */
+ BFI_MC_FLASH = 3, /* Flash message class */
+ BFI_MC_CEE = 4, /* CEE */
BFI_MC_FCPORT = 5, /* FC port */
BFI_MC_IOCFC = 6, /* FC - IO Controller (IOC) */
- BFI_MC_LL = 7, /* Link Layer */
+ BFI_MC_ABLK = 7, /* ASIC block configuration */
BFI_MC_UF = 8, /* Unsolicited frame receive */
BFI_MC_FCXP = 9, /* FC Transport */
BFI_MC_LPS = 10, /* lport fc login services */
BFI_MC_RPORT = 11, /* Remote port */
- BFI_MC_ITNIM = 12, /* I-T nexus (Initiator mode) */
+ BFI_MC_ITN = 12, /* I-T nexus (Initiator mode) */
BFI_MC_IOIM_READ = 13, /* read IO (Initiator mode) */
BFI_MC_IOIM_WRITE = 14, /* write IO (Initiator mode) */
BFI_MC_IOIM_IO = 15, /* IO (Initiator mode) */
@@ -168,6 +208,8 @@ enum bfi_mclass {
BFI_MC_IOIM_IOCOM = 17, /* good IO completion */
BFI_MC_TSKIM = 18, /* Initiator Task management */
BFI_MC_PORT = 21, /* Physical port */
+ BFI_MC_SFP = 22, /* SFP module */
+ BFI_MC_PHY = 25, /* External PHY message class */
BFI_MC_MAX = 32
};
@@ -175,23 +217,28 @@ enum bfi_mclass {
#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_LOADER_BIOS 1
-#define BFI_BOOT_LOADER_UEFI 2
-
/*
*----------------------------------------------------------------------
* IOC
*----------------------------------------------------------------------
*/
+/*
+ * Different asic generations
+ */
+enum bfi_asic_gen {
+ BFI_ASIC_GEN_CB = 1, /* crossbow 8G FC */
+ BFI_ASIC_GEN_CT = 2, /* catapult 8G FC or 10G CNA */
+ BFI_ASIC_GEN_CT2 = 3, /* catapult-2 16G FC or 10G CNA */
+};
+
+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,
@@ -204,8 +251,8 @@ 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),
+ BFI_IOC_I2H_ACQ_ADDR_REPLY = BFA_I2HM(5),
};
/*
@@ -220,7 +267,8 @@ struct bfi_ioc_attr_s {
wwn_t mfg_pwwn; /* Mfg port wwn */
wwn_t mfg_nwwn; /* Mfg node wwn */
mac_t mfg_mac; /* Mfg mac */
- u16 rsvd_a;
+ u8 port_mode; /* bfi_port_mode */
+ u8 rsvd_a;
wwn_t pwwn;
wwn_t nwwn;
mac_t mac; /* PBC or Mfg mac */
@@ -272,21 +320,33 @@ struct bfi_ioc_getattr_reply_s {
#define BFI_IOC_FW_SIGNATURE (0xbfadbfad)
#define BFI_IOC_MD5SUM_SZ 4
struct bfi_ioc_image_hdr_s {
- u32 signature; /* constant signature */
- u32 rsvd_a;
- u32 exec; /* exec vector */
- u32 param; /* parameters */
+ u32 signature; /* constant signature */
+ 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 bootenv; /* fimware boot env */
u32 rsvd_b[4];
u32 md5sum[BFI_IOC_MD5SUM_SZ];
};
-/*
- * BFI_IOC_I2H_READY_EVENT message
- */
-struct bfi_ioc_rdy_event_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 init_status; /* init event status */
- u8 rsvd[3];
+#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)))
+
+#define BFI_FWBOOT_TYPE_NORMAL 0
+#define BFI_FWBOOT_TYPE_MEMTEST 2
+#define BFI_FWBOOT_ENV_OS 0
+
+enum bfi_port_mode {
+ BFI_PORT_MODE_FC = 1,
+ BFI_PORT_MODE_ETH = 2,
};
struct bfi_ioc_hbeat_s {
@@ -345,8 +405,8 @@ enum {
*/
struct bfi_ioc_ctrl_req_s {
struct bfi_mhdr_s mh;
- u8 ioc_class;
- u8 rsvd[3];
+ u16 clscode;
+ u16 rsvd;
u32 tv_sec;
};
#define bfi_ioc_enable_req_t struct bfi_ioc_ctrl_req_s;
@@ -358,7 +418,9 @@ struct bfi_ioc_ctrl_req_s {
struct bfi_ioc_ctrl_reply_s {
struct bfi_mhdr_s mh; /* Common msg header */
u8 status; /* enable/disable status */
- u8 rsvd[3];
+ u8 port_mode; /* bfa_mode_s */
+ u8 cap_bm; /* capability bit mask */
+ u8 rsvd;
};
#define bfi_ioc_enable_reply_t struct bfi_ioc_ctrl_reply_s;
#define bfi_ioc_disable_reply_t struct bfi_ioc_ctrl_reply_s;
@@ -380,7 +442,7 @@ union bfi_ioc_h2i_msg_u {
*/
union bfi_ioc_i2h_msg_u {
struct bfi_mhdr_s mh;
- struct bfi_ioc_rdy_event_s rdy_event;
+ struct bfi_ioc_ctrl_reply_s fw_event;
u32 mboxmsg[BFI_IOC_MSGSZ];
};
@@ -393,6 +455,7 @@ union bfi_ioc_i2h_msg_u {
#define BFI_PBC_MAX_BLUNS 8
#define BFI_PBC_MAX_VPORTS 16
+#define BFI_PBC_PORT_DISABLED 2
/*
* PBC boot lun configuration
@@ -574,6 +637,496 @@ union bfi_port_i2h_msg_u {
struct bfi_port_generic_rsp_s clearstats_rsp;
};
+/*
+ *----------------------------------------------------------------------
+ * ABLK
+ *----------------------------------------------------------------------
+ */
+enum bfi_ablk_h2i_msgs_e {
+ BFI_ABLK_H2I_QUERY = 1,
+ BFI_ABLK_H2I_ADPT_CONFIG = 2,
+ BFI_ABLK_H2I_PORT_CONFIG = 3,
+ BFI_ABLK_H2I_PF_CREATE = 4,
+ BFI_ABLK_H2I_PF_DELETE = 5,
+ BFI_ABLK_H2I_PF_UPDATE = 6,
+ BFI_ABLK_H2I_OPTROM_ENABLE = 7,
+ BFI_ABLK_H2I_OPTROM_DISABLE = 8,
+};
+
+enum bfi_ablk_i2h_msgs_e {
+ BFI_ABLK_I2H_QUERY = BFA_I2HM(BFI_ABLK_H2I_QUERY),
+ BFI_ABLK_I2H_ADPT_CONFIG = BFA_I2HM(BFI_ABLK_H2I_ADPT_CONFIG),
+ BFI_ABLK_I2H_PORT_CONFIG = BFA_I2HM(BFI_ABLK_H2I_PORT_CONFIG),
+ BFI_ABLK_I2H_PF_CREATE = BFA_I2HM(BFI_ABLK_H2I_PF_CREATE),
+ BFI_ABLK_I2H_PF_DELETE = BFA_I2HM(BFI_ABLK_H2I_PF_DELETE),
+ BFI_ABLK_I2H_PF_UPDATE = BFA_I2HM(BFI_ABLK_H2I_PF_UPDATE),
+ BFI_ABLK_I2H_OPTROM_ENABLE = BFA_I2HM(BFI_ABLK_H2I_OPTROM_ENABLE),
+ BFI_ABLK_I2H_OPTROM_DISABLE = BFA_I2HM(BFI_ABLK_H2I_OPTROM_DISABLE),
+};
+
+/* BFI_ABLK_H2I_QUERY */
+struct bfi_ablk_h2i_query_s {
+ struct bfi_mhdr_s mh;
+ union bfi_addr_u addr;
+};
+
+/* BFI_ABL_H2I_ADPT_CONFIG, BFI_ABLK_H2I_PORT_CONFIG */
+struct bfi_ablk_h2i_cfg_req_s {
+ struct bfi_mhdr_s mh;
+ u8 mode;
+ u8 port;
+ u8 max_pf;
+ u8 max_vf;
+};
+
+/*
+ * BFI_ABLK_H2I_PF_CREATE, BFI_ABLK_H2I_PF_DELETE,
+ */
+struct bfi_ablk_h2i_pf_req_s {
+ struct bfi_mhdr_s mh;
+ u8 pcifn;
+ u8 port;
+ u16 pers;
+ u32 bw;
+};
+
+/* BFI_ABLK_H2I_OPTROM_ENABLE, BFI_ABLK_H2I_OPTROM_DISABLE */
+struct bfi_ablk_h2i_optrom_s {
+ struct bfi_mhdr_s mh;
+};
+
+/*
+ * BFI_ABLK_I2H_QUERY
+ * BFI_ABLK_I2H_PORT_CONFIG
+ * BFI_ABLK_I2H_PF_CREATE
+ * BFI_ABLK_I2H_PF_DELETE
+ * BFI_ABLK_I2H_PF_UPDATE
+ * BFI_ABLK_I2H_OPTROM_ENABLE
+ * BFI_ABLK_I2H_OPTROM_DISABLE
+ */
+struct bfi_ablk_i2h_rsp_s {
+ struct bfi_mhdr_s mh;
+ u8 status;
+ u8 pcifn;
+ u8 port_mode;
+};
+
+
+/*
+ * CEE module specific messages
+ */
+
+/* Mailbox commands from host to firmware */
+enum bfi_cee_h2i_msgs_e {
+ BFI_CEE_H2I_GET_CFG_REQ = 1,
+ BFI_CEE_H2I_RESET_STATS = 2,
+ BFI_CEE_H2I_GET_STATS_REQ = 3,
+};
+
+enum bfi_cee_i2h_msgs_e {
+ BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
+ BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
+ BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
+};
+
+/*
+ * H2I command structure for resetting the stats
+ */
+struct bfi_cee_reset_stats_s {
+ struct bfi_mhdr_s mh;
+};
+
+/*
+ * Get configuration command from host
+ */
+struct bfi_cee_get_req_s {
+ struct bfi_mhdr_s mh;
+ union bfi_addr_u dma_addr;
+};
+
+/*
+ * Reply message from firmware
+ */
+struct bfi_cee_get_rsp_s {
+ struct bfi_mhdr_s mh;
+ u8 cmd_status;
+ u8 rsvd[3];
+};
+
+/*
+ * Reply message from firmware
+ */
+struct bfi_cee_stats_rsp_s {
+ struct bfi_mhdr_s mh;
+ u8 cmd_status;
+ u8 rsvd[3];
+};
+
+/* Mailbox message structures from firmware to host */
+union bfi_cee_i2h_msg_u {
+ struct bfi_mhdr_s mh;
+ struct bfi_cee_get_rsp_s get_rsp;
+ struct bfi_cee_stats_rsp_s stats_rsp;
+};
+
+/*
+ * SFP related
+ */
+
+enum bfi_sfp_h2i_e {
+ BFI_SFP_H2I_SHOW = 1,
+ BFI_SFP_H2I_SCN = 2,
+};
+
+enum bfi_sfp_i2h_e {
+ BFI_SFP_I2H_SHOW = BFA_I2HM(BFI_SFP_H2I_SHOW),
+ BFI_SFP_I2H_SCN = BFA_I2HM(BFI_SFP_H2I_SCN),
+};
+
+/*
+ * SFP state
+ */
+enum bfa_sfp_stat_e {
+ BFA_SFP_STATE_INIT = 0, /* SFP state is uninit */
+ BFA_SFP_STATE_REMOVED = 1, /* SFP is removed */
+ BFA_SFP_STATE_INSERTED = 2, /* SFP is inserted */
+ BFA_SFP_STATE_VALID = 3, /* SFP is valid */
+ BFA_SFP_STATE_UNSUPPORT = 4, /* SFP is unsupport */
+ BFA_SFP_STATE_FAILED = 5, /* SFP i2c read fail */
+};
+
+/*
+ * SFP memory access type
+ */
+enum bfi_sfp_mem_e {
+ BFI_SFP_MEM_ALL = 0x1, /* access all data field */
+ BFI_SFP_MEM_DIAGEXT = 0x2, /* access diag ext data field only */
+};
+
+struct bfi_sfp_req_s {
+ struct bfi_mhdr_s mh;
+ u8 memtype;
+ u8 rsvd[3];
+ struct bfi_alen_s alen;
+};
+
+struct bfi_sfp_rsp_s {
+ struct bfi_mhdr_s mh;
+ u8 status;
+ u8 state;
+ u8 rsvd[2];
+};
+
+/*
+ * FLASH module specific
+ */
+enum bfi_flash_h2i_msgs {
+ BFI_FLASH_H2I_QUERY_REQ = 1,
+ BFI_FLASH_H2I_ERASE_REQ = 2,
+ BFI_FLASH_H2I_WRITE_REQ = 3,
+ BFI_FLASH_H2I_READ_REQ = 4,
+ BFI_FLASH_H2I_BOOT_VER_REQ = 5,
+};
+
+enum bfi_flash_i2h_msgs {
+ BFI_FLASH_I2H_QUERY_RSP = BFA_I2HM(1),
+ BFI_FLASH_I2H_ERASE_RSP = BFA_I2HM(2),
+ BFI_FLASH_I2H_WRITE_RSP = BFA_I2HM(3),
+ BFI_FLASH_I2H_READ_RSP = BFA_I2HM(4),
+ BFI_FLASH_I2H_BOOT_VER_RSP = BFA_I2HM(5),
+ BFI_FLASH_I2H_EVENT = BFA_I2HM(127),
+};
+
+/*
+ * Flash query request
+ */
+struct bfi_flash_query_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ struct bfi_alen_s alen;
+};
+
+/*
+ * Flash erase request
+ */
+struct bfi_flash_erase_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 type; /* partition type */
+ u8 instance; /* partition instance */
+ u8 rsv[3];
+};
+
+/*
+ * Flash write request
+ */
+struct bfi_flash_write_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ struct bfi_alen_s alen;
+ u32 type; /* partition type */
+ u8 instance; /* partition instance */
+ u8 last;
+ u8 rsv[2];
+ u32 offset;
+ u32 length;
+};
+
+/*
+ * Flash read request
+ */
+struct bfi_flash_read_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 type; /* partition type */
+ u8 instance; /* partition instance */
+ u8 rsv[3];
+ u32 offset;
+ u32 length;
+ struct bfi_alen_s alen;
+};
+
+/*
+ * Flash query response
+ */
+struct bfi_flash_query_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 status;
+};
+
+/*
+ * Flash read response
+ */
+struct bfi_flash_read_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 type; /* partition type */
+ u8 instance; /* partition instance */
+ u8 rsv[3];
+ u32 status;
+ u32 length;
+};
+
+/*
+ * Flash write response
+ */
+struct bfi_flash_write_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 type; /* partition type */
+ u8 instance; /* partition instance */
+ u8 rsv[3];
+ u32 status;
+ u32 length;
+};
+
+/*
+ * Flash erase response
+ */
+struct bfi_flash_erase_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 type; /* partition type */
+ u8 instance; /* partition instance */
+ u8 rsv[3];
+ u32 status;
+};
+
+/*
+ *----------------------------------------------------------------------
+ * DIAG
+ *----------------------------------------------------------------------
+ */
+enum bfi_diag_h2i {
+ BFI_DIAG_H2I_PORTBEACON = 1,
+ BFI_DIAG_H2I_LOOPBACK = 2,
+ BFI_DIAG_H2I_FWPING = 3,
+ BFI_DIAG_H2I_TEMPSENSOR = 4,
+ BFI_DIAG_H2I_LEDTEST = 5,
+ BFI_DIAG_H2I_QTEST = 6,
+};
+
+enum bfi_diag_i2h {
+ BFI_DIAG_I2H_PORTBEACON = BFA_I2HM(BFI_DIAG_H2I_PORTBEACON),
+ BFI_DIAG_I2H_LOOPBACK = BFA_I2HM(BFI_DIAG_H2I_LOOPBACK),
+ BFI_DIAG_I2H_FWPING = BFA_I2HM(BFI_DIAG_H2I_FWPING),
+ BFI_DIAG_I2H_TEMPSENSOR = BFA_I2HM(BFI_DIAG_H2I_TEMPSENSOR),
+ BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST),
+ BFI_DIAG_I2H_QTEST = BFA_I2HM(BFI_DIAG_H2I_QTEST),
+};
+
+#define BFI_DIAG_MAX_SGES 2
+#define BFI_DIAG_DMA_BUF_SZ (2 * 1024)
+#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
+#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3
+
+struct bfi_diag_lb_req_s {
+ struct bfi_mhdr_s mh;
+ u32 loopcnt;
+ u32 pattern;
+ u8 lb_mode; /*!< bfa_port_opmode_t */
+ u8 speed; /*!< bfa_port_speed_t */
+ u8 rsvd[2];
+};
+
+struct bfi_diag_lb_rsp_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ struct bfa_diag_loopback_result_s res; /* 16 bytes */
+};
+
+struct bfi_diag_fwping_req_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ struct bfi_alen_s alen; /* 12 bytes */
+ u32 data; /* user input data pattern */
+ u32 count; /* user input dma count */
+ u8 qtag; /* track CPE vc */
+ u8 rsv[3];
+};
+
+struct bfi_diag_fwping_rsp_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ u32 data; /* user input data pattern */
+ u8 qtag; /* track CPE vc */
+ u8 dma_status; /* dma status */
+ u8 rsv[2];
+};
+
+/*
+ * Temperature Sensor
+ */
+struct bfi_diag_ts_req_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ u16 temp; /* 10-bit A/D value */
+ u16 brd_temp; /* 9-bit board temp */
+ u8 status;
+ u8 ts_junc; /* show junction tempsensor */
+ u8 ts_brd; /* show board tempsensor */
+ u8 rsv;
+};
+#define bfi_diag_ts_rsp_t struct bfi_diag_ts_req_s
+
+struct bfi_diag_ledtest_req_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ u8 cmd;
+ u8 color;
+ u8 portid;
+ u8 led; /* bitmap of LEDs to be tested */
+ u16 freq; /* no. of blinks every 10 secs */
+ u8 rsv[2];
+};
+
+/* notify host led operation is done */
+struct bfi_diag_ledtest_rsp_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+};
+
+struct bfi_diag_portbeacon_req_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ u32 period; /* beaconing period */
+ u8 beacon; /* 1: beacon on */
+ u8 rsvd[3];
+};
+
+/* notify host the beacon is off */
+struct bfi_diag_portbeacon_rsp_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+};
+
+struct bfi_diag_qtest_req_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ u32 data[BFI_LMSG_PL_WSZ]; /* fill up tcm prefetch area */
+};
+#define bfi_diag_qtest_rsp_t struct bfi_diag_qtest_req_s
+
+/*
+ * PHY module specific
+ */
+enum bfi_phy_h2i_msgs_e {
+ BFI_PHY_H2I_QUERY_REQ = 1,
+ BFI_PHY_H2I_STATS_REQ = 2,
+ BFI_PHY_H2I_WRITE_REQ = 3,
+ BFI_PHY_H2I_READ_REQ = 4,
+};
+
+enum bfi_phy_i2h_msgs_e {
+ BFI_PHY_I2H_QUERY_RSP = BFA_I2HM(1),
+ BFI_PHY_I2H_STATS_RSP = BFA_I2HM(2),
+ BFI_PHY_I2H_WRITE_RSP = BFA_I2HM(3),
+ BFI_PHY_I2H_READ_RSP = BFA_I2HM(4),
+};
+
+/*
+ * External PHY query request
+ */
+struct bfi_phy_query_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 instance;
+ u8 rsv[3];
+ struct bfi_alen_s alen;
+};
+
+/*
+ * External PHY stats request
+ */
+struct bfi_phy_stats_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 instance;
+ u8 rsv[3];
+ struct bfi_alen_s alen;
+};
+
+/*
+ * External PHY write request
+ */
+struct bfi_phy_write_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 instance;
+ u8 last;
+ u8 rsv[2];
+ u32 offset;
+ u32 length;
+ struct bfi_alen_s alen;
+};
+
+/*
+ * External PHY read request
+ */
+struct bfi_phy_read_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 instance;
+ u8 rsv[3];
+ u32 offset;
+ u32 length;
+ struct bfi_alen_s alen;
+};
+
+/*
+ * External PHY query response
+ */
+struct bfi_phy_query_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 status;
+};
+
+/*
+ * External PHY stats response
+ */
+struct bfi_phy_stats_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 status;
+};
+
+/*
+ * External PHY read response
+ */
+struct bfi_phy_read_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 status;
+ u32 length;
+};
+
+/*
+ * External PHY write response
+ */
+struct bfi_phy_write_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 status;
+ u32 length;
+};
+
#pragma pack()
#endif /* __BFI_H__ */
diff --git a/drivers/scsi/bfa/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h
deleted file mode 100644
index 39ad42b66b5b..000000000000
--- a/drivers/scsi/bfa/bfi_cbreg.h
+++ /dev/null
@@ -1,305 +0,0 @@
-
-/*
- * bfi_cbreg.h crossbow host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CBREG_H__
-#define __BFI_CBREG_H__
-
-
-#define HOSTFN0_INT_STATUS 0x00014000
-#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 0x000fffff
-#define HOSTFN0_INT_MSK 0x00014004
-#define HOST_PAGE_NUM_FN0 0x00014008
-#define __HOST_PAGE_NUM_FN 0x000001ff
-#define HOSTFN1_INT_STATUS 0x00014100
-#define __HOSTFN1_INT_STAT_LVL_MK 0x00f00000
-#define __HOSTFN1_INT_STAT_LVL_SH 20
-#define __HOSTFN1_INT_STAT_LVL(_v) ((_v) << __HOSTFN1_INT_STAT_LVL_SH)
-#define __HOSTFN1_INT_STAT_P 0x000fffff
-#define HOSTFN1_INT_MSK 0x00014104
-#define HOST_PAGE_NUM_FN1 0x00014108
-#define APP_PLL_400_CTL_REG 0x00014204
-#define __P_400_PLL_LOCK 0x80000000
-#define __APP_PLL_400_SRAM_USE_100MHZ 0x00100000
-#define __APP_PLL_400_RESET_TIMER_MK 0x000e0000
-#define __APP_PLL_400_RESET_TIMER_SH 17
-#define __APP_PLL_400_RESET_TIMER(_v) ((_v) << __APP_PLL_400_RESET_TIMER_SH)
-#define __APP_PLL_400_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_400_CNTLMT0_1_MK 0x0000c000
-#define __APP_PLL_400_CNTLMT0_1_SH 14
-#define __APP_PLL_400_CNTLMT0_1(_v) ((_v) << __APP_PLL_400_CNTLMT0_1_SH)
-#define __APP_PLL_400_JITLMT0_1_MK 0x00003000
-#define __APP_PLL_400_JITLMT0_1_SH 12
-#define __APP_PLL_400_JITLMT0_1(_v) ((_v) << __APP_PLL_400_JITLMT0_1_SH)
-#define __APP_PLL_400_HREF 0x00000800
-#define __APP_PLL_400_HDIV 0x00000400
-#define __APP_PLL_400_P0_1_MK 0x00000300
-#define __APP_PLL_400_P0_1_SH 8
-#define __APP_PLL_400_P0_1(_v) ((_v) << __APP_PLL_400_P0_1_SH)
-#define __APP_PLL_400_Z0_2_MK 0x000000e0
-#define __APP_PLL_400_Z0_2_SH 5
-#define __APP_PLL_400_Z0_2(_v) ((_v) << __APP_PLL_400_Z0_2_SH)
-#define __APP_PLL_400_RSEL200500 0x00000010
-#define __APP_PLL_400_ENARST 0x00000008
-#define __APP_PLL_400_BYPASS 0x00000004
-#define __APP_PLL_400_LRESETN 0x00000002
-#define __APP_PLL_400_ENABLE 0x00000001
-#define APP_PLL_212_CTL_REG 0x00014208
-#define __P_212_PLL_LOCK 0x80000000
-#define __APP_PLL_212_RESET_TIMER_MK 0x000e0000
-#define __APP_PLL_212_RESET_TIMER_SH 17
-#define __APP_PLL_212_RESET_TIMER(_v) ((_v) << __APP_PLL_212_RESET_TIMER_SH)
-#define __APP_PLL_212_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_212_CNTLMT0_1_MK 0x0000c000
-#define __APP_PLL_212_CNTLMT0_1_SH 14
-#define __APP_PLL_212_CNTLMT0_1(_v) ((_v) << __APP_PLL_212_CNTLMT0_1_SH)
-#define __APP_PLL_212_JITLMT0_1_MK 0x00003000
-#define __APP_PLL_212_JITLMT0_1_SH 12
-#define __APP_PLL_212_JITLMT0_1(_v) ((_v) << __APP_PLL_212_JITLMT0_1_SH)
-#define __APP_PLL_212_HREF 0x00000800
-#define __APP_PLL_212_HDIV 0x00000400
-#define __APP_PLL_212_P0_1_MK 0x00000300
-#define __APP_PLL_212_P0_1_SH 8
-#define __APP_PLL_212_P0_1(_v) ((_v) << __APP_PLL_212_P0_1_SH)
-#define __APP_PLL_212_Z0_2_MK 0x000000e0
-#define __APP_PLL_212_Z0_2_SH 5
-#define __APP_PLL_212_Z0_2(_v) ((_v) << __APP_PLL_212_Z0_2_SH)
-#define __APP_PLL_212_RSEL200500 0x00000010
-#define __APP_PLL_212_ENARST 0x00000008
-#define __APP_PLL_212_BYPASS 0x00000004
-#define __APP_PLL_212_LRESETN 0x00000002
-#define __APP_PLL_212_ENABLE 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 HOSTFN0_LPU0_CMD_STAT 0x00019000
-#define __HOSTFN0_LPU0_MBOX_INFO_MK 0xfffffffe
-#define __HOSTFN0_LPU0_MBOX_INFO_SH 1
-#define __HOSTFN0_LPU0_MBOX_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN0_CMD_STAT 0x00019008
-#define __LPU0_HOSTFN0_MBOX_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN0_MBOX_INFO_SH 1
-#define __LPU0_HOSTFN0_MBOX_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU1_CMD_STAT 0x00019014
-#define __HOSTFN1_LPU1_MBOX_INFO_MK 0xfffffffe
-#define __HOSTFN1_LPU1_MBOX_INFO_SH 1
-#define __HOSTFN1_LPU1_MBOX_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN1_CMD_STAT 0x0001901c
-#define __LPU1_HOSTFN1_MBOX_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN1_MBOX_INFO_SH 1
-#define __LPU1_HOSTFN1_MBOX_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX_CMD_STATUS 0x00000001
-#define CPE_Q0_DEPTH 0x00010014
-#define CPE_Q0_PI 0x0001001c
-#define CPE_Q0_CI 0x00010020
-#define CPE_Q1_DEPTH 0x00010034
-#define CPE_Q1_PI 0x0001003c
-#define CPE_Q1_CI 0x00010040
-#define CPE_Q2_DEPTH 0x00010054
-#define CPE_Q2_PI 0x0001005c
-#define CPE_Q2_CI 0x00010060
-#define CPE_Q3_DEPTH 0x00010074
-#define CPE_Q3_PI 0x0001007c
-#define CPE_Q3_CI 0x00010080
-#define CPE_Q4_DEPTH 0x00010094
-#define CPE_Q4_PI 0x0001009c
-#define CPE_Q4_CI 0x000100a0
-#define CPE_Q5_DEPTH 0x000100b4
-#define CPE_Q5_PI 0x000100bc
-#define CPE_Q5_CI 0x000100c0
-#define CPE_Q6_DEPTH 0x000100d4
-#define CPE_Q6_PI 0x000100dc
-#define CPE_Q6_CI 0x000100e0
-#define CPE_Q7_DEPTH 0x000100f4
-#define CPE_Q7_PI 0x000100fc
-#define CPE_Q7_CI 0x00010100
-#define RME_Q0_DEPTH 0x00011014
-#define RME_Q0_PI 0x0001101c
-#define RME_Q0_CI 0x00011020
-#define RME_Q1_DEPTH 0x00011034
-#define RME_Q1_PI 0x0001103c
-#define RME_Q1_CI 0x00011040
-#define RME_Q2_DEPTH 0x00011054
-#define RME_Q2_PI 0x0001105c
-#define RME_Q2_CI 0x00011060
-#define RME_Q3_DEPTH 0x00011074
-#define RME_Q3_PI 0x0001107c
-#define RME_Q3_CI 0x00011080
-#define RME_Q4_DEPTH 0x00011094
-#define RME_Q4_PI 0x0001109c
-#define RME_Q4_CI 0x000110a0
-#define RME_Q5_DEPTH 0x000110b4
-#define RME_Q5_PI 0x000110bc
-#define RME_Q5_CI 0x000110c0
-#define RME_Q6_DEPTH 0x000110d4
-#define RME_Q6_PI 0x000110dc
-#define RME_Q6_CI 0x000110e0
-#define RME_Q7_DEPTH 0x000110f4
-#define RME_Q7_PI 0x000110fc
-#define RME_Q7_CI 0x00011100
-#define PSS_CTL_REG 0x00018800
-#define __PSS_I2C_CLK_DIV_MK 0x00030000
-#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_LMEM1_CORR_ERR 0x00000800
-#define __PSS_LMEM0_CORR_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 0x00000fff
-
-
-/*
- * 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.
- */
-#define HOSTFN0_LPU_MBOX0_0 0x00019200
-#define HOSTFN1_LPU_MBOX0_8 0x00019260
-#define LPU_HOSTFN0_MBOX0_0 0x00019280
-#define LPU_HOSTFN1_MBOX0_8 0x000192e0
-
-
-/*
- * 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_Q_DEPTH(__n) \
- (CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH))
-#define CPE_Q_PI(__n) \
- (CPE_Q0_PI + (__n) * (CPE_Q1_PI - CPE_Q0_PI))
-#define CPE_Q_CI(__n) \
- (CPE_Q0_CI + (__n) * (CPE_Q1_CI - CPE_Q0_CI))
-#define RME_Q_DEPTH(__n) \
- (RME_Q0_DEPTH + (__n) * (RME_Q1_DEPTH - RME_Q0_DEPTH))
-#define RME_Q_PI(__n) \
- (RME_Q0_PI + (__n) * (RME_Q1_PI - RME_Q0_PI))
-#define RME_Q_CI(__n) \
- (RME_Q0_CI + (__n) * (RME_Q1_CI - RME_Q0_CI))
-
-#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_CPE_Q4 = 4,
- BFA_MSIX_CPE_Q5 = 5,
- BFA_MSIX_CPE_Q6 = 6,
- BFA_MSIX_CPE_Q7 = 7,
- BFA_MSIX_RME_Q0 = 8,
- BFA_MSIX_RME_Q1 = 9,
- BFA_MSIX_RME_Q2 = 10,
- BFA_MSIX_RME_Q3 = 11,
- BFA_MSIX_RME_Q4 = 12,
- BFA_MSIX_RME_Q5 = 13,
- BFA_MSIX_RME_Q6 = 14,
- BFA_MSIX_RME_Q7 = 15,
- BFA_MSIX_ERR_EMC = 16,
- BFA_MSIX_ERR_LPU0 = 17,
- BFA_MSIX_ERR_LPU1 = 18,
- BFA_MSIX_ERR_PSS = 19,
- BFA_MSIX_MBOX_LPU0 = 20,
- BFA_MSIX_MBOX_LPU1 = 21,
- BFA_MSIX_CB_MAX = 22,
-};
-
-/*
- * 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_CPE_MASK 0x000000ffU
-#define __HFN_INT_RME_MASK 0x0000ff00U
-
-
-/*
- * crossbow memory map.
- */
-#define PSS_SMEM_PAGE_START 0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff)
-
-/*
- * End of crossbow memory map
- */
-
-
-#endif /* __BFI_CBREG_H__ */
-
diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h
deleted file mode 100644
index fc4ce4a5a183..000000000000
--- a/drivers/scsi/bfa/bfi_ctreg.h
+++ /dev/null
@@ -1,636 +0,0 @@
-
-/*
- * 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/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index 19e888a57555..0d9f1fb50db0 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -28,11 +28,17 @@ enum bfi_iocfc_h2i_msgs {
BFI_IOCFC_H2I_CFG_REQ = 1,
BFI_IOCFC_H2I_SET_INTR_REQ = 2,
BFI_IOCFC_H2I_UPDATEQ_REQ = 3,
+ BFI_IOCFC_H2I_FAA_ENABLE_REQ = 4,
+ BFI_IOCFC_H2I_FAA_DISABLE_REQ = 5,
+ BFI_IOCFC_H2I_FAA_QUERY_REQ = 6,
};
enum bfi_iocfc_i2h_msgs {
BFI_IOCFC_I2H_CFG_REPLY = BFA_I2HM(1),
BFI_IOCFC_I2H_UPDATEQ_RSP = BFA_I2HM(3),
+ BFI_IOCFC_I2H_FAA_ENABLE_RSP = BFA_I2HM(4),
+ BFI_IOCFC_I2H_FAA_DISABLE_RSP = BFA_I2HM(5),
+ BFI_IOCFC_I2H_FAA_QUERY_RSP = BFA_I2HM(6),
};
struct bfi_iocfc_cfg_s {
@@ -40,6 +46,12 @@ struct bfi_iocfc_cfg_s {
u8 sense_buf_len; /* SCSI sense length */
u16 rsvd_1;
u32 endian_sig; /* endian signature of host */
+ u8 rsvd_2;
+ u8 single_msix_vec;
+ u8 rsvd[2];
+ __be16 num_ioim_reqs;
+ __be16 num_fwtio_reqs;
+
/*
* Request and response circular queue base addresses, size and
@@ -54,7 +66,8 @@ struct bfi_iocfc_cfg_s {
union bfi_addr_u stats_addr; /* DMA-able address for stats */
union bfi_addr_u cfgrsp_addr; /* config response dma address */
- union bfi_addr_u ioim_snsbase; /* IO sense buffer base address */
+ union bfi_addr_u ioim_snsbase[BFI_IOIM_SNSBUF_SEGS];
+ /* IO sense buf base addr segments */
struct bfa_iocfc_intr_attr_s intr_attr; /* IOC interrupt attributes */
};
@@ -68,11 +81,25 @@ struct bfi_iocfc_bootwwns {
u8 rsvd[7];
};
+/**
+ * Queue configuration response from firmware
+ */
+struct bfi_iocfc_qreg_s {
+ u32 cpe_q_ci_off[BFI_IOC_MAX_CQS];
+ u32 cpe_q_pi_off[BFI_IOC_MAX_CQS];
+ u32 cpe_qctl_off[BFI_IOC_MAX_CQS];
+ u32 rme_q_ci_off[BFI_IOC_MAX_CQS];
+ u32 rme_q_pi_off[BFI_IOC_MAX_CQS];
+ u32 rme_qctl_off[BFI_IOC_MAX_CQS];
+ u8 hw_qid[BFI_IOC_MAX_CQS];
+};
+
struct bfi_iocfc_cfgrsp_s {
struct bfa_iocfc_fwcfg_s fwcfg;
struct bfa_iocfc_intr_attr_s intr_attr;
struct bfi_iocfc_bootwwns bootwwns;
struct bfi_pbc_s pbc_cfg;
+ struct bfi_iocfc_qreg_s qreg;
};
/*
@@ -150,6 +177,37 @@ union bfi_iocfc_i2h_msg_u {
u32 mboxmsg[BFI_IOC_MSGSZ];
};
+/*
+ * BFI_IOCFC_H2I_FAA_ENABLE_REQ BFI_IOCFC_H2I_FAA_DISABLE_REQ message
+ */
+struct bfi_faa_en_dis_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+};
+
+/*
+ * BFI_IOCFC_H2I_FAA_QUERY_REQ message
+ */
+struct bfi_faa_query_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 faa_status; /* FAA status */
+ u8 addr_source; /* PWWN source */
+ u8 rsvd[2];
+ wwn_t faa; /* Fabric acquired PWWN */
+};
+
+/*
+ * BFI_IOCFC_I2H_FAA_ENABLE_RSP, BFI_IOCFC_I2H_FAA_DISABLE_RSP message
+ */
+struct bfi_faa_en_dis_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 status; /* updateq status */
+ u8 rsvd[3];
+};
+
+/*
+ * BFI_IOCFC_I2H_FAA_QUERY_RSP message
+ */
+#define bfi_faa_query_rsp_t struct bfi_faa_query_s
enum bfi_fcport_h2i {
BFI_FCPORT_H2I_ENABLE_REQ = (1),
@@ -213,7 +271,8 @@ struct bfi_fcport_enable_req_s {
struct bfi_fcport_set_svc_params_req_s {
struct bfi_mhdr_s mh; /* msg header */
__be16 tx_bbcredit; /* Tx credits */
- u16 rsvd;
+ u8 bb_scn; /* BB_SC FC credit recovery */
+ u8 rsvd;
};
/*
@@ -293,12 +352,12 @@ struct bfi_fcxp_send_req_s {
u8 class; /* FC class used for req/rsp */
u8 rsp_timeout; /* timeout in secs, 0-no response */
u8 cts; /* continue sequence */
- u8 lp_tag; /* lport tag */
+ u8 lp_fwtag; /* lport tag */
struct fchs_s fchs; /* request FC header structure */
__be32 req_len; /* request payload length */
__be32 rsp_maxlen; /* max response length expected */
- struct bfi_sge_s req_sge[BFA_FCXP_MAX_SGES]; /* request buf */
- struct bfi_sge_s rsp_sge[BFA_FCXP_MAX_SGES]; /* response buf */
+ struct bfi_alen_s req_alen; /* request buffer */
+ struct bfi_alen_s rsp_alen; /* response buffer */
};
/*
@@ -328,7 +387,7 @@ struct bfi_uf_buf_post_s {
struct bfi_mhdr_s mh; /* Common msg header */
u16 buf_tag; /* buffer tag */
__be16 buf_len; /* total buffer length */
- struct bfi_sge_s sge[BFA_UF_MAX_SGES]; /* buffer DMA SGEs */
+ struct bfi_alen_s alen; /* buffer address/len pair */
};
struct bfi_uf_frm_rcvd_s {
@@ -346,26 +405,27 @@ enum bfi_lps_h2i_msgs {
};
enum bfi_lps_i2h_msgs {
- BFI_LPS_H2I_LOGIN_RSP = BFA_I2HM(1),
- BFI_LPS_H2I_LOGOUT_RSP = BFA_I2HM(2),
- BFI_LPS_H2I_CVL_EVENT = BFA_I2HM(3),
+ BFI_LPS_I2H_LOGIN_RSP = BFA_I2HM(1),
+ BFI_LPS_I2H_LOGOUT_RSP = BFA_I2HM(2),
+ BFI_LPS_I2H_CVL_EVENT = BFA_I2HM(3),
};
struct bfi_lps_login_req_s {
struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
+ u8 bfa_tag;
u8 alpa;
__be16 pdu_size;
wwn_t pwwn;
wwn_t nwwn;
u8 fdisc;
u8 auth_en;
- u8 rsvd[2];
+ u8 lps_role;
+ u8 bb_scn;
};
struct bfi_lps_login_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
+ u8 fw_tag;
u8 status;
u8 lsrjt_rsn;
u8 lsrjt_expl;
@@ -380,31 +440,33 @@ struct bfi_lps_login_rsp_s {
mac_t fcf_mac;
u8 ext_status;
u8 brcd_switch; /* attached peer is brcd switch */
+ u8 bb_scn; /* atatched port's bb_scn */
+ u8 bfa_tag;
};
struct bfi_lps_logout_req_s {
struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
+ u8 fw_tag;
u8 rsvd[3];
wwn_t port_name;
};
struct bfi_lps_logout_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
+ u8 bfa_tag;
u8 status;
u8 rsvd[2];
};
struct bfi_lps_cvl_event_s {
struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
+ u8 bfa_tag;
u8 rsvd[3];
};
struct bfi_lps_n2n_pid_req_s {
struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
+ u8 fw_tag;
u32 lp_pid:24;
};
@@ -439,7 +501,7 @@ struct bfi_rport_create_req_s {
u16 bfa_handle; /* host rport handle */
__be16 max_frmsz; /* max rcv pdu size */
u32 pid:24, /* remote port ID */
- lp_tag:8; /* local port tag */
+ lp_fwtag:8; /* local port tag */
u32 local_pid:24, /* local port ID */
cisc:8;
u8 fc_class; /* supported FC classes */
@@ -502,62 +564,63 @@ union bfi_rport_i2h_msg_u {
* Initiator mode I-T nexus interface defines.
*/
-enum bfi_itnim_h2i {
- BFI_ITNIM_H2I_CREATE_REQ = 1, /* i-t nexus creation */
- BFI_ITNIM_H2I_DELETE_REQ = 2, /* i-t nexus deletion */
+enum bfi_itn_h2i {
+ BFI_ITN_H2I_CREATE_REQ = 1, /* i-t nexus creation */
+ BFI_ITN_H2I_DELETE_REQ = 2, /* i-t nexus deletion */
};
-enum bfi_itnim_i2h {
- BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
- BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
- BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
+enum bfi_itn_i2h {
+ BFI_ITN_I2H_CREATE_RSP = BFA_I2HM(1),
+ BFI_ITN_I2H_DELETE_RSP = BFA_I2HM(2),
+ BFI_ITN_I2H_SLER_EVENT = BFA_I2HM(3),
};
-struct bfi_itnim_create_req_s {
+struct bfi_itn_create_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 fw_handle; /* f/w handle for itnim */
u8 class; /* FC class for IO */
u8 seq_rec; /* sequence recovery support */
u8 msg_no; /* seq id of the msg */
+ u8 role;
};
-struct bfi_itnim_create_rsp_s {
+struct bfi_itn_create_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 bfa_handle; /* bfa handle for itnim */
u8 status; /* fcp request status */
u8 seq_id; /* seq id of the msg */
};
-struct bfi_itnim_delete_req_s {
+struct bfi_itn_delete_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 fw_handle; /* f/w itnim handle */
u8 seq_id; /* seq id of the msg */
u8 rsvd;
};
-struct bfi_itnim_delete_rsp_s {
+struct bfi_itn_delete_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 bfa_handle; /* bfa handle for itnim */
u8 status; /* fcp request status */
u8 seq_id; /* seq id of the msg */
};
-struct bfi_itnim_sler_event_s {
+struct bfi_itn_sler_event_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 bfa_handle; /* bfa handle for itnim */
u16 rsvd;
};
-union bfi_itnim_h2i_msg_u {
- struct bfi_itnim_create_req_s *create_req;
- struct bfi_itnim_delete_req_s *delete_req;
+union bfi_itn_h2i_msg_u {
+ struct bfi_itn_create_req_s *create_req;
+ struct bfi_itn_delete_req_s *delete_req;
struct bfi_msg_s *msg;
};
-union bfi_itnim_i2h_msg_u {
- struct bfi_itnim_create_rsp_s *create_rsp;
- struct bfi_itnim_delete_rsp_s *delete_rsp;
- struct bfi_itnim_sler_event_s *sler_event;
+union bfi_itn_i2h_msg_u {
+ struct bfi_itn_create_rsp_s *create_rsp;
+ struct bfi_itn_delete_rsp_s *delete_rsp;
+ struct bfi_itn_sler_event_s *sler_event;
struct bfi_msg_s *msg;
};
@@ -693,7 +756,6 @@ enum bfi_ioim_status {
BFI_IOIM_STS_PATHTOV = 8,
};
-#define BFI_IOIM_SNSLEN (256)
/*
* I/O response message
*/
@@ -772,4 +834,27 @@ struct bfi_tskim_rsp_s {
#pragma pack()
+/*
+ * Crossbow PCI MSI-X vector defines
+ */
+enum {
+ BFI_MSIX_CPE_QMIN_CB = 0,
+ BFI_MSIX_CPE_QMAX_CB = 7,
+ BFI_MSIX_RME_QMIN_CB = 8,
+ BFI_MSIX_RME_QMAX_CB = 15,
+ BFI_MSIX_CB_MAX = 22,
+};
+
+/*
+ * Catapult FC PCI MSI-X vector defines
+ */
+enum {
+ BFI_MSIX_LPU_ERR_CT = 0,
+ BFI_MSIX_CPE_QMIN_CT = 1,
+ BFI_MSIX_CPE_QMAX_CT = 4,
+ BFI_MSIX_RME_QMIN_CT = 5,
+ BFI_MSIX_RME_QMAX_CT = 8,
+ BFI_MSIX_CT_MAX = 9,
+};
+
#endif /* __BFI_MS_H__ */
diff --git a/drivers/scsi/bfa/bfi_reg.h b/drivers/scsi/bfa/bfi_reg.h
new file mode 100644
index 000000000000..d892064b64a8
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_reg.h
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus 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.
+ */
+
+/*
+ * 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 /* ct */
+#define __APP_ETH_CLK_LOWSPEED 0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED 0x00000002
+#define __GLOBAL_FCOE_MODE 0x00000001
+#define FW_INIT_HALT_P0 0x000191ac /* ct */
+#define __FW_INIT_HALT_P 0x00000001
+#define FW_INIT_HALT_P1 0x000191bc /* ct */
+#define PMM_1T_RESET_REG_P0 0x0002381c /* ct */
+#define __PMM_1T_RESET_P 0x00000001
+#define PMM_1T_RESET_REG_P1 0x00023c1c /* ct */
+
+/**
+ * Catapult-2 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)
+
+/*
+ * Catapult-2 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 __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 catapult-2
+ */
+#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/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index 97a61b4d81b7..e1f1e3448f98 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -19,6 +19,23 @@ struct b577xx_doorbell_hdr {
/*
* doorbell message sent to the chip
*/
+struct b577xx_doorbell {
+#if defined(__BIG_ENDIAN)
+ u16 zero_fill2;
+ u8 zero_fill1;
+ struct b577xx_doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct b577xx_doorbell_hdr header;
+ u8 zero_fill1;
+ u16 zero_fill2;
+#endif
+};
+
+
+
+/*
+ * doorbell message sent to the chip
+ */
struct b577xx_doorbell_set_prod {
#if defined(__BIG_ENDIAN)
u16 prod;
@@ -39,106 +56,63 @@ struct regpair {
/*
- * Fixed size structure in order to plant it in Union structure
+ * ABTS info $$KEEP_ENDIANNESS$$
*/
-struct fcoe_abts_rsp_union {
- u32 r_ctl;
- u32 abts_rsp_payload[7];
+struct fcoe_abts_info {
+ __le16 aborted_task_id;
+ __le16 reserved0;
+ __le32 reserved1;
};
/*
- * 4 regs size
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
*/
-struct fcoe_bd_ctx {
- u32 buf_addr_hi;
- u32 buf_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 rsrv0;
- u16 buf_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 buf_len;
- u16 rsrv0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 rsrv1;
- u16 flags;
-#elif defined(__LITTLE_ENDIAN)
- u16 flags;
- u16 rsrv1;
-#endif
+struct fcoe_abts_rsp_union {
+ u8 r_ctl;
+ u8 rsrv[3];
+ __le32 abts_rsp_payload[7];
};
-struct fcoe_cleanup_flow_info {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u16 task_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 task_id;
- u16 reserved1;
-#endif
- u32 reserved2[7];
+/*
+ * 4 regs size $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_bd_ctx {
+ __le32 buf_addr_hi;
+ __le32 buf_addr_lo;
+ __le16 buf_len;
+ __le16 rsrv0;
+ __le16 flags;
+ __le16 rsrv1;
};
-struct fcoe_fcp_cmd_payload {
- u32 opaque[8];
-};
-
-struct fcoe_fc_hdr {
-#if defined(__BIG_ENDIAN)
- u8 cs_ctl;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 cs_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 r_ctl;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 r_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 seq_id;
- u8 df_ctl;
- u16 seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 seq_cnt;
- u8 df_ctl;
- u8 seq_id;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 type;
- u8 f_ctl[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 f_ctl[3];
- u8 type;
-#endif
- u32 parameters;
-#if defined(__BIG_ENDIAN)
- u16 ox_id;
- u16 rx_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_id;
- u16 ox_id;
-#endif
+/*
+ * FCoE cached sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cached_sge_ctx {
+ struct regpair cur_buf_addr;
+ __le16 cur_buf_rem;
+ __le16 second_buf_rem;
+ struct regpair second_buf_addr;
};
-struct fcoe_fc_frame {
- struct fcoe_fc_hdr fc_hdr;
- u32 reserved0[2];
-};
-union fcoe_cmd_flow_info {
- struct fcoe_fcp_cmd_payload fcp_cmd_payload;
- struct fcoe_fc_frame mp_fc_frame;
+/*
+ * Cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cleanup_info {
+ __le16 cleaned_task_id;
+ __le16 rolled_tx_seq_cnt;
+ __le32 rolled_tx_data_offset;
};
-
+/*
+ * Fcp RSP flags $$KEEP_ENDIANNESS$$
+ */
struct fcoe_fcp_rsp_flags {
u8 flags;
#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
@@ -155,95 +129,168 @@ struct fcoe_fcp_rsp_flags {
#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
};
-
+/*
+ * Fcp RSP payload $$KEEP_ENDIANNESS$$
+ */
struct fcoe_fcp_rsp_payload {
struct regpair reserved0;
- u32 fcp_resid;
-#if defined(__BIG_ENDIAN)
- u16 retry_delay_timer;
- struct fcoe_fcp_rsp_flags fcp_flags;
- u8 scsi_status_code;
-#elif defined(__LITTLE_ENDIAN)
+ __le32 fcp_resid;
u8 scsi_status_code;
struct fcoe_fcp_rsp_flags fcp_flags;
- u16 retry_delay_timer;
-#endif
- u32 fcp_rsp_len;
- u32 fcp_sns_len;
+ __le16 retry_delay_timer;
+ __le32 fcp_rsp_len;
+ __le32 fcp_sns_len;
};
-
/*
* Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
*/
struct fcoe_fcp_rsp_union {
struct fcoe_fcp_rsp_payload payload;
struct regpair reserved0;
};
+/*
+ * FC header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_hdr {
+ u8 s_id[3];
+ u8 cs_ctl;
+ u8 d_id[3];
+ u8 r_ctl;
+ __le16 seq_cnt;
+ u8 df_ctl;
+ u8 seq_id;
+ u8 f_ctl[3];
+ u8 type;
+ __le32 parameters;
+ __le16 rx_id;
+ __le16 ox_id;
+};
-struct fcoe_fcp_xfr_rdy_payload {
- u32 burst_len;
- u32 data_ro;
+/*
+ * FC header union $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mp_rsp_union {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 mp_payload_len;
+ __le32 rsrv;
};
-struct fcoe_read_flow_info {
- struct fcoe_fc_hdr fc_data_in_hdr;
- u32 reserved[2];
+/*
+ * Completion information $$KEEP_ENDIANNESS$$
+ */
+union fcoe_comp_flow_info {
+ struct fcoe_fcp_rsp_union fcp_rsp;
+ struct fcoe_abts_rsp_union abts_rsp;
+ struct fcoe_mp_rsp_union mp_rsp;
+ __le32 opaque[8];
};
-struct fcoe_write_flow_info {
- struct fcoe_fc_hdr fc_data_out_hdr;
- struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
+
+/*
+ * External ABTS info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_abts_info {
+ __le32 rsrv0[6];
+ struct fcoe_abts_info ctx;
};
-union fcoe_rsp_flow_info {
- struct fcoe_fcp_rsp_union fcp_rsp;
- struct fcoe_abts_rsp_union abts_rsp;
+
+/*
+ * External cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_cleanup_info {
+ __le32 rsrv0[6];
+ struct fcoe_cleanup_info ctx;
};
+
/*
- * 32 bytes used for general purposes
+ * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
*/
-union fcoe_general_task_ctx {
- union fcoe_cmd_flow_info cmd_info;
- struct fcoe_read_flow_info read_info;
- struct fcoe_write_flow_info write_info;
- union fcoe_rsp_flow_info rsp_info;
- struct fcoe_cleanup_flow_info cleanup_info;
- u32 comp_info[8];
+struct fcoe_fw_tx_seq_ctx {
+ __le32 data_offset;
+ __le16 seq_cnt;
+ __le16 rsrv0;
+};
+
+/*
+ * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_fw_tx_seq_ctx {
+ __le32 rsrv0[6];
+ struct fcoe_fw_tx_seq_ctx ctx;
+};
+
+
+/*
+ * FCoE multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mul_sges_ctx {
+ struct regpair cur_sge_addr;
+ __le16 cur_sge_off;
+ u8 cur_sge_idx;
+ u8 sgl_size;
+};
+
+/*
+ * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_mul_sges_ctx {
+ struct fcoe_mul_sges_ctx mul_sgl;
+ struct regpair rsrv0;
};
/*
- * FCoE KCQ CQE parameters
+ * FCP CMD payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_cmd_payload {
+ __le32 opaque[8];
+};
+
+
+
+
+
+/*
+ * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_xfr_rdy_payload {
+ __le32 burst_len;
+ __le32 data_ro;
+};
+
+
+/*
+ * FC frame $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_frame {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 reserved0[2];
+};
+
+
+
+
+/*
+ * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
*/
union fcoe_kcqe_params {
- u32 reserved0[4];
+ __le32 reserved0[4];
};
/*
- * FCoE KCQ CQE
+ * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_kcqe {
- u32 fcoe_conn_id;
- u32 completion_status;
- u32 fcoe_conn_context_id;
+ __le32 fcoe_conn_id;
+ __le32 completion_status;
+ __le32 fcoe_conn_context_id;
union fcoe_kcqe_params params;
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
- u8 op_code;
- u16 qe_self_seq;
-#elif defined(__LITTLE_ENDIAN)
- u16 qe_self_seq;
+ __le16 qe_self_seq;
u8 op_code;
u8 flags;
#define FCOE_KCQE_RESERVED0 (0x7<<0)
@@ -254,23 +301,14 @@ struct fcoe_kcqe {
#define FCOE_KCQE_LAYER_CODE_SHIFT 4
#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
-#endif
};
+
+
/*
- * FCoE KWQE header
+ * FCoE KWQE header $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_header {
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
- u8 op_code;
-#elif defined(__LITTLE_ENDIAN)
u8 op_code;
u8 flags;
#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
@@ -279,50 +317,23 @@ struct fcoe_kwqe_header {
#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-#endif
};
/*
- * FCoE firmware init request 1
+ * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init1 {
-#if defined(__BIG_ENDIAN)
+ __le16 num_tasks;
struct fcoe_kwqe_header hdr;
- u16 num_tasks;
-#elif defined(__LITTLE_ENDIAN)
- u16 num_tasks;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 task_list_pbl_addr_lo;
- u32 task_list_pbl_addr_hi;
- u32 dummy_buffer_addr_lo;
- u32 dummy_buffer_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rq_num_wqes;
- u16 sq_num_wqes;
-#elif defined(__LITTLE_ENDIAN)
- u16 sq_num_wqes;
- u16 rq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 cq_num_wqes;
- u16 rq_buffer_log_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_buffer_log_size;
- u16 cq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
- u8 num_sessions_log;
- u16 mtu;
-#elif defined(__LITTLE_ENDIAN)
- u16 mtu;
+ __le32 task_list_pbl_addr_lo;
+ __le32 task_list_pbl_addr_hi;
+ __le32 dummy_buffer_addr_lo;
+ __le32 dummy_buffer_addr_hi;
+ __le16 sq_num_wqes;
+ __le16 rq_num_wqes;
+ __le16 rq_buffer_log_size;
+ __le16 cq_num_wqes;
+ __le16 mtu;
u8 num_sessions_log;
u8 flags;
#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
@@ -331,113 +342,73 @@ struct fcoe_kwqe_init1 {
#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
-#endif
};
/*
- * FCoE firmware init request 2
+ * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init2 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ u8 hsi_major_version;
+ u8 hsi_minor_version;
struct fcoe_kwqe_header hdr;
-#endif
- u32 hash_tbl_pbl_addr_lo;
- u32 hash_tbl_pbl_addr_hi;
- u32 t2_hash_tbl_addr_lo;
- u32 t2_hash_tbl_addr_hi;
- u32 t2_ptr_hash_tbl_addr_lo;
- u32 t2_ptr_hash_tbl_addr_hi;
- u32 free_list_count;
+ __le32 hash_tbl_pbl_addr_lo;
+ __le32 hash_tbl_pbl_addr_hi;
+ __le32 t2_hash_tbl_addr_lo;
+ __le32 t2_hash_tbl_addr_hi;
+ __le32 t2_ptr_hash_tbl_addr_lo;
+ __le32 t2_ptr_hash_tbl_addr_hi;
+ __le32 free_list_count;
};
/*
- * FCoE firmware init request 3
+ * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init3 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u32 error_bit_map_lo;
- u32 error_bit_map_hi;
-#if defined(__BIG_ENDIAN)
- u8 reserved21[3];
- u8 cached_session_enable;
-#elif defined(__LITTLE_ENDIAN)
- u8 cached_session_enable;
+ __le32 error_bit_map_lo;
+ __le32 error_bit_map_hi;
+ u8 perf_config;
u8 reserved21[3];
-#endif
- u32 reserved2[4];
+ __le32 reserved2[4];
};
/*
- * FCoE connection offload request 1
+ * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload1 {
-#if defined(__BIG_ENDIAN)
+ __le16 fcoe_conn_id;
struct fcoe_kwqe_header hdr;
- u16 fcoe_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 fcoe_conn_id;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 sq_addr_lo;
- u32 sq_addr_hi;
- u32 rq_pbl_addr_lo;
- u32 rq_pbl_addr_hi;
- u32 rq_first_pbe_addr_lo;
- u32 rq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 rq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_prod;
- u16 reserved0;
-#endif
+ __le32 sq_addr_lo;
+ __le32 sq_addr_hi;
+ __le32 rq_pbl_addr_lo;
+ __le32 rq_pbl_addr_hi;
+ __le32 rq_first_pbe_addr_lo;
+ __le32 rq_first_pbe_addr_hi;
+ __le16 rq_prod;
+ __le16 reserved0;
};
/*
- * FCoE connection offload request 2
+ * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload2 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 tx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_max_fc_pay_len;
+ __le16 tx_max_fc_pay_len;
struct fcoe_kwqe_header hdr;
-#endif
- u32 cq_addr_lo;
- u32 cq_addr_hi;
- u32 xferq_addr_lo;
- u32 xferq_addr_hi;
- u32 conn_db_addr_lo;
- u32 conn_db_addr_hi;
- u32 reserved1;
+ __le32 cq_addr_lo;
+ __le32 cq_addr_hi;
+ __le32 xferq_addr_lo;
+ __le32 xferq_addr_hi;
+ __le32 conn_db_addr_lo;
+ __le32 conn_db_addr_hi;
+ __le32 reserved1;
};
/*
- * FCoE connection offload request 3
+ * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload3 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
- u16 vlan_tag;
+ __le16 vlan_tag;
#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
@@ -445,34 +416,8 @@ struct fcoe_kwqe_conn_offload3 {
#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
struct fcoe_kwqe_header hdr;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 tx_max_conc_seqs_c3;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 s_id[3];
u8 tx_max_conc_seqs_c3;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 d_id[3];
u8 flags;
#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
@@ -491,79 +436,44 @@ struct fcoe_kwqe_conn_offload3 {
#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-#endif
- u32 reserved;
- u32 confq_first_pbe_addr_lo;
- u32 confq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rx_max_fc_pay_len;
- u16 tx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_total_conc_seqs;
- u16 rx_max_fc_pay_len;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 rx_open_seqs_exch_c3;
- u8 rx_max_conc_seqs_c3;
- u16 rx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_total_conc_seqs;
+ __le32 reserved;
+ __le32 confq_first_pbe_addr_lo;
+ __le32 confq_first_pbe_addr_hi;
+ __le16 tx_total_conc_seqs;
+ __le16 rx_max_fc_pay_len;
+ __le16 rx_total_conc_seqs;
u8 rx_max_conc_seqs_c3;
u8 rx_open_seqs_exch_c3;
-#endif
};
/*
- * FCoE connection offload request 4
+ * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload4 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u8 reserved2;
- u8 e_d_tov_timer_val;
-#elif defined(__LITTLE_ENDIAN)
u8 e_d_tov_timer_val;
u8 reserved2;
struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u8 dst_mac_addr_hi16[2];
-#endif
- u8 dst_mac_addr_lo32[4];
- u32 lcq_addr_lo;
- u32 lcq_addr_hi;
- u32 confq_pbl_base_addr_lo;
- u32 confq_pbl_base_addr_hi;
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
+ u8 dst_mac_addr_hi[2];
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ __le32 lcq_addr_lo;
+ __le32 lcq_addr_hi;
+ __le32 confq_pbl_base_addr_lo;
+ __le32 confq_pbl_base_addr_hi;
};
/*
- * FCoE connection enable request
+ * FCoE connection enable request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_enable_disable {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
u16 vlan_tag;
#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
@@ -571,82 +481,52 @@ struct fcoe_kwqe_conn_enable_disable {
#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-#endif
- u8 dst_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 dst_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u16 reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 vlan_flag;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ u8 dst_mac_addr_hi[2];
+ __le16 reserved1;
u8 s_id[3];
u8 vlan_flag;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 reserved3;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 d_id[3];
u8 reserved3;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved4;
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved4;
};
/*
- * FCoE connection destroy request
+ * FCoE connection destroy request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved1[5];
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved1[5];
};
/*
- * FCoe destroy request
+ * FCoe destroy request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
-#endif
- u32 reserved1[7];
+ __le32 reserved1[7];
};
/*
- * FCoe statistics request
+ * FCoe statistics request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_stat {
-#if defined(__BIG_ENDIAN)
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 stat_params_addr_lo;
- u32 stat_params_addr_hi;
- u32 reserved1[5];
+ __le32 stat_params_addr_lo;
+ __le32 stat_params_addr_hi;
+ __le32 reserved1[5];
};
/*
- * FCoE KWQ WQE
+ * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
*/
union fcoe_kwqe {
struct fcoe_kwqe_init1 init1;
@@ -662,19 +542,42 @@ union fcoe_kwqe {
struct fcoe_kwqe_stat statistics;
};
-struct fcoe_mul_sges_ctx {
- struct regpair cur_sge_addr;
-#if defined(__BIG_ENDIAN)
- u8 sgl_size;
- u8 cur_sge_idx;
- u16 cur_sge_off;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_sge_off;
- u8 cur_sge_idx;
- u8 sgl_size;
-#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * TX SGL context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_sgl_union_ctx {
+ struct fcoe_cached_sge_ctx cached_sge;
+ struct fcoe_ext_mul_sges_ctx sgl;
+ __le32 opaque[5];
};
+/*
+ * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_read_flow_info {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0[3];
+};
+
+
+/*
+ * Fcoe stat context $$KEEP_ENDIANNESS$$
+ */
struct fcoe_s_stat_ctx {
u8 flags;
#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
@@ -693,51 +596,34 @@ struct fcoe_s_stat_ctx {
#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
};
-struct fcoe_seq_ctx {
-#if defined(__BIG_ENDIAN)
- u16 low_seq_cnt;
- struct fcoe_s_stat_ctx s_stat;
- u8 seq_id;
-#elif defined(__LITTLE_ENDIAN)
+/*
+ * Fcoe rx seq context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_seq_ctx {
u8 seq_id;
struct fcoe_s_stat_ctx s_stat;
- u16 low_seq_cnt;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 err_seq_cnt;
- u16 high_seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 high_seq_cnt;
- u16 err_seq_cnt;
-#endif
- u32 low_exp_ro;
- u32 high_exp_ro;
+ __le16 seq_cnt;
+ __le32 low_exp_ro;
+ __le32 high_exp_ro;
};
-struct fcoe_single_sge_ctx {
- struct regpair cur_buf_addr;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 cur_buf_rem;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_buf_rem;
- u16 reserved0;
-#endif
-};
-
-union fcoe_sgl_ctx {
- struct fcoe_single_sge_ctx single_sge;
- struct fcoe_mul_sges_ctx mul_sges;
+/*
+ * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_rx_wr_union_ctx {
+ struct fcoe_read_flow_info read_info;
+ union fcoe_comp_flow_info comp_info;
+ __le32 opaque[8];
};
/*
- * FCoE SQ element
+ * FCoE SQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_sqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_SQE_TASK_ID (0x7FFF<<0)
#define FCOE_SQE_TASK_ID_SHIFT 0
#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
@@ -746,135 +632,141 @@ struct fcoe_sqe {
-struct fcoe_task_ctx_entry_tx_only {
- union fcoe_sgl_ctx sgl_ctx;
+/*
+ * 14 regs $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_only {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0;
};
-struct fcoe_task_ctx_entry_txwr_rxrd {
-#if defined(__BIG_ENDIAN)
- u16 verify_tx_seq;
+/*
+ * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
+ */
+union fcoe_tx_wr_rx_rd_union_ctx {
+ struct fcoe_fc_frame tx_frame;
+ struct fcoe_fcp_cmd_payload fcp_cmd;
+ struct fcoe_ext_cleanup_info cleanup;
+ struct fcoe_ext_abts_info abts;
+ struct fcoe_ext_fw_tx_seq_ctx tx_seq;
+ __le32 opaque[8];
+};
+
+/*
+ * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd_const {
u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
-#elif defined(__LITTLE_ENDIAN)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u16 verify_tx_seq;
-#endif
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+ __le16 rsrv3;
+ __le32 verify_tx_seq;
};
/*
- * Common section. Both TX and RX processing might write and read from it in
- * different flows
+ * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
*/
-struct fcoe_task_ctx_entry_tx_rx_cmn {
- u32 data_2_trns;
- union fcoe_general_task_ctx general;
-#if defined(__BIG_ENDIAN)
- u16 tx_low_seq_cnt;
- struct fcoe_s_stat_ctx tx_s_stat;
- u8 tx_seq_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 tx_seq_id;
- struct fcoe_s_stat_ctx tx_s_stat;
- u16 tx_low_seq_cnt;
-#endif
- u32 common_flags;
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
-};
-
-struct fcoe_task_ctx_entry_rxwr_txrd {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
- u16 rx_id;
-#endif
+struct fcoe_tce_tx_wr_rx_rd {
+ union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
+ struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
};
-struct fcoe_task_ctx_entry_rx_only {
- struct fcoe_seq_ctx seq_ctx;
- struct fcoe_seq_ctx ooo_seq_ctx;
- u32 rsrv3;
- union fcoe_sgl_ctx sgl_ctx;
+/*
+ * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_const {
+ __le32 data_2_trns;
+ __le32 init_flags;
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
+};
+
+/*
+ * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_var {
+ __le16 rx_flags;
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
+ __le16 rx_id;
+ struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
+};
+
+/*
+ * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd {
+ struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
+ struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
+};
+
+/*
+ * tce_rx_only $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_only {
+ struct fcoe_rx_seq_ctx rx_seq_ctx;
+ union fcoe_rx_wr_union_ctx union_ctx;
};
+/*
+ * task_ctx_entry $$KEEP_ENDIANNESS$$
+ */
struct fcoe_task_ctx_entry {
- struct fcoe_task_ctx_entry_tx_only tx_wr_only;
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
- struct fcoe_task_ctx_entry_rx_only rx_wr_only;
- u32 reserved[4];
+ struct fcoe_tce_tx_only txwr_only;
+ struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+ struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+ struct fcoe_tce_rx_only rxwr_only;
};
+
+
+
+
+
+
+
+
/*
- * FCoE XFRQ element
+ * FCoE XFRQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_xfrqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
#define FCOE_XFRQE_TASK_ID_SHIFT 0
#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
@@ -883,22 +775,31 @@ struct fcoe_xfrqe {
/*
- * FCoE CONFQ element
+ * fcoe rx doorbell message sent to the chip $$KEEP_ENDIANNESS$$
+ */
+struct b577xx_fcoe_rx_doorbell {
+ struct b577xx_doorbell_hdr hdr;
+ u8 params;
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM (0x1F<<0)
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT 0
+#define B577XX_FCOE_RX_DOORBELL_OPCODE (0x7<<5)
+#define B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT 5
+ __le16 doorbell_cq_cons;
+};
+
+
+/*
+ * FCoE CONFQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_confqe {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 ox_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 ox_id;
- u16 rx_id;
-#endif
- u32 param;
+ __le16 ox_id;
+ __le16 rx_id;
+ __le32 param;
};
/*
- * FCoE connection data base
+ * FCoE conection data base
*/
struct fcoe_conn_db {
#if defined(__BIG_ENDIAN)
@@ -914,10 +815,10 @@ struct fcoe_conn_db {
/*
- * FCoE CQ element
+ * FCoE CQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_CQE_CQE_INFO (0x3FFF<<0)
#define FCOE_CQE_CQE_INFO_SHIFT 0
#define FCOE_CQE_CQE_TYPE (0x1<<14)
@@ -928,61 +829,46 @@ struct fcoe_cqe {
/*
- * FCoE error/warning resporting entry
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_partial_err_report_entry {
+ __le32 err_warn_bitmap_lo;
+ __le32 err_warn_bitmap_hi;
+ __le32 tx_buf_off;
+ __le32 rx_buf_off;
+};
+
+/*
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
*/
struct fcoe_err_report_entry {
- u32 err_warn_bitmap_lo;
- u32 err_warn_bitmap_hi;
- u32 tx_buf_off;
- u32 rx_buf_off;
+ struct fcoe_partial_err_report_entry data;
struct fcoe_fc_hdr fc_hdr;
};
/*
- * FCoE hash table entry (32 bytes)
+ * FCoE hash table entry (32 bytes) $$KEEP_ENDIANNESS$$
*/
struct fcoe_hash_table_entry {
-#if defined(__BIG_ENDIAN)
- u8 d_id_0;
- u8 s_id_2;
- u8 s_id_1;
- u8 s_id_0;
-#elif defined(__LITTLE_ENDIAN)
u8 s_id_0;
u8 s_id_1;
u8 s_id_2;
u8 d_id_0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 dst_mac_addr_hi;
- u8 d_id_2;
- u8 d_id_1;
-#elif defined(__LITTLE_ENDIAN)
u8 d_id_1;
u8 d_id_2;
- u16 dst_mac_addr_hi;
-#endif
- u32 dst_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 vlan_id;
- u16 src_mac_addr_hi;
-#elif defined(__LITTLE_ENDIAN)
- u16 src_mac_addr_hi;
- u16 vlan_id;
-#endif
- u32 src_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 reserved0;
- u8 vlan_flag;
-#elif defined(__LITTLE_ENDIAN)
+ __le16 dst_mac_addr_hi;
+ __le16 dst_mac_addr_mid;
+ __le16 dst_mac_addr_lo;
+ __le16 src_mac_addr_hi;
+ __le16 vlan_id;
+ __le16 src_mac_addr_lo;
+ __le16 src_mac_addr_mid;
u8 vlan_flag;
u8 reserved0;
- u16 reserved1;
-#endif
- u32 reserved2;
- u32 field_id;
+ __le16 reserved1;
+ __le32 reserved2;
+ __le32 field_id;
#define FCOE_HASH_TABLE_ENTRY_CID (0xFFFFFF<<0)
#define FCOE_HASH_TABLE_ENTRY_CID_SHIFT 0
#define FCOE_HASH_TABLE_ENTRY_RESERVED3 (0x7F<<24)
@@ -991,11 +877,27 @@ struct fcoe_hash_table_entry {
#define FCOE_HASH_TABLE_ENTRY_VALID_SHIFT 31
};
+
/*
- * FCoE pending work request CQE
+ * FCoE LCQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_lcqe {
+ __le32 wqe;
+#define FCOE_LCQE_TASK_ID (0xFFFF<<0)
+#define FCOE_LCQE_TASK_ID_SHIFT 0
+#define FCOE_LCQE_LCQE_TYPE (0xFF<<16)
+#define FCOE_LCQE_LCQE_TYPE_SHIFT 16
+#define FCOE_LCQE_RESERVED (0xFF<<24)
+#define FCOE_LCQE_RESERVED_SHIFT 24
+};
+
+
+
+/*
+ * FCoE pending work request CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_pend_wq_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_PEND_WQ_CQE_TASK_ID (0x3FFF<<0)
#define FCOE_PEND_WQ_CQE_TASK_ID_SHIFT 0
#define FCOE_PEND_WQ_CQE_CQE_TYPE (0x1<<14)
@@ -1006,53 +908,61 @@ struct fcoe_pend_wq_cqe {
/*
- * FCoE RX statistics parameters section#0
+ * FCoE RX statistics parameters section#0 $$KEEP_ENDIANNESS$$
*/
struct fcoe_rx_stat_params_section0 {
- u32 fcoe_ver_cnt;
- u32 fcoe_rx_pkt_cnt;
- u32 fcoe_rx_byte_cnt;
- u32 fcoe_rx_drop_pkt_cnt;
+ __le32 fcoe_rx_pkt_cnt;
+ __le32 fcoe_rx_byte_cnt;
};
/*
- * FCoE RX statistics parameters section#1
+ * FCoE RX statistics parameters section#1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_rx_stat_params_section1 {
- u32 fc_crc_cnt;
- u32 eofa_del_cnt;
- u32 miss_frame_cnt;
- u32 seq_timeout_cnt;
- u32 drop_seq_cnt;
- u32 fcoe_rx_drop_pkt_cnt;
- u32 fcp_rx_pkt_cnt;
- u32 reserved0;
+ __le32 fcoe_ver_cnt;
+ __le32 fcoe_rx_drop_pkt_cnt;
+};
+
+
+/*
+ * FCoE RX statistics parameters section#2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_stat_params_section2 {
+ __le32 fc_crc_cnt;
+ __le32 eofa_del_cnt;
+ __le32 miss_frame_cnt;
+ __le32 seq_timeout_cnt;
+ __le32 drop_seq_cnt;
+ __le32 fcoe_rx_drop_pkt_cnt;
+ __le32 fcp_rx_pkt_cnt;
+ __le32 reserved0;
};
/*
- * FCoE TX statistics parameters
+ * FCoE TX statistics parameters $$KEEP_ENDIANNESS$$
*/
struct fcoe_tx_stat_params {
- u32 fcoe_tx_pkt_cnt;
- u32 fcoe_tx_byte_cnt;
- u32 fcp_tx_pkt_cnt;
- u32 reserved0;
+ __le32 fcoe_tx_pkt_cnt;
+ __le32 fcoe_tx_byte_cnt;
+ __le32 fcp_tx_pkt_cnt;
+ __le32 reserved0;
};
/*
- * FCoE statistics parameters
+ * FCoE statistics parameters $$KEEP_ENDIANNESS$$
*/
struct fcoe_statistics_params {
struct fcoe_tx_stat_params tx_stat;
struct fcoe_rx_stat_params_section0 rx_stat0;
struct fcoe_rx_stat_params_section1 rx_stat1;
+ struct fcoe_rx_stat_params_section2 rx_stat2;
};
/*
- * FCoE t2 hash table entry (64 bytes)
+ * FCoE t2 hash table entry (64 bytes) $$KEEP_ENDIANNESS$$
*/
struct fcoe_t2_hash_table_entry {
struct fcoe_hash_table_entry data;
@@ -1060,11 +970,13 @@ struct fcoe_t2_hash_table_entry {
struct regpair reserved0[3];
};
+
+
/*
- * FCoE unsolicited CQE
+ * FCoE unsolicited CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_unsolicited_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_UNSOLICITED_CQE_SUBTYPE (0x3<<0)
#define FCOE_UNSOLICITED_CQE_SUBTYPE_SHIFT 0
#define FCOE_UNSOLICITED_CQE_PKT_LEN (0xFFF<<2)
@@ -1075,6 +987,4 @@ struct fcoe_unsolicited_cqe {
#define FCOE_UNSOLICITED_CQE_TOGGLE_BIT_SHIFT 15
};
-
-
#endif /* __57XX_FCOE_HSI_LINUX_LE__ */
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 0a404bfb44fe..d924236e1b91 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -62,7 +62,7 @@
#include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc"
-#define BNX2FC_VERSION "1.0.1"
+#define BNX2FC_VERSION "1.0.3"
#define PFX "bnx2fc: "
@@ -152,7 +152,6 @@ struct bnx2fc_percpu_s {
spinlock_t fp_work_lock;
};
-
struct bnx2fc_hba {
struct list_head link;
struct cnic_dev *cnic;
@@ -179,6 +178,7 @@ struct bnx2fc_hba {
#define BNX2FC_CTLR_INIT_DONE 1
#define BNX2FC_CREATE_DONE 2
struct fcoe_ctlr ctlr;
+ struct list_head vports;
u8 vlan_enabled;
int vlan_id;
u32 next_conn_id;
@@ -232,6 +232,11 @@ struct bnx2fc_hba {
#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_hba, ctlr)
+struct bnx2fc_lport {
+ struct list_head list;
+ struct fc_lport *lport;
+};
+
struct bnx2fc_cmd_mgr {
struct bnx2fc_hba *hba;
u16 next_idx;
@@ -262,9 +267,14 @@ struct bnx2fc_rport {
#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x8
#define BNX2FC_FLAG_EXPL_LOGO 0x9
+ u8 src_addr[ETH_ALEN];
u32 max_sqes;
u32 max_rqes;
u32 max_cqes;
+ atomic_t free_sqes;
+
+ struct b577xx_doorbell_set_prod sq_db;
+ struct b577xx_fcoe_rx_doorbell rx_db;
struct fcoe_sqe *sq;
dma_addr_t sq_dma;
@@ -274,7 +284,7 @@ struct bnx2fc_rport {
struct fcoe_cqe *cq;
dma_addr_t cq_dma;
- u32 cq_cons_idx;
+ u16 cq_cons_idx;
u8 cq_curr_toggle_bit;
u32 cq_mem_size;
@@ -423,6 +433,7 @@ struct bnx2fc_work {
struct bnx2fc_unsol_els {
struct fc_lport *lport;
struct fc_frame *fp;
+ struct bnx2fc_hba *hba;
struct work_struct unsol_els_work;
};
@@ -505,6 +516,7 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
struct fc_frame *,
void *),
void *arg, u32 timeout);
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt);
int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
index fe7769173c43..399cda047a77 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_constants.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -5,6 +5,12 @@
* This file defines HSI constants for the FCoE flows
*/
+/* Current FCoE HSI version number composed of two fields (16 bit) */
+/* Implies on a change broken previous HSI */
+#define FCOE_HSI_MAJOR_VERSION (1)
+/* Implies on a change which does not broken previous HSI */
+#define FCOE_HSI_MINOR_VERSION (1)
+
/* KWQ/KCQ FCoE layer code */
#define FCOE_KWQE_LAYER_CODE (7)
@@ -40,21 +46,62 @@
#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE (0x3)
#define FCOE_KCQE_COMPLETION_STATUS_CTX_FREE_FAILURE (0x4)
#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR (0x5)
+#define FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION (0x6)
+
+/* CQE type */
+#define FCOE_PENDING_CQE_TYPE 0
+#define FCOE_UNSOLIC_CQE_TYPE 1
/* Unsolicited CQE type */
#define FCOE_UNSOLICITED_FRAME_CQE_TYPE 0
#define FCOE_ERROR_DETECTION_CQE_TYPE 1
#define FCOE_WARNING_DETECTION_CQE_TYPE 2
+/* E_D_TOV timer resolution in ms */
+#define FCOE_E_D_TOV_TIMER_RESOLUTION_MS (20)
+
+/* E_D_TOV timer resolution for SDM (4 micro) */
+#define FCOE_E_D_TOV_SDM_TIMER_RESOLUTION \
+ (FCOE_E_D_TOV_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* REC timer resolution in ms */
+#define FCOE_REC_TIMER_RESOLUTION_MS (20)
+
+/* REC timer resolution for SDM (4 micro) */
+#define FCOE_REC_SDM_TIMER_RESOLUTION (FCOE_REC_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* E_D_TOV timer default wraparound value (2 sec) in 20 ms resolution */
+#define FCOE_E_D_TOV_DEFAULT_WRAPAROUND_VAL \
+ (2000 / FCOE_E_D_TOV_TIMER_RESOLUTION_MS)
+
+/* REC_TOV timer default wraparound value (3 sec) in 20 ms resolution */
+#define FCOE_REC_TOV_DEFAULT_WRAPAROUND_VAL \
+ (3000 / FCOE_REC_TIMER_RESOLUTION_MS)
+
+#define FCOE_NUM_OF_TIMER_TASKS (8 * 1024)
+
+#define FCOE_NUM_OF_CACHED_TASKS_TIMER (8)
+
/* Task context constants */
+/******** Remove FCP_CMD write tce sleep ***********************/
+/* In case timer services are required then shall be updated by Xstorm after
+ * start processing the task. In case no timer facilities are required then the
+ * driver would initialize the state to this value
+ *
+#define FCOE_TASK_TX_STATE_NORMAL 0
+ * After driver has initialize the task in case timer services required *
+#define FCOE_TASK_TX_STATE_INIT 1
+******** Remove FCP_CMD write tce sleep ***********************/
/* After driver has initialize the task in case timer services required */
#define FCOE_TASK_TX_STATE_INIT 0
/* In case timer services are required then shall be updated by Xstorm after
* start processing the task. In case no timer facilities are required then the
- * driver would initialize the state to this value */
+ * driver would initialize the state to this value
+ */
#define FCOE_TASK_TX_STATE_NORMAL 1
/* Task is under abort procedure. Updated in order to stop processing of
- * pending WQEs on this task */
+ * pending WQEs on this task
+ */
#define FCOE_TASK_TX_STATE_ABORT 2
/* For E_D_T_TOV timer expiration in Xstorm (Class 2 only) */
#define FCOE_TASK_TX_STATE_ERROR 3
@@ -66,17 +113,8 @@
#define FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP 6
/* For sequence cleanup request task */
#define FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP 7
-/* Mark task as aborted and indicate that ABTS was not transmitted */
-#define FCOE_TASK_TX_STATE_BEFORE_ABTS_TX 8
-/* Mark task as aborted and indicate that ABTS was transmitted */
-#define FCOE_TASK_TX_STATE_AFTER_ABTS_TX 9
/* For completion the ABTS task. */
-#define FCOE_TASK_TX_STATE_ABTS_TX_COMPLETED 10
-/* Mark task as aborted and indicate that Exchange cleanup was not transmitted
- */
-#define FCOE_TASK_TX_STATE_BEFORE_EXCHANGE_CLEANUP_TX 11
-/* Mark task as aborted and indicate that Exchange cleanup was transmitted */
-#define FCOE_TASK_TX_STATE_AFTER_EXCHANGE_CLEANUP_TX 12
+#define FCOE_TASK_TX_STATE_ABTS_TX 8
#define FCOE_TASK_RX_STATE_NORMAL 0
#define FCOE_TASK_RX_STATE_COMPLETED 1
@@ -86,25 +124,25 @@
#define FCOE_TASK_RX_STATE_WARNING 3
/* For E_D_T_TOV timer expiration in Ustorm */
#define FCOE_TASK_RX_STATE_ERROR 4
-/* ABTS ACC arrived wait for local completion to finally complete the task. */
-#define FCOE_TASK_RX_STATE_ABTS_ACC_ARRIVED 5
-/* local completion arrived wait for ABTS ACC to finally complete the task. */
-#define FCOE_TASK_RX_STATE_ABTS_LOCAL_COMP_ARRIVED 6
+/* FW only: First visit at rx-path, part of the abts round trip */
+#define FCOE_TASK_RX_STATE_ABTS_IN_PROCESS 5
+/* FW only: Second visit at rx-path, after ABTS frame transmitted */
+#define FCOE_TASK_RX_STATE_ABTS_TRANSMITTED 6
/* Special completion indication in case of task was aborted. */
#define FCOE_TASK_RX_STATE_ABTS_COMPLETED 7
-/* Special completion indication in case of task was cleaned. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED 8
-/* Special completion indication (in task requested the exchange cleanup) in
- * case cleaned task is in non-valid. */
-#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED 9
+/* FW only: First visit at rx-path, part of the cleanup round trip */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_IN_PROCESS 8
+/* FW only: Special completion indication in case of task was cleaned. */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED 9
+/* Not in used: Special completion indication (in task requested the exchange
+ * cleanup) in case cleaned task is in non-valid.
+ */
+#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED 10
/* Special completion indication (in task requested the sequence cleanup) in
- * case cleaned task was already returned to normal. */
-#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP 10
-/* Exchange cleanup arrived wait until xfer will be handled to finally
- * complete the task. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_ARRIVED 11
-/* Xfer handled, wait for exchange cleanup to finally complete the task. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_HANDLED_XFER 12
+ * case cleaned task was already returned to normal.
+ */
+#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP 11
+
#define FCOE_TASK_TYPE_WRITE 0
#define FCOE_TASK_TYPE_READ 1
@@ -120,11 +158,40 @@
#define FCOE_TASK_CLASS_TYPE_3 0
#define FCOE_TASK_CLASS_TYPE_2 1
+/* FCoE/FC packet fields */
+#define FCOE_ETH_TYPE 0x8906
+
+/* FCoE maximum elements in hash table */
+#define FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW 8
+
+/* FCoE half of the elements in hash table */
+#define FCOE_HALF_ELEMENTS_IN_HASH_TABLE_ROW \
+ (FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW / 2)
+
+/* FcoE number of cached T2 entries */
+#define T_FCOE_NUMBER_OF_CACHED_T2_ENTRIES (4)
+
+/* FCoE maximum elements in hash table */
+#define FCOE_HASH_TBL_CHUNK_SIZE 16384
+
/* Everest FCoE connection type */
#define B577XX_FCOE_CONNECTION_TYPE 4
-/* Error codes for Error Reporting in fast path flows */
-/* XFER error codes */
+/* FCoE number of rows (in log). This number derives
+ * from the maximum connections supported which is 2048.
+ * TBA: Need a different constant for E2
+ */
+#define FCOE_MAX_NUM_SESSIONS_LOG 11
+
+#define FC_ABTS_REPLY_MAX_PAYLOAD_LEN 12
+
+/* Error codes for Error Reporting in slow path flows */
+#define FCOE_SLOW_PATH_ERROR_CODE_TOO_MANY_FUNCS 0
+#define FCOE_SLOW_PATH_ERROR_CODE_NO_LICENSE 1
+
+/* Error codes for Error Reporting in fast path flows
+ * XFER error codes
+ */
#define FCOE_ERROR_CODE_XFER_OOO_RO 0
#define FCOE_ERROR_CODE_XFER_RO_NOT_ALIGNED 1
#define FCOE_ERROR_CODE_XFER_NULL_BURST_LEN 2
@@ -155,17 +222,17 @@
#define FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET 23
#define FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET 24
#define FCOE_ERROR_CODE_DATA_EOFN_END_SEQ_SET 25
-#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET 26
-#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ 27
+#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET 26
+#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ 27
#define FCOE_ERROR_CODE_DATA_FCTL 28
/* Middle path error codes */
-#define FCOE_ERROR_CODE_MIDPATH_TYPE_NOT_ELS 29
+#define FCOE_ERROR_CODE_MIDPATH_INVALID_TYPE 29
#define FCOE_ERROR_CODE_MIDPATH_SOFI3_SEQ_ACTIVE_SET 30
#define FCOE_ERROR_CODE_MIDPATH_SOFN_SEQ_ACTIVE_RESET 31
#define FCOE_ERROR_CODE_MIDPATH_EOFN_END_SEQ_SET 32
#define FCOE_ERROR_CODE_MIDPATH_EOFT_END_SEQ_RESET 33
-#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_FCTL 34
+#define FCOE_ERROR_CODE_MIDPATH_REPLY_FCTL 34
#define FCOE_ERROR_CODE_MIDPATH_INVALID_REPLY 35
#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_RCTL 36
@@ -173,7 +240,7 @@
#define FCOE_ERROR_CODE_ABTS_REPLY_F_CTL 37
#define FCOE_ERROR_CODE_ABTS_REPLY_DDF_RCTL_FIELD 38
#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_BLS_RCTL 39
-#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL 40
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL 40
#define FCOE_ERROR_CODE_ABTS_REPLY_RCTL_GENERAL_MISMATCH 41
/* Common error codes */
@@ -185,7 +252,7 @@
#define FCOE_ERROR_CODE_COMMON_DATA_NO_MORE_SGES 47
#define FCOE_ERROR_CODE_COMMON_OPTIONAL_FC_HDR 48
#define FCOE_ERROR_CODE_COMMON_READ_TCE_OX_ID_TOO_BIG 49
-#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED 50
+#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED 50
/* Unsolicited Rx error codes */
#define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_ELS 51
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index 52c358427ce2..7e89143f15cf 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -83,7 +83,7 @@ int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
rrq.rrq_cmd = ELS_RRQ;
hton24(rrq.rrq_s_id, sid);
rrq.rrq_ox_id = htons(aborted_io_req->xid);
- rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
+ rrq.rrq_rx_id = htons(aborted_io_req->task->rxwr_txrd.var_ctx.rx_id);
retry_rrq:
rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
@@ -417,12 +417,13 @@ void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
hdr = (u64 *)fc_hdr;
temp_hdr = (u64 *)
- &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ &task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
hdr[2] = cpu_to_be64(temp_hdr[2]);
- mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+ mp_req->resp_len =
+ task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
/* Parse ELS response */
if ((els_req->cb_func) && (els_req->cb_arg)) {
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index ab255fbc7f36..a97aff3a0662 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -21,7 +21,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 "Mar 17, 2011"
+#define DRV_MODULE_RELDATE "Jun 10, 2011"
static char version[] __devinitdata =
@@ -612,7 +612,7 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
return bnx2fc_stats;
}
- bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat1.fc_crc_cnt;
+ bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat2.fc_crc_cnt;
bnx2fc_stats->tx_frames += fw_stats->tx_stat.fcoe_tx_pkt_cnt;
bnx2fc_stats->tx_words += (fw_stats->tx_stat.fcoe_tx_byte_cnt) / 4;
bnx2fc_stats->rx_frames += fw_stats->rx_stat0.fcoe_rx_pkt_cnt;
@@ -679,6 +679,9 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport)
case SPEED_1000:
lport->link_speed = FC_PORTSPEED_1GBIT;
break;
+ case SPEED_2500:
+ lport->link_speed = FC_PORTSPEED_2GBIT;
+ break;
case SPEED_10000:
lport->link_speed = FC_PORTSPEED_10GBIT;
break;
@@ -767,17 +770,23 @@ static void bnx2fc_destroy_timer(unsigned long data)
*
* @context: adapter structure pointer
* @event: event type
+ * @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
*/
-static void bnx2fc_indicate_netevent(void *context, unsigned long event)
+static void bnx2fc_indicate_netevent(void *context, unsigned long event,
+ u16 vlan_id)
{
struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
struct fc_lport *lport = hba->ctlr.lp;
struct fc_lport *vport;
u32 link_possible = 1;
+ /* Ignore vlans for now */
+ if (vlan_id != 0)
+ return;
+
if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
BNX2FC_MISC_DBG("driver not ready. event=%s %ld\n",
hba->netdev->name, event);
@@ -1225,6 +1234,7 @@ static int bnx2fc_interface_setup(struct bnx2fc_hba *hba,
hba->ctlr.get_src_addr = bnx2fc_get_src_mac;
set_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done);
+ INIT_LIST_HEAD(&hba->vports);
rc = bnx2fc_netdev_setup(hba);
if (rc)
goto setup_err;
@@ -1261,8 +1271,15 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
struct fcoe_port *port;
struct Scsi_Host *shost;
struct fc_vport *vport = dev_to_vport(parent);
+ struct bnx2fc_lport *blport;
int rc = 0;
+ blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL);
+ if (!blport) {
+ BNX2FC_HBA_DBG(hba->ctlr.lp, "Unable to alloc bnx2fc_lport\n");
+ return NULL;
+ }
+
/* Allocate Scsi_Host structure */
if (!npiv)
lport = libfc_host_alloc(&bnx2fc_shost_template, sizeof(*port));
@@ -1271,7 +1288,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
if (!lport) {
printk(KERN_ERR PFX "could not allocate scsi host structure\n");
- return NULL;
+ goto free_blport;
}
shost = lport->host;
port = lport_priv(lport);
@@ -1327,12 +1344,20 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
}
bnx2fc_interface_get(hba);
+
+ spin_lock_bh(&hba->hba_lock);
+ blport->lport = lport;
+ list_add_tail(&blport->list, &hba->vports);
+ spin_unlock_bh(&hba->hba_lock);
+
return lport;
shost_err:
scsi_remove_host(shost);
lp_config_err:
scsi_host_put(lport->host);
+free_blport:
+ kfree(blport);
return NULL;
}
@@ -1348,6 +1373,7 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
{
struct fcoe_port *port = lport_priv(lport);
struct bnx2fc_hba *hba = port->priv;
+ struct bnx2fc_lport *blport, *tmp;
BNX2FC_HBA_DBG(hba->ctlr.lp, "ENTERED bnx2fc_if_destroy\n");
/* Stop the transmit retry timer */
@@ -1372,6 +1398,15 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
/* 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);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index f756d5f85c7a..09bdd9b88d1a 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -100,6 +100,9 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
fcoe_init2.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+ fcoe_init2.hsi_major_version = FCOE_HSI_MAJOR_VERSION;
+ fcoe_init2.hsi_minor_version = FCOE_HSI_MINOR_VERSION;
+
fcoe_init2.hash_tbl_pbl_addr_lo = (u32) hba->hash_tbl_pbl_dma;
fcoe_init2.hash_tbl_pbl_addr_hi = (u32)
((u64) hba->hash_tbl_pbl_dma >> 32);
@@ -122,6 +125,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
fcoe_init3.error_bit_map_lo = 0xffffffff;
fcoe_init3.error_bit_map_hi = 0xffffffff;
+ fcoe_init3.perf_config = 1;
kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
@@ -289,19 +293,19 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
ofld_req4.e_d_tov_timer_val = lport->e_d_tov / 20;
- ofld_req4.src_mac_addr_lo32[0] = port->data_src_addr[5];
+ ofld_req4.src_mac_addr_lo[0] = port->data_src_addr[5];
/* local mac */
- ofld_req4.src_mac_addr_lo32[1] = port->data_src_addr[4];
- ofld_req4.src_mac_addr_lo32[2] = port->data_src_addr[3];
- ofld_req4.src_mac_addr_lo32[3] = port->data_src_addr[2];
- ofld_req4.src_mac_addr_hi16[0] = port->data_src_addr[1];
- ofld_req4.src_mac_addr_hi16[1] = port->data_src_addr[0];
- ofld_req4.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- ofld_req4.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- ofld_req4.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- ofld_req4.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- ofld_req4.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- ofld_req4.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ ofld_req4.src_mac_addr_lo[1] = port->data_src_addr[4];
+ ofld_req4.src_mac_addr_mid[0] = port->data_src_addr[3];
+ ofld_req4.src_mac_addr_mid[1] = port->data_src_addr[2];
+ ofld_req4.src_mac_addr_hi[0] = port->data_src_addr[1];
+ ofld_req4.src_mac_addr_hi[1] = port->data_src_addr[0];
+ ofld_req4.dst_mac_addr_lo[0] = hba->ctlr.dest_addr[5];/* fcf mac */
+ ofld_req4.dst_mac_addr_lo[1] = hba->ctlr.dest_addr[4];
+ ofld_req4.dst_mac_addr_mid[0] = hba->ctlr.dest_addr[3];
+ ofld_req4.dst_mac_addr_mid[1] = hba->ctlr.dest_addr[2];
+ ofld_req4.dst_mac_addr_hi[0] = hba->ctlr.dest_addr[1];
+ ofld_req4.dst_mac_addr_hi[1] = hba->ctlr.dest_addr[0];
ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma;
ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32);
@@ -345,20 +349,21 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
enbl_req.hdr.flags =
(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- enbl_req.src_mac_addr_lo32[0] = port->data_src_addr[5];
+ enbl_req.src_mac_addr_lo[0] = port->data_src_addr[5];
/* local mac */
- enbl_req.src_mac_addr_lo32[1] = port->data_src_addr[4];
- enbl_req.src_mac_addr_lo32[2] = port->data_src_addr[3];
- enbl_req.src_mac_addr_lo32[3] = port->data_src_addr[2];
- enbl_req.src_mac_addr_hi16[0] = port->data_src_addr[1];
- enbl_req.src_mac_addr_hi16[1] = port->data_src_addr[0];
-
- enbl_req.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- enbl_req.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- enbl_req.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- enbl_req.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- enbl_req.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- enbl_req.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ enbl_req.src_mac_addr_lo[1] = port->data_src_addr[4];
+ enbl_req.src_mac_addr_mid[0] = port->data_src_addr[3];
+ enbl_req.src_mac_addr_mid[1] = port->data_src_addr[2];
+ enbl_req.src_mac_addr_hi[0] = port->data_src_addr[1];
+ enbl_req.src_mac_addr_hi[1] = port->data_src_addr[0];
+ memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN);
+
+ enbl_req.dst_mac_addr_lo[0] = hba->ctlr.dest_addr[5];/* fcf mac */
+ enbl_req.dst_mac_addr_lo[1] = hba->ctlr.dest_addr[4];
+ enbl_req.dst_mac_addr_mid[0] = hba->ctlr.dest_addr[3];
+ enbl_req.dst_mac_addr_mid[1] = hba->ctlr.dest_addr[2];
+ enbl_req.dst_mac_addr_hi[0] = hba->ctlr.dest_addr[1];
+ enbl_req.dst_mac_addr_hi[1] = hba->ctlr.dest_addr[0];
port_id = fc_host_port_id(lport->host);
if (port_id != tgt->sid) {
@@ -411,18 +416,19 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port,
disable_req.hdr.flags =
(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- disable_req.src_mac_addr_lo32[0] = port->data_src_addr[5];
- disable_req.src_mac_addr_lo32[2] = port->data_src_addr[3];
- disable_req.src_mac_addr_lo32[3] = port->data_src_addr[2];
- disable_req.src_mac_addr_hi16[0] = port->data_src_addr[1];
- disable_req.src_mac_addr_hi16[1] = port->data_src_addr[0];
+ disable_req.src_mac_addr_lo[0] = tgt->src_addr[5];
+ disable_req.src_mac_addr_lo[1] = tgt->src_addr[4];
+ disable_req.src_mac_addr_mid[0] = tgt->src_addr[3];
+ disable_req.src_mac_addr_mid[1] = tgt->src_addr[2];
+ disable_req.src_mac_addr_hi[0] = tgt->src_addr[1];
+ disable_req.src_mac_addr_hi[1] = tgt->src_addr[0];
- disable_req.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- disable_req.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- disable_req.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- disable_req.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- disable_req.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- disable_req.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ disable_req.dst_mac_addr_lo[0] = hba->ctlr.dest_addr[5];/* fcf mac */
+ disable_req.dst_mac_addr_lo[1] = hba->ctlr.dest_addr[4];
+ disable_req.dst_mac_addr_mid[0] = hba->ctlr.dest_addr[3];
+ disable_req.dst_mac_addr_mid[1] = hba->ctlr.dest_addr[2];
+ disable_req.dst_mac_addr_hi[0] = hba->ctlr.dest_addr[1];
+ disable_req.dst_mac_addr_hi[1] = hba->ctlr.dest_addr[0];
port_id = tgt->sid;
disable_req.s_id[0] = (port_id & 0x000000FF);
@@ -480,16 +486,36 @@ int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
return rc;
}
+static bool is_valid_lport(struct bnx2fc_hba *hba, struct fc_lport *lport)
+{
+ struct bnx2fc_lport *blport;
+
+ spin_lock_bh(&hba->hba_lock);
+ list_for_each_entry(blport, &hba->vports, list) {
+ if (blport->lport == lport) {
+ spin_unlock_bh(&hba->hba_lock);
+ return true;
+ }
+ }
+ spin_unlock_bh(&hba->hba_lock);
+ return false;
+
+}
+
+
static void bnx2fc_unsol_els_work(struct work_struct *work)
{
struct bnx2fc_unsol_els *unsol_els;
struct fc_lport *lport;
+ struct bnx2fc_hba *hba;
struct fc_frame *fp;
unsol_els = container_of(work, struct bnx2fc_unsol_els, unsol_els_work);
lport = unsol_els->lport;
fp = unsol_els->fp;
- fc_exch_recv(lport, fp);
+ hba = unsol_els->hba;
+ if (is_valid_lport(hba, lport))
+ fc_exch_recv(lport, fp);
kfree(unsol_els);
}
@@ -499,6 +525,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
{
struct fcoe_port *port = tgt->port;
struct fc_lport *lport = port->lport;
+ struct bnx2fc_hba *hba = port->priv;
struct bnx2fc_unsol_els *unsol_els;
struct fc_frame_header *fh;
struct fc_frame *fp;
@@ -559,6 +586,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
fr_eof(fp) = FC_EOF_T;
fr_crc(fp) = cpu_to_le32(~crc);
unsol_els->lport = lport;
+ unsol_els->hba = hba;
unsol_els->fp = fp;
INIT_WORK(&unsol_els->unsol_els_work, bnx2fc_unsol_els_work);
queue_work(bnx2fc_wq, &unsol_els->unsol_els_work);
@@ -640,10 +668,10 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
xid = err_entry->fc_hdr.ox_id;
BNX2FC_TGT_DBG(tgt, "Unsol Error Frame OX_ID = 0x%x\n", xid);
BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x\n",
- err_entry->err_warn_bitmap_hi,
- err_entry->err_warn_bitmap_lo);
+ err_entry->data.err_warn_bitmap_hi,
+ err_entry->data.err_warn_bitmap_lo);
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
- err_entry->tx_buf_off, err_entry->rx_buf_off);
+ err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
bnx2fc_return_rqe(tgt, 1);
@@ -722,10 +750,10 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
xid = cpu_to_be16(err_entry->fc_hdr.ox_id);
BNX2FC_TGT_DBG(tgt, "Unsol Warning Frame OX_ID = 0x%x\n", xid);
BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x",
- err_entry->err_warn_bitmap_hi,
- err_entry->err_warn_bitmap_lo);
+ err_entry->data.err_warn_bitmap_hi,
+ err_entry->data.err_warn_bitmap_lo);
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
- err_entry->tx_buf_off, err_entry->rx_buf_off);
+ err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
bnx2fc_return_rqe(tgt, 1);
spin_unlock_bh(&tgt->tgt_lock);
@@ -762,9 +790,9 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
task = &(task_page[index]);
- num_rq = ((task->rx_wr_tx_rd.rx_flags &
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE) >>
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT);
+ num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
@@ -777,22 +805,19 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
/* Timestamp IO completion time */
cmd_type = io_req->cmd_type;
- /* optimized completion path */
- if (cmd_type == BNX2FC_SCSI_CMD) {
- rx_state = ((task->rx_wr_tx_rd.rx_flags &
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE) >>
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT);
+ rx_state = ((task->rxwr_txrd.var_ctx.rx_flags &
+ FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE) >>
+ FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT);
+ /* Process other IO completion types */
+ switch (cmd_type) {
+ case BNX2FC_SCSI_CMD:
if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
spin_unlock_bh(&tgt->tgt_lock);
return;
}
- }
- /* Process other IO completion types */
- switch (cmd_type) {
- case BNX2FC_SCSI_CMD:
if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
bnx2fc_process_abts_compl(io_req, task, num_rq);
else if (rx_state ==
@@ -819,8 +844,16 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
break;
case BNX2FC_ELS:
- BNX2FC_IO_DBG(io_req, "cq_compl - call process_els_compl\n");
- bnx2fc_process_els_compl(io_req, task, num_rq);
+ if (rx_state == FCOE_TASK_RX_STATE_COMPLETED)
+ bnx2fc_process_els_compl(io_req, task, num_rq);
+ else if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
+ bnx2fc_process_abts_compl(io_req, task, num_rq);
+ else if (rx_state ==
+ FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED)
+ bnx2fc_process_cleanup_compl(io_req, task, num_rq);
+ else
+ printk(KERN_ERR PFX "Invalid rx state = %d\n",
+ rx_state);
break;
case BNX2FC_CLEANUP:
@@ -835,6 +868,20 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
spin_unlock_bh(&tgt->tgt_lock);
}
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt)
+{
+ struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
+ u32 msg;
+
+ wmb();
+ rx_db->doorbell_cq_cons = tgt->cq_cons_idx | (tgt->cq_curr_toggle_bit <<
+ FCOE_CQE_TOGGLE_BIT_SHIFT);
+ msg = *((u32 *)rx_db);
+ writel(cpu_to_le32(msg), tgt->ctx_base);
+ mmiowb();
+
+}
+
struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
{
struct bnx2fc_work *work;
@@ -853,8 +900,8 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
struct fcoe_cqe *cq;
u32 cq_cons;
struct fcoe_cqe *cqe;
+ u32 num_free_sqes = 0;
u16 wqe;
- bool more_cqes_found = false;
/*
* cq_lock is a low contention lock used to protect
@@ -872,62 +919,51 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
cq_cons = tgt->cq_cons_idx;
cqe = &cq[cq_cons];
- do {
- more_cqes_found ^= true;
-
- while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
- (tgt->cq_curr_toggle_bit <<
- FCOE_CQE_TOGGLE_BIT_SHIFT)) {
+ while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
+ (tgt->cq_curr_toggle_bit <<
+ FCOE_CQE_TOGGLE_BIT_SHIFT)) {
- /* new entry on the cq */
- if (wqe & FCOE_CQE_CQE_TYPE) {
- /* Unsolicited event notification */
- bnx2fc_process_unsol_compl(tgt, wqe);
- } else {
- struct bnx2fc_work *work = NULL;
- struct bnx2fc_percpu_s *fps = NULL;
- unsigned int cpu = wqe % num_possible_cpus();
-
- fps = &per_cpu(bnx2fc_percpu, cpu);
- spin_lock_bh(&fps->fp_work_lock);
- if (unlikely(!fps->iothread))
- goto unlock;
-
- work = bnx2fc_alloc_work(tgt, wqe);
- if (work)
- list_add_tail(&work->list,
- &fps->work_list);
+ /* new entry on the cq */
+ if (wqe & FCOE_CQE_CQE_TYPE) {
+ /* Unsolicited event notification */
+ bnx2fc_process_unsol_compl(tgt, wqe);
+ } else {
+ /* Pending work request completion */
+ struct bnx2fc_work *work = NULL;
+ struct bnx2fc_percpu_s *fps = NULL;
+ unsigned int cpu = wqe % num_possible_cpus();
+
+ fps = &per_cpu(bnx2fc_percpu, cpu);
+ spin_lock_bh(&fps->fp_work_lock);
+ if (unlikely(!fps->iothread))
+ goto unlock;
+
+ work = bnx2fc_alloc_work(tgt, wqe);
+ if (work)
+ list_add_tail(&work->list,
+ &fps->work_list);
unlock:
- spin_unlock_bh(&fps->fp_work_lock);
+ spin_unlock_bh(&fps->fp_work_lock);
- /* Pending work request completion */
- if (fps->iothread && work)
- wake_up_process(fps->iothread);
- else
- bnx2fc_process_cq_compl(tgt, wqe);
- }
- cqe++;
- tgt->cq_cons_idx++;
-
- if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
- tgt->cq_cons_idx = 0;
- cqe = cq;
- tgt->cq_curr_toggle_bit =
- 1 - tgt->cq_curr_toggle_bit;
- }
+ /* Pending work request completion */
+ if (fps->iothread && work)
+ wake_up_process(fps->iothread);
+ else
+ bnx2fc_process_cq_compl(tgt, wqe);
}
- /* Re-arm CQ */
- if (more_cqes_found) {
- tgt->conn_db->cq_arm.lo = -1;
- wmb();
+ cqe++;
+ tgt->cq_cons_idx++;
+ num_free_sqes++;
+
+ if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
+ tgt->cq_cons_idx = 0;
+ cqe = cq;
+ tgt->cq_curr_toggle_bit =
+ 1 - tgt->cq_curr_toggle_bit;
}
- } while (more_cqes_found);
-
- /*
- * Commit tgt->cq_cons_idx change to the memory
- * spin_lock implies full memory barrier, no need to smp_wmb
- */
-
+ }
+ bnx2fc_arm_cq(tgt);
+ atomic_add(num_free_sqes, &tgt->free_sqes);
spin_unlock_bh(&tgt->cq_lock);
return 0;
}
@@ -1141,7 +1177,11 @@ static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code)
case FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR:
printk(KERN_ERR PFX "init_failure due to NIC error\n");
break;
-
+ case FCOE_KCQE_COMPLETION_STATUS_ERROR:
+ printk(KERN_ERR PFX "init failure due to compl status err\n");
+ break;
+ case FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION:
+ printk(KERN_ERR PFX "init failure due to HSI mismatch\n");
default:
printk(KERN_ERR PFX "Unknown Error code %d\n", err_code);
}
@@ -1247,21 +1287,14 @@ void bnx2fc_add_2_sq(struct bnx2fc_rport *tgt, u16 xid)
void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt)
{
- struct b577xx_doorbell_set_prod ev_doorbell;
+ struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
u32 msg;
wmb();
-
- memset(&ev_doorbell, 0, sizeof(struct b577xx_doorbell_set_prod));
- ev_doorbell.header.header = B577XX_DOORBELL_HDR_DB_TYPE;
-
- ev_doorbell.prod = tgt->sq_prod_idx |
+ sq_db->prod = tgt->sq_prod_idx |
(tgt->sq_curr_toggle_bit << 15);
- ev_doorbell.header.header |= B577XX_FCOE_CONNECTION_TYPE <<
- B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
- msg = *((u32 *)&ev_doorbell);
+ msg = *((u32 *)sq_db);
writel(cpu_to_le32(msg), tgt->ctx_base);
-
mmiowb();
}
@@ -1322,18 +1355,26 @@ void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
/* Tx Write Rx Read */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
- /* Common */
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.general.cleanup_info.task_id = orig_xid;
-
-
+ /* init flags */
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.union_ctx.cleanup.ctx.cleaned_task_id = orig_xid;
+
+ /* Tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags =
+ FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
+
+ /* Rx Read Tx Write */
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
}
void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
@@ -1342,6 +1383,7 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
struct bnx2fc_rport *tgt = io_req->tgt;
struct fc_frame_header *fc_hdr;
+ struct fcoe_ext_mul_sges_ctx *sgl;
u8 task_type = 0;
u64 *hdr;
u64 temp_hdr[3];
@@ -1367,47 +1409,49 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
/* Tx only */
if ((task_type == FCOE_TASK_TYPE_MIDPATH) ||
(task_type == FCOE_TASK_TYPE_UNSOLICITED)) {
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
(u32)mp_req->mp_req_bd_dma;
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
(u32)((u64)mp_req->mp_req_bd_dma >> 32);
- task->tx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
- BNX2FC_IO_DBG(io_req, "init_mp_task - bd_dma = 0x%llx\n",
- (unsigned long long)mp_req->mp_req_bd_dma);
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size = 1;
}
/* Tx Write Rx Read */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_INIT <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-
- /* Common */
- task->cmn.data_2_trns = io_req->data_xfer_len;
- context_id = tgt->context_id;
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+ /* init flags */
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+
+ /* tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_INIT <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
/* Rx Write Tx Read */
+ task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
+
+ /* rx flags */
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
+
+ context_id = tgt->context_id;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
fc_hdr = &(mp_req->req_fc_hdr);
if (task_type == FCOE_TASK_TYPE_MIDPATH) {
fc_hdr->fh_ox_id = cpu_to_be16(io_req->xid);
fc_hdr->fh_rx_id = htons(0xffff);
- task->rx_wr_tx_rd.rx_id = 0xffff;
+ task->rxwr_txrd.var_ctx.rx_id = 0xffff;
} else if (task_type == FCOE_TASK_TYPE_UNSOLICITED) {
fc_hdr->fh_rx_id = cpu_to_be16(io_req->xid);
}
/* Fill FC Header into middle path buffer */
- hdr = (u64 *) &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ hdr = (u64 *) &task->txwr_rxrd.union_ctx.tx_frame.fc_hdr;
memcpy(temp_hdr, fc_hdr, sizeof(temp_hdr));
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
@@ -1415,12 +1459,12 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
/* Rx Only */
if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
- (u32)mp_req->mp_resp_bd_dma;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)mp_req->mp_resp_bd_dma;
+ sgl->mul_sgl.cur_sge_addr.hi =
(u32)((u64)mp_req->mp_resp_bd_dma >> 32);
- task->rx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+ sgl->mul_sgl.sgl_size = 1;
}
}
@@ -1431,6 +1475,8 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
struct io_bdt *bd_tbl = io_req->bd_tbl;
struct bnx2fc_rport *tgt = io_req->tgt;
+ struct fcoe_cached_sge_ctx *cached_sge;
+ struct fcoe_ext_mul_sges_ctx *sgl;
u64 *fcp_cmnd;
u64 tmp_fcp_cmnd[4];
u32 context_id;
@@ -1449,47 +1495,33 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
/* Tx only */
if (task_type == FCOE_TASK_TYPE_WRITE) {
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
(u32)bd_tbl->bd_tbl_dma;
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
- task->tx_wr_only.sgl_ctx.mul_sges.sgl_size =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
bd_tbl->bd_valid;
}
/*Tx Write Rx Read */
/* Init state to NORMAL */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-
- /* Common */
- task->cmn.data_2_trns = io_req->data_xfer_len;
- context_id = tgt->context_id;
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
-
- /* Set initiative ownership */
- task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT;
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+ /* tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
/* Set initial seq counter */
- task->cmn.tx_low_seq_cnt = 1;
-
- /* Set state to "waiting for the first packet" */
- task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME;
+ task->txwr_rxrd.union_ctx.tx_seq.ctx.seq_cnt = 1;
/* Fill FCP_CMND IU */
fcp_cmnd = (u64 *)
- task->cmn.general.cmd_info.fcp_cmd_payload.opaque;
+ task->txwr_rxrd.union_ctx.fcp_cmd.opaque;
bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)&tmp_fcp_cmnd);
/* swap fcp_cmnd */
@@ -1501,32 +1533,54 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
}
/* Rx Write Tx Read */
- task->rx_wr_tx_rd.rx_id = 0xffff;
+ task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
+
+ context_id = tgt->context_id;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
+ /* rx flags */
+ /* Set state to "waiting for the first packet" */
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
+
+ task->rxwr_txrd.var_ctx.rx_id = 0xffff;
/* Rx Only */
+ cached_sge = &task->rxwr_only.union_ctx.read_info.sgl_ctx.cached_sge;
+ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
+ bd_count = bd_tbl->bd_valid;
if (task_type == FCOE_TASK_TYPE_READ) {
-
- bd_count = bd_tbl->bd_valid;
if (bd_count == 1) {
struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.lo =
- fcoe_bd_tbl->buf_addr_lo;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.hi =
- fcoe_bd_tbl->buf_addr_hi;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_rem =
- fcoe_bd_tbl->buf_len;
- task->tx_wr_rx_rd.init_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT;
+ cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+ task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
+ } else if (bd_count == 2) {
+ struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+ cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+
+ fcoe_bd_tbl++;
+ cached_sge->second_buf_addr.lo =
+ fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->second_buf_addr.hi =
+ fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->second_buf_rem = fcoe_bd_tbl->buf_len;
+ task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
} else {
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
- (u32)bd_tbl->bd_tbl_dma;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)bd_tbl->bd_tbl_dma;
+ sgl->mul_sgl.cur_sge_addr.hi =
(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
- task->rx_wr_only.sgl_ctx.mul_sges.sgl_size =
- bd_tbl->bd_valid;
+ sgl->mul_sgl.sgl_size = bd_count;
}
}
}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index b5b5c346d779..45eba6d609c9 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -425,6 +425,7 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
struct list_head *listp;
struct io_bdt *bd_tbl;
int index = RESERVE_FREE_LIST_INDEX;
+ u32 free_sqes;
u32 max_sqes;
u16 xid;
@@ -445,8 +446,10 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
* cmgr lock
*/
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+ free_sqes = atomic_read(&tgt->free_sqes);
if ((list_empty(&(cmd_mgr->free_list[index]))) ||
- (tgt->num_active_ios.counter >= max_sqes)) {
+ (tgt->num_active_ios.counter >= max_sqes) ||
+ (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
"ios(%d):sqes(%d)\n",
tgt->num_active_ios.counter, tgt->max_sqes);
@@ -463,6 +466,7 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
xid = io_req->xid;
cmd_mgr->cmds[xid] = io_req;
atomic_inc(&tgt->num_active_ios);
+ atomic_dec(&tgt->free_sqes);
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
INIT_LIST_HEAD(&io_req->link);
@@ -489,6 +493,7 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
struct bnx2fc_cmd *io_req;
struct list_head *listp;
struct io_bdt *bd_tbl;
+ u32 free_sqes;
u32 max_sqes;
u16 xid;
int index = get_cpu();
@@ -499,8 +504,10 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
* cmgr lock
*/
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+ free_sqes = atomic_read(&tgt->free_sqes);
if ((list_empty(&cmd_mgr->free_list[index])) ||
- (tgt->num_active_ios.counter >= max_sqes)) {
+ (tgt->num_active_ios.counter >= max_sqes) ||
+ (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
put_cpu();
return NULL;
@@ -513,6 +520,7 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
xid = io_req->xid;
cmd_mgr->cmds[xid] = io_req;
atomic_inc(&tgt->num_active_ios);
+ atomic_dec(&tgt->free_sqes);
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
put_cpu();
@@ -873,7 +881,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
/* Obtain oxid and rxid for the original exchange to be aborted */
fc_hdr->fh_ox_id = htons(io_req->xid);
- fc_hdr->fh_rx_id = htons(io_req->task->rx_wr_tx_rd.rx_id);
+ fc_hdr->fh_rx_id = htons(io_req->task->rxwr_txrd.var_ctx.rx_id);
sid = tgt->sid;
did = rport->port_id;
@@ -1189,7 +1197,7 @@ void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
kref_put(&io_req->refcount,
bnx2fc_cmd_release); /* drop timer hold */
- r_ctl = task->cmn.general.rsp_info.abts_rsp.r_ctl;
+ r_ctl = (u8)task->rxwr_only.union_ctx.comp_info.abts_rsp.r_ctl;
switch (r_ctl) {
case FC_RCTL_BA_ACC:
@@ -1344,12 +1352,13 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
fc_hdr = &(tm_req->resp_fc_hdr);
hdr = (u64 *)fc_hdr;
temp_hdr = (u64 *)
- &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ &task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
hdr[2] = cpu_to_be64(temp_hdr[2]);
- tm_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+ tm_req->resp_len =
+ task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
rsp_buf = tm_req->resp_buf;
@@ -1724,7 +1733,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
/* Fetch fcp_rsp from task context and perform cmd completion */
fcp_rsp = (struct fcoe_fcp_rsp_payload *)
- &(task->cmn.general.rsp_info.fcp_rsp.payload);
+ &(task->rxwr_only.union_ctx.comp_info.fcp_rsp.payload);
/* parse fcp_rsp and obtain sense data from RQ if available */
bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
@@ -1734,7 +1743,6 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
printk(KERN_ERR PFX "SCp.ptr is NULL\n");
return;
}
- io_req->sc_cmd = NULL;
if (io_req->on_active_queue) {
list_del_init(&io_req->link);
@@ -1754,6 +1762,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
}
bnx2fc_unmap_sg_list(io_req);
+ io_req->sc_cmd = NULL;
switch (io_req->fcp_status) {
case FC_GOOD:
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index a2e3830bd268..3e892bd66fbe 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -133,6 +133,8 @@ 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:
@@ -315,6 +317,8 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
struct fc_rport *rport = rdata->rport;
struct bnx2fc_hba *hba = port->priv;
+ struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
+ struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
tgt->rport = rport;
tgt->rdata = rdata;
@@ -335,6 +339,7 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
tgt->max_sqes = BNX2FC_SQ_WQES_MAX;
tgt->max_rqes = BNX2FC_RQ_WQES_MAX;
tgt->max_cqes = BNX2FC_CQ_WQES_MAX;
+ atomic_set(&tgt->free_sqes, BNX2FC_SQ_WQES_MAX);
/* Initialize the toggle bit */
tgt->sq_curr_toggle_bit = 1;
@@ -345,7 +350,17 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
tgt->rq_cons_idx = 0;
atomic_set(&tgt->num_active_ios, 0);
- tgt->work_time_slice = 2;
+ /* initialize sq doorbell */
+ sq_db->header.header = B577XX_DOORBELL_HDR_DB_TYPE;
+ sq_db->header.header |= B577XX_FCOE_CONNECTION_TYPE <<
+ B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
+ /* initialize rx doorbell */
+ rx_db->hdr.header = ((0x1 << B577XX_DOORBELL_HDR_RX_SHIFT) |
+ (0x1 << B577XX_DOORBELL_HDR_DB_TYPE_SHIFT) |
+ (B577XX_FCOE_CONNECTION_TYPE <<
+ B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT));
+ rx_db->params = (0x2 << B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT) |
+ (0x3 << B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT);
spin_lock_init(&tgt->tgt_lock);
spin_lock_init(&tgt->cq_lock);
@@ -758,8 +773,6 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
}
memset(tgt->lcq, 0, tgt->lcq_mem_size);
- /* Arm CQ */
- tgt->conn_db->cq_arm.lo = -1;
tgt->conn_db->rq_prod = 0x8000;
return 0;
@@ -787,6 +800,8 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
iounmap(tgt->ctx_base);
tgt->ctx_base = NULL;
}
+
+ spin_lock_bh(&tgt->cq_lock);
/* Free LCQ */
if (tgt->lcq) {
dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
@@ -828,17 +843,16 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
tgt->rq = NULL;
}
/* Free CQ */
- spin_lock_bh(&tgt->cq_lock);
if (tgt->cq) {
dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
tgt->cq, tgt->cq_dma);
tgt->cq = NULL;
}
- spin_unlock_bh(&tgt->cq_lock);
/* Free SQ */
if (tgt->sq) {
dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
tgt->sq, tgt->sq_dma);
tgt->sq = NULL;
}
+ spin_unlock_bh(&tgt->cq_lock);
}
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 30e6bdbd65af..57515f1f1690 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,6 +1,6 @@
/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 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
@@ -125,7 +125,7 @@
/* SQ/RQ/CQ DB structure sizes */
#define ISCSI_SQ_DB_SIZE (16)
-#define ISCSI_RQ_DB_SIZE (16)
+#define ISCSI_RQ_DB_SIZE (64)
#define ISCSI_CQ_DB_SIZE (80)
#define ISCSI_SQN_TO_NOTIFY_NOT_VALID 0xFFFF
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index dad6c8a34317..72118db89a20 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,6 +1,6 @@
/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 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
@@ -707,8 +707,10 @@ struct iscsi_kwqe_conn_update {
#define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
#elif defined(__LITTLE_ENDIAN)
u8 conn_flags;
#define ISCSI_KWQE_CONN_UPDATE_HEADER_DIGEST (0x1<<0)
@@ -719,8 +721,10 @@ struct iscsi_kwqe_conn_update {
#define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
u8 reserved2;
u8 max_outstanding_r2ts;
u8 session_error_recovery_level;
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 6bdd25a93db9..dc5700765db4 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,6 +1,6 @@
/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -22,11 +22,14 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/in.h>
#include <linux/kfifo.h>
#include <linux/netdevice.h>
#include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/cpu.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -202,10 +205,13 @@ struct io_bdt {
/**
* bnx2i_cmd - iscsi command structure
*
+ * @hdr: iSCSI header
+ * @conn: iscsi_conn pointer
* @scsi_cmd: SCSI-ML task pointer corresponding to this iscsi cmd
* @sg: SG list
* @io_tbl: buffer descriptor (BD) table
* @bd_tbl_dma: buffer descriptor (BD) table's dma address
+ * @req: bnx2i specific command request struct
*/
struct bnx2i_cmd {
struct iscsi_hdr hdr;
@@ -229,6 +235,7 @@ struct bnx2i_cmd {
* @gen_pdu: login/nopout/logout pdu resources
* @violation_notified: bit mask used to track iscsi error/warning messages
* already printed out
+ * @work_cnt: keeps track of the number of outstanding work
*
* iSCSI connection structure
*/
@@ -252,6 +259,8 @@ struct bnx2i_conn {
*/
struct generic_pdu_resc gen_pdu;
u64 violation_notified;
+
+ atomic_t work_cnt;
};
@@ -478,7 +487,7 @@ struct bnx2i_5771x_cq_db {
struct bnx2i_5771x_sq_rq_db {
u16 prod_idx;
- u8 reserved0[14]; /* Pad structure size to 16 bytes */
+ u8 reserved0[62]; /* Pad structure size to 64 bytes */
};
@@ -661,7 +670,6 @@ enum {
* @hba: adapter to which this connection belongs
* @conn: iscsi connection this EP is linked to
* @cls_ep: associated iSCSI endpoint pointer
- * @sess: iscsi session this EP is linked to
* @cm_sk: cnic sock struct
* @hba_age: age to detect if 'iscsid' issues ep_disconnect()
* after HBA reset is completed by bnx2i/cnic/bnx2
@@ -687,7 +695,7 @@ struct bnx2i_endpoint {
u32 hba_age;
u32 state;
unsigned long timestamp;
- int num_active_cmds;
+ atomic_t num_active_cmds;
u32 ec_shift;
struct qp_info qp;
@@ -700,6 +708,19 @@ struct bnx2i_endpoint {
};
+struct bnx2i_work {
+ struct list_head list;
+ struct iscsi_session *session;
+ struct bnx2i_conn *bnx2i_conn;
+ struct cqe cqe;
+};
+
+struct bnx2i_percpu_s {
+ struct task_struct *iothread;
+ struct list_head work_list;
+ spinlock_t p_work_lock;
+};
+
/* Global variables */
extern unsigned int error_mask1, error_mask2;
@@ -783,7 +804,7 @@ extern struct bnx2i_endpoint *bnx2i_find_ep_in_destroy_list(
struct bnx2i_hba *hba, u32 iscsi_cid);
extern int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep);
-extern void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);
+extern int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);
extern int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep);
@@ -793,4 +814,8 @@ extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn);
extern void bnx2i_print_xmit_pdu_queue(struct bnx2i_conn *conn);
extern void bnx2i_print_recv_state(struct bnx2i_conn *conn);
+extern int bnx2i_percpu_io_thread(void *arg);
+extern int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
+ struct bnx2i_conn *bnx2i_conn,
+ struct cqe *cqe);
#endif
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 5c54a2d9b834..030a96c646c3 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1,6 +1,6 @@
/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -17,6 +17,8 @@
#include <scsi/libiscsi.h>
#include "bnx2i.h"
+DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
+
/**
* bnx2i_get_cid_num - get cid from ep
* @ep: endpoint pointer
@@ -131,16 +133,16 @@ static void bnx2i_iscsi_license_error(struct bnx2i_hba *hba, u32 error_code)
* the driver. EQ event is generated CQ index is hit or at least 1 CQ is
* outstanding and on chip timer expires
*/
-void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
+int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
{
struct bnx2i_5771x_cq_db *cq_db;
u16 cq_index;
- u16 next_index;
+ u16 next_index = 0;
u32 num_active_cmds;
/* Coalesce CQ entries only on 10G devices */
if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type))
- return;
+ return 0;
/* Do not update CQ DB multiple times before firmware writes
* '0xFFFF' to CQDB->SQN field. Deviation may cause spurious
@@ -150,16 +152,17 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
if (action != CNIC_ARM_CQE_FP)
if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF)
- return;
+ return 0;
if (action == CNIC_ARM_CQE || action == CNIC_ARM_CQE_FP) {
- num_active_cmds = ep->num_active_cmds;
+ num_active_cmds = atomic_read(&ep->num_active_cmds);
if (num_active_cmds <= event_coal_min)
next_index = 1;
- else
- next_index = event_coal_min +
- ((num_active_cmds - event_coal_min) >>
- ep->ec_shift);
+ else {
+ next_index = num_active_cmds >> ep->ec_shift;
+ if (next_index > num_active_cmds - event_coal_min)
+ next_index = num_active_cmds - event_coal_min;
+ }
if (!next_index)
next_index = 1;
cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1;
@@ -170,6 +173,7 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
cq_db->sqn[0] = cq_index;
}
+ return next_index;
}
@@ -265,7 +269,7 @@ static void bnx2i_ring_sq_dbell(struct bnx2i_conn *bnx2i_conn, int count)
struct bnx2i_5771x_sq_rq_db *sq_db;
struct bnx2i_endpoint *ep = bnx2i_conn->ep;
- ep->num_active_cmds++;
+ atomic_inc(&ep->num_active_cmds);
wmb(); /* flush SQ WQE memory before the doorbell is rung */
if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
sq_db = (struct bnx2i_5771x_sq_rq_db *) ep->qp.sq_pgtbl_virt;
@@ -430,7 +434,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
default:
tmfabort_wqe->ref_itt = RESERVED_ITT;
}
- memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
+ memcpy(scsi_lun, &tmfabort_hdr->lun, sizeof(struct scsi_lun));
tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
@@ -547,7 +551,7 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
nopout_wqe->op_code = nopout_hdr->opcode;
nopout_wqe->op_attr = ISCSI_FLAG_CMD_FINAL;
- memcpy(nopout_wqe->lun, nopout_hdr->lun, 8);
+ memcpy(nopout_wqe->lun, &nopout_hdr->lun, 8);
if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
u32 tmp = nopout_wqe->lun[0];
@@ -1331,14 +1335,15 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
/**
* bnx2i_process_scsi_cmd_resp - this function handles scsi cmd completion.
- * @conn: iscsi connection
+ * @session: iscsi session
+ * @bnx2i_conn: bnx2i connection
* @cqe: pointer to newly DMA'ed CQE entry for processing
*
* process SCSI CMD Response CQE & complete the request to SCSI-ML
*/
-static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
- struct bnx2i_conn *bnx2i_conn,
- struct cqe *cqe)
+int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
+ struct bnx2i_conn *bnx2i_conn,
+ struct cqe *cqe)
{
struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
struct bnx2i_cmd_response *resp_cqe;
@@ -1348,7 +1353,7 @@ static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
u32 datalen = 0;
resp_cqe = (struct bnx2i_cmd_response *)cqe;
- spin_lock(&session->lock);
+ spin_lock_bh(&session->lock);
task = iscsi_itt_to_task(conn,
resp_cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
if (!task)
@@ -1409,7 +1414,7 @@ done:
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr,
conn->data, datalen);
fail:
- spin_unlock(&session->lock);
+ spin_unlock_bh(&session->lock);
return 0;
}
@@ -1711,7 +1716,7 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session,
hdr->flags = ISCSI_FLAG_CMD_FINAL;
hdr->itt = task->hdr->itt;
hdr->ttt = cpu_to_be32(nop_in->ttt);
- memcpy(hdr->lun, nop_in->lun, 8);
+ memcpy(&hdr->lun, nop_in->lun, 8);
}
done:
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
@@ -1754,7 +1759,7 @@ static void bnx2i_process_async_mesg(struct iscsi_session *session,
resp_hdr->opcode = async_cqe->op_code;
resp_hdr->flags = 0x80;
- memcpy(resp_hdr->lun, async_cqe->lun, 8);
+ memcpy(&resp_hdr->lun, async_cqe->lun, 8);
resp_hdr->exp_cmdsn = cpu_to_be32(async_cqe->exp_cmd_sn);
resp_hdr->max_cmdsn = cpu_to_be32(async_cqe->max_cmd_sn);
@@ -1836,21 +1841,136 @@ static void bnx2i_process_cmd_cleanup_resp(struct iscsi_session *session,
}
+/**
+ * bnx2i_percpu_io_thread - thread per cpu for ios
+ *
+ * @arg: ptr to bnx2i_percpu_info structure
+ */
+int bnx2i_percpu_io_thread(void *arg)
+{
+ struct bnx2i_percpu_s *p = arg;
+ struct bnx2i_work *work, *tmp;
+ LIST_HEAD(work_list);
+
+ set_user_nice(current, -20);
+
+ while (!kthread_should_stop()) {
+ spin_lock_bh(&p->p_work_lock);
+ while (!list_empty(&p->work_list)) {
+ list_splice_init(&p->work_list, &work_list);
+ spin_unlock_bh(&p->p_work_lock);
+
+ list_for_each_entry_safe(work, tmp, &work_list, list) {
+ list_del_init(&work->list);
+ /* work allocated in the bh, freed here */
+ bnx2i_process_scsi_cmd_resp(work->session,
+ work->bnx2i_conn,
+ &work->cqe);
+ atomic_dec(&work->bnx2i_conn->work_cnt);
+ kfree(work);
+ }
+ spin_lock_bh(&p->p_work_lock);
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_bh(&p->p_work_lock);
+ schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+
+ return 0;
+}
+
+
+/**
+ * bnx2i_queue_scsi_cmd_resp - queue cmd completion to the percpu thread
+ * @bnx2i_conn: bnx2i connection
+ *
+ * this function is called by generic KCQ handler to queue all pending cmd
+ * completion CQEs
+ *
+ * The implementation is to queue the cmd response based on the
+ * last recorded command for the given connection. The
+ * cpu_id gets recorded upon task_xmit. No out-of-order completion!
+ */
+static int bnx2i_queue_scsi_cmd_resp(struct iscsi_session *session,
+ struct bnx2i_conn *bnx2i_conn,
+ struct bnx2i_nop_in_msg *cqe)
+{
+ struct bnx2i_work *bnx2i_work = NULL;
+ struct bnx2i_percpu_s *p = NULL;
+ struct iscsi_task *task;
+ struct scsi_cmnd *sc;
+ int rc = 0;
+ int cpu;
+
+ spin_lock(&session->lock);
+ task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data,
+ cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
+ if (!task) {
+ spin_unlock(&session->lock);
+ return -EINVAL;
+ }
+ sc = task->sc;
+ spin_unlock(&session->lock);
+
+ if (!blk_rq_cpu_valid(sc->request))
+ cpu = smp_processor_id();
+ else
+ cpu = sc->request->cpu;
+
+ p = &per_cpu(bnx2i_percpu, cpu);
+ spin_lock(&p->p_work_lock);
+ if (unlikely(!p->iothread)) {
+ rc = -EINVAL;
+ goto err;
+ }
+ /* Alloc and copy to the cqe */
+ bnx2i_work = kzalloc(sizeof(struct bnx2i_work), GFP_ATOMIC);
+ if (bnx2i_work) {
+ INIT_LIST_HEAD(&bnx2i_work->list);
+ bnx2i_work->session = session;
+ bnx2i_work->bnx2i_conn = bnx2i_conn;
+ memcpy(&bnx2i_work->cqe, cqe, sizeof(struct cqe));
+ list_add_tail(&bnx2i_work->list, &p->work_list);
+ atomic_inc(&bnx2i_conn->work_cnt);
+ wake_up_process(p->iothread);
+ spin_unlock(&p->p_work_lock);
+ goto done;
+ } else
+ rc = -ENOMEM;
+err:
+ spin_unlock(&p->p_work_lock);
+ bnx2i_process_scsi_cmd_resp(session, bnx2i_conn, (struct cqe *)cqe);
+done:
+ return rc;
+}
+
/**
* bnx2i_process_new_cqes - process newly DMA'ed CQE's
- * @bnx2i_conn: iscsi connection
+ * @bnx2i_conn: bnx2i connection
*
* this function is called by generic KCQ handler to process all pending CQE's
*/
-static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
+static int bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
{
struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
struct iscsi_session *session = conn->session;
- struct qp_info *qp = &bnx2i_conn->ep->qp;
+ struct qp_info *qp;
struct bnx2i_nop_in_msg *nopin;
int tgt_async_msg;
+ int cqe_cnt = 0;
+
+ if (bnx2i_conn->ep == NULL)
+ return 0;
+
+ qp = &bnx2i_conn->ep->qp;
+ if (!qp->cq_virt) {
+ printk(KERN_ALERT "bnx2i (%s): cq resr freed in bh execution!",
+ bnx2i_conn->hba->netdev->name);
+ goto out;
+ }
while (1) {
nopin = (struct bnx2i_nop_in_msg *) qp->cq_cons_qe;
if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
@@ -1873,8 +1993,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
switch (nopin->op_code) {
case ISCSI_OP_SCSI_CMD_RSP:
case ISCSI_OP_SCSI_DATA_IN:
- bnx2i_process_scsi_cmd_resp(session, bnx2i_conn,
- qp->cq_cons_qe);
+ /* Run the kthread engine only for data cmds
+ All other cmds will be completed in this bh! */
+ bnx2i_queue_scsi_cmd_resp(session, bnx2i_conn, nopin);
break;
case ISCSI_OP_LOGIN_RSP:
bnx2i_process_login_resp(session, bnx2i_conn,
@@ -1918,13 +2039,21 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n",
nopin->op_code);
}
- if (!tgt_async_msg)
- bnx2i_conn->ep->num_active_cmds--;
+ if (!tgt_async_msg) {
+ if (!atomic_read(&bnx2i_conn->ep->num_active_cmds))
+ printk(KERN_ALERT "bnx2i (%s): no active cmd! "
+ "op 0x%x\n",
+ bnx2i_conn->hba->netdev->name,
+ nopin->op_code);
+ else
+ atomic_dec(&bnx2i_conn->ep->num_active_cmds);
+ }
cqe_out:
/* clear out in production version only, till beta keep opcode
* field intact, will be helpful in debugging (context dump)
* nopin->op_code = 0;
*/
+ cqe_cnt++;
qp->cqe_exp_seq_sn++;
if (qp->cqe_exp_seq_sn == (qp->cqe_size * 2 + 1))
qp->cqe_exp_seq_sn = ISCSI_INITIAL_SN;
@@ -1937,6 +2066,8 @@ cqe_out:
qp->cq_cons_idx++;
}
}
+out:
+ return cqe_cnt;
}
/**
@@ -1952,6 +2083,7 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
{
struct bnx2i_conn *bnx2i_conn;
u32 iscsi_cid;
+ int nxt_idx;
iscsi_cid = new_cqe_kcqe->iscsi_conn_id;
bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid);
@@ -1964,9 +2096,12 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid);
return;
}
+
bnx2i_process_new_cqes(bnx2i_conn);
- bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
- bnx2i_process_new_cqes(bnx2i_conn);
+ nxt_idx = bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep,
+ CNIC_ARM_CQE_FP);
+ if (nxt_idx && nxt_idx == bnx2i_process_new_cqes(bnx2i_conn))
+ bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
}
@@ -2312,7 +2447,7 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba,
printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
"opcode\n", hba->netdev->name);
else if (ofld_kcqe->completion_status ==
- ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
+ ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
/* error status code valid only for 5771x chipset */
ep->state = EP_STATE_OFLD_FAILED_CID_BUSY;
else
@@ -2386,14 +2521,20 @@ static void bnx2i_indicate_kcqe(void *context, struct kcqe *kcqe[],
* bnx2i_indicate_netevent - Generic netdev event handler
* @context: adapter structure pointer
* @event: event type
+ * @vlan_id: vlans id - associated vlan id with this event
*
* Handles four netdev events, NETDEV_UP, NETDEV_DOWN,
* NETDEV_GOING_DOWN and NETDEV_CHANGE
*/
-static void bnx2i_indicate_netevent(void *context, unsigned long event)
+static void bnx2i_indicate_netevent(void *context, unsigned long event,
+ u16 vlan_id)
{
struct bnx2i_hba *hba = context;
+ /* Ignore all netevent coming from vlans */
+ if (vlan_id != 0)
+ return;
+
switch (event) {
case NETDEV_UP:
if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
@@ -2511,7 +2652,7 @@ static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
static int bnx2i_send_nl_mesg(void *context, u32 msg_type,
- char *buf, u16 buflen)
+ char *buf, u16 buflen)
{
struct bnx2i_hba *hba = context;
int rc;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 6adbdc34a9a5..1a947f1b9729 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,6 +1,6 @@
/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
static u32 adapter_count;
#define DRV_MODULE_NAME "bnx2i"
-#define DRV_MODULE_VERSION "2.6.2.3"
-#define DRV_MODULE_RELDATE "Dec 31, 2010"
+#define DRV_MODULE_VERSION "2.7.0.3"
+#define DRV_MODULE_RELDATE "Jun 15, 2011"
static char version[] __devinitdata =
"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -30,7 +30,7 @@ MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
"Eddie Wai <eddie.wai@broadcom.com>");
MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
- " iSCSI Driver");
+ "/57800/57810/57840 iSCSI Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -40,7 +40,7 @@ unsigned int event_coal_min = 24;
module_param(event_coal_min, int, 0664);
MODULE_PARM_DESC(event_coal_min, "Event Coalescing Minimum Commands");
-unsigned int event_coal_div = 1;
+unsigned int event_coal_div = 2;
module_param(event_coal_div, int, 0664);
MODULE_PARM_DESC(event_coal_div, "Event Coalescing Divide Factor");
@@ -66,6 +66,15 @@ MODULE_PARM_DESC(rq_size, "Configure RQ size");
u64 iscsi_error_mask = 0x00;
+DEFINE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
+
+static int bnx2i_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu);
+/* notification function for CPU hotplug events */
+static struct notifier_block bnx2i_cpu_notifier = {
+ .notifier_call = bnx2i_cpu_callback,
+};
+
/**
* bnx2i_identify_device - identifies NetXtreme II device type
@@ -88,11 +97,20 @@ void bnx2i_identify_device(struct bnx2i_hba *hba)
(hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
- } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57712 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57712E)
+ } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57712 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57712E ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800_VF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810_VF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840_VF)
set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
else
printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
@@ -163,21 +181,14 @@ void bnx2i_start(void *handle)
struct bnx2i_hba *hba = handle;
int i = HZ;
- if (!hba->cnic->max_iscsi_conn) {
- printk(KERN_ALERT "bnx2i: dev %s does not support "
- "iSCSI\n", hba->netdev->name);
+ /*
+ * We should never register devices that don't support iSCSI
+ * (see bnx2i_init_one), so something is wrong if we try to
+ * start a iSCSI adapter on hardware with 0 supported iSCSI
+ * connections
+ */
+ BUG_ON(!hba->cnic->max_iscsi_conn);
- if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
- mutex_lock(&bnx2i_dev_lock);
- list_del_init(&hba->link);
- adapter_count--;
- hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
- clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
- mutex_unlock(&bnx2i_dev_lock);
- bnx2i_free_hba(hba);
- }
- return;
- }
bnx2i_send_fw_iscsi_init_msg(hba);
while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
msleep(BNX2I_INIT_POLL_TIME);
@@ -281,6 +292,13 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
int rc;
mutex_lock(&bnx2i_dev_lock);
+ if (!cnic->max_iscsi_conn) {
+ printk(KERN_ALERT "bnx2i: dev %s does not support "
+ "iSCSI\n", hba->netdev->name);
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
hba->cnic = cnic;
rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba);
if (!rc) {
@@ -298,6 +316,7 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
else
printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc);
+out:
mutex_unlock(&bnx2i_dev_lock);
return rc;
@@ -362,6 +381,91 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
/**
+ * bnx2i_percpu_thread_create - Create a receive thread for an
+ * online CPU
+ *
+ * @cpu: cpu index for the online cpu
+ */
+static void bnx2i_percpu_thread_create(unsigned int cpu)
+{
+ struct bnx2i_percpu_s *p;
+ struct task_struct *thread;
+
+ p = &per_cpu(bnx2i_percpu, cpu);
+
+ thread = kthread_create(bnx2i_percpu_io_thread, (void *)p,
+ "bnx2i_thread/%d", cpu);
+ /* bind thread to the cpu */
+ if (likely(!IS_ERR(thread))) {
+ kthread_bind(thread, cpu);
+ p->iothread = thread;
+ wake_up_process(thread);
+ }
+}
+
+
+static void bnx2i_percpu_thread_destroy(unsigned int cpu)
+{
+ struct bnx2i_percpu_s *p;
+ struct task_struct *thread;
+ struct bnx2i_work *work, *tmp;
+
+ /* Prevent any new work from being queued for this CPU */
+ p = &per_cpu(bnx2i_percpu, cpu);
+ spin_lock_bh(&p->p_work_lock);
+ thread = p->iothread;
+ p->iothread = NULL;
+
+ /* Free all work in the list */
+ list_for_each_entry_safe(work, tmp, &p->work_list, list) {
+ list_del_init(&work->list);
+ bnx2i_process_scsi_cmd_resp(work->session,
+ work->bnx2i_conn, &work->cqe);
+ kfree(work);
+ }
+
+ spin_unlock_bh(&p->p_work_lock);
+ if (thread)
+ kthread_stop(thread);
+}
+
+
+/**
+ * bnx2i_cpu_callback - Handler for CPU hotplug events
+ *
+ * @nfb: The callback data block
+ * @action: The event triggering the callback
+ * @hcpu: The index of the CPU that the event is for
+ *
+ * This creates or destroys per-CPU data for iSCSI
+ *
+ * Returns NOTIFY_OK always.
+ */
+static int bnx2i_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ printk(KERN_INFO "bnx2i: CPU %x online: Create Rx thread\n",
+ cpu);
+ bnx2i_percpu_thread_create(cpu);
+ break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ printk(KERN_INFO "CPU %x offline: Remove Rx thread\n", cpu);
+ bnx2i_percpu_thread_destroy(cpu);
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+
+/**
* bnx2i_mod_init - module init entry point
*
* initialize any driver wide global data structures such as endpoint pool,
@@ -371,6 +475,8 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
static int __init bnx2i_mod_init(void)
{
int err;
+ unsigned cpu = 0;
+ struct bnx2i_percpu_s *p;
printk(KERN_INFO "%s", version);
@@ -393,6 +499,20 @@ static int __init bnx2i_mod_init(void)
goto unreg_xport;
}
+ /* Create percpu kernel threads to handle iSCSI I/O completions */
+ for_each_possible_cpu(cpu) {
+ p = &per_cpu(bnx2i_percpu, cpu);
+ INIT_LIST_HEAD(&p->work_list);
+ spin_lock_init(&p->p_work_lock);
+ p->iothread = NULL;
+ }
+
+ for_each_online_cpu(cpu)
+ bnx2i_percpu_thread_create(cpu);
+
+ /* Initialize per CPU interrupt thread */
+ register_hotcpu_notifier(&bnx2i_cpu_notifier);
+
return 0;
unreg_xport:
@@ -413,6 +533,7 @@ out:
static void __exit bnx2i_mod_exit(void)
{
struct bnx2i_hba *hba;
+ unsigned cpu = 0;
mutex_lock(&bnx2i_dev_lock);
while (!list_empty(&adapter_list)) {
@@ -430,6 +551,11 @@ static void __exit bnx2i_mod_exit(void)
}
mutex_unlock(&bnx2i_dev_lock);
+ unregister_hotcpu_notifier(&bnx2i_cpu_notifier);
+
+ for_each_online_cpu(cpu)
+ bnx2i_percpu_thread_destroy(cpu);
+
iscsi_unregister_transport(&bnx2i_iscsi_transport);
cnic_unregister_driver(CNIC_ULP_ISCSI);
}
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 041928b23cb0..5c55a75ae597 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,7 +1,7 @@
/*
* bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -27,6 +27,7 @@ static struct scsi_host_template bnx2i_host_template;
*/
static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */
+DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
static int bnx2i_adapter_ready(struct bnx2i_hba *hba)
{
@@ -1214,7 +1215,8 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
struct bnx2i_cmd *cmd = task->dd_data;
struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
- if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes)
+ if (atomic_read(&bnx2i_conn->ep->num_active_cmds) + 1 >
+ hba->max_sqes)
return -ENOMEM;
/*
@@ -1354,6 +1356,9 @@ bnx2i_conn_create(struct iscsi_cls_session *cls_session, uint32_t cid)
bnx2i_conn = conn->dd_data;
bnx2i_conn->cls_conn = cls_conn;
bnx2i_conn->hba = hba;
+
+ atomic_set(&bnx2i_conn->work_cnt, 0);
+
/* 'ep' ptr will be assigned in bind() call */
bnx2i_conn->ep = NULL;
init_completion(&bnx2i_conn->cmd_cleanup_cmpl);
@@ -1457,11 +1462,34 @@ static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
struct bnx2i_conn *bnx2i_conn = conn->dd_data;
struct Scsi_Host *shost;
struct bnx2i_hba *hba;
+ struct bnx2i_work *work, *tmp;
+ unsigned cpu = 0;
+ struct bnx2i_percpu_s *p;
shost = iscsi_session_to_shost(iscsi_conn_to_session(cls_conn));
hba = iscsi_host_priv(shost);
bnx2i_conn_free_login_resources(hba, bnx2i_conn);
+
+ if (atomic_read(&bnx2i_conn->work_cnt)) {
+ for_each_online_cpu(cpu) {
+ p = &per_cpu(bnx2i_percpu, cpu);
+ spin_lock_bh(&p->p_work_lock);
+ list_for_each_entry_safe(work, tmp,
+ &p->work_list, list) {
+ if (work->session == conn->session &&
+ work->bnx2i_conn == bnx2i_conn) {
+ list_del_init(&work->list);
+ kfree(work);
+ if (!atomic_dec_and_test(
+ &bnx2i_conn->work_cnt))
+ break;
+ }
+ }
+ spin_unlock_bh(&p->p_work_lock);
+ }
+ }
+
iscsi_conn_teardown(cls_conn);
}
@@ -1769,7 +1797,7 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
}
bnx2i_ep = ep->dd_data;
- bnx2i_ep->num_active_cmds = 0;
+ atomic_set(&bnx2i_ep->num_active_cmds, 0);
iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
if (iscsi_cid == -1) {
printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
@@ -2163,9 +2191,9 @@ static struct scsi_host_template bnx2i_host_template = {
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
.change_queue_depth = iscsi_change_queue_depth,
- .can_queue = 1024,
+ .can_queue = 2048,
.max_sectors = 127,
- .cmd_per_lun = 24,
+ .cmd_per_lun = 128,
.this_id = -1,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = ISCSI_MAX_BDS_PER_CMD,
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 9174196d9033..83a77f7244d2 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,6 +1,6 @@
/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2004 - 2010 Broadcom Corporation
+ * Copyright (c) 2004 - 2011 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
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index fc2cdb62f53b..bd22041e2789 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -985,7 +985,7 @@ static int init_act_open(struct cxgbi_sock *csk)
csk->saddr.sin_addr.s_addr = chba->ipv4addr;
csk->rss_qid = 0;
- csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev);
+ csk->l2t = t3_l2t_get(t3dev, dst_get_neighbour(dst), ndev);
if (!csk->l2t) {
pr_err("NO l2t available.\n");
return -EINVAL;
@@ -1245,7 +1245,7 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
struct cxgbi_ddp_info *ddp = tdev->ulp_iscsi;
struct ulp_iscsi_info uinfo;
unsigned int pgsz_factor[4];
- int err;
+ int i, err;
if (ddp) {
kref_get(&ddp->refcnt);
@@ -1271,6 +1271,8 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
cxgbi_ddp_page_size_factor(pgsz_factor);
+ for (i = 0; i < 4; i++)
+ uinfo.pgsz_factor[i] = pgsz_factor[i];
uinfo.ulimit = uinfo.llimit + (ddp->nppods << PPOD_SIZE_SHIFT);
err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index f3a4cd7cf782..ae13c4993aa3 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -1160,7 +1160,7 @@ static int init_act_open(struct cxgbi_sock *csk)
cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
cxgbi_sock_get(csk);
- csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0);
+ csk->l2t = cxgb4_l2t_get(lldi->l2t, dst_get_neighbour(csk->dst), ndev, 0);
if (!csk->l2t) {
pr_err("%s, cannot alloc l2t.\n", ndev->name);
goto rel_resource;
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index a2a9c7c6c643..77ac217ad5ce 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -492,7 +492,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
goto err_out;
}
dst = &rt->dst;
- ndev = dst->neighbour->dev;
+ ndev = dst_get_neighbour(dst)->dev;
if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
pr_info("multi-cast route %pI4, port %u, dev %s.\n",
@@ -506,7 +506,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
mtu = ndev->mtu;
pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
- dst->neighbour->dev->name, ndev->name, mtu);
+ dst_get_neighbour(dst)->dev->name, ndev->name, mtu);
}
cdev = cxgbi_device_find_by_netdev(ndev, &port);
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index e7fc70d6b478..2e7c136bb805 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -35,7 +35,7 @@
* mode page were taken from the LSI RDAC 2.4 GPL'd
* driver, and then converted to Linux conventions.
*/
-#define RDAC_QUIESCENCE_TIME 20;
+#define RDAC_QUIESCENCE_TIME 20
/*
* Page Codes
*/
diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
index 179ad77f6cc9..bd9e31e16249 100644
--- a/drivers/scsi/dpt/dpti_i2o.h
+++ b/drivers/scsi/dpt/dpti_i2o.h
@@ -22,7 +22,7 @@
#include <linux/i2o-dev.h>
#include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
/*
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 155d7b9bdeae..204fa8d4b4ab 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -99,7 +99,8 @@ static void fcoe_destroy_work(struct work_struct *);
static int fcoe_ddp_setup(struct fc_lport *, u16, struct scatterlist *,
unsigned int);
static int fcoe_ddp_done(struct fc_lport *, u16);
-
+static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *,
+ unsigned int);
static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
static bool fcoe_match(struct net_device *netdev);
@@ -143,6 +144,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
.frame_send = fcoe_xmit,
.ddp_setup = fcoe_ddp_setup,
.ddp_done = fcoe_ddp_done,
+ .ddp_target = fcoe_ddp_target,
.elsct_send = fcoe_elsct_send,
.get_lesb = fcoe_get_lesb,
.lport_set_port_id = fcoe_set_port_id,
@@ -429,21 +431,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
struct fcoe_ctlr *fip = &fcoe->ctlr;
u8 flogi_maddr[ETH_ALEN];
const struct net_device_ops *ops;
- struct fcoe_port *port = lport_priv(fcoe->ctlr.lp);
-
- FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
-
- /* Logout of the fabric */
- fc_fabric_logoff(fcoe->ctlr.lp);
-
- /* Cleanup the fc_lport */
- fc_lport_destroy(fcoe->ctlr.lp);
-
- /* Stop the transmit retry timer */
- del_timer_sync(&port->timer);
-
- /* Free existing transmit skbs */
- fcoe_clean_pending_queue(fcoe->ctlr.lp);
/*
* Don't listen for Ethernet packets anymore.
@@ -466,9 +453,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
} else
dev_mc_del(netdev, FIP_ALL_ENODE_MACS);
- if (!is_zero_ether_addr(port->data_src_addr))
- dev_uc_del(netdev, port->data_src_addr);
-
/* Tell the LLD we are done w/ FCoE */
ops = netdev->netdev_ops;
if (ops->ndo_fcoe_disable) {
@@ -476,6 +460,8 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
" specific feature for LLD.\n");
}
+
+ /* Release the self-reference taken during fcoe_interface_create() */
fcoe_interface_put(fcoe);
}
@@ -749,12 +735,27 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
* The offload EM that this routine is associated with will handle any
* packets that are for SCSI read requests.
*
+ * This has been enhanced to work when FCoE stack is operating in target
+ * mode.
+ *
* Returns: True for read types I/O, otherwise returns false.
*/
bool fcoe_oem_match(struct fc_frame *fp)
{
- return fc_fcp_is_read(fr_fsp(fp)) &&
- (fr_fsp(fp)->data_len > fcoe_ddp_min);
+ struct fc_frame_header *fh = fc_frame_header_get(fp);
+ struct fcp_cmnd *fcp;
+
+ if (fc_fcp_is_read(fr_fsp(fp)) &&
+ (fr_fsp(fp)->data_len > fcoe_ddp_min))
+ return true;
+ else if (!(ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)) {
+ fcp = fc_frame_payload_get(fp, sizeof(*fcp));
+ if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN &&
+ fcp && (ntohl(fcp->fc_dl) > fcoe_ddp_min) &&
+ (fcp->fc_flags & FCP_CFL_WRDATA))
+ return true;
+ }
+ return false;
}
/**
@@ -844,6 +845,32 @@ skip_oem:
*/
static void fcoe_if_destroy(struct fc_lport *lport)
{
+ struct fcoe_port *port = lport_priv(lport);
+ struct fcoe_interface *fcoe = port->priv;
+ struct net_device *netdev = fcoe->netdev;
+
+ FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
+
+ /* Logout of the fabric */
+ fc_fabric_logoff(lport);
+
+ /* Cleanup the fc_lport */
+ fc_lport_destroy(lport);
+
+ /* Stop the transmit retry timer */
+ del_timer_sync(&port->timer);
+
+ /* Free existing transmit skbs */
+ fcoe_clean_pending_queue(lport);
+
+ rtnl_lock();
+ if (!is_zero_ether_addr(port->data_src_addr))
+ dev_uc_del(netdev, port->data_src_addr);
+ rtnl_unlock();
+
+ /* Release reference held in fcoe_if_create() */
+ fcoe_interface_put(fcoe);
+
/* Free queued packets for the per-CPU receive threads */
fcoe_percpu_clean(lport);
@@ -887,6 +914,28 @@ static int fcoe_ddp_setup(struct fc_lport *lport, u16 xid,
}
/**
+ * fcoe_ddp_target() - Call a LLD's ddp_target through the net device
+ * @lport: The local port to setup DDP for
+ * @xid: The exchange ID for this DDP transfer
+ * @sgl: The scatterlist describing this transfer
+ * @sgc: The number of sg items
+ *
+ * Returns: 0 if the DDP context was not configured
+ */
+static int fcoe_ddp_target(struct fc_lport *lport, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc)
+{
+ struct net_device *netdev = fcoe_netdev(lport);
+
+ if (netdev->netdev_ops->ndo_fcoe_ddp_target)
+ return netdev->netdev_ops->ndo_fcoe_ddp_target(netdev, xid,
+ sgl, sgc);
+
+ return 0;
+}
+
+
+/**
* fcoe_ddp_done() - Call a LLD's ddp_done through the net device
* @lport: The local port to complete DDP on
* @xid: The exchange ID for this DDP transfer
@@ -1206,6 +1255,36 @@ static int fcoe_cpu_callback(struct notifier_block *nfb,
}
/**
+ * fcoe_select_cpu() - Selects CPU to handle post-processing of incoming
+ * command.
+ * @curr_cpu: CPU which received request
+ *
+ * This routine selects next CPU based on cpumask.
+ *
+ * Returns: int (CPU number). Caller to verify if returned CPU is online or not.
+ */
+static unsigned int fcoe_select_cpu(unsigned int curr_cpu)
+{
+ static unsigned int selected_cpu;
+
+ if (num_online_cpus() == 1)
+ return curr_cpu;
+ /*
+ * Doing following check, to skip "curr_cpu (smp_processor_id)"
+ * from selection of CPU is intentional. This is to avoid same CPU
+ * doing post-processing of command. "curr_cpu" to just receive
+ * incoming request in case where rx_id is UNKNOWN and all other
+ * CPU to actually process the command(s)
+ */
+ do {
+ selected_cpu = cpumask_next(selected_cpu, cpu_online_mask);
+ if (selected_cpu >= nr_cpu_ids)
+ selected_cpu = cpumask_first(cpu_online_mask);
+ } while (selected_cpu == curr_cpu);
+ return selected_cpu;
+}
+
+/**
* fcoe_rcv() - Receive packets from a net device
* @skb: The received packet
* @netdev: The net device that the packet was received on
@@ -1281,9 +1360,20 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
*/
if (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)
cpu = ntohs(fh->fh_ox_id) & fc_cpu_mask;
- else
+ else {
cpu = smp_processor_id();
+ if ((fh->fh_type == FC_TYPE_FCP) &&
+ (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)) {
+ do {
+ cpu = fcoe_select_cpu(cpu);
+ } while (!cpu_online(cpu));
+ } else if ((fh->fh_type == FC_TYPE_FCP) &&
+ (ntohs(fh->fh_rx_id) != FC_XID_UNKNOWN)) {
+ cpu = ntohs(fh->fh_rx_id) & fc_cpu_mask;
+ } else
+ cpu = smp_processor_id();
+ }
fps = &per_cpu(fcoe_percpu, cpu);
spin_lock_bh(&fps->fcoe_rx_list.lock);
if (unlikely(!fps->thread)) {
@@ -1733,7 +1823,6 @@ static int fcoe_device_notification(struct notifier_block *notifier,
case NETDEV_UNREGISTER:
list_del(&fcoe->list);
port = lport_priv(fcoe->ctlr.lp);
- fcoe_interface_cleanup(fcoe);
queue_work(fcoe_wq, &port->destroy_work);
goto out;
break;
@@ -1827,22 +1916,22 @@ static int fcoe_destroy(struct net_device *netdev)
{
struct fcoe_interface *fcoe;
struct fc_lport *lport;
+ struct fcoe_port *port;
int rc = 0;
mutex_lock(&fcoe_config_mutex);
rtnl_lock();
fcoe = fcoe_hostlist_lookup_port(netdev);
if (!fcoe) {
- rtnl_unlock();
rc = -ENODEV;
goto out_nodev;
}
lport = fcoe->ctlr.lp;
+ port = lport_priv(lport);
list_del(&fcoe->list);
- fcoe_interface_cleanup(fcoe);
- rtnl_unlock();
- fcoe_if_destroy(lport);
+ queue_work(fcoe_wq, &port->destroy_work);
out_nodev:
+ rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
return rc;
}
@@ -1854,10 +1943,25 @@ out_nodev:
static void fcoe_destroy_work(struct work_struct *work)
{
struct fcoe_port *port;
+ struct fcoe_interface *fcoe;
+ int npiv = 0;
port = container_of(work, struct fcoe_port, destroy_work);
mutex_lock(&fcoe_config_mutex);
+
+ /* set if this is an NPIV port */
+ npiv = port->lport->vport ? 1 : 0;
+
+ fcoe = port->priv;
fcoe_if_destroy(port->lport);
+
+ /* Do not tear down the fcoe interface for NPIV port */
+ if (!npiv) {
+ rtnl_lock();
+ fcoe_interface_cleanup(fcoe);
+ rtnl_unlock();
+ }
+
mutex_unlock(&fcoe_config_mutex);
}
@@ -1886,7 +1990,7 @@ static bool fcoe_match(struct net_device *netdev)
*/
static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
{
- int rc;
+ int rc = 0;
struct fcoe_interface *fcoe;
struct fc_lport *lport;
@@ -1911,7 +2015,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
netdev->name);
rc = -EIO;
fcoe_interface_cleanup(fcoe);
- goto out_free;
+ goto out_nodev;
}
/* Make this the "master" N_Port */
@@ -1926,17 +2030,6 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
if (!fcoe_link_ok(lport))
fcoe_ctlr_link_up(&fcoe->ctlr);
- /*
- * Release from init in fcoe_interface_create(), on success lport
- * should be holding a reference taken in fcoe_if_create().
- */
- fcoe_interface_put(fcoe);
- rtnl_unlock();
- mutex_unlock(&fcoe_config_mutex);
-
- return 0;
-out_free:
- fcoe_interface_put(fcoe);
out_nodev:
rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
@@ -2218,7 +2311,6 @@ static void __exit fcoe_exit(void)
list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) {
list_del(&fcoe->list);
port = lport_priv(fcoe->ctlr.lp);
- fcoe_interface_cleanup(fcoe);
queue_work(fcoe_wq, &port->destroy_work);
}
rtnl_unlock();
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 671cde9d4060..95a5ba29320d 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -37,7 +37,7 @@
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.5.0.1"
+#define DRV_VERSION "1.5.0.2"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index bb63f1a1f808..fc98eb61e760 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -388,17 +388,6 @@ static void fnic_iounmap(struct fnic *fnic)
iounmap(fnic->bar0.vaddr);
}
-/*
- * Allocate element for mempools requiring GFP_DMA flag.
- * Otherwise, checks in kmem_flagcheck() hit BUG_ON().
- */
-static void *fnic_alloc_slab_dma(gfp_t gfp_mask, void *pool_data)
-{
- struct kmem_cache *mem = pool_data;
-
- return kmem_cache_alloc(mem, gfp_mask | GFP_ATOMIC | GFP_DMA);
-}
-
/**
* fnic_get_mac() - get assigned data MAC address for FIP code.
* @lport: local port.
@@ -603,14 +592,12 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
if (!fnic->io_req_pool)
goto err_out_free_resources;
- pool = mempool_create(2, fnic_alloc_slab_dma, mempool_free_slab,
- fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
+ pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
if (!pool)
goto err_out_free_ioreq_pool;
fnic->io_sgl_pool[FNIC_SGL_CACHE_DFLT] = pool;
- pool = mempool_create(2, fnic_alloc_slab_dma, mempool_free_slab,
- fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
+ pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
if (!pool)
goto err_out_free_dflt_pool;
fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX] = pool;
@@ -876,7 +863,7 @@ static int __init fnic_init_module(void)
len = sizeof(struct fnic_dflt_sgl_list);
fnic_sgl_cache[FNIC_SGL_CACHE_DFLT] = kmem_cache_create
("fnic_sgl_dflt", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
- SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA,
+ SLAB_HWCACHE_ALIGN,
NULL);
if (!fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]) {
printk(KERN_ERR PFX "failed to create fnic dflt sgl slab\n");
@@ -888,7 +875,7 @@ static int __init fnic_init_module(void)
len = sizeof(struct fnic_sgl_list);
fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create
("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
- SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA,
+ SLAB_HWCACHE_ALIGN,
NULL);
if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) {
printk(KERN_ERR PFX "failed to create fnic max sgl slab\n");
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 538b31c2cf58..c40ce52ed7c6 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -406,7 +406,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
if (sg_count) {
io_req->sgl_list =
mempool_alloc(fnic->io_sgl_pool[io_req->sgl_type],
- GFP_ATOMIC | GFP_DMA);
+ GFP_ATOMIC);
if (!io_req->sgl_list) {
ret = SCSI_MLQUEUE_HOST_BUSY;
scsi_dma_unmap(sc);
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 6bba23a26303..c6f99b1d2383 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -46,7 +46,7 @@
#include <linux/cciss_ioctl.h>
#include <linux/string.h>
#include <linux/bitmap.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/kthread.h>
#include "hpsa_cmd.h"
#include "hpsa.h"
diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
index df6bff7366cf..89700cbca16e 100644
--- a/drivers/scsi/iscsi_boot_sysfs.c
+++ b/drivers/scsi/iscsi_boot_sysfs.c
@@ -64,7 +64,8 @@ static void iscsi_boot_kobj_release(struct kobject *kobj)
struct iscsi_boot_kobj *boot_kobj =
container_of(kobj, struct iscsi_boot_kobj, kobj);
- kfree(boot_kobj->data);
+ if (boot_kobj->release)
+ boot_kobj->release(boot_kobj->data);
kfree(boot_kobj);
}
@@ -305,7 +306,8 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
struct attribute_group *attr_group,
const char *name, int index, void *data,
ssize_t (*show) (void *data, int type, char *buf),
- mode_t (*is_visible) (void *data, int type))
+ mode_t (*is_visible) (void *data, int type),
+ void (*release) (void *data))
{
struct iscsi_boot_kobj *boot_kobj;
@@ -323,6 +325,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
boot_kobj->data = data;
boot_kobj->show = show;
boot_kobj->is_visible = is_visible;
+ boot_kobj->release = release;
if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
/*
@@ -331,7 +334,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
* the boot kobj was not setup and the normal release
* path is not being run.
*/
- boot_kobj->data = NULL;
+ boot_kobj->release = NULL;
kobject_put(&boot_kobj->kobj);
return NULL;
}
@@ -357,6 +360,7 @@ static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
* @data: driver specific data for target
* @show: attr show function
* @is_visible: attr visibility function
+ * @release: release function
*
* Note: The boot sysfs lib will free the data passed in for the caller
* when all refs to the target kobject have been released.
@@ -365,10 +369,12 @@ struct iscsi_boot_kobj *
iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
void *data,
ssize_t (*show) (void *data, int type, char *buf),
- mode_t (*is_visible) (void *data, int type))
+ mode_t (*is_visible) (void *data, int type),
+ void (*release) (void *data))
{
return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
- "target%d", index, data, show, is_visible);
+ "target%d", index, data, show, is_visible,
+ release);
}
EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
@@ -379,6 +385,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
* @data: driver specific data
* @show: attr show function
* @is_visible: attr visibility function
+ * @release: release function
*
* Note: The boot sysfs lib will free the data passed in for the caller
* when all refs to the initiator kobject have been released.
@@ -387,12 +394,13 @@ struct iscsi_boot_kobj *
iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
void *data,
ssize_t (*show) (void *data, int type, char *buf),
- mode_t (*is_visible) (void *data, int type))
+ mode_t (*is_visible) (void *data, int type),
+ void (*release) (void *data))
{
return iscsi_boot_create_kobj(boot_kset,
&iscsi_boot_initiator_attr_group,
"initiator", index, data, show,
- is_visible);
+ is_visible, release);
}
EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
@@ -403,6 +411,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
* @data: driver specific data
* @show: attr show function
* @is_visible: attr visibility function
+ * @release: release function
*
* Note: The boot sysfs lib will free the data passed in for the caller
* when all refs to the ethernet kobject have been released.
@@ -411,12 +420,13 @@ struct iscsi_boot_kobj *
iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
void *data,
ssize_t (*show) (void *data, int type, char *buf),
- mode_t (*is_visible) (void *data, int type))
+ mode_t (*is_visible) (void *data, int type),
+ void (*release) (void *data))
{
return iscsi_boot_create_kobj(boot_kset,
&iscsi_boot_ethernet_attr_group,
"ethernet%d", index, data, show,
- is_visible);
+ is_visible, release);
}
EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
@@ -472,6 +482,9 @@ void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
{
struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
+ if (!boot_kset)
+ return;
+
list_for_each_entry_safe(boot_kobj, tmp_kobj,
&boot_kset->kobj_list, list)
iscsi_boot_remove_kobj(boot_kobj);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 3df985305f69..7724414588fa 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -107,10 +107,12 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
* If the socket is in CLOSE or CLOSE_WAIT we should
* not close the connection if there is still some
* data pending.
+ *
+ * Must be called with sk_callback_lock.
*/
static inline int iscsi_sw_sk_state_check(struct sock *sk)
{
- struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+ struct iscsi_conn *conn = sk->sk_user_data;
if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) &&
!atomic_read(&sk->sk_rmem_alloc)) {
@@ -123,11 +125,17 @@ static inline int iscsi_sw_sk_state_check(struct sock *sk)
static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
{
- struct iscsi_conn *conn = sk->sk_user_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct iscsi_conn *conn;
+ struct iscsi_tcp_conn *tcp_conn;
read_descriptor_t rd_desc;
read_lock(&sk->sk_callback_lock);
+ conn = sk->sk_user_data;
+ if (!conn) {
+ read_unlock(&sk->sk_callback_lock);
+ return;
+ }
+ tcp_conn = conn->dd_data;
/*
* Use rd_desc to pass 'conn' to iscsi_tcp_recv.
@@ -141,11 +149,10 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
iscsi_sw_sk_state_check(sk);
- read_unlock(&sk->sk_callback_lock);
-
/* If we had to (atomically) map a highmem page,
* unmap it now. */
iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
+ read_unlock(&sk->sk_callback_lock);
}
static void iscsi_sw_tcp_state_change(struct sock *sk)
@@ -157,8 +164,11 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
void (*old_state_change)(struct sock *);
read_lock(&sk->sk_callback_lock);
-
- conn = (struct iscsi_conn*)sk->sk_user_data;
+ conn = sk->sk_user_data;
+ if (!conn) {
+ read_unlock(&sk->sk_callback_lock);
+ return;
+ }
session = conn->session;
iscsi_sw_sk_state_check(sk);
@@ -178,11 +188,25 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
**/
static void iscsi_sw_tcp_write_space(struct sock *sk)
{
- struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ struct iscsi_conn *conn;
+ struct iscsi_tcp_conn *tcp_conn;
+ struct iscsi_sw_tcp_conn *tcp_sw_conn;
+ void (*old_write_space)(struct sock *);
+
+ read_lock_bh(&sk->sk_callback_lock);
+ conn = sk->sk_user_data;
+ if (!conn) {
+ read_unlock_bh(&sk->sk_callback_lock);
+ return;
+ }
+
+ tcp_conn = conn->dd_data;
+ tcp_sw_conn = tcp_conn->dd_data;
+ old_write_space = tcp_sw_conn->old_write_space;
+ read_unlock_bh(&sk->sk_callback_lock);
+
+ old_write_space(sk);
- tcp_sw_conn->old_write_space(sk);
ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
iscsi_conn_queue_work(conn);
}
@@ -592,20 +616,17 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
/* userspace may have goofed up and not bound us */
if (!sock)
return;
- /*
- * Make sure our recv side is stopped.
- * Older tools called conn stop before ep_disconnect
- * so IO could still be coming in.
- */
- write_lock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
- write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
sock->sk->sk_err = EIO;
wake_up_interruptible(sk_sleep(sock->sk));
- iscsi_conn_stop(cls_conn, flag);
+ /* stop xmit side */
+ iscsi_suspend_tx(conn);
+
+ /* stop recv side and release socket */
iscsi_sw_tcp_release_conn(conn);
+
+ iscsi_conn_stop(cls_conn, flag);
}
static int
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 3b8a6451ea28..f5a0665b6773 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -965,8 +965,30 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
sp = &ep->seq;
if (sp->id != fh->fh_seq_id) {
atomic_inc(&mp->stats.seq_not_found);
- reject = FC_RJT_SEQ_ID; /* sequence/exch should exist */
- goto rel;
+ if (f_ctl & FC_FC_END_SEQ) {
+ /*
+ * Update sequence_id based on incoming last
+ * frame of sequence exchange. This is needed
+ * for FCoE target where DDP has been used
+ * on target where, stack is indicated only
+ * about last frame's (payload _header) header.
+ * Whereas "seq_id" which is part of
+ * frame_header is allocated by initiator
+ * which is totally different from "seq_id"
+ * allocated when XFER_RDY was sent by target.
+ * To avoid false -ve which results into not
+ * sending RSP, hence write request on other
+ * end never finishes.
+ */
+ spin_lock_bh(&ep->ex_lock);
+ sp->ssb_stat |= SSB_ST_RESP;
+ sp->id = fh->fh_seq_id;
+ spin_unlock_bh(&ep->ex_lock);
+ } else {
+ /* sequence/exch should exist */
+ reject = FC_RJT_SEQ_ID;
+ goto rel;
+ }
}
}
WARN_ON(ep != fc_seq_exch(sp));
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 389ab80aef0a..e008b1673507 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1025,6 +1025,8 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN);
}
fc_lport_state_enter(lport, LPORT_ST_RESET);
+ fc_host_post_event(lport->host, fc_get_event_number(),
+ FCH_EVT_LIPRESET, 0);
fc_vports_linkchange(lport);
fc_lport_reset_locked(lport);
if (lport->link_up)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 49e1ccca09d5..760db7619446 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -153,18 +153,6 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
}
/**
- * fc_rport_free_rcu() - Free a remote port
- * @rcu: The rcu_head structure inside the remote port
- */
-static void fc_rport_free_rcu(struct rcu_head *rcu)
-{
- struct fc_rport_priv *rdata;
-
- rdata = container_of(rcu, struct fc_rport_priv, rcu);
- kfree(rdata);
-}
-
-/**
* fc_rport_destroy() - Free a remote port after last reference is released
* @kref: The remote port's kref
*/
@@ -173,7 +161,7 @@ static void fc_rport_destroy(struct kref *kref)
struct fc_rport_priv *rdata;
rdata = container_of(kref, struct fc_rport_priv, kref);
- call_rcu(&rdata->rcu, fc_rport_free_rcu);
+ kfree_rcu(rdata, rcu);
}
/**
@@ -801,6 +789,20 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
switch (rdata->rp_state) {
case RPORT_ST_INIT:
+ /*
+ * If received the FLOGI request on RPORT which is INIT state
+ * (means not transition to FLOGI either fc_rport timeout
+ * function didn;t trigger or this end hasn;t received
+ * beacon yet from other end. In that case only, allow RPORT
+ * state machine to continue, otherwise fall through which
+ * causes the code to send reject response.
+ * NOTE; Not checking for FIP->state such as VNMP_UP or
+ * VNMP_CLAIM because if FIP state is not one of those,
+ * RPORT wouldn;t have created and 'rport_lookup' would have
+ * failed anyway in that case.
+ */
+ if (lport->point_to_multipoint)
+ break;
case RPORT_ST_DELETE:
mutex_unlock(&rdata->rp_mutex);
rjt_data.reason = ELS_RJT_FIP;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 0c550d5b9133..d7a4120034a2 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -169,7 +169,7 @@ void iscsi_prep_data_out_pdu(struct iscsi_task *task, struct iscsi_r2t_info *r2t
hdr->datasn = cpu_to_be32(r2t->datasn);
r2t->datasn++;
hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
- memcpy(hdr->lun, task->lun, sizeof(hdr->lun));
+ hdr->lun = task->lun;
hdr->itt = task->hdr_itt;
hdr->exp_statsn = r2t->exp_statsn;
hdr->offset = cpu_to_be32(r2t->data_offset + r2t->sent);
@@ -296,7 +296,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
/*
* Allow PDUs for unrelated LUNs
*/
- hdr_lun = scsilun_to_int((struct scsi_lun *)tmf->lun);
+ hdr_lun = scsilun_to_int(&tmf->lun);
if (hdr_lun != task->sc->device->lun)
return 0;
/* fall through */
@@ -389,8 +389,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
return rc;
hdr->opcode = ISCSI_OP_SCSI_CMD;
hdr->flags = ISCSI_ATTR_SIMPLE;
- int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
- memcpy(task->lun, hdr->lun, sizeof(task->lun));
+ int_to_scsilun(sc->device->lun, &hdr->lun);
+ task->lun = hdr->lun;
hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
cmd_len = sc->cmd_len;
if (cmd_len < ISCSI_CDB_SIZE)
@@ -968,7 +968,7 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
hdr.flags = ISCSI_FLAG_CMD_FINAL;
if (rhdr) {
- memcpy(hdr.lun, rhdr->lun, 8);
+ hdr.lun = rhdr->lun;
hdr.ttt = rhdr->ttt;
hdr.itt = RESERVED_ITT;
} else
@@ -2092,7 +2092,7 @@ static void iscsi_prep_abort_task_pdu(struct iscsi_task *task,
hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK;
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
- memcpy(hdr->lun, task->lun, sizeof(hdr->lun));
+ hdr->lun = task->lun;
hdr->rtt = task->hdr_itt;
hdr->refcmdsn = task->cmdsn;
}
@@ -2233,7 +2233,7 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK;
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
- int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ int_to_scsilun(sc->device->lun, &hdr->lun);
hdr->rtt = RESERVED_ITT;
}
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index e98ae33f1295..09b232fd9a1b 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -1084,7 +1084,8 @@ iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
struct iscsi_cls_conn *cls_conn;
struct iscsi_tcp_conn *tcp_conn;
- cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn), conn_idx);
+ cls_conn = iscsi_conn_setup(cls_session,
+ sizeof(*tcp_conn) + dd_data_size, conn_idx);
if (!cls_conn)
return NULL;
conn = cls_conn->dd_data;
@@ -1096,22 +1097,13 @@ iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
tcp_conn = conn->dd_data;
tcp_conn->iscsi_conn = conn;
-
- tcp_conn->dd_data = kzalloc(dd_data_size, GFP_KERNEL);
- if (!tcp_conn->dd_data) {
- iscsi_conn_teardown(cls_conn);
- return NULL;
- }
+ tcp_conn->dd_data = conn->dd_data + sizeof(*tcp_conn);
return cls_conn;
}
EXPORT_SYMBOL_GPL(iscsi_tcp_conn_setup);
void iscsi_tcp_conn_teardown(struct iscsi_cls_conn *cls_conn)
{
- struct iscsi_conn *conn = cls_conn->dd_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-
- kfree(tcp_conn->dd_data);
iscsi_conn_teardown(cls_conn);
}
EXPORT_SYMBOL_GPL(iscsi_tcp_conn_teardown);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index ffe82d169b40..30b25c5fdd7e 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1147,7 +1147,8 @@ static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
{
char mybuf[64];
char *pbuf, *step_str;
- int bsize, i;
+ int i;
+ size_t bsize;
/* Protect copy from user */
if (!access_ok(VERIFY_READ, buf, nbytes))
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 9059524cf225..ab4c4d651d0c 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -2955,18 +2955,18 @@ typedef struct _SLI2_RDSC {
typedef struct _PCB {
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t type:8;
-#define TYPE_NATIVE_SLI2 0x01;
+#define TYPE_NATIVE_SLI2 0x01
uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2 0x01;
+#define FEATURE_INITIAL_SLI2 0x01
uint32_t rsvd:12;
uint32_t maxRing:4;
#else /* __LITTLE_ENDIAN_BITFIELD */
uint32_t maxRing:4;
uint32_t rsvd:12;
uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2 0x01;
+#define FEATURE_INITIAL_SLI2 0x01
uint32_t type:8;
-#define TYPE_NATIVE_SLI2 0x01;
+#define TYPE_NATIVE_SLI2 0x01
#endif
uint32_t mailBoxSize;
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index bf2a1c516293..af3a6af97cc7 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -215,13 +215,6 @@ static int __init mac_scsi_setup(char *str) {
__setup("mac5380=", mac_scsi_setup);
/*
- * If you want to find the instance with (k)gdb ...
- */
-#if NDEBUG
-static struct Scsi_Host *default_instance;
-#endif
-
-/*
* Function : int macscsi_detect(struct scsi_host_template * tpnt)
*
* Purpose : initializes mac NCR5380 driver based on the
@@ -233,7 +226,7 @@ static struct Scsi_Host *default_instance;
*
*/
-int macscsi_detect(struct scsi_host_template * tpnt)
+int __init macscsi_detect(struct scsi_host_template * tpnt)
{
static int called = 0;
int flags = 0;
@@ -268,10 +261,7 @@ int macscsi_detect(struct scsi_host_template * tpnt)
/* Once we support multiple 5380s (e.g. DuoDock) we'll do
something different here */
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-#if NDEBUG
- default_instance = instance;
-#endif
-
+
if (macintosh_config->ident == MAC_MODEL_IIFX) {
mac_scsi_regp = via1+0x8000;
mac_scsi_drq = via1+0xE000;
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index a3e60385787f..3105d5e8d908 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -8,7 +8,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.17
+ * mpi2.h Version: 02.00.18
*
* Version History
* ---------------
@@ -64,6 +64,8 @@
* 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT.
* Added alternative defines for the SGE Direction bit.
* 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
* --------------------------------------------------------------------------
*/
@@ -89,7 +91,7 @@
#define MPI2_VERSION_02_00 (0x0200)
/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x11)
+#define MPI2_HEADER_VERSION_UNIT (0x12)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@@ -1060,10 +1062,14 @@ typedef struct _MPI2_IEEE_SGE_UNION
#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
+ /* IEEE Simple Element only */
#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
+ /* IEEE Simple Element only */
#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
-
+ /* IEEE Simple Element only */
+#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR (0x03)
+ /* IEEE Chain Element only */
/****************************************************************************
* IEEE SGE operation Macros
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index f5b9c766e28f..61475a6480e3 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -6,7 +6,7 @@
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
- * mpi2_cnfg.h Version: 02.00.16
+ * mpi2_cnfg.h Version: 02.00.17
*
* Version History
* ---------------
@@ -127,6 +127,13 @@
* Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
* 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing)
* defines.
+ * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to
+ * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
+ * the Pinout field.
+ * Added BoardTemperature and BoardTemperatureUnits fields
+ * to MPI2_CONFIG_PAGE_IO_UNIT_7.
+ * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
+ * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
* --------------------------------------------------------------------------
*/
@@ -210,6 +217,7 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17)
#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19)
+#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A)
/*****************************************************************************
@@ -612,23 +620,31 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
U32 Pinout; /* 0x00 */
U8 Connector[16]; /* 0x04 */
U8 Location; /* 0x14 */
- U8 Reserved1; /* 0x15 */
+ U8 ReceptacleID; /* 0x15 */
U16 Slot; /* 0x16 */
U32 Reserved2; /* 0x18 */
} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
/* defines for the Pinout field */
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100)
-#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x00000002)
-#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001)
+#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00)
+#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8)
+
+#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF)
+#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00)
+#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02)
+#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04)
+#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08)
+#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C)
+#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D)
/* defines for the Location field */
#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
@@ -662,7 +678,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7
MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
-#define MPI2_MANUFACTURING7_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING7_PAGEVERSION (0x01)
/* defines for the Flags field */
#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
@@ -849,11 +865,13 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
U16 IOCTemperature; /* 0x10 */
U8 IOCTemperatureUnits; /* 0x12 */
U8 IOCSpeed; /* 0x13 */
- U32 Reserved3; /* 0x14 */
+ U16 BoardTemperature; /* 0x14 */
+ U8 BoardTemperatureUnits; /* 0x16 */
+ U8 Reserved3; /* 0x17 */
} MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t;
-#define MPI2_IOUNITPAGE7_PAGEVERSION (0x01)
+#define MPI2_IOUNITPAGE7_PAGEVERSION (0x02)
/* defines for IO Unit Page 7 PCIeWidth field */
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01)
@@ -881,7 +899,6 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008)
#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004)
-
/* defines for IO Unit Page 7 IOCTemperatureUnits field */
#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00)
#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01)
@@ -893,6 +910,11 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04)
#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08)
+/* defines for IO Unit Page 7 BoardTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02)
+
/****************************************************************************
@@ -2799,5 +2821,25 @@ typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03)
+/****************************************************************************
+* Extended Manufacturing Config Pages
+****************************************************************************/
+
+/*
+ * Generic structure to use for product-specific extended manufacturing pages
+ * (currently Extended Manufacturing Page 40 through Extended Manufacturing
+ * Page 60).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 ProductSpecificInfo; /* 0x08 */
+} MPI2_CONFIG_PAGE_EXT_MAN_PS,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
+ Mpi2ExtManufacturingPagePS_t,
+ MPI2_POINTER pMpi2ExtManufacturingPagePS_t;
+
+/* PageVersion should be provided by product-specific code */
+
#endif
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
index 165454d52591..de90162413c2 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -6,7 +6,7 @@
* Title: MPI SCSI initiator mode messages and structures
* Creation Date: June 23, 2006
*
- * mpi2_init.h Version: 02.00.10
+ * mpi2_init.h Version: 02.00.11
*
* Version History
* ---------------
@@ -33,6 +33,7 @@
* Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
* 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it.
* 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request.
+ * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
* --------------------------------------------------------------------------
*/
@@ -139,6 +140,9 @@ typedef struct _MPI2_SCSI_IO_REQUEST
#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4)
#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0)
+/* number of SGLOffset fields */
+#define MPI2_SCSIIO_NUM_SGLOFFSETS (4)
+
/* SCSI IO IoFlags bits */
/* Large CDB Address Space */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
index 761cbdb8a033..1f0c190d336e 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -6,7 +6,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: October 11, 2006
*
- * mpi2_ioc.h Version: 02.00.15
+ * mpi2_ioc.h Version: 02.00.16
*
* Version History
* ---------------
@@ -103,6 +103,7 @@
* defines.
* 05-12-10 02.00.15 Marked Task Set Full Event as obsolete.
* Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
+ * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
* --------------------------------------------------------------------------
*/
@@ -1032,6 +1033,7 @@ typedef struct _MPI2_FW_DOWNLOAD_REQUEST
#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A)
#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
+#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
/* FWDownload TransactionContext Element */
typedef struct _MPI2_FW_DOWNLOAD_TCSGE
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index efa0255491c2..83035bd1c489 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -94,7 +94,7 @@ module_param(diag_buffer_enable, int, 0);
MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
"(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
-int mpt2sas_fwfault_debug;
+static int mpt2sas_fwfault_debug;
MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
"and halt firmware - (default=0)");
@@ -857,7 +857,7 @@ _base_interrupt(int irq, void *bus_id)
completed_cmds = 0;
cb_idx = 0xFF;
do {
- rd.word = rpf->Words;
+ rd.word = le64_to_cpu(rpf->Words);
if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
goto out;
reply = 0;
@@ -906,7 +906,7 @@ _base_interrupt(int irq, void *bus_id)
next:
- rpf->Words = ULLONG_MAX;
+ rpf->Words = cpu_to_le64(ULLONG_MAX);
ioc->reply_post_host_index = (ioc->reply_post_host_index ==
(ioc->reply_post_queue_depth - 1)) ? 0 :
ioc->reply_post_host_index + 1;
@@ -1740,9 +1740,11 @@ _base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
static void
_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
{
- if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_INTEL &&
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008) {
+ if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
+ return;
+ switch (ioc->pdev->device) {
+ case MPI2_MFGPAGE_DEVID_SAS2008:
switch (ioc->pdev->subsystem_device) {
case MPT2SAS_INTEL_RMS2LL080_SSDID:
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -1752,7 +1754,20 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
MPT2SAS_INTEL_RMS2LL040_BRANDING);
break;
+ default:
+ break;
+ }
+ case MPI2_MFGPAGE_DEVID_SAS2308_2:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_INTEL_RS25GB008_SSDID:
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RS25GB008_BRANDING);
+ break;
+ default:
+ break;
}
+ default:
+ break;
}
}
@@ -1817,7 +1832,9 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
char desc[16];
u8 revision;
u32 iounit_pg1_flags;
+ u32 bios_version;
+ bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
strncpy(desc, ioc->manu_pg0.ChipName, 16);
printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
@@ -1828,10 +1845,10 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
(ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
ioc->facts.FWVersion.Word & 0x000000FF,
revision,
- (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24,
- (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16,
- (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
- ioc->bios_pg3.BiosVersion & 0x000000FF);
+ (bios_version & 0xFF000000) >> 24,
+ (bios_version & 0x00FF0000) >> 16,
+ (bios_version & 0x0000FF00) >> 8,
+ bios_version & 0x000000FF);
_base_display_dell_branding(ioc);
_base_display_intel_branding(ioc);
@@ -2150,7 +2167,7 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
static int
_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
{
- Mpi2IOCFactsReply_t *facts;
+ struct mpt2sas_facts *facts;
u32 queue_size, queue_diff;
u16 max_sge_elements;
u16 num_of_reply_frames;
@@ -2783,7 +2800,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
int i;
u8 failed;
u16 dummy;
- u32 *mfp;
+ __le32 *mfp;
/* make sure doorbell is not in use */
if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
@@ -2871,7 +2888,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
writel(0, &ioc->chip->HostInterruptStatus);
if (ioc->logging_level & MPT_DEBUG_INIT) {
- mfp = (u32 *)reply;
+ mfp = (__le32 *)reply;
printk(KERN_INFO "\toffset:data\n");
for (i = 0; i < reply_bytes/4; i++)
printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
@@ -3097,7 +3114,8 @@ static int
_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
{
Mpi2PortFactsRequest_t mpi_request;
- Mpi2PortFactsReply_t mpi_reply, *pfacts;
+ Mpi2PortFactsReply_t mpi_reply;
+ struct mpt2sas_port_facts *pfacts;
int mpi_reply_sz, mpi_request_sz, r;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -3139,7 +3157,8 @@ static int
_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
{
Mpi2IOCFactsRequest_t mpi_request;
- Mpi2IOCFactsReply_t mpi_reply, *facts;
+ Mpi2IOCFactsReply_t mpi_reply;
+ struct mpt2sas_facts *facts;
int mpi_reply_sz, mpi_request_sz, r;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -3225,17 +3244,6 @@ _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);
- /* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was
- * removed and made reserved. For those with older firmware will need
- * this fix. It was decided that the Reply and Request frame sizes are
- * the same.
- */
- if ((ioc->facts.HeaderVersion >> 8) < 0xA) {
- mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz);
-/* mpi_request.SystemReplyFrameSize =
- * cpu_to_le16(ioc->reply_sz);
- */
- }
mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
mpi_request.ReplyDescriptorPostQueueDepth =
@@ -3243,25 +3251,17 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
mpi_request.ReplyFreeQueueDepth =
cpu_to_le16(ioc->reply_free_queue_depth);
-#if BITS_PER_LONG > 32
mpi_request.SenseBufferAddressHigh =
- cpu_to_le32(ioc->sense_dma >> 32);
+ cpu_to_le32((u64)ioc->sense_dma >> 32);
mpi_request.SystemReplyAddressHigh =
- cpu_to_le32(ioc->reply_dma >> 32);
+ cpu_to_le32((u64)ioc->reply_dma >> 32);
mpi_request.SystemRequestFrameBaseAddress =
- cpu_to_le64(ioc->request_dma);
+ cpu_to_le64((u64)ioc->request_dma);
mpi_request.ReplyFreeQueueAddress =
- cpu_to_le64(ioc->reply_free_dma);
+ cpu_to_le64((u64)ioc->reply_free_dma);
mpi_request.ReplyDescriptorPostQueueAddress =
- cpu_to_le64(ioc->reply_post_free_dma);
-#else
- mpi_request.SystemRequestFrameBaseAddress =
- cpu_to_le32(ioc->request_dma);
- mpi_request.ReplyFreeQueueAddress =
- cpu_to_le32(ioc->reply_free_dma);
- mpi_request.ReplyDescriptorPostQueueAddress =
- cpu_to_le32(ioc->reply_post_free_dma);
-#endif
+ cpu_to_le64((u64)ioc->reply_post_free_dma);
+
/* This time stamp specifies number of milliseconds
* since epoch ~ midnight January 1, 1970.
@@ -3271,10 +3271,10 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
(current_time.tv_usec / 1000));
if (ioc->logging_level & MPT_DEBUG_INIT) {
- u32 *mfp;
+ __le32 *mfp;
int i;
- mfp = (u32 *)&mpi_request;
+ mfp = (__le32 *)&mpi_request;
printk(KERN_INFO "\toffset:data\n");
for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
@@ -3759,7 +3759,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
/* initialize Reply Post Free Queue */
for (i = 0; i < ioc->reply_post_queue_depth; i++)
- ioc->reply_post_free[i].Words = ULLONG_MAX;
+ ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
r = _base_send_ioc_init(ioc, sleep_flag);
if (r)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index dcc289c25459..8d5be2120c63 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 "08.100.00.02"
-#define MPT2SAS_MAJOR_VERSION 08
+#define MPT2SAS_DRIVER_VERSION "09.100.00.00"
+#define MPT2SAS_MAJOR_VERSION 09
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
-#define MPT2SAS_RELEASE_VERSION 02
+#define MPT2SAS_RELEASE_VERSION 00
/*
* Set MPT2SAS_SG_DEPTH value based on user input.
@@ -161,12 +161,15 @@
"Intel Integrated RAID Module RMS2LL080"
#define MPT2SAS_INTEL_RMS2LL040_BRANDING \
"Intel Integrated RAID Module RMS2LL040"
+#define MPT2SAS_INTEL_RS25GB008_BRANDING \
+ "Intel(R) RAID Controller RS25GB008"
/*
* Intel HBA SSDIDs
*/
#define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E
#define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F
+#define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000
/*
@@ -541,6 +544,63 @@ struct _tr_list {
typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
+/* IOC Facts and Port Facts converted from little endian to cpu */
+union mpi2_version_union {
+ MPI2_VERSION_STRUCT Struct;
+ u32 Word;
+};
+
+struct mpt2sas_facts {
+ u16 MsgVersion;
+ u16 HeaderVersion;
+ u8 IOCNumber;
+ u8 VP_ID;
+ u8 VF_ID;
+ u16 IOCExceptions;
+ u16 IOCStatus;
+ u32 IOCLogInfo;
+ u8 MaxChainDepth;
+ u8 WhoInit;
+ u8 NumberOfPorts;
+ u8 MaxMSIxVectors;
+ u16 RequestCredit;
+ u16 ProductID;
+ u32 IOCCapabilities;
+ union mpi2_version_union FWVersion;
+ u16 IOCRequestFrameSize;
+ u16 Reserved3;
+ u16 MaxInitiators;
+ u16 MaxTargets;
+ u16 MaxSasExpanders;
+ u16 MaxEnclosures;
+ u16 ProtocolFlags;
+ u16 HighPriorityCredit;
+ u16 MaxReplyDescriptorPostQueueDepth;
+ u8 ReplyFrameSize;
+ u8 MaxVolumes;
+ u16 MaxDevHandle;
+ u16 MaxPersistentEntries;
+ u16 MinDevHandle;
+};
+
+struct mpt2sas_port_facts {
+ u8 PortNumber;
+ u8 VP_ID;
+ u8 VF_ID;
+ u8 PortType;
+ u16 MaxPostedCmdBuffers;
+};
+
+/**
+ * enum mutex_type - task management mutex type
+ * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
+ * @TM_MUTEX_ON: mutex is required
+ */
+enum mutex_type {
+ TM_MUTEX_OFF = 0,
+ TM_MUTEX_ON = 1,
+};
+
/**
* struct MPT2SAS_ADAPTER - per adapter struct
* @list: ioc_list
@@ -703,6 +763,7 @@ struct MPT2SAS_ADAPTER {
/* misc flags */
int aen_event_read_flag;
u8 broadcast_aen_busy;
+ u16 broadcast_aen_pending;
u8 shost_recovery;
struct mutex reset_in_progress_mutex;
@@ -749,8 +810,8 @@ struct MPT2SAS_ADAPTER {
u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
/* static config pages */
- Mpi2IOCFactsReply_t facts;
- Mpi2PortFactsReply_t *pfacts;
+ struct mpt2sas_facts facts;
+ struct mpt2sas_port_facts *pfacts;
Mpi2ManufacturingPage0_t manu_pg0;
Mpi2BiosPage2_t bios_pg2;
Mpi2BiosPage3_t bios_pg3;
@@ -840,7 +901,7 @@ struct MPT2SAS_ADAPTER {
/* reply free queue */
u16 reply_free_queue_depth;
- u32 *reply_free;
+ __le32 *reply_free;
dma_addr_t reply_free_dma;
struct dma_pool *reply_free_dma_pool;
u32 reply_free_host_index;
@@ -932,8 +993,8 @@ void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
u32 reply);
int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- uint channel, uint id, uint lun, u8 type, u16 smid_task,
- ulong timeout, struct scsi_cmnd *scmd);
+ uint channel, uint id, uint lun, u8 type, u16 smid_task,
+ ulong timeout, unsigned long serial_number, enum mutex_type m_type);
void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 437c2d94c45a..38ed0260959d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -994,7 +994,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
mpt2sas_scsih_issue_tm(ioc,
le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
- NULL);
+ 0, TM_MUTEX_ON);
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
} else
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
@@ -2706,13 +2706,13 @@ static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
_ctl_ioc_reset_count_show, NULL);
struct DIAG_BUFFER_START {
- u32 Size;
- u32 DiagVersion;
+ __le32 Size;
+ __le32 DiagVersion;
u8 BufferType;
u8 Reserved[3];
- u32 Reserved1;
- u32 Reserved2;
- u32 Reserved3;
+ __le32 Reserved1;
+ __le32 Reserved2;
+ __le32 Reserved3;
};
/**
* _ctl_host_trace_buffer_size_show - host buffer size (trace only)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
index 3dcddfeb6f4c..9731f8e661bf 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_debug.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h
@@ -164,7 +164,7 @@ static inline void
_debug_dump_mf(void *mpi_request, int sz)
{
int i;
- u32 *mfp = (u32 *)mpi_request;
+ __le32 *mfp = (__le32 *)mpi_request;
printk(KERN_INFO "mf:\n\t");
for (i = 0; i < sz; i++) {
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index a7dbc6825f5f..939f283d0c28 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -94,6 +94,10 @@ static u32 logging_level;
MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
"(default=0)");
+static ushort max_sectors = 0xFFFF;
+module_param(max_sectors, ushort, 0);
+MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 8192 default=8192");
+
/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
#define MPT2SAS_MAX_LUN (16895)
static int max_lun = MPT2SAS_MAX_LUN;
@@ -1956,7 +1960,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
case MPI2_RAID_VOL_TYPE_RAID1E:
qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
if (ioc->manu_pg10.OEMIdentifier &&
- (ioc->manu_pg10.GenericFlags0 &
+ (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
MFG10_GF0_R10_DISPLAY) &&
!(raid_device->num_pds % 2))
r_level = "RAID10";
@@ -2236,6 +2240,8 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
* @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
* @smid_task: smid assigned to the task
* @timeout: timeout in seconds
+ * @serial_number: the serial_number from scmd
+ * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
* Context: user
*
* A generic API for sending task management requests to firmware.
@@ -2247,17 +2253,18 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
int
mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
- struct scsi_cmnd *scmd)
+ unsigned long serial_number, enum mutex_type m_type)
{
Mpi2SCSITaskManagementRequest_t *mpi_request;
Mpi2SCSITaskManagementReply_t *mpi_reply;
u16 smid = 0;
u32 ioc_state;
unsigned long timeleft;
- struct scsi_cmnd *scmd_lookup;
+ struct scsiio_tracker *scsi_lookup = NULL;
int rc;
- mutex_lock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_lock(&ioc->tm_cmds.mutex);
if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
__func__, ioc->name);
@@ -2277,18 +2284,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
if (ioc_state & MPI2_DOORBELL_USED) {
dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
"active!\n", ioc->name));
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
goto err_out;
}
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
mpt2sas_base_fault_info(ioc, ioc_state &
MPI2_DOORBELL_DATA_MASK);
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
goto err_out;
}
@@ -2300,6 +2307,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
goto err_out;
}
+ if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+ scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
+
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
" task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
smid_task));
@@ -2307,6 +2317,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
ioc->tm_cmds.smid = smid;
memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+ memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = type;
@@ -2322,9 +2333,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
_debug_dump_mf(mpi_request,
sizeof(Mpi2SCSITaskManagementRequest_t)/4);
if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
mpt2sas_scsih_clear_tm_flag(ioc, handle);
goto err_out;
@@ -2346,20 +2357,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
}
}
- /* sanity check:
- * Check to see the commands were terminated.
- * This is only needed for eh callbacks, hence the scmd check.
- */
- rc = FAILED;
- if (scmd == NULL)
- goto bypass_sanity_checks;
switch (type) {
case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
- scmd_lookup = _scsih_scsi_lookup_get(ioc, smid_task);
- if (scmd_lookup)
- rc = FAILED;
- else
- rc = SUCCESS;
+ rc = SUCCESS;
+ if (scsi_lookup->scmd == NULL)
+ break;
+ rc = FAILED;
break;
case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2369,24 +2372,31 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
rc = SUCCESS;
break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
rc = FAILED;
else
rc = SUCCESS;
break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
+ rc = SUCCESS;
+ break;
+ default:
+ rc = FAILED;
+ break;
}
- bypass_sanity_checks:
-
mpt2sas_scsih_clear_tm_flag(ioc, handle);
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_unlock(&ioc->tm_cmds.mutex);
return rc;
err_out:
- mutex_unlock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_unlock(&ioc->tm_cmds.mutex);
return rc;
}
@@ -2496,7 +2506,8 @@ _scsih_abort(struct scsi_cmnd *scmd)
handle = sas_device_priv_data->sas_target->handle;
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, scmd);
+ MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
+ scmd->serial_number, TM_MUTEX_ON);
out:
sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
@@ -2557,7 +2568,8 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, scmd);
+ MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
+ TM_MUTEX_ON);
out:
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
@@ -2617,7 +2629,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
- 30, scmd);
+ 30, 0, TM_MUTEX_ON);
out:
starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
@@ -2750,6 +2762,31 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
}
/**
+ * _scsih_ublock_io_all_device - unblock every device
+ * @ioc: per adapter object
+ *
+ * change the device state from block to running
+ */
+static void
+_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (!sas_device_priv_data->block)
+ continue;
+ sas_device_priv_data->block = 0;
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
+ "handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle));
+ scsi_internal_device_unblock(sdev);
+ }
+}
+/**
* _scsih_ublock_io_device - set the device state to SDEV_RUNNING
* @ioc: per adapter object
* @handle: device handle
@@ -2779,6 +2816,34 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
}
/**
+ * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (sas_device_priv_data->block)
+ continue;
+ sas_device_priv_data->block = 1;
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
+ "handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle));
+ scsi_internal_device_block(sdev);
+ }
+}
+
+
+/**
* _scsih_block_io_device - set the device state to SDEV_BLOCK
* @ioc: per adapter object
* @handle: device handle
@@ -3698,7 +3763,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
return 0;
}
- if (ioc->pci_error_recovery) {
+ if (ioc->pci_error_recovery || ioc->remove_host) {
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
return 0;
@@ -4598,7 +4663,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
Mpi2SasEnclosurePage0_t enclosure_pg0;
u32 ioc_status;
u16 parent_handle;
- __le64 sas_address, sas_address_parent = 0;
+ u64 sas_address, sas_address_parent = 0;
int i;
unsigned long flags;
struct _sas_port *mpt2sas_port = NULL;
@@ -5380,9 +5445,10 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
break;
}
printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
- "\thandle(0x%04x), sas address(0x%016llx)", ioc->name,
- reason_str, le16_to_cpu(event_data->DevHandle),
- (unsigned long long)le64_to_cpu(event_data->SASAddress));
+ "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
+ ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
+ (unsigned long long)le64_to_cpu(event_data->SASAddress),
+ le16_to_cpu(event_data->TaskTag));
if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
event_data->ASC, event_data->ASCQ);
@@ -5404,7 +5470,7 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
{
struct MPT2SAS_TARGET *target_priv_data;
struct _sas_device *sas_device;
- __le64 sas_address;
+ u64 sas_address;
unsigned long flags;
Mpi2EventDataSasDeviceStatusChange_t *event_data =
fw_event->event_data;
@@ -5522,25 +5588,38 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
u32 termination_count;
u32 query_count;
Mpi2SCSITaskManagementReply_t *mpi_reply;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
-#endif
u16 ioc_status;
unsigned long flags;
int r;
+ u8 max_retries = 0;
+ u8 task_abort_retries;
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: "
- "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
- event_data->PortWidth));
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
+ mutex_lock(&ioc->tm_cmds.mutex);
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
+ "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
+ event_data->PortWidth));
+
+ _scsih_block_io_all_device(ioc);
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- ioc->broadcast_aen_busy = 0;
+ mpi_reply = ioc->tm_cmds.reply;
+broadcast_aen_retry:
+
+ /* sanity checks for retrying this loop */
+ if (max_retries++ == 5) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
+ ioc->name, __func__));
+ goto out;
+ } else if (max_retries > 1)
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
+ ioc->name, __func__, max_retries - 1));
+
termination_count = 0;
query_count = 0;
- mpi_reply = ioc->tm_cmds.reply;
for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+ if (ioc->ioc_reset_in_progress_status)
+ goto out;
scmd = _scsih_scsi_lookup_get(ioc, smid);
if (!scmd)
continue;
@@ -5561,34 +5640,90 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
lun = sas_device_priv_data->lun;
query_count++;
+ if (ioc->ioc_reset_in_progress_status)
+ goto out;
+
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
- MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL);
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
+ MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
+ TM_MUTEX_OFF);
+ if (r == FAILED) {
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: FAILED when sending "
+ "QUERY_TASK: scmd(%p)\n", scmd);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
& MPI2_IOCSTATUS_MASK;
- if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
- (mpi_reply->ResponseCode ==
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
+ "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
+ scmd);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
+
+ /* see if IO is still owned by IOC and target */
+ if (mpi_reply->ResponseCode ==
MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
mpi_reply->ResponseCode ==
- MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) {
+ MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
continue;
}
+ task_abort_retries = 0;
+ tm_retry:
+ if (task_abort_retries++ == 60) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "%s: ABORT_TASK: giving up\n", ioc->name,
+ __func__));
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
+
+ if (ioc->ioc_reset_in_progress_status)
+ goto out_no_lock;
+
r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
- scmd);
- if (r == FAILED)
- sdev_printk(KERN_WARNING, sdev, "task abort: FAILED "
+ scmd->serial_number, TM_MUTEX_OFF);
+ if (r == FAILED) {
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
"scmd(%p)\n", scmd);
+ goto tm_retry;
+ }
+
+ if (task_abort_retries > 1)
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
+ " scmd(%p)\n",
+ task_abort_retries - 1, scmd);
+
termination_count += le32_to_cpu(mpi_reply->TerminationCount);
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
}
+
+ if (ioc->broadcast_aen_pending) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
+ " pending AEN\n", ioc->name, __func__));
+ ioc->broadcast_aen_pending = 0;
+ goto broadcast_aen_retry;
+ }
+
+ out:
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ out_no_lock:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"%s - exit, query_count = %d termination_count = %d\n",
ioc->name, __func__, query_count, termination_count));
+
+ ioc->broadcast_aen_busy = 0;
+ if (!ioc->ioc_reset_in_progress_status)
+ _scsih_ublock_io_all_device(ioc);
+ mutex_unlock(&ioc->tm_cmds.mutex);
}
/**
@@ -6566,7 +6701,7 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
Mpi2ExpanderPage0_t expander_pg0;
Mpi2ConfigReply_t mpi_reply;
u16 ioc_status;
- __le64 sas_address;
+ u64 sas_address;
u16 handle;
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
@@ -6862,10 +6997,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
mpi_reply->EventData;
if (baen_data->Primitive !=
- MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
- ioc->broadcast_aen_busy)
+ MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
return 1;
- ioc->broadcast_aen_busy = 1;
+
+ if (ioc->broadcast_aen_busy) {
+ ioc->broadcast_aen_pending++;
+ return 1;
+ } else
+ ioc->broadcast_aen_busy = 1;
break;
}
@@ -7211,7 +7350,6 @@ _scsih_remove(struct pci_dev *pdev)
}
sas_remove_host(shost);
- _scsih_shutdown(pdev);
list_del(&ioc->list);
scsi_remove_host(shost);
scsi_host_put(shost);
@@ -7436,6 +7574,25 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
shost->transportt = mpt2sas_transport_template;
shost->unique_id = ioc->id;
+ if (max_sectors != 0xFFFF) {
+ if (max_sectors < 64) {
+ shost->max_sectors = 64;
+ printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+ "for max_sectors, range is 64 to 8192. Assigning "
+ "value of 64.\n", ioc->name, max_sectors);
+ } else if (max_sectors > 8192) {
+ shost->max_sectors = 8192;
+ printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+ "for max_sectors, range is 64 to 8192. Assigning "
+ "default value of 8192.\n", ioc->name,
+ max_sectors);
+ } else {
+ shost->max_sectors = max_sectors & 0xFFFE;
+ printk(MPT2SAS_INFO_FMT "The max_sectors value is "
+ "set to %d\n", ioc->name, shost->max_sectors);
+ }
+ }
+
if ((scsi_add_host(shost, &pdev->dev))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
@@ -7505,7 +7662,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- u32 device_state;
+ pci_power_t device_state;
mpt2sas_base_stop_watchdog(ioc);
scsi_block_requests(shost);
@@ -7532,7 +7689,7 @@ _scsih_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- u32 device_state = pdev->current_state;
+ pci_power_t device_state = pdev->current_state;
int r;
printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index cb1cdecbe0f8..15c798026217 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -299,7 +299,6 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
void *data_out = NULL;
dma_addr_t data_out_dma;
u32 sz;
- u64 *sas_address_le;
u16 wait_state_count;
if (ioc->shost_recovery || ioc->pci_error_recovery) {
@@ -372,8 +371,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- sas_address_le = (u64 *)&mpi_request->SASAddress;
- *sas_address_le = cpu_to_le64(sas_address);
+ mpi_request->SASAddress = cpu_to_le64(sas_address);
mpi_request->RequestDataLength =
cpu_to_le16(sizeof(struct rep_manu_request));
psge = &mpi_request->SGL;
@@ -1049,14 +1047,14 @@ struct phy_error_log_reply{
u8 function; /* 0x11 */
u8 function_result;
u8 response_length;
- u16 expander_change_count;
+ __be16 expander_change_count;
u8 reserved_1[3];
u8 phy_identifier;
u8 reserved_2[2];
- u32 invalid_dword;
- u32 running_disparity_error;
- u32 loss_of_dword_sync;
- u32 phy_reset_problem;
+ __be32 invalid_dword;
+ __be32 running_disparity_error;
+ __be32 loss_of_dword_sync;
+ __be32 phy_reset_problem;
};
/**
@@ -1085,7 +1083,6 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
void *data_out = NULL;
dma_addr_t data_out_dma;
u32 sz;
- u64 *sas_address_le;
u16 wait_state_count;
if (ioc->shost_recovery || ioc->pci_error_recovery) {
@@ -1160,8 +1157,7 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- sas_address_le = (u64 *)&mpi_request->SASAddress;
- *sas_address_le = cpu_to_le64(phy->identify.sas_address);
+ mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
mpi_request->RequestDataLength =
cpu_to_le16(sizeof(struct phy_error_log_request));
psge = &mpi_request->SGL;
@@ -1406,7 +1402,6 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
void *data_out = NULL;
dma_addr_t data_out_dma;
u32 sz;
- u64 *sas_address_le;
u16 wait_state_count;
if (ioc->shost_recovery) {
@@ -1486,8 +1481,7 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- sas_address_le = (u64 *)&mpi_request->SASAddress;
- *sas_address_le = cpu_to_le64(phy->identify.sas_address);
+ mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
mpi_request->RequestDataLength =
cpu_to_le16(sizeof(struct phy_error_log_request));
psge = &mpi_request->SGL;
@@ -1914,7 +1908,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- *((u64 *)&mpi_request->SASAddress) = (rphy) ?
+ mpi_request->SASAddress = (rphy) ?
cpu_to_le64(rphy->identify.sas_address) :
cpu_to_le64(ioc->sas_hba.sas_address);
mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index aa05e661d113..b97c8ab0c20e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -54,7 +54,7 @@
#include <scsi/libsas.h>
#include <scsi/scsi_tcq.h>
#include <scsi/sas_ata.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "pm8001_defs.h"
#define DRV_NAME "pm8001"
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 1b60a95adb50..ae8e298746ba 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -63,7 +63,7 @@ qla2100_intr_handler(int irq, void *dev_id)
/*
* Issue a "HARD" reset in order for the RISC interrupt
- * bit to be cleared. Schedule a big hammmer to get
+ * bit to be cleared. Schedule a big hammer to get
* out of the RISC PAUSED state.
*/
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
@@ -169,7 +169,7 @@ qla2300_intr_handler(int irq, void *dev_id)
/*
* Issue a "HARD" reset in order for the RISC
* interrupt bit to be cleared. Schedule a big
- * hammmer to get out of the RISC PAUSED state.
+ * hammer to get out of the RISC PAUSED state.
*/
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
RD_REG_WORD(&reg->hccr);
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 82e9e5c0476e..cf8dfab9489f 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -197,6 +197,7 @@ static struct {
{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
+ {"IOMEGA", "ZIP", NULL, BLIST_NOTQ | BLIST_NOLUN},
{"IOMEGA", "Io20S *F", NULL, BLIST_KEY},
{"INSITE", "Floptical F*8I", NULL, BLIST_KEY},
{"INSITE", "I325VM", NULL, BLIST_KEY},
@@ -243,6 +244,7 @@ static struct {
{"Tornado-", "F4", "*", BLIST_NOREPORTLUN},
{"TOSHIBA", "CDROM", NULL, BLIST_ISROM},
{"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM},
+ {"Traxdata", "CDR4120", NULL, BLIST_NOLUN}, /* locks up */
{"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36},
{"WangDAT", "Model 2600", "01.7", BLIST_SELECT_NO_ATN},
{"WangDAT", "Model 3200", "02.2", BLIST_SELECT_NO_ATN},
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ec1803a48723..28d9c9d6b4b4 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -213,6 +213,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
int ret = DRIVER_ERROR << 24;
req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
+ if (!req)
+ return ret;
if (bufflen && blk_rq_map_kern(sdev->request_queue, req,
buffer, bufflen, __GFP_WAIT))
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index d70e91ae60af..d82a023a9015 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -144,9 +144,9 @@ int scsi_autopm_get_device(struct scsi_device *sdev)
int err;
err = pm_runtime_get_sync(&sdev->sdev_gendev);
- if (err < 0)
+ if (err < 0 && err !=-EACCES)
pm_runtime_put_sync(&sdev->sdev_gendev);
- else if (err > 0)
+ else
err = 0;
return err;
}
@@ -173,9 +173,9 @@ int scsi_autopm_get_host(struct Scsi_Host *shost)
int err;
err = pm_runtime_get_sync(&shost->shost_gendev);
- if (err < 0)
+ if (err < 0 && err !=-EACCES)
pm_runtime_put_sync(&shost->shost_gendev);
- else if (err > 0)
+ else
err = 0;
return err;
}
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index eb7a3e85304f..eba183c428cf 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -160,6 +160,10 @@ static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev,
return NULL;
}
+/* For device slot and array device slot elements, byte 3 bit 6
+ * is "fault sensed" while byte 3 bit 5 is "fault reqstd". As this
+ * code stands these bits are shifted 4 positions right so in
+ * sysfs they will appear as bits 2 and 1 respectively. Strange. */
static void ses_get_fault(struct enclosure_device *edev,
struct enclosure_component *ecomp)
{
@@ -181,7 +185,7 @@ static int ses_set_fault(struct enclosure_device *edev,
/* zero is disabled */
break;
case ENCLOSURE_SETTING_ENABLED:
- desc[2] = 0x02;
+ desc[3] = 0x20;
break;
default:
/* SES doesn't do the SGPIO blink settings */
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 4778e2707168..5fc97d2ba2fd 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -221,14 +221,33 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi,
return 0;
events = sr_get_events(cd->device);
+ cd->get_event_changed |= events & DISK_EVENT_MEDIA_CHANGE;
+
+ /*
+ * If earlier GET_EVENT_STATUS_NOTIFICATION and TUR did not agree
+ * for several times in a row. We rely on TUR only for this likely
+ * broken device, to prevent generating incorrect media changed
+ * events for every open().
+ */
+ if (cd->ignore_get_event) {
+ events &= ~DISK_EVENT_MEDIA_CHANGE;
+ goto do_tur;
+ }
+
/*
* GET_EVENT_STATUS_NOTIFICATION is enough unless MEDIA_CHANGE
* is being cleared. Note that there are devices which hang
* if asked to execute TUR repeatedly.
*/
- if (!(clearing & DISK_EVENT_MEDIA_CHANGE))
- goto skip_tur;
+ if (cd->device->changed) {
+ events |= DISK_EVENT_MEDIA_CHANGE;
+ cd->device->changed = 0;
+ cd->tur_changed = true;
+ }
+ if (!(clearing & DISK_EVENT_MEDIA_CHANGE))
+ return events;
+do_tur:
/* let's see whether the media is there with TUR */
last_present = cd->media_present;
ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
@@ -242,12 +261,31 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi,
(scsi_sense_valid(&sshdr) && sshdr.asc != 0x3a);
if (last_present != cd->media_present)
- events |= DISK_EVENT_MEDIA_CHANGE;
-skip_tur:
+ cd->device->changed = 1;
+
if (cd->device->changed) {
events |= DISK_EVENT_MEDIA_CHANGE;
cd->device->changed = 0;
+ cd->tur_changed = true;
+ }
+
+ if (cd->ignore_get_event)
+ return events;
+
+ /* check whether GET_EVENT is reporting spurious MEDIA_CHANGE */
+ if (!cd->tur_changed) {
+ if (cd->get_event_changed) {
+ if (cd->tur_mismatch++ > 8) {
+ sdev_printk(KERN_WARNING, cd->device,
+ "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n");
+ cd->ignore_get_event = true;
+ }
+ } else {
+ cd->tur_mismatch = 0;
+ }
}
+ cd->tur_changed = false;
+ cd->get_event_changed = false;
return events;
}
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index e036f1dc83c8..37c8f6b17510 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -41,6 +41,13 @@ typedef struct scsi_cd {
unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */
unsigned readcd_cdda:1; /* reading audio data using READ_CD */
unsigned media_present:1; /* media is present */
+
+ /* GET_EVENT spurious event handling, blk layer guarantees exclusion */
+ int tur_mismatch; /* nr of get_event TUR mismatches */
+ bool tur_changed:1; /* changed according to TUR */
+ bool get_event_changed:1; /* changed according to GET_EVENT */
+ bool ignore_get_event:1; /* GET_EVENT is unreliable, use TUR */
+
struct cdrom_device_info cdi;
/* We hold gendisk and scsi_device references on probe and use
* the refs on this kref to decide when to release them */
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 07eaef1c722b..7e12a2e4e0a3 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -49,13 +49,6 @@
* inside the execution of NCR5380_intr(), leading to recursive
* calls.
*
- * - I've added a function merge_contiguous_buffers() that tries to
- * merge scatter-gather buffers that are located at contiguous
- * physical addresses and can be processed with the same DMA setup.
- * Since most scatter-gather operations work on a page (4K) of
- * 4 buffers (1K), in more than 90% of all cases three interrupts and
- * DMA setup actions are saved.
- *
* - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
* and USLEEP, because these were messing up readability and will never be
* needed for Atari SCSI.
@@ -266,8 +259,9 @@ static struct scsi_host_template *the_template = NULL;
(struct NCR5380_hostdata *)(in)->hostdata
#define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
-#define NEXT(cmd) (*(struct scsi_cmnd **)&((cmd)->host_scribble))
-#define NEXTADDR(cmd) ((struct scsi_cmnd **)&((cmd)->host_scribble))
+#define NEXT(cmd) ((struct scsi_cmnd *)(cmd)->host_scribble)
+#define SET_NEXT(cmd, next) ((cmd)->host_scribble = (void *)(next))
+#define NEXTADDR(cmd) ((struct scsi_cmnd **)&((cmd)->host_scribble))
#define HOSTNO instance->host_no
#define H_NO(cmd) (cmd)->device->host->host_no
@@ -459,47 +453,6 @@ static void free_all_tags( void )
/*
- * Function: void merge_contiguous_buffers(struct scsi_cmnd *cmd)
- *
- * Purpose: Try to merge several scatter-gather requests into one DMA
- * transfer. This is possible if the scatter buffers lie on
- * physical contiguous addresses.
- *
- * Parameters: struct scsi_cmnd *cmd
- * The command to work on. The first scatter buffer's data are
- * assumed to be already transferred into ptr/this_residual.
- */
-
-static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
-{
- unsigned long endaddr;
-#if (NDEBUG & NDEBUG_MERGING)
- unsigned long oldlen = cmd->SCp.this_residual;
- int cnt = 1;
-#endif
-
- for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
- cmd->SCp.buffers_residual &&
- virt_to_phys(SGADDR(&(cmd->SCp.buffer[1]))) == endaddr; ) {
-
- MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
- SGADDR(&(cmd->SCp.buffer[1])), endaddr);
-#if (NDEBUG & NDEBUG_MERGING)
- ++cnt;
-#endif
- ++cmd->SCp.buffer;
- --cmd->SCp.buffers_residual;
- cmd->SCp.this_residual += cmd->SCp.buffer->length;
- endaddr += cmd->SCp.buffer->length;
- }
-#if (NDEBUG & NDEBUG_MERGING)
- if (oldlen != cmd->SCp.this_residual)
- MER_PRINTK("merged %d buffers from %p, new length %08x\n",
- cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
-#endif
-}
-
-/*
* Function : void initialize_SCp(struct scsi_cmnd *cmd)
*
* Purpose : initialize the saved data pointers for cmd to point to the
@@ -520,11 +473,6 @@ static __inline__ void initialize_SCp(struct scsi_cmnd *cmd)
cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer);
cmd->SCp.this_residual = cmd->SCp.buffer->length;
-
- /* ++roman: Try to merge some scatter-buffers if they are at
- * contiguous physical addresses.
- */
-// merge_contiguous_buffers( cmd );
} else {
cmd->SCp.buffer = NULL;
cmd->SCp.buffers_residual = 0;
@@ -841,7 +789,7 @@ static char *lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, char *pos, char *buffer,
*
*/
-static int NCR5380_init (struct Scsi_Host *instance, int flags)
+static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
{
int i;
SETUP_HOSTDATA(instance);
@@ -889,6 +837,11 @@ static int NCR5380_init (struct Scsi_Host *instance, int flags)
return 0;
}
+static void NCR5380_exit(struct Scsi_Host *instance)
+{
+ /* Empty, as we didn't schedule any delayed work */
+}
+
/*
* Function : int NCR5380_queue_command (struct scsi_cmnd *cmd,
* void (*done)(struct scsi_cmnd *))
@@ -962,7 +915,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd,
* in a queue
*/
- NEXT(cmd) = NULL;
+ SET_NEXT(cmd, NULL);
cmd->scsi_done = done;
cmd->result = 0;
@@ -990,14 +943,14 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd,
*/
if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
LIST(cmd, hostdata->issue_queue);
- NEXT(cmd) = hostdata->issue_queue;
+ SET_NEXT(cmd, hostdata->issue_queue);
hostdata->issue_queue = cmd;
} else {
for (tmp = (struct scsi_cmnd *)hostdata->issue_queue;
NEXT(tmp); tmp = NEXT(tmp))
;
LIST(cmd, tmp);
- NEXT(tmp) = cmd;
+ SET_NEXT(tmp, cmd);
}
local_irq_restore(flags);
@@ -1105,12 +1058,12 @@ static void NCR5380_main (struct work_struct *bl)
local_irq_disable();
if (prev) {
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
- NEXT(prev) = NEXT(tmp);
+ SET_NEXT(prev, NEXT(tmp));
} else {
REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
hostdata->issue_queue = NEXT(tmp);
}
- NEXT(tmp) = NULL;
+ SET_NEXT(tmp, NULL);
/* reenable interrupts after finding one */
local_irq_restore(flags);
@@ -1144,7 +1097,7 @@ static void NCR5380_main (struct work_struct *bl)
} else {
local_irq_disable();
LIST(tmp, hostdata->issue_queue);
- NEXT(tmp) = hostdata->issue_queue;
+ SET_NEXT(tmp, hostdata->issue_queue);
hostdata->issue_queue = tmp;
#ifdef SUPPORT_TAGS
cmd_free_tag( tmp );
@@ -1439,7 +1392,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd,
local_irq_restore(flags);
/* Wait for arbitration logic to complete */
-#if NCR_TIMEOUT
+#ifdef NCR_TIMEOUT
{
unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
@@ -2070,11 +2023,6 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
--cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
cmd->SCp.ptr = SGADDR(cmd->SCp.buffer);
-
- /* ++roman: Try to merge some scatter-buffers if
- * they are at contiguous physical addresses.
- */
-// merge_contiguous_buffers( cmd );
INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
HOSTNO, cmd->SCp.this_residual,
cmd->SCp.buffers_residual);
@@ -2274,7 +2222,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
local_irq_save(flags);
LIST(cmd,hostdata->issue_queue);
- NEXT(cmd) = hostdata->issue_queue;
+ SET_NEXT(cmd, hostdata->issue_queue);
hostdata->issue_queue = (struct scsi_cmnd *) cmd;
local_irq_restore(flags);
QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
@@ -2330,7 +2278,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
local_irq_save(flags);
cmd->device->disconnect = 1;
LIST(cmd,hostdata->disconnected_queue);
- NEXT(cmd) = hostdata->disconnected_queue;
+ SET_NEXT(cmd, hostdata->disconnected_queue);
hostdata->connected = NULL;
hostdata->disconnected_queue = cmd;
local_irq_restore(flags);
@@ -2589,12 +2537,12 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
) {
if (prev) {
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
- NEXT(prev) = NEXT(tmp);
+ SET_NEXT(prev, NEXT(tmp));
} else {
REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
hostdata->disconnected_queue = NEXT(tmp);
}
- NEXT(tmp) = NULL;
+ SET_NEXT(tmp, NULL);
break;
}
}
@@ -2762,7 +2710,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
if (cmd == tmp) {
REMOVE(5, *prev, tmp, NEXT(tmp));
(*prev) = NEXT(tmp);
- NEXT(tmp) = NULL;
+ SET_NEXT(tmp, NULL);
tmp->result = DID_ABORT << 16;
local_irq_restore(flags);
ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
@@ -2835,7 +2783,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
if (cmd == tmp) {
REMOVE(5, *prev, tmp, NEXT(tmp));
*prev = NEXT(tmp);
- NEXT(tmp) = NULL;
+ SET_NEXT(tmp, NULL);
tmp->result = DID_ABORT << 16;
/* We must unlock the tag/LUN immediately here, since the
* target goes to BUS FREE and doesn't send us another
@@ -2943,7 +2891,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
for (i = 0; (cmd = disconnected_queue); ++i) {
disconnected_queue = NEXT(cmd);
- NEXT(cmd) = NULL;
+ SET_NEXT(cmd, NULL);
cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
cmd->scsi_done( cmd );
}
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 613f5880d135..baf7328de956 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -70,6 +70,12 @@
#include <asm/idprom.h>
#include <asm/machines.h>
+#define NDEBUG 0
+
+#define NDEBUG_ABORT 0x00100000
+#define NDEBUG_TAGS 0x00200000
+#define NDEBUG_MERGING 0x00400000
+
/* dma on! */
#define REAL_DMA
@@ -86,8 +92,6 @@ static void NCR5380_print(struct Scsi_Host *instance);
/*#define RESET_BOOT */
#define DRIVER_SETUP
-#define NDEBUG 0
-
/*
* BUG can be used to trigger a strange code-size related hang on 2.1 kernels
*/
@@ -195,7 +199,7 @@ static struct Scsi_Host *default_instance;
*
*/
-int sun3scsi_detect(struct scsi_host_template * tpnt)
+int __init sun3scsi_detect(struct scsi_host_template * tpnt)
{
unsigned long ioaddr;
static int called = 0;
@@ -314,6 +318,7 @@ int sun3scsi_release (struct Scsi_Host *shpnt)
iounmap((void *)sun3_scsi_regp);
+ NCR5380_exit(shpnt);
return 0;
}
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
index 7c526b8e30ac..fbba78e5722e 100644
--- a/drivers/scsi/sun3_scsi_vme.c
+++ b/drivers/scsi/sun3_scsi_vme.c
@@ -39,6 +39,12 @@
/* dma on! */
#define REAL_DMA
+#define NDEBUG 0
+
+#define NDEBUG_ABORT 0x00100000
+#define NDEBUG_TAGS 0x00200000
+#define NDEBUG_MERGING 0x00400000
+
#include "scsi.h"
#include "initio.h"
#include <scsi/scsi_host.h>
@@ -50,8 +56,6 @@ extern int sun3_map_test(unsigned long, char *);
/*#define RESET_BOOT */
#define DRIVER_SETUP
-#define NDEBUG 0
-
/*
* BUG can be used to trigger a strange code-size related hang on 2.1 kernels
*/
@@ -137,7 +141,7 @@ static struct Scsi_Host *default_instance;
*
*/
-static int sun3scsi_detect(struct scsi_host_template * tpnt)
+static int __init sun3scsi_detect(struct scsi_host_template * tpnt)
{
unsigned long ioaddr, irq = 0;
static int called = 0;
@@ -283,6 +287,7 @@ int sun3scsi_release (struct Scsi_Host *shpnt)
iounmap((void *)sun3_scsi_regp);
+ NCR5380_exit(shpnt);
return 0;
}
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index 7e9c39951ecb..d6702e57d428 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -670,7 +670,7 @@ static struct dentry *clk_debugfs_root;
static int clk_debugfs_register_one(struct clk *c)
{
int err;
- struct dentry *d, *child, *child_tmp;
+ struct dentry *d;
struct clk *pa = c->parent;
char s[255];
char *p = s;
@@ -699,10 +699,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;
err_out:
- d = c->dentry;
- list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
- debugfs_remove(child);
- debugfs_remove(c->dentry);
+ debugfs_remove_recursive(c->dentry);
return err;
}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index de35c3ad8a69..52e2900d9d8e 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -86,9 +86,6 @@ config SPI_BFIN_SPORT
help
Enable support for a SPI bus via the Blackfin SPORT peripheral.
- This driver can also be built as a module. If so, the module
- will be called spi_bfin_sport.
-
config SPI_AU1550
tristate "Au1550/Au12x0 SPI Controller"
depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
@@ -97,9 +94,6 @@ config SPI_AU1550
If you say yes to this option, support will be included for the
Au1550 SPI controller (may also work with Au1200,Au1210,Au1250).
- This driver can also be built as a module. If so, the module
- will be called au1550_spi.
-
config SPI_BITBANG
tristate "Utilities for Bitbanging SPI masters"
help
@@ -130,9 +124,6 @@ config SPI_COLDFIRE_QSPI
This enables support for the Coldfire QSPI controller in master
mode.
- This driver can also be built as a module. If so, the module
- will be called coldfire_qspi.
-
config SPI_DAVINCI
tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
depends on SPI_MASTER && ARCH_DAVINCI
@@ -140,9 +131,6 @@ config SPI_DAVINCI
help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
- This driver can also be built as a module. The module will be called
- davinci_spi.
-
config SPI_EP93XX
tristate "Cirrus Logic EP93xx SPI controller"
depends on ARCH_EP93XX
@@ -150,9 +138,6 @@ config SPI_EP93XX
This enables using the Cirrus EP93xx SPI controller in master
mode.
- To compile this driver as a module, choose M here. The module will be
- called ep93xx_spi.
-
config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master"
depends on GENERIC_GPIO
@@ -169,21 +154,6 @@ config SPI_GPIO
GPIO operations, you should be able to leverage that for better
speed with a custom version of this driver; see the source code.
-config SPI_IMX_VER_IMX1
- def_bool y if SOC_IMX1
-
-config SPI_IMX_VER_0_0
- def_bool y if SOC_IMX21 || SOC_IMX27
-
-config SPI_IMX_VER_0_4
- def_bool y if SOC_IMX31
-
-config SPI_IMX_VER_0_7
- def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
-
-config SPI_IMX_VER_2_3
- def_bool y if SOC_IMX51 || SOC_IMX53
-
config SPI_IMX
tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC
@@ -328,16 +298,6 @@ config SPI_S3C24XX_FIQ
no free DMA channels, or when doing transfers that required both
TX and RX data paths.
-config SPI_S3C24XX_GPIO
- tristate "Samsung S3C24XX series SPI by GPIO"
- depends on ARCH_S3C2410 && EXPERIMENTAL
- select SPI_BITBANG
- help
- SPI driver for Samsung S3C24XX series ARM SoCs using
- GPIO lines to provide the SPI bus. This can be used where
- the inbuilt hardware cannot provide the transfer mode, or
- where the board is using non hardware connected pins.
-
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
depends on (ARCH_S3C64XX || ARCH_S5P64X0)
@@ -385,16 +345,16 @@ config SPI_TI_SSP
This selects an SPI master implementation using a TI sequencer
serial port.
- To compile this driver as a module, choose M here: the
- module will be called ti-ssp-spi.
-
config SPI_TOPCLIFF_PCH
- tristate "Topcliff PCH SPI Controller"
+ tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller"
depends on PCI
help
SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
used in some x86 embedded processors.
+ This driver also supports the ML7213, a companion chip for the
+ Atom E6xx series and compatible with the Intel EG20T PCH.
+
config SPI_TXX9
tristate "Toshiba TXx9 SPI controller"
depends on GENERIC_GPIO && CPU_TX49XX
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 0f8c69b6b19e..61c3261c388c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -7,68 +7,55 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
# small core, mostly translating board-specific
# config declarations into driver model code
obj-$(CONFIG_SPI_MASTER) += spi.o
+obj-$(CONFIG_SPI_SPIDEV) += spidev.o
# SPI master controller drivers (bus)
-obj-$(CONFIG_SPI_ALTERA) += spi_altera.o
-obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o
-obj-$(CONFIG_SPI_ATH79) += ath79_spi.o
-obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o
-obj-$(CONFIG_SPI_BFIN_SPORT) += spi_bfin_sport.o
-obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
-obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
-obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
-obj-$(CONFIG_SPI_COLDFIRE_QSPI) += coldfire_qspi.o
-obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o
-obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI) += dw_spi_midpci.o
-dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o
-obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o
-obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o
-obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
-obj-$(CONFIG_SPI_IMX) += spi_imx.o
-obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
-obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
-obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o
-obj-$(CONFIG_SPI_OC_TINY) += spi_oc_tiny.o
-obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
-obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
-obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o
-obj-$(CONFIG_SPI_ORION) += orion_spi.o
-obj-$(CONFIG_SPI_PL022) += amba-pl022.o
-obj-$(CONFIG_SPI_MPC512x_PSC) += mpc512x_psc_spi.o
-obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
-obj-$(CONFIG_SPI_MPC52xx) += mpc52xx_spi.o
-obj-$(CONFIG_SPI_FSL_LIB) += spi_fsl_lib.o
-obj-$(CONFIG_SPI_FSL_ESPI) += spi_fsl_espi.o
-obj-$(CONFIG_SPI_FSL_SPI) += spi_fsl_spi.o
-obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o
-obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
-obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx_hw.o
-obj-$(CONFIG_SPI_S3C64XX) += spi_s3c64xx.o
-obj-$(CONFIG_SPI_TEGRA) += spi_tegra.o
-obj-$(CONFIG_SPI_TI_SSP) += ti-ssp-spi.o
-obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o
-obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
-obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
-obj-$(CONFIG_SPI_SH) += spi_sh.o
-obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
-obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
-obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
-obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
+obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
+obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
+obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
+obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
+obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
+obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
+obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
+obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
+obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
+obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
+obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
+obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
+spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
+obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
+obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
+obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
+obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
+obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
+obj-$(CONFIG_SPI_IMX) += spi-imx.o
+obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
+obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
+obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
+obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
+obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
+obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
+obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o
+obj-$(CONFIG_SPI_OMAP_100K) += spi-omap-100k.o
+obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
+obj-$(CONFIG_SPI_ORION) += spi-orion.o
+obj-$(CONFIG_SPI_PL022) += spi-pl022.o
+obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
+obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o
+obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
+obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
+spi-s3c24xx-hw-y := spi-s3c24xx.o
+spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
+obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o
+obj-$(CONFIG_SPI_SH) += spi-sh.o
+obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
+obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
+obj-$(CONFIG_SPI_STMP3XXX) += spi-stmp.o
+obj-$(CONFIG_SPI_TEGRA) += spi-tegra.o
+obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o
+obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o
+obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
+obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
+obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
-# special build for s3c24xx spi driver with fiq support
-spi_s3c24xx_hw-y := spi_s3c24xx.o
-spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
-
-# ... add above this line ...
-
-# SPI protocol drivers (device/link on bus)
-obj-$(CONFIG_SPI_SPIDEV) += spidev.o
-obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
-# ... add above this line ...
-
-# SPI slave controller drivers (upstream link)
-# ... add above this line ...
-
-# SPI slave drivers (protocol for that link)
-# ... add above this line ...
diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h
deleted file mode 100644
index 6e06b6ad3a45..000000000000
--- a/drivers/spi/atmel_spi.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Register definitions for Atmel Serial Peripheral Interface (SPI)
- *
- * Copyright (C) 2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ATMEL_SPI_H__
-#define __ATMEL_SPI_H__
-
-/* SPI register offsets */
-#define SPI_CR 0x0000
-#define SPI_MR 0x0004
-#define SPI_RDR 0x0008
-#define SPI_TDR 0x000c
-#define SPI_SR 0x0010
-#define SPI_IER 0x0014
-#define SPI_IDR 0x0018
-#define SPI_IMR 0x001c
-#define SPI_CSR0 0x0030
-#define SPI_CSR1 0x0034
-#define SPI_CSR2 0x0038
-#define SPI_CSR3 0x003c
-#define SPI_RPR 0x0100
-#define SPI_RCR 0x0104
-#define SPI_TPR 0x0108
-#define SPI_TCR 0x010c
-#define SPI_RNPR 0x0110
-#define SPI_RNCR 0x0114
-#define SPI_TNPR 0x0118
-#define SPI_TNCR 0x011c
-#define SPI_PTCR 0x0120
-#define SPI_PTSR 0x0124
-
-/* Bitfields in CR */
-#define SPI_SPIEN_OFFSET 0
-#define SPI_SPIEN_SIZE 1
-#define SPI_SPIDIS_OFFSET 1
-#define SPI_SPIDIS_SIZE 1
-#define SPI_SWRST_OFFSET 7
-#define SPI_SWRST_SIZE 1
-#define SPI_LASTXFER_OFFSET 24
-#define SPI_LASTXFER_SIZE 1
-
-/* Bitfields in MR */
-#define SPI_MSTR_OFFSET 0
-#define SPI_MSTR_SIZE 1
-#define SPI_PS_OFFSET 1
-#define SPI_PS_SIZE 1
-#define SPI_PCSDEC_OFFSET 2
-#define SPI_PCSDEC_SIZE 1
-#define SPI_FDIV_OFFSET 3
-#define SPI_FDIV_SIZE 1
-#define SPI_MODFDIS_OFFSET 4
-#define SPI_MODFDIS_SIZE 1
-#define SPI_LLB_OFFSET 7
-#define SPI_LLB_SIZE 1
-#define SPI_PCS_OFFSET 16
-#define SPI_PCS_SIZE 4
-#define SPI_DLYBCS_OFFSET 24
-#define SPI_DLYBCS_SIZE 8
-
-/* Bitfields in RDR */
-#define SPI_RD_OFFSET 0
-#define SPI_RD_SIZE 16
-
-/* Bitfields in TDR */
-#define SPI_TD_OFFSET 0
-#define SPI_TD_SIZE 16
-
-/* Bitfields in SR */
-#define SPI_RDRF_OFFSET 0
-#define SPI_RDRF_SIZE 1
-#define SPI_TDRE_OFFSET 1
-#define SPI_TDRE_SIZE 1
-#define SPI_MODF_OFFSET 2
-#define SPI_MODF_SIZE 1
-#define SPI_OVRES_OFFSET 3
-#define SPI_OVRES_SIZE 1
-#define SPI_ENDRX_OFFSET 4
-#define SPI_ENDRX_SIZE 1
-#define SPI_ENDTX_OFFSET 5
-#define SPI_ENDTX_SIZE 1
-#define SPI_RXBUFF_OFFSET 6
-#define SPI_RXBUFF_SIZE 1
-#define SPI_TXBUFE_OFFSET 7
-#define SPI_TXBUFE_SIZE 1
-#define SPI_NSSR_OFFSET 8
-#define SPI_NSSR_SIZE 1
-#define SPI_TXEMPTY_OFFSET 9
-#define SPI_TXEMPTY_SIZE 1
-#define SPI_SPIENS_OFFSET 16
-#define SPI_SPIENS_SIZE 1
-
-/* Bitfields in CSR0 */
-#define SPI_CPOL_OFFSET 0
-#define SPI_CPOL_SIZE 1
-#define SPI_NCPHA_OFFSET 1
-#define SPI_NCPHA_SIZE 1
-#define SPI_CSAAT_OFFSET 3
-#define SPI_CSAAT_SIZE 1
-#define SPI_BITS_OFFSET 4
-#define SPI_BITS_SIZE 4
-#define SPI_SCBR_OFFSET 8
-#define SPI_SCBR_SIZE 8
-#define SPI_DLYBS_OFFSET 16
-#define SPI_DLYBS_SIZE 8
-#define SPI_DLYBCT_OFFSET 24
-#define SPI_DLYBCT_SIZE 8
-
-/* Bitfields in RCR */
-#define SPI_RXCTR_OFFSET 0
-#define SPI_RXCTR_SIZE 16
-
-/* Bitfields in TCR */
-#define SPI_TXCTR_OFFSET 0
-#define SPI_TXCTR_SIZE 16
-
-/* Bitfields in RNCR */
-#define SPI_RXNCR_OFFSET 0
-#define SPI_RXNCR_SIZE 16
-
-/* Bitfields in TNCR */
-#define SPI_TXNCR_OFFSET 0
-#define SPI_TXNCR_SIZE 16
-
-/* Bitfields in PTCR */
-#define SPI_RXTEN_OFFSET 0
-#define SPI_RXTEN_SIZE 1
-#define SPI_RXTDIS_OFFSET 1
-#define SPI_RXTDIS_SIZE 1
-#define SPI_TXTEN_OFFSET 8
-#define SPI_TXTEN_SIZE 1
-#define SPI_TXTDIS_OFFSET 9
-#define SPI_TXTDIS_SIZE 1
-
-/* Constants for BITS */
-#define SPI_BITS_8_BPT 0
-#define SPI_BITS_9_BPT 1
-#define SPI_BITS_10_BPT 2
-#define SPI_BITS_11_BPT 3
-#define SPI_BITS_12_BPT 4
-#define SPI_BITS_13_BPT 5
-#define SPI_BITS_14_BPT 6
-#define SPI_BITS_15_BPT 7
-#define SPI_BITS_16_BPT 8
-
-/* Bit manipulation macros */
-#define SPI_BIT(name) \
- (1 << SPI_##name##_OFFSET)
-#define SPI_BF(name,value) \
- (((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
-#define SPI_BFEXT(name,value) \
- (((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
-#define SPI_BFINS(name,value,old) \
- ( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
- | SPI_BF(name,value))
-
-/* Register access macros */
-#define spi_readl(port,reg) \
- __raw_readl((port)->regs + SPI_##reg)
-#define spi_writel(port,reg,value) \
- __raw_writel((value), (port)->regs + SPI_##reg)
-
-#endif /* __ATMEL_SPI_H__ */
diff --git a/drivers/spi/spi_altera.c b/drivers/spi/spi-altera.c
index 4813a63ce6fb..4813a63ce6fb 100644
--- a/drivers/spi/spi_altera.c
+++ b/drivers/spi/spi-altera.c
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/spi-ath79.c
index fcff810ea3b0..03019bf5a5e9 100644
--- a/drivers/spi/ath79_spi.c
+++ b/drivers/spi/spi-ath79.c
@@ -232,7 +232,7 @@ static __devinit int ath79_spi_probe(struct platform_device *pdev)
goto err_put_master;
}
- sp->base = ioremap(r->start, r->end - r->start + 1);
+ sp->base = ioremap(r->start, resource_size(r));
if (!sp->base) {
ret = -ENXIO;
goto err_put_master;
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/spi-atmel.c
index 08711e9202ab..82dee9a6c0de 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/spi-atmel.c
@@ -25,7 +25,160 @@
#include <mach/gpio.h>
#include <mach/cpu.h>
-#include "atmel_spi.h"
+/* SPI register offsets */
+#define SPI_CR 0x0000
+#define SPI_MR 0x0004
+#define SPI_RDR 0x0008
+#define SPI_TDR 0x000c
+#define SPI_SR 0x0010
+#define SPI_IER 0x0014
+#define SPI_IDR 0x0018
+#define SPI_IMR 0x001c
+#define SPI_CSR0 0x0030
+#define SPI_CSR1 0x0034
+#define SPI_CSR2 0x0038
+#define SPI_CSR3 0x003c
+#define SPI_RPR 0x0100
+#define SPI_RCR 0x0104
+#define SPI_TPR 0x0108
+#define SPI_TCR 0x010c
+#define SPI_RNPR 0x0110
+#define SPI_RNCR 0x0114
+#define SPI_TNPR 0x0118
+#define SPI_TNCR 0x011c
+#define SPI_PTCR 0x0120
+#define SPI_PTSR 0x0124
+
+/* Bitfields in CR */
+#define SPI_SPIEN_OFFSET 0
+#define SPI_SPIEN_SIZE 1
+#define SPI_SPIDIS_OFFSET 1
+#define SPI_SPIDIS_SIZE 1
+#define SPI_SWRST_OFFSET 7
+#define SPI_SWRST_SIZE 1
+#define SPI_LASTXFER_OFFSET 24
+#define SPI_LASTXFER_SIZE 1
+
+/* Bitfields in MR */
+#define SPI_MSTR_OFFSET 0
+#define SPI_MSTR_SIZE 1
+#define SPI_PS_OFFSET 1
+#define SPI_PS_SIZE 1
+#define SPI_PCSDEC_OFFSET 2
+#define SPI_PCSDEC_SIZE 1
+#define SPI_FDIV_OFFSET 3
+#define SPI_FDIV_SIZE 1
+#define SPI_MODFDIS_OFFSET 4
+#define SPI_MODFDIS_SIZE 1
+#define SPI_LLB_OFFSET 7
+#define SPI_LLB_SIZE 1
+#define SPI_PCS_OFFSET 16
+#define SPI_PCS_SIZE 4
+#define SPI_DLYBCS_OFFSET 24
+#define SPI_DLYBCS_SIZE 8
+
+/* Bitfields in RDR */
+#define SPI_RD_OFFSET 0
+#define SPI_RD_SIZE 16
+
+/* Bitfields in TDR */
+#define SPI_TD_OFFSET 0
+#define SPI_TD_SIZE 16
+
+/* Bitfields in SR */
+#define SPI_RDRF_OFFSET 0
+#define SPI_RDRF_SIZE 1
+#define SPI_TDRE_OFFSET 1
+#define SPI_TDRE_SIZE 1
+#define SPI_MODF_OFFSET 2
+#define SPI_MODF_SIZE 1
+#define SPI_OVRES_OFFSET 3
+#define SPI_OVRES_SIZE 1
+#define SPI_ENDRX_OFFSET 4
+#define SPI_ENDRX_SIZE 1
+#define SPI_ENDTX_OFFSET 5
+#define SPI_ENDTX_SIZE 1
+#define SPI_RXBUFF_OFFSET 6
+#define SPI_RXBUFF_SIZE 1
+#define SPI_TXBUFE_OFFSET 7
+#define SPI_TXBUFE_SIZE 1
+#define SPI_NSSR_OFFSET 8
+#define SPI_NSSR_SIZE 1
+#define SPI_TXEMPTY_OFFSET 9
+#define SPI_TXEMPTY_SIZE 1
+#define SPI_SPIENS_OFFSET 16
+#define SPI_SPIENS_SIZE 1
+
+/* Bitfields in CSR0 */
+#define SPI_CPOL_OFFSET 0
+#define SPI_CPOL_SIZE 1
+#define SPI_NCPHA_OFFSET 1
+#define SPI_NCPHA_SIZE 1
+#define SPI_CSAAT_OFFSET 3
+#define SPI_CSAAT_SIZE 1
+#define SPI_BITS_OFFSET 4
+#define SPI_BITS_SIZE 4
+#define SPI_SCBR_OFFSET 8
+#define SPI_SCBR_SIZE 8
+#define SPI_DLYBS_OFFSET 16
+#define SPI_DLYBS_SIZE 8
+#define SPI_DLYBCT_OFFSET 24
+#define SPI_DLYBCT_SIZE 8
+
+/* Bitfields in RCR */
+#define SPI_RXCTR_OFFSET 0
+#define SPI_RXCTR_SIZE 16
+
+/* Bitfields in TCR */
+#define SPI_TXCTR_OFFSET 0
+#define SPI_TXCTR_SIZE 16
+
+/* Bitfields in RNCR */
+#define SPI_RXNCR_OFFSET 0
+#define SPI_RXNCR_SIZE 16
+
+/* Bitfields in TNCR */
+#define SPI_TXNCR_OFFSET 0
+#define SPI_TXNCR_SIZE 16
+
+/* Bitfields in PTCR */
+#define SPI_RXTEN_OFFSET 0
+#define SPI_RXTEN_SIZE 1
+#define SPI_RXTDIS_OFFSET 1
+#define SPI_RXTDIS_SIZE 1
+#define SPI_TXTEN_OFFSET 8
+#define SPI_TXTEN_SIZE 1
+#define SPI_TXTDIS_OFFSET 9
+#define SPI_TXTDIS_SIZE 1
+
+/* Constants for BITS */
+#define SPI_BITS_8_BPT 0
+#define SPI_BITS_9_BPT 1
+#define SPI_BITS_10_BPT 2
+#define SPI_BITS_11_BPT 3
+#define SPI_BITS_12_BPT 4
+#define SPI_BITS_13_BPT 5
+#define SPI_BITS_14_BPT 6
+#define SPI_BITS_15_BPT 7
+#define SPI_BITS_16_BPT 8
+
+/* Bit manipulation macros */
+#define SPI_BIT(name) \
+ (1 << SPI_##name##_OFFSET)
+#define SPI_BF(name,value) \
+ (((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
+#define SPI_BFEXT(name,value) \
+ (((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
+#define SPI_BFINS(name,value,old) \
+ ( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
+ | SPI_BF(name,value))
+
+/* Register access macros */
+#define spi_readl(port,reg) \
+ __raw_readl((port)->regs + SPI_##reg)
+#define spi_writel(port,reg,value) \
+ __raw_writel((value), (port)->regs + SPI_##reg)
+
/*
* The core SPI transfer engine just talks to a register bank to set up
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/spi-au1550.c
index b50563d320e1..bddee5f516b2 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/spi-au1550.c
@@ -1,5 +1,5 @@
/*
- * au1550_spi.c - au1550 psc spi controller driver
+ * au1550 psc spi controller driver
* may work also with au1200, au1210, au1250
* will not work on au1000, au1100 and au1500 (no full spi controller there)
*
diff --git a/drivers/spi/spi_bfin_sport.c b/drivers/spi/spi-bfin-sport.c
index e557ff617b11..e557ff617b11 100644
--- a/drivers/spi/spi_bfin_sport.c
+++ b/drivers/spi/spi-bfin-sport.c
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index cc880c95e7de..b8d25f2b7038 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -58,7 +58,7 @@ struct bfin_spi_master_data {
struct spi_master *master;
/* Regs base of SPI controller */
- void __iomem *regs_base;
+ struct bfin_spi_regs __iomem *regs;
/* Pin request list */
u16 *pin_req;
@@ -122,34 +122,14 @@ struct bfin_spi_slave_data {
const struct bfin_spi_transfer_ops *ops;
};
-#define DEFINE_SPI_REG(reg, off) \
-static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \
- { return bfin_read16(drv_data->regs_base + off); } \
-static inline void write_##reg(struct bfin_spi_master_data *drv_data, u16 v) \
- { bfin_write16(drv_data->regs_base + off, v); }
-
-DEFINE_SPI_REG(CTRL, 0x00)
-DEFINE_SPI_REG(FLAG, 0x04)
-DEFINE_SPI_REG(STAT, 0x08)
-DEFINE_SPI_REG(TDBR, 0x0C)
-DEFINE_SPI_REG(RDBR, 0x10)
-DEFINE_SPI_REG(BAUD, 0x14)
-DEFINE_SPI_REG(SHAW, 0x18)
-
static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)
{
- u16 cr;
-
- cr = read_CTRL(drv_data);
- write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
+ bfin_write_or(&drv_data->regs->ctl, BIT_CTL_ENABLE);
}
static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
{
- u16 cr;
-
- cr = read_CTRL(drv_data);
- write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE)));
+ bfin_write_and(&drv_data->regs->ctl, ~BIT_CTL_ENABLE);
}
/* Caculate the SPI_BAUD register value based on input HZ */
@@ -172,10 +152,10 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
unsigned long limit = loops_per_jiffy << 1;
/* wait for stop and clear stat */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && --limit)
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF) && --limit)
cpu_relax();
- write_STAT(drv_data, BIT_STAT_CLR);
+ bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
return limit;
}
@@ -183,29 +163,19 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
/* Chip select operation functions for cs_change flag */
static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)
{
- if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
- u16 flag = read_FLAG(drv_data);
-
- flag &= ~chip->flag;
-
- write_FLAG(drv_data, flag);
- } else {
+ if (likely(chip->chip_select_num < MAX_CTRL_CS))
+ bfin_write_and(&drv_data->regs->flg, ~chip->flag);
+ else
gpio_set_value(chip->cs_gpio, 0);
- }
}
static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
struct bfin_spi_slave_data *chip)
{
- if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
- u16 flag = read_FLAG(drv_data);
-
- flag |= chip->flag;
-
- write_FLAG(drv_data, flag);
- } else {
+ if (likely(chip->chip_select_num < MAX_CTRL_CS))
+ bfin_write_or(&drv_data->regs->flg, chip->flag);
+ else
gpio_set_value(chip->cs_gpio, 1);
- }
/* Move delay here for consistency */
if (chip->cs_chg_udelay)
@@ -216,25 +186,15 @@ static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,
struct bfin_spi_slave_data *chip)
{
- if (chip->chip_select_num < MAX_CTRL_CS) {
- u16 flag = read_FLAG(drv_data);
-
- flag |= (chip->flag >> 8);
-
- write_FLAG(drv_data, flag);
- }
+ if (chip->chip_select_num < MAX_CTRL_CS)
+ bfin_write_or(&drv_data->regs->flg, chip->flag >> 8);
}
static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,
struct bfin_spi_slave_data *chip)
{
- if (chip->chip_select_num < MAX_CTRL_CS) {
- u16 flag = read_FLAG(drv_data);
-
- flag &= ~(chip->flag >> 8);
-
- write_FLAG(drv_data, flag);
- }
+ if (chip->chip_select_num < MAX_CTRL_CS)
+ bfin_write_and(&drv_data->regs->flg, ~(chip->flag >> 8));
}
/* stop controller and re-config current chip*/
@@ -243,15 +203,15 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
struct bfin_spi_slave_data *chip = drv_data->cur_chip;
/* Clear status and disable clock */
- write_STAT(drv_data, BIT_STAT_CLR);
+ bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
bfin_spi_disable(drv_data);
dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
SSYNC();
/* Load the registers */
- write_CTRL(drv_data, chip->ctl_reg);
- write_BAUD(drv_data, chip->baud);
+ bfin_write(&drv_data->regs->ctl, chip->ctl_reg);
+ bfin_write(&drv_data->regs->baud, chip->baud);
bfin_spi_enable(drv_data);
bfin_spi_cs_active(drv_data, chip);
@@ -260,7 +220,7 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
/* used to kick off transfer in rx mode and read unwanted RX data */
static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)
{
- (void) read_RDBR(drv_data);
+ (void) bfin_read(&drv_data->regs->rdbr);
}
static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
@@ -269,10 +229,10 @@ static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->tx < drv_data->tx_end) {
- write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
+ bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
/* wait until transfer finished.
checking SPIF or TXS may not guarantee transfer completion */
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
/* discard RX data and clear RXS */
bfin_spi_dummy_read(drv_data);
@@ -287,10 +247,10 @@ static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
- write_TDBR(drv_data, tx_val);
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ bfin_write(&drv_data->regs->tdbr, tx_val);
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
- *(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
+ *(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
}
}
@@ -300,10 +260,10 @@ static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
- write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
- *(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
+ *(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
}
}
@@ -319,11 +279,11 @@ static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->tx < drv_data->tx_end) {
- write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+ bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
drv_data->tx += 2;
/* wait until transfer finished.
checking SPIF or TXS may not guarantee transfer completion */
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
/* discard RX data and clear RXS */
bfin_spi_dummy_read(drv_data);
@@ -338,10 +298,10 @@ static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
- write_TDBR(drv_data, tx_val);
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ bfin_write(&drv_data->regs->tdbr, tx_val);
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
- *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+ *(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
drv_data->rx += 2;
}
}
@@ -352,11 +312,11 @@ static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
- write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+ bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
drv_data->tx += 2;
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
- *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+ *(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
drv_data->rx += 2;
}
}
@@ -428,7 +388,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
int loop = 0;
/* wait until transfer finished. */
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
@@ -439,11 +399,11 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
if (n_bytes % 2) {
u16 *buf = (u16 *)drv_data->rx;
for (loop = 0; loop < n_bytes / 2; loop++)
- *buf++ = read_RDBR(drv_data);
+ *buf++ = bfin_read(&drv_data->regs->rdbr);
} else {
u8 *buf = (u8 *)drv_data->rx;
for (loop = 0; loop < n_bytes; loop++)
- *buf++ = read_RDBR(drv_data);
+ *buf++ = bfin_read(&drv_data->regs->rdbr);
}
drv_data->rx += n_bytes;
}
@@ -468,15 +428,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
u16 *buf = (u16 *)drv_data->rx;
u16 *buf2 = (u16 *)drv_data->tx;
for (loop = 0; loop < n_bytes / 2; loop++) {
- *buf++ = read_RDBR(drv_data);
- write_TDBR(drv_data, *buf2++);
+ *buf++ = bfin_read(&drv_data->regs->rdbr);
+ bfin_write(&drv_data->regs->tdbr, *buf2++);
}
} else {
u8 *buf = (u8 *)drv_data->rx;
u8 *buf2 = (u8 *)drv_data->tx;
for (loop = 0; loop < n_bytes; loop++) {
- *buf++ = read_RDBR(drv_data);
- write_TDBR(drv_data, *buf2++);
+ *buf++ = bfin_read(&drv_data->regs->rdbr);
+ bfin_write(&drv_data->regs->tdbr, *buf2++);
}
}
} else if (drv_data->rx) {
@@ -485,14 +445,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
if (n_bytes % 2) {
u16 *buf = (u16 *)drv_data->rx;
for (loop = 0; loop < n_bytes / 2; loop++) {
- *buf++ = read_RDBR(drv_data);
- write_TDBR(drv_data, chip->idle_tx_val);
+ *buf++ = bfin_read(&drv_data->regs->rdbr);
+ bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
}
} else {
u8 *buf = (u8 *)drv_data->rx;
for (loop = 0; loop < n_bytes; loop++) {
- *buf++ = read_RDBR(drv_data);
- write_TDBR(drv_data, chip->idle_tx_val);
+ *buf++ = bfin_read(&drv_data->regs->rdbr);
+ bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
}
}
} else if (drv_data->tx) {
@@ -501,14 +461,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
if (n_bytes % 2) {
u16 *buf = (u16 *)drv_data->tx;
for (loop = 0; loop < n_bytes / 2; loop++) {
- read_RDBR(drv_data);
- write_TDBR(drv_data, *buf++);
+ bfin_read(&drv_data->regs->rdbr);
+ bfin_write(&drv_data->regs->tdbr, *buf++);
}
} else {
u8 *buf = (u8 *)drv_data->tx;
for (loop = 0; loop < n_bytes; loop++) {
- read_RDBR(drv_data);
- write_TDBR(drv_data, *buf++);
+ bfin_read(&drv_data->regs->rdbr);
+ bfin_write(&drv_data->regs->tdbr, *buf++);
}
}
}
@@ -528,19 +488,19 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
struct spi_message *msg = drv_data->cur_msg;
unsigned long timeout;
unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
- u16 spistat = read_STAT(drv_data);
+ u16 spistat = bfin_read(&drv_data->regs->stat);
dev_dbg(&drv_data->pdev->dev,
"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
dmastat, spistat);
if (drv_data->rx != NULL) {
- u16 cr = read_CTRL(drv_data);
+ u16 cr = bfin_read(&drv_data->regs->ctl);
/* discard old RX data and clear RXS */
bfin_spi_dummy_read(drv_data);
- write_CTRL(drv_data, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
- write_CTRL(drv_data, cr & ~BIT_CTL_TIMOD); /* Restore State */
- write_STAT(drv_data, BIT_STAT_CLR); /* Clear Status */
+ bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
+ bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_TIMOD); /* Restore State */
+ bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); /* Clear Status */
}
clear_dma_irqstat(drv_data->dma_channel);
@@ -552,17 +512,17 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
* register until it goes low for 2 successive reads
*/
if (drv_data->tx != NULL) {
- while ((read_STAT(drv_data) & BIT_STAT_TXS) ||
- (read_STAT(drv_data) & BIT_STAT_TXS))
+ while ((bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS) ||
+ (bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS))
cpu_relax();
}
dev_dbg(&drv_data->pdev->dev,
"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
- dmastat, read_STAT(drv_data));
+ dmastat, bfin_read(&drv_data->regs->stat));
timeout = jiffies + HZ;
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
if (!time_before(jiffies, timeout)) {
dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
break;
@@ -699,9 +659,9 @@ static void bfin_spi_pump_transfers(unsigned long data)
bfin_spi_giveback(drv_data);
return;
}
- cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
+ cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
cr |= cr_width;
- write_CTRL(drv_data, cr);
+ bfin_write(&drv_data->regs->ctl, cr);
dev_dbg(&drv_data->pdev->dev,
"transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n",
@@ -712,11 +672,11 @@ static void bfin_spi_pump_transfers(unsigned long data)
/* Speed setup (surely valid because already checked) */
if (transfer->speed_hz)
- write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz));
+ bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
else
- write_BAUD(drv_data, chip->baud);
+ bfin_write(&drv_data->regs->baud, chip->baud);
- write_STAT(drv_data, BIT_STAT_CLR);
+ bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
bfin_spi_cs_active(drv_data, chip);
dev_dbg(&drv_data->pdev->dev,
@@ -749,7 +709,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
}
/* poll for SPI completion before start */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
cpu_relax();
/* dirty hack for autobuffer DMA mode */
@@ -766,7 +726,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
enable_dma(drv_data->dma_channel);
/* start SPI transfer */
- write_CTRL(drv_data, cr | BIT_CTL_TIMOD_DMA_TX);
+ bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TIMOD_DMA_TX);
/* just return here, there can only be one transfer
* in this mode
@@ -821,7 +781,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
set_dma_config(drv_data->dma_channel, dma_config);
local_irq_save(flags);
SSYNC();
- write_CTRL(drv_data, cr);
+ bfin_write(&drv_data->regs->ctl, cr);
enable_dma(drv_data->dma_channel);
dma_enable_irq(drv_data->dma_channel);
local_irq_restore(flags);
@@ -835,7 +795,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
* problems with setting up the output value in TDBR prior to the
* start of the transfer.
*/
- write_CTRL(drv_data, cr | BIT_CTL_TXMOD);
+ bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TXMOD);
if (chip->pio_interrupt) {
/* SPI irq should have been disabled by now */
@@ -845,19 +805,19 @@ static void bfin_spi_pump_transfers(unsigned long data)
/* start transfer */
if (drv_data->tx == NULL)
- write_TDBR(drv_data, chip->idle_tx_val);
+ bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
else {
int loop;
if (bits_per_word % 16 == 0) {
u16 *buf = (u16 *)drv_data->tx;
for (loop = 0; loop < bits_per_word / 16;
loop++) {
- write_TDBR(drv_data, *buf++);
+ bfin_write(&drv_data->regs->tdbr, *buf++);
}
} else if (bits_per_word % 8 == 0) {
u8 *buf = (u8 *)drv_data->tx;
for (loop = 0; loop < bits_per_word / 8; loop++)
- write_TDBR(drv_data, *buf++);
+ bfin_write(&drv_data->regs->tdbr, *buf++);
}
drv_data->tx += drv_data->n_bytes;
@@ -1005,7 +965,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
#define MAX_SPI_SSEL 7
-static u16 ssel[][MAX_SPI_SSEL] = {
+static const u16 ssel[][MAX_SPI_SSEL] = {
{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
P_SPI0_SSEL4, P_SPI0_SSEL5,
P_SPI0_SSEL6, P_SPI0_SSEL7},
@@ -1226,7 +1186,7 @@ static void bfin_spi_cleanup(struct spi_device *spi)
spi_set_ctldata(spi, NULL);
}
-static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
{
INIT_LIST_HEAD(&drv_data->queue);
spin_lock_init(&drv_data->lock);
@@ -1248,7 +1208,7 @@ static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
return 0;
}
-static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
{
unsigned long flags;
@@ -1270,7 +1230,7 @@ static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
return 0;
}
-static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
{
unsigned long flags;
unsigned limit = 500;
@@ -1299,7 +1259,7 @@ static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
return status;
}
-static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
{
int status;
@@ -1353,8 +1313,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
goto out_error_get_res;
}
- drv_data->regs_base = ioremap(res->start, resource_size(res));
- if (drv_data->regs_base == NULL) {
+ drv_data->regs = ioremap(res->start, resource_size(res));
+ if (drv_data->regs == NULL) {
dev_err(dev, "Cannot map IO\n");
status = -ENXIO;
goto out_error_ioremap;
@@ -1397,8 +1357,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
/* Reset SPI registers. If these registers were used by the boot loader,
* the sky may fall on your head if you enable the dma controller.
*/
- write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
- write_FLAG(drv_data, 0xFF00);
+ bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
+ bfin_write(&drv_data->regs->flg, 0xFF00);
/* Register with the SPI framework */
platform_set_drvdata(pdev, drv_data);
@@ -1408,15 +1368,15 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
goto out_error_queue_alloc;
}
- dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n",
- DRV_DESC, DRV_VERSION, drv_data->regs_base,
+ dev_info(dev, "%s, Version %s, regs@%p, dma channel@%d\n",
+ DRV_DESC, DRV_VERSION, drv_data->regs,
drv_data->dma_channel);
return status;
out_error_queue_alloc:
bfin_spi_destroy_queue(drv_data);
out_error_free_io:
- iounmap((void *) drv_data->regs_base);
+ iounmap(drv_data->regs);
out_error_ioremap:
out_error_get_res:
spi_master_put(master);
@@ -1473,14 +1433,14 @@ static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
if (status != 0)
return status;
- drv_data->ctrl_reg = read_CTRL(drv_data);
- drv_data->flag_reg = read_FLAG(drv_data);
+ drv_data->ctrl_reg = bfin_read(&drv_data->regs->ctl);
+ drv_data->flag_reg = bfin_read(&drv_data->regs->flg);
/*
* reset SPI_CTL and SPI_FLG registers
*/
- write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
- write_FLAG(drv_data, 0xFF00);
+ bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
+ bfin_write(&drv_data->regs->flg, 0xFF00);
return 0;
}
@@ -1490,8 +1450,8 @@ static int bfin_spi_resume(struct platform_device *pdev)
struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
int status = 0;
- write_CTRL(drv_data, drv_data->ctrl_reg);
- write_FLAG(drv_data, drv_data->flag_reg);
+ bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg);
+ bfin_write(&drv_data->regs->flg, drv_data->flag_reg);
/* Start the queue running */
status = bfin_spi_start_queue(drv_data);
diff --git a/drivers/spi/spi_bitbang_txrx.h b/drivers/spi/spi-bitbang-txrx.h
index c16bf853c3eb..c16bf853c3eb 100644
--- a/drivers/spi/spi_bitbang_txrx.h
+++ b/drivers/spi/spi-bitbang-txrx.h
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi-bitbang.c
index 14a63f6010d1..02d57fbba295 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -1,5 +1,5 @@
/*
- * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
+ * polling/bitbanging SPI master controller driver utilities
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -68,7 +68,7 @@ static unsigned bitbang_txrx_8(
unsigned ns,
struct spi_transfer *t
) {
- unsigned bits = spi->bits_per_word;
+ unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned count = t->len;
const u8 *tx = t->tx_buf;
u8 *rx = t->rx_buf;
@@ -94,7 +94,7 @@ static unsigned bitbang_txrx_16(
unsigned ns,
struct spi_transfer *t
) {
- unsigned bits = spi->bits_per_word;
+ unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned count = t->len;
const u16 *tx = t->tx_buf;
u16 *rx = t->rx_buf;
@@ -120,7 +120,7 @@ static unsigned bitbang_txrx_32(
unsigned ns,
struct spi_transfer *t
) {
- unsigned bits = spi->bits_per_word;
+ unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned count = t->len;
const u32 *tx = t->tx_buf;
u32 *rx = t->rx_buf;
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi-butterfly.c
index 0d4ceba3b590..9f907ec52def 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi-butterfly.c
@@ -1,5 +1,5 @@
/*
- * spi_butterfly.c - parport-to-butterfly adapter
+ * parport-to-butterfly adapter
*
* Copyright (C) 2005 David Brownell
*
@@ -149,7 +149,7 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
#define spidelay(X) do{}while(0)
//#define spidelay ndelay
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
static u32
butterfly_txrx_word_mode0(struct spi_device *spi,
diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/spi-coldfire-qspi.c
index ae2cd1c1fda8..ae2cd1c1fda8 100644
--- a/drivers/spi/coldfire_qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/spi-davinci.c
index 1f0ed8005c91..1f0ed8005c91 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/spi-davinci.c
diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/spi-dw-mid.c
index 489178243d88..130e55537db6 100644
--- a/drivers/spi/dw_spi_mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -1,5 +1,5 @@
/*
- * dw_spi_mid.c - special handling for DW core on Intel MID platform
+ * Special handling for DW core on Intel MID platform
*
* Copyright (c) 2009, Intel Corporation.
*
@@ -23,7 +23,7 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
-#include "dw_spi.h"
+#include "spi-dw.h"
#ifdef CONFIG_SPI_DW_MID_DMA
#include <linux/intel_mid_dma.h>
diff --git a/drivers/spi/dw_spi_mmio.c b/drivers/spi/spi-dw-mmio.c
index e0e813dad150..34eb66501dbf 100644
--- a/drivers/spi/dw_spi_mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -1,5 +1,5 @@
/*
- * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core
+ * Memory-mapped interface driver for DW SPI Core
*
* Copyright (c) 2010, Octasic semiconductor.
*
@@ -16,7 +16,7 @@
#include <linux/spi/spi.h>
#include <linux/scatterlist.h>
-#include "dw_spi.h"
+#include "spi-dw.h"
#define DRIVER_NAME "dw_spi_mmio"
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/spi-dw-pci.c
index ad260aa5e526..c5f37f03ac8b 100644
--- a/drivers/spi/dw_spi_pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -1,5 +1,5 @@
/*
- * dw_spi_pci.c - PCI interface driver for DW SPI Core
+ * PCI interface driver for DW SPI Core
*
* Copyright (c) 2009, Intel Corporation.
*
@@ -22,7 +22,7 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
-#include "dw_spi.h"
+#include "spi-dw.h"
#define DRIVER_NAME "dw_spi_pci"
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/spi-dw.c
index 919fa9d9e16b..857cd30b44bb 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/spi-dw.c
@@ -1,5 +1,5 @@
/*
- * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
+ * Designware SPI core controller driver (refer pxa2xx_spi.c)
*
* Copyright (c) 2009, Intel Corporation.
*
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
-#include "dw_spi.h"
+#include "spi-dw.h"
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
@@ -818,9 +818,11 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
dws->prev_chip = NULL;
dws->dma_inited = 0;
dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
+ snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
+ dws->bus_num);
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
- "dw_spi", dws);
+ dws->name, dws);
if (ret < 0) {
dev_err(&master->dev, "can not get IRQ\n");
goto err_free_master;
diff --git a/drivers/spi/dw_spi.h b/drivers/spi/spi-dw.h
index 7a5e78d2a5cb..8b7b07bf6c3f 100644
--- a/drivers/spi/dw_spi.h
+++ b/drivers/spi/spi-dw.h
@@ -96,6 +96,7 @@ struct dw_spi {
struct spi_device *cur_dev;
struct device *parent_dev;
enum dw_ssi_type type;
+ char name[16];
void __iomem *regs;
unsigned long paddr;
diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/spi-ep93xx.c
index d3570071e98f..1cf645479bfe 100644
--- a/drivers/spi/ep93xx_spi.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -1,7 +1,7 @@
/*
* Driver for Cirrus Logic EP93xx SPI controller.
*
- * Copyright (c) 2010 Mika Westerberg
+ * Copyright (C) 2010-2011 Mika Westerberg
*
* Explicit FIFO handling code was inspired by amba-pl022 driver.
*
@@ -21,13 +21,16 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/dmaengine.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
+#include <linux/scatterlist.h>
#include <linux/spi/spi.h>
+#include <mach/dma.h>
#include <mach/ep93xx_spi.h>
#define SSPCR0 0x0000
@@ -71,6 +74,7 @@
* @pdev: pointer to platform device
* @clk: clock for the controller
* @regs_base: pointer to ioremap()'d registers
+ * @sspdr_phys: physical address of the SSPDR register
* @irq: IRQ number used by the driver
* @min_rate: minimum clock rate (in Hz) supported by the controller
* @max_rate: maximum clock rate (in Hz) supported by the controller
@@ -84,6 +88,14 @@
* @rx: current byte in transfer to receive
* @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
* frame decreases this level and sending one frame increases it.
+ * @dma_rx: RX DMA channel
+ * @dma_tx: TX DMA channel
+ * @dma_rx_data: RX parameters passed to the DMA engine
+ * @dma_tx_data: TX parameters passed to the DMA engine
+ * @rx_sgt: sg table for RX transfers
+ * @tx_sgt: sg table for TX transfers
+ * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
+ * the client
*
* This structure holds EP93xx SPI controller specific information. When
* @running is %true, driver accepts transfer requests from protocol drivers.
@@ -100,6 +112,7 @@ struct ep93xx_spi {
const struct platform_device *pdev;
struct clk *clk;
void __iomem *regs_base;
+ unsigned long sspdr_phys;
int irq;
unsigned long min_rate;
unsigned long max_rate;
@@ -112,6 +125,13 @@ struct ep93xx_spi {
size_t tx;
size_t rx;
size_t fifo_level;
+ struct dma_chan *dma_rx;
+ struct dma_chan *dma_tx;
+ struct ep93xx_dma_data dma_rx_data;
+ struct ep93xx_dma_data dma_tx_data;
+ struct sg_table rx_sgt;
+ struct sg_table tx_sgt;
+ void *zeropage;
};
/**
@@ -496,14 +516,195 @@ static int ep93xx_spi_read_write(struct ep93xx_spi *espi)
espi->fifo_level++;
}
- if (espi->rx == t->len) {
- msg->actual_length += t->len;
+ if (espi->rx == t->len)
return 0;
- }
return -EINPROGRESS;
}
+static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
+{
+ /*
+ * Now everything is set up for the current transfer. We prime the TX
+ * FIFO, enable interrupts, and wait for the transfer to complete.
+ */
+ if (ep93xx_spi_read_write(espi)) {
+ ep93xx_spi_enable_interrupts(espi);
+ wait_for_completion(&espi->wait);
+ }
+}
+
+/**
+ * ep93xx_spi_dma_prepare() - prepares a DMA transfer
+ * @espi: ep93xx SPI controller struct
+ * @dir: DMA transfer direction
+ *
+ * Function configures the DMA, maps the buffer and prepares the DMA
+ * descriptor. Returns a valid DMA descriptor in case of success and ERR_PTR
+ * in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
+{
+ struct spi_transfer *t = espi->current_msg->state;
+ struct dma_async_tx_descriptor *txd;
+ enum dma_slave_buswidth buswidth;
+ struct dma_slave_config conf;
+ struct scatterlist *sg;
+ struct sg_table *sgt;
+ struct dma_chan *chan;
+ const void *buf, *pbuf;
+ size_t len = t->len;
+ int i, ret, nents;
+
+ if (bits_per_word(espi) > 8)
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ else
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+
+ memset(&conf, 0, sizeof(conf));
+ conf.direction = dir;
+
+ if (dir == DMA_FROM_DEVICE) {
+ chan = espi->dma_rx;
+ buf = t->rx_buf;
+ sgt = &espi->rx_sgt;
+
+ conf.src_addr = espi->sspdr_phys;
+ conf.src_addr_width = buswidth;
+ } else {
+ chan = espi->dma_tx;
+ buf = t->tx_buf;
+ sgt = &espi->tx_sgt;
+
+ conf.dst_addr = espi->sspdr_phys;
+ conf.dst_addr_width = buswidth;
+ }
+
+ ret = dmaengine_slave_config(chan, &conf);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /*
+ * We need to split the transfer into PAGE_SIZE'd chunks. This is
+ * because we are using @espi->zeropage to provide a zero RX buffer
+ * for the TX transfers and we have only allocated one page for that.
+ *
+ * For performance reasons we allocate a new sg_table only when
+ * needed. Otherwise we will re-use the current one. Eventually the
+ * last sg_table is released in ep93xx_spi_release_dma().
+ */
+
+ nents = DIV_ROUND_UP(len, PAGE_SIZE);
+ if (nents != sgt->nents) {
+ sg_free_table(sgt);
+
+ ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ pbuf = buf;
+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+ size_t bytes = min_t(size_t, len, PAGE_SIZE);
+
+ if (buf) {
+ sg_set_page(sg, virt_to_page(pbuf), bytes,
+ offset_in_page(pbuf));
+ } else {
+ sg_set_page(sg, virt_to_page(espi->zeropage),
+ bytes, 0);
+ }
+
+ pbuf += bytes;
+ len -= bytes;
+ }
+
+ if (WARN_ON(len)) {
+ dev_warn(&espi->pdev->dev, "len = %d expected 0!", len);
+ return ERR_PTR(-EINVAL);
+ }
+
+ nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+ if (!nents)
+ return ERR_PTR(-ENOMEM);
+
+ txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents,
+ dir, DMA_CTRL_ACK);
+ if (!txd) {
+ dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+ return ERR_PTR(-ENOMEM);
+ }
+ return txd;
+}
+
+/**
+ * ep93xx_spi_dma_finish() - finishes with a DMA transfer
+ * @espi: ep93xx SPI controller struct
+ * @dir: DMA transfer direction
+ *
+ * Function finishes with the DMA transfer. After this, the DMA buffer is
+ * unmapped.
+ */
+static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
+ enum dma_data_direction dir)
+{
+ struct dma_chan *chan;
+ struct sg_table *sgt;
+
+ if (dir == DMA_FROM_DEVICE) {
+ chan = espi->dma_rx;
+ sgt = &espi->rx_sgt;
+ } else {
+ chan = espi->dma_tx;
+ sgt = &espi->tx_sgt;
+ }
+
+ dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+}
+
+static void ep93xx_spi_dma_callback(void *callback_param)
+{
+ complete(callback_param);
+}
+
+static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
+{
+ struct spi_message *msg = espi->current_msg;
+ struct dma_async_tx_descriptor *rxd, *txd;
+
+ rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE);
+ if (IS_ERR(rxd)) {
+ dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
+ msg->status = PTR_ERR(rxd);
+ return;
+ }
+
+ txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
+ if (IS_ERR(txd)) {
+ ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+ dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
+ msg->status = PTR_ERR(txd);
+ return;
+ }
+
+ /* We are ready when RX is done */
+ rxd->callback = ep93xx_spi_dma_callback;
+ rxd->callback_param = &espi->wait;
+
+ /* Now submit both descriptors and wait while they finish */
+ dmaengine_submit(rxd);
+ dmaengine_submit(txd);
+
+ dma_async_issue_pending(espi->dma_rx);
+ dma_async_issue_pending(espi->dma_tx);
+
+ wait_for_completion(&espi->wait);
+
+ ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
+ ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+}
+
/**
* ep93xx_spi_process_transfer() - processes one SPI transfer
* @espi: ep93xx SPI controller struct
@@ -556,13 +757,14 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
espi->tx = 0;
/*
- * Now everything is set up for the current transfer. We prime the TX
- * FIFO, enable interrupts, and wait for the transfer to complete.
+ * There is no point of setting up DMA for the transfers which will
+ * fit into the FIFO and can be transferred with a single interrupt.
+ * So in these cases we will be using PIO and don't bother for DMA.
*/
- if (ep93xx_spi_read_write(espi)) {
- ep93xx_spi_enable_interrupts(espi);
- wait_for_completion(&espi->wait);
- }
+ if (espi->dma_rx && t->len > SPI_FIFO_SIZE)
+ ep93xx_spi_dma_transfer(espi);
+ else
+ ep93xx_spi_pio_transfer(espi);
/*
* In case of error during transmit, we bail out from processing
@@ -571,6 +773,8 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
if (msg->status)
return;
+ msg->actual_length += t->len;
+
/*
* After this transfer is finished, perform any possible
* post-transfer actions requested by the protocol driver.
@@ -752,6 +956,75 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static bool ep93xx_spi_dma_filter(struct dma_chan *chan, void *filter_param)
+{
+ if (ep93xx_dma_chan_is_m2p(chan))
+ return false;
+
+ chan->private = filter_param;
+ return true;
+}
+
+static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
+{
+ dma_cap_mask_t mask;
+ int ret;
+
+ espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!espi->zeropage)
+ return -ENOMEM;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ espi->dma_rx_data.port = EP93XX_DMA_SSP;
+ espi->dma_rx_data.direction = DMA_FROM_DEVICE;
+ espi->dma_rx_data.name = "ep93xx-spi-rx";
+
+ espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
+ &espi->dma_rx_data);
+ if (!espi->dma_rx) {
+ ret = -ENODEV;
+ goto fail_free_page;
+ }
+
+ espi->dma_tx_data.port = EP93XX_DMA_SSP;
+ espi->dma_tx_data.direction = DMA_TO_DEVICE;
+ espi->dma_tx_data.name = "ep93xx-spi-tx";
+
+ espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
+ &espi->dma_tx_data);
+ if (!espi->dma_tx) {
+ ret = -ENODEV;
+ goto fail_release_rx;
+ }
+
+ return 0;
+
+fail_release_rx:
+ dma_release_channel(espi->dma_rx);
+ espi->dma_rx = NULL;
+fail_free_page:
+ free_page((unsigned long)espi->zeropage);
+
+ return ret;
+}
+
+static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
+{
+ if (espi->dma_rx) {
+ dma_release_channel(espi->dma_rx);
+ sg_free_table(&espi->rx_sgt);
+ }
+ if (espi->dma_tx) {
+ dma_release_channel(espi->dma_tx);
+ sg_free_table(&espi->tx_sgt);
+ }
+
+ if (espi->zeropage)
+ free_page((unsigned long)espi->zeropage);
+}
+
static int __init ep93xx_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
@@ -818,6 +1091,7 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
goto fail_put_clock;
}
+ espi->sspdr_phys = res->start + SSPDR;
espi->regs_base = ioremap(res->start, resource_size(res));
if (!espi->regs_base) {
dev_err(&pdev->dev, "failed to map resources\n");
@@ -832,10 +1106,13 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
goto fail_unmap_regs;
}
+ if (info->use_dma && ep93xx_spi_setup_dma(espi))
+ dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
+
espi->wq = create_singlethread_workqueue("ep93xx_spid");
if (!espi->wq) {
dev_err(&pdev->dev, "unable to create workqueue\n");
- goto fail_free_irq;
+ goto fail_free_dma;
}
INIT_WORK(&espi->msg_work, ep93xx_spi_work);
INIT_LIST_HEAD(&espi->msg_queue);
@@ -857,7 +1134,8 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
fail_free_queue:
destroy_workqueue(espi->wq);
-fail_free_irq:
+fail_free_dma:
+ ep93xx_spi_release_dma(espi);
free_irq(espi->irq, espi);
fail_unmap_regs:
iounmap(espi->regs_base);
@@ -901,6 +1179,7 @@ static int __exit ep93xx_spi_remove(struct platform_device *pdev)
}
spin_unlock_irq(&espi->lock);
+ ep93xx_spi_release_dma(espi);
free_irq(espi->irq, espi);
iounmap(espi->regs_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi-fsl-espi.c
index 496f895a0024..54e499d5f92c 100644
--- a/drivers/spi/spi_fsl_espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -22,7 +22,7 @@
#include <linux/err.h>
#include <sysdev/fsl_soc.h>
-#include "spi_fsl_lib.h"
+#include "spi-fsl-lib.h"
/* eSPI Controller registers */
struct fsl_espi_reg {
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi-fsl-lib.c
index ff59f42ae990..2674fad7f68a 100644
--- a/drivers/spi/spi_fsl_lib.c
+++ b/drivers/spi/spi-fsl-lib.c
@@ -25,7 +25,7 @@
#include <linux/of_spi.h>
#include <sysdev/fsl_soc.h>
-#include "spi_fsl_lib.h"
+#include "spi-fsl-lib.h"
#define MPC8XXX_SPI_RX_BUF(type) \
void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi-fsl-lib.h
index cbe881b9ea76..cbe881b9ea76 100644
--- a/drivers/spi/spi_fsl_lib.h
+++ b/drivers/spi/spi-fsl-lib.h
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi-fsl-spi.c
index 7963c9b49566..d2407558773f 100644
--- a/drivers/spi/spi_fsl_spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -37,7 +37,7 @@
#include <asm/cpm.h>
#include <asm/qe.h>
-#include "spi_fsl_lib.h"
+#include "spi-fsl-lib.h"
/* CPM1 and CPM2 are mutually exclusive. */
#ifdef CONFIG_CPM1
@@ -684,7 +684,7 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
struct device_node *np = dev->of_node;
const u32 *iprop;
int size;
- unsigned long spi_base_ofs;
+ void __iomem *spi_base;
unsigned long pram_ofs = -ENOMEM;
/* Can't use of_address_to_resource(), QE muram isn't at 0. */
@@ -702,33 +702,27 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
return pram_ofs;
}
- /* CPM1 and CPM2 pram must be at a fixed addr. */
- if (!iprop || size != sizeof(*iprop) * 4)
- return -ENOMEM;
-
- spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
- if (IS_ERR_VALUE(spi_base_ofs))
- return -ENOMEM;
+ spi_base = of_iomap(np, 1);
+ if (spi_base == NULL)
+ return -EINVAL;
if (mspi->flags & SPI_CPM2) {
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
- if (!IS_ERR_VALUE(pram_ofs)) {
- u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
-
- out_be16(spi_base, pram_ofs);
- }
+ out_be16(spi_base, pram_ofs);
} else {
- struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
+ struct spi_pram __iomem *pram = spi_base;
u16 rpbase = in_be16(&pram->rpbase);
/* Microcode relocation patch applied? */
if (rpbase)
pram_ofs = rpbase;
- else
- return spi_base_ofs;
+ else {
+ pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+ out_be16(spi_base, pram_ofs);
+ }
}
- cpm_muram_free(spi_base_ofs);
+ iounmap(spi_base);
return pram_ofs;
}
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi-gpio.c
index 63e51b011d50..0e88ab745490 100644
--- a/drivers/spi/spi_gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -1,5 +1,5 @@
/*
- * spi_gpio.c - SPI master driver using generic bitbanged GPIO
+ * SPI master driver using generic bitbanged GPIO
*
* Copyright (C) 2006,2008 David Brownell
*
@@ -69,7 +69,7 @@ struct spi_gpio {
* #define SPI_MOSI_GPIO 120
* #define SPI_SCK_GPIO 121
* #define SPI_N_CHIPSEL 4
- * #include "spi_gpio.c"
+ * #include "spi-gpio.c"
*/
#ifndef DRIVER_NAME
@@ -127,7 +127,7 @@ static inline int getmiso(const struct spi_device *spi)
*/
#define spidelay(nsecs) do {} while (0)
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
/*
* These functions can leverage inline expansion of GPIO calls to shrink
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi-imx.c
index 69d6dba67c19..8ac6542aedcd 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi-imx.c
@@ -34,6 +34,9 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <mach/spi.h>
@@ -45,9 +48,6 @@
#define MXC_CSPIINT 0x0c
#define MXC_RESET 0x1c
-#define MX3_CSPISTAT 0x14
-#define MX3_CSPISTAT_RR (1 << 3)
-
/* generic defines to abstract from the different register layouts */
#define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
#define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
@@ -60,12 +60,12 @@ struct spi_imx_config {
};
enum spi_imx_devtype {
- SPI_IMX_VER_IMX1,
- SPI_IMX_VER_0_0,
- SPI_IMX_VER_0_4,
- SPI_IMX_VER_0_5,
- SPI_IMX_VER_0_7,
- SPI_IMX_VER_2_3,
+ IMX1_CSPI,
+ IMX21_CSPI,
+ IMX27_CSPI,
+ IMX31_CSPI,
+ IMX35_CSPI, /* CSPI on all i.mx except above */
+ IMX51_ECSPI, /* ECSPI on i.mx51 and later */
};
struct spi_imx_data;
@@ -76,7 +76,7 @@ struct spi_imx_devtype_data {
void (*trigger)(struct spi_imx_data *);
int (*rx_available)(struct spi_imx_data *);
void (*reset)(struct spi_imx_data *);
- unsigned int fifosize;
+ enum spi_imx_devtype devtype;
};
struct spi_imx_data {
@@ -87,7 +87,6 @@ struct spi_imx_data {
int irq;
struct clk *clk;
unsigned long spi_clk;
- int *chipselect;
unsigned int count;
void (*tx)(struct spi_imx_data *);
@@ -96,9 +95,25 @@ struct spi_imx_data {
const void *tx_buf;
unsigned int txfifo; /* number of words pushed in tx FIFO */
- struct spi_imx_devtype_data devtype_data;
+ struct spi_imx_devtype_data *devtype_data;
+ int chipselect[0];
};
+static inline int is_imx27_cspi(struct spi_imx_data *d)
+{
+ return d->devtype_data->devtype == IMX27_CSPI;
+}
+
+static inline int is_imx35_cspi(struct spi_imx_data *d)
+{
+ return d->devtype_data->devtype == IMX35_CSPI;
+}
+
+static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
+{
+ return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+}
+
#define MXC_SPI_BUF_RX(type) \
static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \
{ \
@@ -140,14 +155,9 @@ static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
/* MX21, MX27 */
static unsigned int spi_imx_clkdiv_1(unsigned int fin,
- unsigned int fspi)
+ unsigned int fspi, unsigned int max)
{
- int i, max;
-
- if (cpu_is_mx21())
- max = 18;
- else
- max = 16;
+ int i;
for (i = 2; i < max; i++)
if (fspi * mxc_clkdivs[i] >= fin)
@@ -171,30 +181,30 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
}
-#define SPI_IMX2_3_CTRL 0x08
-#define SPI_IMX2_3_CTRL_ENABLE (1 << 0)
-#define SPI_IMX2_3_CTRL_XCH (1 << 2)
-#define SPI_IMX2_3_CTRL_MODE_MASK (0xf << 4)
-#define SPI_IMX2_3_CTRL_POSTDIV_OFFSET 8
-#define SPI_IMX2_3_CTRL_PREDIV_OFFSET 12
-#define SPI_IMX2_3_CTRL_CS(cs) ((cs) << 18)
-#define SPI_IMX2_3_CTRL_BL_OFFSET 20
+#define MX51_ECSPI_CTRL 0x08
+#define MX51_ECSPI_CTRL_ENABLE (1 << 0)
+#define MX51_ECSPI_CTRL_XCH (1 << 2)
+#define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4)
+#define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8
+#define MX51_ECSPI_CTRL_PREDIV_OFFSET 12
+#define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18)
+#define MX51_ECSPI_CTRL_BL_OFFSET 20
-#define SPI_IMX2_3_CONFIG 0x0c
-#define SPI_IMX2_3_CONFIG_SCLKPHA(cs) (1 << ((cs) + 0))
-#define SPI_IMX2_3_CONFIG_SCLKPOL(cs) (1 << ((cs) + 4))
-#define SPI_IMX2_3_CONFIG_SBBCTRL(cs) (1 << ((cs) + 8))
-#define SPI_IMX2_3_CONFIG_SSBPOL(cs) (1 << ((cs) + 12))
+#define MX51_ECSPI_CONFIG 0x0c
+#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs) + 0))
+#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs) + 4))
+#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs) + 8))
+#define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs) + 12))
-#define SPI_IMX2_3_INT 0x10
-#define SPI_IMX2_3_INT_TEEN (1 << 0)
-#define SPI_IMX2_3_INT_RREN (1 << 3)
+#define MX51_ECSPI_INT 0x10
+#define MX51_ECSPI_INT_TEEN (1 << 0)
+#define MX51_ECSPI_INT_RREN (1 << 3)
-#define SPI_IMX2_3_STAT 0x18
-#define SPI_IMX2_3_STAT_RR (1 << 3)
+#define MX51_ECSPI_STAT 0x18
+#define MX51_ECSPI_STAT_RR (1 << 3)
/* MX51 eCSPI */
-static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)
+static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
{
/*
* there are two 4-bit dividers, the pre-divider divides by
@@ -222,36 +232,36 @@ static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)
pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
__func__, fin, fspi, post, pre);
- return (pre << SPI_IMX2_3_CTRL_PREDIV_OFFSET) |
- (post << SPI_IMX2_3_CTRL_POSTDIV_OFFSET);
+ return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
+ (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
}
-static void __maybe_unused spi_imx2_3_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned val = 0;
if (enable & MXC_INT_TE)
- val |= SPI_IMX2_3_INT_TEEN;
+ val |= MX51_ECSPI_INT_TEEN;
if (enable & MXC_INT_RR)
- val |= SPI_IMX2_3_INT_RREN;
+ val |= MX51_ECSPI_INT_RREN;
- writel(val, spi_imx->base + SPI_IMX2_3_INT);
+ writel(val, spi_imx->base + MX51_ECSPI_INT);
}
-static void __maybe_unused spi_imx2_3_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
{
u32 reg;
- reg = readl(spi_imx->base + SPI_IMX2_3_CTRL);
- reg |= SPI_IMX2_3_CTRL_XCH;
- writel(reg, spi_imx->base + SPI_IMX2_3_CTRL);
+ reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
+ reg |= MX51_ECSPI_CTRL_XCH;
+ writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
}
-static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config)
{
- u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0;
+ u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
/*
* The hardware seems to have a race condition when changing modes. The
@@ -260,42 +270,42 @@ static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
* the same time.
* So set master mode for all channels as we do not support slave mode.
*/
- ctrl |= SPI_IMX2_3_CTRL_MODE_MASK;
+ ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
/* set clock speed */
- ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz);
+ ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);
/* set chip select to use */
- ctrl |= SPI_IMX2_3_CTRL_CS(config->cs);
+ ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
- ctrl |= (config->bpw - 1) << SPI_IMX2_3_CTRL_BL_OFFSET;
+ ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
- cfg |= SPI_IMX2_3_CONFIG_SBBCTRL(config->cs);
+ cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs);
if (config->mode & SPI_CPHA)
- cfg |= SPI_IMX2_3_CONFIG_SCLKPHA(config->cs);
+ cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
if (config->mode & SPI_CPOL)
- cfg |= SPI_IMX2_3_CONFIG_SCLKPOL(config->cs);
+ cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
if (config->mode & SPI_CS_HIGH)
- cfg |= SPI_IMX2_3_CONFIG_SSBPOL(config->cs);
+ cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
- writel(ctrl, spi_imx->base + SPI_IMX2_3_CTRL);
- writel(cfg, spi_imx->base + SPI_IMX2_3_CONFIG);
+ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
+ writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
return 0;
}
-static int __maybe_unused spi_imx2_3_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(spi_imx->base + SPI_IMX2_3_STAT) & SPI_IMX2_3_STAT_RR;
+ return readl(spi_imx->base + MX51_ECSPI_STAT) & MX51_ECSPI_STAT_RR;
}
-static void __maybe_unused spi_imx2_3_reset(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx)
{
/* drain receive buffer */
- while (spi_imx2_3_rx_available(spi_imx))
+ while (mx51_ecspi_rx_available(spi_imx))
readl(spi_imx->base + MXC_CSPIRXDATA);
}
@@ -343,32 +353,7 @@ static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int __maybe_unused spi_imx0_4_config(struct spi_imx_data *spi_imx,
- struct spi_imx_config *config)
-{
- unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
- int cs = spi_imx->chipselect[config->cs];
-
- reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
- MX31_CSPICTRL_DR_SHIFT;
-
- reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
-
- if (config->mode & SPI_CPHA)
- reg |= MX31_CSPICTRL_PHA;
- if (config->mode & SPI_CPOL)
- reg |= MX31_CSPICTRL_POL;
- if (config->mode & SPI_CS_HIGH)
- reg |= MX31_CSPICTRL_SSPOL;
- if (cs < 0)
- reg |= (cs + 32) << MX31_CSPICTRL_CS_SHIFT;
-
- writel(reg, spi_imx->base + MXC_CSPICTRL);
-
- return 0;
-}
-
-static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config)
{
unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
@@ -377,8 +362,12 @@ static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
MX31_CSPICTRL_DR_SHIFT;
- reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
- reg |= MX31_CSPICTRL_SSCTL;
+ if (is_imx35_cspi(spi_imx)) {
+ reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
+ reg |= MX31_CSPICTRL_SSCTL;
+ } else {
+ reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
+ }
if (config->mode & SPI_CPHA)
reg |= MX31_CSPICTRL_PHA;
@@ -387,7 +376,9 @@ static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
if (config->mode & SPI_CS_HIGH)
reg |= MX31_CSPICTRL_SSPOL;
if (cs < 0)
- reg |= (cs + 32) << MX35_CSPICTRL_CS_SHIFT;
+ reg |= (cs + 32) <<
+ (is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT :
+ MX31_CSPICTRL_CS_SHIFT);
writel(reg, spi_imx->base + MXC_CSPICTRL);
@@ -399,77 +390,78 @@ static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
}
-static void __maybe_unused spi_imx0_4_reset(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx)
{
/* drain receive buffer */
- while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
+ while (readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR)
readl(spi_imx->base + MXC_CSPIRXDATA);
}
-#define MX27_INTREG_RR (1 << 4)
-#define MX27_INTREG_TEEN (1 << 9)
-#define MX27_INTREG_RREN (1 << 13)
+#define MX21_INTREG_RR (1 << 4)
+#define MX21_INTREG_TEEN (1 << 9)
+#define MX21_INTREG_RREN (1 << 13)
-#define MX27_CSPICTRL_POL (1 << 5)
-#define MX27_CSPICTRL_PHA (1 << 6)
-#define MX27_CSPICTRL_SSPOL (1 << 8)
-#define MX27_CSPICTRL_XCH (1 << 9)
-#define MX27_CSPICTRL_ENABLE (1 << 10)
-#define MX27_CSPICTRL_MASTER (1 << 11)
-#define MX27_CSPICTRL_DR_SHIFT 14
-#define MX27_CSPICTRL_CS_SHIFT 19
+#define MX21_CSPICTRL_POL (1 << 5)
+#define MX21_CSPICTRL_PHA (1 << 6)
+#define MX21_CSPICTRL_SSPOL (1 << 8)
+#define MX21_CSPICTRL_XCH (1 << 9)
+#define MX21_CSPICTRL_ENABLE (1 << 10)
+#define MX21_CSPICTRL_MASTER (1 << 11)
+#define MX21_CSPICTRL_DR_SHIFT 14
+#define MX21_CSPICTRL_CS_SHIFT 19
-static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned int val = 0;
if (enable & MXC_INT_TE)
- val |= MX27_INTREG_TEEN;
+ val |= MX21_INTREG_TEEN;
if (enable & MXC_INT_RR)
- val |= MX27_INTREG_RREN;
+ val |= MX21_INTREG_RREN;
writel(val, spi_imx->base + MXC_CSPIINT);
}
-static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx)
{
unsigned int reg;
reg = readl(spi_imx->base + MXC_CSPICTRL);
- reg |= MX27_CSPICTRL_XCH;
+ reg |= MX21_CSPICTRL_XCH;
writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config)
{
- unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
+ unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER;
int cs = spi_imx->chipselect[config->cs];
+ unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18;
- reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) <<
- MX27_CSPICTRL_DR_SHIFT;
+ reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) <<
+ MX21_CSPICTRL_DR_SHIFT;
reg |= config->bpw - 1;
if (config->mode & SPI_CPHA)
- reg |= MX27_CSPICTRL_PHA;
+ reg |= MX21_CSPICTRL_PHA;
if (config->mode & SPI_CPOL)
- reg |= MX27_CSPICTRL_POL;
+ reg |= MX21_CSPICTRL_POL;
if (config->mode & SPI_CS_HIGH)
- reg |= MX27_CSPICTRL_SSPOL;
+ reg |= MX21_CSPICTRL_SSPOL;
if (cs < 0)
- reg |= (cs + 32) << MX27_CSPICTRL_CS_SHIFT;
+ reg |= (cs + 32) << MX21_CSPICTRL_CS_SHIFT;
writel(reg, spi_imx->base + MXC_CSPICTRL);
return 0;
}
-static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx21_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
+ return readl(spi_imx->base + MXC_CSPIINT) & MX21_INTREG_RR;
}
-static void __maybe_unused spi_imx0_0_reset(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx)
{
writel(1, spi_imx->base + MXC_RESET);
}
@@ -535,61 +527,94 @@ static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
writel(1, spi_imx->base + MXC_RESET);
}
-/*
- * These version numbers are taken from the Freescale driver. Unfortunately it
- * doesn't support i.MX1, so this entry doesn't match the scheme. :-(
- */
-static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = {
-#ifdef CONFIG_SPI_IMX_VER_IMX1
- [SPI_IMX_VER_IMX1] = {
- .intctrl = mx1_intctrl,
- .config = mx1_config,
- .trigger = mx1_trigger,
- .rx_available = mx1_rx_available,
- .reset = mx1_reset,
- .fifosize = 8,
- },
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_0
- [SPI_IMX_VER_0_0] = {
- .intctrl = mx27_intctrl,
- .config = mx27_config,
- .trigger = mx27_trigger,
- .rx_available = mx27_rx_available,
- .reset = spi_imx0_0_reset,
- .fifosize = 8,
- },
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_4
- [SPI_IMX_VER_0_4] = {
- .intctrl = mx31_intctrl,
- .config = spi_imx0_4_config,
- .trigger = mx31_trigger,
- .rx_available = mx31_rx_available,
- .reset = spi_imx0_4_reset,
- .fifosize = 8,
- },
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_7
- [SPI_IMX_VER_0_7] = {
- .intctrl = mx31_intctrl,
- .config = spi_imx0_7_config,
- .trigger = mx31_trigger,
- .rx_available = mx31_rx_available,
- .reset = spi_imx0_4_reset,
- .fifosize = 8,
- },
-#endif
-#ifdef CONFIG_SPI_IMX_VER_2_3
- [SPI_IMX_VER_2_3] = {
- .intctrl = spi_imx2_3_intctrl,
- .config = spi_imx2_3_config,
- .trigger = spi_imx2_3_trigger,
- .rx_available = spi_imx2_3_rx_available,
- .reset = spi_imx2_3_reset,
- .fifosize = 64,
- },
-#endif
+static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
+ .intctrl = mx1_intctrl,
+ .config = mx1_config,
+ .trigger = mx1_trigger,
+ .rx_available = mx1_rx_available,
+ .reset = mx1_reset,
+ .devtype = IMX1_CSPI,
+};
+
+static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
+ .intctrl = mx21_intctrl,
+ .config = mx21_config,
+ .trigger = mx21_trigger,
+ .rx_available = mx21_rx_available,
+ .reset = mx21_reset,
+ .devtype = IMX21_CSPI,
+};
+
+static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
+ /* i.mx27 cspi shares the functions with i.mx21 one */
+ .intctrl = mx21_intctrl,
+ .config = mx21_config,
+ .trigger = mx21_trigger,
+ .rx_available = mx21_rx_available,
+ .reset = mx21_reset,
+ .devtype = IMX27_CSPI,
+};
+
+static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
+ .intctrl = mx31_intctrl,
+ .config = mx31_config,
+ .trigger = mx31_trigger,
+ .rx_available = mx31_rx_available,
+ .reset = mx31_reset,
+ .devtype = IMX31_CSPI,
+};
+
+static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
+ /* i.mx35 and later cspi shares the functions with i.mx31 one */
+ .intctrl = mx31_intctrl,
+ .config = mx31_config,
+ .trigger = mx31_trigger,
+ .rx_available = mx31_rx_available,
+ .reset = mx31_reset,
+ .devtype = IMX35_CSPI,
+};
+
+static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
+ .intctrl = mx51_ecspi_intctrl,
+ .config = mx51_ecspi_config,
+ .trigger = mx51_ecspi_trigger,
+ .rx_available = mx51_ecspi_rx_available,
+ .reset = mx51_ecspi_reset,
+ .devtype = IMX51_ECSPI,
+};
+
+static struct platform_device_id spi_imx_devtype[] = {
+ {
+ .name = "imx1-cspi",
+ .driver_data = (kernel_ulong_t) &imx1_cspi_devtype_data,
+ }, {
+ .name = "imx21-cspi",
+ .driver_data = (kernel_ulong_t) &imx21_cspi_devtype_data,
+ }, {
+ .name = "imx27-cspi",
+ .driver_data = (kernel_ulong_t) &imx27_cspi_devtype_data,
+ }, {
+ .name = "imx31-cspi",
+ .driver_data = (kernel_ulong_t) &imx31_cspi_devtype_data,
+ }, {
+ .name = "imx35-cspi",
+ .driver_data = (kernel_ulong_t) &imx35_cspi_devtype_data,
+ }, {
+ .name = "imx51-ecspi",
+ .driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data,
+ }, {
+ /* sentinel */
+ }
+};
+
+static const struct of_device_id spi_imx_dt_ids[] = {
+ { .compatible = "fsl,imx1-cspi", .data = &imx1_cspi_devtype_data, },
+ { .compatible = "fsl,imx21-cspi", .data = &imx21_cspi_devtype_data, },
+ { .compatible = "fsl,imx27-cspi", .data = &imx27_cspi_devtype_data, },
+ { .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, },
+ { .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, },
+ { .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
+ { /* sentinel */ }
};
static void spi_imx_chipselect(struct spi_device *spi, int is_active)
@@ -607,21 +632,21 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active)
static void spi_imx_push(struct spi_imx_data *spi_imx)
{
- while (spi_imx->txfifo < spi_imx->devtype_data.fifosize) {
+ while (spi_imx->txfifo < spi_imx_get_fifosize(spi_imx)) {
if (!spi_imx->count)
break;
spi_imx->tx(spi_imx);
spi_imx->txfifo++;
}
- spi_imx->devtype_data.trigger(spi_imx);
+ spi_imx->devtype_data->trigger(spi_imx);
}
static irqreturn_t spi_imx_isr(int irq, void *dev_id)
{
struct spi_imx_data *spi_imx = dev_id;
- while (spi_imx->devtype_data.rx_available(spi_imx)) {
+ while (spi_imx->devtype_data->rx_available(spi_imx)) {
spi_imx->rx(spi_imx);
spi_imx->txfifo--;
}
@@ -635,12 +660,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
/* No data left to push, but still waiting for rx data,
* enable receive data available interrupt.
*/
- spi_imx->devtype_data.intctrl(
+ spi_imx->devtype_data->intctrl(
spi_imx, MXC_INT_RR);
return IRQ_HANDLED;
}
- spi_imx->devtype_data.intctrl(spi_imx, 0);
+ spi_imx->devtype_data->intctrl(spi_imx, 0);
complete(&spi_imx->xfer_done);
return IRQ_HANDLED;
@@ -677,7 +702,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
} else
BUG();
- spi_imx->devtype_data.config(spi_imx, &config);
+ spi_imx->devtype_data->config(spi_imx, &config);
return 0;
}
@@ -696,7 +721,7 @@ static int spi_imx_transfer(struct spi_device *spi,
spi_imx_push(spi_imx);
- spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE);
+ spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE);
wait_for_completion(&spi_imx->xfer_done);
@@ -723,72 +748,47 @@ static void spi_imx_cleanup(struct spi_device *spi)
{
}
-static struct platform_device_id spi_imx_devtype[] = {
- {
- .name = "imx1-cspi",
- .driver_data = SPI_IMX_VER_IMX1,
- }, {
- .name = "imx21-cspi",
- .driver_data = SPI_IMX_VER_0_0,
- }, {
- .name = "imx25-cspi",
- .driver_data = SPI_IMX_VER_0_7,
- }, {
- .name = "imx27-cspi",
- .driver_data = SPI_IMX_VER_0_0,
- }, {
- .name = "imx31-cspi",
- .driver_data = SPI_IMX_VER_0_4,
- }, {
- .name = "imx35-cspi",
- .driver_data = SPI_IMX_VER_0_7,
- }, {
- .name = "imx51-cspi",
- .driver_data = SPI_IMX_VER_0_7,
- }, {
- .name = "imx51-ecspi",
- .driver_data = SPI_IMX_VER_2_3,
- }, {
- .name = "imx53-cspi",
- .driver_data = SPI_IMX_VER_0_7,
- }, {
- .name = "imx53-ecspi",
- .driver_data = SPI_IMX_VER_2_3,
- }, {
- /* sentinel */
- }
-};
-
static int __devinit spi_imx_probe(struct platform_device *pdev)
{
- struct spi_imx_master *mxc_platform_info;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(spi_imx_dt_ids, &pdev->dev);
+ struct spi_imx_master *mxc_platform_info =
+ dev_get_platdata(&pdev->dev);
struct spi_master *master;
struct spi_imx_data *spi_imx;
struct resource *res;
- int i, ret;
+ int i, ret, num_cs;
- mxc_platform_info = dev_get_platdata(&pdev->dev);
- if (!mxc_platform_info) {
+ if (!np && !mxc_platform_info) {
dev_err(&pdev->dev, "can't get the platform data\n");
return -EINVAL;
}
- master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
+ ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
+ if (ret < 0)
+ num_cs = mxc_platform_info->num_chipselect;
+
+ master = spi_alloc_master(&pdev->dev,
+ sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
if (!master)
return -ENOMEM;
platform_set_drvdata(pdev, master);
master->bus_num = pdev->id;
- master->num_chipselect = mxc_platform_info->num_chipselect;
+ master->num_chipselect = num_cs;
spi_imx = spi_master_get_devdata(master);
spi_imx->bitbang.master = spi_master_get(master);
- spi_imx->chipselect = mxc_platform_info->chipselect;
for (i = 0; i < master->num_chipselect; i++) {
- if (spi_imx->chipselect[i] < 0)
+ int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
+ if (cs_gpio < 0)
+ cs_gpio = mxc_platform_info->chipselect[i];
+ if (cs_gpio < 0)
continue;
+ spi_imx->chipselect[i] = cs_gpio;
ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
if (ret) {
while (i > 0) {
@@ -810,8 +810,8 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
init_completion(&spi_imx->xfer_done);
- spi_imx->devtype_data =
- spi_imx_devtype_data[pdev->id_entry->driver_data];
+ spi_imx->devtype_data = of_id ? of_id->data :
+ (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -854,10 +854,11 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
clk_enable(spi_imx->clk);
spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
- spi_imx->devtype_data.reset(spi_imx);
+ spi_imx->devtype_data->reset(spi_imx);
- spi_imx->devtype_data.intctrl(spi_imx, 0);
+ spi_imx->devtype_data->intctrl(spi_imx, 0);
+ master->dev.of_node = pdev->dev.of_node;
ret = spi_bitbang_start(&spi_imx->bitbang);
if (ret) {
dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
@@ -920,6 +921,7 @@ static struct platform_driver spi_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
+ .of_match_table = spi_imx_dt_ids,
},
.id_table = spi_imx_devtype,
.probe = spi_imx_probe,
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi-lm70llp.c
index 7746a41ab6d6..933eb9d9ddd4 100644
--- a/drivers/spi/spi_lm70llp.c
+++ b/drivers/spi/spi-lm70llp.c
@@ -1,5 +1,5 @@
/*
- * spi_lm70llp.c - driver for LM70EVAL-LLP board for the LM70 sensor
+ * Driver for LM70EVAL-LLP board for the LM70 sensor
*
* Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
*
@@ -174,7 +174,7 @@ static inline int getmiso(struct spi_device *s)
}
/*--------------------------------------------------------------------*/
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
static void lm70_chipselect(struct spi_device *spi, int value)
{
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/spi-mpc512x-psc.c
index 6a5b4238fb6b..6a5b4238fb6b 100644
--- a/drivers/spi/mpc512x_psc_spi.c
+++ b/drivers/spi/spi-mpc512x-psc.c
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/spi-mpc52xx-psc.c
index e30baf0852ac..e30baf0852ac 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/spi-mpc52xx.c
index 015a974bed72..015a974bed72 100644
--- a/drivers/spi/mpc52xx_spi.c
+++ b/drivers/spi/spi-mpc52xx.c
diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi-nuc900.c
index 3cd15f690f16..c0a6ce81f9c0 100644
--- a/drivers/spi/spi_nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -1,5 +1,4 @@
-/* linux/drivers/spi/spi_nuc900.c
- *
+/*
* Copyright (c) 2009 Nuvoton technology.
* Wan ZongShun <mcuos.com@gmail.com>
*
@@ -7,7 +6,7 @@
* 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/spinlock.h>
diff --git a/drivers/spi/spi_oc_tiny.c b/drivers/spi/spi-oc-tiny.c
index f1bde66cea19..f1bde66cea19 100644
--- a/drivers/spi/spi_oc_tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/spi-omap-100k.c
index 9bd1c92ad96e..9bd1c92ad96e 100644
--- a/drivers/spi/omap_spi_100k.c
+++ b/drivers/spi/spi-omap-100k.c
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/spi-omap-uwire.c
index 160d3266205f..00a8e9d7dbe4 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -1,5 +1,5 @@
/*
- * omap_uwire.c -- MicroWire interface driver for OMAP
+ * MicroWire interface driver for OMAP
*
* Copyright 2003 MontaVista Software Inc. <source@mvista.com>
*
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 969cdd2fe124..fde3a2d4f120 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1116,8 +1116,8 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
status = -ENODEV;
goto err1;
}
- if (!request_mem_region(r->start, (r->end - r->start) + 1,
- dev_name(&pdev->dev))) {
+ if (!request_mem_region(r->start, resource_size(r),
+ dev_name(&pdev->dev))) {
status = -EBUSY;
goto err1;
}
@@ -1125,7 +1125,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
r->start += pdata->regs_offset;
r->end += pdata->regs_offset;
mcspi->phys = r->start;
- mcspi->base = ioremap(r->start, r->end - r->start + 1);
+ mcspi->base = ioremap(r->start, resource_size(r));
if (!mcspi->base) {
dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
status = -ENOMEM;
@@ -1190,7 +1190,7 @@ err4:
err3:
kfree(mcspi->dma_channels);
err2:
- release_mem_region(r->start, (r->end - r->start) + 1);
+ release_mem_region(r->start, resource_size(r));
iounmap(mcspi->base);
err1:
return status;
@@ -1210,7 +1210,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
omap2_mcspi_disable_clocks(mcspi);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, (r->end - r->start) + 1);
+ release_mem_region(r->start, resource_size(r));
base = mcspi->base;
spi_unregister_master(master);
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/spi-orion.c
index 0b677dc041ad..9421a390a5e3 100644
--- a/drivers/spi/orion_spi.c
+++ b/drivers/spi/spi-orion.c
@@ -1,5 +1,5 @@
/*
- * orion_spi.c -- Marvell Orion SPI controller driver
+ * Marvell Orion SPI controller driver
*
* Author: Shadi Ammouri <shadi@marvell.com>
* Copyright (C) 2007-2008 Marvell Ltd.
@@ -489,7 +489,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
goto out;
}
- if (!request_mem_region(r->start, (r->end - r->start) + 1,
+ if (!request_mem_region(r->start, resource_size(r),
dev_name(&pdev->dev))) {
status = -EBUSY;
goto out;
@@ -511,7 +511,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
return status;
out_rel_mem:
- release_mem_region(r->start, (r->end - r->start) + 1);
+ release_mem_region(r->start, resource_size(r));
out:
spi_master_put(master);
@@ -531,7 +531,7 @@ static int __exit orion_spi_remove(struct platform_device *pdev)
cancel_work_sync(&spi->work);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, (r->end - r->start) + 1);
+ release_mem_region(r->start, resource_size(r));
spi_unregister_master(master);
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/spi-pl022.c
index d18ce9e946d8..eba88c749fb1 100644
--- a/drivers/spi/amba-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1,6 +1,4 @@
/*
- * drivers/spi/amba-pl022.c
- *
* A driver for the ARM PL022 PrimeCell SSP/SPI bus master.
*
* Copyright (C) 2008-2009 ST-Ericsson AB
@@ -42,6 +40,7 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
+#include <linux/pm_runtime.h>
/*
* This macro is used to define some register default values.
@@ -383,6 +382,8 @@ struct pl022 {
enum ssp_reading read;
enum ssp_writing write;
u32 exp_fifo_level;
+ enum ssp_rx_level_trig rx_lev_trig;
+ enum ssp_tx_level_trig tx_lev_trig;
/* DMA settings */
#ifdef CONFIG_DMA_ENGINE
struct dma_chan *dma_rx_channel;
@@ -517,6 +518,7 @@ static void giveback(struct pl022 *pl022)
clk_disable(pl022->clk);
amba_pclk_disable(pl022->adev);
amba_vcore_disable(pl022->adev);
+ pm_runtime_put(&pl022->adev->dev);
}
/**
@@ -909,12 +911,10 @@ static int configure_dma(struct pl022 *pl022)
struct dma_slave_config rx_conf = {
.src_addr = SSP_DR(pl022->phybase),
.direction = DMA_FROM_DEVICE,
- .src_maxburst = pl022->vendor->fifodepth >> 1,
};
struct dma_slave_config tx_conf = {
.dst_addr = SSP_DR(pl022->phybase),
.direction = DMA_TO_DEVICE,
- .dst_maxburst = pl022->vendor->fifodepth >> 1,
};
unsigned int pages;
int ret;
@@ -928,6 +928,54 @@ static int configure_dma(struct pl022 *pl022)
if (!rxchan || !txchan)
return -ENODEV;
+ /*
+ * If supplied, the DMA burstsize should equal the FIFO trigger level.
+ * Notice that the DMA engine uses one-to-one mapping. Since we can
+ * not trigger on 2 elements this needs explicit mapping rather than
+ * calculation.
+ */
+ switch (pl022->rx_lev_trig) {
+ case SSP_RX_1_OR_MORE_ELEM:
+ rx_conf.src_maxburst = 1;
+ break;
+ case SSP_RX_4_OR_MORE_ELEM:
+ rx_conf.src_maxburst = 4;
+ break;
+ case SSP_RX_8_OR_MORE_ELEM:
+ rx_conf.src_maxburst = 8;
+ break;
+ case SSP_RX_16_OR_MORE_ELEM:
+ rx_conf.src_maxburst = 16;
+ break;
+ case SSP_RX_32_OR_MORE_ELEM:
+ rx_conf.src_maxburst = 32;
+ break;
+ default:
+ rx_conf.src_maxburst = pl022->vendor->fifodepth >> 1;
+ break;
+ }
+
+ switch (pl022->tx_lev_trig) {
+ case SSP_TX_1_OR_MORE_EMPTY_LOC:
+ tx_conf.dst_maxburst = 1;
+ break;
+ case SSP_TX_4_OR_MORE_EMPTY_LOC:
+ tx_conf.dst_maxburst = 4;
+ break;
+ case SSP_TX_8_OR_MORE_EMPTY_LOC:
+ tx_conf.dst_maxburst = 8;
+ break;
+ case SSP_TX_16_OR_MORE_EMPTY_LOC:
+ tx_conf.dst_maxburst = 16;
+ break;
+ case SSP_TX_32_OR_MORE_EMPTY_LOC:
+ tx_conf.dst_maxburst = 32;
+ break;
+ default:
+ tx_conf.dst_maxburst = pl022->vendor->fifodepth >> 1;
+ break;
+ }
+
switch (pl022->read) {
case READING_NULL:
/* Use the same as for writing */
@@ -1496,6 +1544,7 @@ static void pump_messages(struct work_struct *work)
* and core will be disabled when giveback() is called in each method
* (poll/interrupt/DMA)
*/
+ pm_runtime_get_sync(&pl022->adev->dev);
amba_vcore_enable(pl022->adev);
amba_pclk_enable(pl022->adev);
clk_enable(pl022->clk);
@@ -1629,17 +1678,57 @@ static int verify_controller_parameters(struct pl022 *pl022,
"Communication mode is configured incorrectly\n");
return -EINVAL;
}
- if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM)
- || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) {
+ switch (chip_info->rx_lev_trig) {
+ case SSP_RX_1_OR_MORE_ELEM:
+ case SSP_RX_4_OR_MORE_ELEM:
+ case SSP_RX_8_OR_MORE_ELEM:
+ /* These are always OK, all variants can handle this */
+ break;
+ case SSP_RX_16_OR_MORE_ELEM:
+ if (pl022->vendor->fifodepth < 16) {
+ dev_err(&pl022->adev->dev,
+ "RX FIFO Trigger Level is configured incorrectly\n");
+ return -EINVAL;
+ }
+ break;
+ case SSP_RX_32_OR_MORE_ELEM:
+ if (pl022->vendor->fifodepth < 32) {
+ dev_err(&pl022->adev->dev,
+ "RX FIFO Trigger Level is configured incorrectly\n");
+ return -EINVAL;
+ }
+ break;
+ default:
dev_err(&pl022->adev->dev,
"RX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
+ break;
}
- if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC)
- || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) {
+ switch (chip_info->tx_lev_trig) {
+ case SSP_TX_1_OR_MORE_EMPTY_LOC:
+ case SSP_TX_4_OR_MORE_EMPTY_LOC:
+ case SSP_TX_8_OR_MORE_EMPTY_LOC:
+ /* These are always OK, all variants can handle this */
+ break;
+ case SSP_TX_16_OR_MORE_EMPTY_LOC:
+ if (pl022->vendor->fifodepth < 16) {
+ dev_err(&pl022->adev->dev,
+ "TX FIFO Trigger Level is configured incorrectly\n");
+ return -EINVAL;
+ }
+ break;
+ case SSP_TX_32_OR_MORE_EMPTY_LOC:
+ if (pl022->vendor->fifodepth < 32) {
+ dev_err(&pl022->adev->dev,
+ "TX FIFO Trigger Level is configured incorrectly\n");
+ return -EINVAL;
+ }
+ break;
+ default:
dev_err(&pl022->adev->dev,
"TX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
+ break;
}
if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
if ((chip_info->ctrl_len < SSP_BITS_4)
@@ -1874,6 +1963,9 @@ static int pl022_setup(struct spi_device *spi)
goto err_config_params;
}
+ pl022->rx_lev_trig = chip_info->rx_lev_trig;
+ pl022->tx_lev_trig = chip_info->tx_lev_trig;
+
/* Now set controller state based on controller data */
chip->xfer_type = chip_info->com_mode;
if (!chip_info->cs_control) {
@@ -2094,6 +2186,8 @@ 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)) {
@@ -2155,6 +2249,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
destroy_queue(pl022);
pl022_dma_remove(pl022);
free_irq(adev->irq[0], pl022);
+ pm_runtime_disable(&adev->dev);
err_no_irq:
clk_put(pl022->clk);
err_no_clk:
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi-ppc4xx.c
index 2a298c029194..b267fd901e54 100644
--- a/drivers/spi/spi_ppc4xx.c
+++ b/drivers/spi/spi-ppc4xx.c
@@ -502,7 +502,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op)
goto free_gpios;
}
hw->mapbase = resource.start;
- hw->mapsize = resource.end - resource.start + 1;
+ hw->mapsize = resource_size(&resource);
/* Sanity check */
if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) {
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/spi-pxa2xx-pci.c
index 378e504f89eb..378e504f89eb 100644
--- a/drivers/spi/pxa2xx_spi_pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/spi-pxa2xx.c
index dc25bee8d33f..dc25bee8d33f 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/spi-pxa2xx.c
diff --git a/drivers/spi/spi_s3c24xx_fiq.S b/drivers/spi/spi-s3c24xx-fiq.S
index 3793cae361db..059f2dc1fda2 100644
--- a/drivers/spi/spi_s3c24xx_fiq.S
+++ b/drivers/spi/spi-s3c24xx-fiq.S
@@ -17,7 +17,7 @@
#include <mach/regs-irq.h>
#include <plat/regs-spi.h>
-#include "spi_s3c24xx_fiq.h"
+#include "spi-s3c24xx-fiq.h"
.text
diff --git a/drivers/spi/spi_s3c24xx_fiq.h b/drivers/spi/spi-s3c24xx-fiq.h
index a5950bb25b51..a5950bb25b51 100644
--- a/drivers/spi/spi_s3c24xx_fiq.h
+++ b/drivers/spi/spi-s3c24xx-fiq.h
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index 1a5fcabfd565..1996ac57ef91 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -1,5 +1,4 @@
-/* linux/drivers/spi/spi_s3c24xx.c
- *
+/*
* Copyright (c) 2006 Ben Dooks
* Copyright 2006-2009 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -32,7 +31,7 @@
#include <plat/fiq.h>
#include <asm/fiq.h>
-#include "spi_s3c24xx_fiq.h"
+#include "spi-s3c24xx-fiq.h"
/**
* s3c24xx_spi_devstate - per device data
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 8945e201e42e..595dacc7645f 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -1,5 +1,4 @@
-/* linux/drivers/spi/spi_s3c64xx.c
- *
+/*
* Copyright (C) 2009 Samsung Electronics Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi-sh-msiof.c
index e00d94b22250..e00d94b22250 100644
--- a/drivers/spi/spi_sh_msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi-sh-sci.c
index 5c6439161199..e7779c09f6ef 100644
--- a/drivers/spi/spi_sh_sci.c
+++ b/drivers/spi/spi-sh-sci.c
@@ -78,7 +78,7 @@ static inline u32 getmiso(struct spi_device *dev)
#define spidelay(x) ndelay(x)
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits)
diff --git a/drivers/spi/spi_sh.c b/drivers/spi/spi-sh.c
index 9eedd71ad898..9eedd71ad898 100644
--- a/drivers/spi/spi_sh.c
+++ b/drivers/spi/spi-sh.c
diff --git a/drivers/spi/spi_stmp.c b/drivers/spi/spi-stmp.c
index fadff76eb7e0..fadff76eb7e0 100644
--- a/drivers/spi/spi_stmp.c
+++ b/drivers/spi/spi-stmp.c
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi-tegra.c
index 6c3aa6ecaade..a5a6302dc8e0 100644
--- a/drivers/spi/spi_tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -498,14 +498,14 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
goto err0;
}
- if (!request_mem_region(r->start, (r->end - r->start) + 1,
+ if (!request_mem_region(r->start, resource_size(r),
dev_name(&pdev->dev))) {
ret = -EBUSY;
goto err0;
}
tspi->phys = r->start;
- tspi->base = ioremap(r->start, r->end - r->start + 1);
+ tspi->base = ioremap(r->start, resource_size(r));
if (!tspi->base) {
dev_err(&pdev->dev, "can't ioremap iomem\n");
ret = -ENOMEM;
@@ -546,6 +546,7 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
tspi->rx_dma_req.dev = tspi;
+ master->dev.of_node = pdev->dev.of_node;
ret = spi_register_master(master);
if (ret < 0)
@@ -563,7 +564,7 @@ err3:
err2:
iounmap(tspi->base);
err1:
- release_mem_region(r->start, (r->end - r->start) + 1);
+ release_mem_region(r->start, resource_size(r));
err0:
spi_master_put(master);
return ret;
@@ -588,17 +589,28 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)
iounmap(tspi->base);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, (r->end - r->start) + 1);
+ release_mem_region(r->start, resource_size(r));
return 0;
}
MODULE_ALIAS("platform:spi_tegra");
+#ifdef CONFIG_OF
+static struct of_device_id spi_tegra_of_match_table[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-spi", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, spi_tegra_of_match_table);
+#else /* CONFIG_OF */
+#define spi_tegra_of_match_table NULL
+#endif /* CONFIG_OF */
+
static struct platform_driver spi_tegra_driver = {
.driver = {
.name = "spi_tegra",
.owner = THIS_MODULE,
+ .of_match_table = spi_tegra_of_match_table,
},
.remove = __devexit_p(spi_tegra_remove),
};
diff --git a/drivers/spi/ti-ssp-spi.c b/drivers/spi/spi-ti-ssp.c
index ee22795c7973..ee22795c7973 100644
--- a/drivers/spi/ti-ssp-spi.c
+++ b/drivers/spi/spi-ti-ssp.c
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/spi-tle62x0.c
index 32a40876532f..940e73d1cf09 100644
--- a/drivers/spi/tle62x0.c
+++ b/drivers/spi/spi-tle62x0.c
@@ -1,5 +1,5 @@
/*
- * tle62x0.c -- support Infineon TLE62x0 driver chips
+ * Support Infineon TLE62x0 driver chips
*
* Copyright (c) 2007 Simtec Electronics
* Ben Dooks, <ben@simtec.co.uk>
diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi-topcliff-pch.c
index 79e48d451137..1d23f3831866 100644
--- a/drivers/spi/spi_topcliff_pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -26,6 +26,10 @@
#include <linux/spi/spidev.h>
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <linux/dmaengine.h>
+#include <linux/pch_dma.h>
/* Register offsets */
#define PCH_SPCR 0x00 /* SPI control register */
@@ -35,6 +39,7 @@
#define PCH_SPDRR 0x10 /* SPI read data register */
#define PCH_SSNXCR 0x18 /* SSN Expand Control Register */
#define PCH_SRST 0x1C /* SPI reset register */
+#define PCH_ADDRESS_SIZE 0x20
#define PCH_SPSR_TFD 0x000007C0
#define PCH_SPSR_RFD 0x0000F800
@@ -52,8 +57,6 @@
#define STATUS_EXITING 2
#define PCH_SLEEP_TIME 10
-#define PCH_ADDRESS_SIZE 0x20
-
#define SSN_LOW 0x02U
#define SSN_NO_CONTROL 0x00U
#define PCH_MAX_CS 0xFF
@@ -73,22 +76,57 @@
#define SPSR_TFI_BIT (1 << 0)
#define SPSR_RFI_BIT (1 << 1)
#define SPSR_FI_BIT (1 << 2)
+#define SPSR_ORF_BIT (1 << 3)
#define SPBRR_SIZE_BIT (1 << 10)
-#define PCH_ALL (SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
+#define PCH_ALL (SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|\
+ SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
#define SPCR_RFIC_FIELD 20
#define SPCR_TFIC_FIELD 16
-#define SPSR_INT_BITS 0x1F
-#define MASK_SPBRR_SPBR_BITS (~((1 << 10) - 1))
-#define MASK_RFIC_SPCR_BITS (~(0xf << 20))
-#define MASK_TFIC_SPCR_BITS (~(0xf000f << 12))
+#define MASK_SPBRR_SPBR_BITS ((1 << 10) - 1)
+#define MASK_RFIC_SPCR_BITS (0xf << SPCR_RFIC_FIELD)
+#define MASK_TFIC_SPCR_BITS (0xf << SPCR_TFIC_FIELD)
#define PCH_CLOCK_HZ 50000000
#define PCH_MAX_SPBR 1023
+/* Definition for ML7213 by OKI SEMICONDUCTOR */
+#define PCI_VENDOR_ID_ROHM 0x10DB
+#define PCI_DEVICE_ID_ML7213_SPI 0x802c
+#define PCI_DEVICE_ID_ML7223_SPI 0x800F
+/*
+ * Set the number of SPI instance max
+ * Intel EG20T PCH : 1ch
+ * OKI SEMICONDUCTOR ML7213 IOH : 2ch
+ * OKI SEMICONDUCTOR ML7223 IOH : 1ch
+*/
+#define PCH_SPI_MAX_DEV 2
+
+#define PCH_BUF_SIZE 4096
+#define PCH_DMA_TRANS_SIZE 12
+
+static int use_dma = 1;
+
+struct pch_spi_dma_ctrl {
+ struct dma_async_tx_descriptor *desc_tx;
+ struct dma_async_tx_descriptor *desc_rx;
+ struct pch_dma_slave param_tx;
+ struct pch_dma_slave param_rx;
+ struct dma_chan *chan_tx;
+ struct dma_chan *chan_rx;
+ struct scatterlist *sg_tx_p;
+ struct scatterlist *sg_rx_p;
+ struct scatterlist sg_tx;
+ struct scatterlist sg_rx;
+ int nent;
+ void *tx_buf_virt;
+ void *rx_buf_virt;
+ dma_addr_t tx_buf_dma;
+ dma_addr_t rx_buf_dma;
+};
/**
* struct pch_spi_data - Holds the SPI channel specific details
* @io_remap_addr: The remapped PCI base address
@@ -121,9 +159,13 @@
* @cur_trans: The current transfer that this SPI driver is
* handling
* @board_dat: Reference to the SPI device data structure
+ * @plat_dev: platform_device structure
+ * @ch: SPI channel number
+ * @irq_reg_sts: Status of IRQ registration
*/
struct pch_spi_data {
void __iomem *io_remap_addr;
+ unsigned long io_base_addr;
struct spi_master *master;
struct work_struct work;
struct workqueue_struct *wk;
@@ -144,27 +186,36 @@ struct pch_spi_data {
struct spi_message *current_msg;
struct spi_transfer *cur_trans;
struct pch_spi_board_data *board_dat;
+ struct platform_device *plat_dev;
+ int ch;
+ struct pch_spi_dma_ctrl dma;
+ int use_dma;
+ u8 irq_reg_sts;
};
/**
* struct pch_spi_board_data - Holds the SPI device specific details
* @pdev: Pointer to the PCI device
- * @irq_reg_sts: Status of IRQ registration
- * @pci_req_sts: Status of pci_request_regions
* @suspend_sts: Status of suspend
- * @data: Pointer to SPI channel data structure
+ * @num: The number of SPI device instance
*/
struct pch_spi_board_data {
struct pci_dev *pdev;
- u8 irq_reg_sts;
- u8 pci_req_sts;
u8 suspend_sts;
- struct pch_spi_data *data;
+ int num;
+};
+
+struct pch_pd_dev_save {
+ int num;
+ struct platform_device *pd_save[PCH_SPI_MAX_DEV];
+ struct pch_spi_board_data *board_dat;
};
static struct pci_device_id pch_spi_pcidev_id[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_SPI)},
- {0,}
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, },
+ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
+ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
+ { }
};
/**
@@ -251,10 +302,10 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
/* reset rx threshold */
- reg_spcr_val &= MASK_RFIC_SPCR_BITS;
+ reg_spcr_val &= ~MASK_RFIC_SPCR_BITS;
reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
- iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))),
- (io_remap_addr + PCH_SPCR));
+
+ iowrite32(reg_spcr_val, (io_remap_addr + PCH_SPCR));
}
/* update counts */
@@ -265,12 +316,15 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
/* if transfer complete interrupt */
if (reg_spsr_val & SPSR_FI_BIT) {
- /* disable FI & RFI interrupts */
- pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
- SPCR_FIE_BIT | SPCR_RFIE_BIT);
+ if (tx_index < bpw_len)
+ dev_err(&data->master->dev,
+ "%s : Transfer is not completed", __func__);
+ /* disable interrupts */
+ pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
/* transfer is completed;inform pch_spi_process_messages */
data->transfer_complete = true;
+ data->transfer_active = false;
wake_up(&data->wait);
}
}
@@ -283,24 +337,28 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
static irqreturn_t pch_spi_handler(int irq, void *dev_id)
{
u32 reg_spsr_val;
- struct pch_spi_data *data;
void __iomem *spsr;
void __iomem *io_remap_addr;
irqreturn_t ret = IRQ_NONE;
- struct pch_spi_board_data *board_dat = dev_id;
+ struct pch_spi_data *data = dev_id;
+ struct pch_spi_board_data *board_dat = data->board_dat;
if (board_dat->suspend_sts) {
dev_dbg(&board_dat->pdev->dev,
"%s returning due to suspend\n", __func__);
return IRQ_NONE;
}
+ if (data->use_dma)
+ return IRQ_NONE;
- data = board_dat->data;
io_remap_addr = data->io_remap_addr;
spsr = io_remap_addr + PCH_SPSR;
reg_spsr_val = ioread32(spsr);
+ if (reg_spsr_val & SPSR_ORF_BIT)
+ dev_err(&board_dat->pdev->dev, "%s Over run error", __func__);
+
/* Check if the interrupt is for SPI device */
if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr);
@@ -326,7 +384,7 @@ static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
if (n_spbr > PCH_MAX_SPBR)
n_spbr = PCH_MAX_SPBR;
- pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS);
+ pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, MASK_SPBRR_SPBR_BITS);
}
/**
@@ -435,26 +493,27 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
dev_dbg(&pspi->dev, "%s Transfer List not empty. "
"Transfer Speed is set.\n", __func__);
+ spin_lock_irqsave(&data->lock, flags);
/* validate Tx/Rx buffers and Transfer length */
list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
if (!transfer->tx_buf && !transfer->rx_buf) {
dev_err(&pspi->dev,
"%s Tx and Rx buffer NULL\n", __func__);
retval = -EINVAL;
- goto err_out;
+ goto err_return_spinlock;
}
if (!transfer->len) {
dev_err(&pspi->dev, "%s Transfer length invalid\n",
__func__);
retval = -EINVAL;
- goto err_out;
+ goto err_return_spinlock;
}
dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
" valid\n", __func__);
- /* if baud rate hs been specified validate the same */
+ /* if baud rate has been specified validate the same */
if (transfer->speed_hz > PCH_MAX_BAUDRATE)
transfer->speed_hz = PCH_MAX_BAUDRATE;
@@ -465,25 +524,24 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
retval = -EINVAL;
dev_err(&pspi->dev,
"%s Invalid bits per word\n", __func__);
- goto err_out;
+ goto err_return_spinlock;
}
}
}
-
- spin_lock_irqsave(&data->lock, flags);
+ spin_unlock_irqrestore(&data->lock, flags);
/* We won't process any messages if we have been asked to terminate */
if (data->status == STATUS_EXITING) {
dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);
retval = -ESHUTDOWN;
- goto err_return_spinlock;
+ goto err_out;
}
/* If suspended ,return -EINVAL */
if (data->board_dat->suspend_sts) {
dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);
retval = -EINVAL;
- goto err_return_spinlock;
+ goto err_out;
}
/* set status of message */
@@ -491,9 +549,11 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);
pmsg->status = -EINPROGRESS;
-
+ spin_lock_irqsave(&data->lock, flags);
/* add message to queue */
list_add_tail(&pmsg->queue, &data->queue);
+ spin_unlock_irqrestore(&data->lock, flags);
+
dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
/* schedule work queue to run */
@@ -502,11 +562,13 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
retval = 0;
-err_return_spinlock:
- spin_unlock_irqrestore(&data->lock, flags);
err_out:
dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
return retval;
+err_return_spinlock:
+ dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
+ spin_unlock_irqrestore(&data->lock, flags);
+ return retval;
}
static inline void pch_spi_select_chip(struct pch_spi_data *data,
@@ -527,8 +589,7 @@ static inline void pch_spi_select_chip(struct pch_spi_data *data,
pch_spi_setup_transfer(pspi);
}
-static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
- struct spi_message **ppmsg)
+static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
{
int size;
u32 n_writes;
@@ -537,8 +598,6 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
const u8 *tx_buf;
const u16 *tx_sbuf;
- pmsg = *ppmsg;
-
/* set baud rate if needed */
if (data->cur_trans->speed_hz) {
dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
@@ -621,10 +680,9 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
data->transfer_active = true;
}
-
-static void pch_spi_nomore_transfer(struct pch_spi_data *data,
- struct spi_message *pmsg)
+static void pch_spi_nomore_transfer(struct pch_spi_data *data)
{
+ struct spi_message *pmsg;
dev_dbg(&data->master->dev, "%s called\n", __func__);
/* Invoke complete callback
* [To the spi core..indicating end of transfer] */
@@ -675,29 +733,21 @@ static void pch_spi_nomore_transfer(struct pch_spi_data *data,
static void pch_spi_set_ir(struct pch_spi_data *data)
{
- /* enable interrupts */
- if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
+ /* enable interrupts, set threshold, enable SPI */
+ if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH)
/* set receive threshold to PCH_RX_THOLD */
pch_spi_setclr_reg(data->master, PCH_SPCR,
- PCH_RX_THOLD << SPCR_RFIC_FIELD,
- ~MASK_RFIC_SPCR_BITS);
- /* enable FI and RFI interrupts */
- pch_spi_setclr_reg(data->master, PCH_SPCR,
- SPCR_RFIE_BIT | SPCR_FIE_BIT, 0);
- } else {
+ PCH_RX_THOLD << SPCR_RFIC_FIELD |
+ SPCR_FIE_BIT | SPCR_RFIE_BIT |
+ SPCR_ORIE_BIT | SPCR_SPE_BIT,
+ MASK_RFIC_SPCR_BITS | PCH_ALL);
+ else
/* set receive threshold to maximum */
pch_spi_setclr_reg(data->master, PCH_SPCR,
- PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
- ~MASK_TFIC_SPCR_BITS);
- /* enable FI interrupt */
- pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0);
- }
-
- dev_dbg(&data->master->dev,
- "%s:invoking pch_spi_set_enable to enable SPI\n", __func__);
-
- /* SPI set enable */
- pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0);
+ PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD |
+ SPCR_FIE_BIT | SPCR_ORIE_BIT |
+ SPCR_SPE_BIT,
+ MASK_RFIC_SPCR_BITS | PCH_ALL);
/* Wait until the transfer completes; go to sleep after
initiating the transfer. */
@@ -710,15 +760,13 @@ static void pch_spi_set_ir(struct pch_spi_data *data)
dev_dbg(&data->master->dev,
"%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
- data->transfer_active = false;
- dev_dbg(&data->master->dev,
- "%s set data->transfer_active = false\n", __func__);
-
/* clear all interrupts */
pch_spi_writereg(data->master, PCH_SPSR,
pch_spi_readreg(data->master, PCH_SPSR));
- /* disable interrupts */
- pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+ /* Disable interrupts and SPI transfer */
+ pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL | SPCR_SPE_BIT);
+ /* clear FIFO */
+ pch_spi_clear_fifo(data->master);
}
static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
@@ -742,6 +790,327 @@ static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
}
}
+static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw)
+{
+ int j;
+ u8 *rx_buf;
+ u16 *rx_sbuf;
+ const u8 *rx_dma_buf;
+ const u16 *rx_dma_sbuf;
+
+ /* copy Rx Data */
+ if (!data->cur_trans->rx_buf)
+ return;
+
+ if (bpw == 8) {
+ rx_buf = data->cur_trans->rx_buf;
+ rx_dma_buf = data->dma.rx_buf_virt;
+ for (j = 0; j < data->bpw_len; j++)
+ *rx_buf++ = *rx_dma_buf++ & 0xFF;
+ } else {
+ rx_sbuf = data->cur_trans->rx_buf;
+ rx_dma_sbuf = data->dma.rx_buf_virt;
+ for (j = 0; j < data->bpw_len; j++)
+ *rx_sbuf++ = *rx_dma_sbuf++;
+ }
+}
+
+static void pch_spi_start_transfer(struct pch_spi_data *data)
+{
+ struct pch_spi_dma_ctrl *dma;
+ unsigned long flags;
+
+ dma = &data->dma;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ /* disable interrupts, SPI set enable */
+ pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_SPE_BIT, PCH_ALL);
+
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ /* Wait until the transfer completes; go to sleep after
+ initiating the transfer. */
+ dev_dbg(&data->master->dev,
+ "%s:waiting for transfer to get over\n", __func__);
+ wait_event_interruptible(data->wait, data->transfer_complete);
+
+ dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent,
+ DMA_FROM_DEVICE);
+ async_tx_ack(dma->desc_rx);
+ async_tx_ack(dma->desc_tx);
+ kfree(dma->sg_tx_p);
+ kfree(dma->sg_rx_p);
+
+ spin_lock_irqsave(&data->lock, flags);
+ pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
+ dev_dbg(&data->master->dev,
+ "%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
+
+ /* clear fifo threshold, disable interrupts, disable SPI transfer */
+ pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
+ MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS | PCH_ALL |
+ SPCR_SPE_BIT);
+ /* clear all interrupts */
+ pch_spi_writereg(data->master, PCH_SPSR,
+ pch_spi_readreg(data->master, PCH_SPSR));
+ /* clear FIFO */
+ pch_spi_clear_fifo(data->master);
+
+ spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static void pch_dma_rx_complete(void *arg)
+{
+ struct pch_spi_data *data = arg;
+
+ /* transfer is completed;inform pch_spi_process_messages_dma */
+ data->transfer_complete = true;
+ wake_up_interruptible(&data->wait);
+}
+
+static bool pch_spi_filter(struct dma_chan *chan, void *slave)
+{
+ struct pch_dma_slave *param = slave;
+
+ if ((chan->chan_id == param->chan_id) &&
+ (param->dma_dev == chan->device->dev)) {
+ chan->private = param;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+ struct pci_dev *dma_dev;
+ struct pch_dma_slave *param;
+ struct pch_spi_dma_ctrl *dma;
+ unsigned int width;
+
+ if (bpw == 8)
+ width = PCH_DMA_WIDTH_1_BYTE;
+ else
+ width = PCH_DMA_WIDTH_2_BYTES;
+
+ dma = &data->dma;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ /* Get DMA's dev information */
+ dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(12, 0));
+
+ /* Set Tx DMA */
+ param = &dma->param_tx;
+ param->dma_dev = &dma_dev->dev;
+ param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */
+ param->tx_reg = data->io_base_addr + PCH_SPDWR;
+ param->width = width;
+ chan = dma_request_channel(mask, pch_spi_filter, param);
+ if (!chan) {
+ dev_err(&data->master->dev,
+ "ERROR: dma_request_channel FAILS(Tx)\n");
+ data->use_dma = 0;
+ return;
+ }
+ dma->chan_tx = chan;
+
+ /* Set Rx DMA */
+ param = &dma->param_rx;
+ param->dma_dev = &dma_dev->dev;
+ param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */
+ param->rx_reg = data->io_base_addr + PCH_SPDRR;
+ param->width = width;
+ chan = dma_request_channel(mask, pch_spi_filter, param);
+ if (!chan) {
+ dev_err(&data->master->dev,
+ "ERROR: dma_request_channel FAILS(Rx)\n");
+ dma_release_channel(dma->chan_tx);
+ dma->chan_tx = NULL;
+ data->use_dma = 0;
+ return;
+ }
+ dma->chan_rx = chan;
+}
+
+static void pch_spi_release_dma(struct pch_spi_data *data)
+{
+ struct pch_spi_dma_ctrl *dma;
+
+ dma = &data->dma;
+ if (dma->chan_tx) {
+ dma_release_channel(dma->chan_tx);
+ dma->chan_tx = NULL;
+ }
+ if (dma->chan_rx) {
+ dma_release_channel(dma->chan_rx);
+ dma->chan_rx = NULL;
+ }
+ return;
+}
+
+static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
+{
+ const u8 *tx_buf;
+ const u16 *tx_sbuf;
+ u8 *tx_dma_buf;
+ u16 *tx_dma_sbuf;
+ struct scatterlist *sg;
+ struct dma_async_tx_descriptor *desc_tx;
+ struct dma_async_tx_descriptor *desc_rx;
+ int num;
+ int i;
+ int size;
+ int rem;
+ unsigned long flags;
+ struct pch_spi_dma_ctrl *dma;
+
+ dma = &data->dma;
+
+ /* set baud rate if needed */
+ if (data->cur_trans->speed_hz) {
+ dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
+ spin_lock_irqsave(&data->lock, flags);
+ pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
+ spin_unlock_irqrestore(&data->lock, flags);
+ }
+
+ /* set bits per word if needed */
+ if (data->cur_trans->bits_per_word &&
+ (data->current_msg->spi->bits_per_word !=
+ data->cur_trans->bits_per_word)) {
+ dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
+ spin_lock_irqsave(&data->lock, flags);
+ pch_spi_set_bits_per_word(data->master,
+ data->cur_trans->bits_per_word);
+ spin_unlock_irqrestore(&data->lock, flags);
+ *bpw = data->cur_trans->bits_per_word;
+ } else {
+ *bpw = data->current_msg->spi->bits_per_word;
+ }
+ data->bpw_len = data->cur_trans->len / (*bpw / 8);
+
+ /* copy Tx Data */
+ if (data->cur_trans->tx_buf != NULL) {
+ if (*bpw == 8) {
+ tx_buf = data->cur_trans->tx_buf;
+ tx_dma_buf = dma->tx_buf_virt;
+ for (i = 0; i < data->bpw_len; i++)
+ *tx_dma_buf++ = *tx_buf++;
+ } else {
+ tx_sbuf = data->cur_trans->tx_buf;
+ tx_dma_sbuf = dma->tx_buf_virt;
+ for (i = 0; i < data->bpw_len; i++)
+ *tx_dma_sbuf++ = *tx_sbuf++;
+ }
+ }
+ if (data->bpw_len > PCH_DMA_TRANS_SIZE) {
+ num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1;
+ size = PCH_DMA_TRANS_SIZE;
+ rem = data->bpw_len % PCH_DMA_TRANS_SIZE;
+ } else {
+ num = 1;
+ size = data->bpw_len;
+ rem = data->bpw_len;
+ }
+ dev_dbg(&data->master->dev, "%s num=%d size=%d rem=%d\n",
+ __func__, num, size, rem);
+ spin_lock_irqsave(&data->lock, flags);
+
+ /* set receive fifo threshold and transmit fifo threshold */
+ pch_spi_setclr_reg(data->master, PCH_SPCR,
+ ((size - 1) << SPCR_RFIC_FIELD) |
+ ((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) <<
+ SPCR_TFIC_FIELD),
+ MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS);
+
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ /* RX */
+ dma->sg_rx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+ sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */
+ /* offset, length setting */
+ sg = dma->sg_rx_p;
+ for (i = 0; i < num; i++, sg++) {
+ if (i == 0) {
+ sg->offset = 0;
+ sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem,
+ sg->offset);
+ sg_dma_len(sg) = rem;
+ } else {
+ sg->offset = rem + size * (i - 1);
+ sg->offset = sg->offset * (*bpw / 8);
+ sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size,
+ sg->offset);
+ sg_dma_len(sg) = size;
+ }
+ sg_dma_address(sg) = dma->rx_buf_dma + sg->offset;
+ }
+ sg = dma->sg_rx_p;
+ desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg,
+ num, DMA_FROM_DEVICE,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc_rx) {
+ dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
+ __func__);
+ return;
+ }
+ dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_FROM_DEVICE);
+ desc_rx->callback = pch_dma_rx_complete;
+ desc_rx->callback_param = data;
+ dma->nent = num;
+ dma->desc_rx = desc_rx;
+
+ /* TX */
+ dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+ sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
+ /* offset, length setting */
+ sg = dma->sg_tx_p;
+ for (i = 0; i < num; i++, sg++) {
+ if (i == 0) {
+ sg->offset = 0;
+ sg_set_page(sg, virt_to_page(dma->tx_buf_virt), rem,
+ sg->offset);
+ sg_dma_len(sg) = rem;
+ } else {
+ sg->offset = rem + size * (i - 1);
+ sg->offset = sg->offset * (*bpw / 8);
+ sg_set_page(sg, virt_to_page(dma->tx_buf_virt), size,
+ sg->offset);
+ sg_dma_len(sg) = size;
+ }
+ sg_dma_address(sg) = dma->tx_buf_dma + sg->offset;
+ }
+ sg = dma->sg_tx_p;
+ desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx,
+ sg, num, DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc_tx) {
+ dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
+ __func__);
+ return;
+ }
+ dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_TO_DEVICE);
+ desc_tx->callback = NULL;
+ desc_tx->callback_param = data;
+ dma->nent = num;
+ dma->desc_tx = desc_tx;
+
+ dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
+ "0x2 to SSNXCR\n", __func__);
+
+ spin_lock_irqsave(&data->lock, flags);
+ pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
+ desc_rx->tx_submit(desc_rx);
+ desc_tx->tx_submit(desc_tx);
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ /* reset transfer complete flag */
+ data->transfer_complete = false;
+}
static void pch_spi_process_messages(struct work_struct *pwork)
{
@@ -753,13 +1122,10 @@ static void pch_spi_process_messages(struct work_struct *pwork)
dev_dbg(&data->master->dev, "%s data initialized\n", __func__);
spin_lock(&data->lock);
-
/* check if suspend has been initiated;if yes flush queue */
if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
- dev_dbg(&data->master->dev,
- "%s suspend/remove initiated,flushing queue\n",
- __func__);
-
+ dev_dbg(&data->master->dev, "%s suspend/remove initiated,"
+ "flushing queue\n", __func__);
list_for_each_entry(pmsg, data->queue.next, queue) {
pmsg->status = -EIO;
@@ -793,53 +1159,42 @@ static void pch_spi_process_messages(struct work_struct *pwork)
spin_unlock(&data->lock);
+ if (data->use_dma)
+ pch_spi_request_dma(data,
+ data->current_msg->spi->bits_per_word);
do {
/* If we are already processing a message get the next
transfer structure from the message otherwise retrieve
the 1st transfer request from the message. */
spin_lock(&data->lock);
-
if (data->cur_trans == NULL) {
data->cur_trans =
- list_entry(data->current_msg->transfers.
- next, struct spi_transfer,
- transfer_list);
- dev_dbg(&data->master->dev,
- "%s :Getting 1st transfer message\n", __func__);
+ list_entry(data->current_msg->transfers.next,
+ struct spi_transfer, transfer_list);
+ dev_dbg(&data->master->dev, "%s "
+ ":Getting 1st transfer message\n", __func__);
} else {
data->cur_trans =
- list_entry(data->cur_trans->transfer_list.next,
- struct spi_transfer,
- transfer_list);
- dev_dbg(&data->master->dev,
- "%s :Getting next transfer message\n",
- __func__);
+ list_entry(data->cur_trans->transfer_list.next,
+ struct spi_transfer, transfer_list);
+ dev_dbg(&data->master->dev, "%s "
+ ":Getting next transfer message\n", __func__);
}
-
spin_unlock(&data->lock);
- pch_spi_set_tx(data, &bpw, &pmsg);
-
- /* Control interrupt*/
- pch_spi_set_ir(data);
-
- /* Disable SPI transfer */
- pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0,
- SPCR_SPE_BIT);
-
- /* clear FIFO */
- pch_spi_clear_fifo(data->master);
-
- /* copy Rx Data */
- pch_spi_copy_rx_data(data, bpw);
-
- /* free memory */
- kfree(data->pkt_rx_buff);
- data->pkt_rx_buff = NULL;
-
- kfree(data->pkt_tx_buff);
- data->pkt_tx_buff = NULL;
-
+ if (data->use_dma) {
+ pch_spi_handle_dma(data, &bpw);
+ pch_spi_start_transfer(data);
+ pch_spi_copy_rx_data_for_dma(data, bpw);
+ } else {
+ pch_spi_set_tx(data, &bpw);
+ pch_spi_set_ir(data);
+ pch_spi_copy_rx_data(data, bpw);
+ kfree(data->pkt_rx_buff);
+ data->pkt_rx_buff = NULL;
+ kfree(data->pkt_tx_buff);
+ data->pkt_tx_buff = NULL;
+ }
/* increment message count */
data->current_msg->actual_length += data->cur_trans->len;
@@ -860,125 +1215,60 @@ static void pch_spi_process_messages(struct work_struct *pwork)
/* No more transfer in this message. */
if ((data->cur_trans->transfer_list.next) ==
&(data->current_msg->transfers)) {
- pch_spi_nomore_transfer(data, pmsg);
+ pch_spi_nomore_transfer(data);
}
spin_unlock(&data->lock);
} while (data->cur_trans != NULL);
+
+ if (data->use_dma)
+ pch_spi_release_dma(data);
}
-static void pch_spi_free_resources(struct pch_spi_board_data *board_dat)
+static void pch_spi_free_resources(struct pch_spi_board_data *board_dat,
+ struct pch_spi_data *data)
{
dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
/* free workqueue */
- if (board_dat->data->wk != NULL) {
- destroy_workqueue(board_dat->data->wk);
- board_dat->data->wk = NULL;
+ if (data->wk != NULL) {
+ destroy_workqueue(data->wk);
+ data->wk = NULL;
dev_dbg(&board_dat->pdev->dev,
"%s destroy_workqueue invoked successfully\n",
__func__);
}
-
- /* disable interrupts & free IRQ */
- if (board_dat->irq_reg_sts) {
- /* disable interrupts */
- pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
- PCH_ALL);
-
- /* free IRQ */
- free_irq(board_dat->pdev->irq, board_dat);
-
- dev_dbg(&board_dat->pdev->dev,
- "%s free_irq invoked successfully\n", __func__);
-
- board_dat->irq_reg_sts = false;
- }
-
- /* unmap PCI base address */
- if (board_dat->data->io_remap_addr != 0) {
- pci_iounmap(board_dat->pdev, board_dat->data->io_remap_addr);
-
- board_dat->data->io_remap_addr = 0;
-
- dev_dbg(&board_dat->pdev->dev,
- "%s pci_iounmap invoked successfully\n", __func__);
- }
-
- /* release PCI region */
- if (board_dat->pci_req_sts) {
- pci_release_regions(board_dat->pdev);
- dev_dbg(&board_dat->pdev->dev,
- "%s pci_release_regions invoked successfully\n",
- __func__);
- board_dat->pci_req_sts = false;
- }
}
-static int pch_spi_get_resources(struct pch_spi_board_data *board_dat)
+static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
+ struct pch_spi_data *data)
{
- void __iomem *io_remap_addr;
- int retval;
+ int retval = 0;
+
dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
/* create workqueue */
- board_dat->data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
- if (!board_dat->data->wk) {
+ data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
+ if (!data->wk) {
dev_err(&board_dat->pdev->dev,
"%s create_singlet hread_workqueue failed\n", __func__);
retval = -EBUSY;
goto err_return;
}
- dev_dbg(&board_dat->pdev->dev,
- "%s create_singlethread_workqueue success\n", __func__);
-
- retval = pci_request_regions(board_dat->pdev, KBUILD_MODNAME);
- if (retval != 0) {
- dev_err(&board_dat->pdev->dev,
- "%s request_region failed\n", __func__);
- goto err_return;
- }
-
- board_dat->pci_req_sts = true;
-
- io_remap_addr = pci_iomap(board_dat->pdev, 1, 0);
- if (io_remap_addr == 0) {
- dev_err(&board_dat->pdev->dev,
- "%s pci_iomap failed\n", __func__);
- retval = -ENOMEM;
- goto err_return;
- }
-
- /* calculate base address for all channels */
- board_dat->data->io_remap_addr = io_remap_addr;
-
/* reset PCH SPI h/w */
- pch_spi_reset(board_dat->data->master);
+ pch_spi_reset(data->master);
dev_dbg(&board_dat->pdev->dev,
"%s pch_spi_reset invoked successfully\n", __func__);
- /* register IRQ */
- retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
- IRQF_SHARED, KBUILD_MODNAME, board_dat);
- if (retval != 0) {
- dev_err(&board_dat->pdev->dev,
- "%s request_irq failed\n", __func__);
- goto err_return;
- }
-
- dev_dbg(&board_dat->pdev->dev, "%s request_irq returned=%d\n",
- __func__, retval);
-
- board_dat->irq_reg_sts = true;
dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
err_return:
if (retval != 0) {
dev_err(&board_dat->pdev->dev,
"%s FAIL:invoking pch_spi_free_resources\n", __func__);
- pch_spi_free_resources(board_dat);
+ pch_spi_free_resources(board_dat, data);
}
dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
@@ -986,255 +1276,387 @@ err_return:
return retval;
}
-static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static void pch_free_dma_buf(struct pch_spi_board_data *board_dat,
+ struct pch_spi_data *data)
{
+ struct pch_spi_dma_ctrl *dma;
+
+ dma = &data->dma;
+ if (dma->tx_buf_dma)
+ dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE,
+ dma->tx_buf_virt, dma->tx_buf_dma);
+ if (dma->rx_buf_dma)
+ dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE,
+ dma->rx_buf_virt, dma->rx_buf_dma);
+ return;
+}
- struct spi_master *master;
-
- struct pch_spi_board_data *board_dat;
- int retval;
-
- dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
-
- /* allocate memory for private data */
- board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
- if (board_dat == NULL) {
- dev_err(&pdev->dev,
- " %s memory allocation for private data failed\n",
- __func__);
- retval = -ENOMEM;
- goto err_kmalloc;
- }
+static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
+ struct pch_spi_data *data)
+{
+ struct pch_spi_dma_ctrl *dma;
+
+ dma = &data->dma;
+ /* Get Consistent memory for Tx DMA */
+ dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+ PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL);
+ /* Get Consistent memory for Rx DMA */
+ dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+ PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL);
+}
- dev_dbg(&pdev->dev,
- "%s memory allocation for private data success\n", __func__);
+static int __devinit pch_spi_pd_probe(struct platform_device *plat_dev)
+{
+ int ret;
+ struct spi_master *master;
+ struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
+ struct pch_spi_data *data;
- /* enable PCI device */
- retval = pci_enable_device(pdev);
- if (retval != 0) {
- dev_err(&pdev->dev, "%s pci_enable_device FAILED\n", __func__);
+ dev_dbg(&plat_dev->dev, "%s:debug\n", __func__);
- goto err_pci_en_device;
+ master = spi_alloc_master(&board_dat->pdev->dev,
+ sizeof(struct pch_spi_data));
+ if (!master) {
+ dev_err(&plat_dev->dev, "spi_alloc_master[%d] failed.\n",
+ plat_dev->id);
+ return -ENOMEM;
}
- dev_dbg(&pdev->dev, "%s pci_enable_device returned=%d\n",
- __func__, retval);
+ data = spi_master_get_devdata(master);
+ data->master = master;
- board_dat->pdev = pdev;
+ platform_set_drvdata(plat_dev, data);
- /* alllocate memory for SPI master */
- master = spi_alloc_master(&pdev->dev, sizeof(struct pch_spi_data));
- if (master == NULL) {
- retval = -ENOMEM;
- dev_err(&pdev->dev, "%s Fail.\n", __func__);
- goto err_spi_alloc_master;
+ /* baseaddress + address offset) */
+ data->io_base_addr = pci_resource_start(board_dat->pdev, 1) +
+ PCH_ADDRESS_SIZE * plat_dev->id;
+ data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) +
+ PCH_ADDRESS_SIZE * plat_dev->id;
+ if (!data->io_remap_addr) {
+ dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__);
+ ret = -ENOMEM;
+ goto err_pci_iomap;
}
- dev_dbg(&pdev->dev,
- "%s spi_alloc_master returned non NULL\n", __func__);
+ dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n",
+ plat_dev->id, data->io_remap_addr);
/* initialize members of SPI master */
master->bus_num = -1;
master->num_chipselect = PCH_MAX_CS;
master->setup = pch_spi_setup;
master->transfer = pch_spi_transfer;
- dev_dbg(&pdev->dev,
- "%s transfer member of SPI master initialized\n", __func__);
-
- board_dat->data = spi_master_get_devdata(master);
-
- board_dat->data->master = master;
- board_dat->data->n_curnt_chip = 255;
- board_dat->data->board_dat = board_dat;
- board_dat->data->status = STATUS_RUNNING;
-
- INIT_LIST_HEAD(&board_dat->data->queue);
- spin_lock_init(&board_dat->data->lock);
- INIT_WORK(&board_dat->data->work, pch_spi_process_messages);
- init_waitqueue_head(&board_dat->data->wait);
- /* allocate resources for PCH SPI */
- retval = pch_spi_get_resources(board_dat);
- if (retval) {
- dev_err(&pdev->dev, "%s fail(retval=%d)\n", __func__, retval);
+ data->board_dat = board_dat;
+ data->plat_dev = plat_dev;
+ data->n_curnt_chip = 255;
+ data->status = STATUS_RUNNING;
+ data->ch = plat_dev->id;
+ data->use_dma = use_dma;
+
+ INIT_LIST_HEAD(&data->queue);
+ spin_lock_init(&data->lock);
+ INIT_WORK(&data->work, pch_spi_process_messages);
+ init_waitqueue_head(&data->wait);
+
+ ret = pch_spi_get_resources(board_dat, data);
+ if (ret) {
+ dev_err(&plat_dev->dev, "%s fail(retval=%d)\n", __func__, ret);
goto err_spi_get_resources;
}
- dev_dbg(&pdev->dev, "%s pch_spi_get_resources returned=%d\n",
- __func__, retval);
-
- /* save private data in dev */
- pci_set_drvdata(pdev, board_dat);
- dev_dbg(&pdev->dev, "%s invoked pci_set_drvdata\n", __func__);
+ ret = request_irq(board_dat->pdev->irq, pch_spi_handler,
+ IRQF_SHARED, KBUILD_MODNAME, data);
+ if (ret) {
+ dev_err(&plat_dev->dev,
+ "%s request_irq failed\n", __func__);
+ goto err_request_irq;
+ }
+ data->irq_reg_sts = true;
- /* set master mode */
pch_spi_set_master_mode(master);
- dev_dbg(&pdev->dev,
- "%s invoked pch_spi_set_master_mode\n", __func__);
- /* Register the controller with the SPI core. */
- retval = spi_register_master(master);
- if (retval != 0) {
- dev_err(&pdev->dev,
+ ret = spi_register_master(master);
+ if (ret != 0) {
+ dev_err(&plat_dev->dev,
"%s spi_register_master FAILED\n", __func__);
- goto err_spi_reg_master;
+ goto err_spi_register_master;
}
- dev_dbg(&pdev->dev, "%s spi_register_master returned=%d\n",
- __func__, retval);
-
+ if (use_dma) {
+ dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
+ pch_alloc_dma_buf(board_dat, data);
+ }
return 0;
-err_spi_reg_master:
- spi_unregister_master(master);
+err_spi_register_master:
+ free_irq(board_dat->pdev->irq, board_dat);
+err_request_irq:
+ pch_spi_free_resources(board_dat, data);
err_spi_get_resources:
-err_spi_alloc_master:
+ pci_iounmap(board_dat->pdev, data->io_remap_addr);
+err_pci_iomap:
spi_master_put(master);
- pci_disable_device(pdev);
-err_pci_en_device:
- kfree(board_dat);
-err_kmalloc:
- return retval;
+
+ return ret;
}
-static void pch_spi_remove(struct pci_dev *pdev)
+static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)
{
- struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+ struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
+ struct pch_spi_data *data = platform_get_drvdata(plat_dev);
int count;
+ unsigned long flags;
- dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+ dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n",
+ __func__, plat_dev->id, board_dat->pdev->irq);
- if (!board_dat) {
- dev_err(&pdev->dev,
- "%s pci_get_drvdata returned NULL\n", __func__);
- return;
- }
+ if (use_dma)
+ pch_free_dma_buf(board_dat, data);
/* check for any pending messages; no action is taken if the queue
* is still full; but at least we tried. Unload anyway */
count = 500;
- spin_lock(&board_dat->data->lock);
- board_dat->data->status = STATUS_EXITING;
- while ((list_empty(&board_dat->data->queue) == 0) && --count) {
+ spin_lock_irqsave(&data->lock, flags);
+ data->status = STATUS_EXITING;
+ while ((list_empty(&data->queue) == 0) && --count) {
dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",
__func__);
- spin_unlock(&board_dat->data->lock);
+ spin_unlock_irqrestore(&data->lock, flags);
msleep(PCH_SLEEP_TIME);
- spin_lock(&board_dat->data->lock);
+ spin_lock_irqsave(&data->lock, flags);
}
- spin_unlock(&board_dat->data->lock);
-
- /* Free resources allocated for PCH SPI */
- pch_spi_free_resources(board_dat);
-
- spi_unregister_master(board_dat->data->master);
-
- /* free memory for private data */
- kfree(board_dat);
+ spin_unlock_irqrestore(&data->lock, flags);
- pci_set_drvdata(pdev, NULL);
+ pch_spi_free_resources(board_dat, data);
+ /* disable interrupts & free IRQ */
+ if (data->irq_reg_sts) {
+ /* disable interrupts */
+ pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+ data->irq_reg_sts = false;
+ free_irq(board_dat->pdev->irq, data);
+ }
- /* disable PCI device */
- pci_disable_device(pdev);
+ pci_iounmap(board_dat->pdev, data->io_remap_addr);
+ spi_unregister_master(data->master);
+ spi_master_put(data->master);
+ platform_set_drvdata(plat_dev, NULL);
- dev_dbg(&pdev->dev, "%s invoked pci_disable_device\n", __func__);
+ return 0;
}
-
#ifdef CONFIG_PM
-static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
+static int pch_spi_pd_suspend(struct platform_device *pd_dev,
+ pm_message_t state)
{
u8 count;
- int retval;
-
- struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+ struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
+ struct pch_spi_data *data = platform_get_drvdata(pd_dev);
- dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+ dev_dbg(&pd_dev->dev, "%s ENTRY\n", __func__);
if (!board_dat) {
- dev_err(&pdev->dev,
+ dev_err(&pd_dev->dev,
"%s pci_get_drvdata returned NULL\n", __func__);
return -EFAULT;
}
- retval = 0;
- board_dat->suspend_sts = true;
-
/* check if the current message is processed:
Only after thats done the transfer will be suspended */
count = 255;
while ((--count) > 0) {
- if (!(board_dat->data->bcurrent_msg_processing)) {
- dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_"
- "msg_processing = false\n", __func__);
+ if (!(data->bcurrent_msg_processing))
break;
- } else {
- dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_msg_"
- "processing = true\n", __func__);
- }
msleep(PCH_SLEEP_TIME);
}
/* Free IRQ */
- if (board_dat->irq_reg_sts) {
+ if (data->irq_reg_sts) {
/* disable all interrupts */
- pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
- PCH_ALL);
- pch_spi_reset(board_dat->data->master);
-
- free_irq(board_dat->pdev->irq, board_dat);
+ pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+ pch_spi_reset(data->master);
+ free_irq(board_dat->pdev->irq, data);
- board_dat->irq_reg_sts = false;
- dev_dbg(&pdev->dev,
+ data->irq_reg_sts = false;
+ dev_dbg(&pd_dev->dev,
"%s free_irq invoked successfully.\n", __func__);
}
+ return 0;
+}
+
+static int pch_spi_pd_resume(struct platform_device *pd_dev)
+{
+ struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
+ struct pch_spi_data *data = platform_get_drvdata(pd_dev);
+ int retval;
+
+ if (!board_dat) {
+ dev_err(&pd_dev->dev,
+ "%s pci_get_drvdata returned NULL\n", __func__);
+ return -EFAULT;
+ }
+
+ if (!data->irq_reg_sts) {
+ /* register IRQ */
+ retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
+ IRQF_SHARED, KBUILD_MODNAME, data);
+ if (retval < 0) {
+ dev_err(&pd_dev->dev,
+ "%s request_irq failed\n", __func__);
+ return retval;
+ }
+
+ /* reset PCH SPI h/w */
+ pch_spi_reset(data->master);
+ pch_spi_set_master_mode(data->master);
+ data->irq_reg_sts = true;
+ }
+ return 0;
+}
+#else
+#define pch_spi_pd_suspend NULL
+#define pch_spi_pd_resume NULL
+#endif
+
+static struct platform_driver pch_spi_pd_driver = {
+ .driver = {
+ .name = "pch-spi",
+ .owner = THIS_MODULE,
+ },
+ .probe = pch_spi_pd_probe,
+ .remove = __devexit_p(pch_spi_pd_remove),
+ .suspend = pch_spi_pd_suspend,
+ .resume = pch_spi_pd_resume
+};
+
+static int __devinit pch_spi_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct pch_spi_board_data *board_dat;
+ struct platform_device *pd_dev = NULL;
+ int retval;
+ int i;
+ struct pch_pd_dev_save *pd_dev_save;
+
+ pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL);
+ if (!pd_dev_save) {
+ dev_err(&pdev->dev, "%s Can't allocate pd_dev_sav\n", __func__);
+ return -ENOMEM;
+ }
+
+ board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
+ if (!board_dat) {
+ dev_err(&pdev->dev, "%s Can't allocate board_dat\n", __func__);
+ retval = -ENOMEM;
+ goto err_no_mem;
+ }
+
+ retval = pci_request_regions(pdev, KBUILD_MODNAME);
+ if (retval) {
+ dev_err(&pdev->dev, "%s request_region failed\n", __func__);
+ goto pci_request_regions;
+ }
+
+ board_dat->pdev = pdev;
+ board_dat->num = id->driver_data;
+ pd_dev_save->num = id->driver_data;
+ pd_dev_save->board_dat = board_dat;
+
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ dev_err(&pdev->dev, "%s pci_enable_device failed\n", __func__);
+ goto pci_enable_device;
+ }
+
+ for (i = 0; i < board_dat->num; i++) {
+ pd_dev = platform_device_alloc("pch-spi", i);
+ if (!pd_dev) {
+ dev_err(&pdev->dev, "platform_device_alloc failed\n");
+ goto err_platform_device;
+ }
+ pd_dev_save->pd_save[i] = pd_dev;
+ pd_dev->dev.parent = &pdev->dev;
+
+ retval = platform_device_add_data(pd_dev, board_dat,
+ sizeof(*board_dat));
+ if (retval) {
+ dev_err(&pdev->dev,
+ "platform_device_add_data failed\n");
+ platform_device_put(pd_dev);
+ goto err_platform_device;
+ }
+
+ retval = platform_device_add(pd_dev);
+ if (retval) {
+ dev_err(&pdev->dev, "platform_device_add failed\n");
+ platform_device_put(pd_dev);
+ goto err_platform_device;
+ }
+ }
+
+ pci_set_drvdata(pdev, pd_dev_save);
+
+ return 0;
+
+err_platform_device:
+ pci_disable_device(pdev);
+pci_enable_device:
+ pci_release_regions(pdev);
+pci_request_regions:
+ kfree(board_dat);
+err_no_mem:
+ kfree(pd_dev_save);
+
+ return retval;
+}
+
+static void __devexit pch_spi_remove(struct pci_dev *pdev)
+{
+ int i;
+ struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
+
+ dev_dbg(&pdev->dev, "%s ENTRY:pdev=%p\n", __func__, pdev);
+
+ for (i = 0; i < pd_dev_save->num; i++)
+ platform_device_unregister(pd_dev_save->pd_save[i]);
+
+ pci_disable_device(pdev);
+ pci_release_regions(pdev);
+ kfree(pd_dev_save->board_dat);
+ kfree(pd_dev_save);
+}
+
+#ifdef CONFIG_PM
+static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ int retval;
+ struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
+
+ dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+ pd_dev_save->board_dat->suspend_sts = true;
+
/* save config space */
retval = pci_save_state(pdev);
-
if (retval == 0) {
- dev_dbg(&pdev->dev, "%s pci_save_state returned=%d\n",
- __func__, retval);
- /* disable PM notifications */
pci_enable_wake(pdev, PCI_D3hot, 0);
- dev_dbg(&pdev->dev,
- "%s pci_enable_wake invoked successfully\n", __func__);
- /* disable PCI device */
pci_disable_device(pdev);
- dev_dbg(&pdev->dev,
- "%s pci_disable_device invoked successfully\n",
- __func__);
- /* move device to D3hot state */
pci_set_power_state(pdev, PCI_D3hot);
- dev_dbg(&pdev->dev,
- "%s pci_set_power_state invoked successfully\n",
- __func__);
} else {
dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
}
- dev_dbg(&pdev->dev, "%s return=%d\n", __func__, retval);
-
return retval;
}
static int pch_spi_resume(struct pci_dev *pdev)
{
int retval;
-
- struct pch_spi_board_data *board = pci_get_drvdata(pdev);
+ struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
- if (!board) {
- dev_err(&pdev->dev,
- "%s pci_get_drvdata returned NULL\n", __func__);
- return -EFAULT;
- }
-
- /* move device to DO power state */
pci_set_power_state(pdev, PCI_D0);
-
- /* restore state */
pci_restore_state(pdev);
retval = pci_enable_device(pdev);
@@ -1242,34 +1664,12 @@ static int pch_spi_resume(struct pci_dev *pdev)
dev_err(&pdev->dev,
"%s pci_enable_device failed\n", __func__);
} else {
- /* disable PM notifications */
pci_enable_wake(pdev, PCI_D3hot, 0);
- /* register IRQ handler */
- if (!board->irq_reg_sts) {
- /* register IRQ */
- retval = request_irq(board->pdev->irq, pch_spi_handler,
- IRQF_SHARED, KBUILD_MODNAME,
- board);
- if (retval < 0) {
- dev_err(&pdev->dev,
- "%s request_irq failed\n", __func__);
- return retval;
- }
- board->irq_reg_sts = true;
-
- /* reset PCH SPI h/w */
- pch_spi_reset(board->data->master);
- pch_spi_set_master_mode(board->data->master);
-
- /* set suspend status to false */
- board->suspend_sts = false;
-
- }
+ /* set suspend status to false */
+ pd_dev_save->board_dat->suspend_sts = false;
}
- dev_dbg(&pdev->dev, "%s returning=%d\n", __func__, retval);
-
return retval;
}
#else
@@ -1289,15 +1689,29 @@ static struct pci_driver pch_spi_pcidev = {
static int __init pch_spi_init(void)
{
- return pci_register_driver(&pch_spi_pcidev);
+ int ret;
+ ret = platform_driver_register(&pch_spi_pd_driver);
+ if (ret)
+ return ret;
+
+ ret = pci_register_driver(&pch_spi_pcidev);
+ if (ret)
+ return ret;
+
+ return 0;
}
module_init(pch_spi_init);
static void __exit pch_spi_exit(void)
{
pci_unregister_driver(&pch_spi_pcidev);
+ platform_driver_unregister(&pch_spi_pd_driver);
}
module_exit(pch_spi_exit);
+module_param(use_dma, int, 0644);
+MODULE_PARM_DESC(use_dma,
+ "to use DMA for data transfers pass 1 else 0; default 1");
+
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Topcliff PCH SPI PCI Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7xxx IOH SPI Driver");
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi-txx9.c
index dfa024b633e1..f0a2ab0428a3 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi-txx9.c
@@ -1,5 +1,5 @@
/*
- * spi_txx9.c - TXx9 SPI controller driver.
+ * TXx9 SPI controller driver.
*
* Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
* Copyright (C) 2000-2001 Toshiba Corporation
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/spi-xilinx.c
index 4d2c75df886c..4d2c75df886c 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/spi-xilinx.c
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2e13a14bba3f..4d1b9f517ce8 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1,5 +1,5 @@
/*
- * spi.c - SPI init/core code
+ * SPI init/core code
*
* Copyright (C) 2005 David Brownell
*
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
deleted file mode 100644
index be991359bf92..000000000000
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx_gpio.c
- *
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- *
- * S3C24XX GPIO based SPI driver
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/spi-gpio.h>
-#include <mach/hardware.h>
-
-struct s3c2410_spigpio {
- struct spi_bitbang bitbang;
-
- struct s3c2410_spigpio_info *info;
- struct platform_device *dev;
-};
-
-static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi)
-{
- return spi_master_get_devdata(spi->master);
-}
-
-static inline void setsck(struct spi_device *dev, int on)
-{
- struct s3c2410_spigpio *sg = spidev_to_sg(dev);
- s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0);
-}
-
-static inline void setmosi(struct spi_device *dev, int on)
-{
- struct s3c2410_spigpio *sg = spidev_to_sg(dev);
- s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0);
-}
-
-static inline u32 getmiso(struct spi_device *dev)
-{
- struct s3c2410_spigpio *sg = spidev_to_sg(dev);
- return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0;
-}
-
-#define spidelay(x) ndelay(x)
-
-#include "spi_bitbang_txrx.h"
-
-
-static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
-}
-
-
-static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
-{
- struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-
- if (sg->info && sg->info->chip_select)
- (sg->info->chip_select)(sg->info, value);
-}
-
-static int s3c2410_spigpio_probe(struct platform_device *dev)
-{
- struct s3c2410_spigpio_info *info;
- struct spi_master *master;
- struct s3c2410_spigpio *sp;
- int ret;
-
- master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
- if (master == NULL) {
- dev_err(&dev->dev, "failed to allocate spi master\n");
- ret = -ENOMEM;
- goto err;
- }
-
- sp = spi_master_get_devdata(master);
-
- platform_set_drvdata(dev, sp);
-
- /* copy in the plkatform data */
- info = sp->info = dev->dev.platform_data;
-
- /* setup spi bitbang adaptor */
- sp->bitbang.master = spi_master_get(master);
- sp->bitbang.master->bus_num = info->bus_num;
- sp->bitbang.master->num_chipselect = info->num_chipselect;
- sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
-
- sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
- sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
- sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
- sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;
-
- /* set state of spi pins, always assume that the clock is
- * available, but do check the MOSI and MISO. */
- s3c2410_gpio_setpin(info->pin_clk, 0);
- s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT);
-
- if (info->pin_mosi < S3C2410_GPH10) {
- s3c2410_gpio_setpin(info->pin_mosi, 0);
- s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT);
- }
-
- if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10)
- s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT);
-
- ret = spi_bitbang_start(&sp->bitbang);
- if (ret)
- goto err_no_bitbang;
-
- return 0;
-
- err_no_bitbang:
- spi_master_put(sp->bitbang.master);
- err:
- return ret;
-
-}
-
-static int s3c2410_spigpio_remove(struct platform_device *dev)
-{
- struct s3c2410_spigpio *sp = platform_get_drvdata(dev);
-
- spi_bitbang_stop(&sp->bitbang);
- spi_master_put(sp->bitbang.master);
-
- return 0;
-}
-
-/* all gpio should be held over suspend/resume, so we should
- * not need to deal with this
-*/
-
-#define s3c2410_spigpio_suspend NULL
-#define s3c2410_spigpio_resume NULL
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:spi_s3c24xx_gpio");
-
-static struct platform_driver s3c2410_spigpio_drv = {
- .probe = s3c2410_spigpio_probe,
- .remove = s3c2410_spigpio_remove,
- .suspend = s3c2410_spigpio_suspend,
- .resume = s3c2410_spigpio_resume,
- .driver = {
- .name = "spi_s3c24xx_gpio",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s3c2410_spigpio_init(void)
-{
- return platform_driver_register(&s3c2410_spigpio_drv);
-}
-
-static void __exit s3c2410_spigpio_exit(void)
-{
- platform_driver_unregister(&s3c2410_spigpio_drv);
-}
-
-module_init(s3c2410_spigpio_init);
-module_exit(s3c2410_spigpio_exit);
-
-MODULE_DESCRIPTION("S3C24XX SPI Driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d9fd86211365..830adbed1d7a 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -1,5 +1,5 @@
/*
- * spidev.c -- simple synchronous userspace interface to SPI devices
+ * Simple synchronous userspace interface to SPI devices
*
* Copyright (C) 2006 SWAPP
* Andrea Paterniani <a.paterniani@swapp-eng.it>
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c
index 744d3f6e4709..bf53e44c82a1 100644
--- a/drivers/ssb/b43_pci_bridge.c
+++ b/drivers/ssb/b43_pci_bridge.c
@@ -5,7 +5,7 @@
* because of its small size we include it in the SSB core
* instead of creating a standalone module.
*
- * Copyright 2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 06d15b6f2215..5d9c97c24797 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -3,7 +3,7 @@
* Broadcom ChipCommon core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 305ade7825f7..52901c14c68b 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -2,7 +2,7 @@
* Sonics Silicon Backplane
* Broadcom ChipCommon Power Management Unit driver
*
- * Copyright 2009, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2009, Michael Buesch <m@bues.ch>
* Copyright 2007, Broadcom Corporation
*
* Licensed under the GNU/GPL. See COPYING for details.
@@ -417,9 +417,9 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
u32 min_msk = 0, max_msk = 0;
unsigned int i;
const struct pmu_res_updown_tab_entry *updown_tab = NULL;
- unsigned int updown_tab_size;
+ unsigned int updown_tab_size = 0;
const struct pmu_res_depend_tab_entry *depend_tab = NULL;
- unsigned int depend_tab_size;
+ unsigned int depend_tab_size = 0;
switch (bus->chip_id) {
case 0x4312:
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index c3e1d3e6d610..dc47f30e9cf7 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -3,7 +3,7 @@
* Broadcom EXTIF core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
* Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
* Copyright 2007, Aurelien Jarno <aurelien@aurel32.net>
*
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
index 5ba92a2719a4..3adb98dad70c 100644
--- a/drivers/ssb/driver_gige.c
+++ b/drivers/ssb/driver_gige.c
@@ -3,7 +3,7 @@
* Broadcom Gigabit Ethernet core driver
*
* Copyright 2008, Broadcom Corporation
- * Copyright 2008, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2008, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -106,8 +106,9 @@ void gige_pcicfg_write32(struct ssb_gige *dev,
gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
}
-static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int reg, int size, u32 *val)
+static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn, int reg,
+ int size, u32 *val)
{
struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
unsigned long flags;
@@ -136,8 +137,9 @@ static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_SUCCESSFUL;
}
-static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int reg, int size, u32 val)
+static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn, int reg,
+ int size, u32 val)
{
struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
unsigned long flags;
@@ -166,7 +168,8 @@ static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_SUCCESSFUL;
}
-static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+static int __devinit ssb_gige_probe(struct ssb_device *sdev,
+ const struct ssb_device_id *id)
{
struct ssb_gige *dev;
u32 base, tmslow, tmshigh;
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 97efce184a8f..ced501568594 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -3,7 +3,7 @@
* Broadcom MIPS core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index d6620ad309ce..e6ac3177fbbe 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -3,7 +3,7 @@
* Broadcom PCI-core driver
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -314,7 +314,7 @@ int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return ssb_mips_irq(extpci_core->dev) + 2;
}
-static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
{
u32 val;
@@ -379,7 +379,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
register_pci_controller(&ssb_pcicore_controller);
}
-static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
+static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc)
{
struct ssb_bus *bus = pc->dev->bus;
u16 chipid_top;
@@ -412,7 +412,7 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
* Workarounds.
**************************************************/
-static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
{
u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
@@ -514,7 +514,7 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
* Generic and Clientmode operation code.
**************************************************/
-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
{
ssb_pcicore_fix_sprom_core_index(pc);
@@ -529,7 +529,7 @@ static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
}
}
-void ssb_pcicore_init(struct ssb_pcicore *pc)
+void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
{
struct ssb_device *dev = pc->dev;
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index a0e0d246b592..eec3e267be4d 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -3,7 +3,7 @@
* Embedded systems support code
*
* Copyright 2005-2008, Broadcom Corporation
- * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006-2008, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index f8a13f863217..29c7d4f9d1ae 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -3,7 +3,7 @@
* Subsystem core
*
* Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -557,7 +557,7 @@ error:
}
/* Needs ssb_buses_lock() */
-static int ssb_attach_queued_buses(void)
+static int __devinit ssb_attach_queued_buses(void)
{
struct ssb_bus *bus, *n;
int err = 0;
@@ -768,9 +768,9 @@ out:
return err;
}
-static int ssb_bus_register(struct ssb_bus *bus,
- ssb_invariants_func_t get_invariants,
- unsigned long baseaddr)
+static int __devinit ssb_bus_register(struct ssb_bus *bus,
+ ssb_invariants_func_t get_invariants,
+ unsigned long baseaddr)
{
int err;
@@ -851,8 +851,8 @@ err_disable_xtal:
}
#ifdef CONFIG_SSB_PCIHOST
-int ssb_bus_pcibus_register(struct ssb_bus *bus,
- struct pci_dev *host_pci)
+int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus,
+ struct pci_dev *host_pci)
{
int err;
@@ -875,9 +875,9 @@ EXPORT_SYMBOL(ssb_bus_pcibus_register);
#endif /* CONFIG_SSB_PCIHOST */
#ifdef CONFIG_SSB_PCMCIAHOST
-int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
- struct pcmcia_device *pcmcia_dev,
- unsigned long baseaddr)
+int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+ struct pcmcia_device *pcmcia_dev,
+ unsigned long baseaddr)
{
int err;
@@ -897,8 +897,9 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
#ifdef CONFIG_SSB_SDIOHOST
-int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
- unsigned int quirks)
+int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus,
+ struct sdio_func *func,
+ unsigned int quirks)
{
int err;
@@ -918,9 +919,9 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
EXPORT_SYMBOL(ssb_bus_sdiobus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
-int ssb_bus_ssbbus_register(struct ssb_bus *bus,
- unsigned long baseaddr,
- ssb_invariants_func_t get_invariants)
+int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus,
+ unsigned long baseaddr,
+ ssb_invariants_func_t get_invariants)
{
int err;
@@ -1001,8 +1002,8 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
switch (plltype) {
case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */
if (m & SSB_CHIPCO_CLK_T6_MMASK)
- return SSB_CHIPCO_CLK_T6_M0;
- return SSB_CHIPCO_CLK_T6_M1;
+ return SSB_CHIPCO_CLK_T6_M1;
+ return SSB_CHIPCO_CLK_T6_M0;
case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */
case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */
@@ -1265,7 +1266,10 @@ u32 ssb_dma_translation(struct ssb_device *dev)
case SSB_BUSTYPE_SSB:
return 0;
case SSB_BUSTYPE_PCI:
- return SSB_PCI_DMA;
+ if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)
+ return SSB_PCIE_DMA_H32;
+ else
+ return SSB_PCI_DMA;
default:
__ssb_dma_not_implemented(dev);
}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 7ad48585c5e6..34c3bab90b9a 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -1,7 +1,7 @@
/*
* Sonics Silicon Backplane PCI-Hostbus related functions.
*
- * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
* Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
@@ -734,12 +734,9 @@ out_free:
static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
struct ssb_boardinfo *bi)
{
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
- &bi->vendor);
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
- &bi->type);
- pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
- &bi->rev);
+ bi->vendor = bus->host_pci->subsystem_vendor;
+ bi->type = bus->host_pci->subsystem_device;
+ bi->rev = bus->host_pci->revision;
}
int ssb_pci_get_invariants(struct ssb_bus *bus,
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index f6c8c81a0025..116a8116984b 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -6,7 +6,7 @@
* Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
- * Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+ * Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -53,8 +53,8 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
# define ssb_pcihost_resume NULL
#endif /* CONFIG_PM */
-static int ssb_pcihost_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
+static int __devinit ssb_pcihost_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
struct ssb_bus *ssb;
int err = -ENOMEM;
@@ -110,7 +110,7 @@ static void ssb_pcihost_remove(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
}
-int ssb_pcihost_register(struct pci_driver *driver)
+int __devinit ssb_pcihost_register(struct pci_driver *driver)
{
driver->probe = ssb_pcihost_probe;
driver->remove = ssb_pcihost_remove;
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index f8533795ee7f..c821c6b2a6a0 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -3,7 +3,7 @@
* PCMCIA-Hostbus related functions
*
* Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 45e5babd3961..3e844874631f 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -2,7 +2,7 @@
* Sonics Silicon Backplane
* Bus scanning
*
- * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2007 Michael Buesch <m@bues.ch>
* Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
@@ -310,8 +310,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
} else {
if (bus->bustype == SSB_BUSTYPE_PCI) {
bus->chip_id = pcidev_to_chipid(bus->host_pci);
- pci_read_config_byte(bus->host_pci, PCI_REVISION_ID,
- &bus->chip_rev);
+ bus->chip_rev = bus->host_pci->revision;
bus->chip_package = 0;
} else {
bus->chip_id = 0x4710;
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
index 65a6080cb02a..63fd709038ca 100644
--- a/drivers/ssb/sdio.c
+++ b/drivers/ssb/sdio.c
@@ -6,7 +6,7 @@
*
* Based on drivers/ssb/pcmcia.c
* Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
*
* Licensed under the GNU/GPL. See COPYING for details.
*
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 45ff0e3a3828..80d366fcf8d3 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -2,7 +2,7 @@
* Sonics Silicon Backplane
* Common SPROM support routines
*
- * Copyright (C) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2008 Michael Buesch <m@bues.ch>
* Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
* Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 196284dc2f36..06c9081d596d 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -24,10 +24,6 @@ menuconfig STAGING
if STAGING
-source "drivers/staging/tty/Kconfig"
-
-source "drivers/staging/generic_serial/Kconfig"
-
source "drivers/staging/et131x/Kconfig"
source "drivers/staging/slicoss/Kconfig"
@@ -100,8 +96,6 @@ source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig"
-source "drivers/staging/cs5535_gpio/Kconfig"
-
source "drivers/staging/zram/Kconfig"
source "drivers/staging/zcache/Kconfig"
@@ -120,8 +114,6 @@ source "drivers/staging/cxt1e1/Kconfig"
source "drivers/staging/xgifb/Kconfig"
-source "drivers/staging/msm/Kconfig"
-
source "drivers/staging/lirc/Kconfig"
source "drivers/staging/easycap/Kconfig"
@@ -132,8 +124,6 @@ source "drivers/staging/tidspbridge/Kconfig"
source "drivers/staging/quickstart/Kconfig"
-source "drivers/staging/westbridge/Kconfig"
-
source "drivers/staging/sbe-2t3e3/Kconfig"
source "drivers/staging/ath6kl/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index fa41b9c23783..f3c5e33bb263 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -3,8 +3,6 @@
# fix for build system bug...
obj-$(CONFIG_STAGING) += staging.o
-obj-y += tty/
-obj-y += generic_serial/
obj-$(CONFIG_ET131X) += et131x/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
@@ -41,7 +39,6 @@ obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
-obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio/
obj-$(CONFIG_ZRAM) += zram/
obj-$(CONFIG_XVMALLOC) += zram/
obj-$(CONFIG_ZCACHE) += zcache/
@@ -52,12 +49,10 @@ obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
obj-$(CONFIG_CRYSTALHD) += crystalhd/
obj-$(CONFIG_CXT1E1) += cxt1e1/
obj-$(CONFIG_FB_XGI) += xgifb/
-obj-$(CONFIG_MSM_STAGING) += msm/
obj-$(CONFIG_EASYCAP) += easycap/
obj-$(CONFIG_SOLO6X10) += solo6x10/
obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
-obj-$(CONFIG_WESTBRIDGE_ASTORIA) += westbridge/astoria/
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/
obj-$(CONFIG_USB_ENESTORAGE) += keucr/
diff --git a/drivers/staging/altera-stapl/Kconfig b/drivers/staging/altera-stapl/Kconfig
index 7f01d8e93992..b6537321ed72 100644
--- a/drivers/staging/altera-stapl/Kconfig
+++ b/drivers/staging/altera-stapl/Kconfig
@@ -1,5 +1,3 @@
-comment "Altera FPGA firmware download module"
-
config ALTERA_STAPL
tristate "Altera FPGA firmware download module"
depends on I2C
diff --git a/drivers/staging/altera-stapl/Makefile b/drivers/staging/altera-stapl/Makefile
index 055f61ee781a..ddeede3c4b96 100644
--- a/drivers/staging/altera-stapl/Makefile
+++ b/drivers/staging/altera-stapl/Makefile
@@ -1,3 +1,3 @@
-altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o
+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/altera-stapl/altera.c b/drivers/staging/altera-stapl/altera.c
index 9cd5e76880c0..8d73a8642736 100644
--- a/drivers/staging/altera-stapl/altera.c
+++ b/drivers/staging/altera-stapl/altera.c
@@ -2430,16 +2430,23 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
int index = 0;
s32 offset = 0L;
s32 error_address = 0L;
+ int retval = 0;
- key = kzalloc(33 * sizeof(char), GFP_KERNEL);
- if (!key)
- return -ENOMEM;
- value = kzalloc(257 * sizeof(char), GFP_KERNEL);
- if (!value)
- return -ENOMEM;
+ key = kzalloc(33, GFP_KERNEL);
+ if (!key) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ value = kzalloc(257, GFP_KERNEL);
+ if (!value) {
+ retval = -ENOMEM;
+ goto free_key;
+ }
astate = kzalloc(sizeof(struct altera_state), GFP_KERNEL);
- if (!astate)
- return -ENOMEM;
+ if (!astate) {
+ retval = -ENOMEM;
+ goto free_value;
+ }
astate->config = config;
if (!astate->config->jtag_io) {
@@ -2518,10 +2525,12 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
} else if (exec_result)
printk(KERN_ERR "%s: error %d\n", __func__, exec_result);
- kfree(key);
- kfree(value);
kfree(astate);
-
- return 0;
+free_value:
+ kfree(value);
+free_key:
+ kfree(key);
+out:
+ return retval;
}
EXPORT_SYMBOL(altera_init);
diff --git a/drivers/staging/ath6kl/TODO b/drivers/staging/ath6kl/TODO
index 019df4b471eb..7be4b46ebb59 100644
--- a/drivers/staging/ath6kl/TODO
+++ b/drivers/staging/ath6kl/TODO
@@ -1,7 +1,7 @@
TODO:
We are working hard on cleaning up the driver. There's sooooooooo much todo
-so instead of editign this file please use the wiki:
+so instead of editing this file please use the wiki:
http://wireless.kernel.org/en/users/Drivers/ath6kl
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
index 48dd9e363596..499b7a90e941 100644
--- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c
+++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
@@ -954,9 +954,13 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
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) {
@@ -970,6 +974,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
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) {
@@ -1028,6 +1034,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
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) {
@@ -1041,6 +1049,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
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) {
@@ -1057,23 +1067,29 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file));
return A_ERROR;
}
- 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;
+
+ 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 && fw_entry->data) {
- ar6000_softmac_update(ar, (u8 *)fw_entry->data, fw_entry->size);
+ if (file==AR6K_BOARD_DATA_FILE && *buf_len) {
+ ar6000_softmac_update(ar, *buf, *buf_len);
}
#endif
- fw_entry_size = fw_entry->size;
+ fw_entry_size = *buf_len;
/* Load extended board data for AR6003 */
- if ((file==AR6K_BOARD_DATA_FILE) && (fw_entry->data)) {
+ if ((file==AR6K_BOARD_DATA_FILE) && *buf) {
u32 board_ext_address;
u32 board_ext_data_size;
u32 board_data_size;
@@ -1089,14 +1105,13 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
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) && (fw_entry->size == (board_data_size + board_ext_data_size))) {
+ if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) {
u32 param;
- status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(fw_entry->data + board_data_size), board_ext_data_size);
+ 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__));
- A_RELEASE_FIRMWARE(fw_entry);
return A_ERROR;
}
@@ -1110,17 +1125,16 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
}
if (compressed) {
- status = BMIFastDownload(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
+ status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size);
} else {
- status = BMIWriteMemory(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
+ status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size);
}
if (status) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
- A_RELEASE_FIRMWARE(fw_entry);
return A_ERROR;
}
- A_RELEASE_FIRMWARE(fw_entry);
+
return 0;
}
@@ -2088,6 +2102,11 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister)
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"));
}
@@ -4114,6 +4133,13 @@ ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver)
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);
diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c
index d3a774dbb7e8..5fdda4aa2fee 100644
--- a/drivers/staging/ath6kl/os/linux/cfg80211.c
+++ b/drivers/staging/ath6kl/os/linux/cfg80211.c
@@ -24,6 +24,7 @@
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/cfg80211.h>
+#include <net/netlink.h>
#include "ar6000_drv.h"
@@ -867,26 +868,31 @@ 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)
- {
- /* Translate data to cfg80211 mgmt format */
- if (ar->arWmi)
- wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
+ if (!ar->scan_request)
+ return;
+
+ if ((status == A_ECANCELED) || (status == A_EBUSY)) {
+ cfg80211_scan_done(ar->scan_request, true);
+ goto out;
+ }
- cfg80211_scan_done(ar->scan_request,
- ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false);
+ /* Translate data to cfg80211 mgmt format */
+ wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
- if(ar->scan_request->n_ssids &&
- ar->scan_request->ssids[0].ssid_len) {
+ 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);
+ wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG,
+ 0, NULL);
}
- }
- ar->scan_request = NULL;
}
+
+out:
+ ar->scan_request = NULL;
}
static int
@@ -1453,6 +1459,159 @@ ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
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[] = {
@@ -1607,6 +1766,28 @@ static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev,
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,
@@ -1628,6 +1809,10 @@ cfg80211_ops ar6k_cfg80211_ops = {
.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 *
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
index 22453b0873e4..80cef77738fb 100644
--- a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
+++ b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
@@ -52,7 +52,6 @@
#include "aggr_recv_api.h"
#include <host_version.h>
#include <linux/rtnetlink.h>
-#include <linux/init.h>
#include <linux/moduleparam.h>
#include "ar6000_api.h"
#ifdef CONFIG_HOST_TCMD_SUPPORT
@@ -546,15 +545,9 @@ struct ar6_softc {
s8 arMaxRetries;
u8 arPhyCapability;
#ifdef CONFIG_HOST_TCMD_SUPPORT
- u8 tcmdRxReport;
- u32 tcmdRxTotalPkt;
- s32 tcmdRxRssi;
- u32 tcmdPm;
u32 arTargetMode;
- u32 tcmdRxcrcErrPkt;
- u32 tcmdRxsecErrPkt;
- u16 tcmdRateCnt[TCMD_MAX_RATES];
- u16 tcmdRateCntShortGuard[TCMD_MAX_RATES];
+ void *tcmd_rx_report;
+ int tcmd_rx_report_len;
#endif
AR6000_WLAN_STATE arWlanState;
struct ar_node_mapping arNodeMap[MAX_NODE_NUM];
@@ -651,6 +644,15 @@ struct ar6_softc {
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
diff --git a/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/drivers/staging/ath6kl/os/linux/include/cfg80211.h
index 1a6ae97c6b08..d5253207b198 100644
--- a/drivers/staging/ath6kl/os/linux/include/cfg80211.h
+++ b/drivers/staging/ath6kl/os/linux/include/cfg80211.h
@@ -41,6 +41,17 @@ void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
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
index d4030e26b20c..dbbe1a00b92c 100644
--- a/drivers/staging/ath6kl/os/linux/include/config_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/config_linux.h
@@ -28,8 +28,6 @@
extern "C" {
#endif
-#include <linux/version.h>
-
/*
* Host side Test Command support
*/
diff --git a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
index 769a48014313..e6e96de3fc6b 100644
--- a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
+++ b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
@@ -24,8 +24,6 @@
#ifndef _IEEE80211_IOCTL_H_
#define _IEEE80211_IOCTL_H_
-#include <linux/version.h>
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
index 07078b49583f..41f437307727 100644
--- a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
@@ -29,7 +29,6 @@
#ifdef __KERNEL__
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
diff --git a/drivers/staging/ath6kl/wmi/wmi.c b/drivers/staging/ath6kl/wmi/wmi.c
index 4a17f99ea143..c7b5e5cf9df7 100644
--- a/drivers/staging/ath6kl/wmi/wmi.c
+++ b/drivers/staging/ath6kl/wmi/wmi.c
@@ -41,6 +41,7 @@
#include "a_debug.h"
#include "dbglog_api.h"
#include "roaming.h"
+#include "cfg80211.h"
#define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0)
@@ -4465,10 +4466,9 @@ wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
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);
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- return 0;
+ return 0;
}
#endif /* CONFIG_HOST_TCMD_SUPPORT*/
diff --git a/drivers/staging/bcm/Debug.h b/drivers/staging/bcm/Debug.h
index 3138729cf34f..420382d1cacf 100644
--- a/drivers/staging/bcm/Debug.h
+++ b/drivers/staging/bcm/Debug.h
@@ -131,7 +131,7 @@ DriverEntry.c, bcmfwup.c, ChipDetectTask.c, HaltnReset.c, InterfaceDDR.c */
// TODO - put PHS_SEND in Tx PHS_RECEIVE in Rx path ?
#define PHS_SEND (OTHERS<<16)
-#define PHS_RECIEVE (OTHERS<<17)
+#define PHS_RECEIVE (OTHERS<<17)
#define PHS_MODULE (OTHERS<<18)
#define INTF_INIT (OTHERS<<19)
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c
index 806ef5d18522..d495828a731f 100644
--- a/drivers/staging/bcm/InterfaceRx.c
+++ b/drivers/staging/bcm/InterfaceRx.c
@@ -157,7 +157,7 @@ static void read_bulk_callback(struct urb *urb)
{
/* Moving ahead by ETH_HLEN to the data ptr as received from FW */
skb_pull(skb, ETH_HLEN);
- PHSRecieve(Adapter, pLeader->Vcid, skb, &skb->len,
+ PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len,
NULL,bHeaderSupressionEnabled);
if(!Adapter->PackInfo[QueueIndex].bEthCSSupport)
@@ -229,7 +229,7 @@ static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb)
/*
Function: InterfaceRx
-Description: This is the hardware specific Function for Recieveing
+Description: This is the hardware specific Function for Receiving
data packet/control packets from the device.
Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context
diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h
index feb351578c8b..916bebb7ed50 100644
--- a/drivers/staging/bcm/Macros.h
+++ b/drivers/staging/bcm/Macros.h
@@ -176,8 +176,8 @@ enum enLinkStatus {
PHY_SYNC_ACHIVED = 2,
LINKUP_IN_PROGRESS = 3,
LINKUP_DONE = 4,
- DREG_RECIEVED = 5,
- LINK_STATUS_RESET_RECIEVED = 6,
+ 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
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index c5003b62234c..c5b3a3666bc7 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -1447,16 +1447,10 @@ static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount)
int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
{
- INT uiRetVal =0;
-
- uiRetVal = Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
+ return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
uiAddress, pucBuff, sSize);
-
- if(uiRetVal < 0)
- return uiRetVal;
-
- return uiRetVal;
}
+
int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
{
int iRetVal;
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
index d1ca1912a74b..4aa2b71a40eb 100644
--- a/drivers/staging/bcm/PHSModule.c
+++ b/drivers/staging/bcm/PHSModule.c
@@ -209,7 +209,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter,
return STATUS_SUCCESS;
}
-int PHSRecieve(PMINI_ADAPTER Adapter,
+int PHSReceive(PMINI_ADAPTER Adapter,
USHORT usVcid,
struct sk_buff *packet,
UINT *punPacketLen,
@@ -223,7 +223,7 @@ int PHSRecieve(PMINI_ADAPTER Adapter,
UINT TotalBytesAdded = 0;
if(!bHeaderSuppressionEnabled)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
return ulPhsStatus;
}
@@ -238,7 +238,7 @@ int PHSRecieve(PMINI_ADAPTER Adapter,
&nTotalsupressedPktHdrBytes,
&nStandardPktHdrLen);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
nTotalsupressedPktHdrBytes,nStandardPktHdrLen);
if(ulPhsStatus != STATUS_PHS_COMPRESSED)
@@ -786,14 +786,14 @@ ULONG PhsDeCompress(IN void* pvContext,
if(pDeviceExtension == NULL)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Invalid Device Extension\n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n");
return ERR_PHS_INVALID_DEVICE_EXETENSION;
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Restoring header \n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Restoring header\n");
phsi = *((unsigned char *)(pvInputBuffer));
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x \n",phsi);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi);
if(phsi == UNCOMPRESSED_PACKET )
{
return STATUS_PHS_NOCOMPRESSION;
@@ -804,7 +804,7 @@ ULONG PhsDeCompress(IN void* pvContext,
uiVcid,&pstServiceFlowEntry);
if(nSFIndex == PHS_INVALID_TABLE_INDEX)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
return ERR_SF_MATCH_FAIL;
}
@@ -1417,7 +1417,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
int in_buf_len = *header_size-1;
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
in_buf++;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"====>\n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"====>\n");
*header_size = 0;
if((decomp_phs_rules == NULL ))
@@ -1425,7 +1425,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
tmp_memb = decomp_phs_rules;
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
+ //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
//*header_size = tmp_memb->u8PHSFLength;
phss = tmp_memb->u8PHSS;
phsf = tmp_memb->u8PHSF;
@@ -1433,7 +1433,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
if(phss > MAX_PHS_LENGTHS)
phss = MAX_PHS_LENGTHS;
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
+ //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
while((phss > 0) && (size < in_buf_len))
{
bit = ((*phsm << i)& SUPPRESS);
@@ -1441,13 +1441,13 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
if(bit == SUPPRESS)
{
*out_buf = *phsf;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d",
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d",
phss,*phsf,*out_buf);
}
else
{
*out_buf = *in_buf;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d",
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d",
phss,*in_buf,*out_buf);
in_buf++;
size++;
diff --git a/drivers/staging/bcm/PHSModule.h b/drivers/staging/bcm/PHSModule.h
index 0dd05a7c55d9..c629585d0a8c 100644
--- a/drivers/staging/bcm/PHSModule.h
+++ b/drivers/staging/bcm/PHSModule.h
@@ -9,7 +9,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter,
PUINT PacketLen,
UCHAR bEthCSSupport);
-int PHSRecieve(PMINI_ADAPTER Adapter,
+int PHSReceive(PMINI_ADAPTER Adapter,
USHORT usVcid,
struct sk_buff *packet,
UINT *punPacketLen,
diff --git a/drivers/staging/bcm/headers.h b/drivers/staging/bcm/headers.h
index 1148e5e22eb9..947d06325681 100644
--- a/drivers/staging/bcm/headers.h
+++ b/drivers/staging/bcm/headers.h
@@ -20,25 +20,22 @@
#include <linux/file.h>
#include <linux/string.h>
#include <linux/etherdevice.h>
-#include <net/ip.h>
#include <linux/wait.h>
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
-
-#include <linux/version.h>
#include <linux/stddef.h>
-#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/unistd.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
-#include <asm/uaccess.h>
#include <linux/kthread.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/usb.h>
+#include <asm/uaccess.h>
+#include <net/ip.h>
#include "Typedefs.h"
#include "Version.h"
@@ -61,7 +58,6 @@
#include "Queue.h"
#include "vendorspecificextn.h"
-
#include "InterfaceMacros.h"
#include "InterfaceAdapter.h"
#include "InterfaceIsr.h"
diff --git a/drivers/staging/bcm/sort.c b/drivers/staging/bcm/sort.c
index fc5d07aec3d2..63c966a02546 100644
--- a/drivers/staging/bcm/sort.c
+++ b/drivers/staging/bcm/sort.c
@@ -1,4 +1,5 @@
#include "headers.h"
+#include <linux/sort.h>
/*
* File Name: sort.c
@@ -10,54 +11,42 @@
* Copyright (c) 2007 Beceem Communications Pvt. Ltd
*/
+static int compare_packet_info(void const *a, void const *b)
+{
+ PacketInfo const *pa = a;
+ PacketInfo const *pb = b;
+
+ if (!pa->bValid || !pb->bValid)
+ return 0;
+
+ return pa->u8TrafficPriority - pb->u8TrafficPriority;
+}
+
VOID SortPackInfo(PMINI_ADAPTER Adapter)
{
- UINT nIndex1;
- UINT nIndex2;
-
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=======");
-
- for(nIndex1 = 0; nIndex1 < NO_OF_QUEUES -2 ; nIndex1++)
- {
- for(nIndex2 = nIndex1 + 1 ; nIndex2 < NO_OF_QUEUES -1 ; nIndex2++)
- {
- if(Adapter->PackInfo[nIndex1].bValid && Adapter->PackInfo[nIndex2].bValid)
- {
- if(Adapter->PackInfo[nIndex2].u8TrafficPriority <
- Adapter->PackInfo[nIndex1].u8TrafficPriority)
- {
- PacketInfo stTemppackInfo = Adapter->PackInfo[nIndex2];
- Adapter->PackInfo[nIndex2] = Adapter->PackInfo[nIndex1];
- Adapter->PackInfo[nIndex1] = stTemppackInfo;
-
- }
- }
- }
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL, "<=======");
+
+ sort(Adapter->PackInfo, NO_OF_QUEUES, sizeof(PacketInfo),
+ compare_packet_info, NULL);
+}
+
+static int compare_classifiers(void const *a, void const *b)
+{
+ S_CLASSIFIER_RULE const *pa = a;
+ S_CLASSIFIER_RULE const *pb = b;
+
+ if (!pa->bUsed || !pb->bUsed)
+ return 0;
+
+ return pa->u8ClassifierRulePriority - pb->u8ClassifierRulePriority;
}
VOID SortClassifiers(PMINI_ADAPTER Adapter)
{
- UINT nIndex1;
- UINT nIndex2;
-
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=======");
-
- for(nIndex1 = 0; nIndex1 < MAX_CLASSIFIERS -1 ; nIndex1++)
- {
- for(nIndex2 = nIndex1 + 1 ; nIndex2 < MAX_CLASSIFIERS ; nIndex2++)
- {
- if(Adapter->astClassifierTable[nIndex1].bUsed && Adapter->astClassifierTable[nIndex2].bUsed)
- {
- if(Adapter->astClassifierTable[nIndex2].u8ClassifierRulePriority <
- Adapter->astClassifierTable[nIndex1].u8ClassifierRulePriority)
- {
- S_CLASSIFIER_RULE stTempClassifierRule = Adapter->astClassifierTable[nIndex2];
- Adapter->astClassifierTable[nIndex2] = Adapter->astClassifierTable[nIndex1];
- Adapter->astClassifierTable[nIndex1] = stTempClassifierRule;
-
- }
- }
- }
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL, "<=======");
+
+ sort(Adapter->astClassifierTable, MAX_CLASSIFIERS,
+ sizeof(S_CLASSIFIER_RULE), compare_classifiers, NULL);
}
diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile
index e7b3f27847cf..8b01f5e7ba25 100644
--- a/drivers/staging/brcm80211/Makefile
+++ b/drivers/staging/brcm80211/Makefile
@@ -17,8 +17,8 @@
# common flags
subdir-ccflags-y := -DBCMDMA32
-subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG -DBCMDBG_ASSERT
+subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG
-obj-$(CONFIG_BRCMUTIL) += util/
+obj-$(CONFIG_BRCMUTIL) += brcmutil/
obj-$(CONFIG_BRCMFMAC) += brcmfmac/
obj-$(CONFIG_BRCMSMAC) += brcmsmac/
diff --git a/drivers/staging/brcm80211/README b/drivers/staging/brcm80211/README
index 8ad558675bd3..bb86b1b3e58e 100644
--- a/drivers/staging/brcm80211/README
+++ b/drivers/staging/brcm80211/README
@@ -1,64 +1 @@
-Broadcom brcmsmac (mac80211-based softmac PCIe) and brcmfmac (SDIO) drivers.
-
-Completely open source host drivers, no binary object files.
-
-Support for the following chips:
-===============================
-
- brcmsmac (PCIe)
- Name Device ID
- BCM4313 0x4727
- BCM43224 0x4353
- BCM43225 0x4357
-
- brcmfmac (SDIO)
- Name
- BCM4329
-
-Both brcmsmac and brcmfmac drivers require firmware files that need to be
-separately downloaded.
-
-Firmware
-======================
-Firmware is available from the Linux firmware repository at:
-
- git://git.kernel.org/pub/scm/linux/kernel/git/dwmw2/linux-firmware.git
- http://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
- https://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
-
-
-===============================================================
-Broadcom brcmsmac driver
-===============================================================
-- Support for both 32 and 64 bit Linux kernels
-
-
-Firmware installation
-======================
-Copy brcm/bcm43xx-0.fw and brcm/bcm43xx_hdr-0.fw to
-/lib/firmware/brcm (or wherever firmware is normally installed
-on your system).
-
-
-===============================================================
-Broadcom brcmfmac driver
-===============================================================
-- Support for 32 bit Linux kernel, 64 bit untested
-
-
-Firmware installation
-======================
-Copy brcm/bcm4329-fullmac-4.bin and brcm/bcm4329-fullmac-4.txt
-to /lib/firmware/brcm (or wherever firmware is normally installed on your
-system).
-
-
-Contact Info:
-=============
-Brett Rudley brudley@broadcom.com
-Henry Ptasinski henryp@broadcom.com
-Dowan Kim dowan@broadcom.com
-Roland Vossen rvossen@broadcom.com
-Arend van Spriel arend@broadcom.com
-
-For more info, refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
+refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/TODO b/drivers/staging/brcm80211/TODO
index e9c1393a2b92..e2e2ef9bd7ac 100644
--- a/drivers/staging/brcm80211/TODO
+++ b/drivers/staging/brcm80211/TODO
@@ -2,14 +2,12 @@ To Do List for Broadcom Mac80211 driver before getting in mainline
Bugs
====
-- Oops on AMPDU traffic, to be solved by new ucode (currently under test)
+- none known at this moment
-brcmfmac and brcmsmac
+brcmfmac
=====================
-- ASSERTS not allowed in mainline, replace by warning + error handling
-- Replace printk and WL_ERROR() with proper routines
+- ASSERTS deprecated in mainline, replace by warning + error handling
-brcmfmac
+brcm80211 info page
=====================
-- Replace driver's proprietary ssb interface with generic kernel ssb module
-- Build and test on 64 bit linux kernel
+http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile
index c5ec562c3645..da3c80575907 100644
--- a/drivers/staging/brcm80211/brcmfmac/Makefile
+++ b/drivers/staging/brcm80211/brcmfmac/Makefile
@@ -16,23 +16,11 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ccflags-y := \
- -DARP_OFFLOAD_SUPPORT \
- -DBCMLXSDMMC \
- -DBCMPLATFORM_BUS \
- -DBCMSDIO \
- -DBDC \
- -DBRCM_FULLMAC \
- -DDHD_FIRSTREAD=64 \
- -DDHD_SCHED \
- -DDHD_SDALIGN=64 \
- -DEMBEDDED_PLATFORM \
- -DMAX_HDR_READ=64 \
- -DMMC_SDIO_ABORT \
- -DPKT_FILTER_SUPPORT \
- -DSHOW_EVENTS \
- -DTOE
+ -DBRCMF_FIRSTREAD=64 \
+ -DBRCMF_SDALIGN=64 \
+ -DMAX_HDR_READ=64
-ccflags-$(CONFIG_BRCMDBG) += -DDHD_DEBUG
+ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS
ccflags-y += \
-Idrivers/staging/brcm80211/brcmfmac \
@@ -40,17 +28,12 @@ ccflags-y += \
DHDOFILES = \
wl_cfg80211.o \
- wl_iw.o \
dhd_cdc.o \
dhd_common.o \
- dhd_custom_gpio.o \
dhd_sdio.o \
dhd_linux.o \
- dhd_linux_sched.o \
bcmsdh.o \
- bcmsdh_linux.o \
- bcmsdh_sdmmc.o \
- bcmsdh_sdmmc_linux.o
+ bcmsdh_sdmmc.o
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += $(DHDOFILES)
diff --git a/drivers/staging/brcm80211/brcmfmac/README b/drivers/staging/brcm80211/brcmfmac/README
deleted file mode 100644
index 139597f9cb07..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/README
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/drivers/staging/brcm80211/brcmfmac/aiutils.c b/drivers/staging/brcm80211/brcmfmac/aiutils.c
deleted file mode 100644
index e64808648ce3..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/aiutils.c
+++ /dev/null
@@ -1 +0,0 @@
-#include "../util/aiutils.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmcdc.h b/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
deleted file mode 100644
index ed4c4a517eca..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
+++ /dev/null
@@ -1,98 +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/if_ether.h>
-
-typedef struct cdc_ioctl {
- u32 cmd; /* ioctl command value */
- u32 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 */
-} cdc_ioctl_t;
-
-/* Max valid buffer size that can be sent to the dongle */
-#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
-
-/* len field is divided into input and output buffer lengths */
-#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected
- response length, */
- /* excluding IOCTL header */
-#define CDCL_IOC_OUTLEN_SHIFT 0
-#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length,
- excluding IOCTL header */
-#define CDCL_IOC_INLEN_SHIFT 16
-
-/* CDC flag definitions */
-#define CDCF_IOC_ERROR 0x01 /* 0=success, 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 /* used to uniquely id an ioctl
- req/resp pairing */
-#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */
-
-#define CDC_IOC_IF_IDX(flags) \
- (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
-#define CDC_IOC_ID(flags) \
- (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
-
-#define CDC_GET_IF_IDX(hdr) \
- ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
-#define CDC_SET_IF_IDX(hdr, idx) \
- ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
- ((idx) << CDCF_IOC_IF_SHIFT)))
-
-/*
- * BDC header
- *
- * The BDC header is used on data packets to convey priority across USB.
- */
-
-#define BDC_HEADER_LEN 4
-
-#define BDC_PROTO_VER 1 /* Protocol version */
-
-#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
-#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
-
-#define BDC_FLAG__UNUSED 0x03 /* Unassigned */
-#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good
- RX checksums */
-#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */
-
-#define BDC_PRIORITY_MASK 0x7
-
-#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */
- /* FLOW CONTROL info only */
-#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */
-
-#define BDC_FLAG2_IF_MASK 0x0f /* APSTA: interface on which the
- packet was received */
-#define BDC_FLAG2_IF_SHIFT 0
-
-#define BDC_GET_IF_IDX(hdr) \
- ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
-#define BDC_SET_IF_IDX(hdr, idx) \
- ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
- ((idx) << BDC_FLAG2_IF_SHIFT)))
-
-struct bdc_header {
- u8 flags; /* Flags */
- u8 priority; /* 802.1d Priority 0:2 bits, 4:7 flow
- control info for usb */
- u8 flags2;
- u8 rssi;
-};
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmchip.h b/drivers/staging/brcm80211/brcmfmac/bcmchip.h
index c0d4c3bf6d42..d7d3afd5a10f 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmchip.h
+++ b/drivers/staging/brcm80211/brcmfmac/bcmchip.h
@@ -17,12 +17,6 @@
#ifndef _bcmchip_h_
#define _bcmchip_h_
-/* Core reg address translation */
-#define CORE_CC_REG(base, field) (base + offsetof(chipcregs_t, field))
-#define CORE_BUS_REG(base, field) (base + offsetof(sdpcmd_regs_t, field))
-#define CORE_SB(base, field) \
- (base + SBCONFIGOFF + offsetof(sbconfig_t, field))
-
/* bcm4329 */
/* SDIO device core, ID 0x829 */
#define BCM4329_CORE_BUS_BASE 0x18011000
@@ -31,5 +25,8 @@
/* ARM Cortex M3 core, ID 0x82a */
#define BCM4329_CORE_ARM_BASE 0x18002000
#define BCM4329_RAMSIZE 0x48000
+/* firmware name */
+#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin"
+#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt"
#endif /* _bcmchip_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h b/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
deleted file mode 100644
index 53c32915acc9..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
+++ /dev/null
@@ -1,113 +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 _sdio_api_h_
-#define _sdio_api_h_
-
-#define SDIOH_API_RC_SUCCESS (0x00)
-#define SDIOH_API_RC_FAIL (0x01)
-#define SDIOH_API_SUCCESS(status) (status == 0)
-
-#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 */
-
-#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 */
-
-typedef int SDIOH_API_RC;
-
-/* SDio Host structure */
-typedef struct sdioh_info sdioh_info_t;
-
-/* callback function, taking one arg */
-typedef void (*sdioh_cb_fn_t) (void *);
-
-/* 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 sdioh_info_t *sdioh_attach(void *cfghdl, uint irq);
-extern SDIOH_API_RC sdioh_detach(sdioh_info_t *si);
-extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si,
- sdioh_cb_fn_t fn, void *argh);
-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
-
-/* query whether SD interrupt is enabled or not */
-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
-
-/* enable or disable SD interrupt */
-extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
-
-#if defined(DHD_DEBUG)
-extern bool sdioh_interrupt_pending(sdioh_info_t *si);
-#endif
-
-extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
-extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
-
-/* read or write one byte using cmd52 */
-extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc,
- uint addr, u8 *byte);
-
-/* read or write 2/4 bytes using cmd53 */
-extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type,
- uint rw, uint fnc, uint addr,
- u32 *word, uint nbyte);
-
-/* read or write any buffer using cmd53 */
-extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *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 SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, u8 *cis,
- u32 length);
-
-extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, u32 addr,
- u8 *data);
-extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, u32 addr,
- u8 *data);
-
-/* query number of io functions */
-extern uint sdioh_query_iofnum(sdioh_info_t *si);
-
-/* handle iovars */
-extern int sdioh_iovar_op(sdioh_info_t *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 sdioh_abort(sdioh_info_t *si, uint fnc);
-
-/* Start and Stop SDIO without re-enumerating the SD card. */
-extern int sdioh_start(sdioh_info_t *si, int stage);
-extern int sdioh_stop(sdioh_info_t *si);
-
-/* Reset and re-initialize the device */
-extern int sdioh_sdio_reset(sdioh_info_t *si);
-
-/* Helper function */
-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
-
-#endif /* _sdio_api_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
index 3750fcf5a871..f4e72ed126b0 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
@@ -13,29 +13,59 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* ****************** BCMSDH Interface Functions *************************** */
+/* ****************** SDIO CARD Interface Functions **************************/
#include <linux/types.h>
#include <linux/netdevice.h>
+#include <linux/pci.h>
#include <linux/pci_ids.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-#include <hndsoc.h>
-
-#include <bcmsdh.h> /* BRCM API for SDIO
- clients (such as wl, dhd) */
-#include <bcmsdbus.h> /* common SDIO/controller interface */
-#include <sbsdio.h> /* BRCM sdio device core */
-
-#include <sdio.h> /* sdio spec */
-#include "dngl_stats.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
-const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
-struct bcmsdh_info {
+#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 */
@@ -43,282 +73,232 @@ struct bcmsdh_info {
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 */
-bcmsdh_info_t *l_bcmsdh;
+static struct brcmf_sdio_card *l_card;
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-extern int sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
+const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
-void bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
-{
- sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
-}
-#endif
+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);
-bcmsdh_info_t *bcmsdh_attach(void *cfghdl, void **regsva, uint irq)
+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)
{
- bcmsdh_info_t *bcmsdh;
+ struct brcmf_sdio_card *card;
- bcmsdh = kzalloc(sizeof(bcmsdh_info_t), GFP_ATOMIC);
- if (bcmsdh == NULL) {
- BCMSDH_ERROR(("bcmsdh_attach: out of memory"));
+ 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_bcmsdh = bcmsdh;
+ l_card = card;
- bcmsdh->sdioh = sdioh_attach(cfghdl, irq);
- if (!bcmsdh->sdioh) {
- bcmsdh_detach(bcmsdh);
+ card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
+ if (!card->sdioh) {
+ brcmf_sdcard_detach(card);
return NULL;
}
- bcmsdh->init_success = true;
+ card->init_success = true;
- *regsva = (u32 *) SI_ENUM_BASE;
+ *regsva = SI_ENUM_BASE;
/* Report the BAR, to fix if needed */
- bcmsdh->sbwad = SI_ENUM_BASE;
- return bcmsdh;
+ card->sbwad = SI_ENUM_BASE;
+ return card;
}
-int bcmsdh_detach(void *sdh)
+int brcmf_sdcard_detach(struct brcmf_sdio_card *card)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
- if (bcmsdh != NULL) {
- if (bcmsdh->sdioh) {
- sdioh_detach(bcmsdh->sdioh);
- bcmsdh->sdioh = NULL;
+ if (card != NULL) {
+ if (card->sdioh) {
+ brcmf_sdioh_detach(card->sdioh);
+ card->sdioh = NULL;
}
- kfree(bcmsdh);
+ kfree(card);
}
- l_bcmsdh = NULL;
+ l_card = NULL;
return 0;
}
int
-bcmsdh_iovar_op(void *sdh, const char *name,
+brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
void *params, int plen, void *arg, int len, bool set)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set);
-}
-
-bool bcmsdh_intr_query(void *sdh)
-{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
- bool on;
-
- ASSERT(bcmsdh);
- status = sdioh_interrupt_query(bcmsdh->sdioh, &on);
- if (SDIOH_API_SUCCESS(status))
- return false;
- else
- return on;
-}
-
-int bcmsdh_intr_enable(void *sdh)
-{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
- ASSERT(bcmsdh);
-
- status = sdioh_interrupt_set(bcmsdh->sdioh, true);
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg,
+ len, set);
}
-int bcmsdh_intr_disable(void *sdh)
+int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
- ASSERT(bcmsdh);
-
- status = sdioh_interrupt_set(bcmsdh->sdioh, false);
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ return brcmf_sdioh_interrupt_set(card->sdioh, true);
}
-int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
- ASSERT(bcmsdh);
-
- status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ return brcmf_sdioh_interrupt_set(card->sdioh, false);
}
-int bcmsdh_intr_dereg(void *sdh)
+int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
+ void (*fn)(void *), void *argh)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
- ASSERT(bcmsdh);
-
- status = sdioh_interrupt_deregister(bcmsdh->sdioh);
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh);
}
-#if defined(DHD_DEBUG)
-bool bcmsdh_intr_pending(void *sdh)
+int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
- ASSERT(sdh);
- return sdioh_interrupt_pending(bcmsdh->sdioh);
+ return brcmf_sdioh_interrupt_deregister(card->sdioh);
}
-#endif
-int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
+ int *err)
{
- ASSERT(sdh);
-
- /* don't support yet */
- return -ENOTSUPP;
-}
-
-u8 bcmsdh_cfg_read(void *sdh, uint fnc_num, u32 addr, int *err)
-{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ int status;
s32 retry = 0;
-#endif
u8 data = 0;
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
-
- ASSERT(bcmsdh->init_success);
+ if (!card)
+ card = l_card;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
do {
if (retry) /* wait for 1 ms till bus get settled down */
udelay(1000);
-#endif
status =
- sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr,
+ brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr,
(u8 *) &data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- } while (!SDIOH_API_SUCCESS(status)
+ } while (status != 0
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
if (err)
- *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+ *err = status;
- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
+ BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
__func__, fnc_num, addr, data));
return data;
}
void
-bcmsdh_cfg_write(void *sdh, uint fnc_num, u32 addr, u8 data, int *err)
+brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
+ u8 data, int *err)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ int status;
s32 retry = 0;
-#endif
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
+ if (!card)
+ card = l_card;
- ASSERT(bcmsdh->init_success);
-
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
do {
if (retry) /* wait for 1 ms till bus get settled down */
udelay(1000);
-#endif
status =
- sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr,
+ brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr,
(u8 *) &data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- } while (!SDIOH_API_SUCCESS(status)
+ } while (status != 0
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
if (err)
- *err = SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ *err = status;
- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
+ BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
__func__, fnc_num, addr, data));
}
-u32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, u32 addr, int *err)
+u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
+ u32 addr, int *err)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
+ int status;
u32 data = 0;
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
-
- ASSERT(bcmsdh->init_success);
+ if (!card)
+ card = l_card;
- status =
- sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ,
- fnc_num, addr, &data, 4);
+ status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
+ SDIOH_READ, fnc_num, addr, &data, 4);
if (err)
- *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+ *err = status;
- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
+ BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
__func__, fnc_num, addr, data));
return data;
}
void
-bcmsdh_cfg_write_word(void *sdh, uint fnc_num, u32 addr, u32 data,
- int *err)
+brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num,
+ u32 addr, u32 data, int *err)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
-
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
+ int status;
- ASSERT(bcmsdh->init_success);
+ if (!card)
+ card = l_card;
status =
- sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+ brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
SDIOH_WRITE, fnc_num, addr, &data, 4);
if (err)
- *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+ *err = status;
- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
+ BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
__func__, fnc_num, addr, data));
}
-int bcmsdh_cis_read(void *sdh, uint func, u8 * cis, uint length)
+int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis,
+ uint length)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
+ int status;
u8 *tmp_buf, *tmp_ptr;
u8 *ptr;
bool ascii = func & ~0xf;
func &= 0x7;
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
+ if (!card)
+ card = l_card;
- ASSERT(bcmsdh->init_success);
- ASSERT(cis);
- ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
-
- status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
+ 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) {
- BCMSDH_ERROR(("%s: out of memory\n", __func__));
+ BRCMF_SD_ERROR(("%s: out of memory\n", __func__));
return -ENOMEM;
}
memcpy(tmp_buf, cis, length);
@@ -331,60 +311,60 @@ int bcmsdh_cis_read(void *sdh, uint func, u8 * cis, uint length)
kfree(tmp_buf);
}
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ return status;
}
-static int bcmsdhsdio_set_sbaddr_window(void *sdh, u32 address)
+static int
+brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
{
int err = 0;
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
(address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
if (!err)
- bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
- (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_SBADDRMID,
+ (address >> 16) & SBSDIO_SBADDRMID_MASK,
+ &err);
if (!err)
- bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
- (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
- &err);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_SBADDRHIGH,
+ (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
+ &err);
return err;
}
-u32 bcmsdh_reg_read(void *sdh, u32 addr, uint size)
+u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
+ int status;
u32 word = 0;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
-
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
+ BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
- ASSERT(bcmsdh->init_success);
+ if (!card)
+ card = l_card;
- if (bar0 != bcmsdh->sbwad) {
- if (bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))
+ if (bar0 != card->sbwad) {
+ if (brcmf_sdcard_set_sbaddr_window(card, bar0))
return 0xFFFFFFFF;
- bcmsdh->sbwad = bar0;
+ card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
if (size == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+ status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
- bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+ card->regfail = (status != 0);
- BCMSDH_INFO(("u32data = 0x%x\n", word));
+ BRCMF_SD_INFO(("u32data = 0x%x\n", word));
/* if ok, return appropriately masked word */
- if (SDIOH_API_SUCCESS(status)) {
+ if (status == 0) {
switch (size) {
case sizeof(u8):
return word & 0xff;
@@ -393,90 +373,86 @@ u32 bcmsdh_reg_read(void *sdh, u32 addr, uint size)
case sizeof(u32):
return word;
default:
- bcmsdh->regfail = true;
+ card->regfail = true;
}
}
/* otherwise, bad sdio access or invalid size */
- BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
+ BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
addr, size));
return 0xFFFFFFFF;
}
-u32 bcmsdh_reg_write(void *sdh, u32 addr, uint size, u32 data)
+u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
+ u32 data)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
+ int status;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
- BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
+ BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
__func__, addr, size * 8, data));
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
-
- ASSERT(bcmsdh->init_success);
+ if (!card)
+ card = l_card;
- if (bar0 != bcmsdh->sbwad) {
- err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+ if (bar0 != card->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(card, bar0);
if (err)
return err;
- bcmsdh->sbwad = bar0;
+ card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
if (size == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
status =
- sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+ brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
- bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+ card->regfail = (status != 0);
- if (SDIOH_API_SUCCESS(status))
+ if (status == 0)
return 0;
- BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
+ BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
__func__, data, addr, size));
return 0xFFFFFFFF;
}
-bool bcmsdh_regfail(void *sdh)
+bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card)
{
- return ((bcmsdh_info_t *) sdh)->regfail;
+ return card->regfail;
}
int
-bcmsdh_recv_buf(void *sdh, u32 addr, uint fn, uint flags,
- u8 *buf, uint nbytes, struct sk_buff *pkt,
- bcmsdh_cmplt_fn_t complete, void *handle)
-{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
+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;
- ASSERT(bcmsdh);
- ASSERT(bcmsdh->init_success);
-
- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+ BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
__func__, fn, addr, nbytes));
/* Async not implemented yet */
- ASSERT(!(flags & SDIO_REQ_ASYNC));
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
- if (bar0 != bcmsdh->sbwad) {
- err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+ if (bar0 != card->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(card, bar0);
if (err)
return err;
- bcmsdh->sbwad = bar0;
+ card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
@@ -486,42 +462,37 @@ bcmsdh_recv_buf(void *sdh, u32 addr, uint fn, uint flags,
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
- SDIOH_READ, fn, addr, width, nbytes, buf,
- pkt);
+ status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
+ incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ return status;
}
int
-bcmsdh_send_buf(void *sdh, u32 addr, uint fn, uint flags,
- u8 *buf, uint nbytes, void *pkt,
- bcmsdh_cmplt_fn_t complete, void *handle)
+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)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
uint incr_fix;
uint width;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
- ASSERT(bcmsdh);
- ASSERT(bcmsdh->init_success);
-
- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+ BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
__func__, fn, addr, nbytes));
/* Async not implemented yet */
- ASSERT(!(flags & SDIO_REQ_ASYNC));
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
- if (bar0 != bcmsdh->sbwad) {
- err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+ if (bar0 != card->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(card, bar0);
if (err)
return err;
- bcmsdh->sbwad = bar0;
+ card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
@@ -531,101 +502,141 @@ bcmsdh_send_buf(void *sdh, u32 addr, uint fn, uint flags,
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
- SDIOH_WRITE, fn, addr, width, nbytes, buf,
- pkt);
-
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
+ incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
}
-int bcmsdh_rwdata(void *sdh, uint rw, u32 addr, u8 *buf, uint nbytes)
+int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
+ u8 *buf, uint nbytes)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- SDIOH_API_RC status;
-
- ASSERT(bcmsdh);
- ASSERT(bcmsdh->init_success);
- ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
-
addr &= SBSDIO_SB_OFT_ADDR_MASK;
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- status =
- sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC,
- (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
- addr, 4, nbytes, buf, NULL);
-
- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+ 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 bcmsdh_abort(void *sdh, uint fn)
+int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
- return sdioh_abort(bcmsdh->sdioh, fn);
+ return brcmf_sdioh_abort(card->sdioh, fn);
}
-int bcmsdh_start(void *sdh, int stage)
+int brcmf_sdcard_query_device(struct brcmf_sdio_card *card)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
- return sdioh_start(bcmsdh->sdioh, stage);
+ card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
+ return card->vendevid;
}
-int bcmsdh_stop(void *sdh)
+u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+ if (!card)
+ card = l_card;
- return sdioh_stop(bcmsdh->sdioh);
+ return card->sbwad;
}
-int bcmsdh_query_device(void *sdh)
+int brcmf_sdio_probe(struct device *dev)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
- bcmsdh->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
- return bcmsdh->vendevid;
-}
+ struct sdio_hc *sdhc = NULL;
+ u32 regs = 0;
+ struct brcmf_sdio_card *card = NULL;
+ int irq = 0;
+ u32 vendevid;
+ unsigned long irq_flags = 0;
-uint bcmsdh_query_iofnum(void *sdh)
-{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+ /* 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;
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
+ card = brcmf_sdcard_attach((void *)0, &regs, irq);
+ if (!card) {
+ SDLX_MSG(("%s: attach failed\n", __func__));
+ goto err;
+ }
- return sdioh_query_iofnum(bcmsdh->sdioh);
-}
+ 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;
+ }
-int bcmsdh_reset(bcmsdh_info_t *sdh)
-{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+ return 0;
- return sdioh_sdio_reset(bcmsdh->sdioh);
-}
+ /* error handling */
+err:
+ if (sdhc) {
+ if (sdhc->card)
+ brcmf_sdcard_detach(sdhc->card);
+ kfree(sdhc);
+ }
-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh)
-{
- ASSERT(sdh);
- return sdh->sdioh;
+ return -ENODEV;
}
-/* Function to pass device-status bits to DHD. */
-u32 bcmsdh_get_dstatus(void *sdh)
+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;
}
-u32 bcmsdh_cur_sbwad(void *sdh)
+int brcmf_sdio_register(struct brcmf_sdioh_driver *driver)
{
- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+ drvinfo = *driver;
- if (!bcmsdh)
- bcmsdh = l_bcmsdh;
+ SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
+ return brcmf_sdio_function_init();
+}
- return bcmsdh->sbwad;
+void brcmf_sdio_unregister(void)
+{
+ brcmf_sdio_function_cleanup();
}
-void bcmsdh_chipinfo(void *sdh, u32 chip, u32 chiprev)
+void brcmf_sdio_wdtmr_enable(bool enable)
{
- return;
+ 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_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
deleted file mode 100644
index 465f623760f3..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
+++ /dev/null
@@ -1,386 +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.
- */
-
-/**
- * @file bcmsdh_linux.c
- */
-
-#define __UNDEF_NO_VERSION__
-
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/completion.h>
-
-#include <pcicfg.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-
-#if defined(OOB_INTR_ONLY)
-#include <linux/irq.h>
-extern void dhdsdio_isr(void *args);
-#include <dngl_stats.h>
-#include <dhd.h>
-#endif /* defined(OOB_INTR_ONLY) */
-#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270)
-#if !defined(BCMPLATFORM_BUS)
-#define BCMPLATFORM_BUS
-#endif /* !defined(BCMPLATFORM_BUS) */
-
-#include <linux/platform_device.h>
-#endif /* CONFIG_MACH_SANDGATE2G */
-
-#include "dngl_stats.h"
-#include "dhd.h"
-
-/**
- * SDIO Host Controller info
- */
-typedef struct bcmsdh_hc bcmsdh_hc_t;
-
-struct bcmsdh_hc {
- bcmsdh_hc_t *next;
-#ifdef BCMPLATFORM_BUS
- struct device *dev; /* platform device handle */
-#else
- struct pci_dev *dev; /* pci device handle */
-#endif /* BCMPLATFORM_BUS */
- void *regs; /* SDIO Host Controller address */
- bcmsdh_info_t *sdh; /* SDIO Host Controller handle */
- void *ch;
- unsigned int oob_irq;
- unsigned long oob_flags; /* OOB Host specifiction
- as edge and etc */
- bool oob_irq_registered;
-#if defined(OOB_INTR_ONLY)
- spinlock_t irq_lock;
-#endif
-};
-static bcmsdh_hc_t *sdhcinfo;
-
-/* driver info, initialized when bcmsdh_register is called */
-static bcmsdh_driver_t drvinfo = { NULL, NULL };
-
-/* debugging macros */
-#define SDLX_MSG(x)
-
-/**
- * Checks to see if vendor and device IDs match a supported SDIO Host Controller.
- */
-bool bcmsdh_chipmatch(u16 vendor, u16 device)
-{
- /* Add other vendors and devices as required */
-
-#ifdef BCMSDIOH_STD
- /* Check for Arasan host controller */
- if (vendor == VENDOR_SI_IMAGE)
- return true;
-
- /* Check for BRCM 27XX Standard host controller */
- if (device == BCM27XX_SDIOH_ID && vendor == PCI_VENDOR_ID_BROADCOM)
- return true;
-
- /* Check for BRCM Standard host controller */
- if (device == SDIOH_FPGA_ID && vendor == PCI_VENDOR_ID_BROADCOM)
- return true;
-
- /* Check for TI PCIxx21 Standard host controller */
- if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI)
- return true;
-
- if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI)
- return true;
-
- /* Ricoh R5C822 Standard SDIO Host */
- if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH)
- return true;
-
- /* JMicron Standard SDIO Host */
- if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON)
- return true;
-#endif /* BCMSDIOH_STD */
-#ifdef BCMSDIOH_SPI
- /* This is the PciSpiHost. */
- if (device == SPIH_FPGA_ID && vendor == PCI_VENDOR_ID_BROADCOM) {
- return true;
- }
-#endif /* BCMSDIOH_SPI */
-
- return false;
-}
-
-#if defined(BCMPLATFORM_BUS)
-#if defined(BCMLXSDMMC)
-/* forward declarations */
-int bcmsdh_probe(struct device *dev);
-EXPORT_SYMBOL(bcmsdh_probe);
-
-int bcmsdh_remove(struct device *dev);
-EXPORT_SYMBOL(bcmsdh_remove);
-
-#else
-/* forward declarations */
-static int __devinit bcmsdh_probe(struct device *dev);
-static int __devexit bcmsdh_remove(struct device *dev);
-#endif /* BCMLXSDMMC */
-
-#ifndef BCMLXSDMMC
-static
-#endif /* BCMLXSDMMC */
-int bcmsdh_probe(struct device *dev)
-{
- bcmsdh_hc_t *sdhc = NULL;
- unsigned long regs = 0;
- bcmsdh_info_t *sdh = NULL;
-#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
- struct platform_device *pdev;
- struct resource *r;
-#endif /* BCMLXSDMMC */
- int irq = 0;
- u32 vendevid;
- unsigned long irq_flags = 0;
-
-#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
- pdev = to_platform_device(dev);
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (!r || irq == NO_IRQ)
- return -ENXIO;
-#endif /* BCMLXSDMMC */
-
-#if defined(OOB_INTR_ONLY)
-#ifdef HW_OOB
- irq_flags =
- IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
- IORESOURCE_IRQ_SHAREABLE;
-#else
- irq_flags = IRQF_TRIGGER_FALLING;
-#endif /* HW_OOB */
- irq = dhd_customer_oob_irq_map(&irq_flags);
- if (irq < 0) {
- SDLX_MSG(("%s: Host irq is not defined\n", __func__));
- return 1;
- }
-#endif /* defined(OOB_INTR_ONLY) */
- /* allocate SDIO Host Controller state info */
- sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC);
- if (!sdhc) {
- SDLX_MSG(("%s: out of memory\n", __func__));
- goto err;
- }
- sdhc->dev = (void *)dev;
-
-#ifdef BCMLXSDMMC
- sdh = bcmsdh_attach((void *)0, (void **)&regs, irq);
- if (!sdh) {
- SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
- goto err;
- }
-#else
- sdh = bcmsdh_attach((void *)r->start, (void **)&regs, irq);
- if (!sdh) {
- SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
- goto err;
- }
-#endif /* BCMLXSDMMC */
- sdhc->sdh = sdh;
- sdhc->oob_irq = irq;
- sdhc->oob_flags = irq_flags;
- sdhc->oob_irq_registered = false; /* to make sure.. */
-#if defined(OOB_INTR_ONLY)
- spin_lock_init(&sdhc->irq_lock);
-#endif
-
- /* chain SDIO Host Controller info together */
- sdhc->next = sdhcinfo;
- sdhcinfo = sdhc;
- /* Read the vendor/device ID from the CIS */
- vendevid = bcmsdh_query_device(sdh);
-
- /* try to attach to the target device */
- sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
- 0, 0, 0, 0, (void *)regs, sdh);
- if (!sdhc->ch) {
- SDLX_MSG(("%s: device attach failed\n", __func__));
- goto err;
- }
-
- return 0;
-
- /* error handling */
-err:
- if (sdhc) {
- if (sdhc->sdh)
- bcmsdh_detach(sdhc->sdh);
- kfree(sdhc);
- }
-
- return -ENODEV;
-}
-
-#ifndef BCMLXSDMMC
-static
-#endif /* BCMLXSDMMC */
-int bcmsdh_remove(struct device *dev)
-{
- bcmsdh_hc_t *sdhc, *prev;
-
- sdhc = sdhcinfo;
- drvinfo.detach(sdhc->ch);
- bcmsdh_detach(sdhc->sdh);
- /* 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);
-
-#if !defined(BCMLXSDMMC)
- dev_set_drvdata(dev, NULL);
-#endif /* !defined(BCMLXSDMMC) */
-
- return 0;
-}
-#endif /* BCMPLATFORM_BUS */
-
-extern int sdio_function_init(void);
-
-int bcmsdh_register(bcmsdh_driver_t *driver)
-{
- drvinfo = *driver;
-
- SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
- return sdio_function_init();
-}
-
-extern void sdio_function_cleanup(void);
-
-void bcmsdh_unregister(void)
-{
- sdio_function_cleanup();
-}
-
-#if defined(OOB_INTR_ONLY)
-void bcmsdh_oob_intr_set(bool enable)
-{
- static bool curstate = 1;
- unsigned long flags;
-
- spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
- if (curstate != enable) {
- if (enable)
- enable_irq(sdhcinfo->oob_irq);
- else
- disable_irq_nosync(sdhcinfo->oob_irq);
- curstate = enable;
- }
- spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
-}
-
-static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
-{
- dhd_pub_t *dhdp;
-
- dhdp = (dhd_pub_t *) dev_get_drvdata(sdhcinfo->dev);
-
- bcmsdh_oob_intr_set(0);
-
- if (dhdp == NULL) {
- SDLX_MSG(("Out of band GPIO interrupt fired way too early\n"));
- return IRQ_HANDLED;
- }
-
- dhdsdio_isr((void *)dhdp->bus);
-
- return IRQ_HANDLED;
-}
-
-int bcmsdh_register_oob_intr(void *dhdp)
-{
- int error = 0;
-
- SDLX_MSG(("%s Enter\n", __func__));
-
- sdhcinfo->oob_flags =
- IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
- IORESOURCE_IRQ_SHAREABLE;
- dev_set_drvdata(sdhcinfo->dev, dhdp);
-
- if (!sdhcinfo->oob_irq_registered) {
- SDLX_MSG(("%s IRQ=%d Type=%X\n", __func__,
- (int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags));
- /* Refer to customer Host IRQ docs about
- proper irqflags definition */
- error =
- request_irq(sdhcinfo->oob_irq, wlan_oob_irq,
- sdhcinfo->oob_flags, "bcmsdh_sdmmc", NULL);
- if (error)
- return -ENODEV;
-
- irq_set_irq_wake(sdhcinfo->oob_irq, 1);
- sdhcinfo->oob_irq_registered = true;
- }
-
- return 0;
-}
-
-void bcmsdh_unregister_oob_intr(void)
-{
- SDLX_MSG(("%s: Enter\n", __func__));
-
- irq_set_irq_wake(sdhcinfo->oob_irq, 0);
- disable_irq(sdhcinfo->oob_irq); /* just in case.. */
- free_irq(sdhcinfo->oob_irq, NULL);
- sdhcinfo->oob_irq_registered = false;
-}
-#endif /* defined(OOB_INTR_ONLY) */
-/* Module parameters specific to each host-controller driver */
-
-extern uint sd_msglevel; /* Debug message level */
-module_param(sd_msglevel, uint, 0);
-
-extern uint sd_power; /* 0 = SD Power OFF,
- 1 = SD Power ON. */
-module_param(sd_power, uint, 0);
-
-extern uint sd_clock; /* SD Clock Control, 0 = SD Clock OFF,
- 1 = SD Clock ON */
-module_param(sd_clock, uint, 0);
-
-extern uint sd_divisor; /* Divisor (-1 means external clock) */
-module_param(sd_divisor, uint, 0);
-
-extern uint sd_sdmode; /* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */
-module_param(sd_sdmode, uint, 0);
-
-extern uint sd_hiok; /* Ok to use hi-speed mode */
-module_param(sd_hiok, uint, 0);
-
-extern uint sd_f2_blocksize;
-module_param(sd_f2_blocksize, int, 0);
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index c0ffbd35e0ca..38bd9ba3096f 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -15,64 +15,179 @@
*/
#include <linux/types.h>
#include <linux/netdevice.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-#include <sdio.h> /* SDIO Device and Protocol Specs */
-#include <sdioh.h> /* SDIO Host Controller Specification */
-#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h> /* ioctl/iovars */
-
+#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 <dngl_stats.h>
-#include <dhd.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"
-#include "bcmsdh_sdmmc.h"
+#define BLOCK_SIZE_64 64
+#define BLOCK_SIZE_512 512
+#define BLOCK_SIZE_4318 64
+#define BLOCK_SIZE_4328 512
-extern int sdio_function_init(void);
-extern void sdio_function_cleanup(void);
+/* private bus modes */
+#define SDIOH_MODE_SD4 2
-#if !defined(OOB_INTR_ONLY)
-static void IRQHandler(struct sdio_func *func);
-static void IRQHandlerF2(struct sdio_func *func);
-#endif /* !defined(OOB_INTR_ONLY) */
-static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr);
-extern int sdio_reset_comm(struct mmc_card *card);
+#define CLIENT_INTR 0x100 /* Get rid of this! */
-extern PBCMSDH_SDMMC_INSTANCE gInstance;
+#if !defined(SDIO_VENDOR_ID_BROADCOM)
+#define SDIO_VENDOR_ID_BROADCOM 0x02d0
+#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
-uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */
-uint sd_f2_blocksize = 512; /* Default blocksize */
+#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000
+
+#define DMA_ALIGN_MASK 0x03
-uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */
+#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_power = 1; /* Default to SD Slot powered ON */
-uint sd_clock = 1; /* Default to SD Clock turned ON */
-uint sd_hiok = false; /* Don't use hi-speed mode by default */
uint sd_msglevel = 0x01;
-uint sd_use_dma = true;
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
-#define DMA_ALIGN_MASK 0x03
+/* module param defaults */
+static int clockoverride;
-int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
- int regsize, u32 *data);
+module_param(clockoverride, int, 0644);
+MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
-void sdioh_sdio_set_host_pm_flags(int flag)
-{
- if (sdio_set_host_pm_flags(gInstance->func[1], flag))
- printk(KERN_ERR "%s: Failed to set pm_flags 0x%08x\n",\
- __func__, (unsigned int)flag);
-}
+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 sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
+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;
@@ -81,16 +196,16 @@ static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
sd_trace(("%s\n", __func__));
/* Get the Card's common CIS address */
- sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
+ 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 = SDIOD_FBR_STARTADDR, func = 1;
+ for (fbraddr = SDIO_FBR_BASE(1), func = 1;
func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
sd->func_cis_ptr[func] =
- sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
+ 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]));
}
@@ -104,8 +219,8 @@ static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
err_ret = sdio_enable_func(gInstance->func[1]);
sdio_release_host(gInstance->func[1]);
if (err_ret) {
- sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x",
- err_ret));
+ sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 "
+ "Err: 0x%08x\n", err_ret));
}
return false;
@@ -114,9 +229,9 @@ static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
/*
* Public entry points & extern's
*/
-sdioh_info_t *sdioh_attach(void *bar0, uint irq)
+struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
{
- sdioh_info_t *sd;
+ struct sdioh_info *sd;
int err_ret;
sd_trace(("%s\n", __func__));
@@ -126,19 +241,18 @@ sdioh_info_t *sdioh_attach(void *bar0, uint irq)
return NULL;
}
- sd = kzalloc(sizeof(sdioh_info_t), GFP_ATOMIC);
+ sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
if (sd == NULL) {
sd_err(("sdioh_attach: out of memory\n"));
return NULL;
}
- if (sdioh_sdmmc_osinit(sd) != 0) {
+ if (brcmf_sdioh_osinit(sd) != 0) {
sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
kfree(sd);
return NULL;
}
sd->num_funcs = 2;
- sd->sd_blockmode = true;
sd->use_client_ints = true;
sd->client_block_size[0] = 64;
@@ -150,7 +264,7 @@ sdioh_info_t *sdioh_attach(void *bar0, uint irq)
sd->client_block_size[1] = 64;
err_ret = sdio_set_block_size(gInstance->func[1], 64);
if (err_ret)
- sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
+ sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n"));
/* Release host controller F1 */
sdio_release_host(gInstance->func[1]);
@@ -163,20 +277,20 @@ sdioh_info_t *sdioh_attach(void *bar0, uint irq)
err_ret =
sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
if (err_ret)
- sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize "
- "to %d\n", sd_f2_blocksize));
+ 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]);
}
- sdioh_sdmmc_card_enablefuncs(sd);
+ brcmf_sdioh_enablefuncs(sd);
sd_trace(("%s: Done\n", __func__));
return sd;
}
-extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
+extern int brcmf_sdioh_detach(struct sdioh_info *sd)
{
sd_trace(("%s\n", __func__));
@@ -193,92 +307,25 @@ extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
sdio_release_host(gInstance->func[1]);
/* deregister irq */
- sdioh_sdmmc_osfree(sd);
+ brcmf_sdioh_osfree(sd);
kfree(sd);
}
- return SDIOH_API_RC_SUCCESS;
-}
-
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-
-extern SDIOH_API_RC sdioh_enable_func_intr(void)
-{
- u8 reg;
- int err;
-
- if (gInstance->func[0]) {
- sdio_claim_host(gInstance->func[0]);
-
- reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
- if (err) {
- sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
- __func__, err));
- sdio_release_host(gInstance->func[0]);
- return SDIOH_API_RC_FAIL;
- }
-
- /* Enable F1 and F2 interrupts, set master enable */
- reg |=
- (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN |
- INTR_CTL_MASTER_EN);
-
- sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
- sdio_release_host(gInstance->func[0]);
-
- if (err) {
- sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
- __func__, err));
- return SDIOH_API_RC_FAIL;
- }
- }
-
- return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC sdioh_disable_func_intr(void)
-{
- u8 reg;
- int err;
-
- if (gInstance->func[0]) {
- sdio_claim_host(gInstance->func[0]);
- reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
- if (err) {
- sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
- __func__, err));
- sdio_release_host(gInstance->func[0]);
- return SDIOH_API_RC_FAIL;
- }
-
- reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
- /* Disable master interrupt with the last function interrupt */
- if (!(reg & 0xFE))
- reg = 0;
- sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
-
- sdio_release_host(gInstance->func[0]);
- if (err) {
- sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
- __func__, err));
- return SDIOH_API_RC_FAIL;
- }
- }
- return SDIOH_API_RC_SUCCESS;
+ return 0;
}
-#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
/* Configure callback to client when we receive client interrupt */
-extern SDIOH_API_RC
-sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
+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 SDIOH_API_RC_FAIL;
+ return -EINVAL;
}
-#if !defined(OOB_INTR_ONLY)
+
sd->intr_handler = fn;
sd->intr_handler_arg = argh;
sd->intr_handler_valid = true;
@@ -286,26 +333,23 @@ sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
/* register and unmask irq */
if (gInstance->func[2]) {
sdio_claim_host(gInstance->func[2]);
- sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
+ 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], IRQHandler);
+ sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
sdio_release_host(gInstance->func[1]);
}
-#elif defined(HW_OOB)
- sdioh_enable_func_intr();
-#endif /* defined(OOB_INTR_ONLY) */
- return SDIOH_API_RC_SUCCESS;
+
+ return 0;
}
-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *sd)
+extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
{
sd_trace(("%s: Entering\n", __func__));
-#if !defined(OOB_INTR_ONLY)
if (gInstance->func[1]) {
/* register and unmask irq */
sdio_claim_host(gInstance->func[1]);
@@ -324,73 +368,28 @@ extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *sd)
sd->intr_handler_valid = false;
sd->intr_handler = NULL;
sd->intr_handler_arg = NULL;
-#elif defined(HW_OOB)
- sdioh_disable_func_intr();
-#endif /* !defined(OOB_INTR_ONLY) */
- return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
-{
- sd_trace(("%s: Entering\n", __func__));
- *onoff = sd->client_intr_enabled;
- return SDIOH_API_RC_SUCCESS;
-}
-#if defined(DHD_DEBUG)
-extern bool sdioh_interrupt_pending(sdioh_info_t *sd)
-{
return 0;
}
-#endif
-
-uint sdioh_query_iofnum(sdioh_info_t *sd)
-{
- return sd->num_funcs;
-}
/* IOVar table */
enum {
IOV_MSGLEVEL = 1,
- IOV_BLOCKMODE,
IOV_BLOCKSIZE,
- IOV_DMA,
IOV_USEINTS,
IOV_NUMINTS,
- IOV_NUMLOCALINTS,
- IOV_HOSTREG,
IOV_DEVREG,
- IOV_DIVISOR,
- IOV_SDMODE,
- IOV_HISPEED,
IOV_HCIREGS,
- IOV_POWER,
- IOV_CLOCK,
IOV_RXCHAIN
};
-const bcm_iovar_t sdioh_iovars[] = {
+const struct brcmu_iovar sdioh_iovars[] = {
{"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
- {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0},
{"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
size) */
- {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0},
{"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
{"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
- {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0},
- {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
- ,
- {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
- ,
- {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0}
- ,
- {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0}
- ,
- {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0}
- ,
- {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}
- ,
- {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}
+ {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
,
{"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
,
@@ -398,33 +397,37 @@ const bcm_iovar_t sdioh_iovars[] = {
};
int
-sdioh_iovar_op(sdioh_info_t *si, const char *name,
- void *params, int plen, void *arg, int len, bool set)
+brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
{
- const bcm_iovar_t *vi = NULL;
+ const struct brcmu_iovar *vi = NULL;
int bcmerror = 0;
int val_size;
s32 int_val = 0;
bool bool_val;
u32 actionid;
- ASSERT(name);
- ASSERT(len >= 0);
+ if (name == NULL || len <= 0)
+ return -EINVAL;
+
+ /* Set does not take qualifiers */
+ if (set && (params || plen))
+ return -EINVAL;
- /* Get must have return space; Set does not take qualifiers */
- ASSERT(set || (arg && len));
- ASSERT(!set || (!params && !plen));
+ /* Get must have return space;*/
+ if (!set && !(arg && len))
+ return -EINVAL;
sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
name));
- vi = bcm_iovar_lookup(sdioh_iovars, name);
+ vi = brcmu_iovar_lookup(sdioh_iovars, name);
if (vi == NULL) {
bcmerror = -ENOTSUPP;
goto exit;
}
- bcmerror = bcm_iovar_lencheck(vi, arg, len, set);
+ bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
if (bcmerror != 0)
goto exit;
@@ -457,16 +460,6 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
sd_msglevel = int_val;
break;
- case IOV_GVAL(IOV_BLOCKMODE):
- int_val = (s32) si->sd_blockmode;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_BLOCKMODE):
- si->sd_blockmode = (bool) int_val;
- /* Haven't figured out how to make non-block mode with DMA */
- break;
-
case IOV_GVAL(IOV_BLOCKSIZE):
if ((u32) int_val > si->num_funcs) {
bcmerror = -EINVAL;
@@ -518,15 +511,6 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
memcpy(arg, &int_val, val_size);
break;
- case IOV_GVAL(IOV_DMA):
- int_val = (s32) si->sd_use_dma;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_DMA):
- si->sd_use_dma = (bool) int_val;
- break;
-
case IOV_GVAL(IOV_USEINTS):
int_val = (s32) si->use_client_ints;
memcpy(arg, &int_val, val_size);
@@ -541,117 +525,18 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
break;
- case IOV_GVAL(IOV_DIVISOR):
- int_val = (u32) sd_divisor;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_DIVISOR):
- sd_divisor = int_val;
- break;
-
- case IOV_GVAL(IOV_POWER):
- int_val = (u32) sd_power;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_POWER):
- sd_power = int_val;
- break;
-
- case IOV_GVAL(IOV_CLOCK):
- int_val = (u32) sd_clock;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_CLOCK):
- sd_clock = int_val;
- break;
-
- case IOV_GVAL(IOV_SDMODE):
- int_val = (u32) sd_sdmode;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_SDMODE):
- sd_sdmode = int_val;
- break;
-
- case IOV_GVAL(IOV_HISPEED):
- int_val = (u32) sd_hiok;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_HISPEED):
- sd_hiok = int_val;
- break;
-
case IOV_GVAL(IOV_NUMINTS):
int_val = (s32) si->intrcount;
memcpy(arg, &int_val, val_size);
break;
- case IOV_GVAL(IOV_NUMLOCALINTS):
- int_val = (s32) 0;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_HOSTREG):
- {
- sdreg_t *sd_ptr = (sdreg_t *) params;
-
- if (sd_ptr->offset < SD_SysAddr
- || sd_ptr->offset > SD_MaxCurCap) {
- sd_err(("%s: bad offset 0x%x\n", __func__,
- sd_ptr->offset));
- bcmerror = -EINVAL;
- break;
- }
-
- sd_trace(("%s: rreg%d at offset %d\n", __func__,
- (sd_ptr->offset & 1) ? 8
- : ((sd_ptr->offset & 2) ? 16 : 32),
- sd_ptr->offset));
- if (sd_ptr->offset & 1)
- int_val = 8; /* sdioh_sdmmc_rreg8(si,
- sd_ptr->offset); */
- else if (sd_ptr->offset & 2)
- int_val = 16; /* sdioh_sdmmc_rreg16(si,
- sd_ptr->offset); */
- else
- int_val = 32; /* sdioh_sdmmc_rreg(si,
- sd_ptr->offset); */
-
- memcpy(arg, &int_val, sizeof(int_val));
- break;
- }
-
- case IOV_SVAL(IOV_HOSTREG):
- {
- sdreg_t *sd_ptr = (sdreg_t *) params;
-
- if (sd_ptr->offset < SD_SysAddr
- || sd_ptr->offset > SD_MaxCurCap) {
- sd_err(("%s: bad offset 0x%x\n", __func__,
- sd_ptr->offset));
- bcmerror = -EINVAL;
- break;
- }
-
- sd_trace(("%s: wreg%d value 0x%08x at offset %d\n",
- __func__, sd_ptr->value,
- (sd_ptr->offset & 1) ? 8
- : ((sd_ptr->offset & 2) ? 16 : 32),
- sd_ptr->offset));
- break;
- }
-
case IOV_GVAL(IOV_DEVREG):
{
- sdreg_t *sd_ptr = (sdreg_t *) params;
+ struct brcmf_sdreg *sd_ptr =
+ (struct brcmf_sdreg *) params;
u8 data = 0;
- if (sdioh_cfg_read
+ if (brcmf_sdioh_cfg_read
(si, sd_ptr->func, sd_ptr->offset, &data)) {
bcmerror = -EIO;
break;
@@ -664,10 +549,11 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
case IOV_SVAL(IOV_DEVREG):
{
- sdreg_t *sd_ptr = (sdreg_t *) params;
+ struct brcmf_sdreg *sd_ptr =
+ (struct brcmf_sdreg *) params;
u8 data = (u8) sd_ptr->value;
- if (sdioh_cfg_write
+ if (brcmf_sdioh_cfg_write
(si, sd_ptr->func, sd_ptr->offset, &data)) {
bcmerror = -EIO;
break;
@@ -684,50 +570,32 @@ exit:
return bcmerror;
}
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-
-SDIOH_API_RC sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
-{
- SDIOH_API_RC status;
- u8 data;
-
- if (enable)
- data = 3; /* enable hw oob interrupt */
- else
- data = 4; /* disable hw oob interrupt */
- data |= 4; /* Active HIGH */
-
- status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
- return status;
-}
-#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
-
-extern SDIOH_API_RC
-sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
+extern int
+brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
{
- SDIOH_API_RC status;
- /* No lock needed since sdioh_request_byte does locking */
- status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, 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 SDIOH_API_RC
-sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
+extern int
+brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
{
- /* No lock needed since sdioh_request_byte does locking */
- SDIOH_API_RC status;
- status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, 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 sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr)
+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 ((sdioh_sdmmc_card_regread(sd, 0, regaddr, 1, &regdata)) !=
+ if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, &regdata)) !=
SUCCESS)
sd_err(("%s: Can't read!\n", __func__));
@@ -741,8 +609,8 @@ static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr)
return scratch;
}
-extern SDIOH_API_RC
-sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
+extern int
+brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
{
u32 count;
int offset;
@@ -754,7 +622,7 @@ sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
if (!sd->func_cis_ptr[func]) {
memset(cis, 0, length);
sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
- return SDIOH_API_RC_FAIL;
+ return -ENOTSUPP;
}
sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
@@ -762,37 +630,37 @@ sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
for (count = 0; count < length; count++) {
offset = sd->func_cis_ptr[func] + count;
- if (sdioh_sdmmc_card_regread(sd, 0, offset, 1, &foo) < 0) {
+ if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
sd_err(("%s: regread failed: Can't read CIS\n",
__func__));
- return SDIOH_API_RC_FAIL;
+ return -EIO;
}
*cis = (u8) (foo & 0xff);
cis++;
}
- return SDIOH_API_RC_SUCCESS;
+ return 0;
}
-extern SDIOH_API_RC
-sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
- u8 *byte)
+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));
- DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+ 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 == SDIOD_CCCR_IOEN) {
+ if (regaddr == SDIO_CCCR_IOEx) {
if (gInstance->func[2]) {
sdio_claim_host(gInstance->func[2]);
if (*byte & SDIO_FUNC_ENABLE_2) {
@@ -801,7 +669,9 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
sdio_enable_func
(gInstance->func[2]);
if (err_ret)
- sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
+ sd_err(("request_byte: "
+ "enable F2 "
+ "failed:%d\n",
err_ret));
} else {
/* Disable Function 2 */
@@ -809,15 +679,16 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
sdio_disable_func
(gInstance->func[2]);
if (err_ret)
- sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
+ sd_err(("request_byte: "
+ "Disab F2 "
+ "failed:%d\n",
err_ret));
}
sdio_release_host(gInstance->func[2]);
}
}
-#if defined(MMC_SDIO_ABORT)
/* to allow abort command through F1 */
- else if (regaddr == SDIOD_CCCR_IOABORT) {
+ else if (regaddr == SDIO_CCCR_ABORT) {
sdio_claim_host(gInstance->func[func]);
/*
* this sdio_f0_writeb() can be replaced
@@ -828,10 +699,8 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
sdio_writeb(gInstance->func[func], *byte,
regaddr, &err_ret);
sdio_release_host(gInstance->func[func]);
- }
-#endif /* MMC_SDIO_ABORT */
- else if (regaddr < 0xF0) {
- sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write "
+ } else if (regaddr < 0xF0) {
+ sd_err(("brcmf: F0 Wr:0x%02x: write "
"disallowed\n", regaddr));
} else {
/* Claim host controller, perform F0 write,
@@ -867,29 +736,29 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
}
if (err_ret)
- sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, "
+ 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 == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+ return err_ret;
}
-extern SDIOH_API_RC
-sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func,
- uint addr, u32 *word, uint nbytes)
+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 = SDIOH_API_RC_FAIL;
+ int err_ret = -EIO;
if (func == 0) {
sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
- return SDIOH_API_RC_FAIL;
+ 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));
- DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+ BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait);
+ BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
/* Claim host controller */
sdio_claim_host(gInstance->func[func]);
@@ -920,16 +789,16 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func,
sdio_release_host(gInstance->func[func]);
if (err_ret) {
- sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
+ sd_err(("brcmf: Failed to %s word, Err: 0x%08x\n",
rw ? "Write" : "Read", err_ret));
}
- return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+ return err_ret;
}
-static SDIOH_API_RC
-sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
- uint addr, struct sk_buff *pkt)
+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;
@@ -939,9 +808,8 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
sd_trace(("%s: Enter\n", __func__));
- ASSERT(pkt);
- DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+ BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait);
+ BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
/* Claim host controller */
sdio_claim_host(gInstance->func[func]);
@@ -950,21 +818,6 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
pkt_len += 3;
pkt_len &= 0xFFFFFFFC;
-#ifdef CONFIG_MMC_MSM7X00A
- if ((pkt_len % 64) == 32) {
- sd_trace(("%s: Rounding up TX packet +=32\n",
- __func__));
- pkt_len += 32;
- }
-#endif /* CONFIG_MMC_MSM7X00A */
- /* Make sure the packet is aligned properly.
- * If it isn't, then this
- * is the fault of sdioh_request_buffer() which
- * is supposed to give
- * us something we can work with.
- */
- ASSERT(((u32) (pkt->data) & DMA_ALIGN_MASK) == 0);
-
if ((write) && (!fifo)) {
err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
((u8 *) (pnext->data)),
@@ -1005,7 +858,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
sdio_release_host(gInstance->func[func]);
sd_trace(("%s: Exit\n", __func__));
- return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+ return err_ret;
}
/*
@@ -1023,114 +876,101 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
* aligned packet.
*
*/
-extern SDIOH_API_RC
-sdioh_request_buffer(sdioh_info_t *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)
+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)
{
- SDIOH_API_RC Status;
+ int Status;
struct sk_buff *mypkt = NULL;
sd_trace(("%s: Enter\n", __func__));
- DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+ 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 = bcm_pkt_buf_get_skb(buflen_u);
+ mypkt = brcmu_pkt_buf_get_skb(buflen_u);
if (!mypkt) {
- sd_err(("%s: bcm_pkt_buf_get_skb failed: len %d\n",
+ sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
__func__, buflen_u));
- return SDIOH_API_RC_FAIL;
+ return -EIO;
}
/* For a write, copy the buffer data into the packet. */
if (write)
memcpy(mypkt->data, buffer, buflen_u);
- Status =
- sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
+ 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);
- bcm_pkt_buf_free_skb(mypkt);
- } else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
- /* Case 2: We have a packet, but it is unaligned. */
-
- /* In this case, we cannot have a chain. */
- ASSERT(pkt->next == NULL);
-
+ 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 = bcm_pkt_buf_get_skb(pkt->len);
+ mypkt = brcmu_pkt_buf_get_skb(pkt->len);
if (!mypkt) {
- sd_err(("%s: bcm_pkt_buf_get_skb failed: len %d\n",
+ sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
__func__, pkt->len));
- return SDIOH_API_RC_FAIL;
+ return -EIO;
}
/* For a write, copy the buffer data into the packet. */
if (write)
memcpy(mypkt->data, pkt->data, pkt->len);
- Status =
- sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
+ 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);
- bcm_pkt_buf_free_skb(mypkt);
+ 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 =
- sdioh_request_packet(sd, fix_inc, write, func, addr, pkt);
+ 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 sdioh_abort(sdioh_info_t *sd, uint func)
+extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
{
-#if defined(MMC_SDIO_ABORT)
char t_func = (char)func;
-#endif /* defined(MMC_SDIO_ABORT) */
sd_trace(("%s: Enter\n", __func__));
-#if defined(MMC_SDIO_ABORT)
- /* issue abort cmd52 command through F1 */
- sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT,
+ /* issue abort cmd52 command through F0 */
+ brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
&t_func);
-#endif /* defined(MMC_SDIO_ABORT) */
-
- sd_trace(("%s: Exit\n", __func__));
- return SDIOH_API_RC_SUCCESS;
-}
-/* Reset and re-initialize the device */
-int sdioh_sdio_reset(sdioh_info_t *si)
-{
- sd_trace(("%s: Enter\n", __func__));
sd_trace(("%s: Exit\n", __func__));
- return SDIOH_API_RC_SUCCESS;
+ return 0;
}
/* Disable device interrupt */
-void sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
+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 sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
+void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
{
sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
sd->intmask |= CLIENT_INTR;
@@ -1138,19 +978,19 @@ void sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
/* Read client card reg */
int
-sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
+brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
int regsize, u32 *data)
{
if ((func == 0) || (regsize == 1)) {
u8 temp = 0;
- sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
+ 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 {
- sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
+ brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
regsize);
if (regsize == 2)
*data &= 0xffff;
@@ -1161,25 +1001,20 @@ sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
return SUCCESS;
}
-#if !defined(OOB_INTR_ONLY)
-/* bcmsdh_sdmmc interrupt handler */
-static void IRQHandler(struct sdio_func *func)
+static void brcmf_sdioh_irqhandler(struct sdio_func *func)
{
- sdioh_info_t *sd;
+ struct sdioh_info *sd;
- sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
+ sd_trace(("brcmf: ***IRQHandler\n"));
sd = gInstance->sd;
- ASSERT(sd != NULL);
sdio_release_host(gInstance->func[0]);
if (sd->use_client_ints) {
sd->intrcount++;
- ASSERT(sd->intr_handler);
- ASSERT(sd->intr_handler_arg);
(sd->intr_handler) (sd->intr_handler_arg);
} else {
- sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
+ 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));
@@ -1188,52 +1023,174 @@ static void IRQHandler(struct sdio_func *func)
sdio_claim_host(gInstance->func[0]);
}
-/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
-static void IRQHandlerF2(struct sdio_func *func)
+/* interrupt handler for F2 (dummy handler) */
+static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
{
- sdioh_info_t *sd;
+ struct sdioh_info *sd;
- sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
+ 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);
+ }
+ }
- ASSERT(sd != NULL);
+ 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;
}
-#endif /* !defined(OOB_INTR_ONLY) */
-#ifdef NOTUSED
-/* Write client card reg */
-static int
-sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, u32 regaddr,
- int regsize, u32 data)
+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);
+ }
+}
- if ((func == 0) || (regsize == 1)) {
- u8 temp;
- temp = data & 0xff;
- sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
- sd_data(("%s: byte write data=0x%02x\n", __func__, data));
- } else {
- if (regsize == 2)
- data &= 0xffff;
+#ifdef CONFIG_PM
+static int brcmf_sdio_suspend(struct device *dev)
+{
+ mmc_pm_flag_t sdio_flags;
+ int ret = 0;
- sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data,
- regsize);
+ sd_trace(("%s\n", __func__));
- sd_data(("%s: word write data=0x%08x\n", __func__, data));
+ 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;
}
- return SUCCESS;
+ 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 /* NOTUSED */
+#endif /* CONFIG_PM */
-int sdioh_start(sdioh_info_t *si, int stage)
+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;
}
-int sdioh_stop(sdioh_info_t *si)
+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/bcmsdh_sdmmc.h b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
deleted file mode 100644
index 3ef42b318493..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
+++ /dev/null
@@ -1,134 +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 __BCMSDH_SDMMC_H__
-#define __BCMSDH_SDMMC_H__
-
-#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
-
-/* Allocate/init/free per-OS private data */
-extern int sdioh_sdmmc_osinit(sdioh_info_t *sd);
-extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
-
-#define BLOCK_SIZE_64 64
-#define BLOCK_SIZE_512 512
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* internal return code */
-#define SUCCESS 0
-#define ERROR 1
-
-/* private bus modes */
-#define SDIOH_MODE_SD4 2
-#define CLIENT_INTR 0x100 /* Get rid of this! */
-
-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 */
- sdioh_cb_fn_t intr_handler; /* 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_use_dma; /* DMA on CMD53 */
- 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 sd_mode; /* SD1/SD4/SPI */
- 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 */
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmsdh_sdmmc.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/* OS-independent interrupt handler */
-extern bool check_client_intr(sdioh_info_t *sd);
-
-/* Core interrupt enable/disable of device interrupts */
-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
-
-/**************************************************************
- * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
- */
-
-/* Register mapping routines */
-extern u32 *sdioh_sdmmc_reg_map(s32 addr, int size);
-extern void sdioh_sdmmc_reg_unmap(s32 addr, int size);
-
-/* Interrupt (de)registration routines */
-extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
-extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
-
-typedef struct _BCMSDH_SDMMC_INSTANCE {
- sdioh_info_t *sd;
- struct sdio_func *func[SDIOD_MAX_IOFUNCS];
- u32 host_claimed;
-} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
-
-#endif /* __BCMSDH_SDMMC_H__ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
deleted file mode 100644
index 2792a4dfe651..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
+++ /dev/null
@@ -1,235 +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/sched.h> /* request_irq() */
-#include <linux/netdevice.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <sdio.h> /* SDIO Specs */
-#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h> /* to get msglevel bit values */
-
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-
-#include "dngl_stats.h"
-#include "dhd.h"
-
-#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
-
-#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) */
-
-#include <bcmsdh_sdmmc.h>
-
-#include <dhd_dbg.h>
-#include <wl_cfg80211.h>
-
-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
-
-int sdio_function_init(void);
-void sdio_function_cleanup(void);
-
-/* module param defaults */
-static int clockoverride;
-
-module_param(clockoverride, int, 0644);
-MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
-
-PBCMSDH_SDMMC_INSTANCE gInstance;
-
-/* Maximum number of bcmsdh_sdmmc devices supported by driver */
-#define BCMSDH_SDMMC_MAX_DEVICES 1
-
-extern int bcmsdh_probe(struct device *dev);
-extern int bcmsdh_remove(struct device *dev);
-struct device sdmmc_dev;
-
-static int bcmsdh_sdmmc_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
-{
- int ret = 0;
- static struct sdio_func sdio_func_0;
- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
- sd_trace(("sdio_bcmsdh: 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 bcmsdh_probe...\n"));
- ret = bcmsdh_probe(&sdmmc_dev);
- }
- }
-
- gInstance->func[func->num] = func;
-
- if (func->num == 2) {
- wl_cfg80211_sdio_func(func);
- sd_trace(("F2 found, calling bcmsdh_probe...\n"));
- ret = bcmsdh_probe(&sdmmc_dev);
- }
-
- return ret;
-}
-
-static void bcmsdh_sdmmc_remove(struct sdio_func *func)
-{
- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
- sd_info(("sdio_bcmsdh: 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 bcmsdh_remove...\n"));
- bcmsdh_remove(&sdmmc_dev);
- }
-}
-
-/* devices we support, null terminated */
-static const struct sdio_device_id bcmsdh_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 */ },
-};
-
-MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids);
-
-static struct sdio_driver bcmsdh_sdmmc_driver = {
- .probe = bcmsdh_sdmmc_probe,
- .remove = bcmsdh_sdmmc_remove,
- .name = "brcmfmac",
- .id_table = bcmsdh_sdmmc_ids,
-};
-
-struct sdos_info {
- sdioh_info_t *sd;
- spinlock_t lock;
-};
-
-int sdioh_sdmmc_osinit(sdioh_info_t *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 sdioh_sdmmc_osfree(sdioh_info_t *sd)
-{
- struct sdos_info *sdos;
- ASSERT(sd && sd->sdos_info);
-
- sdos = (struct sdos_info *)sd->sdos_info;
- kfree(sdos);
-}
-
-/* Interrupt enable/disable */
-SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *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;
- ASSERT(sdos);
-
-#if !defined(OOB_INTR_ONLY)
- if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
- sd_err(("%s: no handler registered, will not enable\n",
- __func__));
- return SDIOH_API_RC_FAIL;
- }
-#endif /* !defined(OOB_INTR_ONLY) */
-
- /* Ensure atomicity for enable/disable calls */
- spin_lock_irqsave(&sdos->lock, flags);
-
- sd->client_intr_enabled = enable;
- if (enable)
- sdioh_sdmmc_devintr_on(sd);
- else
- sdioh_sdmmc_devintr_off(sd);
-
- spin_unlock_irqrestore(&sdos->lock, flags);
-
- return SDIOH_API_RC_SUCCESS;
-}
-
-/*
- * module init
-*/
-int sdio_function_init(void)
-{
- int error = 0;
- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
-
- gInstance = kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL);
- if (!gInstance)
- return -ENOMEM;
-
- memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
- error = sdio_register_driver(&bcmsdh_sdmmc_driver);
-
- return error;
-}
-
-/*
- * module cleanup
-*/
-extern int bcmsdh_remove(struct device *dev);
-void sdio_function_cleanup(void)
-{
- sd_trace(("%s Enter\n", __func__));
-
- sdio_unregister_driver(&bcmsdh_sdmmc_driver);
-
- kfree(gInstance);
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/staging/brcm80211/brcmfmac/dhd.h
index a726b493ea8d..82bf04df16d0 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd.h
@@ -18,51 +18,539 @@
* Common types *
*/
-#ifndef _dhd_h_
-#define _dhd_h_
-
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/suspend.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-/* The kernel threading is sdio-specific */
-
-#include <wlioctl.h>
-
-/* Forward decls */
-struct dhd_bus;
-struct dhd_prot;
-struct dhd_info;
+#ifndef _BRCMF_H_
+#define _BRCMF_H_
+
+#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
+
+#define BRCMF_C_UP 2
+#define BRCMF_C_SET_PROMISC 10
+#define BRCMF_C_GET_RATE 12
+#define BRCMF_C_GET_INFRA 19
+#define BRCMF_C_SET_INFRA 20
+#define BRCMF_C_GET_AUTH 21
+#define BRCMF_C_SET_AUTH 22
+#define BRCMF_C_GET_BSSID 23
+#define BRCMF_C_GET_SSID 25
+#define BRCMF_C_SET_SSID 26
+#define BRCMF_C_GET_CHANNEL 29
+#define BRCMF_C_GET_SRL 31
+#define BRCMF_C_GET_LRL 33
+#define BRCMF_C_GET_RADIO 37
+#define BRCMF_C_SET_RADIO 38
+#define BRCMF_C_GET_PHYTYPE 39
+#define BRCMF_C_SET_KEY 45
+#define BRCMF_C_SET_PASSIVE_SCAN 49
+#define BRCMF_C_SCAN 50
+#define BRCMF_C_SCAN_RESULTS 51
+#define BRCMF_C_DISASSOC 52
+#define BRCMF_C_REASSOC 53
+#define BRCMF_C_SET_ROAM_TRIGGER 55
+#define BRCMF_C_SET_ROAM_DELTA 57
+#define BRCMF_C_GET_DTIMPRD 77
+#define BRCMF_C_SET_COUNTRY 84
+#define BRCMF_C_GET_PM 85
+#define BRCMF_C_SET_PM 86
+#define BRCMF_C_GET_AP 117
+#define BRCMF_C_SET_AP 118
+#define BRCMF_C_GET_RSSI 127
+#define BRCMF_C_GET_WSEC 133
+#define BRCMF_C_SET_WSEC 134
+#define BRCMF_C_GET_PHY_NOISE 135
+#define BRCMF_C_GET_BSS_INFO 136
+#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
+#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
+#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201
+#define BRCMF_C_GET_VALID_CHANNELS 217
+#define BRCMF_C_GET_KEY_PRIMARY 235
+#define BRCMF_C_SET_KEY_PRIMARY 236
+#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258
+#define BRCMF_C_GET_VAR 262
+#define BRCMF_C_SET_VAR 263
+
+/* phy types (returned by WLC_GET_PHYTPE) */
+#define WLC_PHY_TYPE_A 0
+#define WLC_PHY_TYPE_B 1
+#define WLC_PHY_TYPE_G 2
+#define WLC_PHY_TYPE_N 4
+#define WLC_PHY_TYPE_LP 5
+#define WLC_PHY_TYPE_SSN 6
+#define WLC_PHY_TYPE_HT 7
+#define WLC_PHY_TYPE_LCN 8
+#define WLC_PHY_TYPE_NULL 0xf
+
+#define 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 */
+#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
+
+/* masks for channel and ssid count */
+#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
+#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
+
+#define BRCMF_SCAN_ACTION_START 1
+#define BRCMF_SCAN_ACTION_CONTINUE 2
+#define WL_SCAN_ACTION_ABORT 3
+
+#define BRCMF_ISCAN_REQ_VERSION 1
+
+/* brcmf_iscan_results status values */
+#define BRCMF_SCAN_RESULTS_SUCCESS 0
+#define BRCMF_SCAN_RESULTS_PARTIAL 1
+#define BRCMF_SCAN_RESULTS_PENDING 2
+#define BRCMF_SCAN_RESULTS_ABORTED 3
+#define BRCMF_SCAN_RESULTS_NO_MEM 4
+
+#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 */
+
+/* For supporting multiple interfaces */
+#define BRCMF_MAX_IFS 16
+#define BRCMF_DEL_IF -0xe
+#define BRCMF_BAD_IF -0xf
+
+#define DOT11_BSSTYPE_ANY 2
+#define DOT11_MAX_DEFAULT_KEYS 4
+
+#define BRCMF_EVENT_MSG_LINK 0x01
+#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
+#define BRCMF_EVENT_MSG_GROUP 0x04
+
+struct brcmf_event_msg {
+ u16 version;
+ u16 flags;
+ u32 event_type;
+ u32 status;
+ u32 reason;
+ u32 auth_type;
+ u32 datalen;
+ u8 addr[ETH_ALEN];
+ char ifname[IFNAMSIZ];
+} __packed;
+
+struct brcm_ethhdr {
+ u16 subtype;
+ u16 length;
+ u8 version;
+ u8 oui[3];
+ u16 usr_subtype;
+} __packed;
+
+struct brcmf_event {
+ struct ethhdr eth;
+ struct brcm_ethhdr hdr;
+ struct brcmf_event_msg msg;
+} __packed;
+
+struct dngl_stats {
+ unsigned long rx_packets; /* total packets received */
+ unsigned long tx_packets; /* total packets transmitted */
+ unsigned long rx_bytes; /* total bytes received */
+ unsigned long tx_bytes; /* total bytes transmitted */
+ unsigned long rx_errors; /* bad packets received */
+ unsigned long tx_errors; /* packet transmit problems */
+ unsigned long rx_dropped; /* packets dropped by dongle */
+ unsigned long tx_dropped; /* packets dropped by dongle */
+ unsigned long multicast; /* multicast packets received */
+};
+
+#define BRCMF_E_SET_SSID 0
+#define BRCMF_E_JOIN 1
+#define BRCMF_E_START 2
+#define BRCMF_E_AUTH 3
+#define BRCMF_E_AUTH_IND 4
+#define BRCMF_E_DEAUTH 5
+#define BRCMF_E_DEAUTH_IND 6
+#define BRCMF_E_ASSOC 7
+#define BRCMF_E_ASSOC_IND 8
+#define BRCMF_E_REASSOC 9
+#define BRCMF_E_REASSOC_IND 10
+#define BRCMF_E_DISASSOC 11
+#define BRCMF_E_DISASSOC_IND 12
+#define BRCMF_E_QUIET_START 13
+#define BRCMF_E_QUIET_END 14
+#define BRCMF_E_BEACON_RX 15
+#define BRCMF_E_LINK 16
+#define BRCMF_E_MIC_ERROR 17
+#define BRCMF_E_NDIS_LINK 18
+#define BRCMF_E_ROAM 19
+#define BRCMF_E_TXFAIL 20
+#define BRCMF_E_PMKID_CACHE 21
+#define BRCMF_E_RETROGRADE_TSF 22
+#define BRCMF_E_PRUNE 23
+#define BRCMF_E_AUTOAUTH 24
+#define BRCMF_E_EAPOL_MSG 25
+#define BRCMF_E_SCAN_COMPLETE 26
+#define BRCMF_E_ADDTS_IND 27
+#define BRCMF_E_DELTS_IND 28
+#define BRCMF_E_BCNSENT_IND 29
+#define BRCMF_E_BCNRX_MSG 30
+#define BRCMF_E_BCNLOST_MSG 31
+#define BRCMF_E_ROAM_PREP 32
+#define BRCMF_E_PFN_NET_FOUND 33
+#define BRCMF_E_PFN_NET_LOST 34
+#define BRCMF_E_RESET_COMPLETE 35
+#define BRCMF_E_JOIN_START 36
+#define BRCMF_E_ROAM_START 37
+#define BRCMF_E_ASSOC_START 38
+#define BRCMF_E_IBSS_ASSOC 39
+#define BRCMF_E_RADIO 40
+#define BRCMF_E_PSM_WATCHDOG 41
+#define BRCMF_E_PROBREQ_MSG 44
+#define BRCMF_E_SCAN_CONFIRM_IND 45
+#define BRCMF_E_PSK_SUP 46
+#define BRCMF_E_COUNTRY_CODE_CHANGED 47
+#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48
+#define BRCMF_E_ICV_ERROR 49
+#define BRCMF_E_UNICAST_DECODE_ERROR 50
+#define BRCMF_E_MULTICAST_DECODE_ERROR 51
+#define BRCMF_E_TRACE 52
+#define BRCMF_E_IF 54
+#define BRCMF_E_RSSI 56
+#define BRCMF_E_PFN_SCAN_COMPLETE 57
+#define BRCMF_E_EXTLOG_MSG 58
+#define BRCMF_E_ACTION_FRAME 59
+#define BRCMF_E_ACTION_FRAME_COMPLETE 60
+#define BRCMF_E_PRE_ASSOC_IND 61
+#define BRCMF_E_PRE_REASSOC_IND 62
+#define BRCMF_E_CHANNEL_ADOPTED 63
+#define BRCMF_E_AP_STARTED 64
+#define BRCMF_E_DFS_AP_STOP 65
+#define BRCMF_E_DFS_AP_RESUME 66
+#define BRCMF_E_RESERVED1 67
+#define BRCMF_E_RESERVED2 68
+#define BRCMF_E_ESCAN_RESULT 69
+#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70
+#define BRCMF_E_DCS_REQUEST 73
+
+#define BRCMF_E_FIFO_CREDIT_MAP 74
+
+#define BRCMF_E_LAST 75
+
+#define BRCMF_E_STATUS_SUCCESS 0
+#define BRCMF_E_STATUS_FAIL 1
+#define BRCMF_E_STATUS_TIMEOUT 2
+#define BRCMF_E_STATUS_NO_NETWORKS 3
+#define BRCMF_E_STATUS_ABORT 4
+#define BRCMF_E_STATUS_NO_ACK 5
+#define BRCMF_E_STATUS_UNSOLICITED 6
+#define BRCMF_E_STATUS_ATTEMPT 7
+#define BRCMF_E_STATUS_PARTIAL 8
+#define BRCMF_E_STATUS_NEWSCAN 9
+#define BRCMF_E_STATUS_NEWASSOC 10
+#define BRCMF_E_STATUS_11HQUIET 11
+#define BRCMF_E_STATUS_SUPPRESS 12
+#define BRCMF_E_STATUS_NOCHANS 13
+#define BRCMF_E_STATUS_CS_ABORT 15
+#define BRCMF_E_STATUS_ERROR 16
+
+#define BRCMF_E_REASON_INITIAL_ASSOC 0
+#define BRCMF_E_REASON_LOW_RSSI 1
+#define BRCMF_E_REASON_DEAUTH 2
+#define BRCMF_E_REASON_DISASSOC 3
+#define BRCMF_E_REASON_BCNS_LOST 4
+#define BRCMF_E_REASON_MINTXRATE 9
+#define BRCMF_E_REASON_TXFAIL 10
+
+#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
+#define BRCMF_E_REASON_DIRECTED_ROAM 6
+#define BRCMF_E_REASON_TSPEC_REJECTED 7
+#define BRCMF_E_REASON_BETTER_AP 8
+
+#define BRCMF_E_PRUNE_ENCR_MISMATCH 1
+#define BRCMF_E_PRUNE_BCAST_BSSID 2
+#define BRCMF_E_PRUNE_MAC_DENY 3
+#define BRCMF_E_PRUNE_MAC_NA 4
+#define BRCMF_E_PRUNE_REG_PASSV 5
+#define BRCMF_E_PRUNE_SPCT_MGMT 6
+#define BRCMF_E_PRUNE_RADAR 7
+#define BRCMF_E_RSN_MISMATCH 8
+#define BRCMF_E_PRUNE_NO_COMMON_RATES 9
+#define BRCMF_E_PRUNE_BASIC_RATES 10
+#define BRCMF_E_PRUNE_CIPHER_NA 12
+#define BRCMF_E_PRUNE_KNOWN_STA 13
+#define BRCMF_E_PRUNE_WDS_PEER 15
+#define BRCMF_E_PRUNE_QBSS_LOAD 16
+#define BRCMF_E_PRUNE_HOME_AP 17
+
+#define BRCMF_E_SUP_OTHER 0
+#define BRCMF_E_SUP_DECRYPT_KEY_DATA 1
+#define BRCMF_E_SUP_BAD_UCAST_WEP128 2
+#define BRCMF_E_SUP_BAD_UCAST_WEP40 3
+#define BRCMF_E_SUP_UNSUP_KEY_LEN 4
+#define BRCMF_E_SUP_PW_KEY_CIPHER 5
+#define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6
+#define BRCMF_E_SUP_MSG3_IE_MISMATCH 7
+#define BRCMF_E_SUP_NO_INSTALL_FLAG 8
+#define BRCMF_E_SUP_MSG3_NO_GTK 9
+#define BRCMF_E_SUP_GRP_KEY_CIPHER 10
+#define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11
+#define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12
+#define BRCMF_E_SUP_SEND_FAIL 13
+#define BRCMF_E_SUP_DEAUTH 14
+
+#define BRCMF_E_IF_ADD 1
+#define BRCMF_E_IF_DEL 2
+#define BRCMF_E_IF_CHANGE 3
+
+#define BRCMF_E_IF_ROLE_STA 0
+#define BRCMF_E_IF_ROLE_AP 1
+#define BRCMF_E_IF_ROLE_WDS 2
+
+#define BRCMF_E_LINK_BCN_LOSS 1
+#define BRCMF_E_LINK_DISASSOC 2
+#define BRCMF_E_LINK_ASSOC_REC 3
+#define BRCMF_E_LINK_BSSCFG_DIS 4
/* The level of bus communication with the dongle */
-enum dhd_bus_state {
- DHD_BUS_DOWN, /* Not ready for frame transfers */
- DHD_BUS_LOAD, /* Download access only (CPU reset) */
- DHD_BUS_DATA /* Ready for frame transfers */
+enum brcmf_bus_state {
+ BRCMF_BUS_DOWN, /* Not ready for frame transfers */
+ BRCMF_BUS_LOAD, /* Download access only (CPU reset) */
+ BRCMF_BUS_DATA /* Ready for frame transfers */
+};
+
+/* Pattern matching filter. Specifies an offset within received packets to
+ * start matching, the pattern to match, the size of the pattern, and a bitmask
+ * that indicates which bits within the pattern should be matched.
+ */
+struct brcmf_pkt_filter_pattern {
+ 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.
+ */
+};
+
+/* 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 */
+ union { /* Filter definitions */
+ struct brcmf_pkt_filter_pattern pattern; /* Filter pattern */
+ } u;
+};
+
+/* IOVAR "pkt_filter_enable" parameter. */
+struct brcmf_pkt_filter_enable {
+ u32 id; /* Unique filter id */
+ u32 enable; /* Enable/disable bool */
+};
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in struct brcmf_scan_results)
+ */
+struct brcmf_bss_info {
+ u32 version; /* version field */
+ u32 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 */
+ 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 */
+ } rateset; /* supported rates */
+ chanspec_t chanspec; /* chanspec for bss */
+ u16 atim_window; /* units are Kusec */
+ u8 dtim_period; /* DTIM period */
+ s16 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_*) */
+ u8 ctl_ch; /* 802.11N BSS control channel number */
+ u32 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 */
+ /* Add new fields here */
+ /* variable length Information Elements */
+};
+
+struct brcmf_ssid {
+ u32 SSID_len;
+ unsigned char SSID[32];
+};
+
+struct brcmf_scan_params {
+ struct brcmf_ssid ssid; /* 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
+ * active scanning
+ */
+ s32 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
+ */
+ s32 channel_num; /* count of channels and ssids that follow
+ *
+ * low half is count of channels in
+ * channel_list, 0 means default (use all
+ * available channels)
+ *
+ * high half is entries in struct brcmf_ssid
+ * array that follows channel_list, aligned for
+ * s32 (4 bytes) meaning an odd channel count
+ * implies a 2-byte pad between end of
+ * channel_list and first ssid
+ *
+ * if ssid count is zero, single ssid in the
+ * fixed parameter portion is assumed, otherwise
+ * ssid in the fixed portion is ignored
+ */
+ u16 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;
+};
+
+/* 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;
+ u32 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 */
+};
+#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;
+};
+
+/* size of brcmf_scan_results not including variable length array */
+#define BRCMF_SCAN_RESULTS_FIXED_SIZE \
+ (sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info))
+
+/* incremental scan results struct */
+struct brcmf_iscan_results {
+ u32 status;
+ struct brcmf_scan_results results;
+};
+
+/* size of brcmf_iscan_results not including variable length array */
+#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
+ (BRCMF_SCAN_RESULTS_FIXED_SIZE + \
+ offsetof(struct brcmf_iscan_results, results))
+
+struct brcmf_wsec_key {
+ u32 index; /* key index */
+ u32 len; /* key length */
+ u8 data[WLAN_MAX_KEY_LEN]; /* key data */
+ u32 pad_1[18];
+ u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ u32 flags; /* misc flags */
+ u32 pad_2[2];
+ int pad_3;
+ int iv_initialized; /* has IV been initialized already? */
+ int pad_4;
+ /* Rx IV */
+ struct {
+ u32 hi; /* upper 32 bits of IV */
+ u16 lo; /* lower 16 bits of IV */
+ } rxiv;
+ u32 pad_5[2];
+ u8 ea[ETH_ALEN]; /* per station */
+};
+
+/* Used to get specific STA parameters */
+struct brcmf_scb_val {
+ u32 val;
+ u8 ea[ETH_ALEN];
+};
+
+/* channel encoding */
+struct brcmf_channel_info {
+ int hw_channel;
+ int target_channel;
+ int scan_channel;
};
+/* Linux network driver ioctl encoding */
+struct brcmf_ioctl {
+ uint cmd; /* common ioctl definition */
+ void *buf; /* pointer to user buffer */
+ uint len; /* length of user buffer */
+ u8 set; /* get or set request (optional) */
+ uint used; /* bytes read or written (optional) */
+ uint needed; /* bytes needed (optional) */
+};
+
+/* Forward decls for struct brcmf_pub (see below) */
+struct brcmf_bus; /* device bus info */
+struct brcmf_proto; /* device communication protocol info */
+struct brcmf_info; /* device driver info */
+
/* Common structure for module and instance linkage */
-typedef struct dhd_pub {
+struct brcmf_pub {
/* Linkage ponters */
- struct dhd_bus *bus; /* Bus module handle */
- struct dhd_prot *prot; /* Protocol module handle */
- struct dhd_info *info; /* Info module handle */
+ struct brcmf_bus *bus;
+ struct brcmf_proto *prot;
+ struct brcmf_info *info;
- /* Internal dhd items */
+ /* 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 dhd_bus_state busstate;
- uint hdrlen; /* Total DHD header length (proto + bus) */
+ enum brcmf_bus_state busstate;
+ uint hdrlen; /* Total BRCMF header length (proto + bus) */
uint maxctl; /* Max size rxctl request from proto to bus */
uint rxsz; /* Rx buffer size bus module should use */
u8 wme_dp; /* wme discard priority */
@@ -71,7 +559,7 @@ typedef struct dhd_pub {
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 */
- dngl_stats_t dstats; /* Stats for dongle-based data */
+ struct dngl_stats dstats; /* Stats for dongle-based data */
/* Additional stats for the bus level */
unsigned long tx_packets; /* Data packets sent to dongle */
@@ -88,7 +576,7 @@ typedef struct dhd_pub {
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 dhd dpc scheduled by
+ 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
@@ -108,40 +596,51 @@ typedef struct dhd_pub {
int suspend_disable_flag; /* "1" to disable all extra powersaving
during suspend */
int in_suspend; /* flag set to 1 when early suspend called */
-#ifdef PNO_SUPPORT
- int pno_enable; /* pno status : "1" is pno enable */
-#endif /* PNO_SUPPORT */
int dtim_skip; /* dtim skip , default 0 means wake each dtim */
/* Pkt filter defination */
char *pktfilter[100];
int pktfilter_count;
- u8 country_code[WLC_CNTRY_BUF_SZ];
- char eventmask[WL_EVENTING_MASK_LEN];
+ u8 country_code[BRCM_CNTRY_BUF_SZ];
+ char eventmask[BRCMF_EVENTING_MASK_LEN];
+
+};
+
+struct brcmf_if_event {
+ u8 ifidx;
+ u8 action;
+ u8 flags;
+ 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) */
+};
-} dhd_pub_t;
+struct bcmevent_name {
+ uint event;
+ const char *name;
+};
#if defined(CONFIG_PM_SLEEP)
-extern atomic_t dhd_mmc_suspend;
-#define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define _DHD_PM_RESUME_WAIT(a, b) do { \
+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(&dhd_mmc_suspend) && retry++ != b) { \
+ while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \
wait_event_timeout(a, false, HZ/100); \
} \
} while (0)
-#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30)
-#define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
-#define DHD_PM_RESUME_RETURN_ERROR(a) \
- do { if (atomic_read(&dhd_mmc_suspend)) return a; } while (0)
-#define DHD_PM_RESUME_RETURN do { \
- if (atomic_read(&dhd_mmc_suspend)) \
- return; \
- } 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 DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define SPINWAIT_SLEEP(a, exp, us) do { \
+#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); \
@@ -151,14 +650,12 @@ extern atomic_t dhd_mmc_suspend;
#else
-#define DHD_PM_RESUME_WAIT_INIT(a)
-#define DHD_PM_RESUME_WAIT(a)
-#define DHD_PM_RESUME_WAIT_FOREVER(a)
-#define DHD_PM_RESUME_RETURN_ERROR(a)
-#define DHD_PM_RESUME_RETURN
+#define BRCMF_PM_RESUME_WAIT_INIT(a)
+#define BRCMF_PM_RESUME_WAIT(a)
+#define BRCMF_PM_RESUME_RETURN_ERROR(a)
-#define DHD_SPINWAIT_SLEEP_INIT(a)
-#define SPINWAIT_SLEEP(a, exp, us) do { \
+#define BRCMF_SPINWAIT_SLEEP_INIT(a)
+#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
uint countdown = (us) + 9; \
while ((exp) && (countdown >= 10)) { \
udelay(10); \
@@ -167,29 +664,82 @@ extern atomic_t dhd_mmc_suspend;
} while (0)
#endif /* defined(CONFIG_PM_SLEEP) */
-#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
-static inline void MUTEX_LOCK_INIT(dhd_pub_t *dhdp)
+/*
+ * 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(dhd_pub_t *dhdp)
+static inline void MUTEX_LOCK(struct brcmf_pub *drvr)
{
}
-static inline void MUTEX_UNLOCK(dhd_pub_t *dhdp)
+static inline void MUTEX_UNLOCK(struct brcmf_pub *drvr)
{
}
-static inline void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t *dhdp)
+static inline void MUTEX_LOCK_SOFTAP_SET_INIT(struct brcmf_pub *drvr)
{
}
-static inline void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t *dhdp)
+static inline void MUTEX_LOCK_SOFTAP_SET(struct brcmf_pub *drvr)
{
}
-static inline void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t *dhdp)
+static inline void MUTEX_UNLOCK_SOFTAP_SET(struct brcmf_pub *drvr)
{
}
@@ -205,210 +755,150 @@ static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
{
}
-typedef struct dhd_if_event {
- u8 ifidx;
- u8 action;
- u8 flags;
- u8 bssidx;
-} dhd_if_event_t;
-
-/*
- * Exported from dhd OS modules (dhd_linux/dhd_ndis)
- */
-
/* Indication from bus module regarding presence/insertion of dongle.
- * Return dhd_pub_t pointer, used as handle to OS module in later calls.
+ * Return struct brcmf_pub pointer, used as handle to OS module in later calls.
* Returned structure should have bus and prot pointers filled in.
* bus_hdrlen specifies required headroom for bus module header.
*/
-extern dhd_pub_t *dhd_attach(struct dhd_bus *bus,
- uint bus_hdrlen);
-extern int dhd_net_attach(dhd_pub_t *dhdp, int idx);
+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);
/* Indication from bus module regarding removal/absence of dongle */
-extern void dhd_detach(dhd_pub_t *dhdp);
+extern void brcmf_detach(struct brcmf_pub *drvr);
/* Indication from bus module to change flow-control state */
-extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on);
+extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on);
-extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q,
+extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
struct sk_buff *pkt, int prec);
/* Receive frame for delivery to OS. Callee disposes of rxp. */
-extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx,
+extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
struct sk_buff *rxp, int numpkt);
/* Return pointer to interface name */
-extern char *dhd_ifname(dhd_pub_t *dhdp, int idx);
-
-/* Request scheduling of the bus dpc */
-extern void dhd_sched_dpc(dhd_pub_t *dhdp);
+extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
/* Notify tx completion */
-extern void dhd_txcomplete(dhd_pub_t *dhdp, struct sk_buff *txp, bool success);
+extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp,
+ bool success);
/* Query ioctl */
-extern int dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
- uint len);
+extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx,
+ uint cmd, void *buf, uint len);
/* OS independent layer functions */
-extern int dhd_os_proto_block(dhd_pub_t *pub);
-extern int dhd_os_proto_unblock(dhd_pub_t *pub);
-extern int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition,
+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 dhd_os_ioctl_resp_wake(dhd_pub_t *pub);
-extern unsigned int dhd_os_get_ioctl_resp_timeout(void);
-extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
-extern void *dhd_os_open_image(char *filename);
-extern int dhd_os_get_image_block(char *buf, int len, void *image);
-extern void dhd_os_close_image(void *image);
-extern void dhd_os_wd_timer(void *bus, uint wdtick);
-extern void dhd_os_sdlock(dhd_pub_t *pub);
-extern void dhd_os_sdunlock(dhd_pub_t *pub);
-extern void dhd_os_sdlock_txq(dhd_pub_t *pub);
-extern void dhd_os_sdunlock_txq(dhd_pub_t *pub);
-extern void dhd_os_sdlock_rxq(dhd_pub_t *pub);
-extern void dhd_os_sdunlock_rxq(dhd_pub_t *pub);
-extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t *pub);
-extern void dhd_customer_gpio_wlan_ctrl(int onoff);
-extern int dhd_custom_get_mac_address(unsigned char *buf);
-extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t *pub);
-extern void dhd_os_sdlock_eventq(dhd_pub_t *pub);
-extern void dhd_os_sdunlock_eventq(dhd_pub_t *pub);
-#ifdef DHD_DEBUG
-extern int write_to_file(dhd_pub_t *dhd, u8 *buf, int size);
-#endif /* DHD_DEBUG */
-#if defined(OOB_INTR_ONLY)
-extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
-#endif /* defined(OOB_INTR_ONLY) */
-extern void dhd_os_sdtxlock(dhd_pub_t *pub);
-extern void dhd_os_sdtxunlock(dhd_pub_t *pub);
-
-int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
-
-typedef struct {
- u32 limit; /* Expiration time (usec) */
- u32 increment; /* Current expiration increment (usec) */
- u32 elapsed; /* Current elapsed time (usec) */
- u32 tick; /* O/S tick time (usec) */
-} dhd_timeout_t;
+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);
+#endif /* BCMDBG */
-extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
-extern int dhd_timeout_expired(dhd_timeout_t *tmo);
+extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec);
+extern int brcmf_timeout_expired(struct brcmf_timeout *tmo);
-extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
-extern u8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx);
-extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata,
- wl_event_msg_t *, void **data_ptr);
+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 *,
+ void **data_ptr);
-extern void dhd_common_init(void);
+extern void brcmf_c_init(void);
-extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle,
+extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle,
char *name, u8 *mac_addr, u32 flags, u8 bssidx);
-extern void dhd_del_if(struct dhd_info *dhd, int ifidx);
-
-extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char *name);
-extern void dhd_vif_del(struct dhd_info *dhd, int ifidx);
-
-extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx);
-extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, unsigned char * cp,
- int len);
+extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
/* Send packet to dongle via data channel */
-extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pkt);
-
-/* Send event to host */
-extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event,
- void *data);
-extern int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag);
-extern uint dhd_bus_status(dhd_pub_t *dhdp);
-extern int dhd_bus_start(dhd_pub_t *dhdp);
-
-enum cust_gpio_modes {
- WLAN_RESET_ON,
- WLAN_RESET_OFF,
- WLAN_POWER_ON,
- WLAN_POWER_OFF
+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 */
};
-/*
- * Insmod parameters for debug/test
- */
-
-/* Watchdog timer interval */
-extern uint dhd_watchdog_ms;
-
-#if defined(DHD_DEBUG)
-/* Console output poll interval */
-extern uint dhd_console_ms;
-#endif /* defined(DHD_DEBUG) */
-
-/* Use interrupts */
-extern uint dhd_intr;
-
-/* Use polling */
-extern uint dhd_poll;
-
-/* ARP offload agent mode */
-extern uint dhd_arp_mode;
-
-/* ARP offload enable */
-extern uint dhd_arp_enable;
-
-/* Pkt filte enable control */
-extern uint dhd_pkt_filter_enable;
-
-/* Pkt filter init setup */
-extern uint dhd_pkt_filter_init;
-
-/* Pkt filter mode control */
-extern uint dhd_master_mode;
-/* Roaming mode control */
-extern uint dhd_roam;
-
-/* Roaming mode control */
-extern uint dhd_radio_up;
-
-/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
-extern int dhd_idletime;
-#define DHD_IDLETIME_TICKS 1
-
-/* SDIO Drive Strength */
-extern uint dhd_sdiod_drive_strength;
-
-/* Override to force tx queueing all the time */
-extern uint dhd_force_tx_queueing;
+/* 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
+
+/* message levels */
+#define BRCMF_ERROR_VAL 0x0001
+#define BRCMF_TRACE_VAL 0x0002
+#define BRCMF_INFO_VAL 0x0004
+#define BRCMF_DATA_VAL 0x0008
+#define BRCMF_CTL_VAL 0x0010
+#define BRCMF_TIMER_VAL 0x0020
+#define BRCMF_HDRS_VAL 0x0040
+#define BRCMF_BYTES_VAL 0x0080
+#define BRCMF_INTR_VAL 0x0100
+#define BRCMF_GLOM_VAL 0x0400
+#define BRCMF_EVENT_VAL 0x0800
+#define BRCMF_BTA_VAL 0x1000
+#define BRCMF_ISCAN_VAL 0x2000
#ifdef SDTEST
-/* Echo packet generator (SDIO), pkts/s */
-extern uint dhd_pktgen;
-
-/* Echo packet len (0 => sawtooth, max 1800) */
-extern uint dhd_pktgen_len;
-#define MAX_PKTGEN_LEN 1800
-#endif
-
-/* optionally set by a module_param_string() */
-#define MOD_PARAM_PATHLEN 2048
-extern char fw_path[MOD_PARAM_PATHLEN];
-extern char nv_path[MOD_PARAM_PATHLEN];
+/* 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 */
+};
-/* For supporting multiple interfaces */
-#define DHD_MAX_IFS 16
-#define DHD_DEL_IF -0xe
-#define DHD_BAD_IF -0xf
+/* Version in case structure changes */
+#define BRCMF_PKTGEN_VERSION 2
-extern void dhd_wait_for_event(dhd_pub_t *dhd, bool * lockvar);
-extern void dhd_wait_event_wakeup(dhd_pub_t *dhd);
+/* 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 */
-extern u32 g_assert_type;
+/* Enter idle immediately (no timeout) */
+#define BRCMF_IDLE_IMMEDIATE (-1)
-#ifdef BCMDBG
-#define ASSERT(exp) \
- do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
-extern void osl_assert(char *exp, char *file, int line);
-#else
-#define ASSERT(exp) do {} while (0)
-#endif /* defined(BCMDBG) */
+/* 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 */
-#endif /* _dhd_h_ */
+#endif /* _BRCMF_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
index 065f1aeb6ca9..653cf0daa0eb 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
@@ -14,69 +14,65 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _dhd_bus_h_
-#define _dhd_bus_h_
+#ifndef _BRCMF_BUS_H_
+#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
/*
- * Exported from dhd bus module (dhd_usb, dhd_sdio)
+ * Exported from brcmf bus module (brcmf_usb, brcmf_sdio)
*/
-/* Indicate (dis)interest in finding dongles. */
-extern int dhd_bus_register(void);
-extern void dhd_bus_unregister(void);
+/* dongle ram module parameter */
+extern int brcmf_dongle_memsize;
+
+/* Tx/Rx bounds module parameters */
+extern uint brcmf_txbound;
+extern uint brcmf_rxbound;
-/* Download firmware image and nvram image */
-extern bool dhd_bus_download_firmware(struct dhd_bus *bus,
- char *fw_path, char *nv_path);
+/* 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);
/* Stop bus module: clear pending frames, disable data flow */
-extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
+extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex);
/* Initialize bus module: prepare for communication w/dongle */
-extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex);
+extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex);
/* Send a data frame to the dongle. Callee disposes of txp. */
-extern int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *txp);
+extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp);
/* Send/receive a control message to/from the dongle.
* Expects caller to enforce a single outstanding transaction.
*/
-extern int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
-extern int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
+extern int
+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
-/* Watchdog timer function */
-extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
-
-#ifdef DHD_DEBUG
-/* Device console input function */
-extern int dhd_bus_console_in(dhd_pub_t *dhd, unsigned char *msg, uint msglen);
-#endif /* DHD_DEBUG */
-
-/* Deferred processing for the bus, return true requests reschedule */
-extern bool dhd_bus_dpc(struct dhd_bus *bus);
-extern void dhd_bus_isr(bool *InterruptRecognized,
- bool *QueueMiniportHandleInterrupt, void *arg);
+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 dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+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 dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+extern void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr,
+ struct brcmu_strbuf *strbuf);
/* Clear any bus counters */
-extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
-
-/* return the dongle chipid */
-extern uint dhd_bus_chip(struct dhd_bus *bus);
-
-/* Set user-specified nvram parameters. */
-extern void dhd_bus_set_nvram_params(struct dhd_bus *bus,
- const char *nvram_params);
+extern void brcmf_bus_clearcounts(struct brcmf_pub *drvr);
-extern void *dhd_bus_pub(struct dhd_bus *bus);
-extern void *dhd_bus_txq(struct dhd_bus *bus);
-extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
+extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick);
-#endif /* _dhd_bus_h_ */
+#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
index ba5a5cb7eede..345acabe935e 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
@@ -16,33 +16,71 @@
#include <linux/types.h>
#include <linux/netdevice.h>
-#include <bcmdefs.h>
-
-#include <bcmutils.h>
-#include <bcmcdc.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_proto.h>
-#include <dhd_bus.h>
-#include <dhd_dbg.h>
-#ifdef CUSTOMER_HW2
-int wifi_get_mac_addr(unsigned char *buf);
-#endif
-
-extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
-
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN 32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
+#include <linux/sched.h>
+#include <defs.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "dhd_proto.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+
+struct brcmf_proto_cdc_ioctl {
+ u32 cmd; /* ioctl command value */
+ u32 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 */
+};
+
+/* 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)))
+
+/*
+ * BDC header - Broadcom specific extension of CDC.
+ * Used on data packets to convey priority across USB.
+ */
+#define BDC_HEADER_LEN 4
+#define BDC_PROTO_VER 1 /* Protocol version */
+#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
+#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
+#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */
+#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */
+#define BDC_PRIORITY_MASK 0x7
+#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */
+#define BDC_FLAG2_IF_SHIFT 0
+
+#define BDC_GET_IF_IDX(hdr) \
+ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+#define BDC_SET_IF_IDX(hdr, idx) \
+ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
+ ((idx) << BDC_FLAG2_IF_SHIFT)))
+
+struct brcmf_proto_bdc_header {
+ u8 flags;
+ u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */
+ u8 flags2;
+ u8 rssi;
+};
+
#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
-#define BUS_HEADER_LEN (16+DHD_SDALIGN) /* Must be atleast SDPCM_RESERVE
- * defined in dhd_sdio.c
+#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
* for alignment padding.
@@ -51,21 +89,22 @@ extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
* round off at the end of buffer
*/
-typedef struct dhd_prot {
+struct brcmf_proto {
u16 reqid;
u8 pending;
u32 lastcmd;
u8 bus_header[BUS_HEADER_LEN];
- cdc_ioctl_t msg;
- unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
-} dhd_prot_t;
+ struct brcmf_proto_cdc_ioctl msg;
+ unsigned char buf[BRCMF_C_IOCTL_MAXLEN + ROUND_UP_MARGIN];
+};
-static int dhdcdc_msg(dhd_pub_t *dhd)
+static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
{
- dhd_prot_t *prot = dhd->prot;
- int len = le32_to_cpu(prot->msg.len) + sizeof(cdc_ioctl_t);
+ struct brcmf_proto *prot = drvr->prot;
+ int len = le32_to_cpu(prot->msg.len) +
+ sizeof(struct brcmf_proto_cdc_ioctl);
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* 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
@@ -75,20 +114,21 @@ static int dhdcdc_msg(dhd_pub_t *dhd)
len = CDC_MAX_MSG_SIZE;
/* Send request */
- return dhd_bus_txctl(dhd->bus, (unsigned char *)&prot->msg, len);
+ return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg,
+ len);
}
-static int dhdcdc_cmplt(dhd_pub_t *dhd, u32 id, u32 len)
+static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
{
int ret;
- dhd_prot_t *prot = dhd->prot;
+ struct brcmf_proto *prot = drvr->prot;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
do {
- ret =
- dhd_bus_rxctl(dhd->bus, (unsigned char *)&prot->msg,
- len + sizeof(cdc_ioctl_t));
+ ret = brcmf_sdbrcm_bus_rxctl(drvr->bus,
+ (unsigned char *)&prot->msg,
+ len + sizeof(struct brcmf_proto_cdc_ioctl));
if (ret < 0)
break;
} while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
@@ -97,30 +137,31 @@ static int dhdcdc_cmplt(dhd_pub_t *dhd, u32 id, u32 len)
}
int
-dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
+brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len)
{
- dhd_prot_t *prot = dhd->prot;
- cdc_ioctl_t *msg = &prot->msg;
+ struct brcmf_proto *prot = drvr->prot;
+ struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
void *info;
int ret = 0, retries = 0;
u32 id, flags = 0;
- DHD_TRACE(("%s: Enter\n", __func__));
- DHD_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
+ BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
/* Respond "bcmerror" and "bcmerrorstr" with local cache */
- if (cmd == WLC_GET_VAR && buf) {
+ if (cmd == BRCMF_C_GET_VAR && buf) {
if (!strcmp((char *)buf, "bcmerrorstr")) {
strncpy((char *)buf, "bcm_error",
BCME_STRLEN);
goto done;
} else if (!strcmp((char *)buf, "bcmerror")) {
- *(int *)buf = dhd->dongle_error;
+ *(int *)buf = drvr->dongle_error;
goto done;
}
}
- memset(msg, 0, sizeof(cdc_ioctl_t));
+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
@@ -131,16 +172,16 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
if (buf)
memcpy(prot->buf, buf, len);
- ret = dhdcdc_msg(dhd);
+ ret = brcmf_proto_cdc_msg(drvr);
if (ret < 0) {
- DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status "
- "%d\n", ret));
+ BRCMF_ERROR(("brcmf_proto_cdc_query_ioctl: brcmf_proto_cdc_msg "
+ "failed w/status %d\n", ret));
goto done;
}
retry:
/* wait for interrupt and get first fragment */
- ret = dhdcdc_cmplt(dhd, prot->reqid, len);
+ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
if (ret < 0)
goto done;
@@ -150,8 +191,9 @@ retry:
if ((id < prot->reqid) && (++retries < RETRIES))
goto retry;
if (id != prot->reqid) {
- DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
- dhd_ifname(dhd, ifidx), __func__, id, prot->reqid));
+ BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(drvr, ifidx), __func__, id,
+ prot->reqid));
ret = -EINVAL;
goto done;
}
@@ -170,24 +212,25 @@ retry:
if (flags & CDCF_IOC_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
- dhd->dongle_error = ret;
+ drvr->dongle_error = ret;
}
done:
return ret;
}
-int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
+int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len)
{
- dhd_prot_t *prot = dhd->prot;
- cdc_ioctl_t *msg = &prot->msg;
+ struct brcmf_proto *prot = drvr->prot;
+ struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
int ret = 0;
u32 flags, id;
- DHD_TRACE(("%s: Enter\n", __func__));
- DHD_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
+ BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
- memset(msg, 0, sizeof(cdc_ioctl_t));
+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
@@ -198,11 +241,11 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
if (buf)
memcpy(prot->buf, buf, len);
- ret = dhdcdc_msg(dhd);
+ ret = brcmf_proto_cdc_msg(drvr);
if (ret < 0)
goto done;
- ret = dhdcdc_cmplt(dhd, prot->reqid, len);
+ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
if (ret < 0)
goto done;
@@ -210,8 +253,9 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
if (id != prot->reqid) {
- DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
- dhd_ifname(dhd, ifidx), __func__, id, prot->reqid));
+ BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(drvr, ifidx), __func__, id,
+ prot->reqid));
ret = -EINVAL;
goto done;
}
@@ -220,41 +264,40 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
if (flags & CDCF_IOC_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
- dhd->dongle_error = ret;
+ drvr->dongle_error = ret;
}
done:
return ret;
}
-extern int dhd_bus_interface(struct dhd_bus *bus, uint arg, void *arg2);
int
-dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
+brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, struct brcmf_ioctl *ioc,
+ void *buf, int len)
{
- dhd_prot_t *prot = dhd->prot;
+ struct brcmf_proto *prot = drvr->prot;
int ret = -1;
- if (dhd->busstate == DHD_BUS_DOWN) {
- DHD_ERROR(("%s : bus is down. we have nothing to do\n",
- __func__));
+ if (drvr->busstate == BRCMF_BUS_DOWN) {
+ BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
+ __func__));
return ret;
}
- dhd_os_proto_block(dhd);
-
- DHD_TRACE(("%s: Enter\n", __func__));
+ brcmf_os_proto_block(drvr);
- ASSERT(len <= WLC_IOCTL_MAXLEN);
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (len > WLC_IOCTL_MAXLEN)
+ if (len > BRCMF_C_IOCTL_MAXLEN)
goto done;
if (prot->pending == true) {
- DHD_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 == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR))
- DHD_TRACE(("iovar cmd=%s\n", (char *)buf));
+ 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));
goto done;
}
@@ -262,36 +305,39 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
prot->pending = true;
prot->lastcmd = ioc->cmd;
if (ioc->set)
- ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len);
+ ret = brcmf_proto_cdc_set_ioctl(drvr, ifidx, ioc->cmd,
+ buf, len);
else {
- ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len);
+ ret = brcmf_proto_cdc_query_ioctl(drvr, ifidx, ioc->cmd,
+ buf, len);
if (ret > 0)
- ioc->used = ret - sizeof(cdc_ioctl_t);
+ ioc->used = ret - sizeof(struct brcmf_proto_cdc_ioctl);
}
/* Too many programs assume ioctl() returns 0 on success */
if (ret >= 0)
ret = 0;
else {
- cdc_ioctl_t *msg = &prot->msg;
+ struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
/* len == needed when set/query fails from dongle */
ioc->needed = le32_to_cpu(msg->len);
}
/* Intercept the wme_dp ioctl here */
- if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) {
+ if (!ret && ioc->cmd == BRCMF_C_SET_VAR &&
+ !strcmp(buf, "wme_dp")) {
int slen, val = 0;
slen = strlen("wme_dp") + 1;
if (len >= (int)(slen + sizeof(int)))
memcpy(&val, (char *)buf + slen, sizeof(int));
- dhd->wme_dp = (u8) le32_to_cpu(val);
+ drvr->wme_dp = (u8) le32_to_cpu(val);
}
prot->pending = false;
done:
- dhd_os_proto_unblock(dhd);
+ brcmf_os_proto_unblock(drvr);
return ret;
}
@@ -302,35 +348,23 @@ done:
(((struct sk_buff *)(skb))->ip_summed = \
((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
-/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because
- skb->ip_summed is overloaded */
-
-int
-dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- return -ENOTSUPP;
-}
-
-void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+void brcmf_proto_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
{
- bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
+ brcmu_bprintf(strbuf, "Protocol CDC: reqid %d\n", drvr->prot->reqid);
}
-void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, struct sk_buff *pktbuf)
+void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
+ struct sk_buff *pktbuf)
{
-#ifdef BDC
- struct bdc_header *h;
-#endif /* BDC */
+ struct brcmf_proto_bdc_header *h;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
-#ifdef BDC
/* Push BDC header used to convey priority for buses that don't */
skb_push(pktbuf, BDC_HEADER_LEN);
- h = (struct bdc_header *)(pktbuf->data);
+ h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
if (PKTSUMNEEDED(pktbuf))
@@ -339,79 +373,74 @@ void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, struct sk_buff *pktbuf)
h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
h->flags2 = 0;
h->rssi = 0;
-#endif /* BDC */
BDC_SET_IF_IDX(h, ifidx);
}
-int dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, struct sk_buff *pktbuf)
+int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
+ struct sk_buff *pktbuf)
{
-#ifdef BDC
- struct bdc_header *h;
-#endif
+ struct brcmf_proto_bdc_header *h;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
-#ifdef BDC
/* Pop BDC header used to convey priority for buses that don't */
if (pktbuf->len < BDC_HEADER_LEN) {
- DHD_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
- pktbuf->len, BDC_HEADER_LEN));
+ BRCMF_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
+ pktbuf->len, BDC_HEADER_LEN));
return -EBADE;
}
- h = (struct bdc_header *)(pktbuf->data);
+ h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
*ifidx = BDC_GET_IF_IDX(h);
- if (*ifidx >= DHD_MAX_IFS) {
- DHD_ERROR(("%s: rx data ifnum out of range (%d)\n",
- __func__, *ifidx));
+ if (*ifidx >= BRCMF_MAX_IFS) {
+ BRCMF_ERROR(("%s: rx data ifnum out of range (%d)\n",
+ __func__, *ifidx));
return -EBADE;
}
if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
BDC_PROTO_VER) {
- DHD_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
- dhd_ifname(dhd, *ifidx), h->flags));
+ BRCMF_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) {
- DHD_INFO(("%s: BDC packet received with good rx-csum, "
- "flags 0x%x\n",
- dhd_ifname(dhd, *ifidx), h->flags));
+ BRCMF_INFO(("%s: BDC packet received with good rx-csum, "
+ "flags 0x%x\n",
+ brcmf_ifname(drvr, *ifidx), h->flags));
PKTSETSUMGOOD(pktbuf, true);
}
pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
skb_pull(pktbuf, BDC_HEADER_LEN);
-#endif /* BDC */
return 0;
}
-int dhd_prot_attach(dhd_pub_t *dhd)
+int brcmf_proto_attach(struct brcmf_pub *drvr)
{
- dhd_prot_t *cdc;
+ struct brcmf_proto *cdc;
- cdc = kzalloc(sizeof(dhd_prot_t), GFP_ATOMIC);
+ cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC);
if (!cdc) {
- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+ BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
goto fail;
}
/* ensure that the msg buf directly follows the cdc msg struct */
if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
- DHD_ERROR(("dhd_prot_t is not correctly defined\n"));
+ BRCMF_ERROR(("struct brcmf_proto is not correctly defined\n"));
goto fail;
}
- dhd->prot = cdc;
-#ifdef BDC
- dhd->hdrlen += BDC_HEADER_LEN;
-#endif
- dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN;
+ drvr->prot = cdc;
+ drvr->hdrlen += BDC_HEADER_LEN;
+ drvr->maxctl = BRCMF_C_IOCTL_MAXLEN +
+ sizeof(struct brcmf_proto_cdc_ioctl) + ROUND_UP_MARGIN;
return 0;
fail:
@@ -420,55 +449,54 @@ fail:
}
/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */
-void dhd_prot_detach(dhd_pub_t *dhd)
+void brcmf_proto_detach(struct brcmf_pub *drvr)
{
- kfree(dhd->prot);
- dhd->prot = NULL;
+ kfree(drvr->prot);
+ drvr->prot = NULL;
}
-void dhd_prot_dstats(dhd_pub_t *dhd)
+void brcmf_proto_dstats(struct brcmf_pub *drvr)
{
/* No stats from dongle added yet, copy bus stats */
- dhd->dstats.tx_packets = dhd->tx_packets;
- dhd->dstats.tx_errors = dhd->tx_errors;
- dhd->dstats.rx_packets = dhd->rx_packets;
- dhd->dstats.rx_errors = dhd->rx_errors;
- dhd->dstats.rx_dropped = dhd->rx_dropped;
- dhd->dstats.multicast = dhd->rx_multicast;
+ drvr->dstats.tx_packets = drvr->tx_packets;
+ drvr->dstats.tx_errors = drvr->tx_errors;
+ drvr->dstats.rx_packets = drvr->rx_packets;
+ drvr->dstats.rx_errors = drvr->rx_errors;
+ drvr->dstats.rx_dropped = drvr->rx_dropped;
+ drvr->dstats.multicast = drvr->rx_multicast;
return;
}
-int dhd_prot_init(dhd_pub_t *dhd)
+int brcmf_proto_init(struct brcmf_pub *drvr)
{
int ret = 0;
char buf[128];
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- dhd_os_proto_block(dhd);
+ brcmf_os_proto_block(drvr);
/* Get the device MAC address */
strcpy(buf, "cur_etheraddr");
- ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+ ret = brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR,
+ buf, sizeof(buf));
if (ret < 0) {
- dhd_os_proto_unblock(dhd);
+ brcmf_os_proto_unblock(drvr);
return ret;
}
- memcpy(dhd->mac, buf, ETH_ALEN);
+ memcpy(drvr->mac, buf, ETH_ALEN);
- dhd_os_proto_unblock(dhd);
+ brcmf_os_proto_unblock(drvr);
-#ifdef EMBEDDED_PLATFORM
- ret = dhd_preinit_ioctls(dhd);
-#endif /* EMBEDDED_PLATFORM */
+ ret = brcmf_c_preinit_ioctls(drvr);
/* Always assumes wl for now */
- dhd->iswl = true;
+ drvr->iswl = true;
return ret;
}
-void dhd_prot_stop(dhd_pub_t *dhd)
+void brcmf_proto_stop(struct brcmf_pub *drvr)
{
/* Nothing to do for CDC */
}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
index 0bfb93c0075a..fdec4683c422 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
@@ -15,64 +15,41 @@
*/
#include <linux/kernel.h>
#include <linux/string.h>
-#include <bcmdefs.h>
+#include <linux/sched.h>
#include <linux/netdevice.h>
-#include <bcmutils.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <msgtrace.h>
-#include <wlioctl.h>
-
-int dhd_msg_level;
-char fw_path[MOD_PARAM_PATHLEN];
-char nv_path[MOD_PARAM_PATHLEN];
-
-/* Last connection success/failure status */
-u32 dhd_conn_event;
-u32 dhd_conn_status;
-u32 dhd_conn_reason;
-
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
- uint len);
-extern void dhd_ind_scan_confirm(void *h, bool status);
-extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen);
-void dhd_iscan_lock(void);
-void dhd_iscan_unlock(void);
-
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN 32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
-
-#define EPI_VERSION_STR "4.218.248.5"
-#ifdef DHD_DEBUG
-const char dhd_version[] =
-"Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " __DATE__
+#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 dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
+const char brcmf_version[] = "Dongle Host Driver, version " BRCMF_VERSION_STR;
#endif
-void dhd_set_timer(void *bus, uint wdtick);
-
/* IOVar table */
enum {
IOV_VERSION = 1,
IOV_MSGLEVEL,
IOV_BCMERRORSTR,
IOV_BCMERROR,
- IOV_WDTICK,
IOV_DUMP,
-#ifdef DHD_DEBUG
- IOV_CONS,
- IOV_DCONSOLE_POLL,
-#endif
IOV_CLEARCOUNTS,
IOV_LOGDUMP,
IOV_LOGCAL,
@@ -82,27 +59,19 @@ enum {
IOV_LAST
};
-const bcm_iovar_t dhd_iovars[] = {
- {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version)}
+const struct brcmu_iovar brcmf_iovars[] = {
+ {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(brcmf_version)}
,
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
{"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}
,
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
{"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN}
,
{"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0}
,
- {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0}
- ,
- {"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}
- ,
-#ifdef DHD_DEBUG
- {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0}
+ {"dump", IOV_DUMP, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
,
- {"cons", IOV_CONS, 0, IOVT_BUFFER, 0}
- ,
-#endif
{"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0}
,
{"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0}
@@ -112,7 +81,23 @@ const bcm_iovar_t dhd_iovars[] = {
{NULL, 0, 0, 0, 0}
};
-void dhd_common_init(void)
+/* 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.
@@ -122,87 +107,77 @@ void dhd_common_init(void)
* first time that the driver is initialized vs subsequent
* initializations.
*/
- dhd_msg_level = DHD_ERROR_VAL;
-#ifdef CONFIG_BCM4329_FW_PATH
- strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN - 1);
-#else
- fw_path[0] = '\0';
-#endif
-#ifdef CONFIG_BCM4329_NVRAM_PATH
- strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN - 1);
-#else
- nv_path[0] = '\0';
-#endif
+ brcmf_msg_level = BRCMF_ERROR_VAL;
}
-static int dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen)
+static int brcmf_c_dump(struct brcmf_pub *drvr, char *buf, int buflen)
{
- struct bcmstrbuf b;
- struct bcmstrbuf *strbuf = &b;
-
- bcm_binit(strbuf, buf, buflen);
-
- /* Base DHD info */
- bcm_bprintf(strbuf, "%s\n", dhd_version);
- bcm_bprintf(strbuf, "\n");
- bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
- dhdp->up, dhdp->txoff, dhdp->busstate);
- bcm_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
- dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz);
- bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n",
- dhdp->iswl, dhdp->drv_version, &dhdp->mac);
- bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", dhdp->bcmerror,
- dhdp->tickcnt);
-
- bcm_bprintf(strbuf, "dongle stats:\n");
- bcm_bprintf(strbuf,
+ 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",
- dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes,
- dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped);
- bcm_bprintf(strbuf,
+ 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",
- dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes,
- dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped);
- bcm_bprintf(strbuf, "multicast %ld\n", dhdp->dstats.multicast);
-
- bcm_bprintf(strbuf, "bus stats:\n");
- bcm_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
- dhdp->tx_packets, dhdp->tx_multicast, dhdp->tx_errors);
- bcm_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
- dhdp->tx_ctlpkts, dhdp->tx_ctlerrs);
- bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n",
- dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors);
- bcm_bprintf(strbuf,
+ 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",
- dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped,
- dhdp->rx_flushed);
- bcm_bprintf(strbuf,
+ 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",
- dhdp->rx_readahead_cnt, dhdp->tx_realloc, dhdp->fc_packets);
- bcm_bprintf(strbuf, "wd_dpc_sched %ld\n", dhdp->wd_dpc_sched);
- bcm_bprintf(strbuf, "\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 */
- dhd_prot_dump(dhdp, strbuf);
- bcm_bprintf(strbuf, "\n");
+ brcmf_proto_dump(drvr, strbuf);
+ brcmu_bprintf(strbuf, "\n");
/* Add any bus info */
- dhd_bus_dump(dhdp, strbuf);
+ brcmf_sdbrcm_bus_dump(drvr, strbuf);
return !strbuf->size ? -EOVERFLOW : 0;
}
static int
-dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
- const char *name, void *params, int plen, void *arg, int len,
- int val_size)
+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;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
+ bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
if (bcmerror != 0)
goto exit;
@@ -212,16 +187,16 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
switch (actionid) {
case IOV_GVAL(IOV_VERSION):
/* Need to have checked buffer length */
- strncpy((char *)arg, dhd_version, len);
+ strncpy((char *)arg, brcmf_version, len);
break;
case IOV_GVAL(IOV_MSGLEVEL):
- int_val = (s32) dhd_msg_level;
+ int_val = (s32) brcmf_msg_level;
memcpy(arg, &int_val, val_size);
break;
case IOV_SVAL(IOV_MSGLEVEL):
- dhd_msg_level = int_val;
+ brcmf_msg_level = int_val;
break;
case IOV_GVAL(IOV_BCMERRORSTR):
@@ -231,58 +206,29 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
break;
case IOV_GVAL(IOV_BCMERROR):
- int_val = (s32) dhd_pub->bcmerror;
+ int_val = (s32) drvr->bcmerror;
memcpy(arg, &int_val, val_size);
break;
- case IOV_GVAL(IOV_WDTICK):
- int_val = (s32) dhd_watchdog_ms;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_WDTICK):
- if (!dhd_pub->up) {
- bcmerror = -ENOLINK;
- break;
- }
- dhd_os_wd_timer(dhd_pub, (uint) int_val);
- break;
-
case IOV_GVAL(IOV_DUMP):
- bcmerror = dhd_dump(dhd_pub, arg, len);
- break;
-
-#ifdef DHD_DEBUG
- case IOV_GVAL(IOV_DCONSOLE_POLL):
- int_val = (s32) dhd_console_ms;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_DCONSOLE_POLL):
- dhd_console_ms = (uint) int_val;
- break;
-
- case IOV_SVAL(IOV_CONS):
- if (len > 0)
- bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+ bcmerror = brcmf_c_dump(drvr, arg, len);
break;
-#endif
case IOV_SVAL(IOV_CLEARCOUNTS):
- dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
- dhd_pub->tx_errors = dhd_pub->rx_errors = 0;
- dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0;
- dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0;
- dhd_pub->rx_dropped = 0;
- dhd_pub->rx_readahead_cnt = 0;
- dhd_pub->tx_realloc = 0;
- dhd_pub->wd_dpc_sched = 0;
- memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats));
- dhd_bus_clearcounts(dhd_pub);
+ 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) dhd_os_get_ioctl_resp_timeout();
+ int_val = (s32) brcmf_os_get_ioctl_resp_timeout();
memcpy(arg, &int_val, sizeof(int_val));
break;
}
@@ -291,7 +237,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
if (int_val <= 0)
bcmerror = -EINVAL;
else
- dhd_os_set_ioctl_resp_timeout((unsigned int)
+ brcmf_os_set_ioctl_resp_timeout((unsigned int)
int_val);
break;
}
@@ -305,8 +251,8 @@ exit:
return bcmerror;
}
-bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
- int prec)
+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 */
@@ -316,7 +262,7 @@ bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
* exceeding total queue length
*/
if (!pktq_pfull(q, prec) && !pktq_full(q)) {
- bcm_pktq_penq(q, prec, pkt);
+ brcmu_pktq_penq(q, prec, pkt);
return true;
}
@@ -324,8 +270,7 @@ bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
if (pktq_pfull(q, prec))
eprec = prec;
else if (pktq_full(q)) {
- p = bcm_pktq_peek_tail(q, &eprec);
- ASSERT(p);
+ p = brcmu_pktq_peek_tail(q, &eprec);
if (eprec > prec)
return false;
}
@@ -333,60 +278,58 @@ bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
/* Evict if needed */
if (eprec >= 0) {
/* Detect queueing to unconfigured precedence */
- ASSERT(!pktq_pempty(q, eprec));
- discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec);
+ 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 ? bcm_pktq_pdeq(q, eprec) :
- bcm_pktq_pdeq_tail(q, eprec);
+ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
+ brcmu_pktq_pdeq_tail(q, eprec);
if (p == NULL) {
- DHD_ERROR(("%s: bcm_pktq_penq() failed, oldest %d.",
- __func__, discard_oldest));
- ASSERT(p);
+ BRCMF_ERROR(("%s: brcmu_pktq_penq() failed, oldest %d.",
+ __func__, discard_oldest));
}
-
- bcm_pkt_buf_free_skb(p);
+ brcmu_pkt_buf_free_skb(p);
}
/* Enqueue */
- p = bcm_pktq_penq(q, prec, pkt);
+ p = brcmu_pktq_penq(q, prec, pkt);
if (p == NULL) {
- DHD_ERROR(("%s: bcm_pktq_penq() failed.", __func__));
- ASSERT(p);
+ BRCMF_ERROR(("%s: brcmu_pktq_penq() failed.", __func__));
}
- return true;
+ return p != NULL;
}
static int
-dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
+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 bcm_iovar_t *vi = NULL;
+ const struct brcmu_iovar *vi = NULL;
u32 actionid;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- ASSERT(name);
- ASSERT(len >= 0);
+ if (name == NULL || len <= 0)
+ return -EINVAL;
- /* Get MUST have return space */
- ASSERT(set || (arg && len));
+ /* Set does not take qualifiers */
+ if (set && (params || plen))
+ return -EINVAL;
- /* Set does NOT take qualifiers */
- ASSERT(!set || (!params && !plen));
+ /* Get must have return space;*/
+ if (!set && !(arg && len))
+ return -EINVAL;
- vi = bcm_iovar_lookup(dhd_iovars, name);
+ vi = brcmu_iovar_lookup(brcmf_iovars, name);
if (vi == NULL) {
bcmerror = -ENOTSUPP;
goto exit;
}
- DHD_CTL(("%s: %s %s, len %d plen %d\n", __func__,
- name, (set ? "set" : "get"), len, plen));
+ 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
@@ -406,39 +349,40 @@ dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
bcmerror =
- dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len,
+ brcmf_c_doiovar(drvr, vi, actionid, name, params, plen, arg, len,
val_size);
exit:
return bcmerror;
}
-int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
+int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc, void *buf,
+ uint buflen)
{
int bcmerror = 0;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
if (!buf)
return -EINVAL;
switch (ioc->cmd) {
- case DHD_GET_MAGIC:
+ case BRCMF_GET_MAGIC:
if (buflen < sizeof(int))
bcmerror = -EOVERFLOW;
else
- *(int *)buf = DHD_IOCTL_MAGIC;
+ *(int *)buf = BRCMF_IOCTL_MAGIC;
break;
- case DHD_GET_VERSION:
+ case BRCMF_GET_VERSION:
if (buflen < sizeof(int))
bcmerror = -EOVERFLOW;
else
- *(int *)buf = DHD_IOCTL_VERSION;
+ *(int *)buf = BRCMF_IOCTL_VERSION;
break;
- case DHD_GET_VAR:
- case DHD_SET_VAR:{
+ case BRCMF_GET_VAR:
+ case BRCMF_SET_VAR:{
char *arg;
uint arglen;
@@ -456,38 +400,25 @@ int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
arg++, arglen--;
/* call with the appropriate arguments */
- if (ioc->cmd == DHD_GET_VAR)
- bcmerror =
- dhd_iovar_op(dhd_pub, buf, arg, arglen, buf,
- buflen, IOV_GET);
+ if (ioc->cmd == BRCMF_GET_VAR)
+ bcmerror = brcmf_c_iovar_op(drvr, buf, arg,
+ arglen, buf, buflen, IOV_GET);
else
bcmerror =
- dhd_iovar_op(dhd_pub, buf, NULL, 0, arg,
- arglen, IOV_SET);
- if (bcmerror != -ENOTSUPP)
- break;
-
- /* not in generic table, try protocol module */
- if (ioc->cmd == DHD_GET_VAR)
- bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg,
- arglen, buf,
- buflen, IOV_GET);
- else
- bcmerror = dhd_prot_iovar_op(dhd_pub, buf,
- NULL, 0, arg,
- arglen, IOV_SET);
+ 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 == DHD_GET_VAR)
- bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
- arg, arglen, buf,
- buflen, IOV_GET);
+ if (ioc->cmd == BRCMF_GET_VAR)
+ bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
+ buf, arg, arglen, buf, buflen,
+ IOV_GET);
else
- bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
- NULL, 0, arg,
- arglen, IOV_SET);
+ bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
+ buf, NULL, 0, arg, arglen,
+ IOV_SET);
break;
}
@@ -500,7 +431,8 @@ int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
}
#ifdef SHOW_EVENTS
-static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
+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;
@@ -512,62 +444,62 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
char *event_name;
} event_names[] = {
{
- WLC_E_SET_SSID, "SET_SSID"}, {
- WLC_E_JOIN, "JOIN"}, {
- WLC_E_START, "START"}, {
- WLC_E_AUTH, "AUTH"}, {
- WLC_E_AUTH_IND, "AUTH_IND"}, {
- WLC_E_DEAUTH, "DEAUTH"}, {
- WLC_E_DEAUTH_IND, "DEAUTH_IND"}, {
- WLC_E_ASSOC, "ASSOC"}, {
- WLC_E_ASSOC_IND, "ASSOC_IND"}, {
- WLC_E_REASSOC, "REASSOC"}, {
- WLC_E_REASSOC_IND, "REASSOC_IND"}, {
- WLC_E_DISASSOC, "DISASSOC"}, {
- WLC_E_DISASSOC_IND, "DISASSOC_IND"}, {
- WLC_E_QUIET_START, "START_QUIET"}, {
- WLC_E_QUIET_END, "END_QUIET"}, {
- WLC_E_BEACON_RX, "BEACON_RX"}, {
- WLC_E_LINK, "LINK"}, {
- WLC_E_MIC_ERROR, "MIC_ERROR"}, {
- WLC_E_NDIS_LINK, "NDIS_LINK"}, {
- WLC_E_ROAM, "ROAM"}, {
- WLC_E_TXFAIL, "TXFAIL"}, {
- WLC_E_PMKID_CACHE, "PMKID_CACHE"}, {
- WLC_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
- WLC_E_PRUNE, "PRUNE"}, {
- WLC_E_AUTOAUTH, "AUTOAUTH"}, {
- WLC_E_EAPOL_MSG, "EAPOL_MSG"}, {
- WLC_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
- WLC_E_ADDTS_IND, "ADDTS_IND"}, {
- WLC_E_DELTS_IND, "DELTS_IND"}, {
- WLC_E_BCNSENT_IND, "BCNSENT_IND"}, {
- WLC_E_BCNRX_MSG, "BCNRX_MSG"}, {
- WLC_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
- WLC_E_ROAM_PREP, "ROAM_PREP"}, {
- WLC_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
- WLC_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
- WLC_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
- WLC_E_JOIN_START, "JOIN_START"}, {
- WLC_E_ROAM_START, "ROAM_START"}, {
- WLC_E_ASSOC_START, "ASSOC_START"}, {
- WLC_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
- WLC_E_RADIO, "RADIO"}, {
- WLC_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
- WLC_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
- WLC_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
- WLC_E_PSK_SUP, "PSK_SUP"}, {
- WLC_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
- WLC_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
- WLC_E_ICV_ERROR, "ICV_ERROR"}, {
- WLC_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
- WLC_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
- WLC_E_TRACE, "TRACE"}, {
- WLC_E_ACTION_FRAME, "ACTION FRAME"}, {
- WLC_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
- WLC_E_IF, "IF"}, {
- WLC_E_RSSI, "RSSI"}, {
- WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
+ 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);
@@ -585,54 +517,55 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
event_name = event_names[i].event_name;
}
- DHD_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
- DHD_EVENT(("flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n",
- flags, status, reason, auth_type, eabuf));
+ 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 & WLC_EVENT_MSG_LINK)
+ if (flags & BRCMF_EVENT_MSG_LINK)
link = true;
- if (flags & WLC_EVENT_MSG_GROUP)
+ if (flags & BRCMF_EVENT_MSG_GROUP)
group = true;
- if (flags & WLC_EVENT_MSG_FLUSHTXQ)
+ if (flags & BRCMF_EVENT_MSG_FLUSHTXQ)
flush_txq = true;
switch (event_type) {
- case WLC_E_START:
- case WLC_E_DEAUTH:
- case WLC_E_DISASSOC:
- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ case BRCMF_E_START:
+ case BRCMF_E_DEAUTH:
+ case BRCMF_E_DISASSOC:
+ BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
break;
- case WLC_E_ASSOC_IND:
- case WLC_E_REASSOC_IND:
- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ case BRCMF_E_ASSOC_IND:
+ case BRCMF_E_REASSOC_IND:
+ BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
break;
- case WLC_E_ASSOC:
- case WLC_E_REASSOC:
- if (status == WLC_E_STATUS_SUCCESS) {
- DHD_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n",
- event_name, eabuf));
- } else if (status == WLC_E_STATUS_TIMEOUT) {
- DHD_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n",
- event_name, eabuf));
- } else if (status == WLC_E_STATUS_FAIL) {
- DHD_EVENT(("MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
- event_name, eabuf, (int)reason));
+ 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 {
- DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status "
- "%d\n", event_name, eabuf, (int)status));
+ BRCMF_EVENT(("MACEVENT: %s, MAC %s, unexpected status "
+ "%d\n", event_name, eabuf, (int)status));
}
break;
- case WLC_E_DEAUTH_IND:
- case WLC_E_DISASSOC_IND:
- DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name,
- eabuf, (int)reason));
+ 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 WLC_E_AUTH:
- case WLC_E_AUTH_IND:
+ 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)
@@ -641,102 +574,102 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
auth_str = err_msg;
}
- if (event_type == WLC_E_AUTH_IND) {
- DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name,
- eabuf, auth_str));
- } else if (status == WLC_E_STATUS_SUCCESS) {
- DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
- event_name, eabuf, auth_str));
- } else if (status == WLC_E_STATUS_TIMEOUT) {
- DHD_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
- event_name, eabuf, auth_str));
- } else if (status == WLC_E_STATUS_FAIL) {
- DHD_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, "
- "reason %d\n",
- event_name, eabuf, auth_str, (int)reason));
+ 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 WLC_E_JOIN:
- case WLC_E_ROAM:
- case WLC_E_SET_SSID:
- if (status == WLC_E_STATUS_SUCCESS) {
- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name,
- eabuf));
- } else if (status == WLC_E_STATUS_FAIL) {
- DHD_EVENT(("MACEVENT: %s, failed\n", event_name));
- } else if (status == WLC_E_STATUS_NO_NETWORKS) {
- DHD_EVENT(("MACEVENT: %s, no networks found\n",
- event_name));
+ 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 {
- DHD_EVENT(("MACEVENT: %s, unexpected status %d\n",
- event_name, (int)status));
+ BRCMF_EVENT(("MACEVENT: %s, unexpected status %d\n",
+ event_name, (int)status));
}
break;
- case WLC_E_BEACON_RX:
- if (status == WLC_E_STATUS_SUCCESS) {
- DHD_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
- } else if (status == WLC_E_STATUS_FAIL) {
- DHD_EVENT(("MACEVENT: %s, FAIL\n", event_name));
+ 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 {
- DHD_EVENT(("MACEVENT: %s, status %d\n", event_name,
- status));
+ BRCMF_EVENT(("MACEVENT: %s, status %d\n", event_name,
+ status));
}
break;
- case WLC_E_LINK:
- DHD_EVENT(("MACEVENT: %s %s\n", event_name,
- link ? "UP" : "DOWN"));
+ case BRCMF_E_LINK:
+ BRCMF_EVENT(("MACEVENT: %s %s\n", event_name,
+ link ? "UP" : "DOWN"));
break;
- case WLC_E_MIC_ERROR:
- DHD_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
- event_name, eabuf, group, flush_txq));
+ case BRCMF_E_MIC_ERROR:
+ BRCMF_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
+ event_name, eabuf, group, flush_txq));
break;
- case WLC_E_ICV_ERROR:
- case WLC_E_UNICAST_DECODE_ERROR:
- case WLC_E_MULTICAST_DECODE_ERROR:
- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ 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 WLC_E_TXFAIL:
- DHD_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
+ case BRCMF_E_TXFAIL:
+ BRCMF_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
break;
- case WLC_E_SCAN_COMPLETE:
- case WLC_E_PMKID_CACHE:
- DHD_EVENT(("MACEVENT: %s\n", event_name));
+ case BRCMF_E_SCAN_COMPLETE:
+ case BRCMF_E_PMKID_CACHE:
+ BRCMF_EVENT(("MACEVENT: %s\n", event_name));
break;
- case WLC_E_PFN_NET_FOUND:
- case WLC_E_PFN_NET_LOST:
- case WLC_E_PFN_SCAN_COMPLETE:
- DHD_EVENT(("PNOEVENT: %s\n", event_name));
+ 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 WLC_E_PSK_SUP:
- case WLC_E_PRUNE:
- DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n",
+ 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 WLC_E_TRACE:
+ case BRCMF_E_TRACE:
{
static u32 seqnum_prev;
- msgtrace_hdr_t hdr;
+ struct msgtrace_hdr hdr;
u32 nblost;
char *s, *p;
buf = (unsigned char *) event_data;
- memcpy(&hdr, buf, MSGTRACE_HDRLEN);
+ memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
if (hdr.version != MSGTRACE_VERSION) {
- DHD_ERROR(
+ BRCMF_ERROR(
("\nMACEVENT: %s [unsupported version --> "
- "dhd version:%d dongle version:%d]\n",
+ "brcmf version:%d dongle version:%d]\n",
event_name, MSGTRACE_VERSION, hdr.version)
);
/* Reset datalen to avoid display below */
@@ -745,11 +678,12 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
}
/* There are 2 bytes available at the end of data */
- buf[MSGTRACE_HDRLEN + be16_to_cpu(hdr.len)] = '\0';
+ *(buf + sizeof(struct msgtrace_hdr)
+ + be16_to_cpu(hdr.len)) = '\0';
if (be32_to_cpu(hdr.discarded_bytes)
|| be32_to_cpu(hdr.discarded_printf)) {
- DHD_ERROR(
+ BRCMF_ERROR(
("\nWLC_E_TRACE: [Discarded traces in dongle -->"
"discarded_bytes %d discarded_printf %d]\n",
be32_to_cpu(hdr.discarded_bytes),
@@ -758,7 +692,7 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
if (nblost > 0) {
- DHD_ERROR(
+ BRCMF_ERROR(
("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
be32_to_cpu(hdr.seqnum), nblost));
}
@@ -768,7 +702,7 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
* avoid display big
* printf (issue with Linux printk )
*/
- p = (char *)&buf[MSGTRACE_HDRLEN];
+ p = (char *)&buf[sizeof(struct msgtrace_hdr)];
while ((s = strstr(p, "\n")) != NULL) {
*s = '\0';
printk(KERN_DEBUG"%s\n", p);
@@ -781,49 +715,49 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
}
break;
- case WLC_E_RSSI:
- DHD_EVENT(("MACEVENT: %s %d\n", event_name,
- be32_to_cpu(*((int *)event_data))));
+ case BRCMF_E_RSSI:
+ BRCMF_EVENT(("MACEVENT: %s %d\n", event_name,
+ be32_to_cpu(*((int *)event_data))));
break;
default:
- DHD_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));
+ 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;
- DHD_EVENT((" data (%d) : ", datalen));
+ BRCMF_EVENT((" data (%d) : ", datalen));
for (i = 0; i < datalen; i++)
- DHD_EVENT((" 0x%02x ", *buf++));
- DHD_EVENT(("\n"));
+ BRCMF_EVENT((" 0x%02x ", *buf++));
+ BRCMF_EVENT(("\n"));
}
}
#endif /* SHOW_EVENTS */
int
-wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
- wl_event_msg_t *event, void **data_ptr)
+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 */
- bcm_event_t *pvt_data = (bcm_event_t *) pktdata;
+ 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->bcm_hdr.oui[0], DOT11_OUI_LEN)) {
- DHD_ERROR(("%s: mismatched OUI, bailing\n", __func__));
+ 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->bcm_hdr.usr_subtype) !=
+ if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
BCMILCP_BCM_SUBTYPE_EVENT) {
- DHD_ERROR(("%s: mismatched subtype, bailing\n", __func__));
+ BRCMF_ERROR(("%s: mismatched subtype, bailing\n", __func__));
return -EBADE;
}
@@ -831,93 +765,87 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
event_data = *data_ptr;
/* memcpy since BRCM event pkt may be unaligned. */
- memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
+ 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(bcm_event_t);
+ evlen = get_unaligned_be32(&event->datalen) +
+ sizeof(struct brcmf_event);
switch (type) {
- case WLC_E_IF:
+ case BRCMF_E_IF:
{
- dhd_if_event_t *ifevent = (dhd_if_event_t *) event_data;
- DHD_TRACE(("%s: if event\n", __func__));
+ struct brcmf_if_event *ifevent =
+ (struct brcmf_if_event *) event_data;
+ BRCMF_TRACE(("%s: if event\n", __func__));
if (ifevent->ifidx > 0 &&
- ifevent->ifidx < DHD_MAX_IFS) {
- if (ifevent->action == WLC_E_IF_ADD)
- dhd_add_if(dhd, ifevent->ifidx,
+ 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
- dhd_del_if(dhd, ifevent->ifidx);
+ brcmf_del_if(drvr_priv, ifevent->ifidx);
} else {
- DHD_ERROR(("%s: Invalid ifidx %d for %s\n",
- __func__, ifevent->ifidx,
- event->ifname));
+ BRCMF_ERROR(("%s: Invalid ifidx %d for %s\n",
+ __func__, ifevent->ifidx,
+ event->ifname));
}
}
/* send up the if event: btamp user needs it */
- *ifidx = dhd_ifname2idx(dhd, event->ifname);
- /* push up to external supp/auth */
- dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
+ *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
break;
-#ifdef P2P
- case WLC_E_NDIS_LINK:
- break;
-#endif
- /* fall through */
/* These are what external supplicant/authenticator wants */
- case WLC_E_LINK:
- case WLC_E_ASSOC_IND:
- case WLC_E_REASSOC_IND:
- case WLC_E_DISASSOC_IND:
- case WLC_E_MIC_ERROR:
+ 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 = dhd_ifname2idx(dhd, event->ifname);
- /* push up to external supp/auth */
- dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
- DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n",
- __func__, type, flags, status));
+ *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 WLC_E_NDIS_LINK */
- if (type == WLC_E_NDIS_LINK) {
+ /* put it back to BRCMF_E_NDIS_LINK */
+ if (type == BRCMF_E_NDIS_LINK) {
u32 temp;
temp = get_unaligned_be32(&event->event_type);
- DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp));
+ BRCMF_TRACE(("Converted to WLC_E_LINK type %d\n",
+ temp));
- temp = be32_to_cpu(WLC_E_NDIS_LINK);
- memcpy((void *)(&pvt_data->event.event_type), &temp,
- sizeof(pvt_data->event.event_type));
+ 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
- wl_show_host_event(event, event_data);
+ 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 wl_pattern_atoh(char *src, char *dst)
+static int brcmf_c_pattern_atoh(char *src, char *dst)
{
int i;
if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
- DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
+ BRCMF_ERROR(("Mask invalid format. Needs to start with 0x\n"));
return -1;
}
src = src + 2; /* Skip past 0x */
if (strlen(src) % 2 != 0) {
- DHD_ERROR(("Mask invalid format. Length must be even.\n"));
+ BRCMF_ERROR(("Mask invalid format. Length must be even.\n"));
return -1;
}
for (i = 0; *src != '\0'; i++) {
@@ -931,7 +859,7 @@ static int wl_pattern_atoh(char *src, char *dst)
}
void
-dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
+brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
int master_mode)
{
char *argv[8];
@@ -942,12 +870,12 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
char *arg_save = 0, *arg_org = 0;
int rc;
char buf[128];
- wl_pkt_filter_enable_t enable_parm;
- wl_pkt_filter_enable_t *pkt_filterp;
+ 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) {
- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+ BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
goto fail;
}
arg_org = arg_save;
@@ -957,7 +885,7 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
i = 0;
if (NULL == argv[i]) {
- DHD_ERROR(("No args provided\n"));
+ BRCMF_ERROR(("No args provided\n"));
goto fail;
}
@@ -967,7 +895,7 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
buf[str_len] = '\0';
buf_len = str_len + 1;
- pkt_filterp = (wl_pkt_filter_enable_t *) (buf + 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);
@@ -979,33 +907,34 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
/* Enable/disable the specified filter. */
- rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+ rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
rc = rc >= 0 ? 0 : rc;
if (rc)
- DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
+ BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+ __func__, arg, rc));
else
- DHD_TRACE(("%s: successfully added pktfilter %s\n",
- __func__, arg));
+ BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
+ __func__, arg));
/* Contorl the master mode */
- bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
+ brcmu_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
sizeof(buf));
- rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, 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)
- DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
+ BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+ __func__, arg, rc));
fail:
kfree(arg_org);
}
-void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
+void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
{
const char *str;
- wl_pkt_filter_t pkt_filter;
- wl_pkt_filter_t *pkt_filterp;
+ struct brcmf_pkt_filter pkt_filter;
+ struct brcmf_pkt_filter *pkt_filterp;
int buf_len;
int str_len;
int rc;
@@ -1014,29 +943,22 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
char *argv[8], *buf = 0;
int i = 0;
char *arg_save = 0, *arg_org = 0;
-#define BUF_SIZE 2048
arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
if (!arg_save) {
- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+ BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
goto fail;
}
arg_org = arg_save;
- buf = kmalloc(BUF_SIZE, GFP_ATOMIC);
+ buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
if (!buf) {
- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+ BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
goto fail;
}
- memcpy(arg_save, arg, strlen(arg) + 1);
-
- if (strlen(arg) > BUF_SIZE) {
- DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg),
- (int)sizeof(buf)));
- goto fail;
- }
+ strcpy(arg_save, arg);
argv[i] = strsep(&arg_save, " ");
while (argv[i++])
@@ -1044,23 +966,22 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
i = 0;
if (NULL == argv[i]) {
- DHD_ERROR(("No args provided\n"));
+ BRCMF_ERROR(("No args provided\n"));
goto fail;
}
str = "pkt_filter_add";
+ strcpy(buf, str);
str_len = strlen(str);
- strncpy(buf, str, str_len);
- buf[str_len] = '\0';
buf_len = str_len + 1;
- pkt_filterp = (wl_pkt_filter_t *) (buf + 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]) {
- DHD_ERROR(("Polarity not provided\n"));
+ BRCMF_ERROR(("Polarity not provided\n"));
goto fail;
}
@@ -1068,7 +989,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
if (NULL == argv[++i]) {
- DHD_ERROR(("Filter type not provided\n"));
+ BRCMF_ERROR(("Filter type not provided\n"));
goto fail;
}
@@ -1076,7 +997,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
if (NULL == argv[++i]) {
- DHD_ERROR(("Offset not provided\n"));
+ BRCMF_ERROR(("Offset not provided\n"));
goto fail;
}
@@ -1084,34 +1005,34 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
if (NULL == argv[++i]) {
- DHD_ERROR(("Bitmask not provided\n"));
+ BRCMF_ERROR(("Bitmask not provided\n"));
goto fail;
}
/* Parse pattern filter mask. */
mask_size =
- wl_pattern_atoh
+ brcmf_c_pattern_atoh
(argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
if (NULL == argv[++i]) {
- DHD_ERROR(("Pattern not provided\n"));
+ BRCMF_ERROR(("Pattern not provided\n"));
goto fail;
}
/* Parse pattern filter pattern. */
pattern_size =
- wl_pattern_atoh(argv[i],
+ brcmf_c_pattern_atoh(argv[i],
(char *)&pkt_filterp->u.pattern.
mask_and_pattern[mask_size]);
if (mask_size != pattern_size) {
- DHD_ERROR(("Mask and pattern not the same size\n"));
+ BRCMF_ERROR(("Mask and pattern not the same size\n"));
goto fail;
}
pkt_filter.u.pattern.size_bytes = mask_size;
- buf_len += WL_PKT_FILTER_FIXED_LEN;
- buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * 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
@@ -1120,17 +1041,17 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
*/
memcpy((char *)pkt_filterp,
&pkt_filter,
- WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+ BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN);
- rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+ rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
rc = rc >= 0 ? 0 : rc;
if (rc)
- DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
+ BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+ __func__, arg, rc));
else
- DHD_TRACE(("%s: successfully added pktfilter %s\n",
- __func__, arg));
+ BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
+ __func__, arg));
fail:
kfree(arg_org);
@@ -1138,711 +1059,138 @@ fail:
kfree(buf);
}
-void dhd_arp_offload_set(dhd_pub_t *dhd, int arp_mode)
+void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
{
char iovbuf[32];
int retcode;
- bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
- retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ 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)
- DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
- "retcode = %d\n", __func__, arp_mode, retcode));
+ BRCMF_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
+ "retcode = %d\n", __func__, arp_mode, retcode));
else
- DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
- __func__, arp_mode));
+ BRCMF_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
+ __func__, arp_mode));
}
-void dhd_arp_offload_enable(dhd_pub_t *dhd, int arp_enable)
+void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
{
char iovbuf[32];
int retcode;
- bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
- retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ 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)
- DHD_TRACE(("%s: failed to enabe ARP offload to %d, "
- "retcode = %d\n", __func__, arp_enable, retcode));
+ BRCMF_TRACE(("%s: failed to enabe ARP offload to %d, "
+ "retcode = %d\n", __func__, arp_enable, retcode));
else
- DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
- __func__, arp_enable));
+ BRCMF_TRACE(("%s: successfully enabed ARP offload to %d\n",
+ __func__, arp_enable));
}
-int dhd_preinit_ioctls(dhd_pub_t *dhd)
+int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr)
{
- char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for
+ 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 = DHD_SDALIGN;
+ u32 dongle_align = BRCMF_SDALIGN;
u32 glom = 0;
uint bcn_timeout = 3;
int scan_assoc_time = 40;
int scan_unassoc_time = 40;
-#ifdef GET_CUSTOM_MAC_ENABLE
- int ret = 0;
- u8 ea_addr[ETH_ALEN];
-#endif /* GET_CUSTOM_MAC_ENABLE */
-
- dhd_os_proto_block(dhd);
-
-#ifdef GET_CUSTOM_MAC_ENABLE
- /* Read MAC address from external customer place
- ** NOTE that default mac address has to be present in
- ** otp or nvram file to bring up
- ** firmware but unique per board mac address maybe provided by
- ** customer code
- */
- ret = dhd_custom_get_mac_address(ea_addr);
- if (!ret) {
- bcm_mkiovar("cur_etheraddr", (void *)ea_addr, ETH_ALEN,
- buf, sizeof(buf));
- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
- if (ret < 0) {
- DHD_ERROR(("%s: can't set MAC address , error=%d\n",
- __func__, ret));
- } else
- memcpy(dhd->mac.octet, (void *)&ea_addr,
- ETH_ALEN);
- }
-#endif /* GET_CUSTOM_MAC_ENABLE */
+ int i;
+
+ brcmf_os_proto_block(drvr);
/* Set Country code */
- if (dhd->country_code[0] != 0) {
- if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
- dhd->country_code,
- sizeof(dhd->country_code)) < 0) {
- DHD_ERROR(("%s: country code setting failed\n",
- __func__));
+ 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;
- bcm_mkiovar("ver", 0, 0, buf, sizeof(buf));
- dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(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 */
- DHD_ERROR(("Firmware version = %s\n", buf));
+ BRCMF_ERROR(("Firmware version = %s\n", buf));
/* Set PowerSave mode */
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
+ brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_PM, (char *)&power_mode,
sizeof(power_mode));
/* Match Host and Dongle rx alignment */
- bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
+ brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ sizeof(iovbuf));
/* disable glom option per default */
- bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ 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 */
- bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+ brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, 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 */
- bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ 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 (dhd_radio_up)
- dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+ if (brcmf_radio_up)
+ brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_UP, (char *)&up,
+ sizeof(up));
/* Setup event_msgs */
- bcm_mkiovar("event_msgs", dhd->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
- sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ 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));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME,
+ brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
(char *)&scan_assoc_time, sizeof(scan_assoc_time));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME,
+ brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
(char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
-#ifdef ARP_OFFLOAD_SUPPORT
/* Set and enable ARP offload feature */
- if (dhd_arp_enable)
- dhd_arp_offload_set(dhd, dhd_arp_mode);
- dhd_arp_offload_enable(dhd, dhd_arp_enable);
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-#ifdef PKT_FILTER_SUPPORT
- {
- int i;
- /* Set up pkt filter */
- if (dhd_pkt_filter_enable) {
- for (i = 0; i < dhd->pktfilter_count; i++) {
- dhd_pktfilter_offload_set(dhd,
- dhd->pktfilter[i]);
- dhd_pktfilter_offload_enable(dhd,
- dhd->pktfilter[i],
- dhd_pkt_filter_init,
- dhd_master_mode);
- }
- }
- }
-#endif /* PKT_FILTER_SUPPORT */
-
- dhd_os_proto_unblock(dhd);
-
- return 0;
-}
-
-#ifdef SIMPLE_ISCAN
-uint iscan_thread_id;
-iscan_buf_t *iscan_chain;
-
-iscan_buf_t *dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
-{
- iscan_buf_t *iscanbuf_alloc = 0;
- iscan_buf_t *iscanbuf_head;
-
- dhd_iscan_lock();
-
- iscanbuf_alloc = kmalloc(sizeof(iscan_buf_t), GFP_ATOMIC);
- if (iscanbuf_alloc == NULL)
- goto fail;
-
- iscanbuf_alloc->next = NULL;
- iscanbuf_head = *iscanbuf;
-
- DHD_ISCAN(("%s: addr of allocated node = 0x%X"
- "addr of iscanbuf_head = 0x%X dhd = 0x%X\n",
- __func__, iscanbuf_alloc, iscanbuf_head, dhd));
-
- if (iscanbuf_head == NULL) {
- *iscanbuf = iscanbuf_alloc;
- DHD_ISCAN(("%s: Head is allocated\n", __func__));
- goto fail;
- }
-
- while (iscanbuf_head->next)
- iscanbuf_head = iscanbuf_head->next;
-
- iscanbuf_head->next = iscanbuf_alloc;
-
-fail:
- dhd_iscan_unlock();
- return iscanbuf_alloc;
-}
-
-void dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
-{
- iscan_buf_t *iscanbuf_free = 0;
- iscan_buf_t *iscanbuf_prv = 0;
- iscan_buf_t *iscanbuf_cur = iscan_chain;
- dhd_pub_t *dhd = dhd_bus_pub(dhdp);
-
- dhd_iscan_lock();
- /* If iscan_delete is null then delete the entire
- * chain or else delete specific one provided
- */
- if (!iscan_delete) {
- while (iscanbuf_cur) {
- iscanbuf_free = iscanbuf_cur;
- iscanbuf_cur = iscanbuf_cur->next;
- iscanbuf_free->next = 0;
- kfree(iscanbuf_free);
- }
- iscan_chain = 0;
- } else {
- while (iscanbuf_cur) {
- if (iscanbuf_cur == iscan_delete)
- break;
- iscanbuf_prv = iscanbuf_cur;
- iscanbuf_cur = iscanbuf_cur->next;
- }
- if (iscanbuf_prv)
- iscanbuf_prv->next = iscan_delete->next;
-
- iscan_delete->next = 0;
- kfree(iscan_delete);
-
- if (!iscanbuf_prv)
- iscan_chain = 0;
- }
- dhd_iscan_unlock();
-}
-
-iscan_buf_t *dhd_iscan_result_buf(void)
-{
- return iscan_chain;
-}
-
-/*
-* print scan cache
-* print partial iscan_skip list differently
-*/
-int dhd_iscan_print_cache(iscan_buf_t *iscan_skip)
-{
- int i = 0, l = 0;
- iscan_buf_t *iscan_cur;
- wl_iscan_results_t *list;
- wl_scan_results_t *results;
- wl_bss_info_t UNALIGNED *bi;
-
- dhd_iscan_lock();
-
- iscan_cur = dhd_iscan_result_buf();
-
- while (iscan_cur) {
- list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
- if (!list)
- break;
-
- results = (wl_scan_results_t *)&list->results;
- if (!results)
- break;
-
- if (results->version != WL_BSS_INFO_VERSION) {
- DHD_ISCAN(("%s: results->version %d != "
- "WL_BSS_INFO_VERSION\n",
- __func__, results->version));
- goto done;
- }
-
- bi = results->bss_info;
- for (i = 0; i < results->count; i++) {
- if (!bi)
- break;
-
- DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
- iscan_cur != iscan_skip ? "BSS" : "bss", l,
- i, bi->BSSID.octet[0], bi->BSSID.octet[1],
- bi->BSSID.octet[2], bi->BSSID.octet[3],
- bi->BSSID.octet[4], bi->BSSID.octet[5]));
-
- bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
- }
- iscan_cur = iscan_cur->next;
- l++;
- }
-
-done:
- dhd_iscan_unlock();
- return 0;
-}
-
-/*
-* delete disappeared AP from specific scan cache but skip partial
-* list in iscan_skip
-*/
-int dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
-{
- int i = 0, j = 0, l = 0;
- iscan_buf_t *iscan_cur;
- wl_iscan_results_t *list;
- wl_scan_results_t *results;
- wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
-
- unsigned char *s_addr = addr;
-
- dhd_iscan_lock();
- DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n",
- __func__, s_addr[0], s_addr[1], s_addr[2],
- s_addr[3], s_addr[4], s_addr[5]));
-
- iscan_cur = dhd_iscan_result_buf();
-
- while (iscan_cur) {
- if (iscan_cur != iscan_skip) {
- list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
- if (!list)
- break;
-
- results = (wl_scan_results_t *)&list->results;
- if (!results)
- break;
-
- if (results->version != WL_BSS_INFO_VERSION) {
- DHD_ERROR(("%s: results->version %d != "
- "WL_BSS_INFO_VERSION\n",
- __func__, results->version));
- goto done;
- }
-
- bi = results->bss_info;
- for (i = 0; i < results->count; i++) {
- if (!bi)
- break;
-
- if (!memcmp
- (bi->BSSID.octet, addr, ETH_ALEN)) {
- DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] "
- "%X:%X:%X:%X:%X:%X\n",
- __func__, l, i, bi->BSSID.octet[0],
- bi->BSSID.octet[1], bi->BSSID.octet[2],
- bi->BSSID.octet[3], bi->BSSID.octet[4],
- bi->BSSID.octet[5]));
-
- bi_new = bi;
- bi = (wl_bss_info_t *)((unsigned long)
- bi + bi->length);
-/*
- if(bi && bi_new) {
- memcpy(bi_new, bi, results->buflen -
- bi_new->length);
- results->buflen -= bi_new->length;
- }
-*/
- results->buflen -= bi_new->length;
- results->count--;
-
- for (j = i; j < results->count; j++) {
- if (bi && bi_new) {
- DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d]" "%X:%X:%X:%X:%X:%X\n",
- __func__, l, j,
- bi->BSSID.octet[0],
- bi->BSSID.octet[1],
- bi->BSSID.octet[2],
- bi->BSSID.octet[3],
- bi->BSSID.octet[4],
- bi->BSSID.octet[5]));
-
- bi_next =
- (wl_bss_info_t *)((unsigned long)bi +
- bi->length);
- memcpy(bi_new, bi,
- bi->length);
- bi_new =
- (wl_bss_info_t *)((unsigned long)bi_new +
- bi_new->
- length);
- bi = bi_next;
- }
- }
-
- if (results->count == 0) {
- /* Prune now empty partial
- scan list */
- dhd_iscan_free_buf(dhdp,
- iscan_cur);
- goto done;
- }
- break;
- }
- bi = (wl_bss_info_t *)((unsigned long)bi +
- bi->length);
- }
+ 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);
}
- iscan_cur = iscan_cur->next;
- l++;
- }
-
-done:
- dhd_iscan_unlock();
- return 0;
-}
-
-int dhd_iscan_remove_duplicates(void *dhdp, iscan_buf_t *iscan_cur)
-{
- int i = 0;
- wl_iscan_results_t *list;
- wl_scan_results_t *results;
- wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
-
- dhd_iscan_lock();
-
- DHD_ISCAN(("%s: Scan cache before delete\n", __func__));
- dhd_iscan_print_cache(iscan_cur);
-
- if (!iscan_cur)
- goto done;
-
- list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
- if (!list)
- goto done;
-
- results = (wl_scan_results_t *)&list->results;
- if (!results)
- goto done;
-
- if (results->version != WL_BSS_INFO_VERSION) {
- DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
- __func__, results->version));
- goto done;
}
- bi = results->bss_info;
- for (i = 0; i < results->count; i++) {
- if (!bi)
- break;
-
- DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n",
- __func__, i, bi->BSSID.octet[0],
- bi->BSSID.octet[1], bi->BSSID.octet[2],
- bi->BSSID.octet[3], bi->BSSID.octet[4],
- bi->BSSID.octet[5]));
-
- dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
+ brcmf_os_proto_unblock(drvr);
- bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
- }
-
-done:
- DHD_ISCAN(("%s: Scan cache after delete\n", __func__));
- dhd_iscan_print_cache(iscan_cur);
- dhd_iscan_unlock();
return 0;
}
-
-void dhd_iscan_ind_scan_confirm(void *dhdp, bool status)
-{
-
- dhd_ind_scan_confirm(dhdp, status);
-}
-
-int dhd_iscan_request(void *dhdp, u16 action)
-{
- int rc;
- wl_iscan_params_t params;
- dhd_pub_t *dhd = dhd_bus_pub(dhdp);
- char buf[WLC_IOCTL_SMLEN];
-
- memset(&params, 0, sizeof(wl_iscan_params_t));
- memcpy(&params.params.bssid, &ether_bcast, ETH_ALEN);
-
- params.params.bss_type = DOT11_BSSTYPE_ANY;
- params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
-
- params.params.nprobes = -1;
- params.params.active_time = -1;
- params.params.passive_time = -1;
- params.params.home_time = -1;
- params.params.channel_num = 0;
-
- params.version = ISCAN_REQ_VERSION;
- params.action = action;
- params.scan_duration = 0;
-
- bcm_mkiovar("iscan", (char *)&params, sizeof(wl_iscan_params_t), buf,
- WLC_IOCTL_SMLEN);
- rc = dhd_wl_ioctl(dhdp, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN);
-
- return rc;
-}
-
-static int dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
-{
- wl_iscan_results_t *list_buf;
- wl_iscan_results_t list;
- wl_scan_results_t *results;
- iscan_buf_t *iscan_cur;
- int status = -1;
- dhd_pub_t *dhd = dhd_bus_pub(dhdp);
- int rc;
-
- iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain);
- if (!iscan_cur) {
- DHD_ERROR(("%s: Failed to allocate node\n", __func__));
- dhd_iscan_free_buf(dhdp, 0);
- dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT);
- goto fail;
- }
-
- dhd_iscan_lock();
-
- memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
- list_buf = (wl_iscan_results_t *) iscan_cur->iscan_buf;
- results = &list_buf->results;
- results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
- results->version = 0;
- results->count = 0;
-
- memset(&list, 0, sizeof(list));
- list.results.buflen = WLC_IW_ISCAN_MAXLEN;
- bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
- iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
- rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf,
- WLC_IW_ISCAN_MAXLEN);
-
- results->buflen = results->buflen;
- results->version = results->version;
- *scan_count = results->count = results->count;
- status = list_buf->status;
-
- dhd_iscan_unlock();
-
- if (!(*scan_count))
- dhd_iscan_free_buf(dhdp, iscan_cur);
- else
- dhd_iscan_remove_duplicates(dhdp, iscan_cur);
-
-fail:
- return status;
-}
-#endif /* SIMPLE_ISCAN */
-
-#ifdef PNO_SUPPORT
-int dhd_pno_clean(dhd_pub_t *dhd)
-{
- char iovbuf[128];
- int pfn_enabled = 0;
- int iov_len = 0;
- int ret;
-
- /* Disable pfn */
- iov_len =
- bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf));
- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
- if (ret >= 0) {
- /* clear pfn */
- iov_len = bcm_mkiovar("pfnclear", 0, 0, iovbuf, sizeof(iovbuf));
- if (iov_len) {
- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
- iov_len);
- if (ret < 0) {
- DHD_ERROR(("%s failed code %d\n", __func__,
- ret));
- }
- } else {
- ret = -1;
- DHD_ERROR(("%s failed code %d\n", __func__, iov_len));
- }
- } else
- DHD_ERROR(("%s failed code %d\n", __func__, ret));
-
- return ret;
-}
-
-int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
-{
- char iovbuf[128];
- int ret = -1;
-
- if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
- DHD_ERROR(("%s error exit\n", __func__));
- return ret;
- }
-
- /* Enable/disable PNO */
- ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf,
- sizeof(iovbuf));
- if (ret > 0) {
- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf));
- if (ret < 0) {
- DHD_ERROR(("%s failed for error=%d\n", __func__, ret));
- return ret;
- } else {
- dhd->pno_enable = pfn_enabled;
- DHD_TRACE(("%s set pno as %d\n", __func__,
- dhd->pno_enable));
- }
- } else
- DHD_ERROR(("%s failed err=%d\n", __func__, ret));
-
- return ret;
-}
-
-/* Function to execute combined scan */
-int
-dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t *ssids_local, int nssid, unsigned char scan_fr)
-{
- int err = -1;
- char iovbuf[128];
- int k, i;
- wl_pfn_param_t pfn_param;
- wl_pfn_t pfn_element;
-
- DHD_TRACE(("%s nssid=%d nchan=%d\n", __func__, nssid, scan_fr));
-
- if ((!dhd) && (!ssids_local)) {
- DHD_ERROR(("%s error exit\n", __func__));
- err = -1;
- }
-
- /* Check for broadcast ssid */
- for (k = 0; k < nssid; k++) {
- if (!ssids_local[k].SSID_len) {
- DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO "
- "setting\n", k));
- return err;
- }
- }
-/* #define PNO_DUMP 1 */
-#ifdef PNO_DUMP
- {
- int j;
- for (j = 0; j < nssid; j++) {
- DHD_ERROR(("%d: scan for %s size =%d\n", j,
- ssids_local[j].SSID,
- ssids_local[j].SSID_len));
- }
- }
-#endif /* PNO_DUMP */
-
- /* clean up everything */
- err = dhd_pno_clean(dhd);
- if (err < 0) {
- DHD_ERROR(("%s failed error=%d\n", __func__, err));
- return err;
- }
- memset(&pfn_param, 0, sizeof(pfn_param));
- memset(&pfn_element, 0, sizeof(pfn_element));
-
- /* set pfn parameters */
- pfn_param.version = PFN_VERSION;
- pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT);
-
- /* set up pno scan fr */
- if (scan_fr != 0)
- pfn_param.scan_freq = scan_fr;
-
- bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf,
- sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
- /* set all pfn ssid */
- for (i = 0; i < nssid; i++) {
-
- pfn_element.bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
- pfn_element.auth = WLAN_AUTH_OPEN;
- pfn_element.wpa_auth = WPA_AUTH_PFN_ANY;
- pfn_element.wsec = 0;
- pfn_element.infra = 1;
-
- memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID,
- ssids_local[i].SSID_len);
- pfn_element.ssid.SSID_len = ssids_local[i].SSID_len;
-
- err = bcm_mkiovar("pfn_add", (char *)&pfn_element,
- sizeof(pfn_element), iovbuf, sizeof(iovbuf));
- if (err > 0) {
- err = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf));
- if (err < 0) {
- DHD_ERROR(("%s failed for i=%d error=%d\n",
- __func__, i, err));
- return err;
- }
- } else
- DHD_ERROR(("%s failed err=%d\n", __func__, err));
- }
-
- /* Enable PNO */
- /* dhd_pno_enable(dhd, 1); */
- return err;
-}
-
-int dhd_pno_get_status(dhd_pub_t *dhd)
-{
- int ret = -1;
-
- if (!dhd)
- return ret;
- else
- return dhd->pno_enable;
-}
-
-#endif /* PNO_SUPPORT */
-
-/* Androd ComboSCAN support */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c b/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
deleted file mode 100644
index 1cf6c5dc2bb7..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
+++ /dev/null
@@ -1,158 +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/netdevice.h>
-#include <bcmutils.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-
-#include <wlioctl.h>
-#include <wl_iw.h>
-
-#define WL_ERROR(fmt, args...) printk(fmt, ##args)
-#define WL_TRACE(fmt, args...) no_printk(fmt, ##args)
-
-#ifdef CUSTOMER_HW
-extern void bcm_wlan_power_off(int);
-extern void bcm_wlan_power_on(int);
-#endif /* CUSTOMER_HW */
-#ifdef CUSTOMER_HW2
-int wifi_set_carddetect(int on);
-int wifi_set_power(int on, unsigned long msec);
-int wifi_get_irq_number(unsigned long *irq_flags_ptr);
-#endif
-
-#if defined(OOB_INTR_ONLY)
-
-#if defined(BCMLXSDMMC)
-extern int sdioh_mmc_irq(int irq);
-#endif /* (BCMLXSDMMC) */
-
-#ifdef CUSTOMER_HW3
-#include <mach/gpio.h>
-#endif
-
-/* Customer specific Host GPIO definition */
-static int dhd_oob_gpio_num = -1; /* GG 19 */
-
-module_param(dhd_oob_gpio_num, int, 0644);
-MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
-
-int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
-{
- int host_oob_irq = 0;
-
-#ifdef CUSTOMER_HW2
- host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
-
-#else /* for NOT CUSTOMER_HW2 */
-#if defined(CUSTOM_OOB_GPIO_NUM)
- if (dhd_oob_gpio_num < 0)
- dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
-#endif
-
- if (dhd_oob_gpio_num < 0) {
- WL_ERROR("%s: ERROR customer specific Host GPIO is NOT defined\n",
- __func__);
- return dhd_oob_gpio_num;
- }
-
- WL_ERROR("%s: customer specific Host GPIO number is (%d)\n",
- __func__, dhd_oob_gpio_num);
-
-#if defined CUSTOMER_HW
- host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
-#elif defined CUSTOMER_HW3
- gpio_request(dhd_oob_gpio_num, "oob irq");
- host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
- gpio_direction_input(dhd_oob_gpio_num);
-#endif /* CUSTOMER_HW */
-#endif /* CUSTOMER_HW2 */
-
- return host_oob_irq;
-}
-#endif /* defined(OOB_INTR_ONLY) */
-
-/* Customer function to control hw specific wlan gpios */
-void dhd_customer_gpio_wlan_ctrl(int onoff)
-{
- switch (onoff) {
- case WLAN_RESET_OFF:
- WL_TRACE("%s: call customer specific GPIO to insert WLAN RESET\n",
- __func__);
-#ifdef CUSTOMER_HW
- bcm_wlan_power_off(2);
-#endif /* CUSTOMER_HW */
-#ifdef CUSTOMER_HW2
- wifi_set_power(0, 0);
-#endif
- WL_ERROR("=========== WLAN placed in RESET ========\n");
- break;
-
- case WLAN_RESET_ON:
- WL_TRACE("%s: callc customer specific GPIO to remove WLAN RESET\n",
- __func__);
-#ifdef CUSTOMER_HW
- bcm_wlan_power_on(2);
-#endif /* CUSTOMER_HW */
-#ifdef CUSTOMER_HW2
- wifi_set_power(1, 0);
-#endif
- WL_ERROR("=========== WLAN going back to live ========\n");
- break;
-
- case WLAN_POWER_OFF:
- WL_TRACE("%s: call customer specific GPIO to turn off WL_REG_ON\n",
- __func__);
-#ifdef CUSTOMER_HW
- bcm_wlan_power_off(1);
-#endif /* CUSTOMER_HW */
- break;
-
- case WLAN_POWER_ON:
- WL_TRACE("%s: call customer specific GPIO to turn on WL_REG_ON\n",
- __func__);
-#ifdef CUSTOMER_HW
- bcm_wlan_power_on(1);
-#endif /* CUSTOMER_HW */
- /* Lets customer power to get stable */
- udelay(200);
- break;
- }
-}
-
-#ifdef GET_CUSTOM_MAC_ENABLE
-/* Function to get custom MAC address */
-int dhd_custom_get_mac_address(unsigned char *buf)
-{
- WL_TRACE("%s Enter\n", __func__);
- if (!buf)
- return -EINVAL;
-
- /* Customer access to MAC address stored outside of DHD driver */
-
-#ifdef EXAMPLE_GET_MAC
- /* EXAMPLE code */
- {
- u8 ea_example[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xFF};
- memcpy(buf, ea_example, ETH_ALEN);
- }
-#endif /* EXAMPLE_GET_MAC */
-
- return 0;
-}
-#endif /* GET_CUSTOM_MAC_ENABLE */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
index 0817f1348e09..5be4d7a609c2 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
@@ -14,90 +14,57 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _dhd_dbg_
-#define _dhd_dbg_
+#ifndef _BRCMF_DBG_H_
+#define _BRCMF_DBG_H_
-#if defined(DHD_DEBUG)
+#if defined(BCMDBG)
-#define DHD_ERROR(args) \
- do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
+#define BRCMF_ERROR(args) \
+ do {if ((brcmf_msg_level & BRCMF_ERROR_VAL) && (net_ratelimit())) \
printk args; } while (0)
-#define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) \
+#define BRCMF_TRACE(args) do {if (brcmf_msg_level & BRCMF_TRACE_VAL) \
printk args; } while (0)
-#define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) \
+#define BRCMF_INFO(args) do {if (brcmf_msg_level & BRCMF_INFO_VAL) \
printk args; } while (0)
-#define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) \
+#define BRCMF_DATA(args) do {if (brcmf_msg_level & BRCMF_DATA_VAL) \
printk args; } while (0)
-#define DHD_CTL(args) do {if (dhd_msg_level & DHD_CTL_VAL) \
+#define BRCMF_CTL(args) do {if (brcmf_msg_level & BRCMF_CTL_VAL) \
printk args; } while (0)
-#define DHD_TIMER(args) do {if (dhd_msg_level & DHD_TIMER_VAL) \
+#define BRCMF_TIMER(args) do {if (brcmf_msg_level & BRCMF_TIMER_VAL) \
printk args; } while (0)
-#define DHD_HDRS(args) do {if (dhd_msg_level & DHD_HDRS_VAL) \
+#define BRCMF_INTR(args) do {if (brcmf_msg_level & BRCMF_INTR_VAL) \
printk args; } while (0)
-#define DHD_BYTES(args) do {if (dhd_msg_level & DHD_BYTES_VAL) \
+#define BRCMF_GLOM(args) do {if (brcmf_msg_level & BRCMF_GLOM_VAL) \
printk args; } while (0)
-#define DHD_INTR(args) do {if (dhd_msg_level & DHD_INTR_VAL) \
+#define BRCMF_EVENT(args) do {if (brcmf_msg_level & BRCMF_EVENT_VAL) \
printk args; } while (0)
-#define DHD_GLOM(args) do {if (dhd_msg_level & DHD_GLOM_VAL) \
- printk args; } while (0)
-#define DHD_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) \
- printk args; } while (0)
-#define DHD_BTA(args) do {if (dhd_msg_level & DHD_BTA_VAL) \
- printk args; } while (0)
-#define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) \
- printk args; } while (0)
-
-#define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL)
-#define DHD_TRACE_ON() (dhd_msg_level & DHD_TRACE_VAL)
-#define DHD_INFO_ON() (dhd_msg_level & DHD_INFO_VAL)
-#define DHD_DATA_ON() (dhd_msg_level & DHD_DATA_VAL)
-#define DHD_CTL_ON() (dhd_msg_level & DHD_CTL_VAL)
-#define DHD_TIMER_ON() (dhd_msg_level & DHD_TIMER_VAL)
-#define DHD_HDRS_ON() (dhd_msg_level & DHD_HDRS_VAL)
-#define DHD_BYTES_ON() (dhd_msg_level & DHD_BYTES_VAL)
-#define DHD_INTR_ON() (dhd_msg_level & DHD_INTR_VAL)
-#define DHD_GLOM_ON() (dhd_msg_level & DHD_GLOM_VAL)
-#define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL)
-#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL)
-#define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL)
-#else /* (defined BCMDBG) || (defined DHD_DEBUG) */
+#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
+#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL)
+#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL)
+#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
+#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
-#define DHD_ERROR(args) do {if (net_ratelimit()) printk args; } while (0)
-#define DHD_TRACE(args)
-#define DHD_INFO(args)
-#define DHD_DATA(args)
-#define DHD_CTL(args)
-#define DHD_TIMER(args)
-#define DHD_HDRS(args)
-#define DHD_BYTES(args)
-#define DHD_INTR(args)
-#define DHD_GLOM(args)
-#define DHD_EVENT(args)
-#define DHD_BTA(args)
-#define DHD_ISCAN(args)
+#else /* (defined BCMDBG) || (defined BCMDBG) */
-#define DHD_ERROR_ON() 0
-#define DHD_TRACE_ON() 0
-#define DHD_INFO_ON() 0
-#define DHD_DATA_ON() 0
-#define DHD_CTL_ON() 0
-#define DHD_TIMER_ON() 0
-#define DHD_HDRS_ON() 0
-#define DHD_BYTES_ON() 0
-#define DHD_INTR_ON() 0
-#define DHD_GLOM_ON() 0
-#define DHD_EVENT_ON() 0
-#define DHD_BTA_ON() 0
-#define DHD_ISCAN_ON() 0
-#endif /* defined(DHD_DEBUG) */
+#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 DHD_LOG(args)
+#define BRCMF_DATA_ON() 0
+#define BRCMF_CTL_ON() 0
+#define BRCMF_HDRS_ON() 0
+#define BRCMF_BYTES_ON() 0
+#define BRCMF_GLOM_ON() 0
-#define DHD_NONE(args)
-extern int dhd_msg_level;
+#endif /* defined(BCMDBG) */
-/* Defines msg bits */
-#include <dhdioctl.h>
+extern int brcmf_msg_level;
-#endif /* _dhd_dbg_ */
+#endif /* _BRCMF_DBG_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
index f356c564cfb9..05dada98eb6b 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -14,9 +14,6 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifdef CONFIG_WIFI_CONTROL_FUNC
-#include <linux/platform_device.h>
-#endif
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
@@ -31,177 +28,34 @@
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-
-#include <wl_cfg80211.h>
-
-#define EPI_VERSION_STR "4.218.248.5"
-#define ETH_P_BRCM 0x886c
-
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-#include <linux/wifi_tiwlan.h>
-
-struct semaphore wifi_control_sem;
-
-struct dhd_bus *g_bus;
-
-static struct wifi_platform_data *wifi_control_data;
-static struct resource *wifi_irqres;
-
-int wifi_get_irq_number(unsigned long *irq_flags_ptr)
-{
- if (wifi_irqres) {
- *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
- return (int)wifi_irqres->start;
- }
-#ifdef CUSTOM_OOB_GPIO_NUM
- return CUSTOM_OOB_GPIO_NUM;
-#else
- return -1;
-#endif
-}
-
-int wifi_set_carddetect(int on)
-{
- printk(KERN_ERR "%s = %d\n", __func__, on);
- if (wifi_control_data && wifi_control_data->set_carddetect)
- wifi_control_data->set_carddetect(on);
- return 0;
-}
-
-int wifi_set_power(int on, unsigned long msec)
-{
- printk(KERN_ERR "%s = %d\n", __func__, on);
- if (wifi_control_data && wifi_control_data->set_power)
- wifi_control_data->set_power(on);
- if (msec)
- mdelay(msec);
- return 0;
-}
-
-int wifi_set_reset(int on, unsigned long msec)
-{
- printk(KERN_ERR "%s = %d\n", __func__, on);
- if (wifi_control_data && wifi_control_data->set_reset)
- wifi_control_data->set_reset(on);
- if (msec)
- mdelay(msec);
- return 0;
-}
-
-static int wifi_probe(struct platform_device *pdev)
-{
- struct wifi_platform_data *wifi_ctrl =
- (struct wifi_platform_data *)(pdev->dev.platform_data);
-
- printk(KERN_ERR "## %s\n", __func__);
- wifi_irqres =
- platform_get_resource_byname(pdev, IORESOURCE_IRQ,
- "bcm4329_wlan_irq");
- wifi_control_data = wifi_ctrl;
-
- wifi_set_power(1, 0); /* Power On */
- wifi_set_carddetect(1); /* CardDetect (0->1) */
-
- up(&wifi_control_sem);
- return 0;
-}
-
-static int wifi_remove(struct platform_device *pdev)
-{
- struct wifi_platform_data *wifi_ctrl =
- (struct wifi_platform_data *)(pdev->dev.platform_data);
-
- printk(KERN_ERR "## %s\n", __func__);
- wifi_control_data = wifi_ctrl;
-
- wifi_set_carddetect(0); /* CardDetect (1->0) */
- wifi_set_power(0, 0); /* Power Off */
-
- up(&wifi_control_sem);
- return 0;
-}
-
-static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
-{
- DHD_TRACE(("##> %s\n", __func__));
- return 0;
-}
-
-static int wifi_resume(struct platform_device *pdev)
-{
- DHD_TRACE(("##> %s\n", __func__));
- return 0;
-}
-
-static struct platform_driver wifi_device = {
- .probe = wifi_probe,
- .remove = wifi_remove,
- .suspend = wifi_suspend,
- .resume = wifi_resume,
- .driver = {
- .name = KBUILD_MODNAME,
- }
-};
-
-int wifi_add_dev(void)
-{
- DHD_TRACE(("## Calling platform_driver_register\n"));
- return platform_driver_register(&wifi_device);
-}
-
-void wifi_del_dev(void)
-{
- DHD_TRACE(("## Unregister platform_driver_register\n"));
- platform_driver_unregister(&wifi_device);
-}
-#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+#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 dhd_mmc_suspend;
-DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
+atomic_t brcmf_mmc_suspend;
#endif /* defined(CONFIG_PM_SLEEP) */
-#if defined(OOB_INTR_ONLY)
-extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable);
-#endif /* defined(OOB_INTR_ONLY) */
-
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");
-#define DRV_MODULE_NAME "brcmfmac"
-
-/* Linux wireless extension support */
-#if defined(CONFIG_WIRELESS_EXT)
-#include <wl_iw.h>
-extern wl_iw_extra_params_t g_wl_iw_params;
-#endif /* defined(CONFIG_WIRELESS_EXT) */
-
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
- uint len);
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
-
-#ifdef PKT_FILTER_SUPPORT
-extern void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg);
-extern void dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
- int master_mode);
-#endif
/* Interface control information */
-typedef struct dhd_if {
- struct dhd_info *info; /* back pointer to dhd_info */
+struct brcmf_if {
+ struct brcmf_info *info; /* back pointer to brcmf_info */
/* OS/stack specifics */
struct net_device *net;
struct net_device_stats stats;
@@ -212,33 +66,17 @@ typedef struct dhd_if {
bool attached; /* Delayed attachment when unset */
bool txflowcontrol; /* Per interface flow control indicator */
char name[IFNAMSIZ]; /* linux interface name */
-} dhd_if_t;
+};
/* Local private structure (extension of pub) */
-typedef struct dhd_info {
-#if defined(CONFIG_WIRELESS_EXT)
- wl_iw_t iw; /* wireless extensions state (must be first) */
-#endif /* defined(CONFIG_WIRELESS_EXT) */
-
- dhd_pub_t pub;
+struct brcmf_info {
+ struct brcmf_pub pub;
/* OS/stack specifics */
- dhd_if_t *iflist[DHD_MAX_IFS];
+ struct brcmf_if *iflist[BRCMF_MAX_IFS];
struct semaphore proto_sem;
wait_queue_head_t ioctl_resp_wait;
- struct timer_list timer;
- bool wd_timer_valid;
- struct tasklet_struct tasklet;
- spinlock_t sdlock;
- spinlock_t txqlock;
- /* Thread based operation */
- bool threads_only;
- struct semaphore sdsem;
- struct task_struct *watchdog_tsk;
- struct semaphore watchdog_sem;
- struct task_struct *dpc_tsk;
- struct semaphore dpc_sem;
/* Thread to issue ioctl for multicast */
struct task_struct *sysioc_tsk;
@@ -246,83 +84,44 @@ typedef struct dhd_info {
bool set_multicast;
bool set_macaddress;
u8 macvalue[ETH_ALEN];
- wait_queue_head_t ctrl_wait;
atomic_t pend_8021x_cnt;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
- struct early_suspend early_suspend;
-#endif /* CONFIG_HAS_EARLYSUSPEND */
-} dhd_info_t;
-
-/* Definitions to provide path to the firmware and nvram
- * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt"
- */
-char firmware_path[MOD_PARAM_PATHLEN];
-char nvram_path[MOD_PARAM_PATHLEN];
-
-/* load firmware and/or nvram values from the filesystem */
-module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
-module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
+};
/* Error bits */
-module_param(dhd_msg_level, int, 0);
+module_param(brcmf_msg_level, int, 0);
/* Spawn a thread for system ioctls (set mac, set mcast) */
-uint dhd_sysioc = true;
-module_param(dhd_sysioc, uint, 0);
-
-/* Watchdog interval */
-uint dhd_watchdog_ms = 10;
-module_param(dhd_watchdog_ms, uint, 0);
-
-#ifdef DHD_DEBUG
-/* Console poll interval */
-uint dhd_console_ms;
-module_param(dhd_console_ms, uint, 0);
-#endif /* DHD_DEBUG */
+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 dhd_arp_mode = 0xb;
-module_param(dhd_arp_mode, uint, 0);
+uint brcmf_arp_mode = 0xb;
+module_param(brcmf_arp_mode, uint, 0);
/* ARP offload enable */
-uint dhd_arp_enable = true;
-module_param(dhd_arp_enable, uint, 0);
+uint brcmf_arp_enable = true;
+module_param(brcmf_arp_enable, uint, 0);
/* Global Pkt filter enable control */
-uint dhd_pkt_filter_enable = true;
-module_param(dhd_pkt_filter_enable, uint, 0);
+uint brcmf_pkt_filter_enable = true;
+module_param(brcmf_pkt_filter_enable, uint, 0);
/* Pkt filter init setup */
-uint dhd_pkt_filter_init;
-module_param(dhd_pkt_filter_init, uint, 0);
+uint brcmf_pkt_filter_init;
+module_param(brcmf_pkt_filter_init, uint, 0);
/* Pkt filter mode control */
-uint dhd_master_mode = true;
-module_param(dhd_master_mode, uint, 1);
-
-/* Watchdog thread priority, -1 to use kernel timer */
-int dhd_watchdog_prio = 97;
-module_param(dhd_watchdog_prio, int, 0);
-
-/* DPC thread priority, -1 to use tasklet */
-int dhd_dpc_prio = 98;
-module_param(dhd_dpc_prio, int, 0);
+uint brcmf_master_mode = true;
+module_param(brcmf_master_mode, uint, 0);
-/* DPC thread priority, -1 to use tasklet */
-extern int dhd_dongle_memsize;
-module_param(dhd_dongle_memsize, int, 0);
+module_param(brcmf_dongle_memsize, int, 0);
/* Contorl fw roaming */
-#ifdef CUSTOMER_HW2
-uint dhd_roam;
-#else
-uint dhd_roam = 1;
-#endif
+uint brcmf_roam = 1;
/* Control radio state */
-uint dhd_radio_up = 1;
+uint brcmf_radio_up = 1;
/* Network inteface name */
char iface_name[IFNAMSIZ] = "wlan";
@@ -331,252 +130,58 @@ module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
/* The following are specific to the SDIO dongle */
/* IOCTL response timeout */
-int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
+int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
/* Idle timeout for backplane clock */
-int dhd_idletime = DHD_IDLETIME_TICKS;
-module_param(dhd_idletime, int, 0);
+int brcmf_idletime = BRCMF_IDLETIME_TICKS;
+module_param(brcmf_idletime, int, 0);
/* Use polling */
-uint dhd_poll = false;
-module_param(dhd_poll, uint, 0);
-
-/* Use cfg80211 */
-uint dhd_cfg80211 = true;
-module_param(dhd_cfg80211, uint, 0);
+uint brcmf_poll;
+module_param(brcmf_poll, uint, 0);
/* Use interrupts */
-uint dhd_intr = true;
-module_param(dhd_intr, uint, 0);
+uint brcmf_intr = true;
+module_param(brcmf_intr, uint, 0);
/* SDIO Drive Strength (in milliamps) */
-uint dhd_sdiod_drive_strength = 6;
-module_param(dhd_sdiod_drive_strength, uint, 0);
+uint brcmf_sdiod_drive_strength = 6;
+module_param(brcmf_sdiod_drive_strength, uint, 0);
/* Tx/Rx bounds */
-extern uint dhd_txbound;
-extern uint dhd_rxbound;
-module_param(dhd_txbound, uint, 0);
-module_param(dhd_rxbound, uint, 0);
-
-/* Deferred transmits */
-extern uint dhd_deferred_tx;
-module_param(dhd_deferred_tx, uint, 0);
+module_param(brcmf_txbound, uint, 0);
+module_param(brcmf_rxbound, uint, 0);
#ifdef SDTEST
/* Echo packet generator (pkts/s) */
-uint dhd_pktgen;
-module_param(dhd_pktgen, uint, 0);
+uint brcmf_pktgen;
+module_param(brcmf_pktgen, uint, 0);
/* Echo packet len (0 => sawtooth, max 2040) */
-uint dhd_pktgen_len;
-module_param(dhd_pktgen_len, uint, 0);
-#endif
-
-#define FAVORITE_WIFI_CP (!!dhd_cfg80211)
-#define IS_CFG80211_FAVORITE() FAVORITE_WIFI_CP
-#define DBG_CFG80211_GET() ((dhd_cfg80211 & WL_DBG_MASK) >> 1)
-#define NO_FW_REQ() (dhd_cfg80211 & 0x80)
-
-/* Version string to report */
-#ifdef DHD_DEBUG
-#define DHD_COMPILED "\nCompiled in " SRCBASE
-#else
-#define DHD_COMPILED
+uint brcmf_pktgen_len;
+module_param(brcmf_pktgen_len, uint, 0);
#endif
-static void dhd_dpc(unsigned long data);
-/* forward decl */
-extern int dhd_wait_pend8021x(struct net_device *dev);
-
-#ifdef TOE
-#ifndef BDC
-#error TOE requires BDC
-#endif /* !BDC */
-static int dhd_toe_get(dhd_info_t *dhd, int idx, u32 *toe_ol);
-static int dhd_toe_set(dhd_info_t *dhd, int idx, u32 toe_ol);
-#endif /* TOE */
-
-static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
- wl_event_msg_t *event_ptr, void **data_ptr);
-
-#if defined(CONFIG_PM_SLEEP)
-static int dhd_sleep_pm_callback(struct notifier_block *nfb,
- unsigned long action, void *ignored)
-{
- switch (action) {
- case PM_HIBERNATION_PREPARE:
- case PM_SUSPEND_PREPARE:
- atomic_set(&dhd_mmc_suspend, true);
- return NOTIFY_OK;
- case PM_POST_HIBERNATION:
- case PM_POST_SUSPEND:
- atomic_set(&dhd_mmc_suspend, false);
- return NOTIFY_OK;
- }
- return 0;
-}
-
-static struct notifier_block dhd_sleep_pm_notifier = {
- .notifier_call = dhd_sleep_pm_callback,
- .priority = 0
-};
-
-extern int register_pm_notifier(struct notifier_block *nb);
-extern int unregister_pm_notifier(struct notifier_block *nb);
-#endif /* defined(CONFIG_PM_SLEEP) */
- /* && defined(DHD_GPL) */
-static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
-{
-#ifdef PKT_FILTER_SUPPORT
- DHD_TRACE(("%s: %d\n", __func__, value));
- /* 1 - Enable packet filter, only allow unicast packet to send up */
- /* 0 - Disable packet filter */
- if (dhd_pkt_filter_enable) {
- int i;
-
- for (i = 0; i < dhd->pktfilter_count; i++) {
- dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
- dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
- value, dhd_master_mode);
- }
- }
-#endif
-}
-
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-static int dhd_set_suspend(int value, dhd_pub_t *dhd)
-{
- int power_mode = PM_MAX;
- /* wl_pkt_filter_enable_t enable_parm; */
- char iovbuf[32];
- int bcn_li_dtim = 3;
-#ifdef CUSTOMER_HW2
- uint roamvar = 1;
-#endif /* CUSTOMER_HW2 */
-
- DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n",
- __func__, value, dhd->in_suspend));
-
- if (dhd && dhd->up) {
- if (value && dhd->in_suspend) {
-
- /* Kernel suspended */
- DHD_TRACE(("%s: force extra Suspend setting\n",
- __func__));
-
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
- (char *)&power_mode,
- sizeof(power_mode));
-
- /* Enable packet filter, only allow unicast
- packet to send up */
- dhd_set_packet_filter(1, dhd);
-
- /* if dtim skip setup as default force it
- * to wake each third dtim
- * for better power saving.
- * Note that side effect is chance to miss BC/MC
- * packet
- */
- if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1))
- bcn_li_dtim = 3;
- else
- bcn_li_dtim = dhd->dtim_skip;
- bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
- 4, iovbuf, sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
- /* Disable build-in roaming to allowed \
- * supplicant to take of romaing
- */
- bcm_mkiovar("roam_off", (char *)&roamvar, 4,
- iovbuf, sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf));
-#endif /* CUSTOMER_HW2 */
- } else {
-
- /* Kernel resumed */
- DHD_TRACE(("%s: Remove extra suspend setting\n",
- __func__));
-
- power_mode = PM_FAST;
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
- (char *)&power_mode,
- sizeof(power_mode));
-
- /* disable pkt filter */
- dhd_set_packet_filter(0, dhd);
-
- /* restore pre-suspend setting for dtim_skip */
- bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
- 4, iovbuf, sizeof(iovbuf));
-
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
- roamvar = 0;
- bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
- sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf));
-#endif /* CUSTOMER_HW2 */
- }
- }
-
- return 0;
-}
-
-static void dhd_suspend_resume_helper(struct dhd_info *dhd, int val)
-{
- dhd_pub_t *dhdp = &dhd->pub;
-
- dhd_os_proto_block(dhdp);
- /* Set flag when early suspend was called */
- dhdp->in_suspend = val;
- if (!dhdp->suspend_disable_flag)
- dhd_set_suspend(val, dhdp);
- dhd_os_proto_unblock(dhdp);
-}
-
-static void dhd_early_suspend(struct early_suspend *h)
-{
- struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
-
- DHD_TRACE(("%s: enter\n", __func__));
-
- if (dhd)
- dhd_suspend_resume_helper(dhd, 1);
-
-}
-
-static void dhd_late_resume(struct early_suspend *h)
-{
- struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
-
- DHD_TRACE(("%s: enter\n", __func__));
-
- if (dhd)
- dhd_suspend_resume_helper(dhd, 0);
-}
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+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:
*
- * dhd_timeout_start(&tmo, usec);
- * while (!dhd_timeout_expired(&tmo))
+ * brcmf_timeout_start(&tmo, usec);
+ * while (!brcmf_timeout_expired(&tmo))
* if (poll_something())
* break;
- * if (dhd_timeout_expired(&tmo))
+ * if (brcmf_timeout_expired(&tmo))
* fatal();
*/
-void dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
+void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec)
{
tmo->limit = usec;
tmo->increment = 0;
@@ -584,7 +189,7 @@ void dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
tmo->tick = 1000000 / HZ;
}
-int dhd_timeout_expired(dhd_timeout_t *tmo)
+int brcmf_timeout_expired(struct brcmf_timeout *tmo)
{
/* Does nothing the first call */
if (tmo->increment == 0) {
@@ -621,74 +226,68 @@ int dhd_timeout_expired(dhd_timeout_t *tmo)
return 0;
}
-static int dhd_net2idx(dhd_info_t *dhd, struct net_device *net)
+static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
{
int i = 0;
- ASSERT(dhd);
- while (i < DHD_MAX_IFS) {
- if (dhd->iflist[i] && (dhd->iflist[i]->net == net))
+ while (i < BRCMF_MAX_IFS) {
+ if (drvr_priv->iflist[i] && (drvr_priv->iflist[i]->net == net))
return i;
i++;
}
- return DHD_BAD_IF;
+ return BRCMF_BAD_IF;
}
-int dhd_ifname2idx(dhd_info_t *dhd, char *name)
+int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
{
- int i = DHD_MAX_IFS;
-
- ASSERT(dhd);
+ int i = BRCMF_MAX_IFS;
if (name == NULL || *name == '\0')
return 0;
while (--i > 0)
- if (dhd->iflist[i]
- && !strncmp(dhd->iflist[i]->name, name, IFNAMSIZ))
+ if (drvr_priv->iflist[i]
+ && !strncmp(drvr_priv->iflist[i]->name, name, IFNAMSIZ))
break;
- DHD_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
+ BRCMF_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
return i; /* default - the primary interface */
}
-char *dhd_ifname(dhd_pub_t *dhdp, int ifidx)
+char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
{
- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-
- ASSERT(dhd);
+ struct brcmf_info *drvr_priv = drvr->info;
- if (ifidx < 0 || ifidx >= DHD_MAX_IFS) {
- DHD_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
+ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+ BRCMF_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
return "<if_bad>";
}
- if (dhd->iflist[ifidx] == NULL) {
- DHD_ERROR(("%s: null i/f %d\n", __func__, ifidx));
+ if (drvr_priv->iflist[ifidx] == NULL) {
+ BRCMF_ERROR(("%s: null i/f %d\n", __func__, ifidx));
return "<if_null>";
}
- if (dhd->iflist[ifidx]->net)
- return dhd->iflist[ifidx]->net->name;
+ if (drvr_priv->iflist[ifidx]->net)
+ return drvr_priv->iflist[ifidx]->net->name;
return "<if_none>";
}
-static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
+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;
- wl_ioctl_t ioc;
+ struct brcmf_ioctl ioc;
char *buf, *bufp;
uint buflen;
int ret;
- ASSERT(dhd && dhd->iflist[ifidx]);
- dev = dhd->iflist[ifidx]->net;
+ dev = drvr_priv->iflist[ifidx]->net;
cnt = netdev_mc_count(dev);
/* Determine initial value of allmulti flag */
@@ -699,8 +298,8 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
bufp = buf = kmalloc(buflen, GFP_ATOMIC);
if (!bufp) {
- DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
- dhd_ifname(&dhd->pub, ifidx), cnt));
+ BRCMF_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
return;
}
@@ -720,15 +319,15 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
}
memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = WLC_SET_VAR;
+ ioc.cmd = BRCMF_C_SET_VAR;
ioc.buf = buf;
ioc.len = buflen;
ioc.set = true;
- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
if (ret < 0) {
- DHD_ERROR(("%s: set mcast_list failed, cnt %d\n",
- dhd_ifname(&dhd->pub, ifidx), cnt));
+ BRCMF_ERROR(("%s: set mcast_list failed, cnt %d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
allmulti = cnt ? true : allmulti;
}
@@ -742,32 +341,33 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
buflen = sizeof("allmulti") + sizeof(allmulti);
buf = kmalloc(buflen, GFP_ATOMIC);
if (!buf) {
- DHD_ERROR(("%s: out of memory for allmulti\n",
- dhd_ifname(&dhd->pub, ifidx)));
+ BRCMF_ERROR(("%s: out of memory for allmulti\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx)));
return;
}
allmulti = cpu_to_le32(allmulti);
- if (!bcm_mkiovar
+ if (!brcmu_mkiovar
("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
- DHD_ERROR(("%s: mkiovar failed for allmulti, datalen %d "
- "buflen %u\n", dhd_ifname(&dhd->pub, ifidx),
- (int)sizeof(allmulti), 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 = WLC_SET_VAR;
+ ioc.cmd = BRCMF_C_SET_VAR;
ioc.buf = buf;
ioc.len = buflen;
ioc.set = true;
- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
if (ret < 0) {
- DHD_ERROR(("%s: set allmulti %d failed\n",
- dhd_ifname(&dhd->pub, ifidx),
- le32_to_cpu(allmulti)));
+ BRCMF_ERROR(("%s: set allmulti %d failed\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx),
+ le32_to_cpu(allmulti)));
}
kfree(buf);
@@ -779,45 +379,44 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
allmulti = cpu_to_le32(allmulti);
memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = WLC_SET_PROMISC;
+ ioc.cmd = BRCMF_C_SET_PROMISC;
ioc.buf = &allmulti;
ioc.len = sizeof(allmulti);
ioc.set = true;
- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
if (ret < 0) {
- DHD_ERROR(("%s: set promisc %d failed\n",
- dhd_ifname(&dhd->pub, ifidx),
- le32_to_cpu(allmulti)));
+ BRCMF_ERROR(("%s: set promisc %d failed\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx),
+ le32_to_cpu(allmulti)));
}
}
-static int
-_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, u8 *addr)
+static int _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr)
{
char buf[32];
- wl_ioctl_t ioc;
+ struct brcmf_ioctl ioc;
int ret;
- DHD_TRACE(("%s enter\n", __func__));
- if (!bcm_mkiovar
+ BRCMF_TRACE(("%s enter\n", __func__));
+ if (!brcmu_mkiovar
("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) {
- DHD_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
- dhd_ifname(&dhd->pub, ifidx)));
+ BRCMF_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx)));
return -1;
}
memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = WLC_SET_VAR;
+ ioc.cmd = BRCMF_C_SET_VAR;
ioc.buf = buf;
ioc.len = 32;
ioc.set = true;
- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
if (ret < 0) {
- DHD_ERROR(("%s: set cur_etheraddr failed\n",
- dhd_ifname(&dhd->pub, ifidx)));
+ BRCMF_ERROR(("%s: set cur_etheraddr failed\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx)));
} else {
- memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
+ memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
}
return ret;
@@ -827,45 +426,44 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, u8 *addr)
extern struct net_device *ap_net_dev;
#endif
-static void dhd_op_if(dhd_if_t *ifp)
+/* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */
+static void brcmf_op_if(struct brcmf_if *ifp)
{
- dhd_info_t *dhd;
+ struct brcmf_info *drvr_priv;
int ret = 0, err = 0;
- ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */
-
- dhd = ifp->info;
+ drvr_priv = ifp->info;
- DHD_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
+ BRCMF_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
switch (ifp->state) {
- case WLC_E_IF_ADD:
+ case BRCMF_E_IF_ADD:
/*
* Delete the existing interface before overwriting it
- * in case we missed the WLC_E_IF_DEL event.
+ * in case we missed the BRCMF_E_IF_DEL event.
*/
if (ifp->net != NULL) {
- DHD_ERROR(("%s: ERROR: netdev:%s already exists, "
- "try free & unregister\n",
- __func__, ifp->net->name));
+ 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(dhd));
+ ifp->net = alloc_etherdev(sizeof(drvr_priv));
if (!ifp->net) {
- DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+ BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
ret = -ENOMEM;
}
if (ret == 0) {
strcpy(ifp->net->name, ifp->name);
- memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd));
- err = dhd_net_attach(&dhd->pub, ifp->idx);
+ memcpy(netdev_priv(ifp->net), &drvr_priv, sizeof(drvr_priv));
+ err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
if (err != 0) {
- DHD_ERROR(("%s: dhd_net_attach failed, "
- "err %d\n",
- __func__, err));
+ BRCMF_ERROR(("%s: brcmf_net_attach failed, "
+ "err %d\n",
+ __func__, err));
ret = -EOPNOTSUPP;
} else {
#ifdef SOFTAP
@@ -880,26 +478,25 @@ static void dhd_op_if(dhd_if_t *ifp)
wl0.1 is ready */
up(&ap_eth_sema);
#endif
- DHD_TRACE(("\n ==== pid:%x, net_device for "
- "if:%s created ===\n\n",
- current->pid, ifp->net->name));
+ BRCMF_TRACE(("\n ==== pid:%x, net_device for "
+ "if:%s created ===\n\n",
+ current->pid, ifp->net->name));
ifp->state = 0;
}
}
break;
- case WLC_E_IF_DEL:
+ case BRCMF_E_IF_DEL:
if (ifp->net != NULL) {
- DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
- __func__));
+ BRCMF_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
+ __func__));
netif_stop_queue(ifp->net);
unregister_netdev(ifp->net);
- ret = DHD_DEL_IF; /* Make sure the free_netdev()
+ ret = BRCMF_DEL_IF; /* Make sure the free_netdev()
is called */
}
break;
default:
- DHD_ERROR(("%s: bad op %d\n", __func__, ifp->state));
- ASSERT(!ifp->state);
+ BRCMF_ERROR(("%s: bad op %d\n", __func__, ifp->state));
break;
}
@@ -907,7 +504,7 @@ static void dhd_op_if(dhd_if_t *ifp)
if (ifp->net)
free_netdev(ifp->net);
- dhd->iflist[ifp->idx] = NULL;
+ drvr_priv->iflist[ifp->idx] = NULL;
kfree(ifp);
#ifdef SOFTAP
if (ifp->net == ap_net_dev)
@@ -917,9 +514,9 @@ static void dhd_op_if(dhd_if_t *ifp)
}
}
-static int _dhd_sysioc_thread(void *data)
+static int _brcmf_sysioc_thread(void *data)
{
- dhd_info_t *dhd = (dhd_info_t *) data;
+ struct brcmf_info *drvr_priv = (struct brcmf_info *) data;
int i;
#ifdef SOFTAP
bool in_ap = false;
@@ -927,46 +524,51 @@ static int _dhd_sysioc_thread(void *data)
allow_signal(SIGTERM);
- while (down_interruptible(&dhd->sysioc_sem) == 0) {
+ while (down_interruptible(&drvr_priv->sysioc_sem) == 0) {
if (kthread_should_stop())
break;
- for (i = 0; i < DHD_MAX_IFS; i++) {
- if (dhd->iflist[i]) {
+ 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 (dhd->iflist[i]->state)
- dhd_op_if(dhd->iflist[i]);
+ if (ifentry->state)
+ brcmf_op_if(ifentry);
#ifdef SOFTAP
- if (dhd->iflist[i] == NULL) {
- DHD_TRACE(("\n\n %s: interface %d "
- "removed!\n", __func__, i));
+ if (drvr_priv->iflist[i] == NULL) {
+ BRCMF_TRACE(("\n\n %s: interface %d "
+ "removed!\n", __func__,
+ i));
continue;
}
- if (in_ap && dhd->set_macaddress) {
- DHD_TRACE(("attempt to set MAC for %s "
- "in AP Mode," "blocked. \n",
- dhd->iflist[i]->net->name));
- dhd->set_macaddress = false;
+ 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 && dhd->set_multicast) {
- DHD_TRACE(("attempt to set MULTICAST list for %s" "in AP Mode, blocked. \n",
- dhd->iflist[i]->net->name));
- dhd->set_multicast = false;
+ 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 (dhd->set_multicast) {
- dhd->set_multicast = false;
- _dhd_set_multicast_list(dhd, i);
+ if (drvr_priv->set_multicast) {
+ drvr_priv->set_multicast = false;
+ _brcmf_set_multicast_list(drvr_priv, i);
}
- if (dhd->set_macaddress) {
- dhd->set_macaddress = false;
- _dhd_set_mac_address(dhd, i,
- dhd->macvalue);
+ if (drvr_priv->set_macaddress) {
+ drvr_priv->set_macaddress = false;
+ _brcmf_set_mac_address(drvr_priv, i,
+ drvr_priv->macvalue);
}
}
}
@@ -974,47 +576,44 @@ static int _dhd_sysioc_thread(void *data)
return 0;
}
-static int dhd_set_mac_address(struct net_device *dev, void *addr)
+static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr)
{
int ret = 0;
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
struct sockaddr *sa = (struct sockaddr *)addr;
int ifidx;
- ifidx = dhd_net2idx(dhd, dev);
- if (ifidx == DHD_BAD_IF)
+ ifidx = brcmf_net2idx(drvr_priv, dev);
+ if (ifidx == BRCMF_BAD_IF)
return -1;
- ASSERT(dhd->sysioc_tsk);
- memcpy(&dhd->macvalue, sa->sa_data, ETH_ALEN);
- dhd->set_macaddress = true;
- up(&dhd->sysioc_sem);
+ memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
+ drvr_priv->set_macaddress = true;
+ up(&drvr_priv->sysioc_sem);
return ret;
}
-static void dhd_set_multicast_list(struct net_device *dev)
+static void brcmf_netdev_set_multicast_list(struct net_device *dev)
{
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
int ifidx;
- ifidx = dhd_net2idx(dhd, dev);
- if (ifidx == DHD_BAD_IF)
+ ifidx = brcmf_net2idx(drvr_priv, dev);
+ if (ifidx == BRCMF_BAD_IF)
return;
- ASSERT(dhd->sysioc_tsk);
- dhd->set_multicast = true;
- up(&dhd->sysioc_sem);
+ drvr_priv->set_multicast = true;
+ up(&drvr_priv->sysioc_sem);
}
-int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
+int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
{
- int ret;
- dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
+ struct brcmf_info *drvr_priv = drvr->info;
/* Reject if down */
- if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN))
+ if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN))
return -ENODEV;
/* Update multicast statistic */
@@ -1023,143 +622,107 @@ int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
struct ethhdr *eh = (struct ethhdr *)pktdata;
if (is_multicast_ether_addr(eh->h_dest))
- dhdp->tx_multicast++;
+ drvr->tx_multicast++;
if (ntohs(eh->h_proto) == ETH_P_PAE)
- atomic_inc(&dhd->pend_8021x_cnt);
+ atomic_inc(&drvr_priv->pend_8021x_cnt);
}
/* If the protocol uses a data header, apply it */
- dhd_prot_hdrpush(dhdp, ifidx, pktbuf);
+ brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
/* Use bus module to send data frame */
-#ifdef BCMDBUS
- ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */);
-#else
- ret = dhd_bus_txdata(dhdp->bus, pktbuf);
-#endif /* BCMDBUS */
-
- return ret;
-}
-
-static inline void *
-osl_pkt_frmnative(struct sk_buff *skb)
-{
- return (void *)skb;
-}
-#define PKTFRMNATIVE(osh, skb) \
- osl_pkt_frmnative((struct sk_buff *)(skb))
-
-static inline struct sk_buff *
-osl_pkt_tonative(void *pkt)
-{
- return (struct sk_buff *)pkt;
+ return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf);
}
-#define PKTTONATIVE(osh, pkt) \
- osl_pkt_tonative((pkt))
-static int dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
+static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *net)
{
int ret;
- void *pktbuf;
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
int ifidx;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* Reject if down */
- if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) {
- DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
- __func__, dhd->pub.up, dhd->pub.busstate));
+ 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 = dhd_net2idx(dhd, net);
- if (ifidx == DHD_BAD_IF) {
- DHD_ERROR(("%s: bad ifidx %d\n", __func__, ifidx));
+ 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) < dhd->pub.hdrlen) {
+ if (skb_headroom(skb) < drvr_priv->pub.hdrlen) {
struct sk_buff *skb2;
- DHD_INFO(("%s: insufficient headroom\n",
- dhd_ifname(&dhd->pub, ifidx)));
- dhd->pub.tx_realloc++;
- skb2 = skb_realloc_headroom(skb, dhd->pub.hdrlen);
+ 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) {
- DHD_ERROR(("%s: skb_realloc_headroom failed\n",
- dhd_ifname(&dhd->pub, ifidx)));
+ BRCMF_ERROR(("%s: skb_realloc_headroom failed\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx)));
ret = -ENOMEM;
goto done;
}
}
- /* Convert to packet */
- pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb);
- if (!pktbuf) {
- DHD_ERROR(("%s: PKTFRMNATIVE failed\n",
- dhd_ifname(&dhd->pub, ifidx)));
- dev_kfree_skb_any(skb);
- ret = -ENOMEM;
- goto done;
- }
-
- ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf);
+ ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
done:
if (ret)
- dhd->pub.dstats.tx_dropped++;
+ drvr_priv->pub.dstats.tx_dropped++;
else
- dhd->pub.tx_packets++;
+ drvr_priv->pub.tx_packets++;
/* Return ok: we always eat the packet */
return 0;
}
-void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state)
+void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state)
{
struct net_device *net;
- dhd_info_t *dhd = dhdp->info;
+ struct brcmf_info *drvr_priv = drvr->info;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- dhdp->txoff = state;
- ASSERT(dhd && dhd->iflist[ifidx]);
- net = dhd->iflist[ifidx]->net;
+ drvr->txoff = state;
+ net = drvr_priv->iflist[ifidx]->net;
if (state == ON)
netif_stop_queue(net);
else
netif_wake_queue(net);
}
-void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
+void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
int numpkt)
{
- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
- struct sk_buff *skb;
+ struct brcmf_info *drvr_priv = drvr->info;
unsigned char *eth;
uint len;
void *data;
struct sk_buff *pnext, *save_pktbuf;
int i;
- dhd_if_t *ifp;
- wl_event_msg_t event;
-
- DHD_TRACE(("%s: Enter\n", __func__));
+ struct brcmf_if *ifp;
+ struct brcmf_event_msg event;
- save_pktbuf = pktbuf;
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) {
+ save_pktbuf = skb;
- pnext = pktbuf->next;
- pktbuf->next = NULL;
+ for (i = 0; skb && i < numpkt; i++, skb = pnext) {
- skb = PKTTONATIVE(dhdp->osh, pktbuf);
+ 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
@@ -1176,16 +739,15 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
eth = skb->data;
len = skb->len;
- ifp = dhd->iflist[ifidx];
+ ifp = drvr_priv->iflist[ifidx];
if (ifp == NULL)
- ifp = dhd->iflist[0];
+ ifp = drvr_priv->iflist[0];
- ASSERT(ifp);
skb->dev = ifp->net;
skb->protocol = eth_type_trans(skb, skb->dev);
if (skb->pkt_type == PACKET_MULTICAST)
- dhd->pub.rx_multicast++;
+ drvr_priv->pub.rx_multicast++;
skb->data = eth;
skb->len = len;
@@ -1194,20 +756,20 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
skb_pull(skb, ETH_HLEN);
/* Process special event packets and then discard them */
- if (ntohs(skb->protocol) == ETH_P_BRCM)
- dhd_wl_host_event(dhd, &ifidx,
+ if (ntohs(skb->protocol) == ETH_P_LINK_CTL)
+ brcmf_host_event(drvr_priv, &ifidx,
skb_mac_header(skb),
&event, &data);
- ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
- if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
- ifp = dhd->iflist[ifidx];
+ if (drvr_priv->iflist[ifidx] &&
+ !drvr_priv->iflist[ifidx]->state)
+ ifp = drvr_priv->iflist[ifidx];
if (ifp->net)
ifp->net->last_rx = jiffies;
- dhdp->dstats.rx_bytes += skb->len;
- dhdp->rx_packets++; /* Local count */
+ drvr->dstats.rx_bytes += skb->len;
+ drvr->rx_packets++; /* Local count */
if (in_interrupt()) {
netif_rx(skb);
@@ -1223,216 +785,83 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
}
}
-void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx)
-{
- /* Linux version has nothing to do */
- return;
-}
-
-void dhd_txcomplete(dhd_pub_t *dhdp, struct sk_buff *txp, bool success)
+void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
{
uint ifidx;
- dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
+ struct brcmf_info *drvr_priv = drvr->info;
struct ethhdr *eh;
u16 type;
- dhd_prot_hdrpull(dhdp, &ifidx, txp);
+ brcmf_proto_hdrpull(drvr, &ifidx, txp);
eh = (struct ethhdr *)(txp->data);
type = ntohs(eh->h_proto);
if (type == ETH_P_PAE)
- atomic_dec(&dhd->pend_8021x_cnt);
+ atomic_dec(&drvr_priv->pend_8021x_cnt);
}
-static struct net_device_stats *dhd_get_stats(struct net_device *net)
+static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net)
{
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
- dhd_if_t *ifp;
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ struct brcmf_if *ifp;
int ifidx;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- ifidx = dhd_net2idx(dhd, net);
- if (ifidx == DHD_BAD_IF)
+ ifidx = brcmf_net2idx(drvr_priv, net);
+ if (ifidx == BRCMF_BAD_IF)
return NULL;
- ifp = dhd->iflist[ifidx];
- ASSERT(dhd && ifp);
+ ifp = drvr_priv->iflist[ifidx];
- if (dhd->pub.up) {
+ if (drvr_priv->pub.up) {
/* Use the protocol to get dongle stats */
- dhd_prot_dstats(&dhd->pub);
+ brcmf_proto_dstats(&drvr_priv->pub);
}
/* Copy dongle stats to net device stats */
- ifp->stats.rx_packets = dhd->pub.dstats.rx_packets;
- ifp->stats.tx_packets = dhd->pub.dstats.tx_packets;
- ifp->stats.rx_bytes = dhd->pub.dstats.rx_bytes;
- ifp->stats.tx_bytes = dhd->pub.dstats.tx_bytes;
- ifp->stats.rx_errors = dhd->pub.dstats.rx_errors;
- ifp->stats.tx_errors = dhd->pub.dstats.tx_errors;
- ifp->stats.rx_dropped = dhd->pub.dstats.rx_dropped;
- ifp->stats.tx_dropped = dhd->pub.dstats.tx_dropped;
- ifp->stats.multicast = dhd->pub.dstats.multicast;
+ 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;
}
-static int dhd_watchdog_thread(void *data)
-{
- dhd_info_t *dhd = (dhd_info_t *) data;
-
- /* This thread doesn't need any user-level access,
- * so get rid of all our resources
- */
-#ifdef DHD_SCHED
- if (dhd_watchdog_prio > 0) {
- struct sched_param param;
- param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO) ?
- dhd_watchdog_prio : (MAX_RT_PRIO - 1);
- setScheduler(current, SCHED_FIFO, &param);
- }
-#endif /* DHD_SCHED */
-
- allow_signal(SIGTERM);
- /* Run until signal received */
- while (1) {
- if (kthread_should_stop())
- break;
- if (down_interruptible(&dhd->watchdog_sem) == 0) {
- if (dhd->pub.dongle_reset == false) {
- /* Call the bus module watchdog */
- dhd_bus_watchdog(&dhd->pub);
- }
- /* Count the tick for reference */
- dhd->pub.tickcnt++;
- } else
- break;
- }
- return 0;
-}
-
-static void dhd_watchdog(unsigned long data)
-{
- dhd_info_t *dhd = (dhd_info_t *) data;
-
- if (dhd->watchdog_tsk) {
- up(&dhd->watchdog_sem);
-
- /* Reschedule the watchdog */
- if (dhd->wd_timer_valid) {
- mod_timer(&dhd->timer,
- jiffies + dhd_watchdog_ms * HZ / 1000);
- }
- return;
- }
-
- /* Call the bus module watchdog */
- dhd_bus_watchdog(&dhd->pub);
-
- /* Count the tick for reference */
- dhd->pub.tickcnt++;
-
- /* Reschedule the watchdog */
- if (dhd->wd_timer_valid)
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-}
-
-static int dhd_dpc_thread(void *data)
-{
- dhd_info_t *dhd = (dhd_info_t *) data;
-
- /* This thread doesn't need any user-level access,
- * so get rid of all our resources
- */
-#ifdef DHD_SCHED
- if (dhd_dpc_prio > 0) {
- struct sched_param param;
- param.sched_priority =
- (dhd_dpc_prio <
- MAX_RT_PRIO) ? dhd_dpc_prio : (MAX_RT_PRIO - 1);
- setScheduler(current, SCHED_FIFO, &param);
- }
-#endif /* DHD_SCHED */
-
- allow_signal(SIGTERM);
- /* Run until signal received */
- while (1) {
- if (kthread_should_stop())
- break;
- if (down_interruptible(&dhd->dpc_sem) == 0) {
- /* Call bus dpc unless it indicated down
- (then clean stop) */
- if (dhd->pub.busstate != DHD_BUS_DOWN) {
- if (dhd_bus_dpc(dhd->pub.bus)) {
- up(&dhd->dpc_sem);
- }
- } else {
- dhd_bus_stop(dhd->pub.bus, true);
- }
- } else
- break;
- }
- return 0;
-}
-
-static void dhd_dpc(unsigned long data)
-{
- dhd_info_t *dhd;
-
- dhd = (dhd_info_t *) data;
-
- /* Call bus dpc unless it indicated down (then clean stop) */
- if (dhd->pub.busstate != DHD_BUS_DOWN) {
- if (dhd_bus_dpc(dhd->pub.bus))
- tasklet_schedule(&dhd->tasklet);
- } else {
- dhd_bus_stop(dhd->pub.bus, true);
- }
-}
-
-void dhd_sched_dpc(dhd_pub_t *dhdp)
-{
- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-
- if (dhd->dpc_tsk) {
- up(&dhd->dpc_sem);
- return;
- }
-
- tasklet_schedule(&dhd->tasklet);
-}
-
-#ifdef TOE
/* Retrieve current toe component enables, which are kept
as a bitmap in toe_ol iovar */
-static int dhd_toe_get(dhd_info_t *dhd, int ifidx, u32 *toe_ol)
+static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
{
- wl_ioctl_t ioc;
+ struct brcmf_ioctl ioc;
char buf[32];
int ret;
memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = WLC_GET_VAR;
+ ioc.cmd = BRCMF_C_GET_VAR;
ioc.buf = buf;
ioc.len = (uint) sizeof(buf);
ioc.set = false;
strcpy(buf, "toe_ol");
- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ 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) {
- DHD_ERROR(("%s: toe not supported by device\n",
- dhd_ifname(&dhd->pub, ifidx)));
+ BRCMF_ERROR(("%s: toe not supported by device\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx)));
return -EOPNOTSUPP;
}
- DHD_INFO(("%s: could not get toe_ol: ret=%d\n",
- dhd_ifname(&dhd->pub, ifidx), ret));
+ BRCMF_INFO(("%s: could not get toe_ol: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret));
return ret;
}
@@ -1442,15 +871,15 @@ static int dhd_toe_get(dhd_info_t *dhd, int ifidx, u32 *toe_ol)
/* Set current toe component enables in toe_ol iovar,
and set toe global enable iovar */
-static int dhd_toe_set(dhd_info_t *dhd, int ifidx, u32 toe_ol)
+static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
{
- wl_ioctl_t ioc;
+ struct brcmf_ioctl ioc;
char buf[32];
int toe, ret;
memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = WLC_SET_VAR;
+ ioc.cmd = BRCMF_C_SET_VAR;
ioc.buf = buf;
ioc.len = (uint) sizeof(buf);
ioc.set = true;
@@ -1460,10 +889,10 @@ static int dhd_toe_set(dhd_info_t *dhd, int ifidx, u32 toe_ol)
strcpy(buf, "toe_ol");
memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32));
- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
if (ret < 0) {
- DHD_ERROR(("%s: could not set toe_ol: ret=%d\n",
- dhd_ifname(&dhd->pub, ifidx), ret));
+ BRCMF_ERROR(("%s: could not set toe_ol: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret));
return ret;
}
@@ -1474,44 +903,42 @@ static int dhd_toe_set(dhd_info_t *dhd, int ifidx, u32 toe_ol)
strcpy(buf, "toe");
memcpy(&buf[sizeof("toe")], &toe, sizeof(u32));
- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
if (ret < 0) {
- DHD_ERROR(("%s: could not set toe: ret=%d\n",
- dhd_ifname(&dhd->pub, ifidx), ret));
+ BRCMF_ERROR(("%s: could not set toe: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret));
return ret;
}
return 0;
}
-#endif /* TOE */
-static void dhd_ethtool_get_drvinfo(struct net_device *net,
+static void brcmf_ethtool_get_drvinfo(struct net_device *net,
struct ethtool_drvinfo *info)
{
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- sprintf(info->driver, DRV_MODULE_NAME);
- sprintf(info->version, "%lu", dhd->pub.drv_version);
- sprintf(info->fw_version, "%s", wl_cfg80211_get_fwname());
- sprintf(info->bus_info, "%s", dev_name(&wl_cfg80211_get_sdio_func()->dev));
+ 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 dhd_ethtool_ops = {
- .get_drvinfo = dhd_ethtool_get_drvinfo
+struct ethtool_ops brcmf_ethtool_ops = {
+ .get_drvinfo = brcmf_ethtool_get_drvinfo
};
-static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
+static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
{
struct ethtool_drvinfo info;
char drvname[sizeof(info.driver)];
u32 cmd;
-#ifdef TOE
struct ethtool_value edata;
u32 toe_cmpnt, csum_dir;
int ret;
-#endif
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* all ethtool calls start with a cmd word */
if (copy_from_user(&cmd, uaddr, sizeof(u32)))
@@ -1529,36 +956,35 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
memset(&info, 0, sizeof(info));
info.cmd = cmd;
- /* if dhd requested, identify ourselves */
+ /* if requested, identify ourselves */
if (strcmp(drvname, "?dhd") == 0) {
sprintf(info.driver, "dhd");
- strcpy(info.version, EPI_VERSION_STR);
+ strcpy(info.version, BRCMF_VERSION_STR);
}
/* otherwise, require dongle to be up */
- else if (!dhd->pub.up) {
- DHD_ERROR(("%s: dongle is not up\n", __func__));
+ else if (!drvr_priv->pub.up) {
+ BRCMF_ERROR(("%s: dongle is not up\n", __func__));
return -ENODEV;
}
/* finally, report dongle driver type */
- else if (dhd->pub.iswl)
+ else if (drvr_priv->pub.iswl)
sprintf(info.driver, "wl");
else
sprintf(info.driver, "xx");
- sprintf(info.version, "%lu", dhd->pub.drv_version);
+ sprintf(info.version, "%lu", drvr_priv->pub.drv_version);
if (copy_to_user(uaddr, &info, sizeof(info)))
return -EFAULT;
- DHD_CTL(("%s: given %*s, returning %s\n", __func__,
- (int)sizeof(drvname), drvname, info.driver));
+ BRCMF_CTL(("%s: given %*s, returning %s\n", __func__,
+ (int)sizeof(drvname), drvname, info.driver));
break;
-#ifdef TOE
/* Get toe offload components from dongle */
case ETHTOOL_GRXCSUM:
case ETHTOOL_GTXCSUM:
- ret = dhd_toe_get(dhd, 0, &toe_cmpnt);
+ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
if (ret < 0)
return ret;
@@ -1579,7 +1005,7 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
return -EFAULT;
/* Read the current settings, update and write back */
- ret = dhd_toe_get(dhd, 0, &toe_cmpnt);
+ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
if (ret < 0)
return ret;
@@ -1591,22 +1017,21 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
else
toe_cmpnt &= ~csum_dir;
- ret = dhd_toe_set(dhd, 0, toe_cmpnt);
+ 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)
- dhd->iflist[0]->net->features |=
+ drvr_priv->iflist[0]->net->features |=
NETIF_F_IP_CSUM;
else
- dhd->iflist[0]->net->features &=
+ drvr_priv->iflist[0]->net->features &=
~NETIF_F_IP_CSUM;
}
break;
-#endif /* TOE */
default:
return -EOPNOTSUPP;
@@ -1615,10 +1040,11 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
return 0;
}
-static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
+static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr,
+ int cmd)
{
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
- dhd_ioctl_t ioc;
+ 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;
@@ -1626,22 +1052,14 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
int ifidx;
bool is_set_key_cmd;
- ifidx = dhd_net2idx(dhd, net);
- DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
+ ifidx = brcmf_net2idx(drvr_priv, net);
+ BRCMF_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
- if (ifidx == DHD_BAD_IF)
+ if (ifidx == BRCMF_BAD_IF)
return -1;
-#if defined(CONFIG_WIRELESS_EXT)
- /* linux wireless extensions */
- if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
- /* may recurse, do NOT lock */
- return wl_iw_ioctl(net, ifr, cmd);
- }
-#endif /* defined(CONFIG_WIRELESS_EXT) */
-
if (cmd == SIOCETHTOOL)
- return dhd_ethtool(dhd, (void *)ifr->ifr_data);
+ return brcmf_ethtool(drvr_priv, (void *)ifr->ifr_data);
if (cmd != SIOCDEVPRIVATE)
return -EOPNOTSUPP;
@@ -1649,14 +1067,14 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
memset(&ioc, 0, sizeof(ioc));
/* Copy the ioc control structure part of ioctl request */
- if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
+ 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, DHD_IOCTL_MAXLEN);
+ buflen = min_t(int, ioc.len, BRCMF_IOCTL_MAXLEN);
/* optimization for direct ioctl calls from kernel */
/*
if (segment_eq(get_fs(), KERNEL_DS)) {
@@ -1676,9 +1094,9 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
}
}
- /* To differentiate between wl and dhd read 4 more byes */
- if ((copy_from_user(&driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t),
- sizeof(uint)) != 0)) {
+ /* 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;
}
@@ -1688,39 +1106,41 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
goto done;
}
- /* check for local dhd ioctl and handle it */
- if (driver == DHD_IOCTL_MAGIC) {
- bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen);
+ /* 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)
- dhd->pub.bcmerror = bcmerror;
+ drvr_priv->pub.bcmerror = bcmerror;
goto done;
}
/* send to dongle (must be up, and wl) */
- if ((dhd->pub.busstate != DHD_BUS_DATA)) {
- DHD_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
+ if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
+ BRCMF_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
bcmerror = -EIO;
goto done;
}
- if (!dhd->pub.iswl) {
+ if (!drvr_priv->pub.iswl) {
bcmerror = -EIO;
goto done;
}
- /* Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to
- * prevent M4 encryption.
+ /*
+ * Intercept BRCMF_C_SET_KEY IOCTL - serialize M4 send and
+ * set key IOCTL to prevent M4 encryption.
*/
- is_set_key_cmd = ((ioc.cmd == WLC_SET_KEY) ||
- ((ioc.cmd == WLC_SET_VAR) &&
+ is_set_key_cmd = ((ioc.cmd == BRCMF_C_SET_KEY) ||
+ ((ioc.cmd == BRCMF_C_SET_VAR) &&
!(strncmp("wsec_key", ioc.buf, 9))) ||
- ((ioc.cmd == WLC_SET_VAR) &&
+ ((ioc.cmd == BRCMF_C_SET_VAR) &&
!(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
if (is_set_key_cmd)
- dhd_wait_pend8021x(net);
+ brcmf_netdev_wait_pend8021x(net);
bcmerror =
- dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
+ brcmf_proto_ioctl(&drvr_priv->pub, ifidx, (struct brcmf_ioctl *)&ioc,
+ buf, buflen);
done:
if (!bcmerror && buf && ioc.buf) {
@@ -1736,159 +1156,146 @@ done:
return bcmerror;
}
-static int dhd_stop(struct net_device *net)
+static int brcmf_netdev_stop(struct net_device *net)
{
#if !defined(IGNORE_ETH0_DOWN)
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- DHD_TRACE(("%s: Enter\n", __func__));
- if (IS_CFG80211_FAVORITE()) {
- wl_cfg80211_down();
- }
- if (dhd->pub.up == 0)
+ BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_cfg80211_down();
+ if (drvr_priv->pub.up == 0)
return 0;
/* Set state and stop OS transmissions */
- dhd->pub.up = 0;
+ drvr_priv->pub.up = 0;
netif_stop_queue(net);
#else
- DHD_ERROR(("BYPASS %s:due to BRCM compilation : under investigation\n",
- __func__));
+ BRCMF_ERROR(("BYPASS %s:due to BRCM compilation: under investigation\n",
+ __func__));
#endif /* !defined(IGNORE_ETH0_DOWN) */
return 0;
}
-static int dhd_open(struct net_device *net)
+static int brcmf_netdev_open(struct net_device *net)
{
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
-#ifdef TOE
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
u32 toe_ol;
-#endif
- int ifidx = dhd_net2idx(dhd, net);
+ int ifidx = brcmf_net2idx(drvr_priv, net);
s32 ret = 0;
- DHD_TRACE(("%s: ifidx %d\n", __func__, ifidx));
+ BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
if (ifidx == 0) { /* do it only for primary eth0 */
/* try to bring up bus */
- ret = dhd_bus_start(&dhd->pub);
+ ret = brcmf_bus_start(&drvr_priv->pub);
if (ret != 0) {
- DHD_ERROR(("%s: failed with code %d\n", __func__, ret));
+ BRCMF_ERROR(("%s: failed with code %d\n",
+ __func__, ret));
return -1;
}
- atomic_set(&dhd->pend_8021x_cnt, 0);
+ atomic_set(&drvr_priv->pend_8021x_cnt, 0);
- memcpy(net->dev_addr, dhd->pub.mac, ETH_ALEN);
+ memcpy(net->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
-#ifdef TOE
/* Get current TOE mode from dongle */
- if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0
+ if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
&& (toe_ol & TOE_TX_CSUM_OL) != 0)
- dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM;
+ drvr_priv->iflist[ifidx]->net->features |=
+ NETIF_F_IP_CSUM;
else
- dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM;
-#endif
+ drvr_priv->iflist[ifidx]->net->features &=
+ ~NETIF_F_IP_CSUM;
}
/* Allow transmit calls */
netif_start_queue(net);
- dhd->pub.up = 1;
- if (IS_CFG80211_FAVORITE()) {
- if (unlikely(wl_cfg80211_up())) {
- DHD_ERROR(("%s: failed to bring up cfg80211\n",
- __func__));
- return -1;
- }
+ 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
-dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
+brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, char *name,
u8 *mac_addr, u32 flags, u8 bssidx)
{
- dhd_if_t *ifp;
-
- DHD_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
+ struct brcmf_if *ifp;
- ASSERT(dhd && (ifidx < DHD_MAX_IFS));
+ BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
- ifp = dhd->iflist[ifidx];
- if (!ifp && !(ifp = kmalloc(sizeof(dhd_if_t), GFP_ATOMIC))) {
- DHD_ERROR(("%s: OOM - dhd_if_t\n", __func__));
- return -ENOMEM;
+ 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(dhd_if_t));
- ifp->info = dhd;
- dhd->iflist[ifidx] = ifp;
+ 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 = WLC_E_IF_ADD;
+ ifp->state = BRCMF_E_IF_ADD;
ifp->idx = ifidx;
- ASSERT(dhd->sysioc_tsk);
- up(&dhd->sysioc_sem);
+ up(&drvr_priv->sysioc_sem);
} else
ifp->net = (struct net_device *)handle;
return 0;
}
-void dhd_del_if(dhd_info_t *dhd, int ifidx)
+void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
{
- dhd_if_t *ifp;
+ struct brcmf_if *ifp;
- DHD_TRACE(("%s: idx %d\n", __func__, ifidx));
+ BRCMF_TRACE(("%s: idx %d\n", __func__, ifidx));
- ASSERT(dhd && ifidx && (ifidx < DHD_MAX_IFS));
- ifp = dhd->iflist[ifidx];
+ ifp = drvr_priv->iflist[ifidx];
if (!ifp) {
- DHD_ERROR(("%s: Null interface\n", __func__));
+ BRCMF_ERROR(("%s: Null interface\n", __func__));
return;
}
- ifp->state = WLC_E_IF_DEL;
+ ifp->state = BRCMF_E_IF_DEL;
ifp->idx = ifidx;
- ASSERT(dhd->sysioc_tsk);
- up(&dhd->sysioc_sem);
+ up(&drvr_priv->sysioc_sem);
}
-dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
+struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
{
- dhd_info_t *dhd = NULL;
+ struct brcmf_info *drvr_priv = NULL;
struct net_device *net;
- DHD_TRACE(("%s: Enter\n", __func__));
- /* updates firmware nvram path if it was provided as module
- paramters */
- if ((firmware_path != NULL) && (firmware_path[0] != '\0'))
- strcpy(fw_path, firmware_path);
- if ((nvram_path != NULL) && (nvram_path[0] != '\0'))
- strcpy(nv_path, nvram_path);
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* Allocate etherdev, including space for private structure */
- net = alloc_etherdev(sizeof(dhd));
+ net = alloc_etherdev(sizeof(drvr_priv));
if (!net) {
- DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+ BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
goto fail;
}
- /* Allocate primary dhd_info */
- dhd = kzalloc(sizeof(dhd_info_t), GFP_ATOMIC);
- if (!dhd) {
- DHD_ERROR(("%s: OOM - alloc dhd_info\n", __func__));
+ /* 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 dhd_info into the priv
+ * Save the brcmf_info into the priv
*/
- memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+ memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
/* Set network interface name if it was provided as module parameter */
if (iface_name[0]) {
@@ -1902,317 +1309,180 @@ dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
strcat(net->name, "%d");
}
- if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) ==
- DHD_BAD_IF)
+ 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(&dhd->proto_sem, 1);
+ sema_init(&drvr_priv->proto_sem, 1);
/* Initialize other structure content */
- init_waitqueue_head(&dhd->ioctl_resp_wait);
- init_waitqueue_head(&dhd->ctrl_wait);
-
- /* Initialize the spinlocks */
- spin_lock_init(&dhd->sdlock);
- spin_lock_init(&dhd->txqlock);
+ init_waitqueue_head(&drvr_priv->ioctl_resp_wait);
/* Link to info module */
- dhd->pub.info = dhd;
+ drvr_priv->pub.info = drvr_priv;
/* Link to bus module */
- dhd->pub.bus = bus;
- dhd->pub.hdrlen = bus_hdrlen;
+ drvr_priv->pub.bus = bus;
+ drvr_priv->pub.hdrlen = bus_hdrlen;
/* Attach and link in the protocol */
- if (dhd_prot_attach(&dhd->pub) != 0) {
- DHD_ERROR(("dhd_prot_attach failed\n"));
+ if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
+ BRCMF_ERROR(("brcmf_prot_attach failed\n"));
goto fail;
}
-#if defined(CONFIG_WIRELESS_EXT)
- /* Attach and link in the iw */
- if (wl_iw_attach(net, (void *)&dhd->pub) != 0) {
- DHD_ERROR(("wl_iw_attach failed\n"));
- goto fail;
- }
-#endif /* defined(CONFIG_WIRELESS_EXT) */
/* Attach and link in the cfg80211 */
- if (IS_CFG80211_FAVORITE()) {
- if (unlikely(wl_cfg80211_attach(net, &dhd->pub))) {
- DHD_ERROR(("wl_cfg80211_attach failed\n"));
- goto fail;
- }
- if (!NO_FW_REQ()) {
- strcpy(fw_path, wl_cfg80211_get_fwname());
- strcpy(nv_path, wl_cfg80211_get_nvramname());
- }
- }
-
- /* Set up the watchdog timer */
- init_timer(&dhd->timer);
- dhd->timer.data = (unsigned long) dhd;
- dhd->timer.function = dhd_watchdog;
-
- /* Initialize thread based operation and lock */
- sema_init(&dhd->sdsem, 1);
- if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0))
- dhd->threads_only = true;
- else
- dhd->threads_only = false;
-
- if (dhd_dpc_prio >= 0) {
- /* Initialize watchdog thread */
- sema_init(&dhd->watchdog_sem, 0);
- dhd->watchdog_tsk = kthread_run(dhd_watchdog_thread, dhd,
- "dhd_watchdog");
- if (IS_ERR(dhd->watchdog_tsk)) {
- printk(KERN_WARNING
- "dhd_watchdog thread failed to start\n");
- dhd->watchdog_tsk = NULL;
- }
- } else {
- dhd->watchdog_tsk = NULL;
- }
-
- /* Set up the bottom half handler */
- if (dhd_dpc_prio >= 0) {
- /* Initialize DPC thread */
- sema_init(&dhd->dpc_sem, 0);
- dhd->dpc_tsk = kthread_run(dhd_dpc_thread, dhd, "dhd_dpc");
- if (IS_ERR(dhd->dpc_tsk)) {
- printk(KERN_WARNING
- "dhd_dpc thread failed to start\n");
- dhd->dpc_tsk = NULL;
- }
- } else {
- tasklet_init(&dhd->tasklet, dhd_dpc, (unsigned long) dhd);
- dhd->dpc_tsk = NULL;
+ if (unlikely(brcmf_cfg80211_attach(net, &drvr_priv->pub))) {
+ BRCMF_ERROR(("wl_cfg80211_attach failed\n"));
+ goto fail;
}
- if (dhd_sysioc) {
- sema_init(&dhd->sysioc_sem, 0);
- dhd->sysioc_tsk = kthread_run(_dhd_sysioc_thread, dhd,
- "_dhd_sysioc");
- if (IS_ERR(dhd->sysioc_tsk)) {
+ 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
- "_dhd_sysioc thread failed to start\n");
- dhd->sysioc_tsk = NULL;
+ "_brcmf_sysioc thread failed to start\n");
+ drvr_priv->sysioc_tsk = NULL;
}
} else
- dhd->sysioc_tsk = NULL;
+ drvr_priv->sysioc_tsk = NULL;
/*
- * Save the dhd_info into the priv
+ * Save the brcmf_info into the priv
*/
- memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+ memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
- g_bus = bus;
-#endif
#if defined(CONFIG_PM_SLEEP)
- atomic_set(&dhd_mmc_suspend, false);
- if (!IS_CFG80211_FAVORITE())
- register_pm_notifier(&dhd_sleep_pm_notifier);
+ atomic_set(&brcmf_mmc_suspend, false);
#endif /* defined(CONFIG_PM_SLEEP) */
- /* && defined(DHD_GPL) */
- /* Init lock suspend to prevent kernel going to suspend */
-#ifdef CONFIG_HAS_EARLYSUSPEND
- dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
- dhd->early_suspend.suspend = dhd_early_suspend;
- dhd->early_suspend.resume = dhd_late_resume;
- register_early_suspend(&dhd->early_suspend);
-#endif
-
- return &dhd->pub;
+ return &drvr_priv->pub;
fail:
if (net)
free_netdev(net);
- if (dhd)
- dhd_detach(&dhd->pub);
+ if (drvr_priv)
+ brcmf_detach(&drvr_priv->pub);
return NULL;
}
-int dhd_bus_start(dhd_pub_t *dhdp)
+int brcmf_bus_start(struct brcmf_pub *drvr)
{
int ret = -1;
- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-#ifdef EMBEDDED_PLATFORM
- char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
- '\0' + bitvec */
-#endif /* EMBEDDED_PLATFORM */
-
- ASSERT(dhd);
-
- DHD_TRACE(("%s:\n", __func__));
-
- /* try to download image and nvram to the dongle */
- if (dhd->pub.busstate == DHD_BUS_DOWN) {
- if (!(dhd_bus_download_firmware(dhd->pub.bus,
- fw_path, nv_path))) {
- DHD_ERROR(("%s: dhdsdio_probe_download failed. "
- "firmware = %s nvram = %s\n",
- __func__, fw_path, nv_path));
- return -1;
- }
- }
+ struct brcmf_info *drvr_priv = drvr->info;
+ /* Room for "event_msgs" + '\0' + bitvec */
+ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
- /* Start the watchdog timer */
- dhd->pub.tickcnt = 0;
- dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
+ BRCMF_TRACE(("%s:\n", __func__));
/* Bring up the bus */
- ret = dhd_bus_init(&dhd->pub, true);
+ ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub, true);
if (ret != 0) {
- DHD_ERROR(("%s, dhd_bus_init failed %d\n", __func__, ret));
+ BRCMF_ERROR(("%s, brcmf_sdbrcm_bus_init failed %d\n", __func__,
+ ret));
return ret;
}
-#if defined(OOB_INTR_ONLY)
- /* Host registration for OOB interrupt */
- if (bcmsdh_register_oob_intr(dhdp)) {
- del_timer_sync(&dhd->timer);
- dhd->wd_timer_valid = false;
- DHD_ERROR(("%s Host failed to resgister for OOB\n", __func__));
- return -ENODEV;
- }
-
- /* Enable oob at firmware */
- dhd_enable_oob_intr(dhd->pub.bus, true);
-#endif /* defined(OOB_INTR_ONLY) */
/* If bus is not ready, can't come up */
- if (dhd->pub.busstate != DHD_BUS_DATA) {
- del_timer_sync(&dhd->timer);
- dhd->wd_timer_valid = false;
- DHD_ERROR(("%s failed bus is not ready\n", __func__));
+ if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) {
+ BRCMF_ERROR(("%s failed bus is not ready\n", __func__));
return -ENODEV;
}
-#ifdef EMBEDDED_PLATFORM
- bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
- sizeof(iovbuf));
- dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
- memcpy(dhdp->eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-
- setbit(dhdp->eventmask, WLC_E_SET_SSID);
- setbit(dhdp->eventmask, WLC_E_PRUNE);
- setbit(dhdp->eventmask, WLC_E_AUTH);
- setbit(dhdp->eventmask, WLC_E_REASSOC);
- setbit(dhdp->eventmask, WLC_E_REASSOC_IND);
- setbit(dhdp->eventmask, WLC_E_DEAUTH_IND);
- setbit(dhdp->eventmask, WLC_E_DISASSOC_IND);
- setbit(dhdp->eventmask, WLC_E_DISASSOC);
- setbit(dhdp->eventmask, WLC_E_JOIN);
- setbit(dhdp->eventmask, WLC_E_ASSOC_IND);
- setbit(dhdp->eventmask, WLC_E_PSK_SUP);
- setbit(dhdp->eventmask, WLC_E_LINK);
- setbit(dhdp->eventmask, WLC_E_NDIS_LINK);
- setbit(dhdp->eventmask, WLC_E_MIC_ERROR);
- setbit(dhdp->eventmask, WLC_E_PMKID_CACHE);
- setbit(dhdp->eventmask, WLC_E_TXFAIL);
- setbit(dhdp->eventmask, WLC_E_JOIN_START);
- setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
-#ifdef PNO_SUPPORT
- setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
-#endif /* PNO_SUPPORT */
+
+ 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 */
- dhdp->pktfilter_count = 1;
+ drvr->pktfilter_count = 1;
/* Setup filter to allow only unicast */
- dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00";
-#endif /* EMBEDDED_PLATFORM */
+ drvr->pktfilter[0] = "100 0 0 0 0x01 0x00";
/* Bus is ready, do any protocol initialization */
- ret = dhd_prot_init(&dhd->pub);
+ ret = brcmf_proto_init(&drvr_priv->pub);
if (ret < 0)
return ret;
return 0;
}
-int
-dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len,
- int set)
-{
- char buf[strlen(name) + 1 + cmd_len];
- int len = sizeof(buf);
- wl_ioctl_t ioc;
- int ret;
-
- len = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len);
-
- memset(&ioc, 0, sizeof(ioc));
-
- ioc.cmd = set ? WLC_SET_VAR : WLC_GET_VAR;
- ioc.buf = buf;
- ioc.len = len;
- ioc.set = set;
-
- ret = dhd_prot_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (!set && ret >= 0)
- memcpy(cmd_buf, buf, cmd_len);
-
- return ret;
-}
-
-static struct net_device_ops dhd_ops_pri = {
- .ndo_open = dhd_open,
- .ndo_stop = dhd_stop,
- .ndo_get_stats = dhd_get_stats,
- .ndo_do_ioctl = dhd_ioctl_entry,
- .ndo_start_xmit = dhd_start_xmit,
- .ndo_set_mac_address = dhd_set_mac_address,
- .ndo_set_multicast_list = dhd_set_multicast_list
+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 dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
+int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
{
- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
+ struct brcmf_info *drvr_priv = drvr->info;
struct net_device *net;
u8 temp_addr[ETH_ALEN] = {
0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
- DHD_TRACE(("%s: ifidx %d\n", __func__, ifidx));
-
- ASSERT(dhd && dhd->iflist[ifidx]);
+ BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
- net = dhd->iflist[ifidx]->net;
- ASSERT(net);
-
- ASSERT(!net->netdev_ops);
- net->netdev_ops = &dhd_ops_pri;
+ 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, dhd->pub.mac, ETH_ALEN);
+ memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN);
}
if (ifidx == 1) {
- DHD_TRACE(("%s ACCESS POINT MAC: \n", __func__));
+ 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 + dhd->pub.hdrlen;
- net->ethtool_ops = &dhd_ethtool_ops;
+ net->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
+ net->ethtool_ops = &brcmf_ethtool_ops;
- dhd->pub.rxsz = net->mtu + net->hard_header_len + dhd->pub.hdrlen;
+ 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) {
- DHD_ERROR(("%s: couldn't register the net device\n",
- __func__));
+ BRCMF_ERROR(("%s: couldn't register the net device\n",
+ __func__));
goto fail;
}
- DHD_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
+ BRCMF_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
return 0;
@@ -2221,221 +1491,139 @@ fail:
return -EBADE;
}
-void dhd_bus_detach(dhd_pub_t *dhdp)
+static void brcmf_bus_detach(struct brcmf_pub *drvr)
{
- dhd_info_t *dhd;
+ struct brcmf_info *drvr_priv;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (dhdp) {
- dhd = (dhd_info_t *) dhdp->info;
- if (dhd) {
+ if (drvr) {
+ drvr_priv = drvr->info;
+ if (drvr_priv) {
/* Stop the protocol module */
- dhd_prot_stop(&dhd->pub);
+ brcmf_proto_stop(&drvr_priv->pub);
/* Stop the bus module */
- dhd_bus_stop(dhd->pub.bus, true);
-#if defined(OOB_INTR_ONLY)
- bcmsdh_unregister_oob_intr();
-#endif /* defined(OOB_INTR_ONLY) */
-
- /* Clear the watchdog timer */
- del_timer_sync(&dhd->timer);
- dhd->wd_timer_valid = false;
+ brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus, true);
}
}
}
-void dhd_detach(dhd_pub_t *dhdp)
+void brcmf_detach(struct brcmf_pub *drvr)
{
- dhd_info_t *dhd;
+ struct brcmf_info *drvr_priv;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (dhdp) {
- dhd = (dhd_info_t *) dhdp->info;
- if (dhd) {
- dhd_if_t *ifp;
+ if (drvr) {
+ drvr_priv = drvr->info;
+ if (drvr_priv) {
+ struct brcmf_if *ifp;
int i;
-#if defined(CONFIG_HAS_EARLYSUSPEND)
- if (dhd->early_suspend.suspend)
- unregister_early_suspend(&dhd->early_suspend);
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
-
- for (i = 1; i < DHD_MAX_IFS; i++)
- if (dhd->iflist[i])
- dhd_del_if(dhd, i);
+ for (i = 1; i < BRCMF_MAX_IFS; i++)
+ if (drvr_priv->iflist[i])
+ brcmf_del_if(drvr_priv, i);
- ifp = dhd->iflist[0];
- ASSERT(ifp);
- if (ifp->net->netdev_ops == &dhd_ops_pri) {
- dhd_stop(ifp->net);
+ ifp = drvr_priv->iflist[0];
+ if (ifp->net->netdev_ops == &brcmf_netdev_ops_pri) {
+ brcmf_netdev_stop(ifp->net);
unregister_netdev(ifp->net);
}
- if (dhd->watchdog_tsk) {
- send_sig(SIGTERM, dhd->watchdog_tsk, 1);
- kthread_stop(dhd->watchdog_tsk);
- dhd->watchdog_tsk = NULL;
+ if (drvr_priv->sysioc_tsk) {
+ send_sig(SIGTERM, drvr_priv->sysioc_tsk, 1);
+ kthread_stop(drvr_priv->sysioc_tsk);
+ drvr_priv->sysioc_tsk = NULL;
}
- if (dhd->dpc_tsk) {
- send_sig(SIGTERM, dhd->dpc_tsk, 1);
- kthread_stop(dhd->dpc_tsk);
- dhd->dpc_tsk = NULL;
- } else
- tasklet_kill(&dhd->tasklet);
-
- if (dhd->sysioc_tsk) {
- send_sig(SIGTERM, dhd->sysioc_tsk, 1);
- kthread_stop(dhd->sysioc_tsk);
- dhd->sysioc_tsk = NULL;
- }
+ brcmf_bus_detach(drvr);
- dhd_bus_detach(dhdp);
+ if (drvr->prot)
+ brcmf_proto_detach(drvr);
- if (dhdp->prot)
- dhd_prot_detach(dhdp);
+ brcmf_cfg80211_detach();
-#if defined(CONFIG_WIRELESS_EXT)
- wl_iw_detach();
-#endif /* (CONFIG_WIRELESS_EXT) */
-
- if (IS_CFG80211_FAVORITE())
- wl_cfg80211_detach();
-
-#if defined(CONFIG_PM_SLEEP)
- if (!IS_CFG80211_FAVORITE())
- unregister_pm_notifier(&dhd_sleep_pm_notifier);
-#endif /* defined(CONFIG_PM_SLEEP) */
- /* && defined(DHD_GPL) */
free_netdev(ifp->net);
kfree(ifp);
- kfree(dhd);
+ kfree(drvr_priv);
}
}
}
-static void __exit dhd_module_cleanup(void)
+static void __exit brcmf_module_cleanup(void)
{
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- dhd_bus_unregister();
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
- wifi_del_dev();
-#endif
- /* Call customer gpio to turn off power with WL_REG_ON signal */
- dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+ brcmf_bus_unregister();
}
-static int __init dhd_module_init(void)
+static int __init brcmf_module_init(void)
{
int error;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- /* Sanity check on the module parameters */
- do {
- /* Both watchdog and DPC as tasklets are ok */
- if ((dhd_watchdog_prio < 0) && (dhd_dpc_prio < 0))
- break;
-
- /* If both watchdog and DPC are threads, TX must be deferred */
- if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0)
- && dhd_deferred_tx)
- break;
-
- DHD_ERROR(("Invalid module parameters.\n"));
- return -EINVAL;
- } while (0);
- /* Call customer gpio to turn on power with WL_REG_ON signal */
- dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON);
-
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
- sema_init(&wifi_control_sem, 0);
-
- error = wifi_add_dev();
- if (error) {
- DHD_ERROR(("%s: platform_driver_register failed\n", __func__));
- goto failed;
- }
-
- /* Waiting callback after platform_driver_register is done or
- exit with error */
- if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
- printk(KERN_ERR "%s: platform_driver_register timeout\n",
- __func__);
- /* remove device */
- wifi_del_dev();
- goto failed;
- }
-#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
-
- error = dhd_bus_register();
+ error = brcmf_bus_register();
if (error) {
- DHD_ERROR(("%s: sdio_register_driver failed\n", __func__));
+ BRCMF_ERROR(("%s: brcmf_bus_register failed\n", __func__));
goto failed;
}
- return error;
+ return 0;
failed:
- /* turn off power and exit */
- dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
return -EINVAL;
}
-module_init(dhd_module_init);
-module_exit(dhd_module_cleanup);
+module_init(brcmf_module_init);
+module_exit(brcmf_module_cleanup);
-/*
- * OS specific functions required to implement DHD driver in OS independent way
- */
-int dhd_os_proto_block(dhd_pub_t *pub)
+int brcmf_os_proto_block(struct brcmf_pub *drvr)
{
- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+ struct brcmf_info *drvr_priv = drvr->info;
- if (dhd) {
- down(&dhd->proto_sem);
+ if (drvr_priv) {
+ down(&drvr_priv->proto_sem);
return 1;
}
return 0;
}
-int dhd_os_proto_unblock(dhd_pub_t *pub)
+int brcmf_os_proto_unblock(struct brcmf_pub *drvr)
{
- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+ struct brcmf_info *drvr_priv = drvr->info;
- if (dhd) {
- up(&dhd->proto_sem);
+ if (drvr_priv) {
+ up(&drvr_priv->proto_sem);
return 1;
}
return 0;
}
-unsigned int dhd_os_get_ioctl_resp_timeout(void)
+unsigned int brcmf_os_get_ioctl_resp_timeout(void)
{
- return (unsigned int)dhd_ioctl_timeout_msec;
+ return (unsigned int)brcmf_ioctl_timeout_msec;
}
-void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
+void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
{
- dhd_ioctl_timeout_msec = (int)timeout_msec;
+ brcmf_ioctl_timeout_msec = (int)timeout_msec;
}
-int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
+int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
+ bool *pending)
{
- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+ struct brcmf_info *drvr_priv = drvr->info;
DECLARE_WAITQUEUE(wait, current);
- int timeout = dhd_ioctl_timeout_msec;
+ 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(&dhd->ioctl_resp_wait, &wait);
+ add_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
while (!(*condition) && (!signal_pending(current) && timeout))
@@ -2445,366 +1633,59 @@ int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
*pending = true;
set_current_state(TASK_RUNNING);
- remove_wait_queue(&dhd->ioctl_resp_wait, &wait);
+ remove_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
return timeout;
}
-int dhd_os_ioctl_resp_wake(dhd_pub_t *pub)
+int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr)
{
- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+ struct brcmf_info *drvr_priv = drvr->info;
- if (waitqueue_active(&dhd->ioctl_resp_wait))
- wake_up_interruptible(&dhd->ioctl_resp_wait);
+ if (waitqueue_active(&drvr_priv->ioctl_resp_wait))
+ wake_up_interruptible(&drvr_priv->ioctl_resp_wait);
return 0;
}
-void dhd_os_wd_timer(void *bus, uint wdtick)
-{
- dhd_pub_t *pub = bus;
- static uint save_dhd_watchdog_ms;
- dhd_info_t *dhd = (dhd_info_t *) pub->info;
-
- /* don't start the wd until fw is loaded */
- if (pub->busstate == DHD_BUS_DOWN)
- return;
-
- /* Totally stop the timer */
- if (!wdtick && dhd->wd_timer_valid == true) {
- del_timer_sync(&dhd->timer);
- dhd->wd_timer_valid = false;
- save_dhd_watchdog_ms = wdtick;
- return;
- }
-
- if (wdtick) {
- dhd_watchdog_ms = (uint) wdtick;
-
- if (save_dhd_watchdog_ms != dhd_watchdog_ms) {
-
- if (dhd->wd_timer_valid == true)
- /* Stop timer and restart at new value */
- del_timer_sync(&dhd->timer);
-
- /* Create timer again when watchdog period is
- dynamically changed or in the first instance
- */
- dhd->timer.expires =
- jiffies + dhd_watchdog_ms * HZ / 1000;
- add_timer(&dhd->timer);
-
- } else {
- /* Re arm the timer, at last watchdog period */
- mod_timer(&dhd->timer,
- jiffies + dhd_watchdog_ms * HZ / 1000);
- }
-
- dhd->wd_timer_valid = true;
- save_dhd_watchdog_ms = wdtick;
- }
-}
-
-void *dhd_os_open_image(char *filename)
-{
- struct file *fp;
-
- if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
- return wl_cfg80211_request_fw(filename);
-
- fp = filp_open(filename, O_RDONLY, 0);
- /*
- * 2.6.11 (FC4) supports filp_open() but later revs don't?
- * Alternative:
- * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
- * ???
- */
- if (IS_ERR(fp))
- fp = NULL;
-
- return fp;
-}
-
-int dhd_os_get_image_block(char *buf, int len, void *image)
-{
- struct file *fp = (struct file *)image;
- int rdlen;
-
- if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
- return wl_cfg80211_read_fw(buf, len);
-
- if (!image)
- return 0;
-
- rdlen = kernel_read(fp, fp->f_pos, buf, len);
- if (rdlen > 0)
- fp->f_pos += rdlen;
-
- return rdlen;
-}
-
-void dhd_os_close_image(void *image)
-{
- if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
- return wl_cfg80211_release_fw();
- if (image)
- filp_close((struct file *)image, NULL);
-}
-
-void dhd_os_sdlock(dhd_pub_t *pub)
-{
- dhd_info_t *dhd;
-
- dhd = (dhd_info_t *) (pub->info);
-
- if (dhd->threads_only)
- down(&dhd->sdsem);
- else
- spin_lock_bh(&dhd->sdlock);
-}
-
-void dhd_os_sdunlock(dhd_pub_t *pub)
-{
- dhd_info_t *dhd;
-
- dhd = (dhd_info_t *) (pub->info);
-
- if (dhd->threads_only)
- up(&dhd->sdsem);
- else
- spin_unlock_bh(&dhd->sdlock);
-}
-
-void dhd_os_sdlock_txq(dhd_pub_t *pub)
-{
- dhd_info_t *dhd;
-
- dhd = (dhd_info_t *) (pub->info);
- spin_lock_bh(&dhd->txqlock);
-}
-
-void dhd_os_sdunlock_txq(dhd_pub_t *pub)
-{
- dhd_info_t *dhd;
-
- dhd = (dhd_info_t *) (pub->info);
- spin_unlock_bh(&dhd->txqlock);
-}
-
-void dhd_os_sdlock_rxq(dhd_pub_t *pub)
-{
-}
-
-void dhd_os_sdunlock_rxq(dhd_pub_t *pub)
-{
-}
-
-void dhd_os_sdtxlock(dhd_pub_t *pub)
-{
- dhd_os_sdlock(pub);
-}
-
-void dhd_os_sdtxunlock(dhd_pub_t *pub)
-{
- dhd_os_sdunlock(pub);
-}
-
-static int
-dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
- wl_event_msg_t *event, void **data)
+static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
+ struct brcmf_event_msg *event, void **data)
{
int bcmerror = 0;
- ASSERT(dhd != NULL);
-
- bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data);
+ bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
if (bcmerror != 0)
return bcmerror;
-#if defined(CONFIG_WIRELESS_EXT)
- if (!IS_CFG80211_FAVORITE()) {
- if ((dhd->iflist[*ifidx] == NULL)
- || (dhd->iflist[*ifidx]->net == NULL)) {
- DHD_ERROR(("%s Exit null pointer\n", __func__));
- return bcmerror;
- }
-
- if (dhd->iflist[*ifidx]->net)
- wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
- }
-#endif /* defined(CONFIG_WIRELESS_EXT) */
-
- if (IS_CFG80211_FAVORITE()) {
- ASSERT(dhd->iflist[*ifidx] != NULL);
- ASSERT(dhd->iflist[*ifidx]->net != NULL);
- if (dhd->iflist[*ifidx]->net)
- wl_cfg80211_event(dhd->iflist[*ifidx]->net, event,
- *data);
- }
+ if (drvr_priv->iflist[*ifidx]->net)
+ brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net,
+ event, *data);
return bcmerror;
}
-/* send up locally generated event */
-void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
-{
- switch (be32_to_cpu(event->event_type)) {
- default:
- break;
- }
-}
-
-void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
+int brcmf_netdev_reset(struct net_device *dev, u8 flag)
{
- struct dhd_info *dhdinfo = dhd->info;
- dhd_os_sdunlock(dhd);
- wait_event_interruptible_timeout(dhdinfo->ctrl_wait,
- (*lockvar == false), HZ * 2);
- dhd_os_sdlock(dhd);
- return;
-}
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
-void dhd_wait_event_wakeup(dhd_pub_t *dhd)
-{
- struct dhd_info *dhdinfo = dhd->info;
- if (waitqueue_active(&dhdinfo->ctrl_wait))
- wake_up_interruptible(&dhdinfo->ctrl_wait);
- return;
-}
-
-int dhd_dev_reset(struct net_device *dev, u8 flag)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
- /* Turning off watchdog */
- if (flag)
- dhd_os_wd_timer(&dhd->pub, 0);
-
- dhd_bus_devreset(&dhd->pub, flag);
-
- /* Turning on watchdog back */
- if (!flag)
- dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
- DHD_ERROR(("%s: WLAN OFF DONE\n", __func__));
+ brcmf_bus_devreset(&drvr_priv->pub, flag);
return 1;
}
-int net_os_set_suspend_disable(struct net_device *dev, int val)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int ret = 0;
-
- if (dhd) {
- ret = dhd->pub.suspend_disable_flag;
- dhd->pub.suspend_disable_flag = val;
- }
- return ret;
-}
-
-int net_os_set_suspend(struct net_device *dev, int val)
+static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
{
- int ret = 0;
-#if defined(CONFIG_HAS_EARLYSUSPEND)
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
- if (dhd) {
- dhd_os_proto_block(&dhd->pub);
- ret = dhd_set_suspend(val, &dhd->pub);
- dhd_os_proto_unblock(&dhd->pub);
- }
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
- return ret;
-}
-
-int net_os_set_dtim_skip(struct net_device *dev, int val)
-{
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
-
- if (dhd)
- dhd->pub.dtim_skip = val;
-
- return 0;
-}
-
-int net_os_set_packet_filter(struct net_device *dev, int val)
-{
- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
- int ret = 0;
-
- /* Packet filtering is set only if we still in early-suspend and
- * we need either to turn it ON or turn it OFF
- * We can always turn it OFF in case of early-suspend, but we turn it
- * back ON only if suspend_disable_flag was not set
- */
- if (dhd && dhd->pub.up) {
- dhd_os_proto_block(&dhd->pub);
- if (dhd->pub.in_suspend) {
- if (!val || (val && !dhd->pub.suspend_disable_flag))
- dhd_set_packet_filter(val, &dhd->pub);
- }
- dhd_os_proto_unblock(&dhd->pub);
- }
- return ret;
-}
-
-void dhd_dev_init_ioctl(struct net_device *dev)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
- dhd_preinit_ioctls(&dhd->pub);
-}
-
-#ifdef PNO_SUPPORT
-/* Linux wrapper to call common dhd_pno_clean */
-int dhd_dev_pno_reset(struct net_device *dev)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
- return dhd_pno_clean(&dhd->pub);
-}
-
-/* Linux wrapper to call common dhd_pno_enable */
-int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
- return dhd_pno_enable(&dhd->pub, pfn_enabled);
-}
-
-/* Linux wrapper to call common dhd_pno_set */
-int
-dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t *ssids_local, int nssid,
- unsigned char scan_fr)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
- return dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr);
-}
-
-/* Linux wrapper to get pno status */
-int dhd_dev_get_pno_status(struct net_device *dev)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
- return dhd_pno_get_status(&dhd->pub);
-}
-
-#endif /* PNO_SUPPORT */
-
-static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
-{
- return atomic_read(&dhd->pend_8021x_cnt);
+ return atomic_read(&drvr_priv->pend_8021x_cnt);
}
#define MAX_WAIT_FOR_8021X_TX 10
-int dhd_wait_pend8021x(struct net_device *dev)
+int brcmf_netdev_wait_pend8021x(struct net_device *dev)
{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(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 = dhd_get_pend_8021x_cnt(dhd);
+ int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
while (ntimes && pend) {
if (pend) {
@@ -2813,20 +1694,13 @@ int dhd_wait_pend8021x(struct net_device *dev)
set_current_state(TASK_RUNNING);
ntimes--;
}
- pend = dhd_get_pend_8021x_cnt(dhd);
+ pend = brcmf_get_pend_8021x_cnt(drvr_priv);
}
return pend;
}
-void wl_os_wd_timer(struct net_device *ndev, uint wdtick)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(ndev);
-
- dhd_os_wd_timer(&dhd->pub, wdtick);
-}
-
-#ifdef DHD_DEBUG
-int write_to_file(dhd_pub_t *dhd, u8 *buf, int size)
+#ifdef BCMDBG
+int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size)
{
int ret = 0;
struct file *fp;
@@ -2840,7 +1714,7 @@ int write_to_file(dhd_pub_t *dhd, u8 *buf, int size)
/* open file to write */
fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
if (!fp) {
- DHD_ERROR(("%s: open file error\n", __func__));
+ BRCMF_ERROR(("%s: open file error\n", __func__));
ret = -1;
goto exit;
}
@@ -2859,4 +1733,4 @@ exit:
return ret;
}
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c
deleted file mode 100644
index c66f1c2941e2..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c
+++ /dev/null
@@ -1,25 +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/module.h>
-#include <linux/sched.h>
-
-int setScheduler(struct task_struct *p, int policy, struct sched_param *param)
-{
- int rc = 0;
- rc = sched_setscheduler(p, policy, param);
- return rc;
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
index 030d5ffb0e83..ff788b37afdc 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
@@ -14,11 +14,8 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _dhd_proto_h_
-#define _dhd_proto_h_
-
-#include <dhdioctl.h>
-#include <wlioctl.h>
+#ifndef _BRCMF_PROTO_H_
+#define _BRCMF_PROTO_H_
#ifndef IOCTL_RESP_TIMEOUT
#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */
@@ -29,62 +26,50 @@
#endif
/*
- * Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
+ * Exported from the brcmf protocol module (brcmf_cdc)
*/
/* Linkage, sets prot link and updates hdrlen in pub */
-extern int dhd_prot_attach(dhd_pub_t *dhdp);
+extern int brcmf_proto_attach(struct brcmf_pub *drvr);
-/* Unlink, frees allocated protocol memory (including dhd_prot) */
-extern void dhd_prot_detach(dhd_pub_t *dhdp);
+/* Unlink, frees allocated protocol memory (including brcmf_proto) */
+extern void brcmf_proto_detach(struct brcmf_pub *drvr);
/* Initialize protocol: sync w/dongle state.
* Sets dongle media info (iswl, drv_version, mac address).
*/
-extern int dhd_prot_init(dhd_pub_t *dhdp);
+extern int brcmf_proto_init(struct brcmf_pub *drvr);
/* Stop protocol: sync w/dongle state. */
-extern void dhd_prot_stop(dhd_pub_t *dhdp);
+extern void brcmf_proto_stop(struct brcmf_pub *drvr);
/* Add any protocol-specific data header.
* Caller must reserve prot_hdrlen prepend space.
*/
-extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, struct sk_buff *txp);
+extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
+ struct sk_buff *txp);
/* Remove any protocol-specific data header. */
-extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, struct sk_buff *rxp);
+extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx,
+ struct sk_buff *rxp);
/* Use protocol to issue ioctl to dongle */
-extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc,
- void *buf, int len);
-
-/* Check for and handle local prot-specific iovar commands */
-extern int dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
- void *params, int plen, void *arg, int len,
- bool set);
+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 dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+extern void brcmf_proto_dump(struct brcmf_pub *drvr,
+ struct brcmu_strbuf *strbuf);
/* Update local copy of dongle statistics */
-extern void dhd_prot_dstats(dhd_pub_t *dhdp);
+extern void brcmf_proto_dstats(struct brcmf_pub *drvr);
-extern int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf,
- uint buflen);
+extern int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc,
+ void *buf, uint buflen);
-extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
+extern int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr);
-/********************************
- * For version-string expansion *
- */
-#if defined(BDC)
-#define DHD_PROTOCOL "bdc"
-#elif defined(CDC)
-#define DHD_PROTOCOL "cdc"
-#elif defined(RNDIS)
-#define DHD_PROTOCOL "rndis"
-#else
-#define DHD_PROTOCOL "unknown"
-#endif /* proto */
-
-#endif /* _dhd_proto_h_ */
+extern int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx,
+ uint cmd, void *buf, uint len);
+
+#endif /* _BRCMF_PROTO_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
index a71c6f8ee8a3..7fa95b6213c5 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
@@ -16,47 +16,145 @@
#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 <bcmdefs.h>
-#include <bcmsdh.h>
-
-#ifdef BCMEMBEDIMAGE
-#include BCMEMBEDIMAGE
-#endif /* BCMEMBEDIMAGE */
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmdevs.h>
-
-#include <hndsoc.h>
-#ifdef DHD_DEBUG
-#include <hndrte_armtrap.h>
-#include <hndrte_cons.h>
-#endif /* DHD_DEBUG */
-#include <sbchipc.h>
-#include <sbhnddma.h>
-
-#include <sdio.h>
-#include <sbsdio.h>
-#include <sbsdpcmdev.h>
-#include <bcmsdpcm.h>
-
-#include <proto/802.11.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <dhdioctl.h>
-#include <sdiovar.h>
-#include <bcmchip.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;
+};
-#ifndef DHDSDIO_MEM_DUMP_FNAME
-#define DHDSDIO_MEM_DUMP_FNAME "mem_dump"
-#endif
+#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 */
@@ -65,47 +163,239 @@
#define TXRETRIES 2 /* # of retries for tx frames */
-#if defined(CONFIG_MACH_SANDGATE2G)
-#define DHD_RXBOUND 250 /* Default for max rx frames in
+#define BRCMF_RXBOUND 50 /* Default for max rx frames in
one scheduling */
-#else
-#define DHD_RXBOUND 50 /* Default for max rx frames in
- one scheduling */
-#endif /* defined(CONFIG_MACH_SANDGATE2G) */
-#define DHD_TXBOUND 20 /* Default for max tx frames in
+#define BRCMF_TXBOUND 20 /* Default for max tx frames in
one scheduling */
-#define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */
+#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 */
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN 32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
+#ifndef BRCMF_FIRSTREAD
+#define BRCMF_FIRSTREAD 32
#endif
-#ifndef DHD_FIRSTREAD
-#define DHD_FIRSTREAD 32
-#endif
-#if !ISPOWEROF2(DHD_FIRSTREAD)
-#error DHD_FIRSTREAD is not a power of 2!
+#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 + DHD_SDALIGN)
+#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN)
#else
-#define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN)
+#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
@@ -117,7 +407,7 @@
#define MAX_RX_DATASZ 2048
/* Maximum milliseconds to wait for F2 to come up */
-#define DHD_WAIT_F2RDY 3000
+#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
@@ -130,13 +420,48 @@
#endif
/* Value for ChipClockCSR during initial setup */
-#define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \
+#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \
SBSDIO_ALP_AVAIL_REQ)
-#define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
/* 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
*/
@@ -144,21 +469,130 @@
(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
((prio^2)) : (prio))
-DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
- uint len);
+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 DHD_DEBUG
+#ifdef BCMDBG
/* Device console log buffer state */
-typedef struct dhd_console {
+struct brcmf_console {
uint count; /* Poll interval msec counter */
uint log_addr; /* Log struct address (fixed) */
- hndrte_log_t log; /* Log struct (host copy) */
+ 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 */
-} dhd_console_t;
-#endif /* DHD_DEBUG */
+};
+#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 {
@@ -167,7 +601,7 @@ struct chip_info {
u32 cccorebase;
u32 ccrev;
u32 cccaps;
- u32 buscorebase;
+ u32 buscorebase; /* 32 bits backplane bus address */
u32 buscorerev;
u32 buscoretype;
u32 ramcorebase;
@@ -177,19 +611,14 @@ struct chip_info {
};
/* Private data for SDIO bus interaction */
-typedef struct dhd_bus {
- dhd_pub_t *dhd;
+struct brcmf_bus {
+ struct brcmf_pub *drvr;
- bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */
+ 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 sbaddr; /* Current SB window pointer (-1, invalid) */
- sdpcmd_regs_t *regs; /* Registers for SDIO core */
- uint sdpcmrev; /* SDIO core revision */
- uint armrev; /* CPU core revision */
- uint ramrev; /* SOCRAM core revision */
u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
u32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
@@ -199,10 +628,7 @@ typedef struct dhd_bus {
bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
bool fcstate; /* State of dongle flow-control */
- u16 cl_devid; /* cached devid for dhdsdio_probe_attach() */
- char *fw_path; /* module_param: path to firmware image */
- char *nv_path; /* module_param: path to nvram vars file */
- const char *nvram_params; /* user specified nvram params. */
+ u16 cl_devid; /* cached devid for brcmf_sdio_probe_attach() */
uint blocksize; /* Block size of SDIO transfers */
uint roundup; /* Max roundup limit */
@@ -212,7 +638,7 @@ typedef struct dhd_bus {
u8 tx_seq; /* Transmit sequence number (next) */
u8 tx_max; /* Maximum transmit sequence allowed */
- u8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
+ 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) */
@@ -242,27 +668,23 @@ typedef struct dhd_bus {
uint polltick; /* Tick counter */
uint pollcnt; /* Count of active polls */
-#ifdef DHD_DEBUG
- dhd_console_t console; /* Console output polling support */
+#ifdef BCMDBG
+ struct brcmf_console console; /* Console output polling support */
uint console_addr; /* Console address from shared struct */
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
- uint regfails; /* Count of R_REG/W_REG failures */
+ 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_divisor; /* Speed control to bus driver */
- s32 sd_mode; /* Mode control to bus driver */
- s32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
- bool use_rxchain; /* If dhd should use PKT chains */
+ 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 */
- uint prev_rxlim_hit; /* Is prev rx limit exceeded
- (per dpc schedule) */
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;
@@ -314,7 +736,68 @@ typedef struct dhd_bus {
u8 *ctrl_frame_buf;
u32 ctrl_frame_len;
bool ctrl_frame_stat;
-} dhd_bus_t;
+
+ 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
@@ -322,29 +805,45 @@ typedef struct dhd_bus {
#define CLK_PENDING 2 /* Not used yet */
#define CLK_AVAIL 3
-#define DHD_NOPMU(dhd) (false)
+#define BRCMF_NOPMU(brcmf) (false)
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
static int qcount[NUMPRIO];
static int tx_packets[NUMPRIO];
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
/* Deferred transmit */
-const uint dhd_deferred_tx = 1;
+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);
-extern uint dhd_watchdog_ms;
-extern void dhd_os_wd_timer(void *bus, uint wdtick);
+/* 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 dhd_txbound;
-uint dhd_rxbound;
-uint dhd_txminmax;
+uint brcmf_txbound;
+uint brcmf_rxbound;
+uint brcmf_txminmax;
/* override the RAM size if possible */
#define DONGLE_MIN_MEMSIZE (128 * 1024)
-int dhd_dongle_memsize;
+int brcmf_dongle_memsize;
-static bool dhd_alignctl;
+static bool brcmf_alignctl;
static bool sd1idle;
@@ -352,9 +851,7 @@ static bool retrydata;
#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
static const uint watermark = 8;
-static const uint firstread = DHD_FIRSTREAD;
-
-#define HDATLEN (firstread - (SDPCM_HDRLEN))
+static const uint firstread = BRCMF_FIRSTREAD;
/* Retry count for register access failures */
static const uint retry_limit = 2;
@@ -364,20 +861,11 @@ static bool forcealign;
#define ALIGNMENT 4
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
-#endif
-
-#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
-#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
-#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
#define PKTALIGN(_p, _len, _align) \
do { \
uint datalign; \
datalign = (unsigned long)((_p)->data); \
datalign = roundup(datalign, (_align)) - datalign; \
- ASSERT(datalign < (_align)); \
- ASSERT((_p)->len >= ((_len) + datalign)); \
if (datalign) \
skb_pull((_p), datalign); \
__skb_trim((_p), (_len)); \
@@ -387,146 +875,166 @@ extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
static const uint max_roundup = 512;
/* Try doing readahead */
-static bool dhd_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))
-/* Macros to get register read/write status */
-/* NOTE: these assume a local dhdsdio_bus_t *bus! */
-#define R_SDREG(regvar, regaddr, retryvar) \
-do { \
- retryvar = 0; \
- do { \
- regvar = R_REG(regaddr); \
- } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
- if (retryvar) { \
- bus->regfails += (retryvar-1); \
- if (retryvar > retry_limit) { \
- DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
- __func__, __LINE__)); \
- regvar = 0; \
- } \
- } \
-} while (0)
-
-#define W_SDREG(regval, regaddr, retryvar) \
-do { \
- retryvar = 0; \
- do { \
- W_REG(regaddr, regval); \
- } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
- if (retryvar) { \
- bus->regfails += (retryvar-1); \
- if (retryvar > retry_limit) \
- DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
- __func__, __LINE__)); \
- } \
-} while (0)
-
-#define DHD_BUS SDIO_BUS
+/*
+ * 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 dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
-static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
+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 DHD_DEBUG
-static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size);
-static int dhdsdio_mem_dump(dhd_bus_t *bus);
-#endif /* DHD_DEBUG */
-static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
-
-static void dhdsdio_release(dhd_bus_t *bus);
-static void dhdsdio_release_malloc(dhd_bus_t *bus);
-static void dhdsdio_disconnect(void *ptr);
-static bool dhdsdio_chipmatch(u16 chipid);
-static bool dhdsdio_probe_attach(dhd_bus_t *bus, void *sdh,
- void *regsva, u16 devid);
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh);
-static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh);
-static void dhdsdio_release_dongle(dhd_bus_t *bus);
-
-static uint process_nvram_vars(char *varbuf, uint len);
-
-static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size);
-static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn,
+#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, bcmsdh_cmplt_fn_t complete,
+ struct sk_buff *pkt,
+ void (*complete)(void *handle, int status,
+ bool sync_waiting),
void *handle);
-static bool dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh);
-static int _dhdsdio_download_firmware(struct dhd_bus *bus);
+static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card);
+static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus);
-static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
-static int dhdsdio_download_nvram(struct dhd_bus *bus);
-#ifdef BCMEMBEDIMAGE
-static int dhdsdio_download_code_array(struct dhd_bus *bus);
-#endif
-static void dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase);
-static int dhdsdio_chip_attach(struct dhd_bus *bus, void *regs);
-static void dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase);
-static void dhdsdio_sdiod_drive_strength_init(struct dhd_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 dhdsdio_chip_detach(struct dhd_bus *bus);
+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 dhdsdio_pktfree2(dhd_bus_t *bus, struct sk_buff *pkt)
+static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt)
{
- dhd_os_sdlock_rxq(bus->dhd);
if ((bus->bus != SPI_BUS) || bus->usebufpool)
- bcm_pkt_buf_free_skb(pkt);
- dhd_os_sdunlock_rxq(bus->dhd);
+ brcmu_pkt_buf_free_skb(pkt);
}
-static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
+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 */
- DHD_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
- dhd_dongle_memsize, min_size));
- if ((dhd_dongle_memsize > min_size) &&
- (dhd_dongle_memsize < (s32) bus->orig_ramsize))
- bus->ramsize = dhd_dongle_memsize;
+ 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 dhdsdio_set_siaddr_window(dhd_bus_t *bus, u32 address)
+static int brcmf_sdbrcm_set_siaddr_window(struct brcmf_bus *bus, u32 address)
{
int err = 0;
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
(address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
if (!err)
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_SBADDRMID,
(address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
if (!err)
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
- (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
- &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 dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
+static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
{
int err;
u8 clkctl, clkreq, devctl;
- bcmsdh_info_t *sdh;
+ struct brcmf_sdio_card *card;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
-#if defined(OOB_INTR_ONLY)
- pendok = false;
-#endif
clkctl = 0;
- sdh = bus->sdh;
+ card = bus->card;
if (on) {
/* Request HT Avail */
@@ -537,99 +1045,93 @@ static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
&& (bus->ci->chiprev == 0))
clkreq |= SBSDIO_FORCE_ALP;
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- clkreq, &err);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
if (err) {
- DHD_ERROR(("%s: HT Avail request error: %d\n",
- __func__, 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_SDREG(dummy, &bus->regs->clockctlstatus, retries);
+ r_sdreg32(bus, &dummy,
+ offsetof(struct sdpcmd_regs, clockctlstatus),
+ &retries);
}
/* Check current status */
- clkctl =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
+ clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err) {
- DHD_ERROR(("%s: HT Avail read error: %d\n",
- __func__, 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 =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- &err);
+ devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
if (err) {
- DHD_ERROR(("%s: Devctl error setting CA: %d\n",
- __func__, err));
+ BRCMF_ERROR(("%s: Devctl error setting CA:"
+ " %d\n", __func__, err));
return -EBADE;
}
devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- devctl, &err);
- DHD_INFO(("CLKCTL: set PENDING\n"));
+ 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 =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- &err);
+ brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- devctl, &err);
+ 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)) {
- SPINWAIT_SLEEP(sdioh_spinwait_sleep,
- ((clkctl =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- &err)),
- !SBSDIO_CLKAV(clkctl, bus->alp_only)),
- PMU_MAX_TRANSITION_DLY);
+ 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) {
- DHD_ERROR(("%s: HT Avail request error: %d\n",
- __func__, err));
+ BRCMF_ERROR(("%s: HT Avail request error: %d\n",
+ __func__, err));
return -EBADE;
}
if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
- __func__, PMU_MAX_TRANSITION_DLY, clkctl));
+ 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;
- DHD_INFO(("CLKCTL: turned ON\n"));
-
-#if defined(DHD_DEBUG)
- if (bus->alp_only == true) {
-#if !defined(BCMLXSDMMC)
- if (!SBSDIO_ALPONLY(clkctl)) {
- DHD_ERROR(("%s: HT Clock, when ALP Only\n",
- __func__));
- }
-#endif /* !defined(BCMLXSDMMC) */
- } else {
+ BRCMF_INFO(("CLKCTL: turned ON\n"));
+
+#if defined(BCMDBG)
+ if (bus->alp_only != true) {
if (SBSDIO_ALPONLY(clkctl)) {
- DHD_ERROR(("%s: HT Clock should be on.\n",
- __func__));
+ BRCMF_ERROR(("%s: HT Clock should be on.\n",
+ __func__));
}
}
-#endif /* defined (DHD_DEBUG) */
+#endif /* defined (BCMDBG) */
bus->activity = true;
} else {
@@ -637,21 +1139,20 @@ static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
if (bus->clkstate == CLK_PENDING) {
/* Cancel CA-only interrupt filter */
- devctl =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- &err);
+ devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- devctl, &err);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, devctl, &err);
}
bus->clkstate = CLK_SDONLY;
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- clkreq, &err);
- DHD_INFO(("CLKCTL: turned OFF\n"));
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
+ BRCMF_INFO(("CLKCTL: turned OFF\n"));
if (err) {
- DHD_ERROR(("%s: Failed access turning clock off: %d\n",
- __func__, err));
+ BRCMF_ERROR(("%s: Failed access turning clock off:"
+ " %d\n", __func__, err));
return -EBADE;
}
}
@@ -659,105 +1160,31 @@ static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
}
/* Change idle/active SD state */
-static int dhdsdio_sdclk(dhd_bus_t *bus, bool on)
+static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
{
- int err;
- s32 iovalue;
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- DHD_TRACE(("%s: Enter\n", __func__));
-
- if (on) {
- if (bus->idleclock == DHD_IDLE_STOP) {
- /* Turn on clock and restore mode */
- iovalue = 1;
- err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
- &iovalue, sizeof(iovalue), true);
- if (err) {
- DHD_ERROR(("%s: error enabling sd_clock: %d\n",
- __func__, err));
- return -EBADE;
- }
-
- iovalue = bus->sd_mode;
- err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
- &iovalue, sizeof(iovalue), true);
- if (err) {
- DHD_ERROR(("%s: error changing sd_mode: %d\n",
- __func__, err));
- return -EBADE;
- }
- } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
- /* Restore clock speed */
- iovalue = bus->sd_divisor;
- err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
- &iovalue, sizeof(iovalue), true);
- if (err) {
- DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
- __func__, err));
- return -EBADE;
- }
- }
+ if (on)
bus->clkstate = CLK_SDONLY;
- } else {
- /* Stop or slow the SD clock itself */
- if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
- DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
- __func__, bus->sd_divisor, bus->sd_mode));
- return -EBADE;
- }
- if (bus->idleclock == DHD_IDLE_STOP) {
- if (sd1idle) {
- /* Change to SD1 mode and turn off clock */
- iovalue = 1;
- err =
- bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL,
- 0, &iovalue,
- sizeof(iovalue), true);
- if (err) {
- DHD_ERROR(("%s: error changing sd_clock: %d\n",
- __func__, err));
- return -EBADE;
- }
- }
-
- iovalue = 0;
- err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
- &iovalue, sizeof(iovalue), true);
- if (err) {
- DHD_ERROR(("%s: error disabling sd_clock: %d\n",
- __func__, err));
- return -EBADE;
- }
- } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
- /* Set divisor to idle value */
- iovalue = bus->idleclock;
- err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
- &iovalue, sizeof(iovalue), true);
- if (err) {
- DHD_ERROR(("%s: error changing sd_divisor: %d\n",
- __func__, err));
- return -EBADE;
- }
- }
+ else
bus->clkstate = CLK_NONE;
- }
return 0;
}
/* Transition SD and backplane clock readiness */
-static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
+static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
{
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
uint oldstate = bus->clkstate;
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* Early exit if we're already there */
if (bus->clkstate == target) {
if (target == CLK_AVAIL) {
- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
bus->activity = true;
}
return 0;
@@ -767,50 +1194,50 @@ static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
case CLK_AVAIL:
/* Make sure SD clock is available */
if (bus->clkstate == CLK_NONE)
- dhdsdio_sdclk(bus, true);
+ brcmf_sdbrcm_sdclk(bus, true);
/* Now request HT Avail on the backplane */
- dhdsdio_htclk(bus, true, pendok);
- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ 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)
- dhdsdio_sdclk(bus, true);
+ brcmf_sdbrcm_sdclk(bus, true);
else if (bus->clkstate == CLK_AVAIL)
- dhdsdio_htclk(bus, false, false);
+ brcmf_sdbrcm_htclk(bus, false, false);
else
- DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
- bus->clkstate, target));
- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ 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)
- dhdsdio_htclk(bus, false, false);
+ brcmf_sdbrcm_htclk(bus, false, false);
/* Now remove the SD clock */
- dhdsdio_sdclk(bus, false);
- dhd_os_wd_timer(bus->dhd, 0);
+ brcmf_sdbrcm_sdclk(bus, false);
+ brcmf_sdbrcm_wd_timer(bus, 0);
break;
}
-#ifdef DHD_DEBUG
- DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
-#endif /* DHD_DEBUG */
+#ifdef BCMDBG
+ BRCMF_INFO(("brcmf_sdbrcm_clkctl: %d -> %d\n",
+ oldstate, bus->clkstate));
+#endif /* BCMDBG */
return 0;
}
-int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
+int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
{
- bcmsdh_info_t *sdh = bus->sdh;
- sdpcmd_regs_t *regs = bus->regs;
+ struct brcmf_sdio_card *card = bus->card;
uint retries = 0;
- DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
- (sleep ? "SLEEP" : "WAKE"),
- (bus->sleeping ? "SLEEP" : "WAKE")));
+ 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)
@@ -823,27 +1250,31 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
return -EBUSY;
/* Disable SDIO interrupts (no longer interested) */
- bcmsdh_intr_disable(bus->sdh);
+ brcmf_sdcard_intr_disable(bus->card);
/* Make sure the controller has the bus up */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
/* Tell device to start using OOB wakeup */
- W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
+ w_sdreg32(bus, SMB_USE_OOB,
+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
if (retries > retry_limit)
- DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+ BRCMF_ERROR(("CANNOT SIGNAL CHIP, "
+ "WILL NOT WAKE UP!!\n"));
/* Turn off our contribution to the HT clock request */
- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
+ 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) {
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- SBSDIO_DEVCTL_PADS_ISO, NULL);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL,
+ SBSDIO_DEVCTL_PADS_ISO, NULL);
}
/* Change state */
@@ -852,82 +1283,55 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
} else {
/* Waking up: bus power up is ok, set local state */
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- 0, NULL);
+ 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))
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0,
- NULL);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, 0, NULL);
/* Make sure the controller has the bus up */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
/* Send misc interrupt to indicate OOB not needed */
- W_SDREG(0, &regs->tosbmailboxdata, retries);
+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata),
+ &retries);
if (retries <= retry_limit)
- W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
+ w_sdreg32(bus, SMB_DEV_INT,
+ offsetof(struct sdpcmd_regs, tosbmailbox),
+ &retries);
if (retries > retry_limit)
- DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
+ BRCMF_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
/* Make sure we have SD bus access */
- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
/* Change state */
bus->sleeping = false;
/* Enable interrupts again */
- if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
+ if (bus->intr && (bus->drvr->busstate == BRCMF_BUS_DATA)) {
bus->intdis = false;
- bcmsdh_intr_enable(bus->sdh);
+ brcmf_sdcard_intr_enable(bus->card);
}
}
return 0;
}
-#if defined(OOB_INTR_ONLY)
-void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
-{
-#if defined(HW_OOB)
- bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
-#else
- sdpcmd_regs_t *regs = bus->regs;
- uint retries = 0;
-
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
- if (enable == true) {
-
- /* Tell device to start using OOB wakeup */
- W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
- if (retries > retry_limit)
- DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
-
- } else {
- /* Send misc interrupt to indicate OOB not needed */
- W_SDREG(0, &regs->tosbmailboxdata, retries);
- if (retries <= retry_limit)
- W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
- }
-
- /* Turn off our contribution to the HT clock request */
- dhdsdio_clkctl(bus, CLK_SDONLY, false);
-#endif /* !defined(HW_OOB) */
-}
-#endif /* defined(OOB_INTR_ONLY) */
-
#define BUS_WAKE(bus) \
do { \
if ((bus)->sleeping) \
- dhdsdio_bussleep((bus), false); \
+ 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 dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
+static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan,
bool free_pkt)
{
int ret;
@@ -935,15 +1339,15 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
u16 len, pad = 0;
u32 swheader;
uint retries = 0;
- bcmsdh_info_t *sdh;
+ struct brcmf_sdio_card *card;
struct sk_buff *new;
int i;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- sdh = bus->sdh;
+ card = bus->card;
- if (bus->dhd->dongle_reset) {
+ if (bus->drvr->dongle_reset) {
ret = -EPERM;
goto done;
}
@@ -951,40 +1355,39 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
frame = (u8 *) (pkt->data);
/* Add alignment padding, allocate new packet if needed */
- pad = ((unsigned long)frame % DHD_SDALIGN);
+ pad = ((unsigned long)frame % BRCMF_SDALIGN);
if (pad) {
if (skb_headroom(pkt) < pad) {
- DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
- __func__, skb_headroom(pkt), pad));
- bus->dhd->tx_realloc++;
- new = bcm_pkt_buf_get_skb(pkt->len + DHD_SDALIGN);
+ 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) {
- DHD_ERROR(("%s: couldn't allocate new %d-byte "
- "packet\n",
- __func__, pkt->len + DHD_SDALIGN));
+ BRCMF_ERROR(("%s: couldn't allocate new "
+ "%d-byte packet\n", __func__,
+ pkt->len + BRCMF_SDALIGN));
ret = -ENOMEM;
goto done;
}
- PKTALIGN(new, pkt->len, DHD_SDALIGN);
+ PKTALIGN(new, pkt->len, BRCMF_SDALIGN);
memcpy(new->data, pkt->data, pkt->len);
if (free_pkt)
- bcm_pkt_buf_free_skb(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);
- ASSERT(((unsigned long)frame % DHD_SDALIGN) == 0);
+ /* precondition: (frame % BRCMF_SDALIGN) == 0) */
pad = 0;
} else {
skb_push(pkt, pad);
frame = (u8 *) (pkt->data);
-
- ASSERT((pad + SDPCM_HDRLEN) <= (int)(pkt->len));
+ /* precondition: pad + SDPCM_HDRLEN <= pkt->len */
memset(frame, 0, pad + SDPCM_HDRLEN);
}
}
- ASSERT(pad < DHD_SDALIGN);
+ /* precondition: pad < BRCMF_SDALIGN */
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
len = (u16) (pkt->len);
@@ -1000,14 +1403,14 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
tx_packets[pkt->priority]++;
- if (DHD_BYTES_ON() &&
- (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
- (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
+ 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 (DHD_HDRS_ON()) {
+ } else if (BRCMF_HDRS_ON()) {
printk(KERN_DEBUG "TxHdr:\n");
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
frame, min_t(u16, len, 16));
@@ -1018,53 +1421,40 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
u16 pad = bus->blocksize - (len % bus->blocksize);
if ((pad <= bus->roundup) && (pad < bus->blocksize))
-#ifdef NOTUSED
- if (pad <= skb_tailroom(pkt))
-#endif /* NOTUSED */
len += pad;
- } else if (len % DHD_SDALIGN) {
- len += DHD_SDALIGN - (len % DHD_SDALIGN);
+ } 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))) {
-#ifdef NOTUSED
- if (skb_tailroom(pkt))
-#endif
len = roundup(len, ALIGNMENT);
-#ifdef NOTUSED
- else
- DHD_ERROR(("%s: sending unrounded %d-byte packet\n",
- __func__, len));
-#endif
}
do {
- ret =
- dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
- F2SYNC, frame, len, pkt, NULL, NULL);
+ ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
+ SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL);
bus->f2txdata++;
- ASSERT(ret != -BCME_PENDING);
if (ret < 0) {
/* On failure, abort the command
and terminate the frame */
- DHD_INFO(("%s: sdio error %d, abort command and "
- "terminate frame.\n", __func__, ret));
+ BRCMF_INFO(("%s: sdio error %d, abort command and "
+ "terminate frame.\n", __func__, ret));
bus->tx_sderrs++;
- bcmsdh_abort(sdh, SDIO_FUNC_2);
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+ 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 = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCHI,
NULL);
- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCLO,
NULL);
bus->f1regdata += 2;
@@ -1081,22 +1471,22 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
done:
/* restore pkt buffer pointer before calling tx complete routine */
skb_pull(pkt, SDPCM_HDRLEN + pad);
- dhd_os_sdunlock(bus->dhd);
- dhd_txcomplete(bus->dhd, pkt, ret != 0);
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
+ brcmf_txcomplete(bus->drvr, pkt, ret != 0);
+ brcmf_sdbrcm_sdlock(bus);
if (free_pkt)
- bcm_pkt_buf_free_skb(pkt);
+ brcmu_pkt_buf_free_skb(pkt);
return ret;
}
-int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
+int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
{
int ret = -EBADE;
uint datalen, prec;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
datalen = pkt->len;
@@ -1116,79 +1506,80 @@ int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
/* Add space for the header */
skb_push(pkt, SDPCM_HDRLEN);
- ASSERT(IS_ALIGNED((unsigned long)(pkt->data), 2));
+ /* 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 (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
+ if (brcmf_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
|| bus->dpc_sched || (!DATAOK(bus))
|| (bus->flowcontrol & NBITVAL(prec))
|| (bus->clkstate != CLK_AVAIL)) {
- DHD_TRACE(("%s: deferring pktq len %d\n", __func__,
- pktq_len(&bus->txq)));
+ BRCMF_TRACE(("%s: deferring pktq len %d\n", __func__,
+ pktq_len(&bus->txq)));
bus->fcqueued++;
/* Priority based enq */
- dhd_os_sdlock_txq(bus->dhd);
- if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == false) {
+ spin_lock_bh(&bus->txqlock);
+ if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
skb_pull(pkt, SDPCM_HDRLEN);
- dhd_txcomplete(bus->dhd, pkt, false);
- bcm_pkt_buf_free_skb(pkt);
- DHD_ERROR(("%s: out of bus->txq !!!\n", __func__));
+ 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;
}
- dhd_os_sdunlock_txq(bus->dhd);
+ spin_unlock_bh(&bus->txqlock);
if (pktq_len(&bus->txq) >= TXHI)
- dhd_txflowcontrol(bus->dhd, 0, ON);
+ brcmf_txflowcontrol(bus->drvr, 0, ON);
-#ifdef DHD_DEBUG
+#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 (dhd_deferred_tx && !bus->dpc_sched) {
+ if (brcmf_deferred_tx && !bus->dpc_sched) {
bus->dpc_sched = true;
- dhd_sched_dpc(bus->dhd);
+ brcmf_sdbrcm_sched_dpc(bus);
}
} else {
/* Lock: we're about to use shared data/code (and SDIO) */
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
/* Otherwise, send it now */
BUS_WAKE(bus);
/* Make sure back plane ht clk is on, no pending allowed */
- dhdsdio_clkctl(bus, CLK_AVAIL, true);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
#ifndef SDTEST
- DHD_TRACE(("%s: calling txpkt\n", __func__));
- ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+ BRCMF_TRACE(("%s: calling txpkt\n", __func__));
+ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
#else
- ret = dhdsdio_txpkt(bus, pkt,
+ ret = brcmf_sdbrcm_txpkt(bus, pkt,
(bus->ext_loop ? SDPCM_TEST_CHANNEL :
SDPCM_DATA_CHANNEL), true);
#endif
if (ret)
- bus->dhd->tx_errors++;
+ bus->drvr->tx_errors++;
else
- bus->dhd->dstats.tx_bytes += datalen;
+ bus->drvr->dstats.tx_bytes += datalen;
- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
+ !bus->dpc_sched) {
bus->activity = false;
- dhdsdio_clkctl(bus, CLK_NONE, true);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
}
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
}
return ret;
}
-static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
+static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
{
struct sk_buff *pkt;
u32 intstatus = 0;
@@ -1198,42 +1589,43 @@ static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
uint datalen;
u8 tx_prec_map;
- dhd_pub_t *dhd = bus->dhd;
- sdpcmd_regs_t *regs = bus->regs;
+ struct brcmf_pub *drvr = bus->drvr;
- DHD_TRACE(("%s: Enter\n", __func__));
+ 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++) {
- dhd_os_sdlock_txq(bus->dhd);
- pkt = bcm_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
+ spin_lock_bh(&bus->txqlock);
+ pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
if (pkt == NULL) {
- dhd_os_sdunlock_txq(bus->dhd);
+ spin_unlock_bh(&bus->txqlock);
break;
}
- dhd_os_sdunlock_txq(bus->dhd);
+ spin_unlock_bh(&bus->txqlock);
datalen = pkt->len - SDPCM_HDRLEN;
#ifndef SDTEST
- ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
#else
- ret = dhdsdio_txpkt(bus, pkt,
+ ret = brcmf_sdbrcm_txpkt(bus, pkt,
(bus->ext_loop ? SDPCM_TEST_CHANNEL :
SDPCM_DATA_CHANNEL), true);
#endif
if (ret)
- bus->dhd->tx_errors++;
+ bus->drvr->tx_errors++;
else
- bus->dhd->dstats.tx_bytes += datalen;
+ 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_SDREG(intstatus, &regs->intstatus, retries);
+ r_sdreg32(bus, &intstatus,
+ offsetof(struct sdpcmd_regs, intstatus),
+ &retries);
bus->f2txdata++;
- if (bcmsdh_regfail(bus->sdh))
+ if (brcmf_sdcard_regfail(bus->card))
break;
if (intstatus & bus->hostintmask)
bus->ipend = true;
@@ -1241,27 +1633,28 @@ static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
}
/* Deflow-control stack if needed */
- if (dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
- dhd->txoff && (pktq_len(&bus->txq) < TXLOW))
- dhd_txflowcontrol(dhd, 0, OFF);
+ if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
+ drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
+ brcmf_txflowcontrol(drvr, 0, OFF);
return cnt;
}
-int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
+int
+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
{
u8 *frame;
u16 len;
u32 swheader;
uint retries = 0;
- bcmsdh_info_t *sdh = bus->sdh;
+ struct brcmf_sdio_card *card = bus->card;
u8 doff = 0;
int ret = -1;
int i;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (bus->dhd->dongle_reset)
+ if (bus->drvr->dongle_reset)
return -EIO;
/* Back the pointer to make a room for bus header */
@@ -1269,15 +1662,15 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
len = (msglen += SDPCM_HDRLEN);
/* Add alignment padding (optional for ctl frames) */
- if (dhd_alignctl) {
- doff = ((unsigned long)frame % DHD_SDALIGN);
+ if (brcmf_alignctl) {
+ doff = ((unsigned long)frame % BRCMF_SDALIGN);
if (doff) {
frame -= doff;
len += doff;
msglen += doff;
memset(frame, 0, doff + SDPCM_HDRLEN);
}
- ASSERT(doff < DHD_SDALIGN);
+ /* precondition: doff < BRCMF_SDALIGN */
}
doff += SDPCM_HDRLEN;
@@ -1286,23 +1679,23 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
u16 pad = bus->blocksize - (len % bus->blocksize);
if ((pad <= bus->roundup) && (pad < bus->blocksize))
len += pad;
- } else if (len % DHD_SDALIGN) {
- len += DHD_SDALIGN - (len % DHD_SDALIGN);
+ } else if (len % BRCMF_SDALIGN) {
+ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
}
/* Satisfy length-alignment requirements */
if (forcealign && (len & (ALIGNMENT - 1)))
len = roundup(len, ALIGNMENT);
- ASSERT(IS_ALIGNED((unsigned long)frame, 2));
+ /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
/* Need to lock here to protect txseq and SDIO tx calls */
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
BUS_WAKE(bus);
/* Make sure backplane clock is on */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ 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);
@@ -1318,31 +1711,33 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
if (!DATAOK(bus)) {
- DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
- __func__, bus->tx_max, bus->tx_seq));
+ 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;
- dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
+ brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
if (bus->ctrl_frame_stat == false) {
- DHD_INFO(("%s: ctrl_frame_stat == false\n", __func__));
+ BRCMF_INFO(("%s: ctrl_frame_stat == false\n",
+ __func__));
ret = 0;
} else {
- DHD_INFO(("%s: ctrl_frame_stat == true\n", __func__));
+ BRCMF_INFO(("%s: ctrl_frame_stat == true\n", __func__));
ret = -1;
}
}
if (ret == -1) {
-#ifdef DHD_DEBUG
- if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+#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 (DHD_HDRS_ON()) {
+ } else if (BRCMF_HDRS_ON()) {
printk(KERN_DEBUG "TxHdr:\n");
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
frame, min_t(u16, len, 16));
@@ -1351,35 +1746,35 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
do {
bus->ctrl_frame_stat = false;
- ret =
- dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh),
- SDIO_FUNC_2, F2SYNC, frame, len,
- NULL, NULL, NULL);
-
- ASSERT(ret != -BCME_PENDING);
+ 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 */
- DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
- __func__, ret));
+ BRCMF_INFO(("%s: sdio error %d, abort command "
+ "and terminate frame.\n",
+ __func__, ret));
bus->tx_sderrs++;
- bcmsdh_abort(sdh, SDIO_FUNC_2);
+ brcmf_sdcard_abort(card, SDIO_FUNC_2);
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+ 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 = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ hi = brcmf_sdcard_cfg_read(card,
+ SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCHI,
NULL);
- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ lo = brcmf_sdcard_cfg_read(card,
+ SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCLO,
- NULL);
+ NULL);
bus->f1regdata += 2;
if ((hi == 0) && (lo == 0))
break;
@@ -1393,67 +1788,67 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
} while ((ret < 0) && retries++ < TXRETRIES);
}
- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
bus->activity = false;
- dhdsdio_clkctl(bus, CLK_NONE, true);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
}
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
if (ret)
- bus->dhd->tx_ctlerrs++;
+ bus->drvr->tx_ctlerrs++;
else
- bus->dhd->tx_ctlpkts++;
+ bus->drvr->tx_ctlpkts++;
return ret ? -EIO : 0;
}
-int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
+int brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
{
int timeleft;
uint rxlen = 0;
bool pending;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (bus->dhd->dongle_reset)
+ if (bus->drvr->dongle_reset)
return -EIO;
/* Wait until control frame is available */
- timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
+ timeleft = brcmf_os_ioctl_resp_wait(bus->drvr, &bus->rxlen, &pending);
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
rxlen = bus->rxlen;
memcpy(msg, bus->rxctl, min(msglen, rxlen));
bus->rxlen = 0;
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
if (rxlen) {
- DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
- __func__, rxlen, msglen));
+ BRCMF_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
+ __func__, rxlen, msglen));
} else if (timeleft == 0) {
- DHD_ERROR(("%s: resumed on timeout\n", __func__));
-#ifdef DHD_DEBUG
- dhd_os_sdlock(bus->dhd);
- dhdsdio_checkdied(bus, NULL, 0);
- dhd_os_sdunlock(bus->dhd);
-#endif /* DHD_DEBUG */
+ 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) {
- DHD_CTL(("%s: cancelled\n", __func__));
+ BRCMF_CTL(("%s: cancelled\n", __func__));
return -ERESTARTSYS;
} else {
- DHD_CTL(("%s: resumed for unknown reason?\n", __func__));
-#ifdef DHD_DEBUG
- dhd_os_sdlock(bus->dhd);
- dhdsdio_checkdied(bus, NULL, 0);
- dhd_os_sdunlock(bus->dhd);
-#endif /* DHD_DEBUG */
+ 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->dhd->rx_ctlpkts++;
+ bus->drvr->rx_ctlpkts++;
else
- bus->dhd->rx_ctlerrs++;
+ bus->drvr->rx_ctlerrs++;
return rxlen ? (int)rxlen : -ETIMEDOUT;
}
@@ -1467,8 +1862,10 @@ enum {
IOV_SDCIS,
IOV_MEMBYTES,
IOV_MEMSIZE,
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
IOV_CHECKDIED,
+ IOV_CONS,
+ IOV_DCONSOLE_POLL,
#endif
IOV_DOWNLOAD,
IOV_FORCEEVEN,
@@ -1491,10 +1888,11 @@ enum {
IOV_IDLECLOCK,
IOV_SD1IDLE,
IOV_SLEEP,
+ IOV_WDTICK,
IOV_VARS
};
-const bcm_iovar_t dhdsdio_iovars[] = {
+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},
@@ -1511,12 +1909,17 @@ const bcm_iovar_t dhdsdio_iovars[] = {
{"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0},
{"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0},
{"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0},
-#ifdef DHD_DEBUG
- {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
+ {"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(sdreg_t)}
+ {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
,
- {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}
+ {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
,
{"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0}
,
@@ -1528,15 +1931,13 @@ const bcm_iovar_t dhdsdio_iovars[] = {
,
{"cpu", IOV_CPU, 0, IOVT_BOOL, 0}
,
-#ifdef DHD_DEBUG
{"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0}
,
-#endif /* DHD_DEBUG */
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
#ifdef SDTEST
{"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0}
,
- {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t)}
+ {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(struct brcmf_pktgen)}
,
#endif /* SDTEST */
@@ -1544,122 +1945,122 @@ const bcm_iovar_t dhdsdio_iovars[] = {
};
static void
-dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
+brcmf_dump_pct(struct brcmu_strbuf *strbuf, char *desc, uint num, uint div)
{
uint q1, q2;
if (!div) {
- bcm_bprintf(strbuf, "%s N/A", desc);
+ brcmu_bprintf(strbuf, "%s N/A", desc);
} else {
q1 = num / div;
q2 = (100 * (num - (q1 * div))) / div;
- bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
+ brcmu_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
}
}
-void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
{
- dhd_bus_t *bus = dhdp->bus;
+ struct brcmf_bus *bus = drvr->bus;
- bcm_bprintf(strbuf, "Bus SDIO structure:\n");
- bcm_bprintf(strbuf,
+ 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);
- bcm_bprintf(strbuf,
+ 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);
- bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
+ brcmu_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
- bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
+ brcmu_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
bus->pollrate, bus->pollcnt, bus->regfails);
- bcm_bprintf(strbuf, "\nAdditional counters:\n");
- bcm_bprintf(strbuf,
+ 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);
- bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
+ brcmu_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
- bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", bus->fc_rcvd,
- bus->fc_xoff, bus->fc_xon);
- bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
+ 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);
- bcm_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);
+ 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);
{
- dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
+ brcmf_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->drvr->rx_packets,
(bus->f2rxhdrs + bus->f2rxdata));
- dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets,
+ brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->rx_packets,
bus->f1regdata);
- dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
+ brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->rx_packets,
(bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
- dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets,
+ brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->rx_packets,
bus->intrcount);
- bcm_bprintf(strbuf, "\n");
+ brcmu_bprintf(strbuf, "\n");
- dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
- bus->dhd->rx_packets);
- dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
+ brcmf_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
+ bus->drvr->rx_packets);
+ brcmf_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
bus->rxglomframes);
- bcm_bprintf(strbuf, "\n");
+ brcmu_bprintf(strbuf, "\n");
- dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets,
+ brcmf_dump_pct(strbuf, "Tx: pkts/f2wr", bus->drvr->tx_packets,
bus->f2txdata);
- dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets,
+ brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->tx_packets,
bus->f1regdata);
- dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
+ brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->tx_packets,
(bus->f2txdata + bus->f1regdata));
- dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets,
+ brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->tx_packets,
bus->intrcount);
- bcm_bprintf(strbuf, "\n");
+ brcmu_bprintf(strbuf, "\n");
- dhd_dump_pct(strbuf, "Total: pkts/f2rw",
- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+ brcmf_dump_pct(strbuf, "Total: pkts/f2rw",
+ (bus->drvr->tx_packets + bus->drvr->rx_packets),
(bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
- dhd_dump_pct(strbuf, ", pkts/f1sd",
- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+ brcmf_dump_pct(strbuf, ", pkts/f1sd",
+ (bus->drvr->tx_packets + bus->drvr->rx_packets),
bus->f1regdata);
- dhd_dump_pct(strbuf, ", pkts/sd",
- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+ brcmf_dump_pct(strbuf, ", pkts/sd",
+ (bus->drvr->tx_packets + bus->drvr->rx_packets),
(bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata +
bus->f1regdata));
- dhd_dump_pct(strbuf, ", pkts/int",
- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+ brcmf_dump_pct(strbuf, ", pkts/int",
+ (bus->drvr->tx_packets + bus->drvr->rx_packets),
bus->intrcount);
- bcm_bprintf(strbuf, "\n\n");
+ brcmu_bprintf(strbuf, "\n\n");
}
#ifdef SDTEST
if (bus->pktgen_count) {
- bcm_bprintf(strbuf, "pktgen config and count:\n");
- bcm_bprintf(strbuf,
+ 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);
- bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
+ brcmu_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
bus->pktgen_sent, bus->pktgen_rcvd,
bus->pktgen_fail);
}
#endif /* SDTEST */
-#ifdef DHD_DEBUG
- bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
- bus->dpc_sched,
- (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
- bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
+#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 /* DHD_DEBUG */
- bcm_bprintf(strbuf,
+#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 dhd_bus_clearcounts(dhd_pub_t *dhdp)
+void brcmf_bus_clearcounts(struct brcmf_pub *drvr)
{
- dhd_bus_t *bus = (dhd_bus_t *) dhdp->bus;
+ 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;
@@ -1670,11 +2071,11 @@ void dhd_bus_clearcounts(dhd_pub_t *dhdp)
}
#ifdef SDTEST
-static int dhdsdio_pktgen_get(dhd_bus_t *bus, u8 *arg)
+static int brcmf_sdbrcm_pktgen_get(struct brcmf_bus *bus, u8 *arg)
{
- dhd_pktgen_t pktgen;
+ struct brcmf_pktgen pktgen;
- pktgen.version = DHD_PKTGEN_VERSION;
+ pktgen.version = BRCMF_PKTGEN_VERSION;
pktgen.freq = bus->pktgen_freq;
pktgen.count = bus->pktgen_count;
pktgen.print = bus->pktgen_print;
@@ -1692,13 +2093,13 @@ static int dhdsdio_pktgen_get(dhd_bus_t *bus, u8 *arg)
return 0;
}
-static int dhdsdio_pktgen_set(dhd_bus_t *bus, u8 *arg)
+static int brcmf_sdbrcm_pktgen_set(struct brcmf_bus *bus, u8 *arg)
{
- dhd_pktgen_t pktgen;
+ struct brcmf_pktgen pktgen;
uint oldcnt, oldmode;
memcpy(&pktgen, arg, sizeof(pktgen));
- if (pktgen.version != DHD_PKTGEN_VERSION)
+ if (pktgen.version != BRCMF_PKTGEN_VERSION)
return -EINVAL;
oldcnt = bus->pktgen_count;
@@ -1726,7 +2127,7 @@ static int dhdsdio_pktgen_set(dhd_bus_t *bus, u8 *arg)
#endif /* SDTEST */
static int
-dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
+brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
uint size)
{
int bcmerror = 0;
@@ -1741,21 +2142,22 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
dsize = size;
/* Set the backplane window to include the start address */
- bcmerror = dhdsdio_set_siaddr_window(bus, address);
+ bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
if (bcmerror) {
- DHD_ERROR(("%s: window change failed\n", __func__));
+ BRCMF_ERROR(("%s: window change failed\n", __func__));
goto xfer_done;
}
/* Do the transfer(s) */
while (size) {
- DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
- __func__, (write ? "write" : "read"), dsize,
- sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
+ 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 =
- bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize);
+ brcmf_sdcard_rwdata(bus->card, write, sdaddr, data, dsize);
if (bcmerror) {
- DHD_ERROR(("%s: membytes transfer failed\n", __func__));
+ BRCMF_ERROR(("%s: membytes transfer failed\n",
+ __func__));
break;
}
@@ -1764,10 +2166,10 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
if (size) {
data += dsize;
address += dsize;
- bcmerror = dhdsdio_set_siaddr_window(bus, address);
+ bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
if (bcmerror) {
- DHD_ERROR(("%s: window change failed\n",
- __func__));
+ BRCMF_ERROR(("%s: window change failed\n",
+ __func__));
break;
}
sdaddr = 0;
@@ -1777,43 +2179,45 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
xfer_done:
/* Return the window to backplane enumeration space for core access */
- if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
- DHD_ERROR(("%s: FAILED to set window back to 0x%x\n",
- __func__, bcmsdh_cur_sbwad(bus->sdh)));
+ 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 DHD_DEBUG
-static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
+#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 = dhdsdio_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr, 4);
+ rv = brcmf_sdbrcm_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr,
+ 4);
if (rv < 0)
return rv;
addr = le32_to_cpu(addr);
- DHD_INFO(("sdpcm_shared address 0x%08X\n", 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)) {
- DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
- __func__, addr));
+ BRCMF_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
+ __func__, addr));
return -EBADE;
}
- /* Read hndrte_shared structure */
- rv = dhdsdio_membytes(bus, false, addr, (u8 *) sh,
- sizeof(sdpcm_shared_t));
+ /* Read rte_shared structure */
+ rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *) sh,
+ sizeof(struct sdpcm_shared));
if (rv < 0)
return rv;
@@ -1827,28 +2231,28 @@ static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
- DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
- "is different than sdpcm_shared version %d in dongle\n",
- __func__, SDPCM_SHARED_VERSION,
- sh->flags & SDPCM_SHARED_VERSION_MASK));
+ 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 dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
+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;
- trap_t tr;
- sdpcm_shared_t sdpcm_shared;
- struct bcmstrbuf strbuf;
+ struct brcmf_trap tr;
+ struct sdpcm_shared sdpcm_shared;
+ struct brcmu_strbuf strbuf;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
if (data == NULL) {
/*
@@ -1858,8 +2262,8 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
size = msize;
mbuffer = data = kmalloc(msize, GFP_ATOMIC);
if (mbuffer == NULL) {
- DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__,
- msize));
+ BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__,
+ msize));
bcmerror = -ENOMEM;
goto done;
}
@@ -1867,18 +2271,18 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
str = kmalloc(maxstrlen, GFP_ATOMIC);
if (str == NULL) {
- DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
+ BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
bcmerror = -ENOMEM;
goto done;
}
- bcmerror = dhdsdio_readshared(bus, &sdpcm_shared);
+ bcmerror = brcmf_sdbrcm_readshared(bus, &sdpcm_shared);
if (bcmerror < 0)
goto done;
- bcm_binit(&strbuf, data, size);
+ brcmu_binit(&strbuf, data, size);
- bcm_bprintf(&strbuf,
+ brcmu_bprintf(&strbuf,
"msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
@@ -1887,7 +2291,7 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
* (Avoids conflict with real asserts for programmatic
* parsing of output.)
*/
- bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
+ brcmu_bprintf(&strbuf, "Assrt not built in dongle\n");
}
if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) ==
@@ -1896,49 +2300,49 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
* (Avoids conflict with real asserts for programmatic
* parsing of output.)
*/
- bcm_bprintf(&strbuf, "No trap%s in dongle",
+ 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 */
- bcm_bprintf(&strbuf, "Dongle assert");
+ brcmu_bprintf(&strbuf, "Dongle assert");
if (sdpcm_shared.assert_exp_addr != 0) {
str[0] = '\0';
- bcmerror = dhdsdio_membytes(bus, false,
+ bcmerror = brcmf_sdbrcm_membytes(bus, false,
sdpcm_shared.assert_exp_addr,
(u8 *) str, maxstrlen);
if (bcmerror < 0)
goto done;
str[maxstrlen - 1] = '\0';
- bcm_bprintf(&strbuf, " expr \"%s\"", str);
+ brcmu_bprintf(&strbuf, " expr \"%s\"", str);
}
if (sdpcm_shared.assert_file_addr != 0) {
str[0] = '\0';
- bcmerror = dhdsdio_membytes(bus, false,
+ bcmerror = brcmf_sdbrcm_membytes(bus, false,
sdpcm_shared.assert_file_addr,
(u8 *) str, maxstrlen);
if (bcmerror < 0)
goto done;
str[maxstrlen - 1] = '\0';
- bcm_bprintf(&strbuf, " file \"%s\"", str);
+ brcmu_bprintf(&strbuf, " file \"%s\"", str);
}
- bcm_bprintf(&strbuf, " line %d ",
+ brcmu_bprintf(&strbuf, " line %d ",
sdpcm_shared.assert_line);
}
if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
- bcmerror = dhdsdio_membytes(bus, false,
+ bcmerror = brcmf_sdbrcm_membytes(bus, false,
sdpcm_shared.trap_addr, (u8 *)&tr,
- sizeof(trap_t));
+ sizeof(struct brcmf_trap));
if (bcmerror < 0)
goto done;
- bcm_bprintf(&strbuf,
+ 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",
@@ -1950,14 +2354,14 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
}
if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP))
- DHD_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
+ BRCMF_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
/* Mem dump to a file on device */
- dhdsdio_mem_dump(bus);
+ brcmf_sdbrcm_mem_dump(bus);
}
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
done:
kfree(mbuffer);
@@ -1966,7 +2370,7 @@ done:
return bcmerror;
}
-static int dhdsdio_mem_dump(dhd_bus_t *bus)
+static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus)
{
int ret = 0;
int size; /* Full mem size */
@@ -1978,7 +2382,7 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
size = bus->ramsize;
buf = kmalloc(size, GFP_ATOMIC);
if (!buf) {
- DHD_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
+ BRCMF_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
return -1;
}
@@ -1987,9 +2391,10 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
databuf = buf;
while (size) {
read_size = min(MEMBLOCK, size);
- ret = dhdsdio_membytes(bus, false, start, databuf, read_size);
+ ret = brcmf_sdbrcm_membytes(bus, false, start, databuf,
+ read_size);
if (ret) {
- DHD_ERROR(("%s: Error membytes %d\n", __func__, ret));
+ BRCMF_ERROR(("%s: Error membytes %d\n", __func__, ret));
kfree(buf);
return -1;
}
@@ -2003,20 +2408,20 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
printk(KERN_DEBUG "Done\n");
/* free buf before return !!! */
- if (write_to_file(bus->dhd, buf, bus->ramsize)) {
- DHD_ERROR(("%s: Error writing to files\n", __func__));
+ 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 write_to_file, not here */
+ /* buf free handled in brcmf_write_to_file, not here */
return 0;
}
#define CONSOLE_LINE_MAX 192
-static int dhdsdio_readconsole(dhd_bus_t *bus)
+static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
{
- dhd_console_t *c = &bus->console;
+ struct brcmf_console *c = &bus->console;
u8 line[CONSOLE_LINE_MAX], ch;
u32 n, idx, addr;
int rv;
@@ -2026,8 +2431,8 @@ static int dhdsdio_readconsole(dhd_bus_t *bus)
return 0;
/* Read console log struct */
- addr = bus->console_addr + offsetof(hndrte_cons_t, log);
- rv = dhdsdio_membytes(bus, false, addr, (u8 *)&c->log,
+ 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;
@@ -2053,7 +2458,7 @@ static int dhdsdio_readconsole(dhd_bus_t *bus)
/* Read the console buffer */
addr = le32_to_cpu(c->log.buf);
- rv = dhdsdio_membytes(bus, false, addr, c->buf, c->bufsize);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
if (rv < 0)
return rv;
@@ -2089,16 +2494,16 @@ break2:
return 0;
}
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
-int dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
+int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
{
int bcmerror = 0;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* Basic sanity checks */
- if (bus->dhd->up) {
+ if (bus->drvr->up) {
bcmerror = -EISCONN;
goto err;
}
@@ -2125,7 +2530,7 @@ err:
}
static int
-dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
+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)
{
@@ -2133,11 +2538,11 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
s32 int_val = 0;
bool bool_val = 0;
- DHD_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));
+ 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 = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
+ bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
if (bcmerror != 0)
goto exit;
@@ -2147,10 +2552,10 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
bool_val = (int_val != 0) ? true : false;
/* Some ioctls use the bus */
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
- if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
+ if (bus->drvr->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
actionid == IOV_GVAL(IOV_DEVRESET))) {
bcmerror = -EPERM;
goto exit;
@@ -2159,7 +2564,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
/* Handle sleep stuff before any clock mucking */
if (vi->varid == IOV_SLEEP) {
if (IOV_ISSET(actionid)) {
- bcmerror = dhdsdio_bussleep(bus, bool_val);
+ bcmerror = brcmf_sdbrcm_bussleep(bus, bool_val);
} else {
int_val = (s32) bus->sleeping;
memcpy(arg, &int_val, val_size);
@@ -2168,9 +2573,9 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
}
/* Request clock to allow SDIO accesses */
- if (!bus->dhd->dongle_reset) {
+ if (!bus->drvr->dongle_reset) {
BUS_WAKE(bus);
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
}
switch (actionid) {
@@ -2182,15 +2587,13 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
case IOV_SVAL(IOV_INTR):
bus->intr = bool_val;
bus->intdis = false;
- if (bus->dhd->up) {
+ if (bus->drvr->up) {
+ BRCMF_INTR(("%s: %s SDIO interrupts\n", __func__,
+ bus->intr ? "enable" : "disable"));
if (bus->intr) {
- DHD_INTR(("%s: enable SDIO device interrupts\n",
- __func__));
- bcmsdh_intr_enable(bus->sdh);
+ brcmf_sdcard_intr_enable(bus->card);
} else {
- DHD_INTR(("%s: disable SDIO interrupts\n",
- __func__));
- bcmsdh_intr_disable(bus->sdh);
+ brcmf_sdcard_intr_disable(bus->card);
}
}
break;
@@ -2211,7 +2614,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
break;
case IOV_SVAL(IOV_IDLETIME):
- if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE))
+ if ((int_val < 0) && (int_val != BRCMF_IDLE_IMMEDIATE))
bcmerror = -EINVAL;
else
bus->idletime = int_val;
@@ -2244,8 +2647,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
- ASSERT(plen >= 2 * sizeof(int));
-
address = (u32) int_val;
memcpy(&int_val, (char *)params + sizeof(int_val),
sizeof(int_val));
@@ -2254,25 +2655,25 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
/* Do some validation */
dsize = set ? plen - (2 * sizeof(int)) : len;
if (dsize < size) {
- DHD_ERROR(("%s: error on %s membytes, addr "
- "0x%08x size %d dsize %d\n",
- __func__, (set ? "set" : "get"),
- address, size, dsize));
+ 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;
}
- DHD_INFO(("%s: Request to %s %d bytes at address "
- "0x%08x\n",
- __func__, (set ? "write" : "read"), size, address));
+ 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))) {
- DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d "
- "bytes at 0x%08x\n",
- __func__, bus->orig_ramsize, size, address));
+ BRCMF_ERROR(("%s: ramsize 0x%08x doesn't have"
+ " %d bytes at 0x%08x\n", __func__,
+ bus->orig_ramsize, size, address));
bcmerror = -EINVAL;
break;
}
@@ -2283,8 +2684,8 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
2 * sizeof(int) : (u8 *) arg;
/* Call to do the transfer */
- bcmerror =
- dhdsdio_membytes(bus, set, address, data, size);
+ bcmerror = brcmf_sdbrcm_membytes(bus, set, address,
+ data, size);
break;
}
@@ -2295,33 +2696,33 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
break;
case IOV_GVAL(IOV_SDIOD_DRIVE):
- int_val = (s32) dhd_sdiod_drive_strength;
+ int_val = (s32) brcmf_sdiod_drive_strength;
memcpy(arg, &int_val, val_size);
break;
case IOV_SVAL(IOV_SDIOD_DRIVE):
- dhd_sdiod_drive_strength = int_val;
- dhdsdio_sdiod_drive_strength_init(bus,
- dhd_sdiod_drive_strength);
+ brcmf_sdiod_drive_strength = int_val;
+ brcmf_sdbrcm_sdiod_drive_strength_init(bus,
+ brcmf_sdiod_drive_strength);
break;
case IOV_SVAL(IOV_DOWNLOAD):
- bcmerror = dhdsdio_download_state(bus, bool_val);
+ bcmerror = brcmf_sdbrcm_download_state(bus, bool_val);
break;
case IOV_SVAL(IOV_VARS):
- bcmerror = dhdsdio_downloadvars(bus, arg, len);
+ bcmerror = brcmf_sdbrcm_downloadvars(bus, arg, len);
break;
case IOV_GVAL(IOV_READAHEAD):
- int_val = (s32) dhd_readahead;
+ int_val = (s32) brcmf_readahead;
memcpy(arg, &int_val, val_size);
break;
case IOV_SVAL(IOV_READAHEAD):
- if (bool_val && !dhd_readahead)
+ if (bool_val && !brcmf_readahead)
bus->nextlen = 0;
- dhd_readahead = bool_val;
+ brcmf_readahead = bool_val;
break;
case IOV_GVAL(IOV_SDRXCHAIN):
@@ -2336,40 +2737,56 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
bus->use_rxchain = bool_val;
break;
case IOV_GVAL(IOV_ALIGNCTL):
- int_val = (s32) dhd_alignctl;
+ int_val = (s32) brcmf_alignctl;
memcpy(arg, &int_val, val_size);
break;
case IOV_SVAL(IOV_ALIGNCTL):
- dhd_alignctl = bool_val;
+ brcmf_alignctl = bool_val;
break;
case IOV_GVAL(IOV_SDALIGN):
- int_val = DHD_SDALIGN;
+ int_val = BRCMF_SDALIGN;
memcpy(arg, &int_val, val_size);
break;
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
case IOV_GVAL(IOV_VARS):
if (bus->varsz < (uint) len)
memcpy(arg, bus->vars, bus->varsz);
else
bcmerror = -EOVERFLOW;
break;
-#endif /* DHD_DEBUG */
+#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;
-#ifdef DHD_DEBUG
case IOV_GVAL(IOV_SDREG):
{
- sdreg_t *sd_ptr;
+ struct brcmf_sdreg *sd_ptr;
u32 addr, size;
- sd_ptr = (sdreg_t *) params;
+ sd_ptr = (struct brcmf_sdreg *) params;
- addr = (unsigned long)bus->regs + sd_ptr->offset;
+ addr = bus->ci->buscorebase + sd_ptr->offset;
size = sd_ptr->func;
- int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
- if (bcmsdh_regfail(bus->sdh))
+ 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;
@@ -2377,15 +2794,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
case IOV_SVAL(IOV_SDREG):
{
- sdreg_t *sd_ptr;
+ struct brcmf_sdreg *sd_ptr;
u32 addr, size;
- sd_ptr = (sdreg_t *) params;
+ sd_ptr = (struct brcmf_sdreg *) params;
- addr = (unsigned long)bus->regs + sd_ptr->offset;
+ addr = bus->ci->buscorebase + sd_ptr->offset;
size = sd_ptr->func;
- bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
- if (bcmsdh_regfail(bus->sdh))
+ brcmf_sdcard_reg_write(bus->card, addr, size,
+ sd_ptr->value);
+ if (brcmf_sdcard_regfail(bus->card))
bcmerror = -EIO;
break;
}
@@ -2394,15 +2812,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
(not SDIO core) */
case IOV_GVAL(IOV_SBREG):
{
- sdreg_t sdreg;
+ struct brcmf_sdreg sdreg;
u32 addr, size;
memcpy(&sdreg, params, sizeof(sdreg));
addr = SI_ENUM_BASE + sdreg.offset;
size = sdreg.func;
- int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
- if (bcmsdh_regfail(bus->sdh))
+ 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;
@@ -2410,15 +2829,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
case IOV_SVAL(IOV_SBREG):
{
- sdreg_t sdreg;
+ struct brcmf_sdreg sdreg;
u32 addr, size;
memcpy(&sdreg, params, sizeof(sdreg));
addr = SI_ENUM_BASE + sdreg.offset;
size = sdreg.func;
- bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
- if (bcmsdh_regfail(bus->sdh))
+ brcmf_sdcard_reg_write(bus->card, addr, size,
+ sdreg.value);
+ if (brcmf_sdcard_regfail(bus->card))
bcmerror = -EIO;
break;
}
@@ -2428,15 +2848,15 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
*(char *)arg = 0;
strcat(arg, "\nFunc 0\n");
- bcmsdh_cis_read(bus->sdh, 0x10,
+ brcmf_sdcard_cis_read(bus->card, 0x10,
(u8 *) arg + strlen(arg),
SBSDIO_CIS_SIZE_LIMIT);
strcat(arg, "\nFunc 1\n");
- bcmsdh_cis_read(bus->sdh, 0x11,
+ brcmf_sdcard_cis_read(bus->card, 0x11,
(u8 *) arg + strlen(arg),
SBSDIO_CIS_SIZE_LIMIT);
strcat(arg, "\nFunc 2\n");
- bcmsdh_cis_read(bus->sdh, 0x12,
+ brcmf_sdcard_cis_read(bus->card, 0x12,
(u8 *) arg + strlen(arg),
SBSDIO_CIS_SIZE_LIMIT);
break;
@@ -2452,32 +2872,32 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
break;
case IOV_GVAL(IOV_TXBOUND):
- int_val = (s32) dhd_txbound;
+ int_val = (s32) brcmf_txbound;
memcpy(arg, &int_val, val_size);
break;
case IOV_SVAL(IOV_TXBOUND):
- dhd_txbound = (uint) int_val;
+ brcmf_txbound = (uint) int_val;
break;
case IOV_GVAL(IOV_RXBOUND):
- int_val = (s32) dhd_rxbound;
+ int_val = (s32) brcmf_rxbound;
memcpy(arg, &int_val, val_size);
break;
case IOV_SVAL(IOV_RXBOUND):
- dhd_rxbound = (uint) int_val;
+ brcmf_rxbound = (uint) int_val;
break;
case IOV_GVAL(IOV_TXMINMAX):
- int_val = (s32) dhd_txminmax;
+ int_val = (s32) brcmf_txminmax;
memcpy(arg, &int_val, val_size);
break;
case IOV_SVAL(IOV_TXMINMAX):
- dhd_txminmax = (uint) int_val;
+ brcmf_txminmax = (uint) int_val;
break;
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
#ifdef SDTEST
case IOV_GVAL(IOV_EXTLOOP):
@@ -2490,31 +2910,44 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
break;
case IOV_GVAL(IOV_PKTGEN):
- bcmerror = dhdsdio_pktgen_get(bus, arg);
+ bcmerror = brcmf_sdbrcm_pktgen_get(bus, arg);
break;
case IOV_SVAL(IOV_PKTGEN):
- bcmerror = dhdsdio_pktgen_set(bus, arg);
+ bcmerror = brcmf_sdbrcm_pktgen_set(bus, arg);
break;
#endif /* SDTEST */
case IOV_SVAL(IOV_DEVRESET):
- DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
- "busstate=%d\n",
- __func__, bool_val, bus->dhd->dongle_reset,
- bus->dhd->busstate));
+ BRCMF_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
+ "busstate=%d\n",
+ __func__, bool_val, bus->drvr->dongle_reset,
+ bus->drvr->busstate));
- dhd_bus_devreset(bus->dhd, (u8) bool_val);
+ brcmf_bus_devreset(bus->drvr, (u8) bool_val);
break;
case IOV_GVAL(IOV_DEVRESET):
- DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
+ BRCMF_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
/* Get its status */
- int_val = (bool) bus->dhd->dongle_reset;
+ 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:
@@ -2523,29 +2956,29 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
}
exit:
- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
bus->activity = false;
- dhdsdio_clkctl(bus, CLK_NONE, true);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
}
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
- dhd_preinit_ioctls((dhd_pub_t *) bus->dhd);
+ brcmf_c_preinit_ioctls(bus->drvr);
return bcmerror;
}
-static int dhdsdio_write_vars(dhd_bus_t *bus)
+static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
{
int bcmerror = 0;
u32 varsize;
u32 varaddr;
u8 *vbuffer;
u32 varsizew;
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
char *nvram_ularray;
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
/* Even if there are no vars are to be written, we still
need to set the ramsize. */
@@ -2561,10 +2994,10 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
/* Write the vars list */
bcmerror =
- dhdsdio_membytes(bus, true, varaddr, vbuffer, varsize);
-#ifdef DHD_DEBUG
+ brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
+#ifdef BCMDBG
/* Verify NVRAM bytes */
- DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
+ BRCMF_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
if (!nvram_ularray)
return -ENOMEM;
@@ -2574,30 +3007,31 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
/* Read the vars list to temp buffer for comparison */
bcmerror =
- dhdsdio_membytes(bus, false, varaddr, nvram_ularray,
+ brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
varsize);
if (bcmerror) {
- DHD_ERROR(("%s: error %d on reading %d nvram bytes at "
- "0x%08x\n", __func__, bcmerror, varsize, varaddr));
+ 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)) {
- DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n",
- __func__));
+ BRCMF_ERROR(("%s: Downloaded NVRAM image is "
+ "corrupted.\n", __func__));
} else
- DHD_ERROR(("%s: Download/Upload/Compare of NVRAM ok.\n",
- __func__));
+ BRCMF_ERROR(("%s: Download/Upload/Compare of"
+ " NVRAM ok.\n", __func__));
kfree(nvram_ularray);
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
kfree(vbuffer);
}
/* adjust to the user specified RAM */
- DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
- bus->orig_ramsize, bus->ramsize));
- DHD_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
+ 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);
/*
@@ -2613,17 +3047,17 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
varsizew = cpu_to_le32(varsizew);
}
- DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
- varsizew));
+ BRCMF_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
+ varsizew));
/* Write the length token to the last word */
- bcmerror = dhdsdio_membytes(bus, true, (bus->orig_ramsize - 4),
+ bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->orig_ramsize - 4),
(u8 *)&varsizew, 4);
return bcmerror;
}
-static int dhdsdio_download_state(dhd_bus_t *bus, bool enter)
+static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
{
uint retries;
u32 regdata;
@@ -2635,139 +3069,114 @@ static int dhdsdio_download_state(dhd_bus_t *bus, bool enter)
if (enter) {
bus->alp_only = true;
- dhdsdio_chip_disablecore(bus->sdh, bus->ci->armcorebase);
+ brcmf_sdbrcm_chip_disablecore(bus->card, bus->ci->armcorebase);
- dhdsdio_chip_resetcore(bus->sdh, bus->ci->ramcorebase);
+ brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->ramcorebase);
/* Clear the top bit of memory */
if (bus->ramsize) {
u32 zeros = 0;
- dhdsdio_membytes(bus, true, bus->ramsize - 4,
+ brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
(u8 *)&zeros, 4);
}
} else {
- regdata = bcmsdh_reg_read(bus->sdh,
+ 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) {
- DHD_ERROR(("%s: SOCRAM core is down after reset?\n",
- __func__));
+ BRCMF_ERROR(("%s: SOCRAM core is down after reset?\n",
+ __func__));
bcmerror = -EBADE;
goto fail;
}
- bcmerror = dhdsdio_write_vars(bus);
+ bcmerror = brcmf_sdbrcm_write_vars(bus);
if (bcmerror) {
- DHD_ERROR(("%s: no vars written to RAM\n", __func__));
+ BRCMF_ERROR(("%s: no vars written to RAM\n", __func__));
bcmerror = 0;
}
- W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
+ w_sdreg32(bus, 0xFFFFFFFF,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
- dhdsdio_chip_resetcore(bus->sdh, bus->ci->armcorebase);
+ brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->armcorebase);
/* Allow HT Clock now that the ARM is running. */
bus->alp_only = false;
- bus->dhd->busstate = DHD_BUS_LOAD;
+ bus->drvr->busstate = BRCMF_BUS_LOAD;
}
fail:
return bcmerror;
}
int
-dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
- void *params, int plen, void *arg, int len, bool set)
+brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
{
- dhd_bus_t *bus = dhdp->bus;
- const bcm_iovar_t *vi = NULL;
+ struct brcmf_bus *bus = drvr->bus;
+ const struct brcmu_iovar *vi = NULL;
int bcmerror = 0;
int val_size;
u32 actionid;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- ASSERT(name);
- ASSERT(len >= 0);
+ if (name == NULL || len <= 0)
+ return -EINVAL;
- /* Get MUST have return space */
- ASSERT(set || (arg && len));
+ /* Set does not take qualifiers */
+ if (set && (params || plen))
+ return -EINVAL;
- /* Set does NOT take qualifiers */
- ASSERT(!set || (!params && !plen));
+ /* Get must have return space;*/
+ if (!set && !(arg && len))
+ return -EINVAL;
/* Look up var locally; if not found pass to host driver */
- vi = bcm_iovar_lookup(dhdsdio_iovars, name);
+ vi = brcmu_iovar_lookup(brcmf_sdio_iovars, name);
if (vi == NULL) {
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
BUS_WAKE(bus);
/* Turn on clock in case SD command needs backplane */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+ bcmerror = brcmf_sdcard_iovar_op(bus->card, name, params, plen,
+ arg, len, set);
- bcmerror =
- bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len,
- set);
-
- /* Check for bus configuration changes of interest */
-
- /* If it was divisor change, read the new one */
- if (set && strcmp(name, "sd_divisor") == 0) {
- if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
- &bus->sd_divisor, sizeof(s32),
- false) != 0) {
- bus->sd_divisor = -1;
- DHD_ERROR(("%s: fail on %s get\n", __func__,
- name));
- } else {
- DHD_INFO(("%s: noted %s update, value now %d\n",
- __func__, name, bus->sd_divisor));
- }
- }
- /* If it was a mode change, read the new one */
- if (set && strcmp(name, "sd_mode") == 0) {
- if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
- &bus->sd_mode, sizeof(s32),
- false) != 0) {
- bus->sd_mode = -1;
- DHD_ERROR(("%s: fail on %s get\n", __func__,
- name));
- } else {
- DHD_INFO(("%s: noted %s update, value now %d\n",
- __func__, name, bus->sd_mode));
- }
- }
/* Similar check for blocksize change */
if (set && strcmp(name, "sd_blocksize") == 0) {
s32 fnum = 2;
- if (bcmsdh_iovar_op
- (bus->sdh, "sd_blocksize", &fnum, sizeof(s32),
+ if (brcmf_sdcard_iovar_op
+ (bus->card, "sd_blocksize", &fnum, sizeof(s32),
&bus->blocksize, sizeof(s32),
false) != 0) {
bus->blocksize = 0;
- DHD_ERROR(("%s: fail on %s get\n", __func__,
- "sd_blocksize"));
+ BRCMF_ERROR(("%s: fail on %s get\n", __func__,
+ "sd_blocksize"));
} else {
- DHD_INFO(("%s: noted %s update, value now %d\n",
- __func__, "sd_blocksize",
- bus->blocksize));
+ BRCMF_INFO(("%s: noted sd_blocksize update,"
+ " value now %d\n", __func__,
+ bus->blocksize));
}
}
bus->roundup = min(max_roundup, bus->blocksize);
- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
+ !bus->dpc_sched) {
bus->activity = false;
- dhdsdio_clkctl(bus, CLK_NONE, true);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
}
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
goto exit;
}
- DHD_CTL(("%s: %s %s, len %d plen %d\n", __func__,
- name, (set ? "set" : "get"), len, plen));
+ 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
@@ -2786,168 +3195,188 @@ dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
val_size = sizeof(int);
actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- bcmerror =
- dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len,
- val_size);
+ bcmerror = brcmf_sdbrcm_doiovar(bus, vi, actionid, name, params, plen,
+ arg, len, val_size);
exit:
return bcmerror;
}
-void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
+void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex)
{
u32 local_hostintmask;
u8 saveclk;
uint retries;
int err;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
if (enforce_mutex)
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
BUS_WAKE(bus);
/* Enable clock for device interrupts */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ 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_SDREG(0, &bus->regs->hostintmask, retries);
+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
local_hostintmask = bus->hostintmask;
bus->hostintmask = 0;
/* Change our idea of bus state */
- bus->dhd->busstate = DHD_BUS_DOWN;
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
/* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk =
- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
+ saveclk = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (!err) {
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
}
if (err) {
- DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
- __func__, err));
+ BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
+ __func__, err));
}
/* Turn off the bus (F2), free any pending packets */
- DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
- bcmsdh_intr_disable(bus->sdh);
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
+ 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_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
+ w_sdreg32(bus, local_hostintmask,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
/* Turn off the backplane clock (only) */
- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
/* Clear the data packet queues */
- bcm_pktq_flush(&bus->txq, true, NULL, NULL);
+ brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
/* Clear any held glomming stuff */
if (bus->glomd)
- bcm_pkt_buf_free_skb(bus->glomd);
+ brcmu_pkt_buf_free_skb(bus->glomd);
if (bus->glom)
- bcm_pkt_buf_free_skb(bus->glom);
+ brcmu_pkt_buf_free_skb(bus->glom);
bus->glom = bus->glomd = NULL;
/* Clear rx control and wake any waiters */
bus->rxlen = 0;
- dhd_os_ioctl_resp_wake(bus->dhd);
+ 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)
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
}
-int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
+int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex)
{
- dhd_bus_t *bus = dhdp->bus;
- dhd_timeout_t tmo;
+ struct brcmf_bus *bus = drvr->bus;
+ struct brcmf_timeout tmo;
uint retries = 0;
u8 ready, enable;
int err, ret = 0;
u8 saveclk;
- DHD_TRACE(("%s: Enter\n", __func__));
+ 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;
+ }
- ASSERT(bus->dhd);
- if (!bus->dhd)
+ if (!bus->drvr)
return 0;
+ /* Start the watchdog timer */
+ bus->drvr->tickcnt = 0;
+ brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
+
if (enforce_mutex)
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
/* Make sure backplane clock is on, needed to generate F2 interrupt */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ 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 =
- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
+ brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (!err) {
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
}
if (err) {
- DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
- __func__, err));
+ BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
+ __func__, err));
goto exit;
}
/* Enable function 2 (frame transfers) */
- W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
- &bus->regs->tosbmailboxdata, retries);
+ 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);
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
+ 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 */
- dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
+ brcmf_timeout_start(&tmo, BRCMF_WAIT_F2RDY * 1000);
ready = 0;
- while (ready != enable && !dhd_timeout_expired(&tmo))
- ready =
- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY,
- NULL);
+ while (ready != enable && !brcmf_timeout_expired(&tmo))
+ ready = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0,
+ SDIO_CCCR_IORx, NULL);
- DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
- __func__, enable, ready, tmo.elapsed));
+ 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_SDREG(bus->hostintmask,
- (unsigned int *)CORE_BUS_REG(bus->ci->buscorebase,
- hostintmask), retries);
+ w_sdreg32(bus, bus->hostintmask,
+ offsetof(struct sdpcmd_regs, hostintmask), &retries);
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_WATERMARK,
(u8) watermark, &err);
/* Set bus state according to enable result */
- dhdp->busstate = DHD_BUS_DATA;
-
- /* bcmsdh_intr_unmask(bus->sdh); */
+ drvr->busstate = BRCMF_BUS_DATA;
bus->intdis = false;
if (bus->intr) {
- DHD_INTR(("%s: enable SDIO device interrupts\n",
- __func__));
- bcmsdh_intr_enable(bus->sdh);
+ BRCMF_INTR(("%s: enable SDIO device interrupts\n",
+ __func__));
+ brcmf_sdcard_intr_enable(bus->card);
} else {
- DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
- bcmsdh_intr_disable(bus->sdh);
+ BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
+ brcmf_sdcard_intr_disable(bus->card);
}
}
@@ -2955,75 +3384,90 @@ int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
else {
/* Disable F2 again */
enable = SDIO_FUNC_ENABLE_1;
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable,
- NULL);
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ enable, NULL);
}
/* Restore previous clock setting */
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ 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 (dhdp->busstate != DHD_BUS_DATA)
- dhdsdio_clkctl(bus, CLK_NONE, false);
+ if (drvr->busstate != BRCMF_BUS_DATA)
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
exit:
if (enforce_mutex)
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
return ret;
}
-static void dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
+static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
{
- bcmsdh_info_t *sdh = bus->sdh;
- sdpcmd_regs_t *regs = bus->regs;
+ struct brcmf_sdio_card *card = bus->card;
uint retries = 0;
u16 lastrbc;
u8 hi, lo;
int err;
- DHD_ERROR(("%s: %sterminate frame%s\n", __func__,
- (abort ? "abort command, " : ""),
- (rtx ? ", send NAK" : "")));
+ BRCMF_ERROR(("%s: %sterminate frame%s\n", __func__,
+ (abort ? "abort command, " : ""),
+ (rtx ? ", send NAK" : "")));
if (abort)
- bcmsdh_abort(sdh, SDIO_FUNC_2);
+ brcmf_sdcard_abort(card, SDIO_FUNC_2);
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
- &err);
+ 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 = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI,
- NULL);
- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO,
- NULL);
+ 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))) {
- DHD_ERROR(("%s: count growing: last 0x%04x now "
- "0x%04x\n",
- __func__, lastrbc, ((hi << 8) + lo)));
+ BRCMF_ERROR(("%s: count growing: last 0x%04x now "
+ "0x%04x\n",
+ __func__, lastrbc, ((hi << 8) + lo)));
}
lastrbc = (hi << 8) + lo;
}
if (!retries) {
- DHD_ERROR(("%s: count never zeroed: last 0x%04x\n",
- __func__, lastrbc));
+ BRCMF_ERROR(("%s: count never zeroed: last 0x%04x\n",
+ __func__, lastrbc));
} else {
- DHD_INFO(("%s: flush took %d iterations\n", __func__,
- (0xffff - retries)));
+ BRCMF_INFO(("%s: flush took %d iterations\n", __func__,
+ (0xffff - retries)));
}
if (rtx) {
bus->rxrtx++;
- W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
+ w_sdreg32(bus, SMB_NAK,
+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
+
bus->f1regdata++;
if (retries <= retry_limit)
bus->rxskip = true;
@@ -3033,35 +3477,33 @@ static void dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
bus->nextlen = 0;
/* If we can't reach the device, signal failure */
- if (err || bcmsdh_regfail(sdh))
- bus->dhd->busstate = DHD_BUS_DOWN;
+ if (err || brcmf_sdcard_regfail(card))
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
}
static void
-dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
+brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
{
- bcmsdh_info_t *sdh = bus->sdh;
+ struct brcmf_sdio_card *card = bus->card;
uint rdlen, pad;
int sdret;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* Control data already received in aligned rxctl */
if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
goto gotpkt;
- ASSERT(bus->rxbuf);
/* Set rxctl for frame (w/optional alignment) */
bus->rxctl = bus->rxbuf;
- if (dhd_alignctl) {
+ if (brcmf_alignctl) {
bus->rxctl += firstread;
- pad = ((unsigned long)bus->rxctl % DHD_SDALIGN);
+ pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
if (pad)
- bus->rxctl += (DHD_SDALIGN - pad);
+ bus->rxctl += (BRCMF_SDALIGN - pad);
bus->rxctl -= firstread;
}
- ASSERT(bus->rxctl >= bus->rxbuf);
/* Copy the already-read portion over */
memcpy(bus->rxctl, hdr, firstread);
@@ -3079,10 +3521,10 @@ dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
pad = bus->blocksize - (rdlen % bus->blocksize);
if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
- ((len + pad) < bus->dhd->maxctl))
+ ((len + pad) < bus->drvr->maxctl))
rdlen += pad;
- } else if (rdlen % DHD_SDALIGN) {
- rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+ } else if (rdlen % BRCMF_SDALIGN) {
+ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
}
/* Satisfy length-alignment requirements */
@@ -3090,44 +3532,44 @@ dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
rdlen = roundup(rdlen, ALIGNMENT);
/* Drop if the read is too big or it exceeds our maximum */
- if ((rdlen + firstread) > bus->dhd->maxctl) {
- DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
- __func__, rdlen, bus->dhd->maxctl));
- bus->dhd->rx_errors++;
- dhdsdio_rxfail(bus, false, false);
+ 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->dhd->maxctl) {
- DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
- "%d-byte limit\n",
- __func__, len, (len - doff), bus->dhd->maxctl));
- bus->dhd->rx_errors++;
+ 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++;
- dhdsdio_rxfail(bus, false, false);
+ brcmf_sdbrcm_rxfail(bus, false, false);
goto done;
}
/* Read remainder of frame body into the rxctl buffer */
- sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
+ sdret = brcmf_sdcard_recv_buf(card, brcmf_sdcard_cur_sbwad(card),
+ SDIO_FUNC_2,
F2SYNC, (bus->rxctl + firstread), rdlen,
NULL, NULL, NULL);
bus->f2rxdata++;
- ASSERT(sdret != -BCME_PENDING);
/* Control frame failures need retransmission */
if (sdret < 0) {
- DHD_ERROR(("%s: read %d control bytes failed: %d\n",
- __func__, rdlen, sdret));
- bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
- dhdsdio_rxfail(bus, true, true);
+ 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 DHD_DEBUG
- if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
printk(KERN_DEBUG "RxCtrl:\n");
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
}
@@ -3139,10 +3581,10 @@ gotpkt:
done:
/* Awake any waiters */
- dhd_os_ioctl_resp_wake(bus->dhd);
+ brcmf_os_ioctl_resp_wake(bus->drvr);
}
-static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
+static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
{
u16 dlen, totlen;
u8 *dptr, num = 0;
@@ -3160,19 +3602,18 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
/* If packets, issue read(s) and send up packet chain */
/* Return sequence numbers consumed? */
- DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd,
- bus->glom));
+ 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) {
- dhd_os_sdlock_rxq(bus->dhd);
-
pfirst = plast = pnext = NULL;
dlen = (u16) (bus->glomd->len);
dptr = bus->glomd->data;
if (!dlen || (dlen & 1)) {
- DHD_ERROR(("%s: bad glomd len(%d), ignore descriptor\n",
- __func__, dlen));
+ BRCMF_ERROR(("%s: bad glomd len(%d),"
+ " ignore descriptor\n",
+ __func__, dlen));
dlen = 0;
}
@@ -3183,14 +3624,15 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
dptr += sizeof(u16);
if ((sublen < SDPCM_HDRLEN) ||
((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
- DHD_ERROR(("%s: descriptor len %d bad: %d\n",
- __func__, num, sublen));
+ BRCMF_ERROR(("%s: descriptor len %d bad: %d\n",
+ __func__, num, sublen));
pnext = NULL;
break;
}
- if (sublen % DHD_SDALIGN) {
- DHD_ERROR(("%s: sublen %d not multiple of %d\n",
- __func__, sublen, DHD_SDALIGN));
+ if (sublen % BRCMF_SDALIGN) {
+ BRCMF_ERROR(("%s: sublen %d not multiple of"
+ " %d\n", __func__, sublen,
+ BRCMF_SDALIGN));
usechain = false;
}
totlen += sublen;
@@ -3204,123 +3646,120 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
}
/* Allocate/chain packet for next subframe */
- pnext = bcm_pkt_buf_get_skb(sublen + DHD_SDALIGN);
+ pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN);
if (pnext == NULL) {
- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
- "num %d len %d\n", __func__,
- num, sublen));
+ BRCMF_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
+ "num %d len %d\n", __func__,
+ num, sublen));
break;
}
- ASSERT(!(pnext->prev));
if (!pfirst) {
- ASSERT(!plast);
pfirst = plast = pnext;
} else {
- ASSERT(plast);
plast->next = pnext;
plast = pnext;
}
/* Adhere to start alignment requirements */
- PKTALIGN(pnext, sublen, DHD_SDALIGN);
+ PKTALIGN(pnext, sublen, BRCMF_SDALIGN);
}
/* If all allocations succeeded, save packet chain
in bus structure */
if (pnext) {
- DHD_GLOM(("%s: allocated %d-byte packet chain for %d "
- "subframes\n", __func__, totlen, num));
- if (DHD_GLOM_ON() && bus->nextlen) {
+ 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) {
- DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d " "rxseq %d\n",
- __func__, bus->nextlen,
- totlen, rxseq));
+ 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)
- bcm_pkt_buf_free_skb(pfirst);
+ brcmu_pkt_buf_free_skb(pfirst);
bus->glom = NULL;
num = 0;
}
/* Done with descriptor packet */
- bcm_pkt_buf_free_skb(bus->glomd);
+ brcmu_pkt_buf_free_skb(bus->glomd);
bus->glomd = NULL;
bus->nextlen = 0;
-
- dhd_os_sdunlock_rxq(bus->dhd);
}
/* Ok -- either we just generated a packet chain,
or had one from before */
if (bus->glom) {
- if (DHD_GLOM_ON()) {
- DHD_GLOM(("%s: try superframe read, packet chain:\n",
- __func__));
+ if (BRCMF_GLOM_ON()) {
+ BRCMF_GLOM(("%s: try superframe read, packet chain:\n",
+ __func__));
for (pnext = bus->glom; pnext; pnext = pnext->next) {
- DHD_GLOM((" %p: %p len 0x%04x (%d)\n",
- pnext, (u8 *) (pnext->data),
- pnext->len, pnext->len));
+ BRCMF_GLOM((" %p: %p len 0x%04x (%d)\n",
+ pnext, (u8 *) (pnext->data),
+ pnext->len, pnext->len));
}
}
pfirst = bus->glom;
- dlen = (u16) bcm_pkttotlen(pfirst);
+ 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 = bcmsdh_recv_buf(bus,
- bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+ 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 = bcmsdh_recv_buf(bus,
- bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+ 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) bcm_pktfrombuf(pfirst, 0, dlen,
+ sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
bus->dataptr);
if (sublen != dlen) {
- DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
- __func__, dlen, sublen));
+ BRCMF_ERROR(("%s: FAILED TO COPY, dlen %d "
+ "sublen %d\n",
+ __func__, dlen, sublen));
errcode = -1;
}
pnext = NULL;
} else {
- DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
- dlen));
+ BRCMF_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, "
+ "FORCE FAILURE\n", dlen));
errcode = -1;
}
bus->f2rxdata++;
- ASSERT(errcode != -BCME_PENDING);
/* On failure, kill the superframe, allow a couple retries */
if (errcode < 0) {
- DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
- __func__, dlen, errcode));
- bus->dhd->rx_errors++;
+ BRCMF_ERROR(("%s: glom read of %d bytes failed: %d\n",
+ __func__, dlen, errcode));
+ bus->drvr->rx_errors++;
if (bus->glomerr++ < 3) {
- dhdsdio_rxfail(bus, true, true);
+ brcmf_sdbrcm_rxfail(bus, true, true);
} else {
bus->glomerr = 0;
- dhdsdio_rxfail(bus, true, false);
- dhd_os_sdlock_rxq(bus->dhd);
- bcm_pkt_buf_free_skb(bus->glom);
- dhd_os_sdunlock_rxq(bus->dhd);
+ brcmf_sdbrcm_rxfail(bus, true, false);
+ brcmu_pkt_buf_free_skb(bus->glom);
bus->rxglomfail++;
bus->glom = NULL;
}
return 0;
}
-#ifdef DHD_DEBUG
- if (DHD_GLOM_ON()) {
+#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));
@@ -3336,8 +3775,8 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- DHD_INFO(("%s: nextlen too large (%d) seq %d\n",
- __func__, bus->nextlen, seq));
+ 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]);
@@ -3345,47 +3784,48 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
errcode = 0;
if ((u16)~(sublen ^ check)) {
- DHD_ERROR(("%s (superframe): HW hdr error: len/check "
- "0x%04x/0x%04x\n", __func__, 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) {
- DHD_ERROR(("%s (superframe): len 0x%04x, rounded "
- "0x%04x, expect 0x%04x\n",
- __func__, sublen,
- 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) {
- DHD_ERROR(("%s (superframe): bad channel %d\n",
+ 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])) {
- DHD_ERROR(("%s (superframe): got second descriptor?\n",
- __func__));
+ BRCMF_ERROR(("%s (superframe): got 2nd descriptor?\n",
+ __func__));
errcode = -1;
} else if ((doff < SDPCM_HDRLEN) ||
(doff > (pfirst->len - SDPCM_HDRLEN))) {
- DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d "
- "pkt %d min %d\n",
- __func__, doff, sublen,
- 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) {
- DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
- __func__, seq, rxseq));
+ 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) {
- DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
+ 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;
@@ -3403,8 +3843,8 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
check = get_unaligned_le16(dptr + sizeof(u16));
chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-#ifdef DHD_DEBUG
- if (DHD_GLOM_ON()) {
+#ifdef BCMDBG
+ if (BRCMF_GLOM_ON()) {
printk(KERN_DEBUG "subframe:\n");
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
dptr, 32);
@@ -3412,24 +3852,25 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
#endif
if ((u16)~(sublen ^ check)) {
- DHD_ERROR(("%s (subframe %d): HW hdr error: "
- "len/check 0x%04x/0x%04x\n",
- __func__, num, 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)) {
- DHD_ERROR(("%s (subframe %d): length mismatch: "
- "len 0x%04x, expect 0x%04x\n",
- __func__, num, sublen, dlen));
+ 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)) {
- DHD_ERROR(("%s (subframe %d): bad channel %d\n",
- __func__, num, chan));
+ BRCMF_ERROR(("%s (subframe %d): bad channel"
+ " %d\n", __func__, num, chan));
errcode = -1;
} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
- DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
- __func__, num, doff, sublen,
- SDPCM_HDRLEN));
+ BRCMF_ERROR(("%s (subframe %d): Bad data offset"
+ " %d: HW %d min %d\n",
+ __func__, num, doff, sublen,
+ SDPCM_HDRLEN));
errcode = -1;
}
}
@@ -3440,13 +3881,11 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
if (bus->glomerr++ < 3) {
/* Restore superframe header space */
skb_push(pfirst, sfdoff);
- dhdsdio_rxfail(bus, true, true);
+ brcmf_sdbrcm_rxfail(bus, true, true);
} else {
bus->glomerr = 0;
- dhdsdio_rxfail(bus, true, false);
- dhd_os_sdlock_rxq(bus->dhd);
- bcm_pkt_buf_free_skb(bus->glom);
- dhd_os_sdunlock_rxq(bus->dhd);
+ brcmf_sdbrcm_rxfail(bus, true, false);
+ brcmu_pkt_buf_free_skb(bus->glom);
bus->rxglomfail++;
bus->glom = NULL;
}
@@ -3459,7 +3898,6 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
bus->glom = NULL;
plast = NULL;
- dhd_os_sdlock_rxq(bus->dhd);
for (num = 0; pfirst; rxseq++, pfirst = pnext) {
pnext = pfirst->next;
pfirst->next = NULL;
@@ -3470,22 +3908,22 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
- DHD_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));
+ 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));
- ASSERT((chan == SDPCM_DATA_CHANNEL)
- || (chan == SDPCM_EVENT_CHANNEL));
+ /* precondition: chan == SDPCM_DATA_CHANNEL ||
+ chan == SDPCM_EVENT_CHANNEL */
if (rxseq != seq) {
- DHD_GLOM(("%s: rx_seq %d, expected %d\n",
- __func__, seq, rxseq));
+ BRCMF_GLOM(("%s: rx_seq %d, expected %d\n",
+ __func__, seq, rxseq));
bus->rx_badseq++;
rxseq = seq;
}
-#ifdef DHD_DEBUG
- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#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);
@@ -3496,24 +3934,22 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
skb_pull(pfirst, doff);
if (pfirst->len == 0) {
- bcm_pkt_buf_free_skb(pfirst);
+ brcmu_pkt_buf_free_skb(pfirst);
if (plast) {
plast->next = pnext;
} else {
- ASSERT(save_pfirst == pfirst);
save_pfirst = pnext;
}
continue;
- } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) !=
- 0) {
- DHD_ERROR(("%s: rx protocol error\n",
- __func__));
- bus->dhd->rx_errors++;
- bcm_pkt_buf_free_skb(pfirst);
+ } 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 {
- ASSERT(save_pfirst == pfirst);
save_pfirst = pnext;
}
continue;
@@ -3525,24 +3961,23 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
plast = pfirst;
num++;
-#ifdef DHD_DEBUG
- if (DHD_GLOM_ON()) {
- DHD_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));
+#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 /* DHD_DEBUG */
+#endif /* BCMDBG */
}
- dhd_os_sdunlock_rxq(bus->dhd);
if (num) {
- dhd_os_sdunlock(bus->dhd);
- dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num);
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
+ brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
+ brcmf_sdbrcm_sdlock(bus);
}
bus->rxglomframes++;
@@ -3552,9 +3987,10 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
}
/* Return true if there may be more frames to read */
-static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
+static uint
+brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
{
- bcmsdh_info_t *sdh = bus->sdh;
+ struct brcmf_sdio_card *card = bus->card;
u16 len, check; /* Extracted hardware header fields */
u8 chan, seq, doff; /* Extracted software header fields */
@@ -3565,7 +4001,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
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 bcmsdh calls */
+ 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 */
@@ -3573,17 +4009,15 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
int ifidx = 0;
uint rxcount = 0; /* Total frames read */
-#if defined(DHD_DEBUG) || defined(SDTEST)
+#if defined(BCMDBG) || defined(SDTEST)
bool sdtest = false; /* To limit message spew from test mode */
#endif
- DHD_TRACE(("%s: Enter\n", __func__));
-
- ASSERT(maxframes);
+ BRCMF_TRACE(("%s: Enter\n", __func__));
#ifdef SDTEST
/* Allow pktgen to override maxframes */
- if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
+ if (bus->pktgen_count && (bus->pktgen_mode == BRCMF_PKTGEN_RECV)) {
maxframes = bus->pktgen_count;
sdtest = true;
}
@@ -3593,23 +4027,23 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
*finished = false;
for (rxseq = bus->rx_seq, rxleft = maxframes;
- !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
+ !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN;
rxseq++, rxleft--) {
/* Handle glomming separately */
if (bus->glom || bus->glomd) {
u8 cnt;
- DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
- __func__, bus->glomd, bus->glom));
- cnt = dhdsdio_rxglom(bus, rxseq);
- DHD_GLOM(("%s: rxglom returned %d\n", __func__, 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 (dhd_readahead && bus->nextlen) {
+ if (brcmf_readahead && bus->nextlen) {
u16 nextlen = bus->nextlen;
bus->nextlen = 0;
@@ -3629,9 +4063,9 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
&& ((rdlen + pad + firstread) <
MAX_RX_DATASZ))
rdlen += pad;
- } else if (rdlen % DHD_SDALIGN) {
+ } else if (rdlen % BRCMF_SDALIGN) {
rdlen +=
- DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+ BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
}
}
@@ -3646,42 +4080,40 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
* or non-data frame.
*/
/* Allocate a packet buffer */
- dhd_os_sdlock_rxq(bus->dhd);
- pkt = bcm_pkt_buf_get_skb(rdlen + DHD_SDALIGN);
+ pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN);
if (!pkt) {
if (bus->bus == SPI_BUS) {
bus->usebufpool = false;
bus->rxctl = bus->rxbuf;
- if (dhd_alignctl) {
+ if (brcmf_alignctl) {
bus->rxctl += firstread;
pad = ((unsigned long)bus->rxctl %
- DHD_SDALIGN);
+ BRCMF_SDALIGN);
if (pad)
bus->rxctl +=
- (DHD_SDALIGN - pad);
+ (BRCMF_SDALIGN - pad);
bus->rxctl -= firstread;
}
- ASSERT(bus->rxctl >= bus->rxbuf);
rxbuf = bus->rxctl;
/* Read the entire frame */
- sdret = bcmsdh_recv_buf(bus,
- bcmsdh_cur_sbwad(sdh),
- SDIO_FUNC_2, F2SYNC,
- rxbuf, rdlen,
- NULL, NULL, NULL);
+ sdret = brcmf_sdcard_recv_buf(card,
+ brcmf_sdcard_cur_sbwad(card),
+ SDIO_FUNC_2, F2SYNC,
+ rxbuf, rdlen,
+ NULL, NULL, NULL);
bus->f2rxdata++;
- ASSERT(sdret != -BCME_PENDING);
/* Control frame failures need
retransmission */
if (sdret < 0) {
- DHD_ERROR(("%s: read %d control bytes failed: %d\n",
- __func__,
- rdlen, sdret));
+ BRCMF_ERROR(("%s: read %d "
+ "control bytes "
+ "failed: %d\n",
+ __func__,
+ rdlen, sdret));
/* dhd.rx_ctlerrs is higher */
bus->rxc_errors++;
- dhd_os_sdunlock_rxq(bus->dhd);
- dhdsdio_rxfail(bus, true,
+ brcmf_sdbrcm_rxfail(bus, true,
(bus->bus ==
SPI_BUS) ? false
: true);
@@ -3690,50 +4122,45 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
} else {
/* Give up on data,
request rtx of events */
- DHD_ERROR(("%s (nextlen): "
- "bcm_pkt_buf_get_skb failed:"
- " len %d rdlen %d expected"
- " rxseq %d\n", __func__,
- len, rdlen, rxseq));
- /* Just go try again w/normal
- header read */
- dhd_os_sdunlock_rxq(bus->dhd);
+ 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;
- ASSERT(!(pkt->prev));
- PKTALIGN(pkt, rdlen, DHD_SDALIGN);
+ PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
rxbuf = (u8 *) (pkt->data);
/* Read the entire frame */
- sdret = bcmsdh_recv_buf(bus,
- bcmsdh_cur_sbwad(sdh),
+ sdret = brcmf_sdcard_recv_buf(card,
+ brcmf_sdcard_cur_sbwad(card),
SDIO_FUNC_2, F2SYNC,
rxbuf, rdlen,
pkt, NULL, NULL);
bus->f2rxdata++;
- ASSERT(sdret != -BCME_PENDING);
if (sdret < 0) {
- DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
- __func__, rdlen, sdret));
- bcm_pkt_buf_free_skb(pkt);
- bus->dhd->rx_errors++;
- dhd_os_sdunlock_rxq(bus->dhd);
+ 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
*/
- dhdsdio_rxfail(bus, true,
+ brcmf_sdbrcm_rxfail(bus, true,
(bus->bus ==
SPI_BUS) ? false :
true);
continue;
}
}
- dhd_os_sdunlock_rxq(bus->dhd);
/* Now check the header */
memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
@@ -3744,29 +4171,29 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
/* All zeros means readahead info was bad */
if (!(len | check)) {
- DHD_INFO(("%s (nextlen): read zeros in HW "
- "header???\n", __func__));
- dhdsdio_pktfree2(bus, pkt);
+ BRCMF_INFO(("%s (nextlen): read zeros in HW "
+ "header???\n", __func__));
+ brcmf_sdbrcm_pktfree2(bus, pkt);
continue;
}
/* Validate check bytes */
if ((u16)~(len ^ check)) {
- DHD_ERROR(("%s (nextlen): HW hdr error:"
- " nextlen/len/check"
- " 0x%04x/0x%04x/0x%04x\n",
- __func__, nextlen, 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++;
- dhdsdio_rxfail(bus, false, false);
- dhdsdio_pktfree2(bus, pkt);
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ brcmf_sdbrcm_pktfree2(bus, pkt);
continue;
}
/* Validate frame length */
if (len < SDPCM_HDRLEN) {
- DHD_ERROR(("%s (nextlen): HW hdr length "
- "invalid: %d\n", __func__, len));
- dhdsdio_pktfree2(bus, pkt);
+ BRCMF_ERROR(("%s (nextlen): HW hdr length "
+ "invalid: %d\n", __func__, len));
+ brcmf_sdbrcm_pktfree2(bus, pkt);
continue;
}
@@ -3775,13 +4202,14 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
if (len_consistent) {
/* Mismatch, force retry w/normal
header (may be >4K) */
- DHD_ERROR(("%s (nextlen): mismatch, "
- "nextlen %d len %d rnd %d; "
- "expected rxseq %d\n",
- __func__, nextlen,
- len, roundup(len, 16), rxseq));
- dhdsdio_rxfail(bus, true, (bus->bus != SPI_BUS));
- dhdsdio_pktfree2(bus, pkt);
+ 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;
}
@@ -3799,12 +4227,13 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
bus->rxhdr[SDPCM_FRAMETAG_LEN +
SDPCM_NEXTLEN_OFFSET];
if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- DHD_INFO(("%s (nextlen): got frame w/nextlen too large" " (%d), seq %d\n",
- __func__, bus->nextlen, seq));
+ BRCMF_INFO(("%s (nextlen): got frame w/nextlen"
+ " too large (%d), seq %d\n",
+ __func__, bus->nextlen, seq));
bus->nextlen = 0;
}
- bus->dhd->rx_readahead_cnt++;
+ bus->drvr->rx_readahead_cnt++;
/* Handle Flow Control */
fcbits = SDPCM_FCMASK_VALUE(
@@ -3823,27 +4252,27 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
/* Check and update sequence number */
if (rxseq != seq) {
- DHD_INFO(("%s (nextlen): rx_seq %d, expected "
- "%d\n", __func__, seq, rxseq));
+ 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) {
- DHD_ERROR(("%s: got unlikely tx max %d with "
- "tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
+ 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 DHD_DEBUG
- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#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 (DHD_HDRS_ON()) {
+ } else if (BRCMF_HDRS_ON()) {
printk(KERN_DEBUG "RxHdr:\n");
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
bus->rxhdr, SDPCM_HDRLEN);
@@ -3852,31 +4281,35 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
if (chan == SDPCM_CONTROL_CHANNEL) {
if (bus->bus == SPI_BUS) {
- dhdsdio_read_control(bus, rxbuf, len,
- doff);
+ brcmf_sdbrcm_read_control(bus, rxbuf,
+ len, doff);
} else {
- DHD_ERROR(("%s (nextlen): readahead on control" " packet %d?\n",
- __func__, seq));
+ BRCMF_ERROR(("%s (nextlen): readahead"
+ " on control packet %d?\n",
+ __func__, seq));
/* Force retry w/normal header read */
bus->nextlen = 0;
- dhdsdio_rxfail(bus, false, true);
+ brcmf_sdbrcm_rxfail(bus, false, true);
}
- dhdsdio_pktfree2(bus, pkt);
+ brcmf_sdbrcm_pktfree2(bus, pkt);
continue;
}
if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
- DHD_ERROR(("Received %d bytes on %d channel. Running out of " "rx pktbuf's or not yet malloced.\n",
- len, chan));
+ 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)) {
- DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
- __func__, doff, len, SDPCM_HDRLEN));
- dhdsdio_rxfail(bus, false, false);
- dhdsdio_pktfree2(bus, pkt);
+ 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;
}
@@ -3888,21 +4321,21 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
break;
/* Read frame header (hardware and software) */
- sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
+ sdret = brcmf_sdcard_recv_buf(card,
+ brcmf_sdcard_cur_sbwad(card),
SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread,
NULL, NULL, NULL);
bus->f2rxhdrs++;
- ASSERT(sdret != -BCME_PENDING);
if (sdret < 0) {
- DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
- sdret));
+ BRCMF_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
+ sdret));
bus->rx_hdrfail++;
- dhdsdio_rxfail(bus, true, true);
+ brcmf_sdbrcm_rxfail(bus, true, true);
continue;
}
-#ifdef DHD_DEBUG
- if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
+#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);
@@ -3921,17 +4354,17 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
/* Validate check bytes */
if ((u16) ~(len ^ check)) {
- DHD_ERROR(("%s: HW hdr err: len/check 0x%04x/0x%04x\n",
- __func__, len, check));
+ BRCMF_ERROR(("%s: HW hdr err: len/check "
+ "0x%04x/0x%04x\n", __func__, len, check));
bus->rx_badhdr++;
- dhdsdio_rxfail(bus, false, false);
+ brcmf_sdbrcm_rxfail(bus, false, false);
continue;
}
/* Validate frame length */
if (len < SDPCM_HDRLEN) {
- DHD_ERROR(("%s: HW hdr length invalid: %d\n",
- __func__, len));
+ BRCMF_ERROR(("%s: HW hdr length invalid: %d\n",
+ __func__, len));
continue;
}
@@ -3943,12 +4376,11 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
/* Validate data offset */
if ((doff < SDPCM_HDRLEN) || (doff > len)) {
- DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d "
- "seq %d\n",
- __func__, doff, len, SDPCM_HDRLEN, seq));
+ BRCMF_ERROR(("%s: Bad data offset %d: HW len %d,"
+ " min %d seq %d\n", __func__, doff,
+ len, SDPCM_HDRLEN, seq));
bus->rx_badhdr++;
- ASSERT(0);
- dhdsdio_rxfail(bus, false, false);
+ brcmf_sdbrcm_rxfail(bus, false, false);
continue;
}
@@ -3956,9 +4388,9 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
bus->nextlen =
bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- DHD_INFO(("%s (nextlen): got frame w/nextlen too large "
- "(%d), seq %d\n",
- __func__, bus->nextlen, seq));
+ BRCMF_INFO(("%s (nextlen): got frame w/nextlen too"
+ " large (%d), seq %d\n",
+ __func__, bus->nextlen, seq));
bus->nextlen = 0;
}
@@ -3978,30 +4410,29 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
/* Check and update sequence number */
if (rxseq != seq) {
- DHD_INFO(("%s: rx_seq %d, expected %d\n", __func__,
- seq, rxseq));
+ 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) {
- DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
+ 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) {
- dhdsdio_read_control(bus, bus->rxhdr, len, doff);
+ brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff);
continue;
}
- ASSERT((chan == SDPCM_DATA_CHANNEL)
- || (chan == SDPCM_EVENT_CHANNEL)
- || (chan == SDPCM_TEST_CHANNEL)
- || (chan == SDPCM_GLOM_CHANNEL));
+ /* 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;
@@ -4013,8 +4444,8 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
((rdlen + pad + firstread) < MAX_RX_DATASZ))
rdlen += pad;
- } else if (rdlen % DHD_SDALIGN) {
- rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+ } else if (rdlen % BRCMF_SDALIGN) {
+ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
}
/* Satisfy length-alignment requirements */
@@ -4023,54 +4454,45 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
if ((rdlen + firstread) > MAX_RX_DATASZ) {
/* Too long -- skip this frame */
- DHD_ERROR(("%s: too long: len %d rdlen %d\n",
- __func__, len, rdlen));
- bus->dhd->rx_errors++;
+ BRCMF_ERROR(("%s: too long: len %d rdlen %d\n",
+ __func__, len, rdlen));
+ bus->drvr->rx_errors++;
bus->rx_toolong++;
- dhdsdio_rxfail(bus, false, false);
+ brcmf_sdbrcm_rxfail(bus, false, false);
continue;
}
- dhd_os_sdlock_rxq(bus->dhd);
- pkt = bcm_pkt_buf_get_skb(rdlen + firstread + DHD_SDALIGN);
+ pkt = brcmu_pkt_buf_get_skb(rdlen + firstread + BRCMF_SDALIGN);
if (!pkt) {
/* Give up on data, request rtx of events */
- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed: rdlen %d "
- "chan %d\n", __func__, rdlen, chan));
- bus->dhd->rx_dropped++;
- dhd_os_sdunlock_rxq(bus->dhd);
- dhdsdio_rxfail(bus, false, RETRYCHAN(chan));
+ 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;
}
- dhd_os_sdunlock_rxq(bus->dhd);
-
- ASSERT(!(pkt->prev));
/* Leave room for what we already read, and align remainder */
- ASSERT(firstread < pkt->len);
skb_pull(pkt, firstread);
- PKTALIGN(pkt, rdlen, DHD_SDALIGN);
+ PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
/* Read the remaining frame data */
- sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
- F2SYNC, ((u8 *) (pkt->data)), rdlen,
- pkt, NULL, NULL);
+ sdret = brcmf_sdcard_recv_buf(card,
+ brcmf_sdcard_cur_sbwad(card),
+ SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)),
+ rdlen, pkt, NULL, NULL);
bus->f2rxdata++;
- ASSERT(sdret != -BCME_PENDING);
if (sdret < 0) {
- DHD_ERROR(("%s: read %d %s bytes failed: %d\n",
- __func__, rdlen,
- ((chan ==
- SDPCM_EVENT_CHANNEL) ? "event" : ((chan ==
- SDPCM_DATA_CHANNEL)
- ? "data" : "test")),
- sdret));
- dhd_os_sdlock_rxq(bus->dhd);
- bcm_pkt_buf_free_skb(pkt);
- dhd_os_sdunlock_rxq(bus->dhd);
- bus->dhd->rx_errors++;
- dhdsdio_rxfail(bus, true, RETRYCHAN(chan));
+ 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;
}
@@ -4078,8 +4500,8 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
skb_push(pkt, firstread);
memcpy(pkt->data, bus->rxhdr, firstread);
-#ifdef DHD_DEBUG
- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#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);
@@ -4090,10 +4512,10 @@ deliver:
/* Save superframe descriptor and allocate packet frame */
if (chan == SDPCM_GLOM_CHANNEL) {
if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
- DHD_GLOM(("%s: glom descriptor, %d bytes:\n",
- __func__, len));
-#ifdef DHD_DEBUG
- if (DHD_GLOM_ON()) {
+ 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,
@@ -4101,13 +4523,12 @@ deliver:
}
#endif
__skb_trim(pkt, len);
- ASSERT(doff == SDPCM_HDRLEN);
skb_pull(pkt, SDPCM_HDRLEN);
bus->glomd = pkt;
} else {
- DHD_ERROR(("%s: glom superframe w/o "
- "descriptor!\n", __func__));
- dhdsdio_rxfail(bus, false, false);
+ BRCMF_ERROR(("%s: glom superframe w/o "
+ "descriptor!\n", __func__));
+ brcmf_sdbrcm_rxfail(bus, false, false);
}
continue;
}
@@ -4119,39 +4540,35 @@ deliver:
#ifdef SDTEST
/* Test channel packets are processed separately */
if (chan == SDPCM_TEST_CHANNEL) {
- dhdsdio_testrcv(bus, pkt, seq);
+ brcmf_sdbrcm_checkdied(bus, pkt, seq);
continue;
}
#endif /* SDTEST */
if (pkt->len == 0) {
- dhd_os_sdlock_rxq(bus->dhd);
- bcm_pkt_buf_free_skb(pkt);
- dhd_os_sdunlock_rxq(bus->dhd);
+ brcmu_pkt_buf_free_skb(pkt);
continue;
- } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) {
- DHD_ERROR(("%s: rx protocol error\n", __func__));
- dhd_os_sdlock_rxq(bus->dhd);
- bcm_pkt_buf_free_skb(pkt);
- dhd_os_sdunlock_rxq(bus->dhd);
- bus->dhd->rx_errors++;
+ } 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 */
- dhd_os_sdunlock(bus->dhd);
- dhd_rx_frame(bus->dhd, ifidx, pkt, 1);
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
+ brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
+ brcmf_sdbrcm_sdlock(bus);
}
rxcount = maxframes - rxleft;
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
/* Message if we hit the limit */
if (!rxleft && !sdtest)
- DHD_DATA(("%s: hit rx limit of %d frames\n", __func__,
- maxframes));
+ BRCMF_DATA(("%s: hit rx limit of %d frames\n", __func__,
+ maxframes));
else
-#endif /* DHD_DEBUG */
- DHD_DATA(("%s: processed %d frames\n", __func__, rxcount));
+#endif /* BCMDBG */
+ BRCMF_DATA(("%s: processed %d frames\n", __func__, rxcount));
/* Back off rxseq if awaiting rtx, update rx_seq */
if (bus->rxskip)
rxseq--;
@@ -4160,28 +4577,30 @@ deliver:
return rxcount;
}
-static u32 dhdsdio_hostmail(dhd_bus_t *bus)
+static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
{
- sdpcmd_regs_t *regs = bus->regs;
u32 intstatus = 0;
u32 hmb_data;
u8 fcbits;
uint retries = 0;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* Read mailbox data and ack that we did so */
- R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
+ r_sdreg32(bus, &hmb_data,
+ offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
+
if (retries <= retry_limit)
- W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
+ 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) {
- DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
- bus->rx_seq));
+ BRCMF_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
+ bus->rx_seq));
if (!bus->rxskip)
- DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
+ BRCMF_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
bus->rxskip = false;
intstatus |= I_HMB_FRAME_IND;
@@ -4195,12 +4614,12 @@ static u32 dhdsdio_hostmail(dhd_bus_t *bus)
(hmb_data & HMB_DATA_VERSION_MASK) >>
HMB_DATA_VERSION_SHIFT;
if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
- DHD_ERROR(("Version mismatch, dongle reports %d, "
- "expecting %d\n",
- bus->sdpcm_ver, SDPCM_PROT_VERSION));
+ BRCMF_ERROR(("Version mismatch, dongle reports %d, "
+ "expecting %d\n",
+ bus->sdpcm_ver, SDPCM_PROT_VERSION));
else
- DHD_INFO(("Dongle ready, protocol version %d\n",
- bus->sdpcm_ver));
+ BRCMF_INFO(("Dongle ready, protocol version %d\n",
+ bus->sdpcm_ver));
}
/*
@@ -4228,78 +4647,74 @@ static u32 dhdsdio_hostmail(dhd_bus_t *bus)
HMB_DATA_FC |
HMB_DATA_FWREADY |
HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) {
- DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
+ BRCMF_ERROR(("Unknown mailbox data content: 0x%02x\n",
+ hmb_data));
}
return intstatus;
}
-bool dhdsdio_dpc(dhd_bus_t *bus)
+static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
{
- bcmsdh_info_t *sdh = bus->sdh;
- sdpcmd_regs_t *regs = bus->regs;
+ struct brcmf_sdio_card *card = bus->card;
u32 intstatus, newstatus = 0;
uint retries = 0;
- uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
- uint txlimit = dhd_txbound; /* Tx frames to send before resched */
+ 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 */
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* Start with leftover status bits */
intstatus = bus->intstatus;
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
/* If waiting for HTAVAIL, check status */
if (bus->clkstate == CLK_PENDING) {
int err;
u8 clkctl, devctl = 0;
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
/* Check for inconsistent device control */
- devctl =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+ devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
if (err) {
- DHD_ERROR(("%s: error reading DEVCTL: %d\n",
- __func__, err));
- bus->dhd->busstate = DHD_BUS_DOWN;
- } else {
- ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
+ BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
+ __func__, err));
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
}
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
/* Read CSR, if clock on switch to AVAIL, else ignore */
- clkctl =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
+ clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err) {
- DHD_ERROR(("%s: error reading CSR: %d\n", __func__,
- err));
- bus->dhd->busstate = DHD_BUS_DOWN;
+ BRCMF_ERROR(("%s: error reading CSR: %d\n", __func__,
+ err));
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
}
- DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl,
- clkctl));
+ BRCMF_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
+ devctl, clkctl));
if (SBSDIO_HTAV(clkctl)) {
- devctl =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- &err);
+ devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
if (err) {
- DHD_ERROR(("%s: error reading DEVCTL: %d\n",
- __func__, err));
- bus->dhd->busstate = DHD_BUS_DOWN;
+ BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
+ __func__, err));
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
}
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- devctl, &err);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, devctl, &err);
if (err) {
- DHD_ERROR(("%s: error writing DEVCTL: %d\n",
- __func__, err));
- bus->dhd->busstate = DHD_BUS_DOWN;
+ BRCMF_ERROR(("%s: error writing DEVCTL: %d\n",
+ __func__, err));
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
}
bus->clkstate = CLK_AVAIL;
} else {
@@ -4310,21 +4725,24 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
BUS_WAKE(bus);
/* Make sure backplane clock is on */
- dhdsdio_clkctl(bus, CLK_AVAIL, true);
+ 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_SDREG(newstatus, &regs->intstatus, retries);
+ r_sdreg32(bus, &newstatus,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
bus->f1regdata++;
- if (bcmsdh_regfail(bus->sdh))
+ if (brcmf_sdcard_regfail(bus->card))
newstatus = 0;
newstatus &= bus->hostintmask;
bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
if (newstatus) {
- W_SDREG(newstatus, &regs->intstatus, retries);
+ w_sdreg32(bus, newstatus,
+ offsetof(struct sdpcmd_regs, intstatus),
+ &retries);
bus->f1regdata++;
}
}
@@ -4339,8 +4757,11 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
*/
if (intstatus & I_HMB_FC_CHANGE) {
intstatus &= ~I_HMB_FC_CHANGE;
- W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
- R_SDREG(newstatus, &regs->intstatus, retries);
+ 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));
@@ -4350,28 +4771,28 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
/* Handle host mailbox indication */
if (intstatus & I_HMB_HOST_INT) {
intstatus &= ~I_HMB_HOST_INT;
- intstatus |= dhdsdio_hostmail(bus);
+ intstatus |= brcmf_sdbrcm_hostmail(bus);
}
/* Generally don't ask for these, can get CRC errors... */
if (intstatus & I_WR_OOSYNC) {
- DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
+ BRCMF_ERROR(("Dongle reports WR_OOSYNC\n"));
intstatus &= ~I_WR_OOSYNC;
}
if (intstatus & I_RD_OOSYNC) {
- DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
+ BRCMF_ERROR(("Dongle reports RD_OOSYNC\n"));
intstatus &= ~I_RD_OOSYNC;
}
if (intstatus & I_SBINT) {
- DHD_ERROR(("Dongle reports SBINT\n"));
+ BRCMF_ERROR(("Dongle reports SBINT\n"));
intstatus &= ~I_SBINT;
}
/* Would be active due to wake-wlan in gSPI */
if (intstatus & I_CHIPACTIVE) {
- DHD_INFO(("Dongle reports CHIPACTIVE\n"));
+ BRCMF_INFO(("Dongle reports CHIPACTIVE\n"));
intstatus &= ~I_CHIPACTIVE;
}
@@ -4381,7 +4802,7 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
/* On frame indication, read available frames */
if (PKT_AVAILABLE()) {
- framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
+ framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone);
if (rxdone || bus->rxskip)
intstatus &= ~I_HMB_FRAME_IND;
rxlimit -= min(framecnt, rxlimit);
@@ -4391,51 +4812,45 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
bus->intstatus = intstatus;
clkwait:
-#if defined(OOB_INTR_ONLY)
- bcmsdh_oob_intr_set(1);
-#endif /* (OOB_INTR_ONLY) */
/* 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 && !bcmsdh_regfail(sdh)) {
- DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
- __func__, rxdone, framecnt));
+ 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;
- bcmsdh_intr_enable(sdh);
+ brcmf_sdcard_intr_enable(card);
}
if (DATAOK(bus) && bus->ctrl_frame_stat &&
(bus->clkstate == CLK_AVAIL)) {
int ret, i;
- ret =
- dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
- F2SYNC, (u8 *) bus->ctrl_frame_buf,
- (u32) bus->ctrl_frame_len, NULL,
- NULL, NULL);
- ASSERT(ret != -BCME_PENDING);
+ 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 */
- DHD_INFO(("%s: sdio error %d, abort command and "
- "terminate frame.\n", __func__, ret));
+ BRCMF_INFO(("%s: sdio error %d, abort command and "
+ "terminate frame.\n", __func__, ret));
bus->tx_sderrs++;
- bcmsdh_abort(sdh, SDIO_FUNC_2);
+ brcmf_sdcard_abort(card, SDIO_FUNC_2);
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+ 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 = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCHI,
NULL);
- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCLO,
NULL);
bus->f1regdata += 2;
@@ -4447,16 +4862,16 @@ clkwait:
if (ret == 0)
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
- DHD_INFO(("Return_dpc value is : %d\n", ret));
+ BRCMF_INFO(("Return_dpc value is : %d\n", ret));
bus->ctrl_frame_stat = false;
- dhd_wait_event_wakeup(bus->dhd);
+ 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 &&
- bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
+ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
&& DATAOK(bus)) {
- framecnt = rxdone ? txlimit : min(txlimit, dhd_txminmax);
- framecnt = dhdsdio_sendfromq(bus, framecnt);
+ framecnt = rxdone ? txlimit : min(txlimit, brcmf_txminmax);
+ framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt);
txlimit -= framecnt;
}
@@ -4464,18 +4879,20 @@ clkwait:
else await next interrupt */
/* On failed register access, all bets are off:
no resched or interrupts */
- if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
- DHD_ERROR(("%s: failed backplane access over SDIO, halting "
- "operation %d\n", __func__, bcmsdh_regfail(sdh)));
- bus->dhd->busstate = DHD_BUS_DOWN;
+ 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) {
- DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
- "I_CHIPACTIVE interrupt\n", __func__));
+ BRCMF_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
+ "I_CHIPACTIVE interrupt\n", __func__));
resched = true;
} else if (bus->intstatus || bus->ipend ||
- (!bus->fcstate && bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
- DATAOK(bus)) || PKT_AVAILABLE()) {
+ (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
+ && DATAOK(bus)) || PKT_AVAILABLE()) {
resched = true;
}
@@ -4483,42 +4900,31 @@ clkwait:
/* If we're done for now, turn off clock request. */
if ((bus->clkstate != CLK_PENDING)
- && bus->idletime == DHD_IDLE_IMMEDIATE) {
+ && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
bus->activity = false;
- dhdsdio_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
}
- dhd_os_sdunlock(bus->dhd);
-
- return resched;
-}
-
-bool dhd_bus_dpc(struct dhd_bus *bus)
-{
- bool resched;
-
- /* Call the DPC directly. */
- DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
- resched = dhdsdio_dpc(bus);
+ brcmf_sdbrcm_sdunlock(bus);
return resched;
}
-void dhdsdio_isr(void *arg)
+void brcmf_sdbrcm_isr(void *arg)
{
- dhd_bus_t *bus = (dhd_bus_t *) arg;
- bcmsdh_info_t *sdh;
+ struct brcmf_bus *bus = (struct brcmf_bus *) arg;
+ struct brcmf_sdio_card *card;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
if (!bus) {
- DHD_ERROR(("%s : bus is null pointer , exit\n", __func__));
+ BRCMF_ERROR(("%s : bus is null pointer , exit\n", __func__));
return;
}
- sdh = bus->sdh;
+ card = bus->card;
- if (bus->dhd->busstate == DHD_BUS_DOWN) {
- DHD_ERROR(("%s : bus is down. we have nothing to do\n",
+ if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
+ BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
__func__));
return;
}
@@ -4528,54 +4934,55 @@ void dhdsdio_isr(void *arg)
/* Shouldn't get this interrupt if we're sleeping? */
if (bus->sleeping) {
- DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
+ BRCMF_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
return;
}
/* Disable additional interrupts (is this needed now)? */
if (bus->intr)
- DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
+ BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
else
- DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
+ BRCMF_ERROR(("brcmf_sdbrcm_isr() w/o interrupt configured!\n"));
- bcmsdh_intr_disable(sdh);
+ brcmf_sdcard_intr_disable(card);
bus->intdis = true;
#if defined(SDIO_ISR_THREAD)
- DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
- while (dhdsdio_dpc(bus))
+ BRCMF_TRACE(("Calling brcmf_sdbrcm_dpc() from %s\n", __func__));
+ while (brcmf_sdbrcm_dpc(bus))
;
#else
bus->dpc_sched = true;
- dhd_sched_dpc(bus->dhd);
+ brcmf_sdbrcm_sched_dpc(bus);
#endif
}
#ifdef SDTEST
-static void dhdsdio_pktgen_init(dhd_bus_t *bus)
+static void brcmf_sdbrcm_pktgen_init(struct brcmf_bus *bus)
{
/* Default to specified length, or full range */
- if (dhd_pktgen_len) {
- bus->pktgen_maxlen = min(dhd_pktgen_len, MAX_PKTGEN_LEN);
+ 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 = MAX_PKTGEN_LEN;
+ 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 / dhd_watchdog_ms;
- bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
+ bus->pktgen_print = 10000 / brcmf_watchdog_ms;
+ bus->pktgen_count = (brcmf_pktgen * brcmf_watchdog_ms + 999) / 1000;
/* Default to echo mode */
- bus->pktgen_mode = DHD_PKTGEN_ECHO;
+ bus->pktgen_mode = BRCMF_PKTGEN_ECHO;
bus->pktgen_stop = 1;
}
-static void dhdsdio_pktgen(dhd_bus_t *bus)
+static void brcmf_sdbrcm_pktgen(struct brcmf_bus *bus)
{
struct sk_buff *pkt;
u8 *data;
@@ -4591,9 +4998,9 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
}
/* For recv mode, just make sure dongle has started sending */
- if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
+ if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
if (!bus->pktgen_rcvd)
- dhdsdio_sdtest_set(bus, true);
+ brcmf_sdbrcm_sdtest_set(bus, true);
return;
}
@@ -4608,39 +5015,39 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
/* Allocate an appropriate-sized packet */
len = bus->pktgen_len;
- pkt = bcm_pkt_buf_get_skb(
- (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
+ pkt = brcmu_pkt_buf_get_skb(
+ len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN,
true);
if (!pkt) {
- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n",
- __func__));
+ BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n",
+ __func__));
break;
}
PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
- DHD_SDALIGN);
+ BRCMF_SDALIGN);
data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
/* Write test header cmd and extra based on mode */
switch (bus->pktgen_mode) {
- case DHD_PKTGEN_ECHO:
+ case BRCMF_PKTGEN_ECHO:
*data++ = SDPCM_TEST_ECHOREQ;
*data++ = (u8) bus->pktgen_sent;
break;
- case DHD_PKTGEN_SEND:
+ case BRCMF_PKTGEN_SEND:
*data++ = SDPCM_TEST_DISCARD;
*data++ = (u8) bus->pktgen_sent;
break;
- case DHD_PKTGEN_RXBURST:
+ case BRCMF_PKTGEN_RXBURST:
*data++ = SDPCM_TEST_BURST;
*data++ = (u8) bus->pktgen_count;
break;
default:
- DHD_ERROR(("Unrecognized pktgen mode %d\n",
- bus->pktgen_mode));
- bcm_pkt_buf_free_skb(pkt, true);
+ BRCMF_ERROR(("Unrecognized pktgen mode %d\n",
+ bus->pktgen_mode));
+ brcmu_pkt_buf_free_skb(pkt, true);
bus->pktgen_count = 0;
return;
}
@@ -4655,17 +5062,17 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
*data++ =
SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent);
-#ifdef DHD_DEBUG
- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
- printk(KERN_DEBUG "dhdsdio_pktgen: Tx Data:\n");
+ 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 (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
+ if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
bus->pktgen_fail++;
if (bus->pktgen_stop
&& bus->pktgen_stop == bus->pktgen_fail)
@@ -4678,24 +5085,24 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
bus->pktgen_len = (u16) bus->pktgen_minlen;
/* Special case for burst mode: just send one request! */
- if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
+ if (bus->pktgen_mode == BRCMF_PKTGEN_RXBURST)
break;
}
}
-static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
+static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start)
{
struct sk_buff *pkt;
u8 *data;
/* Allocate the packet */
- pkt = bcm_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
- DHD_SDALIGN, true);
+ pkt = brcmu_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
+ BRCMF_SDALIGN, true);
if (!pkt) {
- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n", __func__));
+ BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n", __func__));
return;
}
- PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
+ PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), BRCMF_SDALIGN);
data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
/* Fill in the test header */
@@ -4705,11 +5112,12 @@ static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
*data++ = (bus->pktgen_maxlen >> 8);
/* Send it */
- if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
+ if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
bus->pktgen_fail++;
}
-static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
+static void
+brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, struct sk_buff *pkt, uint seq)
{
u8 *data;
uint pktlen;
@@ -4722,9 +5130,9 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
/* Check for min length */
pktlen = pkt->len;
if (pktlen < SDPCM_TEST_HDRLEN) {
- DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n",
- pktlen));
- bcm_pkt_buf_free_skb(pkt, false);
+ BRCMF_ERROR(("brcmf_sdbrcm_checkdied: toss runt frame, pktlen "
+ "%d\n", pktlen));
+ brcmu_pkt_buf_free_skb(pkt, false);
return;
}
@@ -4739,10 +5147,11 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ
|| cmd == SDPCM_TEST_ECHORSP) {
if (pktlen != len + SDPCM_TEST_HDRLEN) {
- DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, "
- "pktlen %d seq %d" " cmd %d extra %d len %d\n",
- pktlen, seq, cmd, extra, len));
- bcm_pkt_buf_free_skb(pkt, false);
+ 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;
}
}
@@ -4753,76 +5162,80 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
/* Rx->Tx turnaround ok (even on NDIS w/current
implementation) */
*(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP;
- if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0) {
+ if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0)
bus->pktgen_sent++;
- } else {
+ else {
bus->pktgen_fail++;
- bcm_pkt_buf_free_skb(pkt, false);
+ brcmu_pkt_buf_free_skb(pkt, false);
}
bus->pktgen_rcvd++;
break;
case SDPCM_TEST_ECHORSP:
if (bus->ext_loop) {
- bcm_pkt_buf_free_skb(pkt, false);
+ 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)) {
- DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: " "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
- offset, len,
- SDPCM_TEST_FILL(offset, extra), *data));
+ 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;
}
}
- bcm_pkt_buf_free_skb(pkt, false);
+ brcmu_pkt_buf_free_skb(pkt, false);
bus->pktgen_rcvd++;
break;
case SDPCM_TEST_DISCARD:
- bcm_pkt_buf_free_skb(pkt, false);
+ brcmu_pkt_buf_free_skb(pkt, false);
bus->pktgen_rcvd++;
break;
case SDPCM_TEST_BURST:
case SDPCM_TEST_SEND:
default:
- DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, "
- "pktlen %d seq %d" " cmd %d extra %d len %d\n",
- pktlen, seq, cmd, extra, len));
- bcm_pkt_buf_free_skb(pkt, false);
+ 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 == DHD_PKTGEN_RECV) {
+ if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
if (bus->pktgen_total
&& (bus->pktgen_rcvd >= bus->pktgen_total)) {
bus->pktgen_count = 0;
- dhdsdio_sdtest_set(bus, false);
+ brcmf_sdbrcm_sdtest_set(bus, false);
}
}
}
#endif /* SDTEST */
-extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
+extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
{
- dhd_bus_t *bus;
+ struct brcmf_bus *bus;
- DHD_TIMER(("%s: Enter\n", __func__));
+ BRCMF_TIMER(("%s: Enter\n", __func__));
- bus = dhdp->bus;
+ bus = drvr->bus;
- if (bus->dhd->dongle_reset)
+ if (bus->drvr->dongle_reset)
return false;
/* Ignore the timer if simulating bus down */
if (bus->sleeping)
return false;
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
/* Poll period: check device if appropriate. */
if (bus->poll && (++bus->polltick >= bus->pollrate)) {
@@ -4836,9 +5249,9 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
if (!bus->dpc_sched) {
u8 devpend;
- devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
- SDIOD_CCCR_INTPEND,
- NULL);
+ devpend = brcmf_sdcard_cfg_read(bus->card,
+ SDIO_FUNC_0, SDIO_CCCR_INTx,
+ NULL);
intstatus =
devpend & (INTR_STATUS_FUNC1 |
INTR_STATUS_FUNC2);
@@ -4850,10 +5263,10 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
bus->pollcnt++;
bus->ipend = true;
if (bus->intr)
- bcmsdh_intr_disable(bus->sdh);
+ brcmf_sdcard_intr_disable(bus->card);
bus->dpc_sched = true;
- dhd_sched_dpc(bus->dhd);
+ brcmf_sdbrcm_sched_dpc(bus);
}
}
@@ -4861,28 +5274,28 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
/* Update interrupt tracking */
bus->lastintrs = bus->intrcount;
}
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
/* Poll for console output periodically */
- if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
- bus->console.count += dhd_watchdog_ms;
- if (bus->console.count >= dhd_console_ms) {
- bus->console.count -= dhd_console_ms;
+ 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 */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
- if (dhdsdio_readconsole(bus) < 0)
- dhd_console_ms = 0; /* On error,
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ if (brcmf_sdbrcm_readconsole(bus) < 0)
+ brcmf_console_ms = 0; /* On error,
stop trying */
}
}
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
#ifdef SDTEST
/* Generate packets if configured */
if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
/* Make sure backplane clock is on */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
bus->pktgen_tick = 0;
- dhdsdio_pktgen(bus);
+ brcmf_sdbrcm_pktgen(bus);
}
#endif
@@ -4892,22 +5305,23 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
bus->idlecount = 0;
if (bus->activity) {
bus->activity = false;
- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
} else {
- dhdsdio_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
}
}
}
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
return bus->ipend;
}
-#ifdef DHD_DEBUG
-extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
+#ifdef BCMDBG
+static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
+ unsigned char *msg, uint msglen)
{
- dhd_bus_t *bus = dhdp->bus;
+ struct brcmf_bus *bus = drvr->bus;
u32 addr, val;
int rv;
struct sk_buff *pkt;
@@ -4917,88 +5331,59 @@ extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
return -ENOTSUPP;
/* Exclusive bus access */
- dhd_os_sdlock(bus->dhd);
+ brcmf_sdbrcm_sdlock(bus);
/* Don't allow input if dongle is in reset */
- if (bus->dhd->dongle_reset) {
- dhd_os_sdunlock(bus->dhd);
+ 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 */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
/* Zero cbuf_index */
- addr = bus->console_addr + offsetof(hndrte_cons_t, cbuf_idx);
+ addr = bus->console_addr + offsetof(struct rte_console, cbuf_idx);
val = cpu_to_le32(0);
- rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
+ 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(hndrte_cons_t, cbuf);
- rv = dhdsdio_membytes(bus, true, addr, (u8 *)msg, msglen);
+ 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(hndrte_cons_t, vcons_in);
+ addr = bus->console_addr + offsetof(struct rte_console, vcons_in);
val = cpu_to_le32(msglen);
- rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
+ 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 = bcm_pkt_buf_get_skb(4 + SDPCM_RESERVE);
+ pkt = brcmu_pkt_buf_get_skb(4 + SDPCM_RESERVE);
if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
- dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
+ brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
done:
- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
bus->activity = false;
- dhdsdio_clkctl(bus, CLK_NONE, true);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
}
- dhd_os_sdunlock(bus->dhd);
+ brcmf_sdbrcm_sdunlock(bus);
return rv;
}
-#endif /* DHD_DEBUG */
-
-#ifdef DHD_DEBUG
-static void dhd_dump_cis(uint fn, u8 *cis)
-{
- uint byte, tag, tdata;
- DHD_INFO(("Function %d CIS:\n", fn));
-
- for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
- if ((byte % 16) == 0)
- DHD_INFO((" "));
- DHD_INFO(("%02x ", cis[byte]));
- if ((byte % 16) == 15)
- DHD_INFO(("\n"));
- if (!tdata--) {
- tag = cis[byte];
- if (tag == 0xff)
- break;
- else if (!tag)
- tdata = 0;
- else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
- tdata = cis[byte + 1] + 1;
- else
- DHD_INFO(("]"));
- }
- }
- if ((byte % 16) != 15)
- DHD_INFO(("\n"));
-}
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
-static bool dhdsdio_chipmatch(u16 chipid)
+static bool brcmf_sdbrcm_chipmatch(u16 chipid)
{
if (chipid == BCM4325_CHIP_ID)
return true;
@@ -5009,12 +5394,12 @@ static bool dhdsdio_chipmatch(u16 chipid)
return false;
}
-static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
- u16 slot, u16 func, uint bustype, void *regsva,
- void *sdh)
+static void *brcmf_sdbrcm_probe(u16 venid, u16 devid, u16 bus_no,
+ u16 slot, u16 func, uint bustype, u32 regsva,
+ void *card)
{
int ret;
- dhd_bus_t *bus;
+ 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.
@@ -5024,26 +5409,26 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
* first time that the driver is initialized vs subsequent
* initializations.
*/
- dhd_txbound = DHD_TXBOUND;
- dhd_rxbound = DHD_RXBOUND;
- dhd_alignctl = true;
+ brcmf_txbound = BRCMF_TXBOUND;
+ brcmf_rxbound = BRCMF_RXBOUND;
+ brcmf_alignctl = true;
sd1idle = true;
- dhd_readahead = true;
+ brcmf_readahead = true;
retrydata = false;
- dhd_dongle_memsize = 0;
- dhd_txminmax = DHD_TXMINMAX;
+ brcmf_dongle_memsize = 0;
+ brcmf_txminmax = BRCMF_TXMINMAX;
forcealign = true;
- dhd_common_init();
+ brcmf_c_init();
- DHD_TRACE(("%s: Enter\n", __func__));
- DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
+ BRCMF_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
- /* We make assumptions about address window mappings */
- ASSERT((unsigned long)regsva == SI_ENUM_BASE);
+ /* We make an assumption about address window mappings:
+ * regsva == SI_ENUM_BASE*/
- /* BCMSDH passes venid and devid based on CIS parsing -- but
+ /* 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.
@@ -5054,7 +5439,7 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
case PCI_VENDOR_ID_BROADCOM:
break;
default:
- DHD_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
+ BRCMF_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
return NULL;
}
@@ -5063,104 +5448,156 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
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 */
- DHD_INFO(("%s: found 4325 Dongle\n", __func__));
+ 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:
- DHD_INFO(("%s: found 4329 Dongle\n", __func__));
+ 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 */
- DHD_INFO(("%s: found 4319 Dongle\n", __func__));
+ BRCMF_INFO(("%s: found 4319 Dongle\n", __func__));
break;
case 0:
- DHD_INFO(("%s: allow device id 0, will check chip internals\n",
- __func__));
+ BRCMF_INFO(("%s: allow device id 0, will check chip"
+ " internals\n", __func__));
break;
default:
- DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
- __func__, venid, devid));
+ 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(dhd_bus_t), GFP_ATOMIC);
+ bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
if (!bus) {
- DHD_ERROR(("%s: kmalloc of dhd_bus_t failed\n", __func__));
+ BRCMF_ERROR(("%s: kmalloc of struct dhd_bus failed\n",
+ __func__));
goto fail;
}
- bus->sdh = sdh;
+ bus->card = card;
bus->cl_devid = (u16) devid;
- bus->bus = DHD_BUS;
+ 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 (!(dhdsdio_probe_attach(bus, sdh, regsva, devid))) {
- DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __func__));
+ if (!(brcmf_sdbrcm_probe_attach(bus, card, regsva, devid))) {
+ BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_attach failed\n",
+ __func__));
goto fail;
}
- /* Attach to the dhd/OS/network interface */
- bus->dhd = dhd_attach(bus, SDPCM_RESERVE);
- if (!bus->dhd) {
- DHD_ERROR(("%s: dhd_attach failed\n", __func__));
+ 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 (!(dhdsdio_probe_malloc(bus, sdh))) {
- DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __func__));
+ if (!(brcmf_sdbrcm_probe_malloc(bus, card))) {
+ BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_malloc failed\n",
+ __func__));
goto fail;
}
- if (!(dhdsdio_probe_init(bus, sdh))) {
- DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __func__));
+ 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). */
- DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
- __func__));
- bcmsdh_intr_disable(sdh);
- ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus);
+ 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) {
- DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
- __func__, ret));
+ BRCMF_ERROR(("%s: FAILED: sdcard_intr_reg returned %d\n",
+ __func__, ret));
goto fail;
}
- DHD_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
+ BRCMF_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
- DHD_INFO(("%s: completed!!\n", __func__));
+ BRCMF_INFO(("%s: completed!!\n", __func__));
/* if firmware path present try to download and bring up bus */
- ret = dhd_bus_start(bus->dhd);
+ ret = brcmf_bus_start(bus->drvr);
if (ret != 0) {
if (ret == -ENOLINK) {
- DHD_ERROR(("%s: dongle is not responding\n", __func__));
+ 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 (dhd_net_attach(bus->dhd, 0) != 0) {
- DHD_ERROR(("%s: Net attach failed!!\n", __func__));
+ if (brcmf_net_attach(bus->drvr, 0) != 0) {
+ BRCMF_ERROR(("%s: Net attach failed!!\n", __func__));
goto fail;
}
return bus;
fail:
- dhdsdio_release(bus);
+ brcmf_sdbrcm_release(bus);
return NULL;
}
static bool
-dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
+brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, u32 regsva,
+ u16 devid)
{
u8 clkctl = 0;
int err = 0;
@@ -5168,130 +5605,81 @@ dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
bus->alp_only = true;
/* Return the window to backplane enumeration space for core access */
- if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE))
- DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __func__));
+ if (brcmf_sdbrcm_set_siaddr_window(bus, SI_ENUM_BASE))
+ BRCMF_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n",
+ __func__));
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
- bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
+ brcmf_sdcard_reg_read(bus->card, SI_ENUM_BASE, 4));
-#endif /* DHD_DEBUG */
+#endif /* BCMDBG */
/*
- * Force PLL off until dhdsdio_chip_attach()
+ * Force PLL off until brcmf_sdbrcm_chip_attach()
* programs PLL control regs
*/
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- DHD_INIT_CLKCTL1, &err);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ BRCMF_INIT_CLKCTL1, &err);
if (!err)
clkctl =
- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
+ brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
- DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote "
- "0x%02x read 0x%02x\n",
- err, DHD_INIT_CLKCTL1, clkctl));
+ 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;
}
-#ifdef DHD_DEBUG
- if (DHD_INFO_ON()) {
- uint fn, numfn;
- u8 *cis[SDIOD_MAX_IOFUNCS];
- int err = 0;
-
- numfn = bcmsdh_query_iofnum(sdh);
- ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
- /* Make sure ALP is available before trying to read CIS */
- SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- NULL)),
- !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
-
- /* Now request ALP be put on the bus */
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- DHD_INIT_CLKCTL2, &err);
- udelay(65);
-
- for (fn = 0; fn <= numfn; fn++) {
- cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
- if (!cis[fn]) {
- DHD_INFO(("dhdsdio_probe: fn %d cis malloc "
- "failed\n", fn));
- break;
- }
-
- err = bcmsdh_cis_read(sdh, fn, cis[fn],
- SBSDIO_CIS_SIZE_LIMIT);
- if (err) {
- DHD_INFO(("dhdsdio_probe: fn %d cis read "
- "err %d\n", fn, err));
- kfree(cis[fn]);
- break;
- }
- dhd_dump_cis(fn, cis[fn]);
- }
-
- while (fn-- > 0) {
- ASSERT(cis[fn]);
- kfree(cis[fn]);
- }
-
- if (err) {
- DHD_ERROR(("dhdsdio_probe: error read/parsing CIS\n"));
- goto fail;
- }
- }
-#endif /* DHD_DEBUG */
-
- if (dhdsdio_chip_attach(bus, regsva)) {
- DHD_ERROR(("%s: dhdsdio_chip_attach failed!\n", __func__));
+ if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
+ BRCMF_ERROR(("%s: brcmf_sdbrcm_chip_attach failed!\n",
+ __func__));
goto fail;
}
- bcmsdh_chipinfo(sdh, bus->ci->chip, bus->ci->chiprev);
-
- if (!dhdsdio_chipmatch((u16) bus->ci->chip)) {
- DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
- __func__, bus->ci->chip));
+ if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
+ BRCMF_ERROR(("%s: unsupported chip: 0x%04x\n",
+ __func__, bus->ci->chip));
goto fail;
}
- dhdsdio_sdiod_drive_strength_init(bus, dhd_sdiod_drive_strength);
+ brcmf_sdbrcm_sdiod_drive_strength_init(bus, brcmf_sdiod_drive_strength);
/* Get info on the ARM and SOCRAM cores... */
- if (!DHD_NOPMU(bus)) {
- bus->armrev = SBCOREREV(bcmsdh_reg_read(bus->sdh,
- CORE_SB(bus->ci->armcorebase, sbidhigh), 4));
+ 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)) {
- DHD_ERROR(("%s: failed to find SOCRAM memory!\n",
- __func__));
+ BRCMF_ERROR(("%s: failed to find SOCRAM memory!\n",
+ __func__));
goto fail;
}
bus->ramsize = bus->orig_ramsize;
- if (dhd_dongle_memsize)
- dhd_dongle_setmemsize(bus, dhd_dongle_memsize);
+ if (brcmf_dongle_memsize)
+ brcmf_sdbrcm_setmemsize(bus, brcmf_dongle_memsize);
- DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
- bus->ramsize, bus->orig_ramsize));
+ BRCMF_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
+ bus->ramsize, bus->orig_ramsize));
}
- bus->regs = (void *)bus->ci->buscorebase;
-
/* Set core control so an SDIO reset does a backplane reset */
- OR_REG(&bus->regs->corecontrol, CC_BPRESEN);
+ OR_REG(bus->ci->buscorebase + offsetof(struct sdpcmd_regs,
+ corecontrol),
+ CC_BPRESEN, u32);
- bcm_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+ brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
/* Locate an appropriately-aligned portion of hdrbuf */
- bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], DHD_SDALIGN);
+ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
+ BRCMF_SDALIGN);
/* Set the poll and/or interrupt flags */
- bus->intr = (bool) dhd_intr;
- bus->poll = (bool) dhd_poll;
+ bus->intr = (bool) brcmf_intr;
+ bus->poll = (bool) brcmf_poll;
if (bus->poll)
bus->pollrate = 1;
@@ -5301,18 +5689,18 @@ fail:
return false;
}
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
+static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card)
{
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (bus->dhd->maxctl) {
+ if (bus->drvr->maxctl) {
bus->rxblen =
- roundup((bus->dhd->maxctl + SDPCM_HDRLEN),
- ALIGNMENT) + DHD_SDALIGN;
+ roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
+ ALIGNMENT) + BRCMF_SDALIGN;
bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
if (!(bus->rxbuf)) {
- DHD_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
- __func__, bus->rxblen));
+ BRCMF_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
+ __func__, bus->rxblen));
goto fail;
}
}
@@ -5320,8 +5708,8 @@ static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
/* Allocate buffer to receive glomed packet */
bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
if (!(bus->databuf)) {
- DHD_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
- __func__, MAX_DATA_BUF));
+ 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);
@@ -5329,10 +5717,9 @@ static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
}
/* Align the buffer */
- if ((unsigned long)bus->databuf % DHD_SDALIGN)
- bus->dataptr =
- bus->databuf + (DHD_SDALIGN -
- ((unsigned long)bus->databuf % DHD_SDALIGN));
+ if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
+ bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
+ ((unsigned long)bus->databuf % BRCMF_SDALIGN));
else
bus->dataptr = bus->databuf;
@@ -5342,181 +5729,145 @@ fail:
return false;
}
-static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh)
+static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card)
{
s32 fnum;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
#ifdef SDTEST
- dhdsdio_pktgen_init(bus);
+ brcmf_sdbrcm_pktgen_init(bus);
#endif /* SDTEST */
/* Disable F2 to clear any intermediate frame state on the dongle */
- bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1,
- NULL);
+ brcmf_sdcard_cfg_write(card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ SDIO_FUNC_ENABLE_1, NULL);
- bus->dhd->busstate = DHD_BUS_DOWN;
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
bus->sleeping = false;
bus->rxflow = false;
- bus->prev_rxlim_hit = 0;
/* Done with backplane-dependent accesses, can drop clock... */
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+ 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) dhd_idletime;
- bus->idleclock = DHD_IDLE_ACTIVE;
-
- /* Query the SD clock speed */
- if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
- &bus->sd_divisor, sizeof(s32),
- false) != 0) {
- DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_divisor"));
- bus->sd_divisor = -1;
- } else {
- DHD_INFO(("%s: Initial value for %s is %d\n",
- __func__, "sd_divisor", bus->sd_divisor));
- }
-
- /* Query the SD bus mode */
- if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
- &bus->sd_mode, sizeof(s32), false) != 0) {
- DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_mode"));
- bus->sd_mode = -1;
- } else {
- DHD_INFO(("%s: Initial value for %s is %d\n",
- __func__, "sd_mode", bus->sd_mode));
- }
+ bus->idletime = (s32) brcmf_idletime;
+ bus->idleclock = BRCMF_IDLE_ACTIVE;
/* Query the F2 block size, set roundup accordingly */
fnum = 2;
- if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(s32),
+ if (brcmf_sdcard_iovar_op(card, "sd_blocksize", &fnum, sizeof(s32),
&bus->blocksize, sizeof(s32), false) != 0) {
bus->blocksize = 0;
- DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
+ BRCMF_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
} else {
- DHD_INFO(("%s: Initial value for %s is %d\n",
- __func__, "sd_blocksize", bus->blocksize));
+ 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 (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
+ if (brcmf_sdcard_iovar_op(card, "sd_rxchain", NULL, 0,
&bus->sd_rxchain, sizeof(s32),
false) != 0) {
bus->sd_rxchain = false;
} else {
- DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
- __func__,
- (bus->sd_rxchain ? "supports" : "does not support")));
+ 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;
}
-bool
-dhd_bus_download_firmware(struct dhd_bus *bus, char *fw_path, char *nv_path)
-{
- bool ret;
- bus->fw_path = fw_path;
- bus->nv_path = nv_path;
-
- ret = dhdsdio_download_firmware(bus, bus->sdh);
-
- return ret;
-}
-
static bool
-dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh)
+brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card)
{
bool ret;
/* Download the firmware */
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- ret = _dhdsdio_download_firmware(bus) == 0;
+ ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
return ret;
}
/* Detach and free everything */
-static void dhdsdio_release(dhd_bus_t *bus)
+static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
{
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
if (bus) {
/* De-register interrupt handler */
- bcmsdh_intr_disable(bus->sdh);
- bcmsdh_intr_dereg(bus->sdh);
+ brcmf_sdcard_intr_disable(bus->card);
+ brcmf_sdcard_intr_dereg(bus->card);
- if (bus->dhd) {
- dhd_detach(bus->dhd);
- dhdsdio_release_dongle(bus);
- bus->dhd = NULL;
+ if (bus->drvr) {
+ brcmf_detach(bus->drvr);
+ brcmf_sdbrcm_release_dongle(bus);
+ bus->drvr = NULL;
}
- dhdsdio_release_malloc(bus);
+ brcmf_sdbrcm_release_malloc(bus);
kfree(bus);
}
- DHD_TRACE(("%s: Disconnected\n", __func__));
+ BRCMF_TRACE(("%s: Disconnected\n", __func__));
}
-static void dhdsdio_release_malloc(dhd_bus_t *bus)
+static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
{
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (bus->dhd && bus->dhd->dongle_reset)
+ if (bus->drvr && bus->drvr->dongle_reset)
return;
- if (bus->rxbuf) {
- kfree(bus->rxbuf);
- bus->rxctl = bus->rxbuf = NULL;
- bus->rxlen = 0;
- }
+ kfree(bus->rxbuf);
+ bus->rxctl = bus->rxbuf = NULL;
+ bus->rxlen = 0;
kfree(bus->databuf);
bus->databuf = NULL;
}
-static void dhdsdio_release_dongle(dhd_bus_t *bus)
+static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
{
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (bus->dhd && bus->dhd->dongle_reset)
+ if (bus->drvr && bus->drvr->dongle_reset)
return;
if (bus->ci) {
- dhdsdio_clkctl(bus, CLK_AVAIL, false);
- dhdsdio_clkctl(bus, CLK_NONE, false);
- dhdsdio_chip_detach(bus);
+ 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;
}
- DHD_TRACE(("%s: Disconnected\n", __func__));
+ BRCMF_TRACE(("%s: Disconnected\n", __func__));
}
-static void dhdsdio_disconnect(void *ptr)
+static void brcmf_sdbrcm_disconnect(void *ptr)
{
- dhd_bus_t *bus = (dhd_bus_t *)ptr;
+ struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
if (bus) {
- ASSERT(bus->dhd);
- dhdsdio_release(bus);
+ brcmf_sdbrcm_release(bus);
}
- DHD_TRACE(("%s: Disconnected\n", __func__));
+ BRCMF_TRACE(("%s: Disconnected\n", __func__));
}
/* Register/Unregister functions are called by the main DHD entry
@@ -5524,147 +5875,78 @@ static void dhdsdio_disconnect(void *ptr)
* order to look for or await the device.
*/
-static bcmsdh_driver_t dhd_sdio = {
- dhdsdio_probe,
- dhdsdio_disconnect
+static struct brcmf_sdioh_driver brcmf_sdio = {
+ brcmf_sdbrcm_probe,
+ brcmf_sdbrcm_disconnect
};
-int dhd_bus_register(void)
+int brcmf_bus_register(void)
{
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- return bcmsdh_register(&dhd_sdio);
-}
+ /* 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;
-void dhd_bus_unregister(void)
-{
- DHD_TRACE(("%s: Enter\n", __func__));
+ /* 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);
- bcmsdh_unregister();
+ return brcmf_sdio_register(&brcmf_sdio);
}
-#ifdef BCMEMBEDIMAGE
-static int dhdsdio_download_code_array(struct dhd_bus *bus)
+void brcmf_bus_unregister(void)
{
- int bcmerror = -1;
- int offset = 0;
-
- DHD_INFO(("%s: download embedded firmware...\n", __func__));
-
- /* Download image */
- while ((offset + MEMBLOCK) < sizeof(dlarray)) {
- bcmerror =
- dhdsdio_membytes(bus, true, offset, dlarray + offset,
- MEMBLOCK);
- if (bcmerror) {
- DHD_ERROR(("%s: error %d on writing %d membytes at "
- "0x%08x\n",
- __func__, bcmerror, MEMBLOCK, offset));
- goto err;
- }
-
- offset += MEMBLOCK;
- }
+ BRCMF_TRACE(("%s: Enter\n", __func__));
- if (offset < sizeof(dlarray)) {
- bcmerror = dhdsdio_membytes(bus, true, offset,
- dlarray + offset,
- sizeof(dlarray) - offset);
- if (bcmerror) {
- DHD_ERROR(("%s: error %d on writing %d membytes at "
- "0x%08x\n", __func__, bcmerror,
- sizeof(dlarray) - offset, offset));
- goto err;
- }
- }
-#ifdef DHD_DEBUG
- /* Upload and compare the downloaded code */
- {
- unsigned char *ularray;
-
- ularray = kmalloc(bus->ramsize, GFP_ATOMIC);
- if (!ularray) {
- bcmerror = -ENOMEM;
- goto err;
- }
- /* Upload image to verify downloaded contents. */
- offset = 0;
- memset(ularray, 0xaa, bus->ramsize);
- while ((offset + MEMBLOCK) < sizeof(dlarray)) {
- bcmerror =
- dhdsdio_membytes(bus, false, offset,
- ularray + offset, MEMBLOCK);
- if (bcmerror) {
- DHD_ERROR(("%s: error %d on reading %d membytes"
- " at 0x%08x\n",
- __func__, bcmerror, MEMBLOCK, offset));
- goto free;
- }
-
- offset += MEMBLOCK;
- }
-
- if (offset < sizeof(dlarray)) {
- bcmerror = dhdsdio_membytes(bus, false, offset,
- ularray + offset,
- sizeof(dlarray) - offset);
- if (bcmerror) {
- DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
- __func__, bcmerror,
- sizeof(dlarray) - offset, offset));
- goto free;
- }
- }
-
- if (memcmp(dlarray, ularray, sizeof(dlarray))) {
- DHD_ERROR(("%s: Downloaded image is corrupted.\n",
- __func__));
- ASSERT(0);
- goto free;
- } else
- DHD_ERROR(("%s: Download/Upload/Compare succeeded.\n",
- __func__));
-free:
- kfree(ularray);
- }
-#endif /* DHD_DEBUG */
-
-err:
- return bcmerror;
+ brcmf_sdio_unregister();
}
-#endif /* BCMEMBEDIMAGE */
-static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
+static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
{
- int bcmerror = -1;
int offset = 0;
uint len;
- void *image = NULL;
u8 *memblock = NULL, *memptr;
+ int ret;
- DHD_INFO(("%s: download firmware %s\n", __func__, fw_path));
+ BRCMF_INFO(("%s: Enter\n", __func__));
- image = dhd_os_open_image(fw_path);
- if (image == NULL)
- goto err;
+ 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 + DHD_SDALIGN, GFP_ATOMIC);
+ memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC);
if (memblock == NULL) {
- DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
- __func__, MEMBLOCK));
+ BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
+ __func__, MEMBLOCK));
+ ret = -ENOMEM;
goto err;
}
- if ((u32)(unsigned long)memblock % DHD_SDALIGN)
- memptr +=
- (DHD_SDALIGN - ((u32)(unsigned long)memblock % DHD_SDALIGN));
+ if ((u32)(unsigned long)memblock % BRCMF_SDALIGN)
+ memptr += (BRCMF_SDALIGN -
+ ((u32)(unsigned long)memblock % BRCMF_SDALIGN));
/* Download image */
while ((len =
- dhd_os_get_image_block((char *)memptr, MEMBLOCK, image))) {
- bcmerror = dhdsdio_membytes(bus, true, offset, memptr, len);
- if (bcmerror) {
- DHD_ERROR(("%s: error %d on writing %d membytes at "
- "0x%08x\n", __func__, bcmerror, MEMBLOCK, offset));
+ 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;
}
@@ -5674,10 +5956,10 @@ static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
err:
kfree(memblock);
- if (image)
- dhd_os_close_image(image);
+ release_firmware(bus->firmware);
+ bus->fw_ptr = 0;
- return bcmerror;
+ return ret;
}
/*
@@ -5689,7 +5971,7 @@ err:
* by two NULs.
*/
-static uint process_nvram_vars(char *varbuf, uint len)
+static uint brcmf_process_nvram_vars(char *varbuf, uint len)
{
char *dp;
bool findNewline;
@@ -5731,162 +6013,86 @@ static uint process_nvram_vars(char *varbuf, uint len)
return buf_len;
}
-/*
- EXAMPLE: nvram_array
- nvram_arry format:
- name=value
- Use carriage return at the end of each assignment,
- and an empty string with
- carriage return at the end of array.
-
- For example:
- unsigned char nvram_array[] = {"name1=value1\n",
- "name2=value2\n", "\n"};
- Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
-
- Search "EXAMPLE: nvram_array" to see how the array is activated.
-*/
-
-void dhd_bus_set_nvram_params(struct dhd_bus *bus, const char *nvram_params)
-{
- bus->nvram_params = nvram_params;
-}
-
-static int dhdsdio_download_nvram(struct dhd_bus *bus)
+static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
{
- int bcmerror = -1;
uint len;
- void *image = NULL;
char *memblock = NULL;
char *bufp;
- char *nv_path;
- bool nvram_file_exists;
-
- nv_path = bus->nv_path;
-
- nvram_file_exists = ((nv_path != NULL) && (nv_path[0] != '\0'));
- if (!nvram_file_exists && (bus->nvram_params == NULL))
- return 0;
+ int ret;
- if (nvram_file_exists) {
- image = dhd_os_open_image(nv_path);
- if (image == NULL)
- goto err;
+ 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) {
- DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
- __func__, MEMBLOCK));
+ BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
+ __func__, MEMBLOCK));
+ ret = -ENOMEM;
goto err;
}
- /* Download variables */
- if (nvram_file_exists) {
- len = dhd_os_get_image_block(memblock, MEMBLOCK, image);
- } else {
- len = strlen(bus->nvram_params);
- ASSERT(len <= MEMBLOCK);
- if (len > MEMBLOCK)
- len = MEMBLOCK;
- memcpy(memblock, bus->nvram_params, len);
- }
+ len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus);
if (len > 0 && len < MEMBLOCK) {
bufp = (char *)memblock;
bufp[len] = 0;
- len = process_nvram_vars(bufp, len);
+ len = brcmf_process_nvram_vars(bufp, len);
bufp += len;
*bufp++ = 0;
if (len)
- bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
- if (bcmerror) {
- DHD_ERROR(("%s: error downloading vars: %d\n",
- __func__, bcmerror));
- }
+ ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
+ if (ret)
+ BRCMF_ERROR(("%s: error downloading vars: %d\n",
+ __func__, ret));
} else {
- DHD_ERROR(("%s: error reading nvram file: %d\n",
- __func__, len));
- bcmerror = -EIO;
+ BRCMF_ERROR(("%s: error reading nvram file: %d\n",
+ __func__, len));
+ ret = -EIO;
}
err:
kfree(memblock);
- if (image)
- dhd_os_close_image(image);
+ release_firmware(bus->firmware);
+ bus->fw_ptr = 0;
- return bcmerror;
+ return ret;
}
-static int _dhdsdio_download_firmware(struct dhd_bus *bus)
+static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
{
int bcmerror = -1;
- bool embed = false; /* download embedded firmware */
- bool dlok = false; /* download firmware succeeded */
-
- /* Out immediately if no image to download */
- if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
-#ifdef BCMEMBEDIMAGE
- embed = true;
-#else
- return bcmerror;
-#endif
- }
-
/* Keep arm in reset */
- if (dhdsdio_download_state(bus, true)) {
- DHD_ERROR(("%s: error placing ARM core in reset\n", __func__));
+ 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 ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
- if (dhdsdio_download_code_file(bus, bus->fw_path)) {
- DHD_ERROR(("%s: dongle image file download failed\n",
- __func__));
-#ifdef BCMEMBEDIMAGE
- embed = true;
-#else
- goto err;
-#endif
- } else {
- embed = false;
- dlok = true;
- }
- }
-#ifdef BCMEMBEDIMAGE
- if (embed) {
- if (dhdsdio_download_code_array(bus)) {
- DHD_ERROR(("%s: dongle image array download failed\n",
- __func__));
- goto err;
- } else {
- dlok = true;
- }
- }
-#endif
- if (!dlok) {
- DHD_ERROR(("%s: dongle image download failed\n", __func__));
+ if (brcmf_sdbrcm_download_code_file(bus)) {
+ BRCMF_ERROR(("%s: dongle image file download failed\n",
+ __func__));
goto err;
}
- /* EXAMPLE: nvram_array */
- /* If a valid nvram_arry is specified as above, it can be passed
- down to dongle */
- /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
-
/* External nvram takes precedence if specified */
- if (dhdsdio_download_nvram(bus)) {
- DHD_ERROR(("%s: dongle nvram file download failed\n",
- __func__));
+ if (brcmf_sdbrcm_download_nvram(bus)) {
+ BRCMF_ERROR(("%s: dongle nvram file download failed\n",
+ __func__));
}
/* Take arm out of reset */
- if (dhdsdio_download_state(bus, false)) {
- DHD_ERROR(("%s: error getting out of ARM core reset\n",
- __func__));
+ if (brcmf_sdbrcm_download_state(bus, false)) {
+ BRCMF_ERROR(("%s: error getting out of ARM core reset\n",
+ __func__));
goto err;
}
@@ -5898,110 +6104,83 @@ err:
static int
-dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn, uint flags,
+brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
u8 *buf, uint nbytes, struct sk_buff *pkt,
- bcmsdh_cmplt_fn_t complete, void *handle)
+ void (*complete)(void *handle, int status,
+ bool sync_waiting),
+ void *handle)
{
- return bcmsdh_send_buf
- (bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete,
+ return brcmf_sdcard_send_buf
+ (bus->card, addr, fn, flags, buf, nbytes, pkt, complete,
handle);
}
-uint dhd_bus_chip(struct dhd_bus *bus)
-{
- ASSERT(bus->ci != NULL);
- return bus->ci->chip;
-}
-
-void *dhd_bus_pub(struct dhd_bus *bus)
-{
- return bus->dhd;
-}
-
-void *dhd_bus_txq(struct dhd_bus *bus)
-{
- return &bus->txq;
-}
-
-uint dhd_bus_hdrlen(struct dhd_bus *bus)
-{
- return SDPCM_HDRLEN;
-}
-
-int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag)
+int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag)
{
int bcmerror = 0;
- dhd_bus_t *bus;
+ struct brcmf_bus *bus;
- bus = dhdp->bus;
+ bus = drvr->bus;
if (flag == true) {
- if (!bus->dhd->dongle_reset) {
+ 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 */
- dhd_bus_stop(bus, false);
+ brcmf_sdbrcm_bus_stop(bus, false);
/* Clean tx/rx buffer pointers,
detach from the dongle */
- dhdsdio_release_dongle(bus);
+ brcmf_sdbrcm_release_dongle(bus);
- bus->dhd->dongle_reset = true;
- bus->dhd->up = false;
+ bus->drvr->dongle_reset = true;
+ bus->drvr->up = false;
- DHD_TRACE(("%s: WLAN OFF DONE\n", __func__));
+ 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 */
- DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
+ BRCMF_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
- if (bus->dhd->dongle_reset) {
+ if (bus->drvr->dongle_reset) {
/* Turn on WLAN */
- /* Reset SD client */
- bcmsdh_reset(bus->sdh);
/* Attempt to re-attach & download */
- if (dhdsdio_probe_attach(bus, bus->sdh,
- (u32 *) SI_ENUM_BASE,
- bus->cl_devid)) {
+ if (brcmf_sdbrcm_probe_attach(bus, bus->card,
+ SI_ENUM_BASE,
+ bus->cl_devid)) {
/* Attempt to download binary to the dongle */
- if (dhdsdio_probe_init
- (bus, bus->sdh)
- && dhdsdio_download_firmware(bus,
- bus->sdh)) {
-
+ if (brcmf_sdbrcm_probe_init(bus, bus->card)) {
/* Re-init bus, enable F2 transfer */
- dhd_bus_init((dhd_pub_t *) bus->dhd,
- false);
-
-#if defined(OOB_INTR_ONLY)
- dhd_enable_oob_intr(bus, true);
-#endif /* defined(OOB_INTR_ONLY) */
+ brcmf_sdbrcm_bus_init(bus->drvr, false);
- bus->dhd->dongle_reset = false;
- bus->dhd->up = true;
+ bus->drvr->dongle_reset = false;
+ bus->drvr->up = true;
- DHD_TRACE(("%s: WLAN ON DONE\n",
- __func__));
+ BRCMF_TRACE(("%s: WLAN ON DONE\n",
+ __func__));
} else
bcmerror = -EIO;
} else
bcmerror = -EIO;
} else {
bcmerror = -EISCONN;
- DHD_ERROR(("%s: Set DEVRESET=false invoked when device "
- "is on\n", __func__));
+ 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
-dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
+brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_card *card,
+ struct chip_info *ci, u32 regs)
{
u32 regdata;
@@ -6011,13 +6190,14 @@ dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
* For different chiptypes or old sdio hosts w/o chipcommon,
* other ways of recognition should be added here.
*/
- ci->cccorebase = (u32)regs;
- regdata = bcmsdh_reg_read(sdh, CORE_CC_REG(ci->cccorebase, chipid), 4);
+ 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;
- DHD_INFO(("%s: chipid=0x%x chiprev=%d\n",
- __func__, ci->chip, ci->chiprev));
+ 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) {
@@ -6028,126 +6208,127 @@ dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
ci->ramsize = BCM4329_RAMSIZE;
break;
default:
- DHD_ERROR(("%s: chipid 0x%x is not supported\n",
- __func__, ci->chip));
+ BRCMF_ERROR(("%s: chipid 0x%x is not supported\n",
+ __func__, ci->chip));
return -ENODEV;
}
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(ci->cccorebase, sbidhigh), 4);
ci->ccrev = SBCOREREV(regdata);
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
ci->pmurev = regdata & PCAP_REV_MASK;
- regdata = bcmsdh_reg_read(sdh, CORE_SB(ci->buscorebase, sbidhigh), 4);
+ 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;
- DHD_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
- __func__, ci->ccrev, ci->pmurev,
- ci->buscorerev, ci->buscoretype));
+ 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 = bcmsdh_reg_read(sdh,
+ ci->cccaps = brcmf_sdcard_reg_read(card,
CORE_CC_REG(ci->cccorebase, capabilities), 4);
return 0;
}
static void
-dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase)
+brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase)
{
u32 regdata;
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbtmstatelow), 4);
if (regdata & SBTML_RESET)
return;
- regdata = bcmsdh_reg_read(sdh,
+ 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 = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbtmstatelow), 4);
- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+ brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
regdata | SBTML_REJ);
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbtmstatelow), 4);
udelay(1);
- SPINWAIT((bcmsdh_reg_read(sdh,
+ SPINWAIT((brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbtmstatehigh), 4) &
SBTMH_BUSY), 100000);
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbtmstatehigh), 4);
if (regdata & SBTMH_BUSY)
- DHD_ERROR(("%s: ARM core still busy\n", __func__));
+ BRCMF_ERROR(("%s: ARM core still busy\n", __func__));
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbidlow), 4);
if (regdata & SBIDL_INIT) {
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbimstate), 4) |
SBIM_RJ;
- bcmsdh_reg_write(sdh,
+ brcmf_sdcard_reg_write(card,
CORE_SB(corebase, sbimstate), 4,
regdata);
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbimstate), 4);
udelay(1);
- SPINWAIT((bcmsdh_reg_read(sdh,
+ SPINWAIT((brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbimstate), 4) &
SBIM_BY), 100000);
}
/* set reset and reject while enabling the clocks */
- bcmsdh_reg_write(sdh,
+ brcmf_sdcard_reg_write(card,
CORE_SB(corebase, sbtmstatelow), 4,
(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
SBTML_REJ | SBTML_RESET));
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbtmstatelow), 4);
udelay(10);
/* clear the initiator reject bit */
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbidlow), 4);
if (regdata & SBIDL_INIT) {
- regdata = bcmsdh_reg_read(sdh,
+ regdata = brcmf_sdcard_reg_read(card,
CORE_SB(corebase, sbimstate), 4) &
~SBIM_RJ;
- bcmsdh_reg_write(sdh,
+ brcmf_sdcard_reg_write(card,
CORE_SB(corebase, sbimstate), 4,
regdata);
}
}
/* leave reset and reject asserted */
- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+ brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
(SBTML_REJ | SBTML_RESET));
udelay(1);
}
static int
-dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
+brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
{
struct chip_info *ci;
int err;
u8 clkval, clkset;
- DHD_TRACE(("%s: Enter\n", __func__));
+ BRCMF_TRACE(("%s: Enter\n", __func__));
/* alloc chip_info_t */
ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
if (NULL == ci) {
- DHD_ERROR(("%s: malloc failed!\n", __func__));
+ BRCMF_ERROR(("%s: malloc failed!\n", __func__));
return -ENOMEM;
}
@@ -6156,48 +6337,48 @@ dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
/* 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;
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
clkset, &err);
if (err) {
- DHD_ERROR(("%s: error writing for HT off\n", __func__));
+ 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 = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+ clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, NULL);
if ((clkval & ~SBSDIO_AVBITS) == clkset) {
SPINWAIT(((clkval =
- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR,
NULL)),
!SBSDIO_ALPAV(clkval)),
PMU_MAX_TRANSITION_DLY);
if (!SBSDIO_ALPAV(clkval)) {
- DHD_ERROR(("%s: timeout on ALPAV wait, clkval 0x%02x\n",
- __func__, 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;
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR,
clkset, &err);
udelay(65);
} else {
- DHD_ERROR(("%s: ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
- __func__, clkset, clkval));
+ 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 */
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
- NULL);
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP,
+ 0, NULL);
- err = dhdsdio_chip_recognition(bus->sdh, ci, regs);
+ err = brcmf_sdbrcm_chip_recognition(bus->card, ci, regs);
if (err)
goto fail;
@@ -6205,24 +6386,24 @@ dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
* Make sure any on-chip ARM is off (in case strapping is wrong),
* or downloaded code was already running.
*/
- dhdsdio_chip_disablecore(bus->sdh, ci->armcorebase);
+ brcmf_sdbrcm_chip_disablecore(bus->card, ci->armcorebase);
- bcmsdh_reg_write(bus->sdh,
+ brcmf_sdcard_reg_write(bus->card,
CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
- bcmsdh_reg_write(bus->sdh,
+ 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 */
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
+ 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 = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+ clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
0, NULL);
/* Done with backplane-dependent accesses, can drop clock... */
- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
- NULL);
+ brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ 0, NULL);
bus->ci = ci;
return 0;
@@ -6233,7 +6414,7 @@ fail:
}
static void
-dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase)
+brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase)
{
u32 regdata;
@@ -6241,35 +6422,37 @@ dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase)
* Must do the disable sequence first to work for
* arbitrary current core state.
*/
- dhdsdio_chip_disablecore(sdh, corebase);
+ brcmf_sdbrcm_chip_disablecore(card, corebase);
/*
* Now do the initialization sequence.
* set reset while enabling the clock and
* forcing them on throughout the core
*/
- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+ brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
SBTML_RESET);
udelay(1);
- regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbtmstatehigh), 4);
+ regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh),
+ 4);
if (regdata & SBTMH_SERR)
- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatehigh), 4, 0);
+ brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatehigh),
+ 4, 0);
- regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbimstate), 4);
+ regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4);
if (regdata & (SBIM_IBE | SBIM_TO))
- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbimstate), 4,
+ 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 */
- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+ 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 */
- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+ brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
udelay(1);
}
@@ -6317,7 +6500,7 @@ static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
static void
-dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
+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;
@@ -6344,10 +6527,10 @@ dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
str_shift = 11;
break;
default:
- DHD_ERROR(("No SDIO Drive strength init"
- "done for chip %s rev %d pmurev %d\n",
- bcm_chipname(bus->ci->chip, chn, 8),
- bus->ci->chiprev, bus->ci->pmurev));
+ 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;
}
@@ -6363,28 +6546,227 @@ dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
}
}
- bcmsdh_reg_write(bus->sdh,
+ brcmf_sdcard_reg_write(bus->card,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
4, 1);
- cc_data_temp = bcmsdh_reg_read(bus->sdh,
+ 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;
- bcmsdh_reg_write(bus->sdh,
+ brcmf_sdcard_reg_write(bus->card,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
4, cc_data_temp);
- DHD_INFO(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
- drivestrength, cc_data_temp));
+ BRCMF_INFO(("SDIO: %dmA drive strength selected, "
+ "set to 0x%08x\n", drivestrength, cc_data_temp));
}
}
static void
-dhdsdio_chip_detach(struct dhd_bus *bus)
+brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
{
- DHD_TRACE(("%s: Enter\n", __func__));
+ 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/dhdioctl.h b/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
deleted file mode 100644
index f0ba53558ccd..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
+++ /dev/null
@@ -1,100 +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 _dhdioctl_h_
-#define _dhdioctl_h_
-
-/* Linux network driver ioctl encoding */
-typedef struct dhd_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 */
-} dhd_ioctl_t;
-
-/* per-driver magic numbers */
-#define DHD_IOCTL_MAGIC 0x00444944
-
-/* bump this number if you change the ioctl interface */
-#define DHD_IOCTL_VERSION 1
-
-#define DHD_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
-#define DHD_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */
-
-/* common ioctl definitions */
-#define DHD_GET_MAGIC 0
-#define DHD_GET_VERSION 1
-#define DHD_GET_VAR 2
-#define DHD_SET_VAR 3
-
-/* message levels */
-#define DHD_ERROR_VAL 0x0001
-#define DHD_TRACE_VAL 0x0002
-#define DHD_INFO_VAL 0x0004
-#define DHD_DATA_VAL 0x0008
-#define DHD_CTL_VAL 0x0010
-#define DHD_TIMER_VAL 0x0020
-#define DHD_HDRS_VAL 0x0040
-#define DHD_BYTES_VAL 0x0080
-#define DHD_INTR_VAL 0x0100
-#define DHD_LOG_VAL 0x0200
-#define DHD_GLOM_VAL 0x0400
-#define DHD_EVENT_VAL 0x0800
-#define DHD_BTA_VAL 0x1000
-#define DHD_ISCAN_VAL 0x2000
-
-#ifdef SDTEST
-/* For pktgen iovar */
-typedef struct dhd_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 */
-} dhd_pktgen_t;
-
-/* Version in case structure changes */
-#define DHD_PKTGEN_VERSION 2
-
-/* Type of test packets to use */
-#define DHD_PKTGEN_ECHO 1 /* Send echo requests */
-#define DHD_PKTGEN_SEND 2 /* Send discard packets */
-#define DHD_PKTGEN_RXBURST 3 /* Request dongle send N packets */
-#define DHD_PKTGEN_RECV 4 /* Continuous rx from continuous
- tx dongle */
-#endif /* SDTEST */
-
-/* Enter idle immediately (no timeout) */
-#define DHD_IDLE_IMMEDIATE (-1)
-
-/* Values for idleclock iovar: other values are the sd_divisor to use
- when idle */
-#define DHD_IDLE_ACTIVE 0 /* Do not request any SD clock change
- when idle */
-#define DHD_IDLE_STOP (-1) /* Request SD clock be stopped
- (and use SD1 mode) */
-
-#endif /* _dhdioctl_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dngl_stats.h b/drivers/staging/brcm80211/brcmfmac/dngl_stats.h
deleted file mode 100644
index 699cbffa9c4b..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/dngl_stats.h
+++ /dev/null
@@ -1,32 +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 _dngl_stats_h_
-#define _dngl_stats_h_
-
-typedef struct {
- unsigned long rx_packets; /* total packets received */
- unsigned long tx_packets; /* total packets transmitted */
- unsigned long rx_bytes; /* total bytes received */
- unsigned long tx_bytes; /* total bytes transmitted */
- unsigned long rx_errors; /* bad packets received */
- unsigned long tx_errors; /* packet transmit problems */
- unsigned long rx_dropped; /* packets dropped by dongle */
- unsigned long tx_dropped; /* packets dropped by dongle */
- unsigned long multicast; /* multicast packets received */
-} dngl_stats_t;
-
-#endif /* _dngl_stats_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h b/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
deleted file mode 100644
index 28f092c9e027..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
+++ /dev/null
@@ -1,75 +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 _hndrte_armtrap_h
-#define _hndrte_armtrap_h
-
-/* ARM trap handling */
-
-/* Trap types defined by ARM (see arminc.h) */
-
-/* Trap locations in lo memory */
-#define TRAP_STRIDE 4
-#define FIRST_TRAP TR_RST
-#define LAST_TRAP (TR_FIQ * TRAP_STRIDE)
-
-#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
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-typedef struct _trap_struct {
- 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;
-} trap_t;
-
-#endif /* !_LANGUAGE_ASSEMBLY */
-
-#endif /* _hndrte_armtrap_h */
diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h b/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
deleted file mode 100644
index 4df3eecaa83b..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
+++ /dev/null
@@ -1,62 +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 _hndrte_cons_h
-#define _hndrte_cons_h
-
-#define CBUF_LEN (128)
-
-#define LOG_BUF_LEN 1024
-
-typedef struct {
- u32 buf; /* Can't be pointer on (64-bit) hosts */
- uint buf_size;
- uint idx;
- char *_buf_compat; /* Redundant pointer for backward compat. */
-} hndrte_log_t;
-
-typedef struct {
- /* 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.
- */
- hndrte_log_t 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];
-} hndrte_cons_t;
-
-#endif /* _hndrte_cons_h */
-
diff --git a/drivers/staging/brcm80211/brcmfmac/msgtrace.h b/drivers/staging/brcm80211/brcmfmac/msgtrace.h
deleted file mode 100644
index d654671a5a30..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/msgtrace.h
+++ /dev/null
@@ -1,61 +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 _MSGTRACE_H
-#define _MSGTRACE_H
-
-#define MSGTRACE_VERSION 1
-
-/* Message trace header */
-typedef 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 */
-} __attribute__((packed)) msgtrace_hdr_t;
-
-#define MSGTRACE_HDRLEN sizeof(msgtrace_hdr_t)
-
-/* The hbus driver generates traces when sending a trace message.
- * This causes endless traces.
- * This flag must be set to true in any hbus traces.
- * The flag is reset in the function msgtrace_put.
- * This prevents endless traces but generates hasardous
- * lost of traces only in bus device code.
- * It is recommendat to set this flag in macro SD_TRACE
- * but not in SD_ERROR for avoiding missing
- * hbus error traces. hbus error trace should not generates endless traces.
- */
-extern bool msgtrace_hbus_trace;
-
-typedef void (*msgtrace_func_send_t) (void *hdl1, void *hdl2, u8 *hdr,
- u16 hdrlen, u8 *buf,
- u16 buflen);
-
-extern void msgtrace_sent(void);
-extern void msgtrace_put(char *buf, int count);
-extern void msgtrace_init(void *hdl1, void *hdl2,
- msgtrace_func_send_t func_send);
-
-#endif /* _MSGTRACE_H */
diff --git a/drivers/staging/brcm80211/brcmfmac/sdio_host.h b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
new file mode 100644
index 000000000000..d34547215060
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
@@ -0,0 +1,347 @@
+/*
+ * 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/brcmfmac/sdioh.h b/drivers/staging/brcm80211/brcmfmac/sdioh.h
deleted file mode 100644
index f96aaf9cec74..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/sdioh.h
+++ /dev/null
@@ -1,63 +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 _SDIOH_H
-#define _SDIOH_H
-
-#define SD_SysAddr 0x000
-#define SD_BlockSize 0x004
-#define SD_BlockCount 0x006
-#define SD_Arg0 0x008
-#define SD_Arg1 0x00A
-#define SD_TransferMode 0x00C
-#define SD_Command 0x00E
-#define SD_Response0 0x010
-#define SD_Response1 0x012
-#define SD_Response2 0x014
-#define SD_Response3 0x016
-#define SD_Response4 0x018
-#define SD_Response5 0x01A
-#define SD_Response6 0x01C
-#define SD_Response7 0x01E
-#define SD_BufferDataPort0 0x020
-#define SD_BufferDataPort1 0x022
-#define SD_PresentState 0x024
-#define SD_HostCntrl 0x028
-#define SD_PwrCntrl 0x029
-#define SD_BlockGapCntrl 0x02A
-#define SD_WakeupCntrl 0x02B
-#define SD_ClockCntrl 0x02C
-#define SD_TimeoutCntrl 0x02E
-#define SD_SoftwareReset 0x02F
-#define SD_IntrStatus 0x030
-#define SD_ErrorIntrStatus 0x032
-#define SD_IntrStatusEnable 0x034
-#define SD_ErrorIntrStatusEnable 0x036
-#define SD_IntrSignalEnable 0x038
-#define SD_ErrorIntrSignalEnable 0x03A
-#define SD_CMD12ErrorStatus 0x03C
-#define SD_Capabilities 0x040
-#define SD_Capabilities_Reserved 0x044
-#define SD_MaxCurCap 0x048
-#define SD_MaxCurCap_Reserved 0x04C
-#define SD_ADMA_SysAddr 0x58
-#define SD_SlotInterruptStatus 0x0FC
-#define SD_HostControllerVersion 0x0FE
-
-/* SD specific registers in PCI config space */
-#define SD_SlotInfo 0x40
-
-#endif /* _SDIOH_H */
diff --git a/drivers/staging/brcm80211/brcmfmac/sdiovar.h b/drivers/staging/brcm80211/brcmfmac/sdiovar.h
deleted file mode 100644
index d1cfa5f0a982..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/sdiovar.h
+++ /dev/null
@@ -1,38 +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 _sdiovar_h_
-#define _sdiovar_h_
-
-typedef struct sdreg {
- int func;
- int offset;
- int value;
-} sdreg_t;
-
-/* 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 */
-
-#define NUM_PREV_TRANSACTIONS 16
-
-#endif /* _sdiovar_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index 1827b0bf9201..821206d3e536 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -16,336 +16,325 @@
#include <linux/kernel.h>
#include <linux/if_arp.h>
-
-#include <bcmutils.h>
-
-#include <asm/uaccess.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhdioctl.h>
-#include <wlioctl.h>
-
+#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/netdevice.h>
#include <linux/sched.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 <linux/mmc/sdio_func.h>
-#include <linux/firmware.h>
-#include <wl_cfg80211.h>
-void sdioh_sdio_set_host_pm_flags(int flag);
+#include <brcmu_utils.h>
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include "dhd.h"
+#include "wl_cfg80211.h"
static struct sdio_func *cfg80211_sdio_func;
-static struct wl_dev *wl_cfg80211_dev;
+static struct brcmf_cfg80211_dev *cfg80211_dev;
static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-u32 wl_dbg_level = WL_DBG_ERR;
-
-#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4.bin"
-#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4.txt"
+u32 brcmf_dbg_level = WL_DBG_ERR;
/*
** cfg80211_ops api/callback list
*/
-static s32 wl_cfg80211_change_iface(struct wiphy *wiphy,
- struct net_device *ndev,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params);
-static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request,
- struct cfg80211_ssid *this_ssid);
-static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request);
-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
-static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_ibss_params *params);
-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
- struct net_device *dev);
-static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
- struct net_device *dev, u8 *mac,
- struct station_info *sinfo);
-static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- struct net_device *dev, bool enabled,
- s32 timeout);
-static s32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *addr,
- const struct cfg80211_bitrate_mask
- *mask);
-static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
- u16 reason_code);
-static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+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 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+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 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+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 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool pairwise, const u8 *mac_addr);
-static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+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 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+static s32 brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx);
-static s32 wl_cfg80211_resume(struct wiphy *wiphy);
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
-static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+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 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+static s32 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_pmksa *pmksa);
-static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
+static s32 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy,
struct net_device *dev);
/*
** event & event Q handlers for cfg80211 interfaces
*/
-static s32 wl_create_event_handler(struct wl_priv *wl);
-static void wl_destroy_event_handler(struct wl_priv *wl);
-static s32 wl_event_handler(void *data);
-static void wl_init_eq(struct wl_priv *wl);
-static void wl_flush_eq(struct wl_priv *wl);
-static void wl_lock_eq(struct wl_priv *wl);
-static void wl_unlock_eq(struct wl_priv *wl);
-static void wl_init_eq_lock(struct wl_priv *wl);
-static void wl_init_eloop_handler(struct wl_event_loop *el);
-static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
-static s32 wl_enq_event(struct wl_priv *wl, u32 type,
- const wl_event_msg_t *msg, void *data);
-static void wl_put_event(struct wl_event_q *e);
-static void wl_wakeup_event(struct wl_priv *wl);
-static s32 wl_notify_connect_status(struct wl_priv *wl,
- struct net_device *ndev,
- const wl_event_msg_t *e, void *data);
-static s32 wl_notify_roaming_status(struct wl_priv *wl,
- struct net_device *ndev,
- const wl_event_msg_t *e, void *data);
-static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
- const wl_event_msg_t *e, void *data);
-static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
- const wl_event_msg_t *e, void *data,
- bool completed);
-static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
- const wl_event_msg_t *e, void *data);
-static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
- const wl_event_msg_t *e, void *data);
+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
*/
-struct sdio_func *wl_cfg80211_get_sdio_func(void);
-static void wl_clear_sdio_func(void);
+static void brcmf_clear_sdio_func(void);
/*
** ioctl utilites
*/
-static s32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
+static s32 brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
s32 buf_len);
-static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name,
+static __used s32 brcmf_dev_bufvar_set(struct net_device *dev, s8 *name,
s8 *buf, s32 len);
-static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
-static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name,
+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 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
+static s32 brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
u32 len);
/*
** cfg80211 set_wiphy_params utilities
*/
-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
-static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
+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 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e,
- void *data, s32 item);
-static void *wl_read_prof(struct wl_priv *wl, s32 item);
-static void wl_init_prof(struct wl_profile *prof);
+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 wl_set_wpa_version(struct net_device *dev,
+static s32 brcmf_set_wpa_version(struct net_device *dev,
struct cfg80211_connect_params *sme);
-static s32 wl_set_auth_type(struct net_device *dev,
+static s32 brcmf_set_auth_type(struct net_device *dev,
struct cfg80211_connect_params *sme);
-static s32 wl_set_set_cipher(struct net_device *dev,
+static s32 brcmf_set_set_cipher(struct net_device *dev,
struct cfg80211_connect_params *sme);
-static s32 wl_set_key_mgmt(struct net_device *dev,
+static s32 brcmf_set_key_mgmt(struct net_device *dev,
struct cfg80211_connect_params *sme);
-static s32 wl_set_set_sharedkey(struct net_device *dev,
+static s32 brcmf_set_set_sharedkey(struct net_device *dev,
struct cfg80211_connect_params *sme);
-static s32 wl_get_assoc_ies(struct wl_priv *wl);
-static void wl_clear_assoc_ies(struct wl_priv *wl);
-static void wl_ch_to_chanspec(int ch,
- struct wl_join_params *join_params, size_t *join_params_size);
+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 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
-static s32 wl_mode_to_nl80211_iftype(s32 mode);
-static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
+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 wl_free_wdev(struct wl_priv *wl);
-static s32 wl_inform_bss(struct wl_priv *wl);
-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
-static s32 wl_update_bss_info(struct wl_priv *wl);
-static s32 wl_add_keyext(struct wiphy *wiphy, struct net_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 wl_wsec_key *key);
-static void swap_key_to_BE(struct wl_wsec_key *key);
+static void swap_key_from_BE(struct brcmf_wsec_key *key);
+static void swap_key_to_BE(struct brcmf_wsec_key *key);
/*
-** wl_priv memory init/deinit utilities
+** brcmf_cfg80211_priv memory init/deinit utilities
*/
-static s32 wl_init_priv_mem(struct wl_priv *wl);
-static void wl_deinit_priv_mem(struct wl_priv *wl);
+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 wl_delay(u32 ms);
+static void brcmf_delay(u32 ms);
/*
** store/restore cfg80211 instance data
*/
-static void wl_set_drvdata(struct wl_dev *dev, void *data);
-static void *wl_get_drvdata(struct wl_dev *dev);
+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 wl_is_ibssmode(struct wl_priv *wl);
+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv);
/*
** dongle up/down , default configuration utilities
*/
-static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
-static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
-static void wl_link_down(struct wl_priv *wl);
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
-static s32 __wl_cfg80211_up(struct wl_priv *wl);
-static s32 __wl_cfg80211_down(struct wl_priv *wl);
-static s32 wl_dongle_probecap(struct wl_priv *wl);
-static void wl_init_conf(struct wl_conf *conf);
+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);
/*
** dongle configuration utilities
*/
-#ifndef EMBEDDED_PLATFORM
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
-static s32 wl_dongle_country(struct net_device *ndev, u8 ccode);
-static s32 wl_dongle_up(struct net_device *ndev, u32 up);
-static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
-static s32 wl_dongle_glom(struct net_device *ndev, u32 glom,
- u32 dongle_align);
-static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe,
- s32 arp_ol);
-static s32 wl_pattern_atoh(s8 *src, s8 *dst);
-static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode);
-static s32 wl_update_wiphybands(struct wl_priv *wl);
-#endif /* !EMBEDDED_PLATFORM */
-
-static s32 wl_dongle_eventmsg(struct net_device *ndev);
-static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
- s32 scan_unassoc_time, s32 scan_passive_time);
-static s32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
-static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar,
+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);
/*
** iscan handler
*/
-static void wl_iscan_timer(unsigned long data);
-static void wl_term_iscan(struct wl_priv *wl);
-static s32 wl_init_iscan(struct wl_priv *wl);
-static s32 wl_iscan_thread(void *data);
-static s32 wl_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
+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 wl_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
+static s32 brcmf_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
void *param, s32 paramlen, void *bufptr,
s32 buflen);
-static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid,
- u16 action);
-static s32 wl_do_iscan(struct wl_priv *wl);
-static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
-static s32 wl_invoke_iscan(struct wl_priv *wl);
-static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
- struct wl_scan_results **bss_list);
-static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
-static void wl_init_iscan_eloop(struct wl_iscan_eloop *el);
-static s32 wl_iscan_done(struct wl_priv *wl);
-static s32 wl_iscan_pending(struct wl_priv *wl);
-static s32 wl_iscan_inprogress(struct wl_priv *wl);
-static s32 wl_iscan_aborted(struct wl_priv *wl);
-
-/*
-** fw/nvram downloading handler
-*/
-static void wl_init_fw(struct wl_fw_ctrl *fw);
+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);
/*
* find most significant bit set
*/
-static __used u32 wl_find_msb(u16 bit16);
+static __used u32 brcmf_find_msb(u16 bit16);
/*
* update pmklist to dongle
*/
-static __used s32 wl_update_pmklist(struct net_device *dev,
- struct wl_pmk_list *pmk_list, s32 err);
+static __used s32 brcmf_update_pmklist(struct net_device *dev,
+ struct brcmf_cfg80211_pmk_list *pmk_list,
+ s32 err);
-static void wl_set_mpc(struct net_device *ndev, int mpc);
+static void brcmf_set_mpc(struct net_device *ndev, int mpc);
/*
* debufs support
*/
-static int wl_debugfs_add_netdev_params(struct wl_priv *wl);
-static void wl_debugfs_remove_netdev(struct wl_priv *wl);
+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() \
+#define WL_PRIV_GET() \
({ \
- struct wl_iface *ci; \
- if (unlikely(!(wl_cfg80211_dev && \
- (ci = wl_get_drvdata(wl_cfg80211_dev))))) { \
+ struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg80211_dev); \
+ if (unlikely(!ci)) { \
WL_ERR("wl_cfg80211_dev is unavailable\n"); \
BUG(); \
- } \
- ci_to_wl(ci); \
+ } \
+ ci->cfg_priv; \
})
#define CHECK_SYS_UP() \
do { \
- struct wl_priv *wl = wiphy_to_wl(wiphy); \
- if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) { \
+ 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)wl->status); \
+ (int)cfg_priv->status); \
return -EIO; \
} \
} while (0)
-extern int dhd_wait_pend8021x(struct net_device *dev);
#define CHAN2G(_channel, _freq, _flags) { \
.band = IEEE80211_BAND_2GHZ, \
.center_freq = (_freq), \
@@ -373,18 +362,18 @@ extern int dhd_wait_pend8021x(struct net_device *dev);
}
static struct ieee80211_rate __wl_rates[] = {
- RATETAB_ENT(WLC_RATE_1M, 0),
- RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
- RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
- RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
- RATETAB_ENT(WLC_RATE_6M, 0),
- RATETAB_ENT(WLC_RATE_9M, 0),
- RATETAB_ENT(WLC_RATE_12M, 0),
- RATETAB_ENT(WLC_RATE_18M, 0),
- RATETAB_ENT(WLC_RATE_24M, 0),
- RATETAB_ENT(WLC_RATE_36M, 0),
- RATETAB_ENT(WLC_RATE_48M, 0),
- RATETAB_ENT(WLC_RATE_54M, 0),
+ RATETAB_ENT(BRCM_RATE_1M, 0),
+ RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(BRCM_RATE_6M, 0),
+ RATETAB_ENT(BRCM_RATE_9M, 0),
+ RATETAB_ENT(BRCM_RATE_12M, 0),
+ RATETAB_ENT(BRCM_RATE_18M, 0),
+ RATETAB_ENT(BRCM_RATE_24M, 0),
+ RATETAB_ENT(BRCM_RATE_36M, 0),
+ RATETAB_ENT(BRCM_RATE_48M, 0),
+ RATETAB_ENT(BRCM_RATE_54M, 0),
};
#define wl_a_rates (__wl_rates + 4)
@@ -521,7 +510,7 @@ static const u32 __wl_cipher_suites[] = {
WLAN_CIPHER_SUITE_AES_CMAC,
};
-static void swap_key_from_BE(struct wl_wsec_key *key)
+static void swap_key_from_BE(struct brcmf_wsec_key *key)
{
key->index = cpu_to_le32(key->index);
key->len = cpu_to_le32(key->len);
@@ -532,7 +521,7 @@ static void swap_key_from_BE(struct wl_wsec_key *key)
key->iv_initialized = cpu_to_le32(key->iv_initialized);
}
-static void swap_key_to_BE(struct wl_wsec_key *key)
+static void swap_key_to_BE(struct brcmf_wsec_key *key)
{
key->index = le32_to_cpu(key->index);
key->len = le32_to_cpu(key->len);
@@ -544,10 +533,10 @@ static void swap_key_to_BE(struct wl_wsec_key *key)
}
static s32
-wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
+brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
{
struct ifreq ifr;
- struct wl_ioctl ioc;
+ struct brcmf_ioctl ioc;
mm_segment_t fs;
s32 err = 0;
@@ -567,11 +556,11 @@ wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
}
static s32
-wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct wireless_dev *wdev;
s32 infra = 0;
s32 err = 0;
@@ -586,11 +575,11 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
type);
return -EOPNOTSUPP;
case NL80211_IFTYPE_ADHOC:
- wl->conf->mode = WL_MODE_IBSS;
+ cfg_priv->conf->mode = WL_MODE_IBSS;
infra = 0;
break;
case NL80211_IFTYPE_STATION:
- wl->conf->mode = WL_MODE_BSS;
+ cfg_priv->conf->mode = WL_MODE_BSS;
infra = 1;
break;
default:
@@ -599,7 +588,7 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
}
infra = cpu_to_le32(infra);
- err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+ err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
if (unlikely(err)) {
WL_ERR("WLC_SET_INFRA error (%d)\n", err);
err = -EAGAIN;
@@ -609,7 +598,7 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
}
WL_INFO("IF Type = %s\n",
- (wl->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
+ (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
done:
WL_TRACE("Exit\n");
@@ -617,7 +606,8 @@ done:
return err;
}
-static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
+static void wl_iscan_prep(struct brcmf_scan_params *params,
+ struct brcmf_ssid *ssid)
{
memcpy(params->bssid, ether_bcast, ETH_ALEN);
params->bss_type = DOT11_BSSTYPE_ANY;
@@ -633,58 +623,59 @@ static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
params->passive_time = cpu_to_le32(params->passive_time);
params->home_time = cpu_to_le32(params->home_time);
if (ssid && ssid->SSID_len)
- memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
+ memcpy(&params->ssid, ssid, sizeof(struct brcmf_ssid));
}
static s32
-wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
s32 paramlen, void *bufptr, s32 buflen)
{
s32 iolen;
- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
BUG_ON(!iolen);
- return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
+ return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, bufptr, iolen);
}
static s32
-wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
s32 paramlen, void *bufptr, s32 buflen)
{
s32 iolen;
- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
BUG_ON(!iolen);
- return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
+ return brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, bufptr, buflen);
}
static s32
-wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
+brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
+ struct brcmf_ssid *ssid, u16 action)
{
- s32 params_size =
- (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
- struct wl_iscan_params *params;
+ s32 params_size = (BRCMF_SCAN_PARAMS_FIXED_SIZE +
+ offsetof(struct brcmf_iscan_params, params));
+ struct brcmf_iscan_params *params;
s32 err = 0;
if (ssid && ssid->SSID_len)
- params_size += sizeof(struct wlc_ssid);
+ params_size += sizeof(struct brcmf_ssid);
params = kzalloc(params_size, GFP_KERNEL);
if (unlikely(!params))
return -ENOMEM;
- BUG_ON(params_size >= WLC_IOCTL_SMLEN);
+ BUG_ON(params_size >= BRCMF_C_IOCTL_SMLEN);
wl_iscan_prep(&params->params, ssid);
- params->version = cpu_to_le32(ISCAN_REQ_VERSION);
+ 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(wl_iscan_params_t, params); */
- err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
- iscan->ioctl_buf, WLC_IOCTL_SMLEN);
+ /* 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) {
WL_INFO("system busy : iscan canceled\n");
@@ -696,11 +687,11 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
return err;
}
-static s32 wl_do_iscan(struct wl_priv *wl)
+static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
- struct net_device *ndev = wl_to_ndev(wl);
- struct wlc_ssid ssid;
+ 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;
s32 err = 0;
@@ -709,16 +700,16 @@ static s32 wl_do_iscan(struct wl_priv *wl)
iscan->state = WL_ISCAN_STATE_SCANING;
- passive_scan = wl->active_scan ? 0 : 1;
- err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
+ passive_scan = cfg_priv->active_scan ? 0 : 1;
+ err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
if (unlikely(err)) {
WL_ERR("error (%d)\n", err);
return err;
}
- wl_set_mpc(ndev, 0);
- wl->iscan_kickstart = true;
- wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+ brcmf_set_mpc(ndev, 0);
+ cfg_priv->iscan_kickstart = true;
+ brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
iscan->timer_on = 1;
@@ -726,30 +717,30 @@ static s32 wl_do_iscan(struct wl_priv *wl)
}
static s32
-__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid)
{
- struct wl_priv *wl = ndev_to_wl(ndev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct cfg80211_ssid *ssids;
- struct wl_scan_req *sr = wl_to_sr(wl);
+ struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
s32 passive_scan;
bool iscan_req;
bool spec_scan;
s32 err = 0;
- if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
- WL_ERR("Scanning already : status (%d)\n", (int)wl->status);
+ if (unlikely(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, &wl->status))) {
- WL_ERR("Scanning being aborted : status (%d)\n",
- (int)wl->status);
+ if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status))) {
+ WL_ERR("Scanning being aborted : status (%lu)\n",
+ cfg_priv->status);
return -EAGAIN;
}
- if (test_bit(WL_STATUS_CONNECTING, &wl->status)) {
- WL_ERR("Connecting : status (%d)\n",
- (int)wl->status);
+ if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
+ WL_ERR("Connecting : status (%lu)\n",
+ cfg_priv->status);
return -EAGAIN;
}
@@ -758,7 +749,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
if (request) {
/* scan bss */
ssids = request->ssids;
- if (wl->iscan_on && (!ssids || !ssids->ssid_len))
+ if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
iscan_req = true;
} else {
/* scan in ibss */
@@ -766,10 +757,10 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
ssids = this_ssid;
}
- wl->scan_request = request;
- set_bit(WL_STATUS_SCANNING, &wl->status);
+ cfg_priv->scan_request = request;
+ set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
if (iscan_req) {
- err = wl_do_iscan(wl);
+ err = brcmf_do_iscan(cfg_priv);
if (likely(!err))
return err;
else
@@ -788,15 +779,15 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
WL_SCAN("Broadcast scan\n");
}
- passive_scan = wl->active_scan ? 0 : 1;
- err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+ passive_scan = cfg_priv->active_scan ? 0 : 1;
+ err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
if (unlikely(err)) {
WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
goto scan_out;
}
- wl_set_mpc(ndev, 0);
- err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
+ brcmf_set_mpc(ndev, 0);
+ err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN, &sr->ssid,
sizeof(sr->ssid));
if (err) {
if (err == -EBUSY) {
@@ -805,7 +796,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
} else {
WL_ERR("WLC_SCAN error (%d)\n", err);
}
- wl_set_mpc(ndev, 1);
+ brcmf_set_mpc(ndev, 1);
goto scan_out;
}
}
@@ -813,13 +804,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
return 0;
scan_out:
- clear_bit(WL_STATUS_SCANNING, &wl->status);
- wl->scan_request = NULL;
+ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
+ cfg_priv->scan_request = NULL;
return err;
}
static s32
-wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request)
{
s32 err = 0;
@@ -828,7 +819,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
CHECK_SYS_UP();
- err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
+ err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
if (unlikely(err))
WL_ERR("scan error (%d)\n", err);
@@ -836,17 +827,18 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
return err;
}
-static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
+static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
{
- s8 buf[WLC_IOCTL_SMLEN];
+ s8 buf[BRCMF_C_IOCTL_SMLEN];
u32 len;
s32 err = 0;
val = cpu_to_le32(val);
- len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+ len = brcmu_mkiovar(name, (char *)(&val), sizeof(val), buf,
+ sizeof(buf));
BUG_ON(!len);
- err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, buf, len);
if (unlikely(err))
WL_ERR("error (%d)\n", err);
@@ -854,10 +846,10 @@ static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
}
static s32
-wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
+brcmf_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
{
union {
- s8 buf[WLC_IOCTL_SMLEN];
+ s8 buf[BRCMF_C_IOCTL_SMLEN];
s32 val;
} var;
u32 len;
@@ -865,10 +857,10 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
s32 err = 0;
len =
- bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
+ brcmu_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
sizeof(var.buf));
BUG_ON(!len);
- err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
+ err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, &var, len);
if (unlikely(err))
WL_ERR("error (%d)\n", err);
@@ -877,35 +869,35 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
return err;
}
-static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
+static s32 brcmf_set_rts(struct net_device *dev, u32 rts_threshold)
{
s32 err = 0;
- err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold);
+ err = brcmf_dev_intvar_set(dev, "rtsthresh", rts_threshold);
if (unlikely(err))
WL_ERR("Error (%d)\n", err);
return err;
}
-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
+static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold)
{
s32 err = 0;
- err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold);
+ err = brcmf_dev_intvar_set(dev, "fragthresh", frag_threshold);
if (unlikely(err))
WL_ERR("Error (%d)\n", err);
return err;
}
-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
+static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l)
{
s32 err = 0;
- u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
+ u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
retry = cpu_to_le32(retry);
- err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
+ err = brcmf_dev_ioctl(dev, cmd, &retry, sizeof(retry));
if (unlikely(err)) {
WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
return err;
@@ -913,40 +905,40 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
return err;
}
-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- struct net_device *ndev = wl_to_ndev(wl);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = cfg_to_ndev(cfg_priv);
s32 err = 0;
WL_TRACE("Enter\n");
CHECK_SYS_UP();
if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
- (wl->conf->rts_threshold != wiphy->rts_threshold)) {
- wl->conf->rts_threshold = wiphy->rts_threshold;
- err = wl_set_rts(ndev, wl->conf->rts_threshold);
+ (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
+ cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
+ err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
if (!err)
goto done;
}
if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
- (wl->conf->frag_threshold != wiphy->frag_threshold)) {
- wl->conf->frag_threshold = wiphy->frag_threshold;
- err = wl_set_frag(ndev, wl->conf->frag_threshold);
+ (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
+ cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
+ err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
if (!err)
goto done;
}
if (changed & WIPHY_PARAM_RETRY_LONG
- && (wl->conf->retry_long != wiphy->retry_long)) {
- wl->conf->retry_long = wiphy->retry_long;
- err = wl_set_retry(ndev, wl->conf->retry_long, true);
+ && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
+ cfg_priv->conf->retry_long = wiphy->retry_long;
+ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
if (!err)
goto done;
}
if (changed & WIPHY_PARAM_RETRY_SHORT
- && (wl->conf->retry_short != wiphy->retry_short)) {
- wl->conf->retry_short = wiphy->retry_short;
- err = wl_set_retry(ndev, wl->conf->retry_short, false);
+ && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
+ cfg_priv->conf->retry_short = wiphy->retry_short;
+ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
if (!err)
goto done;
}
@@ -957,11 +949,11 @@ done:
}
static s32
-wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- struct wl_join_params join_params;
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct brcmf_join_params join_params;
size_t join_params_size = 0;
s32 err = 0;
s32 wsec = 0;
@@ -977,6 +969,8 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
return -EOPNOTSUPP;
}
+ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+
if (params->bssid)
WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
params->bssid[0], params->bssid[1], params->bssid[2],
@@ -1018,7 +1012,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
if (params->privacy)
wsec |= WEP_ENABLED;
- err = wl_dev_intvar_set(dev, "wsec", wsec);
+ err = brcmf_dev_intvar_set(dev, "wsec", wsec);
if (unlikely(err)) {
WL_ERR("wsec failed (%d)\n", err);
goto done;
@@ -1030,14 +1024,14 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
else
bcnprd = cpu_to_le32(100);
- err = wl_dev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
+ err = brcmf_dev_ioctl(dev, BRCM_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
if (unlikely(err)) {
WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
goto done;
}
/* Configure required join parameter */
- memset(&join_params, 0, sizeof(wl_join_params_t));
+ memset(&join_params, 0, sizeof(struct brcmf_join_params));
/* SSID */
join_params.ssid.SSID_len =
@@ -1045,67 +1039,69 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
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);
- wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
+ brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
/* BSSID */
if (params->bssid) {
memcpy(join_params.params.bssid, params->bssid, ETH_ALEN);
- join_params_size =
- sizeof(join_params.ssid) + WL_ASSOC_PARAMS_FIXED_SIZE;
+ join_params_size = sizeof(join_params.ssid) +
+ BRCMF_ASSOC_PARAMS_FIXED_SIZE;
} else {
memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
}
- wl_update_prof(wl, NULL, &join_params.params.bssid, WL_PROF_BSSID);
+ brcmf_update_prof(cfg_priv, NULL,
+ &join_params.params.bssid, WL_PROF_BSSID);
/* Channel */
if (params->channel) {
u32 target_channel;
- wl->channel =
+ cfg_priv->channel =
ieee80211_frequency_to_channel(
params->channel->center_freq);
if (params->channel_fixed) {
/* adding chanspec */
- wl_ch_to_chanspec(wl->channel,
+ brcmf_ch_to_chanspec(cfg_priv->channel,
&join_params, &join_params_size);
}
/* set channel for starter */
- target_channel = cpu_to_le32(wl->channel);
- err = wl_dev_ioctl(dev, WLC_SET_CHANNEL,
+ target_channel = cpu_to_le32(cfg_priv->channel);
+ err = brcmf_dev_ioctl(dev, BRCM_SET_CHANNEL,
&target_channel, sizeof(target_channel));
if (unlikely(err)) {
WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
goto done;
}
} else
- wl->channel = 0;
+ cfg_priv->channel = 0;
- wl->ibss_starter = false;
+ cfg_priv->ibss_starter = false;
- err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+ &join_params, join_params_size);
if (unlikely(err)) {
WL_ERR("WLC_SET_SSID failed (%d)\n", err);
goto done;
}
- set_bit(WL_STATUS_CONNECTING, &wl->status);
-
done:
+ if (err)
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
WL_TRACE("Exit\n");
return err;
}
-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
s32 err = 0;
WL_TRACE("Enter\n");
CHECK_SYS_UP();
- wl_link_down(wl);
+ brcmf_link_down(cfg_priv);
WL_TRACE("Exit\n");
@@ -1113,10 +1109,10 @@ static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
}
static s32
-wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
{
- struct wl_priv *wl = ndev_to_wl(dev);
- struct wl_security *sec;
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1127,21 +1123,21 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
else
val = WPA_AUTH_DISABLED;
WL_CONN("setting wpa_auth to 0x%0x\n", val);
- err = wl_dev_intvar_set(dev, "wpa_auth", val);
+ err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
if (unlikely(err)) {
WL_ERR("set wpa_auth failed (%d)\n", err);
return err;
}
- sec = wl_read_prof(wl, WL_PROF_SEC);
+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
sec->wpa_versions = sme->crypto.wpa_versions;
return err;
}
static s32
-wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
{
- struct wl_priv *wl = ndev_to_wl(dev);
- struct wl_security *sec;
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1166,21 +1162,21 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
break;
}
- err = wl_dev_intvar_set(dev, "auth", val);
+ err = brcmf_dev_intvar_set(dev, "auth", val);
if (unlikely(err)) {
WL_ERR("set auth failed (%d)\n", err);
return err;
}
- sec = wl_read_prof(wl, WL_PROF_SEC);
+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
sec->auth_type = sme->auth_type;
return err;
}
static s32
-wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
{
- struct wl_priv *wl = ndev_to_wl(dev);
- struct wl_security *sec;
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_security *sec;
s32 pval = 0;
s32 gval = 0;
s32 err = 0;
@@ -1229,13 +1225,13 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
}
WL_CONN("pval (%d) gval (%d)\n", pval, gval);
- err = wl_dev_intvar_set(dev, "wsec", pval | gval);
+ err = brcmf_dev_intvar_set(dev, "wsec", pval | gval);
if (unlikely(err)) {
WL_ERR("error (%d)\n", err);
return err;
}
- sec = wl_read_prof(wl, WL_PROF_SEC);
+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
sec->cipher_group = sme->crypto.cipher_group;
@@ -1243,15 +1239,15 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
}
static s32
-wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
{
- struct wl_priv *wl = ndev_to_wl(dev);
- struct wl_security *sec;
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
if (sme->crypto.n_akm_suites) {
- err = wl_dev_intvar_get(dev, "wpa_auth", &val);
+ err = brcmf_dev_intvar_get(dev, "wpa_auth", &val);
if (unlikely(err)) {
WL_ERR("could not get wpa_auth (%d)\n", err);
return err;
@@ -1285,31 +1281,31 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
}
WL_CONN("setting wpa_auth to %d\n", val);
- err = wl_dev_intvar_set(dev, "wpa_auth", val);
+ err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
if (unlikely(err)) {
WL_ERR("could not set wpa_auth (%d)\n", err);
return err;
}
}
- sec = wl_read_prof(wl, WL_PROF_SEC);
+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
sec->wpa_auth = sme->crypto.akm_suites[0];
return err;
}
static s32
-wl_set_set_sharedkey(struct net_device *dev,
+brcmf_set_set_sharedkey(struct net_device *dev,
struct cfg80211_connect_params *sme)
{
- struct wl_priv *wl = ndev_to_wl(dev);
- struct wl_security *sec;
- struct wl_wsec_key key;
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ 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 = wl_read_prof(wl, WL_PROF_SEC);
+ 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 (!
@@ -1325,7 +1321,7 @@ wl_set_set_sharedkey(struct net_device *dev,
return -EINVAL;
}
memcpy(key.data, sme->key, key.len);
- key.flags = WL_PRIMARY_KEY;
+ key.flags = BRCMF_PRIMARY_KEY;
switch (sec->cipher_pairwise) {
case WLAN_CIPHER_SUITE_WEP40:
key.algo = CRYPTO_ALGO_WEP1;
@@ -1343,7 +1339,7 @@ wl_set_set_sharedkey(struct net_device *dev,
key.len, key.index, key.algo);
WL_CONN("key \"%s\"\n", key.data);
swap_key_from_BE(&key);
- err = wl_dev_ioctl(dev, WLC_SET_KEY, &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);
@@ -1352,7 +1348,7 @@ wl_set_set_sharedkey(struct net_device *dev,
if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
WL_CONN("set auth_type to shared key\n");
val = 1; /* shared key */
- err = wl_dev_intvar_set(dev, "auth", val);
+ err = brcmf_dev_intvar_set(dev, "auth", val);
if (unlikely(err)) {
WL_ERR("set auth failed (%d)\n", err);
return err;
@@ -1364,12 +1360,12 @@ wl_set_set_sharedkey(struct net_device *dev,
}
static s32
-wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct ieee80211_channel *chan = sme->channel;
- struct wl_join_params join_params;
+ struct brcmf_join_params join_params;
size_t join_params_size;
s32 err = 0;
@@ -1382,37 +1378,49 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return -EOPNOTSUPP;
}
+ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+
if (chan) {
- wl->channel =
+ cfg_priv->channel =
ieee80211_frequency_to_channel(chan->center_freq);
WL_CONN("channel (%d), center_req (%d)\n",
- wl->channel, chan->center_freq);
+ cfg_priv->channel, chan->center_freq);
} else
- wl->channel = 0;
+ cfg_priv->channel = 0;
WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
- err = wl_set_wpa_version(dev, sme);
- if (unlikely(err))
- return err;
+ err = brcmf_set_wpa_version(dev, sme);
+ if (err) {
+ WL_ERR("wl_set_wpa_version failed (%d)\n", err);
+ goto done;
+ }
- err = wl_set_auth_type(dev, sme);
- if (unlikely(err))
- return err;
+ err = brcmf_set_auth_type(dev, sme);
+ if (err) {
+ WL_ERR("wl_set_auth_type failed (%d)\n", err);
+ goto done;
+ }
- err = wl_set_set_cipher(dev, sme);
- if (unlikely(err))
- return err;
+ err = brcmf_set_set_cipher(dev, sme);
+ if (err) {
+ WL_ERR("wl_set_set_cipher failed (%d)\n", err);
+ goto done;
+ }
- err = wl_set_key_mgmt(dev, sme);
- if (unlikely(err))
- return err;
+ err = brcmf_set_key_mgmt(dev, sme);
+ if (err) {
+ WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
+ goto done;
+ }
- err = wl_set_set_sharedkey(dev, sme);
- if (unlikely(err))
- return err;
+ err = brcmf_set_set_sharedkey(dev, sme);
+ if (err) {
+ WL_ERR("wl_set_set_sharedkey failed (%d)\n", err);
+ goto done;
+ }
- wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
+ 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
@@ -1423,7 +1431,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
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);
- wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
+ brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
if (sme->bssid)
memcpy(join_params.params.bssid, sme->bssid, ETH_ALEN);
@@ -1435,52 +1443,54 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
join_params.ssid.SSID, join_params.ssid.SSID_len);
}
- wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
- err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
- if (unlikely(err)) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- set_bit(WL_STATUS_CONNECTING, &wl->status);
+ brcmf_ch_to_chanspec(cfg_priv->channel,
+ &join_params, &join_params_size);
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+ &join_params, join_params_size);
+ if (err)
+ WL_ERR("WLC_SET_SSID failed (%d)\n", err);
+done:
+ if (err)
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
WL_TRACE("Exit\n");
return err;
}
static s32
-wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
u16 reason_code)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- scb_val_t scbval;
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct brcmf_scb_val scbval;
s32 err = 0;
WL_TRACE("Enter. Reason code = %d\n", reason_code);
CHECK_SYS_UP();
- clear_bit(WL_STATUS_CONNECTED, &wl->status);
+ clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
scbval.val = reason_code;
- memcpy(&scbval.ea, wl_read_prof(wl, WL_PROF_BSSID), ETH_ALEN);
+ memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
scbval.val = cpu_to_le32(scbval.val);
- err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
- sizeof(scb_val_t));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, &scbval,
+ sizeof(struct brcmf_scb_val));
if (unlikely(err))
WL_ERR("error (%d)\n", err);
- wl->link_up = false;
+ cfg_priv->link_up = false;
WL_TRACE("Exit\n");
return err;
}
static s32
-wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type, s32 dbm)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- struct net_device *ndev = wl_to_ndev(wl);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = cfg_to_ndev(cfg_priv);
u16 txpwrmw;
s32 err = 0;
s32 disable = 0;
@@ -1509,7 +1519,7 @@ wl_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 = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
+ err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_RADIO, &disable, sizeof(disable));
if (unlikely(err))
WL_ERR("WLC_SET_RADIO error (%d)\n", err);
@@ -1517,21 +1527,21 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
txpwrmw = 0xffff;
else
txpwrmw = (u16) dbm;
- err = wl_dev_intvar_set(ndev, "qtxpower",
- (s32) (bcm_mw_to_qdbm(txpwrmw)));
+ err = brcmf_dev_intvar_set(ndev, "qtxpower",
+ (s32) (brcmu_mw_to_qdbm(txpwrmw)));
if (unlikely(err))
WL_ERR("qtxpower error (%d)\n", err);
- wl->conf->tx_power = dbm;
+ cfg_priv->conf->tx_power = dbm;
done:
WL_TRACE("Exit\n");
return err;
}
-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- struct net_device *ndev = wl_to_ndev(wl);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = cfg_to_ndev(cfg_priv);
s32 txpwrdbm;
u8 result;
s32 err = 0;
@@ -1539,14 +1549,14 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
WL_TRACE("Enter\n");
CHECK_SYS_UP();
- err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
+ err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
if (unlikely(err)) {
WL_ERR("error (%d)\n", err);
goto done;
}
result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
- *dbm = (s32) bcm_qdbm_to_mw(result);
+ *dbm = (s32) brcmu_qdbm_to_mw(result);
done:
WL_TRACE("Exit\n");
@@ -1554,7 +1564,7 @@ done:
}
static s32
-wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool unicast, bool multicast)
{
u32 index;
@@ -1565,7 +1575,7 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
WL_CONN("key index (%d)\n", key_idx);
CHECK_SYS_UP();
- err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
if (unlikely(err)) {
WL_ERR("WLC_GET_WSEC error (%d)\n", err);
goto done;
@@ -1576,7 +1586,7 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
/* Just select a new current key */
index = (u32) key_idx;
index = cpu_to_le32(index);
- err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY_PRIMARY, &index,
sizeof(index));
if (unlikely(err))
WL_ERR("error (%d)\n", err);
@@ -1587,10 +1597,10 @@ done:
}
static s32
-wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, const u8 *mac_addr, struct key_params *params)
{
- struct wl_wsec_key key;
+ struct brcmf_wsec_key key;
s32 err = 0;
memset(&key, 0, sizeof(key));
@@ -1604,7 +1614,7 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
if (key.len == 0) {
/* key delete */
swap_key_from_BE(&key);
- err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
if (unlikely(err)) {
WL_ERR("key delete error (%d)\n", err);
return err;
@@ -1663,8 +1673,8 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
}
swap_key_from_BE(&key);
- dhd_wait_pend8021x(dev);
- err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ brcmf_netdev_wait_pend8021x(dev);
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
if (unlikely(err)) {
WL_ERR("WLC_SET_KEY error (%d)\n", err);
return err;
@@ -1674,11 +1684,11 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
}
static s32
-wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
- struct wl_wsec_key key;
+ struct brcmf_wsec_key key;
s32 val;
s32 wsec;
s32 err = 0;
@@ -1690,7 +1700,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
if (mac_addr) {
WL_TRACE("Exit");
- return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
+ return brcmf_add_keyext(wiphy, dev, key_idx, mac_addr, params);
}
memset(&key, 0, sizeof(key));
@@ -1704,7 +1714,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
}
memcpy(key.data, params->key, key.len);
- key.flags = WL_PRIMARY_KEY;
+ key.flags = BRCMF_PRIMARY_KEY;
switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
key.algo = CRYPTO_ALGO_WEP1;
@@ -1737,21 +1747,21 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
/* Set the new key/index */
swap_key_from_BE(&key);
- err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(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);
goto done;
}
val = WEP_ENABLED;
- err = wl_dev_intvar_get(dev, "wsec", &wsec);
+ err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
if (unlikely(err)) {
WL_ERR("get wsec error (%d)\n", err);
goto done;
}
wsec &= ~(WEP_ENABLED);
wsec |= val;
- err = wl_dev_intvar_set(dev, "wsec", wsec);
+ err = brcmf_dev_intvar_set(dev, "wsec", wsec);
if (unlikely(err)) {
WL_ERR("set wsec error (%d)\n", err);
goto done;
@@ -1759,7 +1769,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
val = 1; /* assume shared key. otherwise 0 */
val = cpu_to_le32(val);
- err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
if (unlikely(err))
WL_ERR("WLC_SET_AUTH error (%d)\n", err);
done:
@@ -1768,10 +1778,10 @@ done:
}
static s32
-wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool pairwise, const u8 *mac_addr)
{
- struct wl_wsec_key key;
+ struct brcmf_wsec_key key;
s32 err = 0;
s32 val;
s32 wsec;
@@ -1781,13 +1791,13 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
- key.flags = WL_PRIMARY_KEY;
+ key.flags = BRCMF_PRIMARY_KEY;
key.algo = CRYPTO_ALGO_OFF;
WL_CONN("key index (%d)\n", key_idx);
/* Set the new key/index */
swap_key_from_BE(&key);
- err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
if (unlikely(err)) {
if (err == -EINVAL) {
if (key.index >= DOT11_MAX_DEFAULT_KEYS)
@@ -1802,7 +1812,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
val = 0;
- err = wl_dev_intvar_get(dev, "wsec", &wsec);
+ err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
if (unlikely(err)) {
WL_ERR("get wsec error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
@@ -1811,7 +1821,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
wsec &= ~(WEP_ENABLED);
wsec |= val;
- err = wl_dev_intvar_set(dev, "wsec", wsec);
+ err = brcmf_dev_intvar_set(dev, "wsec", wsec);
if (unlikely(err)) {
WL_ERR("set wsec error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
@@ -1821,7 +1831,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
val = 0; /* assume open key. otherwise 1 */
val = cpu_to_le32(val);
- err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
if (unlikely(err)) {
WL_ERR("WLC_SET_AUTH error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
@@ -1833,14 +1843,14 @@ done:
}
static s32
-wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+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))
{
struct key_params params;
- struct wl_wsec_key key;
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- struct wl_security *sec;
+ struct brcmf_wsec_key key;
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct brcmf_cfg80211_security *sec;
s32 wsec;
s32 err = 0;
@@ -1855,7 +1865,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
memcpy(params.key, key.data, params.key_len);
- err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
if (unlikely(err)) {
WL_ERR("WLC_GET_WSEC error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
@@ -1865,7 +1875,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
wsec = le32_to_cpu(wsec);
switch (wsec) {
case WEP_ENABLED:
- sec = wl_read_prof(wl, WL_PROF_SEC);
+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
params.cipher = WLAN_CIPHER_SUITE_WEP40;
WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
@@ -1895,7 +1905,7 @@ done:
}
static s32
-wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev, u8 key_idx)
{
WL_INFO("Not supported\n");
@@ -1905,15 +1915,15 @@ wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
}
static s32
-wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_info *sinfo)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- scb_val_t scb_val;
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct brcmf_scb_val scb_val;
int rssi;
s32 rate;
s32 err = 0;
- u8 *bssid = wl_read_prof(wl, WL_PROF_BSSID);
+ u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
WL_TRACE("Enter\n");
CHECK_SYS_UP();
@@ -1930,7 +1940,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
}
/* Report the current tx rate */
- err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RATE, &rate, sizeof(rate));
if (err) {
WL_ERR("Could not get rate (%d)\n", err);
} else {
@@ -1940,10 +1950,10 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
WL_CONN("Rate %d Mbps\n", rate / 2);
}
- if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
scb_val.val = 0;
- err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val,
- sizeof(scb_val_t));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RSSI, &scb_val,
+ sizeof(struct brcmf_scb_val));
if (unlikely(err)) {
WL_ERR("Could not get rssi (%d)\n", err);
}
@@ -1959,7 +1969,7 @@ done:
}
static s32
-wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
bool enabled, s32 timeout)
{
s32 pm;
@@ -1972,7 +1982,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
pm = cpu_to_le32(pm);
WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
- err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+ err = brcmf_dev_ioctl(dev, BRCMF_C_SET_PM, &pm, sizeof(pm));
if (unlikely(err)) {
if (err == -ENODEV)
WL_ERR("net_device is not ready yet\n");
@@ -1983,7 +1993,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
return err;
}
-static __used u32 wl_find_msb(u16 bit16)
+static __used u32 brcmf_find_msb(u16 bit16)
{
u32 ret = 0;
@@ -2011,7 +2021,7 @@ static __used u32 wl_find_msb(u16 bit16)
}
static s32
-wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr,
const struct cfg80211_bitrate_mask *mask)
{
@@ -2028,7 +2038,7 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
/* addr param is always NULL. ignore it */
/* Get current rateset */
- err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
+ err = brcmf_dev_ioctl(dev, BRCM_GET_CURR_RATESET, &rateset,
sizeof(rateset));
if (unlikely(err)) {
WL_ERR("could not get current rateset (%d)\n", err);
@@ -2037,9 +2047,9 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
rateset.count = le32_to_cpu(rateset.count);
- legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
+ legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
if (!legacy)
- legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
+ legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
val = wl_g_rates[legacy - 1].bitrate * 100000;
@@ -2057,8 +2067,8 @@ wl_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 = wl_dev_intvar_set(dev, "bg_rate", rate);
- err_a = wl_dev_intvar_set(dev, "a_rate", rate);
+ 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)) {
WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
err = err_bg | err_a;
@@ -2069,10 +2079,9 @@ done:
return err;
}
-static s32 wl_cfg80211_resume(struct wiphy *wiphy)
+static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- struct net_device *ndev = wl_to_ndev(wl);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
/*
* Check for WL_STATUS_READY before any function call which
@@ -2082,23 +2091,21 @@ static s32 wl_cfg80211_resume(struct wiphy *wiphy)
WL_TRACE("Enter\n");
#if defined(CONFIG_PM_SLEEP)
- atomic_set(&dhd_mmc_suspend, false);
+ atomic_set(&brcmf_mmc_suspend, false);
#endif /* defined(CONFIG_PM_SLEEP) */
- if (test_bit(WL_STATUS_READY, &wl->status)) {
- /* Turn on Watchdog timer */
- wl_os_wd_timer(ndev, dhd_watchdog_ms);
- wl_invoke_iscan(wiphy_to_wl(wiphy));
- }
+ if (test_bit(WL_STATUS_READY, &cfg_priv->status))
+ brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
WL_TRACE("Exit\n");
return 0;
}
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
+static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
+ struct cfg80211_wowlan *wow)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
- struct net_device *ndev = wl_to_ndev(wl);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = cfg_to_ndev(cfg_priv);
WL_TRACE("Enter\n");
@@ -2112,11 +2119,12 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
* While going to suspend if associated with AP disassociate
* from AP to save power while system is in suspended state
*/
- if (test_bit(WL_STATUS_CONNECTED, &wl->status) &&
- test_bit(WL_STATUS_READY, &wl->status)) {
+ if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
+ test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
+ test_bit(WL_STATUS_READY, &cfg_priv->status)) {
WL_INFO("Disassociating from AP"
" while entering suspend state\n");
- wl_link_down(wl);
+ brcmf_link_down(cfg_priv);
/*
* Make sure WPA_Supplicant receives all the event
@@ -2124,37 +2132,31 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
* the state fw and WPA_Supplicant state consistent
*/
rtnl_unlock();
- wl_delay(500);
+ brcmf_delay(500);
rtnl_lock();
}
- set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
- if (test_bit(WL_STATUS_READY, &wl->status))
- wl_term_iscan(wl);
+ set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
+ if (test_bit(WL_STATUS_READY, &cfg_priv->status))
+ brcmf_term_iscan(cfg_priv);
- if (wl->scan_request) {
+ if (cfg_priv->scan_request) {
/* Indidate scan abort to cfg80211 layer */
WL_INFO("Terminating scan in progress\n");
- cfg80211_scan_done(wl->scan_request, true);
- wl->scan_request = NULL;
+ cfg80211_scan_done(cfg_priv->scan_request, true);
+ cfg_priv->scan_request = NULL;
}
- clear_bit(WL_STATUS_SCANNING, &wl->status);
- clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
- clear_bit(WL_STATUS_CONNECTING, &wl->status);
- clear_bit(WL_STATUS_CONNECTED, &wl->status);
-
- /* Inform SDIO stack not to switch off power to the chip */
- sdioh_sdio_set_host_pm_flags(MMC_PM_KEEP_POWER);
+ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
+ clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
/* Turn off watchdog timer */
- if (test_bit(WL_STATUS_READY, &wl->status)) {
- WL_INFO("Terminate watchdog timer and enable MPC\n");
- wl_set_mpc(ndev, 1);
- wl_os_wd_timer(ndev, 0);
+ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+ WL_INFO("Enable MPC\n");
+ brcmf_set_mpc(ndev, 1);
}
#if defined(CONFIG_PM_SLEEP)
- atomic_set(&dhd_mmc_suspend, true);
+ atomic_set(&brcmf_mmc_suspend, true);
#endif /* defined(CONFIG_PM_SLEEP) */
WL_TRACE("Exit\n");
@@ -2163,8 +2165,8 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
}
static __used s32
-wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
- s32 err)
+brcmf_update_pmklist(struct net_device *dev,
+ struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
{
int i, j;
@@ -2177,55 +2179,51 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
}
if (likely(!err))
- wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
+ brcmf_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
sizeof(*pmk_list));
return err;
}
static s32
-wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_pmksa *pmksa)
+brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ struct _pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
s32 err = 0;
int i;
WL_TRACE("Enter\n");
CHECK_SYS_UP();
- for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
- if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
- ETH_ALEN))
+ for (i = 0; i < pmkids->npmkid; i++)
+ if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
break;
if (i < WL_NUM_PMKIDS_MAX) {
- memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
- ETH_ALEN);
- memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
- WLAN_PMKID_LEN);
- if (i == wl->pmk_list->pmkids.npmkid)
- wl->pmk_list->pmkids.npmkid++;
+ 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++;
} else
err = -EINVAL;
WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
- &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID);
+ pmkids->pmkid[pmkids->npmkid].BSSID);
for (i = 0; i < WLAN_PMKID_LEN; i++)
- WL_CONN("%02x\n",
- wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
- PMKID[i]);
+ WL_CONN("%02x\n", pmkids->pmkid[pmkids->npmkid].PMKID[i]);
- err = wl_update_pmklist(dev, wl->pmk_list, err);
+ err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
}
static s32
-wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_pmksa *pmksa)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct _pmkid_list pmkid;
s32 err = 0;
int i;
@@ -2240,28 +2238,29 @@ wl_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 < wl->pmk_list->pmkids.npmkid; i++)
+ for (i = 0; i < cfg_priv->pmk_list->pmkids.npmkid; i++)
if (!memcmp
- (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
+ (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
ETH_ALEN))
break;
- if ((wl->pmk_list->pmkids.npmkid > 0)
- && (i < wl->pmk_list->pmkids.npmkid)) {
- memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
- for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
- memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
- &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
+ if ((cfg_priv->pmk_list->pmkids.npmkid > 0)
+ && (i < cfg_priv->pmk_list->pmkids.npmkid)) {
+ memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
+ sizeof(pmkid_t));
+ for (; i < (cfg_priv->pmk_list->pmkids.npmkid - 1); i++) {
+ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
+ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
ETH_ALEN);
- memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
- &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
+ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
+ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
WLAN_PMKID_LEN);
}
- wl->pmk_list->pmkids.npmkid--;
+ cfg_priv->pmk_list->pmkids.npmkid--;
} else
err = -EINVAL;
- err = wl_update_pmklist(dev, wl->pmk_list, err);
+ err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
@@ -2269,16 +2268,16 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
}
static s32
-wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
{
- struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
s32 err = 0;
WL_TRACE("Enter\n");
CHECK_SYS_UP();
- memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
- err = wl_update_pmklist(dev, wl->pmk_list, err);
+ memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
+ err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
@@ -2286,31 +2285,31 @@ wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
}
static struct cfg80211_ops wl_cfg80211_ops = {
- .change_virtual_intf = wl_cfg80211_change_iface,
- .scan = wl_cfg80211_scan,
- .set_wiphy_params = wl_cfg80211_set_wiphy_params,
- .join_ibss = wl_cfg80211_join_ibss,
- .leave_ibss = wl_cfg80211_leave_ibss,
- .get_station = wl_cfg80211_get_station,
- .set_tx_power = wl_cfg80211_set_tx_power,
- .get_tx_power = wl_cfg80211_get_tx_power,
- .add_key = wl_cfg80211_add_key,
- .del_key = wl_cfg80211_del_key,
- .get_key = wl_cfg80211_get_key,
- .set_default_key = wl_cfg80211_config_default_key,
- .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
- .set_power_mgmt = wl_cfg80211_set_power_mgmt,
- .set_bitrate_mask = wl_cfg80211_set_bitrate_mask,
- .connect = wl_cfg80211_connect,
- .disconnect = wl_cfg80211_disconnect,
- .suspend = wl_cfg80211_suspend,
- .resume = wl_cfg80211_resume,
- .set_pmksa = wl_cfg80211_set_pmksa,
- .del_pmksa = wl_cfg80211_del_pmksa,
- .flush_pmksa = wl_cfg80211_flush_pmksa
+ .change_virtual_intf = brcmf_cfg80211_change_iface,
+ .scan = brcmf_cfg80211_scan,
+ .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
+ .join_ibss = brcmf_cfg80211_join_ibss,
+ .leave_ibss = brcmf_cfg80211_leave_ibss,
+ .get_station = brcmf_cfg80211_get_station,
+ .set_tx_power = brcmf_cfg80211_set_tx_power,
+ .get_tx_power = brcmf_cfg80211_get_tx_power,
+ .add_key = brcmf_cfg80211_add_key,
+ .del_key = brcmf_cfg80211_del_key,
+ .get_key = brcmf_cfg80211_get_key,
+ .set_default_key = brcmf_cfg80211_config_default_key,
+ .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
+ .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
+ .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
+ .connect = brcmf_cfg80211_connect,
+ .disconnect = brcmf_cfg80211_disconnect,
+ .suspend = brcmf_cfg80211_suspend,
+ .resume = brcmf_cfg80211_resume,
+ .set_pmksa = brcmf_cfg80211_set_pmksa,
+ .del_pmksa = brcmf_cfg80211_del_pmksa,
+ .flush_pmksa = brcmf_cfg80211_flush_pmksa
};
-static s32 wl_mode_to_nl80211_iftype(s32 mode)
+static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
{
s32 err = 0;
@@ -2326,7 +2325,7 @@ static s32 wl_mode_to_nl80211_iftype(s32 mode)
return err;
}
-static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
+static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
struct device *dev)
{
struct wireless_dev *wdev;
@@ -2338,7 +2337,8 @@ static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
return ERR_PTR(-ENOMEM);
}
wdev->wiphy =
- wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv) + sizeof_iface);
+ wiphy_new(&wl_cfg80211_ops,
+ sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
if (unlikely(!wdev->wiphy)) {
WL_ERR("Couldn not allocate wiphy device\n");
err = -ENOMEM;
@@ -2384,9 +2384,9 @@ wiphy_new_out:
return ERR_PTR(err);
}
-static void wl_free_wdev(struct wl_priv *wl)
+static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wireless_dev *wdev = wl_to_wdev(wl);
+ struct wireless_dev *wdev = cfg_to_wdev(cfg_priv);
if (unlikely(!wdev)) {
WL_ERR("wdev is invalid\n");
@@ -2395,18 +2395,18 @@ static void wl_free_wdev(struct wl_priv *wl)
wiphy_unregister(wdev->wiphy);
wiphy_free(wdev->wiphy);
kfree(wdev);
- wl_to_wdev(wl) = NULL;
+ cfg_to_wdev(cfg_priv) = NULL;
}
-static s32 wl_inform_bss(struct wl_priv *wl)
+static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wl_scan_results *bss_list;
- struct wl_bss_info *bi = NULL; /* must be initialized */
+ struct brcmf_scan_results *bss_list;
+ struct brcmf_bss_info *bi = NULL; /* must be initialized */
s32 err = 0;
int i;
- bss_list = wl->bss_list;
- if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) {
+ 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;
@@ -2414,7 +2414,7 @@ static s32 wl_inform_bss(struct wl_priv *wl)
WL_SCAN("scanned AP count (%d)\n", bss_list->count);
bi = next_bss(bss_list, bi);
for_each_bss(bss_list, bi, i) {
- err = wl_inform_single_bss(wl, bi);
+ err = brcmf_inform_single_bss(cfg_priv, bi);
if (unlikely(err))
break;
}
@@ -2422,9 +2422,10 @@ static s32 wl_inform_bss(struct wl_priv *wl)
}
-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
+static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
+ struct brcmf_bss_info *bi)